diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:12:21 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:12:21 +0000 |
commit | eb1ff93d02b5f17b6b409e83c6d9be585f4a04b3 (patch) | |
tree | 7490b4a8943293f251ad733465936e6ec302b3e9 /ELF/LinkerScript.h | |
parent | bafea25f368c63f0b39789906adfed6e39219e64 (diff) | |
download | src-eb1ff93d02b5f17b6b409e83c6d9be585f4a04b3.tar.gz src-eb1ff93d02b5f17b6b409e83c6d9be585f4a04b3.zip |
Vendor import of lld trunk r321017:vendor/lld/lld-trunk-r321017
Notes
Notes:
svn path=/vendor/lld/dist/; revision=326947
svn path=/vendor/lld/lld-trunk-r321017/; revision=326948; tag=vendor/lld/lld-trunk-r321017
Diffstat (limited to 'ELF/LinkerScript.h')
-rw-r--r-- | ELF/LinkerScript.h | 211 |
1 files changed, 98 insertions, 113 deletions
diff --git a/ELF/LinkerScript.h b/ELF/LinkerScript.h index dd5a7d797f60..11131dda8e26 100644 --- a/ELF/LinkerScript.h +++ b/ELF/LinkerScript.h @@ -13,10 +13,11 @@ #include "Config.h" #include "Strings.h" #include "Writer.h" -#include "lld/Core/LLVM.h" +#include "lld/Common/LLVM.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/MemoryBuffer.h" #include <cstddef> @@ -28,31 +29,39 @@ namespace lld { namespace elf { -class DefinedCommon; -class SymbolBody; +class Defined; +class Symbol; class InputSectionBase; class InputSection; class OutputSection; -class OutputSectionFactory; class InputSectionBase; class SectionBase; +// This represents an r-value in the linker script. struct ExprValue { - SectionBase *Sec; - uint64_t Val; - bool ForceAbsolute; - uint64_t Alignment = 1; - std::string Loc; - ExprValue(SectionBase *Sec, bool ForceAbsolute, uint64_t Val, const Twine &Loc) - : Sec(Sec), Val(Val), ForceAbsolute(ForceAbsolute), Loc(Loc.str()) {} - ExprValue(SectionBase *Sec, uint64_t Val, const Twine &Loc) - : ExprValue(Sec, false, Val, Loc) {} - ExprValue(uint64_t Val) : ExprValue(nullptr, Val, "") {} + : Sec(Sec), ForceAbsolute(ForceAbsolute), Val(Val), Loc(Loc.str()) {} + + ExprValue(uint64_t Val) : ExprValue(nullptr, false, Val, "") {} + bool isAbsolute() const { return ForceAbsolute || Sec == nullptr; } uint64_t getValue() const; uint64_t getSecAddr() const; + uint64_t getSectionOffset() const; + + // If a value is relative to a section, it has a non-null Sec. + SectionBase *Sec; + + // True if this expression is enclosed in ABSOLUTE(). + // This flag affects the return value of getValue(). + bool ForceAbsolute; + + uint64_t Val; + uint64_t Alignment = 1; + + // Original source location. Used for error messages. + std::string Loc; }; // This represents an expression in the linker script. @@ -66,8 +75,8 @@ enum SectionsCommandKind { AssignmentKind, // . = expr or <sym> = expr OutputSectionKind, InputSectionKind, - AssertKind, // ASSERT(expr) - BytesDataKind // BYTE(expr), SHORT(expr), LONG(expr) or QUAD(expr) + AssertKind, // ASSERT(expr) + ByteKind // BYTE(expr), SHORT(expr), LONG(expr) or QUAD(expr) }; struct BaseCommand { @@ -80,11 +89,13 @@ struct SymbolAssignment : BaseCommand { SymbolAssignment(StringRef Name, Expr E, std::string Loc) : BaseCommand(AssignmentKind), Name(Name), Expression(E), Location(Loc) {} - static bool classof(const BaseCommand *C); + static bool classof(const BaseCommand *C) { + return C->Kind == AssignmentKind; + } // The LHS of an expression. Name is either a symbol name or ".". StringRef Name; - SymbolBody *Sym = nullptr; + Defined *Sym = nullptr; // The RHS of an expression. Expr Expression; @@ -114,37 +125,6 @@ struct MemoryRegion { uint32_t NegFlags; }; -struct OutputSectionCommand : BaseCommand { - OutputSectionCommand(StringRef Name) - : BaseCommand(OutputSectionKind), Name(Name) {} - - static bool classof(const BaseCommand *C); - - OutputSection *Sec = nullptr; - MemoryRegion *MemRegion = nullptr; - StringRef Name; - Expr AddrExpr; - Expr AlignExpr; - Expr LMAExpr; - Expr SubalignExpr; - std::vector<BaseCommand *> Commands; - std::vector<StringRef> Phdrs; - llvm::Optional<uint32_t> Filler; - ConstraintKind Constraint = ConstraintKind::NoConstraint; - std::string Location; - std::string MemoryRegionName; - bool Noload = false; - - template <class ELFT> void finalize(); - template <class ELFT> void writeTo(uint8_t *Buf); - template <class ELFT> void maybeCompress(); - uint32_t getFiller(); - - void sort(std::function<int(InputSectionBase *S)> Order); - void sortInitFini(); - void sortCtorsDtors(); -}; - // This struct represents one section match pattern in SECTIONS() command. // It can optionally have negative match pattern for EXCLUDED_FILE command. // Also it may be surrounded with SORT() command, so contains sorting rules. @@ -158,11 +138,14 @@ struct SectionPattern { SortSectionPolicy SortInner; }; +class ThunkSection; struct InputSectionDescription : BaseCommand { InputSectionDescription(StringRef FilePattern) : BaseCommand(InputSectionKind), FilePat(FilePattern) {} - static bool classof(const BaseCommand *C); + static bool classof(const BaseCommand *C) { + return C->Kind == InputSectionKind; + } StringMatcher FilePat; @@ -171,23 +154,28 @@ struct InputSectionDescription : BaseCommand { std::vector<SectionPattern> SectionPatterns; std::vector<InputSection *> Sections; + + // Temporary record of synthetic ThunkSection instances and the pass that + // they were created in. This is used to insert newly created ThunkSections + // into Sections at the end of a createThunks() pass. + std::vector<std::pair<ThunkSection *, uint32_t>> ThunkSections; }; // Represents an ASSERT(). struct AssertCommand : BaseCommand { AssertCommand(Expr E) : BaseCommand(AssertKind), Expression(E) {} - static bool classof(const BaseCommand *C); + static bool classof(const BaseCommand *C) { return C->Kind == AssertKind; } Expr Expression; }; // Represents BYTE(), SHORT(), LONG(), or QUAD(). -struct BytesDataCommand : BaseCommand { - BytesDataCommand(Expr E, unsigned Size) - : BaseCommand(BytesDataKind), Expression(E), Size(Size) {} +struct ByteCommand : BaseCommand { + ByteCommand(Expr E, unsigned Size) + : BaseCommand(ByteKind), Expression(E), Size(Size) {} - static bool classof(const BaseCommand *C); + static bool classof(const BaseCommand *C) { return C->Kind == ByteKind; } Expr Expression; unsigned Offset; @@ -196,106 +184,103 @@ struct BytesDataCommand : BaseCommand { struct PhdrsCommand { StringRef Name; - unsigned Type; - bool HasFilehdr; - bool HasPhdrs; - unsigned Flags; - Expr LMAExpr; -}; - -// ScriptConfiguration holds linker script parse results. -struct ScriptConfiguration { - // Used to assign addresses to sections. - std::vector<BaseCommand *> Commands; - - // Used to assign sections to headers. - std::vector<PhdrsCommand> PhdrsCommands; - - bool HasSections = false; - - // List of section patterns specified with KEEP commands. They will - // be kept even if they are unused and --gc-sections is specified. - std::vector<InputSectionDescription *> KeptSections; - - // A map from memory region name to a memory region descriptor. - llvm::DenseMap<llvm::StringRef, MemoryRegion> MemoryRegions; - - // A list of symbols referenced by the script. - std::vector<llvm::StringRef> ReferencedSymbols; + unsigned Type = llvm::ELF::PT_NULL; + bool HasFilehdr = false; + bool HasPhdrs = false; + llvm::Optional<unsigned> Flags; + Expr LMAExpr = nullptr; }; class LinkerScript final { - // Temporary state used in processCommands() and assignAddresses() + // Temporary state used in processSectionCommands() and assignAddresses() // that must be reinitialized for each call to the above functions, and must // not be used outside of the scope of a call to the above functions. struct AddressState { + AddressState(); uint64_t ThreadBssOffset = 0; OutputSection *OutSec = nullptr; MemoryRegion *MemRegion = nullptr; llvm::DenseMap<const MemoryRegion *, uint64_t> MemRegionOffset; std::function<uint64_t()> LMAOffset; - AddressState(const ScriptConfiguration &Opt); }; - llvm::DenseMap<OutputSection *, OutputSectionCommand *> SecToCommand; - llvm::DenseMap<StringRef, OutputSectionCommand *> NameToOutputSectionCommand; + llvm::DenseMap<StringRef, OutputSection *> NameToOutputSection; + + void addSymbol(SymbolAssignment *Cmd); void assignSymbol(SymbolAssignment *Cmd, bool InSec); void setDot(Expr E, const Twine &Loc, bool InSec); std::vector<InputSection *> - computeInputSections(const InputSectionDescription *); + computeInputSections(const InputSectionDescription *, + const llvm::DenseMap<SectionBase *, int> &Order); - std::vector<InputSectionBase *> - createInputSectionList(OutputSectionCommand &Cmd); + std::vector<InputSection *> + createInputSectionList(OutputSection &Cmd, + const llvm::DenseMap<SectionBase *, int> &Order); - std::vector<size_t> getPhdrIndices(OutputSectionCommand *Cmd); - size_t getPhdrIndex(const Twine &Loc, StringRef PhdrName); + std::vector<size_t> getPhdrIndices(OutputSection *Sec); - MemoryRegion *findMemoryRegion(OutputSectionCommand *Cmd); + MemoryRegion *findMemoryRegion(OutputSection *Sec); void switchTo(OutputSection *Sec); uint64_t advance(uint64_t Size, unsigned Align); void output(InputSection *Sec); - void process(BaseCommand &Base); - AddressState *CurAddressState = nullptr; + void assignOffsets(OutputSection *Sec); + + // Ctx captures the local AddressState and makes it accessible + // deliberately. This is needed as there are some cases where we cannot just + // thread the current state through to a lambda function created by the + // script parser. + // This should remain a plain pointer as its lifetime is smaller than + // LinkerScript. + AddressState *Ctx = nullptr; + OutputSection *Aether; uint64_t Dot; public: - bool ErrorOnMissingSection = false; - OutputSectionCommand *createOutputSectionCommand(StringRef Name, - StringRef Location); - OutputSectionCommand *getOrCreateOutputSectionCommand(StringRef Name); + OutputSection *createOutputSection(StringRef Name, StringRef Location); + OutputSection *getOrCreateOutputSection(StringRef Name); - OutputSectionCommand *getCmd(OutputSection *Sec) const; - bool hasPhdrsCommands() { return !Opt.PhdrsCommands.empty(); } + bool hasPhdrsCommands() { return !PhdrsCommands.empty(); } uint64_t getDot() { return Dot; } - void discard(ArrayRef<InputSectionBase *> V); + void discard(ArrayRef<InputSection *> V); - ExprValue getSymbolValue(const Twine &Loc, StringRef S); - bool isDefined(StringRef S); + ExprValue getSymbolValue(StringRef Name, const Twine &Loc); - void fabricateDefaultCommands(); - void addOrphanSections(OutputSectionFactory &Factory); + void addOrphanSections(); void removeEmptyCommands(); void adjustSectionsBeforeSorting(); void adjustSectionsAfterSorting(); - std::vector<PhdrEntry> createPhdrs(); - bool ignoreInterpSection(); + std::vector<PhdrEntry *> createPhdrs(); + bool needsInterpSection(); bool shouldKeep(InputSectionBase *S); - void assignOffsets(OutputSectionCommand *Cmd); - void processNonSectionCommands(); void assignAddresses(); - void allocateHeaders(std::vector<PhdrEntry> &Phdrs); - void addSymbol(SymbolAssignment *Cmd); - void processCommands(OutputSectionFactory &Factory); + void allocateHeaders(std::vector<PhdrEntry *> &Phdrs); + void processSectionCommands(); + + // SECTIONS command list. + std::vector<BaseCommand *> SectionCommands; + + // PHDRS command list. + std::vector<PhdrsCommand> PhdrsCommands; + + bool HasSectionsCommand = false; + bool ErrorOnMissingSection = false; - // Parsed linker script configurations are set to this struct. - ScriptConfiguration Opt; + // List of section patterns specified with KEEP commands. They will + // be kept even if they are unused and --gc-sections is specified. + std::vector<InputSectionDescription *> KeptSections; + + // A map from memory region name to a memory region descriptor. + llvm::MapVector<llvm::StringRef, MemoryRegion *> MemoryRegions; + + // A list of symbols referenced by the script. + std::vector<llvm::StringRef> ReferencedSymbols; }; extern LinkerScript *Script; |