]> git.saurik.com Git - apple/ld64.git/blobdiff - src/ld/Resolver.cpp
ld64-409.12.tar.gz
[apple/ld64.git] / src / ld / Resolver.cpp
index 588def7be0f2857c60a099425e40700a7f987134..17e00cb78e81b97b7c1e20a3e4a8579ecfd75eab 100644 (file)
 #include <vector>
 #include <list>
 #include <algorithm>
-#include <ext/hash_map>
-#include <ext/hash_set>
 #include <dlfcn.h>
 #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 {
@@ -131,6 +133,11 @@ public:
        virtual ld::Atom::UnwindInfo::iterator  endUnwind() const       { return NULL; }
        virtual ld::Atom::LineInfo::iterator    beginLineInfo() const { return  NULL; }
        virtual ld::Atom::LineInfo::iterator    endLineInfo() const { return NULL; }
+
+       void                                                                    setFinalAliasOf() const {
+                                                                                               (const_cast<AliasAtom*>(this))->setAttributesFromAtom(_aliasOf);
+                                                                                               (const_cast<AliasAtom*>(this))->setScope(ld::Atom::scopeGlobal);
+                                                                                       }
                                                                                                                        
 private:
        const char*                                                     _name;
@@ -172,7 +179,7 @@ private:
 
 SectionBoundaryAtom* SectionBoundaryAtom::makeSectionBoundaryAtom(const char* name, bool start, const char* segSectName)
 {
-       
+
        const char* segSectDividor = strrchr(segSectName, '$');
        if ( segSectDividor == NULL )
                throwf("malformed section$ symbol name: %s", name);
@@ -182,8 +189,12 @@ SectionBoundaryAtom* SectionBoundaryAtom::makeSectionBoundaryAtom(const char* na
                throwf("malformed section$ symbol name: %s", name);
        char segName[18];
        strlcpy(segName, segSectName, segNameLen+1);
-       
-       const ld::Section* section = new ld::Section(strdup(segName), sectionName, ld::Section::typeUnclassified);
+
+       ld::Section::Type sectType = ld::Section::typeUnclassified;
+       if (!strcmp(segName, "__TEXT") && !strcmp(sectionName, "__thread_starts"))
+               sectType = ld::Section::typeThreadStarts;
+
+       const ld::Section* section = new ld::Section(strdup(segName), sectionName, sectType);
        return new SectionBoundaryAtom(name, *section, (start ? ld::Atom::typeSectionStart : typeSectionEnd));
 }
 
@@ -272,20 +283,27 @@ SegmentBoundaryAtom* SegmentBoundaryAtom::makeOldSegmentBoundaryAtom(const char*
 
 void Resolver::initializeState()
 {
-       // set initial objc constraint based on command line options
-       if ( _options.objcGc() )
-               _internal.objcObjectConstraint = ld::File::objcConstraintRetainReleaseOrGC;
-       else if ( _options.objcGcOnly() )
-               _internal.objcObjectConstraint = ld::File::objcConstraintGC;
-       
        _internal.cpuSubType = _options.subArchitecture();
+       
+       // In -r mode, look for -linker_option additions
+       if ( _options.outputKind() == Options::kObjectFile ) {
+               ld::relocatable::File::LinkerOptionsList lo = _options.linkerOptions();
+               for (relocatable::File::LinkerOptionsList::const_iterator it=lo.begin(); it != lo.end(); ++it) {
+                       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()
 {
        // each input files contributes initial atoms
        _atoms.reserve(1024);
-       _inputFiles.forEachInitialAtom(*this);
+       _inputFiles.forEachInitialAtom(*this, _internal);
     
        _completedInitialObjectFiles = true;
        
@@ -293,36 +311,143 @@ void Resolver::buildAtomList()
 }
 
 
+void Resolver::doLinkerOption(const std::vector<const char*>& linkerOption, const char* fileName)
+{
+       if ( linkerOption.size() == 1 ) {
+               const char* lo1 = linkerOption.front();
+               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);
+               }
+       }
+       else if ( linkerOption.size() == 2 ) {
+               const char* lo2a = linkerOption[0];
+               const char* lo2b = linkerOption[1];
+               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);
+               }
+       }
+       else {
+               warning("unknown linker option from object file ignored, starting with: '%s' from %s", linkerOption.front(), fileName);
+       }
+}
+
+
 void Resolver::doFile(const ld::File& file)
 {
        const ld::relocatable::File* objFile = dynamic_cast<const ld::relocatable::File*>(&file);
        const ld::dylib::File* dylibFile = dynamic_cast<const ld::dylib::File*>(&file);
 
        if ( objFile != NULL ) {
+               // if file has linker options, process them
+               ld::relocatable::File::LinkerOptionsList* lo = objFile->linkerOptions();
+               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();
+                       }
+               }
                // update which form of ObjC is being used
-               switch ( file.objCConstraint() ) {
-                       case ld::File::objcConstraintNone:
-                               break;
-                       case ld::File::objcConstraintRetainRelease:
-                               if ( _internal.objcObjectConstraint == ld::File::objcConstraintGC )
-                                       throwf("%s built with incompatible Garbage Collection settings to link with previous .o files", file.path());
-                               if ( _options.objcGcOnly() )
-                                       throwf("command line specified -objc_gc_only, but file is retain/release based: %s", file.path());
-                               if ( _options.objcGc() )
-                                       throwf("command line specified -objc_gc, but file is retain/release based: %s", file.path());
-                               _internal.objcObjectConstraint = ld::File::objcConstraintRetainRelease;
-                               break;
-                       case ld::File::objcConstraintRetainReleaseOrGC:
-                               if ( _internal.objcObjectConstraint == ld::File::objcConstraintNone )
-                                       _internal.objcObjectConstraint = ld::File::objcConstraintRetainReleaseOrGC;
-                               break;
-                       case ld::File::objcConstraintGC:
-                               if ( _internal.objcObjectConstraint == ld::File::objcConstraintRetainRelease )
-                                       throwf("%s built with incompatible Garbage Collection settings to link with previous .o files", file.path());
-                               _internal.objcObjectConstraint = ld::File::objcConstraintGC;
-                               break;
+               if ( objFile->hasObjC() )
+                       _internal.hasObjC = true;
+
+               // 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
+                                       _options.platforms().forEach(^(ld::Platform platform, uint32_t version, bool &stop) {
+                                               switch ( platform ) {
+                                                       case ld::kPlatform_macOS:
+                                                       case ld::kPlatform_bridgeOS:
+                                                       case ld::kPlatform_iOSMac:
+                                                       case ld::kPlatform_unknown:
+                                                               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 ld::kPlatform_iOS:
+                                                       case ld::kPlatform_iOSSimulator:
+                                                               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 ld::kPlatform_watchOS:
+                                                       case ld::kPlatform_watchOSSimulator:
+                                                       case ld::kPlatform_tvOS:
+                                                       case ld::kPlatform_tvOSSimulator:
+                                                               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);
+                       }
                }
-       
+
+               // verify all files use same version of Swift language
+               if ( file.swiftVersion() != 0 ) {
+                       _internal.someObjectFileHasSwift = true;
+                       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;
@@ -330,7 +455,29 @@ 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;
+
+#if MULTI
+               // 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;
+#endif
+
+               auto objPlatforms = objFile->platforms();
+               if ( (!objPlatforms.empty()) && (_options.outputKind() == Options::kObjectFile) && (_internal.derivedPlatforms.empty())  )
+                       _internal.derivedPlatforms = objPlatforms;
+               // 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() ) {
@@ -353,46 +500,172 @@ 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;
                                
                        case CPU_TYPE_X86_64:
-                               _internal.cpuSubType = CPU_SUBTYPE_X86_64_ALL;
+                               if ( _options.subArchitecture() != nextObjectSubType ) {
+                                       if ( _options.allowSubArchitectureMismatches() ) {
+                                               warning("object file %s was built for different x86_64 sub-type (%d) than link command line (%d)", 
+                                                       file.path(), nextObjectSubType, _options.subArchitecture());
+                                       }
+                                       else {
+                                               throwf("object file %s was built for different x86_64 sub-type (%d) than link command line (%d)", 
+                                                       file.path(), nextObjectSubType, _options.subArchitecture());
+                                       }
+                               }
                                break;
                }
        }
        if ( dylibFile != NULL ) {
-               // update which form of ObjC dylibs are being linked
-               switch ( dylibFile->objCConstraint() ) {
-                       case ld::File::objcConstraintNone:
-                               break;
-                       case ld::File::objcConstraintRetainRelease:
-                               if ( _internal.objcDylibConstraint == ld::File::objcConstraintGC )
-                                       throwf("%s built with incompatible Garbage Collection settings to link with previous dylibs", file.path());
-                               if ( _options.objcGcOnly() )
-                                       throwf("command line specified -objc_gc_only, but dylib is retain/release based: %s", file.path());
-                               if ( _options.objcGc() )
-                                       throwf("command line specified -objc_gc, but dylib is retain/release based: %s", file.path());
-                               _internal.objcDylibConstraint = ld::File::objcConstraintRetainRelease;
-                               break;
-                       case ld::File::objcConstraintRetainReleaseOrGC:
-                               if ( _internal.objcDylibConstraint == ld::File::objcConstraintNone )
-                                       _internal.objcDylibConstraint = ld::File::objcConstraintRetainReleaseOrGC;
-                               break;
-                       case ld::File::objcConstraintGC:
-                               if ( _internal.objcDylibConstraint == ld::File::objcConstraintRetainRelease )
-                                       throwf("%s built with incompatible Garbage Collection settings to link with previous dylibs", file.path());
-                               _internal.objcDylibConstraint = ld::File::objcConstraintGC;
-                               break;
+               // 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 ) {
+                                       _options.platforms().forEach(^(ld::Platform platform, uint32_t version, bool &stop) {
+                                               switch ( platform ) {
+                                                       case ld::kPlatform_macOS:
+                                                       case ld::kPlatform_bridgeOS:
+                                                       case ld::kPlatform_iOSMac:
+                                                       case ld::kPlatform_unknown:
+                                                               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 ld::kPlatform_iOS:
+                                                       case ld::kPlatform_iOSSimulator:
+                                                               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 ld::kPlatform_watchOS:
+                                                       case ld::kPlatform_watchOSSimulator:
+                                                       case ld::kPlatform_tvOS:
+                                                       case ld::kPlatform_tvOSSimulator:
+                                                               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());
+               }
+
+               // Don't allow swift frameworks to link other swift frameworks.
+               if ( !_internal.firstSwiftDylibFile && _options.outputKind() == Options::kDynamicLibrary
+                       && file.swiftVersion() != 0 && getenv("LD_DISALLOW_SWIFT_LINKING_SWIFT")) {
+                       // Check that we aren't a whitelisted path.
+                       bool inWhiteList = false;
+                       const char *whitelistedPaths[] = { "/System/Library/PrivateFrameworks/Swift" };
+                       for (auto whitelistedPath : whitelistedPaths) {
+                               if (!strncmp(whitelistedPath, dylibFile->installPath(), strlen(whitelistedPath))) {
+                                       inWhiteList = true;
+                                       break;
+                               }
+                       }
+                       if (!inWhiteList) {
+                               _internal.firstSwiftDylibFile = dylibFile;
+                       }
+               }
+
+               // <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.platforms().contains(ld::kPlatform_iOS) && !_options.platforms().minOS(iOS_8_0) ) {
+                               // <rdar://problem/17598404> only warn about linking against embedded dylib if it is built for iOS 8 or later
+                               if ( dylibFile->platforms().minOS(ld::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());
+                       }
+               }
+       }
 }
 
 void Resolver::doAtom(const ld::Atom& atom)
 {
-       //fprintf(stderr, "Resolver::doAtom(%p), name=%s, sect=%s\n", &atom, atom.name(), atom.section().sectionName());
+       //fprintf(stderr, "Resolver::doAtom(%p), name=%s, sect=%s, scope=%d\n", &atom, atom.name(), atom.section().sectionName(), atom.scope());
+       if ( _ltoCodeGenFinished && (atom.contentType() == ld::Atom::typeLTOtemporary) && (atom.scope() != ld::Atom::scopeTranslationUnit) )
+               warning("'%s' is implemented in bitcode, but it was loaded too late", atom.name());
 
        // add to list of known atoms
        _atoms.push_back(&atom);
@@ -418,14 +691,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));
                                                }
