]> git.saurik.com Git - apple/ld64.git/blobdiff - src/ld/InputFiles.cpp
ld64-305.tar.gz
[apple/ld64.git] / src / ld / InputFiles.cpp
index 30c0875de7af9e3311a2212a310e8b1c38f4c60c..1c69de62135e58464aca1c0174b4bfe09425485c 100644 (file)
@@ -58,6 +58,7 @@
 #include "InputFiles.h"
 #include "macho_relocatable_file.h"
 #include "macho_dylib_file.h"
 #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"
 #include "archive_file.h"
 #include "lto_file.h"
 #include "opaque_section_file.h"
@@ -176,6 +177,11 @@ private:
 ld::Section CustomStackAtom::_s_section("__UNIXSTACK", "__stack", ld::Section::typeStack, true);
 
 
 ld::Section CustomStackAtom::_s_section("__UNIXSTACK", "__stack", ld::Section::typeStack, true);
 
 
+static bool isCompilerSupportLib(const char* path) {
+       const char* libName = strrchr(path, '/');
+       return ( (libName != NULL) && (strncmp(libName, "/libclang_rt", 12) == 0) );
+}
+
 
 const char* InputFiles::fileArch(const uint8_t* p, unsigned len)
 {
 
 const char* InputFiles::fileArch(const uint8_t* p, unsigned len)
 {
@@ -209,14 +215,16 @@ const char* InputFiles::fileArch(const uint8_t* p, unsigned len)
 ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib)
 {
        // map in whole file
 ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib)
 {
        // map in whole file
-       uint64_t len = info.fileLen;
+       struct stat stat_buf;
        int fd = ::open(info.path, O_RDONLY, 0);
        if ( fd == -1 )
                throwf("can't open file, errno=%d", errno);
        int fd = ::open(info.path, O_RDONLY, 0);
        if ( fd == -1 )
                throwf("can't open file, errno=%d", errno);
-       if ( info.fileLen < 20 )
-               throwf("file too small (length=%llu)", info.fileLen);
-
-       uint8_t* p = (uint8_t*)::mmap(NULL, info.fileLen, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
+       if ( ::fstat(fd, &stat_buf) != 0 )
+               throwf("fstat(%s) failed, errno=%d\n", info.path, errno);
+       if ( stat_buf.st_size < 20 )
+               throwf("file too small (length=%llu)", stat_buf.st_size);
+       int64_t len = stat_buf.st_size;
+       uint8_t* p = (uint8_t*)::mmap(NULL, stat_buf.st_size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
        if ( p == (uint8_t*)(-1) )
                throwf("can't map file, errno=%d", errno);
 
        if ( p == (uint8_t*)(-1) )
                throwf("can't map file, errno=%d", errno);
 
@@ -254,23 +262,23 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib
                if ( sliceFound ) {
                        uint32_t fileOffset = OSSwapBigToHostInt32(archs[sliceToUse].offset);
                        len = OSSwapBigToHostInt32(archs[sliceToUse].size);
                if ( sliceFound ) {
                        uint32_t fileOffset = OSSwapBigToHostInt32(archs[sliceToUse].offset);
                        len = OSSwapBigToHostInt32(archs[sliceToUse].size);
-                       if ( fileOffset+len > info.fileLen ) {
+                       if ( fileOffset+len > stat_buf.st_size ) {
                                // <rdar://problem/17593430> file size was read awhile ago.  If file is being written, wait a second to see if big enough now
                                sleep(1);
                                // <rdar://problem/17593430> file size was read awhile ago.  If file is being written, wait a second to see if big enough now
                                sleep(1);
-                               uint64_t newFileLen = info.fileLen;
+                               int64_t newFileLen = stat_buf.st_size;
                                struct stat statBuffer;
                                if ( stat(info.path, &statBuffer) == 0 ) {
                                        newFileLen = statBuffer.st_size;
                                }
                                if ( fileOffset+len > newFileLen ) {
                                        throwf("truncated fat file. Slice from %u to %llu is past end of file with length %llu", 
                                struct stat statBuffer;
                                if ( stat(info.path, &statBuffer) == 0 ) {
                                        newFileLen = statBuffer.st_size;
                                }
                                if ( fileOffset+len > newFileLen ) {
                                        throwf("truncated fat file. Slice from %u to %llu is past end of file with length %llu", 
-                                               fileOffset, fileOffset+len, info.fileLen);
+                                               fileOffset, fileOffset+len, stat_buf.st_size);
                                }
                        }
                        // if requested architecture is page aligned within fat file, then remap just that portion of file
                        if ( (fileOffset & 0x00000FFF) == 0 ) {
                                // unmap whole file
                                }
                        }
                        // if requested architecture is page aligned within fat file, then remap just that portion of file
                        if ( (fileOffset & 0x00000FFF) == 0 ) {
                                // unmap whole file
-                               munmap((caddr_t)p, info.fileLen);
+                               munmap((caddr_t)p, stat_buf.st_size);
                                // re-map just part we need
                                p = (uint8_t*)::mmap(NULL, len, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, fileOffset);
                                if ( p == (uint8_t*)(-1) )
                                // re-map just part we need
                                p = (uint8_t*)::mmap(NULL, len, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, fileOffset);
                                if ( p == (uint8_t*)(-1) )
@@ -294,7 +302,16 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib
        objOpts.neverConvertDwarf   = !_options.needsUnwindInfoSection();
        objOpts.verboseOptimizationHints = _options.verboseOptimizationHints();
        objOpts.armUsesZeroCostExceptions = _options.armUsesZeroCostExceptions();
        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.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);
        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 +326,8 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib
                OSAtomicIncrement32(&_totalObjectLoaded);
                return objResult;
        }
                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() ) {
        ld::dylib::File* dylibResult;
        bool dylibsNotAllowed = false;
        switch ( _options.outputKind() ) {
@@ -321,6 +338,10 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib
                        if ( dylibResult != NULL ) {
                                return dylibResult;
                        }
                        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:
                        break;
                case Options::kStaticExecutable:
                case Options::kDyld:
@@ -331,7 +352,6 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib
                        break;
        }
 
                        break;
        }
 
-
        // see if it is a static library
        ::archive::ParserOptions archOpts;
        archOpts.objOpts                                = objOpts;
        // see if it is a static library
        ::archive::ParserOptions archOpts;
        archOpts.objOpts                                = objOpts;
@@ -341,8 +361,17 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib
        archOpts.objcABI2                               = _options.objCABIVersion2POverride();
        archOpts.verboseLoad                    = _options.whyLoad();
        archOpts.logAllFiles                    = _options.logAllFiles();
        archOpts.objcABI2                               = _options.objCABIVersion2POverride();
        archOpts.verboseLoad                    = _options.whyLoad();
        archOpts.logAllFiles                    = _options.logAllFiles();
+       // Set ObjSource Kind, libclang_rt is compiler static library
+       if ( isCompilerSupportLib(info.path) )
+               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 ) {
        ld::archive::File* archiveResult = ::archive::parse(p, len, info.path, info.modTime, info.ordinal, archOpts);
        if ( archiveResult != NULL ) {
+       
                OSAtomicAdd64(len, &_totalArchiveSize);
                OSAtomicIncrement32(&_totalArchivesLoaded);
                return archiveResult;
                OSAtomicAdd64(len, &_totalArchiveSize);
                OSAtomicIncrement32(&_totalArchivesLoaded);
                return archiveResult;
@@ -395,7 +424,7 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib
        }
 }
 
        }
 }
 
-void InputFiles::logDylib(ld::File* file, bool indirect)
+void InputFiles::logDylib(ld::File* file, bool indirect, bool speculative)
 {
        if ( _options.traceDylibs() ) {
                const char* fullPath = file->path();
 {
        if ( _options.traceDylibs() ) {
                const char* fullPath = file->path();
@@ -407,11 +436,19 @@ void InputFiles::logDylib(ld::File* file, bool indirect)
                        // don't log upward dylibs when XBS is computing dependencies
                        logTraceInfo("[Logging for XBS] Used upward dynamic library: %s\n", fullPath);
                }
                        // don't log upward dylibs when XBS is computing dependencies
                        logTraceInfo("[Logging for XBS] Used upward dynamic library: %s\n", fullPath);
                }
+               else if ( (dylib != NULL ) && dylib->speculativelyLoaded() ) {
+                       logTraceInfo("[Logging for XBS] Speculatively loaded dynamic library: %s\n", fullPath);
+               }
                else {
                else {
-                       if ( indirect ) 
-                               logTraceInfo("[Logging for XBS] Used indirect dynamic library: %s\n", fullPath);
-                       else 
+                       if ( indirect ) {
+                               if ( speculative )
+                                       logTraceInfo("[Logging for XBS] Speculatively loaded indirect dynamic library: %s\n", fullPath);
+                               else
+                                       logTraceInfo("[Logging for XBS] Used indirect dynamic library: %s\n", fullPath);
+                       }
+                       else {
                                logTraceInfo("[Logging for XBS] Used dynamic library: %s\n", fullPath);
                                logTraceInfo("[Logging for XBS] Used dynamic library: %s\n", fullPath);
+                       }
                }
        }
        
                }
        }
        
@@ -437,7 +474,7 @@ void InputFiles::logDylib(ld::File* file, bool indirect)
 
 void InputFiles::logArchive(ld::File* file) const
 {
 
 void InputFiles::logArchive(ld::File* file) const
 {
-       if ( _options.traceArchives() && (_archiveFilesLogged.count(file) == 0) ) {
+       if ( (_options.traceArchives() || _options.traceEmitJSON()) && (_archiveFilesLogged.count(file) == 0) ) {
                // <rdar://problem/4947347> LD_TRACE_ARCHIVES should only print out when a .o is actually used from an archive
                _archiveFilesLogged.insert(file);
                const char* fullPath = file->path();
                // <rdar://problem/4947347> LD_TRACE_ARCHIVES should only print out when a .o is actually used from an archive
                _archiveFilesLogged.insert(file);
                const char* fullPath = file->path();
@@ -445,45 +482,25 @@ void InputFiles::logArchive(ld::File* file) const
                if ( realpath(fullPath, realName) != NULL )
                        fullPath = realName;
                logTraceInfo("[Logging for XBS] Used static archive: %s\n", fullPath);
                if ( realpath(fullPath, realName) != NULL )
                        fullPath = realName;
                logTraceInfo("[Logging for XBS] Used static archive: %s\n", fullPath);
+               
+               std::string archivePath(fullPath);
+               _archiveFilePaths.push_back(archivePath);
        }
 }
 
 
 void InputFiles::logTraceInfo(const char* format, ...) const
 {
        }
 }
 
 
 void InputFiles::logTraceInfo(const char* format, ...) const
 {
-       // one time open() of custom LD_TRACE_FILE
-       static int trace_file = -1;
-       if ( trace_file == -1 ) {
-               const char *trace_file_path = _options.traceOutputFile();
-               if ( trace_file_path != NULL ) {
-                       trace_file = open(trace_file_path, O_WRONLY | O_APPEND | O_CREAT, 0666);
-                       if ( trace_file == -1 )
-                               throwf("Could not open or create trace file (errno=%d): %s", errno, trace_file_path);
-               }
-               else {
-                       trace_file = fileno(stderr);
-               }
-       }
-
        char trace_buffer[MAXPATHLEN * 2];
     va_list ap;
        va_start(ap, format);
        int length = vsnprintf(trace_buffer, sizeof(trace_buffer), format, ap);
        va_end(ap);
        char trace_buffer[MAXPATHLEN * 2];
     va_list ap;
        va_start(ap, format);
        int length = vsnprintf(trace_buffer, sizeof(trace_buffer), format, ap);
        va_end(ap);
-       char* buffer_ptr = trace_buffer;
-
-       while (length > 0) {
-               ssize_t amount_written = write(trace_file, buffer_ptr, length);
-               if(amount_written == -1)
-                       /* Failure to write shouldn't fail the build. */
-                       return;
-               buffer_ptr += amount_written;
-               length -= amount_written;
-       }
+       _options.writeToTraceFile(trace_buffer, length);
 }
 
 
 }
 
 
-ld::dylib::File* InputFiles::findDylib(const char* installPath, const char* fromPath)
+ld::dylib::File* InputFiles::findDylib(const char* installPath, const ld::dylib::File* fromDylib, bool speculative)
 {
        //fprintf(stderr, "findDylib(%s, %s)\n", installPath, fromPath);
        InstallNameToDylib::iterator pos = _installPathToDylibs.find(installPath);
 {
        //fprintf(stderr, "findDylib(%s, %s)\n", installPath, fromPath);
        InstallNameToDylib::iterator pos = _installPathToDylibs.find(installPath);
@@ -504,7 +521,7 @@ ld::dylib::File* InputFiles::findDylib(const char* installPath, const char* from
                                        if ( dylibReader != NULL ) {
                                                addDylib(dylibReader, info);
                                                //_installPathToDylibs[strdup(installPath)] = dylibReader;
                                        if ( dylibReader != NULL ) {
                                                addDylib(dylibReader, info);
                                                //_installPathToDylibs[strdup(installPath)] = dylibReader;
-                                               this->logDylib(dylibReader, true);
+                                               this->logDylib(dylibReader, true, speculative);
                                                return dylibReader;
                                        }
                                        else 
                                                return dylibReader;
                                        }
                                        else 
@@ -515,20 +532,9 @@ ld::dylib::File* InputFiles::findDylib(const char* installPath, const char* from
                                }
                        }
                }
                                }
                        }
                }
