]> git.saurik.com Git - apple/ld64.git/blobdiff - src/ld/Options.cpp
ld64-409.12.tar.gz
[apple/ld64.git] / src / ld / Options.cpp
index d916c536c120d761726c8bebe46c4b9b82794df8..09290a921b95267872e14a233ad24bf2681bba97 100644 (file)
 #include <spawn.h>
 #include <cxxabi.h>
 #include <Availability.h>
+#include <tapi/tapi.h>
 
 #include <vector>
+#include <map>
+#include <sstream>
 
+#include "ld.hpp"
 #include "Options.h"
 #include "Architectures.hpp"
 #include "MachOFileAbstraction.hpp"
 #include "Snapshot.h"
 
+// from FunctionNameDemangle.h
+extern "C" size_t fnd_get_demangled_name(const char *mangledName, char *outputBuffer, size_t length);
+
+
 // upward dependency on lto::version()
 namespace lto {
        extern const char* version();
+       extern unsigned static_api_version();
+       extern unsigned runtime_api_version();
 }
 
 // magic to place command line in crash reports
@@ -107,50 +117,57 @@ void throwf(const char* format, ...)
 
 bool Options::FileInfo::checkFileExists(const Options& options, const char *p)
 {
+       if (isInlined) {
+               modTime = 0;
+               return true;
+       }
        struct stat statBuffer;
        if (p == NULL) 
          p = path;
        if ( stat(p, &statBuffer) == 0 ) {
                if (p != path) path = strdup(p);
-               fileLen = statBuffer.st_size;
                modTime = statBuffer.st_mtime;
                return true;
        }
-       if ( options.dumpDependencyInfo() )
-               options.dumpDependency(Options::depNotFound, p);
+       options.addDependency(Options::depNotFound, p);
+//     fprintf(stderr, "not found: %s\n", p);
     return false;
 }
 
 
 Options::Options(int argc, const char* argv[])
-       : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0), fArchitectureName("unknown"), fOutputKind(kDynamicExecutable), 
-         fHasPreferredSubType(false), fArchSupportsThumb2(false), fPrebind(false), fBindAtLoad(false), fKeepPrivateExterns(false),
-         fNeedsModuleTable(false), fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false), 
+       : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0),
+         fFallbackArchitecture(0), fFallbackSubArchitecture(0), fArchitectureName("unknown"), fOutputKind(kDynamicExecutable),
+         fHasPreferredSubType(false), fArchSupportsThumb2(false), fBindAtLoad(false), fKeepPrivateExterns(false),
+         fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false),
          fInterposeMode(kInterposeNone), fDeadStrip(false), fNameSpace(kTwoLevelNameSpace),
-         fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL), fFinalName(NULL), fEntryName("start"), 
-         fBaseAddress(0), fMaxAddress(0x7FFFFFFFFFFFFFFFLL), 
-         fBaseWritableAddress(0), fSplitSegs(false),
+         fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL), fFinalName(NULL), fEntryName(NULL),
+         fBaseAddress(0), fMaxAddress(0xFFFFFFFFFFFFFFFFULL),
+         fBaseWritableAddress(0),
          fExportMode(kExportDefault), fLibrarySearchMode(kSearchDylibAndArchiveInEachDir),
          fUndefinedTreatment(kUndefinedError), fMessagesPrefixedWithArchitecture(true), 
          fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak),
          fClientName(NULL),
          fUmbrellaName(NULL), fInitFunctionName(NULL), fDotOutputFile(NULL), fExecutablePath(NULL),
-         fBundleLoader(NULL), fDtraceScriptName(NULL), fSegAddrTablePath(NULL), fMapPath(NULL), 
-         fDyldInstallPath("/usr/lib/dyld"), fTempLtoObjectPath(NULL), fOverridePathlibLTO(NULL), fLtoCpu(NULL),
+         fBundleLoader(NULL), fDtraceScriptName(NULL), fMapPath(NULL),
+         fDyldInstallPath("/usr/lib/dyld"), fLtoCachePath(NULL), fTempLtoObjectPath(NULL), fOverridePathlibLTO(NULL), fLtoCpu(NULL),
+         fKextObjectsEnable(-1),fKextObjectsDirPath(NULL),fToolchainPath(NULL),
          fZeroPageSize(ULLONG_MAX), fStackSize(0), fStackAddr(0), fSourceVersion(0), fSDKVersion(0), fExecutableStack(false), 
          fNonExecutableHeap(false), fDisableNonExecutableHeap(false),
          fMinimumHeaderPad(32), fSegmentAlignment(4096), 
          fCommonsMode(kCommonsIgnoreDylibs),  fUUIDMode(kUUIDContent), fLocalSymbolHandling(kLocalSymbolsAll), fWarnCommons(false), 
          fVerbose(false), fKeepRelocations(false), fWarnStabs(false),
          fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
-         fSharedRegionEligible(false), fPrintOrderFileStatistics(false),  
+         fSharedRegionEligible(false), fSharedRegionEligibleForceOff(false), fPrintOrderFileStatistics(false),
          fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), fPIEOnCommandLine(false),
          fDisablePositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
          fDeadStripDylibs(false),  fAllowTextRelocs(false), fWarnTextRelocs(false), fKextsUseStubs(false),
-         fUsingLazyDylibLinking(false), fEncryptable(true), 
+         fUsingLazyDylibLinking(false), fEncryptable(true), fEncryptableForceOn(false), fEncryptableForceOff(false),
          fOrderData(true), fMarkDeadStrippableDylib(false),
-         fMakeCompressedDyldInfo(true), fMakeCompressedDyldInfoForceOff(false), fNoEHLabels(false),
-         fAllowCpuSubtypeMismatches(false), fUseSimplifiedDylibReExports(false),
+         fMakeCompressedDyldInfo(true), fMakeCompressedDyldInfoForceOff(false),
+         fMakeThreadedStartsSection(false), fNoEHLabels(false),
+         fAllowCpuSubtypeMismatches(false), fEnforceDylibSubtypesMatch(false),
+         fWarnOnSwiftABIVersionMismatches(false), fUseSimplifiedDylibReExports(false),
          fObjCABIVersion2Override(false), fObjCABIVersion1Override(false), fCanUseUpwardDylib(false),
          fFullyLoadArchives(false), fLoadAllObjcObjectsFromArchives(false), fFlatNamespace(false),
          fLinkingMainExecutable(false), fForFinalLinkedImage(false), fForStatic(false),
@@ -158,8 +175,8 @@ Options::Options(int argc, const char* argv[])
          fSetuidSafe(false), fImplicitlyLinkPublicDylibs(true), fAddCompactUnwindEncoding(true),
          fWarnCompactUnwind(false), fRemoveDwarfUnwindIfCompactExists(false),
          fAutoOrderInitializers(true), fOptimizeZeroFill(true), fMergeZeroFill(false), fLogObjectFiles(false),
-         fLogAllFiles(false), fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false),
-         fOutputSlidable(false), fWarnWeakExports(false), 
+         fLogAllFiles(false), fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false), fTraceEmitJSON(false),
+         fOutputSlidable(false), fWarnWeakExports(false), fNoWeakExports(false),
          fObjcGcCompaction(false), fObjCGc(false), fObjCGcOnly(false), 
          fDemangle(false), fTLVSupport(false), 
          fVersionLoadCommand(false), fVersionLoadCommandForcedOn(false), 
@@ -168,18 +185,26 @@ Options::Options(int argc, const char* argv[])
          fDataInCodeInfoLoadCommand(false), fDataInCodeInfoLoadCommandForcedOn(false), fDataInCodeInfoLoadCommandForcedOff(false),
          fCanReExportSymbols(false), fObjcCategoryMerging(true), fPageAlignDataAtoms(false), 
          fNeedsThreadLoadCommand(false), fEntryPointLoadCommand(false),
-         fEntryPointLoadCommandForceOn(false), fEntryPointLoadCommandForceOff(false),
-         fSourceVersionLoadCommand(false), 
+         fSourceVersionLoadCommand(false),
          fSourceVersionLoadCommandForceOn(false), fSourceVersionLoadCommandForceOff(false), 
-         fDependentDRInfo(false), fDependentDRInfoForcedOn(false), fDependentDRInfoForcedOff(false),
-         fTargetIOSSimulator(false), fExportDynamic(false), fAbsoluteSymbols(false),
+         fExportDynamic(false), fAbsoluteSymbols(false),
          fAllowSimulatorToLinkWithMacOSX(false), fKeepDwarfUnwind(true),
          fKeepDwarfUnwindForcedOn(false), fKeepDwarfUnwindForcedOff(false),
-         fGenerateDtraceDOF(true),
-         fDebugInfoStripping(kDebugInfoMinimal), fTraceOutputFile(NULL), 
-         fMacVersionMin(ld::macVersionUnset), fIOSVersionMin(ld::iOSVersionUnset), 
-         fSaveTempFiles(false), fSnapshotRequested(false), fPipelineFifo(NULL), 
-         fDependencyInfoPath(NULL), fDependencyFileDescriptor(-1)
+         fVerboseOptimizationHints(false), fIgnoreOptimizationHints(false),
+         fGenerateDtraceDOF(true), fAllowBranchIslands(true), fTraceSymbolLayout(false), 
+         fMarkAppExtensionSafe(false), fCheckAppExtensionSafe(false), fForceLoadSwiftLibs(false),
+         fSharedRegionEncodingV2(false), fUseDataConstSegment(false),
+         fUseDataConstSegmentForceOn(false), fUseDataConstSegmentForceOff(false), fUseTextExecSegment(false),
+         fBundleBitcode(false), fHideSymbols(false), fVerifyBitcode(false),
+         fReverseMapUUIDRename(false), fDeDupe(true), fVerboseDeDupe(false),
+         fUseLinkedListBinding(false), fNoLazyBinding(false), fDebugVariant(false),
+         fReverseMapPath(NULL), fLTOCodegenOnly(false),
+         fIgnoreAutoLink(false), fAllowDeadDups(false), fAllowWeakImports(true), fInitializersTreatment(Options::kInvalid),
+         fZeroModTimeInDebugMap(false), fBitcodeKind(kBitcodeProcess),
+         fDebugInfoStripping(kDebugInfoMinimal), fTraceOutputFile(NULL),
+         fSaveTempFiles(false), fLinkSnapshot(this), fSnapshotRequested(false), fPipelineFifo(NULL),
+         fDependencyInfoPath(NULL), fBuildContextName(NULL), fTraceFileDescriptor(-1), fMaxDefaultCommonAlign(0),
+         fUnalignedPointerTreatment(kUnalignedPointerIgnore)
 {
        this->checkForClassic(argc, argv);
        this->parsePreCommandLineEnvironmentSettings();
@@ -188,17 +213,15 @@ Options::Options(int argc, const char* argv[])
        this->reconfigureDefaults();
        this->checkIllegalOptionCombinations();
        
-       if ( this->dumpDependencyInfo() ) {
-               this->dumpDependency(depOutputFile, fOutputFile);
-               if ( fMapPath != NULL ) 
-               this->dumpDependency(depOutputFile, fMapPath);
-       }
+       this->addDependency(depOutputFile, fOutputFile);
+       if ( fMapPath != NULL )
+               this->addDependency(depOutputFile, fMapPath);
 }
 
 Options::~Options()
 {
-  if ( fDependencyFileDescriptor != -1 )
-       ::close(fDependencyFileDescriptor);
+       if ( fTraceFileDescriptor != -1 )
+               ::close(fTraceFileDescriptor);
 }
 
 bool Options::errorBecauseOfWarnings() const
@@ -234,7 +257,7 @@ bool Options::interposable(const char* name) const
 
 bool Options::printWhyLive(const char* symbolName) const
 {
-       return ( fWhyLive.find(symbolName) != fWhyLive.end() );
+       return fWhyLive.contains(symbolName);
 }
 
 
@@ -305,12 +328,15 @@ uint32_t Options::initialSegProtection(const char* segName) const
                        return it->init;
                }
        }
