1//===- lld/ReaderWriter/MachOLinkingContext.h -----------------------------===//
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_READER_WRITER_MACHO_LINKING_CONTEXT_H
10#define LLD_READER_WRITER_MACHO_LINKING_CONTEXT_H
11
12#include "lld/Core/LinkingContext.h"
13#include "lld/Core/Reader.h"
14#include "lld/Core/Writer.h"
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/StringMap.h"
17#include "llvm/ADT/StringSet.h"
18#include "llvm/BinaryFormat/MachO.h"
19#include "llvm/Support/ErrorHandling.h"
20#include <set>
21
22using llvm::MachO::HeaderFileType;
23
24namespace lld {
25
26namespace mach_o {
27class ArchHandler;
28class MachODylibFile;
29class MachOFile;
30class SectCreateFile;
31}
32
33class MachOLinkingContext : public LinkingContext {
34public:
35  MachOLinkingContext();
36  ~MachOLinkingContext() override;
37
38  enum Arch {
39    arch_unknown,
40    arch_ppc,
41    arch_x86,
42    arch_x86_64,
43    arch_armv6,
44    arch_armv7,
45    arch_armv7s,
46    arch_arm64,
47  };
48
49  enum class OS {
50    unknown,
51    macOSX,
52    iOS,
53    iOS_simulator
54  };
55
56  enum class ExportMode {
57    globals,    // Default, all global symbols exported.
58    exported,   // -exported_symbol[s_list], only listed symbols exported.
59    unexported  // -unexported_symbol[s_list], no listed symbol exported.
60  };
61
62  enum class DebugInfoMode {
63    addDebugMap,    // Default
64    noDebugMap      // -S option
65  };
66
67  enum class UndefinedMode {
68    error,
69    warning,
70    suppress,
71    dynamicLookup
72  };
73
74  enum ObjCConstraint {
75    objc_unknown = 0,
76    objc_supports_gc = 2,
77    objc_gc_only = 4,
78    // Image optimized by dyld = 8
79    // GC compaction = 16
80    objc_retainReleaseForSimulator = 32,
81    objc_retainRelease
82  };
83
84  /// Initializes the context to sane default values given the specified output
85  /// file type, arch, os, and minimum os version.  This should be called before
86  /// other setXXX() methods.
87  void configure(HeaderFileType type, Arch arch, OS os, uint32_t minOSVersion,
88                 bool exportDynamicSymbols);
89
90  void addPasses(PassManager &pm) override;
91  bool validateImpl() override;
92  std::string demangle(StringRef symbolName) const override;
93
94  void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
95
96  /// Creates a new file which is owned by the context.  Returns a pointer to
97  /// the new file.
98  template <class T, class... Args>
99  typename std::enable_if<!std::is_array<T>::value, T *>::type
100  make_file(Args &&... args) const {
101    auto file = std::unique_ptr<T>(new T(std::forward<Args>(args)...));
102    auto *filePtr = file.get();
103    auto *ctx = const_cast<MachOLinkingContext *>(this);
104    ctx->getNodes().push_back(std::make_unique<FileNode>(std::move(file)));
105    return filePtr;
106  }
107
108  uint32_t getCPUType() const;
109  uint32_t getCPUSubType() const;
110
111  bool addEntryPointLoadCommand() const;
112  bool addUnixThreadLoadCommand() const;
113  bool outputTypeHasEntry() const;
114  bool is64Bit() const;
115
116  virtual uint64_t pageZeroSize() const { return _pageZeroSize; }
117  virtual uint64_t pageSize() const { return _pageSize; }
118
119  mach_o::ArchHandler &archHandler() const;
120
121  HeaderFileType outputMachOType() const { return _outputMachOType; }
122
123  Arch arch() const { return _arch; }
124  StringRef archName() const { return nameFromArch(_arch); }
125  OS os() const { return _os; }
126
127  ExportMode exportMode() const { return _exportMode; }
128  void setExportMode(ExportMode mode) { _exportMode = mode; }
129  void addExportSymbol(StringRef sym);
130  bool exportRestrictMode() const { return _exportMode != ExportMode::globals; }
131  bool exportSymbolNamed(StringRef sym) const;
132
133  DebugInfoMode debugInfoMode() const { return _debugInfoMode; }
134  void setDebugInfoMode(DebugInfoMode mode) {
135    _debugInfoMode = mode;
136  }
137
138  void appendOrderedSymbol(StringRef symbol, StringRef filename);
139
140  bool keepPrivateExterns() const { return _keepPrivateExterns; }
141  void setKeepPrivateExterns(bool v) { _keepPrivateExterns = v; }
142  bool demangleSymbols() const { return _demangle; }
143  void setDemangleSymbols(bool d) { _demangle = d; }
144  bool mergeObjCCategories() const { return _mergeObjCCategories; }
145  void setMergeObjCCategories(bool v) { _mergeObjCCategories = v; }
146  /// Create file at specified path which will contain a binary encoding
147  /// of all input and output file paths.
148  std::error_code createDependencyFile(StringRef path);
149  void addInputFileDependency(StringRef path) const;
150  void addInputFileNotFound(StringRef path) const;
151  void addOutputFileDependency(StringRef path) const;
152
153  bool minOS(StringRef mac, StringRef iOS) const;
154  void setDoNothing(bool value) { _doNothing = value; }
155  bool doNothing() const { return _doNothing; }
156  bool printAtoms() const { return _printAtoms; }
157  bool testingFileUsage() const { return _testingFileUsage; }
158  const StringRefVector &searchDirs() const { return _searchDirs; }
159  const StringRefVector &frameworkDirs() const { return _frameworkDirs; }
160  void setSysLibRoots(const StringRefVector &paths);
161  const StringRefVector &sysLibRoots() const { return _syslibRoots; }
162  bool PIE() const { return _pie; }
163  void setPIE(bool pie) { _pie = pie; }
164  bool generateVersionLoadCommand() const {
165    return _generateVersionLoadCommand;
166  }
167  void setGenerateVersionLoadCommand(bool v) {
168    _generateVersionLoadCommand = v;
169  }
170
171  bool generateFunctionStartsLoadCommand() const {
172    return _generateFunctionStartsLoadCommand;
173  }
174  void setGenerateFunctionStartsLoadCommand(bool v) {
175    _generateFunctionStartsLoadCommand = v;
176  }
177
178  bool generateDataInCodeLoadCommand() const {
179    return _generateDataInCodeLoadCommand;
180  }
181  void setGenerateDataInCodeLoadCommand(bool v) {
182    _generateDataInCodeLoadCommand = v;
183  }
184
185  uint64_t stackSize() const { return _stackSize; }
186  void setStackSize(uint64_t stackSize) { _stackSize = stackSize; }
187
188  uint64_t baseAddress() const { return _baseAddress; }
189  void setBaseAddress(uint64_t baseAddress) { _baseAddress = baseAddress; }
190
191  ObjCConstraint objcConstraint() const { return _objcConstraint; }
192
193  uint32_t osMinVersion() const { return _osMinVersion; }
194
195  uint32_t sdkVersion() const { return _sdkVersion; }
196  void setSdkVersion(uint64_t v) { _sdkVersion = v; }
197
198  uint64_t sourceVersion() const { return _sourceVersion; }
199  void setSourceVersion(uint64_t v) { _sourceVersion = v; }
200
201  uint32_t swiftVersion() const { return _swiftVersion; }
202
203  /// Checks whether a given path on the filesystem exists.
204  ///
205  /// When running in -test_file_usage mode, this method consults an
206  /// internally maintained list of files that exist (provided by -path_exists)
207  /// instead of the actual filesystem.
208  bool pathExists(StringRef path) const;
209
210  /// Like pathExists() but only used on files - not directories.
211  bool fileExists(StringRef path) const;
212
213  /// Adds any library search paths derived from the given base, possibly
214  /// modified by -syslibroots.
215  ///
216  /// The set of paths added consists of approximately all syslibroot-prepended
217  /// versions of libPath that exist, or the original libPath if there are none
218  /// for whatever reason. With various edge-cases for compatibility.
219  void addModifiedSearchDir(StringRef libPath, bool isSystemPath = false);
220
221  /// Determine whether -lFoo can be resolve within the given path, and
222  /// return the filename if so.
223  ///
224  /// The -lFoo option is documented to search for libFoo.dylib and libFoo.a in
225  /// that order, unless Foo ends in ".o", in which case only the exact file
226  /// matches (e.g. -lfoo.o would only find foo.o).
227  llvm::Optional<StringRef> searchDirForLibrary(StringRef path,
228                                                StringRef libName) const;
229
230  /// Iterates through all search path entries looking for libName (as
231  /// specified by -lFoo).
232  llvm::Optional<StringRef> searchLibrary(StringRef libName) const;
233
234  /// Add a framework search path.  Internally, this method may be prepended
235  /// the path with syslibroot.
236  void addFrameworkSearchDir(StringRef fwPath, bool isSystemPath = false);
237
238  /// Iterates through all framework directories looking for
239  /// Foo.framework/Foo (when fwName = "Foo").
240  llvm::Optional<StringRef> findPathForFramework(StringRef fwName) const;
241
242  /// The dylib's binary compatibility version, in the raw uint32 format.
243  ///
244  /// When building a dynamic library, this is the compatibility version that
245  /// gets embedded into the result. Other Mach-O binaries that link against
246  /// this library will store the compatibility version in its load command. At
247  /// runtime, the loader will verify that the binary is compatible with the
248  /// installed dynamic library.
249  uint32_t compatibilityVersion() const { return _compatibilityVersion; }
250
251  /// The dylib's current version, in the raw uint32 format.
252  ///
253  /// When building a dynamic library, this is the current version that gets
254  /// embedded into the result. Other Mach-O binaries that link against
255  /// this library will store the compatibility version in its load command.
256  uint32_t currentVersion() const { return _currentVersion; }
257
258  /// The dylib's install name.
259  ///
260  /// Binaries that link against the dylib will embed this path into the dylib
261  /// load command. When loading the binaries at runtime, this is the location
262  /// on disk that the loader will look for the dylib.
263  StringRef installName() const { return _installName; }
264
265  /// Whether or not the dylib has side effects during initialization.
266  ///
267  /// Dylibs marked as being dead strippable provide the guarantee that loading
268  /// the dylib has no side effects, allowing the linker to strip out the dylib
269  /// when linking a binary that does not use any of its symbols.
270  bool deadStrippableDylib() const { return _deadStrippableDylib; }
271
272  /// Whether or not to use flat namespace.
273  ///
274  /// MachO usually uses a two-level namespace, where each external symbol
275  /// referenced by the target is associated with the dylib that will provide
276  /// the symbol's definition at runtime. Using flat namespace overrides this
277  /// behavior: the linker searches all dylibs on the command line and all
278  /// dylibs those original dylibs depend on, but does not record which dylib
279  /// an external symbol came from. At runtime dyld again searches all images
280  /// and uses the first definition it finds. In addition, any undefines in
281  /// loaded flat_namespace dylibs must be resolvable at build time.
282  bool useFlatNamespace() const { return _flatNamespace; }
283
284  /// How to handle undefined symbols.
285  ///
286  /// Options are:
287  ///  * error: Report an error and terminate linking.
288  ///  * warning: Report a warning, but continue linking.
289  ///  * suppress: Ignore and continue linking.
290  ///  * dynamic_lookup: For use with -twolevel namespace: Records source dylibs
291  ///    for symbols that are defined in a linked dylib at static link time.
292  ///    Undefined symbols are handled by searching all loaded images at
293  ///    runtime.
294  UndefinedMode undefinedMode() const { return _undefinedMode; }
295
296  /// The path to the executable that will load the bundle at runtime.
297  ///
298  /// When building a Mach-O bundle, this executable will be examined if there
299  /// are undefined symbols after the main link phase. It is expected that this
300  /// binary will be loading the bundle at runtime and will provide the symbols
301  /// at that point.
302  StringRef bundleLoader() const { return _bundleLoader; }
303
304  void setCompatibilityVersion(uint32_t vers) { _compatibilityVersion = vers; }
305  void setCurrentVersion(uint32_t vers) { _currentVersion = vers; }
306  void setInstallName(StringRef name) { _installName = name; }
307  void setDeadStrippableDylib(bool deadStrippable) {
308    _deadStrippableDylib = deadStrippable;
309  }
310  void setUseFlatNamespace(bool flatNamespace) {
311    _flatNamespace = flatNamespace;
312  }
313
314  void setUndefinedMode(UndefinedMode undefinedMode) {
315    _undefinedMode = undefinedMode;
316  }
317
318  void setBundleLoader(StringRef loader) { _bundleLoader = loader; }
319  void setPrintAtoms(bool value=true) { _printAtoms = value; }
320  void setTestingFileUsage(bool value = true) {
321    _testingFileUsage = value;
322  }
323  void addExistingPathForDebug(StringRef path) {
324    _existingPaths.insert(path);
325  }
326
327  void addRpath(StringRef rpath);
328  const StringRefVector &rpaths() const { return _rpaths; }
329
330  /// Add section alignment constraint on final layout.
331  void addSectionAlignment(StringRef seg, StringRef sect, uint16_t align);
332
333  /// Add a section based on a command-line sectcreate option.
334  void addSectCreateSection(StringRef seg, StringRef sect,
335                            std::unique_ptr<MemoryBuffer> content);
336
337  /// Returns true if specified section had alignment constraints.
338  bool sectionAligned(StringRef seg, StringRef sect, uint16_t &align) const;
339
340  StringRef dyldPath() const { return "/usr/lib/dyld"; }
341
342  /// Stub creation Pass should be run.
343  bool needsStubsPass() const;
344
345  // GOT creation Pass should be run.
346  bool needsGOTPass() const;
347
348  /// Pass to add TLV sections.
349  bool needsTLVPass() const;
350
351  /// Pass to transform __compact_unwind into __unwind_info should be run.
352  bool needsCompactUnwindPass() const;
353
354  /// Pass to add shims switching between thumb and arm mode.
355  bool needsShimPass() const;
356
357  /// Pass to add objc image info and optimized objc data.
358  bool needsObjCPass() const;
359
360  /// Magic symbol name stubs will need to help lazy bind.
361  StringRef binderSymbolName() const;
362
363  /// Used to keep track of direct and indirect dylibs.
364  void registerDylib(mach_o::MachODylibFile *dylib, bool upward) const;
365
366  // Reads a file from disk to memory. Returns only a needed chunk
367  // if a fat binary.
368  ErrorOr<std::unique_ptr<MemoryBuffer>> getMemoryBuffer(StringRef path);
369
370  /// Used to find indirect dylibs. Instantiates a MachODylibFile if one
371  /// has not already been made for the requested dylib.  Uses -L and -F
372  /// search paths to allow indirect dylibs to be overridden.
373  mach_o::MachODylibFile* findIndirectDylib(StringRef path);
374
375  uint32_t dylibCurrentVersion(StringRef installName) const;
376
377  uint32_t dylibCompatVersion(StringRef installName) const;
378
379  ArrayRef<mach_o::MachODylibFile*> allDylibs() const {
380    return _allDylibs;
381  }
382
383  /// Creates a copy (owned by this MachOLinkingContext) of a string.
384  StringRef copy(StringRef str) { return str.copy(_allocator); }
385
386  /// If the memoryBuffer is a fat file with a slice for the current arch,
387  /// this method will return the offset and size of that slice.
388  bool sliceFromFatFile(MemoryBufferRef mb, uint32_t &offset, uint32_t &size);
389
390  /// Returns if a command line option specified dylib is an upward link.
391  bool isUpwardDylib(StringRef installName) const;
392
393  static bool isThinObjectFile(StringRef path, Arch &arch);
394  static Arch archFromCpuType(uint32_t cputype, uint32_t cpusubtype);
395  static Arch archFromName(StringRef archName);
396  static StringRef nameFromArch(Arch arch);
397  static uint32_t cpuTypeFromArch(Arch arch);
398  static uint32_t cpuSubtypeFromArch(Arch arch);
399  static bool is64Bit(Arch arch);
400  static bool isHostEndian(Arch arch);
401  static bool isBigEndian(Arch arch);
402
403  /// Construct 32-bit value from string "X.Y.Z" where
404  /// bits are xxxx.yy.zz.  Largest number is 65535.255.255
405  static bool parsePackedVersion(StringRef str, uint32_t &result);
406
407  /// Construct 64-bit value from string "A.B.C.D.E" where
408  /// bits are aaaa.bb.cc.dd.ee.  Largest number is 16777215.1023.1023.1023.1023
409  static bool parsePackedVersion(StringRef str, uint64_t &result);
410
411  void finalizeInputFiles() override;
412
413  llvm::Error handleLoadedFile(File &file) override;
414
415  bool customAtomOrderer(const DefinedAtom *left, const DefinedAtom *right,
416                         bool &leftBeforeRight) const;
417
418  /// Return the 'flat namespace' file. This is the file that supplies
419  /// atoms for otherwise undefined symbols when the -flat_namespace or
420  /// -undefined dynamic_lookup options are used.
421  File* flatNamespaceFile() const { return _flatNamespaceFile; }
422
423private:
424  Writer &writer() const override;
425  mach_o::MachODylibFile* loadIndirectDylib(StringRef path);
426  struct ArchInfo {
427    StringRef                 archName;
428    MachOLinkingContext::Arch arch;
429    bool                      littleEndian;
430    uint32_t                  cputype;
431    uint32_t                  cpusubtype;
432  };
433
434  struct SectionAlign {
435    StringRef segmentName;
436    StringRef sectionName;
437    uint16_t  align;
438  };
439
440  struct OrderFileNode {
441    StringRef fileFilter;
442    unsigned  order;
443  };
444
445  static bool findOrderOrdinal(const std::vector<OrderFileNode> &nodes,
446                             const DefinedAtom *atom, unsigned &ordinal);
447
448  static ArchInfo _s_archInfos[];
449
450  std::set<StringRef> _existingPaths; // For testing only.
451  StringRefVector _searchDirs;
452  StringRefVector _syslibRoots;
453  StringRefVector _frameworkDirs;
454  HeaderFileType _outputMachOType = llvm::MachO::MH_EXECUTE;
455  bool _outputMachOTypeStatic = false; // Disambiguate static vs dynamic prog
456  bool _doNothing = false;             // for -help and -v which just print info
457  bool _pie = false;
458  Arch _arch = arch_unknown;
459  OS _os = OS::macOSX;
460  uint32_t _osMinVersion = 0;
461  uint32_t _sdkVersion = 0;
462  uint64_t _sourceVersion = 0;
463  uint64_t _pageZeroSize = 0;
464  uint64_t _pageSize = 4096;
465  uint64_t _baseAddress = 0;
466  uint64_t _stackSize = 0;
467  uint32_t _compatibilityVersion = 0;
468  uint32_t _currentVersion = 0;
469  ObjCConstraint _objcConstraint = objc_unknown;
470  uint32_t _swiftVersion = 0;
471  StringRef _installName;
472  StringRefVector _rpaths;
473  bool _flatNamespace = false;
474  UndefinedMode _undefinedMode = UndefinedMode::error;
475  bool _deadStrippableDylib = false;
476  bool _printAtoms = false;
477  bool _testingFileUsage = false;
478  bool _keepPrivateExterns = false;
479  bool _demangle = false;
480  bool _mergeObjCCategories = true;
481  bool _generateVersionLoadCommand = false;
482  bool _generateFunctionStartsLoadCommand = false;
483  bool _generateDataInCodeLoadCommand = false;
484  StringRef _bundleLoader;
485  mutable std::unique_ptr<mach_o::ArchHandler> _archHandler;
486  mutable std::unique_ptr<Writer> _writer;
487  std::vector<SectionAlign> _sectAligns;
488  mutable llvm::StringMap<mach_o::MachODylibFile*> _pathToDylibMap;
489  mutable std::vector<mach_o::MachODylibFile*> _allDylibs;
490  mutable std::set<mach_o::MachODylibFile*> _upwardDylibs;
491  mutable std::vector<std::unique_ptr<File>> _indirectDylibs;
492  mutable std::mutex _dylibsMutex;
493  ExportMode _exportMode = ExportMode::globals;
494  llvm::StringSet<> _exportedSymbols;
495  DebugInfoMode _debugInfoMode = DebugInfoMode::addDebugMap;
496  std::unique_ptr<llvm::raw_fd_ostream> _dependencyInfo;
497  llvm::StringMap<std::vector<OrderFileNode>> _orderFiles;
498  unsigned _orderFileEntries = 0;
499  File *_flatNamespaceFile = nullptr;
500  mach_o::SectCreateFile *_sectCreateFile = nullptr;
501};
502
503} // end namespace lld
504
505#endif // LLD_READER_WRITER_MACHO_LINKING_CONTEXT_H
506