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>
43 #include "Architectures.hpp"
44 #include "MachOFileAbstraction.hpp"
48 // from FunctionNameDemangle.h
49 extern "C" size_t fnd_get_demangled_name(const char *mangledName
, char *outputBuffer
, size_t length
);
52 // upward dependency on lto::version()
54 extern const char* version();
57 // magic to place command line in crash reports
58 const int crashreporterBufferSize
= 2000;
59 static char crashreporterBuffer
[crashreporterBufferSize
];
60 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
61 #include <CrashReporterClient.h>
62 // hack until ld does not need to build on 10.6 anymore
63 struct crashreporter_annotations_t gCRAnnotations
64 __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION
)))
65 = { CRASHREPORTER_ANNOTATIONS_VERSION
, 0, 0, 0, 0, 0, 0 };
67 extern "C" char* __crashreporter_info__
;
69 char* __crashreporter_info__
= crashreporterBuffer
;
73 static bool sEmitWarnings
= true;
74 static bool sFatalWarnings
= false;
75 static const char* sWarningsSideFilePath
= NULL
;
76 static FILE* sWarningsSideFile
= NULL
;
77 static int sWarningsCount
= 0;
79 void warning(const char* format
, ...)
82 if ( sEmitWarnings
) {
84 if ( sWarningsSideFilePath
!= NULL
) {
85 if ( sWarningsSideFile
== NULL
)
86 sWarningsSideFile
= fopen(sWarningsSideFilePath
, "a");
88 va_start(list
, format
);
89 fprintf(stderr
, "ld: warning: ");
90 vfprintf(stderr
, format
, list
);
91 fprintf(stderr
, "\n");
92 if ( sWarningsSideFile
!= NULL
) {
93 fprintf(sWarningsSideFile
, "ld: warning: ");
94 vfprintf(sWarningsSideFile
, format
, list
);
95 fprintf(sWarningsSideFile
, "\n");
96 fflush(sWarningsSideFile
);
102 void throwf(const char* format
, ...)
106 va_start(list
, format
);
107 vasprintf(&p
, format
, list
);
115 bool Options::FileInfo::checkFileExists(const Options
& options
, const char *p
)
117 struct stat statBuffer
;
120 if ( stat(p
, &statBuffer
) == 0 ) {
121 if (p
!= path
) path
= strdup(p
);
122 fileLen
= statBuffer
.st_size
;
123 modTime
= statBuffer
.st_mtime
;
126 if ( options
.dumpDependencyInfo() )
127 options
.dumpDependency(Options::depNotFound
, p
);
132 Options::Options(int argc
, const char* argv
[])
133 : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0), fArchitectureName("unknown"), fOutputKind(kDynamicExecutable
),
134 fHasPreferredSubType(false), fArchSupportsThumb2(false), fPrebind(false), fBindAtLoad(false), fKeepPrivateExterns(false),
135 fNeedsModuleTable(false), fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false),
136 fInterposeMode(kInterposeNone
), fDeadStrip(false), fNameSpace(kTwoLevelNameSpace
),
137 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL
), fFinalName(NULL
), fEntryName(NULL
),
138 fBaseAddress(0), fMaxAddress(0x7FFFFFFFFFFFFFFFLL
),
139 fBaseWritableAddress(0), fSplitSegs(false),
140 fExportMode(kExportDefault
), fLibrarySearchMode(kSearchDylibAndArchiveInEachDir
),
141 fUndefinedTreatment(kUndefinedError
), fMessagesPrefixedWithArchitecture(true),
142 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak
),
144 fUmbrellaName(NULL
), fInitFunctionName(NULL
), fDotOutputFile(NULL
), fExecutablePath(NULL
),
145 fBundleLoader(NULL
), fDtraceScriptName(NULL
), fSegAddrTablePath(NULL
), fMapPath(NULL
),
146 fDyldInstallPath("/usr/lib/dyld"), fTempLtoObjectPath(NULL
), fOverridePathlibLTO(NULL
), fLtoCpu(NULL
),
147 fZeroPageSize(ULLONG_MAX
), fStackSize(0), fStackAddr(0), fSourceVersion(0), fSDKVersion(0), fExecutableStack(false),
148 fNonExecutableHeap(false), fDisableNonExecutableHeap(false),
149 fMinimumHeaderPad(32), fSegmentAlignment(4096),
150 fCommonsMode(kCommonsIgnoreDylibs
), fUUIDMode(kUUIDContent
), fLocalSymbolHandling(kLocalSymbolsAll
), fWarnCommons(false),
151 fVerbose(false), fKeepRelocations(false), fWarnStabs(false),
152 fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
153 fSharedRegionEligible(false), fSharedRegionEligibleForceOff(false), fPrintOrderFileStatistics(false),
154 fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), fPIEOnCommandLine(false),
155 fDisablePositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
156 fDeadStripDylibs(false), fAllowTextRelocs(false), fWarnTextRelocs(false), fKextsUseStubs(false),
157 fUsingLazyDylibLinking(false), fEncryptable(true), fEncryptableForceOn(false), fEncryptableForceOff(false),
158 fOrderData(true), fMarkDeadStrippableDylib(false),
159 fMakeCompressedDyldInfo(true), fMakeCompressedDyldInfoForceOff(false), fNoEHLabels(false),
160 fAllowCpuSubtypeMismatches(false), fEnforceDylibSubtypesMatch(false), fUseSimplifiedDylibReExports(false),
161 fObjCABIVersion2Override(false), fObjCABIVersion1Override(false), fCanUseUpwardDylib(false),
162 fFullyLoadArchives(false), fLoadAllObjcObjectsFromArchives(false), fFlatNamespace(false),
163 fLinkingMainExecutable(false), fForFinalLinkedImage(false), fForStatic(false),
164 fForDyld(false), fMakeTentativeDefinitionsReal(false), fWhyLoad(false), fRootSafe(false),
165 fSetuidSafe(false), fImplicitlyLinkPublicDylibs(true), fAddCompactUnwindEncoding(true),
166 fWarnCompactUnwind(false), fRemoveDwarfUnwindIfCompactExists(false),
167 fAutoOrderInitializers(true), fOptimizeZeroFill(true), fMergeZeroFill(false), fLogObjectFiles(false),
168 fLogAllFiles(false), fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false),
169 fOutputSlidable(false), fWarnWeakExports(false),
170 fObjcGcCompaction(false), fObjCGc(false), fObjCGcOnly(false),
171 fDemangle(false), fTLVSupport(false),
172 fVersionLoadCommand(false), fVersionLoadCommandForcedOn(false),
173 fVersionLoadCommandForcedOff(false), fFunctionStartsLoadCommand(false),
174 fFunctionStartsForcedOn(false), fFunctionStartsForcedOff(false),
175 fDataInCodeInfoLoadCommand(false), fDataInCodeInfoLoadCommandForcedOn(false), fDataInCodeInfoLoadCommandForcedOff(false),
176 fCanReExportSymbols(false), fObjcCategoryMerging(true), fPageAlignDataAtoms(false),
177 fNeedsThreadLoadCommand(false), fEntryPointLoadCommand(false),
178 fEntryPointLoadCommandForceOn(false), fEntryPointLoadCommandForceOff(false),
179 fSourceVersionLoadCommand(false),
180 fSourceVersionLoadCommandForceOn(false), fSourceVersionLoadCommandForceOff(false),
181 fTargetIOSSimulator(false), fExportDynamic(false), fAbsoluteSymbols(false),
182 fAllowSimulatorToLinkWithMacOSX(false), fKeepDwarfUnwind(true),
183 fKeepDwarfUnwindForcedOn(false), fKeepDwarfUnwindForcedOff(false),
184 fVerboseOptimizationHints(false), fIgnoreOptimizationHints(false),
185 fGenerateDtraceDOF(true), fAllowBranchIslands(true), fTraceSymbolLayout(false),
186 fMarkAppExtensionSafe(false), fCheckAppExtensionSafe(false), fForceLoadSwiftLibs(false),
187 fSharedRegionEncodingV2(false), fUseDataConstSegment(false),
188 fUseDataConstSegmentForceOn(false), fUseDataConstSegmentForceOff(false),
189 fBundleBitcode(false), fHideSymbols(false), fVerifyBitcode(false),
190 fReverseMapUUIDRename(false), fDeDupe(true), fVerboseDeDupe(false),
191 fReverseMapPath(NULL
), fLTOCodegenOnly(false),
192 fIgnoreAutoLink(false), fAllowDeadDups(false), fBitcodeKind(kBitcodeProcess
),
193 fPlatform(kPlatformUnknown
), fDebugInfoStripping(kDebugInfoMinimal
), fTraceOutputFile(NULL
),
194 fMacVersionMin(ld::macVersionUnset
), fIOSVersionMin(ld::iOSVersionUnset
),
195 fSaveTempFiles(false), fSnapshotRequested(false), fPipelineFifo(NULL
),
196 fDependencyInfoPath(NULL
), fDependencyFileDescriptor(-1), fMaxDefaultCommonAlign(0), fFilePreference(kModTime
),
197 fForceTextBasedStub(false)
199 this->checkForClassic(argc
, argv
);
200 this->parsePreCommandLineEnvironmentSettings();
201 this->parse(argc
, argv
);
202 this->parsePostCommandLineEnvironmentSettings();
203 this->reconfigureDefaults();
204 this->checkIllegalOptionCombinations();
206 if ( this->dumpDependencyInfo() ) {
207 this->dumpDependency(depOutputFile
, fOutputFile
);
208 if ( fMapPath
!= NULL
)
209 this->dumpDependency(depOutputFile
, fMapPath
);
215 if ( fDependencyFileDescriptor
!= -1 )
216 ::close(fDependencyFileDescriptor
);
219 bool Options::errorBecauseOfWarnings() const
221 return (sFatalWarnings
&& (sWarningsCount
> 0));
225 const char* Options::installPath() const
227 if ( fDylibInstallName
!= NULL
)
228 return fDylibInstallName
;
229 else if ( fFinalName
!= NULL
)
236 bool Options::interposable(const char* name
) const
238 switch ( fInterposeMode
) {
241 case kInterposeAllExternal
:
244 return fInterposeList
.contains(name
);
246 throw "internal error";
250 bool Options::printWhyLive(const char* symbolName
) const
252 return fWhyLive
.contains(symbolName
);
256 const char* Options::dotOutputFile()
258 return fDotOutputFile
;
262 bool Options::hasWildCardExportRestrictList() const
264 // has -exported_symbols_list which contains some wildcards
265 return ((fExportMode
== kExportSome
) && fExportSymbols
.hasWildCards());
268 bool Options::hasWeakBitTweaks() const
270 // has -exported_symbols_list which contains some wildcards
271 return (!fForceWeakSymbols
.empty() || !fForceNotWeakSymbols
.empty());
274 bool Options::allGlobalsAreDeadStripRoots() const
276 // -exported_symbols_list means globals are not exported by default
277 if ( fExportMode
== kExportSome
)
280 switch ( fOutputKind
) {
281 case Options::kDynamicExecutable
:
282 // <rdar://problem/12839986> Add the -export_dynamic flag
283 return fExportDynamic
;
284 case Options::kStaticExecutable
:
285 // <rdar://problem/13361218> Support the -export_dynamic flag for xnu
286 return fExportDynamic
;
287 case Options::kPreload
:
288 // by default unused globals in a main executable are stripped
290 case Options::kDynamicLibrary
:
291 case Options::kDynamicBundle
:
292 case Options::kObjectFile
:
294 case Options::kKextBundle
:
301 bool Options::keepRelocations()
303 return fKeepRelocations
;
306 bool Options::warnStabs()
311 const char* Options::executablePath()
313 return fExecutablePath
;
316 uint32_t Options::initialSegProtection(const char* segName
) const
318 for(std::vector
<Options::SegmentProtect
>::const_iterator it
= fCustomSegmentProtections
.begin(); it
!= fCustomSegmentProtections
.end(); ++it
) {
319 if ( strcmp(it
->name
, segName
) == 0 ) {
323 if ( strcmp(segName
, "__PAGEZERO") == 0 ) {
326 else if ( strcmp(segName
, "__TEXT") == 0 ) {
327 return VM_PROT_READ
| VM_PROT_EXECUTE
;
329 else if ( strcmp(segName
, "__LINKEDIT") == 0 ) {
333 // all others default to read-write
334 return VM_PROT_READ
| VM_PROT_WRITE
;
337 uint32_t Options::maxSegProtection(const char* segName
) const
339 // iPhoneOS always uses same protection for max and initial
340 // <rdar://problem/11663436> simulator apps need to use MacOSX max-prot
341 if ( (fPlatform
!= kPlatformOSX
) && !fTargetIOSSimulator
)
342 return initialSegProtection(segName
);
344 for(std::vector
<Options::SegmentProtect
>::const_iterator it
= fCustomSegmentProtections
.begin(); it
!= fCustomSegmentProtections
.end(); ++it
) {
345 if ( strcmp(it
->name
, segName
) == 0 ) {
349 if ( strcmp(segName
, "__PAGEZERO") == 0 ) {
352 // all others default to all
353 return VM_PROT_READ
| VM_PROT_WRITE
| VM_PROT_EXECUTE
;
356 uint64_t Options::segPageSize(const char* segName
) const
358 for(std::vector
<SegmentSize
>::const_iterator it
=fCustomSegmentSizes
.begin(); it
!= fCustomSegmentSizes
.end(); ++it
) {
359 if ( strcmp(it
->name
, segName
) == 0 )
362 return fSegmentAlignment
;
365 uint64_t Options::customSegmentAddress(const char* segName
) const
367 for(std::vector
<SegmentStart
>::const_iterator it
=fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
368 if ( strcmp(it
->name
, segName
) == 0 )
371 // if custom stack in use, model as segment with custom address
372 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
373 return fStackAddr
- fStackSize
;
377 bool Options::hasCustomSegmentAddress(const char* segName
) const
379 for(std::vector
<SegmentStart
>::const_iterator it
=fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
380 if ( strcmp(it
->name
, segName
) == 0 )
383 // if custom stack in use, model as segment with custom address
384 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
389 bool Options::hasCustomSectionAlignment(const char* segName
, const char* sectName
) const
391 for (std::vector
<SectionAlignment
>::const_iterator it
= fSectionAlignments
.begin(); it
!= fSectionAlignments
.end(); ++it
) {
392 if ( (strcmp(it
->segmentName
, segName
) == 0) && (strcmp(it
->sectionName
, sectName
) == 0) )
398 uint8_t Options::customSectionAlignment(const char* segName
, const char* sectName
) const
400 for (std::vector
<SectionAlignment
>::const_iterator it
= fSectionAlignments
.begin(); it
!= fSectionAlignments
.end(); ++it
) {
401 if ( (strcmp(it
->segmentName
, segName
) == 0) && (strcmp(it
->sectionName
, sectName
) == 0) )
402 return it
->alignment
;
407 bool Options::segmentOrderAfterFixedAddressSegment(const char* segName
) const
409 bool nowPinned
= false;
410 for (std::vector
<const char*>::const_iterator it
=fSegmentOrder
.begin(); it
!= fSegmentOrder
.end(); ++it
) {
411 if ( strcmp(*it
, segName
) == 0 )
413 if ( hasCustomSegmentAddress(*it
) )
419 bool Options::hasExportedSymbolOrder()
421 return (fExportSymbolsOrder
.size() > 0);
424 bool Options::exportedSymbolOrder(const char* sym
, unsigned int* order
) const
426 NameToOrder::const_iterator pos
= fExportSymbolsOrder
.find(sym
);
427 if ( pos
!= fExportSymbolsOrder
.end() ) {
428 *order
= pos
->second
;
437 void Options::loadSymbolOrderFile(const char* fileOfExports
, NameToOrder
& orderMapping
)
439 // read in whole file
440 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
442 throwf("can't open -exported_symbols_order file: %s", fileOfExports
);
443 struct stat stat_buf
;
444 ::fstat(fd
, &stat_buf
);
445 char* p
= (char*)malloc(stat_buf
.st_size
);
447 throwf("can't process -exported_symbols_order file: %s", fileOfExports
);
449 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
450 throwf("can't read -exported_symbols_order file: %s", fileOfExports
);
454 // parse into symbols and add to unordered_set
455 unsigned int count
= 0;
456 char * const end
= &p
[stat_buf
.st_size
];
457 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
458 char* symbolStart
= NULL
;
459 for (char* s
= p
; s
< end
; ++s
) {
465 else if ( !isspace(*s
) ) {
471 if ( (*s
== '\n') || (*s
== '\r') ) {
473 // removing any trailing spaces
475 while ( isspace(*last
) ) {
479 orderMapping
[symbolStart
] = ++count
;
485 if ( (*s
== '\n') || (*s
== '\r') )
490 if ( state
== inSymbol
) {
491 warning("missing line-end at end of file \"%s\"", fileOfExports
);
492 int len
= end
-symbolStart
+1;
493 char* temp
= new char[len
];
494 strlcpy(temp
, symbolStart
, len
);
496 // remove any trailing spaces
497 char* last
= &temp
[len
-2];
498 while ( isspace(*last
) ) {
502 orderMapping
[temp
] = ++count
;
505 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
508 bool Options::forceWeak(const char* symbolName
) const
510 return fForceWeakSymbols
.contains(symbolName
);
513 bool Options::forceNotWeak(const char* symbolName
) const
515 return fForceNotWeakSymbols
.contains(symbolName
);
518 bool Options::forceWeakNonWildCard(const char* symbolName
) const
520 return fForceWeakSymbols
.containsNonWildcard(symbolName
);
523 bool Options::forceNotWeakNonWildcard(const char* symbolName
) const
525 return fForceNotWeakSymbols
.containsNonWildcard(symbolName
);
528 bool Options::forceCoalesce(const char* symbolName
) const
530 return fForceCoalesceSymbols
.contains(symbolName
);
534 bool Options::shouldExport(const char* symbolName
) const
536 switch (fExportMode
) {
538 return fExportSymbols
.contains(symbolName
);
539 case kDontExportSome
:
540 return ! fDontExportSymbols
.contains(symbolName
);
544 throw "internal error";
547 bool Options::shouldReExport(const char* symbolName
) const
549 return fReExportSymbols
.contains(symbolName
);
552 bool Options::keepLocalSymbol(const char* symbolName
) const
554 switch (fLocalSymbolHandling
) {
555 case kLocalSymbolsAll
:
557 case kLocalSymbolsNone
:
559 case kLocalSymbolsSelectiveInclude
:
560 return fLocalSymbolsIncluded
.contains(symbolName
);
561 case kLocalSymbolsSelectiveExclude
:
562 return ! fLocalSymbolsExcluded
.contains(symbolName
);
564 throw "internal error";
567 const std::vector
<const char*>* Options::sectionOrder(const char* segName
) const
569 for (std::vector
<SectionOrderList
>::const_iterator it
=fSectionOrder
.begin(); it
!= fSectionOrder
.end(); ++it
) {
570 if ( strcmp(it
->segmentName
, segName
) == 0 )
571 return &it
->sectionOrder
;
576 uint32_t Options::minOSversion() const
580 return iOSVersionMin();
582 return macosxVersionMin();
583 case kPlatformWatchOS
:
584 return watchOSVersionMin();
586 case Options::kPlatform_tvOS
:
587 return iOSVersionMin();
595 void Options::setArchitecture(cpu_type_t type
, cpu_subtype_t subtype
, Options::Platform platform
)
597 for (const ArchInfo
* t
=archInfoArray
; t
->archName
!= NULL
; ++t
) {
598 if ( (type
== t
->cpuType
) && (subtype
== t
->cpuSubType
) ) {
599 fArchitecture
= type
;
600 fSubArchitecture
= subtype
;
601 fArchitectureName
= t
->archName
;
602 fHasPreferredSubType
= t
->isSubType
;
603 fArchSupportsThumb2
= t
->supportsThumb2
;
604 fPlatform
= platform
;
607 case CPU_TYPE_X86_64
:
608 if ( (fPlatform
== kPlatformOSX
) && (fOutputKind
!= Options::kObjectFile
) ) {
609 #ifdef DEFAULT_MACOSX_MIN_VERSION
610 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION
);
611 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
613 warning("-macosx_version_min not specified, assuming 10.6");
614 fMacVersionMin
= ld::mac10_6
;
620 if ( (fPlatform
== kPlatformiOS
) && (fOutputKind
!= Options::kObjectFile
) ) {
621 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
622 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION
);
623 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION
);
625 warning("-ios_version_min not specified, assuming 6.0");
626 setIOSVersionMin("6.0");
631 fLinkSnapshot
.recordArch(fArchitectureName
);
632 // only use compressed LINKEDIT for:
633 // Mac OS X 10.6 or later
635 if ( !fMakeCompressedDyldInfo
&& minOS(ld::mac10_6
, ld::iOS_3_1
) && !fMakeCompressedDyldInfoForceOff
)
636 fMakeCompressedDyldInfo
= true;
637 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
638 if ( minOS(ld::mac10_5
, ld::iOS_2_0
) )
639 fUseSimplifiedDylibReExports
= true;
643 fArchitectureName
= "unknown architecture";
646 bool Options::armUsesZeroCostExceptions() const
648 return ( (fArchitecture
== CPU_TYPE_ARM
) && (fSubArchitecture
== CPU_SUBTYPE_ARM_V7K
) );
651 void Options::parseArch(const char* arch
)
654 throw "-arch must be followed by an architecture string";
655 for (const ArchInfo
* t
=archInfoArray
; t
->archName
!= NULL
; ++t
) {
656 if ( strcmp(t
->archName
,arch
) == 0 ) {
657 fArchitectureName
= arch
;
658 fArchitecture
= t
->cpuType
;
659 fSubArchitecture
= t
->cpuSubType
;
660 fHasPreferredSubType
= t
->isSubType
;
661 fArchSupportsThumb2
= t
->supportsThumb2
;
665 throwf("unknown/unsupported architecture name for: -arch %s", arch
);
668 bool Options::checkForFile(const char* format
, const char* dir
, const char* rootName
, FileInfo
& result
) const
670 char possiblePath
[strlen(dir
)+strlen(rootName
)+strlen(format
)+8];
671 sprintf(possiblePath
, format
, dir
, rootName
);
672 bool found
= result
.checkFileExists(*this, possiblePath
);
673 if ( fTraceDylibSearching
)
674 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), possiblePath
);
679 Options::FileInfo
Options::findLibrary(const char* rootName
, bool dylibsOnly
) const
682 const int rootNameLen
= strlen(rootName
);
683 // if rootName ends in .o there is no .a vs .dylib choice
684 if ( (rootNameLen
> 3) && (strcmp(&rootName
[rootNameLen
-2], ".o") == 0) ) {
685 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
686 it
!= fLibrarySearchPaths
.end();
688 const char* dir
= *it
;
689 if ( checkForFile("%s/%s", dir
, rootName
, result
) )
694 bool lookForDylibs
= false;
695 switch ( fOutputKind
) {
696 case Options::kDynamicExecutable
:
697 case Options::kDynamicLibrary
:
698 case Options::kDynamicBundle
:
699 case Options::kObjectFile
: // <rdar://problem/15914513>
700 lookForDylibs
= true;
702 case Options::kStaticExecutable
:
704 case Options::kPreload
:
705 case Options::kKextBundle
:
706 lookForDylibs
= false;
709 switch ( fLibrarySearchMode
) {
710 case kSearchAllDirsForDylibsThenAllDirsForArchives
:
711 // first look in all directories for just for dylibs
712 if ( lookForDylibs
) {
713 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
714 it
!= fLibrarySearchPaths
.end();
716 const char* dir
= *it
;
717 auto path
= std::string(dir
) + "/lib" + rootName
+ ".dylib";
718 if ( findFile(path
, {".tbd"}, result
) )
721 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
722 it
!= fLibrarySearchPaths
.end();
724 const char* dir
= *it
;
725 if ( checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
729 // next look in all directories for just for archives
731 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
732 it
!= fLibrarySearchPaths
.end();
734 const char* dir
= *it
;
735 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
741 case kSearchDylibAndArchiveInEachDir
:
742 // look in each directory for just for a dylib then for an archive
743 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
744 it
!= fLibrarySearchPaths
.end();
746 const char* dir
= *it
;
747 auto path
= std::string(dir
) + "/lib" + rootName
+ ".dylib";
748 if ( lookForDylibs
&& findFile(path
, {".tbd"}, result
) )
750 if ( lookForDylibs
&& checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
752 if ( !dylibsOnly
&& checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
758 throwf("library not found for -l%s", rootName
);
761 Options::FileInfo
Options::findFramework(const char* frameworkName
) const
763 if ( frameworkName
== NULL
)
764 throw "-framework missing next argument";
765 char temp
[strlen(frameworkName
)+1];
766 strcpy(temp
, frameworkName
);
767 const char* name
= temp
;
768 const char* suffix
= NULL
;
769 char* comma
= strchr(temp
, ',');
770 if ( comma
!= NULL
) {
774 return findFramework(name
, suffix
);
777 Options::FileInfo
Options::findFramework(const char* rootName
, const char* suffix
) const
779 for (const auto* path
: fFrameworkSearchPaths
) {
780 auto possiblePath
= std::string(path
).append("/").append(rootName
).append(".framework/").append(rootName
);
781 if ( suffix
!= nullptr ) {
782 char realPath
[PATH_MAX
];
783 // no symlink in framework to suffix variants, so follow main symlink
784 if ( realpath(possiblePath
.c_str(), realPath
) != nullptr )
785 possiblePath
= std::string(realPath
).append(suffix
);
788 if ( findFile(possiblePath
, {".tbd"}, result
) )
791 // try without suffix
792 if ( suffix
!= NULL
)
793 return findFramework(rootName
, NULL
);
795 throwf("framework not found %s", rootName
);
798 static std::string
replace_extension(const std::string
&path
, const std::string
&ext
)
801 auto lastSlashIdx
= result
.find_last_of('/');
802 auto lastDotIdx
= result
.find_last_of('.');
803 if (lastDotIdx
!= std::string::npos
&& lastDotIdx
> lastSlashIdx
)
804 result
.erase(lastDotIdx
, std::string::npos
);
805 if ( ext
.size() > 0 && ext
[0] == '.' )
808 result
.append('.' + ext
);
812 bool Options::findFile(const std::string
&path
, const std::vector
<std::string
> &tbdExtensions
, FileInfo
& result
) const
815 for ( const auto &ext
: tbdExtensions
) {
816 auto newPath
= replace_extension(path
, ext
);
817 bool found
= tbdInfo
.checkFileExists(*this, newPath
.c_str());
818 if ( fTraceDylibSearching
)
819 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), newPath
.c_str());
821 if ( (fFilePreference
== kTextBasedStub
) || fForceTextBasedStub
) {
832 bool found
= dylibInfo
.checkFileExists(*this, path
.c_str());
833 if ( fTraceDylibSearching
)
834 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), path
.c_str());
835 if ( found
&& (fFilePreference
== kMachO
) ) {
841 if ( !dylibInfo
.missing() && tbdInfo
.missing() ) {
845 else if ( dylibInfo
.missing() && !tbdInfo
.missing() ) {
849 else if ( !dylibInfo
.missing() && !tbdInfo
.missing() ) {
850 if ( dylibInfo
.modTime
== tbdInfo
.modTime
) {
855 // <rdar://problem/24459693> Disable false warning about out-of-sync .tbd files.
856 //warning("text-based stub file %s and library file %s are out of sync. Falling back to library file for linking.", tbdInfo.path, dylibInfo.path);
865 Options::FileInfo
Options::findFile(const std::string
&path
) const
869 // if absolute path and not a .o file, then use SDK prefix
870 if ( (path
[0] == '/') && (strcmp(&path
[path
.size()-2], ".o") != 0) ) {
871 for (const auto* sdkPathDir
: fSDKPaths
) {
872 auto possiblePath
= std::string(sdkPathDir
) + path
;
873 if ( findFile(possiblePath
, {".tbd"}, result
) )
878 if ( findFile(path
, {".tbd"}, result
) )
881 // try @executable_path substitution
882 if ( (path
.find("@executable_path/") == 0) && (fExecutablePath
!= nullptr) ) {
883 char newPath
[strlen(fExecutablePath
) + path
.size()];
884 strcpy(newPath
, fExecutablePath
);
885 char* addPoint
= strrchr(newPath
,'/');
886 if ( addPoint
!= nullptr )
887 strcpy(&addPoint
[1], &path
[17]);
889 strcpy(newPath
, &path
[17]);
891 if ( findFile(newPath
, {".tbd"}, result
) )
896 throwf("file not found: %s", path
.c_str());
899 Options::FileInfo
Options::findFileUsingPaths(const std::string
&path
) const
903 auto lastSlashPos
= path
.find_last_of('/');
904 auto pos
= ( lastSlashPos
!= std::string::npos
) ? lastSlashPos
+ 1 : 0;
905 auto leafName
= path
.substr(pos
);
907 // Is this in a framework?
908 // /path/Foo.framework/Foo ==> true (Foo)
909 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
910 // /path/Foo.framework/Resources/Bar ==> false
911 bool isFramework
= false;
912 if ( lastSlashPos
!= std::string::npos
) {
913 auto frameworkDir
= std::string("/").append(leafName
).append(".framework/");
914 if ( path
.rfind(frameworkDir
) != std::string::npos
)
918 // These are abbreviated versions of the routines findFramework and findLibrary above
919 // because we already know the final name of the file that we're looking for and so
920 // don't need to try variations, just paths. We do need to add the additional bits
921 // onto the framework path though.
923 auto endPos
= path
.rfind(".framework");
924 auto beginPos
= path
.find_last_of('/', endPos
);
925 auto leafPath
= path
.substr(beginPos
);
926 for (const auto* dir
: fFrameworkSearchPaths
) {
927 auto possiblePath
= dir
+ leafPath
;
928 if ( findFile(possiblePath
, {".tbd"}, result
) )
932 // if this is a .dylib inside a framework, do not search -L paths
933 // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
934 bool embeddedDylib
= ( (leafName
.size() > 6)
935 && (leafName
.find(".dylib", leafName
.size()-6) != std::string::npos
)
936 && (path
.find(".framework/") != std::string::npos
) );
937 if ( !embeddedDylib
) {
938 for (const auto* dir
: fLibrarySearchPaths
) {
939 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
940 auto possiblePath
= dir
+ leafName
;
941 if ( findFile(possiblePath
, {".tbd"}, result
) )
947 // If we didn't find it fall back to findFile.
948 return findFile(path
);
953 void Options::parseSegAddrTable(const char* segAddrPath
, const char* installPth
)
955 FILE* file
= fopen(segAddrPath
, "r");
956 if ( file
== NULL
) {
957 warning("-seg_addr_table file cannot be read: %s", segAddrPath
);
962 uint64_t firstColumAddress
= 0;
963 uint64_t secondColumAddress
= 0;
964 bool hasSecondColumn
= false;
965 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
966 path
[PATH_MAX
-1] = '\0';
967 char* eol
= strchr(path
, '\n');
970 // ignore lines not starting with 0x number
971 if ( (path
[0] == '0') && (path
[1] == 'x') ) {
973 firstColumAddress
= strtoull(path
, &p
, 16);
974 while ( isspace(*p
) )
976 // see if second column is a number
977 if ( (p
[0] == '0') && (p
[1] == 'x') ) {
978 secondColumAddress
= strtoull(p
, &p
, 16);
979 hasSecondColumn
= true;
980 while ( isspace(*p
) )
983 while ( isspace(*p
) )
986 // remove any trailing whitespace
987 for(char* end
= eol
-1; (end
> p
) && isspace(*end
); --end
)
989 // see if this line is for the dylib being linked
990 if ( strcmp(p
, installPth
) == 0 ) {
991 fBaseAddress
= firstColumAddress
;
992 if ( hasSecondColumn
) {
993 fBaseWritableAddress
= secondColumAddress
;
996 break; // out of while loop
1005 void Options::loadFileList(const char* fileOfPaths
, ld::File::Ordinal baseOrdinal
)
1008 const char* comma
= strrchr(fileOfPaths
, ',');
1009 const char* prefix
= NULL
;
1010 if ( comma
!= NULL
) {
1011 // <rdar://problem/5907981> -filelist fails with comma in path
1012 file
= fopen(fileOfPaths
, "r");
1013 if ( file
== NULL
) {
1015 int realFileOfPathsLen
= comma
-fileOfPaths
;
1016 char realFileOfPaths
[realFileOfPathsLen
+1];
1017 strncpy(realFileOfPaths
,fileOfPaths
, realFileOfPathsLen
);
1018 realFileOfPaths
[realFileOfPathsLen
] = '\0';
1019 file
= fopen(realFileOfPaths
, "r");
1021 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", realFileOfPaths
, errno
, strerror(errno
));
1022 if ( this->dumpDependencyInfo() )
1023 this->dumpDependency(Options::depFileList
, realFileOfPaths
);
1027 file
= fopen(fileOfPaths
, "r");
1029 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", fileOfPaths
, errno
, strerror(errno
));
1030 if ( this->dumpDependencyInfo() )
1031 this->dumpDependency(Options::depFileList
, fileOfPaths
);
1034 char path
[PATH_MAX
];
1035 ld::File::Ordinal previousOrdinal
= baseOrdinal
;
1036 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
1037 path
[PATH_MAX
-1] = '\0';
1038 char* eol
= strchr(path
, '\n');
1041 if ( prefix
!= NULL
) {
1042 char builtPath
[strlen(prefix
)+strlen(path
)+2];
1043 strcpy(builtPath
, prefix
);
1044 strcat(builtPath
, "/");
1045 strcat(builtPath
, path
);
1046 if (fPipelineFifo
!= NULL
) {
1047 FileInfo info
= FileInfo(builtPath
);
1048 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1049 previousOrdinal
= info
.ordinal
;
1050 info
.fromFileList
= true;
1051 fInputFiles
.push_back(info
);
1053 FileInfo info
= findFile(builtPath
);
1054 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1055 previousOrdinal
= info
.ordinal
;
1056 info
.fromFileList
= true;
1057 fInputFiles
.push_back(info
);
1061 if (fPipelineFifo
!= NULL
) {
1062 FileInfo info
= FileInfo(path
);
1063 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1064 previousOrdinal
= info
.ordinal
;
1065 info
.fromFileList
= true;
1066 fInputFiles
.push_back(info
);
1068 FileInfo info
= findFile(path
);
1069 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1070 previousOrdinal
= info
.ordinal
;
1071 info
.fromFileList
= true;
1072 fInputFiles
.push_back(info
);
1080 void Options::SetWithWildcards::remove(const NameSet
& toBeRemoved
)
1082 for(NameSet::const_iterator it
=toBeRemoved
.begin(); it
!= toBeRemoved
.end(); ++it
) {
1083 const char* symbolName
= *it
;
1084 NameSet::iterator pos
= fRegular
.find(symbolName
);
1085 if ( pos
!= fRegular
.end() )
1086 fRegular
.erase(pos
);
1090 bool Options::SetWithWildcards::hasWildCards(const char* symbol
)
1092 // an exported symbol name containing *, ?, or [ requires wildcard matching
1093 return ( strpbrk(symbol
, "*?[") != NULL
);
1096 void Options::SetWithWildcards::insert(const char* symbol
)
1098 if ( hasWildCards(symbol
) )
1099 fWildCard
.push_back(symbol
);
1101 fRegular
.insert(symbol
);
1104 bool Options::SetWithWildcards::contains(const char* symbol
, bool* matchBecauseOfWildcard
) const
1106 if ( matchBecauseOfWildcard
!= NULL
)
1107 *matchBecauseOfWildcard
= false;
1108 // first look at hash table on non-wildcard symbols
1109 if ( fRegular
.find(symbol
) != fRegular
.end() )
1111 // next walk list of wild card symbols looking for a match
1112 for(std::vector
<const char*>::const_iterator it
= fWildCard
.begin(); it
!= fWildCard
.end(); ++it
) {
1113 if ( wildCardMatch(*it
, symbol
) ) {
1114 if ( matchBecauseOfWildcard
!= NULL
)
1115 *matchBecauseOfWildcard
= true;
1122 // Support "foo.o:_bar" to mean symbol _bar in file foo.o
1123 bool Options::SetWithWildcards::containsWithPrefix(const char* symbol
, const char* file
, bool& wildCardMatch
) const
1125 wildCardMatch
= false;
1126 if ( contains(symbol
, &wildCardMatch
) )
1130 const char* s
= strrchr(file
, '/');
1133 char buff
[strlen(file
)+strlen(symbol
)+2];
1134 sprintf(buff
, "%s:%s", file
, symbol
);
1135 return contains(buff
, &wildCardMatch
);
1138 bool Options::SetWithWildcards::containsNonWildcard(const char* symbol
) const
1140 // look at hash table on non-wildcard symbols
1141 return ( fRegular
.find(symbol
) != fRegular
.end() );
1145 std::vector
<const char*> Options::exportsData() const
1147 return fExportSymbols
.data();
1151 std::vector
<const char*> Options::SetWithWildcards::data() const
1153 std::vector
<const char*> data
;
1154 for (NameSet::iterator it
=regularBegin(); it
!= regularEnd(); ++it
) {
1155 data
.push_back(*it
);
1157 for (std::vector
<const char*>::const_iterator it
=fWildCard
.begin(); it
!= fWildCard
.end(); ++it
) {
1158 data
.push_back(*it
);
1163 bool Options::SetWithWildcards::inCharRange(const char*& p
, unsigned char c
) const
1167 while ( *p
!= '\0' ) {
1170 // found beginining [ and ending ]
1171 unsigned char last
= '\0';
1172 for ( const char* s
= b
; s
< e
; ++s
) {
1174 unsigned char next
= *(++s
);
1175 if ( (last
<= c
) && (c
<= next
) )
1192 bool Options::SetWithWildcards::wildCardMatch(const char* pattern
, const char* symbol
) const
1194 const char* s
= symbol
;
1195 for (const char* p
= pattern
; *p
!= '\0'; ++p
) {
1200 for (const char* t
= s
; *t
!= '\0'; ++t
) {
1201 if ( wildCardMatch(&p
[1], t
) )
1211 if ( ! inCharRange(p
, *s
) )
1221 return (*s
== '\0');
1225 void Options::loadExportFile(const char* fileOfExports
, const char* option
, SetWithWildcards
& set
)
1227 if ( fileOfExports
== NULL
)
1228 throwf("missing file after %s", option
);
1229 // read in whole file
1230 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
1232 throwf("can't open %s file: %s", option
, fileOfExports
);
1233 struct stat stat_buf
;
1234 ::fstat(fd
, &stat_buf
);
1235 char* p
= (char*)malloc(stat_buf
.st_size
);
1237 throwf("can't process %s file: %s", option
, fileOfExports
);
1239 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1240 throwf("can't read %s file: %s", option
, fileOfExports
);
1242 if ( this->dumpDependencyInfo() )
1243 this->dumpDependency(Options::depMisc
, fileOfExports
);
1247 // parse into symbols and add to unordered_set
1248 char * const end
= &p
[stat_buf
.st_size
];
1249 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1250 char* symbolStart
= NULL
;
1251 for (char* s
= p
; s
< end
; ++s
) {
1257 else if ( !isspace(*s
) ) {
1263 if ( (*s
== '\n') || (*s
== '\r') ) {
1265 // removing any trailing spaces
1267 while ( isspace(*last
) ) {
1271 set
.insert(symbolStart
);
1277 if ( (*s
== '\n') || (*s
== '\r') )
1282 if ( state
== inSymbol
) {
1283 warning("missing line-end at end of file \"%s\"", fileOfExports
);
1284 int len
= end
-symbolStart
+1;
1285 char* temp
= new char[len
];
1286 strlcpy(temp
, symbolStart
, len
);
1288 // remove any trailing spaces
1289 char* last
= &temp
[len
-2];
1290 while ( isspace(*last
) ) {
1297 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
1300 void Options::parseAliasFile(const char* fileOfAliases
)
1302 // read in whole file
1303 int fd
= ::open(fileOfAliases
, O_RDONLY
, 0);
1305 throwf("can't open alias file: %s", fileOfAliases
);
1306 struct stat stat_buf
;
1307 ::fstat(fd
, &stat_buf
);
1308 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1310 throwf("can't process alias file: %s", fileOfAliases
);
1312 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1313 throwf("can't read alias file: %s", fileOfAliases
);
1314 p
[stat_buf
.st_size
] = '\n';
1316 if ( this->dumpDependencyInfo() )
1317 this->dumpDependency(Options::depMisc
, fileOfAliases
);
1319 // parse into symbols and add to fAliases
1321 char * const end
= &p
[stat_buf
.st_size
+1];
1322 enum { lineStart
, inRealName
, inBetween
, inAliasName
, inComment
} state
= lineStart
;
1324 for (char* s
= p
; s
< end
; ++s
) {
1330 else if ( !isspace(*s
) ) {
1337 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1341 else if ( isspace(*s
) ) {
1348 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1352 else if ( ! isspace(*s
) ) {
1353 state
= inAliasName
;
1360 // removing any trailing spaces
1362 while ( isspace(*last
) ) {
1366 fAliases
.push_back(pair
);
1369 else if ( *s
== '\n' ) {
1371 // removing any trailing spaces
1373 while ( isspace(*last
) ) {
1377 fAliases
.push_back(pair
);
1388 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
1393 void Options::setUndefinedTreatment(const char* treatment
)
1395 if ( treatment
== NULL
)
1396 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
1398 if ( strcmp(treatment
, "warning") == 0 )
1399 fUndefinedTreatment
= kUndefinedWarning
;
1400 else if ( strcmp(treatment
, "error") == 0 )
1401 fUndefinedTreatment
= kUndefinedError
;
1402 else if ( strcmp(treatment
, "suppress") == 0 )
1403 fUndefinedTreatment
= kUndefinedSuppress
;
1404 else if ( strcmp(treatment
, "dynamic_lookup") == 0 )
1405 fUndefinedTreatment
= kUndefinedDynamicLookup
;
1407 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1410 Options::Treatment
Options::parseTreatment(const char* treatment
)
1412 if ( treatment
== NULL
)
1415 if ( strcmp(treatment
, "warning") == 0 )
1417 else if ( strcmp(treatment
, "error") == 0 )
1419 else if ( strcmp(treatment
, "suppress") == 0 )
1425 void Options::setMacOSXVersionMin(const char* version
)
1428 if ( !parsePackedVersion32(version
, value
) ) {
1429 throwf("-macosx_version_min value malformed: '%s'", version
);
1431 fMacVersionMin
= (ld::MacVersionMin
)value
;
1432 fPlatform
= kPlatformOSX
;
1435 void Options::setIOSVersionMin(const char* version
)
1438 if ( !parsePackedVersion32(version
, value
) ) {
1439 throwf("-ios_version_min value malformed: '%s'", version
);
1441 fIOSVersionMin
= (ld::IOSVersionMin
)value
;
1442 fPlatform
= kPlatformiOS
;
1446 void Options::setWatchOSVersionMin(const char* version
)
1449 if ( !parsePackedVersion32(version
, value
) ) {
1450 throwf("-watchos_version_min value malformed: '%s'", version
);
1452 fWatchOSVersionMin
= (ld::WatchOSVersionMin
)value
;
1453 fPlatform
= kPlatformWatchOS
;
1457 bool Options::minOS(ld::MacVersionMin requiredMacMin
, ld::IOSVersionMin requirediPhoneOSMin
)
1459 if ( fMacVersionMin
!= ld::macVersionUnset
) {
1460 return ( fMacVersionMin
>= requiredMacMin
);
1462 else if ( fWatchOSVersionMin
!= ld::wOSVersionUnset
) {
1463 // Hack until we fully track watch and ios versions seperately
1464 return ( (fWatchOSVersionMin
+ 0x00070000) >= requirediPhoneOSMin
);
1467 return ( fIOSVersionMin
>= requirediPhoneOSMin
);
1471 bool Options::min_iOS(ld::IOSVersionMin requirediOSMin
)
1473 if ( fWatchOSVersionMin
!= ld::wOSVersionUnset
) {
1474 // Hack until we fully track watch and ios versions seperately
1475 return ( (fWatchOSVersionMin
+ 0x00070000) >= requirediOSMin
);
1478 return ( fIOSVersionMin
>= requirediOSMin
);
1482 void Options::setWeakReferenceMismatchTreatment(const char* treatment
)
1484 if ( treatment
== NULL
)
1485 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1487 if ( strcmp(treatment
, "error") == 0 )
1488 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchError
;
1489 else if ( strcmp(treatment
, "weak") == 0 )
1490 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchWeak
;
1491 else if ( strcmp(treatment
, "non-weak") == 0 )
1492 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchNonWeak
;
1494 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1497 Options::CommonsMode
Options::parseCommonsTreatment(const char* mode
)
1500 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1502 if ( strcmp(mode
, "ignore_dylibs") == 0 )
1503 return kCommonsIgnoreDylibs
;
1504 else if ( strcmp(mode
, "use_dylibs") == 0 )
1505 return kCommonsOverriddenByDylibs
;
1506 else if ( strcmp(mode
, "error") == 0 )
1507 return kCommonsConflictsDylibsError
;
1509 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1512 void Options::addDylibOverride(const char* paths
)
1514 if ( paths
== NULL
)
1515 throw "-dylib_file must followed by two colon separated paths";
1516 const char* colon
= strchr(paths
, ':');
1517 if ( colon
== NULL
)
1518 throw "-dylib_file must followed by two colon separated paths";
1519 int len
= colon
-paths
;
1520 char* target
= new char[len
+2];
1521 strncpy(target
, paths
, len
);
1523 DylibOverride entry
;
1524 entry
.installName
= target
;
1525 entry
.useInstead
= &colon
[1];
1526 fDylibOverrides
.push_back(entry
);
1529 uint64_t Options::parseAddress(const char* addr
)
1532 uint64_t result
= strtoull(addr
, &endptr
, 16);
1536 uint32_t Options::parseProtection(const char* prot
)
1538 uint32_t result
= 0;
1539 for(const char* p
= prot
; *p
!= '\0'; ++p
) {
1540 switch(tolower(*p
)) {
1542 result
|= VM_PROT_READ
;
1545 result
|= VM_PROT_WRITE
;
1548 result
|= VM_PROT_EXECUTE
;
1553 throwf("unknown -segprot lettter in %s", prot
);
1561 // Parses number of form A[.B[.B[.D[.E]]]] into a uint64_t where the bits are a24.b10.c10.d10.e10
1563 uint64_t Options::parseVersionNumber64(const char* versionString
)
1571 a
= strtoul(versionString
, &end
, 10);
1572 if ( *end
== '.' ) {
1573 b
= strtoul(&end
[1], &end
, 10);
1574 if ( *end
== '.' ) {
1575 c
= strtoul(&end
[1], &end
, 10);
1576 if ( *end
== '.' ) {
1577 d
= strtoul(&end
[1], &end
, 10);
1578 if ( *end
== '.' ) {
1579 e
= strtoul(&end
[1], &end
, 10);
1584 if ( (*end
!= '\0') || (a
> 0xFFFFFF) || (b
> 0x3FF) || (c
> 0x3FF) || (d
> 0x3FF) || (e
> 0x3FF) )
1585 throwf("malformed 64-bit a.b.c.d.e version number: %s", versionString
);
1587 return (a
<< 40) | ( b
<< 30 ) | ( c
<< 20 ) | ( d
<< 10 ) | e
;
1591 uint32_t Options::currentVersion32() const
1593 // warn if it does not fit into 32 bit vers number
1594 uint32_t a
= (fDylibCurrentVersion
>> 40) & 0xFFFF;
1595 uint32_t b
= (fDylibCurrentVersion
>> 30) & 0xFF;
1596 uint32_t c
= (fDylibCurrentVersion
>> 20) & 0xFF;
1597 uint64_t rep32
= ((uint64_t)a
<< 40) | ((uint64_t)b
<< 30) | ((uint64_t)c
<< 20);
1598 if ( rep32
!= fDylibCurrentVersion
) {
1599 warning("truncating -current_version to fit in 32-bit space used by old mach-o format");
1600 a
= (fDylibCurrentVersion
>> 40) & 0xFFFFFF;
1603 b
= (fDylibCurrentVersion
>> 30) & 0x3FF;
1606 c
= (fDylibCurrentVersion
>> 20) & 0x3FF;
1610 return (a
<< 16) | ( b
<< 8 ) | c
;
1614 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1616 uint32_t Options::parseVersionNumber32(const char* versionString
)
1622 x
= strtoul(versionString
, &end
, 10);
1623 if ( *end
== '.' ) {
1624 y
= strtoul(&end
[1], &end
, 10);
1625 if ( *end
== '.' ) {
1626 z
= strtoul(&end
[1], &end
, 10);
1629 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
1630 throwf("malformed 32-bit x.y.z version number: %s", versionString
);
1632 return (x
<< 16) | ( y
<< 8 ) | z
;
1635 static const char* cstringSymbolName(const char* orderFileString
)
1638 asprintf(&result
, "cstring=%s", orderFileString
);
1639 // convert escaped characters
1641 for(const char* s
=result
; *s
!= '\0'; ++s
, ++d
) {
1679 // hexadecimal value of char
1683 while ( isxdigit(*s
) ) {
1688 value
+= ((toupper(*s
)-'A') + 10);
1695 if ( isdigit(*s
) ) {
1696 // octal value of char
1698 while ( isdigit(*s
) ) {
1699 value
= (value
<< 3) + (*s
-'0');
1714 void Options::parseOrderFile(const char* path
, bool cstring
)
1716 // order files override auto-ordering
1717 fAutoOrderInitializers
= false;
1719 // read in whole file
1720 int fd
= ::open(path
, O_RDONLY
, 0);
1722 throwf("can't open order file: %s", path
);
1723 struct stat stat_buf
;
1724 ::fstat(fd
, &stat_buf
);
1725 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1727 throwf("can't process order file: %s", path
);
1728 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1729 throwf("can't read order file: %s", path
);
1731 p
[stat_buf
.st_size
] = '\n';
1732 if ( this->dumpDependencyInfo() )
1733 this->dumpDependency(Options::depMisc
, path
);
1735 // parse into vector of pairs
1736 char * const end
= &p
[stat_buf
.st_size
+1];
1737 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1738 char* symbolStart
= NULL
;
1739 for (char* s
= p
; s
< end
; ++s
) {
1745 else if ( !isspace(*s
) || cstring
) {
1751 if ( (*s
== '\n') || (!cstring
&& (*s
== '#')) ) {
1752 bool wasComment
= (*s
== '#');
1754 // removing any trailing spaces
1756 while ( isspace(*last
) ) {
1760 // if there is an architecture prefix, only use this symbol it if matches current arch
1761 if ( strncmp(symbolStart
, "ppc:", 4) == 0 ) {
1764 else if ( strncmp(symbolStart
, "ppc64:", 6) == 0 ) {
1767 else if ( strncmp(symbolStart
, "i386:", 5) == 0 ) {
1768 if ( fArchitecture
== CPU_TYPE_I386
)
1769 symbolStart
= &symbolStart
[5];
1773 else if ( strncmp(symbolStart
, "x86_64:", 7) == 0 ) {
1774 if ( fArchitecture
== CPU_TYPE_X86_64
)
1775 symbolStart
= &symbolStart
[7];
1779 else if ( strncmp(symbolStart
, "arm:", 4) == 0 ) {
1780 if ( fArchitecture
== CPU_TYPE_ARM
)
1781 symbolStart
= &symbolStart
[4];
1785 else if ( strncmp(symbolStart
, "arm64:", 6) == 0 ) {
1786 if ( fArchitecture
== CPU_TYPE_ARM64
)
1787 symbolStart
= &symbolStart
[6];
1791 if ( symbolStart
!= NULL
) {
1792 char* objFileName
= NULL
;
1793 char* colon
= strstr(symbolStart
, ".o:");
1794 if ( colon
!= NULL
) {
1796 objFileName
= symbolStart
;
1797 symbolStart
= &colon
[3];
1800 colon
= strstr(symbolStart
, ".o):");
1801 if ( colon
!= NULL
) {
1803 objFileName
= symbolStart
;
1804 symbolStart
= &colon
[4];
1807 // trim leading spaces
1808 while ( isspace(*symbolStart
) )
1810 Options::OrderedSymbol pair
;
1812 pair
.symbolName
= cstringSymbolName(symbolStart
);
1814 pair
.symbolName
= symbolStart
;
1815 pair
.objectFileName
= objFileName
;
1816 fOrderedSymbols
.push_back(pair
);
1831 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1834 void Options::parseSectionOrderFile(const char* segment
, const char* section
, const char* path
)
1836 if ( (strcmp(section
, "__cstring") == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1837 parseOrderFile(path
, true);
1839 else if ( (strncmp(section
, "__literal",9) == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1840 warning("sorting of __literal[4,8,16] sections not supported");
1843 // ignore section information and append all symbol names to global order file
1844 parseOrderFile(path
, false);
1848 void Options::addSection(const char* segment
, const char* section
, const char* path
)
1850 if ( strlen(segment
) > 16 )
1851 throw "-seccreate segment name max 16 chars";
1852 if ( strlen(section
) > 16 ) {
1853 char* tmp
= strdup(section
);
1855 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section
, tmp
);
1859 // read in whole file
1860 int fd
= ::open(path
, O_RDONLY
, 0);
1862 throwf("can't open -sectcreate file: %s", path
);
1863 struct stat stat_buf
;
1864 ::fstat(fd
, &stat_buf
);
1865 char* p
= (char*)malloc(stat_buf
.st_size
);
1867 throwf("can't process -sectcreate file: %s", path
);
1868 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1869 throwf("can't read -sectcreate file: %s", path
);
1872 // record section to create
1873 ExtraSection info
= { segment
, section
, path
, (uint8_t*)p
, (uint64_t)stat_buf
.st_size
};
1874 fExtraSections
.push_back(info
);
1877 void Options::addSectionRename(const char* srcSegment
, const char* srcSection
, const char* dstSegment
, const char* dstSection
)
1879 if ( strlen(srcSegment
) > 16 )
1880 throw "-rename_section segment name max 16 chars";
1881 if ( strlen(srcSection
) > 16 )
1882 throw "-rename_section section name max 16 chars";
1883 if ( strlen(dstSegment
) > 16 )
1884 throw "-rename_section segment name max 16 chars";
1885 if ( strlen(dstSection
) > 16 )
1886 throw "-rename_section section name max 16 chars";
1889 info
.fromSegment
= srcSegment
;
1890 info
.fromSection
= srcSection
;
1891 info
.toSegment
= dstSegment
;
1892 info
.toSection
= dstSection
;
1894 fSectionRenames
.push_back(info
);
1898 void Options::addSegmentRename(const char* srcSegment
, const char* dstSegment
)
1900 if ( strlen(srcSegment
) > 16 )
1901 throw "-rename_segment segment name max 16 chars";
1902 if ( strlen(dstSegment
) > 16 )
1903 throw "-rename_segment segment name max 16 chars";
1906 info
.fromSegment
= srcSegment
;
1907 info
.toSegment
= dstSegment
;
1909 fSegmentRenames
.push_back(info
);
1914 void Options::addSymbolMove(const char* dstSegment
, const char* symbolList
,
1915 std::vector
<SymbolsMove
>& list
, const char* optionName
)
1917 if ( strlen(dstSegment
) > 16 )
1918 throwf("%s segment name max 16 chars", optionName
);
1921 list
.push_back(tmp
);
1922 SymbolsMove
& info
= list
.back();
1923 info
.toSegment
= dstSegment
;
1924 loadExportFile(symbolList
, optionName
, info
.symbols
);
1927 bool Options::moveRwSymbol(const char* symName
, const char* filePath
, const char*& seg
, bool& wildCardMatch
) const
1929 for (std::vector
<SymbolsMove
>::const_iterator it
=fSymbolsMovesData
.begin(); it
!= fSymbolsMovesData
.end(); ++it
) {
1930 const SymbolsMove
& info
= *it
;
1931 if ( info
.symbols
.containsWithPrefix(symName
, filePath
, wildCardMatch
)) {
1932 seg
= info
.toSegment
;
1939 bool Options::moveRoSymbol(const char* symName
, const char* filePath
, const char*& seg
, bool& wildCardMatch
) const
1941 for (std::vector
<SymbolsMove
>::const_iterator it
=fSymbolsMovesCode
.begin(); it
!= fSymbolsMovesCode
.end(); ++it
) {
1942 const SymbolsMove
& info
= *it
;
1943 if ( info
.symbols
.containsWithPrefix(symName
, filePath
, wildCardMatch
)) {
1944 seg
= info
.toSegment
;
1951 void Options::addSectionAlignment(const char* segment
, const char* section
, const char* alignmentStr
)
1953 if ( strlen(segment
) > 16 )
1954 throw "-sectalign segment name max 16 chars";
1955 if ( strlen(section
) > 16 )
1956 throw "-sectalign section name max 16 chars";
1958 // argument to -sectalign is a hexadecimal number
1960 unsigned long value
= strtoul(alignmentStr
, &endptr
, 16);
1961 if ( *endptr
!= '\0')
1962 throw "argument for -sectalign is not a hexadecimal number";
1963 if ( value
> 0x8000 )
1964 throw "argument for -sectalign must be less than or equal to 0x8000";
1966 warning("zero is not a valid -sectalign");
1970 // alignment is power of 2 (e.g. page alignment = 12)
1971 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
1972 if ( (unsigned long)(1 << alignment
) != value
) {
1973 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
1974 segment
, section
, 1 << alignment
);
1977 SectionAlignment info
= { segment
, section
, alignment
};
1978 fSectionAlignments
.push_back(info
);
1981 void Options::addLibrary(const FileInfo
& info
)
1983 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
1984 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
1985 if ( strcmp(info
.path
, fit
->path
) == 0 ) {
1986 // if dylib is specified again but weak, record that it should be weak
1987 if ( info
.options
.fWeakImport
)
1988 fit
->options
.fWeakImport
= true;
1993 fInputFiles
.push_back(info
);
1996 void Options::warnObsolete(const char* arg
)
1998 warning("option %s is obsolete and being ignored", arg
);
2002 void Options::cannotBeUsedWithBitcode(const char* arg
)
2004 if ( fBundleBitcode
)
2005 throwf("%s and -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES) cannot be used together", arg
);
2008 std::string
Options::getVersionString32(uint32_t ver
) const
2010 if (ver
== 0 || ver
>= 0x10000000)
2013 unsigned microVersion
= ver
& 0xFF;
2014 unsigned minorVersion
= (ver
>> 8) & 0xFF;
2015 unsigned majorVersion
= (ver
>> 16) & 0xFF;
2016 std::stringstream versionString
;
2017 versionString
<< majorVersion
<< "." << minorVersion
<< "." << microVersion
;
2018 return versionString
.str();
2021 std::string
Options::getVersionString64(uint64_t ver
) const
2023 uint64_t a
= (ver
>> 40) & 0xFFFFFF;
2024 uint64_t b
= (ver
>> 30) & 0x3FF;
2025 uint64_t c
= (ver
>> 20) & 0x3FF;
2026 uint64_t d
= (ver
>> 10) & 0x3FF;
2027 uint64_t e
= ver
& 0x3FF;
2028 std::stringstream versionString
;
2029 versionString
<< a
<< "." << b
<< "." << c
<< "." << d
<< "." << e
;
2030 return versionString
.str();
2033 // Convert X.Y[.Z] to 32-bit value xxxxyyzz
2034 bool Options::parsePackedVersion32(const std::string
& versionStr
, uint32_t &result
)
2038 if ( versionStr
.empty() )
2041 size_t pos
= versionStr
.find('.');
2042 if ( pos
== std::string::npos
)
2045 std::string majorStr
= versionStr
.substr(0, pos
);
2046 std::string rest
= versionStr
.substr(pos
+1);
2050 int majorValue
= std::stoi(majorStr
, &majorEnd
);
2051 if ( majorEnd
!= majorStr
.size() )
2053 if ( majorValue
< 0 )
2055 if ( majorValue
> 65535 )
2058 std::string minorStr
;
2059 std::string microStr
;
2060 pos
= rest
.find('.');
2061 if ( pos
== std::string::npos
) {
2065 minorStr
= rest
.substr(0, pos
);
2066 microStr
= rest
.substr(pos
+1);
2070 int minorValue
= std::stoi(minorStr
, &minorEnd
);
2071 if ( minorEnd
!= minorStr
.size() )
2073 if ( minorValue
< 0 )
2075 if ( minorValue
> 255 )
2079 if ( !microStr
.empty() ) {
2081 microValue
= std::stoi(microStr
, µEnd
);
2082 if ( microEnd
!= microStr
.size() )
2084 if ( microValue
< 0 )
2086 if ( microValue
> 255 )
2090 result
= (majorValue
<< 16) | (minorValue
<< 8) | microValue
;
2095 // std::stoi() throws exception on malformed input
2100 std::string
Options::getSDKVersionStr() const
2102 return getVersionString32(fSDKVersion
);
2105 std::string
Options::getPlatformStr() const
2107 switch (fPlatform
) {
2108 case Options::kPlatformOSX
:
2110 case Options::kPlatformiOS
:
2111 if (targetIOSSimulator())
2112 return "iPhoneSimulator";
2115 case Options::kPlatformWatchOS
:
2116 if (targetIOSSimulator())
2117 return "watchOS Simulator";
2120 #if SUPPORT_APPLE_TV
2121 case Options::kPlatform_tvOS
:
2122 if (targetIOSSimulator())
2123 return "AppleTVSimulator";
2128 case Options::kPlatformUnknown
:
2133 std::vector
<std::string
> Options::writeBitcodeLinkOptions() const
2135 std::vector
<std::string
> linkCommand
;
2136 switch ( fOutputKind
) {
2137 case Options::kDynamicLibrary
:
2138 linkCommand
.push_back("-dylib");
2139 linkCommand
.push_back("-compatibility_version");
2140 if ( fDylibCompatVersion
!= 0 ) {
2141 linkCommand
.push_back(getVersionString32(fDylibCompatVersion
));
2143 linkCommand
.push_back(getVersionString32(currentVersion32()));
2145 if ( fDylibCurrentVersion
!= 0 ) {
2146 linkCommand
.push_back("-current_version");
2147 linkCommand
.push_back(getVersionString64(fDylibCurrentVersion
));
2149 linkCommand
.push_back("-install_name");
2150 linkCommand
.push_back(installPath());
2152 case Options::kDynamicExecutable
:
2153 linkCommand
.push_back("-execute");
2155 case Options::kObjectFile
:
2156 linkCommand
.push_back("-r");
2159 throwf("could not write bitcode options file output kind\n");
2162 if (!fImplicitlyLinkPublicDylibs
)
2163 linkCommand
.push_back("-no_implicit_dylibs");
2165 // Add deployment target.
2166 // Platform is allowed to be unknown for "ld -r".
2167 switch (fPlatform
) {
2168 case Options::kPlatformOSX
:
2169 linkCommand
.push_back("-macosx_version_min");
2170 linkCommand
.push_back(getVersionString32((unsigned)fMacVersionMin
));
2172 case Options::kPlatformiOS
:
2173 if (targetIOSSimulator())
2174 linkCommand
.push_back("-ios_simulator_version_min");
2176 linkCommand
.push_back("-ios_version_min");
2177 linkCommand
.push_back(getVersionString32((unsigned)fIOSVersionMin
));
2179 case Options::kPlatformWatchOS
:
2180 if (targetIOSSimulator())
2181 linkCommand
.push_back("-watchos_simulator_version_min");
2183 linkCommand
.push_back("-watchos_version_min");
2184 linkCommand
.push_back(getVersionString32((unsigned)fIOSVersionMin
));
2186 #if SUPPORT_APPLE_TV
2187 case Options::kPlatform_tvOS
:
2188 if (targetIOSSimulator())
2189 linkCommand
.push_back("-tvos_simulator_version_min");
2191 linkCommand
.push_back("-tvos_version_min");
2192 linkCommand
.push_back(getVersionString32((unsigned)fIOSVersionMin
));
2195 case Options::kPlatformUnknown
:
2196 if ( fOutputKind
!= Options::kObjectFile
) {
2197 throwf("platform is unknown for final bitcode bundle,"
2198 "deployment target and min version is required for -bitcode_bundle");
2206 linkCommand
.push_back("-e");
2207 linkCommand
.push_back(fEntryName
);
2211 if (!fRPaths
.empty()) {
2212 for (std::vector
<const char*>::const_iterator it
=fRPaths
.begin(); it
!= fRPaths
.end(); ++it
) {
2213 linkCommand
.push_back("-rpath");
2214 linkCommand
.push_back(*it
);
2218 // Other bitcode compatiable options
2219 if ( fObjCABIVersion1Override
) {
2220 linkCommand
.push_back("-objc_abi_version");
2221 linkCommand
.push_back("1");
2222 } else if ( fObjCABIVersion2Override
) {
2223 linkCommand
.push_back("-objc_abi_version");
2224 linkCommand
.push_back("2");
2226 if ( fExecutablePath
) {
2227 linkCommand
.push_back("-executable_path");
2228 linkCommand
.push_back(fExecutablePath
);
2231 linkCommand
.push_back("-dead_strip");
2232 if ( fExportDynamic
)
2233 linkCommand
.push_back("-export_dynamic");
2234 if ( fMarkAppExtensionSafe
&& fCheckAppExtensionSafe
)
2235 linkCommand
.push_back("-application_extension");
2237 if ( fSourceVersionLoadCommandForceOn
)
2238 linkCommand
.push_back("-add_source_version");
2239 if ( fSourceVersion
!= 0 ) {
2240 linkCommand
.push_back("-source_version");
2241 linkCommand
.push_back(getVersionString64(fSourceVersion
));
2244 // linker flag added by swift driver
2245 // rdar://problem/20108072
2246 if ( !fObjcCategoryMerging
)
2247 linkCommand
.push_back("-no_objc_category_merging");
2253 // Process all command line arguments.
2255 // The only error checking done here is that each option is valid and if it has arguments
2256 // that they too are valid.
2258 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
2259 // whichever was last on the command line is used.
2261 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
2263 void Options::parse(int argc
, const char* argv
[])
2265 // Store the original args in the link snapshot.
2266 fLinkSnapshot
.recordRawArgs(argc
, argv
);
2268 // pass one builds search list from -L and -F options
2269 this->buildSearchPaths(argc
, argv
);
2271 // reduce re-allocations
2272 fInputFiles
.reserve(32);
2274 // pass two parse all other options
2275 for(int i
=1; i
< argc
; ++i
) {
2276 const char* arg
= argv
[i
];
2278 if ( arg
[0] == '-' ) {
2279 // by default, copy one arg to the snapshot link command, and do no file copying
2280 int snapshotArgIndex
= i
;
2281 int snapshotArgCount
= -1; // -1 means compute count based on change in index
2282 int snapshotFileArgIndex
= -1; // -1 means no data file parameter to arg
2284 // Since we don't care about the files passed, just the option names, we do this here.
2286 fprintf (stderr
, "[Logging ld64 options]\t%s\n", arg
);
2288 if ( (arg
[1] == 'L') || (arg
[1] == 'F') ) {
2289 snapshotArgCount
= 0; // stripped out of link snapshot
2292 // previously handled by buildSearchPaths()
2294 // The one gnu style option we have to keep compatibility
2295 // with gcc. Might as well have the single hyphen one as well.
2296 else if ( (strcmp(arg
, "--help") == 0)
2297 || (strcmp(arg
, "-help") == 0)) {
2298 fprintf (stdout
, "ld64: For information on command line options please use 'man ld'.\n");
2301 else if ( strcmp(arg
, "-arch") == 0 ) {
2302 parseArch(argv
[++i
]);
2304 else if ( strcmp(arg
, "-dynamic") == 0 ) {
2307 else if ( strcmp(arg
, "-static") == 0 ) {
2309 if ( (fOutputKind
!= kObjectFile
) && (fOutputKind
!= kKextBundle
) ) {
2310 fOutputKind
= kStaticExecutable
;
2312 cannotBeUsedWithBitcode(arg
);
2314 else if ( strcmp(arg
, "-dylib") == 0 ) {
2315 fOutputKind
= kDynamicLibrary
;
2317 else if ( strcmp(arg
, "-bundle") == 0 ) {
2318 fOutputKind
= kDynamicBundle
;
2319 cannotBeUsedWithBitcode(arg
);
2321 else if ( strcmp(arg
, "-dylinker") == 0 ) {
2322 fOutputKind
= kDyld
;
2323 cannotBeUsedWithBitcode(arg
);
2325 else if ( strcmp(arg
, "-execute") == 0 ) {
2326 if ( fOutputKind
!= kStaticExecutable
)
2327 fOutputKind
= kDynamicExecutable
;
2329 else if ( strcmp(arg
, "-preload") == 0 ) {
2330 fOutputKind
= kPreload
;
2331 cannotBeUsedWithBitcode(arg
);
2333 else if ( strcmp(arg
, "-r") == 0 ) {
2334 fOutputKind
= kObjectFile
;
2336 else if ( strcmp(arg
, "-kext") == 0 ) {
2337 fOutputKind
= kKextBundle
;
2338 cannotBeUsedWithBitcode(arg
);
2340 else if ( strcmp(arg
, "-o") == 0 ) {
2341 snapshotArgCount
= 0;
2342 fOutputFile
= argv
[++i
];
2343 fLinkSnapshot
.setSnapshotName(fOutputFile
);
2345 else if ( strncmp(arg
, "-lazy-l", 7) == 0 ) {
2346 snapshotArgCount
= 0;
2347 FileInfo info
= findLibrary(&arg
[7], true);
2348 info
.options
.fLazyLoad
= true;
2349 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2351 fUsingLazyDylibLinking
= true;
2352 cannotBeUsedWithBitcode(arg
);
2354 else if ( strcmp(arg
, "-lto_library") == 0 ) {
2355 snapshotFileArgIndex
= 1;
2356 fOverridePathlibLTO
= argv
[++i
];
2357 if ( fOverridePathlibLTO
== NULL
)
2358 throw "missing argument to -lto_library";
2360 else if ( (arg
[1] == 'l') && (strncmp(arg
,"-lazy_",6) !=0) ) {
2361 snapshotArgCount
= 0;
2362 FileInfo info
= findLibrary(&arg
[2]);
2363 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2366 // This causes a dylib to be weakly bound at
2367 // link time. This corresponds to weak_import.
2368 else if ( strncmp(arg
, "-weak-l", 7) == 0 ) {
2369 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2370 snapshotArgCount
= 0;
2371 FileInfo info
= findLibrary(&arg
[7]);
2372 info
.options
.fWeakImport
= true;
2373 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2376 // Avoid lazy binding.
2377 else if ( strcmp(arg
, "-bind_at_load") == 0 ) {
2379 cannotBeUsedWithBitcode(arg
);
2381 else if ( strcmp(arg
, "-twolevel_namespace") == 0 ) {
2382 fNameSpace
= kTwoLevelNameSpace
;
2384 else if ( strcmp(arg
, "-flat_namespace") == 0 ) {
2385 fNameSpace
= kFlatNameSpace
;
2386 cannotBeUsedWithBitcode(arg
);
2388 // Also sets a bit to ensure dyld causes everything
2389 // in the namespace to be flat.
2391 else if ( strcmp(arg
, "-force_flat_namespace") == 0 ) {
2392 fNameSpace
= kForceFlatNameSpace
;
2393 cannotBeUsedWithBitcode(arg
);
2395 // Similar to --whole-archive.
2396 else if ( strcmp(arg
, "-all_load") == 0 ) {
2397 fFullyLoadArchives
= true;
2399 else if ( strcmp(arg
, "-noall_load") == 0) {
2402 // Similar to -all_load
2403 else if ( strcmp(arg
, "-ObjC") == 0 ) {
2404 fLoadAllObjcObjectsFromArchives
= true;
2406 // Similar to -all_load, but for the following archive only.
2407 else if ( strcmp(arg
, "-force_load") == 0 ) {
2408 FileInfo info
= findFile(argv
[++i
]);
2409 info
.options
.fForceLoad
= true;
2410 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2413 // Library versioning.
2414 else if ( (strcmp(arg
, "-dylib_compatibility_version") == 0)
2415 || (strcmp(arg
, "-compatibility_version") == 0)) {
2416 const char* vers
= argv
[++i
];
2418 throw "-dylib_compatibility_version missing <version>";
2419 fDylibCompatVersion
= parseVersionNumber32(vers
);
2421 else if ( (strcmp(arg
, "-dylib_current_version") == 0)
2422 || (strcmp(arg
, "-current_version") == 0)) {
2423 const char* vers
= argv
[++i
];
2425 throw "-dylib_current_version missing <version>";
2426 fDylibCurrentVersion
= parseVersionNumber64(vers
);
2428 else if ( strcmp(arg
, "-sectorder") == 0 ) {
2429 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2430 throw "-sectorder missing <segment> <section> <file-path>";
2431 snapshotFileArgIndex
= 3;
2432 parseSectionOrderFile(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2434 cannotBeUsedWithBitcode(arg
);
2436 else if ( strcmp(arg
, "-order_file") == 0 ) {
2437 snapshotFileArgIndex
= 1;
2438 parseOrderFile(argv
[++i
], false);
2440 else if ( strcmp(arg
, "-order_file_statistics") == 0 ) {
2441 fPrintOrderFileStatistics
= true;
2442 cannotBeUsedWithBitcode(arg
);
2444 // ??? Deprecate segcreate.
2445 // -sectcreate puts whole files into a section in the output.
2446 else if ( (strcmp(arg
, "-sectcreate") == 0) || (strcmp(arg
, "-segcreate") == 0) ) {
2447 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2448 throw "-sectcreate missing <segment> <section> <file-path>";
2449 snapshotFileArgIndex
= 3;
2450 addSection(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2453 // Since we have a full path in binary/library names we need to be able to override it.
2454 else if ( (strcmp(arg
, "-dylib_install_name") == 0)
2455 || (strcmp(arg
, "-dylinker_install_name") == 0)
2456 || (strcmp(arg
, "-install_name") == 0)) {
2457 fDylibInstallName
= argv
[++i
];
2458 if ( fDylibInstallName
== NULL
)
2459 throw "-install_name missing <path>";
2461 // Sets the base address of the output.
2462 else if ( (strcmp(arg
, "-seg1addr") == 0) || (strcmp(arg
, "-image_base") == 0) ) {
2463 const char* address
= argv
[++i
];
2464 if ( address
== NULL
)
2465 throwf("%s missing <address>", arg
);
2466 fBaseAddress
= parseAddress(address
);
2467 uint64_t temp
= ((fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
2468 if ( fBaseAddress
!= temp
) {
2469 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment
);
2470 fBaseAddress
= temp
;
2472 cannotBeUsedWithBitcode(arg
);
2474 else if ( strcmp(arg
, "-e") == 0 ) {
2475 fEntryName
= argv
[++i
];
2477 // Same as -@ from the FSF linker.
2478 else if ( strcmp(arg
, "-filelist") == 0 ) {
2479 snapshotArgCount
= 0;
2480 const char* path
= argv
[++i
];
2481 if ( (path
== NULL
) || (path
[0] == '-') )
2482 throw "-filelist missing <path>";
2483 ld::File::Ordinal baseOrdinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2484 loadFileList(path
, baseOrdinal
);
2486 else if ( strcmp(arg
, "-keep_private_externs") == 0 ) {
2487 cannotBeUsedWithBitcode(arg
);
2488 fKeepPrivateExterns
= true;
2490 else if ( strcmp(arg
, "-final_output") == 0 ) {
2491 fFinalName
= argv
[++i
];
2493 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
2494 // just ensures that this happens for cross object file boundaries.
2495 else if ( (strcmp(arg
, "-interposable") == 0) || (strcmp(arg
, "-multi_module") == 0)) {
2496 switch ( fInterposeMode
) {
2497 case kInterposeNone
:
2498 case kInterposeAllExternal
:
2499 fInterposeMode
= kInterposeAllExternal
;
2501 case kInterposeSome
:
2502 // do nothing, -interposable_list overrides -interposable"
2505 cannotBeUsedWithBitcode(arg
);
2507 else if ( strcmp(arg
, "-interposable_list") == 0 ) {
2508 snapshotFileArgIndex
= 1;
2509 fInterposeMode
= kInterposeSome
;
2510 loadExportFile(argv
[++i
], "-interposable_list", fInterposeList
);
2511 cannotBeUsedWithBitcode(arg
);
2513 // Default for -interposable/-multi_module/-single_module.
2514 else if ( strcmp(arg
, "-single_module") == 0 ) {
2515 fInterposeMode
= kInterposeNone
;
2517 else if ( strcmp(arg
, "-exported_symbols_list") == 0 ) {
2518 snapshotFileArgIndex
= 1;
2519 if ( fExportMode
== kDontExportSome
)
2520 throw "can't use -exported_symbols_list and -unexported_symbols_list";
2521 fExportMode
= kExportSome
;
2522 loadExportFile(argv
[++i
], "-exported_symbols_list", fExportSymbols
);
2524 else if ( strcmp(arg
, "-unexported_symbols_list") == 0 ) {
2525 snapshotFileArgIndex
= 1;
2526 if ( fExportMode
== kExportSome
)
2527 throw "can't use -unexported_symbols_list and -exported_symbols_list";
2528 fExportMode
= kDontExportSome
;
2529 loadExportFile(argv
[++i
], "-unexported_symbols_list", fDontExportSymbols
);
2531 else if ( strcmp(arg
, "-exported_symbol") == 0 ) {
2532 if ( fExportMode
== kDontExportSome
)
2533 throw "can't use -exported_symbol and -unexported_symbols";
2534 fExportMode
= kExportSome
;
2535 fExportSymbols
.insert(argv
[++i
]);
2537 else if ( strcmp(arg
, "-unexported_symbol") == 0 ) {
2538 if ( fExportMode
== kExportSome
)
2539 throw "can't use -unexported_symbol and -exported_symbol";
2540 fExportMode
= kDontExportSome
;
2541 fDontExportSymbols
.insert(argv
[++i
]);
2543 else if ( strcmp(arg
, "-non_global_symbols_no_strip_list") == 0 ) {
2544 snapshotFileArgIndex
= 1;
2545 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveExclude
)
2546 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2547 fLocalSymbolHandling
= kLocalSymbolsSelectiveInclude
;
2548 loadExportFile(argv
[++i
], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded
);
2549 cannotBeUsedWithBitcode(arg
);
2551 else if ( strcmp(arg
, "-non_global_symbols_strip_list") == 0 ) {
2552 snapshotFileArgIndex
= 1;
2553 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveInclude
)
2554 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2555 fLocalSymbolHandling
= kLocalSymbolsSelectiveExclude
;
2556 loadExportFile(argv
[++i
], "-non_global_symbols_strip_list", fLocalSymbolsExcluded
);
2557 cannotBeUsedWithBitcode(arg
);
2560 else if ( strcmp(arg
, "-no_arch_warnings") == 0 ) {
2561 fIgnoreOtherArchFiles
= true;
2563 else if ( strcmp(arg
, "-force_cpusubtype_ALL") == 0 ) {
2564 fForceSubtypeAll
= true;
2565 fAllowCpuSubtypeMismatches
= true;
2566 cannotBeUsedWithBitcode(arg
);
2568 // Similar to -weak-l but uses the absolute path name to the library.
2569 else if ( strcmp(arg
, "-weak_library") == 0 ) {
2570 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2571 snapshotArgCount
= 0;
2572 FileInfo info
= findFile(argv
[++i
]);
2573 info
.options
.fWeakImport
= true;
2574 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2576 cannotBeUsedWithBitcode(arg
);
2578 else if ( strcmp(arg
, "-lazy_library") == 0 ) {
2579 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2580 snapshotArgCount
= 0;
2581 FileInfo info
= findFile(argv
[++i
]);
2582 info
.options
.fLazyLoad
= true;
2583 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2585 fUsingLazyDylibLinking
= true;
2586 cannotBeUsedWithBitcode(arg
);
2588 else if ( strcmp(arg
, "-framework") == 0 ) {
2589 snapshotArgCount
= 0;
2590 FileInfo info
= findFramework(argv
[++i
]);
2591 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2594 else if ( strcmp(arg
, "-weak_framework") == 0 ) {
2595 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2596 snapshotArgCount
= 0;
2597 FileInfo info
= findFramework(argv
[++i
]);
2598 info
.options
.fWeakImport
= true;
2599 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2602 else if ( strcmp(arg
, "-lazy_framework") == 0 ) {
2603 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2604 snapshotArgCount
= 0;
2605 FileInfo info
= findFramework(argv
[++i
]);
2606 info
.options
.fLazyLoad
= true;
2607 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2609 fUsingLazyDylibLinking
= true;
2610 cannotBeUsedWithBitcode(arg
);
2612 else if ( strcmp(arg
, "-search_paths_first") == 0 ) {
2613 // previously handled by buildSearchPaths()
2615 else if ( strcmp(arg
, "-search_dylibs_first") == 0 ) {
2616 // previously handled by buildSearchPaths()
2618 else if ( strcmp(arg
, "-undefined") == 0 ) {
2619 setUndefinedTreatment(argv
[++i
]);
2620 cannotBeUsedWithBitcode(arg
);
2622 // Debugging output flag.
2623 else if ( strcmp(arg
, "-arch_multiple") == 0 ) {
2624 fMessagesPrefixedWithArchitecture
= true;
2626 // Specify what to do with relocations in read only
2627 // sections like .text. Could be errors, warnings,
2628 // or suppressed. Currently we do nothing with the
2630 else if ( strcmp(arg
, "-read_only_relocs") == 0 ) {
2631 switch ( parseTreatment(argv
[++i
]) ) {
2634 throw "-read_only_relocs missing [ warning | error | suppress ]";
2636 fWarnTextRelocs
= true;
2637 fAllowTextRelocs
= true;
2638 cannotBeUsedWithBitcode(arg
);
2641 fWarnTextRelocs
= false;
2642 fAllowTextRelocs
= true;
2643 cannotBeUsedWithBitcode(arg
);
2646 fWarnTextRelocs
= false;
2647 fAllowTextRelocs
= false;
2651 else if ( strcmp(arg
, "-sect_diff_relocs") == 0 ) {
2655 // Warn, error or make strong a mismatch between weak
2656 // and non-weak references.
2657 else if ( strcmp(arg
, "-weak_reference_mismatches") == 0 ) {
2658 setWeakReferenceMismatchTreatment(argv
[++i
]);
2660 // For a deployment target of 10.3 and earlier ld64 will
2661 // prebind an executable with 0s in all addresses that
2662 // are prebound. This can then be fixed up by update_prebinding
2663 // later. Prebinding is less useful on 10.4 and greater.
2664 else if ( strcmp(arg
, "-prebind") == 0 ) {
2666 cannotBeUsedWithBitcode(arg
);
2668 else if ( strcmp(arg
, "-noprebind") == 0 ) {
2672 else if ( strcmp(arg
, "-prebind_allow_overlap") == 0 ) {
2675 else if ( strcmp(arg
, "-prebind_all_twolevel_modules") == 0 ) {
2678 else if ( strcmp(arg
, "-noprebind_all_twolevel_modules") == 0 ) {
2681 else if ( strcmp(arg
, "-nofixprebinding") == 0 ) {
2684 // This should probably be deprecated when we respect -L and -F
2685 // when searching for libraries.
2686 else if ( strcmp(arg
, "-dylib_file") == 0 ) {
2687 // ignore for snapshot because a stub dylib will be created in the snapshot
2688 snapshotArgCount
= 0;
2689 addDylibOverride(argv
[++i
]);
2690 cannotBeUsedWithBitcode(arg
);
2692 // What to expand @executable_path to if found in dependent dylibs
2693 else if ( strcmp(arg
, "-executable_path") == 0 ) {
2694 fExecutablePath
= argv
[++i
];
2695 if ( (fExecutablePath
== NULL
) || (fExecutablePath
[0] == '-') )
2696 throw "-executable_path missing <path>";
2697 // if a directory was passed, add / to end
2698 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2699 struct stat statBuffer
;
2700 if ( stat(fExecutablePath
, &statBuffer
) == 0 ) {
2701 if ( (statBuffer
.st_mode
& S_IFMT
) == S_IFDIR
) {
2702 char* pathWithSlash
= new char[strlen(fExecutablePath
)+2];
2703 strcpy(pathWithSlash
, fExecutablePath
);
2704 strcat(pathWithSlash
, "/");
2705 fExecutablePath
= pathWithSlash
;
2709 // Aligns all segments to the power of 2 boundary specified.
2710 else if ( strcmp(arg
, "-segalign") == 0 ) {
2711 const char* size
= argv
[++i
];
2713 throw "-segalign missing <size>";
2714 fSegmentAlignment
= parseAddress(size
);
2715 uint8_t alignment
= (uint8_t)__builtin_ctz(fSegmentAlignment
);
2716 uint32_t p2aligned
= (1 << alignment
);
2717 if ( p2aligned
!= fSegmentAlignment
) {
2718 warning("alignment for -segalign %s is not a power of two, using 0x%X", size
, p2aligned
);
2719 fSegmentAlignment
= p2aligned
;
2721 cannotBeUsedWithBitcode(arg
);
2723 // Puts a specified segment at a particular address that must
2724 // be a multiple of the segment alignment.
2725 else if ( strcmp(arg
, "-segaddr") == 0 ) {
2727 seg
.name
= argv
[++i
];
2728 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2729 throw "-segaddr missing segName Adddress";
2730 seg
.address
= parseAddress(argv
[++i
]);
2731 uint64_t temp
= ((seg
.address
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
2732 if ( seg
.address
!= temp
)
2733 warning("-segaddr %s not %lld byte aligned", seg
.name
, fSegmentAlignment
);
2734 fCustomSegmentAddresses
.push_back(seg
);
2735 cannotBeUsedWithBitcode(arg
);
2737 // ??? Deprecate when we deprecate split-seg.
2738 else if ( strcmp(arg
, "-segs_read_only_addr") == 0 ) {
2739 fBaseAddress
= parseAddress(argv
[++i
]);
2740 cannotBeUsedWithBitcode(arg
);
2742 // ??? Deprecate when we deprecate split-seg.
2743 else if ( strcmp(arg
, "-segs_read_write_addr") == 0 ) {
2744 fBaseWritableAddress
= parseAddress(argv
[++i
]);
2746 cannotBeUsedWithBitcode(arg
);
2748 // ??? Deprecate when we get rid of basing at build time.
2749 else if ( strcmp(arg
, "-seg_addr_table") == 0 ) {
2750 snapshotFileArgIndex
= 1;
2751 const char* name
= argv
[++i
];
2753 throw "-seg_addr_table missing argument";
2754 fSegAddrTablePath
= name
;
2755 cannotBeUsedWithBitcode(arg
);
2757 else if ( strcmp(arg
, "-seg_addr_table_filename") == 0 ) {
2761 else if ( strcmp(arg
, "-segprot") == 0 ) {
2763 seg
.name
= argv
[++i
];
2764 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) || (argv
[i
+2] == NULL
) )
2765 throw "-segprot missing segName max-prot init-prot";
2766 seg
.max
= parseProtection(argv
[++i
]);
2767 seg
.init
= parseProtection(argv
[++i
]);
2768 if ( strcmp(seg
.name
, "__LINKEDIT") == 0 )
2769 warning("-segprot cannot be used to modify __LINKEDIT protections");
2771 fCustomSegmentProtections
.push_back(seg
);
2772 cannotBeUsedWithBitcode(arg
);
2774 else if ( strcmp(arg
, "-pagezero_size") == 0 ) {
2775 const char* size
= argv
[++i
];
2777 throw "-pagezero_size missing <size>";
2778 fZeroPageSize
= parseAddress(size
);
2779 uint64_t temp
= fZeroPageSize
& (-4096); // page align
2780 if ( (fZeroPageSize
!= temp
) )
2781 warning("-pagezero_size not page aligned, rounding down");
2782 fZeroPageSize
= temp
;
2783 cannotBeUsedWithBitcode(arg
);
2785 else if ( strcmp(arg
, "-stack_addr") == 0 ) {
2786 const char* address
= argv
[++i
];
2787 if ( address
== NULL
)
2788 throw "-stack_addr missing <address>";
2789 fStackAddr
= parseAddress(address
);
2790 cannotBeUsedWithBitcode(arg
);
2792 else if ( strcmp(arg
, "-stack_size") == 0 ) {
2793 const char* size
= argv
[++i
];
2795 throw "-stack_size missing <address>";
2796 fStackSize
= parseAddress(size
);
2798 else if ( strcmp(arg
, "-allow_stack_execute") == 0 ) {
2799 fExecutableStack
= true;
2800 cannotBeUsedWithBitcode(arg
);
2802 else if ( strcmp(arg
, "-allow_heap_execute") == 0 ) {
2803 fDisableNonExecutableHeap
= true;
2804 cannotBeUsedWithBitcode(arg
);
2806 else if ( strcmp(arg
, "-sectalign") == 0 ) {
2807 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2808 throw "-sectalign missing <segment> <section> <file-path>";
2809 addSectionAlignment(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2811 cannotBeUsedWithBitcode(arg
);
2813 else if ( strcmp(arg
, "-sectorder_detail") == 0 ) {
2816 else if ( strcmp(arg
, "-sectobjectsymbols") == 0 ) {
2820 else if ( strcmp(arg
, "-bundle_loader") == 0 ) {
2821 snapshotFileArgIndex
= 1;
2822 fBundleLoader
= argv
[++i
];
2823 if ( (fBundleLoader
== NULL
) || (fBundleLoader
[0] == '-') )
2824 throw "-bundle_loader missing <path>";
2825 FileInfo info
= findFile(fBundleLoader
);
2826 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2827 info
.options
.fBundleLoader
= true;
2828 fInputFiles
.push_back(info
);
2830 else if ( strcmp(arg
, "-private_bundle") == 0 ) {
2833 else if ( strcmp(arg
, "-twolevel_namespace_hints") == 0 ) {
2836 // Use this flag to set default behavior for deployement targets.
2837 else if ( strcmp(arg
, "-macosx_version_min") == 0 ) {
2838 const char* macVers
= argv
[++i
];
2839 if ( macVers
== NULL
)
2840 throw "-macosx_version_min missing version argument";
2841 const char* envMacVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
2842 const char* enviPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
2843 if ( (envMacVers
!= NULL
) && (enviPhoneVers
!= NULL
) ) {
2844 // <rdar://problem/13774329> when conflicting deployments set, break tie by looking at syslibroot
2845 warning("both MACOSX_DEPLOYMENT_TARGET and IPHONEOS_DEPLOYMENT_TARGET are set");
2846 if ( !fSDKPaths
.empty() ) {
2847 const char* sysrootPath
= fSDKPaths
.back();
2848 const char* lastSlash
= strrchr(sysrootPath
, '/');
2849 if ( strstr(lastSlash
, "Simulator") != NULL
)
2850 setIOSVersionMin(enviPhoneVers
);
2852 setMacOSXVersionMin(macVers
);
2855 setMacOSXVersionMin(macVers
);
2859 setMacOSXVersionMin(macVers
);
2862 else if ( (strcmp(arg
, "-ios_version_min") == 0) || (strcmp(arg
, "-iphoneos_version_min") == 0) ) {
2863 const char* vers
= argv
[++i
];
2865 throw "-ios_version_min missing version argument";
2866 setIOSVersionMin(vers
);
2868 else if ( strcmp(arg
, "-ios_simulator_version_min") == 0 ) {
2869 const char* vers
= argv
[++i
];
2871 throw "-ios_simulator_version_min missing version argument";
2872 setIOSVersionMin(vers
);
2873 fTargetIOSSimulator
= true;
2875 else if ( strcmp(arg
, "-watchos_version_min") == 0 ) {
2876 const char* vers
= argv
[++i
];
2878 throw "-watchos_version_min missing version argument";
2879 setWatchOSVersionMin(vers
);
2881 else if ( strcmp(arg
, "-watchos_simulator_version_min") == 0 ) {
2882 const char* vers
= argv
[++i
];
2884 throw "-watchos_simulator_version_min missing version argument";
2885 setWatchOSVersionMin(vers
);
2886 fTargetIOSSimulator
= true;
2888 #if SUPPORT_APPLE_TV
2889 else if ( strcmp(arg
, "-tvos_version_min") == 0 ) {
2890 const char* vers
= argv
[++i
];
2892 throw "-tvos_version_min missing version argument";
2893 setIOSVersionMin(vers
);
2894 fPlatform
= kPlatform_tvOS
;
2896 else if ( strcmp(arg
, "-tvos_simulator_version_min") == 0 ) {
2897 const char* vers
= argv
[++i
];
2899 throw "-tvos_simulator_version_min missing version argument";
2900 setIOSVersionMin(vers
);
2901 fPlatform
= kPlatform_tvOS
;
2902 fTargetIOSSimulator
= true;
2905 else if ( strcmp(arg
, "-multiply_defined") == 0 ) {
2906 //warnObsolete(arg);
2909 else if ( strcmp(arg
, "-multiply_defined_unused") == 0 ) {
2913 else if ( strcmp(arg
, "-nomultidefs") == 0 ) {
2916 // Display each file in which the argument symbol appears and whether
2917 // the file defines or references it. This option takes an argument
2918 // as -y<symbol> note that there is no space.
2919 else if ( strncmp(arg
, "-y", 2) == 0 ) {
2922 // Same output as -y, but output <arg> number of undefined symbols only.
2923 else if ( strcmp(arg
, "-Y") == 0 ) {
2924 //warnObsolete(arg);
2927 // This option affects all objects linked into the final result.
2928 else if ( strcmp(arg
, "-m") == 0 ) {
2931 else if ( (strcmp(arg
, "-why_load") == 0) || (strcmp(arg
, "-whyload") == 0) ) {
2934 else if ( strcmp(arg
, "-why_live") == 0 ) {
2935 const char* name
= argv
[++i
];
2937 throw "-why_live missing symbol name argument";
2938 fWhyLive
.insert(name
);
2940 else if ( strcmp(arg
, "-u") == 0 ) {
2941 const char* name
= argv
[++i
];
2943 throw "-u missing argument";
2944 fInitialUndefines
.push_back(name
);
2945 cannotBeUsedWithBitcode(arg
);
2947 else if ( strcmp(arg
, "-U") == 0 ) {
2948 const char* name
= argv
[++i
];
2950 throw "-U missing argument";
2951 fAllowedUndefined
.insert(name
);
2952 cannotBeUsedWithBitcode(arg
);
2954 else if ( strcmp(arg
, "-s") == 0 ) {
2956 fLocalSymbolHandling
= kLocalSymbolsNone
;
2957 fDebugInfoStripping
= Options::kDebugInfoNone
;
2959 else if ( strcmp(arg
, "-x") == 0 ) {
2960 fLocalSymbolHandling
= kLocalSymbolsNone
;
2962 else if ( strcmp(arg
, "-S") == 0 ) {
2963 fDebugInfoStripping
= Options::kDebugInfoNone
;
2965 else if ( strcmp(arg
, "-X") == 0 ) {
2968 else if ( strcmp(arg
, "-Si") == 0 ) {
2970 fDebugInfoStripping
= Options::kDebugInfoFull
;
2972 else if ( strcmp(arg
, "-b") == 0 ) {
2975 else if ( strcmp(arg
, "-Sn") == 0 ) {
2977 fDebugInfoStripping
= Options::kDebugInfoFull
;
2979 else if ( strcmp(arg
, "-Sp") == 0 ) {
2982 else if ( strcmp(arg
, "-dead_strip") == 0 ) {
2985 else if ( strcmp(arg
, "-no_dead_strip_inits_and_terms") == 0 ) {
2988 else if ( strcmp(arg
, "-w") == 0 ) {
2989 // previously handled by buildSearchPaths()
2991 else if ( strcmp(arg
, "-fatal_warnings") == 0 ) {
2992 // previously handled by buildSearchPaths()
2994 else if ( strcmp(arg
, "-arch_errors_fatal") == 0 ) {
2995 fErrorOnOtherArchFiles
= true;
2997 else if ( strcmp(arg
, "-M") == 0 ) {
3000 else if ( strcmp(arg
, "-headerpad") == 0 ) {
3001 const char* size
= argv
[++i
];
3003 throw "-headerpad missing argument";
3004 fMinimumHeaderPad
= parseAddress(size
);
3005 cannotBeUsedWithBitcode(arg
);
3007 else if ( strcmp(arg
, "-headerpad_max_install_names") == 0 ) {
3008 // ignore -headerpad_max_install_names when compiling with bitcode
3009 // rdar://problem/20748962
3010 if ( fBundleBitcode
)
3011 warning("-headerpad_max_install_names is ignored when used with -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES)");
3013 fMaxMinimumHeaderPad
= true;
3015 else if ( strcmp(arg
, "-t") == 0 ) {
3016 fLogAllFiles
= true;
3018 else if ( strcmp(arg
, "-whatsloaded") == 0 ) {
3019 fLogObjectFiles
= true;
3021 else if ( strcmp(arg
, "-A") == 0 ) {
3025 else if ( strcmp(arg
, "-umbrella") == 0 ) {
3026 const char* name
= argv
[++i
];
3028 throw "-umbrella missing argument";
3029 fUmbrellaName
= name
;
3030 cannotBeUsedWithBitcode(arg
);
3032 else if ( strcmp(arg
, "-allowable_client") == 0 ) {
3033 const char* name
= argv
[++i
];
3036 throw "-allowable_client missing argument";
3038 fAllowableClients
.push_back(name
);
3039 cannotBeUsedWithBitcode(arg
);
3041 else if ( strcmp(arg
, "-client_name") == 0 ) {
3042 const char* name
= argv
[++i
];
3045 throw "-client_name missing argument";
3048 cannotBeUsedWithBitcode(arg
);
3050 else if ( strcmp(arg
, "-sub_umbrella") == 0 ) {
3051 const char* name
= argv
[++i
];
3053 throw "-sub_umbrella missing argument";
3054 fSubUmbellas
.push_back(name
);
3055 cannotBeUsedWithBitcode(arg
);
3057 else if ( strcmp(arg
, "-sub_library") == 0 ) {
3058 const char* name
= argv
[++i
];
3060 throw "-sub_library missing argument";
3061 fSubLibraries
.push_back(name
);
3062 cannotBeUsedWithBitcode(arg
);
3064 else if ( strcmp(arg
, "-init") == 0 ) {
3065 const char* name
= argv
[++i
];
3067 throw "-init missing argument";
3068 fInitFunctionName
= name
;
3069 cannotBeUsedWithBitcode(arg
);
3071 else if ( strcmp(arg
, "-dot") == 0 ) {
3072 const char* name
= argv
[++i
];
3074 throw "-dot missing argument";
3075 fDotOutputFile
= name
;
3076 cannotBeUsedWithBitcode(arg
);
3078 else if ( strcmp(arg
, "-warn_commons") == 0 ) {
3079 fWarnCommons
= true;
3081 else if ( strcmp(arg
, "-commons") == 0 ) {
3082 fCommonsMode
= parseCommonsTreatment(argv
[++i
]);
3084 else if ( strcmp(arg
, "-keep_relocs") == 0 ) {
3085 fKeepRelocations
= true;
3087 else if ( strcmp(arg
, "-warn_stabs") == 0 ) {
3090 else if ( strcmp(arg
, "-pause") == 0 ) {
3093 else if ( strcmp(arg
, "-print_statistics") == 0 ) {
3096 else if ( strcmp(arg
, "-d") == 0 ) {
3097 fMakeTentativeDefinitionsReal
= true;
3099 else if ( strcmp(arg
, "-v") == 0 ) {
3100 // previously handled by buildSearchPaths()
3102 else if ( strcmp(arg
, "-Z") == 0 ) {
3103 // previously handled by buildSearchPaths()
3105 else if ( strcmp(arg
, "-syslibroot") == 0 ) {
3106 snapshotArgCount
= 0;
3108 // previously handled by buildSearchPaths()
3110 else if ( strcmp(arg
, "-bitcode_bundle") == 0 ) {
3111 snapshotArgCount
= 0;
3112 // previously handled by buildSearchPaths()
3114 else if ( strcmp(arg
, "-no_uuid") == 0 ) {
3115 fUUIDMode
= kUUIDNone
;
3116 cannotBeUsedWithBitcode(arg
);
3118 else if ( strcmp(arg
, "-random_uuid") == 0 ) {
3119 fUUIDMode
= kUUIDRandom
;
3120 cannotBeUsedWithBitcode(arg
);
3122 else if ( strcmp(arg
, "-dtrace") == 0 ) {
3123 snapshotFileArgIndex
= 1;
3124 const char* name
= argv
[++i
];
3126 throw "-dtrace missing argument";
3127 fDtraceScriptName
= name
;
3128 cannotBeUsedWithBitcode(arg
);
3130 else if ( strcmp(arg
, "-root_safe") == 0 ) {
3133 else if ( strcmp(arg
, "-setuid_safe") == 0 ) {
3136 else if ( strcmp(arg
, "-alias") == 0 ) {
3137 Options::AliasPair pair
;
3138 pair
.realName
= argv
[++i
];
3139 if ( pair
.realName
== NULL
)
3140 throw "missing argument to -alias";
3141 pair
.alias
= argv
[++i
];
3142 if ( pair
.alias
== NULL
)
3143 throw "missing argument to -alias";
3144 fAliases
.push_back(pair
);
3145 cannotBeUsedWithBitcode(arg
);
3147 else if ( strcmp(arg
, "-alias_list") == 0 ) {
3148 snapshotFileArgIndex
= 1;
3149 parseAliasFile(argv
[++i
]);
3150 cannotBeUsedWithBitcode(arg
);
3152 else if ( strcmp(arg
, "-save-temps") == 0 ) {
3153 fSaveTempFiles
= true;
3155 else if ( strcmp(arg
, "-bitcode_hide_symbols") == 0 ) {
3156 fHideSymbols
= true;
3158 else if ( strcmp(arg
, "-bitcode_verify") == 0 ) {
3159 fVerifyBitcode
= true;
3161 else if ( strcmp(arg
, "-bitcode_symbol_map") == 0) {
3162 fReverseMapPath
= argv
[++i
];
3163 if ( fReverseMapPath
== NULL
)
3164 throw "missing argument to -bitcode_symbol_map";
3165 struct stat statbuf
;
3166 ::stat(fReverseMapPath
, &statbuf
);
3167 if (S_ISDIR(statbuf
.st_mode
)) {
3168 char tempPath
[PATH_MAX
];
3169 sprintf(tempPath
, "%s/XXXXXX", fReverseMapPath
);
3170 int tempFile
= ::mkstemp(tempPath
);
3172 throwf("could not write file to symbol map directory: %s", fReverseMapPath
);
3174 fReverseMapTempPath
= std::string(tempPath
);
3175 fReverseMapUUIDRename
= true;
3177 fReverseMapTempPath
= std::string(fReverseMapPath
);
3179 else if ( strcmp(argv
[i
], "-flto-codegen-only") == 0) {
3180 fLTOCodegenOnly
= true;
3182 else if ( strcmp(argv
[i
], "-ignore_auto_link") == 0) {
3183 fIgnoreAutoLink
= true;
3185 else if ( strcmp(argv
[i
], "-allow_dead_duplicates") == 0) {
3186 fAllowDeadDups
= true;
3188 else if ( strcmp(argv
[i
], "-bitcode_process_mode") == 0 ) {
3189 const char* bitcode_type
= argv
[++i
];
3190 if ( bitcode_type
== NULL
)
3191 throw "missing argument to -bitcode_process_mode";
3192 else if ( strcmp(bitcode_type
, "strip") == 0 )
3193 fBitcodeKind
= kBitcodeStrip
;
3194 else if ( strcmp(bitcode_type
, "marker") == 0 )
3195 fBitcodeKind
= kBitcodeMarker
;
3196 else if ( strcmp(bitcode_type
, "data") == 0 )
3197 fBitcodeKind
= kBitcodeAsData
;
3198 else if ( strcmp(bitcode_type
, "bitcode") == 0 )
3199 fBitcodeKind
= kBitcodeProcess
;
3201 throw "unknown argument to -bitcode_process_mode {strip,marker,data,bitcode}";
3203 else if ( strcmp(arg
, "-rpath") == 0 ) {
3204 const char* path
= argv
[++i
];
3206 throw "missing argument to -rpath";
3207 fRPaths
.push_back(path
);
3209 else if ( strcmp(arg
, "-read_only_stubs") == 0 ) {
3210 fReadOnlyx86Stubs
= true;
3212 else if ( strcmp(arg
, "-slow_stubs") == 0 ) {
3215 else if ( strcmp(arg
, "-map") == 0 ) {
3216 fMapPath
= argv
[++i
];
3217 if ( fMapPath
== NULL
)
3218 throw "missing argument to -map";
3220 else if ( strcmp(arg
, "-pie") == 0 ) {
3221 fPositionIndependentExecutable
= true;
3222 fPIEOnCommandLine
= true;
3224 else if ( strcmp(arg
, "-no_pie") == 0 ) {
3225 fDisablePositionIndependentExecutable
= true;
3226 cannotBeUsedWithBitcode(arg
);
3228 else if ( strncmp(arg
, "-reexport-l", 11) == 0 ) {
3229 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3230 snapshotArgCount
= 0;
3231 FileInfo info
= findLibrary(&arg
[11], true);
3232 info
.options
.fReExport
= true;
3233 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3235 cannotBeUsedWithBitcode(arg
);
3237 else if ( strcmp(arg
, "-reexport_library") == 0 ) {
3238 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3239 snapshotArgCount
= 0;
3240 FileInfo info
= findFile(argv
[++i
]);
3241 info
.options
.fReExport
= true;
3242 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3244 cannotBeUsedWithBitcode(arg
);
3246 else if ( strcmp(arg
, "-reexport_framework") == 0 ) {
3247 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3248 snapshotArgCount
= 0;
3249 FileInfo info
= findFramework(argv
[++i
]);
3250 info
.options
.fReExport
= true;
3251 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3253 cannotBeUsedWithBitcode(arg
);
3255 else if ( strncmp(arg
, "-upward-l", 9) == 0 ) {
3256 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3257 snapshotArgCount
= 0;
3258 FileInfo info
= findLibrary(&arg
[9], true);
3259 info
.options
.fUpward
= true;
3260 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3262 cannotBeUsedWithBitcode(arg
);
3264 else if ( strcmp(arg
, "-upward_library") == 0 ) {
3265 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3266 snapshotArgCount
= 0;
3267 FileInfo info
= findFile(argv
[++i
]);
3268 info
.options
.fUpward
= true;
3269 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3271 cannotBeUsedWithBitcode(arg
);
3273 else if ( strcmp(arg
, "-upward_framework") == 0 ) {
3274 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3275 snapshotArgCount
= 0;
3276 FileInfo info
= findFramework(argv
[++i
]);
3277 info
.options
.fUpward
= true;
3278 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3280 cannotBeUsedWithBitcode(arg
);
3282 else if ( strcmp(arg
, "-dead_strip_dylibs") == 0 ) {
3283 fDeadStripDylibs
= true;
3284 cannotBeUsedWithBitcode(arg
);
3286 else if ( strcmp(arg
, "-no_implicit_dylibs") == 0 ) {
3287 fImplicitlyLinkPublicDylibs
= false;
3289 else if ( strcmp(arg
, "-new_linker") == 0 ) {
3292 else if ( strcmp(arg
, "-no_encryption") == 0 ) {
3293 fEncryptableForceOff
= true;
3294 cannotBeUsedWithBitcode(arg
);
3296 else if ( strcmp(arg
, "-encryptable") == 0 ) {
3297 fEncryptableForceOn
= true;
3298 cannotBeUsedWithBitcode(arg
);
3300 else if ( strcmp(arg
, "-no_compact_unwind") == 0 ) {
3301 fAddCompactUnwindEncoding
= false;
3302 cannotBeUsedWithBitcode(arg
);
3304 else if ( strcmp(arg
, "-mllvm") == 0 ) {
3305 const char* opts
= argv
[++i
];
3307 throw "missing argument to -mllvm";
3308 fLLVMOptions
.push_back(opts
);
3309 cannotBeUsedWithBitcode(arg
);
3311 else if ( strcmp(arg
, "-mcpu") == 0 ) {
3312 const char* cpu
= argv
[++i
];
3314 throw "missing argument to -mcpu";
3316 cannotBeUsedWithBitcode(arg
);
3318 else if ( strcmp(arg
, "-no_order_inits") == 0 ) {
3319 fAutoOrderInitializers
= false;
3320 cannotBeUsedWithBitcode(arg
);
3322 else if ( strcmp(arg
, "-no_order_data") == 0 ) {
3324 cannotBeUsedWithBitcode(arg
);
3326 else if ( strcmp(arg
, "-seg_page_size") == 0 ) {
3328 seg
.name
= argv
[++i
];
3329 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
3330 throw "-seg_page_size missing segName Adddress";
3331 seg
.size
= parseAddress(argv
[++i
]);
3332 uint64_t temp
= seg
.size
& (-4096); // page align
3333 if ( (seg
.size
!= temp
) )
3334 warning("-seg_page_size %s not 4K aligned, rounding down", seg
.name
);
3335 fCustomSegmentSizes
.push_back(seg
);
3336 cannotBeUsedWithBitcode(arg
);
3338 else if ( strcmp(arg
, "-mark_dead_strippable_dylib") == 0 ) {
3339 fMarkDeadStrippableDylib
= true;
3340 cannotBeUsedWithBitcode(arg
);
3342 else if ( strcmp(arg
, "-exported_symbols_order") == 0 ) {
3343 snapshotFileArgIndex
= 1;
3344 loadSymbolOrderFile(argv
[++i
], fExportSymbolsOrder
);
3345 cannotBeUsedWithBitcode(arg
);
3347 else if ( strcmp(arg
, "-no_compact_linkedit") == 0 ) {
3348 warnObsolete("-no_compact_linkedit");
3350 else if ( strcmp(arg
, "-no_eh_labels") == 0 ) {
3352 cannotBeUsedWithBitcode(arg
);
3354 else if ( strcmp(arg
, "-warn_compact_unwind") == 0 ) {
3355 fWarnCompactUnwind
= true;
3357 else if ( strcmp(arg
, "-allow_sub_type_mismatches") == 0 ) {
3358 fAllowCpuSubtypeMismatches
= true;
3359 cannotBeUsedWithBitcode(arg
);
3361 else if ( strcmp(arg
, "-no_zero_fill_sections") == 0 ) {
3362 fOptimizeZeroFill
= false;
3363 cannotBeUsedWithBitcode(arg
);
3365 else if ( strcmp(arg
, "-merge_zero_fill_sections") == 0 ) {
3366 fMergeZeroFill
= true;
3367 cannotBeUsedWithBitcode(arg
);
3369 else if ( strcmp(arg
, "-objc_abi_version") == 0 ) {
3370 const char* version
= argv
[++i
];
3371 if ( version
== NULL
)
3372 throw "-objc_abi_version missing version number";
3373 if ( strcmp(version
, "2") == 0 ) {
3374 fObjCABIVersion1Override
= false;
3375 fObjCABIVersion2Override
= true;
3377 else if ( strcmp(version
, "1") == 0 ) {
3378 fObjCABIVersion1Override
= true;
3379 fObjCABIVersion2Override
= false;
3382 warning("ignoring unrecognized argument (%s) to -objc_abi_version", version
);
3384 else if ( strcmp(arg
, "-warn_weak_exports") == 0 ) {
3385 fWarnWeakExports
= true;
3387 else if ( strcmp(arg
, "-objc_gc_compaction") == 0 ) {
3388 fObjcGcCompaction
= true;
3389 cannotBeUsedWithBitcode(arg
);
3391 else if ( strcmp(arg
, "-objc_gc") == 0 ) {
3393 if ( fObjCGcOnly
) {
3394 warning("-objc_gc overriding -objc_gc_only");
3395 fObjCGcOnly
= false;
3397 cannotBeUsedWithBitcode(arg
);
3399 else if ( strcmp(arg
, "-objc_gc_only") == 0 ) {
3402 warning("-objc_gc_only overriding -objc_gc");
3405 cannotBeUsedWithBitcode(arg
);
3407 else if ( strcmp(arg
, "-demangle") == 0 ) {
3410 else if ( strcmp(arg
, "-version_load_command") == 0 ) {
3411 fVersionLoadCommandForcedOn
= true;
3412 fVersionLoadCommandForcedOff
= false;
3414 else if ( strcmp(arg
, "-no_version_load_command") == 0 ) {
3415 fVersionLoadCommandForcedOff
= true;
3416 fVersionLoadCommandForcedOn
= false;
3417 cannotBeUsedWithBitcode(arg
);
3419 else if ( strcmp(arg
, "-function_starts") == 0 ) {
3420 fFunctionStartsForcedOn
= true;
3421 fFunctionStartsForcedOff
= false;
3423 else if ( strcmp(arg
, "-no_function_starts") == 0 ) {
3424 fFunctionStartsForcedOff
= true;
3425 fFunctionStartsForcedOn
= false;
3426 cannotBeUsedWithBitcode(arg
);
3428 else if ( strcmp(arg
, "-no_data_in_code_info") == 0 ) {
3429 fDataInCodeInfoLoadCommandForcedOff
= true;
3430 fDataInCodeInfoLoadCommandForcedOn
= false;
3431 cannotBeUsedWithBitcode(arg
);
3433 else if ( strcmp(arg
, "-data_in_code_info") == 0 ) {
3434 fDataInCodeInfoLoadCommandForcedOn
= true;
3435 fDataInCodeInfoLoadCommandForcedOff
= false;
3437 else if ( strcmp(arg
, "-object_path_lto") == 0 ) {
3438 fTempLtoObjectPath
= argv
[++i
];
3439 if ( fTempLtoObjectPath
== NULL
)
3440 throw "missing argument to -object_path_lto";
3442 else if ( strcmp(arg
, "-no_objc_category_merging") == 0 ) {
3443 fObjcCategoryMerging
= false;
3445 else if ( strcmp(arg
, "-force_symbols_weak_list") == 0 ) {
3446 snapshotFileArgIndex
= 1;
3447 loadExportFile(argv
[++i
], "-force_symbols_weak_list", fForceWeakSymbols
);
3448 cannotBeUsedWithBitcode(arg
);
3450 else if ( strcmp(arg
, "-force_symbols_not_weak_list") == 0 ) {
3451 snapshotFileArgIndex
= 1;
3452 loadExportFile(argv
[++i
], "-force_symbols_not_weak_list", fForceNotWeakSymbols
);
3453 cannotBeUsedWithBitcode(arg
);
3455 else if ( strcmp(arg
, "-force_symbol_weak") == 0 ) {
3456 const char* symbol
= argv
[++i
];
3457 if ( symbol
== NULL
)
3458 throw "-force_symbol_weak missing <symbol>";
3459 fForceWeakSymbols
.insert(symbol
);
3460 cannotBeUsedWithBitcode(arg
);
3462 else if ( strcmp(arg
, "-force_symbol_not_weak") == 0 ) {
3463 const char* symbol
= argv
[++i
];
3464 if ( symbol
== NULL
)
3465 throw "-force_symbol_not_weak missing <symbol>";
3466 fForceNotWeakSymbols
.insert(symbol
);
3467 cannotBeUsedWithBitcode(arg
);
3469 else if ( strcmp(arg
, "-reexported_symbols_list") == 0 ) {
3470 snapshotFileArgIndex
= 1;
3471 if ( fExportMode
== kExportSome
)
3472 throw "can't use -exported_symbols_list and -reexported_symbols_list";
3473 loadExportFile(argv
[++i
], "-reexported_symbols_list", fReExportSymbols
);
3475 else if ( strcmp(arg
, "-dyld_env") == 0 ) {
3476 const char* envarg
= argv
[++i
];
3477 if ( envarg
== NULL
)
3478 throw "-dyld_env missing ENV=VALUE";
3479 if ( strchr(envarg
, '=') == NULL
)
3480 throw "-dyld_env missing ENV=VALUE";
3481 fDyldEnvironExtras
.push_back(envarg
);
3482 cannotBeUsedWithBitcode(arg
);
3484 else if ( strcmp(arg
, "-page_align_data_atoms") == 0 ) {
3485 fPageAlignDataAtoms
= true;
3486 cannotBeUsedWithBitcode(arg
);
3488 else if (strcmp(arg
, "-debug_snapshot") == 0) {
3489 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
3490 fSnapshotRequested
= true;
3491 cannotBeUsedWithBitcode(arg
);
3493 else if (strcmp(arg
, "-snapshot_dir") == 0) {
3494 const char* path
= argv
[++i
];
3496 throw "-snapshot_dir missing path";
3497 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
3498 fLinkSnapshot
.setSnapshotPath(path
);
3499 fSnapshotRequested
= true;
3500 cannotBeUsedWithBitcode(arg
);
3502 else if ( strcmp(arg
, "-new_main") == 0 ) {
3503 fEntryPointLoadCommandForceOn
= true;
3504 cannotBeUsedWithBitcode(arg
);
3506 else if ( strcmp(arg
, "-no_new_main") == 0 ) {
3507 fEntryPointLoadCommandForceOff
= true;
3508 cannotBeUsedWithBitcode(arg
);
3510 else if ( strcmp(arg
, "-source_version") == 0 ) {
3511 const char* vers
= argv
[++i
];
3513 throw "-source_version missing <version>";
3514 fSourceVersion
= parseVersionNumber64(vers
);
3516 else if ( strcmp(arg
, "-add_source_version") == 0 ) {
3517 fSourceVersionLoadCommandForceOn
= true;
3519 else if ( strcmp(arg
, "-no_source_version") == 0 ) {
3520 fSourceVersionLoadCommandForceOff
= true;
3521 cannotBeUsedWithBitcode(arg
);
3523 else if ( strcmp(arg
, "-sdk_version") == 0 ) {
3524 const char* vers
= argv
[++i
];
3526 throw "-sdk_version missing <version>";
3527 fSDKVersion
= parseVersionNumber32(vers
);
3529 else if ( strcmp(arg
, "-dependent_dr_info") == 0 ) {
3532 else if ( strcmp(arg
, "-no_dependent_dr_info") == 0 ) {
3535 else if ( strcmp(arg
, "-kexts_use_stubs") == 0 ) {
3536 fKextsUseStubs
= true;
3537 cannotBeUsedWithBitcode(arg
);
3539 else if ( strcmp(argv
[i
], "-dependency_info") == 0 ) {
3540 snapshotArgCount
= 0;
3542 // previously handled by buildSearchPaths()
3544 else if ( strcmp(arg
, "-export_dynamic") == 0 ) {
3545 fExportDynamic
= true;
3547 else if ( strcmp(arg
, "-force_symbols_coalesce_list") == 0 ) {
3548 snapshotFileArgIndex
= 1;
3549 loadExportFile(argv
[++i
], "-force_symbols_coalesce_list", fForceCoalesceSymbols
);
3551 else if ( strcmp(arg
, "-add_linker_option") == 0 ) {
3552 // ex: -add_linker_option '-framework Foundation'
3553 const char* optString
= argv
[++i
];
3554 if ( optString
== NULL
)
3555 throw "-add_linker_option missing <option>";
3556 // break up into list of tokens at whitespace
3557 std::vector
<const char*> opts
;
3558 char* buffer
= strdup(optString
);
3559 char* start
= buffer
;
3560 for (char* s
= buffer
; ; ++s
) {
3561 if ( isspace(*s
) ) {
3563 opts
.push_back(start
);
3566 else if ( *s
== '\0' ) {
3567 opts
.push_back(start
);
3571 fLinkerOptions
.push_back(opts
);
3572 cannotBeUsedWithBitcode(arg
);
3574 else if ( strcmp(arg
, "-allow_simulator_linking_to_macosx_dylibs") == 0 ) {
3575 fAllowSimulatorToLinkWithMacOSX
= true;
3576 cannotBeUsedWithBitcode(arg
);
3578 else if ( strcmp(arg
, "-keep_dwarf_unwind") == 0 ) {
3579 fKeepDwarfUnwindForcedOn
= true;
3580 fKeepDwarfUnwindForcedOff
= false;
3581 cannotBeUsedWithBitcode(arg
);
3583 else if ( strcmp(arg
, "-no_keep_dwarf_unwind") == 0 ) {
3584 fKeepDwarfUnwindForcedOn
= false;
3585 fKeepDwarfUnwindForcedOff
= true;
3586 cannotBeUsedWithBitcode(arg
);
3588 else if ( strcmp(arg
, "-verbose_optimization_hints") == 0 ) {
3589 fVerboseOptimizationHints
= true;
3591 else if ( strcmp(arg
, "-ignore_optimization_hints") == 0 ) {
3592 fIgnoreOptimizationHints
= true;
3593 cannotBeUsedWithBitcode(arg
);
3595 else if ( strcmp(arg
, "-no_dtrace_dof") == 0 ) {
3596 fGenerateDtraceDOF
= false;
3598 else if ( strcmp(arg
, "-rename_section") == 0 ) {
3599 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) || (argv
[i
+4]==NULL
) )
3600 throw "-rename_section missing <segment> <section> <segment> <section>";
3601 addSectionRename(argv
[i
+1], argv
[i
+2], argv
[i
+3], argv
[i
+4]);
3603 cannotBeUsedWithBitcode(arg
);
3605 else if ( strcmp(arg
, "-rename_segment") == 0 ) {
3606 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3607 throw "-rename_segment missing <existing-segment> <new-segment>";
3608 addSegmentRename(argv
[i
+1], argv
[i
+2]);
3610 cannotBeUsedWithBitcode(arg
);
3612 else if ( strcmp(arg
, "-move_to_ro_segment") == 0 ) {
3613 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3614 throw "-move_to_ro_segment missing <segment> <symbol-list-file>";
3615 addSymbolMove(argv
[i
+1], argv
[i
+2], fSymbolsMovesCode
, "-move_to_ro_segment");
3617 cannotBeUsedWithBitcode(arg
);
3619 else if ( strcmp(arg
, "-move_to_rw_segment") == 0 ) {
3620 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3621 throw "-move_to_rw_segment missing <segment> <symbol-list-file>";
3622 addSymbolMove(argv
[i
+1], argv
[i
+2], fSymbolsMovesData
, "-move_to_rw_segment");
3624 cannotBeUsedWithBitcode(arg
);
3626 else if ( strcmp(arg
, "-trace_symbol_layout") == 0 ) {
3627 fTraceSymbolLayout
= true;
3629 else if ( strcmp(arg
, "-no_branch_islands") == 0 ) {
3630 fAllowBranchIslands
= false;
3631 cannotBeUsedWithBitcode(arg
);
3633 else if ( strcmp(arg
, "-segment_order") == 0 ) {
3634 // ex: -segment_order __TEXT:__DATA:__JUNK
3635 const char* optString
= argv
[++i
];
3636 if ( optString
== NULL
)
3637 throw "-segment_order missing colon separated <segment-list>";
3638 if ( !fSegmentOrder
.empty() )
3639 throw "-segment_order used more than once";
3640 // break up into list of tokens at colon
3641 char* buffer
= strdup(optString
);
3642 char* start
= buffer
;
3643 for (char* s
= buffer
; ; ++s
) {
3646 fSegmentOrder
.push_back(start
);
3649 else if ( *s
== '\0' ) {
3650 fSegmentOrder
.push_back(start
);
3654 cannotBeUsedWithBitcode(arg
);
3656 else if ( strcmp(arg
, "-section_order") == 0 ) {
3657 // ex: -section_order __DATA __data:__const:__nl_pointers
3658 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3659 throw "-section_order missing <segment> <section-list>";
3660 const char* segName
= argv
[++i
];
3661 const char* optString
= argv
[++i
];
3662 if ( sectionOrder(segName
) != NULL
)
3663 throwf("-section_order %s ... used more than once", segName
);
3664 SectionOrderList dummy
;
3665 fSectionOrder
.push_back(dummy
);
3666 SectionOrderList
& entry
= fSectionOrder
.back();
3667 entry
.segmentName
= segName
;
3668 // break up into list of tokens at colon
3669 char* buffer
= strdup(optString
);
3670 char* start
= buffer
;
3671 for (char* s
= buffer
; ; ++s
) {
3674 entry
.sectionOrder
.push_back(start
);
3677 else if ( *s
== '\0' ) {
3678 entry
.sectionOrder
.push_back(start
);
3682 cannotBeUsedWithBitcode(arg
);
3684 else if ( strcmp(arg
, "-application_extension") == 0 ) {
3685 fMarkAppExtensionSafe
= true;
3686 fCheckAppExtensionSafe
= true;
3688 else if ( strcmp(arg
, "-no_application_extension") == 0 ) {
3689 fMarkAppExtensionSafe
= false;
3690 fCheckAppExtensionSafe
= false;
3692 else if ( strcmp(arg
, "-add_ast_path") == 0 ) {
3693 const char* path
= argv
[++i
];
3695 throw "-add_ast_path missing <option>";
3696 fASTFilePaths
.push_back(path
);
3698 else if ( strcmp(arg
, "-force_load_swift_libs") == 0 ) {
3699 fForceLoadSwiftLibs
= true;
3701 else if ( strcmp(arg
, "-not_for_dyld_shared_cache") == 0 ) {
3702 fSharedRegionEligibleForceOff
= true;
3703 cannotBeUsedWithBitcode(arg
);
3705 else if ( strcmp(arg
, "-dirty_data_list") == 0 ) {
3706 if ( argv
[i
+1] == NULL
)
3707 throw "-dirty_data_list missing <symbol-list-file>";
3708 addSymbolMove("__DATA_DIRTY", argv
[i
+1], fSymbolsMovesData
, "-dirty_data_list");
3710 cannotBeUsedWithBitcode(arg
);
3712 else if ( strcmp(arg
, "-data_const") == 0 ) {
3713 fUseDataConstSegmentForceOn
= true;
3714 cannotBeUsedWithBitcode(arg
);
3716 else if ( strcmp(arg
, "-no_data_const") == 0 ) {
3717 fUseDataConstSegmentForceOff
= true;
3718 cannotBeUsedWithBitcode(arg
);
3720 else if ( strcmp(arg
, "-no_deduplicate") == 0 ) {
3723 else if ( strcmp(arg
, "-verbose_deduplicate") == 0 ) {
3724 fVerboseDeDupe
= true;
3726 else if ( strcmp(arg
, "-max_default_common_align") == 0 ) {
3727 const char* alignStr
= argv
[++i
];
3728 if ( alignStr
== NULL
)
3729 throw "-max_default_common_align missing <align-value>";
3730 // argument is a hexadecimal number
3732 unsigned long value
= strtoul(alignStr
, &endptr
, 16);
3733 if ( *endptr
!= '\0')
3734 throw "argument for -max_default_common_align is not a hexadecimal number";
3735 if ( value
> 0x8000 )
3736 throw "argument for -max_default_common_align must be less than or equal to 0x8000";
3738 warning("zero is not a valid -max_default_common_align");
3741 // alignment is power of 2
3742 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
3743 if ( (unsigned long)(1 << alignment
) != value
) {
3744 warning("alignment for -max_default_common_align is not a power of two, using 0x%X", 1 << alignment
);
3746 fMaxDefaultCommonAlign
= alignment
;
3748 else if ( strcmp(arg
, "-prefer-mod-time-check") == 0 ) {
3749 fFilePreference
= kModTime
;
3751 else if ( strcmp(arg
, "-prefer-text-based-stub-file") == 0 ) {
3752 fFilePreference
= kTextBasedStub
;
3754 else if ( strcmp(arg
, "-prefer-macho-file") == 0 ) {
3755 fFilePreference
= kMachO
;
3757 // put this last so that it does not interfer with other options starting with 'i'
3758 else if ( strncmp(arg
, "-i", 2) == 0 ) {
3759 const char* colon
= strchr(arg
, ':');
3760 if ( colon
== NULL
)
3761 throwf("unknown option: %s", arg
);
3762 Options::AliasPair pair
;
3763 char* temp
= new char[colon
-arg
];
3764 strlcpy(temp
, &arg
[2], colon
-arg
-1);
3765 pair
.realName
= &colon
[1];
3767 fAliases
.push_back(pair
);
3770 throwf("unknown option: %s", arg
);
3773 if (snapshotArgCount
== -1)
3774 snapshotArgCount
= i
-snapshotArgIndex
+1;
3775 if (snapshotArgCount
> 0)
3776 fLinkSnapshot
.addSnapshotLinkArg(snapshotArgIndex
, snapshotArgCount
, snapshotFileArgIndex
);
3779 FileInfo info
= findFile(arg
);
3780 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3781 if ( strcmp(&info
.path
[strlen(info
.path
)-2], ".a") == 0 )
3784 fInputFiles
.push_back(info
);
3788 // if a -lazy option was used, implicitly link in lazydylib1.o
3789 if ( fUsingLazyDylibLinking
) {
3790 FileInfo info
= findLibrary("lazydylib1.o");
3791 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)argc
);
3795 if (fSnapshotRequested
)
3796 fLinkSnapshot
.createSnapshot();
3802 // -syslibroot <path> is used for SDK support.
3803 // The rule is that all search paths (both explicit and default) are
3804 // checked to see if they exist in the SDK. If so, that path is
3805 // replaced with the sdk prefixed path. If not, that search path
3806 // is used as is. If multiple -syslibroot options are specified
3807 // their directory structures are logically overlayed and files
3808 // from sdks specified earlier on the command line used before later ones.
3810 void Options::buildSearchPaths(int argc
, const char* argv
[])
3812 bool addStandardLibraryDirectories
= true;
3813 std::vector
<const char*> libraryPaths
;
3814 std::vector
<const char*> frameworkPaths
;
3815 libraryPaths
.reserve(10);
3816 frameworkPaths
.reserve(10);
3817 // scan through argv looking for -L, -F, -Z, and -syslibroot options
3818 for(int i
=0; i
< argc
; ++i
) {
3819 if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'L') ) {
3820 const char* libSearchDir
= &argv
[i
][2];
3821 // Allow either "-L{path}" or "-L {path}".
3822 if (argv
[i
][2] == '\0') {
3823 // -L {path}. Make sure there is an argument following this.
3824 const char* path
= argv
[++i
];
3826 throw "-L missing argument";
3827 libSearchDir
= path
;
3829 if ( libSearchDir
[0] == '\0' )
3830 throw "-L must be immediately followed by a directory path (no space)";
3831 libraryPaths
.push_back(libSearchDir
);
3833 else if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'F') ) {
3834 const char* frameworkSearchDir
= &argv
[i
][2];
3835 // Allow either "-F{path}" or "-F {path}".
3836 if (argv
[i
][2] == '\0') {
3837 // -F {path}. Make sure there is an argument following this.
3838 const char* path
= argv
[++i
];
3840 throw "-F missing argument";
3841 frameworkSearchDir
= path
;
3843 if ( frameworkSearchDir
[0] == '\0' )
3844 throw "-F must be immediately followed by a directory path (no space)";
3845 frameworkPaths
.push_back(frameworkSearchDir
);
3847 else if ( strcmp(argv
[i
], "-Z") == 0 )
3848 addStandardLibraryDirectories
= false;
3849 else if ( strcmp(argv
[i
], "-v") == 0 ) {
3851 extern const char ldVersionString
[];
3852 fprintf(stderr
, "%s", ldVersionString
);
3853 fprintf(stderr
, "configured to support archs: %s\n", ALL_SUPPORTED_ARCHS
);
3854 // if only -v specified, exit cleanly
3856 const char* ltoVers
= lto::version();
3857 if ( ltoVers
!= NULL
)
3858 fprintf(stderr
, "LTO support using: %s\n", ltoVers
);
3862 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
3863 const char* path
= argv
[++i
];
3865 throw "-syslibroot missing argument";
3866 fSDKPaths
.push_back(path
);
3868 else if ( strcmp(argv
[i
], "-search_paths_first") == 0 ) {
3869 fLibrarySearchMode
= kSearchDylibAndArchiveInEachDir
;
3871 else if ( strcmp(argv
[i
], "-search_dylibs_first") == 0 ) {
3872 fLibrarySearchMode
= kSearchAllDirsForDylibsThenAllDirsForArchives
;
3874 else if ( strcmp(argv
[i
], "-w") == 0 ) {
3875 sEmitWarnings
= false;
3877 else if ( strcmp(argv
[i
], "-fatal_warnings") == 0 ) {
3878 sFatalWarnings
= true;
3880 else if ( strcmp(argv
[i
], "-dependency_info") == 0 ) {
3881 const char* path
= argv
[++i
];
3883 throw "-dependency_info missing <path>";
3884 fDependencyInfoPath
= path
;
3886 else if ( strcmp(argv
[i
], "-bitcode_bundle") == 0 ) {
3887 fBundleBitcode
= true;
3890 int standardLibraryPathsStartIndex
= libraryPaths
.size();
3891 int standardFrameworkPathsStartIndex
= frameworkPaths
.size();
3892 if ( addStandardLibraryDirectories
) {
3893 libraryPaths
.push_back("/usr/lib");
3894 libraryPaths
.push_back("/usr/local/lib");
3896 frameworkPaths
.push_back("/Library/Frameworks/");
3897 frameworkPaths
.push_back("/System/Library/Frameworks/");
3898 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
3901 // <rdar://problem/5829579> Support for configure based hacks
3902 // if last -syslibroot is /, then ignore all syslibroots
3903 if ( fSDKPaths
.size() > 0 ) {
3904 if ( strcmp(fSDKPaths
.back(), "/") == 0 ) {
3909 // now merge sdk and library paths to make real search paths
3910 fLibrarySearchPaths
.reserve(libraryPaths
.size()*(fSDKPaths
.size()+1));
3912 for (std::vector
<const char*>::iterator it
= libraryPaths
.begin(); it
!= libraryPaths
.end(); ++it
, ++libIndex
) {
3913 const char* libDir
= *it
;
3914 bool sdkOverride
= false;
3915 if ( libDir
[0] == '/' ) {
3916 char betterLibDir
[PATH_MAX
];
3917 if ( strstr(libDir
, "/..") != NULL
) {
3918 if ( realpath(libDir
, betterLibDir
) != NULL
)
3919 libDir
= strdup(betterLibDir
);
3921 const int libDirLen
= strlen(libDir
);
3922 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
3923 const char* sdkDir
= *sdkit
;
3924 const int sdkDirLen
= strlen(sdkDir
);
3925 char newPath
[libDirLen
+ sdkDirLen
+4];
3926 strcpy(newPath
, sdkDir
);
3927 if ( newPath
[sdkDirLen
-1] == '/' )
3928 newPath
[sdkDirLen
-1] = '\0';
3929 strcat(newPath
, libDir
);
3930 struct stat statBuffer
;
3931 if ( stat(newPath
, &statBuffer
) == 0 ) {
3932 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 ) {
3933 warning("-syslibroot and -L combined path '%s' is not a directory", newPath
);
3936 fLibrarySearchPaths
.push_back(strdup(newPath
));
3942 if ( !sdkOverride
) {
3943 if ( (libIndex
>= standardLibraryPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
3944 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
3945 // if one SDK is specified and a standard library path is not in the SDK, don't use it
3948 struct stat statBuffer
;
3949 if ( stat(libDir
, &statBuffer
) == 0 ) {
3950 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 )
3951 warning("-L path '%s' is not a directory", libDir
);
3953 fLibrarySearchPaths
.push_back(libDir
);
3955 else if ( !addStandardLibraryDirectories
|| (strcmp(libDir
, "/usr/local/lib") != 0) ) {
3956 warning("directory not found for option '-L%s'", libDir
);
3963 // now merge sdk and framework paths to make real search paths
3964 fFrameworkSearchPaths
.reserve(frameworkPaths
.size()*(fSDKPaths
.size()+1));
3966 for (std::vector
<const char*>::iterator it
= frameworkPaths
.begin(); it
!= frameworkPaths
.end(); ++it
, ++frameIndex
) {
3967 const char* frameworkDir
= *it
;
3968 bool sdkOverride
= false;
3969 if ( frameworkDir
[0] == '/' ) {
3970 char betterFrameworkDir
[PATH_MAX
];
3971 if ( strstr(frameworkDir
, "/..") != NULL
) {
3972 if ( realpath(frameworkDir
, betterFrameworkDir
) != NULL
)
3973 frameworkDir
= strdup(betterFrameworkDir
);
3975 const int frameworkDirLen
= strlen(frameworkDir
);
3976 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
3977 const char* sdkDir
= *sdkit
;
3978 const int sdkDirLen
= strlen(sdkDir
);
3979 char newPath
[frameworkDirLen
+ sdkDirLen
+4];
3980 strcpy(newPath
, sdkDir
);
3981 if ( newPath
[sdkDirLen
-1] == '/' )
3982 newPath
[sdkDirLen
-1] = '\0';
3983 strcat(newPath
, frameworkDir
);
3984 struct stat statBuffer
;
3985 if ( stat(newPath
, &statBuffer
) == 0 ) {
3986 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 ) {
3987 warning("-syslibroot and -F combined path '%s' is not a directory", newPath
);
3990 fFrameworkSearchPaths
.push_back(strdup(newPath
));
3996 if ( !sdkOverride
) {
3997 if ( (frameIndex
>= standardFrameworkPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
3998 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
3999 // if one SDK is specified and a standard library path is not in the SDK, don't use it
4002 struct stat statBuffer
;
4003 if ( stat(frameworkDir
, &statBuffer
) == 0 ) {
4004 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 )
4005 warning("-F path '%s' is not a directory", frameworkDir
);
4007 fFrameworkSearchPaths
.push_back(frameworkDir
);
4009 else if ( !addStandardLibraryDirectories
|| (strcmp(frameworkDir
, "/Library/Frameworks/") != 0) ) {
4010 warning("directory not found for option '-F%s'", frameworkDir
);
4017 fprintf(stderr
,"Library search paths:\n");
4018 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
4019 it
!= fLibrarySearchPaths
.end();
4021 fprintf(stderr
,"\t%s\n", *it
);
4022 fprintf(stderr
,"Framework search paths:\n");
4023 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
4024 it
!= fFrameworkSearchPaths
.end();
4026 fprintf(stderr
,"\t%s\n", *it
);
4030 // this is run before the command line is parsed
4031 void Options::parsePreCommandLineEnvironmentSettings()
4033 if ((getenv("LD_TRACE_ARCHIVES") != NULL
)
4034 || (getenv("RC_TRACE_ARCHIVES") != NULL
))
4035 fTraceArchives
= true;
4037 if ((getenv("LD_TRACE_DYLIBS") != NULL
)
4038 || (getenv("RC_TRACE_DYLIBS") != NULL
)) {
4039 fTraceDylibs
= true;
4040 fTraceIndirectDylibs
= true;
4043 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL
) {
4044 fTraceDylibSearching
= true;
4047 if (getenv("LD_PRINT_OPTIONS") != NULL
)
4048 fPrintOptions
= true;
4050 if (fTraceDylibs
|| fTraceArchives
)
4051 fTraceOutputFile
= getenv("LD_TRACE_FILE");
4053 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL
)
4054 fPrintOrderFileStatistics
= true;
4056 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL
)
4059 if (getenv("LD_NO_ENCRYPT") != NULL
) {
4060 fEncryptable
= false;
4061 fMarkAppExtensionSafe
= true; // temporary
4062 fCheckAppExtensionSafe
= false;
4065 if (getenv("LD_APPLICATION_EXTENSION_SAFE") != NULL
) {
4066 fMarkAppExtensionSafe
= true;
4067 fCheckAppExtensionSafe
= false;
4070 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL
)
4071 fAllowCpuSubtypeMismatches
= true;
4073 if (getenv("LD_DYLIB_CPU_SUBTYPES_MUST_MATCH") != NULL
)
4074 fEnforceDylibSubtypesMatch
= true;
4076 sWarningsSideFilePath
= getenv("LD_WARN_FILE");
4078 const char* customDyldPath
= getenv("LD_DYLD_PATH");
4079 if ( customDyldPath
!= NULL
)
4080 fDyldInstallPath
= customDyldPath
;
4082 const char* debugArchivePath
= getenv("LD_DEBUG_SNAPSHOT");
4083 if (debugArchivePath
!= NULL
) {
4084 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
4085 if (strlen(debugArchivePath
) > 0)
4086 fLinkSnapshot
.setSnapshotPath(debugArchivePath
);
4087 fSnapshotRequested
= true;
4090 const char* pipeFdString
= getenv("LD_PIPELINE_FIFO");
4091 if (pipeFdString
!= NULL
) {
4092 fPipelineFifo
= pipeFdString
;
4095 // Workaround for rdar://problem/24301175
4096 if ((getenv("RC_XBS") != NULL
) && !(getenv("RC_BUILDIT") != NULL
))
4097 fForceTextBasedStub
= true;
4101 // this is run after the command line is parsed
4102 void Options::parsePostCommandLineEnvironmentSettings()
4104 // when building a dynamic main executable, default any use of @executable_path to output path
4105 if ( fExecutablePath
== NULL
&& (fOutputKind
== kDynamicExecutable
) ) {
4106 fExecutablePath
= fOutputFile
;
4109 // allow build system to set default seg_addr_table
4110 if ( fSegAddrTablePath
== NULL
)
4111 fSegAddrTablePath
= getenv("LD_SEG_ADDR_TABLE");
4113 // allow build system to turn on prebinding
4115 fPrebind
= ( getenv("LD_PREBIND") != NULL
);
4118 // allow build system to force on dead-code-stripping
4119 if ( !fDeadStrip
) {
4120 if ( getenv("LD_DEAD_STRIP") != NULL
) {
4121 switch (fOutputKind
) {
4122 case Options::kDynamicLibrary
:
4123 case Options::kDynamicExecutable
:
4124 case Options::kDynamicBundle
:
4127 case Options::kPreload
:
4128 case Options::kObjectFile
:
4129 case Options::kDyld
:
4130 case Options::kStaticExecutable
:
4131 case Options::kKextBundle
:
4137 // allow build system to force on -warn_commons
4138 if ( getenv("LD_WARN_COMMONS") != NULL
)
4139 fWarnCommons
= true;
4141 // allow B&I to set default -source_version
4142 if ( fSourceVersion
== 0 ) {
4143 const char* vers
= getenv("RC_ProjectSourceVersion");
4145 fSourceVersion
= parseVersionNumber64(vers
);
4150 void Options::reconfigureDefaults()
4152 // sync reader options
4153 switch ( fOutputKind
) {
4154 case Options::kObjectFile
:
4155 fForFinalLinkedImage
= false;
4157 case Options::kDyld
:
4159 fForFinalLinkedImage
= true;
4162 case Options::kDynamicLibrary
:
4163 case Options::kDynamicBundle
:
4164 case Options::kKextBundle
:
4165 fForFinalLinkedImage
= true;
4168 case Options::kDynamicExecutable
:
4169 case Options::kStaticExecutable
:
4170 case Options::kPreload
:
4171 fLinkingMainExecutable
= true;
4172 fForFinalLinkedImage
= true;
4177 // set default min OS version
4178 if ( (fMacVersionMin
== ld::macVersionUnset
) && (fIOSVersionMin
== ld::iOSVersionUnset
) && (fWatchOSVersionMin
== ld::wOSVersionUnset
) ) {
4179 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
4180 const char* macVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
4181 const char* iPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
4182 const char* iOSVers
= getenv("IOS_DEPLOYMENT_TARGET");
4183 const char* wOSVers
= getenv("WATCHOS_DEPLOYMENT_TARGET");
4184 if ( macVers
!= NULL
)
4185 setMacOSXVersionMin(macVers
);
4186 else if ( iPhoneVers
!= NULL
)
4187 setIOSVersionMin(iPhoneVers
);
4188 else if ( iOSVers
!= NULL
)
4189 setIOSVersionMin(iOSVers
);
4190 else if ( wOSVers
!= NULL
)
4191 setWatchOSVersionMin(wOSVers
);
4193 // if still nothing, set default based on architecture
4194 switch ( fArchitecture
) {
4196 case CPU_TYPE_X86_64
:
4197 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
4198 #ifdef DEFAULT_MACOSX_MIN_VERSION
4199 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION
);
4200 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
4202 warning("-macosx_version_min not specified, assuming 10.6");
4203 setMacOSXVersionMin("10.6");
4208 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
4209 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
4210 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION
);
4211 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION
);
4213 if ( fSubArchitecture
== CPU_SUBTYPE_ARM_V7K
) {
4214 warning("-watchos_version_min not specified, assuming 2.0");
4215 setWatchOSVersionMin("2.0");
4218 warning("-ios_version_min not specified, assuming 6.0");
4219 setIOSVersionMin("6.0");
4225 // architecture will be infered later by examining .o files
4232 // adjust min based on architecture
4233 switch ( fArchitecture
) {
4235 if ( (fPlatform
== kPlatformOSX
) && (fMacVersionMin
< ld::mac10_4
) ) {
4236 //warning("-macosx_version_min should be 10.4 or later for i386");
4237 fMacVersionMin
= ld::mac10_4
;
4240 case CPU_TYPE_X86_64
:
4241 if ( (fPlatform
== kPlatformOSX
) && (fMacVersionMin
< ld::mac10_4
) ) {
4242 //warning("-macosx_version_min should be 10.4 or later for x86_64");
4243 fMacVersionMin
= ld::mac10_4
;
4246 case CPU_TYPE_ARM64
:
4247 if ( (fPlatform
== kPlatformiOS
) && (fIOSVersionMin
< ld::iOS_7_0
) ) {
4248 //warning("-mios_version_min should be 7.0 or later for arm64");
4249 fIOSVersionMin
= ld::iOS_7_0
;
4254 // default to adding functions start for dynamic code, static code must opt-in
4255 switch ( fOutputKind
) {
4256 case Options::kPreload
:
4257 case Options::kStaticExecutable
:
4258 case Options::kKextBundle
:
4259 if ( fDataInCodeInfoLoadCommandForcedOn
)
4260 fDataInCodeInfoLoadCommand
= true;
4261 if ( fFunctionStartsForcedOn
)
4262 fFunctionStartsLoadCommand
= true;
4264 case Options::kObjectFile
:
4265 if ( !fDataInCodeInfoLoadCommandForcedOff
)
4266 fDataInCodeInfoLoadCommand
= true;
4267 if ( fFunctionStartsForcedOn
)
4268 fFunctionStartsLoadCommand
= true;
4270 case Options::kDynamicExecutable
:
4271 case Options::kDyld
:
4272 case Options::kDynamicLibrary
:
4273 case Options::kDynamicBundle
:
4274 if ( !fDataInCodeInfoLoadCommandForcedOff
)
4275 fDataInCodeInfoLoadCommand
= true;
4276 if ( !fFunctionStartsForcedOff
)
4277 fFunctionStartsLoadCommand
= true;
4281 // adjust kext type based on architecture
4282 if ( fOutputKind
== kKextBundle
) {
4283 switch ( fArchitecture
) {
4284 case CPU_TYPE_X86_64
:
4285 // x86_64 uses new MH_KEXT_BUNDLE type
4286 fMakeCompressedDyldInfo
= false;
4287 fMakeCompressedDyldInfoForceOff
= true;
4288 fAllowTextRelocs
= true;
4289 fUndefinedTreatment
= kUndefinedDynamicLookup
;
4291 case CPU_TYPE_ARM64
:
4292 // arm64 uses new MH_KEXT_BUNDLE type
4293 fMakeCompressedDyldInfo
= false;
4294 fMakeCompressedDyldInfoForceOff
= true;
4295 fAllowTextRelocs
= false;
4296 fKextsUseStubs
= true;
4297 fUndefinedTreatment
= kUndefinedDynamicLookup
;
4300 if ( min_iOS(ld::iOS_5_0
) ) {
4301 // iOS 5.0 and later use new MH_KEXT_BUNDLE type
4302 fMakeCompressedDyldInfo
= false;
4303 fMakeCompressedDyldInfoForceOff
= true;
4304 // kexts are PIC in iOS 6.0 and later
4305 fAllowTextRelocs
= !min_iOS(ld::iOS_6_0
);
4306 fKextsUseStubs
= !fAllowTextRelocs
;
4307 fUndefinedTreatment
= kUndefinedDynamicLookup
;
4310 // else use object file
4313 fOutputKind
= kObjectFile
;
4318 // disable implicit dylibs when targeting 10.3
4319 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
4320 if ( !minOS(ld::mac10_4
, ld::iOS_2_0
) )
4321 fImplicitlyLinkPublicDylibs
= false;
4324 // allow build system to force linker to ignore -prebind
4325 if ( getenv("LD_FORCE_NO_PREBIND") != NULL
)
4328 // allow build system to force linker to ignore -seg_addr_table
4329 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL
)
4330 fSegAddrTablePath
= NULL
;
4332 // check for base address specified externally
4333 if ( (fSegAddrTablePath
!= NULL
) && (fOutputKind
== Options::kDynamicLibrary
) ) {
4334 parseSegAddrTable(fSegAddrTablePath
, this->installPath());
4335 // HACK to support seg_addr_table entries that are physical paths instead of install paths
4336 if ( fBaseAddress
== 0 ) {
4337 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
4338 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.4.dylib");
4339 if ( fBaseAddress
== 0 )
4340 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.9.dylib");
4343 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
4344 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libz.1.2.3.dylib");
4346 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
4347 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libutil1.0.dylib");
4351 // split segs only allowed for dylibs
4353 // split seg only supported for i386, and arm.
4354 switch ( fArchitecture
) {
4356 if ( fOutputKind
!= Options::kDynamicLibrary
)
4358 // make sure read and write segments are proper distance apart
4359 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x10000000) )
4360 fBaseWritableAddress
= fBaseAddress
+ 0x10000000;
4363 if ( fOutputKind
!= Options::kDynamicLibrary
) {
4367 // make sure read and write segments are proper distance apart
4368 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x08000000) )
4369 fBaseWritableAddress
= fBaseAddress
+ 0x08000000;
4375 fBaseWritableAddress
= 0;
4379 // set too-large size
4380 switch ( fArchitecture
) {
4382 fMaxAddress
= 0xFFFFFFFF;
4384 case CPU_TYPE_X86_64
:
4387 switch ( fOutputKind
) {
4388 case Options::kDynamicExecutable
:
4389 case Options::kDynamicLibrary
:
4390 case Options::kDynamicBundle
:
4391 // user land code is limited to low 1GB
4392 fMaxAddress
= 0x2FFFFFFF;
4394 case Options::kStaticExecutable
:
4395 case Options::kObjectFile
:
4396 case Options::kDyld
:
4397 case Options::kPreload
:
4398 case Options::kKextBundle
:
4399 fMaxAddress
= 0xFFFFFFFF;
4402 // range check -seg1addr for ARM
4403 if ( fBaseAddress
> fMaxAddress
) {
4404 warning("ignoring -seg1addr 0x%08llX. Address out of range.", fBaseAddress
);
4410 // <rdar://problem/6138961> -r implies no prebinding for all architectures
4411 if ( fOutputKind
== Options::kObjectFile
)
4414 // disable prebinding depending on arch and min OS version
4416 switch ( fArchitecture
) {
4418 if ( fMacVersionMin
== ld::mac10_4
) {
4419 // in 10.4 only split seg dylibs are prebound
4420 if ( (fOutputKind
!= Options::kDynamicLibrary
) || ! fSplitSegs
)
4423 else if ( fMacVersionMin
>= ld::mac10_5
) {
4424 // in 10.5 nothing is prebound
4427 else if ( fIOSVersionMin
!= ld::iOSVersionUnset
) {
4428 // nothing in simulator is prebound
4432 // in 10.3 and earlier only dylibs and main executables could be prebound
4433 switch ( fOutputKind
) {
4434 case Options::kDynamicExecutable
:
4435 case Options::kDynamicLibrary
:
4436 // only main executables and dylibs can be prebound
4438 case Options::kStaticExecutable
:
4439 case Options::kDynamicBundle
:
4440 case Options::kObjectFile
:
4441 case Options::kDyld
:
4442 case Options::kPreload
:
4443 case Options::kKextBundle
:
4444 // disable prebinding for everything else
4450 case CPU_TYPE_X86_64
:
4454 switch ( fOutputKind
) {
4455 case Options::kDynamicExecutable
:
4456 case Options::kDynamicLibrary
:
4457 // only main executables and dylibs can be prebound
4459 case Options::kStaticExecutable
:
4460 case Options::kDynamicBundle
:
4461 case Options::kObjectFile
:
4462 case Options::kDyld
:
4463 case Options::kPreload
:
4464 case Options::kKextBundle
:
4465 // disable prebinding for everything else
4473 // only prebound images can be split-seg
4474 if ( fSplitSegs
&& !fPrebind
)
4477 // determine if info for shared region should be added
4478 if ( fOutputKind
== Options::kDynamicLibrary
) {
4479 if ( minOS(ld::mac10_5
, ld::iOS_3_1
) )
4480 if ( !fPrebind
&& !fSharedRegionEligibleForceOff
)
4481 if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
4482 || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
4483 fSharedRegionEligible
= true;
4485 else if ( fOutputKind
== Options::kDyld
) {
4486 // <rdar://problem/10111122> Enable dyld to be put into the dyld shared cache
4487 fSharedRegionEligible
= true;
4490 // <rdar://problem/18719327> warn if -rpath is used with OS dylibs
4491 if ( fSharedRegionEligible
&& !fRPaths
.empty() )
4492 warning("-rpath cannot be used with dylibs that will be in the dyld shared cache");
4494 // automatically use __DATA_CONST in iOS dylibs
4495 if ( fSharedRegionEligible
&& minOS(ld::mac10_Future
, ld::iOS_9_0
) && !fUseDataConstSegmentForceOff
) {
4496 fUseDataConstSegment
= true;
4498 if ( fUseDataConstSegmentForceOn
) {
4499 fUseDataConstSegment
= true;
4501 if ( fUseDataConstSegment
) {
4502 addSectionRename("__DATA", "__got", "__DATA_CONST", "__got");
4503 addSectionRename("__DATA", "__la_symbol_ptr", "__DATA_CONST", "__la_symbol_ptr");
4504 addSectionRename("__DATA", "__nl_symbol_ptr", "__DATA_CONST", "__nl_symbol_ptr");
4505 addSectionRename("__DATA", "__const", "__DATA_CONST", "__const");
4506 addSectionRename("__DATA", "__cfstring", "__DATA_CONST", "__cfstring");
4507 addSectionRename("__DATA", "__mod_init_func", "__DATA_CONST", "__mod_init_func");
4508 addSectionRename("__DATA", "__mod_term_func", "__DATA_CONST", "__mod_term_func");
4509 addSectionRename("__DATA", "__objc_classlist", "__DATA_CONST", "__objc_classlist");
4510 addSectionRename("__DATA", "__objc_nlclslist", "__DATA_CONST", "__objc_nlclslist");
4511 addSectionRename("__DATA", "__objc_catlist", "__DATA_CONST", "__objc_catlist");
4512 addSectionRename("__DATA", "__objc_nlcatlist", "__DATA_CONST", "__objc_nlcatlist");
4513 addSectionRename("__DATA", "__objc_protolist", "__DATA_CONST", "__objc_protolist");
4514 addSectionRename("__DATA", "__objc_imageinfo", "__DATA_CONST", "__objc_imageinfo");
4515 addSectionRename("__DATA", "__objc_const", "__DATA_CONST", "__objc_const");
4518 // Use V2 shared cache info when targetting newer OSs
4519 if ( fSharedRegionEligible
&& minOS(ld::mac10_Future
, ld::iOS_9_0
)) {
4520 fSharedRegionEncodingV2
= true;
4521 fIgnoreOptimizationHints
= true;
4524 // figure out if module table is needed for compatibility with old ld/dyld
4525 if ( fOutputKind
== Options::kDynamicLibrary
) {
4526 switch ( fArchitecture
) {
4528 if ( fIOSVersionMin
!= ld::iOSVersionUnset
) // simulator never needs modules
4532 fNeedsModuleTable
= true; // redo_prebinding requires a module table
4537 // <rdar://problem/5366363> -r -x implies -S
4538 if ( (fOutputKind
== Options::kObjectFile
) && (fLocalSymbolHandling
== kLocalSymbolsNone
) )
4539 fDebugInfoStripping
= Options::kDebugInfoNone
;
4541 // <rdar://problem/15252891> -r implies -no_uuid
4542 if ( fOutputKind
== Options::kObjectFile
)
4543 fUUIDMode
= kUUIDNone
;
4545 // choose how to process unwind info
4546 switch ( fArchitecture
) {
4548 case CPU_TYPE_X86_64
:
4549 case CPU_TYPE_ARM64
:
4550 switch ( fOutputKind
) {
4551 case Options::kObjectFile
:
4552 case Options::kStaticExecutable
:
4553 case Options::kPreload
:
4554 case Options::kKextBundle
:
4555 fAddCompactUnwindEncoding
= false;
4557 case Options::kDyld
:
4558 case Options::kDynamicLibrary
:
4559 case Options::kDynamicBundle
:
4560 case Options::kDynamicExecutable
:
4561 //if ( fAddCompactUnwindEncoding && (fVersionMin >= ld::mac10_6) )
4562 // fRemoveDwarfUnwindIfCompactExists = true;
4567 if ( armUsesZeroCostExceptions() ) {
4568 switch ( fOutputKind
) {
4569 case Options::kObjectFile
:
4570 case Options::kStaticExecutable
:
4571 case Options::kPreload
:
4572 case Options::kKextBundle
:
4573 fAddCompactUnwindEncoding
= false;
4575 case Options::kDyld
:
4576 case Options::kDynamicLibrary
:
4577 case Options::kDynamicBundle
:
4578 case Options::kDynamicExecutable
:
4579 fAddCompactUnwindEncoding
= true;
4584 fAddCompactUnwindEncoding
= false;
4585 fRemoveDwarfUnwindIfCompactExists
= false;
4589 // if -arch is missing, assume we don't want compact unwind info
4590 fAddCompactUnwindEncoding
= false;
4594 // only iOS executables should be encryptable
4595 switch ( fOutputKind
) {
4596 case Options::kObjectFile
:
4597 case Options::kDyld
:
4598 case Options::kStaticExecutable
:
4599 case Options::kPreload
:
4600 case Options::kKextBundle
:
4601 fEncryptable
= false;
4603 case Options::kDynamicExecutable
:
4605 case Options::kDynamicLibrary
:
4606 case Options::kDynamicBundle
:
4607 // <rdar://problem/16293398> Add LC_ENCRYPTION_INFO load command to bundled frameworks
4608 if ( !min_iOS(ld::iOS_7_0
) )
4609 fEncryptable
= false;
4612 if ( (fArchitecture
!= CPU_TYPE_ARM
) && (fArchitecture
!= CPU_TYPE_ARM64
) )
4613 fEncryptable
= false;
4614 if ( fEncryptableForceOn
)
4615 fEncryptable
= true;
4616 else if ( fEncryptableForceOff
)
4617 fEncryptable
= false;
4619 // don't move inits in dyld because dyld wants certain
4620 // entries point at stable locations at the start of __text
4621 if ( fOutputKind
== Options::kDyld
)
4622 fAutoOrderInitializers
= false;
4625 // disable __data ordering for some output kinds
4626 switch ( fOutputKind
) {
4627 case Options::kObjectFile
:
4628 case Options::kDyld
:
4629 case Options::kStaticExecutable
:
4630 case Options::kPreload
:
4631 case Options::kKextBundle
:
4634 case Options::kDynamicExecutable
:
4635 case Options::kDynamicLibrary
:
4636 case Options::kDynamicBundle
:
4640 // only use compressed LINKEDIT for final linked images
4641 switch ( fOutputKind
) {
4642 case Options::kDynamicExecutable
:
4643 case Options::kDynamicLibrary
:
4644 case Options::kDynamicBundle
:
4646 case Options::kPreload
:
4647 case Options::kStaticExecutable
:
4648 case Options::kObjectFile
:
4649 case Options::kDyld
:
4650 case Options::kKextBundle
:
4651 fMakeCompressedDyldInfoForceOff
= true;
4654 if ( fMakeCompressedDyldInfoForceOff
)
4655 fMakeCompressedDyldInfo
= false;
4658 // only use compressed LINKEDIT for:
4659 // Mac OS X 10.6 or later
4661 if ( fMakeCompressedDyldInfo
) {
4662 if ( !minOS(ld::mac10_6
, ld::iOS_3_1
) )
4663 fMakeCompressedDyldInfo
= false;
4666 // only ARM and x86_64 enforces that cpu-sub-types must match
4667 switch ( fArchitecture
) {
4670 case CPU_TYPE_X86_64
:
4671 fEnforceDylibSubtypesMatch
= false;
4674 case CPU_TYPE_ARM64
:
4675 fEnforceDylibSubtypesMatch
= false;
4676 fAllowCpuSubtypeMismatches
= true;
4681 // only final linked images can not optimize zero fill sections
4682 if ( fOutputKind
== Options::kObjectFile
)
4683 fOptimizeZeroFill
= true;
4685 // all undefines in -r mode
4686 // if ( fOutputKind == Options::kObjectFile )
4687 // fUndefinedTreatment = kUndefinedSuppress;
4689 // only dynamic final linked images should warn about use of commmons
4690 if ( fWarnCommons
) {
4691 switch ( fOutputKind
) {
4692 case Options::kDynamicExecutable
:
4693 case Options::kDynamicLibrary
:
4694 case Options::kDynamicBundle
:
4696 case Options::kPreload
:
4697 case Options::kStaticExecutable
:
4698 case Options::kObjectFile
:
4699 case Options::kDyld
:
4700 case Options::kKextBundle
:
4701 fWarnCommons
= false;
4706 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
4707 if ( minOS(ld::mac10_5
, ld::iOS_2_0
) )
4708 fUseSimplifiedDylibReExports
= true;
4710 // Mac OS X 10.7 and iOS 4.2 support LC_LOAD_UPWARD_DYLIB
4711 if ( minOS(ld::mac10_7
, ld::iOS_4_2
) && (fOutputKind
== kDynamicLibrary
) )
4712 fCanUseUpwardDylib
= true;
4714 // MacOSX 10.7 defaults to PIE
4715 if ( ((fArchitecture
== CPU_TYPE_X86_64
) || (fArchitecture
== CPU_TYPE_I386
))
4716 && (fOutputKind
== kDynamicExecutable
)
4717 && (fMacVersionMin
>= ld::mac10_7
) ) {
4718 fPositionIndependentExecutable
= true;
4721 // armv7 for iOS4.3 defaults to PIE
4722 if ( (fArchitecture
== CPU_TYPE_ARM
)
4723 && fArchSupportsThumb2
4724 && (fOutputKind
== kDynamicExecutable
)
4725 && min_iOS(ld::iOS_4_3
) ) {
4726 fPositionIndependentExecutable
= true;
4729 // Simulator defaults to PIE
4730 if ( fTargetIOSSimulator
&& (fOutputKind
== kDynamicExecutable
) )
4731 fPositionIndependentExecutable
= true;
4733 // -no_pie anywhere on command line disable PIE
4734 if ( fDisablePositionIndependentExecutable
)
4735 fPositionIndependentExecutable
= false;
4737 // arm64 is always PIE
4738 if ( (fArchitecture
== CPU_TYPE_ARM64
) && (fOutputKind
== kDynamicExecutable
) ) {
4739 fPositionIndependentExecutable
= true;
4742 // set fOutputSlidable
4743 switch ( fOutputKind
) {
4744 case Options::kObjectFile
:
4745 fOutputSlidable
= false;
4747 case Options::kStaticExecutable
:
4748 case Options::kDynamicExecutable
:
4749 fOutputSlidable
= fPositionIndependentExecutable
;
4751 case Options::kPreload
:
4752 fOutputSlidable
= fPIEOnCommandLine
;
4754 case Options::kDyld
:
4755 case Options::kDynamicLibrary
:
4756 case Options::kDynamicBundle
:
4757 case Options::kKextBundle
:
4758 fOutputSlidable
= true;
4762 // let linker know if thread local variables are supported
4763 if ( fMacVersionMin
>= ld::mac10_7
) {
4766 else if ( (fArchitecture
== CPU_TYPE_ARM64
) && min_iOS(ld::iOS_8_0
) ) {
4769 else if ( (fArchitecture
== CPU_TYPE_ARM
) && min_iOS(ld::iOS_9_0
) ) {
4772 else if ( fTargetIOSSimulator
&& (fArchitecture
== CPU_TYPE_X86_64
) && min_iOS(ld::iOS_8_0
) ) {
4775 else if ( fTargetIOSSimulator
&& (fArchitecture
== CPU_TYPE_I386
) && min_iOS(ld::iOS_9_0
) ) {
4779 // default to adding version load command for dynamic code, static code must opt-in
4780 switch ( fOutputKind
) {
4781 case Options::kObjectFile
:
4782 fVersionLoadCommand
= false;
4784 case Options::kStaticExecutable
:
4785 case Options::kPreload
:
4786 case Options::kKextBundle
:
4787 if ( fVersionLoadCommandForcedOn
)
4788 fVersionLoadCommand
= true;
4790 case Options::kDynamicExecutable
:
4791 case Options::kDyld
:
4792 case Options::kDynamicLibrary
:
4793 case Options::kDynamicBundle
:
4794 if ( !fVersionLoadCommandForcedOff
)
4795 fVersionLoadCommand
= true;
4799 // support re-export of individual symbols in MacOSX 10.7 and iOS 4.2
4800 if ( (fOutputKind
== kDynamicLibrary
) && minOS(ld::mac10_7
, ld::iOS_4_2
) )
4801 fCanReExportSymbols
= true;
4803 // ObjC optimization is only in dynamic final linked images
4804 switch ( fOutputKind
) {
4805 case Options::kObjectFile
:
4806 case Options::kStaticExecutable
:
4807 case Options::kPreload
:
4808 case Options::kKextBundle
:
4809 case Options::kDyld
:
4810 fObjcCategoryMerging
= false;
4812 case Options::kDynamicExecutable
:
4813 case Options::kDynamicLibrary
:
4814 case Options::kDynamicBundle
:
4818 // i386 main executables linked on Mac OS X 10.7 default to NX heap
4819 // regardless of target unless overriden with -allow_heap_execute anywhere
4820 // on the command line
4821 if ( (fArchitecture
== CPU_TYPE_I386
) && (fOutputKind
== kDynamicExecutable
) && !fDisableNonExecutableHeap
)
4822 fNonExecutableHeap
= true;
4824 // Use LC_MAIN instead of LC_UNIXTHREAD for newer OSs
4825 switch ( fOutputKind
) {
4826 case Options::kDynamicExecutable
:
4827 if ( fEntryPointLoadCommandForceOn
) {
4828 fEntryPointLoadCommand
= true;
4829 if ( fEntryName
== NULL
)
4830 fEntryName
= "_main";
4832 else if ( fEntryPointLoadCommandForceOff
) {
4833 fNeedsThreadLoadCommand
= true;
4834 if ( fEntryName
== NULL
)
4835 fEntryName
= "start";
4838 // <rdar://problem/16310363> Linker should look for "_main" not "start" when building for sim regardless of min OS
4839 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) || fTargetIOSSimulator
) {
4840 fEntryPointLoadCommand
= true;
4841 if ( fEntryName
== NULL
)
4842 fEntryName
= "_main";
4843 if ( strcmp(fEntryName
, "start") == 0 ) {
4844 warning("Ignoring '-e start' because entry point 'start' is not used for the targeted OS version");
4845 fEntryName
= "_main";
4849 fNeedsThreadLoadCommand
= true;
4850 if ( fEntryName
== NULL
)
4851 fEntryName
= "start";
4855 case Options::kObjectFile
:
4856 case Options::kKextBundle
:
4857 case Options::kDynamicLibrary
:
4858 case Options::kDynamicBundle
:
4861 case Options::kStaticExecutable
:
4862 case Options::kPreload
:
4863 case Options::kDyld
:
4864 fNeedsThreadLoadCommand
= true;
4865 if ( fEntryName
== NULL
)
4866 fEntryName
= "start"; // Perhaps these should have no default and require -e
4870 // add LC_SOURCE_VERSION
4871 switch ( fOutputKind
) {
4872 case Options::kDynamicExecutable
:
4873 case Options::kKextBundle
:
4874 case Options::kDynamicLibrary
:
4875 case Options::kDynamicBundle
:
4876 case Options::kDyld
:
4877 case Options::kStaticExecutable
:
4878 if ( fSourceVersionLoadCommandForceOn
) {
4879 fSourceVersionLoadCommand
= true;
4881 else if ( fSourceVersionLoadCommandForceOff
) {
4882 fSourceVersionLoadCommand
= false;
4885 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) ) {
4886 fSourceVersionLoadCommand
= true;
4889 fSourceVersionLoadCommand
= false;
4892 case Options::kObjectFile
:
4893 case Options::kPreload
:
4894 fSourceVersionLoadCommand
= false;
4898 // if -sdk_version not on command line, infer from -syslibroot
4899 if ( (fSDKVersion
== 0) && (fSDKPaths
.size() > 0) ) {
4900 const char* sdkPath
= fSDKPaths
.front();
4901 const char* end
= &sdkPath
[strlen(sdkPath
)-1];
4902 while ( !isdigit(*end
) && (end
> sdkPath
) )
4904 const char* start
= end
-1;
4905 while ( (isdigit(*start
) || (*start
== '.')) && (start
> sdkPath
))
4907 char sdkVersionStr
[32];
4908 int len
= end
-start
+1;
4910 strlcpy(sdkVersionStr
, start
+1, len
);
4911 fSDKVersion
= parseVersionNumber32(sdkVersionStr
);
4915 // if -sdk_version and -syslibroot not used, but targeting MacOSX, use current OS version
4916 if ( (fSDKVersion
== 0) && (fMacVersionMin
!= ld::macVersionUnset
) ) {
4917 // special case if RC_ProjectName and MACOSX_DEPLOYMENT_TARGET are both set that sdkversion=minos
4918 if ( getenv("RC_ProjectName") && getenv("MACOSX_DEPLOYMENT_TARGET") ) {
4919 fSDKVersion
= fMacVersionMin
;
4922 int mib
[2] = { CTL_KERN
, KERN_OSRELEASE
};
4923 char kernVersStr
[100];
4924 size_t strlen
= sizeof(kernVersStr
);
4925 if ( sysctl(mib
, 2, kernVersStr
, &strlen
, NULL
, 0) != -1 ) {
4926 uint32_t kernVers
= parseVersionNumber32(kernVersStr
);
4927 int minor
= (kernVers
>> 16) - 4; // kernel major version is 4 ahead of x in 10.x
4928 fSDKVersion
= 0x000A0000 + (minor
<< 8);
4933 // allow trie based absolute symbols if targeting new enough OS
4934 if ( fMakeCompressedDyldInfo
) {
4935 if ( minOS(ld::mac10_9
, ld::iOS_7_0
) ) {
4936 fAbsoluteSymbols
= true;
4940 // <rdar://problem/12959510> iOS main executables now default to 16KB page size
4941 if ( (fIOSVersionMin
!= ld::iOSVersionUnset
) && (fOutputKind
== Options::kDynamicExecutable
) ) {
4942 // <rdar://problem/13070042> Only third party apps should have 16KB page segments by default
4943 if ( fEncryptable
) {
4944 if ( fSegmentAlignment
== 4096 )
4945 fSegmentAlignment
= 4096*4;
4949 // <rdar://problem/12258065> ARM64 needs 16KB page size for user land code
4950 // <rdar://problem/15974532> make armv7[s] use 16KB pages in user land code for iOS 8 or later
4951 if ( fSegmentAlignment
== 4096 ) {
4952 switch ( fOutputKind
) {
4953 case Options::kDynamicExecutable
:
4954 case Options::kDynamicLibrary
:
4955 case Options::kDynamicBundle
:
4956 case Options::kDyld
:
4957 if ( (fArchitecture
== CPU_TYPE_ARM64
)
4958 || ((fArchitecture
== CPU_TYPE_ARM
) && min_iOS(ld::iOS_7_0
)) ) {
4959 fSegmentAlignment
= 4096*4;
4962 case Options::kStaticExecutable
:
4963 case Options::kKextBundle
:
4964 // <rdar://problem/14676611> 16KB segments for arm64 kexts
4965 if ( (fArchitecture
== CPU_TYPE_ARM64
) && min_iOS(ld::iOS_9_0
) ) {
4966 fSegmentAlignment
= 4096*4;
4969 case Options::kObjectFile
:
4970 case Options::kPreload
:
4977 // <rdar://problem/13624134> linker should not convert dwarf unwind if .o file has compact unwind section
4978 switch ( fOutputKind
) {
4979 case Options::kDynamicExecutable
:
4980 case Options::kDynamicLibrary
:
4981 case Options::kDynamicBundle
:
4982 case Options::kDyld
:
4983 if ( fKeepDwarfUnwindForcedOn
) {
4984 fKeepDwarfUnwind
= true;
4986 else if ( fKeepDwarfUnwindForcedOff
) {
4987 fKeepDwarfUnwind
= false;
4990 if ( minOS(ld::mac10_9
, ld::iOS_7_0
) )
4991 fKeepDwarfUnwind
= false;
4993 fKeepDwarfUnwind
= true;
4996 case Options::kKextBundle
:
4997 case Options::kStaticExecutable
:
4998 case Options::kObjectFile
:
4999 case Options::kPreload
:
5000 fKeepDwarfUnwind
= true;
5004 // Make sure -image_base matches alignment
5005 uint64_t alignedBaseAddress
= (fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
);
5006 if ( alignedBaseAddress
!= fBaseAddress
) {
5007 warning("base address 0x%llX is not properly aligned. Changing it to 0x%llX", fBaseAddress
, alignedBaseAddress
);
5008 fBaseAddress
= alignedBaseAddress
;
5011 // If -dirty_data_list not specified, look in $SDKROOT/AppleInternal/DirtyDataFiles/<dylib>.dirty for dirty data list
5012 if ( fSymbolsMovesData
.empty() && fUseDataConstSegment
&& ( fDylibInstallName
!= NULL
) && !fSDKPaths
.empty() ) {
5013 const char* dylibLeaf
= strrchr(fDylibInstallName
, '/');
5015 char path
[PATH_MAX
];
5016 strlcpy(path
, fSDKPaths
.front(), sizeof(path
));
5017 strlcat(path
, "/AppleInternal/DirtyDataFiles", sizeof(path
));
5018 strlcat(path
, dylibLeaf
, sizeof(path
));
5019 strlcat(path
, ".dirty", sizeof(path
));
5021 if ( info
.checkFileExists(*this, path
) )
5022 addSymbolMove("__DATA_DIRTY", path
, fSymbolsMovesData
, "-dirty_data_list");
5026 // <rdar://problem/20503811> Reduce the default alignment of structures/arrays to save memory in embedded systems
5027 if ( fMaxDefaultCommonAlign
== 0 ) {
5028 if ( fOutputKind
== Options::kPreload
)
5029 fMaxDefaultCommonAlign
= 8;
5031 fMaxDefaultCommonAlign
= 15;
5035 void Options::checkIllegalOptionCombinations()
5037 // check -undefined setting
5038 switch ( fUndefinedTreatment
) {
5039 case kUndefinedError
:
5042 case kUndefinedDynamicLookup
:
5043 switch (fPlatform
) {
5047 case kPlatformWatchOS
:
5048 #if SUPPORT_APPLE_TV
5049 case kPlatform_tvOS
:
5051 if ( fOutputKind
!= kKextBundle
)
5052 warning("-undefined dynamic_lookup is deprecated on %s", platformName(fPlatform
));
5058 case kUndefinedWarning
:
5059 case kUndefinedSuppress
:
5060 // requires flat namespace
5061 if ( fNameSpace
== kTwoLevelNameSpace
)
5062 throw "can't use -undefined warning or suppress with -twolevel_namespace";
5066 // unify -sub_umbrella with dylibs
5067 for (std::vector
<const char*>::iterator it
= fSubUmbellas
.begin(); it
!= fSubUmbellas
.end(); it
++) {
5068 const char* subUmbrella
= *it
;
5070 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
5071 Options::FileInfo
& info
= *fit
;
5072 const char* lastSlash
= strrchr(info
.path
, '/');
5073 if ( lastSlash
== NULL
)
5074 lastSlash
= info
.path
- 1;
5075 std::string
path(&lastSlash
[1]);
5076 auto idx
= path
.find(".tbd", path
.size() - 4);
5077 if (idx
!= std::string::npos
)
5079 if ( path
== subUmbrella
) {
5080 info
.options
.fReExport
= true;
5082 fLinkSnapshot
.recordSubUmbrella(info
.path
);
5087 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella
);
5090 // unify -sub_library with dylibs
5091 for (std::vector
<const char*>::iterator it
= fSubLibraries
.begin(); it
!= fSubLibraries
.end(); it
++) {
5092 const char* subLibrary
= *it
;
5094 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
5095 Options::FileInfo
& info
= *fit
;
5096 const char* lastSlash
= strrchr(info
.path
, '/');
5097 if ( lastSlash
== NULL
)
5098 lastSlash
= info
.path
- 1;
5099 const char* dot
= strchr(&lastSlash
[1], '.');
5101 dot
= &lastSlash
[strlen(lastSlash
)];
5102 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
5103 info
.options
.fReExport
= true;
5105 fLinkSnapshot
.recordSubLibrary(info
.path
);
5110 warning("-sub_library %s does not match a supplied dylib", subLibrary
);
5113 // sync reader options
5114 if ( fNameSpace
!= kTwoLevelNameSpace
) {
5115 fFlatNamespace
= true;
5116 switch (fPlatform
) {
5120 case kPlatformWatchOS
:
5121 #if SUPPORT_APPLE_TV
5122 case Options::kPlatform_tvOS
:
5124 warning("-flat_namespace is deprecated on %s", platformName(fPlatform
));
5132 // check -stack_addr
5133 if ( fStackAddr
!= 0 ) {
5134 switch (fArchitecture
) {
5137 if ( fStackAddr
> 0xFFFFFFFF )
5138 throw "-stack_addr must be < 4G for 32-bit processes";
5140 case CPU_TYPE_X86_64
:
5141 case CPU_TYPE_ARM64
:
5144 if ( (fStackAddr
& -4096) != fStackAddr
)
5145 throw "-stack_addr must be multiples of 4K";
5146 if ( fStackSize
== 0 )
5147 throw "-stack_addr must be used with -stack_size";
5150 // check -stack_size
5151 if ( fStackSize
!= 0 ) {
5152 switch (fArchitecture
) {
5154 if ( fPlatform
== kPlatformOSX
) {
5155 if ( fStackSize
> 0xFFFFFFFF )
5156 throw "-stack_size must be < 4GB for 32-bit processes";
5157 if ( fStackAddr
== 0 )
5158 fStackAddr
= 0xC0000000;
5159 if ( (fStackAddr
> 0xB0000000) && ((fStackAddr
-fStackSize
) < 0xB0000000) )
5160 warning("custom stack placement overlaps and will disable shared region");
5163 if ( fStackSize
> 0x1F000000 )
5164 throw "-stack_size must be < 496MB";
5165 if ( fStackAddr
== 0 )
5166 fStackAddr
= 0xC0000000;
5170 if ( fStackSize
> 0x1F000000 )
5171 throw "-stack_size must be < 496MB";
5172 if ( fStackAddr
== 0 )
5173 fStackAddr
= 0x1F000000;
5174 if ( fStackAddr
> 0x20000000)
5175 throw "-stack_addr must be < 0x20000000 for arm";
5177 case CPU_TYPE_X86_64
:
5178 if ( fPlatform
== kPlatformOSX
) {
5179 if ( fStackSize
> 0x10000000000 )
5180 throw "-stack_size must be <= 1TB";
5181 if ( fStackAddr
== 0 ) {
5182 fStackAddr
= 0x00007FFF5C000000LL
;
5186 if ( fStackSize
> 0x20000000 )
5187 throw "-stack_size must be <= 512MB";
5188 if ( fStackAddr
== 0 ) {
5189 fStackAddr
= 0x120000000;
5192 case CPU_TYPE_ARM64
:
5193 if ( fStackSize
> 0x20000000 )
5194 throw "-stack_size must be <= 512MB";
5195 if ( fStackAddr
== 0 )
5196 fStackAddr
= 0x120000000;
5200 if ( (fStackSize
& (-fSegmentAlignment
)) != fStackSize
)
5201 throwf("-stack_size must be multiple of segment alignment (%lldKB)", fSegmentAlignment
/1024);
5202 switch ( fOutputKind
) {
5203 case Options::kDynamicExecutable
:
5204 case Options::kStaticExecutable
:
5205 // custom stack size only legal when building main executable
5207 case Options::kDynamicLibrary
:
5208 case Options::kDynamicBundle
:
5209 case Options::kObjectFile
:
5210 case Options::kDyld
:
5211 case Options::kPreload
:
5212 case Options::kKextBundle
:
5213 throw "-stack_size option can only be used when linking a main executable";
5215 if ( fStackSize
> fStackAddr
)
5216 throwf("-stack_size (0x%08llX) must be smaller than -stack_addr (0x%08llX)", fStackSize
, fStackAddr
);
5219 // check that -allow_stack_execute is only used with main executables
5220 if ( fExecutableStack
) {
5221 switch ( fOutputKind
) {
5222 case Options::kDynamicExecutable
:
5223 case Options::kStaticExecutable
:
5224 // -allow_stack_execute size only legal when building main executable
5226 case Options::kDynamicLibrary
:
5227 case Options::kDynamicBundle
:
5228 case Options::kObjectFile
:
5229 case Options::kDyld
:
5230 case Options::kPreload
:
5231 case Options::kKextBundle
:
5232 throw "-allow_stack_execute option can only be used when linking a main executable";
5236 // check that -allow_heap_execute is only used with i386 main executables
5237 if ( fDisableNonExecutableHeap
) {
5238 if ( fArchitecture
!= CPU_TYPE_I386
)
5239 throw "-allow_heap_execute option can only be used when linking for i386";
5240 switch ( fOutputKind
) {
5241 case Options::kDynamicExecutable
:
5242 // -allow_heap_execute only legal when building main executable
5244 case Options::kStaticExecutable
:
5245 case Options::kDynamicLibrary
:
5246 case Options::kDynamicBundle
:
5247 case Options::kObjectFile
:
5248 case Options::kDyld
:
5249 case Options::kPreload
:
5250 case Options::kKextBundle
:
5251 throw "-allow_heap_execute option can only be used when linking a main executable";
5255 // check -client_name is only used when making a bundle or main executable
5256 if ( fClientName
!= NULL
) {
5257 switch ( fOutputKind
) {
5258 case Options::kDynamicExecutable
:
5259 case Options::kDynamicBundle
:
5261 case Options::kStaticExecutable
:
5262 case Options::kDynamicLibrary
:
5263 case Options::kObjectFile
:
5264 case Options::kDyld
:
5265 case Options::kPreload
:
5266 case Options::kKextBundle
:
5267 throw "-client_name can only be used with -bundle";
5271 // check -init is only used when building a dylib
5272 if ( (fInitFunctionName
!= NULL
) && (fOutputKind
!= Options::kDynamicLibrary
) )
5273 throw "-init can only be used with -dynamiclib";
5275 // check -bundle_loader only used with -bundle
5276 if ( (fBundleLoader
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
5277 throw "-bundle_loader can only be used with -bundle";
5279 // check -dtrace not used with -r
5280 if ( (fDtraceScriptName
!= NULL
) && (fOutputKind
== Options::kObjectFile
) )
5281 throw "-dtrace can only be used when creating final linked images";
5283 // check -d can only be used with -r
5284 if ( fMakeTentativeDefinitionsReal
&& (fOutputKind
!= Options::kObjectFile
) )
5285 throw "-d can only be used with -r";
5287 // check that -root_safe is not used with -r
5288 if ( fRootSafe
&& (fOutputKind
== Options::kObjectFile
) )
5289 throw "-root_safe cannot be used with -r";
5291 // check that -setuid_safe is not used with -r
5292 if ( fSetuidSafe
&& (fOutputKind
== Options::kObjectFile
) )
5293 throw "-setuid_safe cannot be used with -r";
5295 // <rdar://problem/12781832> compiler driver no longer uses -objc_abi_version, it uses -ios_simulator_version_min instead
5296 if ( !fObjCABIVersion1Override
&& !fObjCABIVersion2Override
&& fTargetIOSSimulator
)
5297 fObjCABIVersion2Override
= true;
5299 // rdar://problem/4718189 map ObjC class names to new runtime names
5300 bool alterObjC1ClassNamesToObjC2
= false;
5301 switch (fArchitecture
) {
5303 // i386 only uses new symbols when using objc2 ABI
5304 if ( fObjCABIVersion2Override
)
5305 alterObjC1ClassNamesToObjC2
= true;
5307 case CPU_TYPE_X86_64
:
5309 case CPU_TYPE_ARM64
:
5310 alterObjC1ClassNamesToObjC2
= true;
5314 // make sure all required exported symbols exist
5315 std::vector
<const char*> impliedExports
;
5316 for (NameSet::iterator it
=fExportSymbols
.regularBegin(); it
!= fExportSymbols
.regularEnd(); ++it
) {
5317 const char* name
= *it
;
5318 const int len
= strlen(name
);
5319 if ( (strcmp(&name
[len
-3], ".eh") == 0) || (strncmp(name
, ".objc_category_name_", 20) == 0) ) {
5320 // never export .eh symbols
5321 warning("ignoring %s in export list", name
);
5323 else if ( (fArchitecture
== CPU_TYPE_I386
) && !fObjCABIVersion2Override
&& (strncmp(name
, "_OBJC_CLASS_$", 13) == 0) ) {
5324 warning("ignoring Objc2 Class symbol %s in i386 export list", name
);
5325 fRemovedExports
.insert(name
);
5327 else if ( alterObjC1ClassNamesToObjC2
&& (strncmp(name
, ".objc_class_name_", 17) == 0) ) {
5328 // linking ObjC2 ABI, but have ObjC1 ABI name in export list. Change it to intended name
5329 fRemovedExports
.insert(name
);
5331 asprintf(&temp
, "_OBJC_CLASS_$_%s", &name
[17]);
5332 impliedExports
.push_back(temp
);
5333 asprintf(&temp
, "_OBJC_METACLASS_$_%s", &name
[17]);
5334 impliedExports
.push_back(temp
);
5337 fInitialUndefines
.push_back(name
);
5340 fExportSymbols
.remove(fRemovedExports
);
5341 for (std::vector
<const char*>::iterator it
=impliedExports
.begin(); it
!= impliedExports
.end(); ++it
) {
5342 const char* name
= *it
;
5343 fExportSymbols
.insert(name
);
5344 fInitialUndefines
.push_back(name
);
5347 // make sure all required re-exported symbols exist
5348 for (NameSet::iterator it
=fReExportSymbols
.regularBegin(); it
!= fReExportSymbols
.regularEnd(); ++it
) {
5349 fInitialUndefines
.push_back(*it
);
5352 // make sure that -init symbol exists
5353 if ( fInitFunctionName
!= NULL
)
5354 fInitialUndefines
.push_back(fInitFunctionName
);
5356 // make sure that entry symbol exists
5357 switch ( fOutputKind
) {
5358 case Options::kDynamicExecutable
:
5359 case Options::kStaticExecutable
:
5360 case Options::kDyld
:
5361 case Options::kPreload
:
5362 fInitialUndefines
.push_back(fEntryName
);
5364 case Options::kDynamicLibrary
:
5365 case Options::kDynamicBundle
:
5366 case Options::kObjectFile
:
5367 case Options::kKextBundle
:
5371 // make sure every alias base exists
5372 for (std::vector
<AliasPair
>::iterator it
=fAliases
.begin(); it
!= fAliases
.end(); ++it
) {
5373 fInitialUndefines
.push_back(it
->realName
);
5376 // check custom segments
5377 if ( fCustomSegmentAddresses
.size() != 0 ) {
5378 // verify no segment is in zero page
5379 if ( fZeroPageSize
!= ULLONG_MAX
) {
5380 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
5381 if ( it
->address
< fZeroPageSize
)
5382 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it
->name
, it
->address
);
5385 // verify no duplicates
5386 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
5387 for (std::vector
<SegmentStart
>::iterator it2
= fCustomSegmentAddresses
.begin(); it2
!= fCustomSegmentAddresses
.end(); ++it2
) {
5388 if ( (it
->address
== it2
->address
) && (it
!= it2
) )
5389 throwf("duplicate -segaddr addresses for %s and %s", it
->name
, it2
->name
);
5391 // a custom segment address of zero will disable the use of a zero page
5392 if ( it
->address
== 0 )
5397 if ( fZeroPageSize
== ULLONG_MAX
) {
5398 // zero page size not specified on command line, set default
5399 switch (fArchitecture
) {
5402 // first 4KB for 32-bit architectures
5403 fZeroPageSize
= 0x1000;
5405 case CPU_TYPE_ARM64
:
5406 case CPU_TYPE_X86_64
:
5407 // first 4GB for x86_64 on all OS's
5408 fZeroPageSize
= 0x100000000ULL
;
5411 // if -arch not used, default to 4K zero-page
5412 fZeroPageSize
= 0x1000;
5416 switch ( fOutputKind
) {
5417 case Options::kDynamicExecutable
:
5418 case Options::kStaticExecutable
:
5419 // -pagezero_size size only legal when building main executable
5421 case Options::kDynamicLibrary
:
5422 case Options::kDynamicBundle
:
5423 case Options::kObjectFile
:
5424 case Options::kDyld
:
5425 case Options::kPreload
:
5426 case Options::kKextBundle
:
5427 if ( fZeroPageSize
!= 0 )
5428 throw "-pagezero_size option can only be used when linking a main executable";
5432 // if main executable with custom base address, model zero page as custom segment
5433 if ( (fOutputKind
== Options::kDynamicExecutable
) && (fBaseAddress
!= 0) && (fZeroPageSize
!= 0) ) {
5435 seg
.name
= "__PAGEZERO";
5437 fCustomSegmentAddresses
.push_back(seg
);
5440 // -dead_strip and -r are incompatible
5441 if ( fDeadStrip
&& (fOutputKind
== Options::kObjectFile
) )
5442 throw "-r and -dead_strip cannot be used together";
5444 // can't use -rpath unless targeting 10.5 or later
5445 if ( fRPaths
.size() > 0 ) {
5446 if ( !minOS(ld::mac10_5
, ld::iOS_2_0
) )
5447 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
5448 switch ( fOutputKind
) {
5449 case Options::kDynamicExecutable
:
5450 case Options::kDynamicLibrary
:
5451 case Options::kDynamicBundle
:
5453 case Options::kStaticExecutable
:
5454 case Options::kObjectFile
:
5455 case Options::kDyld
:
5456 case Options::kPreload
:
5457 case Options::kKextBundle
:
5458 throw "-rpath can only be used when creating a dynamic final linked image";
5462 if ( fPositionIndependentExecutable
) {
5463 switch ( fOutputKind
) {
5464 case Options::kDynamicExecutable
:
5465 // check -pie is only used when building a dynamic main executable for 10.5
5466 if ( !minOS(ld::mac10_5
, ld::iOS_4_2
) ) {
5467 if ( fIOSVersionMin
== ld::iOSVersionUnset
)
5468 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
5470 throw "-pie can only be used when targeting iOS 4.2 or later";
5473 case Options::kStaticExecutable
:
5474 case Options::kPreload
:
5475 // -pie is ok with -static or -preload
5477 case Options::kDynamicLibrary
:
5478 case Options::kDynamicBundle
:
5479 warning("-pie being ignored. It is only used when linking a main executable");
5480 fPositionIndependentExecutable
= false;
5482 case Options::kObjectFile
:
5483 case Options::kDyld
:
5484 case Options::kKextBundle
:
5485 throw "-pie can only be used when linking a main executable";
5489 // check -read_only_relocs is not used with x86_64
5490 if ( fAllowTextRelocs
) {
5491 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
!= kKextBundle
) ) {
5492 warning("-read_only_relocs cannot be used with x86_64");
5493 fAllowTextRelocs
= false;
5497 // check -mark_auto_dead_strip is only used with dylibs
5498 if ( fMarkDeadStrippableDylib
) {
5499 if ( fOutputKind
!= Options::kDynamicLibrary
) {
5500 warning("-mark_auto_dead_strip can only be used when creating a dylib");
5501 fMarkDeadStrippableDylib
= false;
5505 // -force_cpusubtype_ALL is not supported for ARM
5506 if ( fForceSubtypeAll
) {
5507 if ( fArchitecture
== CPU_TYPE_ARM
) {
5508 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
5512 // -reexported_symbols_list can only be used with -dynamiclib
5513 if ( !fReExportSymbols
.empty() ) {
5514 if ( fOutputKind
!= Options::kDynamicLibrary
)
5515 throw "-reexported_symbols_list can only used used when created dynamic libraries";
5516 if ( !minOS(ld::mac10_7
, ld::iOS_4_2
) )
5517 throw "targeted OS version does not support -reexported_symbols_list";
5520 // -dyld_env can only be used with main executables
5521 if ( (fOutputKind
!= Options::kDynamicExecutable
) && (fDyldEnvironExtras
.size() != 0) )
5522 throw "-dyld_env can only used used when created main executables";
5524 // -segment_order can only be used with -preload
5525 if ( !fSegmentOrder
.empty() && (fOutputKind
!= Options::kPreload
) )
5526 throw "-segment_order can only used used with -preload output";
5528 // warn about bitcode option combinations
5529 if ( !fBundleBitcode
) {
5530 if ( fVerifyBitcode
)
5531 warning("-bitcode_verify is ignored without -bitcode_bundle");
5532 else if ( fHideSymbols
)
5533 warning("-bitcode_hide_symbols is ignored without -bitcode_bundle");
5535 if ( fReverseMapPath
!= NULL
&& !fHideSymbols
) {
5536 throw "-bitcode_symbol_map can only be used with -bitcode_hide_symbols";
5538 if ( fBitcodeKind
!= kBitcodeProcess
&&
5539 fOutputKind
!= Options::kObjectFile
) {
5540 throw "-bitcode_process_mode can only be used together with -r";
5542 // auto fix up the process type for strip -S.
5543 // when there is only one input and output type is object file, downgrade kBitcodeProcess to kBitcodeAsData.
5544 if ( fOutputKind
== Options::kObjectFile
&& fInputFiles
.size() == 1 && fBitcodeKind
== Options::kBitcodeProcess
)
5545 fBitcodeKind
= Options::kBitcodeAsData
;
5547 // <rdar://problem/17598404> warn if building an embedded iOS dylib for pre-iOS 8
5548 // <rdar://problem/18935714> How can we suppress "ld: warning: embedded dylibs/frameworks only run on iOS 8 or later" when building XCTest?
5549 if ( (fOutputKind
== Options::kDynamicLibrary
) && (fIOSVersionMin
!= ld::iOSVersionUnset
) && (fDylibInstallName
!= NULL
) ) {
5550 if ( !min_iOS(ld::iOS_8_0
) && (fDylibInstallName
[0] == '@') && !fEncryptableForceOff
)
5551 warning("embedded dylibs/frameworks only run on iOS 8 or later");
5556 void Options::checkForClassic(int argc
, const char* argv
[])
5559 bool archFound
= false;
5560 bool staticFound
= false;
5561 bool dtraceFound
= false;
5562 bool kextFound
= false;
5563 bool rFound
= false;
5564 bool creatingMachKernel
= false;
5565 bool newLinker
= false;
5567 // build command line buffer in case ld crashes
5568 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
5569 CRSetCrashLogMessage(crashreporterBuffer
);
5571 const char* srcRoot
= getenv("SRCROOT");
5572 if ( srcRoot
!= NULL
) {
5573 strlcpy(crashreporterBuffer
, "SRCROOT=", crashreporterBufferSize
);
5574 strlcat(crashreporterBuffer
, srcRoot
, crashreporterBufferSize
);
5575 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
5578 strlcat(crashreporterBuffer
, LD_VERS
, crashreporterBufferSize
);
5579 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
5581 strlcat(crashreporterBuffer
, "ld ", crashreporterBufferSize
);
5582 for(int i
=1; i
< argc
; ++i
) {
5583 strlcat(crashreporterBuffer
, argv
[i
], crashreporterBufferSize
);
5584 strlcat(crashreporterBuffer
, " ", crashreporterBufferSize
);
5587 for(int i
=0; i
< argc
; ++i
) {
5588 const char* arg
= argv
[i
];
5589 if ( arg
[0] == '-' ) {
5590 if ( strcmp(arg
, "-arch") == 0 ) {
5591 parseArch(argv
[++i
]);
5594 else if ( strcmp(arg
, "-static") == 0 ) {
5597 else if ( strcmp(arg
, "-kext") == 0 ) {
5600 else if ( strcmp(arg
, "-dtrace") == 0 ) {
5603 else if ( strcmp(arg
, "-r") == 0 ) {
5606 else if ( strcmp(arg
, "-new_linker") == 0 ) {
5609 else if ( strcmp(arg
, "-classic_linker") == 0 ) {
5610 // ld_classic does not understand this option, so remove it
5611 for(int j
=i
; j
< argc
; ++j
)
5612 argv
[j
] = argv
[j
+1];
5613 warning("using ld_classic");
5614 this->gotoClassicLinker(argc
-1, argv
);
5616 else if ( strcmp(arg
, "-o") == 0 ) {
5617 const char* outfile
= argv
[++i
];
5618 if ( (outfile
!= NULL
) && (strstr(outfile
, "/mach_kernel") != NULL
) )
5619 creatingMachKernel
= true;
5625 void Options::gotoClassicLinker(int argc
, const char* argv
[])
5627 argv
[0] = "ld_classic";
5628 // ld_classic does not support -iphoneos_version_min, so change
5629 for(int j
=0; j
< argc
; ++j
) {
5630 if ( (strcmp(argv
[j
], "-iphoneos_version_min") == 0) || (strcmp(argv
[j
], "-ios_version_min") == 0) ) {
5631 argv
[j
] = "-macosx_version_min";
5637 // ld classic does not understand -kext (change to -static -r)
5638 for(int j
=0; j
< argc
; ++j
) {
5639 if ( strcmp(argv
[j
], "-kext") == 0)
5641 else if ( strcmp(argv
[j
], "-dynamic") == 0)
5642 argv
[j
] = "-static";
5644 // ld classic does not understand -demangle
5645 for(int j
=0; j
< argc
; ++j
) {
5646 if ( strcmp(argv
[j
], "-demangle") == 0)
5647 argv
[j
] = "-noprebind";
5649 // in -v mode, print command line passed to ld_classic
5650 for(int i
=0; i
< argc
; ++i
) {
5651 if ( strcmp(argv
[i
], "-v") == 0 ) {
5652 for(int j
=0; j
< argc
; ++j
)
5653 printf("%s ", argv
[j
]);
5658 char rawPath
[PATH_MAX
];
5659 char path
[PATH_MAX
];
5660 uint32_t bufSize
= PATH_MAX
;
5661 if ( _NSGetExecutablePath(rawPath
, &bufSize
) != -1 ) {
5662 if ( realpath(rawPath
, path
) != NULL
) {
5663 char* lastSlash
= strrchr(path
, '/');
5664 if ( lastSlash
!= NULL
) {
5665 strcpy(lastSlash
+1, "ld_classic");
5667 execvp(path
, (char**)argv
);
5671 // in case of error in above, try searching for ld_classic via PATH
5672 execvp(argv
[0], (char**)argv
);
5673 fprintf(stderr
, "can't exec ld_classic\n");
5678 // Note, returned string buffer is own by this function.
5679 // It should not be freed
5680 // It will be reused, so clients need to strdup() if they want
5681 // to use it long term.
5682 const char* Options::demangleSymbol(const char* sym
) const
5684 // only try to demangle symbols if -demangle on command line
5688 static size_t size
= 1024;
5689 static char* buff
= (char*)malloc(size
);
5692 // only try to demangle symbols that look like Swift symbols
5693 if ( strncmp(sym
, "__T", 3) == 0 ) {
5694 size_t demangledSize
= fnd_get_demangled_name(&sym
[1], buff
, size
);
5695 if ( demangledSize
> size
) {
5696 size
= demangledSize
+2;
5697 buff
= (char*)realloc(buff
, size
);
5698 demangledSize
= fnd_get_demangled_name(&sym
[1], buff
, size
);
5700 if ( demangledSize
!= 0 )
5705 // only try to demangle symbols that look like C++ symbols
5706 if ( strncmp(sym
, "__Z", 3) != 0 )
5710 char* result
= abi::__cxa_demangle(&sym
[1], buff
, &size
, &status
);
5711 if ( result
!= NULL
) {
5712 // if demangling successful, keep buffer for next demangle
5720 void Options::dumpDependency(uint8_t opcode
, const char* path
) const
5722 if ( !this->dumpDependencyInfo() )
5725 // one time open() of -dependency_info file
5726 if ( fDependencyFileDescriptor
== -1 ) {
5727 fDependencyFileDescriptor
= open(this->dependencyInfoPath(), O_WRONLY
| O_TRUNC
| O_CREAT
, 0666);
5728 if ( fDependencyFileDescriptor
== -1 )
5729 throwf("Could not open or create -dependency_info file: %s", this->dependencyInfoPath());
5732 uint8_t version
= depLinkerVersion
;
5733 if ( write(fDependencyFileDescriptor
, &version
, 1) == -1 )
5734 throwf("write() to -dependency_info failed, errno=%d", errno
);
5735 extern const char ldVersionString
[];
5736 if ( write(fDependencyFileDescriptor
, ldVersionString
, strlen(ldVersionString
)+1) == -1 )
5737 throwf("write() to -dependency_info failed, errno=%d", errno
);
5740 char realPath
[PATH_MAX
];
5741 if ( path
[0] != '/' ) {
5742 if ( realpath(path
, realPath
) != NULL
) {
5747 if ( write(fDependencyFileDescriptor
, &opcode
, 1) == -1 )
5748 throwf("write() to -dependency_info failed, errno=%d", errno
);
5749 if ( write(fDependencyFileDescriptor
, path
, strlen(path
)+1) == -1 )
5750 throwf("write() to -dependency_info failed, errno=%d", errno
);
5752 //fprintf(stderr, "0x%02X %s\n", opcode, path);