diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-12-24 01:00:50 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-12-24 01:00:50 +0000 |
commit | 0d9ba4fe26725cacc7253fc3c72c4574f26bc099 (patch) | |
tree | 90c426d54188ca226b29aaf8a308bba364a73d1a /ELF/Writer.cpp | |
parent | eb1ff93d02b5f17b6b409e83c6d9be585f4a04b3 (diff) | |
download | src-0d9ba4fe26725cacc7253fc3c72c4574f26bc099.tar.gz src-0d9ba4fe26725cacc7253fc3c72c4574f26bc099.zip |
Vendor import of lld trunk r321414:vendor/lld/lld-trunk-r321414
Notes
Notes:
svn path=/vendor/lld/dist/; revision=327130
svn path=/vendor/lld/lld-trunk-r321414/; revision=327131; tag=vendor/lld/lld-trunk-r321414
Diffstat (limited to 'ELF/Writer.cpp')
-rw-r--r-- | ELF/Writer.cpp | 118 |
1 files changed, 59 insertions, 59 deletions
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp index c7a3cae49ae6..15f382104756 100644 --- a/ELF/Writer.cpp +++ b/ELF/Writer.cpp @@ -54,7 +54,6 @@ private: void resolveShfLinkOrder(); void sortInputSections(); void finalizeSections(); - void addPredefinedSections(); void setReservedSymbolSections(); std::vector<PhdrEntry *> createPhdrs(); @@ -157,35 +156,34 @@ template <class ELFT> static void combineEhFrameSections() { V.erase(std::remove(V.begin(), V.end(), nullptr), V.end()); } -template <class ELFT> static Defined *addOptionalRegular(StringRef Name, SectionBase *Sec, uint64_t Val, uint8_t StOther = STV_HIDDEN, uint8_t Binding = STB_GLOBAL) { Symbol *S = Symtab->find(Name); if (!S || S->isDefined()) return nullptr; - Symbol *Sym = Symtab->addRegular<ELFT>(Name, StOther, STT_NOTYPE, Val, - /*Size=*/0, Binding, Sec, - /*File=*/nullptr); + Symbol *Sym = Symtab->addRegular(Name, StOther, STT_NOTYPE, Val, + /*Size=*/0, Binding, Sec, + /*File=*/nullptr); return cast<Defined>(Sym); } // The linker is expected to define some symbols depending on // the linking result. This function defines such symbols. -template <class ELFT> void elf::addReservedSymbols() { +void elf::addReservedSymbols() { if (Config->EMachine == EM_MIPS) { // Define _gp for MIPS. st_value of _gp symbol will be updated by Writer // so that it points to an absolute address which by default is relative // to GOT. Default offset is 0x7ff0. // See "Global Data Symbols" in Chapter 6 in the following document: // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf - ElfSym::MipsGp = Symtab->addAbsolute<ELFT>("_gp", STV_HIDDEN, STB_GLOBAL); + ElfSym::MipsGp = Symtab->addAbsolute("_gp", STV_HIDDEN, STB_GLOBAL); // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between // start of function and 'gp' pointer into GOT. if (Symtab->find("_gp_disp")) ElfSym::MipsGpDisp = - Symtab->addAbsolute<ELFT>("_gp_disp", STV_HIDDEN, STB_GLOBAL); + Symtab->addAbsolute("_gp_disp", STV_HIDDEN, STB_GLOBAL); // The __gnu_local_gp is a magic symbol equal to the current value of 'gp' // pointer. This symbol is used in the code generated by .cpload pseudo-op @@ -193,10 +191,10 @@ template <class ELFT> void elf::addReservedSymbols() { // https://sourceware.org/ml/binutils/2004-12/msg00094.html if (Symtab->find("__gnu_local_gp")) ElfSym::MipsLocalGp = - Symtab->addAbsolute<ELFT>("__gnu_local_gp", STV_HIDDEN, STB_GLOBAL); + Symtab->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_GLOBAL); } - ElfSym::GlobalOffsetTable = addOptionalRegular<ELFT>( + ElfSym::GlobalOffsetTable = addOptionalRegular( "_GLOBAL_OFFSET_TABLE_", Out::ElfHeader, Target->GotBaseSymOff); // __ehdr_start is the location of ELF file headers. Note that we define @@ -210,14 +208,14 @@ template <class ELFT> void elf::addReservedSymbols() { // different in different DSOs, so we chose the start address of the DSO. for (const char *Name : {"__ehdr_start", "__executable_start", "__dso_handle"}) - addOptionalRegular<ELFT>(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<ELFT>(S, Out::ElfHeader, Pos, STV_DEFAULT); + return addOptionalRegular(S, Out::ElfHeader, Pos, STV_DEFAULT); }; ElfSym::Bss = Add("__bss_start", 0); @@ -390,6 +388,11 @@ template <class ELFT> static void createSyntheticSections() { Add(InX::ShStrTab); if (InX::StrTab) Add(InX::StrTab); + + if (Config->EMachine == EM_ARM && !Config->Relocatable) + // Add a sentinel to terminate .ARM.exidx. It helps an unwinder + // to find the exact address range of the last entry. + Add(make<ARMExidxSentinelSection>()); } // The main function of the writer. @@ -830,10 +833,10 @@ template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() { if (!Config->Static) return; StringRef S = Config->IsRela ? "__rela_iplt_start" : "__rel_iplt_start"; - addOptionalRegular<ELFT>(S, InX::RelaIplt, 0, STV_HIDDEN, STB_WEAK); + addOptionalRegular(S, InX::RelaIplt, 0, STV_HIDDEN, STB_WEAK); S = Config->IsRela ? "__rela_iplt_end" : "__rel_iplt_end"; - addOptionalRegular<ELFT>(S, InX::RelaIplt, -1, STV_HIDDEN, STB_WEAK); + addOptionalRegular(S, InX::RelaIplt, -1, STV_HIDDEN, STB_WEAK); } template <class ELFT> @@ -1145,10 +1148,10 @@ template <class ELFT> void Writer<ELFT>::sortSections() { } static bool compareByFilePosition(InputSection *A, InputSection *B) { - // Synthetic doesn't have link order dependecy, stable_sort will keep it last + // Synthetic, i. e. a sentinel section, should go last. if (A->kind() == InputSectionBase::Synthetic || B->kind() == InputSectionBase::Synthetic) - return false; + return A->kind() != InputSectionBase::Synthetic; InputSection *LA = A->getLinkOrderDep(); InputSection *LB = B->getLinkOrderDep(); OutputSection *AOut = LA->getParent(); @@ -1231,23 +1234,37 @@ template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() { } std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition); - if (Config->MergeArmExidx && !Config->Relocatable && - Config->EMachine == EM_ARM && Sec->Type == SHT_ARM_EXIDX) { - // The EHABI for the Arm Architecture permits consecutive identical - // table entries to be merged. We use a simple implementation that - // removes a .ARM.exidx Input Section if it can be merged into the - // previous one. This does not require any rewriting of InputSection - // contents but misses opportunities for fine grained deduplication where - // only a subset of the InputSection contents can be merged. - int Cur = 1; - int Prev = 0; - int N = Sections.size(); - while (Cur < N) { - if (isDuplicateArmExidxSec(Sections[Prev], Sections[Cur])) - Sections[Cur] = nullptr; - else - Prev = Cur; - ++Cur; + if (!Config->Relocatable && Config->EMachine == EM_ARM && + Sec->Type == SHT_ARM_EXIDX) { + + if (!Sections.empty() && isa<ARMExidxSentinelSection>(Sections.back())) { + assert(Sections.size() >= 2 && + "We should create a sentinel section only if there are " + "alive regular exidx sections."); + // The last executable section is required to fill the sentinel. + // Remember it here so that we don't have to find it again. + auto *Sentinel = cast<ARMExidxSentinelSection>(Sections.back()); + Sentinel->Highest = Sections[Sections.size() - 2]->getLinkOrderDep(); + } + + if (Config->MergeArmExidx) { + // The EHABI for the Arm Architecture permits consecutive identical + // table entries to be merged. We use a simple implementation that + // removes a .ARM.exidx Input Section if it can be merged into the + // previous one. This does not require any rewriting of InputSection + // contents but misses opportunities for fine grained deduplication + // where only a subset of the InputSection contents can be merged. + int Cur = 1; + int Prev = 0; + // The last one is a sentinel entry which should not be removed. + int N = Sections.size() - 1; + while (Cur < N) { + if (isDuplicateArmExidxSec(Sections[Prev], Sections[Cur])) + Sections[Cur] = nullptr; + else + Prev = Cur; + ++Cur; + } } } @@ -1367,9 +1384,9 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { // 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<ELFT>("_DYNAMIC", STV_HIDDEN, STT_NOTYPE, 0 /*Value*/, - /*Size=*/0, STB_WEAK, InX::Dynamic, - /*File=*/nullptr); + Symtab->addRegular("_DYNAMIC", STV_HIDDEN, STT_NOTYPE, 0 /*Value*/, + /*Size=*/0, STB_WEAK, InX::Dynamic, + /*File=*/nullptr); // Define __rel[a]_iplt_{start,end} symbols if needed. addRelIpltSymbols(); @@ -1413,7 +1430,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { if (errorCount()) return; - addPredefinedSections(); removeUnusedSyntheticSections(); sortSections(); @@ -1510,17 +1526,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { [](SyntheticSection *SS) { SS->postThunkContents(); }); } -template <class ELFT> void Writer<ELFT>::addPredefinedSections() { - // ARM ABI requires .ARM.exidx to be terminated by some piece of data. - // We have the terminater synthetic section class. Add that at the end. - OutputSection *Cmd = findSection(".ARM.exidx"); - if (!Cmd || !Cmd->Live || Config->Relocatable) - return; - - auto *Sentinel = make<ARMExidxSentinelSection>(); - Cmd->addSection(Sentinel); -} - // The linker is expected to define SECNAME_start and SECNAME_end // symbols for a few sections. This function defines them. template <class ELFT> void Writer<ELFT>::addStartEndSymbols() { @@ -1528,13 +1533,13 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() { // 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<ELFT>(Start, OS, 0); - addOptionalRegular<ELFT>(End, OS, -1); + addOptionalRegular(Start, OS, 0); + addOptionalRegular(End, OS, -1); } else { if (Config->Pic) OS = Out::ElfHeader; - addOptionalRegular<ELFT>(Start, OS, 0); - addOptionalRegular<ELFT>(End, OS, 0); + addOptionalRegular(Start, OS, 0); + addOptionalRegular(End, OS, 0); } }; @@ -1556,8 +1561,8 @@ void Writer<ELFT>::addStartStopSymbols(OutputSection *Sec) { StringRef S = Sec->Name; if (!isValidCIdentifier(S)) return; - addOptionalRegular<ELFT>(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT); - addOptionalRegular<ELFT>(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); } static bool needsPtLoad(OutputSection *Sec) { @@ -2057,8 +2062,3 @@ template void elf::writeResult<ELF32LE>(); template void elf::writeResult<ELF32BE>(); template void elf::writeResult<ELF64LE>(); template void elf::writeResult<ELF64BE>(); - -template void elf::addReservedSymbols<ELF32LE>(); -template void elf::addReservedSymbols<ELF32BE>(); -template void elf::addReservedSymbols<ELF64LE>(); -template void elf::addReservedSymbols<ELF64BE>(); |