Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -59,6 +59,9 @@ std::vector createPhdrs(); void removeEmptyPTLoad(); void addPtArmExid(std::vector &Phdrs); + DefinedRegular *addOptionalRegular(StringRef Name, SectionBase *Sec, + uint64_t Val, uint8_t StOther = STV_HIDDEN, + uint8_t Binding = STB_GLOBAL); void assignFileOffsets(); void assignFileOffsetsBinary(); void setPhdrs(); @@ -81,6 +84,7 @@ OutputSection *findSection(StringRef Name); std::vector Phdrs; + std::vector> SectionStartSymbols; uint64_t FileSize; uint64_t SectionHeaderOff; @@ -737,16 +741,23 @@ } template -static DefinedRegular * -addOptionalRegular(StringRef Name, SectionBase *Sec, uint64_t Val, - uint8_t StOther = STV_HIDDEN, uint8_t Binding = STB_GLOBAL) { +DefinedRegular * +Writer::addOptionalRegular(StringRef Name, SectionBase *Sec, uint64_t Val, + uint8_t StOther, uint8_t Binding) { SymbolBody *S = Symtab->find(Name); if (!S || S->isInCurrentOutput()) return nullptr; - SymbolBody *Sym = Symtab->addRegular(Name, StOther, STT_NOTYPE, Val, - /*Size=*/0, Binding, Sec, - /*File=*/nullptr); - return cast(Sym); + DefinedRegular *Sym = cast( + Symtab->addRegular(Name, StOther, STT_NOTYPE, Val, + /*Size=*/0, Binding, Sec, + /*File=*/nullptr)); + // If the value is zero this is a section start symbol. We should set the + // size of that symbol to be the size of the section but we don't know the + // size yet. Therefore we save the symbol and the section now and update the + // size once we know the final size of the output section + if (Sec && Val == 0) + SectionStartSymbols.push_back(std::make_pair(Sym, Sec->getOutputSection())); + return Sym; } // The beginning and the ending of .rel[a].plt section are marked @@ -759,10 +770,10 @@ if (!Config->Static) return; StringRef S = Config->IsRela ? "__rela_iplt_start" : "__rel_iplt_start"; - addOptionalRegular(S, In::RelaIplt, 0, STV_HIDDEN, STB_WEAK); + addOptionalRegular(S, In::RelaIplt, 0, STV_HIDDEN, STB_WEAK); S = Config->IsRela ? "__rela_iplt_end" : "__rel_iplt_end"; - addOptionalRegular(S, In::RelaIplt, -1, STV_HIDDEN, STB_WEAK); + addOptionalRegular(S, In::RelaIplt, -1, STV_HIDDEN, STB_WEAK); } // The linker is expected to define some symbols depending on @@ -796,7 +807,7 @@ // of the .got InputSection *GotSection = InX::MipsGot ? cast(InX::MipsGot) : cast(InX::Got); - ElfSym::GlobalOffsetTable = addOptionalRegular( + ElfSym::GlobalOffsetTable = addOptionalRegular( "_GLOBAL_OFFSET_TABLE_", GotSection, Target->GotBaseSymOff); // __ehdr_start is the location of ELF file headers. Note that we define @@ -810,14 +821,14 @@ // different in different DSOs, so we chose the start address of the DSO. for (const char *Name : {"__ehdr_start", "__executable_start", "__dso_handle"}) - addOptionalRegular(Name, Out::ElfHeader, 0, STV_HIDDEN); + addOptionalRegular(Name, Out::ElfHeader, 0, STV_HIDDEN); // If linker script do layout we do not need to create any standart symbols. if (Script->HasSectionsCommand) return; - auto Add = [](StringRef S, int64_t Pos) { - return addOptionalRegular(S, Out::ElfHeader, Pos, STV_DEFAULT); + auto Add = [this](StringRef S, int64_t Pos) { + return addOptionalRegular(S, Out::ElfHeader, Pos, STV_DEFAULT); }; ElfSym::Bss = Add("__bss_start", 0); @@ -1234,10 +1245,16 @@ // It should be okay as no one seems to care about the type. // Even the author of gold doesn't remember why gold behaves that way. // https://sourceware.org/ml/binutils/2002-03/msg00360.html - if (InX::DynSymTab) - Symtab->addRegular("_DYNAMIC", STV_HIDDEN, STT_NOTYPE, 0 /*Value*/, - /*Size=*/0, STB_WEAK, InX::Dynamic, - /*File=*/nullptr); + if (InX::DynSymTab) { + SymbolBody *Sym = Symtab->addRegular( + "_DYNAMIC", STV_HIDDEN, STT_NOTYPE, 0 /*Value*/, + /*Size=*/0, STB_WEAK, InX::Dynamic, + /*File=*/nullptr); + // We don't know the final size of the dynamic section yet so defer setting + // the size of the output section + SectionStartSymbols.push_back(std::make_pair( + cast(Sym), InX::Dynamic->getOutputSection())); + } // Define __rel[a]_iplt_{start,end} symbols if needed. addRelIpltSymbols(); @@ -1365,6 +1382,11 @@ // createThunks may have added local symbols to the static symbol table applySynthetic({InX::SymTab}, [](SyntheticSection *SS) { SS->postThunkContents(); }); + + // Now that we know the size of all output sections we can update the size + // of the section start symbols. + for (const auto &it : SectionStartSymbols) + it.first->Size = it.second->Size; } template void Writer::addPredefinedSections() { @@ -1385,13 +1407,13 @@ // These symbols resolve to the image base if the section does not exist. // A special value -1 indicates end of the section. if (OS) { - addOptionalRegular(Start, OS, 0); - addOptionalRegular(End, OS, -1); + addOptionalRegular(Start, OS, 0); + addOptionalRegular(End, OS, -1); } else { if (Config->Pic) OS = Out::ElfHeader; - addOptionalRegular(Start, OS, 0); - addOptionalRegular(End, OS, 0); + addOptionalRegular(Start, OS, 0); + addOptionalRegular(End, OS, 0); } }; @@ -1413,8 +1435,8 @@ StringRef S = Sec->Name; if (!isValidCIdentifier(S)) return; - addOptionalRegular(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT); - addOptionalRegular(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT); + addOptionalRegular(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT); + addOptionalRegular(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT); } template OutputSection *Writer::findSection(StringRef Name) { Index: test/ELF/section-start-symbols.s =================================================================== --- /dev/null +++ test/ELF/section-start-symbols.s @@ -0,0 +1,101 @@ +# RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o +# RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi \ +# RUN: -defsym=ARRAYS_EXIST=1 %s -o %t-with-arrays.o +# RUN: ld.lld --static %t.o -o %t.exe +# RUN: ld.lld --static %t-with-arrays.o -o %t-with-arrays.exe +# RUN: llvm-objdump -t %t.exe | FileCheck %s -check-prefixes STATIC,BOTH,EMPTY-ARRAYS +# RUN: llvm-objdump -t %t-with-arrays.exe | FileCheck %s -check-prefixes STATIC,BOTH,WITH-ARRAYS +# RUN: ld.lld -pie %t.o -o %t-pie.exe -z notext +# RUN: ld.lld -pie %t-with-arrays.o -o %t-with-arrays-pie.exe -z notext +# RUN: llvm-objdump -t %t-pie.exe | FileCheck -check-prefixes PIE-EMPTY,BOTH,EMPTY-ARRAYS %s +# RUN: llvm-objdump -t %t-with-arrays-pie.exe | FileCheck -check-prefixes PIE-WITH-ARRAYS,BOTH,WITH-ARRAYS %s +# REQUIRES: arm + + .syntax unified +.section .text + + .weak _DYNAMIC + .global _start + .global _start +_start: + .fnstart + bx lr + .word __exidx_start + .word __exidx_end + .word __preinit_array_start + .word __preinit_array_end + .word __init_array_start + .word __init_array_end + .word __fini_array_start + .word __fini_array_end + .word _DYNAMIC + .word __start_foo + .word __stop_foo + .word __bss_start + .word __ehdr_start + .word __executable_start + .word __dso_handle +.ifdef NOTYET + # FIXME: if I try to reference __rel_iplt_start here, llvm-objdump + # fails with the error: index past the end of the symbol table + # this also happens without my patch setting the sizes so there seems to be + # some corruption happening with a zero size .rel.iplt? + .weak __rel_iplt_start + .word __rel_iplt_start + .weak __rel_iplt_end + .word __rel_iplt_end +.endif + + .cantunwind + .fnend + +.section foo,"aw" + .quad 0 + .quad 1 + +.comm bss_sym,4,4 + +.ifdef ARRAYS_EXIST + +.section .init_array,"aw",%init_array + .quad 0 + +.section .preinit_array,"aw",%preinit_array + .quad 0 + .byte 0 + +.section .fini_array,"aw",%fini_array + .quad 0 + .short 0 + +.endif +# PIE-EMPTY: .dynamic 00000068 .hidden _DYNAMIC +# PIE-WITH-ARRAYS: .dynamic 00000098 .hidden _DYNAMIC +# BOTH: .ARM.exidx 00000034 .hidden __dso_handle +# BOTH: .ARM.exidx 00000034 .hidden __ehdr_start +# BOTH: .ARM.exidx 00000034 .hidden __executable_start +# BOTH: .ARM.exidx 00000000 .hidden __exidx_end +# BOTH: .ARM.exidx 00000010 .hidden __exidx_start +# STATIC-EMPTY: *ABS* 00000000 .hidden __fini_array_end +# STATIC-EMPTY: *ABS* 00000000 .hidden __fini_array_start +# STATIC-EMPTY: *ABS* 00000000 .hidden __init_array_end +# STATIC-EMPTY: *ABS* 00000000 .hidden __init_array_start +# STATIC-EMPTY: *ABS* 00000000 .hidden __preinit_array_end +# STATIC-EMPTY: *ABS* 00000000 .hidden __preinit_array_start +# In PIE executables the __init/__fini symbols point to the ELF header +# PIE-EMPTY: .ARM.exidx 00000034 .hidden __fini_array_end +# PIE-EMPTY: .ARM.exidx 00000034 .hidden __fini_array_start +# PIE-EMPTY: .ARM.exidx 00000034 .hidden __init_array_end +# PIE-EMPTY: .ARM.exidx 00000034 .hidden __init_array_start +# PIE-EMPTY: .ARM.exidx 00000034 .hidden __preinit_array_end +# PIE-EMPTY: .ARM.exidx 00000034 .hidden __preinit_array_start +# WITH-ARRAYS: .fini_array 00000000 .hidden __fini_array_end +# WITH-ARRAYS: .fini_array 0000000a .hidden __fini_array_start +# WITH-ARRAYS: .init_array 00000000 .hidden __init_array_end +# WITH-ARRAYS: .init_array 00000008 .hidden __init_array_start +# WITH-ARRAYS: .preinit_array 00000000 .hidden __preinit_array_end +# WITH-ARRAYS: .preinit_array 00000009 .hidden __preinit_array_start +# STATIC: w *UND* 00000000 _DYNAMIC +# BOTH: .bss 00000034 __bss_start +# BOTH: foo 00000010 __start_foo +# BOTH: foo 00000000 __stop_foo