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
This commit is contained in:
Rafael Espindola 2017-09-12 16:38:01 +00:00
parent f696a22d3c
commit 4d5601608d
1 changed files with 49 additions and 68 deletions

View File

@ -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;
}
}