//===- LinkerScript.h -------------------------------------------*- C++ -*-===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLD_ELF_LINKER_SCRIPT_H #define LLD_ELF_LINKER_SCRIPT_H #include "Writer.h" #include "lld/Core/LLVM.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/MapVector.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/MemoryBuffer.h" #include namespace lld { namespace elf { class SymbolBody; template class InputSectionBase; template class OutputSectionBase; template class OutputSectionFactory; template class DefinedCommon; typedef std::function Expr; // Parses a linker script. Calling this function updates // Config and ScriptConfig. void readLinkerScript(MemoryBufferRef MB); class ScriptParser; template class InputSectionBase; template class OutputSectionBase; // This enum is used to implement linker script SECTIONS command. // https://sourceware.org/binutils/docs/ld/SECTIONS.html#SECTIONS enum SectionsCommandKind { AssignmentKind, OutputSectionKind, InputSectionKind }; struct BaseCommand { BaseCommand(int K) : Kind(K) {} virtual ~BaseCommand() {} int Kind; }; struct SymbolAssignment : BaseCommand { SymbolAssignment(StringRef Name, Expr E) : BaseCommand(AssignmentKind), Name(Name), Expression(E) {} static bool classof(const BaseCommand *C); StringRef Name; Expr Expression; bool Provide = false; bool Hidden = false; SymbolBody *Sym = nullptr; }; // Linker scripts allow additional constraints to be put on ouput sections. // An output section will only be created if all of its input sections are // read-only // or all of its input sections are read-write by using the keyword ONLY_IF_RO // and ONLY_IF_RW respectively. enum class ConstraintKind { NoConstraint, ReadOnly, ReadWrite }; struct OutputSectionCommand : BaseCommand { OutputSectionCommand(StringRef Name) : BaseCommand(OutputSectionKind), Name(Name) {} static bool classof(const BaseCommand *C); StringRef Name; Expr AddrExpr; Expr AlignExpr; std::vector> Commands; std::vector Phdrs; std::vector Filler; ConstraintKind Constraint = ConstraintKind::NoConstraint; }; struct InputSectionDescription : BaseCommand { InputSectionDescription() : BaseCommand(InputSectionKind) {} static bool classof(const BaseCommand *C); StringRef FilePattern; std::vector ExcludedFiles; std::vector SectionPatterns; }; struct PhdrsCommand { StringRef Name; unsigned Type; bool HasFilehdr; bool HasPhdrs; unsigned Flags; }; // ScriptConfiguration holds linker script parse results. struct ScriptConfiguration { // Used to assign addresses to sections. std::vector> Commands; // Used to assign sections to headers. std::vector PhdrsCommands; bool HasContents = false; llvm::BumpPtrAllocator Alloc; // List of section patterns specified with KEEP commands. They will // be kept even if they are unused and --gc-sections is specified. std::vector KeptSections; }; extern ScriptConfiguration *ScriptConfig; // This is a runner of the linker script. template class LinkerScript { typedef typename ELFT::uint uintX_t; public: std::vector *> createSections(OutputSectionFactory &Factory); std::vector> createPhdrs(ArrayRef *> S); ArrayRef getFiller(StringRef Name); bool shouldKeep(InputSectionBase *S); void assignAddresses(ArrayRef *> S); int compareSections(StringRef A, StringRef B); void addScriptedSymbols(); bool hasPhdrsCommands(); private: std::vector> getSectionMap(); std::vector *> getInputSections(const InputSectionDescription *); // "ScriptConfig" is a bit too long, so define a short name for it. ScriptConfiguration &Opt = *ScriptConfig; std::vector *> filter(std::vector *> &Sections); int getSectionIndex(StringRef Name); std::vector getPhdrIndices(StringRef SectionName); size_t getPhdrIndex(StringRef PhdrName); void dispatchAssignment(SymbolAssignment *Cmd); uintX_t Dot; }; // Variable template is a C++14 feature, so we can't template // a global variable. Use a struct to workaround. template struct Script { static LinkerScript *X; }; template LinkerScript *Script::X; } // namespace elf } // namespace lld #endif