]> git.saurik.com Git - apple/ld64.git/blobdiff - src/ld/Options.cpp
ld64-253.6.tar.gz
[apple/ld64.git] / src / ld / Options.cpp
index 3f5b054eca1e76c35fbaecec88e6ebdbe97d4973..8106e933614f1819569c08748e5e61f933f68b0d 100644 (file)
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <mach/vm_prot.h>
+#include <sys/sysctl.h>
 #include <mach-o/dyld.h>
 #include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <spawn.h>
+#include <cxxabi.h>
+#include <Availability.h>
 
 #include <vector>
+#include <map>
+#include <sstream>
 
-#include "configure.h"
 #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 {
@@ -43,16 +56,29 @@ namespace lto {
 
 // magic to place command line in crash reports
 const int crashreporterBufferSize = 2000;
-extern "C" char* __crashreporter_info__;
 static char crashreporterBuffer[crashreporterBufferSize];
-char* __crashreporter_info__ = crashreporterBuffer;
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
+       #include <CrashReporterClient.h>
+       // hack until ld does not need to build on 10.6 anymore
+    struct crashreporter_annotations_t gCRAnnotations 
+        __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION))) 
+        = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 };
+#else
+       extern "C" char* __crashreporter_info__;
+       __attribute__((used)) 
+       char* __crashreporter_info__ = crashreporterBuffer;
+#endif
+
 
 static bool                    sEmitWarnings = true;
+static bool                    sFatalWarnings = false;
 static const char*     sWarningsSideFilePath = NULL;
 static FILE*           sWarningsSideFile = NULL;
+static int                     sWarningsCount = 0;
 
 void warning(const char* format, ...)
 {
+       ++sWarningsCount;
        if ( sEmitWarnings ) {
                va_list list;
                if ( sWarningsSideFilePath != NULL ) {
@@ -85,12 +111,30 @@ void throwf(const char* format, ...)
        throw t;
 }
 
+
+bool Options::FileInfo::checkFileExists(const Options& options, const char *p)
+{
+       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);
+    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), 
          fInterposeMode(kInterposeNone), fDeadStrip(false), fNameSpace(kTwoLevelNameSpace),
-         fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL), fFinalName(NULL), fEntryName("start"), 
+         fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL), fFinalName(NULL), fEntryName(NULL), 
          fBaseAddress(0), fMaxAddress(0x7FFFFFFFFFFFFFFFLL), 
          fBaseWritableAddress(0), fSplitSegs(false),
          fExportMode(kExportDefault), fLibrarySearchMode(kSearchDylibAndArchiveInEachDir),
@@ -99,18 +143,18 @@ Options::Options(int argc, const char* argv[])
          fClientName(NULL),
          fUmbrellaName(NULL), fInitFunctionName(NULL), fDotOutputFile(NULL), fExecutablePath(NULL),
          fBundleLoader(NULL), fDtraceScriptName(NULL), fSegAddrTablePath(NULL), fMapPath(NULL), 
-         fDyldInstallPath("/usr/lib/dyld"), fTempLtoObjectPath(NULL), 
-         fZeroPageSize(ULLONG_MAX), fStackSize(0), fStackAddr(0), fExecutableStack(false), 
+         fDyldInstallPath("/usr/lib/dyld"), fTempLtoObjectPath(NULL), fOverridePathlibLTO(NULL), fLtoCpu(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), 
-         fUsingLazyDylibLinking(false), fEncryptable(true), 
+         fDeadStripDylibs(false),  fAllowTextRelocs(false), fWarnTextRelocs(false), fKextsUseStubs(false),
+         fUsingLazyDylibLinking(false), fEncryptable(true), fEncryptableForceOn(false), fEncryptableForceOff(false),
          fOrderData(true), fMarkDeadStrippableDylib(false),
          fMakeCompressedDyldInfo(true), fMakeCompressedDyldInfoForceOff(false), fNoEHLabels(false),
          fAllowCpuSubtypeMismatches(false), fUseSimplifiedDylibReExports(false),
@@ -128,10 +172,27 @@ Options::Options(int argc, const char* argv[])
          fVersionLoadCommand(false), fVersionLoadCommandForcedOn(false), 
          fVersionLoadCommandForcedOff(false), fFunctionStartsLoadCommand(false),
          fFunctionStartsForcedOn(false), fFunctionStartsForcedOff(false),
+         fDataInCodeInfoLoadCommand(false), fDataInCodeInfoLoadCommandForcedOn(false), fDataInCodeInfoLoadCommandForcedOff(false),
          fCanReExportSymbols(false), fObjcCategoryMerging(true), fPageAlignDataAtoms(false), 
-         fDebugInfoStripping(kDebugInfoMinimal), fTraceOutputFile(NULL), 
-         fMacVersionMin(ld::macVersionUnset), fIOSVersionMin(ld::iOSVersionUnset), 
-         fSaveTempFiles(false)
+         fNeedsThreadLoadCommand(false), fEntryPointLoadCommand(false),
+         fEntryPointLoadCommandForceOn(false), fEntryPointLoadCommandForceOff(false),
+         fSourceVersionLoadCommand(false), 
+         fSourceVersionLoadCommandForceOn(false), fSourceVersionLoadCommandForceOff(false), 
+         fTargetIOSSimulator(false), fExportDynamic(false), fAbsoluteSymbols(false),
+         fAllowSimulatorToLinkWithMacOSX(false), fKeepDwarfUnwind(true),
+         fKeepDwarfUnwindForcedOn(false), fKeepDwarfUnwindForcedOff(false),
+         fVerboseOptimizationHints(false), fIgnoreOptimizationHints(false),
+         fGenerateDtraceDOF(true), fAllowBranchIslands(true), fTraceSymbolLayout(false), 
+         fMarkAppExtensionSafe(false), fCheckAppExtensionSafe(false), fForceLoadSwiftLibs(false),
+         fSharedRegionEncodingV2(false), fUseDataConstSegment(false),
+         fUseDataConstSegmentForceOn(false), fUseDataConstSegmentForceOff(false),
+         fBundleBitcode(false), fHideSymbols(false), fVerifyBitcode(false),
+         fReverseMapUUIDRename(false), fReverseMapPath(NULL), fLTOCodegenOnly(false),
+         fIgnoreAutoLink(false), fAllowDeadDups(false), fBitcodeKind(kBitcodeProcess),
+         fPlatform(kPlatformUnknown), fDebugInfoStripping(kDebugInfoMinimal), fTraceOutputFile(NULL),
+         fMacVersionMin(ld::macVersionUnset), fIOSVersionMin(ld::iOSVersionUnset),
+         fSaveTempFiles(false), fSnapshotRequested(false), fPipelineFifo(NULL),
+         fDependencyInfoPath(NULL), fDependencyFileDescriptor(-1)
 {
        this->checkForClassic(argc, argv);
        this->parsePreCommandLineEnvironmentSettings();
@@ -139,13 +200,24 @@ Options::Options(int argc, const char* argv[])
        this->parsePostCommandLineEnvironmentSettings();
        this->reconfigureDefaults();
        this->checkIllegalOptionCombinations();
+       
+       if ( this->dumpDependencyInfo() ) {
+               this->dumpDependency(depOutputFile, fOutputFile);
+               if ( fMapPath != NULL ) 
+               this->dumpDependency(depOutputFile, fMapPath);
+       }
 }
 
 Options::~Options()
 {
+  if ( fDependencyFileDescriptor != -1 )
+       ::close(fDependencyFileDescriptor);
 }
 
-
+bool Options::errorBecauseOfWarnings() const
+{
+       return (sFatalWarnings && (sWarningsCount > 0));
+}
 
 
 const char*    Options::installPath() const
@@ -175,7 +247,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);
 }
 
 
@@ -205,7 +277,11 @@ bool Options::allGlobalsAreDeadStripRoots() const
        //
        switch ( fOutputKind ) {
                case Options::kDynamicExecutable:
+                       // <rdar://problem/12839986> Add the -export_dynamic flag 
+                       return fExportDynamic;
                case Options::kStaticExecutable:
+                       // <rdar://problem/13361218> Support the -export_dynamic flag for xnu
+                       return fExportDynamic;
                case Options::kPreload:
                        // by default unused globals in a main executable are stripped
                        return false;
@@ -235,7 +311,6 @@ const char* Options::executablePath()
        return fExecutablePath;
 }
 
-
 uint32_t Options::initialSegProtection(const char* segName) const
 {
        for(std::vector<Options::SegmentProtect>::const_iterator it = fCustomSegmentProtections.begin(); it != fCustomSegmentProtections.end(); ++it) {
@@ -260,7 +335,8 @@ uint32_t Options::initialSegProtection(const char* segName) const
 uint32_t Options::maxSegProtection(const char* segName) const
 {
        // iPhoneOS always uses same protection for max and initial
-       if ( fIOSVersionMin != ld::iOSVersionUnset ) 
+       // <rdar://problem/11663436> simulator apps need to use MacOSX max-prot
+       if ( (fPlatform != kPlatformOSX) && !fTargetIOSSimulator )
                return initialSegProtection(segName);
 
        for(std::vector<Options::SegmentProtect>::const_iterator it = fCustomSegmentProtections.begin(); it != fCustomSegmentProtections.end(); ++it) {
@@ -326,6 +402,17 @@ uint8_t Options::customSectionAlignment(const char* segName, const char* sectNam
        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()
 {
@@ -362,7 +449,7 @@ void Options::loadSymbolOrderFile(const char* fileOfExports, NameToOrder& orderM
 
        ::close(fd);
 
-       // parse into symbols and add to hash_set
+       // parse into symbols and add to unordered_set
        unsigned int count = 0;
        char * const end = &p[stat_buf.st_size];
        enum { lineStart, inSymbol, inComment } state = lineStart;
@@ -436,6 +523,11 @@ bool Options::forceNotWeakNonWildcard(const char* symbolName) const
        return fForceNotWeakSymbols.containsNonWildcard(symbolName);
 }
 
+bool Options::forceCoalesce(const char* symbolName) const
+{
+       return fForceCoalesceSymbols.contains(symbolName);
+}
+
 
 bool Options::shouldExport(const char* symbolName) const
 {
@@ -470,199 +562,125 @@ 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;
+}
+
+uint32_t Options::minOSversion() const
 {
-       fArchitecture = type;
-       fSubArchitecture = subtype;
-       switch ( type ) {
-       case CPU_TYPE_POWERPC:
-               switch ( subtype ) {
-               case CPU_SUBTYPE_POWERPC_750:
-                       fArchitectureName = "ppc750";
-                       fHasPreferredSubType = true;
-                       break;
-               case CPU_SUBTYPE_POWERPC_7400:
-                       fArchitectureName = "ppc7400";
-                       fHasPreferredSubType = true;
-                       break;
-               case CPU_SUBTYPE_POWERPC_7450:
-                       fArchitectureName = "ppc7450";
-                       fHasPreferredSubType = true;
-                       break;
-               case CPU_SUBTYPE_POWERPC_970:
-                       fArchitectureName = "ppc970";
-                       fHasPreferredSubType = true;
-                       break;
-               case CPU_SUBTYPE_POWERPC_ALL:
-                       fArchitectureName = "ppc";
-                       fHasPreferredSubType = false;
-                       break;
+       switch (fPlatform) {
+               case kPlatformiOS:
+                       return iOSVersionMin();
+               case kPlatformOSX:
+                       return macosxVersionMin();
+               case kPlatformWatchOS:
+                       return watchOSVersionMin();
+#if SUPPORT_APPLE_TV
+               case Options::kPlatform_tvOS:
+                       return iOSVersionMin();
+#endif
                default:
-                       assert(0 && "unknown ppc subtype");
-                       fArchitectureName = "ppc";
                        break;
-               }
-               if ( (fMacVersionMin == ld::macVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
-       #ifdef DEFAULT_MACOSX_MIN_VERSION
-                       warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION);
-                       setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
-       #else
-                       warning("-macosx_version_min not specificed, assuming 10.6");
-                       fMacVersionMin = ld::mac10_6;
-       #endif          
-               }
-               break;
-       case CPU_TYPE_POWERPC64:
-               fArchitectureName = "ppc64";
-               if ( (fMacVersionMin == ld::macVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
-                       warning("-macosx_version_min not specificed, assuming 10.5");
-                       fMacVersionMin = ld::mac10_5;
-               }
-               break;
-       case CPU_TYPE_I386:
-               fArchitectureName = "i386";
-               if ( (fMacVersionMin == ld::macVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
-       #ifdef DEFAULT_MACOSX_MIN_VERSION
-                       warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION);
-                       setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
-       #else
-                       warning("-macosx_version_min not specificed, assuming 10.6");
-                       fMacVersionMin = ld::mac10_6;
-       #endif          
-               }
-               if ( !fMakeCompressedDyldInfo && (fMacVersionMin >= ld::mac10_6) && !fMakeCompressedDyldInfoForceOff )
-                       fMakeCompressedDyldInfo = true;
-               break;
-       case CPU_TYPE_X86_64:
-               fArchitectureName = "x86_64";
-               if ( (fMacVersionMin == ld::macVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
-       #ifdef DEFAULT_MACOSX_MIN_VERSION
-                       warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION);
-                       setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
-       #else
-                       warning("-macosx_version_min not specificed, assuming 10.6");
-                       fMacVersionMin = ld::mac10_6;
-       #endif          
-               }
-               if ( !fMakeCompressedDyldInfo && (fMacVersionMin >= ld::mac10_6) && !fMakeCompressedDyldInfoForceOff )
-                       fMakeCompressedDyldInfo = true;
-               break;
-       case CPU_TYPE_ARM:
-               fHasPreferredSubType = true;
-               for (const ARMSubType* t=ARMSubTypes; t->subTypeName != NULL; ++t) {
-                       if ( t->subType == subtype ) {
-                               fArchitectureName = t->subTypeName;
-                               fArchSupportsThumb2 = t->supportsThumb2;
-                               break;
+       }
+       return 0;
+}
+
+void Options::setArchitecture(cpu_type_t type, cpu_subtype_t subtype, Options::Platform platform)
+{
+       for (const ArchInfo* t=archInfoArray; t->archName != NULL; ++t) {
+               if ( (type == t->cpuType) && (subtype == t->cpuSubType) ) {
+                       fArchitecture = type;
+                       fSubArchitecture = subtype;
+                       fArchitectureName = t->archName;
+                       fHasPreferredSubType = t->isSubType;
+                       fArchSupportsThumb2 = t->supportsThumb2;
+                       fPlatform = platform;
+                       switch ( type ) {
+                               case CPU_TYPE_I386:
+                               case CPU_TYPE_X86_64:
+                                       if ( (fPlatform == kPlatformOSX) && (fOutputKind != Options::kObjectFile) ) {
+                               #ifdef DEFAULT_MACOSX_MIN_VERSION
+                                               warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION);
+                                               setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
+                               #else
+                                               warning("-macosx_version_min not specified, assuming 10.6");
+                                               fMacVersionMin = ld::mac10_6;
+                               #endif          
+                                       }
+                                       break;
+                               case CPU_TYPE_ARM:
+                               case CPU_TYPE_ARM64:
+                                       if ( (fPlatform == kPlatformiOS) && (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);
+                               #else
+                                               warning("-ios_version_min not specified, assuming 6.0");
+                                               setIOSVersionMin("6.0");
+                               #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 )
+                               fMakeCompressedDyldInfo = true;
+                       // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
+                       if ( minOS(ld::mac10_5, ld::iOS_2_0) )
+                               fUseSimplifiedDylibReExports = true;
+                       return;
                }
-               assert(fArchitectureName != NULL);
-               if ( (fMacVersionMin == ld::macVersionUnset) && (fIOSVersionMin == ld::iOSVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
-#if defined(DEFAULT_IPHONEOS_MIN_VERSION)
-                       warning("-ios_version_min not specificed, assuming " DEFAULT_IPHONEOS_MIN_VERSION);
-                       setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION);
-#elif defined(DEFAULT_MACOSX_MIN_VERSION)
-                       warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION);
-                       setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
-#else
-                       warning("-macosx_version_min not specificed, assuming 10.6");
-                       fMacVersionMin = ld::mac10_6;
-#endif
-               }
-               if ( !fMakeCompressedDyldInfo && minOS(ld::mac10_6, ld::iOS_3_1) && !fMakeCompressedDyldInfoForceOff )
-                       fMakeCompressedDyldInfo = true;
-               break;
-       default:
-               fArchitectureName = "unknown architecture";
-               break;
        }
+       fArchitectureName = "unknown architecture";
+}
+
+bool Options::armUsesZeroCostExceptions() const
+{
+       return ( (fArchitecture == CPU_TYPE_ARM) && (fSubArchitecture == CPU_SUBTYPE_ARM_V7K) );
 }
 
 void Options::parseArch(const char* arch)
 {
        if ( arch == NULL )
                throw "-arch must be followed by an architecture string";
-       fArchitectureName = arch;
-       if ( strcmp(arch, "ppc") == 0 ) {
-               fArchitecture = CPU_TYPE_POWERPC;
-               fSubArchitecture = CPU_SUBTYPE_POWERPC_ALL;
-       }
-       else if ( strcmp(arch, "ppc64") == 0 ) {
-               fArchitecture = CPU_TYPE_POWERPC64;
-               fSubArchitecture = CPU_SUBTYPE_POWERPC_ALL;
-       }
-       else if ( strcmp(arch, "i386") == 0 ) {
-               fArchitecture = CPU_TYPE_I386;
-               fSubArchitecture = CPU_SUBTYPE_I386_ALL;
-       }
-       else if ( strcmp(arch, "x86_64") == 0 ) {
-               fArchitecture = CPU_TYPE_X86_64;
-               fSubArchitecture = CPU_SUBTYPE_X86_64_ALL;
-       }
-       else if ( strcmp(arch, "arm") == 0 ) {
-               fArchitecture = CPU_TYPE_ARM;
-               fSubArchitecture = CPU_SUBTYPE_ARM_ALL;
-       }
-       // compatibility support for cpu-sub-types
-       else if ( strcmp(arch, "ppc750") == 0 ) {
-               fArchitecture = CPU_TYPE_POWERPC;
-               fSubArchitecture = CPU_SUBTYPE_POWERPC_750;
-               fHasPreferredSubType = true;
-       }
-       else if ( strcmp(arch, "ppc7400") == 0 ) {
-               fArchitecture = CPU_TYPE_POWERPC;
-               fSubArchitecture = CPU_SUBTYPE_POWERPC_7400;
-               fHasPreferredSubType = true;
-       }
-       else if ( strcmp(arch, "ppc7450") == 0 ) {
-               fArchitecture = CPU_TYPE_POWERPC;
-               fSubArchitecture = CPU_SUBTYPE_POWERPC_7450;
-               fHasPreferredSubType = true;
-       }
-       else if ( strcmp(arch, "ppc970") == 0 ) {
-               fArchitecture = CPU_TYPE_POWERPC;
-               fSubArchitecture = CPU_SUBTYPE_POWERPC_970;
-               fHasPreferredSubType = true;
-       }
-       else {
-               for (const ARMSubType* t=ARMSubTypes; t->subTypeName != NULL; ++t) {
-                       if ( strcmp(t->subTypeName,arch) == 0 ) {
-                               fArchitecture = CPU_TYPE_ARM;
-                               fSubArchitecture = t->subType;
-                               fArchSupportsThumb2 = t->supportsThumb2;
-                               fHasPreferredSubType = true;
-                               return;
-                       }
+       for (const ArchInfo* t=archInfoArray; t->archName != NULL; ++t) {
+               if ( strcmp(t->archName,arch) == 0 ) {
+                       fArchitectureName = arch;
+                       fArchitecture = t->cpuType;
+                       fSubArchitecture = t->cpuSubType;
+                       fHasPreferredSubType = t->isSubType;
+                       fArchSupportsThumb2 = t->supportsThumb2;
+                       return;
                }
-               throwf("unknown/unsupported architecture name for: -arch %s", arch);
        }
+       throwf("unknown/unsupported architecture name for: -arch %s", arch);
 }
 
 bool Options::checkForFile(const char* format, const char* dir, const char* rootName, FileInfo& result) const
 {
-       struct stat statBuffer;
        char possiblePath[strlen(dir)+strlen(rootName)+strlen(format)+8];
        sprintf(possiblePath, format,  dir, rootName);
-       bool found = (stat(possiblePath, &statBuffer) == 0);
+       bool found = result.checkFileExists(*this, possiblePath);
        if ( fTraceDylibSearching )
                printf("[Logging for XBS]%sfound library: '%s'\n", (found ? " " : " not "), possiblePath);
-       if ( found ) {
-               result.path = strdup(possiblePath);
-               result.fileLen = statBuffer.st_size;
-               result.modTime = statBuffer.st_mtime;
-               return true;
-       }
-       return false;
+       return found;
 }
 
 
-Options::FileInfo Options::findLibrary(const char* rootName, bool dylibsOnly)
+Options::FileInfo Options::findLibrary(const char* rootName, bool dylibsOnly) const
 {
        FileInfo result;
        const int rootNameLen = strlen(rootName);
        // if rootName ends in .o there is no .a vs .dylib choice
        if ( (rootNameLen > 3) && (strcmp(&rootName[rootNameLen-2], ".o") == 0) ) {
-               for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
+               for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
                         it != fLibrarySearchPaths.end();
                         it++) {
                        const char* dir = *it;
@@ -671,19 +689,35 @@ Options::FileInfo Options::findLibrary(const char* rootName, bool dylibsOnly)
                }
        }
        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
                                if ( lookForDylibs ) {
-                                       for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
+                                       for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
                                                 it != fLibrarySearchPaths.end();
                                                 it++) {
                                                const char* dir = *it;
+                                               if ( checkForFile("%s/lib%s.tbd", dir, rootName, result) )
+                                                       return result;
                                                if ( checkForFile("%s/lib%s.dylib", dir, rootName, result) )
                                                        return result;
                                        }
-                                       for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
+                                       for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
                                                 it != fLibrarySearchPaths.end();
                                                 it++) {
                                                const char* dir = *it;
@@ -693,7 +727,7 @@ Options::FileInfo Options::findLibrary(const char* rootName, bool dylibsOnly)
                                }
                                // next look in all directories for just for archives
                                if ( !dylibsOnly ) {
-                                       for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
+                                       for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
                                                 it != fLibrarySearchPaths.end();
                                                 it++) {
                                                const char* dir = *it;
@@ -705,10 +739,12 @@ Options::FileInfo Options::findLibrary(const char* rootName, bool dylibsOnly)
 
                        case kSearchDylibAndArchiveInEachDir:
                                // look in each directory for just for a dylib then for an archive
-                               for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
+                               for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
                                         it != fLibrarySearchPaths.end();
                                         it++) {
                                        const char* dir = *it;
+                                       if ( lookForDylibs && checkForFile("%s/lib%s.tbd", dir, rootName, result) )
+                                               return result;
                                        if ( lookForDylibs && checkForFile("%s/lib%s.dylib", dir, rootName, result) )
                                                return result;
                                        if ( lookForDylibs && checkForFile("%s/lib%s.so", dir, rootName, result) )
@@ -722,7 +758,7 @@ Options::FileInfo Options::findLibrary(const char* rootName, bool dylibsOnly)
        throwf("library not found for -l%s", rootName);
 }
 
-Options::FileInfo Options::findFramework(const char* frameworkName)
+Options::FileInfo Options::findFramework(const char* frameworkName) const
 {
        if ( frameworkName == NULL )
                throw "-framework missing next argument";
@@ -738,38 +774,24 @@ Options::FileInfo Options::findFramework(const char* frameworkName)
        return findFramework(name, suffix);
 }
 
-Options::FileInfo Options::findFramework(const char* rootName, const char* suffix)
+Options::FileInfo Options::findFramework(const char* rootName, const char* suffix) const
 {
-       struct stat statBuffer;
-       for (std::vector<const char*>::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);
                }
-               bool found = (stat(possiblePath, &statBuffer) == 0);
+        FileInfo result;
+               bool found = result.checkFileExists(*this, (possiblePath + ".tbd").c_str());
+               if ( !found )
+                       found = result.checkFileExists(*this, possiblePath.c_str());
                if ( fTraceDylibSearching )
                        printf("[Logging for XBS]%sfound framework: '%s'\n",
-                                  (found ? " " : " not "), possiblePath);
+                                  (found ? " " : " not "), possiblePath.c_str());
                if ( found ) {
-                       FileInfo result;
-                       result.path = strdup(possiblePath);
-                       result.fileLen = statBuffer.st_size;
-                       result.modTime = statBuffer.st_mtime;
                        return result;
                }
        }
@@ -780,78 +802,84 @@ Options::FileInfo Options::findFramework(const char* rootName, const char* suffi
                throwf("framework not found %s", rootName);
 }
 
-Options::FileInfo Options::findFile(const char* path) const
+Options::FileInfo Options::findFile(const std::string &path) const
 {
        FileInfo result;
-       struct stat statBuffer;
 
-       // 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 ( stat(possiblePath, &statBuffer) == 0 ) {
-                               result.path = strdup(possiblePath);
-                               result.fileLen = statBuffer.st_size;
-                               result.modTime = statBuffer.st_mtime;
+       // if absolute path and not a .o file, then use SDK prefix
+       if ( (path[0] == '/') && (strcmp(&path[path.size()-2], ".o") != 0) ) {
+               auto tbdFile = path;
+               auto lastSlashIdx = tbdFile.find_last_of('/');
+               auto lastDotIdx = tbdFile.find_last_of('.');
+               if (lastDotIdx != std::string::npos && lastDotIdx > lastSlashIdx)
+                       tbdFile.erase(lastDotIdx, std::string::npos);
+               tbdFile.append(".tbd");
+
+               for (const auto* sdkPathDir : fSDKPaths) {
+                       auto possiblePath = std::string(sdkPathDir) + tbdFile;
+                       if ( result.checkFileExists(*this, possiblePath.c_str()) )
+                               return result;
+                       possiblePath = std::string(sdkPathDir) + path;
+                       if ( result.checkFileExists(*this, possiblePath.c_str()) )
                                return result;
-                       }
                }
        }
        // try raw path
-       if ( stat(path, &statBuffer) == 0 ) {
-               result.path = strdup(path);
-               result.fileLen = statBuffer.st_size;
-               result.modTime = statBuffer.st_mtime;
+       {
+               std::string file = path;
+               auto lastDotIdx = file.find_last_of('.');
+               if (lastDotIdx != std::string::npos)
+                       file.erase(lastDotIdx, std::string::npos);
+               if ( result.checkFileExists(*this, file.append(".tbd").c_str()) )
+                       return result;
+       }
+       if ( result.checkFileExists(*this, path.c_str()) ) {
                return result;
        }
 
+
        // try @executable_path substitution
-       if ( (strncmp(path, "@executable_path/", 17) == 0) && (fExecutablePath != NULL) ) {
-               char newPath[strlen(fExecutablePath) + strlen(path)];
+       if ( (path.find("@executable_path/") == 0) && (fExecutablePath != nullptr) ) {
+               char newPath[strlen(fExecutablePath) + path.size()];
                strcpy(newPath, fExecutablePath);
                char* addPoint = strrchr(newPath,'/');
-               if ( addPoint != NULL )
+               if ( addPoint != nullptr )
                        strcpy(&addPoint[1], &path[17]);
                else
                        strcpy(newPath, &path[17]);
-               if ( stat(newPath, &statBuffer) == 0 ) {
-                       result.path = strdup(newPath);
-                       result.fileLen = statBuffer.st_size;
-                       result.modTime = statBuffer.st_mtime;
+
+               std::string file = newPath;
+               auto lastDotIdx = file.find_last_of('.');
+               if (lastDotIdx != std::string::npos)
+                       file.erase(lastDotIdx, std::string::npos);
+               if ( result.checkFileExists(*this, file.append(".tbd").c_str()) ) {
+                       return result;
+               }
+               if ( result.checkFileExists(*this, newPath) ) {
                        return result;
                }
        }
 
        // not found
-       throwf("file not found: %s", path);
+       throwf("file not found: %s", path.c_str());
 }
 
-Options::FileInfo Options::findFileUsingPaths(const char* path) const 
+Options::FileInfo Options::findFileUsingPaths(const std::string &path) const
 {
        FileInfo result;
 
-       const char* lastSlash = strrchr(path, '/');
-       const char* leafName = (lastSlash == NULL) ? path : &lastSlash[1];
+       auto lastSlashPos = path.find_last_of('/');
+       auto pos = ( lastSlashPos != std::string::npos ) ? lastSlashPos + 1 : 0;
+       auto leafName = path.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 ( path.rfind(frameworkDir) != std::string::npos )
                        isFramework = true;
        }
        
@@ -860,35 +888,28 @@ 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 = path.rfind(".framework");
+               auto beginPos = path.find_last_of('/', endPos);
+               auto leafPath = path.substr(beginPos);
+               for (const auto* dir : fFrameworkSearchPaths) {
+                       auto possiblePath = dir + leafPath;
+                       if ( checkForFile("%s.%s", possiblePath.c_str(), "tbd", result) )
+                               return result;
+                       if ( checkForFile("%s", possiblePath.c_str(), "", 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)
+                                       && (path.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) )
+                               if ( checkForFile("%s/%s", dir, std::string(leafName).append(".tbd").c_str(), result) )
+                                       return result;
+                               if ( checkForFile("%s/%s", dir, leafName.c_str(), result) )
                                        return result;
                        }
                }
@@ -897,7 +918,8 @@ Options::FileInfo Options::findFileUsingPaths(const char* path) const
        // If we didn't find it fall back to findFile.
        return findFile(path);
 }
+
+
 
 void Options::parseSegAddrTable(const char* segAddrPath, const char* installPth)
 {
@@ -951,7 +973,7 @@ void Options::parseSegAddrTable(const char* segAddrPath, const char* installPth)
        fclose(file);
 }
 
-void Options::loadFileList(const char* fileOfPaths)
+void Options::loadFileList(const char* fileOfPaths, ld::File::Ordinal baseOrdinal)
 {
        FILE* file;
        const char* comma = strrchr(fileOfPaths, ',');
@@ -967,16 +989,21 @@ void Options::loadFileList(const char* fileOfPaths)
                        realFileOfPaths[realFileOfPathsLen] = '\0';
                        file = fopen(realFileOfPaths, "r");
                        if ( file == NULL )
-                               throwf("-filelist file not found: %s\n", realFileOfPaths);
+                               throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", realFileOfPaths, errno, strerror(errno));
+                       if ( this->dumpDependencyInfo() )
+                               this->dumpDependency(Options::depFileList, realFileOfPaths);
                }
        }
        else {
                file = fopen(fileOfPaths, "r");
                if ( file == NULL )
-                       throwf("-filelist file not found: %s\n", fileOfPaths);
+                       throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", fileOfPaths, errno, strerror(errno));
+               if ( this->dumpDependencyInfo() )
+                       this->dumpDependency(Options::depFileList, fileOfPaths);
        }
 
        char path[PATH_MAX];
+       ld::File::Ordinal previousOrdinal = baseOrdinal;
        while ( fgets(path, PATH_MAX, file) != NULL ) {
                path[PATH_MAX-1] = '\0';
                char* eol = strchr(path, '\n');
@@ -987,10 +1014,34 @@ void Options::loadFileList(const char* fileOfPaths)
                        strcpy(builtPath, prefix);
                        strcat(builtPath, "/");
                        strcat(builtPath, path);
-                       fInputFiles.push_back(findFile(builtPath));
+           if (fPipelineFifo != NULL) {
+                          FileInfo info = FileInfo(builtPath);
+                          info.ordinal = previousOrdinal.nextFileListOrdinal();
+                          previousOrdinal = info.ordinal;
+                          info.fromFileList = true;
+              fInputFiles.push_back(info);
+           } else {
+                          FileInfo info = findFile(builtPath);
+                          info.ordinal = previousOrdinal.nextFileListOrdinal();
+                          previousOrdinal = info.ordinal;
+                          info.fromFileList = true;
+                          fInputFiles.push_back(info);
+           }
                }
                else {
-                       fInputFiles.push_back(findFile(path));
+           if (fPipelineFifo != NULL) {
+                          FileInfo info = FileInfo(path);
+                          info.ordinal = previousOrdinal.nextFileListOrdinal();
+                          previousOrdinal = info.ordinal;
+                          info.fromFileList = true;
+                          fInputFiles.push_back(info);
+           } else {
+                          FileInfo info = findFile(path);
+                          info.ordinal = previousOrdinal.nextFileListOrdinal();
+                          previousOrdinal = info.ordinal;
+                          info.fromFileList = true;
+                          fInputFiles.push_back(info);
+           }
                }
        }
        fclose(file);
@@ -1021,19 +1072,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
@@ -1041,6 +1113,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
 {
@@ -1121,9 +1210,12 @@ 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);
+
        ::close(fd);
 
-       // parse into symbols and add to hash_set
+       // parse into symbols and add to unordered_set
        char * const end = &p[stat_buf.st_size];
        enum { lineStart, inSymbol, inComment } state = lineStart;
        char* symbolStart = NULL;
@@ -1192,6 +1284,8 @@ 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);
 
        // parse into symbols and add to fAliases
        AliasPair pair;
@@ -1305,8 +1399,16 @@ void Options::setMacOSXVersionMin(const char* version)
                throw "-macosx_version_min argument missing";
 
        if ( (strncmp(version, "10.", 3) == 0) && isdigit(version[3]) ) {
-               unsigned int minorVersion = version[3] - '0';
+               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;
+               }
                fMacVersionMin = (ld::MacVersionMin)(0x000A0000 | (minorVersion << 8));
+               fPlatform = kPlatformOSX;
        }
        else {
                warning("unknown option to -macosx_version_min, not 10.x");
@@ -1327,18 +1429,52 @@ void Options::setIOSVersionMin(const char* version)
        unsigned int majorVersion = version[0] - '0';
        unsigned int minorVersion = version[2] - '0';
        fIOSVersionMin = (ld::IOSVersionMin)((majorVersion << 16) | (minorVersion << 8));
+       fPlatform = kPlatformiOS;
+}
+
+
+void Options::setWatchOSVersionMin(const char* version)
+{
+       if ( version == NULL )
+               throw "-watchos_version_min argument missing";
+       if ( ! isdigit(version[0]) )
+               throw "-watchos_version_min argument is not a number";
+       if ( version[1] != '.' )
+               throw "-watchos_version_min argument is missing period as second character";
+       if ( ! isdigit(version[2]) )
+               throw "-watchos_version_min argument is not a number";
+
+       unsigned int majorVersion = version[0] - '0';
+       unsigned int minorVersion = version[2] - '0';
+       fWatchOSVersionMin = (ld::WatchOSVersionMin)((majorVersion << 16) | (minorVersion << 8));
+       fPlatform = kPlatformWatchOS;
 }
 
+
 bool Options::minOS(ld::MacVersionMin requiredMacMin, ld::IOSVersionMin requirediPhoneOSMin)
 {
        if ( fMacVersionMin != ld::macVersionUnset ) {
                return ( fMacVersionMin >= requiredMacMin );
        }
+       else if ( fWatchOSVersionMin != ld::wOSVersionUnset ) {
+               // Hack until we fully track watch and ios versions seperately
+               return ( (fWatchOSVersionMin + 0x00070000) >= requirediPhoneOSMin);
+       }
        else {
-               return ( fIOSVersionMin >= requirediPhoneOSMin);
+               return ( fIOSVersionMin >= requirediPhoneOSMin );
        }
 }
 
+bool Options::min_iOS(ld::IOSVersionMin requirediOSMin)
+{
+        if ( fWatchOSVersionMin != ld::wOSVersionUnset ) {
+               // Hack until we fully track watch and ios versions seperately
+               return ( (fWatchOSVersionMin + 0x00070000) >= requirediOSMin);
+       }
+       else {
+               return ( fIOSVersionMin >= requirediOSMin );
+       }
+}
 
 void Options::setWeakReferenceMismatchTreatment(const char* treatment)
 {
@@ -1418,16 +1554,67 @@ uint32_t Options::parseProtection(const char* prot)
 }
 
 
+//
+// Parses number of form A[.B[.B[.D[.E]]]] into a uint64_t where the bits are a24.b10.c10.d10.e10
+//
+uint64_t Options::parseVersionNumber64(const char* versionString)
+{
+       uint64_t a = 0;
+       uint64_t b = 0;
+       uint64_t c = 0;
+       uint64_t d = 0;
+       uint64_t e = 0;
+       char* end;
+       a = strtoul(versionString, &end, 10);
+       if ( *end == '.' ) {
+               b = strtoul(&end[1], &end, 10);
+               if ( *end == '.' ) {
+                       c = strtoul(&end[1], &end, 10);
+                       if ( *end == '.' ) {
+                               d = strtoul(&end[1], &end, 10);
+                               if ( *end == '.' ) {
+                                       e = strtoul(&end[1], &end, 10);
+                               }
+                       }
+               }
+       }
+       if ( (*end != '\0') || (a > 0xFFFFFF) || (b > 0x3FF) || (c > 0x3FF) || (d > 0x3FF)  || (e > 0x3FF) )
+               throwf("malformed 64-bit a.b.c.d.e version number: %s", versionString);
+
+       return (a << 40) | ( b << 30 ) | ( c << 20 ) | ( d << 10 ) | e;
+}
+
+
+uint32_t Options::currentVersion32() const
+{
+       // warn if it does not fit into 32 bit vers number
+       uint32_t a = (fDylibCurrentVersion >> 40) & 0xFFFF;
+       uint32_t b = (fDylibCurrentVersion >> 30) & 0xFF;
+       uint32_t c = (fDylibCurrentVersion >> 20) & 0xFF;
+       uint64_t rep32 = ((uint64_t)a << 40) |  ((uint64_t)b << 30) | ((uint64_t)c << 20);
+       if ( rep32 != fDylibCurrentVersion ) {
+               warning("truncating -current_version to fit in 32-bit space used by old mach-o format");
+               a = (fDylibCurrentVersion >> 40) & 0xFFFFFF;            
+               if ( a > 0xFFFF )
+                       a = 0xFFFF;
+               b = (fDylibCurrentVersion >> 30) & 0x3FF;
+               if ( b > 0xFF )
+                       b = 0xFF;
+               c = (fDylibCurrentVersion >> 20) & 0x3FF;
+               if ( c > 0xFF )
+                       c = 0xFF;
+       }
+       return (a << 16) | ( b << 8 ) | c;
+}
 
 //
 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
 //
-//
-uint32_t Options::parseVersionNumber(const char* versionString)
+uint32_t Options::parseVersionNumber32(const char* versionString)
 {
-       unsigned long x = 0;
-       unsigned long y = 0;
-       unsigned long z = 0;
+       uint32_t x = 0;
+       uint32_t y = 0;
+       uint32_t z = 0;
        char* end;
        x = strtoul(versionString, &end, 10);
        if ( *end == '.' ) {
@@ -1437,7 +1624,7 @@ uint32_t Options::parseVersionNumber(const char* versionString)
                }
        }
        if ( (*end != '\0') || (x > 0xffff) || (y > 0xff) || (z > 0xff) )
-               throwf("malformed version number: %s", versionString);
+               throwf("malformed 32-bit x.y.z version number: %s", versionString);
 
        return (x << 16) | ( y << 8 ) | z;
 }
@@ -1539,6 +1726,8 @@ 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);
 
        // parse into vector of pairs
        char * const end = &p[stat_buf.st_size+1];
@@ -1565,18 +1754,12 @@ void Options::parseOrderFile(const char* path, bool cstring)
                                        *last = '\0';
                                        --last;
                                }
+                               // if there is an architecture prefix, only use this symbol it if matches current arch
                                if ( strncmp(symbolStart, "ppc:", 4) == 0 ) {
-                                       if ( fArchitecture == CPU_TYPE_POWERPC )
-                                               symbolStart = &symbolStart[4];
-                                       else
-                                               symbolStart = NULL;
+                                       symbolStart = NULL;
                                }
-                               // if there is an architecture prefix, only use this symbol it if matches current arch
                                else if ( strncmp(symbolStart, "ppc64:", 6) == 0 ) {
-                                       if ( fArchitecture == CPU_TYPE_POWERPC64 )
-                                               symbolStart = &symbolStart[6];
-                                       else
-                                               symbolStart = NULL;
+                                       symbolStart = NULL;
                                }
                                else if ( strncmp(symbolStart, "i386:", 5) == 0 ) {
                                        if ( fArchitecture == CPU_TYPE_I386 )
@@ -1604,6 +1787,14 @@ void Options::parseOrderFile(const char* path, bool cstring)
                                                objFileName = symbolStart;
                                                symbolStart = &colon[3];
                                        }
+                                       else {
+                                               colon = strstr(symbolStart, ".o):");
+                                               if ( colon != NULL ) {
+                                                       colon[3] = '\0';
+                                                       objFileName = symbolStart;
+                                                       symbolStart = &colon[4];
+                                               }
+                                       }
                                        // trim leading spaces
                                        while ( isspace(*symbolStart) ) 
                                                ++symbolStart;
@@ -1670,10 +1861,84 @@ 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::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 )
@@ -1725,7 +1990,188 @@ 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();
+}
+
+std::string Options::getVersionString64(uint64_t ver) const
+{
+       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();
+}
+
+std::string Options::getSDKVersionStr() const
+{
+       return getVersionString32(fSDKVersion);
+}
+
+std::string Options::getPlatformStr() const
+{
+       switch (fPlatform) {
+               case Options::kPlatformOSX:
+                       return "MacOSX";
+               case Options::kPlatformiOS:
+                       if (targetIOSSimulator())
+                               return "iPhoneSimulator";
+                       else
+                               return "iPhoneOS";
+               case Options::kPlatformWatchOS:
+                       if (targetIOSSimulator())
+                               return "watchOS Simulator";
+                       else
+                               return "watchOS";
+#if SUPPORT_APPLE_TV
+               case Options::kPlatform_tvOS:
+                       if (targetIOSSimulator())
+                               return "AppleTVSimulator";
+                       else
+                               return "AppleTVOS";
+                       break;
+#endif
+               case Options::kPlatformUnknown:
+                       return "Unknown";
+       }
+}
+
+std::vector<std::string> Options::writeBitcodeLinkOptions() const
+{
+       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".
+       switch (fPlatform) {
+               case Options::kPlatformOSX:
+                       linkCommand.push_back("-macosx_version_min");
+                       linkCommand.push_back(getVersionString32((unsigned)fMacVersionMin));
+                       break;
+               case Options::kPlatformiOS:
+                       if (targetIOSSimulator())
+                               linkCommand.push_back("-ios_simulator_version_min");
+                       else
+                               linkCommand.push_back("-ios_version_min");
+                       linkCommand.push_back(getVersionString32((unsigned)fIOSVersionMin));
+                       break;
+               case Options::kPlatformWatchOS:
+                       if (targetIOSSimulator())
+                               linkCommand.push_back("-watchos_simulator_version_min");
+                       else
+                               linkCommand.push_back("-watchos_version_min");
+                       linkCommand.push_back(getVersionString32((unsigned)fIOSVersionMin));
+                       break;
+#if SUPPORT_APPLE_TV
+               case Options::kPlatform_tvOS:
+                       if (targetIOSSimulator())
+                               linkCommand.push_back("-tvos_simulator_version_min");
+                       else
+                               linkCommand.push_back("-tvos_version_min");
+                       linkCommand.push_back(getVersionString32((unsigned)fIOSVersionMin));
+                       break;
+#endif
+               case Options::kPlatformUnknown:
+                       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;
+}
 
 //
 // Process all command line arguments.
@@ -1740,6 +2186,9 @@ void Options::warnObsolete(const char* arg)
 //
 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);
 
