aboutsummaryrefslogtreecommitdiffstats
path: root/ELF/LinkerScript.h
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-12-18 20:12:21 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-12-18 20:12:21 +0000
commiteb1ff93d02b5f17b6b409e83c6d9be585f4a04b3 (patch)
tree7490b4a8943293f251ad733465936e6ec302b3e9 /ELF/LinkerScript.h
parentbafea25f368c63f0b39789906adfed6e39219e64 (diff)
downloadsrc-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.h211
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;