X-Git-Url: https://git.saurik.com/apple/ld64.git/blobdiff_plain/ba348e2165668ae0f4af8b349fc4a6d0910950ed..ec29ba20dfd4abc0cb74366b39dda06af136e073:/src/ld/InputFiles.cpp diff --git a/src/ld/InputFiles.cpp b/src/ld/InputFiles.cpp index 30c0875..ab31d4a 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" @@ -294,7 +295,16 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib objOpts.neverConvertDwarf = !_options.needsUnwindInfoSection(); objOpts.verboseOptimizationHints = _options.verboseOptimizationHints(); objOpts.armUsesZeroCostExceptions = _options.armUsesZeroCostExceptions(); + objOpts.simulator = _options.targetIOSSimulator(); + objOpts.ignoreMismatchPlatform = ((_options.outputKind() == Options::kPreload) || (_options.outputKind() == Options::kStaticExecutable)); objOpts.subType = _options.subArchitecture(); + objOpts.platform = _options.platform(); + objOpts.minOSVersion = _options.minOSversion(); + objOpts.srcKind = ld::relocatable::File::kSourceObj; + objOpts.treateBitcodeAsData = _options.bitcodeKind() == Options::kBitcodeAsData; + objOpts.usingBitcode = _options.bundleBitcode(); + objOpts.maxDefaultCommonAlignment = _options.maxDefaultCommonAlign(); + ld::relocatable::File* objResult = mach_o::relocatable::parse(p, len, info.path, info.modTime, info.ordinal, objOpts); if ( objResult != NULL ) { OSAtomicAdd64(len, &_totalObjectSize); @@ -309,8 +319,8 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib OSAtomicIncrement32(&_totalObjectLoaded); return objResult; } - - // see if it is a dynamic library + + // see if it is a dynamic library (or text-based dynamic library) ld::dylib::File* dylibResult; bool dylibsNotAllowed = false; switch ( _options.outputKind() ) { @@ -321,6 +331,10 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib if ( dylibResult != NULL ) { return dylibResult; } + dylibResult = textstub::dylib::parse(p, len, info.path, info.modTime, _options, info.ordinal, info.options.fBundleLoader, indirectDylib); + if ( dylibResult != NULL ) { + return dylibResult; + } break; case Options::kStaticExecutable: case Options::kDyld: @@ -331,7 +345,6 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib break; } - // see if it is a static library ::archive::ParserOptions archOpts; archOpts.objOpts = objOpts; @@ -341,6 +354,15 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib archOpts.objcABI2 = _options.objCABIVersion2POverride(); archOpts.verboseLoad = _options.whyLoad(); archOpts.logAllFiles = _options.logAllFiles(); + // Set ObjSource Kind, libclang_rt is compiler static library + const char* libName = strrchr(info.path, '/'); + if ( (libName != NULL) && (strncmp(libName, "/libclang_rt", 12) == 0) ) + archOpts.objOpts.srcKind = ld::relocatable::File::kSourceCompilerArchive; + else + archOpts.objOpts.srcKind = ld::relocatable::File::kSourceArchive; + archOpts.objOpts.treateBitcodeAsData = _options.bitcodeKind() == Options::kBitcodeAsData; + archOpts.objOpts.usingBitcode = _options.bundleBitcode(); + ld::archive::File* archiveResult = ::archive::parse(p, len, info.path, info.modTime, info.ordinal, archOpts); if ( archiveResult != NULL ) { OSAtomicAdd64(len, &_totalArchiveSize); @@ -561,15 +583,40 @@ void InputFiles::markExplicitlyLinkedDylibs() } } -bool InputFiles::libraryAlreadyLoaded(const char* path) +bool InputFiles::frameworkAlreadyLoaded(const char* path, const char* frameworkName) { - for (std::vector::const_iterator it = _inputFiles.begin(); it != _inputFiles.end(); ++it) { - if ( strcmp(path, (*it)->path()) == 0 ) + for (ld::File* file : _inputFiles) { + if ( strcmp(path, file->path()) == 0 ) + return true; + } + for (ld::dylib::File* dylibx : _allDylibs) { + const char* fname = dylibx->frameworkName(); + if ( fname == NULL ) + continue; + if ( strcmp(frameworkName, fname) == 0 ) return true; } return false; } +bool InputFiles::libraryAlreadyLoaded(const char* path) +{ + for (ld::File* file : _inputFiles) { + if ( strcmp(path, file->path()) == 0 ) + return true; + } + for (ld::dylib::File* dylib : _allDylibs) { + if ( strcmp(path, dylib->path()) == 0 ) + return true; + } + for (const LibraryInfo& libInfo : _searchLibraries) { + if ( strcmp(path, libInfo.archive()->path()) == 0 ) + return true; + } + + return false; +} + void InputFiles::addLinkerOptionLibraries(ld::Internal& state, ld::File::AtomHandler& handler) { @@ -579,14 +626,17 @@ void InputFiles::addLinkerOptionLibraries(ld::Internal& state, ld::File::AtomHan // process frameworks specified in .o linker options for (CStringSet::const_iterator it = state.linkerOptionFrameworks.begin(); it != state.linkerOptionFrameworks.end(); ++it) { const char* frameworkName = *it; + if ( state.linkerOptionFrameworksProcessed.count(frameworkName) ) + continue; Options::FileInfo info = _options.findFramework(frameworkName); - if ( ! this->libraryAlreadyLoaded(info.path) ) { + if ( ! this->frameworkAlreadyLoaded(info.path, frameworkName) ) { info.ordinal = _linkerOptionOrdinal.nextLinkerOptionOrdinal(); try { ld::File* reader = this->makeFile(info, true); ld::dylib::File* dylibReader = dynamic_cast(reader); if ( dylibReader != NULL ) { if ( ! dylibReader->installPathVersionSpecific() ) { + dylibReader->forEachAtom(handler); dylibReader->setImplicitlyLinked(); this->addDylib(dylibReader, info); } @@ -599,10 +649,13 @@ void InputFiles::addLinkerOptionLibraries(ld::Internal& state, ld::File::AtomHan warning("Auto-Linking supplied '%s', %s", info.path, msg); } } + state.linkerOptionFrameworksProcessed.insert(frameworkName); } // process libraries specified in .o linker options for (CStringSet::const_iterator it = state.linkerOptionLibraries.begin(); it != state.linkerOptionLibraries.end(); ++it) { const char* libName = *it; + if ( state.linkerOptionLibrariesProcessed.count(libName) ) + continue; Options::FileInfo info = _options.findLibrary(libName); if ( ! this->libraryAlreadyLoaded(info.path) ) { info.ordinal = _linkerOptionOrdinal.nextLinkerOptionOrdinal(); @@ -613,6 +666,7 @@ void InputFiles::addLinkerOptionLibraries(ld::Internal& state, ld::File::AtomHan ld::dylib::File* dylibReader = dynamic_cast(reader); ld::archive::File* archiveReader = dynamic_cast(reader); if ( dylibReader != NULL ) { + dylibReader->forEachAtom(handler); dylibReader->setImplicitlyLinked(); this->addDylib(dylibReader, info); } @@ -633,6 +687,7 @@ void InputFiles::addLinkerOptionLibraries(ld::Internal& state, ld::File::AtomHan warning("Auto-Linking supplied '%s', %s", info.path, msg); } } + state.linkerOptionLibrariesProcessed.insert(libName); } } @@ -775,20 +830,27 @@ void InputFiles::inferArchitecture(Options& opts, const char** archName) _inferredArch = true; // scan all input files, looking for a thin .o file. // the first one found is presumably the architecture to link - uint8_t buffer[sizeof(mach_header_64)]; + uint8_t buffer[4096]; const std::vector& 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 @@ -1377,7 +1439,7 @@ void InputFiles::dylibs(ld::Internal& state) //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