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,22 @@ } 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) { Symbol *S = Symtab->find(Name); if (!S || S->isInCurrentOutput()) return nullptr; - Symbol *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 + // section 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(Sym); + return Sym; } // The beginning and the ending of .rel[a].plt section are marked @@ -759,10 +769,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 +806,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 +820,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); @@ -1231,10 +1241,14 @@ // 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) { + Symbol *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(cast(Sym)); + } // Define __rel[a]_iplt_{start,end} symbols if needed. addRelIpltSymbols(); @@ -1362,6 +1376,13 @@ // 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 (DefinedRegular* Sym : SectionStartSymbols) + if (Sym->Section) + if (OutputSection* OS = Sym->Section->getOutputSection()) + Sym->Size = OS->Size; } template void Writer::addPredefinedSections() { @@ -1382,13 +1403,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); } }; @@ -1410,8 +1431,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/arm-gnu-ifunc.s =================================================================== --- test/ELF/arm-gnu-ifunc.s +++ test/ELF/arm-gnu-ifunc.s @@ -73,7 +73,7 @@ // CHECK-NEXT: Symbol { // CHECK-NEXT: Name: __rel_iplt_start // CHECK-NEXT: Value: 0x100F4 -// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Size: 16 // CHECK-NEXT: Binding: Local // CHECK-NEXT: Type: None // CHECK-NEXT: Other [ Index: test/ELF/arm-static-defines.s =================================================================== --- test/ELF/arm-static-defines.s +++ test/ELF/arm-static-defines.s @@ -33,7 +33,7 @@ // CHECK-NEXT: Section: .ARM.exidx // CHECK: Name: __exidx_start // CHECK-NEXT: Value: 0x100D4 -// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Size: 16 // CHECK-NEXT: Binding: Local // CHECK-NEXT: Type: None // CHECK-NEXT: Other [ Index: test/ELF/bss-start-common.s =================================================================== --- test/ELF/bss-start-common.s +++ test/ELF/bss-start-common.s @@ -7,7 +7,7 @@ # CHECK: Idx Name Size Address Type # CHECK: 2 .bss 00000004 0000000000201000 BSS # CHECK: SYMBOL TABLE: -# CHECK: 0000000000201000 .bss 00000000 __bss_start +# CHECK: 0000000000201000 .bss 00000004 __bss_start .global __bss_start .text Index: test/ELF/dso_handle.s =================================================================== --- test/ELF/dso_handle.s +++ test/ELF/dso_handle.s @@ -5,7 +5,7 @@ # RUN: llvm-readobj -symbols %t | FileCheck %s # CHECK: Name: __dso_handle # CHECK-NEXT: Value: 0x0 -# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Size: 64 # CHECK-NEXT: Binding: Local # CHECK-NEXT: Type: None # CHECK-NEXT: Other [ Index: test/ELF/ehdr_start.s =================================================================== --- test/ELF/ehdr_start.s +++ test/ELF/ehdr_start.s @@ -5,7 +5,7 @@ # RUN: llvm-readobj -symbols %t | FileCheck %s # CHECK: Name: __ehdr_start (1) # CHECK-NEXT: Value: 0x200000 -# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Size: 64 # CHECK-NEXT: Binding: Local (0x0) # CHECK-NEXT: Type: None (0x0) # CHECK-NEXT: Other [ (0x2) @@ -15,7 +15,7 @@ # CHECK: Name: __executable_start # CHECK-NEXT: Value: 0x200000 -# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Size: 64 # CHECK-NEXT: Binding: Local # CHECK-NEXT: Type: None # CHECK-NEXT: Other [ Index: test/ELF/gc-sections-metadata-startstop.s =================================================================== --- test/ELF/gc-sections-metadata-startstop.s +++ test/ELF/gc-sections-metadata-startstop.s @@ -11,7 +11,7 @@ # CHECK-NOT: yy # CHECK: SYMBOL TABLE: -# CHECK: xx 00000000 __start_xx +# CHECK: xx 00000008 __start_xx # CHECK: w *UND* 00000000 __start_yy .weak __start_xx Index: test/ELF/global-offset-table-position-arm.s =================================================================== --- test/ELF/global-offset-table-position-arm.s +++ test/ELF/global-offset-table-position-arm.s @@ -26,7 +26,7 @@ // CHECK: Name: _GLOBAL_OFFSET_TABLE_ // CHECK-NEXT: Value: 0x3068 -// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Size: 4 // CHECK-NEXT: Binding: Local // CHECK-NEXT: Type: None // CHECK-NEXT: Other [ (0x2) Index: test/ELF/global-offset-table-position-mips.s =================================================================== --- test/ELF/global-offset-table-position-mips.s +++ test/ELF/global-offset-table-position-mips.s @@ -24,7 +24,7 @@ .word _GLOBAL_OFFSET_TABLE_ - . // CHECK: Name: _GLOBAL_OFFSET_TABLE_ (1) // CHECK-NEXT: Value: 0x20000 -// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Size: 40 // CHECK-NEXT: Binding: Local (0x0) // CHECK-NEXT: Type: None (0x0) // CHECK-NEXT: Other [ (0x2) Index: test/ELF/linkerscript/ehdr_start.s =================================================================== --- test/ELF/linkerscript/ehdr_start.s +++ test/ELF/linkerscript/ehdr_start.s @@ -6,7 +6,7 @@ # RUN: llvm-readobj -symbols %t | FileCheck %s # CHECK: Name: __ehdr_start (1) # CHECK-NEXT: Value: 0x0 -# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Size: 64 # CHECK-NEXT: Binding: Local (0x0) # CHECK-NEXT: Type: None (0x0) # CHECK-NEXT: Other [ (0x2) Index: test/ELF/pre_init_fini_array.s =================================================================== --- test/ELF/pre_init_fini_array.s +++ test/ELF/pre_init_fini_array.s @@ -75,7 +75,7 @@ // CHECK-NEXT: Symbol { // CHECK-NEXT: Name: __fini_array_start // CHECK-NEXT: Value: [[FINI_ADDR]] -// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Size: 10 // CHECK-NEXT: Binding: Local // CHECK-NEXT: Type: None // CHECK-NEXT: Other [ @@ -97,7 +97,7 @@ // CHECK-NEXT: Symbol { // CHECK-NEXT: Name: __init_array_start // CHECK-NEXT: Value: [[INIT_ADDR]] -// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Size: 8 // CHECK-NEXT: Binding: Local // CHECK-NEXT: Type: None // CHECK-NEXT: Other [ @@ -119,7 +119,7 @@ // CHECK-NEXT: Symbol { // CHECK-NEXT: Name: __preinit_array_start // CHECK-NEXT: Value: [[PREINIT_ADDR]] -// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Size: 9 // CHECK-NEXT: Binding: Local // CHECK-NEXT: Type: None // CHECK-NEXT: Other [ 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 00000004 __bss_start +# BOTH: foo 00000010 __start_foo +# BOTH: foo 00000000 __stop_foo