Skip to content

Commit

Permalink
[ELF] - Simplify output section creation.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
George Rimar committed Oct 31, 2017
1 parent 06618bf commit f9b04fd
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 55 deletions.
54 changes: 30 additions & 24 deletions lld/ELF/LinkerScript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
Expand All @@ -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) {
Expand Down Expand Up @@ -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();
Expand Down
1 change: 0 additions & 1 deletion lld/ELF/LinkerScript.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,6 @@ class LinkerScript final {

ExprValue getSymbolValue(StringRef Name, const Twine &Loc);

void fabricateDefaultCommands();
void addOrphanSections(OutputSectionFactory &Factory);
void removeEmptyCommands();
void adjustSectionsBeforeSorting();
Expand Down
37 changes: 7 additions & 30 deletions lld/ELF/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ template <class ELFT> class Writer {
void copyLocalSymbols();
void addSectionSymbols();
void addReservedSymbols();
void createSections();
void forEachRelSec(std::function<void(InputSectionBase &)> Fn);
void sortSections();
void sortInputSections();
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit f9b04fd

Please sign in to comment.