@@ -1751,12 +2200,17 @@ void Options::parse(int argc, const char* argv[])
                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()
@@ -1779,15 +2233,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 )
@@ -1795,47 +2252,69 @@ 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, "-o") == 0 ) {
+                snapshotArgCount = 0;
                                fOutputFile = argv[++i];
+                fLinkSnapshot.setSnapshotName(fOutputFile);
                        }
                        else if ( strncmp(arg, "-lazy-l", 7) == 0 ) {
+                snapshotArgCount = 0;
                                FileInfo info = findLibrary(&arg[7], true);
                                info.options.fLazyLoad = true;
+                               info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
                                addLibrary(info);
                                fUsingLazyDylibLinking = true;
+                               cannotBeUsedWithBitcode(arg);
+                       }
+                       else if ( strcmp(arg, "-lto_library") == 0 ) {
+                snapshotFileArgIndex = 1;
+                               fOverridePathlibLTO = argv[++i];
+                               if ( fOverridePathlibLTO == NULL )
+                                       throw "missing argument to -lto_library";
                        }
                        else if ( (arg[1] == 'l') && (strncmp(arg,"-lazy_",6) !=0) ) {
-                               addLibrary(findLibrary(&arg[2]));
+                snapshotArgCount = 0;
+                               FileInfo info = findLibrary(&arg[2]);
+                               info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
+                               addLibrary(info);
                        }
                        // This causes a dylib to be weakly bound at
                        // link time.  This corresponds to weak_import.
                        else if ( strncmp(arg, "-weak-l", 7) == 0 ) {
+                // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
+                snapshotArgCount = 0;
                                FileInfo info = findLibrary(&arg[7]);
                                info.options.fWeakImport = true;
+                               info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
                                addLibrary(info);
                        }
                        // 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 ) {
