]> git.saurik.com Git - apple/ld64.git/blobdiff - src/ld/parsers/textstub_dylib_file.cpp
ld64-351.8.tar.gz
[apple/ld64.git] / src / ld / parsers / textstub_dylib_file.cpp
index 076736e714929eb6bafe0c297d3c7c382cb282d8..27c456010e8fde56378dcca2a7bc52d81a7330ba 100644 (file)
@@ -29,7 +29,7 @@
 #include <vector>
 
 #include "Architectures.hpp"
-#include "bitcode.hpp"
+#include "Bitcode.hpp"
 #include "MachOFileAbstraction.hpp"
 #include "MachOTrie.hpp"
 #include "generic_dylib_file.hpp"
@@ -50,7 +50,14 @@ class File final : public generic::dylib::File<A>
        using Base = generic::dylib::File<A>;
 
 public:
-                                       File(const char* path, const uint8_t* fileContent, uint64_t fileLength,
+                                       File(const char* path, const uint8_t* fileContent, uint64_t fileLength, const Options *opts,
+                                                time_t mTime, ld::File::Ordinal ordinal, bool linkingFlatNamespace,
+                                                bool linkingMainExecutable, bool hoistImplicitPublicDylibs,
+                                                Options::Platform platform, uint32_t linkMinOSVersion, bool allowWeakImports,
+                                                cpu_type_t cpuType, cpu_subtype_t cpuSubType, bool enforceDylibSubtypesMatch,
+                                                bool allowSimToMacOSX, bool addVers, bool buildingForSimulator,
+                                                bool logAllFiles, const char* installPath, bool indirectDylib);
+                                       File(std::unique_ptr<tapi::LinkerInterfaceFile> &&file, const char *path, const Options *opts,
                                                 time_t mTime, ld::File::Ordinal ordinal, bool linkingFlatNamespace,
                                                 bool linkingMainExecutable, bool hoistImplicitPublicDylibs,
                                                 Options::Platform platform, uint32_t linkMinOSVersion, bool allowWeakImports,
@@ -58,9 +65,18 @@ public:
                                                 bool allowSimToMacOSX, bool addVers, bool buildingForSimulator,
                                                 bool logAllFiles, const char* installPath, bool indirectDylib);
        virtual                 ~File() noexcept {}
+       
+       // overrides of generic::dylib::File
+       virtual void    processIndirectLibraries(ld::dylib::File::DylibHandler*, bool addImplicitDylibs) override final;
 
 private:
+       void                    init(tapi::LinkerInterfaceFile *file, const Options *opts, bool buildingForSimulator,
+                                                bool indirectDylib, bool linkingFlatNamespace, bool linkingMainExecutable,
+                                                const char *path, Options::Platform platform, const char *targetInstallPath);
        void                    buildExportHashTable(const tapi::LinkerInterfaceFile* file);
+       
+       const Options   *_opts;
+       std::unique_ptr<tapi::LinkerInterfaceFile> _interface;
 };
 
 static ld::File::ObjcConstraint mapObjCConstraint(tapi::ObjCConstraint constraint) {
@@ -101,8 +117,8 @@ static Options::Platform mapPlatform(tapi::Platform platform) {
        return Options::kPlatformUnknown;
 }
 
-template <typename A>
-       File<A>::File(const char* path, const uint8_t* fileContent, uint64_t fileLength,
+       template <typename A>
+       File<A>::File(const char* path, const uint8_t* fileContent, uint64_t fileLength, const Options *opts,
                          time_t mTime, ld::File::Ordinal ord, bool linkingFlatNamespace,
                          bool linkingMainExecutable, bool hoistImplicitPublicDylibs, Options::Platform platform,
                          uint32_t linkMinOSVersion, bool allowWeakImports, cpu_type_t cpuType, cpu_subtype_t cpuSubType,
@@ -112,12 +128,25 @@ template <typename A>
        : Base(strdup(path), mTime, ord, platform, linkMinOSVersion, allowWeakImports, linkingFlatNamespace,
                   hoistImplicitPublicDylibs, allowSimToMacOSX, addVers)
 {
-       std::unique_ptr<tapi::LinkerInterfaceFile> file;
        std::string errorMessage;
 
 // <rdar://problem/29038544> Support $ld$weak symbols in .tbd files
-#if ((TAPI_API_VERSION_MAJOR == 1 &&  TAPI_API_VERSION_MINOR >= 1) || (TAPI_API_VERSION_MAJOR > 1))
+#if ((TAPI_API_VERSION_MAJOR == 1 &&  TAPI_API_VERSION_MINOR >= 3) || (TAPI_API_VERSION_MAJOR > 1))
        // Check if the library supports the new create API.
+       if (tapi::APIVersion::isAtLeast(1, 3)) {
+               tapi::ParsingFlags flags = tapi::ParsingFlags::None;
+               if (enforceDylibSubtypesMatch)
+                       flags |= tapi::ParsingFlags::ExactCpuSubType;
+
+               if (!allowWeakImports)
+                       flags |= tapi::ParsingFlags::DisallowWeakImports;
+
+               _interface.reset(tapi::LinkerInterfaceFile::create(
+                       path, cpuType, cpuSubType, flags,
+                       tapi::PackedVersion32(linkMinOSVersion), errorMessage));
+       } else
+#endif
+#if ((TAPI_API_VERSION_MAJOR == 1 &&  TAPI_API_VERSION_MINOR >= 1) || (TAPI_API_VERSION_MAJOR > 1))
        if (tapi::APIVersion::isAtLeast(1, 1)) {
                tapi::ParsingFlags flags = tapi::ParsingFlags::None;
                if (enforceDylibSubtypesMatch)
@@ -126,27 +155,23 @@ template <typename A>
                if (!allowWeakImports)
                        flags |= tapi::ParsingFlags::DisallowWeakImports;
 
-               file.reset(tapi::LinkerInterfaceFile::create(
+               _interface.reset(tapi::LinkerInterfaceFile::create(
                        path, fileContent, fileLength, cpuType, cpuSubType, flags,
                        tapi::PackedVersion32(linkMinOSVersion), errorMessage));
-       } else {
+       } else
+#endif
+#if (TAPI_API_VERSION_MAJOR >= 1)
+       {
                auto matchingType = enforceDylibSubtypesMatch ?
-                               tapi::CpuSubTypeMatching::Exact : tapi::CpuSubTypeMatching::ABI_Compatible;
+                       tapi::CpuSubTypeMatching::Exact : tapi::CpuSubTypeMatching::ABI_Compatible;
 
-               file.reset(tapi::LinkerInterfaceFile::create(
+               _interface.reset(tapi::LinkerInterfaceFile::create(
                        path, fileContent, fileLength, cpuType, cpuSubType, matchingType,
                        tapi::PackedVersion32(linkMinOSVersion), errorMessage));
        }
-#else
-       auto matchingType = enforceDylibSubtypesMatch ?
-               tapi::CpuSubTypeMatching::Exact : tapi::CpuSubTypeMatching::ABI_Compatible;
-
-       file.reset(tapi::LinkerInterfaceFile::create(
-               path, fileContent, fileLength, cpuType, cpuSubType, matchingType,
-               tapi::PackedVersion32(linkMinOSVersion), errorMessage));
 #endif
 
-       if (file == nullptr)
+       if (!_interface)
                throw strdup(errorMessage.c_str());
 
        // unmap file - it is no longer needed.
@@ -156,6 +181,30 @@ template <typename A>
        if ( logAllFiles )
                printf("%s\n", path);
 
+       init(_interface.get(), opts, buildingForSimulator, indirectDylib, linkingFlatNamespace,
+                linkingMainExecutable, path, platform, targetInstallPath);
+}
+
+       template<typename A>
+       File<A>::File(std::unique_ptr<tapi::LinkerInterfaceFile> &&file, const char* path, const Options *opts,
+                                 time_t mTime, ld::File::Ordinal ordinal, bool linkingFlatNamespace,
+                                bool linkingMainExecutable, bool hoistImplicitPublicDylibs,
+                                Options::Platform platform, uint32_t linkMinOSVersion, bool allowWeakImports,
+                                cpu_type_t cpuType, cpu_subtype_t cpuSubType, bool enforceDylibSubtypesMatch,
+                                bool allowSimToMacOSX, bool addVers, bool buildingForSimulator,
+                                bool logAllFiles, const char* installPath, bool indirectDylib)
+       : Base(strdup(path), mTime, ordinal, platform, linkMinOSVersion, allowWeakImports, linkingFlatNamespace,
+                  hoistImplicitPublicDylibs, allowSimToMacOSX, addVers), _interface(std::move(file))
+{
+       init(_interface.get(), opts, buildingForSimulator, indirectDylib, linkingFlatNamespace,
+                linkingMainExecutable, path, platform, installPath);
+}
+       
+template<typename A>
+void File<A>::init(tapi::LinkerInterfaceFile *file, const Options *opts, bool buildingForSimulator,
+                                  bool indirectDylib, bool linkingFlatNamespace, bool linkingMainExecutable,
+                                  const char *path, Options::Platform platform, const char *targetInstallPath) {
+       _opts = opts;
        this->_bitcode = std::unique_ptr<ld::Bitcode>(new ld::Bitcode(nullptr, 0));
        this->_noRexports = !file->hasReexportedLibraries();
        this->_hasWeakExports = file->hasWeakDefinedExports();
@@ -179,16 +228,16 @@ template <typename A>
                if ( strstr(this->_dylibInstallPath, frname) != NULL )
                        this->_frameworkName = leafName;
        }
-
+       
        for (auto &client : file->allowableClients())
                this->_allowableClients.push_back(strdup(client.c_str()));
-
+       
        // <rdar://problem/20659505> [TAPI] Don't hoist "public" (in /usr/lib/) dylibs that should not be directly linked
        this->_hasPublicInstallName = file->hasAllowableClients() ? false : this->isPublicLocation(file->getInstallName().c_str());
-
+       
        for (const auto &client : file->allowableClients())
                this->_allowableClients.emplace_back(strdup(client.c_str()));
-
+       
        auto dylibPlatform = mapPlatform(file->getPlatform());
        if ( (dylibPlatform != platform) && (platform != Options::kPlatformUnknown) ) {
                this->_wrongOS = true;
@@ -196,23 +245,23 @@ template <typename A>
                        if ( buildingForSimulator ) {
                                if ( !this->_allowSimToMacOSXLinking )
                                        throwf("building for %s simulator, but linking against dylib built for %s (%s).",
-                                                       Options::platformName(platform), Options::platformName(dylibPlatform), path);
+                                                  Options::platformName(platform), Options::platformName(dylibPlatform), path);
                        } else {
                                throwf("building for %s, but linking against dylib built for %s (%s).",
-                                               Options::platformName(platform), Options::platformName(dylibPlatform), path);
+                                          Options::platformName(platform), Options::platformName(dylibPlatform), path);
                        }
                }
        }
-
+       
        for (const auto& reexport : file->reexportedLibraries()) {
                const char *path = strdup(reexport.c_str());
                if ( (targetInstallPath == nullptr) || (strcmp(targetInstallPath, path) != 0) )
                        this->_dependentDylibs.emplace_back(path, true);
        }
-
+       
        for (const auto& symbol : file->ignoreExports())
                this->_ignoreExports.insert(strdup(symbol.c_str()));
-
+       
        // if linking flat and this is a flat dylib, create one atom that references all imported symbols.
        if ( linkingFlatNamespace && linkingMainExecutable && (file->hasTwoLevelNamespace() == false) ) {
                std::vector<const char*> importNames;
@@ -223,9 +272,9 @@ template <typename A>
                        importNames.emplace_back(sym.getName().c_str());
                this->_importAtom = new generic::dylib::ImportAtom<A>(*this, importNames);
        }
-
+       
        // build hash table
-       buildExportHashTable(file.get());
+       buildExportHashTable(file);
 }
 
 template <typename A>
@@ -245,6 +294,13 @@ void File<A>::buildExportHashTable(const tapi::LinkerInterfaceFile* file) {
        }
 }
 
+template <typename A>
+void File<A>::processIndirectLibraries(ld::dylib::File::DylibHandler* handler, bool addImplicitDylibs) {
+       if (_interface)
+               _opts->addTAPIInterface(_interface.get(), this->path());
+       Base::processIndirectLibraries(handler, addImplicitDylibs);
+}
+
 template <typename A>
 class Parser
 {
@@ -256,7 +312,7 @@ public:
                                                                  ld::File::Ordinal ordinal, const Options& opts,
                                                                  bool indirectDylib)
        {
-               return new File<A>(path, fileContent, fileLength,mTime, ordinal,
+               return new File<A>(path, fileContent, fileLength, &opts, mTime, ordinal,
                                                   opts.flatNamespace(),
                                                   opts.linkingMainExecutable(),
                                                   opts.implicitlyLinkIndirectPublicDylibs(),
@@ -273,6 +329,29 @@ public:
                                                   opts.installPath(),
                                                   indirectDylib);
        }
+       
+       static ld::dylib::File* parse(const char* path, std::unique_ptr<tapi::LinkerInterfaceFile> &&file, time_t mTime,
+                                                                 ld::File::Ordinal ordinal, const Options& opts,
+                                                                 bool indirectDylib)
+       {
+               return new File<A>(std::move(file), path, &opts, mTime, ordinal,
+                                                  opts.flatNamespace(),
+                                                  opts.linkingMainExecutable(),
+                                                  opts.implicitlyLinkIndirectPublicDylibs(),
+                                                  opts.platform(),
+                                                  opts.minOSversion(),
+                                                  opts.allowWeakImports(),
+                                                  opts.architecture(),
+                                                  opts.subArchitecture(),
+                                                  opts.enforceDylibSubtypesMatch(),
+                                                  opts.allowSimulatorToLinkWithMacOSX(),
+                                                  opts.addVersionLoadCommand(),
+                                                  opts.targetIOSSimulator(),
+                                                  opts.logAllFiles(),
+                                                  opts.installPath(),
+                                                  indirectDylib);
+       }
+
 };
 
 //
@@ -307,7 +386,31 @@ ld::dylib::File* parse(const uint8_t* fileContent, uint64_t fileLength, const ch
        }
        return nullptr;
 }
-       
-       
+
+ld::dylib::File *parse(const char *path, std::unique_ptr<tapi::LinkerInterfaceFile> &&file, time_t modTime,
+                                          ld::File::Ordinal ordinal, const Options& opts, bool indirectDylib) {
+       switch ( opts.architecture() ) {
+#if SUPPORT_ARCH_x86_64
+               case CPU_TYPE_X86_64:
+                       return Parser<x86_64>::parse(path, std::move(file), modTime, ordinal, opts, indirectDylib);
+#endif
+#if SUPPORT_ARCH_i386
+               case CPU_TYPE_I386:
+                       return Parser<x86>::parse(path, std::move(file), modTime, ordinal, opts, indirectDylib);
+#endif
+#if SUPPORT_ARCH_arm_any
+               case CPU_TYPE_ARM:
+                       return Parser<arm>::parse(path, std::move(file), modTime, ordinal, opts, indirectDylib);
+#endif
+#if SUPPORT_ARCH_arm64
+               case CPU_TYPE_ARM64:
+                       return Parser<arm64>::parse(path, std::move(file), modTime, ordinal, opts, indirectDylib);
+#endif
+       }
+       return nullptr;
+
+}
+
+
 } // namespace dylib
 } // namespace textstub