]> git.saurik.com Git - apple/ld64.git/blobdiff - src/ld/Resolver.cpp
ld64-351.8.tar.gz
[apple/ld64.git] / src / ld / Resolver.cpp
index 573cad8d8de878758b140759bb7b27edcccfb717..51afe8dfca9b8ac3482228c50d9c347ff28abb2a 100644 (file)
 #include <AvailabilityMacros.h>
 
 #include "Options.h"
-
 #include "ld.hpp"
+#include "Bitcode.hpp"
 #include "InputFiles.h"
 #include "SymbolTable.h"
 #include "Resolver.h"
 #include "parsers/lto_file.h"
 
+#include "configure.h"
+
+#define VAL(x) #x
+#define STRINGIFY(x) VAL(x)
 
 namespace ld {
 namespace tool {
@@ -282,6 +286,8 @@ void Resolver::initializeState()
                _internal.objcObjectConstraint = ld::File::objcConstraintGC;
        
        _internal.cpuSubType = _options.subArchitecture();
+       _internal.minOSVersion = _options.minOSversion();
+       _internal.derivedPlatform = 0;
        
        // In -r mode, look for -linker_option additions
        if ( _options.outputKind() == Options::kObjectFile ) {
@@ -290,6 +296,11 @@ void Resolver::initializeState()
                        doLinkerOption(*it, "command line");
                }
        }
+#ifdef LD64_VERSION_NUM
+       uint32_t packedNum = Options::parseVersionNumber32(STRINGIFY(LD64_VERSION_NUM));
+       uint64_t combined = (uint64_t)TOOL_LD << 32 | packedNum;
+       _internal.toolsVersions.insert(combined);
+#endif
 }
 
 void Resolver::buildAtomList()
