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