LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 31295 - lld segfault in InputSection::writeTo linking FreeBSD/i386 gptboot loader (reproducer attached)
Summary: lld segfault in InputSection::writeTo linking FreeBSD/i386 gptboot loader (re...
Status: RESOLVED FIXED
Alias: None
Product: lld
Classification: Unclassified
Component: ELF (show other bugs)
Version: unspecified
Hardware: PC FreeBSD
: P normal
Assignee: George Rimar
URL:
Keywords:
Depends on:
Blocks: 23214
  Show dependency tree
 
Reported: 2016-12-06 09:25 PST by emaste
Modified: 2016-12-20 03:46 PST (History)
3 users (show)

See Also:
Fixed By Commit(s):


Attachments
lld segfault reproducer (437.82 KB, application/octet-stream)
2016-12-06 09:25 PST, emaste
Details

Note You need to log in before you can comment on or make changes to this bug.
Description emaste 2016-12-06 09:25:28 PST
Created attachment 17729 [details]
lld segfault reproducer

Linking the gpt bootloader, which is an i386 binary on FreeBSD/amd64.

Boot log excerpt:

--- gptboot.out ---
ld -static -N --gc-sections -m elf_i386_fbsd -Ttext 0x0 -o gptboot.out /tank/emaste/obj/tank/emaste/src/freebsd-xlld/sys/boot/i386/gptboot/../btx/lib/crt0.o gptboot.o sio.o crc32.o drv.o cons.o util.o xform_aes_xts.o /tank/emaste/obj/tank/emaste/src/freebsd-xlld/sys/boot/i386/gptboot/../../geli/libgeliboot.a /tank/emaste/obj/tank/emaste/src/freebsd-xlld/sys/boot/i386/gptboot/../../libstand32/libstand.a


Backtrace excerpt:

(lldb) bt
* thread #5: tid = 102169, 0x00000008065eaf46 libc.so.7`memcpy + 22 at bcopy.S:65, stop reason = invalid address (fault address: 0x9051b1090)
  * frame #0: 0x00000008065eaf46 libc.so.7`memcpy + 22 at bcopy.S:65
    frame #1: 0x000000000068d084 ld.lld`lld::elf::InputSection<llvm::object::ELFType<(this=0x00000008074f3320, Buf=0x00000009051b1000)1, false> >::writeTo(unsigned char*) + 372 at InputSection.cpp:596
    frame #2: 0x000000000081be40 ld.lld`operator(this=0x00007fffdf7f9bd8, IS=0x00000008074f3320) + 32 at OutputSections.cpp:256
    frame #3: 0x000000000081db6c ld.lld`operator() [inlined] lld::elf::OutputSection<llvm::object::ELFType<(__first=__wrap_iter<lld::elf::InputSection<llvm::object::ELFType<1, false> > **> at 0x00007fffdf7f9be8, __last=__wrap_iter<lld::elf::InputSection<llvm::object::ELFType<1, false> > **> at 0x00007fffdf7f9be0, __f=l
ld::elf::OutputSection<llvm::object::ELFType<llvm::support::endianness, false> >::<anonymous class> at 0x00007fffdf7f9bd8)1, false> >::writeTo(unsigned char*)::'lambda'(lld::elf::InputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >*)  std::__1::for_each<std::__1::__wrap_iter<lld::elf::InputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >**>, lld::elf::Output
Section<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeTo(unsigned char*)::'lambda'(lld::elf::InputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >*)>(std::__1::__wrap_iter<lld::elf::InputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >**>, std::__1::__wrap_iter<lld::elf::InputSection<llvm::object::ELFType<(llvm::support::endianness)1, fa
lse> >**>, lld::elf::OutputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeTo(unsigned char*)::'lambda'(lld::elf::InputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >*)) + 93 at algorithm:853
    frame #4: 0x000000000081db0f ld.lld`operator(this=0x0000000808810078) + 191 at Parallel.h:307
    frame #5: 0x000000000081da3c ld.lld`std::__1::__function::__func<void lld::parallel_for_each<std::__1::__wrap_iter<lld::elf::InputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >**>, lld::elf::OutputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeTo(unsigned char*)::'lambda'(lld::elf::InputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >*)>(std::__1::__wrap_iter<lld::elf::InputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >**>, std::__1::__wrap_iter<lld::elf::InputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >**>, lld::elf::OutputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeTo(unsigned char*)::'lambda'(lld::elf::InputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >*))::'lambda'(), std::__1::allocator<void lld::parallel_for_each<std::__1::__wrap_iter<lld::elf::InputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >**>, lld::elf::OutputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeTo(unsigned char*)::'lambda'(lld::elf::InputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >*)>(std::__1::__wrap_iter<lld::elf::InputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >**>, std::__1::__wrap_iter<lld::elf:
:InputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >**>, lld::elf::OutputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeTo(unsigned char*)::'lambda'(lld::elf::InputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >*))::'lambda'()>, void ()>::operator()
() [inlined] decltype(this=0x0000000808810078, __f=0x0000000808810078)1, false> >**> >(fp)(std::__1::forward<>(fp0))) std::__1::__invoke<void lld::parallel_for_each<std::__1::__wrap_iter<lld::elf::InputSection<llvm::object::ELFType<(llvm::spport::endianness)1, false> >**>, lld::elf::OutputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeTo(unsigned char*)::'lambda'(lld::elf::InputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >*)>(std::__1::__wrap_iter<lld::elf::InputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >**>, std::__1::__wrap_iter<lld::elf::InputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >**>, lld::elf::OutputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeTo(unsigned char*)::'lambda'(lld::elf::InputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >*))::'lambda'()&>(std::__1::__wrap_iter<lld::elf::InputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >**>&&) + 60 
at __functional_base:413
Comment 1 George Rimar 2016-12-06 10:23:56 PST
Problem is:
-Ttext 0x0

Our offset calculation does not support this yet:
return First->Offset + Sec->Addr - First->Addr;

First->Offset == 0x0
Sec->Addr == 0x0 (-Ttext)
First->Addr = 0x10000 (Header)
Comment 2 emaste 2016-12-06 11:21:42 PST
Also a segfault in:

--- zfsboot.out ---
ld -static -N --gc-sections -m elf_i386_fbsd -Ttext 0x2000 -o zfsboot.out /tank/
emaste/obj/tank/emaste/src/freebsd-xlld/sys/boot/i386/zfsboot/../btx/lib/crt0.o 
zfsboot.o sio.o drv.o cons.o util.o skein.o skein_block.o /tank/emaste/obj/tank/
emaste/src/freebsd-xlld/sys/boot/i386/zfsboot/../../libstand32/libstand.a
Segmentation fault (core dumped)
*** [zfsboot.out] Error code 139
Comment 3 George Rimar 2016-12-07 11:05:36 PST
D27526 should fix that all.
Comment 4 George Rimar 2016-12-08 08:06:00 PST
So looks -Ttext option does not set the address of .text at fact.
For bfd it do:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        00000000 000080 00ba74 00 WAX  0   0 16
  [ 2] .rodata           PROGBITS        0000ba80 00bb00 0035f4 00   A  0   0 16
  [ 3] .got.plt          PROGBITS        0000f074 00f0f4 00000c 04  WA  0   0  4
...
Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000080 0x00000000 0x00000000 0x0f1b0 0x18598 RWE 0x10
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x10

Buf for gold - dont:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        00000080 000080 00ba74 00  AX  0   0 16
  [ 2] .rodata           PROGBITS        0000bb00 00bb00 0035fc 00   A  0   0 16
  [ 3] .got              PROGBITS        0000f0fc 00f0fc 000000 00  WA  0   0  4
  [ 4] .got.plt          PROGBITS        0000f0fc 00f0fc 00000c 00  WA  0   0  4
...

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x00000000 0x00000000 0x0f238 0x18628 RWE 0x10
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0

But it affects on PT_LOAD VA. Does it mean we just want to set ImageBase to address of -Ttext ?
that looks would have the same behavior as gold shows then. (PT_LOAD will have VA = 0x0, .text will have some address as VA, size_of_headers in the case of reproduce for this issue).
Comment 5 George Rimar 2016-12-20 03:46:50 PST
Should be fixed by Rafael in r290136