]> git.saurik.com Git - apple/ld64.git/blobdiff - src/ld/InputFiles.cpp
ld64-351.8.tar.gz
[apple/ld64.git] / src / ld / InputFiles.cpp
index f49f2e350d820c0d6364cbf0045400ce89b77dcd..2a79ae2ced8b5edcff7df38a3250c81e0ec1f6f8 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"
@@ -176,6 +177,11 @@ private:
 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)
 {
@@ -208,15 +214,26 @@ const char* InputFiles::fileArch(const uint8_t* p, unsigned len)
 
 ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib)
 {
+       // handle inlined framework first.
+       if (info.isInlined) {
+               auto interface = _options.findTAPIFile(info.path);
+               auto file = textstub::dylib::parse(info.path, std::move(interface), info.modTime, info.ordinal, _options, indirectDylib);
+               assert(file && "could not locate the inlined file");
+               if (!file)
+                       throwf("could not parse inline dylib file: %s(%s)", interface->getInstallName().c_str(), info.path);
+               return file;
+       }
        // 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);
-       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);
 
@@ -254,14 +271,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 ( fileOffset+len > info.fileLen ) {
-                               throwf("truncated fat file. Slice from %u to %llu is past end of file with length %llu", 
-                                               fileOffset, 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);
+                               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", 
+                                               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
-                               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) )
@@ -284,7 +310,17 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib
        objOpts.forceDwarfConversion= (_options.outputKind() == Options::kDyld);
        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);
@@ -299,11 +335,30 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib
                OSAtomicIncrement32(&_totalObjectLoaded);
                return objResult;
        }
-       
-       // see if it is a dynamic library
-       ld::dylib::File* dylibResult = mach_o::dylib::parse(p, len, info.path, info.modTime, _options, info.ordinal, info.options.fBundleLoader, indirectDylib);
-       if ( dylibResult != NULL ) {
-               return dylibResult;
+
+       // see if it is a dynamic library (or text-based dynamic library)
+       ld::dylib::File* dylibResult;
+       bool dylibsNotAllowed = false;
+       switch ( _options.outputKind() ) {
+               case Options::kDynamicExecutable:
+               case Options::kDynamicLibrary:
+               case Options::kDynamicBundle:   
+                       dylibResult = mach_o::dylib::parse(p, len, info.path, info.modTime, _options, info.ordinal, info.options.fBundleLoader, 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:
+               case Options::kPreload:
+               case Options::kObjectFile:
+               case Options::kKextBundle:
+                       dylibsNotAllowed = true;
+                       break;
        }
 
        // see if it is a static library
@@ -315,8 +370,17 @@ 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
+       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 ) {
+       
                OSAtomicAdd64(len, &_totalArchiveSize);
                OSAtomicIncrement32(&_totalArchivesLoaded);
                return archiveResult;
@@ -350,6 +414,13 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib
                }
        }
 
+       if ( dylibsNotAllowed ) {
+               cpu_type_t dummy1;
+               cpu_type_t dummy2;
+               if ( mach_o::dylib::isDylibFile(p, &dummy1, &dummy2) )
+                       throw "ignoring unexpected dylib file";
+       }
+
        // error handling
        if ( ((fat_header*)p)->magic == OSSwapBigToHostInt32(FAT_MAGIC) ) {
                throwf("missing required architecture %s in file %s (%u slices)", _options.architectureName(), info.path, sliceCount);
@@ -362,7 +433,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();
@@ -374,37 +445,45 @@ 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);
                }
+               else if ( (dylib != NULL ) && dylib->speculativelyLoaded() ) {
+                       logTraceInfo("[Logging for XBS] Speculatively loaded dynamic library: %s\n", fullPath);
+               }
                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);
+                       }
                }
        }
        
        if ( _options.dumpDependencyInfo() ) {
                const ld::dylib::File* dylib = dynamic_cast<const ld::dylib::File*>(file);
                if ( file == _bundleLoader ) {
-                       _options.dumpDependency(Options::depBundleLoader, file->path());
+                       _options.addDependency(Options::depBundleLoader, file->path());
                }
                else if ( (dylib != NULL ) && dylib->willBeUpwardDylib() ) {
                        if ( indirect ) 
-                               _options.dumpDependency(Options::depUpwardIndirectDylib, file->path());
+                               _options.addDependency(Options::depUpwardIndirectDylib, file->path());
                        else 
-                               _options.dumpDependency(Options::depUpwardDirectDylib, file->path());
+                               _options.addDependency(Options::depUpwardDirectDylib, file->path());
                }
                else {
                        if ( indirect ) 
-                               _options.dumpDependency(Options::depIndirectDylib, file->path());
+                               _options.addDependency(Options::depIndirectDylib, file->path());
                        else 
-                               _options.dumpDependency(Options::depDirectDylib, file->path());
+                               _options.addDependency(Options::depDirectDylib, file->path());
                }
        }
 }
 
 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();