@@ -308,8 +319,10 @@ void Resolver::doLinkerOption(const std::vector<const char*>& linkerOption, cons
 {
        if ( linkerOption.size() == 1 ) {
                const char* lo1 = linkerOption.front();
-               if ( strncmp(lo1, "-l", 2) == 0 ) {
-                       _internal.linkerOptionLibraries.insert(&lo1[2]);
+               if ( strncmp(lo1, "-l", 2) == 0) {
+                       if (_internal.linkerOptionLibraries.count(&lo1[2]) == 0) {
+                               _internal.unprocessedLinkerOptionLibraries.insert(&lo1[2]);
+                       }
                }
                else {
                        warning("unknown linker option from object file ignored: '%s' in %s", lo1, fileName);
@@ -318,8 +331,10 @@ void Resolver::doLinkerOption(const std::vector<const char*>& linkerOption, cons
        else if ( linkerOption.size() == 2 ) {
                const char* lo2a = linkerOption[0];
                const char* lo2b = linkerOption[1];
-               if ( strcmp(lo2a, "-framework") == 0 ) {
-                       _internal.linkerOptionFrameworks.insert(lo2b);
+               if ( strcmp(lo2a, "-framework") == 0) {
+                       if (_internal.linkerOptionFrameworks.count(lo2b) == 0) {
+                               _internal.unprocessedLinkerOptionFrameworks.insert(lo2b);
+                       }
                }
                else {
                        warning("unknown linker option from object file ignored: '%s' '%s' from %s", lo2a, lo2b, fileName);
@@ -330,6 +345,7 @@ void Resolver::doLinkerOption(const std::vector<const char*>& linkerOption, cons
        }
 }
 
+
 void Resolver::doFile(const ld::File& file)
 {
        const ld::relocatable::File* objFile = dynamic_cast<const ld::relocatable::File*>(&file);
@@ -338,12 +354,64 @@ void Resolver::doFile(const ld::File& file)
        if ( objFile != NULL ) {
                // if file has linker options, process them
                ld::relocatable::File::LinkerOptionsList* lo = objFile->linkerOptions();
-               if ( lo != NULL ) {
+               if ( lo != NULL && !_options.ignoreAutoLink() ) {
                        for (relocatable::File::LinkerOptionsList::const_iterator it=lo->begin(); it != lo->end(); ++it) {
                                this->doLinkerOption(*it, file.path());
                        }
+                       // <rdar://problem/23053404> process any additional linker-options introduced by this new archive member being loaded
+                       if ( _completedInitialObjectFiles ) {
+                               _inputFiles.addLinkerOptionLibraries(_internal, *this);
+                               _inputFiles.createIndirectDylibs();
+                       }
                }
-               
+               // Resolve bitcode section in the object file
+               if ( _options.bundleBitcode() ) {
+                       if ( objFile->getBitcode() == NULL ) {
+                               // Handle the special case for compiler_rt objects. Add the file to the list to be process.
+                               if ( objFile->sourceKind() == ld::relocatable::File::kSourceCompilerArchive ) {
+                                       _internal.filesFromCompilerRT.push_back(objFile);
+                               } else if (objFile->sourceKind() != ld::relocatable::File::kSourceLTO  ) {
+                                       // No bitcode section, figure out if the object file comes from LTO/compiler static library
+                                       switch ( _options.platform() ) {
+                                       case Options::kPlatformOSX:
+                                       case Options::kPlatform_bridgeOS:
+                                       case Options::kPlatformUnknown:
+                                               warning("all bitcode will be dropped because '%s' was built without bitcode. "
+                                                               "You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. ", file.path());
+                                               _internal.filesWithBitcode.clear();
+                                               _internal.dropAllBitcode = true;
+                                               break;
+                                       case Options::kPlatformiOS:
+                                               throwf("'%s' does not contain bitcode. "
+                                                          "You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target.", file.path());
+                                               break;
+                                       case Options::kPlatformWatchOS:
+#if SUPPORT_APPLE_TV
+                                       case Options::kPlatform_tvOS:
+#endif
+                                               throwf("'%s' does not contain bitcode. "
+                                                               "You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE) or obtain an updated library from the vendor", file.path());
+                                               break;
+                                       }
+                               }
+                       } else {
+                               // contains bitcode, check if it is just a marker
+                               if ( objFile->getBitcode()->isMarker() ) {
+                                       // if -bitcode_verify_bundle is used, check if all the object files participate in the linking have full bitcode embedded.
+                                       // error on any marker encountered.
+                                       if ( _options.verifyBitcode() )
+                                               throwf("bitcode bundle could not be generated because '%s' was built without full bitcode. "
+                                                          "All object files and libraries for bitcode must be generated from Xcode Archive or Install build",
+                                                          objFile->path());
+                                       // update the internal state that marker is encountered.
+                                       _internal.embedMarkerOnly = true;
+                                       _internal.filesWithBitcode.clear();
+                                       _internal.dropAllBitcode = true;
+                               } else if ( !_internal.dropAllBitcode )
+                                       _internal.filesWithBitcode.push_back(objFile);
+                       }
+               }
+
                // update which form of ObjC is being used
                switch ( file.objCConstraint() ) {
                        case ld::File::objcConstraintNone:
@@ -383,6 +451,37 @@ void Resolver::doFile(const ld::File& file)
                                break;
                }
        
+               // verify all files use same version of Swift language
+               if ( file.swiftVersion() != 0 ) {
+                       if ( _internal.swiftVersion == 0 ) {
+                               _internal.swiftVersion = file.swiftVersion();
+                       }
+                       else if ( file.swiftVersion() != _internal.swiftVersion ) {
+                               char fileVersion[64];
+                               char otherVersion[64];
+                               Options::userReadableSwiftVersion(file.swiftVersion(), fileVersion);
+                               Options::userReadableSwiftVersion(_internal.swiftVersion, otherVersion);
+                               if ( file.swiftVersion() > _internal.swiftVersion ) {
+                                       if ( _options.warnOnSwiftABIVersionMismatches() ) {
+                                               warning("%s compiled with newer version of Swift language (%s) than previous files (%s)",
+                                                       file.path(), fileVersion, otherVersion);
+                                       } else {
+                                               throwf("%s compiled with newer version of Swift language (%s) than previous files (%s)",
+                                                      file.path(), fileVersion, otherVersion);
+                                       }
+                               }
+                               else {
+                                       if ( _options.warnOnSwiftABIVersionMismatches() ) {
+                                               warning("%s compiled with older version of Swift language (%s) than previous files (%s)",
+                                                       file.path(), fileVersion, otherVersion);
+                                       } else {
+                                               throwf("%s compiled with older version of Swift language (%s) than previous files (%s)",
+                                                      file.path(), fileVersion, otherVersion);
+                                       }
+                               }
+                       }
+               }
+               
                // in -r mode, if any .o files have dwarf then add UUID to output .o file
                if ( objFile->debugInfo() == ld::relocatable::File::kDebugInfoDwarf )
                        _internal.someObjectFileHasDwarf = true;
@@ -390,7 +489,28 @@ void Resolver::doFile(const ld::File& file)
                // remember if any .o file did not have MH_SUBSECTIONS_VIA_SYMBOLS bit set
                if ( ! objFile->canScatterAtoms() )
                        _internal.allObjectFilesScatterable = false;
-       
+
+               // remember if building for profiling (so we don't warn about initializers)
+               if ( objFile->hasllvmProfiling() )
+                       _havellvmProfiling = true;
+
+               // update minOSVersion off all .o files
+               uint32_t objMinOS = objFile->minOSVersion();
+               if ( !objMinOS )
+                       _internal.objectFileFoundWithNoVersion = true;
+               if ( (_options.outputKind() == Options::kObjectFile) && (objMinOS > _internal.minOSVersion) )
+                       _internal.minOSVersion = objMinOS;
+
+               uint32_t objPlatform = objFile->platform();
+               if ( (objPlatform != 0) && (_options.outputKind() == Options::kObjectFile) && (_internal.derivedPlatform == 0)  )
+                       _internal.derivedPlatform = objPlatform;
+
+               // update set of known tools used
+               for (const std::pair<uint32_t,uint32_t>& entry : objFile->toolVersions()) {
+                       uint64_t combined = (uint64_t)entry.first << 32 | entry.second;
+                       _internal.toolsVersions.insert(combined);
+               }
+
                // update cpu-sub-type
                cpu_subtype_t nextObjectSubType = file.cpuSubType();
                switch ( _options.architecture() ) {
@@ -413,6 +533,19 @@ void Resolver::doFile(const ld::File& file)
                                }
                                break;
                        
+                       case CPU_TYPE_ARM64:
+                               if ( _options.subArchitecture() != nextObjectSubType ) {
+                                       if ( _options.allowSubArchitectureMismatches() ) {
+                                               warning("object file %s was built for different arm64 sub-type (%d) than link command line (%d)",
+                                                       file.path(), nextObjectSubType, _options.subArchitecture());
+                                       }
+                                       else {
+                                               throwf("object file %s was built for different arm64 sub-type (%d) than link command line (%d)",
+                                                       file.path(), nextObjectSubType, _options.subArchitecture());
+                                       }
+                               }
+                               break;
+
                        case CPU_TYPE_I386:
                                _internal.cpuSubType = CPU_SUBTYPE_I386_ALL;
                                break;
@@ -432,6 +565,58 @@ void Resolver::doFile(const ld::File& file)
                }
        }
        if ( dylibFile != NULL ) {
+               // Check dylib for bitcode, if the library install path is relative path or @rpath, it has to contain bitcode
+               if ( _options.bundleBitcode() ) {
+                       bool isSystemFramework = ( dylibFile->installPath() != NULL ) && ( dylibFile->installPath()[0] == '/' );
+                       if ( dylibFile->getBitcode() == NULL && !isSystemFramework ) {
+                               // Check if the dylib is from toolchain by checking the path
+                               char tcLibPath[PATH_MAX];
+                               char ldPath[PATH_MAX];
+                               char tempPath[PATH_MAX];
+                               uint32_t bufSize = PATH_MAX;
+                               // toolchain library path should pointed to *.xctoolchain/usr/lib
+                               if ( _NSGetExecutablePath(ldPath, &bufSize) != -1 ) {
+                                       if ( realpath(ldPath, tempPath) != NULL ) {
+                                               char* lastSlash = strrchr(tempPath, '/');
+                                               if ( lastSlash != NULL )
+                                                       strcpy(lastSlash, "/../lib");
+                                       }
+                               }
+                               // Compare toolchain library path to the dylib path
+                               if ( realpath(tempPath, tcLibPath) == NULL ||
+                                        realpath(dylibFile->path(), tempPath) == NULL ||
+                                        strncmp(tcLibPath, tempPath, strlen(tcLibPath)) != 0 ) {
+                                       switch ( _options.platform() ) {
+                                       case Options::kPlatformOSX:
+                                       case Options::kPlatform_bridgeOS:
+                                       case Options::kPlatformUnknown:
+                                               warning("all bitcode will be dropped because '%s' was built without bitcode. "
+                                                               "You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target.", file.path());
+                                               _internal.filesWithBitcode.clear();
+                                               _internal.dropAllBitcode = true;
+                                               break;
+                                       case Options::kPlatformiOS:
+                                               throwf("'%s' does not contain bitcode. "
+                                                          "You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target.", file.path());
+                                               break;
+                                       case Options::kPlatformWatchOS:
+#if SUPPORT_APPLE_TV
+                                       case Options::kPlatform_tvOS:
+#endif
+                                               throwf("'%s' does not contain bitcode. "
+                                                               "You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE) or obtain an updated library from the vendor", file.path());
+                                               break;
+                                       }
+                               }
+                       }
+                       // Error on bitcode marker in non-system frameworks if -bitcode_verify is used
+                       if ( _options.verifyBitcode() && !isSystemFramework &&
+                                dylibFile->getBitcode() != NULL && dylibFile->getBitcode()->isMarker() )
+                               throwf("bitcode bundle could not be generated because '%s' was built without full bitcode. "
+                                          "All frameworks and dylibs for bitcode must be generated from Xcode Archive or Install build",
+                                          dylibFile->path());
+               }
+
                // update which form of ObjC dylibs are being linked
                switch ( dylibFile->objCConstraint() ) {
                        case ld::File::objcConstraintNone:
@@ -469,6 +654,60 @@ void Resolver::doFile(const ld::File& file)
                                }
                                break;
                }
+
+               // <rdar://problem/25680358> verify dylibs use same version of Swift language
+               if ( file.swiftVersion() != 0 ) {
+                       if ( _internal.swiftVersion == 0 ) {
+                               _internal.swiftVersion = file.swiftVersion();
+                       }
+                       else if ( file.swiftVersion() != _internal.swiftVersion ) {
+                               char fileVersion[64];
+                               char otherVersion[64];
+                               Options::userReadableSwiftVersion(file.swiftVersion(), fileVersion);
+                               Options::userReadableSwiftVersion(_internal.swiftVersion, otherVersion);
+                               if ( file.swiftVersion() > _internal.swiftVersion ) {
+                                       if ( _options.warnOnSwiftABIVersionMismatches() ) {
+                                               warning("%s compiled with newer version of Swift language (%s) than previous files (%s)",
+                                                       file.path(), fileVersion, otherVersion);
+                                       } else {
+                                               throwf("%s compiled with newer version of Swift language (%s) than previous files (%s)",
+                                                      file.path(), fileVersion, otherVersion);
+                                       }
+                               }
+                               else {
+                                       if ( _options.warnOnSwiftABIVersionMismatches() ) {
+                                               warning("%s compiled with older version of Swift language (%s) than previous files (%s)",
+                                                       file.path(), fileVersion, otherVersion);
+                                       } else {
+                                               throwf("%s compiled with older version of Swift language (%s) than previous files (%s)",
+                                                      file.path(), fileVersion, otherVersion);
+                                       }
+                               }
+                       }
+               }
+
+               if ( _options.checkDylibsAreAppExtensionSafe() && !dylibFile->appExtensionSafe() ) {
+                       warning("linking against a dylib which is not safe for use in application extensions: %s", file.path());
+               }
+               const char* depInstallName = dylibFile->installPath();
+               // <rdar://problem/17229513> embedded frameworks are only supported on iOS 8 and later
+               if ( (depInstallName != NULL) && (depInstallName[0] != '/') ) {
+                       if ( (_options.iOSVersionMin() != iOSVersionUnset) && (_options.iOSVersionMin() < iOS_8_0) ) {
+                               // <rdar://problem/17598404> only warn about linking against embedded dylib if it is built for iOS 8 or later
+                               if ( dylibFile->minOSVersion() >= iOS_8_0 )
+                                       throwf("embedded dylibs/frameworks are only supported on iOS 8.0 and later (%s)", depInstallName);
+                       }
+               }
+               if ( _options.sharedRegionEligible() ) {
+                       assert(depInstallName != NULL);
+                       if ( depInstallName[0] == '@' ) {
+                               warning("invalid -install_name (%s) in dependent dylib (%s). Dylibs/frameworks which might go in dyld shared cache "
+                                               "cannot link with dylib that uses @rpath, @loader_path, etc.", depInstallName, dylibFile->path());
+                       } else if ( (strncmp(depInstallName, "/usr/lib/", 9) != 0) && (strncmp(depInstallName, "/System/Library/", 16) != 0) ) {
+                               warning("invalid -install_name (%s) in dependent dylib (%s). Dylibs/frameworks which might go in dyld shared cache "
+                                               "cannot link with dylibs that won't be in the shared cache", depInstallName, dylibFile->path());
+                       }
+               }
        }
 
 }
@@ -503,14 +742,14 @@ void Resolver::doAtom(const ld::Atom& atom)
                                                        }
                                                        else if ( _options.outputKind() == Options::kDynamicLibrary ) {
                                                                if ( atom.file() != NULL )
-                                                                       warning("target OS does not support re-exporting symbol %s from %s\n", _options.demangleSymbol(name), atom.file()->path());
+                                                                       warning("target OS does not support re-exporting symbol %s from %s\n", _options.demangleSymbol(name), atom.safeFilePath());
                                                                else
                                                                        warning("target OS does not support re-exporting symbol %s\n", _options.demangleSymbol(name));
                                                        }
                                                }
                                                else {
                                                        if ( atom.file() != NULL )
-                                                               warning("cannot export hidden symbol %s from %s", _options.demangleSymbol(name), atom.file()->path());
+                                                               warning("cannot export hidden symbol %s from %s", _options.demangleSymbol(name), atom.safeFilePath());
                                                        else
                                                                warning("cannot export hidden symbol %s", _options.demangleSymbol(name));
                                                }
@@ -522,7 +761,7 @@ void Resolver::doAtom(const ld::Atom& atom)
                                                (const_cast<ld::Atom*>(&atom))->setScope(ld::Atom::scopeGlobal);
                                        }
                                        else {
-                                               throwf("requested re-export symbol %s is not from a dylib, but from %s\n", _options.demangleSymbol(name), atom.file()->path());
+                                               throwf("requested re-export symbol %s is not from a dylib, but from %s\n", _options.demangleSymbol(name), atom.safeFilePath());
                                        }
                                }
                                break;
@@ -533,7 +772,7 @@ void Resolver::doAtom(const ld::Atom& atom)
                                        //fprintf(stderr, "demote %s to hidden\n", name);
                                }
                                if ( _options.canReExportSymbols() && _options.shouldReExport(name) ) {
-                                       throwf("requested re-export symbol %s is not from a dylib, but from %s\n", _options.demangleSymbol(name), atom.file()->path());
+                                       throwf("requested re-export symbol %s is not from a dylib, but from %s\n", _options.demangleSymbol(name), atom.safeFilePath());
                                }
                                break;
                }
@@ -548,16 +787,21 @@ void Resolver::doAtom(const ld::Atom& atom)
 
        // tell symbol table about non-static atoms
        if ( atom.scope() != ld::Atom::scopeTranslationUnit ) {
-               _symbolTable.add(atom, _options.deadCodeStrip() && _completedInitialObjectFiles);
+               _symbolTable.add(atom, _options.deadCodeStrip() && (_completedInitialObjectFiles || _options.allowDeadDuplicates()));
                
                // add symbol aliases defined on the command line
                if ( _options.haveCmdLineAliases() ) {
                        const std::vector<Options::AliasPair>& aliases = _options.cmdLineAliases();
                        for (std::vector<Options::AliasPair>::const_iterator it=aliases.begin(); it != aliases.end(); ++it) {
                                if ( strcmp(it->realName, atom.name()) == 0 ) {
-                                       const AliasAtom* alias = new AliasAtom(atom, it->alias);
-                                       _aliasesFromCmdLine.push_back(alias);
-                                       this->doAtom(*alias);
+                                       if ( strcmp(it->realName, it->alias) == 0 ) {
+                                               warning("ignoring alias of itself '%s'", it->realName);
+                                       }
+                                       else {
+                                               const AliasAtom* alias = new AliasAtom(atom, it->alias);
+                                               _aliasesFromCmdLine.push_back(alias);
+                                               this->doAtom(*alias);
+                                       }
                                }
                        }
                }
@@ -569,11 +813,30 @@ void Resolver::doAtom(const ld::Atom& atom)
        // remember if any atoms are proxies that require LTO
        if ( atom.contentType() == ld::Atom::typeLTOtemporary )
                _haveLLVMObjs = true;
-               
+       
+       // remember if any atoms are aliases
+       if ( atom.section().type() == ld::Section::typeTempAlias )
+               _haveAliases = true;
+       
+       // error or warn about initializers
+       if ( (atom.section().type() == ld::Section::typeInitializerPointers) && !_havellvmProfiling ) {
+               switch ( _options.initializersTreatment() ) {
+                       case Options::kError:
+                               throwf("static initializer found in '%s'",atom.safeFilePath());
+                       case Options::kWarning:
+                               warning("static initializer found in '%s'. Use -no_inits to make this an error.  Use -no_warn_inits to suppress warning",atom.safeFilePath());
+                               break;
+                       default:
+                               break;
+               }
+       }
+       
        if ( _options.deadCodeStrip() ) {
                // add to set of dead-strip-roots, all symbols that the compiler marks as don't strip
                if ( atom.dontDeadStrip() )
                        _deadStripRoots.insert(&atom);
+               else if ( atom.dontDeadStripIfReferencesLive() )
+                       _dontDeadStripIfReferencesLive.push_back(&atom);
                        
                if ( atom.scope() == ld::Atom::scopeGlobal ) {
                        // <rdar://problem/5524973> -exported_symbols_list that has wildcards and -dead_strip
@@ -726,7 +989,7 @@ void Resolver::resolveUndefines()
                }
        }
        
-       // Use linker options to resolve an remaining undefined symbols
+       // Use linker options to resolve any remaining undefined symbols
        if ( !_internal.linkerOptionLibraries.empty() || !_internal.linkerOptionFrameworks.empty() ) {
                std::vector<const char*> undefineNames;
                _symbolTable.undefines(undefineNames);
@@ -768,6 +1031,10 @@ void Resolver::resolveUndefines()
                }
        }
        
+       // After resolving all the undefs within the linkageUnit, record all the remaining undefs and all the proxies.
+       if (_options.bundleBitcode() && _options.hideSymbols())
+               _symbolTable.mustPreserveForBitcode(_internal.allUndefProxies);
+
 }
 
 
