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
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>
28 #include <mach/vm_prot.h>
29 #include <mach-o/dyld.h>
34 #include "configure.h"
36 #include "Architectures.hpp"
37 #include "MachOFileAbstraction.hpp"
39 // upward dependency on lto::version()
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
) {
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
);
76 void throwf(const char* format
, ...)
80 va_start(list
, format
);
81 vasprintf(&p
, format
, list
);
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
),
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),
131 fVersionLoadCommand(true), fFunctionStartsLoadCommand(true),
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();
153 const char* Options::installPath() const
155 if ( fDylibInstallName
!= NULL
)
156 return fDylibInstallName
;
157 else if ( fFinalName
!= NULL
)
164 bool Options::interposable(const char* name
) const
166 switch ( fInterposeMode
) {
169 case kInterposeAllExternal
:
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
)
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
216 case Options::kDynamicLibrary
:
217 case Options::kDynamicBundle
:
218 case Options::kObjectFile
:
220 case Options::kKextBundle
:
227 bool Options::keepRelocations()
229 return fKeepRelocations
;
232 bool Options::warnStabs()
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 ) {
250 if ( strcmp(segName
, "__PAGEZERO") == 0 ) {
253 else if ( strcmp(segName
, "__TEXT") == 0 ) {
254 return VM_PROT_READ
| VM_PROT_EXECUTE
;
256 else if ( strcmp(segName
, "__LINKEDIT") == 0 ) {
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 ) {
275 if ( strcmp(segName
, "__PAGEZERO") == 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 )
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 )
297 // if custom stack in use, model as segment with custom address
298 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
299 return fStackAddr
- fStackSize
;
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 )
309 // if custom stack in use, model as segment with custom address
310 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
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) )
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
;
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
;
352 void Options::loadSymbolOrderFile(const char* fileOfExports
, NameToOrder
& orderMapping
)
354 // read in whole file
355 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
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
);
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
);
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
) {
380 else if ( !isspace(*s
) ) {
386 if ( (*s
== '\n') || (*s
== '\r') ) {
388 // removing any trailing spaces
390 while ( isspace(*last
) ) {
394 orderMapping
[symbolStart
] = ++count
;
400 if ( (*s
== '\n') || (*s
== '\r') )
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
) ) {
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
) {
448 return fExportSymbols
.contains(symbolName
);
449 case kDontExportSome
:
450 return ! fDontExportSymbols
.contains(symbolName
);
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
:
467 case kLocalSymbolsNone
:
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
;
483 case CPU_TYPE_POWERPC
:
485 case CPU_SUBTYPE_POWERPC_750
:
486 fArchitectureName
= "ppc750";
487 fHasPreferredSubType
= true;
489 case CPU_SUBTYPE_POWERPC_7400
:
490 fArchitectureName
= "ppc7400";
491 fHasPreferredSubType
= true;
493 case CPU_SUBTYPE_POWERPC_7450
:
494 fArchitectureName
= "ppc7450";
495 fHasPreferredSubType
= true;
497 case CPU_SUBTYPE_POWERPC_970
:
498 fArchitectureName
= "ppc970";
499 fHasPreferredSubType
= true;
501 case CPU_SUBTYPE_POWERPC_ALL
:
502 fArchitectureName
= "ppc";
503 fHasPreferredSubType
= false;
506 assert(0 && "unknown ppc subtype");
507 fArchitectureName
= "ppc";
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
);
515 warning("-macosx_version_min not specificed, assuming 10.6");
516 fMacVersionMin
= ld::mac10_6
;
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
;
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
);
534 warning("-macosx_version_min not specificed, assuming 10.6");
535 fMacVersionMin
= ld::mac10_6
;
538 if ( !fMakeCompressedDyldInfo
&& (fMacVersionMin
>= ld::mac10_6
) && !fMakeCompressedDyldInfoForceOff
)
539 fMakeCompressedDyldInfo
= true;
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
);
548 warning("-macosx_version_min not specificed, assuming 10.6");
549 fMacVersionMin
= ld::mac10_6
;
552 if ( !fMakeCompressedDyldInfo
&& (fMacVersionMin
>= ld::mac10_6
) && !fMakeCompressedDyldInfoForceOff
)
553 fMakeCompressedDyldInfo
= true;
557 case CPU_SUBTYPE_ARM_V4T
:
558 fArchitectureName
= "armv4t";
559 fHasPreferredSubType
= true;
561 case CPU_SUBTYPE_ARM_V5TEJ
:
562 fArchitectureName
= "armv5";
563 fHasPreferredSubType
= true;
565 case CPU_SUBTYPE_ARM_V6
:
566 fArchitectureName
= "armv6";
567 fHasPreferredSubType
= true;
569 case CPU_SUBTYPE_ARM_V7
:
570 fArchitectureName
= "armv7";
571 fHasPreferredSubType
= true;
574 assert(0 && "unknown arm subtype");
575 fArchitectureName
= "arm";
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
);
586 warning("-macosx_version_min not specificed, assuming 10.6");
587 fMacVersionMin
= ld::mac10_6
;
590 if ( !fMakeCompressedDyldInfo
&& minOS(ld::mac10_6
, ld::iPhone3_1
) && !fMakeCompressedDyldInfoForceOff
)
591 fMakeCompressedDyldInfo
= true;
594 fArchitectureName
= "unknown architecture";
599 void Options::parseArch(const char* arch
)
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;
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
);
683 result
.path
= strdup(possiblePath
);
684 result
.fileLen
= statBuffer
.st_size
;
685 result
.modTime
= statBuffer
.st_mtime
;
692 Options::FileInfo
Options::findLibrary(const char* rootName
, bool dylibsOnly
)
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();
701 const char* dir
= *it
;
702 if ( checkForFile("%s/%s", dir
, rootName
, result
) )
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();
715 const char* dir
= *it
;
716 if ( checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
719 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
720 it
!= fLibrarySearchPaths
.end();
722 const char* dir
= *it
;
723 if ( checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
727 // next look in all directories for just for archives
729 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
730 it
!= fLibrarySearchPaths
.end();
732 const char* dir
= *it
;
733 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
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();
744 const char* dir
= *it
;
745 if ( lookForDylibs
&& checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
747 if ( lookForDylibs
&& checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
749 if ( !dylibsOnly
&& checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
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
) {
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();
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
);
803 result
.path
= strdup(possiblePath
);
804 result
.fileLen
= statBuffer
.st_size
;
805 result
.modTime
= statBuffer
.st_mtime
;
809 // try without suffix
810 if ( suffix
!= NULL
)
811 return findFramework(rootName
, NULL
);
813 throwf("framework not found %s", rootName
);
816 Options::FileInfo
Options::findFile(const char* path
) const
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
;
842 if ( stat(path
, &statBuffer
) == 0 ) {
843 result
.path
= strdup(path
);
844 result
.fileLen
= statBuffer
.st_size
;
845 result
.modTime
= statBuffer
.st_mtime
;
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]);
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
;
867 throwf("file not found: %s", path
);
870 Options::FileInfo
Options::findFileUsingPaths(const char* path
) const
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
)
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.
896 for (std::vector
<const char*>::const_iterator it
= fFrameworkSearchPaths
.begin();
897 it
!= fFrameworkSearchPaths
.end();
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
) )
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();
922 const char* dir
= *it
;
923 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
924 if ( checkForFile("%s/%s", dir
, leafName
, 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
);
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');
952 // ignore lines not starting with 0x number
953 if ( (path
[0] == '0') && (path
[1] == 'x') ) {
955 firstColumAddress
= strtoull(path
, &p
, 16);
956 while ( isspace(*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
) )
965 while ( isspace(*p
) )
968 // remove any trailing whitespace
969 for(char* end
= eol
-1; (end
> p
) && isspace(*end
); --end
)
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
;
978 break; // out of while loop
987 void Options::loadFileList(const char* fileOfPaths
)
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
) {
997 int realFileOfPathsLen
= comma
-fileOfPaths
;
998 char realFileOfPaths
[realFileOfPathsLen
+1];
999 strncpy(realFileOfPaths
,fileOfPaths
, realFileOfPathsLen
);
1000 realFileOfPaths
[realFileOfPathsLen
] = '\0';
1001 file
= fopen(realFileOfPaths
, "r");
1003 throwf("-filelist file not found: %s\n", realFileOfPaths
);
1007 file
= fopen(fileOfPaths
, "r");
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');
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
));
1026 fInputFiles
.push_back(findFile(path
));
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
);
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() )
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
) )
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
1082 while ( *p
!= '\0' ) {
1085 // found beginining [ and ending ]
1086 unsigned char last
= '\0';
1087 for ( const char* s
= b
; s
< e
; ++s
) {
1089 unsigned char next
= *(++s
);
1090 if ( (last
<= c
) && (c
<= next
) )
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
) {
1115 for (const char* t
= s
; *t
!= '\0'; ++t
) {
1116 if ( wildCardMatch(&p
[1], t
) )
1126 if ( ! inCharRange(p
, *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);
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
);
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
);
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
) {
1169 else if ( !isspace(*s
) ) {
1175 if ( (*s
== '\n') || (*s
== '\r') ) {
1177 // removing any trailing spaces
1179 while ( isspace(*last
) ) {
1183 set
.insert(symbolStart
);
1189 if ( (*s
== '\n') || (*s
== '\r') )
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
) ) {
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);
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);
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';
1229 // parse into symbols and add to fAliases
1231 char * const end
= &p
[stat_buf
.st_size
+1];
1232 enum { lineStart
, inRealName
, inBetween
, inAliasName
, inComment
} state
= lineStart
;
1234 for (char* s
= p
; s
< end
; ++s
) {
1240 else if ( !isspace(*s
) ) {
1247 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1251 else if ( isspace(*s
) ) {
1258 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1262 else if ( ! isspace(*s
) ) {
1263 state
= inAliasName
;
1270 // removing any trailing spaces
1272 while ( isspace(*last
) ) {
1276 fAliases
.push_back(pair
);
1279 else if ( *s
== '\n' ) {
1281 // removing any trailing spaces
1283 while ( isspace(*last
) ) {
1287 fAliases
.push_back(pair
);
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
;
1317 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1320 Options::Treatment
Options::parseTreatment(const char* treatment
)
1322 if ( treatment
== NULL
)
1325 if ( strcmp(treatment
, "warning") == 0 )
1327 else if ( strcmp(treatment
, "error") == 0 )
1329 else if ( strcmp(treatment
, "suppress") == 0 )
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));
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
);
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
;
1388 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1391 Options::CommonsMode
Options::parseCommonsTreatment(const char* mode
)
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
;
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
);
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
)
1426 uint64_t result
= strtoull(addr
, &endptr
, 16);
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
)) {
1436 result
|= VM_PROT_READ
;
1439 result
|= VM_PROT_WRITE
;
1442 result
|= VM_PROT_EXECUTE
;
1447 throwf("unknown -segprot lettter in %s", prot
);
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;
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
)
1481 asprintf(&result
, "cstring=%s", orderFileString
);
1482 // convert escaped characters
1484 for(const char* s
=result
; *s
!= '\0'; ++s
, ++d
) {
1522 // hexadecimal value of char
1526 while ( isxdigit(*s
) ) {
1531 value
+= ((toupper(*s
)-'A') + 10);
1538 if ( isdigit(*s
) ) {
1539 // octal value of char
1541 while ( isdigit(*s
) ) {
1542 value
= (value
<< 3) + (*s
-'0');
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);
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);
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
);
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
) {
1586 else if ( !isspace(*s
) || cstring
) {
1592 if ( (*s
== '\n') || (!cstring
&& (*s
== '#')) ) {
1593 bool wasComment
= (*s
== '#');
1595 // removing any trailing spaces
1597 while ( isspace(*last
) ) {
1601 if ( strncmp(symbolStart
, "ppc:", 4) == 0 ) {
1602 if ( fArchitecture
== CPU_TYPE_POWERPC
)
1603 symbolStart
= &symbolStart
[4];
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];
1614 else if ( strncmp(symbolStart
, "i386:", 5) == 0 ) {
1615 if ( fArchitecture
== CPU_TYPE_I386
)
1616 symbolStart
= &symbolStart
[5];
1620 else if ( strncmp(symbolStart
, "x86_64:", 7) == 0 ) {
1621 if ( fArchitecture
== CPU_TYPE_X86_64
)
1622 symbolStart
= &symbolStart
[7];
1626 else if ( strncmp(symbolStart
, "arm:", 4) == 0 ) {
1627 if ( fArchitecture
== CPU_TYPE_ARM
)
1628 symbolStart
= &symbolStart
[4];
1632 if ( symbolStart
!= NULL
) {
1633 char* objFileName
= NULL
;
1634 char* colon
= strstr(symbolStart
, ".o:");
1635 if ( colon
!= NULL
) {
1637 objFileName
= symbolStart
;
1638 symbolStart
= &colon
[3];
1640 // trim leading spaces
1641 while ( isspace(*symbolStart
) )
1643 Options::OrderedSymbol pair
;
1645 pair
.symbolName
= cstringSymbolName(symbolStart
);
1647 pair
.symbolName
= symbolStart
;
1648 pair
.objectFileName
= objFileName
;
1649 fOrderedSymbols
.push_back(pair
);
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");
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
);
1688 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section
, tmp
);
1692 // read in whole file
1693 int fd
= ::open(path
, O_RDONLY
, 0);
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
);
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
);
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
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";
1725 warning("zero is not a valid -sectalign");
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;
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.
1790 fprintf (stderr
, "[Logging ld64 options]\t%s\n", arg
);
1792 if ( (arg
[1] == 'L') || (arg
[1] == 'F') ) {
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");
1804 else if ( strcmp(arg
, "-arch") == 0 ) {
1805 parseArch(argv
[++i
]);
1807 else if ( strcmp(arg
, "-dynamic") == 0 ) {
1810 else if ( strcmp(arg
, "-static") == 0 ) {
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;
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;
1857 // Avoid lazy binding.
1858 else if ( strcmp(arg
, "-bind_at_load") == 0 ) {
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.
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) {
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;
1890 // Library versioning.
1891 else if ( (strcmp(arg
, "-dylib_compatibility_version") == 0)
1892 || (strcmp(arg
, "-compatibility_version") == 0)) {
1893 const char* vers
= argv
[++i
];
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
];
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]);
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]);
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>";
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
;
1969 case kInterposeSome
:
1970 // do nothing, -interposable_list overrides -interposable"
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
);
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;
2031 else if ( strcmp(arg
, "-lazy_library") == 0 ) {
2032 FileInfo info
= findFile(argv
[++i
]);
2033 info
.options
.fLazyLoad
= true;
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;
2045 else if ( strcmp(arg
, "-lazy_framework") == 0 ) {
2046 FileInfo info
= findFramework(argv
[++i
]);
2047 info
.options
.fLazyLoad
= true;
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
2068 else if ( strcmp(arg
, "-read_only_relocs") == 0 ) {
2069 switch ( parseTreatment(argv
[++i
]) ) {
2072 throw "-read_only_relocs missing [ warning | error | suppress ]";
2074 fWarnTextRelocs
= true;
2075 fAllowTextRelocs
= true;
2078 fWarnTextRelocs
= false;
2079 fAllowTextRelocs
= true;
2082 fWarnTextRelocs
= false;
2083 fAllowTextRelocs
= false;
2087 else if ( strcmp(arg
, "-sect_diff_relocs") == 0 ) {
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 ) {
2103 else if ( strcmp(arg
, "-noprebind") == 0 ) {
2107 else if ( strcmp(arg
, "-prebind_allow_overlap") == 0 ) {
2110 else if ( strcmp(arg
, "-prebind_all_twolevel_modules") == 0 ) {
2113 else if ( strcmp(arg
, "-noprebind_all_twolevel_modules") == 0 ) {
2116 else if ( strcmp(arg
, "-nofixprebinding") == 0 ) {
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
];
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 ) {
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
]);
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
];
2180 throw "-seg_addr_table missing argument";
2181 fSegAddrTablePath
= name
;
2183 else if ( strcmp(arg
, "-seg_addr_table_filename") == 0 ) {
2187 else if ( strcmp(arg
, "-segprot") == 0 ) {
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
];
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
];
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]);
2233 else if ( strcmp(arg
, "-sectorder_detail") == 0 ) {
2236 else if ( strcmp(arg
, "-sectobjectsymbols") == 0 ) {
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 ) {
2251 else if ( strcmp(arg
, "-twolevel_namespace_hints") == 0 ) {
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);
2265 else if ( strcmp(arg
, "-multiply_defined_unused") == 0 ) {
2269 else if ( strcmp(arg
, "-nomultidefs") == 0 ) {
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 ) {
2278 // Same output as -y, but output <arg> number of undefined symbols only.
2279 else if ( strcmp(arg
, "-Y") == 0 ) {
2280 //warnObsolete(arg);
2283 // This option affects all objects linked into the final result.
2284 else if ( strcmp(arg
, "-m") == 0 ) {
2287 else if ( (strcmp(arg
, "-why_load") == 0) || (strcmp(arg
, "-whyload") == 0) ) {
2290 else if ( strcmp(arg
, "-why_live") == 0 ) {
2291 const char* name
= argv
[++i
];
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
];
2299 throw "-u missing argument";
2300 fInitialUndefines
.push_back(name
);
2302 else if ( strcmp(arg
, "-U") == 0 ) {
2303 const char* name
= argv
[++i
];
2305 throw "-U missing argument";
2306 fAllowedUndefined
.insert(name
);
2308 else if ( strcmp(arg
, "-s") == 0 ) {
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 ) {
2322 else if ( strcmp(arg
, "-Si") == 0 ) {
2324 fDebugInfoStripping
= Options::kDebugInfoFull
;
2326 else if ( strcmp(arg
, "-b") == 0 ) {
2329 else if ( strcmp(arg
, "-Sn") == 0 ) {
2331 fDebugInfoStripping
= Options::kDebugInfoFull
;
2333 else if ( strcmp(arg
, "-Sp") == 0 ) {
2336 else if ( strcmp(arg
, "-dead_strip") == 0 ) {
2339 else if ( strcmp(arg
, "-no_dead_strip_inits_and_terms") == 0 ) {
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 ) {
2351 else if ( strcmp(arg
, "-headerpad") == 0 ) {
2352 const char* size
= argv
[++i
];
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 ) {
2370 else if ( strcmp(arg
, "-umbrella") == 0 ) {
2371 const char* name
= argv
[++i
];
2373 throw "-umbrella missing argument";
2374 fUmbrellaName
= name
;
2376 else if ( strcmp(arg
, "-allowable_client") == 0 ) {
2377 const char* name
= argv
[++i
];
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
];
2388 throw "-client_name missing argument";
2392 else if ( strcmp(arg
, "-sub_umbrella") == 0 ) {
2393 const char* name
= argv
[++i
];
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
];
2401 throw "-sub_library missing argument";
2402 fSubLibraries
.push_back(name
);
2404 else if ( strcmp(arg
, "-init") == 0 ) {
2405 const char* name
= argv
[++i
];
2407 throw "-init missing argument";
2408 fInitFunctionName
= name
;
2410 else if ( strcmp(arg
, "-dot") == 0 ) {
2411 const char* name
= argv
[++i
];
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 ) {
2428 else if ( strcmp(arg
, "-pause") == 0 ) {
2431 else if ( strcmp(arg
, "-print_statistics") == 0 ) {
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 ) {
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
];
2456 throw "-dtrace missing argument";
2457 fDtraceScriptName
= name
;
2459 else if ( strcmp(arg
, "-root_safe") == 0 ) {
2462 else if ( strcmp(arg
, "-setuid_safe") == 0 ) {
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];
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
];
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 ) {
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;
2522 else if ( strcmp(arg
, "-reexport_library") == 0 ) {
2523 FileInfo info
= findFile(argv
[++i
]);
2524 info
.options
.fReExport
= true;
2527 else if ( strcmp(arg
, "-reexport_framework") == 0 ) {
2528 FileInfo info
= findFramework(argv
[++i
]);
2529 info
.options
.fReExport
= true;
2532 else if ( strncmp(arg
, "-upward-l", 9) == 0 ) {
2533 FileInfo info
= findLibrary(&arg
[9], true);
2534 info
.options
.fUpward
= true;
2537 else if ( strcmp(arg
, "-upward_library") == 0 ) {
2538 FileInfo info
= findFile(argv
[++i
]);
2539 info
.options
.fUpward
= true;
2542 else if ( strcmp(arg
, "-upward_framework") == 0 ) {
2543 FileInfo info
= findFramework(argv
[++i
]);
2544 info
.options
.fUpward
= true;
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 ) {
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
];
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 ) {
2574 else if ( strcmp(arg
, "-seg_page_size") == 0 ) {
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 ) {
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;
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 ) {
2630 if ( fObjCGcOnly
) {
2631 warning("-objc_gc overriding -objc_gc_only");
2632 fObjCGcOnly
= false;
2635 else if ( strcmp(arg
, "-objc_gc_only") == 0 ) {
2638 warning("-objc_gc_only overriding -objc_gc");
2642 else if ( strcmp(arg
, "-demangle") == 0 ) {
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
);
2697 throwf("unknown option: %s", arg
);
2701 FileInfo info
= findFile(arg
);
2702 if ( strcmp(&info
.path
[strlen(info
.path
)-2], ".a") == 0 )
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
];
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
);
2752 warning("path '%s' following -L not a directory", libSearchDir
);
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
];
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
);
2775 warning("path '%s' following -F not a directory", frameworkSearchDir
);
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 ) {
2785 extern const char ldVersionString
[];
2786 fprintf(stderr
, "%s", ldVersionString
);
2787 // if only -v specified, exit cleanly
2789 const char* ltoVers
= lto::version();
2790 if ( ltoVers
!= NULL
)
2791 fprintf(stderr
, "%s\n", ltoVers
);
2795 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
2796 const char* path
= argv
[++i
];
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 ) {
2830 // now merge sdk and library paths to make real search paths
2831 fLibrarySearchPaths
.reserve(libraryPaths
.size()*(fSDKPaths
.size()+1));
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
));
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
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));
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
));
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
2903 fFrameworkSearchPaths
.push_back(frameworkDir
);
2909 fprintf(stderr
,"Library search paths:\n");
2910 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
2911 it
!= fLibrarySearchPaths
.end();
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();
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
)
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
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
:
2997 case Options::kPreload
:
2998 case Options::kObjectFile
:
2999 case Options::kDyld
:
3000 case Options::kStaticExecutable
:
3001 case Options::kKextBundle
:
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;
3020 case Options::kDyld
:
3022 fForFinalLinkedImage
= true;
3025 case Options::kDynamicLibrary
:
3026 case Options::kDynamicBundle
:
3027 case Options::kKextBundle
:
3028 fForFinalLinkedImage
= true;
3031 case Options::kDynamicExecutable
:
3032 case Options::kStaticExecutable
:
3033 case Options::kPreload
:
3034 fLinkingMainExecutable
= true;
3035 fForFinalLinkedImage
= true;
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
);
3054 // if still nothing, set default based on architecture
3055 switch ( fArchitecture
) {
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
);
3064 warning("-macosx_version_min not specificed, assuming 10.6");
3065 fMacVersionMin
= ld::mac10_6
;
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
);
3078 warning("-macosx_version_min not specificed, assuming 10.6");
3079 fMacVersionMin
= ld::mac10_6
;
3084 // architecture will be infered ;ater by examining .o files
3091 // adjust min based on architecture
3092 switch ( fArchitecture
) {
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
;
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
;
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
;
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
;
3123 case CPU_TYPE_POWERPC
:
3127 fOutputKind
= kObjectFile
;
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
)
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
3167 // split seg only supported for ppc, i386, and arm.
3168 switch ( fArchitecture
) {
3169 case CPU_TYPE_POWERPC
:
3171 if ( fOutputKind
!= Options::kDynamicLibrary
)
3173 // make sure read and write segments are proper distance apart
3174 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x10000000) )
3175 fBaseWritableAddress
= fBaseAddress
+ 0x10000000;
3178 if ( fOutputKind
!= Options::kDynamicLibrary
) {
3182 // make sure read and write segments are proper distance apart
3183 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x08000000) )
3184 fBaseWritableAddress
= fBaseAddress
+ 0x08000000;
3190 fBaseWritableAddress
= 0;
3194 // set too-large size
3195 switch ( fArchitecture
) {
3196 case CPU_TYPE_POWERPC
:
3198 fMaxAddress
= 0xFFFFFFFF;
3200 case CPU_TYPE_POWERPC64
:
3201 case CPU_TYPE_X86_64
:
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;
3211 case Options::kStaticExecutable
:
3212 case Options::kObjectFile
:
3213 case Options::kDyld
:
3214 case Options::kPreload
:
3215 case Options::kKextBundle
:
3216 fMaxAddress
= 0xFFFFFFFF;
3219 // range check -seg1addr for ARM
3220 if ( fBaseAddress
> fMaxAddress
) {
3221 warning("ignoring -seg1addr 0x%08llX. Address out of range.", fBaseAddress
);
3227 // <rdar://problem/6138961> -r implies no prebinding for all architectures
3228 if ( fOutputKind
== Options::kObjectFile
)
3231 // disable prebinding depending on arch and min OS version
3233 switch ( fArchitecture
) {
3234 case CPU_TYPE_POWERPC
:
3236 if ( fMacVersionMin
== ld::mac10_4
) {
3237 // in 10.4 only split seg dylibs are prebound
3238 if ( (fOutputKind
!= Options::kDynamicLibrary
) || ! fSplitSegs
)
3241 else if ( fMacVersionMin
>= ld::mac10_5
) {
3242 // in 10.5 nothing is prebound
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
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
3264 case CPU_TYPE_POWERPC64
:
3265 case CPU_TYPE_X86_64
:
3269 switch ( fOutputKind
) {
3270 case Options::kDynamicExecutable
:
3271 case Options::kDynamicLibrary
:
3272 // only main executables and dylibs can be prebound
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
3288 // only prebound images can be split-seg
3289 if ( fSplitSegs
&& !fPrebind
)
3292 // determine if info for shared region should be added
3293 if ( fOutputKind
== Options::kDynamicLibrary
) {
3294 if ( minOS(ld::mac10_5
, ld::iPhone3_1
) )
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;
3311 fNeedsModuleTable
= true; // redo_prebinding requires a module table
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
) {
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;
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;
3340 case CPU_TYPE_POWERPC
:
3341 case CPU_TYPE_POWERPC64
:
3343 fAddCompactUnwindEncoding
= false;
3344 fRemoveDwarfUnwindIfCompactExists
= false;
3347 // if -arch is missing, assume we don't want compact unwind info
3348 fAddCompactUnwindEncoding
= false;
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
:
3373 case Options::kDynamicExecutable
:
3374 case Options::kDynamicLibrary
:
3375 case Options::kDynamicBundle
:
3379 // only use compressed LINKEDIT for final linked images
3380 switch ( fOutputKind
) {
3381 case Options::kDynamicExecutable
:
3382 case Options::kDynamicLibrary
:
3383 case Options::kDynamicBundle
:
3385 case Options::kPreload
:
3386 case Options::kStaticExecutable
:
3387 case Options::kObjectFile
:
3388 case Options::kDyld
:
3389 case Options::kKextBundle
:
3390 fMakeCompressedDyldInfoForceOff
= true;
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
) {
3403 case CPU_TYPE_X86_64
:
3404 if ( fMacVersionMin
< ld::mac10_6
)
3405 fMakeCompressedDyldInfo
= false;
3408 if ( !minOS(ld::mac10_6
, ld::iPhone3_1
) )
3409 fMakeCompressedDyldInfo
= false;
3411 case CPU_TYPE_POWERPC
:
3412 case CPU_TYPE_POWERPC64
:
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
:
3438 case Options::kPreload
:
3439 case Options::kStaticExecutable
:
3440 case Options::kObjectFile
:
3441 case Options::kDyld
:
3442 case Options::kKextBundle
:
3443 fWarnCommons
= false;
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;
3479 case Options::kDynamicExecutable
:
3480 fOutputSlidable
= fPositionIndependentExecutable
;
3482 case Options::kPreload
:
3483 fOutputSlidable
= fPIEOnCommandLine
;
3485 case Options::kDyld
:
3486 case Options::kDynamicLibrary
:
3487 case Options::kDynamicBundle
:
3488 case Options::kKextBundle
:
3489 fOutputSlidable
= true;
3493 // let linker know if thread local variables are supported
3494 if ( fMacVersionMin
>= ld::mac10_7
) {
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;
3507 case Options::kDynamicExecutable
:
3508 case Options::kDyld
:
3509 case Options::kDynamicLibrary
:
3510 case Options::kDynamicBundle
:
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;
3527 case Options::kDynamicExecutable
:
3528 case Options::kDynamicLibrary
:
3529 case Options::kDynamicBundle
:
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
:
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";
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
;
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;
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
;
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], '.');
3586 dot
= &lastSlash
[strlen(lastSlash
)];
3587 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
3588 info
.options
.fReExport
= true;
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
) {
3605 case CPU_TYPE_POWERPC
:
3607 if ( fStackAddr
> 0xFFFFFFFF )
3608 throw "-stack_addr must be < 4G for 32-bit processes";
3610 case CPU_TYPE_POWERPC64
:
3611 case CPU_TYPE_X86_64
:
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
) {
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");
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
;
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
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
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
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
:
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
) {
3746 // i386 only uses new symbols when using objc2 ABI
3747 if ( fObjCABIVersion2Override
)
3748 alterObjC1ClassNamesToObjC2
= true;
3750 case CPU_TYPE_POWERPC64
:
3751 case CPU_TYPE_X86_64
:
3753 alterObjC1ClassNamesToObjC2
= true;
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
);
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
);
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 )
3825 if ( fZeroPageSize
== ULLONG_MAX
) {
3826 // zero page size not specified on command line, set default
3827 switch (fArchitecture
) {
3829 case CPU_TYPE_POWERPC
:
3831 // first 4KB for 32-bit architectures
3832 fZeroPageSize
= 0x1000;
3834 case CPU_TYPE_POWERPC64
:
3835 // first 4GB for ppc64 on 10.5
3836 if ( fMacVersionMin
>= ld::mac10_5
)
3837 fZeroPageSize
= 0x100000000ULL
;
3839 fZeroPageSize
= 0x1000; // 10.4 dyld may not be able to handle >4GB zero page
3841 case CPU_TYPE_X86_64
:
3842 // first 4GB for x86_64 on all OS's
3843 fZeroPageSize
= 0x100000000ULL
;
3846 // if -arch not used, default to 4K zero-page
3847 fZeroPageSize
= 0x1000;
3851 switch ( fOutputKind
) {
3852 case Options::kDynamicExecutable
:
3853 case Options::kStaticExecutable
:
3854 // -pagezero_size size only legal when building main executable
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) ) {
3870 seg
.name
= "__PAGEZERO";
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
:
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";
3905 throw "-pie can only be used when targeting iOS 4.2 or later";
3908 case Options::kPreload
:
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;
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
[])
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
);
3979 strlcat(crashreporterBuffer
, LD_VERS
, crashreporterBufferSize
);
3980 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
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
]);
3995 else if ( strcmp(arg
, "-static") == 0 ) {
3998 else if ( strcmp(arg
, "-kext") == 0 ) {
4001 else if ( strcmp(arg
, "-dtrace") == 0 ) {
4004 else if ( strcmp(arg
, "-r") == 0 ) {
4007 else if ( strcmp(arg
, "-new_linker") == 0 ) {
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
4029 switch ( fArchitecture
) {
4031 case CPU_TYPE_POWERPC
:
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";
4045 // ld classic does not understand -kext (change to -static -r)
4047 for(int j
=0; j
< argc
; ++j
) {
4048 if ( strcmp(argv
[j
], "-kext") == 0)
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
);
4066 // work around for VSPTool
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
]);
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");
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");