Home | History | Annotate | Download | only in ReaderWriter
      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 
     23 using llvm::MachO::HeaderFileType;
     24 
     25 namespace lld {
     26 
     27 namespace mach_o {
     28 class ArchHandler;
     29 class MachODylibFile;
     30 class MachOFile;
     31 class SectCreateFile;
     32 }
     33 
     34 class MachOLinkingContext : public LinkingContext {
     35 public:
     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 
    424 private:
    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