]> git.saurik.com Git - apple/ld64.git/blobdiff - src/ld/InputFiles.cpp
ld64-264.3.101.tar.gz
[apple/ld64.git] / src / ld / InputFiles.cpp
index 30c0875de7af9e3311a2212a310e8b1c38f4c60c..ab31d4acab07ffe72a8e69cfde6a37cbf064fffc 100644 (file)
@@ -58,6 +58,7 @@
 #include "InputFiles.h"
 #include "macho_relocatable_file.h"
 #include "macho_dylib_file.h"
+#include "textstub_dylib_file.hpp"
 #include "archive_file.h"
 #include "lto_file.h"
 #include "opaque_section_file.h"
@@ -294,7 +295,16 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib
        objOpts.neverConvertDwarf   = !_options.needsUnwindInfoSection();
        objOpts.verboseOptimizationHints = _options.verboseOptimizationHints();
        objOpts.armUsesZeroCostExceptions = _options.armUsesZeroCostExceptions();
+       objOpts.simulator                       = _options.targetIOSSimulator();
+       objOpts.ignoreMismatchPlatform = ((_options.outputKind() == Options::kPreload) || (_options.outputKind() == Options::kStaticExecutable));
        objOpts.subType                         = _options.subArchitecture();
+       objOpts.platform                        = _options.platform();
+       objOpts.minOSVersion            = _options.minOSversion();
+       objOpts.srcKind                         = ld::relocatable::File::kSourceObj;
+       objOpts.treateBitcodeAsData     = _options.bitcodeKind() == Options::kBitcodeAsData;
+       objOpts.usingBitcode            = _options.bundleBitcode();
+       objOpts.maxDefaultCommonAlignment = _options.maxDefaultCommonAlign();
+
        ld::relocatable::File* objResult = mach_o::relocatable::parse(p, len, info.path, info.modTime, info.ordinal, objOpts);
        if ( objResult != NULL ) {
                OSAtomicAdd64(len, &_totalObjectSize);
@@ -309,8 +319,8 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib
                OSAtomicIncrement32(&_totalObjectLoaded);
                return objResult;
        }
-       
-       // see if it is a dynamic library
+
+       // see if it is a dynamic library (or text-based dynamic library)
        ld::dylib::File* dylibResult;
        bool dylibsNotAllowed = false;
        switch ( _options.outputKind() ) {
@@ -321,6 +331,10 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib
                        if ( dylibResult != NULL ) {
                                return dylibResult;
                        }
+                       dylibResult = textstub::dylib::parse(p, len, info.path, info.modTime, _options, info.ordinal, info.options.fBundleLoader, indirectDylib);
+                       if ( dylibResult != NULL ) {
+                               return dylibResult;
+                       }
                        break;
                case Options::kStaticExecutable:
                case Options::kDyld:
@@ -331,7 +345,6 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib
                        break;
        }
 
-
        // see if it is a static library
        ::archive::ParserOptions archOpts;
        archOpts.objOpts                                = objOpts;
@@ -341,6 +354,15 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib
        archOpts.objcABI2                               = _options.objCABIVersion2POverride();
        archOpts.verboseLoad                    = _options.whyLoad();
        archOpts.logAllFiles                    = _options.logAllFiles();
+       // Set ObjSource Kind, libclang_rt is compiler static library
+       const char* libName = strrchr(info.path, '/');
+       if ( (libName != NULL) && (strncmp(libName, "/libclang_rt", 12) == 0) )
+               archOpts.objOpts.srcKind = ld::relocatable::File::kSourceCompilerArchive;
+       else
+               archOpts.objOpts.srcKind = ld::relocatable::File::kSourceArchive;
+       archOpts.objOpts.treateBitcodeAsData = _options.bitcodeKind() == Options::kBitcodeAsData;
+       archOpts.objOpts.usingBitcode = _options.bundleBitcode();
+
        ld::archive::File* archiveResult = ::archive::parse(p, len, info.path, info.modTime, info.ordinal, archOpts);
        if ( archiveResult != NULL ) {
                OSAtomicAdd64(len, &_totalArchiveSize);
@@ -561,15 +583,40 @@ void InputFiles::markExplicitlyLinkedDylibs()
        }
 }
 
