Skip to content

[clang][PowerPC] Clang links against host /usr/lib32 when targeting powerpc-linux-gnu instead of /usr/powerpc-linux-gnu/lib #146837

Open
@venkyqz

Description

@venkyqz

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 on x86_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 dependencies gcc-powerpc64-linux-gnu, g++-powerpc64-linux-gnu, binutils-powerpc64-linux-gnu and libc6-dev-ppc64-cross installed with apt 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    clang:driver'clang' and 'clang++' user-facing binaries. Not 'clang-cl'platform:linux

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions