throw t;
}
-bool Options::FileInfo::checkFileExists(const char *p)
+
+bool Options::FileInfo::checkFileExists(const Options& options, const char *p)
{
struct stat statBuffer;
- if (p == NULL) p = path;
+ 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),
fClientName(NULL),
fUmbrellaName(NULL), fInitFunctionName(NULL), fDotOutputFile(NULL), fExecutablePath(NULL),
fBundleLoader(NULL), fDtraceScriptName(NULL), fSegAddrTablePath(NULL), fMapPath(NULL),
- fDyldInstallPath("/usr/lib/dyld"), fTempLtoObjectPath(NULL), fOverridePathlibLTO(NULL),
+ 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),
fSourceVersionLoadCommand(false),
fSourceVersionLoadCommandForceOn(false), fSourceVersionLoadCommandForceOff(false),
fDependentDRInfo(false), fDependentDRInfoForcedOn(false), fDependentDRInfoForcedOff(false),
+ fTargetIOSSimulator(false), fExportDynamic(false), fAbsoluteSymbols(false),
+ fAllowSimulatorToLinkWithMacOSX(false), fKeepDwarfUnwind(true),
+ fKeepDwarfUnwindForcedOn(false), fKeepDwarfUnwindForcedOff(false),
+ fVerboseOptimizationHints(false), fIgnoreOptimizationHints(false),
+ fGenerateDtraceDOF(true), fAllowBranchIslands(true),
fDebugInfoStripping(kDebugInfoMinimal), fTraceOutputFile(NULL),
fMacVersionMin(ld::macVersionUnset), fIOSVersionMin(ld::iOSVersionUnset),
- fSaveTempFiles(false), fSnapshotRequested(false), fPipelineFifo(NULL)
+ fSaveTempFiles(false), fSnapshotRequested(false), fPipelineFifo(NULL),
+ fDependencyInfoPath(NULL), fDependencyFileDescriptor(-1)
{
this->checkForClassic(argc, argv);
this->parsePreCommandLineEnvironmentSettings();
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
//
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;
return fExecutablePath;
}
-
uint32_t Options::initialSegProtection(const char* segName) const
{
for(std::vector<Options::SegmentProtect>::const_iterator it = fCustomSegmentProtections.begin(); it != fCustomSegmentProtections.end(); ++it) {
::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;
return fForceNotWeakSymbols.containsNonWildcard(symbolName);
}
+bool Options::forceCoalesce(const char* symbolName) const
+{
+ return fForceCoalesceSymbols.contains(symbolName);
+}
+
bool Options::shouldExport(const char* symbolName) const
{
fMacVersionMin = ld::mac10_6;
#endif
}
- if ( !fMakeCompressedDyldInfo && minOS(ld::mac10_6, ld::iOS_3_1) && !fMakeCompressedDyldInfoForceOff )
- fMakeCompressedDyldInfo = true;
break;
case CPU_TYPE_ARM:
+ case CPU_TYPE_ARM64:
if ( (fMacVersionMin == ld::macVersionUnset) && (fIOSVersionMin == ld::iOSVersionUnset) && (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);
- #elif defined(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;
+ warning("-ios_version_min not specified, assuming 6.0");
+ setIOSVersionMin("6.0");
#endif
}
- if ( !fMakeCompressedDyldInfo && minOS(ld::mac10_6, ld::iOS_3_1) && !fMakeCompressedDyldInfoForceOff )
- fMakeCompressedDyldInfo = true;
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;
}
}
{
char possiblePath[strlen(dir)+strlen(rootName)+strlen(format)+8];
sprintf(possiblePath, format, dir, rootName);
- bool found = result.checkFileExists(possiblePath);
+ bool found = result.checkFileExists(*this, possiblePath);
if ( fTraceDylibSearching )
printf("[Logging for XBS]%sfound library: '%s'\n", (found ? " " : " not "), possiblePath);
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;
}
}
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.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;
}
// 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;
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;
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";
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
{
- for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin();
+ for (std::vector<const char*>::const_iterator it = fFrameworkSearchPaths.begin();
it != fFrameworkSearchPaths.end();
it++) {
// ??? Shouldn't we be using String here and just initializing it?
}
}
FileInfo result;
- bool found = result.checkFileExists(possiblePath);
+ bool found = result.checkFileExists(*this, possiblePath);
if ( fTraceDylibSearching )
printf("[Logging for XBS]%sfound framework: '%s'\n",
(found ? " " : " not "), possiblePath);
if ( possiblePath[sdkPathDirLen-1] == '/' )
possiblePath[sdkPathDirLen-1] = '\0';
strcat(possiblePath, path);
- if ( result.checkFileExists(possiblePath) ) {
+ if ( result.checkFileExists(*this, possiblePath) ) {
return result;
}
}
}
// try raw path
- if ( result.checkFileExists(path) ) {
+ if ( result.checkFileExists(*this, path) ) {
return result;
}
strcpy(&addPoint[1], &path[17]);
else
strcpy(newPath, &path[17]);
- if ( result.checkFileExists(newPath) ) {
+ if ( result.checkFileExists(*this, newPath) ) {
return result;
}
}
// If we didn't find it fall back to findFile.
return findFile(path);
}
-
+
+
void Options::parseSegAddrTable(const char* segAddrPath, const char* installPth)
{
file = fopen(realFileOfPaths, "r");
if ( file == NULL )
throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", realFileOfPaths, errno, strerror(errno));
+ if ( this->dumpDependencyInfo() )
+ this->dumpDependency(Options::depFileList, realFileOfPaths);
}
}
else {
file = fopen(fileOfPaths, "r");
if ( file == NULL )
throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", fileOfPaths, errno, strerror(errno));
+ if ( this->dumpDependencyInfo() )
+ this->dumpDependency(Options::depFileList, fileOfPaths);
}
char path[PATH_MAX];
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;
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;
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));
}
else {
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];
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;
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::addSectionAlignment(const char* segment, const char* section, const char* alignmentStr)
{
if ( strlen(segment) > 16 )
}
// 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, "-multiply_defined") == 0 ) {
//warnObsolete(arg);
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);
- }
else if ( strcmp(arg, "-save-temps") == 0 ) {
fSaveTempFiles = true;
}
throw "missing argument to -mllvm";
fLLVMOptions.push_back(opts);
}
+ else if ( strcmp(arg, "-mcpu") == 0 ) {
+ const char* cpu = argv[++i];
+ if ( cpu == NULL )
+ throw "missing argument to -mcpu";
+ fLtoCpu = cpu;
+ }
else if ( strcmp(arg, "-no_order_inits") == 0 ) {
fAutoOrderInitializers = false;
}
else if (strcmp(arg, "-debug_snapshot") == 0) {
fLinkSnapshot.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG);
fSnapshotRequested = true;
+ }
+ 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;
}
else if ( strcmp(arg, "-new_main") == 0 ) {
fEntryPointLoadCommandForceOn = true;
else if ( strcmp(arg, "-kexts_use_stubs") == 0 ) {
fKextsUseStubs = true;
}
+ else if ( strcmp(argv[i], "-dependency_info") == 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);
+ }
+ else if ( strcmp(arg, "-allow_simulator_linking_to_macosx_dylibs") == 0 ) {
+ fAllowSimulatorToLinkWithMacOSX = true;
+ }
+ else if ( strcmp(arg, "-keep_dwarf_unwind") == 0 ) {
+ fKeepDwarfUnwindForcedOn = true;
+ fKeepDwarfUnwindForcedOff = false;
+ }
+ else if ( strcmp(arg, "-no_keep_dwarf_unwind") == 0 ) {
+ fKeepDwarfUnwindForcedOn = false;
+ fKeepDwarfUnwindForcedOff = true;
+ }
+ else if ( strcmp(arg, "-verbose_optimization_hints") == 0 ) {
+ fVerboseOptimizationHints = true;
+ }
+ else if ( strcmp(arg, "-ignore_optimization_hints") == 0 ) {
+ fIgnoreOptimizationHints = true;
+ }
+ 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;
+ }
+ else if ( strcmp(arg, "-no_branch_islands") == 0 ) {
+ fAllowBranchIslands = false;
+ }
+ // 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);
}
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;
+ }
}
int standardLibraryPathsStartIndex = libraryPaths.size();
int standardFrameworkPathsStartIndex = frameworkPaths.size();
#if defined(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 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;
+ 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;
}
}
fMacVersionMin = ld::mac10_4;
}
break;
+ case CPU_TYPE_ARM64:
+ if ( fIOSVersionMin < ld::iOS_7_0 ) {
+ //warning("-mios_version_min should be 7.0 or later for arm64");
+ fIOSVersionMin = ld::iOS_7_0;
+ }
+ break;
}
+ // 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 ) {
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 ) {
// iOS 5.0 and later use new MH_KEXT_BUNDLE type
// <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:
break;
}
- // only ARM main executables can be encrypted
+ // only iOS main executables should be encrypted
if ( fOutputKind != Options::kDynamicExecutable )
fEncryptable = false;
- if ( fArchitecture != CPU_TYPE_ARM )
+ if ( (fArchitecture != CPU_TYPE_ARM) && (fArchitecture != CPU_TYPE_ARM64) )
fEncryptable = false;
// don't move inits in dyld because dyld wants certain
fMakeCompressedDyldInfo = false;
}
-
- // only ARM enforces that cpu-sub-types must match
- if ( fArchitecture != CPU_TYPE_ARM )
- fAllowCpuSubtypeMismatches = true;
+ // 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 final linked images can not optimize zero fill sections
if ( fOutputKind == Options::kObjectFile )
if ( fDisablePositionIndependentExecutable )
fPositionIndependentExecutable = false;
+ // arm64 is always PIE
+ if ( (fArchitecture == CPU_TYPE_ARM64) && (fOutputKind == kDynamicExecutable) ) {
+ fPositionIndependentExecutable = true;
+ }
+
// set fOutputSlidable
switch ( fOutputKind ) {
case Options::kObjectFile:
if ( fMacVersionMin >= ld::mac10_7 ) {
fTLVSupport = true;
}
-
+ else if ( (fArchitecture == CPU_TYPE_ARM64) && (fIOSVersionMin >= 0x00080000) ) {
+ fTLVSupport = true;
+ }
+
// default to adding version load command for dynamic code, static code must opt-in
switch ( fOutputKind ) {
case Options::kObjectFile:
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::kPreload:
- case Options::kStaticExecutable:
- case Options::kKextBundle:
- if ( fDataInCodeInfoLoadCommandForcedOn )
- fDataInCodeInfoLoadCommand = true;
- if ( fFunctionStartsForcedOn )
- fFunctionStartsLoadCommand = true;
- break;
- case Options::kObjectFile:
- case Options::kDynamicExecutable:
- case Options::kDyld:
- case Options::kDynamicLibrary:
- case Options::kDynamicBundle:
- if ( !fDataInCodeInfoLoadCommandForcedOff )
- fDataInCodeInfoLoadCommand = true;
- 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;
fNeedsThreadLoadCommand = true;
}
else {
- if ( (fIOSVersionMin != ld::iOSVersionUnset) && (fArchitecture == CPU_TYPE_I386) ) {
- // don't use LC_MAIN for simulator until min host OS is 10.8 for simulator
- fNeedsThreadLoadCommand = true;
- fEntryPointLoadCommand = false;
- }
- else if ( minOS(ld::mac10_8, ld::iOS_6_0) ) {
+ if ( minOS(ld::mac10_8, ld::iOS_6_0) ) {
fEntryPointLoadCommand = true;
fEntryName = "_main";
}
}
}
+ // allow trie based absolute symbols if targeting new enough OS
+ if ( fMakeCompressedDyldInfo ) {
+ if ( minOS(ld::mac10_9, ld::iOS_7_0) ) {
+ // <rdar://problem/13179029> Allow absolute symbols in export trie for device but not simulator
+ if ( !fTargetIOSSimulator )
+ fAbsoluteSymbols = true;
+ }
+ }
+
+ // <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
+ if ( fArchitecture == CPU_TYPE_ARM64 ) {
+ if ( fSegmentAlignment == 4096 ) {
+ switch ( fOutputKind ) {
+ case Options::kDynamicExecutable:
+ case Options::kDynamicLibrary:
+ case Options::kDynamicBundle:
+ case Options::kDyld:
+ fSegmentAlignment = 4096*4;
+ break;
+ case Options::kStaticExecutable:
+ case Options::kKextBundle:
+ 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;
+ }
+
}
void Options::checkIllegalOptionCombinations()
throw "-stack_addr must be < 4G for 32-bit processes";
break;
case CPU_TYPE_X86_64:
+ case CPU_TYPE_ARM64:
break;
}
if ( (fStackAddr & -4096) != fStackAddr )
fStackAddr = 0x2F000000;
if ( fStackAddr > 0x30000000)
throw "-stack_addr must be < 0x30000000 for arm";
+ 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";
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) {
break;
case CPU_TYPE_X86_64:
case CPU_TYPE_ARM:
+ case CPU_TYPE_ARM64:
alterObjC1ClassNamesToObjC2 = true;
break;
}
// first 4KB for 32-bit architectures
fZeroPageSize = 0x1000;
break;
+ case CPU_TYPE_ARM64:
case CPU_TYPE_X86_64:
// first 4GB for x86_64 on all OS's
fZeroPageSize = 0x100000000ULL;
// -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";
+
+ // -rename_sections can only be used in -r mode
+ if ( (fSectionRenames.size() != 0) && (fOutputKind != Options::kObjectFile) )
+ throw "-rename_sections can only used used in -r mode";
}
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);
+}
+
+
+