boot/arm-trusted-firmware: add -no-pie to LDFLAGS
Arm Trusted Firmware (TF-A) v2.11 fails to build in some situations
with the error message:
ld: build/qemu/release/bl1/bl1.elf: error: PHDR segment not covered by LOAD segment
This error can be reproduced with the commands:
make qemu_aarch64_ebbr_defconfig
utils/config --set-str BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_VERSION_VALUE v2.11
make olddefconfig
make
This issue was reported in [1].
This error is coming from a check that was made more strict since
binutils ld 2.34. This error message is normally related to dynamic
linker, so it should normally not apply to a package like TF-A.
When BR2_SHARED_LIBS=y (shared libraries only) and BR2_PIC_PIE=y
(Build code with PIC/PIE), the Buildroot toolchain-wrapper will try
to enable position-independent code/executables. See [2]. This
configuration is a common default.
Arm Trusted Firmware (TF-A) build system, on its side, tries to detect
if the toolchain enables PIE automatically. It does so by checking if
--enable-default-pie is in the output of "$(CC) -v". If found, the TF-A
build system tries to disable PIE globally (it can be explicitly
enabled again with the ENABLE_PIE=1 build variable, in some specific
configurations). This detection mechanism is not working with the
Buildroot toolchain wrapper which is enabling PIE silently. See [3].
Commit 1061ed6c "boot/arm-trusted-firmware: add -fno-PIE to CFLAGS"
added the option -fno-PIE in CFLAGS for that reason. See [4].
TF-A >= v2.11 now needs the same treatment for LDFLAGS. This is
because TF-A switched the default linker from "ld" to "gcc", in
upstream commit [5]. This change makes the Buildroot toolchain wrapper
to enable PIE at link, without passing the "--no-dynamic-linker" option
that would normally avoids this ld error.
Also, even if there is no defconfigs using the
BR2_TARGET_ARM_TRUSTED_FIRMWARE_LATEST_VERSION config directive, it is
worth mentioning that the Buildroot TF-A "latest version" was updated
to v2.11 in commit 9c50759cd "boot/arm-trusted-firmware: bump to
v2.11". See [6]. This latest version is the default choice. So
Buildroot is subject to generate this build failure. This can be
reproduced with the commands:
cat <<EOF >.config
BR2_aarch64=y
BR2_TARGET_ARM_TRUSTED_FIRMWARE=y
BR2_TARGET_ARM_TRUSTED_FIRMWARE_PLATFORM="qemu"
BR2_TOOLCHAIN_EXTERNAL=y
EOF
make olddefconfig
make arm-trusted-firmware
This commit fixes the issue by adding the option "-no-pie" in LDFLAGS.
This will prevent the Buildroot toolchain wrapper to enable PIE, for
versions using "gcc" as a linker. This change should also remain
compatible with older TF-A < 2.11 using "ld" as a linker, since
"-no-pie" is also a valid ld option.
Fixes:
ld: build/qemu/release/bl1/bl1.elf: error: PHDR segment not covered by LOAD segment
[1] https://github.com/TrustedFirmware-A/trusted-firmware-a/issues/26
[2] https://gitlab.com/buildroot.org/buildroot/-/blob/2024.08-rc3/toolchain/toolchain-wrapper.c?ref_type=tags#L403
[3] https://git.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a.git/+/refs/tags/v2.11.0/Makefile#711
[4] https://gitlab.com/buildroot.org/buildroot/-/commit/1061ed6c6273e90618b05ddc0cb66be17364da33
[5] https://git.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a.git/+/2f1c5e7eb1775b252fa4998e10093b8ac34ca699%5E%21/
[6] https://gitlab.com/buildroot.org/buildroot/-/commit/9c50759cd1677e1739078239a1e86fb1d62e33e8
Reported-by: Vincent Stehlé <vincent.stehle@arm.com>
Tested-by: Vincent Stehlé <vincent.stehle@arm.com>
Signed-off-by: Julien Olivain <ju.o@free.fr>
Signed-off-by: Yann E. MORIN <yann.morin.1998@free.fr>
diff --git a/boot/arm-trusted-firmware/arm-trusted-firmware.mk b/boot/arm-trusted-firmware/arm-trusted-firmware.mk
index a3a44fe..172a930 100644
--- a/boot/arm-trusted-firmware/arm-trusted-firmware.mk
+++ b/boot/arm-trusted-firmware/arm-trusted-firmware.mk
@@ -77,11 +77,13 @@
ifeq ($(BR2_PIC_PIE),y)
ARM_TRUSTED_FIRMWARE_CFLAGS += -fno-PIE
+ARM_TRUSTED_FIRMWARE_LDFLAGS += -no-pie
endif
ARM_TRUSTED_FIRMWARE_MAKE_ENV += \
$(TARGET_MAKE_ENV) \
- CFLAGS="$(ARM_TRUSTED_FIRMWARE_CFLAGS)"
+ CFLAGS="$(ARM_TRUSTED_FIRMWARE_CFLAGS)" \
+ LDFLAGS="$(ARM_TRUSTED_FIRMWARE_LDFLAGS)"
ifeq ($(BR2_ARM_CPU_ARMV7A),y)
ARM_TRUSTED_FIRMWARE_MAKE_OPTS += ARM_ARCH_MAJOR=7