@@ -776,12 +1043,12 @@ void Resolver::markLive(const ld::Atom& atom, WhyLiveBackChain* previous)
        //fprintf(stderr, "markLive(%p) %s\n", &atom, atom.name());
        // if -why_live cares about this symbol, then dump chain
        if ( (previous->referer != NULL) && _options.printWhyLive(atom.name()) ) {
-               fprintf(stderr, "%s from %s\n", atom.name(), atom.file()->path());
+               fprintf(stderr, "%s from %s\n", atom.name(), atom.safeFilePath());
                int depth = 1;
                for(WhyLiveBackChain* p = previous; p != NULL; p = p->previous, ++depth) {
                        for(int i=depth; i > 0; --i)
                                fprintf(stderr, "  ");
-                       fprintf(stderr, "%s from %s\n", p->referer->name(), p->referer->file()->path());
+                       fprintf(stderr, "%s from %s\n", p->referer->name(), p->referer->safeFilePath());
                }
        }
        
@@ -826,6 +1093,8 @@ void Resolver::markLive(const ld::Atom& atom, WhyLiveBackChain* previous)
                        case ld::Fixup::kindStoreTargetAddressARM64Page21:
                        case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21:
                        case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21:
+                       case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPage21:
+                       case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPage21:
 #endif
                                if ( fit->binding == ld::Fixup::bindingByContentBound ) {
                                        // normally this was done in convertReferencesToIndirect()
@@ -958,6 +1227,38 @@ void Resolver::deadStripOptimize(bool force)
                this->markLive(**it, &rootChain);
        }
        
