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>
37 #include <tapi/tapi.h>
44 #include "Architectures.hpp"
45 #include "MachOFileAbstraction.hpp"
49 // from FunctionNameDemangle.h
50 extern "C" size_t fnd_get_demangled_name(const char *mangledName
, char *outputBuffer
, size_t length
);
53 // upward dependency on lto::version()
55 extern const char* version();
56 extern unsigned static_api_version();
57 extern unsigned runtime_api_version();
60 // magic to place command line in crash reports
61 const int crashreporterBufferSize
= 2000;
62 static char crashreporterBuffer
[crashreporterBufferSize
];
63 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
64 #include <CrashReporterClient.h>
65 // hack until ld does not need to build on 10.6 anymore
66 struct crashreporter_annotations_t gCRAnnotations
67 __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION
)))
68 = { CRASHREPORTER_ANNOTATIONS_VERSION
, 0, 0, 0, 0, 0, 0 };
70 extern "C" char* __crashreporter_info__
;
72 char* __crashreporter_info__
= crashreporterBuffer
;
76 static bool sEmitWarnings
= true;
77 static bool sFatalWarnings
= false;
78 static const char* sWarningsSideFilePath
= NULL
;
79 static FILE* sWarningsSideFile
= NULL
;
80 static int sWarningsCount
= 0;
82 void warning(const char* format
, ...)
85 if ( sEmitWarnings
) {
87 if ( sWarningsSideFilePath
!= NULL
) {
88 if ( sWarningsSideFile
== NULL
)
89 sWarningsSideFile
= fopen(sWarningsSideFilePath
, "a");
91 va_start(list
, format
);
92 fprintf(stderr
, "ld: warning: ");
93 vfprintf(stderr
, format
, list
);
94 fprintf(stderr
, "\n");
95 if ( sWarningsSideFile
!= NULL
) {
96 fprintf(sWarningsSideFile
, "ld: warning: ");
97 vfprintf(sWarningsSideFile
, format
, list
);
98 fprintf(sWarningsSideFile
, "\n");
99 fflush(sWarningsSideFile
);
105 void throwf(const char* format
, ...)
109 va_start(list
, format
);
110 vasprintf(&p
, format
, list
);
118 bool Options::FileInfo::checkFileExists(const Options
& options
, const char *p
)
120 struct stat statBuffer
;
123 if ( stat(p
, &statBuffer
) == 0 ) {
124 if (p
!= path
) path
= strdup(p
);
125 modTime
= statBuffer
.st_mtime
;
128 if ( options
.dumpDependencyInfo() )
129 options
.dumpDependency(Options::depNotFound
, p
);
130 // fprintf(stderr, "not found: %s\n", p);
135 Options::Options(int argc
, const char* argv
[])
136 : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0), fArchitectureName("unknown"), fOutputKind(kDynamicExecutable
),
137 fHasPreferredSubType(false), fArchSupportsThumb2(false), fPrebind(false), fBindAtLoad(false), fKeepPrivateExterns(false),
138 fNeedsModuleTable(false), fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false),
139 fInterposeMode(kInterposeNone
), fDeadStrip(false), fNameSpace(kTwoLevelNameSpace
),
140 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL
), fFinalName(NULL
), fEntryName(NULL
),
141 fBaseAddress(0), fMaxAddress(0x7FFFFFFFFFFFFFFFLL
),
142 fBaseWritableAddress(0), fSplitSegs(false),
143 fExportMode(kExportDefault
), fLibrarySearchMode(kSearchDylibAndArchiveInEachDir
),
144 fUndefinedTreatment(kUndefinedError
), fMessagesPrefixedWithArchitecture(true),
145 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak
),
147 fUmbrellaName(NULL
), fInitFunctionName(NULL
), fDotOutputFile(NULL
), fExecutablePath(NULL
),
148 fBundleLoader(NULL
), fDtraceScriptName(NULL
), fSegAddrTablePath(NULL
), fMapPath(NULL
),
149 fDyldInstallPath("/usr/lib/dyld"), fLtoCachePath(NULL
), fTempLtoObjectPath(NULL
), fOverridePathlibLTO(NULL
), fLtoCpu(NULL
),
150 fZeroPageSize(ULLONG_MAX
), fStackSize(0), fStackAddr(0), fSourceVersion(0), fSDKVersion(0), fExecutableStack(false),
151 fNonExecutableHeap(false), fDisableNonExecutableHeap(false),
152 fMinimumHeaderPad(32), fSegmentAlignment(4096),
153 fCommonsMode(kCommonsIgnoreDylibs
), fUUIDMode(kUUIDContent
), fLocalSymbolHandling(kLocalSymbolsAll
), fWarnCommons(false),
154 fVerbose(false), fKeepRelocations(false), fWarnStabs(false),
155 fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
156 fSharedRegionEligible(false), fSharedRegionEligibleForceOff(false), fPrintOrderFileStatistics(false),
157 fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), fPIEOnCommandLine(false),
158 fDisablePositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
159 fDeadStripDylibs(false), fAllowTextRelocs(false), fWarnTextRelocs(false), fKextsUseStubs(false),
160 fUsingLazyDylibLinking(false), fEncryptable(true), fEncryptableForceOn(false), fEncryptableForceOff(false),
161 fOrderData(true), fMarkDeadStrippableDylib(false),
162 fMakeCompressedDyldInfo(true), fMakeCompressedDyldInfoForceOff(false), fNoEHLabels(false),
163 fAllowCpuSubtypeMismatches(false), fEnforceDylibSubtypesMatch(false), fUseSimplifiedDylibReExports(false),
164 fObjCABIVersion2Override(false), fObjCABIVersion1Override(false), fCanUseUpwardDylib(false),
165 fFullyLoadArchives(false), fLoadAllObjcObjectsFromArchives(false), fFlatNamespace(false),
166 fLinkingMainExecutable(false), fForFinalLinkedImage(false), fForStatic(false),
167 fForDyld(false), fMakeTentativeDefinitionsReal(false), fWhyLoad(false), fRootSafe(false),
168 fSetuidSafe(false), fImplicitlyLinkPublicDylibs(true), fAddCompactUnwindEncoding(true),
169 fWarnCompactUnwind(false), fRemoveDwarfUnwindIfCompactExists(false),
170 fAutoOrderInitializers(true), fOptimizeZeroFill(true), fMergeZeroFill(false), fLogObjectFiles(false),
171 fLogAllFiles(false), fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false), fTraceEmitJSON(false),
172 fOutputSlidable(false), fWarnWeakExports(false),
173 fObjcGcCompaction(false), fObjCGc(false), fObjCGcOnly(false),
174 fDemangle(false), fTLVSupport(false),
175 fVersionLoadCommand(false), fVersionLoadCommandForcedOn(false),
176 fVersionLoadCommandForcedOff(false), fBuildVersionLoadCommand(false), fFunctionStartsLoadCommand(false),
177 fFunctionStartsForcedOn(false), fFunctionStartsForcedOff(false),
178 fDataInCodeInfoLoadCommand(false), fDataInCodeInfoLoadCommandForcedOn(false), fDataInCodeInfoLoadCommandForcedOff(false),
179 fCanReExportSymbols(false), fObjcCategoryMerging(true), fPageAlignDataAtoms(false),
180 fNeedsThreadLoadCommand(false), fEntryPointLoadCommand(false),
181 fEntryPointLoadCommandForceOn(false), fEntryPointLoadCommandForceOff(false),
182 fSourceVersionLoadCommand(false),
183 fSourceVersionLoadCommandForceOn(false), fSourceVersionLoadCommandForceOff(false),
184 fTargetIOSSimulator(false), fExportDynamic(false), fAbsoluteSymbols(false),
185 fAllowSimulatorToLinkWithMacOSX(false), fKeepDwarfUnwind(true),
186 fKeepDwarfUnwindForcedOn(false), fKeepDwarfUnwindForcedOff(false),
187 fVerboseOptimizationHints(false), fIgnoreOptimizationHints(false),
188 fGenerateDtraceDOF(true), fAllowBranchIslands(true), fTraceSymbolLayout(false),
189 fMarkAppExtensionSafe(false), fCheckAppExtensionSafe(false), fForceLoadSwiftLibs(false),
190 fSharedRegionEncodingV2(false), fUseDataConstSegment(false),
191 fUseDataConstSegmentForceOn(false), fUseDataConstSegmentForceOff(false), fUseTextExecSegment(false),
192 fBundleBitcode(false), fHideSymbols(false), fVerifyBitcode(false),
193 fReverseMapUUIDRename(false), fDeDupe(true), fVerboseDeDupe(false),
194 fReverseMapPath(NULL
), fLTOCodegenOnly(false),
195 fIgnoreAutoLink(false), fAllowDeadDups(false), fAllowWeakImports(true), fNoInitializers(false), fBitcodeKind(kBitcodeProcess
),
196 fPlatform(kPlatformUnknown
), fDebugInfoStripping(kDebugInfoMinimal
), fTraceOutputFile(NULL
),
197 fMacVersionMin(ld::macVersionUnset
), fIOSVersionMin(ld::iOSVersionUnset
), fWatchOSVersionMin(ld::wOSVersionUnset
),
198 fSaveTempFiles(false), fSnapshotRequested(false), fPipelineFifo(NULL
),
199 fDependencyInfoPath(NULL
), fDependencyFileDescriptor(-1), fTraceFileDescriptor(-1), fMaxDefaultCommonAlign(0),
200 fUnalignedPointerTreatment(kUnalignedPointerIgnore
)
202 this->checkForClassic(argc
, argv
);
203 this->parsePreCommandLineEnvironmentSettings();
204 this->parse(argc
, argv
);
205 this->parsePostCommandLineEnvironmentSettings();
206 this->reconfigureDefaults();
207 this->checkIllegalOptionCombinations();
209 if ( this->dumpDependencyInfo() ) {
210 this->dumpDependency(depOutputFile
, fOutputFile
);
211 if ( fMapPath
!= NULL
)
212 this->dumpDependency(depOutputFile
, fMapPath
);
218 if ( fDependencyFileDescriptor
!= -1 )
219 ::close(fDependencyFileDescriptor
);
221 if ( fTraceFileDescriptor
!= -1 )
222 ::close(fTraceFileDescriptor
);
225 bool Options::errorBecauseOfWarnings() const
227 return (sFatalWarnings
&& (sWarningsCount
> 0));
231 const char* Options::installPath() const
233 if ( fDylibInstallName
!= NULL
)
234 return fDylibInstallName
;
235 else if ( fFinalName
!= NULL
)
242 bool Options::interposable(const char* name
) const
244 switch ( fInterposeMode
) {
247 case kInterposeAllExternal
:
250 return fInterposeList
.contains(name
);
252 throw "internal error";
256 bool Options::printWhyLive(const char* symbolName
) const
258 return fWhyLive
.contains(symbolName
);
262 const char* Options::dotOutputFile()
264 return fDotOutputFile
;
268 bool Options::hasWildCardExportRestrictList() const
270 // has -exported_symbols_list which contains some wildcards
271 return ((fExportMode
== kExportSome
) && fExportSymbols
.hasWildCards());
274 bool Options::hasWeakBitTweaks() const
276 // has -exported_symbols_list which contains some wildcards
277 return (!fForceWeakSymbols
.empty() || !fForceNotWeakSymbols
.empty());
280 bool Options::allGlobalsAreDeadStripRoots() const
282 // -exported_symbols_list means globals are not exported by default
283 if ( fExportMode
== kExportSome
)
286 switch ( fOutputKind
) {
287 case Options::kDynamicExecutable
:
288 // <rdar://problem/12839986> Add the -export_dynamic flag
289 return fExportDynamic
;
290 case Options::kStaticExecutable
:
291 // <rdar://problem/13361218> Support the -export_dynamic flag for xnu
292 return fExportDynamic
;
293 case Options::kPreload
:
294 // by default unused globals in a main executable are stripped
296 case Options::kDynamicLibrary
:
297 case Options::kDynamicBundle
:
298 case Options::kObjectFile
:
300 case Options::kKextBundle
:
307 bool Options::keepRelocations()
309 return fKeepRelocations
;
312 bool Options::warnStabs()
317 const char* Options::executablePath()
319 return fExecutablePath
;
322 uint32_t Options::initialSegProtection(const char* segName
) const
324 for(std::vector
<Options::SegmentProtect
>::const_iterator it
= fCustomSegmentProtections
.begin(); it
!= fCustomSegmentProtections
.end(); ++it
) {
325 if ( strcmp(it
->name
, segName
) == 0 ) {
329 if ( strcmp(segName
, "__TEXT") == 0 ) {
330 return ( fUseTextExecSegment
? VM_PROT_READ
: (VM_PROT_READ
| VM_PROT_EXECUTE
) );
332 else if ( strcmp(segName
, "__TEXT_EXEC") == 0 ) {
333 return VM_PROT_READ
| VM_PROT_EXECUTE
;
335 else if ( strcmp(segName
, "__PAGEZERO") == 0 ) {
338 else if ( strcmp(segName
, "__LINKEDIT") == 0 ) {
342 // all others default to read-write
343 return VM_PROT_READ
| VM_PROT_WRITE
;
346 uint32_t Options::maxSegProtection(const char* segName
) const
348 // iPhoneOS always uses same protection for max and initial
349 // <rdar://problem/11663436> simulator apps need to use MacOSX max-prot
350 if ( (fPlatform
!= kPlatformOSX
) && !fTargetIOSSimulator
)
351 return initialSegProtection(segName
);
353 for(std::vector
<Options::SegmentProtect
>::const_iterator it
= fCustomSegmentProtections
.begin(); it
!= fCustomSegmentProtections
.end(); ++it
) {
354 if ( strcmp(it
->name
, segName
) == 0 ) {
358 if ( strcmp(segName
, "__PAGEZERO") == 0 ) {
361 // all others default to all
362 return VM_PROT_READ
| VM_PROT_WRITE
| VM_PROT_EXECUTE
;
365 uint64_t Options::segPageSize(const char* segName
) const
367 for(std::vector
<SegmentSize
>::const_iterator it
=fCustomSegmentSizes
.begin(); it
!= fCustomSegmentSizes
.end(); ++it
) {
368 if ( strcmp(it
->name
, segName
) == 0 )
371 return fSegmentAlignment
;
374 uint64_t Options::customSegmentAddress(const char* segName
) const
376 for(std::vector
<SegmentStart
>::const_iterator it
=fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
377 if ( strcmp(it
->name
, segName
) == 0 )
380 // if custom stack in use, model as segment with custom address
381 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
382 return fStackAddr
- fStackSize
;
386 bool Options::hasCustomSegmentAddress(const char* segName
) const
388 for(std::vector
<SegmentStart
>::const_iterator it
=fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
389 if ( strcmp(it
->name
, segName
) == 0 )
392 // if custom stack in use, model as segment with custom address
393 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
398 bool Options::hasCustomSectionAlignment(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) )
404 if ( fEncryptable
&& (strcmp(sectName
, "__oslogstring") == 0) && (strcmp(segName
, "__TEXT") == 0) )
410 uint8_t Options::customSectionAlignment(const char* segName
, const char* sectName
) const
412 for (std::vector
<SectionAlignment
>::const_iterator it
= fSectionAlignments
.begin(); it
!= fSectionAlignments
.end(); ++it
) {
413 if ( (strcmp(it
->segmentName
, segName
) == 0) && (strcmp(it
->sectionName
, sectName
) == 0) )
414 return it
->alignment
;
416 if ( fEncryptable
&& (strcmp(sectName
, "__oslogstring") == 0) && (strcmp(segName
, "__TEXT") == 0) )
417 return __builtin_ctz(fSegmentAlignment
);
422 bool Options::segmentOrderAfterFixedAddressSegment(const char* segName
) const
424 bool nowPinned
= false;
425 for (std::vector
<const char*>::const_iterator it
=fSegmentOrder
.begin(); it
!= fSegmentOrder
.end(); ++it
) {
426 if ( strcmp(*it
, segName
) == 0 )
428 if ( hasCustomSegmentAddress(*it
) )
434 bool Options::hasExportedSymbolOrder()
436 return (fExportSymbolsOrder
.size() > 0);
439 bool Options::exportedSymbolOrder(const char* sym
, unsigned int* order
) const
441 NameToOrder::const_iterator pos
= fExportSymbolsOrder
.find(sym
);
442 if ( pos
!= fExportSymbolsOrder
.end() ) {
443 *order
= pos
->second
;
452 void Options::loadSymbolOrderFile(const char* fileOfExports
, NameToOrder
& orderMapping
)
454 // read in whole file
455 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
457 throwf("can't open -exported_symbols_order file: %s", fileOfExports
);
458 struct stat stat_buf
;
459 ::fstat(fd
, &stat_buf
);
460 char* p
= (char*)malloc(stat_buf
.st_size
);
462 throwf("can't process -exported_symbols_order file: %s", fileOfExports
);
464 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
465 throwf("can't read -exported_symbols_order file: %s", fileOfExports
);
469 // parse into symbols and add to unordered_set
470 unsigned int count
= 0;
471 char * const end
= &p
[stat_buf
.st_size
];
472 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
473 char* symbolStart
= NULL
;
474 for (char* s
= p
; s
< end
; ++s
) {
480 else if ( !isspace(*s
) ) {
486 if ( (*s
== '\n') || (*s
== '\r') ) {
488 // removing any trailing spaces
490 while ( isspace(*last
) ) {
494 orderMapping
[symbolStart
] = ++count
;
500 if ( (*s
== '\n') || (*s
== '\r') )
505 if ( state
== inSymbol
) {
506 warning("missing line-end at end of file \"%s\"", fileOfExports
);
507 int len
= end
-symbolStart
+1;
508 char* temp
= new char[len
];
509 strlcpy(temp
, symbolStart
, len
);
511 // remove any trailing spaces
512 char* last
= &temp
[len
-2];
513 while ( isspace(*last
) ) {
517 orderMapping
[temp
] = ++count
;
520 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
523 bool Options::forceWeak(const char* symbolName
) const
525 return fForceWeakSymbols
.contains(symbolName
);
528 bool Options::forceNotWeak(const char* symbolName
) const
530 return fForceNotWeakSymbols
.contains(symbolName
);
533 bool Options::forceWeakNonWildCard(const char* symbolName
) const
535 return fForceWeakSymbols
.containsNonWildcard(symbolName
);
538 bool Options::forceNotWeakNonWildcard(const char* symbolName
) const
540 return fForceNotWeakSymbols
.containsNonWildcard(symbolName
);
543 bool Options::forceCoalesce(const char* symbolName
) const
545 return fForceCoalesceSymbols
.contains(symbolName
);
549 bool Options::shouldExport(const char* symbolName
) const
551 switch (fExportMode
) {
553 return fExportSymbols
.contains(symbolName
);
554 case kDontExportSome
:
555 return ! fDontExportSymbols
.contains(symbolName
);
559 throw "internal error";
562 bool Options::shouldReExport(const char* symbolName
) const
564 return fReExportSymbols
.contains(symbolName
);
567 bool Options::keepLocalSymbol(const char* symbolName
) const
569 switch (fLocalSymbolHandling
) {
570 case kLocalSymbolsAll
:
572 case kLocalSymbolsNone
:
574 case kLocalSymbolsSelectiveInclude
:
575 return fLocalSymbolsIncluded
.contains(symbolName
);
576 case kLocalSymbolsSelectiveExclude
:
577 return ! fLocalSymbolsExcluded
.contains(symbolName
);
579 throw "internal error";
582 const std::vector
<const char*>* Options::sectionOrder(const char* segName
) const
584 for (std::vector
<SectionOrderList
>::const_iterator it
=fSectionOrder
.begin(); it
!= fSectionOrder
.end(); ++it
) {
585 if ( strcmp(it
->segmentName
, segName
) == 0 )
586 return &it
->sectionOrder
;
591 uint32_t Options::minOSversion() const
595 return iOSVersionMin();
597 return macosxVersionMin();
598 case kPlatformWatchOS
:
599 return watchOSVersionMin();
601 case Options::kPlatform_tvOS
:
602 return iOSVersionMin();
604 case kPlatform_bridgeOS
:
605 return iOSVersionMin();
606 case kPlatformUnknown
:
612 void Options::setArchitecture(cpu_type_t type
, cpu_subtype_t subtype
, Options::Platform platform
)
614 for (const ArchInfo
* t
=archInfoArray
; t
->archName
!= NULL
; ++t
) {
615 if ( (type
== t
->cpuType
) && (subtype
== t
->cpuSubType
) ) {
616 fArchitecture
= type
;
617 fSubArchitecture
= subtype
;
618 fArchitectureName
= t
->archName
;
619 fHasPreferredSubType
= t
->isSubType
;
620 fArchSupportsThumb2
= t
->supportsThumb2
;
621 if ( fPlatform
== kPlatformUnknown
)
622 fPlatform
= platform
;
625 case CPU_TYPE_X86_64
:
626 if ( (fPlatform
== kPlatformOSX
) && (fOutputKind
!= Options::kObjectFile
) && (fMacVersionMin
== ld::macVersionUnset
) ) {
627 #ifdef DEFAULT_MACOSX_MIN_VERSION
628 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION
);
629 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
631 warning("-macosx_version_min not specified, assuming 10.6");
632 fMacVersionMin
= ld::mac10_6
;
638 if ( (fMacVersionMin
== ld::macVersionUnset
) && (fIOSVersionMin
== ld::iOSVersionUnset
) && (fOutputKind
!= Options::kObjectFile
) ) {
639 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
640 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION
);
641 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION
);
643 warning("-ios_version_min not specified, assuming 6.0");
644 setIOSVersionMin("6.0");
649 fLinkSnapshot
.recordArch(fArchitectureName
);
650 // only use compressed LINKEDIT for:
651 // Mac OS X 10.6 or later
653 if ( !fMakeCompressedDyldInfo
&& minOS(ld::mac10_6
, ld::iOS_3_1
) && !fMakeCompressedDyldInfoForceOff
)
654 fMakeCompressedDyldInfo
= true;
655 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
656 if ( minOS(ld::mac10_5
, ld::iOS_2_0
) )
657 fUseSimplifiedDylibReExports
= true;
661 fArchitectureName
= "unknown architecture";
664 bool Options::armUsesZeroCostExceptions() const
666 return ( (fArchitecture
== CPU_TYPE_ARM
) && (fSubArchitecture
== CPU_SUBTYPE_ARM_V7K
) );
669 void Options::parseArch(const char* arch
)
672 throw "-arch must be followed by an architecture string";
673 for (const ArchInfo
* t
=archInfoArray
; t
->archName
!= NULL
; ++t
) {
674 if ( strcmp(t
->archName
,arch
) == 0 ) {
675 fArchitectureName
= arch
;
676 fArchitecture
= t
->cpuType
;
677 fSubArchitecture
= t
->cpuSubType
;
678 fHasPreferredSubType
= t
->isSubType
;
679 fArchSupportsThumb2
= t
->supportsThumb2
;
683 throwf("unknown/unsupported architecture name for: -arch %s", arch
);
686 bool Options::checkForFile(const char* format
, const char* dir
, const char* rootName
, FileInfo
& result
) const
688 char possiblePath
[strlen(dir
)+strlen(rootName
)+strlen(format
)+8];
689 sprintf(possiblePath
, format
, dir
, rootName
);
690 bool found
= result
.checkFileExists(*this, possiblePath
);
691 if ( fTraceDylibSearching
)
692 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), possiblePath
);
697 Options::FileInfo
Options::findLibrary(const char* rootName
, bool dylibsOnly
) const
700 const int rootNameLen
= strlen(rootName
);
701 // if rootName ends in .o there is no .a vs .dylib choice
702 if ( (rootNameLen
> 3) && (strcmp(&rootName
[rootNameLen
-2], ".o") == 0) ) {
703 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
704 it
!= fLibrarySearchPaths
.end();
706 const char* dir
= *it
;
707 if ( checkForFile("%s/%s", dir
, rootName
, result
) )
712 bool lookForDylibs
= false;
713 switch ( fOutputKind
) {
714 case Options::kDynamicExecutable
:
715 case Options::kDynamicLibrary
:
716 case Options::kDynamicBundle
:
717 case Options::kObjectFile
: // <rdar://problem/15914513>
718 lookForDylibs
= true;
720 case Options::kStaticExecutable
:
722 case Options::kPreload
:
723 case Options::kKextBundle
:
724 lookForDylibs
= false;
727 switch ( fLibrarySearchMode
) {
728 case kSearchAllDirsForDylibsThenAllDirsForArchives
:
729 // first look in all directories for just for dylibs
730 if ( lookForDylibs
) {
731 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
732 it
!= fLibrarySearchPaths
.end();
734 const char* dir
= *it
;
735 auto path
= std::string(dir
) + "/lib" + rootName
+ ".dylib";
736 if ( findFile(path
, {".tbd"}, result
) )
739 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
740 it
!= fLibrarySearchPaths
.end();
742 const char* dir
= *it
;
743 if ( checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
747 // next look in all directories for just for archives
749 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
750 it
!= fLibrarySearchPaths
.end();
752 const char* dir
= *it
;
753 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
759 case kSearchDylibAndArchiveInEachDir
:
760 // look in each directory for just for a dylib then for an archive
761 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
762 it
!= fLibrarySearchPaths
.end();
764 const char* dir
= *it
;
765 auto path
= std::string(dir
) + "/lib" + rootName
+ ".dylib";
766 if ( lookForDylibs
&& findFile(path
, {".tbd"}, result
) )
768 if ( lookForDylibs
&& checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
770 if ( !dylibsOnly
&& checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
776 throwf("library not found for -l%s", rootName
);
779 Options::FileInfo
Options::findFramework(const char* frameworkName
) const
781 if ( frameworkName
== NULL
)
782 throw "-framework missing next argument";
783 char temp
[strlen(frameworkName
)+1];
784 strcpy(temp
, frameworkName
);
785 const char* name
= temp
;
786 const char* suffix
= NULL
;
787 char* comma
= strchr(temp
, ',');
788 if ( comma
!= NULL
) {
792 return findFramework(name
, suffix
);
795 Options::FileInfo
Options::findFramework(const char* rootName
, const char* suffix
) const
797 for (const auto* path
: fFrameworkSearchPaths
) {
798 auto possiblePath
= std::string(path
).append("/").append(rootName
).append(".framework/").append(rootName
);
799 if ( suffix
!= nullptr ) {
800 char realPath
[PATH_MAX
];
801 // no symlink in framework to suffix variants, so follow main symlink
802 if ( realpath(possiblePath
.c_str(), realPath
) != nullptr )
803 possiblePath
= std::string(realPath
).append(suffix
);
806 if ( findFile(possiblePath
, {".tbd"}, result
) )
809 // try without suffix
810 if ( suffix
!= NULL
)
811 return findFramework(rootName
, NULL
);
813 throwf("framework not found %s", rootName
);
816 static std::string
replace_extension(const std::string
&path
, const std::string
&ext
)
819 auto lastSlashIdx
= result
.find_last_of('/');
820 auto lastDotIdx
= result
.find_last_of('.');
821 if (lastDotIdx
!= std::string::npos
&& lastDotIdx
> lastSlashIdx
)
822 result
.erase(lastDotIdx
, std::string::npos
);
823 if ( ext
.size() > 0 && ext
[0] == '.' )
826 result
.append('.' + ext
);
830 bool Options::findFile(const std::string
&path
, const std::vector
<std::string
> &tbdExtensions
, FileInfo
& result
) const
833 for ( const auto &ext
: tbdExtensions
) {
834 auto newPath
= replace_extension(path
, ext
);
835 bool found
= tbdInfo
.checkFileExists(*this, newPath
.c_str());
836 if ( fTraceDylibSearching
)
837 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), newPath
.c_str());
844 bool found
= dylibInfo
.checkFileExists(*this, path
.c_str());
845 if ( fTraceDylibSearching
)
846 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), path
.c_str());
849 // There is only a text-based stub file or a dynamic library file.
850 if ( tbdInfo
.missing() != dylibInfo
.missing() ) {
851 result
= tbdInfo
.missing() ? dylibInfo
: tbdInfo
;
853 // There are both - a text-based stub file and a dynamic library file.
854 else if ( !tbdInfo
.missing() && !dylibInfo
.missing() ) {
855 // Check if we should prefer the text-based stub file (installapi).
856 if (tapi::LinkerInterfaceFile::shouldPreferTextBasedStubFile(tbdInfo
.path
)) {
859 // If the files are still in sync we can use and should use the text-based stub file.
860 else if (tapi::LinkerInterfaceFile::areEquivalent(tbdInfo
.path
, dylibInfo
.path
)) {
863 // Otherwise issue a warning and fall-back to the dynamic library file.
865 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
);
875 static bool startsWith(const std::string
& str
, const std::string
& prefix
)
877 return (str
.compare(0, prefix
.length(), prefix
) == 0);
880 static std::string
getDirPath(const std::string
& path
)
882 std::string::size_type lastSlashPos
= path
.find_last_of('/');
883 if ( lastSlashPos
== std::string::npos
)
886 return path
.substr(0, lastSlashPos
+1);
889 Options::FileInfo
Options::findFile(const std::string
&path
, const ld::dylib::File
* fromDylib
) const
893 // if absolute path and not a .o file, then use SDK prefix
894 if ( (path
[0] == '/') && (strcmp(&path
[path
.size()-2], ".o") != 0) ) {
895 for (const auto* sdkPathDir
: fSDKPaths
) {
896 auto possiblePath
= std::string(sdkPathDir
) + path
;
897 if ( findFile(possiblePath
, {".tbd"}, result
) )
902 // expand @ variables
903 if ( path
[0] == '@' ) {
904 if ( startsWith(path
, "@executable_path/") && (fExecutablePath
!= nullptr) ) {
905 std::string exeBasedPath
= getDirPath(fExecutablePath
) + &path
[17];
906 if ( findFile(exeBasedPath
, {".tbd"}, result
) )
909 else if ( startsWith(path
, "@loader_path/") && (fromDylib
!= nullptr) ) {
910 char absPath
[PATH_MAX
];
911 if ( realpath(fromDylib
->path(), absPath
) != NULL
) {
912 std::string loaderBasedPath
= getDirPath(fromDylib
->path()) + &path
[13];
913 if ( findFile(loaderBasedPath
, {".tbd"}, result
) )
917 else if ( startsWith(path
, "@rpath/") ) {
918 // first search any LC_RPATH supplied by dyld that re-exports dylib to be found
919 if ( fromDylib
!= nullptr ) {
920 for (const char* rp
: fromDylib
->rpaths() ) {
921 std::string rpath
= rp
;
922 // handle dylib that has LC_RPATH = @loader_path/blah
923 if ( startsWith(rpath
, "@loader_path/") ) {
924 char absPath
[PATH_MAX
];
925 if ( realpath(fromDylib
->path(), absPath
) != NULL
)
926 rpath
= getDirPath(absPath
) + &rpath
[13];
928 rpath
= getDirPath(fromDylib
->path()) + &rpath
[13];
930 std::string rpathBasedPath
= rpath
+ "/" + &path
[6];
931 if ( findFile(rpathBasedPath
, {".tbd"}, result
) )
939 if ( findFile(path
, {".tbd"}, result
) )
943 throwf("file not found: %s", path
.c_str());
946 // search for indirect dylib first using -F and -L paths first
947 Options::FileInfo
Options::findIndirectDylib(const std::string
& installName
, const ld::dylib::File
* fromDylib
) const
951 auto lastSlashPos
= installName
.find_last_of('/');
952 auto pos
= ( lastSlashPos
!= std::string::npos
) ? lastSlashPos
+ 1 : 0;
953 auto leafName
= installName
.substr(pos
);
955 // Is this in a framework?
956 // /path/Foo.framework/Foo ==> true (Foo)
957 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
958 // /path/Foo.framework/Resources/Bar ==> false
959 bool isFramework
= false;
960 if ( lastSlashPos
!= std::string::npos
) {
961 auto frameworkDir
= std::string("/").append(leafName
).append(".framework/");
962 if ( installName
.rfind(frameworkDir
) != std::string::npos
)
966 // These are abbreviated versions of the routines findFramework and findLibrary above
967 // because we already know the final name of the file that we're looking for and so
968 // don't need to try variations, just paths. We do need to add the additional bits
969 // onto the framework path though.
971 auto endPos
= installName
.rfind(".framework");
972 auto beginPos
= installName
.find_last_of('/', endPos
);
973 auto leafPath
= installName
.substr(beginPos
);
974 for (const auto* dir
: fFrameworkSearchPaths
) {
975 auto possiblePath
= dir
+ leafPath
;
976 if ( findFile(possiblePath
, {".tbd"}, result
) )
980 // if this is a .dylib inside a framework, do not search -L paths
981 // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
982 bool embeddedDylib
= ( (leafName
.size() > 6)
983 && (leafName
.find(".dylib", leafName
.size()-6) != std::string::npos
)
984 && (installName
.find(".framework/") != std::string::npos
) );
985 if ( !embeddedDylib
) {
986 for (const auto* dir
: fLibrarySearchPaths
) {
987 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
988 std::string possiblePath
= dir
+ std::string("/") + leafName
;
989 if ( findFile(possiblePath
, {".tbd"}, result
) )
995 // If we didn't find it fall back to findFile.
996 return findFile(installName
, fromDylib
);
1001 void Options::parseSegAddrTable(const char* segAddrPath
, const char* installPth
)
1003 FILE* file
= fopen(segAddrPath
, "r");
1004 if ( file
== NULL
) {
1005 warning("-seg_addr_table file cannot be read: %s", segAddrPath
);
1009 char path
[PATH_MAX
];
1010 uint64_t firstColumAddress
= 0;
1011 uint64_t secondColumAddress
= 0;
1012 bool hasSecondColumn
= false;
1013 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
1014 path
[PATH_MAX
-1] = '\0';
1015 char* eol
= strchr(path
, '\n');
1018 // ignore lines not starting with 0x number
1019 if ( (path
[0] == '0') && (path
[1] == 'x') ) {
1021 firstColumAddress
= strtoull(path
, &p
, 16);
1022 while ( isspace(*p
) )
1024 // see if second column is a number
1025 if ( (p
[0] == '0') && (p
[1] == 'x') ) {
1026 secondColumAddress
= strtoull(p
, &p
, 16);
1027 hasSecondColumn
= true;
1028 while ( isspace(*p
) )
1031 while ( isspace(*p
) )
1033 if ( p
[0] == '/' ) {
1034 // remove any trailing whitespace
1035 for(char* end
= eol
-1; (end
> p
) && isspace(*end
); --end
)
1037 // see if this line is for the dylib being linked
1038 if ( strcmp(p
, installPth
) == 0 ) {
1039 fBaseAddress
= firstColumAddress
;
1040 if ( hasSecondColumn
) {
1041 fBaseWritableAddress
= secondColumAddress
;
1044 break; // out of while loop
1053 void Options::loadFileList(const char* fileOfPaths
, ld::File::Ordinal baseOrdinal
)
1056 const char* comma
= strrchr(fileOfPaths
, ',');
1057 const char* prefix
= NULL
;
1058 if ( comma
!= NULL
) {
1059 // <rdar://problem/5907981> -filelist fails with comma in path
1060 file
= fopen(fileOfPaths
, "r");
1061 if ( file
== NULL
) {
1063 int realFileOfPathsLen
= comma
-fileOfPaths
;
1064 char realFileOfPaths
[realFileOfPathsLen
+1];
1065 strncpy(realFileOfPaths
,fileOfPaths
, realFileOfPathsLen
);
1066 realFileOfPaths
[realFileOfPathsLen
] = '\0';
1067 file
= fopen(realFileOfPaths
, "r");
1069 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", realFileOfPaths
, errno
, strerror(errno
));
1070 if ( this->dumpDependencyInfo() )
1071 this->dumpDependency(Options::depFileList
, realFileOfPaths
);
1075 file
= fopen(fileOfPaths
, "r");
1077 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", fileOfPaths
, errno
, strerror(errno
));
1078 if ( this->dumpDependencyInfo() )
1079 this->dumpDependency(Options::depFileList
, fileOfPaths
);
1082 char path
[PATH_MAX
];
1083 ld::File::Ordinal previousOrdinal
= baseOrdinal
;
1084 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
1085 path
[PATH_MAX
-1] = '\0';
1086 char* eol
= strchr(path
, '\n');
1089 if ( prefix
!= NULL
) {
1090 char builtPath
[strlen(prefix
)+strlen(path
)+2];
1091 strcpy(builtPath
, prefix
);
1092 strcat(builtPath
, "/");
1093 strcat(builtPath
, path
);
1094 if (fPipelineFifo
!= NULL
) {
1095 FileInfo info
= FileInfo(builtPath
);
1096 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1097 previousOrdinal
= info
.ordinal
;
1098 info
.fromFileList
= true;
1099 fInputFiles
.push_back(info
);
1101 FileInfo info
= findFile(builtPath
);
1102 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1103 previousOrdinal
= info
.ordinal
;
1104 info
.fromFileList
= true;
1105 fInputFiles
.push_back(info
);
1109 if (fPipelineFifo
!= NULL
) {
1110 FileInfo info
= FileInfo(path
);
1111 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1112 previousOrdinal
= info
.ordinal
;
1113 info
.fromFileList
= true;
1114 fInputFiles
.push_back(info
);
1116 FileInfo info
= findFile(path
);
1117 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1118 previousOrdinal
= info
.ordinal
;
1119 info
.fromFileList
= true;
1120 fInputFiles
.push_back(info
);
1128 void Options::SetWithWildcards::remove(const NameSet
& toBeRemoved
)
1130 for(NameSet::const_iterator it
=toBeRemoved
.begin(); it
!= toBeRemoved
.end(); ++it
) {
1131 const char* symbolName
= *it
;
1132 NameSet::iterator pos
= fRegular
.find(symbolName
);
1133 if ( pos
!= fRegular
.end() )
1134 fRegular
.erase(pos
);
1138 bool Options::SetWithWildcards::hasWildCards(const char* symbol
)
1140 // an exported symbol name containing *, ?, or [ requires wildcard matching
1141 return ( strpbrk(symbol
, "*?[") != NULL
);
1144 void Options::SetWithWildcards::insert(const char* symbol
)
1146 if ( hasWildCards(symbol
) )
1147 fWildCard
.push_back(symbol
);
1149 fRegular
.insert(symbol
);
1152 bool Options::SetWithWildcards::contains(const char* symbol
, bool* matchBecauseOfWildcard
) const
1154 if ( matchBecauseOfWildcard
!= NULL
)
1155 *matchBecauseOfWildcard
= false;
1156 // first look at hash table on non-wildcard symbols
1157 if ( fRegular
.find(symbol
) != fRegular
.end() )
1159 // next walk list of wild card symbols looking for a match
1160 for(std::vector
<const char*>::const_iterator it
= fWildCard
.begin(); it
!= fWildCard
.end(); ++it
) {
1161 if ( wildCardMatch(*it
, symbol
) ) {
1162 if ( matchBecauseOfWildcard
!= NULL
)
1163 *matchBecauseOfWildcard
= true;
1170 // Support "foo.o:_bar" to mean symbol _bar in file foo.o
1171 bool Options::SetWithWildcards::containsWithPrefix(const char* symbol
, const char* file
, bool& wildCardMatch
) const
1173 wildCardMatch
= false;
1174 if ( contains(symbol
, &wildCardMatch
) )
1178 const char* s
= strrchr(file
, '/');
1181 char buff
[strlen(file
)+strlen(symbol
)+2];
1182 sprintf(buff
, "%s:%s", file
, symbol
);
1183 return contains(buff
, &wildCardMatch
);
1186 bool Options::SetWithWildcards::containsNonWildcard(const char* symbol
) const
1188 // look at hash table on non-wildcard symbols
1189 return ( fRegular
.find(symbol
) != fRegular
.end() );
1193 std::vector
<const char*> Options::exportsData() const
1195 return fExportSymbols
.data();
1199 std::vector
<const char*> Options::SetWithWildcards::data() const
1201 std::vector
<const char*> data
;
1202 for (NameSet::iterator it
=regularBegin(); it
!= regularEnd(); ++it
) {
1203 data
.push_back(*it
);
1205 for (std::vector
<const char*>::const_iterator it
=fWildCard
.begin(); it
!= fWildCard
.end(); ++it
) {
1206 data
.push_back(*it
);
1211 bool Options::SetWithWildcards::inCharRange(const char*& p
, unsigned char c
) const
1215 while ( *p
!= '\0' ) {
1218 // found beginining [ and ending ]
1219 unsigned char last
= '\0';
1220 for ( const char* s
= b
; s
< e
; ++s
) {
1222 unsigned char next
= *(++s
);
1223 if ( (last
<= c
) && (c
<= next
) )
1240 bool Options::SetWithWildcards::wildCardMatch(const char* pattern
, const char* symbol
) const
1242 const char* s
= symbol
;
1243 for (const char* p
= pattern
; *p
!= '\0'; ++p
) {
1248 for (const char* t
= s
; *t
!= '\0'; ++t
) {
1249 if ( wildCardMatch(&p
[1], t
) )
1259 if ( ! inCharRange(p
, *s
) )
1269 return (*s
== '\0');
1273 void Options::loadExportFile(const char* fileOfExports
, const char* option
, SetWithWildcards
& set
)
1275 if ( fileOfExports
== NULL
)
1276 throwf("missing file after %s", option
);
1277 // read in whole file
1278 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
1280 throwf("can't open %s file: %s", option
, fileOfExports
);
1281 struct stat stat_buf
;
1282 ::fstat(fd
, &stat_buf
);
1283 char* p
= (char*)malloc(stat_buf
.st_size
);
1285 throwf("can't process %s file: %s", option
, fileOfExports
);
1287 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1288 throwf("can't read %s file: %s", option
, fileOfExports
);
1290 if ( this->dumpDependencyInfo() )
1291 this->dumpDependency(Options::depMisc
, fileOfExports
);
1295 // parse into symbols and add to unordered_set
1296 char * const end
= &p
[stat_buf
.st_size
];
1297 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1298 char* symbolStart
= NULL
;
1299 for (char* s
= p
; s
< end
; ++s
) {
1305 else if ( !isspace(*s
) ) {
1311 if ( (*s
== '\n') || (*s
== '\r') ) {
1313 // removing any trailing spaces
1315 while ( isspace(*last
) ) {
1319 set
.insert(symbolStart
);
1325 if ( (*s
== '\n') || (*s
== '\r') )
1330 if ( state
== inSymbol
) {
1331 warning("missing line-end at end of file \"%s\"", fileOfExports
);
1332 int len
= end
-symbolStart
+1;
1333 char* temp
= new char[len
];
1334 strlcpy(temp
, symbolStart
, len
);
1336 // remove any trailing spaces
1337 char* last
= &temp
[len
-2];
1338 while ( isspace(*last
) ) {
1345 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
1348 void Options::parseAliasFile(const char* fileOfAliases
)
1350 // read in whole file
1351 int fd
= ::open(fileOfAliases
, O_RDONLY
, 0);
1353 throwf("can't open alias file: %s", fileOfAliases
);
1354 struct stat stat_buf
;
1355 ::fstat(fd
, &stat_buf
);
1356 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1358 throwf("can't process alias file: %s", fileOfAliases
);
1360 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1361 throwf("can't read alias file: %s", fileOfAliases
);
1362 p
[stat_buf
.st_size
] = '\n';
1364 if ( this->dumpDependencyInfo() )
1365 this->dumpDependency(Options::depMisc
, fileOfAliases
);
1367 // parse into symbols and add to fAliases
1369 char * const end
= &p
[stat_buf
.st_size
+1];
1370 enum { lineStart
, inRealName
, inBetween
, inAliasName
, inComment
} state
= lineStart
;
1372 for (char* s
= p
; s
< end
; ++s
) {
1378 else if ( !isspace(*s
) ) {
1385 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1389 else if ( isspace(*s
) ) {
1396 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1400 else if ( ! isspace(*s
) ) {
1401 state
= inAliasName
;
1408 // removing any trailing spaces
1410 while ( isspace(*last
) ) {
1414 fAliases
.push_back(pair
);
1417 else if ( *s
== '\n' ) {
1419 // removing any trailing spaces
1421 while ( isspace(*last
) ) {
1425 fAliases
.push_back(pair
);
1436 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
1441 void Options::setUndefinedTreatment(const char* treatment
)
1443 if ( treatment
== NULL
)
1444 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
1446 if ( strcmp(treatment
, "warning") == 0 )
1447 fUndefinedTreatment
= kUndefinedWarning
;
1448 else if ( strcmp(treatment
, "error") == 0 )
1449 fUndefinedTreatment
= kUndefinedError
;
1450 else if ( strcmp(treatment
, "suppress") == 0 )
1451 fUndefinedTreatment
= kUndefinedSuppress
;
1452 else if ( strcmp(treatment
, "dynamic_lookup") == 0 )
1453 fUndefinedTreatment
= kUndefinedDynamicLookup
;
1455 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1458 Options::Treatment
Options::parseTreatment(const char* treatment
)
1460 if ( treatment
== NULL
)
1463 if ( strcmp(treatment
, "warning") == 0 )
1465 else if ( strcmp(treatment
, "error") == 0 )
1467 else if ( strcmp(treatment
, "suppress") == 0 )
1473 void Options::setMacOSXVersionMin(const char* version
)
1476 if ( !parsePackedVersion32(version
, value
) ) {
1477 throwf("-macosx_version_min value malformed: '%s'", version
);
1479 fMacVersionMin
= (ld::MacVersionMin
)value
;
1480 fPlatform
= kPlatformOSX
;
1483 void Options::setIOSVersionMin(const char* version
)
1486 if ( !parsePackedVersion32(version
, value
) ) {
1487 throwf("-ios_version_min value malformed: '%s'", version
);
1489 fIOSVersionMin
= (ld::IOSVersionMin
)value
;
1490 fPlatform
= kPlatformiOS
;
1494 void Options::setWatchOSVersionMin(const char* version
)
1497 if ( !parsePackedVersion32(version
, value
) ) {
1498 throwf("-watchos_version_min value malformed: '%s'", version
);
1500 fWatchOSVersionMin
= (ld::WatchOSVersionMin
)value
;
1501 fPlatform
= kPlatformWatchOS
;
1505 bool Options::minOS(ld::MacVersionMin requiredMacMin
, ld::IOSVersionMin requirediPhoneOSMin
)
1507 if ( fMacVersionMin
!= ld::macVersionUnset
) {
1508 return ( fMacVersionMin
>= requiredMacMin
);
1511 return min_iOS(requirediPhoneOSMin
);
1515 bool Options::min_iOS(ld::IOSVersionMin requirediOSMin
)
1517 if ( fWatchOSVersionMin
!= ld::wOSVersionUnset
) {
1518 // Hack until we fully track watch and ios versions seperately
1519 return ( (fWatchOSVersionMin
+ 0x00070000) >= requirediOSMin
);
1521 else if ( fPlatform
== Options::kPlatform_bridgeOS
) {
1522 // Hack until we fully track bridge and ios versions seperately
1523 return ( (fIOSVersionMin
+ 0x00090000) >= requirediOSMin
);
1526 return ( fIOSVersionMin
>= requirediOSMin
);
1530 void Options::setWeakReferenceMismatchTreatment(const char* treatment
)
1532 if ( treatment
== NULL
)
1533 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1535 if ( strcmp(treatment
, "error") == 0 )
1536 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchError
;
1537 else if ( strcmp(treatment
, "weak") == 0 )
1538 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchWeak
;
1539 else if ( strcmp(treatment
, "non-weak") == 0 )
1540 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchNonWeak
;
1542 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1545 Options::CommonsMode
Options::parseCommonsTreatment(const char* mode
)
1548 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1550 if ( strcmp(mode
, "ignore_dylibs") == 0 )
1551 return kCommonsIgnoreDylibs
;
1552 else if ( strcmp(mode
, "use_dylibs") == 0 )
1553 return kCommonsOverriddenByDylibs
;
1554 else if ( strcmp(mode
, "error") == 0 )
1555 return kCommonsConflictsDylibsError
;
1557 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1560 void Options::addDylibOverride(const char* paths
)
1562 if ( paths
== NULL
)
1563 throw "-dylib_file must followed by two colon separated paths";
1564 const char* colon
= strchr(paths
, ':');
1565 if ( colon
== NULL
)
1566 throw "-dylib_file must followed by two colon separated paths";
1567 int len
= colon
-paths
;
1568 char* target
= new char[len
+2];
1569 strncpy(target
, paths
, len
);
1571 DylibOverride entry
;
1572 entry
.installName
= target
;
1573 entry
.useInstead
= &colon
[1];
1574 fDylibOverrides
.push_back(entry
);
1577 uint64_t Options::parseAddress(const char* addr
)
1580 uint64_t result
= strtoull(addr
, &endptr
, 16);
1584 uint32_t Options::parseProtection(const char* prot
)
1586 uint32_t result
= 0;
1587 for(const char* p
= prot
; *p
!= '\0'; ++p
) {
1588 switch(tolower(*p
)) {
1590 result
|= VM_PROT_READ
;
1593 result
|= VM_PROT_WRITE
;
1596 result
|= VM_PROT_EXECUTE
;
1601 throwf("unknown -segprot lettter in %s", prot
);
1609 // Parses number of form A[.B[.B[.D[.E]]]] into a uint64_t where the bits are a24.b10.c10.d10.e10
1611 uint64_t Options::parseVersionNumber64(const char* versionString
)
1619 a
= strtoul(versionString
, &end
, 10);
1620 if ( *end
== '.' ) {
1621 b
= strtoul(&end
[1], &end
, 10);
1622 if ( *end
== '.' ) {
1623 c
= strtoul(&end
[1], &end
, 10);
1624 if ( *end
== '.' ) {
1625 d
= strtoul(&end
[1], &end
, 10);
1626 if ( *end
== '.' ) {
1627 e
= strtoul(&end
[1], &end
, 10);
1632 if ( (*end
!= '\0') || (a
> 0xFFFFFF) || (b
> 0x3FF) || (c
> 0x3FF) || (d
> 0x3FF) || (e
> 0x3FF) )
1633 throwf("malformed 64-bit a.b.c.d.e version number: %s", versionString
);
1635 return (a
<< 40) | ( b
<< 30 ) | ( c
<< 20 ) | ( d
<< 10 ) | e
;
1639 uint32_t Options::currentVersion32() const
1641 // warn if it does not fit into 32 bit vers number
1642 uint32_t a
= (fDylibCurrentVersion
>> 40) & 0xFFFF;
1643 uint32_t b
= (fDylibCurrentVersion
>> 30) & 0xFF;
1644 uint32_t c
= (fDylibCurrentVersion
>> 20) & 0xFF;
1645 uint64_t rep32
= ((uint64_t)a
<< 40) | ((uint64_t)b
<< 30) | ((uint64_t)c
<< 20);
1646 if ( rep32
!= fDylibCurrentVersion
) {
1647 warning("truncating -current_version to fit in 32-bit space used by old mach-o format");
1648 a
= (fDylibCurrentVersion
>> 40) & 0xFFFFFF;
1651 b
= (fDylibCurrentVersion
>> 30) & 0x3FF;
1654 c
= (fDylibCurrentVersion
>> 20) & 0x3FF;
1658 return (a
<< 16) | ( b
<< 8 ) | c
;
1662 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1664 uint32_t Options::parseVersionNumber32(const char* versionString
)
1670 x
= strtoul(versionString
, &end
, 10);
1671 if ( *end
== '.' ) {
1672 y
= strtoul(&end
[1], &end
, 10);
1673 if ( *end
== '.' ) {
1674 z
= strtoul(&end
[1], &end
, 10);
1677 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
1678 throwf("malformed 32-bit x.y.z version number: %s", versionString
);
1680 return (x
<< 16) | ( y
<< 8 ) | z
;
1683 static const char* cstringSymbolName(const char* orderFileString
)
1686 asprintf(&result
, "cstring=%s", orderFileString
);
1687 // convert escaped characters
1689 for(const char* s
=result
; *s
!= '\0'; ++s
, ++d
) {
1727 // hexadecimal value of char
1731 while ( isxdigit(*s
) ) {
1736 value
+= ((toupper(*s
)-'A') + 10);
1743 if ( isdigit(*s
) ) {
1744 // octal value of char
1746 while ( isdigit(*s
) ) {
1747 value
= (value
<< 3) + (*s
-'0');
1762 void Options::parseOrderFile(const char* path
, bool cstring
)
1764 // order files override auto-ordering
1765 fAutoOrderInitializers
= false;
1767 // <rdar://problem/24856050> ld64 should prefer OrderFiles from the SDK over the ones in /
1768 for (const char* sdkPath
: fSDKPaths
) {
1769 char fullPath
[PATH_MAX
];
1770 strlcpy(fullPath
, sdkPath
, PATH_MAX
);
1771 strlcat(fullPath
, "/", PATH_MAX
);
1772 strlcat(fullPath
, path
, PATH_MAX
);
1773 struct stat statBuffer
;
1774 if ( stat(fullPath
, &statBuffer
) == 0 ) {
1775 path
= strdup(fullPath
);
1780 // read in whole file
1781 int fd
= ::open(path
, O_RDONLY
, 0);
1783 throwf("can't open order file: %s", path
);
1784 struct stat stat_buf
;
1785 ::fstat(fd
, &stat_buf
);
1786 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1788 throwf("can't process order file: %s", path
);
1789 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1790 throwf("can't read order file: %s", path
);
1792 p
[stat_buf
.st_size
] = '\n';
1793 if ( this->dumpDependencyInfo() )
1794 this->dumpDependency(Options::depMisc
, path
);
1796 // parse into vector of pairs
1797 char * const end
= &p
[stat_buf
.st_size
+1];
1798 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1799 char* symbolStart
= NULL
;
1800 for (char* s
= p
; s
< end
; ++s
) {
1806 else if ( !isspace(*s
) || cstring
) {
1812 if ( (*s
== '\n') || (!cstring
&& (*s
== '#')) ) {
1813 bool wasComment
= (*s
== '#');
1815 // removing any trailing spaces
1817 while ( isspace(*last
) ) {
1821 // if there is an architecture prefix, only use this symbol it if matches current arch
1822 if ( strncmp(symbolStart
, "ppc:", 4) == 0 ) {
1825 else if ( strncmp(symbolStart
, "ppc64:", 6) == 0 ) {
1828 else if ( strncmp(symbolStart
, "i386:", 5) == 0 ) {
1829 if ( fArchitecture
== CPU_TYPE_I386
)
1830 symbolStart
= &symbolStart
[5];
1834 else if ( strncmp(symbolStart
, "x86_64:", 7) == 0 ) {
1835 if ( fArchitecture
== CPU_TYPE_X86_64
)
1836 symbolStart
= &symbolStart
[7];
1840 else if ( strncmp(symbolStart
, "arm:", 4) == 0 ) {
1841 if ( fArchitecture
== CPU_TYPE_ARM
)
1842 symbolStart
= &symbolStart
[4];
1846 else if ( strncmp(symbolStart
, "arm64:", 6) == 0 ) {
1847 if ( fArchitecture
== CPU_TYPE_ARM64
)
1848 symbolStart
= &symbolStart
[6];
1852 if ( symbolStart
!= NULL
) {
1853 char* objFileName
= NULL
;
1854 char* colon
= strstr(symbolStart
, ".o:");
1855 if ( colon
!= NULL
) {
1857 objFileName
= symbolStart
;
1858 symbolStart
= &colon
[3];
1861 colon
= strstr(symbolStart
, ".o):");
1862 if ( colon
!= NULL
) {
1864 objFileName
= symbolStart
;
1865 symbolStart
= &colon
[4];
1868 // trim leading spaces
1869 while ( isspace(*symbolStart
) )
1871 Options::OrderedSymbol pair
;
1873 pair
.symbolName
= cstringSymbolName(symbolStart
);
1875 pair
.symbolName
= symbolStart
;
1876 pair
.objectFileName
= objFileName
;
1877 fOrderedSymbols
.push_back(pair
);
1892 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1895 void Options::parseSectionOrderFile(const char* segment
, const char* section
, const char* path
)
1897 if ( (strcmp(section
, "__cstring") == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1898 parseOrderFile(path
, true);
1900 else if ( (strncmp(section
, "__literal",9) == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1901 warning("sorting of __literal[4,8,16] sections not supported");
1904 // ignore section information and append all symbol names to global order file
1905 parseOrderFile(path
, false);
1909 void Options::addSection(const char* segment
, const char* section
, const char* path
)
1911 if ( strlen(segment
) > 16 )
1912 throw "-seccreate segment name max 16 chars";
1913 if ( strlen(section
) > 16 ) {
1914 char* tmp
= strdup(section
);
1916 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section
, tmp
);
1920 // read in whole file
1921 int fd
= ::open(path
, O_RDONLY
, 0);
1923 throwf("can't open -sectcreate file: %s", path
);
1924 struct stat stat_buf
;
1925 ::fstat(fd
, &stat_buf
);
1926 char* p
= (char*)malloc(stat_buf
.st_size
);
1928 throwf("can't process -sectcreate file: %s", path
);
1929 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1930 throwf("can't read -sectcreate file: %s", path
);
1933 // record section to create
1934 ExtraSection info
= { segment
, section
, path
, (uint8_t*)p
, (uint64_t)stat_buf
.st_size
};
1935 fExtraSections
.push_back(info
);
1938 void Options::addSectionRename(const char* srcSegment
, const char* srcSection
, const char* dstSegment
, const char* dstSection
)
1940 if ( strlen(srcSegment
) > 16 )
1941 throw "-rename_section segment name max 16 chars";
1942 if ( strlen(srcSection
) > 16 )
1943 throw "-rename_section section name max 16 chars";
1944 if ( strlen(dstSegment
) > 16 )
1945 throw "-rename_section segment name max 16 chars";
1946 if ( strlen(dstSection
) > 16 )
1947 throw "-rename_section section name max 16 chars";
1950 info
.fromSegment
= srcSegment
;
1951 info
.fromSection
= srcSection
;
1952 info
.toSegment
= dstSegment
;
1953 info
.toSection
= dstSection
;
1955 fSectionRenames
.push_back(info
);
1959 void Options::addSegmentRename(const char* srcSegment
, const char* dstSegment
)
1961 if ( strlen(srcSegment
) > 16 )
1962 throw "-rename_segment segment name max 16 chars";
1963 if ( strlen(dstSegment
) > 16 )
1964 throw "-rename_segment segment name max 16 chars";
1967 info
.fromSegment
= srcSegment
;
1968 info
.toSegment
= dstSegment
;
1970 fSegmentRenames
.push_back(info
);
1975 void Options::addSymbolMove(const char* dstSegment
, const char* symbolList
,
1976 std::vector
<SymbolsMove
>& list
, const char* optionName
)
1978 if ( strlen(dstSegment
) > 16 )
1979 throwf("%s segment name max 16 chars", optionName
);
1982 list
.push_back(tmp
);
1983 SymbolsMove
& info
= list
.back();
1984 info
.toSegment
= dstSegment
;
1985 loadExportFile(symbolList
, optionName
, info
.symbols
);
1988 bool Options::moveRwSymbol(const char* symName
, const char* filePath
, const char*& seg
, bool& wildCardMatch
) const
1990 for (std::vector
<SymbolsMove
>::const_iterator it
=fSymbolsMovesData
.begin(); it
!= fSymbolsMovesData
.end(); ++it
) {
1991 const SymbolsMove
& info
= *it
;
1992 if ( info
.symbols
.containsWithPrefix(symName
, filePath
, wildCardMatch
)) {
1993 seg
= info
.toSegment
;
2000 bool Options::moveRoSymbol(const char* symName
, const char* filePath
, const char*& seg
, bool& wildCardMatch
) const
2002 for (std::vector
<SymbolsMove
>::const_iterator it
=fSymbolsMovesCode
.begin(); it
!= fSymbolsMovesCode
.end(); ++it
) {
2003 const SymbolsMove
& info
= *it
;
2004 if ( info
.symbols
.containsWithPrefix(symName
, filePath
, wildCardMatch
)) {
2005 seg
= info
.toSegment
;
2012 void Options::addSectionAlignment(const char* segment
, const char* section
, const char* alignmentStr
)
2014 if ( strlen(segment
) > 16 )
2015 throw "-sectalign segment name max 16 chars";
2016 if ( strlen(section
) > 16 )
2017 throw "-sectalign section name max 16 chars";
2019 // argument to -sectalign is a hexadecimal number
2021 unsigned long value
= strtoul(alignmentStr
, &endptr
, 16);
2022 if ( *endptr
!= '\0')
2023 throw "argument for -sectalign is not a hexadecimal number";
2024 if ( value
> 0x8000 )
2025 throw "argument for -sectalign must be less than or equal to 0x8000";
2027 warning("zero is not a valid -sectalign");
2031 // alignment is power of 2 (e.g. page alignment = 12)
2032 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
2033 if ( (unsigned long)(1 << alignment
) != value
) {
2034 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
2035 segment
, section
, 1 << alignment
);
2038 SectionAlignment info
= { segment
, section
, alignment
};
2039 fSectionAlignments
.push_back(info
);
2042 void Options::addLibrary(const FileInfo
& info
)
2044 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
2045 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
2046 if ( strcmp(info
.path
, fit
->path
) == 0 ) {
2047 // if dylib is specified again but weak, record that it should be weak
2048 if ( info
.options
.fWeakImport
)
2049 fit
->options
.fWeakImport
= true;
2054 fInputFiles
.push_back(info
);
2057 void Options::warnObsolete(const char* arg
)
2059 warning("option %s is obsolete and being ignored", arg
);
2063 void Options::cannotBeUsedWithBitcode(const char* arg
)
2065 if ( fBundleBitcode
)
2066 throwf("%s and -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES) cannot be used together", arg
);
2069 std::string
Options::getVersionString32(uint32_t ver
) const
2071 if (ver
== 0 || ver
>= 0x10000000)
2074 unsigned microVersion
= ver
& 0xFF;
2075 unsigned minorVersion
= (ver
>> 8) & 0xFF;
2076 unsigned majorVersion
= (ver
>> 16) & 0xFF;
2077 std::stringstream versionString
;
2078 versionString
<< majorVersion
<< "." << minorVersion
<< "." << microVersion
;
2079 return versionString
.str();
2082 std::string
Options::getVersionString64(uint64_t ver
) const
2084 uint64_t a
= (ver
>> 40) & 0xFFFFFF;
2085 uint64_t b
= (ver
>> 30) & 0x3FF;
2086 uint64_t c
= (ver
>> 20) & 0x3FF;
2087 uint64_t d
= (ver
>> 10) & 0x3FF;
2088 uint64_t e
= ver
& 0x3FF;
2089 std::stringstream versionString
;
2090 versionString
<< a
<< "." << b
<< "." << c
<< "." << d
<< "." << e
;
2091 return versionString
.str();
2094 // Convert X.Y[.Z] to 32-bit value xxxxyyzz
2095 bool Options::parsePackedVersion32(const std::string
& versionStr
, uint32_t &result
)
2099 if ( versionStr
.empty() )
2102 size_t pos
= versionStr
.find('.');
2103 if ( pos
== std::string::npos
)
2106 std::string majorStr
= versionStr
.substr(0, pos
);
2107 std::string rest
= versionStr
.substr(pos
+1);
2111 int majorValue
= std::stoi(majorStr
, &majorEnd
);
2112 if ( majorEnd
!= majorStr
.size() )
2114 if ( majorValue
< 0 )
2116 if ( majorValue
> 65535 )
2119 std::string minorStr
;
2120 std::string microStr
;
2121 pos
= rest
.find('.');
2122 if ( pos
== std::string::npos
) {
2126 minorStr
= rest
.substr(0, pos
);
2127 microStr
= rest
.substr(pos
+1);
2131 int minorValue
= std::stoi(minorStr
, &minorEnd
);
2132 if ( minorEnd
!= minorStr
.size() )
2134 if ( minorValue
< 0 )
2136 if ( minorValue
> 255 )
2140 if ( !microStr
.empty() ) {
2142 microValue
= std::stoi(microStr
, µEnd
);
2143 if ( microEnd
!= microStr
.size() )
2145 if ( microValue
< 0 )
2147 if ( microValue
> 255 )
2151 result
= (majorValue
<< 16) | (minorValue
<< 8) | microValue
;
2156 // std::stoi() throws exception on malformed input
2161 std::string
Options::getSDKVersionStr() const
2163 return getVersionString32(fSDKVersion
);
2166 std::string
Options::getPlatformStr() const
2168 switch (fPlatform
) {
2169 case Options::kPlatformOSX
:
2171 case Options::kPlatformiOS
:
2172 if (targetIOSSimulator())
2173 return "iPhoneSimulator";
2176 case Options::kPlatformWatchOS
:
2177 if (targetIOSSimulator())
2178 return "watchOS Simulator";
2181 #if SUPPORT_APPLE_TV
2182 case Options::kPlatform_tvOS
:
2183 if (targetIOSSimulator())
2184 return "AppleTVSimulator";
2189 case Options::kPlatform_bridgeOS
:
2191 case Options::kPlatformUnknown
:
2196 std::vector
<std::string
> Options::writeBitcodeLinkOptions() const
2198 std::vector
<std::string
> linkCommand
;
2199 switch ( fOutputKind
) {
2200 case Options::kDynamicLibrary
:
2201 linkCommand
.push_back("-dylib");
2202 linkCommand
.push_back("-compatibility_version");
2203 if ( fDylibCompatVersion
!= 0 ) {
2204 linkCommand
.push_back(getVersionString32(fDylibCompatVersion
));
2206 linkCommand
.push_back(getVersionString32(currentVersion32()));
2208 if ( fDylibCurrentVersion
!= 0 ) {
2209 linkCommand
.push_back("-current_version");
2210 linkCommand
.push_back(getVersionString64(fDylibCurrentVersion
));
2212 linkCommand
.push_back("-install_name");
2213 linkCommand
.push_back(installPath());
2215 case Options::kDynamicExecutable
:
2216 linkCommand
.push_back("-execute");
2218 case Options::kObjectFile
:
2219 linkCommand
.push_back("-r");
2222 throwf("could not write bitcode options file output kind\n");
2225 if (!fImplicitlyLinkPublicDylibs
)
2226 linkCommand
.push_back("-no_implicit_dylibs");
2228 // Add deployment target.
2229 // Platform is allowed to be unknown for "ld -r".
2230 switch (fPlatform
) {
2231 case Options::kPlatformOSX
:
2232 linkCommand
.push_back("-macosx_version_min");
2233 linkCommand
.push_back(getVersionString32((unsigned)fMacVersionMin
));
2235 case Options::kPlatformiOS
:
2236 if (targetIOSSimulator())
2237 linkCommand
.push_back("-ios_simulator_version_min");
2239 linkCommand
.push_back("-ios_version_min");
2240 linkCommand
.push_back(getVersionString32((unsigned)fIOSVersionMin
));
2242 case Options::kPlatformWatchOS
:
2243 if (targetIOSSimulator())
2244 linkCommand
.push_back("-watchos_simulator_version_min");
2246 linkCommand
.push_back("-watchos_version_min");
2247 linkCommand
.push_back(getVersionString32((unsigned)fIOSVersionMin
));
2249 #if SUPPORT_APPLE_TV
2250 case Options::kPlatform_tvOS
:
2251 if (targetIOSSimulator())
2252 linkCommand
.push_back("-tvos_simulator_version_min");
2254 linkCommand
.push_back("-tvos_version_min");
2255 linkCommand
.push_back(getVersionString32((unsigned)fIOSVersionMin
));
2258 case Options::kPlatform_bridgeOS
:
2259 linkCommand
.push_back("-bridgeos_version_min");
2260 linkCommand
.push_back(getVersionString32((unsigned)fIOSVersionMin
));
2262 case Options::kPlatformUnknown
:
2263 if ( fOutputKind
!= Options::kObjectFile
) {
2264 throwf("platform is unknown for final bitcode bundle,"
2265 "deployment target and min version is required for -bitcode_bundle");
2273 linkCommand
.push_back("-e");
2274 linkCommand
.push_back(fEntryName
);
2278 if (!fRPaths
.empty()) {
2279 for (std::vector
<const char*>::const_iterator it
=fRPaths
.begin(); it
!= fRPaths
.end(); ++it
) {
2280 linkCommand
.push_back("-rpath");
2281 linkCommand
.push_back(*it
);
2285 // Other bitcode compatiable options
2286 if ( fObjCABIVersion1Override
) {
2287 linkCommand
.push_back("-objc_abi_version");
2288 linkCommand
.push_back("1");
2289 } else if ( fObjCABIVersion2Override
) {
2290 linkCommand
.push_back("-objc_abi_version");
2291 linkCommand
.push_back("2");
2293 if ( fExecutablePath
) {
2294 linkCommand
.push_back("-executable_path");
2295 linkCommand
.push_back(fExecutablePath
);
2298 linkCommand
.push_back("-dead_strip");
2299 if ( fExportDynamic
)
2300 linkCommand
.push_back("-export_dynamic");
2301 if ( fMarkAppExtensionSafe
&& fCheckAppExtensionSafe
)
2302 linkCommand
.push_back("-application_extension");
2304 if ( fSourceVersionLoadCommandForceOn
)
2305 linkCommand
.push_back("-add_source_version");
2306 if ( fSourceVersion
!= 0 ) {
2307 linkCommand
.push_back("-source_version");
2308 linkCommand
.push_back(getVersionString64(fSourceVersion
));
2311 // linker flag added by swift driver
2312 // rdar://problem/20108072
2313 if ( !fObjcCategoryMerging
)
2314 linkCommand
.push_back("-no_objc_category_merging");
2320 // Process all command line arguments.
2322 // The only error checking done here is that each option is valid and if it has arguments
2323 // that they too are valid.
2325 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
2326 // whichever was last on the command line is used.
2328 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
2330 void Options::parse(int argc
, const char* argv
[])
2332 // Store the original args in the link snapshot.
2333 fLinkSnapshot
.recordRawArgs(argc
, argv
);
2335 // pass one builds search list from -L and -F options
2336 this->buildSearchPaths(argc
, argv
);
2338 // reduce re-allocations
2339 fInputFiles
.reserve(32);
2341 // pass two parse all other options
2342 for(int i
=1; i
< argc
; ++i
) {
2343 const char* arg
= argv
[i
];
2345 if ( arg
[0] == '-' ) {
2346 // by default, copy one arg to the snapshot link command, and do no file copying
2347 int snapshotArgIndex
= i
;
2348 int snapshotArgCount
= -1; // -1 means compute count based on change in index
2349 int snapshotFileArgIndex
= -1; // -1 means no data file parameter to arg
2351 // Since we don't care about the files passed, just the option names, we do this here.
2353 fprintf (stderr
, "[Logging ld64 options]\t%s\n", arg
);
2355 if ( (arg
[1] == 'L') || (arg
[1] == 'F') ) {
2356 snapshotArgCount
= 0; // stripped out of link snapshot
2359 // previously handled by buildSearchPaths()
2361 // The one gnu style option we have to keep compatibility
2362 // with gcc. Might as well have the single hyphen one as well.
2363 else if ( (strcmp(arg
, "--help") == 0)
2364 || (strcmp(arg
, "-help") == 0)) {
2365 fprintf (stdout
, "ld64: For information on command line options please use 'man ld'.\n");
2368 else if ( strcmp(arg
, "-arch") == 0 ) {
2369 parseArch(argv
[++i
]);
2371 else if ( strcmp(arg
, "-dynamic") == 0 ) {
2374 else if ( strcmp(arg
, "-static") == 0 ) {
2376 if ( (fOutputKind
!= kObjectFile
) && (fOutputKind
!= kKextBundle
) ) {
2377 fOutputKind
= kStaticExecutable
;
2379 cannotBeUsedWithBitcode(arg
);
2381 else if ( strcmp(arg
, "-dylib") == 0 ) {
2382 fOutputKind
= kDynamicLibrary
;
2384 else if ( strcmp(arg
, "-bundle") == 0 ) {
2385 fOutputKind
= kDynamicBundle
;
2386 cannotBeUsedWithBitcode(arg
);
2388 else if ( strcmp(arg
, "-dylinker") == 0 ) {
2389 fOutputKind
= kDyld
;
2390 cannotBeUsedWithBitcode(arg
);
2392 else if ( strcmp(arg
, "-execute") == 0 ) {
2393 if ( fOutputKind
!= kStaticExecutable
)
2394 fOutputKind
= kDynamicExecutable
;
2396 else if ( strcmp(arg
, "-preload") == 0 ) {
2397 fOutputKind
= kPreload
;
2398 cannotBeUsedWithBitcode(arg
);
2400 else if ( strcmp(arg
, "-r") == 0 ) {
2401 fOutputKind
= kObjectFile
;
2403 else if ( strcmp(arg
, "-kext") == 0 ) {
2404 fOutputKind
= kKextBundle
;
2405 cannotBeUsedWithBitcode(arg
);
2407 else if ( strcmp(arg
, "-o") == 0 ) {
2408 snapshotArgCount
= 0;
2409 fOutputFile
= argv
[++i
];
2410 fLinkSnapshot
.setSnapshotName(fOutputFile
);
2412 else if ( strncmp(arg
, "-lazy-l", 7) == 0 ) {
2413 snapshotArgCount
= 0;
2414 FileInfo info
= findLibrary(&arg
[7], true);
2415 info
.options
.fLazyLoad
= true;
2416 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2418 fUsingLazyDylibLinking
= true;
2419 cannotBeUsedWithBitcode(arg
);
2421 else if ( strcmp(arg
, "-lto_library") == 0 ) {
2422 snapshotFileArgIndex
= 1;
2423 fOverridePathlibLTO
= argv
[++i
];
2424 if ( fOverridePathlibLTO
== NULL
)
2425 throw "missing argument to -lto_library";
2427 else if ( strcmp(arg
, "-cache_path_lto") == 0 ) {
2428 fLtoCachePath
= argv
[++i
];
2429 if ( fLtoCachePath
== NULL
)
2430 throw "missing argument to -cache_path_lto";
2432 else if ( strcmp(arg
, "-prune_interval_lto") == 0 ) {
2433 const char* value
= argv
[++i
];
2434 if ( value
== NULL
)
2435 throw "missing argument to -prune_interval_lto";
2437 fLtoPruneInterval
= strtoul(value
, &endptr
, 10);
2438 if ( *endptr
!= '\0')
2439 throw "invalid argument for -prune_interval_lto";
2441 else if ( strcmp(arg
, "-prune_after_lto") == 0 ) {
2442 const char* value
= argv
[++i
];
2443 if ( value
== NULL
)
2444 throw "missing argument to -prune_after_lto";
2446 fLtoPruneAfter
= strtoul(value
, &endptr
, 10);
2447 if ( *endptr
!= '\0')
2448 throw "invalid argument for -prune_after_lto";
2450 else if ( strcmp(arg
, "-max_relative_cache_size_lto") == 0 ) {
2451 const char* value
= argv
[++i
];
2452 if ( value
== NULL
)
2453 throw "missing argument to -max_relative_cache_size_lto";
2455 fLtoMaxCacheSize
= strtoul(value
, &endptr
, 10);
2456 if ( *endptr
!= '\0')
2457 throw "invalid argument for -max_relative_cache_size_lto";
2458 if (fLtoMaxCacheSize
> 100)
2459 throw "Expect a value between 0 and 100 for -max_relative_cache_size_lto";
2461 else if ( (arg
[1] == 'l') && (strncmp(arg
,"-lazy_",6) !=0) ) {
2462 snapshotArgCount
= 0;
2463 FileInfo info
= findLibrary(&arg
[2]);
2464 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2467 // This causes a dylib to be weakly bound at
2468 // link time. This corresponds to weak_import.
2469 else if ( strncmp(arg
, "-weak-l", 7) == 0 ) {
2470 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2471 snapshotArgCount
= 0;
2472 FileInfo info
= findLibrary(&arg
[7]);
2473 info
.options
.fWeakImport
= true;
2474 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2477 // Avoid lazy binding.
2478 else if ( strcmp(arg
, "-bind_at_load") == 0 ) {
2480 cannotBeUsedWithBitcode(arg
);
2482 else if ( strcmp(arg
, "-twolevel_namespace") == 0 ) {
2483 fNameSpace
= kTwoLevelNameSpace
;
2485 else if ( strcmp(arg
, "-flat_namespace") == 0 ) {
2486 fNameSpace
= kFlatNameSpace
;
2487 cannotBeUsedWithBitcode(arg
);
2489 // Also sets a bit to ensure dyld causes everything
2490 // in the namespace to be flat.
2492 else if ( strcmp(arg
, "-force_flat_namespace") == 0 ) {
2493 fNameSpace
= kForceFlatNameSpace
;
2494 cannotBeUsedWithBitcode(arg
);
2496 // Similar to --whole-archive.
2497 else if ( strcmp(arg
, "-all_load") == 0 ) {
2498 fFullyLoadArchives
= true;
2500 else if ( strcmp(arg
, "-noall_load") == 0) {
2503 // Similar to -all_load
2504 else if ( strcmp(arg
, "-ObjC") == 0 ) {
2505 fLoadAllObjcObjectsFromArchives
= true;
2507 // Similar to -all_load, but for the following archive only.
2508 else if ( strcmp(arg
, "-force_load") == 0 ) {
2509 FileInfo info
= findFile(argv
[++i
]);
2510 info
.options
.fForceLoad
= true;
2511 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2514 // Library versioning.
2515 else if ( (strcmp(arg
, "-dylib_compatibility_version") == 0)
2516 || (strcmp(arg
, "-compatibility_version") == 0)) {
2517 const char* vers
= argv
[++i
];
2519 throw "-dylib_compatibility_version missing <version>";
2520 fDylibCompatVersion
= parseVersionNumber32(vers
);
2522 else if ( (strcmp(arg
, "-dylib_current_version") == 0)
2523 || (strcmp(arg
, "-current_version") == 0)) {
2524 const char* vers
= argv
[++i
];
2526 throw "-dylib_current_version missing <version>";
2527 fDylibCurrentVersion
= parseVersionNumber64(vers
);
2529 else if ( strcmp(arg
, "-sectorder") == 0 ) {
2530 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2531 throw "-sectorder missing <segment> <section> <file-path>";
2532 snapshotFileArgIndex
= 3;
2533 parseSectionOrderFile(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2535 cannotBeUsedWithBitcode(arg
);
2537 else if ( strcmp(arg
, "-order_file") == 0 ) {
2538 snapshotFileArgIndex
= 1;
2539 parseOrderFile(argv
[++i
], false);
2541 else if ( strcmp(arg
, "-order_file_statistics") == 0 ) {
2542 fPrintOrderFileStatistics
= true;
2543 cannotBeUsedWithBitcode(arg
);
2545 // ??? Deprecate segcreate.
2546 // -sectcreate puts whole files into a section in the output.
2547 else if ( (strcmp(arg
, "-sectcreate") == 0) || (strcmp(arg
, "-segcreate") == 0) ) {
2548 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2549 throw "-sectcreate missing <segment> <section> <file-path>";
2550 snapshotFileArgIndex
= 3;
2551 addSection(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2554 // Since we have a full path in binary/library names we need to be able to override it.
2555 else if ( (strcmp(arg
, "-dylib_install_name") == 0)
2556 || (strcmp(arg
, "-dylinker_install_name") == 0)
2557 || (strcmp(arg
, "-install_name") == 0)) {
2558 fDylibInstallName
= argv
[++i
];
2559 if ( fDylibInstallName
== NULL
)
2560 throw "-install_name missing <path>";
2562 // Sets the base address of the output.
2563 else if ( (strcmp(arg
, "-seg1addr") == 0) || (strcmp(arg
, "-image_base") == 0) ) {
2564 const char* address
= argv
[++i
];
2565 if ( address
== NULL
)
2566 throwf("%s missing <address>", arg
);
2567 fBaseAddress
= parseAddress(address
);
2568 uint64_t temp
= ((fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
2569 if ( fBaseAddress
!= temp
) {
2570 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment
);
2571 fBaseAddress
= temp
;
2573 cannotBeUsedWithBitcode(arg
);
2575 else if ( strcmp(arg
, "-e") == 0 ) {
2576 fEntryName
= argv
[++i
];
2578 // Same as -@ from the FSF linker.
2579 else if ( strcmp(arg
, "-filelist") == 0 ) {
2580 snapshotArgCount
= 0;
2581 const char* path
= argv
[++i
];
2582 if ( (path
== NULL
) || (path
[0] == '-') )
2583 throw "-filelist missing <path>";
2584 ld::File::Ordinal baseOrdinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2585 loadFileList(path
, baseOrdinal
);
2587 else if ( strcmp(arg
, "-keep_private_externs") == 0 ) {
2588 cannotBeUsedWithBitcode(arg
);
2589 fKeepPrivateExterns
= true;
2591 else if ( strcmp(arg
, "-final_output") == 0 ) {
2592 fFinalName
= argv
[++i
];
2594 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
2595 // just ensures that this happens for cross object file boundaries.
2596 else if ( (strcmp(arg
, "-interposable") == 0) || (strcmp(arg
, "-multi_module") == 0)) {
2597 switch ( fInterposeMode
) {
2598 case kInterposeNone
:
2599 case kInterposeAllExternal
:
2600 fInterposeMode
= kInterposeAllExternal
;
2602 case kInterposeSome
:
2603 // do nothing, -interposable_list overrides -interposable"
2606 cannotBeUsedWithBitcode(arg
);
2608 else if ( strcmp(arg
, "-interposable_list") == 0 ) {
2609 snapshotFileArgIndex
= 1;
2610 fInterposeMode
= kInterposeSome
;
2611 loadExportFile(argv
[++i
], "-interposable_list", fInterposeList
);
2612 cannotBeUsedWithBitcode(arg
);
2614 // Default for -interposable/-multi_module/-single_module.
2615 else if ( strcmp(arg
, "-single_module") == 0 ) {
2616 fInterposeMode
= kInterposeNone
;
2618 else if ( strcmp(arg
, "-exported_symbols_list") == 0 ) {
2619 snapshotFileArgIndex
= 1;
2620 if ( fExportMode
== kDontExportSome
)
2621 throw "can't use -exported_symbols_list and -unexported_symbols_list";
2622 fExportMode
= kExportSome
;
2623 loadExportFile(argv
[++i
], "-exported_symbols_list", fExportSymbols
);
2625 else if ( strcmp(arg
, "-unexported_symbols_list") == 0 ) {
2626 snapshotFileArgIndex
= 1;
2627 if ( fExportMode
== kExportSome
)
2628 throw "can't use -unexported_symbols_list and -exported_symbols_list";
2629 fExportMode
= kDontExportSome
;
2630 loadExportFile(argv
[++i
], "-unexported_symbols_list", fDontExportSymbols
);
2632 else if ( strcmp(arg
, "-exported_symbol") == 0 ) {
2633 if ( fExportMode
== kDontExportSome
)
2634 throw "can't use -exported_symbol and -unexported_symbols";
2635 fExportMode
= kExportSome
;
2636 fExportSymbols
.insert(argv
[++i
]);
2638 else if ( strcmp(arg
, "-unexported_symbol") == 0 ) {
2639 if ( fExportMode
== kExportSome
)
2640 throw "can't use -unexported_symbol and -exported_symbol";
2641 fExportMode
= kDontExportSome
;
2642 fDontExportSymbols
.insert(argv
[++i
]);
2644 else if ( strcmp(arg
, "-non_global_symbols_no_strip_list") == 0 ) {
2645 snapshotFileArgIndex
= 1;
2646 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveExclude
)
2647 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2648 fLocalSymbolHandling
= kLocalSymbolsSelectiveInclude
;
2649 loadExportFile(argv
[++i
], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded
);
2650 cannotBeUsedWithBitcode(arg
);
2652 else if ( strcmp(arg
, "-non_global_symbols_strip_list") == 0 ) {
2653 snapshotFileArgIndex
= 1;
2654 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveInclude
)
2655 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2656 fLocalSymbolHandling
= kLocalSymbolsSelectiveExclude
;
2657 loadExportFile(argv
[++i
], "-non_global_symbols_strip_list", fLocalSymbolsExcluded
);
2658 cannotBeUsedWithBitcode(arg
);
2661 else if ( strcmp(arg
, "-no_arch_warnings") == 0 ) {
2662 fIgnoreOtherArchFiles
= true;
2664 else if ( strcmp(arg
, "-force_cpusubtype_ALL") == 0 ) {
2665 fForceSubtypeAll
= true;
2666 fAllowCpuSubtypeMismatches
= true;
2667 cannotBeUsedWithBitcode(arg
);
2669 // Similar to -weak-l but uses the absolute path name to the library.
2670 else if ( strcmp(arg
, "-weak_library") == 0 ) {
2671 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2672 snapshotArgCount
= 0;
2673 FileInfo info
= findFile(argv
[++i
]);
2674 info
.options
.fWeakImport
= true;
2675 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2677 cannotBeUsedWithBitcode(arg
);
2679 else if ( strcmp(arg
, "-lazy_library") == 0 ) {
2680 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2681 snapshotArgCount
= 0;
2682 FileInfo info
= findFile(argv
[++i
]);
2683 info
.options
.fLazyLoad
= true;
2684 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2686 fUsingLazyDylibLinking
= true;
2687 cannotBeUsedWithBitcode(arg
);
2689 else if ( strcmp(arg
, "-framework") == 0 ) {
2690 snapshotArgCount
= 0;
2691 FileInfo info
= findFramework(argv
[++i
]);
2692 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2695 else if ( strcmp(arg
, "-weak_framework") == 0 ) {
2696 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2697 snapshotArgCount
= 0;
2698 FileInfo info
= findFramework(argv
[++i
]);
2699 info
.options
.fWeakImport
= true;
2700 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2703 else if ( strcmp(arg
, "-lazy_framework") == 0 ) {
2704 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2705 snapshotArgCount
= 0;
2706 FileInfo info
= findFramework(argv
[++i
]);
2707 info
.options
.fLazyLoad
= true;
2708 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2710 fUsingLazyDylibLinking
= true;
2711 cannotBeUsedWithBitcode(arg
);
2713 else if ( strcmp(arg
, "-search_paths_first") == 0 ) {
2714 // previously handled by buildSearchPaths()
2716 else if ( strcmp(arg
, "-search_dylibs_first") == 0 ) {
2717 // previously handled by buildSearchPaths()
2719 else if ( strcmp(arg
, "-undefined") == 0 ) {
2720 setUndefinedTreatment(argv
[++i
]);
2721 cannotBeUsedWithBitcode(arg
);
2723 // Debugging output flag.
2724 else if ( strcmp(arg
, "-arch_multiple") == 0 ) {
2725 fMessagesPrefixedWithArchitecture
= true;
2727 // Specify what to do with relocations in read only
2728 // sections like .text. Could be errors, warnings,
2729 // or suppressed. Currently we do nothing with the
2731 else if ( strcmp(arg
, "-read_only_relocs") == 0 ) {
2732 switch ( parseTreatment(argv
[++i
]) ) {
2735 throw "-read_only_relocs missing [ warning | error | suppress ]";
2737 fWarnTextRelocs
= true;
2738 fAllowTextRelocs
= true;
2739 cannotBeUsedWithBitcode(arg
);
2742 fWarnTextRelocs
= false;
2743 fAllowTextRelocs
= true;
2744 cannotBeUsedWithBitcode(arg
);
2747 fWarnTextRelocs
= false;
2748 fAllowTextRelocs
= false;
2752 else if ( strcmp(arg
, "-sect_diff_relocs") == 0 ) {
2756 // Warn, error or make strong a mismatch between weak
2757 // and non-weak references.
2758 else if ( strcmp(arg
, "-weak_reference_mismatches") == 0 ) {
2759 setWeakReferenceMismatchTreatment(argv
[++i
]);
2761 // For a deployment target of 10.3 and earlier ld64 will
2762 // prebind an executable with 0s in all addresses that
2763 // are prebound. This can then be fixed up by update_prebinding
2764 // later. Prebinding is less useful on 10.4 and greater.
2765 else if ( strcmp(arg
, "-prebind") == 0 ) {
2767 cannotBeUsedWithBitcode(arg
);
2769 else if ( strcmp(arg
, "-noprebind") == 0 ) {
2773 else if ( strcmp(arg
, "-prebind_allow_overlap") == 0 ) {
2776 else if ( strcmp(arg
, "-prebind_all_twolevel_modules") == 0 ) {
2779 else if ( strcmp(arg
, "-noprebind_all_twolevel_modules") == 0 ) {
2782 else if ( strcmp(arg
, "-nofixprebinding") == 0 ) {
2785 // This should probably be deprecated when we respect -L and -F
2786 // when searching for libraries.
2787 else if ( strcmp(arg
, "-dylib_file") == 0 ) {
2788 // ignore for snapshot because a stub dylib will be created in the snapshot
2789 snapshotArgCount
= 0;
2790 addDylibOverride(argv
[++i
]);
2791 cannotBeUsedWithBitcode(arg
);
2793 // What to expand @executable_path to if found in dependent dylibs
2794 else if ( strcmp(arg
, "-executable_path") == 0 ) {
2795 fExecutablePath
= argv
[++i
];
2796 if ( (fExecutablePath
== NULL
) || (fExecutablePath
[0] == '-') )
2797 throw "-executable_path missing <path>";
2798 // if a directory was passed, add / to end
2799 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2800 struct stat statBuffer
;
2801 if ( stat(fExecutablePath
, &statBuffer
) == 0 ) {
2802 if ( (statBuffer
.st_mode
& S_IFMT
) == S_IFDIR
) {
2803 char* pathWithSlash
= new char[strlen(fExecutablePath
)+2];
2804 strcpy(pathWithSlash
, fExecutablePath
);
2805 strcat(pathWithSlash
, "/");
2806 fExecutablePath
= pathWithSlash
;
2810 // Aligns all segments to the power of 2 boundary specified.
2811 else if ( strcmp(arg
, "-segalign") == 0 ) {
2812 const char* size
= argv
[++i
];
2814 throw "-segalign missing <size>";
2815 fSegmentAlignment
= parseAddress(size
);
2816 uint8_t alignment
= (uint8_t)__builtin_ctz(fSegmentAlignment
);
2817 uint32_t p2aligned
= (1 << alignment
);
2818 if ( p2aligned
!= fSegmentAlignment
) {
2819 warning("alignment for -segalign %s is not a power of two, using 0x%X", size
, p2aligned
);
2820 fSegmentAlignment
= p2aligned
;
2822 cannotBeUsedWithBitcode(arg
);
2824 // Puts a specified segment at a particular address that must
2825 // be a multiple of the segment alignment.
2826 else if ( strcmp(arg
, "-segaddr") == 0 ) {
2828 seg
.name
= argv
[++i
];
2829 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2830 throw "-segaddr missing segName Adddress";
2831 seg
.address
= parseAddress(argv
[++i
]);
2832 uint64_t temp
= ((seg
.address
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
2833 if ( seg
.address
!= temp
)
2834 warning("-segaddr %s not %lld byte aligned", seg
.name
, fSegmentAlignment
);
2835 fCustomSegmentAddresses
.push_back(seg
);
2836 cannotBeUsedWithBitcode(arg
);
2838 // ??? Deprecate when we deprecate split-seg.
2839 else if ( strcmp(arg
, "-segs_read_only_addr") == 0 ) {
2840 fBaseAddress
= parseAddress(argv
[++i
]);
2841 cannotBeUsedWithBitcode(arg
);
2843 // ??? Deprecate when we deprecate split-seg.
2844 else if ( strcmp(arg
, "-segs_read_write_addr") == 0 ) {
2845 fBaseWritableAddress
= parseAddress(argv
[++i
]);
2847 cannotBeUsedWithBitcode(arg
);
2849 // ??? Deprecate when we get rid of basing at build time.
2850 else if ( strcmp(arg
, "-seg_addr_table") == 0 ) {
2851 snapshotFileArgIndex
= 1;
2852 const char* name
= argv
[++i
];
2854 throw "-seg_addr_table missing argument";
2855 fSegAddrTablePath
= name
;
2856 cannotBeUsedWithBitcode(arg
);
2858 else if ( strcmp(arg
, "-seg_addr_table_filename") == 0 ) {
2862 else if ( strcmp(arg
, "-segprot") == 0 ) {
2864 seg
.name
= argv
[++i
];
2865 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) || (argv
[i
+2] == NULL
) )
2866 throw "-segprot missing segName max-prot init-prot";
2867 seg
.max
= parseProtection(argv
[++i
]);
2868 seg
.init
= parseProtection(argv
[++i
]);
2869 if ( strcmp(seg
.name
, "__LINKEDIT") == 0 )
2870 warning("-segprot cannot be used to modify __LINKEDIT protections");
2872 fCustomSegmentProtections
.push_back(seg
);
2873 cannotBeUsedWithBitcode(arg
);
2875 else if ( strcmp(arg
, "-pagezero_size") == 0 ) {
2876 const char* size
= argv
[++i
];
2878 throw "-pagezero_size missing <size>";
2879 fZeroPageSize
= parseAddress(size
);
2880 uint64_t temp
= fZeroPageSize
& (-4096); // page align
2881 if ( (fZeroPageSize
!= temp
) )
2882 warning("-pagezero_size not page aligned, rounding down");
2883 fZeroPageSize
= temp
;
2884 cannotBeUsedWithBitcode(arg
);
2886 else if ( strcmp(arg
, "-stack_addr") == 0 ) {
2887 const char* address
= argv
[++i
];
2888 if ( address
== NULL
)
2889 throw "-stack_addr missing <address>";
2890 fStackAddr
= parseAddress(address
);
2891 cannotBeUsedWithBitcode(arg
);
2893 else if ( strcmp(arg
, "-stack_size") == 0 ) {
2894 const char* size
= argv
[++i
];
2896 throw "-stack_size missing <address>";
2897 fStackSize
= parseAddress(size
);
2899 else if ( strcmp(arg
, "-allow_stack_execute") == 0 ) {
2900 fExecutableStack
= true;
2901 cannotBeUsedWithBitcode(arg
);
2903 else if ( strcmp(arg
, "-allow_heap_execute") == 0 ) {
2904 fDisableNonExecutableHeap
= true;
2905 cannotBeUsedWithBitcode(arg
);
2907 else if ( strcmp(arg
, "-sectalign") == 0 ) {
2908 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2909 throw "-sectalign missing <segment> <section> <file-path>";
2910 addSectionAlignment(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2912 cannotBeUsedWithBitcode(arg
);
2914 else if ( strcmp(arg
, "-sectorder_detail") == 0 ) {
2917 else if ( strcmp(arg
, "-sectobjectsymbols") == 0 ) {
2921 else if ( strcmp(arg
, "-bundle_loader") == 0 ) {
2922 snapshotFileArgIndex
= 1;
2923 fBundleLoader
= argv
[++i
];
2924 if ( (fBundleLoader
== NULL
) || (fBundleLoader
[0] == '-') )
2925 throw "-bundle_loader missing <path>";
2926 FileInfo info
= findFile(fBundleLoader
);
2927 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2928 info
.options
.fBundleLoader
= true;
2929 fInputFiles
.push_back(info
);
2931 else if ( strcmp(arg
, "-private_bundle") == 0 ) {
2934 else if ( strcmp(arg
, "-twolevel_namespace_hints") == 0 ) {
2937 // Use this flag to set default behavior for deployement targets.
2938 else if ( strcmp(arg
, "-macosx_version_min") == 0 ) {
2939 const char* macVers
= argv
[++i
];
2940 if ( macVers
== NULL
)
2941 throw "-macosx_version_min missing version argument";
2942 const char* envMacVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
2943 const char* enviPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
2944 if ( (envMacVers
!= NULL
) && (enviPhoneVers
!= NULL
) ) {
2945 // <rdar://problem/13774329> when conflicting deployments set, break tie by looking at syslibroot
2946 warning("both MACOSX_DEPLOYMENT_TARGET and IPHONEOS_DEPLOYMENT_TARGET are set");
2947 if ( !fSDKPaths
.empty() ) {
2948 const char* sysrootPath
= fSDKPaths
.back();
2949 const char* lastSlash
= strrchr(sysrootPath
, '/');
2950 if ( strstr(lastSlash
, "Simulator") != NULL
)
2951 setIOSVersionMin(enviPhoneVers
);
2953 setMacOSXVersionMin(macVers
);
2956 setMacOSXVersionMin(macVers
);
2960 setMacOSXVersionMin(macVers
);
2963 else if ( (strcmp(arg
, "-ios_version_min") == 0) || (strcmp(arg
, "-iphoneos_version_min") == 0) ) {
2964 const char* vers
= argv
[++i
];
2966 throw "-ios_version_min missing version argument";
2967 setIOSVersionMin(vers
);
2969 else if ( strcmp(arg
, "-ios_simulator_version_min") == 0 ) {
2970 const char* vers
= argv
[++i
];
2972 throw "-ios_simulator_version_min missing version argument";
2973 setIOSVersionMin(vers
);
2974 fTargetIOSSimulator
= true;
2976 else if ( strcmp(arg
, "-watchos_version_min") == 0 ) {
2977 const char* vers
= argv
[++i
];
2979 throw "-watchos_version_min missing version argument";
2980 setWatchOSVersionMin(vers
);
2982 else if ( strcmp(arg
, "-watchos_simulator_version_min") == 0 ) {
2983 const char* vers
= argv
[++i
];
2985 throw "-watchos_simulator_version_min missing version argument";
2986 setWatchOSVersionMin(vers
);
2987 fTargetIOSSimulator
= true;
2989 #if SUPPORT_APPLE_TV
2990 else if ( strcmp(arg
, "-tvos_version_min") == 0 ) {
2991 const char* vers
= argv
[++i
];
2993 throw "-tvos_version_min missing version argument";
2994 setIOSVersionMin(vers
);
2995 fPlatform
= kPlatform_tvOS
;
2997 else if ( strcmp(arg
, "-tvos_simulator_version_min") == 0 ) {
2998 const char* vers
= argv
[++i
];
3000 throw "-tvos_simulator_version_min missing version argument";
3001 setIOSVersionMin(vers
);
3002 fPlatform
= kPlatform_tvOS
;
3003 fTargetIOSSimulator
= true;
3006 else if ( strcmp(arg
, "-bridgeos_version_min") == 0 ) {
3007 const char* vers
= argv
[++i
];
3009 throw "-bridgeos_version_min missing version argument";
3010 setIOSVersionMin(vers
);
3011 fPlatform
= kPlatform_bridgeOS
;
3013 else if ( strcmp(arg
, "-multiply_defined") == 0 ) {
3014 //warnObsolete(arg);
3017 else if ( strcmp(arg
, "-multiply_defined_unused") == 0 ) {
3021 else if ( strcmp(arg
, "-nomultidefs") == 0 ) {
3024 // Display each file in which the argument symbol appears and whether
3025 // the file defines or references it. This option takes an argument
3026 // as -y<symbol> note that there is no space.
3027 else if ( strncmp(arg
, "-y", 2) == 0 ) {
3030 // Same output as -y, but output <arg> number of undefined symbols only.
3031 else if ( strcmp(arg
, "-Y") == 0 ) {
3032 //warnObsolete(arg);
3035 // This option affects all objects linked into the final result.
3036 else if ( strcmp(arg
, "-m") == 0 ) {
3039 else if ( (strcmp(arg
, "-why_load") == 0) || (strcmp(arg
, "-whyload") == 0) ) {
3042 else if ( strcmp(arg
, "-why_live") == 0 ) {
3043 const char* name
= argv
[++i
];
3045 throw "-why_live missing symbol name argument";
3046 fWhyLive
.insert(name
);
3048 else if ( strcmp(arg
, "-u") == 0 ) {
3049 const char* name
= argv
[++i
];
3051 throw "-u missing argument";
3052 fInitialUndefines
.push_back(name
);
3053 cannotBeUsedWithBitcode(arg
);
3055 else if ( strcmp(arg
, "-U") == 0 ) {
3056 const char* name
= argv
[++i
];
3058 throw "-U missing argument";
3059 fAllowedUndefined
.insert(name
);
3060 cannotBeUsedWithBitcode(arg
);
3062 else if ( strcmp(arg
, "-s") == 0 ) {
3064 fLocalSymbolHandling
= kLocalSymbolsNone
;
3065 fDebugInfoStripping
= Options::kDebugInfoNone
;
3067 else if ( strcmp(arg
, "-x") == 0 ) {
3068 fLocalSymbolHandling
= kLocalSymbolsNone
;
3070 else if ( strcmp(arg
, "-S") == 0 ) {
3071 fDebugInfoStripping
= Options::kDebugInfoNone
;
3073 else if ( strcmp(arg
, "-X") == 0 ) {
3076 else if ( strcmp(arg
, "-Si") == 0 ) {
3078 fDebugInfoStripping
= Options::kDebugInfoFull
;
3080 else if ( strcmp(arg
, "-b") == 0 ) {
3083 else if ( strcmp(arg
, "-Sn") == 0 ) {
3085 fDebugInfoStripping
= Options::kDebugInfoFull
;
3087 else if ( strcmp(arg
, "-Sp") == 0 ) {
3090 else if ( strcmp(arg
, "-dead_strip") == 0 ) {
3093 else if ( strcmp(arg
, "-no_dead_strip_inits_and_terms") == 0 ) {
3096 else if ( strcmp(arg
, "-w") == 0 ) {
3097 // previously handled by buildSearchPaths()
3099 else if ( strcmp(arg
, "-fatal_warnings") == 0 ) {
3100 // previously handled by buildSearchPaths()
3102 else if ( strcmp(arg
, "-arch_errors_fatal") == 0 ) {
3103 fErrorOnOtherArchFiles
= true;
3105 else if ( strcmp(arg
, "-M") == 0 ) {
3108 else if ( strcmp(arg
, "-headerpad") == 0 ) {
3109 const char* size
= argv
[++i
];
3111 throw "-headerpad missing argument";
3112 fMinimumHeaderPad
= parseAddress(size
);
3113 cannotBeUsedWithBitcode(arg
);
3115 else if ( strcmp(arg
, "-headerpad_max_install_names") == 0 ) {
3116 // ignore -headerpad_max_install_names when compiling with bitcode
3117 // rdar://problem/20748962
3118 if ( fBundleBitcode
)
3119 warning("-headerpad_max_install_names is ignored when used with -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES)");
3121 fMaxMinimumHeaderPad
= true;
3123 else if ( strcmp(arg
, "-t") == 0 ) {
3124 fLogAllFiles
= true;
3126 else if ( strcmp(arg
, "-whatsloaded") == 0 ) {
3127 fLogObjectFiles
= true;
3129 else if ( strcmp(arg
, "-A") == 0 ) {
3133 else if ( strcmp(arg
, "-umbrella") == 0 ) {
3134 const char* name
= argv
[++i
];
3136 throw "-umbrella missing argument";
3137 fUmbrellaName
= name
;
3138 cannotBeUsedWithBitcode(arg
);
3140 else if ( strcmp(arg
, "-allowable_client") == 0 ) {
3141 const char* name
= argv
[++i
];
3144 throw "-allowable_client missing argument";
3146 fAllowableClients
.push_back(name
);
3147 cannotBeUsedWithBitcode(arg
);
3149 else if ( strcmp(arg
, "-client_name") == 0 ) {
3150 const char* name
= argv
[++i
];
3153 throw "-client_name missing argument";
3156 cannotBeUsedWithBitcode(arg
);
3158 else if ( strcmp(arg
, "-sub_umbrella") == 0 ) {
3159 const char* name
= argv
[++i
];
3161 throw "-sub_umbrella missing argument";
3162 fSubUmbellas
.push_back(name
);
3163 cannotBeUsedWithBitcode(arg
);
3165 else if ( strcmp(arg
, "-sub_library") == 0 ) {
3166 const char* name
= argv
[++i
];
3168 throw "-sub_library missing argument";
3169 fSubLibraries
.push_back(name
);
3170 cannotBeUsedWithBitcode(arg
);
3172 else if ( strcmp(arg
, "-init") == 0 ) {
3173 const char* name
= argv
[++i
];
3175 throw "-init missing argument";
3176 fInitFunctionName
= name
;
3177 cannotBeUsedWithBitcode(arg
);
3179 else if ( strcmp(arg
, "-dot") == 0 ) {
3180 const char* name
= argv
[++i
];
3182 throw "-dot missing argument";
3183 fDotOutputFile
= name
;
3184 cannotBeUsedWithBitcode(arg
);
3186 else if ( strcmp(arg
, "-warn_commons") == 0 ) {
3187 fWarnCommons
= true;
3189 else if ( strcmp(arg
, "-commons") == 0 ) {
3190 fCommonsMode
= parseCommonsTreatment(argv
[++i
]);
3192 else if ( strcmp(arg
, "-keep_relocs") == 0 ) {
3193 fKeepRelocations
= true;
3195 else if ( strcmp(arg
, "-warn_stabs") == 0 ) {
3198 else if ( strcmp(arg
, "-pause") == 0 ) {
3201 else if ( strcmp(arg
, "-print_statistics") == 0 ) {
3204 else if ( strcmp(arg
, "-d") == 0 ) {
3205 fMakeTentativeDefinitionsReal
= true;
3207 else if ( strcmp(arg
, "-v") == 0 ) {
3208 // previously handled by buildSearchPaths()
3210 else if ( strcmp(arg
, "-Z") == 0 ) {
3211 // previously handled by buildSearchPaths()
3213 else if ( strcmp(arg
, "-syslibroot") == 0 ) {
3214 snapshotArgCount
= 0;
3216 // previously handled by buildSearchPaths()
3218 else if ( strcmp(arg
, "-bitcode_bundle") == 0 ) {
3219 snapshotArgCount
= 0;
3220 // previously handled by buildSearchPaths()
3222 else if ( strcmp(arg
, "-no_uuid") == 0 ) {
3223 fUUIDMode
= kUUIDNone
;
3224 cannotBeUsedWithBitcode(arg
);
3226 else if ( strcmp(arg
, "-random_uuid") == 0 ) {
3227 fUUIDMode
= kUUIDRandom
;
3228 cannotBeUsedWithBitcode(arg
);
3230 else if ( strcmp(arg
, "-dtrace") == 0 ) {
3231 snapshotFileArgIndex
= 1;
3232 const char* name
= argv
[++i
];
3234 throw "-dtrace missing argument";
3235 fDtraceScriptName
= name
;
3236 cannotBeUsedWithBitcode(arg
);
3238 else if ( strcmp(arg
, "-root_safe") == 0 ) {
3241 else if ( strcmp(arg
, "-setuid_safe") == 0 ) {
3244 else if ( strcmp(arg
, "-alias") == 0 ) {
3245 Options::AliasPair pair
;
3246 pair
.realName
= argv
[++i
];
3247 if ( pair
.realName
== NULL
)
3248 throw "missing argument to -alias";
3249 pair
.alias
= argv
[++i
];
3250 if ( pair
.alias
== NULL
)
3251 throw "missing argument to -alias";
3252 fAliases
.push_back(pair
);
3253 cannotBeUsedWithBitcode(arg
);
3255 else if ( strcmp(arg
, "-alias_list") == 0 ) {
3256 snapshotFileArgIndex
= 1;
3257 parseAliasFile(argv
[++i
]);
3258 cannotBeUsedWithBitcode(arg
);
3260 else if ( strcmp(arg
, "-save-temps") == 0 ) {
3261 fSaveTempFiles
= true;
3263 else if ( strcmp(arg
, "-bitcode_hide_symbols") == 0 ) {
3264 fHideSymbols
= true;
3266 else if ( strcmp(arg
, "-bitcode_verify") == 0 ) {
3267 fVerifyBitcode
= true;
3269 else if ( strcmp(arg
, "-bitcode_symbol_map") == 0) {
3270 fReverseMapPath
= argv
[++i
];
3271 if ( fReverseMapPath
== NULL
)
3272 throw "missing argument to -bitcode_symbol_map";
3273 struct stat statbuf
;
3274 int ret
= ::stat(fReverseMapPath
, &statbuf
);
3275 if ( ret
== 0 && S_ISDIR(statbuf
.st_mode
)) {
3276 char tempPath
[PATH_MAX
];
3277 sprintf(tempPath
, "%s/XXXXXX", fReverseMapPath
);
3278 int tempFile
= ::mkstemp(tempPath
);
3280 throwf("could not write file to symbol map directory: %s", fReverseMapPath
);
3282 fReverseMapTempPath
= std::string(tempPath
);
3283 fReverseMapUUIDRename
= true;
3285 fReverseMapTempPath
= std::string(fReverseMapPath
);
3287 else if ( strcmp(argv
[i
], "-flto-codegen-only") == 0) {
3288 fLTOCodegenOnly
= true;
3290 else if ( strcmp(argv
[i
], "-ignore_auto_link") == 0) {
3291 fIgnoreAutoLink
= true;
3293 else if ( strcmp(argv
[i
], "-allow_dead_duplicates") == 0) {
3294 fAllowDeadDups
= true;
3296 else if ( strcmp(argv
[i
], "-bitcode_process_mode") == 0 ) {
3297 const char* bitcode_type
= argv
[++i
];
3298 if ( bitcode_type
== NULL
)
3299 throw "missing argument to -bitcode_process_mode";
3300 else if ( strcmp(bitcode_type
, "strip") == 0 )
3301 fBitcodeKind
= kBitcodeStrip
;
3302 else if ( strcmp(bitcode_type
, "marker") == 0 )
3303 fBitcodeKind
= kBitcodeMarker
;
3304 else if ( strcmp(bitcode_type
, "data") == 0 )
3305 fBitcodeKind
= kBitcodeAsData
;
3306 else if ( strcmp(bitcode_type
, "bitcode") == 0 )
3307 fBitcodeKind
= kBitcodeProcess
;
3309 throw "unknown argument to -bitcode_process_mode {strip,marker,data,bitcode}";
3311 else if ( strcmp(arg
, "-rpath") == 0 ) {
3312 const char* path
= argv
[++i
];
3314 throw "missing argument to -rpath";
3315 fRPaths
.push_back(path
);
3317 else if ( strcmp(arg
, "-read_only_stubs") == 0 ) {
3318 fReadOnlyx86Stubs
= true;
3320 else if ( strcmp(arg
, "-slow_stubs") == 0 ) {
3323 else if ( strcmp(arg
, "-map") == 0 ) {
3324 fMapPath
= argv
[++i
];
3325 if ( fMapPath
== NULL
)
3326 throw "missing argument to -map";
3328 else if ( strcmp(arg
, "-pie") == 0 ) {
3329 fPositionIndependentExecutable
= true;
3330 fPIEOnCommandLine
= true;
3332 else if ( strcmp(arg
, "-no_pie") == 0 ) {
3333 fDisablePositionIndependentExecutable
= true;
3334 cannotBeUsedWithBitcode(arg
);
3336 else if ( strncmp(arg
, "-reexport-l", 11) == 0 ) {
3337 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3338 snapshotArgCount
= 0;
3339 FileInfo info
= findLibrary(&arg
[11], true);
3340 info
.options
.fReExport
= true;
3341 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3343 cannotBeUsedWithBitcode(arg
);
3345 else if ( strcmp(arg
, "-reexport_library") == 0 ) {
3346 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3347 snapshotArgCount
= 0;
3348 FileInfo info
= findFile(argv
[++i
]);
3349 info
.options
.fReExport
= true;
3350 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3352 cannotBeUsedWithBitcode(arg
);
3354 else if ( strcmp(arg
, "-reexport_framework") == 0 ) {
3355 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3356 snapshotArgCount
= 0;
3357 FileInfo info
= findFramework(argv
[++i
]);
3358 info
.options
.fReExport
= true;
3359 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3361 cannotBeUsedWithBitcode(arg
);
3363 else if ( strncmp(arg
, "-upward-l", 9) == 0 ) {
3364 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3365 snapshotArgCount
= 0;
3366 FileInfo info
= findLibrary(&arg
[9], true);
3367 info
.options
.fUpward
= true;
3368 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3370 cannotBeUsedWithBitcode(arg
);
3372 else if ( strcmp(arg
, "-upward_library") == 0 ) {
3373 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3374 snapshotArgCount
= 0;
3375 FileInfo info
= findFile(argv
[++i
]);
3376 info
.options
.fUpward
= true;
3377 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3379 cannotBeUsedWithBitcode(arg
);
3381 else if ( strcmp(arg
, "-upward_framework") == 0 ) {
3382 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3383 snapshotArgCount
= 0;
3384 FileInfo info
= findFramework(argv
[++i
]);
3385 info
.options
.fUpward
= true;
3386 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3388 cannotBeUsedWithBitcode(arg
);
3390 else if ( strcmp(arg
, "-dead_strip_dylibs") == 0 ) {
3391 fDeadStripDylibs
= true;
3392 cannotBeUsedWithBitcode(arg
);
3394 else if ( strcmp(arg
, "-no_implicit_dylibs") == 0 ) {
3395 fImplicitlyLinkPublicDylibs
= false;
3397 else if ( strcmp(arg
, "-new_linker") == 0 ) {
3400 else if ( strcmp(arg
, "-no_encryption") == 0 ) {
3401 fEncryptableForceOff
= true;
3402 cannotBeUsedWithBitcode(arg
);
3404 else if ( strcmp(arg
, "-encryptable") == 0 ) {
3405 fEncryptableForceOn
= true;
3406 cannotBeUsedWithBitcode(arg
);
3408 else if ( strcmp(arg
, "-no_compact_unwind") == 0 ) {
3409 fAddCompactUnwindEncoding
= false;
3410 cannotBeUsedWithBitcode(arg
);
3412 else if ( strcmp(arg
, "-mllvm") == 0 ) {
3413 const char* opts
= argv
[++i
];
3415 throw "missing argument to -mllvm";
3416 fLLVMOptions
.push_back(opts
);
3417 cannotBeUsedWithBitcode(arg
);
3419 else if ( strcmp(arg
, "-mcpu") == 0 ) {
3420 const char* cpu
= argv
[++i
];
3422 throw "missing argument to -mcpu";
3424 cannotBeUsedWithBitcode(arg
);
3426 else if ( strcmp(arg
, "-no_order_inits") == 0 ) {
3427 fAutoOrderInitializers
= false;
3428 cannotBeUsedWithBitcode(arg
);
3430 else if ( strcmp(arg
, "-no_order_data") == 0 ) {
3432 cannotBeUsedWithBitcode(arg
);
3434 else if ( strcmp(arg
, "-seg_page_size") == 0 ) {
3436 seg
.name
= argv
[++i
];
3437 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
3438 throw "-seg_page_size missing segName Adddress";
3439 seg
.size
= parseAddress(argv
[++i
]);
3440 uint64_t temp
= seg
.size
& (-4096); // page align
3441 if ( (seg
.size
!= temp
) )
3442 warning("-seg_page_size %s not 4K aligned, rounding down", seg
.name
);
3443 fCustomSegmentSizes
.push_back(seg
);
3444 cannotBeUsedWithBitcode(arg
);
3446 else if ( strcmp(arg
, "-mark_dead_strippable_dylib") == 0 ) {
3447 fMarkDeadStrippableDylib
= true;
3448 cannotBeUsedWithBitcode(arg
);
3450 else if ( strcmp(arg
, "-exported_symbols_order") == 0 ) {
3451 snapshotFileArgIndex
= 1;
3452 loadSymbolOrderFile(argv
[++i
], fExportSymbolsOrder
);
3453 cannotBeUsedWithBitcode(arg
);
3455 else if ( strcmp(arg
, "-no_compact_linkedit") == 0 ) {
3456 warnObsolete("-no_compact_linkedit");
3458 else if ( strcmp(arg
, "-no_eh_labels") == 0 ) {
3460 cannotBeUsedWithBitcode(arg
);
3462 else if ( strcmp(arg
, "-warn_compact_unwind") == 0 ) {
3463 fWarnCompactUnwind
= true;
3465 else if ( strcmp(arg
, "-allow_sub_type_mismatches") == 0 ) {
3466 fAllowCpuSubtypeMismatches
= true;
3467 cannotBeUsedWithBitcode(arg
);
3469 else if ( strcmp(arg
, "-no_zero_fill_sections") == 0 ) {
3470 fOptimizeZeroFill
= false;
3471 cannotBeUsedWithBitcode(arg
);
3473 else if ( strcmp(arg
, "-merge_zero_fill_sections") == 0 ) {
3474 fMergeZeroFill
= true;
3475 cannotBeUsedWithBitcode(arg
);
3477 else if ( strcmp(arg
, "-objc_abi_version") == 0 ) {
3478 const char* version
= argv
[++i
];
3479 if ( version
== NULL
)
3480 throw "-objc_abi_version missing version number";
3481 if ( strcmp(version
, "2") == 0 ) {
3482 fObjCABIVersion1Override
= false;
3483 fObjCABIVersion2Override
= true;
3485 else if ( strcmp(version
, "1") == 0 ) {
3486 fObjCABIVersion1Override
= true;
3487 fObjCABIVersion2Override
= false;
3490 warning("ignoring unrecognized argument (%s) to -objc_abi_version", version
);
3492 else if ( strcmp(arg
, "-warn_weak_exports") == 0 ) {
3493 fWarnWeakExports
= true;
3495 else if ( strcmp(arg
, "-objc_gc_compaction") == 0 ) {
3496 fObjcGcCompaction
= true;
3497 cannotBeUsedWithBitcode(arg
);
3499 else if ( strcmp(arg
, "-objc_gc") == 0 ) {
3501 if ( fObjCGcOnly
) {
3502 warning("-objc_gc overriding -objc_gc_only");
3503 fObjCGcOnly
= false;
3505 cannotBeUsedWithBitcode(arg
);
3507 else if ( strcmp(arg
, "-objc_gc_only") == 0 ) {
3510 warning("-objc_gc_only overriding -objc_gc");
3513 cannotBeUsedWithBitcode(arg
);
3515 else if ( strcmp(arg
, "-demangle") == 0 ) {
3518 else if ( strcmp(arg
, "-version_load_command") == 0 ) {
3519 fVersionLoadCommandForcedOn
= true;
3520 fVersionLoadCommandForcedOff
= false;
3522 else if ( strcmp(arg
, "-no_version_load_command") == 0 ) {
3523 fVersionLoadCommandForcedOff
= true;
3524 fVersionLoadCommandForcedOn
= false;
3525 cannotBeUsedWithBitcode(arg
);
3527 else if ( strcmp(arg
, "-function_starts") == 0 ) {
3528 fFunctionStartsForcedOn
= true;
3529 fFunctionStartsForcedOff
= false;
3531 else if ( strcmp(arg
, "-no_function_starts") == 0 ) {
3532 fFunctionStartsForcedOff
= true;
3533 fFunctionStartsForcedOn
= false;
3534 cannotBeUsedWithBitcode(arg
);
3536 else if ( strcmp(arg
, "-no_data_in_code_info") == 0 ) {
3537 fDataInCodeInfoLoadCommandForcedOff
= true;
3538 fDataInCodeInfoLoadCommandForcedOn
= false;
3539 cannotBeUsedWithBitcode(arg
);
3541 else if ( strcmp(arg
, "-data_in_code_info") == 0 ) {
3542 fDataInCodeInfoLoadCommandForcedOn
= true;
3543 fDataInCodeInfoLoadCommandForcedOff
= false;
3545 else if ( strcmp(arg
, "-object_path_lto") == 0 ) {
3546 fTempLtoObjectPath
= argv
[++i
];
3547 if ( fTempLtoObjectPath
== NULL
)
3548 throw "missing argument to -object_path_lto";
3550 else if ( strcmp(arg
, "-no_objc_category_merging") == 0 ) {
3551 fObjcCategoryMerging
= false;
3553 else if ( strcmp(arg
, "-force_symbols_weak_list") == 0 ) {
3554 snapshotFileArgIndex
= 1;
3555 loadExportFile(argv
[++i
], "-force_symbols_weak_list", fForceWeakSymbols
);
3556 cannotBeUsedWithBitcode(arg
);
3558 else if ( strcmp(arg
, "-force_symbols_not_weak_list") == 0 ) {
3559 snapshotFileArgIndex
= 1;
3560 loadExportFile(argv
[++i
], "-force_symbols_not_weak_list", fForceNotWeakSymbols
);
3561 cannotBeUsedWithBitcode(arg
);
3563 else if ( strcmp(arg
, "-force_symbol_weak") == 0 ) {
3564 const char* symbol
= argv
[++i
];
3565 if ( symbol
== NULL
)
3566 throw "-force_symbol_weak missing <symbol>";
3567 fForceWeakSymbols
.insert(symbol
);
3568 cannotBeUsedWithBitcode(arg
);
3570 else if ( strcmp(arg
, "-force_symbol_not_weak") == 0 ) {
3571 const char* symbol
= argv
[++i
];
3572 if ( symbol
== NULL
)
3573 throw "-force_symbol_not_weak missing <symbol>";
3574 fForceNotWeakSymbols
.insert(symbol
);
3575 cannotBeUsedWithBitcode(arg
);
3577 else if ( strcmp(arg
, "-reexported_symbols_list") == 0 ) {
3578 snapshotFileArgIndex
= 1;
3579 if ( fExportMode
== kExportSome
)
3580 throw "can't use -exported_symbols_list and -reexported_symbols_list";
3581 loadExportFile(argv
[++i
], "-reexported_symbols_list", fReExportSymbols
);
3583 else if ( strcmp(arg
, "-dyld_env") == 0 ) {
3584 const char* envarg
= argv
[++i
];
3585 if ( envarg
== NULL
)
3586 throw "-dyld_env missing ENV=VALUE";
3587 if ( strchr(envarg
, '=') == NULL
)
3588 throw "-dyld_env missing ENV=VALUE";
3589 fDyldEnvironExtras
.push_back(envarg
);
3590 cannotBeUsedWithBitcode(arg
);
3592 else if ( strcmp(arg
, "-page_align_data_atoms") == 0 ) {
3593 fPageAlignDataAtoms
= true;
3594 cannotBeUsedWithBitcode(arg
);
3596 else if (strcmp(arg
, "-debug_snapshot") == 0) {
3597 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
3598 fSnapshotRequested
= true;
3599 cannotBeUsedWithBitcode(arg
);
3601 else if (strcmp(arg
, "-snapshot_dir") == 0) {
3602 const char* path
= argv
[++i
];
3604 throw "-snapshot_dir missing path";
3605 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
3606 fLinkSnapshot
.setSnapshotPath(path
);
3607 fSnapshotRequested
= true;
3608 cannotBeUsedWithBitcode(arg
);
3610 else if ( strcmp(arg
, "-new_main") == 0 ) {
3611 fEntryPointLoadCommandForceOn
= true;
3612 cannotBeUsedWithBitcode(arg
);
3614 else if ( strcmp(arg
, "-no_new_main") == 0 ) {
3615 fEntryPointLoadCommandForceOff
= true;
3616 cannotBeUsedWithBitcode(arg
);
3618 else if ( strcmp(arg
, "-source_version") == 0 ) {
3619 const char* vers
= argv
[++i
];
3621 throw "-source_version missing <version>";
3622 fSourceVersion
= parseVersionNumber64(vers
);
3624 else if ( strcmp(arg
, "-add_source_version") == 0 ) {
3625 fSourceVersionLoadCommandForceOn
= true;
3627 else if ( strcmp(arg
, "-no_source_version") == 0 ) {
3628 fSourceVersionLoadCommandForceOff
= true;
3629 cannotBeUsedWithBitcode(arg
);
3631 else if ( strcmp(arg
, "-sdk_version") == 0 ) {
3632 const char* vers
= argv
[++i
];
3634 throw "-sdk_version missing <version>";
3635 fSDKVersion
= parseVersionNumber32(vers
);
3637 else if ( strcmp(arg
, "-dependent_dr_info") == 0 ) {
3640 else if ( strcmp(arg
, "-no_dependent_dr_info") == 0 ) {
3643 else if ( strcmp(arg
, "-kexts_use_stubs") == 0 ) {
3644 fKextsUseStubs
= true;
3645 cannotBeUsedWithBitcode(arg
);
3647 else if ( strcmp(argv
[i
], "-dependency_info") == 0 ) {
3648 snapshotArgCount
= 0;
3650 // previously handled by buildSearchPaths()
3652 else if ( strcmp(arg
, "-export_dynamic") == 0 ) {
3653 fExportDynamic
= true;
3655 else if ( strcmp(arg
, "-force_symbols_coalesce_list") == 0 ) {
3656 snapshotFileArgIndex
= 1;
3657 loadExportFile(argv
[++i
], "-force_symbols_coalesce_list", fForceCoalesceSymbols
);
3659 else if ( strcmp(arg
, "-add_linker_option") == 0 ) {
3660 // ex: -add_linker_option '-framework Foundation'
3661 const char* optString
= argv
[++i
];
3662 if ( optString
== NULL
)
3663 throw "-add_linker_option missing <option>";
3664 // break up into list of tokens at whitespace
3665 std::vector
<const char*> opts
;
3666 char* buffer
= strdup(optString
);
3667 char* start
= buffer
;
3668 for (char* s
= buffer
; ; ++s
) {
3669 if ( isspace(*s
) ) {
3671 opts
.push_back(start
);
3674 else if ( *s
== '\0' ) {
3675 opts
.push_back(start
);
3679 fLinkerOptions
.push_back(opts
);
3680 cannotBeUsedWithBitcode(arg
);
3682 else if ( strcmp(arg
, "-allow_simulator_linking_to_macosx_dylibs") == 0 ) {
3683 fAllowSimulatorToLinkWithMacOSX
= true;
3684 cannotBeUsedWithBitcode(arg
);
3686 else if ( strcmp(arg
, "-keep_dwarf_unwind") == 0 ) {
3687 fKeepDwarfUnwindForcedOn
= true;
3688 fKeepDwarfUnwindForcedOff
= false;
3689 cannotBeUsedWithBitcode(arg
);
3691 else if ( strcmp(arg
, "-no_keep_dwarf_unwind") == 0 ) {
3692 fKeepDwarfUnwindForcedOn
= false;
3693 fKeepDwarfUnwindForcedOff
= true;
3694 cannotBeUsedWithBitcode(arg
);
3696 else if ( strcmp(arg
, "-verbose_optimization_hints") == 0 ) {
3697 fVerboseOptimizationHints
= true;
3699 else if ( strcmp(arg
, "-ignore_optimization_hints") == 0 ) {
3700 fIgnoreOptimizationHints
= true;
3701 cannotBeUsedWithBitcode(arg
);
3703 else if ( strcmp(arg
, "-no_dtrace_dof") == 0 ) {
3704 fGenerateDtraceDOF
= false;
3706 else if ( strcmp(arg
, "-rename_section") == 0 ) {
3707 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) || (argv
[i
+4]==NULL
) )
3708 throw "-rename_section missing <segment> <section> <segment> <section>";
3709 addSectionRename(argv
[i
+1], argv
[i
+2], argv
[i
+3], argv
[i
+4]);
3711 cannotBeUsedWithBitcode(arg
);
3713 else if ( strcmp(arg
, "-rename_segment") == 0 ) {
3714 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3715 throw "-rename_segment missing <existing-segment> <new-segment>";
3716 addSegmentRename(argv
[i
+1], argv
[i
+2]);
3718 cannotBeUsedWithBitcode(arg
);
3720 else if ( strcmp(arg
, "-move_to_ro_segment") == 0 ) {
3721 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3722 throw "-move_to_ro_segment missing <segment> <symbol-list-file>";
3723 addSymbolMove(argv
[i
+1], argv
[i
+2], fSymbolsMovesCode
, "-move_to_ro_segment");
3725 cannotBeUsedWithBitcode(arg
);
3727 else if ( strcmp(arg
, "-move_to_rw_segment") == 0 ) {
3728 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3729 throw "-move_to_rw_segment missing <segment> <symbol-list-file>";
3730 addSymbolMove(argv
[i
+1], argv
[i
+2], fSymbolsMovesData
, "-move_to_rw_segment");
3732 cannotBeUsedWithBitcode(arg
);
3734 else if ( strcmp(arg
, "-trace_symbol_layout") == 0 ) {
3735 fTraceSymbolLayout
= true;
3737 else if ( strcmp(arg
, "-no_branch_islands") == 0 ) {
3738 fAllowBranchIslands
= false;
3739 cannotBeUsedWithBitcode(arg
);
3741 else if ( strcmp(arg
, "-segment_order") == 0 ) {
3742 // ex: -segment_order __TEXT:__DATA:__JUNK
3743 const char* optString
= argv
[++i
];
3744 if ( optString
== NULL
)
3745 throw "-segment_order missing colon separated <segment-list>";
3746 if ( !fSegmentOrder
.empty() )
3747 throw "-segment_order used more than once";
3748 // break up into list of tokens at colon
3749 char* buffer
= strdup(optString
);
3750 char* start
= buffer
;
3751 for (char* s
= buffer
; ; ++s
) {
3754 fSegmentOrder
.push_back(start
);
3757 else if ( *s
== '\0' ) {
3758 fSegmentOrder
.push_back(start
);
3762 cannotBeUsedWithBitcode(arg
);
3764 else if ( strcmp(arg
, "-section_order") == 0 ) {
3765 // ex: -section_order __DATA __data:__const:__nl_pointers
3766 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3767 throw "-section_order missing <segment> <section-list>";
3768 const char* segName
= argv
[++i
];
3769 const char* optString
= argv
[++i
];
3770 if ( sectionOrder(segName
) != NULL
)
3771 throwf("-section_order %s ... used more than once", segName
);
3772 SectionOrderList dummy
;
3773 fSectionOrder
.push_back(dummy
);
3774 SectionOrderList
& entry
= fSectionOrder
.back();
3775 entry
.segmentName
= segName
;
3776 // break up into list of tokens at colon
3777 char* buffer
= strdup(optString
);
3778 char* start
= buffer
;
3779 for (char* s
= buffer
; ; ++s
) {
3782 entry
.sectionOrder
.push_back(start
);
3785 else if ( *s
== '\0' ) {
3786 entry
.sectionOrder
.push_back(start
);
3790 cannotBeUsedWithBitcode(arg
);
3792 else if ( strcmp(arg
, "-application_extension") == 0 ) {
3793 fMarkAppExtensionSafe
= true;
3794 fCheckAppExtensionSafe
= true;
3796 else if ( strcmp(arg
, "-no_application_extension") == 0 ) {
3797 fMarkAppExtensionSafe
= false;
3798 fCheckAppExtensionSafe
= false;
3800 else if ( strcmp(arg
, "-add_ast_path") == 0 ) {
3801 const char* path
= argv
[++i
];
3803 throw "-add_ast_path missing <option>";
3804 fASTFilePaths
.push_back(path
);
3806 else if ( strcmp(arg
, "-force_load_swift_libs") == 0 ) {
3807 fForceLoadSwiftLibs
= true;
3809 else if ( strcmp(arg
, "-not_for_dyld_shared_cache") == 0 ) {
3810 fSharedRegionEligibleForceOff
= true;
3811 cannotBeUsedWithBitcode(arg
);
3813 else if ( strcmp(arg
, "-dirty_data_list") == 0 ) {
3814 if ( argv
[i
+1] == NULL
)
3815 throw "-dirty_data_list missing <symbol-list-file>";
3816 addSymbolMove("__DATA_DIRTY", argv
[i
+1], fSymbolsMovesData
, "-dirty_data_list");
3818 cannotBeUsedWithBitcode(arg
);
3820 else if ( strcmp(arg
, "-data_const") == 0 ) {
3821 fUseDataConstSegmentForceOn
= true;
3822 cannotBeUsedWithBitcode(arg
);
3824 else if ( strcmp(arg
, "-no_data_const") == 0 ) {
3825 fUseDataConstSegmentForceOff
= true;
3826 cannotBeUsedWithBitcode(arg
);
3828 else if ( strcmp(arg
, "-text_exec") == 0 ) {
3829 fUseTextExecSegment
= true;
3830 cannotBeUsedWithBitcode(arg
);
3832 else if ( strcmp(arg
, "-add_split_seg_info") == 0) {
3833 fSharedRegionEligible
= true;
3834 cannotBeUsedWithBitcode(arg
);
3836 else if ( strcmp(arg
, "-no_deduplicate") == 0 ) {
3839 else if ( strcmp(arg
, "-verbose_deduplicate") == 0 ) {
3840 fVerboseDeDupe
= true;
3842 else if ( strcmp(arg
, "-max_default_common_align") == 0 ) {
3843 const char* alignStr
= argv
[++i
];
3844 if ( alignStr
== NULL
)
3845 throw "-max_default_common_align missing <align-value>";
3846 // argument is a hexadecimal number
3848 unsigned long value
= strtoul(alignStr
, &endptr
, 16);
3849 if ( *endptr
!= '\0')
3850 throw "argument for -max_default_common_align is not a hexadecimal number";
3851 if ( value
> 0x8000 )
3852 throw "argument for -max_default_common_align must be less than or equal to 0x8000";
3854 warning("zero is not a valid -max_default_common_align");
3857 // alignment is power of 2
3858 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
3859 if ( (unsigned long)(1 << alignment
) != value
) {
3860 warning("alignment for -max_default_common_align is not a power of two, using 0x%X", 1 << alignment
);
3862 fMaxDefaultCommonAlign
= alignment
;
3864 else if ( strcmp(argv
[i
], "-no_weak_imports") == 0 ) {
3865 fAllowWeakImports
= false;
3867 else if ( strcmp(argv
[i
], "-no_inits") == 0 ) {
3868 fNoInitializers
= true;
3870 // put this last so that it does not interfer with other options starting with 'i'
3871 else if ( strncmp(arg
, "-i", 2) == 0 ) {
3872 const char* colon
= strchr(arg
, ':');
3873 if ( colon
== NULL
)
3874 throwf("unknown option: %s", arg
);
3875 Options::AliasPair pair
;
3876 char* temp
= new char[colon
-arg
];
3877 strlcpy(temp
, &arg
[2], colon
-arg
-1);
3878 pair
.realName
= &colon
[1];
3880 fAliases
.push_back(pair
);
3883 throwf("unknown option: %s", arg
);
3886 if (snapshotArgCount
== -1)
3887 snapshotArgCount
= i
-snapshotArgIndex
+1;
3888 if (snapshotArgCount
> 0)
3889 fLinkSnapshot
.addSnapshotLinkArg(snapshotArgIndex
, snapshotArgCount
, snapshotFileArgIndex
);
3892 FileInfo info
= findFile(arg
);
3893 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3894 if ( strcmp(&info
.path
[strlen(info
.path
)-2], ".a") == 0 )
3897 fInputFiles
.push_back(info
);
3901 // if a -lazy option was used, implicitly link in lazydylib1.o
3902 if ( fUsingLazyDylibLinking
) {
3903 FileInfo info
= findLibrary("lazydylib1.o");
3904 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)argc
);
3908 if (fSnapshotRequested
)
3909 fLinkSnapshot
.createSnapshot();
3915 // -syslibroot <path> is used for SDK support.
3916 // The rule is that all search paths (both explicit and default) are
3917 // checked to see if they exist in the SDK. If so, that path is
3918 // replaced with the sdk prefixed path. If not, that search path
3919 // is used as is. If multiple -syslibroot options are specified
3920 // their directory structures are logically overlayed and files
3921 // from sdks specified earlier on the command line used before later ones.
3923 void Options::buildSearchPaths(int argc
, const char* argv
[])
3925 bool addStandardLibraryDirectories
= true;
3926 std::vector
<const char*> libraryPaths
;
3927 std::vector
<const char*> frameworkPaths
;
3928 libraryPaths
.reserve(10);
3929 frameworkPaths
.reserve(10);
3930 // scan through argv looking for -L, -F, -Z, and -syslibroot options
3931 for(int i
=0; i
< argc
; ++i
) {
3932 if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'L') ) {
3933 const char* libSearchDir
= &argv
[i
][2];
3934 // Allow either "-L{path}" or "-L {path}".
3935 if (argv
[i
][2] == '\0') {
3936 // -L {path}. Make sure there is an argument following this.
3937 const char* path
= argv
[++i
];
3939 throw "-L missing argument";
3940 libSearchDir
= path
;
3942 if ( libSearchDir
[0] == '\0' )
3943 throw "-L must be immediately followed by a directory path (no space)";
3944 libraryPaths
.push_back(libSearchDir
);
3946 else if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'F') ) {
3947 const char* frameworkSearchDir
= &argv
[i
][2];
3948 // Allow either "-F{path}" or "-F {path}".
3949 if (argv
[i
][2] == '\0') {
3950 // -F {path}. Make sure there is an argument following this.
3951 const char* path
= argv
[++i
];
3953 throw "-F missing argument";
3954 frameworkSearchDir
= path
;
3956 if ( frameworkSearchDir
[0] == '\0' )
3957 throw "-F must be immediately followed by a directory path (no space)";
3958 frameworkPaths
.push_back(frameworkSearchDir
);
3960 else if ( strcmp(argv
[i
], "-Z") == 0 )
3961 addStandardLibraryDirectories
= false;
3962 else if ( strcmp(argv
[i
], "-v") == 0 ) {
3964 extern const char ldVersionString
[];
3965 fprintf(stderr
, "%s", ldVersionString
);
3966 fprintf(stderr
, "configured to support archs: %s\n", ALL_SUPPORTED_ARCHS
);
3967 // if only -v specified, exit cleanly
3969 const char* ltoVers
= lto::version();
3970 if ( ltoVers
!= NULL
)
3971 fprintf(stderr
, "LTO support using: %s (static support for %d, runtime is %d)\n",
3972 ltoVers
, lto::static_api_version(), lto::runtime_api_version());
3973 fprintf(stderr
, "TAPI support using: %s\n", tapi::Version::getFullVersionAsString().c_str());
3977 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
3978 const char* path
= argv
[++i
];
3980 throw "-syslibroot missing argument";
3981 fSDKPaths
.push_back(path
);
3983 else if ( strcmp(argv
[i
], "-search_paths_first") == 0 ) {
3984 fLibrarySearchMode
= kSearchDylibAndArchiveInEachDir
;
3986 else if ( strcmp(argv
[i
], "-search_dylibs_first") == 0 ) {
3987 fLibrarySearchMode
= kSearchAllDirsForDylibsThenAllDirsForArchives
;
3989 else if ( strcmp(argv
[i
], "-w") == 0 ) {
3990 sEmitWarnings
= false;
3992 else if ( strcmp(argv
[i
], "-fatal_warnings") == 0 ) {
3993 sFatalWarnings
= true;
3995 else if ( strcmp(argv
[i
], "-dependency_info") == 0 ) {
3996 const char* path
= argv
[++i
];
3998 throw "-dependency_info missing <path>";
3999 fDependencyInfoPath
= path
;
4001 else if ( strcmp(argv
[i
], "-bitcode_bundle") == 0 ) {
4002 fBundleBitcode
= true;
4005 int standardLibraryPathsStartIndex
= libraryPaths
.size();
4006 int standardFrameworkPathsStartIndex
= frameworkPaths
.size();
4007 if ( addStandardLibraryDirectories
) {
4008 libraryPaths
.push_back("/usr/lib");
4009 libraryPaths
.push_back("/usr/local/lib");
4011 frameworkPaths
.push_back("/Library/Frameworks/");
4012 frameworkPaths
.push_back("/System/Library/Frameworks/");
4013 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
4016 // <rdar://problem/5829579> Support for configure based hacks
4017 // if last -syslibroot is /, then ignore all syslibroots
4018 if ( fSDKPaths
.size() > 0 ) {
4019 if ( strcmp(fSDKPaths
.back(), "/") == 0 ) {
4024 // now merge sdk and library paths to make real search paths
4025 fLibrarySearchPaths
.reserve(libraryPaths
.size()*(fSDKPaths
.size()+1));
4027 for (std::vector
<const char*>::iterator it
= libraryPaths
.begin(); it
!= libraryPaths
.end(); ++it
, ++libIndex
) {
4028 const char* libDir
= *it
;
4029 bool sdkOverride
= false;
4030 if ( libDir
[0] == '/' ) {
4031 char betterLibDir
[PATH_MAX
];
4032 if ( strstr(libDir
, "/..") != NULL
) {
4033 if ( realpath(libDir
, betterLibDir
) != NULL
)
4034 libDir
= strdup(betterLibDir
);
4036 const int libDirLen
= strlen(libDir
);
4037 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
4038 const char* sdkDir
= *sdkit
;
4039 const int sdkDirLen
= strlen(sdkDir
);
4040 char newPath
[libDirLen
+ sdkDirLen
+4];
4041 strcpy(newPath
, sdkDir
);
4042 if ( newPath
[sdkDirLen
-1] == '/' )
4043 newPath
[sdkDirLen
-1] = '\0';
4044 strcat(newPath
, libDir
);
4045 struct stat statBuffer
;
4046 if ( stat(newPath
, &statBuffer
) == 0 ) {
4047 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 ) {
4048 warning("-syslibroot and -L combined path '%s' is not a directory", newPath
);
4051 fLibrarySearchPaths
.push_back(strdup(newPath
));
4057 if ( !sdkOverride
) {
4058 if ( (libIndex
>= standardLibraryPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
4059 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
4060 // if one SDK is specified and a standard library path is not in the SDK, don't use it
4063 struct stat statBuffer
;
4064 if ( stat(libDir
, &statBuffer
) == 0 ) {
4065 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 )
4066 warning("-L path '%s' is not a directory", libDir
);
4068 fLibrarySearchPaths
.push_back(libDir
);
4070 else if ( !addStandardLibraryDirectories
|| (strcmp(libDir
, "/usr/local/lib") != 0) ) {
4071 warning("directory not found for option '-L%s'", libDir
);
4078 // now merge sdk and framework paths to make real search paths
4079 fFrameworkSearchPaths
.reserve(frameworkPaths
.size()*(fSDKPaths
.size()+1));
4081 for (std::vector
<const char*>::iterator it
= frameworkPaths
.begin(); it
!= frameworkPaths
.end(); ++it
, ++frameIndex
) {
4082 const char* frameworkDir
= *it
;
4083 bool sdkOverride
= false;
4084 if ( frameworkDir
[0] == '/' ) {
4085 char betterFrameworkDir
[PATH_MAX
];
4086 if ( strstr(frameworkDir
, "/..") != NULL
) {
4087 if ( realpath(frameworkDir
, betterFrameworkDir
) != NULL
)
4088 frameworkDir
= strdup(betterFrameworkDir
);
4090 const int frameworkDirLen
= strlen(frameworkDir
);
4091 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
4092 const char* sdkDir
= *sdkit
;
4093 const int sdkDirLen
= strlen(sdkDir
);
4094 char newPath
[frameworkDirLen
+ sdkDirLen
+4];
4095 strcpy(newPath
, sdkDir
);
4096 if ( newPath
[sdkDirLen
-1] == '/' )
4097 newPath
[sdkDirLen
-1] = '\0';
4098 strcat(newPath
, frameworkDir
);
4099 struct stat statBuffer
;
4100 if ( stat(newPath
, &statBuffer
) == 0 ) {
4101 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 ) {
4102 warning("-syslibroot and -F combined path '%s' is not a directory", newPath
);
4105 fFrameworkSearchPaths
.push_back(strdup(newPath
));
4111 if ( !sdkOverride
) {
4112 if ( (frameIndex
>= standardFrameworkPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
4113 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
4114 // if one SDK is specified and a standard library path is not in the SDK, don't use it
4117 struct stat statBuffer
;
4118 if ( stat(frameworkDir
, &statBuffer
) == 0 ) {
4119 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 )
4120 warning("-F path '%s' is not a directory", frameworkDir
);
4122 fFrameworkSearchPaths
.push_back(frameworkDir
);
4124 else if ( !addStandardLibraryDirectories
|| (strcmp(frameworkDir
, "/Library/Frameworks/") != 0) ) {
4125 warning("directory not found for option '-F%s'", frameworkDir
);
4132 fprintf(stderr
,"Library search paths:\n");
4133 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
4134 it
!= fLibrarySearchPaths
.end();
4136 fprintf(stderr
,"\t%s\n", *it
);
4137 fprintf(stderr
,"Framework search paths:\n");
4138 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
4139 it
!= fFrameworkSearchPaths
.end();
4141 fprintf(stderr
,"\t%s\n", *it
);
4145 // this is run before the command line is parsed
4146 void Options::parsePreCommandLineEnvironmentSettings()
4148 if ((getenv("LD_TRACE_ARCHIVES") != NULL
)
4149 || (getenv("RC_TRACE_ARCHIVES") != NULL
))
4150 fTraceArchives
= true;
4152 if ((getenv("LD_TRACE_DYLIBS") != NULL
)
4153 || (getenv("RC_TRACE_DYLIBS") != NULL
)) {
4154 fTraceDylibs
= true;
4155 fTraceIndirectDylibs
= true;
4158 if ((getenv("LD_TRACE_DEPENDENTS") != NULL
)) {
4160 fTraceEmitJSON
= true;
4163 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL
) {
4164 fTraceDylibSearching
= true;
4167 if (getenv("LD_PRINT_OPTIONS") != NULL
)
4168 fPrintOptions
= true;
4170 if (fTraceDylibs
|| fTraceArchives
|| fTraceEmitJSON
)
4171 fTraceOutputFile
= getenv("LD_TRACE_FILE");
4173 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL
)
4174 fPrintOrderFileStatistics
= true;
4176 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL
)
4179 if (getenv("LD_NO_ENCRYPT") != NULL
) {
4180 fEncryptable
= false;
4181 fMarkAppExtensionSafe
= true; // temporary
4182 fCheckAppExtensionSafe
= false;
4185 if (getenv("LD_APPLICATION_EXTENSION_SAFE") != NULL
) {
4186 fMarkAppExtensionSafe
= true;
4187 fCheckAppExtensionSafe
= false;
4190 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL
)
4191 fAllowCpuSubtypeMismatches
= true;
4193 if (getenv("LD_DYLIB_CPU_SUBTYPES_MUST_MATCH") != NULL
)
4194 fEnforceDylibSubtypesMatch
= true;
4196 sWarningsSideFilePath
= getenv("LD_WARN_FILE");
4198 const char* customDyldPath
= getenv("LD_DYLD_PATH");
4199 if ( customDyldPath
!= NULL
)
4200 fDyldInstallPath
= customDyldPath
;
4202 const char* debugArchivePath
= getenv("LD_DEBUG_SNAPSHOT");
4203 if (debugArchivePath
!= NULL
) {
4204 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
4205 if (strlen(debugArchivePath
) > 0)
4206 fLinkSnapshot
.setSnapshotPath(debugArchivePath
);
4207 fSnapshotRequested
= true;
4210 const char* pipeFdString
= getenv("LD_PIPELINE_FIFO");
4211 if (pipeFdString
!= NULL
) {
4212 fPipelineFifo
= pipeFdString
;
4217 // this is run after the command line is parsed
4218 void Options::parsePostCommandLineEnvironmentSettings()
4220 // when building a dynamic main executable, default any use of @executable_path to output path
4221 if ( fExecutablePath
== NULL
&& (fOutputKind
== kDynamicExecutable
) ) {
4222 fExecutablePath
= fOutputFile
;
4225 // allow build system to set default seg_addr_table
4226 if ( fSegAddrTablePath
== NULL
)
4227 fSegAddrTablePath
= getenv("LD_SEG_ADDR_TABLE");
4229 // allow build system to turn on prebinding
4231 fPrebind
= ( getenv("LD_PREBIND") != NULL
);
4234 // allow build system to force on dead-code-stripping
4235 if ( !fDeadStrip
) {
4236 if ( getenv("LD_DEAD_STRIP") != NULL
) {
4237 switch (fOutputKind
) {
4238 case Options::kDynamicLibrary
:
4239 case Options::kDynamicExecutable
:
4240 case Options::kDynamicBundle
:
4243 case Options::kPreload
:
4244 case Options::kObjectFile
:
4245 case Options::kDyld
:
4246 case Options::kStaticExecutable
:
4247 case Options::kKextBundle
:
4253 // allow build system to force on -warn_commons
4254 if ( getenv("LD_WARN_COMMONS") != NULL
)
4255 fWarnCommons
= true;
4257 // allow B&I to set default -source_version
4258 if ( fSourceVersion
== 0 ) {
4259 const char* vers
= getenv("RC_ProjectSourceVersion");
4261 fSourceVersion
= parseVersionNumber64(vers
);
4267 static bool sharedCacheEligiblePath(const char* path
)
4269 return ( (strncmp(path
, "/usr/lib/", 9) == 0) || (strncmp(path
, "/System/Library/", 16) == 0) );
4272 void Options::reconfigureDefaults()
4274 // sync reader options
4275 switch ( fOutputKind
) {
4276 case Options::kObjectFile
:
4277 fForFinalLinkedImage
= false;
4279 case Options::kDyld
:
4281 fForFinalLinkedImage
= true;
4284 case Options::kDynamicLibrary
:
4285 case Options::kDynamicBundle
:
4286 case Options::kKextBundle
:
4287 fForFinalLinkedImage
= true;
4290 case Options::kDynamicExecutable
:
4291 case Options::kStaticExecutable
:
4292 case Options::kPreload
:
4293 fLinkingMainExecutable
= true;
4294 fForFinalLinkedImage
= true;
4299 // set default min OS version
4300 if ( (fMacVersionMin
== ld::macVersionUnset
) && (fIOSVersionMin
== ld::iOSVersionUnset
) && (fWatchOSVersionMin
== ld::wOSVersionUnset
) ) {
4301 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
4302 const char* macVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
4303 const char* iPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
4304 const char* iOSVers
= getenv("IOS_DEPLOYMENT_TARGET");
4305 const char* wOSVers
= getenv("WATCHOS_DEPLOYMENT_TARGET");
4306 if ( macVers
!= NULL
)
4307 setMacOSXVersionMin(macVers
);
4308 else if ( iPhoneVers
!= NULL
)
4309 setIOSVersionMin(iPhoneVers
);
4310 else if ( iOSVers
!= NULL
)
4311 setIOSVersionMin(iOSVers
);
4312 else if ( wOSVers
!= NULL
)
4313 setWatchOSVersionMin(wOSVers
);
4315 // if still nothing, set default based on architecture
4316 switch ( fArchitecture
) {
4318 case CPU_TYPE_X86_64
:
4319 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
4320 #ifdef DEFAULT_MACOSX_MIN_VERSION
4321 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION
);
4322 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
4324 warning("-macosx_version_min not specified, assuming 10.6");
4325 setMacOSXVersionMin("10.6");
4330 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
4331 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
4332 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION
);
4333 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION
);
4335 if ( fSubArchitecture
== CPU_SUBTYPE_ARM_V7K
) {
4336 warning("-watchos_version_min not specified, assuming 2.0");
4337 setWatchOSVersionMin("2.0");
4340 warning("-ios_version_min not specified, assuming 6.0");
4341 setIOSVersionMin("6.0");
4347 // architecture will be infered later by examining .o files
4354 // adjust min based on architecture
4355 switch ( fArchitecture
) {
4357 if ( (fPlatform
== kPlatformOSX
) && (fMacVersionMin
< ld::mac10_4
) ) {
4358 //warning("-macosx_version_min should be 10.4 or later for i386");
4359 fMacVersionMin
= ld::mac10_4
;
4362 case CPU_TYPE_X86_64
:
4363 if ( (fPlatform
== kPlatformOSX
) && (fMacVersionMin
< ld::mac10_4
) ) {
4364 //warning("-macosx_version_min should be 10.4 or later for x86_64");
4365 fMacVersionMin
= ld::mac10_4
;
4368 case CPU_TYPE_ARM64
:
4369 if ( (fPlatform
== kPlatformiOS
) && (fIOSVersionMin
< ld::iOS_7_0
) ) {
4370 //warning("-mios_version_min should be 7.0 or later for arm64");
4371 fIOSVersionMin
= ld::iOS_7_0
;
4376 // default to adding functions start for dynamic code, static code must opt-in
4377 switch ( fOutputKind
) {
4378 case Options::kPreload
:
4379 case Options::kStaticExecutable
:
4380 case Options::kKextBundle
:
4381 if ( fDataInCodeInfoLoadCommandForcedOn
)
4382 fDataInCodeInfoLoadCommand
= true;
4383 if ( fFunctionStartsForcedOn
)
4384 fFunctionStartsLoadCommand
= true;
4386 case Options::kObjectFile
:
4387 if ( !fDataInCodeInfoLoadCommandForcedOff
)
4388 fDataInCodeInfoLoadCommand
= true;
4389 if ( fFunctionStartsForcedOn
)
4390 fFunctionStartsLoadCommand
= true;
4392 case Options::kDynamicExecutable
:
4393 case Options::kDyld
:
4394 case Options::kDynamicLibrary
:
4395 case Options::kDynamicBundle
:
4396 if ( !fDataInCodeInfoLoadCommandForcedOff
)
4397 fDataInCodeInfoLoadCommand
= true;
4398 if ( !fFunctionStartsForcedOff
)
4399 fFunctionStartsLoadCommand
= true;
4403 // adjust kext type based on architecture
4404 if ( fOutputKind
== kKextBundle
) {
4405 switch ( fArchitecture
) {
4406 case CPU_TYPE_X86_64
:
4407 // x86_64 uses new MH_KEXT_BUNDLE type
4408 fMakeCompressedDyldInfo
= false;
4409 fMakeCompressedDyldInfoForceOff
= true;
4410 fAllowTextRelocs
= true;
4411 fUndefinedTreatment
= kUndefinedDynamicLookup
;
4413 case CPU_TYPE_ARM64
:
4414 // arm64 uses new MH_KEXT_BUNDLE type
4415 fMakeCompressedDyldInfo
= false;
4416 fMakeCompressedDyldInfoForceOff
= true;
4417 fAllowTextRelocs
= false;
4418 fKextsUseStubs
= true;
4419 fUndefinedTreatment
= kUndefinedDynamicLookup
;
4422 if ( min_iOS(ld::iOS_5_0
) ) {
4423 // iOS 5.0 and later use new MH_KEXT_BUNDLE type
4424 fMakeCompressedDyldInfo
= false;
4425 fMakeCompressedDyldInfoForceOff
= true;
4426 // kexts are PIC in iOS 6.0 and later
4427 fAllowTextRelocs
= !min_iOS(ld::iOS_6_0
);
4428 fKextsUseStubs
= !fAllowTextRelocs
;
4429 fUndefinedTreatment
= kUndefinedDynamicLookup
;
4432 // else use object file
4435 fOutputKind
= kObjectFile
;
4440 // disable implicit dylibs when targeting 10.3
4441 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
4442 if ( !minOS(ld::mac10_4
, ld::iOS_2_0
) )
4443 fImplicitlyLinkPublicDylibs
= false;
4446 // allow build system to force linker to ignore -prebind
4447 if ( getenv("LD_FORCE_NO_PREBIND") != NULL
)
4450 // allow build system to force linker to ignore -seg_addr_table
4451 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL
)
4452 fSegAddrTablePath
= NULL
;
4454 // check for base address specified externally
4455 if ( (fSegAddrTablePath
!= NULL
) && (fOutputKind
== Options::kDynamicLibrary
) ) {
4456 parseSegAddrTable(fSegAddrTablePath
, this->installPath());
4457 // HACK to support seg_addr_table entries that are physical paths instead of install paths
4458 if ( fBaseAddress
== 0 ) {
4459 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
4460 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.4.dylib");
4461 if ( fBaseAddress
== 0 )
4462 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.9.dylib");
4465 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
4466 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libz.1.2.3.dylib");
4468 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
4469 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libutil1.0.dylib");
4473 // split segs only allowed for dylibs
4475 // split seg only supported for i386, and arm.
4476 switch ( fArchitecture
) {
4478 if ( fOutputKind
!= Options::kDynamicLibrary
)
4480 // make sure read and write segments are proper distance apart
4481 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x10000000) )
4482 fBaseWritableAddress
= fBaseAddress
+ 0x10000000;
4485 if ( fOutputKind
!= Options::kDynamicLibrary
) {
4489 // make sure read and write segments are proper distance apart
4490 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x08000000) )
4491 fBaseWritableAddress
= fBaseAddress
+ 0x08000000;
4497 fBaseWritableAddress
= 0;
4501 // set too-large size
4502 switch ( fArchitecture
) {
4504 fMaxAddress
= 0xFFFFFFFF;
4506 case CPU_TYPE_X86_64
:
4509 switch ( fOutputKind
) {
4510 case Options::kDynamicExecutable
:
4511 case Options::kDynamicLibrary
:
4512 case Options::kDynamicBundle
:
4513 // user land code is limited to low 1GB
4514 fMaxAddress
= 0x2FFFFFFF;
4516 case Options::kStaticExecutable
:
4517 case Options::kObjectFile
:
4518 case Options::kDyld
:
4519 case Options::kPreload
:
4520 case Options::kKextBundle
:
4521 fMaxAddress
= 0xFFFFFFFF;
4524 // range check -seg1addr for ARM
4525 if ( fBaseAddress
> fMaxAddress
) {
4526 warning("ignoring -seg1addr 0x%08llX. Address out of range.", fBaseAddress
);
4532 // <rdar://problem/6138961> -r implies no prebinding for all architectures
4533 if ( fOutputKind
== Options::kObjectFile
)
4536 // disable prebinding depending on arch and min OS version
4538 switch ( fArchitecture
) {
4540 if ( fMacVersionMin
== ld::mac10_4
) {
4541 // in 10.4 only split seg dylibs are prebound
4542 if ( (fOutputKind
!= Options::kDynamicLibrary
) || ! fSplitSegs
)
4545 else if ( fMacVersionMin
>= ld::mac10_5
) {
4546 // in 10.5 nothing is prebound
4549 else if ( fIOSVersionMin
!= ld::iOSVersionUnset
) {
4550 // nothing in simulator is prebound
4554 // in 10.3 and earlier only dylibs and main executables could be prebound
4555 switch ( fOutputKind
) {
4556 case Options::kDynamicExecutable
:
4557 case Options::kDynamicLibrary
:
4558 // only main executables and dylibs can be prebound
4560 case Options::kStaticExecutable
:
4561 case Options::kDynamicBundle
:
4562 case Options::kObjectFile
:
4563 case Options::kDyld
:
4564 case Options::kPreload
:
4565 case Options::kKextBundle
:
4566 // disable prebinding for everything else
4572 case CPU_TYPE_X86_64
:
4576 switch ( fOutputKind
) {
4577 case Options::kDynamicExecutable
:
4578 case Options::kDynamicLibrary
:
4579 // only main executables and dylibs can be prebound
4581 case Options::kStaticExecutable
:
4582 case Options::kDynamicBundle
:
4583 case Options::kObjectFile
:
4584 case Options::kDyld
:
4585 case Options::kPreload
:
4586 case Options::kKextBundle
:
4587 // disable prebinding for everything else
4595 // only prebound images can be split-seg
4596 if ( fSplitSegs
&& !fPrebind
)
4599 // determine if info for shared region should be added
4600 if ( fOutputKind
== Options::kDynamicLibrary
) {
4601 if ( minOS(ld::mac10_5
, ld::iOS_3_1
) )
4602 if ( !fPrebind
&& !fSharedRegionEligibleForceOff
)
4603 if ( sharedCacheEligiblePath(this->installPath()) )
4604 fSharedRegionEligible
= true;
4606 else if ( fOutputKind
== Options::kDyld
) {
4607 // <rdar://problem/10111122> Enable dyld to be put into the dyld shared cache
4608 fSharedRegionEligible
= true;
4611 // automatically use __DATA_CONST in iOS dylibs
4612 if ( fSharedRegionEligible
&& minOS(ld::mac10_Future
, ld::iOS_9_0
) && !fUseDataConstSegmentForceOff
&& !fTargetIOSSimulator
) {
4613 fUseDataConstSegment
= true;
4615 if ( fUseDataConstSegmentForceOn
) {
4616 fUseDataConstSegment
= true;
4618 // A -kext for iOS 10 ==> -data_const, -text_exec, -add_split_seg_info
4619 if ( (fOutputKind
== Options::kKextBundle
) && minOS(ld::mac10_Future
, ld::iOS_10_0
) && (fArchitecture
== CPU_TYPE_ARM64
) ) {
4620 fUseDataConstSegment
= true;
4621 fUseTextExecSegment
= true;
4622 fSharedRegionEligible
= true;
4624 if ( fUseDataConstSegment
) {
4625 addSectionRename("__DATA", "__got", "__DATA_CONST", "__got");
4626 addSectionRename("__DATA", "__la_symbol_ptr", "__DATA_CONST", "__la_symbol_ptr");
4627 addSectionRename("__DATA", "__nl_symbol_ptr", "__DATA_CONST", "__nl_symbol_ptr");
4628 addSectionRename("__DATA", "__const", "__DATA_CONST", "__const");
4629 addSectionRename("__DATA", "__cfstring", "__DATA_CONST", "__cfstring");
4630 addSectionRename("__DATA", "__mod_init_func", "__DATA_CONST", "__mod_init_func");
4631 addSectionRename("__DATA", "__mod_term_func", "__DATA_CONST", "__mod_term_func");
4632 addSectionRename("__DATA", "__objc_classlist", "__DATA_CONST", "__objc_classlist");
4633 addSectionRename("__DATA", "__objc_nlclslist", "__DATA_CONST", "__objc_nlclslist");
4634 addSectionRename("__DATA", "__objc_catlist", "__DATA_CONST", "__objc_catlist");
4635 addSectionRename("__DATA", "__objc_nlcatlist", "__DATA_CONST", "__objc_nlcatlist");
4636 addSectionRename("__DATA", "__objc_protolist", "__DATA_CONST", "__objc_protolist");
4637 addSectionRename("__DATA", "__objc_imageinfo", "__DATA_CONST", "__objc_imageinfo");
4638 addSectionRename("__DATA", "__objc_const", "__DATA_CONST", "__objc_const");
4640 if ( fUseTextExecSegment
) {
4641 addSectionRename("__TEXT", "__text", "__TEXT_EXEC", "__text");
4642 addSectionRename("__TEXT", "__stubs", "__TEXT_EXEC", "__stubs");
4645 // Use V2 shared cache info when targetting newer OSs
4646 if ( fSharedRegionEligible
&& minOS(ld::mac10_12
, ld::iOS_9_0
)) {
4647 fSharedRegionEncodingV2
= true;
4648 if ( fPlatform
== kPlatformOSX
) {
4649 fSharedRegionEncodingV2
= false;
4650 // <rdar://problem/24772435> only use v2 for Swift dylibs on Mac OS X
4651 if ( strncmp(this->installPath(), "/System/Library/PrivateFrameworks/Swift/", 40) == 0 )
4652 fSharedRegionEncodingV2
= true;
4653 // <rdar://problem/31428120> an other OS frameworks that use swift need v2
4654 for (const char* searchPath
: fLibrarySearchPaths
) {
4655 if ( strstr(searchPath
, "xctoolchain/usr/lib/swift/macos") != NULL
) {
4656 fSharedRegionEncodingV2
= true;
4661 fIgnoreOptimizationHints
= true;
4664 // figure out if module table is needed for compatibility with old ld/dyld
4665 if ( fOutputKind
== Options::kDynamicLibrary
) {
4666 switch ( fArchitecture
) {
4668 if ( fIOSVersionMin
!= ld::iOSVersionUnset
) // simulator never needs modules
4672 fNeedsModuleTable
= true; // redo_prebinding requires a module table
4677 // <rdar://problem/5366363> -r -x implies -S
4678 if ( (fOutputKind
== Options::kObjectFile
) && (fLocalSymbolHandling
== kLocalSymbolsNone
) )
4679 fDebugInfoStripping
= Options::kDebugInfoNone
;
4681 // <rdar://problem/15252891> -r implies -no_uuid
4682 if ( fOutputKind
== Options::kObjectFile
)
4683 fUUIDMode
= kUUIDNone
;
4685 // choose how to process unwind info
4686 switch ( fArchitecture
) {
4688 case CPU_TYPE_X86_64
:
4689 case CPU_TYPE_ARM64
:
4690 switch ( fOutputKind
) {
4691 case Options::kObjectFile
:
4692 case Options::kStaticExecutable
:
4693 case Options::kPreload
:
4694 case Options::kKextBundle
:
4695 fAddCompactUnwindEncoding
= false;
4697 case Options::kDyld
:
4698 case Options::kDynamicLibrary
:
4699 case Options::kDynamicBundle
:
4700 case Options::kDynamicExecutable
:
4701 //if ( fAddCompactUnwindEncoding && (fVersionMin >= ld::mac10_6) )
4702 // fRemoveDwarfUnwindIfCompactExists = true;
4707 if ( armUsesZeroCostExceptions() ) {
4708 switch ( fOutputKind
) {
4709 case Options::kObjectFile
:
4710 case Options::kStaticExecutable
:
4711 case Options::kPreload
:
4712 case Options::kKextBundle
:
4713 fAddCompactUnwindEncoding
= false;
4715 case Options::kDyld
:
4716 case Options::kDynamicLibrary
:
4717 case Options::kDynamicBundle
:
4718 case Options::kDynamicExecutable
:
4719 fAddCompactUnwindEncoding
= true;
4724 fAddCompactUnwindEncoding
= false;
4725 fRemoveDwarfUnwindIfCompactExists
= false;
4729 // if -arch is missing, assume we don't want compact unwind info
4730 fAddCompactUnwindEncoding
= false;
4734 // only iOS executables should be encryptable
4735 switch ( fOutputKind
) {
4736 case Options::kObjectFile
:
4737 case Options::kDyld
:
4738 case Options::kStaticExecutable
:
4739 case Options::kPreload
:
4740 case Options::kKextBundle
:
4741 fEncryptable
= false;
4743 case Options::kDynamicExecutable
:
4745 case Options::kDynamicLibrary
:
4746 case Options::kDynamicBundle
:
4747 // <rdar://problem/16293398> Add LC_ENCRYPTION_INFO load command to bundled frameworks
4748 if ( !min_iOS(ld::iOS_7_0
) )
4749 fEncryptable
= false;
4752 if ( (fArchitecture
!= CPU_TYPE_ARM
) && (fArchitecture
!= CPU_TYPE_ARM64
)
4754 fEncryptable
= false;
4755 if ( fEncryptableForceOn
)
4756 fEncryptable
= true;
4757 else if ( fEncryptableForceOff
)
4758 fEncryptable
= false;
4760 // don't move inits in dyld because dyld wants certain
4761 // entries point at stable locations at the start of __text
4762 if ( fOutputKind
== Options::kDyld
)
4763 fAutoOrderInitializers
= false;
4766 // disable __data ordering for some output kinds
4767 switch ( fOutputKind
) {
4768 case Options::kObjectFile
:
4769 case Options::kDyld
:
4770 case Options::kStaticExecutable
:
4771 case Options::kPreload
:
4772 case Options::kKextBundle
:
4775 case Options::kDynamicExecutable
:
4776 case Options::kDynamicLibrary
:
4777 case Options::kDynamicBundle
:
4781 // only use compressed LINKEDIT for final linked images
4782 switch ( fOutputKind
) {
4783 case Options::kDynamicExecutable
:
4784 case Options::kDynamicLibrary
:
4785 case Options::kDynamicBundle
:
4787 case Options::kPreload
:
4788 case Options::kStaticExecutable
:
4789 case Options::kObjectFile
:
4790 case Options::kDyld
:
4791 case Options::kKextBundle
:
4792 fMakeCompressedDyldInfoForceOff
= true;
4795 if ( fMakeCompressedDyldInfoForceOff
)
4796 fMakeCompressedDyldInfo
= false;
4799 // only use compressed LINKEDIT for:
4800 // Mac OS X 10.6 or later
4802 if ( fMakeCompressedDyldInfo
) {
4803 if ( !minOS(ld::mac10_6
, ld::iOS_3_1
) )
4804 fMakeCompressedDyldInfo
= false;
4807 // only ARM and x86_64 enforces that cpu-sub-types must match
4808 switch ( fArchitecture
) {
4811 case CPU_TYPE_X86_64
:
4812 fEnforceDylibSubtypesMatch
= false;
4815 case CPU_TYPE_ARM64
:
4816 fEnforceDylibSubtypesMatch
= false;
4821 // only final linked images can not optimize zero fill sections
4822 if ( fOutputKind
== Options::kObjectFile
)
4823 fOptimizeZeroFill
= true;
4825 // all undefines in -r mode
4826 // if ( fOutputKind == Options::kObjectFile )
4827 // fUndefinedTreatment = kUndefinedSuppress;
4829 // only dynamic final linked images should warn about use of commmons
4830 if ( fWarnCommons
) {
4831 switch ( fOutputKind
) {
4832 case Options::kDynamicExecutable
:
4833 case Options::kDynamicLibrary
:
4834 case Options::kDynamicBundle
:
4836 case Options::kPreload
:
4837 case Options::kStaticExecutable
:
4838 case Options::kObjectFile
:
4839 case Options::kDyld
:
4840 case Options::kKextBundle
:
4841 fWarnCommons
= false;
4846 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
4847 if ( minOS(ld::mac10_5
, ld::iOS_2_0
) )
4848 fUseSimplifiedDylibReExports
= true;
4850 // Mac OS X 10.7 and iOS 4.2 support LC_LOAD_UPWARD_DYLIB
4851 if ( minOS(ld::mac10_7
, ld::iOS_4_2
) && (fOutputKind
== kDynamicLibrary
) )
4852 fCanUseUpwardDylib
= true;
4854 // MacOSX 10.7 defaults to PIE
4855 if ( (fArchitecture
== CPU_TYPE_I386
)
4856 && (fOutputKind
== kDynamicExecutable
)
4857 && (fMacVersionMin
>= ld::mac10_7
) ) {
4858 fPositionIndependentExecutable
= true;
4861 // armv7 for iOS4.3 defaults to PIE
4862 if ( (fArchitecture
== CPU_TYPE_ARM
)
4863 && fArchSupportsThumb2
4864 && (fOutputKind
== kDynamicExecutable
)
4865 && min_iOS(ld::iOS_4_3
) ) {
4866 fPositionIndependentExecutable
= true;
4869 // <rdar://problem/24535196> x86_64 defaults PIE (regardless of minOS version)
4870 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
== kDynamicExecutable
) && (fMacVersionMin
>= ld::mac10_6
) )
4871 fPositionIndependentExecutable
= true;
4873 // Simulator defaults to PIE
4874 if ( fTargetIOSSimulator
&& (fOutputKind
== kDynamicExecutable
) )
4875 fPositionIndependentExecutable
= true;
4877 // -no_pie anywhere on command line disable PIE
4878 if ( fDisablePositionIndependentExecutable
)
4879 fPositionIndependentExecutable
= false;
4881 // arm64 is always PIE
4882 if ( ((fArchitecture
== CPU_TYPE_ARM64
)
4884 && (fOutputKind
== kDynamicExecutable
) ) {
4885 fPositionIndependentExecutable
= true;
4886 if ( fDisablePositionIndependentExecutable
)
4887 warning("-no_pie ignored for arm64");
4890 // set fOutputSlidable
4891 switch ( fOutputKind
) {
4892 case Options::kObjectFile
:
4893 fOutputSlidable
= false;
4895 case Options::kStaticExecutable
:
4896 case Options::kDynamicExecutable
:
4897 fOutputSlidable
= fPositionIndependentExecutable
;
4899 case Options::kPreload
:
4900 fOutputSlidable
= fPIEOnCommandLine
;
4902 case Options::kDyld
:
4903 case Options::kDynamicLibrary
:
4904 case Options::kDynamicBundle
:
4905 case Options::kKextBundle
:
4906 fOutputSlidable
= true;
4910 // let linker know if thread local variables are supported
4911 if ( fMacVersionMin
>= ld::mac10_7
) {
4914 else if ( ((fArchitecture
== CPU_TYPE_ARM64
)
4916 && min_iOS(ld::iOS_8_0
) ) {
4919 else if ( (fArchitecture
== CPU_TYPE_ARM
) && min_iOS(ld::iOS_9_0
) ) {
4922 else if ( fTargetIOSSimulator
&& (fArchitecture
== CPU_TYPE_X86_64
) && min_iOS(ld::iOS_8_0
) ) {
4925 else if ( fTargetIOSSimulator
&& (fArchitecture
== CPU_TYPE_I386
) && min_iOS(ld::iOS_9_0
) ) {
4929 // default to adding version load command for dynamic code, static code must opt-in
4930 switch ( fOutputKind
) {
4931 case Options::kObjectFile
:
4932 fVersionLoadCommand
= false;
4934 case Options::kStaticExecutable
:
4935 case Options::kPreload
:
4936 case Options::kKextBundle
:
4937 if ( fVersionLoadCommandForcedOn
)
4938 fVersionLoadCommand
= true;
4940 case Options::kDynamicExecutable
:
4941 case Options::kDyld
:
4942 case Options::kDynamicLibrary
:
4943 case Options::kDynamicBundle
:
4944 if ( !fVersionLoadCommandForcedOff
)
4945 fVersionLoadCommand
= true;
4949 // support re-export of individual symbols in MacOSX 10.7 and iOS 4.2
4950 if ( (fOutputKind
== kDynamicLibrary
) && minOS(ld::mac10_7
, ld::iOS_4_2
) )
4951 fCanReExportSymbols
= true;
4953 // ObjC optimization is only in dynamic final linked images
4954 switch ( fOutputKind
) {
4955 case Options::kObjectFile
:
4956 case Options::kStaticExecutable
:
4957 case Options::kPreload
:
4958 case Options::kKextBundle
:
4959 case Options::kDyld
:
4960 fObjcCategoryMerging
= false;
4962 case Options::kDynamicExecutable
:
4963 case Options::kDynamicLibrary
:
4964 case Options::kDynamicBundle
:
4968 // i386 main executables linked on Mac OS X 10.7 default to NX heap
4969 // regardless of target unless overriden with -allow_heap_execute anywhere
4970 // on the command line
4971 if ( (fArchitecture
== CPU_TYPE_I386
) && (fOutputKind
== kDynamicExecutable
) && !fDisableNonExecutableHeap
)
4972 fNonExecutableHeap
= true;
4974 // Use LC_MAIN instead of LC_UNIXTHREAD for newer OSs
4975 switch ( fOutputKind
) {
4976 case Options::kDynamicExecutable
:
4977 if ( fEntryPointLoadCommandForceOn
) {
4978 fEntryPointLoadCommand
= true;
4979 if ( fEntryName
== NULL
)
4980 fEntryName
= "_main";
4982 else if ( fEntryPointLoadCommandForceOff
) {
4983 fNeedsThreadLoadCommand
= true;
4984 if ( fEntryName
== NULL
)
4985 fEntryName
= "start";
4988 // <rdar://problem/16310363> Linker should look for "_main" not "start" when building for sim regardless of min OS
4989 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) || fTargetIOSSimulator
) {
4990 fEntryPointLoadCommand
= true;
4991 if ( fEntryName
== NULL
)
4992 fEntryName
= "_main";
4993 if ( strcmp(fEntryName
, "start") == 0 ) {
4994 warning("Ignoring '-e start' because entry point 'start' is not used for the targeted OS version");
4995 fEntryName
= "_main";
4999 fNeedsThreadLoadCommand
= true;
5000 if ( fEntryName
== NULL
)
5001 fEntryName
= "start";
5005 case Options::kObjectFile
:
5006 case Options::kKextBundle
:
5007 case Options::kDynamicLibrary
:
5008 case Options::kDynamicBundle
:
5011 case Options::kStaticExecutable
:
5012 case Options::kPreload
:
5013 case Options::kDyld
:
5014 fNeedsThreadLoadCommand
= true;
5015 if ( fEntryName
== NULL
)
5016 fEntryName
= "start"; // Perhaps these should have no default and require -e
5020 // add LC_SOURCE_VERSION
5021 switch ( fOutputKind
) {
5022 case Options::kDynamicExecutable
:
5023 case Options::kKextBundle
:
5024 case Options::kDynamicLibrary
:
5025 case Options::kDynamicBundle
:
5026 case Options::kDyld
:
5027 case Options::kStaticExecutable
:
5028 if ( fSourceVersionLoadCommandForceOn
) {
5029 fSourceVersionLoadCommand
= true;
5031 else if ( fSourceVersionLoadCommandForceOff
) {
5032 fSourceVersionLoadCommand
= false;
5035 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) ) {
5036 fSourceVersionLoadCommand
= true;
5039 fSourceVersionLoadCommand
= false;
5042 case Options::kObjectFile
:
5043 case Options::kPreload
:
5044 fSourceVersionLoadCommand
= false;
5048 // if -sdk_version not on command line, infer from -syslibroot
5049 if ( (fSDKVersion
== 0) && (fSDKPaths
.size() > 0) ) {
5050 const char* sdkPath
= fSDKPaths
.front();
5051 const char* end
= &sdkPath
[strlen(sdkPath
)-1];
5052 while ( !isdigit(*end
) && (end
> sdkPath
) )
5054 const char* start
= end
-1;
5055 while ( (isdigit(*start
) || (*start
== '.')) && (start
> sdkPath
))
5057 char sdkVersionStr
[32];
5058 int len
= end
-start
+1;
5060 strlcpy(sdkVersionStr
, start
+1, len
);
5061 fSDKVersion
= parseVersionNumber32(sdkVersionStr
);
5065 // if -sdk_version and -syslibroot not used, but targeting MacOSX, use current OS version
5066 if ( (fSDKVersion
== 0) && (fMacVersionMin
!= ld::macVersionUnset
) ) {
5067 // special case if RC_ProjectName and MACOSX_DEPLOYMENT_TARGET are both set that sdkversion=minos
5068 if ( getenv("RC_ProjectName") && getenv("MACOSX_DEPLOYMENT_TARGET") ) {
5069 fSDKVersion
= fMacVersionMin
;
5072 int mib
[2] = { CTL_KERN
, KERN_OSRELEASE
};
5073 char kernVersStr
[100];
5074 size_t strlen
= sizeof(kernVersStr
);
5075 if ( sysctl(mib
, 2, kernVersStr
, &strlen
, NULL
, 0) != -1 ) {
5076 uint32_t kernVers
= parseVersionNumber32(kernVersStr
);
5077 int minor
= (kernVers
>> 16) - 4; // kernel major version is 4 ahead of x in 10.x
5078 fSDKVersion
= 0x000A0000 + (minor
<< 8);
5083 // allow trie based absolute symbols if targeting new enough OS
5084 if ( fMakeCompressedDyldInfo
) {
5085 if ( minOS(ld::mac10_9
, ld::iOS_7_0
) ) {
5086 fAbsoluteSymbols
= true;
5090 // <rdar://problem/12959510> iOS main executables now default to 16KB page size
5091 if ( (fIOSVersionMin
!= ld::iOSVersionUnset
) && (fOutputKind
== Options::kDynamicExecutable
) ) {
5092 // <rdar://problem/13070042> Only third party apps should have 16KB page segments by default
5093 if ( fEncryptable
) {
5094 if ( fSegmentAlignment
== 4096 )
5095 fSegmentAlignment
= 4096*4;
5099 // <rdar://problem/12258065> ARM64 needs 16KB page size for user land code
5100 // <rdar://problem/15974532> make armv7[s] use 16KB pages in user land code for iOS 8 or later
5101 if ( fSegmentAlignment
== 4096 ) {
5102 switch ( fOutputKind
) {
5103 case Options::kDynamicExecutable
:
5104 case Options::kDynamicLibrary
:
5105 case Options::kDynamicBundle
:
5106 case Options::kDyld
:
5107 if ( ((fArchitecture
== CPU_TYPE_ARM64
)
5109 || ((fArchitecture
== CPU_TYPE_ARM
) && min_iOS(ld::iOS_7_0
)) ) {
5110 fSegmentAlignment
= 4096*4;
5113 case Options::kStaticExecutable
:
5114 case Options::kKextBundle
:
5115 // <rdar://problem/14676611> 16KB segments for arm64 kexts
5116 if ( ((fArchitecture
== CPU_TYPE_ARM64
)
5118 && min_iOS(ld::iOS_9_0
) ) {
5119 fSegmentAlignment
= 4096*4;
5122 case Options::kObjectFile
:
5123 case Options::kPreload
:
5130 // <rdar://problem/13624134> linker should not convert dwarf unwind if .o file has compact unwind section
5131 switch ( fOutputKind
) {
5132 case Options::kDynamicExecutable
:
5133 case Options::kDynamicLibrary
:
5134 case Options::kDynamicBundle
:
5135 case Options::kDyld
:
5136 if ( fKeepDwarfUnwindForcedOn
) {
5137 fKeepDwarfUnwind
= true;
5139 else if ( fKeepDwarfUnwindForcedOff
) {
5140 fKeepDwarfUnwind
= false;
5143 if ( minOS(ld::mac10_9
, ld::iOS_7_0
) )
5144 fKeepDwarfUnwind
= false;
5146 fKeepDwarfUnwind
= true;
5149 case Options::kKextBundle
:
5150 case Options::kStaticExecutable
:
5151 case Options::kObjectFile
:
5152 case Options::kPreload
:
5153 fKeepDwarfUnwind
= true;
5157 // Make sure -image_base matches alignment
5158 uint64_t alignedBaseAddress
= (fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
);
5159 if ( alignedBaseAddress
!= fBaseAddress
) {
5160 warning("base address 0x%llX is not properly aligned. Changing it to 0x%llX", fBaseAddress
, alignedBaseAddress
);
5161 fBaseAddress
= alignedBaseAddress
;
5164 // If -dirty_data_list not specified, look in $SDKROOT/AppleInternal/DirtyDataFiles/<dylib>.dirty for dirty data list
5165 if ( fSymbolsMovesData
.empty() && fUseDataConstSegment
&& ( fDylibInstallName
!= NULL
) && !fSDKPaths
.empty() ) {
5166 const char* dylibLeaf
= strrchr(fDylibInstallName
, '/');
5168 char path
[PATH_MAX
];
5169 strlcpy(path
, fSDKPaths
.front(), sizeof(path
));
5170 strlcat(path
, "/AppleInternal/DirtyDataFiles", sizeof(path
));
5171 strlcat(path
, dylibLeaf
, sizeof(path
));
5172 strlcat(path
, ".dirty", sizeof(path
));
5174 if ( info
.checkFileExists(*this, path
) )
5175 addSymbolMove("__DATA_DIRTY", path
, fSymbolsMovesData
, "-dirty_data_list");
5180 // <rdar://problem/32138080> Automatically use OrderFiles found in the AppleInternal SDK
5181 if ( (fFinalName
!= NULL
) && fOrderedSymbols
.empty() && !fSDKPaths
.empty() ) {
5182 char path
[PATH_MAX
];
5183 strlcpy(path
, fSDKPaths
.front(), sizeof(path
));
5184 strlcat(path
, "/AppleInternal/OrderFiles/", sizeof(path
));
5185 strlcat(path
, fFinalName
, sizeof(path
));
5186 strlcat(path
, ".order", sizeof(path
));
5188 if ( info
.checkFileExists(*this, path
) )
5189 parseOrderFile(path
, false);
5192 // <rdar://problem/20503811> Reduce the default alignment of structures/arrays to save memory in embedded systems
5193 if ( fMaxDefaultCommonAlign
== 0 ) {
5194 if ( fOutputKind
== Options::kPreload
)
5195 fMaxDefaultCommonAlign
= 8;
5197 fMaxDefaultCommonAlign
= 15;
5200 // Add warnings for issues likely to cause OS verification issues
5201 if ( fSharedRegionEligible
&& !fRPaths
.empty() ) {
5202 // <rdar://problem/18719327> warn if -rpath is used with OS dylibs
5203 warning("OS dylibs should not add rpaths (linker option: -rpath) (Xcode build setting: LD_RUNPATH_SEARCH_PATHS)");
5205 if ( (fOutputKind
== Options::kDynamicLibrary
) && (fDylibInstallName
!= NULL
) && (fFinalName
!= NULL
) && sharedCacheEligiblePath(fFinalName
) ) {
5206 if ( strncmp(fDylibInstallName
, "@rpath", 6) == 0 )
5207 warning("OS dylibs should not use @rpath for -install_name. Use absolute path instead");
5208 if ( strcmp(fDylibInstallName
, fFinalName
) != 0 ) {
5209 bool different
= true;
5210 // some projects end up with double slash in -final_output path
5211 if ( strstr(fFinalName
, "//") != NULL
) {
5212 char fixedPath
[strlen(fFinalName
)+1];
5213 char* t
= fixedPath
;
5214 bool lastWasSlash
= false;
5215 for (const char* s
=fFinalName
; *s
!= '\0'; ++s
) {
5217 if ( !lastWasSlash
)
5219 lastWasSlash
= true;
5223 lastWasSlash
= false;
5227 different
= (strcmp(fDylibInstallName
, fixedPath
) != 0);
5230 warning("OS dylibs -install_name should match its real absolute path");
5234 // set if unaligned pointers are warnings or errors
5235 if ( fMacVersionMin
>= ld::mac10_12
) {
5236 // ignore unaligned pointers when targeting older macOS versions
5237 if ( fSharedRegionEligible
)
5238 fUnalignedPointerTreatment
= Options::kUnalignedPointerWarning
;
5240 fUnalignedPointerTreatment
= Options::kUnalignedPointerIgnore
;
5242 else if ( min_iOS(ld::iOS_10_0
) ) {
5243 fUnalignedPointerTreatment
= Options::kUnalignedPointerWarning
;
5246 fUnalignedPointerTreatment
= Options::kUnalignedPointerIgnore
;
5251 void Options::checkIllegalOptionCombinations()
5253 // check -undefined setting
5254 switch ( fUndefinedTreatment
) {
5255 case kUndefinedError
:
5258 case kUndefinedDynamicLookup
:
5259 switch (fPlatform
) {
5263 case kPlatformWatchOS
:
5264 case kPlatform_bridgeOS
:
5265 #if SUPPORT_APPLE_TV
5266 case kPlatform_tvOS
:
5268 if ( fOutputKind
!= kKextBundle
)
5269 warning("-undefined dynamic_lookup is deprecated on %s", platformName(fPlatform
));
5275 case kUndefinedWarning
:
5276 case kUndefinedSuppress
:
5277 // requires flat namespace
5278 if ( fNameSpace
== kTwoLevelNameSpace
)
5279 throw "can't use -undefined warning or suppress with -twolevel_namespace";
5283 // unify -sub_umbrella with dylibs
5284 for (std::vector
<const char*>::iterator it
= fSubUmbellas
.begin(); it
!= fSubUmbellas
.end(); it
++) {
5285 const char* subUmbrella
= *it
;
5287 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
5288 Options::FileInfo
& info
= *fit
;
5289 const char* lastSlash
= strrchr(info
.path
, '/');
5290 if ( lastSlash
== NULL
)
5291 lastSlash
= info
.path
- 1;
5292 std::string
path(&lastSlash
[1]);
5293 auto idx
= path
.find(".tbd", path
.size() - 4);
5294 if (idx
!= std::string::npos
)
5296 if ( path
== subUmbrella
) {
5297 info
.options
.fReExport
= true;
5299 fLinkSnapshot
.recordSubUmbrella(info
.path
);
5304 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella
);
5307 // unify -sub_library with dylibs
5308 for (std::vector
<const char*>::iterator it
= fSubLibraries
.begin(); it
!= fSubLibraries
.end(); it
++) {
5309 const char* subLibrary
= *it
;
5311 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
5312 Options::FileInfo
& info
= *fit
;
5313 const char* lastSlash
= strrchr(info
.path
, '/');
5314 if ( lastSlash
== NULL
)
5315 lastSlash
= info
.path
- 1;
5316 const char* dot
= strchr(&lastSlash
[1], '.');
5318 dot
= &lastSlash
[strlen(lastSlash
)];
5319 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
5320 info
.options
.fReExport
= true;
5322 fLinkSnapshot
.recordSubLibrary(info
.path
);
5327 warning("-sub_library %s does not match a supplied dylib", subLibrary
);
5330 // sync reader options
5331 if ( fNameSpace
!= kTwoLevelNameSpace
) {
5332 fFlatNamespace
= true;
5333 switch (fPlatform
) {
5337 case kPlatformWatchOS
:
5338 case kPlatform_bridgeOS
:
5339 #if SUPPORT_APPLE_TV
5340 case Options::kPlatform_tvOS
:
5342 warning("-flat_namespace is deprecated on %s", platformName(fPlatform
));
5350 // check -stack_addr
5351 if ( fStackAddr
!= 0 ) {
5352 switch (fArchitecture
) {
5355 if ( fStackAddr
> 0xFFFFFFFF )
5356 throw "-stack_addr must be < 4G for 32-bit processes";
5358 case CPU_TYPE_X86_64
:
5359 case CPU_TYPE_ARM64
:
5362 if ( (fStackAddr
& -4096) != fStackAddr
)
5363 throw "-stack_addr must be multiples of 4K";
5364 if ( fStackSize
== 0 )
5365 throw "-stack_addr must be used with -stack_size";
5368 // check -stack_size
5369 if ( fStackSize
!= 0 ) {
5370 switch (fArchitecture
) {
5372 if ( fPlatform
== kPlatformOSX
) {
5373 if ( fStackSize
> 0xFFFFFFFF )
5374 throw "-stack_size must be < 4GB for 32-bit processes";
5375 if ( fStackAddr
== 0 )
5376 fStackAddr
= 0xC0000000;
5377 if ( (fStackAddr
> 0xB0000000) && ((fStackAddr
-fStackSize
) < 0xB0000000) )
5378 warning("custom stack placement overlaps and will disable shared region");
5381 if ( fStackSize
> 0x1F000000 )
5382 throw "-stack_size must be < 496MB";
5383 if ( fStackAddr
== 0 )
5384 fStackAddr
= 0xC0000000;
5388 if ( fStackSize
> 0x1F000000 )
5389 throw "-stack_size must be < 496MB";
5390 if ( fStackAddr
== 0 )
5391 fStackAddr
= 0x1F000000;
5392 if ( fStackAddr
> 0x20000000)
5393 throw "-stack_addr must be < 0x20000000 for arm";
5395 case CPU_TYPE_X86_64
:
5396 if ( fPlatform
== kPlatformOSX
) {
5397 if ( fStackSize
> 0x10000000000 )
5398 throw "-stack_size must be <= 1TB";
5399 if ( fStackAddr
== 0 ) {
5400 fStackAddr
= 0x00007FFF5C000000LL
;
5404 if ( fStackSize
> 0x20000000 )
5405 throw "-stack_size must be <= 512MB";
5406 if ( fStackAddr
== 0 ) {
5407 fStackAddr
= 0x120000000;
5410 case CPU_TYPE_ARM64
:
5411 if ( fStackSize
> 0x20000000 )
5412 throw "-stack_size must be <= 512MB";
5413 if ( fStackAddr
== 0 )
5414 fStackAddr
= 0x120000000;
5418 if ( (fStackSize
& (-fSegmentAlignment
)) != fStackSize
)
5419 throwf("-stack_size must be multiple of segment alignment (%lldKB)", fSegmentAlignment
/1024);
5420 switch ( fOutputKind
) {
5421 case Options::kDynamicExecutable
:
5422 case Options::kStaticExecutable
:
5423 // custom stack size only legal when building main executable
5425 case Options::kDynamicLibrary
:
5426 case Options::kDynamicBundle
:
5427 case Options::kObjectFile
:
5428 case Options::kDyld
:
5429 case Options::kPreload
:
5430 case Options::kKextBundle
:
5431 throw "-stack_size option can only be used when linking a main executable";
5433 if ( fStackSize
> fStackAddr
)
5434 throwf("-stack_size (0x%08llX) must be smaller than -stack_addr (0x%08llX)", fStackSize
, fStackAddr
);
5437 // check that -allow_stack_execute is only used with main executables
5438 if ( fExecutableStack
) {
5439 switch ( fOutputKind
) {
5440 case Options::kDynamicExecutable
:
5441 case Options::kStaticExecutable
:
5442 // -allow_stack_execute size only legal when building main executable
5444 case Options::kDynamicLibrary
:
5445 case Options::kDynamicBundle
:
5446 case Options::kObjectFile
:
5447 case Options::kDyld
:
5448 case Options::kPreload
:
5449 case Options::kKextBundle
:
5450 throw "-allow_stack_execute option can only be used when linking a main executable";
5454 // check that -allow_heap_execute is only used with i386 main executables
5455 if ( fDisableNonExecutableHeap
) {
5456 if ( fArchitecture
!= CPU_TYPE_I386
)
5457 throw "-allow_heap_execute option can only be used when linking for i386";
5458 switch ( fOutputKind
) {
5459 case Options::kDynamicExecutable
:
5460 // -allow_heap_execute only legal when building main executable
5462 case Options::kStaticExecutable
:
5463 case Options::kDynamicLibrary
:
5464 case Options::kDynamicBundle
:
5465 case Options::kObjectFile
:
5466 case Options::kDyld
:
5467 case Options::kPreload
:
5468 case Options::kKextBundle
:
5469 throw "-allow_heap_execute option can only be used when linking a main executable";
5473 // check -client_name is only used when making a bundle or main executable
5474 if ( fClientName
!= NULL
) {
5475 switch ( fOutputKind
) {
5476 case Options::kDynamicExecutable
:
5477 case Options::kDynamicBundle
:
5479 case Options::kStaticExecutable
:
5480 case Options::kDynamicLibrary
:
5481 case Options::kObjectFile
:
5482 case Options::kDyld
:
5483 case Options::kPreload
:
5484 case Options::kKextBundle
:
5485 throw "-client_name can only be used with -bundle";
5489 // check -init is only used when building a dylib
5490 if ( (fInitFunctionName
!= NULL
) && (fOutputKind
!= Options::kDynamicLibrary
) )
5491 throw "-init can only be used with -dynamiclib";
5493 // check -bundle_loader only used with -bundle
5494 if ( (fBundleLoader
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
5495 throw "-bundle_loader can only be used with -bundle";
5497 // check -dtrace not used with -r
5498 if ( (fDtraceScriptName
!= NULL
) && (fOutputKind
== Options::kObjectFile
) )
5499 throw "-dtrace can only be used when creating final linked images";
5501 // check -d can only be used with -r
5502 if ( fMakeTentativeDefinitionsReal
&& (fOutputKind
!= Options::kObjectFile
) )
5503 throw "-d can only be used with -r";
5505 // check that -root_safe is not used with -r
5506 if ( fRootSafe
&& (fOutputKind
== Options::kObjectFile
) )
5507 throw "-root_safe cannot be used with -r";
5509 // check that -setuid_safe is not used with -r
5510 if ( fSetuidSafe
&& (fOutputKind
== Options::kObjectFile
) )
5511 throw "-setuid_safe cannot be used with -r";
5513 // <rdar://problem/12781832> compiler driver no longer uses -objc_abi_version, it uses -ios_simulator_version_min instead
5514 if ( !fObjCABIVersion1Override
&& !fObjCABIVersion2Override
&& fTargetIOSSimulator
)
5515 fObjCABIVersion2Override
= true;
5517 // rdar://problem/4718189 map ObjC class names to new runtime names
5518 bool alterObjC1ClassNamesToObjC2
= false;
5519 switch (fArchitecture
) {
5521 // i386 only uses new symbols when using objc2 ABI
5522 if ( fObjCABIVersion2Override
)
5523 alterObjC1ClassNamesToObjC2
= true;
5525 case CPU_TYPE_X86_64
:
5527 case CPU_TYPE_ARM64
:
5528 alterObjC1ClassNamesToObjC2
= true;
5532 // make sure all required exported symbols exist
5533 std::vector
<const char*> impliedExports
;
5534 for (NameSet::iterator it
=fExportSymbols
.regularBegin(); it
!= fExportSymbols
.regularEnd(); ++it
) {
5535 const char* name
= *it
;
5536 const int len
= strlen(name
);
5537 if ( (strcmp(&name
[len
-3], ".eh") == 0) || (strncmp(name
, ".objc_category_name_", 20) == 0) ) {
5538 // never export .eh symbols
5539 warning("ignoring %s in export list", name
);
5541 else if ( (fArchitecture
== CPU_TYPE_I386
) && !fObjCABIVersion2Override
&& (strncmp(name
, "_OBJC_CLASS_$", 13) == 0) ) {
5542 warning("ignoring Objc2 Class symbol %s in i386 export list", name
);
5543 fRemovedExports
.insert(name
);
5545 else if ( alterObjC1ClassNamesToObjC2
&& (strncmp(name
, ".objc_class_name_", 17) == 0) ) {
5546 // linking ObjC2 ABI, but have ObjC1 ABI name in export list. Change it to intended name
5547 fRemovedExports
.insert(name
);
5549 asprintf(&temp
, "_OBJC_CLASS_$_%s", &name
[17]);
5550 impliedExports
.push_back(temp
);
5551 asprintf(&temp
, "_OBJC_METACLASS_$_%s", &name
[17]);
5552 impliedExports
.push_back(temp
);
5555 fInitialUndefines
.push_back(name
);
5558 fExportSymbols
.remove(fRemovedExports
);
5559 for (std::vector
<const char*>::iterator it
=impliedExports
.begin(); it
!= impliedExports
.end(); ++it
) {
5560 const char* name
= *it
;
5561 fExportSymbols
.insert(name
);
5562 fInitialUndefines
.push_back(name
);
5565 // make sure all required re-exported symbols exist
5566 for (NameSet::iterator it
=fReExportSymbols
.regularBegin(); it
!= fReExportSymbols
.regularEnd(); ++it
) {
5567 fInitialUndefines
.push_back(*it
);
5570 // make sure that -init symbol exists
5571 if ( fInitFunctionName
!= NULL
)
5572 fInitialUndefines
.push_back(fInitFunctionName
);
5574 // make sure that entry symbol exists
5575 switch ( fOutputKind
) {
5576 case Options::kDynamicExecutable
:
5577 case Options::kStaticExecutable
:
5578 case Options::kDyld
:
5579 case Options::kPreload
:
5580 fInitialUndefines
.push_back(fEntryName
);
5582 case Options::kDynamicLibrary
:
5583 case Options::kDynamicBundle
:
5584 case Options::kObjectFile
:
5585 case Options::kKextBundle
:
5589 // make sure every alias base exists
5590 for (std::vector
<AliasPair
>::iterator it
=fAliases
.begin(); it
!= fAliases
.end(); ++it
) {
5591 fInitialUndefines
.push_back(it
->realName
);
5594 // check custom segments
5595 if ( fCustomSegmentAddresses
.size() != 0 ) {
5596 // verify no segment is in zero page
5597 if ( fZeroPageSize
!= ULLONG_MAX
) {
5598 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
5599 if ( it
->address
< fZeroPageSize
)
5600 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it
->name
, it
->address
);
5603 // verify no duplicates
5604 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
5605 for (std::vector
<SegmentStart
>::iterator it2
= fCustomSegmentAddresses
.begin(); it2
!= fCustomSegmentAddresses
.end(); ++it2
) {
5606 if ( (it
->address
== it2
->address
) && (it
!= it2
) )
5607 throwf("duplicate -segaddr addresses for %s and %s", it
->name
, it2
->name
);
5609 // a custom segment address of zero will disable the use of a zero page
5610 if ( it
->address
== 0 )
5615 if ( fZeroPageSize
== ULLONG_MAX
) {
5616 // zero page size not specified on command line, set default
5617 switch (fArchitecture
) {
5620 // first 4KB for 32-bit architectures
5621 fZeroPageSize
= 0x1000;
5623 case CPU_TYPE_ARM64
:
5624 case CPU_TYPE_X86_64
:
5625 // first 4GB for x86_64 on all OS's
5626 fZeroPageSize
= 0x100000000ULL
;
5629 // if -arch not used, default to 4K zero-page
5630 fZeroPageSize
= 0x1000;
5634 switch ( fOutputKind
) {
5635 case Options::kDynamicExecutable
:
5636 case Options::kStaticExecutable
:
5637 // -pagezero_size size only legal when building main executable
5639 case Options::kDynamicLibrary
:
5640 case Options::kDynamicBundle
:
5641 case Options::kObjectFile
:
5642 case Options::kDyld
:
5643 case Options::kPreload
:
5644 case Options::kKextBundle
:
5645 if ( fZeroPageSize
!= 0 )
5646 throw "-pagezero_size option can only be used when linking a main executable";
5650 // if main executable with custom base address, model zero page as custom segment
5651 if ( (fOutputKind
== Options::kDynamicExecutable
) && (fBaseAddress
!= 0) && (fZeroPageSize
!= 0) ) {
5653 seg
.name
= "__PAGEZERO";
5655 fCustomSegmentAddresses
.push_back(seg
);
5658 // -dead_strip and -r are incompatible
5659 if ( fDeadStrip
&& (fOutputKind
== Options::kObjectFile
) )
5660 throw "-r and -dead_strip cannot be used together";
5662 // can't use -rpath unless targeting 10.5 or later
5663 if ( fRPaths
.size() > 0 ) {
5664 if ( !minOS(ld::mac10_5
, ld::iOS_2_0
) )
5665 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
5666 switch ( fOutputKind
) {
5667 case Options::kDynamicExecutable
:
5668 case Options::kDynamicLibrary
:
5669 case Options::kDynamicBundle
:
5671 case Options::kStaticExecutable
:
5672 case Options::kObjectFile
:
5673 case Options::kDyld
:
5674 case Options::kPreload
:
5675 case Options::kKextBundle
:
5676 throw "-rpath can only be used when creating a dynamic final linked image";
5680 if ( fPositionIndependentExecutable
) {
5681 switch ( fOutputKind
) {
5682 case Options::kDynamicExecutable
:
5683 // check -pie is only used when building a dynamic main executable for 10.5
5684 if ( !minOS(ld::mac10_5
, ld::iOS_4_2
) ) {
5685 if ( fIOSVersionMin
== ld::iOSVersionUnset
)
5686 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
5688 throw "-pie can only be used when targeting iOS 4.2 or later";
5691 case Options::kStaticExecutable
:
5692 case Options::kPreload
:
5693 // -pie is ok with -static or -preload
5695 case Options::kDynamicLibrary
:
5696 case Options::kDynamicBundle
:
5697 warning("-pie being ignored. It is only used when linking a main executable");
5698 fPositionIndependentExecutable
= false;
5700 case Options::kObjectFile
:
5701 case Options::kDyld
:
5702 case Options::kKextBundle
:
5703 throw "-pie can only be used when linking a main executable";
5707 // check -read_only_relocs is not used with x86_64
5708 if ( fAllowTextRelocs
) {
5709 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
!= kKextBundle
) ) {
5710 warning("-read_only_relocs cannot be used with x86_64");
5711 fAllowTextRelocs
= false;
5715 // check -mark_auto_dead_strip is only used with dylibs
5716 if ( fMarkDeadStrippableDylib
) {
5717 if ( fOutputKind
!= Options::kDynamicLibrary
) {
5718 warning("-mark_auto_dead_strip can only be used when creating a dylib");
5719 fMarkDeadStrippableDylib
= false;
5723 // -force_cpusubtype_ALL is not supported for ARM
5724 if ( fForceSubtypeAll
) {
5725 if ( fArchitecture
== CPU_TYPE_ARM
) {
5726 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
5730 // -reexported_symbols_list can only be used with -dynamiclib
5731 if ( !fReExportSymbols
.empty() ) {
5732 if ( fOutputKind
!= Options::kDynamicLibrary
)
5733 throw "-reexported_symbols_list can only used used when created dynamic libraries";
5734 if ( !minOS(ld::mac10_7
, ld::iOS_4_2
) )
5735 throw "targeted OS version does not support -reexported_symbols_list";
5738 // -dyld_env can only be used with main executables
5739 if ( (fOutputKind
!= Options::kDynamicExecutable
) && (fDyldEnvironExtras
.size() != 0) )
5740 throw "-dyld_env can only used used when created main executables";
5742 // -segment_order can only be used with -preload or -static
5743 if ( !fSegmentOrder
.empty() && ((fOutputKind
!= Options::kPreload
) && (fOutputKind
!= kStaticExecutable
)) )
5744 throw "-segment_order can only used used with -preload output";
5746 // warn about bitcode option combinations
5747 if ( !fBundleBitcode
) {
5748 if ( fVerifyBitcode
)
5749 warning("-bitcode_verify is ignored without -bitcode_bundle");
5750 else if ( fHideSymbols
)
5751 warning("-bitcode_hide_symbols is ignored without -bitcode_bundle");
5753 if ( fReverseMapPath
!= NULL
&& !fHideSymbols
) {
5754 throw "-bitcode_symbol_map can only be used with -bitcode_hide_symbols";
5756 // auto fix up the process type for strip -S.
5757 // when there is only one input and output type is object file, downgrade kBitcodeProcess to kBitcodeAsData.
5758 if ( fOutputKind
== Options::kObjectFile
&& fInputFiles
.size() == 1 && fBitcodeKind
== Options::kBitcodeProcess
)
5759 fBitcodeKind
= Options::kBitcodeAsData
;
5761 // <rdar://problem/17598404> warn if building an embedded iOS dylib for pre-iOS 8
5762 // <rdar://problem/18935714> How can we suppress "ld: warning: embedded dylibs/frameworks only run on iOS 8 or later" when building XCTest?
5763 if ( (fOutputKind
== Options::kDynamicLibrary
) && (fIOSVersionMin
!= ld::iOSVersionUnset
) && (fDylibInstallName
!= NULL
) ) {
5764 if ( !min_iOS(ld::iOS_8_0
) && (fDylibInstallName
[0] == '@') && !fEncryptableForceOff
)
5765 warning("embedded dylibs/frameworks only run on iOS 8 or later");
5768 // bridgeOS always generates new load command
5769 if ( fVersionLoadCommand
&& (fPlatform
== kPlatform_bridgeOS
) ) {
5770 fBuildVersionLoadCommand
= true;
5773 // produce nicer error when no input
5774 if ( fInputFiles
.empty() ) {
5775 throw "no object files specified";
5780 void Options::checkForClassic(int argc
, const char* argv
[])
5783 bool archFound
= false;
5784 bool staticFound
= false;
5785 bool dtraceFound
= false;
5786 bool kextFound
= false;
5787 bool rFound
= false;
5788 bool creatingMachKernel
= false;
5789 bool newLinker
= false;
5791 // build command line buffer in case ld crashes
5792 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
5793 CRSetCrashLogMessage(crashreporterBuffer
);
5795 const char* srcRoot
= getenv("SRCROOT");
5796 if ( srcRoot
!= NULL
) {
5797 strlcpy(crashreporterBuffer
, "SRCROOT=", crashreporterBufferSize
);
5798 strlcat(crashreporterBuffer
, srcRoot
, crashreporterBufferSize
);
5799 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
5802 strlcat(crashreporterBuffer
, LD_VERS
, crashreporterBufferSize
);
5803 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
5805 strlcat(crashreporterBuffer
, "ld ", crashreporterBufferSize
);
5806 for(int i
=1; i
< argc
; ++i
) {
5807 strlcat(crashreporterBuffer
, argv
[i
], crashreporterBufferSize
);
5808 strlcat(crashreporterBuffer
, " ", crashreporterBufferSize
);
5811 for(int i
=0; i
< argc
; ++i
) {
5812 const char* arg
= argv
[i
];
5813 if ( arg
[0] == '-' ) {
5814 if ( strcmp(arg
, "-arch") == 0 ) {
5815 parseArch(argv
[++i
]);
5818 else if ( strcmp(arg
, "-static") == 0 ) {
5821 else if ( strcmp(arg
, "-kext") == 0 ) {
5824 else if ( strcmp(arg
, "-dtrace") == 0 ) {
5827 else if ( strcmp(arg
, "-r") == 0 ) {
5830 else if ( strcmp(arg
, "-new_linker") == 0 ) {
5833 else if ( strcmp(arg
, "-classic_linker") == 0 ) {
5834 // ld_classic does not understand this option, so remove it
5835 for(int j
=i
; j
< argc
; ++j
)
5836 argv
[j
] = argv
[j
+1];
5837 warning("using ld_classic");
5838 this->gotoClassicLinker(argc
-1, argv
);
5840 else if ( strcmp(arg
, "-o") == 0 ) {
5841 const char* outfile
= argv
[++i
];
5842 if ( (outfile
!= NULL
) && (strstr(outfile
, "/mach_kernel") != NULL
) )
5843 creatingMachKernel
= true;
5849 void Options::gotoClassicLinker(int argc
, const char* argv
[])
5851 argv
[0] = "ld_classic";
5852 // ld_classic does not support -iphoneos_version_min, so change
5853 for(int j
=0; j
< argc
; ++j
) {
5854 if ( (strcmp(argv
[j
], "-iphoneos_version_min") == 0) || (strcmp(argv
[j
], "-ios_version_min") == 0) ) {
5855 argv
[j
] = "-macosx_version_min";
5861 // ld classic does not understand -kext (change to -static -r)
5862 for(int j
=0; j
< argc
; ++j
) {
5863 if ( strcmp(argv
[j
], "-kext") == 0)
5865 else if ( strcmp(argv
[j
], "-dynamic") == 0)
5866 argv
[j
] = "-static";
5868 // ld classic does not understand -demangle
5869 for(int j
=0; j
< argc
; ++j
) {
5870 if ( strcmp(argv
[j
], "-demangle") == 0)
5871 argv
[j
] = "-noprebind";
5873 // in -v mode, print command line passed to ld_classic
5874 for(int i
=0; i
< argc
; ++i
) {
5875 if ( strcmp(argv
[i
], "-v") == 0 ) {
5876 for(int j
=0; j
< argc
; ++j
)
5877 printf("%s ", argv
[j
]);
5882 char rawPath
[PATH_MAX
];
5883 char path
[PATH_MAX
];
5884 uint32_t bufSize
= PATH_MAX
;
5885 if ( _NSGetExecutablePath(rawPath
, &bufSize
) != -1 ) {
5886 if ( realpath(rawPath
, path
) != NULL
) {
5887 char* lastSlash
= strrchr(path
, '/');
5888 if ( lastSlash
!= NULL
) {
5889 strcpy(lastSlash
+1, "ld_classic");
5891 execvp(path
, (char**)argv
);
5895 // in case of error in above, try searching for ld_classic via PATH
5896 execvp(argv
[0], (char**)argv
);
5897 fprintf(stderr
, "can't exec ld_classic\n");
5902 // Note, returned string buffer is own by this function.
5903 // It should not be freed
5904 // It will be reused, so clients need to strdup() if they want
5905 // to use it long term.
5906 const char* Options::demangleSymbol(const char* sym
) const
5908 // only try to demangle symbols if -demangle on command line
5912 static size_t size
= 1024;
5913 static char* buff
= (char*)malloc(size
);
5916 // only try to demangle symbols that look like Swift symbols
5917 if ( strncmp(sym
, "__T", 3) == 0 ) {
5918 size_t demangledSize
= fnd_get_demangled_name(&sym
[1], buff
, size
);
5919 if ( demangledSize
> size
) {
5920 size
= demangledSize
+2;
5921 buff
= (char*)realloc(buff
, size
);
5922 demangledSize
= fnd_get_demangled_name(&sym
[1], buff
, size
);
5924 if ( demangledSize
!= 0 )
5929 // only try to demangle symbols that look like C++ symbols
5930 if ( strncmp(sym
, "__Z", 3) != 0 )
5934 char* result
= abi::__cxa_demangle(&sym
[1], buff
, &size
, &status
);
5935 if ( result
!= NULL
) {
5936 // if demangling successful, keep buffer for next demangle
5944 void Options::dumpDependency(uint8_t opcode
, const char* path
) const
5946 if ( !this->dumpDependencyInfo() )
5949 // one time open() of -dependency_info file
5950 if ( fDependencyFileDescriptor
== -1 ) {
5951 fDependencyFileDescriptor
= open(this->dependencyInfoPath(), O_WRONLY
| O_TRUNC
| O_CREAT
, 0666);
5952 if ( fDependencyFileDescriptor
== -1 )
5953 throwf("Could not open or create -dependency_info file: %s", this->dependencyInfoPath());
5956 uint8_t version
= depLinkerVersion
;
5957 if ( write(fDependencyFileDescriptor
, &version
, 1) == -1 )
5958 throwf("write() to -dependency_info failed, errno=%d", errno
);
5959 extern const char ldVersionString
[];
5960 if ( write(fDependencyFileDescriptor
, ldVersionString
, strlen(ldVersionString
)+1) == -1 )
5961 throwf("write() to -dependency_info failed, errno=%d", errno
);
5964 char realPath
[PATH_MAX
];
5965 if ( path
[0] != '/' ) {
5966 if ( realpath(path
, realPath
) != NULL
) {
5971 if ( write(fDependencyFileDescriptor
, &opcode
, 1) == -1 )
5972 throwf("write() to -dependency_info failed, errno=%d", errno
);
5973 if ( write(fDependencyFileDescriptor
, path
, strlen(path
)+1) == -1 )
5974 throwf("write() to -dependency_info failed, errno=%d", errno
);
5976 //fprintf(stderr, "0x%02X %s\n", opcode, path);
5980 void Options::writeToTraceFile(const char* buffer
, size_t len
) const
5982 // one time open() of custom LD_TRACE_FILE
5983 if ( fTraceFileDescriptor
== -1 ) {
5984 if ( fTraceOutputFile
!= NULL
) {
5985 fTraceFileDescriptor
= open(fTraceOutputFile
, O_WRONLY
| O_APPEND
| O_CREAT
, 0666);
5986 if ( fTraceFileDescriptor
== -1 )
5987 throwf("Could not open or create trace file (errno=%d): %s", errno
, fTraceOutputFile
);
5990 fTraceFileDescriptor
= fileno(stderr
);
5995 ssize_t amountWritten
= write(fTraceFileDescriptor
, buffer
, len
);
5996 if ( amountWritten
== -1 )
5997 /* Failure to write shouldn't fail the build. */
5999 buffer
+= amountWritten
;
6000 len
-= amountWritten
;