X-Git-Url: https://git.saurik.com/apple/ld64.git/blobdiff_plain/ba348e2165668ae0f4af8b349fc4a6d0910950ed..b1c6f52afb9f246c71bc8c8c57a268f11d0895e5:/src/ld/InputFiles.cpp?ds=sidebyside diff --git a/src/ld/InputFiles.cpp b/src/ld/InputFiles.cpp index 30c0875..1c69de6 100644 --- a/src/ld/InputFiles.cpp +++ b/src/ld/InputFiles.cpp @@ -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) { @@ -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 - 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,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 ( fileOffset+len > info.fileLen ) { + if ( fileOffset+len > stat_buf.st_size ) { // 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", - 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 - 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) ) @@ -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.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 +326,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 +338,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 +352,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,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(); + // 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; @@ -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(); @@ -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); } + 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); + } } } @@ -437,7 +474,7 @@ void InputFiles::logDylib(ld::File* file, bool indirect) void InputFiles::logArchive(ld::File* file) const { - if ( _options.traceArchives() && (_archiveFilesLogged.count(file) == 0) ) { + if ( (_options.traceArchives() || _options.traceEmitJSON()) && (_archiveFilesLogged.count(file) == 0) ) { // 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); + + 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); @@ -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; - this->logDylib(dylibReader, true); + this->logDylib(dylibReader, true, speculative); 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; @@ -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); - this->logDylib(dylibReader, true); + this->logDylib(dylibReader, true, speculative); 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::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; + } + + 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) { - 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(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(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 { + // -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(reader); + ld::archive::File* archiveReader = dynamic_cast(reader); + if ( dylibReader != NULL ) { + 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); - } - } - } - // 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 { - // -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(reader); - ld::archive::File* archiveReader = dynamic_cast(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()); - // -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()); + // -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 - uint8_t buffer[sizeof(mach_header_64)]; + uint8_t buffer[4096]; const std::vector& files = opts.getInputFiles(); for (std::vector::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 @@ -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); + _neededFileSlot = -1; #endif const std::vector& 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); - } + } 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 ) - this->logDylib(reader, false); + this->logDylib(reader, false, false); // update stats _totalDylibsLoaded++; @@ -1150,8 +1213,12 @@ void InputFiles::forEachInitialAtom(ld::File::AtomHandler& handler, ld::Internal { ld::archive::File* archive = (ld::archive::File*)file; // 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()); @@ -1165,8 +1232,15 @@ 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, 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) ) { - 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 @@ -1371,13 +1446,25 @@ void InputFiles::dylibs(ld::Internal& state) } // 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::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 @@ -1388,6 +1475,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