+       // special case atoms that need to be live if they reference something live
+       if ( ! _dontDeadStripIfReferencesLive.empty() ) {
+               for (std::vector<const ld::Atom*>::iterator it=_dontDeadStripIfReferencesLive.begin(); it != _dontDeadStripIfReferencesLive.end(); ++it) {
+                       const Atom* liveIfRefLiveAtom = *it;
+                       //fprintf(stderr, "live-if-live atom: %s\n", liveIfRefLiveAtom->name());
+                       if ( liveIfRefLiveAtom->live() )
+                               continue;
+                       bool hasLiveRef = false;
+                       for (ld::Fixup::iterator fit=liveIfRefLiveAtom->fixupsBegin(); fit != liveIfRefLiveAtom->fixupsEnd(); ++fit) {
+                               const Atom* target = NULL;
+                               switch ( fit->binding ) {
+                                       case ld::Fixup::bindingDirectlyBound:
+                                               target = fit->u.target;
+                                               break;
+                                       case ld::Fixup::bindingsIndirectlyBound:
+                                               target = _internal.indirectBindingTable[fit->u.bindingIndex];
+                                               break;
+                                       default:
+                                               break;
+                               }
+                               if ( (target != NULL) && target->live() ) 
+                                       hasLiveRef = true;
+                       }
+                       if ( hasLiveRef ) {
+                               WhyLiveBackChain rootChain;
+                               rootChain.previous = NULL;
+                               rootChain.referer = liveIfRefLiveAtom;
+                               this->markLive(*liveIfRefLiveAtom, &rootChain);
+                       }
+               }
+       }
+       
        // now remove all non-live atoms from _atoms
        const bool log = false;
        if ( log ) {
@@ -969,11 +1270,13 @@ void Resolver::deadStripOptimize(bool force)
        }
        
        if ( _haveLLVMObjs && !force ) {
+                std::copy_if(_atoms.begin(), _atoms.end(), std::back_inserter(_internal.deadAtoms), NotLiveLTO() );
                // <rdar://problem/9777977> don't remove combinable atoms, they may come back in lto output
                _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(), NotLiveLTO()), _atoms.end());
                _symbolTable.removeDeadAtoms();
        }
        else {
+                std::copy_if(_atoms.begin(), _atoms.end(), std::back_inserter(_internal.deadAtoms), NotLive() );
                _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(), NotLive()), _atoms.end());
        }
 
