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