llvm / llvm-project

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

ld.lld -pie crashes on invalid linker script removing .got (https://github.com/android/ndk/issues/1817) #62292

Open appujee opened 1 year ago

appujee commented 1 year ago
 #0 0x0000000002a04c88 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/usr/local//aosp-master-with-phones/prebuilts/clang/host/linux-x86/clang-r450784d1/bin/ld.lld+0x2a04c88)
 #1 0x0000000002a03df0 llvm::sys::RunSignalHandlers() (/usr/local//aosp-master-with-phones/prebuilts/clang/host/linux-x86/clang-r450784d1/bin/ld.lld+0x2a03df0)
 #2 0x0000000002a050da (/usr/local//aosp-master-with-phones/prebuilts/clang/host/linux-x86/clang-r450784d1/bin/ld.lld+0x2a050da)
 #3 0x00007f3b2c54df90 (/lib/x86_64-linux-gnu/libc.so.6+0x3bf90)
 #4 0x000000000232af49 (/usr/local//aosp-master-with-phones/prebuilts/clang/host/linux-x86/clang-r450784d1/bin/ld.lld+0x232af49)
 #5 0x000000000233a704 (/usr/local//aosp-master-with-phones/prebuilts/clang/host/linux-x86/clang-r450784d1/bin/ld.lld+0x233a704)
 #6 0x000000000231b16c (/usr/local//aosp-master-with-phones/prebuilts/clang/host/linux-x86/clang-r450784d1/bin/ld.lld+0x231b16c)
 #7 0x0000000002316fb8 void lld::elf::writeResult<llvm::object::ELFType<(llvm::support::endianness)1, false> >() (/usr/local//aosp-master-with-phones/prebuilts/clang/host/linux-x86/clang-r450784d1/bin/ld.lld+0x2316fb8)
 #8 0x0000000002316901 void lld::elf::LinkerDriver::link<llvm::object::ELFType<(llvm::support::endianness)1, false> >(llvm::opt::InputArgList&) (/usr/local//aosp-master-with-phones/prebuilts/clang/host/linux-x86/clang-r450784d1/bin/ld.lld+0x2316901)
 #9 0x00000000022dda45 lld::elf::LinkerDriver::linkerMain(llvm::ArrayRef<char const*>) (/usr/local//aosp-master-with-phones/prebuilts/clang/host/linux-x86/clang-r450784d1/bin/ld.lld+0x22dda45)
#10 0x00000000022dce45 lld::elf::link(llvm::ArrayRef<char const*>, llvm::raw_ostream&, llvm::raw_ostream&, bool, bool) (/usr/local//aosp-master-with-phones/prebuilts/clang/host/linux-x86/clang-r450784d1/bin/ld.lld+0x22dce45)
#11 0x00000000018fc435 (/usr/local//aosp-master-with-phones/prebuilts/clang/host/linux-x86/clang-r450784d1/bin/ld.lld+0x18fc435)
#12 0x00000000026f8f32 main (/usr/local//aosp-master-with-phones/prebuilts/clang/host/linux-x86/clang-r450784d1/bin/ld.lld+0x26f8f32)
#13 0x00007f3b2c53918a __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:74:3
#14 0x00007f3b2c539245 call_init ./csu/../csu/libc-start.c:128:20
#15 0x00007f3b2c539245 __libc_start_main ./csu/../csu/libc-start.c:368:5
#16 0x00000000029d0d19 _start (/usr/local//aosp-master-with-phones/prebuilts/clang/host/linux-x86/clang-r450784d1/bin/ld.lld+0x29d0d19)
EugeneZelenko commented 1 year ago

Could you please try 16 or main branch?

llvmbot commented 1 year ago

@llvm/issue-subscribers-lld-elf

appujee commented 1 year ago

rep-a-tar-file.tar.zip

appujee commented 1 year ago

Crashed with LLD 16.0.2 as well. With the same command line as attached in the rep.tar file.

appujee commented 1 year ago

Repro steps taken from https://github.com/android/ndk/issues/1817:

Use this entry.s:

    .data
    .global _start
_start:
    .long   _start(GOT_PREL)

And this linker script test.ld:

ENTRY(_start)
SECTIONS {
    .data : { *(.data) }
    .shstrtab : { *(.shstrtab) }

    /DISCARD/ : { *(*) }
}

And use the following command line. Using LLD 16 should crash all the same.

$ ~/aosp-master-with-phones/prebuilts/clang/host/linux-x86/clang-r450784d1/bin/clang ~/g/bugs/ndk-1817/entry.s -c -o entry.o -target armv7-linux-android33 --sysroot ~/llvm-toolchain/toolchain/prebuilts/ndk/r25/toolchains/llvm/prebuilt/linux-x86_64/sysroot

$ ~/aosp-master-with-phones/prebuilts/clang/host/linux-x86/clang-r450784d1/bin/clang -nostartfiles -nodefaultlibs -nostdlib -Wl,-T,test.ld entry.o -o test.elf -fuse-ld=lld -target armv7-linux-android33
MaskRay commented 1 year ago

This is crash on invalid input.

This -pie use case is questionable. The output has GOT relocations, therefore .got is needed. The linker script uses /DISCARD/ : { *(*) } to discard .got. At the minimum .got : { *(.got) } is needed.

The experimental support for partitions requires in.got to be live (partition != 0). To fix the crash on invalid input, we can add a check to Relocations.cpp:addGotEntry, but I feel bad to add the code for the invalid use case. GOT relocations are not at a performance bottleneck, so it may not be that bad.

MaskRay commented 1 year ago

@pcc Can per-partition lld::elf::Parition::relaDyn (and relrDyn) be moved to in.relaDyn (and in.relrDyn)? I think this is the only way to avoid imposing a cost.