@@ -1852,6 +2331,7 @@ void Options::parse(int argc, const char* argv[])
                        else if ( strcmp(arg, "-force_load") == 0 ) {
                                FileInfo info = findFile(argv[++i]);
                                info.options.fForceLoad = true;
+                               info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
                                addLibrary(info);
                        }
                        // Library versioning.
@@ -1860,32 +2340,38 @@ void Options::parse(int argc, const char* argv[])
                                 const char* vers = argv[++i];
                                 if ( vers == NULL )
                                        throw "-dylib_compatibility_version missing <version>";
-                               fDylibCompatVersion = parseVersionNumber(vers);
+                               fDylibCompatVersion = parseVersionNumber32(vers);
                        }
                        else if ( (strcmp(arg, "-dylib_current_version") == 0)
                                          || (strcmp(arg, "-current_version") == 0)) {
                                 const char* vers = argv[++i];
                                 if ( vers == NULL )
                                        throw "-dylib_current_version missing <version>";
-                               fDylibCurrentVersion = parseVersionNumber(vers);
+                               fDylibCurrentVersion = parseVersionNumber64(vers);
                        }
                        else if ( strcmp(arg, "-sectorder") == 0 ) {
                                 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
                                        throw "-sectorder missing <segment> <section> <file-path>";
+                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;
                                parseOrderFile(argv[++i], false);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-order_file_statistics") == 0 ) {
                                fPrintOrderFileStatistics = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        // ??? Deprecate segcreate.
                        // -sectcreate puts whole files into a section in the output.
                        else if ( (strcmp(arg, "-sectcreate") == 0) || (strcmp(arg, "-segcreate") == 0) ) {
                                 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
                                        throw "-sectcreate missing <segment> <section> <file-path>";
+                snapshotFileArgIndex = 3;
                                addSection(argv[i+1], argv[i+2], argv[i+3]);
                                i += 3;
                        }
@@ -1894,7 +2380,7 @@ void Options::parse(int argc, const char* argv[])
                                          || (strcmp(arg, "-dylinker_install_name") == 0)
                                          || (strcmp(arg, "-install_name") == 0)) {
                                fDylibInstallName = argv[++i];
-                                if ( fDylibInstallName == NULL )
+                if ( fDylibInstallName == NULL )
                                        throw "-install_name missing <path>";
                        }
                        // Sets the base address of the output.
