[lld] r313048 - Simplify handling of predefined symbols.
Rafael Espindola via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 12 09:38:01 PDT 2017
Author: rafael
Date: Tue Sep 12 09:38:01 2017
New Revision: 313048
URL: http://llvm.org/viewvc/llvm-project?rev=313048&view=rev
Log:
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.
Modified:
lld/trunk/ELF/Writer.cpp
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=313048&r1=313047&r2=313048&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Tue Sep 12 09:38:01 2017
@@ -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>:
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>:
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>:
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>:
// 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>:
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>:
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;
}
}
More information about the llvm-commits
mailing list