-       if ( strcmp(segName, "__PAGEZERO") == 0 ) {
-               return 0;
+       if ( strcmp(segName, "__TEXT") == 0 ) {
+               return ( fUseTextExecSegment ? VM_PROT_READ : (VM_PROT_READ | VM_PROT_EXECUTE) );
        }
-       else if ( strcmp(segName, "__TEXT") == 0 ) {
+       else if ( strcmp(segName, "__TEXT_EXEC") == 0 ) {
                return VM_PROT_READ | VM_PROT_EXECUTE;
        }
+       else if ( strcmp(segName, "__PAGEZERO") == 0 ) {
+               return 0;
+       }
        else if ( strcmp(segName, "__LINKEDIT") == 0 ) {
                return VM_PROT_READ;
        }
@@ -323,7 +349,7 @@ uint32_t Options::maxSegProtection(const char* segName) const
 {
        // iPhoneOS always uses same protection for max and initial
        // <rdar://problem/11663436> simulator apps need to use MacOSX max-prot
-       if ( (fIOSVersionMin != ld::iOSVersionUnset) && (fArchitecture != CPU_TYPE_I386) )
+       if ( (platforms().contains(ld::kPlatform_macOS) == 0) && !targetIOSSimulator() )
                return initialSegProtection(segName);
 
        for(std::vector<Options::SegmentProtect>::const_iterator it = fCustomSegmentProtections.begin(); it != fCustomSegmentProtections.end(); ++it) {
@@ -377,6 +403,9 @@ bool Options::hasCustomSectionAlignment(const char* segName, const char* sectNam
                if ( (strcmp(it->segmentName, segName) == 0) && (strcmp(it->sectionName, sectName) == 0) )
                        return true;
        }
+       if ( fEncryptable && (strcmp(sectName, "__oslogstring") == 0) && (strcmp(segName, "__TEXT") == 0) )
+               return true;
+
        return false;
 }
 
@@ -386,9 +415,23 @@ uint8_t Options::customSectionAlignment(const char* segName, const char* sectNam
                if ( (strcmp(it->segmentName, segName) == 0) && (strcmp(it->sectionName, sectName) == 0) )
                        return it->alignment;
        }
+       if ( fEncryptable && (strcmp(sectName, "__oslogstring") == 0) && (strcmp(segName, "__TEXT") == 0) )
+               return __builtin_ctz(fSegmentAlignment);
+
        return 0;
 }
 
+bool Options::segmentOrderAfterFixedAddressSegment(const char* segName) const
+{
+       bool nowPinned = false;
+       for (std::vector<const char*>::const_iterator it=fSegmentOrder.begin(); it != fSegmentOrder.end(); ++it) {
+               if ( strcmp(*it, segName) == 0 )
+                       return nowPinned;
+               if ( hasCustomSegmentAddress(*it) )
+                       nowPinned = true;
+       }
+       return false;
+}
 
 bool Options::hasExportedSymbolOrder()
 {
@@ -538,7 +581,16 @@ bool Options::keepLocalSymbol(const char* symbolName) const
        throw "internal error";
 }
 
-void Options::setArchitecture(cpu_type_t type, cpu_subtype_t subtype)
+const std::vector<const char*>* Options::sectionOrder(const char* segName) const
+{ 
+       for (std::vector<SectionOrderList>::const_iterator it=fSectionOrder.begin(); it != fSectionOrder.end(); ++it) {
+               if ( strcmp(it->segmentName, segName) == 0 )
+                       return &it->sectionOrder;
+       }
+       return NULL;
+}
+
+void Options::setArchitecture(cpu_type_t type, cpu_subtype_t subtype, ld::Platform platform, uint32_t minOsVers)
 {
        for (const ArchInfo* t=archInfoArray; t->archName != NULL; ++t) {
                if ( (type == t->cpuType) && (subtype == t->cpuSubType) ) {
@@ -547,40 +599,47 @@ void Options::setArchitecture(cpu_type_t type, cpu_subtype_t subtype)
                        fArchitectureName = t->archName;
                        fHasPreferredSubType = t->isSubType;
                        fArchSupportsThumb2 = t->supportsThumb2;
+                       if ( platforms().empty() && (platform != ld::kPlatform_unknown) )
+                               fPlatforms.add({platform, minOsVers});
                        switch ( type ) {
                                case CPU_TYPE_I386:
                                case CPU_TYPE_X86_64:
-                                       if ( (fMacVersionMin == ld::macVersionUnset) && (fIOSVersionMin == ld::iOSVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
+                                       if ( platforms().contains(ld::kPlatform_macOS) && (fOutputKind != Options::kObjectFile) && (platforms().minOS(ld::kPlatform_macOS) == 0) ) {
                                #ifdef DEFAULT_MACOSX_MIN_VERSION
                                                warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION);
-                                               setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
+                                               setVersionMin(ld::kPlatform_macOS, DEFAULT_MACOSX_MIN_VERSION);
                                #else
                                                warning("-macosx_version_min not specified, assuming 10.6");
-                                               fMacVersionMin = ld::mac10_6;
-                               #endif          
+                                               setVersionMin(ld::kPlatform_macOS, "10.6");
+                               #endif
                                        }
                                        break;
                                case CPU_TYPE_ARM:
                                case CPU_TYPE_ARM64:
-                                       if ( (fMacVersionMin == ld::macVersionUnset) && (fIOSVersionMin == ld::iOSVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
+                               if ( platforms().contains(ld::kPlatform_iOS) && (platforms().minOS(ld::kPlatform_iOS) == 0) && (fOutputKind != Options::kObjectFile) ) {
                                #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
                                                warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION);
-                                               setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION);
+                                               setVersionMin(ld::kPlatformiOS, DEFAULT_IPHONEOS_MIN_VERSION);
                                #else
                                                warning("-ios_version_min not specified, assuming 6.0");
-                                               setIOSVersionMin("6.0");
+                                               setVersionMin(ld::kPlatform_iOS, "6.0");
                                #endif
                                        }
+#if SUPPORT_ARCH_arm64e
+                                       if ( (fArchitecture == CPU_TYPE_ARM64) && (fSubArchitecture == CPU_SUBTYPE_ARM64_E) ) {
+                                               fSupportsAuthenticatedPointers = true;
+                                       }
+#endif
                                        break;
                        }
                        fLinkSnapshot.recordArch(fArchitectureName);
                        // only use compressed LINKEDIT for:
                        //                      Mac OS X 10.6 or later
                        //                      iOS 3.1 or later
-                       if ( !fMakeCompressedDyldInfo && minOS(ld::mac10_6, ld::iOS_3_1) && !fMakeCompressedDyldInfoForceOff )
+                       if ( !fMakeCompressedDyldInfo && platforms().minOS(ld::version2009) && !fMakeCompressedDyldInfoForceOff )
                                fMakeCompressedDyldInfo = true;
                        // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
-                       if ( minOS(ld::mac10_5, ld::iOS_2_0) )
+                       if ( platforms().minOS(ld::version2008) )
                                fUseSimplifiedDylibReExports = true;
                        return;
                }
@@ -588,6 +647,40 @@ void Options::setArchitecture(cpu_type_t type, cpu_subtype_t subtype)
        fArchitectureName = "unknown architecture";
 }
 
+bool Options::armUsesZeroCostExceptions() const
+{
+       return ( (fArchitecture == CPU_TYPE_ARM) && (fSubArchitecture == CPU_SUBTYPE_ARM_V7K) );
+}
+
+void Options::selectFallbackArch(const char *arch)
+{
+       // Should have the format "desired_arch:fallback_arch", for example "arm64_32:armv7k" to allow an armv7k
+       // slice to substitute for arm64_32 if the latter isn't present.
+       if (const char* fallbackEnv = getenv("LD_DYLIB_ARCH_FALLBACK") ) {
+               std::string fallback(fallbackEnv);
+               auto delimPos = fallback.find(':');
+
+               // Check we've got a potentially valid fallback string and that it's this architecture we're falling back from.
+               if ( delimPos == std::string::npos || fallback.substr(0, delimPos) != arch )
+                       return;
+
+               std::string fallbackTo = fallback.substr(delimPos + 1);
+               for (const ArchInfo *t = archInfoArray; t->archName != nullptr; ++t) {
+                       if ( fallbackTo == t->archName ) {
+                               fFallbackArchitecture = t->cpuType;
+                               fFallbackSubArchitecture = t->cpuSubType;
+                       }
+               }
+       }
+       else {
+               // <rdar://problem/39797337> let x86_64h fallback and use x86_64 slice
+               if ( (fArchitecture == CPU_TYPE_X86_64) && (fSubArchitecture == CPU_SUBTYPE_X86_64_H) ) {
+                       fFallbackArchitecture    = CPU_TYPE_X86_64;
+                       fFallbackSubArchitecture = CPU_SUBTYPE_X86_ALL;
+               }
+       }
+}
+
 void Options::parseArch(const char* arch)
 {
        if ( arch == NULL )
@@ -599,6 +692,7 @@ void Options::parseArch(const char* arch)
                        fSubArchitecture = t->cpuSubType;
                        fHasPreferredSubType = t->isSubType;
                        fArchSupportsThumb2 = t->supportsThumb2;
+                       selectFallbackArch(arch);
                        return;
                }
        }
@@ -631,7 +725,21 @@ Options::FileInfo Options::findLibrary(const char* rootName, bool dylibsOnly) co
                }
        }
        else {
-               bool lookForDylibs = ( fOutputKind != Options::kDyld);
+               bool lookForDylibs = false;
+               switch ( fOutputKind ) {
+                       case Options::kDynamicExecutable:
+                       case Options::kDynamicLibrary:
+                       case Options::kDynamicBundle:
+                       case Options::kObjectFile:  // <rdar://problem/15914513> 
+                               lookForDylibs = true;
+                               break;
+                       case Options::kStaticExecutable:
+                       case Options::kDyld:
+                       case Options::kPreload:
+                       case Options::kKextBundle:
+                               lookForDylibs = false;
+                               break;
+               }
                switch ( fLibrarySearchMode ) {
                case kSearchAllDirsForDylibsThenAllDirsForArchives:
                                // first look in all directories for just for dylibs
@@ -640,7 +748,8 @@ Options::FileInfo Options::findLibrary(const char* rootName, bool dylibsOnly) co
                                                 it != fLibrarySearchPaths.end();
                                                 it++) {
                                                const char* dir = *it;
-                                               if ( checkForFile("%s/lib%s.dylib", dir, rootName, result) )
+                                               auto path = std::string(dir) + "/lib" + rootName + ".dylib";
+                                               if ( findFile(path, {".tbd"}, result) )
                                                        return result;
                                        }
                                        for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
@@ -669,7 +778,8 @@ Options::FileInfo Options::findLibrary(const char* rootName, bool dylibsOnly) co
                                         it != fLibrarySearchPaths.end();
                                         it++) {
                                        const char* dir = *it;
-                                       if ( lookForDylibs && checkForFile("%s/lib%s.dylib", dir, rootName, result) )
+                                       auto path = std::string(dir) + "/lib" + rootName + ".dylib";
+                                       if ( lookForDylibs && findFile(path, {".tbd"}, result) )
                                                return result;
                                        if ( lookForDylibs && checkForFile("%s/lib%s.so", dir, rootName, result) )
                                                return result;
@@ -700,34 +810,17 @@ Options::FileInfo Options::findFramework(const char* frameworkName) const
 
 Options::FileInfo Options::findFramework(const char* rootName, const char* suffix) const
 {
-       for (std::vector<const char*>::const_iterator it = fFrameworkSearchPaths.begin();
-                it != fFrameworkSearchPaths.end();
-                it++) {
-               // ??? Shouldn't we be using String here and just initializing it?
-               // ??? Use str.c_str () to pull out the string for the stat call.
-               const char* dir = *it;
-               char possiblePath[PATH_MAX];
-               strcpy(possiblePath, dir);
-               strcat(possiblePath, "/");
-               strcat(possiblePath, rootName);
-               strcat(possiblePath, ".framework/");
-               strcat(possiblePath, rootName);
-               if ( suffix != NULL ) {
+       for (const auto* path : fFrameworkSearchPaths) {
+               auto possiblePath = std::string(path).append("/").append(rootName).append(".framework/").append(rootName);
+               if ( suffix != nullptr ) {
                        char realPath[PATH_MAX];
                        // no symlink in framework to suffix variants, so follow main symlink
-                       if ( realpath(possiblePath, realPath) != NULL ) {
-                               strcpy(possiblePath, realPath);
-                               strcat(possiblePath, suffix);
-                       }
+                       if ( realpath(possiblePath.c_str(), realPath) != nullptr )
+                               possiblePath = std::string(realPath).append(suffix);
                }
         FileInfo result;
-               bool found = result.checkFileExists(*this, possiblePath);
-               if ( fTraceDylibSearching )
-                       printf("[Logging for XBS]%sfound framework: '%s'\n",
-                                  (found ? " " : " not "), possiblePath);
-               if ( found ) {
+               if ( findFile(possiblePath, {".tbd"}, result) )
                        return result;
-               }
        }
        // try without suffix
        if ( suffix != NULL )
@@ -736,68 +829,236 @@ Options::FileInfo Options::findFramework(const char* rootName, const char* suffi
                throwf("framework not found %s", rootName);
 }
 
-Options::FileInfo Options::findFile(const char* path) const
+static std::string replace_extension(const std::string &path, const std::string &ext)
+{
+       auto result = path;
+       auto lastSlashIdx = result.find_last_of('/');
+       auto lastDotIdx = result.find_last_of('.');
+       if (lastDotIdx != std::string::npos && lastDotIdx > lastSlashIdx)
+               result.erase(lastDotIdx, std::string::npos);
+       if ( ext.size() > 0 && ext[0] == '.' )
+               result.append(ext);
+       else
+               result.append('.' + ext);
+       return result;
+}
+
+void Options::addTAPIInterface(tapi::LinkerInterfaceFile* interface, const char *path) const {
+#if ((TAPI_API_VERSION_MAJOR == 1 &&  TAPI_API_VERSION_MINOR >= 3) || (TAPI_API_VERSION_MAJOR > 1))
+       if (tapi::APIVersion::isAtLeast(1, 3)) {
+               for (auto &name : interface->inlinedFrameworkNames()) {
+                       fTAPIFiles.emplace_back(interface, path, name.c_str());
+               }
+       }
+#endif
+}
+
+bool Options::findFile(const std::string &path, const std::vector<std::string> &tbdExtensions, FileInfo& result) const
+{
+       FileInfo tbdInfo;
+       for ( const auto &ext : tbdExtensions ) {
+               auto newPath = replace_extension(path, ext);
+               bool found = tbdInfo.checkFileExists(*this, newPath.c_str());
+               if ( fTraceDylibSearching )
+                       printf("[Logging for XBS]%sfound library: '%s'\n", (found ? " " : " not "), newPath.c_str());
+               if ( found )
+                       break;
+       }
+
+       FileInfo dylibInfo;
+       {
+               bool found = dylibInfo.checkFileExists(*this, path.c_str());
+               if ( fTraceDylibSearching )
+                       printf("[Logging for XBS]%sfound library: '%s'\n", (found ? " " : " not "), path.c_str());
+       }
+
+       // There is only a text-based stub file or a dynamic library file.
+       if ( tbdInfo.missing() != dylibInfo.missing() ) {
+               result = tbdInfo.missing() ? dylibInfo : tbdInfo;
+       }
+       // There are both - a text-based stub file and a dynamic library file.
+       else if ( !tbdInfo.missing() && !dylibInfo.missing() ) {
+               // Check if we should prefer the text-based stub file (installapi).
+               if (tapi::LinkerInterfaceFile::shouldPreferTextBasedStubFile(tbdInfo.path)) {
+                       result = tbdInfo;
+               }
+               // If the files are still in sync we can use and should use the text-based stub file.
+               else if (tapi::LinkerInterfaceFile::areEquivalent(tbdInfo.path, dylibInfo.path)) {
+                       result = tbdInfo;
+               }
+               // Otherwise issue a warning and fall-back to the dynamic library file.
+               else {
+                       warning("text-based stub file %s and library file %s are out of sync. Falling back to library file for linking.", tbdInfo.path, dylibInfo.path);
+                       result = dylibInfo;
+               }
+       } else {
+               return false;
+       }
+
+       return true;
+}
+
+static bool startsWith(const std::string& str, const std::string& prefix)
+{
+       return (str.compare(0, prefix.length(), prefix) == 0);
+}
+
+static std::string getDirPath(const std::string& path)
+{
+       std::string::size_type lastSlashPos = path.find_last_of('/');
+       if ( lastSlashPos == std::string::npos )
+               return "./";
+       else
+               return path.substr(0, lastSlashPos+1);
+}
+
+Options::FileInfo Options::findFile(const std::string &path, const ld::dylib::File* fromDylib) const
 {
        FileInfo result;
 
-       // if absolute path and not a .o file, the use SDK prefix
-       if ( (path[0] == '/') && (strcmp(&path[strlen(path)-2], ".o") != 0) ) {
-               const int pathLen = strlen(path);
-               for (std::vector<const char*>::const_iterator it = fSDKPaths.begin(); it != fSDKPaths.end(); it++) {
-                       // ??? Shouldn't we be using String here?
-                       const char* sdkPathDir = *it;
-                       const int sdkPathDirLen = strlen(sdkPathDir);
-                       char possiblePath[sdkPathDirLen+pathLen+4];
-                       strcpy(possiblePath, sdkPathDir);
-                       if ( possiblePath[sdkPathDirLen-1] == '/' )
-                               possiblePath[sdkPathDirLen-1] = '\0';
-                       strcat(possiblePath, path);
-                       if ( result.checkFileExists(*this, possiblePath) ) {
+       // if absolute path and not a .o file, then use SDK prefix
+       if ( (path[0] == '/') && (strcmp(&path[path.size()-2], ".o") != 0) ) {
+               for (const auto* sdkPathDir : fSDKPaths) {
+                       auto possiblePath = std::string(sdkPathDir) + path;
+                       if ( findFile(possiblePath, {".tbd"}, result) )
+                               return result;
+               }
+       }
+
+       // expand @ variables
+       if ( path[0] == '@' ) {
+               if ( startsWith(path, "@executable_path/") && (fExecutablePath != nullptr) ) {
+                       std::string exeBasedPath = getDirPath(fExecutablePath) + &path[17];
+                       if ( findFile(exeBasedPath, {".tbd"}, result) )
                                return result;
+               }
+               else if ( startsWith(path, "@loader_path/") && (fromDylib != nullptr) ) {
+                       char absPath[PATH_MAX];
+                       if ( realpath(fromDylib->path(), absPath) != NULL ) {
+                               std::string loaderBasedPath = getDirPath(fromDylib->path()) + &path[13];
+                               if ( findFile(loaderBasedPath, {".tbd"}, result) )
+                                       return result;
+                       }
+               }
+               else if ( startsWith(path, "@rpath/") ) {
+                       // first search any LC_RPATH supplied by dyld that re-exports dylib to be found
+                       if ( fromDylib != nullptr ) {
+                               for (const char* rp : fromDylib->rpaths() ) {
+                                       std::string rpath = rp;
+                                       // handle dylib that has LC_RPATH = @loader_path/blah
+                                       if ( startsWith(rpath, "@loader_path/") ) {
+                                               char absPath[PATH_MAX];
+                                               if ( realpath(fromDylib->path(), absPath) != NULL )
+                                                       rpath = getDirPath(absPath) + &rpath[13];
+                                               else
+                                                       rpath = getDirPath(fromDylib->path()) + &rpath[13];
+                                       }
+                                       std::string rpathBasedPath = rpath + "/" + &path[6];
+                                       if ( findFile(rpathBasedPath, {".tbd"}, result) )
+                                               return result;
+                               }
                        }
                }
        }
+
+       // find inlined TBD file before raw path.
+       // rdar://problem/35864452
+       if (hasInlinedTAPIFile(path)) {
+               FileInfo inlinedFile(path.c_str());
+               inlinedFile.isInlined = true;
+               return inlinedFile;
+       }
+
        // try raw path
-       if ( result.checkFileExists(*this, path) ) {
+       if ( findFile(path, {".tbd"}, result) )
                return result;
+
+       // not found
+       throwf("file not found: %s", path.c_str());
+}
+
+bool Options::hasInlinedTAPIFile(const std::string &path) const {
+       for (const auto &dylib : fTAPIFiles) {
+               if (dylib.getInstallName() == path)
+                       return true;
        }
+       return false;
+}
 
-       // try @executable_path substitution
-       if ( (strncmp(path, "@executable_path/", 17) == 0) && (fExecutablePath != NULL) ) {
-               char newPath[strlen(fExecutablePath) + strlen(path)];
-               strcpy(newPath, fExecutablePath);
-               char* addPoint = strrchr(newPath,'/');
-               if ( addPoint != NULL )
-                       strcpy(&addPoint[1], &path[17]);
-               else
-                       strcpy(newPath, &path[17]);
-               if ( result.checkFileExists(*this, newPath) ) {
-                       return result;
+tapi::LinkerInterfaceFile* Options::findTAPIFile(const std::string &path) const
+{
+#if ((TAPI_API_VERSION_MAJOR == 1 &&  TAPI_API_VERSION_MINOR >= 3) || (TAPI_API_VERSION_MAJOR > 1))
+       tapi::LinkerInterfaceFile* interface = nullptr;
+       std::string TBDPath;
+       
+       // create parsing options.
+       tapi::ParsingFlags flags = tapi::ParsingFlags::None;
+       if (enforceDylibSubtypesMatch())
+               flags |= tapi::ParsingFlags::ExactCpuSubType;
+       
+       if (!allowWeakImports())
+               flags |= tapi::ParsingFlags::DisallowWeakImports;
+
+       __block uint32_t linkMinOSVersion = 0;
+       //FIXME handle this correctly once we have multi-platform TAPI.
+       platforms().forEach(^(ld::Platform platform, uint32_t version, bool &stop) {
+               if (linkMinOSVersion == 0)
+                       linkMinOSVersion = version;
+               if (platform == ld::kPlatform_macOS)
+                       linkMinOSVersion = version;
+       });
+
+       // Search through all the inlined framework.
+       for (const auto &dylib : fTAPIFiles) {
+               if (dylib.getInstallName() == path) {
+                       // If the install name matches, parse the framework.
+                       std::string errorMessage;
+                       auto file = dylib.getInterfaceFile()->getInlinedFramework(path.c_str(), architecture(), subArchitecture(),
+                                                                                                                                         flags, tapi::PackedVersion32(linkMinOSVersion), errorMessage);
+                       if (!file)
+                               throw strdup(errorMessage.c_str());
+
+                       if (!interface) {
+                               // If this is the first inlined framework found, record the information.
+                               interface = file;
+                               TBDPath = dylib.getTAPIFilePath();
+                       } else {
+                               // If we found other inlined framework already, check to see if their versions are the same.
+                               // If not the same, emit an warning and record the newer one. Otherwise, just use the current one.
+                               if (interface->getCurrentVersion() == file->getCurrentVersion())
+                                       continue;
+                               warning("Inlined framework/dylib mismatch: %s (%s and %s)", path.c_str(),
+                                               TBDPath.c_str(), dylib.getTAPIFilePath().c_str());
+                               if (interface->getCurrentVersion() < file->getCurrentVersion()) {
+                                       interface = file;
+                                       TBDPath = dylib.getTAPIFilePath();
+                               }
+                       }
                }
        }
-
-       // not found
-       throwf("file not found: %s", path);
+       return interface;
+#else
+       return nullptr;
+#endif
 }
 
-Options::FileInfo Options::findFileUsingPaths(const char* path) const 
+// search for indirect dylib first using -F and -L paths first
+Options::FileInfo Options::findIndirectDylib(const std::string& installName, const ld::dylib::File* fromDylib) const
 {
        FileInfo result;
 
-       const char* lastSlash = strrchr(path, '/');
-       const char* leafName = (lastSlash == NULL) ? path : &lastSlash[1];
+       auto lastSlashPos = installName.find_last_of('/');
+       auto pos = ( lastSlashPos != std::string::npos ) ? lastSlashPos + 1 : 0;
+       auto leafName = installName.substr(pos);
 
        // Is this in a framework?
        // /path/Foo.framework/Foo                                                      ==> true (Foo)
        // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
        // /path/Foo.framework/Resources/Bar                            ==> false
        bool isFramework = false;
-       if ( lastSlash != NULL ) {
-               char frameworkDir[strlen(leafName) + 20];
-               strcpy(frameworkDir, "/");
-               strcat(frameworkDir, leafName);
-               strcat(frameworkDir, ".framework/");
-               if ( strstr(path, frameworkDir) != NULL )
+       if ( lastSlashPos != std::string::npos ) {
+               auto frameworkDir = std::string("/").append(leafName).append(".framework/");
+               if ( installName.rfind(frameworkDir) != std::string::npos )
                        isFramework = true;
        }
        
@@ -806,96 +1067,32 @@ Options::FileInfo Options::findFileUsingPaths(const char* path) const
        // don't need to try variations, just paths. We do need to add the additional bits
        // onto the framework path though.
        if ( isFramework ) {
-               for (std::vector<const char*>::const_iterator it = fFrameworkSearchPaths.begin();
-                        it != fFrameworkSearchPaths.end();
-                        it++) {
-                       const char* dir = *it;
-                       char possiblePath[PATH_MAX];
-                       strcpy(possiblePath, dir);
-                       strcat(possiblePath, "/");
-                       strcat(possiblePath, leafName);
-                       strcat(possiblePath, ".framework");
-
-                       //fprintf(stderr,"Finding Framework: %s/%s, leafName=%s\n", possiblePath, leafName, leafName);
-                       if ( checkForFile("%s/%s", possiblePath, leafName, result) )
+               auto endPos = installName.rfind(".framework");
+               auto beginPos = installName.find_last_of('/', endPos);
+               auto leafPath = installName.substr(beginPos);
+               for (const auto* dir : fFrameworkSearchPaths) {
+                       auto possiblePath = dir + leafPath;
+                       if ( findFile(possiblePath, {".tbd"}, result) )
                                return result;
                }
-       } 
-       else {
+       } else {
                // if this is a .dylib inside a framework, do not search -L paths
-               // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard 
-               int leafLen = strlen(leafName);
-               bool embeddedDylib = ( (leafLen > 6) 
-                                       && (strcmp(&leafName[leafLen-6], ".dylib") == 0) 
-                                       && (strstr(path, ".framework/") != NULL) );
+               // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
+               bool embeddedDylib = ( (leafName.size() > 6)
+                                       && (leafName.find(".dylib", leafName.size()-6) != std::string::npos)
+                                       && (installName.find(".framework/") != std::string::npos) );
                if ( !embeddedDylib ) {
-                       for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
-                                it != fLibrarySearchPaths.end();
-                                it++) {
-                               const char* dir = *it;
+                       for (const auto* dir : fLibrarySearchPaths) {
                                //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
-                               if ( checkForFile("%s/%s", dir, leafName, result) )
+                               std::string possiblePath = dir + std::string("/") + leafName;
+                               if ( findFile(possiblePath, {".tbd"}, result) )
                                        return result;
                        }
                }
        }
 
        // If we didn't find it fall back to findFile.
-       return findFile(path);
-}
-
-
-
-void Options::parseSegAddrTable(const char* segAddrPath, const char* installPth)
-{
-       FILE* file = fopen(segAddrPath, "r");
-       if ( file == NULL ) {
-               warning("-seg_addr_table file cannot be read: %s", segAddrPath);
-               return;
-       }
-       
-       char path[PATH_MAX];
-       uint64_t firstColumAddress = 0;
-       uint64_t secondColumAddress = 0;
-       bool hasSecondColumn = false;
-       while ( fgets(path, PATH_MAX, file) != NULL ) {
-               path[PATH_MAX-1] = '\0';
-               char* eol = strchr(path, '\n');
-               if ( eol != NULL )
-                       *eol = '\0';
-               // ignore lines not starting with 0x number
-               if ( (path[0] == '0') && (path[1] == 'x') ) {
-                       char* p;
-                       firstColumAddress = strtoull(path, &p, 16);
-                       while ( isspace(*p) )
-                               ++p;
-                       // see if second column is a number
-                       if ( (p[0] == '0') && (p[1] == 'x') ) {
-                               secondColumAddress = strtoull(p, &p, 16);
-                               hasSecondColumn = true;
-                               while ( isspace(*p) )
-                                       ++p;
-                       }
-                       while ( isspace(*p) )
-                               ++p;
-                       if ( p[0] == '/' ) {
-                               // remove any trailing whitespace
-                               for(char* end = eol-1; (end > p) && isspace(*end); --end)
-                                       *end = '\0';
-                               // see if this line is for the dylib being linked
-                               if ( strcmp(p, installPth) == 0 ) {
-                                       fBaseAddress = firstColumAddress;
-                                       if ( hasSecondColumn ) {
-                                               fBaseWritableAddress = secondColumAddress;
-                                               fSplitSegs = true;
-                                       }
-                                       break; // out of while loop
-                               }
-                       }
-               }
-       }
-
-       fclose(file);
+       return findFile(installName, fromDylib);
 }
 
 void Options::loadFileList(const char* fileOfPaths, ld::File::Ordinal baseOrdinal)
@@ -915,16 +1112,14 @@ void Options::loadFileList(const char* fileOfPaths, ld::File::Ordinal baseOrdina
                        file = fopen(realFileOfPaths, "r");
                        if ( file == NULL )
                                throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", realFileOfPaths, errno, strerror(errno));
-                       if ( this->dumpDependencyInfo() )
-                               this->dumpDependency(Options::depFileList, realFileOfPaths);
+                       this->addDependency(Options::depFileList, realFileOfPaths);
                }
        }
        else {
                file = fopen(fileOfPaths, "r");
                if ( file == NULL )
                        throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", fileOfPaths, errno, strerror(errno));
-               if ( this->dumpDependencyInfo() )
-                       this->dumpDependency(Options::depFileList, fileOfPaths);
+               this->addDependency(Options::depFileList, fileOfPaths);
        }
 
        char path[PATH_MAX];
@@ -997,19 +1192,40 @@ void Options::SetWithWildcards::insert(const char* symbol)
                fRegular.insert(symbol);
 }
 
-bool Options::SetWithWildcards::contains(const char* symbol) const
+bool Options::SetWithWildcards::contains(const char* symbol, bool* matchBecauseOfWildcard) const
 {
+       if ( matchBecauseOfWildcard != NULL )
+               *matchBecauseOfWildcard = false;
        // first look at hash table on non-wildcard symbols
        if ( fRegular.find(symbol) != fRegular.end() )
                return true;
        // next walk list of wild card symbols looking for a match
        for(std::vector<const char*>::const_iterator it = fWildCard.begin(); it != fWildCard.end(); ++it) {
-               if ( wildCardMatch(*it, symbol) )
+               if ( wildCardMatch(*it, symbol) ) {
+                       if ( matchBecauseOfWildcard != NULL )
+                               *matchBecauseOfWildcard = true;
                        return true;
+               }
        }
        return false;
 }
 
+// Support "foo.o:_bar" to mean symbol _bar in file foo.o
+bool Options::SetWithWildcards::containsWithPrefix(const char* symbol, const char* file, bool& wildCardMatch) const
+{
+       wildCardMatch = false;
+       if ( contains(symbol, &wildCardMatch) )
+               return true;
+       if ( file == NULL )
+               return false;
+       const char* s = strrchr(file, '/');
+       if ( s != NULL )
+               file = s+1;
+       char buff[strlen(file)+strlen(symbol)+2];
+       sprintf(buff, "%s:%s", file, symbol);
+       return contains(buff, &wildCardMatch);
+}
+
 bool Options::SetWithWildcards::containsNonWildcard(const char* symbol) const
 {
        // look at hash table on non-wildcard symbols
@@ -1017,6 +1233,23 @@ bool Options::SetWithWildcards::containsNonWildcard(const char* symbol) const
 }
 
 
+std::vector<const char*> Options::exportsData() const
+{
+       return fExportSymbols.data();
+}
+
+
+std::vector<const char*> Options::SetWithWildcards::data() const
+{
+       std::vector<const char*> data;
+       for (NameSet::iterator it=regularBegin(); it != regularEnd(); ++it) {
+               data.push_back(*it);
+       }
+       for (std::vector<const char*>::const_iterator it=fWildCard.begin(); it != fWildCard.end(); ++it) {
+               data.push_back(*it);
+       }
+       return data;
+}
 
 bool Options::SetWithWildcards::inCharRange(const char*& p, unsigned char c) const
 {
@@ -1097,8 +1330,7 @@ void Options::loadExportFile(const char* fileOfExports, const char* option, SetW
        if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
                throwf("can't read %s file: %s", option, fileOfExports);
 
-       if ( this->dumpDependencyInfo() )
-               this->dumpDependency(Options::depMisc, fileOfExports);
+       this->addDependency(Options::depMisc, fileOfExports);
 
        ::close(fd);
 
@@ -1171,8 +1403,7 @@ void Options::parseAliasFile(const char* fileOfAliases)
                throwf("can't read alias file: %s", fileOfAliases);
        p[stat_buf.st_size] = '\n';
        ::close(fd);
-       if ( this->dumpDependencyInfo() )
-               this->dumpDependency(Options::depMisc, fileOfAliases);
+       this->addDependency(Options::depMisc, fileOfAliases);
 
        // parse into symbols and add to fAliases
        AliasPair pair;
@@ -1280,54 +1511,31 @@ Options::Treatment Options::parseTreatment(const char* treatment)
                return kInvalid;
 }
 
-void Options::setMacOSXVersionMin(const char* version)
-{
-       if ( version == NULL )
-               throw "-macosx_version_min argument missing";
-
-       if ( (strncmp(version, "10.", 3) == 0) && isdigit(version[3]) ) {
-               unsigned int minorVersion = 0;
-               for (int i=3; isdigit(version[i]); ++i) {
-                       minorVersion = minorVersion*10 + (version[i] - '0');
-               }
-               if ( minorVersion > 255 ) {
-                       warning("Mac OS X minor version > 255 in '%s'", version);
-                       minorVersion = 255;
+void Options::setVersionMin(const ld::Platform& platform, const char *version) {
+       auto checkAndParse = [&](const char *errorFlag) {
+               if ( version == NULL )
+                       throwf("%s missing version argument", errorFlag);
+               uint32_t value;
+               if ( !parsePackedVersion32(version, value) ) {
+                       throwf("%s value malformed: '%s'", errorFlag, version);
                }
-               fMacVersionMin = (ld::MacVersionMin)(0x000A0000 | (minorVersion << 8));
-       }
-       else {
-               warning("unknown option to -macosx_version_min, not 10.x");
-       }
-}
-
-void Options::setIOSVersionMin(const char* version)
-{
-       if ( version == NULL )
-               throw "-ios_version_min argument missing";
-       if ( ! isdigit(version[0]) )
-               throw "-ios_version_min argument is not a number";
-       if ( version[1] != '.' )
-               throw "-ios_version_min argument is missing period as second character";
-       if ( ! isdigit(version[2]) )
-               throw "-ios_version_min argument is not a number";
-
-       unsigned int majorVersion = version[0] - '0';
-       unsigned int minorVersion = version[2] - '0';
-       fIOSVersionMin = (ld::IOSVersionMin)((majorVersion << 16) | (minorVersion << 8));
-}
-
-bool Options::minOS(ld::MacVersionMin requiredMacMin, ld::IOSVersionMin requirediPhoneOSMin)
-{
-       if ( fMacVersionMin != ld::macVersionUnset ) {
-               return ( fMacVersionMin >= requiredMacMin );
-       }
-       else {
-               return ( fIOSVersionMin >= requirediPhoneOSMin);
-       }
+               fPlatforms.add({platform, value});
+       };
+
+       switch(platform) {
+               case ld::kPlatform_macOS:                               checkAndParse("-macosx_version_min"); break;
+               case ld::kPlatform_iOS:                                 checkAndParse("-ios_version_min"); break;
+               case ld::kPlatform_tvOS:                                checkAndParse("-tvos_version_min"); break;
+               case ld::kPlatform_watchOS:                     checkAndParse("-watchos_version_min"); break;
+               case ld::kPlatform_bridgeOS:                    checkAndParse("-bridgeos_version_min"); break;
+               case ld::kPlatform_iOSSimulator:                checkAndParse("-ios_simulator_version_min"); break;
+               case ld::kPlatform_tvOSSimulator:               checkAndParse("-tvos_simulator_version_min"); break;
+               case ld::kPlatform_watchOSSimulator:    checkAndParse("-watchos_simulator_version_min"); break;
+               case ld::kPlatform_unknown:                     throw "kPlatformUnknown is an invalid argument to setVersionMin()";
+               case ld::kPlatform_iOSMac:                              checkAndParse("-iosmac_version_min"); break;
+       };
 }
 
-
 void Options::setWeakReferenceMismatchTreatment(const char* treatment)
 {
        if ( treatment == NULL )
@@ -1565,6 +1773,19 @@ void Options::parseOrderFile(const char* path, bool cstring)
        // order files override auto-ordering
        fAutoOrderInitializers = false;
 
+       // <rdar://problem/24856050> ld64 should prefer OrderFiles from the SDK over the ones in /
+       for (const char* sdkPath : fSDKPaths) {
+               char fullPath[PATH_MAX];
+               strlcpy(fullPath, sdkPath, PATH_MAX);
+               strlcat(fullPath, "/", PATH_MAX);
+               strlcat(fullPath, path, PATH_MAX);
+               struct stat statBuffer;
+               if ( stat(fullPath, &statBuffer) == 0 ) {
+                       path = strdup(fullPath);
+                       break;
+               }
+       }
+
        // read in whole file
        int fd = ::open(path, O_RDONLY, 0);
        if ( fd == -1 )
@@ -1578,8 +1799,7 @@ void Options::parseOrderFile(const char* path, bool cstring)
                throwf("can't read order file: %s", path);
        ::close(fd);
        p[stat_buf.st_size] = '\n';
-       if ( this->dumpDependencyInfo() )
-               this->dumpDependency(Options::depMisc, path);
+       this->addDependency(Options::depMisc, path);
 
        // parse into vector of pairs
        char * const end = &p[stat_buf.st_size+1];
@@ -1631,6 +1851,12 @@ void Options::parseOrderFile(const char* path, bool cstring)
                                        else
                                                symbolStart = NULL;
                                }
+                               else if ( strncmp(symbolStart, "arm64:", 6) == 0 ) {
+                                       if ( fArchitecture == CPU_TYPE_ARM64 )
+                                               symbolStart = &symbolStart[6];
+                                       else
+                                               symbolStart = NULL;
+                               }
                                if ( symbolStart != NULL ) {
                                        char* objFileName = NULL;
                                        char* colon = strstr(symbolStart, ".o:");
@@ -1713,10 +1939,94 @@ void Options::addSection(const char* segment, const char* section, const char* p
        ::close(fd);
 
        // record section to create
-       ExtraSection info = { segment, section, path, (uint8_t*)p, stat_buf.st_size };
+       ExtraSection info = { segment, section, path, (uint8_t*)p, (uint64_t)stat_buf.st_size };
        fExtraSections.push_back(info);
 }
 
+void Options::addSectionRename(const char* srcSegment, const char* srcSection, const char* dstSegment, const char* dstSection)
+{
+       if ( strlen(srcSegment) > 16 )
+               throw "-rename_section segment name max 16 chars";
+       if ( strlen(srcSection) > 16 )
+               throw "-rename_section section name max 16 chars";
+       if ( strlen(dstSegment) > 16 )
+               throw "-rename_section segment name max 16 chars";
+       if ( strlen(dstSection) > 16 )
+               throw "-rename_section section name max 16 chars";
+
+       SectionRename info;
+       info.fromSegment = srcSegment;
+       info.fromSection = srcSection;
+       info.toSegment = dstSegment;
+       info.toSection = dstSection;
+
+       fSectionRenames.push_back(info);
+}
+
+
+void Options::addSegmentRename(const char* srcSegment, const char* dstSegment)
+{
+       if ( strlen(srcSegment) > 16 )
+               throw "-rename_segment segment name max 16 chars";
+       if ( strlen(dstSegment) > 16 )
+               throw "-rename_segment segment name max 16 chars";
+
+       SegmentRename info;
+       info.fromSegment = srcSegment;
+       info.toSegment = dstSegment;
+
+       fSegmentRenames.push_back(info);
+}
+
+
+
+void Options::addSymbolMove(const char* dstSegment, const char* symbolList,
+                                                       std::vector<SymbolsMove>& list, const char* optionName)
+{
+       if ( strlen(dstSegment) > 16 )
+               throwf("%s segment name max 16 chars", optionName);
+       
+       SymbolsMove tmp;
+       list.push_back(tmp);
+       SymbolsMove& info = list.back();
+       info.toSegment = dstSegment;
+       loadExportFile(symbolList, optionName, info.symbols);
+}
+               
+bool Options::moveRwSymbol(const char* symName, const char* filePath, const char*& seg, bool& wildCardMatch) const
+{
+       for (std::vector<SymbolsMove>::const_iterator it=fSymbolsMovesData.begin(); it != fSymbolsMovesData.end(); ++it) {
+               const SymbolsMove& info = *it;
+               if ( info.symbols.containsWithPrefix(symName, filePath, wildCardMatch)) {
+                       seg  = info.toSegment;
+                       return true;
+               }
+       }
+       return false;
+}
+
+bool Options::moveAXMethodList(const char* className) const
+{
+       for (const SymbolsMove& sm : fSymbolsMovesAXMethodLists) {
+               bool wildcard;
+               if ( sm.symbols.containsWithPrefix(className, NULL, wildcard) )
+                       return true;
+       }
+       return false;
+}
+
+bool Options::moveRoSymbol(const char* symName, const char* filePath, const char*& seg, bool& wildCardMatch) const
+{
+       for (std::vector<SymbolsMove>::const_iterator it=fSymbolsMovesCode.begin(); it != fSymbolsMovesCode.end(); ++it) {
+               const SymbolsMove& info = *it;
+               if ( info.symbols.containsWithPrefix(symName, filePath, wildCardMatch)) {
+                       seg  = info.toSegment;
+                       return true;
+               }
+       }
+       return false;
+}
+
 void Options::addSectionAlignment(const char* segment, const char* section, const char* alignmentStr)
 {
        if ( strlen(segment) > 16 )
@@ -1768,47 +2078,293 @@ void Options::warnObsolete(const char* arg)
 }
 
 
+void Options::cannotBeUsedWithBitcode(const char* arg)
+{
+       if ( fBundleBitcode )
+               throwf("%s and -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES) cannot be used together", arg);
+}
 
+std::string Options::getVersionString32(uint32_t ver) const
+{
+       if (ver == 0 || ver >= 0x10000000)
+               return "0.0.0";
+
+       unsigned microVersion = ver & 0xFF;
+       unsigned minorVersion = (ver >> 8) & 0xFF;
+       unsigned majorVersion = (ver >> 16) & 0xFF;
+       std::stringstream versionString;
+       versionString << majorVersion << "." << minorVersion << "." << microVersion;
+       return versionString.str();
+}
 
-//
-// Process all command line arguments.
-//
-// The only error checking done here is that each option is valid and if it has arguments
-// that they too are valid.
-//
-// The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
-// whichever was last on the command line is used.
-//
-// Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
-//
-void Options::parse(int argc, const char* argv[])
+std::string Options::getVersionString64(uint64_t ver) const
 {
-    // Store the original args in the link snapshot.
-    fLinkSnapshot.recordRawArgs(argc, argv);
-    
-       // pass one builds search list from -L and -F options
-       this->buildSearchPaths(argc, argv);
+       uint64_t a = (ver >> 40) & 0xFFFFFF;
+       uint64_t b = (ver >> 30) & 0x3FF;
+       uint64_t c = (ver >> 20) & 0x3FF;
+       uint64_t d = (ver >> 10) & 0x3FF;
+       uint64_t e = ver & 0x3FF;
+       std::stringstream versionString;
+       versionString << a << "." << b << "." << c << "." << d << "." << e;
+       return versionString.str();
+}
 
-       // reduce re-allocations
-       fInputFiles.reserve(32);
+// Convert X.Y[.Z] to 32-bit value xxxxyyzz
+bool Options::parsePackedVersion32(const std::string& versionStr, uint32_t &result)
+{
+       result = 0;
 
-       // pass two parse all other options
-       for(int i=1; i < argc; ++i) {
-               const char* arg = argv[i];
+       if ( versionStr.empty() )
+               return false;
 
-               if ( arg[0] == '-' ) {
-            // by default, copy one arg to the snapshot link command, and do no file copying
-            int snapshotArgIndex = i;
-            int snapshotArgCount = -1; // -1 means compute count based on change in index
-            int snapshotFileArgIndex = -1; // -1 means no data file parameter to arg
+       size_t pos = versionStr.find('.');
+       if ( pos == std::string::npos )
+               return false;
 
-                       // Since we don't care about the files passed, just the option names, we do this here.
-                       if (fPrintOptions)
-                               fprintf (stderr, "[Logging ld64 options]\t%s\n", arg);
+       std::string majorStr = versionStr.substr(0, pos);
+       std::string rest = versionStr.substr(pos+1);
 
-                       if ( (arg[1] == 'L') || (arg[1] == 'F') ) {
-                snapshotArgCount = 0; // stripped out of link snapshot
-                               if (arg[2] == '\0')
+       try {
+               size_t majorEnd;
+               int majorValue = std::stoi(majorStr, &majorEnd);
+               if ( majorEnd != majorStr.size() )
+                       return false;
+               if ( majorValue < 0 )
+                       return false;
+               if ( majorValue > 65535 )
+                       return false;
+
+               std::string minorStr;
+               std::string microStr;
+               pos = rest.find('.');
+               if ( pos == std::string::npos ) {
+                       minorStr = rest;
+               }
+               else {
+                       minorStr = rest.substr(0, pos);
+                       microStr = rest.substr(pos+1);
+               }
+
+               size_t minorEnd;
+               int minorValue = std::stoi(minorStr, &minorEnd);
+               if ( minorEnd != minorStr.size() )
+                       return false;
+               if ( minorValue < 0 )
+                       return false;
+               if ( minorValue > 255 )
+                       return false;
+
+               int microValue = 0;
+               if ( !microStr.empty() ) {
+                       size_t microEnd;
+                       microValue = std::stoi(microStr, &microEnd);
+                       if ( microEnd != microStr.size() )
+                               return false;
+                       if ( microValue < 0 )
+                               return false;
+                       if ( microValue > 255 )
+                               return false;
+               }
+
+               result = (uint32_t)((majorValue << 16) | (minorValue << 8) | microValue);
+
+               return true;
+       }
+       catch (...) {
+               // std::stoi() throws exception on malformed input
+               return false;
+       }
+}
+
+std::string Options::getSDKVersionStr() const
+{
+       return getVersionString32(fSDKVersion);
+}
+
+std::vector<std::string> Options::writeBitcodeLinkOptions() const
+{
+       __block std::vector<std::string> linkCommand;
+       switch ( fOutputKind ) {
+               case Options::kDynamicLibrary:
+                       linkCommand.push_back("-dylib");
+                       linkCommand.push_back("-compatibility_version");
+                       if ( fDylibCompatVersion != 0 ) {
+                               linkCommand.push_back(getVersionString32(fDylibCompatVersion));
+                       } else {
+                               linkCommand.push_back(getVersionString32(currentVersion32()));
+                       }
+                       if ( fDylibCurrentVersion != 0 ) {
+                               linkCommand.push_back("-current_version");
+                               linkCommand.push_back(getVersionString64(fDylibCurrentVersion));
+                       }
+                       linkCommand.push_back("-install_name");
+                       linkCommand.push_back(installPath());
+                       break;
+               case Options::kDynamicExecutable:
+                       linkCommand.push_back("-execute");
+                       break;
+               case Options::kObjectFile:
+                       linkCommand.push_back("-r");
+                       break;
+               default:
+                       throwf("could not write bitcode options file output kind\n");
+       }
+
+       if (!fImplicitlyLinkPublicDylibs)
+               linkCommand.push_back("-no_implicit_dylibs");
+
+       // Add deployment target.
+       // Platform is allowed to be unknown for "ld -r".
+
+       platforms().forEach(^(ld::Platform platform, uint32_t version, bool &stop) {
+               switch (platform) {
+                       case ld::kPlatform_macOS:
+                               linkCommand.push_back("-macosx_version_min");
+                               linkCommand.push_back(getVersionString32(version));
+                               break;
+                       case ld::kPlatform_iOS:
+                               linkCommand.push_back("-ios_version_min");
+                               linkCommand.push_back(getVersionString32(version));
+                               break;
+                       case ld::kPlatform_iOSSimulator:
+                               linkCommand.push_back("-ios_simulator_version_min");
+                               linkCommand.push_back(getVersionString32(version));
+                               break;
+                       case ld::kPlatform_watchOS:
+                               linkCommand.push_back("-watchos_version_min");
+                               linkCommand.push_back(getVersionString32(version));
+                               break;
+                       case ld::kPlatform_watchOSSimulator:
+                               linkCommand.push_back("-watchos_simulator_version_min");
+                               linkCommand.push_back(getVersionString32(version));
+                               break;
+                       case ld::kPlatform_tvOS:
+                               linkCommand.push_back("-tvos_version_min");
+                               linkCommand.push_back(getVersionString32(version));
+                               break;
+                       case ld::kPlatform_tvOSSimulator:
+                               linkCommand.push_back("-tvos_simulator_version_min");
+                               linkCommand.push_back(getVersionString32(version));
+                               break;
+                       case ld::kPlatform_bridgeOS:
+                               linkCommand.push_back("-bridgeos_version_min");
+                               linkCommand.push_back(getVersionString32(version));
+                               break;
+                       case ld::kPlatform_iOSMac:
+                               linkCommand.push_back("-iosmac_version_min");
+                               linkCommand.push_back(getVersionString32(version));
+                               break;
+                       case ld::kPlatform_unknown:
+                               if ( fOutputKind != Options::kObjectFile ) {
+                                       throwf("platform is unknown for final bitcode bundle,"
+                                                  "deployment target and min version is required for -bitcode_bundle");
+                               }
+                               break;
+               }
+       });
+
+
+       // entry name
+       if ( fEntryName ) {
+               linkCommand.push_back("-e");
+               linkCommand.push_back(fEntryName);
+       }
+
+       // Write rpaths
+       if (!fRPaths.empty()) {
+               for (std::vector<const char*>::const_iterator it=fRPaths.begin(); it != fRPaths.end(); ++it) {
+                       linkCommand.push_back("-rpath");
+                       linkCommand.push_back(*it);
+               }
+       }
+
+       // Other bitcode compatiable options
+       if ( fObjCABIVersion1Override ) {
+               linkCommand.push_back("-objc_abi_version");
+               linkCommand.push_back("1");
+       } else if ( fObjCABIVersion2Override ) {
+               linkCommand.push_back("-objc_abi_version");
+               linkCommand.push_back("2");
+       }
+       if ( fExecutablePath ) {
+               linkCommand.push_back("-executable_path");
+               linkCommand.push_back(fExecutablePath);
+       }
+       if ( fDeadStrip )
+               linkCommand.push_back("-dead_strip");
+       if ( fExportDynamic )
+               linkCommand.push_back("-export_dynamic");
+       if ( fMarkAppExtensionSafe && fCheckAppExtensionSafe )
+               linkCommand.push_back("-application_extension");
+
+       if ( fSourceVersionLoadCommandForceOn )
+               linkCommand.push_back("-add_source_version");
+       if ( fSourceVersion != 0 ) {
+               linkCommand.push_back("-source_version");
+               linkCommand.push_back(getVersionString64(fSourceVersion));
+       }
+
+       // linker flag added by swift driver
+       // rdar://problem/20108072
+       if ( !fObjcCategoryMerging )
+               linkCommand.push_back("-no_objc_category_merging");
+
+       return linkCommand;
+}
+
+const char* Options::checkForNullArgument(const char* argument_name, const char* arg) const
+{
+       if ( arg == NULL )
+               throwf("missing argument for %s", argument_name);
+       return arg;
+}
+
+const char* Options::checkForNullVersionArgument(const char* argument_name, const char* arg) const
+{
+       if ( arg == NULL )
+               throwf("%s missing version argument", argument_name);
+       return arg;
+}
+
+//
+// Process all command line arguments.
+//
+// The only error checking done here is that each option is valid and if it has arguments
+// that they too are valid.
+//
+// The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
+// whichever was last on the command line is used.
+//
+// Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
+//
+void Options::parse(int argc, const char* argv[])
+{
+    // Store the original args in the link snapshot.
+    fLinkSnapshot.recordRawArgs(argc, argv);
+    
+       // pass one builds search list from -L and -F options
+       this->buildSearchPaths(argc, argv);
+
+       // reduce re-allocations
+       fInputFiles.reserve(32);
+
+       // pass two parse all other options
+       for(int i=1; i < argc; ++i) {
+               const char* arg = argv[i];
+
+               if ( arg[0] == '-' ) {
+            // by default, copy one arg to the snapshot link command, and do no file copying
+            int snapshotArgIndex = i;
+            int snapshotArgCount = -1; // -1 means compute count based on change in index
+            int snapshotFileArgIndex = -1; // -1 means no data file parameter to arg
+
+                       // Since we don't care about the files passed, just the option names, we do this here.
+                       if (fPrintOptions)
+                               fprintf (stderr, "[Logging ld64 options]\t%s\n", arg);
+
+                       if ( (arg[1] == 'L') || (arg[1] == 'F') ) {
+                snapshotArgCount = 0; // stripped out of link snapshot
+                               if (arg[2] == '\0')
                                        ++i;
                                // previously handled by buildSearchPaths()
                        }
@@ -1820,7 +2376,9 @@ void Options::parse(int argc, const char* argv[])
                                exit (0);
                        }
                        else if ( strcmp(arg, "-arch") == 0 ) {
-                               parseArch(argv[++i]);
+                               const char* arch = argv[++i];
+                               parseArch(arch);
+                               fLinkSnapshot.recordArch(arch);
                        }
                        else if ( strcmp(arg, "-dynamic") == 0 ) {
                                // default
@@ -1830,15 +2388,18 @@ void Options::parse(int argc, const char* argv[])
                                if ( (fOutputKind != kObjectFile) && (fOutputKind != kKextBundle) ) {
                                        fOutputKind = kStaticExecutable;
                                }
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-dylib") == 0 ) {
                                fOutputKind = kDynamicLibrary;
                        }
                        else if ( strcmp(arg, "-bundle") == 0 ) {
                                fOutputKind = kDynamicBundle;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-dylinker") == 0 ) {
                                fOutputKind = kDyld;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-execute") == 0 ) {
                                if ( fOutputKind != kStaticExecutable )
@@ -1846,17 +2407,28 @@ void Options::parse(int argc, const char* argv[])
                        }
                        else if ( strcmp(arg, "-preload") == 0 ) {
                                fOutputKind = kPreload;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-r") == 0 ) {
                                fOutputKind = kObjectFile;
                        }
                        else if ( strcmp(arg, "-kext") == 0 ) {
                                fOutputKind = kKextBundle;
+                               cannotBeUsedWithBitcode(arg);
+                       }
+                       else if ( strcmp(arg, "-kext_objects_dir") == 0 ) {
+                               fKextObjectsDirPath = argv[++i];
+                               if ( fKextObjectsDirPath == NULL )
+                                       throw "missing argument to -kext_objects_dir";
+                               fKextObjectsEnable = 1;
+                       }
+                       else if ( strcmp(arg, "-no_kext_objects") == 0 ) {
+                               fKextObjectsEnable = 0;
                        }
                        else if ( strcmp(arg, "-o") == 0 ) {
-                snapshotArgCount = 0;
-                               fOutputFile = argv[++i];
-                fLinkSnapshot.setSnapshotName(fOutputFile);
+                               snapshotArgCount = 0;
+                               fOutputFile = checkForNullArgument(arg, argv[++i]);
+                               fLinkSnapshot.setOutputPath(fOutputFile);
                        }
                        else if ( strncmp(arg, "-lazy-l", 7) == 0 ) {
                 snapshotArgCount = 0;
@@ -1865,6 +2437,7 @@ void Options::parse(int argc, const char* argv[])
                                info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
                                addLibrary(info);
                                fUsingLazyDylibLinking = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-lto_library") == 0 ) {
                 snapshotFileArgIndex = 1;
@@ -1872,6 +2445,41 @@ void Options::parse(int argc, const char* argv[])
                                if ( fOverridePathlibLTO == NULL )
                                        throw "missing argument to -lto_library";
                        }
+                       else if ( strcmp(arg, "-cache_path_lto") == 0 ) {
+                               fLtoCachePath = argv[++i];
+                               if ( fLtoCachePath == NULL )
+                                       throw "missing argument to -cache_path_lto";
+                       }
+                       else if ( strcmp(arg, "-prune_interval_lto") == 0 ) {
+                               const char* value = argv[++i];
+                               if ( value == NULL )
+                                       throw "missing argument to -prune_interval_lto";
+                               char* endptr;
+                               fLtoPruneIntervalOverwrite = true;
+                               fLtoPruneInterval = strtoul(value, &endptr, 10);
+                               if ( *endptr != '\0')
+                                       throw "invalid argument for -prune_interval_lto";
+                       }
+                       else if ( strcmp(arg, "-prune_after_lto") == 0 ) {
+                               const char* value = argv[++i];
+                               if ( value == NULL )
+                                       throw "missing argument to -prune_after_lto";
+                               char* endptr;
+                               fLtoPruneAfter = strtoul(value, &endptr, 10);
+                               if ( *endptr != '\0')
+                                       throw "invalid argument for -prune_after_lto";
+                       }
+                       else if ( strcmp(arg, "-max_relative_cache_size_lto") == 0 ) {
+                               const char* value = argv[++i];
+                               if ( value == NULL )
+                                       throw "missing argument to -max_relative_cache_size_lto";
+                               char* endptr;
+                               fLtoMaxCacheSize = strtoul(value, &endptr, 10);
+                               if ( *endptr != '\0')
+                                       throw "invalid argument for -max_relative_cache_size_lto";
+                               if (fLtoMaxCacheSize > 100)
+                                       throw "Expect a value between 0 and 100 for -max_relative_cache_size_lto";
+                       }
                        else if ( (arg[1] == 'l') && (strncmp(arg,"-lazy_",6) !=0) ) {
                 snapshotArgCount = 0;
                                FileInfo info = findLibrary(&arg[2]);
@@ -1891,18 +2499,21 @@ void Options::parse(int argc, const char* argv[])
                        // Avoid lazy binding.
                        else if ( strcmp(arg, "-bind_at_load") == 0 ) {
                                fBindAtLoad = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-twolevel_namespace") == 0 ) {
                                fNameSpace = kTwoLevelNameSpace;
                        }
                        else if ( strcmp(arg, "-flat_namespace") == 0 ) {
                                fNameSpace = kFlatNameSpace;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        // Also sets a bit to ensure dyld causes everything
                        // in the namespace to be flat.
                        // ??? Deprecate
                        else if ( strcmp(arg, "-force_flat_namespace") == 0 ) {
                                fNameSpace = kForceFlatNameSpace;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        // Similar to --whole-archive.
                        else if ( strcmp(arg, "-all_load") == 0 ) {
@@ -1917,7 +2528,8 @@ void Options::parse(int argc, const char* argv[])
                        }
                        // Similar to -all_load, but for the following archive only.
                        else if ( strcmp(arg, "-force_load") == 0 ) {
-                               FileInfo info = findFile(argv[++i]);
+                               const char* path = checkForNullArgument(arg, argv[++i]);
+                               FileInfo info = findFile(path);
                                info.options.fForceLoad = true;
                                info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
                                addLibrary(info);
@@ -1943,6 +2555,7 @@ void Options::parse(int argc, const char* argv[])
                 snapshotFileArgIndex = 3;
                                parseSectionOrderFile(argv[i+1], argv[i+2], argv[i+3]);
                                i += 3;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-order_file") == 0 ) {
                 snapshotFileArgIndex = 1;
@@ -1950,6 +2563,7 @@ void Options::parse(int argc, const char* argv[])
                        }
                        else if ( strcmp(arg, "-order_file_statistics") == 0 ) {
                                fPrintOrderFileStatistics = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        // ??? Deprecate segcreate.
                        // -sectcreate puts whole files into a section in the output.
@@ -1979,6 +2593,7 @@ void Options::parse(int argc, const char* argv[])
                                        warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment);
                                        fBaseAddress = temp;
                                }
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-e") == 0 ) {
                                fEntryName = argv[++i];
@@ -1993,7 +2608,8 @@ void Options::parse(int argc, const char* argv[])
                                 loadFileList(path, baseOrdinal);
                        }
                        else if ( strcmp(arg, "-keep_private_externs") == 0 ) {
-                                fKeepPrivateExterns = true;
+                               cannotBeUsedWithBitcode(arg);
+                               fKeepPrivateExterns = true;
                        }
                        else if ( strcmp(arg, "-final_output") == 0 ) {
                                fFinalName = argv[++i];
@@ -2010,11 +2626,13 @@ void Options::parse(int argc, const char* argv[])
                                                // do nothing, -interposable_list overrides -interposable"
                                                break;
                                }
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-interposable_list") == 0 ) {
                 snapshotFileArgIndex = 1;
                                fInterposeMode = kInterposeSome;
                                loadExportFile(argv[++i], "-interposable_list", fInterposeList);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        // Default for -interposable/-multi_module/-single_module.
                        else if ( strcmp(arg, "-single_module") == 0 ) {
@@ -2038,13 +2656,15 @@ void Options::parse(int argc, const char* argv[])
                                if ( fExportMode == kDontExportSome )
                                        throw "can't use -exported_symbol and -unexported_symbols";
                                fExportMode = kExportSome;
-                               fExportSymbols.insert(argv[++i]);
+                               const char* symbol = checkForNullArgument(arg, argv[++i]);
+                               fExportSymbols.insert(symbol);
                        }
                        else if ( strcmp(arg, "-unexported_symbol") == 0 ) {
                                if ( fExportMode == kExportSome )
                                        throw "can't use -unexported_symbol and -exported_symbol";
                                fExportMode = kDontExportSome;
-                               fDontExportSymbols.insert(argv[++i]);
+                               const char* symbol = checkForNullArgument(arg, argv[++i]);
+                               fDontExportSymbols.insert(symbol);
                        }
                        else if ( strcmp(arg, "-non_global_symbols_no_strip_list") == 0 ) {
                 snapshotFileArgIndex = 1;
@@ -2052,6 +2672,7 @@ void Options::parse(int argc, const char* argv[])
                                        throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
                                fLocalSymbolHandling = kLocalSymbolsSelectiveInclude;
                                loadExportFile(argv[++i], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-non_global_symbols_strip_list") == 0 ) {
                 snapshotFileArgIndex = 1;
@@ -2059,6 +2680,7 @@ void Options::parse(int argc, const char* argv[])
                                        throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
                                fLocalSymbolHandling = kLocalSymbolsSelectiveExclude;
                                loadExportFile(argv[++i], "-non_global_symbols_strip_list", fLocalSymbolsExcluded);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        // ??? Deprecate
                        else if ( strcmp(arg, "-no_arch_warnings") == 0 ) {
@@ -2067,24 +2689,29 @@ void Options::parse(int argc, const char* argv[])
                        else if ( strcmp(arg, "-force_cpusubtype_ALL") == 0 ) {
                                fForceSubtypeAll = true;
                                fAllowCpuSubtypeMismatches = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        // Similar to -weak-l but uses the absolute path name to the library.
                        else if ( strcmp(arg, "-weak_library") == 0 ) {
                 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
                 snapshotArgCount = 0;
-                               FileInfo info = findFile(argv[++i]);
+                               const char* path = checkForNullArgument(arg, argv[++i]);
+                               FileInfo info = findFile(path);
                                info.options.fWeakImport = true;
                                info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
                                addLibrary(info);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-lazy_library") == 0 ) {
                 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
                 snapshotArgCount = 0;
-                               FileInfo info = findFile(argv[++i]);
+                               const char* path = checkForNullArgument(arg, argv[++i]);
+                               FileInfo info = findFile(path);
                                info.options.fLazyLoad = true;
                                info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
                                addLibrary(info);
                                fUsingLazyDylibLinking = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-framework") == 0 ) {
                 snapshotArgCount = 0;
@@ -2108,6 +2735,7 @@ void Options::parse(int argc, const char* argv[])
                                info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
                                addLibrary(info);
                                fUsingLazyDylibLinking = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-search_paths_first") == 0 ) {
                                // previously handled by buildSearchPaths()
@@ -2117,6 +2745,7 @@ void Options::parse(int argc, const char* argv[])
                        }
                        else if ( strcmp(arg, "-undefined") == 0 ) {
                 setUndefinedTreatment(argv[++i]);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        // Debugging output flag.
                        else if ( strcmp(arg, "-arch_multiple") == 0 ) {
@@ -2134,10 +2763,12 @@ void Options::parse(int argc, const char* argv[])
                                        case kWarning:
                                                fWarnTextRelocs = true;
                                                fAllowTextRelocs = true;
+                                               cannotBeUsedWithBitcode(arg);
                                                break;
                                        case kSuppress:
                                                fWarnTextRelocs = false;
                                                fAllowTextRelocs = true;
+                                               cannotBeUsedWithBitcode(arg);
                                                break;
                                        case kError:
                                                fWarnTextRelocs = false;
@@ -2159,11 +2790,11 @@ void Options::parse(int argc, const char* argv[])
                        // are prebound.  This can then be fixed up by update_prebinding
                        // later.  Prebinding is less useful on 10.4 and greater.
                        else if ( strcmp(arg, "-prebind") == 0 ) {
-                               fPrebind = true;
+                               warnObsolete(arg);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-noprebind") == 0 ) {
                                warnObsolete(arg);
-                               fPrebind = false;
                        }
                        else if ( strcmp(arg, "-prebind_allow_overlap") == 0 ) {
                                warnObsolete(arg);
@@ -2183,6 +2814,7 @@ void Options::parse(int argc, const char* argv[])
                 // ignore for snapshot because a stub dylib will be created in the snapshot
                  snapshotArgCount = 0;
                                 addDylibOverride(argv[++i]);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        // What to expand @executable_path to if found in dependent dylibs
                        else if ( strcmp(arg, "-executable_path") == 0 ) {
@@ -2213,6 +2845,7 @@ void Options::parse(int argc, const char* argv[])
                                        warning("alignment for -segalign %s is not a power of two, using 0x%X", size, p2aligned);
                                        fSegmentAlignment = p2aligned;
                                }
+                               cannotBeUsedWithBitcode(arg);
                        }
                        // Puts a specified segment at a particular address that must
                        // be a multiple of the segment alignment.
@@ -2226,23 +2859,28 @@ void Options::parse(int argc, const char* argv[])
                                if ( seg.address != temp )
                                        warning("-segaddr %s not %lld byte aligned", seg.name, fSegmentAlignment);
                                fCustomSegmentAddresses.push_back(seg);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        // ??? Deprecate when we deprecate split-seg.
                        else if ( strcmp(arg, "-segs_read_only_addr") == 0 ) {
-                               fBaseAddress = parseAddress(argv[++i]);
+                               warnObsolete(arg);
+                               ++i;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        // ??? Deprecate when we deprecate split-seg.
                        else if ( strcmp(arg, "-segs_read_write_addr") == 0 ) {
-                               fBaseWritableAddress = parseAddress(argv[++i]);
-                               fSplitSegs = true;
+                               warnObsolete(arg);
+                               ++i;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        // ??? Deprecate when we get rid of basing at build time.
                        else if ( strcmp(arg, "-seg_addr_table") == 0 ) {
+                               warnObsolete(arg);
                 snapshotFileArgIndex = 1;
                                const char* name = argv[++i];
                                if ( name == NULL )
                                        throw "-seg_addr_table missing argument";
-                               fSegAddrTablePath = name;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-seg_addr_table_filename") == 0 ) {
                                warnObsolete(arg);
@@ -2255,7 +2893,11 @@ void Options::parse(int argc, const char* argv[])
                                        throw "-segprot missing segName max-prot init-prot";
                                seg.max = parseProtection(argv[++i]);
                                seg.init = parseProtection(argv[++i]);
-                               fCustomSegmentProtections.push_back(seg);
+                               if ( strcmp(seg.name, "__LINKEDIT") == 0 )
+                                       warning("-segprot cannot be used to modify __LINKEDIT protections");
+                               else
+                                       fCustomSegmentProtections.push_back(seg);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-pagezero_size") == 0 ) {
                                 const char* size = argv[++i];
@@ -2266,33 +2908,35 @@ void Options::parse(int argc, const char* argv[])
                                if ( (fZeroPageSize != temp)  )
                                        warning("-pagezero_size not page aligned, rounding down");
                                 fZeroPageSize = temp;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-stack_addr") == 0 ) {
                                 const char* address = argv[++i];
                                 if ( address == NULL )
                                        throw "-stack_addr missing <address>";
                                fStackAddr = parseAddress(address);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-stack_size") == 0 ) {
                                 const char* size = argv[++i];
                                 if ( size == NULL )
                                        throw "-stack_size missing <address>";
                                fStackSize = parseAddress(size);
-                               uint64_t temp = fStackSize & (-4096); // page align
-                               if ( (fStackSize != temp)  )
-                                       warning("-stack_size not page aligned, rounding down");
                        }
                        else if ( strcmp(arg, "-allow_stack_execute") == 0 ) {
                                fExecutableStack = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-allow_heap_execute") == 0 ) {
                                fDisableNonExecutableHeap = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-sectalign") == 0 ) {
                                 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
                                        throw "-sectalign missing <segment> <section> <file-path>";
                                addSectionAlignment(argv[i+1], argv[i+2], argv[i+3]);
                                i += 3;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-sectorder_detail") == 0 ) {
                                warnObsolete(arg);
@@ -2319,7 +2963,7 @@ void Options::parse(int argc, const char* argv[])
                        }
                        // Use this flag to set default behavior for deployement targets.
                        else if ( strcmp(arg, "-macosx_version_min") == 0 ) {
-                               const char* macVers = argv[++i];
+                               const char* macVers = checkForNullVersionArgument(arg, argv[++i]);
                                const char* envMacVers = getenv("MACOSX_DEPLOYMENT_TARGET");
                                const char* enviPhoneVers = getenv("IPHONEOS_DEPLOYMENT_TARGET");
                                if ( (envMacVers != NULL) && (enviPhoneVers != NULL) ) {
@@ -2329,24 +2973,49 @@ void Options::parse(int argc, const char* argv[])
                                                const char* sysrootPath = fSDKPaths.back();
                                                const char* lastSlash = strrchr(sysrootPath, '/');
                                                if ( strstr(lastSlash, "Simulator") != NULL ) 
-                                                       setIOSVersionMin(enviPhoneVers);
+                                                       setVersionMin(ld::kPlatform_iOS, enviPhoneVers);
                                                else
-                                                       setMacOSXVersionMin(macVers);
+                                                       setVersionMin(ld::kPlatform_macOS, macVers);
                                        }
                                        else {
-                                               setMacOSXVersionMin(macVers);
+                                               setVersionMin(ld::kPlatform_macOS, macVers);
                                        }
                                }
                                else {
-                                       setMacOSXVersionMin(macVers);
+                                       setVersionMin(ld::kPlatform_macOS, macVers);
                                }
                        }
                        else if ( (strcmp(arg, "-ios_version_min") == 0) || (strcmp(arg, "-iphoneos_version_min") == 0) ) {
-                               setIOSVersionMin(argv[++i]); 
+                               const char* vers = checkForNullVersionArgument(arg, argv[++i]);
+                               setVersionMin(ld::kPlatform_iOS, vers);
                        }
                        else if ( strcmp(arg, "-ios_simulator_version_min") == 0 ) {
-                               setIOSVersionMin(argv[++i]);
-                               fTargetIOSSimulator = true;
+                               const char* vers = checkForNullVersionArgument(arg, argv[++i]);
+                               setVersionMin(ld::kPlatform_iOSSimulator, vers);
+                       }
+                       else if ( strcmp(arg, "-watchos_version_min") == 0 ) {
+                               const char* vers = checkForNullVersionArgument(arg, argv[++i]);
+                               setVersionMin(ld::kPlatform_watchOS, vers);
+                       }
+                       else if ( strcmp(arg, "-watchos_simulator_version_min") == 0 ) {
+                               const char* vers = checkForNullVersionArgument(arg, argv[++i]);
+                               setVersionMin(ld::kPlatform_watchOSSimulator, vers);
+                       }
+                       else if ( strcmp(arg, "-tvos_version_min") == 0 ) {
+                               const char* vers = checkForNullVersionArgument(arg, argv[++i]);
+                               setVersionMin(ld::kPlatform_tvOS, vers);
+                       }
+                       else if ( strcmp(arg, "-tvos_simulator_version_min") == 0 ) {
+                               const char* vers = checkForNullVersionArgument(arg, argv[++i]);
+                               setVersionMin(ld::kPlatform_tvOSSimulator, vers);
+                       }
+                       else if ( strcmp(arg, "-bridgeos_version_min") == 0 ) {
+                               const char* vers = checkForNullVersionArgument(arg, argv[++i]);
+                               setVersionMin(ld::kPlatform_bridgeOS, vers);
+                       }
+                       else if ( strcmp(arg, "-iosmac_version_min") == 0 ) {
+                               const char* vers = checkForNullVersionArgument(arg, argv[++i]);
+                               setVersionMin(ld::kPlatform_iOSMac, vers);
                        }
                        else if ( strcmp(arg, "-multiply_defined") == 0 ) {
                                //warnObsolete(arg);
@@ -2388,12 +3057,14 @@ void Options::parse(int argc, const char* argv[])
                                if ( name == NULL )
                                        throw "-u missing argument";
                                fInitialUndefines.push_back(name);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-U") == 0 ) {
                                const char* name = argv[++i];
                                if ( name == NULL )
                                        throw "-U missing argument";
                                fAllowedUndefined.insert(name);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-s") == 0 ) {
                                warnObsolete(arg);
@@ -2446,9 +3117,15 @@ void Options::parse(int argc, const char* argv[])
                                if ( size == NULL )
                                        throw "-headerpad missing argument";
                                 fMinimumHeaderPad = parseAddress(size);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-headerpad_max_install_names") == 0 ) {
-                               fMaxMinimumHeaderPad = true;
+                               // ignore -headerpad_max_install_names when compiling with bitcode
+                               // rdar://problem/20748962
+                               if ( fBundleBitcode )
+                                       warning("-headerpad_max_install_names is ignored when used with -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES)");
+                               else
+                                       fMaxMinimumHeaderPad = true;
                        }
                        else if ( strcmp(arg, "-t") == 0 ) {
                                fLogAllFiles = true;
@@ -2465,6 +3142,7 @@ void Options::parse(int argc, const char* argv[])
                                if ( name == NULL )
                                        throw "-umbrella missing argument";
                                fUmbrellaName = name;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-allowable_client") == 0 ) {
                                const char* name = argv[++i];
@@ -2473,6 +3151,7 @@ void Options::parse(int argc, const char* argv[])
                                        throw "-allowable_client missing argument";
 
                                fAllowableClients.push_back(name);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-client_name") == 0 ) {
                                const char* name = argv[++i];
@@ -2481,30 +3160,35 @@ void Options::parse(int argc, const char* argv[])
                                        throw "-client_name missing argument";
 
                                fClientName = name;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-sub_umbrella") == 0 ) {
                                const char* name = argv[++i];
                                if ( name == NULL )
                                        throw "-sub_umbrella missing argument";
                                 fSubUmbellas.push_back(name);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-sub_library") == 0 ) {
                                const char* name = argv[++i];
                                if ( name == NULL )
                                        throw "-sub_library missing argument";
                                 fSubLibraries.push_back(name);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-init") == 0 ) {
                                const char* name = argv[++i];
                                if ( name == NULL )
                                        throw "-init missing argument";
                                fInitFunctionName = name;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-dot") == 0 ) {
                                const char* name = argv[++i];
                                if ( name == NULL )
                                        throw "-dot missing argument";
                                fDotOutputFile = name;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-warn_commons") == 0 ) {
                                fWarnCommons = true;
@@ -2538,11 +3222,17 @@ void Options::parse(int argc, const char* argv[])
                                ++i;
                                // previously handled by buildSearchPaths()
                        }
+                       else if ( strcmp(arg, "-bitcode_bundle") == 0 ) {
+                               snapshotArgCount = 0;
+                               // previously handled by buildSearchPaths()
+                       }
                        else if ( strcmp(arg, "-no_uuid") == 0 ) {
                                fUUIDMode = kUUIDNone;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-random_uuid") == 0 ) {
                                fUUIDMode = kUUIDRandom;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-dtrace") == 0 ) {
                 snapshotFileArgIndex = 1;
@@ -2550,6 +3240,7 @@ void Options::parse(int argc, const char* argv[])
                                if ( name == NULL )
                                        throw "-dtrace missing argument";
                                fDtraceScriptName = name;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-root_safe") == 0 ) {
                                fRootSafe = true;
@@ -2559,37 +3250,65 @@ void Options::parse(int argc, const char* argv[])
                        }
                        else if ( strcmp(arg, "-alias") == 0 ) {
                                Options::AliasPair pair;
-                               pair.realName = argv[++i];
-                               if ( pair.realName == NULL )
-                                       throw "missing argument to -alias";
-                               pair.alias = argv[++i];
-                               if ( pair.alias == NULL )
-                                       throw "missing argument to -alias";
+                               pair.realName = checkForNullArgument(arg, argv[++i]);
+                               pair.alias = checkForNullArgument(arg, argv[++i]);
                                fAliases.push_back(pair);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-alias_list") == 0 ) {
                 snapshotFileArgIndex = 1;
                                parseAliasFile(argv[++i]);
-                       }
-                       // put this last so that it does not interfer with other options starting with 'i'
-                       else if ( strncmp(arg, "-i", 2) == 0 ) {
-                               const char* colon = strchr(arg, ':');
-                               if ( colon == NULL )
-                                       throwf("unknown option: %s", arg);
-                               Options::AliasPair pair;
-                               char* temp = new char[colon-arg];
-                               strlcpy(temp, &arg[2], colon-arg-1);
-                               pair.realName = &colon[1];
-                               pair.alias = temp;
-                               fAliases.push_back(pair);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-save-temps") == 0 ) {
                                fSaveTempFiles = true;
                        }
+                       else if ( strcmp(arg, "-bitcode_hide_symbols") == 0 ) {
+                               fHideSymbols = true;
+                       }
+                       else if ( strcmp(arg, "-bitcode_verify") == 0 ) {
+                               fVerifyBitcode = true;
+                       }
+                       else if ( strcmp(arg, "-bitcode_symbol_map") == 0) {
+                               fReverseMapPath = checkForNullArgument(arg, argv[++i]);
+                               struct stat statbuf;
+                               int ret = ::stat(fReverseMapPath, &statbuf);
+                               if ( ret == 0 && S_ISDIR(statbuf.st_mode)) {
+                                       char tempPath[PATH_MAX];
+                                       sprintf(tempPath, "%s/XXXXXX", fReverseMapPath);
+                                       int tempFile = ::mkstemp(tempPath);
+                                       if (tempFile == -1)
+                                               throwf("could not write file to symbol map directory: %s", fReverseMapPath);
+                                       ::close(tempFile);
+                                       fReverseMapTempPath = std::string(tempPath);
+                                       fReverseMapUUIDRename = true;
+                               } else
+                                       fReverseMapTempPath = std::string(fReverseMapPath);
+                       }
+                       else if ( strcmp(arg, "-flto-codegen-only") == 0) {
+                               fLTOCodegenOnly = true;
+                       }
+                       else if ( strcmp(arg, "-ignore_auto_link") == 0) {
+                               fIgnoreAutoLink = true;
+                       }
+                       else if ( strcmp(arg, "-allow_dead_duplicates") == 0) {
+                               fAllowDeadDups = true;
+                       }
+                       else if ( strcmp(arg, "-bitcode_process_mode") == 0 ) {
+                               const char* bitcode_type = checkForNullArgument(arg, argv[++i]);
+                               if ( strcmp(bitcode_type, "strip") == 0 )
+                                       fBitcodeKind = kBitcodeStrip;
+                               else if ( strcmp(bitcode_type, "marker") == 0 )
+                                       fBitcodeKind = kBitcodeMarker;
+                               else if ( strcmp(bitcode_type, "data") == 0 )
+                                       fBitcodeKind = kBitcodeAsData;
+                               else if ( strcmp(bitcode_type, "bitcode") == 0 )
+                                       fBitcodeKind = kBitcodeProcess;
+                               else
+                                       throw "unknown argument to -bitcode_process_mode {strip,marker,data,bitcode}";
+                       }
                        else if ( strcmp(arg, "-rpath") == 0 ) {
-                               const char* path = argv[++i];
-                               if ( path == NULL )
-                                       throw "missing argument to -rpath";
+                               const char* path = checkForNullArgument(arg, argv[++i]);
                                fRPaths.push_back(path);
                        }
                        else if ( strcmp(arg, "-read_only_stubs") == 0 ) {
@@ -2599,9 +3318,7 @@ void Options::parse(int argc, const char* argv[])
                                warnObsolete(arg);
                        }
                        else if ( strcmp(arg, "-map") == 0 ) {
-                               fMapPath = argv[++i];
-                               if ( fMapPath == NULL )
-                                       throw "missing argument to -map";
+                               fMapPath = checkForNullArgument(arg, argv[++i]);
                        }
                        else if ( strcmp(arg, "-pie") == 0 ) {
                                fPositionIndependentExecutable = true;
@@ -2609,6 +3326,7 @@ void Options::parse(int argc, const char* argv[])
                        }
                        else if ( strcmp(arg, "-no_pie") == 0 ) {
                                fDisablePositionIndependentExecutable = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strncmp(arg, "-reexport-l", 11) == 0 ) {
                 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
@@ -2617,14 +3335,17 @@ void Options::parse(int argc, const char* argv[])
                                info.options.fReExport = true;
                                info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
                                addLibrary(info);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-reexport_library") == 0 ) {
                 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
                 snapshotArgCount = 0;
-                               FileInfo info = findFile(argv[++i]);
+                               const char* path = checkForNullArgument(arg, argv[++i]);
+                               FileInfo info = findFile(path);
                                info.options.fReExport = true;
                                info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
                                addLibrary(info);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-reexport_framework") == 0 ) {
                 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
@@ -2633,6 +3354,7 @@ void Options::parse(int argc, const char* argv[])
                                info.options.fReExport = true;
                                info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
                                addLibrary(info);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strncmp(arg, "-upward-l", 9) == 0 ) {
                 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
@@ -2641,14 +3363,17 @@ void Options::parse(int argc, const char* argv[])
                                info.options.fUpward = true;
                                info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
                                addLibrary(info);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-upward_library") == 0 ) {
                 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
                 snapshotArgCount = 0;
-                               FileInfo info = findFile(argv[++i]);
+                               const char* path = checkForNullArgument(arg, argv[++i]);
+                               FileInfo info = findFile(path);
                                info.options.fUpward = true;
                                info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
                                addLibrary(info);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-upward_framework") == 0 ) {
                 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
@@ -2657,9 +3382,11 @@ void Options::parse(int argc, const char* argv[])
                                info.options.fUpward = true;
                                info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
                                addLibrary(info);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-dead_strip_dylibs") == 0 ) {
                                fDeadStripDylibs = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-no_implicit_dylibs") == 0 ) {
                                fImplicitlyLinkPublicDylibs = false;
@@ -2668,28 +3395,34 @@ void Options::parse(int argc, const char* argv[])
                                // ignore
                        }
                        else if ( strcmp(arg, "-no_encryption") == 0 ) {
-                               fEncryptable = false;
+                               fEncryptableForceOff = true;
+                               cannotBeUsedWithBitcode(arg);
+                       }
+                       else if ( strcmp(arg, "-encryptable") == 0 ) {
+                               fEncryptableForceOn = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-no_compact_unwind") == 0 ) {
                                fAddCompactUnwindEncoding = false;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-mllvm") == 0 ) {
-                               const char* opts = argv[++i];
-                               if ( opts == NULL )
-                                       throw "missing argument to -mllvm";
+                               const char* opts = checkForNullArgument(arg, argv[++i]);
                                fLLVMOptions.push_back(opts);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-mcpu") == 0 ) {
-                               const char* cpu = argv[++i];
-                               if ( cpu == NULL )
-                                       throw "missing argument to -mcpu";
+                               const char* cpu = checkForNullArgument(arg, argv[++i]);
                                fLtoCpu = cpu;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-no_order_inits") == 0 ) {
                                fAutoOrderInitializers = false;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-no_order_data") == 0 ) {
                                fOrderData = false;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-seg_page_size") == 0 ) {
                                SegmentSize seg;
@@ -2701,36 +3434,41 @@ void Options::parse(int argc, const char* argv[])
                                if ( (seg.size != temp)  )
                                        warning("-seg_page_size %s not 4K aligned, rounding down", seg.name);
                                fCustomSegmentSizes.push_back(seg);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-mark_dead_strippable_dylib") == 0 ) {
                                fMarkDeadStrippableDylib = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-exported_symbols_order") == 0 ) {
                 snapshotFileArgIndex = 1;
                                loadSymbolOrderFile(argv[++i], fExportSymbolsOrder);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-no_compact_linkedit") == 0 ) {
                                warnObsolete("-no_compact_linkedit");
                        }
                        else if ( strcmp(arg, "-no_eh_labels") == 0 ) {
                                fNoEHLabels = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-warn_compact_unwind") == 0 ) {
                                fWarnCompactUnwind = true;
                        }
                        else if ( strcmp(arg, "-allow_sub_type_mismatches") == 0 ) {
                                fAllowCpuSubtypeMismatches = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-no_zero_fill_sections") == 0 ) {
                                fOptimizeZeroFill = false;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-merge_zero_fill_sections") == 0 ) {
                                fMergeZeroFill = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-objc_abi_version") == 0 ) {
-                               const char* version = argv[++i];
-                                if ( version == NULL )
-                                       throw "-objc_abi_version missing version number";
+                               const char* version = checkForNullVersionArgument(arg, argv[++i]);
                                if ( strcmp(version, "2") == 0 ) {
                                        fObjCABIVersion1Override = false;
                                        fObjCABIVersion2Override = true;
@@ -2745,22 +3483,28 @@ void Options::parse(int argc, const char* argv[])
                        else if ( strcmp(arg, "-warn_weak_exports") == 0 ) {
                                fWarnWeakExports = true;
                        }
+                       else if ( strcmp(arg, "-no_weak_exports") == 0 ) {
+                               fNoWeakExports = true;
+                       }
                        else if ( strcmp(arg, "-objc_gc_compaction") == 0 ) {
                                fObjcGcCompaction = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-objc_gc") == 0 ) {
                                fObjCGc = true;
-                               if ( fObjCGcOnly ) { 
+                               if ( fObjCGcOnly ) {
                                        warning("-objc_gc overriding -objc_gc_only");
-                                       fObjCGcOnly = false;    
+                                       fObjCGcOnly = false;
                                }
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-objc_gc_only") == 0 ) {
                                fObjCGcOnly = true;
-                               if ( fObjCGc ) { 
+                               if ( fObjCGc ) {
                                        warning("-objc_gc_only overriding -objc_gc");
-                                       fObjCGc = false;        
+                                       fObjCGc = false;
                                }
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-demangle") == 0 ) {
                                fDemangle = true;
@@ -2769,10 +3513,6 @@ void Options::parse(int argc, const char* argv[])
                                fVersionLoadCommandForcedOn = true;
                                fVersionLoadCommandForcedOff = false;
                        }
-                       else if ( strcmp(arg, "-no_version_load_command") == 0 ) {
-                               fVersionLoadCommandForcedOff = true;
-                               fVersionLoadCommandForcedOn = false;
-                       }
                        else if ( strcmp(arg, "-function_starts") == 0 ) {
                                fFunctionStartsForcedOn = true;
                                fFunctionStartsForcedOff = false;
@@ -2780,19 +3520,19 @@ void Options::parse(int argc, const char* argv[])
                        else if ( strcmp(arg, "-no_function_starts") == 0 ) {
                                fFunctionStartsForcedOff = true;
                                fFunctionStartsForcedOn = false;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-no_data_in_code_info") == 0 ) {
                                fDataInCodeInfoLoadCommandForcedOff = true;
                                fDataInCodeInfoLoadCommandForcedOn = false;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-data_in_code_info") == 0 ) {
                                fDataInCodeInfoLoadCommandForcedOn  = true;
                                fDataInCodeInfoLoadCommandForcedOff = false;
                        }
                        else if ( strcmp(arg, "-object_path_lto") == 0 ) {
-                               fTempLtoObjectPath = argv[++i];
-                               if ( fTempLtoObjectPath == NULL )
-                                       throw "missing argument to -object_path_lto";
+                               fTempLtoObjectPath = checkForNullArgument(arg, argv[++i]);
                        }
                        else if ( strcmp(arg, "-no_objc_category_merging") == 0 ) {
                                fObjcCategoryMerging = false;
@@ -2800,22 +3540,26 @@ void Options::parse(int argc, const char* argv[])
                        else if ( strcmp(arg, "-force_symbols_weak_list") == 0 ) {
                 snapshotFileArgIndex = 1;
                                loadExportFile(argv[++i], "-force_symbols_weak_list", fForceWeakSymbols);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-force_symbols_not_weak_list") == 0 ) {
                 snapshotFileArgIndex = 1;
                                loadExportFile(argv[++i], "-force_symbols_not_weak_list", fForceNotWeakSymbols);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-force_symbol_weak") == 0 ) {
                                const char* symbol = argv[++i];
                                if ( symbol == NULL )
                                        throw "-force_symbol_weak missing <symbol>";
                                fForceWeakSymbols.insert(symbol);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-force_symbol_not_weak") == 0 ) {
                                const char* symbol = argv[++i];
                                if ( symbol == NULL )
                                        throw "-force_symbol_not_weak missing <symbol>";
                                fForceNotWeakSymbols.insert(symbol);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-reexported_symbols_list") == 0 ) {
                 snapshotFileArgIndex = 1;
@@ -2830,13 +3574,16 @@ void Options::parse(int argc, const char* argv[])
                                if ( strchr(envarg, '=') == NULL )
                                        throw "-dyld_env missing ENV=VALUE";
                                fDyldEnvironExtras.push_back(envarg);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-page_align_data_atoms") == 0 ) {
                                fPageAlignDataAtoms = true;
+                               cannotBeUsedWithBitcode(arg);
                        } 
                        else if (strcmp(arg, "-debug_snapshot") == 0) {
                 fLinkSnapshot.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG);
                 fSnapshotRequested = true;
+                               cannotBeUsedWithBitcode(arg);
             }
                        else if (strcmp(arg, "-snapshot_dir") == 0) {
                                const char* path = argv[++i];
@@ -2845,13 +3592,8 @@ void Options::parse(int argc, const char* argv[])
                                fLinkSnapshot.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG);
                                fLinkSnapshot.setSnapshotPath(path);
                                fSnapshotRequested = true;
+                               cannotBeUsedWithBitcode(arg);
             }
-                       else if ( strcmp(arg, "-new_main") == 0 ) {
-                               fEntryPointLoadCommandForceOn = true;
-                       }
-                       else if ( strcmp(arg, "-no_new_main") == 0 ) {
-                               fEntryPointLoadCommandForceOff = true;
-                       }
                        else if ( strcmp(arg, "-source_version") == 0 ) {
                                 const char* vers = argv[++i];
                                 if ( vers == NULL )
@@ -2863,6 +3605,7 @@ void Options::parse(int argc, const char* argv[])
                        }
                        else if ( strcmp(arg, "-no_source_version") == 0 ) {
                                fSourceVersionLoadCommandForceOff = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-sdk_version") == 0 ) {
                                 const char* vers = argv[++i];
@@ -2871,15 +3614,17 @@ void Options::parse(int argc, const char* argv[])
                                fSDKVersion = parseVersionNumber32(vers);
                        }
                        else if ( strcmp(arg, "-dependent_dr_info") == 0 ) {
-                               fDependentDRInfoForcedOn = true;
+                               warnObsolete(arg);
                        }
                        else if ( strcmp(arg, "-no_dependent_dr_info") == 0 ) {
-                               fDependentDRInfoForcedOff = true;
+                               warnObsolete(arg);
                        }
                        else if ( strcmp(arg, "-kexts_use_stubs") == 0 ) {
                                fKextsUseStubs = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
-                       else if ( strcmp(argv[i], "-dependency_info") == 0 ) {
+                       else if ( strcmp(arg, "-dependency_info") == 0 ) {
+                snapshotArgCount = 0;
                                ++i;
                                // previously handled by buildSearchPaths()
                        }
@@ -2911,21 +3656,220 @@ void Options::parse(int argc, const char* argv[])
                                        }
                                }
                                fLinkerOptions.push_back(opts);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-allow_simulator_linking_to_macosx_dylibs") == 0 ) {
                                fAllowSimulatorToLinkWithMacOSX = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-keep_dwarf_unwind") == 0 ) {
                                fKeepDwarfUnwindForcedOn = true;
                                fKeepDwarfUnwindForcedOff = false;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-no_keep_dwarf_unwind") == 0 ) {
                                fKeepDwarfUnwindForcedOn = false;
                                fKeepDwarfUnwindForcedOff = true;
+                               cannotBeUsedWithBitcode(arg);
+                       }
+                       else if ( strcmp(arg, "-verbose_optimization_hints") == 0 ) {
+                               fVerboseOptimizationHints = true;
+                       }
+                       else if ( strcmp(arg, "-ignore_optimization_hints") == 0 ) {
+                               fIgnoreOptimizationHints = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-no_dtrace_dof") == 0 ) {
                                fGenerateDtraceDOF = false;
                        }
+                       else if ( strcmp(arg, "-rename_section") == 0 ) {
+                                if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) || (argv[i+4]==NULL) )
+                                       throw "-rename_section missing <segment> <section> <segment> <section>";
+                               addSectionRename(argv[i+1], argv[i+2], argv[i+3], argv[i+4]);
+                               i += 4;
+                               cannotBeUsedWithBitcode(arg);
+                       }
+                       else if ( strcmp(arg, "-rename_segment") == 0 ) {
+                                if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) )
+                                       throw "-rename_segment missing <existing-segment> <new-segment>";
+                               addSegmentRename(argv[i+1], argv[i+2]);
+                               i += 2;
+                               cannotBeUsedWithBitcode(arg);
+                       }
+                       else if ( strcmp(arg, "-move_to_ro_segment") == 0 ) {
+                                if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) )
+                                       throw "-move_to_ro_segment missing <segment> <symbol-list-file>";
+                               addSymbolMove(argv[i+1], argv[i+2], fSymbolsMovesCode, "-move_to_ro_segment");
+                               i += 2;
+                               cannotBeUsedWithBitcode(arg);
+                       }
+                       else if ( strcmp(arg, "-move_to_rw_segment") == 0 ) {
+                                if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) )
+                                       throw "-move_to_rw_segment missing <segment> <symbol-list-file>";
+                               addSymbolMove(argv[i+1], argv[i+2], fSymbolsMovesData, "-move_to_rw_segment");
+                               i += 2;
+                               cannotBeUsedWithBitcode(arg);
+                       }
+                       else if ( strcmp(arg, "-trace_symbol_layout") == 0 ) {
+                               fTraceSymbolLayout = true;
+                       }
+                       else if ( strcmp(arg, "-no_branch_islands") == 0 ) {
+                               fAllowBranchIslands = false;
+                               cannotBeUsedWithBitcode(arg);
+                       }
+                       else if ( strcmp(arg, "-segment_order") == 0 ) {
+                               // ex: -segment_order __TEXT:__DATA:__JUNK
+                               const char* optString = argv[++i];
+                               if ( optString == NULL )
+                                       throw "-segment_order missing colon separated <segment-list>";
+                               if ( !fSegmentOrder.empty() )
+                                       throw "-segment_order used more than once";
+                               // break up into list of tokens at colon
+                               char* buffer = strdup(optString);
+                               char* start = buffer;
+                               for (char* s = buffer; ; ++s) {
+                                       if ( *s == ':'  ) {
+                                               *s = '\0';
+                                               fSegmentOrder.push_back(start);
+                                               start = s+1;
+                                       }
+                                       else if ( *s == '\0' ) {
+                                               fSegmentOrder.push_back(start);
+                                               break;
+                                       }
+                               }
+                               cannotBeUsedWithBitcode(arg);
+                       }
+                       else if ( strcmp(arg, "-section_order") == 0 ) {
+                               // ex: -section_order __DATA  __data:__const:__nl_pointers
+                                if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) )
+                                       throw "-section_order missing <segment> <section-list>";
+                               const char* segName = argv[++i];
+                               const char* optString = argv[++i];
+                               if ( sectionOrder(segName) != NULL )
+                                       throwf("-section_order %s ... used more than once", segName);
+                               SectionOrderList dummy;
+                               fSectionOrder.push_back(dummy);
+                               SectionOrderList& entry = fSectionOrder.back();
+                               entry.segmentName = segName;
+                               // break up into list of tokens at colon
+                               char* buffer = strdup(optString);
+                               char* start = buffer;
+                               for (char* s = buffer; ; ++s) {
+                                       if ( *s == ':'  ) {
+                                               *s = '\0';
+                                               entry.sectionOrder.push_back(start);
+                                               start = s+1;
+                                       }
+                                       else if ( *s == '\0' ) {
+                                               entry.sectionOrder.push_back(start);
+                                               break;
+                                       }
+                               }
+                               cannotBeUsedWithBitcode(arg);
+                       }                       
+                       else if ( strcmp(arg, "-application_extension") == 0 ) {
+                               fMarkAppExtensionSafe = true;
+                               fCheckAppExtensionSafe = true;
+                       }
+                       else if ( strcmp(arg, "-no_application_extension") == 0 ) {
+                               fMarkAppExtensionSafe = false;
+                               fCheckAppExtensionSafe = false;
+                       }
+                       else if ( strcmp(arg, "-add_ast_path") == 0 ) {
+                               const char* path = argv[++i];
+                               if ( path == NULL )
+                                       throw "-add_ast_path missing <option>";
+                               fASTFilePaths.push_back(path);
+                       }
+                       else if ( strcmp(arg, "-force_load_swift_libs") == 0 ) {
+                               fForceLoadSwiftLibs = true;
+                       }
+                       else if ( strcmp(arg, "-not_for_dyld_shared_cache") == 0 ) {
+                               fSharedRegionEligibleForceOff = true;
+                               cannotBeUsedWithBitcode(arg);
+                       }
+                       else if ( strcmp(arg, "-dirty_data_list") == 0 ) {
+                                if ( argv[i+1] == NULL )
+                                       throw "-dirty_data_list missing <symbol-list-file>";
+                               addSymbolMove("__DATA_DIRTY", argv[i+1], fSymbolsMovesData, "-dirty_data_list");
+                               ++i;
+                               cannotBeUsedWithBitcode(arg);
+                       }
+                       else if ( strcmp(arg, "-data_const") == 0 ) {
+                               fUseDataConstSegmentForceOn = true;
+                               cannotBeUsedWithBitcode(arg);
+                       }
+                       else if ( strcmp(arg, "-no_data_const") == 0 ) {
+                               fUseDataConstSegmentForceOff = true;
+                               cannotBeUsedWithBitcode(arg);
+                       }
+                       else if ( strcmp(arg, "-text_exec") == 0 ) {
+                               fUseTextExecSegment = true;
+                               cannotBeUsedWithBitcode(arg);
+                       }
+                       else if ( strcmp(arg, "-add_split_seg_info") == 0) {
+                               fSharedRegionEligible = true;
+                               cannotBeUsedWithBitcode(arg);
+                       }
+                       else if ( strcmp(arg, "-no_deduplicate") == 0 ) {
+                               fDeDupe = false;
+                       }
+                       else if ( strcmp(arg, "-verbose_deduplicate") == 0 ) {
+                               fVerboseDeDupe = true;
+                       }
+                       else if ( strcmp(arg, "-max_default_common_align") == 0 ) {
+                               const char* alignStr = argv[++i];
+                               if ( alignStr == NULL )
+                                       throw "-max_default_common_align missing <align-value>";
+                               // argument is a hexadecimal number
+                               char* endptr;
+                               unsigned long value = strtoul(alignStr, &endptr, 16);
+                               if ( *endptr != '\0')
+                                       throw "argument for -max_default_common_align is not a hexadecimal number";
+                               if ( value > 0x8000 )
+                                       throw "argument for -max_default_common_align must be less than or equal to 0x8000";
+                               if ( value == 0 ) {
+                                       warning("zero is not a valid -max_default_common_align");
+                                       value = 1;
+                               }
+                               // alignment is power of 2 
+                               uint8_t alignment = (uint8_t)__builtin_ctz(value);
+                               if ( (unsigned long)(1 << alignment) != value ) {
+                                       warning("alignment for -max_default_common_align is not a power of two, using 0x%X", 1 << alignment);
+                               }
+                               fMaxDefaultCommonAlign = alignment;
+                       }
+                       else if ( strcmp(arg, "-no_weak_imports") == 0 ) {
+                               fAllowWeakImports = false;
+                       }
+                       else if ( strcmp(arg, "-no_inits") == 0 ) {
+                               fInitializersTreatment = Options::kError;
+                       }
+                       else if ( strcmp(arg, "-no_warn_inits") == 0 ) {
+                               fInitializersTreatment = Options::kSuppress;
+                       }
+                       else if ( strcmp(arg, "-threaded_starts_section") == 0 ) {
+                               fMakeThreadedStartsSection = true;
+                       }
+                       else if (strcmp(arg, "-debug_variant") == 0) {
+                           fDebugVariant = true;
+            }
+                       else if (strcmp(arg, "-no_new_main") == 0) {
+                               // HACK until 39514191 is fixed
+                       }
+                       // put this last so that it does not interfer with other options starting with 'i'
+                       else if ( strncmp(arg, "-i", 2) == 0 ) {
+                               const char* colon = strchr(arg, ':');
+                               if ( colon == NULL )
+                                       throwf("unknown option: %s", arg);
+                               Options::AliasPair pair;
+                               char* temp = new char[colon-arg];
+                               strlcpy(temp, &arg[2], colon-arg-1);
+                               pair.realName = &colon[1];
+                               pair.alias = temp;
+                               fAliases.push_back(pair);
+                       }
                        else {
                                throwf("unknown option: %s", arg);
                        }
@@ -2954,9 +3898,25 @@ void Options::parse(int argc, const char* argv[])
     
     if (fSnapshotRequested)
         fLinkSnapshot.createSnapshot();
-}
-
 
+       if ( kKextBundle == fOutputKind ) {
+               if ( fKextObjectsEnable < 0 )
+                       fKextObjectsEnable = ((fArchitecture == CPU_TYPE_ARM64) || (fArchitecture == CPU_TYPE_ARM));
+
+               if (fKextObjectsEnable > 0) {
+                       if ( !fKextObjectsDirPath ) {
+                               const char* dstroot;
+                               const char* objdir = getenv("LD_KEXT_OBJECTS_DIR");
+                               if ( objdir )
+                                       fKextObjectsDirPath = strdup(objdir);
+                               else if ( (dstroot = getenv("DSTROOT")) )
+                                       asprintf((char **)&fKextObjectsDirPath, "%s/AppleInternal/KextObjects", dstroot);
+                       }
+                       fLinkSnapshot.setSnapshotMode(Snapshot::SNAPSHOT_KEXT);
+                       fLinkSnapshot.createSnapshot();
+               }
+       }
+}
 
 //
 // -syslibroot <path> is used for SDK support.
@@ -2988,16 +3948,7 @@ void Options::buildSearchPaths(int argc, const char* argv[])
                        }
                        if ( libSearchDir[0] == '\0' ) 
                                throw "-L must be immediately followed by a directory path (no space)";
-                       struct stat statbuf;
-                       if ( stat(libSearchDir, &statbuf) == 0 ) {
-                               if ( statbuf.st_mode & S_IFDIR )
-                                       libraryPaths.push_back(libSearchDir);
-                               else
-                                       warning("path '%s' following -L not a directory", libSearchDir);
-                       }
-                       else {
-                               warning("directory not found for option '-L%s'", libSearchDir);
-                       }
+                       libraryPaths.push_back(libSearchDir);
                }
                else if ( (argv[i][0] == '-') && (argv[i][1] == 'F') ) {
                        const char* frameworkSearchDir = &argv[i][2];
@@ -3011,16 +3962,7 @@ void Options::buildSearchPaths(int argc, const char* argv[])
                        }
                        if ( frameworkSearchDir[0] == '\0' ) 
                                throw "-F must be immediately followed by a directory path (no space)";
-                       struct stat statbuf;
-                       if ( stat(frameworkSearchDir, &statbuf) == 0 ) {
-                               if ( statbuf.st_mode & S_IFDIR )
-                                       frameworkPaths.push_back(frameworkSearchDir);
-                               else
-                                       warning("path '%s' following -F not a directory", frameworkSearchDir);
-                       }
-                       else {
-                               warning("directory not found for option '-F%s'", frameworkSearchDir);
-                       }
+                       frameworkPaths.push_back(frameworkSearchDir);
                }
                else if ( strcmp(argv[i], "-Z") == 0 )
                        addStandardLibraryDirectories = false;
@@ -3028,12 +3970,15 @@ void Options::buildSearchPaths(int argc, const char* argv[])
                        fVerbose = true;
                        extern const char ldVersionString[];
                        fprintf(stderr, "%s", ldVersionString);
+                       fprintf(stderr, "BUILD "  __TIME__ " "  __DATE__"\n");
                        fprintf(stderr, "configured to support archs: %s\n", ALL_SUPPORTED_ARCHS);
                         // if only -v specified, exit cleanly
                         if ( argc == 2 ) {
                                const char* ltoVers = lto::version();
                                if ( ltoVers != NULL )
-                                       fprintf(stderr, "LTO support using: %s\n", ltoVers);
+                                       fprintf(stderr, "LTO support using: %s (static support for %d, runtime is %d)\n",
+                                                       ltoVers, lto::static_api_version(), lto::runtime_api_version());
+                               fprintf(stderr, "TAPI support using: %s\n", tapi::Version::getFullVersionAsString().c_str());
                                exit(0);
                        }
                }
@@ -3061,6 +4006,9 @@ void Options::buildSearchPaths(int argc, const char* argv[])
                                throw "-dependency_info missing <path>";
                        fDependencyInfoPath = path;
                }
+               else if ( strcmp(argv[i], "-bitcode_bundle") == 0 ) {
+                       fBundleBitcode = true;
+               }
        }
        int standardLibraryPathsStartIndex = libraryPaths.size();
        int standardFrameworkPathsStartIndex = frameworkPaths.size();
@@ -3104,8 +4052,13 @@ void Options::buildSearchPaths(int argc, const char* argv[])
                                strcat(newPath, libDir);
                                struct stat statBuffer;
                                if ( stat(newPath, &statBuffer) == 0 ) {
-                                       fLibrarySearchPaths.push_back(strdup(newPath));
-                                       sdkOverride = true;
+                                       if ( (statBuffer.st_mode & S_IFDIR) == 0 ) {
+                                               warning("-syslibroot and -L combined path '%s' is not a directory", newPath);
+                                       }
+                                       else {
+                                               fLibrarySearchPaths.push_back(strdup(newPath));
+                                               sdkOverride = true;
+                                       }
                                }
                        }
                }
@@ -3115,11 +4068,21 @@ void Options::buildSearchPaths(int argc, const char* argv[])
                                // if one SDK is specified and a standard library path is not in the SDK, don't use it
                        }
                        else {
-                               fLibrarySearchPaths.push_back(libDir);
+                               struct stat statBuffer;
+                               if ( stat(libDir, &statBuffer) == 0 ) {
+                                       if ( (statBuffer.st_mode & S_IFDIR) == 0 )
+                                               warning("-L path '%s' is not a directory", libDir);
+                                       else
+                                               fLibrarySearchPaths.push_back(libDir);
+                               }
+                               else if ( !addStandardLibraryDirectories || (strcmp(libDir, "/usr/local/lib") != 0) ) {
+                                       warning("directory not found for option '-L%s'", libDir);
+                               }
                        }
                }
        }
 
+
        // now merge sdk and framework paths to make real search paths
        fFrameworkSearchPaths.reserve(frameworkPaths.size()*(fSDKPaths.size()+1));
        int frameIndex = 0;
@@ -3143,8 +4106,13 @@ void Options::buildSearchPaths(int argc, const char* argv[])
                                strcat(newPath, frameworkDir);
                                struct stat statBuffer;
                                if ( stat(newPath, &statBuffer) == 0 ) {
-                                       fFrameworkSearchPaths.push_back(strdup(newPath));
-                                       sdkOverride = true;
+                                       if ( (statBuffer.st_mode & S_IFDIR) == 0 ) {
+                                               warning("-syslibroot and -F combined path '%s' is not a directory", newPath);
+                                       }
+                                       else {
+                                               fFrameworkSearchPaths.push_back(strdup(newPath));
+                                               sdkOverride = true;
+                                       }
                                }
                        }
                }
@@ -3154,7 +4122,16 @@ void Options::buildSearchPaths(int argc, const char* argv[])
                                // if one SDK is specified and a standard library path is not in the SDK, don't use it
                        }
                        else {
-                               fFrameworkSearchPaths.push_back(frameworkDir);
+                               struct stat statBuffer;
+                               if ( stat(frameworkDir, &statBuffer) == 0 ) {
+                                       if ( (statBuffer.st_mode & S_IFDIR) == 0 )
+                                               warning("-F path '%s' is not a directory", frameworkDir);
+                                       else
+                                               fFrameworkSearchPaths.push_back(frameworkDir);
+                               }
+                               else if ( !addStandardLibraryDirectories || (strcmp(frameworkDir, "/Library/Frameworks/") != 0) ) {
+                                       warning("directory not found for option '-F%s'", frameworkDir);
+                               }
                        }
                }
        }
@@ -3185,6 +4162,11 @@ void Options::parsePreCommandLineEnvironmentSettings()
            fTraceDylibs = true;
                fTraceIndirectDylibs = true;
        }
+       
+       if ((getenv("LD_TRACE_DEPENDENTS") != NULL)) {
+               
+               fTraceEmitJSON = true;
+       }
 
        if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL) {
            fTraceDylibSearching = true;
@@ -3193,21 +4175,32 @@ void Options::parsePreCommandLineEnvironmentSettings()
        if (getenv("LD_PRINT_OPTIONS") != NULL)
                fPrintOptions = true;
 
-       if (fTraceDylibs || fTraceArchives)
+       if (fTraceDylibs || fTraceArchives || fTraceEmitJSON)
                fTraceOutputFile = getenv("LD_TRACE_FILE");
 
        if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL)
                fPrintOrderFileStatistics = true;
 
-       if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL)
-               fSplitSegs = true;
-               
-       if (getenv("LD_NO_ENCRYPT") != NULL)
+       if (getenv("LD_NO_ENCRYPT") != NULL) {
                fEncryptable = false;
+               fMarkAppExtensionSafe = true; // temporary
+               fCheckAppExtensionSafe = false;
+       }
+
+       if (getenv("LD_APPLICATION_EXTENSION_SAFE") != NULL) {
+               fMarkAppExtensionSafe = true;
+               fCheckAppExtensionSafe = false;
+       }
        
        if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL)
                fAllowCpuSubtypeMismatches = true;
        