-               char newPath[MAXPATHLEN];
-               // handle @loader_path
-               if ( strncmp(installPath, "@loader_path/", 13) == 0 ) {
-                       strcpy(newPath, fromPath);
-                       char* addPoint = strrchr(newPath,'/');
-                       if ( addPoint != NULL )
-                               strcpy(&addPoint[1], &installPath[13]);
-                       else
-                               strcpy(newPath, &installPath[13]);
-                       installPath = newPath;
-               }
-               // note: @executable_path case is handled inside findFileUsingPaths()
-               // search for dylib using -F and -L paths
-               Options::FileInfo info = _options.findFileUsingPaths(installPath);
+
+               // search for dylib using -F and -L paths and expanding @ paths
+               Options::FileInfo info = _options.findIndirectDylib(installPath, fromDylib);
                _indirectDylibOrdinal = _indirectDylibOrdinal.nextIndirectDylibOrdinal();
                info.ordinal = _indirectDylibOrdinal;
                info.options.fIndirectDylib = true;
                _indirectDylibOrdinal = _indirectDylibOrdinal.nextIndirectDylibOrdinal();
                info.ordinal = _indirectDylibOrdinal;
                info.options.fIndirectDylib = true;
@@ -539,7 +545,7 @@ ld::dylib::File* InputFiles::findDylib(const char* installPath, const char* from
                                //assert(_installPathToDylibs.find(installPath) !=  _installPathToDylibs.end());
                                //_installPathToDylibs[strdup(installPath)] = dylibReader;
                                addDylib(dylibReader, info);
                                //assert(_installPathToDylibs.find(installPath) !=  _installPathToDylibs.end());
                                //_installPathToDylibs[strdup(installPath)] = dylibReader;
                                addDylib(dylibReader, info);
-                               this->logDylib(dylibReader, true);
+                               this->logDylib(dylibReader, true, speculative);
                                return dylibReader;
                        }
                        else 
                                return dylibReader;
                        }
                        else 
