diff options
-rw-r--r-- | lld/ELF/Driver.cpp | 2 | ||||
-rw-r--r-- | lld/ELF/LinkerScript.cpp | 92 | ||||
-rw-r--r-- | lld/ELF/LinkerScript.h | 19 |
3 files changed, 32 insertions, 81 deletions
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 45c6b1b96c0..22482eb237e 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -569,7 +569,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { std::unique_ptr<TargetInfo> TI(createTarget()); Target = TI.get(); LinkerScript<ELFT> LS; - Script<ELFT>::X = &LS; + ScriptBase = Script<ELFT>::X = &LS; Config->Rela = ELFT::Is64Bits || Config->EMachine == EM_X86_64; Config->Mips64EL = diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index a6fbe64d5ee..d1cfd569ada 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -41,6 +41,7 @@ using namespace llvm::object; using namespace lld; using namespace lld::elf; +LinkerScriptBase *elf::ScriptBase; ScriptConfiguration *elf::ScriptConfig; template <class ELFT> @@ -556,8 +557,7 @@ template <class ELFT> bool LinkerScript<ELFT>::hasPhdrsCommands() { } template <class ELFT> -typename ELFT::uint -LinkerScript<ELFT>::getOutputSectionAddress(StringRef Name) { +uint64_t LinkerScript<ELFT>::getOutputSectionAddress(StringRef Name) { for (OutputSectionBase<ELFT> *Sec : *OutputSections) if (Sec->getName() == Name) return Sec->getVA(); @@ -566,7 +566,7 @@ LinkerScript<ELFT>::getOutputSectionAddress(StringRef Name) { } template <class ELFT> -typename ELFT::uint LinkerScript<ELFT>::getOutputSectionSize(StringRef Name) { +uint64_t LinkerScript<ELFT>::getOutputSectionSize(StringRef Name) { for (OutputSectionBase<ELFT> *Sec : *OutputSections) if (Sec->getName() == Name) return Sec->getSize(); @@ -574,11 +574,17 @@ typename ELFT::uint LinkerScript<ELFT>::getOutputSectionSize(StringRef Name) { return 0; } -template <class ELFT> -typename ELFT::uint LinkerScript<ELFT>::getHeaderSize() { +template <class ELFT> uint64_t LinkerScript<ELFT>::getHeaderSize() { return Out<ELFT>::ElfHeader->getSize() + Out<ELFT>::ProgramHeaders->getSize(); } +template <class ELFT> uint64_t LinkerScript<ELFT>::getSymbolValue(StringRef S) { + if (SymbolBody *B = Symtab<ELFT>::X->find(S)) + return B->getVA<ELFT>(); + error("symbol not found: " + S); + return 0; +} + // Returns indices of ELF headers containing specific section, identified // by Name. Each index is a zero based number of ELF header listed within // PHDRS {} script block. @@ -1099,74 +1105,7 @@ SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok, static uint64_t getSymbolValue(StringRef S, uint64_t Dot) { if (S == ".") return Dot; - - switch (Config->EKind) { - case ELF32LEKind: - if (SymbolBody *B = Symtab<ELF32LE>::X->find(S)) - return B->getVA<ELF32LE>(); - break; - case ELF32BEKind: - if (SymbolBody *B = Symtab<ELF32BE>::X->find(S)) - return B->getVA<ELF32BE>(); - break; - case ELF64LEKind: - if (SymbolBody *B = Symtab<ELF64LE>::X->find(S)) - return B->getVA<ELF64LE>(); - break; - case ELF64BEKind: - if (SymbolBody *B = Symtab<ELF64BE>::X->find(S)) - return B->getVA<ELF64BE>(); - break; - default: - llvm_unreachable("unsupported target"); - } - error("symbol not found: " + S); - return 0; -} - -static uint64_t getSectionSize(StringRef Name) { - switch (Config->EKind) { - case ELF32LEKind: - return Script<ELF32LE>::X->getOutputSectionSize(Name); - case ELF32BEKind: - return Script<ELF32BE>::X->getOutputSectionSize(Name); - case ELF64LEKind: - return Script<ELF64LE>::X->getOutputSectionSize(Name); - case ELF64BEKind: - return Script<ELF64BE>::X->getOutputSectionSize(Name); - default: - llvm_unreachable("unsupported target"); - } -} - -static uint64_t getSectionAddress(StringRef Name) { - switch (Config->EKind) { - case ELF32LEKind: - return Script<ELF32LE>::X->getOutputSectionAddress(Name); - case ELF32BEKind: - return Script<ELF32BE>::X->getOutputSectionAddress(Name); - case ELF64LEKind: - return Script<ELF64LE>::X->getOutputSectionAddress(Name); - case ELF64BEKind: - return Script<ELF64BE>::X->getOutputSectionAddress(Name); - default: - llvm_unreachable("unsupported target"); - } -} - -static uint64_t getHeaderSize() { - switch (Config->EKind) { - case ELF32LEKind: - return Script<ELF32LE>::X->getHeaderSize(); - case ELF32BEKind: - return Script<ELF32BE>::X->getHeaderSize(); - case ELF64LEKind: - return Script<ELF64LE>::X->getHeaderSize(); - case ELF64BEKind: - return Script<ELF64BE>::X->getHeaderSize(); - default: - llvm_unreachable("unsupported target"); - } + return ScriptBase->getSymbolValue(S); } SymbolAssignment *ScriptParser::readAssignment(StringRef Name) { @@ -1314,7 +1253,8 @@ Expr ScriptParser::readPrimary() { expect("("); StringRef Name = next(); expect(")"); - return [=](uint64_t Dot) { return getSectionAddress(Name); }; + return + [=](uint64_t Dot) { return ScriptBase->getOutputSectionAddress(Name); }; } if (Tok == "ASSERT") return readAssert(); @@ -1366,10 +1306,10 @@ Expr ScriptParser::readPrimary() { expect("("); StringRef Name = next(); expect(")"); - return [=](uint64_t Dot) { return getSectionSize(Name); }; + return [=](uint64_t Dot) { return ScriptBase->getOutputSectionSize(Name); }; } if (Tok == "SIZEOF_HEADERS") - return [=](uint64_t Dot) { return getHeaderSize(); }; + return [=](uint64_t Dot) { return ScriptBase->getHeaderSize(); }; // Tok is a literal number. uint64_t V; diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index b27d1da225b..5b4032467fe 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -123,6 +123,14 @@ struct PhdrsCommand { unsigned Flags; }; +class LinkerScriptBase { +public: + virtual uint64_t getOutputSectionAddress(StringRef Name) = 0; + virtual uint64_t getOutputSectionSize(StringRef Name) = 0; + virtual uint64_t getHeaderSize() = 0; + virtual uint64_t getSymbolValue(StringRef S) = 0; +}; + // ScriptConfiguration holds linker script parse results. struct ScriptConfiguration { // Used to create symbol assignments outside SECTIONS command. @@ -145,7 +153,7 @@ struct ScriptConfiguration { extern ScriptConfiguration *ScriptConfig; // This is a runner of the linker script. -template <class ELFT> class LinkerScript { +template <class ELFT> class LinkerScript final : public LinkerScriptBase { typedef typename ELFT::uint uintX_t; public: @@ -163,9 +171,10 @@ public: void assignAddresses(); int compareSections(StringRef A, StringRef B); bool hasPhdrsCommands(); - uintX_t getOutputSectionAddress(StringRef Name); - uintX_t getOutputSectionSize(StringRef Name); - uintX_t getHeaderSize(); + uint64_t getOutputSectionAddress(StringRef Name) override; + uint64_t getOutputSectionSize(StringRef Name) override; + uint64_t getHeaderSize() override; + uint64_t getSymbolValue(StringRef S) override; std::vector<OutputSectionBase<ELFT> *> *OutputSections; @@ -193,6 +202,8 @@ private: template <class ELFT> struct Script { static LinkerScript<ELFT> *X; }; template <class ELFT> LinkerScript<ELFT> *Script<ELFT>::X; +extern LinkerScriptBase *ScriptBase; + } // namespace elf } // namespace lld |