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