+       if (getenv("LD_DYLIB_CPU_SUBTYPES_MUST_MATCH") != NULL)
+               fEnforceDylibSubtypesMatch = true;
+
+       if (getenv("LD_WARN_ON_SWIFT_ABI_VERSION_MISMATCHES") != NULL)
+               fWarnOnSwiftABIVersionMismatches = true;
+       
        sWarningsSideFilePath = getenv("LD_WARN_FILE");
        
        const char* customDyldPath = getenv("LD_DYLD_PATH");
@@ -3226,6 +4219,25 @@ void Options::parsePreCommandLineEnvironmentSettings()
     if (pipeFdString != NULL) {
                fPipelineFifo = pipeFdString;
     }
+
+       // <rdar://problem/30746905> [Reproducible Builds] If env ZERO_AR_DATE is set, zero out timestamp in N_OSO stab
+       if ( getenv("ZERO_AR_DATE") != NULL )
+               fZeroModTimeInDebugMap = true;
+
+       char rawPath[PATH_MAX];
+       char path[PATH_MAX];
+       char *base;
+       uint32_t bufSize = PATH_MAX;
+       if ( _NSGetExecutablePath(rawPath, &bufSize) != -1 ) {
+               if ( realpath(rawPath, path) != NULL ) {
+#define TOOLCHAINBASEPATH "/Developer/Toolchains/"
+                       if ( (base = strstr(path, TOOLCHAINBASEPATH)) )
+                               fToolchainPath = strndup(path, base - path + strlen(TOOLCHAINBASEPATH));
+               }
+       }
+
+       // <rdar://problem/38679559> ld64 should consider RC_RELEASE when calculating a binary's UUID
+       fBuildContextName = getenv("RC_RELEASE");
 }
 
 
