1 //===- lld/ReaderWriter/MachOLinkingContext.h -----------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLD_READER_WRITER_MACHO_LINKING_CONTEXT_H
10 #define LLD_READER_WRITER_MACHO_LINKING_CONTEXT_H
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"
22 using llvm::MachO::HeaderFileType;
33 class MachOLinkingContext : public LinkingContext {
35 MachOLinkingContext();
36 ~MachOLinkingContext() override;
56 enum class ExportMode {
57 globals, // Default, all global symbols exported.
58 whiteList, // -exported_symbol[s_list], only listed symbols exported.
59 blackList // -unexported_symbol[s_list], no listed symbol exported.
62 enum class DebugInfoMode {
63 addDebugMap, // Default
64 noDebugMap // -S option
67 enum class UndefinedMode {
78 // Image optimized by dyld = 8
80 objc_retainReleaseForSimulator = 32,
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);
90 void addPasses(PassManager &pm) override;
91 bool validateImpl() override;
92 std::string demangle(StringRef symbolName) const override;
94 void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
96 /// Creates a new file which is owned by the context. Returns a pointer to
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(llvm::make_unique<FileNode>(std::move(file)));
108 uint32_t getCPUType() const;
109 uint32_t getCPUSubType() const;
111 bool addEntryPointLoadCommand() const;
112 bool addUnixThreadLoadCommand() const;
113 bool outputTypeHasEntry() const;
114 bool is64Bit() const;
116 virtual uint64_t pageZeroSize() const { return _pageZeroSize; }
117 virtual uint64_t pageSize() const { return _pageSize; }
119 mach_o::ArchHandler &archHandler() const;
121 HeaderFileType outputMachOType() const { return _outputMachOType; }
123 Arch arch() const { return _arch; }
124 StringRef archName() const { return nameFromArch(_arch); }
125 OS os() const { return _os; }
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;
133 DebugInfoMode debugInfoMode() const { return _debugInfoMode; }
134 void setDebugInfoMode(DebugInfoMode mode) {
135 _debugInfoMode = mode;
138 void appendOrderedSymbol(StringRef symbol, StringRef filename);
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;
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;
167 void setGenerateVersionLoadCommand(bool v) {
168 _generateVersionLoadCommand = v;
171 bool generateFunctionStartsLoadCommand() const {
172 return _generateFunctionStartsLoadCommand;
174 void setGenerateFunctionStartsLoadCommand(bool v) {
175 _generateFunctionStartsLoadCommand = v;
178 bool generateDataInCodeLoadCommand() const {
179 return _generateDataInCodeLoadCommand;
181 void setGenerateDataInCodeLoadCommand(bool v) {
182 _generateDataInCodeLoadCommand = v;
185 uint64_t stackSize() const { return _stackSize; }
186 void setStackSize(uint64_t stackSize) { _stackSize = stackSize; }
188 uint64_t baseAddress() const { return _baseAddress; }
189 void setBaseAddress(uint64_t baseAddress) { _baseAddress = baseAddress; }
191 ObjCConstraint objcConstraint() const { return _objcConstraint; }
193 uint32_t osMinVersion() const { return _osMinVersion; }
195 uint32_t sdkVersion() const { return _sdkVersion; }
196 void setSdkVersion(uint64_t v) { _sdkVersion = v; }
198 uint64_t sourceVersion() const { return _sourceVersion; }
199 void setSourceVersion(uint64_t v) { _sourceVersion = v; }
201 uint32_t swiftVersion() const { return _swiftVersion; }
203 /// Checks whether a given path on the filesystem exists.
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;
210 /// Like pathExists() but only used on files - not directories.
211 bool fileExists(StringRef path) const;
213 /// Adds any library search paths derived from the given base, possibly
214 /// modified by -syslibroots.
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);
221 /// Determine whether -lFoo can be resolve within the given path, and
222 /// return the filename if so.
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;
230 /// Iterates through all search path entries looking for libName (as
231 /// specified by -lFoo).
232 llvm::Optional<StringRef> searchLibrary(StringRef libName) const;
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);
238 /// Iterates through all framework directories looking for
239 /// Foo.framework/Foo (when fwName = "Foo").
240 llvm::Optional<StringRef> findPathForFramework(StringRef fwName) const;
242 /// The dylib's binary compatibility version, in the raw uint32 format.
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; }
251 /// The dylib's current version, in the the raw uint32 format.
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; }
258 /// The dylib's install name.
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; }
265 /// Whether or not the dylib has side effects during initialization.
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; }
272 /// Whether or not to use flat namespace.
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; }
284 /// How to handle undefined symbols.
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
294 UndefinedMode undefinedMode() const { return _undefinedMode; }
296 /// The path to the executable that will load the bundle at runtime.
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
302 StringRef bundleLoader() const { return _bundleLoader; }
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;
310 void setUseFlatNamespace(bool flatNamespace) {
311 _flatNamespace = flatNamespace;
314 void setUndefinedMode(UndefinedMode undefinedMode) {
315 _undefinedMode = undefinedMode;
318 void setBundleLoader(StringRef loader) { _bundleLoader = loader; }
319 void setPrintAtoms(bool value=true) { _printAtoms = value; }
320 void setTestingFileUsage(bool value = true) {
321 _testingFileUsage = value;
323 void addExistingPathForDebug(StringRef path) {
324 _existingPaths.insert(path);
327 void addRpath(StringRef rpath);
328 const StringRefVector &rpaths() const { return _rpaths; }
330 /// Add section alignment constraint on final layout.
331 void addSectionAlignment(StringRef seg, StringRef sect, uint16_t align);
333 /// Add a section based on a command-line sectcreate option.
334 void addSectCreateSection(StringRef seg, StringRef sect,
335 std::unique_ptr<MemoryBuffer> content);
337 /// Returns true if specified section had alignment constraints.
338 bool sectionAligned(StringRef seg, StringRef sect, uint16_t &align) const;
340 StringRef dyldPath() const { return "/usr/lib/dyld"; }
342 /// Stub creation Pass should be run.
343 bool needsStubsPass() const;
345 // GOT creation Pass should be run.
346 bool needsGOTPass() const;
348 /// Pass to add TLV sections.
349 bool needsTLVPass() const;
351 /// Pass to transform __compact_unwind into __unwind_info should be run.
352 bool needsCompactUnwindPass() const;
354 /// Pass to add shims switching between thumb and arm mode.
355 bool needsShimPass() const;
357 /// Pass to add objc image info and optimized objc data.
358 bool needsObjCPass() const;
360 /// Magic symbol name stubs will need to help lazy bind.
361 StringRef binderSymbolName() const;
363 /// Used to keep track of direct and indirect dylibs.
364 void registerDylib(mach_o::MachODylibFile *dylib, bool upward) const;
366 // Reads a file from disk to memory. Returns only a needed chunk
368 ErrorOr<std::unique_ptr<MemoryBuffer>> getMemoryBuffer(StringRef path);
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);
375 uint32_t dylibCurrentVersion(StringRef installName) const;
377 uint32_t dylibCompatVersion(StringRef installName) const;
379 ArrayRef<mach_o::MachODylibFile*> allDylibs() const {
383 /// Creates a copy (owned by this MachOLinkingContext) of a string.
384 StringRef copy(StringRef str) { return str.copy(_allocator); }
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);
390 /// Returns if a command line option specified dylib is an upward link.
391 bool isUpwardDylib(StringRef installName) const;
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);
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);
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);
411 void finalizeInputFiles() override;
413 llvm::Error handleLoadedFile(File &file) override;
415 bool customAtomOrderer(const DefinedAtom *left, const DefinedAtom *right,
416 bool &leftBeforeRight) const;
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; }
424 Writer &writer() const override;
425 mach_o::MachODylibFile* loadIndirectDylib(StringRef path);
426 void checkExportWhiteList(const DefinedAtom *atom) const;
427 void checkExportBlackList(const DefinedAtom *atom) const;
430 MachOLinkingContext::Arch arch;
436 struct SectionAlign {
437 StringRef segmentName;
438 StringRef sectionName;
442 struct OrderFileNode {
443 StringRef fileFilter;
447 static bool findOrderOrdinal(const std::vector<OrderFileNode> &nodes,
448 const DefinedAtom *atom, unsigned &ordinal);
450 static ArchInfo _s_archInfos[];
452 std::set<StringRef> _existingPaths; // For testing only.
453 StringRefVector _searchDirs;
454 StringRefVector _syslibRoots;
455 StringRefVector _frameworkDirs;
456 HeaderFileType _outputMachOType = llvm::MachO::MH_EXECUTE;
457 bool _outputMachOTypeStatic = false; // Disambiguate static vs dynamic prog
458 bool _doNothing = false; // for -help and -v which just print info
460 Arch _arch = arch_unknown;
462 uint32_t _osMinVersion = 0;
463 uint32_t _sdkVersion = 0;
464 uint64_t _sourceVersion = 0;
465 uint64_t _pageZeroSize = 0;
466 uint64_t _pageSize = 4096;
467 uint64_t _baseAddress = 0;
468 uint64_t _stackSize = 0;
469 uint32_t _compatibilityVersion = 0;
470 uint32_t _currentVersion = 0;
471 ObjCConstraint _objcConstraint = objc_unknown;
472 uint32_t _swiftVersion = 0;
473 StringRef _installName;
474 StringRefVector _rpaths;
475 bool _flatNamespace = false;
476 UndefinedMode _undefinedMode = UndefinedMode::error;
477 bool _deadStrippableDylib = false;
478 bool _printAtoms = false;
479 bool _testingFileUsage = false;
480 bool _keepPrivateExterns = false;
481 bool _demangle = false;
482 bool _mergeObjCCategories = true;
483 bool _generateVersionLoadCommand = false;
484 bool _generateFunctionStartsLoadCommand = false;
485 bool _generateDataInCodeLoadCommand = false;
486 StringRef _bundleLoader;
487 mutable std::unique_ptr<mach_o::ArchHandler> _archHandler;
488 mutable std::unique_ptr<Writer> _writer;
489 std::vector<SectionAlign> _sectAligns;
490 mutable llvm::StringMap<mach_o::MachODylibFile*> _pathToDylibMap;
491 mutable std::vector<mach_o::MachODylibFile*> _allDylibs;
492 mutable std::set<mach_o::MachODylibFile*> _upwardDylibs;
493 mutable std::vector<std::unique_ptr<File>> _indirectDylibs;
494 mutable std::mutex _dylibsMutex;
495 ExportMode _exportMode = ExportMode::globals;
496 llvm::StringSet<> _exportedSymbols;
497 DebugInfoMode _debugInfoMode = DebugInfoMode::addDebugMap;
498 std::unique_ptr<llvm::raw_fd_ostream> _dependencyInfo;
499 llvm::StringMap<std::vector<OrderFileNode>> _orderFiles;
500 unsigned _orderFileEntries = 0;
501 File *_flatNamespaceFile = nullptr;
502 mach_o::SectCreateFile *_sectCreateFile = nullptr;
505 } // end namespace lld
507 #endif // LLD_READER_WRITER_MACHO_LINKING_CONTEXT_H