@@ -561,77 +567,126 @@ 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;
 }
 
                        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;
+       }
+
+       char realDylibPath[PATH_MAX];
+       if ( (realpath(path, realDylibPath) != NULL) && (strcmp(path, realDylibPath) != 0) ) {
+               return libraryAlreadyLoaded(realDylibPath);
+       }
+
+       return false;
+}
+
 
 void InputFiles::addLinkerOptionLibraries(ld::Internal& state, ld::File::AtomHandler& handler)
 {      
 
 void InputFiles::addLinkerOptionLibraries(ld::Internal& state, ld::File::AtomHandler& handler)
 {      
-    if ( _options.outputKind() == Options::kObjectFile ) 
-               return;
-
-       // process frameworks specified in .o linker options
-       for (CStringSet::const_iterator it = state.linkerOptionFrameworks.begin(); it != state.linkerOptionFrameworks.end(); ++it) {
-               const char* frameworkName = *it;
-               Options::FileInfo info = _options.findFramework(frameworkName);
-               if ( ! this->libraryAlreadyLoaded(info.path) ) {
-                       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() ) {
+       if ( _options.outputKind() == Options::kObjectFile )
+               return;
+  
+       while (! state.unprocessedLinkerOptionLibraries.empty() || ! state.unprocessedLinkerOptionFrameworks.empty()) {
+
+               // process frameworks specified in .o linker options
+               CStringSet newFrameworks = std::move(state.unprocessedLinkerOptionFrameworks);
+               state.unprocessedLinkerOptionFrameworks.clear();
+               for (const char* frameworkName : newFrameworks) {
+                       if ( state.linkerOptionFrameworks.count(frameworkName) )
+                               continue;
+                       Options::FileInfo info = _options.findFramework(frameworkName);
+                       if ( ! this->frameworkAlreadyLoaded(info.path, frameworkName) ) {
+                               _linkerOptionOrdinal = _linkerOptionOrdinal.nextLinkerOptionOrdinal();
+                               info.ordinal = _linkerOptionOrdinal;
+                               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();
+                                                       dylibReader->setSpeculativelyLoaded();
+                                                       this->addDylib(dylibReader, info);
+                                               }
+                                       }
+                                       else {
+                                               throwf("framework linker option at %s is not a dylib", info.path);
+                                       }
+                               }
+                               catch (const char* msg) {
+                                       warning("Auto-Linking supplied '%s', %s", info.path, msg);
+                               }
+                       }
+                       state.linkerOptionFrameworks.insert(frameworkName);
+               }
+
+               // process libraries specified in .o linker options
+               // fixme optimize with std::move?
+               CStringSet newLibraries = std::move(state.unprocessedLinkerOptionLibraries);
+               state.unprocessedLinkerOptionLibraries.clear();
+               for (const char* libName : newLibraries) {
+                       if ( state.linkerOptionLibraries.count(libName) )
+                               continue;
+                       Options::FileInfo info = _options.findLibrary(libName);
+                       if ( ! this->libraryAlreadyLoaded(info.path) ) {
+                               _linkerOptionOrdinal = _linkerOptionOrdinal.nextLinkerOptionOrdinal();
+                               info.ordinal = _linkerOptionOrdinal;
+                               try {
+                                       //<rdar://problem/17787306> -force_load_swift_libs
+                                       info.options.fForceLoad = _options.forceLoadSwiftLibs() && (strncmp(libName, "swift", 5) == 0);
+                                       ld::File* reader = this->makeFile(info, true);
+                                       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();
                                                dylibReader->setImplicitlyLinked();
+                                               dylibReader->setSpeculativelyLoaded();
                                                this->addDylib(dylibReader, info);
                                        }
                                                this->addDylib(dylibReader, info);
                                        }
-                               }
-                               else {
-                                       throwf("framework linker option at %s is not a dylib", info.path);
-                               }
-                       }
-                       catch (const char* msg) {
-                               warning("Auto-Linking supplied '%s', %s", info.path, msg);
-                       }
-               }
-       }
-       // process libraries specified in .o linker options
-       for (CStringSet::const_iterator it = state.linkerOptionLibraries.begin(); it != state.linkerOptionLibraries.end(); ++it) {
-               const char* libName = *it;
-               Options::FileInfo info = _options.findLibrary(libName);
-               if ( ! this->libraryAlreadyLoaded(info.path) ) {
-                       info.ordinal = _linkerOptionOrdinal.nextLinkerOptionOrdinal();
-                       try {
-                               //<rdar://problem/17787306> -force_load_swift_libs
-                               info.options.fForceLoad = _options.forceLoadSwiftLibs() && (strncmp(libName, "swift", 5) == 0);
-                               ld::File* reader = this->makeFile(info, true);
-                               ld::dylib::File* dylibReader = dynamic_cast<ld::dylib::File*>(reader);
-                               ld::archive::File* archiveReader = dynamic_cast<ld::archive::File*>(reader);
-                               if ( dylibReader != NULL ) {
-                                       dylibReader->setImplicitlyLinked();
-                                       this->addDylib(dylibReader, info);
-                               }
-                               else if ( archiveReader != NULL ) {
-                                       _searchLibraries.push_back(LibraryInfo(archiveReader));
-                                       if ( _options.dumpDependencyInfo() )
-                                               _options.dumpDependency(Options::depArchive, archiveReader->path());
-                                       //<rdar://problem/17787306> -force_load_swift_libs
-                                       if (info.options.fForceLoad) {
-                                               archiveReader->forEachAtom(handler);
+                                       else if ( archiveReader != NULL ) {
+                                               _searchLibraries.push_back(LibraryInfo(archiveReader));
+                                               if ( _options.dumpDependencyInfo() )
+                                                       _options.dumpDependency(Options::depArchive, archiveReader->path());
+                                               //<rdar://problem/17787306> -force_load_swift_libs
+                                               if (info.options.fForceLoad) {
+                                                       archiveReader->forEachAtom(handler);
+                                               }
                                        }
                                        }
-                               }
-                               else {
-                                       throwf("linker option dylib at %s is not a dylib", info.path);
-                               }
-                       }
-                       catch (const char* msg) {
-                               warning("Auto-Linking supplied '%s', %s", info.path, msg);
-                       }
+                                       else {
+                                               throwf("linker option dylib at %s is not a dylib", info.path);
+                                       }
+                               }
+                               catch (const char* msg) {
+                                       warning("Auto-Linking supplied '%s', %s", info.path, msg);
+                               }
+                       }
+                       state.linkerOptionLibraries.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
        _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 ) {
        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__
        // 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__
 #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__
 #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
 #else
        #error unknown default architecture
 #endif
@@ -827,6 +889,7 @@ InputFiles::InputFiles(Options& opts, const char** archName)
        pthread_mutex_init(&_parseLock, NULL);
        pthread_cond_init(&_parseWorkReady, NULL);
        pthread_cond_init(&_newFileAvailable, NULL);
        pthread_mutex_init(&_parseLock, NULL);
        pthread_cond_init(&_parseWorkReady, NULL);
        pthread_cond_init(&_newFileAvailable, NULL);
+       _neededFileSlot = -1;
 #endif
        const std::vector<Options::FileInfo>& files = _options.getInputFiles();
        if ( files.size() == 0 )
 #endif
        const std::vector<Options::FileInfo>& files = _options.getInputFiles();
        if ( files.size() == 0 )
@@ -924,7 +987,7 @@ void InputFiles::parseWorkerThread() {
                        if (_s_logPThreads) printf("parsing index %u\n", slot);
                        try {
                                file = makeFile(entry, false);
                        if (_s_logPThreads) printf("parsing index %u\n", slot);
                        try {
                                file = makeFile(entry, false);
-                       } 
+                       }
                        catch (const char *msg) {
                                if ( (strstr(msg, "architecture") != NULL) && !_options.errorOnOtherArchFiles() ) {
                                        if ( _options.ignoreOtherArchInputFiles() ) {
                        catch (const char *msg) {
                                if ( (strstr(msg, "architecture") != NULL) && !_options.errorOnOtherArchFiles() ) {
                                        if ( _options.ignoreOtherArchInputFiles() ) {
@@ -1024,7 +1087,7 @@ ld::File* InputFiles::addDylib(ld::dylib::File* reader, const Options::FileInfo&
 
        // log direct readers
        if ( ! info.options.fIndirectDylib ) 
 
        // log direct readers
        if ( ! info.options.fIndirectDylib ) 
-               this->logDylib(reader, false);
+               this->logDylib(reader, false, false);
 
        // update stats
        _totalDylibsLoaded++;
 
        // update stats
        _totalDylibsLoaded++;
@@ -1150,8 +1213,12 @@ void InputFiles::forEachInitialAtom(ld::File::AtomHandler& handler, ld::Internal
                        {
                                ld::archive::File* archive = (ld::archive::File*)file;
                                // <rdar://problem/9740166> force loaded archives should be in LD_TRACE
                        {
                                ld::archive::File* archive = (ld::archive::File*)file;
                                // <rdar://problem/9740166> force loaded archives should be in LD_TRACE
-                               if ( (info.options.fForceLoad || _options.fullyLoadArchives()) && _options.traceArchives() ) 
+                               if ( (info.options.fForceLoad || _options.fullyLoadArchives()) && (_options.traceArchives() || _options.traceEmitJSON()) )
                                        logArchive(archive);
                                        logArchive(archive);
+
+                               if ( isCompilerSupportLib(info.path) && (info.options.fForceLoad || _options.fullyLoadArchives()) )
+                                       state.forceLoadCompilerRT = true;
+
                                _searchLibraries.push_back(LibraryInfo(archive));
                                if ( _options.dumpDependencyInfo() )
                                        _options.dumpDependency(Options::depArchive, archive->path());
                                _searchLibraries.push_back(LibraryInfo(archive));
                                if ( _options.dumpDependencyInfo() )
                                        _options.dumpDependency(Options::depArchive, archive->path());
@@ -1165,8 +1232,15 @@ void InputFiles::forEachInitialAtom(ld::File::AtomHandler& handler, ld::Internal
                        }
                                break;
                }
                        }
                                break;
                }
-               file->forEachAtom(handler);
+               try {
+                       file->forEachAtom(handler);
+               }
+               catch (const char* msg) {
+                       asprintf((char**)&_exception, "%s file '%s'", msg, file->path());
+               }
        }
        }
+       if (_exception)
+               throw _exception;
 
        markExplicitlyLinkedDylibs();
        addLinkerOptionLibraries(state, handler);
 
        markExplicitlyLinkedDylibs();
        addLinkerOptionLibraries(state, handler);
@@ -1247,16 +1321,17 @@ bool InputFiles::searchLibraries(const char* name, bool searchDylibs, bool searc
                 ld::archive::File *archiveFile = lib.archive();
                 if ( dataSymbolOnly ) {
                     if ( archiveFile->justInTimeDataOnlyforEachAtom(name, handler) ) {
                 ld::archive::File *archiveFile = lib.archive();
                 if ( dataSymbolOnly ) {
                     if ( archiveFile->justInTimeDataOnlyforEachAtom(name, handler) ) {
-                        if ( _options.traceArchives() 
+                        if ( _options.traceArchives() || _options.traceEmitJSON())
                             logArchive(archiveFile);
                         _options.snapshot().recordArchive(archiveFile->path());
                             logArchive(archiveFile);
                         _options.snapshot().recordArchive(archiveFile->path());
+                                               // DALLAS _state.archives.push_back(archiveFile);
                         // found data definition in static library, done
                        return true;
                     }
                 }
                 else {
                     if ( archiveFile->justInTimeforEachAtom(name, handler) ) {
                         // found data definition in static library, done
                        return true;
                     }
                 }
                 else {
                     if ( archiveFile->justInTimeforEachAtom(name, handler) ) {
-                        if ( _options.traceArchives() 
+                        if ( _options.traceArchives() || _options.traceEmitJSON())
                             logArchive(archiveFile);
                         _options.snapshot().recordArchive(archiveFile->path());
                         // found definition in static library, done
                             logArchive(archiveFile);
                         _options.snapshot().recordArchive(archiveFile->path());
                         // found definition in static library, done
@@ -1371,13 +1446,25 @@ void InputFiles::dylibs(ld::Internal& state)
                }
                // <rdar://problem/15002251> make implicit dylib order be deterministic by sorting by install_name
                std::sort(implicitDylibs.begin(), implicitDylibs.end(), DylibByInstallNameSorter());
                }
                // <rdar://problem/15002251> make implicit dylib order be deterministic by sorting by install_name
                std::sort(implicitDylibs.begin(), implicitDylibs.end(), DylibByInstallNameSorter());
+
+               if ( _options.traceDylibs() ) {
+                       for (ld::dylib::File* dylib :  implicitDylibs) {
+                               if ( dylib->speculativelyLoaded() && !dylib->explicitlyLinked() && dylib->providedExportAtom() ) {
+                                       const char* fullPath = dylib->path();
+                                       char realName[MAXPATHLEN];
+                                       if ( realpath(fullPath, realName) != NULL )
+                                               fullPath = realName;
+                                       logTraceInfo("[Logging for XBS] Used dynamic library: %s\n", fullPath);
+                               }
+                       }
+               }
                state.dylibs.insert(state.dylibs.end(), implicitDylibs.begin(), implicitDylibs.end());
        }
 
        //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;
                state.dylibs.insert(state.dylibs.end(), implicitDylibs.begin(), implicitDylibs.end());
        }
 
        //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
        //}
        
        // and -bundle_loader
@@ -1388,6 +1475,14 @@ void InputFiles::dylibs(ld::Internal& state)
                throw "dynamic main executables must link with libSystem.dylib";
 }
 
                throw "dynamic main executables must link with libSystem.dylib";
 }
 
+void InputFiles::archives(ld::Internal& state)
+{
+       for (const std::string path :  _archiveFilePaths) {
+               
+               state.archivePaths.push_back(path);
+       }
+}
+
 
 } // namespace tool 
 } // namespace ld 
 
 } // namespace tool 
 } // namespace ld