-bool InputFiles::libraryAlreadyLoaded(const char* path) 
+bool InputFiles::frameworkAlreadyLoaded(const char* path, const char* frameworkName)
 {
-       for (std::vector<ld::File*>::const_iterator it = _inputFiles.begin(); it != _inputFiles.end(); ++it) {
-               if ( strcmp(path, (*it)->path()) == 0 )
+       for (ld::File* file : _inputFiles) {
+               if ( strcmp(path, file->path()) == 0 )
+                       return true;
+       }
+       for (ld::dylib::File* dylibx : _allDylibs) {
+               const char* fname = dylibx->frameworkName();
+               if ( fname == NULL )
+                       continue;
+               if ( strcmp(frameworkName, fname) == 0 )
                        return true;
        }
        return false;
 }
 
+bool InputFiles::libraryAlreadyLoaded(const char* path)
+{
+       for (ld::File* file : _inputFiles) {
+               if ( strcmp(path, file->path()) == 0 )
+                       return true;
+       }
+       for (ld::dylib::File* dylib : _allDylibs) {
+               if ( strcmp(path, dylib->path()) == 0 )
+                       return true;
+       }
+       for (const LibraryInfo& libInfo : _searchLibraries) {
+               if ( strcmp(path, libInfo.archive()->path()) == 0 )
+                       return true;
+       }
+
+       return false;
+}
+
 
 void InputFiles::addLinkerOptionLibraries(ld::Internal& state, ld::File::AtomHandler& handler)
 {      
@@ -579,14 +626,17 @@ void InputFiles::addLinkerOptionLibraries(ld::Internal& state, ld::File::AtomHan
        // process frameworks specified in .o linker options
        for (CStringSet::const_iterator it = state.linkerOptionFrameworks.begin(); it != state.linkerOptionFrameworks.end(); ++it) {
                const char* frameworkName = *it;
+               if ( state.linkerOptionFrameworksProcessed.count(frameworkName) )
+                       continue;
                Options::FileInfo info = _options.findFramework(frameworkName);
-               if ( ! this->libraryAlreadyLoaded(info.path) ) {
+               if ( ! this->frameworkAlreadyLoaded(info.path, frameworkName) ) {
                        info.ordinal = _linkerOptionOrdinal.nextLinkerOptionOrdinal();
                        try {
                                ld::File* reader = this->makeFile(info, true);
                                ld::dylib::File* dylibReader = dynamic_cast<ld::dylib::File*>(reader);
                                if ( dylibReader != NULL ) {
                                        if ( ! dylibReader->installPathVersionSpecific() ) {
+                                               dylibReader->forEachAtom(handler);
                                                dylibReader->setImplicitlyLinked();
                                                this->addDylib(dylibReader, info);
                                        }
@@ -599,10 +649,13 @@ void InputFiles::addLinkerOptionLibraries(ld::Internal& state, ld::File::AtomHan
                                warning("Auto-Linking supplied '%s', %s", info.path, msg);
                        }
                }
+               state.linkerOptionFrameworksProcessed.insert(frameworkName);
        }
        // process libraries specified in .o linker options
        for (CStringSet::const_iterator it = state.linkerOptionLibraries.begin(); it != state.linkerOptionLibraries.end(); ++it) {
                const char* libName = *it;
+               if ( state.linkerOptionLibrariesProcessed.count(libName) )
+                       continue;
                Options::FileInfo info = _options.findLibrary(libName);
                if ( ! this->libraryAlreadyLoaded(info.path) ) {
                        info.ordinal = _linkerOptionOrdinal.nextLinkerOptionOrdinal();
@@ -613,6 +666,7 @@ void InputFiles::addLinkerOptionLibraries(ld::Internal& state, ld::File::AtomHan
                                ld::dylib::File* dylibReader = dynamic_cast<ld::dylib::File*>(reader);
                                ld::archive::File* archiveReader = dynamic_cast<ld::archive::File*>(reader);
                                if ( dylibReader != NULL ) {
+                                       dylibReader->forEachAtom(handler);
                                        dylibReader->setImplicitlyLinked();
                                        this->addDylib(dylibReader, info);
                                }
@@ -633,6 +687,7 @@ void InputFiles::addLinkerOptionLibraries(ld::Internal& state, ld::File::AtomHan
                                warning("Auto-Linking supplied '%s', %s", info.path, msg);
                        }
                }
+               state.linkerOptionLibrariesProcessed.insert(libName);
        }
 }
 
@@ -775,20 +830,27 @@ void InputFiles::inferArchitecture(Options& opts, const char** archName)
        _inferredArch = true;
        // scan all input files, looking for a thin .o file.
        // the first one found is presumably the architecture to link
-       uint8_t buffer[sizeof(mach_header_64)];
+       uint8_t buffer[4096];
        const std::vector<Options::FileInfo>& files = opts.getInputFiles();
        for (std::vector<Options::FileInfo>::const_iterator it = files.begin(); it != files.end(); ++it) {
                int fd = ::open(it->path, O_RDONLY, 0);
                if ( fd != -1 ) {
-                       ssize_t amount = read(fd, buffer, sizeof(buffer));
-                       ::close(fd);
-                       if ( amount >= (ssize_t)sizeof(buffer) ) {
-                               cpu_type_t type;
-                               cpu_subtype_t subtype;
-                               if ( mach_o::relocatable::isObjectFile(buffer, &type, &subtype) ) {
-                                       opts.setArchitecture(type, subtype);
-                                       *archName = opts.architectureName();
-                                       return;
+                       struct stat stat_buf;
+                       if ( fstat(fd, &stat_buf) != -1) {
+                               ssize_t readAmount = stat_buf.st_size;
+                               if ( 4096 < readAmount )
+                                       readAmount = 4096;
+                               ssize_t amount = read(fd, buffer, readAmount);
+                               ::close(fd);
+                               if ( amount >= readAmount ) {
+                                       cpu_type_t type;
+                                       cpu_subtype_t subtype;
+                                       Options::Platform platform;
+                                       if ( mach_o::relocatable::isObjectFile(buffer, &type, &subtype, &platform) ) {
+                                               opts.setArchitecture(type, subtype, platform);
+                                               *archName = opts.architectureName();
+                                               return;
+                                       }
                                }
                        }
                }
@@ -797,11 +859,11 @@ void InputFiles::inferArchitecture(Options& opts, const char** archName)
        // no thin .o files found, so default to same architecture this tool was built as
        warning("-arch not specified");
 #if __i386__
-       opts.setArchitecture(CPU_TYPE_I386, CPU_SUBTYPE_X86_ALL);
+       opts.setArchitecture(CPU_TYPE_I386, CPU_SUBTYPE_X86_ALL, Options::kPlatformOSX);
 #elif __x86_64__
-       opts.setArchitecture(CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL);
+       opts.setArchitecture(CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL, Options::kPlatformOSX);
 #elif __arm__
-       opts.setArchitecture(CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6);
+       opts.setArchitecture(CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6, Options::kPlatformOSX);
 #else
        #error unknown default architecture
 #endif
@@ -1377,7 +1439,7 @@ void InputFiles::dylibs(ld::Internal& state)
        //fprintf(stderr, "all dylibs:\n");
        //for(std::vector<ld::dylib::File*>::iterator it=state.dylibs.begin(); it != state.dylibs.end(); ++it) {
        //      const ld::dylib::File* dylib = *it;
-       //      fprintf(stderr, "    %p %s\n", dylib, dylib->path());
+       //      fprintf(stderr, "    %p impl=%d %s\n", dylib, dylib->implicitlyLinked(), dylib->path());
        //}
        
        // and -bundle_loader