@@ -437,7 +710,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;
@@ -448,7 +721,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;
                }
@@ -456,21 +729,28 @@ void Resolver::doAtom(const ld::Atom& atom)
 
        // work around for kernel that uses 'l' labels in assembly code
        if ( (atom.symbolTableInclusion() == ld::Atom::symbolTableNotInFinalLinkedImages) 
-                       && (atom.name()[0] == 'l') && (_options.outputKind() == Options::kStaticExecutable) )
+                       && (atom.name()[0] == 'l') && (_options.outputKind() == Options::kStaticExecutable) 
+                       && (strncmp(atom.name(), "ltmp", 4) != 0) )
                (const_cast<ld::Atom*>(&atom))->setSymbolTableInclusion(ld::Atom::symbolTableIn);
 
 
        // 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 ld::Atom* alias = new AliasAtom(atom, it->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);
+                                       }
                                }
                        }
                }
@@ -482,11 +762,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
@@ -506,6 +805,8 @@ bool Resolver::isDtraceProbe(ld::Fixup::Kind kind)
                case ld::Fixup::kindStoreX86DtraceIsEnableSiteClear:
                case ld::Fixup::kindStoreARMDtraceCallSiteNop:
                case ld::Fixup::kindStoreARMDtraceIsEnableSiteClear:
+               case ld::Fixup::kindStoreARM64DtraceCallSiteNop:
+               case ld::Fixup::kindStoreARM64DtraceIsEnableSiteClear:
                case ld::Fixup::kindStoreThumbDtraceCallSiteNop:
                case ld::Fixup::kindStoreThumbDtraceIsEnableSiteClear:
                case ld::Fixup::kindDtraceExtra:
@@ -523,6 +824,8 @@ void Resolver::convertReferencesToIndirect(const ld::Atom& atom)
        const ld::Atom* dummy;
        ld::Fixup::iterator end = atom.fixupsEnd();
        for (ld::Fixup::iterator fit=atom.fixupsBegin(); fit != end; ++fit) {
+               if ( fit->kind == ld::Fixup::kindLinkerOptimizationHint )
+                       _internal.someObjectHasOptimizationHints = true;
                switch ( fit->binding ) { 
                        case ld::Fixup::bindingByNameUnbound:
                                if ( isDtraceProbe(fit->kind) && (_options.outputKind() != Options::kObjectFile ) ) {
@@ -634,14 +937,34 @@ void Resolver::resolveUndefines()
                        }
                }
        }
-               
+       
+       // Use linker options to resolve any remaining undefined symbols
+       if ( !_internal.linkerOptionLibraries.empty() || !_internal.linkerOptionFrameworks.empty() ) {
+               std::vector<const char*> undefineNames;
+               _symbolTable.undefines(undefineNames);
+               if ( undefineNames.size() != 0 ) {
+                       for (std::vector<const char*>::iterator it = undefineNames.begin(); it != undefineNames.end(); ++it) {
+                               const char* undef = *it;
+                               if ( ! _symbolTable.hasName(undef) ) {
+                                       _inputFiles.searchLibraries(undef, true, true, false, *this);
+                               }
+                       }
+               }
+       }
+       
        // create proxies as needed for undefined symbols
        if ( (_options.undefinedTreatment() != Options::kUndefinedError) || (_options.outputKind() == Options::kObjectFile) ) {
                std::vector<const char*> undefineNames;
                _symbolTable.undefines(undefineNames);
                for(std::vector<const char*>::iterator it = undefineNames.begin(); it != undefineNames.end(); ++it) {
-                       // make proxy
-                       this->doAtom(*new UndefinedProxyAtom(*it));
+                       const char* undefName = *it;
+                       // <rdar://problem/14547001> "ld -r -exported_symbol _foo" has wrong error message if _foo is undefined
+                       bool makeProxy = true;
+                       if ( (_options.outputKind() == Options::kObjectFile) && _options.hasExportMaskList() && _options.shouldExport(undefName) ) 
+                               makeProxy = false;
+                       
+                       if ( makeProxy ) 
+                               this->doAtom(*new UndefinedProxyAtom(undefName));
                }
        }
        