@@ -412,45 +491,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);
+               
+               std::string archivePath(fullPath);
+               _archiveFilePaths.push_back(archivePath);
        }
 }
 
 
 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* 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);
@@ -471,7 +530,7 @@ ld::dylib::File* InputFiles::findDylib(const char* installPath, const char* from
                                        if ( dylibReader != NULL ) {
                                                addDylib(dylibReader, info);
                                                //_installPathToDylibs[strdup(installPath)] = dylibReader;
-                                               this->logDylib(dylibReader, true);
+                                               this->logDylib(dylibReader, true, speculative);
                                                return dylibReader;
                                        }
                                        else 
@@ -482,20 +541,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;
@@ -506,7 +554,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);
-                               this->logDylib(dylibReader, true);
+                               this->logDylib(dylibReader, true, speculative);
                                return dylibReader;
                        }
                        else 
@@ -528,71 +576,134 @@ void InputFiles::markExplicitlyLinkedDylibs()
        }
 }
 
-bool InputFiles::libraryAlreadyLoaded(const char* path) 
+bool InputFiles::frameworkAlreadyLoaded(const char* path, const char* frameworkName)
+{
+       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 (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* 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)
+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();
+       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;
                        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->setImplicitlyLinked();
-                                               this->addDylib(dylibReader, info);
+                               Options::FileInfo info = _options.findFramework(frameworkName);
+                               if ( ! this->frameworkAlreadyLoaded(info.path, frameworkName) ) {
+                                       _linkerOptionOrdinal = _linkerOptionOrdinal.nextLinkerOptionOrdinal();
+                                       info.ordinal = _linkerOptionOrdinal;
+                                       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 ) {
+                                               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);
-                               }
-                       }
+                                       else if ( archiveReader != NULL ) {
+                                               _searchLibraries.push_back(LibraryInfo(archiveReader));
+                                               _options.addDependency(Options::depArchive, archiveReader->path());
+                                               //<rdar://problem/17787306> -force_load_swift_libs
+                                               if (info.options.fForceLoad) {
+                                                       archiveReader->forEachAtom(handler);
+                                               }
+                                       }
+                                       else {
+                                               throwf("framework linker option at %s is not a dylib and not an archive", info.path);
+                                       }
+                               }
+                       }
                        catch (const char* msg) {
-                               warning("Auto-Linking supplied '%s', %s", info.path, msg);
+                               warning("Auto-Linking %s", 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();
+                       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;
                        try {
-                               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());
-                               }
-                               else {
-                                       throwf("linker option dylib at %s is not a dylib", info.path);
-                               }
-                       }
+                               Options::FileInfo info = _options.findLibrary(libName);
+                               if ( ! this->libraryAlreadyLoaded(info.path) ) {
+                                       _linkerOptionOrdinal = _linkerOptionOrdinal.nextLinkerOptionOrdinal();
+                                       info.ordinal = _linkerOptionOrdinal;
+                                       //<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->setSpeculativelyLoaded();
+                                               this->addDylib(dylibReader, info);
+                                       }
+                                       else if ( archiveReader != NULL ) {
+                                               _searchLibraries.push_back(LibraryInfo(archiveReader));
+                                               _options.addDependency(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);
+                               warning("Auto-Linking %s", msg);
                        }
+                       state.linkerOptionLibraries.insert(libName);
                }
        }
 }
@@ -642,8 +753,7 @@ void InputFiles::createOpaqueFileSections()
        // extra command line sections always at end
        for (Options::ExtraSection::const_iterator it=_options.extraSectionsBegin(); it != _options.extraSectionsEnd(); ++it) {
                _inputFiles.push_back(opaque_section::parse(it->segmentName, it->sectionName, it->path, it->data, it->dataLen));
-               if ( _options.dumpDependencyInfo() )
-                       _options.dumpDependency(Options::depSection, it->path);
+               _options.addDependency(Options::depSection, it->path);
        }
 
 }
