123.2
[darwin-xtools.git] / ld64 / src / ld / Options.cpp
blob1de337988a27f6928efac0e1e086d01e25b3bf9f
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2005-2010 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 const char* sWarningsSideFilePath = NULL;
52 static FILE* sWarningsSideFile = NULL;
54 void warning(const char* format, ...)
56 if ( sEmitWarnings ) {
57 va_list list;
58 if ( sWarningsSideFilePath != NULL ) {
59 if ( sWarningsSideFile == NULL )
60 sWarningsSideFile = fopen(sWarningsSideFilePath, "a");
62 va_start(list, format);
63 fprintf(stderr, "ld: warning: ");
64 vfprintf(stderr, format, list);
65 fprintf(stderr, "\n");
66 if ( sWarningsSideFile != NULL ) {
67 fprintf(sWarningsSideFile, "ld: warning: ");
68 vfprintf(sWarningsSideFile, format, list);
69 fprintf(sWarningsSideFile, "\n");
70 fflush(sWarningsSideFile);
72 va_end(list);
76 void throwf(const char* format, ...)
78 va_list list;
79 char* p;
80 va_start(list, format);
81 vasprintf(&p, format, list);
82 va_end(list);
84 const char* t = p;
85 throw t;
88 Options::Options(int argc, const char* argv[])
89 : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0), fArchitectureName("unknown"), fOutputKind(kDynamicExecutable),
90 fHasPreferredSubType(false), fPrebind(false), fBindAtLoad(false), fKeepPrivateExterns(false),
91 fNeedsModuleTable(false), fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false),
92 fInterposeMode(kInterposeNone), fDeadStrip(false), fNameSpace(kTwoLevelNameSpace),
93 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL), fFinalName(NULL), fEntryName("start"),
94 fBaseAddress(0), fMaxAddress(0x7FFFFFFFFFFFFFFFLL),
95 fBaseWritableAddress(0), fSplitSegs(false),
96 fExportMode(kExportDefault), fLibrarySearchMode(kSearchDylibAndArchiveInEachDir),
97 fUndefinedTreatment(kUndefinedError), fMessagesPrefixedWithArchitecture(true),
98 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak),
99 fClientName(NULL),
100 fUmbrellaName(NULL), fInitFunctionName(NULL), fDotOutputFile(NULL), fExecutablePath(NULL),
101 fBundleLoader(NULL), fDtraceScriptName(NULL), fSegAddrTablePath(NULL), fMapPath(NULL),
102 fDyldInstallPath("/usr/lib/dyld"), fTempLtoObjectPath(NULL),
103 fZeroPageSize(ULLONG_MAX), fStackSize(0), fStackAddr(0), fExecutableStack(false),
104 fNonExecutableHeap(false), fDisableNonExecutableHeap(false),
105 fMinimumHeaderPad(32), fSegmentAlignment(4096),
106 fCommonsMode(kCommonsIgnoreDylibs), fUUIDMode(kUUIDContent), fLocalSymbolHandling(kLocalSymbolsAll), fWarnCommons(false),
107 fVerbose(false), fKeepRelocations(false), fWarnStabs(false),
108 fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
109 fSharedRegionEligible(false), fPrintOrderFileStatistics(false),
110 fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), fPIEOnCommandLine(false),
111 fDisablePositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
112 fDeadStripDylibs(false), fAllowTextRelocs(false), fWarnTextRelocs(false),
113 fUsingLazyDylibLinking(false), fEncryptable(true),
114 fOrderData(true), fMarkDeadStrippableDylib(false),
115 fMakeCompressedDyldInfo(true), fMakeCompressedDyldInfoForceOff(false), fNoEHLabels(false),
116 fAllowCpuSubtypeMismatches(false), fUseSimplifiedDylibReExports(false),
117 fObjCABIVersion2Override(false), fObjCABIVersion1Override(false), fCanUseUpwardDylib(false),
118 fFullyLoadArchives(false), fLoadAllObjcObjectsFromArchives(false), fFlatNamespace(false),
119 fLinkingMainExecutable(false), fForFinalLinkedImage(false), fForStatic(false),
120 fForDyld(false), fMakeTentativeDefinitionsReal(false), fWhyLoad(false), fRootSafe(false),
121 fSetuidSafe(false), fImplicitlyLinkPublicDylibs(true), fAddCompactUnwindEncoding(true),
122 fWarnCompactUnwind(false), fRemoveDwarfUnwindIfCompactExists(false),
123 fAutoOrderInitializers(true), fOptimizeZeroFill(true), fLogObjectFiles(false),
124 fLogAllFiles(false), fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false),
125 fOutputSlidable(false), fWarnWeakExports(false),
126 fObjcGcCompaction(false), fObjCGc(false), fObjCGcOnly(false),
127 fDemangle(false), fTLVSupport(false),
128 #if __MAC_OS_X_VERSION_MIN_REQUIRED < 1070
129 fVersionLoadCommand(false), fFunctionStartsLoadCommand(false),
130 #else
131 fVersionLoadCommand(true), fFunctionStartsLoadCommand(true),
132 #endif
133 fCanReExportSymbols(false), fObjcCategoryMerging(true),
134 fDebugInfoStripping(kDebugInfoMinimal), fTraceOutputFile(NULL),
135 fMacVersionMin(ld::macVersionUnset), fIPhoneVersionMin(ld::iPhoneVersionUnset),
136 fSaveTempFiles(false)
138 this->checkForClassic(argc, argv);
139 this->parsePreCommandLineEnvironmentSettings();
140 this->parse(argc, argv);
141 this->parsePostCommandLineEnvironmentSettings();
142 this->reconfigureDefaults();
143 this->checkIllegalOptionCombinations();
146 Options::~Options()
153 const char* Options::installPath() const
155 if ( fDylibInstallName != NULL )
156 return fDylibInstallName;
157 else if ( fFinalName != NULL )
158 return fFinalName;
159 else
160 return fOutputFile;
164 bool Options::interposable(const char* name) const
166 switch ( fInterposeMode ) {
167 case kInterposeNone:
168 return false;
169 case kInterposeAllExternal:
170 return true;
171 case kInterposeSome:
172 return fInterposeList.contains(name);
174 throw "internal error";
180 bool Options::printWhyLive(const char* symbolName) const
182 return ( fWhyLive.find(symbolName) != fWhyLive.end() );
186 const char* Options::dotOutputFile()
188 return fDotOutputFile;
192 bool Options::hasWildCardExportRestrictList() const
194 // has -exported_symbols_list which contains some wildcards
195 return ((fExportMode == kExportSome) && fExportSymbols.hasWildCards());
198 bool Options::hasWeakBitTweaks() const
200 // has -exported_symbols_list which contains some wildcards
201 return (!fForceWeakSymbols.empty() || !fForceNotWeakSymbols.empty());
204 bool Options::allGlobalsAreDeadStripRoots() const
206 // -exported_symbols_list means globals are not exported by default
207 if ( fExportMode == kExportSome )
208 return false;
210 switch ( fOutputKind ) {
211 case Options::kDynamicExecutable:
212 case Options::kStaticExecutable:
213 case Options::kPreload:
214 // by default unused globals in a main executable are stripped
215 return false;
216 case Options::kDynamicLibrary:
217 case Options::kDynamicBundle:
218 case Options::kObjectFile:
219 case Options::kDyld:
220 case Options::kKextBundle:
221 return true;
223 return false;
227 bool Options::keepRelocations()
229 return fKeepRelocations;
232 bool Options::warnStabs()
234 return fWarnStabs;
237 const char* Options::executablePath()
239 return fExecutablePath;
243 uint32_t Options::initialSegProtection(const char* segName) const
245 for(std::vector<Options::SegmentProtect>::const_iterator it = fCustomSegmentProtections.begin(); it != fCustomSegmentProtections.end(); ++it) {
246 if ( strcmp(it->name, segName) == 0 ) {
247 return it->init;
250 if ( strcmp(segName, "__PAGEZERO") == 0 ) {
251 return 0;
253 else if ( strcmp(segName, "__TEXT") == 0 ) {
254 return VM_PROT_READ | VM_PROT_EXECUTE;
256 else if ( strcmp(segName, "__LINKEDIT") == 0 ) {
257 return VM_PROT_READ;
260 // all others default to read-write
261 return VM_PROT_READ | VM_PROT_WRITE;
264 uint32_t Options::maxSegProtection(const char* segName) const
266 // iPhoneOS always uses same protection for max and initial
267 if ( fIPhoneVersionMin != ld::iPhoneVersionUnset )
268 return initialSegProtection(segName);
270 for(std::vector<Options::SegmentProtect>::const_iterator it = fCustomSegmentProtections.begin(); it != fCustomSegmentProtections.end(); ++it) {
271 if ( strcmp(it->name, segName) == 0 ) {
272 return it->max;
275 if ( strcmp(segName, "__PAGEZERO") == 0 ) {
276 return 0;
278 // all others default to all
279 return VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
282 uint64_t Options::segPageSize(const char* segName) const
284 for(std::vector<SegmentSize>::const_iterator it=fCustomSegmentSizes.begin(); it != fCustomSegmentSizes.end(); ++it) {
285 if ( strcmp(it->name, segName) == 0 )
286 return it->size;
288 return fSegmentAlignment;
291 uint64_t Options::customSegmentAddress(const char* segName) const
293 for(std::vector<SegmentStart>::const_iterator it=fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
294 if ( strcmp(it->name, segName) == 0 )
295 return it->address;
297 // if custom stack in use, model as segment with custom address
298 if ( (fStackSize != 0) && (strcmp("__UNIXSTACK", segName) == 0) )
299 return fStackAddr - fStackSize;
300 return 0;
303 bool Options::hasCustomSegmentAddress(const char* segName) const
305 for(std::vector<SegmentStart>::const_iterator it=fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
306 if ( strcmp(it->name, segName) == 0 )
307 return true;
309 // if custom stack in use, model as segment with custom address
310 if ( (fStackSize != 0) && (strcmp("__UNIXSTACK", segName) == 0) )
311 return true;
312 return false;
315 bool Options::hasCustomSectionAlignment(const char* segName, const char* sectName) const
317 for (std::vector<SectionAlignment>::const_iterator it = fSectionAlignments.begin(); it != fSectionAlignments.end(); ++it) {
318 if ( (strcmp(it->segmentName, segName) == 0) && (strcmp(it->sectionName, sectName) == 0) )
319 return true;
321 return false;
324 uint8_t Options::customSectionAlignment(const char* segName, const char* sectName) const
326 for (std::vector<SectionAlignment>::const_iterator it = fSectionAlignments.begin(); it != fSectionAlignments.end(); ++it) {
327 if ( (strcmp(it->segmentName, segName) == 0) && (strcmp(it->sectionName, sectName) == 0) )
328 return it->alignment;
330 return 0;
334 bool Options::hasExportedSymbolOrder()
336 return (fExportSymbolsOrder.size() > 0);
339 bool Options::exportedSymbolOrder(const char* sym, unsigned int* order) const
341 NameToOrder::const_iterator pos = fExportSymbolsOrder.find(sym);
342 if ( pos != fExportSymbolsOrder.end() ) {
343 *order = pos->second;
344 return true;
346 else {
347 *order = 0xFFFFFFFF;
348 return false;
352 void Options::loadSymbolOrderFile(const char* fileOfExports, NameToOrder& orderMapping)
354 // read in whole file
355 int fd = ::open(fileOfExports, O_RDONLY, 0);
356 if ( fd == -1 )
357 throwf("can't open -exported_symbols_order file: %s", fileOfExports);
358 struct stat stat_buf;
359 ::fstat(fd, &stat_buf);
360 char* p = (char*)malloc(stat_buf.st_size);
361 if ( p == NULL )
362 throwf("can't process -exported_symbols_order file: %s", fileOfExports);
364 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
365 throwf("can't read -exported_symbols_order file: %s", fileOfExports);
367 ::close(fd);
369 // parse into symbols and add to hash_set
370 unsigned int count = 0;
371 char * const end = &p[stat_buf.st_size];
372 enum { lineStart, inSymbol, inComment } state = lineStart;
373 char* symbolStart = NULL;
374 for (char* s = p; s < end; ++s ) {
375 switch ( state ) {
376 case lineStart:
377 if ( *s =='#' ) {
378 state = inComment;
380 else if ( !isspace(*s) ) {
381 state = inSymbol;
382 symbolStart = s;
384 break;
385 case inSymbol:
386 if ( (*s == '\n') || (*s == '\r') ) {
387 *s = '\0';
388 // removing any trailing spaces
389 char* last = s-1;
390 while ( isspace(*last) ) {
391 *last = '\0';
392 --last;
394 orderMapping[symbolStart] = ++count;
395 symbolStart = NULL;
396 state = lineStart;
398 break;
399 case inComment:
400 if ( (*s == '\n') || (*s == '\r') )
401 state = lineStart;
402 break;
405 if ( state == inSymbol ) {
406 warning("missing line-end at end of file \"%s\"", fileOfExports);
407 int len = end-symbolStart+1;
408 char* temp = new char[len];
409 strlcpy(temp, symbolStart, len);
411 // remove any trailing spaces
412 char* last = &temp[len-2];
413 while ( isspace(*last) ) {
414 *last = '\0';
415 --last;
417 orderMapping[temp] = ++count;
420 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
423 bool Options::forceWeak(const char* symbolName) const
425 return fForceWeakSymbols.contains(symbolName);
428 bool Options::forceNotWeak(const char* symbolName) const
430 return fForceNotWeakSymbols.contains(symbolName);
433 bool Options::forceWeakNonWildCard(const char* symbolName) const
435 return fForceWeakSymbols.containsNonWildcard(symbolName);
438 bool Options::forceNotWeakNonWildcard(const char* symbolName) const
440 return fForceNotWeakSymbols.containsNonWildcard(symbolName);
444 bool Options::shouldExport(const char* symbolName) const
446 switch (fExportMode) {
447 case kExportSome:
448 return fExportSymbols.contains(symbolName);
449 case kDontExportSome:
450 return ! fDontExportSymbols.contains(symbolName);
451 case kExportDefault:
452 return true;
454 throw "internal error";
457 bool Options::shouldReExport(const char* symbolName) const
459 return fReExportSymbols.contains(symbolName);
462 bool Options::keepLocalSymbol(const char* symbolName) const
464 switch (fLocalSymbolHandling) {
465 case kLocalSymbolsAll:
466 return true;
467 case kLocalSymbolsNone:
468 return false;
469 case kLocalSymbolsSelectiveInclude:
470 return fLocalSymbolsIncluded.contains(symbolName);
471 case kLocalSymbolsSelectiveExclude:
472 return ! fLocalSymbolsExcluded.contains(symbolName);
474 throw "internal error";
478 void Options::setArchitecture(cpu_type_t type, cpu_subtype_t subtype)
480 fArchitecture = type;
481 fSubArchitecture = subtype;
482 switch ( type ) {
483 case CPU_TYPE_POWERPC:
484 switch ( subtype ) {
485 case CPU_SUBTYPE_POWERPC_750:
486 fArchitectureName = "ppc750";
487 fHasPreferredSubType = true;
488 break;
489 case CPU_SUBTYPE_POWERPC_7400:
490 fArchitectureName = "ppc7400";
491 fHasPreferredSubType = true;
492 break;
493 case CPU_SUBTYPE_POWERPC_7450:
494 fArchitectureName = "ppc7450";
495 fHasPreferredSubType = true;
496 break;
497 case CPU_SUBTYPE_POWERPC_970:
498 fArchitectureName = "ppc970";
499 fHasPreferredSubType = true;
500 break;
501 case CPU_SUBTYPE_POWERPC_ALL:
502 fArchitectureName = "ppc";
503 fHasPreferredSubType = false;
504 break;
505 default:
506 assert(0 && "unknown ppc subtype");
507 fArchitectureName = "ppc";
508 break;
510 if ( (fMacVersionMin == ld::macVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
511 #ifdef DEFAULT_MACOSX_MIN_VERSION
512 warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION);
513 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
514 #else
515 warning("-macosx_version_min not specificed, assuming 10.6");
516 fMacVersionMin = ld::mac10_6;
517 #endif
519 break;
520 case CPU_TYPE_POWERPC64:
521 fArchitectureName = "ppc64";
522 if ( (fMacVersionMin == ld::macVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
523 warning("-macosx_version_min not specificed, assuming 10.5");
524 fMacVersionMin = ld::mac10_5;
526 break;
527 case CPU_TYPE_I386:
528 fArchitectureName = "i386";
529 if ( (fMacVersionMin == ld::macVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
530 #ifdef DEFAULT_MACOSX_MIN_VERSION
531 warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION);
532 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
533 #else
534 warning("-macosx_version_min not specificed, assuming 10.6");
535 fMacVersionMin = ld::mac10_6;
536 #endif
538 if ( !fMakeCompressedDyldInfo && (fMacVersionMin >= ld::mac10_6) && !fMakeCompressedDyldInfoForceOff )
539 fMakeCompressedDyldInfo = true;
540 break;
541 case CPU_TYPE_X86_64:
542 fArchitectureName = "x86_64";
543 if ( (fMacVersionMin == ld::macVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
544 #ifdef DEFAULT_MACOSX_MIN_VERSION
545 warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION);
546 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
547 #else
548 warning("-macosx_version_min not specificed, assuming 10.6");
549 fMacVersionMin = ld::mac10_6;
550 #endif
552 if ( !fMakeCompressedDyldInfo && (fMacVersionMin >= ld::mac10_6) && !fMakeCompressedDyldInfoForceOff )
553 fMakeCompressedDyldInfo = true;
554 break;
555 case CPU_TYPE_ARM:
556 switch ( subtype ) {
557 case CPU_SUBTYPE_ARM_V4T:
558 fArchitectureName = "armv4t";
559 fHasPreferredSubType = true;
560 break;
561 case CPU_SUBTYPE_ARM_V5TEJ:
562 fArchitectureName = "armv5";
563 fHasPreferredSubType = true;
564 break;
565 case CPU_SUBTYPE_ARM_V6:
566 fArchitectureName = "armv6";
567 fHasPreferredSubType = true;
568 break;
569 case CPU_SUBTYPE_ARM_V7:
570 fArchitectureName = "armv7";
571 fHasPreferredSubType = true;
572 break;
573 default:
574 assert(0 && "unknown arm subtype");
575 fArchitectureName = "arm";
576 break;
578 if ( (fMacVersionMin == ld::macVersionUnset) && (fIPhoneVersionMin == ld::iPhoneVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
579 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
580 warning("-ios_version_min not specificed, assuming " DEFAULT_IPHONEOS_MIN_VERSION);
581 setIPhoneVersionMin(DEFAULT_IPHONEOS_MIN_VERSION);
582 #elif defined(DEFAULT_MACOSX_MIN_VERSION)
583 warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION);
584 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
585 #else
586 warning("-macosx_version_min not specificed, assuming 10.6");
587 fMacVersionMin = ld::mac10_6;
588 #endif
590 if ( !fMakeCompressedDyldInfo && minOS(ld::mac10_6, ld::iPhone3_1) && !fMakeCompressedDyldInfoForceOff )
591 fMakeCompressedDyldInfo = true;
592 break;
593 default:
594 fArchitectureName = "unknown architecture";
595 break;
599 void Options::parseArch(const char* arch)
601 if ( arch == NULL )
602 throw "-arch must be followed by an architecture string";
603 fArchitectureName = arch;
604 if ( strcmp(arch, "ppc") == 0 ) {
605 fArchitecture = CPU_TYPE_POWERPC;
606 fSubArchitecture = CPU_SUBTYPE_POWERPC_ALL;
608 else if ( strcmp(arch, "ppc64") == 0 ) {
609 fArchitecture = CPU_TYPE_POWERPC64;
610 fSubArchitecture = CPU_SUBTYPE_POWERPC_ALL;
612 else if ( strcmp(arch, "i386") == 0 ) {
613 fArchitecture = CPU_TYPE_I386;
614 fSubArchitecture = CPU_SUBTYPE_I386_ALL;
616 else if ( strcmp(arch, "x86_64") == 0 ) {
617 fArchitecture = CPU_TYPE_X86_64;
618 fSubArchitecture = CPU_SUBTYPE_X86_64_ALL;
620 else if ( strcmp(arch, "arm") == 0 ) {
621 fArchitecture = CPU_TYPE_ARM;
622 fSubArchitecture = CPU_SUBTYPE_ARM_ALL;
624 // compatibility support for cpu-sub-types
625 else if ( strcmp(arch, "ppc750") == 0 ) {
626 fArchitecture = CPU_TYPE_POWERPC;
627 fSubArchitecture = CPU_SUBTYPE_POWERPC_750;
628 fHasPreferredSubType = true;
630 else if ( strcmp(arch, "ppc7400") == 0 ) {
631 fArchitecture = CPU_TYPE_POWERPC;
632 fSubArchitecture = CPU_SUBTYPE_POWERPC_7400;
633 fHasPreferredSubType = true;
635 else if ( strcmp(arch, "ppc7450") == 0 ) {
636 fArchitecture = CPU_TYPE_POWERPC;
637 fSubArchitecture = CPU_SUBTYPE_POWERPC_7450;
638 fHasPreferredSubType = true;
640 else if ( strcmp(arch, "ppc970") == 0 ) {
641 fArchitecture = CPU_TYPE_POWERPC;
642 fSubArchitecture = CPU_SUBTYPE_POWERPC_970;
643 fHasPreferredSubType = true;
645 else if ( strcmp(arch, "armv6") == 0 ) {
646 fArchitecture = CPU_TYPE_ARM;
647 fSubArchitecture = CPU_SUBTYPE_ARM_V6;
648 fHasPreferredSubType = true;
650 else if ( strcmp(arch, "armv5") == 0 ) {
651 fArchitecture = CPU_TYPE_ARM;
652 fSubArchitecture = CPU_SUBTYPE_ARM_V5TEJ;
653 fHasPreferredSubType = true;
655 else if ( strcmp(arch, "armv4t") == 0 ) {
656 fArchitecture = CPU_TYPE_ARM;
657 fSubArchitecture = CPU_SUBTYPE_ARM_V4T;
658 fHasPreferredSubType = true;
660 else if ( strcmp(arch, "xscale") == 0 ) {
661 fArchitecture = CPU_TYPE_ARM;
662 fSubArchitecture = CPU_SUBTYPE_ARM_XSCALE;
663 fHasPreferredSubType = true;
665 else if ( strcmp(arch, "armv7") == 0 ) {
666 fArchitecture = CPU_TYPE_ARM;
667 fSubArchitecture = CPU_SUBTYPE_ARM_V7;
668 fHasPreferredSubType = true;
670 else
671 throwf("unknown/unsupported architecture name for: -arch %s", arch);
674 bool Options::checkForFile(const char* format, const char* dir, const char* rootName, FileInfo& result) const
676 struct stat statBuffer;
677 char possiblePath[strlen(dir)+strlen(rootName)+strlen(format)+8];
678 sprintf(possiblePath, format, dir, rootName);
679 bool found = (stat(possiblePath, &statBuffer) == 0);
680 if ( fTraceDylibSearching )
681 printf("[Logging for XBS]%sfound library: '%s'\n", (found ? " " : " not "), possiblePath);
682 if ( found ) {
683 result.path = strdup(possiblePath);
684 result.fileLen = statBuffer.st_size;
685 result.modTime = statBuffer.st_mtime;
686 return true;
688 return false;
692 Options::FileInfo Options::findLibrary(const char* rootName, bool dylibsOnly)
694 FileInfo result;
695 const int rootNameLen = strlen(rootName);
696 // if rootName ends in .o there is no .a vs .dylib choice
697 if ( (rootNameLen > 3) && (strcmp(&rootName[rootNameLen-2], ".o") == 0) ) {
698 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
699 it != fLibrarySearchPaths.end();
700 it++) {
701 const char* dir = *it;
702 if ( checkForFile("%s/%s", dir, rootName, result) )
703 return result;
706 else {
707 bool lookForDylibs = ( fOutputKind != Options::kDyld);
708 switch ( fLibrarySearchMode ) {
709 case kSearchAllDirsForDylibsThenAllDirsForArchives:
710 // first look in all directories for just for dylibs
711 if ( lookForDylibs ) {
712 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
713 it != fLibrarySearchPaths.end();
714 it++) {
715 const char* dir = *it;
716 if ( checkForFile("%s/lib%s.dylib", dir, rootName, result) )
717 return result;
719 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
720 it != fLibrarySearchPaths.end();
721 it++) {
722 const char* dir = *it;
723 if ( checkForFile("%s/lib%s.so", dir, rootName, result) )
724 return result;
727 // next look in all directories for just for archives
728 if ( !dylibsOnly ) {
729 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
730 it != fLibrarySearchPaths.end();
731 it++) {
732 const char* dir = *it;
733 if ( checkForFile("%s/lib%s.a", dir, rootName, result) )
734 return result;
737 break;
739 case kSearchDylibAndArchiveInEachDir:
740 // look in each directory for just for a dylib then for an archive
741 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
742 it != fLibrarySearchPaths.end();
743 it++) {
744 const char* dir = *it;
745 if ( lookForDylibs && checkForFile("%s/lib%s.dylib", dir, rootName, result) )
746 return result;
747 if ( lookForDylibs && checkForFile("%s/lib%s.so", dir, rootName, result) )
748 return result;
749 if ( !dylibsOnly && checkForFile("%s/lib%s.a", dir, rootName, result) )
750 return result;
752 break;
755 throwf("library not found for -l%s", rootName);
758 Options::FileInfo Options::findFramework(const char* frameworkName)
760 if ( frameworkName == NULL )
761 throw "-framework missing next argument";
762 char temp[strlen(frameworkName)+1];
763 strcpy(temp, frameworkName);
764 const char* name = temp;
765 const char* suffix = NULL;
766 char* comma = strchr(temp, ',');
767 if ( comma != NULL ) {
768 *comma = '\0';
769 suffix = &comma[1];
771 return findFramework(name, suffix);
774 Options::FileInfo Options::findFramework(const char* rootName, const char* suffix)
776 struct stat statBuffer;
777 for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin();
778 it != fFrameworkSearchPaths.end();
779 it++) {
780 // ??? Shouldn't we be using String here and just initializing it?
781 // ??? Use str.c_str () to pull out the string for the stat call.
782 const char* dir = *it;
783 char possiblePath[PATH_MAX];
784 strcpy(possiblePath, dir);
785 strcat(possiblePath, "/");
786 strcat(possiblePath, rootName);
787 strcat(possiblePath, ".framework/");
788 strcat(possiblePath, rootName);
789 if ( suffix != NULL ) {
790 char realPath[PATH_MAX];
791 // no symlink in framework to suffix variants, so follow main symlink
792 if ( realpath(possiblePath, realPath) != NULL ) {
793 strcpy(possiblePath, realPath);
794 strcat(possiblePath, suffix);
797 bool found = (stat(possiblePath, &statBuffer) == 0);
798 if ( fTraceDylibSearching )
799 printf("[Logging for XBS]%sfound framework: '%s'\n",
800 (found ? " " : " not "), possiblePath);
801 if ( found ) {
802 FileInfo result;
803 result.path = strdup(possiblePath);
804 result.fileLen = statBuffer.st_size;
805 result.modTime = statBuffer.st_mtime;
806 return result;
809 // try without suffix
810 if ( suffix != NULL )
811 return findFramework(rootName, NULL);
812 else
813 throwf("framework not found %s", rootName);
816 Options::FileInfo Options::findFile(const char* path) const
818 FileInfo result;
819 struct stat statBuffer;
821 // if absolute path and not a .o file, the use SDK prefix
822 if ( (path[0] == '/') && (strcmp(&path[strlen(path)-2], ".o") != 0) ) {
823 const int pathLen = strlen(path);
824 for (std::vector<const char*>::const_iterator it = fSDKPaths.begin(); it != fSDKPaths.end(); it++) {
825 // ??? Shouldn't we be using String here?
826 const char* sdkPathDir = *it;
827 const int sdkPathDirLen = strlen(sdkPathDir);
828 char possiblePath[sdkPathDirLen+pathLen+4];
829 strcpy(possiblePath, sdkPathDir);
830 if ( possiblePath[sdkPathDirLen-1] == '/' )
831 possiblePath[sdkPathDirLen-1] = '\0';
832 strcat(possiblePath, path);
833 if ( stat(possiblePath, &statBuffer) == 0 ) {
834 result.path = strdup(possiblePath);
835 result.fileLen = statBuffer.st_size;
836 result.modTime = statBuffer.st_mtime;
837 return result;
841 // try raw path
842 if ( stat(path, &statBuffer) == 0 ) {
843 result.path = strdup(path);
844 result.fileLen = statBuffer.st_size;
845 result.modTime = statBuffer.st_mtime;
846 return result;
849 // try @executable_path substitution
850 if ( (strncmp(path, "@executable_path/", 17) == 0) && (fExecutablePath != NULL) ) {
851 char newPath[strlen(fExecutablePath) + strlen(path)];
852 strcpy(newPath, fExecutablePath);
853 char* addPoint = strrchr(newPath,'/');
854 if ( addPoint != NULL )
855 strcpy(&addPoint[1], &path[17]);
856 else
857 strcpy(newPath, &path[17]);
858 if ( stat(newPath, &statBuffer) == 0 ) {
859 result.path = strdup(newPath);
860 result.fileLen = statBuffer.st_size;
861 result.modTime = statBuffer.st_mtime;
862 return result;
866 // not found
867 throwf("file not found: %s", path);
870 Options::FileInfo Options::findFileUsingPaths(const char* path) const
872 FileInfo result;
874 const char* lastSlash = strrchr(path, '/');
875 const char* leafName = (lastSlash == NULL) ? path : &lastSlash[1];
877 // Is this in a framework?
878 // /path/Foo.framework/Foo ==> true (Foo)
879 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
880 // /path/Foo.framework/Resources/Bar ==> false
881 bool isFramework = false;
882 if ( lastSlash != NULL ) {
883 char frameworkDir[strlen(leafName) + 20];
884 strcpy(frameworkDir, "/");
885 strcat(frameworkDir, leafName);
886 strcat(frameworkDir, ".framework/");
887 if ( strstr(path, frameworkDir) != NULL )
888 isFramework = true;
891 // These are abbreviated versions of the routines findFramework and findLibrary above
892 // because we already know the final name of the file that we're looking for and so
893 // don't need to try variations, just paths. We do need to add the additional bits
894 // onto the framework path though.
895 if ( isFramework ) {
896 for (std::vector<const char*>::const_iterator it = fFrameworkSearchPaths.begin();
897 it != fFrameworkSearchPaths.end();
898 it++) {
899 const char* dir = *it;
900 char possiblePath[PATH_MAX];
901 strcpy(possiblePath, dir);
902 strcat(possiblePath, "/");
903 strcat(possiblePath, leafName);
904 strcat(possiblePath, ".framework");
906 //fprintf(stderr,"Finding Framework: %s/%s, leafName=%s\n", possiblePath, leafName, leafName);
907 if ( checkForFile("%s/%s", possiblePath, leafName, result) )
908 return result;
911 else {
912 // if this is a .dylib inside a framework, do not search -L paths
913 // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
914 int leafLen = strlen(leafName);
915 bool embeddedDylib = ( (leafLen > 6)
916 && (strcmp(&leafName[leafLen-6], ".dylib") == 0)
917 && (strstr(path, ".framework/") != NULL) );
918 if ( !embeddedDylib ) {
919 for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
920 it != fLibrarySearchPaths.end();
921 it++) {
922 const char* dir = *it;
923 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
924 if ( checkForFile("%s/%s", dir, leafName, result) )
925 return result;
930 // If we didn't find it fall back to findFile.
931 return findFile(path);
935 void Options::parseSegAddrTable(const char* segAddrPath, const char* installPth)
937 FILE* file = fopen(segAddrPath, "r");
938 if ( file == NULL ) {
939 warning("-seg_addr_table file cannot be read: %s", segAddrPath);
940 return;
943 char path[PATH_MAX];
944 uint64_t firstColumAddress = 0;
945 uint64_t secondColumAddress = 0;
946 bool hasSecondColumn = false;
947 while ( fgets(path, PATH_MAX, file) != NULL ) {
948 path[PATH_MAX-1] = '\0';
949 char* eol = strchr(path, '\n');
950 if ( eol != NULL )
951 *eol = '\0';
952 // ignore lines not starting with 0x number
953 if ( (path[0] == '0') && (path[1] == 'x') ) {
954 char* p;
955 firstColumAddress = strtoull(path, &p, 16);
956 while ( isspace(*p) )
957 ++p;
958 // see if second column is a number
959 if ( (p[0] == '0') && (p[1] == 'x') ) {
960 secondColumAddress = strtoull(p, &p, 16);
961 hasSecondColumn = true;
962 while ( isspace(*p) )
963 ++p;
965 while ( isspace(*p) )
966 ++p;
967 if ( p[0] == '/' ) {
968 // remove any trailing whitespace
969 for(char* end = eol-1; (end > p) && isspace(*end); --end)
970 *end = '\0';
971 // see if this line is for the dylib being linked
972 if ( strcmp(p, installPth) == 0 ) {
973 fBaseAddress = firstColumAddress;
974 if ( hasSecondColumn ) {
975 fBaseWritableAddress = secondColumAddress;
976 fSplitSegs = true;
978 break; // out of while loop
984 fclose(file);
987 void Options::loadFileList(const char* fileOfPaths)
989 FILE* file;
990 const char* comma = strrchr(fileOfPaths, ',');
991 const char* prefix = NULL;
992 if ( comma != NULL ) {
993 // <rdar://problem/5907981> -filelist fails with comma in path
994 file = fopen(fileOfPaths, "r");
995 if ( file == NULL ) {
996 prefix = comma+1;
997 int realFileOfPathsLen = comma-fileOfPaths;
998 char realFileOfPaths[realFileOfPathsLen+1];
999 strncpy(realFileOfPaths,fileOfPaths, realFileOfPathsLen);
1000 realFileOfPaths[realFileOfPathsLen] = '\0';
1001 file = fopen(realFileOfPaths, "r");
1002 if ( file == NULL )
1003 throwf("-filelist file not found: %s\n", realFileOfPaths);
1006 else {
1007 file = fopen(fileOfPaths, "r");
1008 if ( file == NULL )
1009 throwf("-filelist file not found: %s\n", fileOfPaths);
1012 char path[PATH_MAX];
1013 while ( fgets(path, PATH_MAX, file) != NULL ) {
1014 path[PATH_MAX-1] = '\0';
1015 char* eol = strchr(path, '\n');
1016 if ( eol != NULL )
1017 *eol = '\0';
1018 if ( prefix != NULL ) {
1019 char builtPath[strlen(prefix)+strlen(path)+2];
1020 strcpy(builtPath, prefix);
1021 strcat(builtPath, "/");
1022 strcat(builtPath, path);
1023 fInputFiles.push_back(findFile(builtPath));
1025 else {
1026 fInputFiles.push_back(findFile(path));
1029 fclose(file);
1033 void Options::SetWithWildcards::remove(const NameSet& toBeRemoved)
1035 for(NameSet::const_iterator it=toBeRemoved.begin(); it != toBeRemoved.end(); ++it) {
1036 const char* symbolName = *it;
1037 NameSet::iterator pos = fRegular.find(symbolName);
1038 if ( pos != fRegular.end() )
1039 fRegular.erase(pos);
1043 bool Options::SetWithWildcards::hasWildCards(const char* symbol)
1045 // an exported symbol name containing *, ?, or [ requires wildcard matching
1046 return ( strpbrk(symbol, "*?[") != NULL );
1049 void Options::SetWithWildcards::insert(const char* symbol)
1051 if ( hasWildCards(symbol) )
1052 fWildCard.push_back(symbol);
1053 else
1054 fRegular.insert(symbol);
1057 bool Options::SetWithWildcards::contains(const char* symbol) const
1059 // first look at hash table on non-wildcard symbols
1060 if ( fRegular.find(symbol) != fRegular.end() )
1061 return true;
1062 // next walk list of wild card symbols looking for a match
1063 for(std::vector<const char*>::const_iterator it = fWildCard.begin(); it != fWildCard.end(); ++it) {
1064 if ( wildCardMatch(*it, symbol) )
1065 return true;
1067 return false;
1070 bool Options::SetWithWildcards::containsNonWildcard(const char* symbol) const
1072 // look at hash table on non-wildcard symbols
1073 return ( fRegular.find(symbol) != fRegular.end() );
1078 bool Options::SetWithWildcards::inCharRange(const char*& p, unsigned char c) const
1080 ++p; // find end
1081 const char* b = p;
1082 while ( *p != '\0' ) {
1083 if ( *p == ']') {
1084 const char* e = p;
1085 // found beginining [ and ending ]
1086 unsigned char last = '\0';
1087 for ( const char* s = b; s < e; ++s ) {
1088 if ( *s == '-' ) {
1089 unsigned char next = *(++s);
1090 if ( (last <= c) && (c <= next) )
1091 return true;
1092 ++s;
1094 else {
1095 if ( *s == c )
1096 return true;
1097 last = *s;
1100 return false;
1102 ++p;
1104 return false;
1107 bool Options::SetWithWildcards::wildCardMatch(const char* pattern, const char* symbol) const
1109 const char* s = symbol;
1110 for (const char* p = pattern; *p != '\0'; ++p) {
1111 switch ( *p ) {
1112 case '*':
1113 if ( p[1] == '\0' )
1114 return true;
1115 for (const char* t = s; *t != '\0'; ++t) {
1116 if ( wildCardMatch(&p[1], t) )
1117 return true;
1119 return false;
1120 case '?':
1121 if ( *s == '\0' )
1122 return false;
1123 ++s;
1124 break;
1125 case '[':
1126 if ( ! inCharRange(p, *s) )
1127 return false;
1128 ++s;
1129 break;
1130 default:
1131 if ( *s != *p )
1132 return false;
1133 ++s;
1136 return (*s == '\0');
1140 void Options::loadExportFile(const char* fileOfExports, const char* option, SetWithWildcards& set)
1142 if ( fileOfExports == NULL )
1143 throwf("missing file after %s", option);
1144 // read in whole file
1145 int fd = ::open(fileOfExports, O_RDONLY, 0);
1146 if ( fd == -1 )
1147 throwf("can't open %s file: %s", option, fileOfExports);
1148 struct stat stat_buf;
1149 ::fstat(fd, &stat_buf);
1150 char* p = (char*)malloc(stat_buf.st_size);
1151 if ( p == NULL )
1152 throwf("can't process %s file: %s", option, fileOfExports);
1154 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1155 throwf("can't read %s file: %s", option, fileOfExports);
1157 ::close(fd);
1159 // parse into symbols and add to hash_set
1160 char * const end = &p[stat_buf.st_size];
1161 enum { lineStart, inSymbol, inComment } state = lineStart;
1162 char* symbolStart = NULL;
1163 for (char* s = p; s < end; ++s ) {
1164 switch ( state ) {
1165 case lineStart:
1166 if ( *s =='#' ) {
1167 state = inComment;
1169 else if ( !isspace(*s) ) {
1170 state = inSymbol;
1171 symbolStart = s;
1173 break;
1174 case inSymbol:
1175 if ( (*s == '\n') || (*s == '\r') ) {
1176 *s = '\0';
1177 // removing any trailing spaces
1178 char* last = s-1;
1179 while ( isspace(*last) ) {
1180 *last = '\0';
1181 --last;
1183 set.insert(symbolStart);
1184 symbolStart = NULL;
1185 state = lineStart;
1187 break;
1188 case inComment:
1189 if ( (*s == '\n') || (*s == '\r') )
1190 state = lineStart;
1191 break;
1194 if ( state == inSymbol ) {
1195 warning("missing line-end at end of file \"%s\"", fileOfExports);
1196 int len = end-symbolStart+1;
1197 char* temp = new char[len];
1198 strlcpy(temp, symbolStart, len);
1200 // remove any trailing spaces
1201 char* last = &temp[len-2];
1202 while ( isspace(*last) ) {
1203 *last = '\0';
1204 --last;
1206 set.insert(temp);
1209 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
1212 void Options::parseAliasFile(const char* fileOfAliases)
1214 // read in whole file
1215 int fd = ::open(fileOfAliases, O_RDONLY, 0);
1216 if ( fd == -1 )
1217 throwf("can't open alias file: %s", fileOfAliases);
1218 struct stat stat_buf;
1219 ::fstat(fd, &stat_buf);
1220 char* p = (char*)malloc(stat_buf.st_size+1);
1221 if ( p == NULL )
1222 throwf("can't process alias file: %s", fileOfAliases);
1224 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1225 throwf("can't read alias file: %s", fileOfAliases);
1226 p[stat_buf.st_size] = '\n';
1227 ::close(fd);
1229 // parse into symbols and add to fAliases
1230 AliasPair pair;
1231 char * const end = &p[stat_buf.st_size+1];
1232 enum { lineStart, inRealName, inBetween, inAliasName, inComment } state = lineStart;
1233 int lineNumber = 1;
1234 for (char* s = p; s < end; ++s ) {
1235 switch ( state ) {
1236 case lineStart:
1237 if ( *s =='#' ) {
1238 state = inComment;
1240 else if ( !isspace(*s) ) {
1241 state = inRealName;
1242 pair.realName = s;
1244 break;
1245 case inRealName:
1246 if ( *s == '\n' ) {
1247 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber, fileOfAliases);
1248 ++lineNumber;
1249 state = lineStart;
1251 else if ( isspace(*s) ) {
1252 *s = '\0';
1253 state = inBetween;
1255 break;
1256 case inBetween:
1257 if ( *s == '\n' ) {
1258 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber, fileOfAliases);
1259 ++lineNumber;
1260 state = lineStart;
1262 else if ( ! isspace(*s) ) {
1263 state = inAliasName;
1264 pair.alias = s;
1266 break;
1267 case inAliasName:
1268 if ( *s =='#' ) {
1269 *s = '\0';
1270 // removing any trailing spaces
1271 char* last = s-1;
1272 while ( isspace(*last) ) {
1273 *last = '\0';
1274 --last;
1276 fAliases.push_back(pair);
1277 state = inComment;
1279 else if ( *s == '\n' ) {
1280 *s = '\0';
1281 // removing any trailing spaces
1282 char* last = s-1;
1283 while ( isspace(*last) ) {
1284 *last = '\0';
1285 --last;
1287 fAliases.push_back(pair);
1288 state = lineStart;
1290 break;
1291 case inComment:
1292 if ( *s == '\n' )
1293 state = lineStart;
1294 break;
1298 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
1303 void Options::setUndefinedTreatment(const char* treatment)
1305 if ( treatment == NULL )
1306 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
1308 if ( strcmp(treatment, "warning") == 0 )
1309 fUndefinedTreatment = kUndefinedWarning;
1310 else if ( strcmp(treatment, "error") == 0 )
1311 fUndefinedTreatment = kUndefinedError;
1312 else if ( strcmp(treatment, "suppress") == 0 )
1313 fUndefinedTreatment = kUndefinedSuppress;
1314 else if ( strcmp(treatment, "dynamic_lookup") == 0 )
1315 fUndefinedTreatment = kUndefinedDynamicLookup;
1316 else
1317 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1320 Options::Treatment Options::parseTreatment(const char* treatment)
1322 if ( treatment == NULL )
1323 return kNULL;
1325 if ( strcmp(treatment, "warning") == 0 )
1326 return kWarning;
1327 else if ( strcmp(treatment, "error") == 0 )
1328 return kError;
1329 else if ( strcmp(treatment, "suppress") == 0 )
1330 return kSuppress;
1331 else
1332 return kInvalid;
1335 void Options::setMacOSXVersionMin(const char* version)
1337 if ( version == NULL )
1338 throw "-macosx_version_min argument missing";
1340 if ( (strncmp(version, "10.", 3) == 0) && isdigit(version[3]) ) {
1341 unsigned int minorVersion = version[3] - '0';
1342 fMacVersionMin = (ld::MacVersionMin)(0x000A0000 | (minorVersion << 8));
1344 else {
1345 warning("unknown option to -macosx_version_min, not 10.x");
1349 void Options::setIPhoneVersionMin(const char* version)
1351 if ( version == NULL )
1352 throw "-ios_version_min argument missing";
1353 if ( ! isdigit(version[0]) )
1354 throw "-ios_version_min argument is not a number";
1355 if ( version[1] != '.' )
1356 throw "-ios_version_min argument is missing period as second character";
1357 if ( ! isdigit(version[2]) )
1358 throw "-ios_version_min argument is not a number";
1360 unsigned int majorVersion = version[0] - '0';
1361 unsigned int minorVersion = version[2] - '0';
1362 fIPhoneVersionMin = (ld::IPhoneVersionMin)((majorVersion << 16) | (minorVersion << 8));
1365 bool Options::minOS(ld::MacVersionMin requiredMacMin, ld::IPhoneVersionMin requirediPhoneOSMin)
1367 if ( fMacVersionMin != ld::macVersionUnset ) {
1368 return ( fMacVersionMin >= requiredMacMin );
1370 else {
1371 return ( fIPhoneVersionMin >= requirediPhoneOSMin);
1376 void Options::setWeakReferenceMismatchTreatment(const char* treatment)
1378 if ( treatment == NULL )
1379 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1381 if ( strcmp(treatment, "error") == 0 )
1382 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchError;
1383 else if ( strcmp(treatment, "weak") == 0 )
1384 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchWeak;
1385 else if ( strcmp(treatment, "non-weak") == 0 )
1386 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchNonWeak;
1387 else
1388 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1391 Options::CommonsMode Options::parseCommonsTreatment(const char* mode)
1393 if ( mode == NULL )
1394 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1396 if ( strcmp(mode, "ignore_dylibs") == 0 )
1397 return kCommonsIgnoreDylibs;
1398 else if ( strcmp(mode, "use_dylibs") == 0 )
1399 return kCommonsOverriddenByDylibs;
1400 else if ( strcmp(mode, "error") == 0 )
1401 return kCommonsConflictsDylibsError;
1402 else
1403 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1406 void Options::addDylibOverride(const char* paths)
1408 if ( paths == NULL )
1409 throw "-dylib_file must followed by two colon separated paths";
1410 const char* colon = strchr(paths, ':');
1411 if ( colon == NULL )
1412 throw "-dylib_file must followed by two colon separated paths";
1413 int len = colon-paths;
1414 char* target = new char[len+2];
1415 strncpy(target, paths, len);
1416 target[len] = '\0';
1417 DylibOverride entry;
1418 entry.installName = target;
1419 entry.useInstead = &colon[1];
1420 fDylibOverrides.push_back(entry);
1423 uint64_t Options::parseAddress(const char* addr)
1425 char* endptr;
1426 uint64_t result = strtoull(addr, &endptr, 16);
1427 return result;
1430 uint32_t Options::parseProtection(const char* prot)
1432 uint32_t result = 0;
1433 for(const char* p = prot; *p != '\0'; ++p) {
1434 switch(tolower(*p)) {
1435 case 'r':
1436 result |= VM_PROT_READ;
1437 break;
1438 case 'w':
1439 result |= VM_PROT_WRITE;
1440 break;
1441 case 'x':
1442 result |= VM_PROT_EXECUTE;
1443 break;
1444 case '-':
1445 break;
1446 default:
1447 throwf("unknown -segprot lettter in %s", prot);
1450 return result;
1456 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1459 uint32_t Options::parseVersionNumber(const char* versionString)
1461 unsigned long x = 0;
1462 unsigned long y = 0;
1463 unsigned long z = 0;
1464 char* end;
1465 x = strtoul(versionString, &end, 10);
1466 if ( *end == '.' ) {
1467 y = strtoul(&end[1], &end, 10);
1468 if ( *end == '.' ) {
1469 z = strtoul(&end[1], &end, 10);
1472 if ( (*end != '\0') || (x > 0xffff) || (y > 0xff) || (z > 0xff) )
1473 throwf("malformed version number: %s", versionString);
1475 return (x << 16) | ( y << 8 ) | z;
1478 static const char* cstringSymbolName(const char* orderFileString)
1480 char* result;
1481 asprintf(&result, "cstring=%s", orderFileString);
1482 // convert escaped characters
1483 char* d = result;
1484 for(const char* s=result; *s != '\0'; ++s, ++d) {
1485 if ( *s == '\\' ) {
1486 ++s;
1487 switch ( *s ) {
1488 case 'n':
1489 *d = '\n';
1490 break;
1491 case 't':
1492 *d = '\t';
1493 break;
1494 case 'v':
1495 *d = '\v';
1496 break;
1497 case 'b':
1498 *d = '\b';
1499 break;
1500 case 'r':
1501 *d = '\r';
1502 break;
1503 case 'f':
1504 *d = '\f';
1505 break;
1506 case 'a':
1507 *d = '\a';
1508 break;
1509 case '\\':
1510 *d = '\\';
1511 break;
1512 case '?':
1513 *d = '\?';
1514 break;
1515 case '\'':
1516 *d = '\r';
1517 break;
1518 case '\"':
1519 *d = '\"';
1520 break;
1521 case 'x':
1522 // hexadecimal value of char
1524 ++s;
1525 char value = 0;
1526 while ( isxdigit(*s) ) {
1527 value *= 16;
1528 if ( isdigit(*s) )
1529 value += (*s-'0');
1530 else
1531 value += ((toupper(*s)-'A') + 10);
1532 ++s;
1534 *d = value;
1536 break;
1537 default:
1538 if ( isdigit(*s) ) {
1539 // octal value of char
1540 char value = 0;
1541 while ( isdigit(*s) ) {
1542 value = (value << 3) + (*s-'0');
1543 ++s;
1545 *d = value;
1549 else {
1550 *d = *s;
1553 *d = '\0';
1554 return result;
1557 void Options::parseOrderFile(const char* path, bool cstring)
1559 // order files override auto-ordering
1560 fAutoOrderInitializers = false;
1562 // read in whole file
1563 int fd = ::open(path, O_RDONLY, 0);
1564 if ( fd == -1 )
1565 throwf("can't open order file: %s", path);
1566 struct stat stat_buf;
1567 ::fstat(fd, &stat_buf);
1568 char* p = (char*)malloc(stat_buf.st_size+1);
1569 if ( p == NULL )
1570 throwf("can't process order file: %s", path);
1571 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1572 throwf("can't read order file: %s", path);
1573 ::close(fd);
1574 p[stat_buf.st_size] = '\n';
1576 // parse into vector of pairs
1577 char * const end = &p[stat_buf.st_size+1];
1578 enum { lineStart, inSymbol, inComment } state = lineStart;
1579 char* symbolStart = NULL;
1580 for (char* s = p; s < end; ++s ) {
1581 switch ( state ) {
1582 case lineStart:
1583 if ( *s =='#' ) {
1584 state = inComment;
1586 else if ( !isspace(*s) || cstring ) {
1587 state = inSymbol;
1588 symbolStart = s;
1590 break;
1591 case inSymbol:
1592 if ( (*s == '\n') || (!cstring && (*s == '#')) ) {
1593 bool wasComment = (*s == '#');
1594 *s = '\0';
1595 // removing any trailing spaces
1596 char* last = s-1;
1597 while ( isspace(*last) ) {
1598 *last = '\0';
1599 --last;
1601 if ( strncmp(symbolStart, "ppc:", 4) == 0 ) {
1602 if ( fArchitecture == CPU_TYPE_POWERPC )
1603 symbolStart = &symbolStart[4];
1604 else
1605 symbolStart = NULL;
1607 // if there is an architecture prefix, only use this symbol it if matches current arch
1608 else if ( strncmp(symbolStart, "ppc64:", 6) == 0 ) {
1609 if ( fArchitecture == CPU_TYPE_POWERPC64 )
1610 symbolStart = &symbolStart[6];
1611 else
1612 symbolStart = NULL;
1614 else if ( strncmp(symbolStart, "i386:", 5) == 0 ) {
1615 if ( fArchitecture == CPU_TYPE_I386 )
1616 symbolStart = &symbolStart[5];
1617 else
1618 symbolStart = NULL;
1620 else if ( strncmp(symbolStart, "x86_64:", 7) == 0 ) {
1621 if ( fArchitecture == CPU_TYPE_X86_64 )
1622 symbolStart = &symbolStart[7];
1623 else
1624 symbolStart = NULL;
1626 else if ( strncmp(symbolStart, "arm:", 4) == 0 ) {
1627 if ( fArchitecture == CPU_TYPE_ARM )
1628 symbolStart = &symbolStart[4];
1629 else
1630 symbolStart = NULL;
1632 if ( symbolStart != NULL ) {
1633 char* objFileName = NULL;
1634 char* colon = strstr(symbolStart, ".o:");
1635 if ( colon != NULL ) {
1636 colon[2] = '\0';
1637 objFileName = symbolStart;
1638 symbolStart = &colon[3];
1640 // trim leading spaces
1641 while ( isspace(*symbolStart) )
1642 ++symbolStart;
1643 Options::OrderedSymbol pair;
1644 if ( cstring )
1645 pair.symbolName = cstringSymbolName(symbolStart);
1646 else
1647 pair.symbolName = symbolStart;
1648 pair.objectFileName = objFileName;
1649 fOrderedSymbols.push_back(pair);
1651 symbolStart = NULL;
1652 if ( wasComment )
1653 state = inComment;
1654 else
1655 state = lineStart;
1657 break;
1658 case inComment:
1659 if ( *s == '\n' )
1660 state = lineStart;
1661 break;
1664 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1667 void Options::parseSectionOrderFile(const char* segment, const char* section, const char* path)
1669 if ( (strcmp(section, "__cstring") == 0) && (strcmp(segment, "__TEXT") == 0) ) {
1670 parseOrderFile(path, true);
1672 else if ( (strncmp(section, "__literal",9) == 0) && (strcmp(segment, "__TEXT") == 0) ) {
1673 warning("sorting of __literal[4,8,16] sections not supported");
1675 else {
1676 // ignore section information and append all symbol names to global order file
1677 parseOrderFile(path, false);
1681 void Options::addSection(const char* segment, const char* section, const char* path)
1683 if ( strlen(segment) > 16 )
1684 throw "-seccreate segment name max 16 chars";
1685 if ( strlen(section) > 16 ) {
1686 char* tmp = strdup(section);
1687 tmp[16] = '\0';
1688 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section, tmp);
1689 section = tmp;
1692 // read in whole file
1693 int fd = ::open(path, O_RDONLY, 0);
1694 if ( fd == -1 )
1695 throwf("can't open -sectcreate file: %s", path);
1696 struct stat stat_buf;
1697 ::fstat(fd, &stat_buf);
1698 char* p = (char*)malloc(stat_buf.st_size);
1699 if ( p == NULL )
1700 throwf("can't process -sectcreate file: %s", path);
1701 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1702 throwf("can't read -sectcreate file: %s", path);
1703 ::close(fd);
1705 // record section to create
1706 ExtraSection info = { segment, section, path, (uint8_t*)p, stat_buf.st_size };
1707 fExtraSections.push_back(info);
1710 void Options::addSectionAlignment(const char* segment, const char* section, const char* alignmentStr)
1712 if ( strlen(segment) > 16 )
1713 throw "-sectalign segment name max 16 chars";
1714 if ( strlen(section) > 16 )
1715 throw "-sectalign section name max 16 chars";
1717 // argument to -sectalign is a hexadecimal number
1718 char* endptr;
1719 unsigned long value = strtoul(alignmentStr, &endptr, 16);
1720 if ( *endptr != '\0')
1721 throw "argument for -sectalign is not a hexadecimal number";
1722 if ( value > 0x8000 )
1723 throw "argument for -sectalign must be less than or equal to 0x8000";
1724 if ( value == 0 ) {
1725 warning("zero is not a valid -sectalign");
1726 value = 1;
1729 // alignment is power of 2 (e.g. page alignment = 12)
1730 uint8_t alignment = (uint8_t)__builtin_ctz(value);
1731 if ( (unsigned long)(1 << alignment) != value ) {
1732 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
1733 segment, section, 1 << alignment);
1736 SectionAlignment info = { segment, section, alignment };
1737 fSectionAlignments.push_back(info);
1740 void Options::addLibrary(const FileInfo& info)
1742 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
1743 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
1744 if ( strcmp(info.path, fit->path) == 0 ) {
1745 // if dylib is specified again but weak, record that it should be weak
1746 if ( info.options.fWeakImport )
1747 fit->options.fWeakImport = true;
1748 return;
1751 // add to list
1752 fInputFiles.push_back(info);
1755 void Options::warnObsolete(const char* arg)
1757 warning("option %s is obsolete and being ignored", arg);
1764 // Process all command line arguments.
1766 // The only error checking done here is that each option is valid and if it has arguments
1767 // that they too are valid.
1769 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
1770 // whichever was last on the command line is used.
1772 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
1774 void Options::parse(int argc, const char* argv[])
1776 // pass one builds search list from -L and -F options
1777 this->buildSearchPaths(argc, argv);
1779 // reduce re-allocations
1780 fInputFiles.reserve(32);
1782 // pass two parse all other options
1783 for(int i=1; i < argc; ++i) {
1784 const char* arg = argv[i];
1786 if ( arg[0] == '-' ) {
1788 // Since we don't care about the files passed, just the option names, we do this here.
1789 if (fPrintOptions)
1790 fprintf (stderr, "[Logging ld64 options]\t%s\n", arg);
1792 if ( (arg[1] == 'L') || (arg[1] == 'F') ) {
1793 if (arg[2] == '\0')
1794 ++i;
1795 // previously handled by buildSearchPaths()
1797 // The one gnu style option we have to keep compatibility
1798 // with gcc. Might as well have the single hyphen one as well.
1799 else if ( (strcmp(arg, "--help") == 0)
1800 || (strcmp(arg, "-help") == 0)) {
1801 fprintf (stdout, "ld64: For information on command line options please use 'man ld'.\n");
1802 exit (0);
1804 else if ( strcmp(arg, "-arch") == 0 ) {
1805 parseArch(argv[++i]);
1807 else if ( strcmp(arg, "-dynamic") == 0 ) {
1808 // default
1810 else if ( strcmp(arg, "-static") == 0 ) {
1811 fForStatic = true;
1812 if ( (fOutputKind != kObjectFile) && (fOutputKind != kKextBundle) ) {
1813 fOutputKind = kStaticExecutable;
1816 else if ( strcmp(arg, "-dylib") == 0 ) {
1817 fOutputKind = kDynamicLibrary;
1819 else if ( strcmp(arg, "-bundle") == 0 ) {
1820 fOutputKind = kDynamicBundle;
1822 else if ( strcmp(arg, "-dylinker") == 0 ) {
1823 fOutputKind = kDyld;
1825 else if ( strcmp(arg, "-execute") == 0 ) {
1826 if ( fOutputKind != kStaticExecutable )
1827 fOutputKind = kDynamicExecutable;
1829 else if ( strcmp(arg, "-preload") == 0 ) {
1830 fOutputKind = kPreload;
1832 else if ( strcmp(arg, "-r") == 0 ) {
1833 fOutputKind = kObjectFile;
1835 else if ( strcmp(arg, "-kext") == 0 ) {
1836 fOutputKind = kKextBundle;
1838 else if ( strcmp(arg, "-o") == 0 ) {
1839 fOutputFile = argv[++i];
1841 else if ( strncmp(arg, "-lazy-l", 7) == 0 ) {
1842 FileInfo info = findLibrary(&arg[7], true);
1843 info.options.fLazyLoad = true;
1844 addLibrary(info);
1845 fUsingLazyDylibLinking = true;
1847 else if ( (arg[1] == 'l') && (strncmp(arg,"-lazy_",6) !=0) ) {
1848 addLibrary(findLibrary(&arg[2]));
1850 // This causes a dylib to be weakly bound at
1851 // link time. This corresponds to weak_import.
1852 else if ( strncmp(arg, "-weak-l", 7) == 0 ) {
1853 FileInfo info = findLibrary(&arg[7]);
1854 info.options.fWeakImport = true;
1855 addLibrary(info);
1857 // Avoid lazy binding.
1858 else if ( strcmp(arg, "-bind_at_load") == 0 ) {
1859 fBindAtLoad = true;
1861 else if ( strcmp(arg, "-twolevel_namespace") == 0 ) {
1862 fNameSpace = kTwoLevelNameSpace;
1864 else if ( strcmp(arg, "-flat_namespace") == 0 ) {
1865 fNameSpace = kFlatNameSpace;
1867 // Also sets a bit to ensure dyld causes everything
1868 // in the namespace to be flat.
1869 // ??? Deprecate
1870 else if ( strcmp(arg, "-force_flat_namespace") == 0 ) {
1871 fNameSpace = kForceFlatNameSpace;
1873 // Similar to --whole-archive.
1874 else if ( strcmp(arg, "-all_load") == 0 ) {
1875 fFullyLoadArchives = true;
1877 else if ( strcmp(arg, "-noall_load") == 0) {
1878 warnObsolete(arg);
1880 // Similar to -all_load
1881 else if ( strcmp(arg, "-ObjC") == 0 ) {
1882 fLoadAllObjcObjectsFromArchives = true;
1884 // Similar to -all_load, but for the following archive only.
1885 else if ( strcmp(arg, "-force_load") == 0 ) {
1886 FileInfo info = findFile(argv[++i]);
1887 info.options.fForceLoad = true;
1888 addLibrary(info);
1890 // Library versioning.
1891 else if ( (strcmp(arg, "-dylib_compatibility_version") == 0)
1892 || (strcmp(arg, "-compatibility_version") == 0)) {
1893 const char* vers = argv[++i];
1894 if ( vers == NULL )
1895 throw "-dylib_compatibility_version missing <version>";
1896 fDylibCompatVersion = parseVersionNumber(vers);
1898 else if ( (strcmp(arg, "-dylib_current_version") == 0)
1899 || (strcmp(arg, "-current_version") == 0)) {
1900 const char* vers = argv[++i];
1901 if ( vers == NULL )
1902 throw "-dylib_current_version missing <version>";
1903 fDylibCurrentVersion = parseVersionNumber(vers);
1905 else if ( strcmp(arg, "-sectorder") == 0 ) {
1906 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
1907 throw "-sectorder missing <segment> <section> <file-path>";
1908 parseSectionOrderFile(argv[i+1], argv[i+2], argv[i+3]);
1909 i += 3;
1911 else if ( strcmp(arg, "-order_file") == 0 ) {
1912 parseOrderFile(argv[++i], false);
1914 else if ( strcmp(arg, "-order_file_statistics") == 0 ) {
1915 fPrintOrderFileStatistics = true;
1917 // ??? Deprecate segcreate.
1918 // -sectcreate puts whole files into a section in the output.
1919 else if ( (strcmp(arg, "-sectcreate") == 0) || (strcmp(arg, "-segcreate") == 0) ) {
1920 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
1921 throw "-sectcreate missing <segment> <section> <file-path>";
1922 addSection(argv[i+1], argv[i+2], argv[i+3]);
1923 i += 3;
1925 // Since we have a full path in binary/library names we need to be able to override it.
1926 else if ( (strcmp(arg, "-dylib_install_name") == 0)
1927 || (strcmp(arg, "-dylinker_install_name") == 0)
1928 || (strcmp(arg, "-install_name") == 0)) {
1929 fDylibInstallName = argv[++i];
1930 if ( fDylibInstallName == NULL )
1931 throw "-install_name missing <path>";
1933 // Sets the base address of the output.
1934 else if ( (strcmp(arg, "-seg1addr") == 0) || (strcmp(arg, "-image_base") == 0) ) {
1935 const char* address = argv[++i];
1936 if ( address == NULL )
1937 throwf("%s missing <address>", arg);
1938 fBaseAddress = parseAddress(address);
1939 uint64_t temp = ((fBaseAddress+fSegmentAlignment-1) & (-fSegmentAlignment));
1940 if ( fBaseAddress != temp ) {
1941 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment);
1942 fBaseAddress = temp;
1945 else if ( strcmp(arg, "-e") == 0 ) {
1946 fEntryName = argv[++i];
1948 // Same as -@ from the FSF linker.
1949 else if ( strcmp(arg, "-filelist") == 0 ) {
1950 const char* path = argv[++i];
1951 if ( (path == NULL) || (path[0] == '-') )
1952 throw "-filelist missing <path>";
1953 loadFileList(path);
1955 else if ( strcmp(arg, "-keep_private_externs") == 0 ) {
1956 fKeepPrivateExterns = true;
1958 else if ( strcmp(arg, "-final_output") == 0 ) {
1959 fFinalName = argv[++i];
1961 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
1962 // just ensures that this happens for cross object file boundaries.
1963 else if ( (strcmp(arg, "-interposable") == 0) || (strcmp(arg, "-multi_module") == 0)) {
1964 switch ( fInterposeMode ) {
1965 case kInterposeNone:
1966 case kInterposeAllExternal:
1967 fInterposeMode = kInterposeAllExternal;
1968 break;
1969 case kInterposeSome:
1970 // do nothing, -interposable_list overrides -interposable"
1971 break;
1974 else if ( strcmp(arg, "-interposable_list") == 0 ) {
1975 fInterposeMode = kInterposeSome;
1976 loadExportFile(argv[++i], "-interposable_list", fInterposeList);
1978 // Default for -interposable/-multi_module/-single_module.
1979 else if ( strcmp(arg, "-single_module") == 0 ) {
1980 fInterposeMode = kInterposeNone;
1982 else if ( strcmp(arg, "-exported_symbols_list") == 0 ) {
1983 if ( fExportMode == kDontExportSome )
1984 throw "can't use -exported_symbols_list and -unexported_symbols_list";
1985 fExportMode = kExportSome;
1986 loadExportFile(argv[++i], "-exported_symbols_list", fExportSymbols);
1988 else if ( strcmp(arg, "-unexported_symbols_list") == 0 ) {
1989 if ( fExportMode == kExportSome )
1990 throw "can't use -unexported_symbols_list and -exported_symbols_list";
1991 fExportMode = kDontExportSome;
1992 loadExportFile(argv[++i], "-unexported_symbols_list", fDontExportSymbols);
1994 else if ( strcmp(arg, "-exported_symbol") == 0 ) {
1995 if ( fExportMode == kDontExportSome )
1996 throw "can't use -exported_symbol and -unexported_symbols";
1997 fExportMode = kExportSome;
1998 fExportSymbols.insert(argv[++i]);
2000 else if ( strcmp(arg, "-unexported_symbol") == 0 ) {
2001 if ( fExportMode == kExportSome )
2002 throw "can't use -unexported_symbol and -exported_symbol";
2003 fExportMode = kDontExportSome;
2004 fDontExportSymbols.insert(argv[++i]);
2006 else if ( strcmp(arg, "-non_global_symbols_no_strip_list") == 0 ) {
2007 if ( fLocalSymbolHandling == kLocalSymbolsSelectiveExclude )
2008 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2009 fLocalSymbolHandling = kLocalSymbolsSelectiveInclude;
2010 loadExportFile(argv[++i], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded);
2012 else if ( strcmp(arg, "-non_global_symbols_strip_list") == 0 ) {
2013 if ( fLocalSymbolHandling == kLocalSymbolsSelectiveInclude )
2014 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2015 fLocalSymbolHandling = kLocalSymbolsSelectiveExclude;
2016 loadExportFile(argv[++i], "-non_global_symbols_strip_list", fLocalSymbolsExcluded);
2018 // ??? Deprecate
2019 else if ( strcmp(arg, "-no_arch_warnings") == 0 ) {
2020 fIgnoreOtherArchFiles = true;
2022 else if ( strcmp(arg, "-force_cpusubtype_ALL") == 0 ) {
2023 fForceSubtypeAll = true;
2025 // Similar to -weak-l but uses the absolute path name to the library.
2026 else if ( strcmp(arg, "-weak_library") == 0 ) {
2027 FileInfo info = findFile(argv[++i]);
2028 info.options.fWeakImport = true;
2029 addLibrary(info);
2031 else if ( strcmp(arg, "-lazy_library") == 0 ) {
2032 FileInfo info = findFile(argv[++i]);
2033 info.options.fLazyLoad = true;
2034 addLibrary(info);
2035 fUsingLazyDylibLinking = true;
2037 else if ( strcmp(arg, "-framework") == 0 ) {
2038 addLibrary(findFramework(argv[++i]));
2040 else if ( strcmp(arg, "-weak_framework") == 0 ) {
2041 FileInfo info = findFramework(argv[++i]);
2042 info.options.fWeakImport = true;
2043 addLibrary(info);
2045 else if ( strcmp(arg, "-lazy_framework") == 0 ) {
2046 FileInfo info = findFramework(argv[++i]);
2047 info.options.fLazyLoad = true;
2048 addLibrary(info);
2049 fUsingLazyDylibLinking = true;
2051 else if ( strcmp(arg, "-search_paths_first") == 0 ) {
2052 // previously handled by buildSearchPaths()
2054 else if ( strcmp(arg, "-search_dylibs_first") == 0 ) {
2055 // previously handled by buildSearchPaths()
2057 else if ( strcmp(arg, "-undefined") == 0 ) {
2058 setUndefinedTreatment(argv[++i]);
2060 // Debugging output flag.
2061 else if ( strcmp(arg, "-arch_multiple") == 0 ) {
2062 fMessagesPrefixedWithArchitecture = true;
2064 // Specify what to do with relocations in read only
2065 // sections like .text. Could be errors, warnings,
2066 // or suppressed. Currently we do nothing with the
2067 // flag.
2068 else if ( strcmp(arg, "-read_only_relocs") == 0 ) {
2069 switch ( parseTreatment(argv[++i]) ) {
2070 case kNULL:
2071 case kInvalid:
2072 throw "-read_only_relocs missing [ warning | error | suppress ]";
2073 case kWarning:
2074 fWarnTextRelocs = true;
2075 fAllowTextRelocs = true;
2076 break;
2077 case kSuppress:
2078 fWarnTextRelocs = false;
2079 fAllowTextRelocs = true;
2080 break;
2081 case kError:
2082 fWarnTextRelocs = false;
2083 fAllowTextRelocs = false;
2084 break;
2087 else if ( strcmp(arg, "-sect_diff_relocs") == 0 ) {
2088 warnObsolete(arg);
2089 ++i;
2091 // Warn, error or make strong a mismatch between weak
2092 // and non-weak references.
2093 else if ( strcmp(arg, "-weak_reference_mismatches") == 0 ) {
2094 setWeakReferenceMismatchTreatment(argv[++i]);
2096 // For a deployment target of 10.3 and earlier ld64 will
2097 // prebind an executable with 0s in all addresses that
2098 // are prebound. This can then be fixed up by update_prebinding
2099 // later. Prebinding is less useful on 10.4 and greater.
2100 else if ( strcmp(arg, "-prebind") == 0 ) {
2101 fPrebind = true;
2103 else if ( strcmp(arg, "-noprebind") == 0 ) {
2104 warnObsolete(arg);
2105 fPrebind = false;
2107 else if ( strcmp(arg, "-prebind_allow_overlap") == 0 ) {
2108 warnObsolete(arg);
2110 else if ( strcmp(arg, "-prebind_all_twolevel_modules") == 0 ) {
2111 warnObsolete(arg);
2113 else if ( strcmp(arg, "-noprebind_all_twolevel_modules") == 0 ) {
2114 warnObsolete(arg);
2116 else if ( strcmp(arg, "-nofixprebinding") == 0 ) {
2117 warnObsolete(arg);
2119 // This should probably be deprecated when we respect -L and -F
2120 // when searching for libraries.
2121 else if ( strcmp(arg, "-dylib_file") == 0 ) {
2122 addDylibOverride(argv[++i]);
2124 // What to expand @executable_path to if found in dependent dylibs
2125 else if ( strcmp(arg, "-executable_path") == 0 ) {
2126 fExecutablePath = argv[++i];
2127 if ( (fExecutablePath == NULL) || (fExecutablePath[0] == '-') )
2128 throw "-executable_path missing <path>";
2129 // if a directory was passed, add / to end
2130 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2131 struct stat statBuffer;
2132 if ( stat(fExecutablePath, &statBuffer) == 0 ) {
2133 if ( (statBuffer.st_mode & S_IFMT) == S_IFDIR ) {
2134 char* pathWithSlash = new char[strlen(fExecutablePath)+2];
2135 strcpy(pathWithSlash, fExecutablePath);
2136 strcat(pathWithSlash, "/");
2137 fExecutablePath = pathWithSlash;
2141 // Aligns all segments to the power of 2 boundary specified.
2142 else if ( strcmp(arg, "-segalign") == 0 ) {
2143 const char* size = argv[++i];
2144 if ( size == NULL )
2145 throw "-segalign missing <size>";
2146 fSegmentAlignment = parseAddress(size);
2147 uint8_t alignment = (uint8_t)__builtin_ctz(fSegmentAlignment);
2148 uint32_t p2aligned = (1 << alignment);
2149 if ( p2aligned != fSegmentAlignment ) {
2150 warning("alignment for -segalign %s is not a power of two, using 0x%X", size, p2aligned);
2151 fSegmentAlignment = p2aligned;
2154 // Puts a specified segment at a particular address that must
2155 // be a multiple of the segment alignment.
2156 else if ( strcmp(arg, "-segaddr") == 0 ) {
2157 SegmentStart seg;
2158 seg.name = argv[++i];
2159 if ( (seg.name == NULL) || (argv[i+1] == NULL) )
2160 throw "-segaddr missing segName Adddress";
2161 seg.address = parseAddress(argv[++i]);
2162 uint64_t temp = seg.address & (-4096); // page align
2163 if ( (seg.address != temp) )
2164 warning("-segaddr %s not page aligned, rounding down", seg.name);
2165 fCustomSegmentAddresses.push_back(seg);
2167 // ??? Deprecate when we deprecate split-seg.
2168 else if ( strcmp(arg, "-segs_read_only_addr") == 0 ) {
2169 fBaseAddress = parseAddress(argv[++i]);
2171 // ??? Deprecate when we deprecate split-seg.
2172 else if ( strcmp(arg, "-segs_read_write_addr") == 0 ) {
2173 fBaseWritableAddress = parseAddress(argv[++i]);
2174 fSplitSegs = true;
2176 // ??? Deprecate when we get rid of basing at build time.
2177 else if ( strcmp(arg, "-seg_addr_table") == 0 ) {
2178 const char* name = argv[++i];
2179 if ( name == NULL )
2180 throw "-seg_addr_table missing argument";
2181 fSegAddrTablePath = name;
2183 else if ( strcmp(arg, "-seg_addr_table_filename") == 0 ) {
2184 warnObsolete(arg);
2185 ++i;
2187 else if ( strcmp(arg, "-segprot") == 0 ) {
2188 SegmentProtect seg;
2189 seg.name = argv[++i];
2190 if ( (seg.name == NULL) || (argv[i+1] == NULL) || (argv[i+2] == NULL) )
2191 throw "-segprot missing segName max-prot init-prot";
2192 seg.max = parseProtection(argv[++i]);
2193 seg.init = parseProtection(argv[++i]);
2194 fCustomSegmentProtections.push_back(seg);
2196 else if ( strcmp(arg, "-pagezero_size") == 0 ) {
2197 const char* size = argv[++i];
2198 if ( size == NULL )
2199 throw "-pagezero_size missing <size>";
2200 fZeroPageSize = parseAddress(size);
2201 uint64_t temp = fZeroPageSize & (-4096); // page align
2202 if ( (fZeroPageSize != temp) )
2203 warning("-pagezero_size not page aligned, rounding down");
2204 fZeroPageSize = temp;
2206 else if ( strcmp(arg, "-stack_addr") == 0 ) {
2207 const char* address = argv[++i];
2208 if ( address == NULL )
2209 throw "-stack_addr missing <address>";
2210 fStackAddr = parseAddress(address);
2212 else if ( strcmp(arg, "-stack_size") == 0 ) {
2213 const char* size = argv[++i];
2214 if ( size == NULL )
2215 throw "-stack_size missing <address>";
2216 fStackSize = parseAddress(size);
2217 uint64_t temp = fStackSize & (-4096); // page align
2218 if ( (fStackSize != temp) )
2219 warning("-stack_size not page aligned, rounding down");
2221 else if ( strcmp(arg, "-allow_stack_execute") == 0 ) {
2222 fExecutableStack = true;
2224 else if ( strcmp(arg, "-allow_heap_execute") == 0 ) {
2225 fDisableNonExecutableHeap = true;
2227 else if ( strcmp(arg, "-sectalign") == 0 ) {
2228 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
2229 throw "-sectalign missing <segment> <section> <file-path>";
2230 addSectionAlignment(argv[i+1], argv[i+2], argv[i+3]);
2231 i += 3;
2233 else if ( strcmp(arg, "-sectorder_detail") == 0 ) {
2234 warnObsolete(arg);
2236 else if ( strcmp(arg, "-sectobjectsymbols") == 0 ) {
2237 warnObsolete(arg);
2238 i += 2;
2240 else if ( strcmp(arg, "-bundle_loader") == 0 ) {
2241 fBundleLoader = argv[++i];
2242 if ( (fBundleLoader == NULL) || (fBundleLoader[0] == '-') )
2243 throw "-bundle_loader missing <path>";
2244 FileInfo info = findFile(fBundleLoader);
2245 info.options.fBundleLoader = true;
2246 fInputFiles.push_back(info);
2248 else if ( strcmp(arg, "-private_bundle") == 0 ) {
2249 warnObsolete(arg);
2251 else if ( strcmp(arg, "-twolevel_namespace_hints") == 0 ) {
2252 // FIX FIX
2254 // Use this flag to set default behavior for deployement targets.
2255 else if ( strcmp(arg, "-macosx_version_min") == 0 ) {
2256 setMacOSXVersionMin(argv[++i]);
2258 else if ( (strcmp(arg, "-iphoneos_version_min") == 0) || (strcmp(arg, "-ios_version_min") == 0) ) {
2259 setIPhoneVersionMin(argv[++i]);
2261 else if ( strcmp(arg, "-multiply_defined") == 0 ) {
2262 //warnObsolete(arg);
2263 ++i;
2265 else if ( strcmp(arg, "-multiply_defined_unused") == 0 ) {
2266 warnObsolete(arg);
2267 ++i;
2269 else if ( strcmp(arg, "-nomultidefs") == 0 ) {
2270 warnObsolete(arg);
2272 // Display each file in which the argument symbol appears and whether
2273 // the file defines or references it. This option takes an argument
2274 // as -y<symbol> note that there is no space.
2275 else if ( strncmp(arg, "-y", 2) == 0 ) {
2276 warnObsolete("-y");
2278 // Same output as -y, but output <arg> number of undefined symbols only.
2279 else if ( strcmp(arg, "-Y") == 0 ) {
2280 //warnObsolete(arg);
2281 ++i;
2283 // This option affects all objects linked into the final result.
2284 else if ( strcmp(arg, "-m") == 0 ) {
2285 warnObsolete(arg);
2287 else if ( (strcmp(arg, "-why_load") == 0) || (strcmp(arg, "-whyload") == 0) ) {
2288 fWhyLoad = true;
2290 else if ( strcmp(arg, "-why_live") == 0 ) {
2291 const char* name = argv[++i];
2292 if ( name == NULL )
2293 throw "-why_live missing symbol name argument";
2294 fWhyLive.insert(name);
2296 else if ( strcmp(arg, "-u") == 0 ) {
2297 const char* name = argv[++i];
2298 if ( name == NULL )
2299 throw "-u missing argument";
2300 fInitialUndefines.push_back(name);
2302 else if ( strcmp(arg, "-U") == 0 ) {
2303 const char* name = argv[++i];
2304 if ( name == NULL )
2305 throw "-U missing argument";
2306 fAllowedUndefined.insert(name);
2308 else if ( strcmp(arg, "-s") == 0 ) {
2309 warnObsolete(arg);
2310 fLocalSymbolHandling = kLocalSymbolsNone;
2311 fDebugInfoStripping = Options::kDebugInfoNone;
2313 else if ( strcmp(arg, "-x") == 0 ) {
2314 fLocalSymbolHandling = kLocalSymbolsNone;
2316 else if ( strcmp(arg, "-S") == 0 ) {
2317 fDebugInfoStripping = Options::kDebugInfoNone;
2319 else if ( strcmp(arg, "-X") == 0 ) {
2320 warnObsolete(arg);
2322 else if ( strcmp(arg, "-Si") == 0 ) {
2323 warnObsolete(arg);
2324 fDebugInfoStripping = Options::kDebugInfoFull;
2326 else if ( strcmp(arg, "-b") == 0 ) {
2327 warnObsolete(arg);
2329 else if ( strcmp(arg, "-Sn") == 0 ) {
2330 warnObsolete(arg);
2331 fDebugInfoStripping = Options::kDebugInfoFull;
2333 else if ( strcmp(arg, "-Sp") == 0 ) {
2334 warnObsolete(arg);
2336 else if ( strcmp(arg, "-dead_strip") == 0 ) {
2337 fDeadStrip = true;
2339 else if ( strcmp(arg, "-no_dead_strip_inits_and_terms") == 0 ) {
2340 fDeadStrip = true;
2342 else if ( strcmp(arg, "-w") == 0 ) {
2343 // previously handled by buildSearchPaths()
2345 else if ( strcmp(arg, "-arch_errors_fatal") == 0 ) {
2346 fErrorOnOtherArchFiles = true;
2348 else if ( strcmp(arg, "-M") == 0 ) {
2349 // FIX FIX
2351 else if ( strcmp(arg, "-headerpad") == 0 ) {
2352 const char* size = argv[++i];
2353 if ( size == NULL )
2354 throw "-headerpad missing argument";
2355 fMinimumHeaderPad = parseAddress(size);
2357 else if ( strcmp(arg, "-headerpad_max_install_names") == 0 ) {
2358 fMaxMinimumHeaderPad = true;
2360 else if ( strcmp(arg, "-t") == 0 ) {
2361 fLogAllFiles = true;
2363 else if ( strcmp(arg, "-whatsloaded") == 0 ) {
2364 fLogObjectFiles = true;
2366 else if ( strcmp(arg, "-A") == 0 ) {
2367 warnObsolete(arg);
2368 ++i;
2370 else if ( strcmp(arg, "-umbrella") == 0 ) {
2371 const char* name = argv[++i];
2372 if ( name == NULL )
2373 throw "-umbrella missing argument";
2374 fUmbrellaName = name;
2376 else if ( strcmp(arg, "-allowable_client") == 0 ) {
2377 const char* name = argv[++i];
2379 if ( name == NULL )
2380 throw "-allowable_client missing argument";
2382 fAllowableClients.push_back(name);
2384 else if ( strcmp(arg, "-client_name") == 0 ) {
2385 const char* name = argv[++i];
2387 if ( name == NULL )
2388 throw "-client_name missing argument";
2390 fClientName = name;
2392 else if ( strcmp(arg, "-sub_umbrella") == 0 ) {
2393 const char* name = argv[++i];
2394 if ( name == NULL )
2395 throw "-sub_umbrella missing argument";
2396 fSubUmbellas.push_back(name);
2398 else if ( strcmp(arg, "-sub_library") == 0 ) {
2399 const char* name = argv[++i];
2400 if ( name == NULL )
2401 throw "-sub_library missing argument";
2402 fSubLibraries.push_back(name);
2404 else if ( strcmp(arg, "-init") == 0 ) {
2405 const char* name = argv[++i];
2406 if ( name == NULL )
2407 throw "-init missing argument";
2408 fInitFunctionName = name;
2410 else if ( strcmp(arg, "-dot") == 0 ) {
2411 const char* name = argv[++i];
2412 if ( name == NULL )
2413 throw "-dot missing argument";
2414 fDotOutputFile = name;
2416 else if ( strcmp(arg, "-warn_commons") == 0 ) {
2417 fWarnCommons = true;
2419 else if ( strcmp(arg, "-commons") == 0 ) {
2420 fCommonsMode = parseCommonsTreatment(argv[++i]);
2422 else if ( strcmp(arg, "-keep_relocs") == 0 ) {
2423 fKeepRelocations = true;
2425 else if ( strcmp(arg, "-warn_stabs") == 0 ) {
2426 fWarnStabs = true;
2428 else if ( strcmp(arg, "-pause") == 0 ) {
2429 fPause = true;
2431 else if ( strcmp(arg, "-print_statistics") == 0 ) {
2432 fStatistics = true;
2434 else if ( strcmp(arg, "-d") == 0 ) {
2435 fMakeTentativeDefinitionsReal = true;
2437 else if ( strcmp(arg, "-v") == 0 ) {
2438 // previously handled by buildSearchPaths()
2440 else if ( strcmp(arg, "-Z") == 0 ) {
2441 // previously handled by buildSearchPaths()
2443 else if ( strcmp(arg, "-syslibroot") == 0 ) {
2444 ++i;
2445 // previously handled by buildSearchPaths()
2447 else if ( strcmp(arg, "-no_uuid") == 0 ) {
2448 fUUIDMode = kUUIDNone;
2450 else if ( strcmp(arg, "-random_uuid") == 0 ) {
2451 fUUIDMode = kUUIDRandom;
2453 else if ( strcmp(arg, "-dtrace") == 0 ) {
2454 const char* name = argv[++i];
2455 if ( name == NULL )
2456 throw "-dtrace missing argument";
2457 fDtraceScriptName = name;
2459 else if ( strcmp(arg, "-root_safe") == 0 ) {
2460 fRootSafe = true;
2462 else if ( strcmp(arg, "-setuid_safe") == 0 ) {
2463 fSetuidSafe = true;
2465 else if ( strcmp(arg, "-alias") == 0 ) {
2466 Options::AliasPair pair;
2467 pair.realName = argv[++i];
2468 if ( pair.realName == NULL )
2469 throw "missing argument to -alias";
2470 pair.alias = argv[++i];
2471 if ( pair.alias == NULL )
2472 throw "missing argument to -alias";
2473 fAliases.push_back(pair);
2475 else if ( strcmp(arg, "-alias_list") == 0 ) {
2476 parseAliasFile(argv[++i]);
2478 // put this last so that it does not interfer with other options starting with 'i'
2479 else if ( strncmp(arg, "-i", 2) == 0 ) {
2480 const char* colon = strchr(arg, ':');
2481 if ( colon == NULL )
2482 throwf("unknown option: %s", arg);
2483 Options::AliasPair pair;
2484 char* temp = new char[colon-arg];
2485 strlcpy(temp, &arg[2], colon-arg-1);
2486 pair.realName = &colon[1];
2487 pair.alias = temp;
2488 fAliases.push_back(pair);
2490 else if ( strcmp(arg, "-save-temps") == 0 ) {
2491 fSaveTempFiles = true;
2493 else if ( strcmp(arg, "-rpath") == 0 ) {
2494 const char* path = argv[++i];
2495 if ( path == NULL )
2496 throw "missing argument to -rpath";
2497 fRPaths.push_back(path);
2499 else if ( strcmp(arg, "-read_only_stubs") == 0 ) {
2500 fReadOnlyx86Stubs = true;
2502 else if ( strcmp(arg, "-slow_stubs") == 0 ) {
2503 warnObsolete(arg);
2505 else if ( strcmp(arg, "-map") == 0 ) {
2506 fMapPath = argv[++i];
2507 if ( fMapPath == NULL )
2508 throw "missing argument to -map";
2510 else if ( strcmp(arg, "-pie") == 0 ) {
2511 fPositionIndependentExecutable = true;
2512 fPIEOnCommandLine = true;
2514 else if ( strcmp(arg, "-no_pie") == 0 ) {
2515 fDisablePositionIndependentExecutable = true;
2517 else if ( strncmp(arg, "-reexport-l", 11) == 0 ) {
2518 FileInfo info = findLibrary(&arg[11], true);
2519 info.options.fReExport = true;
2520 addLibrary(info);
2522 else if ( strcmp(arg, "-reexport_library") == 0 ) {
2523 FileInfo info = findFile(argv[++i]);
2524 info.options.fReExport = true;
2525 addLibrary(info);
2527 else if ( strcmp(arg, "-reexport_framework") == 0 ) {
2528 FileInfo info = findFramework(argv[++i]);
2529 info.options.fReExport = true;
2530 addLibrary(info);
2532 else if ( strncmp(arg, "-upward-l", 9) == 0 ) {
2533 FileInfo info = findLibrary(&arg[9], true);
2534 info.options.fUpward = true;
2535 addLibrary(info);
2537 else if ( strcmp(arg, "-upward_library") == 0 ) {
2538 FileInfo info = findFile(argv[++i]);
2539 info.options.fUpward = true;
2540 addLibrary(info);
2542 else if ( strcmp(arg, "-upward_framework") == 0 ) {
2543 FileInfo info = findFramework(argv[++i]);
2544 info.options.fUpward = true;
2545 addLibrary(info);
2547 else if ( strcmp(arg, "-dead_strip_dylibs") == 0 ) {
2548 fDeadStripDylibs = true;
2550 else if ( strcmp(arg, "-no_implicit_dylibs") == 0 ) {
2551 fImplicitlyLinkPublicDylibs = false;
2553 else if ( strcmp(arg, "-new_linker") == 0 ) {
2554 // ignore
2556 else if ( strcmp(arg, "-no_encryption") == 0 ) {
2557 fEncryptable = false;
2559 else if ( strcmp(arg, "-no_compact_unwind") == 0 ) {
2560 fAddCompactUnwindEncoding = false;
2562 else if ( strcmp(arg, "-mllvm") == 0 ) {
2563 const char* opts = argv[++i];
2564 if ( opts == NULL )
2565 throw "missing argument to -mllvm";
2566 fLLVMOptions.push_back(opts);
2568 else if ( strcmp(arg, "-no_order_inits") == 0 ) {
2569 fAutoOrderInitializers = false;
2571 else if ( strcmp(arg, "-no_order_data") == 0 ) {
2572 fOrderData = false;
2574 else if ( strcmp(arg, "-seg_page_size") == 0 ) {
2575 SegmentSize seg;
2576 seg.name = argv[++i];
2577 if ( (seg.name == NULL) || (argv[i+1] == NULL) )
2578 throw "-seg_page_size missing segName Adddress";
2579 seg.size = parseAddress(argv[++i]);
2580 uint64_t temp = seg.size & (-4096); // page align
2581 if ( (seg.size != temp) )
2582 warning("-seg_page_size %s not 4K aligned, rounding down", seg.name);
2583 fCustomSegmentSizes.push_back(seg);
2585 else if ( strcmp(arg, "-mark_dead_strippable_dylib") == 0 ) {
2586 fMarkDeadStrippableDylib = true;
2588 else if ( strcmp(arg, "-exported_symbols_order") == 0 ) {
2589 loadSymbolOrderFile(argv[++i], fExportSymbolsOrder);
2591 else if ( strcmp(arg, "-no_compact_linkedit") == 0 ) {
2592 fMakeCompressedDyldInfo = false;
2593 fMakeCompressedDyldInfoForceOff = true;
2595 else if ( strcmp(arg, "-no_eh_labels") == 0 ) {
2596 fNoEHLabels = true;
2598 else if ( strcmp(arg, "-warn_compact_unwind") == 0 ) {
2599 fWarnCompactUnwind = true;
2601 else if ( strcmp(arg, "-allow_sub_type_mismatches") == 0 ) {
2602 fAllowCpuSubtypeMismatches = true;
2604 else if ( strcmp(arg, "-no_zero_fill_sections") == 0 ) {
2605 fOptimizeZeroFill = false;
2607 else if ( strcmp(arg, "-objc_abi_version") == 0 ) {
2608 const char* version = argv[++i];
2609 if ( version == NULL )
2610 throw "-objc_abi_version missing version number";
2611 if ( strcmp(version, "2") == 0 ) {
2612 fObjCABIVersion1Override = false;
2613 fObjCABIVersion2Override = true;
2615 else if ( strcmp(version, "1") == 0 ) {
2616 fObjCABIVersion1Override = true;
2617 fObjCABIVersion2Override = false;
2619 else
2620 warning("ignoring unrecognized argument (%s) to -objc_abi_version", version);
2622 else if ( strcmp(arg, "-warn_weak_exports") == 0 ) {
2623 fWarnWeakExports = true;
2625 else if ( strcmp(arg, "-objc_gc_compaction") == 0 ) {
2626 fObjcGcCompaction = true;
2628 else if ( strcmp(arg, "-objc_gc") == 0 ) {
2629 fObjCGc = true;
2630 if ( fObjCGcOnly ) {
2631 warning("-objc_gc overriding -objc_gc_only");
2632 fObjCGcOnly = false;
2635 else if ( strcmp(arg, "-objc_gc_only") == 0 ) {
2636 fObjCGcOnly = true;
2637 if ( fObjCGc ) {
2638 warning("-objc_gc_only overriding -objc_gc");
2639 fObjCGc = false;
2642 else if ( strcmp(arg, "-demangle") == 0 ) {
2643 fDemangle = true;
2645 else if ( strcmp(arg, "-version_load_command") == 0 ) {
2646 fVersionLoadCommand = true;
2648 else if ( strcmp(arg, "-no_version_load_command") == 0 ) {
2649 fVersionLoadCommand = false;
2651 else if ( strcmp(arg, "-function_starts") == 0 ) {
2652 fFunctionStartsLoadCommand = true;
2654 else if ( strcmp(arg, "-no_function_starts") == 0 ) {
2655 fFunctionStartsLoadCommand = false;
2657 else if ( strcmp(arg, "-object_path_lto") == 0 ) {
2658 fTempLtoObjectPath = argv[++i];
2659 if ( fTempLtoObjectPath == NULL )
2660 throw "missing argument to -object_path_lto";
2662 else if ( strcmp(arg, "-no_objc_category_merging") == 0 ) {
2663 fObjcCategoryMerging = false;
2665 else if ( strcmp(arg, "-force_symbols_weak_list") == 0 ) {
2666 loadExportFile(argv[++i], "-force_symbols_weak_list", fForceWeakSymbols);
2668 else if ( strcmp(arg, "-force_symbols_not_weak_list") == 0 ) {
2669 loadExportFile(argv[++i], "-force_symbols_not_weak_list", fForceNotWeakSymbols);
2671 else if ( strcmp(arg, "-force_symbol_weak") == 0 ) {
2672 const char* symbol = argv[++i];
2673 if ( symbol == NULL )
2674 throw "-force_symbol_weak missing <symbol>";
2675 fForceWeakSymbols.insert(symbol);
2677 else if ( strcmp(arg, "-force_symbol_not_weak") == 0 ) {
2678 const char* symbol = argv[++i];
2679 if ( symbol == NULL )
2680 throw "-force_symbol_not_weak missing <symbol>";
2681 fForceNotWeakSymbols.insert(symbol);
2683 else if ( strcmp(arg, "-reexported_symbols_list") == 0 ) {
2684 if ( fExportMode == kExportSome )
2685 throw "can't use -exported_symbols_list and -reexported_symbols_list";
2686 loadExportFile(argv[++i], "-reexported_symbols_list", fReExportSymbols);
2688 else if ( strcmp(arg, "-dyld_env") == 0 ) {
2689 const char* envarg = argv[++i];
2690 if ( envarg == NULL )
2691 throw "-dyld_env missing ENV=VALUE";
2692 if ( strchr(envarg, '=') == NULL )
2693 throw "-dyld_env missing ENV=VALUE";
2694 fDyldEnvironExtras.push_back(envarg);
2696 else {
2697 throwf("unknown option: %s", arg);
2700 else {
2701 FileInfo info = findFile(arg);
2702 if ( strcmp(&info.path[strlen(info.path)-2], ".a") == 0 )
2703 addLibrary(info);
2704 else
2705 fInputFiles.push_back(info);
2709 // if a -lazy option was used, implicitly link in lazydylib1.o
2710 if ( fUsingLazyDylibLinking ) {
2711 addLibrary(findLibrary("lazydylib1.o"));
2718 // -syslibroot <path> is used for SDK support.
2719 // The rule is that all search paths (both explicit and default) are
2720 // checked to see if they exist in the SDK. If so, that path is
2721 // replaced with the sdk prefixed path. If not, that search path
2722 // is used as is. If multiple -syslibroot options are specified
2723 // their directory structures are logically overlayed and files
2724 // from sdks specified earlier on the command line used before later ones.
2726 void Options::buildSearchPaths(int argc, const char* argv[])
2728 bool addStandardLibraryDirectories = true;
2729 std::vector<const char*> libraryPaths;
2730 std::vector<const char*> frameworkPaths;
2731 libraryPaths.reserve(10);
2732 frameworkPaths.reserve(10);
2733 // scan through argv looking for -L, -F, -Z, and -syslibroot options
2734 for(int i=0; i < argc; ++i) {
2735 if ( (argv[i][0] == '-') && (argv[i][1] == 'L') ) {
2736 const char* libSearchDir = &argv[i][2];
2737 // Allow either "-L{path}" or "-L {path}".
2738 if (argv[i][2] == '\0') {
2739 // -L {path}. Make sure there is an argument following this.
2740 const char* path = argv[++i];
2741 if ( path == NULL )
2742 throw "-L missing argument";
2743 libSearchDir = path;
2745 if ( libSearchDir[0] == '\0' )
2746 throw "-L must be immediately followed by a directory path (no space)";
2747 struct stat statbuf;
2748 if ( stat(libSearchDir, &statbuf) == 0 ) {
2749 if ( statbuf.st_mode & S_IFDIR )
2750 libraryPaths.push_back(libSearchDir);
2751 else
2752 warning("path '%s' following -L not a directory", libSearchDir);
2754 else {
2755 warning("directory not found for option '-L%s'", libSearchDir);
2758 else if ( (argv[i][0] == '-') && (argv[i][1] == 'F') ) {
2759 const char* frameworkSearchDir = &argv[i][2];
2760 // Allow either "-F{path}" or "-F {path}".
2761 if (argv[i][2] == '\0') {
2762 // -F {path}. Make sure there is an argument following this.
2763 const char* path = argv[++i];
2764 if ( path == NULL )
2765 throw "-F missing argument";
2766 frameworkSearchDir = path;
2768 if ( frameworkSearchDir[0] == '\0' )
2769 throw "-F must be immediately followed by a directory path (no space)";
2770 struct stat statbuf;
2771 if ( stat(frameworkSearchDir, &statbuf) == 0 ) {
2772 if ( statbuf.st_mode & S_IFDIR )
2773 frameworkPaths.push_back(frameworkSearchDir);
2774 else
2775 warning("path '%s' following -F not a directory", frameworkSearchDir);
2777 else {
2778 warning("directory not found for option '-F%s'", frameworkSearchDir);
2781 else if ( strcmp(argv[i], "-Z") == 0 )
2782 addStandardLibraryDirectories = false;
2783 else if ( strcmp(argv[i], "-v") == 0 ) {
2784 fVerbose = true;
2785 extern const char ldVersionString[];
2786 fprintf(stderr, "%s", ldVersionString);
2787 // if only -v specified, exit cleanly
2788 if ( argc == 2 ) {
2789 const char* ltoVers = lto::version();
2790 if ( ltoVers != NULL )
2791 fprintf(stderr, "%s\n", ltoVers);
2792 exit(0);
2795 else if ( strcmp(argv[i], "-syslibroot") == 0 ) {
2796 const char* path = argv[++i];
2797 if ( path == NULL )
2798 throw "-syslibroot missing argument";
2799 fSDKPaths.push_back(path);
2801 else if ( strcmp(argv[i], "-search_paths_first") == 0 ) {
2802 fLibrarySearchMode = kSearchDylibAndArchiveInEachDir;
2804 else if ( strcmp(argv[i], "-search_dylibs_first") == 0 ) {
2805 fLibrarySearchMode = kSearchAllDirsForDylibsThenAllDirsForArchives;
2807 else if ( strcmp(argv[i], "-w") == 0 ) {
2808 sEmitWarnings = false;
2811 int standardLibraryPathsStartIndex = libraryPaths.size();
2812 int standardFrameworkPathsStartIndex = frameworkPaths.size();
2813 if ( addStandardLibraryDirectories ) {
2814 libraryPaths.push_back("/usr/lib");
2815 libraryPaths.push_back("/usr/local/lib");
2817 frameworkPaths.push_back("/Library/Frameworks/");
2818 frameworkPaths.push_back("/System/Library/Frameworks/");
2819 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
2822 // <rdar://problem/5829579> Support for configure based hacks
2823 // if last -syslibroot is /, then ignore all syslibroots
2824 if ( fSDKPaths.size() > 0 ) {
2825 if ( strcmp(fSDKPaths.back(), "/") == 0 ) {
2826 fSDKPaths.clear();
2830 // now merge sdk and library paths to make real search paths
2831 fLibrarySearchPaths.reserve(libraryPaths.size()*(fSDKPaths.size()+1));
2832 int libIndex = 0;
2833 for (std::vector<const char*>::iterator it = libraryPaths.begin(); it != libraryPaths.end(); ++it, ++libIndex) {
2834 const char* libDir = *it;
2835 bool sdkOverride = false;
2836 if ( libDir[0] == '/' ) {
2837 char betterLibDir[PATH_MAX];
2838 if ( strstr(libDir, "/..") != NULL ) {
2839 if ( realpath(libDir, betterLibDir) != NULL )
2840 libDir = strdup(betterLibDir);
2842 const int libDirLen = strlen(libDir);
2843 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
2844 const char* sdkDir = *sdkit;
2845 const int sdkDirLen = strlen(sdkDir);
2846 char newPath[libDirLen + sdkDirLen+4];
2847 strcpy(newPath, sdkDir);
2848 if ( newPath[sdkDirLen-1] == '/' )
2849 newPath[sdkDirLen-1] = '\0';
2850 strcat(newPath, libDir);
2851 struct stat statBuffer;
2852 if ( stat(newPath, &statBuffer) == 0 ) {
2853 fLibrarySearchPaths.push_back(strdup(newPath));
2854 sdkOverride = true;
2858 if ( !sdkOverride ) {
2859 if ( (libIndex >= standardLibraryPathsStartIndex) && (fSDKPaths.size() == 1) ) {
2860 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2861 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2863 else {
2864 fLibrarySearchPaths.push_back(libDir);
2869 // now merge sdk and framework paths to make real search paths
2870 fFrameworkSearchPaths.reserve(frameworkPaths.size()*(fSDKPaths.size()+1));
2871 int frameIndex = 0;
2872 for (std::vector<const char*>::iterator it = frameworkPaths.begin(); it != frameworkPaths.end(); ++it, ++frameIndex) {
2873 const char* frameworkDir = *it;
2874 bool sdkOverride = false;
2875 if ( frameworkDir[0] == '/' ) {
2876 char betterFrameworkDir[PATH_MAX];
2877 if ( strstr(frameworkDir, "/..") != NULL ) {
2878 if ( realpath(frameworkDir, betterFrameworkDir) != NULL )
2879 frameworkDir = strdup(betterFrameworkDir);
2881 const int frameworkDirLen = strlen(frameworkDir);
2882 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
2883 const char* sdkDir = *sdkit;
2884 const int sdkDirLen = strlen(sdkDir);
2885 char newPath[frameworkDirLen + sdkDirLen+4];
2886 strcpy(newPath, sdkDir);
2887 if ( newPath[sdkDirLen-1] == '/' )
2888 newPath[sdkDirLen-1] = '\0';
2889 strcat(newPath, frameworkDir);
2890 struct stat statBuffer;
2891 if ( stat(newPath, &statBuffer) == 0 ) {
2892 fFrameworkSearchPaths.push_back(strdup(newPath));
2893 sdkOverride = true;
2897 if ( !sdkOverride ) {
2898 if ( (frameIndex >= standardFrameworkPathsStartIndex) && (fSDKPaths.size() == 1) ) {
2899 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2900 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2902 else {
2903 fFrameworkSearchPaths.push_back(frameworkDir);
2908 if ( fVerbose ) {
2909 fprintf(stderr,"Library search paths:\n");
2910 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
2911 it != fLibrarySearchPaths.end();
2912 it++)
2913 fprintf(stderr,"\t%s\n", *it);
2914 fprintf(stderr,"Framework search paths:\n");
2915 for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin();
2916 it != fFrameworkSearchPaths.end();
2917 it++)
2918 fprintf(stderr,"\t%s\n", *it);
2922 // this is run before the command line is parsed
2923 void Options::parsePreCommandLineEnvironmentSettings()
2925 if ((getenv("LD_TRACE_ARCHIVES") != NULL)
2926 || (getenv("RC_TRACE_ARCHIVES") != NULL))
2927 fTraceArchives = true;
2929 if ((getenv("LD_TRACE_DYLIBS") != NULL)
2930 || (getenv("RC_TRACE_DYLIBS") != NULL)) {
2931 fTraceDylibs = true;
2932 fTraceIndirectDylibs = true;
2935 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL) {
2936 fTraceDylibSearching = true;
2939 if (getenv("LD_PRINT_OPTIONS") != NULL)
2940 fPrintOptions = true;
2942 if (fTraceDylibs || fTraceArchives)
2943 fTraceOutputFile = getenv("LD_TRACE_FILE");
2945 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL)
2946 fPrintOrderFileStatistics = true;
2948 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL)
2949 fSplitSegs = true;
2951 if (getenv("LD_NO_ENCRYPT") != NULL)
2952 fEncryptable = false;
2954 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL)
2955 fAllowCpuSubtypeMismatches = true;
2957 // for now disable compressed linkedit functionality
2958 if ( getenv("LD_NO_COMPACT_LINKEDIT") != NULL ) {
2959 fMakeCompressedDyldInfo = false;
2960 fMakeCompressedDyldInfoForceOff = true;
2963 sWarningsSideFilePath = getenv("LD_WARN_FILE");
2965 const char* customDyldPath = getenv("LD_DYLD_PATH");
2966 if ( customDyldPath != NULL )
2967 fDyldInstallPath = customDyldPath;
2971 // this is run after the command line is parsed
2972 void Options::parsePostCommandLineEnvironmentSettings()
2974 // when building a dynamic main executable, default any use of @executable_path to output path
2975 if ( fExecutablePath == NULL && (fOutputKind == kDynamicExecutable) ) {
2976 fExecutablePath = fOutputFile;
2979 // allow build system to set default seg_addr_table
2980 if ( fSegAddrTablePath == NULL )
2981 fSegAddrTablePath = getenv("LD_SEG_ADDR_TABLE");
2983 // allow build system to turn on prebinding
2984 if ( !fPrebind ) {
2985 fPrebind = ( getenv("LD_PREBIND") != NULL );
2988 // allow build system to force on dead-code-stripping
2989 if ( !fDeadStrip ) {
2990 if ( getenv("LD_DEAD_STRIP") != NULL ) {
2991 switch (fOutputKind) {
2992 case Options::kDynamicLibrary:
2993 case Options::kDynamicExecutable:
2994 case Options::kDynamicBundle:
2995 fDeadStrip = true;
2996 break;
2997 case Options::kPreload:
2998 case Options::kObjectFile:
2999 case Options::kDyld:
3000 case Options::kStaticExecutable:
3001 case Options::kKextBundle:
3002 break;
3007 // allow build system to force on -warn_commons
3008 if ( getenv("LD_WARN_COMMONS") != NULL )
3009 fWarnCommons = true;
3013 void Options::reconfigureDefaults()
3015 // sync reader options
3016 switch ( fOutputKind ) {
3017 case Options::kObjectFile:
3018 fForFinalLinkedImage = false;
3019 break;
3020 case Options::kDyld:
3021 fForDyld = true;
3022 fForFinalLinkedImage = true;
3023 fNoEHLabels = true;
3024 break;
3025 case Options::kDynamicLibrary:
3026 case Options::kDynamicBundle:
3027 case Options::kKextBundle:
3028 fForFinalLinkedImage = true;
3029 fNoEHLabels = true;
3030 break;
3031 case Options::kDynamicExecutable:
3032 case Options::kStaticExecutable:
3033 case Options::kPreload:
3034 fLinkingMainExecutable = true;
3035 fForFinalLinkedImage = true;
3036 fNoEHLabels = true;
3037 break;
3040 // set default min OS version
3041 if ( (fMacVersionMin == ld::macVersionUnset)
3042 && (fIPhoneVersionMin == ld::iPhoneVersionUnset) ) {
3043 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
3044 const char* macVers = getenv("MACOSX_DEPLOYMENT_TARGET");
3045 const char* iPhoneVers = getenv("IPHONEOS_DEPLOYMENT_TARGET");
3046 const char* iOSVers = getenv("IOS_DEPLOYMENT_TARGET");
3047 if ( macVers != NULL )
3048 setMacOSXVersionMin(macVers);
3049 else if ( iPhoneVers != NULL )
3050 setIPhoneVersionMin(iPhoneVers);
3051 else if ( iOSVers != NULL )
3052 setIPhoneVersionMin(iOSVers);
3053 else {
3054 // if still nothing, set default based on architecture
3055 switch ( fArchitecture ) {
3056 case CPU_TYPE_I386:
3057 case CPU_TYPE_X86_64:
3058 case CPU_TYPE_POWERPC:
3059 if ( (fOutputKind != Options::kObjectFile) && (fOutputKind != Options::kPreload) ) {
3060 #ifdef DEFAULT_MACOSX_MIN_VERSION
3061 warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION);
3062 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
3063 #else
3064 warning("-macosx_version_min not specificed, assuming 10.6");
3065 fMacVersionMin = ld::mac10_6;
3066 #endif
3068 break;
3069 case CPU_TYPE_ARM:
3070 if ( (fOutputKind != Options::kObjectFile) && (fOutputKind != Options::kPreload) ) {
3071 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
3072 warning("-ios_version_min not specificed, assuming " DEFAULT_IPHONEOS_MIN_VERSION);
3073 setIPhoneVersionMin(DEFAULT_IPHONEOS_MIN_VERSION);
3074 #elif defined(DEFAULT_MACOSX_MIN_VERSION)
3075 warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION);
3076 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
3077 #else
3078 warning("-macosx_version_min not specificed, assuming 10.6");
3079 fMacVersionMin = ld::mac10_6;
3080 #endif
3082 break;
3083 default:
3084 // architecture will be infered ;ater by examining .o files
3085 break;
3091 // adjust min based on architecture
3092 switch ( fArchitecture ) {
3093 case CPU_TYPE_I386:
3094 if ( (fMacVersionMin < ld::mac10_4) && (fIPhoneVersionMin == ld::iPhoneVersionUnset) ) {
3095 //warning("-macosx_version_min should be 10.4 or later for i386");
3096 fMacVersionMin = ld::mac10_4;
3098 break;
3099 case CPU_TYPE_POWERPC64:
3100 if ( fMacVersionMin < ld::mac10_4 ) {
3101 //warning("-macosx_version_min should be 10.4 or later for ppc64");
3102 fMacVersionMin = ld::mac10_4;
3104 break;
3105 case CPU_TYPE_X86_64:
3106 if ( fMacVersionMin < ld::mac10_4 ) {
3107 //warning("-macosx_version_min should be 10.4 or later for x86_64");
3108 fMacVersionMin = ld::mac10_4;
3110 break;
3113 // adjust kext type based on architecture
3114 if ( fOutputKind == kKextBundle ) {
3115 switch ( fArchitecture ) {
3116 case CPU_TYPE_X86_64:
3117 // x86_64 uses new MH_KEXT_BUNDLE type
3118 fMakeCompressedDyldInfo = false;
3119 fMakeCompressedDyldInfoForceOff = true;
3120 fAllowTextRelocs = true;
3121 fUndefinedTreatment = kUndefinedDynamicLookup;
3122 break;
3123 case CPU_TYPE_POWERPC:
3124 case CPU_TYPE_I386:
3125 case CPU_TYPE_ARM:
3126 // use .o files
3127 fOutputKind = kObjectFile;
3128 break;
3132 // disable implicit dylibs when targeting 10.3
3133 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
3134 if ( !minOS(ld::mac10_4, ld::iPhone2_0) )
3135 fImplicitlyLinkPublicDylibs = false;
3138 // allow build system to force linker to ignore -prebind
3139 if ( getenv("LD_FORCE_NO_PREBIND") != NULL )
3140 fPrebind = false;
3142 // allow build system to force linker to ignore -seg_addr_table
3143 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL )
3144 fSegAddrTablePath = NULL;
3146 // check for base address specified externally
3147 if ( (fSegAddrTablePath != NULL) && (fOutputKind == Options::kDynamicLibrary) ) {
3148 parseSegAddrTable(fSegAddrTablePath, this->installPath());
3149 // HACK to support seg_addr_table entries that are physical paths instead of install paths
3150 if ( fBaseAddress == 0 ) {
3151 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
3152 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libstdc++.6.0.4.dylib");
3153 if ( fBaseAddress == 0 )
3154 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libstdc++.6.0.9.dylib");
3157 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
3158 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libz.1.2.3.dylib");
3160 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
3161 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libutil1.0.dylib");
3165 // split segs only allowed for dylibs
3166 if ( fSplitSegs ) {
3167 // split seg only supported for ppc, i386, and arm.
3168 switch ( fArchitecture ) {
3169 case CPU_TYPE_POWERPC:
3170 case CPU_TYPE_I386:
3171 if ( fOutputKind != Options::kDynamicLibrary )
3172 fSplitSegs = false;
3173 // make sure read and write segments are proper distance apart
3174 if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x10000000) )
3175 fBaseWritableAddress = fBaseAddress + 0x10000000;
3176 break;
3177 case CPU_TYPE_ARM:
3178 if ( fOutputKind != Options::kDynamicLibrary ) {
3179 fSplitSegs = false;
3181 else {
3182 // make sure read and write segments are proper distance apart
3183 if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x08000000) )
3184 fBaseWritableAddress = fBaseAddress + 0x08000000;
3186 break;
3187 default:
3188 fSplitSegs = false;
3189 fBaseAddress = 0;
3190 fBaseWritableAddress = 0;
3194 // set too-large size
3195 switch ( fArchitecture ) {
3196 case CPU_TYPE_POWERPC:
3197 case CPU_TYPE_I386:
3198 fMaxAddress = 0xFFFFFFFF;
3199 break;
3200 case CPU_TYPE_POWERPC64:
3201 case CPU_TYPE_X86_64:
3202 break;
3203 case CPU_TYPE_ARM:
3204 switch ( fOutputKind ) {
3205 case Options::kDynamicExecutable:
3206 case Options::kDynamicLibrary:
3207 case Options::kDynamicBundle:
3208 // user land code is limited to low 1GB
3209 fMaxAddress = 0x2FFFFFFF;
3210 break;
3211 case Options::kStaticExecutable:
3212 case Options::kObjectFile:
3213 case Options::kDyld:
3214 case Options::kPreload:
3215 case Options::kKextBundle:
3216 fMaxAddress = 0xFFFFFFFF;
3217 break;
3219 // range check -seg1addr for ARM
3220 if ( fBaseAddress > fMaxAddress ) {
3221 warning("ignoring -seg1addr 0x%08llX. Address out of range.", fBaseAddress);
3222 fBaseAddress = 0;
3224 break;
3227 // <rdar://problem/6138961> -r implies no prebinding for all architectures
3228 if ( fOutputKind == Options::kObjectFile )
3229 fPrebind = false;
3231 // disable prebinding depending on arch and min OS version
3232 if ( fPrebind ) {
3233 switch ( fArchitecture ) {
3234 case CPU_TYPE_POWERPC:
3235 case CPU_TYPE_I386:
3236 if ( fMacVersionMin == ld::mac10_4 ) {
3237 // in 10.4 only split seg dylibs are prebound
3238 if ( (fOutputKind != Options::kDynamicLibrary) || ! fSplitSegs )
3239 fPrebind = false;
3241 else if ( fMacVersionMin >= ld::mac10_5 ) {
3242 // in 10.5 nothing is prebound
3243 fPrebind = false;
3245 else {
3246 // in 10.3 and earlier only dylibs and main executables could be prebound
3247 switch ( fOutputKind ) {
3248 case Options::kDynamicExecutable:
3249 case Options::kDynamicLibrary:
3250 // only main executables and dylibs can be prebound
3251 break;
3252 case Options::kStaticExecutable:
3253 case Options::kDynamicBundle:
3254 case Options::kObjectFile:
3255 case Options::kDyld:
3256 case Options::kPreload:
3257 case Options::kKextBundle:
3258 // disable prebinding for everything else
3259 fPrebind = false;
3260 break;
3263 break;
3264 case CPU_TYPE_POWERPC64:
3265 case CPU_TYPE_X86_64:
3266 fPrebind = false;
3267 break;
3268 case CPU_TYPE_ARM:
3269 switch ( fOutputKind ) {
3270 case Options::kDynamicExecutable:
3271 case Options::kDynamicLibrary:
3272 // only main executables and dylibs can be prebound
3273 break;
3274 case Options::kStaticExecutable:
3275 case Options::kDynamicBundle:
3276 case Options::kObjectFile:
3277 case Options::kDyld:
3278 case Options::kPreload:
3279 case Options::kKextBundle:
3280 // disable prebinding for everything else
3281 fPrebind = false;
3282 break;
3284 break;
3288 // only prebound images can be split-seg
3289 if ( fSplitSegs && !fPrebind )
3290 fSplitSegs = false;
3292 // determine if info for shared region should be added
3293 if ( fOutputKind == Options::kDynamicLibrary ) {
3294 if ( minOS(ld::mac10_5, ld::iPhone3_1) )
3295 if ( !fPrebind )
3296 if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
3297 || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
3298 fSharedRegionEligible = true;
3301 // figure out if module table is needed for compatibility with old ld/dyld
3302 if ( fOutputKind == Options::kDynamicLibrary ) {
3303 switch ( fArchitecture ) {
3304 case CPU_TYPE_POWERPC: // 10.3 and earlier dyld requires a module table
3305 case CPU_TYPE_I386: // ld_classic for 10.4.x requires a module table
3306 if ( fMacVersionMin <= ld::mac10_5 )
3307 fNeedsModuleTable = true;
3308 break;
3309 case CPU_TYPE_ARM:
3310 if ( fPrebind )
3311 fNeedsModuleTable = true; // redo_prebinding requires a module table
3312 break;
3316 // <rdar://problem/5366363> -r -x implies -S
3317 if ( (fOutputKind == Options::kObjectFile) && (fLocalSymbolHandling == kLocalSymbolsNone) )
3318 fDebugInfoStripping = Options::kDebugInfoNone;
3320 // choose how to process unwind info
3321 switch ( fArchitecture ) {
3322 case CPU_TYPE_I386:
3323 case CPU_TYPE_X86_64:
3324 switch ( fOutputKind ) {
3325 case Options::kObjectFile:
3326 case Options::kStaticExecutable:
3327 case Options::kPreload:
3328 case Options::kKextBundle:
3329 fAddCompactUnwindEncoding = false;
3330 break;
3331 case Options::kDyld:
3332 case Options::kDynamicLibrary:
3333 case Options::kDynamicBundle:
3334 case Options::kDynamicExecutable:
3335 //if ( fAddCompactUnwindEncoding && (fVersionMin >= ld::mac10_6) )
3336 // fRemoveDwarfUnwindIfCompactExists = true;
3337 break;
3339 break;
3340 case CPU_TYPE_POWERPC:
3341 case CPU_TYPE_POWERPC64:
3342 case CPU_TYPE_ARM:
3343 fAddCompactUnwindEncoding = false;
3344 fRemoveDwarfUnwindIfCompactExists = false;
3345 break;
3346 case 0:
3347 // if -arch is missing, assume we don't want compact unwind info
3348 fAddCompactUnwindEncoding = false;
3349 break;
3352 // only ARM main executables can be encrypted
3353 if ( fOutputKind != Options::kDynamicExecutable )
3354 fEncryptable = false;
3355 if ( fArchitecture != CPU_TYPE_ARM )
3356 fEncryptable = false;
3358 // don't move inits in dyld because dyld wants certain
3359 // entries point at stable locations at the start of __text
3360 if ( fOutputKind == Options::kDyld )
3361 fAutoOrderInitializers = false;
3364 // disable __data ordering for some output kinds
3365 switch ( fOutputKind ) {
3366 case Options::kObjectFile:
3367 case Options::kDyld:
3368 case Options::kStaticExecutable:
3369 case Options::kPreload:
3370 case Options::kKextBundle:
3371 fOrderData = false;
3372 break;
3373 case Options::kDynamicExecutable:
3374 case Options::kDynamicLibrary:
3375 case Options::kDynamicBundle:
3376 break;
3379 // only use compressed LINKEDIT for final linked images
3380 switch ( fOutputKind ) {
3381 case Options::kDynamicExecutable:
3382 case Options::kDynamicLibrary:
3383 case Options::kDynamicBundle:
3384 break;
3385 case Options::kPreload:
3386 case Options::kStaticExecutable:
3387 case Options::kObjectFile:
3388 case Options::kDyld:
3389 case Options::kKextBundle:
3390 fMakeCompressedDyldInfoForceOff = true;
3391 break;
3393 if ( fMakeCompressedDyldInfoForceOff )
3394 fMakeCompressedDyldInfo = false;
3397 // only use compressed LINKEDIT for:
3398 // x86_64 and i386 on Mac OS X 10.6 or later
3399 // arm on iPhoneOS 3.1 or later
3400 if ( fMakeCompressedDyldInfo ) {
3401 switch (fArchitecture) {
3402 case CPU_TYPE_I386:
3403 case CPU_TYPE_X86_64:
3404 if ( fMacVersionMin < ld::mac10_6 )
3405 fMakeCompressedDyldInfo = false;
3406 break;
3407 case CPU_TYPE_ARM:
3408 if ( !minOS(ld::mac10_6, ld::iPhone3_1) )
3409 fMakeCompressedDyldInfo = false;
3410 break;
3411 case CPU_TYPE_POWERPC:
3412 case CPU_TYPE_POWERPC64:
3413 default:
3414 fMakeCompressedDyldInfo = false;
3419 // only ARM enforces that cpu-sub-types must match
3420 if ( fArchitecture != CPU_TYPE_ARM )
3421 fAllowCpuSubtypeMismatches = true;
3423 // only final linked images can not optimize zero fill sections
3424 if ( fOutputKind == Options::kObjectFile )
3425 fOptimizeZeroFill = true;
3427 // all undefines in -r mode
3428 // if ( fOutputKind == Options::kObjectFile )
3429 // fUndefinedTreatment = kUndefinedSuppress;
3431 // only dynamic final linked images should warn about use of commmons
3432 if ( fWarnCommons ) {
3433 switch ( fOutputKind ) {
3434 case Options::kDynamicExecutable:
3435 case Options::kDynamicLibrary:
3436 case Options::kDynamicBundle:
3437 break;
3438 case Options::kPreload:
3439 case Options::kStaticExecutable:
3440 case Options::kObjectFile:
3441 case Options::kDyld:
3442 case Options::kKextBundle:
3443 fWarnCommons = false;
3444 break;
3448 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
3449 if ( minOS(ld::mac10_5, ld::iPhone2_0) )
3450 fUseSimplifiedDylibReExports = true;
3452 // Mac OS X 10.7 and iOS 4.2 support LC_LOAD_UPWARD_DYLIB
3453 if ( minOS(ld::mac10_7, ld::iPhone4_2) && (fOutputKind == kDynamicLibrary) )
3454 fCanUseUpwardDylib = true;
3456 // x86_64 for MacOSX 10.7 defaults to PIE
3457 if ( (fArchitecture == CPU_TYPE_X86_64) && (fOutputKind == kDynamicExecutable) && (fMacVersionMin >= ld::mac10_7) ) {
3458 fPositionIndependentExecutable = true;
3461 // armv7 for iOS4.3 defaults to PIE
3462 if ( (fArchitecture == CPU_TYPE_ARM)
3463 && (fSubArchitecture == CPU_SUBTYPE_ARM_V7)
3464 && (fOutputKind == kDynamicExecutable)
3465 && (fIPhoneVersionMin >= ld::iPhone4_3) ) {
3466 fPositionIndependentExecutable = true;
3469 // -no_pie anywhere on command line disable PIE
3470 if ( fDisablePositionIndependentExecutable )
3471 fPositionIndependentExecutable = false;
3473 // set fOutputSlidable
3474 switch ( fOutputKind ) {
3475 case Options::kObjectFile:
3476 case Options::kStaticExecutable:
3477 fOutputSlidable = false;
3478 break;
3479 case Options::kDynamicExecutable:
3480 fOutputSlidable = fPositionIndependentExecutable;
3481 break;
3482 case Options::kPreload:
3483 fOutputSlidable = fPIEOnCommandLine;
3484 break;
3485 case Options::kDyld:
3486 case Options::kDynamicLibrary:
3487 case Options::kDynamicBundle:
3488 case Options::kKextBundle:
3489 fOutputSlidable = true;
3490 break;
3493 // let linker know if thread local variables are supported
3494 if ( fMacVersionMin >= ld::mac10_7 ) {
3495 fTLVSupport = true;
3498 // version load command is only in some kinds of output files
3499 switch ( fOutputKind ) {
3500 case Options::kObjectFile:
3501 case Options::kStaticExecutable:
3502 case Options::kPreload:
3503 case Options::kKextBundle:
3504 fVersionLoadCommand = false;
3505 fFunctionStartsLoadCommand = false;
3506 break;
3507 case Options::kDynamicExecutable:
3508 case Options::kDyld:
3509 case Options::kDynamicLibrary:
3510 case Options::kDynamicBundle:
3511 break;
3514 // support re-export of individual symbols in MacOSX 10.7 and iOS 4.2
3515 if ( (fOutputKind == kDynamicLibrary) && minOS(ld::mac10_7, ld::iPhone4_2) )
3516 fCanReExportSymbols = true;
3518 // ObjC optimization is only in dynamic final linked images
3519 switch ( fOutputKind ) {
3520 case Options::kObjectFile:
3521 case Options::kStaticExecutable:
3522 case Options::kPreload:
3523 case Options::kKextBundle:
3524 case Options::kDyld:
3525 fObjcCategoryMerging = false;
3526 break;
3527 case Options::kDynamicExecutable:
3528 case Options::kDynamicLibrary:
3529 case Options::kDynamicBundle:
3530 break;
3533 // i386 main executables linked on Mac OS X 10.7 default to NX heap
3534 // regardless of target unless overriden with -allow_heap_execute anywhere
3535 // on the command line
3536 if ( (fArchitecture == CPU_TYPE_I386) && (fOutputKind == kDynamicExecutable) && !fDisableNonExecutableHeap)
3537 fNonExecutableHeap = true;
3540 void Options::checkIllegalOptionCombinations()
3542 // check -undefined setting
3543 switch ( fUndefinedTreatment ) {
3544 case kUndefinedError:
3545 case kUndefinedDynamicLookup:
3546 // always legal
3547 break;
3548 case kUndefinedWarning:
3549 case kUndefinedSuppress:
3550 // requires flat namespace
3551 if ( fNameSpace == kTwoLevelNameSpace )
3552 throw "can't use -undefined warning or suppress with -twolevel_namespace";
3553 break;
3556 // unify -sub_umbrella with dylibs
3557 for (std::vector<const char*>::iterator it = fSubUmbellas.begin(); it != fSubUmbellas.end(); it++) {
3558 const char* subUmbrella = *it;
3559 bool found = false;
3560 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
3561 Options::FileInfo& info = *fit;
3562 const char* lastSlash = strrchr(info.path, '/');
3563 if ( lastSlash == NULL )
3564 lastSlash = info.path - 1;
3565 if ( strcmp(&lastSlash[1], subUmbrella) == 0 ) {
3566 info.options.fReExport = true;
3567 found = true;
3568 break;
3571 if ( ! found )
3572 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella);
3575 // unify -sub_library with dylibs
3576 for (std::vector<const char*>::iterator it = fSubLibraries.begin(); it != fSubLibraries.end(); it++) {
3577 const char* subLibrary = *it;
3578 bool found = false;
3579 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
3580 Options::FileInfo& info = *fit;
3581 const char* lastSlash = strrchr(info.path, '/');
3582 if ( lastSlash == NULL )
3583 lastSlash = info.path - 1;
3584 const char* dot = strchr(&lastSlash[1], '.');
3585 if ( dot == NULL )
3586 dot = &lastSlash[strlen(lastSlash)];
3587 if ( strncmp(&lastSlash[1], subLibrary, dot-lastSlash-1) == 0 ) {
3588 info.options.fReExport = true;
3589 found = true;
3590 break;
3593 if ( ! found )
3594 warning("-sub_library %s does not match a supplied dylib", subLibrary);
3597 // sync reader options
3598 if ( fNameSpace != kTwoLevelNameSpace )
3599 fFlatNamespace = true;
3601 // check -stack_addr
3602 if ( fStackAddr != 0 ) {
3603 switch (fArchitecture) {
3604 case CPU_TYPE_I386:
3605 case CPU_TYPE_POWERPC:
3606 case CPU_TYPE_ARM:
3607 if ( fStackAddr > 0xFFFFFFFF )
3608 throw "-stack_addr must be < 4G for 32-bit processes";
3609 break;
3610 case CPU_TYPE_POWERPC64:
3611 case CPU_TYPE_X86_64:
3612 break;
3614 if ( (fStackAddr & -4096) != fStackAddr )
3615 throw "-stack_addr must be multiples of 4K";
3616 if ( fStackSize == 0 )
3617 throw "-stack_addr must be used with -stack_size";
3620 // check -stack_size
3621 if ( fStackSize != 0 ) {
3622 switch (fArchitecture) {
3623 case CPU_TYPE_I386:
3624 case CPU_TYPE_POWERPC:
3625 if ( fStackSize > 0xFFFFFFFF )
3626 throw "-stack_size must be < 4G for 32-bit processes";
3627 if ( fStackAddr == 0 ) {
3628 fStackAddr = 0xC0000000;
3630 if ( (fStackAddr > 0xB0000000) && ((fStackAddr-fStackSize) < 0xB0000000) )
3631 warning("custom stack placement overlaps and will disable shared region");
3632 break;
3633 case CPU_TYPE_ARM:
3634 if ( fStackSize > 0x2F000000 )
3635 throw "-stack_size must be < 752MB";
3636 if ( fStackAddr == 0 )
3637 fStackAddr = 0x2F000000;
3638 if ( fStackAddr > 0x30000000)
3639 throw "-stack_addr must be < 0x30000000 for arm";
3640 case CPU_TYPE_POWERPC64:
3641 case CPU_TYPE_X86_64:
3642 if ( fStackAddr == 0 ) {
3643 fStackAddr = 0x00007FFF5C000000LL;
3645 break;
3647 if ( (fStackSize & -4096) != fStackSize )
3648 throw "-stack_size must be multiples of 4K";
3649 switch ( fOutputKind ) {
3650 case Options::kDynamicExecutable:
3651 case Options::kStaticExecutable:
3652 // custom stack size only legal when building main executable
3653 break;
3654 case Options::kDynamicLibrary:
3655 case Options::kDynamicBundle:
3656 case Options::kObjectFile:
3657 case Options::kDyld:
3658 case Options::kPreload:
3659 case Options::kKextBundle:
3660 throw "-stack_size option can only be used when linking a main executable";
3662 if ( fStackSize > fStackAddr )
3663 throwf("-stack_size (0x%08llX) must be smaller than -stack_addr (0x%08llX)", fStackSize, fStackAddr);
3666 // check that -allow_stack_execute is only used with main executables
3667 if ( fExecutableStack ) {
3668 switch ( fOutputKind ) {
3669 case Options::kDynamicExecutable:
3670 case Options::kStaticExecutable:
3671 // -allow_stack_execute size only legal when building main executable
3672 break;
3673 case Options::kDynamicLibrary:
3674 case Options::kDynamicBundle:
3675 case Options::kObjectFile:
3676 case Options::kDyld:
3677 case Options::kPreload:
3678 case Options::kKextBundle:
3679 throw "-allow_stack_execute option can only be used when linking a main executable";
3683 // check that -allow_heap_execute is only used with i386 main executables
3684 if ( fDisableNonExecutableHeap ) {
3685 if ( fArchitecture != CPU_TYPE_I386 )
3686 throw "-allow_heap_execute option can only be used when linking for i386";
3687 switch ( fOutputKind ) {
3688 case Options::kDynamicExecutable:
3689 // -allow_heap_execute only legal when building main executable
3690 break;
3691 case Options::kStaticExecutable:
3692 case Options::kDynamicLibrary:
3693 case Options::kDynamicBundle:
3694 case Options::kObjectFile:
3695 case Options::kDyld:
3696 case Options::kPreload:
3697 case Options::kKextBundle:
3698 throw "-allow_heap_execute option can only be used when linking a main executable";
3702 // check -client_name is only used when making a bundle or main executable
3703 if ( fClientName != NULL ) {
3704 switch ( fOutputKind ) {
3705 case Options::kDynamicExecutable:
3706 case Options::kDynamicBundle:
3707 break;
3708 case Options::kStaticExecutable:
3709 case Options::kDynamicLibrary:
3710 case Options::kObjectFile:
3711 case Options::kDyld:
3712 case Options::kPreload:
3713 case Options::kKextBundle:
3714 throw "-client_name can only be used with -bundle";
3718 // check -init is only used when building a dylib
3719 if ( (fInitFunctionName != NULL) && (fOutputKind != Options::kDynamicLibrary) )
3720 throw "-init can only be used with -dynamiclib";
3722 // check -bundle_loader only used with -bundle
3723 if ( (fBundleLoader != NULL) && (fOutputKind != Options::kDynamicBundle) )
3724 throw "-bundle_loader can only be used with -bundle";
3726 // check -dtrace not used with -r
3727 if ( (fDtraceScriptName != NULL) && (fOutputKind == Options::kObjectFile) )
3728 throw "-dtrace can only be used when creating final linked images";
3730 // check -d can only be used with -r
3731 if ( fMakeTentativeDefinitionsReal && (fOutputKind != Options::kObjectFile) )
3732 throw "-d can only be used with -r";
3734 // check that -root_safe is not used with -r
3735 if ( fRootSafe && (fOutputKind == Options::kObjectFile) )
3736 throw "-root_safe cannot be used with -r";
3738 // check that -setuid_safe is not used with -r
3739 if ( fSetuidSafe && (fOutputKind == Options::kObjectFile) )
3740 throw "-setuid_safe cannot be used with -r";
3742 // rdar://problem/4718189 map ObjC class names to new runtime names
3743 bool alterObjC1ClassNamesToObjC2 = false;
3744 switch (fArchitecture) {
3745 case CPU_TYPE_I386:
3746 // i386 only uses new symbols when using objc2 ABI
3747 if ( fObjCABIVersion2Override )
3748 alterObjC1ClassNamesToObjC2 = true;
3749 break;
3750 case CPU_TYPE_POWERPC64:
3751 case CPU_TYPE_X86_64:
3752 case CPU_TYPE_ARM:
3753 alterObjC1ClassNamesToObjC2 = true;
3754 break;
3757 // make sure all required exported symbols exist
3758 std::vector<const char*> impliedExports;
3759 for (NameSet::iterator it=fExportSymbols.regularBegin(); it != fExportSymbols.regularEnd(); ++it) {
3760 const char* name = *it;
3761 const int len = strlen(name);
3762 if ( (strcmp(&name[len-3], ".eh") == 0) || (strncmp(name, ".objc_category_name_", 20) == 0) ) {
3763 // never export .eh symbols
3764 warning("ignoring %s in export list", name);
3766 else if ( (fArchitecture == CPU_TYPE_I386) && !fObjCABIVersion2Override && (strncmp(name, "_OBJC_CLASS_$", 13) == 0) ) {
3767 warning("ignoring Objc2 Class symbol %s in i386 export list", name);
3768 fRemovedExports.insert(name);
3770 else if ( alterObjC1ClassNamesToObjC2 && (strncmp(name, ".objc_class_name_", 17) == 0) ) {
3771 // linking ObjC2 ABI, but have ObjC1 ABI name in export list. Change it to intended name
3772 fRemovedExports.insert(name);
3773 char* temp;
3774 asprintf(&temp, "_OBJC_CLASS_$_%s", &name[17]);
3775 impliedExports.push_back(temp);
3776 asprintf(&temp, "_OBJC_METACLASS_$_%s", &name[17]);
3777 impliedExports.push_back(temp);
3779 else {
3780 fInitialUndefines.push_back(name);
3783 fExportSymbols.remove(fRemovedExports);
3784 for (std::vector<const char*>::iterator it=impliedExports.begin(); it != impliedExports.end(); ++it) {
3785 const char* name = *it;
3786 fExportSymbols.insert(name);
3787 fInitialUndefines.push_back(name);
3790 // make sure all required re-exported symbols exist
3791 for (NameSet::iterator it=fReExportSymbols.regularBegin(); it != fReExportSymbols.regularEnd(); ++it) {
3792 fInitialUndefines.push_back(*it);
3795 // make sure that -init symbol exist
3796 if ( fInitFunctionName != NULL )
3797 fInitialUndefines.push_back(fInitFunctionName);
3799 // make sure every alias base exists
3800 for (std::vector<AliasPair>::iterator it=fAliases.begin(); it != fAliases.end(); ++it) {
3801 fInitialUndefines.push_back(it->realName);
3804 // check custom segments
3805 if ( fCustomSegmentAddresses.size() != 0 ) {
3806 // verify no segment is in zero page
3807 if ( fZeroPageSize != ULLONG_MAX ) {
3808 for (std::vector<SegmentStart>::iterator it = fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
3809 if ( it->address < fZeroPageSize )
3810 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it->name, it->address);
3813 // verify no duplicates
3814 for (std::vector<SegmentStart>::iterator it = fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
3815 for (std::vector<SegmentStart>::iterator it2 = fCustomSegmentAddresses.begin(); it2 != fCustomSegmentAddresses.end(); ++it2) {
3816 if ( (it->address == it2->address) && (it != it2) )
3817 throwf("duplicate -segaddr addresses for %s and %s", it->name, it2->name);
3819 // a custom segment address of zero will disable the use of a zero page
3820 if ( it->address == 0 )
3821 fZeroPageSize = 0;
3825 if ( fZeroPageSize == ULLONG_MAX ) {
3826 // zero page size not specified on command line, set default
3827 switch (fArchitecture) {
3828 case CPU_TYPE_I386:
3829 case CPU_TYPE_POWERPC:
3830 case CPU_TYPE_ARM:
3831 // first 4KB for 32-bit architectures
3832 fZeroPageSize = 0x1000;
3833 break;
3834 case CPU_TYPE_POWERPC64:
3835 // first 4GB for ppc64 on 10.5
3836 if ( fMacVersionMin >= ld::mac10_5 )
3837 fZeroPageSize = 0x100000000ULL;
3838 else
3839 fZeroPageSize = 0x1000; // 10.4 dyld may not be able to handle >4GB zero page
3840 break;
3841 case CPU_TYPE_X86_64:
3842 // first 4GB for x86_64 on all OS's
3843 fZeroPageSize = 0x100000000ULL;
3844 break;
3845 default:
3846 // if -arch not used, default to 4K zero-page
3847 fZeroPageSize = 0x1000;
3850 else {
3851 switch ( fOutputKind ) {
3852 case Options::kDynamicExecutable:
3853 case Options::kStaticExecutable:
3854 // -pagezero_size size only legal when building main executable
3855 break;
3856 case Options::kDynamicLibrary:
3857 case Options::kDynamicBundle:
3858 case Options::kObjectFile:
3859 case Options::kDyld:
3860 case Options::kPreload:
3861 case Options::kKextBundle:
3862 if ( fZeroPageSize != 0 )
3863 throw "-pagezero_size option can only be used when linking a main executable";
3867 // if main executable with custom base address, model zero page as custom segment
3868 if ( (fOutputKind == Options::kDynamicExecutable) && (fBaseAddress != 0) && (fZeroPageSize != 0) ) {
3869 SegmentStart seg;
3870 seg.name = "__PAGEZERO";
3871 seg.address = 0;;
3872 fCustomSegmentAddresses.push_back(seg);
3875 // -dead_strip and -r are incompatible
3876 if ( fDeadStrip && (fOutputKind == Options::kObjectFile) )
3877 throw "-r and -dead_strip cannot be used together";
3879 // can't use -rpath unless targeting 10.5 or later
3880 if ( fRPaths.size() > 0 ) {
3881 if ( !minOS(ld::mac10_5, ld::iPhone2_0) )
3882 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
3883 switch ( fOutputKind ) {
3884 case Options::kDynamicExecutable:
3885 case Options::kDynamicLibrary:
3886 case Options::kDynamicBundle:
3887 break;
3888 case Options::kStaticExecutable:
3889 case Options::kObjectFile:
3890 case Options::kDyld:
3891 case Options::kPreload:
3892 case Options::kKextBundle:
3893 throw "-rpath can only be used when creating a dynamic final linked image";
3897 // check -pie is only used when building a dynamic main executable for 10.5
3898 if ( fPositionIndependentExecutable ) {
3899 switch ( fOutputKind ) {
3900 case Options::kDynamicExecutable:
3901 if ( !minOS(ld::mac10_5, ld::iPhone4_2) ) {
3902 if ( fIPhoneVersionMin == ld::iPhoneVersionUnset )
3903 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
3904 else
3905 throw "-pie can only be used when targeting iOS 4.2 or later";
3907 break;
3908 case Options::kPreload:
3909 break;
3910 case Options::kDynamicLibrary:
3911 case Options::kDynamicBundle:
3912 warning("-pie being ignored. It is only used when linking a main executable");
3913 fPositionIndependentExecutable = false;
3914 break;
3915 case Options::kStaticExecutable:
3916 case Options::kObjectFile:
3917 case Options::kDyld:
3918 case Options::kKextBundle:
3919 throw "-pie can only be used when linking a main executable";
3923 // check -read_only_relocs is not used with x86_64
3924 if ( fAllowTextRelocs ) {
3925 if ( (fArchitecture == CPU_TYPE_X86_64) && (fOutputKind != kKextBundle) ) {
3926 warning("-read_only_relocs cannot be used with x86_64");
3927 fAllowTextRelocs = false;
3931 // check -mark_auto_dead_strip is only used with dylibs
3932 if ( fMarkDeadStrippableDylib ) {
3933 if ( fOutputKind != Options::kDynamicLibrary ) {
3934 warning("-mark_auto_dead_strip can only be used when creating a dylib");
3935 fMarkDeadStrippableDylib = false;
3939 // -force_cpusubtype_ALL is not supported for ARM
3940 if ( fForceSubtypeAll ) {
3941 if ( fArchitecture == CPU_TYPE_ARM ) {
3942 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
3946 // -reexported_symbols_list can only be used with -dynamiclib
3947 if ( !fReExportSymbols.empty() ) {
3948 if ( fOutputKind != Options::kDynamicLibrary )
3949 throw "-reexported_symbols_list can only used used when created dynamic libraries";
3950 if ( !minOS(ld::mac10_7, ld::iPhone4_2) )
3951 throw "targeted OS version does not support -reexported_symbols_list";
3954 // -dyld_env can only be used with main executables
3955 if ( (fOutputKind != Options::kDynamicExecutable) && (fDyldEnvironExtras.size() != 0) )
3956 throw "-dyld_env can only used used when created main executables";
3960 void Options::checkForClassic(int argc, const char* argv[])
3962 // scan options
3963 bool archFound = false;
3964 bool staticFound = false;
3965 bool dtraceFound = false;
3966 bool kextFound = false;
3967 bool rFound = false;
3968 bool creatingMachKernel = false;
3969 bool newLinker = false;
3971 // build command line buffer in case ld crashes
3972 const char* srcRoot = getenv("SRCROOT");
3973 if ( srcRoot != NULL ) {
3974 strlcpy(crashreporterBuffer, "SRCROOT=", crashreporterBufferSize);
3975 strlcat(crashreporterBuffer, srcRoot, crashreporterBufferSize);
3976 strlcat(crashreporterBuffer, "\n", crashreporterBufferSize);
3978 #ifdef LD_VERS
3979 strlcat(crashreporterBuffer, LD_VERS, crashreporterBufferSize);
3980 strlcat(crashreporterBuffer, "\n", crashreporterBufferSize);
3981 #endif
3982 strlcat(crashreporterBuffer, "ld ", crashreporterBufferSize);
3983 for(int i=1; i < argc; ++i) {
3984 strlcat(crashreporterBuffer, argv[i], crashreporterBufferSize);
3985 strlcat(crashreporterBuffer, " ", crashreporterBufferSize);
3988 for(int i=0; i < argc; ++i) {
3989 const char* arg = argv[i];
3990 if ( arg[0] == '-' ) {
3991 if ( strcmp(arg, "-arch") == 0 ) {
3992 parseArch(argv[++i]);
3993 archFound = true;
3995 else if ( strcmp(arg, "-static") == 0 ) {
3996 staticFound = true;
3998 else if ( strcmp(arg, "-kext") == 0 ) {
3999 kextFound = true;
4001 else if ( strcmp(arg, "-dtrace") == 0 ) {
4002 dtraceFound = true;
4004 else if ( strcmp(arg, "-r") == 0 ) {
4005 rFound = true;
4007 else if ( strcmp(arg, "-new_linker") == 0 ) {
4008 newLinker = true;
4010 else if ( strcmp(arg, "-classic_linker") == 0 ) {
4011 // ld_classic does not understand this option, so remove it
4012 for(int j=i; j < argc; ++j)
4013 argv[j] = argv[j+1];
4014 this->gotoClassicLinker(argc-1, argv);
4016 else if ( strcmp(arg, "-o") == 0 ) {
4017 const char* outfile = argv[++i];
4018 if ( (outfile != NULL) && (strstr(outfile, "/mach_kernel") != NULL) )
4019 creatingMachKernel = true;
4024 // -dtrace only supported by new linker
4025 if( dtraceFound )
4026 return;
4028 if( archFound ) {
4029 switch ( fArchitecture ) {
4030 case CPU_TYPE_I386:
4031 case CPU_TYPE_POWERPC:
4032 case CPU_TYPE_ARM:
4033 if ( (staticFound || kextFound) && !newLinker ) {
4034 // this environment variable will disable use of ld_classic for -static links
4035 if ( getenv("LD_NO_CLASSIC_LINKER_STATIC") == NULL ) {
4036 // ld_classic does not support -iphoneos_version_min, so change
4037 for(int j=0; j < argc; ++j) {
4038 if ( (strcmp(argv[j], "-iphoneos_version_min") == 0) || (strcmp(argv[j], "-ios_version_min") == 0) ) {
4039 argv[j] = "-macosx_version_min";
4040 if ( j < argc-1 )
4041 argv[j+1] = "10.5";
4042 break;
4045 // ld classic does not understand -kext (change to -static -r)
4046 if ( kextFound ) {
4047 for(int j=0; j < argc; ++j) {
4048 if ( strcmp(argv[j], "-kext") == 0)
4049 argv[j] = "-r";
4050 else if ( strcmp(argv[j], "-dynamic") == 0)
4051 argv[j] = "-static";
4054 // ld classic does not understand -demangle
4055 for(int j=0; j < argc; ++j) {
4056 if ( strcmp(argv[j], "-demangle") == 0)
4057 argv[j] = "-noprebind";
4059 this->gotoClassicLinker(argc, argv);
4062 break;
4065 else {
4066 // work around for VSPTool
4067 if ( staticFound )
4068 this->gotoClassicLinker(argc, argv);
4073 void Options::gotoClassicLinker(int argc, const char* argv[])
4075 argv[0] = "ld_classic";
4076 // in -v mode, print command line passed to ld_classic
4077 for(int i=0; i < argc; ++i) {
4078 if ( strcmp(argv[i], "-v") == 0 ) {
4079 for(int j=0; j < argc; ++j)
4080 printf("%s ", argv[j]);
4081 printf("\n");
4082 break;
4085 char rawPath[PATH_MAX];
4086 char path[PATH_MAX];
4087 uint32_t bufSize = PATH_MAX;
4088 if ( _NSGetExecutablePath(rawPath, &bufSize) != -1 ) {
4089 if ( realpath(rawPath, path) != NULL ) {
4090 char* lastSlash = strrchr(path, '/');
4091 if ( lastSlash != NULL ) {
4092 strcpy(lastSlash+1, "ld_classic");
4093 argv[0] = path;
4094 execvp(path, (char**)argv);
4098 // in case of error in above, try searching for ld_classic via PATH
4099 execvp(argv[0], (char**)argv);
4100 fprintf(stderr, "can't exec ld_classic\n");
4101 exit(1);