@@ -1908,19 +2394,23 @@ 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];
                        }
                        // Same as -@ from the FSF linker.
                        else if ( strcmp(arg, "-filelist") == 0 ) {
+                 snapshotArgCount = 0;
                                 const char* path = argv[++i];
                                 if ( (path == NULL) || (path[0] == '-') )
                                        throw "-filelist missing <path>";
-                                loadFileList(path);
+                                ld::File::Ordinal baseOrdinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
+                                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];
@@ -1937,26 +2427,32 @@ 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 ) {
                                fInterposeMode = kInterposeNone;
                        }
                        else if ( strcmp(arg, "-exported_symbols_list") == 0 ) {
+                snapshotFileArgIndex = 1;
                                if ( fExportMode == kDontExportSome )
                                        throw "can't use -exported_symbols_list and -unexported_symbols_list";
                                fExportMode = kExportSome;
                                loadExportFile(argv[++i], "-exported_symbols_list", fExportSymbols);
                        }
                        else if ( strcmp(arg, "-unexported_symbols_list") == 0 ) {
+                snapshotFileArgIndex = 1;
                                if ( fExportMode == kExportSome )
                                        throw "can't use -unexported_symbols_list and -exported_symbols_list";
                                fExportMode = kDontExportSome;
                                loadExportFile(argv[++i], "-unexported_symbols_list", fDontExportSymbols);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-exported_symbol") == 0 ) {
                                if ( fExportMode == kDontExportSome )
@@ -1969,18 +2465,23 @@ void Options::parse(int argc, const char* argv[])
                                        throw "can't use -unexported_symbol and -exported_symbol";
                                fExportMode = kDontExportSome;
                                fDontExportSymbols.insert(argv[++i]);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-non_global_symbols_no_strip_list") == 0 ) {
+                snapshotFileArgIndex = 1;
                                if ( fLocalSymbolHandling == kLocalSymbolsSelectiveExclude )
                                        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;
                                if ( fLocalSymbolHandling == kLocalSymbolsSelectiveInclude )
                                        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 ) {
@@ -1989,32 +2490,51 @@ 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]);
                                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]);
                                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 ) {
-                               addLibrary(findFramework(argv[++i]));
+                snapshotArgCount = 0;
+                               FileInfo info = findFramework(argv[++i]);
+                               info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
+                               addLibrary(info);
                        }
                        else if ( strcmp(arg, "-weak_framework") == 0 ) {
+                // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
+                snapshotArgCount = 0;
                                FileInfo info = findFramework(argv[++i]);
                                info.options.fWeakImport = true;
+                               info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
                                addLibrary(info);
                        }
                        else if ( strcmp(arg, "-lazy_framework") == 0 ) {
+                // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
+                snapshotArgCount = 0;
                                FileInfo info = findFramework(argv[++i]);
                                info.options.fLazyLoad = true;
+                               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()
@@ -2023,7 +2543,8 @@ void Options::parse(int argc, const char* argv[])
                                // previously handled by buildSearchPaths()
                        }
                        else if ( strcmp(arg, "-undefined") == 0 ) {
-                                setUndefinedTreatment(argv[++i]);
+                setUndefinedTreatment(argv[++i]);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        // Debugging output flag.
                        else if ( strcmp(arg, "-arch_multiple") == 0 ) {
@@ -2041,10 +2562,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;
@@ -2059,7 +2582,7 @@ void Options::parse(int argc, const char* argv[])
                        // Warn, error or make strong a mismatch between weak
                        // and non-weak references.
                        else if ( strcmp(arg, "-weak_reference_mismatches") == 0 ) {
-                                setWeakReferenceMismatchTreatment(argv[++i]);
+                setWeakReferenceMismatchTreatment(argv[++i]);
                        }
                        // For a deployment target of 10.3 and earlier ld64 will
                        // prebind an executable with 0s in all addresses that
@@ -2067,6 +2590,7 @@ void Options::parse(int argc, const char* argv[])
                        // later.  Prebinding is less useful on 10.4 and greater.
                        else if ( strcmp(arg, "-prebind") == 0 ) {
                                fPrebind = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-noprebind") == 0 ) {
                                warnObsolete(arg);
@@ -2087,7 +2611,10 @@ void Options::parse(int argc, const char* argv[])
                        // This should probably be deprecated when we respect -L and -F
                        // when searching for libraries.
                        else if ( strcmp(arg, "-dylib_file") == 0 ) {
+                // 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 ) {
@@ -2118,6 +2645,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.
@@ -2127,26 +2655,31 @@ void Options::parse(int argc, const char* argv[])
                                 if ( (seg.name == NULL) || (argv[i+1] == NULL) )
                                        throw "-segaddr missing segName Adddress";
                                seg.address = parseAddress(argv[++i]);
-                               uint64_t temp = seg.address & (-4096); // page align
-                               if ( (seg.address != temp)  )
-                                       warning("-segaddr %s not page aligned, rounding down", seg.name);
+                               uint64_t temp = ((seg.address+fSegmentAlignment-1) & (-fSegmentAlignment)); 
+                               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]);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        // ??? Deprecate when we deprecate split-seg.
                        else if ( strcmp(arg, "-segs_read_write_addr") == 0 ) {
                                fBaseWritableAddress = parseAddress(argv[++i]);
                                fSplitSegs = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        // ??? Deprecate when we get rid of basing at build time.
                        else if ( strcmp(arg, "-seg_addr_table") == 0 ) {
+                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);
@@ -2160,6 +2693,7 @@ void Options::parse(int argc, const char* argv[])
                                seg.max = parseProtection(argv[++i]);
                                seg.init = parseProtection(argv[++i]);
                                fCustomSegmentProtections.push_back(seg);
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-pagezero_size") == 0 ) {
                                 const char* size = argv[++i];
@@ -2170,12 +2704,14 @@ 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];
@@ -2188,15 +2724,18 @@ void Options::parse(int argc, const char* argv[])
                        }
                        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);
@@ -2206,10 +2745,12 @@ void Options::parse(int argc, const char* argv[])
                                i += 2;
                        }
                        else if ( strcmp(arg, "-bundle_loader") == 0 ) {
+                snapshotFileArgIndex = 1;
                                fBundleLoader = argv[++i];
                                if ( (fBundleLoader == NULL) || (fBundleLoader[0] == '-') )
                                        throw "-bundle_loader missing <path>";
                                FileInfo info = findFile(fBundleLoader);
+                               info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
                                info.options.fBundleLoader = true;
                                fInputFiles.push_back(info);
                        }
@@ -2221,14 +2762,53 @@ 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 ) {
-                               setMacOSXVersionMin(argv[++i]);
+                               const char* macVers = argv[++i];
+                               const char* envMacVers = getenv("MACOSX_DEPLOYMENT_TARGET");
+                               const char* enviPhoneVers = getenv("IPHONEOS_DEPLOYMENT_TARGET");
+                               if ( (envMacVers != NULL) && (enviPhoneVers != NULL) ) {
+                                       // <rdar://problem/13774329> when conflicting deployments set, break tie by looking at syslibroot
+                                       warning("both MACOSX_DEPLOYMENT_TARGET and IPHONEOS_DEPLOYMENT_TARGET are set");
+                                       if ( !fSDKPaths.empty() ) {
+                                               const char* sysrootPath = fSDKPaths.back();
+                                               const char* lastSlash = strrchr(sysrootPath, '/');
+                                               if ( strstr(lastSlash, "Simulator") != NULL ) 
+                                                       setIOSVersionMin(enviPhoneVers);
+                                               else
+                                                       setMacOSXVersionMin(macVers);
+                                       }
+                                       else {
+                                               setMacOSXVersionMin(macVers);
+                                       }
+                               }
+                               else {
+                                       setMacOSXVersionMin(macVers);
+                               }
                        }
                        else if ( (strcmp(arg, "-ios_version_min") == 0) || (strcmp(arg, "-iphoneos_version_min") == 0) ) {
                                setIOSVersionMin(argv[++i]); 
                        }
                        else if ( strcmp(arg, "-ios_simulator_version_min") == 0 ) {
                                setIOSVersionMin(argv[++i]);
+                               fTargetIOSSimulator = true;
+                       }
+                       else if ( strcmp(arg, "-watchos_version_min") == 0 ) {
+                               setWatchOSVersionMin(argv[++i]);
+                       }
+                       else if ( strcmp(arg, "-watchos_simulator_version_min") == 0 ) {
+                               setWatchOSVersionMin(argv[++i]);
+                               fTargetIOSSimulator = true;
+                       }
+       #if SUPPORT_APPLE_TV
+                       else if ( strcmp(arg, "-tvos_version_min") == 0 ) {
+                               setIOSVersionMin(argv[++i]);
+                               fPlatform = kPlatform_tvOS;
                        }
+                       else if ( strcmp(arg, "-tvos_simulator_version_min") == 0 ) {
+                               setIOSVersionMin(argv[++i]);
+                               fPlatform = kPlatform_tvOS;
+                               fTargetIOSSimulator = true;
+                       }
+       #endif
                        else if ( strcmp(arg, "-multiply_defined") == 0 ) {
                                //warnObsolete(arg);
                                ++i;
@@ -2269,12 +2849,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);
@@ -2313,6 +2895,9 @@ void Options::parse(int argc, const char* argv[])
                        else if ( strcmp(arg, "-w") == 0 ) {
                                // previously handled by buildSearchPaths()
                        }
+                       else if ( strcmp(arg, "-fatal_warnings") == 0 ) {
+                               // previously handled by buildSearchPaths()
+                       }
                        else if ( strcmp(arg, "-arch_errors_fatal") == 0 ) {
                                fErrorOnOtherArchFiles = true;
                        }
@@ -2324,9 +2909,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;
@@ -2343,6 +2934,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];
@@ -2351,6 +2943,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];
@@ -2359,30 +2952,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;
@@ -2412,20 +3010,29 @@ void Options::parse(int argc, const char* argv[])
                                // previously handled by buildSearchPaths()
                        }
                        else if ( strcmp(arg, "-syslibroot") == 0 ) {
+                snapshotArgCount = 0;
                                ++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;
                                const char* name = argv[++i];
                                if ( name == NULL )
                                        throw "-dtrace missing argument";
                                fDtraceScriptName = name;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-root_safe") == 0 ) {
                                fRootSafe = true;
@@ -2442,25 +3049,68 @@ void Options::parse(int argc, const char* argv[])
                                if ( pair.alias == NULL )
                                        throw "missing argument to -alias";
                                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;
+                               if ( !fBundleBitcode )
+                                       warning("-bitcode_hide_symbols is ignored without -bitcode_bundle");
+                       }
+                       else if ( strcmp(arg, "-bitcode_verify") == 0 ) {
+                               fVerifyBitcode = true;
+                               if ( !fBundleBitcode )
+                                       warning("-bitcode_verify is ignored without -bitcode_bundle");
+                       }
+                       else if ( strcmp(arg, "-bitcode_symbol_map") == 0) {
+                               fReverseMapPath = argv[++i];
+                               if ( fReverseMapPath == NULL )
+                                       throw "missing argument to -bitcode_symbol_map";
+                               struct stat statbuf;
+                               ::stat(fReverseMapPath, &statbuf);
+                               if (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(argv[i], "-flto-codegen-only") == 0) {
+                               fLTOCodegenOnly = true;
+                       }
+                       else if ( strcmp(argv[i], "-ignore_auto_link") == 0) {
+                               fIgnoreAutoLink = true;
+                       }
+                       else if ( strcmp(argv[i], "-allow_dead_duplicates") == 0) {
+                               fAllowDeadDups = true;
+                       }
+                       else if ( strcmp(argv[i], "-bitcode_process_mode") == 0 ) {
+                               const char* bitcode_type = argv[++i];
+                               if ( bitcode_type == NULL )
+                                       throw "missing argument to -bitcode_process_mode";
+                               else 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 )
@@ -2484,39 +3134,65 @@ 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)
+                snapshotArgCount = 0;
                                FileInfo info = findLibrary(&arg[11], true);
                                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]);
                                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)
+                snapshotArgCount = 0;
                                FileInfo info = findFramework(argv[++i]);
                                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)
+                snapshotArgCount = 0;
                                FileInfo info = findLibrary(&arg[9], true);
                                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]);
                                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)
+                snapshotArgCount = 0;
                                FileInfo info = findFramework(argv[++i]);
                                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;
@@ -2525,22 +3201,38 @@ 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";
                                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";
+                               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;
@@ -2552,30 +3244,38 @@ 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];
@@ -2597,6 +3297,7 @@ void Options::parse(int argc, const char* argv[])
                        }
                        else if ( strcmp(arg, "-objc_gc_compaction") == 0 ) {
                                fObjcGcCompaction = true;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-objc_gc") == 0 ) {
                                fObjCGc = true;
@@ -2604,6 +3305,7 @@ void Options::parse(int argc, const char* argv[])
                                        warning("-objc_gc overriding -objc_gc_only");
                                        fObjCGcOnly = false;    
                                }
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-objc_gc_only") == 0 ) {
                                fObjCGcOnly = true;
@@ -2611,6 +3313,7 @@ void Options::parse(int argc, const char* argv[])
                                        warning("-objc_gc_only overriding -objc_gc");
                                        fObjCGc = false;        
                                }
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-demangle") == 0 ) {
                                fDemangle = true;
@@ -2622,6 +3325,7 @@ void Options::parse(int argc, const char* argv[])
                        else if ( strcmp(arg, "-no_version_load_command") == 0 ) {
                                fVersionLoadCommandForcedOff = true;
                                fVersionLoadCommandForcedOn = false;
+                               cannotBeUsedWithBitcode(arg);
                        }
                        else if ( strcmp(arg, "-function_starts") == 0 ) {
                                fFunctionStartsForcedOn = true;
@@ -2630,6 +3334,16 @@ 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];
@@ -2640,24 +3354,31 @@ void Options::parse(int argc, const char* argv[])
                                fObjcCategoryMerging = false;
                        }
                        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;
                                if ( fExportMode == kExportSome )
                                        throw "can't use -exported_symbols_list and -reexported_symbols_list";
                                loadExportFile(argv[++i], "-reexported_symbols_list", fReExportSymbols);
