128-2
[darwin-xtools.git] / ld64 / src / ld / Options.cpp
blob629903f89a082f5b3cc51e1c726156da9f1f0a99
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2005-2011 Apple Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
12 * file.
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
22 * @APPLE_LICENSE_HEADER_END@
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <mach/vm_prot.h>
29 #include <mach-o/dyld.h>
30 #include <fcntl.h>
32 #include <vector>
34 #include "configure.h"
35 #include "Options.h"
36 #include "Architectures.hpp"
37 #include "MachOFileAbstraction.hpp"
39 // upward dependency on lto::version()
40 namespace lto {
41 extern const char* version();
44 // magic to place command line in crash reports
45 const int crashreporterBufferSize = 2000;
46 extern "C" char* __crashreporter_info__;
47 static char crashreporterBuffer[crashreporterBufferSize];
48 char* __crashreporter_info__ = crashreporterBuffer;
50 static bool sEmitWarnings = true;
51 static bool sFatalWarnings = false;
52 static const char* sWarningsSideFilePath = NULL;
53 static FILE* sWarningsSideFile = NULL;
54 static int sWarningsCount = 0;
56 void warning(const char* format, ...)
58 ++sWarningsCount;
59 if ( sEmitWarnings ) {
60 va_list list;
61 if ( sWarningsSideFilePath != NULL ) {
62 if ( sWarningsSideFile == NULL )
63 sWarningsSideFile = fopen(sWarningsSideFilePath, "a");
65 va_start(list, format);
66 fprintf(stderr, "ld: warning: ");
67 vfprintf(stderr, format, list);
68 fprintf(stderr, "\n");
69 if ( sWarningsSideFile != NULL ) {
70 fprintf(sWarningsSideFile, "ld: warning: ");
71 vfprintf(sWarningsSideFile, format, list);
72 fprintf(sWarningsSideFile, "\n");
73 fflush(sWarningsSideFile);
75 va_end(list);
79 void throwf(const char* format, ...)
81 va_list list;
82 char* p;
83 va_start(list, format);
84 vasprintf(&p, format, list);
85 va_end(list);
87 const char* t = p;
88 throw t;
91 Options::Options(int argc, const char* argv[])
92 : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0), fArchitectureName("unknown"), fOutputKind(kDynamicExecutable),
93 fHasPreferredSubType(false), fArchSupportsThumb2(false), fPrebind(false), fBindAtLoad(false), fKeepPrivateExterns(false),
94 fNeedsModuleTable(false), fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false),
95 fInterposeMode(kInterposeNone), fDeadStrip(false), fNameSpace(kTwoLevelNameSpace),
96 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL), fFinalName(NULL), fEntryName("start"),
97 fBaseAddress(0), fMaxAddress(0x7FFFFFFFFFFFFFFFLL),
98 fBaseWritableAddress(0), fSplitSegs(false),
99 fExportMode(kExportDefault), fLibrarySearchMode(kSearchDylibAndArchiveInEachDir),
100 fUndefinedTreatment(kUndefinedError), fMessagesPrefixedWithArchitecture(true),
101 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak),
102 fClientName(NULL),
103 fUmbrellaName(NULL), fInitFunctionName(NULL), fDotOutputFile(NULL), fExecutablePath(NULL),
104 fBundleLoader(NULL), fDtraceScriptName(NULL), fSegAddrTablePath(NULL), fMapPath(NULL),
105 fDyldInstallPath("/usr/lib/dyld"), fTempLtoObjectPath(NULL),
106 fZeroPageSize(ULLONG_MAX), fStackSize(0), fStackAddr(0), fExecutableStack(false),
107 fNonExecutableHeap(false), fDisableNonExecutableHeap(false),
108 fMinimumHeaderPad(32), fSegmentAlignment(4096),
109 fCommonsMode(kCommonsIgnoreDylibs), fUUIDMode(kUUIDContent), fLocalSymbolHandling(kLocalSymbolsAll), fWarnCommons(false),
110 fVerbose(false), fKeepRelocations(false), fWarnStabs(false),
111 fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
112 fSharedRegionEligible(false), fPrintOrderFileStatistics(false),
113 fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), fPIEOnCommandLine(false),
114 fDisablePositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
115 fDeadStripDylibs(false), fAllowTextRelocs(false), fWarnTextRelocs(false),
116 fUsingLazyDylibLinking(false), fEncryptable(true),
117 fOrderData(true), fMarkDeadStrippableDylib(false),
118 fMakeCompressedDyldInfo(true), fMakeCompressedDyldInfoForceOff(false), fNoEHLabels(false),
119 fAllowCpuSubtypeMismatches(false), fUseSimplifiedDylibReExports(false),
120 fObjCABIVersion2Override(false), fObjCABIVersion1Override(false), fCanUseUpwardDylib(false),
121 fFullyLoadArchives(false), fLoadAllObjcObjectsFromArchives(false), fFlatNamespace(false),
122 fLinkingMainExecutable(false), fForFinalLinkedImage(false), fForStatic(false),
123 fForDyld(false), fMakeTentativeDefinitionsReal(false), fWhyLoad(false), fRootSafe(false),
124 fSetuidSafe(false), fImplicitlyLinkPublicDylibs(true), fAddCompactUnwindEncoding(true),
125 fWarnCompactUnwind(false), fRemoveDwarfUnwindIfCompactExists(false),
126 fAutoOrderInitializers(true), fOptimizeZeroFill(true), fMergeZeroFill(false), fLogObjectFiles(false),
127 fLogAllFiles(false), fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false),
128 fOutputSlidable(false), fWarnWeakExports(false),
129 fObjcGcCompaction(false), fObjCGc(false), fObjCGcOnly(false),
130 fDemangle(false), fTLVSupport(false),
131 fVersionLoadCommand(false), fVersionLoadCommandForcedOn(false),
132 fVersionLoadCommandForcedOff(false), fFunctionStartsLoadCommand(false),
133 fFunctionStartsForcedOn(false), fFunctionStartsForcedOff(false),
134 fCanReExportSymbols(false), fObjcCategoryMerging(true), fPageAlignDataAtoms(false),
135 fDebugInfoStripping(kDebugInfoMinimal), fTraceOutputFile(NULL),
136 fMacVersionMin(ld::macVersionUnset), fIOSVersionMin(ld::iOSVersionUnset),
137 fSaveTempFiles(false)
139 this->checkForClassic(argc, argv);
140 this->parsePreCommandLineEnvironmentSettings();
141 this->parse(argc, argv);
142 this->parsePostCommandLineEnvironmentSettings();
143 this->reconfigureDefaults();
144 this->checkIllegalOptionCombinations();
147 Options::~Options()
152 bool Options::errorBecauseOfWarnings() const
154 return (sFatalWarnings && (sWarningsCount > 0));
158 const char* Options::installPath() const
160 if ( fDylibInstallName != NULL )
161 return fDylibInstallName;
162 else if ( fFinalName != NULL )
163 return fFinalName;
164 else
165 return fOutputFile;
169 bool Options::interposable(const char* name) const
171 switch ( fInterposeMode ) {
172 case kInterposeNone:
173 return false;
174 case kInterposeAllExternal:
175 return true;
176 case kInterposeSome:
177 return fInterposeList.contains(name);
179 throw "internal error";
183 bool Options::printWhyLive(const char* symbolName) const
185 return ( fWhyLive.find(symbolName) != fWhyLive.end() );
189 const char* Options::dotOutputFile()
191 return fDotOutputFile;
195 bool Options::hasWildCardExportRestrictList() const
197 // has -exported_symbols_list which contains some wildcards
198 return ((fExportMode == kExportSome) && fExportSymbols.hasWildCards());
201 bool Options::hasWeakBitTweaks() const
203 // has -exported_symbols_list which contains some wildcards
204 return (!fForceWeakSymbols.empty() || !fForceNotWeakSymbols.empty());
207 bool Options::allGlobalsAreDeadStripRoots() const
209 // -exported_symbols_list means globals are not exported by default
210 if ( fExportMode == kExportSome )
211 return false;
213 switch ( fOutputKind ) {
214 case Options::kDynamicExecutable:
215 case Options::kStaticExecutable:
216 case Options::kPreload:
217 // by default unused globals in a main executable are stripped
218 return false;
219 case Options::kDynamicLibrary:
220 case Options::kDynamicBundle:
221 case Options::kObjectFile:
222 case Options::kDyld:
223 case Options::kKextBundle:
224 return true;
226 return false;
230 bool Options::keepRelocations()
232 return fKeepRelocations;
235 bool Options::warnStabs()
237 return fWarnStabs;
240 const char* Options::executablePath()
242 return fExecutablePath;
246 uint32_t Options::initialSegProtection(const char* segName) const
248 for(std::vector<Options::SegmentProtect>::const_iterator it = fCustomSegmentProtections.begin(); it != fCustomSegmentProtections.end(); ++it) {
249 if ( strcmp(it->name, segName) == 0 ) {
250 return it->init;
253 if ( strcmp(segName, "__PAGEZERO") == 0 ) {
254 return 0;
256 else if ( strcmp(segName, "__TEXT") == 0 ) {
257 return VM_PROT_READ | VM_PROT_EXECUTE;
259 else if ( strcmp(segName, "__LINKEDIT") == 0 ) {
260 return VM_PROT_READ;
263 // all others default to read-write
264 return VM_PROT_READ | VM_PROT_WRITE;
267 uint32_t Options::maxSegProtection(const char* segName) const
269 // iPhoneOS always uses same protection for max and initial
270 if ( fIOSVersionMin != ld::iOSVersionUnset )
271 return initialSegProtection(segName);
273 for(std::vector<Options::SegmentProtect>::const_iterator it = fCustomSegmentProtections.begin(); it != fCustomSegmentProtections.end(); ++it) {
274 if ( strcmp(it->name, segName) == 0 ) {
275 return it->max;
278 if ( strcmp(segName, "__PAGEZERO") == 0 ) {
279 return 0;
281 // all others default to all
282 return VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
285 uint64_t Options::segPageSize(const char* segName) const
287 for(std::vector<SegmentSize>::const_iterator it=fCustomSegmentSizes.begin(); it != fCustomSegmentSizes.end(); ++it) {
288 if ( strcmp(it->name, segName) == 0 )
289 return it->size;
291 return fSegmentAlignment;
294 uint64_t Options::customSegmentAddress(const char* segName) const
296 for(std::vector<SegmentStart>::const_iterator it=fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
297 if ( strcmp(it->name, segName) == 0 )
298 return it->address;
300 // if custom stack in use, model as segment with custom address
301 if ( (fStackSize != 0) && (strcmp("__UNIXSTACK", segName) == 0) )
302 return fStackAddr - fStackSize;
303 return 0;
306 bool Options::hasCustomSegmentAddress(const char* segName) const
308 for(std::vector<SegmentStart>::const_iterator it=fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
309 if ( strcmp(it->name, segName) == 0 )
310 return true;
312 // if custom stack in use, model as segment with custom address
313 if ( (fStackSize != 0) && (strcmp("__UNIXSTACK", segName) == 0) )
314 return true;
315 return false;
318 bool Options::hasCustomSectionAlignment(const char* segName, const char* sectName) const
320 for (std::vector<SectionAlignment>::const_iterator it = fSectionAlignments.begin(); it != fSectionAlignments.end(); ++it) {
321 if ( (strcmp(it->segmentName, segName) == 0) && (strcmp(it->sectionName, sectName) == 0) )
322 return true;
324 return false;
327 uint8_t Options::customSectionAlignment(const char* segName, const char* sectName) const
329 for (std::vector<SectionAlignment>::const_iterator it = fSectionAlignments.begin(); it != fSectionAlignments.end(); ++it) {
330 if ( (strcmp(it->segmentName, segName) == 0) && (strcmp(it->sectionName, sectName) == 0) )
331 return it->alignment;
333 return 0;
337 bool Options::hasExportedSymbolOrder()
339 return (fExportSymbolsOrder.size() > 0);
342 bool Options::exportedSymbolOrder(const char* sym, unsigned int* order) const
344 NameToOrder::const_iterator pos = fExportSymbolsOrder.find(sym);
345 if ( pos != fExportSymbolsOrder.end() ) {
346 *order = pos->second;
347 return true;
349 else {
350 *order = 0xFFFFFFFF;
351 return false;
355 void Options::loadSymbolOrderFile(const char* fileOfExports, NameToOrder& orderMapping)
357 // read in whole file
358 int fd = ::open(fileOfExports, O_RDONLY, 0);
359 if ( fd == -1 )
360 throwf("can't open -exported_symbols_order file: %s", fileOfExports);
361 struct stat stat_buf;
362 ::fstat(fd, &stat_buf);
363 char* p = (char*)malloc(stat_buf.st_size);
364 if ( p == NULL )
365 throwf("can't process -exported_symbols_order file: %s", fileOfExports);
367 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
368 throwf("can't read -exported_symbols_order file: %s", fileOfExports);
370 ::close(fd);
372 // parse into symbols and add to hash_set
373 unsigned int count = 0;
374 char * const end = &p[stat_buf.st_size];
375 enum { lineStart, inSymbol, inComment } state = lineStart;
376 char* symbolStart = NULL;
377 for (char* s = p; s < end; ++s ) {
378 switch ( state ) {
379 case lineStart:
380 if ( *s =='#' ) {
381 state = inComment;
383 else if ( !isspace(*s) ) {
384 state = inSymbol;
385 symbolStart = s;
387 break;
388 case inSymbol:
389 if ( (*s == '\n') || (*s == '\r') ) {
390 *s = '\0';
391 // removing any trailing spaces
392 char* last = s-1;
393 while ( isspace(*last) ) {
394 *last = '\0';
395 --last;
397 orderMapping[symbolStart] = ++count;
398 symbolStart = NULL;
399 state = lineStart;
401 break;
402 case inComment:
403 if ( (*s == '\n') || (*s == '\r') )
404 state = lineStart;
405 break;
408 if ( state == inSymbol ) {
409 warning("missing line-end at end of file \"%s\"", fileOfExports);
410 int len = end-symbolStart+1;
411 char* temp = new char[len];
412 strlcpy(temp, symbolStart, len);
414 // remove any trailing spaces
415 char* last = &temp[len-2];
416 while ( isspace(*last) ) {
417 *last = '\0';
418 --last;
420 orderMapping[temp] = ++count;
423 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
426 bool Options::forceWeak(const char* symbolName) const
428 return fForceWeakSymbols.contains(symbolName);
431 bool Options::forceNotWeak(const char* symbolName) const
433 return fForceNotWeakSymbols.contains(symbolName);
436 bool Options::forceWeakNonWildCard(const char* symbolName) const
438 return fForceWeakSymbols.containsNonWildcard(symbolName);
441 bool Options::forceNotWeakNonWildcard(const char* symbolName) const
443 return fForceNotWeakSymbols.containsNonWildcard(symbolName);
447 bool Options::shouldExport(const char* symbolName) const
449 switch (fExportMode) {
450 case kExportSome:
451 return fExportSymbols.contains(symbolName);
452 case kDontExportSome:
453 return ! fDontExportSymbols.contains(symbolName);
454 case kExportDefault:
455 return true;
457 throw "internal error";
460 bool Options::shouldReExport(const char* symbolName) const
462 return fReExportSymbols.contains(symbolName);
465 bool Options::keepLocalSymbol(const char* symbolName) const
467 switch (fLocalSymbolHandling) {
468 case kLocalSymbolsAll:
469 return true;
470 case kLocalSymbolsNone:
471 return false;
472 case kLocalSymbolsSelectiveInclude:
473 return fLocalSymbolsIncluded.contains(symbolName);
474 case kLocalSymbolsSelectiveExclude:
475 return ! fLocalSymbolsExcluded.contains(symbolName);
477 throw "internal error";
480 void Options::setArchitecture(cpu_type_t type, cpu_subtype_t subtype)
482 fArchitecture = type;
483 fSubArchitecture = subtype;
484 switch ( type ) {
485 case CPU_TYPE_I386:
486 fArchitectureName = "i386";
487 if ( (fMacVersionMin == ld::macVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
488 #ifdef DEFAULT_MACOSX_MIN_VERSION
489 warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION);
490 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
491 #else
492 warning("-macosx_version_min not specificed, assuming 10.6");
493 fMacVersionMin = ld::mac10_6;
494 #endif
496 if ( !fMakeCompressedDyldInfo && (fMacVersionMin >= ld::mac10_6) && !fMakeCompressedDyldInfoForceOff )
497 fMakeCompressedDyldInfo = true;
498 break;
499 case CPU_TYPE_X86_64:
500 fArchitectureName = "x86_64";
501 if ( (fMacVersionMin == ld::macVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
502 #ifdef DEFAULT_MACOSX_MIN_VERSION
503 warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION);
504 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
505 #else
506 warning("-macosx_version_min not specificed, assuming 10.6");
507 fMacVersionMin = ld::mac10_6;
508 #endif
510 if ( !fMakeCompressedDyldInfo && (fMacVersionMin >= ld::mac10_6) && !fMakeCompressedDyldInfoForceOff )
511 fMakeCompressedDyldInfo = true;
512 break;
513 case CPU_TYPE_ARM:
514 fHasPreferredSubType = true;
515 for (const ARMSubType* t=ARMSubTypes; t->subTypeName != NULL; ++t) {
516 if ( t->subType == subtype ) {
517 fArchitectureName = t->subTypeName;
518 fArchSupportsThumb2 = t->supportsThumb2;
519 break;
522 assert(fArchitectureName != NULL);
523 if ( (fMacVersionMin == ld::macVersionUnset) && (fIOSVersionMin == ld::iOSVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
524 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
525 warning("-ios_version_min not specificed, assuming " DEFAULT_IPHONEOS_MIN_VERSION);
526 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION);
527 #elif defined(DEFAULT_MACOSX_MIN_VERSION)
528 warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION);
529 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
530 #else
531 warning("-macosx_version_min not specificed, assuming 10.6");
532 fMacVersionMin = ld::mac10_6;
533 #endif
535 if ( !fMakeCompressedDyldInfo && minOS(ld::mac10_6, ld::iOS_3_1) && !fMakeCompressedDyldInfoForceOff )
536 fMakeCompressedDyldInfo = true;
537 break;
538 default:
539 fArchitectureName = "unknown architecture";
540 break;
544 void Options::parseArch(const char* arch)
546 if ( arch == NULL )
547 throw "-arch must be followed by an architecture string";
548 fArchitectureName = arch;
549 if ( strcmp(arch, "i386") == 0 ) {
550 fArchitecture = CPU_TYPE_I386;
551 fSubArchitecture = CPU_SUBTYPE_I386_ALL;
553 else if ( strcmp(arch, "x86_64") == 0 ) {
554 fArchitecture = CPU_TYPE_X86_64;
555 fSubArchitecture = CPU_SUBTYPE_X86_64_ALL;
557 else if ( strcmp(arch, "arm") == 0 ) {
558 fArchitecture = CPU_TYPE_ARM;
559 fSubArchitecture = CPU_SUBTYPE_ARM_ALL;
561 else {
562 for (const ARMSubType* t=ARMSubTypes; t->subTypeName != NULL; ++t) {
563 if ( strcmp(t->subTypeName,arch) == 0 ) {
564 fArchitecture = CPU_TYPE_ARM;
565 fSubArchitecture = t->subType;
566 fArchSupportsThumb2 = t->supportsThumb2;
567 fHasPreferredSubType = true;
568 return;
571 throwf("unknown/unsupported architecture name for: -arch %s", arch);
575 bool Options::checkForFile(const char* format, const char* dir, const char* rootName, FileInfo& result) const
577 struct stat statBuffer;
578 char possiblePath[strlen(dir)+strlen(rootName)+strlen(format)+8];
579 sprintf(possiblePath, format, dir, rootName);
580 bool found = (stat(possiblePath, &statBuffer) == 0);
581 if ( fTraceDylibSearching )
582 printf("[Logging for XBS]%sfound library: '%s'\n", (found ? " " : " not "), possiblePath);
583 if ( found ) {
584 result.path = strdup(possiblePath);
585 result.fileLen = statBuffer.st_size;
586 result.modTime = statBuffer.st_mtime;
587 return true;
589 return false;
593 Options::FileInfo Options::findLibrary(const char* rootName, bool dylibsOnly)
595 FileInfo result;
596 const int rootNameLen = strlen(rootName);
597 // if rootName ends in .o there is no .a vs .dylib choice
598 if ( (rootNameLen > 3) && (strcmp(&rootName[rootNameLen-2], ".o") == 0) ) {
599 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
600 it != fLibrarySearchPaths.end();
601 it++) {
602 const char* dir = *it;
603 if ( checkForFile("%s/%s", dir, rootName, result) )
604 return result;
607 else {
608 bool lookForDylibs = ( fOutputKind != Options::kDyld);
609 switch ( fLibrarySearchMode ) {
610 case kSearchAllDirsForDylibsThenAllDirsForArchives:
611 // first look in all directories for just for dylibs
612 if ( lookForDylibs ) {
613 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
614 it != fLibrarySearchPaths.end();
615 it++) {
616 const char* dir = *it;
617 if ( checkForFile("%s/lib%s.dylib", dir, rootName, result) )
618 return result;
620 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
621 it != fLibrarySearchPaths.end();
622 it++) {
623 const char* dir = *it;
624 if ( checkForFile("%s/lib%s.so", dir, rootName, result) )
625 return result;
628 // next look in all directories for just for archives
629 if ( !dylibsOnly ) {
630 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
631 it != fLibrarySearchPaths.end();
632 it++) {
633 const char* dir = *it;
634 if ( checkForFile("%s/lib%s.a", dir, rootName, result) )
635 return result;
638 break;
640 case kSearchDylibAndArchiveInEachDir:
641 // look in each directory for just for a dylib then for an archive
642 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
643 it != fLibrarySearchPaths.end();
644 it++) {
645 const char* dir = *it;
646 if ( lookForDylibs && checkForFile("%s/lib%s.dylib", dir, rootName, result) )
647 return result;
648 if ( lookForDylibs && checkForFile("%s/lib%s.so", dir, rootName, result) )
649 return result;
650 if ( !dylibsOnly && checkForFile("%s/lib%s.a", dir, rootName, result) )
651 return result;
653 break;
656 throwf("library not found for -l%s", rootName);
659 Options::FileInfo Options::findFramework(const char* frameworkName)
661 if ( frameworkName == NULL )
662 throw "-framework missing next argument";
663 char temp[strlen(frameworkName)+1];
664 strcpy(temp, frameworkName);
665 const char* name = temp;
666 const char* suffix = NULL;
667 char* comma = strchr(temp, ',');
668 if ( comma != NULL ) {
669 *comma = '\0';
670 suffix = &comma[1];
672 return findFramework(name, suffix);
675 Options::FileInfo Options::findFramework(const char* rootName, const char* suffix)
677 struct stat statBuffer;
678 for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin();
679 it != fFrameworkSearchPaths.end();
680 it++) {
681 // ??? Shouldn't we be using String here and just initializing it?
682 // ??? Use str.c_str () to pull out the string for the stat call.
683 const char* dir = *it;
684 char possiblePath[PATH_MAX];
685 strcpy(possiblePath, dir);
686 strcat(possiblePath, "/");
687 strcat(possiblePath, rootName);
688 strcat(possiblePath, ".framework/");
689 strcat(possiblePath, rootName);
690 if ( suffix != NULL ) {
691 char realPath[PATH_MAX];
692 // no symlink in framework to suffix variants, so follow main symlink
693 if ( realpath(possiblePath, realPath) != NULL ) {
694 strcpy(possiblePath, realPath);
695 strcat(possiblePath, suffix);
698 bool found = (stat(possiblePath, &statBuffer) == 0);
699 if ( fTraceDylibSearching )
700 printf("[Logging for XBS]%sfound framework: '%s'\n",
701 (found ? " " : " not "), possiblePath);
702 if ( found ) {
703 FileInfo result;
704 result.path = strdup(possiblePath);
705 result.fileLen = statBuffer.st_size;
706 result.modTime = statBuffer.st_mtime;
707 return result;
710 // try without suffix
711 if ( suffix != NULL )
712 return findFramework(rootName, NULL);
713 else
714 throwf("framework not found %s", rootName);
717 Options::FileInfo Options::findFile(const char* path) const
719 FileInfo result;
720 struct stat statBuffer;
722 // if absolute path and not a .o file, the use SDK prefix
723 if ( (path[0] == '/') && (strcmp(&path[strlen(path)-2], ".o") != 0) ) {
724 const int pathLen = strlen(path);
725 for (std::vector<const char*>::const_iterator it = fSDKPaths.begin(); it != fSDKPaths.end(); it++) {
726 // ??? Shouldn't we be using String here?
727 const char* sdkPathDir = *it;
728 const int sdkPathDirLen = strlen(sdkPathDir);
729 char possiblePath[sdkPathDirLen+pathLen+4];
730 strcpy(possiblePath, sdkPathDir);
731 if ( possiblePath[sdkPathDirLen-1] == '/' )
732 possiblePath[sdkPathDirLen-1] = '\0';
733 strcat(possiblePath, path);
734 if ( stat(possiblePath, &statBuffer) == 0 ) {
735 result.path = strdup(possiblePath);
736 result.fileLen = statBuffer.st_size;
737 result.modTime = statBuffer.st_mtime;
738 return result;
742 // try raw path
743 if ( stat(path, &statBuffer) == 0 ) {
744 result.path = strdup(path);
745 result.fileLen = statBuffer.st_size;
746 result.modTime = statBuffer.st_mtime;
747 return result;
750 // try @executable_path substitution
751 if ( (strncmp(path, "@executable_path/", 17) == 0) && (fExecutablePath != NULL) ) {
752 char newPath[strlen(fExecutablePath) + strlen(path)];
753 strcpy(newPath, fExecutablePath);
754 char* addPoint = strrchr(newPath,'/');
755 if ( addPoint != NULL )
756 strcpy(&addPoint[1], &path[17]);
757 else
758 strcpy(newPath, &path[17]);
759 if ( stat(newPath, &statBuffer) == 0 ) {
760 result.path = strdup(newPath);
761 result.fileLen = statBuffer.st_size;
762 result.modTime = statBuffer.st_mtime;
763 return result;
767 // not found
768 throwf("file not found: %s", path);
771 Options::FileInfo Options::findFileUsingPaths(const char* path) const
773 FileInfo result;
775 const char* lastSlash = strrchr(path, '/');
776 const char* leafName = (lastSlash == NULL) ? path : &lastSlash[1];
778 // Is this in a framework?
779 // /path/Foo.framework/Foo ==> true (Foo)
780 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
781 // /path/Foo.framework/Resources/Bar ==> false
782 bool isFramework = false;
783 if ( lastSlash != NULL ) {
784 char frameworkDir[strlen(leafName) + 20];
785 strcpy(frameworkDir, "/");
786 strcat(frameworkDir, leafName);
787 strcat(frameworkDir, ".framework/");
788 if ( strstr(path, frameworkDir) != NULL )
789 isFramework = true;
792 // These are abbreviated versions of the routines findFramework and findLibrary above
793 // because we already know the final name of the file that we're looking for and so
794 // don't need to try variations, just paths. We do need to add the additional bits
795 // onto the framework path though.
796 if ( isFramework ) {
797 for (std::vector<const char*>::const_iterator it = fFrameworkSearchPaths.begin();
798 it != fFrameworkSearchPaths.end();
799 it++) {
800 const char* dir = *it;
801 char possiblePath[PATH_MAX];
802 strcpy(possiblePath, dir);
803 strcat(possiblePath, "/");
804 strcat(possiblePath, leafName);
805 strcat(possiblePath, ".framework");
807 //fprintf(stderr,"Finding Framework: %s/%s, leafName=%s\n", possiblePath, leafName, leafName);
808 if ( checkForFile("%s/%s", possiblePath, leafName, result) )
809 return result;
812 else {
813 // if this is a .dylib inside a framework, do not search -L paths
814 // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
815 int leafLen = strlen(leafName);
816 bool embeddedDylib = ( (leafLen > 6)
817 && (strcmp(&leafName[leafLen-6], ".dylib") == 0)
818 && (strstr(path, ".framework/") != NULL) );
819 if ( !embeddedDylib ) {
820 for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
821 it != fLibrarySearchPaths.end();
822 it++) {
823 const char* dir = *it;
824 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
825 if ( checkForFile("%s/%s", dir, leafName, result) )
826 return result;
831 // If we didn't find it fall back to findFile.
832 return findFile(path);
836 void Options::parseSegAddrTable(const char* segAddrPath, const char* installPth)
838 FILE* file = fopen(segAddrPath, "r");
839 if ( file == NULL ) {
840 warning("-seg_addr_table file cannot be read: %s", segAddrPath);
841 return;
844 char path[PATH_MAX];
845 uint64_t firstColumAddress = 0;
846 uint64_t secondColumAddress = 0;
847 bool hasSecondColumn = false;
848 while ( fgets(path, PATH_MAX, file) != NULL ) {
849 path[PATH_MAX-1] = '\0';
850 char* eol = strchr(path, '\n');
851 if ( eol != NULL )
852 *eol = '\0';
853 // ignore lines not starting with 0x number
854 if ( (path[0] == '0') && (path[1] == 'x') ) {
855 char* p;
856 firstColumAddress = strtoull(path, &p, 16);
857 while ( isspace(*p) )
858 ++p;
859 // see if second column is a number
860 if ( (p[0] == '0') && (p[1] == 'x') ) {
861 secondColumAddress = strtoull(p, &p, 16);
862 hasSecondColumn = true;
863 while ( isspace(*p) )
864 ++p;
866 while ( isspace(*p) )
867 ++p;
868 if ( p[0] == '/' ) {
869 // remove any trailing whitespace
870 for(char* end = eol-1; (end > p) && isspace(*end); --end)
871 *end = '\0';
872 // see if this line is for the dylib being linked
873 if ( strcmp(p, installPth) == 0 ) {
874 fBaseAddress = firstColumAddress;
875 if ( hasSecondColumn ) {
876 fBaseWritableAddress = secondColumAddress;
877 fSplitSegs = true;
879 break; // out of while loop
885 fclose(file);
888 void Options::loadFileList(const char* fileOfPaths)
890 FILE* file;
891 const char* comma = strrchr(fileOfPaths, ',');
892 const char* prefix = NULL;
893 if ( comma != NULL ) {
894 // <rdar://problem/5907981> -filelist fails with comma in path
895 file = fopen(fileOfPaths, "r");
896 if ( file == NULL ) {
897 prefix = comma+1;
898 int realFileOfPathsLen = comma-fileOfPaths;
899 char realFileOfPaths[realFileOfPathsLen+1];
900 strncpy(realFileOfPaths,fileOfPaths, realFileOfPathsLen);
901 realFileOfPaths[realFileOfPathsLen] = '\0';
902 file = fopen(realFileOfPaths, "r");
903 if ( file == NULL )
904 throwf("-filelist file not found: %s\n", realFileOfPaths);
907 else {
908 file = fopen(fileOfPaths, "r");
909 if ( file == NULL )
910 throwf("-filelist file not found: %s\n", fileOfPaths);
913 char path[PATH_MAX];
914 while ( fgets(path, PATH_MAX, file) != NULL ) {
915 path[PATH_MAX-1] = '\0';
916 char* eol = strchr(path, '\n');
917 if ( eol != NULL )
918 *eol = '\0';
919 if ( prefix != NULL ) {
920 char builtPath[strlen(prefix)+strlen(path)+2];
921 strcpy(builtPath, prefix);
922 strcat(builtPath, "/");
923 strcat(builtPath, path);
924 fInputFiles.push_back(findFile(builtPath));
926 else {
927 fInputFiles.push_back(findFile(path));
930 fclose(file);
934 void Options::SetWithWildcards::remove(const NameSet& toBeRemoved)
936 for(NameSet::const_iterator it=toBeRemoved.begin(); it != toBeRemoved.end(); ++it) {
937 const char* symbolName = *it;
938 NameSet::iterator pos = fRegular.find(symbolName);
939 if ( pos != fRegular.end() )
940 fRegular.erase(pos);
944 bool Options::SetWithWildcards::hasWildCards(const char* symbol)
946 // an exported symbol name containing *, ?, or [ requires wildcard matching
947 return ( strpbrk(symbol, "*?[") != NULL );
950 void Options::SetWithWildcards::insert(const char* symbol)
952 if ( hasWildCards(symbol) )
953 fWildCard.push_back(symbol);
954 else
955 fRegular.insert(symbol);
958 bool Options::SetWithWildcards::contains(const char* symbol) const
960 // first look at hash table on non-wildcard symbols
961 if ( fRegular.find(symbol) != fRegular.end() )
962 return true;
963 // next walk list of wild card symbols looking for a match
964 for(std::vector<const char*>::const_iterator it = fWildCard.begin(); it != fWildCard.end(); ++it) {
965 if ( wildCardMatch(*it, symbol) )
966 return true;
968 return false;
971 bool Options::SetWithWildcards::containsNonWildcard(const char* symbol) const
973 // look at hash table on non-wildcard symbols
974 return ( fRegular.find(symbol) != fRegular.end() );
979 bool Options::SetWithWildcards::inCharRange(const char*& p, unsigned char c) const
981 ++p; // find end
982 const char* b = p;
983 while ( *p != '\0' ) {
984 if ( *p == ']') {
985 const char* e = p;
986 // found beginining [ and ending ]
987 unsigned char last = '\0';
988 for ( const char* s = b; s < e; ++s ) {
989 if ( *s == '-' ) {
990 unsigned char next = *(++s);
991 if ( (last <= c) && (c <= next) )
992 return true;
993 ++s;
995 else {
996 if ( *s == c )
997 return true;
998 last = *s;
1001 return false;
1003 ++p;
1005 return false;
1008 bool Options::SetWithWildcards::wildCardMatch(const char* pattern, const char* symbol) const
1010 const char* s = symbol;
1011 for (const char* p = pattern; *p != '\0'; ++p) {
1012 switch ( *p ) {
1013 case '*':
1014 if ( p[1] == '\0' )
1015 return true;
1016 for (const char* t = s; *t != '\0'; ++t) {
1017 if ( wildCardMatch(&p[1], t) )
1018 return true;
1020 return false;
1021 case '?':
1022 if ( *s == '\0' )
1023 return false;
1024 ++s;
1025 break;
1026 case '[':
1027 if ( ! inCharRange(p, *s) )
1028 return false;
1029 ++s;
1030 break;
1031 default:
1032 if ( *s != *p )
1033 return false;
1034 ++s;
1037 return (*s == '\0');
1041 void Options::loadExportFile(const char* fileOfExports, const char* option, SetWithWildcards& set)
1043 if ( fileOfExports == NULL )
1044 throwf("missing file after %s", option);
1045 // read in whole file
1046 int fd = ::open(fileOfExports, O_RDONLY, 0);
1047 if ( fd == -1 )
1048 throwf("can't open %s file: %s", option, fileOfExports);
1049 struct stat stat_buf;
1050 ::fstat(fd, &stat_buf);
1051 char* p = (char*)malloc(stat_buf.st_size);
1052 if ( p == NULL )
1053 throwf("can't process %s file: %s", option, fileOfExports);
1055 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1056 throwf("can't read %s file: %s", option, fileOfExports);
1058 ::close(fd);
1060 // parse into symbols and add to hash_set
1061 char * const end = &p[stat_buf.st_size];
1062 enum { lineStart, inSymbol, inComment } state = lineStart;
1063 char* symbolStart = NULL;
1064 for (char* s = p; s < end; ++s ) {
1065 switch ( state ) {
1066 case lineStart:
1067 if ( *s =='#' ) {
1068 state = inComment;
1070 else if ( !isspace(*s) ) {
1071 state = inSymbol;
1072 symbolStart = s;
1074 break;
1075 case inSymbol:
1076 if ( (*s == '\n') || (*s == '\r') ) {
1077 *s = '\0';
1078 // removing any trailing spaces
1079 char* last = s-1;
1080 while ( isspace(*last) ) {
1081 *last = '\0';
1082 --last;
1084 set.insert(symbolStart);
1085 symbolStart = NULL;
1086 state = lineStart;
1088 break;
1089 case inComment:
1090 if ( (*s == '\n') || (*s == '\r') )
1091 state = lineStart;
1092 break;
1095 if ( state == inSymbol ) {
1096 warning("missing line-end at end of file \"%s\"", fileOfExports);
1097 int len = end-symbolStart+1;
1098 char* temp = new char[len];
1099 strlcpy(temp, symbolStart, len);
1101 // remove any trailing spaces
1102 char* last = &temp[len-2];
1103 while ( isspace(*last) ) {
1104 *last = '\0';
1105 --last;
1107 set.insert(temp);
1110 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
1113 void Options::parseAliasFile(const char* fileOfAliases)
1115 // read in whole file
1116 int fd = ::open(fileOfAliases, O_RDONLY, 0);
1117 if ( fd == -1 )
1118 throwf("can't open alias file: %s", fileOfAliases);
1119 struct stat stat_buf;
1120 ::fstat(fd, &stat_buf);
1121 char* p = (char*)malloc(stat_buf.st_size+1);
1122 if ( p == NULL )
1123 throwf("can't process alias file: %s", fileOfAliases);
1125 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1126 throwf("can't read alias file: %s", fileOfAliases);
1127 p[stat_buf.st_size] = '\n';
1128 ::close(fd);
1130 // parse into symbols and add to fAliases
1131 AliasPair pair;
1132 char * const end = &p[stat_buf.st_size+1];
1133 enum { lineStart, inRealName, inBetween, inAliasName, inComment } state = lineStart;
1134 int lineNumber = 1;
1135 for (char* s = p; s < end; ++s ) {
1136 switch ( state ) {
1137 case lineStart:
1138 if ( *s =='#' ) {
1139 state = inComment;
1141 else if ( !isspace(*s) ) {
1142 state = inRealName;
1143 pair.realName = s;
1145 break;
1146 case inRealName:
1147 if ( *s == '\n' ) {
1148 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber, fileOfAliases);
1149 ++lineNumber;
1150 state = lineStart;
1152 else if ( isspace(*s) ) {
1153 *s = '\0';
1154 state = inBetween;
1156 break;
1157 case inBetween:
1158 if ( *s == '\n' ) {
1159 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber, fileOfAliases);
1160 ++lineNumber;
1161 state = lineStart;
1163 else if ( ! isspace(*s) ) {
1164 state = inAliasName;
1165 pair.alias = s;
1167 break;
1168 case inAliasName:
1169 if ( *s =='#' ) {
1170 *s = '\0';
1171 // removing any trailing spaces
1172 char* last = s-1;
1173 while ( isspace(*last) ) {
1174 *last = '\0';
1175 --last;
1177 fAliases.push_back(pair);
1178 state = inComment;
1180 else if ( *s == '\n' ) {
1181 *s = '\0';
1182 // removing any trailing spaces
1183 char* last = s-1;
1184 while ( isspace(*last) ) {
1185 *last = '\0';
1186 --last;
1188 fAliases.push_back(pair);
1189 state = lineStart;
1191 break;
1192 case inComment:
1193 if ( *s == '\n' )
1194 state = lineStart;
1195 break;
1199 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
1204 void Options::setUndefinedTreatment(const char* treatment)
1206 if ( treatment == NULL )
1207 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
1209 if ( strcmp(treatment, "warning") == 0 )
1210 fUndefinedTreatment = kUndefinedWarning;
1211 else if ( strcmp(treatment, "error") == 0 )
1212 fUndefinedTreatment = kUndefinedError;
1213 else if ( strcmp(treatment, "suppress") == 0 )
1214 fUndefinedTreatment = kUndefinedSuppress;
1215 else if ( strcmp(treatment, "dynamic_lookup") == 0 )
1216 fUndefinedTreatment = kUndefinedDynamicLookup;
1217 else
1218 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1221 Options::Treatment Options::parseTreatment(const char* treatment)
1223 if ( treatment == NULL )
1224 return kNULL;
1226 if ( strcmp(treatment, "warning") == 0 )
1227 return kWarning;
1228 else if ( strcmp(treatment, "error") == 0 )
1229 return kError;
1230 else if ( strcmp(treatment, "suppress") == 0 )
1231 return kSuppress;
1232 else
1233 return kInvalid;
1236 void Options::setMacOSXVersionMin(const char* version)
1238 if ( version == NULL )
1239 throw "-macosx_version_min argument missing";
1241 if ( (strncmp(version, "10.", 3) == 0) && isdigit(version[3]) ) {
1242 unsigned int minorVersion = version[3] - '0';
1243 fMacVersionMin = (ld::MacVersionMin)(0x000A0000 | (minorVersion << 8));
1245 else {
1246 warning("unknown option to -macosx_version_min, not 10.x");
1250 void Options::setIOSVersionMin(const char* version)
1252 if ( version == NULL )
1253 throw "-ios_version_min argument missing";
1254 if ( ! isdigit(version[0]) )
1255 throw "-ios_version_min argument is not a number";
1256 if ( version[1] != '.' )
1257 throw "-ios_version_min argument is missing period as second character";
1258 if ( ! isdigit(version[2]) )
1259 throw "-ios_version_min argument is not a number";
1261 unsigned int majorVersion = version[0] - '0';
1262 unsigned int minorVersion = version[2] - '0';
1263 fIOSVersionMin = (ld::IOSVersionMin)((majorVersion << 16) | (minorVersion << 8));
1266 bool Options::minOS(ld::MacVersionMin requiredMacMin, ld::IOSVersionMin requirediPhoneOSMin)
1268 if ( fMacVersionMin != ld::macVersionUnset ) {
1269 return ( fMacVersionMin >= requiredMacMin );
1271 else {
1272 return ( fIOSVersionMin >= requirediPhoneOSMin);
1277 void Options::setWeakReferenceMismatchTreatment(const char* treatment)
1279 if ( treatment == NULL )
1280 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1282 if ( strcmp(treatment, "error") == 0 )
1283 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchError;
1284 else if ( strcmp(treatment, "weak") == 0 )
1285 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchWeak;
1286 else if ( strcmp(treatment, "non-weak") == 0 )
1287 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchNonWeak;
1288 else
1289 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1292 Options::CommonsMode Options::parseCommonsTreatment(const char* mode)
1294 if ( mode == NULL )
1295 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1297 if ( strcmp(mode, "ignore_dylibs") == 0 )
1298 return kCommonsIgnoreDylibs;
1299 else if ( strcmp(mode, "use_dylibs") == 0 )
1300 return kCommonsOverriddenByDylibs;
1301 else if ( strcmp(mode, "error") == 0 )
1302 return kCommonsConflictsDylibsError;
1303 else
1304 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1307 void Options::addDylibOverride(const char* paths)
1309 if ( paths == NULL )
1310 throw "-dylib_file must followed by two colon separated paths";
1311 const char* colon = strchr(paths, ':');
1312 if ( colon == NULL )
1313 throw "-dylib_file must followed by two colon separated paths";
1314 int len = colon-paths;
1315 char* target = new char[len+2];
1316 strncpy(target, paths, len);
1317 target[len] = '\0';
1318 DylibOverride entry;
1319 entry.installName = target;
1320 entry.useInstead = &colon[1];
1321 fDylibOverrides.push_back(entry);
1324 uint64_t Options::parseAddress(const char* addr)
1326 char* endptr;
1327 uint64_t result = strtoull(addr, &endptr, 16);
1328 return result;
1331 uint32_t Options::parseProtection(const char* prot)
1333 uint32_t result = 0;
1334 for(const char* p = prot; *p != '\0'; ++p) {
1335 switch(tolower(*p)) {
1336 case 'r':
1337 result |= VM_PROT_READ;
1338 break;
1339 case 'w':
1340 result |= VM_PROT_WRITE;
1341 break;
1342 case 'x':
1343 result |= VM_PROT_EXECUTE;
1344 break;
1345 case '-':
1346 break;
1347 default:
1348 throwf("unknown -segprot lettter in %s", prot);
1351 return result;
1356 // Parses number of form A[.B[.B[.D[.E]]]] into a uint64_t where the bits are a24.b10.c10.d10.e10
1358 uint64_t Options::parseVersionNumber64(const char* versionString)
1360 uint64_t a = 0;
1361 uint64_t b = 0;
1362 uint64_t c = 0;
1363 uint64_t d = 0;
1364 uint64_t e = 0;
1365 char* end;
1366 a = strtoul(versionString, &end, 10);
1367 if ( *end == '.' ) {
1368 b = strtoul(&end[1], &end, 10);
1369 if ( *end == '.' ) {
1370 c = strtoul(&end[1], &end, 10);
1371 if ( *end == '.' ) {
1372 d = strtoul(&end[1], &end, 10);
1373 if ( *end == '.' ) {
1374 e = strtoul(&end[1], &end, 10);
1379 if ( (*end != '\0') || (a > 0xFFFFFF) || (b > 0x3FF) || (c > 0x3FF) || (d > 0x3FF) || (e > 0x3FF) )
1380 throwf("malformed 64-bit a.b.c.d.e version number: %s", versionString);
1382 return (a << 40) | ( b << 30 ) | ( c << 20 ) | ( d << 10 ) | e;
1386 uint32_t Options::currentVersion32() const
1388 // warn if it does not fit into 32 bit vers number
1389 uint32_t a = (fDylibCurrentVersion >> 40) & 0xFFFF;
1390 uint32_t b = (fDylibCurrentVersion >> 30) & 0xFF;
1391 uint32_t c = (fDylibCurrentVersion >> 20) & 0xFF;
1392 uint64_t rep32 = ((uint64_t)a << 40) | ((uint64_t)b << 30) | ((uint64_t)c << 20);
1393 if ( rep32 != fDylibCurrentVersion ) {
1394 warning("truncating -current_version to fit in 32-bit space used by old mach-o format");
1395 a = (fDylibCurrentVersion >> 40) & 0xFFFFFF;
1396 if ( a > 0xFFFF )
1397 a = 0xFFFF;
1398 b = (fDylibCurrentVersion >> 30) & 0x3FF;
1399 if ( b > 0xFF )
1400 b = 0xFF;
1401 c = (fDylibCurrentVersion >> 20) & 0x3FF;
1402 if ( c > 0xFF )
1403 c = 0xFF;
1405 return (a << 16) | ( b << 8 ) | c;
1409 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1411 uint32_t Options::parseVersionNumber32(const char* versionString)
1413 uint32_t x = 0;
1414 uint32_t y = 0;
1415 uint32_t z = 0;
1416 char* end;
1417 x = strtoul(versionString, &end, 10);
1418 if ( *end == '.' ) {
1419 y = strtoul(&end[1], &end, 10);
1420 if ( *end == '.' ) {
1421 z = strtoul(&end[1], &end, 10);
1424 if ( (*end != '\0') || (x > 0xffff) || (y > 0xff) || (z > 0xff) )
1425 throwf("malformed 32-bit x.y.z version number: %s", versionString);
1427 return (x << 16) | ( y << 8 ) | z;
1430 static const char* cstringSymbolName(const char* orderFileString)
1432 char* result;
1433 asprintf(&result, "cstring=%s", orderFileString);
1434 // convert escaped characters
1435 char* d = result;
1436 for(const char* s=result; *s != '\0'; ++s, ++d) {
1437 if ( *s == '\\' ) {
1438 ++s;
1439 switch ( *s ) {
1440 case 'n':
1441 *d = '\n';
1442 break;
1443 case 't':
1444 *d = '\t';
1445 break;
1446 case 'v':
1447 *d = '\v';
1448 break;
1449 case 'b':
1450 *d = '\b';
1451 break;
1452 case 'r':
1453 *d = '\r';
1454 break;
1455 case 'f':
1456 *d = '\f';
1457 break;
1458 case 'a':
1459 *d = '\a';
1460 break;
1461 case '\\':
1462 *d = '\\';
1463 break;
1464 case '?':
1465 *d = '\?';
1466 break;
1467 case '\'':
1468 *d = '\r';
1469 break;
1470 case '\"':
1471 *d = '\"';
1472 break;
1473 case 'x':
1474 // hexadecimal value of char
1476 ++s;
1477 char value = 0;
1478 while ( isxdigit(*s) ) {
1479 value *= 16;
1480 if ( isdigit(*s) )
1481 value += (*s-'0');
1482 else
1483 value += ((toupper(*s)-'A') + 10);
1484 ++s;
1486 *d = value;
1488 break;
1489 default:
1490 if ( isdigit(*s) ) {
1491 // octal value of char
1492 char value = 0;
1493 while ( isdigit(*s) ) {
1494 value = (value << 3) + (*s-'0');
1495 ++s;
1497 *d = value;
1501 else {
1502 *d = *s;
1505 *d = '\0';
1506 return result;
1509 void Options::parseOrderFile(const char* path, bool cstring)
1511 // order files override auto-ordering
1512 fAutoOrderInitializers = false;
1514 // read in whole file
1515 int fd = ::open(path, O_RDONLY, 0);
1516 if ( fd == -1 )
1517 throwf("can't open order file: %s", path);
1518 struct stat stat_buf;
1519 ::fstat(fd, &stat_buf);
1520 char* p = (char*)malloc(stat_buf.st_size+1);
1521 if ( p == NULL )
1522 throwf("can't process order file: %s", path);
1523 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1524 throwf("can't read order file: %s", path);
1525 ::close(fd);
1526 p[stat_buf.st_size] = '\n';
1528 // parse into vector of pairs
1529 char * const end = &p[stat_buf.st_size+1];
1530 enum { lineStart, inSymbol, inComment } state = lineStart;
1531 char* symbolStart = NULL;
1532 for (char* s = p; s < end; ++s ) {
1533 switch ( state ) {
1534 case lineStart:
1535 if ( *s =='#' ) {
1536 state = inComment;
1538 else if ( !isspace(*s) || cstring ) {
1539 state = inSymbol;
1540 symbolStart = s;
1542 break;
1543 case inSymbol:
1544 if ( (*s == '\n') || (!cstring && (*s == '#')) ) {
1545 bool wasComment = (*s == '#');
1546 *s = '\0';
1547 // removing any trailing spaces
1548 char* last = s-1;
1549 while ( isspace(*last) ) {
1550 *last = '\0';
1551 --last;
1553 // if there is an architecture prefix, only use this symbol it if matches current arch
1554 if ( strncmp(symbolStart, "ppc:", 4) == 0 ) {
1555 symbolStart = NULL;
1557 else if ( strncmp(symbolStart, "ppc64:", 6) == 0 ) {
1558 symbolStart = NULL;
1560 else if ( strncmp(symbolStart, "i386:", 5) == 0 ) {
1561 if ( fArchitecture == CPU_TYPE_I386 )
1562 symbolStart = &symbolStart[5];
1563 else
1564 symbolStart = NULL;
1566 else if ( strncmp(symbolStart, "x86_64:", 7) == 0 ) {
1567 if ( fArchitecture == CPU_TYPE_X86_64 )
1568 symbolStart = &symbolStart[7];
1569 else
1570 symbolStart = NULL;
1572 else if ( strncmp(symbolStart, "arm:", 4) == 0 ) {
1573 if ( fArchitecture == CPU_TYPE_ARM )
1574 symbolStart = &symbolStart[4];
1575 else
1576 symbolStart = NULL;
1578 if ( symbolStart != NULL ) {
1579 char* objFileName = NULL;
1580 char* colon = strstr(symbolStart, ".o:");
1581 if ( colon != NULL ) {
1582 colon[2] = '\0';
1583 objFileName = symbolStart;
1584 symbolStart = &colon[3];
1586 // trim leading spaces
1587 while ( isspace(*symbolStart) )
1588 ++symbolStart;
1589 Options::OrderedSymbol pair;
1590 if ( cstring )
1591 pair.symbolName = cstringSymbolName(symbolStart);
1592 else
1593 pair.symbolName = symbolStart;
1594 pair.objectFileName = objFileName;
1595 fOrderedSymbols.push_back(pair);
1597 symbolStart = NULL;
1598 if ( wasComment )
1599 state = inComment;
1600 else
1601 state = lineStart;
1603 break;
1604 case inComment:
1605 if ( *s == '\n' )
1606 state = lineStart;
1607 break;
1610 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1613 void Options::parseSectionOrderFile(const char* segment, const char* section, const char* path)
1615 if ( (strcmp(section, "__cstring") == 0) && (strcmp(segment, "__TEXT") == 0) ) {
1616 parseOrderFile(path, true);
1618 else if ( (strncmp(section, "__literal",9) == 0) && (strcmp(segment, "__TEXT") == 0) ) {
1619 warning("sorting of __literal[4,8,16] sections not supported");
1621 else {
1622 // ignore section information and append all symbol names to global order file
1623 parseOrderFile(path, false);
1627 void Options::addSection(const char* segment, const char* section, const char* path)
1629 if ( strlen(segment) > 16 )
1630 throw "-seccreate segment name max 16 chars";
1631 if ( strlen(section) > 16 ) {
1632 char* tmp = strdup(section);
1633 tmp[16] = '\0';
1634 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section, tmp);
1635 section = tmp;
1638 // read in whole file
1639 int fd = ::open(path, O_RDONLY, 0);
1640 if ( fd == -1 )
1641 throwf("can't open -sectcreate file: %s", path);
1642 struct stat stat_buf;
1643 ::fstat(fd, &stat_buf);
1644 char* p = (char*)malloc(stat_buf.st_size);
1645 if ( p == NULL )
1646 throwf("can't process -sectcreate file: %s", path);
1647 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1648 throwf("can't read -sectcreate file: %s", path);
1649 ::close(fd);
1651 // record section to create
1652 ExtraSection info = { segment, section, path, (uint8_t*)p, stat_buf.st_size };
1653 fExtraSections.push_back(info);
1656 void Options::addSectionAlignment(const char* segment, const char* section, const char* alignmentStr)
1658 if ( strlen(segment) > 16 )
1659 throw "-sectalign segment name max 16 chars";
1660 if ( strlen(section) > 16 )
1661 throw "-sectalign section name max 16 chars";
1663 // argument to -sectalign is a hexadecimal number
1664 char* endptr;
1665 unsigned long value = strtoul(alignmentStr, &endptr, 16);
1666 if ( *endptr != '\0')
1667 throw "argument for -sectalign is not a hexadecimal number";
1668 if ( value > 0x8000 )
1669 throw "argument for -sectalign must be less than or equal to 0x8000";
1670 if ( value == 0 ) {
1671 warning("zero is not a valid -sectalign");
1672 value = 1;
1675 // alignment is power of 2 (e.g. page alignment = 12)
1676 uint8_t alignment = (uint8_t)__builtin_ctz(value);
1677 if ( (unsigned long)(1 << alignment) != value ) {
1678 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
1679 segment, section, 1 << alignment);
1682 SectionAlignment info = { segment, section, alignment };
1683 fSectionAlignments.push_back(info);
1686 void Options::addLibrary(const FileInfo& info)
1688 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
1689 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
1690 if ( strcmp(info.path, fit->path) == 0 ) {
1691 // if dylib is specified again but weak, record that it should be weak
1692 if ( info.options.fWeakImport )
1693 fit->options.fWeakImport = true;
1694 return;
1697 // add to list
1698 fInputFiles.push_back(info);
1701 void Options::warnObsolete(const char* arg)
1703 warning("option %s is obsolete and being ignored", arg);
1710 // Process all command line arguments.
1712 // The only error checking done here is that each option is valid and if it has arguments
1713 // that they too are valid.
1715 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
1716 // whichever was last on the command line is used.
1718 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
1720 void Options::parse(int argc, const char* argv[])
1722 // pass one builds search list from -L and -F options
1723 this->buildSearchPaths(argc, argv);
1725 // reduce re-allocations
1726 fInputFiles.reserve(32);
1728 // pass two parse all other options
1729 for(int i=1; i < argc; ++i) {
1730 const char* arg = argv[i];
1732 if ( arg[0] == '-' ) {
1734 // Since we don't care about the files passed, just the option names, we do this here.
1735 if (fPrintOptions)
1736 fprintf (stderr, "[Logging ld64 options]\t%s\n", arg);
1738 if ( (arg[1] == 'L') || (arg[1] == 'F') ) {
1739 if (arg[2] == '\0')
1740 ++i;
1741 // previously handled by buildSearchPaths()
1743 // The one gnu style option we have to keep compatibility
1744 // with gcc. Might as well have the single hyphen one as well.
1745 else if ( (strcmp(arg, "--help") == 0)
1746 || (strcmp(arg, "-help") == 0)) {
1747 fprintf (stdout, "ld64: For information on command line options please use 'man ld'.\n");
1748 exit (0);
1750 else if ( strcmp(arg, "-arch") == 0 ) {
1751 parseArch(argv[++i]);
1753 else if ( strcmp(arg, "-dynamic") == 0 ) {
1754 // default
1756 else if ( strcmp(arg, "-static") == 0 ) {
1757 fForStatic = true;
1758 if ( (fOutputKind != kObjectFile) && (fOutputKind != kKextBundle) ) {
1759 fOutputKind = kStaticExecutable;
1762 else if ( strcmp(arg, "-dylib") == 0 ) {
1763 fOutputKind = kDynamicLibrary;
1765 else if ( strcmp(arg, "-bundle") == 0 ) {
1766 fOutputKind = kDynamicBundle;
1768 else if ( strcmp(arg, "-dylinker") == 0 ) {
1769 fOutputKind = kDyld;
1771 else if ( strcmp(arg, "-execute") == 0 ) {
1772 if ( fOutputKind != kStaticExecutable )
1773 fOutputKind = kDynamicExecutable;
1775 else if ( strcmp(arg, "-preload") == 0 ) {
1776 fOutputKind = kPreload;
1778 else if ( strcmp(arg, "-r") == 0 ) {
1779 fOutputKind = kObjectFile;
1781 else if ( strcmp(arg, "-kext") == 0 ) {
1782 fOutputKind = kKextBundle;
1784 else if ( strcmp(arg, "-o") == 0 ) {
1785 fOutputFile = argv[++i];
1787 else if ( strncmp(arg, "-lazy-l", 7) == 0 ) {
1788 FileInfo info = findLibrary(&arg[7], true);
1789 info.options.fLazyLoad = true;
1790 addLibrary(info);
1791 fUsingLazyDylibLinking = true;
1793 else if ( (arg[1] == 'l') && (strncmp(arg,"-lazy_",6) !=0) ) {
1794 addLibrary(findLibrary(&arg[2]));
1796 // This causes a dylib to be weakly bound at
1797 // link time. This corresponds to weak_import.
1798 else if ( strncmp(arg, "-weak-l", 7) == 0 ) {
1799 FileInfo info = findLibrary(&arg[7]);
1800 info.options.fWeakImport = true;
1801 addLibrary(info);
1803 // Avoid lazy binding.
1804 else if ( strcmp(arg, "-bind_at_load") == 0 ) {
1805 fBindAtLoad = true;
1807 else if ( strcmp(arg, "-twolevel_namespace") == 0 ) {
1808 fNameSpace = kTwoLevelNameSpace;
1810 else if ( strcmp(arg, "-flat_namespace") == 0 ) {
1811 fNameSpace = kFlatNameSpace;
1813 // Also sets a bit to ensure dyld causes everything
1814 // in the namespace to be flat.
1815 // ??? Deprecate
1816 else if ( strcmp(arg, "-force_flat_namespace") == 0 ) {
1817 fNameSpace = kForceFlatNameSpace;
1819 // Similar to --whole-archive.
1820 else if ( strcmp(arg, "-all_load") == 0 ) {
1821 fFullyLoadArchives = true;
1823 else if ( strcmp(arg, "-noall_load") == 0) {
1824 warnObsolete(arg);
1826 // Similar to -all_load
1827 else if ( strcmp(arg, "-ObjC") == 0 ) {
1828 fLoadAllObjcObjectsFromArchives = true;
1830 // Similar to -all_load, but for the following archive only.
1831 else if ( strcmp(arg, "-force_load") == 0 ) {
1832 FileInfo info = findFile(argv[++i]);
1833 info.options.fForceLoad = true;
1834 addLibrary(info);
1836 // Library versioning.
1837 else if ( (strcmp(arg, "-dylib_compatibility_version") == 0)
1838 || (strcmp(arg, "-compatibility_version") == 0)) {
1839 const char* vers = argv[++i];
1840 if ( vers == NULL )
1841 throw "-dylib_compatibility_version missing <version>";
1842 fDylibCompatVersion = parseVersionNumber32(vers);
1844 else if ( (strcmp(arg, "-dylib_current_version") == 0)
1845 || (strcmp(arg, "-current_version") == 0)) {
1846 const char* vers = argv[++i];
1847 if ( vers == NULL )
1848 throw "-dylib_current_version missing <version>";
1849 fDylibCurrentVersion = parseVersionNumber64(vers);
1851 else if ( strcmp(arg, "-sectorder") == 0 ) {
1852 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
1853 throw "-sectorder missing <segment> <section> <file-path>";
1854 parseSectionOrderFile(argv[i+1], argv[i+2], argv[i+3]);
1855 i += 3;
1857 else if ( strcmp(arg, "-order_file") == 0 ) {
1858 parseOrderFile(argv[++i], false);
1860 else if ( strcmp(arg, "-order_file_statistics") == 0 ) {
1861 fPrintOrderFileStatistics = true;
1863 // ??? Deprecate segcreate.
1864 // -sectcreate puts whole files into a section in the output.
1865 else if ( (strcmp(arg, "-sectcreate") == 0) || (strcmp(arg, "-segcreate") == 0) ) {
1866 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
1867 throw "-sectcreate missing <segment> <section> <file-path>";
1868 addSection(argv[i+1], argv[i+2], argv[i+3]);
1869 i += 3;
1871 // Since we have a full path in binary/library names we need to be able to override it.
1872 else if ( (strcmp(arg, "-dylib_install_name") == 0)
1873 || (strcmp(arg, "-dylinker_install_name") == 0)
1874 || (strcmp(arg, "-install_name") == 0)) {
1875 fDylibInstallName = argv[++i];
1876 if ( fDylibInstallName == NULL )
1877 throw "-install_name missing <path>";
1879 // Sets the base address of the output.
1880 else if ( (strcmp(arg, "-seg1addr") == 0) || (strcmp(arg, "-image_base") == 0) ) {
1881 const char* address = argv[++i];
1882 if ( address == NULL )
1883 throwf("%s missing <address>", arg);
1884 fBaseAddress = parseAddress(address);
1885 uint64_t temp = ((fBaseAddress+fSegmentAlignment-1) & (-fSegmentAlignment));
1886 if ( fBaseAddress != temp ) {
1887 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment);
1888 fBaseAddress = temp;
1891 else if ( strcmp(arg, "-e") == 0 ) {
1892 fEntryName = argv[++i];
1894 // Same as -@ from the FSF linker.
1895 else if ( strcmp(arg, "-filelist") == 0 ) {
1896 const char* path = argv[++i];
1897 if ( (path == NULL) || (path[0] == '-') )
1898 throw "-filelist missing <path>";
1899 loadFileList(path);
1901 else if ( strcmp(arg, "-keep_private_externs") == 0 ) {
1902 fKeepPrivateExterns = true;
1904 else if ( strcmp(arg, "-final_output") == 0 ) {
1905 fFinalName = argv[++i];
1907 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
1908 // just ensures that this happens for cross object file boundaries.
1909 else if ( (strcmp(arg, "-interposable") == 0) || (strcmp(arg, "-multi_module") == 0)) {
1910 switch ( fInterposeMode ) {
1911 case kInterposeNone:
1912 case kInterposeAllExternal:
1913 fInterposeMode = kInterposeAllExternal;
1914 break;
1915 case kInterposeSome:
1916 // do nothing, -interposable_list overrides -interposable"
1917 break;
1920 else if ( strcmp(arg, "-interposable_list") == 0 ) {
1921 fInterposeMode = kInterposeSome;
1922 loadExportFile(argv[++i], "-interposable_list", fInterposeList);
1924 // Default for -interposable/-multi_module/-single_module.
1925 else if ( strcmp(arg, "-single_module") == 0 ) {
1926 fInterposeMode = kInterposeNone;
1928 else if ( strcmp(arg, "-exported_symbols_list") == 0 ) {
1929 if ( fExportMode == kDontExportSome )
1930 throw "can't use -exported_symbols_list and -unexported_symbols_list";
1931 fExportMode = kExportSome;
1932 loadExportFile(argv[++i], "-exported_symbols_list", fExportSymbols);
1934 else if ( strcmp(arg, "-unexported_symbols_list") == 0 ) {
1935 if ( fExportMode == kExportSome )
1936 throw "can't use -unexported_symbols_list and -exported_symbols_list";
1937 fExportMode = kDontExportSome;
1938 loadExportFile(argv[++i], "-unexported_symbols_list", fDontExportSymbols);
1940 else if ( strcmp(arg, "-exported_symbol") == 0 ) {
1941 if ( fExportMode == kDontExportSome )
1942 throw "can't use -exported_symbol and -unexported_symbols";
1943 fExportMode = kExportSome;
1944 fExportSymbols.insert(argv[++i]);
1946 else if ( strcmp(arg, "-unexported_symbol") == 0 ) {
1947 if ( fExportMode == kExportSome )
1948 throw "can't use -unexported_symbol and -exported_symbol";
1949 fExportMode = kDontExportSome;
1950 fDontExportSymbols.insert(argv[++i]);
1952 else if ( strcmp(arg, "-non_global_symbols_no_strip_list") == 0 ) {
1953 if ( fLocalSymbolHandling == kLocalSymbolsSelectiveExclude )
1954 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
1955 fLocalSymbolHandling = kLocalSymbolsSelectiveInclude;
1956 loadExportFile(argv[++i], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded);
1958 else if ( strcmp(arg, "-non_global_symbols_strip_list") == 0 ) {
1959 if ( fLocalSymbolHandling == kLocalSymbolsSelectiveInclude )
1960 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
1961 fLocalSymbolHandling = kLocalSymbolsSelectiveExclude;
1962 loadExportFile(argv[++i], "-non_global_symbols_strip_list", fLocalSymbolsExcluded);
1964 // ??? Deprecate
1965 else if ( strcmp(arg, "-no_arch_warnings") == 0 ) {
1966 fIgnoreOtherArchFiles = true;
1968 else if ( strcmp(arg, "-force_cpusubtype_ALL") == 0 ) {
1969 fForceSubtypeAll = true;
1970 fAllowCpuSubtypeMismatches = true;
1972 // Similar to -weak-l but uses the absolute path name to the library.
1973 else if ( strcmp(arg, "-weak_library") == 0 ) {
1974 FileInfo info = findFile(argv[++i]);
1975 info.options.fWeakImport = true;
1976 addLibrary(info);
1978 else if ( strcmp(arg, "-lazy_library") == 0 ) {
1979 FileInfo info = findFile(argv[++i]);
1980 info.options.fLazyLoad = true;
1981 addLibrary(info);
1982 fUsingLazyDylibLinking = true;
1984 else if ( strcmp(arg, "-framework") == 0 ) {
1985 addLibrary(findFramework(argv[++i]));
1987 else if ( strcmp(arg, "-weak_framework") == 0 ) {
1988 FileInfo info = findFramework(argv[++i]);
1989 info.options.fWeakImport = true;
1990 addLibrary(info);
1992 else if ( strcmp(arg, "-lazy_framework") == 0 ) {
1993 FileInfo info = findFramework(argv[++i]);
1994 info.options.fLazyLoad = true;
1995 addLibrary(info);
1996 fUsingLazyDylibLinking = true;
1998 else if ( strcmp(arg, "-search_paths_first") == 0 ) {
1999 // previously handled by buildSearchPaths()
2001 else if ( strcmp(arg, "-search_dylibs_first") == 0 ) {
2002 // previously handled by buildSearchPaths()
2004 else if ( strcmp(arg, "-undefined") == 0 ) {
2005 setUndefinedTreatment(argv[++i]);
2007 // Debugging output flag.
2008 else if ( strcmp(arg, "-arch_multiple") == 0 ) {
2009 fMessagesPrefixedWithArchitecture = true;
2011 // Specify what to do with relocations in read only
2012 // sections like .text. Could be errors, warnings,
2013 // or suppressed. Currently we do nothing with the
2014 // flag.
2015 else if ( strcmp(arg, "-read_only_relocs") == 0 ) {
2016 switch ( parseTreatment(argv[++i]) ) {
2017 case kNULL:
2018 case kInvalid:
2019 throw "-read_only_relocs missing [ warning | error | suppress ]";
2020 case kWarning:
2021 fWarnTextRelocs = true;
2022 fAllowTextRelocs = true;
2023 break;
2024 case kSuppress:
2025 fWarnTextRelocs = false;
2026 fAllowTextRelocs = true;
2027 break;
2028 case kError:
2029 fWarnTextRelocs = false;
2030 fAllowTextRelocs = false;
2031 break;
2034 else if ( strcmp(arg, "-sect_diff_relocs") == 0 ) {
2035 warnObsolete(arg);
2036 ++i;
2038 // Warn, error or make strong a mismatch between weak
2039 // and non-weak references.
2040 else if ( strcmp(arg, "-weak_reference_mismatches") == 0 ) {
2041 setWeakReferenceMismatchTreatment(argv[++i]);
2043 // For a deployment target of 10.3 and earlier ld64 will
2044 // prebind an executable with 0s in all addresses that
2045 // are prebound. This can then be fixed up by update_prebinding
2046 // later. Prebinding is less useful on 10.4 and greater.
2047 else if ( strcmp(arg, "-prebind") == 0 ) {
2048 fPrebind = true;
2050 else if ( strcmp(arg, "-noprebind") == 0 ) {
2051 warnObsolete(arg);
2052 fPrebind = false;
2054 else if ( strcmp(arg, "-prebind_allow_overlap") == 0 ) {
2055 warnObsolete(arg);
2057 else if ( strcmp(arg, "-prebind_all_twolevel_modules") == 0 ) {
2058 warnObsolete(arg);
2060 else if ( strcmp(arg, "-noprebind_all_twolevel_modules") == 0 ) {
2061 warnObsolete(arg);
2063 else if ( strcmp(arg, "-nofixprebinding") == 0 ) {
2064 warnObsolete(arg);
2066 // This should probably be deprecated when we respect -L and -F
2067 // when searching for libraries.
2068 else if ( strcmp(arg, "-dylib_file") == 0 ) {
2069 addDylibOverride(argv[++i]);
2071 // What to expand @executable_path to if found in dependent dylibs
2072 else if ( strcmp(arg, "-executable_path") == 0 ) {
2073 fExecutablePath = argv[++i];
2074 if ( (fExecutablePath == NULL) || (fExecutablePath[0] == '-') )
2075 throw "-executable_path missing <path>";
2076 // if a directory was passed, add / to end
2077 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2078 struct stat statBuffer;
2079 if ( stat(fExecutablePath, &statBuffer) == 0 ) {
2080 if ( (statBuffer.st_mode & S_IFMT) == S_IFDIR ) {
2081 char* pathWithSlash = new char[strlen(fExecutablePath)+2];
2082 strcpy(pathWithSlash, fExecutablePath);
2083 strcat(pathWithSlash, "/");
2084 fExecutablePath = pathWithSlash;
2088 // Aligns all segments to the power of 2 boundary specified.
2089 else if ( strcmp(arg, "-segalign") == 0 ) {
2090 const char* size = argv[++i];
2091 if ( size == NULL )
2092 throw "-segalign missing <size>";
2093 fSegmentAlignment = parseAddress(size);
2094 uint8_t alignment = (uint8_t)__builtin_ctz(fSegmentAlignment);
2095 uint32_t p2aligned = (1 << alignment);
2096 if ( p2aligned != fSegmentAlignment ) {
2097 warning("alignment for -segalign %s is not a power of two, using 0x%X", size, p2aligned);
2098 fSegmentAlignment = p2aligned;
2101 // Puts a specified segment at a particular address that must
2102 // be a multiple of the segment alignment.
2103 else if ( strcmp(arg, "-segaddr") == 0 ) {
2104 SegmentStart seg;
2105 seg.name = argv[++i];
2106 if ( (seg.name == NULL) || (argv[i+1] == NULL) )
2107 throw "-segaddr missing segName Adddress";
2108 seg.address = parseAddress(argv[++i]);
2109 uint64_t temp = ((seg.address+fSegmentAlignment-1) & (-fSegmentAlignment));
2110 if ( seg.address != temp )
2111 warning("-segaddr %s not %lld byte aligned", seg.name, fSegmentAlignment);
2112 fCustomSegmentAddresses.push_back(seg);
2114 // ??? Deprecate when we deprecate split-seg.
2115 else if ( strcmp(arg, "-segs_read_only_addr") == 0 ) {
2116 fBaseAddress = parseAddress(argv[++i]);
2118 // ??? Deprecate when we deprecate split-seg.
2119 else if ( strcmp(arg, "-segs_read_write_addr") == 0 ) {
2120 fBaseWritableAddress = parseAddress(argv[++i]);
2121 fSplitSegs = true;
2123 // ??? Deprecate when we get rid of basing at build time.
2124 else if ( strcmp(arg, "-seg_addr_table") == 0 ) {
2125 const char* name = argv[++i];
2126 if ( name == NULL )
2127 throw "-seg_addr_table missing argument";
2128 fSegAddrTablePath = name;
2130 else if ( strcmp(arg, "-seg_addr_table_filename") == 0 ) {
2131 warnObsolete(arg);
2132 ++i;
2134 else if ( strcmp(arg, "-segprot") == 0 ) {
2135 SegmentProtect seg;
2136 seg.name = argv[++i];
2137 if ( (seg.name == NULL) || (argv[i+1] == NULL) || (argv[i+2] == NULL) )
2138 throw "-segprot missing segName max-prot init-prot";
2139 seg.max = parseProtection(argv[++i]);
2140 seg.init = parseProtection(argv[++i]);
2141 fCustomSegmentProtections.push_back(seg);
2143 else if ( strcmp(arg, "-pagezero_size") == 0 ) {
2144 const char* size = argv[++i];
2145 if ( size == NULL )
2146 throw "-pagezero_size missing <size>";
2147 fZeroPageSize = parseAddress(size);
2148 uint64_t temp = fZeroPageSize & (-4096); // page align
2149 if ( (fZeroPageSize != temp) )
2150 warning("-pagezero_size not page aligned, rounding down");
2151 fZeroPageSize = temp;
2153 else if ( strcmp(arg, "-stack_addr") == 0 ) {
2154 const char* address = argv[++i];
2155 if ( address == NULL )
2156 throw "-stack_addr missing <address>";
2157 fStackAddr = parseAddress(address);
2159 else if ( strcmp(arg, "-stack_size") == 0 ) {
2160 const char* size = argv[++i];
2161 if ( size == NULL )
2162 throw "-stack_size missing <address>";
2163 fStackSize = parseAddress(size);
2164 uint64_t temp = fStackSize & (-4096); // page align
2165 if ( (fStackSize != temp) )
2166 warning("-stack_size not page aligned, rounding down");
2168 else if ( strcmp(arg, "-allow_stack_execute") == 0 ) {
2169 fExecutableStack = true;
2171 else if ( strcmp(arg, "-allow_heap_execute") == 0 ) {
2172 fDisableNonExecutableHeap = true;
2174 else if ( strcmp(arg, "-sectalign") == 0 ) {
2175 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
2176 throw "-sectalign missing <segment> <section> <file-path>";
2177 addSectionAlignment(argv[i+1], argv[i+2], argv[i+3]);
2178 i += 3;
2180 else if ( strcmp(arg, "-sectorder_detail") == 0 ) {
2181 warnObsolete(arg);
2183 else if ( strcmp(arg, "-sectobjectsymbols") == 0 ) {
2184 warnObsolete(arg);
2185 i += 2;
2187 else if ( strcmp(arg, "-bundle_loader") == 0 ) {
2188 fBundleLoader = argv[++i];
2189 if ( (fBundleLoader == NULL) || (fBundleLoader[0] == '-') )
2190 throw "-bundle_loader missing <path>";
2191 FileInfo info = findFile(fBundleLoader);
2192 info.options.fBundleLoader = true;
2193 fInputFiles.push_back(info);
2195 else if ( strcmp(arg, "-private_bundle") == 0 ) {
2196 warnObsolete(arg);
2198 else if ( strcmp(arg, "-twolevel_namespace_hints") == 0 ) {
2199 // FIX FIX
2201 // Use this flag to set default behavior for deployement targets.
2202 else if ( strcmp(arg, "-macosx_version_min") == 0 ) {
2203 setMacOSXVersionMin(argv[++i]);
2205 else if ( (strcmp(arg, "-ios_version_min") == 0) || (strcmp(arg, "-iphoneos_version_min") == 0) ) {
2206 setIOSVersionMin(argv[++i]);
2208 else if ( strcmp(arg, "-ios_simulator_version_min") == 0 ) {
2209 setIOSVersionMin(argv[++i]);
2211 else if ( strcmp(arg, "-multiply_defined") == 0 ) {
2212 //warnObsolete(arg);
2213 ++i;
2215 else if ( strcmp(arg, "-multiply_defined_unused") == 0 ) {
2216 warnObsolete(arg);
2217 ++i;
2219 else if ( strcmp(arg, "-nomultidefs") == 0 ) {
2220 warnObsolete(arg);
2222 // Display each file in which the argument symbol appears and whether
2223 // the file defines or references it. This option takes an argument
2224 // as -y<symbol> note that there is no space.
2225 else if ( strncmp(arg, "-y", 2) == 0 ) {
2226 warnObsolete("-y");
2228 // Same output as -y, but output <arg> number of undefined symbols only.
2229 else if ( strcmp(arg, "-Y") == 0 ) {
2230 //warnObsolete(arg);
2231 ++i;
2233 // This option affects all objects linked into the final result.
2234 else if ( strcmp(arg, "-m") == 0 ) {
2235 warnObsolete(arg);
2237 else if ( (strcmp(arg, "-why_load") == 0) || (strcmp(arg, "-whyload") == 0) ) {
2238 fWhyLoad = true;
2240 else if ( strcmp(arg, "-why_live") == 0 ) {
2241 const char* name = argv[++i];
2242 if ( name == NULL )
2243 throw "-why_live missing symbol name argument";
2244 fWhyLive.insert(name);
2246 else if ( strcmp(arg, "-u") == 0 ) {
2247 const char* name = argv[++i];
2248 if ( name == NULL )
2249 throw "-u missing argument";
2250 fInitialUndefines.push_back(name);
2252 else if ( strcmp(arg, "-U") == 0 ) {
2253 const char* name = argv[++i];
2254 if ( name == NULL )
2255 throw "-U missing argument";
2256 fAllowedUndefined.insert(name);
2258 else if ( strcmp(arg, "-s") == 0 ) {
2259 warnObsolete(arg);
2260 fLocalSymbolHandling = kLocalSymbolsNone;
2261 fDebugInfoStripping = Options::kDebugInfoNone;
2263 else if ( strcmp(arg, "-x") == 0 ) {
2264 fLocalSymbolHandling = kLocalSymbolsNone;
2266 else if ( strcmp(arg, "-S") == 0 ) {
2267 fDebugInfoStripping = Options::kDebugInfoNone;
2269 else if ( strcmp(arg, "-X") == 0 ) {
2270 warnObsolete(arg);
2272 else if ( strcmp(arg, "-Si") == 0 ) {
2273 warnObsolete(arg);
2274 fDebugInfoStripping = Options::kDebugInfoFull;
2276 else if ( strcmp(arg, "-b") == 0 ) {
2277 warnObsolete(arg);
2279 else if ( strcmp(arg, "-Sn") == 0 ) {
2280 warnObsolete(arg);
2281 fDebugInfoStripping = Options::kDebugInfoFull;
2283 else if ( strcmp(arg, "-Sp") == 0 ) {
2284 warnObsolete(arg);
2286 else if ( strcmp(arg, "-dead_strip") == 0 ) {
2287 fDeadStrip = true;
2289 else if ( strcmp(arg, "-no_dead_strip_inits_and_terms") == 0 ) {
2290 fDeadStrip = true;
2292 else if ( strcmp(arg, "-w") == 0 ) {
2293 // previously handled by buildSearchPaths()
2295 else if ( strcmp(arg, "-fatal_warnings") == 0 ) {
2296 // previously handled by buildSearchPaths()
2298 else if ( strcmp(arg, "-arch_errors_fatal") == 0 ) {
2299 fErrorOnOtherArchFiles = true;
2301 else if ( strcmp(arg, "-M") == 0 ) {
2302 // FIX FIX
2304 else if ( strcmp(arg, "-headerpad") == 0 ) {
2305 const char* size = argv[++i];
2306 if ( size == NULL )
2307 throw "-headerpad missing argument";
2308 fMinimumHeaderPad = parseAddress(size);
2310 else if ( strcmp(arg, "-headerpad_max_install_names") == 0 ) {
2311 fMaxMinimumHeaderPad = true;
2313 else if ( strcmp(arg, "-t") == 0 ) {
2314 fLogAllFiles = true;
2316 else if ( strcmp(arg, "-whatsloaded") == 0 ) {
2317 fLogObjectFiles = true;
2319 else if ( strcmp(arg, "-A") == 0 ) {
2320 warnObsolete(arg);
2321 ++i;
2323 else if ( strcmp(arg, "-umbrella") == 0 ) {
2324 const char* name = argv[++i];
2325 if ( name == NULL )
2326 throw "-umbrella missing argument";
2327 fUmbrellaName = name;
2329 else if ( strcmp(arg, "-allowable_client") == 0 ) {
2330 const char* name = argv[++i];
2332 if ( name == NULL )
2333 throw "-allowable_client missing argument";
2335 fAllowableClients.push_back(name);
2337 else if ( strcmp(arg, "-client_name") == 0 ) {
2338 const char* name = argv[++i];
2340 if ( name == NULL )
2341 throw "-client_name missing argument";
2343 fClientName = name;
2345 else if ( strcmp(arg, "-sub_umbrella") == 0 ) {
2346 const char* name = argv[++i];
2347 if ( name == NULL )
2348 throw "-sub_umbrella missing argument";
2349 fSubUmbellas.push_back(name);
2351 else if ( strcmp(arg, "-sub_library") == 0 ) {
2352 const char* name = argv[++i];
2353 if ( name == NULL )
2354 throw "-sub_library missing argument";
2355 fSubLibraries.push_back(name);
2357 else if ( strcmp(arg, "-init") == 0 ) {
2358 const char* name = argv[++i];
2359 if ( name == NULL )
2360 throw "-init missing argument";
2361 fInitFunctionName = name;
2363 else if ( strcmp(arg, "-dot") == 0 ) {
2364 const char* name = argv[++i];
2365 if ( name == NULL )
2366 throw "-dot missing argument";
2367 fDotOutputFile = name;
2369 else if ( strcmp(arg, "-warn_commons") == 0 ) {
2370 fWarnCommons = true;
2372 else if ( strcmp(arg, "-commons") == 0 ) {
2373 fCommonsMode = parseCommonsTreatment(argv[++i]);
2375 else if ( strcmp(arg, "-keep_relocs") == 0 ) {
2376 fKeepRelocations = true;
2378 else if ( strcmp(arg, "-warn_stabs") == 0 ) {
2379 fWarnStabs = true;
2381 else if ( strcmp(arg, "-pause") == 0 ) {
2382 fPause = true;
2384 else if ( strcmp(arg, "-print_statistics") == 0 ) {
2385 fStatistics = true;
2387 else if ( strcmp(arg, "-d") == 0 ) {
2388 fMakeTentativeDefinitionsReal = true;
2390 else if ( strcmp(arg, "-v") == 0 ) {
2391 // previously handled by buildSearchPaths()
2393 else if ( strcmp(arg, "-Z") == 0 ) {
2394 // previously handled by buildSearchPaths()
2396 else if ( strcmp(arg, "-syslibroot") == 0 ) {
2397 ++i;
2398 // previously handled by buildSearchPaths()
2400 else if ( strcmp(arg, "-no_uuid") == 0 ) {
2401 fUUIDMode = kUUIDNone;
2403 else if ( strcmp(arg, "-random_uuid") == 0 ) {
2404 fUUIDMode = kUUIDRandom;
2406 else if ( strcmp(arg, "-dtrace") == 0 ) {
2407 const char* name = argv[++i];
2408 if ( name == NULL )
2409 throw "-dtrace missing argument";
2410 fDtraceScriptName = name;
2412 else if ( strcmp(arg, "-root_safe") == 0 ) {
2413 fRootSafe = true;
2415 else if ( strcmp(arg, "-setuid_safe") == 0 ) {
2416 fSetuidSafe = true;
2418 else if ( strcmp(arg, "-alias") == 0 ) {
2419 Options::AliasPair pair;
2420 pair.realName = argv[++i];
2421 if ( pair.realName == NULL )
2422 throw "missing argument to -alias";
2423 pair.alias = argv[++i];
2424 if ( pair.alias == NULL )
2425 throw "missing argument to -alias";
2426 fAliases.push_back(pair);
2428 else if ( strcmp(arg, "-alias_list") == 0 ) {
2429 parseAliasFile(argv[++i]);
2431 // put this last so that it does not interfer with other options starting with 'i'
2432 else if ( strncmp(arg, "-i", 2) == 0 ) {
2433 const char* colon = strchr(arg, ':');
2434 if ( colon == NULL )
2435 throwf("unknown option: %s", arg);
2436 Options::AliasPair pair;
2437 char* temp = new char[colon-arg];
2438 strlcpy(temp, &arg[2], colon-arg-1);
2439 pair.realName = &colon[1];
2440 pair.alias = temp;
2441 fAliases.push_back(pair);
2443 else if ( strcmp(arg, "-save-temps") == 0 ) {
2444 fSaveTempFiles = true;
2446 else if ( strcmp(arg, "-rpath") == 0 ) {
2447 const char* path = argv[++i];
2448 if ( path == NULL )
2449 throw "missing argument to -rpath";
2450 fRPaths.push_back(path);
2452 else if ( strcmp(arg, "-read_only_stubs") == 0 ) {
2453 fReadOnlyx86Stubs = true;
2455 else if ( strcmp(arg, "-slow_stubs") == 0 ) {
2456 warnObsolete(arg);
2458 else if ( strcmp(arg, "-map") == 0 ) {
2459 fMapPath = argv[++i];
2460 if ( fMapPath == NULL )
2461 throw "missing argument to -map";
2463 else if ( strcmp(arg, "-pie") == 0 ) {
2464 fPositionIndependentExecutable = true;
2465 fPIEOnCommandLine = true;
2467 else if ( strcmp(arg, "-no_pie") == 0 ) {
2468 fDisablePositionIndependentExecutable = true;
2470 else if ( strncmp(arg, "-reexport-l", 11) == 0 ) {
2471 FileInfo info = findLibrary(&arg[11], true);
2472 info.options.fReExport = true;
2473 addLibrary(info);
2475 else if ( strcmp(arg, "-reexport_library") == 0 ) {
2476 FileInfo info = findFile(argv[++i]);
2477 info.options.fReExport = true;
2478 addLibrary(info);
2480 else if ( strcmp(arg, "-reexport_framework") == 0 ) {
2481 FileInfo info = findFramework(argv[++i]);
2482 info.options.fReExport = true;
2483 addLibrary(info);
2485 else if ( strncmp(arg, "-upward-l", 9) == 0 ) {
2486 FileInfo info = findLibrary(&arg[9], true);
2487 info.options.fUpward = true;
2488 addLibrary(info);
2490 else if ( strcmp(arg, "-upward_library") == 0 ) {
2491 FileInfo info = findFile(argv[++i]);
2492 info.options.fUpward = true;
2493 addLibrary(info);
2495 else if ( strcmp(arg, "-upward_framework") == 0 ) {
2496 FileInfo info = findFramework(argv[++i]);
2497 info.options.fUpward = true;
2498 addLibrary(info);
2500 else if ( strcmp(arg, "-dead_strip_dylibs") == 0 ) {
2501 fDeadStripDylibs = true;
2503 else if ( strcmp(arg, "-no_implicit_dylibs") == 0 ) {
2504 fImplicitlyLinkPublicDylibs = false;
2506 else if ( strcmp(arg, "-new_linker") == 0 ) {
2507 // ignore
2509 else if ( strcmp(arg, "-no_encryption") == 0 ) {
2510 fEncryptable = false;
2512 else if ( strcmp(arg, "-no_compact_unwind") == 0 ) {
2513 fAddCompactUnwindEncoding = false;
2515 else if ( strcmp(arg, "-mllvm") == 0 ) {
2516 const char* opts = argv[++i];
2517 if ( opts == NULL )
2518 throw "missing argument to -mllvm";
2519 fLLVMOptions.push_back(opts);
2521 else if ( strcmp(arg, "-no_order_inits") == 0 ) {
2522 fAutoOrderInitializers = false;
2524 else if ( strcmp(arg, "-no_order_data") == 0 ) {
2525 fOrderData = false;
2527 else if ( strcmp(arg, "-seg_page_size") == 0 ) {
2528 SegmentSize seg;
2529 seg.name = argv[++i];
2530 if ( (seg.name == NULL) || (argv[i+1] == NULL) )
2531 throw "-seg_page_size missing segName Adddress";
2532 seg.size = parseAddress(argv[++i]);
2533 uint64_t temp = seg.size & (-4096); // page align
2534 if ( (seg.size != temp) )
2535 warning("-seg_page_size %s not 4K aligned, rounding down", seg.name);
2536 fCustomSegmentSizes.push_back(seg);
2538 else if ( strcmp(arg, "-mark_dead_strippable_dylib") == 0 ) {
2539 fMarkDeadStrippableDylib = true;
2541 else if ( strcmp(arg, "-exported_symbols_order") == 0 ) {
2542 loadSymbolOrderFile(argv[++i], fExportSymbolsOrder);
2544 else if ( strcmp(arg, "-no_compact_linkedit") == 0 ) {
2545 warnObsolete("-no_compact_linkedit");
2547 else if ( strcmp(arg, "-no_eh_labels") == 0 ) {
2548 fNoEHLabels = true;
2550 else if ( strcmp(arg, "-warn_compact_unwind") == 0 ) {
2551 fWarnCompactUnwind = true;
2553 else if ( strcmp(arg, "-allow_sub_type_mismatches") == 0 ) {
2554 fAllowCpuSubtypeMismatches = true;
2556 else if ( strcmp(arg, "-no_zero_fill_sections") == 0 ) {
2557 fOptimizeZeroFill = false;
2559 else if ( strcmp(arg, "-merge_zero_fill_sections") == 0 ) {
2560 fMergeZeroFill = true;
2562 else if ( strcmp(arg, "-objc_abi_version") == 0 ) {
2563 const char* version = argv[++i];
2564 if ( version == NULL )
2565 throw "-objc_abi_version missing version number";
2566 if ( strcmp(version, "2") == 0 ) {
2567 fObjCABIVersion1Override = false;
2568 fObjCABIVersion2Override = true;
2570 else if ( strcmp(version, "1") == 0 ) {
2571 fObjCABIVersion1Override = true;
2572 fObjCABIVersion2Override = false;
2574 else
2575 warning("ignoring unrecognized argument (%s) to -objc_abi_version", version);
2577 else if ( strcmp(arg, "-warn_weak_exports") == 0 ) {
2578 fWarnWeakExports = true;
2580 else if ( strcmp(arg, "-objc_gc_compaction") == 0 ) {
2581 fObjcGcCompaction = true;
2583 else if ( strcmp(arg, "-objc_gc") == 0 ) {
2584 fObjCGc = true;
2585 if ( fObjCGcOnly ) {
2586 warning("-objc_gc overriding -objc_gc_only");
2587 fObjCGcOnly = false;
2590 else if ( strcmp(arg, "-objc_gc_only") == 0 ) {
2591 fObjCGcOnly = true;
2592 if ( fObjCGc ) {
2593 warning("-objc_gc_only overriding -objc_gc");
2594 fObjCGc = false;
2597 else if ( strcmp(arg, "-demangle") == 0 ) {
2598 fDemangle = true;
2600 else if ( strcmp(arg, "-version_load_command") == 0 ) {
2601 fVersionLoadCommandForcedOn = true;
2602 fVersionLoadCommandForcedOff = false;
2604 else if ( strcmp(arg, "-no_version_load_command") == 0 ) {
2605 fVersionLoadCommandForcedOff = true;
2606 fVersionLoadCommandForcedOn = false;
2608 else if ( strcmp(arg, "-function_starts") == 0 ) {
2609 fFunctionStartsForcedOn = true;
2610 fFunctionStartsForcedOff = false;
2612 else if ( strcmp(arg, "-no_function_starts") == 0 ) {
2613 fFunctionStartsForcedOff = true;
2614 fFunctionStartsForcedOn = false;
2616 else if ( strcmp(arg, "-object_path_lto") == 0 ) {
2617 fTempLtoObjectPath = argv[++i];
2618 if ( fTempLtoObjectPath == NULL )
2619 throw "missing argument to -object_path_lto";
2621 else if ( strcmp(arg, "-no_objc_category_merging") == 0 ) {
2622 fObjcCategoryMerging = false;
2624 else if ( strcmp(arg, "-force_symbols_weak_list") == 0 ) {
2625 loadExportFile(argv[++i], "-force_symbols_weak_list", fForceWeakSymbols);
2627 else if ( strcmp(arg, "-force_symbols_not_weak_list") == 0 ) {
2628 loadExportFile(argv[++i], "-force_symbols_not_weak_list", fForceNotWeakSymbols);
2630 else if ( strcmp(arg, "-force_symbol_weak") == 0 ) {
2631 const char* symbol = argv[++i];
2632 if ( symbol == NULL )
2633 throw "-force_symbol_weak missing <symbol>";
2634 fForceWeakSymbols.insert(symbol);
2636 else if ( strcmp(arg, "-force_symbol_not_weak") == 0 ) {
2637 const char* symbol = argv[++i];
2638 if ( symbol == NULL )
2639 throw "-force_symbol_not_weak missing <symbol>";
2640 fForceNotWeakSymbols.insert(symbol);
2642 else if ( strcmp(arg, "-reexported_symbols_list") == 0 ) {
2643 if ( fExportMode == kExportSome )
2644 throw "can't use -exported_symbols_list and -reexported_symbols_list";
2645 loadExportFile(argv[++i], "-reexported_symbols_list", fReExportSymbols);
2647 else if ( strcmp(arg, "-dyld_env") == 0 ) {
2648 const char* envarg = argv[++i];
2649 if ( envarg == NULL )
2650 throw "-dyld_env missing ENV=VALUE";
2651 if ( strchr(envarg, '=') == NULL )
2652 throw "-dyld_env missing ENV=VALUE";
2653 fDyldEnvironExtras.push_back(envarg);
2655 else if ( strcmp(arg, "-page_align_data_atoms") == 0 ) {
2656 fPageAlignDataAtoms = true;
2658 else {
2659 throwf("unknown option: %s", arg);
2662 else {
2663 FileInfo info = findFile(arg);
2664 if ( strcmp(&info.path[strlen(info.path)-2], ".a") == 0 )
2665 addLibrary(info);
2666 else
2667 fInputFiles.push_back(info);
2671 // if a -lazy option was used, implicitly link in lazydylib1.o
2672 if ( fUsingLazyDylibLinking ) {
2673 addLibrary(findLibrary("lazydylib1.o"));
2680 // -syslibroot <path> is used for SDK support.
2681 // The rule is that all search paths (both explicit and default) are
2682 // checked to see if they exist in the SDK. If so, that path is
2683 // replaced with the sdk prefixed path. If not, that search path
2684 // is used as is. If multiple -syslibroot options are specified
2685 // their directory structures are logically overlayed and files
2686 // from sdks specified earlier on the command line used before later ones.
2688 void Options::buildSearchPaths(int argc, const char* argv[])
2690 bool addStandardLibraryDirectories = true;
2691 std::vector<const char*> libraryPaths;
2692 std::vector<const char*> frameworkPaths;
2693 libraryPaths.reserve(10);
2694 frameworkPaths.reserve(10);
2695 // scan through argv looking for -L, -F, -Z, and -syslibroot options
2696 for(int i=0; i < argc; ++i) {
2697 if ( (argv[i][0] == '-') && (argv[i][1] == 'L') ) {
2698 const char* libSearchDir = &argv[i][2];
2699 // Allow either "-L{path}" or "-L {path}".
2700 if (argv[i][2] == '\0') {
2701 // -L {path}. Make sure there is an argument following this.
2702 const char* path = argv[++i];
2703 if ( path == NULL )
2704 throw "-L missing argument";
2705 libSearchDir = path;
2707 if ( libSearchDir[0] == '\0' )
2708 throw "-L must be immediately followed by a directory path (no space)";
2709 struct stat statbuf;
2710 if ( stat(libSearchDir, &statbuf) == 0 ) {
2711 if ( statbuf.st_mode & S_IFDIR )
2712 libraryPaths.push_back(libSearchDir);
2713 else
2714 warning("path '%s' following -L not a directory", libSearchDir);
2716 else {
2717 warning("directory not found for option '-L%s'", libSearchDir);
2720 else if ( (argv[i][0] == '-') && (argv[i][1] == 'F') ) {
2721 const char* frameworkSearchDir = &argv[i][2];
2722 // Allow either "-F{path}" or "-F {path}".
2723 if (argv[i][2] == '\0') {
2724 // -F {path}. Make sure there is an argument following this.
2725 const char* path = argv[++i];
2726 if ( path == NULL )
2727 throw "-F missing argument";
2728 frameworkSearchDir = path;
2730 if ( frameworkSearchDir[0] == '\0' )
2731 throw "-F must be immediately followed by a directory path (no space)";
2732 struct stat statbuf;
2733 if ( stat(frameworkSearchDir, &statbuf) == 0 ) {
2734 if ( statbuf.st_mode & S_IFDIR )
2735 frameworkPaths.push_back(frameworkSearchDir);
2736 else
2737 warning("path '%s' following -F not a directory", frameworkSearchDir);
2739 else {
2740 warning("directory not found for option '-F%s'", frameworkSearchDir);
2743 else if ( strcmp(argv[i], "-Z") == 0 )
2744 addStandardLibraryDirectories = false;
2745 else if ( strcmp(argv[i], "-v") == 0 ) {
2746 fVerbose = true;
2747 extern const char ldVersionString[];
2748 fprintf(stderr, "%s", ldVersionString);
2749 // if only -v specified, exit cleanly
2750 if ( argc == 2 ) {
2751 const char* ltoVers = lto::version();
2752 if ( ltoVers != NULL )
2753 fprintf(stderr, "%s\n", ltoVers);
2754 exit(0);
2757 else if ( strcmp(argv[i], "-syslibroot") == 0 ) {
2758 const char* path = argv[++i];
2759 if ( path == NULL )
2760 throw "-syslibroot missing argument";
2761 fSDKPaths.push_back(path);
2763 else if ( strcmp(argv[i], "-search_paths_first") == 0 ) {
2764 fLibrarySearchMode = kSearchDylibAndArchiveInEachDir;
2766 else if ( strcmp(argv[i], "-search_dylibs_first") == 0 ) {
2767 fLibrarySearchMode = kSearchAllDirsForDylibsThenAllDirsForArchives;
2769 else if ( strcmp(argv[i], "-w") == 0 ) {
2770 sEmitWarnings = false;
2772 else if ( strcmp(argv[i], "-fatal_warnings") == 0 ) {
2773 sFatalWarnings = true;
2776 int standardLibraryPathsStartIndex = libraryPaths.size();
2777 int standardFrameworkPathsStartIndex = frameworkPaths.size();
2778 if ( addStandardLibraryDirectories ) {
2779 libraryPaths.push_back("/usr/lib");
2780 libraryPaths.push_back("/usr/local/lib");
2782 frameworkPaths.push_back("/Library/Frameworks/");
2783 frameworkPaths.push_back("/System/Library/Frameworks/");
2784 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
2787 // <rdar://problem/5829579> Support for configure based hacks
2788 // if last -syslibroot is /, then ignore all syslibroots
2789 if ( fSDKPaths.size() > 0 ) {
2790 if ( strcmp(fSDKPaths.back(), "/") == 0 ) {
2791 fSDKPaths.clear();
2795 // now merge sdk and library paths to make real search paths
2796 fLibrarySearchPaths.reserve(libraryPaths.size()*(fSDKPaths.size()+1));
2797 int libIndex = 0;
2798 for (std::vector<const char*>::iterator it = libraryPaths.begin(); it != libraryPaths.end(); ++it, ++libIndex) {
2799 const char* libDir = *it;
2800 bool sdkOverride = false;
2801 if ( libDir[0] == '/' ) {
2802 char betterLibDir[PATH_MAX];
2803 if ( strstr(libDir, "/..") != NULL ) {
2804 if ( realpath(libDir, betterLibDir) != NULL )
2805 libDir = strdup(betterLibDir);
2807 const int libDirLen = strlen(libDir);
2808 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
2809 const char* sdkDir = *sdkit;
2810 const int sdkDirLen = strlen(sdkDir);
2811 char newPath[libDirLen + sdkDirLen+4];
2812 strcpy(newPath, sdkDir);
2813 if ( newPath[sdkDirLen-1] == '/' )
2814 newPath[sdkDirLen-1] = '\0';
2815 strcat(newPath, libDir);
2816 struct stat statBuffer;
2817 if ( stat(newPath, &statBuffer) == 0 ) {
2818 fLibrarySearchPaths.push_back(strdup(newPath));
2819 sdkOverride = true;
2823 if ( !sdkOverride ) {
2824 if ( (libIndex >= standardLibraryPathsStartIndex) && (fSDKPaths.size() == 1) ) {
2825 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2826 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2828 else {
2829 fLibrarySearchPaths.push_back(libDir);
2834 // now merge sdk and framework paths to make real search paths
2835 fFrameworkSearchPaths.reserve(frameworkPaths.size()*(fSDKPaths.size()+1));
2836 int frameIndex = 0;
2837 for (std::vector<const char*>::iterator it = frameworkPaths.begin(); it != frameworkPaths.end(); ++it, ++frameIndex) {
2838 const char* frameworkDir = *it;
2839 bool sdkOverride = false;
2840 if ( frameworkDir[0] == '/' ) {
2841 char betterFrameworkDir[PATH_MAX];
2842 if ( strstr(frameworkDir, "/..") != NULL ) {
2843 if ( realpath(frameworkDir, betterFrameworkDir) != NULL )
2844 frameworkDir = strdup(betterFrameworkDir);
2846 const int frameworkDirLen = strlen(frameworkDir);
2847 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
2848 const char* sdkDir = *sdkit;
2849 const int sdkDirLen = strlen(sdkDir);
2850 char newPath[frameworkDirLen + sdkDirLen+4];
2851 strcpy(newPath, sdkDir);
2852 if ( newPath[sdkDirLen-1] == '/' )
2853 newPath[sdkDirLen-1] = '\0';
2854 strcat(newPath, frameworkDir);
2855 struct stat statBuffer;
2856 if ( stat(newPath, &statBuffer) == 0 ) {
2857 fFrameworkSearchPaths.push_back(strdup(newPath));
2858 sdkOverride = true;
2862 if ( !sdkOverride ) {
2863 if ( (frameIndex >= standardFrameworkPathsStartIndex) && (fSDKPaths.size() == 1) ) {
2864 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2865 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2867 else {
2868 fFrameworkSearchPaths.push_back(frameworkDir);
2873 if ( fVerbose ) {
2874 fprintf(stderr,"Library search paths:\n");
2875 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
2876 it != fLibrarySearchPaths.end();
2877 it++)
2878 fprintf(stderr,"\t%s\n", *it);
2879 fprintf(stderr,"Framework search paths:\n");
2880 for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin();
2881 it != fFrameworkSearchPaths.end();
2882 it++)
2883 fprintf(stderr,"\t%s\n", *it);
2887 // this is run before the command line is parsed
2888 void Options::parsePreCommandLineEnvironmentSettings()
2890 if ((getenv("LD_TRACE_ARCHIVES") != NULL)
2891 || (getenv("RC_TRACE_ARCHIVES") != NULL))
2892 fTraceArchives = true;
2894 if ((getenv("LD_TRACE_DYLIBS") != NULL)
2895 || (getenv("RC_TRACE_DYLIBS") != NULL)) {
2896 fTraceDylibs = true;
2897 fTraceIndirectDylibs = true;
2900 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL) {
2901 fTraceDylibSearching = true;
2904 if (getenv("LD_PRINT_OPTIONS") != NULL)
2905 fPrintOptions = true;
2907 if (fTraceDylibs || fTraceArchives)
2908 fTraceOutputFile = getenv("LD_TRACE_FILE");
2910 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL)
2911 fPrintOrderFileStatistics = true;
2913 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL)
2914 fSplitSegs = true;
2916 if (getenv("LD_NO_ENCRYPT") != NULL)
2917 fEncryptable = false;
2919 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL)
2920 fAllowCpuSubtypeMismatches = true;
2922 sWarningsSideFilePath = getenv("LD_WARN_FILE");
2924 const char* customDyldPath = getenv("LD_DYLD_PATH");
2925 if ( customDyldPath != NULL )
2926 fDyldInstallPath = customDyldPath;
2930 // this is run after the command line is parsed
2931 void Options::parsePostCommandLineEnvironmentSettings()
2933 // when building a dynamic main executable, default any use of @executable_path to output path
2934 if ( fExecutablePath == NULL && (fOutputKind == kDynamicExecutable) ) {
2935 fExecutablePath = fOutputFile;
2938 // allow build system to set default seg_addr_table
2939 if ( fSegAddrTablePath == NULL )
2940 fSegAddrTablePath = getenv("LD_SEG_ADDR_TABLE");
2942 // allow build system to turn on prebinding
2943 if ( !fPrebind ) {
2944 fPrebind = ( getenv("LD_PREBIND") != NULL );
2947 // allow build system to force on dead-code-stripping
2948 if ( !fDeadStrip ) {
2949 if ( getenv("LD_DEAD_STRIP") != NULL ) {
2950 switch (fOutputKind) {
2951 case Options::kDynamicLibrary:
2952 case Options::kDynamicExecutable:
2953 case Options::kDynamicBundle:
2954 fDeadStrip = true;
2955 break;
2956 case Options::kPreload:
2957 case Options::kObjectFile:
2958 case Options::kDyld:
2959 case Options::kStaticExecutable:
2960 case Options::kKextBundle:
2961 break;
2966 // allow build system to force on -warn_commons
2967 if ( getenv("LD_WARN_COMMONS") != NULL )
2968 fWarnCommons = true;
2972 void Options::reconfigureDefaults()
2974 // sync reader options
2975 switch ( fOutputKind ) {
2976 case Options::kObjectFile:
2977 fForFinalLinkedImage = false;
2978 break;
2979 case Options::kDyld:
2980 fForDyld = true;
2981 fForFinalLinkedImage = true;
2982 fNoEHLabels = true;
2983 break;
2984 case Options::kDynamicLibrary:
2985 case Options::kDynamicBundle:
2986 case Options::kKextBundle:
2987 fForFinalLinkedImage = true;
2988 fNoEHLabels = true;
2989 break;
2990 case Options::kDynamicExecutable:
2991 case Options::kStaticExecutable:
2992 case Options::kPreload:
2993 fLinkingMainExecutable = true;
2994 fForFinalLinkedImage = true;
2995 fNoEHLabels = true;
2996 break;
2999 // set default min OS version
3000 if ( (fMacVersionMin == ld::macVersionUnset)
3001 && (fIOSVersionMin == ld::iOSVersionUnset) ) {
3002 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
3003 const char* macVers = getenv("MACOSX_DEPLOYMENT_TARGET");
3004 const char* iPhoneVers = getenv("IPHONEOS_DEPLOYMENT_TARGET");
3005 const char* iOSVers = getenv("IOS_DEPLOYMENT_TARGET");
3006 const char* iOSSimulatorVers = getenv("IOS_SIMULATOR_DEPLOYMENT_TARGET");
3007 if ( macVers != NULL )
3008 setMacOSXVersionMin(macVers);
3009 else if ( iPhoneVers != NULL )
3010 setIOSVersionMin(iPhoneVers);
3011 else if ( iOSVers != NULL )
3012 setIOSVersionMin(iOSVers);
3013 else if ( iOSSimulatorVers != NULL )
3014 setIOSVersionMin(iOSSimulatorVers);
3015 else {
3016 // if still nothing, set default based on architecture
3017 switch ( fArchitecture ) {
3018 case CPU_TYPE_I386:
3019 case CPU_TYPE_X86_64:
3020 if ( (fOutputKind != Options::kObjectFile) && (fOutputKind != Options::kPreload) ) {
3021 #ifdef DEFAULT_MACOSX_MIN_VERSION
3022 warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION);
3023 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
3024 #else
3025 warning("-macosx_version_min not specificed, assuming 10.6");
3026 fMacVersionMin = ld::mac10_6;
3027 #endif
3029 break;
3030 case CPU_TYPE_ARM:
3031 if ( (fOutputKind != Options::kObjectFile) && (fOutputKind != Options::kPreload) ) {
3032 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
3033 warning("-ios_version_min not specificed, assuming " DEFAULT_IPHONEOS_MIN_VERSION);
3034 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION);
3035 #elif defined(DEFAULT_MACOSX_MIN_VERSION)
3036 warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION);
3037 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
3038 #else
3039 warning("-macosx_version_min not specificed, assuming 10.6");
3040 fMacVersionMin = ld::mac10_6;
3041 #endif
3043 break;
3044 default:
3045 // architecture will be infered ;ater by examining .o files
3046 break;
3052 // adjust min based on architecture
3053 switch ( fArchitecture ) {
3054 case CPU_TYPE_I386:
3055 if ( (fMacVersionMin < ld::mac10_4) && (fIOSVersionMin == ld::iOSVersionUnset) ) {
3056 //warning("-macosx_version_min should be 10.4 or later for i386");
3057 fMacVersionMin = ld::mac10_4;
3059 break;
3060 case CPU_TYPE_X86_64:
3061 if ( fMacVersionMin < ld::mac10_4 ) {
3062 //warning("-macosx_version_min should be 10.4 or later for x86_64");
3063 fMacVersionMin = ld::mac10_4;
3065 break;
3068 // adjust kext type based on architecture
3069 if ( fOutputKind == kKextBundle ) {
3070 switch ( fArchitecture ) {
3071 case CPU_TYPE_X86_64:
3072 // x86_64 uses new MH_KEXT_BUNDLE type
3073 fMakeCompressedDyldInfo = false;
3074 fMakeCompressedDyldInfoForceOff = true;
3075 fAllowTextRelocs = true;
3076 fUndefinedTreatment = kUndefinedDynamicLookup;
3077 break;
3078 case CPU_TYPE_ARM:
3079 if ( fIOSVersionMin >= ld::iOS_5_0 ) {
3080 // iOS 5.0 and later use new MH_KEXT_BUNDLE type
3081 fMakeCompressedDyldInfo = false;
3082 fMakeCompressedDyldInfoForceOff = true;
3083 fAllowTextRelocs = true;
3084 fUndefinedTreatment = kUndefinedDynamicLookup;
3085 break;
3087 // else use object file
3088 case CPU_TYPE_I386:
3089 // use .o files
3090 fOutputKind = kObjectFile;
3091 break;
3095 // disable implicit dylibs when targeting 10.3
3096 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
3097 if ( !minOS(ld::mac10_4, ld::iOS_2_0) )
3098 fImplicitlyLinkPublicDylibs = false;
3101 // allow build system to force linker to ignore -prebind
3102 if ( getenv("LD_FORCE_NO_PREBIND") != NULL )
3103 fPrebind = false;
3105 // allow build system to force linker to ignore -seg_addr_table
3106 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL )
3107 fSegAddrTablePath = NULL;
3109 // check for base address specified externally
3110 if ( (fSegAddrTablePath != NULL) && (fOutputKind == Options::kDynamicLibrary) ) {
3111 parseSegAddrTable(fSegAddrTablePath, this->installPath());
3112 // HACK to support seg_addr_table entries that are physical paths instead of install paths
3113 if ( fBaseAddress == 0 ) {
3114 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
3115 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libstdc++.6.0.4.dylib");
3116 if ( fBaseAddress == 0 )
3117 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libstdc++.6.0.9.dylib");
3120 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
3121 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libz.1.2.3.dylib");
3123 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
3124 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libutil1.0.dylib");
3128 // split segs only allowed for dylibs
3129 if ( fSplitSegs ) {
3130 // split seg only supported for i386, and arm.
3131 switch ( fArchitecture ) {
3132 case CPU_TYPE_I386:
3133 if ( fOutputKind != Options::kDynamicLibrary )
3134 fSplitSegs = false;
3135 // make sure read and write segments are proper distance apart
3136 if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x10000000) )
3137 fBaseWritableAddress = fBaseAddress + 0x10000000;
3138 break;
3139 case CPU_TYPE_ARM:
3140 if ( fOutputKind != Options::kDynamicLibrary ) {
3141 fSplitSegs = false;
3143 else {
3144 // make sure read and write segments are proper distance apart
3145 if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x08000000) )
3146 fBaseWritableAddress = fBaseAddress + 0x08000000;
3148 break;
3149 default:
3150 fSplitSegs = false;
3151 fBaseAddress = 0;
3152 fBaseWritableAddress = 0;
3156 // set too-large size
3157 switch ( fArchitecture ) {
3158 case CPU_TYPE_I386:
3159 fMaxAddress = 0xFFFFFFFF;
3160 break;
3161 case CPU_TYPE_X86_64:
3162 break;
3163 case CPU_TYPE_ARM:
3164 switch ( fOutputKind ) {
3165 case Options::kDynamicExecutable:
3166 case Options::kDynamicLibrary:
3167 case Options::kDynamicBundle:
3168 // user land code is limited to low 1GB
3169 fMaxAddress = 0x2FFFFFFF;
3170 break;
3171 case Options::kStaticExecutable:
3172 case Options::kObjectFile:
3173 case Options::kDyld:
3174 case Options::kPreload:
3175 case Options::kKextBundle:
3176 fMaxAddress = 0xFFFFFFFF;
3177 break;
3179 // range check -seg1addr for ARM
3180 if ( fBaseAddress > fMaxAddress ) {
3181 warning("ignoring -seg1addr 0x%08llX. Address out of range.", fBaseAddress);
3182 fBaseAddress = 0;
3184 break;
3187 // <rdar://problem/6138961> -r implies no prebinding for all architectures
3188 if ( fOutputKind == Options::kObjectFile )
3189 fPrebind = false;
3191 // disable prebinding depending on arch and min OS version
3192 if ( fPrebind ) {
3193 switch ( fArchitecture ) {
3194 case CPU_TYPE_I386:
3195 if ( fMacVersionMin == ld::mac10_4 ) {
3196 // in 10.4 only split seg dylibs are prebound
3197 if ( (fOutputKind != Options::kDynamicLibrary) || ! fSplitSegs )
3198 fPrebind = false;
3200 else if ( fMacVersionMin >= ld::mac10_5 ) {
3201 // in 10.5 nothing is prebound
3202 fPrebind = false;
3204 else if ( fIOSVersionMin != ld::iOSVersionUnset ) {
3205 // nothing in simulator is prebound
3206 fPrebind = false;
3208 else {
3209 // in 10.3 and earlier only dylibs and main executables could be prebound
3210 switch ( fOutputKind ) {
3211 case Options::kDynamicExecutable:
3212 case Options::kDynamicLibrary:
3213 // only main executables and dylibs can be prebound
3214 break;
3215 case Options::kStaticExecutable:
3216 case Options::kDynamicBundle:
3217 case Options::kObjectFile:
3218 case Options::kDyld:
3219 case Options::kPreload:
3220 case Options::kKextBundle:
3221 // disable prebinding for everything else
3222 fPrebind = false;
3223 break;
3226 break;
3227 case CPU_TYPE_X86_64:
3228 fPrebind = false;
3229 break;
3230 case CPU_TYPE_ARM:
3231 switch ( fOutputKind ) {
3232 case Options::kDynamicExecutable:
3233 case Options::kDynamicLibrary:
3234 // only main executables and dylibs can be prebound
3235 break;
3236 case Options::kStaticExecutable:
3237 case Options::kDynamicBundle:
3238 case Options::kObjectFile:
3239 case Options::kDyld:
3240 case Options::kPreload:
3241 case Options::kKextBundle:
3242 // disable prebinding for everything else
3243 fPrebind = false;
3244 break;
3246 break;
3250 // only prebound images can be split-seg
3251 if ( fSplitSegs && !fPrebind )
3252 fSplitSegs = false;
3254 // determine if info for shared region should be added
3255 if ( fOutputKind == Options::kDynamicLibrary ) {
3256 if ( minOS(ld::mac10_5, ld::iOS_3_1) )
3257 if ( !fPrebind )
3258 if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
3259 || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
3260 fSharedRegionEligible = true;
3262 else if ( fOutputKind == Options::kDyld ) {
3263 // <rdar://problem/10111122> Enable dyld to be put into the dyld shared cache
3264 fSharedRegionEligible = true;
3267 // figure out if module table is needed for compatibility with old ld/dyld
3268 if ( fOutputKind == Options::kDynamicLibrary ) {
3269 switch ( fArchitecture ) {
3270 case CPU_TYPE_I386:
3271 if ( fIOSVersionMin != ld::iOSVersionUnset ) // simulator never needs modules
3272 break;
3273 case CPU_TYPE_ARM:
3274 if ( fPrebind )
3275 fNeedsModuleTable = true; // redo_prebinding requires a module table
3276 break;
3280 // <rdar://problem/5366363> -r -x implies -S
3281 if ( (fOutputKind == Options::kObjectFile) && (fLocalSymbolHandling == kLocalSymbolsNone) )
3282 fDebugInfoStripping = Options::kDebugInfoNone;
3284 // choose how to process unwind info
3285 switch ( fArchitecture ) {
3286 case CPU_TYPE_I386:
3287 case CPU_TYPE_X86_64:
3288 switch ( fOutputKind ) {
3289 case Options::kObjectFile:
3290 case Options::kStaticExecutable:
3291 case Options::kPreload:
3292 case Options::kKextBundle:
3293 fAddCompactUnwindEncoding = false;
3294 break;
3295 case Options::kDyld:
3296 case Options::kDynamicLibrary:
3297 case Options::kDynamicBundle:
3298 case Options::kDynamicExecutable:
3299 //if ( fAddCompactUnwindEncoding && (fVersionMin >= ld::mac10_6) )
3300 // fRemoveDwarfUnwindIfCompactExists = true;
3301 break;
3303 break;
3304 case CPU_TYPE_ARM:
3305 fAddCompactUnwindEncoding = false;
3306 fRemoveDwarfUnwindIfCompactExists = false;
3307 break;
3308 case 0:
3309 // if -arch is missing, assume we don't want compact unwind info
3310 fAddCompactUnwindEncoding = false;
3311 break;
3314 // only ARM main executables can be encrypted
3315 if ( fOutputKind != Options::kDynamicExecutable )
3316 fEncryptable = false;
3317 if ( fArchitecture != CPU_TYPE_ARM )
3318 fEncryptable = false;
3320 // don't move inits in dyld because dyld wants certain
3321 // entries point at stable locations at the start of __text
3322 if ( fOutputKind == Options::kDyld )
3323 fAutoOrderInitializers = false;
3326 // disable __data ordering for some output kinds
3327 switch ( fOutputKind ) {
3328 case Options::kObjectFile:
3329 case Options::kDyld:
3330 case Options::kStaticExecutable:
3331 case Options::kPreload:
3332 case Options::kKextBundle:
3333 fOrderData = false;
3334 break;
3335 case Options::kDynamicExecutable:
3336 case Options::kDynamicLibrary:
3337 case Options::kDynamicBundle:
3338 break;
3341 // only use compressed LINKEDIT for final linked images
3342 switch ( fOutputKind ) {
3343 case Options::kDynamicExecutable:
3344 case Options::kDynamicLibrary:
3345 case Options::kDynamicBundle:
3346 break;
3347 case Options::kPreload:
3348 case Options::kStaticExecutable:
3349 case Options::kObjectFile:
3350 case Options::kDyld:
3351 case Options::kKextBundle:
3352 fMakeCompressedDyldInfoForceOff = true;
3353 break;
3355 if ( fMakeCompressedDyldInfoForceOff )
3356 fMakeCompressedDyldInfo = false;
3359 // only use compressed LINKEDIT for:
3360 // x86_64 and i386 on Mac OS X 10.6 or later
3361 // arm on iPhoneOS 3.1 or later
3362 if ( fMakeCompressedDyldInfo ) {
3363 switch (fArchitecture) {
3364 case CPU_TYPE_I386:
3365 if ( fIOSVersionMin != ld::iOSVersionUnset ) // simulator always uses compressed LINKEDIT
3366 break;
3367 case CPU_TYPE_X86_64:
3368 if ( fMacVersionMin < ld::mac10_6 )
3369 fMakeCompressedDyldInfo = false;
3370 break;
3371 case CPU_TYPE_ARM:
3372 if ( !minOS(ld::mac10_6, ld::iOS_3_1) )
3373 fMakeCompressedDyldInfo = false;
3374 break;
3375 default:
3376 fMakeCompressedDyldInfo = false;
3381 // only ARM enforces that cpu-sub-types must match
3382 if ( fArchitecture != CPU_TYPE_ARM )
3383 fAllowCpuSubtypeMismatches = true;
3385 // only final linked images can not optimize zero fill sections
3386 if ( fOutputKind == Options::kObjectFile )
3387 fOptimizeZeroFill = true;
3389 // all undefines in -r mode
3390 // if ( fOutputKind == Options::kObjectFile )
3391 // fUndefinedTreatment = kUndefinedSuppress;
3393 // only dynamic final linked images should warn about use of commmons
3394 if ( fWarnCommons ) {
3395 switch ( fOutputKind ) {
3396 case Options::kDynamicExecutable:
3397 case Options::kDynamicLibrary:
3398 case Options::kDynamicBundle:
3399 break;
3400 case Options::kPreload:
3401 case Options::kStaticExecutable:
3402 case Options::kObjectFile:
3403 case Options::kDyld:
3404 case Options::kKextBundle:
3405 fWarnCommons = false;
3406 break;
3410 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
3411 if ( minOS(ld::mac10_5, ld::iOS_2_0) )
3412 fUseSimplifiedDylibReExports = true;
3414 // Mac OS X 10.7 and iOS 4.2 support LC_LOAD_UPWARD_DYLIB
3415 if ( minOS(ld::mac10_7, ld::iOS_4_2) && (fOutputKind == kDynamicLibrary) )
3416 fCanUseUpwardDylib = true;
3418 // MacOSX 10.7 defaults to PIE
3419 if ( ((fArchitecture == CPU_TYPE_X86_64) || (fArchitecture == CPU_TYPE_I386))
3420 && (fOutputKind == kDynamicExecutable)
3421 && (fMacVersionMin >= ld::mac10_7) ) {
3422 fPositionIndependentExecutable = true;
3425 // armv7 for iOS4.3 defaults to PIE
3426 if ( (fArchitecture == CPU_TYPE_ARM)
3427 && fArchSupportsThumb2
3428 && (fOutputKind == kDynamicExecutable)
3429 && (fIOSVersionMin >= ld::iOS_4_3) ) {
3430 fPositionIndependentExecutable = true;
3433 // -no_pie anywhere on command line disable PIE
3434 if ( fDisablePositionIndependentExecutable )
3435 fPositionIndependentExecutable = false;
3437 // set fOutputSlidable
3438 switch ( fOutputKind ) {
3439 case Options::kObjectFile:
3440 case Options::kStaticExecutable:
3441 fOutputSlidable = false;
3442 break;
3443 case Options::kDynamicExecutable:
3444 fOutputSlidable = fPositionIndependentExecutable;
3445 break;
3446 case Options::kPreload:
3447 fOutputSlidable = fPIEOnCommandLine;
3448 break;
3449 case Options::kDyld:
3450 case Options::kDynamicLibrary:
3451 case Options::kDynamicBundle:
3452 case Options::kKextBundle:
3453 fOutputSlidable = true;
3454 break;
3457 // let linker know if thread local variables are supported
3458 if ( fMacVersionMin >= ld::mac10_7 ) {
3459 fTLVSupport = true;
3462 // default to adding version load command for dynamic code, static code must opt-in
3463 switch ( fOutputKind ) {
3464 case Options::kObjectFile:
3465 fVersionLoadCommand = false;
3466 break;
3467 case Options::kStaticExecutable:
3468 case Options::kPreload:
3469 case Options::kKextBundle:
3470 if ( fVersionLoadCommandForcedOn )
3471 fVersionLoadCommand = true;
3472 break;
3473 case Options::kDynamicExecutable:
3474 case Options::kDyld:
3475 case Options::kDynamicLibrary:
3476 case Options::kDynamicBundle:
3477 if ( !fVersionLoadCommandForcedOff )
3478 fVersionLoadCommand = true;
3479 // <rdar://problem/9945513> for now, don't create version load commands for iOS simulator builds
3480 if ( fVersionLoadCommand && (fArchitecture == CPU_TYPE_I386) ) {
3481 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
3482 if ( strstr(*sdkit, "/iPhoneSimulator.platform/") != NULL )
3483 fVersionLoadCommand = false;
3486 break;
3489 // default to adding functions start for dynamic code, static code must opt-in
3490 switch ( fOutputKind ) {
3491 case Options::kObjectFile:
3492 fFunctionStartsLoadCommand = false;
3493 break;
3494 case Options::kPreload:
3495 case Options::kStaticExecutable:
3496 case Options::kKextBundle:
3497 if ( fFunctionStartsForcedOn )
3498 fFunctionStartsLoadCommand = true;
3499 break;
3500 case Options::kDynamicExecutable:
3501 case Options::kDyld:
3502 case Options::kDynamicLibrary:
3503 case Options::kDynamicBundle:
3504 if ( !fFunctionStartsForcedOff )
3505 fFunctionStartsLoadCommand = true;
3506 break;
3509 // support re-export of individual symbols in MacOSX 10.7 and iOS 4.2
3510 if ( (fOutputKind == kDynamicLibrary) && minOS(ld::mac10_7, ld::iOS_4_2) )
3511 fCanReExportSymbols = true;
3513 // ObjC optimization is only in dynamic final linked images
3514 switch ( fOutputKind ) {
3515 case Options::kObjectFile:
3516 case Options::kStaticExecutable:
3517 case Options::kPreload:
3518 case Options::kKextBundle:
3519 case Options::kDyld:
3520 fObjcCategoryMerging = false;
3521 break;
3522 case Options::kDynamicExecutable:
3523 case Options::kDynamicLibrary:
3524 case Options::kDynamicBundle:
3525 break;
3528 // i386 main executables linked on Mac OS X 10.7 default to NX heap
3529 // regardless of target unless overriden with -allow_heap_execute anywhere
3530 // on the command line
3531 if ( (fArchitecture == CPU_TYPE_I386) && (fOutputKind == kDynamicExecutable) && !fDisableNonExecutableHeap)
3532 fNonExecutableHeap = true;
3535 void Options::checkIllegalOptionCombinations()
3537 // check -undefined setting
3538 switch ( fUndefinedTreatment ) {
3539 case kUndefinedError:
3540 case kUndefinedDynamicLookup:
3541 // always legal
3542 break;
3543 case kUndefinedWarning:
3544 case kUndefinedSuppress:
3545 // requires flat namespace
3546 if ( fNameSpace == kTwoLevelNameSpace )
3547 throw "can't use -undefined warning or suppress with -twolevel_namespace";
3548 break;
3551 // unify -sub_umbrella with dylibs
3552 for (std::vector<const char*>::iterator it = fSubUmbellas.begin(); it != fSubUmbellas.end(); it++) {
3553 const char* subUmbrella = *it;
3554 bool found = false;
3555 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
3556 Options::FileInfo& info = *fit;
3557 const char* lastSlash = strrchr(info.path, '/');
3558 if ( lastSlash == NULL )
3559 lastSlash = info.path - 1;
3560 if ( strcmp(&lastSlash[1], subUmbrella) == 0 ) {
3561 info.options.fReExport = true;
3562 found = true;
3563 break;
3566 if ( ! found )
3567 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella);
3570 // unify -sub_library with dylibs
3571 for (std::vector<const char*>::iterator it = fSubLibraries.begin(); it != fSubLibraries.end(); it++) {
3572 const char* subLibrary = *it;
3573 bool found = false;
3574 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
3575 Options::FileInfo& info = *fit;
3576 const char* lastSlash = strrchr(info.path, '/');
3577 if ( lastSlash == NULL )
3578 lastSlash = info.path - 1;
3579 const char* dot = strchr(&lastSlash[1], '.');
3580 if ( dot == NULL )
3581 dot = &lastSlash[strlen(lastSlash)];
3582 if ( strncmp(&lastSlash[1], subLibrary, dot-lastSlash-1) == 0 ) {
3583 info.options.fReExport = true;
3584 found = true;
3585 break;
3588 if ( ! found )
3589 warning("-sub_library %s does not match a supplied dylib", subLibrary);
3592 // sync reader options
3593 if ( fNameSpace != kTwoLevelNameSpace )
3594 fFlatNamespace = true;
3596 // check -stack_addr
3597 if ( fStackAddr != 0 ) {
3598 switch (fArchitecture) {
3599 case CPU_TYPE_I386:
3600 case CPU_TYPE_ARM:
3601 if ( fStackAddr > 0xFFFFFFFF )
3602 throw "-stack_addr must be < 4G for 32-bit processes";
3603 break;
3604 case CPU_TYPE_X86_64:
3605 break;
3607 if ( (fStackAddr & -4096) != fStackAddr )
3608 throw "-stack_addr must be multiples of 4K";
3609 if ( fStackSize == 0 )
3610 throw "-stack_addr must be used with -stack_size";
3613 // check -stack_size
3614 if ( fStackSize != 0 ) {
3615 switch (fArchitecture) {
3616 case CPU_TYPE_I386:
3617 if ( fStackSize > 0xFFFFFFFF )
3618 throw "-stack_size must be < 4G for 32-bit processes";
3619 if ( fStackAddr == 0 ) {
3620 fStackAddr = 0xC0000000;
3622 if ( (fStackAddr > 0xB0000000) && ((fStackAddr-fStackSize) < 0xB0000000) )
3623 warning("custom stack placement overlaps and will disable shared region");
3624 break;
3625 case CPU_TYPE_ARM:
3626 if ( fStackSize > 0x2F000000 )
3627 throw "-stack_size must be < 752MB";
3628 if ( fStackAddr == 0 )
3629 fStackAddr = 0x2F000000;
3630 if ( fStackAddr > 0x30000000)
3631 throw "-stack_addr must be < 0x30000000 for arm";
3632 case CPU_TYPE_X86_64:
3633 if ( fStackAddr == 0 ) {
3634 fStackAddr = 0x00007FFF5C000000LL;
3636 break;
3638 if ( (fStackSize & -4096) != fStackSize )
3639 throw "-stack_size must be multiples of 4K";
3640 switch ( fOutputKind ) {
3641 case Options::kDynamicExecutable:
3642 case Options::kStaticExecutable:
3643 // custom stack size only legal when building main executable
3644 break;
3645 case Options::kDynamicLibrary:
3646 case Options::kDynamicBundle:
3647 case Options::kObjectFile:
3648 case Options::kDyld:
3649 case Options::kPreload:
3650 case Options::kKextBundle:
3651 throw "-stack_size option can only be used when linking a main executable";
3653 if ( fStackSize > fStackAddr )
3654 throwf("-stack_size (0x%08llX) must be smaller than -stack_addr (0x%08llX)", fStackSize, fStackAddr);
3657 // check that -allow_stack_execute is only used with main executables
3658 if ( fExecutableStack ) {
3659 switch ( fOutputKind ) {
3660 case Options::kDynamicExecutable:
3661 case Options::kStaticExecutable:
3662 // -allow_stack_execute size only legal when building main executable
3663 break;
3664 case Options::kDynamicLibrary:
3665 case Options::kDynamicBundle:
3666 case Options::kObjectFile:
3667 case Options::kDyld:
3668 case Options::kPreload:
3669 case Options::kKextBundle:
3670 throw "-allow_stack_execute option can only be used when linking a main executable";
3674 // check that -allow_heap_execute is only used with i386 main executables
3675 if ( fDisableNonExecutableHeap ) {
3676 if ( fArchitecture != CPU_TYPE_I386 )
3677 throw "-allow_heap_execute option can only be used when linking for i386";
3678 switch ( fOutputKind ) {
3679 case Options::kDynamicExecutable:
3680 // -allow_heap_execute only legal when building main executable
3681 break;
3682 case Options::kStaticExecutable:
3683 case Options::kDynamicLibrary:
3684 case Options::kDynamicBundle:
3685 case Options::kObjectFile:
3686 case Options::kDyld:
3687 case Options::kPreload:
3688 case Options::kKextBundle:
3689 throw "-allow_heap_execute option can only be used when linking a main executable";
3693 // check -client_name is only used when making a bundle or main executable
3694 if ( fClientName != NULL ) {
3695 switch ( fOutputKind ) {
3696 case Options::kDynamicExecutable:
3697 case Options::kDynamicBundle:
3698 break;
3699 case Options::kStaticExecutable:
3700 case Options::kDynamicLibrary:
3701 case Options::kObjectFile:
3702 case Options::kDyld:
3703 case Options::kPreload:
3704 case Options::kKextBundle:
3705 throw "-client_name can only be used with -bundle";
3709 // check -init is only used when building a dylib
3710 if ( (fInitFunctionName != NULL) && (fOutputKind != Options::kDynamicLibrary) )
3711 throw "-init can only be used with -dynamiclib";
3713 // check -bundle_loader only used with -bundle
3714 if ( (fBundleLoader != NULL) && (fOutputKind != Options::kDynamicBundle) )
3715 throw "-bundle_loader can only be used with -bundle";
3717 // check -dtrace not used with -r
3718 if ( (fDtraceScriptName != NULL) && (fOutputKind == Options::kObjectFile) )
3719 throw "-dtrace can only be used when creating final linked images";
3721 // check -d can only be used with -r
3722 if ( fMakeTentativeDefinitionsReal && (fOutputKind != Options::kObjectFile) )
3723 throw "-d can only be used with -r";
3725 // check that -root_safe is not used with -r
3726 if ( fRootSafe && (fOutputKind == Options::kObjectFile) )
3727 throw "-root_safe cannot be used with -r";
3729 // check that -setuid_safe is not used with -r
3730 if ( fSetuidSafe && (fOutputKind == Options::kObjectFile) )
3731 throw "-setuid_safe cannot be used with -r";
3733 // rdar://problem/4718189 map ObjC class names to new runtime names
3734 bool alterObjC1ClassNamesToObjC2 = false;
3735 switch (fArchitecture) {
3736 case CPU_TYPE_I386:
3737 // i386 only uses new symbols when using objc2 ABI
3738 if ( fObjCABIVersion2Override )
3739 alterObjC1ClassNamesToObjC2 = true;
3740 break;
3741 case CPU_TYPE_X86_64:
3742 case CPU_TYPE_ARM:
3743 alterObjC1ClassNamesToObjC2 = true;
3744 break;
3747 // make sure all required exported symbols exist
3748 std::vector<const char*> impliedExports;
3749 for (NameSet::iterator it=fExportSymbols.regularBegin(); it != fExportSymbols.regularEnd(); ++it) {
3750 const char* name = *it;
3751 const int len = strlen(name);
3752 if ( (strcmp(&name[len-3], ".eh") == 0) || (strncmp(name, ".objc_category_name_", 20) == 0) ) {
3753 // never export .eh symbols
3754 warning("ignoring %s in export list", name);
3756 else if ( (fArchitecture == CPU_TYPE_I386) && !fObjCABIVersion2Override && (strncmp(name, "_OBJC_CLASS_$", 13) == 0) ) {
3757 warning("ignoring Objc2 Class symbol %s in i386 export list", name);
3758 fRemovedExports.insert(name);
3760 else if ( alterObjC1ClassNamesToObjC2 && (strncmp(name, ".objc_class_name_", 17) == 0) ) {
3761 // linking ObjC2 ABI, but have ObjC1 ABI name in export list. Change it to intended name
3762 fRemovedExports.insert(name);
3763 char* temp;
3764 asprintf(&temp, "_OBJC_CLASS_$_%s", &name[17]);
3765 impliedExports.push_back(temp);
3766 asprintf(&temp, "_OBJC_METACLASS_$_%s", &name[17]);
3767 impliedExports.push_back(temp);
3769 else {
3770 fInitialUndefines.push_back(name);
3773 fExportSymbols.remove(fRemovedExports);
3774 for (std::vector<const char*>::iterator it=impliedExports.begin(); it != impliedExports.end(); ++it) {
3775 const char* name = *it;
3776 fExportSymbols.insert(name);
3777 fInitialUndefines.push_back(name);
3780 // make sure all required re-exported symbols exist
3781 for (NameSet::iterator it=fReExportSymbols.regularBegin(); it != fReExportSymbols.regularEnd(); ++it) {
3782 fInitialUndefines.push_back(*it);
3785 // make sure that -init symbol exists
3786 if ( fInitFunctionName != NULL )
3787 fInitialUndefines.push_back(fInitFunctionName);
3789 // make sure that entry symbol exists
3790 switch ( fOutputKind ) {
3791 case Options::kDynamicExecutable:
3792 case Options::kStaticExecutable:
3793 case Options::kDyld:
3794 case Options::kPreload:
3795 fInitialUndefines.push_back(fEntryName);
3796 break;
3797 case Options::kDynamicLibrary:
3798 case Options::kDynamicBundle:
3799 case Options::kObjectFile:
3800 case Options::kKextBundle:
3801 break;
3804 // make sure every alias base exists
3805 for (std::vector<AliasPair>::iterator it=fAliases.begin(); it != fAliases.end(); ++it) {
3806 fInitialUndefines.push_back(it->realName);
3809 // check custom segments
3810 if ( fCustomSegmentAddresses.size() != 0 ) {
3811 // verify no segment is in zero page
3812 if ( fZeroPageSize != ULLONG_MAX ) {
3813 for (std::vector<SegmentStart>::iterator it = fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
3814 if ( it->address < fZeroPageSize )
3815 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it->name, it->address);
3818 // verify no duplicates
3819 for (std::vector<SegmentStart>::iterator it = fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
3820 for (std::vector<SegmentStart>::iterator it2 = fCustomSegmentAddresses.begin(); it2 != fCustomSegmentAddresses.end(); ++it2) {
3821 if ( (it->address == it2->address) && (it != it2) )
3822 throwf("duplicate -segaddr addresses for %s and %s", it->name, it2->name);
3824 // a custom segment address of zero will disable the use of a zero page
3825 if ( it->address == 0 )
3826 fZeroPageSize = 0;
3830 if ( fZeroPageSize == ULLONG_MAX ) {
3831 // zero page size not specified on command line, set default
3832 switch (fArchitecture) {
3833 case CPU_TYPE_I386:
3834 case CPU_TYPE_ARM:
3835 // first 4KB for 32-bit architectures
3836 fZeroPageSize = 0x1000;
3837 break;
3838 case CPU_TYPE_X86_64:
3839 // first 4GB for x86_64 on all OS's
3840 fZeroPageSize = 0x100000000ULL;
3841 break;
3842 default:
3843 // if -arch not used, default to 4K zero-page
3844 fZeroPageSize = 0x1000;
3847 else {
3848 switch ( fOutputKind ) {
3849 case Options::kDynamicExecutable:
3850 case Options::kStaticExecutable:
3851 // -pagezero_size size only legal when building main executable
3852 break;
3853 case Options::kDynamicLibrary:
3854 case Options::kDynamicBundle:
3855 case Options::kObjectFile:
3856 case Options::kDyld:
3857 case Options::kPreload:
3858 case Options::kKextBundle:
3859 if ( fZeroPageSize != 0 )
3860 throw "-pagezero_size option can only be used when linking a main executable";
3864 // if main executable with custom base address, model zero page as custom segment
3865 if ( (fOutputKind == Options::kDynamicExecutable) && (fBaseAddress != 0) && (fZeroPageSize != 0) ) {
3866 SegmentStart seg;
3867 seg.name = "__PAGEZERO";
3868 seg.address = 0;;
3869 fCustomSegmentAddresses.push_back(seg);
3872 // -dead_strip and -r are incompatible
3873 if ( fDeadStrip && (fOutputKind == Options::kObjectFile) )
3874 throw "-r and -dead_strip cannot be used together";
3876 // can't use -rpath unless targeting 10.5 or later
3877 if ( fRPaths.size() > 0 ) {
3878 if ( !minOS(ld::mac10_5, ld::iOS_2_0) )
3879 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
3880 switch ( fOutputKind ) {
3881 case Options::kDynamicExecutable:
3882 case Options::kDynamicLibrary:
3883 case Options::kDynamicBundle:
3884 break;
3885 case Options::kStaticExecutable:
3886 case Options::kObjectFile:
3887 case Options::kDyld:
3888 case Options::kPreload:
3889 case Options::kKextBundle:
3890 throw "-rpath can only be used when creating a dynamic final linked image";
3894 // check -pie is only used when building a dynamic main executable for 10.5
3895 if ( fPositionIndependentExecutable ) {
3896 switch ( fOutputKind ) {
3897 case Options::kDynamicExecutable:
3898 if ( !minOS(ld::mac10_5, ld::iOS_4_2) ) {
3899 if ( fIOSVersionMin == ld::iOSVersionUnset )
3900 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
3901 else
3902 throw "-pie can only be used when targeting iOS 4.2 or later";
3904 break;
3905 case Options::kPreload:
3906 break;
3907 case Options::kDynamicLibrary:
3908 case Options::kDynamicBundle:
3909 warning("-pie being ignored. It is only used when linking a main executable");
3910 fPositionIndependentExecutable = false;
3911 break;
3912 case Options::kStaticExecutable:
3913 case Options::kObjectFile:
3914 case Options::kDyld:
3915 case Options::kKextBundle:
3916 throw "-pie can only be used when linking a main executable";
3920 // check -read_only_relocs is not used with x86_64
3921 if ( fAllowTextRelocs ) {
3922 if ( (fArchitecture == CPU_TYPE_X86_64) && (fOutputKind != kKextBundle) ) {
3923 warning("-read_only_relocs cannot be used with x86_64");
3924 fAllowTextRelocs = false;
3928 // check -mark_auto_dead_strip is only used with dylibs
3929 if ( fMarkDeadStrippableDylib ) {
3930 if ( fOutputKind != Options::kDynamicLibrary ) {
3931 warning("-mark_auto_dead_strip can only be used when creating a dylib");
3932 fMarkDeadStrippableDylib = false;
3936 // -force_cpusubtype_ALL is not supported for ARM
3937 if ( fForceSubtypeAll ) {
3938 if ( fArchitecture == CPU_TYPE_ARM ) {
3939 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
3943 // -reexported_symbols_list can only be used with -dynamiclib
3944 if ( !fReExportSymbols.empty() ) {
3945 if ( fOutputKind != Options::kDynamicLibrary )
3946 throw "-reexported_symbols_list can only used used when created dynamic libraries";
3947 if ( !minOS(ld::mac10_7, ld::iOS_4_2) )
3948 throw "targeted OS version does not support -reexported_symbols_list";
3951 // -dyld_env can only be used with main executables
3952 if ( (fOutputKind != Options::kDynamicExecutable) && (fDyldEnvironExtras.size() != 0) )
3953 throw "-dyld_env can only used used when created main executables";
3957 void Options::checkForClassic(int argc, const char* argv[])
3959 // scan options
3960 bool archFound = false;
3961 bool staticFound = false;
3962 bool dtraceFound = false;
3963 bool kextFound = false;
3964 bool rFound = false;
3965 bool creatingMachKernel = false;
3966 bool newLinker = false;
3968 // build command line buffer in case ld crashes
3969 const char* srcRoot = getenv("SRCROOT");
3970 if ( srcRoot != NULL ) {
3971 strlcpy(crashreporterBuffer, "SRCROOT=", crashreporterBufferSize);
3972 strlcat(crashreporterBuffer, srcRoot, crashreporterBufferSize);
3973 strlcat(crashreporterBuffer, "\n", crashreporterBufferSize);
3975 #ifdef LD_VERS
3976 strlcat(crashreporterBuffer, LD_VERS, crashreporterBufferSize);
3977 strlcat(crashreporterBuffer, "\n", crashreporterBufferSize);
3978 #endif
3979 strlcat(crashreporterBuffer, "ld ", crashreporterBufferSize);
3980 for(int i=1; i < argc; ++i) {
3981 strlcat(crashreporterBuffer, argv[i], crashreporterBufferSize);
3982 strlcat(crashreporterBuffer, " ", crashreporterBufferSize);
3985 for(int i=0; i < argc; ++i) {
3986 const char* arg = argv[i];
3987 if ( arg[0] == '-' ) {
3988 if ( strcmp(arg, "-arch") == 0 ) {
3989 parseArch(argv[++i]);
3990 archFound = true;
3992 else if ( strcmp(arg, "-static") == 0 ) {
3993 staticFound = true;
3995 else if ( strcmp(arg, "-kext") == 0 ) {
3996 kextFound = true;
3998 else if ( strcmp(arg, "-dtrace") == 0 ) {
3999 dtraceFound = true;
4001 else if ( strcmp(arg, "-r") == 0 ) {
4002 rFound = true;
4004 else if ( strcmp(arg, "-new_linker") == 0 ) {
4005 newLinker = true;
4007 else if ( strcmp(arg, "-classic_linker") == 0 ) {
4008 // ld_classic does not understand this option, so remove it
4009 for(int j=i; j < argc; ++j)
4010 argv[j] = argv[j+1];
4011 warning("using ld_classic");
4012 this->gotoClassicLinker(argc-1, argv);
4014 else if ( strcmp(arg, "-o") == 0 ) {
4015 const char* outfile = argv[++i];
4016 if ( (outfile != NULL) && (strstr(outfile, "/mach_kernel") != NULL) )
4017 creatingMachKernel = true;
4022 // -dtrace only supported by new linker
4023 if( dtraceFound )
4024 return;
4026 if( archFound ) {
4027 switch ( fArchitecture ) {
4028 case CPU_TYPE_I386:
4029 if ( (staticFound || kextFound) && !newLinker ) {
4030 // this environment variable will disable use of ld_classic for -static links
4031 if ( getenv("LD_NO_CLASSIC_LINKER_STATIC") == NULL ) {
4032 this->gotoClassicLinker(argc, argv);
4035 break;
4038 else {
4039 // work around for VSPTool
4040 if ( staticFound ) {
4041 warning("using ld_classic");
4042 this->gotoClassicLinker(argc, argv);
4048 void Options::gotoClassicLinker(int argc, const char* argv[])
4050 argv[0] = "ld_classic";
4051 // ld_classic does not support -iphoneos_version_min, so change
4052 for(int j=0; j < argc; ++j) {
4053 if ( (strcmp(argv[j], "-iphoneos_version_min") == 0) || (strcmp(argv[j], "-ios_version_min") == 0) ) {
4054 argv[j] = "-macosx_version_min";
4055 if ( j < argc-1 )
4056 argv[j+1] = "10.5";
4057 break;
4060 // ld classic does not understand -kext (change to -static -r)
4061 for(int j=0; j < argc; ++j) {
4062 if ( strcmp(argv[j], "-kext") == 0)
4063 argv[j] = "-r";
4064 else if ( strcmp(argv[j], "-dynamic") == 0)
4065 argv[j] = "-static";
4067 // ld classic does not understand -demangle
4068 for(int j=0; j < argc; ++j) {
4069 if ( strcmp(argv[j], "-demangle") == 0)
4070 argv[j] = "-noprebind";
4072 // in -v mode, print command line passed to ld_classic
4073 for(int i=0; i < argc; ++i) {
4074 if ( strcmp(argv[i], "-v") == 0 ) {
4075 for(int j=0; j < argc; ++j)
4076 printf("%s ", argv[j]);
4077 printf("\n");
4078 break;
4081 char rawPath[PATH_MAX];
4082 char path[PATH_MAX];
4083 uint32_t bufSize = PATH_MAX;
4084 if ( _NSGetExecutablePath(rawPath, &bufSize) != -1 ) {
4085 if ( realpath(rawPath, path) != NULL ) {
4086 char* lastSlash = strrchr(path, '/');
4087 if ( lastSlash != NULL ) {
4088 strcpy(lastSlash+1, "ld_classic");
4089 argv[0] = path;
4090 execvp(path, (char**)argv);
4094 // in case of error in above, try searching for ld_classic via PATH
4095 execvp(argv[0], (char**)argv);
4096 fprintf(stderr, "can't exec ld_classic\n");
4097 exit(1);