@@ -657,6 +980,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);
+
 }
 
 
@@ -665,12 +992,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());
                }
        }
        
@@ -693,10 +1020,14 @@ void Resolver::markLive(const ld::Atom& atom, WhyLiveBackChain* previous)
                        case ld::Fixup::kindNoneGroupSubordinate:
                        case ld::Fixup::kindNoneGroupSubordinateFDE:
                        case ld::Fixup::kindNoneGroupSubordinateLSDA:
+                       case ld::Fixup::kindNoneGroupSubordinatePersonality:
                        case ld::Fixup::kindSetTargetAddress:
                        case ld::Fixup::kindSubtractTargetAddress:
                        case ld::Fixup::kindStoreTargetAddressLittleEndian32:
                        case ld::Fixup::kindStoreTargetAddressLittleEndian64:
+#if SUPPORT_ARCH_arm64e
+                       case ld::Fixup::kindStoreTargetAddressLittleEndianAuth64:
+#endif
                        case ld::Fixup::kindStoreTargetAddressBigEndian32:
                        case ld::Fixup::kindStoreTargetAddressBigEndian64:
                        case ld::Fixup::kindStoreTargetAddressX86PCRel32:
@@ -709,6 +1040,14 @@ void Resolver::markLive(const ld::Atom& atom, WhyLiveBackChain* previous)
                        case ld::Fixup::kindStoreTargetAddressX86Abs32TLVLoadNowLEA:
                        case ld::Fixup::kindStoreTargetAddressARMBranch24:
                        case ld::Fixup::kindStoreTargetAddressThumbBranch22:
+#if SUPPORT_ARCH_arm64
+                       case ld::Fixup::kindStoreTargetAddressARM64Branch26:
+                       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()
                                        // but a archive loaded .o file may have a forward reference
@@ -840,6 +1179,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 ) {
@@ -851,10 +1222,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());
        }
 
@@ -1021,11 +1395,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
                                        }
@@ -1085,6 +1459,10 @@ void Resolver::checkUndefines(bool force)
        int unresolvableExportsCount = 0;
        if ( unresolvableCount != 0 ) {
                if ( doPrint ) {
+                       for (const auto& lib : _internal.missingLinkerOptionLibraries)
+                               warning("Could not find auto-linked library '%s'", lib);
+                       for (const auto& frm : _internal.missingLinkerOptionFrameworks)
+                               warning("Could not find auto-linked framework '%s'", frm);
                        if ( _options.printArchPrefix() )
                                fprintf(stderr, "Undefined symbols for architecture %s:\n", _options.architectureName());
                        else
@@ -1109,6 +1487,10 @@ void Resolver::checkUndefines(bool force)
                                        else if ( _options.hasReExportList() && _options.shouldReExport(name) ) {
                                                fprintf(stderr, "     -reexported_symbols_list command line option\n");
                                        }
+                                       else if ( (_options.outputKind() == Options::kDynamicExecutable)
+                                                       && (_options.entryName() != NULL) && (strcmp(name, _options.entryName()) == 0) ) {
+                                               fprintf(stderr, "     implicit entry/start for main executable\n");
+                                       }
                                        else {
                                                bool isInitialUndefine = false;
                                                for (Options::UndefinesIterator uit=_options.initialUndefinesBegin(); uit != _options.initialUndefinesEnd(); ++uit) {
@@ -1237,6 +1619,7 @@ void Resolver::fillInHelpersInInternalState()
        }
        
        _internal.classicBindingHelper = NULL;
+       // FIXME: What about fMakeThreadedStartsSection?
        if ( needsStubHelper && !_options.makeCompressedDyldInfo() ) { 
                // "dyld_stub_binding_helper" comes from .o file, so should already exist in symbol table
                if ( _symbolTable.hasName("dyld_stub_binding_helper") ) {
@@ -1257,6 +1640,7 @@ void Resolver::fillInHelpersInInternalState()
        }
        
        _internal.compressedFastBinderProxy = NULL;
+       // FIXME: What about fMakeThreadedStartsSection?
        if ( needsStubHelper && _options.makeCompressedDyldInfo() ) { 
                // "dyld_stub_binder" comes from libSystem.dylib so will need to manually resolve
                if ( !_symbolTable.hasName("dyld_stub_binder") ) {
@@ -1286,7 +1670,12 @@ void Resolver::fillInInternalState()
        
        // <rdar://problem/7783918> make sure there is a __text section so that codesigning works
        if ( (_options.outputKind() == Options::kDynamicLibrary) || (_options.outputKind() == Options::kDynamicBundle) )
-               _internal.getFinalSection(ld::Section("__TEXT", "__text", ld::Section::typeCode));
+               _internal.getFinalSection(*new ld::Section("__TEXT", "__text", ld::Section::typeCode));
+
+       // Don't allow swift frameworks to link other swift frameworks.
+       if ( _internal.someObjectFileHasSwift && _internal.firstSwiftDylibFile != nullptr )
+               throwf("linking swift frameworks against other swift frameworks (%s) is not permitted",
+                          _internal.firstSwiftDylibFile->path());
 }
 
 void Resolver::fillInEntryPoint()
@@ -1294,7 +1683,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()
 {
@@ -1317,39 +1737,74 @@ void Resolver::linkTimeOptimize()
        if ( ! _haveLLVMObjs )
                return;
 
+       // <rdar://problem/15314161> LTO: Symbol multiply defined error should specify exactly where the symbol is found
+    _symbolTable.checkDuplicateSymbols();
+
        // run LLVM lto code-gen
        lto::OptimizeOptions optOpt;
        optOpt.outputFilePath                           = _options.outputFilePath();
        optOpt.tmpObjectFilePath                        = _options.tempLtoObjectPath();
+       optOpt.ltoCachePath                                     = _options.ltoCachePath();
+       optOpt.ltoPruneIntervalOverwrite        = _options.ltoPruneIntervalOverwrite();
+       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));
+#if SUPPORT_ARCH_arm64e
+       optOpt.supportsAuthenticatedPointers = _options.supportsAuthenticatedPointers();
+#endif
+       optOpt.bitcodeBundle                            = (_options.bundleBitcode() && (_options.bitcodeKind() != Options::kBitcodeMarker));
+       optOpt.maxDefaultCommonAlignment        = _options.maxDefaultCommonAlign();
        optOpt.arch                                                     = _options.architecture();
+       optOpt.mcpu                                                     = _options.mcpuLTO();
+       optOpt.platforms                                        = _options.platforms();
        optOpt.llvmOptions                                      = &_options.llvmOptions();
+       optOpt.initialUndefines                         = &_options.initialUndefines();
        
        std::vector<const ld::Atom*>            newAtoms;
        std::vector<const char*>                        additionalUndefines; 
        if ( ! lto::optimize(_atoms, _internal, optOpt, *this, newAtoms, additionalUndefines) )
                return; // if nothing done
-               
+       _ltoCodeGenFinished = true;
        
        // add all newly created atoms to _atoms and update symbol table
        for(std::vector<const ld::Atom*>::iterator it = newAtoms.begin(); it != newAtoms.end(); ++it)
                this->doAtom(**it);
-               
+
        // some atoms might have been optimized way (marked coalesced), remove them
        this->removeCoalescedAwayAtoms();
 
-       // run through all atoms again and make sure newly codegened atoms have refernces bound
+       // run through all atoms again and make sure newly codegened atoms have references bound
        for (std::vector<const ld::Atom*>::const_iterator it=_atoms.begin(); it != _atoms.end(); ++it) 
                this->convertReferencesToIndirect(**it);
 
+       // adjust section of any new
+       for (std::vector<const AliasAtom*>::const_iterator it=_aliasesFromCmdLine.begin(); it != _aliasesFromCmdLine.end(); ++it) {
+               const AliasAtom* aliasAtom = *it;
+               // update fields in AliasAtom to match newly constructed mach-o atom
+               aliasAtom->setFinalAliasOf();
+       }
+       
+       // <rdar://problem/14609792> add any auto-link libraries requested by LTO output to dylibs to search
+       _inputFiles.addLinkerOptionLibraries(_internal, *this);
+       _inputFiles.createIndirectDylibs();
+
        // resolve new undefines (e.g calls to _malloc and _memcpy that llvm compiler conjures up)
        for(std::vector<const char*>::iterator uit = additionalUndefines.begin(); uit != additionalUndefines.end(); ++uit) {
                const char *targetName = *uit;
@@ -1361,13 +1816,32 @@ 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) {
+                       const ld::Atom* atom = *it;
+                       if ( atom->scope() == ld::Atom::scopeGlobal ) {
+                               if ( !_options.shouldExport(atom->name()) ) {
+                                       (const_cast<ld::Atom*>(atom))->setScope(ld::Atom::scopeLinkageUnit);
+                               }
+                       }
+               }
+       }
        
        if ( _options.outputKind() == Options::kObjectFile ) {
                // if -r mode, add proxies for new undefines (e.g. ___stack_chk_fail)
@@ -1375,10 +1849,28 @@ void Resolver::linkTimeOptimize()
        }
        else {
                // last chance to check for undefines
+               this->resolveUndefines();
                this->checkUndefines(true);
 
                // 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);
        }
 }
 
@@ -1415,6 +1907,20 @@ 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");
+       for (std::vector<const ld::Atom*>::const_iterator it=_atoms.begin(); it != _atoms.end(); ++it) {
+               const ld::Atom* atom = *it;
+               fprintf(stderr, "  %p name=%s, def=%d\n", atom, atom->name(), atom->definition());
+       }
+}
 
 void Resolver::resolve()
 {
@@ -1426,12 +1932,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();
 }