@@ -736,20 +846,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;
+                                       }
                                }
                        }
                }
@@ -758,11 +875,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
@@ -788,6 +905,7 @@ InputFiles::InputFiles(Options& opts, const char** archName)
        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 )
@@ -885,7 +1003,7 @@ void InputFiles::parseWorkerThread() {
                        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() ) {
@@ -895,6 +1013,9 @@ void InputFiles::parseWorkerThread() {
                                                warning("ignoring file %s, %s", entry.path, msg);
                                        }
                                } 
+                               else if ( strstr(msg, "ignoring unexpected") != NULL ) {
+                                       warning("%s, %s", entry.path, msg);
+                               }
                                else {
                                        asprintf((char**)&exception, "%s file '%s'", msg, entry.path);
                                }
@@ -982,7 +1103,7 @@ ld::File* InputFiles::addDylib(ld::dylib::File* reader, const Options::FileInfo&
 
        // log direct readers
        if ( ! info.options.fIndirectDylib ) 
-               this->logDylib(reader, false);
+               this->logDylib(reader, false, false);
 
        // update stats
        _totalDylibsLoaded++;
@@ -1094,8 +1215,7 @@ void InputFiles::forEachInitialAtom(ld::File::AtomHandler& handler, ld::Internal
                        {
                                ld::relocatable::File* reloc = (ld::relocatable::File*)file;
                                _options.snapshot().recordObjectFile(reloc->path());
-                               if ( _options.dumpDependencyInfo() )
-                                       _options.dumpDependency(Options::depObjectFile, reloc->path());
+                               _options.addDependency(Options::depObjectFile, reloc->path());
                        }
                                break;
                        case ld::File::Dylib:
@@ -1108,11 +1228,14 @@ 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
-                               if ( (info.options.fForceLoad || _options.fullyLoadArchives()) && _options.traceArchives() ) 
+                               if ( (info.options.fForceLoad || _options.fullyLoadArchives()) && (_options.traceArchives() || _options.traceEmitJSON()) )
                                        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());
+                               _options.addDependency(Options::depArchive, archive->path());
                        }
                                break;
                        case ld::File::Other:
@@ -1123,11 +1246,18 @@ void InputFiles::forEachInitialAtom(ld::File::AtomHandler& handler, ld::Internal
                        }
                                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);
+       addLinkerOptionLibraries(state, handler);
        createIndirectDylibs();
        createOpaqueFileSections();
        
@@ -1205,16 +1335,17 @@ bool InputFiles::searchLibraries(const char* name, bool searchDylibs, bool searc
                 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());
+                                               // DALLAS _state.archives.push_back(archiveFile);
                         // 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
@@ -1276,6 +1407,14 @@ static bool vectorContains(const std::vector<ld::dylib::File*>& vec, ld::dylib::
        return std::find(vec.begin(), vec.end(), key) != vec.end();
 }
 
+struct DylibByInstallNameSorter
+{      
+        bool operator()(const ld::dylib::File* left, const ld::dylib::File* right)
+        {
+          return (strcmp(left->installPath(), right->installPath()) < 0);
+        }
+};
+
 void InputFiles::dylibs(ld::Internal& state)
 {
        bool dylibsOK = false;
@@ -1310,20 +1449,36 @@ void InputFiles::dylibs(ld::Internal& state)
        }
        // add implicitly linked dylibs
        if ( _options.nameSpace() == Options::kTwoLevelNameSpace ) {
+               std::vector<ld::dylib::File*> implicitDylibs;
                for (InstallNameToDylib::const_iterator it=_installPathToDylibs.begin(); it != _installPathToDylibs.end(); ++it) {
                        ld::dylib::File* dylibFile = it->second;
                        if ( dylibFile->implicitlyLinked() && dylibsOK ) {
-                               if ( ! vectorContains(state.dylibs, dylibFile) ) {
-                                       state.dylibs.push_back(dylibFile);
+                               if ( ! vectorContains(implicitDylibs, dylibFile) ) {
+                                       implicitDylibs.push_back(dylibFile);
                                }
                        }
                }
+               // <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;
-       //      fprintf(stderr, "    %p %s\n", dylib, dylib->path());
+       //      fprintf(stderr, "    %p impl=%d %s\n", dylib, dylib->implicitlyLinked(), dylib->path());
        //}
        
        // and -bundle_loader
@@ -1334,6 +1489,14 @@ void InputFiles::dylibs(ld::Internal& state)
                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