forked from OSchip/llvm-project
[ELF] - Simplify output section creation.
When there is no SECTION commands given, all sections are technically orphans, but now we handle script orphans sections and regular "orphans" sections for non-scripted case differently, though we can handle them at one place. Patch do that change. Differential revision: https://reviews.llvm.org/D39045 llvm-svn: 316984
This commit is contained in:
parent
06618bf71a
commit
f9b04fd91f
|
@ -426,25 +426,6 @@ void LinkerScript::processSectionCommands() {
|
|||
}
|
||||
}
|
||||
|
||||
// If no SECTIONS command was given, we create simple SectionCommands
|
||||
// as if a minimum SECTIONS command were given. This function does that.
|
||||
void LinkerScript::fabricateDefaultCommands() {
|
||||
// Define start address
|
||||
uint64_t StartAddr = UINT64_MAX;
|
||||
|
||||
// The Sections with -T<section> have been sorted in order of ascending
|
||||
// address. We must lower StartAddr if the lowest -T<section address> as
|
||||
// calls to setDot() must be monotonically increasing.
|
||||
for (auto &KV : Config->SectionStartMap)
|
||||
StartAddr = std::min(StartAddr, KV.second);
|
||||
|
||||
auto Expr = [=] {
|
||||
return std::min(StartAddr, Target->getImageBase() + elf::getHeaderSize());
|
||||
};
|
||||
SectionCommands.insert(SectionCommands.begin(),
|
||||
make<SymbolAssignment>(".", Expr, ""));
|
||||
}
|
||||
|
||||
static OutputSection *findByName(ArrayRef<BaseCommand *> Vec,
|
||||
StringRef Name) {
|
||||
for (BaseCommand *Base : Vec)
|
||||
|
@ -465,6 +446,7 @@ static void reportOrphan(InputSectionBase *IS, StringRef Name) {
|
|||
void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) {
|
||||
unsigned End = SectionCommands.size();
|
||||
|
||||
std::vector<OutputSection *> V;
|
||||
for (InputSectionBase *S : InputSections) {
|
||||
if (!S->Live || S->Parent)
|
||||
continue;
|
||||
|
@ -479,9 +461,18 @@ void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) {
|
|||
}
|
||||
|
||||
if (OutputSection *OS = Factory.addInputSec(S, Name))
|
||||
SectionCommands.push_back(OS);
|
||||
V.push_back(OS);
|
||||
assert(S->getOutputSection()->SectionIndex == INT_MAX);
|
||||
}
|
||||
|
||||
// If no SECTIONS command was given, we should insert sections commands
|
||||
// before others, so that we can handle scripts which refers them,
|
||||
// for example: "foo = ABSOLUTE(ADDR(.text)));".
|
||||
// When SECTIONS command is present we just add all orphans to the end.
|
||||
if (HasSectionsCommand)
|
||||
SectionCommands.insert(SectionCommands.end(), V.begin(), V.end());
|
||||
else
|
||||
SectionCommands.insert(SectionCommands.begin(), V.begin(), V.end());
|
||||
}
|
||||
|
||||
uint64_t LinkerScript::advance(uint64_t Size, unsigned Alignment) {
|
||||
|
@ -802,11 +793,26 @@ LinkerScript::AddressState::AddressState() {
|
|||
}
|
||||
}
|
||||
|
||||
// Assign addresses as instructed by linker script SECTIONS sub-commands.
|
||||
static uint64_t getInitialDot() {
|
||||
// By default linker scripts use an initial value of 0 for '.',
|
||||
// but prefer -image-base if set.
|
||||
if (Script->HasSectionsCommand)
|
||||
return Config->ImageBase ? *Config->ImageBase : 0;
|
||||
|
||||
uint64_t StartAddr = UINT64_MAX;
|
||||
// The Sections with -T<section> have been sorted in order of ascending
|
||||
// address. We must lower StartAddr if the lowest -T<section address> as
|
||||
// calls to setDot() must be monotonically increasing.
|
||||
for (auto &KV : Config->SectionStartMap)
|
||||
StartAddr = std::min(StartAddr, KV.second);
|
||||
return std::min(StartAddr, Target->getImageBase() + elf::getHeaderSize());
|
||||
}
|
||||
|
||||
// Here we assign addresses as instructed by linker script SECTIONS
|
||||
// sub-commands. Doing that allows us to use final VA values, so here
|
||||
// we also handle rest commands like symbol assignments and ASSERTs.
|
||||
void LinkerScript::assignAddresses() {
|
||||
// By default linker scripts use an initial value of 0 for '.', but prefer
|
||||
// -image-base if set.
|
||||
Dot = Config->ImageBase ? *Config->ImageBase : 0;
|
||||
Dot = getInitialDot();
|
||||
|
||||
auto Deleter = make_unique<AddressState>();
|
||||
Ctx = Deleter.get();
|
||||
|
|
|
@ -250,7 +250,6 @@ public:
|
|||
|
||||
ExprValue getSymbolValue(StringRef Name, const Twine &Loc);
|
||||
|
||||
void fabricateDefaultCommands();
|
||||
void addOrphanSections(OutputSectionFactory &Factory);
|
||||
void removeEmptyCommands();
|
||||
void adjustSectionsBeforeSorting();
|
||||
|
|
|
@ -49,7 +49,6 @@ private:
|
|||
void copyLocalSymbols();
|
||||
void addSectionSymbols();
|
||||
void addReservedSymbols();
|
||||
void createSections();
|
||||
void forEachRelSec(std::function<void(InputSectionBase &)> Fn);
|
||||
void sortSections();
|
||||
void sortInputSections();
|
||||
|
@ -169,22 +168,14 @@ template <class ELFT> void Writer<ELFT>::run() {
|
|||
if (!Config->Relocatable)
|
||||
addReservedSymbols();
|
||||
|
||||
// Create output sections.
|
||||
if (Script->HasSectionsCommand) {
|
||||
// If linker script contains SECTIONS commands, let it create sections.
|
||||
Script->processSectionCommands();
|
||||
// We want to process linker script commands. When SECTIONS command
|
||||
// is given we let it create sections.
|
||||
Script->processSectionCommands();
|
||||
|
||||
// Linker scripts may have left some input sections unassigned.
|
||||
// Assign such sections using the default rule.
|
||||
Script->addOrphanSections(Factory);
|
||||
} else {
|
||||
// If linker script does not contain SECTIONS commands, create
|
||||
// output sections by default rules. We still need to give the
|
||||
// linker script a chance to run, because it might contain
|
||||
// non-SECTIONS commands such as ASSERT.
|
||||
Script->processSectionCommands();
|
||||
createSections();
|
||||
}
|
||||
// Linker scripts controls how input sections are assigned to output sections.
|
||||
// Input sections that were not handled by scripts are called "orphans", and
|
||||
// they are assigned to output sections by the default rule. Process that.
|
||||
Script->addOrphanSections(Factory);
|
||||
|
||||
if (Config->Discard != DiscardPolicy::All)
|
||||
copyLocalSymbols();
|
||||
|
@ -852,20 +843,6 @@ void Writer<ELFT>::forEachRelSec(std::function<void(InputSectionBase &)> Fn) {
|
|||
Fn(*ES);
|
||||
}
|
||||
|
||||
template <class ELFT> void Writer<ELFT>::createSections() {
|
||||
std::vector<OutputSection *> Vec;
|
||||
for (InputSectionBase *IS : InputSections)
|
||||
if (IS && IS->Live)
|
||||
if (OutputSection *Sec =
|
||||
Factory.addInputSec(IS, getOutputSectionName(IS->Name)))
|
||||
Vec.push_back(Sec);
|
||||
|
||||
Script->SectionCommands.insert(Script->SectionCommands.begin(), Vec.begin(),
|
||||
Vec.end());
|
||||
|
||||
Script->fabricateDefaultCommands();
|
||||
}
|
||||
|
||||
// This function generates assignments for predefined symbols (e.g. _end or
|
||||
// _etext) and inserts them into the commands sequence to be processed at the
|
||||
// appropriate time. This ensures that the value is going to be correct by the
|
||||
|
|
Loading…
Reference in New Issue