@@ -3237,15 +4249,6 @@ void Options::parsePostCommandLineEnvironmentSettings()
                fExecutablePath = fOutputFile;
        }
 
-       // allow build system to set default seg_addr_table
-       if ( fSegAddrTablePath == NULL )
-               fSegAddrTablePath = getenv("LD_SEG_ADDR_TABLE");
-
-       // allow build system to turn on prebinding
-       if ( !fPrebind ) {
-               fPrebind = ( getenv("LD_PREBIND") != NULL );
-       }
-       
        // allow build system to force on dead-code-stripping
        if ( !fDeadStrip ) {
                if ( getenv("LD_DEAD_STRIP") != NULL ) {
@@ -3278,6 +4281,12 @@ void Options::parsePostCommandLineEnvironmentSettings()
                
 }
 
+
+static bool sharedCacheEligiblePath(const char* path)
+{
+       return ( (strncmp(path, "/usr/lib/", 9) == 0) || (strncmp(path, "/System/Library/", 16) == 0) );
+}
+
 void Options::reconfigureDefaults()
 {
        // sync reader options
@@ -3306,21 +4315,22 @@ void Options::reconfigureDefaults()
        }
 
        // set default min OS version
-       if ( (fMacVersionMin == ld::macVersionUnset)
-               && (fIOSVersionMin == ld::iOSVersionUnset) ) {
+       if ( platforms().empty() ) {
                // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
+               if ( (fOutputKind != Options::kObjectFile) && (fOutputKind != Options::kPreload) )
+                       warning("No version-min specified on command line");
                const char* macVers = getenv("MACOSX_DEPLOYMENT_TARGET");
                const char* iPhoneVers = getenv("IPHONEOS_DEPLOYMENT_TARGET");
                const char* iOSVers = getenv("IOS_DEPLOYMENT_TARGET");
-               const char* iOSSimulatorVers = getenv("IOS_SIMULATOR_DEPLOYMENT_TARGET");
-               if ( macVers != NULL ) 
-                       setMacOSXVersionMin(macVers);
+               const char* wOSVers = getenv("WATCHOS_DEPLOYMENT_TARGET");
+               if ( macVers != NULL )
+                       setVersionMin(ld::kPlatform_macOS, macVers);
                else if ( iPhoneVers != NULL )
-                       setIOSVersionMin(iPhoneVers);
+                       setVersionMin(ld::kPlatform_iOS, iPhoneVers);
                else if ( iOSVers != NULL )
-                       setIOSVersionMin(iOSVers);
-               else if ( iOSSimulatorVers != NULL )
-                       setIOSVersionMin(iOSSimulatorVers);
+                       setVersionMin(ld::kPlatform_iOS, iOSVers);
+               else if ( wOSVers != NULL )
+                       setVersionMin(ld::kPlatform_watchOS, wOSVers);
                else {
                        // if still nothing, set default based on architecture
                        switch ( fArchitecture ) {
@@ -3329,21 +4339,27 @@ void Options::reconfigureDefaults()
                                        if ( (fOutputKind != Options::kObjectFile) && (fOutputKind != Options::kPreload) ) {
                        #ifdef DEFAULT_MACOSX_MIN_VERSION
                                                warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION);
-                                               setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
+                                               setVersionMin(ld::kPlatform_macOS, DEFAULT_MACOSX_MIN_VERSION);
                        #else
                                                warning("-macosx_version_min not specified, assuming 10.6");
-                                               fMacVersionMin = ld::mac10_6;
-                       #endif          
+                                               setVersionMin(ld::kPlatform_macOS, "10.6");
+                       #endif
                                        }
                                        break;
                                case CPU_TYPE_ARM:
                                        if ( (fOutputKind != Options::kObjectFile) && (fOutputKind != Options::kPreload) ) {
                        #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
                                                warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION);
-                                               setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION);
+                                               setVersionMin(ld::kPlatformiOS, DEFAULT_IPHONEOS_MIN_VERSION);
                        #else
-                                               warning("-ios_version_min not specified, assuming 6.0");
-                                               setIOSVersionMin("6.0");
+                                               if ( fSubArchitecture == CPU_SUBTYPE_ARM_V7K ) {
+                                                       warning("-watchos_version_min not specified, assuming 2.0");
+                                                       setVersionMin(ld::kPlatform_watchOS, "2.0");
+                                               }
+                                               else {
+                                                       warning("-ios_version_min not specified, assuming 6.0");
+                                                       setVersionMin(ld::kPlatform_iOS, "6.0");
+                                               }
                        #endif
                                        }
                                        break;
@@ -3354,29 +4370,23 @@ void Options::reconfigureDefaults()
                }
        }
 
