Open
Description
Environment
Category | Detail |
---|---|
OS | Ubuntu 22.04 |
Architecture | x86_64 host |
Clang Versions | 11 – 20 (tested: 11, 13, 15, 17, 19, 20.1.6) |
Target triple | powerpc-linux-gnu |
Clang build | Release |
Summary
- Clang incorrectly links host's
/usr/lib32/Scrt1.o
when compiling for--target=powerpc-linux-gnu
onx86_64
Ubuntu systems, despite the correct cross toolchain being installed under/usr/powerpc-linux-gnu
.
This causes linker errors due to a mismatched ELF format. This issue does not occur for--target=powerpc64-linux-gnu
under identical environments (with dependenciesgcc-powerpc64-linux-gnu
,g++-powerpc64-linux-gnu
,binutils-powerpc64-linux-gnu
andlibc6-dev-ppc64-cross
installed withapt
as well).
Reproduce
- File:
hello.c
#include <stdio.h>
int main() {
printf("Hello PowerPC!\\n");
return 0;
}
- Install dependency
root@f806c162d501:/test# apt-get install gcc-powerpc-linux-gnu g++-powerpc-linux-gnu binutils-powerpc-linux-gnu libc6-dev-powerpc-cross
- Broken command
root@f806c162d501:/test# clang-20 --target=powerpc-linux-gnu -o hello-ppc hello.c
- Output: Failed
/usr/bin/powerpc-linux-gnu-ld: /usr/lib/gcc-cross/powerpc-linux-gnu/11/../../../../lib32/Scrt1.o: relocations in generic ELF (EM: 3)
/usr/bin/powerpc-linux-gnu-ld: /usr/lib/gcc-cross/powerpc-linux-gnu/11/../../../../lib32/Scrt1.o: relocations in generic ELF (EM: 3)
/usr/bin/powerpc-linux-gnu-ld: /usr/lib/gcc-cross/powerpc-linux-gnu/11/../../../../lib32/Scrt1.o: error adding symbols: file in wrong format
- Verbose Output
root@f806c162d501:/test# clang-20 -v --target=powerpc-linux-gnu -o hello-ppc hello.c
clang version 20.1.7
Target: powerpc-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/local/bin
Found candidate GCC installation: /usr/lib/gcc-cross/powerpc-linux-gnu/11
Found candidate GCC installation: /usr/lib/gcc-cross/powerpc64-linux-gnu/11
Selected GCC installation: /usr/lib/gcc-cross/powerpc-linux-gnu/11
Candidate multilib: .;@m32
Selected multilib: .;@m32
"/usr/local/bin/clang-20" -cc1 -triple powerpc-unknown-linux-gnu -emit-obj -dumpdir hello-ppc- -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name hello.c -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu ppc -mfloat-abi hard -debugger-tuning=gdb -fdebug-compilation-dir=/test -v -fcoverage-compilation-dir=/test -resource-dir /usr/local/lib/clang/20 -internal-isystem /usr/local/lib/clang/20/include/ppc_wrappers -internal-isystem /usr/local/lib/clang/20/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc-cross/powerpc-linux-gnu/11/../../../../powerpc-linux-gnu/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -ferror-limit 19 -fno-signed-char -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/hello-ac8ddb.o -x c hello.c
clang -cc1 version 20.1.7 based upon LLVM 20.1.7 default target x86_64-unknown-linux-gnu
ignoring nonexistent directory "/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/local/lib/clang/20/include/ppc_wrappers
/usr/local/lib/clang/20/include
/usr/local/include
/usr/lib/gcc-cross/powerpc-linux-gnu/11/../../../../powerpc-linux-gnu/include
/usr/include
End of search list.
"/usr/bin/powerpc-linux-gnu-ld" -z relro --hash-style=gnu --eh-frame-hdr -m elf32ppclinux -pie -dynamic-linker /lib/ld.so.1 -o hello-ppc /usr/lib/gcc-cross/powerpc-linux-gnu/11/../../../../lib32/Scrt1.o /usr/lib/gcc-cross/powerpc-linux-gnu/11/../../../../lib32/crti.o /usr/lib/gcc-cross/powerpc-linux-gnu/11/crtbeginS.o -L/usr/lib/gcc-cross/powerpc-linux-gnu/11 -L/usr/lib/gcc-cross/powerpc-linux-gnu/11/../../../../lib32 -L/lib/powerpc-linux-gnu -L/lib/../lib32 -L/usr/lib/powerpc-linux-gnu -L/usr/lib/../lib32 -L/usr/lib/gcc-cross/powerpc-linux-gnu/11/../../../../powerpc-linux-gnu/lib -L/lib -L/usr/lib /tmp/hello-ac8ddb.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc-cross/powerpc-linux-gnu/11/crtendS.o /usr/lib/gcc-cross/powerpc-linux-gnu/11/../../../../lib32/crtn.o
/usr/bin/powerpc-linux-gnu-ld: /usr/lib/gcc-cross/powerpc-linux-gnu/11/../../../../**lib32/Scrt1.o**: relocations in generic ELF (EM: 3)
/usr/bin/powerpc-linux-gnu-ld: /usr/lib/gcc-cross/powerpc-linux-gnu/11/../../../../**lib32/Scrt1.o**: relocations in generic ELF (EM: 3)
/usr/bin/powerpc-linux-gnu-ld: /usr/lib/gcc-cross/powerpc-linux-gnu/11/../../../../**lib32/Scrt1.o**: error adding symbols: file in wrong format
clang-20: error: linker command failed with exit code 1 (use -v to see invocation)
Expected Behavior
- Clang should use the correct startup objects from:
/usr/powerpc-linux-gnu/lib/Scrt1.o
- and not pick up unrelated host files from:
/usr/lib32/Scrt1.o
Observation
- Despite
-target=powerpc-linux-gnu
, Clang chooses/usr/lib32/Scrt1.o
from the host. - Resulting in a linker error due to incompatible ELF class.
- This behavior is not observed when targeting:
powerpc64-linux-gnu
aarch64-linux-gnu
arm-linux-gnueabi
- etc.
Workarounds
- Specify targer specific
Scrt1.o
file
root@f806c162d501:/test# clang-20 -v --target=powerpc-linux-gnu -nostdlib /usr/powerpc-linux-gnu/lib/crt1.o -L/usr/powerpc-linux-gnu/lib -lc /usr/powerpc-linux-gnu/lib/crtn.o -o hello-ppc hello.c
- Output (Verbose): Success
root@f806c162d501:/test# clang-20 -v --target=powerpc-linux-gnu -nostdlib /usr/powerpc-linux-gnu/lib/crt1.o -L/usr/powerpc-linux-gnu/lib -lc /usr/powerpc-linux-gnu/lib/crtn.o -o hello-ppc hello.c
clang version 20.1.7
Target: powerpc-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/local/bin
Found candidate GCC installation: /usr/lib/gcc-cross/powerpc-linux-gnu/11
Found candidate GCC installation: /usr/lib/gcc-cross/powerpc64-linux-gnu/11
Selected GCC installation: /usr/lib/gcc-cross/powerpc-linux-gnu/11
Candidate multilib: .;@m32
Selected multilib: .;@m32
"/usr/local/bin/clang-20" -cc1 -triple powerpc-unknown-linux-gnu -emit-obj -dumpdir hello-ppc- -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name hello.c -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu ppc -mfloat-abi hard -debugger-tuning=gdb -fdebug-compilation-dir=/test -v -fcoverage-compilation-dir=/test -resource-dir /usr/local/lib/clang/20 -internal-isystem /usr/local/lib/clang/20/include/ppc_wrappers -internal-isystem /usr/local/lib/clang/20/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc-cross/powerpc-linux-gnu/11/../../../../powerpc-linux-gnu/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -ferror-limit 19 -fno-signed-char -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/hello-d0a071.o -x c hello.c
clang -cc1 version 20.1.7 based upon LLVM 20.1.7 default target x86_64-unknown-linux-gnu
ignoring nonexistent directory "/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/local/lib/clang/20/include/ppc_wrappers
/usr/local/lib/clang/20/include
/usr/local/include
/usr/lib/gcc-cross/powerpc-linux-gnu/11/../../../../powerpc-linux-gnu/include
/usr/include
End of search list.
"/usr/bin/powerpc-linux-gnu-ld" -z relro --hash-style=gnu --eh-frame-hdr -m elf32ppclinux -pie -dynamic-linker /lib/ld.so.1 -o hello-ppc -L/usr/powerpc-linux-gnu/lib -L/usr/lib/gcc-cross/powerpc-linux-gnu/11 -L/usr/lib/gcc-cross/powerpc-linux-gnu/11/../../../../lib32 -L/lib/powerpc-linux-gnu -L/lib/../lib32 -L/usr/lib/powerpc-linux-gnu -L/usr/lib/../lib32 -L/usr/lib/gcc-cross/powerpc-linux-gnu/11/../../../../powerpc-linux-gnu/lib -L/lib -L/usr/lib /usr/powerpc-linux-gnu/lib/crt1.o -lc /usr/powerpc-linux-gnu/lib/crtn.o /tmp/hello-d0a071.o
Fix Advice
Clang should:
- Prefer
$sysroot/$triple/lib
and similar over host/usr/lib32
if-target
is specified. - Match the behavior of GCC and avoid falling back to host paths unless explicitly instructed.