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