@@ -2669,16 +3390,268 @@ 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];
+                               if ( path == NULL )
+                                       throw "-snapshot_dir missing path";
+                               fLinkSnapshot.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG);
+                               fLinkSnapshot.setSnapshotPath(path);
+                               fSnapshotRequested = true;
+                               cannotBeUsedWithBitcode(arg);
+            }
+                       else if ( strcmp(arg, "-new_main") == 0 ) {
+                               fEntryPointLoadCommandForceOn = true;
+                               cannotBeUsedWithBitcode(arg);
+                       }
+                       else if ( strcmp(arg, "-no_new_main") == 0 ) {
+                               fEntryPointLoadCommandForceOff = true;
+                               cannotBeUsedWithBitcode(arg);
+                       }
+                       else if ( strcmp(arg, "-source_version") == 0 ) {
+                                const char* vers = argv[++i];
+                                if ( vers == NULL )
+                                       throw "-source_version missing <version>";
+                               fSourceVersion = parseVersionNumber64(vers);
+                       }
+                       else if ( strcmp(arg, "-add_source_version") == 0 ) {
+                               fSourceVersionLoadCommandForceOn = true;
+                       }
+                       else if ( strcmp(arg, "-no_source_version") == 0 ) {
+                               fSourceVersionLoadCommandForceOff = true;
+                               cannotBeUsedWithBitcode(arg);
+                       }
+                       else if ( strcmp(arg, "-sdk_version") == 0 ) {
+                                const char* vers = argv[++i];
+                                if ( vers == NULL )
+                                       throw "-sdk_version missing <version>";
+                               fSDKVersion = parseVersionNumber32(vers);
+                       }
+                       else if ( strcmp(arg, "-dependent_dr_info") == 0 ) {
+                               warnObsolete(arg);
+                       }
+                       else if ( strcmp(arg, "-no_dependent_dr_info") == 0 ) {
+                               warnObsolete(arg);
+                       }
+                       else if ( strcmp(arg, "-kexts_use_stubs") == 0 ) {
+                               fKextsUseStubs = true;
+                               cannotBeUsedWithBitcode(arg);
+                       }
+                       else if ( strcmp(argv[i], "-dependency_info") == 0 ) {
+                snapshotArgCount = 0;
+                               ++i;
+                               // previously handled by buildSearchPaths()
+                       }
+                       else if ( strcmp(arg, "-export_dynamic") == 0 ) {
+                               fExportDynamic = true;
+                       }
+                       else if ( strcmp(arg, "-force_symbols_coalesce_list") == 0 ) {
+                snapshotFileArgIndex = 1;
+                               loadExportFile(argv[++i], "-force_symbols_coalesce_list", fForceCoalesceSymbols);
+                       }
+                       else if ( strcmp(arg, "-add_linker_option") == 0 ) {
+                               // ex: -add_linker_option '-framework Foundation'
+                               const char* optString = argv[++i];
+                               if ( optString == NULL )
+                                       throw "-add_linker_option missing <option>";
+                               // break up into list of tokens at whitespace
+                               std::vector<const char*> opts;
+                               char* buffer = strdup(optString);
+                               char* start = buffer;
+                               for (char* s = buffer; ; ++s) {
+                                       if ( isspace(*s)  ) {
+                                               *s = '\0';
+                                               opts.push_back(start);
+                                               start = s+1;
+                                       }
+                                       else if ( *s == '\0' ) {
+                                               opts.push_back(start);
+                                               break;
+                                       }
+                               }
+                               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);
+                       }
+                       // 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);
                        }
+            
+            if (snapshotArgCount == -1)
+                snapshotArgCount = i-snapshotArgIndex+1;
+            if (snapshotArgCount > 0)
+                fLinkSnapshot.addSnapshotLinkArg(snapshotArgIndex, snapshotArgCount, snapshotFileArgIndex);
                }
                else {
                        FileInfo info = findFile(arg);
+                       info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
                        if ( strcmp(&info.path[strlen(info.path)-2], ".a") == 0 )
                                addLibrary(info);
                        else
@@ -2688,8 +3661,13 @@ void Options::parse(int argc, const char* argv[])
        
        // if a -lazy option was used, implicitly link in lazydylib1.o
        if ( fUsingLazyDylibLinking ) {
-               addLibrary(findLibrary("lazydylib1.o"));
+               FileInfo info = findLibrary("lazydylib1.o");
+               info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)argc);
+               addLibrary(info);
        }
+    
+    if (fSnapshotRequested)
+        fLinkSnapshot.createSnapshot();
 }
 
 
@@ -2764,11 +3742,12 @@ void Options::buildSearchPaths(int argc, const char* argv[])
                        fVerbose = true;
                        extern const char ldVersionString[];
                        fprintf(stderr, "%s", ldVersionString);
+                       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, "%s\n", ltoVers);
+                                       fprintf(stderr, "LTO support using: %s\n", ltoVers);
                                exit(0);
                        }
                }
@@ -2787,6 +3766,18 @@ void Options::buildSearchPaths(int argc, const char* argv[])
                else if ( strcmp(argv[i], "-w") == 0 ) {
                        sEmitWarnings = false;
                }
+               else if ( strcmp(argv[i], "-fatal_warnings") == 0 ) {
+                       sFatalWarnings = true;
+               }
+               else if ( strcmp(argv[i], "-dependency_info") == 0 ) {
+                        const char* path = argv[++i];
+                        if ( path == NULL )
+                               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();
@@ -2928,8 +3919,16 @@ void Options::parsePreCommandLineEnvironmentSettings()
        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;
@@ -2939,6 +3938,19 @@ void Options::parsePreCommandLineEnvironmentSettings()
        const char* customDyldPath = getenv("LD_DYLD_PATH");
        if ( customDyldPath != NULL ) 
                fDyldInstallPath = customDyldPath;
+    
+    const char* debugArchivePath = getenv("LD_DEBUG_SNAPSHOT");
+    if (debugArchivePath != NULL) {
+        fLinkSnapshot.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG);
+        if (strlen(debugArchivePath) > 0)
+            fLinkSnapshot.setSnapshotPath(debugArchivePath);
+        fSnapshotRequested = true;
+    }
+
+    const char* pipeFdString = getenv("LD_PIPELINE_FIFO");
+    if (pipeFdString != NULL) {
+               fPipelineFifo = pipeFdString;
+    }
 }
 
 
@@ -2981,6 +3993,13 @@ void Options::parsePostCommandLineEnvironmentSettings()
        // allow build system to force on -warn_commons
        if ( getenv("LD_WARN_COMMONS") != NULL )
                fWarnCommons = true;
+       
+       // allow B&I to set default -source_version
+       if ( fSourceVersion == 0 ) {
+               const char* vers = getenv("RC_ProjectSourceVersion");
+               if ( vers != NULL )
+                       fSourceVersion = parseVersionNumber64(vers);
+       }
                
 }
 
@@ -3012,53 +4031,54 @@ void Options::reconfigureDefaults()
        }
 
        // set default min OS version
-       if ( (fMacVersionMin == ld::macVersionUnset)
-               && (fIOSVersionMin == ld::iOSVersionUnset) ) {
+       if ( (fMacVersionMin == ld::macVersionUnset) && (fIOSVersionMin == ld::iOSVersionUnset) && (fWatchOSVersionMin == ld::wOSVersionUnset) ) {
                // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
                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 ) 
+               const char* wOSVers = getenv("WATCHOS_DEPLOYMENT_TARGET");
+               if ( macVers != NULL )
                        setMacOSXVersionMin(macVers);
                else if ( iPhoneVers != NULL )
                        setIOSVersionMin(iPhoneVers);
                else if ( iOSVers != NULL )
                        setIOSVersionMin(iOSVers);
-               else if ( iOSSimulatorVers != NULL )
-                       setIOSVersionMin(iOSSimulatorVers);
+               else if ( wOSVers != NULL )
+                       setWatchOSVersionMin(wOSVers);
                else {
                        // if still nothing, set default based on architecture
                        switch ( fArchitecture ) {
                                case CPU_TYPE_I386:
                                case CPU_TYPE_X86_64:
-                               case CPU_TYPE_POWERPC:                  
                                        if ( (fOutputKind != Options::kObjectFile) && (fOutputKind != Options::kPreload) ) {
                        #ifdef DEFAULT_MACOSX_MIN_VERSION
-                                               warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION);
+                                               warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION);
                                                setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
                        #else
-                                               warning("-macosx_version_min not specificed, assuming 10.6");
-                                               fMacVersionMin = ld::mac10_6;
+                                               warning("-macosx_version_min not specified, assuming 10.6");
+                                               setMacOSXVersionMin("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 specificed, assuming " DEFAULT_IPHONEOS_MIN_VERSION);
+                                               warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION);
                                                setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION);
-                       #elif defined(DEFAULT_MACOSX_MIN_VERSION)
-                                               warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION);
-                                               setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
                        #else
-                                               warning("-macosx_version_min not specificed, assuming 10.6");
-                                               fMacVersionMin = ld::mac10_6;
+                                               if ( fSubArchitecture == CPU_SUBTYPE_ARM_V7K ) {
+                                                       warning("-watchos_version_min not specified, assuming 2.0");
+                                                       setWatchOSVersionMin("2.0");
+                                               }
+                                               else {
+                                                       warning("-ios_version_min not specified, assuming 6.0");
+                                                       setIOSVersionMin("6.0");
+                                               }
                        #endif
                                        }
                                        break;
                                default:
-                                       // architecture will be infered ;ater by examining .o files
+                                       // architecture will be infered later by examining .o files
                                        break;
                        }
                }