-
+       __block ld::VersionSet platformOverrides;
        // adjust min based on architecture
-       switch ( fArchitecture ) {
-               case CPU_TYPE_I386:
-                       if ( (fMacVersionMin < ld::mac10_4) && (fIOSVersionMin == ld::iOSVersionUnset) ) {
-                               //warning("-macosx_version_min should be 10.4 or later for i386");
-                               fMacVersionMin = ld::mac10_4;
-                       }
-                       break;
-               case CPU_TYPE_X86_64:
-                       if ( (fMacVersionMin < ld::mac10_4) && (fIOSVersionMin == ld::iOSVersionUnset) ) {
-                               //warning("-macosx_version_min should be 10.4 or later for x86_64");
-                               fMacVersionMin = ld::mac10_4;
-                       }
-                       break;
-               case CPU_TYPE_ARM64:
-                       if ( fIOSVersionMin < ld::iOS_7_0 ) {
-                               //warning("-mios_version_min should be 7.0 or later for arm64");
-                               fIOSVersionMin = ld::iOS_7_0;
-                       }
-                       break;
-       }
-       
+       platforms().forEach(^(ld::Platform platform, uint32_t version, bool &stop) {
+               if ( (fArchitecture == CPU_TYPE_I386 || fArchitecture == CPU_TYPE_X86_64)
+                               && platform == ld::kPlatform_macOS && !platforms().minOS(ld::mac10_4) ) {
+                       platformOverrides.add(ld::mac10_4);
+               } else if (fArchitecture == CPU_TYPE_ARM64 && platform == ld::kPlatform_iOS
+                                  && !platforms().minOS(ld::iOS_7_0)) {
+                       platformOverrides.add(ld::iOS_7_0);
+               }
+       });
+
+       // Insert the overrides into fPlatfroms
+       platformOverrides.forEach(^(ld::Platform platform, uint32_t version, bool &stop) {
+               fPlatforms.add({platform, version});
+       });
+
        // default to adding functions start for dynamic code, static code must opt-in
        switch ( fOutputKind ) {
                case Options::kPreload:
@@ -3388,6 +4398,11 @@ void Options::reconfigureDefaults()
                                fFunctionStartsLoadCommand = true;
                        break;
                case Options::kObjectFile:
+                       if ( !fDataInCodeInfoLoadCommandForcedOff )
+                               fDataInCodeInfoLoadCommand = true;
+                       if ( fFunctionStartsForcedOn )
+                               fFunctionStartsLoadCommand = true;
+                       break;
                case Options::kDynamicExecutable:
                case Options::kDyld:
                case Options::kDynamicLibrary:
@@ -3418,17 +4433,12 @@ void Options::reconfigureDefaults()
                                fUndefinedTreatment = kUndefinedDynamicLookup;
                                break;
                        case CPU_TYPE_ARM:
-                               if ( fIOSVersionMin >= ld::iOS_5_0 ) {
-                    // iOS 5.0 and later use new MH_KEXT_BUNDLE type
-                    fMakeCompressedDyldInfo = false;
-                    fMakeCompressedDyldInfoForceOff = true;
-                                       // kexts are PIC in iOS 6.0 and later
-                                       fAllowTextRelocs = (fIOSVersionMin < ld::iOS_6_0);
-                                       fKextsUseStubs = !fAllowTextRelocs;
-                    fUndefinedTreatment = kUndefinedDynamicLookup;
-                                       break;
-                               }
-                               // else use object file
+                               fMakeCompressedDyldInfo = false;
+                               fMakeCompressedDyldInfoForceOff = true;
+                               fAllowTextRelocs = false;
+                               fKextsUseStubs = !fAllowTextRelocs;
+                               fUndefinedTreatment = kUndefinedDynamicLookup;
+                               break;
                        case CPU_TYPE_I386:
                                // use .o files
                                fOutputKind = kObjectFile;
@@ -3438,65 +4448,9 @@ void Options::reconfigureDefaults()
 
        // disable implicit dylibs when targeting 10.3
        // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
-       if ( !minOS(ld::mac10_4, ld::iOS_2_0) )
+       if ( !platforms().minOS(ld::version2007) )
                fImplicitlyLinkPublicDylibs = false;
 
-
-       // allow build system to force linker to ignore -prebind
-       if ( getenv("LD_FORCE_NO_PREBIND") != NULL )
-               fPrebind = false;                       
-
-       // allow build system to force linker to ignore -seg_addr_table
-       if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL )
-                  fSegAddrTablePath = NULL;
-
-       // check for base address specified externally
-       if ( (fSegAddrTablePath != NULL) &&  (fOutputKind == Options::kDynamicLibrary) ) {
-               parseSegAddrTable(fSegAddrTablePath, this->installPath());
-               // HACK to support seg_addr_table entries that are physical paths instead of install paths
-               if ( fBaseAddress == 0 ) {
-                       if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
-                               parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libstdc++.6.0.4.dylib");
-                               if ( fBaseAddress == 0 )
-                                       parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libstdc++.6.0.9.dylib");
-                       }
-                               
-                       else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 ) 
-                               parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libz.1.2.3.dylib");
-                               
-                       else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 ) 
-                               parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libutil1.0.dylib");
-               }               
-       }
-       
-       // split segs only allowed for dylibs
-       if ( fSplitSegs ) {
-        // split seg only supported for i386, and arm.
-        switch ( fArchitecture ) {
-            case CPU_TYPE_I386:
-                if ( fOutputKind != Options::kDynamicLibrary )
-                    fSplitSegs = false;
-                // make sure read and write segments are proper distance apart
-                if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x10000000) )
-                    fBaseWritableAddress = fBaseAddress + 0x10000000;
-                break;
-            case CPU_TYPE_ARM:
-                if ( fOutputKind != Options::kDynamicLibrary ) {
-                    fSplitSegs = false;
-                               }
-                               else {
-                                       // make sure read and write segments are proper distance apart
-                                       if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x08000000) )
-                                               fBaseWritableAddress = fBaseAddress + 0x08000000;
-                               }
-                break;
-            default:
-                fSplitSegs = false;
-                fBaseAddress = 0;
-                fBaseWritableAddress = 0;
-               }
-       }
-
        // set too-large size
        switch ( fArchitecture ) {
                case CPU_TYPE_I386:
@@ -3528,103 +4482,87 @@ void Options::reconfigureDefaults()
                        break;
        }
 
