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 <sys/sysctl.h>
30 #include <mach-o/dyld.h>
36 #include <Availability.h>
41 #include "Architectures.hpp"
42 #include "MachOFileAbstraction.hpp"
45 // upward dependency on lto::version()
47 extern const char* version();
50 // magic to place command line in crash reports
51 const int crashreporterBufferSize
= 2000;
52 static char crashreporterBuffer
[crashreporterBufferSize
];
53 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
54 #include <CrashReporterClient.h>
55 // hack until ld does not need to build on 10.6 anymore
56 struct crashreporter_annotations_t gCRAnnotations
57 __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION
)))
58 = { CRASHREPORTER_ANNOTATIONS_VERSION
, 0, 0, 0, 0, 0, 0 };
60 extern "C" char* __crashreporter_info__
;
62 char* __crashreporter_info__
= crashreporterBuffer
;
66 static bool sEmitWarnings
= true;
67 static bool sFatalWarnings
= false;
68 static const char* sWarningsSideFilePath
= NULL
;
69 static FILE* sWarningsSideFile
= NULL
;
70 static int sWarningsCount
= 0;
72 void warning(const char* format
, ...)
75 if ( sEmitWarnings
) {
77 if ( sWarningsSideFilePath
!= NULL
) {
78 if ( sWarningsSideFile
== NULL
)
79 sWarningsSideFile
= fopen(sWarningsSideFilePath
, "a");
81 va_start(list
, format
);
82 fprintf(stderr
, "ld: warning: ");
83 vfprintf(stderr
, format
, list
);
84 fprintf(stderr
, "\n");
85 if ( sWarningsSideFile
!= NULL
) {
86 fprintf(sWarningsSideFile
, "ld: warning: ");
87 vfprintf(sWarningsSideFile
, format
, list
);
88 fprintf(sWarningsSideFile
, "\n");
89 fflush(sWarningsSideFile
);
95 void throwf(const char* format
, ...)
99 va_start(list
, format
);
100 vasprintf(&p
, format
, list
);
108 bool Options::FileInfo::checkFileExists(const Options
& options
, const char *p
)
110 struct stat statBuffer
;
113 if ( stat(p
, &statBuffer
) == 0 ) {
114 if (p
!= path
) path
= strdup(p
);
115 fileLen
= statBuffer
.st_size
;
116 modTime
= statBuffer
.st_mtime
;
119 if ( options
.dumpDependencyInfo() )
120 options
.dumpDependency(Options::depNotFound
, p
);
125 Options::Options(int argc
, const char* argv
[])
126 : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0), fArchitectureName("unknown"), fOutputKind(kDynamicExecutable
),
127 fHasPreferredSubType(false), fArchSupportsThumb2(false), fPrebind(false), fBindAtLoad(false), fKeepPrivateExterns(false),
128 fNeedsModuleTable(false), fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false),
129 fInterposeMode(kInterposeNone
), fDeadStrip(false), fNameSpace(kTwoLevelNameSpace
),
130 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL
), fFinalName(NULL
), fEntryName("start"),
131 fBaseAddress(0), fMaxAddress(0x7FFFFFFFFFFFFFFFLL
),
132 fBaseWritableAddress(0), fSplitSegs(false),
133 fExportMode(kExportDefault
), fLibrarySearchMode(kSearchDylibAndArchiveInEachDir
),
134 fUndefinedTreatment(kUndefinedError
), fMessagesPrefixedWithArchitecture(true),
135 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak
),
137 fUmbrellaName(NULL
), fInitFunctionName(NULL
), fDotOutputFile(NULL
), fExecutablePath(NULL
),
138 fBundleLoader(NULL
), fDtraceScriptName(NULL
), fSegAddrTablePath(NULL
), fMapPath(NULL
),
139 fDyldInstallPath("/usr/lib/dyld"), fTempLtoObjectPath(NULL
), fOverridePathlibLTO(NULL
), fLtoCpu(NULL
),
140 fZeroPageSize(ULLONG_MAX
), fStackSize(0), fStackAddr(0), fSourceVersion(0), fSDKVersion(0), fExecutableStack(false),
141 fNonExecutableHeap(false), fDisableNonExecutableHeap(false),
142 fMinimumHeaderPad(32), fSegmentAlignment(4096),
143 fCommonsMode(kCommonsIgnoreDylibs
), fUUIDMode(kUUIDContent
), fLocalSymbolHandling(kLocalSymbolsAll
), fWarnCommons(false),
144 fVerbose(false), fKeepRelocations(false), fWarnStabs(false),
145 fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
146 fSharedRegionEligible(false), fPrintOrderFileStatistics(false),
147 fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), fPIEOnCommandLine(false),
148 fDisablePositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
149 fDeadStripDylibs(false), fAllowTextRelocs(false), fWarnTextRelocs(false), fKextsUseStubs(false),
150 fUsingLazyDylibLinking(false), fEncryptable(true),
151 fOrderData(true), fMarkDeadStrippableDylib(false),
152 fMakeCompressedDyldInfo(true), fMakeCompressedDyldInfoForceOff(false), fNoEHLabels(false),
153 fAllowCpuSubtypeMismatches(false), fUseSimplifiedDylibReExports(false),
154 fObjCABIVersion2Override(false), fObjCABIVersion1Override(false), fCanUseUpwardDylib(false),
155 fFullyLoadArchives(false), fLoadAllObjcObjectsFromArchives(false), fFlatNamespace(false),
156 fLinkingMainExecutable(false), fForFinalLinkedImage(false), fForStatic(false),
157 fForDyld(false), fMakeTentativeDefinitionsReal(false), fWhyLoad(false), fRootSafe(false),
158 fSetuidSafe(false), fImplicitlyLinkPublicDylibs(true), fAddCompactUnwindEncoding(true),
159 fWarnCompactUnwind(false), fRemoveDwarfUnwindIfCompactExists(false),
160 fAutoOrderInitializers(true), fOptimizeZeroFill(true), fMergeZeroFill(false), fLogObjectFiles(false),
161 fLogAllFiles(false), fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false),
162 fOutputSlidable(false), fWarnWeakExports(false),
163 fObjcGcCompaction(false), fObjCGc(false), fObjCGcOnly(false),
164 fDemangle(false), fTLVSupport(false),
165 fVersionLoadCommand(false), fVersionLoadCommandForcedOn(false),
166 fVersionLoadCommandForcedOff(false), fFunctionStartsLoadCommand(false),
167 fFunctionStartsForcedOn(false), fFunctionStartsForcedOff(false),
168 fDataInCodeInfoLoadCommand(false), fDataInCodeInfoLoadCommandForcedOn(false), fDataInCodeInfoLoadCommandForcedOff(false),
169 fCanReExportSymbols(false), fObjcCategoryMerging(true), fPageAlignDataAtoms(false),
170 fNeedsThreadLoadCommand(false), fEntryPointLoadCommand(false),
171 fEntryPointLoadCommandForceOn(false), fEntryPointLoadCommandForceOff(false),
172 fSourceVersionLoadCommand(false),
173 fSourceVersionLoadCommandForceOn(false), fSourceVersionLoadCommandForceOff(false),
174 fDependentDRInfo(false), fDependentDRInfoForcedOn(false), fDependentDRInfoForcedOff(false),
175 fTargetIOSSimulator(false), fExportDynamic(false), fAbsoluteSymbols(false),
176 fAllowSimulatorToLinkWithMacOSX(false), fKeepDwarfUnwind(true),
177 fKeepDwarfUnwindForcedOn(false), fKeepDwarfUnwindForcedOff(false),
178 fVerboseOptimizationHints(false), fIgnoreOptimizationHints(false),
179 fGenerateDtraceDOF(true), fAllowBranchIslands(true),
180 fDebugInfoStripping(kDebugInfoMinimal
), fTraceOutputFile(NULL
),
181 fMacVersionMin(ld::macVersionUnset
), fIOSVersionMin(ld::iOSVersionUnset
),
182 fSaveTempFiles(false), fSnapshotRequested(false), fPipelineFifo(NULL
),
183 fDependencyInfoPath(NULL
), fDependencyFileDescriptor(-1)
185 this->checkForClassic(argc
, argv
);
186 this->parsePreCommandLineEnvironmentSettings();
187 this->parse(argc
, argv
);
188 this->parsePostCommandLineEnvironmentSettings();
189 this->reconfigureDefaults();
190 this->checkIllegalOptionCombinations();
192 if ( this->dumpDependencyInfo() ) {
193 this->dumpDependency(depOutputFile
, fOutputFile
);
194 if ( fMapPath
!= NULL
)
195 this->dumpDependency(depOutputFile
, fMapPath
);
201 if ( fDependencyFileDescriptor
!= -1 )
202 ::close(fDependencyFileDescriptor
);
205 bool Options::errorBecauseOfWarnings() const
207 return (sFatalWarnings
&& (sWarningsCount
> 0));
211 const char* Options::installPath() const
213 if ( fDylibInstallName
!= NULL
)
214 return fDylibInstallName
;
215 else if ( fFinalName
!= NULL
)
222 bool Options::interposable(const char* name
) const
224 switch ( fInterposeMode
) {
227 case kInterposeAllExternal
:
230 return fInterposeList
.contains(name
);
232 throw "internal error";
236 bool Options::printWhyLive(const char* symbolName
) const
238 return ( fWhyLive
.find(symbolName
) != fWhyLive
.end() );
242 const char* Options::dotOutputFile()
244 return fDotOutputFile
;
248 bool Options::hasWildCardExportRestrictList() const
250 // has -exported_symbols_list which contains some wildcards
251 return ((fExportMode
== kExportSome
) && fExportSymbols
.hasWildCards());
254 bool Options::hasWeakBitTweaks() const
256 // has -exported_symbols_list which contains some wildcards
257 return (!fForceWeakSymbols
.empty() || !fForceNotWeakSymbols
.empty());
260 bool Options::allGlobalsAreDeadStripRoots() const
262 // -exported_symbols_list means globals are not exported by default
263 if ( fExportMode
== kExportSome
)
266 switch ( fOutputKind
) {
267 case Options::kDynamicExecutable
:
268 // <rdar://problem/12839986> Add the -export_dynamic flag
269 return fExportDynamic
;
270 case Options::kStaticExecutable
:
271 // <rdar://problem/13361218> Support the -export_dynamic flag for xnu
272 return fExportDynamic
;
273 case Options::kPreload
:
274 // by default unused globals in a main executable are stripped
276 case Options::kDynamicLibrary
:
277 case Options::kDynamicBundle
:
278 case Options::kObjectFile
:
280 case Options::kKextBundle
:
287 bool Options::keepRelocations()
289 return fKeepRelocations
;
292 bool Options::warnStabs()
297 const char* Options::executablePath()
299 return fExecutablePath
;
302 uint32_t Options::initialSegProtection(const char* segName
) const
304 for(std::vector
<Options::SegmentProtect
>::const_iterator it
= fCustomSegmentProtections
.begin(); it
!= fCustomSegmentProtections
.end(); ++it
) {
305 if ( strcmp(it
->name
, segName
) == 0 ) {
309 if ( strcmp(segName
, "__PAGEZERO") == 0 ) {
312 else if ( strcmp(segName
, "__TEXT") == 0 ) {
313 return VM_PROT_READ
| VM_PROT_EXECUTE
;
315 else if ( strcmp(segName
, "__LINKEDIT") == 0 ) {
319 // all others default to read-write
320 return VM_PROT_READ
| VM_PROT_WRITE
;
323 uint32_t Options::maxSegProtection(const char* segName
) const
325 // iPhoneOS always uses same protection for max and initial
326 // <rdar://problem/11663436> simulator apps need to use MacOSX max-prot
327 if ( (fIOSVersionMin
!= ld::iOSVersionUnset
) && (fArchitecture
!= CPU_TYPE_I386
) )
328 return initialSegProtection(segName
);
330 for(std::vector
<Options::SegmentProtect
>::const_iterator it
= fCustomSegmentProtections
.begin(); it
!= fCustomSegmentProtections
.end(); ++it
) {
331 if ( strcmp(it
->name
, segName
) == 0 ) {
335 if ( strcmp(segName
, "__PAGEZERO") == 0 ) {
338 // all others default to all
339 return VM_PROT_READ
| VM_PROT_WRITE
| VM_PROT_EXECUTE
;
342 uint64_t Options::segPageSize(const char* segName
) const
344 for(std::vector
<SegmentSize
>::const_iterator it
=fCustomSegmentSizes
.begin(); it
!= fCustomSegmentSizes
.end(); ++it
) {
345 if ( strcmp(it
->name
, segName
) == 0 )
348 return fSegmentAlignment
;
351 uint64_t Options::customSegmentAddress(const char* segName
) const
353 for(std::vector
<SegmentStart
>::const_iterator it
=fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
354 if ( strcmp(it
->name
, segName
) == 0 )
357 // if custom stack in use, model as segment with custom address
358 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
359 return fStackAddr
- fStackSize
;
363 bool Options::hasCustomSegmentAddress(const char* segName
) const
365 for(std::vector
<SegmentStart
>::const_iterator it
=fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
366 if ( strcmp(it
->name
, segName
) == 0 )
369 // if custom stack in use, model as segment with custom address
370 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
375 bool Options::hasCustomSectionAlignment(const char* segName
, const char* sectName
) const
377 for (std::vector
<SectionAlignment
>::const_iterator it
= fSectionAlignments
.begin(); it
!= fSectionAlignments
.end(); ++it
) {
378 if ( (strcmp(it
->segmentName
, segName
) == 0) && (strcmp(it
->sectionName
, sectName
) == 0) )
384 uint8_t Options::customSectionAlignment(const char* segName
, const char* sectName
) const
386 for (std::vector
<SectionAlignment
>::const_iterator it
= fSectionAlignments
.begin(); it
!= fSectionAlignments
.end(); ++it
) {
387 if ( (strcmp(it
->segmentName
, segName
) == 0) && (strcmp(it
->sectionName
, sectName
) == 0) )
388 return it
->alignment
;
394 bool Options::hasExportedSymbolOrder()
396 return (fExportSymbolsOrder
.size() > 0);
399 bool Options::exportedSymbolOrder(const char* sym
, unsigned int* order
) const
401 NameToOrder::const_iterator pos
= fExportSymbolsOrder
.find(sym
);
402 if ( pos
!= fExportSymbolsOrder
.end() ) {
403 *order
= pos
->second
;
412 void Options::loadSymbolOrderFile(const char* fileOfExports
, NameToOrder
& orderMapping
)
414 // read in whole file
415 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
417 throwf("can't open -exported_symbols_order file: %s", fileOfExports
);
418 struct stat stat_buf
;
419 ::fstat(fd
, &stat_buf
);
420 char* p
= (char*)malloc(stat_buf
.st_size
);
422 throwf("can't process -exported_symbols_order file: %s", fileOfExports
);
424 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
425 throwf("can't read -exported_symbols_order file: %s", fileOfExports
);
429 // parse into symbols and add to unordered_set
430 unsigned int count
= 0;
431 char * const end
= &p
[stat_buf
.st_size
];
432 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
433 char* symbolStart
= NULL
;
434 for (char* s
= p
; s
< end
; ++s
) {
440 else if ( !isspace(*s
) ) {
446 if ( (*s
== '\n') || (*s
== '\r') ) {
448 // removing any trailing spaces
450 while ( isspace(*last
) ) {
454 orderMapping
[symbolStart
] = ++count
;
460 if ( (*s
== '\n') || (*s
== '\r') )
465 if ( state
== inSymbol
) {
466 warning("missing line-end at end of file \"%s\"", fileOfExports
);
467 int len
= end
-symbolStart
+1;
468 char* temp
= new char[len
];
469 strlcpy(temp
, symbolStart
, len
);
471 // remove any trailing spaces
472 char* last
= &temp
[len
-2];
473 while ( isspace(*last
) ) {
477 orderMapping
[temp
] = ++count
;
480 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
483 bool Options::forceWeak(const char* symbolName
) const
485 return fForceWeakSymbols
.contains(symbolName
);
488 bool Options::forceNotWeak(const char* symbolName
) const
490 return fForceNotWeakSymbols
.contains(symbolName
);
493 bool Options::forceWeakNonWildCard(const char* symbolName
) const
495 return fForceWeakSymbols
.containsNonWildcard(symbolName
);
498 bool Options::forceNotWeakNonWildcard(const char* symbolName
) const
500 return fForceNotWeakSymbols
.containsNonWildcard(symbolName
);
503 bool Options::forceCoalesce(const char* symbolName
) const
505 return fForceCoalesceSymbols
.contains(symbolName
);
509 bool Options::shouldExport(const char* symbolName
) const
511 switch (fExportMode
) {
513 return fExportSymbols
.contains(symbolName
);
514 case kDontExportSome
:
515 return ! fDontExportSymbols
.contains(symbolName
);
519 throw "internal error";
522 bool Options::shouldReExport(const char* symbolName
) const
524 return fReExportSymbols
.contains(symbolName
);
527 bool Options::keepLocalSymbol(const char* symbolName
) const
529 switch (fLocalSymbolHandling
) {
530 case kLocalSymbolsAll
:
532 case kLocalSymbolsNone
:
534 case kLocalSymbolsSelectiveInclude
:
535 return fLocalSymbolsIncluded
.contains(symbolName
);
536 case kLocalSymbolsSelectiveExclude
:
537 return ! fLocalSymbolsExcluded
.contains(symbolName
);
539 throw "internal error";
542 void Options::setArchitecture(cpu_type_t type
, cpu_subtype_t subtype
)
544 for (const ArchInfo
* t
=archInfoArray
; t
->archName
!= NULL
; ++t
) {
545 if ( (type
== t
->cpuType
) && (subtype
== t
->cpuSubType
) ) {
546 fArchitecture
= type
;
547 fSubArchitecture
= subtype
;
548 fArchitectureName
= t
->archName
;
549 fHasPreferredSubType
= t
->isSubType
;
550 fArchSupportsThumb2
= t
->supportsThumb2
;
553 case CPU_TYPE_X86_64
:
554 if ( (fMacVersionMin
== ld::macVersionUnset
) && (fIOSVersionMin
== ld::iOSVersionUnset
) && (fOutputKind
!= Options::kObjectFile
) ) {
555 #ifdef DEFAULT_MACOSX_MIN_VERSION
556 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION
);
557 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
559 warning("-macosx_version_min not specified, assuming 10.6");
560 fMacVersionMin
= ld::mac10_6
;
566 if ( (fMacVersionMin
== ld::macVersionUnset
) && (fIOSVersionMin
== ld::iOSVersionUnset
) && (fOutputKind
!= Options::kObjectFile
) ) {
567 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
568 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION
);
569 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION
);
571 warning("-ios_version_min not specified, assuming 6.0");
572 setIOSVersionMin("6.0");
577 fLinkSnapshot
.recordArch(fArchitectureName
);
578 // only use compressed LINKEDIT for:
579 // Mac OS X 10.6 or later
581 if ( !fMakeCompressedDyldInfo
&& minOS(ld::mac10_6
, ld::iOS_3_1
) && !fMakeCompressedDyldInfoForceOff
)
582 fMakeCompressedDyldInfo
= true;
583 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
584 if ( minOS(ld::mac10_5
, ld::iOS_2_0
) )
585 fUseSimplifiedDylibReExports
= true;
589 fArchitectureName
= "unknown architecture";
592 void Options::parseArch(const char* arch
)
595 throw "-arch must be followed by an architecture string";
596 for (const ArchInfo
* t
=archInfoArray
; t
->archName
!= NULL
; ++t
) {
597 if ( strcmp(t
->archName
,arch
) == 0 ) {
598 fArchitectureName
= arch
;
599 fArchitecture
= t
->cpuType
;
600 fSubArchitecture
= t
->cpuSubType
;
601 fHasPreferredSubType
= t
->isSubType
;
602 fArchSupportsThumb2
= t
->supportsThumb2
;
606 throwf("unknown/unsupported architecture name for: -arch %s", arch
);
609 bool Options::checkForFile(const char* format
, const char* dir
, const char* rootName
, FileInfo
& result
) const
611 char possiblePath
[strlen(dir
)+strlen(rootName
)+strlen(format
)+8];
612 sprintf(possiblePath
, format
, dir
, rootName
);
613 bool found
= result
.checkFileExists(*this, possiblePath
);
614 if ( fTraceDylibSearching
)
615 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), possiblePath
);
620 Options::FileInfo
Options::findLibrary(const char* rootName
, bool dylibsOnly
) const
623 const int rootNameLen
= strlen(rootName
);
624 // if rootName ends in .o there is no .a vs .dylib choice
625 if ( (rootNameLen
> 3) && (strcmp(&rootName
[rootNameLen
-2], ".o") == 0) ) {
626 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
627 it
!= fLibrarySearchPaths
.end();
629 const char* dir
= *it
;
630 if ( checkForFile("%s/%s", dir
, rootName
, result
) )
635 bool lookForDylibs
= false;
636 switch ( fOutputKind
) {
637 case Options::kDynamicExecutable
:
638 case Options::kDynamicLibrary
:
639 case Options::kDynamicBundle
:
640 case Options::kObjectFile
: // <rdar://problem/15914513>
641 lookForDylibs
= true;
643 case Options::kStaticExecutable
:
645 case Options::kPreload
:
646 case Options::kKextBundle
:
647 lookForDylibs
= false;
650 switch ( fLibrarySearchMode
) {
651 case kSearchAllDirsForDylibsThenAllDirsForArchives
:
652 // first look in all directories for just for dylibs
653 if ( lookForDylibs
) {
654 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
655 it
!= fLibrarySearchPaths
.end();
657 const char* dir
= *it
;
658 if ( checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
661 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
662 it
!= fLibrarySearchPaths
.end();
664 const char* dir
= *it
;
665 if ( checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
669 // next look in all directories for just for archives
671 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
672 it
!= fLibrarySearchPaths
.end();
674 const char* dir
= *it
;
675 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
681 case kSearchDylibAndArchiveInEachDir
:
682 // look in each directory for just for a dylib then for an archive
683 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
684 it
!= fLibrarySearchPaths
.end();
686 const char* dir
= *it
;
687 if ( lookForDylibs
&& checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
689 if ( lookForDylibs
&& checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
691 if ( !dylibsOnly
&& checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
697 throwf("library not found for -l%s", rootName
);
700 Options::FileInfo
Options::findFramework(const char* frameworkName
) const
702 if ( frameworkName
== NULL
)
703 throw "-framework missing next argument";
704 char temp
[strlen(frameworkName
)+1];
705 strcpy(temp
, frameworkName
);
706 const char* name
= temp
;
707 const char* suffix
= NULL
;
708 char* comma
= strchr(temp
, ',');
709 if ( comma
!= NULL
) {
713 return findFramework(name
, suffix
);
716 Options::FileInfo
Options::findFramework(const char* rootName
, const char* suffix
) const
718 for (std::vector
<const char*>::const_iterator it
= fFrameworkSearchPaths
.begin();
719 it
!= fFrameworkSearchPaths
.end();
721 // ??? Shouldn't we be using String here and just initializing it?
722 // ??? Use str.c_str () to pull out the string for the stat call.
723 const char* dir
= *it
;
724 char possiblePath
[PATH_MAX
];
725 strcpy(possiblePath
, dir
);
726 strcat(possiblePath
, "/");
727 strcat(possiblePath
, rootName
);
728 strcat(possiblePath
, ".framework/");
729 strcat(possiblePath
, rootName
);
730 if ( suffix
!= NULL
) {
731 char realPath
[PATH_MAX
];
732 // no symlink in framework to suffix variants, so follow main symlink
733 if ( realpath(possiblePath
, realPath
) != NULL
) {
734 strcpy(possiblePath
, realPath
);
735 strcat(possiblePath
, suffix
);
739 bool found
= result
.checkFileExists(*this, possiblePath
);
740 if ( fTraceDylibSearching
)
741 printf("[Logging for XBS]%sfound framework: '%s'\n",
742 (found
? " " : " not "), possiblePath
);
747 // try without suffix
748 if ( suffix
!= NULL
)
749 return findFramework(rootName
, NULL
);
751 throwf("framework not found %s", rootName
);
754 Options::FileInfo
Options::findFile(const char* path
) const
758 // if absolute path and not a .o file, the use SDK prefix
759 if ( (path
[0] == '/') && (strcmp(&path
[strlen(path
)-2], ".o") != 0) ) {
760 const int pathLen
= strlen(path
);
761 for (std::vector
<const char*>::const_iterator it
= fSDKPaths
.begin(); it
!= fSDKPaths
.end(); it
++) {
762 // ??? Shouldn't we be using String here?
763 const char* sdkPathDir
= *it
;
764 const int sdkPathDirLen
= strlen(sdkPathDir
);
765 char possiblePath
[sdkPathDirLen
+pathLen
+4];
766 strcpy(possiblePath
, sdkPathDir
);
767 if ( possiblePath
[sdkPathDirLen
-1] == '/' )
768 possiblePath
[sdkPathDirLen
-1] = '\0';
769 strcat(possiblePath
, path
);
770 if ( result
.checkFileExists(*this, possiblePath
) ) {
776 if ( result
.checkFileExists(*this, path
) ) {
780 // try @executable_path substitution
781 if ( (strncmp(path
, "@executable_path/", 17) == 0) && (fExecutablePath
!= NULL
) ) {
782 char newPath
[strlen(fExecutablePath
) + strlen(path
)];
783 strcpy(newPath
, fExecutablePath
);
784 char* addPoint
= strrchr(newPath
,'/');
785 if ( addPoint
!= NULL
)
786 strcpy(&addPoint
[1], &path
[17]);
788 strcpy(newPath
, &path
[17]);
789 if ( result
.checkFileExists(*this, newPath
) ) {
795 throwf("file not found: %s", path
);
798 Options::FileInfo
Options::findFileUsingPaths(const char* path
) const
802 const char* lastSlash
= strrchr(path
, '/');
803 const char* leafName
= (lastSlash
== NULL
) ? path
: &lastSlash
[1];
805 // Is this in a framework?
806 // /path/Foo.framework/Foo ==> true (Foo)
807 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
808 // /path/Foo.framework/Resources/Bar ==> false
809 bool isFramework
= false;
810 if ( lastSlash
!= NULL
) {
811 char frameworkDir
[strlen(leafName
) + 20];
812 strcpy(frameworkDir
, "/");
813 strcat(frameworkDir
, leafName
);
814 strcat(frameworkDir
, ".framework/");
815 if ( strstr(path
, frameworkDir
) != NULL
)
819 // These are abbreviated versions of the routines findFramework and findLibrary above
820 // because we already know the final name of the file that we're looking for and so
821 // don't need to try variations, just paths. We do need to add the additional bits
822 // onto the framework path though.
824 for (std::vector
<const char*>::const_iterator it
= fFrameworkSearchPaths
.begin();
825 it
!= fFrameworkSearchPaths
.end();
827 const char* dir
= *it
;
828 char possiblePath
[PATH_MAX
];
829 strcpy(possiblePath
, dir
);
830 strcat(possiblePath
, "/");
831 strcat(possiblePath
, leafName
);
832 strcat(possiblePath
, ".framework");
834 //fprintf(stderr,"Finding Framework: %s/%s, leafName=%s\n", possiblePath, leafName, leafName);
835 if ( checkForFile("%s/%s", possiblePath
, leafName
, result
) )
840 // if this is a .dylib inside a framework, do not search -L paths
841 // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
842 int leafLen
= strlen(leafName
);
843 bool embeddedDylib
= ( (leafLen
> 6)
844 && (strcmp(&leafName
[leafLen
-6], ".dylib") == 0)
845 && (strstr(path
, ".framework/") != NULL
) );
846 if ( !embeddedDylib
) {
847 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
848 it
!= fLibrarySearchPaths
.end();
850 const char* dir
= *it
;
851 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
852 if ( checkForFile("%s/%s", dir
, leafName
, result
) )
858 // If we didn't find it fall back to findFile.
859 return findFile(path
);
864 void Options::parseSegAddrTable(const char* segAddrPath
, const char* installPth
)
866 FILE* file
= fopen(segAddrPath
, "r");
867 if ( file
== NULL
) {
868 warning("-seg_addr_table file cannot be read: %s", segAddrPath
);
873 uint64_t firstColumAddress
= 0;
874 uint64_t secondColumAddress
= 0;
875 bool hasSecondColumn
= false;
876 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
877 path
[PATH_MAX
-1] = '\0';
878 char* eol
= strchr(path
, '\n');
881 // ignore lines not starting with 0x number
882 if ( (path
[0] == '0') && (path
[1] == 'x') ) {
884 firstColumAddress
= strtoull(path
, &p
, 16);
885 while ( isspace(*p
) )
887 // see if second column is a number
888 if ( (p
[0] == '0') && (p
[1] == 'x') ) {
889 secondColumAddress
= strtoull(p
, &p
, 16);
890 hasSecondColumn
= true;
891 while ( isspace(*p
) )
894 while ( isspace(*p
) )
897 // remove any trailing whitespace
898 for(char* end
= eol
-1; (end
> p
) && isspace(*end
); --end
)
900 // see if this line is for the dylib being linked
901 if ( strcmp(p
, installPth
) == 0 ) {
902 fBaseAddress
= firstColumAddress
;
903 if ( hasSecondColumn
) {
904 fBaseWritableAddress
= secondColumAddress
;
907 break; // out of while loop
916 void Options::loadFileList(const char* fileOfPaths
, ld::File::Ordinal baseOrdinal
)
919 const char* comma
= strrchr(fileOfPaths
, ',');
920 const char* prefix
= NULL
;
921 if ( comma
!= NULL
) {
922 // <rdar://problem/5907981> -filelist fails with comma in path
923 file
= fopen(fileOfPaths
, "r");
924 if ( file
== NULL
) {
926 int realFileOfPathsLen
= comma
-fileOfPaths
;
927 char realFileOfPaths
[realFileOfPathsLen
+1];
928 strncpy(realFileOfPaths
,fileOfPaths
, realFileOfPathsLen
);
929 realFileOfPaths
[realFileOfPathsLen
] = '\0';
930 file
= fopen(realFileOfPaths
, "r");
932 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", realFileOfPaths
, errno
, strerror(errno
));
933 if ( this->dumpDependencyInfo() )
934 this->dumpDependency(Options::depFileList
, realFileOfPaths
);
938 file
= fopen(fileOfPaths
, "r");
940 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", fileOfPaths
, errno
, strerror(errno
));
941 if ( this->dumpDependencyInfo() )
942 this->dumpDependency(Options::depFileList
, fileOfPaths
);
946 ld::File::Ordinal previousOrdinal
= baseOrdinal
;
947 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
948 path
[PATH_MAX
-1] = '\0';
949 char* eol
= strchr(path
, '\n');
952 if ( prefix
!= NULL
) {
953 char builtPath
[strlen(prefix
)+strlen(path
)+2];
954 strcpy(builtPath
, prefix
);
955 strcat(builtPath
, "/");
956 strcat(builtPath
, path
);
957 if (fPipelineFifo
!= NULL
) {
958 FileInfo info
= FileInfo(builtPath
);
959 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
960 previousOrdinal
= info
.ordinal
;
961 info
.fromFileList
= true;
962 fInputFiles
.push_back(info
);
964 FileInfo info
= findFile(builtPath
);
965 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
966 previousOrdinal
= info
.ordinal
;
967 info
.fromFileList
= true;
968 fInputFiles
.push_back(info
);
972 if (fPipelineFifo
!= NULL
) {
973 FileInfo info
= FileInfo(path
);
974 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
975 previousOrdinal
= info
.ordinal
;
976 info
.fromFileList
= true;
977 fInputFiles
.push_back(info
);
979 FileInfo info
= findFile(path
);
980 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
981 previousOrdinal
= info
.ordinal
;
982 info
.fromFileList
= true;
983 fInputFiles
.push_back(info
);
991 void Options::SetWithWildcards::remove(const NameSet
& toBeRemoved
)
993 for(NameSet::const_iterator it
=toBeRemoved
.begin(); it
!= toBeRemoved
.end(); ++it
) {
994 const char* symbolName
= *it
;
995 NameSet::iterator pos
= fRegular
.find(symbolName
);
996 if ( pos
!= fRegular
.end() )
1001 bool Options::SetWithWildcards::hasWildCards(const char* symbol
)
1003 // an exported symbol name containing *, ?, or [ requires wildcard matching
1004 return ( strpbrk(symbol
, "*?[") != NULL
);
1007 void Options::SetWithWildcards::insert(const char* symbol
)
1009 if ( hasWildCards(symbol
) )
1010 fWildCard
.push_back(symbol
);
1012 fRegular
.insert(symbol
);
1015 bool Options::SetWithWildcards::contains(const char* symbol
) const
1017 // first look at hash table on non-wildcard symbols
1018 if ( fRegular
.find(symbol
) != fRegular
.end() )
1020 // next walk list of wild card symbols looking for a match
1021 for(std::vector
<const char*>::const_iterator it
= fWildCard
.begin(); it
!= fWildCard
.end(); ++it
) {
1022 if ( wildCardMatch(*it
, symbol
) )
1028 bool Options::SetWithWildcards::containsNonWildcard(const char* symbol
) const
1030 // look at hash table on non-wildcard symbols
1031 return ( fRegular
.find(symbol
) != fRegular
.end() );
1036 bool Options::SetWithWildcards::inCharRange(const char*& p
, unsigned char c
) const
1040 while ( *p
!= '\0' ) {
1043 // found beginining [ and ending ]
1044 unsigned char last
= '\0';
1045 for ( const char* s
= b
; s
< e
; ++s
) {
1047 unsigned char next
= *(++s
);
1048 if ( (last
<= c
) && (c
<= next
) )
1065 bool Options::SetWithWildcards::wildCardMatch(const char* pattern
, const char* symbol
) const
1067 const char* s
= symbol
;
1068 for (const char* p
= pattern
; *p
!= '\0'; ++p
) {
1073 for (const char* t
= s
; *t
!= '\0'; ++t
) {
1074 if ( wildCardMatch(&p
[1], t
) )
1084 if ( ! inCharRange(p
, *s
) )
1094 return (*s
== '\0');
1098 void Options::loadExportFile(const char* fileOfExports
, const char* option
, SetWithWildcards
& set
)
1100 if ( fileOfExports
== NULL
)
1101 throwf("missing file after %s", option
);
1102 // read in whole file
1103 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
1105 throwf("can't open %s file: %s", option
, fileOfExports
);
1106 struct stat stat_buf
;
1107 ::fstat(fd
, &stat_buf
);
1108 char* p
= (char*)malloc(stat_buf
.st_size
);
1110 throwf("can't process %s file: %s", option
, fileOfExports
);
1112 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1113 throwf("can't read %s file: %s", option
, fileOfExports
);
1115 if ( this->dumpDependencyInfo() )
1116 this->dumpDependency(Options::depMisc
, fileOfExports
);
1120 // parse into symbols and add to unordered_set
1121 char * const end
= &p
[stat_buf
.st_size
];
1122 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1123 char* symbolStart
= NULL
;
1124 for (char* s
= p
; s
< end
; ++s
) {
1130 else if ( !isspace(*s
) ) {
1136 if ( (*s
== '\n') || (*s
== '\r') ) {
1138 // removing any trailing spaces
1140 while ( isspace(*last
) ) {
1144 set
.insert(symbolStart
);
1150 if ( (*s
== '\n') || (*s
== '\r') )
1155 if ( state
== inSymbol
) {
1156 warning("missing line-end at end of file \"%s\"", fileOfExports
);
1157 int len
= end
-symbolStart
+1;
1158 char* temp
= new char[len
];
1159 strlcpy(temp
, symbolStart
, len
);
1161 // remove any trailing spaces
1162 char* last
= &temp
[len
-2];
1163 while ( isspace(*last
) ) {
1170 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
1173 void Options::parseAliasFile(const char* fileOfAliases
)
1175 // read in whole file
1176 int fd
= ::open(fileOfAliases
, O_RDONLY
, 0);
1178 throwf("can't open alias file: %s", fileOfAliases
);
1179 struct stat stat_buf
;
1180 ::fstat(fd
, &stat_buf
);
1181 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1183 throwf("can't process alias file: %s", fileOfAliases
);
1185 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1186 throwf("can't read alias file: %s", fileOfAliases
);
1187 p
[stat_buf
.st_size
] = '\n';
1189 if ( this->dumpDependencyInfo() )
1190 this->dumpDependency(Options::depMisc
, fileOfAliases
);
1192 // parse into symbols and add to fAliases
1194 char * const end
= &p
[stat_buf
.st_size
+1];
1195 enum { lineStart
, inRealName
, inBetween
, inAliasName
, inComment
} state
= lineStart
;
1197 for (char* s
= p
; s
< end
; ++s
) {
1203 else if ( !isspace(*s
) ) {
1210 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1214 else if ( isspace(*s
) ) {
1221 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1225 else if ( ! isspace(*s
) ) {
1226 state
= inAliasName
;
1233 // removing any trailing spaces
1235 while ( isspace(*last
) ) {
1239 fAliases
.push_back(pair
);
1242 else if ( *s
== '\n' ) {
1244 // removing any trailing spaces
1246 while ( isspace(*last
) ) {
1250 fAliases
.push_back(pair
);
1261 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
1266 void Options::setUndefinedTreatment(const char* treatment
)
1268 if ( treatment
== NULL
)
1269 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
1271 if ( strcmp(treatment
, "warning") == 0 )
1272 fUndefinedTreatment
= kUndefinedWarning
;
1273 else if ( strcmp(treatment
, "error") == 0 )
1274 fUndefinedTreatment
= kUndefinedError
;
1275 else if ( strcmp(treatment
, "suppress") == 0 )
1276 fUndefinedTreatment
= kUndefinedSuppress
;
1277 else if ( strcmp(treatment
, "dynamic_lookup") == 0 )
1278 fUndefinedTreatment
= kUndefinedDynamicLookup
;
1280 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1283 Options::Treatment
Options::parseTreatment(const char* treatment
)
1285 if ( treatment
== NULL
)
1288 if ( strcmp(treatment
, "warning") == 0 )
1290 else if ( strcmp(treatment
, "error") == 0 )
1292 else if ( strcmp(treatment
, "suppress") == 0 )
1298 void Options::setMacOSXVersionMin(const char* version
)
1300 if ( version
== NULL
)
1301 throw "-macosx_version_min argument missing";
1303 if ( (strncmp(version
, "10.", 3) == 0) && isdigit(version
[3]) ) {
1304 unsigned int minorVersion
= 0;
1305 for (int i
=3; isdigit(version
[i
]); ++i
) {
1306 minorVersion
= minorVersion
*10 + (version
[i
] - '0');
1308 if ( minorVersion
> 255 ) {
1309 warning("Mac OS X minor version > 255 in '%s'", version
);
1312 fMacVersionMin
= (ld::MacVersionMin
)(0x000A0000 | (minorVersion
<< 8));
1315 warning("unknown option to -macosx_version_min, not 10.x");
1319 void Options::setIOSVersionMin(const char* version
)
1321 if ( version
== NULL
)
1322 throw "-ios_version_min argument missing";
1323 if ( ! isdigit(version
[0]) )
1324 throw "-ios_version_min argument is not a number";
1325 if ( version
[1] != '.' )
1326 throw "-ios_version_min argument is missing period as second character";
1327 if ( ! isdigit(version
[2]) )
1328 throw "-ios_version_min argument is not a number";
1330 unsigned int majorVersion
= version
[0] - '0';
1331 unsigned int minorVersion
= version
[2] - '0';
1332 fIOSVersionMin
= (ld::IOSVersionMin
)((majorVersion
<< 16) | (minorVersion
<< 8));
1335 bool Options::minOS(ld::MacVersionMin requiredMacMin
, ld::IOSVersionMin requirediPhoneOSMin
)
1337 if ( fMacVersionMin
!= ld::macVersionUnset
) {
1338 return ( fMacVersionMin
>= requiredMacMin
);
1341 return ( fIOSVersionMin
>= requirediPhoneOSMin
);
1346 void Options::setWeakReferenceMismatchTreatment(const char* treatment
)
1348 if ( treatment
== NULL
)
1349 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1351 if ( strcmp(treatment
, "error") == 0 )
1352 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchError
;
1353 else if ( strcmp(treatment
, "weak") == 0 )
1354 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchWeak
;
1355 else if ( strcmp(treatment
, "non-weak") == 0 )
1356 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchNonWeak
;
1358 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1361 Options::CommonsMode
Options::parseCommonsTreatment(const char* mode
)
1364 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1366 if ( strcmp(mode
, "ignore_dylibs") == 0 )
1367 return kCommonsIgnoreDylibs
;
1368 else if ( strcmp(mode
, "use_dylibs") == 0 )
1369 return kCommonsOverriddenByDylibs
;
1370 else if ( strcmp(mode
, "error") == 0 )
1371 return kCommonsConflictsDylibsError
;
1373 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1376 void Options::addDylibOverride(const char* paths
)
1378 if ( paths
== NULL
)
1379 throw "-dylib_file must followed by two colon separated paths";
1380 const char* colon
= strchr(paths
, ':');
1381 if ( colon
== NULL
)
1382 throw "-dylib_file must followed by two colon separated paths";
1383 int len
= colon
-paths
;
1384 char* target
= new char[len
+2];
1385 strncpy(target
, paths
, len
);
1387 DylibOverride entry
;
1388 entry
.installName
= target
;
1389 entry
.useInstead
= &colon
[1];
1390 fDylibOverrides
.push_back(entry
);
1393 uint64_t Options::parseAddress(const char* addr
)
1396 uint64_t result
= strtoull(addr
, &endptr
, 16);
1400 uint32_t Options::parseProtection(const char* prot
)
1402 uint32_t result
= 0;
1403 for(const char* p
= prot
; *p
!= '\0'; ++p
) {
1404 switch(tolower(*p
)) {
1406 result
|= VM_PROT_READ
;
1409 result
|= VM_PROT_WRITE
;
1412 result
|= VM_PROT_EXECUTE
;
1417 throwf("unknown -segprot lettter in %s", prot
);
1425 // Parses number of form A[.B[.B[.D[.E]]]] into a uint64_t where the bits are a24.b10.c10.d10.e10
1427 uint64_t Options::parseVersionNumber64(const char* versionString
)
1435 a
= strtoul(versionString
, &end
, 10);
1436 if ( *end
== '.' ) {
1437 b
= strtoul(&end
[1], &end
, 10);
1438 if ( *end
== '.' ) {
1439 c
= strtoul(&end
[1], &end
, 10);
1440 if ( *end
== '.' ) {
1441 d
= strtoul(&end
[1], &end
, 10);
1442 if ( *end
== '.' ) {
1443 e
= strtoul(&end
[1], &end
, 10);
1448 if ( (*end
!= '\0') || (a
> 0xFFFFFF) || (b
> 0x3FF) || (c
> 0x3FF) || (d
> 0x3FF) || (e
> 0x3FF) )
1449 throwf("malformed 64-bit a.b.c.d.e version number: %s", versionString
);
1451 return (a
<< 40) | ( b
<< 30 ) | ( c
<< 20 ) | ( d
<< 10 ) | e
;
1455 uint32_t Options::currentVersion32() const
1457 // warn if it does not fit into 32 bit vers number
1458 uint32_t a
= (fDylibCurrentVersion
>> 40) & 0xFFFF;
1459 uint32_t b
= (fDylibCurrentVersion
>> 30) & 0xFF;
1460 uint32_t c
= (fDylibCurrentVersion
>> 20) & 0xFF;
1461 uint64_t rep32
= ((uint64_t)a
<< 40) | ((uint64_t)b
<< 30) | ((uint64_t)c
<< 20);
1462 if ( rep32
!= fDylibCurrentVersion
) {
1463 warning("truncating -current_version to fit in 32-bit space used by old mach-o format");
1464 a
= (fDylibCurrentVersion
>> 40) & 0xFFFFFF;
1467 b
= (fDylibCurrentVersion
>> 30) & 0x3FF;
1470 c
= (fDylibCurrentVersion
>> 20) & 0x3FF;
1474 return (a
<< 16) | ( b
<< 8 ) | c
;
1478 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1480 uint32_t Options::parseVersionNumber32(const char* versionString
)
1486 x
= strtoul(versionString
, &end
, 10);
1487 if ( *end
== '.' ) {
1488 y
= strtoul(&end
[1], &end
, 10);
1489 if ( *end
== '.' ) {
1490 z
= strtoul(&end
[1], &end
, 10);
1493 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
1494 throwf("malformed 32-bit x.y.z version number: %s", versionString
);
1496 return (x
<< 16) | ( y
<< 8 ) | z
;
1499 static const char* cstringSymbolName(const char* orderFileString
)
1502 asprintf(&result
, "cstring=%s", orderFileString
);
1503 // convert escaped characters
1505 for(const char* s
=result
; *s
!= '\0'; ++s
, ++d
) {
1543 // hexadecimal value of char
1547 while ( isxdigit(*s
) ) {
1552 value
+= ((toupper(*s
)-'A') + 10);
1559 if ( isdigit(*s
) ) {
1560 // octal value of char
1562 while ( isdigit(*s
) ) {
1563 value
= (value
<< 3) + (*s
-'0');
1578 void Options::parseOrderFile(const char* path
, bool cstring
)
1580 // order files override auto-ordering
1581 fAutoOrderInitializers
= false;
1583 // read in whole file
1584 int fd
= ::open(path
, O_RDONLY
, 0);
1586 throwf("can't open order file: %s", path
);
1587 struct stat stat_buf
;
1588 ::fstat(fd
, &stat_buf
);
1589 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1591 throwf("can't process order file: %s", path
);
1592 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1593 throwf("can't read order file: %s", path
);
1595 p
[stat_buf
.st_size
] = '\n';
1596 if ( this->dumpDependencyInfo() )
1597 this->dumpDependency(Options::depMisc
, path
);
1599 // parse into vector of pairs
1600 char * const end
= &p
[stat_buf
.st_size
+1];
1601 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1602 char* symbolStart
= NULL
;
1603 for (char* s
= p
; s
< end
; ++s
) {
1609 else if ( !isspace(*s
) || cstring
) {
1615 if ( (*s
== '\n') || (!cstring
&& (*s
== '#')) ) {
1616 bool wasComment
= (*s
== '#');
1618 // removing any trailing spaces
1620 while ( isspace(*last
) ) {
1624 // if there is an architecture prefix, only use this symbol it if matches current arch
1625 if ( strncmp(symbolStart
, "ppc:", 4) == 0 ) {
1628 else if ( strncmp(symbolStart
, "ppc64:", 6) == 0 ) {
1631 else if ( strncmp(symbolStart
, "i386:", 5) == 0 ) {
1632 if ( fArchitecture
== CPU_TYPE_I386
)
1633 symbolStart
= &symbolStart
[5];
1637 else if ( strncmp(symbolStart
, "x86_64:", 7) == 0 ) {
1638 if ( fArchitecture
== CPU_TYPE_X86_64
)
1639 symbolStart
= &symbolStart
[7];
1643 else if ( strncmp(symbolStart
, "arm:", 4) == 0 ) {
1644 if ( fArchitecture
== CPU_TYPE_ARM
)
1645 symbolStart
= &symbolStart
[4];
1649 if ( symbolStart
!= NULL
) {
1650 char* objFileName
= NULL
;
1651 char* colon
= strstr(symbolStart
, ".o:");
1652 if ( colon
!= NULL
) {
1654 objFileName
= symbolStart
;
1655 symbolStart
= &colon
[3];
1658 colon
= strstr(symbolStart
, ".o):");
1659 if ( colon
!= NULL
) {
1661 objFileName
= symbolStart
;
1662 symbolStart
= &colon
[4];
1665 // trim leading spaces
1666 while ( isspace(*symbolStart
) )
1668 Options::OrderedSymbol pair
;
1670 pair
.symbolName
= cstringSymbolName(symbolStart
);
1672 pair
.symbolName
= symbolStart
;
1673 pair
.objectFileName
= objFileName
;
1674 fOrderedSymbols
.push_back(pair
);
1689 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1692 void Options::parseSectionOrderFile(const char* segment
, const char* section
, const char* path
)
1694 if ( (strcmp(section
, "__cstring") == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1695 parseOrderFile(path
, true);
1697 else if ( (strncmp(section
, "__literal",9) == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1698 warning("sorting of __literal[4,8,16] sections not supported");
1701 // ignore section information and append all symbol names to global order file
1702 parseOrderFile(path
, false);
1706 void Options::addSection(const char* segment
, const char* section
, const char* path
)
1708 if ( strlen(segment
) > 16 )
1709 throw "-seccreate segment name max 16 chars";
1710 if ( strlen(section
) > 16 ) {
1711 char* tmp
= strdup(section
);
1713 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section
, tmp
);
1717 // read in whole file
1718 int fd
= ::open(path
, O_RDONLY
, 0);
1720 throwf("can't open -sectcreate file: %s", path
);
1721 struct stat stat_buf
;
1722 ::fstat(fd
, &stat_buf
);
1723 char* p
= (char*)malloc(stat_buf
.st_size
);
1725 throwf("can't process -sectcreate file: %s", path
);
1726 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1727 throwf("can't read -sectcreate file: %s", path
);
1730 // record section to create
1731 ExtraSection info
= { segment
, section
, path
, (uint8_t*)p
, stat_buf
.st_size
};
1732 fExtraSections
.push_back(info
);
1735 void Options::addSectionRename(const char* srcSegment
, const char* srcSection
, const char* dstSegment
, const char* dstSection
)
1737 if ( strlen(srcSegment
) > 16 )
1738 throw "-rename_section segment name max 16 chars";
1739 if ( strlen(srcSection
) > 16 )
1740 throw "-rename_section section name max 16 chars";
1741 if ( strlen(dstSegment
) > 16 )
1742 throw "-rename_section segment name max 16 chars";
1743 if ( strlen(dstSection
) > 16 )
1744 throw "-rename_section section name max 16 chars";
1747 info
.fromSegment
= srcSegment
;
1748 info
.fromSection
= srcSection
;
1749 info
.toSegment
= dstSegment
;
1750 info
.toSection
= dstSection
;
1752 fSectionRenames
.push_back(info
);
1756 void Options::addSectionAlignment(const char* segment
, const char* section
, const char* alignmentStr
)
1758 if ( strlen(segment
) > 16 )
1759 throw "-sectalign segment name max 16 chars";
1760 if ( strlen(section
) > 16 )
1761 throw "-sectalign section name max 16 chars";
1763 // argument to -sectalign is a hexadecimal number
1765 unsigned long value
= strtoul(alignmentStr
, &endptr
, 16);
1766 if ( *endptr
!= '\0')
1767 throw "argument for -sectalign is not a hexadecimal number";
1768 if ( value
> 0x8000 )
1769 throw "argument for -sectalign must be less than or equal to 0x8000";
1771 warning("zero is not a valid -sectalign");
1775 // alignment is power of 2 (e.g. page alignment = 12)
1776 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
1777 if ( (unsigned long)(1 << alignment
) != value
) {
1778 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
1779 segment
, section
, 1 << alignment
);
1782 SectionAlignment info
= { segment
, section
, alignment
};
1783 fSectionAlignments
.push_back(info
);
1786 void Options::addLibrary(const FileInfo
& info
)
1788 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
1789 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
1790 if ( strcmp(info
.path
, fit
->path
) == 0 ) {
1791 // if dylib is specified again but weak, record that it should be weak
1792 if ( info
.options
.fWeakImport
)
1793 fit
->options
.fWeakImport
= true;
1798 fInputFiles
.push_back(info
);
1801 void Options::warnObsolete(const char* arg
)
1803 warning("option %s is obsolete and being ignored", arg
);
1810 // Process all command line arguments.
1812 // The only error checking done here is that each option is valid and if it has arguments
1813 // that they too are valid.
1815 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
1816 // whichever was last on the command line is used.
1818 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
1820 void Options::parse(int argc
, const char* argv
[])
1822 // Store the original args in the link snapshot.
1823 fLinkSnapshot
.recordRawArgs(argc
, argv
);
1825 // pass one builds search list from -L and -F options
1826 this->buildSearchPaths(argc
, argv
);
1828 // reduce re-allocations
1829 fInputFiles
.reserve(32);
1831 // pass two parse all other options
1832 for(int i
=1; i
< argc
; ++i
) {
1833 const char* arg
= argv
[i
];
1835 if ( arg
[0] == '-' ) {
1836 // by default, copy one arg to the snapshot link command, and do no file copying
1837 int snapshotArgIndex
= i
;
1838 int snapshotArgCount
= -1; // -1 means compute count based on change in index
1839 int snapshotFileArgIndex
= -1; // -1 means no data file parameter to arg
1841 // Since we don't care about the files passed, just the option names, we do this here.
1843 fprintf (stderr
, "[Logging ld64 options]\t%s\n", arg
);
1845 if ( (arg
[1] == 'L') || (arg
[1] == 'F') ) {
1846 snapshotArgCount
= 0; // stripped out of link snapshot
1849 // previously handled by buildSearchPaths()
1851 // The one gnu style option we have to keep compatibility
1852 // with gcc. Might as well have the single hyphen one as well.
1853 else if ( (strcmp(arg
, "--help") == 0)
1854 || (strcmp(arg
, "-help") == 0)) {
1855 fprintf (stdout
, "ld64: For information on command line options please use 'man ld'.\n");
1858 else if ( strcmp(arg
, "-arch") == 0 ) {
1859 parseArch(argv
[++i
]);
1861 else if ( strcmp(arg
, "-dynamic") == 0 ) {
1864 else if ( strcmp(arg
, "-static") == 0 ) {
1866 if ( (fOutputKind
!= kObjectFile
) && (fOutputKind
!= kKextBundle
) ) {
1867 fOutputKind
= kStaticExecutable
;
1870 else if ( strcmp(arg
, "-dylib") == 0 ) {
1871 fOutputKind
= kDynamicLibrary
;
1873 else if ( strcmp(arg
, "-bundle") == 0 ) {
1874 fOutputKind
= kDynamicBundle
;
1876 else if ( strcmp(arg
, "-dylinker") == 0 ) {
1877 fOutputKind
= kDyld
;
1879 else if ( strcmp(arg
, "-execute") == 0 ) {
1880 if ( fOutputKind
!= kStaticExecutable
)
1881 fOutputKind
= kDynamicExecutable
;
1883 else if ( strcmp(arg
, "-preload") == 0 ) {
1884 fOutputKind
= kPreload
;
1886 else if ( strcmp(arg
, "-r") == 0 ) {
1887 fOutputKind
= kObjectFile
;
1889 else if ( strcmp(arg
, "-kext") == 0 ) {
1890 fOutputKind
= kKextBundle
;
1892 else if ( strcmp(arg
, "-o") == 0 ) {
1893 snapshotArgCount
= 0;
1894 fOutputFile
= argv
[++i
];
1895 fLinkSnapshot
.setSnapshotName(fOutputFile
);
1897 else if ( strncmp(arg
, "-lazy-l", 7) == 0 ) {
1898 snapshotArgCount
= 0;
1899 FileInfo info
= findLibrary(&arg
[7], true);
1900 info
.options
.fLazyLoad
= true;
1901 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
1903 fUsingLazyDylibLinking
= true;
1905 else if ( strcmp(arg
, "-lto_library") == 0 ) {
1906 snapshotFileArgIndex
= 1;
1907 fOverridePathlibLTO
= argv
[++i
];
1908 if ( fOverridePathlibLTO
== NULL
)
1909 throw "missing argument to -lto_library";
1911 else if ( (arg
[1] == 'l') && (strncmp(arg
,"-lazy_",6) !=0) ) {
1912 snapshotArgCount
= 0;
1913 FileInfo info
= findLibrary(&arg
[2]);
1914 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
1917 // This causes a dylib to be weakly bound at
1918 // link time. This corresponds to weak_import.
1919 else if ( strncmp(arg
, "-weak-l", 7) == 0 ) {
1920 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
1921 snapshotArgCount
= 0;
1922 FileInfo info
= findLibrary(&arg
[7]);
1923 info
.options
.fWeakImport
= true;
1924 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
1927 // Avoid lazy binding.
1928 else if ( strcmp(arg
, "-bind_at_load") == 0 ) {
1931 else if ( strcmp(arg
, "-twolevel_namespace") == 0 ) {
1932 fNameSpace
= kTwoLevelNameSpace
;
1934 else if ( strcmp(arg
, "-flat_namespace") == 0 ) {
1935 fNameSpace
= kFlatNameSpace
;
1937 // Also sets a bit to ensure dyld causes everything
1938 // in the namespace to be flat.
1940 else if ( strcmp(arg
, "-force_flat_namespace") == 0 ) {
1941 fNameSpace
= kForceFlatNameSpace
;
1943 // Similar to --whole-archive.
1944 else if ( strcmp(arg
, "-all_load") == 0 ) {
1945 fFullyLoadArchives
= true;
1947 else if ( strcmp(arg
, "-noall_load") == 0) {
1950 // Similar to -all_load
1951 else if ( strcmp(arg
, "-ObjC") == 0 ) {
1952 fLoadAllObjcObjectsFromArchives
= true;
1954 // Similar to -all_load, but for the following archive only.
1955 else if ( strcmp(arg
, "-force_load") == 0 ) {
1956 FileInfo info
= findFile(argv
[++i
]);
1957 info
.options
.fForceLoad
= true;
1958 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
1961 // Library versioning.
1962 else if ( (strcmp(arg
, "-dylib_compatibility_version") == 0)
1963 || (strcmp(arg
, "-compatibility_version") == 0)) {
1964 const char* vers
= argv
[++i
];
1966 throw "-dylib_compatibility_version missing <version>";
1967 fDylibCompatVersion
= parseVersionNumber32(vers
);
1969 else if ( (strcmp(arg
, "-dylib_current_version") == 0)
1970 || (strcmp(arg
, "-current_version") == 0)) {
1971 const char* vers
= argv
[++i
];
1973 throw "-dylib_current_version missing <version>";
1974 fDylibCurrentVersion
= parseVersionNumber64(vers
);
1976 else if ( strcmp(arg
, "-sectorder") == 0 ) {
1977 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
1978 throw "-sectorder missing <segment> <section> <file-path>";
1979 snapshotFileArgIndex
= 3;
1980 parseSectionOrderFile(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1983 else if ( strcmp(arg
, "-order_file") == 0 ) {
1984 snapshotFileArgIndex
= 1;
1985 parseOrderFile(argv
[++i
], false);
1987 else if ( strcmp(arg
, "-order_file_statistics") == 0 ) {
1988 fPrintOrderFileStatistics
= true;
1990 // ??? Deprecate segcreate.
1991 // -sectcreate puts whole files into a section in the output.
1992 else if ( (strcmp(arg
, "-sectcreate") == 0) || (strcmp(arg
, "-segcreate") == 0) ) {
1993 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
1994 throw "-sectcreate missing <segment> <section> <file-path>";
1995 snapshotFileArgIndex
= 3;
1996 addSection(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1999 // Since we have a full path in binary/library names we need to be able to override it.
2000 else if ( (strcmp(arg
, "-dylib_install_name") == 0)
2001 || (strcmp(arg
, "-dylinker_install_name") == 0)
2002 || (strcmp(arg
, "-install_name") == 0)) {
2003 fDylibInstallName
= argv
[++i
];
2004 if ( fDylibInstallName
== NULL
)
2005 throw "-install_name missing <path>";
2007 // Sets the base address of the output.
2008 else if ( (strcmp(arg
, "-seg1addr") == 0) || (strcmp(arg
, "-image_base") == 0) ) {
2009 const char* address
= argv
[++i
];
2010 if ( address
== NULL
)
2011 throwf("%s missing <address>", arg
);
2012 fBaseAddress
= parseAddress(address
);
2013 uint64_t temp
= ((fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
2014 if ( fBaseAddress
!= temp
) {
2015 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment
);
2016 fBaseAddress
= temp
;
2019 else if ( strcmp(arg
, "-e") == 0 ) {
2020 fEntryName
= argv
[++i
];
2022 // Same as -@ from the FSF linker.
2023 else if ( strcmp(arg
, "-filelist") == 0 ) {
2024 snapshotArgCount
= 0;
2025 const char* path
= argv
[++i
];
2026 if ( (path
== NULL
) || (path
[0] == '-') )
2027 throw "-filelist missing <path>";
2028 ld::File::Ordinal baseOrdinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2029 loadFileList(path
, baseOrdinal
);
2031 else if ( strcmp(arg
, "-keep_private_externs") == 0 ) {
2032 fKeepPrivateExterns
= true;
2034 else if ( strcmp(arg
, "-final_output") == 0 ) {
2035 fFinalName
= argv
[++i
];
2037 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
2038 // just ensures that this happens for cross object file boundaries.
2039 else if ( (strcmp(arg
, "-interposable") == 0) || (strcmp(arg
, "-multi_module") == 0)) {
2040 switch ( fInterposeMode
) {
2041 case kInterposeNone
:
2042 case kInterposeAllExternal
:
2043 fInterposeMode
= kInterposeAllExternal
;
2045 case kInterposeSome
:
2046 // do nothing, -interposable_list overrides -interposable"
2050 else if ( strcmp(arg
, "-interposable_list") == 0 ) {
2051 snapshotFileArgIndex
= 1;
2052 fInterposeMode
= kInterposeSome
;
2053 loadExportFile(argv
[++i
], "-interposable_list", fInterposeList
);
2055 // Default for -interposable/-multi_module/-single_module.
2056 else if ( strcmp(arg
, "-single_module") == 0 ) {
2057 fInterposeMode
= kInterposeNone
;
2059 else if ( strcmp(arg
, "-exported_symbols_list") == 0 ) {
2060 snapshotFileArgIndex
= 1;
2061 if ( fExportMode
== kDontExportSome
)
2062 throw "can't use -exported_symbols_list and -unexported_symbols_list";
2063 fExportMode
= kExportSome
;
2064 loadExportFile(argv
[++i
], "-exported_symbols_list", fExportSymbols
);
2066 else if ( strcmp(arg
, "-unexported_symbols_list") == 0 ) {
2067 snapshotFileArgIndex
= 1;
2068 if ( fExportMode
== kExportSome
)
2069 throw "can't use -unexported_symbols_list and -exported_symbols_list";
2070 fExportMode
= kDontExportSome
;
2071 loadExportFile(argv
[++i
], "-unexported_symbols_list", fDontExportSymbols
);
2073 else if ( strcmp(arg
, "-exported_symbol") == 0 ) {
2074 if ( fExportMode
== kDontExportSome
)
2075 throw "can't use -exported_symbol and -unexported_symbols";
2076 fExportMode
= kExportSome
;
2077 fExportSymbols
.insert(argv
[++i
]);
2079 else if ( strcmp(arg
, "-unexported_symbol") == 0 ) {
2080 if ( fExportMode
== kExportSome
)
2081 throw "can't use -unexported_symbol and -exported_symbol";
2082 fExportMode
= kDontExportSome
;
2083 fDontExportSymbols
.insert(argv
[++i
]);
2085 else if ( strcmp(arg
, "-non_global_symbols_no_strip_list") == 0 ) {
2086 snapshotFileArgIndex
= 1;
2087 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveExclude
)
2088 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2089 fLocalSymbolHandling
= kLocalSymbolsSelectiveInclude
;
2090 loadExportFile(argv
[++i
], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded
);
2092 else if ( strcmp(arg
, "-non_global_symbols_strip_list") == 0 ) {
2093 snapshotFileArgIndex
= 1;
2094 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveInclude
)
2095 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2096 fLocalSymbolHandling
= kLocalSymbolsSelectiveExclude
;
2097 loadExportFile(argv
[++i
], "-non_global_symbols_strip_list", fLocalSymbolsExcluded
);
2100 else if ( strcmp(arg
, "-no_arch_warnings") == 0 ) {
2101 fIgnoreOtherArchFiles
= true;
2103 else if ( strcmp(arg
, "-force_cpusubtype_ALL") == 0 ) {
2104 fForceSubtypeAll
= true;
2105 fAllowCpuSubtypeMismatches
= true;
2107 // Similar to -weak-l but uses the absolute path name to the library.
2108 else if ( strcmp(arg
, "-weak_library") == 0 ) {
2109 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2110 snapshotArgCount
= 0;
2111 FileInfo info
= findFile(argv
[++i
]);
2112 info
.options
.fWeakImport
= true;
2113 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2116 else if ( strcmp(arg
, "-lazy_library") == 0 ) {
2117 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2118 snapshotArgCount
= 0;
2119 FileInfo info
= findFile(argv
[++i
]);
2120 info
.options
.fLazyLoad
= true;
2121 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2123 fUsingLazyDylibLinking
= true;
2125 else if ( strcmp(arg
, "-framework") == 0 ) {
2126 snapshotArgCount
= 0;
2127 FileInfo info
= findFramework(argv
[++i
]);
2128 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2131 else if ( strcmp(arg
, "-weak_framework") == 0 ) {
2132 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2133 snapshotArgCount
= 0;
2134 FileInfo info
= findFramework(argv
[++i
]);
2135 info
.options
.fWeakImport
= true;
2136 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2139 else if ( strcmp(arg
, "-lazy_framework") == 0 ) {
2140 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2141 snapshotArgCount
= 0;
2142 FileInfo info
= findFramework(argv
[++i
]);
2143 info
.options
.fLazyLoad
= true;
2144 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2146 fUsingLazyDylibLinking
= true;
2148 else if ( strcmp(arg
, "-search_paths_first") == 0 ) {
2149 // previously handled by buildSearchPaths()
2151 else if ( strcmp(arg
, "-search_dylibs_first") == 0 ) {
2152 // previously handled by buildSearchPaths()
2154 else if ( strcmp(arg
, "-undefined") == 0 ) {
2155 setUndefinedTreatment(argv
[++i
]);
2157 // Debugging output flag.
2158 else if ( strcmp(arg
, "-arch_multiple") == 0 ) {
2159 fMessagesPrefixedWithArchitecture
= true;
2161 // Specify what to do with relocations in read only
2162 // sections like .text. Could be errors, warnings,
2163 // or suppressed. Currently we do nothing with the
2165 else if ( strcmp(arg
, "-read_only_relocs") == 0 ) {
2166 switch ( parseTreatment(argv
[++i
]) ) {
2169 throw "-read_only_relocs missing [ warning | error | suppress ]";
2171 fWarnTextRelocs
= true;
2172 fAllowTextRelocs
= true;
2175 fWarnTextRelocs
= false;
2176 fAllowTextRelocs
= true;
2179 fWarnTextRelocs
= false;
2180 fAllowTextRelocs
= false;
2184 else if ( strcmp(arg
, "-sect_diff_relocs") == 0 ) {
2188 // Warn, error or make strong a mismatch between weak
2189 // and non-weak references.
2190 else if ( strcmp(arg
, "-weak_reference_mismatches") == 0 ) {
2191 setWeakReferenceMismatchTreatment(argv
[++i
]);
2193 // For a deployment target of 10.3 and earlier ld64 will
2194 // prebind an executable with 0s in all addresses that
2195 // are prebound. This can then be fixed up by update_prebinding
2196 // later. Prebinding is less useful on 10.4 and greater.
2197 else if ( strcmp(arg
, "-prebind") == 0 ) {
2200 else if ( strcmp(arg
, "-noprebind") == 0 ) {
2204 else if ( strcmp(arg
, "-prebind_allow_overlap") == 0 ) {
2207 else if ( strcmp(arg
, "-prebind_all_twolevel_modules") == 0 ) {
2210 else if ( strcmp(arg
, "-noprebind_all_twolevel_modules") == 0 ) {
2213 else if ( strcmp(arg
, "-nofixprebinding") == 0 ) {
2216 // This should probably be deprecated when we respect -L and -F
2217 // when searching for libraries.
2218 else if ( strcmp(arg
, "-dylib_file") == 0 ) {
2219 // ignore for snapshot because a stub dylib will be created in the snapshot
2220 snapshotArgCount
= 0;
2221 addDylibOverride(argv
[++i
]);
2223 // What to expand @executable_path to if found in dependent dylibs
2224 else if ( strcmp(arg
, "-executable_path") == 0 ) {
2225 fExecutablePath
= argv
[++i
];
2226 if ( (fExecutablePath
== NULL
) || (fExecutablePath
[0] == '-') )
2227 throw "-executable_path missing <path>";
2228 // if a directory was passed, add / to end
2229 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2230 struct stat statBuffer
;
2231 if ( stat(fExecutablePath
, &statBuffer
) == 0 ) {
2232 if ( (statBuffer
.st_mode
& S_IFMT
) == S_IFDIR
) {
2233 char* pathWithSlash
= new char[strlen(fExecutablePath
)+2];
2234 strcpy(pathWithSlash
, fExecutablePath
);
2235 strcat(pathWithSlash
, "/");
2236 fExecutablePath
= pathWithSlash
;
2240 // Aligns all segments to the power of 2 boundary specified.
2241 else if ( strcmp(arg
, "-segalign") == 0 ) {
2242 const char* size
= argv
[++i
];
2244 throw "-segalign missing <size>";
2245 fSegmentAlignment
= parseAddress(size
);
2246 uint8_t alignment
= (uint8_t)__builtin_ctz(fSegmentAlignment
);
2247 uint32_t p2aligned
= (1 << alignment
);
2248 if ( p2aligned
!= fSegmentAlignment
) {
2249 warning("alignment for -segalign %s is not a power of two, using 0x%X", size
, p2aligned
);
2250 fSegmentAlignment
= p2aligned
;
2253 // Puts a specified segment at a particular address that must
2254 // be a multiple of the segment alignment.
2255 else if ( strcmp(arg
, "-segaddr") == 0 ) {
2257 seg
.name
= argv
[++i
];
2258 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2259 throw "-segaddr missing segName Adddress";
2260 seg
.address
= parseAddress(argv
[++i
]);
2261 uint64_t temp
= ((seg
.address
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
2262 if ( seg
.address
!= temp
)
2263 warning("-segaddr %s not %lld byte aligned", seg
.name
, fSegmentAlignment
);
2264 fCustomSegmentAddresses
.push_back(seg
);
2266 // ??? Deprecate when we deprecate split-seg.
2267 else if ( strcmp(arg
, "-segs_read_only_addr") == 0 ) {
2268 fBaseAddress
= parseAddress(argv
[++i
]);
2270 // ??? Deprecate when we deprecate split-seg.
2271 else if ( strcmp(arg
, "-segs_read_write_addr") == 0 ) {
2272 fBaseWritableAddress
= parseAddress(argv
[++i
]);
2275 // ??? Deprecate when we get rid of basing at build time.
2276 else if ( strcmp(arg
, "-seg_addr_table") == 0 ) {
2277 snapshotFileArgIndex
= 1;
2278 const char* name
= argv
[++i
];
2280 throw "-seg_addr_table missing argument";
2281 fSegAddrTablePath
= name
;
2283 else if ( strcmp(arg
, "-seg_addr_table_filename") == 0 ) {
2287 else if ( strcmp(arg
, "-segprot") == 0 ) {
2289 seg
.name
= argv
[++i
];
2290 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) || (argv
[i
+2] == NULL
) )
2291 throw "-segprot missing segName max-prot init-prot";
2292 seg
.max
= parseProtection(argv
[++i
]);
2293 seg
.init
= parseProtection(argv
[++i
]);
2294 fCustomSegmentProtections
.push_back(seg
);
2296 else if ( strcmp(arg
, "-pagezero_size") == 0 ) {
2297 const char* size
= argv
[++i
];
2299 throw "-pagezero_size missing <size>";
2300 fZeroPageSize
= parseAddress(size
);
2301 uint64_t temp
= fZeroPageSize
& (-4096); // page align
2302 if ( (fZeroPageSize
!= temp
) )
2303 warning("-pagezero_size not page aligned, rounding down");
2304 fZeroPageSize
= temp
;
2306 else if ( strcmp(arg
, "-stack_addr") == 0 ) {
2307 const char* address
= argv
[++i
];
2308 if ( address
== NULL
)
2309 throw "-stack_addr missing <address>";
2310 fStackAddr
= parseAddress(address
);
2312 else if ( strcmp(arg
, "-stack_size") == 0 ) {
2313 const char* size
= argv
[++i
];
2315 throw "-stack_size missing <address>";
2316 fStackSize
= parseAddress(size
);
2317 uint64_t temp
= fStackSize
& (-4096); // page align
2318 if ( (fStackSize
!= temp
) )
2319 warning("-stack_size not page aligned, rounding down");
2321 else if ( strcmp(arg
, "-allow_stack_execute") == 0 ) {
2322 fExecutableStack
= true;
2324 else if ( strcmp(arg
, "-allow_heap_execute") == 0 ) {
2325 fDisableNonExecutableHeap
= true;
2327 else if ( strcmp(arg
, "-sectalign") == 0 ) {
2328 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2329 throw "-sectalign missing <segment> <section> <file-path>";
2330 addSectionAlignment(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2333 else if ( strcmp(arg
, "-sectorder_detail") == 0 ) {
2336 else if ( strcmp(arg
, "-sectobjectsymbols") == 0 ) {
2340 else if ( strcmp(arg
, "-bundle_loader") == 0 ) {
2341 snapshotFileArgIndex
= 1;
2342 fBundleLoader
= argv
[++i
];
2343 if ( (fBundleLoader
== NULL
) || (fBundleLoader
[0] == '-') )
2344 throw "-bundle_loader missing <path>";
2345 FileInfo info
= findFile(fBundleLoader
);
2346 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2347 info
.options
.fBundleLoader
= true;
2348 fInputFiles
.push_back(info
);
2350 else if ( strcmp(arg
, "-private_bundle") == 0 ) {
2353 else if ( strcmp(arg
, "-twolevel_namespace_hints") == 0 ) {
2356 // Use this flag to set default behavior for deployement targets.
2357 else if ( strcmp(arg
, "-macosx_version_min") == 0 ) {
2358 const char* macVers
= argv
[++i
];
2359 const char* envMacVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
2360 const char* enviPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
2361 if ( (envMacVers
!= NULL
) && (enviPhoneVers
!= NULL
) ) {
2362 // <rdar://problem/13774329> when conflicting deployments set, break tie by looking at syslibroot
2363 warning("both MACOSX_DEPLOYMENT_TARGET and IPHONEOS_DEPLOYMENT_TARGET are set");
2364 if ( !fSDKPaths
.empty() ) {
2365 const char* sysrootPath
= fSDKPaths
.back();
2366 const char* lastSlash
= strrchr(sysrootPath
, '/');
2367 if ( strstr(lastSlash
, "Simulator") != NULL
)
2368 setIOSVersionMin(enviPhoneVers
);
2370 setMacOSXVersionMin(macVers
);
2373 setMacOSXVersionMin(macVers
);
2377 setMacOSXVersionMin(macVers
);
2380 else if ( (strcmp(arg
, "-ios_version_min") == 0) || (strcmp(arg
, "-iphoneos_version_min") == 0) ) {
2381 setIOSVersionMin(argv
[++i
]);
2383 else if ( strcmp(arg
, "-ios_simulator_version_min") == 0 ) {
2384 setIOSVersionMin(argv
[++i
]);
2385 fTargetIOSSimulator
= true;
2387 else if ( strcmp(arg
, "-multiply_defined") == 0 ) {
2388 //warnObsolete(arg);
2391 else if ( strcmp(arg
, "-multiply_defined_unused") == 0 ) {
2395 else if ( strcmp(arg
, "-nomultidefs") == 0 ) {
2398 // Display each file in which the argument symbol appears and whether
2399 // the file defines or references it. This option takes an argument
2400 // as -y<symbol> note that there is no space.
2401 else if ( strncmp(arg
, "-y", 2) == 0 ) {
2404 // Same output as -y, but output <arg> number of undefined symbols only.
2405 else if ( strcmp(arg
, "-Y") == 0 ) {
2406 //warnObsolete(arg);
2409 // This option affects all objects linked into the final result.
2410 else if ( strcmp(arg
, "-m") == 0 ) {
2413 else if ( (strcmp(arg
, "-why_load") == 0) || (strcmp(arg
, "-whyload") == 0) ) {
2416 else if ( strcmp(arg
, "-why_live") == 0 ) {
2417 const char* name
= argv
[++i
];
2419 throw "-why_live missing symbol name argument";
2420 fWhyLive
.insert(name
);
2422 else if ( strcmp(arg
, "-u") == 0 ) {
2423 const char* name
= argv
[++i
];
2425 throw "-u missing argument";
2426 fInitialUndefines
.push_back(name
);
2428 else if ( strcmp(arg
, "-U") == 0 ) {
2429 const char* name
= argv
[++i
];
2431 throw "-U missing argument";
2432 fAllowedUndefined
.insert(name
);
2434 else if ( strcmp(arg
, "-s") == 0 ) {
2436 fLocalSymbolHandling
= kLocalSymbolsNone
;
2437 fDebugInfoStripping
= Options::kDebugInfoNone
;
2439 else if ( strcmp(arg
, "-x") == 0 ) {
2440 fLocalSymbolHandling
= kLocalSymbolsNone
;
2442 else if ( strcmp(arg
, "-S") == 0 ) {
2443 fDebugInfoStripping
= Options::kDebugInfoNone
;
2445 else if ( strcmp(arg
, "-X") == 0 ) {
2448 else if ( strcmp(arg
, "-Si") == 0 ) {
2450 fDebugInfoStripping
= Options::kDebugInfoFull
;
2452 else if ( strcmp(arg
, "-b") == 0 ) {
2455 else if ( strcmp(arg
, "-Sn") == 0 ) {
2457 fDebugInfoStripping
= Options::kDebugInfoFull
;
2459 else if ( strcmp(arg
, "-Sp") == 0 ) {
2462 else if ( strcmp(arg
, "-dead_strip") == 0 ) {
2465 else if ( strcmp(arg
, "-no_dead_strip_inits_and_terms") == 0 ) {
2468 else if ( strcmp(arg
, "-w") == 0 ) {
2469 // previously handled by buildSearchPaths()
2471 else if ( strcmp(arg
, "-fatal_warnings") == 0 ) {
2472 // previously handled by buildSearchPaths()
2474 else if ( strcmp(arg
, "-arch_errors_fatal") == 0 ) {
2475 fErrorOnOtherArchFiles
= true;
2477 else if ( strcmp(arg
, "-M") == 0 ) {
2480 else if ( strcmp(arg
, "-headerpad") == 0 ) {
2481 const char* size
= argv
[++i
];
2483 throw "-headerpad missing argument";
2484 fMinimumHeaderPad
= parseAddress(size
);
2486 else if ( strcmp(arg
, "-headerpad_max_install_names") == 0 ) {
2487 fMaxMinimumHeaderPad
= true;
2489 else if ( strcmp(arg
, "-t") == 0 ) {
2490 fLogAllFiles
= true;
2492 else if ( strcmp(arg
, "-whatsloaded") == 0 ) {
2493 fLogObjectFiles
= true;
2495 else if ( strcmp(arg
, "-A") == 0 ) {
2499 else if ( strcmp(arg
, "-umbrella") == 0 ) {
2500 const char* name
= argv
[++i
];
2502 throw "-umbrella missing argument";
2503 fUmbrellaName
= name
;
2505 else if ( strcmp(arg
, "-allowable_client") == 0 ) {
2506 const char* name
= argv
[++i
];
2509 throw "-allowable_client missing argument";
2511 fAllowableClients
.push_back(name
);
2513 else if ( strcmp(arg
, "-client_name") == 0 ) {
2514 const char* name
= argv
[++i
];
2517 throw "-client_name missing argument";
2521 else if ( strcmp(arg
, "-sub_umbrella") == 0 ) {
2522 const char* name
= argv
[++i
];
2524 throw "-sub_umbrella missing argument";
2525 fSubUmbellas
.push_back(name
);
2527 else if ( strcmp(arg
, "-sub_library") == 0 ) {
2528 const char* name
= argv
[++i
];
2530 throw "-sub_library missing argument";
2531 fSubLibraries
.push_back(name
);
2533 else if ( strcmp(arg
, "-init") == 0 ) {
2534 const char* name
= argv
[++i
];
2536 throw "-init missing argument";
2537 fInitFunctionName
= name
;
2539 else if ( strcmp(arg
, "-dot") == 0 ) {
2540 const char* name
= argv
[++i
];
2542 throw "-dot missing argument";
2543 fDotOutputFile
= name
;
2545 else if ( strcmp(arg
, "-warn_commons") == 0 ) {
2546 fWarnCommons
= true;
2548 else if ( strcmp(arg
, "-commons") == 0 ) {
2549 fCommonsMode
= parseCommonsTreatment(argv
[++i
]);
2551 else if ( strcmp(arg
, "-keep_relocs") == 0 ) {
2552 fKeepRelocations
= true;
2554 else if ( strcmp(arg
, "-warn_stabs") == 0 ) {
2557 else if ( strcmp(arg
, "-pause") == 0 ) {
2560 else if ( strcmp(arg
, "-print_statistics") == 0 ) {
2563 else if ( strcmp(arg
, "-d") == 0 ) {
2564 fMakeTentativeDefinitionsReal
= true;
2566 else if ( strcmp(arg
, "-v") == 0 ) {
2567 // previously handled by buildSearchPaths()
2569 else if ( strcmp(arg
, "-Z") == 0 ) {
2570 // previously handled by buildSearchPaths()
2572 else if ( strcmp(arg
, "-syslibroot") == 0 ) {
2573 snapshotArgCount
= 0;
2575 // previously handled by buildSearchPaths()
2577 else if ( strcmp(arg
, "-no_uuid") == 0 ) {
2578 fUUIDMode
= kUUIDNone
;
2580 else if ( strcmp(arg
, "-random_uuid") == 0 ) {
2581 fUUIDMode
= kUUIDRandom
;
2583 else if ( strcmp(arg
, "-dtrace") == 0 ) {
2584 snapshotFileArgIndex
= 1;
2585 const char* name
= argv
[++i
];
2587 throw "-dtrace missing argument";
2588 fDtraceScriptName
= name
;
2590 else if ( strcmp(arg
, "-root_safe") == 0 ) {
2593 else if ( strcmp(arg
, "-setuid_safe") == 0 ) {
2596 else if ( strcmp(arg
, "-alias") == 0 ) {
2597 Options::AliasPair pair
;
2598 pair
.realName
= argv
[++i
];
2599 if ( pair
.realName
== NULL
)
2600 throw "missing argument to -alias";
2601 pair
.alias
= argv
[++i
];
2602 if ( pair
.alias
== NULL
)
2603 throw "missing argument to -alias";
2604 fAliases
.push_back(pair
);
2606 else if ( strcmp(arg
, "-alias_list") == 0 ) {
2607 snapshotFileArgIndex
= 1;
2608 parseAliasFile(argv
[++i
]);
2610 else if ( strcmp(arg
, "-save-temps") == 0 ) {
2611 fSaveTempFiles
= true;
2613 else if ( strcmp(arg
, "-rpath") == 0 ) {
2614 const char* path
= argv
[++i
];
2616 throw "missing argument to -rpath";
2617 fRPaths
.push_back(path
);
2619 else if ( strcmp(arg
, "-read_only_stubs") == 0 ) {
2620 fReadOnlyx86Stubs
= true;
2622 else if ( strcmp(arg
, "-slow_stubs") == 0 ) {
2625 else if ( strcmp(arg
, "-map") == 0 ) {
2626 fMapPath
= argv
[++i
];
2627 if ( fMapPath
== NULL
)
2628 throw "missing argument to -map";
2630 else if ( strcmp(arg
, "-pie") == 0 ) {
2631 fPositionIndependentExecutable
= true;
2632 fPIEOnCommandLine
= true;
2634 else if ( strcmp(arg
, "-no_pie") == 0 ) {
2635 fDisablePositionIndependentExecutable
= true;
2637 else if ( strncmp(arg
, "-reexport-l", 11) == 0 ) {
2638 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2639 snapshotArgCount
= 0;
2640 FileInfo info
= findLibrary(&arg
[11], true);
2641 info
.options
.fReExport
= true;
2642 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2645 else if ( strcmp(arg
, "-reexport_library") == 0 ) {
2646 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2647 snapshotArgCount
= 0;
2648 FileInfo info
= findFile(argv
[++i
]);
2649 info
.options
.fReExport
= true;
2650 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2653 else if ( strcmp(arg
, "-reexport_framework") == 0 ) {
2654 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2655 snapshotArgCount
= 0;
2656 FileInfo info
= findFramework(argv
[++i
]);
2657 info
.options
.fReExport
= true;
2658 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2661 else if ( strncmp(arg
, "-upward-l", 9) == 0 ) {
2662 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2663 snapshotArgCount
= 0;
2664 FileInfo info
= findLibrary(&arg
[9], true);
2665 info
.options
.fUpward
= true;
2666 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2669 else if ( strcmp(arg
, "-upward_library") == 0 ) {
2670 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2671 snapshotArgCount
= 0;
2672 FileInfo info
= findFile(argv
[++i
]);
2673 info
.options
.fUpward
= true;
2674 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2677 else if ( strcmp(arg
, "-upward_framework") == 0 ) {
2678 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2679 snapshotArgCount
= 0;
2680 FileInfo info
= findFramework(argv
[++i
]);
2681 info
.options
.fUpward
= true;
2682 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2685 else if ( strcmp(arg
, "-dead_strip_dylibs") == 0 ) {
2686 fDeadStripDylibs
= true;
2688 else if ( strcmp(arg
, "-no_implicit_dylibs") == 0 ) {
2689 fImplicitlyLinkPublicDylibs
= false;
2691 else if ( strcmp(arg
, "-new_linker") == 0 ) {
2694 else if ( strcmp(arg
, "-no_encryption") == 0 ) {
2695 fEncryptable
= false;
2697 else if ( strcmp(arg
, "-no_compact_unwind") == 0 ) {
2698 fAddCompactUnwindEncoding
= false;
2700 else if ( strcmp(arg
, "-mllvm") == 0 ) {
2701 const char* opts
= argv
[++i
];
2703 throw "missing argument to -mllvm";
2704 fLLVMOptions
.push_back(opts
);
2706 else if ( strcmp(arg
, "-mcpu") == 0 ) {
2707 const char* cpu
= argv
[++i
];
2709 throw "missing argument to -mcpu";
2712 else if ( strcmp(arg
, "-no_order_inits") == 0 ) {
2713 fAutoOrderInitializers
= false;
2715 else if ( strcmp(arg
, "-no_order_data") == 0 ) {
2718 else if ( strcmp(arg
, "-seg_page_size") == 0 ) {
2720 seg
.name
= argv
[++i
];
2721 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2722 throw "-seg_page_size missing segName Adddress";
2723 seg
.size
= parseAddress(argv
[++i
]);
2724 uint64_t temp
= seg
.size
& (-4096); // page align
2725 if ( (seg
.size
!= temp
) )
2726 warning("-seg_page_size %s not 4K aligned, rounding down", seg
.name
);
2727 fCustomSegmentSizes
.push_back(seg
);
2729 else if ( strcmp(arg
, "-mark_dead_strippable_dylib") == 0 ) {
2730 fMarkDeadStrippableDylib
= true;
2732 else if ( strcmp(arg
, "-exported_symbols_order") == 0 ) {
2733 snapshotFileArgIndex
= 1;
2734 loadSymbolOrderFile(argv
[++i
], fExportSymbolsOrder
);
2736 else if ( strcmp(arg
, "-no_compact_linkedit") == 0 ) {
2737 warnObsolete("-no_compact_linkedit");
2739 else if ( strcmp(arg
, "-no_eh_labels") == 0 ) {
2742 else if ( strcmp(arg
, "-warn_compact_unwind") == 0 ) {
2743 fWarnCompactUnwind
= true;
2745 else if ( strcmp(arg
, "-allow_sub_type_mismatches") == 0 ) {
2746 fAllowCpuSubtypeMismatches
= true;
2748 else if ( strcmp(arg
, "-no_zero_fill_sections") == 0 ) {
2749 fOptimizeZeroFill
= false;
2751 else if ( strcmp(arg
, "-merge_zero_fill_sections") == 0 ) {
2752 fMergeZeroFill
= true;
2754 else if ( strcmp(arg
, "-objc_abi_version") == 0 ) {
2755 const char* version
= argv
[++i
];
2756 if ( version
== NULL
)
2757 throw "-objc_abi_version missing version number";
2758 if ( strcmp(version
, "2") == 0 ) {
2759 fObjCABIVersion1Override
= false;
2760 fObjCABIVersion2Override
= true;
2762 else if ( strcmp(version
, "1") == 0 ) {
2763 fObjCABIVersion1Override
= true;
2764 fObjCABIVersion2Override
= false;
2767 warning("ignoring unrecognized argument (%s) to -objc_abi_version", version
);
2769 else if ( strcmp(arg
, "-warn_weak_exports") == 0 ) {
2770 fWarnWeakExports
= true;
2772 else if ( strcmp(arg
, "-objc_gc_compaction") == 0 ) {
2773 fObjcGcCompaction
= true;
2775 else if ( strcmp(arg
, "-objc_gc") == 0 ) {
2777 if ( fObjCGcOnly
) {
2778 warning("-objc_gc overriding -objc_gc_only");
2779 fObjCGcOnly
= false;
2782 else if ( strcmp(arg
, "-objc_gc_only") == 0 ) {
2785 warning("-objc_gc_only overriding -objc_gc");
2789 else if ( strcmp(arg
, "-demangle") == 0 ) {
2792 else if ( strcmp(arg
, "-version_load_command") == 0 ) {
2793 fVersionLoadCommandForcedOn
= true;
2794 fVersionLoadCommandForcedOff
= false;
2796 else if ( strcmp(arg
, "-no_version_load_command") == 0 ) {
2797 fVersionLoadCommandForcedOff
= true;
2798 fVersionLoadCommandForcedOn
= false;
2800 else if ( strcmp(arg
, "-function_starts") == 0 ) {
2801 fFunctionStartsForcedOn
= true;
2802 fFunctionStartsForcedOff
= false;
2804 else if ( strcmp(arg
, "-no_function_starts") == 0 ) {
2805 fFunctionStartsForcedOff
= true;
2806 fFunctionStartsForcedOn
= false;
2808 else if ( strcmp(arg
, "-no_data_in_code_info") == 0 ) {
2809 fDataInCodeInfoLoadCommandForcedOff
= true;
2810 fDataInCodeInfoLoadCommandForcedOn
= false;
2812 else if ( strcmp(arg
, "-data_in_code_info") == 0 ) {
2813 fDataInCodeInfoLoadCommandForcedOn
= true;
2814 fDataInCodeInfoLoadCommandForcedOff
= false;
2816 else if ( strcmp(arg
, "-object_path_lto") == 0 ) {
2817 fTempLtoObjectPath
= argv
[++i
];
2818 if ( fTempLtoObjectPath
== NULL
)
2819 throw "missing argument to -object_path_lto";
2821 else if ( strcmp(arg
, "-no_objc_category_merging") == 0 ) {
2822 fObjcCategoryMerging
= false;
2824 else if ( strcmp(arg
, "-force_symbols_weak_list") == 0 ) {
2825 snapshotFileArgIndex
= 1;
2826 loadExportFile(argv
[++i
], "-force_symbols_weak_list", fForceWeakSymbols
);
2828 else if ( strcmp(arg
, "-force_symbols_not_weak_list") == 0 ) {
2829 snapshotFileArgIndex
= 1;
2830 loadExportFile(argv
[++i
], "-force_symbols_not_weak_list", fForceNotWeakSymbols
);
2832 else if ( strcmp(arg
, "-force_symbol_weak") == 0 ) {
2833 const char* symbol
= argv
[++i
];
2834 if ( symbol
== NULL
)
2835 throw "-force_symbol_weak missing <symbol>";
2836 fForceWeakSymbols
.insert(symbol
);
2838 else if ( strcmp(arg
, "-force_symbol_not_weak") == 0 ) {
2839 const char* symbol
= argv
[++i
];
2840 if ( symbol
== NULL
)
2841 throw "-force_symbol_not_weak missing <symbol>";
2842 fForceNotWeakSymbols
.insert(symbol
);
2844 else if ( strcmp(arg
, "-reexported_symbols_list") == 0 ) {
2845 snapshotFileArgIndex
= 1;
2846 if ( fExportMode
== kExportSome
)
2847 throw "can't use -exported_symbols_list and -reexported_symbols_list";
2848 loadExportFile(argv
[++i
], "-reexported_symbols_list", fReExportSymbols
);
2850 else if ( strcmp(arg
, "-dyld_env") == 0 ) {
2851 const char* envarg
= argv
[++i
];
2852 if ( envarg
== NULL
)
2853 throw "-dyld_env missing ENV=VALUE";
2854 if ( strchr(envarg
, '=') == NULL
)
2855 throw "-dyld_env missing ENV=VALUE";
2856 fDyldEnvironExtras
.push_back(envarg
);
2858 else if ( strcmp(arg
, "-page_align_data_atoms") == 0 ) {
2859 fPageAlignDataAtoms
= true;
2861 else if (strcmp(arg
, "-debug_snapshot") == 0) {
2862 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
2863 fSnapshotRequested
= true;
2865 else if (strcmp(arg
, "-snapshot_dir") == 0) {
2866 const char* path
= argv
[++i
];
2868 throw "-snapshot_dir missing path";
2869 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
2870 fLinkSnapshot
.setSnapshotPath(path
);
2871 fSnapshotRequested
= true;
2873 else if ( strcmp(arg
, "-new_main") == 0 ) {
2874 fEntryPointLoadCommandForceOn
= true;
2876 else if ( strcmp(arg
, "-no_new_main") == 0 ) {
2877 fEntryPointLoadCommandForceOff
= true;
2879 else if ( strcmp(arg
, "-source_version") == 0 ) {
2880 const char* vers
= argv
[++i
];
2882 throw "-source_version missing <version>";
2883 fSourceVersion
= parseVersionNumber64(vers
);
2885 else if ( strcmp(arg
, "-add_source_version") == 0 ) {
2886 fSourceVersionLoadCommandForceOn
= true;
2888 else if ( strcmp(arg
, "-no_source_version") == 0 ) {
2889 fSourceVersionLoadCommandForceOff
= true;
2891 else if ( strcmp(arg
, "-sdk_version") == 0 ) {
2892 const char* vers
= argv
[++i
];
2894 throw "-sdk_version missing <version>";
2895 fSDKVersion
= parseVersionNumber32(vers
);
2897 else if ( strcmp(arg
, "-dependent_dr_info") == 0 ) {
2898 fDependentDRInfoForcedOn
= true;
2900 else if ( strcmp(arg
, "-no_dependent_dr_info") == 0 ) {
2901 fDependentDRInfoForcedOff
= true;
2903 else if ( strcmp(arg
, "-kexts_use_stubs") == 0 ) {
2904 fKextsUseStubs
= true;
2906 else if ( strcmp(argv
[i
], "-dependency_info") == 0 ) {
2908 // previously handled by buildSearchPaths()
2910 else if ( strcmp(arg
, "-export_dynamic") == 0 ) {
2911 fExportDynamic
= true;
2913 else if ( strcmp(arg
, "-force_symbols_coalesce_list") == 0 ) {
2914 snapshotFileArgIndex
= 1;
2915 loadExportFile(argv
[++i
], "-force_symbols_coalesce_list", fForceCoalesceSymbols
);
2917 else if ( strcmp(arg
, "-add_linker_option") == 0 ) {
2918 // ex: -add_linker_option '-framework Foundation'
2919 const char* optString
= argv
[++i
];
2920 if ( optString
== NULL
)
2921 throw "-add_linker_option missing <option>";
2922 // break up into list of tokens at whitespace
2923 std::vector
<const char*> opts
;
2924 char* buffer
= strdup(optString
);
2925 char* start
= buffer
;
2926 for (char* s
= buffer
; ; ++s
) {
2927 if ( isspace(*s
) ) {
2929 opts
.push_back(start
);
2932 else if ( *s
== '\0' ) {
2933 opts
.push_back(start
);
2937 fLinkerOptions
.push_back(opts
);
2939 else if ( strcmp(arg
, "-allow_simulator_linking_to_macosx_dylibs") == 0 ) {
2940 fAllowSimulatorToLinkWithMacOSX
= true;
2942 else if ( strcmp(arg
, "-keep_dwarf_unwind") == 0 ) {
2943 fKeepDwarfUnwindForcedOn
= true;
2944 fKeepDwarfUnwindForcedOff
= false;
2946 else if ( strcmp(arg
, "-no_keep_dwarf_unwind") == 0 ) {
2947 fKeepDwarfUnwindForcedOn
= false;
2948 fKeepDwarfUnwindForcedOff
= true;
2950 else if ( strcmp(arg
, "-verbose_optimization_hints") == 0 ) {
2951 fVerboseOptimizationHints
= true;
2953 else if ( strcmp(arg
, "-ignore_optimization_hints") == 0 ) {
2954 fIgnoreOptimizationHints
= true;
2956 else if ( strcmp(arg
, "-no_dtrace_dof") == 0 ) {
2957 fGenerateDtraceDOF
= false;
2959 else if ( strcmp(arg
, "-rename_section") == 0 ) {
2960 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) || (argv
[i
+4]==NULL
) )
2961 throw "-rename_section missing <segment> <section> <segment> <section>";
2962 addSectionRename(argv
[i
+1], argv
[i
+2], argv
[i
+3], argv
[i
+4]);
2965 else if ( strcmp(arg
, "-no_branch_islands") == 0 ) {
2966 fAllowBranchIslands
= false;
2968 // put this last so that it does not interfer with other options starting with 'i'
2969 else if ( strncmp(arg
, "-i", 2) == 0 ) {
2970 const char* colon
= strchr(arg
, ':');
2971 if ( colon
== NULL
)
2972 throwf("unknown option: %s", arg
);
2973 Options::AliasPair pair
;
2974 char* temp
= new char[colon
-arg
];
2975 strlcpy(temp
, &arg
[2], colon
-arg
-1);
2976 pair
.realName
= &colon
[1];
2978 fAliases
.push_back(pair
);
2981 throwf("unknown option: %s", arg
);
2984 if (snapshotArgCount
== -1)
2985 snapshotArgCount
= i
-snapshotArgIndex
+1;
2986 if (snapshotArgCount
> 0)
2987 fLinkSnapshot
.addSnapshotLinkArg(snapshotArgIndex
, snapshotArgCount
, snapshotFileArgIndex
);
2990 FileInfo info
= findFile(arg
);
2991 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2992 if ( strcmp(&info
.path
[strlen(info
.path
)-2], ".a") == 0 )
2995 fInputFiles
.push_back(info
);
2999 // if a -lazy option was used, implicitly link in lazydylib1.o
3000 if ( fUsingLazyDylibLinking
) {
3001 FileInfo info
= findLibrary("lazydylib1.o");
3002 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)argc
);
3006 if (fSnapshotRequested
)
3007 fLinkSnapshot
.createSnapshot();
3013 // -syslibroot <path> is used for SDK support.
3014 // The rule is that all search paths (both explicit and default) are
3015 // checked to see if they exist in the SDK. If so, that path is
3016 // replaced with the sdk prefixed path. If not, that search path
3017 // is used as is. If multiple -syslibroot options are specified
3018 // their directory structures are logically overlayed and files
3019 // from sdks specified earlier on the command line used before later ones.
3021 void Options::buildSearchPaths(int argc
, const char* argv
[])
3023 bool addStandardLibraryDirectories
= true;
3024 std::vector
<const char*> libraryPaths
;
3025 std::vector
<const char*> frameworkPaths
;
3026 libraryPaths
.reserve(10);
3027 frameworkPaths
.reserve(10);
3028 // scan through argv looking for -L, -F, -Z, and -syslibroot options
3029 for(int i
=0; i
< argc
; ++i
) {
3030 if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'L') ) {
3031 const char* libSearchDir
= &argv
[i
][2];
3032 // Allow either "-L{path}" or "-L {path}".
3033 if (argv
[i
][2] == '\0') {
3034 // -L {path}. Make sure there is an argument following this.
3035 const char* path
= argv
[++i
];
3037 throw "-L missing argument";
3038 libSearchDir
= path
;
3040 if ( libSearchDir
[0] == '\0' )
3041 throw "-L must be immediately followed by a directory path (no space)";
3042 struct stat statbuf
;
3043 if ( stat(libSearchDir
, &statbuf
) == 0 ) {
3044 if ( statbuf
.st_mode
& S_IFDIR
)
3045 libraryPaths
.push_back(libSearchDir
);
3047 warning("path '%s' following -L not a directory", libSearchDir
);
3050 warning("directory not found for option '-L%s'", libSearchDir
);
3053 else if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'F') ) {
3054 const char* frameworkSearchDir
= &argv
[i
][2];
3055 // Allow either "-F{path}" or "-F {path}".
3056 if (argv
[i
][2] == '\0') {
3057 // -F {path}. Make sure there is an argument following this.
3058 const char* path
= argv
[++i
];
3060 throw "-F missing argument";
3061 frameworkSearchDir
= path
;
3063 if ( frameworkSearchDir
[0] == '\0' )
3064 throw "-F must be immediately followed by a directory path (no space)";
3065 struct stat statbuf
;
3066 if ( stat(frameworkSearchDir
, &statbuf
) == 0 ) {
3067 if ( statbuf
.st_mode
& S_IFDIR
)
3068 frameworkPaths
.push_back(frameworkSearchDir
);
3070 warning("path '%s' following -F not a directory", frameworkSearchDir
);
3073 warning("directory not found for option '-F%s'", frameworkSearchDir
);
3076 else if ( strcmp(argv
[i
], "-Z") == 0 )
3077 addStandardLibraryDirectories
= false;
3078 else if ( strcmp(argv
[i
], "-v") == 0 ) {
3080 extern const char ldVersionString
[];
3081 fprintf(stderr
, "%s", ldVersionString
);
3082 fprintf(stderr
, "configured to support archs: %s\n", ALL_SUPPORTED_ARCHS
);
3083 // if only -v specified, exit cleanly
3085 const char* ltoVers
= lto::version();
3086 if ( ltoVers
!= NULL
)
3087 fprintf(stderr
, "LTO support using: %s\n", ltoVers
);
3091 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
3092 const char* path
= argv
[++i
];
3094 throw "-syslibroot missing argument";
3095 fSDKPaths
.push_back(path
);
3097 else if ( strcmp(argv
[i
], "-search_paths_first") == 0 ) {
3098 fLibrarySearchMode
= kSearchDylibAndArchiveInEachDir
;
3100 else if ( strcmp(argv
[i
], "-search_dylibs_first") == 0 ) {
3101 fLibrarySearchMode
= kSearchAllDirsForDylibsThenAllDirsForArchives
;
3103 else if ( strcmp(argv
[i
], "-w") == 0 ) {
3104 sEmitWarnings
= false;
3106 else if ( strcmp(argv
[i
], "-fatal_warnings") == 0 ) {
3107 sFatalWarnings
= true;
3109 else if ( strcmp(argv
[i
], "-dependency_info") == 0 ) {
3110 const char* path
= argv
[++i
];
3112 throw "-dependency_info missing <path>";
3113 fDependencyInfoPath
= path
;
3116 int standardLibraryPathsStartIndex
= libraryPaths
.size();
3117 int standardFrameworkPathsStartIndex
= frameworkPaths
.size();
3118 if ( addStandardLibraryDirectories
) {
3119 libraryPaths
.push_back("/usr/lib");
3120 libraryPaths
.push_back("/usr/local/lib");
3122 frameworkPaths
.push_back("/Library/Frameworks/");
3123 frameworkPaths
.push_back("/System/Library/Frameworks/");
3124 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
3127 // <rdar://problem/5829579> Support for configure based hacks
3128 // if last -syslibroot is /, then ignore all syslibroots
3129 if ( fSDKPaths
.size() > 0 ) {
3130 if ( strcmp(fSDKPaths
.back(), "/") == 0 ) {
3135 // now merge sdk and library paths to make real search paths
3136 fLibrarySearchPaths
.reserve(libraryPaths
.size()*(fSDKPaths
.size()+1));
3138 for (std::vector
<const char*>::iterator it
= libraryPaths
.begin(); it
!= libraryPaths
.end(); ++it
, ++libIndex
) {
3139 const char* libDir
= *it
;
3140 bool sdkOverride
= false;
3141 if ( libDir
[0] == '/' ) {
3142 char betterLibDir
[PATH_MAX
];
3143 if ( strstr(libDir
, "/..") != NULL
) {
3144 if ( realpath(libDir
, betterLibDir
) != NULL
)
3145 libDir
= strdup(betterLibDir
);
3147 const int libDirLen
= strlen(libDir
);
3148 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
3149 const char* sdkDir
= *sdkit
;
3150 const int sdkDirLen
= strlen(sdkDir
);
3151 char newPath
[libDirLen
+ sdkDirLen
+4];
3152 strcpy(newPath
, sdkDir
);
3153 if ( newPath
[sdkDirLen
-1] == '/' )
3154 newPath
[sdkDirLen
-1] = '\0';
3155 strcat(newPath
, libDir
);
3156 struct stat statBuffer
;
3157 if ( stat(newPath
, &statBuffer
) == 0 ) {
3158 fLibrarySearchPaths
.push_back(strdup(newPath
));
3163 if ( !sdkOverride
) {
3164 if ( (libIndex
>= standardLibraryPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
3165 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
3166 // if one SDK is specified and a standard library path is not in the SDK, don't use it
3169 fLibrarySearchPaths
.push_back(libDir
);
3174 // now merge sdk and framework paths to make real search paths
3175 fFrameworkSearchPaths
.reserve(frameworkPaths
.size()*(fSDKPaths
.size()+1));
3177 for (std::vector
<const char*>::iterator it
= frameworkPaths
.begin(); it
!= frameworkPaths
.end(); ++it
, ++frameIndex
) {
3178 const char* frameworkDir
= *it
;
3179 bool sdkOverride
= false;
3180 if ( frameworkDir
[0] == '/' ) {
3181 char betterFrameworkDir
[PATH_MAX
];
3182 if ( strstr(frameworkDir
, "/..") != NULL
) {
3183 if ( realpath(frameworkDir
, betterFrameworkDir
) != NULL
)
3184 frameworkDir
= strdup(betterFrameworkDir
);
3186 const int frameworkDirLen
= strlen(frameworkDir
);
3187 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
3188 const char* sdkDir
= *sdkit
;
3189 const int sdkDirLen
= strlen(sdkDir
);
3190 char newPath
[frameworkDirLen
+ sdkDirLen
+4];
3191 strcpy(newPath
, sdkDir
);
3192 if ( newPath
[sdkDirLen
-1] == '/' )
3193 newPath
[sdkDirLen
-1] = '\0';
3194 strcat(newPath
, frameworkDir
);
3195 struct stat statBuffer
;
3196 if ( stat(newPath
, &statBuffer
) == 0 ) {
3197 fFrameworkSearchPaths
.push_back(strdup(newPath
));
3202 if ( !sdkOverride
) {
3203 if ( (frameIndex
>= standardFrameworkPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
3204 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
3205 // if one SDK is specified and a standard library path is not in the SDK, don't use it
3208 fFrameworkSearchPaths
.push_back(frameworkDir
);
3214 fprintf(stderr
,"Library search paths:\n");
3215 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
3216 it
!= fLibrarySearchPaths
.end();
3218 fprintf(stderr
,"\t%s\n", *it
);
3219 fprintf(stderr
,"Framework search paths:\n");
3220 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
3221 it
!= fFrameworkSearchPaths
.end();
3223 fprintf(stderr
,"\t%s\n", *it
);
3227 // this is run before the command line is parsed
3228 void Options::parsePreCommandLineEnvironmentSettings()
3230 if ((getenv("LD_TRACE_ARCHIVES") != NULL
)
3231 || (getenv("RC_TRACE_ARCHIVES") != NULL
))
3232 fTraceArchives
= true;
3234 if ((getenv("LD_TRACE_DYLIBS") != NULL
)
3235 || (getenv("RC_TRACE_DYLIBS") != NULL
)) {
3236 fTraceDylibs
= true;
3237 fTraceIndirectDylibs
= true;
3240 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL
) {
3241 fTraceDylibSearching
= true;
3244 if (getenv("LD_PRINT_OPTIONS") != NULL
)
3245 fPrintOptions
= true;
3247 if (fTraceDylibs
|| fTraceArchives
)
3248 fTraceOutputFile
= getenv("LD_TRACE_FILE");
3250 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL
)
3251 fPrintOrderFileStatistics
= true;
3253 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL
)
3256 if (getenv("LD_NO_ENCRYPT") != NULL
)
3257 fEncryptable
= false;
3259 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL
)
3260 fAllowCpuSubtypeMismatches
= true;
3262 sWarningsSideFilePath
= getenv("LD_WARN_FILE");
3264 const char* customDyldPath
= getenv("LD_DYLD_PATH");
3265 if ( customDyldPath
!= NULL
)
3266 fDyldInstallPath
= customDyldPath
;
3268 const char* debugArchivePath
= getenv("LD_DEBUG_SNAPSHOT");
3269 if (debugArchivePath
!= NULL
) {
3270 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
3271 if (strlen(debugArchivePath
) > 0)
3272 fLinkSnapshot
.setSnapshotPath(debugArchivePath
);
3273 fSnapshotRequested
= true;
3276 const char* pipeFdString
= getenv("LD_PIPELINE_FIFO");
3277 if (pipeFdString
!= NULL
) {
3278 fPipelineFifo
= pipeFdString
;
3283 // this is run after the command line is parsed
3284 void Options::parsePostCommandLineEnvironmentSettings()
3286 // when building a dynamic main executable, default any use of @executable_path to output path
3287 if ( fExecutablePath
== NULL
&& (fOutputKind
== kDynamicExecutable
) ) {
3288 fExecutablePath
= fOutputFile
;
3291 // allow build system to set default seg_addr_table
3292 if ( fSegAddrTablePath
== NULL
)
3293 fSegAddrTablePath
= getenv("LD_SEG_ADDR_TABLE");
3295 // allow build system to turn on prebinding
3297 fPrebind
= ( getenv("LD_PREBIND") != NULL
);
3300 // allow build system to force on dead-code-stripping
3301 if ( !fDeadStrip
) {
3302 if ( getenv("LD_DEAD_STRIP") != NULL
) {
3303 switch (fOutputKind
) {
3304 case Options::kDynamicLibrary
:
3305 case Options::kDynamicExecutable
:
3306 case Options::kDynamicBundle
:
3309 case Options::kPreload
:
3310 case Options::kObjectFile
:
3311 case Options::kDyld
:
3312 case Options::kStaticExecutable
:
3313 case Options::kKextBundle
:
3319 // allow build system to force on -warn_commons
3320 if ( getenv("LD_WARN_COMMONS") != NULL
)
3321 fWarnCommons
= true;
3323 // allow B&I to set default -source_version
3324 if ( fSourceVersion
== 0 ) {
3325 const char* vers
= getenv("RC_ProjectSourceVersion");
3327 fSourceVersion
= parseVersionNumber64(vers
);
3332 void Options::reconfigureDefaults()
3334 // sync reader options
3335 switch ( fOutputKind
) {
3336 case Options::kObjectFile
:
3337 fForFinalLinkedImage
= false;
3339 case Options::kDyld
:
3341 fForFinalLinkedImage
= true;
3344 case Options::kDynamicLibrary
:
3345 case Options::kDynamicBundle
:
3346 case Options::kKextBundle
:
3347 fForFinalLinkedImage
= true;
3350 case Options::kDynamicExecutable
:
3351 case Options::kStaticExecutable
:
3352 case Options::kPreload
:
3353 fLinkingMainExecutable
= true;
3354 fForFinalLinkedImage
= true;
3359 // set default min OS version
3360 if ( (fMacVersionMin
== ld::macVersionUnset
)
3361 && (fIOSVersionMin
== ld::iOSVersionUnset
) ) {
3362 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
3363 const char* macVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
3364 const char* iPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
3365 const char* iOSVers
= getenv("IOS_DEPLOYMENT_TARGET");
3366 const char* iOSSimulatorVers
= getenv("IOS_SIMULATOR_DEPLOYMENT_TARGET");
3367 if ( macVers
!= NULL
)
3368 setMacOSXVersionMin(macVers
);
3369 else if ( iPhoneVers
!= NULL
)
3370 setIOSVersionMin(iPhoneVers
);
3371 else if ( iOSVers
!= NULL
)
3372 setIOSVersionMin(iOSVers
);
3373 else if ( iOSSimulatorVers
!= NULL
)
3374 setIOSVersionMin(iOSSimulatorVers
);
3376 // if still nothing, set default based on architecture
3377 switch ( fArchitecture
) {
3379 case CPU_TYPE_X86_64
:
3380 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
3381 #ifdef DEFAULT_MACOSX_MIN_VERSION
3382 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION
);
3383 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
3385 warning("-macosx_version_min not specified, assuming 10.6");
3386 fMacVersionMin
= ld::mac10_6
;
3391 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
3392 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
3393 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION
);
3394 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION
);
3396 warning("-ios_version_min not specified, assuming 6.0");
3397 setIOSVersionMin("6.0");
3402 // architecture will be infered later by examining .o files
3409 // adjust min based on architecture
3410 switch ( fArchitecture
) {
3412 if ( (fMacVersionMin
< ld::mac10_4
) && (fIOSVersionMin
== ld::iOSVersionUnset
) ) {
3413 //warning("-macosx_version_min should be 10.4 or later for i386");
3414 fMacVersionMin
= ld::mac10_4
;
3417 case CPU_TYPE_X86_64
:
3418 if ( (fMacVersionMin
< ld::mac10_4
) && (fIOSVersionMin
== ld::iOSVersionUnset
) ) {
3419 //warning("-macosx_version_min should be 10.4 or later for x86_64");
3420 fMacVersionMin
= ld::mac10_4
;
3423 case CPU_TYPE_ARM64
:
3424 if ( fIOSVersionMin
< ld::iOS_7_0
) {
3425 //warning("-mios_version_min should be 7.0 or later for arm64");
3426 fIOSVersionMin
= ld::iOS_7_0
;
3431 // default to adding functions start for dynamic code, static code must opt-in
3432 switch ( fOutputKind
) {
3433 case Options::kPreload
:
3434 case Options::kStaticExecutable
:
3435 case Options::kKextBundle
:
3436 if ( fDataInCodeInfoLoadCommandForcedOn
)
3437 fDataInCodeInfoLoadCommand
= true;
3438 if ( fFunctionStartsForcedOn
)
3439 fFunctionStartsLoadCommand
= true;
3441 case Options::kObjectFile
:
3442 if ( !fDataInCodeInfoLoadCommandForcedOff
)
3443 fDataInCodeInfoLoadCommand
= true;
3444 if ( fFunctionStartsForcedOn
)
3445 fFunctionStartsLoadCommand
= true;
3447 case Options::kDynamicExecutable
:
3448 case Options::kDyld
:
3449 case Options::kDynamicLibrary
:
3450 case Options::kDynamicBundle
:
3451 if ( !fDataInCodeInfoLoadCommandForcedOff
)
3452 fDataInCodeInfoLoadCommand
= true;
3453 if ( !fFunctionStartsForcedOff
)
3454 fFunctionStartsLoadCommand
= true;
3458 // adjust kext type based on architecture
3459 if ( fOutputKind
== kKextBundle
) {
3460 switch ( fArchitecture
) {
3461 case CPU_TYPE_X86_64
:
3462 // x86_64 uses new MH_KEXT_BUNDLE type
3463 fMakeCompressedDyldInfo
= false;
3464 fMakeCompressedDyldInfoForceOff
= true;
3465 fAllowTextRelocs
= true;
3466 fUndefinedTreatment
= kUndefinedDynamicLookup
;
3468 case CPU_TYPE_ARM64
:
3469 // arm64 uses new MH_KEXT_BUNDLE type
3470 fMakeCompressedDyldInfo
= false;
3471 fMakeCompressedDyldInfoForceOff
= true;
3472 fAllowTextRelocs
= false;
3473 fKextsUseStubs
= true;
3474 fUndefinedTreatment
= kUndefinedDynamicLookup
;
3477 if ( fIOSVersionMin
>= ld::iOS_5_0
) {
3478 // iOS 5.0 and later use new MH_KEXT_BUNDLE type
3479 fMakeCompressedDyldInfo
= false;
3480 fMakeCompressedDyldInfoForceOff
= true;
3481 // kexts are PIC in iOS 6.0 and later
3482 fAllowTextRelocs
= (fIOSVersionMin
< ld::iOS_6_0
);
3483 fKextsUseStubs
= !fAllowTextRelocs
;
3484 fUndefinedTreatment
= kUndefinedDynamicLookup
;
3487 // else use object file
3490 fOutputKind
= kObjectFile
;
3495 // disable implicit dylibs when targeting 10.3
3496 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
3497 if ( !minOS(ld::mac10_4
, ld::iOS_2_0
) )
3498 fImplicitlyLinkPublicDylibs
= false;
3501 // allow build system to force linker to ignore -prebind
3502 if ( getenv("LD_FORCE_NO_PREBIND") != NULL
)
3505 // allow build system to force linker to ignore -seg_addr_table
3506 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL
)
3507 fSegAddrTablePath
= NULL
;
3509 // check for base address specified externally
3510 if ( (fSegAddrTablePath
!= NULL
) && (fOutputKind
== Options::kDynamicLibrary
) ) {
3511 parseSegAddrTable(fSegAddrTablePath
, this->installPath());
3512 // HACK to support seg_addr_table entries that are physical paths instead of install paths
3513 if ( fBaseAddress
== 0 ) {
3514 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
3515 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.4.dylib");
3516 if ( fBaseAddress
== 0 )
3517 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.9.dylib");
3520 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
3521 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libz.1.2.3.dylib");
3523 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
3524 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libutil1.0.dylib");
3528 // split segs only allowed for dylibs
3530 // split seg only supported for i386, and arm.
3531 switch ( fArchitecture
) {
3533 if ( fOutputKind
!= Options::kDynamicLibrary
)
3535 // make sure read and write segments are proper distance apart
3536 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x10000000) )
3537 fBaseWritableAddress
= fBaseAddress
+ 0x10000000;
3540 if ( fOutputKind
!= Options::kDynamicLibrary
) {
3544 // make sure read and write segments are proper distance apart
3545 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x08000000) )
3546 fBaseWritableAddress
= fBaseAddress
+ 0x08000000;
3552 fBaseWritableAddress
= 0;
3556 // set too-large size
3557 switch ( fArchitecture
) {
3559 fMaxAddress
= 0xFFFFFFFF;
3561 case CPU_TYPE_X86_64
:
3564 switch ( fOutputKind
) {
3565 case Options::kDynamicExecutable
:
3566 case Options::kDynamicLibrary
:
3567 case Options::kDynamicBundle
:
3568 // user land code is limited to low 1GB
3569 fMaxAddress
= 0x2FFFFFFF;
3571 case Options::kStaticExecutable
:
3572 case Options::kObjectFile
:
3573 case Options::kDyld
:
3574 case Options::kPreload
:
3575 case Options::kKextBundle
:
3576 fMaxAddress
= 0xFFFFFFFF;
3579 // range check -seg1addr for ARM
3580 if ( fBaseAddress
> fMaxAddress
) {
3581 warning("ignoring -seg1addr 0x%08llX. Address out of range.", fBaseAddress
);
3587 // <rdar://problem/6138961> -r implies no prebinding for all architectures
3588 if ( fOutputKind
== Options::kObjectFile
)
3591 // disable prebinding depending on arch and min OS version
3593 switch ( fArchitecture
) {
3595 if ( fMacVersionMin
== ld::mac10_4
) {
3596 // in 10.4 only split seg dylibs are prebound
3597 if ( (fOutputKind
!= Options::kDynamicLibrary
) || ! fSplitSegs
)
3600 else if ( fMacVersionMin
>= ld::mac10_5
) {
3601 // in 10.5 nothing is prebound
3604 else if ( fIOSVersionMin
!= ld::iOSVersionUnset
) {
3605 // nothing in simulator is prebound
3609 // in 10.3 and earlier only dylibs and main executables could be prebound
3610 switch ( fOutputKind
) {
3611 case Options::kDynamicExecutable
:
3612 case Options::kDynamicLibrary
:
3613 // only main executables and dylibs can be prebound
3615 case Options::kStaticExecutable
:
3616 case Options::kDynamicBundle
:
3617 case Options::kObjectFile
:
3618 case Options::kDyld
:
3619 case Options::kPreload
:
3620 case Options::kKextBundle
:
3621 // disable prebinding for everything else
3627 case CPU_TYPE_X86_64
:
3631 switch ( fOutputKind
) {
3632 case Options::kDynamicExecutable
:
3633 case Options::kDynamicLibrary
:
3634 // only main executables and dylibs can be prebound
3636 case Options::kStaticExecutable
:
3637 case Options::kDynamicBundle
:
3638 case Options::kObjectFile
:
3639 case Options::kDyld
:
3640 case Options::kPreload
:
3641 case Options::kKextBundle
:
3642 // disable prebinding for everything else
3650 // only prebound images can be split-seg
3651 if ( fSplitSegs
&& !fPrebind
)
3654 // determine if info for shared region should be added
3655 if ( fOutputKind
== Options::kDynamicLibrary
) {
3656 if ( minOS(ld::mac10_5
, ld::iOS_3_1
) )
3658 if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
3659 || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
3660 fSharedRegionEligible
= true;
3662 else if ( fOutputKind
== Options::kDyld
) {
3663 // <rdar://problem/10111122> Enable dyld to be put into the dyld shared cache
3664 fSharedRegionEligible
= true;
3667 // figure out if module table is needed for compatibility with old ld/dyld
3668 if ( fOutputKind
== Options::kDynamicLibrary
) {
3669 switch ( fArchitecture
) {
3671 if ( fIOSVersionMin
!= ld::iOSVersionUnset
) // simulator never needs modules
3675 fNeedsModuleTable
= true; // redo_prebinding requires a module table
3680 // <rdar://problem/5366363> -r -x implies -S
3681 if ( (fOutputKind
== Options::kObjectFile
) && (fLocalSymbolHandling
== kLocalSymbolsNone
) )
3682 fDebugInfoStripping
= Options::kDebugInfoNone
;
3684 // <rdar://problem/15252891> -r implies -no_uuid
3685 if ( fOutputKind
== Options::kObjectFile
)
3686 fUUIDMode
= kUUIDNone
;
3688 // choose how to process unwind info
3689 switch ( fArchitecture
) {
3691 case CPU_TYPE_X86_64
:
3692 case CPU_TYPE_ARM64
:
3693 switch ( fOutputKind
) {
3694 case Options::kObjectFile
:
3695 case Options::kStaticExecutable
:
3696 case Options::kPreload
:
3697 case Options::kKextBundle
:
3698 fAddCompactUnwindEncoding
= false;
3700 case Options::kDyld
:
3701 case Options::kDynamicLibrary
:
3702 case Options::kDynamicBundle
:
3703 case Options::kDynamicExecutable
:
3704 //if ( fAddCompactUnwindEncoding && (fVersionMin >= ld::mac10_6) )
3705 // fRemoveDwarfUnwindIfCompactExists = true;
3710 fAddCompactUnwindEncoding
= false;
3711 fRemoveDwarfUnwindIfCompactExists
= false;
3714 // if -arch is missing, assume we don't want compact unwind info
3715 fAddCompactUnwindEncoding
= false;
3719 // only iOS main executables should be encrypted
3720 if ( fOutputKind
!= Options::kDynamicExecutable
)
3721 fEncryptable
= false;
3722 if ( (fArchitecture
!= CPU_TYPE_ARM
) && (fArchitecture
!= CPU_TYPE_ARM64
) )
3723 fEncryptable
= false;
3725 // don't move inits in dyld because dyld wants certain
3726 // entries point at stable locations at the start of __text
3727 if ( fOutputKind
== Options::kDyld
)
3728 fAutoOrderInitializers
= false;
3731 // disable __data ordering for some output kinds
3732 switch ( fOutputKind
) {
3733 case Options::kObjectFile
:
3734 case Options::kDyld
:
3735 case Options::kStaticExecutable
:
3736 case Options::kPreload
:
3737 case Options::kKextBundle
:
3740 case Options::kDynamicExecutable
:
3741 case Options::kDynamicLibrary
:
3742 case Options::kDynamicBundle
:
3746 // only use compressed LINKEDIT for final linked images
3747 switch ( fOutputKind
) {
3748 case Options::kDynamicExecutable
:
3749 case Options::kDynamicLibrary
:
3750 case Options::kDynamicBundle
:
3752 case Options::kPreload
:
3753 case Options::kStaticExecutable
:
3754 case Options::kObjectFile
:
3755 case Options::kDyld
:
3756 case Options::kKextBundle
:
3757 fMakeCompressedDyldInfoForceOff
= true;
3760 if ( fMakeCompressedDyldInfoForceOff
)
3761 fMakeCompressedDyldInfo
= false;
3764 // only use compressed LINKEDIT for:
3765 // Mac OS X 10.6 or later
3767 if ( fMakeCompressedDyldInfo
) {
3768 if ( !minOS(ld::mac10_6
, ld::iOS_3_1
) )
3769 fMakeCompressedDyldInfo
= false;
3772 // only ARM and x86_64 enforces that cpu-sub-types must match
3773 switch ( fArchitecture
) {
3775 case CPU_TYPE_X86_64
:
3778 case CPU_TYPE_ARM64
:
3779 fAllowCpuSubtypeMismatches
= true;
3784 // only final linked images can not optimize zero fill sections
3785 if ( fOutputKind
== Options::kObjectFile
)
3786 fOptimizeZeroFill
= true;
3788 // all undefines in -r mode
3789 // if ( fOutputKind == Options::kObjectFile )
3790 // fUndefinedTreatment = kUndefinedSuppress;
3792 // only dynamic final linked images should warn about use of commmons
3793 if ( fWarnCommons
) {
3794 switch ( fOutputKind
) {
3795 case Options::kDynamicExecutable
:
3796 case Options::kDynamicLibrary
:
3797 case Options::kDynamicBundle
:
3799 case Options::kPreload
:
3800 case Options::kStaticExecutable
:
3801 case Options::kObjectFile
:
3802 case Options::kDyld
:
3803 case Options::kKextBundle
:
3804 fWarnCommons
= false;
3809 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
3810 if ( minOS(ld::mac10_5
, ld::iOS_2_0
) )
3811 fUseSimplifiedDylibReExports
= true;
3813 // Mac OS X 10.7 and iOS 4.2 support LC_LOAD_UPWARD_DYLIB
3814 if ( minOS(ld::mac10_7
, ld::iOS_4_2
) && (fOutputKind
== kDynamicLibrary
) )
3815 fCanUseUpwardDylib
= true;
3817 // MacOSX 10.7 defaults to PIE
3818 if ( ((fArchitecture
== CPU_TYPE_X86_64
) || (fArchitecture
== CPU_TYPE_I386
))
3819 && (fOutputKind
== kDynamicExecutable
)
3820 && (fMacVersionMin
>= ld::mac10_7
) ) {
3821 fPositionIndependentExecutable
= true;
3824 // armv7 for iOS4.3 defaults to PIE
3825 if ( (fArchitecture
== CPU_TYPE_ARM
)
3826 && fArchSupportsThumb2
3827 && (fOutputKind
== kDynamicExecutable
)
3828 && (fIOSVersionMin
>= ld::iOS_4_3
) ) {
3829 fPositionIndependentExecutable
= true;
3832 // -no_pie anywhere on command line disable PIE
3833 if ( fDisablePositionIndependentExecutable
)
3834 fPositionIndependentExecutable
= false;
3836 // arm64 is always PIE
3837 if ( (fArchitecture
== CPU_TYPE_ARM64
) && (fOutputKind
== kDynamicExecutable
) ) {
3838 fPositionIndependentExecutable
= true;
3841 // set fOutputSlidable
3842 switch ( fOutputKind
) {
3843 case Options::kObjectFile
:
3844 fOutputSlidable
= false;
3846 case Options::kStaticExecutable
:
3847 case Options::kDynamicExecutable
:
3848 fOutputSlidable
= fPositionIndependentExecutable
;
3850 case Options::kPreload
:
3851 fOutputSlidable
= fPIEOnCommandLine
;
3853 case Options::kDyld
:
3854 case Options::kDynamicLibrary
:
3855 case Options::kDynamicBundle
:
3856 case Options::kKextBundle
:
3857 fOutputSlidable
= true;
3861 // let linker know if thread local variables are supported
3862 if ( fMacVersionMin
>= ld::mac10_7
) {
3865 else if ( (fArchitecture
== CPU_TYPE_ARM64
) && (fIOSVersionMin
>= 0x00080000) ) {
3869 // default to adding version load command for dynamic code, static code must opt-in
3870 switch ( fOutputKind
) {
3871 case Options::kObjectFile
:
3872 fVersionLoadCommand
= false;
3874 case Options::kStaticExecutable
:
3875 case Options::kPreload
:
3876 case Options::kKextBundle
:
3877 if ( fVersionLoadCommandForcedOn
)
3878 fVersionLoadCommand
= true;
3880 case Options::kDynamicExecutable
:
3881 case Options::kDyld
:
3882 case Options::kDynamicLibrary
:
3883 case Options::kDynamicBundle
:
3884 if ( !fVersionLoadCommandForcedOff
)
3885 fVersionLoadCommand
= true;
3889 // support re-export of individual symbols in MacOSX 10.7 and iOS 4.2
3890 if ( (fOutputKind
== kDynamicLibrary
) && minOS(ld::mac10_7
, ld::iOS_4_2
) )
3891 fCanReExportSymbols
= true;
3893 // ObjC optimization is only in dynamic final linked images
3894 switch ( fOutputKind
) {
3895 case Options::kObjectFile
:
3896 case Options::kStaticExecutable
:
3897 case Options::kPreload
:
3898 case Options::kKextBundle
:
3899 case Options::kDyld
:
3900 fObjcCategoryMerging
= false;
3902 case Options::kDynamicExecutable
:
3903 case Options::kDynamicLibrary
:
3904 case Options::kDynamicBundle
:
3908 // i386 main executables linked on Mac OS X 10.7 default to NX heap
3909 // regardless of target unless overriden with -allow_heap_execute anywhere
3910 // on the command line
3911 if ( (fArchitecture
== CPU_TYPE_I386
) && (fOutputKind
== kDynamicExecutable
) && !fDisableNonExecutableHeap
)
3912 fNonExecutableHeap
= true;
3914 // Use LC_MAIN instead of LC_UNIXTHREAD for newer OSs
3915 switch ( fOutputKind
) {
3916 case Options::kDynamicExecutable
:
3917 if ( fEntryPointLoadCommandForceOn
) {
3918 fEntryPointLoadCommand
= true;
3919 fEntryName
= "_main";
3921 else if ( fEntryPointLoadCommandForceOff
) {
3922 fNeedsThreadLoadCommand
= true;
3925 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) ) {
3926 fEntryPointLoadCommand
= true;
3927 fEntryName
= "_main";
3930 fNeedsThreadLoadCommand
= true;
3933 case Options::kObjectFile
:
3934 case Options::kKextBundle
:
3935 case Options::kDynamicLibrary
:
3936 case Options::kDynamicBundle
:
3939 case Options::kStaticExecutable
:
3940 case Options::kPreload
:
3941 case Options::kDyld
:
3942 fNeedsThreadLoadCommand
= true;
3946 // add LC_SOURCE_VERSION
3947 switch ( fOutputKind
) {
3948 case Options::kDynamicExecutable
:
3949 case Options::kKextBundle
:
3950 case Options::kDynamicLibrary
:
3951 case Options::kDynamicBundle
:
3952 case Options::kDyld
:
3953 case Options::kStaticExecutable
:
3954 if ( fSourceVersionLoadCommandForceOn
) {
3955 fSourceVersionLoadCommand
= true;
3957 else if ( fSourceVersionLoadCommandForceOff
) {
3958 fSourceVersionLoadCommand
= false;
3961 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) ) {
3962 fSourceVersionLoadCommand
= true;
3965 fSourceVersionLoadCommand
= false;
3968 case Options::kObjectFile
:
3969 case Options::kPreload
:
3970 fSourceVersionLoadCommand
= false;
3975 // add LC_DYLIB_CODE_SIGN_DRS
3976 switch ( fOutputKind
) {
3977 case Options::kDynamicExecutable
:
3978 case Options::kDynamicLibrary
:
3979 case Options::kDynamicBundle
:
3980 if ( fDependentDRInfoForcedOn
) {
3981 fDependentDRInfo
= true;
3983 else if ( fDependentDRInfoForcedOff
) {
3984 fDependentDRInfo
= false;
3987 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) )
3988 fDependentDRInfo
= true;
3990 fDependentDRInfo
= false;
3993 case Options::kKextBundle
:
3994 case Options::kDyld
:
3995 case Options::kStaticExecutable
:
3996 case Options::kObjectFile
:
3997 case Options::kPreload
:
3998 fDependentDRInfo
= false;
4002 // if -sdk_version not on command line, infer from -syslibroot
4003 if ( (fSDKVersion
== 0) && (fSDKPaths
.size() > 0) ) {
4004 const char* sdkPath
= fSDKPaths
.front();
4005 const char* end
= &sdkPath
[strlen(sdkPath
)-1];
4006 while ( !isdigit(*end
) && (end
> sdkPath
) )
4008 const char* start
= end
-1;
4009 while ( (isdigit(*start
) || (*start
== '.')) && (start
> sdkPath
))
4011 char sdkVersionStr
[32];
4012 int len
= end
-start
+1;
4014 strlcpy(sdkVersionStr
, start
+1, len
);
4015 fSDKVersion
= parseVersionNumber32(sdkVersionStr
);
4019 // if -sdk_version and -syslibroot not used, but targeting MacOSX, use current OS version
4020 if ( (fSDKVersion
== 0) && (fMacVersionMin
!= ld::macVersionUnset
) ) {
4021 // special case if RC_ProjectName and MACOSX_DEPLOYMENT_TARGET are both set that sdkversion=minos
4022 if ( getenv("RC_ProjectName") && getenv("MACOSX_DEPLOYMENT_TARGET") ) {
4023 fSDKVersion
= fMacVersionMin
;
4026 int mib
[2] = { CTL_KERN
, KERN_OSRELEASE
};
4027 char kernVersStr
[100];
4028 size_t strlen
= sizeof(kernVersStr
);
4029 if ( sysctl(mib
, 2, kernVersStr
, &strlen
, NULL
, 0) != -1 ) {
4030 uint32_t kernVers
= parseVersionNumber32(kernVersStr
);
4031 int minor
= (kernVers
>> 16) - 4; // kernel major version is 4 ahead of x in 10.x
4032 fSDKVersion
= 0x000A0000 + (minor
<< 8);
4037 // allow trie based absolute symbols if targeting new enough OS
4038 if ( fMakeCompressedDyldInfo
) {
4039 if ( minOS(ld::mac10_9
, ld::iOS_7_0
) ) {
4040 // <rdar://problem/13179029> Allow absolute symbols in export trie for device but not simulator
4041 if ( !fTargetIOSSimulator
)
4042 fAbsoluteSymbols
= true;
4046 // <rdar://problem/12959510> iOS main executables now default to 16KB page size
4047 if ( (fIOSVersionMin
!= ld::iOSVersionUnset
) && (fOutputKind
== Options::kDynamicExecutable
) ) {
4048 // <rdar://problem/13070042> Only third party apps should have 16KB page segments by default
4049 if ( fEncryptable
) {
4050 if ( fSegmentAlignment
== 4096 )
4051 fSegmentAlignment
= 4096*4;
4055 // <rdar://problem/12258065> ARM64 needs 16KB page size for user land code
4056 if ( fArchitecture
== CPU_TYPE_ARM64
) {
4057 if ( fSegmentAlignment
== 4096 ) {
4058 switch ( fOutputKind
) {
4059 case Options::kDynamicExecutable
:
4060 case Options::kDynamicLibrary
:
4061 case Options::kDynamicBundle
:
4062 case Options::kDyld
:
4063 fSegmentAlignment
= 4096*4;
4065 case Options::kStaticExecutable
:
4066 case Options::kKextBundle
:
4067 case Options::kObjectFile
:
4068 case Options::kPreload
:
4074 // <rdar://problem/13624134> linker should not convert dwarf unwind if .o file has compact unwind section
4075 switch ( fOutputKind
) {
4076 case Options::kDynamicExecutable
:
4077 case Options::kDynamicLibrary
:
4078 case Options::kDynamicBundle
:
4079 case Options::kDyld
:
4080 if ( fKeepDwarfUnwindForcedOn
) {
4081 fKeepDwarfUnwind
= true;
4083 else if ( fKeepDwarfUnwindForcedOff
) {
4084 fKeepDwarfUnwind
= false;
4087 if ( minOS(ld::mac10_9
, ld::iOS_7_0
) )
4088 fKeepDwarfUnwind
= false;
4090 fKeepDwarfUnwind
= true;
4093 case Options::kKextBundle
:
4094 case Options::kStaticExecutable
:
4095 case Options::kObjectFile
:
4096 case Options::kPreload
:
4097 fKeepDwarfUnwind
= true;
4103 void Options::checkIllegalOptionCombinations()
4105 // check -undefined setting
4106 switch ( fUndefinedTreatment
) {
4107 case kUndefinedError
:
4108 case kUndefinedDynamicLookup
:
4111 case kUndefinedWarning
:
4112 case kUndefinedSuppress
:
4113 // requires flat namespace
4114 if ( fNameSpace
== kTwoLevelNameSpace
)
4115 throw "can't use -undefined warning or suppress with -twolevel_namespace";
4119 // unify -sub_umbrella with dylibs
4120 for (std::vector
<const char*>::iterator it
= fSubUmbellas
.begin(); it
!= fSubUmbellas
.end(); it
++) {
4121 const char* subUmbrella
= *it
;
4123 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
4124 Options::FileInfo
& info
= *fit
;
4125 const char* lastSlash
= strrchr(info
.path
, '/');
4126 if ( lastSlash
== NULL
)
4127 lastSlash
= info
.path
- 1;
4128 if ( strcmp(&lastSlash
[1], subUmbrella
) == 0 ) {
4129 info
.options
.fReExport
= true;
4131 fLinkSnapshot
.recordSubUmbrella(info
.path
);
4136 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella
);
4139 // unify -sub_library with dylibs
4140 for (std::vector
<const char*>::iterator it
= fSubLibraries
.begin(); it
!= fSubLibraries
.end(); it
++) {
4141 const char* subLibrary
= *it
;
4143 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
4144 Options::FileInfo
& info
= *fit
;
4145 const char* lastSlash
= strrchr(info
.path
, '/');
4146 if ( lastSlash
== NULL
)
4147 lastSlash
= info
.path
- 1;
4148 const char* dot
= strchr(&lastSlash
[1], '.');
4150 dot
= &lastSlash
[strlen(lastSlash
)];
4151 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
4152 info
.options
.fReExport
= true;
4154 fLinkSnapshot
.recordSubLibrary(info
.path
);
4159 warning("-sub_library %s does not match a supplied dylib", subLibrary
);
4162 // sync reader options
4163 if ( fNameSpace
!= kTwoLevelNameSpace
)
4164 fFlatNamespace
= true;
4166 // check -stack_addr
4167 if ( fStackAddr
!= 0 ) {
4168 switch (fArchitecture
) {
4171 if ( fStackAddr
> 0xFFFFFFFF )
4172 throw "-stack_addr must be < 4G for 32-bit processes";
4174 case CPU_TYPE_X86_64
:
4175 case CPU_TYPE_ARM64
:
4178 if ( (fStackAddr
& -4096) != fStackAddr
)
4179 throw "-stack_addr must be multiples of 4K";
4180 if ( fStackSize
== 0 )
4181 throw "-stack_addr must be used with -stack_size";
4184 // check -stack_size
4185 if ( fStackSize
!= 0 ) {
4186 switch (fArchitecture
) {
4188 if ( fStackSize
> 0xFFFFFFFF )
4189 throw "-stack_size must be < 4G for 32-bit processes";
4190 if ( fStackAddr
== 0 ) {
4191 fStackAddr
= 0xC0000000;
4193 if ( (fStackAddr
> 0xB0000000) && ((fStackAddr
-fStackSize
) < 0xB0000000) )
4194 warning("custom stack placement overlaps and will disable shared region");
4197 if ( fStackSize
> 0x2F000000 )
4198 throw "-stack_size must be < 752MB";
4199 if ( fStackAddr
== 0 )
4200 fStackAddr
= 0x2F000000;
4201 if ( fStackAddr
> 0x30000000)
4202 throw "-stack_addr must be < 0x30000000 for arm";
4204 case CPU_TYPE_X86_64
:
4205 if ( fStackAddr
== 0 ) {
4206 fStackAddr
= 0x00007FFF5C000000LL
;
4209 case CPU_TYPE_ARM64
:
4210 if ( fStackSize
> 0x20000000 )
4211 throw "-stack_size must be < 512MB";
4212 if ( fStackAddr
== 0 ) {
4213 fStackAddr
= 0x120000000;
4217 if ( (fStackSize
& -4096) != fStackSize
)
4218 throw "-stack_size must be multiples of 4K";
4219 switch ( fOutputKind
) {
4220 case Options::kDynamicExecutable
:
4221 case Options::kStaticExecutable
:
4222 // custom stack size only legal when building main executable
4224 case Options::kDynamicLibrary
:
4225 case Options::kDynamicBundle
:
4226 case Options::kObjectFile
:
4227 case Options::kDyld
:
4228 case Options::kPreload
:
4229 case Options::kKextBundle
:
4230 throw "-stack_size option can only be used when linking a main executable";
4232 if ( fStackSize
> fStackAddr
)
4233 throwf("-stack_size (0x%08llX) must be smaller than -stack_addr (0x%08llX)", fStackSize
, fStackAddr
);
4236 // check that -allow_stack_execute is only used with main executables
4237 if ( fExecutableStack
) {
4238 switch ( fOutputKind
) {
4239 case Options::kDynamicExecutable
:
4240 case Options::kStaticExecutable
:
4241 // -allow_stack_execute size only legal when building main executable
4243 case Options::kDynamicLibrary
:
4244 case Options::kDynamicBundle
:
4245 case Options::kObjectFile
:
4246 case Options::kDyld
:
4247 case Options::kPreload
:
4248 case Options::kKextBundle
:
4249 throw "-allow_stack_execute option can only be used when linking a main executable";
4253 // check that -allow_heap_execute is only used with i386 main executables
4254 if ( fDisableNonExecutableHeap
) {
4255 if ( fArchitecture
!= CPU_TYPE_I386
)
4256 throw "-allow_heap_execute option can only be used when linking for i386";
4257 switch ( fOutputKind
) {
4258 case Options::kDynamicExecutable
:
4259 // -allow_heap_execute only legal when building main executable
4261 case Options::kStaticExecutable
:
4262 case Options::kDynamicLibrary
:
4263 case Options::kDynamicBundle
:
4264 case Options::kObjectFile
:
4265 case Options::kDyld
:
4266 case Options::kPreload
:
4267 case Options::kKextBundle
:
4268 throw "-allow_heap_execute option can only be used when linking a main executable";
4272 // check -client_name is only used when making a bundle or main executable
4273 if ( fClientName
!= NULL
) {
4274 switch ( fOutputKind
) {
4275 case Options::kDynamicExecutable
:
4276 case Options::kDynamicBundle
:
4278 case Options::kStaticExecutable
:
4279 case Options::kDynamicLibrary
:
4280 case Options::kObjectFile
:
4281 case Options::kDyld
:
4282 case Options::kPreload
:
4283 case Options::kKextBundle
:
4284 throw "-client_name can only be used with -bundle";
4288 // check -init is only used when building a dylib
4289 if ( (fInitFunctionName
!= NULL
) && (fOutputKind
!= Options::kDynamicLibrary
) )
4290 throw "-init can only be used with -dynamiclib";
4292 // check -bundle_loader only used with -bundle
4293 if ( (fBundleLoader
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
4294 throw "-bundle_loader can only be used with -bundle";
4296 // check -dtrace not used with -r
4297 if ( (fDtraceScriptName
!= NULL
) && (fOutputKind
== Options::kObjectFile
) )
4298 throw "-dtrace can only be used when creating final linked images";
4300 // check -d can only be used with -r
4301 if ( fMakeTentativeDefinitionsReal
&& (fOutputKind
!= Options::kObjectFile
) )
4302 throw "-d can only be used with -r";
4304 // check that -root_safe is not used with -r
4305 if ( fRootSafe
&& (fOutputKind
== Options::kObjectFile
) )
4306 throw "-root_safe cannot be used with -r";
4308 // check that -setuid_safe is not used with -r
4309 if ( fSetuidSafe
&& (fOutputKind
== Options::kObjectFile
) )
4310 throw "-setuid_safe cannot be used with -r";
4312 // <rdar://problem/12781832> compiler driver no longer uses -objc_abi_version, it uses -ios_simulator_version_min instead
4313 if ( !fObjCABIVersion1Override
&& !fObjCABIVersion2Override
&& fTargetIOSSimulator
)
4314 fObjCABIVersion2Override
= true;
4316 // rdar://problem/4718189 map ObjC class names to new runtime names
4317 bool alterObjC1ClassNamesToObjC2
= false;
4318 switch (fArchitecture
) {
4320 // i386 only uses new symbols when using objc2 ABI
4321 if ( fObjCABIVersion2Override
)
4322 alterObjC1ClassNamesToObjC2
= true;
4324 case CPU_TYPE_X86_64
:
4326 case CPU_TYPE_ARM64
:
4327 alterObjC1ClassNamesToObjC2
= true;
4331 // make sure all required exported symbols exist
4332 std::vector
<const char*> impliedExports
;
4333 for (NameSet::iterator it
=fExportSymbols
.regularBegin(); it
!= fExportSymbols
.regularEnd(); ++it
) {
4334 const char* name
= *it
;
4335 const int len
= strlen(name
);
4336 if ( (strcmp(&name
[len
-3], ".eh") == 0) || (strncmp(name
, ".objc_category_name_", 20) == 0) ) {
4337 // never export .eh symbols
4338 warning("ignoring %s in export list", name
);
4340 else if ( (fArchitecture
== CPU_TYPE_I386
) && !fObjCABIVersion2Override
&& (strncmp(name
, "_OBJC_CLASS_$", 13) == 0) ) {
4341 warning("ignoring Objc2 Class symbol %s in i386 export list", name
);
4342 fRemovedExports
.insert(name
);
4344 else if ( alterObjC1ClassNamesToObjC2
&& (strncmp(name
, ".objc_class_name_", 17) == 0) ) {
4345 // linking ObjC2 ABI, but have ObjC1 ABI name in export list. Change it to intended name
4346 fRemovedExports
.insert(name
);
4348 asprintf(&temp
, "_OBJC_CLASS_$_%s", &name
[17]);
4349 impliedExports
.push_back(temp
);
4350 asprintf(&temp
, "_OBJC_METACLASS_$_%s", &name
[17]);
4351 impliedExports
.push_back(temp
);
4354 fInitialUndefines
.push_back(name
);
4357 fExportSymbols
.remove(fRemovedExports
);
4358 for (std::vector
<const char*>::iterator it
=impliedExports
.begin(); it
!= impliedExports
.end(); ++it
) {
4359 const char* name
= *it
;
4360 fExportSymbols
.insert(name
);
4361 fInitialUndefines
.push_back(name
);
4364 // make sure all required re-exported symbols exist
4365 for (NameSet::iterator it
=fReExportSymbols
.regularBegin(); it
!= fReExportSymbols
.regularEnd(); ++it
) {
4366 fInitialUndefines
.push_back(*it
);
4369 // make sure that -init symbol exists
4370 if ( fInitFunctionName
!= NULL
)
4371 fInitialUndefines
.push_back(fInitFunctionName
);
4373 // make sure that entry symbol exists
4374 switch ( fOutputKind
) {
4375 case Options::kDynamicExecutable
:
4376 case Options::kStaticExecutable
:
4377 case Options::kDyld
:
4378 case Options::kPreload
:
4379 fInitialUndefines
.push_back(fEntryName
);
4381 case Options::kDynamicLibrary
:
4382 case Options::kDynamicBundle
:
4383 case Options::kObjectFile
:
4384 case Options::kKextBundle
:
4388 // make sure every alias base exists
4389 for (std::vector
<AliasPair
>::iterator it
=fAliases
.begin(); it
!= fAliases
.end(); ++it
) {
4390 fInitialUndefines
.push_back(it
->realName
);
4393 // check custom segments
4394 if ( fCustomSegmentAddresses
.size() != 0 ) {
4395 // verify no segment is in zero page
4396 if ( fZeroPageSize
!= ULLONG_MAX
) {
4397 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
4398 if ( it
->address
< fZeroPageSize
)
4399 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it
->name
, it
->address
);
4402 // verify no duplicates
4403 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
4404 for (std::vector
<SegmentStart
>::iterator it2
= fCustomSegmentAddresses
.begin(); it2
!= fCustomSegmentAddresses
.end(); ++it2
) {
4405 if ( (it
->address
== it2
->address
) && (it
!= it2
) )
4406 throwf("duplicate -segaddr addresses for %s and %s", it
->name
, it2
->name
);
4408 // a custom segment address of zero will disable the use of a zero page
4409 if ( it
->address
== 0 )
4414 if ( fZeroPageSize
== ULLONG_MAX
) {
4415 // zero page size not specified on command line, set default
4416 switch (fArchitecture
) {
4419 // first 4KB for 32-bit architectures
4420 fZeroPageSize
= 0x1000;
4422 case CPU_TYPE_ARM64
:
4423 case CPU_TYPE_X86_64
:
4424 // first 4GB for x86_64 on all OS's
4425 fZeroPageSize
= 0x100000000ULL
;
4428 // if -arch not used, default to 4K zero-page
4429 fZeroPageSize
= 0x1000;
4433 switch ( fOutputKind
) {
4434 case Options::kDynamicExecutable
:
4435 case Options::kStaticExecutable
:
4436 // -pagezero_size size only legal when building main executable
4438 case Options::kDynamicLibrary
:
4439 case Options::kDynamicBundle
:
4440 case Options::kObjectFile
:
4441 case Options::kDyld
:
4442 case Options::kPreload
:
4443 case Options::kKextBundle
:
4444 if ( fZeroPageSize
!= 0 )
4445 throw "-pagezero_size option can only be used when linking a main executable";
4449 // if main executable with custom base address, model zero page as custom segment
4450 if ( (fOutputKind
== Options::kDynamicExecutable
) && (fBaseAddress
!= 0) && (fZeroPageSize
!= 0) ) {
4452 seg
.name
= "__PAGEZERO";
4454 fCustomSegmentAddresses
.push_back(seg
);
4457 // -dead_strip and -r are incompatible
4458 if ( fDeadStrip
&& (fOutputKind
== Options::kObjectFile
) )
4459 throw "-r and -dead_strip cannot be used together";
4461 // can't use -rpath unless targeting 10.5 or later
4462 if ( fRPaths
.size() > 0 ) {
4463 if ( !minOS(ld::mac10_5
, ld::iOS_2_0
) )
4464 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
4465 switch ( fOutputKind
) {
4466 case Options::kDynamicExecutable
:
4467 case Options::kDynamicLibrary
:
4468 case Options::kDynamicBundle
:
4470 case Options::kStaticExecutable
:
4471 case Options::kObjectFile
:
4472 case Options::kDyld
:
4473 case Options::kPreload
:
4474 case Options::kKextBundle
:
4475 throw "-rpath can only be used when creating a dynamic final linked image";
4479 if ( fPositionIndependentExecutable
) {
4480 switch ( fOutputKind
) {
4481 case Options::kDynamicExecutable
:
4482 // check -pie is only used when building a dynamic main executable for 10.5
4483 if ( !minOS(ld::mac10_5
, ld::iOS_4_2
) ) {
4484 if ( fIOSVersionMin
== ld::iOSVersionUnset
)
4485 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
4487 throw "-pie can only be used when targeting iOS 4.2 or later";
4490 case Options::kStaticExecutable
:
4491 case Options::kPreload
:
4492 // -pie is ok with -static or -preload
4494 case Options::kDynamicLibrary
:
4495 case Options::kDynamicBundle
:
4496 warning("-pie being ignored. It is only used when linking a main executable");
4497 fPositionIndependentExecutable
= false;
4499 case Options::kObjectFile
:
4500 case Options::kDyld
:
4501 case Options::kKextBundle
:
4502 throw "-pie can only be used when linking a main executable";
4506 // check -read_only_relocs is not used with x86_64
4507 if ( fAllowTextRelocs
) {
4508 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
!= kKextBundle
) ) {
4509 warning("-read_only_relocs cannot be used with x86_64");
4510 fAllowTextRelocs
= false;
4514 // check -mark_auto_dead_strip is only used with dylibs
4515 if ( fMarkDeadStrippableDylib
) {
4516 if ( fOutputKind
!= Options::kDynamicLibrary
) {
4517 warning("-mark_auto_dead_strip can only be used when creating a dylib");
4518 fMarkDeadStrippableDylib
= false;
4522 // -force_cpusubtype_ALL is not supported for ARM
4523 if ( fForceSubtypeAll
) {
4524 if ( fArchitecture
== CPU_TYPE_ARM
) {
4525 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
4529 // -reexported_symbols_list can only be used with -dynamiclib
4530 if ( !fReExportSymbols
.empty() ) {
4531 if ( fOutputKind
!= Options::kDynamicLibrary
)
4532 throw "-reexported_symbols_list can only used used when created dynamic libraries";
4533 if ( !minOS(ld::mac10_7
, ld::iOS_4_2
) )
4534 throw "targeted OS version does not support -reexported_symbols_list";
4537 // -dyld_env can only be used with main executables
4538 if ( (fOutputKind
!= Options::kDynamicExecutable
) && (fDyldEnvironExtras
.size() != 0) )
4539 throw "-dyld_env can only used used when created main executables";
4541 // -rename_sections can only be used in -r mode
4542 if ( (fSectionRenames
.size() != 0) && (fOutputKind
!= Options::kObjectFile
) )
4543 throw "-rename_sections can only used used in -r mode";
4547 void Options::checkForClassic(int argc
, const char* argv
[])
4550 bool archFound
= false;
4551 bool staticFound
= false;
4552 bool dtraceFound
= false;
4553 bool kextFound
= false;
4554 bool rFound
= false;
4555 bool creatingMachKernel
= false;
4556 bool newLinker
= false;
4558 // build command line buffer in case ld crashes
4559 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
4560 CRSetCrashLogMessage(crashreporterBuffer
);
4562 const char* srcRoot
= getenv("SRCROOT");
4563 if ( srcRoot
!= NULL
) {
4564 strlcpy(crashreporterBuffer
, "SRCROOT=", crashreporterBufferSize
);
4565 strlcat(crashreporterBuffer
, srcRoot
, crashreporterBufferSize
);
4566 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
4569 strlcat(crashreporterBuffer
, LD_VERS
, crashreporterBufferSize
);
4570 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
4572 strlcat(crashreporterBuffer
, "ld ", crashreporterBufferSize
);
4573 for(int i
=1; i
< argc
; ++i
) {
4574 strlcat(crashreporterBuffer
, argv
[i
], crashreporterBufferSize
);
4575 strlcat(crashreporterBuffer
, " ", crashreporterBufferSize
);
4578 for(int i
=0; i
< argc
; ++i
) {
4579 const char* arg
= argv
[i
];
4580 if ( arg
[0] == '-' ) {
4581 if ( strcmp(arg
, "-arch") == 0 ) {
4582 parseArch(argv
[++i
]);
4585 else if ( strcmp(arg
, "-static") == 0 ) {
4588 else if ( strcmp(arg
, "-kext") == 0 ) {
4591 else if ( strcmp(arg
, "-dtrace") == 0 ) {
4594 else if ( strcmp(arg
, "-r") == 0 ) {
4597 else if ( strcmp(arg
, "-new_linker") == 0 ) {
4600 else if ( strcmp(arg
, "-classic_linker") == 0 ) {
4601 // ld_classic does not understand this option, so remove it
4602 for(int j
=i
; j
< argc
; ++j
)
4603 argv
[j
] = argv
[j
+1];
4604 warning("using ld_classic");
4605 this->gotoClassicLinker(argc
-1, argv
);
4607 else if ( strcmp(arg
, "-o") == 0 ) {
4608 const char* outfile
= argv
[++i
];
4609 if ( (outfile
!= NULL
) && (strstr(outfile
, "/mach_kernel") != NULL
) )
4610 creatingMachKernel
= true;
4616 void Options::gotoClassicLinker(int argc
, const char* argv
[])
4618 argv
[0] = "ld_classic";
4619 // ld_classic does not support -iphoneos_version_min, so change
4620 for(int j
=0; j
< argc
; ++j
) {
4621 if ( (strcmp(argv
[j
], "-iphoneos_version_min") == 0) || (strcmp(argv
[j
], "-ios_version_min") == 0) ) {
4622 argv
[j
] = "-macosx_version_min";
4628 // ld classic does not understand -kext (change to -static -r)
4629 for(int j
=0; j
< argc
; ++j
) {
4630 if ( strcmp(argv
[j
], "-kext") == 0)
4632 else if ( strcmp(argv
[j
], "-dynamic") == 0)
4633 argv
[j
] = "-static";
4635 // ld classic does not understand -demangle
4636 for(int j
=0; j
< argc
; ++j
) {
4637 if ( strcmp(argv
[j
], "-demangle") == 0)
4638 argv
[j
] = "-noprebind";
4640 // in -v mode, print command line passed to ld_classic
4641 for(int i
=0; i
< argc
; ++i
) {
4642 if ( strcmp(argv
[i
], "-v") == 0 ) {
4643 for(int j
=0; j
< argc
; ++j
)
4644 printf("%s ", argv
[j
]);
4649 char rawPath
[PATH_MAX
];
4650 char path
[PATH_MAX
];
4651 uint32_t bufSize
= PATH_MAX
;
4652 if ( _NSGetExecutablePath(rawPath
, &bufSize
) != -1 ) {
4653 if ( realpath(rawPath
, path
) != NULL
) {
4654 char* lastSlash
= strrchr(path
, '/');
4655 if ( lastSlash
!= NULL
) {
4656 strcpy(lastSlash
+1, "ld_classic");
4658 execvp(path
, (char**)argv
);
4662 // in case of error in above, try searching for ld_classic via PATH
4663 execvp(argv
[0], (char**)argv
);
4664 fprintf(stderr
, "can't exec ld_classic\n");
4669 // Note, returned string buffer is own by this function.
4670 // It should not be freed
4671 // It will be reused, so clients need to strdup() if they want
4672 // to use it long term.
4673 const char* Options::demangleSymbol(const char* sym
) const
4675 // only try to demangle symbols if -demangle on command line
4679 // only try to demangle symbols that look like C++ symbols
4680 if ( strncmp(sym
, "__Z", 3) != 0 )
4683 static size_t size
= 1024;
4684 static char* buff
= (char*)malloc(size
);
4687 char* result
= abi::__cxa_demangle(&sym
[1], buff
, &size
, &status
);
4688 if ( result
!= NULL
) {
4689 // if demangling successful, keep buffer for next demangle
4697 void Options::dumpDependency(uint8_t opcode
, const char* path
) const
4699 if ( !this->dumpDependencyInfo() )
4702 // one time open() of -dependency_info file
4703 if ( fDependencyFileDescriptor
== -1 ) {
4704 fDependencyFileDescriptor
= open(this->dependencyInfoPath(), O_WRONLY
| O_TRUNC
| O_CREAT
, 0666);
4705 if ( fDependencyFileDescriptor
== -1 )
4706 throwf("Could not open or create -dependency_info file: %s", this->dependencyInfoPath());
4709 uint8_t version
= depLinkerVersion
;
4710 if ( write(fDependencyFileDescriptor
, &version
, 1) == -1 )
4711 throwf("write() to -dependency_info failed, errno=%d", errno
);
4712 extern const char ldVersionString
[];
4713 if ( write(fDependencyFileDescriptor
, ldVersionString
, strlen(ldVersionString
)+1) == -1 )
4714 throwf("write() to -dependency_info failed, errno=%d", errno
);
4717 char realPath
[PATH_MAX
];
4718 if ( path
[0] != '/' ) {
4719 if ( realpath(path
, realPath
) != NULL
) {
4724 if ( write(fDependencyFileDescriptor
, &opcode
, 1) == -1 )
4725 throwf("write() to -dependency_info failed, errno=%d", errno
);
4726 if ( write(fDependencyFileDescriptor
, path
, strlen(path
)+1) == -1 )
4727 throwf("write() to -dependency_info failed, errno=%d", errno
);
4729 //fprintf(stderr, "0x%02X %s\n", opcode, path);