Index: ELF/InputFiles.h =================================================================== --- ELF/InputFiles.h +++ ELF/InputFiles.h @@ -129,7 +129,7 @@ // R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations. uint32_t getMipsGp0() const; - std::vector KeptLocalSyms; + std::vector> KeptLocalSyms; private: void initializeSections(llvm::DenseSet &ComdatGroups); Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -12,7 +12,6 @@ #include "lld/Core/LLVM.h" -#include "llvm/ADT/MapVector.h" #include "llvm/MC/StringTableBuilder.h" #include "llvm/Object/ELF.h" @@ -73,6 +72,7 @@ void setVA(uintX_t VA) { Header.sh_addr = VA; } uintX_t getVA() const { return Header.sh_addr; } void setFileOffset(uintX_t Off) { Header.sh_offset = Off; } + void setSHName(unsigned Val) { Header.sh_name = Val; } void writeHeaderTo(Elf_Shdr *SHdr); StringRef getName() { return Name; } @@ -195,12 +195,16 @@ void finalize() override; void writeTo(uint8_t *Buf) override; - void addLocalSymbol(StringRef Name); void addSymbol(SymbolBody *Body); StringTableSection &getStrTabSec() const { return StrTabSec; } unsigned getNumSymbols() const { return NumLocals + Symbols.size() + 1; } - ArrayRef getSymbols() const { return Symbols; } + ArrayRef> getSymbols() const { + return Symbols; + } + + unsigned NumLocals = 0; + StringTableSection &StrTabSec; private: void writeLocalSymbols(uint8_t *&Buf); @@ -209,9 +213,7 @@ static uint8_t getSymbolBinding(SymbolBody *Body); SymbolTable &Table; - StringTableSection &StrTabSec; - std::vector Symbols; - unsigned NumLocals = 0; + std::vector> Symbols; }; template @@ -328,18 +330,17 @@ public: typedef typename llvm::object::ELFFile::uintX_t uintX_t; StringTableSection(StringRef Name, bool Dynamic); - void reserve(StringRef S); - size_t addString(StringRef S); + size_t addString(StringRef S, bool HashIt = true); void writeTo(uint8_t *Buf) override; - size_t getSize() const { return Used + Reserved; } + size_t getSize() const { return Size; } void finalize() override { this->Header.sh_size = getSize(); } bool isDynamic() const { return Dynamic; } private: const bool Dynamic; + llvm::DenseMap StringMap; std::vector Strings; - size_t Used = 1; // ELF string tables start with a NUL byte, so 1. - size_t Reserved = 0; + size_t Size = 1; // ELF string tables start with a NUL byte, so 1. }; template @@ -367,7 +368,7 @@ // Adds symbols to the hash table. // Sorts the input to satisfy GNU hash section requirements. - void addSymbols(std::vector &Symbols); + void addSymbols(std::vector> &Symbols); private: static unsigned calcNBuckets(unsigned NumHashed); @@ -379,6 +380,7 @@ struct HashedSymbolData { SymbolBody *Body; + unsigned STName; uint32_t Hash; }; Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -379,7 +379,6 @@ template void OutputSectionBase::writeHeaderTo(Elf_Shdr *SHdr) { - Header.sh_name = Out::ShStrTab->addString(Name); *SHdr = Header; } @@ -428,7 +427,9 @@ Elf_Word *Buckets = P; Elf_Word *Chains = P + NumSymbols; - for (SymbolBody *Body : Out::DynSymTab->getSymbols()) { + for (const std::pair &P : + Out::DynSymTab->getSymbols()) { + SymbolBody *Body = P.first; StringRef Name = Body->getName(); unsigned I = Body->DynamicSymbolTableIndex; uint32_t Hash = hashSysv(Name) % NumSymbols; @@ -560,15 +561,18 @@ } template -void GnuHashTableSection::addSymbols(std::vector &Symbols) { - std::vector NotHashed; +void GnuHashTableSection::addSymbols( + std::vector> &Symbols) { + std::vector> NotHashed; NotHashed.reserve(Symbols.size()); HashedSymbols.reserve(Symbols.size()); - for (SymbolBody *B : Symbols) { + for (const std::pair &P : Symbols) { + SymbolBody *B = P.first; if (includeInGnuHashTable(B)) - HashedSymbols.push_back(HashedSymbolData{B, hashGnu(B->getName())}); + HashedSymbols.push_back( + HashedSymbolData{B, P.second, hashGnu(B->getName())}); else - NotHashed.push_back(B); + NotHashed.push_back(P); } if (HashedSymbols.empty()) return; @@ -581,7 +585,7 @@ Symbols = std::move(NotHashed); for (const HashedSymbolData &Item : HashedSymbols) - Symbols.push_back(Item.Body); + Symbols.push_back(std::make_pair(Item.Body, Item.STName)); } template @@ -606,18 +610,21 @@ Elf_Shdr &Header = this->Header; Header.sh_link = Out::DynStrTab->SectionIndex; + auto Add = [=](Entry E) { Entries.push_back(E); }; + // Reserve strings. We know that these are the last string to be added to // DynStrTab and doing this here allows this function to set DT_STRSZ. if (!Config->RPath.empty()) - Out::DynStrTab->reserve(Config->RPath); - if (!Config->SoName.empty()) - Out::DynStrTab->reserve(Config->SoName); + Add({Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH, + Out::DynStrTab->addString(Config->RPath)}); for (const std::unique_ptr> &F : SymTab.getSharedFiles()) if (F->isNeeded()) - Out::DynStrTab->reserve(F->getSoName()); + Add({DT_NEEDED, Out::DynStrTab->addString(F->getSoName())}); + if (!Config->SoName.empty()) + Add({DT_SONAME, Out::DynStrTab->addString(Config->SoName)}); + Out::DynStrTab->finalize(); - auto Add = [=](Entry E) { Entries.push_back(E); }; if (Out::RelaDyn->hasRelocs()) { bool IsRela = Out::RelaDyn->isRela(); @@ -643,13 +650,6 @@ if (Out::HashTab) Add({DT_HASH, Out::HashTab}); - if (!Config->RPath.empty()) - Add({Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH, - Out::DynStrTab->addString(Config->RPath)}); - - if (!Config->SoName.empty()) - Add({DT_SONAME, Out::DynStrTab->addString(Config->SoName)}); - if (PreInitArraySec) { Add({DT_PREINIT_ARRAY, PreInitArraySec}); Add({DT_PREINIT_ARRAYSZ, PreInitArraySec->getSize()}); @@ -663,10 +663,6 @@ Add({DT_FINI_ARRAYSZ, (uintX_t)FiniArraySec->getSize()}); } - for (const std::unique_ptr> &F : SymTab.getSharedFiles()) - if (F->isNeeded()) - Add({DT_NEEDED, Out::DynStrTab->addString(F->getSoName())}); - if (SymbolBody *B = SymTab.find(Config->Init)) Add({DT_INIT, B}); if (SymbolBody *B = SymTab.find(Config->Fini)) @@ -1207,13 +1203,15 @@ void EHOutputSection::addSection(InputSectionBase *C) { auto *S = cast>(C); const Elf_Shdr *RelSec = S->RelocSection; - if (!RelSec) - return addSectionAux( - S, make_range((const Elf_Rela *)nullptr, (const Elf_Rela *)nullptr)); + if (!RelSec) { + addSectionAux(S, make_range(nullptr, nullptr)); + return; + } ELFFile &Obj = S->getFile()->getObj(); if (RelSec->sh_type == SHT_RELA) - return addSectionAux(S, Obj.relas(RelSec)); - return addSectionAux(S, Obj.rels(RelSec)); + addSectionAux(S, Obj.relas(RelSec)); + else + addSectionAux(S, Obj.rels(RelSec)); } template @@ -1347,30 +1345,18 @@ this->Header.sh_addralign = 1; } -// String tables are created in two phases. First you call reserve() -// to reserve room in the string table, and then call addString() to actually -// add that string. -// -// Why two phases? We want to know the size of the string table as early as -// possible to fix file layout. So we have separated finalize(), which -// determines the size of the section, from writeTo(), which writes the section -// contents to the output buffer. If we merge reserve() with addString(), -// we need a plumbing work for finalize() and writeTo() so that offsets -// we obtained in the former function can be written in the latter. -// This design eliminated that need. -template void StringTableSection::reserve(StringRef S) { - Reserved += S.size() + 1; // +1 for NUL -} - -// Adds a string to the string table. You must call reserve() with the -// same string before calling addString(). -template size_t StringTableSection::addString(StringRef S) { - size_t Pos = Used; +// Adds a string to the string table. +template +size_t StringTableSection::addString(StringRef S, bool HashIt) { + if (HashIt) { + auto R = StringMap.insert(std::make_pair(S, Size)); + if (!R.second) + return R.first->second; + } + size_t Ret = Size; + Size += S.size() + 1; Strings.push_back(S); - Used += S.size() + 1; - Reserved -= S.size() + 1; - assert((int64_t)Reserved >= 0); - return Pos; + return Ret; } template void StringTableSection::writeTo(uint8_t *Buf) { @@ -1388,7 +1374,7 @@ : OutputSectionBase(StrTabSec.isDynamic() ? ".dynsym" : ".symtab", StrTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB, StrTabSec.isDynamic() ? (uintX_t)SHF_ALLOC : 0), - Table(Table), StrTabSec(StrTabSec) { + StrTabSec(StrTabSec), Table(Table) { this->Header.sh_entsize = sizeof(Elf_Sym); this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4; } @@ -1398,10 +1384,11 @@ // See "Global Offset Table" in Chapter 5 in the following document // for detailed description: // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf -static bool sortMipsSymbols(SymbolBody *L, SymbolBody *R) { - if (!L->isInGot() || !R->isInGot()) - return R->isInGot(); - return L->GotIndex < R->GotIndex; +static bool sortMipsSymbols(const std::pair &L, + const std::pair &R) { + if (!L.first->isInGot() || !R.first->isInGot()) + return R.first->isInGot(); + return L.first->GotIndex < R.first->GotIndex; } template void SymbolTableSection::finalize() { @@ -1414,9 +1401,10 @@ if (!StrTabSec.isDynamic()) { std::stable_sort(Symbols.begin(), Symbols.end(), - [](SymbolBody *L, SymbolBody *R) { - return getSymbolBinding(L) == STB_LOCAL && - getSymbolBinding(R) != STB_LOCAL; + [](const std::pair &L, + const std::pair &R) { + return getSymbolBinding(L.first) == STB_LOCAL && + getSymbolBinding(R.first) != STB_LOCAL; }); return; } @@ -1426,20 +1414,14 @@ else if (Config->EMachine == EM_MIPS) std::stable_sort(Symbols.begin(), Symbols.end(), sortMipsSymbols); size_t I = 0; - for (SymbolBody *B : Symbols) - B->DynamicSymbolTableIndex = ++I; -} - -template -void SymbolTableSection::addLocalSymbol(StringRef Name) { - StrTabSec.reserve(Name); - ++NumLocals; + for (const std::pair &P : Symbols) + P.first->DynamicSymbolTableIndex = ++I; } template void SymbolTableSection::addSymbol(SymbolBody *Body) { - StrTabSec.reserve(Body->getName()); - Symbols.push_back(Body); + Symbols.push_back( + std::make_pair(Body, StrTabSec.addString(Body->getName(), false))); } template void SymbolTableSection::writeTo(uint8_t *Buf) { @@ -1458,10 +1440,8 @@ // Iterate over all input object files to copy their local symbols // to the output symbol table pointed by Buf. for (const std::unique_ptr> &File : Table.getObjectFiles()) { - for (const Elf_Sym *Sym : File->KeptLocalSyms) { - ErrorOr SymNameOrErr = Sym->getName(File->getStringTable()); - error(SymNameOrErr); - StringRef SymName = *SymNameOrErr; + for (const std::pair &P : File->KeptLocalSyms) { + const Elf_Sym *Sym = P.first; auto *ESym = reinterpret_cast(Buf); uintX_t VA = 0; @@ -1478,7 +1458,7 @@ if (Config->EMachine != EM_AMDGPU) VA += OutSec->getVA(); } - ESym->st_name = StrTabSec.addString(SymName); + ESym->st_name = P.second; ESym->st_size = Sym->st_size; ESym->setBindingAndType(Sym->getBinding(), Sym->getType()); ESym->st_value = VA; @@ -1502,7 +1482,8 @@ // Write the internal symbol table contents to the output symbol table // pointed by Buf. auto *ESym = reinterpret_cast(Buf); - for (SymbolBody *Body : Symbols) { + for (const std::pair &P : Symbols) { + SymbolBody *Body = P.first; const OutputSectionBase *OutSec = nullptr; switch (Body->kind()) { @@ -1532,8 +1513,7 @@ break; } - StringRef Name = Body->getName(); - ESym->st_name = StrTabSec.addString(Name); + ESym->st_name = P.second; unsigned char Type = STT_NOTYPE; uintX_t Size = 0; Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -430,8 +430,9 @@ if (!Section->isLive()) continue; } - Out::SymTab->addLocalSymbol(SymName); - F->KeptLocalSyms.push_back(&Sym); + ++Out::SymTab->NumLocals; + F->KeptLocalSyms.push_back(std::make_pair( + &Sym, Out::SymTab->StrTabSec.addString(SymName))); } } } @@ -903,7 +904,7 @@ } for (OutputSectionBase *Sec : OutputSections) - Out::ShStrTab->reserve(Sec->getName()); + Sec->setSHName(Out::ShStrTab->addString(Sec->getName())); // Finalizers fix each section's size. // .dynsym is finalized early since that may fill up .gnu.hash. Index: test/ELF/dynamic-reloc.s =================================================================== --- test/ELF/dynamic-reloc.s +++ test/ELF/dynamic-reloc.s @@ -43,6 +43,7 @@ // CHECK: DynamicSection [ // CHECK-NEXT: Tag Type Name/Value +// CHECK-NEXT: 0x0000000000000001 NEEDED SharedLibrary ({{.*}}2.so) // CHECK-NEXT: 0x0000000000000017 JMPREL // CHECK-NEXT: 0x0000000000000002 PLTRELSZ 24 (bytes) // CHECK-NEXT: 0x0000000000000003 PLTGOT @@ -52,7 +53,6 @@ // CHECK-NEXT: 0x0000000000000005 STRTAB // CHECK-NEXT: 0x000000000000000A STRSZ // CHECK-NEXT: 0x0000000000000004 HASH -// CHECK-NEXT: 0x0000000000000001 NEEDED SharedLibrary ({{.*}}2.so) // CHECK-NEXT: 0x0000000000000015 DEBUG 0x0 // CHECK-NEXT: 0x0000000000000000 NULL 0x0 // CHECK-NEXT: ] Index: test/ELF/linkerscript-sections.s =================================================================== --- test/ELF/linkerscript-sections.s +++ test/ELF/linkerscript-sections.s @@ -22,7 +22,7 @@ # SEC-DEFAULT: 4 .bss 00000002 {{[0-9a-f]*}} BSS # SEC-DEFAULT: 5 .shstrtab 00000002 {{[0-9a-f]*}} # SEC-DEFAULT: 6 .symtab 00000030 {{[0-9a-f]*}} -# SEC-DEFAULT: 7 .shstrtab 0000003c {{[0-9a-f]*}} +# SEC-DEFAULT: 7 .shstrtab 00000032 {{[0-9a-f]*}} # SEC-DEFAULT: 8 .strtab 00000008 {{[0-9a-f]*}} # Sections are put in order specified in linker script. @@ -42,7 +42,7 @@ # SEC-ORDER: 1 .bss 00000002 {{[0-9a-f]*}} BSS # SEC-ORDER: 2 other 00000003 {{[0-9a-f]*}} DATA # SEC-ORDER: 3 .shstrtab 00000002 {{[0-9a-f]*}} -# SEC-ORDER: 4 .shstrtab 0000003c {{[0-9a-f]*}} +# SEC-ORDER: 4 .shstrtab 00000032 {{[0-9a-f]*}} # SEC-ORDER: 5 .symtab 00000030 {{[0-9a-f]*}} # SEC-ORDER: 6 .strtab 00000008 {{[0-9a-f]*}} # SEC-ORDER: 7 .data 00000020 {{[0-9a-f]*}} DATA @@ -63,7 +63,7 @@ # SEC-SWAP-NAMES: 4 .bss 00000002 {{[0-9a-f]*}} BSS # SEC-SWAP-NAMES: 5 .shstrtab 00000002 {{[0-9a-f]*}} # SEC-SWAP-NAMES: 6 .symtab 00000030 {{[0-9a-f]*}} -# SEC-SWAP-NAMES: 7 .shstrtab 0000003c {{[0-9a-f]*}} +# SEC-SWAP-NAMES: 7 .shstrtab 00000032 {{[0-9a-f]*}} # SEC-SWAP-NAMES: 8 .strtab 00000008 {{[0-9a-f]*}} # .shstrtab from the input object file is discarded. @@ -100,7 +100,7 @@ # SEC-MULTI: 3 .bss 00000002 {{[0-9a-f]*}} BSS # SEC-MULTI: 4 .shstrtab 00000002 {{[0-9a-f]*}} # SEC-MULTI: 5 .symtab 00000030 {{[0-9a-f]*}} -# SEC-MULTI: 6 .shstrtab 00000036 {{[0-9a-f]*}} +# SEC-MULTI: 6 .shstrtab 0000002c {{[0-9a-f]*}} # SEC-MULTI: 7 .strtab 00000008 {{[0-9a-f]*}} .globl _start; Index: test/ELF/shared-be.s =================================================================== --- test/ELF/shared-be.s +++ test/ELF/shared-be.s @@ -20,12 +20,12 @@ // CHECK: DynamicSection [ // CHECK-NEXT: Tag Type Name/Value +// CHECK-NEXT: 0x000000000000001D RUNPATH foo:bar +// CHECK-NEXT: 0x0000000000000001 NEEDED SharedLibrary ({{.*}}2.so) // CHECK-NEXT: 0x0000000000000007 RELA [[RELADDR]] // CHECK-NEXT: 0x0000000000000008 RELASZ [[RELSIZE]] (bytes) // CHECK-NEXT: 0x0000000000000009 RELAENT [[RELENT]] (bytes) -// CHECK: 0x000000000000001D RUNPATH foo:bar -// CHECK-NEXT: 0x0000000000000001 NEEDED SharedLibrary ({{.*}}2.so) -// CHECK-NEXT: 0x0000000000000015 DEBUG 0x0 +// CHECK: 0x0000000000000015 DEBUG 0x0 // CHECK-NEXT: 0x0000000000000000 NULL 0x0 // CHECK-NEXT: ] Index: test/ELF/shared.s =================================================================== --- test/ELF/shared.s +++ test/ELF/shared.s @@ -243,6 +243,8 @@ // CHECK: DynamicSection [ // CHECK-NEXT: Tag Type Name/Value +// CHECK-NEXT: 0x0000001D RUNPATH foo:bar +// CHECK-NEXT: 0x00000001 NEEDED SharedLibrary ({{.*}}2.so) // CHECK-NEXT: 0x00000011 REL [[RELADDR]] // CHECK-NEXT: 0x00000012 RELSZ [[RELSIZE]] (bytes) // CHECK-NEXT: 0x00000013 RELENT [[RELENT]] (bytes) @@ -251,8 +253,6 @@ // CHECK-NEXT: 0x00000005 STRTAB [[DYNSTRADDR]] // CHECK-NEXT: 0x0000000A STRSZ // CHECK-NEXT: 0x00000004 HASH [[HASHADDR]] -// CHECK-NEXT: 0x0000001D RUNPATH foo:bar -// CHECK-NEXT: 0x00000001 NEEDED SharedLibrary ({{.*}}2.so) // CHECK-NEXT: 0x00000015 DEBUG 0x0 // CHECK-NEXT: 0x00000000 NULL 0x0 // CHECK-NEXT: ] Index: test/ELF/string-table.s =================================================================== --- test/ELF/string-table.s +++ test/ELF/string-table.s @@ -59,9 +59,8 @@ // CHECK-NEXT: EntrySize: 0 // CHECK-NEXT: SectionData ( // CHECK-NEXT: 0000: 00626172 002E7465 78740066 6F6F6261 |.bar..text.fooba| -// CHECK-NEXT: 0010: 7200666F 6F626172 00666F6F 62617200 |r.foobar.foobar.| -// CHECK-NEXT: 0020: 2E73796D 74616200 2E736873 74727461 |.symtab..shstrta| -// CHECK-NEXT: 0030: 62002E73 74727461 6200 |b..strtab.| +// CHECK-NEXT: 0010: 72002E73 796D7461 62002E73 68737472 |r..symtab..shstr| +// CHECK-NEXT: 0020: 74616200 2E737472 74616200 |tab..strtab.| // CHECK-NEXT: ) // CHECK-NEXT:} // CHECK: Name: .strtab