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 &registry() const { return _registry; }
188  Registry &registry() { 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