@@ -1140,11 +1443,11 @@ bool Resolver::printReferencedBy(const char* name, SymbolTable::IndirectBindingS
                                                        ++foundReferenceCount;
                                        }
                                        else if ( atom->contentType() == ld::Atom::typeCFI ) {
-                                               fprintf(stderr, "      Dwarf Exception Unwind Info (__eh_frame) in %s\n", pathLeafName(atom->file()->path()));
+                                               fprintf(stderr, "      Dwarf Exception Unwind Info (__eh_frame) in %s\n", pathLeafName(atom->safeFilePath()));
                                                ++foundReferenceCount;
                                        }
                                        else {
-                                               fprintf(stderr, "      %s in %s\n", _options.demangleSymbol(atom->name()), pathLeafName(atom->file()->path()));
+                                               fprintf(stderr, "      %s in %s\n", _options.demangleSymbol(atom->name()), pathLeafName(atom->safeFilePath()));
                                                ++foundReferenceCount;
                                                break; // if undefined used twice in a function, only show first
                                        }
@@ -1417,7 +1720,38 @@ void Resolver::fillInEntryPoint()
        _internal.entryPoint = this->entryPoint(true);
 }
 
-
+void Resolver::syncAliases()
+{
+       if ( !_haveAliases || (_options.outputKind() == Options::kObjectFile) )
+               return;
+       
+       // Set attributes of alias to match its found target
+       for (std::vector<const ld::Atom*>::iterator it = _atoms.begin(); it != _atoms.end(); ++it) {
+               const ld::Atom* atom = *it;
+               if ( atom->section().type() == ld::Section::typeTempAlias ) {
+                       assert(atom->fixupsBegin() != atom->fixupsEnd());
+                       for (ld::Fixup::iterator fit = atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) {
+                               const ld::Atom* target;
+                               ld::Atom::Scope scope;
+                               assert(fit->kind == ld::Fixup::kindNoneFollowOn);
+                               switch ( fit->binding ) {
+                                       case ld::Fixup::bindingByNameUnbound:
+                                               break;
+                                       case ld::Fixup::bindingsIndirectlyBound:
+                                               target = _internal.indirectBindingTable[fit->u.bindingIndex];
+                                               assert(target != NULL);
+                                               scope = atom->scope();
+                                               (const_cast<Atom*>(atom))->setAttributesFromAtom(*target);
+                                               // alias has same attributes as target, except for scope
+                                               (const_cast<Atom*>(atom))->setScope(scope);
+                                               break;
+                                       default:
+                                               assert(0 && "internal error: unexpected alias binding");
+                               }
+                       }
+               }
+       }
+}
 
 void Resolver::removeCoalescedAwayAtoms()
 {
@@ -1447,20 +1781,35 @@ void Resolver::linkTimeOptimize()
        lto::OptimizeOptions optOpt;
        optOpt.outputFilePath                           = _options.outputFilePath();
        optOpt.tmpObjectFilePath                        = _options.tempLtoObjectPath();
+       optOpt.ltoCachePath                                     = _options.ltoCachePath();
+       optOpt.ltoPruneInterval                         = _options.ltoPruneInterval();
+       optOpt.ltoPruneAfter                            = _options.ltoPruneAfter();
+       optOpt.ltoMaxCacheSize                          = _options.ltoMaxCacheSize();
        optOpt.preserveAllGlobals                       = _options.allGlobalsAreDeadStripRoots() || _options.hasExportRestrictList();
        optOpt.verbose                                          = _options.verbose();
        optOpt.saveTemps                                        = _options.saveTempFiles();
+       optOpt.ltoCodegenOnly                                   = _options.ltoCodegenOnly();
        optOpt.pie                                                      = _options.positionIndependentExecutable();
        optOpt.mainExecutable                           = _options.linkingMainExecutable();;
        optOpt.staticExecutable                         = (_options.outputKind() == Options::kStaticExecutable);
+       optOpt.preload                                          = (_options.outputKind() == Options::kPreload);
        optOpt.relocatable                                      = (_options.outputKind() == Options::kObjectFile);
        optOpt.allowTextRelocs                          = _options.allowTextRelocs();
        optOpt.linkerDeadStripping                      = _options.deadCodeStrip();
        optOpt.needsUnwindInfoSection           = _options.needsUnwindInfoSection();
        optOpt.keepDwarfUnwind                          = _options.keepDwarfUnwind();
+       optOpt.verboseOptimizationHints     = _options.verboseOptimizationHints();
+       optOpt.armUsesZeroCostExceptions    = _options.armUsesZeroCostExceptions();
+       optOpt.simulator                                        = _options.targetIOSSimulator();
+       optOpt.ignoreMismatchPlatform           = ((_options.outputKind() == Options::kPreload) || (_options.outputKind() == Options::kStaticExecutable));
+       optOpt.bitcodeBundle                            = (_options.bundleBitcode() && (_options.bitcodeKind() != Options::kBitcodeMarker));
+       optOpt.maxDefaultCommonAlignment        = _options.maxDefaultCommonAlign();
        optOpt.arch                                                     = _options.architecture();
        optOpt.mcpu                                                     = _options.mcpuLTO();
+       optOpt.platform                                         = _options.platform();
+       optOpt.minOSVersion                                     = _options.minOSversion();
        optOpt.llvmOptions                                      = &_options.llvmOptions();
+       optOpt.initialUndefines                         = &_options.initialUndefines();
        
        std::vector<const ld::Atom*>            newAtoms;
        std::vector<const char*>                        additionalUndefines; 
@@ -1487,7 +1836,7 @@ void Resolver::linkTimeOptimize()
        }
        
        // <rdar://problem/14609792> add any auto-link libraries requested by LTO output to dylibs to search