@@ -3068,25 +4088,52 @@ void Options::reconfigureDefaults()
        // adjust min based on architecture
        switch ( fArchitecture ) {
                case CPU_TYPE_I386:
-                       if ( (fMacVersionMin < ld::mac10_4) && (fIOSVersionMin == ld::iOSVersionUnset) ) {
+                       if ( (fPlatform == kPlatformOSX) && (fMacVersionMin < ld::mac10_4) ) {
                                //warning("-macosx_version_min should be 10.4 or later for i386");
                                fMacVersionMin = ld::mac10_4;
                        }
                        break;
-               case CPU_TYPE_POWERPC64:
-                       if ( fMacVersionMin < ld::mac10_4 ) {
-                               //warning("-macosx_version_min should be 10.4 or later for ppc64");
-                               fMacVersionMin = ld::mac10_4;
-                       }
-                       break;
                case CPU_TYPE_X86_64:
-                       if ( fMacVersionMin < ld::mac10_4 ) {
+                       if ( (fPlatform == kPlatformOSX) && (fMacVersionMin < ld::mac10_4) ) {
                                //warning("-macosx_version_min should be 10.4 or later for x86_64");
                                fMacVersionMin = ld::mac10_4;
                        }
                        break;
+               case CPU_TYPE_ARM64:
+                       if ( (fPlatform == kPlatformiOS) && (fIOSVersionMin < ld::iOS_7_0) ) {
+                               //warning("-mios_version_min should be 7.0 or later for arm64");
+                               fIOSVersionMin = ld::iOS_7_0;
+                       }
+                       break;
        }
        
+       // default to adding functions start for dynamic code, static code must opt-in
+       switch ( fOutputKind ) {
+               case Options::kPreload:
+               case Options::kStaticExecutable:
+               case Options::kKextBundle:
+                       if ( fDataInCodeInfoLoadCommandForcedOn )
+                               fDataInCodeInfoLoadCommand = true;
+                       if ( fFunctionStartsForcedOn )
+                               fFunctionStartsLoadCommand = true;
+                       break;
+               case Options::kObjectFile:
+                       if ( !fDataInCodeInfoLoadCommandForcedOff )
+                               fDataInCodeInfoLoadCommand = true;
+                       if ( fFunctionStartsForcedOn )
+                               fFunctionStartsLoadCommand = true;
+                       break;
+               case Options::kDynamicExecutable:
+               case Options::kDyld:
+               case Options::kDynamicLibrary:
+               case Options::kDynamicBundle:
+                       if ( !fDataInCodeInfoLoadCommandForcedOff )
+                               fDataInCodeInfoLoadCommand = true;
+                       if ( !fFunctionStartsForcedOff )
+                               fFunctionStartsLoadCommand = true;
+                       break;
+       }
+               
        // adjust kext type based on architecture
        if ( fOutputKind == kKextBundle ) {
                switch ( fArchitecture ) {
@@ -3097,17 +4144,26 @@ void Options::reconfigureDefaults()
                                fAllowTextRelocs = true;
                                fUndefinedTreatment = kUndefinedDynamicLookup;
                                break;
+                       case CPU_TYPE_ARM64:
+                               // arm64 uses new MH_KEXT_BUNDLE type
+                               fMakeCompressedDyldInfo = false;
+                               fMakeCompressedDyldInfoForceOff = true;
+                               fAllowTextRelocs = false; 
+                               fKextsUseStubs = true;
+                               fUndefinedTreatment = kUndefinedDynamicLookup;
+                               break;
                        case CPU_TYPE_ARM:
-                               if ( fIOSVersionMin >= ld::iOS_5_0 ) {
+                               if ( min_iOS(ld::iOS_5_0) ) {
                     // iOS 5.0 and later use new MH_KEXT_BUNDLE type
                     fMakeCompressedDyldInfo = false;
                     fMakeCompressedDyldInfoForceOff = true;
-                    fAllowTextRelocs = true;
+                                       // kexts are PIC in iOS 6.0 and later
+                                       fAllowTextRelocs = !min_iOS(ld::iOS_6_0);
+                                       fKextsUseStubs = !fAllowTextRelocs;
                     fUndefinedTreatment = kUndefinedDynamicLookup;
                                        break;
                                }
                                // else use object file
-                       case CPU_TYPE_POWERPC:
                        case CPU_TYPE_I386:
                                // use .o files
                                fOutputKind = kObjectFile;
@@ -3150,9 +4206,8 @@ void Options::reconfigureDefaults()
        
        // split segs only allowed for dylibs
        if ( fSplitSegs ) {
-        // split seg only supported for ppc, i386, and arm.
+        // split seg only supported for i386, and arm.
         switch ( fArchitecture ) {
-            case CPU_TYPE_POWERPC:
             case CPU_TYPE_I386:
                 if ( fOutputKind != Options::kDynamicLibrary )
                     fSplitSegs = false;
@@ -3179,11 +4234,9 @@ void Options::reconfigureDefaults()
 
        // set too-large size
        switch ( fArchitecture ) {
-               case CPU_TYPE_POWERPC:
                case CPU_TYPE_I386:
                        fMaxAddress = 0xFFFFFFFF;
                        break;
-               case CPU_TYPE_POWERPC64:
                case CPU_TYPE_X86_64:
                        break;
                case CPU_TYPE_ARM:
@@ -3217,7 +4270,6 @@ void Options::reconfigureDefaults()
        // disable prebinding depending on arch and min OS version
        if ( fPrebind ) {
                switch ( fArchitecture ) {
-                       case CPU_TYPE_POWERPC:
                        case CPU_TYPE_I386:
                                if ( fMacVersionMin == ld::mac10_4 ) {
                                        // in 10.4 only split seg dylibs are prebound
@@ -3251,7 +4303,6 @@ void Options::reconfigureDefaults()
                                        }
                                }
                                break;
-                       case CPU_TYPE_POWERPC64:
                        case CPU_TYPE_X86_64:
                                fPrebind = false;
                                break;
@@ -3282,22 +4333,56 @@ void Options::reconfigureDefaults()
        // 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 ( !fPrebind && !fSharedRegionEligibleForceOff )
                                if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
                                        || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
                                        fSharedRegionEligible = true;
        }
+       else if ( fOutputKind == Options::kDyld ) {
+        // <rdar://problem/10111122> Enable dyld to be put into the dyld shared cache
+        fSharedRegionEligible = true;
+       }
+
+       // <rdar://problem/18719327> warn if -rpath is used with OS dylibs
+       if ( fSharedRegionEligible && !fRPaths.empty() ) 
+               warning("-rpath cannot be used with dylibs that will be in the dyld shared cache");
+
+       // automatically use __DATA_CONST in iOS dylibs
+       if ( fSharedRegionEligible && minOS(ld::mac10_Future, ld::iOS_9_0) && !fUseDataConstSegmentForceOff ) {
+               fUseDataConstSegment = true;
+       }
+       if ( fUseDataConstSegmentForceOn ) {
+               fUseDataConstSegment = true;
+       }
+       if ( fUseDataConstSegment ) {
+               addSectionRename("__DATA", "__got",                             "__DATA_CONST", "__got");
+               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");
+       }
        
+       // Use V2 shared cache info when targetting newer OSs
+       if ( fSharedRegionEligible && minOS(ld::mac10_Future, ld::iOS_9_0)) {
+               fSharedRegionEncodingV2 = true;
+               fIgnoreOptimizationHints = 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
                                        break;
-                       case CPU_TYPE_POWERPC:  // 10.3 and earlier dyld requires a module table
-                               if ( fMacVersionMin <= ld::mac10_5 )
-                                       fNeedsModuleTable = true;
-                               break;
                        case CPU_TYPE_ARM:
                                if ( fPrebind )
                                        fNeedsModuleTable = true; // redo_prebinding requires a module table
@@ -3308,11 +4393,16 @@ void Options::reconfigureDefaults()
        // <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:             
                case CPU_TYPE_X86_64:           
+               case CPU_TYPE_ARM64:            
                        switch ( fOutputKind ) {
                                case Options::kObjectFile:
                                case Options::kStaticExecutable:
@@ -3329,11 +4419,27 @@ void Options::reconfigureDefaults()
                                        break;
                        }
                        break;
-               case CPU_TYPE_POWERPC:
-               case CPU_TYPE_POWERPC64:                
                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
@@ -3341,10 +4447,29 @@ void Options::reconfigureDefaults()
                        break;
        }
                
-       // only ARM main executables can 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 ( !min_iOS(ld::iOS_7_0) )
+                               fEncryptable = false;
+                       break;
+       }
+       if ( (fArchitecture != CPU_TYPE_ARM) && (fArchitecture != CPU_TYPE_ARM64) )
                fEncryptable = false;
-       if ( fArchitecture != CPU_TYPE_ARM )
+       if ( fEncryptableForceOn )
+               fEncryptable = true;
+       else if ( fEncryptableForceOff )
                fEncryptable = false;
 
        // don't move inits in dyld because dyld wants certain
@@ -3387,32 +4512,24 @@ void Options::reconfigureDefaults()
 
        
        // only use compressed LINKEDIT for:
-       //                      x86_64 and i386 on Mac OS X 10.6 or later
-       //                      arm on iPhoneOS 3.1 or later
+       //                      Mac OS X 10.6 or later
+       //                      iOS 3.1 or later
        if ( fMakeCompressedDyldInfo ) {
-               switch (fArchitecture) {
-                       case CPU_TYPE_I386:
-                               if ( fIOSVersionMin != ld::iOSVersionUnset ) // simulator always uses compressed LINKEDIT
-                                       break;
-                       case CPU_TYPE_X86_64:
-                               if ( fMacVersionMin < ld::mac10_6 ) 
-                                       fMakeCompressedDyldInfo = false;
-                               break;
-            case CPU_TYPE_ARM:
-                               if ( !minOS(ld::mac10_6, ld::iOS_3_1) )
-                                       fMakeCompressedDyldInfo = false;
-                               break;
-                       case CPU_TYPE_POWERPC:
-                       case CPU_TYPE_POWERPC64:
-                       default:
-                               fMakeCompressedDyldInfo = false;
-               }
+               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_X86_64:
+                       break;
+               case CPU_TYPE_I386:
+               case CPU_TYPE_ARM64:
+                       fAllowCpuSubtypeMismatches = true;
+                       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 )
@@ -3458,20 +4575,29 @@ void Options::reconfigureDefaults()
        if ( (fArchitecture == CPU_TYPE_ARM) 
                && fArchSupportsThumb2
                && (fOutputKind == kDynamicExecutable) 
-               && (fIOSVersionMin >= ld::iOS_4_3) ) {
+               && min_iOS(ld::iOS_4_3) ) {
                        fPositionIndependentExecutable = true;
        }
 
+       // Simulator defaults to PIE
+       if ( fTargetIOSSimulator && (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) ) {
+               fPositionIndependentExecutable = true;
+       }
+
        // set fOutputSlidable
        switch ( fOutputKind ) {
                case Options::kObjectFile:
-               case Options::kStaticExecutable:
                        fOutputSlidable = false;
                        break;
+               case Options::kStaticExecutable:
                case Options::kDynamicExecutable:
                        fOutputSlidable = fPositionIndependentExecutable;
                        break;
@@ -3490,7 +4616,13 @@ void Options::reconfigureDefaults()
        if ( fMacVersionMin >= ld::mac10_7 ) {
                fTLVSupport = true;
        }
-       
+       else if ( (fArchitecture == CPU_TYPE_ARM64) && min_iOS(ld::iOS_8_0) ) {
+               fTLVSupport = true;
+       }
+       else if ( (fArchitecture == CPU_TYPE_ARM) && min_iOS(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:
@@ -3508,36 +4640,9 @@ void Options::reconfigureDefaults()
                case Options::kDynamicBundle:
                        if ( !fVersionLoadCommandForcedOff )
                                fVersionLoadCommand = true;
-                       // <rdar://problem/9945513> for now, don't create version load commands for iOS simulator builds
-                       if ( fVersionLoadCommand && (fArchitecture == CPU_TYPE_I386) ) {
-                               for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
-                                       if ( strstr(*sdkit, "/iPhoneSimulator.platform/") != NULL )
-                                               fVersionLoadCommand = false;
-                               }
-                       }
                        break;
        }
        
-       // default to adding functions start for dynamic code, static code must opt-in
-       switch ( fOutputKind ) {
-               case Options::kObjectFile:
-                       fFunctionStartsLoadCommand = false;
-                       break;
-               case Options::kPreload:
-               case Options::kStaticExecutable:
-               case Options::kKextBundle:
-                       if ( fFunctionStartsForcedOn )
-                               fFunctionStartsLoadCommand = true;
-                       break;
-               case Options::kDynamicExecutable:
-               case Options::kDyld:
-               case Options::kDynamicLibrary:
-               case Options::kDynamicBundle:
-                       if ( !fFunctionStartsForcedOff )
-                               fFunctionStartsLoadCommand = true;
-                       break;
-       }
-               
        // 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) )
                fCanReExportSymbols = true;
@@ -3562,6 +4667,209 @@ void Options::reconfigureDefaults()
        // on the command line
        if ( (fArchitecture == CPU_TYPE_I386) && (fOutputKind == kDynamicExecutable) && !fDisableNonExecutableHeap)
                fNonExecutableHeap = true;
+               
+       // Use LC_MAIN instead of LC_UNIXTHREAD for newer OSs
+       switch ( fOutputKind ) {
+               case Options::kDynamicExecutable:
+                       if ( fEntryPointLoadCommandForceOn ) {
+                               fEntryPointLoadCommand = true;
+                               if ( fEntryName == NULL ) 
+                                       fEntryName = "_main";
+                       }
+                       else if ( fEntryPointLoadCommandForceOff ) {
+                               fNeedsThreadLoadCommand = true;
+                               if ( fEntryName == NULL ) 
+                                       fEntryName = "start";
+                       }
+                       else {
+                               // <rdar://problem/16310363> Linker should look for "_main" not "start" when building for sim regardless of min OS
+                               if ( minOS(ld::mac10_8, ld::iOS_6_0) || fTargetIOSSimulator ) {
+                                       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;
+                                       if ( fEntryName == NULL ) 
+                                               fEntryName = "start";
+                               }
+                       }
+                       break;
+               case Options::kObjectFile:
+               case Options::kKextBundle:
+               case Options::kDynamicLibrary:
+               case Options::kDynamicBundle:
+                       break;
+                       
+               case Options::kStaticExecutable:
+               case Options::kPreload:
+               case Options::kDyld:
+                       fNeedsThreadLoadCommand = true;
+                       if ( fEntryName == NULL ) 
+                               fEntryName = "start";  // Perhaps these should have no default and require -e
+                       break;
+       }
+       
+       // add LC_SOURCE_VERSION
+       switch ( fOutputKind ) {
+               case Options::kDynamicExecutable:
+               case Options::kKextBundle:
+               case Options::kDynamicLibrary:
+               case Options::kDynamicBundle:
+               case Options::kDyld:
+               case Options::kStaticExecutable:
+                       if ( fSourceVersionLoadCommandForceOn ) {
+                               fSourceVersionLoadCommand = true;
+                       }
+                       else if ( fSourceVersionLoadCommandForceOff ) {
+                               fSourceVersionLoadCommand = false;
+                       }
+                       else {
+                               if ( minOS(ld::mac10_8, ld::iOS_6_0) ) {
+                                       fSourceVersionLoadCommand = true;
+                               }
+                               else
+                                       fSourceVersionLoadCommand = false;
+                       }
+                       break;
+               case Options::kObjectFile:
+               case Options::kPreload:
+                       fSourceVersionLoadCommand = false;
+                       break;
+       }
+
+       // if -sdk_version not on command line, infer from -syslibroot
+       if ( (fSDKVersion == 0) && (fSDKPaths.size() > 0) ) {
+               const char* sdkPath = fSDKPaths.front();
+               const char* end = &sdkPath[strlen(sdkPath)-1];
+               while ( !isdigit(*end) && (end > sdkPath) )
+                       --end;
+               const char* start = end-1;
+               while ( (isdigit(*start) || (*start == '.')) && (start > sdkPath))
+                       --start;
+               char sdkVersionStr[32];
+               int len = end-start+1;
+               if ( len > 2 ) {
+                       strlcpy(sdkVersionStr, start+1, len);
+                       fSDKVersion = parseVersionNumber32(sdkVersionStr);
+               }
+       }
+       
+       // if -sdk_version and -syslibroot not used, but targeting MacOSX, use current OS version
+       if ( (fSDKVersion == 0) && (fMacVersionMin != ld::macVersionUnset) ) {
+               // 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;
+               }
+               else {
+                       int mib[2] = { CTL_KERN, KERN_OSRELEASE };
+                       char kernVersStr[100];
+                       size_t strlen = sizeof(kernVersStr);
+                       if ( sysctl(mib, 2, kernVersStr, &strlen, NULL, 0) != -1 ) {
+                               uint32_t kernVers = parseVersionNumber32(kernVersStr);
+                               int minor = (kernVers >> 16) - 4;  // kernel major version is 4 ahead of x in 10.x
+                               fSDKVersion = 0x000A0000 + (minor << 8);
+                       }
+               }
+       }
+       
+       // allow trie based absolute symbols if targeting new enough OS
+       if ( fMakeCompressedDyldInfo ) {
+               if ( minOS(ld::mac10_9, ld::iOS_7_0) ) {
+                       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/12258065> ARM64 needs 16KB page size for user land code
+       // <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:
+                               if ( (fArchitecture == CPU_TYPE_ARM64) 
+                               || ((fArchitecture == CPU_TYPE_ARM) && min_iOS(ld::iOS_7_0)) ) {
+                                       fSegmentAlignment = 4096*4;
+                               }
+                               break;
+                       case Options::kStaticExecutable:
+                       case Options::kKextBundle:
+                               // <rdar://problem/14676611> 16KB segments for arm64 kexts
+                               if ( (fArchitecture == CPU_TYPE_ARM64) && min_iOS(ld::iOS_9_0) ) {
+                                       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:
+               case Options::kDynamicLibrary:
+               case Options::kDynamicBundle:
+               case Options::kDyld:
+                       if ( fKeepDwarfUnwindForcedOn ) {
+                               fKeepDwarfUnwind = true;
+                       }
+                       else if ( fKeepDwarfUnwindForcedOff ) {
+                               fKeepDwarfUnwind = false;
+                       }
+                       else {
+                               if ( minOS(ld::mac10_9, ld::iOS_7_0) ) 
+                                       fKeepDwarfUnwind = false;
+                               else
+                                       fKeepDwarfUnwind = true;
+                       }
+                       break;
+               case Options::kKextBundle:
+               case Options::kStaticExecutable:
+               case Options::kObjectFile:
+               case Options::kPreload:
+                       fKeepDwarfUnwind = true;
+                       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");
+               }
+       }
+
 }
 
 void Options::checkIllegalOptionCombinations()
@@ -3592,6 +4900,7 @@ void Options::checkIllegalOptionCombinations()
                        if ( strcmp(&lastSlash[1], subUmbrella) == 0 ) {
                                info.options.fReExport = true;
                                found = true;
+                fLinkSnapshot.recordSubUmbrella(info.path);
                                break;
                        }
                }
@@ -3614,6 +4923,7 @@ void Options::checkIllegalOptionCombinations()
                        if ( strncmp(&lastSlash[1], subLibrary, dot-lastSlash-1) == 0 ) {
                                info.options.fReExport = true;
                                found = true;
+                fLinkSnapshot.recordSubLibrary(info.path);
                                break;
                        }
                }
@@ -3629,13 +4939,12 @@ void Options::checkIllegalOptionCombinations()
        if ( fStackAddr != 0 ) {
                switch (fArchitecture) {
                        case CPU_TYPE_I386:
-                       case CPU_TYPE_POWERPC:
             case CPU_TYPE_ARM:
                                if ( fStackAddr > 0xFFFFFFFF )
                                        throw "-stack_addr must be < 4G for 32-bit processes";
                                break;
-                       case CPU_TYPE_POWERPC64:
                        case CPU_TYPE_X86_64:
+                       case CPU_TYPE_ARM64:
                                break;
                }
                if ( (fStackAddr & -4096) != fStackAddr )
@@ -3648,7 +4957,6 @@ void Options::checkIllegalOptionCombinations()
        if ( fStackSize != 0 ) {
                switch (fArchitecture) {
                        case CPU_TYPE_I386:
-                       case CPU_TYPE_POWERPC:
                                if ( fStackSize > 0xFFFFFFFF )
                                        throw "-stack_size must be < 4G for 32-bit processes";
                                if ( fStackAddr == 0 ) {
@@ -3664,12 +4972,19 @@ void Options::checkIllegalOptionCombinations()
                                        fStackAddr = 0x2F000000;
                 if ( fStackAddr > 0x30000000)
                     throw "-stack_addr must be < 0x30000000 for arm";
-                       case CPU_TYPE_POWERPC64:
+                               break;
                        case CPU_TYPE_X86_64:
                                if ( fStackAddr == 0 ) {
                                        fStackAddr = 0x00007FFF5C000000LL;
                                }
                                break;
+                       case CPU_TYPE_ARM64:
+                               if ( fStackSize > 0x20000000 )
+                                       throw "-stack_size must be < 512MB";
+                               if ( fStackAddr == 0 ) {
+                                       fStackAddr = 0x120000000;
+                               }
+                               break;
                }
                if ( (fStackSize & -4096) != fStackSize )
                        throw "-stack_size must be multiples of 4K";
@@ -3766,6 +5081,10 @@ void Options::checkIllegalOptionCombinations()
        if ( fSetuidSafe && (fOutputKind == Options::kObjectFile) )
                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 )
+               fObjCABIVersion2Override = true;
+
        // rdar://problem/4718189 map ObjC class names to new runtime names
        bool alterObjC1ClassNamesToObjC2 = false;
        switch (fArchitecture) {
@@ -3774,9 +5093,9 @@ void Options::checkIllegalOptionCombinations()
                        if ( fObjCABIVersion2Override )
                                alterObjC1ClassNamesToObjC2 = true;
                        break;
-               case CPU_TYPE_POWERPC64:
                case CPU_TYPE_X86_64:
                case CPU_TYPE_ARM:
+               case CPU_TYPE_ARM64:
                        alterObjC1ClassNamesToObjC2 = true;
                        break;
        }
@@ -3868,18 +5187,11 @@ void Options::checkIllegalOptionCombinations()
                // zero page size not specified on command line, set default
                switch (fArchitecture) {
                        case CPU_TYPE_I386:
-                       case CPU_TYPE_POWERPC:
             case CPU_TYPE_ARM:
                                // first 4KB for 32-bit architectures
                                fZeroPageSize = 0x1000;
                                break;
-                       case CPU_TYPE_POWERPC64:
-                               // first 4GB for ppc64 on 10.5
-                               if ( fMacVersionMin >= ld::mac10_5 )
-                                       fZeroPageSize = 0x100000000ULL;
-                               else
-                                       fZeroPageSize = 0x1000; // 10.4 dyld may not be able to handle >4GB zero page
-                               break;
+                       case CPU_TYPE_ARM64:
                        case CPU_TYPE_X86_64:
                                // first 4GB for x86_64 on all OS's
                                fZeroPageSize = 0x100000000ULL;
@@ -3936,10 +5248,10 @@ void Options::checkIllegalOptionCombinations()
                }
        }
        
-       // check -pie is only used when building a dynamic main executable for 10.5
        if ( fPositionIndependentExecutable ) {
                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";
@@ -3947,14 +5259,15 @@ void Options::checkIllegalOptionCombinations()
                                                throw "-pie can only be used when targeting iOS 4.2 or later";
                                }
                                break;
+                       case Options::kStaticExecutable:
                        case Options::kPreload:
+                               // -pie is ok with -static or -preload
                                break;
                        case Options::kDynamicLibrary:
                        case Options::kDynamicBundle:
                                warning("-pie being ignored. It is only used when linking a main executable");
                                fPositionIndependentExecutable = false;
                                break;
-                       case Options::kStaticExecutable:
                        case Options::kObjectFile:
                        case Options::kDyld:
                        case Options::kKextBundle:
@@ -3996,6 +5309,26 @@ void Options::checkIllegalOptionCombinations()
        // -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
+       if ( !fSegmentOrder.empty() && (fOutputKind != Options::kPreload) )
+               throw "-segment_order can only used used with -preload output";
+
+       if ( fBitcodeKind != kBitcodeProcess &&
+                fOutputKind != Options::kObjectFile ) {
+               throw "-bitcode_process_mode can only be used together with -r";
+       }
+       // 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) && (fIOSVersionMin != ld::iOSVersionUnset) && (fDylibInstallName != NULL) ) {
+               if ( !min_iOS(ld::iOS_8_0) && (fDylibInstallName[0] == '@') && !fEncryptableForceOff )
+                       warning("embedded dylibs/frameworks only run on iOS 8 or later");
+       }
 }      
 
 
@@ -4011,6 +5344,9 @@ void Options::checkForClassic(int argc, const char* argv[])
        bool newLinker = false;
        
        // build command line buffer in case ld crashes
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
+       CRSetCrashLogMessage(crashreporterBuffer);
+#endif
        const char* srcRoot = getenv("SRCROOT");
        if ( srcRoot != NULL ) {
                strlcpy(crashreporterBuffer, "SRCROOT=", crashreporterBufferSize);
@@ -4053,6 +5389,7 @@ void Options::checkForClassic(int argc, const char* argv[])
                                // ld_classic does not understand this option, so remove it
                                for(int j=i; j < argc; ++j)
                                        argv[j] = argv[j+1];
+                               warning("using ld_classic");
                                this->gotoClassicLinker(argc-1, argv);
                        }
                        else if ( strcmp(arg, "-o") == 0 ) {
@@ -4062,35 +5399,10 @@ void Options::checkForClassic(int argc, const char* argv[])
                        }
                }
        }
-
-       // -dtrace only supported by new linker
-       if( dtraceFound )
-               return;
-
-       if( archFound ) {
-               switch ( fArchitecture ) {
-               case CPU_TYPE_I386:
-               case CPU_TYPE_POWERPC:
-                       if ( (staticFound || kextFound) && !newLinker ) {
-                               // this environment variable will disable use of ld_classic for -static links
-                               if ( getenv("LD_NO_CLASSIC_LINKER_STATIC") == NULL ) {
-                                       this->gotoClassicLinker(argc, argv);
-                               }
-                       }
-                       break;
-               }
-       }
-       else {
-               // work around for VSPTool
-               if ( staticFound )
-                       this->gotoClassicLinker(argc, argv);
-       }
-
 }
 
 void Options::gotoClassicLinker(int argc, const char* argv[])
 {
-       warning("using ld_classic");
        argv[0] = "ld_classic";
        // ld_classic does not support -iphoneos_version_min, so change
        for(int j=0; j < argc; ++j) {
@@ -4140,3 +5452,84 @@ void Options::gotoClassicLinker(int argc, const char* argv[])
        fprintf(stderr, "can't exec ld_classic\n");
        exit(1);
 }
+
+
+// Note, returned string buffer is own by this function.
+// It should not be freed
+// It will be reused, so clients need to strdup() if they want
+// to use it long term.
+const char* Options::demangleSymbol(const char* sym) const
+{
+       // only try to demangle symbols if -demangle on command line
+       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, "__T", 3) == 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;
+
+       int status;
+       char* result = abi::__cxa_demangle(&sym[1], buff, &size, &status); 
+       if ( result != NULL ) {
+               // if demangling successful, keep buffer for next demangle
+               buff = result;
+               return buff;
+       }
+       return sym;
+}
+
+
+void Options::dumpDependency(uint8_t opcode, const char* path) const
+{
+       if ( !this->dumpDependencyInfo() ) 
+               return;
+
+       // 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 )
+                       throwf("write() to -dependency_info failed, errno=%d", errno);
+               extern const char ldVersionString[];
+               if ( write(fDependencyFileDescriptor, ldVersionString, strlen(ldVersionString)+1) == -1 )
+                       throwf("write() to -dependency_info failed, errno=%d", errno);
+       }
+
+       char realPath[PATH_MAX];
+       if ( path[0] != '/' ) {
+               if ( realpath(path, realPath) != NULL ) {
+                       path = realPath;
+               }
+       }
+
+       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);
+}
+
+
+