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(NULL
),
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), fTraceSymbolLayout(false),
180 fMarkAppExtensionSafe(false), fCheckAppExtensionSafe(false), fForceLoadSwiftLibs(false),
181 fDebugInfoStripping(kDebugInfoMinimal
), fTraceOutputFile(NULL
),
182 fMacVersionMin(ld::macVersionUnset
), fIOSVersionMin(ld::iOSVersionUnset
),
183 fSaveTempFiles(false), fSnapshotRequested(false), fPipelineFifo(NULL
),
184 fDependencyInfoPath(NULL
), fDependencyFileDescriptor(-1)
186 this->checkForClassic(argc
, argv
);
187 this->parsePreCommandLineEnvironmentSettings();
188 this->parse(argc
, argv
);
189 this->parsePostCommandLineEnvironmentSettings();
190 this->reconfigureDefaults();
191 this->checkIllegalOptionCombinations();
193 if ( this->dumpDependencyInfo() ) {
194 this->dumpDependency(depOutputFile
, fOutputFile
);
195 if ( fMapPath
!= NULL
)
196 this->dumpDependency(depOutputFile
, fMapPath
);
202 if ( fDependencyFileDescriptor
!= -1 )
203 ::close(fDependencyFileDescriptor
);
206 bool Options::errorBecauseOfWarnings() const
208 return (sFatalWarnings
&& (sWarningsCount
> 0));
212 const char* Options::installPath() const
214 if ( fDylibInstallName
!= NULL
)
215 return fDylibInstallName
;
216 else if ( fFinalName
!= NULL
)
223 bool Options::interposable(const char* name
) const
225 switch ( fInterposeMode
) {
228 case kInterposeAllExternal
:
231 return fInterposeList
.contains(name
);
233 throw "internal error";
237 bool Options::printWhyLive(const char* symbolName
) const
239 return ( fWhyLive
.find(symbolName
) != fWhyLive
.end() );
243 const char* Options::dotOutputFile()
245 return fDotOutputFile
;
249 bool Options::hasWildCardExportRestrictList() const
251 // has -exported_symbols_list which contains some wildcards
252 return ((fExportMode
== kExportSome
) && fExportSymbols
.hasWildCards());
255 bool Options::hasWeakBitTweaks() const
257 // has -exported_symbols_list which contains some wildcards
258 return (!fForceWeakSymbols
.empty() || !fForceNotWeakSymbols
.empty());
261 bool Options::allGlobalsAreDeadStripRoots() const
263 // -exported_symbols_list means globals are not exported by default
264 if ( fExportMode
== kExportSome
)
267 switch ( fOutputKind
) {
268 case Options::kDynamicExecutable
:
269 // <rdar://problem/12839986> Add the -export_dynamic flag
270 return fExportDynamic
;
271 case Options::kStaticExecutable
:
272 // <rdar://problem/13361218> Support the -export_dynamic flag for xnu
273 return fExportDynamic
;
274 case Options::kPreload
:
275 // by default unused globals in a main executable are stripped
277 case Options::kDynamicLibrary
:
278 case Options::kDynamicBundle
:
279 case Options::kObjectFile
:
281 case Options::kKextBundle
:
288 bool Options::keepRelocations()
290 return fKeepRelocations
;
293 bool Options::warnStabs()
298 const char* Options::executablePath()
300 return fExecutablePath
;
303 uint32_t Options::initialSegProtection(const char* segName
) const
305 for(std::vector
<Options::SegmentProtect
>::const_iterator it
= fCustomSegmentProtections
.begin(); it
!= fCustomSegmentProtections
.end(); ++it
) {
306 if ( strcmp(it
->name
, segName
) == 0 ) {
310 if ( strcmp(segName
, "__PAGEZERO") == 0 ) {
313 else if ( strcmp(segName
, "__TEXT") == 0 ) {
314 return VM_PROT_READ
| VM_PROT_EXECUTE
;
316 else if ( strcmp(segName
, "__LINKEDIT") == 0 ) {
320 // all others default to read-write
321 return VM_PROT_READ
| VM_PROT_WRITE
;
324 uint32_t Options::maxSegProtection(const char* segName
) const
326 // iPhoneOS always uses same protection for max and initial
327 // <rdar://problem/11663436> simulator apps need to use MacOSX max-prot
328 if ( (fIOSVersionMin
!= ld::iOSVersionUnset
) && (fArchitecture
!= CPU_TYPE_I386
) )
329 return initialSegProtection(segName
);
331 for(std::vector
<Options::SegmentProtect
>::const_iterator it
= fCustomSegmentProtections
.begin(); it
!= fCustomSegmentProtections
.end(); ++it
) {
332 if ( strcmp(it
->name
, segName
) == 0 ) {
336 if ( strcmp(segName
, "__PAGEZERO") == 0 ) {
339 // all others default to all
340 return VM_PROT_READ
| VM_PROT_WRITE
| VM_PROT_EXECUTE
;
343 uint64_t Options::segPageSize(const char* segName
) const
345 for(std::vector
<SegmentSize
>::const_iterator it
=fCustomSegmentSizes
.begin(); it
!= fCustomSegmentSizes
.end(); ++it
) {
346 if ( strcmp(it
->name
, segName
) == 0 )
349 return fSegmentAlignment
;
352 uint64_t Options::customSegmentAddress(const char* segName
) const
354 for(std::vector
<SegmentStart
>::const_iterator it
=fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
355 if ( strcmp(it
->name
, segName
) == 0 )
358 // if custom stack in use, model as segment with custom address
359 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
360 return fStackAddr
- fStackSize
;
364 bool Options::hasCustomSegmentAddress(const char* segName
) const
366 for(std::vector
<SegmentStart
>::const_iterator it
=fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
367 if ( strcmp(it
->name
, segName
) == 0 )
370 // if custom stack in use, model as segment with custom address
371 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
376 bool Options::hasCustomSectionAlignment(const char* segName
, const char* sectName
) const
378 for (std::vector
<SectionAlignment
>::const_iterator it
= fSectionAlignments
.begin(); it
!= fSectionAlignments
.end(); ++it
) {
379 if ( (strcmp(it
->segmentName
, segName
) == 0) && (strcmp(it
->sectionName
, sectName
) == 0) )
385 uint8_t Options::customSectionAlignment(const char* segName
, const char* sectName
) const
387 for (std::vector
<SectionAlignment
>::const_iterator it
= fSectionAlignments
.begin(); it
!= fSectionAlignments
.end(); ++it
) {
388 if ( (strcmp(it
->segmentName
, segName
) == 0) && (strcmp(it
->sectionName
, sectName
) == 0) )
389 return it
->alignment
;
395 bool Options::hasExportedSymbolOrder()
397 return (fExportSymbolsOrder
.size() > 0);
400 bool Options::exportedSymbolOrder(const char* sym
, unsigned int* order
) const
402 NameToOrder::const_iterator pos
= fExportSymbolsOrder
.find(sym
);
403 if ( pos
!= fExportSymbolsOrder
.end() ) {
404 *order
= pos
->second
;
413 void Options::loadSymbolOrderFile(const char* fileOfExports
, NameToOrder
& orderMapping
)
415 // read in whole file
416 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
418 throwf("can't open -exported_symbols_order file: %s", fileOfExports
);
419 struct stat stat_buf
;
420 ::fstat(fd
, &stat_buf
);
421 char* p
= (char*)malloc(stat_buf
.st_size
);
423 throwf("can't process -exported_symbols_order file: %s", fileOfExports
);
425 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
426 throwf("can't read -exported_symbols_order file: %s", fileOfExports
);
430 // parse into symbols and add to unordered_set
431 unsigned int count
= 0;
432 char * const end
= &p
[stat_buf
.st_size
];
433 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
434 char* symbolStart
= NULL
;
435 for (char* s
= p
; s
< end
; ++s
) {
441 else if ( !isspace(*s
) ) {
447 if ( (*s
== '\n') || (*s
== '\r') ) {
449 // removing any trailing spaces
451 while ( isspace(*last
) ) {
455 orderMapping
[symbolStart
] = ++count
;
461 if ( (*s
== '\n') || (*s
== '\r') )
466 if ( state
== inSymbol
) {
467 warning("missing line-end at end of file \"%s\"", fileOfExports
);
468 int len
= end
-symbolStart
+1;
469 char* temp
= new char[len
];
470 strlcpy(temp
, symbolStart
, len
);
472 // remove any trailing spaces
473 char* last
= &temp
[len
-2];
474 while ( isspace(*last
) ) {
478 orderMapping
[temp
] = ++count
;
481 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
484 bool Options::forceWeak(const char* symbolName
) const
486 return fForceWeakSymbols
.contains(symbolName
);
489 bool Options::forceNotWeak(const char* symbolName
) const
491 return fForceNotWeakSymbols
.contains(symbolName
);
494 bool Options::forceWeakNonWildCard(const char* symbolName
) const
496 return fForceWeakSymbols
.containsNonWildcard(symbolName
);
499 bool Options::forceNotWeakNonWildcard(const char* symbolName
) const
501 return fForceNotWeakSymbols
.containsNonWildcard(symbolName
);
504 bool Options::forceCoalesce(const char* symbolName
) const
506 return fForceCoalesceSymbols
.contains(symbolName
);
510 bool Options::shouldExport(const char* symbolName
) const
512 switch (fExportMode
) {
514 return fExportSymbols
.contains(symbolName
);
515 case kDontExportSome
:
516 return ! fDontExportSymbols
.contains(symbolName
);
520 throw "internal error";
523 bool Options::shouldReExport(const char* symbolName
) const
525 return fReExportSymbols
.contains(symbolName
);
528 bool Options::keepLocalSymbol(const char* symbolName
) const
530 switch (fLocalSymbolHandling
) {
531 case kLocalSymbolsAll
:
533 case kLocalSymbolsNone
:
535 case kLocalSymbolsSelectiveInclude
:
536 return fLocalSymbolsIncluded
.contains(symbolName
);
537 case kLocalSymbolsSelectiveExclude
:
538 return ! fLocalSymbolsExcluded
.contains(symbolName
);
540 throw "internal error";
543 const std::vector
<const char*>* Options::sectionOrder(const char* segName
) const
545 for (std::vector
<SectionOrderList
>::const_iterator it
=fSectionOrder
.begin(); it
!= fSectionOrder
.end(); ++it
) {
546 if ( strcmp(it
->segmentName
, segName
) == 0 )
547 return &it
->sectionOrder
;
554 void Options::setArchitecture(cpu_type_t type
, cpu_subtype_t subtype
)
556 for (const ArchInfo
* t
=archInfoArray
; t
->archName
!= NULL
; ++t
) {
557 if ( (type
== t
->cpuType
) && (subtype
== t
->cpuSubType
) ) {
558 fArchitecture
= type
;
559 fSubArchitecture
= subtype
;
560 fArchitectureName
= t
->archName
;
561 fHasPreferredSubType
= t
->isSubType
;
562 fArchSupportsThumb2
= t
->supportsThumb2
;
565 case CPU_TYPE_X86_64
:
566 if ( (fMacVersionMin
== ld::macVersionUnset
) && (fIOSVersionMin
== ld::iOSVersionUnset
) && (fOutputKind
!= Options::kObjectFile
) ) {
567 #ifdef DEFAULT_MACOSX_MIN_VERSION
568 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION
);
569 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
571 warning("-macosx_version_min not specified, assuming 10.6");
572 fMacVersionMin
= ld::mac10_6
;
578 if ( (fMacVersionMin
== ld::macVersionUnset
) && (fIOSVersionMin
== ld::iOSVersionUnset
) && (fOutputKind
!= Options::kObjectFile
) ) {
579 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
580 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION
);
581 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION
);
583 warning("-ios_version_min not specified, assuming 6.0");
584 setIOSVersionMin("6.0");
589 fLinkSnapshot
.recordArch(fArchitectureName
);
590 // only use compressed LINKEDIT for:
591 // Mac OS X 10.6 or later
593 if ( !fMakeCompressedDyldInfo
&& minOS(ld::mac10_6
, ld::iOS_3_1
) && !fMakeCompressedDyldInfoForceOff
)
594 fMakeCompressedDyldInfo
= true;
595 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
596 if ( minOS(ld::mac10_5
, ld::iOS_2_0
) )
597 fUseSimplifiedDylibReExports
= true;
601 fArchitectureName
= "unknown architecture";
604 void Options::parseArch(const char* arch
)
607 throw "-arch must be followed by an architecture string";
608 for (const ArchInfo
* t
=archInfoArray
; t
->archName
!= NULL
; ++t
) {
609 if ( strcmp(t
->archName
,arch
) == 0 ) {
610 fArchitectureName
= arch
;
611 fArchitecture
= t
->cpuType
;
612 fSubArchitecture
= t
->cpuSubType
;
613 fHasPreferredSubType
= t
->isSubType
;
614 fArchSupportsThumb2
= t
->supportsThumb2
;
618 throwf("unknown/unsupported architecture name for: -arch %s", arch
);
621 bool Options::checkForFile(const char* format
, const char* dir
, const char* rootName
, FileInfo
& result
) const
623 char possiblePath
[strlen(dir
)+strlen(rootName
)+strlen(format
)+8];
624 sprintf(possiblePath
, format
, dir
, rootName
);
625 bool found
= result
.checkFileExists(*this, possiblePath
);
626 if ( fTraceDylibSearching
)
627 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), possiblePath
);
632 Options::FileInfo
Options::findLibrary(const char* rootName
, bool dylibsOnly
) const
635 const int rootNameLen
= strlen(rootName
);
636 // if rootName ends in .o there is no .a vs .dylib choice
637 if ( (rootNameLen
> 3) && (strcmp(&rootName
[rootNameLen
-2], ".o") == 0) ) {
638 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
639 it
!= fLibrarySearchPaths
.end();
641 const char* dir
= *it
;
642 if ( checkForFile("%s/%s", dir
, rootName
, result
) )
647 bool lookForDylibs
= false;
648 switch ( fOutputKind
) {
649 case Options::kDynamicExecutable
:
650 case Options::kDynamicLibrary
:
651 case Options::kDynamicBundle
:
652 case Options::kObjectFile
: // <rdar://problem/15914513>
653 lookForDylibs
= true;
655 case Options::kStaticExecutable
:
657 case Options::kPreload
:
658 case Options::kKextBundle
:
659 lookForDylibs
= false;
662 switch ( fLibrarySearchMode
) {
663 case kSearchAllDirsForDylibsThenAllDirsForArchives
:
664 // first look in all directories for just for dylibs
665 if ( lookForDylibs
) {
666 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
667 it
!= fLibrarySearchPaths
.end();
669 const char* dir
= *it
;
670 if ( checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
673 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
674 it
!= fLibrarySearchPaths
.end();
676 const char* dir
= *it
;
677 if ( checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
681 // next look in all directories for just for archives
683 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
684 it
!= fLibrarySearchPaths
.end();
686 const char* dir
= *it
;
687 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
693 case kSearchDylibAndArchiveInEachDir
:
694 // look in each directory for just for a dylib then for an archive
695 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
696 it
!= fLibrarySearchPaths
.end();
698 const char* dir
= *it
;
699 if ( lookForDylibs
&& checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
701 if ( lookForDylibs
&& checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
703 if ( !dylibsOnly
&& checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
709 throwf("library not found for -l%s", rootName
);
712 Options::FileInfo
Options::findFramework(const char* frameworkName
) const
714 if ( frameworkName
== NULL
)
715 throw "-framework missing next argument";
716 char temp
[strlen(frameworkName
)+1];
717 strcpy(temp
, frameworkName
);
718 const char* name
= temp
;
719 const char* suffix
= NULL
;
720 char* comma
= strchr(temp
, ',');
721 if ( comma
!= NULL
) {
725 return findFramework(name
, suffix
);
728 Options::FileInfo
Options::findFramework(const char* rootName
, const char* suffix
) const
730 for (std::vector
<const char*>::const_iterator it
= fFrameworkSearchPaths
.begin();
731 it
!= fFrameworkSearchPaths
.end();
733 // ??? Shouldn't we be using String here and just initializing it?
734 // ??? Use str.c_str () to pull out the string for the stat call.
735 const char* dir
= *it
;
736 char possiblePath
[PATH_MAX
];
737 strcpy(possiblePath
, dir
);
738 strcat(possiblePath
, "/");
739 strcat(possiblePath
, rootName
);
740 strcat(possiblePath
, ".framework/");
741 strcat(possiblePath
, rootName
);
742 if ( suffix
!= NULL
) {
743 char realPath
[PATH_MAX
];
744 // no symlink in framework to suffix variants, so follow main symlink
745 if ( realpath(possiblePath
, realPath
) != NULL
) {
746 strcpy(possiblePath
, realPath
);
747 strcat(possiblePath
, suffix
);
751 bool found
= result
.checkFileExists(*this, possiblePath
);
752 if ( fTraceDylibSearching
)
753 printf("[Logging for XBS]%sfound framework: '%s'\n",
754 (found
? " " : " not "), possiblePath
);
759 // try without suffix
760 if ( suffix
!= NULL
)
761 return findFramework(rootName
, NULL
);
763 throwf("framework not found %s", rootName
);
766 Options::FileInfo
Options::findFile(const char* path
) const
770 // if absolute path and not a .o file, the use SDK prefix
771 if ( (path
[0] == '/') && (strcmp(&path
[strlen(path
)-2], ".o") != 0) ) {
772 const int pathLen
= strlen(path
);
773 for (std::vector
<const char*>::const_iterator it
= fSDKPaths
.begin(); it
!= fSDKPaths
.end(); it
++) {
774 // ??? Shouldn't we be using String here?
775 const char* sdkPathDir
= *it
;
776 const int sdkPathDirLen
= strlen(sdkPathDir
);
777 char possiblePath
[sdkPathDirLen
+pathLen
+4];
778 strcpy(possiblePath
, sdkPathDir
);
779 if ( possiblePath
[sdkPathDirLen
-1] == '/' )
780 possiblePath
[sdkPathDirLen
-1] = '\0';
781 strcat(possiblePath
, path
);
782 if ( result
.checkFileExists(*this, possiblePath
) ) {
788 if ( result
.checkFileExists(*this, path
) ) {
792 // try @executable_path substitution
793 if ( (strncmp(path
, "@executable_path/", 17) == 0) && (fExecutablePath
!= NULL
) ) {
794 char newPath
[strlen(fExecutablePath
) + strlen(path
)];
795 strcpy(newPath
, fExecutablePath
);
796 char* addPoint
= strrchr(newPath
,'/');
797 if ( addPoint
!= NULL
)
798 strcpy(&addPoint
[1], &path
[17]);
800 strcpy(newPath
, &path
[17]);
801 if ( result
.checkFileExists(*this, newPath
) ) {
807 throwf("file not found: %s", path
);
810 Options::FileInfo
Options::findFileUsingPaths(const char* path
) const
814 const char* lastSlash
= strrchr(path
, '/');
815 const char* leafName
= (lastSlash
== NULL
) ? path
: &lastSlash
[1];
817 // Is this in a framework?
818 // /path/Foo.framework/Foo ==> true (Foo)
819 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
820 // /path/Foo.framework/Resources/Bar ==> false
821 bool isFramework
= false;
822 if ( lastSlash
!= NULL
) {
823 char frameworkDir
[strlen(leafName
) + 20];
824 strcpy(frameworkDir
, "/");
825 strcat(frameworkDir
, leafName
);
826 strcat(frameworkDir
, ".framework/");
827 if ( strstr(path
, frameworkDir
) != NULL
)
831 // These are abbreviated versions of the routines findFramework and findLibrary above
832 // because we already know the final name of the file that we're looking for and so
833 // don't need to try variations, just paths. We do need to add the additional bits
834 // onto the framework path though.
836 for (std::vector
<const char*>::const_iterator it
= fFrameworkSearchPaths
.begin();
837 it
!= fFrameworkSearchPaths
.end();
839 const char* dir
= *it
;
840 char possiblePath
[PATH_MAX
];
841 strcpy(possiblePath
, dir
);
842 strcat(possiblePath
, "/");
843 strcat(possiblePath
, leafName
);
844 strcat(possiblePath
, ".framework");
846 //fprintf(stderr,"Finding Framework: %s/%s, leafName=%s\n", possiblePath, leafName, leafName);
847 if ( checkForFile("%s/%s", possiblePath
, leafName
, result
) )
852 // if this is a .dylib inside a framework, do not search -L paths
853 // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
854 int leafLen
= strlen(leafName
);
855 bool embeddedDylib
= ( (leafLen
> 6)
856 && (strcmp(&leafName
[leafLen
-6], ".dylib") == 0)
857 && (strstr(path
, ".framework/") != NULL
) );
858 if ( !embeddedDylib
) {
859 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
860 it
!= fLibrarySearchPaths
.end();
862 const char* dir
= *it
;
863 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
864 if ( checkForFile("%s/%s", dir
, leafName
, result
) )
870 // If we didn't find it fall back to findFile.
871 return findFile(path
);
876 void Options::parseSegAddrTable(const char* segAddrPath
, const char* installPth
)
878 FILE* file
= fopen(segAddrPath
, "r");
879 if ( file
== NULL
) {
880 warning("-seg_addr_table file cannot be read: %s", segAddrPath
);
885 uint64_t firstColumAddress
= 0;
886 uint64_t secondColumAddress
= 0;
887 bool hasSecondColumn
= false;
888 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
889 path
[PATH_MAX
-1] = '\0';
890 char* eol
= strchr(path
, '\n');
893 // ignore lines not starting with 0x number
894 if ( (path
[0] == '0') && (path
[1] == 'x') ) {
896 firstColumAddress
= strtoull(path
, &p
, 16);
897 while ( isspace(*p
) )
899 // see if second column is a number
900 if ( (p
[0] == '0') && (p
[1] == 'x') ) {
901 secondColumAddress
= strtoull(p
, &p
, 16);
902 hasSecondColumn
= true;
903 while ( isspace(*p
) )
906 while ( isspace(*p
) )
909 // remove any trailing whitespace
910 for(char* end
= eol
-1; (end
> p
) && isspace(*end
); --end
)
912 // see if this line is for the dylib being linked
913 if ( strcmp(p
, installPth
) == 0 ) {
914 fBaseAddress
= firstColumAddress
;
915 if ( hasSecondColumn
) {
916 fBaseWritableAddress
= secondColumAddress
;
919 break; // out of while loop
928 void Options::loadFileList(const char* fileOfPaths
, ld::File::Ordinal baseOrdinal
)
931 const char* comma
= strrchr(fileOfPaths
, ',');
932 const char* prefix
= NULL
;
933 if ( comma
!= NULL
) {
934 // <rdar://problem/5907981> -filelist fails with comma in path
935 file
= fopen(fileOfPaths
, "r");
936 if ( file
== NULL
) {
938 int realFileOfPathsLen
= comma
-fileOfPaths
;
939 char realFileOfPaths
[realFileOfPathsLen
+1];
940 strncpy(realFileOfPaths
,fileOfPaths
, realFileOfPathsLen
);
941 realFileOfPaths
[realFileOfPathsLen
] = '\0';
942 file
= fopen(realFileOfPaths
, "r");
944 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", realFileOfPaths
, errno
, strerror(errno
));
945 if ( this->dumpDependencyInfo() )
946 this->dumpDependency(Options::depFileList
, realFileOfPaths
);
950 file
= fopen(fileOfPaths
, "r");
952 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", fileOfPaths
, errno
, strerror(errno
));
953 if ( this->dumpDependencyInfo() )
954 this->dumpDependency(Options::depFileList
, fileOfPaths
);
958 ld::File::Ordinal previousOrdinal
= baseOrdinal
;
959 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
960 path
[PATH_MAX
-1] = '\0';
961 char* eol
= strchr(path
, '\n');
964 if ( prefix
!= NULL
) {
965 char builtPath
[strlen(prefix
)+strlen(path
)+2];
966 strcpy(builtPath
, prefix
);
967 strcat(builtPath
, "/");
968 strcat(builtPath
, path
);
969 if (fPipelineFifo
!= NULL
) {
970 FileInfo info
= FileInfo(builtPath
);
971 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
972 previousOrdinal
= info
.ordinal
;
973 info
.fromFileList
= true;
974 fInputFiles
.push_back(info
);
976 FileInfo info
= findFile(builtPath
);
977 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
978 previousOrdinal
= info
.ordinal
;
979 info
.fromFileList
= true;
980 fInputFiles
.push_back(info
);
984 if (fPipelineFifo
!= NULL
) {
985 FileInfo info
= FileInfo(path
);
986 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
987 previousOrdinal
= info
.ordinal
;
988 info
.fromFileList
= true;
989 fInputFiles
.push_back(info
);
991 FileInfo info
= findFile(path
);
992 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
993 previousOrdinal
= info
.ordinal
;
994 info
.fromFileList
= true;
995 fInputFiles
.push_back(info
);
1003 void Options::SetWithWildcards::remove(const NameSet
& toBeRemoved
)
1005 for(NameSet::const_iterator it
=toBeRemoved
.begin(); it
!= toBeRemoved
.end(); ++it
) {
1006 const char* symbolName
= *it
;
1007 NameSet::iterator pos
= fRegular
.find(symbolName
);
1008 if ( pos
!= fRegular
.end() )
1009 fRegular
.erase(pos
);
1013 bool Options::SetWithWildcards::hasWildCards(const char* symbol
)
1015 // an exported symbol name containing *, ?, or [ requires wildcard matching
1016 return ( strpbrk(symbol
, "*?[") != NULL
);
1019 void Options::SetWithWildcards::insert(const char* symbol
)
1021 if ( hasWildCards(symbol
) )
1022 fWildCard
.push_back(symbol
);
1024 fRegular
.insert(symbol
);
1027 bool Options::SetWithWildcards::contains(const char* symbol
, bool* matchBecauseOfWildcard
) const
1029 if ( matchBecauseOfWildcard
!= NULL
)
1030 *matchBecauseOfWildcard
= false;
1031 // first look at hash table on non-wildcard symbols
1032 if ( fRegular
.find(symbol
) != fRegular
.end() )
1034 // next walk list of wild card symbols looking for a match
1035 for(std::vector
<const char*>::const_iterator it
= fWildCard
.begin(); it
!= fWildCard
.end(); ++it
) {
1036 if ( wildCardMatch(*it
, symbol
) ) {
1037 if ( matchBecauseOfWildcard
!= NULL
)
1038 *matchBecauseOfWildcard
= true;
1045 // Support "foo.o:_bar" to mean symbol _bar in file foo.o
1046 bool Options::SetWithWildcards::containsWithPrefix(const char* symbol
, const char* file
, bool& wildCardMatch
) const
1048 wildCardMatch
= false;
1049 if ( contains(symbol
, &wildCardMatch
) )
1053 const char* s
= strrchr(file
, '/');
1056 char buff
[strlen(file
)+strlen(symbol
)+2];
1057 sprintf(buff
, "%s:%s", file
, symbol
);
1058 return contains(buff
, &wildCardMatch
);
1061 bool Options::SetWithWildcards::containsNonWildcard(const char* symbol
) const
1063 // look at hash table on non-wildcard symbols
1064 return ( fRegular
.find(symbol
) != fRegular
.end() );
1069 bool Options::SetWithWildcards::inCharRange(const char*& p
, unsigned char c
) const
1073 while ( *p
!= '\0' ) {
1076 // found beginining [ and ending ]
1077 unsigned char last
= '\0';
1078 for ( const char* s
= b
; s
< e
; ++s
) {
1080 unsigned char next
= *(++s
);
1081 if ( (last
<= c
) && (c
<= next
) )
1098 bool Options::SetWithWildcards::wildCardMatch(const char* pattern
, const char* symbol
) const
1100 const char* s
= symbol
;
1101 for (const char* p
= pattern
; *p
!= '\0'; ++p
) {
1106 for (const char* t
= s
; *t
!= '\0'; ++t
) {
1107 if ( wildCardMatch(&p
[1], t
) )
1117 if ( ! inCharRange(p
, *s
) )
1127 return (*s
== '\0');
1131 void Options::loadExportFile(const char* fileOfExports
, const char* option
, SetWithWildcards
& set
)
1133 if ( fileOfExports
== NULL
)
1134 throwf("missing file after %s", option
);
1135 // read in whole file
1136 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
1138 throwf("can't open %s file: %s", option
, fileOfExports
);
1139 struct stat stat_buf
;
1140 ::fstat(fd
, &stat_buf
);
1141 char* p
= (char*)malloc(stat_buf
.st_size
);
1143 throwf("can't process %s file: %s", option
, fileOfExports
);
1145 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1146 throwf("can't read %s file: %s", option
, fileOfExports
);
1148 if ( this->dumpDependencyInfo() )
1149 this->dumpDependency(Options::depMisc
, fileOfExports
);
1153 // parse into symbols and add to unordered_set
1154 char * const end
= &p
[stat_buf
.st_size
];
1155 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1156 char* symbolStart
= NULL
;
1157 for (char* s
= p
; s
< end
; ++s
) {
1163 else if ( !isspace(*s
) ) {
1169 if ( (*s
== '\n') || (*s
== '\r') ) {
1171 // removing any trailing spaces
1173 while ( isspace(*last
) ) {
1177 set
.insert(symbolStart
);
1183 if ( (*s
== '\n') || (*s
== '\r') )
1188 if ( state
== inSymbol
) {
1189 warning("missing line-end at end of file \"%s\"", fileOfExports
);
1190 int len
= end
-symbolStart
+1;
1191 char* temp
= new char[len
];
1192 strlcpy(temp
, symbolStart
, len
);
1194 // remove any trailing spaces
1195 char* last
= &temp
[len
-2];
1196 while ( isspace(*last
) ) {
1203 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
1206 void Options::parseAliasFile(const char* fileOfAliases
)
1208 // read in whole file
1209 int fd
= ::open(fileOfAliases
, O_RDONLY
, 0);
1211 throwf("can't open alias file: %s", fileOfAliases
);
1212 struct stat stat_buf
;
1213 ::fstat(fd
, &stat_buf
);
1214 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1216 throwf("can't process alias file: %s", fileOfAliases
);
1218 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1219 throwf("can't read alias file: %s", fileOfAliases
);
1220 p
[stat_buf
.st_size
] = '\n';
1222 if ( this->dumpDependencyInfo() )
1223 this->dumpDependency(Options::depMisc
, fileOfAliases
);
1225 // parse into symbols and add to fAliases
1227 char * const end
= &p
[stat_buf
.st_size
+1];
1228 enum { lineStart
, inRealName
, inBetween
, inAliasName
, inComment
} state
= lineStart
;
1230 for (char* s
= p
; s
< end
; ++s
) {
1236 else if ( !isspace(*s
) ) {
1243 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1247 else if ( isspace(*s
) ) {
1254 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1258 else if ( ! isspace(*s
) ) {
1259 state
= inAliasName
;
1266 // removing any trailing spaces
1268 while ( isspace(*last
) ) {
1272 fAliases
.push_back(pair
);
1275 else if ( *s
== '\n' ) {
1277 // removing any trailing spaces
1279 while ( isspace(*last
) ) {
1283 fAliases
.push_back(pair
);
1294 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
1299 void Options::setUndefinedTreatment(const char* treatment
)
1301 if ( treatment
== NULL
)
1302 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
1304 if ( strcmp(treatment
, "warning") == 0 )
1305 fUndefinedTreatment
= kUndefinedWarning
;
1306 else if ( strcmp(treatment
, "error") == 0 )
1307 fUndefinedTreatment
= kUndefinedError
;
1308 else if ( strcmp(treatment
, "suppress") == 0 )
1309 fUndefinedTreatment
= kUndefinedSuppress
;
1310 else if ( strcmp(treatment
, "dynamic_lookup") == 0 )
1311 fUndefinedTreatment
= kUndefinedDynamicLookup
;
1313 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1316 Options::Treatment
Options::parseTreatment(const char* treatment
)
1318 if ( treatment
== NULL
)
1321 if ( strcmp(treatment
, "warning") == 0 )
1323 else if ( strcmp(treatment
, "error") == 0 )
1325 else if ( strcmp(treatment
, "suppress") == 0 )
1331 void Options::setMacOSXVersionMin(const char* version
)
1333 if ( version
== NULL
)
1334 throw "-macosx_version_min argument missing";
1336 if ( (strncmp(version
, "10.", 3) == 0) && isdigit(version
[3]) ) {
1337 unsigned int minorVersion
= 0;
1338 for (int i
=3; isdigit(version
[i
]); ++i
) {
1339 minorVersion
= minorVersion
*10 + (version
[i
] - '0');
1341 if ( minorVersion
> 255 ) {
1342 warning("Mac OS X minor version > 255 in '%s'", version
);
1345 fMacVersionMin
= (ld::MacVersionMin
)(0x000A0000 | (minorVersion
<< 8));
1348 warning("unknown option to -macosx_version_min, not 10.x");
1352 void Options::setIOSVersionMin(const char* version
)
1354 if ( version
== NULL
)
1355 throw "-ios_version_min argument missing";
1356 if ( ! isdigit(version
[0]) )
1357 throw "-ios_version_min argument is not a number";
1358 if ( version
[1] != '.' )
1359 throw "-ios_version_min argument is missing period as second character";
1360 if ( ! isdigit(version
[2]) )
1361 throw "-ios_version_min argument is not a number";
1363 unsigned int majorVersion
= version
[0] - '0';
1364 unsigned int minorVersion
= version
[2] - '0';
1365 fIOSVersionMin
= (ld::IOSVersionMin
)((majorVersion
<< 16) | (minorVersion
<< 8));
1368 bool Options::minOS(ld::MacVersionMin requiredMacMin
, ld::IOSVersionMin requirediPhoneOSMin
)
1370 if ( fMacVersionMin
!= ld::macVersionUnset
) {
1371 return ( fMacVersionMin
>= requiredMacMin
);
1374 return ( fIOSVersionMin
>= requirediPhoneOSMin
);
1379 void Options::setWeakReferenceMismatchTreatment(const char* treatment
)
1381 if ( treatment
== NULL
)
1382 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1384 if ( strcmp(treatment
, "error") == 0 )
1385 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchError
;
1386 else if ( strcmp(treatment
, "weak") == 0 )
1387 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchWeak
;
1388 else if ( strcmp(treatment
, "non-weak") == 0 )
1389 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchNonWeak
;
1391 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1394 Options::CommonsMode
Options::parseCommonsTreatment(const char* mode
)
1397 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1399 if ( strcmp(mode
, "ignore_dylibs") == 0 )
1400 return kCommonsIgnoreDylibs
;
1401 else if ( strcmp(mode
, "use_dylibs") == 0 )
1402 return kCommonsOverriddenByDylibs
;
1403 else if ( strcmp(mode
, "error") == 0 )
1404 return kCommonsConflictsDylibsError
;
1406 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1409 void Options::addDylibOverride(const char* paths
)
1411 if ( paths
== NULL
)
1412 throw "-dylib_file must followed by two colon separated paths";
1413 const char* colon
= strchr(paths
, ':');
1414 if ( colon
== NULL
)
1415 throw "-dylib_file must followed by two colon separated paths";
1416 int len
= colon
-paths
;
1417 char* target
= new char[len
+2];
1418 strncpy(target
, paths
, len
);
1420 DylibOverride entry
;
1421 entry
.installName
= target
;
1422 entry
.useInstead
= &colon
[1];
1423 fDylibOverrides
.push_back(entry
);
1426 uint64_t Options::parseAddress(const char* addr
)
1429 uint64_t result
= strtoull(addr
, &endptr
, 16);
1433 uint32_t Options::parseProtection(const char* prot
)
1435 uint32_t result
= 0;
1436 for(const char* p
= prot
; *p
!= '\0'; ++p
) {
1437 switch(tolower(*p
)) {
1439 result
|= VM_PROT_READ
;
1442 result
|= VM_PROT_WRITE
;
1445 result
|= VM_PROT_EXECUTE
;
1450 throwf("unknown -segprot lettter in %s", prot
);
1458 // Parses number of form A[.B[.B[.D[.E]]]] into a uint64_t where the bits are a24.b10.c10.d10.e10
1460 uint64_t Options::parseVersionNumber64(const char* versionString
)
1468 a
= strtoul(versionString
, &end
, 10);
1469 if ( *end
== '.' ) {
1470 b
= strtoul(&end
[1], &end
, 10);
1471 if ( *end
== '.' ) {
1472 c
= strtoul(&end
[1], &end
, 10);
1473 if ( *end
== '.' ) {
1474 d
= strtoul(&end
[1], &end
, 10);
1475 if ( *end
== '.' ) {
1476 e
= strtoul(&end
[1], &end
, 10);
1481 if ( (*end
!= '\0') || (a
> 0xFFFFFF) || (b
> 0x3FF) || (c
> 0x3FF) || (d
> 0x3FF) || (e
> 0x3FF) )
1482 throwf("malformed 64-bit a.b.c.d.e version number: %s", versionString
);
1484 return (a
<< 40) | ( b
<< 30 ) | ( c
<< 20 ) | ( d
<< 10 ) | e
;
1488 uint32_t Options::currentVersion32() const
1490 // warn if it does not fit into 32 bit vers number
1491 uint32_t a
= (fDylibCurrentVersion
>> 40) & 0xFFFF;
1492 uint32_t b
= (fDylibCurrentVersion
>> 30) & 0xFF;
1493 uint32_t c
= (fDylibCurrentVersion
>> 20) & 0xFF;
1494 uint64_t rep32
= ((uint64_t)a
<< 40) | ((uint64_t)b
<< 30) | ((uint64_t)c
<< 20);
1495 if ( rep32
!= fDylibCurrentVersion
) {
1496 warning("truncating -current_version to fit in 32-bit space used by old mach-o format");
1497 a
= (fDylibCurrentVersion
>> 40) & 0xFFFFFF;
1500 b
= (fDylibCurrentVersion
>> 30) & 0x3FF;
1503 c
= (fDylibCurrentVersion
>> 20) & 0x3FF;
1507 return (a
<< 16) | ( b
<< 8 ) | c
;
1511 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1513 uint32_t Options::parseVersionNumber32(const char* versionString
)
1519 x
= strtoul(versionString
, &end
, 10);
1520 if ( *end
== '.' ) {
1521 y
= strtoul(&end
[1], &end
, 10);
1522 if ( *end
== '.' ) {
1523 z
= strtoul(&end
[1], &end
, 10);
1526 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
1527 throwf("malformed 32-bit x.y.z version number: %s", versionString
);
1529 return (x
<< 16) | ( y
<< 8 ) | z
;
1532 static const char* cstringSymbolName(const char* orderFileString
)
1535 asprintf(&result
, "cstring=%s", orderFileString
);
1536 // convert escaped characters
1538 for(const char* s
=result
; *s
!= '\0'; ++s
, ++d
) {
1576 // hexadecimal value of char
1580 while ( isxdigit(*s
) ) {
1585 value
+= ((toupper(*s
)-'A') + 10);
1592 if ( isdigit(*s
) ) {
1593 // octal value of char
1595 while ( isdigit(*s
) ) {
1596 value
= (value
<< 3) + (*s
-'0');
1611 void Options::parseOrderFile(const char* path
, bool cstring
)
1613 // order files override auto-ordering
1614 fAutoOrderInitializers
= false;
1616 // read in whole file
1617 int fd
= ::open(path
, O_RDONLY
, 0);
1619 throwf("can't open order file: %s", path
);
1620 struct stat stat_buf
;
1621 ::fstat(fd
, &stat_buf
);
1622 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1624 throwf("can't process order file: %s", path
);
1625 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1626 throwf("can't read order file: %s", path
);
1628 p
[stat_buf
.st_size
] = '\n';
1629 if ( this->dumpDependencyInfo() )
1630 this->dumpDependency(Options::depMisc
, path
);
1632 // parse into vector of pairs
1633 char * const end
= &p
[stat_buf
.st_size
+1];
1634 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1635 char* symbolStart
= NULL
;
1636 for (char* s
= p
; s
< end
; ++s
) {
1642 else if ( !isspace(*s
) || cstring
) {
1648 if ( (*s
== '\n') || (!cstring
&& (*s
== '#')) ) {
1649 bool wasComment
= (*s
== '#');
1651 // removing any trailing spaces
1653 while ( isspace(*last
) ) {
1657 // if there is an architecture prefix, only use this symbol it if matches current arch
1658 if ( strncmp(symbolStart
, "ppc:", 4) == 0 ) {
1661 else if ( strncmp(symbolStart
, "ppc64:", 6) == 0 ) {
1664 else if ( strncmp(symbolStart
, "i386:", 5) == 0 ) {
1665 if ( fArchitecture
== CPU_TYPE_I386
)
1666 symbolStart
= &symbolStart
[5];
1670 else if ( strncmp(symbolStart
, "x86_64:", 7) == 0 ) {
1671 if ( fArchitecture
== CPU_TYPE_X86_64
)
1672 symbolStart
= &symbolStart
[7];
1676 else if ( strncmp(symbolStart
, "arm:", 4) == 0 ) {
1677 if ( fArchitecture
== CPU_TYPE_ARM
)
1678 symbolStart
= &symbolStart
[4];
1682 if ( symbolStart
!= NULL
) {
1683 char* objFileName
= NULL
;
1684 char* colon
= strstr(symbolStart
, ".o:");
1685 if ( colon
!= NULL
) {
1687 objFileName
= symbolStart
;
1688 symbolStart
= &colon
[3];
1691 colon
= strstr(symbolStart
, ".o):");
1692 if ( colon
!= NULL
) {
1694 objFileName
= symbolStart
;
1695 symbolStart
= &colon
[4];
1698 // trim leading spaces
1699 while ( isspace(*symbolStart
) )
1701 Options::OrderedSymbol pair
;
1703 pair
.symbolName
= cstringSymbolName(symbolStart
);
1705 pair
.symbolName
= symbolStart
;
1706 pair
.objectFileName
= objFileName
;
1707 fOrderedSymbols
.push_back(pair
);
1722 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1725 void Options::parseSectionOrderFile(const char* segment
, const char* section
, const char* path
)
1727 if ( (strcmp(section
, "__cstring") == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1728 parseOrderFile(path
, true);
1730 else if ( (strncmp(section
, "__literal",9) == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1731 warning("sorting of __literal[4,8,16] sections not supported");
1734 // ignore section information and append all symbol names to global order file
1735 parseOrderFile(path
, false);
1739 void Options::addSection(const char* segment
, const char* section
, const char* path
)
1741 if ( strlen(segment
) > 16 )
1742 throw "-seccreate segment name max 16 chars";
1743 if ( strlen(section
) > 16 ) {
1744 char* tmp
= strdup(section
);
1746 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section
, tmp
);
1750 // read in whole file
1751 int fd
= ::open(path
, O_RDONLY
, 0);
1753 throwf("can't open -sectcreate file: %s", path
);
1754 struct stat stat_buf
;
1755 ::fstat(fd
, &stat_buf
);
1756 char* p
= (char*)malloc(stat_buf
.st_size
);
1758 throwf("can't process -sectcreate file: %s", path
);
1759 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1760 throwf("can't read -sectcreate file: %s", path
);
1763 // record section to create
1764 ExtraSection info
= { segment
, section
, path
, (uint8_t*)p
, stat_buf
.st_size
};
1765 fExtraSections
.push_back(info
);
1768 void Options::addSectionRename(const char* srcSegment
, const char* srcSection
, const char* dstSegment
, const char* dstSection
)
1770 if ( strlen(srcSegment
) > 16 )
1771 throw "-rename_section segment name max 16 chars";
1772 if ( strlen(srcSection
) > 16 )
1773 throw "-rename_section section name max 16 chars";
1774 if ( strlen(dstSegment
) > 16 )
1775 throw "-rename_section segment name max 16 chars";
1776 if ( strlen(dstSection
) > 16 )
1777 throw "-rename_section section name max 16 chars";
1780 info
.fromSegment
= srcSegment
;
1781 info
.fromSection
= srcSection
;
1782 info
.toSegment
= dstSegment
;
1783 info
.toSection
= dstSection
;
1785 fSectionRenames
.push_back(info
);
1789 void Options::addSegmentRename(const char* srcSegment
, const char* dstSegment
)
1791 if ( strlen(srcSegment
) > 16 )
1792 throw "-rename_segment segment name max 16 chars";
1793 if ( strlen(dstSegment
) > 16 )
1794 throw "-rename_segment segment name max 16 chars";
1797 info
.fromSegment
= srcSegment
;
1798 info
.toSegment
= dstSegment
;
1800 fSegmentRenames
.push_back(info
);
1805 void Options::addSymbolMove(const char* dstSegment
, const char* symbolList
,
1806 std::vector
<SymbolsMove
>& list
, const char* optionName
)
1808 if ( strlen(dstSegment
) > 16 )
1809 throwf("%s segment name max 16 chars", optionName
);
1812 list
.push_back(tmp
);
1813 SymbolsMove
& info
= list
.back();
1814 info
.toSegment
= dstSegment
;
1815 loadExportFile(symbolList
, optionName
, info
.symbols
);
1818 bool Options::moveRwSymbol(const char* symName
, const char* filePath
, const char*& seg
, bool& wildCardMatch
) const
1820 for (std::vector
<SymbolsMove
>::const_iterator it
=fSymbolsMovesData
.begin(); it
!= fSymbolsMovesData
.end(); ++it
) {
1821 const SymbolsMove
& info
= *it
;
1822 if ( info
.symbols
.containsWithPrefix(symName
, filePath
, wildCardMatch
)) {
1823 seg
= info
.toSegment
;
1830 bool Options::moveRoSymbol(const char* symName
, const char* filePath
, const char*& seg
, bool& wildCardMatch
) const
1832 for (std::vector
<SymbolsMove
>::const_iterator it
=fSymbolsMovesCode
.begin(); it
!= fSymbolsMovesCode
.end(); ++it
) {
1833 const SymbolsMove
& info
= *it
;
1834 if ( info
.symbols
.containsWithPrefix(symName
, filePath
, wildCardMatch
)) {
1835 seg
= info
.toSegment
;
1842 void Options::addSectionAlignment(const char* segment
, const char* section
, const char* alignmentStr
)
1844 if ( strlen(segment
) > 16 )
1845 throw "-sectalign segment name max 16 chars";
1846 if ( strlen(section
) > 16 )
1847 throw "-sectalign section name max 16 chars";
1849 // argument to -sectalign is a hexadecimal number
1851 unsigned long value
= strtoul(alignmentStr
, &endptr
, 16);
1852 if ( *endptr
!= '\0')
1853 throw "argument for -sectalign is not a hexadecimal number";
1854 if ( value
> 0x8000 )
1855 throw "argument for -sectalign must be less than or equal to 0x8000";
1857 warning("zero is not a valid -sectalign");
1861 // alignment is power of 2 (e.g. page alignment = 12)
1862 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
1863 if ( (unsigned long)(1 << alignment
) != value
) {
1864 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
1865 segment
, section
, 1 << alignment
);
1868 SectionAlignment info
= { segment
, section
, alignment
};
1869 fSectionAlignments
.push_back(info
);
1872 void Options::addLibrary(const FileInfo
& info
)
1874 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
1875 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
1876 if ( strcmp(info
.path
, fit
->path
) == 0 ) {
1877 // if dylib is specified again but weak, record that it should be weak
1878 if ( info
.options
.fWeakImport
)
1879 fit
->options
.fWeakImport
= true;
1884 fInputFiles
.push_back(info
);
1887 void Options::warnObsolete(const char* arg
)
1889 warning("option %s is obsolete and being ignored", arg
);
1896 // Process all command line arguments.
1898 // The only error checking done here is that each option is valid and if it has arguments
1899 // that they too are valid.
1901 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
1902 // whichever was last on the command line is used.
1904 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
1906 void Options::parse(int argc
, const char* argv
[])
1908 // Store the original args in the link snapshot.
1909 fLinkSnapshot
.recordRawArgs(argc
, argv
);
1911 // pass one builds search list from -L and -F options
1912 this->buildSearchPaths(argc
, argv
);
1914 // reduce re-allocations
1915 fInputFiles
.reserve(32);
1917 // pass two parse all other options
1918 for(int i
=1; i
< argc
; ++i
) {
1919 const char* arg
= argv
[i
];
1921 if ( arg
[0] == '-' ) {
1922 // by default, copy one arg to the snapshot link command, and do no file copying
1923 int snapshotArgIndex
= i
;
1924 int snapshotArgCount
= -1; // -1 means compute count based on change in index
1925 int snapshotFileArgIndex
= -1; // -1 means no data file parameter to arg
1927 // Since we don't care about the files passed, just the option names, we do this here.
1929 fprintf (stderr
, "[Logging ld64 options]\t%s\n", arg
);
1931 if ( (arg
[1] == 'L') || (arg
[1] == 'F') ) {
1932 snapshotArgCount
= 0; // stripped out of link snapshot
1935 // previously handled by buildSearchPaths()
1937 // The one gnu style option we have to keep compatibility
1938 // with gcc. Might as well have the single hyphen one as well.
1939 else if ( (strcmp(arg
, "--help") == 0)
1940 || (strcmp(arg
, "-help") == 0)) {
1941 fprintf (stdout
, "ld64: For information on command line options please use 'man ld'.\n");
1944 else if ( strcmp(arg
, "-arch") == 0 ) {
1945 parseArch(argv
[++i
]);
1947 else if ( strcmp(arg
, "-dynamic") == 0 ) {
1950 else if ( strcmp(arg
, "-static") == 0 ) {
1952 if ( (fOutputKind
!= kObjectFile
) && (fOutputKind
!= kKextBundle
) ) {
1953 fOutputKind
= kStaticExecutable
;
1956 else if ( strcmp(arg
, "-dylib") == 0 ) {
1957 fOutputKind
= kDynamicLibrary
;
1959 else if ( strcmp(arg
, "-bundle") == 0 ) {
1960 fOutputKind
= kDynamicBundle
;
1962 else if ( strcmp(arg
, "-dylinker") == 0 ) {
1963 fOutputKind
= kDyld
;
1965 else if ( strcmp(arg
, "-execute") == 0 ) {
1966 if ( fOutputKind
!= kStaticExecutable
)
1967 fOutputKind
= kDynamicExecutable
;
1969 else if ( strcmp(arg
, "-preload") == 0 ) {
1970 fOutputKind
= kPreload
;
1972 else if ( strcmp(arg
, "-r") == 0 ) {
1973 fOutputKind
= kObjectFile
;
1975 else if ( strcmp(arg
, "-kext") == 0 ) {
1976 fOutputKind
= kKextBundle
;
1978 else if ( strcmp(arg
, "-o") == 0 ) {
1979 snapshotArgCount
= 0;
1980 fOutputFile
= argv
[++i
];
1981 fLinkSnapshot
.setSnapshotName(fOutputFile
);
1983 else if ( strncmp(arg
, "-lazy-l", 7) == 0 ) {
1984 snapshotArgCount
= 0;
1985 FileInfo info
= findLibrary(&arg
[7], true);
1986 info
.options
.fLazyLoad
= true;
1987 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
1989 fUsingLazyDylibLinking
= true;
1991 else if ( strcmp(arg
, "-lto_library") == 0 ) {
1992 snapshotFileArgIndex
= 1;
1993 fOverridePathlibLTO
= argv
[++i
];
1994 if ( fOverridePathlibLTO
== NULL
)
1995 throw "missing argument to -lto_library";
1997 else if ( (arg
[1] == 'l') && (strncmp(arg
,"-lazy_",6) !=0) ) {
1998 snapshotArgCount
= 0;
1999 FileInfo info
= findLibrary(&arg
[2]);
2000 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2003 // This causes a dylib to be weakly bound at
2004 // link time. This corresponds to weak_import.
2005 else if ( strncmp(arg
, "-weak-l", 7) == 0 ) {
2006 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2007 snapshotArgCount
= 0;
2008 FileInfo info
= findLibrary(&arg
[7]);
2009 info
.options
.fWeakImport
= true;
2010 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2013 // Avoid lazy binding.
2014 else if ( strcmp(arg
, "-bind_at_load") == 0 ) {
2017 else if ( strcmp(arg
, "-twolevel_namespace") == 0 ) {
2018 fNameSpace
= kTwoLevelNameSpace
;
2020 else if ( strcmp(arg
, "-flat_namespace") == 0 ) {
2021 fNameSpace
= kFlatNameSpace
;
2023 // Also sets a bit to ensure dyld causes everything
2024 // in the namespace to be flat.
2026 else if ( strcmp(arg
, "-force_flat_namespace") == 0 ) {
2027 fNameSpace
= kForceFlatNameSpace
;
2029 // Similar to --whole-archive.
2030 else if ( strcmp(arg
, "-all_load") == 0 ) {
2031 fFullyLoadArchives
= true;
2033 else if ( strcmp(arg
, "-noall_load") == 0) {
2036 // Similar to -all_load
2037 else if ( strcmp(arg
, "-ObjC") == 0 ) {
2038 fLoadAllObjcObjectsFromArchives
= true;
2040 // Similar to -all_load, but for the following archive only.
2041 else if ( strcmp(arg
, "-force_load") == 0 ) {
2042 FileInfo info
= findFile(argv
[++i
]);
2043 info
.options
.fForceLoad
= true;
2044 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2047 // Library versioning.
2048 else if ( (strcmp(arg
, "-dylib_compatibility_version") == 0)
2049 || (strcmp(arg
, "-compatibility_version") == 0)) {
2050 const char* vers
= argv
[++i
];
2052 throw "-dylib_compatibility_version missing <version>";
2053 fDylibCompatVersion
= parseVersionNumber32(vers
);
2055 else if ( (strcmp(arg
, "-dylib_current_version") == 0)
2056 || (strcmp(arg
, "-current_version") == 0)) {
2057 const char* vers
= argv
[++i
];
2059 throw "-dylib_current_version missing <version>";
2060 fDylibCurrentVersion
= parseVersionNumber64(vers
);
2062 else if ( strcmp(arg
, "-sectorder") == 0 ) {
2063 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2064 throw "-sectorder missing <segment> <section> <file-path>";
2065 snapshotFileArgIndex
= 3;
2066 parseSectionOrderFile(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2069 else if ( strcmp(arg
, "-order_file") == 0 ) {
2070 snapshotFileArgIndex
= 1;
2071 parseOrderFile(argv
[++i
], false);
2073 else if ( strcmp(arg
, "-order_file_statistics") == 0 ) {
2074 fPrintOrderFileStatistics
= true;
2076 // ??? Deprecate segcreate.
2077 // -sectcreate puts whole files into a section in the output.
2078 else if ( (strcmp(arg
, "-sectcreate") == 0) || (strcmp(arg
, "-segcreate") == 0) ) {
2079 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2080 throw "-sectcreate missing <segment> <section> <file-path>";
2081 snapshotFileArgIndex
= 3;
2082 addSection(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2085 // Since we have a full path in binary/library names we need to be able to override it.
2086 else if ( (strcmp(arg
, "-dylib_install_name") == 0)
2087 || (strcmp(arg
, "-dylinker_install_name") == 0)
2088 || (strcmp(arg
, "-install_name") == 0)) {
2089 fDylibInstallName
= argv
[++i
];
2090 if ( fDylibInstallName
== NULL
)
2091 throw "-install_name missing <path>";
2093 // Sets the base address of the output.
2094 else if ( (strcmp(arg
, "-seg1addr") == 0) || (strcmp(arg
, "-image_base") == 0) ) {
2095 const char* address
= argv
[++i
];
2096 if ( address
== NULL
)
2097 throwf("%s missing <address>", arg
);
2098 fBaseAddress
= parseAddress(address
);
2099 uint64_t temp
= ((fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
2100 if ( fBaseAddress
!= temp
) {
2101 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment
);
2102 fBaseAddress
= temp
;
2105 else if ( strcmp(arg
, "-e") == 0 ) {
2106 fEntryName
= argv
[++i
];
2108 // Same as -@ from the FSF linker.
2109 else if ( strcmp(arg
, "-filelist") == 0 ) {
2110 snapshotArgCount
= 0;
2111 const char* path
= argv
[++i
];
2112 if ( (path
== NULL
) || (path
[0] == '-') )
2113 throw "-filelist missing <path>";
2114 ld::File::Ordinal baseOrdinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2115 loadFileList(path
, baseOrdinal
);
2117 else if ( strcmp(arg
, "-keep_private_externs") == 0 ) {
2118 fKeepPrivateExterns
= true;
2120 else if ( strcmp(arg
, "-final_output") == 0 ) {
2121 fFinalName
= argv
[++i
];
2123 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
2124 // just ensures that this happens for cross object file boundaries.
2125 else if ( (strcmp(arg
, "-interposable") == 0) || (strcmp(arg
, "-multi_module") == 0)) {
2126 switch ( fInterposeMode
) {
2127 case kInterposeNone
:
2128 case kInterposeAllExternal
:
2129 fInterposeMode
= kInterposeAllExternal
;
2131 case kInterposeSome
:
2132 // do nothing, -interposable_list overrides -interposable"
2136 else if ( strcmp(arg
, "-interposable_list") == 0 ) {
2137 snapshotFileArgIndex
= 1;
2138 fInterposeMode
= kInterposeSome
;
2139 loadExportFile(argv
[++i
], "-interposable_list", fInterposeList
);
2141 // Default for -interposable/-multi_module/-single_module.
2142 else if ( strcmp(arg
, "-single_module") == 0 ) {
2143 fInterposeMode
= kInterposeNone
;
2145 else if ( strcmp(arg
, "-exported_symbols_list") == 0 ) {
2146 snapshotFileArgIndex
= 1;
2147 if ( fExportMode
== kDontExportSome
)
2148 throw "can't use -exported_symbols_list and -unexported_symbols_list";
2149 fExportMode
= kExportSome
;
2150 loadExportFile(argv
[++i
], "-exported_symbols_list", fExportSymbols
);
2152 else if ( strcmp(arg
, "-unexported_symbols_list") == 0 ) {
2153 snapshotFileArgIndex
= 1;
2154 if ( fExportMode
== kExportSome
)
2155 throw "can't use -unexported_symbols_list and -exported_symbols_list";
2156 fExportMode
= kDontExportSome
;
2157 loadExportFile(argv
[++i
], "-unexported_symbols_list", fDontExportSymbols
);
2159 else if ( strcmp(arg
, "-exported_symbol") == 0 ) {
2160 if ( fExportMode
== kDontExportSome
)
2161 throw "can't use -exported_symbol and -unexported_symbols";
2162 fExportMode
= kExportSome
;
2163 fExportSymbols
.insert(argv
[++i
]);
2165 else if ( strcmp(arg
, "-unexported_symbol") == 0 ) {
2166 if ( fExportMode
== kExportSome
)
2167 throw "can't use -unexported_symbol and -exported_symbol";
2168 fExportMode
= kDontExportSome
;
2169 fDontExportSymbols
.insert(argv
[++i
]);
2171 else if ( strcmp(arg
, "-non_global_symbols_no_strip_list") == 0 ) {
2172 snapshotFileArgIndex
= 1;
2173 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveExclude
)
2174 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2175 fLocalSymbolHandling
= kLocalSymbolsSelectiveInclude
;
2176 loadExportFile(argv
[++i
], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded
);
2178 else if ( strcmp(arg
, "-non_global_symbols_strip_list") == 0 ) {
2179 snapshotFileArgIndex
= 1;
2180 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveInclude
)
2181 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2182 fLocalSymbolHandling
= kLocalSymbolsSelectiveExclude
;
2183 loadExportFile(argv
[++i
], "-non_global_symbols_strip_list", fLocalSymbolsExcluded
);
2186 else if ( strcmp(arg
, "-no_arch_warnings") == 0 ) {
2187 fIgnoreOtherArchFiles
= true;
2189 else if ( strcmp(arg
, "-force_cpusubtype_ALL") == 0 ) {
2190 fForceSubtypeAll
= true;
2191 fAllowCpuSubtypeMismatches
= true;
2193 // Similar to -weak-l but uses the absolute path name to the library.
2194 else if ( strcmp(arg
, "-weak_library") == 0 ) {
2195 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2196 snapshotArgCount
= 0;
2197 FileInfo info
= findFile(argv
[++i
]);
2198 info
.options
.fWeakImport
= true;
2199 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2202 else if ( strcmp(arg
, "-lazy_library") == 0 ) {
2203 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2204 snapshotArgCount
= 0;
2205 FileInfo info
= findFile(argv
[++i
]);
2206 info
.options
.fLazyLoad
= true;
2207 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2209 fUsingLazyDylibLinking
= true;
2211 else if ( strcmp(arg
, "-framework") == 0 ) {
2212 snapshotArgCount
= 0;
2213 FileInfo info
= findFramework(argv
[++i
]);
2214 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2217 else if ( strcmp(arg
, "-weak_framework") == 0 ) {
2218 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2219 snapshotArgCount
= 0;
2220 FileInfo info
= findFramework(argv
[++i
]);
2221 info
.options
.fWeakImport
= true;
2222 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2225 else if ( strcmp(arg
, "-lazy_framework") == 0 ) {
2226 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2227 snapshotArgCount
= 0;
2228 FileInfo info
= findFramework(argv
[++i
]);
2229 info
.options
.fLazyLoad
= true;
2230 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2232 fUsingLazyDylibLinking
= true;
2234 else if ( strcmp(arg
, "-search_paths_first") == 0 ) {
2235 // previously handled by buildSearchPaths()
2237 else if ( strcmp(arg
, "-search_dylibs_first") == 0 ) {
2238 // previously handled by buildSearchPaths()
2240 else if ( strcmp(arg
, "-undefined") == 0 ) {
2241 setUndefinedTreatment(argv
[++i
]);
2243 // Debugging output flag.
2244 else if ( strcmp(arg
, "-arch_multiple") == 0 ) {
2245 fMessagesPrefixedWithArchitecture
= true;
2247 // Specify what to do with relocations in read only
2248 // sections like .text. Could be errors, warnings,
2249 // or suppressed. Currently we do nothing with the
2251 else if ( strcmp(arg
, "-read_only_relocs") == 0 ) {
2252 switch ( parseTreatment(argv
[++i
]) ) {
2255 throw "-read_only_relocs missing [ warning | error | suppress ]";
2257 fWarnTextRelocs
= true;
2258 fAllowTextRelocs
= true;
2261 fWarnTextRelocs
= false;
2262 fAllowTextRelocs
= true;
2265 fWarnTextRelocs
= false;
2266 fAllowTextRelocs
= false;
2270 else if ( strcmp(arg
, "-sect_diff_relocs") == 0 ) {
2274 // Warn, error or make strong a mismatch between weak
2275 // and non-weak references.
2276 else if ( strcmp(arg
, "-weak_reference_mismatches") == 0 ) {
2277 setWeakReferenceMismatchTreatment(argv
[++i
]);
2279 // For a deployment target of 10.3 and earlier ld64 will
2280 // prebind an executable with 0s in all addresses that
2281 // are prebound. This can then be fixed up by update_prebinding
2282 // later. Prebinding is less useful on 10.4 and greater.
2283 else if ( strcmp(arg
, "-prebind") == 0 ) {
2286 else if ( strcmp(arg
, "-noprebind") == 0 ) {
2290 else if ( strcmp(arg
, "-prebind_allow_overlap") == 0 ) {
2293 else if ( strcmp(arg
, "-prebind_all_twolevel_modules") == 0 ) {
2296 else if ( strcmp(arg
, "-noprebind_all_twolevel_modules") == 0 ) {
2299 else if ( strcmp(arg
, "-nofixprebinding") == 0 ) {
2302 // This should probably be deprecated when we respect -L and -F
2303 // when searching for libraries.
2304 else if ( strcmp(arg
, "-dylib_file") == 0 ) {
2305 // ignore for snapshot because a stub dylib will be created in the snapshot
2306 snapshotArgCount
= 0;
2307 addDylibOverride(argv
[++i
]);
2309 // What to expand @executable_path to if found in dependent dylibs
2310 else if ( strcmp(arg
, "-executable_path") == 0 ) {
2311 fExecutablePath
= argv
[++i
];
2312 if ( (fExecutablePath
== NULL
) || (fExecutablePath
[0] == '-') )
2313 throw "-executable_path missing <path>";
2314 // if a directory was passed, add / to end
2315 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2316 struct stat statBuffer
;
2317 if ( stat(fExecutablePath
, &statBuffer
) == 0 ) {
2318 if ( (statBuffer
.st_mode
& S_IFMT
) == S_IFDIR
) {
2319 char* pathWithSlash
= new char[strlen(fExecutablePath
)+2];
2320 strcpy(pathWithSlash
, fExecutablePath
);
2321 strcat(pathWithSlash
, "/");
2322 fExecutablePath
= pathWithSlash
;
2326 // Aligns all segments to the power of 2 boundary specified.
2327 else if ( strcmp(arg
, "-segalign") == 0 ) {
2328 const char* size
= argv
[++i
];
2330 throw "-segalign missing <size>";
2331 fSegmentAlignment
= parseAddress(size
);
2332 uint8_t alignment
= (uint8_t)__builtin_ctz(fSegmentAlignment
);
2333 uint32_t p2aligned
= (1 << alignment
);
2334 if ( p2aligned
!= fSegmentAlignment
) {
2335 warning("alignment for -segalign %s is not a power of two, using 0x%X", size
, p2aligned
);
2336 fSegmentAlignment
= p2aligned
;
2339 // Puts a specified segment at a particular address that must
2340 // be a multiple of the segment alignment.
2341 else if ( strcmp(arg
, "-segaddr") == 0 ) {
2343 seg
.name
= argv
[++i
];
2344 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2345 throw "-segaddr missing segName Adddress";
2346 seg
.address
= parseAddress(argv
[++i
]);
2347 uint64_t temp
= ((seg
.address
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
2348 if ( seg
.address
!= temp
)
2349 warning("-segaddr %s not %lld byte aligned", seg
.name
, fSegmentAlignment
);
2350 fCustomSegmentAddresses
.push_back(seg
);
2352 // ??? Deprecate when we deprecate split-seg.
2353 else if ( strcmp(arg
, "-segs_read_only_addr") == 0 ) {
2354 fBaseAddress
= parseAddress(argv
[++i
]);
2356 // ??? Deprecate when we deprecate split-seg.
2357 else if ( strcmp(arg
, "-segs_read_write_addr") == 0 ) {
2358 fBaseWritableAddress
= parseAddress(argv
[++i
]);
2361 // ??? Deprecate when we get rid of basing at build time.
2362 else if ( strcmp(arg
, "-seg_addr_table") == 0 ) {
2363 snapshotFileArgIndex
= 1;
2364 const char* name
= argv
[++i
];
2366 throw "-seg_addr_table missing argument";
2367 fSegAddrTablePath
= name
;
2369 else if ( strcmp(arg
, "-seg_addr_table_filename") == 0 ) {
2373 else if ( strcmp(arg
, "-segprot") == 0 ) {
2375 seg
.name
= argv
[++i
];
2376 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) || (argv
[i
+2] == NULL
) )
2377 throw "-segprot missing segName max-prot init-prot";
2378 seg
.max
= parseProtection(argv
[++i
]);
2379 seg
.init
= parseProtection(argv
[++i
]);
2380 fCustomSegmentProtections
.push_back(seg
);
2382 else if ( strcmp(arg
, "-pagezero_size") == 0 ) {
2383 const char* size
= argv
[++i
];
2385 throw "-pagezero_size missing <size>";
2386 fZeroPageSize
= parseAddress(size
);
2387 uint64_t temp
= fZeroPageSize
& (-4096); // page align
2388 if ( (fZeroPageSize
!= temp
) )
2389 warning("-pagezero_size not page aligned, rounding down");
2390 fZeroPageSize
= temp
;
2392 else if ( strcmp(arg
, "-stack_addr") == 0 ) {
2393 const char* address
= argv
[++i
];
2394 if ( address
== NULL
)
2395 throw "-stack_addr missing <address>";
2396 fStackAddr
= parseAddress(address
);
2398 else if ( strcmp(arg
, "-stack_size") == 0 ) {
2399 const char* size
= argv
[++i
];
2401 throw "-stack_size missing <address>";
2402 fStackSize
= parseAddress(size
);
2403 uint64_t temp
= fStackSize
& (-4096); // page align
2404 if ( (fStackSize
!= temp
) )
2405 warning("-stack_size not page aligned, rounding down");
2407 else if ( strcmp(arg
, "-allow_stack_execute") == 0 ) {
2408 fExecutableStack
= true;
2410 else if ( strcmp(arg
, "-allow_heap_execute") == 0 ) {
2411 fDisableNonExecutableHeap
= true;
2413 else if ( strcmp(arg
, "-sectalign") == 0 ) {
2414 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2415 throw "-sectalign missing <segment> <section> <file-path>";
2416 addSectionAlignment(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2419 else if ( strcmp(arg
, "-sectorder_detail") == 0 ) {
2422 else if ( strcmp(arg
, "-sectobjectsymbols") == 0 ) {
2426 else if ( strcmp(arg
, "-bundle_loader") == 0 ) {
2427 snapshotFileArgIndex
= 1;
2428 fBundleLoader
= argv
[++i
];
2429 if ( (fBundleLoader
== NULL
) || (fBundleLoader
[0] == '-') )
2430 throw "-bundle_loader missing <path>";
2431 FileInfo info
= findFile(fBundleLoader
);
2432 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2433 info
.options
.fBundleLoader
= true;
2434 fInputFiles
.push_back(info
);
2436 else if ( strcmp(arg
, "-private_bundle") == 0 ) {
2439 else if ( strcmp(arg
, "-twolevel_namespace_hints") == 0 ) {
2442 // Use this flag to set default behavior for deployement targets.
2443 else if ( strcmp(arg
, "-macosx_version_min") == 0 ) {
2444 const char* macVers
= argv
[++i
];
2445 const char* envMacVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
2446 const char* enviPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
2447 if ( (envMacVers
!= NULL
) && (enviPhoneVers
!= NULL
) ) {
2448 // <rdar://problem/13774329> when conflicting deployments set, break tie by looking at syslibroot
2449 warning("both MACOSX_DEPLOYMENT_TARGET and IPHONEOS_DEPLOYMENT_TARGET are set");
2450 if ( !fSDKPaths
.empty() ) {
2451 const char* sysrootPath
= fSDKPaths
.back();
2452 const char* lastSlash
= strrchr(sysrootPath
, '/');
2453 if ( strstr(lastSlash
, "Simulator") != NULL
)
2454 setIOSVersionMin(enviPhoneVers
);
2456 setMacOSXVersionMin(macVers
);
2459 setMacOSXVersionMin(macVers
);
2463 setMacOSXVersionMin(macVers
);
2466 else if ( (strcmp(arg
, "-ios_version_min") == 0) || (strcmp(arg
, "-iphoneos_version_min") == 0) ) {
2467 setIOSVersionMin(argv
[++i
]);
2469 else if ( strcmp(arg
, "-ios_simulator_version_min") == 0 ) {
2470 setIOSVersionMin(argv
[++i
]);
2471 fTargetIOSSimulator
= true;
2473 else if ( strcmp(arg
, "-multiply_defined") == 0 ) {
2474 //warnObsolete(arg);
2477 else if ( strcmp(arg
, "-multiply_defined_unused") == 0 ) {
2481 else if ( strcmp(arg
, "-nomultidefs") == 0 ) {
2484 // Display each file in which the argument symbol appears and whether
2485 // the file defines or references it. This option takes an argument
2486 // as -y<symbol> note that there is no space.
2487 else if ( strncmp(arg
, "-y", 2) == 0 ) {
2490 // Same output as -y, but output <arg> number of undefined symbols only.
2491 else if ( strcmp(arg
, "-Y") == 0 ) {
2492 //warnObsolete(arg);
2495 // This option affects all objects linked into the final result.
2496 else if ( strcmp(arg
, "-m") == 0 ) {
2499 else if ( (strcmp(arg
, "-why_load") == 0) || (strcmp(arg
, "-whyload") == 0) ) {
2502 else if ( strcmp(arg
, "-why_live") == 0 ) {
2503 const char* name
= argv
[++i
];
2505 throw "-why_live missing symbol name argument";
2506 fWhyLive
.insert(name
);
2508 else if ( strcmp(arg
, "-u") == 0 ) {
2509 const char* name
= argv
[++i
];
2511 throw "-u missing argument";
2512 fInitialUndefines
.push_back(name
);
2514 else if ( strcmp(arg
, "-U") == 0 ) {
2515 const char* name
= argv
[++i
];
2517 throw "-U missing argument";
2518 fAllowedUndefined
.insert(name
);
2520 else if ( strcmp(arg
, "-s") == 0 ) {
2522 fLocalSymbolHandling
= kLocalSymbolsNone
;
2523 fDebugInfoStripping
= Options::kDebugInfoNone
;
2525 else if ( strcmp(arg
, "-x") == 0 ) {
2526 fLocalSymbolHandling
= kLocalSymbolsNone
;
2528 else if ( strcmp(arg
, "-S") == 0 ) {
2529 fDebugInfoStripping
= Options::kDebugInfoNone
;
2531 else if ( strcmp(arg
, "-X") == 0 ) {
2534 else if ( strcmp(arg
, "-Si") == 0 ) {
2536 fDebugInfoStripping
= Options::kDebugInfoFull
;
2538 else if ( strcmp(arg
, "-b") == 0 ) {
2541 else if ( strcmp(arg
, "-Sn") == 0 ) {
2543 fDebugInfoStripping
= Options::kDebugInfoFull
;
2545 else if ( strcmp(arg
, "-Sp") == 0 ) {
2548 else if ( strcmp(arg
, "-dead_strip") == 0 ) {
2551 else if ( strcmp(arg
, "-no_dead_strip_inits_and_terms") == 0 ) {
2554 else if ( strcmp(arg
, "-w") == 0 ) {
2555 // previously handled by buildSearchPaths()
2557 else if ( strcmp(arg
, "-fatal_warnings") == 0 ) {
2558 // previously handled by buildSearchPaths()
2560 else if ( strcmp(arg
, "-arch_errors_fatal") == 0 ) {
2561 fErrorOnOtherArchFiles
= true;
2563 else if ( strcmp(arg
, "-M") == 0 ) {
2566 else if ( strcmp(arg
, "-headerpad") == 0 ) {
2567 const char* size
= argv
[++i
];
2569 throw "-headerpad missing argument";
2570 fMinimumHeaderPad
= parseAddress(size
);
2572 else if ( strcmp(arg
, "-headerpad_max_install_names") == 0 ) {
2573 fMaxMinimumHeaderPad
= true;
2575 else if ( strcmp(arg
, "-t") == 0 ) {
2576 fLogAllFiles
= true;
2578 else if ( strcmp(arg
, "-whatsloaded") == 0 ) {
2579 fLogObjectFiles
= true;
2581 else if ( strcmp(arg
, "-A") == 0 ) {
2585 else if ( strcmp(arg
, "-umbrella") == 0 ) {
2586 const char* name
= argv
[++i
];
2588 throw "-umbrella missing argument";
2589 fUmbrellaName
= name
;
2591 else if ( strcmp(arg
, "-allowable_client") == 0 ) {
2592 const char* name
= argv
[++i
];
2595 throw "-allowable_client missing argument";
2597 fAllowableClients
.push_back(name
);
2599 else if ( strcmp(arg
, "-client_name") == 0 ) {
2600 const char* name
= argv
[++i
];
2603 throw "-client_name missing argument";
2607 else if ( strcmp(arg
, "-sub_umbrella") == 0 ) {
2608 const char* name
= argv
[++i
];
2610 throw "-sub_umbrella missing argument";
2611 fSubUmbellas
.push_back(name
);
2613 else if ( strcmp(arg
, "-sub_library") == 0 ) {
2614 const char* name
= argv
[++i
];
2616 throw "-sub_library missing argument";
2617 fSubLibraries
.push_back(name
);
2619 else if ( strcmp(arg
, "-init") == 0 ) {
2620 const char* name
= argv
[++i
];
2622 throw "-init missing argument";
2623 fInitFunctionName
= name
;
2625 else if ( strcmp(arg
, "-dot") == 0 ) {
2626 const char* name
= argv
[++i
];
2628 throw "-dot missing argument";
2629 fDotOutputFile
= name
;
2631 else if ( strcmp(arg
, "-warn_commons") == 0 ) {
2632 fWarnCommons
= true;
2634 else if ( strcmp(arg
, "-commons") == 0 ) {
2635 fCommonsMode
= parseCommonsTreatment(argv
[++i
]);
2637 else if ( strcmp(arg
, "-keep_relocs") == 0 ) {
2638 fKeepRelocations
= true;
2640 else if ( strcmp(arg
, "-warn_stabs") == 0 ) {
2643 else if ( strcmp(arg
, "-pause") == 0 ) {
2646 else if ( strcmp(arg
, "-print_statistics") == 0 ) {
2649 else if ( strcmp(arg
, "-d") == 0 ) {
2650 fMakeTentativeDefinitionsReal
= true;
2652 else if ( strcmp(arg
, "-v") == 0 ) {
2653 // previously handled by buildSearchPaths()
2655 else if ( strcmp(arg
, "-Z") == 0 ) {
2656 // previously handled by buildSearchPaths()
2658 else if ( strcmp(arg
, "-syslibroot") == 0 ) {
2659 snapshotArgCount
= 0;
2661 // previously handled by buildSearchPaths()
2663 else if ( strcmp(arg
, "-no_uuid") == 0 ) {
2664 fUUIDMode
= kUUIDNone
;
2666 else if ( strcmp(arg
, "-random_uuid") == 0 ) {
2667 fUUIDMode
= kUUIDRandom
;
2669 else if ( strcmp(arg
, "-dtrace") == 0 ) {
2670 snapshotFileArgIndex
= 1;
2671 const char* name
= argv
[++i
];
2673 throw "-dtrace missing argument";
2674 fDtraceScriptName
= name
;
2676 else if ( strcmp(arg
, "-root_safe") == 0 ) {
2679 else if ( strcmp(arg
, "-setuid_safe") == 0 ) {
2682 else if ( strcmp(arg
, "-alias") == 0 ) {
2683 Options::AliasPair pair
;
2684 pair
.realName
= argv
[++i
];
2685 if ( pair
.realName
== NULL
)
2686 throw "missing argument to -alias";
2687 pair
.alias
= argv
[++i
];
2688 if ( pair
.alias
== NULL
)
2689 throw "missing argument to -alias";
2690 fAliases
.push_back(pair
);
2692 else if ( strcmp(arg
, "-alias_list") == 0 ) {
2693 snapshotFileArgIndex
= 1;
2694 parseAliasFile(argv
[++i
]);
2696 else if ( strcmp(arg
, "-save-temps") == 0 ) {
2697 fSaveTempFiles
= true;
2699 else if ( strcmp(arg
, "-rpath") == 0 ) {
2700 const char* path
= argv
[++i
];
2702 throw "missing argument to -rpath";
2703 fRPaths
.push_back(path
);
2705 else if ( strcmp(arg
, "-read_only_stubs") == 0 ) {
2706 fReadOnlyx86Stubs
= true;
2708 else if ( strcmp(arg
, "-slow_stubs") == 0 ) {
2711 else if ( strcmp(arg
, "-map") == 0 ) {
2712 fMapPath
= argv
[++i
];
2713 if ( fMapPath
== NULL
)
2714 throw "missing argument to -map";
2716 else if ( strcmp(arg
, "-pie") == 0 ) {
2717 fPositionIndependentExecutable
= true;
2718 fPIEOnCommandLine
= true;
2720 else if ( strcmp(arg
, "-no_pie") == 0 ) {
2721 fDisablePositionIndependentExecutable
= true;
2723 else if ( strncmp(arg
, "-reexport-l", 11) == 0 ) {
2724 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2725 snapshotArgCount
= 0;
2726 FileInfo info
= findLibrary(&arg
[11], true);
2727 info
.options
.fReExport
= true;
2728 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2731 else if ( strcmp(arg
, "-reexport_library") == 0 ) {
2732 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2733 snapshotArgCount
= 0;
2734 FileInfo info
= findFile(argv
[++i
]);
2735 info
.options
.fReExport
= true;
2736 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2739 else if ( strcmp(arg
, "-reexport_framework") == 0 ) {
2740 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2741 snapshotArgCount
= 0;
2742 FileInfo info
= findFramework(argv
[++i
]);
2743 info
.options
.fReExport
= true;
2744 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2747 else if ( strncmp(arg
, "-upward-l", 9) == 0 ) {
2748 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2749 snapshotArgCount
= 0;
2750 FileInfo info
= findLibrary(&arg
[9], true);
2751 info
.options
.fUpward
= true;
2752 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2755 else if ( strcmp(arg
, "-upward_library") == 0 ) {
2756 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2757 snapshotArgCount
= 0;
2758 FileInfo info
= findFile(argv
[++i
]);
2759 info
.options
.fUpward
= true;
2760 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2763 else if ( strcmp(arg
, "-upward_framework") == 0 ) {
2764 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2765 snapshotArgCount
= 0;
2766 FileInfo info
= findFramework(argv
[++i
]);
2767 info
.options
.fUpward
= true;
2768 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2771 else if ( strcmp(arg
, "-dead_strip_dylibs") == 0 ) {
2772 fDeadStripDylibs
= true;
2774 else if ( strcmp(arg
, "-no_implicit_dylibs") == 0 ) {
2775 fImplicitlyLinkPublicDylibs
= false;
2777 else if ( strcmp(arg
, "-new_linker") == 0 ) {
2780 else if ( strcmp(arg
, "-no_encryption") == 0 ) {
2781 fEncryptable
= false;
2783 else if ( strcmp(arg
, "-no_compact_unwind") == 0 ) {
2784 fAddCompactUnwindEncoding
= false;
2786 else if ( strcmp(arg
, "-mllvm") == 0 ) {
2787 const char* opts
= argv
[++i
];
2789 throw "missing argument to -mllvm";
2790 fLLVMOptions
.push_back(opts
);
2792 else if ( strcmp(arg
, "-mcpu") == 0 ) {
2793 const char* cpu
= argv
[++i
];
2795 throw "missing argument to -mcpu";
2798 else if ( strcmp(arg
, "-no_order_inits") == 0 ) {
2799 fAutoOrderInitializers
= false;
2801 else if ( strcmp(arg
, "-no_order_data") == 0 ) {
2804 else if ( strcmp(arg
, "-seg_page_size") == 0 ) {
2806 seg
.name
= argv
[++i
];
2807 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2808 throw "-seg_page_size missing segName Adddress";
2809 seg
.size
= parseAddress(argv
[++i
]);
2810 uint64_t temp
= seg
.size
& (-4096); // page align
2811 if ( (seg
.size
!= temp
) )
2812 warning("-seg_page_size %s not 4K aligned, rounding down", seg
.name
);
2813 fCustomSegmentSizes
.push_back(seg
);
2815 else if ( strcmp(arg
, "-mark_dead_strippable_dylib") == 0 ) {
2816 fMarkDeadStrippableDylib
= true;
2818 else if ( strcmp(arg
, "-exported_symbols_order") == 0 ) {
2819 snapshotFileArgIndex
= 1;
2820 loadSymbolOrderFile(argv
[++i
], fExportSymbolsOrder
);
2822 else if ( strcmp(arg
, "-no_compact_linkedit") == 0 ) {
2823 warnObsolete("-no_compact_linkedit");
2825 else if ( strcmp(arg
, "-no_eh_labels") == 0 ) {
2828 else if ( strcmp(arg
, "-warn_compact_unwind") == 0 ) {
2829 fWarnCompactUnwind
= true;
2831 else if ( strcmp(arg
, "-allow_sub_type_mismatches") == 0 ) {
2832 fAllowCpuSubtypeMismatches
= true;
2834 else if ( strcmp(arg
, "-no_zero_fill_sections") == 0 ) {
2835 fOptimizeZeroFill
= false;
2837 else if ( strcmp(arg
, "-merge_zero_fill_sections") == 0 ) {
2838 fMergeZeroFill
= true;
2840 else if ( strcmp(arg
, "-objc_abi_version") == 0 ) {
2841 const char* version
= argv
[++i
];
2842 if ( version
== NULL
)
2843 throw "-objc_abi_version missing version number";
2844 if ( strcmp(version
, "2") == 0 ) {
2845 fObjCABIVersion1Override
= false;
2846 fObjCABIVersion2Override
= true;
2848 else if ( strcmp(version
, "1") == 0 ) {
2849 fObjCABIVersion1Override
= true;
2850 fObjCABIVersion2Override
= false;
2853 warning("ignoring unrecognized argument (%s) to -objc_abi_version", version
);
2855 else if ( strcmp(arg
, "-warn_weak_exports") == 0 ) {
2856 fWarnWeakExports
= true;
2858 else if ( strcmp(arg
, "-objc_gc_compaction") == 0 ) {
2859 fObjcGcCompaction
= true;
2861 else if ( strcmp(arg
, "-objc_gc") == 0 ) {
2863 if ( fObjCGcOnly
) {
2864 warning("-objc_gc overriding -objc_gc_only");
2865 fObjCGcOnly
= false;
2868 else if ( strcmp(arg
, "-objc_gc_only") == 0 ) {
2871 warning("-objc_gc_only overriding -objc_gc");
2875 else if ( strcmp(arg
, "-demangle") == 0 ) {
2878 else if ( strcmp(arg
, "-version_load_command") == 0 ) {
2879 fVersionLoadCommandForcedOn
= true;
2880 fVersionLoadCommandForcedOff
= false;
2882 else if ( strcmp(arg
, "-no_version_load_command") == 0 ) {
2883 fVersionLoadCommandForcedOff
= true;
2884 fVersionLoadCommandForcedOn
= false;
2886 else if ( strcmp(arg
, "-function_starts") == 0 ) {
2887 fFunctionStartsForcedOn
= true;
2888 fFunctionStartsForcedOff
= false;
2890 else if ( strcmp(arg
, "-no_function_starts") == 0 ) {
2891 fFunctionStartsForcedOff
= true;
2892 fFunctionStartsForcedOn
= false;
2894 else if ( strcmp(arg
, "-no_data_in_code_info") == 0 ) {
2895 fDataInCodeInfoLoadCommandForcedOff
= true;
2896 fDataInCodeInfoLoadCommandForcedOn
= false;
2898 else if ( strcmp(arg
, "-data_in_code_info") == 0 ) {
2899 fDataInCodeInfoLoadCommandForcedOn
= true;
2900 fDataInCodeInfoLoadCommandForcedOff
= false;
2902 else if ( strcmp(arg
, "-object_path_lto") == 0 ) {
2903 fTempLtoObjectPath
= argv
[++i
];
2904 if ( fTempLtoObjectPath
== NULL
)
2905 throw "missing argument to -object_path_lto";
2907 else if ( strcmp(arg
, "-no_objc_category_merging") == 0 ) {
2908 fObjcCategoryMerging
= false;
2910 else if ( strcmp(arg
, "-force_symbols_weak_list") == 0 ) {
2911 snapshotFileArgIndex
= 1;
2912 loadExportFile(argv
[++i
], "-force_symbols_weak_list", fForceWeakSymbols
);
2914 else if ( strcmp(arg
, "-force_symbols_not_weak_list") == 0 ) {
2915 snapshotFileArgIndex
= 1;
2916 loadExportFile(argv
[++i
], "-force_symbols_not_weak_list", fForceNotWeakSymbols
);
2918 else if ( strcmp(arg
, "-force_symbol_weak") == 0 ) {
2919 const char* symbol
= argv
[++i
];
2920 if ( symbol
== NULL
)
2921 throw "-force_symbol_weak missing <symbol>";
2922 fForceWeakSymbols
.insert(symbol
);
2924 else if ( strcmp(arg
, "-force_symbol_not_weak") == 0 ) {
2925 const char* symbol
= argv
[++i
];
2926 if ( symbol
== NULL
)
2927 throw "-force_symbol_not_weak missing <symbol>";
2928 fForceNotWeakSymbols
.insert(symbol
);
2930 else if ( strcmp(arg
, "-reexported_symbols_list") == 0 ) {
2931 snapshotFileArgIndex
= 1;
2932 if ( fExportMode
== kExportSome
)
2933 throw "can't use -exported_symbols_list and -reexported_symbols_list";
2934 loadExportFile(argv
[++i
], "-reexported_symbols_list", fReExportSymbols
);
2936 else if ( strcmp(arg
, "-dyld_env") == 0 ) {
2937 const char* envarg
= argv
[++i
];
2938 if ( envarg
== NULL
)
2939 throw "-dyld_env missing ENV=VALUE";
2940 if ( strchr(envarg
, '=') == NULL
)
2941 throw "-dyld_env missing ENV=VALUE";
2942 fDyldEnvironExtras
.push_back(envarg
);
2944 else if ( strcmp(arg
, "-page_align_data_atoms") == 0 ) {
2945 fPageAlignDataAtoms
= true;
2947 else if (strcmp(arg
, "-debug_snapshot") == 0) {
2948 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
2949 fSnapshotRequested
= true;
2951 else if (strcmp(arg
, "-snapshot_dir") == 0) {
2952 const char* path
= argv
[++i
];
2954 throw "-snapshot_dir missing path";
2955 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
2956 fLinkSnapshot
.setSnapshotPath(path
);
2957 fSnapshotRequested
= true;
2959 else if ( strcmp(arg
, "-new_main") == 0 ) {
2960 fEntryPointLoadCommandForceOn
= true;
2962 else if ( strcmp(arg
, "-no_new_main") == 0 ) {
2963 fEntryPointLoadCommandForceOff
= true;
2965 else if ( strcmp(arg
, "-source_version") == 0 ) {
2966 const char* vers
= argv
[++i
];
2968 throw "-source_version missing <version>";
2969 fSourceVersion
= parseVersionNumber64(vers
);
2971 else if ( strcmp(arg
, "-add_source_version") == 0 ) {
2972 fSourceVersionLoadCommandForceOn
= true;
2974 else if ( strcmp(arg
, "-no_source_version") == 0 ) {
2975 fSourceVersionLoadCommandForceOff
= true;
2977 else if ( strcmp(arg
, "-sdk_version") == 0 ) {
2978 const char* vers
= argv
[++i
];
2980 throw "-sdk_version missing <version>";
2981 fSDKVersion
= parseVersionNumber32(vers
);
2983 else if ( strcmp(arg
, "-dependent_dr_info") == 0 ) {
2984 fDependentDRInfoForcedOn
= true;
2986 else if ( strcmp(arg
, "-no_dependent_dr_info") == 0 ) {
2987 fDependentDRInfoForcedOff
= true;
2989 else if ( strcmp(arg
, "-kexts_use_stubs") == 0 ) {
2990 fKextsUseStubs
= true;
2992 else if ( strcmp(argv
[i
], "-dependency_info") == 0 ) {
2993 snapshotArgCount
= 0;
2995 // previously handled by buildSearchPaths()
2997 else if ( strcmp(arg
, "-export_dynamic") == 0 ) {
2998 fExportDynamic
= true;
3000 else if ( strcmp(arg
, "-force_symbols_coalesce_list") == 0 ) {
3001 snapshotFileArgIndex
= 1;
3002 loadExportFile(argv
[++i
], "-force_symbols_coalesce_list", fForceCoalesceSymbols
);
3004 else if ( strcmp(arg
, "-add_linker_option") == 0 ) {
3005 // ex: -add_linker_option '-framework Foundation'
3006 const char* optString
= argv
[++i
];
3007 if ( optString
== NULL
)
3008 throw "-add_linker_option missing <option>";
3009 // break up into list of tokens at whitespace
3010 std::vector
<const char*> opts
;
3011 char* buffer
= strdup(optString
);
3012 char* start
= buffer
;
3013 for (char* s
= buffer
; ; ++s
) {
3014 if ( isspace(*s
) ) {
3016 opts
.push_back(start
);
3019 else if ( *s
== '\0' ) {
3020 opts
.push_back(start
);
3024 fLinkerOptions
.push_back(opts
);
3026 else if ( strcmp(arg
, "-allow_simulator_linking_to_macosx_dylibs") == 0 ) {
3027 fAllowSimulatorToLinkWithMacOSX
= true;
3029 else if ( strcmp(arg
, "-keep_dwarf_unwind") == 0 ) {
3030 fKeepDwarfUnwindForcedOn
= true;
3031 fKeepDwarfUnwindForcedOff
= false;
3033 else if ( strcmp(arg
, "-no_keep_dwarf_unwind") == 0 ) {
3034 fKeepDwarfUnwindForcedOn
= false;
3035 fKeepDwarfUnwindForcedOff
= true;
3037 else if ( strcmp(arg
, "-verbose_optimization_hints") == 0 ) {
3038 fVerboseOptimizationHints
= true;
3040 else if ( strcmp(arg
, "-ignore_optimization_hints") == 0 ) {
3041 fIgnoreOptimizationHints
= true;
3043 else if ( strcmp(arg
, "-no_dtrace_dof") == 0 ) {
3044 fGenerateDtraceDOF
= false;
3046 else if ( strcmp(arg
, "-rename_section") == 0 ) {
3047 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) || (argv
[i
+4]==NULL
) )
3048 throw "-rename_section missing <segment> <section> <segment> <section>";
3049 addSectionRename(argv
[i
+1], argv
[i
+2], argv
[i
+3], argv
[i
+4]);
3052 else if ( strcmp(arg
, "-rename_segment") == 0 ) {
3053 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3054 throw "-rename_segment missing <existing-segment> <new-segment>";
3055 addSegmentRename(argv
[i
+1], argv
[i
+2]);
3058 else if ( strcmp(arg
, "-move_to_ro_segment") == 0 ) {
3059 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3060 throw "-move_to_ro_segment missing <segment> <symbol-list-file>";
3061 addSymbolMove(argv
[i
+1], argv
[i
+2], fSymbolsMovesCode
, "-move_to_ro_segment");
3064 else if ( strcmp(arg
, "-move_to_rw_segment") == 0 ) {
3065 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3066 throw "-move_to_rw_segment missing <segment> <symbol-list-file>";
3067 addSymbolMove(argv
[i
+1], argv
[i
+2], fSymbolsMovesData
, "-move_to_rw_segment");
3070 else if ( strcmp(arg
, "-trace_symbol_layout") == 0 ) {
3071 fTraceSymbolLayout
= true;
3073 else if ( strcmp(arg
, "-no_branch_islands") == 0 ) {
3074 fAllowBranchIslands
= false;
3076 else if ( strcmp(arg
, "-segment_order") == 0 ) {
3077 // ex: -segment_order __TEXT:__DATA:__JUNK
3078 const char* optString
= argv
[++i
];
3079 if ( optString
== NULL
)
3080 throw "-segment_order missing colon separated <segment-list>";
3081 if ( !fSegmentOrder
.empty() )
3082 throw "-segment_order used more than once";
3083 // break up into list of tokens at colon
3084 char* buffer
= strdup(optString
);
3085 char* start
= buffer
;
3086 for (char* s
= buffer
; ; ++s
) {
3089 fSegmentOrder
.push_back(start
);
3092 else if ( *s
== '\0' ) {
3093 fSegmentOrder
.push_back(start
);
3098 else if ( strcmp(arg
, "-section_order") == 0 ) {
3099 // ex: -section_order __DATA __data:__const:__nl_pointers
3100 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3101 throw "-section_order missing <segment> <section-list>";
3102 const char* segName
= argv
[++i
];
3103 const char* optString
= argv
[++i
];
3104 if ( sectionOrder(segName
) != NULL
)
3105 throwf("-section_order %s ... used more than once", segName
);
3106 SectionOrderList dummy
;
3107 fSectionOrder
.push_back(dummy
);
3108 SectionOrderList
& entry
= fSectionOrder
.back();
3109 entry
.segmentName
= segName
;
3110 // break up into list of tokens at colon
3111 char* buffer
= strdup(optString
);
3112 char* start
= buffer
;
3113 for (char* s
= buffer
; ; ++s
) {
3116 entry
.sectionOrder
.push_back(start
);
3119 else if ( *s
== '\0' ) {
3120 entry
.sectionOrder
.push_back(start
);
3125 else if ( strcmp(arg
, "-application_extension") == 0 ) {
3126 fMarkAppExtensionSafe
= true;
3127 fCheckAppExtensionSafe
= true;
3129 else if ( strcmp(arg
, "-no_application_extension") == 0 ) {
3130 fMarkAppExtensionSafe
= false;
3131 fCheckAppExtensionSafe
= false;
3133 else if ( strcmp(arg
, "-add_ast_path") == 0 ) {
3134 const char* path
= argv
[++i
];
3136 throw "-add_ast_path missing <option>";
3137 fASTFilePaths
.push_back(path
);
3139 else if ( strcmp(arg
, "-force_load_swift_libs") == 0 ) {
3140 fForceLoadSwiftLibs
= true;
3142 // put this last so that it does not interfer with other options starting with 'i'
3143 else if ( strncmp(arg
, "-i", 2) == 0 ) {
3144 const char* colon
= strchr(arg
, ':');
3145 if ( colon
== NULL
)
3146 throwf("unknown option: %s", arg
);
3147 Options::AliasPair pair
;
3148 char* temp
= new char[colon
-arg
];
3149 strlcpy(temp
, &arg
[2], colon
-arg
-1);
3150 pair
.realName
= &colon
[1];
3152 fAliases
.push_back(pair
);
3155 throwf("unknown option: %s", arg
);
3158 if (snapshotArgCount
== -1)
3159 snapshotArgCount
= i
-snapshotArgIndex
+1;
3160 if (snapshotArgCount
> 0)
3161 fLinkSnapshot
.addSnapshotLinkArg(snapshotArgIndex
, snapshotArgCount
, snapshotFileArgIndex
);
3164 FileInfo info
= findFile(arg
);
3165 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3166 if ( strcmp(&info
.path
[strlen(info
.path
)-2], ".a") == 0 )
3169 fInputFiles
.push_back(info
);
3173 // if a -lazy option was used, implicitly link in lazydylib1.o
3174 if ( fUsingLazyDylibLinking
) {
3175 FileInfo info
= findLibrary("lazydylib1.o");
3176 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)argc
);
3180 if (fSnapshotRequested
)
3181 fLinkSnapshot
.createSnapshot();
3187 // -syslibroot <path> is used for SDK support.
3188 // The rule is that all search paths (both explicit and default) are
3189 // checked to see if they exist in the SDK. If so, that path is
3190 // replaced with the sdk prefixed path. If not, that search path
3191 // is used as is. If multiple -syslibroot options are specified
3192 // their directory structures are logically overlayed and files
3193 // from sdks specified earlier on the command line used before later ones.
3195 void Options::buildSearchPaths(int argc
, const char* argv
[])
3197 bool addStandardLibraryDirectories
= true;
3198 std::vector
<const char*> libraryPaths
;
3199 std::vector
<const char*> frameworkPaths
;
3200 libraryPaths
.reserve(10);
3201 frameworkPaths
.reserve(10);
3202 // scan through argv looking for -L, -F, -Z, and -syslibroot options
3203 for(int i
=0; i
< argc
; ++i
) {
3204 if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'L') ) {
3205 const char* libSearchDir
= &argv
[i
][2];
3206 // Allow either "-L{path}" or "-L {path}".
3207 if (argv
[i
][2] == '\0') {
3208 // -L {path}. Make sure there is an argument following this.
3209 const char* path
= argv
[++i
];
3211 throw "-L missing argument";
3212 libSearchDir
= path
;
3214 if ( libSearchDir
[0] == '\0' )
3215 throw "-L must be immediately followed by a directory path (no space)";
3216 struct stat statbuf
;
3217 if ( stat(libSearchDir
, &statbuf
) == 0 ) {
3218 if ( statbuf
.st_mode
& S_IFDIR
)
3219 libraryPaths
.push_back(libSearchDir
);
3221 warning("path '%s' following -L not a directory", libSearchDir
);
3224 warning("directory not found for option '-L%s'", libSearchDir
);
3227 else if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'F') ) {
3228 const char* frameworkSearchDir
= &argv
[i
][2];
3229 // Allow either "-F{path}" or "-F {path}".
3230 if (argv
[i
][2] == '\0') {
3231 // -F {path}. Make sure there is an argument following this.
3232 const char* path
= argv
[++i
];
3234 throw "-F missing argument";
3235 frameworkSearchDir
= path
;
3237 if ( frameworkSearchDir
[0] == '\0' )
3238 throw "-F must be immediately followed by a directory path (no space)";
3239 struct stat statbuf
;
3240 if ( stat(frameworkSearchDir
, &statbuf
) == 0 ) {
3241 if ( statbuf
.st_mode
& S_IFDIR
)
3242 frameworkPaths
.push_back(frameworkSearchDir
);
3244 warning("path '%s' following -F not a directory", frameworkSearchDir
);
3247 warning("directory not found for option '-F%s'", frameworkSearchDir
);
3250 else if ( strcmp(argv
[i
], "-Z") == 0 )
3251 addStandardLibraryDirectories
= false;
3252 else if ( strcmp(argv
[i
], "-v") == 0 ) {
3254 extern const char ldVersionString
[];
3255 fprintf(stderr
, "%s", ldVersionString
);
3256 fprintf(stderr
, "configured to support archs: %s\n", ALL_SUPPORTED_ARCHS
);
3257 // if only -v specified, exit cleanly
3259 const char* ltoVers
= lto::version();
3260 if ( ltoVers
!= NULL
)
3261 fprintf(stderr
, "LTO support using: %s\n", ltoVers
);
3265 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
3266 const char* path
= argv
[++i
];
3268 throw "-syslibroot missing argument";
3269 fSDKPaths
.push_back(path
);
3271 else if ( strcmp(argv
[i
], "-search_paths_first") == 0 ) {
3272 fLibrarySearchMode
= kSearchDylibAndArchiveInEachDir
;
3274 else if ( strcmp(argv
[i
], "-search_dylibs_first") == 0 ) {
3275 fLibrarySearchMode
= kSearchAllDirsForDylibsThenAllDirsForArchives
;
3277 else if ( strcmp(argv
[i
], "-w") == 0 ) {
3278 sEmitWarnings
= false;
3280 else if ( strcmp(argv
[i
], "-fatal_warnings") == 0 ) {
3281 sFatalWarnings
= true;
3283 else if ( strcmp(argv
[i
], "-dependency_info") == 0 ) {
3284 const char* path
= argv
[++i
];
3286 throw "-dependency_info missing <path>";
3287 fDependencyInfoPath
= path
;
3290 int standardLibraryPathsStartIndex
= libraryPaths
.size();
3291 int standardFrameworkPathsStartIndex
= frameworkPaths
.size();
3292 if ( addStandardLibraryDirectories
) {
3293 libraryPaths
.push_back("/usr/lib");
3294 libraryPaths
.push_back("/usr/local/lib");
3296 frameworkPaths
.push_back("/Library/Frameworks/");
3297 frameworkPaths
.push_back("/System/Library/Frameworks/");
3298 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
3301 // <rdar://problem/5829579> Support for configure based hacks
3302 // if last -syslibroot is /, then ignore all syslibroots
3303 if ( fSDKPaths
.size() > 0 ) {
3304 if ( strcmp(fSDKPaths
.back(), "/") == 0 ) {
3309 // now merge sdk and library paths to make real search paths
3310 fLibrarySearchPaths
.reserve(libraryPaths
.size()*(fSDKPaths
.size()+1));
3312 for (std::vector
<const char*>::iterator it
= libraryPaths
.begin(); it
!= libraryPaths
.end(); ++it
, ++libIndex
) {
3313 const char* libDir
= *it
;
3314 bool sdkOverride
= false;
3315 if ( libDir
[0] == '/' ) {
3316 char betterLibDir
[PATH_MAX
];
3317 if ( strstr(libDir
, "/..") != NULL
) {
3318 if ( realpath(libDir
, betterLibDir
) != NULL
)
3319 libDir
= strdup(betterLibDir
);
3321 const int libDirLen
= strlen(libDir
);
3322 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
3323 const char* sdkDir
= *sdkit
;
3324 const int sdkDirLen
= strlen(sdkDir
);
3325 char newPath
[libDirLen
+ sdkDirLen
+4];
3326 strcpy(newPath
, sdkDir
);
3327 if ( newPath
[sdkDirLen
-1] == '/' )
3328 newPath
[sdkDirLen
-1] = '\0';
3329 strcat(newPath
, libDir
);
3330 struct stat statBuffer
;
3331 if ( stat(newPath
, &statBuffer
) == 0 ) {
3332 fLibrarySearchPaths
.push_back(strdup(newPath
));
3337 if ( !sdkOverride
) {
3338 if ( (libIndex
>= standardLibraryPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
3339 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
3340 // if one SDK is specified and a standard library path is not in the SDK, don't use it
3343 fLibrarySearchPaths
.push_back(libDir
);
3348 // now merge sdk and framework paths to make real search paths
3349 fFrameworkSearchPaths
.reserve(frameworkPaths
.size()*(fSDKPaths
.size()+1));
3351 for (std::vector
<const char*>::iterator it
= frameworkPaths
.begin(); it
!= frameworkPaths
.end(); ++it
, ++frameIndex
) {
3352 const char* frameworkDir
= *it
;
3353 bool sdkOverride
= false;
3354 if ( frameworkDir
[0] == '/' ) {
3355 char betterFrameworkDir
[PATH_MAX
];
3356 if ( strstr(frameworkDir
, "/..") != NULL
) {
3357 if ( realpath(frameworkDir
, betterFrameworkDir
) != NULL
)
3358 frameworkDir
= strdup(betterFrameworkDir
);
3360 const int frameworkDirLen
= strlen(frameworkDir
);
3361 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
3362 const char* sdkDir
= *sdkit
;
3363 const int sdkDirLen
= strlen(sdkDir
);
3364 char newPath
[frameworkDirLen
+ sdkDirLen
+4];
3365 strcpy(newPath
, sdkDir
);
3366 if ( newPath
[sdkDirLen
-1] == '/' )
3367 newPath
[sdkDirLen
-1] = '\0';
3368 strcat(newPath
, frameworkDir
);
3369 struct stat statBuffer
;
3370 if ( stat(newPath
, &statBuffer
) == 0 ) {
3371 fFrameworkSearchPaths
.push_back(strdup(newPath
));
3376 if ( !sdkOverride
) {
3377 if ( (frameIndex
>= standardFrameworkPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
3378 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
3379 // if one SDK is specified and a standard library path is not in the SDK, don't use it
3382 fFrameworkSearchPaths
.push_back(frameworkDir
);
3388 fprintf(stderr
,"Library search paths:\n");
3389 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
3390 it
!= fLibrarySearchPaths
.end();
3392 fprintf(stderr
,"\t%s\n", *it
);
3393 fprintf(stderr
,"Framework search paths:\n");
3394 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
3395 it
!= fFrameworkSearchPaths
.end();
3397 fprintf(stderr
,"\t%s\n", *it
);
3401 // this is run before the command line is parsed
3402 void Options::parsePreCommandLineEnvironmentSettings()
3404 if ((getenv("LD_TRACE_ARCHIVES") != NULL
)
3405 || (getenv("RC_TRACE_ARCHIVES") != NULL
))
3406 fTraceArchives
= true;
3408 if ((getenv("LD_TRACE_DYLIBS") != NULL
)
3409 || (getenv("RC_TRACE_DYLIBS") != NULL
)) {
3410 fTraceDylibs
= true;
3411 fTraceIndirectDylibs
= true;
3414 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL
) {
3415 fTraceDylibSearching
= true;
3418 if (getenv("LD_PRINT_OPTIONS") != NULL
)
3419 fPrintOptions
= true;
3421 if (fTraceDylibs
|| fTraceArchives
)
3422 fTraceOutputFile
= getenv("LD_TRACE_FILE");
3424 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL
)
3425 fPrintOrderFileStatistics
= true;
3427 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL
)
3430 if (getenv("LD_NO_ENCRYPT") != NULL
) {
3431 fEncryptable
= false;
3432 fMarkAppExtensionSafe
= true; // temporary
3433 fCheckAppExtensionSafe
= false;
3436 if (getenv("LD_APPLICATION_EXTENSION_SAFE") != NULL
) {
3437 fMarkAppExtensionSafe
= true;
3438 fCheckAppExtensionSafe
= false;
3441 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL
)
3442 fAllowCpuSubtypeMismatches
= true;
3444 sWarningsSideFilePath
= getenv("LD_WARN_FILE");
3446 const char* customDyldPath
= getenv("LD_DYLD_PATH");
3447 if ( customDyldPath
!= NULL
)
3448 fDyldInstallPath
= customDyldPath
;
3450 const char* debugArchivePath
= getenv("LD_DEBUG_SNAPSHOT");
3451 if (debugArchivePath
!= NULL
) {
3452 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
3453 if (strlen(debugArchivePath
) > 0)
3454 fLinkSnapshot
.setSnapshotPath(debugArchivePath
);
3455 fSnapshotRequested
= true;
3458 const char* pipeFdString
= getenv("LD_PIPELINE_FIFO");
3459 if (pipeFdString
!= NULL
) {
3460 fPipelineFifo
= pipeFdString
;
3465 // this is run after the command line is parsed
3466 void Options::parsePostCommandLineEnvironmentSettings()
3468 // when building a dynamic main executable, default any use of @executable_path to output path
3469 if ( fExecutablePath
== NULL
&& (fOutputKind
== kDynamicExecutable
) ) {
3470 fExecutablePath
= fOutputFile
;
3473 // allow build system to set default seg_addr_table
3474 if ( fSegAddrTablePath
== NULL
)
3475 fSegAddrTablePath
= getenv("LD_SEG_ADDR_TABLE");
3477 // allow build system to turn on prebinding
3479 fPrebind
= ( getenv("LD_PREBIND") != NULL
);
3482 // allow build system to force on dead-code-stripping
3483 if ( !fDeadStrip
) {
3484 if ( getenv("LD_DEAD_STRIP") != NULL
) {
3485 switch (fOutputKind
) {
3486 case Options::kDynamicLibrary
:
3487 case Options::kDynamicExecutable
:
3488 case Options::kDynamicBundle
:
3491 case Options::kPreload
:
3492 case Options::kObjectFile
:
3493 case Options::kDyld
:
3494 case Options::kStaticExecutable
:
3495 case Options::kKextBundle
:
3501 // allow build system to force on -warn_commons
3502 if ( getenv("LD_WARN_COMMONS") != NULL
)
3503 fWarnCommons
= true;
3505 // allow B&I to set default -source_version
3506 if ( fSourceVersion
== 0 ) {
3507 const char* vers
= getenv("RC_ProjectSourceVersion");
3509 fSourceVersion
= parseVersionNumber64(vers
);
3514 void Options::reconfigureDefaults()
3516 // sync reader options
3517 switch ( fOutputKind
) {
3518 case Options::kObjectFile
:
3519 fForFinalLinkedImage
= false;
3521 case Options::kDyld
:
3523 fForFinalLinkedImage
= true;
3526 case Options::kDynamicLibrary
:
3527 case Options::kDynamicBundle
:
3528 case Options::kKextBundle
:
3529 fForFinalLinkedImage
= true;
3532 case Options::kDynamicExecutable
:
3533 case Options::kStaticExecutable
:
3534 case Options::kPreload
:
3535 fLinkingMainExecutable
= true;
3536 fForFinalLinkedImage
= true;
3541 // set default min OS version
3542 if ( (fMacVersionMin
== ld::macVersionUnset
)
3543 && (fIOSVersionMin
== ld::iOSVersionUnset
) ) {
3544 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
3545 const char* macVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
3546 const char* iPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
3547 const char* iOSVers
= getenv("IOS_DEPLOYMENT_TARGET");
3548 const char* iOSSimulatorVers
= getenv("IOS_SIMULATOR_DEPLOYMENT_TARGET");
3549 if ( macVers
!= NULL
)
3550 setMacOSXVersionMin(macVers
);
3551 else if ( iPhoneVers
!= NULL
)
3552 setIOSVersionMin(iPhoneVers
);
3553 else if ( iOSVers
!= NULL
)
3554 setIOSVersionMin(iOSVers
);
3555 else if ( iOSSimulatorVers
!= NULL
)
3556 setIOSVersionMin(iOSSimulatorVers
);
3558 // if still nothing, set default based on architecture
3559 switch ( fArchitecture
) {
3561 case CPU_TYPE_X86_64
:
3562 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
3563 #ifdef DEFAULT_MACOSX_MIN_VERSION
3564 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION
);
3565 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
3567 warning("-macosx_version_min not specified, assuming 10.6");
3568 fMacVersionMin
= ld::mac10_6
;
3573 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
3574 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
3575 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION
);
3576 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION
);
3578 warning("-ios_version_min not specified, assuming 6.0");
3579 setIOSVersionMin("6.0");
3584 // architecture will be infered later by examining .o files
3591 // adjust min based on architecture
3592 switch ( fArchitecture
) {
3594 if ( (fMacVersionMin
< ld::mac10_4
) && (fIOSVersionMin
== ld::iOSVersionUnset
) ) {
3595 //warning("-macosx_version_min should be 10.4 or later for i386");
3596 fMacVersionMin
= ld::mac10_4
;
3599 case CPU_TYPE_X86_64
:
3600 if ( (fMacVersionMin
< ld::mac10_4
) && (fIOSVersionMin
== ld::iOSVersionUnset
) ) {
3601 //warning("-macosx_version_min should be 10.4 or later for x86_64");
3602 fMacVersionMin
= ld::mac10_4
;
3605 case CPU_TYPE_ARM64
:
3606 if ( fIOSVersionMin
< ld::iOS_7_0
) {
3607 //warning("-mios_version_min should be 7.0 or later for arm64");
3608 fIOSVersionMin
= ld::iOS_7_0
;
3613 // default to adding functions start for dynamic code, static code must opt-in
3614 switch ( fOutputKind
) {
3615 case Options::kPreload
:
3616 case Options::kStaticExecutable
:
3617 case Options::kKextBundle
:
3618 if ( fDataInCodeInfoLoadCommandForcedOn
)
3619 fDataInCodeInfoLoadCommand
= true;
3620 if ( fFunctionStartsForcedOn
)
3621 fFunctionStartsLoadCommand
= true;
3623 case Options::kObjectFile
:
3624 if ( !fDataInCodeInfoLoadCommandForcedOff
)
3625 fDataInCodeInfoLoadCommand
= true;
3626 if ( fFunctionStartsForcedOn
)
3627 fFunctionStartsLoadCommand
= true;
3629 case Options::kDynamicExecutable
:
3630 case Options::kDyld
:
3631 case Options::kDynamicLibrary
:
3632 case Options::kDynamicBundle
:
3633 if ( !fDataInCodeInfoLoadCommandForcedOff
)
3634 fDataInCodeInfoLoadCommand
= true;
3635 if ( !fFunctionStartsForcedOff
)
3636 fFunctionStartsLoadCommand
= true;
3640 // adjust kext type based on architecture
3641 if ( fOutputKind
== kKextBundle
) {
3642 switch ( fArchitecture
) {
3643 case CPU_TYPE_X86_64
:
3644 // x86_64 uses new MH_KEXT_BUNDLE type
3645 fMakeCompressedDyldInfo
= false;
3646 fMakeCompressedDyldInfoForceOff
= true;
3647 fAllowTextRelocs
= true;
3648 fUndefinedTreatment
= kUndefinedDynamicLookup
;
3650 case CPU_TYPE_ARM64
:
3651 // arm64 uses new MH_KEXT_BUNDLE type
3652 fMakeCompressedDyldInfo
= false;
3653 fMakeCompressedDyldInfoForceOff
= true;
3654 fAllowTextRelocs
= false;
3655 fKextsUseStubs
= true;
3656 fUndefinedTreatment
= kUndefinedDynamicLookup
;
3659 if ( fIOSVersionMin
>= ld::iOS_5_0
) {
3660 // iOS 5.0 and later use new MH_KEXT_BUNDLE type
3661 fMakeCompressedDyldInfo
= false;
3662 fMakeCompressedDyldInfoForceOff
= true;
3663 // kexts are PIC in iOS 6.0 and later
3664 fAllowTextRelocs
= (fIOSVersionMin
< ld::iOS_6_0
);
3665 fKextsUseStubs
= !fAllowTextRelocs
;
3666 fUndefinedTreatment
= kUndefinedDynamicLookup
;
3669 // else use object file
3672 fOutputKind
= kObjectFile
;
3677 // disable implicit dylibs when targeting 10.3
3678 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
3679 if ( !minOS(ld::mac10_4
, ld::iOS_2_0
) )
3680 fImplicitlyLinkPublicDylibs
= false;
3683 // allow build system to force linker to ignore -prebind
3684 if ( getenv("LD_FORCE_NO_PREBIND") != NULL
)
3687 // allow build system to force linker to ignore -seg_addr_table
3688 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL
)
3689 fSegAddrTablePath
= NULL
;
3691 // check for base address specified externally
3692 if ( (fSegAddrTablePath
!= NULL
) && (fOutputKind
== Options::kDynamicLibrary
) ) {
3693 parseSegAddrTable(fSegAddrTablePath
, this->installPath());
3694 // HACK to support seg_addr_table entries that are physical paths instead of install paths
3695 if ( fBaseAddress
== 0 ) {
3696 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
3697 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.4.dylib");
3698 if ( fBaseAddress
== 0 )
3699 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.9.dylib");
3702 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
3703 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libz.1.2.3.dylib");
3705 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
3706 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libutil1.0.dylib");
3710 // split segs only allowed for dylibs
3712 // split seg only supported for i386, and arm.
3713 switch ( fArchitecture
) {
3715 if ( fOutputKind
!= Options::kDynamicLibrary
)
3717 // make sure read and write segments are proper distance apart
3718 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x10000000) )
3719 fBaseWritableAddress
= fBaseAddress
+ 0x10000000;
3722 if ( fOutputKind
!= Options::kDynamicLibrary
) {
3726 // make sure read and write segments are proper distance apart
3727 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x08000000) )
3728 fBaseWritableAddress
= fBaseAddress
+ 0x08000000;
3734 fBaseWritableAddress
= 0;
3738 // set too-large size
3739 switch ( fArchitecture
) {
3741 fMaxAddress
= 0xFFFFFFFF;
3743 case CPU_TYPE_X86_64
:
3746 switch ( fOutputKind
) {
3747 case Options::kDynamicExecutable
:
3748 case Options::kDynamicLibrary
:
3749 case Options::kDynamicBundle
:
3750 // user land code is limited to low 1GB
3751 fMaxAddress
= 0x2FFFFFFF;
3753 case Options::kStaticExecutable
:
3754 case Options::kObjectFile
:
3755 case Options::kDyld
:
3756 case Options::kPreload
:
3757 case Options::kKextBundle
:
3758 fMaxAddress
= 0xFFFFFFFF;
3761 // range check -seg1addr for ARM
3762 if ( fBaseAddress
> fMaxAddress
) {
3763 warning("ignoring -seg1addr 0x%08llX. Address out of range.", fBaseAddress
);
3769 // <rdar://problem/6138961> -r implies no prebinding for all architectures
3770 if ( fOutputKind
== Options::kObjectFile
)
3773 // disable prebinding depending on arch and min OS version
3775 switch ( fArchitecture
) {
3777 if ( fMacVersionMin
== ld::mac10_4
) {
3778 // in 10.4 only split seg dylibs are prebound
3779 if ( (fOutputKind
!= Options::kDynamicLibrary
) || ! fSplitSegs
)
3782 else if ( fMacVersionMin
>= ld::mac10_5
) {
3783 // in 10.5 nothing is prebound
3786 else if ( fIOSVersionMin
!= ld::iOSVersionUnset
) {
3787 // nothing in simulator is prebound
3791 // in 10.3 and earlier only dylibs and main executables could be prebound
3792 switch ( fOutputKind
) {
3793 case Options::kDynamicExecutable
:
3794 case Options::kDynamicLibrary
:
3795 // only main executables and dylibs can be prebound
3797 case Options::kStaticExecutable
:
3798 case Options::kDynamicBundle
:
3799 case Options::kObjectFile
:
3800 case Options::kDyld
:
3801 case Options::kPreload
:
3802 case Options::kKextBundle
:
3803 // disable prebinding for everything else
3809 case CPU_TYPE_X86_64
:
3813 switch ( fOutputKind
) {
3814 case Options::kDynamicExecutable
:
3815 case Options::kDynamicLibrary
:
3816 // only main executables and dylibs can be prebound
3818 case Options::kStaticExecutable
:
3819 case Options::kDynamicBundle
:
3820 case Options::kObjectFile
:
3821 case Options::kDyld
:
3822 case Options::kPreload
:
3823 case Options::kKextBundle
:
3824 // disable prebinding for everything else
3832 // only prebound images can be split-seg
3833 if ( fSplitSegs
&& !fPrebind
)
3836 // determine if info for shared region should be added
3837 if ( fOutputKind
== Options::kDynamicLibrary
) {
3838 if ( minOS(ld::mac10_5
, ld::iOS_3_1
) )
3840 if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
3841 || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
3842 fSharedRegionEligible
= true;
3844 else if ( fOutputKind
== Options::kDyld
) {
3845 // <rdar://problem/10111122> Enable dyld to be put into the dyld shared cache
3846 fSharedRegionEligible
= true;
3849 // figure out if module table is needed for compatibility with old ld/dyld
3850 if ( fOutputKind
== Options::kDynamicLibrary
) {
3851 switch ( fArchitecture
) {
3853 if ( fIOSVersionMin
!= ld::iOSVersionUnset
) // simulator never needs modules
3857 fNeedsModuleTable
= true; // redo_prebinding requires a module table
3862 // <rdar://problem/5366363> -r -x implies -S
3863 if ( (fOutputKind
== Options::kObjectFile
) && (fLocalSymbolHandling
== kLocalSymbolsNone
) )
3864 fDebugInfoStripping
= Options::kDebugInfoNone
;
3866 // <rdar://problem/15252891> -r implies -no_uuid
3867 if ( fOutputKind
== Options::kObjectFile
)
3868 fUUIDMode
= kUUIDNone
;
3870 // choose how to process unwind info
3871 switch ( fArchitecture
) {
3873 case CPU_TYPE_X86_64
:
3874 case CPU_TYPE_ARM64
:
3875 switch ( fOutputKind
) {
3876 case Options::kObjectFile
:
3877 case Options::kStaticExecutable
:
3878 case Options::kPreload
:
3879 case Options::kKextBundle
:
3880 fAddCompactUnwindEncoding
= false;
3882 case Options::kDyld
:
3883 case Options::kDynamicLibrary
:
3884 case Options::kDynamicBundle
:
3885 case Options::kDynamicExecutable
:
3886 //if ( fAddCompactUnwindEncoding && (fVersionMin >= ld::mac10_6) )
3887 // fRemoveDwarfUnwindIfCompactExists = true;
3892 fAddCompactUnwindEncoding
= false;
3893 fRemoveDwarfUnwindIfCompactExists
= false;
3896 // if -arch is missing, assume we don't want compact unwind info
3897 fAddCompactUnwindEncoding
= false;
3901 // only iOS executables should be encryptable
3902 switch ( fOutputKind
) {
3903 case Options::kObjectFile
:
3904 case Options::kDyld
:
3905 case Options::kStaticExecutable
:
3906 case Options::kPreload
:
3907 case Options::kKextBundle
:
3908 fEncryptable
= false;
3910 case Options::kDynamicExecutable
:
3912 case Options::kDynamicLibrary
:
3913 case Options::kDynamicBundle
:
3914 // <rdar://problem/16293398> Add LC_ENCRYPTION_INFO load command to bundled frameworks
3915 if ( fIOSVersionMin
< ld::iOS_8_0
)
3916 fEncryptable
= false;
3919 if ( (fArchitecture
!= CPU_TYPE_ARM
) && (fArchitecture
!= CPU_TYPE_ARM64
) )
3920 fEncryptable
= false;
3922 // don't move inits in dyld because dyld wants certain
3923 // entries point at stable locations at the start of __text
3924 if ( fOutputKind
== Options::kDyld
)
3925 fAutoOrderInitializers
= false;
3928 // disable __data ordering for some output kinds
3929 switch ( fOutputKind
) {
3930 case Options::kObjectFile
:
3931 case Options::kDyld
:
3932 case Options::kStaticExecutable
:
3933 case Options::kPreload
:
3934 case Options::kKextBundle
:
3937 case Options::kDynamicExecutable
:
3938 case Options::kDynamicLibrary
:
3939 case Options::kDynamicBundle
:
3943 // only use compressed LINKEDIT for final linked images
3944 switch ( fOutputKind
) {
3945 case Options::kDynamicExecutable
:
3946 case Options::kDynamicLibrary
:
3947 case Options::kDynamicBundle
:
3949 case Options::kPreload
:
3950 case Options::kStaticExecutable
:
3951 case Options::kObjectFile
:
3952 case Options::kDyld
:
3953 case Options::kKextBundle
:
3954 fMakeCompressedDyldInfoForceOff
= true;
3957 if ( fMakeCompressedDyldInfoForceOff
)
3958 fMakeCompressedDyldInfo
= false;
3961 // only use compressed LINKEDIT for:
3962 // Mac OS X 10.6 or later
3964 if ( fMakeCompressedDyldInfo
) {
3965 if ( !minOS(ld::mac10_6
, ld::iOS_3_1
) )
3966 fMakeCompressedDyldInfo
= false;
3969 // only ARM and x86_64 enforces that cpu-sub-types must match
3970 switch ( fArchitecture
) {
3972 case CPU_TYPE_X86_64
:
3975 case CPU_TYPE_ARM64
:
3976 fAllowCpuSubtypeMismatches
= true;
3981 // only final linked images can not optimize zero fill sections
3982 if ( fOutputKind
== Options::kObjectFile
)
3983 fOptimizeZeroFill
= true;
3985 // all undefines in -r mode
3986 // if ( fOutputKind == Options::kObjectFile )
3987 // fUndefinedTreatment = kUndefinedSuppress;
3989 // only dynamic final linked images should warn about use of commmons
3990 if ( fWarnCommons
) {
3991 switch ( fOutputKind
) {
3992 case Options::kDynamicExecutable
:
3993 case Options::kDynamicLibrary
:
3994 case Options::kDynamicBundle
:
3996 case Options::kPreload
:
3997 case Options::kStaticExecutable
:
3998 case Options::kObjectFile
:
3999 case Options::kDyld
:
4000 case Options::kKextBundle
:
4001 fWarnCommons
= false;
4006 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
4007 if ( minOS(ld::mac10_5
, ld::iOS_2_0
) )
4008 fUseSimplifiedDylibReExports
= true;
4010 // Mac OS X 10.7 and iOS 4.2 support LC_LOAD_UPWARD_DYLIB
4011 if ( minOS(ld::mac10_7
, ld::iOS_4_2
) && (fOutputKind
== kDynamicLibrary
) )
4012 fCanUseUpwardDylib
= true;
4014 // MacOSX 10.7 defaults to PIE
4015 if ( ((fArchitecture
== CPU_TYPE_X86_64
) || (fArchitecture
== CPU_TYPE_I386
))
4016 && (fOutputKind
== kDynamicExecutable
)
4017 && (fMacVersionMin
>= ld::mac10_7
) ) {
4018 fPositionIndependentExecutable
= true;
4021 // armv7 for iOS4.3 defaults to PIE
4022 if ( (fArchitecture
== CPU_TYPE_ARM
)
4023 && fArchSupportsThumb2
4024 && (fOutputKind
== kDynamicExecutable
)
4025 && (fIOSVersionMin
>= ld::iOS_4_3
) ) {
4026 fPositionIndependentExecutable
= true;
4029 // Simulator defaults to PIE
4030 if ( fTargetIOSSimulator
&& (fOutputKind
== kDynamicExecutable
) )
4031 fPositionIndependentExecutable
= true;
4033 // -no_pie anywhere on command line disable PIE
4034 if ( fDisablePositionIndependentExecutable
)
4035 fPositionIndependentExecutable
= false;
4037 // arm64 is always PIE
4038 if ( (fArchitecture
== CPU_TYPE_ARM64
) && (fOutputKind
== kDynamicExecutable
) ) {
4039 fPositionIndependentExecutable
= true;
4042 // set fOutputSlidable
4043 switch ( fOutputKind
) {
4044 case Options::kObjectFile
:
4045 fOutputSlidable
= false;
4047 case Options::kStaticExecutable
:
4048 case Options::kDynamicExecutable
:
4049 fOutputSlidable
= fPositionIndependentExecutable
;
4051 case Options::kPreload
:
4052 fOutputSlidable
= fPIEOnCommandLine
;
4054 case Options::kDyld
:
4055 case Options::kDynamicLibrary
:
4056 case Options::kDynamicBundle
:
4057 case Options::kKextBundle
:
4058 fOutputSlidable
= true;
4062 // let linker know if thread local variables are supported
4063 if ( fMacVersionMin
>= ld::mac10_7
) {
4066 else if ( (fArchitecture
== CPU_TYPE_ARM64
) && (fIOSVersionMin
>= ld::iOS_8_0
) ) {
4070 // default to adding version load command for dynamic code, static code must opt-in
4071 switch ( fOutputKind
) {
4072 case Options::kObjectFile
:
4073 fVersionLoadCommand
= false;
4075 case Options::kStaticExecutable
:
4076 case Options::kPreload
:
4077 case Options::kKextBundle
:
4078 if ( fVersionLoadCommandForcedOn
)
4079 fVersionLoadCommand
= true;
4081 case Options::kDynamicExecutable
:
4082 case Options::kDyld
:
4083 case Options::kDynamicLibrary
:
4084 case Options::kDynamicBundle
:
4085 if ( !fVersionLoadCommandForcedOff
)
4086 fVersionLoadCommand
= true;
4090 // support re-export of individual symbols in MacOSX 10.7 and iOS 4.2
4091 if ( (fOutputKind
== kDynamicLibrary
) && minOS(ld::mac10_7
, ld::iOS_4_2
) )
4092 fCanReExportSymbols
= true;
4094 // ObjC optimization is only in dynamic final linked images
4095 switch ( fOutputKind
) {
4096 case Options::kObjectFile
:
4097 case Options::kStaticExecutable
:
4098 case Options::kPreload
:
4099 case Options::kKextBundle
:
4100 case Options::kDyld
:
4101 fObjcCategoryMerging
= false;
4103 case Options::kDynamicExecutable
:
4104 case Options::kDynamicLibrary
:
4105 case Options::kDynamicBundle
:
4109 // i386 main executables linked on Mac OS X 10.7 default to NX heap
4110 // regardless of target unless overriden with -allow_heap_execute anywhere
4111 // on the command line
4112 if ( (fArchitecture
== CPU_TYPE_I386
) && (fOutputKind
== kDynamicExecutable
) && !fDisableNonExecutableHeap
)
4113 fNonExecutableHeap
= true;
4115 // Use LC_MAIN instead of LC_UNIXTHREAD for newer OSs
4116 switch ( fOutputKind
) {
4117 case Options::kDynamicExecutable
:
4118 if ( fEntryPointLoadCommandForceOn
) {
4119 fEntryPointLoadCommand
= true;
4120 if ( fEntryName
== NULL
)
4121 fEntryName
= "_main";
4123 else if ( fEntryPointLoadCommandForceOff
) {
4124 fNeedsThreadLoadCommand
= true;
4125 if ( fEntryName
== NULL
)
4126 fEntryName
= "start";
4129 // <rdar://problem/16310363> Linker should look for "_main" not "start" when building for sim regardless of min OS
4130 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) || fTargetIOSSimulator
) {
4131 fEntryPointLoadCommand
= true;
4132 if ( fEntryName
== NULL
)
4133 fEntryName
= "_main";
4134 if ( strcmp(fEntryName
, "start") == 0 ) {
4135 warning("Ignoring '-e start' because entry point 'start' is not used for the targeted OS version");
4136 fEntryName
= "_main";
4140 fNeedsThreadLoadCommand
= true;
4141 if ( fEntryName
== NULL
)
4142 fEntryName
= "start";
4146 case Options::kObjectFile
:
4147 case Options::kKextBundle
:
4148 case Options::kDynamicLibrary
:
4149 case Options::kDynamicBundle
:
4152 case Options::kStaticExecutable
:
4153 case Options::kPreload
:
4154 case Options::kDyld
:
4155 fNeedsThreadLoadCommand
= true;
4156 if ( fEntryName
== NULL
)
4157 fEntryName
= "start"; // Perhaps these should have no default and require -e
4161 // add LC_SOURCE_VERSION
4162 switch ( fOutputKind
) {
4163 case Options::kDynamicExecutable
:
4164 case Options::kKextBundle
:
4165 case Options::kDynamicLibrary
:
4166 case Options::kDynamicBundle
:
4167 case Options::kDyld
:
4168 case Options::kStaticExecutable
:
4169 if ( fSourceVersionLoadCommandForceOn
) {
4170 fSourceVersionLoadCommand
= true;
4172 else if ( fSourceVersionLoadCommandForceOff
) {
4173 fSourceVersionLoadCommand
= false;
4176 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) ) {
4177 fSourceVersionLoadCommand
= true;
4180 fSourceVersionLoadCommand
= false;
4183 case Options::kObjectFile
:
4184 case Options::kPreload
:
4185 fSourceVersionLoadCommand
= false;
4190 // add LC_DYLIB_CODE_SIGN_DRS
4191 switch ( fOutputKind
) {
4192 case Options::kDynamicExecutable
:
4193 case Options::kDynamicLibrary
:
4194 case Options::kDynamicBundle
:
4195 if ( fDependentDRInfoForcedOn
) {
4196 fDependentDRInfo
= true;
4198 else if ( fDependentDRInfoForcedOff
) {
4199 fDependentDRInfo
= false;
4202 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) )
4203 fDependentDRInfo
= true;
4205 fDependentDRInfo
= false;
4208 case Options::kKextBundle
:
4209 case Options::kDyld
:
4210 case Options::kStaticExecutable
:
4211 case Options::kObjectFile
:
4212 case Options::kPreload
:
4213 fDependentDRInfo
= false;
4217 // if -sdk_version not on command line, infer from -syslibroot
4218 if ( (fSDKVersion
== 0) && (fSDKPaths
.size() > 0) ) {
4219 const char* sdkPath
= fSDKPaths
.front();
4220 const char* end
= &sdkPath
[strlen(sdkPath
)-1];
4221 while ( !isdigit(*end
) && (end
> sdkPath
) )
4223 const char* start
= end
-1;
4224 while ( (isdigit(*start
) || (*start
== '.')) && (start
> sdkPath
))
4226 char sdkVersionStr
[32];
4227 int len
= end
-start
+1;
4229 strlcpy(sdkVersionStr
, start
+1, len
);
4230 fSDKVersion
= parseVersionNumber32(sdkVersionStr
);
4234 // if -sdk_version and -syslibroot not used, but targeting MacOSX, use current OS version
4235 if ( (fSDKVersion
== 0) && (fMacVersionMin
!= ld::macVersionUnset
) ) {
4236 // special case if RC_ProjectName and MACOSX_DEPLOYMENT_TARGET are both set that sdkversion=minos
4237 if ( getenv("RC_ProjectName") && getenv("MACOSX_DEPLOYMENT_TARGET") ) {
4238 fSDKVersion
= fMacVersionMin
;
4241 int mib
[2] = { CTL_KERN
, KERN_OSRELEASE
};
4242 char kernVersStr
[100];
4243 size_t strlen
= sizeof(kernVersStr
);
4244 if ( sysctl(mib
, 2, kernVersStr
, &strlen
, NULL
, 0) != -1 ) {
4245 uint32_t kernVers
= parseVersionNumber32(kernVersStr
);
4246 int minor
= (kernVers
>> 16) - 4; // kernel major version is 4 ahead of x in 10.x
4247 fSDKVersion
= 0x000A0000 + (minor
<< 8);
4252 // allow trie based absolute symbols if targeting new enough OS
4253 if ( fMakeCompressedDyldInfo
) {
4254 if ( minOS(ld::mac10_9
, ld::iOS_7_0
) ) {
4255 // <rdar://problem/13179029> Allow absolute symbols in export trie for device but not simulator
4256 if ( !fTargetIOSSimulator
)
4257 fAbsoluteSymbols
= true;
4261 // <rdar://problem/12959510> iOS main executables now default to 16KB page size
4262 if ( (fIOSVersionMin
!= ld::iOSVersionUnset
) && (fOutputKind
== Options::kDynamicExecutable
) ) {
4263 // <rdar://problem/13070042> Only third party apps should have 16KB page segments by default
4264 if ( fEncryptable
) {
4265 if ( fSegmentAlignment
== 4096 )
4266 fSegmentAlignment
= 4096*4;
4270 // <rdar://problem/12258065> ARM64 needs 16KB page size for user land code
4271 // <rdar://problem/15974532> make armv7[s] use 16KB pages in user land code for iOS 8 or later
4272 if ( fSegmentAlignment
== 4096 ) {
4273 if ( (fArchitecture
== CPU_TYPE_ARM64
)
4274 || ((fArchitecture
== CPU_TYPE_ARM
) && (fIOSVersionMin
>= ld::iOS_8_0
) &&
4275 ((fSubArchitecture
== CPU_SUBTYPE_ARM_V7S
) || (fSubArchitecture
== CPU_SUBTYPE_ARM_V7
))) ) {
4276 switch ( fOutputKind
) {
4277 case Options::kDynamicExecutable
:
4278 case Options::kDynamicLibrary
:
4279 case Options::kDynamicBundle
:
4280 case Options::kDyld
:
4281 fSegmentAlignment
= 4096*4;
4283 case Options::kStaticExecutable
:
4284 case Options::kKextBundle
:
4285 case Options::kObjectFile
:
4286 case Options::kPreload
:
4292 // <rdar://problem/13624134> linker should not convert dwarf unwind if .o file has compact unwind section
4293 switch ( fOutputKind
) {
4294 case Options::kDynamicExecutable
:
4295 case Options::kDynamicLibrary
:
4296 case Options::kDynamicBundle
:
4297 case Options::kDyld
:
4298 if ( fKeepDwarfUnwindForcedOn
) {
4299 fKeepDwarfUnwind
= true;
4301 else if ( fKeepDwarfUnwindForcedOff
) {
4302 fKeepDwarfUnwind
= false;
4305 if ( minOS(ld::mac10_9
, ld::iOS_7_0
) )
4306 fKeepDwarfUnwind
= false;
4308 fKeepDwarfUnwind
= true;
4311 case Options::kKextBundle
:
4312 case Options::kStaticExecutable
:
4313 case Options::kObjectFile
:
4314 case Options::kPreload
:
4315 fKeepDwarfUnwind
= true;
4321 void Options::checkIllegalOptionCombinations()
4323 // check -undefined setting
4324 switch ( fUndefinedTreatment
) {
4325 case kUndefinedError
:
4326 case kUndefinedDynamicLookup
:
4329 case kUndefinedWarning
:
4330 case kUndefinedSuppress
:
4331 // requires flat namespace
4332 if ( fNameSpace
== kTwoLevelNameSpace
)
4333 throw "can't use -undefined warning or suppress with -twolevel_namespace";
4337 // unify -sub_umbrella with dylibs
4338 for (std::vector
<const char*>::iterator it
= fSubUmbellas
.begin(); it
!= fSubUmbellas
.end(); it
++) {
4339 const char* subUmbrella
= *it
;
4341 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
4342 Options::FileInfo
& info
= *fit
;
4343 const char* lastSlash
= strrchr(info
.path
, '/');
4344 if ( lastSlash
== NULL
)
4345 lastSlash
= info
.path
- 1;
4346 if ( strcmp(&lastSlash
[1], subUmbrella
) == 0 ) {
4347 info
.options
.fReExport
= true;
4349 fLinkSnapshot
.recordSubUmbrella(info
.path
);
4354 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella
);
4357 // unify -sub_library with dylibs
4358 for (std::vector
<const char*>::iterator it
= fSubLibraries
.begin(); it
!= fSubLibraries
.end(); it
++) {
4359 const char* subLibrary
= *it
;
4361 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
4362 Options::FileInfo
& info
= *fit
;
4363 const char* lastSlash
= strrchr(info
.path
, '/');
4364 if ( lastSlash
== NULL
)
4365 lastSlash
= info
.path
- 1;
4366 const char* dot
= strchr(&lastSlash
[1], '.');
4368 dot
= &lastSlash
[strlen(lastSlash
)];
4369 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
4370 info
.options
.fReExport
= true;
4372 fLinkSnapshot
.recordSubLibrary(info
.path
);
4377 warning("-sub_library %s does not match a supplied dylib", subLibrary
);
4380 // sync reader options
4381 if ( fNameSpace
!= kTwoLevelNameSpace
)
4382 fFlatNamespace
= true;
4384 // check -stack_addr
4385 if ( fStackAddr
!= 0 ) {
4386 switch (fArchitecture
) {
4389 if ( fStackAddr
> 0xFFFFFFFF )
4390 throw "-stack_addr must be < 4G for 32-bit processes";
4392 case CPU_TYPE_X86_64
:
4393 case CPU_TYPE_ARM64
:
4396 if ( (fStackAddr
& -4096) != fStackAddr
)
4397 throw "-stack_addr must be multiples of 4K";
4398 if ( fStackSize
== 0 )
4399 throw "-stack_addr must be used with -stack_size";
4402 // check -stack_size
4403 if ( fStackSize
!= 0 ) {
4404 switch (fArchitecture
) {
4406 if ( fStackSize
> 0xFFFFFFFF )
4407 throw "-stack_size must be < 4G for 32-bit processes";
4408 if ( fStackAddr
== 0 ) {
4409 fStackAddr
= 0xC0000000;
4411 if ( (fStackAddr
> 0xB0000000) && ((fStackAddr
-fStackSize
) < 0xB0000000) )
4412 warning("custom stack placement overlaps and will disable shared region");
4415 if ( fStackSize
> 0x2F000000 )
4416 throw "-stack_size must be < 752MB";
4417 if ( fStackAddr
== 0 )
4418 fStackAddr
= 0x2F000000;
4419 if ( fStackAddr
> 0x30000000)
4420 throw "-stack_addr must be < 0x30000000 for arm";
4422 case CPU_TYPE_X86_64
:
4423 if ( fStackAddr
== 0 ) {
4424 fStackAddr
= 0x00007FFF5C000000LL
;
4427 case CPU_TYPE_ARM64
:
4428 if ( fStackSize
> 0x20000000 )
4429 throw "-stack_size must be < 512MB";
4430 if ( fStackAddr
== 0 ) {
4431 fStackAddr
= 0x120000000;
4435 if ( (fStackSize
& -4096) != fStackSize
)
4436 throw "-stack_size must be multiples of 4K";
4437 switch ( fOutputKind
) {
4438 case Options::kDynamicExecutable
:
4439 case Options::kStaticExecutable
:
4440 // custom stack size only legal when building main executable
4442 case Options::kDynamicLibrary
:
4443 case Options::kDynamicBundle
:
4444 case Options::kObjectFile
:
4445 case Options::kDyld
:
4446 case Options::kPreload
:
4447 case Options::kKextBundle
:
4448 throw "-stack_size option can only be used when linking a main executable";
4450 if ( fStackSize
> fStackAddr
)
4451 throwf("-stack_size (0x%08llX) must be smaller than -stack_addr (0x%08llX)", fStackSize
, fStackAddr
);
4454 // check that -allow_stack_execute is only used with main executables
4455 if ( fExecutableStack
) {
4456 switch ( fOutputKind
) {
4457 case Options::kDynamicExecutable
:
4458 case Options::kStaticExecutable
:
4459 // -allow_stack_execute size only legal when building main executable
4461 case Options::kDynamicLibrary
:
4462 case Options::kDynamicBundle
:
4463 case Options::kObjectFile
:
4464 case Options::kDyld
:
4465 case Options::kPreload
:
4466 case Options::kKextBundle
:
4467 throw "-allow_stack_execute option can only be used when linking a main executable";
4471 // check that -allow_heap_execute is only used with i386 main executables
4472 if ( fDisableNonExecutableHeap
) {
4473 if ( fArchitecture
!= CPU_TYPE_I386
)
4474 throw "-allow_heap_execute option can only be used when linking for i386";
4475 switch ( fOutputKind
) {
4476 case Options::kDynamicExecutable
:
4477 // -allow_heap_execute only legal when building main executable
4479 case Options::kStaticExecutable
:
4480 case Options::kDynamicLibrary
:
4481 case Options::kDynamicBundle
:
4482 case Options::kObjectFile
:
4483 case Options::kDyld
:
4484 case Options::kPreload
:
4485 case Options::kKextBundle
:
4486 throw "-allow_heap_execute option can only be used when linking a main executable";
4490 // check -client_name is only used when making a bundle or main executable
4491 if ( fClientName
!= NULL
) {
4492 switch ( fOutputKind
) {
4493 case Options::kDynamicExecutable
:
4494 case Options::kDynamicBundle
:
4496 case Options::kStaticExecutable
:
4497 case Options::kDynamicLibrary
:
4498 case Options::kObjectFile
:
4499 case Options::kDyld
:
4500 case Options::kPreload
:
4501 case Options::kKextBundle
:
4502 throw "-client_name can only be used with -bundle";
4506 // check -init is only used when building a dylib
4507 if ( (fInitFunctionName
!= NULL
) && (fOutputKind
!= Options::kDynamicLibrary
) )
4508 throw "-init can only be used with -dynamiclib";
4510 // check -bundle_loader only used with -bundle
4511 if ( (fBundleLoader
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
4512 throw "-bundle_loader can only be used with -bundle";
4514 // check -dtrace not used with -r
4515 if ( (fDtraceScriptName
!= NULL
) && (fOutputKind
== Options::kObjectFile
) )
4516 throw "-dtrace can only be used when creating final linked images";
4518 // check -d can only be used with -r
4519 if ( fMakeTentativeDefinitionsReal
&& (fOutputKind
!= Options::kObjectFile
) )
4520 throw "-d can only be used with -r";
4522 // check that -root_safe is not used with -r
4523 if ( fRootSafe
&& (fOutputKind
== Options::kObjectFile
) )
4524 throw "-root_safe cannot be used with -r";
4526 // check that -setuid_safe is not used with -r
4527 if ( fSetuidSafe
&& (fOutputKind
== Options::kObjectFile
) )
4528 throw "-setuid_safe cannot be used with -r";
4530 // <rdar://problem/12781832> compiler driver no longer uses -objc_abi_version, it uses -ios_simulator_version_min instead
4531 if ( !fObjCABIVersion1Override
&& !fObjCABIVersion2Override
&& fTargetIOSSimulator
)
4532 fObjCABIVersion2Override
= true;
4534 // rdar://problem/4718189 map ObjC class names to new runtime names
4535 bool alterObjC1ClassNamesToObjC2
= false;
4536 switch (fArchitecture
) {
4538 // i386 only uses new symbols when using objc2 ABI
4539 if ( fObjCABIVersion2Override
)
4540 alterObjC1ClassNamesToObjC2
= true;
4542 case CPU_TYPE_X86_64
:
4544 case CPU_TYPE_ARM64
:
4545 alterObjC1ClassNamesToObjC2
= true;
4549 // make sure all required exported symbols exist
4550 std::vector
<const char*> impliedExports
;
4551 for (NameSet::iterator it
=fExportSymbols
.regularBegin(); it
!= fExportSymbols
.regularEnd(); ++it
) {
4552 const char* name
= *it
;
4553 const int len
= strlen(name
);
4554 if ( (strcmp(&name
[len
-3], ".eh") == 0) || (strncmp(name
, ".objc_category_name_", 20) == 0) ) {
4555 // never export .eh symbols
4556 warning("ignoring %s in export list", name
);
4558 else if ( (fArchitecture
== CPU_TYPE_I386
) && !fObjCABIVersion2Override
&& (strncmp(name
, "_OBJC_CLASS_$", 13) == 0) ) {
4559 warning("ignoring Objc2 Class symbol %s in i386 export list", name
);
4560 fRemovedExports
.insert(name
);
4562 else if ( alterObjC1ClassNamesToObjC2
&& (strncmp(name
, ".objc_class_name_", 17) == 0) ) {
4563 // linking ObjC2 ABI, but have ObjC1 ABI name in export list. Change it to intended name
4564 fRemovedExports
.insert(name
);
4566 asprintf(&temp
, "_OBJC_CLASS_$_%s", &name
[17]);
4567 impliedExports
.push_back(temp
);
4568 asprintf(&temp
, "_OBJC_METACLASS_$_%s", &name
[17]);
4569 impliedExports
.push_back(temp
);
4572 fInitialUndefines
.push_back(name
);
4575 fExportSymbols
.remove(fRemovedExports
);
4576 for (std::vector
<const char*>::iterator it
=impliedExports
.begin(); it
!= impliedExports
.end(); ++it
) {
4577 const char* name
= *it
;
4578 fExportSymbols
.insert(name
);
4579 fInitialUndefines
.push_back(name
);
4582 // make sure all required re-exported symbols exist
4583 for (NameSet::iterator it
=fReExportSymbols
.regularBegin(); it
!= fReExportSymbols
.regularEnd(); ++it
) {
4584 fInitialUndefines
.push_back(*it
);
4587 // make sure that -init symbol exists
4588 if ( fInitFunctionName
!= NULL
)
4589 fInitialUndefines
.push_back(fInitFunctionName
);
4591 // make sure that entry symbol exists
4592 switch ( fOutputKind
) {
4593 case Options::kDynamicExecutable
:
4594 case Options::kStaticExecutable
:
4595 case Options::kDyld
:
4596 case Options::kPreload
:
4597 fInitialUndefines
.push_back(fEntryName
);
4599 case Options::kDynamicLibrary
:
4600 case Options::kDynamicBundle
:
4601 case Options::kObjectFile
:
4602 case Options::kKextBundle
:
4606 // make sure every alias base exists
4607 for (std::vector
<AliasPair
>::iterator it
=fAliases
.begin(); it
!= fAliases
.end(); ++it
) {
4608 fInitialUndefines
.push_back(it
->realName
);
4611 // check custom segments
4612 if ( fCustomSegmentAddresses
.size() != 0 ) {
4613 // verify no segment is in zero page
4614 if ( fZeroPageSize
!= ULLONG_MAX
) {
4615 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
4616 if ( it
->address
< fZeroPageSize
)
4617 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it
->name
, it
->address
);
4620 // verify no duplicates
4621 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
4622 for (std::vector
<SegmentStart
>::iterator it2
= fCustomSegmentAddresses
.begin(); it2
!= fCustomSegmentAddresses
.end(); ++it2
) {
4623 if ( (it
->address
== it2
->address
) && (it
!= it2
) )
4624 throwf("duplicate -segaddr addresses for %s and %s", it
->name
, it2
->name
);
4626 // a custom segment address of zero will disable the use of a zero page
4627 if ( it
->address
== 0 )
4632 if ( fZeroPageSize
== ULLONG_MAX
) {
4633 // zero page size not specified on command line, set default
4634 switch (fArchitecture
) {
4637 // first 4KB for 32-bit architectures
4638 fZeroPageSize
= 0x1000;
4640 case CPU_TYPE_ARM64
:
4641 case CPU_TYPE_X86_64
:
4642 // first 4GB for x86_64 on all OS's
4643 fZeroPageSize
= 0x100000000ULL
;
4646 // if -arch not used, default to 4K zero-page
4647 fZeroPageSize
= 0x1000;
4651 switch ( fOutputKind
) {
4652 case Options::kDynamicExecutable
:
4653 case Options::kStaticExecutable
:
4654 // -pagezero_size size only legal when building main executable
4656 case Options::kDynamicLibrary
:
4657 case Options::kDynamicBundle
:
4658 case Options::kObjectFile
:
4659 case Options::kDyld
:
4660 case Options::kPreload
:
4661 case Options::kKextBundle
:
4662 if ( fZeroPageSize
!= 0 )
4663 throw "-pagezero_size option can only be used when linking a main executable";
4667 // if main executable with custom base address, model zero page as custom segment
4668 if ( (fOutputKind
== Options::kDynamicExecutable
) && (fBaseAddress
!= 0) && (fZeroPageSize
!= 0) ) {
4670 seg
.name
= "__PAGEZERO";
4672 fCustomSegmentAddresses
.push_back(seg
);
4675 // -dead_strip and -r are incompatible
4676 if ( fDeadStrip
&& (fOutputKind
== Options::kObjectFile
) )
4677 throw "-r and -dead_strip cannot be used together";
4679 // can't use -rpath unless targeting 10.5 or later
4680 if ( fRPaths
.size() > 0 ) {
4681 if ( !minOS(ld::mac10_5
, ld::iOS_2_0
) )
4682 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
4683 switch ( fOutputKind
) {
4684 case Options::kDynamicExecutable
:
4685 case Options::kDynamicLibrary
:
4686 case Options::kDynamicBundle
:
4688 case Options::kStaticExecutable
:
4689 case Options::kObjectFile
:
4690 case Options::kDyld
:
4691 case Options::kPreload
:
4692 case Options::kKextBundle
:
4693 throw "-rpath can only be used when creating a dynamic final linked image";
4697 if ( fPositionIndependentExecutable
) {
4698 switch ( fOutputKind
) {
4699 case Options::kDynamicExecutable
:
4700 // check -pie is only used when building a dynamic main executable for 10.5
4701 if ( !minOS(ld::mac10_5
, ld::iOS_4_2
) ) {
4702 if ( fIOSVersionMin
== ld::iOSVersionUnset
)
4703 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
4705 throw "-pie can only be used when targeting iOS 4.2 or later";
4708 case Options::kStaticExecutable
:
4709 case Options::kPreload
:
4710 // -pie is ok with -static or -preload
4712 case Options::kDynamicLibrary
:
4713 case Options::kDynamicBundle
:
4714 warning("-pie being ignored. It is only used when linking a main executable");
4715 fPositionIndependentExecutable
= false;
4717 case Options::kObjectFile
:
4718 case Options::kDyld
:
4719 case Options::kKextBundle
:
4720 throw "-pie can only be used when linking a main executable";
4724 // check -read_only_relocs is not used with x86_64
4725 if ( fAllowTextRelocs
) {
4726 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
!= kKextBundle
) ) {
4727 warning("-read_only_relocs cannot be used with x86_64");
4728 fAllowTextRelocs
= false;
4732 // check -mark_auto_dead_strip is only used with dylibs
4733 if ( fMarkDeadStrippableDylib
) {
4734 if ( fOutputKind
!= Options::kDynamicLibrary
) {
4735 warning("-mark_auto_dead_strip can only be used when creating a dylib");
4736 fMarkDeadStrippableDylib
= false;
4740 // -force_cpusubtype_ALL is not supported for ARM
4741 if ( fForceSubtypeAll
) {
4742 if ( fArchitecture
== CPU_TYPE_ARM
) {
4743 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
4747 // -reexported_symbols_list can only be used with -dynamiclib
4748 if ( !fReExportSymbols
.empty() ) {
4749 if ( fOutputKind
!= Options::kDynamicLibrary
)
4750 throw "-reexported_symbols_list can only used used when created dynamic libraries";
4751 if ( !minOS(ld::mac10_7
, ld::iOS_4_2
) )
4752 throw "targeted OS version does not support -reexported_symbols_list";
4755 // -dyld_env can only be used with main executables
4756 if ( (fOutputKind
!= Options::kDynamicExecutable
) && (fDyldEnvironExtras
.size() != 0) )
4757 throw "-dyld_env can only used used when created main executables";
4759 // -segment_order can only be used with -preload
4760 if ( !fSegmentOrder
.empty() && (fOutputKind
!= Options::kPreload
) )
4761 throw "-segment_order can only used used with -preload output";
4763 // <rdar://problem/17598404> warn if building an embedded iOS dylib for pre-iOS 8
4764 if ( (fOutputKind
== Options::kDynamicLibrary
) && (fIOSVersionMin
!= ld::iOSVersionUnset
) && (fDylibInstallName
!= NULL
) ) {
4765 if ( (fIOSVersionMin
< ld::iOS_8_0
) && (fDylibInstallName
[0] == '@') )
4766 warning("embedded dylibs/frameworks only run on iOS 8 or later");
4771 void Options::checkForClassic(int argc
, const char* argv
[])
4774 bool archFound
= false;
4775 bool staticFound
= false;
4776 bool dtraceFound
= false;
4777 bool kextFound
= false;
4778 bool rFound
= false;
4779 bool creatingMachKernel
= false;
4780 bool newLinker
= false;
4782 // build command line buffer in case ld crashes
4783 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
4784 CRSetCrashLogMessage(crashreporterBuffer
);
4786 const char* srcRoot
= getenv("SRCROOT");
4787 if ( srcRoot
!= NULL
) {
4788 strlcpy(crashreporterBuffer
, "SRCROOT=", crashreporterBufferSize
);
4789 strlcat(crashreporterBuffer
, srcRoot
, crashreporterBufferSize
);
4790 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
4793 strlcat(crashreporterBuffer
, LD_VERS
, crashreporterBufferSize
);
4794 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
4796 strlcat(crashreporterBuffer
, "ld ", crashreporterBufferSize
);
4797 for(int i
=1; i
< argc
; ++i
) {
4798 strlcat(crashreporterBuffer
, argv
[i
], crashreporterBufferSize
);
4799 strlcat(crashreporterBuffer
, " ", crashreporterBufferSize
);
4802 for(int i
=0; i
< argc
; ++i
) {
4803 const char* arg
= argv
[i
];
4804 if ( arg
[0] == '-' ) {
4805 if ( strcmp(arg
, "-arch") == 0 ) {
4806 parseArch(argv
[++i
]);
4809 else if ( strcmp(arg
, "-static") == 0 ) {
4812 else if ( strcmp(arg
, "-kext") == 0 ) {
4815 else if ( strcmp(arg
, "-dtrace") == 0 ) {
4818 else if ( strcmp(arg
, "-r") == 0 ) {
4821 else if ( strcmp(arg
, "-new_linker") == 0 ) {
4824 else if ( strcmp(arg
, "-classic_linker") == 0 ) {
4825 // ld_classic does not understand this option, so remove it
4826 for(int j
=i
; j
< argc
; ++j
)
4827 argv
[j
] = argv
[j
+1];
4828 warning("using ld_classic");
4829 this->gotoClassicLinker(argc
-1, argv
);
4831 else if ( strcmp(arg
, "-o") == 0 ) {
4832 const char* outfile
= argv
[++i
];
4833 if ( (outfile
!= NULL
) && (strstr(outfile
, "/mach_kernel") != NULL
) )
4834 creatingMachKernel
= true;
4840 void Options::gotoClassicLinker(int argc
, const char* argv
[])
4842 argv
[0] = "ld_classic";
4843 // ld_classic does not support -iphoneos_version_min, so change
4844 for(int j
=0; j
< argc
; ++j
) {
4845 if ( (strcmp(argv
[j
], "-iphoneos_version_min") == 0) || (strcmp(argv
[j
], "-ios_version_min") == 0) ) {
4846 argv
[j
] = "-macosx_version_min";
4852 // ld classic does not understand -kext (change to -static -r)
4853 for(int j
=0; j
< argc
; ++j
) {
4854 if ( strcmp(argv
[j
], "-kext") == 0)
4856 else if ( strcmp(argv
[j
], "-dynamic") == 0)
4857 argv
[j
] = "-static";
4859 // ld classic does not understand -demangle
4860 for(int j
=0; j
< argc
; ++j
) {
4861 if ( strcmp(argv
[j
], "-demangle") == 0)
4862 argv
[j
] = "-noprebind";
4864 // in -v mode, print command line passed to ld_classic
4865 for(int i
=0; i
< argc
; ++i
) {
4866 if ( strcmp(argv
[i
], "-v") == 0 ) {
4867 for(int j
=0; j
< argc
; ++j
)
4868 printf("%s ", argv
[j
]);
4873 char rawPath
[PATH_MAX
];
4874 char path
[PATH_MAX
];
4875 uint32_t bufSize
= PATH_MAX
;
4876 if ( _NSGetExecutablePath(rawPath
, &bufSize
) != -1 ) {
4877 if ( realpath(rawPath
, path
) != NULL
) {
4878 char* lastSlash
= strrchr(path
, '/');
4879 if ( lastSlash
!= NULL
) {
4880 strcpy(lastSlash
+1, "ld_classic");
4882 execvp(path
, (char**)argv
);
4886 // in case of error in above, try searching for ld_classic via PATH
4887 execvp(argv
[0], (char**)argv
);
4888 fprintf(stderr
, "can't exec ld_classic\n");
4893 // Note, returned string buffer is own by this function.
4894 // It should not be freed
4895 // It will be reused, so clients need to strdup() if they want
4896 // to use it long term.
4897 const char* Options::demangleSymbol(const char* sym
) const
4899 // only try to demangle symbols if -demangle on command line
4903 // only try to demangle symbols that look like C++ symbols
4904 if ( strncmp(sym
, "__Z", 3) != 0 )
4907 static size_t size
= 1024;
4908 static char* buff
= (char*)malloc(size
);
4911 char* result
= abi::__cxa_demangle(&sym
[1], buff
, &size
, &status
);
4912 if ( result
!= NULL
) {
4913 // if demangling successful, keep buffer for next demangle
4921 void Options::dumpDependency(uint8_t opcode
, const char* path
) const
4923 if ( !this->dumpDependencyInfo() )
4926 // one time open() of -dependency_info file
4927 if ( fDependencyFileDescriptor
== -1 ) {
4928 fDependencyFileDescriptor
= open(this->dependencyInfoPath(), O_WRONLY
| O_TRUNC
| O_CREAT
, 0666);
4929 if ( fDependencyFileDescriptor
== -1 )
4930 throwf("Could not open or create -dependency_info file: %s", this->dependencyInfoPath());
4933 uint8_t version
= depLinkerVersion
;
4934 if ( write(fDependencyFileDescriptor
, &version
, 1) == -1 )
4935 throwf("write() to -dependency_info failed, errno=%d", errno
);
4936 extern const char ldVersionString
[];
4937 if ( write(fDependencyFileDescriptor
, ldVersionString
, strlen(ldVersionString
)+1) == -1 )
4938 throwf("write() to -dependency_info failed, errno=%d", errno
);
4941 char realPath
[PATH_MAX
];
4942 if ( path
[0] != '/' ) {
4943 if ( realpath(path
, realPath
) != NULL
) {
4948 if ( write(fDependencyFileDescriptor
, &opcode
, 1) == -1 )
4949 throwf("write() to -dependency_info failed, errno=%d", errno
);
4950 if ( write(fDependencyFileDescriptor
, path
, strlen(path
)+1) == -1 )
4951 throwf("write() to -dependency_info failed, errno=%d", errno
);
4953 //fprintf(stderr, "0x%02X %s\n", opcode, path);