diff options
-rw-r--r-- | lld/ELF/LinkerScript.cpp | 54 | ||||
-rw-r--r-- | lld/ELF/LinkerScript.h | 1 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 37 |
3 files changed, 37 insertions, 55 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index ccf86e46b8e..e8c377cb181 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -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(); diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index 4851c1160a1..478405d463f 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -250,7 +250,6 @@ public: ExprValue getSymbolValue(StringRef Name, const Twine &Loc); - void fabricateDefaultCommands(); void addOrphanSections(OutputSectionFactory &Factory); void removeEmptyCommands(); void adjustSectionsBeforeSorting(); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 497b7573214..d9040602674 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -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 |