llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
26.83k stars 11.01k forks source link

Build issue for 32-bit configuration on OS SLES 15 #43085

Open llvmbot opened 4 years ago

llvmbot commented 4 years ago
Bugzilla Link 43740
Version unspecified
OS Linux
Attachments Test case File
Reporter LLVM Bugzilla Contributor
CC @MaskRay,@smithp35

Extended Description

Compiling small test case with clang for 32-bit configuration give linker issue. lld unable to recognize 32-bit object file, while system ld is able to recognize and link it- (Test file is attached)

clang++ -m32 test_m32.cpp -fuse-ld=lld ld.lld: error: /usr/lib64/gcc/x86_64-suse-linux/7/32/crt1.o is incompatible with elf_i386 ld.lld: error: /usr/lib64/gcc/x86_64-suse-linux/7/32/crti.o is incompatible with elf_i386 ld.lld: error: /usr/lib64/gcc/x86_64-suse-linux/7/32/crtbegin.o is incompatible with elf_i386 ld.lld: error: /tmp/test_m32-4d557c.o is incompatible with elf_i386 ld.lld: error: /usr/lib64/gcc/x86_64-suse-linux/7/32/libstdc++.so is incompatible with elf_i386 ld.lld: error: /lib/libgcc_s.so.1 is incompatible with elf_i386 ld.lld: error: /lib/libgcc_s.so.1 is incompatible with elf_i386 ld.lld: error: /usr/lib64/gcc/x86_64-suse-linux/7/32/crtend.o is incompatible with elf_i386 ld.lld: error: /usr/lib64/gcc/x86_64-suse-linux/7/32/crtn.o is incompatible with elf_i386 clang-8: error: linker command failed with exit code 1 (use -v to see invocation)

clang++ -m32 test_m32.cpp -fuse-ld=ld /usr/lib64/gcc/x86_64-suse-linux/7/../../../../x86_64-suse-linux/bin/ld: skipping incompatible /usr/lib64/gcc/x86_64-suse-linux/7/../../../libm.so when searching for -lm /usr/lib64/gcc/x86_64-suse-linux/7/../../../../x86_64-suse-linux/bin/ld: skipping incompatible /usr/lib64/gcc/x86_64-suse-linux/7/../../../libc.so when searching for -lc

MaskRay commented 4 years ago

For two reasons I think "skipping incompatible libraries" is probably not worthwhile in lld.

1) This usually indicates real library path configuration problems that should not be ignored. 2) If a .so is actually a linker script that includes other libraries, but without an OUTPUT_FORMAT directive, GNU ld and gold's behavior of skipping incompatible libraries may still not work if the linker script contents are different.

% cat /usr/lib/x86_64-linux-gnu/libncurses.so INPUT(libncurses.so.6 -ltinfo) % cat /usr/lib/i386-linux-gnu/libncurses.so INPUT(libncurses.so.6 -ltinfo)

Aside: GNU ld and gold implement a pair of options --warn-mismatch (default) and --no-warn-mismatch.

On Debian, the scripts have the same content. If one inputs libncurses.so.6.1 while the other inputs libncurses.so.6.2, then the "skipping incompatible libraries" scheme will still not work.

For this particular report, if clang has such problems, we should probably fix clang/lib/Driver/ToolChains instead.

llvmbot commented 4 years ago

1) 32bit multilib packages needs to be installed on SLES-

gcc7-c++-32bit/gcc8-c++-32bit and glibc-32bit

2) Need to specify library path to 32 bit while linking-

Output of test case after above steps: $ ./bin/clang++ -m32 ./test_m32.cpp -L/usr/lib $ ./a.out 2

Exact reason why compiler is not including 32 bit path even with -m32 option for SLES needs to be fix in the compiler.

smithp35 commented 4 years ago

Apologies I don't have any contact with the people that work in the area. It is often the case that code that deals with the layout for a specific Linux distribution is contributed by someone from that distribution that knows what directory layout to search through.

One possible approach is to approach the toolchain maintainer for SUSE/SLES, this is assuming that you are using clang from the distribution, they may be interested in fixing this in the clang driver. It would be helpful to add -v to clang as this will give the search path that clang is using, along with the clang version and SUSE version.

I think that LLD could be improved here to follow the binutils behaviour, although I don't know when we'll have someone with time to look at it. I think it wouldn't be too difficult to have LLD ignore a linker script if OUTPUT_FORMAT is the first command (so the script couldn't have changed anything) and it is not compatible with the emulation. I think that this will fix most of the problems but won't catch instances where OUTPUT_FORMAT isn't the first command.

llvmbot commented 4 years ago

Hi Peter, Thanks for reply. So is there anybody from clang driver team looking at this bug?

smithp35 commented 4 years ago

This looks closely related to llvm/llvm-project#43083

The emulation provided to LLD is elf_i386, the chances are the files such as /usr/lib64/gcc/x86_64-suse-linux/7/32/crt1.o are indeed i386 objects. The problem is likely caused by -lc picking up an x86_64 libc from a search path that includes 64-bit directories (see ld /usr/lib64/gcc/x86_64-suse-linux/7/../../../../x86_64-suse-linux/bin/ld: skipping incompatible /usr/lib64/gcc/x86_64-suse-linux/7/../../../libc.so when searching for -lc )

This libc.so is likely a linker script with a command like: OUTPUT_FORMAT(elf64-x86-64) which is changing the machine type to x86_64.

So the root cause of the problem is the clang driver adding a directory to the library path containing 64-bit libc.so. LLD should at least give a better error message, and at best should be helpful enough to skip these directories.

llvmbot commented 4 years ago

This issue is specific to OS SUSE/SLES, On Ubuntu it is working fine.