-       // <rdar://problem/6138961> -r implies no prebinding for all architectures
-       if ( fOutputKind == Options::kObjectFile )
-               fPrebind = false;                       
-
-       // disable prebinding depending on arch and min OS version
-       if ( fPrebind ) {
-               switch ( fArchitecture ) {
-                       case CPU_TYPE_I386:
-                               if ( fMacVersionMin == ld::mac10_4 ) {
-                                       // in 10.4 only split seg dylibs are prebound
-                                       if ( (fOutputKind != Options::kDynamicLibrary) || ! fSplitSegs )
-                                               fPrebind = false;
-                               }
-                               else if ( fMacVersionMin >= ld::mac10_5 ) {
-                                       // in 10.5 nothing is prebound
-                                       fPrebind = false;
-                               }
-                               else if ( fIOSVersionMin != ld::iOSVersionUnset ) {
-                                       // nothing in simulator is prebound
-                                       fPrebind = false;
-                               }
-                               else {
-                                       // in 10.3 and earlier only dylibs and main executables could be prebound
-                                       switch ( fOutputKind ) {
-                                               case Options::kDynamicExecutable:
-                                               case Options::kDynamicLibrary:
-                                                       // only main executables and dylibs can be prebound
-                                                       break;
-                                               case Options::kStaticExecutable:
-                                               case Options::kDynamicBundle:
-                                               case Options::kObjectFile:
-                                               case Options::kDyld:
-                                               case Options::kPreload:
-                                               case Options::kKextBundle:
-                                                       // disable prebinding for everything else
-                                                       fPrebind = false;
-                                                       break;
-                                       }
-                               }
-                               break;
-                       case CPU_TYPE_X86_64:
-                               fPrebind = false;
-                               break;
-            case CPU_TYPE_ARM:
-                               switch ( fOutputKind ) {
-                                       case Options::kDynamicExecutable:
-                                       case Options::kDynamicLibrary:
-                                               // only main executables and dylibs can be prebound
-                                               break;
-                                       case Options::kStaticExecutable:
-                                       case Options::kDynamicBundle:
-                                       case Options::kObjectFile:
-                                       case Options::kDyld:
-                                       case Options::kPreload:
-                                       case Options::kKextBundle:
-                                               // disable prebinding for everything else
-                                               fPrebind = false;
-                                               break;
-                               }
-                               break;
-               }
-       }
-
-       // only prebound images can be split-seg
-       if ( fSplitSegs && !fPrebind )
-               fSplitSegs = false;
-
        // determine if info for shared region should be added
        if ( fOutputKind == Options::kDynamicLibrary ) {
-               if ( minOS(ld::mac10_5, ld::iOS_3_1) )
-                       if ( !fPrebind )
-                               if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
-                                       || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
+               if ( platforms().minOS(ld::version2008Fall) )
+                       if ( !fSharedRegionEligibleForceOff )
+                               if ( sharedCacheEligiblePath(this->installPath()) )
                                        fSharedRegionEligible = true;
        }
        else if ( fOutputKind == Options::kDyld ) {
         // <rdar://problem/10111122> Enable dyld to be put into the dyld shared cache
         fSharedRegionEligible = true;
        }
