Given these files: x.c: int main() { return 0; } x.map: { local: *; }; an executable linked with: clang x.c -o x -fuse-ld=lld -Wl,--version-script=x.map does not run with an error: ./x: symbol lookup error: ./x: undefined symbol: and "LD_DEBUG=symbols ./x" reveals that ld is looking for a symbol with zero-length name. (Such linker scripts are useful when an executable needs to dlopen a shared object without exposing symbols that are supposed to be details of implementation.) This was introduced in https://reviews.llvm.org/D46103. LLD before r330966 and other linkers produce an executable that runs with code 0, therefore this is a regression in LLD 7.
LLD >= r330966 does something wrong with the undefined versioned symbol __libc_start_main@GLIBC_2.2.5. Good "readelf -s" output: … Relocation section '.rela.plt' at offset 0x420 contains 2 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000202028 000500000007 R_X86_64_JUMP_SLO 00000000002011c0 __libc_start_main@GLIBC_2.2.5 + 0 … Bad "readelf -s" output: … Relocation section '.rela.plt' at offset 0x3b8 contains 2 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000202028 000000000007 R_X86_64_JUMP_SLO 0 … Good "readelf -V" output: Version symbols section '.gnu.version' contains 6 entries: Addr: 0000000000200320 Offset: 0x000320 Link: 3 (.dynsym) 000: 0 (*local*) 0 (*local*) 0 (*local*) 0 (*local*) 004: 0 (*local*) 2 (GLIBC_2.2.5) Version needs section '.gnu.version_r' contains 1 entries: Addr: 0x000000000020032c Offset: 0x00032c Link: 7 (.dynstr) 000000: Version: 1 File: libc.so.6 Cnt: 1 0x0010: Name: GLIBC_2.2.5 Flags: none Version: 2 Bad "readelf -V" output: No version information found in this file.
It works for me. What is your operating system? $ cat x.c int main() { return 0; } $ cat x.map { local: *; }; $ bin/clang x.c -o x -fuse-ld=lld -Wl,--version-script=x.map $ ./x $
I'm testing on Ubuntu 16, but this should be reproducible on any system with glibc. Is the lld used by clang recent enough? If not, put the directory with ld.lld in front of the PATH. Otherwise, what is the output of "readelf -s ./x" and "readelf -V ./x"? $ clang -v clang version 8.0.0 (trunk 343356) Target: x86_64-unknown-linux-gnu … $ clang x.c -o x -fuse-ld=lld -Wl,--version LLD 8.0.0 (trunk 343356) (compatible with GNU linkers)
Yes, I tried lld 7 that I built from the released source code. lld has a feature to gather input files to pack it to a single tar archive. Can you add `--reproduce=repro.tar` to your command line, compress a generated tar file and then share it with me?
Here is repro.tar.gz: https://s3.amazonaws.com/orivej/bugs/llvm/39104/repro.tar.gz
Created attachment 20941 [details] reproducer I have made a more self-contained reproducer that does not depend on glibc. This: tar xf repro2.tar.gz cd repro2 make test should run ./x without error, but ./x fails with the undefined symbol error. This succeeds: make clean make test ld=ld
Thanks. I tried to fix it but looks like the easiest way of fixing it is to revert that patch. Since many patches have been submitted that patch, it is not very easy to do that, but I'll do.
I have proposed a revert at https://reviews.llvm.org/D52698 (tested with check-lld). Could you help with a test case? I don't understand the issue yet. (Is it limited to version scripts, or can it happen without version scripts? How to reduce crt1.o in repro2 and build it from source?)
(In reply to Orivej Desh from comment #8) > I have proposed a revert at https://reviews.llvm.org/D52698 (tested with > check-lld). > > Could you help with a test case? I was able to use the following code to build my version of crt1.o for your test case: .global __libc_csu_init .global __libc_csu_fini .global __libc_start_main .global _start _start: xor %ebp,%ebp mov %rdx,%r9 pop %rsi mov %rsp,%rdx and $0xfffffffffffffff0,%rsp push %rax push %rsp mov $__libc_csu_fini,%r8 mov $__libc_csu_init,%rcx mov $main,%rdi call __libc_start_main hlt (I used "objdump -D" and "readelf -r" to restore the original code from crt1.o).
Fixed in: r343668
Thanks! This seems appropriate to release in 7.0.1.