LinkingContext.h revision 292934
1//===- lld/Core/LinkingContext.h - Linker Target Info Interface -----------===// 2// 3// The LLVM Linker 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef LLD_CORE_LINKING_CONTEXT_H 11#define LLD_CORE_LINKING_CONTEXT_H 12 13#include "lld/Core/Error.h" 14#include "lld/Core/LLVM.h" 15#include "lld/Core/Node.h" 16#include "lld/Core/Parallel.h" 17#include "lld/Core/Reference.h" 18#include "lld/Core/range.h" 19#include "lld/Core/Reader.h" 20#include "llvm/Support/ErrorOr.h" 21#include "llvm/Support/raw_ostream.h" 22#include <string> 23#include <vector> 24 25namespace lld { 26class PassManager; 27class File; 28class Writer; 29class Node; 30class SharedLibraryFile; 31 32/// \brief 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. For example, ELFLinkingContext has methods that supplies 37/// options to the ELF Writer and ELF Passes. 38class LinkingContext { 39public: 40 /// \brief The types of output file that the linker creates. 41 enum class OutputFileType : uint8_t { 42 Default, // The default output type for this target 43 YAML, // The output type is set to YAML 44 }; 45 46 virtual ~LinkingContext(); 47 48 /// \name Methods needed by core linking 49 /// @{ 50 51 /// Name of symbol linker should use as "entry point" to program, 52 /// usually "main" or "start". 53 virtual StringRef entrySymbolName() const { return _entrySymbolName; } 54 55 /// Whether core linking should remove Atoms not reachable by following 56 /// References from the entry point Atom or from all global scope Atoms 57 /// if globalsAreDeadStripRoots() is true. 58 bool deadStrip() const { return _deadStrip; } 59 60 /// Only used if deadStrip() returns true. Means all global scope Atoms 61 /// should be marked live (along with all Atoms they reference). Usually 62 /// this method returns false for main executables, but true for dynamic 63 /// shared libraries. 64 bool globalsAreDeadStripRoots() const { return _globalsAreDeadStripRoots; } 65 66 /// Only used if deadStrip() returns true. This method returns the names 67 /// of DefinedAtoms that should be marked live (along with all Atoms they 68 /// reference). Only Atoms with scope scopeLinkageUnit or scopeGlobal can 69 /// be kept live using this method. 70 const std::vector<StringRef> &deadStripRoots() const { 71 return _deadStripRoots; 72 } 73 74 /// Add the given symbol name to the dead strip root set. Only used if 75 /// deadStrip() returns true. 76 void addDeadStripRoot(StringRef symbolName) { 77 assert(!symbolName.empty() && "Empty symbol cannot be a dead strip root"); 78 _deadStripRoots.push_back(symbolName); 79 } 80 81 /// Archive files (aka static libraries) are normally lazily loaded. That is, 82 /// object files within an archive are only loaded and linked in, if the 83 /// object file contains a DefinedAtom which will replace an existing 84 /// UndefinedAtom. If this method returns true, core linking will also look 85 /// for archive members to replace existing tentative definitions in addition 86 /// to replacing undefines. Note: a "tentative definition" (also called a 87 /// "common" symbols) is a C (but not C++) concept. They are modeled in lld 88 /// as a DefinedAtom with merge() of mergeAsTentative. 89 bool searchArchivesToOverrideTentativeDefinitions() const { 90 return _searchArchivesToOverrideTentativeDefinitions; 91 } 92 93 /// Normally core linking will turn a tentative definition into a real 94 /// definition if not replaced by a real DefinedAtom from some object file. 95 /// If this method returns true, core linking will search all supplied 96 /// dynamic shared libraries for symbol names that match remaining tentative 97 /// definitions. If any are found, the corresponding tentative definition 98 /// atom is replaced with SharedLibraryAtom. 99 bool searchSharedLibrariesToOverrideTentativeDefinitions() const { 100 return _searchSharedLibrariesToOverrideTentativeDefinitions; 101 } 102 103 /// Normally, every UndefinedAtom must be replaced by a DefinedAtom or a 104 /// SharedLibraryAtom for the link to be successful. This method controls 105 /// whether core linking prints out a list of remaining UndefinedAtoms. 106 /// 107 /// \todo This should be a method core linking calls with a list of the 108 /// UndefinedAtoms so that different drivers can format the error message 109 /// as needed. 110 bool printRemainingUndefines() const { return _printRemainingUndefines; } 111 112 /// Normally, every UndefinedAtom must be replaced by a DefinedAtom or a 113 /// SharedLibraryAtom for the link to be successful. This method controls 114 /// whether core linking considers remaining undefines to be an error. 115 bool allowRemainingUndefines() const { return _allowRemainingUndefines; } 116 117 /// In the lld model, a SharedLibraryAtom is a proxy atom for something 118 /// that will be found in a dynamic shared library when the program runs. 119 /// A SharedLibraryAtom optionally contains the name of the shared library 120 /// in which to find the symbol name at runtime. Core linking may merge 121 /// two SharedLibraryAtom with the same name. If this method returns true, 122 /// when merging core linking will also verify that they both have the same 123 /// loadName() and if not print a warning. 124 /// 125 /// \todo This should be a method core linking calls so that drivers can 126 /// format the warning as needed. 127 bool warnIfCoalesableAtomsHaveDifferentLoadName() const { 128 return _warnIfCoalesableAtomsHaveDifferentLoadName; 129 } 130 131 /// In C/C++ you can mark a function's prototype with 132 /// __attribute__((weak_import)) or __attribute__((weak)) to say the function 133 /// may not be available at runtime and/or build time and in which case its 134 /// address will evaluate to NULL. In lld this is modeled using the 135 /// UndefinedAtom::canBeNull() method. During core linking, UndefinedAtom 136 /// with the same name are automatically merged. If this method returns 137 /// true, core link also verfies that the canBeNull() value for merged 138 /// UndefinedAtoms are the same and warns if not. 139 /// 140 /// \todo This should be a method core linking calls so that drivers can 141 /// format the warning as needed. 142 bool warnIfCoalesableAtomsHaveDifferentCanBeNull() const { 143 return _warnIfCoalesableAtomsHaveDifferentCanBeNull; 144 } 145 146 /// Normally, every UndefinedAtom must be replaced by a DefinedAtom or a 147 /// SharedLibraryAtom for the link to be successful. This method controls 148 /// whether core linking considers remaining undefines from the shared library 149 /// to be an error. 150 bool allowShlibUndefines() const { return _allowShlibUndefines; } 151 152 /// If true, core linking will write the path to each input file to stdout 153 /// (i.e. llvm::outs()) as it is used. This is used to implement the -t 154 /// linker option. 155 /// 156 /// \todo This should be a method core linking calls so that drivers can 157 /// format the line as needed. 158 bool logInputFiles() const { return _logInputFiles; } 159 160 /// Parts of LLVM use global variables which are bound to command line 161 /// options (see llvm::cl::Options). This method returns "command line" 162 /// options which are used to configure LLVM's command line settings. 163 /// For instance the -debug-only XXX option can be used to dynamically 164 /// trace different parts of LLVM and lld. 165 const std::vector<const char *> &llvmOptions() const { return _llvmOptions; } 166 167 /// \name Methods used by Drivers to configure TargetInfo 168 /// @{ 169 void setOutputPath(StringRef str) { _outputPath = str; } 170 171 // Set the entry symbol name. You may also need to call addDeadStripRoot() for 172 // the symbol if your platform supports dead-stripping, so that the symbol 173 // will not be removed from the output. 174 void setEntrySymbolName(StringRef name) { 175 _entrySymbolName = name; 176 } 177 178 void setDeadStripping(bool enable) { _deadStrip = enable; } 179 void setAllowDuplicates(bool enable) { _allowDuplicates = enable; } 180 void setGlobalsAreDeadStripRoots(bool v) { _globalsAreDeadStripRoots = v; } 181 void setSearchArchivesToOverrideTentativeDefinitions(bool search) { 182 _searchArchivesToOverrideTentativeDefinitions = search; 183 } 184 void setSearchSharedLibrariesToOverrideTentativeDefinitions(bool search) { 185 _searchSharedLibrariesToOverrideTentativeDefinitions = search; 186 } 187 void setWarnIfCoalesableAtomsHaveDifferentCanBeNull(bool warn) { 188 _warnIfCoalesableAtomsHaveDifferentCanBeNull = warn; 189 } 190 void setWarnIfCoalesableAtomsHaveDifferentLoadName(bool warn) { 191 _warnIfCoalesableAtomsHaveDifferentLoadName = warn; 192 } 193 void setPrintRemainingUndefines(bool print) { 194 _printRemainingUndefines = print; 195 } 196 void setAllowRemainingUndefines(bool allow) { 197 _allowRemainingUndefines = allow; 198 } 199 void setAllowShlibUndefines(bool allow) { _allowShlibUndefines = allow; } 200 void setLogInputFiles(bool log) { _logInputFiles = log; } 201 202 // Returns true if multiple definitions should not be treated as a 203 // fatal error. 204 bool getAllowDuplicates() const { return _allowDuplicates; } 205 206 void appendLLVMOption(const char *opt) { _llvmOptions.push_back(opt); } 207 208 void addAlias(StringRef from, StringRef to) { _aliasSymbols[from] = to; } 209 const std::map<std::string, std::string> &getAliases() const { 210 return _aliasSymbols; 211 } 212 213 std::vector<std::unique_ptr<Node>> &getNodes() { return _nodes; } 214 const std::vector<std::unique_ptr<Node>> &getNodes() const { return _nodes; } 215 216 /// Notify the LinkingContext when the symbol table found a name collision. 217 /// The useNew parameter specifies which the symbol table plans to keep, 218 /// but that can be changed by the LinkingContext. This is also an 219 /// opportunity for flavor specific processing. 220 virtual void notifySymbolTableCoalesce(const Atom *existingAtom, 221 const Atom *newAtom, bool &useNew) {} 222 223 /// This method adds undefined symbols specified by the -u option to the to 224 /// the list of undefined symbols known to the linker. This option essentially 225 /// forces an undefined symbol to be created. You may also need to call 226 /// addDeadStripRoot() for the symbol if your platform supports dead 227 /// stripping, so that the symbol will not be removed from the output. 228 void addInitialUndefinedSymbol(StringRef symbolName) { 229 _initialUndefinedSymbols.push_back(symbolName); 230 } 231 232 /// Iterators for symbols that appear on the command line. 233 typedef std::vector<StringRef> StringRefVector; 234 typedef StringRefVector::iterator StringRefVectorIter; 235 typedef StringRefVector::const_iterator StringRefVectorConstIter; 236 237 /// Create linker internal files containing atoms for the linker to include 238 /// during link. Flavors can override this function in their LinkingContext 239 /// to add more internal files. These internal files are positioned before 240 /// the actual input files. 241 virtual void createInternalFiles(std::vector<std::unique_ptr<File> > &) const; 242 243 /// Return the list of undefined symbols that are specified in the 244 /// linker command line, using the -u option. 245 range<const StringRef *> initialUndefinedSymbols() const { 246 return _initialUndefinedSymbols; 247 } 248 249 /// After all set* methods are called, the Driver calls this method 250 /// to validate that there are no missing options or invalid combinations 251 /// of options. If there is a problem, a description of the problem 252 /// is written to the supplied stream. 253 /// 254 /// \returns true if there is an error with the current settings. 255 bool validate(raw_ostream &diagnostics); 256 257 /// Formats symbol name for use in error messages. 258 virtual std::string demangle(StringRef symbolName) const { 259 return symbolName; 260 } 261 262 /// @} 263 /// \name Methods used by Driver::link() 264 /// @{ 265 266 /// Returns the file system path to which the linked output should be written. 267 /// 268 /// \todo To support in-memory linking, we need an abstraction that allows 269 /// the linker to write to an in-memory buffer. 270 StringRef outputPath() const { return _outputPath; } 271 272 /// Set the various output file types that the linker would 273 /// create 274 bool setOutputFileType(StringRef outputFileType) { 275 if (outputFileType.equals_lower("yaml")) { 276 _outputFileType = OutputFileType::YAML; 277 return true; 278 } 279 return false; 280 } 281 282 /// Returns the output file type that that the linker needs to create. 283 OutputFileType outputFileType() const { return _outputFileType; } 284 285 /// Accessor for Register object embedded in LinkingContext. 286 const Registry ®istry() const { return _registry; } 287 Registry ®istry() { return _registry; } 288 289 /// This method is called by core linking to give the Writer a chance 290 /// to add file format specific "files" to set of files to be linked. This is 291 /// how file format specific atoms can be added to the link. 292 virtual void createImplicitFiles(std::vector<std::unique_ptr<File>> &); 293 294 /// This method is called by core linking to build the list of Passes to be 295 /// run on the merged/linked graph of all input files. 296 virtual void addPasses(PassManager &pm); 297 298 /// Calls through to the writeFile() method on the specified Writer. 299 /// 300 /// \param linkedFile This is the merged/linked graph of all input file Atoms. 301 virtual std::error_code writeFile(const File &linkedFile) const; 302 303 /// Return the next ordinal and Increment it. 304 virtual uint64_t getNextOrdinalAndIncrement() const { return _nextOrdinal++; } 305 306 // This function is called just before the Resolver kicks in. 307 // Derived classes may use it to change the list of input files. 308 virtual void finalizeInputFiles() {} 309 310 TaskGroup &getTaskGroup() { return _taskGroup; } 311 312 /// @} 313protected: 314 LinkingContext(); // Must be subclassed 315 316 /// Abstract method to lazily instantiate the Writer. 317 virtual Writer &writer() const = 0; 318 319 /// Method to create an internal file for the entry symbol 320 virtual std::unique_ptr<File> createEntrySymbolFile() const; 321 std::unique_ptr<File> createEntrySymbolFile(StringRef filename) const; 322 323 /// Method to create an internal file for an undefined symbol 324 virtual std::unique_ptr<File> createUndefinedSymbolFile() const; 325 std::unique_ptr<File> createUndefinedSymbolFile(StringRef filename) const; 326 327 /// Method to create an internal file for alias symbols 328 std::unique_ptr<File> createAliasSymbolFile() const; 329 330 StringRef _outputPath; 331 StringRef _entrySymbolName; 332 bool _deadStrip; 333 bool _allowDuplicates; 334 bool _globalsAreDeadStripRoots; 335 bool _searchArchivesToOverrideTentativeDefinitions; 336 bool _searchSharedLibrariesToOverrideTentativeDefinitions; 337 bool _warnIfCoalesableAtomsHaveDifferentCanBeNull; 338 bool _warnIfCoalesableAtomsHaveDifferentLoadName; 339 bool _printRemainingUndefines; 340 bool _allowRemainingUndefines; 341 bool _logInputFiles; 342 bool _allowShlibUndefines; 343 OutputFileType _outputFileType; 344 std::vector<StringRef> _deadStripRoots; 345 std::map<std::string, std::string> _aliasSymbols; 346 std::vector<const char *> _llvmOptions; 347 StringRefVector _initialUndefinedSymbols; 348 std::vector<std::unique_ptr<Node>> _nodes; 349 mutable llvm::BumpPtrAllocator _allocator; 350 mutable uint64_t _nextOrdinal; 351 Registry _registry; 352 353private: 354 /// Validate the subclass bits. Only called by validate. 355 virtual bool validateImpl(raw_ostream &diagnostics) = 0; 356 TaskGroup _taskGroup; 357}; 358 359} // end namespace lld 360 361#endif 362