diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2017-09-12 16:38:01 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2017-09-12 16:38:01 +0000 |
commit | 4d5601608dcc3df3ef0db126c55c402160fba040 (patch) | |
tree | ad255a96c8ed51d3a042947cfaa08063bfa3ad8b | |
parent | f696a22d3cea40534e7b14174998acf176a436d1 (diff) | |
download | bcm5719-llvm-4d5601608dcc3df3ef0db126c55c402160fba040.tar.gz bcm5719-llvm-4d5601608dcc3df3ef0db126c55c402160fba040.zip |
Simplify handling of predefined symbols.
Given our representation of symbols as section + offset, we can
finalize symbols like _end as soon as the section is known.
llvm-svn: 313048
-rw-r--r-- | lld/ELF/Writer.cpp | 117 |
1 files changed, 49 insertions, 68 deletions
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 276b815c79f..b9181736a5b 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -54,7 +54,7 @@ private: void sortSections(); void finalizeSections(); void addPredefinedSections(); - void addPredefinedSymbols(); + void setReservedSymbolSections(); std::vector<PhdrEntry *> createPhdrs(); void removeEmptyPTLoad(); @@ -63,7 +63,7 @@ private: void assignFileOffsetsBinary(); void setPhdrs(); void fixSectionAlignments(); - void fixPredefinedSymbols(); + void makeMipsGpAbs(); void openFile(); void writeTrapInstr(); void writeHeader(); @@ -198,12 +198,6 @@ template <class ELFT> void Writer<ELFT>::run() { parallelForEach(OutputSections, [](OutputSection *Sec) { Sec->maybeCompress<ELFT>(); }); - // Generate assignments for predefined symbols (e.g. _end or _etext) - // before assigning addresses. These symbols may be referred to from - // the linker script and we need to ensure they have the correct value - // prior evaluating any expressions using these symbols. - addPredefinedSymbols(); - Script->assignAddresses(); Script->allocateHeaders(Phdrs); @@ -223,7 +217,7 @@ template <class ELFT> void Writer<ELFT>::run() { for (OutputSection *Sec : OutputSections) Sec->Addr = 0; } else { - fixPredefinedSymbols(); + makeMipsGpAbs(); } // It does not make sense try to open the file if we have error already. @@ -846,11 +840,11 @@ template <class ELFT> void Writer<ELFT>::addReservedSymbols() { if (Script->Opt.HasSections) return; - auto Add = [](StringRef S) { - return addOptionalRegular<ELFT>(S, Out::ElfHeader, 0, STV_DEFAULT); + auto Add = [](StringRef S, int64_t Pos = -1) { + return addOptionalRegular<ELFT>(S, Out::ElfHeader, Pos, STV_DEFAULT); }; - ElfSym::Bss = Add("__bss_start"); + ElfSym::Bss = Add("__bss_start", 0); ElfSym::End1 = Add("end"); ElfSym::End2 = Add("_end"); ElfSym::Etext1 = Add("etext"); @@ -928,7 +922,7 @@ template <class ELFT> void Writer<ELFT>::createSections() { // appropriate time. This ensures that the value is going to be correct by the // time any references to these symbols are processed and is equivalent to // defining these symbols explicitly in the linker script. -template <class ELFT> void Writer<ELFT>::addPredefinedSymbols() { +template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() { PhdrEntry *Last = nullptr; PhdrEntry *LastRO = nullptr; PhdrEntry *LastRW = nullptr; @@ -943,58 +937,55 @@ template <class ELFT> void Writer<ELFT>::addPredefinedSymbols() { LastRO = P; } - auto Make = [](DefinedRegular *S) { - auto *Cmd = make<SymbolAssignment>( - S->getName(), [=] { return Script->getSymbolValue("", "."); }, ""); - Cmd->Sym = S; - return Cmd; - }; - - std::vector<BaseCommand *> &V = Script->Opt.Commands; - // _end is the first location after the uninitialized data region. if (Last) { - for (size_t I = 0; I < V.size(); ++I) { - if (V[I] != Last->LastSec) - continue; - if (ElfSym::End2) - V.insert(V.begin() + I + 1, Make(ElfSym::End2)); - if (ElfSym::End1) - V.insert(V.begin() + I + 1, Make(ElfSym::End1)); - break; - } + if (ElfSym::End1) + ElfSym::End1->Section = Last->LastSec; + if (ElfSym::End2) + ElfSym::End2->Section = Last->LastSec; } // _etext is the first location after the last read-only loadable segment. if (LastRO) { - for (size_t I = 0; I < V.size(); ++I) { - if (V[I] != LastRO->LastSec) - continue; - if (ElfSym::Etext2) - V.insert(V.begin() + I + 1, Make(ElfSym::Etext2)); - if (ElfSym::Etext1) - V.insert(V.begin() + I + 1, Make(ElfSym::Etext1)); - break; - } + if (ElfSym::Etext1) + ElfSym::Etext1->Section = LastRO->LastSec; + if (ElfSym::Etext2) + ElfSym::Etext2->Section = LastRO->LastSec; } // _edata points to the end of the last non SHT_NOBITS section. if (LastRW) { size_t I = 0; - for (; I < V.size(); ++I) - if (V[I] == LastRW->FirstSec) + for (; I < OutputSections.size(); ++I) + if (OutputSections[I] == LastRW->FirstSec) break; - for (; I < V.size(); ++I) { - auto *Sec = dyn_cast<OutputSection>(V[I]); - if (!Sec || Sec->Type != SHT_NOBITS) + for (; I < OutputSections.size(); ++I) { + if (OutputSections[I]->Type != SHT_NOBITS) continue; - if (ElfSym::Edata2) - V.insert(V.begin() + I, Make(ElfSym::Edata2)); - if (ElfSym::Edata1) - V.insert(V.begin() + I, Make(ElfSym::Edata1)); break; } + if (ElfSym::Edata1) + ElfSym::Edata1->Section = OutputSections[I - 1]; + if (ElfSym::Edata2) + ElfSym::Edata2->Section = OutputSections[I - 1]; + } + + if (ElfSym::Bss) + ElfSym::Bss->Section = findSection(".bss"); + + // Setup MIPS _gp_disp/__gnu_local_gp symbols which should + // be equal to the _gp symbol's value. + if (ElfSym::MipsGp && !ElfSym::MipsGp->Value) { + // Find GP-relative section with the lowest address + // and use this address to calculate default _gp value. + for (OutputSection *OS : OutputSections) { + if (OS->Flags & SHF_MIPS_GPREL) { + ElfSym::MipsGp->Section = OS; + ElfSym::MipsGp->Value = 0x7ff0; + break; + } + } } } @@ -1360,6 +1351,10 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { Out::ProgramHeaders->Size = sizeof(Elf_Phdr) * Phdrs.size(); } + // Some symbols are defined in term of program headers. Now that we + // have the headers, we can find out which sections they point to. + setReservedSymbolSections(); + // Dynamic section must be the last one in this list and dynamic // symbol table section (DynSymTab) must be the first one. applySynthetic({InX::DynSymTab, InX::Bss, @@ -1790,25 +1785,11 @@ static uint16_t getELFType() { return ET_EXEC; } -// This function is called after we have assigned address and size -// to each section. This function fixes some predefined -// symbol values that depend on section address and size. -template <class ELFT> void Writer<ELFT>::fixPredefinedSymbols() { - if (ElfSym::Bss) - ElfSym::Bss->Section = findSection(".bss"); - - // Setup MIPS _gp_disp/__gnu_local_gp symbols which should - // be equal to the _gp symbol's value. - if (Config->EMachine == EM_MIPS && !ElfSym::MipsGp->Value) { - // Find GP-relative section with the lowest address - // and use this address to calculate default _gp value. - for (const OutputSection *Cmd : OutputSections) { - const OutputSection *OS = Cmd; - if (OS->Flags & SHF_MIPS_GPREL) { - ElfSym::MipsGp->Value = OS->Addr + 0x7ff0; - break; - } - } +// For some reason we have to make the mips gp symbol absolute. +template <class ELFT> void Writer<ELFT>::makeMipsGpAbs() { + if (ElfSym::MipsGp && ElfSym::MipsGp->Section) { + ElfSym::MipsGp->Value += cast<OutputSection>(ElfSym::MipsGp->Section)->Addr; + ElfSym::MipsGp->Section = nullptr; } } |