1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2005-2011 Apple Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
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), fArchSupportsThumb2(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), fMergeZeroFill(false), 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 fVersionLoadCommand(false), fVersionLoadCommandForcedOn(false),
129 fVersionLoadCommandForcedOff(false), fFunctionStartsLoadCommand(false),
130 fFunctionStartsForcedOn(false), fFunctionStartsForcedOff(false),
131 fCanReExportSymbols(false), fObjcCategoryMerging(true), fPageAlignDataAtoms(false),
132 fDebugInfoStripping(kDebugInfoMinimal
), fTraceOutputFile(NULL
),
133 fMacVersionMin(ld::macVersionUnset
), fIOSVersionMin(ld::iOSVersionUnset
),
134 fSaveTempFiles(false)
136 this->checkForClassic(argc
, argv
);
137 this->parsePreCommandLineEnvironmentSettings();
138 this->parse(argc
, argv
);
139 this->parsePostCommandLineEnvironmentSettings();
140 this->reconfigureDefaults();
141 this->checkIllegalOptionCombinations();
151 const char* Options::installPath() const
153 if ( fDylibInstallName
!= NULL
)
154 return fDylibInstallName
;
155 else if ( fFinalName
!= NULL
)
162 bool Options::interposable(const char* name
) const
164 switch ( fInterposeMode
) {
167 case kInterposeAllExternal
:
170 return fInterposeList
.contains(name
);
172 throw "internal error";
176 bool Options::printWhyLive(const char* symbolName
) const
178 return ( fWhyLive
.find(symbolName
) != fWhyLive
.end() );
182 const char* Options::dotOutputFile()
184 return fDotOutputFile
;
188 bool Options::hasWildCardExportRestrictList() const
190 // has -exported_symbols_list which contains some wildcards
191 return ((fExportMode
== kExportSome
) && fExportSymbols
.hasWildCards());
194 bool Options::hasWeakBitTweaks() const
196 // has -exported_symbols_list which contains some wildcards
197 return (!fForceWeakSymbols
.empty() || !fForceNotWeakSymbols
.empty());
200 bool Options::allGlobalsAreDeadStripRoots() const
202 // -exported_symbols_list means globals are not exported by default
203 if ( fExportMode
== kExportSome
)
206 switch ( fOutputKind
) {
207 case Options::kDynamicExecutable
:
208 case Options::kStaticExecutable
:
209 case Options::kPreload
:
210 // by default unused globals in a main executable are stripped
212 case Options::kDynamicLibrary
:
213 case Options::kDynamicBundle
:
214 case Options::kObjectFile
:
216 case Options::kKextBundle
:
223 bool Options::keepRelocations()
225 return fKeepRelocations
;
228 bool Options::warnStabs()
233 const char* Options::executablePath()
235 return fExecutablePath
;
239 uint32_t Options::initialSegProtection(const char* segName
) const
241 for(std::vector
<Options::SegmentProtect
>::const_iterator it
= fCustomSegmentProtections
.begin(); it
!= fCustomSegmentProtections
.end(); ++it
) {
242 if ( strcmp(it
->name
, segName
) == 0 ) {
246 if ( strcmp(segName
, "__PAGEZERO") == 0 ) {
249 else if ( strcmp(segName
, "__TEXT") == 0 ) {
250 return VM_PROT_READ
| VM_PROT_EXECUTE
;
252 else if ( strcmp(segName
, "__LINKEDIT") == 0 ) {
256 // all others default to read-write
257 return VM_PROT_READ
| VM_PROT_WRITE
;
260 uint32_t Options::maxSegProtection(const char* segName
) const
262 // iPhoneOS always uses same protection for max and initial
263 if ( fIOSVersionMin
!= ld::iOSVersionUnset
)
264 return initialSegProtection(segName
);
266 for(std::vector
<Options::SegmentProtect
>::const_iterator it
= fCustomSegmentProtections
.begin(); it
!= fCustomSegmentProtections
.end(); ++it
) {
267 if ( strcmp(it
->name
, segName
) == 0 ) {
271 if ( strcmp(segName
, "__PAGEZERO") == 0 ) {
274 // all others default to all
275 return VM_PROT_READ
| VM_PROT_WRITE
| VM_PROT_EXECUTE
;
278 uint64_t Options::segPageSize(const char* segName
) const
280 for(std::vector
<SegmentSize
>::const_iterator it
=fCustomSegmentSizes
.begin(); it
!= fCustomSegmentSizes
.end(); ++it
) {
281 if ( strcmp(it
->name
, segName
) == 0 )
284 return fSegmentAlignment
;
287 uint64_t Options::customSegmentAddress(const char* segName
) const
289 for(std::vector
<SegmentStart
>::const_iterator it
=fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
290 if ( strcmp(it
->name
, segName
) == 0 )
293 // if custom stack in use, model as segment with custom address
294 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
295 return fStackAddr
- fStackSize
;
299 bool Options::hasCustomSegmentAddress(const char* segName
) const
301 for(std::vector
<SegmentStart
>::const_iterator it
=fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
302 if ( strcmp(it
->name
, segName
) == 0 )
305 // if custom stack in use, model as segment with custom address
306 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
311 bool Options::hasCustomSectionAlignment(const char* segName
, const char* sectName
) const
313 for (std::vector
<SectionAlignment
>::const_iterator it
= fSectionAlignments
.begin(); it
!= fSectionAlignments
.end(); ++it
) {
314 if ( (strcmp(it
->segmentName
, segName
) == 0) && (strcmp(it
->sectionName
, sectName
) == 0) )
320 uint8_t Options::customSectionAlignment(const char* segName
, const char* sectName
) const
322 for (std::vector
<SectionAlignment
>::const_iterator it
= fSectionAlignments
.begin(); it
!= fSectionAlignments
.end(); ++it
) {
323 if ( (strcmp(it
->segmentName
, segName
) == 0) && (strcmp(it
->sectionName
, sectName
) == 0) )
324 return it
->alignment
;
330 bool Options::hasExportedSymbolOrder()
332 return (fExportSymbolsOrder
.size() > 0);
335 bool Options::exportedSymbolOrder(const char* sym
, unsigned int* order
) const
337 NameToOrder::const_iterator pos
= fExportSymbolsOrder
.find(sym
);
338 if ( pos
!= fExportSymbolsOrder
.end() ) {
339 *order
= pos
->second
;
348 void Options::loadSymbolOrderFile(const char* fileOfExports
, NameToOrder
& orderMapping
)
350 // read in whole file
351 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
353 throwf("can't open -exported_symbols_order file: %s", fileOfExports
);
354 struct stat stat_buf
;
355 ::fstat(fd
, &stat_buf
);
356 char* p
= (char*)malloc(stat_buf
.st_size
);
358 throwf("can't process -exported_symbols_order file: %s", fileOfExports
);
360 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
361 throwf("can't read -exported_symbols_order file: %s", fileOfExports
);
365 // parse into symbols and add to hash_set
366 unsigned int count
= 0;
367 char * const end
= &p
[stat_buf
.st_size
];
368 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
369 char* symbolStart
= NULL
;
370 for (char* s
= p
; s
< end
; ++s
) {
376 else if ( !isspace(*s
) ) {
382 if ( (*s
== '\n') || (*s
== '\r') ) {
384 // removing any trailing spaces
386 while ( isspace(*last
) ) {
390 orderMapping
[symbolStart
] = ++count
;
396 if ( (*s
== '\n') || (*s
== '\r') )
401 if ( state
== inSymbol
) {
402 warning("missing line-end at end of file \"%s\"", fileOfExports
);
403 int len
= end
-symbolStart
+1;
404 char* temp
= new char[len
];
405 strlcpy(temp
, symbolStart
, len
);
407 // remove any trailing spaces
408 char* last
= &temp
[len
-2];
409 while ( isspace(*last
) ) {
413 orderMapping
[temp
] = ++count
;
416 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
419 bool Options::forceWeak(const char* symbolName
) const
421 return fForceWeakSymbols
.contains(symbolName
);
424 bool Options::forceNotWeak(const char* symbolName
) const
426 return fForceNotWeakSymbols
.contains(symbolName
);
429 bool Options::forceWeakNonWildCard(const char* symbolName
) const
431 return fForceWeakSymbols
.containsNonWildcard(symbolName
);
434 bool Options::forceNotWeakNonWildcard(const char* symbolName
) const
436 return fForceNotWeakSymbols
.containsNonWildcard(symbolName
);
440 bool Options::shouldExport(const char* symbolName
) const
442 switch (fExportMode
) {
444 return fExportSymbols
.contains(symbolName
);
445 case kDontExportSome
:
446 return ! fDontExportSymbols
.contains(symbolName
);
450 throw "internal error";
453 bool Options::shouldReExport(const char* symbolName
) const
455 return fReExportSymbols
.contains(symbolName
);
458 bool Options::keepLocalSymbol(const char* symbolName
) const
460 switch (fLocalSymbolHandling
) {
461 case kLocalSymbolsAll
:
463 case kLocalSymbolsNone
:
465 case kLocalSymbolsSelectiveInclude
:
466 return fLocalSymbolsIncluded
.contains(symbolName
);
467 case kLocalSymbolsSelectiveExclude
:
468 return ! fLocalSymbolsExcluded
.contains(symbolName
);
470 throw "internal error";
473 void Options::setArchitecture(cpu_type_t type
, cpu_subtype_t subtype
)
475 fArchitecture
= type
;
476 fSubArchitecture
= subtype
;
478 case CPU_TYPE_POWERPC
:
480 case CPU_SUBTYPE_POWERPC_750
:
481 fArchitectureName
= "ppc750";
482 fHasPreferredSubType
= true;
484 case CPU_SUBTYPE_POWERPC_7400
:
485 fArchitectureName
= "ppc7400";
486 fHasPreferredSubType
= true;
488 case CPU_SUBTYPE_POWERPC_7450
:
489 fArchitectureName
= "ppc7450";
490 fHasPreferredSubType
= true;
492 case CPU_SUBTYPE_POWERPC_970
:
493 fArchitectureName
= "ppc970";
494 fHasPreferredSubType
= true;
496 case CPU_SUBTYPE_POWERPC_ALL
:
497 fArchitectureName
= "ppc";
498 fHasPreferredSubType
= false;
501 assert(0 && "unknown ppc subtype");
502 fArchitectureName
= "ppc";
505 if ( (fMacVersionMin
== ld::macVersionUnset
) && (fOutputKind
!= Options::kObjectFile
) ) {
506 #ifdef DEFAULT_MACOSX_MIN_VERSION
507 warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION
);
508 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
510 warning("-macosx_version_min not specificed, assuming 10.6");
511 fMacVersionMin
= ld::mac10_6
;
515 case CPU_TYPE_POWERPC64
:
516 fArchitectureName
= "ppc64";
517 if ( (fMacVersionMin
== ld::macVersionUnset
) && (fOutputKind
!= Options::kObjectFile
) ) {
518 warning("-macosx_version_min not specificed, assuming 10.5");
519 fMacVersionMin
= ld::mac10_5
;
523 fArchitectureName
= "i386";
524 if ( (fMacVersionMin
== ld::macVersionUnset
) && (fOutputKind
!= Options::kObjectFile
) ) {
525 #ifdef DEFAULT_MACOSX_MIN_VERSION
526 warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION
);
527 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
529 warning("-macosx_version_min not specificed, assuming 10.6");
530 fMacVersionMin
= ld::mac10_6
;
533 if ( !fMakeCompressedDyldInfo
&& (fMacVersionMin
>= ld::mac10_6
) && !fMakeCompressedDyldInfoForceOff
)
534 fMakeCompressedDyldInfo
= true;
536 case CPU_TYPE_X86_64
:
537 fArchitectureName
= "x86_64";
538 if ( (fMacVersionMin
== ld::macVersionUnset
) && (fOutputKind
!= Options::kObjectFile
) ) {
539 #ifdef DEFAULT_MACOSX_MIN_VERSION
540 warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION
);
541 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
543 warning("-macosx_version_min not specificed, assuming 10.6");
544 fMacVersionMin
= ld::mac10_6
;
547 if ( !fMakeCompressedDyldInfo
&& (fMacVersionMin
>= ld::mac10_6
) && !fMakeCompressedDyldInfoForceOff
)
548 fMakeCompressedDyldInfo
= true;
551 fHasPreferredSubType
= true;
552 for (const ARMSubType
* t
=ARMSubTypes
; t
->subTypeName
!= NULL
; ++t
) {
553 if ( t
->subType
== subtype
) {
554 fArchitectureName
= t
->subTypeName
;
555 fArchSupportsThumb2
= t
->supportsThumb2
;
559 assert(fArchitectureName
!= NULL
);
560 if ( (fMacVersionMin
== ld::macVersionUnset
) && (fIOSVersionMin
== ld::iOSVersionUnset
) && (fOutputKind
!= Options::kObjectFile
) ) {
561 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
562 warning("-ios_version_min not specificed, assuming " DEFAULT_IPHONEOS_MIN_VERSION
);
563 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION
);
564 #elif defined(DEFAULT_MACOSX_MIN_VERSION)
565 warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION
);
566 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
568 warning("-macosx_version_min not specificed, assuming 10.6");
569 fMacVersionMin
= ld::mac10_6
;
572 if ( !fMakeCompressedDyldInfo
&& minOS(ld::mac10_6
, ld::iOS_3_1
) && !fMakeCompressedDyldInfoForceOff
)
573 fMakeCompressedDyldInfo
= true;
576 fArchitectureName
= "unknown architecture";
581 void Options::parseArch(const char* arch
)
584 throw "-arch must be followed by an architecture string";
585 fArchitectureName
= arch
;
586 if ( strcmp(arch
, "ppc") == 0 ) {
587 fArchitecture
= CPU_TYPE_POWERPC
;
588 fSubArchitecture
= CPU_SUBTYPE_POWERPC_ALL
;
590 else if ( strcmp(arch
, "ppc64") == 0 ) {
591 fArchitecture
= CPU_TYPE_POWERPC64
;
592 fSubArchitecture
= CPU_SUBTYPE_POWERPC_ALL
;
594 else if ( strcmp(arch
, "i386") == 0 ) {
595 fArchitecture
= CPU_TYPE_I386
;
596 fSubArchitecture
= CPU_SUBTYPE_I386_ALL
;
598 else if ( strcmp(arch
, "x86_64") == 0 ) {
599 fArchitecture
= CPU_TYPE_X86_64
;
600 fSubArchitecture
= CPU_SUBTYPE_X86_64_ALL
;
602 else if ( strcmp(arch
, "arm") == 0 ) {
603 fArchitecture
= CPU_TYPE_ARM
;
604 fSubArchitecture
= CPU_SUBTYPE_ARM_ALL
;
606 // compatibility support for cpu-sub-types
607 else if ( strcmp(arch
, "ppc750") == 0 ) {
608 fArchitecture
= CPU_TYPE_POWERPC
;
609 fSubArchitecture
= CPU_SUBTYPE_POWERPC_750
;
610 fHasPreferredSubType
= true;
612 else if ( strcmp(arch
, "ppc7400") == 0 ) {
613 fArchitecture
= CPU_TYPE_POWERPC
;
614 fSubArchitecture
= CPU_SUBTYPE_POWERPC_7400
;
615 fHasPreferredSubType
= true;
617 else if ( strcmp(arch
, "ppc7450") == 0 ) {
618 fArchitecture
= CPU_TYPE_POWERPC
;
619 fSubArchitecture
= CPU_SUBTYPE_POWERPC_7450
;
620 fHasPreferredSubType
= true;
622 else if ( strcmp(arch
, "ppc970") == 0 ) {
623 fArchitecture
= CPU_TYPE_POWERPC
;
624 fSubArchitecture
= CPU_SUBTYPE_POWERPC_970
;
625 fHasPreferredSubType
= true;
628 for (const ARMSubType
* t
=ARMSubTypes
; t
->subTypeName
!= NULL
; ++t
) {
629 if ( strcmp(t
->subTypeName
,arch
) == 0 ) {
630 fArchitecture
= CPU_TYPE_ARM
;
631 fSubArchitecture
= t
->subType
;
632 fArchSupportsThumb2
= t
->supportsThumb2
;
633 fHasPreferredSubType
= true;
637 throwf("unknown/unsupported architecture name for: -arch %s", arch
);
641 bool Options::checkForFile(const char* format
, const char* dir
, const char* rootName
, FileInfo
& result
) const
643 struct stat statBuffer
;
644 char possiblePath
[strlen(dir
)+strlen(rootName
)+strlen(format
)+8];
645 sprintf(possiblePath
, format
, dir
, rootName
);
646 bool found
= (stat(possiblePath
, &statBuffer
) == 0);
647 if ( fTraceDylibSearching
)
648 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), possiblePath
);
650 result
.path
= strdup(possiblePath
);
651 result
.fileLen
= statBuffer
.st_size
;
652 result
.modTime
= statBuffer
.st_mtime
;
659 Options::FileInfo
Options::findLibrary(const char* rootName
, bool dylibsOnly
)
662 const int rootNameLen
= strlen(rootName
);
663 // if rootName ends in .o there is no .a vs .dylib choice
664 if ( (rootNameLen
> 3) && (strcmp(&rootName
[rootNameLen
-2], ".o") == 0) ) {
665 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
666 it
!= fLibrarySearchPaths
.end();
668 const char* dir
= *it
;
669 if ( checkForFile("%s/%s", dir
, rootName
, result
) )
674 bool lookForDylibs
= ( fOutputKind
!= Options::kDyld
);
675 switch ( fLibrarySearchMode
) {
676 case kSearchAllDirsForDylibsThenAllDirsForArchives
:
677 // first look in all directories for just for dylibs
678 if ( lookForDylibs
) {
679 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
680 it
!= fLibrarySearchPaths
.end();
682 const char* dir
= *it
;
683 if ( checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
686 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
687 it
!= fLibrarySearchPaths
.end();
689 const char* dir
= *it
;
690 if ( checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
694 // next look in all directories for just for archives
696 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
697 it
!= fLibrarySearchPaths
.end();
699 const char* dir
= *it
;
700 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
706 case kSearchDylibAndArchiveInEachDir
:
707 // look in each directory for just for a dylib then for an archive
708 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
709 it
!= fLibrarySearchPaths
.end();
711 const char* dir
= *it
;
712 if ( lookForDylibs
&& checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
714 if ( lookForDylibs
&& checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
716 if ( !dylibsOnly
&& checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
722 throwf("library not found for -l%s", rootName
);
725 Options::FileInfo
Options::findFramework(const char* frameworkName
)
727 if ( frameworkName
== NULL
)
728 throw "-framework missing next argument";
729 char temp
[strlen(frameworkName
)+1];
730 strcpy(temp
, frameworkName
);
731 const char* name
= temp
;
732 const char* suffix
= NULL
;
733 char* comma
= strchr(temp
, ',');
734 if ( comma
!= NULL
) {
738 return findFramework(name
, suffix
);
741 Options::FileInfo
Options::findFramework(const char* rootName
, const char* suffix
)
743 struct stat statBuffer
;
744 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
745 it
!= fFrameworkSearchPaths
.end();
747 // ??? Shouldn't we be using String here and just initializing it?
748 // ??? Use str.c_str () to pull out the string for the stat call.
749 const char* dir
= *it
;
750 char possiblePath
[PATH_MAX
];
751 strcpy(possiblePath
, dir
);
752 strcat(possiblePath
, "/");
753 strcat(possiblePath
, rootName
);
754 strcat(possiblePath
, ".framework/");
755 strcat(possiblePath
, rootName
);
756 if ( suffix
!= NULL
) {
757 char realPath
[PATH_MAX
];
758 // no symlink in framework to suffix variants, so follow main symlink
759 if ( realpath(possiblePath
, realPath
) != NULL
) {
760 strcpy(possiblePath
, realPath
);
761 strcat(possiblePath
, suffix
);
764 bool found
= (stat(possiblePath
, &statBuffer
) == 0);
765 if ( fTraceDylibSearching
)
766 printf("[Logging for XBS]%sfound framework: '%s'\n",
767 (found
? " " : " not "), possiblePath
);
770 result
.path
= strdup(possiblePath
);
771 result
.fileLen
= statBuffer
.st_size
;
772 result
.modTime
= statBuffer
.st_mtime
;
776 // try without suffix
777 if ( suffix
!= NULL
)
778 return findFramework(rootName
, NULL
);
780 throwf("framework not found %s", rootName
);
783 Options::FileInfo
Options::findFile(const char* path
) const
786 struct stat statBuffer
;
788 // if absolute path and not a .o file, the use SDK prefix
789 if ( (path
[0] == '/') && (strcmp(&path
[strlen(path
)-2], ".o") != 0) ) {
790 const int pathLen
= strlen(path
);
791 for (std::vector
<const char*>::const_iterator it
= fSDKPaths
.begin(); it
!= fSDKPaths
.end(); it
++) {
792 // ??? Shouldn't we be using String here?
793 const char* sdkPathDir
= *it
;
794 const int sdkPathDirLen
= strlen(sdkPathDir
);
795 char possiblePath
[sdkPathDirLen
+pathLen
+4];
796 strcpy(possiblePath
, sdkPathDir
);
797 if ( possiblePath
[sdkPathDirLen
-1] == '/' )
798 possiblePath
[sdkPathDirLen
-1] = '\0';
799 strcat(possiblePath
, path
);
800 if ( stat(possiblePath
, &statBuffer
) == 0 ) {
801 result
.path
= strdup(possiblePath
);
802 result
.fileLen
= statBuffer
.st_size
;
803 result
.modTime
= statBuffer
.st_mtime
;
809 if ( stat(path
, &statBuffer
) == 0 ) {
810 result
.path
= strdup(path
);
811 result
.fileLen
= statBuffer
.st_size
;
812 result
.modTime
= statBuffer
.st_mtime
;
816 // try @executable_path substitution
817 if ( (strncmp(path
, "@executable_path/", 17) == 0) && (fExecutablePath
!= NULL
) ) {
818 char newPath
[strlen(fExecutablePath
) + strlen(path
)];
819 strcpy(newPath
, fExecutablePath
);
820 char* addPoint
= strrchr(newPath
,'/');
821 if ( addPoint
!= NULL
)
822 strcpy(&addPoint
[1], &path
[17]);
824 strcpy(newPath
, &path
[17]);
825 if ( stat(newPath
, &statBuffer
) == 0 ) {
826 result
.path
= strdup(newPath
);
827 result
.fileLen
= statBuffer
.st_size
;
828 result
.modTime
= statBuffer
.st_mtime
;
834 throwf("file not found: %s", path
);
837 Options::FileInfo
Options::findFileUsingPaths(const char* path
) const
841 const char* lastSlash
= strrchr(path
, '/');
842 const char* leafName
= (lastSlash
== NULL
) ? path
: &lastSlash
[1];
844 // Is this in a framework?
845 // /path/Foo.framework/Foo ==> true (Foo)
846 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
847 // /path/Foo.framework/Resources/Bar ==> false
848 bool isFramework
= false;
849 if ( lastSlash
!= NULL
) {
850 char frameworkDir
[strlen(leafName
) + 20];
851 strcpy(frameworkDir
, "/");
852 strcat(frameworkDir
, leafName
);
853 strcat(frameworkDir
, ".framework/");
854 if ( strstr(path
, frameworkDir
) != NULL
)
858 // These are abbreviated versions of the routines findFramework and findLibrary above
859 // because we already know the final name of the file that we're looking for and so
860 // don't need to try variations, just paths. We do need to add the additional bits
861 // onto the framework path though.
863 for (std::vector
<const char*>::const_iterator it
= fFrameworkSearchPaths
.begin();
864 it
!= fFrameworkSearchPaths
.end();
866 const char* dir
= *it
;
867 char possiblePath
[PATH_MAX
];
868 strcpy(possiblePath
, dir
);
869 strcat(possiblePath
, "/");
870 strcat(possiblePath
, leafName
);
871 strcat(possiblePath
, ".framework");
873 //fprintf(stderr,"Finding Framework: %s/%s, leafName=%s\n", possiblePath, leafName, leafName);
874 if ( checkForFile("%s/%s", possiblePath
, leafName
, result
) )
879 // if this is a .dylib inside a framework, do not search -L paths
880 // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
881 int leafLen
= strlen(leafName
);
882 bool embeddedDylib
= ( (leafLen
> 6)
883 && (strcmp(&leafName
[leafLen
-6], ".dylib") == 0)
884 && (strstr(path
, ".framework/") != NULL
) );
885 if ( !embeddedDylib
) {
886 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
887 it
!= fLibrarySearchPaths
.end();
889 const char* dir
= *it
;
890 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
891 if ( checkForFile("%s/%s", dir
, leafName
, result
) )
897 // If we didn't find it fall back to findFile.
898 return findFile(path
);
902 void Options::parseSegAddrTable(const char* segAddrPath
, const char* installPth
)
904 FILE* file
= fopen(segAddrPath
, "r");
905 if ( file
== NULL
) {
906 warning("-seg_addr_table file cannot be read: %s", segAddrPath
);
911 uint64_t firstColumAddress
= 0;
912 uint64_t secondColumAddress
= 0;
913 bool hasSecondColumn
= false;
914 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
915 path
[PATH_MAX
-1] = '\0';
916 char* eol
= strchr(path
, '\n');
919 // ignore lines not starting with 0x number
920 if ( (path
[0] == '0') && (path
[1] == 'x') ) {
922 firstColumAddress
= strtoull(path
, &p
, 16);
923 while ( isspace(*p
) )
925 // see if second column is a number
926 if ( (p
[0] == '0') && (p
[1] == 'x') ) {
927 secondColumAddress
= strtoull(p
, &p
, 16);
928 hasSecondColumn
= true;
929 while ( isspace(*p
) )
932 while ( isspace(*p
) )
935 // remove any trailing whitespace
936 for(char* end
= eol
-1; (end
> p
) && isspace(*end
); --end
)
938 // see if this line is for the dylib being linked
939 if ( strcmp(p
, installPth
) == 0 ) {
940 fBaseAddress
= firstColumAddress
;
941 if ( hasSecondColumn
) {
942 fBaseWritableAddress
= secondColumAddress
;
945 break; // out of while loop
954 void Options::loadFileList(const char* fileOfPaths
)
957 const char* comma
= strrchr(fileOfPaths
, ',');
958 const char* prefix
= NULL
;
959 if ( comma
!= NULL
) {
960 // <rdar://problem/5907981> -filelist fails with comma in path
961 file
= fopen(fileOfPaths
, "r");
962 if ( file
== NULL
) {
964 int realFileOfPathsLen
= comma
-fileOfPaths
;
965 char realFileOfPaths
[realFileOfPathsLen
+1];
966 strncpy(realFileOfPaths
,fileOfPaths
, realFileOfPathsLen
);
967 realFileOfPaths
[realFileOfPathsLen
] = '\0';
968 file
= fopen(realFileOfPaths
, "r");
970 throwf("-filelist file not found: %s\n", realFileOfPaths
);
974 file
= fopen(fileOfPaths
, "r");
976 throwf("-filelist file not found: %s\n", fileOfPaths
);
980 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
981 path
[PATH_MAX
-1] = '\0';
982 char* eol
= strchr(path
, '\n');
985 if ( prefix
!= NULL
) {
986 char builtPath
[strlen(prefix
)+strlen(path
)+2];
987 strcpy(builtPath
, prefix
);
988 strcat(builtPath
, "/");
989 strcat(builtPath
, path
);
990 fInputFiles
.push_back(findFile(builtPath
));
993 fInputFiles
.push_back(findFile(path
));
1000 void Options::SetWithWildcards::remove(const NameSet
& toBeRemoved
)
1002 for(NameSet::const_iterator it
=toBeRemoved
.begin(); it
!= toBeRemoved
.end(); ++it
) {
1003 const char* symbolName
= *it
;
1004 NameSet::iterator pos
= fRegular
.find(symbolName
);
1005 if ( pos
!= fRegular
.end() )
1006 fRegular
.erase(pos
);
1010 bool Options::SetWithWildcards::hasWildCards(const char* symbol
)
1012 // an exported symbol name containing *, ?, or [ requires wildcard matching
1013 return ( strpbrk(symbol
, "*?[") != NULL
);
1016 void Options::SetWithWildcards::insert(const char* symbol
)
1018 if ( hasWildCards(symbol
) )
1019 fWildCard
.push_back(symbol
);
1021 fRegular
.insert(symbol
);
1024 bool Options::SetWithWildcards::contains(const char* symbol
) const
1026 // first look at hash table on non-wildcard symbols
1027 if ( fRegular
.find(symbol
) != fRegular
.end() )
1029 // next walk list of wild card symbols looking for a match
1030 for(std::vector
<const char*>::const_iterator it
= fWildCard
.begin(); it
!= fWildCard
.end(); ++it
) {
1031 if ( wildCardMatch(*it
, symbol
) )
1037 bool Options::SetWithWildcards::containsNonWildcard(const char* symbol
) const
1039 // look at hash table on non-wildcard symbols
1040 return ( fRegular
.find(symbol
) != fRegular
.end() );
1045 bool Options::SetWithWildcards::inCharRange(const char*& p
, unsigned char c
) const
1049 while ( *p
!= '\0' ) {
1052 // found beginining [ and ending ]
1053 unsigned char last
= '\0';
1054 for ( const char* s
= b
; s
< e
; ++s
) {
1056 unsigned char next
= *(++s
);
1057 if ( (last
<= c
) && (c
<= next
) )
1074 bool Options::SetWithWildcards::wildCardMatch(const char* pattern
, const char* symbol
) const
1076 const char* s
= symbol
;
1077 for (const char* p
= pattern
; *p
!= '\0'; ++p
) {
1082 for (const char* t
= s
; *t
!= '\0'; ++t
) {
1083 if ( wildCardMatch(&p
[1], t
) )
1093 if ( ! inCharRange(p
, *s
) )
1103 return (*s
== '\0');
1107 void Options::loadExportFile(const char* fileOfExports
, const char* option
, SetWithWildcards
& set
)
1109 if ( fileOfExports
== NULL
)
1110 throwf("missing file after %s", option
);
1111 // read in whole file
1112 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
1114 throwf("can't open %s file: %s", option
, fileOfExports
);
1115 struct stat stat_buf
;
1116 ::fstat(fd
, &stat_buf
);
1117 char* p
= (char*)malloc(stat_buf
.st_size
);
1119 throwf("can't process %s file: %s", option
, fileOfExports
);
1121 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1122 throwf("can't read %s file: %s", option
, fileOfExports
);
1126 // parse into symbols and add to hash_set
1127 char * const end
= &p
[stat_buf
.st_size
];
1128 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1129 char* symbolStart
= NULL
;
1130 for (char* s
= p
; s
< end
; ++s
) {
1136 else if ( !isspace(*s
) ) {
1142 if ( (*s
== '\n') || (*s
== '\r') ) {
1144 // removing any trailing spaces
1146 while ( isspace(*last
) ) {
1150 set
.insert(symbolStart
);
1156 if ( (*s
== '\n') || (*s
== '\r') )
1161 if ( state
== inSymbol
) {
1162 warning("missing line-end at end of file \"%s\"", fileOfExports
);
1163 int len
= end
-symbolStart
+1;
1164 char* temp
= new char[len
];
1165 strlcpy(temp
, symbolStart
, len
);
1167 // remove any trailing spaces
1168 char* last
= &temp
[len
-2];
1169 while ( isspace(*last
) ) {
1176 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
1179 void Options::parseAliasFile(const char* fileOfAliases
)
1181 // read in whole file
1182 int fd
= ::open(fileOfAliases
, O_RDONLY
, 0);
1184 throwf("can't open alias file: %s", fileOfAliases
);
1185 struct stat stat_buf
;
1186 ::fstat(fd
, &stat_buf
);
1187 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1189 throwf("can't process alias file: %s", fileOfAliases
);
1191 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1192 throwf("can't read alias file: %s", fileOfAliases
);
1193 p
[stat_buf
.st_size
] = '\n';
1196 // parse into symbols and add to fAliases
1198 char * const end
= &p
[stat_buf
.st_size
+1];
1199 enum { lineStart
, inRealName
, inBetween
, inAliasName
, inComment
} state
= lineStart
;
1201 for (char* s
= p
; s
< end
; ++s
) {
1207 else if ( !isspace(*s
) ) {
1214 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1218 else if ( isspace(*s
) ) {
1225 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1229 else if ( ! isspace(*s
) ) {
1230 state
= inAliasName
;
1237 // removing any trailing spaces
1239 while ( isspace(*last
) ) {
1243 fAliases
.push_back(pair
);
1246 else if ( *s
== '\n' ) {
1248 // removing any trailing spaces
1250 while ( isspace(*last
) ) {
1254 fAliases
.push_back(pair
);
1265 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
1270 void Options::setUndefinedTreatment(const char* treatment
)
1272 if ( treatment
== NULL
)
1273 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
1275 if ( strcmp(treatment
, "warning") == 0 )
1276 fUndefinedTreatment
= kUndefinedWarning
;
1277 else if ( strcmp(treatment
, "error") == 0 )
1278 fUndefinedTreatment
= kUndefinedError
;
1279 else if ( strcmp(treatment
, "suppress") == 0 )
1280 fUndefinedTreatment
= kUndefinedSuppress
;
1281 else if ( strcmp(treatment
, "dynamic_lookup") == 0 )
1282 fUndefinedTreatment
= kUndefinedDynamicLookup
;
1284 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1287 Options::Treatment
Options::parseTreatment(const char* treatment
)
1289 if ( treatment
== NULL
)
1292 if ( strcmp(treatment
, "warning") == 0 )
1294 else if ( strcmp(treatment
, "error") == 0 )
1296 else if ( strcmp(treatment
, "suppress") == 0 )
1302 void Options::setMacOSXVersionMin(const char* version
)
1304 if ( version
== NULL
)
1305 throw "-macosx_version_min argument missing";
1307 if ( (strncmp(version
, "10.", 3) == 0) && isdigit(version
[3]) ) {
1308 unsigned int minorVersion
= version
[3] - '0';
1309 fMacVersionMin
= (ld::MacVersionMin
)(0x000A0000 | (minorVersion
<< 8));
1312 warning("unknown option to -macosx_version_min, not 10.x");
1316 void Options::setIOSVersionMin(const char* version
)
1318 if ( version
== NULL
)
1319 throw "-ios_version_min argument missing";
1320 if ( ! isdigit(version
[0]) )
1321 throw "-ios_version_min argument is not a number";
1322 if ( version
[1] != '.' )
1323 throw "-ios_version_min argument is missing period as second character";
1324 if ( ! isdigit(version
[2]) )
1325 throw "-ios_version_min argument is not a number";
1327 unsigned int majorVersion
= version
[0] - '0';
1328 unsigned int minorVersion
= version
[2] - '0';
1329 fIOSVersionMin
= (ld::IOSVersionMin
)((majorVersion
<< 16) | (minorVersion
<< 8));
1332 bool Options::minOS(ld::MacVersionMin requiredMacMin
, ld::IOSVersionMin requirediPhoneOSMin
)
1334 if ( fMacVersionMin
!= ld::macVersionUnset
) {
1335 return ( fMacVersionMin
>= requiredMacMin
);
1338 return ( fIOSVersionMin
>= requirediPhoneOSMin
);
1343 void Options::setWeakReferenceMismatchTreatment(const char* treatment
)
1345 if ( treatment
== NULL
)
1346 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1348 if ( strcmp(treatment
, "error") == 0 )
1349 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchError
;
1350 else if ( strcmp(treatment
, "weak") == 0 )
1351 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchWeak
;
1352 else if ( strcmp(treatment
, "non-weak") == 0 )
1353 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchNonWeak
;
1355 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1358 Options::CommonsMode
Options::parseCommonsTreatment(const char* mode
)
1361 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1363 if ( strcmp(mode
, "ignore_dylibs") == 0 )
1364 return kCommonsIgnoreDylibs
;
1365 else if ( strcmp(mode
, "use_dylibs") == 0 )
1366 return kCommonsOverriddenByDylibs
;
1367 else if ( strcmp(mode
, "error") == 0 )
1368 return kCommonsConflictsDylibsError
;
1370 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1373 void Options::addDylibOverride(const char* paths
)
1375 if ( paths
== NULL
)
1376 throw "-dylib_file must followed by two colon separated paths";
1377 const char* colon
= strchr(paths
, ':');
1378 if ( colon
== NULL
)
1379 throw "-dylib_file must followed by two colon separated paths";
1380 int len
= colon
-paths
;
1381 char* target
= new char[len
+2];
1382 strncpy(target
, paths
, len
);
1384 DylibOverride entry
;
1385 entry
.installName
= target
;
1386 entry
.useInstead
= &colon
[1];
1387 fDylibOverrides
.push_back(entry
);
1390 uint64_t Options::parseAddress(const char* addr
)
1393 uint64_t result
= strtoull(addr
, &endptr
, 16);
1397 uint32_t Options::parseProtection(const char* prot
)
1399 uint32_t result
= 0;
1400 for(const char* p
= prot
; *p
!= '\0'; ++p
) {
1401 switch(tolower(*p
)) {
1403 result
|= VM_PROT_READ
;
1406 result
|= VM_PROT_WRITE
;
1409 result
|= VM_PROT_EXECUTE
;
1414 throwf("unknown -segprot lettter in %s", prot
);
1423 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1426 uint32_t Options::parseVersionNumber(const char* versionString
)
1428 unsigned long x
= 0;
1429 unsigned long y
= 0;
1430 unsigned long z
= 0;
1432 x
= strtoul(versionString
, &end
, 10);
1433 if ( *end
== '.' ) {
1434 y
= strtoul(&end
[1], &end
, 10);
1435 if ( *end
== '.' ) {
1436 z
= strtoul(&end
[1], &end
, 10);
1439 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
1440 throwf("malformed version number: %s", versionString
);
1442 return (x
<< 16) | ( y
<< 8 ) | z
;
1445 static const char* cstringSymbolName(const char* orderFileString
)
1448 asprintf(&result
, "cstring=%s", orderFileString
);
1449 // convert escaped characters
1451 for(const char* s
=result
; *s
!= '\0'; ++s
, ++d
) {
1489 // hexadecimal value of char
1493 while ( isxdigit(*s
) ) {
1498 value
+= ((toupper(*s
)-'A') + 10);
1505 if ( isdigit(*s
) ) {
1506 // octal value of char
1508 while ( isdigit(*s
) ) {
1509 value
= (value
<< 3) + (*s
-'0');
1524 void Options::parseOrderFile(const char* path
, bool cstring
)
1526 // order files override auto-ordering
1527 fAutoOrderInitializers
= false;
1529 // read in whole file
1530 int fd
= ::open(path
, O_RDONLY
, 0);
1532 throwf("can't open order file: %s", path
);
1533 struct stat stat_buf
;
1534 ::fstat(fd
, &stat_buf
);
1535 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1537 throwf("can't process order file: %s", path
);
1538 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1539 throwf("can't read order file: %s", path
);
1541 p
[stat_buf
.st_size
] = '\n';
1543 // parse into vector of pairs
1544 char * const end
= &p
[stat_buf
.st_size
+1];
1545 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1546 char* symbolStart
= NULL
;
1547 for (char* s
= p
; s
< end
; ++s
) {
1553 else if ( !isspace(*s
) || cstring
) {
1559 if ( (*s
== '\n') || (!cstring
&& (*s
== '#')) ) {
1560 bool wasComment
= (*s
== '#');
1562 // removing any trailing spaces
1564 while ( isspace(*last
) ) {
1568 if ( strncmp(symbolStart
, "ppc:", 4) == 0 ) {
1569 if ( fArchitecture
== CPU_TYPE_POWERPC
)
1570 symbolStart
= &symbolStart
[4];
1574 // if there is an architecture prefix, only use this symbol it if matches current arch
1575 else if ( strncmp(symbolStart
, "ppc64:", 6) == 0 ) {
1576 if ( fArchitecture
== CPU_TYPE_POWERPC64
)
1577 symbolStart
= &symbolStart
[6];
1581 else if ( strncmp(symbolStart
, "i386:", 5) == 0 ) {
1582 if ( fArchitecture
== CPU_TYPE_I386
)
1583 symbolStart
= &symbolStart
[5];
1587 else if ( strncmp(symbolStart
, "x86_64:", 7) == 0 ) {
1588 if ( fArchitecture
== CPU_TYPE_X86_64
)
1589 symbolStart
= &symbolStart
[7];
1593 else if ( strncmp(symbolStart
, "arm:", 4) == 0 ) {
1594 if ( fArchitecture
== CPU_TYPE_ARM
)
1595 symbolStart
= &symbolStart
[4];
1599 if ( symbolStart
!= NULL
) {
1600 char* objFileName
= NULL
;
1601 char* colon
= strstr(symbolStart
, ".o:");
1602 if ( colon
!= NULL
) {
1604 objFileName
= symbolStart
;
1605 symbolStart
= &colon
[3];
1607 // trim leading spaces
1608 while ( isspace(*symbolStart
) )
1610 Options::OrderedSymbol pair
;
1612 pair
.symbolName
= cstringSymbolName(symbolStart
);
1614 pair
.symbolName
= symbolStart
;
1615 pair
.objectFileName
= objFileName
;
1616 fOrderedSymbols
.push_back(pair
);
1631 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1634 void Options::parseSectionOrderFile(const char* segment
, const char* section
, const char* path
)
1636 if ( (strcmp(section
, "__cstring") == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1637 parseOrderFile(path
, true);
1639 else if ( (strncmp(section
, "__literal",9) == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1640 warning("sorting of __literal[4,8,16] sections not supported");
1643 // ignore section information and append all symbol names to global order file
1644 parseOrderFile(path
, false);
1648 void Options::addSection(const char* segment
, const char* section
, const char* path
)
1650 if ( strlen(segment
) > 16 )
1651 throw "-seccreate segment name max 16 chars";
1652 if ( strlen(section
) > 16 ) {
1653 char* tmp
= strdup(section
);
1655 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section
, tmp
);
1659 // read in whole file
1660 int fd
= ::open(path
, O_RDONLY
, 0);
1662 throwf("can't open -sectcreate file: %s", path
);
1663 struct stat stat_buf
;
1664 ::fstat(fd
, &stat_buf
);
1665 char* p
= (char*)malloc(stat_buf
.st_size
);
1667 throwf("can't process -sectcreate file: %s", path
);
1668 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1669 throwf("can't read -sectcreate file: %s", path
);
1672 // record section to create
1673 ExtraSection info
= { segment
, section
, path
, (uint8_t*)p
, stat_buf
.st_size
};
1674 fExtraSections
.push_back(info
);
1677 void Options::addSectionAlignment(const char* segment
, const char* section
, const char* alignmentStr
)
1679 if ( strlen(segment
) > 16 )
1680 throw "-sectalign segment name max 16 chars";
1681 if ( strlen(section
) > 16 )
1682 throw "-sectalign section name max 16 chars";
1684 // argument to -sectalign is a hexadecimal number
1686 unsigned long value
= strtoul(alignmentStr
, &endptr
, 16);
1687 if ( *endptr
!= '\0')
1688 throw "argument for -sectalign is not a hexadecimal number";
1689 if ( value
> 0x8000 )
1690 throw "argument for -sectalign must be less than or equal to 0x8000";
1692 warning("zero is not a valid -sectalign");
1696 // alignment is power of 2 (e.g. page alignment = 12)
1697 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
1698 if ( (unsigned long)(1 << alignment
) != value
) {
1699 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
1700 segment
, section
, 1 << alignment
);
1703 SectionAlignment info
= { segment
, section
, alignment
};
1704 fSectionAlignments
.push_back(info
);
1707 void Options::addLibrary(const FileInfo
& info
)
1709 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
1710 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
1711 if ( strcmp(info
.path
, fit
->path
) == 0 ) {
1712 // if dylib is specified again but weak, record that it should be weak
1713 if ( info
.options
.fWeakImport
)
1714 fit
->options
.fWeakImport
= true;
1719 fInputFiles
.push_back(info
);
1722 void Options::warnObsolete(const char* arg
)
1724 warning("option %s is obsolete and being ignored", arg
);
1731 // Process all command line arguments.
1733 // The only error checking done here is that each option is valid and if it has arguments
1734 // that they too are valid.
1736 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
1737 // whichever was last on the command line is used.
1739 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
1741 void Options::parse(int argc
, const char* argv
[])
1743 // pass one builds search list from -L and -F options
1744 this->buildSearchPaths(argc
, argv
);
1746 // reduce re-allocations
1747 fInputFiles
.reserve(32);
1749 // pass two parse all other options
1750 for(int i
=1; i
< argc
; ++i
) {
1751 const char* arg
= argv
[i
];
1753 if ( arg
[0] == '-' ) {
1755 // Since we don't care about the files passed, just the option names, we do this here.
1757 fprintf (stderr
, "[Logging ld64 options]\t%s\n", arg
);
1759 if ( (arg
[1] == 'L') || (arg
[1] == 'F') ) {
1762 // previously handled by buildSearchPaths()
1764 // The one gnu style option we have to keep compatibility
1765 // with gcc. Might as well have the single hyphen one as well.
1766 else if ( (strcmp(arg
, "--help") == 0)
1767 || (strcmp(arg
, "-help") == 0)) {
1768 fprintf (stdout
, "ld64: For information on command line options please use 'man ld'.\n");
1771 else if ( strcmp(arg
, "-arch") == 0 ) {
1772 parseArch(argv
[++i
]);
1774 else if ( strcmp(arg
, "-dynamic") == 0 ) {
1777 else if ( strcmp(arg
, "-static") == 0 ) {
1779 if ( (fOutputKind
!= kObjectFile
) && (fOutputKind
!= kKextBundle
) ) {
1780 fOutputKind
= kStaticExecutable
;
1783 else if ( strcmp(arg
, "-dylib") == 0 ) {
1784 fOutputKind
= kDynamicLibrary
;
1786 else if ( strcmp(arg
, "-bundle") == 0 ) {
1787 fOutputKind
= kDynamicBundle
;
1789 else if ( strcmp(arg
, "-dylinker") == 0 ) {
1790 fOutputKind
= kDyld
;
1792 else if ( strcmp(arg
, "-execute") == 0 ) {
1793 if ( fOutputKind
!= kStaticExecutable
)
1794 fOutputKind
= kDynamicExecutable
;
1796 else if ( strcmp(arg
, "-preload") == 0 ) {
1797 fOutputKind
= kPreload
;
1799 else if ( strcmp(arg
, "-r") == 0 ) {
1800 fOutputKind
= kObjectFile
;
1802 else if ( strcmp(arg
, "-kext") == 0 ) {
1803 fOutputKind
= kKextBundle
;
1805 else if ( strcmp(arg
, "-o") == 0 ) {
1806 fOutputFile
= argv
[++i
];
1808 else if ( strncmp(arg
, "-lazy-l", 7) == 0 ) {
1809 FileInfo info
= findLibrary(&arg
[7], true);
1810 info
.options
.fLazyLoad
= true;
1812 fUsingLazyDylibLinking
= true;
1814 else if ( (arg
[1] == 'l') && (strncmp(arg
,"-lazy_",6) !=0) ) {
1815 addLibrary(findLibrary(&arg
[2]));
1817 // This causes a dylib to be weakly bound at
1818 // link time. This corresponds to weak_import.
1819 else if ( strncmp(arg
, "-weak-l", 7) == 0 ) {
1820 FileInfo info
= findLibrary(&arg
[7]);
1821 info
.options
.fWeakImport
= true;
1824 // Avoid lazy binding.
1825 else if ( strcmp(arg
, "-bind_at_load") == 0 ) {
1828 else if ( strcmp(arg
, "-twolevel_namespace") == 0 ) {
1829 fNameSpace
= kTwoLevelNameSpace
;
1831 else if ( strcmp(arg
, "-flat_namespace") == 0 ) {
1832 fNameSpace
= kFlatNameSpace
;
1834 // Also sets a bit to ensure dyld causes everything
1835 // in the namespace to be flat.
1837 else if ( strcmp(arg
, "-force_flat_namespace") == 0 ) {
1838 fNameSpace
= kForceFlatNameSpace
;
1840 // Similar to --whole-archive.
1841 else if ( strcmp(arg
, "-all_load") == 0 ) {
1842 fFullyLoadArchives
= true;
1844 else if ( strcmp(arg
, "-noall_load") == 0) {
1847 // Similar to -all_load
1848 else if ( strcmp(arg
, "-ObjC") == 0 ) {
1849 fLoadAllObjcObjectsFromArchives
= true;
1851 // Similar to -all_load, but for the following archive only.
1852 else if ( strcmp(arg
, "-force_load") == 0 ) {
1853 FileInfo info
= findFile(argv
[++i
]);
1854 info
.options
.fForceLoad
= true;
1857 // Library versioning.
1858 else if ( (strcmp(arg
, "-dylib_compatibility_version") == 0)
1859 || (strcmp(arg
, "-compatibility_version") == 0)) {
1860 const char* vers
= argv
[++i
];
1862 throw "-dylib_compatibility_version missing <version>";
1863 fDylibCompatVersion
= parseVersionNumber(vers
);
1865 else if ( (strcmp(arg
, "-dylib_current_version") == 0)
1866 || (strcmp(arg
, "-current_version") == 0)) {
1867 const char* vers
= argv
[++i
];
1869 throw "-dylib_current_version missing <version>";
1870 fDylibCurrentVersion
= parseVersionNumber(vers
);
1872 else if ( strcmp(arg
, "-sectorder") == 0 ) {
1873 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
1874 throw "-sectorder missing <segment> <section> <file-path>";
1875 parseSectionOrderFile(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1878 else if ( strcmp(arg
, "-order_file") == 0 ) {
1879 parseOrderFile(argv
[++i
], false);
1881 else if ( strcmp(arg
, "-order_file_statistics") == 0 ) {
1882 fPrintOrderFileStatistics
= true;
1884 // ??? Deprecate segcreate.
1885 // -sectcreate puts whole files into a section in the output.
1886 else if ( (strcmp(arg
, "-sectcreate") == 0) || (strcmp(arg
, "-segcreate") == 0) ) {
1887 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
1888 throw "-sectcreate missing <segment> <section> <file-path>";
1889 addSection(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1892 // Since we have a full path in binary/library names we need to be able to override it.
1893 else if ( (strcmp(arg
, "-dylib_install_name") == 0)
1894 || (strcmp(arg
, "-dylinker_install_name") == 0)
1895 || (strcmp(arg
, "-install_name") == 0)) {
1896 fDylibInstallName
= argv
[++i
];
1897 if ( fDylibInstallName
== NULL
)
1898 throw "-install_name missing <path>";
1900 // Sets the base address of the output.
1901 else if ( (strcmp(arg
, "-seg1addr") == 0) || (strcmp(arg
, "-image_base") == 0) ) {
1902 const char* address
= argv
[++i
];
1903 if ( address
== NULL
)
1904 throwf("%s missing <address>", arg
);
1905 fBaseAddress
= parseAddress(address
);
1906 uint64_t temp
= ((fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
1907 if ( fBaseAddress
!= temp
) {
1908 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment
);
1909 fBaseAddress
= temp
;
1912 else if ( strcmp(arg
, "-e") == 0 ) {
1913 fEntryName
= argv
[++i
];
1915 // Same as -@ from the FSF linker.
1916 else if ( strcmp(arg
, "-filelist") == 0 ) {
1917 const char* path
= argv
[++i
];
1918 if ( (path
== NULL
) || (path
[0] == '-') )
1919 throw "-filelist missing <path>";
1922 else if ( strcmp(arg
, "-keep_private_externs") == 0 ) {
1923 fKeepPrivateExterns
= true;
1925 else if ( strcmp(arg
, "-final_output") == 0 ) {
1926 fFinalName
= argv
[++i
];
1928 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
1929 // just ensures that this happens for cross object file boundaries.
1930 else if ( (strcmp(arg
, "-interposable") == 0) || (strcmp(arg
, "-multi_module") == 0)) {
1931 switch ( fInterposeMode
) {
1932 case kInterposeNone
:
1933 case kInterposeAllExternal
:
1934 fInterposeMode
= kInterposeAllExternal
;
1936 case kInterposeSome
:
1937 // do nothing, -interposable_list overrides -interposable"
1941 else if ( strcmp(arg
, "-interposable_list") == 0 ) {
1942 fInterposeMode
= kInterposeSome
;
1943 loadExportFile(argv
[++i
], "-interposable_list", fInterposeList
);
1945 // Default for -interposable/-multi_module/-single_module.
1946 else if ( strcmp(arg
, "-single_module") == 0 ) {
1947 fInterposeMode
= kInterposeNone
;
1949 else if ( strcmp(arg
, "-exported_symbols_list") == 0 ) {
1950 if ( fExportMode
== kDontExportSome
)
1951 throw "can't use -exported_symbols_list and -unexported_symbols_list";
1952 fExportMode
= kExportSome
;
1953 loadExportFile(argv
[++i
], "-exported_symbols_list", fExportSymbols
);
1955 else if ( strcmp(arg
, "-unexported_symbols_list") == 0 ) {
1956 if ( fExportMode
== kExportSome
)
1957 throw "can't use -unexported_symbols_list and -exported_symbols_list";
1958 fExportMode
= kDontExportSome
;
1959 loadExportFile(argv
[++i
], "-unexported_symbols_list", fDontExportSymbols
);
1961 else if ( strcmp(arg
, "-exported_symbol") == 0 ) {
1962 if ( fExportMode
== kDontExportSome
)
1963 throw "can't use -exported_symbol and -unexported_symbols";
1964 fExportMode
= kExportSome
;
1965 fExportSymbols
.insert(argv
[++i
]);
1967 else if ( strcmp(arg
, "-unexported_symbol") == 0 ) {
1968 if ( fExportMode
== kExportSome
)
1969 throw "can't use -unexported_symbol and -exported_symbol";
1970 fExportMode
= kDontExportSome
;
1971 fDontExportSymbols
.insert(argv
[++i
]);
1973 else if ( strcmp(arg
, "-non_global_symbols_no_strip_list") == 0 ) {
1974 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveExclude
)
1975 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
1976 fLocalSymbolHandling
= kLocalSymbolsSelectiveInclude
;
1977 loadExportFile(argv
[++i
], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded
);
1979 else if ( strcmp(arg
, "-non_global_symbols_strip_list") == 0 ) {
1980 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveInclude
)
1981 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
1982 fLocalSymbolHandling
= kLocalSymbolsSelectiveExclude
;
1983 loadExportFile(argv
[++i
], "-non_global_symbols_strip_list", fLocalSymbolsExcluded
);
1986 else if ( strcmp(arg
, "-no_arch_warnings") == 0 ) {
1987 fIgnoreOtherArchFiles
= true;
1989 else if ( strcmp(arg
, "-force_cpusubtype_ALL") == 0 ) {
1990 fForceSubtypeAll
= true;
1991 fAllowCpuSubtypeMismatches
= true;
1993 // Similar to -weak-l but uses the absolute path name to the library.
1994 else if ( strcmp(arg
, "-weak_library") == 0 ) {
1995 FileInfo info
= findFile(argv
[++i
]);
1996 info
.options
.fWeakImport
= true;
1999 else if ( strcmp(arg
, "-lazy_library") == 0 ) {
2000 FileInfo info
= findFile(argv
[++i
]);
2001 info
.options
.fLazyLoad
= true;
2003 fUsingLazyDylibLinking
= true;
2005 else if ( strcmp(arg
, "-framework") == 0 ) {
2006 addLibrary(findFramework(argv
[++i
]));
2008 else if ( strcmp(arg
, "-weak_framework") == 0 ) {
2009 FileInfo info
= findFramework(argv
[++i
]);
2010 info
.options
.fWeakImport
= true;
2013 else if ( strcmp(arg
, "-lazy_framework") == 0 ) {
2014 FileInfo info
= findFramework(argv
[++i
]);
2015 info
.options
.fLazyLoad
= true;
2017 fUsingLazyDylibLinking
= true;
2019 else if ( strcmp(arg
, "-search_paths_first") == 0 ) {
2020 // previously handled by buildSearchPaths()
2022 else if ( strcmp(arg
, "-search_dylibs_first") == 0 ) {
2023 // previously handled by buildSearchPaths()
2025 else if ( strcmp(arg
, "-undefined") == 0 ) {
2026 setUndefinedTreatment(argv
[++i
]);
2028 // Debugging output flag.
2029 else if ( strcmp(arg
, "-arch_multiple") == 0 ) {
2030 fMessagesPrefixedWithArchitecture
= true;
2032 // Specify what to do with relocations in read only
2033 // sections like .text. Could be errors, warnings,
2034 // or suppressed. Currently we do nothing with the
2036 else if ( strcmp(arg
, "-read_only_relocs") == 0 ) {
2037 switch ( parseTreatment(argv
[++i
]) ) {
2040 throw "-read_only_relocs missing [ warning | error | suppress ]";
2042 fWarnTextRelocs
= true;
2043 fAllowTextRelocs
= true;
2046 fWarnTextRelocs
= false;
2047 fAllowTextRelocs
= true;
2050 fWarnTextRelocs
= false;
2051 fAllowTextRelocs
= false;
2055 else if ( strcmp(arg
, "-sect_diff_relocs") == 0 ) {
2059 // Warn, error or make strong a mismatch between weak
2060 // and non-weak references.
2061 else if ( strcmp(arg
, "-weak_reference_mismatches") == 0 ) {
2062 setWeakReferenceMismatchTreatment(argv
[++i
]);
2064 // For a deployment target of 10.3 and earlier ld64 will
2065 // prebind an executable with 0s in all addresses that
2066 // are prebound. This can then be fixed up by update_prebinding
2067 // later. Prebinding is less useful on 10.4 and greater.
2068 else if ( strcmp(arg
, "-prebind") == 0 ) {
2071 else if ( strcmp(arg
, "-noprebind") == 0 ) {
2075 else if ( strcmp(arg
, "-prebind_allow_overlap") == 0 ) {
2078 else if ( strcmp(arg
, "-prebind_all_twolevel_modules") == 0 ) {
2081 else if ( strcmp(arg
, "-noprebind_all_twolevel_modules") == 0 ) {
2084 else if ( strcmp(arg
, "-nofixprebinding") == 0 ) {
2087 // This should probably be deprecated when we respect -L and -F
2088 // when searching for libraries.
2089 else if ( strcmp(arg
, "-dylib_file") == 0 ) {
2090 addDylibOverride(argv
[++i
]);
2092 // What to expand @executable_path to if found in dependent dylibs
2093 else if ( strcmp(arg
, "-executable_path") == 0 ) {
2094 fExecutablePath
= argv
[++i
];
2095 if ( (fExecutablePath
== NULL
) || (fExecutablePath
[0] == '-') )
2096 throw "-executable_path missing <path>";
2097 // if a directory was passed, add / to end
2098 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2099 struct stat statBuffer
;
2100 if ( stat(fExecutablePath
, &statBuffer
) == 0 ) {
2101 if ( (statBuffer
.st_mode
& S_IFMT
) == S_IFDIR
) {
2102 char* pathWithSlash
= new char[strlen(fExecutablePath
)+2];
2103 strcpy(pathWithSlash
, fExecutablePath
);
2104 strcat(pathWithSlash
, "/");
2105 fExecutablePath
= pathWithSlash
;
2109 // Aligns all segments to the power of 2 boundary specified.
2110 else if ( strcmp(arg
, "-segalign") == 0 ) {
2111 const char* size
= argv
[++i
];
2113 throw "-segalign missing <size>";
2114 fSegmentAlignment
= parseAddress(size
);
2115 uint8_t alignment
= (uint8_t)__builtin_ctz(fSegmentAlignment
);
2116 uint32_t p2aligned
= (1 << alignment
);
2117 if ( p2aligned
!= fSegmentAlignment
) {
2118 warning("alignment for -segalign %s is not a power of two, using 0x%X", size
, p2aligned
);
2119 fSegmentAlignment
= p2aligned
;
2122 // Puts a specified segment at a particular address that must
2123 // be a multiple of the segment alignment.
2124 else if ( strcmp(arg
, "-segaddr") == 0 ) {
2126 seg
.name
= argv
[++i
];
2127 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2128 throw "-segaddr missing segName Adddress";
2129 seg
.address
= parseAddress(argv
[++i
]);
2130 uint64_t temp
= seg
.address
& (-4096); // page align
2131 if ( (seg
.address
!= temp
) )
2132 warning("-segaddr %s not page aligned, rounding down", seg
.name
);
2133 fCustomSegmentAddresses
.push_back(seg
);
2135 // ??? Deprecate when we deprecate split-seg.
2136 else if ( strcmp(arg
, "-segs_read_only_addr") == 0 ) {
2137 fBaseAddress
= parseAddress(argv
[++i
]);
2139 // ??? Deprecate when we deprecate split-seg.
2140 else if ( strcmp(arg
, "-segs_read_write_addr") == 0 ) {
2141 fBaseWritableAddress
= parseAddress(argv
[++i
]);
2144 // ??? Deprecate when we get rid of basing at build time.
2145 else if ( strcmp(arg
, "-seg_addr_table") == 0 ) {
2146 const char* name
= argv
[++i
];
2148 throw "-seg_addr_table missing argument";
2149 fSegAddrTablePath
= name
;
2151 else if ( strcmp(arg
, "-seg_addr_table_filename") == 0 ) {
2155 else if ( strcmp(arg
, "-segprot") == 0 ) {
2157 seg
.name
= argv
[++i
];
2158 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) || (argv
[i
+2] == NULL
) )
2159 throw "-segprot missing segName max-prot init-prot";
2160 seg
.max
= parseProtection(argv
[++i
]);
2161 seg
.init
= parseProtection(argv
[++i
]);
2162 fCustomSegmentProtections
.push_back(seg
);
2164 else if ( strcmp(arg
, "-pagezero_size") == 0 ) {
2165 const char* size
= argv
[++i
];
2167 throw "-pagezero_size missing <size>";
2168 fZeroPageSize
= parseAddress(size
);
2169 uint64_t temp
= fZeroPageSize
& (-4096); // page align
2170 if ( (fZeroPageSize
!= temp
) )
2171 warning("-pagezero_size not page aligned, rounding down");
2172 fZeroPageSize
= temp
;
2174 else if ( strcmp(arg
, "-stack_addr") == 0 ) {
2175 const char* address
= argv
[++i
];
2176 if ( address
== NULL
)
2177 throw "-stack_addr missing <address>";
2178 fStackAddr
= parseAddress(address
);
2180 else if ( strcmp(arg
, "-stack_size") == 0 ) {
2181 const char* size
= argv
[++i
];
2183 throw "-stack_size missing <address>";
2184 fStackSize
= parseAddress(size
);
2185 uint64_t temp
= fStackSize
& (-4096); // page align
2186 if ( (fStackSize
!= temp
) )
2187 warning("-stack_size not page aligned, rounding down");
2189 else if ( strcmp(arg
, "-allow_stack_execute") == 0 ) {
2190 fExecutableStack
= true;
2192 else if ( strcmp(arg
, "-allow_heap_execute") == 0 ) {
2193 fDisableNonExecutableHeap
= true;
2195 else if ( strcmp(arg
, "-sectalign") == 0 ) {
2196 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2197 throw "-sectalign missing <segment> <section> <file-path>";
2198 addSectionAlignment(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2201 else if ( strcmp(arg
, "-sectorder_detail") == 0 ) {
2204 else if ( strcmp(arg
, "-sectobjectsymbols") == 0 ) {
2208 else if ( strcmp(arg
, "-bundle_loader") == 0 ) {
2209 fBundleLoader
= argv
[++i
];
2210 if ( (fBundleLoader
== NULL
) || (fBundleLoader
[0] == '-') )
2211 throw "-bundle_loader missing <path>";
2212 FileInfo info
= findFile(fBundleLoader
);
2213 info
.options
.fBundleLoader
= true;
2214 fInputFiles
.push_back(info
);
2216 else if ( strcmp(arg
, "-private_bundle") == 0 ) {
2219 else if ( strcmp(arg
, "-twolevel_namespace_hints") == 0 ) {
2222 // Use this flag to set default behavior for deployement targets.
2223 else if ( strcmp(arg
, "-macosx_version_min") == 0 ) {
2224 setMacOSXVersionMin(argv
[++i
]);
2226 else if ( (strcmp(arg
, "-ios_version_min") == 0) || (strcmp(arg
, "-iphoneos_version_min") == 0) ) {
2227 setIOSVersionMin(argv
[++i
]);
2229 else if ( strcmp(arg
, "-ios_simulator_version_min") == 0 ) {
2230 setIOSVersionMin(argv
[++i
]);
2232 else if ( strcmp(arg
, "-multiply_defined") == 0 ) {
2233 //warnObsolete(arg);
2236 else if ( strcmp(arg
, "-multiply_defined_unused") == 0 ) {
2240 else if ( strcmp(arg
, "-nomultidefs") == 0 ) {
2243 // Display each file in which the argument symbol appears and whether
2244 // the file defines or references it. This option takes an argument
2245 // as -y<symbol> note that there is no space.
2246 else if ( strncmp(arg
, "-y", 2) == 0 ) {
2249 // Same output as -y, but output <arg> number of undefined symbols only.
2250 else if ( strcmp(arg
, "-Y") == 0 ) {
2251 //warnObsolete(arg);
2254 // This option affects all objects linked into the final result.
2255 else if ( strcmp(arg
, "-m") == 0 ) {
2258 else if ( (strcmp(arg
, "-why_load") == 0) || (strcmp(arg
, "-whyload") == 0) ) {
2261 else if ( strcmp(arg
, "-why_live") == 0 ) {
2262 const char* name
= argv
[++i
];
2264 throw "-why_live missing symbol name argument";
2265 fWhyLive
.insert(name
);
2267 else if ( strcmp(arg
, "-u") == 0 ) {
2268 const char* name
= argv
[++i
];
2270 throw "-u missing argument";
2271 fInitialUndefines
.push_back(name
);
2273 else if ( strcmp(arg
, "-U") == 0 ) {
2274 const char* name
= argv
[++i
];
2276 throw "-U missing argument";
2277 fAllowedUndefined
.insert(name
);
2279 else if ( strcmp(arg
, "-s") == 0 ) {
2281 fLocalSymbolHandling
= kLocalSymbolsNone
;
2282 fDebugInfoStripping
= Options::kDebugInfoNone
;
2284 else if ( strcmp(arg
, "-x") == 0 ) {
2285 fLocalSymbolHandling
= kLocalSymbolsNone
;
2287 else if ( strcmp(arg
, "-S") == 0 ) {
2288 fDebugInfoStripping
= Options::kDebugInfoNone
;
2290 else if ( strcmp(arg
, "-X") == 0 ) {
2293 else if ( strcmp(arg
, "-Si") == 0 ) {
2295 fDebugInfoStripping
= Options::kDebugInfoFull
;
2297 else if ( strcmp(arg
, "-b") == 0 ) {
2300 else if ( strcmp(arg
, "-Sn") == 0 ) {
2302 fDebugInfoStripping
= Options::kDebugInfoFull
;
2304 else if ( strcmp(arg
, "-Sp") == 0 ) {
2307 else if ( strcmp(arg
, "-dead_strip") == 0 ) {
2310 else if ( strcmp(arg
, "-no_dead_strip_inits_and_terms") == 0 ) {
2313 else if ( strcmp(arg
, "-w") == 0 ) {
2314 // previously handled by buildSearchPaths()
2316 else if ( strcmp(arg
, "-arch_errors_fatal") == 0 ) {
2317 fErrorOnOtherArchFiles
= true;
2319 else if ( strcmp(arg
, "-M") == 0 ) {
2322 else if ( strcmp(arg
, "-headerpad") == 0 ) {
2323 const char* size
= argv
[++i
];
2325 throw "-headerpad missing argument";
2326 fMinimumHeaderPad
= parseAddress(size
);
2328 else if ( strcmp(arg
, "-headerpad_max_install_names") == 0 ) {
2329 fMaxMinimumHeaderPad
= true;
2331 else if ( strcmp(arg
, "-t") == 0 ) {
2332 fLogAllFiles
= true;
2334 else if ( strcmp(arg
, "-whatsloaded") == 0 ) {
2335 fLogObjectFiles
= true;
2337 else if ( strcmp(arg
, "-A") == 0 ) {
2341 else if ( strcmp(arg
, "-umbrella") == 0 ) {
2342 const char* name
= argv
[++i
];
2344 throw "-umbrella missing argument";
2345 fUmbrellaName
= name
;
2347 else if ( strcmp(arg
, "-allowable_client") == 0 ) {
2348 const char* name
= argv
[++i
];
2351 throw "-allowable_client missing argument";
2353 fAllowableClients
.push_back(name
);
2355 else if ( strcmp(arg
, "-client_name") == 0 ) {
2356 const char* name
= argv
[++i
];
2359 throw "-client_name missing argument";
2363 else if ( strcmp(arg
, "-sub_umbrella") == 0 ) {
2364 const char* name
= argv
[++i
];
2366 throw "-sub_umbrella missing argument";
2367 fSubUmbellas
.push_back(name
);
2369 else if ( strcmp(arg
, "-sub_library") == 0 ) {
2370 const char* name
= argv
[++i
];
2372 throw "-sub_library missing argument";
2373 fSubLibraries
.push_back(name
);
2375 else if ( strcmp(arg
, "-init") == 0 ) {
2376 const char* name
= argv
[++i
];
2378 throw "-init missing argument";
2379 fInitFunctionName
= name
;
2381 else if ( strcmp(arg
, "-dot") == 0 ) {
2382 const char* name
= argv
[++i
];
2384 throw "-dot missing argument";
2385 fDotOutputFile
= name
;
2387 else if ( strcmp(arg
, "-warn_commons") == 0 ) {
2388 fWarnCommons
= true;
2390 else if ( strcmp(arg
, "-commons") == 0 ) {
2391 fCommonsMode
= parseCommonsTreatment(argv
[++i
]);
2393 else if ( strcmp(arg
, "-keep_relocs") == 0 ) {
2394 fKeepRelocations
= true;
2396 else if ( strcmp(arg
, "-warn_stabs") == 0 ) {
2399 else if ( strcmp(arg
, "-pause") == 0 ) {
2402 else if ( strcmp(arg
, "-print_statistics") == 0 ) {
2405 else if ( strcmp(arg
, "-d") == 0 ) {
2406 fMakeTentativeDefinitionsReal
= true;
2408 else if ( strcmp(arg
, "-v") == 0 ) {
2409 // previously handled by buildSearchPaths()
2411 else if ( strcmp(arg
, "-Z") == 0 ) {
2412 // previously handled by buildSearchPaths()
2414 else if ( strcmp(arg
, "-syslibroot") == 0 ) {
2416 // previously handled by buildSearchPaths()
2418 else if ( strcmp(arg
, "-no_uuid") == 0 ) {
2419 fUUIDMode
= kUUIDNone
;
2421 else if ( strcmp(arg
, "-random_uuid") == 0 ) {
2422 fUUIDMode
= kUUIDRandom
;
2424 else if ( strcmp(arg
, "-dtrace") == 0 ) {
2425 const char* name
= argv
[++i
];
2427 throw "-dtrace missing argument";
2428 fDtraceScriptName
= name
;
2430 else if ( strcmp(arg
, "-root_safe") == 0 ) {
2433 else if ( strcmp(arg
, "-setuid_safe") == 0 ) {
2436 else if ( strcmp(arg
, "-alias") == 0 ) {
2437 Options::AliasPair pair
;
2438 pair
.realName
= argv
[++i
];
2439 if ( pair
.realName
== NULL
)
2440 throw "missing argument to -alias";
2441 pair
.alias
= argv
[++i
];
2442 if ( pair
.alias
== NULL
)
2443 throw "missing argument to -alias";
2444 fAliases
.push_back(pair
);
2446 else if ( strcmp(arg
, "-alias_list") == 0 ) {
2447 parseAliasFile(argv
[++i
]);
2449 // put this last so that it does not interfer with other options starting with 'i'
2450 else if ( strncmp(arg
, "-i", 2) == 0 ) {
2451 const char* colon
= strchr(arg
, ':');
2452 if ( colon
== NULL
)
2453 throwf("unknown option: %s", arg
);
2454 Options::AliasPair pair
;
2455 char* temp
= new char[colon
-arg
];
2456 strlcpy(temp
, &arg
[2], colon
-arg
-1);
2457 pair
.realName
= &colon
[1];
2459 fAliases
.push_back(pair
);
2461 else if ( strcmp(arg
, "-save-temps") == 0 ) {
2462 fSaveTempFiles
= true;
2464 else if ( strcmp(arg
, "-rpath") == 0 ) {
2465 const char* path
= argv
[++i
];
2467 throw "missing argument to -rpath";
2468 fRPaths
.push_back(path
);
2470 else if ( strcmp(arg
, "-read_only_stubs") == 0 ) {
2471 fReadOnlyx86Stubs
= true;
2473 else if ( strcmp(arg
, "-slow_stubs") == 0 ) {
2476 else if ( strcmp(arg
, "-map") == 0 ) {
2477 fMapPath
= argv
[++i
];
2478 if ( fMapPath
== NULL
)
2479 throw "missing argument to -map";
2481 else if ( strcmp(arg
, "-pie") == 0 ) {
2482 fPositionIndependentExecutable
= true;
2483 fPIEOnCommandLine
= true;
2485 else if ( strcmp(arg
, "-no_pie") == 0 ) {
2486 fDisablePositionIndependentExecutable
= true;
2488 else if ( strncmp(arg
, "-reexport-l", 11) == 0 ) {
2489 FileInfo info
= findLibrary(&arg
[11], true);
2490 info
.options
.fReExport
= true;
2493 else if ( strcmp(arg
, "-reexport_library") == 0 ) {
2494 FileInfo info
= findFile(argv
[++i
]);
2495 info
.options
.fReExport
= true;
2498 else if ( strcmp(arg
, "-reexport_framework") == 0 ) {
2499 FileInfo info
= findFramework(argv
[++i
]);
2500 info
.options
.fReExport
= true;
2503 else if ( strncmp(arg
, "-upward-l", 9) == 0 ) {
2504 FileInfo info
= findLibrary(&arg
[9], true);
2505 info
.options
.fUpward
= true;
2508 else if ( strcmp(arg
, "-upward_library") == 0 ) {
2509 FileInfo info
= findFile(argv
[++i
]);
2510 info
.options
.fUpward
= true;
2513 else if ( strcmp(arg
, "-upward_framework") == 0 ) {
2514 FileInfo info
= findFramework(argv
[++i
]);
2515 info
.options
.fUpward
= true;
2518 else if ( strcmp(arg
, "-dead_strip_dylibs") == 0 ) {
2519 fDeadStripDylibs
= true;
2521 else if ( strcmp(arg
, "-no_implicit_dylibs") == 0 ) {
2522 fImplicitlyLinkPublicDylibs
= false;
2524 else if ( strcmp(arg
, "-new_linker") == 0 ) {
2527 else if ( strcmp(arg
, "-no_encryption") == 0 ) {
2528 fEncryptable
= false;
2530 else if ( strcmp(arg
, "-no_compact_unwind") == 0 ) {
2531 fAddCompactUnwindEncoding
= false;
2533 else if ( strcmp(arg
, "-mllvm") == 0 ) {
2534 const char* opts
= argv
[++i
];
2536 throw "missing argument to -mllvm";
2537 fLLVMOptions
.push_back(opts
);
2539 else if ( strcmp(arg
, "-no_order_inits") == 0 ) {
2540 fAutoOrderInitializers
= false;
2542 else if ( strcmp(arg
, "-no_order_data") == 0 ) {
2545 else if ( strcmp(arg
, "-seg_page_size") == 0 ) {
2547 seg
.name
= argv
[++i
];
2548 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2549 throw "-seg_page_size missing segName Adddress";
2550 seg
.size
= parseAddress(argv
[++i
]);
2551 uint64_t temp
= seg
.size
& (-4096); // page align
2552 if ( (seg
.size
!= temp
) )
2553 warning("-seg_page_size %s not 4K aligned, rounding down", seg
.name
);
2554 fCustomSegmentSizes
.push_back(seg
);
2556 else if ( strcmp(arg
, "-mark_dead_strippable_dylib") == 0 ) {
2557 fMarkDeadStrippableDylib
= true;
2559 else if ( strcmp(arg
, "-exported_symbols_order") == 0 ) {
2560 loadSymbolOrderFile(argv
[++i
], fExportSymbolsOrder
);
2562 else if ( strcmp(arg
, "-no_compact_linkedit") == 0 ) {
2563 warnObsolete("-no_compact_linkedit");
2565 else if ( strcmp(arg
, "-no_eh_labels") == 0 ) {
2568 else if ( strcmp(arg
, "-warn_compact_unwind") == 0 ) {
2569 fWarnCompactUnwind
= true;
2571 else if ( strcmp(arg
, "-allow_sub_type_mismatches") == 0 ) {
2572 fAllowCpuSubtypeMismatches
= true;
2574 else if ( strcmp(arg
, "-no_zero_fill_sections") == 0 ) {
2575 fOptimizeZeroFill
= false;
2577 else if ( strcmp(arg
, "-merge_zero_fill_sections") == 0 ) {
2578 fMergeZeroFill
= true;
2580 else if ( strcmp(arg
, "-objc_abi_version") == 0 ) {
2581 const char* version
= argv
[++i
];
2582 if ( version
== NULL
)
2583 throw "-objc_abi_version missing version number";
2584 if ( strcmp(version
, "2") == 0 ) {
2585 fObjCABIVersion1Override
= false;
2586 fObjCABIVersion2Override
= true;
2588 else if ( strcmp(version
, "1") == 0 ) {
2589 fObjCABIVersion1Override
= true;
2590 fObjCABIVersion2Override
= false;
2593 warning("ignoring unrecognized argument (%s) to -objc_abi_version", version
);
2595 else if ( strcmp(arg
, "-warn_weak_exports") == 0 ) {
2596 fWarnWeakExports
= true;
2598 else if ( strcmp(arg
, "-objc_gc_compaction") == 0 ) {
2599 fObjcGcCompaction
= true;
2601 else if ( strcmp(arg
, "-objc_gc") == 0 ) {
2603 if ( fObjCGcOnly
) {
2604 warning("-objc_gc overriding -objc_gc_only");
2605 fObjCGcOnly
= false;
2608 else if ( strcmp(arg
, "-objc_gc_only") == 0 ) {
2611 warning("-objc_gc_only overriding -objc_gc");
2615 else if ( strcmp(arg
, "-demangle") == 0 ) {
2618 else if ( strcmp(arg
, "-version_load_command") == 0 ) {
2619 fVersionLoadCommandForcedOn
= true;
2620 fVersionLoadCommandForcedOff
= false;
2622 else if ( strcmp(arg
, "-no_version_load_command") == 0 ) {
2623 fVersionLoadCommandForcedOff
= true;
2624 fVersionLoadCommandForcedOn
= false;
2626 else if ( strcmp(arg
, "-function_starts") == 0 ) {
2627 fFunctionStartsForcedOn
= true;
2628 fFunctionStartsForcedOff
= false;
2630 else if ( strcmp(arg
, "-no_function_starts") == 0 ) {
2631 fFunctionStartsForcedOff
= true;
2632 fFunctionStartsForcedOn
= false;
2634 else if ( strcmp(arg
, "-object_path_lto") == 0 ) {
2635 fTempLtoObjectPath
= argv
[++i
];
2636 if ( fTempLtoObjectPath
== NULL
)
2637 throw "missing argument to -object_path_lto";
2639 else if ( strcmp(arg
, "-no_objc_category_merging") == 0 ) {
2640 fObjcCategoryMerging
= false;
2642 else if ( strcmp(arg
, "-force_symbols_weak_list") == 0 ) {
2643 loadExportFile(argv
[++i
], "-force_symbols_weak_list", fForceWeakSymbols
);
2645 else if ( strcmp(arg
, "-force_symbols_not_weak_list") == 0 ) {
2646 loadExportFile(argv
[++i
], "-force_symbols_not_weak_list", fForceNotWeakSymbols
);
2648 else if ( strcmp(arg
, "-force_symbol_weak") == 0 ) {
2649 const char* symbol
= argv
[++i
];
2650 if ( symbol
== NULL
)
2651 throw "-force_symbol_weak missing <symbol>";
2652 fForceWeakSymbols
.insert(symbol
);
2654 else if ( strcmp(arg
, "-force_symbol_not_weak") == 0 ) {
2655 const char* symbol
= argv
[++i
];
2656 if ( symbol
== NULL
)
2657 throw "-force_symbol_not_weak missing <symbol>";
2658 fForceNotWeakSymbols
.insert(symbol
);
2660 else if ( strcmp(arg
, "-reexported_symbols_list") == 0 ) {
2661 if ( fExportMode
== kExportSome
)
2662 throw "can't use -exported_symbols_list and -reexported_symbols_list";
2663 loadExportFile(argv
[++i
], "-reexported_symbols_list", fReExportSymbols
);
2665 else if ( strcmp(arg
, "-dyld_env") == 0 ) {
2666 const char* envarg
= argv
[++i
];
2667 if ( envarg
== NULL
)
2668 throw "-dyld_env missing ENV=VALUE";
2669 if ( strchr(envarg
, '=') == NULL
)
2670 throw "-dyld_env missing ENV=VALUE";
2671 fDyldEnvironExtras
.push_back(envarg
);
2673 else if ( strcmp(arg
, "-page_align_data_atoms") == 0 ) {
2674 fPageAlignDataAtoms
= true;
2677 throwf("unknown option: %s", arg
);
2681 FileInfo info
= findFile(arg
);
2682 if ( strcmp(&info
.path
[strlen(info
.path
)-2], ".a") == 0 )
2685 fInputFiles
.push_back(info
);
2689 // if a -lazy option was used, implicitly link in lazydylib1.o
2690 if ( fUsingLazyDylibLinking
) {
2691 addLibrary(findLibrary("lazydylib1.o"));
2698 // -syslibroot <path> is used for SDK support.
2699 // The rule is that all search paths (both explicit and default) are
2700 // checked to see if they exist in the SDK. If so, that path is
2701 // replaced with the sdk prefixed path. If not, that search path
2702 // is used as is. If multiple -syslibroot options are specified
2703 // their directory structures are logically overlayed and files
2704 // from sdks specified earlier on the command line used before later ones.
2706 void Options::buildSearchPaths(int argc
, const char* argv
[])
2708 bool addStandardLibraryDirectories
= true;
2709 std::vector
<const char*> libraryPaths
;
2710 std::vector
<const char*> frameworkPaths
;
2711 libraryPaths
.reserve(10);
2712 frameworkPaths
.reserve(10);
2713 // scan through argv looking for -L, -F, -Z, and -syslibroot options
2714 for(int i
=0; i
< argc
; ++i
) {
2715 if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'L') ) {
2716 const char* libSearchDir
= &argv
[i
][2];
2717 // Allow either "-L{path}" or "-L {path}".
2718 if (argv
[i
][2] == '\0') {
2719 // -L {path}. Make sure there is an argument following this.
2720 const char* path
= argv
[++i
];
2722 throw "-L missing argument";
2723 libSearchDir
= path
;
2725 if ( libSearchDir
[0] == '\0' )
2726 throw "-L must be immediately followed by a directory path (no space)";
2727 struct stat statbuf
;
2728 if ( stat(libSearchDir
, &statbuf
) == 0 ) {
2729 if ( statbuf
.st_mode
& S_IFDIR
)
2730 libraryPaths
.push_back(libSearchDir
);
2732 warning("path '%s' following -L not a directory", libSearchDir
);
2735 warning("directory not found for option '-L%s'", libSearchDir
);
2738 else if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'F') ) {
2739 const char* frameworkSearchDir
= &argv
[i
][2];
2740 // Allow either "-F{path}" or "-F {path}".
2741 if (argv
[i
][2] == '\0') {
2742 // -F {path}. Make sure there is an argument following this.
2743 const char* path
= argv
[++i
];
2745 throw "-F missing argument";
2746 frameworkSearchDir
= path
;
2748 if ( frameworkSearchDir
[0] == '\0' )
2749 throw "-F must be immediately followed by a directory path (no space)";
2750 struct stat statbuf
;
2751 if ( stat(frameworkSearchDir
, &statbuf
) == 0 ) {
2752 if ( statbuf
.st_mode
& S_IFDIR
)
2753 frameworkPaths
.push_back(frameworkSearchDir
);
2755 warning("path '%s' following -F not a directory", frameworkSearchDir
);
2758 warning("directory not found for option '-F%s'", frameworkSearchDir
);
2761 else if ( strcmp(argv
[i
], "-Z") == 0 )
2762 addStandardLibraryDirectories
= false;
2763 else if ( strcmp(argv
[i
], "-v") == 0 ) {
2765 extern const char ldVersionString
[];
2766 fprintf(stderr
, "%s", ldVersionString
);
2767 // if only -v specified, exit cleanly
2769 const char* ltoVers
= lto::version();
2770 if ( ltoVers
!= NULL
)
2771 fprintf(stderr
, "%s\n", ltoVers
);
2775 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
2776 const char* path
= argv
[++i
];
2778 throw "-syslibroot missing argument";
2779 fSDKPaths
.push_back(path
);
2781 else if ( strcmp(argv
[i
], "-search_paths_first") == 0 ) {
2782 fLibrarySearchMode
= kSearchDylibAndArchiveInEachDir
;
2784 else if ( strcmp(argv
[i
], "-search_dylibs_first") == 0 ) {
2785 fLibrarySearchMode
= kSearchAllDirsForDylibsThenAllDirsForArchives
;
2787 else if ( strcmp(argv
[i
], "-w") == 0 ) {
2788 sEmitWarnings
= false;
2791 int standardLibraryPathsStartIndex
= libraryPaths
.size();
2792 int standardFrameworkPathsStartIndex
= frameworkPaths
.size();
2793 if ( addStandardLibraryDirectories
) {
2794 libraryPaths
.push_back("/usr/lib");
2795 libraryPaths
.push_back("/usr/local/lib");
2797 frameworkPaths
.push_back("/Library/Frameworks/");
2798 frameworkPaths
.push_back("/System/Library/Frameworks/");
2799 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
2802 // <rdar://problem/5829579> Support for configure based hacks
2803 // if last -syslibroot is /, then ignore all syslibroots
2804 if ( fSDKPaths
.size() > 0 ) {
2805 if ( strcmp(fSDKPaths
.back(), "/") == 0 ) {
2810 // now merge sdk and library paths to make real search paths
2811 fLibrarySearchPaths
.reserve(libraryPaths
.size()*(fSDKPaths
.size()+1));
2813 for (std::vector
<const char*>::iterator it
= libraryPaths
.begin(); it
!= libraryPaths
.end(); ++it
, ++libIndex
) {
2814 const char* libDir
= *it
;
2815 bool sdkOverride
= false;
2816 if ( libDir
[0] == '/' ) {
2817 char betterLibDir
[PATH_MAX
];
2818 if ( strstr(libDir
, "/..") != NULL
) {
2819 if ( realpath(libDir
, betterLibDir
) != NULL
)
2820 libDir
= strdup(betterLibDir
);
2822 const int libDirLen
= strlen(libDir
);
2823 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
2824 const char* sdkDir
= *sdkit
;
2825 const int sdkDirLen
= strlen(sdkDir
);
2826 char newPath
[libDirLen
+ sdkDirLen
+4];
2827 strcpy(newPath
, sdkDir
);
2828 if ( newPath
[sdkDirLen
-1] == '/' )
2829 newPath
[sdkDirLen
-1] = '\0';
2830 strcat(newPath
, libDir
);
2831 struct stat statBuffer
;
2832 if ( stat(newPath
, &statBuffer
) == 0 ) {
2833 fLibrarySearchPaths
.push_back(strdup(newPath
));
2838 if ( !sdkOverride
) {
2839 if ( (libIndex
>= standardLibraryPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
2840 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2841 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2844 fLibrarySearchPaths
.push_back(libDir
);
2849 // now merge sdk and framework paths to make real search paths
2850 fFrameworkSearchPaths
.reserve(frameworkPaths
.size()*(fSDKPaths
.size()+1));
2852 for (std::vector
<const char*>::iterator it
= frameworkPaths
.begin(); it
!= frameworkPaths
.end(); ++it
, ++frameIndex
) {
2853 const char* frameworkDir
= *it
;
2854 bool sdkOverride
= false;
2855 if ( frameworkDir
[0] == '/' ) {
2856 char betterFrameworkDir
[PATH_MAX
];
2857 if ( strstr(frameworkDir
, "/..") != NULL
) {
2858 if ( realpath(frameworkDir
, betterFrameworkDir
) != NULL
)
2859 frameworkDir
= strdup(betterFrameworkDir
);
2861 const int frameworkDirLen
= strlen(frameworkDir
);
2862 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
2863 const char* sdkDir
= *sdkit
;
2864 const int sdkDirLen
= strlen(sdkDir
);
2865 char newPath
[frameworkDirLen
+ sdkDirLen
+4];
2866 strcpy(newPath
, sdkDir
);
2867 if ( newPath
[sdkDirLen
-1] == '/' )
2868 newPath
[sdkDirLen
-1] = '\0';
2869 strcat(newPath
, frameworkDir
);
2870 struct stat statBuffer
;
2871 if ( stat(newPath
, &statBuffer
) == 0 ) {
2872 fFrameworkSearchPaths
.push_back(strdup(newPath
));
2877 if ( !sdkOverride
) {
2878 if ( (frameIndex
>= standardFrameworkPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
2879 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2880 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2883 fFrameworkSearchPaths
.push_back(frameworkDir
);
2889 fprintf(stderr
,"Library search paths:\n");
2890 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
2891 it
!= fLibrarySearchPaths
.end();
2893 fprintf(stderr
,"\t%s\n", *it
);
2894 fprintf(stderr
,"Framework search paths:\n");
2895 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
2896 it
!= fFrameworkSearchPaths
.end();
2898 fprintf(stderr
,"\t%s\n", *it
);
2902 // this is run before the command line is parsed
2903 void Options::parsePreCommandLineEnvironmentSettings()
2905 if ((getenv("LD_TRACE_ARCHIVES") != NULL
)
2906 || (getenv("RC_TRACE_ARCHIVES") != NULL
))
2907 fTraceArchives
= true;
2909 if ((getenv("LD_TRACE_DYLIBS") != NULL
)
2910 || (getenv("RC_TRACE_DYLIBS") != NULL
)) {
2911 fTraceDylibs
= true;
2912 fTraceIndirectDylibs
= true;
2915 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL
) {
2916 fTraceDylibSearching
= true;
2919 if (getenv("LD_PRINT_OPTIONS") != NULL
)
2920 fPrintOptions
= true;
2922 if (fTraceDylibs
|| fTraceArchives
)
2923 fTraceOutputFile
= getenv("LD_TRACE_FILE");
2925 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL
)
2926 fPrintOrderFileStatistics
= true;
2928 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL
)
2931 if (getenv("LD_NO_ENCRYPT") != NULL
)
2932 fEncryptable
= false;
2934 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL
)
2935 fAllowCpuSubtypeMismatches
= true;
2937 sWarningsSideFilePath
= getenv("LD_WARN_FILE");
2939 const char* customDyldPath
= getenv("LD_DYLD_PATH");
2940 if ( customDyldPath
!= NULL
)
2941 fDyldInstallPath
= customDyldPath
;
2945 // this is run after the command line is parsed
2946 void Options::parsePostCommandLineEnvironmentSettings()
2948 // when building a dynamic main executable, default any use of @executable_path to output path
2949 if ( fExecutablePath
== NULL
&& (fOutputKind
== kDynamicExecutable
) ) {
2950 fExecutablePath
= fOutputFile
;
2953 // allow build system to set default seg_addr_table
2954 if ( fSegAddrTablePath
== NULL
)
2955 fSegAddrTablePath
= getenv("LD_SEG_ADDR_TABLE");
2957 // allow build system to turn on prebinding
2959 fPrebind
= ( getenv("LD_PREBIND") != NULL
);
2962 // allow build system to force on dead-code-stripping
2963 if ( !fDeadStrip
) {
2964 if ( getenv("LD_DEAD_STRIP") != NULL
) {
2965 switch (fOutputKind
) {
2966 case Options::kDynamicLibrary
:
2967 case Options::kDynamicExecutable
:
2968 case Options::kDynamicBundle
:
2971 case Options::kPreload
:
2972 case Options::kObjectFile
:
2973 case Options::kDyld
:
2974 case Options::kStaticExecutable
:
2975 case Options::kKextBundle
:
2981 // allow build system to force on -warn_commons
2982 if ( getenv("LD_WARN_COMMONS") != NULL
)
2983 fWarnCommons
= true;
2987 void Options::reconfigureDefaults()
2989 // sync reader options
2990 switch ( fOutputKind
) {
2991 case Options::kObjectFile
:
2992 fForFinalLinkedImage
= false;
2994 case Options::kDyld
:
2996 fForFinalLinkedImage
= true;
2999 case Options::kDynamicLibrary
:
3000 case Options::kDynamicBundle
:
3001 case Options::kKextBundle
:
3002 fForFinalLinkedImage
= true;
3005 case Options::kDynamicExecutable
:
3006 case Options::kStaticExecutable
:
3007 case Options::kPreload
:
3008 fLinkingMainExecutable
= true;
3009 fForFinalLinkedImage
= true;
3014 // set default min OS version
3015 if ( (fMacVersionMin
== ld::macVersionUnset
)
3016 && (fIOSVersionMin
== ld::iOSVersionUnset
) ) {
3017 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
3018 const char* macVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
3019 const char* iPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
3020 const char* iOSVers
= getenv("IOS_DEPLOYMENT_TARGET");
3021 const char* iOSSimulatorVers
= getenv("IOS_SIMULATOR_DEPLOYMENT_TARGET");
3022 if ( macVers
!= NULL
)
3023 setMacOSXVersionMin(macVers
);
3024 else if ( iPhoneVers
!= NULL
)
3025 setIOSVersionMin(iPhoneVers
);
3026 else if ( iOSVers
!= NULL
)
3027 setIOSVersionMin(iOSVers
);
3028 else if ( iOSSimulatorVers
!= NULL
)
3029 setIOSVersionMin(iOSSimulatorVers
);
3031 // if still nothing, set default based on architecture
3032 switch ( fArchitecture
) {
3034 case CPU_TYPE_X86_64
:
3035 case CPU_TYPE_POWERPC
:
3036 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
3037 #ifdef DEFAULT_MACOSX_MIN_VERSION
3038 warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION
);
3039 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
3041 warning("-macosx_version_min not specificed, assuming 10.6");
3042 fMacVersionMin
= ld::mac10_6
;
3047 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
3048 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
3049 warning("-ios_version_min not specificed, assuming " DEFAULT_IPHONEOS_MIN_VERSION
);
3050 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION
);
3051 #elif defined(DEFAULT_MACOSX_MIN_VERSION)
3052 warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION
);
3053 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
3055 warning("-macosx_version_min not specificed, assuming 10.6");
3056 fMacVersionMin
= ld::mac10_6
;
3061 // architecture will be infered ;ater by examining .o files
3068 // adjust min based on architecture
3069 switch ( fArchitecture
) {
3071 if ( (fMacVersionMin
< ld::mac10_4
) && (fIOSVersionMin
== ld::iOSVersionUnset
) ) {
3072 //warning("-macosx_version_min should be 10.4 or later for i386");
3073 fMacVersionMin
= ld::mac10_4
;
3076 case CPU_TYPE_POWERPC64
:
3077 if ( fMacVersionMin
< ld::mac10_4
) {
3078 //warning("-macosx_version_min should be 10.4 or later for ppc64");
3079 fMacVersionMin
= ld::mac10_4
;
3082 case CPU_TYPE_X86_64
:
3083 if ( fMacVersionMin
< ld::mac10_4
) {
3084 //warning("-macosx_version_min should be 10.4 or later for x86_64");
3085 fMacVersionMin
= ld::mac10_4
;
3090 // adjust kext type based on architecture
3091 if ( fOutputKind
== kKextBundle
) {
3092 switch ( fArchitecture
) {
3093 case CPU_TYPE_X86_64
:
3094 // x86_64 uses new MH_KEXT_BUNDLE type
3095 fMakeCompressedDyldInfo
= false;
3096 fMakeCompressedDyldInfoForceOff
= true;
3097 fAllowTextRelocs
= true;
3098 fUndefinedTreatment
= kUndefinedDynamicLookup
;
3101 if ( fIOSVersionMin
>= ld::iOS_5_0
) {
3102 // iOS 5.0 and later use new MH_KEXT_BUNDLE type
3103 fMakeCompressedDyldInfo
= false;
3104 fMakeCompressedDyldInfoForceOff
= true;
3105 fAllowTextRelocs
= true;
3106 fUndefinedTreatment
= kUndefinedDynamicLookup
;
3109 // else use object file
3110 case CPU_TYPE_POWERPC
:
3113 fOutputKind
= kObjectFile
;
3118 // disable implicit dylibs when targeting 10.3
3119 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
3120 if ( !minOS(ld::mac10_4
, ld::iOS_2_0
) )
3121 fImplicitlyLinkPublicDylibs
= false;
3124 // allow build system to force linker to ignore -prebind
3125 if ( getenv("LD_FORCE_NO_PREBIND") != NULL
)
3128 // allow build system to force linker to ignore -seg_addr_table
3129 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL
)
3130 fSegAddrTablePath
= NULL
;
3132 // check for base address specified externally
3133 if ( (fSegAddrTablePath
!= NULL
) && (fOutputKind
== Options::kDynamicLibrary
) ) {
3134 parseSegAddrTable(fSegAddrTablePath
, this->installPath());
3135 // HACK to support seg_addr_table entries that are physical paths instead of install paths
3136 if ( fBaseAddress
== 0 ) {
3137 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
3138 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.4.dylib");
3139 if ( fBaseAddress
== 0 )
3140 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.9.dylib");
3143 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
3144 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libz.1.2.3.dylib");
3146 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
3147 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libutil1.0.dylib");
3151 // split segs only allowed for dylibs
3153 // split seg only supported for ppc, i386, and arm.
3154 switch ( fArchitecture
) {
3155 case CPU_TYPE_POWERPC
:
3157 if ( fOutputKind
!= Options::kDynamicLibrary
)
3159 // make sure read and write segments are proper distance apart
3160 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x10000000) )
3161 fBaseWritableAddress
= fBaseAddress
+ 0x10000000;
3164 if ( fOutputKind
!= Options::kDynamicLibrary
) {
3168 // make sure read and write segments are proper distance apart
3169 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x08000000) )
3170 fBaseWritableAddress
= fBaseAddress
+ 0x08000000;
3176 fBaseWritableAddress
= 0;
3180 // set too-large size
3181 switch ( fArchitecture
) {
3182 case CPU_TYPE_POWERPC
:
3184 fMaxAddress
= 0xFFFFFFFF;
3186 case CPU_TYPE_POWERPC64
:
3187 case CPU_TYPE_X86_64
:
3190 switch ( fOutputKind
) {
3191 case Options::kDynamicExecutable
:
3192 case Options::kDynamicLibrary
:
3193 case Options::kDynamicBundle
:
3194 // user land code is limited to low 1GB
3195 fMaxAddress
= 0x2FFFFFFF;
3197 case Options::kStaticExecutable
:
3198 case Options::kObjectFile
:
3199 case Options::kDyld
:
3200 case Options::kPreload
:
3201 case Options::kKextBundle
:
3202 fMaxAddress
= 0xFFFFFFFF;
3205 // range check -seg1addr for ARM
3206 if ( fBaseAddress
> fMaxAddress
) {
3207 warning("ignoring -seg1addr 0x%08llX. Address out of range.", fBaseAddress
);
3213 // <rdar://problem/6138961> -r implies no prebinding for all architectures
3214 if ( fOutputKind
== Options::kObjectFile
)
3217 // disable prebinding depending on arch and min OS version
3219 switch ( fArchitecture
) {
3220 case CPU_TYPE_POWERPC
:
3222 if ( fMacVersionMin
== ld::mac10_4
) {
3223 // in 10.4 only split seg dylibs are prebound
3224 if ( (fOutputKind
!= Options::kDynamicLibrary
) || ! fSplitSegs
)
3227 else if ( fMacVersionMin
>= ld::mac10_5
) {
3228 // in 10.5 nothing is prebound
3231 else if ( fIOSVersionMin
!= ld::iOSVersionUnset
) {
3232 // nothing in simulator is prebound
3236 // in 10.3 and earlier only dylibs and main executables could be prebound
3237 switch ( fOutputKind
) {
3238 case Options::kDynamicExecutable
:
3239 case Options::kDynamicLibrary
:
3240 // only main executables and dylibs can be prebound
3242 case Options::kStaticExecutable
:
3243 case Options::kDynamicBundle
:
3244 case Options::kObjectFile
:
3245 case Options::kDyld
:
3246 case Options::kPreload
:
3247 case Options::kKextBundle
:
3248 // disable prebinding for everything else
3254 case CPU_TYPE_POWERPC64
:
3255 case CPU_TYPE_X86_64
:
3259 switch ( fOutputKind
) {
3260 case Options::kDynamicExecutable
:
3261 case Options::kDynamicLibrary
:
3262 // only main executables and dylibs can be prebound
3264 case Options::kStaticExecutable
:
3265 case Options::kDynamicBundle
:
3266 case Options::kObjectFile
:
3267 case Options::kDyld
:
3268 case Options::kPreload
:
3269 case Options::kKextBundle
:
3270 // disable prebinding for everything else
3278 // only prebound images can be split-seg
3279 if ( fSplitSegs
&& !fPrebind
)
3282 // determine if info for shared region should be added
3283 if ( fOutputKind
== Options::kDynamicLibrary
) {
3284 if ( minOS(ld::mac10_5
, ld::iOS_3_1
) )
3286 if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
3287 || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
3288 fSharedRegionEligible
= true;
3291 // figure out if module table is needed for compatibility with old ld/dyld
3292 if ( fOutputKind
== Options::kDynamicLibrary
) {
3293 switch ( fArchitecture
) {
3295 if ( fIOSVersionMin
!= ld::iOSVersionUnset
) // simulator never needs modules
3297 case CPU_TYPE_POWERPC
: // 10.3 and earlier dyld requires a module table
3298 if ( fMacVersionMin
<= ld::mac10_5
)
3299 fNeedsModuleTable
= true;
3303 fNeedsModuleTable
= true; // redo_prebinding requires a module table
3308 // <rdar://problem/5366363> -r -x implies -S
3309 if ( (fOutputKind
== Options::kObjectFile
) && (fLocalSymbolHandling
== kLocalSymbolsNone
) )
3310 fDebugInfoStripping
= Options::kDebugInfoNone
;
3312 // choose how to process unwind info
3313 switch ( fArchitecture
) {
3315 case CPU_TYPE_X86_64
:
3316 switch ( fOutputKind
) {
3317 case Options::kObjectFile
:
3318 case Options::kStaticExecutable
:
3319 case Options::kPreload
:
3320 case Options::kKextBundle
:
3321 fAddCompactUnwindEncoding
= false;
3323 case Options::kDyld
:
3324 case Options::kDynamicLibrary
:
3325 case Options::kDynamicBundle
:
3326 case Options::kDynamicExecutable
:
3327 //if ( fAddCompactUnwindEncoding && (fVersionMin >= ld::mac10_6) )
3328 // fRemoveDwarfUnwindIfCompactExists = true;
3332 case CPU_TYPE_POWERPC
:
3333 case CPU_TYPE_POWERPC64
:
3335 fAddCompactUnwindEncoding
= false;
3336 fRemoveDwarfUnwindIfCompactExists
= false;
3339 // if -arch is missing, assume we don't want compact unwind info
3340 fAddCompactUnwindEncoding
= false;
3344 // only ARM main executables can be encrypted
3345 if ( fOutputKind
!= Options::kDynamicExecutable
)
3346 fEncryptable
= false;
3347 if ( fArchitecture
!= CPU_TYPE_ARM
)
3348 fEncryptable
= false;
3350 // don't move inits in dyld because dyld wants certain
3351 // entries point at stable locations at the start of __text
3352 if ( fOutputKind
== Options::kDyld
)
3353 fAutoOrderInitializers
= false;
3356 // disable __data ordering for some output kinds
3357 switch ( fOutputKind
) {
3358 case Options::kObjectFile
:
3359 case Options::kDyld
:
3360 case Options::kStaticExecutable
:
3361 case Options::kPreload
:
3362 case Options::kKextBundle
:
3365 case Options::kDynamicExecutable
:
3366 case Options::kDynamicLibrary
:
3367 case Options::kDynamicBundle
:
3371 // only use compressed LINKEDIT for final linked images
3372 switch ( fOutputKind
) {
3373 case Options::kDynamicExecutable
:
3374 case Options::kDynamicLibrary
:
3375 case Options::kDynamicBundle
:
3377 case Options::kPreload
:
3378 case Options::kStaticExecutable
:
3379 case Options::kObjectFile
:
3380 case Options::kDyld
:
3381 case Options::kKextBundle
:
3382 fMakeCompressedDyldInfoForceOff
= true;
3385 if ( fMakeCompressedDyldInfoForceOff
)
3386 fMakeCompressedDyldInfo
= false;
3389 // only use compressed LINKEDIT for:
3390 // x86_64 and i386 on Mac OS X 10.6 or later
3391 // arm on iPhoneOS 3.1 or later
3392 if ( fMakeCompressedDyldInfo
) {
3393 switch (fArchitecture
) {
3395 if ( fIOSVersionMin
!= ld::iOSVersionUnset
) // simulator always uses compressed LINKEDIT
3397 case CPU_TYPE_X86_64
:
3398 if ( fMacVersionMin
< ld::mac10_6
)
3399 fMakeCompressedDyldInfo
= false;
3402 if ( !minOS(ld::mac10_6
, ld::iOS_3_1
) )
3403 fMakeCompressedDyldInfo
= false;
3405 case CPU_TYPE_POWERPC
:
3406 case CPU_TYPE_POWERPC64
:
3408 fMakeCompressedDyldInfo
= false;
3413 // only ARM enforces that cpu-sub-types must match
3414 if ( fArchitecture
!= CPU_TYPE_ARM
)
3415 fAllowCpuSubtypeMismatches
= true;
3417 // only final linked images can not optimize zero fill sections
3418 if ( fOutputKind
== Options::kObjectFile
)
3419 fOptimizeZeroFill
= true;
3421 // all undefines in -r mode
3422 // if ( fOutputKind == Options::kObjectFile )
3423 // fUndefinedTreatment = kUndefinedSuppress;
3425 // only dynamic final linked images should warn about use of commmons
3426 if ( fWarnCommons
) {
3427 switch ( fOutputKind
) {
3428 case Options::kDynamicExecutable
:
3429 case Options::kDynamicLibrary
:
3430 case Options::kDynamicBundle
:
3432 case Options::kPreload
:
3433 case Options::kStaticExecutable
:
3434 case Options::kObjectFile
:
3435 case Options::kDyld
:
3436 case Options::kKextBundle
:
3437 fWarnCommons
= false;
3442 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
3443 if ( minOS(ld::mac10_5
, ld::iOS_2_0
) )
3444 fUseSimplifiedDylibReExports
= true;
3446 // Mac OS X 10.7 and iOS 4.2 support LC_LOAD_UPWARD_DYLIB
3447 if ( minOS(ld::mac10_7
, ld::iOS_4_2
) && (fOutputKind
== kDynamicLibrary
) )
3448 fCanUseUpwardDylib
= true;
3450 // MacOSX 10.7 defaults to PIE
3451 if ( ((fArchitecture
== CPU_TYPE_X86_64
) || (fArchitecture
== CPU_TYPE_I386
))
3452 && (fOutputKind
== kDynamicExecutable
)
3453 && (fMacVersionMin
>= ld::mac10_7
) ) {
3454 fPositionIndependentExecutable
= true;
3457 // armv7 for iOS4.3 defaults to PIE
3458 if ( (fArchitecture
== CPU_TYPE_ARM
)
3459 && fArchSupportsThumb2
3460 && (fOutputKind
== kDynamicExecutable
)
3461 && (fIOSVersionMin
>= ld::iOS_4_3
) ) {
3462 fPositionIndependentExecutable
= true;
3465 // -no_pie anywhere on command line disable PIE
3466 if ( fDisablePositionIndependentExecutable
)
3467 fPositionIndependentExecutable
= false;
3469 // set fOutputSlidable
3470 switch ( fOutputKind
) {
3471 case Options::kObjectFile
:
3472 case Options::kStaticExecutable
:
3473 fOutputSlidable
= false;
3475 case Options::kDynamicExecutable
:
3476 fOutputSlidable
= fPositionIndependentExecutable
;
3478 case Options::kPreload
:
3479 fOutputSlidable
= fPIEOnCommandLine
;
3481 case Options::kDyld
:
3482 case Options::kDynamicLibrary
:
3483 case Options::kDynamicBundle
:
3484 case Options::kKextBundle
:
3485 fOutputSlidable
= true;
3489 // let linker know if thread local variables are supported
3490 if ( fMacVersionMin
>= ld::mac10_7
) {
3494 // default to adding version load command for dynamic code, static code must opt-in
3495 switch ( fOutputKind
) {
3496 case Options::kObjectFile
:
3497 fVersionLoadCommand
= false;
3499 case Options::kStaticExecutable
:
3500 case Options::kPreload
:
3501 case Options::kKextBundle
:
3502 if ( fVersionLoadCommandForcedOn
)
3503 fVersionLoadCommand
= true;
3505 case Options::kDynamicExecutable
:
3506 case Options::kDyld
:
3507 case Options::kDynamicLibrary
:
3508 case Options::kDynamicBundle
:
3509 if ( !fVersionLoadCommandForcedOff
)
3510 fVersionLoadCommand
= true;
3511 // <rdar://problem/9945513> for now, don't create version load commands for iOS simulator builds
3512 if ( fVersionLoadCommand
&& (fArchitecture
== CPU_TYPE_I386
) ) {
3513 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
3514 if ( strstr(*sdkit
, "/iPhoneSimulator.platform/") != NULL
)
3515 fVersionLoadCommand
= false;
3521 // default to adding functions start for dynamic code, static code must opt-in
3522 switch ( fOutputKind
) {
3523 case Options::kObjectFile
:
3524 fFunctionStartsLoadCommand
= false;
3526 case Options::kPreload
:
3527 case Options::kStaticExecutable
:
3528 case Options::kKextBundle
:
3529 if ( fFunctionStartsForcedOn
)
3530 fFunctionStartsLoadCommand
= true;
3532 case Options::kDynamicExecutable
:
3533 case Options::kDyld
:
3534 case Options::kDynamicLibrary
:
3535 case Options::kDynamicBundle
:
3536 if ( !fFunctionStartsForcedOff
)
3537 fFunctionStartsLoadCommand
= true;
3541 // support re-export of individual symbols in MacOSX 10.7 and iOS 4.2
3542 if ( (fOutputKind
== kDynamicLibrary
) && minOS(ld::mac10_7
, ld::iOS_4_2
) )
3543 fCanReExportSymbols
= true;
3545 // ObjC optimization is only in dynamic final linked images
3546 switch ( fOutputKind
) {
3547 case Options::kObjectFile
:
3548 case Options::kStaticExecutable
:
3549 case Options::kPreload
:
3550 case Options::kKextBundle
:
3551 case Options::kDyld
:
3552 fObjcCategoryMerging
= false;
3554 case Options::kDynamicExecutable
:
3555 case Options::kDynamicLibrary
:
3556 case Options::kDynamicBundle
:
3560 // i386 main executables linked on Mac OS X 10.7 default to NX heap
3561 // regardless of target unless overriden with -allow_heap_execute anywhere
3562 // on the command line
3563 if ( (fArchitecture
== CPU_TYPE_I386
) && (fOutputKind
== kDynamicExecutable
) && !fDisableNonExecutableHeap
)
3564 fNonExecutableHeap
= true;
3567 void Options::checkIllegalOptionCombinations()
3569 // check -undefined setting
3570 switch ( fUndefinedTreatment
) {
3571 case kUndefinedError
:
3572 case kUndefinedDynamicLookup
:
3575 case kUndefinedWarning
:
3576 case kUndefinedSuppress
:
3577 // requires flat namespace
3578 if ( fNameSpace
== kTwoLevelNameSpace
)
3579 throw "can't use -undefined warning or suppress with -twolevel_namespace";
3583 // unify -sub_umbrella with dylibs
3584 for (std::vector
<const char*>::iterator it
= fSubUmbellas
.begin(); it
!= fSubUmbellas
.end(); it
++) {
3585 const char* subUmbrella
= *it
;
3587 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
3588 Options::FileInfo
& info
= *fit
;
3589 const char* lastSlash
= strrchr(info
.path
, '/');
3590 if ( lastSlash
== NULL
)
3591 lastSlash
= info
.path
- 1;
3592 if ( strcmp(&lastSlash
[1], subUmbrella
) == 0 ) {
3593 info
.options
.fReExport
= true;
3599 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella
);
3602 // unify -sub_library with dylibs
3603 for (std::vector
<const char*>::iterator it
= fSubLibraries
.begin(); it
!= fSubLibraries
.end(); it
++) {
3604 const char* subLibrary
= *it
;
3606 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
3607 Options::FileInfo
& info
= *fit
;
3608 const char* lastSlash
= strrchr(info
.path
, '/');
3609 if ( lastSlash
== NULL
)
3610 lastSlash
= info
.path
- 1;
3611 const char* dot
= strchr(&lastSlash
[1], '.');
3613 dot
= &lastSlash
[strlen(lastSlash
)];
3614 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
3615 info
.options
.fReExport
= true;
3621 warning("-sub_library %s does not match a supplied dylib", subLibrary
);
3624 // sync reader options
3625 if ( fNameSpace
!= kTwoLevelNameSpace
)
3626 fFlatNamespace
= true;
3628 // check -stack_addr
3629 if ( fStackAddr
!= 0 ) {
3630 switch (fArchitecture
) {
3632 case CPU_TYPE_POWERPC
:
3634 if ( fStackAddr
> 0xFFFFFFFF )
3635 throw "-stack_addr must be < 4G for 32-bit processes";
3637 case CPU_TYPE_POWERPC64
:
3638 case CPU_TYPE_X86_64
:
3641 if ( (fStackAddr
& -4096) != fStackAddr
)
3642 throw "-stack_addr must be multiples of 4K";
3643 if ( fStackSize
== 0 )
3644 throw "-stack_addr must be used with -stack_size";
3647 // check -stack_size
3648 if ( fStackSize
!= 0 ) {
3649 switch (fArchitecture
) {
3651 case CPU_TYPE_POWERPC
:
3652 if ( fStackSize
> 0xFFFFFFFF )
3653 throw "-stack_size must be < 4G for 32-bit processes";
3654 if ( fStackAddr
== 0 ) {
3655 fStackAddr
= 0xC0000000;
3657 if ( (fStackAddr
> 0xB0000000) && ((fStackAddr
-fStackSize
) < 0xB0000000) )
3658 warning("custom stack placement overlaps and will disable shared region");
3661 if ( fStackSize
> 0x2F000000 )
3662 throw "-stack_size must be < 752MB";
3663 if ( fStackAddr
== 0 )
3664 fStackAddr
= 0x2F000000;
3665 if ( fStackAddr
> 0x30000000)
3666 throw "-stack_addr must be < 0x30000000 for arm";
3667 case CPU_TYPE_POWERPC64
:
3668 case CPU_TYPE_X86_64
:
3669 if ( fStackAddr
== 0 ) {
3670 fStackAddr
= 0x00007FFF5C000000LL
;
3674 if ( (fStackSize
& -4096) != fStackSize
)
3675 throw "-stack_size must be multiples of 4K";
3676 switch ( fOutputKind
) {
3677 case Options::kDynamicExecutable
:
3678 case Options::kStaticExecutable
:
3679 // custom stack size only legal when building main executable
3681 case Options::kDynamicLibrary
:
3682 case Options::kDynamicBundle
:
3683 case Options::kObjectFile
:
3684 case Options::kDyld
:
3685 case Options::kPreload
:
3686 case Options::kKextBundle
:
3687 throw "-stack_size option can only be used when linking a main executable";
3689 if ( fStackSize
> fStackAddr
)
3690 throwf("-stack_size (0x%08llX) must be smaller than -stack_addr (0x%08llX)", fStackSize
, fStackAddr
);
3693 // check that -allow_stack_execute is only used with main executables
3694 if ( fExecutableStack
) {
3695 switch ( fOutputKind
) {
3696 case Options::kDynamicExecutable
:
3697 case Options::kStaticExecutable
:
3698 // -allow_stack_execute size only legal when building main executable
3700 case Options::kDynamicLibrary
:
3701 case Options::kDynamicBundle
:
3702 case Options::kObjectFile
:
3703 case Options::kDyld
:
3704 case Options::kPreload
:
3705 case Options::kKextBundle
:
3706 throw "-allow_stack_execute option can only be used when linking a main executable";
3710 // check that -allow_heap_execute is only used with i386 main executables
3711 if ( fDisableNonExecutableHeap
) {
3712 if ( fArchitecture
!= CPU_TYPE_I386
)
3713 throw "-allow_heap_execute option can only be used when linking for i386";
3714 switch ( fOutputKind
) {
3715 case Options::kDynamicExecutable
:
3716 // -allow_heap_execute only legal when building main executable
3718 case Options::kStaticExecutable
:
3719 case Options::kDynamicLibrary
:
3720 case Options::kDynamicBundle
:
3721 case Options::kObjectFile
:
3722 case Options::kDyld
:
3723 case Options::kPreload
:
3724 case Options::kKextBundle
:
3725 throw "-allow_heap_execute option can only be used when linking a main executable";
3729 // check -client_name is only used when making a bundle or main executable
3730 if ( fClientName
!= NULL
) {
3731 switch ( fOutputKind
) {
3732 case Options::kDynamicExecutable
:
3733 case Options::kDynamicBundle
:
3735 case Options::kStaticExecutable
:
3736 case Options::kDynamicLibrary
:
3737 case Options::kObjectFile
:
3738 case Options::kDyld
:
3739 case Options::kPreload
:
3740 case Options::kKextBundle
:
3741 throw "-client_name can only be used with -bundle";
3745 // check -init is only used when building a dylib
3746 if ( (fInitFunctionName
!= NULL
) && (fOutputKind
!= Options::kDynamicLibrary
) )
3747 throw "-init can only be used with -dynamiclib";
3749 // check -bundle_loader only used with -bundle
3750 if ( (fBundleLoader
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
3751 throw "-bundle_loader can only be used with -bundle";
3753 // check -dtrace not used with -r
3754 if ( (fDtraceScriptName
!= NULL
) && (fOutputKind
== Options::kObjectFile
) )
3755 throw "-dtrace can only be used when creating final linked images";
3757 // check -d can only be used with -r
3758 if ( fMakeTentativeDefinitionsReal
&& (fOutputKind
!= Options::kObjectFile
) )
3759 throw "-d can only be used with -r";
3761 // check that -root_safe is not used with -r
3762 if ( fRootSafe
&& (fOutputKind
== Options::kObjectFile
) )
3763 throw "-root_safe cannot be used with -r";
3765 // check that -setuid_safe is not used with -r
3766 if ( fSetuidSafe
&& (fOutputKind
== Options::kObjectFile
) )
3767 throw "-setuid_safe cannot be used with -r";
3769 // rdar://problem/4718189 map ObjC class names to new runtime names
3770 bool alterObjC1ClassNamesToObjC2
= false;
3771 switch (fArchitecture
) {
3773 // i386 only uses new symbols when using objc2 ABI
3774 if ( fObjCABIVersion2Override
)
3775 alterObjC1ClassNamesToObjC2
= true;
3777 case CPU_TYPE_POWERPC64
:
3778 case CPU_TYPE_X86_64
:
3780 alterObjC1ClassNamesToObjC2
= true;
3784 // make sure all required exported symbols exist
3785 std::vector
<const char*> impliedExports
;
3786 for (NameSet::iterator it
=fExportSymbols
.regularBegin(); it
!= fExportSymbols
.regularEnd(); ++it
) {
3787 const char* name
= *it
;
3788 const int len
= strlen(name
);
3789 if ( (strcmp(&name
[len
-3], ".eh") == 0) || (strncmp(name
, ".objc_category_name_", 20) == 0) ) {
3790 // never export .eh symbols
3791 warning("ignoring %s in export list", name
);
3793 else if ( (fArchitecture
== CPU_TYPE_I386
) && !fObjCABIVersion2Override
&& (strncmp(name
, "_OBJC_CLASS_$", 13) == 0) ) {
3794 warning("ignoring Objc2 Class symbol %s in i386 export list", name
);
3795 fRemovedExports
.insert(name
);
3797 else if ( alterObjC1ClassNamesToObjC2
&& (strncmp(name
, ".objc_class_name_", 17) == 0) ) {
3798 // linking ObjC2 ABI, but have ObjC1 ABI name in export list. Change it to intended name
3799 fRemovedExports
.insert(name
);
3801 asprintf(&temp
, "_OBJC_CLASS_$_%s", &name
[17]);
3802 impliedExports
.push_back(temp
);
3803 asprintf(&temp
, "_OBJC_METACLASS_$_%s", &name
[17]);
3804 impliedExports
.push_back(temp
);
3807 fInitialUndefines
.push_back(name
);
3810 fExportSymbols
.remove(fRemovedExports
);
3811 for (std::vector
<const char*>::iterator it
=impliedExports
.begin(); it
!= impliedExports
.end(); ++it
) {
3812 const char* name
= *it
;
3813 fExportSymbols
.insert(name
);
3814 fInitialUndefines
.push_back(name
);
3817 // make sure all required re-exported symbols exist
3818 for (NameSet::iterator it
=fReExportSymbols
.regularBegin(); it
!= fReExportSymbols
.regularEnd(); ++it
) {
3819 fInitialUndefines
.push_back(*it
);
3822 // make sure that -init symbol exists
3823 if ( fInitFunctionName
!= NULL
)
3824 fInitialUndefines
.push_back(fInitFunctionName
);
3826 // make sure that entry symbol exists
3827 switch ( fOutputKind
) {
3828 case Options::kDynamicExecutable
:
3829 case Options::kStaticExecutable
:
3830 case Options::kDyld
:
3831 case Options::kPreload
:
3832 fInitialUndefines
.push_back(fEntryName
);
3834 case Options::kDynamicLibrary
:
3835 case Options::kDynamicBundle
:
3836 case Options::kObjectFile
:
3837 case Options::kKextBundle
:
3841 // make sure every alias base exists
3842 for (std::vector
<AliasPair
>::iterator it
=fAliases
.begin(); it
!= fAliases
.end(); ++it
) {
3843 fInitialUndefines
.push_back(it
->realName
);
3846 // check custom segments
3847 if ( fCustomSegmentAddresses
.size() != 0 ) {
3848 // verify no segment is in zero page
3849 if ( fZeroPageSize
!= ULLONG_MAX
) {
3850 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
3851 if ( it
->address
< fZeroPageSize
)
3852 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it
->name
, it
->address
);
3855 // verify no duplicates
3856 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
3857 for (std::vector
<SegmentStart
>::iterator it2
= fCustomSegmentAddresses
.begin(); it2
!= fCustomSegmentAddresses
.end(); ++it2
) {
3858 if ( (it
->address
== it2
->address
) && (it
!= it2
) )
3859 throwf("duplicate -segaddr addresses for %s and %s", it
->name
, it2
->name
);
3861 // a custom segment address of zero will disable the use of a zero page
3862 if ( it
->address
== 0 )
3867 if ( fZeroPageSize
== ULLONG_MAX
) {
3868 // zero page size not specified on command line, set default
3869 switch (fArchitecture
) {
3871 case CPU_TYPE_POWERPC
:
3873 // first 4KB for 32-bit architectures
3874 fZeroPageSize
= 0x1000;
3876 case CPU_TYPE_POWERPC64
:
3877 // first 4GB for ppc64 on 10.5
3878 if ( fMacVersionMin
>= ld::mac10_5
)
3879 fZeroPageSize
= 0x100000000ULL
;
3881 fZeroPageSize
= 0x1000; // 10.4 dyld may not be able to handle >4GB zero page
3883 case CPU_TYPE_X86_64
:
3884 // first 4GB for x86_64 on all OS's
3885 fZeroPageSize
= 0x100000000ULL
;
3888 // if -arch not used, default to 4K zero-page
3889 fZeroPageSize
= 0x1000;
3893 switch ( fOutputKind
) {
3894 case Options::kDynamicExecutable
:
3895 case Options::kStaticExecutable
:
3896 // -pagezero_size size only legal when building main executable
3898 case Options::kDynamicLibrary
:
3899 case Options::kDynamicBundle
:
3900 case Options::kObjectFile
:
3901 case Options::kDyld
:
3902 case Options::kPreload
:
3903 case Options::kKextBundle
:
3904 if ( fZeroPageSize
!= 0 )
3905 throw "-pagezero_size option can only be used when linking a main executable";
3909 // if main executable with custom base address, model zero page as custom segment
3910 if ( (fOutputKind
== Options::kDynamicExecutable
) && (fBaseAddress
!= 0) && (fZeroPageSize
!= 0) ) {
3912 seg
.name
= "__PAGEZERO";
3914 fCustomSegmentAddresses
.push_back(seg
);
3917 // -dead_strip and -r are incompatible
3918 if ( fDeadStrip
&& (fOutputKind
== Options::kObjectFile
) )
3919 throw "-r and -dead_strip cannot be used together";
3921 // can't use -rpath unless targeting 10.5 or later
3922 if ( fRPaths
.size() > 0 ) {
3923 if ( !minOS(ld::mac10_5
, ld::iOS_2_0
) )
3924 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
3925 switch ( fOutputKind
) {
3926 case Options::kDynamicExecutable
:
3927 case Options::kDynamicLibrary
:
3928 case Options::kDynamicBundle
:
3930 case Options::kStaticExecutable
:
3931 case Options::kObjectFile
:
3932 case Options::kDyld
:
3933 case Options::kPreload
:
3934 case Options::kKextBundle
:
3935 throw "-rpath can only be used when creating a dynamic final linked image";
3939 // check -pie is only used when building a dynamic main executable for 10.5
3940 if ( fPositionIndependentExecutable
) {
3941 switch ( fOutputKind
) {
3942 case Options::kDynamicExecutable
:
3943 if ( !minOS(ld::mac10_5
, ld::iOS_4_2
) ) {
3944 if ( fIOSVersionMin
== ld::iOSVersionUnset
)
3945 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
3947 throw "-pie can only be used when targeting iOS 4.2 or later";
3950 case Options::kPreload
:
3952 case Options::kDynamicLibrary
:
3953 case Options::kDynamicBundle
:
3954 warning("-pie being ignored. It is only used when linking a main executable");
3955 fPositionIndependentExecutable
= false;
3957 case Options::kStaticExecutable
:
3958 case Options::kObjectFile
:
3959 case Options::kDyld
:
3960 case Options::kKextBundle
:
3961 throw "-pie can only be used when linking a main executable";
3965 // check -read_only_relocs is not used with x86_64
3966 if ( fAllowTextRelocs
) {
3967 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
!= kKextBundle
) ) {
3968 warning("-read_only_relocs cannot be used with x86_64");
3969 fAllowTextRelocs
= false;
3973 // check -mark_auto_dead_strip is only used with dylibs
3974 if ( fMarkDeadStrippableDylib
) {
3975 if ( fOutputKind
!= Options::kDynamicLibrary
) {
3976 warning("-mark_auto_dead_strip can only be used when creating a dylib");
3977 fMarkDeadStrippableDylib
= false;
3981 // -force_cpusubtype_ALL is not supported for ARM
3982 if ( fForceSubtypeAll
) {
3983 if ( fArchitecture
== CPU_TYPE_ARM
) {
3984 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
3988 // -reexported_symbols_list can only be used with -dynamiclib
3989 if ( !fReExportSymbols
.empty() ) {
3990 if ( fOutputKind
!= Options::kDynamicLibrary
)
3991 throw "-reexported_symbols_list can only used used when created dynamic libraries";
3992 if ( !minOS(ld::mac10_7
, ld::iOS_4_2
) )
3993 throw "targeted OS version does not support -reexported_symbols_list";
3996 // -dyld_env can only be used with main executables
3997 if ( (fOutputKind
!= Options::kDynamicExecutable
) && (fDyldEnvironExtras
.size() != 0) )
3998 throw "-dyld_env can only used used when created main executables";
4002 void Options::checkForClassic(int argc
, const char* argv
[])
4005 bool archFound
= false;
4006 bool staticFound
= false;
4007 bool dtraceFound
= false;
4008 bool kextFound
= false;
4009 bool rFound
= false;
4010 bool creatingMachKernel
= false;
4011 bool newLinker
= false;
4013 // build command line buffer in case ld crashes
4014 const char* srcRoot
= getenv("SRCROOT");
4015 if ( srcRoot
!= NULL
) {
4016 strlcpy(crashreporterBuffer
, "SRCROOT=", crashreporterBufferSize
);
4017 strlcat(crashreporterBuffer
, srcRoot
, crashreporterBufferSize
);
4018 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
4021 strlcat(crashreporterBuffer
, LD_VERS
, crashreporterBufferSize
);
4022 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
4024 strlcat(crashreporterBuffer
, "ld ", crashreporterBufferSize
);
4025 for(int i
=1; i
< argc
; ++i
) {
4026 strlcat(crashreporterBuffer
, argv
[i
], crashreporterBufferSize
);
4027 strlcat(crashreporterBuffer
, " ", crashreporterBufferSize
);
4030 for(int i
=0; i
< argc
; ++i
) {
4031 const char* arg
= argv
[i
];
4032 if ( arg
[0] == '-' ) {
4033 if ( strcmp(arg
, "-arch") == 0 ) {
4034 parseArch(argv
[++i
]);
4037 else if ( strcmp(arg
, "-static") == 0 ) {
4040 else if ( strcmp(arg
, "-kext") == 0 ) {
4043 else if ( strcmp(arg
, "-dtrace") == 0 ) {
4046 else if ( strcmp(arg
, "-r") == 0 ) {
4049 else if ( strcmp(arg
, "-new_linker") == 0 ) {
4052 else if ( strcmp(arg
, "-classic_linker") == 0 ) {
4053 // ld_classic does not understand this option, so remove it
4054 for(int j
=i
; j
< argc
; ++j
)
4055 argv
[j
] = argv
[j
+1];
4056 this->gotoClassicLinker(argc
-1, argv
);
4058 else if ( strcmp(arg
, "-o") == 0 ) {
4059 const char* outfile
= argv
[++i
];
4060 if ( (outfile
!= NULL
) && (strstr(outfile
, "/mach_kernel") != NULL
) )
4061 creatingMachKernel
= true;
4066 // -dtrace only supported by new linker
4071 switch ( fArchitecture
) {
4073 case CPU_TYPE_POWERPC
:
4074 if ( (staticFound
|| kextFound
) && !newLinker
) {
4075 // this environment variable will disable use of ld_classic for -static links
4076 if ( getenv("LD_NO_CLASSIC_LINKER_STATIC") == NULL
) {
4077 this->gotoClassicLinker(argc
, argv
);
4084 // work around for VSPTool
4086 this->gotoClassicLinker(argc
, argv
);
4091 void Options::gotoClassicLinker(int argc
, const char* argv
[])
4093 warning("using ld_classic");
4094 argv
[0] = "ld_classic";
4095 // ld_classic does not support -iphoneos_version_min, so change
4096 for(int j
=0; j
< argc
; ++j
) {
4097 if ( (strcmp(argv
[j
], "-iphoneos_version_min") == 0) || (strcmp(argv
[j
], "-ios_version_min") == 0) ) {
4098 argv
[j
] = "-macosx_version_min";
4104 // ld classic does not understand -kext (change to -static -r)
4105 for(int j
=0; j
< argc
; ++j
) {
4106 if ( strcmp(argv
[j
], "-kext") == 0)
4108 else if ( strcmp(argv
[j
], "-dynamic") == 0)
4109 argv
[j
] = "-static";
4111 // ld classic does not understand -demangle
4112 for(int j
=0; j
< argc
; ++j
) {
4113 if ( strcmp(argv
[j
], "-demangle") == 0)
4114 argv
[j
] = "-noprebind";
4116 // in -v mode, print command line passed to ld_classic
4117 for(int i
=0; i
< argc
; ++i
) {
4118 if ( strcmp(argv
[i
], "-v") == 0 ) {
4119 for(int j
=0; j
< argc
; ++j
)
4120 printf("%s ", argv
[j
]);
4125 char rawPath
[PATH_MAX
];
4126 char path
[PATH_MAX
];
4127 uint32_t bufSize
= PATH_MAX
;
4128 if ( _NSGetExecutablePath(rawPath
, &bufSize
) != -1 ) {
4129 if ( realpath(rawPath
, path
) != NULL
) {
4130 char* lastSlash
= strrchr(path
, '/');
4131 if ( lastSlash
!= NULL
) {
4132 strcpy(lastSlash
+1, "ld_classic");
4134 execvp(path
, (char**)argv
);
4138 // in case of error in above, try searching for ld_classic via PATH
4139 execvp(argv
[0], (char**)argv
);
4140 fprintf(stderr
, "can't exec ld_classic\n");