-    
-       // figure out if module table is needed for compatibility with old ld/dyld
-       if ( fOutputKind == Options::kDynamicLibrary ) {
-               switch ( fArchitecture ) {
-                       case CPU_TYPE_I386:
-                               if ( fIOSVersionMin != ld::iOSVersionUnset ) // simulator never needs modules
+
+       // automatically use __DATA_CONST in dylibs on all platforms except macOS
+       if ( fSharedRegionEligible && !fUseDataConstSegmentForceOff
+               && !platforms().contains(ld::kPlatform_macOS) && !targetIOSSimulator()) {
+               fUseDataConstSegment = true;
+       }
+       if ( fUseDataConstSegmentForceOn ) {
+               fUseDataConstSegment = true;
+       }
+       // A -kext for iOS 10 ==>  -data_const, -text_exec, -add_split_seg_info
+       if ( (fOutputKind == Options::kKextBundle) && (fArchitecture == CPU_TYPE_ARM64) ) {
+               fUseDataConstSegment = true;
+               fUseTextExecSegment = true;
+               fSharedRegionEligible = true;
+       }
+       if ( fUseDataConstSegment ) {
+               addSectionRename("__DATA", "__got",                             "__DATA_CONST", "__got");
+
+#if SUPPORT_ARCH_arm64e
+               addSectionRename("__DATA", "__auth_got",                "__DATA_CONST", "__auth_got");
+#endif
+               addSectionRename("__DATA", "__la_symbol_ptr",   "__DATA_CONST", "__la_symbol_ptr");
+               addSectionRename("__DATA", "__nl_symbol_ptr",   "__DATA_CONST", "__nl_symbol_ptr");
+               addSectionRename("__DATA", "__const",                   "__DATA_CONST", "__const");
+               addSectionRename("__DATA", "__cfstring",                "__DATA_CONST", "__cfstring");
+               addSectionRename("__DATA", "__mod_init_func",   "__DATA_CONST", "__mod_init_func");
+               addSectionRename("__DATA", "__mod_term_func",   "__DATA_CONST", "__mod_term_func");
+               addSectionRename("__DATA", "__objc_classlist",  "__DATA_CONST", "__objc_classlist");
+               addSectionRename("__DATA", "__objc_nlclslist",  "__DATA_CONST", "__objc_nlclslist");
+               addSectionRename("__DATA", "__objc_catlist",    "__DATA_CONST", "__objc_catlist");
+               addSectionRename("__DATA", "__objc_nlcatlist",  "__DATA_CONST", "__objc_nlcatlist");
+               addSectionRename("__DATA", "__objc_protolist",  "__DATA_CONST", "__objc_protolist");
+               addSectionRename("__DATA", "__objc_imageinfo",  "__DATA_CONST", "__objc_imageinfo");
+               addSectionRename("__DATA", "__objc_const",          "__DATA_CONST", "__objc_const");
+       }
+       if ( fUseTextExecSegment ) {
+               addSectionRename("__TEXT", "__text",                            "__TEXT_EXEC", "__text");
+               addSectionRename("__TEXT", "__stubs",                           "__TEXT_EXEC", "__stubs");
+       }
+       
+       // Use V2 shared cache info when targetting newer OSs
+       if ( fSharedRegionEligible && platforms().minOS(ld::supportsSplitSegV2)) {
+               fSharedRegionEncodingV2 = true;
+               if ( platforms().contains(ld::kPlatform_macOS) ) {
+                       fSharedRegionEncodingV2 = false;
+                       // <rdar://problem/24772435> only use v2 for Swift dylibs on Mac OS X
+                       if ( strncmp(this->installPath(), "/System/Library/PrivateFrameworks/Swift/", 40) == 0 )
+                               fSharedRegionEncodingV2 = true;
+                       // <rdar://problem/32525720> use v2 for ABI stable Swift dylibs on macOS
+                       if ( strncmp(this->installPath(), "/System/Library/Frameworks/Swift/", 33) == 0 )
+                               fSharedRegionEncodingV2 = true;
+                       // <rdar://problem/31428120> an other OS frameworks that use swift need v2
+                       for (const char* searchPath  : fLibrarySearchPaths ) {
+                               if ( strstr(searchPath, "xctoolchain/usr/lib/swift/macos") != NULL ) {
+                                       fSharedRegionEncodingV2 = true;
                                        break;
-                       case CPU_TYPE_ARM:
-                               if ( fPrebind )
-                                       fNeedsModuleTable = true; // redo_prebinding requires a module table
-                               break;
+                               }
+                       }
                }
+               fIgnoreOptimizationHints = true;
        }
-       
+
        // <rdar://problem/5366363> -r -x implies -S
        if ( (fOutputKind == Options::kObjectFile) && (fLocalSymbolHandling == kLocalSymbolsNone) )
                fDebugInfoStripping = Options::kDebugInfoNone;                  
-               
+
+       // <rdar://problem/15252891> -r implies -no_uuid
+       if ( fOutputKind == Options::kObjectFile )
+               fUUIDMode = kUUIDNone;
+
        // choose how to process unwind info
        switch ( fArchitecture ) {
                case CPU_TYPE_I386:             
@@ -3647,8 +4585,26 @@ void Options::reconfigureDefaults()
                        }
                        break;
                case CPU_TYPE_ARM:
-                       fAddCompactUnwindEncoding = false;
-                       fRemoveDwarfUnwindIfCompactExists = false;
+                       if ( armUsesZeroCostExceptions() )  {
+                               switch ( fOutputKind ) {
+                                       case Options::kObjectFile:
+                                       case Options::kStaticExecutable:
+                                       case Options::kPreload:
+                                       case Options::kKextBundle:
+                                               fAddCompactUnwindEncoding = false;
+                                               break;
+                                       case Options::kDyld:
+                                       case Options::kDynamicLibrary:
+                                       case Options::kDynamicBundle:
+                                       case Options::kDynamicExecutable:
+                                               fAddCompactUnwindEncoding = true;
+                                               break;
+                               }
+                       }
+                       else {
+                               fAddCompactUnwindEncoding = false;
+                               fRemoveDwarfUnwindIfCompactExists = false;
+                       }
                        break;
                case 0:
                        // if -arch is missing, assume we don't want compact unwind info
@@ -3656,10 +4612,30 @@ void Options::reconfigureDefaults()
                        break;
        }
                
-       // only iOS main executables should be encrypted
-       if ( fOutputKind != Options::kDynamicExecutable )
+       // only iOS executables should be encryptable
+       switch ( fOutputKind ) {
+               case Options::kObjectFile:
+               case Options::kDyld:
+               case Options::kStaticExecutable:
+               case Options::kPreload:
+               case Options::kKextBundle:
+                       fEncryptable = false;
+                       break;
+               case Options::kDynamicExecutable:
+                       break;
+               case Options::kDynamicLibrary:
+               case Options::kDynamicBundle:
+                       // <rdar://problem/16293398> Add LC_ENCRYPTION_INFO load command to bundled frameworks
+                       if ( !platforms().minOS(ld::version2013) )
+                               fEncryptable = false;
+                       break;
+       }
+       if ( (fArchitecture != CPU_TYPE_ARM) && (fArchitecture != CPU_TYPE_ARM64)
+         )
                fEncryptable = false;
-       if ( (fArchitecture != CPU_TYPE_ARM) && (fArchitecture != CPU_TYPE_ARM64) )
+       if ( fEncryptableForceOn )
+               fEncryptable = true;
+       else if ( fEncryptableForceOff )
                fEncryptable = false;
 
        // don't move inits in dyld because dyld wants certain
@@ -3689,29 +4665,37 @@ void Options::reconfigureDefaults()
                case Options::kDynamicLibrary:
                case Options::kDynamicBundle:
                        break;
+               case Options::kDyld:
+                       // arm64e has support for compressed LINKEDIT.
+                       if ( (fArchitecture == CPU_TYPE_ARM64) && (fSubArchitecture == CPU_SUBTYPE_ARM64_E) )
+                               break;
                case Options::kPreload:
                case Options::kStaticExecutable:
                case Options::kObjectFile:
-               case Options::kDyld:
                case Options::kKextBundle:
                        fMakeCompressedDyldInfoForceOff = true;
                        break;
        }
-       if ( fMakeCompressedDyldInfoForceOff ) 
+
+       // only use legacy LINKEDIT if compressed LINKEDIT is forced off of:
+       //                      macOS before 10.6
+       //                      iOS before 3.1
+       if ( fMakeCompressedDyldInfoForceOff || !platforms().minOS(ld::version2009) )
                fMakeCompressedDyldInfo = false;
 
-       
-       // only use compressed LINKEDIT for:
-       //                      Mac OS X 10.6 or later
-       //                      iOS 3.1 or later
-       if ( fMakeCompressedDyldInfo ) {
-               if ( !minOS(ld::mac10_6, ld::iOS_3_1) )
-                       fMakeCompressedDyldInfo = false;
+       // only ARM and x86_64 enforces that cpu-sub-types must match
+       switch ( fArchitecture ) {
+               case CPU_TYPE_ARM:
+               case CPU_TYPE_ARM64:
+                       break;
+               case CPU_TYPE_X86_64:
+                       fEnforceDylibSubtypesMatch = false;
+                       break;
+               case CPU_TYPE_I386:
+                       fEnforceDylibSubtypesMatch = false;
+                       break;
        }
-
-       // only ARM enforces that cpu-sub-types must match
-       if ( fArchitecture != CPU_TYPE_ARM )
-               fAllowCpuSubtypeMismatches = true;
+               
                
        // only final linked images can not optimize zero fill sections
        if ( fOutputKind == Options::kObjectFile )
@@ -3739,35 +4723,120 @@ void Options::reconfigureDefaults()
        }
        
        // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
-       if ( minOS(ld::mac10_5, ld::iOS_2_0) )
+       if ( platforms().minOS(ld::version2008) )
                fUseSimplifiedDylibReExports = true;
        
        // Mac OS X 10.7 and iOS 4.2 support LC_LOAD_UPWARD_DYLIB
-       if ( minOS(ld::mac10_7, ld::iOS_4_2) && (fOutputKind == kDynamicLibrary) )
+       if ( platforms().minOS(ld::version2010) && (fOutputKind == kDynamicLibrary) )
                fCanUseUpwardDylib = true;
-               
+
+       if (fArchitecture == CPU_TYPE_ARM64) {
+#if SUPPORT_ARCH_arm64e
+               if (fSubArchitecture == CPU_SUBTYPE_ARM64_E)
+               {
+                       // FIXME: Move some of these to arm64
+                       fNoLazyBinding = true;
+                       switch ( fOutputKind ) {
+                               case Options::kDynamicExecutable:
+                               case Options::kDynamicLibrary:
+                               case Options::kDynamicBundle:
+                               case Options::kDyld:
+                                       fUseLinkedListBinding = true;
+                                       fUseAuthenticatedStubs = true;
+                                       break;
+                               case Options::kPreload:
+                               case Options::kStaticExecutable:
+                               case Options::kObjectFile:
+                               case Options::kKextBundle:
+                                       break;
+                       }
+                       switch ( fOutputKind ) {
+                               case Options::kDynamicExecutable:
+                               case Options::kDyld:
+                               case Options::kDynamicLibrary:
+                               case Options::kObjectFile:
+                               case Options::kDynamicBundle:
+                               case Options::kKextBundle:
+                                       fSupportsAuthenticatedPointers = true;
+                                       break;
+                               case Options::kStaticExecutable:
+                               case Options::kPreload:
+                                       fSupportsAuthenticatedPointers = false;
+                                       break;
+                       }
+               }
+#endif
+       }
+
+       if ( fMakeThreadedStartsSection && (fArchitecture != CPU_TYPE_ARM64) ) {
+               // Threaded starts isn't valid here so ignore it.
+               warning("-threaded_starts_section ignored ignored for non-arm64");
+               fMakeThreadedStartsSection = false;
+       }
+
+       if (fMakeThreadedStartsSection) {
+               switch ( fOutputKind ) {
+                       case Options::kDynamicExecutable:
+                       case Options::kDyld:
+                       case Options::kDynamicLibrary:
+                       case Options::kObjectFile:
+                       case Options::kDynamicBundle:
+                       case Options::kKextBundle:
+                               // Threaded starts isn't valid here so ignore it.
+                               warning("-threaded_starts_section ignored for binaries other than -static or -preload");
+                               fMakeThreadedStartsSection = false;
+                               break;
+                       case Options::kStaticExecutable:
+                       case Options::kPreload:
+                               fUseLinkedListBinding = true;
+                               fNoLazyBinding = true;
+#if SUPPORT_ARCH_arm64e
+                               if ( (fArchitecture == CPU_TYPE_ARM64) && (fSubArchitecture == CPU_SUBTYPE_ARM64_E) )
+                                       fSupportsAuthenticatedPointers = true;
+#endif
+                               break;
+               }
+       }
+
+       // Weak binding requires that if we want to use linked list binding, we must
+       // also be using no lazy binding.
+       if ( fUseLinkedListBinding )
+               assert(fNoLazyBinding);
+       
        // MacOSX 10.7 defaults to PIE
