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"
48 // from FunctionNameDemangle.h
49 extern "C" size_t fnd_get_demangled_name(const char *mangledName
, char *outputBuffer
, size_t length
);
52 // upward dependency on lto::version()
54 extern const char* version();
55 extern unsigned static_api_version();
56 extern unsigned runtime_api_version();
59 // magic to place command line in crash reports
60 const int crashreporterBufferSize
= 2000;
61 static char crashreporterBuffer
[crashreporterBufferSize
];
62 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
63 #include <CrashReporterClient.h>
64 // hack until ld does not need to build on 10.6 anymore
65 struct crashreporter_annotations_t gCRAnnotations
66 __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION
)))
67 = { CRASHREPORTER_ANNOTATIONS_VERSION
, 0, 0, 0, 0, 0, 0 };
69 extern "C" char* __crashreporter_info__
;
71 char* __crashreporter_info__
= crashreporterBuffer
;
75 static bool sEmitWarnings
= true;
76 static bool sFatalWarnings
= false;
77 static const char* sWarningsSideFilePath
= NULL
;
78 static FILE* sWarningsSideFile
= NULL
;
79 static int sWarningsCount
= 0;
81 void warning(const char* format
, ...)
84 if ( sEmitWarnings
) {
86 if ( sWarningsSideFilePath
!= NULL
) {
87 if ( sWarningsSideFile
== NULL
)
88 sWarningsSideFile
= fopen(sWarningsSideFilePath
, "a");
90 va_start(list
, format
);
91 fprintf(stderr
, "ld: warning: ");
92 vfprintf(stderr
, format
, list
);
93 fprintf(stderr
, "\n");
94 if ( sWarningsSideFile
!= NULL
) {
95 fprintf(sWarningsSideFile
, "ld: warning: ");
96 vfprintf(sWarningsSideFile
, format
, list
);
97 fprintf(sWarningsSideFile
, "\n");
98 fflush(sWarningsSideFile
);
104 void throwf(const char* format
, ...)
108 va_start(list
, format
);
109 vasprintf(&p
, format
, list
);
117 bool Options::FileInfo::checkFileExists(const Options
& options
, const char *p
)
123 struct stat statBuffer
;
126 if ( stat(p
, &statBuffer
) == 0 ) {
127 if (p
!= path
) path
= strdup(p
);
128 modTime
= statBuffer
.st_mtime
;
131 options
.addDependency(Options::depNotFound
, p
);
132 // fprintf(stderr, "not found: %s\n", p);
137 Options::Options(int argc
, const char* argv
[])
138 : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0), fArchitectureName("unknown"), fOutputKind(kDynamicExecutable
),
139 fHasPreferredSubType(false), fArchSupportsThumb2(false), fPrebind(false), fBindAtLoad(false), fKeepPrivateExterns(false),
140 fNeedsModuleTable(false), fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false),
141 fInterposeMode(kInterposeNone
), fDeadStrip(false), fNameSpace(kTwoLevelNameSpace
),
142 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL
), fFinalName(NULL
), fEntryName(NULL
),
143 fBaseAddress(0), fMaxAddress(0x7FFFFFFFFFFFFFFFLL
),
144 fBaseWritableAddress(0), fSplitSegs(false),
145 fExportMode(kExportDefault
), fLibrarySearchMode(kSearchDylibAndArchiveInEachDir
),
146 fUndefinedTreatment(kUndefinedError
), fMessagesPrefixedWithArchitecture(true),
147 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak
),
149 fUmbrellaName(NULL
), fInitFunctionName(NULL
), fDotOutputFile(NULL
), fExecutablePath(NULL
),
150 fBundleLoader(NULL
), fDtraceScriptName(NULL
), fSegAddrTablePath(NULL
), fMapPath(NULL
),
151 fDyldInstallPath("/usr/lib/dyld"), fLtoCachePath(NULL
), fTempLtoObjectPath(NULL
), fOverridePathlibLTO(NULL
), fLtoCpu(NULL
),
152 fZeroPageSize(ULLONG_MAX
), fStackSize(0), fStackAddr(0), fSourceVersion(0), fSDKVersion(0), fExecutableStack(false),
153 fNonExecutableHeap(false), fDisableNonExecutableHeap(false),
154 fMinimumHeaderPad(32), fSegmentAlignment(4096),
155 fCommonsMode(kCommonsIgnoreDylibs
), fUUIDMode(kUUIDContent
), fLocalSymbolHandling(kLocalSymbolsAll
), fWarnCommons(false),
156 fVerbose(false), fKeepRelocations(false), fWarnStabs(false),
157 fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
158 fSharedRegionEligible(false), fSharedRegionEligibleForceOff(false), fPrintOrderFileStatistics(false),
159 fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), fPIEOnCommandLine(false),
160 fDisablePositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
161 fDeadStripDylibs(false), fAllowTextRelocs(false), fWarnTextRelocs(false), fKextsUseStubs(false),
162 fUsingLazyDylibLinking(false), fEncryptable(true), fEncryptableForceOn(false), fEncryptableForceOff(false),
163 fOrderData(true), fMarkDeadStrippableDylib(false),
164 fMakeCompressedDyldInfo(true), fMakeCompressedDyldInfoForceOff(false), fNoEHLabels(false),
165 fAllowCpuSubtypeMismatches(false), fEnforceDylibSubtypesMatch(false),
166 fWarnOnSwiftABIVersionMismatches(false), fUseSimplifiedDylibReExports(false),
167 fObjCABIVersion2Override(false), fObjCABIVersion1Override(false), fCanUseUpwardDylib(false),
168 fFullyLoadArchives(false), fLoadAllObjcObjectsFromArchives(false), fFlatNamespace(false),
169 fLinkingMainExecutable(false), fForFinalLinkedImage(false), fForStatic(false),
170 fForDyld(false), fMakeTentativeDefinitionsReal(false), fWhyLoad(false), fRootSafe(false),
171 fSetuidSafe(false), fImplicitlyLinkPublicDylibs(true), fAddCompactUnwindEncoding(true),
172 fWarnCompactUnwind(false), fRemoveDwarfUnwindIfCompactExists(false),
173 fAutoOrderInitializers(true), fOptimizeZeroFill(true), fMergeZeroFill(false), fLogObjectFiles(false),
174 fLogAllFiles(false), fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false), fTraceEmitJSON(false),
175 fOutputSlidable(false), fWarnWeakExports(false), fNoWeakExports(false),
176 fObjcGcCompaction(false), fObjCGc(false), fObjCGcOnly(false),
177 fDemangle(false), fTLVSupport(false),
178 fVersionLoadCommand(false), fVersionLoadCommandForcedOn(false),
179 fVersionLoadCommandForcedOff(false), fBuildVersionLoadCommand(false), fFunctionStartsLoadCommand(false),
180 fFunctionStartsForcedOn(false), fFunctionStartsForcedOff(false),
181 fDataInCodeInfoLoadCommand(false), fDataInCodeInfoLoadCommandForcedOn(false), fDataInCodeInfoLoadCommandForcedOff(false),
182 fCanReExportSymbols(false), fObjcCategoryMerging(true), fPageAlignDataAtoms(false),
183 fNeedsThreadLoadCommand(false), fEntryPointLoadCommand(false),
184 fEntryPointLoadCommandForceOn(false), fEntryPointLoadCommandForceOff(false),
185 fSourceVersionLoadCommand(false),
186 fSourceVersionLoadCommandForceOn(false), fSourceVersionLoadCommandForceOff(false),
187 fTargetIOSSimulator(false), fExportDynamic(false), fAbsoluteSymbols(false),
188 fAllowSimulatorToLinkWithMacOSX(false), fKeepDwarfUnwind(true),
189 fKeepDwarfUnwindForcedOn(false), fKeepDwarfUnwindForcedOff(false),
190 fVerboseOptimizationHints(false), fIgnoreOptimizationHints(false),
191 fGenerateDtraceDOF(true), fAllowBranchIslands(true), fTraceSymbolLayout(false),
192 fMarkAppExtensionSafe(false), fCheckAppExtensionSafe(false), fForceLoadSwiftLibs(false),
193 fSharedRegionEncodingV2(false), fUseDataConstSegment(false),
194 fUseDataConstSegmentForceOn(false), fUseDataConstSegmentForceOff(false), fUseTextExecSegment(false),
195 fBundleBitcode(false), fHideSymbols(false), fVerifyBitcode(false),
196 fReverseMapUUIDRename(false), fDeDupe(true), fVerboseDeDupe(false),
197 fReverseMapPath(NULL
), fLTOCodegenOnly(false),
198 fIgnoreAutoLink(false), fAllowDeadDups(false), fAllowWeakImports(true), fInitializersTreatment(Options::kInvalid
),
199 fZeroModTimeInDebugMap(false), fBitcodeKind(kBitcodeProcess
),
200 fPlatform(kPlatformUnknown
), fDebugInfoStripping(kDebugInfoMinimal
), fTraceOutputFile(NULL
),
201 fMacVersionMin(ld::macVersionUnset
), fIOSVersionMin(ld::iOSVersionUnset
), fWatchOSVersionMin(ld::wOSVersionUnset
),
202 fSaveTempFiles(false), fSnapshotRequested(false), fPipelineFifo(NULL
),
203 fDependencyInfoPath(NULL
), fTraceFileDescriptor(-1), fMaxDefaultCommonAlign(0),
204 fUnalignedPointerTreatment(kUnalignedPointerIgnore
)
206 this->checkForClassic(argc
, argv
);
207 this->parsePreCommandLineEnvironmentSettings();
208 this->parse(argc
, argv
);
209 this->parsePostCommandLineEnvironmentSettings();
210 this->reconfigureDefaults();
211 this->checkIllegalOptionCombinations();
213 this->addDependency(depOutputFile
, fOutputFile
);
214 if ( fMapPath
!= NULL
)
215 this->addDependency(depOutputFile
, fMapPath
);
220 if ( fTraceFileDescriptor
!= -1 )
221 ::close(fTraceFileDescriptor
);
224 bool Options::errorBecauseOfWarnings() const
226 return (sFatalWarnings
&& (sWarningsCount
> 0));
230 const char* Options::installPath() const
232 if ( fDylibInstallName
!= NULL
)
233 return fDylibInstallName
;
234 else if ( fFinalName
!= NULL
)
241 bool Options::interposable(const char* name
) const
243 switch ( fInterposeMode
) {
246 case kInterposeAllExternal
:
249 return fInterposeList
.contains(name
);
251 throw "internal error";
255 bool Options::printWhyLive(const char* symbolName
) const
257 return fWhyLive
.contains(symbolName
);
261 const char* Options::dotOutputFile()
263 return fDotOutputFile
;
267 bool Options::hasWildCardExportRestrictList() const
269 // has -exported_symbols_list which contains some wildcards
270 return ((fExportMode
== kExportSome
) && fExportSymbols
.hasWildCards());
273 bool Options::hasWeakBitTweaks() const
275 // has -exported_symbols_list which contains some wildcards
276 return (!fForceWeakSymbols
.empty() || !fForceNotWeakSymbols
.empty());
279 bool Options::allGlobalsAreDeadStripRoots() const
281 // -exported_symbols_list means globals are not exported by default
282 if ( fExportMode
== kExportSome
)
285 switch ( fOutputKind
) {
286 case Options::kDynamicExecutable
:
287 // <rdar://problem/12839986> Add the -export_dynamic flag
288 return fExportDynamic
;
289 case Options::kStaticExecutable
:
290 // <rdar://problem/13361218> Support the -export_dynamic flag for xnu
291 return fExportDynamic
;
292 case Options::kPreload
:
293 // by default unused globals in a main executable are stripped
295 case Options::kDynamicLibrary
:
296 case Options::kDynamicBundle
:
297 case Options::kObjectFile
:
299 case Options::kKextBundle
:
306 bool Options::keepRelocations()
308 return fKeepRelocations
;
311 bool Options::warnStabs()
316 const char* Options::executablePath()
318 return fExecutablePath
;
321 uint32_t Options::initialSegProtection(const char* segName
) const
323 for(std::vector
<Options::SegmentProtect
>::const_iterator it
= fCustomSegmentProtections
.begin(); it
!= fCustomSegmentProtections
.end(); ++it
) {
324 if ( strcmp(it
->name
, segName
) == 0 ) {
328 if ( strcmp(segName
, "__TEXT") == 0 ) {
329 return ( fUseTextExecSegment
? VM_PROT_READ
: (VM_PROT_READ
| VM_PROT_EXECUTE
) );
331 else if ( strcmp(segName
, "__TEXT_EXEC") == 0 ) {
332 return VM_PROT_READ
| VM_PROT_EXECUTE
;
334 else if ( strcmp(segName
, "__PAGEZERO") == 0 ) {
337 else if ( strcmp(segName
, "__LINKEDIT") == 0 ) {
341 // all others default to read-write
342 return VM_PROT_READ
| VM_PROT_WRITE
;
345 uint32_t Options::maxSegProtection(const char* segName
) const
347 // iPhoneOS always uses same protection for max and initial
348 // <rdar://problem/11663436> simulator apps need to use MacOSX max-prot
349 if ( (fPlatform
!= kPlatformOSX
) && !fTargetIOSSimulator
)
350 return initialSegProtection(segName
);
352 for(std::vector
<Options::SegmentProtect
>::const_iterator it
= fCustomSegmentProtections
.begin(); it
!= fCustomSegmentProtections
.end(); ++it
) {
353 if ( strcmp(it
->name
, segName
) == 0 ) {
357 if ( strcmp(segName
, "__PAGEZERO") == 0 ) {
360 // all others default to all
361 return VM_PROT_READ
| VM_PROT_WRITE
| VM_PROT_EXECUTE
;
364 uint64_t Options::segPageSize(const char* segName
) const
366 for(std::vector
<SegmentSize
>::const_iterator it
=fCustomSegmentSizes
.begin(); it
!= fCustomSegmentSizes
.end(); ++it
) {
367 if ( strcmp(it
->name
, segName
) == 0 )
370 return fSegmentAlignment
;
373 uint64_t Options::customSegmentAddress(const char* segName
) const
375 for(std::vector
<SegmentStart
>::const_iterator it
=fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
376 if ( strcmp(it
->name
, segName
) == 0 )
379 // if custom stack in use, model as segment with custom address
380 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
381 return fStackAddr
- fStackSize
;
385 bool Options::hasCustomSegmentAddress(const char* segName
) const
387 for(std::vector
<SegmentStart
>::const_iterator it
=fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
388 if ( strcmp(it
->name
, segName
) == 0 )
391 // if custom stack in use, model as segment with custom address
392 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
397 bool Options::hasCustomSectionAlignment(const char* segName
, const char* sectName
) const
399 for (std::vector
<SectionAlignment
>::const_iterator it
= fSectionAlignments
.begin(); it
!= fSectionAlignments
.end(); ++it
) {
400 if ( (strcmp(it
->segmentName
, segName
) == 0) && (strcmp(it
->sectionName
, sectName
) == 0) )
403 if ( fEncryptable
&& (strcmp(sectName
, "__oslogstring") == 0) && (strcmp(segName
, "__TEXT") == 0) )
409 uint8_t Options::customSectionAlignment(const char* segName
, const char* sectName
) const
411 for (std::vector
<SectionAlignment
>::const_iterator it
= fSectionAlignments
.begin(); it
!= fSectionAlignments
.end(); ++it
) {
412 if ( (strcmp(it
->segmentName
, segName
) == 0) && (strcmp(it
->sectionName
, sectName
) == 0) )
413 return it
->alignment
;
415 if ( fEncryptable
&& (strcmp(sectName
, "__oslogstring") == 0) && (strcmp(segName
, "__TEXT") == 0) )
416 return __builtin_ctz(fSegmentAlignment
);
421 bool Options::segmentOrderAfterFixedAddressSegment(const char* segName
) const
423 bool nowPinned
= false;
424 for (std::vector
<const char*>::const_iterator it
=fSegmentOrder
.begin(); it
!= fSegmentOrder
.end(); ++it
) {
425 if ( strcmp(*it
, segName
) == 0 )
427 if ( hasCustomSegmentAddress(*it
) )
433 bool Options::hasExportedSymbolOrder()
435 return (fExportSymbolsOrder
.size() > 0);
438 bool Options::exportedSymbolOrder(const char* sym
, unsigned int* order
) const
440 NameToOrder::const_iterator pos
= fExportSymbolsOrder
.find(sym
);
441 if ( pos
!= fExportSymbolsOrder
.end() ) {
442 *order
= pos
->second
;
451 void Options::loadSymbolOrderFile(const char* fileOfExports
, NameToOrder
& orderMapping
)
453 // read in whole file
454 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
456 throwf("can't open -exported_symbols_order file: %s", fileOfExports
);
457 struct stat stat_buf
;
458 ::fstat(fd
, &stat_buf
);
459 char* p
= (char*)malloc(stat_buf
.st_size
);
461 throwf("can't process -exported_symbols_order file: %s", fileOfExports
);
463 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
464 throwf("can't read -exported_symbols_order file: %s", fileOfExports
);
468 // parse into symbols and add to unordered_set
469 unsigned int count
= 0;
470 char * const end
= &p
[stat_buf
.st_size
];
471 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
472 char* symbolStart
= NULL
;
473 for (char* s
= p
; s
< end
; ++s
) {
479 else if ( !isspace(*s
) ) {
485 if ( (*s
== '\n') || (*s
== '\r') ) {
487 // removing any trailing spaces
489 while ( isspace(*last
) ) {
493 orderMapping
[symbolStart
] = ++count
;
499 if ( (*s
== '\n') || (*s
== '\r') )
504 if ( state
== inSymbol
) {
505 warning("missing line-end at end of file \"%s\"", fileOfExports
);
506 int len
= end
-symbolStart
+1;
507 char* temp
= new char[len
];
508 strlcpy(temp
, symbolStart
, len
);
510 // remove any trailing spaces
511 char* last
= &temp
[len
-2];
512 while ( isspace(*last
) ) {
516 orderMapping
[temp
] = ++count
;
519 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
522 bool Options::forceWeak(const char* symbolName
) const
524 return fForceWeakSymbols
.contains(symbolName
);
527 bool Options::forceNotWeak(const char* symbolName
) const
529 return fForceNotWeakSymbols
.contains(symbolName
);
532 bool Options::forceWeakNonWildCard(const char* symbolName
) const
534 return fForceWeakSymbols
.containsNonWildcard(symbolName
);
537 bool Options::forceNotWeakNonWildcard(const char* symbolName
) const
539 return fForceNotWeakSymbols
.containsNonWildcard(symbolName
);
542 bool Options::forceCoalesce(const char* symbolName
) const
544 return fForceCoalesceSymbols
.contains(symbolName
);
548 bool Options::shouldExport(const char* symbolName
) const
550 switch (fExportMode
) {
552 return fExportSymbols
.contains(symbolName
);
553 case kDontExportSome
:
554 return ! fDontExportSymbols
.contains(symbolName
);
558 throw "internal error";
561 bool Options::shouldReExport(const char* symbolName
) const
563 return fReExportSymbols
.contains(symbolName
);
566 bool Options::keepLocalSymbol(const char* symbolName
) const
568 switch (fLocalSymbolHandling
) {
569 case kLocalSymbolsAll
:
571 case kLocalSymbolsNone
:
573 case kLocalSymbolsSelectiveInclude
:
574 return fLocalSymbolsIncluded
.contains(symbolName
);
575 case kLocalSymbolsSelectiveExclude
:
576 return ! fLocalSymbolsExcluded
.contains(symbolName
);
578 throw "internal error";
581 const std::vector
<const char*>* Options::sectionOrder(const char* segName
) const
583 for (std::vector
<SectionOrderList
>::const_iterator it
=fSectionOrder
.begin(); it
!= fSectionOrder
.end(); ++it
) {
584 if ( strcmp(it
->segmentName
, segName
) == 0 )
585 return &it
->sectionOrder
;
590 uint32_t Options::minOSversion() const
594 return iOSVersionMin();
596 return macosxVersionMin();
597 case kPlatformWatchOS
:
598 return watchOSVersionMin();
600 case Options::kPlatform_tvOS
:
601 return iOSVersionMin();
603 case kPlatform_bridgeOS
:
604 return iOSVersionMin();
605 case kPlatformUnknown
:
611 void Options::setArchitecture(cpu_type_t type
, cpu_subtype_t subtype
, Options::Platform platform
)
613 for (const ArchInfo
* t
=archInfoArray
; t
->archName
!= NULL
; ++t
) {
614 if ( (type
== t
->cpuType
) && (subtype
== t
->cpuSubType
) ) {
615 fArchitecture
= type
;
616 fSubArchitecture
= subtype
;
617 fArchitectureName
= t
->archName
;
618 fHasPreferredSubType
= t
->isSubType
;
619 fArchSupportsThumb2
= t
->supportsThumb2
;
620 if ( fPlatform
== kPlatformUnknown
)
621 fPlatform
= platform
;
624 case CPU_TYPE_X86_64
:
625 if ( (fPlatform
== kPlatformOSX
) && (fOutputKind
!= Options::kObjectFile
) && (fMacVersionMin
== ld::macVersionUnset
) ) {
626 #ifdef DEFAULT_MACOSX_MIN_VERSION
627 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION
);
628 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
630 warning("-macosx_version_min not specified, assuming 10.6");
631 fMacVersionMin
= ld::mac10_6
;
637 if ( (fMacVersionMin
== ld::macVersionUnset
) && (fIOSVersionMin
== ld::iOSVersionUnset
) && (fOutputKind
!= Options::kObjectFile
) ) {
638 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
639 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION
);
640 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION
);
642 warning("-ios_version_min not specified, assuming 6.0");
643 setIOSVersionMin("6.0");
648 fLinkSnapshot
.recordArch(fArchitectureName
);
649 // only use compressed LINKEDIT for:
650 // Mac OS X 10.6 or later
652 if ( !fMakeCompressedDyldInfo
&& minOS(ld::mac10_6
, ld::iOS_3_1
) && !fMakeCompressedDyldInfoForceOff
)
653 fMakeCompressedDyldInfo
= true;
654 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
655 if ( minOS(ld::mac10_5
, ld::iOS_2_0
) )
656 fUseSimplifiedDylibReExports
= true;
660 fArchitectureName
= "unknown architecture";
663 bool Options::armUsesZeroCostExceptions() const
665 return ( (fArchitecture
== CPU_TYPE_ARM
) && (fSubArchitecture
== CPU_SUBTYPE_ARM_V7K
) );
668 void Options::parseArch(const char* arch
)
671 throw "-arch must be followed by an architecture string";
672 for (const ArchInfo
* t
=archInfoArray
; t
->archName
!= NULL
; ++t
) {
673 if ( strcmp(t
->archName
,arch
) == 0 ) {
674 fArchitectureName
= arch
;
675 fArchitecture
= t
->cpuType
;
676 fSubArchitecture
= t
->cpuSubType
;
677 fHasPreferredSubType
= t
->isSubType
;
678 fArchSupportsThumb2
= t
->supportsThumb2
;
682 throwf("unknown/unsupported architecture name for: -arch %s", arch
);
685 bool Options::checkForFile(const char* format
, const char* dir
, const char* rootName
, FileInfo
& result
) const
687 char possiblePath
[strlen(dir
)+strlen(rootName
)+strlen(format
)+8];
688 sprintf(possiblePath
, format
, dir
, rootName
);
689 bool found
= result
.checkFileExists(*this, possiblePath
);
690 if ( fTraceDylibSearching
)
691 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), possiblePath
);
696 Options::FileInfo
Options::findLibrary(const char* rootName
, bool dylibsOnly
) const
699 const int rootNameLen
= strlen(rootName
);
700 // if rootName ends in .o there is no .a vs .dylib choice
701 if ( (rootNameLen
> 3) && (strcmp(&rootName
[rootNameLen
-2], ".o") == 0) ) {
702 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
703 it
!= fLibrarySearchPaths
.end();
705 const char* dir
= *it
;
706 if ( checkForFile("%s/%s", dir
, rootName
, result
) )
711 bool lookForDylibs
= false;
712 switch ( fOutputKind
) {
713 case Options::kDynamicExecutable
:
714 case Options::kDynamicLibrary
:
715 case Options::kDynamicBundle
:
716 case Options::kObjectFile
: // <rdar://problem/15914513>
717 lookForDylibs
= true;
719 case Options::kStaticExecutable
:
721 case Options::kPreload
:
722 case Options::kKextBundle
:
723 lookForDylibs
= false;
726 switch ( fLibrarySearchMode
) {
727 case kSearchAllDirsForDylibsThenAllDirsForArchives
:
728 // first look in all directories for just for dylibs
729 if ( lookForDylibs
) {
730 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
731 it
!= fLibrarySearchPaths
.end();
733 const char* dir
= *it
;
734 auto path
= std::string(dir
) + "/lib" + rootName
+ ".dylib";
735 if ( findFile(path
, {".tbd"}, result
) )
738 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
739 it
!= fLibrarySearchPaths
.end();
741 const char* dir
= *it
;
742 if ( checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
746 // next look in all directories for just for archives
748 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
749 it
!= fLibrarySearchPaths
.end();
751 const char* dir
= *it
;
752 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
758 case kSearchDylibAndArchiveInEachDir
:
759 // look in each directory for just for a dylib then for an archive
760 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
761 it
!= fLibrarySearchPaths
.end();
763 const char* dir
= *it
;
764 auto path
= std::string(dir
) + "/lib" + rootName
+ ".dylib";
765 if ( lookForDylibs
&& findFile(path
, {".tbd"}, result
) )
767 if ( lookForDylibs
&& checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
769 if ( !dylibsOnly
&& checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
775 throwf("library not found for -l%s", rootName
);
778 Options::FileInfo
Options::findFramework(const char* frameworkName
) const
780 if ( frameworkName
== NULL
)
781 throw "-framework missing next argument";
782 char temp
[strlen(frameworkName
)+1];
783 strcpy(temp
, frameworkName
);
784 const char* name
= temp
;
785 const char* suffix
= NULL
;
786 char* comma
= strchr(temp
, ',');
787 if ( comma
!= NULL
) {
791 return findFramework(name
, suffix
);
794 Options::FileInfo
Options::findFramework(const char* rootName
, const char* suffix
) const
796 for (const auto* path
: fFrameworkSearchPaths
) {
797 auto possiblePath
= std::string(path
).append("/").append(rootName
).append(".framework/").append(rootName
);
798 if ( suffix
!= nullptr ) {
799 char realPath
[PATH_MAX
];
800 // no symlink in framework to suffix variants, so follow main symlink
801 if ( realpath(possiblePath
.c_str(), realPath
) != nullptr )
802 possiblePath
= std::string(realPath
).append(suffix
);
805 if ( findFile(possiblePath
, {".tbd"}, result
) )
808 // try without suffix
809 if ( suffix
!= NULL
)
810 return findFramework(rootName
, NULL
);
812 throwf("framework not found %s", rootName
);
815 static std::string
replace_extension(const std::string
&path
, const std::string
&ext
)
818 auto lastSlashIdx
= result
.find_last_of('/');
819 auto lastDotIdx
= result
.find_last_of('.');
820 if (lastDotIdx
!= std::string::npos
&& lastDotIdx
> lastSlashIdx
)
821 result
.erase(lastDotIdx
, std::string::npos
);
822 if ( ext
.size() > 0 && ext
[0] == '.' )
825 result
.append('.' + ext
);
829 void Options::addTAPIInterface(tapi::LinkerInterfaceFile
*interface
, const char *path
) const {
830 #if ((TAPI_API_VERSION_MAJOR == 1 && TAPI_API_VERSION_MINOR >= 3) || (TAPI_API_VERSION_MAJOR > 1))
831 if (tapi::APIVersion::isAtLeast(1, 3)) {
832 for (auto &name
: interface
->inlinedFrameworkNames()) {
833 fTAPIFiles
.emplace_back(interface
, path
, name
.c_str());
839 bool Options::findFile(const std::string
&path
, const std::vector
<std::string
> &tbdExtensions
, FileInfo
& result
) const
842 for ( const auto &ext
: tbdExtensions
) {
843 auto newPath
= replace_extension(path
, ext
);
844 bool found
= tbdInfo
.checkFileExists(*this, newPath
.c_str());
845 if ( fTraceDylibSearching
)
846 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), newPath
.c_str());
853 bool found
= dylibInfo
.checkFileExists(*this, path
.c_str());
854 if ( fTraceDylibSearching
)
855 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), path
.c_str());
858 // There is only a text-based stub file or a dynamic library file.
859 if ( tbdInfo
.missing() != dylibInfo
.missing() ) {
860 result
= tbdInfo
.missing() ? dylibInfo
: tbdInfo
;
862 // There are both - a text-based stub file and a dynamic library file.
863 else if ( !tbdInfo
.missing() && !dylibInfo
.missing() ) {
864 // Check if we should prefer the text-based stub file (installapi).
865 if (tapi::LinkerInterfaceFile::shouldPreferTextBasedStubFile(tbdInfo
.path
)) {
868 // If the files are still in sync we can use and should use the text-based stub file.
869 else if (tapi::LinkerInterfaceFile::areEquivalent(tbdInfo
.path
, dylibInfo
.path
)) {
872 // Otherwise issue a warning and fall-back to the dynamic library file.
874 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
);
884 static bool startsWith(const std::string
& str
, const std::string
& prefix
)
886 return (str
.compare(0, prefix
.length(), prefix
) == 0);
889 static std::string
getDirPath(const std::string
& path
)
891 std::string::size_type lastSlashPos
= path
.find_last_of('/');
892 if ( lastSlashPos
== std::string::npos
)
895 return path
.substr(0, lastSlashPos
+1);
898 Options::FileInfo
Options::findFile(const std::string
&path
, const ld::dylib::File
* fromDylib
) const
902 // if absolute path and not a .o file, then use SDK prefix
903 if ( (path
[0] == '/') && (strcmp(&path
[path
.size()-2], ".o") != 0) ) {
904 for (const auto* sdkPathDir
: fSDKPaths
) {
905 auto possiblePath
= std::string(sdkPathDir
) + path
;
906 if ( findFile(possiblePath
, {".tbd"}, result
) )
911 // expand @ variables
912 if ( path
[0] == '@' ) {
913 if ( startsWith(path
, "@executable_path/") && (fExecutablePath
!= nullptr) ) {
914 std::string exeBasedPath
= getDirPath(fExecutablePath
) + &path
[17];
915 if ( findFile(exeBasedPath
, {".tbd"}, result
) )
918 else if ( startsWith(path
, "@loader_path/") && (fromDylib
!= nullptr) ) {
919 char absPath
[PATH_MAX
];
920 if ( realpath(fromDylib
->path(), absPath
) != NULL
) {
921 std::string loaderBasedPath
= getDirPath(fromDylib
->path()) + &path
[13];
922 if ( findFile(loaderBasedPath
, {".tbd"}, result
) )
926 else if ( startsWith(path
, "@rpath/") ) {
927 // first search any LC_RPATH supplied by dyld that re-exports dylib to be found
928 if ( fromDylib
!= nullptr ) {
929 for (const char* rp
: fromDylib
->rpaths() ) {
930 std::string rpath
= rp
;
931 // handle dylib that has LC_RPATH = @loader_path/blah
932 if ( startsWith(rpath
, "@loader_path/") ) {
933 char absPath
[PATH_MAX
];
934 if ( realpath(fromDylib
->path(), absPath
) != NULL
)
935 rpath
= getDirPath(absPath
) + &rpath
[13];
937 rpath
= getDirPath(fromDylib
->path()) + &rpath
[13];
939 std::string rpathBasedPath
= rpath
+ "/" + &path
[6];
940 if ( findFile(rpathBasedPath
, {".tbd"}, result
) )
947 // find inlined TBD file before raw path.
948 // rdar://problem/35864452
949 if (hasInlinedTAPIFile(path
)) {
950 FileInfo
inlinedFile(path
.c_str());
951 inlinedFile
.isInlined
= true;
956 if ( findFile(path
, {".tbd"}, result
) )
960 throwf("file not found: %s", path
.c_str());
963 bool Options::hasInlinedTAPIFile(const std::string
&path
) const {
964 for (const auto &dylib
: fTAPIFiles
) {
965 if (dylib
.getInstallName() == path
)
971 std::unique_ptr
<tapi::LinkerInterfaceFile
> Options::findTAPIFile(const std::string
&path
) const
973 std::unique_ptr
<tapi::LinkerInterfaceFile
> interface
;
976 // create parsing options.
977 tapi::ParsingFlags flags
= tapi::ParsingFlags::None
;
978 if (enforceDylibSubtypesMatch())
979 flags
|= tapi::ParsingFlags::ExactCpuSubType
;
981 if (!allowWeakImports())
982 flags
|= tapi::ParsingFlags::DisallowWeakImports
;
984 // Search through all the inlined framework.
985 for (const auto &dylib
: fTAPIFiles
) {
986 if (dylib
.getInstallName() == path
) {
987 // If the install name matches, parse the framework.
988 std::string errorMessage
;
989 auto file
= dylib
.getInterfaceFile()->getInlinedFramework(path
.c_str(), architecture(), subArchitecture(),
990 flags
, tapi::PackedVersion32(minOSversion()), errorMessage
);
992 throw strdup(errorMessage
.c_str());
995 // If this is the first inlined framework found, record the information.
996 interface
.reset(file
);
997 TBDPath
= dylib
.getTAPIFilePath();
999 // If we found other inlined framework already, check to see if their versions are the same.
1000 // If not the same, emit an warning and record the newer one. Otherwise, just use the current one.
1001 if (interface
->getCurrentVersion() == file
->getCurrentVersion())
1003 warning("Inlined framework/dylib mismatch: %s (%s and %s)", path
.c_str(),
1004 TBDPath
.c_str(), dylib
.getTAPIFilePath().c_str());
1005 if (interface
->getCurrentVersion() < file
->getCurrentVersion()) {
1006 interface
.reset(file
);
1007 TBDPath
= dylib
.getTAPIFilePath();
1015 // search for indirect dylib first using -F and -L paths first
1016 Options::FileInfo
Options::findIndirectDylib(const std::string
& installName
, const ld::dylib::File
* fromDylib
) const
1020 auto lastSlashPos
= installName
.find_last_of('/');
1021 auto pos
= ( lastSlashPos
!= std::string::npos
) ? lastSlashPos
+ 1 : 0;
1022 auto leafName
= installName
.substr(pos
);
1024 // Is this in a framework?
1025 // /path/Foo.framework/Foo ==> true (Foo)
1026 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
1027 // /path/Foo.framework/Resources/Bar ==> false
1028 bool isFramework
= false;
1029 if ( lastSlashPos
!= std::string::npos
) {
1030 auto frameworkDir
= std::string("/").append(leafName
).append(".framework/");
1031 if ( installName
.rfind(frameworkDir
) != std::string::npos
)
1035 // These are abbreviated versions of the routines findFramework and findLibrary above
1036 // because we already know the final name of the file that we're looking for and so
1037 // don't need to try variations, just paths. We do need to add the additional bits
1038 // onto the framework path though.
1039 if ( isFramework
) {
1040 auto endPos
= installName
.rfind(".framework");
1041 auto beginPos
= installName
.find_last_of('/', endPos
);
1042 auto leafPath
= installName
.substr(beginPos
);
1043 for (const auto* dir
: fFrameworkSearchPaths
) {
1044 auto possiblePath
= dir
+ leafPath
;
1045 if ( findFile(possiblePath
, {".tbd"}, result
) )
1049 // if this is a .dylib inside a framework, do not search -L paths
1050 // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
1051 bool embeddedDylib
= ( (leafName
.size() > 6)
1052 && (leafName
.find(".dylib", leafName
.size()-6) != std::string::npos
)
1053 && (installName
.find(".framework/") != std::string::npos
) );
1054 if ( !embeddedDylib
) {
1055 for (const auto* dir
: fLibrarySearchPaths
) {
1056 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
1057 std::string possiblePath
= dir
+ std::string("/") + leafName
;
1058 if ( findFile(possiblePath
, {".tbd"}, result
) )
1064 // If we didn't find it fall back to findFile.
1065 return findFile(installName
, fromDylib
);
1070 void Options::parseSegAddrTable(const char* segAddrPath
, const char* installPth
)
1072 FILE* file
= fopen(segAddrPath
, "r");
1073 if ( file
== NULL
) {
1074 warning("-seg_addr_table file cannot be read: %s", segAddrPath
);
1078 char path
[PATH_MAX
];
1079 uint64_t firstColumAddress
= 0;
1080 uint64_t secondColumAddress
= 0;
1081 bool hasSecondColumn
= false;
1082 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
1083 path
[PATH_MAX
-1] = '\0';
1084 char* eol
= strchr(path
, '\n');
1087 // ignore lines not starting with 0x number
1088 if ( (path
[0] == '0') && (path
[1] == 'x') ) {
1090 firstColumAddress
= strtoull(path
, &p
, 16);
1091 while ( isspace(*p
) )
1093 // see if second column is a number
1094 if ( (p
[0] == '0') && (p
[1] == 'x') ) {
1095 secondColumAddress
= strtoull(p
, &p
, 16);
1096 hasSecondColumn
= true;
1097 while ( isspace(*p
) )
1100 while ( isspace(*p
) )
1102 if ( p
[0] == '/' ) {
1103 // remove any trailing whitespace
1104 for(char* end
= eol
-1; (end
> p
) && isspace(*end
); --end
)
1106 // see if this line is for the dylib being linked
1107 if ( strcmp(p
, installPth
) == 0 ) {
1108 fBaseAddress
= firstColumAddress
;
1109 if ( hasSecondColumn
) {
1110 fBaseWritableAddress
= secondColumAddress
;
1113 break; // out of while loop
1122 void Options::loadFileList(const char* fileOfPaths
, ld::File::Ordinal baseOrdinal
)
1125 const char* comma
= strrchr(fileOfPaths
, ',');
1126 const char* prefix
= NULL
;
1127 if ( comma
!= NULL
) {
1128 // <rdar://problem/5907981> -filelist fails with comma in path
1129 file
= fopen(fileOfPaths
, "r");
1130 if ( file
== NULL
) {
1132 int realFileOfPathsLen
= comma
-fileOfPaths
;
1133 char realFileOfPaths
[realFileOfPathsLen
+1];
1134 strncpy(realFileOfPaths
,fileOfPaths
, realFileOfPathsLen
);
1135 realFileOfPaths
[realFileOfPathsLen
] = '\0';
1136 file
= fopen(realFileOfPaths
, "r");
1138 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", realFileOfPaths
, errno
, strerror(errno
));
1139 this->addDependency(Options::depFileList
, realFileOfPaths
);
1143 file
= fopen(fileOfPaths
, "r");
1145 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", fileOfPaths
, errno
, strerror(errno
));
1146 this->addDependency(Options::depFileList
, fileOfPaths
);
1149 char path
[PATH_MAX
];
1150 ld::File::Ordinal previousOrdinal
= baseOrdinal
;
1151 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
1152 path
[PATH_MAX
-1] = '\0';
1153 char* eol
= strchr(path
, '\n');
1156 if ( prefix
!= NULL
) {
1157 char builtPath
[strlen(prefix
)+strlen(path
)+2];
1158 strcpy(builtPath
, prefix
);
1159 strcat(builtPath
, "/");
1160 strcat(builtPath
, path
);
1161 if (fPipelineFifo
!= NULL
) {
1162 FileInfo info
= FileInfo(builtPath
);
1163 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1164 previousOrdinal
= info
.ordinal
;
1165 info
.fromFileList
= true;
1166 fInputFiles
.push_back(info
);
1168 FileInfo info
= findFile(builtPath
);
1169 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1170 previousOrdinal
= info
.ordinal
;
1171 info
.fromFileList
= true;
1172 fInputFiles
.push_back(info
);
1176 if (fPipelineFifo
!= NULL
) {
1177 FileInfo info
= FileInfo(path
);
1178 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1179 previousOrdinal
= info
.ordinal
;
1180 info
.fromFileList
= true;
1181 fInputFiles
.push_back(info
);
1183 FileInfo info
= findFile(path
);
1184 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1185 previousOrdinal
= info
.ordinal
;
1186 info
.fromFileList
= true;
1187 fInputFiles
.push_back(info
);
1195 void Options::SetWithWildcards::remove(const NameSet
& toBeRemoved
)
1197 for(NameSet::const_iterator it
=toBeRemoved
.begin(); it
!= toBeRemoved
.end(); ++it
) {
1198 const char* symbolName
= *it
;
1199 NameSet::iterator pos
= fRegular
.find(symbolName
);
1200 if ( pos
!= fRegular
.end() )
1201 fRegular
.erase(pos
);
1205 bool Options::SetWithWildcards::hasWildCards(const char* symbol
)
1207 // an exported symbol name containing *, ?, or [ requires wildcard matching
1208 return ( strpbrk(symbol
, "*?[") != NULL
);
1211 void Options::SetWithWildcards::insert(const char* symbol
)
1213 if ( hasWildCards(symbol
) )
1214 fWildCard
.push_back(symbol
);
1216 fRegular
.insert(symbol
);
1219 bool Options::SetWithWildcards::contains(const char* symbol
, bool* matchBecauseOfWildcard
) const
1221 if ( matchBecauseOfWildcard
!= NULL
)
1222 *matchBecauseOfWildcard
= false;
1223 // first look at hash table on non-wildcard symbols
1224 if ( fRegular
.find(symbol
) != fRegular
.end() )
1226 // next walk list of wild card symbols looking for a match
1227 for(std::vector
<const char*>::const_iterator it
= fWildCard
.begin(); it
!= fWildCard
.end(); ++it
) {
1228 if ( wildCardMatch(*it
, symbol
) ) {
1229 if ( matchBecauseOfWildcard
!= NULL
)
1230 *matchBecauseOfWildcard
= true;
1237 // Support "foo.o:_bar" to mean symbol _bar in file foo.o
1238 bool Options::SetWithWildcards::containsWithPrefix(const char* symbol
, const char* file
, bool& wildCardMatch
) const
1240 wildCardMatch
= false;
1241 if ( contains(symbol
, &wildCardMatch
) )
1245 const char* s
= strrchr(file
, '/');
1248 char buff
[strlen(file
)+strlen(symbol
)+2];
1249 sprintf(buff
, "%s:%s", file
, symbol
);
1250 return contains(buff
, &wildCardMatch
);
1253 bool Options::SetWithWildcards::containsNonWildcard(const char* symbol
) const
1255 // look at hash table on non-wildcard symbols
1256 return ( fRegular
.find(symbol
) != fRegular
.end() );
1260 std::vector
<const char*> Options::exportsData() const
1262 return fExportSymbols
.data();
1266 std::vector
<const char*> Options::SetWithWildcards::data() const
1268 std::vector
<const char*> data
;
1269 for (NameSet::iterator it
=regularBegin(); it
!= regularEnd(); ++it
) {
1270 data
.push_back(*it
);
1272 for (std::vector
<const char*>::const_iterator it
=fWildCard
.begin(); it
!= fWildCard
.end(); ++it
) {
1273 data
.push_back(*it
);
1278 bool Options::SetWithWildcards::inCharRange(const char*& p
, unsigned char c
) const
1282 while ( *p
!= '\0' ) {
1285 // found beginining [ and ending ]
1286 unsigned char last
= '\0';
1287 for ( const char* s
= b
; s
< e
; ++s
) {
1289 unsigned char next
= *(++s
);
1290 if ( (last
<= c
) && (c
<= next
) )
1307 bool Options::SetWithWildcards::wildCardMatch(const char* pattern
, const char* symbol
) const
1309 const char* s
= symbol
;
1310 for (const char* p
= pattern
; *p
!= '\0'; ++p
) {
1315 for (const char* t
= s
; *t
!= '\0'; ++t
) {
1316 if ( wildCardMatch(&p
[1], t
) )
1326 if ( ! inCharRange(p
, *s
) )
1336 return (*s
== '\0');
1340 void Options::loadExportFile(const char* fileOfExports
, const char* option
, SetWithWildcards
& set
)
1342 if ( fileOfExports
== NULL
)
1343 throwf("missing file after %s", option
);
1344 // read in whole file
1345 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
1347 throwf("can't open %s file: %s", option
, fileOfExports
);
1348 struct stat stat_buf
;
1349 ::fstat(fd
, &stat_buf
);
1350 char* p
= (char*)malloc(stat_buf
.st_size
);
1352 throwf("can't process %s file: %s", option
, fileOfExports
);
1354 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1355 throwf("can't read %s file: %s", option
, fileOfExports
);
1357 this->addDependency(Options::depMisc
, fileOfExports
);
1361 // parse into symbols and add to unordered_set
1362 char * const end
= &p
[stat_buf
.st_size
];
1363 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1364 char* symbolStart
= NULL
;
1365 for (char* s
= p
; s
< end
; ++s
) {
1371 else if ( !isspace(*s
) ) {
1377 if ( (*s
== '\n') || (*s
== '\r') ) {
1379 // removing any trailing spaces
1381 while ( isspace(*last
) ) {
1385 set
.insert(symbolStart
);
1391 if ( (*s
== '\n') || (*s
== '\r') )
1396 if ( state
== inSymbol
) {
1397 warning("missing line-end at end of file \"%s\"", fileOfExports
);
1398 int len
= end
-symbolStart
+1;
1399 char* temp
= new char[len
];
1400 strlcpy(temp
, symbolStart
, len
);
1402 // remove any trailing spaces
1403 char* last
= &temp
[len
-2];
1404 while ( isspace(*last
) ) {
1411 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
1414 void Options::parseAliasFile(const char* fileOfAliases
)
1416 // read in whole file
1417 int fd
= ::open(fileOfAliases
, O_RDONLY
, 0);
1419 throwf("can't open alias file: %s", fileOfAliases
);
1420 struct stat stat_buf
;
1421 ::fstat(fd
, &stat_buf
);
1422 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1424 throwf("can't process alias file: %s", fileOfAliases
);
1426 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1427 throwf("can't read alias file: %s", fileOfAliases
);
1428 p
[stat_buf
.st_size
] = '\n';
1430 this->addDependency(Options::depMisc
, fileOfAliases
);
1432 // parse into symbols and add to fAliases
1434 char * const end
= &p
[stat_buf
.st_size
+1];
1435 enum { lineStart
, inRealName
, inBetween
, inAliasName
, inComment
} state
= lineStart
;
1437 for (char* s
= p
; s
< end
; ++s
) {
1443 else if ( !isspace(*s
) ) {
1450 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1454 else if ( isspace(*s
) ) {
1461 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1465 else if ( ! isspace(*s
) ) {
1466 state
= inAliasName
;
1473 // removing any trailing spaces
1475 while ( isspace(*last
) ) {
1479 fAliases
.push_back(pair
);
1482 else if ( *s
== '\n' ) {
1484 // removing any trailing spaces
1486 while ( isspace(*last
) ) {
1490 fAliases
.push_back(pair
);
1501 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
1506 void Options::setUndefinedTreatment(const char* treatment
)
1508 if ( treatment
== NULL
)
1509 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
1511 if ( strcmp(treatment
, "warning") == 0 )
1512 fUndefinedTreatment
= kUndefinedWarning
;
1513 else if ( strcmp(treatment
, "error") == 0 )
1514 fUndefinedTreatment
= kUndefinedError
;
1515 else if ( strcmp(treatment
, "suppress") == 0 )
1516 fUndefinedTreatment
= kUndefinedSuppress
;
1517 else if ( strcmp(treatment
, "dynamic_lookup") == 0 )
1518 fUndefinedTreatment
= kUndefinedDynamicLookup
;
1520 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1523 Options::Treatment
Options::parseTreatment(const char* treatment
)
1525 if ( treatment
== NULL
)
1528 if ( strcmp(treatment
, "warning") == 0 )
1530 else if ( strcmp(treatment
, "error") == 0 )
1532 else if ( strcmp(treatment
, "suppress") == 0 )
1538 void Options::setMacOSXVersionMin(const char* version
)
1541 if ( !parsePackedVersion32(version
, value
) ) {
1542 throwf("-macosx_version_min value malformed: '%s'", version
);
1544 fMacVersionMin
= (ld::MacVersionMin
)value
;
1545 fPlatform
= kPlatformOSX
;
1548 void Options::setIOSVersionMin(const char* version
)
1551 if ( !parsePackedVersion32(version
, value
) ) {
1552 throwf("-ios_version_min value malformed: '%s'", version
);
1554 fIOSVersionMin
= (ld::IOSVersionMin
)value
;
1555 fPlatform
= kPlatformiOS
;
1559 void Options::setWatchOSVersionMin(const char* version
)
1562 if ( !parsePackedVersion32(version
, value
) ) {
1563 throwf("-watchos_version_min value malformed: '%s'", version
);
1565 fWatchOSVersionMin
= (ld::WatchOSVersionMin
)value
;
1566 fPlatform
= kPlatformWatchOS
;
1570 bool Options::minOS(ld::MacVersionMin requiredMacMin
, ld::IOSVersionMin requirediPhoneOSMin
)
1572 if ( fMacVersionMin
!= ld::macVersionUnset
) {
1573 return ( fMacVersionMin
>= requiredMacMin
);
1576 return min_iOS(requirediPhoneOSMin
);
1580 bool Options::min_iOS(ld::IOSVersionMin requirediOSMin
)
1582 if ( fWatchOSVersionMin
!= ld::wOSVersionUnset
) {
1583 // Hack until we fully track watch and ios versions seperately
1584 return ( (fWatchOSVersionMin
+ 0x00070000) >= requirediOSMin
);
1586 else if ( fPlatform
== Options::kPlatform_bridgeOS
) {
1587 // Hack until we fully track bridge and ios versions seperately
1588 return ( (fIOSVersionMin
+ 0x00090000) >= requirediOSMin
);
1591 return ( fIOSVersionMin
>= requirediOSMin
);
1595 void Options::setWeakReferenceMismatchTreatment(const char* treatment
)
1597 if ( treatment
== NULL
)
1598 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1600 if ( strcmp(treatment
, "error") == 0 )
1601 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchError
;
1602 else if ( strcmp(treatment
, "weak") == 0 )
1603 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchWeak
;
1604 else if ( strcmp(treatment
, "non-weak") == 0 )
1605 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchNonWeak
;
1607 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1610 Options::CommonsMode
Options::parseCommonsTreatment(const char* mode
)
1613 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1615 if ( strcmp(mode
, "ignore_dylibs") == 0 )
1616 return kCommonsIgnoreDylibs
;
1617 else if ( strcmp(mode
, "use_dylibs") == 0 )
1618 return kCommonsOverriddenByDylibs
;
1619 else if ( strcmp(mode
, "error") == 0 )
1620 return kCommonsConflictsDylibsError
;
1622 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1625 void Options::addDylibOverride(const char* paths
)
1627 if ( paths
== NULL
)
1628 throw "-dylib_file must followed by two colon separated paths";
1629 const char* colon
= strchr(paths
, ':');
1630 if ( colon
== NULL
)
1631 throw "-dylib_file must followed by two colon separated paths";
1632 int len
= colon
-paths
;
1633 char* target
= new char[len
+2];
1634 strncpy(target
, paths
, len
);
1636 DylibOverride entry
;
1637 entry
.installName
= target
;
1638 entry
.useInstead
= &colon
[1];
1639 fDylibOverrides
.push_back(entry
);
1642 uint64_t Options::parseAddress(const char* addr
)
1645 uint64_t result
= strtoull(addr
, &endptr
, 16);
1649 uint32_t Options::parseProtection(const char* prot
)
1651 uint32_t result
= 0;
1652 for(const char* p
= prot
; *p
!= '\0'; ++p
) {
1653 switch(tolower(*p
)) {
1655 result
|= VM_PROT_READ
;
1658 result
|= VM_PROT_WRITE
;
1661 result
|= VM_PROT_EXECUTE
;
1666 throwf("unknown -segprot lettter in %s", prot
);
1674 // Parses number of form A[.B[.B[.D[.E]]]] into a uint64_t where the bits are a24.b10.c10.d10.e10
1676 uint64_t Options::parseVersionNumber64(const char* versionString
)
1684 a
= strtoul(versionString
, &end
, 10);
1685 if ( *end
== '.' ) {
1686 b
= strtoul(&end
[1], &end
, 10);
1687 if ( *end
== '.' ) {
1688 c
= strtoul(&end
[1], &end
, 10);
1689 if ( *end
== '.' ) {
1690 d
= strtoul(&end
[1], &end
, 10);
1691 if ( *end
== '.' ) {
1692 e
= strtoul(&end
[1], &end
, 10);
1697 if ( (*end
!= '\0') || (a
> 0xFFFFFF) || (b
> 0x3FF) || (c
> 0x3FF) || (d
> 0x3FF) || (e
> 0x3FF) )
1698 throwf("malformed 64-bit a.b.c.d.e version number: %s", versionString
);
1700 return (a
<< 40) | ( b
<< 30 ) | ( c
<< 20 ) | ( d
<< 10 ) | e
;
1704 uint32_t Options::currentVersion32() const
1706 // warn if it does not fit into 32 bit vers number
1707 uint32_t a
= (fDylibCurrentVersion
>> 40) & 0xFFFF;
1708 uint32_t b
= (fDylibCurrentVersion
>> 30) & 0xFF;
1709 uint32_t c
= (fDylibCurrentVersion
>> 20) & 0xFF;
1710 uint64_t rep32
= ((uint64_t)a
<< 40) | ((uint64_t)b
<< 30) | ((uint64_t)c
<< 20);
1711 if ( rep32
!= fDylibCurrentVersion
) {
1712 warning("truncating -current_version to fit in 32-bit space used by old mach-o format");
1713 a
= (fDylibCurrentVersion
>> 40) & 0xFFFFFF;
1716 b
= (fDylibCurrentVersion
>> 30) & 0x3FF;
1719 c
= (fDylibCurrentVersion
>> 20) & 0x3FF;
1723 return (a
<< 16) | ( b
<< 8 ) | c
;
1727 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1729 uint32_t Options::parseVersionNumber32(const char* versionString
)
1735 x
= strtoul(versionString
, &end
, 10);
1736 if ( *end
== '.' ) {
1737 y
= strtoul(&end
[1], &end
, 10);
1738 if ( *end
== '.' ) {
1739 z
= strtoul(&end
[1], &end
, 10);
1742 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
1743 throwf("malformed 32-bit x.y.z version number: %s", versionString
);
1745 return (x
<< 16) | ( y
<< 8 ) | z
;
1748 static const char* cstringSymbolName(const char* orderFileString
)
1751 asprintf(&result
, "cstring=%s", orderFileString
);
1752 // convert escaped characters
1754 for(const char* s
=result
; *s
!= '\0'; ++s
, ++d
) {
1792 // hexadecimal value of char
1796 while ( isxdigit(*s
) ) {
1801 value
+= ((toupper(*s
)-'A') + 10);
1808 if ( isdigit(*s
) ) {
1809 // octal value of char
1811 while ( isdigit(*s
) ) {
1812 value
= (value
<< 3) + (*s
-'0');
1827 void Options::parseOrderFile(const char* path
, bool cstring
)
1829 // order files override auto-ordering
1830 fAutoOrderInitializers
= false;
1832 // <rdar://problem/24856050> ld64 should prefer OrderFiles from the SDK over the ones in /
1833 for (const char* sdkPath
: fSDKPaths
) {
1834 char fullPath
[PATH_MAX
];
1835 strlcpy(fullPath
, sdkPath
, PATH_MAX
);
1836 strlcat(fullPath
, "/", PATH_MAX
);
1837 strlcat(fullPath
, path
, PATH_MAX
);
1838 struct stat statBuffer
;
1839 if ( stat(fullPath
, &statBuffer
) == 0 ) {
1840 path
= strdup(fullPath
);
1845 // read in whole file
1846 int fd
= ::open(path
, O_RDONLY
, 0);
1848 throwf("can't open order file: %s", path
);
1849 struct stat stat_buf
;
1850 ::fstat(fd
, &stat_buf
);
1851 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1853 throwf("can't process order file: %s", path
);
1854 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1855 throwf("can't read order file: %s", path
);
1857 p
[stat_buf
.st_size
] = '\n';
1858 this->addDependency(Options::depMisc
, path
);
1860 // parse into vector of pairs
1861 char * const end
= &p
[stat_buf
.st_size
+1];
1862 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1863 char* symbolStart
= NULL
;
1864 for (char* s
= p
; s
< end
; ++s
) {
1870 else if ( !isspace(*s
) || cstring
) {
1876 if ( (*s
== '\n') || (!cstring
&& (*s
== '#')) ) {
1877 bool wasComment
= (*s
== '#');
1879 // removing any trailing spaces
1881 while ( isspace(*last
) ) {
1885 // if there is an architecture prefix, only use this symbol it if matches current arch
1886 if ( strncmp(symbolStart
, "ppc:", 4) == 0 ) {
1889 else if ( strncmp(symbolStart
, "ppc64:", 6) == 0 ) {
1892 else if ( strncmp(symbolStart
, "i386:", 5) == 0 ) {
1893 if ( fArchitecture
== CPU_TYPE_I386
)
1894 symbolStart
= &symbolStart
[5];
1898 else if ( strncmp(symbolStart
, "x86_64:", 7) == 0 ) {
1899 if ( fArchitecture
== CPU_TYPE_X86_64
)
1900 symbolStart
= &symbolStart
[7];
1904 else if ( strncmp(symbolStart
, "arm:", 4) == 0 ) {
1905 if ( fArchitecture
== CPU_TYPE_ARM
)
1906 symbolStart
= &symbolStart
[4];
1910 else if ( strncmp(symbolStart
, "arm64:", 6) == 0 ) {
1911 if ( fArchitecture
== CPU_TYPE_ARM64
)
1912 symbolStart
= &symbolStart
[6];
1916 if ( symbolStart
!= NULL
) {
1917 char* objFileName
= NULL
;
1918 char* colon
= strstr(symbolStart
, ".o:");
1919 if ( colon
!= NULL
) {
1921 objFileName
= symbolStart
;
1922 symbolStart
= &colon
[3];
1925 colon
= strstr(symbolStart
, ".o):");
1926 if ( colon
!= NULL
) {
1928 objFileName
= symbolStart
;
1929 symbolStart
= &colon
[4];
1932 // trim leading spaces
1933 while ( isspace(*symbolStart
) )
1935 Options::OrderedSymbol pair
;
1937 pair
.symbolName
= cstringSymbolName(symbolStart
);
1939 pair
.symbolName
= symbolStart
;
1940 pair
.objectFileName
= objFileName
;
1941 fOrderedSymbols
.push_back(pair
);
1956 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1959 void Options::parseSectionOrderFile(const char* segment
, const char* section
, const char* path
)
1961 if ( (strcmp(section
, "__cstring") == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1962 parseOrderFile(path
, true);
1964 else if ( (strncmp(section
, "__literal",9) == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1965 warning("sorting of __literal[4,8,16] sections not supported");
1968 // ignore section information and append all symbol names to global order file
1969 parseOrderFile(path
, false);
1973 void Options::addSection(const char* segment
, const char* section
, const char* path
)
1975 if ( strlen(segment
) > 16 )
1976 throw "-seccreate segment name max 16 chars";
1977 if ( strlen(section
) > 16 ) {
1978 char* tmp
= strdup(section
);
1980 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section
, tmp
);
1984 // read in whole file
1985 int fd
= ::open(path
, O_RDONLY
, 0);
1987 throwf("can't open -sectcreate file: %s", path
);
1988 struct stat stat_buf
;
1989 ::fstat(fd
, &stat_buf
);
1990 char* p
= (char*)malloc(stat_buf
.st_size
);
1992 throwf("can't process -sectcreate file: %s", path
);
1993 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1994 throwf("can't read -sectcreate file: %s", path
);
1997 // record section to create
1998 ExtraSection info
= { segment
, section
, path
, (uint8_t*)p
, (uint64_t)stat_buf
.st_size
};
1999 fExtraSections
.push_back(info
);
2002 void Options::addSectionRename(const char* srcSegment
, const char* srcSection
, const char* dstSegment
, const char* dstSection
)
2004 if ( strlen(srcSegment
) > 16 )
2005 throw "-rename_section segment name max 16 chars";
2006 if ( strlen(srcSection
) > 16 )
2007 throw "-rename_section section name max 16 chars";
2008 if ( strlen(dstSegment
) > 16 )
2009 throw "-rename_section segment name max 16 chars";
2010 if ( strlen(dstSection
) > 16 )
2011 throw "-rename_section section name max 16 chars";
2014 info
.fromSegment
= srcSegment
;
2015 info
.fromSection
= srcSection
;
2016 info
.toSegment
= dstSegment
;
2017 info
.toSection
= dstSection
;
2019 fSectionRenames
.push_back(info
);
2023 void Options::addSegmentRename(const char* srcSegment
, const char* dstSegment
)
2025 if ( strlen(srcSegment
) > 16 )
2026 throw "-rename_segment segment name max 16 chars";
2027 if ( strlen(dstSegment
) > 16 )
2028 throw "-rename_segment segment name max 16 chars";
2031 info
.fromSegment
= srcSegment
;
2032 info
.toSegment
= dstSegment
;
2034 fSegmentRenames
.push_back(info
);
2039 void Options::addSymbolMove(const char* dstSegment
, const char* symbolList
,
2040 std::vector
<SymbolsMove
>& list
, const char* optionName
)
2042 if ( strlen(dstSegment
) > 16 )
2043 throwf("%s segment name max 16 chars", optionName
);
2046 list
.push_back(tmp
);
2047 SymbolsMove
& info
= list
.back();
2048 info
.toSegment
= dstSegment
;
2049 loadExportFile(symbolList
, optionName
, info
.symbols
);
2052 bool Options::moveRwSymbol(const char* symName
, const char* filePath
, const char*& seg
, bool& wildCardMatch
) const
2054 for (std::vector
<SymbolsMove
>::const_iterator it
=fSymbolsMovesData
.begin(); it
!= fSymbolsMovesData
.end(); ++it
) {
2055 const SymbolsMove
& info
= *it
;
2056 if ( info
.symbols
.containsWithPrefix(symName
, filePath
, wildCardMatch
)) {
2057 seg
= info
.toSegment
;
2064 bool Options::moveRoSymbol(const char* symName
, const char* filePath
, const char*& seg
, bool& wildCardMatch
) const
2066 for (std::vector
<SymbolsMove
>::const_iterator it
=fSymbolsMovesCode
.begin(); it
!= fSymbolsMovesCode
.end(); ++it
) {
2067 const SymbolsMove
& info
= *it
;
2068 if ( info
.symbols
.containsWithPrefix(symName
, filePath
, wildCardMatch
)) {
2069 seg
= info
.toSegment
;
2076 void Options::addSectionAlignment(const char* segment
, const char* section
, const char* alignmentStr
)
2078 if ( strlen(segment
) > 16 )
2079 throw "-sectalign segment name max 16 chars";
2080 if ( strlen(section
) > 16 )
2081 throw "-sectalign section name max 16 chars";
2083 // argument to -sectalign is a hexadecimal number
2085 unsigned long value
= strtoul(alignmentStr
, &endptr
, 16);
2086 if ( *endptr
!= '\0')
2087 throw "argument for -sectalign is not a hexadecimal number";
2088 if ( value
> 0x8000 )
2089 throw "argument for -sectalign must be less than or equal to 0x8000";
2091 warning("zero is not a valid -sectalign");
2095 // alignment is power of 2 (e.g. page alignment = 12)
2096 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
2097 if ( (unsigned long)(1 << alignment
) != value
) {
2098 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
2099 segment
, section
, 1 << alignment
);
2102 SectionAlignment info
= { segment
, section
, alignment
};
2103 fSectionAlignments
.push_back(info
);
2106 void Options::addLibrary(const FileInfo
& info
)
2108 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
2109 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
2110 if ( strcmp(info
.path
, fit
->path
) == 0 ) {
2111 // if dylib is specified again but weak, record that it should be weak
2112 if ( info
.options
.fWeakImport
)
2113 fit
->options
.fWeakImport
= true;
2118 fInputFiles
.push_back(info
);
2121 void Options::warnObsolete(const char* arg
)
2123 warning("option %s is obsolete and being ignored", arg
);
2127 void Options::cannotBeUsedWithBitcode(const char* arg
)
2129 if ( fBundleBitcode
)
2130 throwf("%s and -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES) cannot be used together", arg
);
2133 std::string
Options::getVersionString32(uint32_t ver
) const
2135 if (ver
== 0 || ver
>= 0x10000000)
2138 unsigned microVersion
= ver
& 0xFF;
2139 unsigned minorVersion
= (ver
>> 8) & 0xFF;
2140 unsigned majorVersion
= (ver
>> 16) & 0xFF;
2141 std::stringstream versionString
;
2142 versionString
<< majorVersion
<< "." << minorVersion
<< "." << microVersion
;
2143 return versionString
.str();
2146 std::string
Options::getVersionString64(uint64_t ver
) const
2148 uint64_t a
= (ver
>> 40) & 0xFFFFFF;
2149 uint64_t b
= (ver
>> 30) & 0x3FF;
2150 uint64_t c
= (ver
>> 20) & 0x3FF;
2151 uint64_t d
= (ver
>> 10) & 0x3FF;
2152 uint64_t e
= ver
& 0x3FF;
2153 std::stringstream versionString
;
2154 versionString
<< a
<< "." << b
<< "." << c
<< "." << d
<< "." << e
;
2155 return versionString
.str();
2158 // Convert X.Y[.Z] to 32-bit value xxxxyyzz
2159 bool Options::parsePackedVersion32(const std::string
& versionStr
, uint32_t &result
)
2163 if ( versionStr
.empty() )
2166 size_t pos
= versionStr
.find('.');
2167 if ( pos
== std::string::npos
)
2170 std::string majorStr
= versionStr
.substr(0, pos
);
2171 std::string rest
= versionStr
.substr(pos
+1);
2175 int majorValue
= std::stoi(majorStr
, &majorEnd
);
2176 if ( majorEnd
!= majorStr
.size() )
2178 if ( majorValue
< 0 )
2180 if ( majorValue
> 65535 )
2183 std::string minorStr
;
2184 std::string microStr
;
2185 pos
= rest
.find('.');
2186 if ( pos
== std::string::npos
) {
2190 minorStr
= rest
.substr(0, pos
);
2191 microStr
= rest
.substr(pos
+1);
2195 int minorValue
= std::stoi(minorStr
, &minorEnd
);
2196 if ( minorEnd
!= minorStr
.size() )
2198 if ( minorValue
< 0 )
2200 if ( minorValue
> 255 )
2204 if ( !microStr
.empty() ) {
2206 microValue
= std::stoi(microStr
, µEnd
);
2207 if ( microEnd
!= microStr
.size() )
2209 if ( microValue
< 0 )
2211 if ( microValue
> 255 )
2215 result
= (majorValue
<< 16) | (minorValue
<< 8) | microValue
;
2220 // std::stoi() throws exception on malformed input
2225 std::string
Options::getSDKVersionStr() const
2227 return getVersionString32(fSDKVersion
);
2230 std::string
Options::getPlatformStr() const
2232 switch (fPlatform
) {
2233 case Options::kPlatformOSX
:
2235 case Options::kPlatformiOS
:
2236 if (targetIOSSimulator())
2237 return "iPhoneSimulator";
2240 case Options::kPlatformWatchOS
:
2241 if (targetIOSSimulator())
2242 return "watchOS Simulator";
2245 #if SUPPORT_APPLE_TV
2246 case Options::kPlatform_tvOS
:
2247 if (targetIOSSimulator())
2248 return "AppleTVSimulator";
2253 case Options::kPlatform_bridgeOS
:
2255 case Options::kPlatformUnknown
:
2260 std::vector
<std::string
> Options::writeBitcodeLinkOptions() const
2262 std::vector
<std::string
> linkCommand
;
2263 switch ( fOutputKind
) {
2264 case Options::kDynamicLibrary
:
2265 linkCommand
.push_back("-dylib");
2266 linkCommand
.push_back("-compatibility_version");
2267 if ( fDylibCompatVersion
!= 0 ) {
2268 linkCommand
.push_back(getVersionString32(fDylibCompatVersion
));
2270 linkCommand
.push_back(getVersionString32(currentVersion32()));
2272 if ( fDylibCurrentVersion
!= 0 ) {
2273 linkCommand
.push_back("-current_version");
2274 linkCommand
.push_back(getVersionString64(fDylibCurrentVersion
));
2276 linkCommand
.push_back("-install_name");
2277 linkCommand
.push_back(installPath());
2279 case Options::kDynamicExecutable
:
2280 linkCommand
.push_back("-execute");
2282 case Options::kObjectFile
:
2283 linkCommand
.push_back("-r");
2286 throwf("could not write bitcode options file output kind\n");
2289 if (!fImplicitlyLinkPublicDylibs
)
2290 linkCommand
.push_back("-no_implicit_dylibs");
2292 // Add deployment target.
2293 // Platform is allowed to be unknown for "ld -r".
2294 switch (fPlatform
) {
2295 case Options::kPlatformOSX
:
2296 linkCommand
.push_back("-macosx_version_min");
2297 linkCommand
.push_back(getVersionString32((unsigned)fMacVersionMin
));
2299 case Options::kPlatformiOS
:
2300 if (targetIOSSimulator())
2301 linkCommand
.push_back("-ios_simulator_version_min");
2303 linkCommand
.push_back("-ios_version_min");
2304 linkCommand
.push_back(getVersionString32((unsigned)fIOSVersionMin
));
2306 case Options::kPlatformWatchOS
:
2307 if (targetIOSSimulator())
2308 linkCommand
.push_back("-watchos_simulator_version_min");
2310 linkCommand
.push_back("-watchos_version_min");
2311 linkCommand
.push_back(getVersionString32((unsigned)fIOSVersionMin
));
2313 #if SUPPORT_APPLE_TV
2314 case Options::kPlatform_tvOS
:
2315 if (targetIOSSimulator())
2316 linkCommand
.push_back("-tvos_simulator_version_min");
2318 linkCommand
.push_back("-tvos_version_min");
2319 linkCommand
.push_back(getVersionString32((unsigned)fIOSVersionMin
));
2322 case Options::kPlatform_bridgeOS
:
2323 linkCommand
.push_back("-bridgeos_version_min");
2324 linkCommand
.push_back(getVersionString32((unsigned)fIOSVersionMin
));
2326 case Options::kPlatformUnknown
:
2327 if ( fOutputKind
!= Options::kObjectFile
) {
2328 throwf("platform is unknown for final bitcode bundle,"
2329 "deployment target and min version is required for -bitcode_bundle");
2337 linkCommand
.push_back("-e");
2338 linkCommand
.push_back(fEntryName
);
2342 if (!fRPaths
.empty()) {
2343 for (std::vector
<const char*>::const_iterator it
=fRPaths
.begin(); it
!= fRPaths
.end(); ++it
) {
2344 linkCommand
.push_back("-rpath");
2345 linkCommand
.push_back(*it
);
2349 // Other bitcode compatiable options
2350 if ( fObjCABIVersion1Override
) {
2351 linkCommand
.push_back("-objc_abi_version");
2352 linkCommand
.push_back("1");
2353 } else if ( fObjCABIVersion2Override
) {
2354 linkCommand
.push_back("-objc_abi_version");
2355 linkCommand
.push_back("2");
2357 if ( fExecutablePath
) {
2358 linkCommand
.push_back("-executable_path");
2359 linkCommand
.push_back(fExecutablePath
);
2362 linkCommand
.push_back("-dead_strip");
2363 if ( fExportDynamic
)
2364 linkCommand
.push_back("-export_dynamic");
2365 if ( fMarkAppExtensionSafe
&& fCheckAppExtensionSafe
)
2366 linkCommand
.push_back("-application_extension");
2368 if ( fSourceVersionLoadCommandForceOn
)
2369 linkCommand
.push_back("-add_source_version");
2370 if ( fSourceVersion
!= 0 ) {
2371 linkCommand
.push_back("-source_version");
2372 linkCommand
.push_back(getVersionString64(fSourceVersion
));
2375 // linker flag added by swift driver
2376 // rdar://problem/20108072
2377 if ( !fObjcCategoryMerging
)
2378 linkCommand
.push_back("-no_objc_category_merging");
2384 // Process all command line arguments.
2386 // The only error checking done here is that each option is valid and if it has arguments
2387 // that they too are valid.
2389 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
2390 // whichever was last on the command line is used.
2392 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
2394 void Options::parse(int argc
, const char* argv
[])
2396 // Store the original args in the link snapshot.
2397 fLinkSnapshot
.recordRawArgs(argc
, argv
);
2399 // pass one builds search list from -L and -F options
2400 this->buildSearchPaths(argc
, argv
);
2402 // reduce re-allocations
2403 fInputFiles
.reserve(32);
2405 // pass two parse all other options
2406 for(int i
=1; i
< argc
; ++i
) {
2407 const char* arg
= argv
[i
];
2409 if ( arg
[0] == '-' ) {
2410 // by default, copy one arg to the snapshot link command, and do no file copying
2411 int snapshotArgIndex
= i
;
2412 int snapshotArgCount
= -1; // -1 means compute count based on change in index
2413 int snapshotFileArgIndex
= -1; // -1 means no data file parameter to arg
2415 // Since we don't care about the files passed, just the option names, we do this here.
2417 fprintf (stderr
, "[Logging ld64 options]\t%s\n", arg
);
2419 if ( (arg
[1] == 'L') || (arg
[1] == 'F') ) {
2420 snapshotArgCount
= 0; // stripped out of link snapshot
2423 // previously handled by buildSearchPaths()
2425 // The one gnu style option we have to keep compatibility
2426 // with gcc. Might as well have the single hyphen one as well.
2427 else if ( (strcmp(arg
, "--help") == 0)
2428 || (strcmp(arg
, "-help") == 0)) {
2429 fprintf (stdout
, "ld64: For information on command line options please use 'man ld'.\n");
2432 else if ( strcmp(arg
, "-arch") == 0 ) {
2433 parseArch(argv
[++i
]);
2435 else if ( strcmp(arg
, "-dynamic") == 0 ) {
2438 else if ( strcmp(arg
, "-static") == 0 ) {
2440 if ( (fOutputKind
!= kObjectFile
) && (fOutputKind
!= kKextBundle
) ) {
2441 fOutputKind
= kStaticExecutable
;
2443 cannotBeUsedWithBitcode(arg
);
2445 else if ( strcmp(arg
, "-dylib") == 0 ) {
2446 fOutputKind
= kDynamicLibrary
;
2448 else if ( strcmp(arg
, "-bundle") == 0 ) {
2449 fOutputKind
= kDynamicBundle
;
2450 cannotBeUsedWithBitcode(arg
);
2452 else if ( strcmp(arg
, "-dylinker") == 0 ) {
2453 fOutputKind
= kDyld
;
2454 cannotBeUsedWithBitcode(arg
);
2456 else if ( strcmp(arg
, "-execute") == 0 ) {
2457 if ( fOutputKind
!= kStaticExecutable
)
2458 fOutputKind
= kDynamicExecutable
;
2460 else if ( strcmp(arg
, "-preload") == 0 ) {
2461 fOutputKind
= kPreload
;
2462 cannotBeUsedWithBitcode(arg
);
2464 else if ( strcmp(arg
, "-r") == 0 ) {
2465 fOutputKind
= kObjectFile
;
2467 else if ( strcmp(arg
, "-kext") == 0 ) {
2468 fOutputKind
= kKextBundle
;
2469 cannotBeUsedWithBitcode(arg
);
2471 else if ( strcmp(arg
, "-o") == 0 ) {
2472 snapshotArgCount
= 0;
2473 fOutputFile
= argv
[++i
];
2474 fLinkSnapshot
.setSnapshotName(fOutputFile
);
2476 else if ( strncmp(arg
, "-lazy-l", 7) == 0 ) {
2477 snapshotArgCount
= 0;
2478 FileInfo info
= findLibrary(&arg
[7], true);
2479 info
.options
.fLazyLoad
= true;
2480 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2482 fUsingLazyDylibLinking
= true;
2483 cannotBeUsedWithBitcode(arg
);
2485 else if ( strcmp(arg
, "-lto_library") == 0 ) {
2486 snapshotFileArgIndex
= 1;
2487 fOverridePathlibLTO
= argv
[++i
];
2488 if ( fOverridePathlibLTO
== NULL
)
2489 throw "missing argument to -lto_library";
2491 else if ( strcmp(arg
, "-cache_path_lto") == 0 ) {
2492 fLtoCachePath
= argv
[++i
];
2493 if ( fLtoCachePath
== NULL
)
2494 throw "missing argument to -cache_path_lto";
2496 else if ( strcmp(arg
, "-prune_interval_lto") == 0 ) {
2497 const char* value
= argv
[++i
];
2498 if ( value
== NULL
)
2499 throw "missing argument to -prune_interval_lto";
2501 fLtoPruneInterval
= strtoul(value
, &endptr
, 10);
2502 if ( *endptr
!= '\0')
2503 throw "invalid argument for -prune_interval_lto";
2505 else if ( strcmp(arg
, "-prune_after_lto") == 0 ) {
2506 const char* value
= argv
[++i
];
2507 if ( value
== NULL
)
2508 throw "missing argument to -prune_after_lto";
2510 fLtoPruneAfter
= strtoul(value
, &endptr
, 10);
2511 if ( *endptr
!= '\0')
2512 throw "invalid argument for -prune_after_lto";
2514 else if ( strcmp(arg
, "-max_relative_cache_size_lto") == 0 ) {
2515 const char* value
= argv
[++i
];
2516 if ( value
== NULL
)
2517 throw "missing argument to -max_relative_cache_size_lto";
2519 fLtoMaxCacheSize
= strtoul(value
, &endptr
, 10);
2520 if ( *endptr
!= '\0')
2521 throw "invalid argument for -max_relative_cache_size_lto";
2522 if (fLtoMaxCacheSize
> 100)
2523 throw "Expect a value between 0 and 100 for -max_relative_cache_size_lto";
2525 else if ( (arg
[1] == 'l') && (strncmp(arg
,"-lazy_",6) !=0) ) {
2526 snapshotArgCount
= 0;
2527 FileInfo info
= findLibrary(&arg
[2]);
2528 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2531 // This causes a dylib to be weakly bound at
2532 // link time. This corresponds to weak_import.
2533 else if ( strncmp(arg
, "-weak-l", 7) == 0 ) {
2534 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2535 snapshotArgCount
= 0;
2536 FileInfo info
= findLibrary(&arg
[7]);
2537 info
.options
.fWeakImport
= true;
2538 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2541 // Avoid lazy binding.
2542 else if ( strcmp(arg
, "-bind_at_load") == 0 ) {
2544 cannotBeUsedWithBitcode(arg
);
2546 else if ( strcmp(arg
, "-twolevel_namespace") == 0 ) {
2547 fNameSpace
= kTwoLevelNameSpace
;
2549 else if ( strcmp(arg
, "-flat_namespace") == 0 ) {
2550 fNameSpace
= kFlatNameSpace
;
2551 cannotBeUsedWithBitcode(arg
);
2553 // Also sets a bit to ensure dyld causes everything
2554 // in the namespace to be flat.
2556 else if ( strcmp(arg
, "-force_flat_namespace") == 0 ) {
2557 fNameSpace
= kForceFlatNameSpace
;
2558 cannotBeUsedWithBitcode(arg
);
2560 // Similar to --whole-archive.
2561 else if ( strcmp(arg
, "-all_load") == 0 ) {
2562 fFullyLoadArchives
= true;
2564 else if ( strcmp(arg
, "-noall_load") == 0) {
2567 // Similar to -all_load
2568 else if ( strcmp(arg
, "-ObjC") == 0 ) {
2569 fLoadAllObjcObjectsFromArchives
= true;
2571 // Similar to -all_load, but for the following archive only.
2572 else if ( strcmp(arg
, "-force_load") == 0 ) {
2573 FileInfo info
= findFile(argv
[++i
]);
2574 info
.options
.fForceLoad
= true;
2575 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2578 // Library versioning.
2579 else if ( (strcmp(arg
, "-dylib_compatibility_version") == 0)
2580 || (strcmp(arg
, "-compatibility_version") == 0)) {
2581 const char* vers
= argv
[++i
];
2583 throw "-dylib_compatibility_version missing <version>";
2584 fDylibCompatVersion
= parseVersionNumber32(vers
);
2586 else if ( (strcmp(arg
, "-dylib_current_version") == 0)
2587 || (strcmp(arg
, "-current_version") == 0)) {
2588 const char* vers
= argv
[++i
];
2590 throw "-dylib_current_version missing <version>";
2591 fDylibCurrentVersion
= parseVersionNumber64(vers
);
2593 else if ( strcmp(arg
, "-sectorder") == 0 ) {
2594 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2595 throw "-sectorder missing <segment> <section> <file-path>";
2596 snapshotFileArgIndex
= 3;
2597 parseSectionOrderFile(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2599 cannotBeUsedWithBitcode(arg
);
2601 else if ( strcmp(arg
, "-order_file") == 0 ) {
2602 snapshotFileArgIndex
= 1;
2603 parseOrderFile(argv
[++i
], false);
2605 else if ( strcmp(arg
, "-order_file_statistics") == 0 ) {
2606 fPrintOrderFileStatistics
= true;
2607 cannotBeUsedWithBitcode(arg
);
2609 // ??? Deprecate segcreate.
2610 // -sectcreate puts whole files into a section in the output.
2611 else if ( (strcmp(arg
, "-sectcreate") == 0) || (strcmp(arg
, "-segcreate") == 0) ) {
2612 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2613 throw "-sectcreate missing <segment> <section> <file-path>";
2614 snapshotFileArgIndex
= 3;
2615 addSection(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2618 // Since we have a full path in binary/library names we need to be able to override it.
2619 else if ( (strcmp(arg
, "-dylib_install_name") == 0)
2620 || (strcmp(arg
, "-dylinker_install_name") == 0)
2621 || (strcmp(arg
, "-install_name") == 0)) {
2622 fDylibInstallName
= argv
[++i
];
2623 if ( fDylibInstallName
== NULL
)
2624 throw "-install_name missing <path>";
2626 // Sets the base address of the output.
2627 else if ( (strcmp(arg
, "-seg1addr") == 0) || (strcmp(arg
, "-image_base") == 0) ) {
2628 const char* address
= argv
[++i
];
2629 if ( address
== NULL
)
2630 throwf("%s missing <address>", arg
);
2631 fBaseAddress
= parseAddress(address
);
2632 uint64_t temp
= ((fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
2633 if ( fBaseAddress
!= temp
) {
2634 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment
);
2635 fBaseAddress
= temp
;
2637 cannotBeUsedWithBitcode(arg
);
2639 else if ( strcmp(arg
, "-e") == 0 ) {
2640 fEntryName
= argv
[++i
];
2642 // Same as -@ from the FSF linker.
2643 else if ( strcmp(arg
, "-filelist") == 0 ) {
2644 snapshotArgCount
= 0;
2645 const char* path
= argv
[++i
];
2646 if ( (path
== NULL
) || (path
[0] == '-') )
2647 throw "-filelist missing <path>";
2648 ld::File::Ordinal baseOrdinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2649 loadFileList(path
, baseOrdinal
);
2651 else if ( strcmp(arg
, "-keep_private_externs") == 0 ) {
2652 cannotBeUsedWithBitcode(arg
);
2653 fKeepPrivateExterns
= true;
2655 else if ( strcmp(arg
, "-final_output") == 0 ) {
2656 fFinalName
= argv
[++i
];
2658 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
2659 // just ensures that this happens for cross object file boundaries.
2660 else if ( (strcmp(arg
, "-interposable") == 0) || (strcmp(arg
, "-multi_module") == 0)) {
2661 switch ( fInterposeMode
) {
2662 case kInterposeNone
:
2663 case kInterposeAllExternal
:
2664 fInterposeMode
= kInterposeAllExternal
;
2666 case kInterposeSome
:
2667 // do nothing, -interposable_list overrides -interposable"
2670 cannotBeUsedWithBitcode(arg
);
2672 else if ( strcmp(arg
, "-interposable_list") == 0 ) {
2673 snapshotFileArgIndex
= 1;
2674 fInterposeMode
= kInterposeSome
;
2675 loadExportFile(argv
[++i
], "-interposable_list", fInterposeList
);
2676 cannotBeUsedWithBitcode(arg
);
2678 // Default for -interposable/-multi_module/-single_module.
2679 else if ( strcmp(arg
, "-single_module") == 0 ) {
2680 fInterposeMode
= kInterposeNone
;
2682 else if ( strcmp(arg
, "-exported_symbols_list") == 0 ) {
2683 snapshotFileArgIndex
= 1;
2684 if ( fExportMode
== kDontExportSome
)
2685 throw "can't use -exported_symbols_list and -unexported_symbols_list";
2686 fExportMode
= kExportSome
;
2687 loadExportFile(argv
[++i
], "-exported_symbols_list", fExportSymbols
);
2689 else if ( strcmp(arg
, "-unexported_symbols_list") == 0 ) {
2690 snapshotFileArgIndex
= 1;
2691 if ( fExportMode
== kExportSome
)
2692 throw "can't use -unexported_symbols_list and -exported_symbols_list";
2693 fExportMode
= kDontExportSome
;
2694 loadExportFile(argv
[++i
], "-unexported_symbols_list", fDontExportSymbols
);
2696 else if ( strcmp(arg
, "-exported_symbol") == 0 ) {
2697 if ( fExportMode
== kDontExportSome
)
2698 throw "can't use -exported_symbol and -unexported_symbols";
2699 fExportMode
= kExportSome
;
2700 fExportSymbols
.insert(argv
[++i
]);
2702 else if ( strcmp(arg
, "-unexported_symbol") == 0 ) {
2703 if ( fExportMode
== kExportSome
)
2704 throw "can't use -unexported_symbol and -exported_symbol";
2705 fExportMode
= kDontExportSome
;
2706 fDontExportSymbols
.insert(argv
[++i
]);
2708 else if ( strcmp(arg
, "-non_global_symbols_no_strip_list") == 0 ) {
2709 snapshotFileArgIndex
= 1;
2710 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveExclude
)
2711 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2712 fLocalSymbolHandling
= kLocalSymbolsSelectiveInclude
;
2713 loadExportFile(argv
[++i
], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded
);
2714 cannotBeUsedWithBitcode(arg
);
2716 else if ( strcmp(arg
, "-non_global_symbols_strip_list") == 0 ) {
2717 snapshotFileArgIndex
= 1;
2718 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveInclude
)
2719 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2720 fLocalSymbolHandling
= kLocalSymbolsSelectiveExclude
;
2721 loadExportFile(argv
[++i
], "-non_global_symbols_strip_list", fLocalSymbolsExcluded
);
2722 cannotBeUsedWithBitcode(arg
);
2725 else if ( strcmp(arg
, "-no_arch_warnings") == 0 ) {
2726 fIgnoreOtherArchFiles
= true;
2728 else if ( strcmp(arg
, "-force_cpusubtype_ALL") == 0 ) {
2729 fForceSubtypeAll
= true;
2730 fAllowCpuSubtypeMismatches
= true;
2731 cannotBeUsedWithBitcode(arg
);
2733 // Similar to -weak-l but uses the absolute path name to the library.
2734 else if ( strcmp(arg
, "-weak_library") == 0 ) {
2735 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2736 snapshotArgCount
= 0;
2737 FileInfo info
= findFile(argv
[++i
]);
2738 info
.options
.fWeakImport
= true;
2739 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2741 cannotBeUsedWithBitcode(arg
);
2743 else if ( strcmp(arg
, "-lazy_library") == 0 ) {
2744 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2745 snapshotArgCount
= 0;
2746 FileInfo info
= findFile(argv
[++i
]);
2747 info
.options
.fLazyLoad
= true;
2748 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2750 fUsingLazyDylibLinking
= true;
2751 cannotBeUsedWithBitcode(arg
);
2753 else if ( strcmp(arg
, "-framework") == 0 ) {
2754 snapshotArgCount
= 0;
2755 FileInfo info
= findFramework(argv
[++i
]);
2756 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2759 else if ( strcmp(arg
, "-weak_framework") == 0 ) {
2760 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2761 snapshotArgCount
= 0;
2762 FileInfo info
= findFramework(argv
[++i
]);
2763 info
.options
.fWeakImport
= true;
2764 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2767 else if ( strcmp(arg
, "-lazy_framework") == 0 ) {
2768 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2769 snapshotArgCount
= 0;
2770 FileInfo info
= findFramework(argv
[++i
]);
2771 info
.options
.fLazyLoad
= true;
2772 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2774 fUsingLazyDylibLinking
= true;
2775 cannotBeUsedWithBitcode(arg
);
2777 else if ( strcmp(arg
, "-search_paths_first") == 0 ) {
2778 // previously handled by buildSearchPaths()
2780 else if ( strcmp(arg
, "-search_dylibs_first") == 0 ) {
2781 // previously handled by buildSearchPaths()
2783 else if ( strcmp(arg
, "-undefined") == 0 ) {
2784 setUndefinedTreatment(argv
[++i
]);
2785 cannotBeUsedWithBitcode(arg
);
2787 // Debugging output flag.
2788 else if ( strcmp(arg
, "-arch_multiple") == 0 ) {
2789 fMessagesPrefixedWithArchitecture
= true;
2791 // Specify what to do with relocations in read only
2792 // sections like .text. Could be errors, warnings,
2793 // or suppressed. Currently we do nothing with the
2795 else if ( strcmp(arg
, "-read_only_relocs") == 0 ) {
2796 switch ( parseTreatment(argv
[++i
]) ) {
2799 throw "-read_only_relocs missing [ warning | error | suppress ]";
2801 fWarnTextRelocs
= true;
2802 fAllowTextRelocs
= true;
2803 cannotBeUsedWithBitcode(arg
);
2806 fWarnTextRelocs
= false;
2807 fAllowTextRelocs
= true;
2808 cannotBeUsedWithBitcode(arg
);
2811 fWarnTextRelocs
= false;
2812 fAllowTextRelocs
= false;
2816 else if ( strcmp(arg
, "-sect_diff_relocs") == 0 ) {
2820 // Warn, error or make strong a mismatch between weak
2821 // and non-weak references.
2822 else if ( strcmp(arg
, "-weak_reference_mismatches") == 0 ) {
2823 setWeakReferenceMismatchTreatment(argv
[++i
]);
2825 // For a deployment target of 10.3 and earlier ld64 will
2826 // prebind an executable with 0s in all addresses that
2827 // are prebound. This can then be fixed up by update_prebinding
2828 // later. Prebinding is less useful on 10.4 and greater.
2829 else if ( strcmp(arg
, "-prebind") == 0 ) {
2831 cannotBeUsedWithBitcode(arg
);
2833 else if ( strcmp(arg
, "-noprebind") == 0 ) {
2837 else if ( strcmp(arg
, "-prebind_allow_overlap") == 0 ) {
2840 else if ( strcmp(arg
, "-prebind_all_twolevel_modules") == 0 ) {
2843 else if ( strcmp(arg
, "-noprebind_all_twolevel_modules") == 0 ) {
2846 else if ( strcmp(arg
, "-nofixprebinding") == 0 ) {
2849 // This should probably be deprecated when we respect -L and -F
2850 // when searching for libraries.
2851 else if ( strcmp(arg
, "-dylib_file") == 0 ) {
2852 // ignore for snapshot because a stub dylib will be created in the snapshot
2853 snapshotArgCount
= 0;
2854 addDylibOverride(argv
[++i
]);
2855 cannotBeUsedWithBitcode(arg
);
2857 // What to expand @executable_path to if found in dependent dylibs
2858 else if ( strcmp(arg
, "-executable_path") == 0 ) {
2859 fExecutablePath
= argv
[++i
];
2860 if ( (fExecutablePath
== NULL
) || (fExecutablePath
[0] == '-') )
2861 throw "-executable_path missing <path>";
2862 // if a directory was passed, add / to end
2863 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2864 struct stat statBuffer
;
2865 if ( stat(fExecutablePath
, &statBuffer
) == 0 ) {
2866 if ( (statBuffer
.st_mode
& S_IFMT
) == S_IFDIR
) {
2867 char* pathWithSlash
= new char[strlen(fExecutablePath
)+2];
2868 strcpy(pathWithSlash
, fExecutablePath
);
2869 strcat(pathWithSlash
, "/");
2870 fExecutablePath
= pathWithSlash
;
2874 // Aligns all segments to the power of 2 boundary specified.
2875 else if ( strcmp(arg
, "-segalign") == 0 ) {
2876 const char* size
= argv
[++i
];
2878 throw "-segalign missing <size>";
2879 fSegmentAlignment
= parseAddress(size
);
2880 uint8_t alignment
= (uint8_t)__builtin_ctz(fSegmentAlignment
);
2881 uint32_t p2aligned
= (1 << alignment
);
2882 if ( p2aligned
!= fSegmentAlignment
) {
2883 warning("alignment for -segalign %s is not a power of two, using 0x%X", size
, p2aligned
);
2884 fSegmentAlignment
= p2aligned
;
2886 cannotBeUsedWithBitcode(arg
);
2888 // Puts a specified segment at a particular address that must
2889 // be a multiple of the segment alignment.
2890 else if ( strcmp(arg
, "-segaddr") == 0 ) {
2892 seg
.name
= argv
[++i
];
2893 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2894 throw "-segaddr missing segName Adddress";
2895 seg
.address
= parseAddress(argv
[++i
]);
2896 uint64_t temp
= ((seg
.address
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
2897 if ( seg
.address
!= temp
)
2898 warning("-segaddr %s not %lld byte aligned", seg
.name
, fSegmentAlignment
);
2899 fCustomSegmentAddresses
.push_back(seg
);
2900 cannotBeUsedWithBitcode(arg
);
2902 // ??? Deprecate when we deprecate split-seg.
2903 else if ( strcmp(arg
, "-segs_read_only_addr") == 0 ) {
2904 fBaseAddress
= parseAddress(argv
[++i
]);
2905 cannotBeUsedWithBitcode(arg
);
2907 // ??? Deprecate when we deprecate split-seg.
2908 else if ( strcmp(arg
, "-segs_read_write_addr") == 0 ) {
2909 fBaseWritableAddress
= parseAddress(argv
[++i
]);
2911 cannotBeUsedWithBitcode(arg
);
2913 // ??? Deprecate when we get rid of basing at build time.
2914 else if ( strcmp(arg
, "-seg_addr_table") == 0 ) {
2915 snapshotFileArgIndex
= 1;
2916 const char* name
= argv
[++i
];
2918 throw "-seg_addr_table missing argument";
2919 fSegAddrTablePath
= name
;
2920 cannotBeUsedWithBitcode(arg
);
2922 else if ( strcmp(arg
, "-seg_addr_table_filename") == 0 ) {
2926 else if ( strcmp(arg
, "-segprot") == 0 ) {
2928 seg
.name
= argv
[++i
];
2929 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) || (argv
[i
+2] == NULL
) )
2930 throw "-segprot missing segName max-prot init-prot";
2931 seg
.max
= parseProtection(argv
[++i
]);
2932 seg
.init
= parseProtection(argv
[++i
]);
2933 if ( strcmp(seg
.name
, "__LINKEDIT") == 0 )
2934 warning("-segprot cannot be used to modify __LINKEDIT protections");
2936 fCustomSegmentProtections
.push_back(seg
);
2937 cannotBeUsedWithBitcode(arg
);
2939 else if ( strcmp(arg
, "-pagezero_size") == 0 ) {
2940 const char* size
= argv
[++i
];
2942 throw "-pagezero_size missing <size>";
2943 fZeroPageSize
= parseAddress(size
);
2944 uint64_t temp
= fZeroPageSize
& (-4096); // page align
2945 if ( (fZeroPageSize
!= temp
) )
2946 warning("-pagezero_size not page aligned, rounding down");
2947 fZeroPageSize
= temp
;
2948 cannotBeUsedWithBitcode(arg
);
2950 else if ( strcmp(arg
, "-stack_addr") == 0 ) {
2951 const char* address
= argv
[++i
];
2952 if ( address
== NULL
)
2953 throw "-stack_addr missing <address>";
2954 fStackAddr
= parseAddress(address
);
2955 cannotBeUsedWithBitcode(arg
);
2957 else if ( strcmp(arg
, "-stack_size") == 0 ) {
2958 const char* size
= argv
[++i
];
2960 throw "-stack_size missing <address>";
2961 fStackSize
= parseAddress(size
);
2963 else if ( strcmp(arg
, "-allow_stack_execute") == 0 ) {
2964 fExecutableStack
= true;
2965 cannotBeUsedWithBitcode(arg
);
2967 else if ( strcmp(arg
, "-allow_heap_execute") == 0 ) {
2968 fDisableNonExecutableHeap
= true;
2969 cannotBeUsedWithBitcode(arg
);
2971 else if ( strcmp(arg
, "-sectalign") == 0 ) {
2972 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2973 throw "-sectalign missing <segment> <section> <file-path>";
2974 addSectionAlignment(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2976 cannotBeUsedWithBitcode(arg
);
2978 else if ( strcmp(arg
, "-sectorder_detail") == 0 ) {
2981 else if ( strcmp(arg
, "-sectobjectsymbols") == 0 ) {
2985 else if ( strcmp(arg
, "-bundle_loader") == 0 ) {
2986 snapshotFileArgIndex
= 1;
2987 fBundleLoader
= argv
[++i
];
2988 if ( (fBundleLoader
== NULL
) || (fBundleLoader
[0] == '-') )
2989 throw "-bundle_loader missing <path>";
2990 FileInfo info
= findFile(fBundleLoader
);
2991 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2992 info
.options
.fBundleLoader
= true;
2993 fInputFiles
.push_back(info
);
2995 else if ( strcmp(arg
, "-private_bundle") == 0 ) {
2998 else if ( strcmp(arg
, "-twolevel_namespace_hints") == 0 ) {
3001 // Use this flag to set default behavior for deployement targets.
3002 else if ( strcmp(arg
, "-macosx_version_min") == 0 ) {
3003 const char* macVers
= argv
[++i
];
3004 if ( macVers
== NULL
)
3005 throw "-macosx_version_min missing version argument";
3006 const char* envMacVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
3007 const char* enviPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
3008 if ( (envMacVers
!= NULL
) && (enviPhoneVers
!= NULL
) ) {
3009 // <rdar://problem/13774329> when conflicting deployments set, break tie by looking at syslibroot
3010 warning("both MACOSX_DEPLOYMENT_TARGET and IPHONEOS_DEPLOYMENT_TARGET are set");
3011 if ( !fSDKPaths
.empty() ) {
3012 const char* sysrootPath
= fSDKPaths
.back();
3013 const char* lastSlash
= strrchr(sysrootPath
, '/');
3014 if ( strstr(lastSlash
, "Simulator") != NULL
)
3015 setIOSVersionMin(enviPhoneVers
);
3017 setMacOSXVersionMin(macVers
);
3020 setMacOSXVersionMin(macVers
);
3024 setMacOSXVersionMin(macVers
);
3027 else if ( (strcmp(arg
, "-ios_version_min") == 0) || (strcmp(arg
, "-iphoneos_version_min") == 0) ) {
3028 const char* vers
= argv
[++i
];
3030 throw "-ios_version_min missing version argument";
3031 setIOSVersionMin(vers
);
3033 else if ( strcmp(arg
, "-ios_simulator_version_min") == 0 ) {
3034 const char* vers
= argv
[++i
];
3036 throw "-ios_simulator_version_min missing version argument";
3037 setIOSVersionMin(vers
);
3038 fTargetIOSSimulator
= true;
3040 else if ( strcmp(arg
, "-watchos_version_min") == 0 ) {
3041 const char* vers
= argv
[++i
];
3043 throw "-watchos_version_min missing version argument";
3044 setWatchOSVersionMin(vers
);
3046 else if ( strcmp(arg
, "-watchos_simulator_version_min") == 0 ) {
3047 const char* vers
= argv
[++i
];
3049 throw "-watchos_simulator_version_min missing version argument";
3050 setWatchOSVersionMin(vers
);
3051 fTargetIOSSimulator
= true;
3053 #if SUPPORT_APPLE_TV
3054 else if ( strcmp(arg
, "-tvos_version_min") == 0 ) {
3055 const char* vers
= argv
[++i
];
3057 throw "-tvos_version_min missing version argument";
3058 setIOSVersionMin(vers
);
3059 fPlatform
= kPlatform_tvOS
;
3061 else if ( strcmp(arg
, "-tvos_simulator_version_min") == 0 ) {
3062 const char* vers
= argv
[++i
];
3064 throw "-tvos_simulator_version_min missing version argument";
3065 setIOSVersionMin(vers
);
3066 fPlatform
= kPlatform_tvOS
;
3067 fTargetIOSSimulator
= true;
3070 else if ( strcmp(arg
, "-bridgeos_version_min") == 0 ) {
3071 const char* vers
= argv
[++i
];
3073 throw "-bridgeos_version_min missing version argument";
3074 setIOSVersionMin(vers
);
3075 fPlatform
= kPlatform_bridgeOS
;
3077 else if ( strcmp(arg
, "-multiply_defined") == 0 ) {
3078 //warnObsolete(arg);
3081 else if ( strcmp(arg
, "-multiply_defined_unused") == 0 ) {
3085 else if ( strcmp(arg
, "-nomultidefs") == 0 ) {
3088 // Display each file in which the argument symbol appears and whether
3089 // the file defines or references it. This option takes an argument
3090 // as -y<symbol> note that there is no space.
3091 else if ( strncmp(arg
, "-y", 2) == 0 ) {
3094 // Same output as -y, but output <arg> number of undefined symbols only.
3095 else if ( strcmp(arg
, "-Y") == 0 ) {
3096 //warnObsolete(arg);
3099 // This option affects all objects linked into the final result.
3100 else if ( strcmp(arg
, "-m") == 0 ) {
3103 else if ( (strcmp(arg
, "-why_load") == 0) || (strcmp(arg
, "-whyload") == 0) ) {
3106 else if ( strcmp(arg
, "-why_live") == 0 ) {
3107 const char* name
= argv
[++i
];
3109 throw "-why_live missing symbol name argument";
3110 fWhyLive
.insert(name
);
3112 else if ( strcmp(arg
, "-u") == 0 ) {
3113 const char* name
= argv
[++i
];
3115 throw "-u missing argument";
3116 fInitialUndefines
.push_back(name
);
3117 cannotBeUsedWithBitcode(arg
);
3119 else if ( strcmp(arg
, "-U") == 0 ) {
3120 const char* name
= argv
[++i
];
3122 throw "-U missing argument";
3123 fAllowedUndefined
.insert(name
);
3124 cannotBeUsedWithBitcode(arg
);
3126 else if ( strcmp(arg
, "-s") == 0 ) {
3128 fLocalSymbolHandling
= kLocalSymbolsNone
;
3129 fDebugInfoStripping
= Options::kDebugInfoNone
;
3131 else if ( strcmp(arg
, "-x") == 0 ) {
3132 fLocalSymbolHandling
= kLocalSymbolsNone
;
3134 else if ( strcmp(arg
, "-S") == 0 ) {
3135 fDebugInfoStripping
= Options::kDebugInfoNone
;
3137 else if ( strcmp(arg
, "-X") == 0 ) {
3140 else if ( strcmp(arg
, "-Si") == 0 ) {
3142 fDebugInfoStripping
= Options::kDebugInfoFull
;
3144 else if ( strcmp(arg
, "-b") == 0 ) {
3147 else if ( strcmp(arg
, "-Sn") == 0 ) {
3149 fDebugInfoStripping
= Options::kDebugInfoFull
;
3151 else if ( strcmp(arg
, "-Sp") == 0 ) {
3154 else if ( strcmp(arg
, "-dead_strip") == 0 ) {
3157 else if ( strcmp(arg
, "-no_dead_strip_inits_and_terms") == 0 ) {
3160 else if ( strcmp(arg
, "-w") == 0 ) {
3161 // previously handled by buildSearchPaths()
3163 else if ( strcmp(arg
, "-fatal_warnings") == 0 ) {
3164 // previously handled by buildSearchPaths()
3166 else if ( strcmp(arg
, "-arch_errors_fatal") == 0 ) {
3167 fErrorOnOtherArchFiles
= true;
3169 else if ( strcmp(arg
, "-M") == 0 ) {
3172 else if ( strcmp(arg
, "-headerpad") == 0 ) {
3173 const char* size
= argv
[++i
];
3175 throw "-headerpad missing argument";
3176 fMinimumHeaderPad
= parseAddress(size
);
3177 cannotBeUsedWithBitcode(arg
);
3179 else if ( strcmp(arg
, "-headerpad_max_install_names") == 0 ) {
3180 // ignore -headerpad_max_install_names when compiling with bitcode
3181 // rdar://problem/20748962
3182 if ( fBundleBitcode
)
3183 warning("-headerpad_max_install_names is ignored when used with -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES)");
3185 fMaxMinimumHeaderPad
= true;
3187 else if ( strcmp(arg
, "-t") == 0 ) {
3188 fLogAllFiles
= true;
3190 else if ( strcmp(arg
, "-whatsloaded") == 0 ) {
3191 fLogObjectFiles
= true;
3193 else if ( strcmp(arg
, "-A") == 0 ) {
3197 else if ( strcmp(arg
, "-umbrella") == 0 ) {
3198 const char* name
= argv
[++i
];
3200 throw "-umbrella missing argument";
3201 fUmbrellaName
= name
;
3202 cannotBeUsedWithBitcode(arg
);
3204 else if ( strcmp(arg
, "-allowable_client") == 0 ) {
3205 const char* name
= argv
[++i
];
3208 throw "-allowable_client missing argument";
3210 fAllowableClients
.push_back(name
);
3211 cannotBeUsedWithBitcode(arg
);
3213 else if ( strcmp(arg
, "-client_name") == 0 ) {
3214 const char* name
= argv
[++i
];
3217 throw "-client_name missing argument";
3220 cannotBeUsedWithBitcode(arg
);
3222 else if ( strcmp(arg
, "-sub_umbrella") == 0 ) {
3223 const char* name
= argv
[++i
];
3225 throw "-sub_umbrella missing argument";
3226 fSubUmbellas
.push_back(name
);
3227 cannotBeUsedWithBitcode(arg
);
3229 else if ( strcmp(arg
, "-sub_library") == 0 ) {
3230 const char* name
= argv
[++i
];
3232 throw "-sub_library missing argument";
3233 fSubLibraries
.push_back(name
);
3234 cannotBeUsedWithBitcode(arg
);
3236 else if ( strcmp(arg
, "-init") == 0 ) {
3237 const char* name
= argv
[++i
];
3239 throw "-init missing argument";
3240 fInitFunctionName
= name
;
3241 cannotBeUsedWithBitcode(arg
);
3243 else if ( strcmp(arg
, "-dot") == 0 ) {
3244 const char* name
= argv
[++i
];
3246 throw "-dot missing argument";
3247 fDotOutputFile
= name
;
3248 cannotBeUsedWithBitcode(arg
);
3250 else if ( strcmp(arg
, "-warn_commons") == 0 ) {
3251 fWarnCommons
= true;
3253 else if ( strcmp(arg
, "-commons") == 0 ) {
3254 fCommonsMode
= parseCommonsTreatment(argv
[++i
]);
3256 else if ( strcmp(arg
, "-keep_relocs") == 0 ) {
3257 fKeepRelocations
= true;
3259 else if ( strcmp(arg
, "-warn_stabs") == 0 ) {
3262 else if ( strcmp(arg
, "-pause") == 0 ) {
3265 else if ( strcmp(arg
, "-print_statistics") == 0 ) {
3268 else if ( strcmp(arg
, "-d") == 0 ) {
3269 fMakeTentativeDefinitionsReal
= true;
3271 else if ( strcmp(arg
, "-v") == 0 ) {
3272 // previously handled by buildSearchPaths()
3274 else if ( strcmp(arg
, "-Z") == 0 ) {
3275 // previously handled by buildSearchPaths()
3277 else if ( strcmp(arg
, "-syslibroot") == 0 ) {
3278 snapshotArgCount
= 0;
3280 // previously handled by buildSearchPaths()
3282 else if ( strcmp(arg
, "-bitcode_bundle") == 0 ) {
3283 snapshotArgCount
= 0;
3284 // previously handled by buildSearchPaths()
3286 else if ( strcmp(arg
, "-no_uuid") == 0 ) {
3287 fUUIDMode
= kUUIDNone
;
3288 cannotBeUsedWithBitcode(arg
);
3290 else if ( strcmp(arg
, "-random_uuid") == 0 ) {
3291 fUUIDMode
= kUUIDRandom
;
3292 cannotBeUsedWithBitcode(arg
);
3294 else if ( strcmp(arg
, "-dtrace") == 0 ) {
3295 snapshotFileArgIndex
= 1;
3296 const char* name
= argv
[++i
];
3298 throw "-dtrace missing argument";
3299 fDtraceScriptName
= name
;
3300 cannotBeUsedWithBitcode(arg
);
3302 else if ( strcmp(arg
, "-root_safe") == 0 ) {
3305 else if ( strcmp(arg
, "-setuid_safe") == 0 ) {
3308 else if ( strcmp(arg
, "-alias") == 0 ) {
3309 Options::AliasPair pair
;
3310 pair
.realName
= argv
[++i
];
3311 if ( pair
.realName
== NULL
)
3312 throw "missing argument to -alias";
3313 pair
.alias
= argv
[++i
];
3314 if ( pair
.alias
== NULL
)
3315 throw "missing argument to -alias";
3316 fAliases
.push_back(pair
);
3317 cannotBeUsedWithBitcode(arg
);
3319 else if ( strcmp(arg
, "-alias_list") == 0 ) {
3320 snapshotFileArgIndex
= 1;
3321 parseAliasFile(argv
[++i
]);
3322 cannotBeUsedWithBitcode(arg
);
3324 else if ( strcmp(arg
, "-save-temps") == 0 ) {
3325 fSaveTempFiles
= true;
3327 else if ( strcmp(arg
, "-bitcode_hide_symbols") == 0 ) {
3328 fHideSymbols
= true;
3330 else if ( strcmp(arg
, "-bitcode_verify") == 0 ) {
3331 fVerifyBitcode
= true;
3333 else if ( strcmp(arg
, "-bitcode_symbol_map") == 0) {
3334 fReverseMapPath
= argv
[++i
];
3335 if ( fReverseMapPath
== NULL
)
3336 throw "missing argument to -bitcode_symbol_map";
3337 struct stat statbuf
;
3338 int ret
= ::stat(fReverseMapPath
, &statbuf
);
3339 if ( ret
== 0 && S_ISDIR(statbuf
.st_mode
)) {
3340 char tempPath
[PATH_MAX
];
3341 sprintf(tempPath
, "%s/XXXXXX", fReverseMapPath
);
3342 int tempFile
= ::mkstemp(tempPath
);
3344 throwf("could not write file to symbol map directory: %s", fReverseMapPath
);
3346 fReverseMapTempPath
= std::string(tempPath
);
3347 fReverseMapUUIDRename
= true;
3349 fReverseMapTempPath
= std::string(fReverseMapPath
);
3351 else if ( strcmp(argv
[i
], "-flto-codegen-only") == 0) {
3352 fLTOCodegenOnly
= true;
3354 else if ( strcmp(argv
[i
], "-ignore_auto_link") == 0) {
3355 fIgnoreAutoLink
= true;
3357 else if ( strcmp(argv
[i
], "-allow_dead_duplicates") == 0) {
3358 fAllowDeadDups
= true;
3360 else if ( strcmp(argv
[i
], "-bitcode_process_mode") == 0 ) {
3361 const char* bitcode_type
= argv
[++i
];
3362 if ( bitcode_type
== NULL
)
3363 throw "missing argument to -bitcode_process_mode";
3364 else if ( strcmp(bitcode_type
, "strip") == 0 )
3365 fBitcodeKind
= kBitcodeStrip
;
3366 else if ( strcmp(bitcode_type
, "marker") == 0 )
3367 fBitcodeKind
= kBitcodeMarker
;
3368 else if ( strcmp(bitcode_type
, "data") == 0 )
3369 fBitcodeKind
= kBitcodeAsData
;
3370 else if ( strcmp(bitcode_type
, "bitcode") == 0 )
3371 fBitcodeKind
= kBitcodeProcess
;
3373 throw "unknown argument to -bitcode_process_mode {strip,marker,data,bitcode}";
3375 else if ( strcmp(arg
, "-rpath") == 0 ) {
3376 const char* path
= argv
[++i
];
3378 throw "missing argument to -rpath";
3379 fRPaths
.push_back(path
);
3381 else if ( strcmp(arg
, "-read_only_stubs") == 0 ) {
3382 fReadOnlyx86Stubs
= true;
3384 else if ( strcmp(arg
, "-slow_stubs") == 0 ) {
3387 else if ( strcmp(arg
, "-map") == 0 ) {
3388 fMapPath
= argv
[++i
];
3389 if ( fMapPath
== NULL
)
3390 throw "missing argument to -map";
3392 else if ( strcmp(arg
, "-pie") == 0 ) {
3393 fPositionIndependentExecutable
= true;
3394 fPIEOnCommandLine
= true;
3396 else if ( strcmp(arg
, "-no_pie") == 0 ) {
3397 fDisablePositionIndependentExecutable
= true;
3398 cannotBeUsedWithBitcode(arg
);
3400 else if ( strncmp(arg
, "-reexport-l", 11) == 0 ) {
3401 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3402 snapshotArgCount
= 0;
3403 FileInfo info
= findLibrary(&arg
[11], true);
3404 info
.options
.fReExport
= true;
3405 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3407 cannotBeUsedWithBitcode(arg
);
3409 else if ( strcmp(arg
, "-reexport_library") == 0 ) {
3410 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3411 snapshotArgCount
= 0;
3412 FileInfo info
= findFile(argv
[++i
]);
3413 info
.options
.fReExport
= true;
3414 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3416 cannotBeUsedWithBitcode(arg
);
3418 else if ( strcmp(arg
, "-reexport_framework") == 0 ) {
3419 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3420 snapshotArgCount
= 0;
3421 FileInfo info
= findFramework(argv
[++i
]);
3422 info
.options
.fReExport
= true;
3423 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3425 cannotBeUsedWithBitcode(arg
);
3427 else if ( strncmp(arg
, "-upward-l", 9) == 0 ) {
3428 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3429 snapshotArgCount
= 0;
3430 FileInfo info
= findLibrary(&arg
[9], true);
3431 info
.options
.fUpward
= true;
3432 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3434 cannotBeUsedWithBitcode(arg
);
3436 else if ( strcmp(arg
, "-upward_library") == 0 ) {
3437 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3438 snapshotArgCount
= 0;
3439 FileInfo info
= findFile(argv
[++i
]);
3440 info
.options
.fUpward
= true;
3441 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3443 cannotBeUsedWithBitcode(arg
);
3445 else if ( strcmp(arg
, "-upward_framework") == 0 ) {
3446 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3447 snapshotArgCount
= 0;
3448 FileInfo info
= findFramework(argv
[++i
]);
3449 info
.options
.fUpward
= true;
3450 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3452 cannotBeUsedWithBitcode(arg
);
3454 else if ( strcmp(arg
, "-dead_strip_dylibs") == 0 ) {
3455 fDeadStripDylibs
= true;
3456 cannotBeUsedWithBitcode(arg
);
3458 else if ( strcmp(arg
, "-no_implicit_dylibs") == 0 ) {
3459 fImplicitlyLinkPublicDylibs
= false;
3461 else if ( strcmp(arg
, "-new_linker") == 0 ) {
3464 else if ( strcmp(arg
, "-no_encryption") == 0 ) {
3465 fEncryptableForceOff
= true;
3466 cannotBeUsedWithBitcode(arg
);
3468 else if ( strcmp(arg
, "-encryptable") == 0 ) {
3469 fEncryptableForceOn
= true;
3470 cannotBeUsedWithBitcode(arg
);
3472 else if ( strcmp(arg
, "-no_compact_unwind") == 0 ) {
3473 fAddCompactUnwindEncoding
= false;
3474 cannotBeUsedWithBitcode(arg
);
3476 else if ( strcmp(arg
, "-mllvm") == 0 ) {
3477 const char* opts
= argv
[++i
];
3479 throw "missing argument to -mllvm";
3480 fLLVMOptions
.push_back(opts
);
3481 cannotBeUsedWithBitcode(arg
);
3483 else if ( strcmp(arg
, "-mcpu") == 0 ) {
3484 const char* cpu
= argv
[++i
];
3486 throw "missing argument to -mcpu";
3488 cannotBeUsedWithBitcode(arg
);
3490 else if ( strcmp(arg
, "-no_order_inits") == 0 ) {
3491 fAutoOrderInitializers
= false;
3492 cannotBeUsedWithBitcode(arg
);
3494 else if ( strcmp(arg
, "-no_order_data") == 0 ) {
3496 cannotBeUsedWithBitcode(arg
);
3498 else if ( strcmp(arg
, "-seg_page_size") == 0 ) {
3500 seg
.name
= argv
[++i
];
3501 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
3502 throw "-seg_page_size missing segName Adddress";
3503 seg
.size
= parseAddress(argv
[++i
]);
3504 uint64_t temp
= seg
.size
& (-4096); // page align
3505 if ( (seg
.size
!= temp
) )
3506 warning("-seg_page_size %s not 4K aligned, rounding down", seg
.name
);
3507 fCustomSegmentSizes
.push_back(seg
);
3508 cannotBeUsedWithBitcode(arg
);
3510 else if ( strcmp(arg
, "-mark_dead_strippable_dylib") == 0 ) {
3511 fMarkDeadStrippableDylib
= true;
3512 cannotBeUsedWithBitcode(arg
);
3514 else if ( strcmp(arg
, "-exported_symbols_order") == 0 ) {
3515 snapshotFileArgIndex
= 1;
3516 loadSymbolOrderFile(argv
[++i
], fExportSymbolsOrder
);
3517 cannotBeUsedWithBitcode(arg
);
3519 else if ( strcmp(arg
, "-no_compact_linkedit") == 0 ) {
3520 warnObsolete("-no_compact_linkedit");
3522 else if ( strcmp(arg
, "-no_eh_labels") == 0 ) {
3524 cannotBeUsedWithBitcode(arg
);
3526 else if ( strcmp(arg
, "-warn_compact_unwind") == 0 ) {
3527 fWarnCompactUnwind
= true;
3529 else if ( strcmp(arg
, "-allow_sub_type_mismatches") == 0 ) {
3530 fAllowCpuSubtypeMismatches
= true;
3531 cannotBeUsedWithBitcode(arg
);
3533 else if ( strcmp(arg
, "-no_zero_fill_sections") == 0 ) {
3534 fOptimizeZeroFill
= false;
3535 cannotBeUsedWithBitcode(arg
);
3537 else if ( strcmp(arg
, "-merge_zero_fill_sections") == 0 ) {
3538 fMergeZeroFill
= true;
3539 cannotBeUsedWithBitcode(arg
);
3541 else if ( strcmp(arg
, "-objc_abi_version") == 0 ) {
3542 const char* version
= argv
[++i
];
3543 if ( version
== NULL
)
3544 throw "-objc_abi_version missing version number";
3545 if ( strcmp(version
, "2") == 0 ) {
3546 fObjCABIVersion1Override
= false;
3547 fObjCABIVersion2Override
= true;
3549 else if ( strcmp(version
, "1") == 0 ) {
3550 fObjCABIVersion1Override
= true;
3551 fObjCABIVersion2Override
= false;
3554 warning("ignoring unrecognized argument (%s) to -objc_abi_version", version
);
3556 else if ( strcmp(arg
, "-warn_weak_exports") == 0 ) {
3557 fWarnWeakExports
= true;
3559 else if ( strcmp(arg
, "-no_weak_exports") == 0 ) {
3560 fNoWeakExports
= true;
3562 else if ( strcmp(arg
, "-objc_gc_compaction") == 0 ) {
3563 fObjcGcCompaction
= true;
3564 cannotBeUsedWithBitcode(arg
);
3566 else if ( strcmp(arg
, "-objc_gc") == 0 ) {
3568 if ( fObjCGcOnly
) {
3569 warning("-objc_gc overriding -objc_gc_only");
3570 fObjCGcOnly
= false;
3572 cannotBeUsedWithBitcode(arg
);
3574 else if ( strcmp(arg
, "-objc_gc_only") == 0 ) {
3577 warning("-objc_gc_only overriding -objc_gc");
3580 cannotBeUsedWithBitcode(arg
);
3582 else if ( strcmp(arg
, "-demangle") == 0 ) {
3585 else if ( strcmp(arg
, "-version_load_command") == 0 ) {
3586 fVersionLoadCommandForcedOn
= true;
3587 fVersionLoadCommandForcedOff
= false;
3589 else if ( strcmp(arg
, "-no_version_load_command") == 0 ) {
3590 fVersionLoadCommandForcedOff
= true;
3591 fVersionLoadCommandForcedOn
= false;
3592 cannotBeUsedWithBitcode(arg
);
3594 else if ( strcmp(arg
, "-function_starts") == 0 ) {
3595 fFunctionStartsForcedOn
= true;
3596 fFunctionStartsForcedOff
= false;
3598 else if ( strcmp(arg
, "-no_function_starts") == 0 ) {
3599 fFunctionStartsForcedOff
= true;
3600 fFunctionStartsForcedOn
= false;
3601 cannotBeUsedWithBitcode(arg
);
3603 else if ( strcmp(arg
, "-no_data_in_code_info") == 0 ) {
3604 fDataInCodeInfoLoadCommandForcedOff
= true;
3605 fDataInCodeInfoLoadCommandForcedOn
= false;
3606 cannotBeUsedWithBitcode(arg
);
3608 else if ( strcmp(arg
, "-data_in_code_info") == 0 ) {
3609 fDataInCodeInfoLoadCommandForcedOn
= true;
3610 fDataInCodeInfoLoadCommandForcedOff
= false;
3612 else if ( strcmp(arg
, "-object_path_lto") == 0 ) {
3613 fTempLtoObjectPath
= argv
[++i
];
3614 if ( fTempLtoObjectPath
== NULL
)
3615 throw "missing argument to -object_path_lto";
3617 else if ( strcmp(arg
, "-no_objc_category_merging") == 0 ) {
3618 fObjcCategoryMerging
= false;
3620 else if ( strcmp(arg
, "-force_symbols_weak_list") == 0 ) {
3621 snapshotFileArgIndex
= 1;
3622 loadExportFile(argv
[++i
], "-force_symbols_weak_list", fForceWeakSymbols
);
3623 cannotBeUsedWithBitcode(arg
);
3625 else if ( strcmp(arg
, "-force_symbols_not_weak_list") == 0 ) {
3626 snapshotFileArgIndex
= 1;
3627 loadExportFile(argv
[++i
], "-force_symbols_not_weak_list", fForceNotWeakSymbols
);
3628 cannotBeUsedWithBitcode(arg
);
3630 else if ( strcmp(arg
, "-force_symbol_weak") == 0 ) {
3631 const char* symbol
= argv
[++i
];
3632 if ( symbol
== NULL
)
3633 throw "-force_symbol_weak missing <symbol>";
3634 fForceWeakSymbols
.insert(symbol
);
3635 cannotBeUsedWithBitcode(arg
);
3637 else if ( strcmp(arg
, "-force_symbol_not_weak") == 0 ) {
3638 const char* symbol
= argv
[++i
];
3639 if ( symbol
== NULL
)
3640 throw "-force_symbol_not_weak missing <symbol>";
3641 fForceNotWeakSymbols
.insert(symbol
);
3642 cannotBeUsedWithBitcode(arg
);
3644 else if ( strcmp(arg
, "-reexported_symbols_list") == 0 ) {
3645 snapshotFileArgIndex
= 1;
3646 if ( fExportMode
== kExportSome
)
3647 throw "can't use -exported_symbols_list and -reexported_symbols_list";
3648 loadExportFile(argv
[++i
], "-reexported_symbols_list", fReExportSymbols
);
3650 else if ( strcmp(arg
, "-dyld_env") == 0 ) {
3651 const char* envarg
= argv
[++i
];
3652 if ( envarg
== NULL
)
3653 throw "-dyld_env missing ENV=VALUE";
3654 if ( strchr(envarg
, '=') == NULL
)
3655 throw "-dyld_env missing ENV=VALUE";
3656 fDyldEnvironExtras
.push_back(envarg
);
3657 cannotBeUsedWithBitcode(arg
);
3659 else if ( strcmp(arg
, "-page_align_data_atoms") == 0 ) {
3660 fPageAlignDataAtoms
= true;
3661 cannotBeUsedWithBitcode(arg
);
3663 else if (strcmp(arg
, "-debug_snapshot") == 0) {
3664 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
3665 fSnapshotRequested
= true;
3666 cannotBeUsedWithBitcode(arg
);
3668 else if (strcmp(arg
, "-snapshot_dir") == 0) {
3669 const char* path
= argv
[++i
];
3671 throw "-snapshot_dir missing path";
3672 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
3673 fLinkSnapshot
.setSnapshotPath(path
);
3674 fSnapshotRequested
= true;
3675 cannotBeUsedWithBitcode(arg
);
3677 else if ( strcmp(arg
, "-new_main") == 0 ) {
3678 fEntryPointLoadCommandForceOn
= true;
3679 cannotBeUsedWithBitcode(arg
);
3681 else if ( strcmp(arg
, "-no_new_main") == 0 ) {
3682 fEntryPointLoadCommandForceOff
= true;
3683 cannotBeUsedWithBitcode(arg
);
3685 else if ( strcmp(arg
, "-source_version") == 0 ) {
3686 const char* vers
= argv
[++i
];
3688 throw "-source_version missing <version>";
3689 fSourceVersion
= parseVersionNumber64(vers
);
3691 else if ( strcmp(arg
, "-add_source_version") == 0 ) {
3692 fSourceVersionLoadCommandForceOn
= true;
3694 else if ( strcmp(arg
, "-no_source_version") == 0 ) {
3695 fSourceVersionLoadCommandForceOff
= true;
3696 cannotBeUsedWithBitcode(arg
);
3698 else if ( strcmp(arg
, "-sdk_version") == 0 ) {
3699 const char* vers
= argv
[++i
];
3701 throw "-sdk_version missing <version>";
3702 fSDKVersion
= parseVersionNumber32(vers
);
3704 else if ( strcmp(arg
, "-dependent_dr_info") == 0 ) {
3707 else if ( strcmp(arg
, "-no_dependent_dr_info") == 0 ) {
3710 else if ( strcmp(arg
, "-kexts_use_stubs") == 0 ) {
3711 fKextsUseStubs
= true;
3712 cannotBeUsedWithBitcode(arg
);
3714 else if ( strcmp(argv
[i
], "-dependency_info") == 0 ) {
3715 snapshotArgCount
= 0;
3717 // previously handled by buildSearchPaths()
3719 else if ( strcmp(arg
, "-export_dynamic") == 0 ) {
3720 fExportDynamic
= true;
3722 else if ( strcmp(arg
, "-force_symbols_coalesce_list") == 0 ) {
3723 snapshotFileArgIndex
= 1;
3724 loadExportFile(argv
[++i
], "-force_symbols_coalesce_list", fForceCoalesceSymbols
);
3726 else if ( strcmp(arg
, "-add_linker_option") == 0 ) {
3727 // ex: -add_linker_option '-framework Foundation'
3728 const char* optString
= argv
[++i
];
3729 if ( optString
== NULL
)
3730 throw "-add_linker_option missing <option>";
3731 // break up into list of tokens at whitespace
3732 std::vector
<const char*> opts
;
3733 char* buffer
= strdup(optString
);
3734 char* start
= buffer
;
3735 for (char* s
= buffer
; ; ++s
) {
3736 if ( isspace(*s
) ) {
3738 opts
.push_back(start
);
3741 else if ( *s
== '\0' ) {
3742 opts
.push_back(start
);
3746 fLinkerOptions
.push_back(opts
);
3747 cannotBeUsedWithBitcode(arg
);
3749 else if ( strcmp(arg
, "-allow_simulator_linking_to_macosx_dylibs") == 0 ) {
3750 fAllowSimulatorToLinkWithMacOSX
= true;
3751 cannotBeUsedWithBitcode(arg
);
3753 else if ( strcmp(arg
, "-keep_dwarf_unwind") == 0 ) {
3754 fKeepDwarfUnwindForcedOn
= true;
3755 fKeepDwarfUnwindForcedOff
= false;
3756 cannotBeUsedWithBitcode(arg
);
3758 else if ( strcmp(arg
, "-no_keep_dwarf_unwind") == 0 ) {
3759 fKeepDwarfUnwindForcedOn
= false;
3760 fKeepDwarfUnwindForcedOff
= true;
3761 cannotBeUsedWithBitcode(arg
);
3763 else if ( strcmp(arg
, "-verbose_optimization_hints") == 0 ) {
3764 fVerboseOptimizationHints
= true;
3766 else if ( strcmp(arg
, "-ignore_optimization_hints") == 0 ) {
3767 fIgnoreOptimizationHints
= true;
3768 cannotBeUsedWithBitcode(arg
);
3770 else if ( strcmp(arg
, "-no_dtrace_dof") == 0 ) {
3771 fGenerateDtraceDOF
= false;
3773 else if ( strcmp(arg
, "-rename_section") == 0 ) {
3774 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) || (argv
[i
+4]==NULL
) )
3775 throw "-rename_section missing <segment> <section> <segment> <section>";
3776 addSectionRename(argv
[i
+1], argv
[i
+2], argv
[i
+3], argv
[i
+4]);
3778 cannotBeUsedWithBitcode(arg
);
3780 else if ( strcmp(arg
, "-rename_segment") == 0 ) {
3781 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3782 throw "-rename_segment missing <existing-segment> <new-segment>";
3783 addSegmentRename(argv
[i
+1], argv
[i
+2]);
3785 cannotBeUsedWithBitcode(arg
);
3787 else if ( strcmp(arg
, "-move_to_ro_segment") == 0 ) {
3788 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3789 throw "-move_to_ro_segment missing <segment> <symbol-list-file>";
3790 addSymbolMove(argv
[i
+1], argv
[i
+2], fSymbolsMovesCode
, "-move_to_ro_segment");
3792 cannotBeUsedWithBitcode(arg
);
3794 else if ( strcmp(arg
, "-move_to_rw_segment") == 0 ) {
3795 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3796 throw "-move_to_rw_segment missing <segment> <symbol-list-file>";
3797 addSymbolMove(argv
[i
+1], argv
[i
+2], fSymbolsMovesData
, "-move_to_rw_segment");
3799 cannotBeUsedWithBitcode(arg
);
3801 else if ( strcmp(arg
, "-trace_symbol_layout") == 0 ) {
3802 fTraceSymbolLayout
= true;
3804 else if ( strcmp(arg
, "-no_branch_islands") == 0 ) {
3805 fAllowBranchIslands
= false;
3806 cannotBeUsedWithBitcode(arg
);
3808 else if ( strcmp(arg
, "-segment_order") == 0 ) {
3809 // ex: -segment_order __TEXT:__DATA:__JUNK
3810 const char* optString
= argv
[++i
];
3811 if ( optString
== NULL
)
3812 throw "-segment_order missing colon separated <segment-list>";
3813 if ( !fSegmentOrder
.empty() )
3814 throw "-segment_order used more than once";
3815 // break up into list of tokens at colon
3816 char* buffer
= strdup(optString
);
3817 char* start
= buffer
;
3818 for (char* s
= buffer
; ; ++s
) {
3821 fSegmentOrder
.push_back(start
);
3824 else if ( *s
== '\0' ) {
3825 fSegmentOrder
.push_back(start
);
3829 cannotBeUsedWithBitcode(arg
);
3831 else if ( strcmp(arg
, "-section_order") == 0 ) {
3832 // ex: -section_order __DATA __data:__const:__nl_pointers
3833 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3834 throw "-section_order missing <segment> <section-list>";
3835 const char* segName
= argv
[++i
];
3836 const char* optString
= argv
[++i
];
3837 if ( sectionOrder(segName
) != NULL
)
3838 throwf("-section_order %s ... used more than once", segName
);
3839 SectionOrderList dummy
;
3840 fSectionOrder
.push_back(dummy
);
3841 SectionOrderList
& entry
= fSectionOrder
.back();
3842 entry
.segmentName
= segName
;
3843 // break up into list of tokens at colon
3844 char* buffer
= strdup(optString
);
3845 char* start
= buffer
;
3846 for (char* s
= buffer
; ; ++s
) {
3849 entry
.sectionOrder
.push_back(start
);
3852 else if ( *s
== '\0' ) {
3853 entry
.sectionOrder
.push_back(start
);
3857 cannotBeUsedWithBitcode(arg
);
3859 else if ( strcmp(arg
, "-application_extension") == 0 ) {
3860 fMarkAppExtensionSafe
= true;
3861 fCheckAppExtensionSafe
= true;
3863 else if ( strcmp(arg
, "-no_application_extension") == 0 ) {
3864 fMarkAppExtensionSafe
= false;
3865 fCheckAppExtensionSafe
= false;
3867 else if ( strcmp(arg
, "-add_ast_path") == 0 ) {
3868 const char* path
= argv
[++i
];
3870 throw "-add_ast_path missing <option>";
3871 fASTFilePaths
.push_back(path
);
3873 else if ( strcmp(arg
, "-force_load_swift_libs") == 0 ) {
3874 fForceLoadSwiftLibs
= true;
3876 else if ( strcmp(arg
, "-not_for_dyld_shared_cache") == 0 ) {
3877 fSharedRegionEligibleForceOff
= true;
3878 cannotBeUsedWithBitcode(arg
);
3880 else if ( strcmp(arg
, "-dirty_data_list") == 0 ) {
3881 if ( argv
[i
+1] == NULL
)
3882 throw "-dirty_data_list missing <symbol-list-file>";
3883 addSymbolMove("__DATA_DIRTY", argv
[i
+1], fSymbolsMovesData
, "-dirty_data_list");
3885 cannotBeUsedWithBitcode(arg
);
3887 else if ( strcmp(arg
, "-data_const") == 0 ) {
3888 fUseDataConstSegmentForceOn
= true;
3889 cannotBeUsedWithBitcode(arg
);
3891 else if ( strcmp(arg
, "-no_data_const") == 0 ) {
3892 fUseDataConstSegmentForceOff
= true;
3893 cannotBeUsedWithBitcode(arg
);
3895 else if ( strcmp(arg
, "-text_exec") == 0 ) {
3896 fUseTextExecSegment
= true;
3897 cannotBeUsedWithBitcode(arg
);
3899 else if ( strcmp(arg
, "-add_split_seg_info") == 0) {
3900 fSharedRegionEligible
= true;
3901 cannotBeUsedWithBitcode(arg
);
3903 else if ( strcmp(arg
, "-no_deduplicate") == 0 ) {
3906 else if ( strcmp(arg
, "-verbose_deduplicate") == 0 ) {
3907 fVerboseDeDupe
= true;
3909 else if ( strcmp(arg
, "-max_default_common_align") == 0 ) {
3910 const char* alignStr
= argv
[++i
];
3911 if ( alignStr
== NULL
)
3912 throw "-max_default_common_align missing <align-value>";
3913 // argument is a hexadecimal number
3915 unsigned long value
= strtoul(alignStr
, &endptr
, 16);
3916 if ( *endptr
!= '\0')
3917 throw "argument for -max_default_common_align is not a hexadecimal number";
3918 if ( value
> 0x8000 )
3919 throw "argument for -max_default_common_align must be less than or equal to 0x8000";
3921 warning("zero is not a valid -max_default_common_align");
3924 // alignment is power of 2
3925 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
3926 if ( (unsigned long)(1 << alignment
) != value
) {
3927 warning("alignment for -max_default_common_align is not a power of two, using 0x%X", 1 << alignment
);
3929 fMaxDefaultCommonAlign
= alignment
;
3931 else if ( strcmp(argv
[i
], "-no_weak_imports") == 0 ) {
3932 fAllowWeakImports
= false;
3934 else if ( strcmp(argv
[i
], "-no_inits") == 0 ) {
3935 fInitializersTreatment
= Options::kError
;
3937 else if ( strcmp(argv
[i
], "-no_warn_inits") == 0 ) {
3938 fInitializersTreatment
= Options::kSuppress
;
3940 // put this last so that it does not interfer with other options starting with 'i'
3941 else if ( strncmp(arg
, "-i", 2) == 0 ) {
3942 const char* colon
= strchr(arg
, ':');
3943 if ( colon
== NULL
)
3944 throwf("unknown option: %s", arg
);
3945 Options::AliasPair pair
;
3946 char* temp
= new char[colon
-arg
];
3947 strlcpy(temp
, &arg
[2], colon
-arg
-1);
3948 pair
.realName
= &colon
[1];
3950 fAliases
.push_back(pair
);
3953 throwf("unknown option: %s", arg
);
3956 if (snapshotArgCount
== -1)
3957 snapshotArgCount
= i
-snapshotArgIndex
+1;
3958 if (snapshotArgCount
> 0)
3959 fLinkSnapshot
.addSnapshotLinkArg(snapshotArgIndex
, snapshotArgCount
, snapshotFileArgIndex
);
3962 FileInfo info
= findFile(arg
);
3963 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3964 if ( strcmp(&info
.path
[strlen(info
.path
)-2], ".a") == 0 )
3967 fInputFiles
.push_back(info
);
3971 // if a -lazy option was used, implicitly link in lazydylib1.o
3972 if ( fUsingLazyDylibLinking
) {
3973 FileInfo info
= findLibrary("lazydylib1.o");
3974 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)argc
);
3978 if (fSnapshotRequested
)
3979 fLinkSnapshot
.createSnapshot();
3985 // -syslibroot <path> is used for SDK support.
3986 // The rule is that all search paths (both explicit and default) are
3987 // checked to see if they exist in the SDK. If so, that path is
3988 // replaced with the sdk prefixed path. If not, that search path
3989 // is used as is. If multiple -syslibroot options are specified
3990 // their directory structures are logically overlayed and files
3991 // from sdks specified earlier on the command line used before later ones.
3993 void Options::buildSearchPaths(int argc
, const char* argv
[])
3995 bool addStandardLibraryDirectories
= true;
3996 std::vector
<const char*> libraryPaths
;
3997 std::vector
<const char*> frameworkPaths
;
3998 libraryPaths
.reserve(10);
3999 frameworkPaths
.reserve(10);
4000 // scan through argv looking for -L, -F, -Z, and -syslibroot options
4001 for(int i
=0; i
< argc
; ++i
) {
4002 if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'L') ) {
4003 const char* libSearchDir
= &argv
[i
][2];
4004 // Allow either "-L{path}" or "-L {path}".
4005 if (argv
[i
][2] == '\0') {
4006 // -L {path}. Make sure there is an argument following this.
4007 const char* path
= argv
[++i
];
4009 throw "-L missing argument";
4010 libSearchDir
= path
;
4012 if ( libSearchDir
[0] == '\0' )
4013 throw "-L must be immediately followed by a directory path (no space)";
4014 libraryPaths
.push_back(libSearchDir
);
4016 else if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'F') ) {
4017 const char* frameworkSearchDir
= &argv
[i
][2];
4018 // Allow either "-F{path}" or "-F {path}".
4019 if (argv
[i
][2] == '\0') {
4020 // -F {path}. Make sure there is an argument following this.
4021 const char* path
= argv
[++i
];
4023 throw "-F missing argument";
4024 frameworkSearchDir
= path
;
4026 if ( frameworkSearchDir
[0] == '\0' )
4027 throw "-F must be immediately followed by a directory path (no space)";
4028 frameworkPaths
.push_back(frameworkSearchDir
);
4030 else if ( strcmp(argv
[i
], "-Z") == 0 )
4031 addStandardLibraryDirectories
= false;
4032 else if ( strcmp(argv
[i
], "-v") == 0 ) {
4034 extern const char ldVersionString
[];
4035 fprintf(stderr
, "%s", ldVersionString
);
4036 fprintf(stderr
, "configured to support archs: %s\n", ALL_SUPPORTED_ARCHS
);
4037 // if only -v specified, exit cleanly
4039 const char* ltoVers
= lto::version();
4040 if ( ltoVers
!= NULL
)
4041 fprintf(stderr
, "LTO support using: %s (static support for %d, runtime is %d)\n",
4042 ltoVers
, lto::static_api_version(), lto::runtime_api_version());
4043 fprintf(stderr
, "TAPI support using: %s\n", tapi::Version::getFullVersionAsString().c_str());
4047 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
4048 const char* path
= argv
[++i
];
4050 throw "-syslibroot missing argument";
4051 fSDKPaths
.push_back(path
);
4053 else if ( strcmp(argv
[i
], "-search_paths_first") == 0 ) {
4054 fLibrarySearchMode
= kSearchDylibAndArchiveInEachDir
;
4056 else if ( strcmp(argv
[i
], "-search_dylibs_first") == 0 ) {
4057 fLibrarySearchMode
= kSearchAllDirsForDylibsThenAllDirsForArchives
;
4059 else if ( strcmp(argv
[i
], "-w") == 0 ) {
4060 sEmitWarnings
= false;
4062 else if ( strcmp(argv
[i
], "-fatal_warnings") == 0 ) {
4063 sFatalWarnings
= true;
4065 else if ( strcmp(argv
[i
], "-dependency_info") == 0 ) {
4066 const char* path
= argv
[++i
];
4068 throw "-dependency_info missing <path>";
4069 fDependencyInfoPath
= path
;
4071 else if ( strcmp(argv
[i
], "-bitcode_bundle") == 0 ) {
4072 fBundleBitcode
= true;
4075 int standardLibraryPathsStartIndex
= libraryPaths
.size();
4076 int standardFrameworkPathsStartIndex
= frameworkPaths
.size();
4077 if ( addStandardLibraryDirectories
) {
4078 libraryPaths
.push_back("/usr/lib");
4079 libraryPaths
.push_back("/usr/local/lib");
4081 frameworkPaths
.push_back("/Library/Frameworks/");
4082 frameworkPaths
.push_back("/System/Library/Frameworks/");
4083 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
4086 // <rdar://problem/5829579> Support for configure based hacks
4087 // if last -syslibroot is /, then ignore all syslibroots
4088 if ( fSDKPaths
.size() > 0 ) {
4089 if ( strcmp(fSDKPaths
.back(), "/") == 0 ) {
4094 // now merge sdk and library paths to make real search paths
4095 fLibrarySearchPaths
.reserve(libraryPaths
.size()*(fSDKPaths
.size()+1));
4097 for (std::vector
<const char*>::iterator it
= libraryPaths
.begin(); it
!= libraryPaths
.end(); ++it
, ++libIndex
) {
4098 const char* libDir
= *it
;
4099 bool sdkOverride
= false;
4100 if ( libDir
[0] == '/' ) {
4101 char betterLibDir
[PATH_MAX
];
4102 if ( strstr(libDir
, "/..") != NULL
) {
4103 if ( realpath(libDir
, betterLibDir
) != NULL
)
4104 libDir
= strdup(betterLibDir
);
4106 const int libDirLen
= strlen(libDir
);
4107 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
4108 const char* sdkDir
= *sdkit
;
4109 const int sdkDirLen
= strlen(sdkDir
);
4110 char newPath
[libDirLen
+ sdkDirLen
+4];
4111 strcpy(newPath
, sdkDir
);
4112 if ( newPath
[sdkDirLen
-1] == '/' )
4113 newPath
[sdkDirLen
-1] = '\0';
4114 strcat(newPath
, libDir
);
4115 struct stat statBuffer
;
4116 if ( stat(newPath
, &statBuffer
) == 0 ) {
4117 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 ) {
4118 warning("-syslibroot and -L combined path '%s' is not a directory", newPath
);
4121 fLibrarySearchPaths
.push_back(strdup(newPath
));
4127 if ( !sdkOverride
) {
4128 if ( (libIndex
>= standardLibraryPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
4129 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
4130 // if one SDK is specified and a standard library path is not in the SDK, don't use it
4133 struct stat statBuffer
;
4134 if ( stat(libDir
, &statBuffer
) == 0 ) {
4135 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 )
4136 warning("-L path '%s' is not a directory", libDir
);
4138 fLibrarySearchPaths
.push_back(libDir
);
4140 else if ( !addStandardLibraryDirectories
|| (strcmp(libDir
, "/usr/local/lib") != 0) ) {
4141 warning("directory not found for option '-L%s'", libDir
);
4148 // now merge sdk and framework paths to make real search paths
4149 fFrameworkSearchPaths
.reserve(frameworkPaths
.size()*(fSDKPaths
.size()+1));
4151 for (std::vector
<const char*>::iterator it
= frameworkPaths
.begin(); it
!= frameworkPaths
.end(); ++it
, ++frameIndex
) {
4152 const char* frameworkDir
= *it
;
4153 bool sdkOverride
= false;
4154 if ( frameworkDir
[0] == '/' ) {
4155 char betterFrameworkDir
[PATH_MAX
];
4156 if ( strstr(frameworkDir
, "/..") != NULL
) {
4157 if ( realpath(frameworkDir
, betterFrameworkDir
) != NULL
)
4158 frameworkDir
= strdup(betterFrameworkDir
);
4160 const int frameworkDirLen
= strlen(frameworkDir
);
4161 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
4162 const char* sdkDir
= *sdkit
;
4163 const int sdkDirLen
= strlen(sdkDir
);
4164 char newPath
[frameworkDirLen
+ sdkDirLen
+4];
4165 strcpy(newPath
, sdkDir
);
4166 if ( newPath
[sdkDirLen
-1] == '/' )
4167 newPath
[sdkDirLen
-1] = '\0';
4168 strcat(newPath
, frameworkDir
);
4169 struct stat statBuffer
;
4170 if ( stat(newPath
, &statBuffer
) == 0 ) {
4171 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 ) {
4172 warning("-syslibroot and -F combined path '%s' is not a directory", newPath
);
4175 fFrameworkSearchPaths
.push_back(strdup(newPath
));
4181 if ( !sdkOverride
) {
4182 if ( (frameIndex
>= standardFrameworkPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
4183 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
4184 // if one SDK is specified and a standard library path is not in the SDK, don't use it
4187 struct stat statBuffer
;
4188 if ( stat(frameworkDir
, &statBuffer
) == 0 ) {
4189 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 )
4190 warning("-F path '%s' is not a directory", frameworkDir
);
4192 fFrameworkSearchPaths
.push_back(frameworkDir
);
4194 else if ( !addStandardLibraryDirectories
|| (strcmp(frameworkDir
, "/Library/Frameworks/") != 0) ) {
4195 warning("directory not found for option '-F%s'", frameworkDir
);
4202 fprintf(stderr
,"Library search paths:\n");
4203 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
4204 it
!= fLibrarySearchPaths
.end();
4206 fprintf(stderr
,"\t%s\n", *it
);
4207 fprintf(stderr
,"Framework search paths:\n");
4208 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
4209 it
!= fFrameworkSearchPaths
.end();
4211 fprintf(stderr
,"\t%s\n", *it
);
4215 // this is run before the command line is parsed
4216 void Options::parsePreCommandLineEnvironmentSettings()
4218 if ((getenv("LD_TRACE_ARCHIVES") != NULL
)
4219 || (getenv("RC_TRACE_ARCHIVES") != NULL
))
4220 fTraceArchives
= true;
4222 if ((getenv("LD_TRACE_DYLIBS") != NULL
)
4223 || (getenv("RC_TRACE_DYLIBS") != NULL
)) {
4224 fTraceDylibs
= true;
4225 fTraceIndirectDylibs
= true;
4228 if ((getenv("LD_TRACE_DEPENDENTS") != NULL
)) {
4230 fTraceEmitJSON
= true;
4233 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL
) {
4234 fTraceDylibSearching
= true;
4237 if (getenv("LD_PRINT_OPTIONS") != NULL
)
4238 fPrintOptions
= true;
4240 if (fTraceDylibs
|| fTraceArchives
|| fTraceEmitJSON
)
4241 fTraceOutputFile
= getenv("LD_TRACE_FILE");
4243 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL
)
4244 fPrintOrderFileStatistics
= true;
4246 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL
)
4249 if (getenv("LD_NO_ENCRYPT") != NULL
) {
4250 fEncryptable
= false;
4251 fMarkAppExtensionSafe
= true; // temporary
4252 fCheckAppExtensionSafe
= false;
4255 if (getenv("LD_APPLICATION_EXTENSION_SAFE") != NULL
) {
4256 fMarkAppExtensionSafe
= true;
4257 fCheckAppExtensionSafe
= false;
4260 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL
)
4261 fAllowCpuSubtypeMismatches
= true;
4263 if (getenv("LD_DYLIB_CPU_SUBTYPES_MUST_MATCH") != NULL
)
4264 fEnforceDylibSubtypesMatch
= true;
4266 if (getenv("LD_WARN_ON_SWIFT_ABI_VERSION_MISMATCHES") != NULL
)
4267 fWarnOnSwiftABIVersionMismatches
= true;
4269 sWarningsSideFilePath
= getenv("LD_WARN_FILE");
4271 const char* customDyldPath
= getenv("LD_DYLD_PATH");
4272 if ( customDyldPath
!= NULL
)
4273 fDyldInstallPath
= customDyldPath
;
4275 const char* debugArchivePath
= getenv("LD_DEBUG_SNAPSHOT");
4276 if (debugArchivePath
!= NULL
) {
4277 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
4278 if (strlen(debugArchivePath
) > 0)
4279 fLinkSnapshot
.setSnapshotPath(debugArchivePath
);
4280 fSnapshotRequested
= true;
4283 const char* pipeFdString
= getenv("LD_PIPELINE_FIFO");
4284 if (pipeFdString
!= NULL
) {
4285 fPipelineFifo
= pipeFdString
;
4288 // <rdar://problem/30746905> [Reproducible Builds] If env ZERO_AR_DATE is set, zero out timestamp in N_OSO stab
4289 if ( getenv("ZERO_AR_DATE") != NULL
)
4290 fZeroModTimeInDebugMap
= true;
4294 // this is run after the command line is parsed
4295 void Options::parsePostCommandLineEnvironmentSettings()
4297 // when building a dynamic main executable, default any use of @executable_path to output path
4298 if ( fExecutablePath
== NULL
&& (fOutputKind
== kDynamicExecutable
) ) {
4299 fExecutablePath
= fOutputFile
;
4302 // allow build system to set default seg_addr_table
4303 if ( fSegAddrTablePath
== NULL
)
4304 fSegAddrTablePath
= getenv("LD_SEG_ADDR_TABLE");
4306 // allow build system to turn on prebinding
4308 fPrebind
= ( getenv("LD_PREBIND") != NULL
);
4311 // allow build system to force on dead-code-stripping
4312 if ( !fDeadStrip
) {
4313 if ( getenv("LD_DEAD_STRIP") != NULL
) {
4314 switch (fOutputKind
) {
4315 case Options::kDynamicLibrary
:
4316 case Options::kDynamicExecutable
:
4317 case Options::kDynamicBundle
:
4320 case Options::kPreload
:
4321 case Options::kObjectFile
:
4322 case Options::kDyld
:
4323 case Options::kStaticExecutable
:
4324 case Options::kKextBundle
:
4330 // allow build system to force on -warn_commons
4331 if ( getenv("LD_WARN_COMMONS") != NULL
)
4332 fWarnCommons
= true;
4334 // allow B&I to set default -source_version
4335 if ( fSourceVersion
== 0 ) {
4336 const char* vers
= getenv("RC_ProjectSourceVersion");
4338 fSourceVersion
= parseVersionNumber64(vers
);
4344 static bool sharedCacheEligiblePath(const char* path
)
4346 return ( (strncmp(path
, "/usr/lib/", 9) == 0) || (strncmp(path
, "/System/Library/", 16) == 0) );
4349 void Options::reconfigureDefaults()
4351 // sync reader options
4352 switch ( fOutputKind
) {
4353 case Options::kObjectFile
:
4354 fForFinalLinkedImage
= false;
4356 case Options::kDyld
:
4358 fForFinalLinkedImage
= true;
4361 case Options::kDynamicLibrary
:
4362 case Options::kDynamicBundle
:
4363 case Options::kKextBundle
:
4364 fForFinalLinkedImage
= true;
4367 case Options::kDynamicExecutable
:
4368 case Options::kStaticExecutable
:
4369 case Options::kPreload
:
4370 fLinkingMainExecutable
= true;
4371 fForFinalLinkedImage
= true;
4376 // set default min OS version
4377 if ( (fMacVersionMin
== ld::macVersionUnset
) && (fIOSVersionMin
== ld::iOSVersionUnset
) && (fWatchOSVersionMin
== ld::wOSVersionUnset
) ) {
4378 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
4379 const char* macVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
4380 const char* iPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
4381 const char* iOSVers
= getenv("IOS_DEPLOYMENT_TARGET");
4382 const char* wOSVers
= getenv("WATCHOS_DEPLOYMENT_TARGET");
4383 if ( macVers
!= NULL
)
4384 setMacOSXVersionMin(macVers
);
4385 else if ( iPhoneVers
!= NULL
)
4386 setIOSVersionMin(iPhoneVers
);
4387 else if ( iOSVers
!= NULL
)
4388 setIOSVersionMin(iOSVers
);
4389 else if ( wOSVers
!= NULL
)
4390 setWatchOSVersionMin(wOSVers
);
4392 // if still nothing, set default based on architecture
4393 switch ( fArchitecture
) {
4395 case CPU_TYPE_X86_64
:
4396 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
4397 #ifdef DEFAULT_MACOSX_MIN_VERSION
4398 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION
);
4399 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
4401 warning("-macosx_version_min not specified, assuming 10.6");
4402 setMacOSXVersionMin("10.6");
4407 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
4408 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
4409 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION
);
4410 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION
);
4412 if ( fSubArchitecture
== CPU_SUBTYPE_ARM_V7K
) {
4413 warning("-watchos_version_min not specified, assuming 2.0");
4414 setWatchOSVersionMin("2.0");
4417 warning("-ios_version_min not specified, assuming 6.0");
4418 setIOSVersionMin("6.0");
4424 // architecture will be infered later by examining .o files
4431 // adjust min based on architecture
4432 switch ( fArchitecture
) {
4434 if ( (fPlatform
== kPlatformOSX
) && (fMacVersionMin
< ld::mac10_4
) ) {
4435 //warning("-macosx_version_min should be 10.4 or later for i386");
4436 fMacVersionMin
= ld::mac10_4
;
4439 case CPU_TYPE_X86_64
:
4440 if ( (fPlatform
== kPlatformOSX
) && (fMacVersionMin
< ld::mac10_4
) ) {
4441 //warning("-macosx_version_min should be 10.4 or later for x86_64");
4442 fMacVersionMin
= ld::mac10_4
;
4445 case CPU_TYPE_ARM64
:
4446 if ( (fPlatform
== kPlatformiOS
) && (fIOSVersionMin
< ld::iOS_7_0
) ) {
4447 //warning("-mios_version_min should be 7.0 or later for arm64");
4448 fIOSVersionMin
= ld::iOS_7_0
;
4453 // default to adding functions start for dynamic code, static code must opt-in
4454 switch ( fOutputKind
) {
4455 case Options::kPreload
:
4456 case Options::kStaticExecutable
:
4457 case Options::kKextBundle
:
4458 if ( fDataInCodeInfoLoadCommandForcedOn
)
4459 fDataInCodeInfoLoadCommand
= true;
4460 if ( fFunctionStartsForcedOn
)
4461 fFunctionStartsLoadCommand
= true;
4463 case Options::kObjectFile
:
4464 if ( !fDataInCodeInfoLoadCommandForcedOff
)
4465 fDataInCodeInfoLoadCommand
= true;
4466 if ( fFunctionStartsForcedOn
)
4467 fFunctionStartsLoadCommand
= true;
4469 case Options::kDynamicExecutable
:
4470 case Options::kDyld
:
4471 case Options::kDynamicLibrary
:
4472 case Options::kDynamicBundle
:
4473 if ( !fDataInCodeInfoLoadCommandForcedOff
)
4474 fDataInCodeInfoLoadCommand
= true;
4475 if ( !fFunctionStartsForcedOff
)
4476 fFunctionStartsLoadCommand
= true;
4480 // adjust kext type based on architecture
4481 if ( fOutputKind
== kKextBundle
) {
4482 switch ( fArchitecture
) {
4483 case CPU_TYPE_X86_64
:
4484 // x86_64 uses new MH_KEXT_BUNDLE type
4485 fMakeCompressedDyldInfo
= false;
4486 fMakeCompressedDyldInfoForceOff
= true;
4487 fAllowTextRelocs
= true;
4488 fUndefinedTreatment
= kUndefinedDynamicLookup
;
4490 case CPU_TYPE_ARM64
:
4491 // arm64 uses new MH_KEXT_BUNDLE type
4492 fMakeCompressedDyldInfo
= false;
4493 fMakeCompressedDyldInfoForceOff
= true;
4494 fAllowTextRelocs
= false;
4495 fKextsUseStubs
= true;
4496 fUndefinedTreatment
= kUndefinedDynamicLookup
;
4499 if ( min_iOS(ld::iOS_5_0
) ) {
4500 // iOS 5.0 and later use new MH_KEXT_BUNDLE type
4501 fMakeCompressedDyldInfo
= false;
4502 fMakeCompressedDyldInfoForceOff
= true;
4503 // kexts are PIC in iOS 6.0 and later
4504 fAllowTextRelocs
= !min_iOS(ld::iOS_6_0
);
4505 fKextsUseStubs
= !fAllowTextRelocs
;
4506 fUndefinedTreatment
= kUndefinedDynamicLookup
;
4509 // else use object file
4512 fOutputKind
= kObjectFile
;
4517 // disable implicit dylibs when targeting 10.3
4518 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
4519 if ( !minOS(ld::mac10_4
, ld::iOS_2_0
) )
4520 fImplicitlyLinkPublicDylibs
= false;
4523 // allow build system to force linker to ignore -prebind
4524 if ( getenv("LD_FORCE_NO_PREBIND") != NULL
)
4527 // allow build system to force linker to ignore -seg_addr_table
4528 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL
)
4529 fSegAddrTablePath
= NULL
;
4531 // check for base address specified externally
4532 if ( (fSegAddrTablePath
!= NULL
) && (fOutputKind
== Options::kDynamicLibrary
) ) {
4533 parseSegAddrTable(fSegAddrTablePath
, this->installPath());
4534 // HACK to support seg_addr_table entries that are physical paths instead of install paths
4535 if ( fBaseAddress
== 0 ) {
4536 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
4537 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.4.dylib");
4538 if ( fBaseAddress
== 0 )
4539 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.9.dylib");
4542 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
4543 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libz.1.2.3.dylib");
4545 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
4546 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libutil1.0.dylib");
4550 // split segs only allowed for dylibs
4552 // split seg only supported for i386, and arm.
4553 switch ( fArchitecture
) {
4555 if ( fOutputKind
!= Options::kDynamicLibrary
)
4557 // make sure read and write segments are proper distance apart
4558 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x10000000) )
4559 fBaseWritableAddress
= fBaseAddress
+ 0x10000000;
4562 if ( fOutputKind
!= Options::kDynamicLibrary
) {
4566 // make sure read and write segments are proper distance apart
4567 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x08000000) )
4568 fBaseWritableAddress
= fBaseAddress
+ 0x08000000;
4574 fBaseWritableAddress
= 0;
4578 // set too-large size
4579 switch ( fArchitecture
) {
4581 fMaxAddress
= 0xFFFFFFFF;
4583 case CPU_TYPE_X86_64
:
4586 switch ( fOutputKind
) {
4587 case Options::kDynamicExecutable
:
4588 case Options::kDynamicLibrary
:
4589 case Options::kDynamicBundle
:
4590 // user land code is limited to low 1GB
4591 fMaxAddress
= 0x2FFFFFFF;
4593 case Options::kStaticExecutable
:
4594 case Options::kObjectFile
:
4595 case Options::kDyld
:
4596 case Options::kPreload
:
4597 case Options::kKextBundle
:
4598 fMaxAddress
= 0xFFFFFFFF;
4601 // range check -seg1addr for ARM
4602 if ( fBaseAddress
> fMaxAddress
) {
4603 warning("ignoring -seg1addr 0x%08llX. Address out of range.", fBaseAddress
);
4609 // <rdar://problem/6138961> -r implies no prebinding for all architectures
4610 if ( fOutputKind
== Options::kObjectFile
)
4613 // disable prebinding depending on arch and min OS version
4615 switch ( fArchitecture
) {
4617 if ( fMacVersionMin
== ld::mac10_4
) {
4618 // in 10.4 only split seg dylibs are prebound
4619 if ( (fOutputKind
!= Options::kDynamicLibrary
) || ! fSplitSegs
)
4622 else if ( fMacVersionMin
>= ld::mac10_5
) {
4623 // in 10.5 nothing is prebound
4626 else if ( fIOSVersionMin
!= ld::iOSVersionUnset
) {
4627 // nothing in simulator is prebound
4631 // in 10.3 and earlier only dylibs and main executables could be prebound
4632 switch ( fOutputKind
) {
4633 case Options::kDynamicExecutable
:
4634 case Options::kDynamicLibrary
:
4635 // only main executables and dylibs can be prebound
4637 case Options::kStaticExecutable
:
4638 case Options::kDynamicBundle
:
4639 case Options::kObjectFile
:
4640 case Options::kDyld
:
4641 case Options::kPreload
:
4642 case Options::kKextBundle
:
4643 // disable prebinding for everything else
4649 case CPU_TYPE_X86_64
:
4653 switch ( fOutputKind
) {
4654 case Options::kDynamicExecutable
:
4655 case Options::kDynamicLibrary
:
4656 // only main executables and dylibs can be prebound
4658 case Options::kStaticExecutable
:
4659 case Options::kDynamicBundle
:
4660 case Options::kObjectFile
:
4661 case Options::kDyld
:
4662 case Options::kPreload
:
4663 case Options::kKextBundle
:
4664 // disable prebinding for everything else
4672 // only prebound images can be split-seg
4673 if ( fSplitSegs
&& !fPrebind
)
4676 // determine if info for shared region should be added
4677 if ( fOutputKind
== Options::kDynamicLibrary
) {
4678 if ( minOS(ld::mac10_5
, ld::iOS_3_1
) )
4679 if ( !fPrebind
&& !fSharedRegionEligibleForceOff
)
4680 if ( sharedCacheEligiblePath(this->installPath()) )
4681 fSharedRegionEligible
= true;
4683 else if ( fOutputKind
== Options::kDyld
) {
4684 // <rdar://problem/10111122> Enable dyld to be put into the dyld shared cache
4685 fSharedRegionEligible
= true;
4688 // automatically use __DATA_CONST in iOS dylibs
4689 if ( fSharedRegionEligible
&& minOS(ld::mac10_Future
, ld::iOS_9_0
) && !fUseDataConstSegmentForceOff
&& !fTargetIOSSimulator
) {
4690 fUseDataConstSegment
= true;
4692 if ( fUseDataConstSegmentForceOn
) {
4693 fUseDataConstSegment
= true;
4695 // A -kext for iOS 10 ==> -data_const, -text_exec, -add_split_seg_info
4696 if ( (fOutputKind
== Options::kKextBundle
) && minOS(ld::mac10_Future
, ld::iOS_10_0
) && (fArchitecture
== CPU_TYPE_ARM64
) ) {
4697 fUseDataConstSegment
= true;
4698 fUseTextExecSegment
= true;
4699 fSharedRegionEligible
= true;
4701 if ( fUseDataConstSegment
) {
4702 addSectionRename("__DATA", "__got", "__DATA_CONST", "__got");
4703 addSectionRename("__DATA", "__la_symbol_ptr", "__DATA_CONST", "__la_symbol_ptr");
4704 addSectionRename("__DATA", "__nl_symbol_ptr", "__DATA_CONST", "__nl_symbol_ptr");
4705 addSectionRename("__DATA", "__const", "__DATA_CONST", "__const");
4706 addSectionRename("__DATA", "__cfstring", "__DATA_CONST", "__cfstring");
4707 addSectionRename("__DATA", "__mod_init_func", "__DATA_CONST", "__mod_init_func");
4708 addSectionRename("__DATA", "__mod_term_func", "__DATA_CONST", "__mod_term_func");
4709 addSectionRename("__DATA", "__objc_classlist", "__DATA_CONST", "__objc_classlist");
4710 addSectionRename("__DATA", "__objc_nlclslist", "__DATA_CONST", "__objc_nlclslist");
4711 addSectionRename("__DATA", "__objc_catlist", "__DATA_CONST", "__objc_catlist");
4712 addSectionRename("__DATA", "__objc_nlcatlist", "__DATA_CONST", "__objc_nlcatlist");
4713 addSectionRename("__DATA", "__objc_protolist", "__DATA_CONST", "__objc_protolist");
4714 addSectionRename("__DATA", "__objc_imageinfo", "__DATA_CONST", "__objc_imageinfo");
4715 addSectionRename("__DATA", "__objc_const", "__DATA_CONST", "__objc_const");
4717 if ( fUseTextExecSegment
) {
4718 addSectionRename("__TEXT", "__text", "__TEXT_EXEC", "__text");
4719 addSectionRename("__TEXT", "__stubs", "__TEXT_EXEC", "__stubs");
4722 // Use V2 shared cache info when targetting newer OSs
4723 if ( fSharedRegionEligible
&& minOS(ld::mac10_12
, ld::iOS_9_0
)) {
4724 fSharedRegionEncodingV2
= true;
4725 if ( fPlatform
== kPlatformOSX
) {
4726 fSharedRegionEncodingV2
= false;
4727 // <rdar://problem/24772435> only use v2 for Swift dylibs on Mac OS X
4728 if ( strncmp(this->installPath(), "/System/Library/PrivateFrameworks/Swift/", 40) == 0 )
4729 fSharedRegionEncodingV2
= true;
4730 // <rdar://problem/32525720> use v2 for ABI stable Swift dylibs on macOS
4731 if ( strncmp(this->installPath(), "/System/Library/Frameworks/Swift/", 33) == 0 )
4732 fSharedRegionEncodingV2
= true;
4733 // <rdar://problem/31428120> an other OS frameworks that use swift need v2
4734 for (const char* searchPath
: fLibrarySearchPaths
) {
4735 if ( strstr(searchPath
, "xctoolchain/usr/lib/swift/macos") != NULL
) {
4736 fSharedRegionEncodingV2
= true;
4741 fIgnoreOptimizationHints
= true;
4744 // figure out if module table is needed for compatibility with old ld/dyld
4745 if ( fOutputKind
== Options::kDynamicLibrary
) {
4746 switch ( fArchitecture
) {
4748 if ( fIOSVersionMin
!= ld::iOSVersionUnset
) // simulator never needs modules
4752 fNeedsModuleTable
= true; // redo_prebinding requires a module table
4757 // <rdar://problem/5366363> -r -x implies -S
4758 if ( (fOutputKind
== Options::kObjectFile
) && (fLocalSymbolHandling
== kLocalSymbolsNone
) )
4759 fDebugInfoStripping
= Options::kDebugInfoNone
;
4761 // <rdar://problem/15252891> -r implies -no_uuid
4762 if ( fOutputKind
== Options::kObjectFile
)
4763 fUUIDMode
= kUUIDNone
;
4765 // choose how to process unwind info
4766 switch ( fArchitecture
) {
4768 case CPU_TYPE_X86_64
:
4769 case CPU_TYPE_ARM64
:
4770 switch ( fOutputKind
) {
4771 case Options::kObjectFile
:
4772 case Options::kStaticExecutable
:
4773 case Options::kPreload
:
4774 case Options::kKextBundle
:
4775 fAddCompactUnwindEncoding
= false;
4777 case Options::kDyld
:
4778 case Options::kDynamicLibrary
:
4779 case Options::kDynamicBundle
:
4780 case Options::kDynamicExecutable
:
4781 //if ( fAddCompactUnwindEncoding && (fVersionMin >= ld::mac10_6) )
4782 // fRemoveDwarfUnwindIfCompactExists = true;
4787 if ( armUsesZeroCostExceptions() ) {
4788 switch ( fOutputKind
) {
4789 case Options::kObjectFile
:
4790 case Options::kStaticExecutable
:
4791 case Options::kPreload
:
4792 case Options::kKextBundle
:
4793 fAddCompactUnwindEncoding
= false;
4795 case Options::kDyld
:
4796 case Options::kDynamicLibrary
:
4797 case Options::kDynamicBundle
:
4798 case Options::kDynamicExecutable
:
4799 fAddCompactUnwindEncoding
= true;
4804 fAddCompactUnwindEncoding
= false;
4805 fRemoveDwarfUnwindIfCompactExists
= false;
4809 // if -arch is missing, assume we don't want compact unwind info
4810 fAddCompactUnwindEncoding
= false;
4814 // only iOS executables should be encryptable
4815 switch ( fOutputKind
) {
4816 case Options::kObjectFile
:
4817 case Options::kDyld
:
4818 case Options::kStaticExecutable
:
4819 case Options::kPreload
:
4820 case Options::kKextBundle
:
4821 fEncryptable
= false;
4823 case Options::kDynamicExecutable
:
4825 case Options::kDynamicLibrary
:
4826 case Options::kDynamicBundle
:
4827 // <rdar://problem/16293398> Add LC_ENCRYPTION_INFO load command to bundled frameworks
4828 if ( !min_iOS(ld::iOS_7_0
) )
4829 fEncryptable
= false;
4832 if ( (fArchitecture
!= CPU_TYPE_ARM
) && (fArchitecture
!= CPU_TYPE_ARM64
)
4834 fEncryptable
= false;
4835 if ( fEncryptableForceOn
)
4836 fEncryptable
= true;
4837 else if ( fEncryptableForceOff
)
4838 fEncryptable
= false;
4840 // don't move inits in dyld because dyld wants certain
4841 // entries point at stable locations at the start of __text
4842 if ( fOutputKind
== Options::kDyld
)
4843 fAutoOrderInitializers
= false;
4846 // disable __data ordering for some output kinds
4847 switch ( fOutputKind
) {
4848 case Options::kObjectFile
:
4849 case Options::kDyld
:
4850 case Options::kStaticExecutable
:
4851 case Options::kPreload
:
4852 case Options::kKextBundle
:
4855 case Options::kDynamicExecutable
:
4856 case Options::kDynamicLibrary
:
4857 case Options::kDynamicBundle
:
4861 // only use compressed LINKEDIT for final linked images
4862 switch ( fOutputKind
) {
4863 case Options::kDynamicExecutable
:
4864 case Options::kDynamicLibrary
:
4865 case Options::kDynamicBundle
:
4867 case Options::kPreload
:
4868 case Options::kStaticExecutable
:
4869 case Options::kObjectFile
:
4870 case Options::kDyld
:
4871 case Options::kKextBundle
:
4872 fMakeCompressedDyldInfoForceOff
= true;
4875 if ( fMakeCompressedDyldInfoForceOff
)
4876 fMakeCompressedDyldInfo
= false;
4879 // only use compressed LINKEDIT for:
4880 // Mac OS X 10.6 or later
4882 if ( fMakeCompressedDyldInfo
) {
4883 if ( !minOS(ld::mac10_6
, ld::iOS_3_1
) )
4884 fMakeCompressedDyldInfo
= false;
4887 // only ARM and x86_64 enforces that cpu-sub-types must match
4888 switch ( fArchitecture
) {
4891 case CPU_TYPE_X86_64
:
4892 fEnforceDylibSubtypesMatch
= false;
4895 case CPU_TYPE_ARM64
:
4896 fEnforceDylibSubtypesMatch
= false;
4901 // only final linked images can not optimize zero fill sections
4902 if ( fOutputKind
== Options::kObjectFile
)
4903 fOptimizeZeroFill
= true;
4905 // all undefines in -r mode
4906 // if ( fOutputKind == Options::kObjectFile )
4907 // fUndefinedTreatment = kUndefinedSuppress;
4909 // only dynamic final linked images should warn about use of commmons
4910 if ( fWarnCommons
) {
4911 switch ( fOutputKind
) {
4912 case Options::kDynamicExecutable
:
4913 case Options::kDynamicLibrary
:
4914 case Options::kDynamicBundle
:
4916 case Options::kPreload
:
4917 case Options::kStaticExecutable
:
4918 case Options::kObjectFile
:
4919 case Options::kDyld
:
4920 case Options::kKextBundle
:
4921 fWarnCommons
= false;
4926 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
4927 if ( minOS(ld::mac10_5
, ld::iOS_2_0
) )
4928 fUseSimplifiedDylibReExports
= true;
4930 // Mac OS X 10.7 and iOS 4.2 support LC_LOAD_UPWARD_DYLIB
4931 if ( minOS(ld::mac10_7
, ld::iOS_4_2
) && (fOutputKind
== kDynamicLibrary
) )
4932 fCanUseUpwardDylib
= true;
4934 // MacOSX 10.7 defaults to PIE
4935 if ( (fArchitecture
== CPU_TYPE_I386
)
4936 && (fOutputKind
== kDynamicExecutable
)
4937 && (fMacVersionMin
>= ld::mac10_7
) ) {
4938 fPositionIndependentExecutable
= true;
4941 // armv7 for iOS4.3 defaults to PIE
4942 if ( (fArchitecture
== CPU_TYPE_ARM
)
4943 && fArchSupportsThumb2
4944 && (fOutputKind
== kDynamicExecutable
)
4945 && min_iOS(ld::iOS_4_3
) ) {
4946 fPositionIndependentExecutable
= true;
4949 // <rdar://problem/24535196> x86_64 defaults PIE (regardless of minOS version)
4950 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
== kDynamicExecutable
) && (fMacVersionMin
>= ld::mac10_6
) )
4951 fPositionIndependentExecutable
= true;
4953 // Simulator defaults to PIE
4954 if ( fTargetIOSSimulator
&& (fOutputKind
== kDynamicExecutable
) )
4955 fPositionIndependentExecutable
= true;
4957 // -no_pie anywhere on command line disable PIE
4958 if ( fDisablePositionIndependentExecutable
)
4959 fPositionIndependentExecutable
= false;
4961 // arm64 is always PIE
4962 if ( ((fArchitecture
== CPU_TYPE_ARM64
)
4964 && (fOutputKind
== kDynamicExecutable
) ) {
4965 fPositionIndependentExecutable
= true;
4966 if ( fDisablePositionIndependentExecutable
)
4967 warning("-no_pie ignored for arm64");
4970 // set fOutputSlidable
4971 switch ( fOutputKind
) {
4972 case Options::kObjectFile
:
4973 fOutputSlidable
= false;
4975 case Options::kStaticExecutable
:
4976 case Options::kDynamicExecutable
:
4977 fOutputSlidable
= fPositionIndependentExecutable
;
4979 case Options::kPreload
:
4980 fOutputSlidable
= fPIEOnCommandLine
;
4982 case Options::kDyld
:
4983 case Options::kDynamicLibrary
:
4984 case Options::kDynamicBundle
:
4985 case Options::kKextBundle
:
4986 fOutputSlidable
= true;
4990 // let linker know if thread local variables are supported
4991 if ( fMacVersionMin
>= ld::mac10_7
) {
4994 else if ( ((fArchitecture
== CPU_TYPE_ARM64
)
4996 && min_iOS(ld::iOS_8_0
) ) {
4999 else if ( (fArchitecture
== CPU_TYPE_ARM
) && min_iOS(ld::iOS_9_0
) ) {
5002 else if ( fTargetIOSSimulator
&& (fArchitecture
== CPU_TYPE_X86_64
) && min_iOS(ld::iOS_8_0
) ) {
5005 else if ( fTargetIOSSimulator
&& (fArchitecture
== CPU_TYPE_I386
) && min_iOS(ld::iOS_9_0
) ) {
5009 // default to adding version load command for dynamic code, static code must opt-in
5010 switch ( fOutputKind
) {
5011 case Options::kObjectFile
:
5012 fVersionLoadCommand
= false;
5014 case Options::kStaticExecutable
:
5015 case Options::kPreload
:
5016 case Options::kKextBundle
:
5017 if ( fVersionLoadCommandForcedOn
)
5018 fVersionLoadCommand
= true;
5020 case Options::kDynamicExecutable
:
5021 case Options::kDyld
:
5022 case Options::kDynamicLibrary
:
5023 case Options::kDynamicBundle
:
5024 if ( !fVersionLoadCommandForcedOff
)
5025 fVersionLoadCommand
= true;
5029 // support re-export of individual symbols in MacOSX 10.7 and iOS 4.2
5030 if ( (fOutputKind
== kDynamicLibrary
) && minOS(ld::mac10_7
, ld::iOS_4_2
) )
5031 fCanReExportSymbols
= true;
5033 // ObjC optimization is only in dynamic final linked images
5034 switch ( fOutputKind
) {
5035 case Options::kObjectFile
:
5036 case Options::kStaticExecutable
:
5037 case Options::kPreload
:
5038 case Options::kKextBundle
:
5039 case Options::kDyld
:
5040 fObjcCategoryMerging
= false;
5042 case Options::kDynamicExecutable
:
5043 case Options::kDynamicLibrary
:
5044 case Options::kDynamicBundle
:
5048 // i386 main executables linked on Mac OS X 10.7 default to NX heap
5049 // regardless of target unless overriden with -allow_heap_execute anywhere
5050 // on the command line
5051 if ( (fArchitecture
== CPU_TYPE_I386
) && (fOutputKind
== kDynamicExecutable
) && !fDisableNonExecutableHeap
)
5052 fNonExecutableHeap
= true;
5054 // Use LC_MAIN instead of LC_UNIXTHREAD for newer OSs
5055 switch ( fOutputKind
) {
5056 case Options::kDynamicExecutable
:
5057 if ( fEntryPointLoadCommandForceOn
) {
5058 fEntryPointLoadCommand
= true;
5059 if ( fEntryName
== NULL
)
5060 fEntryName
= "_main";
5062 else if ( fEntryPointLoadCommandForceOff
) {
5063 fNeedsThreadLoadCommand
= true;
5064 if ( fEntryName
== NULL
)
5065 fEntryName
= "start";
5068 // <rdar://problem/16310363> Linker should look for "_main" not "start" when building for sim regardless of min OS
5069 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) || fTargetIOSSimulator
) {
5070 fEntryPointLoadCommand
= true;
5071 if ( fEntryName
== NULL
)
5072 fEntryName
= "_main";
5073 if ( strcmp(fEntryName
, "start") == 0 ) {
5074 warning("Ignoring '-e start' because entry point 'start' is not used for the targeted OS version");
5075 fEntryName
= "_main";
5079 fNeedsThreadLoadCommand
= true;
5080 if ( fEntryName
== NULL
)
5081 fEntryName
= "start";
5085 case Options::kObjectFile
:
5086 case Options::kKextBundle
:
5087 case Options::kDynamicLibrary
:
5088 case Options::kDynamicBundle
:
5091 case Options::kStaticExecutable
:
5092 case Options::kPreload
:
5093 case Options::kDyld
:
5094 fNeedsThreadLoadCommand
= true;
5095 if ( fEntryName
== NULL
)
5096 fEntryName
= "start"; // Perhaps these should have no default and require -e
5100 // add LC_SOURCE_VERSION
5101 switch ( fOutputKind
) {
5102 case Options::kDynamicExecutable
:
5103 case Options::kKextBundle
:
5104 case Options::kDynamicLibrary
:
5105 case Options::kDynamicBundle
:
5106 case Options::kDyld
:
5107 case Options::kStaticExecutable
:
5108 if ( fSourceVersionLoadCommandForceOn
) {
5109 fSourceVersionLoadCommand
= true;
5111 else if ( fSourceVersionLoadCommandForceOff
) {
5112 fSourceVersionLoadCommand
= false;
5115 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) ) {
5116 fSourceVersionLoadCommand
= true;
5119 fSourceVersionLoadCommand
= false;
5122 case Options::kObjectFile
:
5123 case Options::kPreload
:
5124 fSourceVersionLoadCommand
= false;
5128 // if -sdk_version not on command line, infer from -syslibroot
5129 if ( (fSDKVersion
== 0) && (fSDKPaths
.size() > 0) ) {
5130 const char* sdkPath
= fSDKPaths
.front();
5131 const char* end
= &sdkPath
[strlen(sdkPath
)-1];
5132 while ( !isdigit(*end
) && (end
> sdkPath
) )
5134 const char* start
= end
-1;
5135 while ( (isdigit(*start
) || (*start
== '.')) && (start
> sdkPath
))
5137 char sdkVersionStr
[32];
5138 int len
= end
-start
+1;
5140 strlcpy(sdkVersionStr
, start
+1, len
);
5141 fSDKVersion
= parseVersionNumber32(sdkVersionStr
);
5145 // if -sdk_version and -syslibroot not used, but targeting MacOSX, use current OS version
5146 if ( (fSDKVersion
== 0) && (fMacVersionMin
!= ld::macVersionUnset
) ) {
5147 // special case if RC_ProjectName and MACOSX_DEPLOYMENT_TARGET are both set that sdkversion=minos
5148 if ( getenv("RC_ProjectName") && getenv("MACOSX_DEPLOYMENT_TARGET") ) {
5149 fSDKVersion
= fMacVersionMin
;
5152 int mib
[2] = { CTL_KERN
, KERN_OSRELEASE
};
5153 char kernVersStr
[100];
5154 size_t strlen
= sizeof(kernVersStr
);
5155 if ( sysctl(mib
, 2, kernVersStr
, &strlen
, NULL
, 0) != -1 ) {
5156 uint32_t kernVers
= parseVersionNumber32(kernVersStr
);
5157 int minor
= (kernVers
>> 16) - 4; // kernel major version is 4 ahead of x in 10.x
5158 fSDKVersion
= 0x000A0000 + (minor
<< 8);
5163 // allow trie based absolute symbols if targeting new enough OS
5164 if ( fMakeCompressedDyldInfo
) {
5165 if ( minOS(ld::mac10_9
, ld::iOS_7_0
) ) {
5166 fAbsoluteSymbols
= true;
5170 // <rdar://problem/12959510> iOS main executables now default to 16KB page size
5171 if ( (fIOSVersionMin
!= ld::iOSVersionUnset
) && (fOutputKind
== Options::kDynamicExecutable
) ) {
5172 // <rdar://problem/13070042> Only third party apps should have 16KB page segments by default
5173 if ( fEncryptable
) {
5174 if ( fSegmentAlignment
== 4096 )
5175 fSegmentAlignment
= 4096*4;
5179 // <rdar://problem/12258065> ARM64 needs 16KB page size for user land code
5180 // <rdar://problem/15974532> make armv7[s] use 16KB pages in user land code for iOS 8 or later
5181 if ( fSegmentAlignment
== 4096 ) {
5182 switch ( fOutputKind
) {
5183 case Options::kDynamicExecutable
:
5184 case Options::kDynamicLibrary
:
5185 case Options::kDynamicBundle
:
5186 case Options::kDyld
:
5187 if ( ((fArchitecture
== CPU_TYPE_ARM64
)
5189 || ((fArchitecture
== CPU_TYPE_ARM
) && min_iOS(ld::iOS_7_0
)) ) {
5190 fSegmentAlignment
= 4096*4;
5193 case Options::kStaticExecutable
:
5194 case Options::kKextBundle
:
5195 // <rdar://problem/14676611> 16KB segments for arm64 kexts
5196 if ( ((fArchitecture
== CPU_TYPE_ARM64
)
5198 && min_iOS(ld::iOS_9_0
) ) {
5199 fSegmentAlignment
= 4096*4;
5202 case Options::kObjectFile
:
5203 case Options::kPreload
:
5210 // <rdar://problem/13624134> linker should not convert dwarf unwind if .o file has compact unwind section
5211 switch ( fOutputKind
) {
5212 case Options::kDynamicExecutable
:
5213 case Options::kDynamicLibrary
:
5214 case Options::kDynamicBundle
:
5215 case Options::kDyld
:
5216 if ( fKeepDwarfUnwindForcedOn
) {
5217 fKeepDwarfUnwind
= true;
5219 else if ( fKeepDwarfUnwindForcedOff
) {
5220 fKeepDwarfUnwind
= false;
5223 if ( minOS(ld::mac10_9
, ld::iOS_7_0
) )
5224 fKeepDwarfUnwind
= false;
5226 fKeepDwarfUnwind
= true;
5229 case Options::kKextBundle
:
5230 case Options::kStaticExecutable
:
5231 case Options::kObjectFile
:
5232 case Options::kPreload
:
5233 fKeepDwarfUnwind
= true;
5237 // Make sure -image_base matches alignment
5238 uint64_t alignedBaseAddress
= (fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
);
5239 if ( alignedBaseAddress
!= fBaseAddress
) {
5240 warning("base address 0x%llX is not properly aligned. Changing it to 0x%llX", fBaseAddress
, alignedBaseAddress
);
5241 fBaseAddress
= alignedBaseAddress
;
5244 // If -dirty_data_list not specified, look in $SDKROOT/AppleInternal/DirtyDataFiles/<dylib>.dirty for dirty data list
5245 if ( fSymbolsMovesData
.empty() && fUseDataConstSegment
&& ( fDylibInstallName
!= NULL
) && !fSDKPaths
.empty() ) {
5246 const char* dylibLeaf
= strrchr(fDylibInstallName
, '/');
5248 char path
[PATH_MAX
];
5249 strlcpy(path
, fSDKPaths
.front(), sizeof(path
));
5250 strlcat(path
, "/AppleInternal/DirtyDataFiles", sizeof(path
));
5251 strlcat(path
, dylibLeaf
, sizeof(path
));
5252 strlcat(path
, ".dirty", sizeof(path
));
5254 if ( info
.checkFileExists(*this, path
) )
5255 addSymbolMove("__DATA_DIRTY", path
, fSymbolsMovesData
, "-dirty_data_list");
5260 // <rdar://problem/32138080> Automatically use OrderFiles found in the AppleInternal SDK
5261 if ( (fFinalName
!= NULL
) && fOrderedSymbols
.empty() && !fSDKPaths
.empty() ) {
5262 char path
[PATH_MAX
];
5263 strlcpy(path
, fSDKPaths
.front(), sizeof(path
));
5264 strlcat(path
, "/AppleInternal/OrderFiles/", sizeof(path
));
5265 strlcat(path
, fFinalName
, sizeof(path
));
5266 strlcat(path
, ".order", sizeof(path
));
5268 if ( info
.checkFileExists(*this, path
) )
5269 parseOrderFile(path
, false);
5272 // <rdar://problem/20503811> Reduce the default alignment of structures/arrays to save memory in embedded systems
5273 if ( fMaxDefaultCommonAlign
== 0 ) {
5274 if ( fOutputKind
== Options::kPreload
)
5275 fMaxDefaultCommonAlign
= 8;
5277 fMaxDefaultCommonAlign
= 15;
5280 // Add warnings for issues likely to cause OS verification issues
5281 if ( fSharedRegionEligible
&& !fRPaths
.empty() ) {
5282 // <rdar://problem/18719327> warn if -rpath is used with OS dylibs
5283 warning("OS dylibs should not add rpaths (linker option: -rpath) (Xcode build setting: LD_RUNPATH_SEARCH_PATHS)");
5285 if ( (fOutputKind
== Options::kDynamicLibrary
) && (fDylibInstallName
!= NULL
) && (fFinalName
!= NULL
) && sharedCacheEligiblePath(fFinalName
) ) {
5286 if ( strncmp(fDylibInstallName
, "@rpath", 6) == 0 )
5287 warning("OS dylibs should not use @rpath for -install_name. Use absolute path instead");
5288 if ( strcmp(fDylibInstallName
, fFinalName
) != 0 ) {
5289 bool different
= true;
5290 // some projects end up with double slash in -final_output path
5291 if ( strstr(fFinalName
, "//") != NULL
) {
5292 char fixedPath
[strlen(fFinalName
)+1];
5293 char* t
= fixedPath
;
5294 bool lastWasSlash
= false;
5295 for (const char* s
=fFinalName
; *s
!= '\0'; ++s
) {
5297 if ( !lastWasSlash
)
5299 lastWasSlash
= true;
5303 lastWasSlash
= false;
5307 different
= (strcmp(fDylibInstallName
, fixedPath
) != 0);
5310 warning("OS dylibs -install_name should match its real absolute path");
5314 // set if unaligned pointers are warnings or errors
5315 if ( fMacVersionMin
>= ld::mac10_12
) {
5316 // ignore unaligned pointers when targeting older macOS versions
5317 if ( fSharedRegionEligible
)
5318 fUnalignedPointerTreatment
= Options::kUnalignedPointerWarning
;
5320 fUnalignedPointerTreatment
= Options::kUnalignedPointerIgnore
;
5322 else if ( min_iOS(ld::iOS_10_0
) ) {
5323 fUnalignedPointerTreatment
= Options::kUnalignedPointerWarning
;
5326 fUnalignedPointerTreatment
= Options::kUnalignedPointerIgnore
;
5329 // warn by default for OS dylibs
5330 if ( fInitializersTreatment
== Options::kInvalid
) {
5331 if ( fSharedRegionEligible
&& (fOutputKind
== Options::kDynamicLibrary
) ) {
5332 fInitializersTreatment
= Options::kWarning
;
5334 if ( (fOutputKind
== Options::kDynamicLibrary
) && (fDylibInstallName
!= NULL
) && (strstr(fDylibInstallName
, "EmbeddedAcousticRecognition.framework") != NULL
) && !fNoWeakExports
)
5335 fInitializersTreatment
= Options::kSuppress
;
5338 fInitializersTreatment
= Options::kSuppress
;
5343 void Options::checkIllegalOptionCombinations()
5345 // check -undefined setting
5346 switch ( fUndefinedTreatment
) {
5347 case kUndefinedError
:
5350 case kUndefinedDynamicLookup
:
5351 switch (fPlatform
) {
5355 case kPlatformWatchOS
:
5356 case kPlatform_bridgeOS
:
5357 #if SUPPORT_APPLE_TV
5358 case kPlatform_tvOS
:
5360 if ( fOutputKind
!= kKextBundle
)
5361 warning("-undefined dynamic_lookup is deprecated on %s", platformName(fPlatform
));
5367 case kUndefinedWarning
:
5368 case kUndefinedSuppress
:
5369 // requires flat namespace
5370 if ( fNameSpace
== kTwoLevelNameSpace
)
5371 throw "can't use -undefined warning or suppress with -twolevel_namespace";
5375 // unify -sub_umbrella with dylibs
5376 for (std::vector
<const char*>::iterator it
= fSubUmbellas
.begin(); it
!= fSubUmbellas
.end(); it
++) {
5377 const char* subUmbrella
= *it
;
5379 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
5380 Options::FileInfo
& info
= *fit
;
5381 const char* lastSlash
= strrchr(info
.path
, '/');
5382 if ( lastSlash
== NULL
)
5383 lastSlash
= info
.path
- 1;
5384 std::string
path(&lastSlash
[1]);
5385 auto idx
= path
.find(".tbd", path
.size() - 4);
5386 if (idx
!= std::string::npos
)
5388 if ( path
== subUmbrella
) {
5389 info
.options
.fReExport
= true;
5391 fLinkSnapshot
.recordSubUmbrella(info
.path
);
5396 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella
);
5399 // unify -sub_library with dylibs
5400 for (std::vector
<const char*>::iterator it
= fSubLibraries
.begin(); it
!= fSubLibraries
.end(); it
++) {
5401 const char* subLibrary
= *it
;
5403 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
5404 Options::FileInfo
& info
= *fit
;
5405 const char* lastSlash
= strrchr(info
.path
, '/');
5406 if ( lastSlash
== NULL
)
5407 lastSlash
= info
.path
- 1;
5408 const char* dot
= strchr(&lastSlash
[1], '.');
5410 dot
= &lastSlash
[strlen(lastSlash
)];
5411 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
5412 info
.options
.fReExport
= true;
5414 fLinkSnapshot
.recordSubLibrary(info
.path
);
5419 warning("-sub_library %s does not match a supplied dylib", subLibrary
);
5422 // sync reader options
5423 if ( fNameSpace
!= kTwoLevelNameSpace
) {
5424 fFlatNamespace
= true;
5425 switch (fPlatform
) {
5429 case kPlatformWatchOS
:
5430 case kPlatform_bridgeOS
:
5431 #if SUPPORT_APPLE_TV
5432 case Options::kPlatform_tvOS
:
5434 warning("-flat_namespace is deprecated on %s", platformName(fPlatform
));
5442 // check -stack_addr
5443 if ( fStackAddr
!= 0 ) {
5444 switch (fArchitecture
) {
5447 if ( fStackAddr
> 0xFFFFFFFF )
5448 throw "-stack_addr must be < 4G for 32-bit processes";
5450 case CPU_TYPE_X86_64
:
5451 case CPU_TYPE_ARM64
:
5454 if ( (fStackAddr
& -4096) != fStackAddr
)
5455 throw "-stack_addr must be multiples of 4K";
5456 if ( fStackSize
== 0 )
5457 throw "-stack_addr must be used with -stack_size";
5460 // check -stack_size
5461 if ( fStackSize
!= 0 ) {
5462 switch (fArchitecture
) {
5464 if ( fPlatform
== kPlatformOSX
) {
5465 if ( fStackSize
> 0xFFFFFFFF )
5466 throw "-stack_size must be < 4GB for 32-bit processes";
5467 if ( fStackAddr
== 0 )
5468 fStackAddr
= 0xC0000000;
5469 if ( (fStackAddr
> 0xB0000000) && ((fStackAddr
-fStackSize
) < 0xB0000000) )
5470 warning("custom stack placement overlaps and will disable shared region");
5473 if ( fStackSize
> 0x1F000000 )
5474 throw "-stack_size must be < 496MB";
5475 if ( fStackAddr
== 0 )
5476 fStackAddr
= 0xC0000000;
5480 if ( fStackSize
> 0x1F000000 )
5481 throw "-stack_size must be < 496MB";
5482 if ( fStackAddr
== 0 )
5483 fStackAddr
= 0x1F000000;
5484 if ( fStackAddr
> 0x20000000)
5485 throw "-stack_addr must be < 0x20000000 for arm";
5487 case CPU_TYPE_X86_64
:
5488 if ( fPlatform
== kPlatformOSX
) {
5489 if ( fStackSize
> 0x10000000000 )
5490 throw "-stack_size must be <= 1TB";
5491 if ( fStackAddr
== 0 ) {
5492 fStackAddr
= 0x00007FFF5C000000LL
;
5496 if ( fStackSize
> 0x20000000 )
5497 throw "-stack_size must be <= 512MB";
5498 if ( fStackAddr
== 0 ) {
5499 fStackAddr
= 0x120000000;
5502 case CPU_TYPE_ARM64
:
5503 if ( fStackSize
> 0x20000000 )
5504 throw "-stack_size must be <= 512MB";
5505 if ( fStackAddr
== 0 )
5506 fStackAddr
= 0x120000000;
5510 if ( (fStackSize
& (-fSegmentAlignment
)) != fStackSize
)
5511 throwf("-stack_size must be multiple of segment alignment (%lldKB)", fSegmentAlignment
/1024);
5512 switch ( fOutputKind
) {
5513 case Options::kDynamicExecutable
:
5514 case Options::kStaticExecutable
:
5515 // custom stack size only legal when building main executable
5517 case Options::kDynamicLibrary
:
5518 case Options::kDynamicBundle
:
5519 case Options::kObjectFile
:
5520 case Options::kDyld
:
5521 case Options::kPreload
:
5522 case Options::kKextBundle
:
5523 throw "-stack_size option can only be used when linking a main executable";
5525 if ( fStackSize
> fStackAddr
)
5526 throwf("-stack_size (0x%08llX) must be smaller than -stack_addr (0x%08llX)", fStackSize
, fStackAddr
);
5529 // check that -allow_stack_execute is only used with main executables
5530 if ( fExecutableStack
) {
5531 switch ( fOutputKind
) {
5532 case Options::kDynamicExecutable
:
5533 case Options::kStaticExecutable
:
5534 // -allow_stack_execute size only legal when building main executable
5536 case Options::kDynamicLibrary
:
5537 case Options::kDynamicBundle
:
5538 case Options::kObjectFile
:
5539 case Options::kDyld
:
5540 case Options::kPreload
:
5541 case Options::kKextBundle
:
5542 throw "-allow_stack_execute option can only be used when linking a main executable";
5546 // check that -allow_heap_execute is only used with i386 main executables
5547 if ( fDisableNonExecutableHeap
) {
5548 if ( fArchitecture
!= CPU_TYPE_I386
)
5549 throw "-allow_heap_execute option can only be used when linking for i386";
5550 switch ( fOutputKind
) {
5551 case Options::kDynamicExecutable
:
5552 // -allow_heap_execute only legal when building main executable
5554 case Options::kStaticExecutable
:
5555 case Options::kDynamicLibrary
:
5556 case Options::kDynamicBundle
:
5557 case Options::kObjectFile
:
5558 case Options::kDyld
:
5559 case Options::kPreload
:
5560 case Options::kKextBundle
:
5561 throw "-allow_heap_execute option can only be used when linking a main executable";
5565 // check -client_name is only used when making a bundle or main executable
5566 if ( fClientName
!= NULL
) {
5567 switch ( fOutputKind
) {
5568 case Options::kDynamicExecutable
:
5569 case Options::kDynamicBundle
:
5571 case Options::kStaticExecutable
:
5572 case Options::kDynamicLibrary
:
5573 case Options::kObjectFile
:
5574 case Options::kDyld
:
5575 case Options::kPreload
:
5576 case Options::kKextBundle
:
5577 throw "-client_name can only be used with -bundle";
5581 // check -init is only used when building a dylib
5582 if ( (fInitFunctionName
!= NULL
) && (fOutputKind
!= Options::kDynamicLibrary
) )
5583 throw "-init can only be used with -dynamiclib";
5585 // check -bundle_loader only used with -bundle
5586 if ( (fBundleLoader
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
5587 throw "-bundle_loader can only be used with -bundle";
5589 // check -dtrace not used with -r
5590 if ( (fDtraceScriptName
!= NULL
) && (fOutputKind
== Options::kObjectFile
) )
5591 throw "-dtrace can only be used when creating final linked images";
5593 // check -d can only be used with -r
5594 if ( fMakeTentativeDefinitionsReal
&& (fOutputKind
!= Options::kObjectFile
) )
5595 throw "-d can only be used with -r";
5597 // check that -root_safe is not used with -r
5598 if ( fRootSafe
&& (fOutputKind
== Options::kObjectFile
) )
5599 throw "-root_safe cannot be used with -r";
5601 // check that -setuid_safe is not used with -r
5602 if ( fSetuidSafe
&& (fOutputKind
== Options::kObjectFile
) )
5603 throw "-setuid_safe cannot be used with -r";
5605 // <rdar://problem/12781832> compiler driver no longer uses -objc_abi_version, it uses -ios_simulator_version_min instead
5606 if ( !fObjCABIVersion1Override
&& !fObjCABIVersion2Override
&& fTargetIOSSimulator
)
5607 fObjCABIVersion2Override
= true;
5609 // rdar://problem/4718189 map ObjC class names to new runtime names
5610 bool alterObjC1ClassNamesToObjC2
= false;
5611 switch (fArchitecture
) {
5613 // i386 only uses new symbols when using objc2 ABI
5614 if ( fObjCABIVersion2Override
)
5615 alterObjC1ClassNamesToObjC2
= true;
5617 case CPU_TYPE_X86_64
:
5619 case CPU_TYPE_ARM64
:
5620 alterObjC1ClassNamesToObjC2
= true;
5624 // make sure all required exported symbols exist
5625 std::vector
<const char*> impliedExports
;
5626 for (NameSet::iterator it
=fExportSymbols
.regularBegin(); it
!= fExportSymbols
.regularEnd(); ++it
) {
5627 const char* name
= *it
;
5628 const int len
= strlen(name
);
5629 if ( (strcmp(&name
[len
-3], ".eh") == 0) || (strncmp(name
, ".objc_category_name_", 20) == 0) ) {
5630 // never export .eh symbols
5631 warning("ignoring %s in export list", name
);
5633 else if ( (fArchitecture
== CPU_TYPE_I386
) && !fObjCABIVersion2Override
&& (strncmp(name
, "_OBJC_CLASS_$", 13) == 0) ) {
5634 warning("ignoring Objc2 Class symbol %s in i386 export list", name
);
5635 fRemovedExports
.insert(name
);
5637 else if ( alterObjC1ClassNamesToObjC2
&& (strncmp(name
, ".objc_class_name_", 17) == 0) ) {
5638 // linking ObjC2 ABI, but have ObjC1 ABI name in export list. Change it to intended name
5639 fRemovedExports
.insert(name
);
5641 asprintf(&temp
, "_OBJC_CLASS_$_%s", &name
[17]);
5642 impliedExports
.push_back(temp
);
5643 asprintf(&temp
, "_OBJC_METACLASS_$_%s", &name
[17]);
5644 impliedExports
.push_back(temp
);
5647 fInitialUndefines
.push_back(name
);
5650 fExportSymbols
.remove(fRemovedExports
);
5651 for (std::vector
<const char*>::iterator it
=impliedExports
.begin(); it
!= impliedExports
.end(); ++it
) {
5652 const char* name
= *it
;
5653 fExportSymbols
.insert(name
);
5654 fInitialUndefines
.push_back(name
);
5657 // make sure all required re-exported symbols exist
5658 for (NameSet::iterator it
=fReExportSymbols
.regularBegin(); it
!= fReExportSymbols
.regularEnd(); ++it
) {
5659 fInitialUndefines
.push_back(*it
);
5662 // make sure that -init symbol exists
5663 if ( fInitFunctionName
!= NULL
)
5664 fInitialUndefines
.push_back(fInitFunctionName
);
5666 // make sure that entry symbol exists
5667 switch ( fOutputKind
) {
5668 case Options::kDynamicExecutable
:
5669 case Options::kStaticExecutable
:
5670 case Options::kDyld
:
5671 case Options::kPreload
:
5672 fInitialUndefines
.push_back(fEntryName
);
5674 case Options::kDynamicLibrary
:
5675 case Options::kDynamicBundle
:
5676 case Options::kObjectFile
:
5677 case Options::kKextBundle
:
5681 // make sure every alias base exists
5682 for (std::vector
<AliasPair
>::iterator it
=fAliases
.begin(); it
!= fAliases
.end(); ++it
) {
5683 fInitialUndefines
.push_back(it
->realName
);
5686 // check custom segments
5687 if ( fCustomSegmentAddresses
.size() != 0 ) {
5688 // verify no segment is in zero page
5689 if ( fZeroPageSize
!= ULLONG_MAX
) {
5690 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
5691 if ( it
->address
< fZeroPageSize
)
5692 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it
->name
, it
->address
);
5695 // verify no duplicates
5696 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
5697 for (std::vector
<SegmentStart
>::iterator it2
= fCustomSegmentAddresses
.begin(); it2
!= fCustomSegmentAddresses
.end(); ++it2
) {
5698 if ( (it
->address
== it2
->address
) && (it
!= it2
) )
5699 throwf("duplicate -segaddr addresses for %s and %s", it
->name
, it2
->name
);
5701 // a custom segment address of zero will disable the use of a zero page
5702 if ( it
->address
== 0 )
5707 if ( fZeroPageSize
== ULLONG_MAX
) {
5708 // zero page size not specified on command line, set default
5709 switch (fArchitecture
) {
5712 // first 4KB for 32-bit architectures
5713 fZeroPageSize
= 0x1000;
5715 case CPU_TYPE_ARM64
:
5716 case CPU_TYPE_X86_64
:
5717 // first 4GB for x86_64 on all OS's
5718 fZeroPageSize
= 0x100000000ULL
;
5721 // if -arch not used, default to 4K zero-page
5722 fZeroPageSize
= 0x1000;
5726 switch ( fOutputKind
) {
5727 case Options::kDynamicExecutable
:
5728 case Options::kStaticExecutable
:
5729 // -pagezero_size size only legal when building main executable
5731 case Options::kDynamicLibrary
:
5732 case Options::kDynamicBundle
:
5733 case Options::kObjectFile
:
5734 case Options::kDyld
:
5735 case Options::kPreload
:
5736 case Options::kKextBundle
:
5737 if ( fZeroPageSize
!= 0 )
5738 throw "-pagezero_size option can only be used when linking a main executable";
5742 // if main executable with custom base address, model zero page as custom segment
5743 if ( (fOutputKind
== Options::kDynamicExecutable
) && (fBaseAddress
!= 0) && (fZeroPageSize
!= 0) ) {
5745 seg
.name
= "__PAGEZERO";
5747 fCustomSegmentAddresses
.push_back(seg
);
5750 // -dead_strip and -r are incompatible
5751 if ( fDeadStrip
&& (fOutputKind
== Options::kObjectFile
) )
5752 throw "-r and -dead_strip cannot be used together";
5754 // can't use -rpath unless targeting 10.5 or later
5755 if ( fRPaths
.size() > 0 ) {
5756 if ( !minOS(ld::mac10_5
, ld::iOS_2_0
) )
5757 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
5758 switch ( fOutputKind
) {
5759 case Options::kDynamicExecutable
:
5760 case Options::kDynamicLibrary
:
5761 case Options::kDynamicBundle
:
5763 case Options::kStaticExecutable
:
5764 case Options::kObjectFile
:
5765 case Options::kDyld
:
5766 case Options::kPreload
:
5767 case Options::kKextBundle
:
5768 throw "-rpath can only be used when creating a dynamic final linked image";
5772 if ( fPositionIndependentExecutable
) {
5773 switch ( fOutputKind
) {
5774 case Options::kDynamicExecutable
:
5775 // check -pie is only used when building a dynamic main executable for 10.5
5776 if ( !minOS(ld::mac10_5
, ld::iOS_4_2
) ) {
5777 if ( fIOSVersionMin
== ld::iOSVersionUnset
)
5778 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
5780 throw "-pie can only be used when targeting iOS 4.2 or later";
5783 case Options::kStaticExecutable
:
5784 case Options::kPreload
:
5785 // -pie is ok with -static or -preload
5787 case Options::kDynamicLibrary
:
5788 case Options::kDynamicBundle
:
5789 warning("-pie being ignored. It is only used when linking a main executable");
5790 fPositionIndependentExecutable
= false;
5792 case Options::kObjectFile
:
5793 case Options::kDyld
:
5794 case Options::kKextBundle
:
5795 throw "-pie can only be used when linking a main executable";
5799 // check -read_only_relocs is not used with x86_64
5800 if ( fAllowTextRelocs
) {
5801 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
!= kKextBundle
) ) {
5802 warning("-read_only_relocs cannot be used with x86_64");
5803 fAllowTextRelocs
= false;
5807 // check -mark_auto_dead_strip is only used with dylibs
5808 if ( fMarkDeadStrippableDylib
) {
5809 if ( fOutputKind
!= Options::kDynamicLibrary
) {
5810 warning("-mark_auto_dead_strip can only be used when creating a dylib");
5811 fMarkDeadStrippableDylib
= false;
5815 // -force_cpusubtype_ALL is not supported for ARM
5816 if ( fForceSubtypeAll
) {
5817 if ( fArchitecture
== CPU_TYPE_ARM
) {
5818 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
5822 // -reexported_symbols_list can only be used with -dynamiclib
5823 if ( !fReExportSymbols
.empty() ) {
5824 if ( fOutputKind
!= Options::kDynamicLibrary
)
5825 throw "-reexported_symbols_list can only used used when created dynamic libraries";
5826 if ( !minOS(ld::mac10_7
, ld::iOS_4_2
) )
5827 throw "targeted OS version does not support -reexported_symbols_list";
5830 // -dyld_env can only be used with main executables
5831 if ( (fOutputKind
!= Options::kDynamicExecutable
) && (fDyldEnvironExtras
.size() != 0) )
5832 throw "-dyld_env can only used used when created main executables";
5834 // -segment_order can only be used with -preload or -static
5835 if ( !fSegmentOrder
.empty() && ((fOutputKind
!= Options::kPreload
) && (fOutputKind
!= kStaticExecutable
)) )
5836 throw "-segment_order can only used used with -preload output";
5838 // warn about bitcode option combinations
5839 if ( !fBundleBitcode
) {
5840 if ( fVerifyBitcode
)
5841 warning("-bitcode_verify is ignored without -bitcode_bundle");
5842 else if ( fHideSymbols
)
5843 warning("-bitcode_hide_symbols is ignored without -bitcode_bundle");
5845 if ( fReverseMapPath
!= NULL
&& !fHideSymbols
) {
5846 throw "-bitcode_symbol_map can only be used with -bitcode_hide_symbols";
5848 // auto fix up the process type for strip -S.
5849 // when there is only one input and output type is object file, downgrade kBitcodeProcess to kBitcodeAsData.
5850 if ( fOutputKind
== Options::kObjectFile
&& fInputFiles
.size() == 1 && fBitcodeKind
== Options::kBitcodeProcess
)
5851 fBitcodeKind
= Options::kBitcodeAsData
;
5853 // <rdar://problem/17598404> warn if building an embedded iOS dylib for pre-iOS 8
5854 // <rdar://problem/18935714> How can we suppress "ld: warning: embedded dylibs/frameworks only run on iOS 8 or later" when building XCTest?
5855 if ( (fOutputKind
== Options::kDynamicLibrary
) && (fIOSVersionMin
!= ld::iOSVersionUnset
) && (fDylibInstallName
!= NULL
) ) {
5856 if ( !min_iOS(ld::iOS_8_0
) && (fDylibInstallName
[0] == '@') && !fEncryptableForceOff
)
5857 warning("embedded dylibs/frameworks only run on iOS 8 or later");
5860 // bridgeOS always generates new load command
5861 if ( fVersionLoadCommand
&& (fPlatform
== kPlatform_bridgeOS
) ) {
5862 fBuildVersionLoadCommand
= true;
5865 // produce nicer error when no input
5866 if ( fInputFiles
.empty() ) {
5867 throw "no object files specified";
5872 void Options::checkForClassic(int argc
, const char* argv
[])
5875 bool archFound
= false;
5876 bool staticFound
= false;
5877 bool dtraceFound
= false;
5878 bool kextFound
= false;
5879 bool rFound
= false;
5880 bool creatingMachKernel
= false;
5881 bool newLinker
= false;
5883 // build command line buffer in case ld crashes
5884 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
5885 CRSetCrashLogMessage(crashreporterBuffer
);
5887 const char* srcRoot
= getenv("SRCROOT");
5888 if ( srcRoot
!= NULL
) {
5889 strlcpy(crashreporterBuffer
, "SRCROOT=", crashreporterBufferSize
);
5890 strlcat(crashreporterBuffer
, srcRoot
, crashreporterBufferSize
);
5891 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
5894 strlcat(crashreporterBuffer
, LD_VERS
, crashreporterBufferSize
);
5895 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
5897 strlcat(crashreporterBuffer
, "ld ", crashreporterBufferSize
);
5898 for(int i
=1; i
< argc
; ++i
) {
5899 strlcat(crashreporterBuffer
, argv
[i
], crashreporterBufferSize
);
5900 strlcat(crashreporterBuffer
, " ", crashreporterBufferSize
);
5903 for(int i
=0; i
< argc
; ++i
) {
5904 const char* arg
= argv
[i
];
5905 if ( arg
[0] == '-' ) {
5906 if ( strcmp(arg
, "-arch") == 0 ) {
5907 parseArch(argv
[++i
]);
5910 else if ( strcmp(arg
, "-static") == 0 ) {
5913 else if ( strcmp(arg
, "-kext") == 0 ) {
5916 else if ( strcmp(arg
, "-dtrace") == 0 ) {
5919 else if ( strcmp(arg
, "-r") == 0 ) {
5922 else if ( strcmp(arg
, "-new_linker") == 0 ) {
5925 else if ( strcmp(arg
, "-classic_linker") == 0 ) {
5926 // ld_classic does not understand this option, so remove it
5927 for(int j
=i
; j
< argc
; ++j
)
5928 argv
[j
] = argv
[j
+1];
5929 warning("using ld_classic");
5930 this->gotoClassicLinker(argc
-1, argv
);
5932 else if ( strcmp(arg
, "-o") == 0 ) {
5933 const char* outfile
= argv
[++i
];
5934 if ( (outfile
!= NULL
) && (strstr(outfile
, "/mach_kernel") != NULL
) )
5935 creatingMachKernel
= true;
5941 void Options::gotoClassicLinker(int argc
, const char* argv
[])
5943 argv
[0] = "ld_classic";
5944 // ld_classic does not support -iphoneos_version_min, so change
5945 for(int j
=0; j
< argc
; ++j
) {
5946 if ( (strcmp(argv
[j
], "-iphoneos_version_min") == 0) || (strcmp(argv
[j
], "-ios_version_min") == 0) ) {
5947 argv
[j
] = "-macosx_version_min";
5953 // ld classic does not understand -kext (change to -static -r)
5954 for(int j
=0; j
< argc
; ++j
) {
5955 if ( strcmp(argv
[j
], "-kext") == 0)
5957 else if ( strcmp(argv
[j
], "-dynamic") == 0)
5958 argv
[j
] = "-static";
5960 // ld classic does not understand -demangle
5961 for(int j
=0; j
< argc
; ++j
) {
5962 if ( strcmp(argv
[j
], "-demangle") == 0)
5963 argv
[j
] = "-noprebind";
5965 // in -v mode, print command line passed to ld_classic
5966 for(int i
=0; i
< argc
; ++i
) {
5967 if ( strcmp(argv
[i
], "-v") == 0 ) {
5968 for(int j
=0; j
< argc
; ++j
)
5969 printf("%s ", argv
[j
]);
5974 char rawPath
[PATH_MAX
];
5975 char path
[PATH_MAX
];
5976 uint32_t bufSize
= PATH_MAX
;
5977 if ( _NSGetExecutablePath(rawPath
, &bufSize
) != -1 ) {
5978 if ( realpath(rawPath
, path
) != NULL
) {
5979 char* lastSlash
= strrchr(path
, '/');
5980 if ( lastSlash
!= NULL
) {
5981 strcpy(lastSlash
+1, "ld_classic");
5983 execvp(path
, (char**)argv
);
5987 // in case of error in above, try searching for ld_classic via PATH
5988 execvp(argv
[0], (char**)argv
);
5989 fprintf(stderr
, "can't exec ld_classic\n");
5994 // Note, returned string buffer is own by this function.
5995 // It should not be freed
5996 // It will be reused, so clients need to strdup() if they want
5997 // to use it long term.
5998 const char* Options::demangleSymbol(const char* sym
) const
6000 // only try to demangle symbols if -demangle on command line
6004 static size_t size
= 1024;
6005 static char* buff
= (char*)malloc(size
);
6008 // only try to demangle symbols that look like Swift symbols
6009 if ( strncmp(sym
, "__T", 3) == 0 ) {
6010 size_t demangledSize
= fnd_get_demangled_name(&sym
[1], buff
, size
);
6011 if ( demangledSize
> size
) {
6012 size
= demangledSize
+2;
6013 buff
= (char*)realloc(buff
, size
);
6014 demangledSize
= fnd_get_demangled_name(&sym
[1], buff
, size
);
6016 if ( demangledSize
!= 0 )
6021 // only try to demangle symbols that look like C++ symbols
6022 if ( strncmp(sym
, "__Z", 3) != 0 )
6026 char* result
= abi::__cxa_demangle(&sym
[1], buff
, &size
, &status
);
6027 if ( result
!= NULL
) {
6028 // if demangling successful, keep buffer for next demangle
6036 void Options::writeDependencyInfo() const
6038 // do nothing if -dependency_info not used
6039 if ( !dumpDependencyInfo() )
6042 // <rdar://problem/30750137> sort entries for build reproducibility
6043 std::sort(fDependencies
.begin(), fDependencies
.end(), [](const DependencyEntry
& a
, const DependencyEntry
& b
) -> bool {
6044 if ( a
.opcode
!= b
.opcode
)
6045 return (a
.opcode
< b
.opcode
);
6046 return (a
.path
< b
.path
);
6049 // one time open() of -dependency_info file
6050 int fd
= open(this->dependencyInfoPath(), O_WRONLY
| O_TRUNC
| O_CREAT
, 0666);
6052 throwf("Could not open or create -dependency_info file: %s", this->dependencyInfoPath());
6055 uint8_t version
= depLinkerVersion
;
6056 if ( write(fd
, &version
, 1) == -1 )
6057 throwf("write() to -dependency_info failed, errno=%d", errno
);
6058 extern const char ldVersionString
[];
6059 if ( write(fd
, ldVersionString
, strlen(ldVersionString
)+1) == -1 )
6060 throwf("write() to -dependency_info failed, errno=%d", errno
);
6062 // write each dependency
6063 for (const auto& entry
: fDependencies
) {
6064 //printf("%d %s\n", entry.opcode, entry.path.c_str());
6065 if ( write(fd
, &entry
.opcode
, 1) == -1 )
6066 throwf("write() to -dependency_info failed, errno=%d", errno
);
6067 if ( write(fd
, entry
.path
.c_str(), entry
.path
.size()+1) == -1 )
6068 throwf("write() to -dependency_info failed, errno=%d", errno
);
6075 void Options::addDependency(uint8_t opcode
, const char* path
) const
6077 if ( !this->dumpDependencyInfo() )
6080 char realPath
[PATH_MAX
];
6081 if ( path
[0] != '/' ) {
6082 if ( realpath(path
, realPath
) != NULL
) {
6087 DependencyEntry entry
;
6088 entry
.opcode
= opcode
;
6090 fDependencies
.push_back(entry
);
6094 void Options::writeToTraceFile(const char* buffer
, size_t len
) const
6096 // one time open() of custom LD_TRACE_FILE
6097 if ( fTraceFileDescriptor
== -1 ) {
6098 if ( fTraceOutputFile
!= NULL
) {
6099 fTraceFileDescriptor
= open(fTraceOutputFile
, O_WRONLY
| O_APPEND
| O_CREAT
, 0666);
6100 if ( fTraceFileDescriptor
== -1 )
6101 throwf("Could not open or create trace file (errno=%d): %s", errno
, fTraceOutputFile
);
6104 fTraceFileDescriptor
= fileno(stderr
);
6109 ssize_t amountWritten
= write(fTraceFileDescriptor
, buffer
, len
);
6110 if ( amountWritten
== -1 )
6111 /* Failure to write shouldn't fail the build. */
6113 buffer
+= amountWritten
;
6114 len
-= amountWritten
;