LinkingContext.h revision 360660
1//===- lld/Core/LinkingContext.h - Linker Target Info Interface -*- C++ -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8 9#ifndef LLD_CORE_LINKING_CONTEXT_H 10#define LLD_CORE_LINKING_CONTEXT_H 11 12#include "lld/Core/Node.h" 13#include "lld/Core/Reader.h" 14#include "llvm/ADT/ArrayRef.h" 15#include "llvm/ADT/StringRef.h" 16#include "llvm/Support/Allocator.h" 17#include "llvm/Support/Error.h" 18#include <cassert> 19#include <cstdint> 20#include <memory> 21#include <string> 22#include <vector> 23 24namespace lld { 25 26class PassManager; 27class File; 28class Writer; 29class Node; 30class SharedLibraryFile; 31 32/// The LinkingContext class encapsulates "what and how" to link. 33/// 34/// The base class LinkingContext contains the options needed by core linking. 35/// Subclasses of LinkingContext have additional options needed by specific 36/// Writers. 37class LinkingContext { 38public: 39 virtual ~LinkingContext(); 40 41 /// \name Methods needed by core linking 42 /// @{ 43 44 /// Name of symbol linker should use as "entry point" to program, 45 /// usually "main" or "start". 46 virtual StringRef entrySymbolName() const { return _entrySymbolName; } 47 48 /// Whether core linking should remove Atoms not reachable by following 49 /// References from the entry point Atom or from all global scope Atoms 50 /// if globalsAreDeadStripRoots() is true. 51 bool deadStrip() const { return _deadStrip; } 52 53 /// Only used if deadStrip() returns true. Means all global scope Atoms 54 /// should be marked live (along with all Atoms they reference). Usually 55 /// this method returns false for main executables, but true for dynamic 56 /// shared libraries. 57 bool globalsAreDeadStripRoots() const { return _globalsAreDeadStripRoots; } 58 59 /// Only used if deadStrip() returns true. This method returns the names 60 /// of DefinedAtoms that should be marked live (along with all Atoms they 61 /// reference). Only Atoms with scope scopeLinkageUnit or scopeGlobal can 62 /// be kept live using this method. 63 ArrayRef<StringRef> deadStripRoots() const { 64 return _deadStripRoots; 65 } 66 67 /// Add the given symbol name to the dead strip root set. Only used if 68 /// deadStrip() returns true. 69 void addDeadStripRoot(StringRef symbolName) { 70 assert(!symbolName.empty() && "Empty symbol cannot be a dead strip root"); 71 _deadStripRoots.push_back(symbolName); 72 } 73 74 /// Normally, every UndefinedAtom must be replaced by a DefinedAtom or a 75 /// SharedLibraryAtom for the link to be successful. This method controls 76 /// whether core linking prints out a list of remaining UndefinedAtoms. 77 /// 78 /// \todo This should be a method core linking calls with a list of the 79 /// UndefinedAtoms so that different drivers can format the error message 80 /// as needed. 81 bool printRemainingUndefines() const { return _printRemainingUndefines; } 82 83 /// Normally, every UndefinedAtom must be replaced by a DefinedAtom or a 84 /// SharedLibraryAtom for the link to be successful. This method controls 85 /// whether core linking considers remaining undefines to be an error. 86 bool allowRemainingUndefines() const { return _allowRemainingUndefines; } 87 88 /// Normally, every UndefinedAtom must be replaced by a DefinedAtom or a 89 /// SharedLibraryAtom for the link to be successful. This method controls 90 /// whether core linking considers remaining undefines from the shared library 91 /// to be an error. 92 bool allowShlibUndefines() const { return _allowShlibUndefines; } 93 94 /// If true, core linking will write the path to each input file to stdout 95 /// (i.e. llvm::outs()) as it is used. This is used to implement the -t 96 /// linker option. 97 /// 98 /// \todo This should be a method core linking calls so that drivers can 99 /// format the line as needed. 100 bool logInputFiles() const { return _logInputFiles; } 101 102 /// Parts of LLVM use global variables which are bound to command line 103 /// options (see llvm::cl::Options). This method returns "command line" 104 /// options which are used to configure LLVM's command line settings. 105 /// For instance the -debug-only XXX option can be used to dynamically 106 /// trace different parts of LLVM and lld. 107 ArrayRef<const char *> llvmOptions() const { return _llvmOptions; } 108 109 /// \name Methods used by Drivers to configure TargetInfo 110 /// @{ 111 void setOutputPath(StringRef str) { _outputPath = str; } 112 113 // Set the entry symbol name. You may also need to call addDeadStripRoot() for 114 // the symbol if your platform supports dead-stripping, so that the symbol 115 // will not be removed from the output. 116 void setEntrySymbolName(StringRef name) { 117 _entrySymbolName = name; 118 } 119 120 void setDeadStripping(bool enable) { _deadStrip = enable; } 121 void setGlobalsAreDeadStripRoots(bool v) { _globalsAreDeadStripRoots = v; } 122 123 void setPrintRemainingUndefines(bool print) { 124 _printRemainingUndefines = print; 125 } 126 127 void setAllowRemainingUndefines(bool allow) { 128 _allowRemainingUndefines = allow; 129 } 130 131 void setAllowShlibUndefines(bool allow) { _allowShlibUndefines = allow; } 132 void setLogInputFiles(bool log) { _logInputFiles = log; } 133 134 void appendLLVMOption(const char *opt) { _llvmOptions.push_back(opt); } 135 136 std::vector<std::unique_ptr<Node>> &getNodes() { return _nodes; } 137 const std::vector<std::unique_ptr<Node>> &getNodes() const { return _nodes; } 138 139 /// This method adds undefined symbols specified by the -u option to the to 140 /// the list of undefined symbols known to the linker. This option essentially 141 /// forces an undefined symbol to be created. You may also need to call 142 /// addDeadStripRoot() for the symbol if your platform supports dead 143 /// stripping, so that the symbol will not be removed from the output. 144 void addInitialUndefinedSymbol(StringRef symbolName) { 145 _initialUndefinedSymbols.push_back(symbolName); 146 } 147 148 /// Iterators for symbols that appear on the command line. 149 typedef std::vector<StringRef> StringRefVector; 150 typedef StringRefVector::iterator StringRefVectorIter; 151 typedef StringRefVector::const_iterator StringRefVectorConstIter; 152 153 /// Create linker internal files containing atoms for the linker to include 154 /// during link. Flavors can override this function in their LinkingContext 155 /// to add more internal files. These internal files are positioned before 156 /// the actual input files. 157 virtual void createInternalFiles(std::vector<std::unique_ptr<File>> &) const; 158 159 /// Return the list of undefined symbols that are specified in the 160 /// linker command line, using the -u option. 161 ArrayRef<StringRef> initialUndefinedSymbols() const { 162 return _initialUndefinedSymbols; 163 } 164 165 /// After all set* methods are called, the Driver calls this method 166 /// to validate that there are no missing options or invalid combinations 167 /// of options. If there is a problem, a description of the problem 168 /// is written to the global error handler. 169 /// 170 /// \returns true if there is an error with the current settings. 171 bool validate(); 172 173 /// Formats symbol name for use in error messages. 174 virtual std::string demangle(StringRef symbolName) const = 0; 175 176 /// @} 177 /// \name Methods used by Driver::link() 178 /// @{ 179 180 /// Returns the file system path to which the linked output should be written. 181 /// 182 /// \todo To support in-memory linking, we need an abstraction that allows 183 /// the linker to write to an in-memory buffer. 184 StringRef outputPath() const { return _outputPath; } 185 186 /// Accessor for Register object embedded in LinkingContext. 187 const Registry ®istry() const { return _registry; } 188 Registry ®istry() { return _registry; } 189 190 /// This method is called by core linking to give the Writer a chance 191 /// to add file format specific "files" to set of files to be linked. This is 192 /// how file format specific atoms can be added to the link. 193 virtual void createImplicitFiles(std::vector<std::unique_ptr<File>> &) = 0; 194 195 /// This method is called by core linking to build the list of Passes to be 196 /// run on the merged/linked graph of all input files. 197 virtual void addPasses(PassManager &pm) = 0; 198 199 /// Calls through to the writeFile() method on the specified Writer. 200 /// 201 /// \param linkedFile This is the merged/linked graph of all input file Atoms. 202 virtual llvm::Error writeFile(const File &linkedFile) const; 203 204 /// Return the next ordinal and Increment it. 205 virtual uint64_t getNextOrdinalAndIncrement() const { return _nextOrdinal++; } 206 207 // This function is called just before the Resolver kicks in. 208 // Derived classes may use it to change the list of input files. 209 virtual void finalizeInputFiles() = 0; 210 211 /// Callback invoked for each file the Resolver decides we are going to load. 212 /// This can be used to update context state based on the file, and emit 213 /// errors for any differences between the context state and a loaded file. 214 /// For example, we can error if we try to load a file which is a different 215 /// arch from that being linked. 216 virtual llvm::Error handleLoadedFile(File &file) = 0; 217 218 /// @} 219protected: 220 LinkingContext(); // Must be subclassed 221 222 /// Abstract method to lazily instantiate the Writer. 223 virtual Writer &writer() const = 0; 224 225 /// Method to create an internal file for the entry symbol 226 virtual std::unique_ptr<File> createEntrySymbolFile() const; 227 std::unique_ptr<File> createEntrySymbolFile(StringRef filename) const; 228 229 /// Method to create an internal file for an undefined symbol 230 virtual std::unique_ptr<File> createUndefinedSymbolFile() const; 231 std::unique_ptr<File> createUndefinedSymbolFile(StringRef filename) const; 232 233 StringRef _outputPath; 234 StringRef _entrySymbolName; 235 bool _deadStrip = false; 236 bool _globalsAreDeadStripRoots = false; 237 bool _printRemainingUndefines = true; 238 bool _allowRemainingUndefines = false; 239 bool _logInputFiles = false; 240 bool _allowShlibUndefines = false; 241 std::vector<StringRef> _deadStripRoots; 242 std::vector<const char *> _llvmOptions; 243 StringRefVector _initialUndefinedSymbols; 244 std::vector<std::unique_ptr<Node>> _nodes; 245 mutable llvm::BumpPtrAllocator _allocator; 246 mutable uint64_t _nextOrdinal = 0; 247 Registry _registry; 248 249private: 250 /// Validate the subclass bits. Only called by validate. 251 virtual bool validateImpl() = 0; 252}; 253 254} // end namespace lld 255 256#endif // LLD_CORE_LINKING_CONTEXT_H 257