-       if ( ((fArchitecture == CPU_TYPE_X86_64) || (fArchitecture == CPU_TYPE_I386))
+       if ( (fArchitecture == CPU_TYPE_I386)
                && (fOutputKind == kDynamicExecutable)
-               && (fMacVersionMin >= ld::mac10_7) ) {
+               && platforms().minOS(ld::mac10_7) ) {
                        fPositionIndependentExecutable = true;
        }
 
        // armv7 for iOS4.3 defaults to PIE
        if ( (fArchitecture == CPU_TYPE_ARM) 
                && fArchSupportsThumb2
-               && (fOutputKind == kDynamicExecutable) 
-               && (fIOSVersionMin >= ld::iOS_4_3) ) {
+               && (fOutputKind == kDynamicExecutable)
+               && (platforms().contains(ld::kPlatform_watchOS) || platforms().minOS(ld::iOS_4_3)) ) {
                        fPositionIndependentExecutable = true;
        }
 
+       // <rdar://problem/24535196> x86_64 defaults PIE (for 10.6 and later)
+       if ( (fArchitecture == CPU_TYPE_X86_64) && (fOutputKind == kDynamicExecutable) && (platforms().minOS(ld::mac10_6) || platforms().contains(ld::kPlatform_iOSMac)) )
+               fPositionIndependentExecutable = true;
+
+       // Simulator defaults to PIE
+       if ( targetIOSSimulator() && (fOutputKind == kDynamicExecutable) )
+               fPositionIndependentExecutable = true;
+
        // -no_pie anywhere on command line disable PIE
        if ( fDisablePositionIndependentExecutable )
                fPositionIndependentExecutable = false;
 
        // arm64 is always PIE
-       if ( (fArchitecture == CPU_TYPE_ARM64) && (fOutputKind == kDynamicExecutable) ) {
+       if ( ((fArchitecture == CPU_TYPE_ARM64)
+          )
+        && (fOutputKind == kDynamicExecutable) ) {
                fPositionIndependentExecutable = true;
+               if ( fDisablePositionIndependentExecutable )
+                       warning("-no_pie ignored for arm64");
        }
 
        // set fOutputSlidable
@@ -3790,11 +4859,15 @@ void Options::reconfigureDefaults()
                        break;
        }
 
-       // let linker know if thread local variables are supported
-       if ( fMacVersionMin >= ld::mac10_7 ) {
+       // Let linker know if thread local variables are supported
+       // This is more complex than normal version checks since
+       // runtime support varies by architecture
+       if (platforms().minOS(ld::supportsTLV)
+                       || ((fArchitecture == CPU_TYPE_ARM64) && platforms().minOS(ld::iOS_8_0))
+                       || ((fArchitecture == CPU_TYPE_X86_64) && platforms().minOS(ld::iOS_9_0))) {
                fTLVSupport = true;
        }
-       
+
        // default to adding version load command for dynamic code, static code must opt-in
        switch ( fOutputKind ) {
                case Options::kObjectFile:
@@ -3816,7 +4889,7 @@ void Options::reconfigureDefaults()
        }
        
        // support re-export of individual symbols in MacOSX 10.7 and iOS 4.2
-       if ( (fOutputKind == kDynamicLibrary) && minOS(ld::mac10_7, ld::iOS_4_2) )
+       if ( (fOutputKind == kDynamicLibrary) && platforms().minOS(ld::version2010) )
                fCanReExportSymbols = true;
        
        // ObjC optimization is only in dynamic final linked images
@@ -3843,20 +4916,20 @@ void Options::reconfigureDefaults()
        // Use LC_MAIN instead of LC_UNIXTHREAD for newer OSs
        switch ( fOutputKind ) {
                case Options::kDynamicExecutable:
-                       if ( fEntryPointLoadCommandForceOn ) {
+                       // <rdar://problem/16310363> Linker should look for "_main" not "start" when building for sim regardless of min OS
+                       if ( platforms().minOS(ld::version2012) ) {
                                fEntryPointLoadCommand = true;
-                               fEntryName = "_main";
-                       }
-                       else if ( fEntryPointLoadCommandForceOff ) {
-                               fNeedsThreadLoadCommand = true;
-                       }
-                       else {
-                               if ( minOS(ld::mac10_8, ld::iOS_6_0) ) {
-                                       fEntryPointLoadCommand = true;
+                               if ( fEntryName == NULL )
+                                       fEntryName = "_main";
+                               if ( strcmp(fEntryName, "start") == 0 ) {
+                                       warning("Ignoring '-e start' because entry point 'start' is not used for the targeted OS version");
                                        fEntryName = "_main";
                                }
-                               else
-                                       fNeedsThreadLoadCommand = true;
+                       }
+                       else {
+                               fNeedsThreadLoadCommand = true;
+                               if ( fEntryName == NULL )
+                                       fEntryName = "start";
                        }
                        break;
                case Options::kObjectFile:
@@ -3869,6 +4942,8 @@ void Options::reconfigureDefaults()
                case Options::kPreload:
                case Options::kDyld:
                        fNeedsThreadLoadCommand = true;
+                       if ( fEntryName == NULL ) 
+                               fEntryName = "start";  // Perhaps these should have no default and require -e
                        break;
        }
        
@@ -3887,7 +4962,7 @@ void Options::reconfigureDefaults()
                                fSourceVersionLoadCommand = false;
                        }
                        else {
-                               if ( minOS(ld::mac10_8, ld::iOS_6_0) ) {
+                               if ( platforms().minOS(ld::version2012) ) {
                                        fSourceVersionLoadCommand = true;
                                }
                                else
@@ -3899,35 +4974,7 @@ void Options::reconfigureDefaults()
                        fSourceVersionLoadCommand = false;
                        break;
        }
-       
-       
-       // add LC_DYLIB_CODE_SIGN_DRS
-       switch ( fOutputKind ) {
-               case Options::kDynamicExecutable:
-               case Options::kDynamicLibrary:
-               case Options::kDynamicBundle:
-                       if ( fDependentDRInfoForcedOn ) {
-                               fDependentDRInfo = true;
-                       }
-                       else if ( fDependentDRInfoForcedOff ) {
-                               fDependentDRInfo = false;
-                       }
-                       else {
-                               if ( minOS(ld::mac10_8, ld::iOS_6_0) ) 
-                                       fDependentDRInfo = true;
-                               else
-                                       fDependentDRInfo = false;
-                       }
-                       break;
-               case Options::kKextBundle:
-               case Options::kDyld:
-               case Options::kStaticExecutable:
-               case Options::kObjectFile:
-               case Options::kPreload:
-                       fDependentDRInfo = false;
-                       break;
-       }
-       
+
        // if -sdk_version not on command line, infer from -syslibroot
        if ( (fSDKVersion == 0) && (fSDKPaths.size() > 0) ) {
                const char* sdkPath = fSDKPaths.front();
@@ -3944,12 +4991,12 @@ void Options::reconfigureDefaults()
                        fSDKVersion = parseVersionNumber32(sdkVersionStr);
                }
        }
-       
+
        // if -sdk_version and -syslibroot not used, but targeting MacOSX, use current OS version
-       if ( (fSDKVersion == 0) && (fMacVersionMin != ld::macVersionUnset) ) {
+       if ( (fSDKVersion == 0) && platforms().contains(ld::kPlatform_macOS) ) {
                // special case if RC_ProjectName and MACOSX_DEPLOYMENT_TARGET are both set that sdkversion=minos
                if ( getenv("RC_ProjectName") && getenv("MACOSX_DEPLOYMENT_TARGET") ) {
-                       fSDKVersion = fMacVersionMin;
+                       fSDKVersion = platforms().minOS(ld::kPlatform_macOS);
                }
                else {
                        int mib[2] = { CTL_KERN, KERN_OSRELEASE };
@@ -3965,41 +5012,47 @@ void Options::reconfigureDefaults()
        
        // allow trie based absolute symbols if targeting new enough OS
        if ( fMakeCompressedDyldInfo ) {
-               if ( minOS(ld::mac10_9, ld::iOS_7_0) ) {
-                       // <rdar://problem/13179029> Allow absolute symbols in export trie for device but not simulator
-                       if ( !fTargetIOSSimulator ) 
-                               fAbsoluteSymbols = true;
+               if ( platforms().minOS(ld::version2013) ) {
+                       fAbsoluteSymbols = true;
                }
        }
-       
-       // <rdar://problem/12959510> iOS main executables now default to 16KB page size
-       if ( (fIOSVersionMin != ld::iOSVersionUnset) && (fOutputKind == Options::kDynamicExecutable) ) {
-               // <rdar://problem/13070042> Only third party apps should have 16KB page segments by default
-               if ( fEncryptable ) {
-                       if ( fSegmentAlignment == 4096 )
-                               fSegmentAlignment = 4096*4;
-               }
+
+       // <rdar://problem/13070042> Only third party apps should have 16KB page segments by default
+       if ( fEncryptable ) {
+               if ( fSegmentAlignment == 4096 )
+                       fSegmentAlignment = 4096*4;
        }
   
        // <rdar://problem/12258065> ARM64 needs 16KB page size for user land code
-       if ( fArchitecture == CPU_TYPE_ARM64 ) {
-               if ( fSegmentAlignment == 4096 ) {
-                       switch ( fOutputKind ) {
-                               case Options::kDynamicExecutable:
-                               case Options::kDynamicLibrary:
-                               case Options::kDynamicBundle:
-                               case Options::kDyld:
+       // <rdar://problem/15974532> make armv7[s] use 16KB pages in user land code for iOS 8 or later
+       if ( fSegmentAlignment == 4096 ) {
+               switch ( fOutputKind ) {
+                       case Options::kDynamicExecutable:
+                       case Options::kDynamicLibrary:
+                       case Options::kDynamicBundle:
+                       case Options::kDyld:
+                               // <rdar://problem/14676611> 16KB segments for arm64 kexts
+                               if ( (fArchitecture == CPU_TYPE_ARM64)
+                     || (fArchitecture == CPU_TYPE_ARM) ) {
                                        fSegmentAlignment = 4096*4;
-                                       break;
-                               case Options::kStaticExecutable:
-                               case Options::kKextBundle:
-                               case Options::kObjectFile:
-                               case Options::kPreload:
-                                       break;
-                       }
+                               }
+                               break;
+                       case Options::kStaticExecutable:
+                       case Options::kKextBundle:
+                               // <rdar://problem/14676611> 16KB segments for arm64 kexts
+                               if ( (fArchitecture == CPU_TYPE_ARM64)
+                                       ) {
+                                       fSegmentAlignment = 4096*4;
+                               }
+                               break;
+                       case Options::kObjectFile:
+                       case Options::kPreload:
+                               break;
                }
        }
-       
+
+
+
        // <rdar://problem/13624134> linker should not convert dwarf unwind if .o file has compact unwind section
        switch ( fOutputKind ) {
                case Options::kDynamicExecutable:
@@ -4013,7 +5066,7 @@ void Options::reconfigureDefaults()
                                fKeepDwarfUnwind = false;
                        }
                        else {
-                               if ( minOS(ld::mac10_9, ld::iOS_7_0) ) 
+                               if ( platforms().minOS(ld::version2013) )
                                        fKeepDwarfUnwind = false;
                                else
                                        fKeepDwarfUnwind = true;
@@ -4027,6 +5080,130 @@ void Options::reconfigureDefaults()
                        break;
        }
        
+       // Make sure -image_base matches alignment
+       uint64_t alignedBaseAddress = (fBaseAddress+fSegmentAlignment-1) & (-fSegmentAlignment);
+       if ( alignedBaseAddress != fBaseAddress ) {
+               warning("base address 0x%llX is not properly aligned. Changing it to 0x%llX", fBaseAddress, alignedBaseAddress);
+               fBaseAddress = alignedBaseAddress;
+       }
+
+       // If -dirty_data_list not specified, look in $SDKROOT/AppleInternal/DirtyDataFiles/<dylib>.dirty for dirty data list
+       if ( fSymbolsMovesData.empty() && fUseDataConstSegment && ( fDylibInstallName != NULL) && !fSDKPaths.empty() ) {
+               const char* dylibLeaf = strrchr(fDylibInstallName, '/');
+               if ( dylibLeaf ) {
+                       char path[PATH_MAX];
+                       strlcpy(path , fSDKPaths.front(), sizeof(path));
+                       strlcat(path , "/AppleInternal/DirtyDataFiles", sizeof(path));
+                       strlcat(path , dylibLeaf, sizeof(path));
+                       strlcat(path , ".dirty", sizeof(path));
+                       FileInfo info;
+                       if ( info.checkFileExists(*this, path) )
+                               addSymbolMove("__DATA_DIRTY", path, fSymbolsMovesData, "-dirty_data_list");
+               }
+       }
+
+
+       // Look in $SDKROOT/AppleInternal/AccessibilityLinkerSymbols/<dylib>.axsymbols for objc-class names
+       if ( fUseDataConstSegment && (fDylibInstallName != NULL) && !fSDKPaths.empty() ) {
+               const char* dylibLeaf = strrchr(fDylibInstallName, '/');
+               if ( dylibLeaf ) {
+                       char path[PATH_MAX];
+                       strlcpy(path , fSDKPaths.front(), sizeof(path));
+                       strlcat(path , "/AppleInternal/AccessibilityLinkerSymbols", sizeof(path));
+                       strlcat(path , dylibLeaf, sizeof(path));
+                       strlcat(path , ".axsymbols", sizeof(path));
+                       FileInfo info;
+                       if ( info.checkFileExists(*this, path) ) {
+                               SymbolsMove tmp;
+                               fSymbolsMovesAXMethodLists.push_back(tmp);
+                               loadExportFile(path, ".axsymbols", fSymbolsMovesAXMethodLists.back().symbols);
+                       }
+               }
+       }
+
+       // <rdar://problem/32138080> Automatically use OrderFiles found in the AppleInternal SDK
+       if ( (fFinalName != NULL) && fOrderedSymbols.empty() && !fSDKPaths.empty() ) {
+               char path[PATH_MAX];
+               strlcpy(path , fSDKPaths.front(), sizeof(path));
+               strlcat(path , "/AppleInternal/OrderFiles/", sizeof(path));
+               strlcat(path , fFinalName, sizeof(path));
+               strlcat(path , ".order", sizeof(path));
+               FileInfo info;
+               if ( info.checkFileExists(*this, path) )
+                       parseOrderFile(path, false);
+       }
+
+       // <rdar://problem/20503811> Reduce the default alignment of structures/arrays to save memory in embedded systems
+       if ( fMaxDefaultCommonAlign == 0 ) {
+               if ( fOutputKind == Options::kPreload )
+                       fMaxDefaultCommonAlign = 8;
+               else
+                       fMaxDefaultCommonAlign = 15;
+       }
+
+       // Add warnings for issues likely to cause OS verification issues
+       if ( fSharedRegionEligible && !fRPaths.empty() && !fDebugVariant ) {
+               // <rdar://problem/18719327> warn if -rpath is used with OS dylibs
+               warning("OS dylibs should not add rpaths (linker option: -rpath) (Xcode build setting: LD_RUNPATH_SEARCH_PATHS)");
+       }
+       if ( (fOutputKind == Options::kDynamicLibrary) && (fDylibInstallName != NULL) && (fFinalName != NULL) && sharedCacheEligiblePath(fFinalName) && !fDebugVariant ) {
+               if ( strncmp(fDylibInstallName, "@rpath", 6) == 0 )
+                       warning("OS dylibs should not use @rpath for -install_name.  Use absolute path instead");
+               if ( strcmp(fDylibInstallName, fFinalName) != 0 ) {
+                       bool different = true;
+                       // some projects end up with double slash in -final_output path
+                       if ( strstr(fFinalName, "//") != NULL ) {
+                               char fixedPath[strlen(fFinalName)+1];
+                               char* t = fixedPath;
+                               bool lastWasSlash = false;
+                               for (const char* s=fFinalName; *s != '\0'; ++s) {
+                                       if ( *s == '/' ) {
+                                               if ( !lastWasSlash )
+                                                       *t++ = *s;
+                                               lastWasSlash = true;
+                                       }
+                                       else {
+                                               *t++ = *s;
+                                               lastWasSlash = false;
+                                       }
+                               }
+                               *t = '\0';
+                               different = (strcmp(fDylibInstallName, fixedPath) != 0);
+                       }
+                       if ( different )
+                               warning("OS dylibs -install_name should match its real absolute path");
+               }
+       }
+
+       // set if unaligned pointers are warnings or errors
+       if ( platforms().minOS(ld::mac10_12) ) {
+               // ignore unaligned pointers when targeting older macOS versions
+               if ( fSharedRegionEligible )
+                       fUnalignedPointerTreatment = Options::kUnalignedPointerWarning;
+               else
+                       fUnalignedPointerTreatment = Options::kUnalignedPointerIgnore;
+       }
+       else if ( platforms().minOS(ld::iOS_10_0) ) {
+#if SUPPORT_ARCH_arm64e
+               if ( (fArchitecture == CPU_TYPE_ARM64) && (fSubArchitecture == CPU_SUBTYPE_ARM64_E) ) {
+                               fUnalignedPointerTreatment = Options::kUnalignedPointerError;
+               } else
+#endif
+                       fUnalignedPointerTreatment = Options::kUnalignedPointerWarning;
+       }
+       else {
+               fUnalignedPointerTreatment = Options::kUnalignedPointerIgnore;
+       }
+
+       // warn by default for OS dylibs
+       if ( fInitializersTreatment == Options::kInvalid ) {
+               if ( fSharedRegionEligible && (fOutputKind == Options::kDynamicLibrary) && !fDebugVariant ) {
+                       fInitializersTreatment = Options::kWarning;
+               }
+               else
+                       fInitializersTreatment = Options::kSuppress;
+       }
+
 }
 
 void Options::checkIllegalOptionCombinations()
@@ -4034,9 +5211,28 @@ void Options::checkIllegalOptionCombinations()
        // check -undefined setting
        switch ( fUndefinedTreatment ) {
                case kUndefinedError:
-               case kUndefinedDynamicLookup:
                        // always legal
                        break;
+               case kUndefinedDynamicLookup: {
+                       platforms().forEach(^(ld::Platform platform, uint32_t version, bool &stop) {
+                               switch (platform) {
+                                       case ld::kPlatform_macOS:
+                                       case ld::kPlatform_iOSMac:
+                                       case ld::kPlatform_unknown:
+                                               break;
+                                       case ld::kPlatform_iOS:
+                                       case ld::kPlatform_iOSSimulator:
+                                       case ld::kPlatform_watchOS:
+                                       case ld::kPlatform_watchOSSimulator:
+                                       case ld::kPlatform_bridgeOS:
+                                       case ld::kPlatform_tvOS:
+                                       case ld::kPlatform_tvOSSimulator:
+                                               if ( fOutputKind != kKextBundle )
+                                                       warning("-undefined dynamic_lookup is deprecated on %s", platformName(platform));
+                                               break;
+                               }
+                       });
+               } break;
                case kUndefinedWarning:
                case kUndefinedSuppress:
                        // requires flat namespace
@@ -4054,7 +5250,11 @@ void Options::checkIllegalOptionCombinations()
                        const char* lastSlash = strrchr(info.path, '/');
                        if ( lastSlash == NULL )
                                lastSlash = info.path - 1;
-                       if ( strcmp(&lastSlash[1], subUmbrella) == 0 ) {
+                       std::string path(&lastSlash[1]);
+                       auto idx = path.find(".tbd", path.size() - 4);
+                       if (idx != std::string::npos)
+                               path.erase(idx);
+                       if ( path == subUmbrella ) {
                                info.options.fReExport = true;
                                found = true;
                 fLinkSnapshot.recordSubUmbrella(info.path);
@@ -4089,8 +5289,28 @@ void Options::checkIllegalOptionCombinations()
        }
 
        // sync reader options
-       if ( fNameSpace != kTwoLevelNameSpace )
+       if ( fNameSpace != kTwoLevelNameSpace ) {
                fFlatNamespace = true;
+               platforms().forEach(^(ld::Platform platform, uint32_t version, bool &stop) {
+                       switch (platform) {
+                               case ld::kPlatform_unknown:
+                               case ld::kPlatform_macOS:
+                               case ld::kPlatform_iOSMac:
+                                       break;
+                               case ld::kPlatform_iOS:
+                               case ld::kPlatform_iOSSimulator:
+                               case ld::kPlatform_watchOS:
+                               case ld::kPlatform_watchOSSimulator:
+                               case ld::kPlatform_bridgeOS:
+                               case ld::kPlatform_tvOS:
+                               case ld::kPlatform_tvOSSimulator:
+                                       warning("-flat_namespace is deprecated on %s", platformName(platform));
+                                       break;
+                       }
+               });
+
+       }
+
 
        // check -stack_addr
        if ( fStackAddr != 0 ) {
@@ -4114,37 +5334,54 @@ void Options::checkIllegalOptionCombinations()
        if ( fStackSize != 0 ) {
                switch (fArchitecture) {
                        case CPU_TYPE_I386:
-                               if ( fStackSize > 0xFFFFFFFF )
-                                       throw "-stack_size must be < 4G for 32-bit processes";
-                               if ( fStackAddr == 0 ) {
-                                       fStackAddr = 0xC0000000;
+                               if ( platforms().contains(ld::kPlatform_macOS) ) {
+                                       if ( fStackSize > 0xFFFFFFFF )
+                                               throw "-stack_size must be < 4GB for 32-bit processes";
+                                       if ( fStackAddr == 0 )
+                                               fStackAddr = 0xC0000000;
+                                       if ( (fStackAddr > 0xB0000000) && ((fStackAddr-fStackSize) < 0xB0000000)  )
+                                               warning("custom stack placement overlaps and will disable shared region");
+                               }
+                               else {
+                                       if ( fStackSize > 0x1F000000 )
+                                               throw "-stack_size must be < 496MB";
+                                       if ( fStackAddr == 0 )
+                                               fStackAddr = 0xC0000000;
                                }
-                               if ( (fStackAddr > 0xB0000000) && ((fStackAddr-fStackSize) < 0xB0000000)  )
-                                       warning("custom stack placement overlaps and will disable shared region");
                                break;
             case CPU_TYPE_ARM:
-                               if ( fStackSize > 0x2F000000 )
-                                       throw "-stack_size must be < 752MB";
+                               if ( fStackSize > 0x1F000000 )
+                                       throw "-stack_size must be < 496MB";
                                if ( fStackAddr == 0 )
-                                       fStackAddr = 0x2F000000;
-                if ( fStackAddr > 0x30000000)
-                    throw "-stack_addr must be < 0x30000000 for arm";
+                                       fStackAddr = 0x1F000000;
+                if ( fStackAddr > 0x20000000)
+                    throw "-stack_addr must be < 0x20000000 for arm";
                                break;
                        case CPU_TYPE_X86_64:
-                               if ( fStackAddr == 0 ) {
-                                       fStackAddr = 0x00007FFF5C000000LL;
+                               if ( platforms().contains(ld::kPlatform_macOS) ) {
+                                       if ( fStackSize > 0x10000000000 )
+                                               throw "-stack_size must be <= 1TB";
+                                       if ( fStackAddr == 0 ) {
+                                               fStackAddr = 0x00007FFF5C000000LL;
+                                       }
+                               }
+                               else {
+                                       if ( fStackSize > 0x20000000 )
+                                               throw "-stack_size must be <= 512MB";
+                                       if ( fStackAddr == 0 ) {
+                                               fStackAddr = 0x120000000;
                                }
                                break;
                        case CPU_TYPE_ARM64:
                                if ( fStackSize > 0x20000000 )
-                                       throw "-stack_size must be < 512MB";
-                               if ( fStackAddr == 0 ) {
+                                       throw "-stack_size must be <= 512MB";
+                               if ( fStackAddr == 0 )
                                        fStackAddr = 0x120000000;
                                }
                                break;
                }
-               if ( (fStackSize & -4096) != fStackSize )
-                       throw "-stack_size must be multiples of 4K";
+               if ( (fStackSize & (-fSegmentAlignment)) != fStackSize )
+                       throwf("-stack_size must be multiple of segment alignment (%lldKB)", fSegmentAlignment/1024);
                switch ( fOutputKind ) {
                        case Options::kDynamicExecutable:
                        case Options::kStaticExecutable:
@@ -4239,7 +5476,7 @@ void Options::checkIllegalOptionCombinations()
                throw "-setuid_safe cannot be used with -r";
 
        // <rdar://problem/12781832> compiler driver no longer uses -objc_abi_version, it uses -ios_simulator_version_min instead
-       if ( !fObjCABIVersion1Override && !fObjCABIVersion2Override && fTargetIOSSimulator )
+       if ( !fObjCABIVersion1Override && !fObjCABIVersion2Override && targetIOSSimulator() )
                fObjCABIVersion2Override = true;
 
        // rdar://problem/4718189 map ObjC class names to new runtime names
@@ -4344,7 +5581,7 @@ void Options::checkIllegalOptionCombinations()
                // zero page size not specified on command line, set default
                switch (fArchitecture) {
                        case CPU_TYPE_I386:
-            case CPU_TYPE_ARM:
+                       case CPU_TYPE_ARM:
                                // first 4KB for 32-bit architectures
                                fZeroPageSize = 0x1000;
                                break;
@@ -4389,7 +5626,7 @@ void Options::checkIllegalOptionCombinations()
 
        // can't use -rpath unless targeting 10.5 or later
        if ( fRPaths.size() > 0 ) {
-               if ( !minOS(ld::mac10_5, ld::iOS_2_0) )
+               if ( !platforms().minOS(ld::version2008) )
                        throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
                switch ( fOutputKind ) {
                        case Options::kDynamicExecutable:
@@ -4409,11 +5646,8 @@ void Options::checkIllegalOptionCombinations()
                switch ( fOutputKind ) {
                        case Options::kDynamicExecutable:
                                // check -pie is only used when building a dynamic main executable for 10.5
-                               if ( !minOS(ld::mac10_5, ld::iOS_4_2) ) {
-                                       if ( fIOSVersionMin == ld::iOSVersionUnset )
-                                               throw "-pie can only be used when targeting Mac OS X 10.5 or later";
-                                       else
-                                               throw "-pie can only be used when targeting iOS 4.2 or later";
+                               if ( !platforms().minOS(ld::supportsPIE) ) {
+                                       throw "-pie requires targetting a newer minimum version";
                                }
                                break;
                        case Options::kStaticExecutable:
@@ -4432,12 +5666,15 @@ void Options::checkIllegalOptionCombinations()
                }
        }
        
-       // check -read_only_relocs is not used with x86_64
+       // check -read_only_relocs is not used with x86_64 or arm64
        if ( fAllowTextRelocs ) {
                if ( (fArchitecture == CPU_TYPE_X86_64) && (fOutputKind != kKextBundle) ) {
                        warning("-read_only_relocs cannot be used with x86_64");
                        fAllowTextRelocs = false;
                }
+               else if ( fArchitecture == CPU_TYPE_ARM64 ) {
+                       warning("-read_only_relocs cannot be used with arm64");
+               }
        }
        
        // check -mark_auto_dead_strip is only used with dylibs
@@ -4459,14 +5696,109 @@ void Options::checkIllegalOptionCombinations()
        if ( !fReExportSymbols.empty() ) {
                if ( fOutputKind != Options::kDynamicLibrary )
                        throw "-reexported_symbols_list can only used used when created dynamic libraries";
-               if ( !minOS(ld::mac10_7, ld::iOS_4_2) )
+               if ( !platforms().minOS(ld::version2010) )
                        throw "targeted OS version does not support -reexported_symbols_list";
        }
        
        // -dyld_env can only be used with main executables
        if ( (fOutputKind != Options::kDynamicExecutable) && (fDyldEnvironExtras.size() != 0) )
                throw "-dyld_env can only used used when created main executables";
-}      
+
+       // -segment_order can only be used with -preload or -static
+       if ( !fSegmentOrder.empty() && ((fOutputKind != Options::kPreload) && (fOutputKind != kStaticExecutable)) )
+               throw "-segment_order can only used used with -preload output";
+
+       // warn about bitcode option combinations
+       if ( !fBundleBitcode ) {
+               if ( fVerifyBitcode )
+                       warning("-bitcode_verify is ignored without -bitcode_bundle");
+               else if ( fHideSymbols )
+                       warning("-bitcode_hide_symbols is ignored without -bitcode_bundle");
+       }
+       if ( fReverseMapPath != NULL && !fHideSymbols ) {
+               throw "-bitcode_symbol_map can only be used with -bitcode_hide_symbols";
+       }
+       // auto fix up the process type for strip -S.
+       // when there is only one input and output type is object file, downgrade kBitcodeProcess to kBitcodeAsData.
+       if ( fOutputKind == Options::kObjectFile && fInputFiles.size() == 1 && fBitcodeKind == Options::kBitcodeProcess )
+               fBitcodeKind = Options::kBitcodeAsData;
+
+       // <rdar://problem/17598404> warn if building an embedded iOS dylib for pre-iOS 8
+       // <rdar://problem/18935714> How can we suppress "ld: warning: embedded dylibs/frameworks only run on iOS 8 or later" when building XCTest?
+       if ( (fOutputKind == Options::kDynamicLibrary) && (fDylibInstallName != NULL) ) {
+               if ( platforms().contains(ld::kPlatform_iOS) && !platforms().minOS(ld::iOS_8_0) && (fDylibInstallName[0] == '@') && !fEncryptableForceOff )
+                       warning("embedded dylibs/frameworks only run on iOS 8 or later");
+       }
+
+       // produce nicer error when no input
+       if ( fInputFiles.empty() ) {
+               throw "no object files specified";
+       }
+
+       // Check zippered combinations.
+       if (platforms().count() > 2) {
+               throw "Illegal platform count.  Only 2 platforms at a maximum can be specified";
+       }
+
+       // Convert from -ios_version_min to -ios_simulator_version_min for now until clang has been updated
+       if (architecture() == CPU_TYPE_X86_64 || architecture() == CPU_TYPE_X86) {
+               if (platforms().contains(ld::kPlatform_iOS)) {
+                       uint32_t version = platforms().minOS(ld::kPlatform_iOS);
+                       fPlatforms.erase(ld::kPlatform_iOS);
+                       // HACK infer the build environment from the SDK path
+                       bool macOSSDK = false;
+                       for (const auto& sdkPath : fSDKPaths) {
+                               if (strstr(sdkPath, "MacOSX10") != 0) {
+                                       macOSSDK = true;
+                                       break;
+                               }
+                       }
+                       if (macOSSDK) {
+                               fPlatforms.add({ ld::kPlatform_iOSMac, version });
+                               warning("URGENT: -ios_version_min is invalid for architecture x86/x86_64, inferring -iosmac_version_min. "
+                                               "This will be an error in the future.");
+                       } else {
+                               fPlatforms.add({ ld::kPlatform_iOSSimulator, version });
+                               warning("URGENT: -ios_version_min is invalid for architecture x86/x86_64, inferring -ios_simulator_version_min. "
+                                               "This will be an error in the future.");
+                       }
+               }
+       }
+
+       if (platforms().count() == 2) {
+               if (!platforms().minOS(ld::mac10_14))
+                       throw "Zippered macOS version platform must be at least 10.14";
+               if (!platforms().minOS(ld::iOS_12_0))
+                       throw "Zippered iosmac version platform must be at least 12.0";
+       }
+
+       if (platforms().contains(ld::kPlatform_iOSMac) && !platforms().minOS(ld::iOS_12_0)) {
+               throw "iosmac platform version must be at least 12.0";
+       }
+
+       // <rdar://problem/38155581> ld64 shouldn't allow final executables to have more than one version load command
+       if ( platforms().contains(ld::kPlatform_iOSMac) && platforms().contains(ld::kPlatform_macOS) ) {
+               if ( (fOutputKind != Options::kDynamicLibrary) && (fOutputKind != Options::kDynamicBundle) ) {
+                       warning("Only dylibs and bundles can be zippered, changing output to be macOS only.");
+                       fPlatforms.erase(ld::kPlatform_iOSMac);
+               }
+       }
+
+       // <rdar://problem/39095109> Linker warning for i386 macOS binaries
+       if ( (architecture() == CPU_TYPE_I386) && platforms().contains(ld::kPlatform_macOS) ) {
+               bool internalSDK = false;
+               for (const char* sdkPath : fSDKPaths) {
+                       std::string possiblePath = std::string(sdkPath) + "/AppleInternal/";
+                       struct stat statBuffer;
+                       if ( stat(possiblePath.c_str(), &statBuffer) == 0 ) {
+                               internalSDK = true;
+                               break;
+                       }
+               }
+               if ( !internalSDK )
+                       warning("The i386 architecture is deprecated for macOS (remove from the Xcode build setting: ARCHS)");
+       }
+}
 
 
 void Options::checkForClassic(int argc, const char* argv[])
@@ -4601,14 +5933,28 @@ const char* Options::demangleSymbol(const char* sym) const
        if ( !fDemangle )
                return sym;
 
+       static size_t size = 1024;
+       static char* buff = (char*)malloc(size);
+
+#if DEMANGLE_SWIFT
+       // only try to demangle symbols that look like Swift symbols
+       if ( strncmp(sym, "_$", 2) == 0 ) {
+               size_t demangledSize = fnd_get_demangled_name(&sym[1], buff, size);
+               if ( demangledSize > size ) {
+                       size = demangledSize+2;
+                       buff = (char*)realloc(buff, size);
+                       demangledSize = fnd_get_demangled_name(&sym[1], buff, size);
+               }
+               if ( demangledSize != 0 )
+                       return buff;
+       }
+#endif
+
        // only try to demangle symbols that look like C++ symbols
        if ( strncmp(sym, "__Z", 3) != 0 )
                return sym;
 
-       static size_t size = 1024;
-       static char* buff = (char*)malloc(size);
        int status;
-       
        char* result = abi::__cxa_demangle(&sym[1], buff, &size, &status); 
        if ( result != NULL ) {
                // if demangling successful, keep buffer for next demangle
@@ -4619,26 +5965,50 @@ const char* Options::demangleSymbol(const char* sym) const
 }
 
 
-void Options::dumpDependency(uint8_t opcode, const char* path) const
+void Options::writeDependencyInfo() const
 {
-       if ( !this->dumpDependencyInfo() ) 
+       // do nothing if -dependency_info not used
+       if ( !dumpDependencyInfo() )
                return;
 
+       // <rdar://problem/30750137> sort entries for build reproducibility
+       std::sort(fDependencies.begin(), fDependencies.end(), [](const DependencyEntry& a, const DependencyEntry& b) -> bool {
+               if ( a.opcode != b.opcode )
+                       return (a.opcode < b.opcode);
+               return (a.path < b.path);
+       });
+
        // one time open() of -dependency_info file
-       if ( fDependencyFileDescriptor == -1 ) {
-               fDependencyFileDescriptor = open(this->dependencyInfoPath(), O_WRONLY | O_TRUNC | O_CREAT, 0666);
-               if ( fDependencyFileDescriptor == -1 )
-                       throwf("Could not open or create -dependency_info file: %s", this->dependencyInfoPath());
-
-               // write header
-               uint8_t version = depLinkerVersion;
-               if ( write(fDependencyFileDescriptor, &version, 1) == -1 )
+       int fd = open(this->dependencyInfoPath(), O_WRONLY | O_TRUNC | O_CREAT, 0666);
+       if ( fd == -1 )
+               throwf("Could not open or create -dependency_info file: %s", this->dependencyInfoPath());
+
+       // write header
+       uint8_t version = depLinkerVersion;
+       if ( write(fd, &version, 1) == -1 )
+               throwf("write() to -dependency_info failed, errno=%d", errno);
+       extern const char ldVersionString[];
+       if ( write(fd, ldVersionString, strlen(ldVersionString)+1) == -1 )
+               throwf("write() to -dependency_info failed, errno=%d", errno);
+
+       // write each dependency
+       for (const auto& entry: fDependencies) {
+               //printf("%d %s\n", entry.opcode, entry.path.c_str());
+               if ( write(fd, &entry.opcode, 1) == -1 )
                        throwf("write() to -dependency_info failed, errno=%d", errno);
-               extern const char ldVersionString[];
-               if ( write(fDependencyFileDescriptor, ldVersionString, strlen(ldVersionString)+1) == -1 )
+               if ( write(fd, entry.path.c_str(), entry.path.size()+1) == -1 )
                        throwf("write() to -dependency_info failed, errno=%d", errno);
        }
 
+       ::close(fd);
+}
+
+
+void Options::addDependency(uint8_t opcode, const char* path) const
+{
+       if ( !this->dumpDependencyInfo() ) 
+               return;
+
        char realPath[PATH_MAX];
        if ( path[0] != '/' ) {
                if ( realpath(path, realPath) != NULL ) {
@@ -4646,13 +6016,35 @@ void Options::dumpDependency(uint8_t opcode, const char* path) const
                }
        }
 
-       if ( write(fDependencyFileDescriptor, &opcode, 1) == -1 )
-               throwf("write() to -dependency_info failed, errno=%d", errno);
-       if ( write(fDependencyFileDescriptor, path, strlen(path)+1) == -1 )
-               throwf("write() to -dependency_info failed, errno=%d", errno);
-
-       //fprintf(stderr, "0x%02X %s\n", opcode, path);
+       DependencyEntry entry;
+       entry.opcode = opcode;
+       entry.path   = path;
+       fDependencies.push_back(entry);
 }
 
 
+void Options::writeToTraceFile(const char* buffer, size_t len) const
+{
+       // one time open() of custom LD_TRACE_FILE
+       if ( fTraceFileDescriptor == -1 ) {
+               if ( fTraceOutputFile != NULL ) {
+                       fTraceFileDescriptor = open(fTraceOutputFile, O_WRONLY | O_APPEND | O_CREAT, 0666);
+                       if ( fTraceFileDescriptor == -1 )
+                               throwf("Could not open or create trace file (errno=%d): %s", errno, fTraceOutputFile);
+               }
+               else {
+                       fTraceFileDescriptor = fileno(stderr);
+               }
+       }
+
+       while (len > 0) {
+               ssize_t amountWritten = write(fTraceFileDescriptor, buffer, len);
+               if ( amountWritten == -1 )
+                       /* Failure to write shouldn't fail the build. */
+                       return;
+               buffer += amountWritten;
+               len -= amountWritten;
+       }
+}
+