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 bool Options::armUsesZeroCostExceptions() const
606 return ( (fArchitecture
== CPU_TYPE_ARM
) && (fSubArchitecture
== CPU_SUBTYPE_ARM_V7K
) );
609 void Options::parseArch(const char* arch
)
612 throw "-arch must be followed by an architecture string";
613 for (const ArchInfo
* t
=archInfoArray
; t
->archName
!= NULL
; ++t
) {
614 if ( strcmp(t
->archName
,arch
) == 0 ) {
615 fArchitectureName
= arch
;
616 fArchitecture
= t
->cpuType
;
617 fSubArchitecture
= t
->cpuSubType
;
618 fHasPreferredSubType
= t
->isSubType
;
619 fArchSupportsThumb2
= t
->supportsThumb2
;
623 throwf("unknown/unsupported architecture name for: -arch %s", arch
);
626 bool Options::checkForFile(const char* format
, const char* dir
, const char* rootName
, FileInfo
& result
) const
628 char possiblePath
[strlen(dir
)+strlen(rootName
)+strlen(format
)+8];
629 sprintf(possiblePath
, format
, dir
, rootName
);
630 bool found
= result
.checkFileExists(*this, possiblePath
);
631 if ( fTraceDylibSearching
)
632 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), possiblePath
);
637 Options::FileInfo
Options::findLibrary(const char* rootName
, bool dylibsOnly
) const
640 const int rootNameLen
= strlen(rootName
);
641 // if rootName ends in .o there is no .a vs .dylib choice
642 if ( (rootNameLen
> 3) && (strcmp(&rootName
[rootNameLen
-2], ".o") == 0) ) {
643 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
644 it
!= fLibrarySearchPaths
.end();
646 const char* dir
= *it
;
647 if ( checkForFile("%s/%s", dir
, rootName
, result
) )
652 bool lookForDylibs
= false;
653 switch ( fOutputKind
) {
654 case Options::kDynamicExecutable
:
655 case Options::kDynamicLibrary
:
656 case Options::kDynamicBundle
:
657 case Options::kObjectFile
: // <rdar://problem/15914513>
658 lookForDylibs
= true;
660 case Options::kStaticExecutable
:
662 case Options::kPreload
:
663 case Options::kKextBundle
:
664 lookForDylibs
= false;
667 switch ( fLibrarySearchMode
) {
668 case kSearchAllDirsForDylibsThenAllDirsForArchives
:
669 // first look in all directories for just for dylibs
670 if ( lookForDylibs
) {
671 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
672 it
!= fLibrarySearchPaths
.end();
674 const char* dir
= *it
;
675 if ( checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
678 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
679 it
!= fLibrarySearchPaths
.end();
681 const char* dir
= *it
;
682 if ( checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
686 // next look in all directories for just for archives
688 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
689 it
!= fLibrarySearchPaths
.end();
691 const char* dir
= *it
;
692 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
698 case kSearchDylibAndArchiveInEachDir
:
699 // look in each directory for just for a dylib then for an archive
700 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
701 it
!= fLibrarySearchPaths
.end();
703 const char* dir
= *it
;
704 if ( lookForDylibs
&& checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
706 if ( lookForDylibs
&& checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
708 if ( !dylibsOnly
&& checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
714 throwf("library not found for -l%s", rootName
);
717 Options::FileInfo
Options::findFramework(const char* frameworkName
) const
719 if ( frameworkName
== NULL
)
720 throw "-framework missing next argument";
721 char temp
[strlen(frameworkName
)+1];
722 strcpy(temp
, frameworkName
);
723 const char* name
= temp
;
724 const char* suffix
= NULL
;
725 char* comma
= strchr(temp
, ',');
726 if ( comma
!= NULL
) {
730 return findFramework(name
, suffix
);
733 Options::FileInfo
Options::findFramework(const char* rootName
, const char* suffix
) const
735 for (std::vector
<const char*>::const_iterator it
= fFrameworkSearchPaths
.begin();
736 it
!= fFrameworkSearchPaths
.end();
738 // ??? Shouldn't we be using String here and just initializing it?
739 // ??? Use str.c_str () to pull out the string for the stat call.
740 const char* dir
= *it
;
741 char possiblePath
[PATH_MAX
];
742 strcpy(possiblePath
, dir
);
743 strcat(possiblePath
, "/");
744 strcat(possiblePath
, rootName
);
745 strcat(possiblePath
, ".framework/");
746 strcat(possiblePath
, rootName
);
747 if ( suffix
!= NULL
) {
748 char realPath
[PATH_MAX
];
749 // no symlink in framework to suffix variants, so follow main symlink
750 if ( realpath(possiblePath
, realPath
) != NULL
) {
751 strcpy(possiblePath
, realPath
);
752 strcat(possiblePath
, suffix
);
756 bool found
= result
.checkFileExists(*this, possiblePath
);
757 if ( fTraceDylibSearching
)
758 printf("[Logging for XBS]%sfound framework: '%s'\n",
759 (found
? " " : " not "), possiblePath
);
764 // try without suffix
765 if ( suffix
!= NULL
)
766 return findFramework(rootName
, NULL
);
768 throwf("framework not found %s", rootName
);
771 Options::FileInfo
Options::findFile(const char* path
) const
775 // if absolute path and not a .o file, the use SDK prefix
776 if ( (path
[0] == '/') && (strcmp(&path
[strlen(path
)-2], ".o") != 0) ) {
777 const int pathLen
= strlen(path
);
778 for (std::vector
<const char*>::const_iterator it
= fSDKPaths
.begin(); it
!= fSDKPaths
.end(); it
++) {
779 // ??? Shouldn't we be using String here?
780 const char* sdkPathDir
= *it
;
781 const int sdkPathDirLen
= strlen(sdkPathDir
);
782 char possiblePath
[sdkPathDirLen
+pathLen
+4];
783 strcpy(possiblePath
, sdkPathDir
);
784 if ( possiblePath
[sdkPathDirLen
-1] == '/' )
785 possiblePath
[sdkPathDirLen
-1] = '\0';
786 strcat(possiblePath
, path
);
787 if ( result
.checkFileExists(*this, possiblePath
) ) {
793 if ( result
.checkFileExists(*this, path
) ) {
797 // try @executable_path substitution
798 if ( (strncmp(path
, "@executable_path/", 17) == 0) && (fExecutablePath
!= NULL
) ) {
799 char newPath
[strlen(fExecutablePath
) + strlen(path
)];
800 strcpy(newPath
, fExecutablePath
);
801 char* addPoint
= strrchr(newPath
,'/');
802 if ( addPoint
!= NULL
)
803 strcpy(&addPoint
[1], &path
[17]);
805 strcpy(newPath
, &path
[17]);
806 if ( result
.checkFileExists(*this, newPath
) ) {
812 throwf("file not found: %s", path
);
815 Options::FileInfo
Options::findFileUsingPaths(const char* path
) const
819 const char* lastSlash
= strrchr(path
, '/');
820 const char* leafName
= (lastSlash
== NULL
) ? path
: &lastSlash
[1];
822 // Is this in a framework?
823 // /path/Foo.framework/Foo ==> true (Foo)
824 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
825 // /path/Foo.framework/Resources/Bar ==> false
826 bool isFramework
= false;
827 if ( lastSlash
!= NULL
) {
828 char frameworkDir
[strlen(leafName
) + 20];
829 strcpy(frameworkDir
, "/");
830 strcat(frameworkDir
, leafName
);
831 strcat(frameworkDir
, ".framework/");
832 if ( strstr(path
, frameworkDir
) != NULL
)
836 // These are abbreviated versions of the routines findFramework and findLibrary above
837 // because we already know the final name of the file that we're looking for and so
838 // don't need to try variations, just paths. We do need to add the additional bits
839 // onto the framework path though.
841 for (std::vector
<const char*>::const_iterator it
= fFrameworkSearchPaths
.begin();
842 it
!= fFrameworkSearchPaths
.end();
844 const char* dir
= *it
;
845 char possiblePath
[PATH_MAX
];
846 strcpy(possiblePath
, dir
);
847 strcat(possiblePath
, "/");
848 strcat(possiblePath
, leafName
);
849 strcat(possiblePath
, ".framework");
851 //fprintf(stderr,"Finding Framework: %s/%s, leafName=%s\n", possiblePath, leafName, leafName);
852 if ( checkForFile("%s/%s", possiblePath
, leafName
, result
) )
857 // if this is a .dylib inside a framework, do not search -L paths
858 // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
859 int leafLen
= strlen(leafName
);
860 bool embeddedDylib
= ( (leafLen
> 6)
861 && (strcmp(&leafName
[leafLen
-6], ".dylib") == 0)
862 && (strstr(path
, ".framework/") != NULL
) );
863 if ( !embeddedDylib
) {
864 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
865 it
!= fLibrarySearchPaths
.end();
867 const char* dir
= *it
;
868 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
869 if ( checkForFile("%s/%s", dir
, leafName
, result
) )
875 // If we didn't find it fall back to findFile.
876 return findFile(path
);
881 void Options::parseSegAddrTable(const char* segAddrPath
, const char* installPth
)
883 FILE* file
= fopen(segAddrPath
, "r");
884 if ( file
== NULL
) {
885 warning("-seg_addr_table file cannot be read: %s", segAddrPath
);
890 uint64_t firstColumAddress
= 0;
891 uint64_t secondColumAddress
= 0;
892 bool hasSecondColumn
= false;
893 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
894 path
[PATH_MAX
-1] = '\0';
895 char* eol
= strchr(path
, '\n');
898 // ignore lines not starting with 0x number
899 if ( (path
[0] == '0') && (path
[1] == 'x') ) {
901 firstColumAddress
= strtoull(path
, &p
, 16);
902 while ( isspace(*p
) )
904 // see if second column is a number
905 if ( (p
[0] == '0') && (p
[1] == 'x') ) {
906 secondColumAddress
= strtoull(p
, &p
, 16);
907 hasSecondColumn
= true;
908 while ( isspace(*p
) )
911 while ( isspace(*p
) )
914 // remove any trailing whitespace
915 for(char* end
= eol
-1; (end
> p
) && isspace(*end
); --end
)
917 // see if this line is for the dylib being linked
918 if ( strcmp(p
, installPth
) == 0 ) {
919 fBaseAddress
= firstColumAddress
;
920 if ( hasSecondColumn
) {
921 fBaseWritableAddress
= secondColumAddress
;
924 break; // out of while loop
933 void Options::loadFileList(const char* fileOfPaths
, ld::File::Ordinal baseOrdinal
)
936 const char* comma
= strrchr(fileOfPaths
, ',');
937 const char* prefix
= NULL
;
938 if ( comma
!= NULL
) {
939 // <rdar://problem/5907981> -filelist fails with comma in path
940 file
= fopen(fileOfPaths
, "r");
941 if ( file
== NULL
) {
943 int realFileOfPathsLen
= comma
-fileOfPaths
;
944 char realFileOfPaths
[realFileOfPathsLen
+1];
945 strncpy(realFileOfPaths
,fileOfPaths
, realFileOfPathsLen
);
946 realFileOfPaths
[realFileOfPathsLen
] = '\0';
947 file
= fopen(realFileOfPaths
, "r");
949 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", realFileOfPaths
, errno
, strerror(errno
));
950 if ( this->dumpDependencyInfo() )
951 this->dumpDependency(Options::depFileList
, realFileOfPaths
);
955 file
= fopen(fileOfPaths
, "r");
957 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", fileOfPaths
, errno
, strerror(errno
));
958 if ( this->dumpDependencyInfo() )
959 this->dumpDependency(Options::depFileList
, fileOfPaths
);
963 ld::File::Ordinal previousOrdinal
= baseOrdinal
;
964 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
965 path
[PATH_MAX
-1] = '\0';
966 char* eol
= strchr(path
, '\n');
969 if ( prefix
!= NULL
) {
970 char builtPath
[strlen(prefix
)+strlen(path
)+2];
971 strcpy(builtPath
, prefix
);
972 strcat(builtPath
, "/");
973 strcat(builtPath
, path
);
974 if (fPipelineFifo
!= NULL
) {
975 FileInfo info
= FileInfo(builtPath
);
976 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
977 previousOrdinal
= info
.ordinal
;
978 info
.fromFileList
= true;
979 fInputFiles
.push_back(info
);
981 FileInfo info
= findFile(builtPath
);
982 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
983 previousOrdinal
= info
.ordinal
;
984 info
.fromFileList
= true;
985 fInputFiles
.push_back(info
);
989 if (fPipelineFifo
!= NULL
) {
990 FileInfo info
= FileInfo(path
);
991 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
992 previousOrdinal
= info
.ordinal
;
993 info
.fromFileList
= true;
994 fInputFiles
.push_back(info
);
996 FileInfo info
= findFile(path
);
997 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
998 previousOrdinal
= info
.ordinal
;
999 info
.fromFileList
= true;
1000 fInputFiles
.push_back(info
);
1008 void Options::SetWithWildcards::remove(const NameSet
& toBeRemoved
)
1010 for(NameSet::const_iterator it
=toBeRemoved
.begin(); it
!= toBeRemoved
.end(); ++it
) {
1011 const char* symbolName
= *it
;
1012 NameSet::iterator pos
= fRegular
.find(symbolName
);
1013 if ( pos
!= fRegular
.end() )
1014 fRegular
.erase(pos
);
1018 bool Options::SetWithWildcards::hasWildCards(const char* symbol
)
1020 // an exported symbol name containing *, ?, or [ requires wildcard matching
1021 return ( strpbrk(symbol
, "*?[") != NULL
);
1024 void Options::SetWithWildcards::insert(const char* symbol
)
1026 if ( hasWildCards(symbol
) )
1027 fWildCard
.push_back(symbol
);
1029 fRegular
.insert(symbol
);
1032 bool Options::SetWithWildcards::contains(const char* symbol
, bool* matchBecauseOfWildcard
) const
1034 if ( matchBecauseOfWildcard
!= NULL
)
1035 *matchBecauseOfWildcard
= false;
1036 // first look at hash table on non-wildcard symbols
1037 if ( fRegular
.find(symbol
) != fRegular
.end() )
1039 // next walk list of wild card symbols looking for a match
1040 for(std::vector
<const char*>::const_iterator it
= fWildCard
.begin(); it
!= fWildCard
.end(); ++it
) {
1041 if ( wildCardMatch(*it
, symbol
) ) {
1042 if ( matchBecauseOfWildcard
!= NULL
)
1043 *matchBecauseOfWildcard
= true;
1050 // Support "foo.o:_bar" to mean symbol _bar in file foo.o
1051 bool Options::SetWithWildcards::containsWithPrefix(const char* symbol
, const char* file
, bool& wildCardMatch
) const
1053 wildCardMatch
= false;
1054 if ( contains(symbol
, &wildCardMatch
) )
1058 const char* s
= strrchr(file
, '/');
1061 char buff
[strlen(file
)+strlen(symbol
)+2];
1062 sprintf(buff
, "%s:%s", file
, symbol
);
1063 return contains(buff
, &wildCardMatch
);
1066 bool Options::SetWithWildcards::containsNonWildcard(const char* symbol
) const
1068 // look at hash table on non-wildcard symbols
1069 return ( fRegular
.find(symbol
) != fRegular
.end() );
1074 bool Options::SetWithWildcards::inCharRange(const char*& p
, unsigned char c
) const
1078 while ( *p
!= '\0' ) {
1081 // found beginining [ and ending ]
1082 unsigned char last
= '\0';
1083 for ( const char* s
= b
; s
< e
; ++s
) {
1085 unsigned char next
= *(++s
);
1086 if ( (last
<= c
) && (c
<= next
) )
1103 bool Options::SetWithWildcards::wildCardMatch(const char* pattern
, const char* symbol
) const
1105 const char* s
= symbol
;
1106 for (const char* p
= pattern
; *p
!= '\0'; ++p
) {
1111 for (const char* t
= s
; *t
!= '\0'; ++t
) {
1112 if ( wildCardMatch(&p
[1], t
) )
1122 if ( ! inCharRange(p
, *s
) )
1132 return (*s
== '\0');
1136 void Options::loadExportFile(const char* fileOfExports
, const char* option
, SetWithWildcards
& set
)
1138 if ( fileOfExports
== NULL
)
1139 throwf("missing file after %s", option
);
1140 // read in whole file
1141 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
1143 throwf("can't open %s file: %s", option
, fileOfExports
);
1144 struct stat stat_buf
;
1145 ::fstat(fd
, &stat_buf
);
1146 char* p
= (char*)malloc(stat_buf
.st_size
);
1148 throwf("can't process %s file: %s", option
, fileOfExports
);
1150 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1151 throwf("can't read %s file: %s", option
, fileOfExports
);
1153 if ( this->dumpDependencyInfo() )
1154 this->dumpDependency(Options::depMisc
, fileOfExports
);
1158 // parse into symbols and add to unordered_set
1159 char * const end
= &p
[stat_buf
.st_size
];
1160 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1161 char* symbolStart
= NULL
;
1162 for (char* s
= p
; s
< end
; ++s
) {
1168 else if ( !isspace(*s
) ) {
1174 if ( (*s
== '\n') || (*s
== '\r') ) {
1176 // removing any trailing spaces
1178 while ( isspace(*last
) ) {
1182 set
.insert(symbolStart
);
1188 if ( (*s
== '\n') || (*s
== '\r') )
1193 if ( state
== inSymbol
) {
1194 warning("missing line-end at end of file \"%s\"", fileOfExports
);
1195 int len
= end
-symbolStart
+1;
1196 char* temp
= new char[len
];
1197 strlcpy(temp
, symbolStart
, len
);
1199 // remove any trailing spaces
1200 char* last
= &temp
[len
-2];
1201 while ( isspace(*last
) ) {
1208 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
1211 void Options::parseAliasFile(const char* fileOfAliases
)
1213 // read in whole file
1214 int fd
= ::open(fileOfAliases
, O_RDONLY
, 0);
1216 throwf("can't open alias file: %s", fileOfAliases
);
1217 struct stat stat_buf
;
1218 ::fstat(fd
, &stat_buf
);
1219 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1221 throwf("can't process alias file: %s", fileOfAliases
);
1223 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1224 throwf("can't read alias file: %s", fileOfAliases
);
1225 p
[stat_buf
.st_size
] = '\n';
1227 if ( this->dumpDependencyInfo() )
1228 this->dumpDependency(Options::depMisc
, fileOfAliases
);
1230 // parse into symbols and add to fAliases
1232 char * const end
= &p
[stat_buf
.st_size
+1];
1233 enum { lineStart
, inRealName
, inBetween
, inAliasName
, inComment
} state
= lineStart
;
1235 for (char* s
= p
; s
< end
; ++s
) {
1241 else if ( !isspace(*s
) ) {
1248 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1252 else if ( isspace(*s
) ) {
1259 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1263 else if ( ! isspace(*s
) ) {
1264 state
= inAliasName
;
1271 // removing any trailing spaces
1273 while ( isspace(*last
) ) {
1277 fAliases
.push_back(pair
);
1280 else if ( *s
== '\n' ) {
1282 // removing any trailing spaces
1284 while ( isspace(*last
) ) {
1288 fAliases
.push_back(pair
);
1299 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
1304 void Options::setUndefinedTreatment(const char* treatment
)
1306 if ( treatment
== NULL
)
1307 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
1309 if ( strcmp(treatment
, "warning") == 0 )
1310 fUndefinedTreatment
= kUndefinedWarning
;
1311 else if ( strcmp(treatment
, "error") == 0 )
1312 fUndefinedTreatment
= kUndefinedError
;
1313 else if ( strcmp(treatment
, "suppress") == 0 )
1314 fUndefinedTreatment
= kUndefinedSuppress
;
1315 else if ( strcmp(treatment
, "dynamic_lookup") == 0 )
1316 fUndefinedTreatment
= kUndefinedDynamicLookup
;
1318 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1321 Options::Treatment
Options::parseTreatment(const char* treatment
)
1323 if ( treatment
== NULL
)
1326 if ( strcmp(treatment
, "warning") == 0 )
1328 else if ( strcmp(treatment
, "error") == 0 )
1330 else if ( strcmp(treatment
, "suppress") == 0 )
1336 void Options::setMacOSXVersionMin(const char* version
)
1338 if ( version
== NULL
)
1339 throw "-macosx_version_min argument missing";
1341 if ( (strncmp(version
, "10.", 3) == 0) && isdigit(version
[3]) ) {
1342 unsigned int minorVersion
= 0;
1343 for (int i
=3; isdigit(version
[i
]); ++i
) {
1344 minorVersion
= minorVersion
*10 + (version
[i
] - '0');
1346 if ( minorVersion
> 255 ) {
1347 warning("Mac OS X minor version > 255 in '%s'", version
);
1350 fMacVersionMin
= (ld::MacVersionMin
)(0x000A0000 | (minorVersion
<< 8));
1353 warning("unknown option to -macosx_version_min, not 10.x");
1357 void Options::setIOSVersionMin(const char* version
)
1359 if ( version
== NULL
)
1360 throw "-ios_version_min argument missing";
1361 if ( ! isdigit(version
[0]) )
1362 throw "-ios_version_min argument is not a number";
1363 if ( version
[1] != '.' )
1364 throw "-ios_version_min argument is missing period as second character";
1365 if ( ! isdigit(version
[2]) )
1366 throw "-ios_version_min argument is not a number";
1368 unsigned int majorVersion
= version
[0] - '0';
1369 unsigned int minorVersion
= version
[2] - '0';
1370 fIOSVersionMin
= (ld::IOSVersionMin
)((majorVersion
<< 16) | (minorVersion
<< 8));
1373 bool Options::minOS(ld::MacVersionMin requiredMacMin
, ld::IOSVersionMin requirediPhoneOSMin
)
1375 if ( fMacVersionMin
!= ld::macVersionUnset
) {
1376 return ( fMacVersionMin
>= requiredMacMin
);
1379 return ( fIOSVersionMin
>= requirediPhoneOSMin
);
1384 void Options::setWeakReferenceMismatchTreatment(const char* treatment
)
1386 if ( treatment
== NULL
)
1387 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1389 if ( strcmp(treatment
, "error") == 0 )
1390 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchError
;
1391 else if ( strcmp(treatment
, "weak") == 0 )
1392 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchWeak
;
1393 else if ( strcmp(treatment
, "non-weak") == 0 )
1394 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchNonWeak
;
1396 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1399 Options::CommonsMode
Options::parseCommonsTreatment(const char* mode
)
1402 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1404 if ( strcmp(mode
, "ignore_dylibs") == 0 )
1405 return kCommonsIgnoreDylibs
;
1406 else if ( strcmp(mode
, "use_dylibs") == 0 )
1407 return kCommonsOverriddenByDylibs
;
1408 else if ( strcmp(mode
, "error") == 0 )
1409 return kCommonsConflictsDylibsError
;
1411 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1414 void Options::addDylibOverride(const char* paths
)
1416 if ( paths
== NULL
)
1417 throw "-dylib_file must followed by two colon separated paths";
1418 const char* colon
= strchr(paths
, ':');
1419 if ( colon
== NULL
)
1420 throw "-dylib_file must followed by two colon separated paths";
1421 int len
= colon
-paths
;
1422 char* target
= new char[len
+2];
1423 strncpy(target
, paths
, len
);
1425 DylibOverride entry
;
1426 entry
.installName
= target
;
1427 entry
.useInstead
= &colon
[1];
1428 fDylibOverrides
.push_back(entry
);
1431 uint64_t Options::parseAddress(const char* addr
)
1434 uint64_t result
= strtoull(addr
, &endptr
, 16);
1438 uint32_t Options::parseProtection(const char* prot
)
1440 uint32_t result
= 0;
1441 for(const char* p
= prot
; *p
!= '\0'; ++p
) {
1442 switch(tolower(*p
)) {
1444 result
|= VM_PROT_READ
;
1447 result
|= VM_PROT_WRITE
;
1450 result
|= VM_PROT_EXECUTE
;
1455 throwf("unknown -segprot lettter in %s", prot
);
1463 // Parses number of form A[.B[.B[.D[.E]]]] into a uint64_t where the bits are a24.b10.c10.d10.e10
1465 uint64_t Options::parseVersionNumber64(const char* versionString
)
1473 a
= strtoul(versionString
, &end
, 10);
1474 if ( *end
== '.' ) {
1475 b
= strtoul(&end
[1], &end
, 10);
1476 if ( *end
== '.' ) {
1477 c
= strtoul(&end
[1], &end
, 10);
1478 if ( *end
== '.' ) {
1479 d
= strtoul(&end
[1], &end
, 10);
1480 if ( *end
== '.' ) {
1481 e
= strtoul(&end
[1], &end
, 10);
1486 if ( (*end
!= '\0') || (a
> 0xFFFFFF) || (b
> 0x3FF) || (c
> 0x3FF) || (d
> 0x3FF) || (e
> 0x3FF) )
1487 throwf("malformed 64-bit a.b.c.d.e version number: %s", versionString
);
1489 return (a
<< 40) | ( b
<< 30 ) | ( c
<< 20 ) | ( d
<< 10 ) | e
;
1493 uint32_t Options::currentVersion32() const
1495 // warn if it does not fit into 32 bit vers number
1496 uint32_t a
= (fDylibCurrentVersion
>> 40) & 0xFFFF;
1497 uint32_t b
= (fDylibCurrentVersion
>> 30) & 0xFF;
1498 uint32_t c
= (fDylibCurrentVersion
>> 20) & 0xFF;
1499 uint64_t rep32
= ((uint64_t)a
<< 40) | ((uint64_t)b
<< 30) | ((uint64_t)c
<< 20);
1500 if ( rep32
!= fDylibCurrentVersion
) {
1501 warning("truncating -current_version to fit in 32-bit space used by old mach-o format");
1502 a
= (fDylibCurrentVersion
>> 40) & 0xFFFFFF;
1505 b
= (fDylibCurrentVersion
>> 30) & 0x3FF;
1508 c
= (fDylibCurrentVersion
>> 20) & 0x3FF;
1512 return (a
<< 16) | ( b
<< 8 ) | c
;
1516 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1518 uint32_t Options::parseVersionNumber32(const char* versionString
)
1524 x
= strtoul(versionString
, &end
, 10);
1525 if ( *end
== '.' ) {
1526 y
= strtoul(&end
[1], &end
, 10);
1527 if ( *end
== '.' ) {
1528 z
= strtoul(&end
[1], &end
, 10);
1531 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
1532 throwf("malformed 32-bit x.y.z version number: %s", versionString
);
1534 return (x
<< 16) | ( y
<< 8 ) | z
;
1537 static const char* cstringSymbolName(const char* orderFileString
)
1540 asprintf(&result
, "cstring=%s", orderFileString
);
1541 // convert escaped characters
1543 for(const char* s
=result
; *s
!= '\0'; ++s
, ++d
) {
1581 // hexadecimal value of char
1585 while ( isxdigit(*s
) ) {
1590 value
+= ((toupper(*s
)-'A') + 10);
1597 if ( isdigit(*s
) ) {
1598 // octal value of char
1600 while ( isdigit(*s
) ) {
1601 value
= (value
<< 3) + (*s
-'0');
1616 void Options::parseOrderFile(const char* path
, bool cstring
)
1618 // order files override auto-ordering
1619 fAutoOrderInitializers
= false;
1621 // read in whole file
1622 int fd
= ::open(path
, O_RDONLY
, 0);
1624 throwf("can't open order file: %s", path
);
1625 struct stat stat_buf
;
1626 ::fstat(fd
, &stat_buf
);
1627 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1629 throwf("can't process order file: %s", path
);
1630 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1631 throwf("can't read order file: %s", path
);
1633 p
[stat_buf
.st_size
] = '\n';
1634 if ( this->dumpDependencyInfo() )
1635 this->dumpDependency(Options::depMisc
, path
);
1637 // parse into vector of pairs
1638 char * const end
= &p
[stat_buf
.st_size
+1];
1639 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1640 char* symbolStart
= NULL
;
1641 for (char* s
= p
; s
< end
; ++s
) {
1647 else if ( !isspace(*s
) || cstring
) {
1653 if ( (*s
== '\n') || (!cstring
&& (*s
== '#')) ) {
1654 bool wasComment
= (*s
== '#');
1656 // removing any trailing spaces
1658 while ( isspace(*last
) ) {
1662 // if there is an architecture prefix, only use this symbol it if matches current arch
1663 if ( strncmp(symbolStart
, "ppc:", 4) == 0 ) {
1666 else if ( strncmp(symbolStart
, "ppc64:", 6) == 0 ) {
1669 else if ( strncmp(symbolStart
, "i386:", 5) == 0 ) {
1670 if ( fArchitecture
== CPU_TYPE_I386
)
1671 symbolStart
= &symbolStart
[5];
1675 else if ( strncmp(symbolStart
, "x86_64:", 7) == 0 ) {
1676 if ( fArchitecture
== CPU_TYPE_X86_64
)
1677 symbolStart
= &symbolStart
[7];
1681 else if ( strncmp(symbolStart
, "arm:", 4) == 0 ) {
1682 if ( fArchitecture
== CPU_TYPE_ARM
)
1683 symbolStart
= &symbolStart
[4];
1687 if ( symbolStart
!= NULL
) {
1688 char* objFileName
= NULL
;
1689 char* colon
= strstr(symbolStart
, ".o:");
1690 if ( colon
!= NULL
) {
1692 objFileName
= symbolStart
;
1693 symbolStart
= &colon
[3];
1696 colon
= strstr(symbolStart
, ".o):");
1697 if ( colon
!= NULL
) {
1699 objFileName
= symbolStart
;
1700 symbolStart
= &colon
[4];
1703 // trim leading spaces
1704 while ( isspace(*symbolStart
) )
1706 Options::OrderedSymbol pair
;
1708 pair
.symbolName
= cstringSymbolName(symbolStart
);
1710 pair
.symbolName
= symbolStart
;
1711 pair
.objectFileName
= objFileName
;
1712 fOrderedSymbols
.push_back(pair
);
1727 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1730 void Options::parseSectionOrderFile(const char* segment
, const char* section
, const char* path
)
1732 if ( (strcmp(section
, "__cstring") == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1733 parseOrderFile(path
, true);
1735 else if ( (strncmp(section
, "__literal",9) == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1736 warning("sorting of __literal[4,8,16] sections not supported");
1739 // ignore section information and append all symbol names to global order file
1740 parseOrderFile(path
, false);
1744 void Options::addSection(const char* segment
, const char* section
, const char* path
)
1746 if ( strlen(segment
) > 16 )
1747 throw "-seccreate segment name max 16 chars";
1748 if ( strlen(section
) > 16 ) {
1749 char* tmp
= strdup(section
);
1751 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section
, tmp
);
1755 // read in whole file
1756 int fd
= ::open(path
, O_RDONLY
, 0);
1758 throwf("can't open -sectcreate file: %s", path
);
1759 struct stat stat_buf
;
1760 ::fstat(fd
, &stat_buf
);
1761 char* p
= (char*)malloc(stat_buf
.st_size
);
1763 throwf("can't process -sectcreate file: %s", path
);
1764 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1765 throwf("can't read -sectcreate file: %s", path
);
1768 // record section to create
1769 ExtraSection info
= { segment
, section
, path
, (uint8_t*)p
, stat_buf
.st_size
};
1770 fExtraSections
.push_back(info
);
1773 void Options::addSectionRename(const char* srcSegment
, const char* srcSection
, const char* dstSegment
, const char* dstSection
)
1775 if ( strlen(srcSegment
) > 16 )
1776 throw "-rename_section segment name max 16 chars";
1777 if ( strlen(srcSection
) > 16 )
1778 throw "-rename_section section name max 16 chars";
1779 if ( strlen(dstSegment
) > 16 )
1780 throw "-rename_section segment name max 16 chars";
1781 if ( strlen(dstSection
) > 16 )
1782 throw "-rename_section section name max 16 chars";
1785 info
.fromSegment
= srcSegment
;
1786 info
.fromSection
= srcSection
;
1787 info
.toSegment
= dstSegment
;
1788 info
.toSection
= dstSection
;
1790 fSectionRenames
.push_back(info
);
1794 void Options::addSegmentRename(const char* srcSegment
, const char* dstSegment
)
1796 if ( strlen(srcSegment
) > 16 )
1797 throw "-rename_segment segment name max 16 chars";
1798 if ( strlen(dstSegment
) > 16 )
1799 throw "-rename_segment segment name max 16 chars";
1802 info
.fromSegment
= srcSegment
;
1803 info
.toSegment
= dstSegment
;
1805 fSegmentRenames
.push_back(info
);
1810 void Options::addSymbolMove(const char* dstSegment
, const char* symbolList
,
1811 std::vector
<SymbolsMove
>& list
, const char* optionName
)
1813 if ( strlen(dstSegment
) > 16 )
1814 throwf("%s segment name max 16 chars", optionName
);
1817 list
.push_back(tmp
);
1818 SymbolsMove
& info
= list
.back();
1819 info
.toSegment
= dstSegment
;
1820 loadExportFile(symbolList
, optionName
, info
.symbols
);
1823 bool Options::moveRwSymbol(const char* symName
, const char* filePath
, const char*& seg
, bool& wildCardMatch
) const
1825 for (std::vector
<SymbolsMove
>::const_iterator it
=fSymbolsMovesData
.begin(); it
!= fSymbolsMovesData
.end(); ++it
) {
1826 const SymbolsMove
& info
= *it
;
1827 if ( info
.symbols
.containsWithPrefix(symName
, filePath
, wildCardMatch
)) {
1828 seg
= info
.toSegment
;
1835 bool Options::moveRoSymbol(const char* symName
, const char* filePath
, const char*& seg
, bool& wildCardMatch
) const
1837 for (std::vector
<SymbolsMove
>::const_iterator it
=fSymbolsMovesCode
.begin(); it
!= fSymbolsMovesCode
.end(); ++it
) {
1838 const SymbolsMove
& info
= *it
;
1839 if ( info
.symbols
.containsWithPrefix(symName
, filePath
, wildCardMatch
)) {
1840 seg
= info
.toSegment
;
1847 void Options::addSectionAlignment(const char* segment
, const char* section
, const char* alignmentStr
)
1849 if ( strlen(segment
) > 16 )
1850 throw "-sectalign segment name max 16 chars";
1851 if ( strlen(section
) > 16 )
1852 throw "-sectalign section name max 16 chars";
1854 // argument to -sectalign is a hexadecimal number
1856 unsigned long value
= strtoul(alignmentStr
, &endptr
, 16);
1857 if ( *endptr
!= '\0')
1858 throw "argument for -sectalign is not a hexadecimal number";
1859 if ( value
> 0x8000 )
1860 throw "argument for -sectalign must be less than or equal to 0x8000";
1862 warning("zero is not a valid -sectalign");
1866 // alignment is power of 2 (e.g. page alignment = 12)
1867 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
1868 if ( (unsigned long)(1 << alignment
) != value
) {
1869 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
1870 segment
, section
, 1 << alignment
);
1873 SectionAlignment info
= { segment
, section
, alignment
};
1874 fSectionAlignments
.push_back(info
);
1877 void Options::addLibrary(const FileInfo
& info
)
1879 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
1880 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
1881 if ( strcmp(info
.path
, fit
->path
) == 0 ) {
1882 // if dylib is specified again but weak, record that it should be weak
1883 if ( info
.options
.fWeakImport
)
1884 fit
->options
.fWeakImport
= true;
1889 fInputFiles
.push_back(info
);
1892 void Options::warnObsolete(const char* arg
)
1894 warning("option %s is obsolete and being ignored", arg
);
1901 // Process all command line arguments.
1903 // The only error checking done here is that each option is valid and if it has arguments
1904 // that they too are valid.
1906 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
1907 // whichever was last on the command line is used.
1909 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
1911 void Options::parse(int argc
, const char* argv
[])
1913 // Store the original args in the link snapshot.
1914 fLinkSnapshot
.recordRawArgs(argc
, argv
);
1916 // pass one builds search list from -L and -F options
1917 this->buildSearchPaths(argc
, argv
);
1919 // reduce re-allocations
1920 fInputFiles
.reserve(32);
1922 // pass two parse all other options
1923 for(int i
=1; i
< argc
; ++i
) {
1924 const char* arg
= argv
[i
];
1926 if ( arg
[0] == '-' ) {
1927 // by default, copy one arg to the snapshot link command, and do no file copying
1928 int snapshotArgIndex
= i
;
1929 int snapshotArgCount
= -1; // -1 means compute count based on change in index
1930 int snapshotFileArgIndex
= -1; // -1 means no data file parameter to arg
1932 // Since we don't care about the files passed, just the option names, we do this here.
1934 fprintf (stderr
, "[Logging ld64 options]\t%s\n", arg
);
1936 if ( (arg
[1] == 'L') || (arg
[1] == 'F') ) {
1937 snapshotArgCount
= 0; // stripped out of link snapshot
1940 // previously handled by buildSearchPaths()
1942 // The one gnu style option we have to keep compatibility
1943 // with gcc. Might as well have the single hyphen one as well.
1944 else if ( (strcmp(arg
, "--help") == 0)
1945 || (strcmp(arg
, "-help") == 0)) {
1946 fprintf (stdout
, "ld64: For information on command line options please use 'man ld'.\n");
1949 else if ( strcmp(arg
, "-arch") == 0 ) {
1950 parseArch(argv
[++i
]);
1952 else if ( strcmp(arg
, "-dynamic") == 0 ) {
1955 else if ( strcmp(arg
, "-static") == 0 ) {
1957 if ( (fOutputKind
!= kObjectFile
) && (fOutputKind
!= kKextBundle
) ) {
1958 fOutputKind
= kStaticExecutable
;
1961 else if ( strcmp(arg
, "-dylib") == 0 ) {
1962 fOutputKind
= kDynamicLibrary
;
1964 else if ( strcmp(arg
, "-bundle") == 0 ) {
1965 fOutputKind
= kDynamicBundle
;
1967 else if ( strcmp(arg
, "-dylinker") == 0 ) {
1968 fOutputKind
= kDyld
;
1970 else if ( strcmp(arg
, "-execute") == 0 ) {
1971 if ( fOutputKind
!= kStaticExecutable
)
1972 fOutputKind
= kDynamicExecutable
;
1974 else if ( strcmp(arg
, "-preload") == 0 ) {
1975 fOutputKind
= kPreload
;
1977 else if ( strcmp(arg
, "-r") == 0 ) {
1978 fOutputKind
= kObjectFile
;
1980 else if ( strcmp(arg
, "-kext") == 0 ) {
1981 fOutputKind
= kKextBundle
;
1983 else if ( strcmp(arg
, "-o") == 0 ) {
1984 snapshotArgCount
= 0;
1985 fOutputFile
= argv
[++i
];
1986 fLinkSnapshot
.setSnapshotName(fOutputFile
);
1988 else if ( strncmp(arg
, "-lazy-l", 7) == 0 ) {
1989 snapshotArgCount
= 0;
1990 FileInfo info
= findLibrary(&arg
[7], true);
1991 info
.options
.fLazyLoad
= true;
1992 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
1994 fUsingLazyDylibLinking
= true;
1996 else if ( strcmp(arg
, "-lto_library") == 0 ) {
1997 snapshotFileArgIndex
= 1;
1998 fOverridePathlibLTO
= argv
[++i
];
1999 if ( fOverridePathlibLTO
== NULL
)
2000 throw "missing argument to -lto_library";
2002 else if ( (arg
[1] == 'l') && (strncmp(arg
,"-lazy_",6) !=0) ) {
2003 snapshotArgCount
= 0;
2004 FileInfo info
= findLibrary(&arg
[2]);
2005 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2008 // This causes a dylib to be weakly bound at
2009 // link time. This corresponds to weak_import.
2010 else if ( strncmp(arg
, "-weak-l", 7) == 0 ) {
2011 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2012 snapshotArgCount
= 0;
2013 FileInfo info
= findLibrary(&arg
[7]);
2014 info
.options
.fWeakImport
= true;
2015 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2018 // Avoid lazy binding.
2019 else if ( strcmp(arg
, "-bind_at_load") == 0 ) {
2022 else if ( strcmp(arg
, "-twolevel_namespace") == 0 ) {
2023 fNameSpace
= kTwoLevelNameSpace
;
2025 else if ( strcmp(arg
, "-flat_namespace") == 0 ) {
2026 fNameSpace
= kFlatNameSpace
;
2028 // Also sets a bit to ensure dyld causes everything
2029 // in the namespace to be flat.
2031 else if ( strcmp(arg
, "-force_flat_namespace") == 0 ) {
2032 fNameSpace
= kForceFlatNameSpace
;
2034 // Similar to --whole-archive.
2035 else if ( strcmp(arg
, "-all_load") == 0 ) {
2036 fFullyLoadArchives
= true;
2038 else if ( strcmp(arg
, "-noall_load") == 0) {
2041 // Similar to -all_load
2042 else if ( strcmp(arg
, "-ObjC") == 0 ) {
2043 fLoadAllObjcObjectsFromArchives
= true;
2045 // Similar to -all_load, but for the following archive only.
2046 else if ( strcmp(arg
, "-force_load") == 0 ) {
2047 FileInfo info
= findFile(argv
[++i
]);
2048 info
.options
.fForceLoad
= true;
2049 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2052 // Library versioning.
2053 else if ( (strcmp(arg
, "-dylib_compatibility_version") == 0)
2054 || (strcmp(arg
, "-compatibility_version") == 0)) {
2055 const char* vers
= argv
[++i
];
2057 throw "-dylib_compatibility_version missing <version>";
2058 fDylibCompatVersion
= parseVersionNumber32(vers
);
2060 else if ( (strcmp(arg
, "-dylib_current_version") == 0)
2061 || (strcmp(arg
, "-current_version") == 0)) {
2062 const char* vers
= argv
[++i
];
2064 throw "-dylib_current_version missing <version>";
2065 fDylibCurrentVersion
= parseVersionNumber64(vers
);
2067 else if ( strcmp(arg
, "-sectorder") == 0 ) {
2068 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2069 throw "-sectorder missing <segment> <section> <file-path>";
2070 snapshotFileArgIndex
= 3;
2071 parseSectionOrderFile(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2074 else if ( strcmp(arg
, "-order_file") == 0 ) {
2075 snapshotFileArgIndex
= 1;
2076 parseOrderFile(argv
[++i
], false);
2078 else if ( strcmp(arg
, "-order_file_statistics") == 0 ) {
2079 fPrintOrderFileStatistics
= true;
2081 // ??? Deprecate segcreate.
2082 // -sectcreate puts whole files into a section in the output.
2083 else if ( (strcmp(arg
, "-sectcreate") == 0) || (strcmp(arg
, "-segcreate") == 0) ) {
2084 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2085 throw "-sectcreate missing <segment> <section> <file-path>";
2086 snapshotFileArgIndex
= 3;
2087 addSection(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2090 // Since we have a full path in binary/library names we need to be able to override it.
2091 else if ( (strcmp(arg
, "-dylib_install_name") == 0)
2092 || (strcmp(arg
, "-dylinker_install_name") == 0)
2093 || (strcmp(arg
, "-install_name") == 0)) {
2094 fDylibInstallName
= argv
[++i
];
2095 if ( fDylibInstallName
== NULL
)
2096 throw "-install_name missing <path>";
2098 // Sets the base address of the output.
2099 else if ( (strcmp(arg
, "-seg1addr") == 0) || (strcmp(arg
, "-image_base") == 0) ) {
2100 const char* address
= argv
[++i
];
2101 if ( address
== NULL
)
2102 throwf("%s missing <address>", arg
);
2103 fBaseAddress
= parseAddress(address
);
2104 uint64_t temp
= ((fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
2105 if ( fBaseAddress
!= temp
) {
2106 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment
);
2107 fBaseAddress
= temp
;
2110 else if ( strcmp(arg
, "-e") == 0 ) {
2111 fEntryName
= argv
[++i
];
2113 // Same as -@ from the FSF linker.
2114 else if ( strcmp(arg
, "-filelist") == 0 ) {
2115 snapshotArgCount
= 0;
2116 const char* path
= argv
[++i
];
2117 if ( (path
== NULL
) || (path
[0] == '-') )
2118 throw "-filelist missing <path>";
2119 ld::File::Ordinal baseOrdinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2120 loadFileList(path
, baseOrdinal
);
2122 else if ( strcmp(arg
, "-keep_private_externs") == 0 ) {
2123 fKeepPrivateExterns
= true;
2125 else if ( strcmp(arg
, "-final_output") == 0 ) {
2126 fFinalName
= argv
[++i
];
2128 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
2129 // just ensures that this happens for cross object file boundaries.
2130 else if ( (strcmp(arg
, "-interposable") == 0) || (strcmp(arg
, "-multi_module") == 0)) {
2131 switch ( fInterposeMode
) {
2132 case kInterposeNone
:
2133 case kInterposeAllExternal
:
2134 fInterposeMode
= kInterposeAllExternal
;
2136 case kInterposeSome
:
2137 // do nothing, -interposable_list overrides -interposable"
2141 else if ( strcmp(arg
, "-interposable_list") == 0 ) {
2142 snapshotFileArgIndex
= 1;
2143 fInterposeMode
= kInterposeSome
;
2144 loadExportFile(argv
[++i
], "-interposable_list", fInterposeList
);
2146 // Default for -interposable/-multi_module/-single_module.
2147 else if ( strcmp(arg
, "-single_module") == 0 ) {
2148 fInterposeMode
= kInterposeNone
;
2150 else if ( strcmp(arg
, "-exported_symbols_list") == 0 ) {
2151 snapshotFileArgIndex
= 1;
2152 if ( fExportMode
== kDontExportSome
)
2153 throw "can't use -exported_symbols_list and -unexported_symbols_list";
2154 fExportMode
= kExportSome
;
2155 loadExportFile(argv
[++i
], "-exported_symbols_list", fExportSymbols
);
2157 else if ( strcmp(arg
, "-unexported_symbols_list") == 0 ) {
2158 snapshotFileArgIndex
= 1;
2159 if ( fExportMode
== kExportSome
)
2160 throw "can't use -unexported_symbols_list and -exported_symbols_list";
2161 fExportMode
= kDontExportSome
;
2162 loadExportFile(argv
[++i
], "-unexported_symbols_list", fDontExportSymbols
);
2164 else if ( strcmp(arg
, "-exported_symbol") == 0 ) {
2165 if ( fExportMode
== kDontExportSome
)
2166 throw "can't use -exported_symbol and -unexported_symbols";
2167 fExportMode
= kExportSome
;
2168 fExportSymbols
.insert(argv
[++i
]);
2170 else if ( strcmp(arg
, "-unexported_symbol") == 0 ) {
2171 if ( fExportMode
== kExportSome
)
2172 throw "can't use -unexported_symbol and -exported_symbol";
2173 fExportMode
= kDontExportSome
;
2174 fDontExportSymbols
.insert(argv
[++i
]);
2176 else if ( strcmp(arg
, "-non_global_symbols_no_strip_list") == 0 ) {
2177 snapshotFileArgIndex
= 1;
2178 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveExclude
)
2179 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2180 fLocalSymbolHandling
= kLocalSymbolsSelectiveInclude
;
2181 loadExportFile(argv
[++i
], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded
);
2183 else if ( strcmp(arg
, "-non_global_symbols_strip_list") == 0 ) {
2184 snapshotFileArgIndex
= 1;
2185 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveInclude
)
2186 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2187 fLocalSymbolHandling
= kLocalSymbolsSelectiveExclude
;
2188 loadExportFile(argv
[++i
], "-non_global_symbols_strip_list", fLocalSymbolsExcluded
);
2191 else if ( strcmp(arg
, "-no_arch_warnings") == 0 ) {
2192 fIgnoreOtherArchFiles
= true;
2194 else if ( strcmp(arg
, "-force_cpusubtype_ALL") == 0 ) {
2195 fForceSubtypeAll
= true;
2196 fAllowCpuSubtypeMismatches
= true;
2198 // Similar to -weak-l but uses the absolute path name to the library.
2199 else if ( strcmp(arg
, "-weak_library") == 0 ) {
2200 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2201 snapshotArgCount
= 0;
2202 FileInfo info
= findFile(argv
[++i
]);
2203 info
.options
.fWeakImport
= true;
2204 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2207 else if ( strcmp(arg
, "-lazy_library") == 0 ) {
2208 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2209 snapshotArgCount
= 0;
2210 FileInfo info
= findFile(argv
[++i
]);
2211 info
.options
.fLazyLoad
= true;
2212 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2214 fUsingLazyDylibLinking
= true;
2216 else if ( strcmp(arg
, "-framework") == 0 ) {
2217 snapshotArgCount
= 0;
2218 FileInfo info
= findFramework(argv
[++i
]);
2219 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2222 else if ( strcmp(arg
, "-weak_framework") == 0 ) {
2223 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2224 snapshotArgCount
= 0;
2225 FileInfo info
= findFramework(argv
[++i
]);
2226 info
.options
.fWeakImport
= true;
2227 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2230 else if ( strcmp(arg
, "-lazy_framework") == 0 ) {
2231 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2232 snapshotArgCount
= 0;
2233 FileInfo info
= findFramework(argv
[++i
]);
2234 info
.options
.fLazyLoad
= true;
2235 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2237 fUsingLazyDylibLinking
= true;
2239 else if ( strcmp(arg
, "-search_paths_first") == 0 ) {
2240 // previously handled by buildSearchPaths()
2242 else if ( strcmp(arg
, "-search_dylibs_first") == 0 ) {
2243 // previously handled by buildSearchPaths()
2245 else if ( strcmp(arg
, "-undefined") == 0 ) {
2246 setUndefinedTreatment(argv
[++i
]);
2248 // Debugging output flag.
2249 else if ( strcmp(arg
, "-arch_multiple") == 0 ) {
2250 fMessagesPrefixedWithArchitecture
= true;
2252 // Specify what to do with relocations in read only
2253 // sections like .text. Could be errors, warnings,
2254 // or suppressed. Currently we do nothing with the
2256 else if ( strcmp(arg
, "-read_only_relocs") == 0 ) {
2257 switch ( parseTreatment(argv
[++i
]) ) {
2260 throw "-read_only_relocs missing [ warning | error | suppress ]";
2262 fWarnTextRelocs
= true;
2263 fAllowTextRelocs
= true;
2266 fWarnTextRelocs
= false;
2267 fAllowTextRelocs
= true;
2270 fWarnTextRelocs
= false;
2271 fAllowTextRelocs
= false;
2275 else if ( strcmp(arg
, "-sect_diff_relocs") == 0 ) {
2279 // Warn, error or make strong a mismatch between weak
2280 // and non-weak references.
2281 else if ( strcmp(arg
, "-weak_reference_mismatches") == 0 ) {
2282 setWeakReferenceMismatchTreatment(argv
[++i
]);
2284 // For a deployment target of 10.3 and earlier ld64 will
2285 // prebind an executable with 0s in all addresses that
2286 // are prebound. This can then be fixed up by update_prebinding
2287 // later. Prebinding is less useful on 10.4 and greater.
2288 else if ( strcmp(arg
, "-prebind") == 0 ) {
2291 else if ( strcmp(arg
, "-noprebind") == 0 ) {
2295 else if ( strcmp(arg
, "-prebind_allow_overlap") == 0 ) {
2298 else if ( strcmp(arg
, "-prebind_all_twolevel_modules") == 0 ) {
2301 else if ( strcmp(arg
, "-noprebind_all_twolevel_modules") == 0 ) {
2304 else if ( strcmp(arg
, "-nofixprebinding") == 0 ) {
2307 // This should probably be deprecated when we respect -L and -F
2308 // when searching for libraries.
2309 else if ( strcmp(arg
, "-dylib_file") == 0 ) {
2310 // ignore for snapshot because a stub dylib will be created in the snapshot
2311 snapshotArgCount
= 0;
2312 addDylibOverride(argv
[++i
]);
2314 // What to expand @executable_path to if found in dependent dylibs
2315 else if ( strcmp(arg
, "-executable_path") == 0 ) {
2316 fExecutablePath
= argv
[++i
];
2317 if ( (fExecutablePath
== NULL
) || (fExecutablePath
[0] == '-') )
2318 throw "-executable_path missing <path>";
2319 // if a directory was passed, add / to end
2320 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2321 struct stat statBuffer
;
2322 if ( stat(fExecutablePath
, &statBuffer
) == 0 ) {
2323 if ( (statBuffer
.st_mode
& S_IFMT
) == S_IFDIR
) {
2324 char* pathWithSlash
= new char[strlen(fExecutablePath
)+2];
2325 strcpy(pathWithSlash
, fExecutablePath
);
2326 strcat(pathWithSlash
, "/");
2327 fExecutablePath
= pathWithSlash
;
2331 // Aligns all segments to the power of 2 boundary specified.
2332 else if ( strcmp(arg
, "-segalign") == 0 ) {
2333 const char* size
= argv
[++i
];
2335 throw "-segalign missing <size>";
2336 fSegmentAlignment
= parseAddress(size
);
2337 uint8_t alignment
= (uint8_t)__builtin_ctz(fSegmentAlignment
);
2338 uint32_t p2aligned
= (1 << alignment
);
2339 if ( p2aligned
!= fSegmentAlignment
) {
2340 warning("alignment for -segalign %s is not a power of two, using 0x%X", size
, p2aligned
);
2341 fSegmentAlignment
= p2aligned
;
2344 // Puts a specified segment at a particular address that must
2345 // be a multiple of the segment alignment.
2346 else if ( strcmp(arg
, "-segaddr") == 0 ) {
2348 seg
.name
= argv
[++i
];
2349 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2350 throw "-segaddr missing segName Adddress";
2351 seg
.address
= parseAddress(argv
[++i
]);
2352 uint64_t temp
= ((seg
.address
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
2353 if ( seg
.address
!= temp
)
2354 warning("-segaddr %s not %lld byte aligned", seg
.name
, fSegmentAlignment
);
2355 fCustomSegmentAddresses
.push_back(seg
);
2357 // ??? Deprecate when we deprecate split-seg.
2358 else if ( strcmp(arg
, "-segs_read_only_addr") == 0 ) {
2359 fBaseAddress
= parseAddress(argv
[++i
]);
2361 // ??? Deprecate when we deprecate split-seg.
2362 else if ( strcmp(arg
, "-segs_read_write_addr") == 0 ) {
2363 fBaseWritableAddress
= parseAddress(argv
[++i
]);
2366 // ??? Deprecate when we get rid of basing at build time.
2367 else if ( strcmp(arg
, "-seg_addr_table") == 0 ) {
2368 snapshotFileArgIndex
= 1;
2369 const char* name
= argv
[++i
];
2371 throw "-seg_addr_table missing argument";
2372 fSegAddrTablePath
= name
;
2374 else if ( strcmp(arg
, "-seg_addr_table_filename") == 0 ) {
2378 else if ( strcmp(arg
, "-segprot") == 0 ) {
2380 seg
.name
= argv
[++i
];
2381 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) || (argv
[i
+2] == NULL
) )
2382 throw "-segprot missing segName max-prot init-prot";
2383 seg
.max
= parseProtection(argv
[++i
]);
2384 seg
.init
= parseProtection(argv
[++i
]);
2385 fCustomSegmentProtections
.push_back(seg
);
2387 else if ( strcmp(arg
, "-pagezero_size") == 0 ) {
2388 const char* size
= argv
[++i
];
2390 throw "-pagezero_size missing <size>";
2391 fZeroPageSize
= parseAddress(size
);
2392 uint64_t temp
= fZeroPageSize
& (-4096); // page align
2393 if ( (fZeroPageSize
!= temp
) )
2394 warning("-pagezero_size not page aligned, rounding down");
2395 fZeroPageSize
= temp
;
2397 else if ( strcmp(arg
, "-stack_addr") == 0 ) {
2398 const char* address
= argv
[++i
];
2399 if ( address
== NULL
)
2400 throw "-stack_addr missing <address>";
2401 fStackAddr
= parseAddress(address
);
2403 else if ( strcmp(arg
, "-stack_size") == 0 ) {
2404 const char* size
= argv
[++i
];
2406 throw "-stack_size missing <address>";
2407 fStackSize
= parseAddress(size
);
2408 uint64_t temp
= fStackSize
& (-4096); // page align
2409 if ( (fStackSize
!= temp
) )
2410 warning("-stack_size not page aligned, rounding down");
2412 else if ( strcmp(arg
, "-allow_stack_execute") == 0 ) {
2413 fExecutableStack
= true;
2415 else if ( strcmp(arg
, "-allow_heap_execute") == 0 ) {
2416 fDisableNonExecutableHeap
= true;
2418 else if ( strcmp(arg
, "-sectalign") == 0 ) {
2419 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2420 throw "-sectalign missing <segment> <section> <file-path>";
2421 addSectionAlignment(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2424 else if ( strcmp(arg
, "-sectorder_detail") == 0 ) {
2427 else if ( strcmp(arg
, "-sectobjectsymbols") == 0 ) {
2431 else if ( strcmp(arg
, "-bundle_loader") == 0 ) {
2432 snapshotFileArgIndex
= 1;
2433 fBundleLoader
= argv
[++i
];
2434 if ( (fBundleLoader
== NULL
) || (fBundleLoader
[0] == '-') )
2435 throw "-bundle_loader missing <path>";
2436 FileInfo info
= findFile(fBundleLoader
);
2437 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2438 info
.options
.fBundleLoader
= true;
2439 fInputFiles
.push_back(info
);
2441 else if ( strcmp(arg
, "-private_bundle") == 0 ) {
2444 else if ( strcmp(arg
, "-twolevel_namespace_hints") == 0 ) {
2447 // Use this flag to set default behavior for deployement targets.
2448 else if ( strcmp(arg
, "-macosx_version_min") == 0 ) {
2449 const char* macVers
= argv
[++i
];
2450 const char* envMacVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
2451 const char* enviPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
2452 if ( (envMacVers
!= NULL
) && (enviPhoneVers
!= NULL
) ) {
2453 // <rdar://problem/13774329> when conflicting deployments set, break tie by looking at syslibroot
2454 warning("both MACOSX_DEPLOYMENT_TARGET and IPHONEOS_DEPLOYMENT_TARGET are set");
2455 if ( !fSDKPaths
.empty() ) {
2456 const char* sysrootPath
= fSDKPaths
.back();
2457 const char* lastSlash
= strrchr(sysrootPath
, '/');
2458 if ( strstr(lastSlash
, "Simulator") != NULL
)
2459 setIOSVersionMin(enviPhoneVers
);
2461 setMacOSXVersionMin(macVers
);
2464 setMacOSXVersionMin(macVers
);
2468 setMacOSXVersionMin(macVers
);
2471 else if ( (strcmp(arg
, "-ios_version_min") == 0) || (strcmp(arg
, "-iphoneos_version_min") == 0) ) {
2472 setIOSVersionMin(argv
[++i
]);
2474 else if ( strcmp(arg
, "-ios_simulator_version_min") == 0 ) {
2475 setIOSVersionMin(argv
[++i
]);
2476 fTargetIOSSimulator
= true;
2478 else if ( strcmp(arg
, "-multiply_defined") == 0 ) {
2479 //warnObsolete(arg);
2482 else if ( strcmp(arg
, "-multiply_defined_unused") == 0 ) {
2486 else if ( strcmp(arg
, "-nomultidefs") == 0 ) {
2489 // Display each file in which the argument symbol appears and whether
2490 // the file defines or references it. This option takes an argument
2491 // as -y<symbol> note that there is no space.
2492 else if ( strncmp(arg
, "-y", 2) == 0 ) {
2495 // Same output as -y, but output <arg> number of undefined symbols only.
2496 else if ( strcmp(arg
, "-Y") == 0 ) {
2497 //warnObsolete(arg);
2500 // This option affects all objects linked into the final result.
2501 else if ( strcmp(arg
, "-m") == 0 ) {
2504 else if ( (strcmp(arg
, "-why_load") == 0) || (strcmp(arg
, "-whyload") == 0) ) {
2507 else if ( strcmp(arg
, "-why_live") == 0 ) {
2508 const char* name
= argv
[++i
];
2510 throw "-why_live missing symbol name argument";
2511 fWhyLive
.insert(name
);
2513 else if ( strcmp(arg
, "-u") == 0 ) {
2514 const char* name
= argv
[++i
];
2516 throw "-u missing argument";
2517 fInitialUndefines
.push_back(name
);
2519 else if ( strcmp(arg
, "-U") == 0 ) {
2520 const char* name
= argv
[++i
];
2522 throw "-U missing argument";
2523 fAllowedUndefined
.insert(name
);
2525 else if ( strcmp(arg
, "-s") == 0 ) {
2527 fLocalSymbolHandling
= kLocalSymbolsNone
;
2528 fDebugInfoStripping
= Options::kDebugInfoNone
;
2530 else if ( strcmp(arg
, "-x") == 0 ) {
2531 fLocalSymbolHandling
= kLocalSymbolsNone
;
2533 else if ( strcmp(arg
, "-S") == 0 ) {
2534 fDebugInfoStripping
= Options::kDebugInfoNone
;
2536 else if ( strcmp(arg
, "-X") == 0 ) {
2539 else if ( strcmp(arg
, "-Si") == 0 ) {
2541 fDebugInfoStripping
= Options::kDebugInfoFull
;
2543 else if ( strcmp(arg
, "-b") == 0 ) {
2546 else if ( strcmp(arg
, "-Sn") == 0 ) {
2548 fDebugInfoStripping
= Options::kDebugInfoFull
;
2550 else if ( strcmp(arg
, "-Sp") == 0 ) {
2553 else if ( strcmp(arg
, "-dead_strip") == 0 ) {
2556 else if ( strcmp(arg
, "-no_dead_strip_inits_and_terms") == 0 ) {
2559 else if ( strcmp(arg
, "-w") == 0 ) {
2560 // previously handled by buildSearchPaths()
2562 else if ( strcmp(arg
, "-fatal_warnings") == 0 ) {
2563 // previously handled by buildSearchPaths()
2565 else if ( strcmp(arg
, "-arch_errors_fatal") == 0 ) {
2566 fErrorOnOtherArchFiles
= true;
2568 else if ( strcmp(arg
, "-M") == 0 ) {
2571 else if ( strcmp(arg
, "-headerpad") == 0 ) {
2572 const char* size
= argv
[++i
];
2574 throw "-headerpad missing argument";
2575 fMinimumHeaderPad
= parseAddress(size
);
2577 else if ( strcmp(arg
, "-headerpad_max_install_names") == 0 ) {
2578 fMaxMinimumHeaderPad
= true;
2580 else if ( strcmp(arg
, "-t") == 0 ) {
2581 fLogAllFiles
= true;
2583 else if ( strcmp(arg
, "-whatsloaded") == 0 ) {
2584 fLogObjectFiles
= true;
2586 else if ( strcmp(arg
, "-A") == 0 ) {
2590 else if ( strcmp(arg
, "-umbrella") == 0 ) {
2591 const char* name
= argv
[++i
];
2593 throw "-umbrella missing argument";
2594 fUmbrellaName
= name
;
2596 else if ( strcmp(arg
, "-allowable_client") == 0 ) {
2597 const char* name
= argv
[++i
];
2600 throw "-allowable_client missing argument";
2602 fAllowableClients
.push_back(name
);
2604 else if ( strcmp(arg
, "-client_name") == 0 ) {
2605 const char* name
= argv
[++i
];
2608 throw "-client_name missing argument";
2612 else if ( strcmp(arg
, "-sub_umbrella") == 0 ) {
2613 const char* name
= argv
[++i
];
2615 throw "-sub_umbrella missing argument";
2616 fSubUmbellas
.push_back(name
);
2618 else if ( strcmp(arg
, "-sub_library") == 0 ) {
2619 const char* name
= argv
[++i
];
2621 throw "-sub_library missing argument";
2622 fSubLibraries
.push_back(name
);
2624 else if ( strcmp(arg
, "-init") == 0 ) {
2625 const char* name
= argv
[++i
];
2627 throw "-init missing argument";
2628 fInitFunctionName
= name
;
2630 else if ( strcmp(arg
, "-dot") == 0 ) {
2631 const char* name
= argv
[++i
];
2633 throw "-dot missing argument";
2634 fDotOutputFile
= name
;
2636 else if ( strcmp(arg
, "-warn_commons") == 0 ) {
2637 fWarnCommons
= true;
2639 else if ( strcmp(arg
, "-commons") == 0 ) {
2640 fCommonsMode
= parseCommonsTreatment(argv
[++i
]);
2642 else if ( strcmp(arg
, "-keep_relocs") == 0 ) {
2643 fKeepRelocations
= true;
2645 else if ( strcmp(arg
, "-warn_stabs") == 0 ) {
2648 else if ( strcmp(arg
, "-pause") == 0 ) {
2651 else if ( strcmp(arg
, "-print_statistics") == 0 ) {
2654 else if ( strcmp(arg
, "-d") == 0 ) {
2655 fMakeTentativeDefinitionsReal
= true;
2657 else if ( strcmp(arg
, "-v") == 0 ) {
2658 // previously handled by buildSearchPaths()
2660 else if ( strcmp(arg
, "-Z") == 0 ) {
2661 // previously handled by buildSearchPaths()
2663 else if ( strcmp(arg
, "-syslibroot") == 0 ) {
2664 snapshotArgCount
= 0;
2666 // previously handled by buildSearchPaths()
2668 else if ( strcmp(arg
, "-no_uuid") == 0 ) {
2669 fUUIDMode
= kUUIDNone
;
2671 else if ( strcmp(arg
, "-random_uuid") == 0 ) {
2672 fUUIDMode
= kUUIDRandom
;
2674 else if ( strcmp(arg
, "-dtrace") == 0 ) {
2675 snapshotFileArgIndex
= 1;
2676 const char* name
= argv
[++i
];
2678 throw "-dtrace missing argument";
2679 fDtraceScriptName
= name
;
2681 else if ( strcmp(arg
, "-root_safe") == 0 ) {
2684 else if ( strcmp(arg
, "-setuid_safe") == 0 ) {
2687 else if ( strcmp(arg
, "-alias") == 0 ) {
2688 Options::AliasPair pair
;
2689 pair
.realName
= argv
[++i
];
2690 if ( pair
.realName
== NULL
)
2691 throw "missing argument to -alias";
2692 pair
.alias
= argv
[++i
];
2693 if ( pair
.alias
== NULL
)
2694 throw "missing argument to -alias";
2695 fAliases
.push_back(pair
);
2697 else if ( strcmp(arg
, "-alias_list") == 0 ) {
2698 snapshotFileArgIndex
= 1;
2699 parseAliasFile(argv
[++i
]);
2701 else if ( strcmp(arg
, "-save-temps") == 0 ) {
2702 fSaveTempFiles
= true;
2704 else if ( strcmp(arg
, "-rpath") == 0 ) {
2705 const char* path
= argv
[++i
];
2707 throw "missing argument to -rpath";
2708 fRPaths
.push_back(path
);
2710 else if ( strcmp(arg
, "-read_only_stubs") == 0 ) {
2711 fReadOnlyx86Stubs
= true;
2713 else if ( strcmp(arg
, "-slow_stubs") == 0 ) {
2716 else if ( strcmp(arg
, "-map") == 0 ) {
2717 fMapPath
= argv
[++i
];
2718 if ( fMapPath
== NULL
)
2719 throw "missing argument to -map";
2721 else if ( strcmp(arg
, "-pie") == 0 ) {
2722 fPositionIndependentExecutable
= true;
2723 fPIEOnCommandLine
= true;
2725 else if ( strcmp(arg
, "-no_pie") == 0 ) {
2726 fDisablePositionIndependentExecutable
= true;
2728 else if ( strncmp(arg
, "-reexport-l", 11) == 0 ) {
2729 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2730 snapshotArgCount
= 0;
2731 FileInfo info
= findLibrary(&arg
[11], true);
2732 info
.options
.fReExport
= true;
2733 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2736 else if ( strcmp(arg
, "-reexport_library") == 0 ) {
2737 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2738 snapshotArgCount
= 0;
2739 FileInfo info
= findFile(argv
[++i
]);
2740 info
.options
.fReExport
= true;
2741 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2744 else if ( strcmp(arg
, "-reexport_framework") == 0 ) {
2745 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2746 snapshotArgCount
= 0;
2747 FileInfo info
= findFramework(argv
[++i
]);
2748 info
.options
.fReExport
= true;
2749 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2752 else if ( strncmp(arg
, "-upward-l", 9) == 0 ) {
2753 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2754 snapshotArgCount
= 0;
2755 FileInfo info
= findLibrary(&arg
[9], true);
2756 info
.options
.fUpward
= true;
2757 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2760 else if ( strcmp(arg
, "-upward_library") == 0 ) {
2761 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2762 snapshotArgCount
= 0;
2763 FileInfo info
= findFile(argv
[++i
]);
2764 info
.options
.fUpward
= true;
2765 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2768 else if ( strcmp(arg
, "-upward_framework") == 0 ) {
2769 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2770 snapshotArgCount
= 0;
2771 FileInfo info
= findFramework(argv
[++i
]);
2772 info
.options
.fUpward
= true;
2773 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2776 else if ( strcmp(arg
, "-dead_strip_dylibs") == 0 ) {
2777 fDeadStripDylibs
= true;
2779 else if ( strcmp(arg
, "-no_implicit_dylibs") == 0 ) {
2780 fImplicitlyLinkPublicDylibs
= false;
2782 else if ( strcmp(arg
, "-new_linker") == 0 ) {
2785 else if ( strcmp(arg
, "-no_encryption") == 0 ) {
2786 fEncryptable
= false;
2788 else if ( strcmp(arg
, "-no_compact_unwind") == 0 ) {
2789 fAddCompactUnwindEncoding
= false;
2791 else if ( strcmp(arg
, "-mllvm") == 0 ) {
2792 const char* opts
= argv
[++i
];
2794 throw "missing argument to -mllvm";
2795 fLLVMOptions
.push_back(opts
);
2797 else if ( strcmp(arg
, "-mcpu") == 0 ) {
2798 const char* cpu
= argv
[++i
];
2800 throw "missing argument to -mcpu";
2803 else if ( strcmp(arg
, "-no_order_inits") == 0 ) {
2804 fAutoOrderInitializers
= false;
2806 else if ( strcmp(arg
, "-no_order_data") == 0 ) {
2809 else if ( strcmp(arg
, "-seg_page_size") == 0 ) {
2811 seg
.name
= argv
[++i
];
2812 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2813 throw "-seg_page_size missing segName Adddress";
2814 seg
.size
= parseAddress(argv
[++i
]);
2815 uint64_t temp
= seg
.size
& (-4096); // page align
2816 if ( (seg
.size
!= temp
) )
2817 warning("-seg_page_size %s not 4K aligned, rounding down", seg
.name
);
2818 fCustomSegmentSizes
.push_back(seg
);
2820 else if ( strcmp(arg
, "-mark_dead_strippable_dylib") == 0 ) {
2821 fMarkDeadStrippableDylib
= true;
2823 else if ( strcmp(arg
, "-exported_symbols_order") == 0 ) {
2824 snapshotFileArgIndex
= 1;
2825 loadSymbolOrderFile(argv
[++i
], fExportSymbolsOrder
);
2827 else if ( strcmp(arg
, "-no_compact_linkedit") == 0 ) {
2828 warnObsolete("-no_compact_linkedit");
2830 else if ( strcmp(arg
, "-no_eh_labels") == 0 ) {
2833 else if ( strcmp(arg
, "-warn_compact_unwind") == 0 ) {
2834 fWarnCompactUnwind
= true;
2836 else if ( strcmp(arg
, "-allow_sub_type_mismatches") == 0 ) {
2837 fAllowCpuSubtypeMismatches
= true;
2839 else if ( strcmp(arg
, "-no_zero_fill_sections") == 0 ) {
2840 fOptimizeZeroFill
= false;
2842 else if ( strcmp(arg
, "-merge_zero_fill_sections") == 0 ) {
2843 fMergeZeroFill
= true;
2845 else if ( strcmp(arg
, "-objc_abi_version") == 0 ) {
2846 const char* version
= argv
[++i
];
2847 if ( version
== NULL
)
2848 throw "-objc_abi_version missing version number";
2849 if ( strcmp(version
, "2") == 0 ) {
2850 fObjCABIVersion1Override
= false;
2851 fObjCABIVersion2Override
= true;
2853 else if ( strcmp(version
, "1") == 0 ) {
2854 fObjCABIVersion1Override
= true;
2855 fObjCABIVersion2Override
= false;
2858 warning("ignoring unrecognized argument (%s) to -objc_abi_version", version
);
2860 else if ( strcmp(arg
, "-warn_weak_exports") == 0 ) {
2861 fWarnWeakExports
= true;
2863 else if ( strcmp(arg
, "-objc_gc_compaction") == 0 ) {
2864 fObjcGcCompaction
= true;
2866 else if ( strcmp(arg
, "-objc_gc") == 0 ) {
2868 if ( fObjCGcOnly
) {
2869 warning("-objc_gc overriding -objc_gc_only");
2870 fObjCGcOnly
= false;
2873 else if ( strcmp(arg
, "-objc_gc_only") == 0 ) {
2876 warning("-objc_gc_only overriding -objc_gc");
2880 else if ( strcmp(arg
, "-demangle") == 0 ) {
2883 else if ( strcmp(arg
, "-version_load_command") == 0 ) {
2884 fVersionLoadCommandForcedOn
= true;
2885 fVersionLoadCommandForcedOff
= false;
2887 else if ( strcmp(arg
, "-no_version_load_command") == 0 ) {
2888 fVersionLoadCommandForcedOff
= true;
2889 fVersionLoadCommandForcedOn
= false;
2891 else if ( strcmp(arg
, "-function_starts") == 0 ) {
2892 fFunctionStartsForcedOn
= true;
2893 fFunctionStartsForcedOff
= false;
2895 else if ( strcmp(arg
, "-no_function_starts") == 0 ) {
2896 fFunctionStartsForcedOff
= true;
2897 fFunctionStartsForcedOn
= false;
2899 else if ( strcmp(arg
, "-no_data_in_code_info") == 0 ) {
2900 fDataInCodeInfoLoadCommandForcedOff
= true;
2901 fDataInCodeInfoLoadCommandForcedOn
= false;
2903 else if ( strcmp(arg
, "-data_in_code_info") == 0 ) {
2904 fDataInCodeInfoLoadCommandForcedOn
= true;
2905 fDataInCodeInfoLoadCommandForcedOff
= false;
2907 else if ( strcmp(arg
, "-object_path_lto") == 0 ) {
2908 fTempLtoObjectPath
= argv
[++i
];
2909 if ( fTempLtoObjectPath
== NULL
)
2910 throw "missing argument to -object_path_lto";
2912 else if ( strcmp(arg
, "-no_objc_category_merging") == 0 ) {
2913 fObjcCategoryMerging
= false;
2915 else if ( strcmp(arg
, "-force_symbols_weak_list") == 0 ) {
2916 snapshotFileArgIndex
= 1;
2917 loadExportFile(argv
[++i
], "-force_symbols_weak_list", fForceWeakSymbols
);
2919 else if ( strcmp(arg
, "-force_symbols_not_weak_list") == 0 ) {
2920 snapshotFileArgIndex
= 1;
2921 loadExportFile(argv
[++i
], "-force_symbols_not_weak_list", fForceNotWeakSymbols
);
2923 else if ( strcmp(arg
, "-force_symbol_weak") == 0 ) {
2924 const char* symbol
= argv
[++i
];
2925 if ( symbol
== NULL
)
2926 throw "-force_symbol_weak missing <symbol>";
2927 fForceWeakSymbols
.insert(symbol
);
2929 else if ( strcmp(arg
, "-force_symbol_not_weak") == 0 ) {
2930 const char* symbol
= argv
[++i
];
2931 if ( symbol
== NULL
)
2932 throw "-force_symbol_not_weak missing <symbol>";
2933 fForceNotWeakSymbols
.insert(symbol
);
2935 else if ( strcmp(arg
, "-reexported_symbols_list") == 0 ) {
2936 snapshotFileArgIndex
= 1;
2937 if ( fExportMode
== kExportSome
)
2938 throw "can't use -exported_symbols_list and -reexported_symbols_list";
2939 loadExportFile(argv
[++i
], "-reexported_symbols_list", fReExportSymbols
);
2941 else if ( strcmp(arg
, "-dyld_env") == 0 ) {
2942 const char* envarg
= argv
[++i
];
2943 if ( envarg
== NULL
)
2944 throw "-dyld_env missing ENV=VALUE";
2945 if ( strchr(envarg
, '=') == NULL
)
2946 throw "-dyld_env missing ENV=VALUE";
2947 fDyldEnvironExtras
.push_back(envarg
);
2949 else if ( strcmp(arg
, "-page_align_data_atoms") == 0 ) {
2950 fPageAlignDataAtoms
= true;
2952 else if (strcmp(arg
, "-debug_snapshot") == 0) {
2953 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
2954 fSnapshotRequested
= true;
2956 else if (strcmp(arg
, "-snapshot_dir") == 0) {
2957 const char* path
= argv
[++i
];
2959 throw "-snapshot_dir missing path";
2960 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
2961 fLinkSnapshot
.setSnapshotPath(path
);
2962 fSnapshotRequested
= true;
2964 else if ( strcmp(arg
, "-new_main") == 0 ) {
2965 fEntryPointLoadCommandForceOn
= true;
2967 else if ( strcmp(arg
, "-no_new_main") == 0 ) {
2968 fEntryPointLoadCommandForceOff
= true;
2970 else if ( strcmp(arg
, "-source_version") == 0 ) {
2971 const char* vers
= argv
[++i
];
2973 throw "-source_version missing <version>";
2974 fSourceVersion
= parseVersionNumber64(vers
);
2976 else if ( strcmp(arg
, "-add_source_version") == 0 ) {
2977 fSourceVersionLoadCommandForceOn
= true;
2979 else if ( strcmp(arg
, "-no_source_version") == 0 ) {
2980 fSourceVersionLoadCommandForceOff
= true;
2982 else if ( strcmp(arg
, "-sdk_version") == 0 ) {
2983 const char* vers
= argv
[++i
];
2985 throw "-sdk_version missing <version>";
2986 fSDKVersion
= parseVersionNumber32(vers
);
2988 else if ( strcmp(arg
, "-dependent_dr_info") == 0 ) {
2989 fDependentDRInfoForcedOn
= true;
2991 else if ( strcmp(arg
, "-no_dependent_dr_info") == 0 ) {
2992 fDependentDRInfoForcedOff
= true;
2994 else if ( strcmp(arg
, "-kexts_use_stubs") == 0 ) {
2995 fKextsUseStubs
= true;
2997 else if ( strcmp(argv
[i
], "-dependency_info") == 0 ) {
2998 snapshotArgCount
= 0;
3000 // previously handled by buildSearchPaths()
3002 else if ( strcmp(arg
, "-export_dynamic") == 0 ) {
3003 fExportDynamic
= true;
3005 else if ( strcmp(arg
, "-force_symbols_coalesce_list") == 0 ) {
3006 snapshotFileArgIndex
= 1;
3007 loadExportFile(argv
[++i
], "-force_symbols_coalesce_list", fForceCoalesceSymbols
);
3009 else if ( strcmp(arg
, "-add_linker_option") == 0 ) {
3010 // ex: -add_linker_option '-framework Foundation'
3011 const char* optString
= argv
[++i
];
3012 if ( optString
== NULL
)
3013 throw "-add_linker_option missing <option>";
3014 // break up into list of tokens at whitespace
3015 std::vector
<const char*> opts
;
3016 char* buffer
= strdup(optString
);
3017 char* start
= buffer
;
3018 for (char* s
= buffer
; ; ++s
) {
3019 if ( isspace(*s
) ) {
3021 opts
.push_back(start
);
3024 else if ( *s
== '\0' ) {
3025 opts
.push_back(start
);
3029 fLinkerOptions
.push_back(opts
);
3031 else if ( strcmp(arg
, "-allow_simulator_linking_to_macosx_dylibs") == 0 ) {
3032 fAllowSimulatorToLinkWithMacOSX
= true;
3034 else if ( strcmp(arg
, "-keep_dwarf_unwind") == 0 ) {
3035 fKeepDwarfUnwindForcedOn
= true;
3036 fKeepDwarfUnwindForcedOff
= false;
3038 else if ( strcmp(arg
, "-no_keep_dwarf_unwind") == 0 ) {
3039 fKeepDwarfUnwindForcedOn
= false;
3040 fKeepDwarfUnwindForcedOff
= true;
3042 else if ( strcmp(arg
, "-verbose_optimization_hints") == 0 ) {
3043 fVerboseOptimizationHints
= true;
3045 else if ( strcmp(arg
, "-ignore_optimization_hints") == 0 ) {
3046 fIgnoreOptimizationHints
= true;
3048 else if ( strcmp(arg
, "-no_dtrace_dof") == 0 ) {
3049 fGenerateDtraceDOF
= false;
3051 else if ( strcmp(arg
, "-rename_section") == 0 ) {
3052 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) || (argv
[i
+4]==NULL
) )
3053 throw "-rename_section missing <segment> <section> <segment> <section>";
3054 addSectionRename(argv
[i
+1], argv
[i
+2], argv
[i
+3], argv
[i
+4]);
3057 else if ( strcmp(arg
, "-rename_segment") == 0 ) {
3058 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3059 throw "-rename_segment missing <existing-segment> <new-segment>";
3060 addSegmentRename(argv
[i
+1], argv
[i
+2]);
3063 else if ( strcmp(arg
, "-move_to_ro_segment") == 0 ) {
3064 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3065 throw "-move_to_ro_segment missing <segment> <symbol-list-file>";
3066 addSymbolMove(argv
[i
+1], argv
[i
+2], fSymbolsMovesCode
, "-move_to_ro_segment");
3069 else if ( strcmp(arg
, "-move_to_rw_segment") == 0 ) {
3070 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3071 throw "-move_to_rw_segment missing <segment> <symbol-list-file>";
3072 addSymbolMove(argv
[i
+1], argv
[i
+2], fSymbolsMovesData
, "-move_to_rw_segment");
3075 else if ( strcmp(arg
, "-trace_symbol_layout") == 0 ) {
3076 fTraceSymbolLayout
= true;
3078 else if ( strcmp(arg
, "-no_branch_islands") == 0 ) {
3079 fAllowBranchIslands
= false;
3081 else if ( strcmp(arg
, "-segment_order") == 0 ) {
3082 // ex: -segment_order __TEXT:__DATA:__JUNK
3083 const char* optString
= argv
[++i
];
3084 if ( optString
== NULL
)
3085 throw "-segment_order missing colon separated <segment-list>";
3086 if ( !fSegmentOrder
.empty() )
3087 throw "-segment_order used more than once";
3088 // break up into list of tokens at colon
3089 char* buffer
= strdup(optString
);
3090 char* start
= buffer
;
3091 for (char* s
= buffer
; ; ++s
) {
3094 fSegmentOrder
.push_back(start
);
3097 else if ( *s
== '\0' ) {
3098 fSegmentOrder
.push_back(start
);
3103 else if ( strcmp(arg
, "-section_order") == 0 ) {
3104 // ex: -section_order __DATA __data:__const:__nl_pointers
3105 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3106 throw "-section_order missing <segment> <section-list>";
3107 const char* segName
= argv
[++i
];
3108 const char* optString
= argv
[++i
];
3109 if ( sectionOrder(segName
) != NULL
)
3110 throwf("-section_order %s ... used more than once", segName
);
3111 SectionOrderList dummy
;
3112 fSectionOrder
.push_back(dummy
);
3113 SectionOrderList
& entry
= fSectionOrder
.back();
3114 entry
.segmentName
= segName
;
3115 // break up into list of tokens at colon
3116 char* buffer
= strdup(optString
);
3117 char* start
= buffer
;
3118 for (char* s
= buffer
; ; ++s
) {
3121 entry
.sectionOrder
.push_back(start
);
3124 else if ( *s
== '\0' ) {
3125 entry
.sectionOrder
.push_back(start
);
3130 else if ( strcmp(arg
, "-application_extension") == 0 ) {
3131 fMarkAppExtensionSafe
= true;
3132 fCheckAppExtensionSafe
= true;
3134 else if ( strcmp(arg
, "-no_application_extension") == 0 ) {
3135 fMarkAppExtensionSafe
= false;
3136 fCheckAppExtensionSafe
= false;
3138 else if ( strcmp(arg
, "-add_ast_path") == 0 ) {
3139 const char* path
= argv
[++i
];
3141 throw "-add_ast_path missing <option>";
3142 fASTFilePaths
.push_back(path
);
3144 else if ( strcmp(arg
, "-force_load_swift_libs") == 0 ) {
3145 fForceLoadSwiftLibs
= true;
3147 // put this last so that it does not interfer with other options starting with 'i'
3148 else if ( strncmp(arg
, "-i", 2) == 0 ) {
3149 const char* colon
= strchr(arg
, ':');
3150 if ( colon
== NULL
)
3151 throwf("unknown option: %s", arg
);
3152 Options::AliasPair pair
;
3153 char* temp
= new char[colon
-arg
];
3154 strlcpy(temp
, &arg
[2], colon
-arg
-1);
3155 pair
.realName
= &colon
[1];
3157 fAliases
.push_back(pair
);
3160 throwf("unknown option: %s", arg
);
3163 if (snapshotArgCount
== -1)
3164 snapshotArgCount
= i
-snapshotArgIndex
+1;
3165 if (snapshotArgCount
> 0)
3166 fLinkSnapshot
.addSnapshotLinkArg(snapshotArgIndex
, snapshotArgCount
, snapshotFileArgIndex
);
3169 FileInfo info
= findFile(arg
);
3170 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3171 if ( strcmp(&info
.path
[strlen(info
.path
)-2], ".a") == 0 )
3174 fInputFiles
.push_back(info
);
3178 // if a -lazy option was used, implicitly link in lazydylib1.o
3179 if ( fUsingLazyDylibLinking
) {
3180 FileInfo info
= findLibrary("lazydylib1.o");
3181 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)argc
);
3185 if (fSnapshotRequested
)
3186 fLinkSnapshot
.createSnapshot();
3192 // -syslibroot <path> is used for SDK support.
3193 // The rule is that all search paths (both explicit and default) are
3194 // checked to see if they exist in the SDK. If so, that path is
3195 // replaced with the sdk prefixed path. If not, that search path
3196 // is used as is. If multiple -syslibroot options are specified
3197 // their directory structures are logically overlayed and files
3198 // from sdks specified earlier on the command line used before later ones.
3200 void Options::buildSearchPaths(int argc
, const char* argv
[])
3202 bool addStandardLibraryDirectories
= true;
3203 std::vector
<const char*> libraryPaths
;
3204 std::vector
<const char*> frameworkPaths
;
3205 libraryPaths
.reserve(10);
3206 frameworkPaths
.reserve(10);
3207 // scan through argv looking for -L, -F, -Z, and -syslibroot options
3208 for(int i
=0; i
< argc
; ++i
) {
3209 if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'L') ) {
3210 const char* libSearchDir
= &argv
[i
][2];
3211 // Allow either "-L{path}" or "-L {path}".
3212 if (argv
[i
][2] == '\0') {
3213 // -L {path}. Make sure there is an argument following this.
3214 const char* path
= argv
[++i
];
3216 throw "-L missing argument";
3217 libSearchDir
= path
;
3219 if ( libSearchDir
[0] == '\0' )
3220 throw "-L must be immediately followed by a directory path (no space)";
3221 struct stat statbuf
;
3222 if ( stat(libSearchDir
, &statbuf
) == 0 ) {
3223 if ( statbuf
.st_mode
& S_IFDIR
)
3224 libraryPaths
.push_back(libSearchDir
);
3226 warning("path '%s' following -L not a directory", libSearchDir
);
3229 warning("directory not found for option '-L%s'", libSearchDir
);
3232 else if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'F') ) {
3233 const char* frameworkSearchDir
= &argv
[i
][2];
3234 // Allow either "-F{path}" or "-F {path}".
3235 if (argv
[i
][2] == '\0') {
3236 // -F {path}. Make sure there is an argument following this.
3237 const char* path
= argv
[++i
];
3239 throw "-F missing argument";
3240 frameworkSearchDir
= path
;
3242 if ( frameworkSearchDir
[0] == '\0' )
3243 throw "-F must be immediately followed by a directory path (no space)";
3244 struct stat statbuf
;
3245 if ( stat(frameworkSearchDir
, &statbuf
) == 0 ) {
3246 if ( statbuf
.st_mode
& S_IFDIR
)
3247 frameworkPaths
.push_back(frameworkSearchDir
);
3249 warning("path '%s' following -F not a directory", frameworkSearchDir
);
3252 warning("directory not found for option '-F%s'", frameworkSearchDir
);
3255 else if ( strcmp(argv
[i
], "-Z") == 0 )
3256 addStandardLibraryDirectories
= false;
3257 else if ( strcmp(argv
[i
], "-v") == 0 ) {
3259 extern const char ldVersionString
[];
3260 fprintf(stderr
, "%s", ldVersionString
);
3261 fprintf(stderr
, "configured to support archs: %s\n", ALL_SUPPORTED_ARCHS
);
3262 // if only -v specified, exit cleanly
3264 const char* ltoVers
= lto::version();
3265 if ( ltoVers
!= NULL
)
3266 fprintf(stderr
, "LTO support using: %s\n", ltoVers
);
3270 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
3271 const char* path
= argv
[++i
];
3273 throw "-syslibroot missing argument";
3274 fSDKPaths
.push_back(path
);
3276 else if ( strcmp(argv
[i
], "-search_paths_first") == 0 ) {
3277 fLibrarySearchMode
= kSearchDylibAndArchiveInEachDir
;
3279 else if ( strcmp(argv
[i
], "-search_dylibs_first") == 0 ) {
3280 fLibrarySearchMode
= kSearchAllDirsForDylibsThenAllDirsForArchives
;
3282 else if ( strcmp(argv
[i
], "-w") == 0 ) {
3283 sEmitWarnings
= false;
3285 else if ( strcmp(argv
[i
], "-fatal_warnings") == 0 ) {
3286 sFatalWarnings
= true;
3288 else if ( strcmp(argv
[i
], "-dependency_info") == 0 ) {
3289 const char* path
= argv
[++i
];
3291 throw "-dependency_info missing <path>";
3292 fDependencyInfoPath
= path
;
3295 int standardLibraryPathsStartIndex
= libraryPaths
.size();
3296 int standardFrameworkPathsStartIndex
= frameworkPaths
.size();
3297 if ( addStandardLibraryDirectories
) {
3298 libraryPaths
.push_back("/usr/lib");
3299 libraryPaths
.push_back("/usr/local/lib");
3301 frameworkPaths
.push_back("/Library/Frameworks/");
3302 frameworkPaths
.push_back("/System/Library/Frameworks/");
3303 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
3306 // <rdar://problem/5829579> Support for configure based hacks
3307 // if last -syslibroot is /, then ignore all syslibroots
3308 if ( fSDKPaths
.size() > 0 ) {
3309 if ( strcmp(fSDKPaths
.back(), "/") == 0 ) {
3314 // now merge sdk and library paths to make real search paths
3315 fLibrarySearchPaths
.reserve(libraryPaths
.size()*(fSDKPaths
.size()+1));
3317 for (std::vector
<const char*>::iterator it
= libraryPaths
.begin(); it
!= libraryPaths
.end(); ++it
, ++libIndex
) {
3318 const char* libDir
= *it
;
3319 bool sdkOverride
= false;
3320 if ( libDir
[0] == '/' ) {
3321 char betterLibDir
[PATH_MAX
];
3322 if ( strstr(libDir
, "/..") != NULL
) {
3323 if ( realpath(libDir
, betterLibDir
) != NULL
)
3324 libDir
= strdup(betterLibDir
);
3326 const int libDirLen
= strlen(libDir
);
3327 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
3328 const char* sdkDir
= *sdkit
;
3329 const int sdkDirLen
= strlen(sdkDir
);
3330 char newPath
[libDirLen
+ sdkDirLen
+4];
3331 strcpy(newPath
, sdkDir
);
3332 if ( newPath
[sdkDirLen
-1] == '/' )
3333 newPath
[sdkDirLen
-1] = '\0';
3334 strcat(newPath
, libDir
);
3335 struct stat statBuffer
;
3336 if ( stat(newPath
, &statBuffer
) == 0 ) {
3337 fLibrarySearchPaths
.push_back(strdup(newPath
));
3342 if ( !sdkOverride
) {
3343 if ( (libIndex
>= standardLibraryPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
3344 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
3345 // if one SDK is specified and a standard library path is not in the SDK, don't use it
3348 fLibrarySearchPaths
.push_back(libDir
);
3353 // now merge sdk and framework paths to make real search paths
3354 fFrameworkSearchPaths
.reserve(frameworkPaths
.size()*(fSDKPaths
.size()+1));
3356 for (std::vector
<const char*>::iterator it
= frameworkPaths
.begin(); it
!= frameworkPaths
.end(); ++it
, ++frameIndex
) {
3357 const char* frameworkDir
= *it
;
3358 bool sdkOverride
= false;
3359 if ( frameworkDir
[0] == '/' ) {
3360 char betterFrameworkDir
[PATH_MAX
];
3361 if ( strstr(frameworkDir
, "/..") != NULL
) {
3362 if ( realpath(frameworkDir
, betterFrameworkDir
) != NULL
)
3363 frameworkDir
= strdup(betterFrameworkDir
);
3365 const int frameworkDirLen
= strlen(frameworkDir
);
3366 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
3367 const char* sdkDir
= *sdkit
;
3368 const int sdkDirLen
= strlen(sdkDir
);
3369 char newPath
[frameworkDirLen
+ sdkDirLen
+4];
3370 strcpy(newPath
, sdkDir
);
3371 if ( newPath
[sdkDirLen
-1] == '/' )
3372 newPath
[sdkDirLen
-1] = '\0';
3373 strcat(newPath
, frameworkDir
);
3374 struct stat statBuffer
;
3375 if ( stat(newPath
, &statBuffer
) == 0 ) {
3376 fFrameworkSearchPaths
.push_back(strdup(newPath
));
3381 if ( !sdkOverride
) {
3382 if ( (frameIndex
>= standardFrameworkPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
3383 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
3384 // if one SDK is specified and a standard library path is not in the SDK, don't use it
3387 fFrameworkSearchPaths
.push_back(frameworkDir
);
3393 fprintf(stderr
,"Library search paths:\n");
3394 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
3395 it
!= fLibrarySearchPaths
.end();
3397 fprintf(stderr
,"\t%s\n", *it
);
3398 fprintf(stderr
,"Framework search paths:\n");
3399 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
3400 it
!= fFrameworkSearchPaths
.end();
3402 fprintf(stderr
,"\t%s\n", *it
);
3406 // this is run before the command line is parsed
3407 void Options::parsePreCommandLineEnvironmentSettings()
3409 if ((getenv("LD_TRACE_ARCHIVES") != NULL
)
3410 || (getenv("RC_TRACE_ARCHIVES") != NULL
))
3411 fTraceArchives
= true;
3413 if ((getenv("LD_TRACE_DYLIBS") != NULL
)
3414 || (getenv("RC_TRACE_DYLIBS") != NULL
)) {
3415 fTraceDylibs
= true;
3416 fTraceIndirectDylibs
= true;
3419 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL
) {
3420 fTraceDylibSearching
= true;
3423 if (getenv("LD_PRINT_OPTIONS") != NULL
)
3424 fPrintOptions
= true;
3426 if (fTraceDylibs
|| fTraceArchives
)
3427 fTraceOutputFile
= getenv("LD_TRACE_FILE");
3429 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL
)
3430 fPrintOrderFileStatistics
= true;
3432 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL
)
3435 if (getenv("LD_NO_ENCRYPT") != NULL
) {
3436 fEncryptable
= false;
3437 fMarkAppExtensionSafe
= true; // temporary
3438 fCheckAppExtensionSafe
= false;
3441 if (getenv("LD_APPLICATION_EXTENSION_SAFE") != NULL
) {
3442 fMarkAppExtensionSafe
= true;
3443 fCheckAppExtensionSafe
= false;
3446 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL
)
3447 fAllowCpuSubtypeMismatches
= true;
3449 sWarningsSideFilePath
= getenv("LD_WARN_FILE");
3451 const char* customDyldPath
= getenv("LD_DYLD_PATH");
3452 if ( customDyldPath
!= NULL
)
3453 fDyldInstallPath
= customDyldPath
;
3455 const char* debugArchivePath
= getenv("LD_DEBUG_SNAPSHOT");
3456 if (debugArchivePath
!= NULL
) {
3457 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
3458 if (strlen(debugArchivePath
) > 0)
3459 fLinkSnapshot
.setSnapshotPath(debugArchivePath
);
3460 fSnapshotRequested
= true;
3463 const char* pipeFdString
= getenv("LD_PIPELINE_FIFO");
3464 if (pipeFdString
!= NULL
) {
3465 fPipelineFifo
= pipeFdString
;
3470 // this is run after the command line is parsed
3471 void Options::parsePostCommandLineEnvironmentSettings()
3473 // when building a dynamic main executable, default any use of @executable_path to output path
3474 if ( fExecutablePath
== NULL
&& (fOutputKind
== kDynamicExecutable
) ) {
3475 fExecutablePath
= fOutputFile
;
3478 // allow build system to set default seg_addr_table
3479 if ( fSegAddrTablePath
== NULL
)
3480 fSegAddrTablePath
= getenv("LD_SEG_ADDR_TABLE");
3482 // allow build system to turn on prebinding
3484 fPrebind
= ( getenv("LD_PREBIND") != NULL
);
3487 // allow build system to force on dead-code-stripping
3488 if ( !fDeadStrip
) {
3489 if ( getenv("LD_DEAD_STRIP") != NULL
) {
3490 switch (fOutputKind
) {
3491 case Options::kDynamicLibrary
:
3492 case Options::kDynamicExecutable
:
3493 case Options::kDynamicBundle
:
3496 case Options::kPreload
:
3497 case Options::kObjectFile
:
3498 case Options::kDyld
:
3499 case Options::kStaticExecutable
:
3500 case Options::kKextBundle
:
3506 // allow build system to force on -warn_commons
3507 if ( getenv("LD_WARN_COMMONS") != NULL
)
3508 fWarnCommons
= true;
3510 // allow B&I to set default -source_version
3511 if ( fSourceVersion
== 0 ) {
3512 const char* vers
= getenv("RC_ProjectSourceVersion");
3514 fSourceVersion
= parseVersionNumber64(vers
);
3519 void Options::reconfigureDefaults()
3521 // sync reader options
3522 switch ( fOutputKind
) {
3523 case Options::kObjectFile
:
3524 fForFinalLinkedImage
= false;
3526 case Options::kDyld
:
3528 fForFinalLinkedImage
= true;
3531 case Options::kDynamicLibrary
:
3532 case Options::kDynamicBundle
:
3533 case Options::kKextBundle
:
3534 fForFinalLinkedImage
= true;
3537 case Options::kDynamicExecutable
:
3538 case Options::kStaticExecutable
:
3539 case Options::kPreload
:
3540 fLinkingMainExecutable
= true;
3541 fForFinalLinkedImage
= true;
3546 // set default min OS version
3547 if ( (fMacVersionMin
== ld::macVersionUnset
)
3548 && (fIOSVersionMin
== ld::iOSVersionUnset
) ) {
3549 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
3550 const char* macVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
3551 const char* iPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
3552 const char* iOSVers
= getenv("IOS_DEPLOYMENT_TARGET");
3553 const char* iOSSimulatorVers
= getenv("IOS_SIMULATOR_DEPLOYMENT_TARGET");
3554 if ( macVers
!= NULL
)
3555 setMacOSXVersionMin(macVers
);
3556 else if ( iPhoneVers
!= NULL
)
3557 setIOSVersionMin(iPhoneVers
);
3558 else if ( iOSVers
!= NULL
)
3559 setIOSVersionMin(iOSVers
);
3560 else if ( iOSSimulatorVers
!= NULL
)
3561 setIOSVersionMin(iOSSimulatorVers
);
3563 // if still nothing, set default based on architecture
3564 switch ( fArchitecture
) {
3566 case CPU_TYPE_X86_64
:
3567 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
3568 #ifdef DEFAULT_MACOSX_MIN_VERSION
3569 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION
);
3570 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
3572 warning("-macosx_version_min not specified, assuming 10.6");
3573 fMacVersionMin
= ld::mac10_6
;
3578 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
3579 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
3580 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION
);
3581 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION
);
3583 warning("-ios_version_min not specified, assuming 6.0");
3584 setIOSVersionMin("6.0");
3589 // architecture will be infered later by examining .o files
3596 // adjust min based on architecture
3597 switch ( fArchitecture
) {
3599 if ( (fMacVersionMin
< ld::mac10_4
) && (fIOSVersionMin
== ld::iOSVersionUnset
) ) {
3600 //warning("-macosx_version_min should be 10.4 or later for i386");
3601 fMacVersionMin
= ld::mac10_4
;
3604 case CPU_TYPE_X86_64
:
3605 if ( (fMacVersionMin
< ld::mac10_4
) && (fIOSVersionMin
== ld::iOSVersionUnset
) ) {
3606 //warning("-macosx_version_min should be 10.4 or later for x86_64");
3607 fMacVersionMin
= ld::mac10_4
;
3610 case CPU_TYPE_ARM64
:
3611 if ( fIOSVersionMin
< ld::iOS_7_0
) {
3612 //warning("-mios_version_min should be 7.0 or later for arm64");
3613 fIOSVersionMin
= ld::iOS_7_0
;
3618 // default to adding functions start for dynamic code, static code must opt-in
3619 switch ( fOutputKind
) {
3620 case Options::kPreload
:
3621 case Options::kStaticExecutable
:
3622 case Options::kKextBundle
:
3623 if ( fDataInCodeInfoLoadCommandForcedOn
)
3624 fDataInCodeInfoLoadCommand
= true;
3625 if ( fFunctionStartsForcedOn
)
3626 fFunctionStartsLoadCommand
= true;
3628 case Options::kObjectFile
:
3629 if ( !fDataInCodeInfoLoadCommandForcedOff
)
3630 fDataInCodeInfoLoadCommand
= true;
3631 if ( fFunctionStartsForcedOn
)
3632 fFunctionStartsLoadCommand
= true;
3634 case Options::kDynamicExecutable
:
3635 case Options::kDyld
:
3636 case Options::kDynamicLibrary
:
3637 case Options::kDynamicBundle
:
3638 if ( !fDataInCodeInfoLoadCommandForcedOff
)
3639 fDataInCodeInfoLoadCommand
= true;
3640 if ( !fFunctionStartsForcedOff
)
3641 fFunctionStartsLoadCommand
= true;
3645 // adjust kext type based on architecture
3646 if ( fOutputKind
== kKextBundle
) {
3647 switch ( fArchitecture
) {
3648 case CPU_TYPE_X86_64
:
3649 // x86_64 uses new MH_KEXT_BUNDLE type
3650 fMakeCompressedDyldInfo
= false;
3651 fMakeCompressedDyldInfoForceOff
= true;
3652 fAllowTextRelocs
= true;
3653 fUndefinedTreatment
= kUndefinedDynamicLookup
;
3655 case CPU_TYPE_ARM64
:
3656 // arm64 uses new MH_KEXT_BUNDLE type
3657 fMakeCompressedDyldInfo
= false;
3658 fMakeCompressedDyldInfoForceOff
= true;
3659 fAllowTextRelocs
= false;
3660 fKextsUseStubs
= true;
3661 fUndefinedTreatment
= kUndefinedDynamicLookup
;
3664 if ( fIOSVersionMin
>= ld::iOS_5_0
) {
3665 // iOS 5.0 and later use new MH_KEXT_BUNDLE type
3666 fMakeCompressedDyldInfo
= false;
3667 fMakeCompressedDyldInfoForceOff
= true;
3668 // kexts are PIC in iOS 6.0 and later
3669 fAllowTextRelocs
= (fIOSVersionMin
< ld::iOS_6_0
);
3670 fKextsUseStubs
= !fAllowTextRelocs
;
3671 fUndefinedTreatment
= kUndefinedDynamicLookup
;
3674 // else use object file
3677 fOutputKind
= kObjectFile
;
3682 // disable implicit dylibs when targeting 10.3
3683 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
3684 if ( !minOS(ld::mac10_4
, ld::iOS_2_0
) )
3685 fImplicitlyLinkPublicDylibs
= false;
3688 // allow build system to force linker to ignore -prebind
3689 if ( getenv("LD_FORCE_NO_PREBIND") != NULL
)
3692 // allow build system to force linker to ignore -seg_addr_table
3693 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL
)
3694 fSegAddrTablePath
= NULL
;
3696 // check for base address specified externally
3697 if ( (fSegAddrTablePath
!= NULL
) && (fOutputKind
== Options::kDynamicLibrary
) ) {
3698 parseSegAddrTable(fSegAddrTablePath
, this->installPath());
3699 // HACK to support seg_addr_table entries that are physical paths instead of install paths
3700 if ( fBaseAddress
== 0 ) {
3701 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
3702 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.4.dylib");
3703 if ( fBaseAddress
== 0 )
3704 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.9.dylib");
3707 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
3708 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libz.1.2.3.dylib");
3710 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
3711 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libutil1.0.dylib");
3715 // split segs only allowed for dylibs
3717 // split seg only supported for i386, and arm.
3718 switch ( fArchitecture
) {
3720 if ( fOutputKind
!= Options::kDynamicLibrary
)
3722 // make sure read and write segments are proper distance apart
3723 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x10000000) )
3724 fBaseWritableAddress
= fBaseAddress
+ 0x10000000;
3727 if ( fOutputKind
!= Options::kDynamicLibrary
) {
3731 // make sure read and write segments are proper distance apart
3732 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x08000000) )
3733 fBaseWritableAddress
= fBaseAddress
+ 0x08000000;
3739 fBaseWritableAddress
= 0;
3743 // set too-large size
3744 switch ( fArchitecture
) {
3746 fMaxAddress
= 0xFFFFFFFF;
3748 case CPU_TYPE_X86_64
:
3751 switch ( fOutputKind
) {
3752 case Options::kDynamicExecutable
:
3753 case Options::kDynamicLibrary
:
3754 case Options::kDynamicBundle
:
3755 // user land code is limited to low 1GB
3756 fMaxAddress
= 0x2FFFFFFF;
3758 case Options::kStaticExecutable
:
3759 case Options::kObjectFile
:
3760 case Options::kDyld
:
3761 case Options::kPreload
:
3762 case Options::kKextBundle
:
3763 fMaxAddress
= 0xFFFFFFFF;
3766 // range check -seg1addr for ARM
3767 if ( fBaseAddress
> fMaxAddress
) {
3768 warning("ignoring -seg1addr 0x%08llX. Address out of range.", fBaseAddress
);
3774 // <rdar://problem/6138961> -r implies no prebinding for all architectures
3775 if ( fOutputKind
== Options::kObjectFile
)
3778 // disable prebinding depending on arch and min OS version
3780 switch ( fArchitecture
) {
3782 if ( fMacVersionMin
== ld::mac10_4
) {
3783 // in 10.4 only split seg dylibs are prebound
3784 if ( (fOutputKind
!= Options::kDynamicLibrary
) || ! fSplitSegs
)
3787 else if ( fMacVersionMin
>= ld::mac10_5
) {
3788 // in 10.5 nothing is prebound
3791 else if ( fIOSVersionMin
!= ld::iOSVersionUnset
) {
3792 // nothing in simulator is prebound
3796 // in 10.3 and earlier only dylibs and main executables could be prebound
3797 switch ( fOutputKind
) {
3798 case Options::kDynamicExecutable
:
3799 case Options::kDynamicLibrary
:
3800 // only main executables and dylibs can be prebound
3802 case Options::kStaticExecutable
:
3803 case Options::kDynamicBundle
:
3804 case Options::kObjectFile
:
3805 case Options::kDyld
:
3806 case Options::kPreload
:
3807 case Options::kKextBundle
:
3808 // disable prebinding for everything else
3814 case CPU_TYPE_X86_64
:
3818 switch ( fOutputKind
) {
3819 case Options::kDynamicExecutable
:
3820 case Options::kDynamicLibrary
:
3821 // only main executables and dylibs can be prebound
3823 case Options::kStaticExecutable
:
3824 case Options::kDynamicBundle
:
3825 case Options::kObjectFile
:
3826 case Options::kDyld
:
3827 case Options::kPreload
:
3828 case Options::kKextBundle
:
3829 // disable prebinding for everything else
3837 // only prebound images can be split-seg
3838 if ( fSplitSegs
&& !fPrebind
)
3841 // determine if info for shared region should be added
3842 if ( fOutputKind
== Options::kDynamicLibrary
) {
3843 if ( minOS(ld::mac10_5
, ld::iOS_3_1
) )
3845 if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
3846 || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
3847 fSharedRegionEligible
= true;
3849 else if ( fOutputKind
== Options::kDyld
) {
3850 // <rdar://problem/10111122> Enable dyld to be put into the dyld shared cache
3851 fSharedRegionEligible
= true;
3854 // figure out if module table is needed for compatibility with old ld/dyld
3855 if ( fOutputKind
== Options::kDynamicLibrary
) {
3856 switch ( fArchitecture
) {
3858 if ( fIOSVersionMin
!= ld::iOSVersionUnset
) // simulator never needs modules
3862 fNeedsModuleTable
= true; // redo_prebinding requires a module table
3867 // <rdar://problem/5366363> -r -x implies -S
3868 if ( (fOutputKind
== Options::kObjectFile
) && (fLocalSymbolHandling
== kLocalSymbolsNone
) )
3869 fDebugInfoStripping
= Options::kDebugInfoNone
;
3871 // <rdar://problem/15252891> -r implies -no_uuid
3872 if ( fOutputKind
== Options::kObjectFile
)
3873 fUUIDMode
= kUUIDNone
;
3875 // choose how to process unwind info
3876 switch ( fArchitecture
) {
3878 case CPU_TYPE_X86_64
:
3879 case CPU_TYPE_ARM64
:
3880 switch ( fOutputKind
) {
3881 case Options::kObjectFile
:
3882 case Options::kStaticExecutable
:
3883 case Options::kPreload
:
3884 case Options::kKextBundle
:
3885 fAddCompactUnwindEncoding
= false;
3887 case Options::kDyld
:
3888 case Options::kDynamicLibrary
:
3889 case Options::kDynamicBundle
:
3890 case Options::kDynamicExecutable
:
3891 //if ( fAddCompactUnwindEncoding && (fVersionMin >= ld::mac10_6) )
3892 // fRemoveDwarfUnwindIfCompactExists = true;
3897 if ( armUsesZeroCostExceptions() ) {
3898 switch ( fOutputKind
) {
3899 case Options::kObjectFile
:
3900 case Options::kStaticExecutable
:
3901 case Options::kPreload
:
3902 case Options::kKextBundle
:
3903 fAddCompactUnwindEncoding
= false;
3905 case Options::kDyld
:
3906 case Options::kDynamicLibrary
:
3907 case Options::kDynamicBundle
:
3908 case Options::kDynamicExecutable
:
3909 fAddCompactUnwindEncoding
= true;
3914 fAddCompactUnwindEncoding
= false;
3915 fRemoveDwarfUnwindIfCompactExists
= false;
3919 // if -arch is missing, assume we don't want compact unwind info
3920 fAddCompactUnwindEncoding
= false;
3924 // only iOS executables should be encryptable
3925 switch ( fOutputKind
) {
3926 case Options::kObjectFile
:
3927 case Options::kDyld
:
3928 case Options::kStaticExecutable
:
3929 case Options::kPreload
:
3930 case Options::kKextBundle
:
3931 fEncryptable
= false;
3933 case Options::kDynamicExecutable
:
3935 case Options::kDynamicLibrary
:
3936 case Options::kDynamicBundle
:
3937 // <rdar://problem/16293398> Add LC_ENCRYPTION_INFO load command to bundled frameworks
3938 if ( fIOSVersionMin
< ld::iOS_8_0
)
3939 fEncryptable
= false;
3942 if ( (fArchitecture
!= CPU_TYPE_ARM
) && (fArchitecture
!= CPU_TYPE_ARM64
) )
3943 fEncryptable
= false;
3945 // don't move inits in dyld because dyld wants certain
3946 // entries point at stable locations at the start of __text
3947 if ( fOutputKind
== Options::kDyld
)
3948 fAutoOrderInitializers
= false;
3951 // disable __data ordering for some output kinds
3952 switch ( fOutputKind
) {
3953 case Options::kObjectFile
:
3954 case Options::kDyld
:
3955 case Options::kStaticExecutable
:
3956 case Options::kPreload
:
3957 case Options::kKextBundle
:
3960 case Options::kDynamicExecutable
:
3961 case Options::kDynamicLibrary
:
3962 case Options::kDynamicBundle
:
3966 // only use compressed LINKEDIT for final linked images
3967 switch ( fOutputKind
) {
3968 case Options::kDynamicExecutable
:
3969 case Options::kDynamicLibrary
:
3970 case Options::kDynamicBundle
:
3972 case Options::kPreload
:
3973 case Options::kStaticExecutable
:
3974 case Options::kObjectFile
:
3975 case Options::kDyld
:
3976 case Options::kKextBundle
:
3977 fMakeCompressedDyldInfoForceOff
= true;
3980 if ( fMakeCompressedDyldInfoForceOff
)
3981 fMakeCompressedDyldInfo
= false;
3984 // only use compressed LINKEDIT for:
3985 // Mac OS X 10.6 or later
3987 if ( fMakeCompressedDyldInfo
) {
3988 if ( !minOS(ld::mac10_6
, ld::iOS_3_1
) )
3989 fMakeCompressedDyldInfo
= false;
3992 // only ARM and x86_64 enforces that cpu-sub-types must match
3993 switch ( fArchitecture
) {
3995 case CPU_TYPE_X86_64
:
3998 case CPU_TYPE_ARM64
:
3999 fAllowCpuSubtypeMismatches
= true;
4004 // only final linked images can not optimize zero fill sections
4005 if ( fOutputKind
== Options::kObjectFile
)
4006 fOptimizeZeroFill
= true;
4008 // all undefines in -r mode
4009 // if ( fOutputKind == Options::kObjectFile )
4010 // fUndefinedTreatment = kUndefinedSuppress;
4012 // only dynamic final linked images should warn about use of commmons
4013 if ( fWarnCommons
) {
4014 switch ( fOutputKind
) {
4015 case Options::kDynamicExecutable
:
4016 case Options::kDynamicLibrary
:
4017 case Options::kDynamicBundle
:
4019 case Options::kPreload
:
4020 case Options::kStaticExecutable
:
4021 case Options::kObjectFile
:
4022 case Options::kDyld
:
4023 case Options::kKextBundle
:
4024 fWarnCommons
= false;
4029 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
4030 if ( minOS(ld::mac10_5
, ld::iOS_2_0
) )
4031 fUseSimplifiedDylibReExports
= true;
4033 // Mac OS X 10.7 and iOS 4.2 support LC_LOAD_UPWARD_DYLIB
4034 if ( minOS(ld::mac10_7
, ld::iOS_4_2
) && (fOutputKind
== kDynamicLibrary
) )
4035 fCanUseUpwardDylib
= true;
4037 // MacOSX 10.7 defaults to PIE
4038 if ( ((fArchitecture
== CPU_TYPE_X86_64
) || (fArchitecture
== CPU_TYPE_I386
))
4039 && (fOutputKind
== kDynamicExecutable
)
4040 && (fMacVersionMin
>= ld::mac10_7
) ) {
4041 fPositionIndependentExecutable
= true;
4044 // armv7 for iOS4.3 defaults to PIE
4045 if ( (fArchitecture
== CPU_TYPE_ARM
)
4046 && fArchSupportsThumb2
4047 && (fOutputKind
== kDynamicExecutable
)
4048 && (fIOSVersionMin
>= ld::iOS_4_3
) ) {
4049 fPositionIndependentExecutable
= true;
4052 // Simulator defaults to PIE
4053 if ( fTargetIOSSimulator
&& (fOutputKind
== kDynamicExecutable
) )
4054 fPositionIndependentExecutable
= true;
4056 // -no_pie anywhere on command line disable PIE
4057 if ( fDisablePositionIndependentExecutable
)
4058 fPositionIndependentExecutable
= false;
4060 // arm64 is always PIE
4061 if ( (fArchitecture
== CPU_TYPE_ARM64
) && (fOutputKind
== kDynamicExecutable
) ) {
4062 fPositionIndependentExecutable
= true;
4065 // set fOutputSlidable
4066 switch ( fOutputKind
) {
4067 case Options::kObjectFile
:
4068 fOutputSlidable
= false;
4070 case Options::kStaticExecutable
:
4071 case Options::kDynamicExecutable
:
4072 fOutputSlidable
= fPositionIndependentExecutable
;
4074 case Options::kPreload
:
4075 fOutputSlidable
= fPIEOnCommandLine
;
4077 case Options::kDyld
:
4078 case Options::kDynamicLibrary
:
4079 case Options::kDynamicBundle
:
4080 case Options::kKextBundle
:
4081 fOutputSlidable
= true;
4085 // let linker know if thread local variables are supported
4086 if ( fMacVersionMin
>= ld::mac10_7
) {
4089 else if ( (fArchitecture
== CPU_TYPE_ARM64
) && (fIOSVersionMin
>= ld::iOS_8_0
) ) {
4093 // default to adding version load command for dynamic code, static code must opt-in
4094 switch ( fOutputKind
) {
4095 case Options::kObjectFile
:
4096 fVersionLoadCommand
= false;
4098 case Options::kStaticExecutable
:
4099 case Options::kPreload
:
4100 case Options::kKextBundle
:
4101 if ( fVersionLoadCommandForcedOn
)
4102 fVersionLoadCommand
= true;
4104 case Options::kDynamicExecutable
:
4105 case Options::kDyld
:
4106 case Options::kDynamicLibrary
:
4107 case Options::kDynamicBundle
:
4108 if ( !fVersionLoadCommandForcedOff
)
4109 fVersionLoadCommand
= true;
4113 // support re-export of individual symbols in MacOSX 10.7 and iOS 4.2
4114 if ( (fOutputKind
== kDynamicLibrary
) && minOS(ld::mac10_7
, ld::iOS_4_2
) )
4115 fCanReExportSymbols
= true;
4117 // ObjC optimization is only in dynamic final linked images
4118 switch ( fOutputKind
) {
4119 case Options::kObjectFile
:
4120 case Options::kStaticExecutable
:
4121 case Options::kPreload
:
4122 case Options::kKextBundle
:
4123 case Options::kDyld
:
4124 fObjcCategoryMerging
= false;
4126 case Options::kDynamicExecutable
:
4127 case Options::kDynamicLibrary
:
4128 case Options::kDynamicBundle
:
4132 // i386 main executables linked on Mac OS X 10.7 default to NX heap
4133 // regardless of target unless overriden with -allow_heap_execute anywhere
4134 // on the command line
4135 if ( (fArchitecture
== CPU_TYPE_I386
) && (fOutputKind
== kDynamicExecutable
) && !fDisableNonExecutableHeap
)
4136 fNonExecutableHeap
= true;
4138 // Use LC_MAIN instead of LC_UNIXTHREAD for newer OSs
4139 switch ( fOutputKind
) {
4140 case Options::kDynamicExecutable
:
4141 if ( fEntryPointLoadCommandForceOn
) {
4142 fEntryPointLoadCommand
= true;
4143 if ( fEntryName
== NULL
)
4144 fEntryName
= "_main";
4146 else if ( fEntryPointLoadCommandForceOff
) {
4147 fNeedsThreadLoadCommand
= true;
4148 if ( fEntryName
== NULL
)
4149 fEntryName
= "start";
4152 // <rdar://problem/16310363> Linker should look for "_main" not "start" when building for sim regardless of min OS
4153 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) || fTargetIOSSimulator
) {
4154 fEntryPointLoadCommand
= true;
4155 if ( fEntryName
== NULL
)
4156 fEntryName
= "_main";
4157 if ( strcmp(fEntryName
, "start") == 0 ) {
4158 warning("Ignoring '-e start' because entry point 'start' is not used for the targeted OS version");
4159 fEntryName
= "_main";
4163 fNeedsThreadLoadCommand
= true;
4164 if ( fEntryName
== NULL
)
4165 fEntryName
= "start";
4169 case Options::kObjectFile
:
4170 case Options::kKextBundle
:
4171 case Options::kDynamicLibrary
:
4172 case Options::kDynamicBundle
:
4175 case Options::kStaticExecutable
:
4176 case Options::kPreload
:
4177 case Options::kDyld
:
4178 fNeedsThreadLoadCommand
= true;
4179 if ( fEntryName
== NULL
)
4180 fEntryName
= "start"; // Perhaps these should have no default and require -e
4184 // add LC_SOURCE_VERSION
4185 switch ( fOutputKind
) {
4186 case Options::kDynamicExecutable
:
4187 case Options::kKextBundle
:
4188 case Options::kDynamicLibrary
:
4189 case Options::kDynamicBundle
:
4190 case Options::kDyld
:
4191 case Options::kStaticExecutable
:
4192 if ( fSourceVersionLoadCommandForceOn
) {
4193 fSourceVersionLoadCommand
= true;
4195 else if ( fSourceVersionLoadCommandForceOff
) {
4196 fSourceVersionLoadCommand
= false;
4199 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) ) {
4200 fSourceVersionLoadCommand
= true;
4203 fSourceVersionLoadCommand
= false;
4206 case Options::kObjectFile
:
4207 case Options::kPreload
:
4208 fSourceVersionLoadCommand
= false;
4213 // add LC_DYLIB_CODE_SIGN_DRS
4214 switch ( fOutputKind
) {
4215 case Options::kDynamicExecutable
:
4216 case Options::kDynamicLibrary
:
4217 case Options::kDynamicBundle
:
4218 if ( fDependentDRInfoForcedOn
) {
4219 fDependentDRInfo
= true;
4221 else if ( fDependentDRInfoForcedOff
) {
4222 fDependentDRInfo
= false;
4225 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) )
4226 fDependentDRInfo
= true;
4228 fDependentDRInfo
= false;
4231 case Options::kKextBundle
:
4232 case Options::kDyld
:
4233 case Options::kStaticExecutable
:
4234 case Options::kObjectFile
:
4235 case Options::kPreload
:
4236 fDependentDRInfo
= false;
4240 // if -sdk_version not on command line, infer from -syslibroot
4241 if ( (fSDKVersion
== 0) && (fSDKPaths
.size() > 0) ) {
4242 const char* sdkPath
= fSDKPaths
.front();
4243 const char* end
= &sdkPath
[strlen(sdkPath
)-1];
4244 while ( !isdigit(*end
) && (end
> sdkPath
) )
4246 const char* start
= end
-1;
4247 while ( (isdigit(*start
) || (*start
== '.')) && (start
> sdkPath
))
4249 char sdkVersionStr
[32];
4250 int len
= end
-start
+1;
4252 strlcpy(sdkVersionStr
, start
+1, len
);
4253 fSDKVersion
= parseVersionNumber32(sdkVersionStr
);
4257 // if -sdk_version and -syslibroot not used, but targeting MacOSX, use current OS version
4258 if ( (fSDKVersion
== 0) && (fMacVersionMin
!= ld::macVersionUnset
) ) {
4259 // special case if RC_ProjectName and MACOSX_DEPLOYMENT_TARGET are both set that sdkversion=minos
4260 if ( getenv("RC_ProjectName") && getenv("MACOSX_DEPLOYMENT_TARGET") ) {
4261 fSDKVersion
= fMacVersionMin
;
4264 int mib
[2] = { CTL_KERN
, KERN_OSRELEASE
};
4265 char kernVersStr
[100];
4266 size_t strlen
= sizeof(kernVersStr
);
4267 if ( sysctl(mib
, 2, kernVersStr
, &strlen
, NULL
, 0) != -1 ) {
4268 uint32_t kernVers
= parseVersionNumber32(kernVersStr
);
4269 int minor
= (kernVers
>> 16) - 4; // kernel major version is 4 ahead of x in 10.x
4270 fSDKVersion
= 0x000A0000 + (minor
<< 8);
4275 // allow trie based absolute symbols if targeting new enough OS
4276 if ( fMakeCompressedDyldInfo
) {
4277 if ( minOS(ld::mac10_9
, ld::iOS_7_0
) ) {
4278 // <rdar://problem/13179029> Allow absolute symbols in export trie for device but not simulator
4279 if ( !fTargetIOSSimulator
)
4280 fAbsoluteSymbols
= true;
4284 // <rdar://problem/12959510> iOS main executables now default to 16KB page size
4285 if ( (fIOSVersionMin
!= ld::iOSVersionUnset
) && (fOutputKind
== Options::kDynamicExecutable
) ) {
4286 // <rdar://problem/13070042> Only third party apps should have 16KB page segments by default
4287 if ( fEncryptable
) {
4288 if ( fSegmentAlignment
== 4096 )
4289 fSegmentAlignment
= 4096*4;
4293 // <rdar://problem/12258065> ARM64 needs 16KB page size for user land code
4294 // <rdar://problem/15974532> make armv7[s] use 16KB pages in user land code for iOS 8 or later
4295 if ( fSegmentAlignment
== 4096 ) {
4296 switch ( fOutputKind
) {
4297 case Options::kDynamicExecutable
:
4298 case Options::kDynamicLibrary
:
4299 case Options::kDynamicBundle
:
4300 case Options::kDyld
:
4301 if ( (fArchitecture
== CPU_TYPE_ARM64
)
4302 || ((fArchitecture
== CPU_TYPE_ARM
) && (fIOSVersionMin
>= ld::iOS_8_0
) &&
4303 ((fSubArchitecture
== CPU_SUBTYPE_ARM_V7S
) || (fSubArchitecture
== CPU_SUBTYPE_ARM_V7
))) ) {
4304 fSegmentAlignment
= 4096*4;
4307 case Options::kStaticExecutable
:
4308 case Options::kKextBundle
:
4309 // <rdar://problem/14676611> 16KB segments for arm64 kexts
4310 if ( (fArchitecture
== CPU_TYPE_ARM64
) && (fIOSVersionMin
>= ld::iOS_9_0
) ) {
4311 fSegmentAlignment
= 4096*4;
4314 case Options::kObjectFile
:
4315 case Options::kPreload
:
4322 // <rdar://problem/13624134> linker should not convert dwarf unwind if .o file has compact unwind section
4323 switch ( fOutputKind
) {
4324 case Options::kDynamicExecutable
:
4325 case Options::kDynamicLibrary
:
4326 case Options::kDynamicBundle
:
4327 case Options::kDyld
:
4328 if ( fKeepDwarfUnwindForcedOn
) {
4329 fKeepDwarfUnwind
= true;
4331 else if ( fKeepDwarfUnwindForcedOff
) {
4332 fKeepDwarfUnwind
= false;
4335 if ( minOS(ld::mac10_9
, ld::iOS_7_0
) )
4336 fKeepDwarfUnwind
= false;
4338 fKeepDwarfUnwind
= true;
4341 case Options::kKextBundle
:
4342 case Options::kStaticExecutable
:
4343 case Options::kObjectFile
:
4344 case Options::kPreload
:
4345 fKeepDwarfUnwind
= true;
4349 // Make sure -image_base matches alignment
4350 uint64_t alignedBaseAddress
= (fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
);
4351 if ( alignedBaseAddress
!= fBaseAddress
) {
4352 warning("base address 0x%llX is not properly aligned. Changing it to 0x%llX", fBaseAddress
, alignedBaseAddress
);
4353 fBaseAddress
= alignedBaseAddress
;
4358 void Options::checkIllegalOptionCombinations()
4360 // check -undefined setting
4361 switch ( fUndefinedTreatment
) {
4362 case kUndefinedError
:
4363 case kUndefinedDynamicLookup
:
4366 case kUndefinedWarning
:
4367 case kUndefinedSuppress
:
4368 // requires flat namespace
4369 if ( fNameSpace
== kTwoLevelNameSpace
)
4370 throw "can't use -undefined warning or suppress with -twolevel_namespace";
4374 // unify -sub_umbrella with dylibs
4375 for (std::vector
<const char*>::iterator it
= fSubUmbellas
.begin(); it
!= fSubUmbellas
.end(); it
++) {
4376 const char* subUmbrella
= *it
;
4378 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
4379 Options::FileInfo
& info
= *fit
;
4380 const char* lastSlash
= strrchr(info
.path
, '/');
4381 if ( lastSlash
== NULL
)
4382 lastSlash
= info
.path
- 1;
4383 if ( strcmp(&lastSlash
[1], subUmbrella
) == 0 ) {
4384 info
.options
.fReExport
= true;
4386 fLinkSnapshot
.recordSubUmbrella(info
.path
);
4391 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella
);
4394 // unify -sub_library with dylibs
4395 for (std::vector
<const char*>::iterator it
= fSubLibraries
.begin(); it
!= fSubLibraries
.end(); it
++) {
4396 const char* subLibrary
= *it
;
4398 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
4399 Options::FileInfo
& info
= *fit
;
4400 const char* lastSlash
= strrchr(info
.path
, '/');
4401 if ( lastSlash
== NULL
)
4402 lastSlash
= info
.path
- 1;
4403 const char* dot
= strchr(&lastSlash
[1], '.');
4405 dot
= &lastSlash
[strlen(lastSlash
)];
4406 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
4407 info
.options
.fReExport
= true;
4409 fLinkSnapshot
.recordSubLibrary(info
.path
);
4414 warning("-sub_library %s does not match a supplied dylib", subLibrary
);
4417 // sync reader options
4418 if ( fNameSpace
!= kTwoLevelNameSpace
)
4419 fFlatNamespace
= true;
4421 // check -stack_addr
4422 if ( fStackAddr
!= 0 ) {
4423 switch (fArchitecture
) {
4426 if ( fStackAddr
> 0xFFFFFFFF )
4427 throw "-stack_addr must be < 4G for 32-bit processes";
4429 case CPU_TYPE_X86_64
:
4430 case CPU_TYPE_ARM64
:
4433 if ( (fStackAddr
& -4096) != fStackAddr
)
4434 throw "-stack_addr must be multiples of 4K";
4435 if ( fStackSize
== 0 )
4436 throw "-stack_addr must be used with -stack_size";
4439 // check -stack_size
4440 if ( fStackSize
!= 0 ) {
4441 switch (fArchitecture
) {
4443 if ( fStackSize
> 0xFFFFFFFF )
4444 throw "-stack_size must be < 4G for 32-bit processes";
4445 if ( fStackAddr
== 0 ) {
4446 fStackAddr
= 0xC0000000;
4448 if ( (fStackAddr
> 0xB0000000) && ((fStackAddr
-fStackSize
) < 0xB0000000) )
4449 warning("custom stack placement overlaps and will disable shared region");
4452 if ( fStackSize
> 0x2F000000 )
4453 throw "-stack_size must be < 752MB";
4454 if ( fStackAddr
== 0 )
4455 fStackAddr
= 0x2F000000;
4456 if ( fStackAddr
> 0x30000000)
4457 throw "-stack_addr must be < 0x30000000 for arm";
4459 case CPU_TYPE_X86_64
:
4460 if ( fStackAddr
== 0 ) {
4461 fStackAddr
= 0x00007FFF5C000000LL
;
4464 case CPU_TYPE_ARM64
:
4465 if ( fStackSize
> 0x20000000 )
4466 throw "-stack_size must be < 512MB";
4467 if ( fStackAddr
== 0 ) {
4468 fStackAddr
= 0x120000000;
4472 if ( (fStackSize
& -4096) != fStackSize
)
4473 throw "-stack_size must be multiples of 4K";
4474 switch ( fOutputKind
) {
4475 case Options::kDynamicExecutable
:
4476 case Options::kStaticExecutable
:
4477 // custom stack size only legal when building main executable
4479 case Options::kDynamicLibrary
:
4480 case Options::kDynamicBundle
:
4481 case Options::kObjectFile
:
4482 case Options::kDyld
:
4483 case Options::kPreload
:
4484 case Options::kKextBundle
:
4485 throw "-stack_size option can only be used when linking a main executable";
4487 if ( fStackSize
> fStackAddr
)
4488 throwf("-stack_size (0x%08llX) must be smaller than -stack_addr (0x%08llX)", fStackSize
, fStackAddr
);
4491 // check that -allow_stack_execute is only used with main executables
4492 if ( fExecutableStack
) {
4493 switch ( fOutputKind
) {
4494 case Options::kDynamicExecutable
:
4495 case Options::kStaticExecutable
:
4496 // -allow_stack_execute size only legal when building main executable
4498 case Options::kDynamicLibrary
:
4499 case Options::kDynamicBundle
:
4500 case Options::kObjectFile
:
4501 case Options::kDyld
:
4502 case Options::kPreload
:
4503 case Options::kKextBundle
:
4504 throw "-allow_stack_execute option can only be used when linking a main executable";
4508 // check that -allow_heap_execute is only used with i386 main executables
4509 if ( fDisableNonExecutableHeap
) {
4510 if ( fArchitecture
!= CPU_TYPE_I386
)
4511 throw "-allow_heap_execute option can only be used when linking for i386";
4512 switch ( fOutputKind
) {
4513 case Options::kDynamicExecutable
:
4514 // -allow_heap_execute only legal when building main executable
4516 case Options::kStaticExecutable
:
4517 case Options::kDynamicLibrary
:
4518 case Options::kDynamicBundle
:
4519 case Options::kObjectFile
:
4520 case Options::kDyld
:
4521 case Options::kPreload
:
4522 case Options::kKextBundle
:
4523 throw "-allow_heap_execute option can only be used when linking a main executable";
4527 // check -client_name is only used when making a bundle or main executable
4528 if ( fClientName
!= NULL
) {
4529 switch ( fOutputKind
) {
4530 case Options::kDynamicExecutable
:
4531 case Options::kDynamicBundle
:
4533 case Options::kStaticExecutable
:
4534 case Options::kDynamicLibrary
:
4535 case Options::kObjectFile
:
4536 case Options::kDyld
:
4537 case Options::kPreload
:
4538 case Options::kKextBundle
:
4539 throw "-client_name can only be used with -bundle";
4543 // check -init is only used when building a dylib
4544 if ( (fInitFunctionName
!= NULL
) && (fOutputKind
!= Options::kDynamicLibrary
) )
4545 throw "-init can only be used with -dynamiclib";
4547 // check -bundle_loader only used with -bundle
4548 if ( (fBundleLoader
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
4549 throw "-bundle_loader can only be used with -bundle";
4551 // check -dtrace not used with -r
4552 if ( (fDtraceScriptName
!= NULL
) && (fOutputKind
== Options::kObjectFile
) )
4553 throw "-dtrace can only be used when creating final linked images";
4555 // check -d can only be used with -r
4556 if ( fMakeTentativeDefinitionsReal
&& (fOutputKind
!= Options::kObjectFile
) )
4557 throw "-d can only be used with -r";
4559 // check that -root_safe is not used with -r
4560 if ( fRootSafe
&& (fOutputKind
== Options::kObjectFile
) )
4561 throw "-root_safe cannot be used with -r";
4563 // check that -setuid_safe is not used with -r
4564 if ( fSetuidSafe
&& (fOutputKind
== Options::kObjectFile
) )
4565 throw "-setuid_safe cannot be used with -r";
4567 // <rdar://problem/12781832> compiler driver no longer uses -objc_abi_version, it uses -ios_simulator_version_min instead
4568 if ( !fObjCABIVersion1Override
&& !fObjCABIVersion2Override
&& fTargetIOSSimulator
)
4569 fObjCABIVersion2Override
= true;
4571 // rdar://problem/4718189 map ObjC class names to new runtime names
4572 bool alterObjC1ClassNamesToObjC2
= false;
4573 switch (fArchitecture
) {
4575 // i386 only uses new symbols when using objc2 ABI
4576 if ( fObjCABIVersion2Override
)
4577 alterObjC1ClassNamesToObjC2
= true;
4579 case CPU_TYPE_X86_64
:
4581 case CPU_TYPE_ARM64
:
4582 alterObjC1ClassNamesToObjC2
= true;
4586 // make sure all required exported symbols exist
4587 std::vector
<const char*> impliedExports
;
4588 for (NameSet::iterator it
=fExportSymbols
.regularBegin(); it
!= fExportSymbols
.regularEnd(); ++it
) {
4589 const char* name
= *it
;
4590 const int len
= strlen(name
);
4591 if ( (strcmp(&name
[len
-3], ".eh") == 0) || (strncmp(name
, ".objc_category_name_", 20) == 0) ) {
4592 // never export .eh symbols
4593 warning("ignoring %s in export list", name
);
4595 else if ( (fArchitecture
== CPU_TYPE_I386
) && !fObjCABIVersion2Override
&& (strncmp(name
, "_OBJC_CLASS_$", 13) == 0) ) {
4596 warning("ignoring Objc2 Class symbol %s in i386 export list", name
);
4597 fRemovedExports
.insert(name
);
4599 else if ( alterObjC1ClassNamesToObjC2
&& (strncmp(name
, ".objc_class_name_", 17) == 0) ) {
4600 // linking ObjC2 ABI, but have ObjC1 ABI name in export list. Change it to intended name
4601 fRemovedExports
.insert(name
);
4603 asprintf(&temp
, "_OBJC_CLASS_$_%s", &name
[17]);
4604 impliedExports
.push_back(temp
);
4605 asprintf(&temp
, "_OBJC_METACLASS_$_%s", &name
[17]);
4606 impliedExports
.push_back(temp
);
4609 fInitialUndefines
.push_back(name
);
4612 fExportSymbols
.remove(fRemovedExports
);
4613 for (std::vector
<const char*>::iterator it
=impliedExports
.begin(); it
!= impliedExports
.end(); ++it
) {
4614 const char* name
= *it
;
4615 fExportSymbols
.insert(name
);
4616 fInitialUndefines
.push_back(name
);
4619 // make sure all required re-exported symbols exist
4620 for (NameSet::iterator it
=fReExportSymbols
.regularBegin(); it
!= fReExportSymbols
.regularEnd(); ++it
) {
4621 fInitialUndefines
.push_back(*it
);
4624 // make sure that -init symbol exists
4625 if ( fInitFunctionName
!= NULL
)
4626 fInitialUndefines
.push_back(fInitFunctionName
);
4628 // make sure that entry symbol exists
4629 switch ( fOutputKind
) {
4630 case Options::kDynamicExecutable
:
4631 case Options::kStaticExecutable
:
4632 case Options::kDyld
:
4633 case Options::kPreload
:
4634 fInitialUndefines
.push_back(fEntryName
);
4636 case Options::kDynamicLibrary
:
4637 case Options::kDynamicBundle
:
4638 case Options::kObjectFile
:
4639 case Options::kKextBundle
:
4643 // make sure every alias base exists
4644 for (std::vector
<AliasPair
>::iterator it
=fAliases
.begin(); it
!= fAliases
.end(); ++it
) {
4645 fInitialUndefines
.push_back(it
->realName
);
4648 // check custom segments
4649 if ( fCustomSegmentAddresses
.size() != 0 ) {
4650 // verify no segment is in zero page
4651 if ( fZeroPageSize
!= ULLONG_MAX
) {
4652 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
4653 if ( it
->address
< fZeroPageSize
)
4654 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it
->name
, it
->address
);
4657 // verify no duplicates
4658 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
4659 for (std::vector
<SegmentStart
>::iterator it2
= fCustomSegmentAddresses
.begin(); it2
!= fCustomSegmentAddresses
.end(); ++it2
) {
4660 if ( (it
->address
== it2
->address
) && (it
!= it2
) )
4661 throwf("duplicate -segaddr addresses for %s and %s", it
->name
, it2
->name
);
4663 // a custom segment address of zero will disable the use of a zero page
4664 if ( it
->address
== 0 )
4669 if ( fZeroPageSize
== ULLONG_MAX
) {
4670 // zero page size not specified on command line, set default
4671 switch (fArchitecture
) {
4674 // first 4KB for 32-bit architectures
4675 fZeroPageSize
= 0x1000;
4677 case CPU_TYPE_ARM64
:
4678 case CPU_TYPE_X86_64
:
4679 // first 4GB for x86_64 on all OS's
4680 fZeroPageSize
= 0x100000000ULL
;
4683 // if -arch not used, default to 4K zero-page
4684 fZeroPageSize
= 0x1000;
4688 switch ( fOutputKind
) {
4689 case Options::kDynamicExecutable
:
4690 case Options::kStaticExecutable
:
4691 // -pagezero_size size only legal when building main executable
4693 case Options::kDynamicLibrary
:
4694 case Options::kDynamicBundle
:
4695 case Options::kObjectFile
:
4696 case Options::kDyld
:
4697 case Options::kPreload
:
4698 case Options::kKextBundle
:
4699 if ( fZeroPageSize
!= 0 )
4700 throw "-pagezero_size option can only be used when linking a main executable";
4704 // if main executable with custom base address, model zero page as custom segment
4705 if ( (fOutputKind
== Options::kDynamicExecutable
) && (fBaseAddress
!= 0) && (fZeroPageSize
!= 0) ) {
4707 seg
.name
= "__PAGEZERO";
4709 fCustomSegmentAddresses
.push_back(seg
);
4712 // -dead_strip and -r are incompatible
4713 if ( fDeadStrip
&& (fOutputKind
== Options::kObjectFile
) )
4714 throw "-r and -dead_strip cannot be used together";
4716 // can't use -rpath unless targeting 10.5 or later
4717 if ( fRPaths
.size() > 0 ) {
4718 if ( !minOS(ld::mac10_5
, ld::iOS_2_0
) )
4719 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
4720 switch ( fOutputKind
) {
4721 case Options::kDynamicExecutable
:
4722 case Options::kDynamicLibrary
:
4723 case Options::kDynamicBundle
:
4725 case Options::kStaticExecutable
:
4726 case Options::kObjectFile
:
4727 case Options::kDyld
:
4728 case Options::kPreload
:
4729 case Options::kKextBundle
:
4730 throw "-rpath can only be used when creating a dynamic final linked image";
4734 if ( fPositionIndependentExecutable
) {
4735 switch ( fOutputKind
) {
4736 case Options::kDynamicExecutable
:
4737 // check -pie is only used when building a dynamic main executable for 10.5
4738 if ( !minOS(ld::mac10_5
, ld::iOS_4_2
) ) {
4739 if ( fIOSVersionMin
== ld::iOSVersionUnset
)
4740 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
4742 throw "-pie can only be used when targeting iOS 4.2 or later";
4745 case Options::kStaticExecutable
:
4746 case Options::kPreload
:
4747 // -pie is ok with -static or -preload
4749 case Options::kDynamicLibrary
:
4750 case Options::kDynamicBundle
:
4751 warning("-pie being ignored. It is only used when linking a main executable");
4752 fPositionIndependentExecutable
= false;
4754 case Options::kObjectFile
:
4755 case Options::kDyld
:
4756 case Options::kKextBundle
:
4757 throw "-pie can only be used when linking a main executable";
4761 // check -read_only_relocs is not used with x86_64
4762 if ( fAllowTextRelocs
) {
4763 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
!= kKextBundle
) ) {
4764 warning("-read_only_relocs cannot be used with x86_64");
4765 fAllowTextRelocs
= false;
4769 // check -mark_auto_dead_strip is only used with dylibs
4770 if ( fMarkDeadStrippableDylib
) {
4771 if ( fOutputKind
!= Options::kDynamicLibrary
) {
4772 warning("-mark_auto_dead_strip can only be used when creating a dylib");
4773 fMarkDeadStrippableDylib
= false;
4777 // -force_cpusubtype_ALL is not supported for ARM
4778 if ( fForceSubtypeAll
) {
4779 if ( fArchitecture
== CPU_TYPE_ARM
) {
4780 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
4784 // -reexported_symbols_list can only be used with -dynamiclib
4785 if ( !fReExportSymbols
.empty() ) {
4786 if ( fOutputKind
!= Options::kDynamicLibrary
)
4787 throw "-reexported_symbols_list can only used used when created dynamic libraries";
4788 if ( !minOS(ld::mac10_7
, ld::iOS_4_2
) )
4789 throw "targeted OS version does not support -reexported_symbols_list";
4792 // -dyld_env can only be used with main executables
4793 if ( (fOutputKind
!= Options::kDynamicExecutable
) && (fDyldEnvironExtras
.size() != 0) )
4794 throw "-dyld_env can only used used when created main executables";
4796 // -segment_order can only be used with -preload
4797 if ( !fSegmentOrder
.empty() && (fOutputKind
!= Options::kPreload
) )
4798 throw "-segment_order can only used used with -preload output";
4800 // <rdar://problem/17598404> warn if building an embedded iOS dylib for pre-iOS 8
4801 if ( (fOutputKind
== Options::kDynamicLibrary
) && (fIOSVersionMin
!= ld::iOSVersionUnset
) && (fDylibInstallName
!= NULL
) ) {
4802 if ( (fIOSVersionMin
< ld::iOS_8_0
) && (fDylibInstallName
[0] == '@') )
4803 warning("embedded dylibs/frameworks only run on iOS 8 or later");
4808 void Options::checkForClassic(int argc
, const char* argv
[])
4811 bool archFound
= false;
4812 bool staticFound
= false;
4813 bool dtraceFound
= false;
4814 bool kextFound
= false;
4815 bool rFound
= false;
4816 bool creatingMachKernel
= false;
4817 bool newLinker
= false;
4819 // build command line buffer in case ld crashes
4820 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
4821 CRSetCrashLogMessage(crashreporterBuffer
);
4823 const char* srcRoot
= getenv("SRCROOT");
4824 if ( srcRoot
!= NULL
) {
4825 strlcpy(crashreporterBuffer
, "SRCROOT=", crashreporterBufferSize
);
4826 strlcat(crashreporterBuffer
, srcRoot
, crashreporterBufferSize
);
4827 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
4830 strlcat(crashreporterBuffer
, LD_VERS
, crashreporterBufferSize
);
4831 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
4833 strlcat(crashreporterBuffer
, "ld ", crashreporterBufferSize
);
4834 for(int i
=1; i
< argc
; ++i
) {
4835 strlcat(crashreporterBuffer
, argv
[i
], crashreporterBufferSize
);
4836 strlcat(crashreporterBuffer
, " ", crashreporterBufferSize
);
4839 for(int i
=0; i
< argc
; ++i
) {
4840 const char* arg
= argv
[i
];
4841 if ( arg
[0] == '-' ) {
4842 if ( strcmp(arg
, "-arch") == 0 ) {
4843 parseArch(argv
[++i
]);
4846 else if ( strcmp(arg
, "-static") == 0 ) {
4849 else if ( strcmp(arg
, "-kext") == 0 ) {
4852 else if ( strcmp(arg
, "-dtrace") == 0 ) {
4855 else if ( strcmp(arg
, "-r") == 0 ) {
4858 else if ( strcmp(arg
, "-new_linker") == 0 ) {
4861 else if ( strcmp(arg
, "-classic_linker") == 0 ) {
4862 // ld_classic does not understand this option, so remove it
4863 for(int j
=i
; j
< argc
; ++j
)
4864 argv
[j
] = argv
[j
+1];
4865 warning("using ld_classic");
4866 this->gotoClassicLinker(argc
-1, argv
);
4868 else if ( strcmp(arg
, "-o") == 0 ) {
4869 const char* outfile
= argv
[++i
];
4870 if ( (outfile
!= NULL
) && (strstr(outfile
, "/mach_kernel") != NULL
) )
4871 creatingMachKernel
= true;
4877 void Options::gotoClassicLinker(int argc
, const char* argv
[])
4879 argv
[0] = "ld_classic";
4880 // ld_classic does not support -iphoneos_version_min, so change
4881 for(int j
=0; j
< argc
; ++j
) {
4882 if ( (strcmp(argv
[j
], "-iphoneos_version_min") == 0) || (strcmp(argv
[j
], "-ios_version_min") == 0) ) {
4883 argv
[j
] = "-macosx_version_min";
4889 // ld classic does not understand -kext (change to -static -r)
4890 for(int j
=0; j
< argc
; ++j
) {
4891 if ( strcmp(argv
[j
], "-kext") == 0)
4893 else if ( strcmp(argv
[j
], "-dynamic") == 0)
4894 argv
[j
] = "-static";
4896 // ld classic does not understand -demangle
4897 for(int j
=0; j
< argc
; ++j
) {
4898 if ( strcmp(argv
[j
], "-demangle") == 0)
4899 argv
[j
] = "-noprebind";
4901 // in -v mode, print command line passed to ld_classic
4902 for(int i
=0; i
< argc
; ++i
) {
4903 if ( strcmp(argv
[i
], "-v") == 0 ) {
4904 for(int j
=0; j
< argc
; ++j
)
4905 printf("%s ", argv
[j
]);
4910 char rawPath
[PATH_MAX
];
4911 char path
[PATH_MAX
];
4912 uint32_t bufSize
= PATH_MAX
;
4913 if ( _NSGetExecutablePath(rawPath
, &bufSize
) != -1 ) {
4914 if ( realpath(rawPath
, path
) != NULL
) {
4915 char* lastSlash
= strrchr(path
, '/');
4916 if ( lastSlash
!= NULL
) {
4917 strcpy(lastSlash
+1, "ld_classic");
4919 execvp(path
, (char**)argv
);
4923 // in case of error in above, try searching for ld_classic via PATH
4924 execvp(argv
[0], (char**)argv
);
4925 fprintf(stderr
, "can't exec ld_classic\n");
4930 // Note, returned string buffer is own by this function.
4931 // It should not be freed
4932 // It will be reused, so clients need to strdup() if they want
4933 // to use it long term.
4934 const char* Options::demangleSymbol(const char* sym
) const
4936 // only try to demangle symbols if -demangle on command line
4940 // only try to demangle symbols that look like C++ symbols
4941 if ( strncmp(sym
, "__Z", 3) != 0 )
4944 static size_t size
= 1024;
4945 static char* buff
= (char*)malloc(size
);
4948 char* result
= abi::__cxa_demangle(&sym
[1], buff
, &size
, &status
);
4949 if ( result
!= NULL
) {
4950 // if demangling successful, keep buffer for next demangle
4958 void Options::dumpDependency(uint8_t opcode
, const char* path
) const
4960 if ( !this->dumpDependencyInfo() )
4963 // one time open() of -dependency_info file
4964 if ( fDependencyFileDescriptor
== -1 ) {
4965 fDependencyFileDescriptor
= open(this->dependencyInfoPath(), O_WRONLY
| O_TRUNC
| O_CREAT
, 0666);
4966 if ( fDependencyFileDescriptor
== -1 )
4967 throwf("Could not open or create -dependency_info file: %s", this->dependencyInfoPath());
4970 uint8_t version
= depLinkerVersion
;
4971 if ( write(fDependencyFileDescriptor
, &version
, 1) == -1 )
4972 throwf("write() to -dependency_info failed, errno=%d", errno
);
4973 extern const char ldVersionString
[];
4974 if ( write(fDependencyFileDescriptor
, ldVersionString
, strlen(ldVersionString
)+1) == -1 )
4975 throwf("write() to -dependency_info failed, errno=%d", errno
);
4978 char realPath
[PATH_MAX
];
4979 if ( path
[0] != '/' ) {
4980 if ( realpath(path
, realPath
) != NULL
) {
4985 if ( write(fDependencyFileDescriptor
, &opcode
, 1) == -1 )
4986 throwf("write() to -dependency_info failed, errno=%d", errno
);
4987 if ( write(fDependencyFileDescriptor
, path
, strlen(path
)+1) == -1 )
4988 throwf("write() to -dependency_info failed, errno=%d", errno
);
4990 //fprintf(stderr, "0x%02X %s\n", opcode, path);