-       _inputFiles.addLinkerOptionLibraries(_internal);
+       _inputFiles.addLinkerOptionLibraries(_internal, *this);
        _inputFiles.createIndirectDylibs();
 
        // resolve new undefines (e.g calls to _malloc and _memcpy that llvm compiler conjures up)
@@ -1501,14 +1850,21 @@ void Resolver::linkTimeOptimize()
 
        // if -dead_strip on command line
        if ( _options.deadCodeStrip() ) {
-               // clear liveness bit
+               // run through all atoms again and make live_section LTO atoms are preserved from dead_stripping if needed
+               _dontDeadStripIfReferencesLive.clear();
                for (std::vector<const ld::Atom*>::const_iterator it=_atoms.begin(); it != _atoms.end(); ++it) {
+                       const ld::Atom* atom = *it;
+                       if ( atom->dontDeadStripIfReferencesLive() ) {
+                               _dontDeadStripIfReferencesLive.push_back(atom);
+                       }
+
+                       // clear liveness bit
                        (const_cast<ld::Atom*>(*it))->setLive((*it)->dontDeadStrip());
                }
                // and re-compute dead code
                this->deadStripOptimize(true);
        }
-       
+
        // <rdar://problem/12386559> if -exported_symbols_list on command line, re-force scope
        if ( _options.hasExportMaskList() ) {
                for (std::vector<const ld::Atom*>::const_iterator it=_atoms.begin(); it != _atoms.end(); ++it) {
@@ -1532,6 +1888,23 @@ void Resolver::linkTimeOptimize()
 
                // check new code does not override some dylib
                this->checkDylibSymbolCollisions();
+
+               // <rdar://problem/33853815> remove undefs from LTO objects that gets optimized away
+               std::unordered_set<const ld::Atom*> mustPreserve;
+               if ( _internal.classicBindingHelper != NULL )
+                       mustPreserve.insert(_internal.classicBindingHelper);
+               if ( _internal.compressedFastBinderProxy != NULL )
+                       mustPreserve.insert(_internal.compressedFastBinderProxy);
+               if ( _internal.lazyBindingHelper != NULL )
+                       mustPreserve.insert(_internal.lazyBindingHelper);
+               if ( const ld::Atom* entry = this->entryPoint(true) )
+                       mustPreserve.insert(entry);
+               for (Options::UndefinesIterator uit=_options.initialUndefinesBegin(); uit != _options.initialUndefinesEnd(); ++uit) {
+                       SymbolTable::IndirectBindingSlot slot = _symbolTable.findSlotForName(*uit);
+                       if ( _internal.indirectBindingTable[slot] != NULL )
+                               mustPreserve.insert(_internal.indirectBindingTable[slot]);
+               }
+               _symbolTable.removeDeadUndefs(_atoms, mustPreserve);
        }
 }
 
@@ -1568,6 +1941,12 @@ void Resolver::tweakWeakness()
        }
 }
 
+void Resolver::buildArchivesList()
+{
+       // Determine which archives were linked and update the internal state.
+       _inputFiles.archives(_internal);
+}
+
 void Resolver::dumpAtoms() 
 {
        fprintf(stderr, "Resolver all atoms:\n");
@@ -1587,12 +1966,14 @@ void Resolver::resolve()
        this->deadStripOptimize();
        this->checkUndefines();
        this->checkDylibSymbolCollisions();
+       this->syncAliases();
        this->removeCoalescedAwayAtoms();
        this->fillInEntryPoint();
        this->linkTimeOptimize();
        this->fillInInternalState();
        this->tweakWeakness();
     _symbolTable.checkDuplicateSymbols();
+       this->buildArchivesList();
 }