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>
45 #include "Architectures.hpp"
46 #include "MachOFileAbstraction.hpp"
49 // from FunctionNameDemangle.h
50 extern "C" size_t fnd_get_demangled_name(const char *mangledName
, char *outputBuffer
, size_t length
);
53 // upward dependency on lto::version()
55 extern const char* version();
56 extern unsigned static_api_version();
57 extern unsigned runtime_api_version();
60 // magic to place command line in crash reports
61 const int crashreporterBufferSize
= 2000;
62 static char crashreporterBuffer
[crashreporterBufferSize
];
63 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
64 #include <CrashReporterClient.h>
65 // hack until ld does not need to build on 10.6 anymore
66 struct crashreporter_annotations_t gCRAnnotations
67 __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION
)))
68 = { CRASHREPORTER_ANNOTATIONS_VERSION
, 0, 0, 0, 0, 0, 0 };
70 extern "C" char* __crashreporter_info__
;
72 char* __crashreporter_info__
= crashreporterBuffer
;
76 static bool sEmitWarnings
= true;
77 static bool sFatalWarnings
= false;
78 static const char* sWarningsSideFilePath
= NULL
;
79 static FILE* sWarningsSideFile
= NULL
;
80 static int sWarningsCount
= 0;
82 void warning(const char* format
, ...)
85 if ( sEmitWarnings
) {
87 if ( sWarningsSideFilePath
!= NULL
) {
88 if ( sWarningsSideFile
== NULL
)
89 sWarningsSideFile
= fopen(sWarningsSideFilePath
, "a");
91 va_start(list
, format
);
92 fprintf(stderr
, "ld: warning: ");
93 vfprintf(stderr
, format
, list
);
94 fprintf(stderr
, "\n");
95 if ( sWarningsSideFile
!= NULL
) {
96 fprintf(sWarningsSideFile
, "ld: warning: ");
97 vfprintf(sWarningsSideFile
, format
, list
);
98 fprintf(sWarningsSideFile
, "\n");
99 fflush(sWarningsSideFile
);
105 void throwf(const char* format
, ...)
109 va_start(list
, format
);
110 vasprintf(&p
, format
, list
);
118 bool Options::FileInfo::checkFileExists(const Options
& options
, const char *p
)
124 struct stat statBuffer
;
127 if ( stat(p
, &statBuffer
) == 0 ) {
128 if (p
!= path
) path
= strdup(p
);
129 modTime
= statBuffer
.st_mtime
;
132 options
.addDependency(Options::depNotFound
, p
);
133 // fprintf(stderr, "not found: %s\n", p);
138 Options::Options(int argc
, const char* argv
[])
139 : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0),
140 fFallbackArchitecture(0), fFallbackSubArchitecture(0), fArchitectureName("unknown"), fOutputKind(kDynamicExecutable
),
141 fHasPreferredSubType(false), fArchSupportsThumb2(false), fBindAtLoad(false), fKeepPrivateExterns(false),
142 fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false),
143 fInterposeMode(kInterposeNone
), fDeadStrip(false), fNameSpace(kTwoLevelNameSpace
),
144 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL
), fFinalName(NULL
), fEntryName(NULL
),
145 fBaseAddress(0), fMaxAddress(0xFFFFFFFFFFFFFFFFULL
),
146 fBaseWritableAddress(0),
147 fExportMode(kExportDefault
), fLibrarySearchMode(kSearchDylibAndArchiveInEachDir
),
148 fUndefinedTreatment(kUndefinedError
), fMessagesPrefixedWithArchitecture(true),
149 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak
),
151 fUmbrellaName(NULL
), fInitFunctionName(NULL
), fDotOutputFile(NULL
), fExecutablePath(NULL
),
152 fBundleLoader(NULL
), fDtraceScriptName(NULL
), fMapPath(NULL
),
153 fDyldInstallPath("/usr/lib/dyld"), fLtoCachePath(NULL
), fTempLtoObjectPath(NULL
), fOverridePathlibLTO(NULL
), fLtoCpu(NULL
),
154 fKextObjectsEnable(-1),fKextObjectsDirPath(NULL
),fToolchainPath(NULL
),
155 fZeroPageSize(ULLONG_MAX
), fStackSize(0), fStackAddr(0), fSourceVersion(0), fSDKVersion(0), fExecutableStack(false),
156 fNonExecutableHeap(false), fDisableNonExecutableHeap(false),
157 fMinimumHeaderPad(32), fSegmentAlignment(4096),
158 fCommonsMode(kCommonsIgnoreDylibs
), fUUIDMode(kUUIDContent
), fLocalSymbolHandling(kLocalSymbolsAll
), fWarnCommons(false),
159 fVerbose(false), fKeepRelocations(false), fWarnStabs(false),
160 fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
161 fSharedRegionEligible(false), fSharedRegionEligibleForceOff(false), fPrintOrderFileStatistics(false),
162 fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), fPIEOnCommandLine(false),
163 fDisablePositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
164 fDeadStripDylibs(false), fAllowTextRelocs(false), fWarnTextRelocs(false), fKextsUseStubs(false),
165 fUsingLazyDylibLinking(false), fEncryptable(true), fEncryptableForceOn(false), fEncryptableForceOff(false),
166 fOrderData(true), fMarkDeadStrippableDylib(false),
167 fMakeCompressedDyldInfo(true), fMakeCompressedDyldInfoForceOff(false),
168 fMakeThreadedStartsSection(false), fNoEHLabels(false),
169 fAllowCpuSubtypeMismatches(false), fEnforceDylibSubtypesMatch(false),
170 fWarnOnSwiftABIVersionMismatches(false), fUseSimplifiedDylibReExports(false),
171 fObjCABIVersion2Override(false), fObjCABIVersion1Override(false), fCanUseUpwardDylib(false),
172 fFullyLoadArchives(false), fLoadAllObjcObjectsFromArchives(false), fFlatNamespace(false),
173 fLinkingMainExecutable(false), fForFinalLinkedImage(false), fForStatic(false),
174 fForDyld(false), fMakeTentativeDefinitionsReal(false), fWhyLoad(false), fRootSafe(false),
175 fSetuidSafe(false), fImplicitlyLinkPublicDylibs(true), fAddCompactUnwindEncoding(true),
176 fWarnCompactUnwind(false), fRemoveDwarfUnwindIfCompactExists(false),
177 fAutoOrderInitializers(true), fOptimizeZeroFill(true), fMergeZeroFill(false), fLogObjectFiles(false),
178 fLogAllFiles(false), fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false), fTraceEmitJSON(false),
179 fOutputSlidable(false), fWarnWeakExports(false), fNoWeakExports(false),
180 fObjcGcCompaction(false), fObjCGc(false), fObjCGcOnly(false),
181 fDemangle(false), fTLVSupport(false),
182 fVersionLoadCommand(false), fVersionLoadCommandForcedOn(false),
183 fVersionLoadCommandForcedOff(false), fFunctionStartsLoadCommand(false),
184 fFunctionStartsForcedOn(false), fFunctionStartsForcedOff(false),
185 fDataInCodeInfoLoadCommand(false), fDataInCodeInfoLoadCommandForcedOn(false), fDataInCodeInfoLoadCommandForcedOff(false),
186 fCanReExportSymbols(false), fObjcCategoryMerging(true), fPageAlignDataAtoms(false),
187 fNeedsThreadLoadCommand(false), fEntryPointLoadCommand(false),
188 fSourceVersionLoadCommand(false),
189 fSourceVersionLoadCommandForceOn(false), fSourceVersionLoadCommandForceOff(false),
190 fExportDynamic(false), fAbsoluteSymbols(false),
191 fAllowSimulatorToLinkWithMacOSX(false), fKeepDwarfUnwind(true),
192 fKeepDwarfUnwindForcedOn(false), fKeepDwarfUnwindForcedOff(false),
193 fVerboseOptimizationHints(false), fIgnoreOptimizationHints(false),
194 fGenerateDtraceDOF(true), fAllowBranchIslands(true), fTraceSymbolLayout(false),
195 fMarkAppExtensionSafe(false), fCheckAppExtensionSafe(false), fForceLoadSwiftLibs(false),
196 fSharedRegionEncodingV2(false), fUseDataConstSegment(false),
197 fUseDataConstSegmentForceOn(false), fUseDataConstSegmentForceOff(false), fUseTextExecSegment(false),
198 fBundleBitcode(false), fHideSymbols(false), fVerifyBitcode(false),
199 fReverseMapUUIDRename(false), fDeDupe(true), fVerboseDeDupe(false),
200 fUseLinkedListBinding(false), fNoLazyBinding(false), fDebugVariant(false),
201 fReverseMapPath(NULL
), fLTOCodegenOnly(false),
202 fIgnoreAutoLink(false), fAllowDeadDups(false), fAllowWeakImports(true), fInitializersTreatment(Options::kInvalid
),
203 fZeroModTimeInDebugMap(false), fBitcodeKind(kBitcodeProcess
),
204 fDebugInfoStripping(kDebugInfoMinimal
), fTraceOutputFile(NULL
),
205 fSaveTempFiles(false), fLinkSnapshot(this), fSnapshotRequested(false), fPipelineFifo(NULL
),
206 fDependencyInfoPath(NULL
), fBuildContextName(NULL
), fTraceFileDescriptor(-1), fMaxDefaultCommonAlign(0),
207 fUnalignedPointerTreatment(kUnalignedPointerIgnore
)
209 this->checkForClassic(argc
, argv
);
210 this->parsePreCommandLineEnvironmentSettings();
211 this->parse(argc
, argv
);
212 this->parsePostCommandLineEnvironmentSettings();
213 this->reconfigureDefaults();
214 this->checkIllegalOptionCombinations();
216 this->addDependency(depOutputFile
, fOutputFile
);
217 if ( fMapPath
!= NULL
)
218 this->addDependency(depOutputFile
, fMapPath
);
223 if ( fTraceFileDescriptor
!= -1 )
224 ::close(fTraceFileDescriptor
);
227 bool Options::errorBecauseOfWarnings() const
229 return (sFatalWarnings
&& (sWarningsCount
> 0));
233 const char* Options::installPath() const
235 if ( fDylibInstallName
!= NULL
)
236 return fDylibInstallName
;
237 else if ( fFinalName
!= NULL
)
244 bool Options::interposable(const char* name
) const
246 switch ( fInterposeMode
) {
249 case kInterposeAllExternal
:
252 return fInterposeList
.contains(name
);
254 throw "internal error";
258 bool Options::printWhyLive(const char* symbolName
) const
260 return fWhyLive
.contains(symbolName
);
264 const char* Options::dotOutputFile()
266 return fDotOutputFile
;
270 bool Options::hasWildCardExportRestrictList() const
272 // has -exported_symbols_list which contains some wildcards
273 return ((fExportMode
== kExportSome
) && fExportSymbols
.hasWildCards());
276 bool Options::hasWeakBitTweaks() const
278 // has -exported_symbols_list which contains some wildcards
279 return (!fForceWeakSymbols
.empty() || !fForceNotWeakSymbols
.empty());
282 bool Options::allGlobalsAreDeadStripRoots() const
284 // -exported_symbols_list means globals are not exported by default
285 if ( fExportMode
== kExportSome
)
288 switch ( fOutputKind
) {
289 case Options::kDynamicExecutable
:
290 // <rdar://problem/12839986> Add the -export_dynamic flag
291 return fExportDynamic
;
292 case Options::kStaticExecutable
:
293 // <rdar://problem/13361218> Support the -export_dynamic flag for xnu
294 return fExportDynamic
;
295 case Options::kPreload
:
296 // by default unused globals in a main executable are stripped
298 case Options::kDynamicLibrary
:
299 case Options::kDynamicBundle
:
300 case Options::kObjectFile
:
302 case Options::kKextBundle
:
309 bool Options::keepRelocations()
311 return fKeepRelocations
;
314 bool Options::warnStabs()
319 const char* Options::executablePath()
321 return fExecutablePath
;
324 uint32_t Options::initialSegProtection(const char* segName
) const
326 for(std::vector
<Options::SegmentProtect
>::const_iterator it
= fCustomSegmentProtections
.begin(); it
!= fCustomSegmentProtections
.end(); ++it
) {
327 if ( strcmp(it
->name
, segName
) == 0 ) {
331 if ( strcmp(segName
, "__TEXT") == 0 ) {
332 return ( fUseTextExecSegment
? VM_PROT_READ
: (VM_PROT_READ
| VM_PROT_EXECUTE
) );
334 else if ( strcmp(segName
, "__TEXT_EXEC") == 0 ) {
335 return VM_PROT_READ
| VM_PROT_EXECUTE
;
337 else if ( strcmp(segName
, "__PAGEZERO") == 0 ) {
340 else if ( strcmp(segName
, "__LINKEDIT") == 0 ) {
344 // all others default to read-write
345 return VM_PROT_READ
| VM_PROT_WRITE
;
348 uint32_t Options::maxSegProtection(const char* segName
) const
350 // iPhoneOS always uses same protection for max and initial
351 // <rdar://problem/11663436> simulator apps need to use MacOSX max-prot
352 if ( (platforms().contains(ld::kPlatform_macOS
) == 0) && !targetIOSSimulator() )
353 return initialSegProtection(segName
);
355 for(std::vector
<Options::SegmentProtect
>::const_iterator it
= fCustomSegmentProtections
.begin(); it
!= fCustomSegmentProtections
.end(); ++it
) {
356 if ( strcmp(it
->name
, segName
) == 0 ) {
360 if ( strcmp(segName
, "__PAGEZERO") == 0 ) {
363 // all others default to all
364 return VM_PROT_READ
| VM_PROT_WRITE
| VM_PROT_EXECUTE
;
367 uint64_t Options::segPageSize(const char* segName
) const
369 for(std::vector
<SegmentSize
>::const_iterator it
=fCustomSegmentSizes
.begin(); it
!= fCustomSegmentSizes
.end(); ++it
) {
370 if ( strcmp(it
->name
, segName
) == 0 )
373 return fSegmentAlignment
;
376 uint64_t Options::customSegmentAddress(const char* segName
) const
378 for(std::vector
<SegmentStart
>::const_iterator it
=fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
379 if ( strcmp(it
->name
, segName
) == 0 )
382 // if custom stack in use, model as segment with custom address
383 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
384 return fStackAddr
- fStackSize
;
388 bool Options::hasCustomSegmentAddress(const char* segName
) const
390 for(std::vector
<SegmentStart
>::const_iterator it
=fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
391 if ( strcmp(it
->name
, segName
) == 0 )
394 // if custom stack in use, model as segment with custom address
395 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
400 bool Options::hasCustomSectionAlignment(const char* segName
, const char* sectName
) const
402 for (std::vector
<SectionAlignment
>::const_iterator it
= fSectionAlignments
.begin(); it
!= fSectionAlignments
.end(); ++it
) {
403 if ( (strcmp(it
->segmentName
, segName
) == 0) && (strcmp(it
->sectionName
, sectName
) == 0) )
406 if ( fEncryptable
&& (strcmp(sectName
, "__oslogstring") == 0) && (strcmp(segName
, "__TEXT") == 0) )
412 uint8_t Options::customSectionAlignment(const char* segName
, const char* sectName
) const
414 for (std::vector
<SectionAlignment
>::const_iterator it
= fSectionAlignments
.begin(); it
!= fSectionAlignments
.end(); ++it
) {
415 if ( (strcmp(it
->segmentName
, segName
) == 0) && (strcmp(it
->sectionName
, sectName
) == 0) )
416 return it
->alignment
;
418 if ( fEncryptable
&& (strcmp(sectName
, "__oslogstring") == 0) && (strcmp(segName
, "__TEXT") == 0) )
419 return __builtin_ctz(fSegmentAlignment
);
424 bool Options::segmentOrderAfterFixedAddressSegment(const char* segName
) const
426 bool nowPinned
= false;
427 for (std::vector
<const char*>::const_iterator it
=fSegmentOrder
.begin(); it
!= fSegmentOrder
.end(); ++it
) {
428 if ( strcmp(*it
, segName
) == 0 )
430 if ( hasCustomSegmentAddress(*it
) )
436 bool Options::hasExportedSymbolOrder()
438 return (fExportSymbolsOrder
.size() > 0);
441 bool Options::exportedSymbolOrder(const char* sym
, unsigned int* order
) const
443 NameToOrder::const_iterator pos
= fExportSymbolsOrder
.find(sym
);
444 if ( pos
!= fExportSymbolsOrder
.end() ) {
445 *order
= pos
->second
;
454 void Options::loadSymbolOrderFile(const char* fileOfExports
, NameToOrder
& orderMapping
)
456 // read in whole file
457 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
459 throwf("can't open -exported_symbols_order file: %s", fileOfExports
);
460 struct stat stat_buf
;
461 ::fstat(fd
, &stat_buf
);
462 char* p
= (char*)malloc(stat_buf
.st_size
);
464 throwf("can't process -exported_symbols_order file: %s", fileOfExports
);
466 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
467 throwf("can't read -exported_symbols_order file: %s", fileOfExports
);
471 // parse into symbols and add to unordered_set
472 unsigned int count
= 0;
473 char * const end
= &p
[stat_buf
.st_size
];
474 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
475 char* symbolStart
= NULL
;
476 for (char* s
= p
; s
< end
; ++s
) {
482 else if ( !isspace(*s
) ) {
488 if ( (*s
== '\n') || (*s
== '\r') ) {
490 // removing any trailing spaces
492 while ( isspace(*last
) ) {
496 orderMapping
[symbolStart
] = ++count
;
502 if ( (*s
== '\n') || (*s
== '\r') )
507 if ( state
== inSymbol
) {
508 warning("missing line-end at end of file \"%s\"", fileOfExports
);
509 int len
= end
-symbolStart
+1;
510 char* temp
= new char[len
];
511 strlcpy(temp
, symbolStart
, len
);
513 // remove any trailing spaces
514 char* last
= &temp
[len
-2];
515 while ( isspace(*last
) ) {
519 orderMapping
[temp
] = ++count
;
522 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
525 bool Options::forceWeak(const char* symbolName
) const
527 return fForceWeakSymbols
.contains(symbolName
);
530 bool Options::forceNotWeak(const char* symbolName
) const
532 return fForceNotWeakSymbols
.contains(symbolName
);
535 bool Options::forceWeakNonWildCard(const char* symbolName
) const
537 return fForceWeakSymbols
.containsNonWildcard(symbolName
);
540 bool Options::forceNotWeakNonWildcard(const char* symbolName
) const
542 return fForceNotWeakSymbols
.containsNonWildcard(symbolName
);
545 bool Options::forceCoalesce(const char* symbolName
) const
547 return fForceCoalesceSymbols
.contains(symbolName
);
551 bool Options::shouldExport(const char* symbolName
) const
553 switch (fExportMode
) {
555 return fExportSymbols
.contains(symbolName
);
556 case kDontExportSome
:
557 return ! fDontExportSymbols
.contains(symbolName
);
561 throw "internal error";
564 bool Options::shouldReExport(const char* symbolName
) const
566 return fReExportSymbols
.contains(symbolName
);
569 bool Options::keepLocalSymbol(const char* symbolName
) const
571 switch (fLocalSymbolHandling
) {
572 case kLocalSymbolsAll
:
574 case kLocalSymbolsNone
:
576 case kLocalSymbolsSelectiveInclude
:
577 return fLocalSymbolsIncluded
.contains(symbolName
);
578 case kLocalSymbolsSelectiveExclude
:
579 return ! fLocalSymbolsExcluded
.contains(symbolName
);
581 throw "internal error";
584 const std::vector
<const char*>* Options::sectionOrder(const char* segName
) const
586 for (std::vector
<SectionOrderList
>::const_iterator it
=fSectionOrder
.begin(); it
!= fSectionOrder
.end(); ++it
) {
587 if ( strcmp(it
->segmentName
, segName
) == 0 )
588 return &it
->sectionOrder
;
593 void Options::setArchitecture(cpu_type_t type
, cpu_subtype_t subtype
, ld::Platform platform
, uint32_t minOsVers
)
595 for (const ArchInfo
* t
=archInfoArray
; t
->archName
!= NULL
; ++t
) {
596 if ( (type
== t
->cpuType
) && (subtype
== t
->cpuSubType
) ) {
597 fArchitecture
= type
;
598 fSubArchitecture
= subtype
;
599 fArchitectureName
= t
->archName
;
600 fHasPreferredSubType
= t
->isSubType
;
601 fArchSupportsThumb2
= t
->supportsThumb2
;
602 if ( platforms().empty() && (platform
!= ld::kPlatform_unknown
) )
603 fPlatforms
.add({platform
, minOsVers
});
606 case CPU_TYPE_X86_64
:
607 if ( platforms().contains(ld::kPlatform_macOS
) && (fOutputKind
!= Options::kObjectFile
) && (platforms().minOS(ld::kPlatform_macOS
) == 0) ) {
608 #ifdef DEFAULT_MACOSX_MIN_VERSION
609 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION
);
610 setVersionMin(ld::kPlatform_macOS
, DEFAULT_MACOSX_MIN_VERSION
);
612 warning("-macosx_version_min not specified, assuming 10.6");
613 setVersionMin(ld::kPlatform_macOS
, "10.6");
619 if ( platforms().contains(ld::kPlatform_iOS
) && (platforms().minOS(ld::kPlatform_iOS
) == 0) && (fOutputKind
!= Options::kObjectFile
) ) {
620 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
621 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION
);
622 setVersionMin(ld::kPlatformiOS
, DEFAULT_IPHONEOS_MIN_VERSION
);
624 warning("-ios_version_min not specified, assuming 6.0");
625 setVersionMin(ld::kPlatform_iOS
, "6.0");
628 #if SUPPORT_ARCH_arm64e
629 if ( (fArchitecture
== CPU_TYPE_ARM64
) && (fSubArchitecture
== CPU_SUBTYPE_ARM64_E
) ) {
630 fSupportsAuthenticatedPointers
= true;
635 fLinkSnapshot
.recordArch(fArchitectureName
);
636 // only use compressed LINKEDIT for:
637 // Mac OS X 10.6 or later
639 if ( !fMakeCompressedDyldInfo
&& platforms().minOS(ld::version2009
) && !fMakeCompressedDyldInfoForceOff
)
640 fMakeCompressedDyldInfo
= true;
641 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
642 if ( platforms().minOS(ld::version2008
) )
643 fUseSimplifiedDylibReExports
= true;
647 fArchitectureName
= "unknown architecture";
650 bool Options::armUsesZeroCostExceptions() const
652 return ( (fArchitecture
== CPU_TYPE_ARM
) && (fSubArchitecture
== CPU_SUBTYPE_ARM_V7K
) );
655 void Options::selectFallbackArch(const char *arch
)
657 // Should have the format "desired_arch:fallback_arch", for example "arm64_32:armv7k" to allow an armv7k
658 // slice to substitute for arm64_32 if the latter isn't present.
659 if (const char* fallbackEnv
= getenv("LD_DYLIB_ARCH_FALLBACK") ) {
660 std::string
fallback(fallbackEnv
);
661 auto delimPos
= fallback
.find(':');
663 // Check we've got a potentially valid fallback string and that it's this architecture we're falling back from.
664 if ( delimPos
== std::string::npos
|| fallback
.substr(0, delimPos
) != arch
)
667 std::string fallbackTo
= fallback
.substr(delimPos
+ 1);
668 for (const ArchInfo
*t
= archInfoArray
; t
->archName
!= nullptr; ++t
) {
669 if ( fallbackTo
== t
->archName
) {
670 fFallbackArchitecture
= t
->cpuType
;
671 fFallbackSubArchitecture
= t
->cpuSubType
;
676 // <rdar://problem/39797337> let x86_64h fallback and use x86_64 slice
677 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fSubArchitecture
== CPU_SUBTYPE_X86_64_H
) ) {
678 fFallbackArchitecture
= CPU_TYPE_X86_64
;
679 fFallbackSubArchitecture
= CPU_SUBTYPE_X86_ALL
;
684 void Options::parseArch(const char* arch
)
687 throw "-arch must be followed by an architecture string";
688 for (const ArchInfo
* t
=archInfoArray
; t
->archName
!= NULL
; ++t
) {
689 if ( strcmp(t
->archName
,arch
) == 0 ) {
690 fArchitectureName
= arch
;
691 fArchitecture
= t
->cpuType
;
692 fSubArchitecture
= t
->cpuSubType
;
693 fHasPreferredSubType
= t
->isSubType
;
694 fArchSupportsThumb2
= t
->supportsThumb2
;
695 selectFallbackArch(arch
);
699 throwf("unknown/unsupported architecture name for: -arch %s", arch
);
702 bool Options::checkForFile(const char* format
, const char* dir
, const char* rootName
, FileInfo
& result
) const
704 char possiblePath
[strlen(dir
)+strlen(rootName
)+strlen(format
)+8];
705 sprintf(possiblePath
, format
, dir
, rootName
);
706 bool found
= result
.checkFileExists(*this, possiblePath
);
707 if ( fTraceDylibSearching
)
708 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), possiblePath
);
713 Options::FileInfo
Options::findLibrary(const char* rootName
, bool dylibsOnly
) const
716 const int rootNameLen
= strlen(rootName
);
717 // if rootName ends in .o there is no .a vs .dylib choice
718 if ( (rootNameLen
> 3) && (strcmp(&rootName
[rootNameLen
-2], ".o") == 0) ) {
719 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
720 it
!= fLibrarySearchPaths
.end();
722 const char* dir
= *it
;
723 if ( checkForFile("%s/%s", dir
, rootName
, result
) )
728 bool lookForDylibs
= false;
729 switch ( fOutputKind
) {
730 case Options::kDynamicExecutable
:
731 case Options::kDynamicLibrary
:
732 case Options::kDynamicBundle
:
733 case Options::kObjectFile
: // <rdar://problem/15914513>
734 lookForDylibs
= true;
736 case Options::kStaticExecutable
:
738 case Options::kPreload
:
739 case Options::kKextBundle
:
740 lookForDylibs
= false;
743 switch ( fLibrarySearchMode
) {
744 case kSearchAllDirsForDylibsThenAllDirsForArchives
:
745 // first look in all directories for just for dylibs
746 if ( lookForDylibs
) {
747 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
748 it
!= fLibrarySearchPaths
.end();
750 const char* dir
= *it
;
751 auto path
= std::string(dir
) + "/lib" + rootName
+ ".dylib";
752 if ( findFile(path
, {".tbd"}, result
) )
755 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
756 it
!= fLibrarySearchPaths
.end();
758 const char* dir
= *it
;
759 if ( checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
763 // next look in all directories for just for archives
765 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
766 it
!= fLibrarySearchPaths
.end();
768 const char* dir
= *it
;
769 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
775 case kSearchDylibAndArchiveInEachDir
:
776 // look in each directory for just for a dylib then for an archive
777 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
778 it
!= fLibrarySearchPaths
.end();
780 const char* dir
= *it
;
781 auto path
= std::string(dir
) + "/lib" + rootName
+ ".dylib";
782 if ( lookForDylibs
&& findFile(path
, {".tbd"}, result
) )
784 if ( lookForDylibs
&& checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
786 if ( !dylibsOnly
&& checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
792 throwf("library not found for -l%s", rootName
);
795 Options::FileInfo
Options::findFramework(const char* frameworkName
) const
797 if ( frameworkName
== NULL
)
798 throw "-framework missing next argument";
799 char temp
[strlen(frameworkName
)+1];
800 strcpy(temp
, frameworkName
);
801 const char* name
= temp
;
802 const char* suffix
= NULL
;
803 char* comma
= strchr(temp
, ',');
804 if ( comma
!= NULL
) {
808 return findFramework(name
, suffix
);
811 Options::FileInfo
Options::findFramework(const char* rootName
, const char* suffix
) const
813 for (const auto* path
: fFrameworkSearchPaths
) {
814 auto possiblePath
= std::string(path
).append("/").append(rootName
).append(".framework/").append(rootName
);
815 if ( suffix
!= nullptr ) {
816 char realPath
[PATH_MAX
];
817 // no symlink in framework to suffix variants, so follow main symlink
818 if ( realpath(possiblePath
.c_str(), realPath
) != nullptr )
819 possiblePath
= std::string(realPath
).append(suffix
);
822 if ( findFile(possiblePath
, {".tbd"}, result
) )
825 // try without suffix
826 if ( suffix
!= NULL
)
827 return findFramework(rootName
, NULL
);
829 throwf("framework not found %s", rootName
);
832 static std::string
replace_extension(const std::string
&path
, const std::string
&ext
)
835 auto lastSlashIdx
= result
.find_last_of('/');
836 auto lastDotIdx
= result
.find_last_of('.');
837 if (lastDotIdx
!= std::string::npos
&& lastDotIdx
> lastSlashIdx
)
838 result
.erase(lastDotIdx
, std::string::npos
);
839 if ( ext
.size() > 0 && ext
[0] == '.' )
842 result
.append('.' + ext
);
846 void Options::addTAPIInterface(tapi::LinkerInterfaceFile
* interface
, const char *path
) const {
847 #if ((TAPI_API_VERSION_MAJOR == 1 && TAPI_API_VERSION_MINOR >= 3) || (TAPI_API_VERSION_MAJOR > 1))
848 if (tapi::APIVersion::isAtLeast(1, 3)) {
849 for (auto &name
: interface
->inlinedFrameworkNames()) {
850 fTAPIFiles
.emplace_back(interface
, path
, name
.c_str());
856 bool Options::findFile(const std::string
&path
, const std::vector
<std::string
> &tbdExtensions
, FileInfo
& result
) const
859 for ( const auto &ext
: tbdExtensions
) {
860 auto newPath
= replace_extension(path
, ext
);
861 bool found
= tbdInfo
.checkFileExists(*this, newPath
.c_str());
862 if ( fTraceDylibSearching
)
863 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), newPath
.c_str());
870 bool found
= dylibInfo
.checkFileExists(*this, path
.c_str());
871 if ( fTraceDylibSearching
)
872 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), path
.c_str());
875 // There is only a text-based stub file or a dynamic library file.
876 if ( tbdInfo
.missing() != dylibInfo
.missing() ) {
877 result
= tbdInfo
.missing() ? dylibInfo
: tbdInfo
;
879 // There are both - a text-based stub file and a dynamic library file.
880 else if ( !tbdInfo
.missing() && !dylibInfo
.missing() ) {
881 // Check if we should prefer the text-based stub file (installapi).
882 if (tapi::LinkerInterfaceFile::shouldPreferTextBasedStubFile(tbdInfo
.path
)) {
885 // If the files are still in sync we can use and should use the text-based stub file.
886 else if (tapi::LinkerInterfaceFile::areEquivalent(tbdInfo
.path
, dylibInfo
.path
)) {
889 // Otherwise issue a warning and fall-back to the dynamic library file.
891 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
);
901 static bool startsWith(const std::string
& str
, const std::string
& prefix
)
903 return (str
.compare(0, prefix
.length(), prefix
) == 0);
906 static std::string
getDirPath(const std::string
& path
)
908 std::string::size_type lastSlashPos
= path
.find_last_of('/');
909 if ( lastSlashPos
== std::string::npos
)
912 return path
.substr(0, lastSlashPos
+1);
915 Options::FileInfo
Options::findFile(const std::string
&path
, const ld::dylib::File
* fromDylib
) const
919 // if absolute path and not a .o file, then use SDK prefix
920 if ( (path
[0] == '/') && (strcmp(&path
[path
.size()-2], ".o") != 0) ) {
921 for (const auto* sdkPathDir
: fSDKPaths
) {
922 auto possiblePath
= std::string(sdkPathDir
) + path
;
923 if ( findFile(possiblePath
, {".tbd"}, result
) )
928 // expand @ variables
929 if ( path
[0] == '@' ) {
930 if ( startsWith(path
, "@executable_path/") && (fExecutablePath
!= nullptr) ) {
931 std::string exeBasedPath
= getDirPath(fExecutablePath
) + &path
[17];
932 if ( findFile(exeBasedPath
, {".tbd"}, result
) )
935 else if ( startsWith(path
, "@loader_path/") && (fromDylib
!= nullptr) ) {
936 char absPath
[PATH_MAX
];
937 if ( realpath(fromDylib
->path(), absPath
) != NULL
) {
938 std::string loaderBasedPath
= getDirPath(fromDylib
->path()) + &path
[13];
939 if ( findFile(loaderBasedPath
, {".tbd"}, result
) )
943 else if ( startsWith(path
, "@rpath/") ) {
944 // first search any LC_RPATH supplied by dyld that re-exports dylib to be found
945 if ( fromDylib
!= nullptr ) {
946 for (const char* rp
: fromDylib
->rpaths() ) {
947 std::string rpath
= rp
;
948 // handle dylib that has LC_RPATH = @loader_path/blah
949 if ( startsWith(rpath
, "@loader_path/") ) {
950 char absPath
[PATH_MAX
];
951 if ( realpath(fromDylib
->path(), absPath
) != NULL
)
952 rpath
= getDirPath(absPath
) + &rpath
[13];
954 rpath
= getDirPath(fromDylib
->path()) + &rpath
[13];
956 std::string rpathBasedPath
= rpath
+ "/" + &path
[6];
957 if ( findFile(rpathBasedPath
, {".tbd"}, result
) )
964 // find inlined TBD file before raw path.
965 // rdar://problem/35864452
966 if (hasInlinedTAPIFile(path
)) {
967 FileInfo
inlinedFile(path
.c_str());
968 inlinedFile
.isInlined
= true;
973 if ( findFile(path
, {".tbd"}, result
) )
977 throwf("file not found: %s", path
.c_str());
980 bool Options::hasInlinedTAPIFile(const std::string
&path
) const {
981 for (const auto &dylib
: fTAPIFiles
) {
982 if (dylib
.getInstallName() == path
)
988 tapi::LinkerInterfaceFile
* Options::findTAPIFile(const std::string
&path
) const
990 #if ((TAPI_API_VERSION_MAJOR == 1 && TAPI_API_VERSION_MINOR >= 3) || (TAPI_API_VERSION_MAJOR > 1))
991 tapi::LinkerInterfaceFile
* interface
= nullptr;
994 // create parsing options.
995 tapi::ParsingFlags flags
= tapi::ParsingFlags::None
;
996 if (enforceDylibSubtypesMatch())
997 flags
|= tapi::ParsingFlags::ExactCpuSubType
;
999 if (!allowWeakImports())
1000 flags
|= tapi::ParsingFlags::DisallowWeakImports
;
1002 __block
uint32_t linkMinOSVersion
= 0;
1003 //FIXME handle this correctly once we have multi-platform TAPI.
1004 platforms().forEach(^(ld::Platform platform
, uint32_t version
, bool &stop
) {
1005 if (linkMinOSVersion
== 0)
1006 linkMinOSVersion
= version
;
1007 if (platform
== ld::kPlatform_macOS
)
1008 linkMinOSVersion
= version
;
1011 // Search through all the inlined framework.
1012 for (const auto &dylib
: fTAPIFiles
) {
1013 if (dylib
.getInstallName() == path
) {
1014 // If the install name matches, parse the framework.
1015 std::string errorMessage
;
1016 auto file
= dylib
.getInterfaceFile()->getInlinedFramework(path
.c_str(), architecture(), subArchitecture(),
1017 flags
, tapi::PackedVersion32(linkMinOSVersion
), errorMessage
);
1019 throw strdup(errorMessage
.c_str());
1022 // If this is the first inlined framework found, record the information.
1024 TBDPath
= dylib
.getTAPIFilePath();
1026 // If we found other inlined framework already, check to see if their versions are the same.
1027 // If not the same, emit an warning and record the newer one. Otherwise, just use the current one.
1028 if (interface
->getCurrentVersion() == file
->getCurrentVersion())
1030 warning("Inlined framework/dylib mismatch: %s (%s and %s)", path
.c_str(),
1031 TBDPath
.c_str(), dylib
.getTAPIFilePath().c_str());
1032 if (interface
->getCurrentVersion() < file
->getCurrentVersion()) {
1034 TBDPath
= dylib
.getTAPIFilePath();
1045 // search for indirect dylib first using -F and -L paths first
1046 Options::FileInfo
Options::findIndirectDylib(const std::string
& installName
, const ld::dylib::File
* fromDylib
) const
1050 auto lastSlashPos
= installName
.find_last_of('/');
1051 auto pos
= ( lastSlashPos
!= std::string::npos
) ? lastSlashPos
+ 1 : 0;
1052 auto leafName
= installName
.substr(pos
);
1054 // Is this in a framework?
1055 // /path/Foo.framework/Foo ==> true (Foo)
1056 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
1057 // /path/Foo.framework/Resources/Bar ==> false
1058 bool isFramework
= false;
1059 if ( lastSlashPos
!= std::string::npos
) {
1060 auto frameworkDir
= std::string("/").append(leafName
).append(".framework/");
1061 if ( installName
.rfind(frameworkDir
) != std::string::npos
)
1065 // These are abbreviated versions of the routines findFramework and findLibrary above
1066 // because we already know the final name of the file that we're looking for and so
1067 // don't need to try variations, just paths. We do need to add the additional bits
1068 // onto the framework path though.
1069 if ( isFramework
) {
1070 auto endPos
= installName
.rfind(".framework");
1071 auto beginPos
= installName
.find_last_of('/', endPos
);
1072 auto leafPath
= installName
.substr(beginPos
);
1073 for (const auto* dir
: fFrameworkSearchPaths
) {
1074 auto possiblePath
= dir
+ leafPath
;
1075 if ( findFile(possiblePath
, {".tbd"}, result
) )
1079 // if this is a .dylib inside a framework, do not search -L paths
1080 // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
1081 bool embeddedDylib
= ( (leafName
.size() > 6)
1082 && (leafName
.find(".dylib", leafName
.size()-6) != std::string::npos
)
1083 && (installName
.find(".framework/") != std::string::npos
) );
1084 if ( !embeddedDylib
) {
1085 for (const auto* dir
: fLibrarySearchPaths
) {
1086 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
1087 std::string possiblePath
= dir
+ std::string("/") + leafName
;
1088 if ( findFile(possiblePath
, {".tbd"}, result
) )
1094 // If we didn't find it fall back to findFile.
1095 return findFile(installName
, fromDylib
);
1098 void Options::loadFileList(const char* fileOfPaths
, ld::File::Ordinal baseOrdinal
)
1101 const char* comma
= strrchr(fileOfPaths
, ',');
1102 const char* prefix
= NULL
;
1103 if ( comma
!= NULL
) {
1104 // <rdar://problem/5907981> -filelist fails with comma in path
1105 file
= fopen(fileOfPaths
, "r");
1106 if ( file
== NULL
) {
1108 int realFileOfPathsLen
= comma
-fileOfPaths
;
1109 char realFileOfPaths
[realFileOfPathsLen
+1];
1110 strncpy(realFileOfPaths
,fileOfPaths
, realFileOfPathsLen
);
1111 realFileOfPaths
[realFileOfPathsLen
] = '\0';
1112 file
= fopen(realFileOfPaths
, "r");
1114 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", realFileOfPaths
, errno
, strerror(errno
));
1115 this->addDependency(Options::depFileList
, realFileOfPaths
);
1119 file
= fopen(fileOfPaths
, "r");
1121 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", fileOfPaths
, errno
, strerror(errno
));
1122 this->addDependency(Options::depFileList
, fileOfPaths
);
1125 char path
[PATH_MAX
];
1126 ld::File::Ordinal previousOrdinal
= baseOrdinal
;
1127 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
1128 path
[PATH_MAX
-1] = '\0';
1129 char* eol
= strchr(path
, '\n');
1132 if ( prefix
!= NULL
) {
1133 char builtPath
[strlen(prefix
)+strlen(path
)+2];
1134 strcpy(builtPath
, prefix
);
1135 strcat(builtPath
, "/");
1136 strcat(builtPath
, path
);
1137 if (fPipelineFifo
!= NULL
) {
1138 FileInfo info
= FileInfo(builtPath
);
1139 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1140 previousOrdinal
= info
.ordinal
;
1141 info
.fromFileList
= true;
1142 fInputFiles
.push_back(info
);
1144 FileInfo info
= findFile(builtPath
);
1145 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1146 previousOrdinal
= info
.ordinal
;
1147 info
.fromFileList
= true;
1148 fInputFiles
.push_back(info
);
1152 if (fPipelineFifo
!= NULL
) {
1153 FileInfo info
= FileInfo(path
);
1154 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1155 previousOrdinal
= info
.ordinal
;
1156 info
.fromFileList
= true;
1157 fInputFiles
.push_back(info
);
1159 FileInfo info
= findFile(path
);
1160 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1161 previousOrdinal
= info
.ordinal
;
1162 info
.fromFileList
= true;
1163 fInputFiles
.push_back(info
);
1171 void Options::SetWithWildcards::remove(const NameSet
& toBeRemoved
)
1173 for(NameSet::const_iterator it
=toBeRemoved
.begin(); it
!= toBeRemoved
.end(); ++it
) {
1174 const char* symbolName
= *it
;
1175 NameSet::iterator pos
= fRegular
.find(symbolName
);
1176 if ( pos
!= fRegular
.end() )
1177 fRegular
.erase(pos
);
1181 bool Options::SetWithWildcards::hasWildCards(const char* symbol
)
1183 // an exported symbol name containing *, ?, or [ requires wildcard matching
1184 return ( strpbrk(symbol
, "*?[") != NULL
);
1187 void Options::SetWithWildcards::insert(const char* symbol
)
1189 if ( hasWildCards(symbol
) )
1190 fWildCard
.push_back(symbol
);
1192 fRegular
.insert(symbol
);
1195 bool Options::SetWithWildcards::contains(const char* symbol
, bool* matchBecauseOfWildcard
) const
1197 if ( matchBecauseOfWildcard
!= NULL
)
1198 *matchBecauseOfWildcard
= false;
1199 // first look at hash table on non-wildcard symbols
1200 if ( fRegular
.find(symbol
) != fRegular
.end() )
1202 // next walk list of wild card symbols looking for a match
1203 for(std::vector
<const char*>::const_iterator it
= fWildCard
.begin(); it
!= fWildCard
.end(); ++it
) {
1204 if ( wildCardMatch(*it
, symbol
) ) {
1205 if ( matchBecauseOfWildcard
!= NULL
)
1206 *matchBecauseOfWildcard
= true;
1213 // Support "foo.o:_bar" to mean symbol _bar in file foo.o
1214 bool Options::SetWithWildcards::containsWithPrefix(const char* symbol
, const char* file
, bool& wildCardMatch
) const
1216 wildCardMatch
= false;
1217 if ( contains(symbol
, &wildCardMatch
) )
1221 const char* s
= strrchr(file
, '/');
1224 char buff
[strlen(file
)+strlen(symbol
)+2];
1225 sprintf(buff
, "%s:%s", file
, symbol
);
1226 return contains(buff
, &wildCardMatch
);
1229 bool Options::SetWithWildcards::containsNonWildcard(const char* symbol
) const
1231 // look at hash table on non-wildcard symbols
1232 return ( fRegular
.find(symbol
) != fRegular
.end() );
1236 std::vector
<const char*> Options::exportsData() const
1238 return fExportSymbols
.data();
1242 std::vector
<const char*> Options::SetWithWildcards::data() const
1244 std::vector
<const char*> data
;
1245 for (NameSet::iterator it
=regularBegin(); it
!= regularEnd(); ++it
) {
1246 data
.push_back(*it
);
1248 for (std::vector
<const char*>::const_iterator it
=fWildCard
.begin(); it
!= fWildCard
.end(); ++it
) {
1249 data
.push_back(*it
);
1254 bool Options::SetWithWildcards::inCharRange(const char*& p
, unsigned char c
) const
1258 while ( *p
!= '\0' ) {
1261 // found beginining [ and ending ]
1262 unsigned char last
= '\0';
1263 for ( const char* s
= b
; s
< e
; ++s
) {
1265 unsigned char next
= *(++s
);
1266 if ( (last
<= c
) && (c
<= next
) )
1283 bool Options::SetWithWildcards::wildCardMatch(const char* pattern
, const char* symbol
) const
1285 const char* s
= symbol
;
1286 for (const char* p
= pattern
; *p
!= '\0'; ++p
) {
1291 for (const char* t
= s
; *t
!= '\0'; ++t
) {
1292 if ( wildCardMatch(&p
[1], t
) )
1302 if ( ! inCharRange(p
, *s
) )
1312 return (*s
== '\0');
1316 void Options::loadExportFile(const char* fileOfExports
, const char* option
, SetWithWildcards
& set
)
1318 if ( fileOfExports
== NULL
)
1319 throwf("missing file after %s", option
);
1320 // read in whole file
1321 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
1323 throwf("can't open %s file: %s", option
, fileOfExports
);
1324 struct stat stat_buf
;
1325 ::fstat(fd
, &stat_buf
);
1326 char* p
= (char*)malloc(stat_buf
.st_size
);
1328 throwf("can't process %s file: %s", option
, fileOfExports
);
1330 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1331 throwf("can't read %s file: %s", option
, fileOfExports
);
1333 this->addDependency(Options::depMisc
, fileOfExports
);
1337 // parse into symbols and add to unordered_set
1338 char * const end
= &p
[stat_buf
.st_size
];
1339 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1340 char* symbolStart
= NULL
;
1341 for (char* s
= p
; s
< end
; ++s
) {
1347 else if ( !isspace(*s
) ) {
1353 if ( (*s
== '\n') || (*s
== '\r') ) {
1355 // removing any trailing spaces
1357 while ( isspace(*last
) ) {
1361 set
.insert(symbolStart
);
1367 if ( (*s
== '\n') || (*s
== '\r') )
1372 if ( state
== inSymbol
) {
1373 warning("missing line-end at end of file \"%s\"", fileOfExports
);
1374 int len
= end
-symbolStart
+1;
1375 char* temp
= new char[len
];
1376 strlcpy(temp
, symbolStart
, len
);
1378 // remove any trailing spaces
1379 char* last
= &temp
[len
-2];
1380 while ( isspace(*last
) ) {
1387 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
1390 void Options::parseAliasFile(const char* fileOfAliases
)
1392 // read in whole file
1393 int fd
= ::open(fileOfAliases
, O_RDONLY
, 0);
1395 throwf("can't open alias file: %s", fileOfAliases
);
1396 struct stat stat_buf
;
1397 ::fstat(fd
, &stat_buf
);
1398 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1400 throwf("can't process alias file: %s", fileOfAliases
);
1402 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1403 throwf("can't read alias file: %s", fileOfAliases
);
1404 p
[stat_buf
.st_size
] = '\n';
1406 this->addDependency(Options::depMisc
, fileOfAliases
);
1408 // parse into symbols and add to fAliases
1410 char * const end
= &p
[stat_buf
.st_size
+1];
1411 enum { lineStart
, inRealName
, inBetween
, inAliasName
, inComment
} state
= lineStart
;
1413 for (char* s
= p
; s
< end
; ++s
) {
1419 else if ( !isspace(*s
) ) {
1426 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1430 else if ( isspace(*s
) ) {
1437 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1441 else if ( ! isspace(*s
) ) {
1442 state
= inAliasName
;
1449 // removing any trailing spaces
1451 while ( isspace(*last
) ) {
1455 fAliases
.push_back(pair
);
1458 else if ( *s
== '\n' ) {
1460 // removing any trailing spaces
1462 while ( isspace(*last
) ) {
1466 fAliases
.push_back(pair
);
1477 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
1482 void Options::setUndefinedTreatment(const char* treatment
)
1484 if ( treatment
== NULL
)
1485 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
1487 if ( strcmp(treatment
, "warning") == 0 )
1488 fUndefinedTreatment
= kUndefinedWarning
;
1489 else if ( strcmp(treatment
, "error") == 0 )
1490 fUndefinedTreatment
= kUndefinedError
;
1491 else if ( strcmp(treatment
, "suppress") == 0 )
1492 fUndefinedTreatment
= kUndefinedSuppress
;
1493 else if ( strcmp(treatment
, "dynamic_lookup") == 0 )
1494 fUndefinedTreatment
= kUndefinedDynamicLookup
;
1496 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1499 Options::Treatment
Options::parseTreatment(const char* treatment
)
1501 if ( treatment
== NULL
)
1504 if ( strcmp(treatment
, "warning") == 0 )
1506 else if ( strcmp(treatment
, "error") == 0 )
1508 else if ( strcmp(treatment
, "suppress") == 0 )
1514 void Options::setVersionMin(const ld::Platform
& platform
, const char *version
) {
1515 auto checkAndParse
= [&](const char *errorFlag
) {
1516 if ( version
== NULL
)
1517 throwf("%s missing version argument", errorFlag
);
1519 if ( !parsePackedVersion32(version
, value
) ) {
1520 throwf("%s value malformed: '%s'", errorFlag
, version
);
1522 fPlatforms
.add({platform
, value
});
1526 case ld::kPlatform_macOS
: checkAndParse("-macosx_version_min"); break;
1527 case ld::kPlatform_iOS
: checkAndParse("-ios_version_min"); break;
1528 case ld::kPlatform_tvOS
: checkAndParse("-tvos_version_min"); break;
1529 case ld::kPlatform_watchOS
: checkAndParse("-watchos_version_min"); break;
1530 case ld::kPlatform_bridgeOS
: checkAndParse("-bridgeos_version_min"); break;
1531 case ld::kPlatform_iOSSimulator
: checkAndParse("-ios_simulator_version_min"); break;
1532 case ld::kPlatform_tvOSSimulator
: checkAndParse("-tvos_simulator_version_min"); break;
1533 case ld::kPlatform_watchOSSimulator
: checkAndParse("-watchos_simulator_version_min"); break;
1534 case ld::kPlatform_unknown
: throw "kPlatformUnknown is an invalid argument to setVersionMin()";
1535 case ld::kPlatform_iOSMac
: checkAndParse("-iosmac_version_min"); break;
1539 void Options::setWeakReferenceMismatchTreatment(const char* treatment
)
1541 if ( treatment
== NULL
)
1542 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1544 if ( strcmp(treatment
, "error") == 0 )
1545 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchError
;
1546 else if ( strcmp(treatment
, "weak") == 0 )
1547 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchWeak
;
1548 else if ( strcmp(treatment
, "non-weak") == 0 )
1549 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchNonWeak
;
1551 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1554 Options::CommonsMode
Options::parseCommonsTreatment(const char* mode
)
1557 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1559 if ( strcmp(mode
, "ignore_dylibs") == 0 )
1560 return kCommonsIgnoreDylibs
;
1561 else if ( strcmp(mode
, "use_dylibs") == 0 )
1562 return kCommonsOverriddenByDylibs
;
1563 else if ( strcmp(mode
, "error") == 0 )
1564 return kCommonsConflictsDylibsError
;
1566 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1569 void Options::addDylibOverride(const char* paths
)
1571 if ( paths
== NULL
)
1572 throw "-dylib_file must followed by two colon separated paths";
1573 const char* colon
= strchr(paths
, ':');
1574 if ( colon
== NULL
)
1575 throw "-dylib_file must followed by two colon separated paths";
1576 int len
= colon
-paths
;
1577 char* target
= new char[len
+2];
1578 strncpy(target
, paths
, len
);
1580 DylibOverride entry
;
1581 entry
.installName
= target
;
1582 entry
.useInstead
= &colon
[1];
1583 fDylibOverrides
.push_back(entry
);
1586 uint64_t Options::parseAddress(const char* addr
)
1589 uint64_t result
= strtoull(addr
, &endptr
, 16);
1593 uint32_t Options::parseProtection(const char* prot
)
1595 uint32_t result
= 0;
1596 for(const char* p
= prot
; *p
!= '\0'; ++p
) {
1597 switch(tolower(*p
)) {
1599 result
|= VM_PROT_READ
;
1602 result
|= VM_PROT_WRITE
;
1605 result
|= VM_PROT_EXECUTE
;
1610 throwf("unknown -segprot lettter in %s", prot
);
1618 // Parses number of form A[.B[.B[.D[.E]]]] into a uint64_t where the bits are a24.b10.c10.d10.e10
1620 uint64_t Options::parseVersionNumber64(const char* versionString
)
1628 a
= strtoul(versionString
, &end
, 10);
1629 if ( *end
== '.' ) {
1630 b
= strtoul(&end
[1], &end
, 10);
1631 if ( *end
== '.' ) {
1632 c
= strtoul(&end
[1], &end
, 10);
1633 if ( *end
== '.' ) {
1634 d
= strtoul(&end
[1], &end
, 10);
1635 if ( *end
== '.' ) {
1636 e
= strtoul(&end
[1], &end
, 10);
1641 if ( (*end
!= '\0') || (a
> 0xFFFFFF) || (b
> 0x3FF) || (c
> 0x3FF) || (d
> 0x3FF) || (e
> 0x3FF) )
1642 throwf("malformed 64-bit a.b.c.d.e version number: %s", versionString
);
1644 return (a
<< 40) | ( b
<< 30 ) | ( c
<< 20 ) | ( d
<< 10 ) | e
;
1648 uint32_t Options::currentVersion32() const
1650 // warn if it does not fit into 32 bit vers number
1651 uint32_t a
= (fDylibCurrentVersion
>> 40) & 0xFFFF;
1652 uint32_t b
= (fDylibCurrentVersion
>> 30) & 0xFF;
1653 uint32_t c
= (fDylibCurrentVersion
>> 20) & 0xFF;
1654 uint64_t rep32
= ((uint64_t)a
<< 40) | ((uint64_t)b
<< 30) | ((uint64_t)c
<< 20);
1655 if ( rep32
!= fDylibCurrentVersion
) {
1656 warning("truncating -current_version to fit in 32-bit space used by old mach-o format");
1657 a
= (fDylibCurrentVersion
>> 40) & 0xFFFFFF;
1660 b
= (fDylibCurrentVersion
>> 30) & 0x3FF;
1663 c
= (fDylibCurrentVersion
>> 20) & 0x3FF;
1667 return (a
<< 16) | ( b
<< 8 ) | c
;
1671 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1673 uint32_t Options::parseVersionNumber32(const char* versionString
)
1679 x
= strtoul(versionString
, &end
, 10);
1680 if ( *end
== '.' ) {
1681 y
= strtoul(&end
[1], &end
, 10);
1682 if ( *end
== '.' ) {
1683 z
= strtoul(&end
[1], &end
, 10);
1686 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
1687 throwf("malformed 32-bit x.y.z version number: %s", versionString
);
1689 return (x
<< 16) | ( y
<< 8 ) | z
;
1692 static const char* cstringSymbolName(const char* orderFileString
)
1695 asprintf(&result
, "cstring=%s", orderFileString
);
1696 // convert escaped characters
1698 for(const char* s
=result
; *s
!= '\0'; ++s
, ++d
) {
1736 // hexadecimal value of char
1740 while ( isxdigit(*s
) ) {
1745 value
+= ((toupper(*s
)-'A') + 10);
1752 if ( isdigit(*s
) ) {
1753 // octal value of char
1755 while ( isdigit(*s
) ) {
1756 value
= (value
<< 3) + (*s
-'0');
1771 void Options::parseOrderFile(const char* path
, bool cstring
)
1773 // order files override auto-ordering
1774 fAutoOrderInitializers
= false;
1776 // <rdar://problem/24856050> ld64 should prefer OrderFiles from the SDK over the ones in /
1777 for (const char* sdkPath
: fSDKPaths
) {
1778 char fullPath
[PATH_MAX
];
1779 strlcpy(fullPath
, sdkPath
, PATH_MAX
);
1780 strlcat(fullPath
, "/", PATH_MAX
);
1781 strlcat(fullPath
, path
, PATH_MAX
);
1782 struct stat statBuffer
;
1783 if ( stat(fullPath
, &statBuffer
) == 0 ) {
1784 path
= strdup(fullPath
);
1789 // read in whole file
1790 int fd
= ::open(path
, O_RDONLY
, 0);
1792 throwf("can't open order file: %s", path
);
1793 struct stat stat_buf
;
1794 ::fstat(fd
, &stat_buf
);
1795 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1797 throwf("can't process order file: %s", path
);
1798 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1799 throwf("can't read order file: %s", path
);
1801 p
[stat_buf
.st_size
] = '\n';
1802 this->addDependency(Options::depMisc
, path
);
1804 // parse into vector of pairs
1805 char * const end
= &p
[stat_buf
.st_size
+1];
1806 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1807 char* symbolStart
= NULL
;
1808 for (char* s
= p
; s
< end
; ++s
) {
1814 else if ( !isspace(*s
) || cstring
) {
1820 if ( (*s
== '\n') || (!cstring
&& (*s
== '#')) ) {
1821 bool wasComment
= (*s
== '#');
1823 // removing any trailing spaces
1825 while ( isspace(*last
) ) {
1829 // if there is an architecture prefix, only use this symbol it if matches current arch
1830 if ( strncmp(symbolStart
, "ppc:", 4) == 0 ) {
1833 else if ( strncmp(symbolStart
, "ppc64:", 6) == 0 ) {
1836 else if ( strncmp(symbolStart
, "i386:", 5) == 0 ) {
1837 if ( fArchitecture
== CPU_TYPE_I386
)
1838 symbolStart
= &symbolStart
[5];
1842 else if ( strncmp(symbolStart
, "x86_64:", 7) == 0 ) {
1843 if ( fArchitecture
== CPU_TYPE_X86_64
)
1844 symbolStart
= &symbolStart
[7];
1848 else if ( strncmp(symbolStart
, "arm:", 4) == 0 ) {
1849 if ( fArchitecture
== CPU_TYPE_ARM
)
1850 symbolStart
= &symbolStart
[4];
1854 else if ( strncmp(symbolStart
, "arm64:", 6) == 0 ) {
1855 if ( fArchitecture
== CPU_TYPE_ARM64
)
1856 symbolStart
= &symbolStart
[6];
1860 if ( symbolStart
!= NULL
) {
1861 char* objFileName
= NULL
;
1862 char* colon
= strstr(symbolStart
, ".o:");
1863 if ( colon
!= NULL
) {
1865 objFileName
= symbolStart
;
1866 symbolStart
= &colon
[3];
1869 colon
= strstr(symbolStart
, ".o):");
1870 if ( colon
!= NULL
) {
1872 objFileName
= symbolStart
;
1873 symbolStart
= &colon
[4];
1876 // trim leading spaces
1877 while ( isspace(*symbolStart
) )
1879 Options::OrderedSymbol pair
;
1881 pair
.symbolName
= cstringSymbolName(symbolStart
);
1883 pair
.symbolName
= symbolStart
;
1884 pair
.objectFileName
= objFileName
;
1885 fOrderedSymbols
.push_back(pair
);
1900 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1903 void Options::parseSectionOrderFile(const char* segment
, const char* section
, const char* path
)
1905 if ( (strcmp(section
, "__cstring") == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1906 parseOrderFile(path
, true);
1908 else if ( (strncmp(section
, "__literal",9) == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1909 warning("sorting of __literal[4,8,16] sections not supported");
1912 // ignore section information and append all symbol names to global order file
1913 parseOrderFile(path
, false);
1917 void Options::addSection(const char* segment
, const char* section
, const char* path
)
1919 if ( strlen(segment
) > 16 )
1920 throw "-seccreate segment name max 16 chars";
1921 if ( strlen(section
) > 16 ) {
1922 char* tmp
= strdup(section
);
1924 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section
, tmp
);
1928 // read in whole file
1929 int fd
= ::open(path
, O_RDONLY
, 0);
1931 throwf("can't open -sectcreate file: %s", path
);
1932 struct stat stat_buf
;
1933 ::fstat(fd
, &stat_buf
);
1934 char* p
= (char*)malloc(stat_buf
.st_size
);
1936 throwf("can't process -sectcreate file: %s", path
);
1937 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1938 throwf("can't read -sectcreate file: %s", path
);
1941 // record section to create
1942 ExtraSection info
= { segment
, section
, path
, (uint8_t*)p
, (uint64_t)stat_buf
.st_size
};
1943 fExtraSections
.push_back(info
);
1946 void Options::addSectionRename(const char* srcSegment
, const char* srcSection
, const char* dstSegment
, const char* dstSection
)
1948 if ( strlen(srcSegment
) > 16 )
1949 throw "-rename_section segment name max 16 chars";
1950 if ( strlen(srcSection
) > 16 )
1951 throw "-rename_section section name max 16 chars";
1952 if ( strlen(dstSegment
) > 16 )
1953 throw "-rename_section segment name max 16 chars";
1954 if ( strlen(dstSection
) > 16 )
1955 throw "-rename_section section name max 16 chars";
1958 info
.fromSegment
= srcSegment
;
1959 info
.fromSection
= srcSection
;
1960 info
.toSegment
= dstSegment
;
1961 info
.toSection
= dstSection
;
1963 fSectionRenames
.push_back(info
);
1967 void Options::addSegmentRename(const char* srcSegment
, const char* dstSegment
)
1969 if ( strlen(srcSegment
) > 16 )
1970 throw "-rename_segment segment name max 16 chars";
1971 if ( strlen(dstSegment
) > 16 )
1972 throw "-rename_segment segment name max 16 chars";
1975 info
.fromSegment
= srcSegment
;
1976 info
.toSegment
= dstSegment
;
1978 fSegmentRenames
.push_back(info
);
1983 void Options::addSymbolMove(const char* dstSegment
, const char* symbolList
,
1984 std::vector
<SymbolsMove
>& list
, const char* optionName
)
1986 if ( strlen(dstSegment
) > 16 )
1987 throwf("%s segment name max 16 chars", optionName
);
1990 list
.push_back(tmp
);
1991 SymbolsMove
& info
= list
.back();
1992 info
.toSegment
= dstSegment
;
1993 loadExportFile(symbolList
, optionName
, info
.symbols
);
1996 bool Options::moveRwSymbol(const char* symName
, const char* filePath
, const char*& seg
, bool& wildCardMatch
) const
1998 for (std::vector
<SymbolsMove
>::const_iterator it
=fSymbolsMovesData
.begin(); it
!= fSymbolsMovesData
.end(); ++it
) {
1999 const SymbolsMove
& info
= *it
;
2000 if ( info
.symbols
.containsWithPrefix(symName
, filePath
, wildCardMatch
)) {
2001 seg
= info
.toSegment
;
2008 bool Options::moveAXMethodList(const char* className
) const
2010 for (const SymbolsMove
& sm
: fSymbolsMovesAXMethodLists
) {
2012 if ( sm
.symbols
.containsWithPrefix(className
, NULL
, wildcard
) )
2018 bool Options::moveRoSymbol(const char* symName
, const char* filePath
, const char*& seg
, bool& wildCardMatch
) const
2020 for (std::vector
<SymbolsMove
>::const_iterator it
=fSymbolsMovesCode
.begin(); it
!= fSymbolsMovesCode
.end(); ++it
) {
2021 const SymbolsMove
& info
= *it
;
2022 if ( info
.symbols
.containsWithPrefix(symName
, filePath
, wildCardMatch
)) {
2023 seg
= info
.toSegment
;
2030 void Options::addSectionAlignment(const char* segment
, const char* section
, const char* alignmentStr
)
2032 if ( strlen(segment
) > 16 )
2033 throw "-sectalign segment name max 16 chars";
2034 if ( strlen(section
) > 16 )
2035 throw "-sectalign section name max 16 chars";
2037 // argument to -sectalign is a hexadecimal number
2039 unsigned long value
= strtoul(alignmentStr
, &endptr
, 16);
2040 if ( *endptr
!= '\0')
2041 throw "argument for -sectalign is not a hexadecimal number";
2042 if ( value
> 0x8000 )
2043 throw "argument for -sectalign must be less than or equal to 0x8000";
2045 warning("zero is not a valid -sectalign");
2049 // alignment is power of 2 (e.g. page alignment = 12)
2050 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
2051 if ( (unsigned long)(1 << alignment
) != value
) {
2052 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
2053 segment
, section
, 1 << alignment
);
2056 SectionAlignment info
= { segment
, section
, alignment
};
2057 fSectionAlignments
.push_back(info
);
2060 void Options::addLibrary(const FileInfo
& info
)
2062 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
2063 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
2064 if ( strcmp(info
.path
, fit
->path
) == 0 ) {
2065 // if dylib is specified again but weak, record that it should be weak
2066 if ( info
.options
.fWeakImport
)
2067 fit
->options
.fWeakImport
= true;
2072 fInputFiles
.push_back(info
);
2075 void Options::warnObsolete(const char* arg
)
2077 warning("option %s is obsolete and being ignored", arg
);
2081 void Options::cannotBeUsedWithBitcode(const char* arg
)
2083 if ( fBundleBitcode
)
2084 throwf("%s and -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES) cannot be used together", arg
);
2087 std::string
Options::getVersionString32(uint32_t ver
) const
2089 if (ver
== 0 || ver
>= 0x10000000)
2092 unsigned microVersion
= ver
& 0xFF;
2093 unsigned minorVersion
= (ver
>> 8) & 0xFF;
2094 unsigned majorVersion
= (ver
>> 16) & 0xFF;
2095 std::stringstream versionString
;
2096 versionString
<< majorVersion
<< "." << minorVersion
<< "." << microVersion
;
2097 return versionString
.str();
2100 std::string
Options::getVersionString64(uint64_t ver
) const
2102 uint64_t a
= (ver
>> 40) & 0xFFFFFF;
2103 uint64_t b
= (ver
>> 30) & 0x3FF;
2104 uint64_t c
= (ver
>> 20) & 0x3FF;
2105 uint64_t d
= (ver
>> 10) & 0x3FF;
2106 uint64_t e
= ver
& 0x3FF;
2107 std::stringstream versionString
;
2108 versionString
<< a
<< "." << b
<< "." << c
<< "." << d
<< "." << e
;
2109 return versionString
.str();
2112 // Convert X.Y[.Z] to 32-bit value xxxxyyzz
2113 bool Options::parsePackedVersion32(const std::string
& versionStr
, uint32_t &result
)
2117 if ( versionStr
.empty() )
2120 size_t pos
= versionStr
.find('.');
2121 if ( pos
== std::string::npos
)
2124 std::string majorStr
= versionStr
.substr(0, pos
);
2125 std::string rest
= versionStr
.substr(pos
+1);
2129 int majorValue
= std::stoi(majorStr
, &majorEnd
);
2130 if ( majorEnd
!= majorStr
.size() )
2132 if ( majorValue
< 0 )
2134 if ( majorValue
> 65535 )
2137 std::string minorStr
;
2138 std::string microStr
;
2139 pos
= rest
.find('.');
2140 if ( pos
== std::string::npos
) {
2144 minorStr
= rest
.substr(0, pos
);
2145 microStr
= rest
.substr(pos
+1);
2149 int minorValue
= std::stoi(minorStr
, &minorEnd
);
2150 if ( minorEnd
!= minorStr
.size() )
2152 if ( minorValue
< 0 )
2154 if ( minorValue
> 255 )
2158 if ( !microStr
.empty() ) {
2160 microValue
= std::stoi(microStr
, µEnd
);
2161 if ( microEnd
!= microStr
.size() )
2163 if ( microValue
< 0 )
2165 if ( microValue
> 255 )
2169 result
= (uint32_t)((majorValue
<< 16) | (minorValue
<< 8) | microValue
);
2174 // std::stoi() throws exception on malformed input
2179 std::string
Options::getSDKVersionStr() const
2181 return getVersionString32(fSDKVersion
);
2184 std::vector
<std::string
> Options::writeBitcodeLinkOptions() const
2186 __block
std::vector
<std::string
> linkCommand
;
2187 switch ( fOutputKind
) {
2188 case Options::kDynamicLibrary
:
2189 linkCommand
.push_back("-dylib");
2190 linkCommand
.push_back("-compatibility_version");
2191 if ( fDylibCompatVersion
!= 0 ) {
2192 linkCommand
.push_back(getVersionString32(fDylibCompatVersion
));
2194 linkCommand
.push_back(getVersionString32(currentVersion32()));
2196 if ( fDylibCurrentVersion
!= 0 ) {
2197 linkCommand
.push_back("-current_version");
2198 linkCommand
.push_back(getVersionString64(fDylibCurrentVersion
));
2200 linkCommand
.push_back("-install_name");
2201 linkCommand
.push_back(installPath());
2203 case Options::kDynamicExecutable
:
2204 linkCommand
.push_back("-execute");
2206 case Options::kObjectFile
:
2207 linkCommand
.push_back("-r");
2210 throwf("could not write bitcode options file output kind\n");
2213 if (!fImplicitlyLinkPublicDylibs
)
2214 linkCommand
.push_back("-no_implicit_dylibs");
2216 // Add deployment target.
2217 // Platform is allowed to be unknown for "ld -r".
2219 platforms().forEach(^(ld::Platform platform
, uint32_t version
, bool &stop
) {
2221 case ld::kPlatform_macOS
:
2222 linkCommand
.push_back("-macosx_version_min");
2223 linkCommand
.push_back(getVersionString32(version
));
2225 case ld::kPlatform_iOS
:
2226 linkCommand
.push_back("-ios_version_min");
2227 linkCommand
.push_back(getVersionString32(version
));
2229 case ld::kPlatform_iOSSimulator
:
2230 linkCommand
.push_back("-ios_simulator_version_min");
2231 linkCommand
.push_back(getVersionString32(version
));
2233 case ld::kPlatform_watchOS
:
2234 linkCommand
.push_back("-watchos_version_min");
2235 linkCommand
.push_back(getVersionString32(version
));
2237 case ld::kPlatform_watchOSSimulator
:
2238 linkCommand
.push_back("-watchos_simulator_version_min");
2239 linkCommand
.push_back(getVersionString32(version
));
2241 case ld::kPlatform_tvOS
:
2242 linkCommand
.push_back("-tvos_version_min");
2243 linkCommand
.push_back(getVersionString32(version
));
2245 case ld::kPlatform_tvOSSimulator
:
2246 linkCommand
.push_back("-tvos_simulator_version_min");
2247 linkCommand
.push_back(getVersionString32(version
));
2249 case ld::kPlatform_bridgeOS
:
2250 linkCommand
.push_back("-bridgeos_version_min");
2251 linkCommand
.push_back(getVersionString32(version
));
2253 case ld::kPlatform_iOSMac
:
2254 linkCommand
.push_back("-iosmac_version_min");
2255 linkCommand
.push_back(getVersionString32(version
));
2257 case ld::kPlatform_unknown
:
2258 if ( fOutputKind
!= Options::kObjectFile
) {
2259 throwf("platform is unknown for final bitcode bundle,"
2260 "deployment target and min version is required for -bitcode_bundle");
2269 linkCommand
.push_back("-e");
2270 linkCommand
.push_back(fEntryName
);
2274 if (!fRPaths
.empty()) {
2275 for (std::vector
<const char*>::const_iterator it
=fRPaths
.begin(); it
!= fRPaths
.end(); ++it
) {
2276 linkCommand
.push_back("-rpath");
2277 linkCommand
.push_back(*it
);
2281 // Other bitcode compatiable options
2282 if ( fObjCABIVersion1Override
) {
2283 linkCommand
.push_back("-objc_abi_version");
2284 linkCommand
.push_back("1");
2285 } else if ( fObjCABIVersion2Override
) {
2286 linkCommand
.push_back("-objc_abi_version");
2287 linkCommand
.push_back("2");
2289 if ( fExecutablePath
) {
2290 linkCommand
.push_back("-executable_path");
2291 linkCommand
.push_back(fExecutablePath
);
2294 linkCommand
.push_back("-dead_strip");
2295 if ( fExportDynamic
)
2296 linkCommand
.push_back("-export_dynamic");
2297 if ( fMarkAppExtensionSafe
&& fCheckAppExtensionSafe
)
2298 linkCommand
.push_back("-application_extension");
2300 if ( fSourceVersionLoadCommandForceOn
)
2301 linkCommand
.push_back("-add_source_version");
2302 if ( fSourceVersion
!= 0 ) {
2303 linkCommand
.push_back("-source_version");
2304 linkCommand
.push_back(getVersionString64(fSourceVersion
));
2307 // linker flag added by swift driver
2308 // rdar://problem/20108072
2309 if ( !fObjcCategoryMerging
)
2310 linkCommand
.push_back("-no_objc_category_merging");
2315 const char* Options::checkForNullArgument(const char* argument_name
, const char* arg
) const
2318 throwf("missing argument for %s", argument_name
);
2322 const char* Options::checkForNullVersionArgument(const char* argument_name
, const char* arg
) const
2325 throwf("%s missing version argument", argument_name
);
2330 // Process all command line arguments.
2332 // The only error checking done here is that each option is valid and if it has arguments
2333 // that they too are valid.
2335 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
2336 // whichever was last on the command line is used.
2338 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
2340 void Options::parse(int argc
, const char* argv
[])
2342 // Store the original args in the link snapshot.
2343 fLinkSnapshot
.recordRawArgs(argc
, argv
);
2345 // pass one builds search list from -L and -F options
2346 this->buildSearchPaths(argc
, argv
);
2348 // reduce re-allocations
2349 fInputFiles
.reserve(32);
2351 // pass two parse all other options
2352 for(int i
=1; i
< argc
; ++i
) {
2353 const char* arg
= argv
[i
];
2355 if ( arg
[0] == '-' ) {
2356 // by default, copy one arg to the snapshot link command, and do no file copying
2357 int snapshotArgIndex
= i
;
2358 int snapshotArgCount
= -1; // -1 means compute count based on change in index
2359 int snapshotFileArgIndex
= -1; // -1 means no data file parameter to arg
2361 // Since we don't care about the files passed, just the option names, we do this here.
2363 fprintf (stderr
, "[Logging ld64 options]\t%s\n", arg
);
2365 if ( (arg
[1] == 'L') || (arg
[1] == 'F') ) {
2366 snapshotArgCount
= 0; // stripped out of link snapshot
2369 // previously handled by buildSearchPaths()
2371 // The one gnu style option we have to keep compatibility
2372 // with gcc. Might as well have the single hyphen one as well.
2373 else if ( (strcmp(arg
, "--help") == 0)
2374 || (strcmp(arg
, "-help") == 0)) {
2375 fprintf (stdout
, "ld64: For information on command line options please use 'man ld'.\n");
2378 else if ( strcmp(arg
, "-arch") == 0 ) {
2379 const char* arch
= argv
[++i
];
2381 fLinkSnapshot
.recordArch(arch
);
2383 else if ( strcmp(arg
, "-dynamic") == 0 ) {
2386 else if ( strcmp(arg
, "-static") == 0 ) {
2388 if ( (fOutputKind
!= kObjectFile
) && (fOutputKind
!= kKextBundle
) ) {
2389 fOutputKind
= kStaticExecutable
;
2391 cannotBeUsedWithBitcode(arg
);
2393 else if ( strcmp(arg
, "-dylib") == 0 ) {
2394 fOutputKind
= kDynamicLibrary
;
2396 else if ( strcmp(arg
, "-bundle") == 0 ) {
2397 fOutputKind
= kDynamicBundle
;
2398 cannotBeUsedWithBitcode(arg
);
2400 else if ( strcmp(arg
, "-dylinker") == 0 ) {
2401 fOutputKind
= kDyld
;
2402 cannotBeUsedWithBitcode(arg
);
2404 else if ( strcmp(arg
, "-execute") == 0 ) {
2405 if ( fOutputKind
!= kStaticExecutable
)
2406 fOutputKind
= kDynamicExecutable
;
2408 else if ( strcmp(arg
, "-preload") == 0 ) {
2409 fOutputKind
= kPreload
;
2410 cannotBeUsedWithBitcode(arg
);
2412 else if ( strcmp(arg
, "-r") == 0 ) {
2413 fOutputKind
= kObjectFile
;
2415 else if ( strcmp(arg
, "-kext") == 0 ) {
2416 fOutputKind
= kKextBundle
;
2417 cannotBeUsedWithBitcode(arg
);
2419 else if ( strcmp(arg
, "-kext_objects_dir") == 0 ) {
2420 fKextObjectsDirPath
= argv
[++i
];
2421 if ( fKextObjectsDirPath
== NULL
)
2422 throw "missing argument to -kext_objects_dir";
2423 fKextObjectsEnable
= 1;
2425 else if ( strcmp(arg
, "-no_kext_objects") == 0 ) {
2426 fKextObjectsEnable
= 0;
2428 else if ( strcmp(arg
, "-o") == 0 ) {
2429 snapshotArgCount
= 0;
2430 fOutputFile
= checkForNullArgument(arg
, argv
[++i
]);
2431 fLinkSnapshot
.setOutputPath(fOutputFile
);
2433 else if ( strncmp(arg
, "-lazy-l", 7) == 0 ) {
2434 snapshotArgCount
= 0;
2435 FileInfo info
= findLibrary(&arg
[7], true);
2436 info
.options
.fLazyLoad
= true;
2437 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2439 fUsingLazyDylibLinking
= true;
2440 cannotBeUsedWithBitcode(arg
);
2442 else if ( strcmp(arg
, "-lto_library") == 0 ) {
2443 snapshotFileArgIndex
= 1;
2444 fOverridePathlibLTO
= argv
[++i
];
2445 if ( fOverridePathlibLTO
== NULL
)
2446 throw "missing argument to -lto_library";
2448 else if ( strcmp(arg
, "-cache_path_lto") == 0 ) {
2449 fLtoCachePath
= argv
[++i
];
2450 if ( fLtoCachePath
== NULL
)
2451 throw "missing argument to -cache_path_lto";
2453 else if ( strcmp(arg
, "-prune_interval_lto") == 0 ) {
2454 const char* value
= argv
[++i
];
2455 if ( value
== NULL
)
2456 throw "missing argument to -prune_interval_lto";
2458 fLtoPruneIntervalOverwrite
= true;
2459 fLtoPruneInterval
= strtoul(value
, &endptr
, 10);
2460 if ( *endptr
!= '\0')
2461 throw "invalid argument for -prune_interval_lto";
2463 else if ( strcmp(arg
, "-prune_after_lto") == 0 ) {
2464 const char* value
= argv
[++i
];
2465 if ( value
== NULL
)
2466 throw "missing argument to -prune_after_lto";
2468 fLtoPruneAfter
= strtoul(value
, &endptr
, 10);
2469 if ( *endptr
!= '\0')
2470 throw "invalid argument for -prune_after_lto";
2472 else if ( strcmp(arg
, "-max_relative_cache_size_lto") == 0 ) {
2473 const char* value
= argv
[++i
];
2474 if ( value
== NULL
)
2475 throw "missing argument to -max_relative_cache_size_lto";
2477 fLtoMaxCacheSize
= strtoul(value
, &endptr
, 10);
2478 if ( *endptr
!= '\0')
2479 throw "invalid argument for -max_relative_cache_size_lto";
2480 if (fLtoMaxCacheSize
> 100)
2481 throw "Expect a value between 0 and 100 for -max_relative_cache_size_lto";
2483 else if ( (arg
[1] == 'l') && (strncmp(arg
,"-lazy_",6) !=0) ) {
2484 snapshotArgCount
= 0;
2485 FileInfo info
= findLibrary(&arg
[2]);
2486 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2489 // This causes a dylib to be weakly bound at
2490 // link time. This corresponds to weak_import.
2491 else if ( strncmp(arg
, "-weak-l", 7) == 0 ) {
2492 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2493 snapshotArgCount
= 0;
2494 FileInfo info
= findLibrary(&arg
[7]);
2495 info
.options
.fWeakImport
= true;
2496 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2499 // Avoid lazy binding.
2500 else if ( strcmp(arg
, "-bind_at_load") == 0 ) {
2502 cannotBeUsedWithBitcode(arg
);
2504 else if ( strcmp(arg
, "-twolevel_namespace") == 0 ) {
2505 fNameSpace
= kTwoLevelNameSpace
;
2507 else if ( strcmp(arg
, "-flat_namespace") == 0 ) {
2508 fNameSpace
= kFlatNameSpace
;
2509 cannotBeUsedWithBitcode(arg
);
2511 // Also sets a bit to ensure dyld causes everything
2512 // in the namespace to be flat.
2514 else if ( strcmp(arg
, "-force_flat_namespace") == 0 ) {
2515 fNameSpace
= kForceFlatNameSpace
;
2516 cannotBeUsedWithBitcode(arg
);
2518 // Similar to --whole-archive.
2519 else if ( strcmp(arg
, "-all_load") == 0 ) {
2520 fFullyLoadArchives
= true;
2522 else if ( strcmp(arg
, "-noall_load") == 0) {
2525 // Similar to -all_load
2526 else if ( strcmp(arg
, "-ObjC") == 0 ) {
2527 fLoadAllObjcObjectsFromArchives
= true;
2529 // Similar to -all_load, but for the following archive only.
2530 else if ( strcmp(arg
, "-force_load") == 0 ) {
2531 const char* path
= checkForNullArgument(arg
, argv
[++i
]);
2532 FileInfo info
= findFile(path
);
2533 info
.options
.fForceLoad
= true;
2534 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2537 // Library versioning.
2538 else if ( (strcmp(arg
, "-dylib_compatibility_version") == 0)
2539 || (strcmp(arg
, "-compatibility_version") == 0)) {
2540 const char* vers
= argv
[++i
];
2542 throw "-dylib_compatibility_version missing <version>";
2543 fDylibCompatVersion
= parseVersionNumber32(vers
);
2545 else if ( (strcmp(arg
, "-dylib_current_version") == 0)
2546 || (strcmp(arg
, "-current_version") == 0)) {
2547 const char* vers
= argv
[++i
];
2549 throw "-dylib_current_version missing <version>";
2550 fDylibCurrentVersion
= parseVersionNumber64(vers
);
2552 else if ( strcmp(arg
, "-sectorder") == 0 ) {
2553 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2554 throw "-sectorder missing <segment> <section> <file-path>";
2555 snapshotFileArgIndex
= 3;
2556 parseSectionOrderFile(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2558 cannotBeUsedWithBitcode(arg
);
2560 else if ( strcmp(arg
, "-order_file") == 0 ) {
2561 snapshotFileArgIndex
= 1;
2562 parseOrderFile(argv
[++i
], false);
2564 else if ( strcmp(arg
, "-order_file_statistics") == 0 ) {
2565 fPrintOrderFileStatistics
= true;
2566 cannotBeUsedWithBitcode(arg
);
2568 // ??? Deprecate segcreate.
2569 // -sectcreate puts whole files into a section in the output.
2570 else if ( (strcmp(arg
, "-sectcreate") == 0) || (strcmp(arg
, "-segcreate") == 0) ) {
2571 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2572 throw "-sectcreate missing <segment> <section> <file-path>";
2573 snapshotFileArgIndex
= 3;
2574 addSection(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2577 // Since we have a full path in binary/library names we need to be able to override it.
2578 else if ( (strcmp(arg
, "-dylib_install_name") == 0)
2579 || (strcmp(arg
, "-dylinker_install_name") == 0)
2580 || (strcmp(arg
, "-install_name") == 0)) {
2581 fDylibInstallName
= argv
[++i
];
2582 if ( fDylibInstallName
== NULL
)
2583 throw "-install_name missing <path>";
2585 // Sets the base address of the output.
2586 else if ( (strcmp(arg
, "-seg1addr") == 0) || (strcmp(arg
, "-image_base") == 0) ) {
2587 const char* address
= argv
[++i
];
2588 if ( address
== NULL
)
2589 throwf("%s missing <address>", arg
);
2590 fBaseAddress
= parseAddress(address
);
2591 uint64_t temp
= ((fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
2592 if ( fBaseAddress
!= temp
) {
2593 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment
);
2594 fBaseAddress
= temp
;
2596 cannotBeUsedWithBitcode(arg
);
2598 else if ( strcmp(arg
, "-e") == 0 ) {
2599 fEntryName
= argv
[++i
];
2601 // Same as -@ from the FSF linker.
2602 else if ( strcmp(arg
, "-filelist") == 0 ) {
2603 snapshotArgCount
= 0;
2604 const char* path
= argv
[++i
];
2605 if ( (path
== NULL
) || (path
[0] == '-') )
2606 throw "-filelist missing <path>";
2607 ld::File::Ordinal baseOrdinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2608 loadFileList(path
, baseOrdinal
);
2610 else if ( strcmp(arg
, "-keep_private_externs") == 0 ) {
2611 cannotBeUsedWithBitcode(arg
);
2612 fKeepPrivateExterns
= true;
2614 else if ( strcmp(arg
, "-final_output") == 0 ) {
2615 fFinalName
= argv
[++i
];
2617 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
2618 // just ensures that this happens for cross object file boundaries.
2619 else if ( (strcmp(arg
, "-interposable") == 0) || (strcmp(arg
, "-multi_module") == 0)) {
2620 switch ( fInterposeMode
) {
2621 case kInterposeNone
:
2622 case kInterposeAllExternal
:
2623 fInterposeMode
= kInterposeAllExternal
;
2625 case kInterposeSome
:
2626 // do nothing, -interposable_list overrides -interposable"
2629 cannotBeUsedWithBitcode(arg
);
2631 else if ( strcmp(arg
, "-interposable_list") == 0 ) {
2632 snapshotFileArgIndex
= 1;
2633 fInterposeMode
= kInterposeSome
;
2634 loadExportFile(argv
[++i
], "-interposable_list", fInterposeList
);
2635 cannotBeUsedWithBitcode(arg
);
2637 // Default for -interposable/-multi_module/-single_module.
2638 else if ( strcmp(arg
, "-single_module") == 0 ) {
2639 fInterposeMode
= kInterposeNone
;
2641 else if ( strcmp(arg
, "-exported_symbols_list") == 0 ) {
2642 snapshotFileArgIndex
= 1;
2643 if ( fExportMode
== kDontExportSome
)
2644 throw "can't use -exported_symbols_list and -unexported_symbols_list";
2645 fExportMode
= kExportSome
;
2646 loadExportFile(argv
[++i
], "-exported_symbols_list", fExportSymbols
);
2648 else if ( strcmp(arg
, "-unexported_symbols_list") == 0 ) {
2649 snapshotFileArgIndex
= 1;
2650 if ( fExportMode
== kExportSome
)
2651 throw "can't use -unexported_symbols_list and -exported_symbols_list";
2652 fExportMode
= kDontExportSome
;
2653 loadExportFile(argv
[++i
], "-unexported_symbols_list", fDontExportSymbols
);
2655 else if ( strcmp(arg
, "-exported_symbol") == 0 ) {
2656 if ( fExportMode
== kDontExportSome
)
2657 throw "can't use -exported_symbol and -unexported_symbols";
2658 fExportMode
= kExportSome
;
2659 const char* symbol
= checkForNullArgument(arg
, argv
[++i
]);
2660 fExportSymbols
.insert(symbol
);
2662 else if ( strcmp(arg
, "-unexported_symbol") == 0 ) {
2663 if ( fExportMode
== kExportSome
)
2664 throw "can't use -unexported_symbol and -exported_symbol";
2665 fExportMode
= kDontExportSome
;
2666 const char* symbol
= checkForNullArgument(arg
, argv
[++i
]);
2667 fDontExportSymbols
.insert(symbol
);
2669 else if ( strcmp(arg
, "-non_global_symbols_no_strip_list") == 0 ) {
2670 snapshotFileArgIndex
= 1;
2671 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveExclude
)
2672 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2673 fLocalSymbolHandling
= kLocalSymbolsSelectiveInclude
;
2674 loadExportFile(argv
[++i
], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded
);
2675 cannotBeUsedWithBitcode(arg
);
2677 else if ( strcmp(arg
, "-non_global_symbols_strip_list") == 0 ) {
2678 snapshotFileArgIndex
= 1;
2679 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveInclude
)
2680 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2681 fLocalSymbolHandling
= kLocalSymbolsSelectiveExclude
;
2682 loadExportFile(argv
[++i
], "-non_global_symbols_strip_list", fLocalSymbolsExcluded
);
2683 cannotBeUsedWithBitcode(arg
);
2686 else if ( strcmp(arg
, "-no_arch_warnings") == 0 ) {
2687 fIgnoreOtherArchFiles
= true;
2689 else if ( strcmp(arg
, "-force_cpusubtype_ALL") == 0 ) {
2690 fForceSubtypeAll
= true;
2691 fAllowCpuSubtypeMismatches
= true;
2692 cannotBeUsedWithBitcode(arg
);
2694 // Similar to -weak-l but uses the absolute path name to the library.
2695 else if ( strcmp(arg
, "-weak_library") == 0 ) {
2696 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2697 snapshotArgCount
= 0;
2698 const char* path
= checkForNullArgument(arg
, argv
[++i
]);
2699 FileInfo info
= findFile(path
);
2700 info
.options
.fWeakImport
= true;
2701 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2703 cannotBeUsedWithBitcode(arg
);
2705 else if ( strcmp(arg
, "-lazy_library") == 0 ) {
2706 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2707 snapshotArgCount
= 0;
2708 const char* path
= checkForNullArgument(arg
, argv
[++i
]);
2709 FileInfo info
= findFile(path
);
2710 info
.options
.fLazyLoad
= true;
2711 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2713 fUsingLazyDylibLinking
= true;
2714 cannotBeUsedWithBitcode(arg
);
2716 else if ( strcmp(arg
, "-framework") == 0 ) {
2717 snapshotArgCount
= 0;
2718 FileInfo info
= findFramework(argv
[++i
]);
2719 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2722 else if ( strcmp(arg
, "-weak_framework") == 0 ) {
2723 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2724 snapshotArgCount
= 0;
2725 FileInfo info
= findFramework(argv
[++i
]);
2726 info
.options
.fWeakImport
= true;
2727 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2730 else if ( strcmp(arg
, "-lazy_framework") == 0 ) {
2731 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2732 snapshotArgCount
= 0;
2733 FileInfo info
= findFramework(argv
[++i
]);
2734 info
.options
.fLazyLoad
= true;
2735 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2737 fUsingLazyDylibLinking
= true;
2738 cannotBeUsedWithBitcode(arg
);
2740 else if ( strcmp(arg
, "-search_paths_first") == 0 ) {
2741 // previously handled by buildSearchPaths()
2743 else if ( strcmp(arg
, "-search_dylibs_first") == 0 ) {
2744 // previously handled by buildSearchPaths()
2746 else if ( strcmp(arg
, "-undefined") == 0 ) {
2747 setUndefinedTreatment(argv
[++i
]);
2748 cannotBeUsedWithBitcode(arg
);
2750 // Debugging output flag.
2751 else if ( strcmp(arg
, "-arch_multiple") == 0 ) {
2752 fMessagesPrefixedWithArchitecture
= true;
2754 // Specify what to do with relocations in read only
2755 // sections like .text. Could be errors, warnings,
2756 // or suppressed. Currently we do nothing with the
2758 else if ( strcmp(arg
, "-read_only_relocs") == 0 ) {
2759 switch ( parseTreatment(argv
[++i
]) ) {
2762 throw "-read_only_relocs missing [ warning | error | suppress ]";
2764 fWarnTextRelocs
= true;
2765 fAllowTextRelocs
= true;
2766 cannotBeUsedWithBitcode(arg
);
2769 fWarnTextRelocs
= false;
2770 fAllowTextRelocs
= true;
2771 cannotBeUsedWithBitcode(arg
);
2774 fWarnTextRelocs
= false;
2775 fAllowTextRelocs
= false;
2779 else if ( strcmp(arg
, "-sect_diff_relocs") == 0 ) {
2783 // Warn, error or make strong a mismatch between weak
2784 // and non-weak references.
2785 else if ( strcmp(arg
, "-weak_reference_mismatches") == 0 ) {
2786 setWeakReferenceMismatchTreatment(argv
[++i
]);
2788 // For a deployment target of 10.3 and earlier ld64 will
2789 // prebind an executable with 0s in all addresses that
2790 // are prebound. This can then be fixed up by update_prebinding
2791 // later. Prebinding is less useful on 10.4 and greater.
2792 else if ( strcmp(arg
, "-prebind") == 0 ) {
2794 cannotBeUsedWithBitcode(arg
);
2796 else if ( strcmp(arg
, "-noprebind") == 0 ) {
2799 else if ( strcmp(arg
, "-prebind_allow_overlap") == 0 ) {
2802 else if ( strcmp(arg
, "-prebind_all_twolevel_modules") == 0 ) {
2805 else if ( strcmp(arg
, "-noprebind_all_twolevel_modules") == 0 ) {
2808 else if ( strcmp(arg
, "-nofixprebinding") == 0 ) {
2811 // This should probably be deprecated when we respect -L and -F
2812 // when searching for libraries.
2813 else if ( strcmp(arg
, "-dylib_file") == 0 ) {
2814 // ignore for snapshot because a stub dylib will be created in the snapshot
2815 snapshotArgCount
= 0;
2816 addDylibOverride(argv
[++i
]);
2817 cannotBeUsedWithBitcode(arg
);
2819 // What to expand @executable_path to if found in dependent dylibs
2820 else if ( strcmp(arg
, "-executable_path") == 0 ) {
2821 fExecutablePath
= argv
[++i
];
2822 if ( (fExecutablePath
== NULL
) || (fExecutablePath
[0] == '-') )
2823 throw "-executable_path missing <path>";
2824 // if a directory was passed, add / to end
2825 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2826 struct stat statBuffer
;
2827 if ( stat(fExecutablePath
, &statBuffer
) == 0 ) {
2828 if ( (statBuffer
.st_mode
& S_IFMT
) == S_IFDIR
) {
2829 char* pathWithSlash
= new char[strlen(fExecutablePath
)+2];
2830 strcpy(pathWithSlash
, fExecutablePath
);
2831 strcat(pathWithSlash
, "/");
2832 fExecutablePath
= pathWithSlash
;
2836 // Aligns all segments to the power of 2 boundary specified.
2837 else if ( strcmp(arg
, "-segalign") == 0 ) {
2838 const char* size
= argv
[++i
];
2840 throw "-segalign missing <size>";
2841 fSegmentAlignment
= parseAddress(size
);
2842 uint8_t alignment
= (uint8_t)__builtin_ctz(fSegmentAlignment
);
2843 uint32_t p2aligned
= (1 << alignment
);
2844 if ( p2aligned
!= fSegmentAlignment
) {
2845 warning("alignment for -segalign %s is not a power of two, using 0x%X", size
, p2aligned
);
2846 fSegmentAlignment
= p2aligned
;
2848 cannotBeUsedWithBitcode(arg
);
2850 // Puts a specified segment at a particular address that must
2851 // be a multiple of the segment alignment.
2852 else if ( strcmp(arg
, "-segaddr") == 0 ) {
2854 seg
.name
= argv
[++i
];
2855 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2856 throw "-segaddr missing segName Adddress";
2857 seg
.address
= parseAddress(argv
[++i
]);
2858 uint64_t temp
= ((seg
.address
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
2859 if ( seg
.address
!= temp
)
2860 warning("-segaddr %s not %lld byte aligned", seg
.name
, fSegmentAlignment
);
2861 fCustomSegmentAddresses
.push_back(seg
);
2862 cannotBeUsedWithBitcode(arg
);
2864 // ??? Deprecate when we deprecate split-seg.
2865 else if ( strcmp(arg
, "-segs_read_only_addr") == 0 ) {
2868 cannotBeUsedWithBitcode(arg
);
2870 // ??? Deprecate when we deprecate split-seg.
2871 else if ( strcmp(arg
, "-segs_read_write_addr") == 0 ) {
2874 cannotBeUsedWithBitcode(arg
);
2876 // ??? Deprecate when we get rid of basing at build time.
2877 else if ( strcmp(arg
, "-seg_addr_table") == 0 ) {
2879 snapshotFileArgIndex
= 1;
2880 const char* name
= argv
[++i
];
2882 throw "-seg_addr_table missing argument";
2883 cannotBeUsedWithBitcode(arg
);
2885 else if ( strcmp(arg
, "-seg_addr_table_filename") == 0 ) {
2889 else if ( strcmp(arg
, "-segprot") == 0 ) {
2891 seg
.name
= argv
[++i
];
2892 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) || (argv
[i
+2] == NULL
) )
2893 throw "-segprot missing segName max-prot init-prot";
2894 seg
.max
= parseProtection(argv
[++i
]);
2895 seg
.init
= parseProtection(argv
[++i
]);
2896 if ( strcmp(seg
.name
, "__LINKEDIT") == 0 )
2897 warning("-segprot cannot be used to modify __LINKEDIT protections");
2899 fCustomSegmentProtections
.push_back(seg
);
2900 cannotBeUsedWithBitcode(arg
);
2902 else if ( strcmp(arg
, "-pagezero_size") == 0 ) {
2903 const char* size
= argv
[++i
];
2905 throw "-pagezero_size missing <size>";
2906 fZeroPageSize
= parseAddress(size
);
2907 uint64_t temp
= fZeroPageSize
& (-4096); // page align
2908 if ( (fZeroPageSize
!= temp
) )
2909 warning("-pagezero_size not page aligned, rounding down");
2910 fZeroPageSize
= temp
;
2911 cannotBeUsedWithBitcode(arg
);
2913 else if ( strcmp(arg
, "-stack_addr") == 0 ) {
2914 const char* address
= argv
[++i
];
2915 if ( address
== NULL
)
2916 throw "-stack_addr missing <address>";
2917 fStackAddr
= parseAddress(address
);
2918 cannotBeUsedWithBitcode(arg
);
2920 else if ( strcmp(arg
, "-stack_size") == 0 ) {
2921 const char* size
= argv
[++i
];
2923 throw "-stack_size missing <address>";
2924 fStackSize
= parseAddress(size
);
2926 else if ( strcmp(arg
, "-allow_stack_execute") == 0 ) {
2927 fExecutableStack
= true;
2928 cannotBeUsedWithBitcode(arg
);
2930 else if ( strcmp(arg
, "-allow_heap_execute") == 0 ) {
2931 fDisableNonExecutableHeap
= true;
2932 cannotBeUsedWithBitcode(arg
);
2934 else if ( strcmp(arg
, "-sectalign") == 0 ) {
2935 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2936 throw "-sectalign missing <segment> <section> <file-path>";
2937 addSectionAlignment(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2939 cannotBeUsedWithBitcode(arg
);
2941 else if ( strcmp(arg
, "-sectorder_detail") == 0 ) {
2944 else if ( strcmp(arg
, "-sectobjectsymbols") == 0 ) {
2948 else if ( strcmp(arg
, "-bundle_loader") == 0 ) {
2949 snapshotFileArgIndex
= 1;
2950 fBundleLoader
= argv
[++i
];
2951 if ( (fBundleLoader
== NULL
) || (fBundleLoader
[0] == '-') )
2952 throw "-bundle_loader missing <path>";
2953 FileInfo info
= findFile(fBundleLoader
);
2954 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2955 info
.options
.fBundleLoader
= true;
2956 fInputFiles
.push_back(info
);
2958 else if ( strcmp(arg
, "-private_bundle") == 0 ) {
2961 else if ( strcmp(arg
, "-twolevel_namespace_hints") == 0 ) {
2964 // Use this flag to set default behavior for deployement targets.
2965 else if ( strcmp(arg
, "-macosx_version_min") == 0 ) {
2966 const char* macVers
= checkForNullVersionArgument(arg
, argv
[++i
]);
2967 const char* envMacVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
2968 const char* enviPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
2969 if ( (envMacVers
!= NULL
) && (enviPhoneVers
!= NULL
) ) {
2970 // <rdar://problem/13774329> when conflicting deployments set, break tie by looking at syslibroot
2971 warning("both MACOSX_DEPLOYMENT_TARGET and IPHONEOS_DEPLOYMENT_TARGET are set");
2972 if ( !fSDKPaths
.empty() ) {
2973 const char* sysrootPath
= fSDKPaths
.back();
2974 const char* lastSlash
= strrchr(sysrootPath
, '/');
2975 if ( strstr(lastSlash
, "Simulator") != NULL
)
2976 setVersionMin(ld::kPlatform_iOS
, enviPhoneVers
);
2978 setVersionMin(ld::kPlatform_macOS
, macVers
);
2981 setVersionMin(ld::kPlatform_macOS
, macVers
);
2985 setVersionMin(ld::kPlatform_macOS
, macVers
);
2988 else if ( (strcmp(arg
, "-ios_version_min") == 0) || (strcmp(arg
, "-iphoneos_version_min") == 0) ) {
2989 const char* vers
= checkForNullVersionArgument(arg
, argv
[++i
]);
2990 setVersionMin(ld::kPlatform_iOS
, vers
);
2992 else if ( strcmp(arg
, "-ios_simulator_version_min") == 0 ) {
2993 const char* vers
= checkForNullVersionArgument(arg
, argv
[++i
]);
2994 setVersionMin(ld::kPlatform_iOSSimulator
, vers
);
2996 else if ( strcmp(arg
, "-watchos_version_min") == 0 ) {
2997 const char* vers
= checkForNullVersionArgument(arg
, argv
[++i
]);
2998 setVersionMin(ld::kPlatform_watchOS
, vers
);
3000 else if ( strcmp(arg
, "-watchos_simulator_version_min") == 0 ) {
3001 const char* vers
= checkForNullVersionArgument(arg
, argv
[++i
]);
3002 setVersionMin(ld::kPlatform_watchOSSimulator
, vers
);
3004 else if ( strcmp(arg
, "-tvos_version_min") == 0 ) {
3005 const char* vers
= checkForNullVersionArgument(arg
, argv
[++i
]);
3006 setVersionMin(ld::kPlatform_tvOS
, vers
);
3008 else if ( strcmp(arg
, "-tvos_simulator_version_min") == 0 ) {
3009 const char* vers
= checkForNullVersionArgument(arg
, argv
[++i
]);
3010 setVersionMin(ld::kPlatform_tvOSSimulator
, vers
);
3012 else if ( strcmp(arg
, "-bridgeos_version_min") == 0 ) {
3013 const char* vers
= checkForNullVersionArgument(arg
, argv
[++i
]);
3014 setVersionMin(ld::kPlatform_bridgeOS
, vers
);
3016 else if ( strcmp(arg
, "-iosmac_version_min") == 0 ) {
3017 const char* vers
= checkForNullVersionArgument(arg
, argv
[++i
]);
3018 setVersionMin(ld::kPlatform_iOSMac
, vers
);
3020 else if ( strcmp(arg
, "-multiply_defined") == 0 ) {
3021 //warnObsolete(arg);
3024 else if ( strcmp(arg
, "-multiply_defined_unused") == 0 ) {
3028 else if ( strcmp(arg
, "-nomultidefs") == 0 ) {
3031 // Display each file in which the argument symbol appears and whether
3032 // the file defines or references it. This option takes an argument
3033 // as -y<symbol> note that there is no space.
3034 else if ( strncmp(arg
, "-y", 2) == 0 ) {
3037 // Same output as -y, but output <arg> number of undefined symbols only.
3038 else if ( strcmp(arg
, "-Y") == 0 ) {
3039 //warnObsolete(arg);
3042 // This option affects all objects linked into the final result.
3043 else if ( strcmp(arg
, "-m") == 0 ) {
3046 else if ( (strcmp(arg
, "-why_load") == 0) || (strcmp(arg
, "-whyload") == 0) ) {
3049 else if ( strcmp(arg
, "-why_live") == 0 ) {
3050 const char* name
= argv
[++i
];
3052 throw "-why_live missing symbol name argument";
3053 fWhyLive
.insert(name
);
3055 else if ( strcmp(arg
, "-u") == 0 ) {
3056 const char* name
= argv
[++i
];
3058 throw "-u missing argument";
3059 fInitialUndefines
.push_back(name
);
3060 cannotBeUsedWithBitcode(arg
);
3062 else if ( strcmp(arg
, "-U") == 0 ) {
3063 const char* name
= argv
[++i
];
3065 throw "-U missing argument";
3066 fAllowedUndefined
.insert(name
);
3067 cannotBeUsedWithBitcode(arg
);
3069 else if ( strcmp(arg
, "-s") == 0 ) {
3071 fLocalSymbolHandling
= kLocalSymbolsNone
;
3072 fDebugInfoStripping
= Options::kDebugInfoNone
;
3074 else if ( strcmp(arg
, "-x") == 0 ) {
3075 fLocalSymbolHandling
= kLocalSymbolsNone
;
3077 else if ( strcmp(arg
, "-S") == 0 ) {
3078 fDebugInfoStripping
= Options::kDebugInfoNone
;
3080 else if ( strcmp(arg
, "-X") == 0 ) {
3083 else if ( strcmp(arg
, "-Si") == 0 ) {
3085 fDebugInfoStripping
= Options::kDebugInfoFull
;
3087 else if ( strcmp(arg
, "-b") == 0 ) {
3090 else if ( strcmp(arg
, "-Sn") == 0 ) {
3092 fDebugInfoStripping
= Options::kDebugInfoFull
;
3094 else if ( strcmp(arg
, "-Sp") == 0 ) {
3097 else if ( strcmp(arg
, "-dead_strip") == 0 ) {
3100 else if ( strcmp(arg
, "-no_dead_strip_inits_and_terms") == 0 ) {
3103 else if ( strcmp(arg
, "-w") == 0 ) {
3104 // previously handled by buildSearchPaths()
3106 else if ( strcmp(arg
, "-fatal_warnings") == 0 ) {
3107 // previously handled by buildSearchPaths()
3109 else if ( strcmp(arg
, "-arch_errors_fatal") == 0 ) {
3110 fErrorOnOtherArchFiles
= true;
3112 else if ( strcmp(arg
, "-M") == 0 ) {
3115 else if ( strcmp(arg
, "-headerpad") == 0 ) {
3116 const char* size
= argv
[++i
];
3118 throw "-headerpad missing argument";
3119 fMinimumHeaderPad
= parseAddress(size
);
3120 cannotBeUsedWithBitcode(arg
);
3122 else if ( strcmp(arg
, "-headerpad_max_install_names") == 0 ) {
3123 // ignore -headerpad_max_install_names when compiling with bitcode
3124 // rdar://problem/20748962
3125 if ( fBundleBitcode
)
3126 warning("-headerpad_max_install_names is ignored when used with -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES)");
3128 fMaxMinimumHeaderPad
= true;
3130 else if ( strcmp(arg
, "-t") == 0 ) {
3131 fLogAllFiles
= true;
3133 else if ( strcmp(arg
, "-whatsloaded") == 0 ) {
3134 fLogObjectFiles
= true;
3136 else if ( strcmp(arg
, "-A") == 0 ) {
3140 else if ( strcmp(arg
, "-umbrella") == 0 ) {
3141 const char* name
= argv
[++i
];
3143 throw "-umbrella missing argument";
3144 fUmbrellaName
= name
;
3145 cannotBeUsedWithBitcode(arg
);
3147 else if ( strcmp(arg
, "-allowable_client") == 0 ) {
3148 const char* name
= argv
[++i
];
3151 throw "-allowable_client missing argument";
3153 fAllowableClients
.push_back(name
);
3154 cannotBeUsedWithBitcode(arg
);
3156 else if ( strcmp(arg
, "-client_name") == 0 ) {
3157 const char* name
= argv
[++i
];
3160 throw "-client_name missing argument";
3163 cannotBeUsedWithBitcode(arg
);
3165 else if ( strcmp(arg
, "-sub_umbrella") == 0 ) {
3166 const char* name
= argv
[++i
];
3168 throw "-sub_umbrella missing argument";
3169 fSubUmbellas
.push_back(name
);
3170 cannotBeUsedWithBitcode(arg
);
3172 else if ( strcmp(arg
, "-sub_library") == 0 ) {
3173 const char* name
= argv
[++i
];
3175 throw "-sub_library missing argument";
3176 fSubLibraries
.push_back(name
);
3177 cannotBeUsedWithBitcode(arg
);
3179 else if ( strcmp(arg
, "-init") == 0 ) {
3180 const char* name
= argv
[++i
];
3182 throw "-init missing argument";
3183 fInitFunctionName
= name
;
3184 cannotBeUsedWithBitcode(arg
);
3186 else if ( strcmp(arg
, "-dot") == 0 ) {
3187 const char* name
= argv
[++i
];
3189 throw "-dot missing argument";
3190 fDotOutputFile
= name
;
3191 cannotBeUsedWithBitcode(arg
);
3193 else if ( strcmp(arg
, "-warn_commons") == 0 ) {
3194 fWarnCommons
= true;
3196 else if ( strcmp(arg
, "-commons") == 0 ) {
3197 fCommonsMode
= parseCommonsTreatment(argv
[++i
]);
3199 else if ( strcmp(arg
, "-keep_relocs") == 0 ) {
3200 fKeepRelocations
= true;
3202 else if ( strcmp(arg
, "-warn_stabs") == 0 ) {
3205 else if ( strcmp(arg
, "-pause") == 0 ) {
3208 else if ( strcmp(arg
, "-print_statistics") == 0 ) {
3211 else if ( strcmp(arg
, "-d") == 0 ) {
3212 fMakeTentativeDefinitionsReal
= true;
3214 else if ( strcmp(arg
, "-v") == 0 ) {
3215 // previously handled by buildSearchPaths()
3217 else if ( strcmp(arg
, "-Z") == 0 ) {
3218 // previously handled by buildSearchPaths()
3220 else if ( strcmp(arg
, "-syslibroot") == 0 ) {
3221 snapshotArgCount
= 0;
3223 // previously handled by buildSearchPaths()
3225 else if ( strcmp(arg
, "-bitcode_bundle") == 0 ) {
3226 snapshotArgCount
= 0;
3227 // previously handled by buildSearchPaths()
3229 else if ( strcmp(arg
, "-no_uuid") == 0 ) {
3230 fUUIDMode
= kUUIDNone
;
3231 cannotBeUsedWithBitcode(arg
);
3233 else if ( strcmp(arg
, "-random_uuid") == 0 ) {
3234 fUUIDMode
= kUUIDRandom
;
3235 cannotBeUsedWithBitcode(arg
);
3237 else if ( strcmp(arg
, "-dtrace") == 0 ) {
3238 snapshotFileArgIndex
= 1;
3239 const char* name
= argv
[++i
];
3241 throw "-dtrace missing argument";
3242 fDtraceScriptName
= name
;
3243 cannotBeUsedWithBitcode(arg
);
3245 else if ( strcmp(arg
, "-root_safe") == 0 ) {
3248 else if ( strcmp(arg
, "-setuid_safe") == 0 ) {
3251 else if ( strcmp(arg
, "-alias") == 0 ) {
3252 Options::AliasPair pair
;
3253 pair
.realName
= checkForNullArgument(arg
, argv
[++i
]);
3254 pair
.alias
= checkForNullArgument(arg
, argv
[++i
]);
3255 fAliases
.push_back(pair
);
3256 cannotBeUsedWithBitcode(arg
);
3258 else if ( strcmp(arg
, "-alias_list") == 0 ) {
3259 snapshotFileArgIndex
= 1;
3260 parseAliasFile(argv
[++i
]);
3261 cannotBeUsedWithBitcode(arg
);
3263 else if ( strcmp(arg
, "-save-temps") == 0 ) {
3264 fSaveTempFiles
= true;
3266 else if ( strcmp(arg
, "-bitcode_hide_symbols") == 0 ) {
3267 fHideSymbols
= true;
3269 else if ( strcmp(arg
, "-bitcode_verify") == 0 ) {
3270 fVerifyBitcode
= true;
3272 else if ( strcmp(arg
, "-bitcode_symbol_map") == 0) {
3273 fReverseMapPath
= checkForNullArgument(arg
, argv
[++i
]);
3274 struct stat statbuf
;
3275 int ret
= ::stat(fReverseMapPath
, &statbuf
);
3276 if ( ret
== 0 && S_ISDIR(statbuf
.st_mode
)) {
3277 char tempPath
[PATH_MAX
];
3278 sprintf(tempPath
, "%s/XXXXXX", fReverseMapPath
);
3279 int tempFile
= ::mkstemp(tempPath
);
3281 throwf("could not write file to symbol map directory: %s", fReverseMapPath
);
3283 fReverseMapTempPath
= std::string(tempPath
);
3284 fReverseMapUUIDRename
= true;
3286 fReverseMapTempPath
= std::string(fReverseMapPath
);
3288 else if ( strcmp(arg
, "-flto-codegen-only") == 0) {
3289 fLTOCodegenOnly
= true;
3291 else if ( strcmp(arg
, "-ignore_auto_link") == 0) {
3292 fIgnoreAutoLink
= true;
3294 else if ( strcmp(arg
, "-allow_dead_duplicates") == 0) {
3295 fAllowDeadDups
= true;
3297 else if ( strcmp(arg
, "-bitcode_process_mode") == 0 ) {
3298 const char* bitcode_type
= checkForNullArgument(arg
, argv
[++i
]);
3299 if ( strcmp(bitcode_type
, "strip") == 0 )
3300 fBitcodeKind
= kBitcodeStrip
;
3301 else if ( strcmp(bitcode_type
, "marker") == 0 )
3302 fBitcodeKind
= kBitcodeMarker
;
3303 else if ( strcmp(bitcode_type
, "data") == 0 )
3304 fBitcodeKind
= kBitcodeAsData
;
3305 else if ( strcmp(bitcode_type
, "bitcode") == 0 )
3306 fBitcodeKind
= kBitcodeProcess
;
3308 throw "unknown argument to -bitcode_process_mode {strip,marker,data,bitcode}";
3310 else if ( strcmp(arg
, "-rpath") == 0 ) {
3311 const char* path
= checkForNullArgument(arg
, argv
[++i
]);
3312 fRPaths
.push_back(path
);
3314 else if ( strcmp(arg
, "-read_only_stubs") == 0 ) {
3315 fReadOnlyx86Stubs
= true;
3317 else if ( strcmp(arg
, "-slow_stubs") == 0 ) {
3320 else if ( strcmp(arg
, "-map") == 0 ) {
3321 fMapPath
= checkForNullArgument(arg
, argv
[++i
]);
3323 else if ( strcmp(arg
, "-pie") == 0 ) {
3324 fPositionIndependentExecutable
= true;
3325 fPIEOnCommandLine
= true;
3327 else if ( strcmp(arg
, "-no_pie") == 0 ) {
3328 fDisablePositionIndependentExecutable
= true;
3329 cannotBeUsedWithBitcode(arg
);
3331 else if ( strncmp(arg
, "-reexport-l", 11) == 0 ) {
3332 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3333 snapshotArgCount
= 0;
3334 FileInfo info
= findLibrary(&arg
[11], true);
3335 info
.options
.fReExport
= true;
3336 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3338 cannotBeUsedWithBitcode(arg
);
3340 else if ( strcmp(arg
, "-reexport_library") == 0 ) {
3341 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3342 snapshotArgCount
= 0;
3343 const char* path
= checkForNullArgument(arg
, argv
[++i
]);
3344 FileInfo info
= findFile(path
);
3345 info
.options
.fReExport
= true;
3346 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3348 cannotBeUsedWithBitcode(arg
);
3350 else if ( strcmp(arg
, "-reexport_framework") == 0 ) {
3351 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3352 snapshotArgCount
= 0;
3353 FileInfo info
= findFramework(argv
[++i
]);
3354 info
.options
.fReExport
= true;
3355 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3357 cannotBeUsedWithBitcode(arg
);
3359 else if ( strncmp(arg
, "-upward-l", 9) == 0 ) {
3360 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3361 snapshotArgCount
= 0;
3362 FileInfo info
= findLibrary(&arg
[9], true);
3363 info
.options
.fUpward
= true;
3364 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3366 cannotBeUsedWithBitcode(arg
);
3368 else if ( strcmp(arg
, "-upward_library") == 0 ) {
3369 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3370 snapshotArgCount
= 0;
3371 const char* path
= checkForNullArgument(arg
, argv
[++i
]);
3372 FileInfo info
= findFile(path
);
3373 info
.options
.fUpward
= true;
3374 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3376 cannotBeUsedWithBitcode(arg
);
3378 else if ( strcmp(arg
, "-upward_framework") == 0 ) {
3379 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3380 snapshotArgCount
= 0;
3381 FileInfo info
= findFramework(argv
[++i
]);
3382 info
.options
.fUpward
= true;
3383 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3385 cannotBeUsedWithBitcode(arg
);
3387 else if ( strcmp(arg
, "-dead_strip_dylibs") == 0 ) {
3388 fDeadStripDylibs
= true;
3389 cannotBeUsedWithBitcode(arg
);
3391 else if ( strcmp(arg
, "-no_implicit_dylibs") == 0 ) {
3392 fImplicitlyLinkPublicDylibs
= false;
3394 else if ( strcmp(arg
, "-new_linker") == 0 ) {
3397 else if ( strcmp(arg
, "-no_encryption") == 0 ) {
3398 fEncryptableForceOff
= true;
3399 cannotBeUsedWithBitcode(arg
);
3401 else if ( strcmp(arg
, "-encryptable") == 0 ) {
3402 fEncryptableForceOn
= true;
3403 cannotBeUsedWithBitcode(arg
);
3405 else if ( strcmp(arg
, "-no_compact_unwind") == 0 ) {
3406 fAddCompactUnwindEncoding
= false;
3407 cannotBeUsedWithBitcode(arg
);
3409 else if ( strcmp(arg
, "-mllvm") == 0 ) {
3410 const char* opts
= checkForNullArgument(arg
, argv
[++i
]);
3411 fLLVMOptions
.push_back(opts
);
3412 cannotBeUsedWithBitcode(arg
);
3414 else if ( strcmp(arg
, "-mcpu") == 0 ) {
3415 const char* cpu
= checkForNullArgument(arg
, argv
[++i
]);
3417 cannotBeUsedWithBitcode(arg
);
3419 else if ( strcmp(arg
, "-no_order_inits") == 0 ) {
3420 fAutoOrderInitializers
= false;
3421 cannotBeUsedWithBitcode(arg
);
3423 else if ( strcmp(arg
, "-no_order_data") == 0 ) {
3425 cannotBeUsedWithBitcode(arg
);
3427 else if ( strcmp(arg
, "-seg_page_size") == 0 ) {
3429 seg
.name
= argv
[++i
];
3430 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
3431 throw "-seg_page_size missing segName Adddress";
3432 seg
.size
= parseAddress(argv
[++i
]);
3433 uint64_t temp
= seg
.size
& (-4096); // page align
3434 if ( (seg
.size
!= temp
) )
3435 warning("-seg_page_size %s not 4K aligned, rounding down", seg
.name
);
3436 fCustomSegmentSizes
.push_back(seg
);
3437 cannotBeUsedWithBitcode(arg
);
3439 else if ( strcmp(arg
, "-mark_dead_strippable_dylib") == 0 ) {
3440 fMarkDeadStrippableDylib
= true;
3441 cannotBeUsedWithBitcode(arg
);
3443 else if ( strcmp(arg
, "-exported_symbols_order") == 0 ) {
3444 snapshotFileArgIndex
= 1;
3445 loadSymbolOrderFile(argv
[++i
], fExportSymbolsOrder
);
3446 cannotBeUsedWithBitcode(arg
);
3448 else if ( strcmp(arg
, "-no_compact_linkedit") == 0 ) {
3449 warnObsolete("-no_compact_linkedit");
3451 else if ( strcmp(arg
, "-no_eh_labels") == 0 ) {
3453 cannotBeUsedWithBitcode(arg
);
3455 else if ( strcmp(arg
, "-warn_compact_unwind") == 0 ) {
3456 fWarnCompactUnwind
= true;
3458 else if ( strcmp(arg
, "-allow_sub_type_mismatches") == 0 ) {
3459 fAllowCpuSubtypeMismatches
= true;
3460 cannotBeUsedWithBitcode(arg
);
3462 else if ( strcmp(arg
, "-no_zero_fill_sections") == 0 ) {
3463 fOptimizeZeroFill
= false;
3464 cannotBeUsedWithBitcode(arg
);
3466 else if ( strcmp(arg
, "-merge_zero_fill_sections") == 0 ) {
3467 fMergeZeroFill
= true;
3468 cannotBeUsedWithBitcode(arg
);
3470 else if ( strcmp(arg
, "-objc_abi_version") == 0 ) {
3471 const char* version
= checkForNullVersionArgument(arg
, argv
[++i
]);
3472 if ( strcmp(version
, "2") == 0 ) {
3473 fObjCABIVersion1Override
= false;
3474 fObjCABIVersion2Override
= true;
3476 else if ( strcmp(version
, "1") == 0 ) {
3477 fObjCABIVersion1Override
= true;
3478 fObjCABIVersion2Override
= false;
3481 warning("ignoring unrecognized argument (%s) to -objc_abi_version", version
);
3483 else if ( strcmp(arg
, "-warn_weak_exports") == 0 ) {
3484 fWarnWeakExports
= true;
3486 else if ( strcmp(arg
, "-no_weak_exports") == 0 ) {
3487 fNoWeakExports
= true;
3489 else if ( strcmp(arg
, "-objc_gc_compaction") == 0 ) {
3490 fObjcGcCompaction
= true;
3491 cannotBeUsedWithBitcode(arg
);
3493 else if ( strcmp(arg
, "-objc_gc") == 0 ) {
3495 if ( fObjCGcOnly
) {
3496 warning("-objc_gc overriding -objc_gc_only");
3497 fObjCGcOnly
= false;
3499 cannotBeUsedWithBitcode(arg
);
3501 else if ( strcmp(arg
, "-objc_gc_only") == 0 ) {
3504 warning("-objc_gc_only overriding -objc_gc");
3507 cannotBeUsedWithBitcode(arg
);
3509 else if ( strcmp(arg
, "-demangle") == 0 ) {
3512 else if ( strcmp(arg
, "-version_load_command") == 0 ) {
3513 fVersionLoadCommandForcedOn
= true;
3514 fVersionLoadCommandForcedOff
= false;
3516 else if ( strcmp(arg
, "-function_starts") == 0 ) {
3517 fFunctionStartsForcedOn
= true;
3518 fFunctionStartsForcedOff
= false;
3520 else if ( strcmp(arg
, "-no_function_starts") == 0 ) {
3521 fFunctionStartsForcedOff
= true;
3522 fFunctionStartsForcedOn
= false;
3523 cannotBeUsedWithBitcode(arg
);
3525 else if ( strcmp(arg
, "-no_data_in_code_info") == 0 ) {
3526 fDataInCodeInfoLoadCommandForcedOff
= true;
3527 fDataInCodeInfoLoadCommandForcedOn
= false;
3528 cannotBeUsedWithBitcode(arg
);
3530 else if ( strcmp(arg
, "-data_in_code_info") == 0 ) {
3531 fDataInCodeInfoLoadCommandForcedOn
= true;
3532 fDataInCodeInfoLoadCommandForcedOff
= false;
3534 else if ( strcmp(arg
, "-object_path_lto") == 0 ) {
3535 fTempLtoObjectPath
= checkForNullArgument(arg
, argv
[++i
]);
3537 else if ( strcmp(arg
, "-no_objc_category_merging") == 0 ) {
3538 fObjcCategoryMerging
= false;
3540 else if ( strcmp(arg
, "-force_symbols_weak_list") == 0 ) {
3541 snapshotFileArgIndex
= 1;
3542 loadExportFile(argv
[++i
], "-force_symbols_weak_list", fForceWeakSymbols
);
3543 cannotBeUsedWithBitcode(arg
);
3545 else if ( strcmp(arg
, "-force_symbols_not_weak_list") == 0 ) {
3546 snapshotFileArgIndex
= 1;
3547 loadExportFile(argv
[++i
], "-force_symbols_not_weak_list", fForceNotWeakSymbols
);
3548 cannotBeUsedWithBitcode(arg
);
3550 else if ( strcmp(arg
, "-force_symbol_weak") == 0 ) {
3551 const char* symbol
= argv
[++i
];
3552 if ( symbol
== NULL
)
3553 throw "-force_symbol_weak missing <symbol>";
3554 fForceWeakSymbols
.insert(symbol
);
3555 cannotBeUsedWithBitcode(arg
);
3557 else if ( strcmp(arg
, "-force_symbol_not_weak") == 0 ) {
3558 const char* symbol
= argv
[++i
];
3559 if ( symbol
== NULL
)
3560 throw "-force_symbol_not_weak missing <symbol>";
3561 fForceNotWeakSymbols
.insert(symbol
);
3562 cannotBeUsedWithBitcode(arg
);
3564 else if ( strcmp(arg
, "-reexported_symbols_list") == 0 ) {
3565 snapshotFileArgIndex
= 1;
3566 if ( fExportMode
== kExportSome
)
3567 throw "can't use -exported_symbols_list and -reexported_symbols_list";
3568 loadExportFile(argv
[++i
], "-reexported_symbols_list", fReExportSymbols
);
3570 else if ( strcmp(arg
, "-dyld_env") == 0 ) {
3571 const char* envarg
= argv
[++i
];
3572 if ( envarg
== NULL
)
3573 throw "-dyld_env missing ENV=VALUE";
3574 if ( strchr(envarg
, '=') == NULL
)
3575 throw "-dyld_env missing ENV=VALUE";
3576 fDyldEnvironExtras
.push_back(envarg
);
3577 cannotBeUsedWithBitcode(arg
);
3579 else if ( strcmp(arg
, "-page_align_data_atoms") == 0 ) {
3580 fPageAlignDataAtoms
= true;
3581 cannotBeUsedWithBitcode(arg
);
3583 else if (strcmp(arg
, "-debug_snapshot") == 0) {
3584 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
3585 fSnapshotRequested
= true;
3586 cannotBeUsedWithBitcode(arg
);
3588 else if (strcmp(arg
, "-snapshot_dir") == 0) {
3589 const char* path
= argv
[++i
];
3591 throw "-snapshot_dir missing path";
3592 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
3593 fLinkSnapshot
.setSnapshotPath(path
);
3594 fSnapshotRequested
= true;
3595 cannotBeUsedWithBitcode(arg
);
3597 else if ( strcmp(arg
, "-source_version") == 0 ) {
3598 const char* vers
= argv
[++i
];
3600 throw "-source_version missing <version>";
3601 fSourceVersion
= parseVersionNumber64(vers
);
3603 else if ( strcmp(arg
, "-add_source_version") == 0 ) {
3604 fSourceVersionLoadCommandForceOn
= true;
3606 else if ( strcmp(arg
, "-no_source_version") == 0 ) {
3607 fSourceVersionLoadCommandForceOff
= true;
3608 cannotBeUsedWithBitcode(arg
);
3610 else if ( strcmp(arg
, "-sdk_version") == 0 ) {
3611 const char* vers
= argv
[++i
];
3613 throw "-sdk_version missing <version>";
3614 fSDKVersion
= parseVersionNumber32(vers
);
3616 else if ( strcmp(arg
, "-dependent_dr_info") == 0 ) {
3619 else if ( strcmp(arg
, "-no_dependent_dr_info") == 0 ) {
3622 else if ( strcmp(arg
, "-kexts_use_stubs") == 0 ) {
3623 fKextsUseStubs
= true;
3624 cannotBeUsedWithBitcode(arg
);
3626 else if ( strcmp(arg
, "-dependency_info") == 0 ) {
3627 snapshotArgCount
= 0;
3629 // previously handled by buildSearchPaths()
3631 else if ( strcmp(arg
, "-export_dynamic") == 0 ) {
3632 fExportDynamic
= true;
3634 else if ( strcmp(arg
, "-force_symbols_coalesce_list") == 0 ) {
3635 snapshotFileArgIndex
= 1;
3636 loadExportFile(argv
[++i
], "-force_symbols_coalesce_list", fForceCoalesceSymbols
);
3638 else if ( strcmp(arg
, "-add_linker_option") == 0 ) {
3639 // ex: -add_linker_option '-framework Foundation'
3640 const char* optString
= argv
[++i
];
3641 if ( optString
== NULL
)
3642 throw "-add_linker_option missing <option>";
3643 // break up into list of tokens at whitespace
3644 std::vector
<const char*> opts
;
3645 char* buffer
= strdup(optString
);
3646 char* start
= buffer
;
3647 for (char* s
= buffer
; ; ++s
) {
3648 if ( isspace(*s
) ) {
3650 opts
.push_back(start
);
3653 else if ( *s
== '\0' ) {
3654 opts
.push_back(start
);
3658 fLinkerOptions
.push_back(opts
);
3659 cannotBeUsedWithBitcode(arg
);
3661 else if ( strcmp(arg
, "-allow_simulator_linking_to_macosx_dylibs") == 0 ) {
3662 fAllowSimulatorToLinkWithMacOSX
= true;
3663 cannotBeUsedWithBitcode(arg
);
3665 else if ( strcmp(arg
, "-keep_dwarf_unwind") == 0 ) {
3666 fKeepDwarfUnwindForcedOn
= true;
3667 fKeepDwarfUnwindForcedOff
= false;
3668 cannotBeUsedWithBitcode(arg
);
3670 else if ( strcmp(arg
, "-no_keep_dwarf_unwind") == 0 ) {
3671 fKeepDwarfUnwindForcedOn
= false;
3672 fKeepDwarfUnwindForcedOff
= true;
3673 cannotBeUsedWithBitcode(arg
);
3675 else if ( strcmp(arg
, "-verbose_optimization_hints") == 0 ) {
3676 fVerboseOptimizationHints
= true;
3678 else if ( strcmp(arg
, "-ignore_optimization_hints") == 0 ) {
3679 fIgnoreOptimizationHints
= true;
3680 cannotBeUsedWithBitcode(arg
);
3682 else if ( strcmp(arg
, "-no_dtrace_dof") == 0 ) {
3683 fGenerateDtraceDOF
= false;
3685 else if ( strcmp(arg
, "-rename_section") == 0 ) {
3686 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) || (argv
[i
+4]==NULL
) )
3687 throw "-rename_section missing <segment> <section> <segment> <section>";
3688 addSectionRename(argv
[i
+1], argv
[i
+2], argv
[i
+3], argv
[i
+4]);
3690 cannotBeUsedWithBitcode(arg
);
3692 else if ( strcmp(arg
, "-rename_segment") == 0 ) {
3693 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3694 throw "-rename_segment missing <existing-segment> <new-segment>";
3695 addSegmentRename(argv
[i
+1], argv
[i
+2]);
3697 cannotBeUsedWithBitcode(arg
);
3699 else if ( strcmp(arg
, "-move_to_ro_segment") == 0 ) {
3700 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3701 throw "-move_to_ro_segment missing <segment> <symbol-list-file>";
3702 addSymbolMove(argv
[i
+1], argv
[i
+2], fSymbolsMovesCode
, "-move_to_ro_segment");
3704 cannotBeUsedWithBitcode(arg
);
3706 else if ( strcmp(arg
, "-move_to_rw_segment") == 0 ) {
3707 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3708 throw "-move_to_rw_segment missing <segment> <symbol-list-file>";
3709 addSymbolMove(argv
[i
+1], argv
[i
+2], fSymbolsMovesData
, "-move_to_rw_segment");
3711 cannotBeUsedWithBitcode(arg
);
3713 else if ( strcmp(arg
, "-trace_symbol_layout") == 0 ) {
3714 fTraceSymbolLayout
= true;
3716 else if ( strcmp(arg
, "-no_branch_islands") == 0 ) {
3717 fAllowBranchIslands
= false;
3718 cannotBeUsedWithBitcode(arg
);
3720 else if ( strcmp(arg
, "-segment_order") == 0 ) {
3721 // ex: -segment_order __TEXT:__DATA:__JUNK
3722 const char* optString
= argv
[++i
];
3723 if ( optString
== NULL
)
3724 throw "-segment_order missing colon separated <segment-list>";
3725 if ( !fSegmentOrder
.empty() )
3726 throw "-segment_order used more than once";
3727 // break up into list of tokens at colon
3728 char* buffer
= strdup(optString
);
3729 char* start
= buffer
;
3730 for (char* s
= buffer
; ; ++s
) {
3733 fSegmentOrder
.push_back(start
);
3736 else if ( *s
== '\0' ) {
3737 fSegmentOrder
.push_back(start
);
3741 cannotBeUsedWithBitcode(arg
);
3743 else if ( strcmp(arg
, "-section_order") == 0 ) {
3744 // ex: -section_order __DATA __data:__const:__nl_pointers
3745 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3746 throw "-section_order missing <segment> <section-list>";
3747 const char* segName
= argv
[++i
];
3748 const char* optString
= argv
[++i
];
3749 if ( sectionOrder(segName
) != NULL
)
3750 throwf("-section_order %s ... used more than once", segName
);
3751 SectionOrderList dummy
;
3752 fSectionOrder
.push_back(dummy
);
3753 SectionOrderList
& entry
= fSectionOrder
.back();
3754 entry
.segmentName
= segName
;
3755 // break up into list of tokens at colon
3756 char* buffer
= strdup(optString
);
3757 char* start
= buffer
;
3758 for (char* s
= buffer
; ; ++s
) {
3761 entry
.sectionOrder
.push_back(start
);
3764 else if ( *s
== '\0' ) {
3765 entry
.sectionOrder
.push_back(start
);
3769 cannotBeUsedWithBitcode(arg
);
3771 else if ( strcmp(arg
, "-application_extension") == 0 ) {
3772 fMarkAppExtensionSafe
= true;
3773 fCheckAppExtensionSafe
= true;
3775 else if ( strcmp(arg
, "-no_application_extension") == 0 ) {
3776 fMarkAppExtensionSafe
= false;
3777 fCheckAppExtensionSafe
= false;
3779 else if ( strcmp(arg
, "-add_ast_path") == 0 ) {
3780 const char* path
= argv
[++i
];
3782 throw "-add_ast_path missing <option>";
3783 fASTFilePaths
.push_back(path
);
3785 else if ( strcmp(arg
, "-force_load_swift_libs") == 0 ) {
3786 fForceLoadSwiftLibs
= true;
3788 else if ( strcmp(arg
, "-not_for_dyld_shared_cache") == 0 ) {
3789 fSharedRegionEligibleForceOff
= true;
3790 cannotBeUsedWithBitcode(arg
);
3792 else if ( strcmp(arg
, "-dirty_data_list") == 0 ) {
3793 if ( argv
[i
+1] == NULL
)
3794 throw "-dirty_data_list missing <symbol-list-file>";
3795 addSymbolMove("__DATA_DIRTY", argv
[i
+1], fSymbolsMovesData
, "-dirty_data_list");
3797 cannotBeUsedWithBitcode(arg
);
3799 else if ( strcmp(arg
, "-data_const") == 0 ) {
3800 fUseDataConstSegmentForceOn
= true;
3801 cannotBeUsedWithBitcode(arg
);
3803 else if ( strcmp(arg
, "-no_data_const") == 0 ) {
3804 fUseDataConstSegmentForceOff
= true;
3805 cannotBeUsedWithBitcode(arg
);
3807 else if ( strcmp(arg
, "-text_exec") == 0 ) {
3808 fUseTextExecSegment
= true;
3809 cannotBeUsedWithBitcode(arg
);
3811 else if ( strcmp(arg
, "-add_split_seg_info") == 0) {
3812 fSharedRegionEligible
= true;
3813 cannotBeUsedWithBitcode(arg
);
3815 else if ( strcmp(arg
, "-no_deduplicate") == 0 ) {
3818 else if ( strcmp(arg
, "-verbose_deduplicate") == 0 ) {
3819 fVerboseDeDupe
= true;
3821 else if ( strcmp(arg
, "-max_default_common_align") == 0 ) {
3822 const char* alignStr
= argv
[++i
];
3823 if ( alignStr
== NULL
)
3824 throw "-max_default_common_align missing <align-value>";
3825 // argument is a hexadecimal number
3827 unsigned long value
= strtoul(alignStr
, &endptr
, 16);
3828 if ( *endptr
!= '\0')
3829 throw "argument for -max_default_common_align is not a hexadecimal number";
3830 if ( value
> 0x8000 )
3831 throw "argument for -max_default_common_align must be less than or equal to 0x8000";
3833 warning("zero is not a valid -max_default_common_align");
3836 // alignment is power of 2
3837 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
3838 if ( (unsigned long)(1 << alignment
) != value
) {
3839 warning("alignment for -max_default_common_align is not a power of two, using 0x%X", 1 << alignment
);
3841 fMaxDefaultCommonAlign
= alignment
;
3843 else if ( strcmp(arg
, "-no_weak_imports") == 0 ) {
3844 fAllowWeakImports
= false;
3846 else if ( strcmp(arg
, "-no_inits") == 0 ) {
3847 fInitializersTreatment
= Options::kError
;
3849 else if ( strcmp(arg
, "-no_warn_inits") == 0 ) {
3850 fInitializersTreatment
= Options::kSuppress
;
3852 else if ( strcmp(arg
, "-threaded_starts_section") == 0 ) {
3853 fMakeThreadedStartsSection
= true;
3855 else if (strcmp(arg
, "-debug_variant") == 0) {
3856 fDebugVariant
= true;
3858 else if (strcmp(arg
, "-no_new_main") == 0) {
3859 // HACK until 39514191 is fixed
3861 // put this last so that it does not interfer with other options starting with 'i'
3862 else if ( strncmp(arg
, "-i", 2) == 0 ) {
3863 const char* colon
= strchr(arg
, ':');
3864 if ( colon
== NULL
)
3865 throwf("unknown option: %s", arg
);
3866 Options::AliasPair pair
;
3867 char* temp
= new char[colon
-arg
];
3868 strlcpy(temp
, &arg
[2], colon
-arg
-1);
3869 pair
.realName
= &colon
[1];
3871 fAliases
.push_back(pair
);
3874 throwf("unknown option: %s", arg
);
3877 if (snapshotArgCount
== -1)
3878 snapshotArgCount
= i
-snapshotArgIndex
+1;
3879 if (snapshotArgCount
> 0)
3880 fLinkSnapshot
.addSnapshotLinkArg(snapshotArgIndex
, snapshotArgCount
, snapshotFileArgIndex
);
3883 FileInfo info
= findFile(arg
);
3884 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3885 if ( strcmp(&info
.path
[strlen(info
.path
)-2], ".a") == 0 )
3888 fInputFiles
.push_back(info
);
3892 // if a -lazy option was used, implicitly link in lazydylib1.o
3893 if ( fUsingLazyDylibLinking
) {
3894 FileInfo info
= findLibrary("lazydylib1.o");
3895 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)argc
);
3899 if (fSnapshotRequested
)
3900 fLinkSnapshot
.createSnapshot();
3902 if ( kKextBundle
== fOutputKind
) {
3903 if ( fKextObjectsEnable
< 0 )
3904 fKextObjectsEnable
= ((fArchitecture
== CPU_TYPE_ARM64
) || (fArchitecture
== CPU_TYPE_ARM
));
3906 if (fKextObjectsEnable
> 0) {
3907 if ( !fKextObjectsDirPath
) {
3908 const char* dstroot
;
3909 const char* objdir
= getenv("LD_KEXT_OBJECTS_DIR");
3911 fKextObjectsDirPath
= strdup(objdir
);
3912 else if ( (dstroot
= getenv("DSTROOT")) )
3913 asprintf((char **)&fKextObjectsDirPath
, "%s/AppleInternal/KextObjects", dstroot
);
3915 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_KEXT
);
3916 fLinkSnapshot
.createSnapshot();
3922 // -syslibroot <path> is used for SDK support.
3923 // The rule is that all search paths (both explicit and default) are
3924 // checked to see if they exist in the SDK. If so, that path is
3925 // replaced with the sdk prefixed path. If not, that search path
3926 // is used as is. If multiple -syslibroot options are specified
3927 // their directory structures are logically overlayed and files
3928 // from sdks specified earlier on the command line used before later ones.
3930 void Options::buildSearchPaths(int argc
, const char* argv
[])
3932 bool addStandardLibraryDirectories
= true;
3933 std::vector
<const char*> libraryPaths
;
3934 std::vector
<const char*> frameworkPaths
;
3935 libraryPaths
.reserve(10);
3936 frameworkPaths
.reserve(10);
3937 // scan through argv looking for -L, -F, -Z, and -syslibroot options
3938 for(int i
=0; i
< argc
; ++i
) {
3939 if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'L') ) {
3940 const char* libSearchDir
= &argv
[i
][2];
3941 // Allow either "-L{path}" or "-L {path}".
3942 if (argv
[i
][2] == '\0') {
3943 // -L {path}. Make sure there is an argument following this.
3944 const char* path
= argv
[++i
];
3946 throw "-L missing argument";
3947 libSearchDir
= path
;
3949 if ( libSearchDir
[0] == '\0' )
3950 throw "-L must be immediately followed by a directory path (no space)";
3951 libraryPaths
.push_back(libSearchDir
);
3953 else if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'F') ) {
3954 const char* frameworkSearchDir
= &argv
[i
][2];
3955 // Allow either "-F{path}" or "-F {path}".
3956 if (argv
[i
][2] == '\0') {
3957 // -F {path}. Make sure there is an argument following this.
3958 const char* path
= argv
[++i
];
3960 throw "-F missing argument";
3961 frameworkSearchDir
= path
;
3963 if ( frameworkSearchDir
[0] == '\0' )
3964 throw "-F must be immediately followed by a directory path (no space)";
3965 frameworkPaths
.push_back(frameworkSearchDir
);
3967 else if ( strcmp(argv
[i
], "-Z") == 0 )
3968 addStandardLibraryDirectories
= false;
3969 else if ( strcmp(argv
[i
], "-v") == 0 ) {
3971 extern const char ldVersionString
[];
3972 fprintf(stderr
, "%s", ldVersionString
);
3973 fprintf(stderr
, "BUILD " __TIME__
" " __DATE__
"\n");
3974 fprintf(stderr
, "configured to support archs: %s\n", ALL_SUPPORTED_ARCHS
);
3975 // if only -v specified, exit cleanly
3977 const char* ltoVers
= lto::version();
3978 if ( ltoVers
!= NULL
)
3979 fprintf(stderr
, "LTO support using: %s (static support for %d, runtime is %d)\n",
3980 ltoVers
, lto::static_api_version(), lto::runtime_api_version());
3981 fprintf(stderr
, "TAPI support using: %s\n", tapi::Version::getFullVersionAsString().c_str());
3985 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
3986 const char* path
= argv
[++i
];
3988 throw "-syslibroot missing argument";
3989 fSDKPaths
.push_back(path
);
3991 else if ( strcmp(argv
[i
], "-search_paths_first") == 0 ) {
3992 fLibrarySearchMode
= kSearchDylibAndArchiveInEachDir
;
3994 else if ( strcmp(argv
[i
], "-search_dylibs_first") == 0 ) {
3995 fLibrarySearchMode
= kSearchAllDirsForDylibsThenAllDirsForArchives
;
3997 else if ( strcmp(argv
[i
], "-w") == 0 ) {
3998 sEmitWarnings
= false;
4000 else if ( strcmp(argv
[i
], "-fatal_warnings") == 0 ) {
4001 sFatalWarnings
= true;
4003 else if ( strcmp(argv
[i
], "-dependency_info") == 0 ) {
4004 const char* path
= argv
[++i
];
4006 throw "-dependency_info missing <path>";
4007 fDependencyInfoPath
= path
;
4009 else if ( strcmp(argv
[i
], "-bitcode_bundle") == 0 ) {
4010 fBundleBitcode
= true;
4013 int standardLibraryPathsStartIndex
= libraryPaths
.size();
4014 int standardFrameworkPathsStartIndex
= frameworkPaths
.size();
4015 if ( addStandardLibraryDirectories
) {
4016 libraryPaths
.push_back("/usr/lib");
4017 libraryPaths
.push_back("/usr/local/lib");
4019 frameworkPaths
.push_back("/Library/Frameworks/");
4020 frameworkPaths
.push_back("/System/Library/Frameworks/");
4021 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
4024 // <rdar://problem/5829579> Support for configure based hacks
4025 // if last -syslibroot is /, then ignore all syslibroots
4026 if ( fSDKPaths
.size() > 0 ) {
4027 if ( strcmp(fSDKPaths
.back(), "/") == 0 ) {
4032 // now merge sdk and library paths to make real search paths
4033 fLibrarySearchPaths
.reserve(libraryPaths
.size()*(fSDKPaths
.size()+1));
4035 for (std::vector
<const char*>::iterator it
= libraryPaths
.begin(); it
!= libraryPaths
.end(); ++it
, ++libIndex
) {
4036 const char* libDir
= *it
;
4037 bool sdkOverride
= false;
4038 if ( libDir
[0] == '/' ) {
4039 char betterLibDir
[PATH_MAX
];
4040 if ( strstr(libDir
, "/..") != NULL
) {
4041 if ( realpath(libDir
, betterLibDir
) != NULL
)
4042 libDir
= strdup(betterLibDir
);
4044 const int libDirLen
= strlen(libDir
);
4045 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
4046 const char* sdkDir
= *sdkit
;
4047 const int sdkDirLen
= strlen(sdkDir
);
4048 char newPath
[libDirLen
+ sdkDirLen
+4];
4049 strcpy(newPath
, sdkDir
);
4050 if ( newPath
[sdkDirLen
-1] == '/' )
4051 newPath
[sdkDirLen
-1] = '\0';
4052 strcat(newPath
, libDir
);
4053 struct stat statBuffer
;
4054 if ( stat(newPath
, &statBuffer
) == 0 ) {
4055 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 ) {
4056 warning("-syslibroot and -L combined path '%s' is not a directory", newPath
);
4059 fLibrarySearchPaths
.push_back(strdup(newPath
));
4065 if ( !sdkOverride
) {
4066 if ( (libIndex
>= standardLibraryPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
4067 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
4068 // if one SDK is specified and a standard library path is not in the SDK, don't use it
4071 struct stat statBuffer
;
4072 if ( stat(libDir
, &statBuffer
) == 0 ) {
4073 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 )
4074 warning("-L path '%s' is not a directory", libDir
);
4076 fLibrarySearchPaths
.push_back(libDir
);
4078 else if ( !addStandardLibraryDirectories
|| (strcmp(libDir
, "/usr/local/lib") != 0) ) {
4079 warning("directory not found for option '-L%s'", libDir
);
4086 // now merge sdk and framework paths to make real search paths
4087 fFrameworkSearchPaths
.reserve(frameworkPaths
.size()*(fSDKPaths
.size()+1));
4089 for (std::vector
<const char*>::iterator it
= frameworkPaths
.begin(); it
!= frameworkPaths
.end(); ++it
, ++frameIndex
) {
4090 const char* frameworkDir
= *it
;
4091 bool sdkOverride
= false;
4092 if ( frameworkDir
[0] == '/' ) {
4093 char betterFrameworkDir
[PATH_MAX
];
4094 if ( strstr(frameworkDir
, "/..") != NULL
) {
4095 if ( realpath(frameworkDir
, betterFrameworkDir
) != NULL
)
4096 frameworkDir
= strdup(betterFrameworkDir
);
4098 const int frameworkDirLen
= strlen(frameworkDir
);
4099 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
4100 const char* sdkDir
= *sdkit
;
4101 const int sdkDirLen
= strlen(sdkDir
);
4102 char newPath
[frameworkDirLen
+ sdkDirLen
+4];
4103 strcpy(newPath
, sdkDir
);
4104 if ( newPath
[sdkDirLen
-1] == '/' )
4105 newPath
[sdkDirLen
-1] = '\0';
4106 strcat(newPath
, frameworkDir
);
4107 struct stat statBuffer
;
4108 if ( stat(newPath
, &statBuffer
) == 0 ) {
4109 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 ) {
4110 warning("-syslibroot and -F combined path '%s' is not a directory", newPath
);
4113 fFrameworkSearchPaths
.push_back(strdup(newPath
));
4119 if ( !sdkOverride
) {
4120 if ( (frameIndex
>= standardFrameworkPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
4121 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
4122 // if one SDK is specified and a standard library path is not in the SDK, don't use it
4125 struct stat statBuffer
;
4126 if ( stat(frameworkDir
, &statBuffer
) == 0 ) {
4127 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 )
4128 warning("-F path '%s' is not a directory", frameworkDir
);
4130 fFrameworkSearchPaths
.push_back(frameworkDir
);
4132 else if ( !addStandardLibraryDirectories
|| (strcmp(frameworkDir
, "/Library/Frameworks/") != 0) ) {
4133 warning("directory not found for option '-F%s'", frameworkDir
);
4140 fprintf(stderr
,"Library search paths:\n");
4141 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
4142 it
!= fLibrarySearchPaths
.end();
4144 fprintf(stderr
,"\t%s\n", *it
);
4145 fprintf(stderr
,"Framework search paths:\n");
4146 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
4147 it
!= fFrameworkSearchPaths
.end();
4149 fprintf(stderr
,"\t%s\n", *it
);
4153 // this is run before the command line is parsed
4154 void Options::parsePreCommandLineEnvironmentSettings()
4156 if ((getenv("LD_TRACE_ARCHIVES") != NULL
)
4157 || (getenv("RC_TRACE_ARCHIVES") != NULL
))
4158 fTraceArchives
= true;
4160 if ((getenv("LD_TRACE_DYLIBS") != NULL
)
4161 || (getenv("RC_TRACE_DYLIBS") != NULL
)) {
4162 fTraceDylibs
= true;
4163 fTraceIndirectDylibs
= true;
4166 if ((getenv("LD_TRACE_DEPENDENTS") != NULL
)) {
4168 fTraceEmitJSON
= true;
4171 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL
) {
4172 fTraceDylibSearching
= true;
4175 if (getenv("LD_PRINT_OPTIONS") != NULL
)
4176 fPrintOptions
= true;
4178 if (fTraceDylibs
|| fTraceArchives
|| fTraceEmitJSON
)
4179 fTraceOutputFile
= getenv("LD_TRACE_FILE");
4181 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL
)
4182 fPrintOrderFileStatistics
= true;
4184 if (getenv("LD_NO_ENCRYPT") != NULL
) {
4185 fEncryptable
= false;
4186 fMarkAppExtensionSafe
= true; // temporary
4187 fCheckAppExtensionSafe
= false;
4190 if (getenv("LD_APPLICATION_EXTENSION_SAFE") != NULL
) {
4191 fMarkAppExtensionSafe
= true;
4192 fCheckAppExtensionSafe
= false;
4195 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL
)
4196 fAllowCpuSubtypeMismatches
= true;
4198 if (getenv("LD_DYLIB_CPU_SUBTYPES_MUST_MATCH") != NULL
)
4199 fEnforceDylibSubtypesMatch
= true;
4201 if (getenv("LD_WARN_ON_SWIFT_ABI_VERSION_MISMATCHES") != NULL
)
4202 fWarnOnSwiftABIVersionMismatches
= true;
4204 sWarningsSideFilePath
= getenv("LD_WARN_FILE");
4206 const char* customDyldPath
= getenv("LD_DYLD_PATH");
4207 if ( customDyldPath
!= NULL
)
4208 fDyldInstallPath
= customDyldPath
;
4210 const char* debugArchivePath
= getenv("LD_DEBUG_SNAPSHOT");
4211 if (debugArchivePath
!= NULL
) {
4212 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
4213 if (strlen(debugArchivePath
) > 0)
4214 fLinkSnapshot
.setSnapshotPath(debugArchivePath
);
4215 fSnapshotRequested
= true;
4218 const char* pipeFdString
= getenv("LD_PIPELINE_FIFO");
4219 if (pipeFdString
!= NULL
) {
4220 fPipelineFifo
= pipeFdString
;
4223 // <rdar://problem/30746905> [Reproducible Builds] If env ZERO_AR_DATE is set, zero out timestamp in N_OSO stab
4224 if ( getenv("ZERO_AR_DATE") != NULL
)
4225 fZeroModTimeInDebugMap
= true;
4227 char rawPath
[PATH_MAX
];
4228 char path
[PATH_MAX
];
4230 uint32_t bufSize
= PATH_MAX
;
4231 if ( _NSGetExecutablePath(rawPath
, &bufSize
) != -1 ) {
4232 if ( realpath(rawPath
, path
) != NULL
) {
4233 #define TOOLCHAINBASEPATH "/Developer/Toolchains/"
4234 if ( (base
= strstr(path
, TOOLCHAINBASEPATH
)) )
4235 fToolchainPath
= strndup(path
, base
- path
+ strlen(TOOLCHAINBASEPATH
));
4239 // <rdar://problem/38679559> ld64 should consider RC_RELEASE when calculating a binary's UUID
4240 fBuildContextName
= getenv("RC_RELEASE");
4244 // this is run after the command line is parsed
4245 void Options::parsePostCommandLineEnvironmentSettings()
4247 // when building a dynamic main executable, default any use of @executable_path to output path
4248 if ( fExecutablePath
== NULL
&& (fOutputKind
== kDynamicExecutable
) ) {
4249 fExecutablePath
= fOutputFile
;
4252 // allow build system to force on dead-code-stripping
4253 if ( !fDeadStrip
) {
4254 if ( getenv("LD_DEAD_STRIP") != NULL
) {
4255 switch (fOutputKind
) {
4256 case Options::kDynamicLibrary
:
4257 case Options::kDynamicExecutable
:
4258 case Options::kDynamicBundle
:
4261 case Options::kPreload
:
4262 case Options::kObjectFile
:
4263 case Options::kDyld
:
4264 case Options::kStaticExecutable
:
4265 case Options::kKextBundle
:
4271 // allow build system to force on -warn_commons
4272 if ( getenv("LD_WARN_COMMONS") != NULL
)
4273 fWarnCommons
= true;
4275 // allow B&I to set default -source_version
4276 if ( fSourceVersion
== 0 ) {
4277 const char* vers
= getenv("RC_ProjectSourceVersion");
4279 fSourceVersion
= parseVersionNumber64(vers
);
4285 static bool sharedCacheEligiblePath(const char* path
)
4287 return ( (strncmp(path
, "/usr/lib/", 9) == 0) || (strncmp(path
, "/System/Library/", 16) == 0) );
4290 void Options::reconfigureDefaults()
4292 // sync reader options
4293 switch ( fOutputKind
) {
4294 case Options::kObjectFile
:
4295 fForFinalLinkedImage
= false;
4297 case Options::kDyld
:
4299 fForFinalLinkedImage
= true;
4302 case Options::kDynamicLibrary
:
4303 case Options::kDynamicBundle
:
4304 case Options::kKextBundle
:
4305 fForFinalLinkedImage
= true;
4308 case Options::kDynamicExecutable
:
4309 case Options::kStaticExecutable
:
4310 case Options::kPreload
:
4311 fLinkingMainExecutable
= true;
4312 fForFinalLinkedImage
= true;
4317 // set default min OS version
4318 if ( platforms().empty() ) {
4319 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
4320 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) )
4321 warning("No version-min specified on command line");
4322 const char* macVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
4323 const char* iPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
4324 const char* iOSVers
= getenv("IOS_DEPLOYMENT_TARGET");
4325 const char* wOSVers
= getenv("WATCHOS_DEPLOYMENT_TARGET");
4326 if ( macVers
!= NULL
)
4327 setVersionMin(ld::kPlatform_macOS
, macVers
);
4328 else if ( iPhoneVers
!= NULL
)
4329 setVersionMin(ld::kPlatform_iOS
, iPhoneVers
);
4330 else if ( iOSVers
!= NULL
)
4331 setVersionMin(ld::kPlatform_iOS
, iOSVers
);
4332 else if ( wOSVers
!= NULL
)
4333 setVersionMin(ld::kPlatform_watchOS
, wOSVers
);
4335 // if still nothing, set default based on architecture
4336 switch ( fArchitecture
) {
4338 case CPU_TYPE_X86_64
:
4339 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
4340 #ifdef DEFAULT_MACOSX_MIN_VERSION
4341 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION
);
4342 setVersionMin(ld::kPlatform_macOS
, DEFAULT_MACOSX_MIN_VERSION
);
4344 warning("-macosx_version_min not specified, assuming 10.6");
4345 setVersionMin(ld::kPlatform_macOS
, "10.6");
4350 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
4351 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
4352 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION
);
4353 setVersionMin(ld::kPlatformiOS
, DEFAULT_IPHONEOS_MIN_VERSION
);
4355 if ( fSubArchitecture
== CPU_SUBTYPE_ARM_V7K
) {
4356 warning("-watchos_version_min not specified, assuming 2.0");
4357 setVersionMin(ld::kPlatform_watchOS
, "2.0");
4360 warning("-ios_version_min not specified, assuming 6.0");
4361 setVersionMin(ld::kPlatform_iOS
, "6.0");
4367 // architecture will be infered later by examining .o files
4373 __block
ld::VersionSet platformOverrides
;
4374 // adjust min based on architecture
4375 platforms().forEach(^(ld::Platform platform
, uint32_t version
, bool &stop
) {
4376 if ( (fArchitecture
== CPU_TYPE_I386
|| fArchitecture
== CPU_TYPE_X86_64
)
4377 && platform
== ld::kPlatform_macOS
&& !platforms().minOS(ld::mac10_4
) ) {
4378 platformOverrides
.add(ld::mac10_4
);
4379 } else if (fArchitecture
== CPU_TYPE_ARM64
&& platform
== ld::kPlatform_iOS
4380 && !platforms().minOS(ld::iOS_7_0
)) {
4381 platformOverrides
.add(ld::iOS_7_0
);
4385 // Insert the overrides into fPlatfroms
4386 platformOverrides
.forEach(^(ld::Platform platform
, uint32_t version
, bool &stop
) {
4387 fPlatforms
.add({platform
, version
});
4390 // default to adding functions start for dynamic code, static code must opt-in
4391 switch ( fOutputKind
) {
4392 case Options::kPreload
:
4393 case Options::kStaticExecutable
:
4394 case Options::kKextBundle
:
4395 if ( fDataInCodeInfoLoadCommandForcedOn
)
4396 fDataInCodeInfoLoadCommand
= true;
4397 if ( fFunctionStartsForcedOn
)
4398 fFunctionStartsLoadCommand
= true;
4400 case Options::kObjectFile
:
4401 if ( !fDataInCodeInfoLoadCommandForcedOff
)
4402 fDataInCodeInfoLoadCommand
= true;
4403 if ( fFunctionStartsForcedOn
)
4404 fFunctionStartsLoadCommand
= true;
4406 case Options::kDynamicExecutable
:
4407 case Options::kDyld
:
4408 case Options::kDynamicLibrary
:
4409 case Options::kDynamicBundle
:
4410 if ( !fDataInCodeInfoLoadCommandForcedOff
)
4411 fDataInCodeInfoLoadCommand
= true;
4412 if ( !fFunctionStartsForcedOff
)
4413 fFunctionStartsLoadCommand
= true;
4417 // adjust kext type based on architecture
4418 if ( fOutputKind
== kKextBundle
) {
4419 switch ( fArchitecture
) {
4420 case CPU_TYPE_X86_64
:
4421 // x86_64 uses new MH_KEXT_BUNDLE type
4422 fMakeCompressedDyldInfo
= false;
4423 fMakeCompressedDyldInfoForceOff
= true;
4424 fAllowTextRelocs
= true;
4425 fUndefinedTreatment
= kUndefinedDynamicLookup
;
4427 case CPU_TYPE_ARM64
:
4428 // arm64 uses new MH_KEXT_BUNDLE type
4429 fMakeCompressedDyldInfo
= false;
4430 fMakeCompressedDyldInfoForceOff
= true;
4431 fAllowTextRelocs
= false;
4432 fKextsUseStubs
= true;
4433 fUndefinedTreatment
= kUndefinedDynamicLookup
;
4436 fMakeCompressedDyldInfo
= false;
4437 fMakeCompressedDyldInfoForceOff
= true;
4438 fAllowTextRelocs
= false;
4439 fKextsUseStubs
= !fAllowTextRelocs
;
4440 fUndefinedTreatment
= kUndefinedDynamicLookup
;
4444 fOutputKind
= kObjectFile
;
4449 // disable implicit dylibs when targeting 10.3
4450 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
4451 if ( !platforms().minOS(ld::version2007
) )
4452 fImplicitlyLinkPublicDylibs
= false;
4454 // set too-large size
4455 switch ( fArchitecture
) {
4457 fMaxAddress
= 0xFFFFFFFF;
4459 case CPU_TYPE_X86_64
:
4462 switch ( fOutputKind
) {
4463 case Options::kDynamicExecutable
:
4464 case Options::kDynamicLibrary
:
4465 case Options::kDynamicBundle
:
4466 // user land code is limited to low 1GB
4467 fMaxAddress
= 0x2FFFFFFF;
4469 case Options::kStaticExecutable
:
4470 case Options::kObjectFile
:
4471 case Options::kDyld
:
4472 case Options::kPreload
:
4473 case Options::kKextBundle
:
4474 fMaxAddress
= 0xFFFFFFFF;
4477 // range check -seg1addr for ARM
4478 if ( fBaseAddress
> fMaxAddress
) {
4479 warning("ignoring -seg1addr 0x%08llX. Address out of range.", fBaseAddress
);
4485 // determine if info for shared region should be added
4486 if ( fOutputKind
== Options::kDynamicLibrary
) {
4487 if ( platforms().minOS(ld::version2008Fall
) )
4488 if ( !fSharedRegionEligibleForceOff
)
4489 if ( sharedCacheEligiblePath(this->installPath()) )
4490 fSharedRegionEligible
= true;
4492 else if ( fOutputKind
== Options::kDyld
) {
4493 // <rdar://problem/10111122> Enable dyld to be put into the dyld shared cache
4494 fSharedRegionEligible
= true;
4497 // automatically use __DATA_CONST in dylibs on all platforms except macOS
4498 if ( fSharedRegionEligible
&& !fUseDataConstSegmentForceOff
4499 && !platforms().contains(ld::kPlatform_macOS
) && !targetIOSSimulator()) {
4500 fUseDataConstSegment
= true;
4502 if ( fUseDataConstSegmentForceOn
) {
4503 fUseDataConstSegment
= true;
4505 // A -kext for iOS 10 ==> -data_const, -text_exec, -add_split_seg_info
4506 if ( (fOutputKind
== Options::kKextBundle
) && (fArchitecture
== CPU_TYPE_ARM64
) ) {
4507 fUseDataConstSegment
= true;
4508 fUseTextExecSegment
= true;
4509 fSharedRegionEligible
= true;
4511 if ( fUseDataConstSegment
) {
4512 addSectionRename("__DATA", "__got", "__DATA_CONST", "__got");
4514 #if SUPPORT_ARCH_arm64e
4515 addSectionRename("__DATA", "__auth_got", "__DATA_CONST", "__auth_got");
4517 addSectionRename("__DATA", "__la_symbol_ptr", "__DATA_CONST", "__la_symbol_ptr");
4518 addSectionRename("__DATA", "__nl_symbol_ptr", "__DATA_CONST", "__nl_symbol_ptr");
4519 addSectionRename("__DATA", "__const", "__DATA_CONST", "__const");
4520 addSectionRename("__DATA", "__cfstring", "__DATA_CONST", "__cfstring");
4521 addSectionRename("__DATA", "__mod_init_func", "__DATA_CONST", "__mod_init_func");
4522 addSectionRename("__DATA", "__mod_term_func", "__DATA_CONST", "__mod_term_func");
4523 addSectionRename("__DATA", "__objc_classlist", "__DATA_CONST", "__objc_classlist");
4524 addSectionRename("__DATA", "__objc_nlclslist", "__DATA_CONST", "__objc_nlclslist");
4525 addSectionRename("__DATA", "__objc_catlist", "__DATA_CONST", "__objc_catlist");
4526 addSectionRename("__DATA", "__objc_nlcatlist", "__DATA_CONST", "__objc_nlcatlist");
4527 addSectionRename("__DATA", "__objc_protolist", "__DATA_CONST", "__objc_protolist");
4528 addSectionRename("__DATA", "__objc_imageinfo", "__DATA_CONST", "__objc_imageinfo");
4529 addSectionRename("__DATA", "__objc_const", "__DATA_CONST", "__objc_const");
4531 if ( fUseTextExecSegment
) {
4532 addSectionRename("__TEXT", "__text", "__TEXT_EXEC", "__text");
4533 addSectionRename("__TEXT", "__stubs", "__TEXT_EXEC", "__stubs");
4536 // Use V2 shared cache info when targetting newer OSs
4537 if ( fSharedRegionEligible
&& platforms().minOS(ld::supportsSplitSegV2
)) {
4538 fSharedRegionEncodingV2
= true;
4539 if ( platforms().contains(ld::kPlatform_macOS
) ) {
4540 fSharedRegionEncodingV2
= false;
4541 // <rdar://problem/24772435> only use v2 for Swift dylibs on Mac OS X
4542 if ( strncmp(this->installPath(), "/System/Library/PrivateFrameworks/Swift/", 40) == 0 )
4543 fSharedRegionEncodingV2
= true;
4544 // <rdar://problem/32525720> use v2 for ABI stable Swift dylibs on macOS
4545 if ( strncmp(this->installPath(), "/System/Library/Frameworks/Swift/", 33) == 0 )
4546 fSharedRegionEncodingV2
= true;
4547 // <rdar://problem/31428120> an other OS frameworks that use swift need v2
4548 for (const char* searchPath
: fLibrarySearchPaths
) {
4549 if ( strstr(searchPath
, "xctoolchain/usr/lib/swift/macos") != NULL
) {
4550 fSharedRegionEncodingV2
= true;
4555 fIgnoreOptimizationHints
= true;
4558 // <rdar://problem/5366363> -r -x implies -S
4559 if ( (fOutputKind
== Options::kObjectFile
) && (fLocalSymbolHandling
== kLocalSymbolsNone
) )
4560 fDebugInfoStripping
= Options::kDebugInfoNone
;
4562 // <rdar://problem/15252891> -r implies -no_uuid
4563 if ( fOutputKind
== Options::kObjectFile
)
4564 fUUIDMode
= kUUIDNone
;
4566 // choose how to process unwind info
4567 switch ( fArchitecture
) {
4569 case CPU_TYPE_X86_64
:
4570 case CPU_TYPE_ARM64
:
4571 switch ( fOutputKind
) {
4572 case Options::kObjectFile
:
4573 case Options::kStaticExecutable
:
4574 case Options::kPreload
:
4575 case Options::kKextBundle
:
4576 fAddCompactUnwindEncoding
= false;
4578 case Options::kDyld
:
4579 case Options::kDynamicLibrary
:
4580 case Options::kDynamicBundle
:
4581 case Options::kDynamicExecutable
:
4582 //if ( fAddCompactUnwindEncoding && (fVersionMin >= ld::mac10_6) )
4583 // fRemoveDwarfUnwindIfCompactExists = true;
4588 if ( armUsesZeroCostExceptions() ) {
4589 switch ( fOutputKind
) {
4590 case Options::kObjectFile
:
4591 case Options::kStaticExecutable
:
4592 case Options::kPreload
:
4593 case Options::kKextBundle
:
4594 fAddCompactUnwindEncoding
= false;
4596 case Options::kDyld
:
4597 case Options::kDynamicLibrary
:
4598 case Options::kDynamicBundle
:
4599 case Options::kDynamicExecutable
:
4600 fAddCompactUnwindEncoding
= true;
4605 fAddCompactUnwindEncoding
= false;
4606 fRemoveDwarfUnwindIfCompactExists
= false;
4610 // if -arch is missing, assume we don't want compact unwind info
4611 fAddCompactUnwindEncoding
= false;
4615 // only iOS executables should be encryptable
4616 switch ( fOutputKind
) {
4617 case Options::kObjectFile
:
4618 case Options::kDyld
:
4619 case Options::kStaticExecutable
:
4620 case Options::kPreload
:
4621 case Options::kKextBundle
:
4622 fEncryptable
= false;
4624 case Options::kDynamicExecutable
:
4626 case Options::kDynamicLibrary
:
4627 case Options::kDynamicBundle
:
4628 // <rdar://problem/16293398> Add LC_ENCRYPTION_INFO load command to bundled frameworks
4629 if ( !platforms().minOS(ld::version2013
) )
4630 fEncryptable
= false;
4633 if ( (fArchitecture
!= CPU_TYPE_ARM
) && (fArchitecture
!= CPU_TYPE_ARM64
)
4635 fEncryptable
= false;
4636 if ( fEncryptableForceOn
)
4637 fEncryptable
= true;
4638 else if ( fEncryptableForceOff
)
4639 fEncryptable
= false;
4641 // don't move inits in dyld because dyld wants certain
4642 // entries point at stable locations at the start of __text
4643 if ( fOutputKind
== Options::kDyld
)
4644 fAutoOrderInitializers
= false;
4647 // disable __data ordering for some output kinds
4648 switch ( fOutputKind
) {
4649 case Options::kObjectFile
:
4650 case Options::kDyld
:
4651 case Options::kStaticExecutable
:
4652 case Options::kPreload
:
4653 case Options::kKextBundle
:
4656 case Options::kDynamicExecutable
:
4657 case Options::kDynamicLibrary
:
4658 case Options::kDynamicBundle
:
4662 // only use compressed LINKEDIT for final linked images
4663 switch ( fOutputKind
) {
4664 case Options::kDynamicExecutable
:
4665 case Options::kDynamicLibrary
:
4666 case Options::kDynamicBundle
:
4668 case Options::kDyld
:
4669 // arm64e has support for compressed LINKEDIT.
4670 if ( (fArchitecture
== CPU_TYPE_ARM64
) && (fSubArchitecture
== CPU_SUBTYPE_ARM64_E
) )
4672 case Options::kPreload
:
4673 case Options::kStaticExecutable
:
4674 case Options::kObjectFile
:
4675 case Options::kKextBundle
:
4676 fMakeCompressedDyldInfoForceOff
= true;
4680 // only use legacy LINKEDIT if compressed LINKEDIT is forced off of:
4681 // macOS before 10.6
4683 if ( fMakeCompressedDyldInfoForceOff
|| !platforms().minOS(ld::version2009
) )
4684 fMakeCompressedDyldInfo
= false;
4686 // only ARM and x86_64 enforces that cpu-sub-types must match
4687 switch ( fArchitecture
) {
4689 case CPU_TYPE_ARM64
:
4691 case CPU_TYPE_X86_64
:
4692 fEnforceDylibSubtypesMatch
= false;
4695 fEnforceDylibSubtypesMatch
= false;
4700 // only final linked images can not optimize zero fill sections
4701 if ( fOutputKind
== Options::kObjectFile
)
4702 fOptimizeZeroFill
= true;
4704 // all undefines in -r mode
4705 // if ( fOutputKind == Options::kObjectFile )
4706 // fUndefinedTreatment = kUndefinedSuppress;
4708 // only dynamic final linked images should warn about use of commmons
4709 if ( fWarnCommons
) {
4710 switch ( fOutputKind
) {
4711 case Options::kDynamicExecutable
:
4712 case Options::kDynamicLibrary
:
4713 case Options::kDynamicBundle
:
4715 case Options::kPreload
:
4716 case Options::kStaticExecutable
:
4717 case Options::kObjectFile
:
4718 case Options::kDyld
:
4719 case Options::kKextBundle
:
4720 fWarnCommons
= false;
4725 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
4726 if ( platforms().minOS(ld::version2008
) )
4727 fUseSimplifiedDylibReExports
= true;
4729 // Mac OS X 10.7 and iOS 4.2 support LC_LOAD_UPWARD_DYLIB
4730 if ( platforms().minOS(ld::version2010
) && (fOutputKind
== kDynamicLibrary
) )
4731 fCanUseUpwardDylib
= true;
4733 if (fArchitecture
== CPU_TYPE_ARM64
) {
4734 #if SUPPORT_ARCH_arm64e
4735 if (fSubArchitecture
== CPU_SUBTYPE_ARM64_E
)
4737 // FIXME: Move some of these to arm64
4738 fNoLazyBinding
= true;
4739 switch ( fOutputKind
) {
4740 case Options::kDynamicExecutable
:
4741 case Options::kDynamicLibrary
:
4742 case Options::kDynamicBundle
:
4743 case Options::kDyld
:
4744 fUseLinkedListBinding
= true;
4745 fUseAuthenticatedStubs
= true;
4747 case Options::kPreload
:
4748 case Options::kStaticExecutable
:
4749 case Options::kObjectFile
:
4750 case Options::kKextBundle
:
4753 switch ( fOutputKind
) {
4754 case Options::kDynamicExecutable
:
4755 case Options::kDyld
:
4756 case Options::kDynamicLibrary
:
4757 case Options::kObjectFile
:
4758 case Options::kDynamicBundle
:
4759 case Options::kKextBundle
:
4760 fSupportsAuthenticatedPointers
= true;
4762 case Options::kStaticExecutable
:
4763 case Options::kPreload
:
4764 fSupportsAuthenticatedPointers
= false;
4771 if ( fMakeThreadedStartsSection
&& (fArchitecture
!= CPU_TYPE_ARM64
) ) {
4772 // Threaded starts isn't valid here so ignore it.
4773 warning("-threaded_starts_section ignored ignored for non-arm64");
4774 fMakeThreadedStartsSection
= false;
4777 if (fMakeThreadedStartsSection
) {
4778 switch ( fOutputKind
) {
4779 case Options::kDynamicExecutable
:
4780 case Options::kDyld
:
4781 case Options::kDynamicLibrary
:
4782 case Options::kObjectFile
:
4783 case Options::kDynamicBundle
:
4784 case Options::kKextBundle
:
4785 // Threaded starts isn't valid here so ignore it.
4786 warning("-threaded_starts_section ignored for binaries other than -static or -preload");
4787 fMakeThreadedStartsSection
= false;
4789 case Options::kStaticExecutable
:
4790 case Options::kPreload
:
4791 fUseLinkedListBinding
= true;
4792 fNoLazyBinding
= true;
4793 #if SUPPORT_ARCH_arm64e
4794 if ( (fArchitecture
== CPU_TYPE_ARM64
) && (fSubArchitecture
== CPU_SUBTYPE_ARM64_E
) )
4795 fSupportsAuthenticatedPointers
= true;
4801 // Weak binding requires that if we want to use linked list binding, we must
4802 // also be using no lazy binding.
4803 if ( fUseLinkedListBinding
)
4804 assert(fNoLazyBinding
);
4806 // MacOSX 10.7 defaults to PIE
4807 if ( (fArchitecture
== CPU_TYPE_I386
)
4808 && (fOutputKind
== kDynamicExecutable
)
4809 && platforms().minOS(ld::mac10_7
) ) {
4810 fPositionIndependentExecutable
= true;
4813 // armv7 for iOS4.3 defaults to PIE
4814 if ( (fArchitecture
== CPU_TYPE_ARM
)
4815 && fArchSupportsThumb2
4816 && (fOutputKind
== kDynamicExecutable
)
4817 && (platforms().contains(ld::kPlatform_watchOS
) || platforms().minOS(ld::iOS_4_3
)) ) {
4818 fPositionIndependentExecutable
= true;
4821 // <rdar://problem/24535196> x86_64 defaults PIE (for 10.6 and later)
4822 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
== kDynamicExecutable
) && (platforms().minOS(ld::mac10_6
) || platforms().contains(ld::kPlatform_iOSMac
)) )
4823 fPositionIndependentExecutable
= true;
4825 // Simulator defaults to PIE
4826 if ( targetIOSSimulator() && (fOutputKind
== kDynamicExecutable
) )
4827 fPositionIndependentExecutable
= true;
4829 // -no_pie anywhere on command line disable PIE
4830 if ( fDisablePositionIndependentExecutable
)
4831 fPositionIndependentExecutable
= false;
4833 // arm64 is always PIE
4834 if ( ((fArchitecture
== CPU_TYPE_ARM64
)
4836 && (fOutputKind
== kDynamicExecutable
) ) {
4837 fPositionIndependentExecutable
= true;
4838 if ( fDisablePositionIndependentExecutable
)
4839 warning("-no_pie ignored for arm64");
4842 // set fOutputSlidable
4843 switch ( fOutputKind
) {
4844 case Options::kObjectFile
:
4845 fOutputSlidable
= false;
4847 case Options::kStaticExecutable
:
4848 case Options::kDynamicExecutable
:
4849 fOutputSlidable
= fPositionIndependentExecutable
;
4851 case Options::kPreload
:
4852 fOutputSlidable
= fPIEOnCommandLine
;
4854 case Options::kDyld
:
4855 case Options::kDynamicLibrary
:
4856 case Options::kDynamicBundle
:
4857 case Options::kKextBundle
:
4858 fOutputSlidable
= true;
4862 // Let linker know if thread local variables are supported
4863 // This is more complex than normal version checks since
4864 // runtime support varies by architecture
4865 if (platforms().minOS(ld::supportsTLV
)
4866 || ((fArchitecture
== CPU_TYPE_ARM64
) && platforms().minOS(ld::iOS_8_0
))
4867 || ((fArchitecture
== CPU_TYPE_X86_64
) && platforms().minOS(ld::iOS_9_0
))) {
4871 // default to adding version load command for dynamic code, static code must opt-in
4872 switch ( fOutputKind
) {
4873 case Options::kObjectFile
:
4874 fVersionLoadCommand
= false;
4876 case Options::kStaticExecutable
:
4877 case Options::kPreload
:
4878 case Options::kKextBundle
:
4879 if ( fVersionLoadCommandForcedOn
)
4880 fVersionLoadCommand
= true;
4882 case Options::kDynamicExecutable
:
4883 case Options::kDyld
:
4884 case Options::kDynamicLibrary
:
4885 case Options::kDynamicBundle
:
4886 if ( !fVersionLoadCommandForcedOff
)
4887 fVersionLoadCommand
= true;
4891 // support re-export of individual symbols in MacOSX 10.7 and iOS 4.2
4892 if ( (fOutputKind
== kDynamicLibrary
) && platforms().minOS(ld::version2010
) )
4893 fCanReExportSymbols
= true;
4895 // ObjC optimization is only in dynamic final linked images
4896 switch ( fOutputKind
) {
4897 case Options::kObjectFile
:
4898 case Options::kStaticExecutable
:
4899 case Options::kPreload
:
4900 case Options::kKextBundle
:
4901 case Options::kDyld
:
4902 fObjcCategoryMerging
= false;
4904 case Options::kDynamicExecutable
:
4905 case Options::kDynamicLibrary
:
4906 case Options::kDynamicBundle
:
4910 // i386 main executables linked on Mac OS X 10.7 default to NX heap
4911 // regardless of target unless overriden with -allow_heap_execute anywhere
4912 // on the command line
4913 if ( (fArchitecture
== CPU_TYPE_I386
) && (fOutputKind
== kDynamicExecutable
) && !fDisableNonExecutableHeap
)
4914 fNonExecutableHeap
= true;
4916 // Use LC_MAIN instead of LC_UNIXTHREAD for newer OSs
4917 switch ( fOutputKind
) {
4918 case Options::kDynamicExecutable
:
4919 // <rdar://problem/16310363> Linker should look for "_main" not "start" when building for sim regardless of min OS
4920 if ( platforms().minOS(ld::version2012
) ) {
4921 fEntryPointLoadCommand
= true;
4922 if ( fEntryName
== NULL
)
4923 fEntryName
= "_main";
4924 if ( strcmp(fEntryName
, "start") == 0 ) {
4925 warning("Ignoring '-e start' because entry point 'start' is not used for the targeted OS version");
4926 fEntryName
= "_main";
4930 fNeedsThreadLoadCommand
= true;
4931 if ( fEntryName
== NULL
)
4932 fEntryName
= "start";
4935 case Options::kObjectFile
:
4936 case Options::kKextBundle
:
4937 case Options::kDynamicLibrary
:
4938 case Options::kDynamicBundle
:
4941 case Options::kStaticExecutable
:
4942 case Options::kPreload
:
4943 case Options::kDyld
:
4944 fNeedsThreadLoadCommand
= true;
4945 if ( fEntryName
== NULL
)
4946 fEntryName
= "start"; // Perhaps these should have no default and require -e
4950 // add LC_SOURCE_VERSION
4951 switch ( fOutputKind
) {
4952 case Options::kDynamicExecutable
:
4953 case Options::kKextBundle
:
4954 case Options::kDynamicLibrary
:
4955 case Options::kDynamicBundle
:
4956 case Options::kDyld
:
4957 case Options::kStaticExecutable
:
4958 if ( fSourceVersionLoadCommandForceOn
) {
4959 fSourceVersionLoadCommand
= true;
4961 else if ( fSourceVersionLoadCommandForceOff
) {
4962 fSourceVersionLoadCommand
= false;
4965 if ( platforms().minOS(ld::version2012
) ) {
4966 fSourceVersionLoadCommand
= true;
4969 fSourceVersionLoadCommand
= false;
4972 case Options::kObjectFile
:
4973 case Options::kPreload
:
4974 fSourceVersionLoadCommand
= false;
4978 // if -sdk_version not on command line, infer from -syslibroot
4979 if ( (fSDKVersion
== 0) && (fSDKPaths
.size() > 0) ) {
4980 const char* sdkPath
= fSDKPaths
.front();
4981 const char* end
= &sdkPath
[strlen(sdkPath
)-1];
4982 while ( !isdigit(*end
) && (end
> sdkPath
) )
4984 const char* start
= end
-1;
4985 while ( (isdigit(*start
) || (*start
== '.')) && (start
> sdkPath
))
4987 char sdkVersionStr
[32];
4988 int len
= end
-start
+1;
4990 strlcpy(sdkVersionStr
, start
+1, len
);
4991 fSDKVersion
= parseVersionNumber32(sdkVersionStr
);
4995 // if -sdk_version and -syslibroot not used, but targeting MacOSX, use current OS version
4996 if ( (fSDKVersion
== 0) && platforms().contains(ld::kPlatform_macOS
) ) {
4997 // special case if RC_ProjectName and MACOSX_DEPLOYMENT_TARGET are both set that sdkversion=minos
4998 if ( getenv("RC_ProjectName") && getenv("MACOSX_DEPLOYMENT_TARGET") ) {
4999 fSDKVersion
= platforms().minOS(ld::kPlatform_macOS
);
5002 int mib
[2] = { CTL_KERN
, KERN_OSRELEASE
};
5003 char kernVersStr
[100];
5004 size_t strlen
= sizeof(kernVersStr
);
5005 if ( sysctl(mib
, 2, kernVersStr
, &strlen
, NULL
, 0) != -1 ) {
5006 uint32_t kernVers
= parseVersionNumber32(kernVersStr
);
5007 int minor
= (kernVers
>> 16) - 4; // kernel major version is 4 ahead of x in 10.x
5008 fSDKVersion
= 0x000A0000 + (minor
<< 8);
5013 // allow trie based absolute symbols if targeting new enough OS
5014 if ( fMakeCompressedDyldInfo
) {
5015 if ( platforms().minOS(ld::version2013
) ) {
5016 fAbsoluteSymbols
= true;
5020 // <rdar://problem/13070042> Only third party apps should have 16KB page segments by default
5021 if ( fEncryptable
) {
5022 if ( fSegmentAlignment
== 4096 )
5023 fSegmentAlignment
= 4096*4;
5026 // <rdar://problem/12258065> ARM64 needs 16KB page size for user land code
5027 // <rdar://problem/15974532> make armv7[s] use 16KB pages in user land code for iOS 8 or later
5028 if ( fSegmentAlignment
== 4096 ) {
5029 switch ( fOutputKind
) {
5030 case Options::kDynamicExecutable
:
5031 case Options::kDynamicLibrary
:
5032 case Options::kDynamicBundle
:
5033 case Options::kDyld
:
5034 // <rdar://problem/14676611> 16KB segments for arm64 kexts
5035 if ( (fArchitecture
== CPU_TYPE_ARM64
)
5036 || (fArchitecture
== CPU_TYPE_ARM
) ) {
5037 fSegmentAlignment
= 4096*4;
5040 case Options::kStaticExecutable
:
5041 case Options::kKextBundle
:
5042 // <rdar://problem/14676611> 16KB segments for arm64 kexts
5043 if ( (fArchitecture
== CPU_TYPE_ARM64
)
5045 fSegmentAlignment
= 4096*4;
5048 case Options::kObjectFile
:
5049 case Options::kPreload
:
5056 // <rdar://problem/13624134> linker should not convert dwarf unwind if .o file has compact unwind section
5057 switch ( fOutputKind
) {
5058 case Options::kDynamicExecutable
:
5059 case Options::kDynamicLibrary
:
5060 case Options::kDynamicBundle
:
5061 case Options::kDyld
:
5062 if ( fKeepDwarfUnwindForcedOn
) {
5063 fKeepDwarfUnwind
= true;
5065 else if ( fKeepDwarfUnwindForcedOff
) {
5066 fKeepDwarfUnwind
= false;
5069 if ( platforms().minOS(ld::version2013
) )
5070 fKeepDwarfUnwind
= false;
5072 fKeepDwarfUnwind
= true;
5075 case Options::kKextBundle
:
5076 case Options::kStaticExecutable
:
5077 case Options::kObjectFile
:
5078 case Options::kPreload
:
5079 fKeepDwarfUnwind
= true;
5083 // Make sure -image_base matches alignment
5084 uint64_t alignedBaseAddress
= (fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
);
5085 if ( alignedBaseAddress
!= fBaseAddress
) {
5086 warning("base address 0x%llX is not properly aligned. Changing it to 0x%llX", fBaseAddress
, alignedBaseAddress
);
5087 fBaseAddress
= alignedBaseAddress
;
5090 // If -dirty_data_list not specified, look in $SDKROOT/AppleInternal/DirtyDataFiles/<dylib>.dirty for dirty data list
5091 if ( fSymbolsMovesData
.empty() && fUseDataConstSegment
&& ( fDylibInstallName
!= NULL
) && !fSDKPaths
.empty() ) {
5092 const char* dylibLeaf
= strrchr(fDylibInstallName
, '/');
5094 char path
[PATH_MAX
];
5095 strlcpy(path
, fSDKPaths
.front(), sizeof(path
));
5096 strlcat(path
, "/AppleInternal/DirtyDataFiles", sizeof(path
));
5097 strlcat(path
, dylibLeaf
, sizeof(path
));
5098 strlcat(path
, ".dirty", sizeof(path
));
5100 if ( info
.checkFileExists(*this, path
) )
5101 addSymbolMove("__DATA_DIRTY", path
, fSymbolsMovesData
, "-dirty_data_list");
5106 // Look in $SDKROOT/AppleInternal/AccessibilityLinkerSymbols/<dylib>.axsymbols for objc-class names
5107 if ( fUseDataConstSegment
&& (fDylibInstallName
!= NULL
) && !fSDKPaths
.empty() ) {
5108 const char* dylibLeaf
= strrchr(fDylibInstallName
, '/');
5110 char path
[PATH_MAX
];
5111 strlcpy(path
, fSDKPaths
.front(), sizeof(path
));
5112 strlcat(path
, "/AppleInternal/AccessibilityLinkerSymbols", sizeof(path
));
5113 strlcat(path
, dylibLeaf
, sizeof(path
));
5114 strlcat(path
, ".axsymbols", sizeof(path
));
5116 if ( info
.checkFileExists(*this, path
) ) {
5118 fSymbolsMovesAXMethodLists
.push_back(tmp
);
5119 loadExportFile(path
, ".axsymbols", fSymbolsMovesAXMethodLists
.back().symbols
);
5124 // <rdar://problem/32138080> Automatically use OrderFiles found in the AppleInternal SDK
5125 if ( (fFinalName
!= NULL
) && fOrderedSymbols
.empty() && !fSDKPaths
.empty() ) {
5126 char path
[PATH_MAX
];
5127 strlcpy(path
, fSDKPaths
.front(), sizeof(path
));
5128 strlcat(path
, "/AppleInternal/OrderFiles/", sizeof(path
));
5129 strlcat(path
, fFinalName
, sizeof(path
));
5130 strlcat(path
, ".order", sizeof(path
));
5132 if ( info
.checkFileExists(*this, path
) )
5133 parseOrderFile(path
, false);
5136 // <rdar://problem/20503811> Reduce the default alignment of structures/arrays to save memory in embedded systems
5137 if ( fMaxDefaultCommonAlign
== 0 ) {
5138 if ( fOutputKind
== Options::kPreload
)
5139 fMaxDefaultCommonAlign
= 8;
5141 fMaxDefaultCommonAlign
= 15;
5144 // Add warnings for issues likely to cause OS verification issues
5145 if ( fSharedRegionEligible
&& !fRPaths
.empty() && !fDebugVariant
) {
5146 // <rdar://problem/18719327> warn if -rpath is used with OS dylibs
5147 warning("OS dylibs should not add rpaths (linker option: -rpath) (Xcode build setting: LD_RUNPATH_SEARCH_PATHS)");
5149 if ( (fOutputKind
== Options::kDynamicLibrary
) && (fDylibInstallName
!= NULL
) && (fFinalName
!= NULL
) && sharedCacheEligiblePath(fFinalName
) && !fDebugVariant
) {
5150 if ( strncmp(fDylibInstallName
, "@rpath", 6) == 0 )
5151 warning("OS dylibs should not use @rpath for -install_name. Use absolute path instead");
5152 if ( strcmp(fDylibInstallName
, fFinalName
) != 0 ) {
5153 bool different
= true;
5154 // some projects end up with double slash in -final_output path
5155 if ( strstr(fFinalName
, "//") != NULL
) {
5156 char fixedPath
[strlen(fFinalName
)+1];
5157 char* t
= fixedPath
;
5158 bool lastWasSlash
= false;
5159 for (const char* s
=fFinalName
; *s
!= '\0'; ++s
) {
5161 if ( !lastWasSlash
)
5163 lastWasSlash
= true;
5167 lastWasSlash
= false;
5171 different
= (strcmp(fDylibInstallName
, fixedPath
) != 0);
5174 warning("OS dylibs -install_name should match its real absolute path");
5178 // set if unaligned pointers are warnings or errors
5179 if ( platforms().minOS(ld::mac10_12
) ) {
5180 // ignore unaligned pointers when targeting older macOS versions
5181 if ( fSharedRegionEligible
)
5182 fUnalignedPointerTreatment
= Options::kUnalignedPointerWarning
;
5184 fUnalignedPointerTreatment
= Options::kUnalignedPointerIgnore
;
5186 else if ( platforms().minOS(ld::iOS_10_0
) ) {
5187 #if SUPPORT_ARCH_arm64e
5188 if ( (fArchitecture
== CPU_TYPE_ARM64
) && (fSubArchitecture
== CPU_SUBTYPE_ARM64_E
) ) {
5189 fUnalignedPointerTreatment
= Options::kUnalignedPointerError
;
5192 fUnalignedPointerTreatment
= Options::kUnalignedPointerWarning
;
5195 fUnalignedPointerTreatment
= Options::kUnalignedPointerIgnore
;
5198 // warn by default for OS dylibs
5199 if ( fInitializersTreatment
== Options::kInvalid
) {
5200 if ( fSharedRegionEligible
&& (fOutputKind
== Options::kDynamicLibrary
) && !fDebugVariant
) {
5201 fInitializersTreatment
= Options::kWarning
;
5204 fInitializersTreatment
= Options::kSuppress
;
5209 void Options::checkIllegalOptionCombinations()
5211 // check -undefined setting
5212 switch ( fUndefinedTreatment
) {
5213 case kUndefinedError
:
5216 case kUndefinedDynamicLookup
: {
5217 platforms().forEach(^(ld::Platform platform
, uint32_t version
, bool &stop
) {
5219 case ld::kPlatform_macOS
:
5220 case ld::kPlatform_iOSMac
:
5221 case ld::kPlatform_unknown
:
5223 case ld::kPlatform_iOS
:
5224 case ld::kPlatform_iOSSimulator
:
5225 case ld::kPlatform_watchOS
:
5226 case ld::kPlatform_watchOSSimulator
:
5227 case ld::kPlatform_bridgeOS
:
5228 case ld::kPlatform_tvOS
:
5229 case ld::kPlatform_tvOSSimulator
:
5230 if ( fOutputKind
!= kKextBundle
)
5231 warning("-undefined dynamic_lookup is deprecated on %s", platformName(platform
));
5236 case kUndefinedWarning
:
5237 case kUndefinedSuppress
:
5238 // requires flat namespace
5239 if ( fNameSpace
== kTwoLevelNameSpace
)
5240 throw "can't use -undefined warning or suppress with -twolevel_namespace";
5244 // unify -sub_umbrella with dylibs
5245 for (std::vector
<const char*>::iterator it
= fSubUmbellas
.begin(); it
!= fSubUmbellas
.end(); it
++) {
5246 const char* subUmbrella
= *it
;
5248 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
5249 Options::FileInfo
& info
= *fit
;
5250 const char* lastSlash
= strrchr(info
.path
, '/');
5251 if ( lastSlash
== NULL
)
5252 lastSlash
= info
.path
- 1;
5253 std::string
path(&lastSlash
[1]);
5254 auto idx
= path
.find(".tbd", path
.size() - 4);
5255 if (idx
!= std::string::npos
)
5257 if ( path
== subUmbrella
) {
5258 info
.options
.fReExport
= true;
5260 fLinkSnapshot
.recordSubUmbrella(info
.path
);
5265 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella
);
5268 // unify -sub_library with dylibs
5269 for (std::vector
<const char*>::iterator it
= fSubLibraries
.begin(); it
!= fSubLibraries
.end(); it
++) {
5270 const char* subLibrary
= *it
;
5272 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
5273 Options::FileInfo
& info
= *fit
;
5274 const char* lastSlash
= strrchr(info
.path
, '/');
5275 if ( lastSlash
== NULL
)
5276 lastSlash
= info
.path
- 1;
5277 const char* dot
= strchr(&lastSlash
[1], '.');
5279 dot
= &lastSlash
[strlen(lastSlash
)];
5280 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
5281 info
.options
.fReExport
= true;
5283 fLinkSnapshot
.recordSubLibrary(info
.path
);
5288 warning("-sub_library %s does not match a supplied dylib", subLibrary
);
5291 // sync reader options
5292 if ( fNameSpace
!= kTwoLevelNameSpace
) {
5293 fFlatNamespace
= true;
5294 platforms().forEach(^(ld::Platform platform
, uint32_t version
, bool &stop
) {
5296 case ld::kPlatform_unknown
:
5297 case ld::kPlatform_macOS
:
5298 case ld::kPlatform_iOSMac
:
5300 case ld::kPlatform_iOS
:
5301 case ld::kPlatform_iOSSimulator
:
5302 case ld::kPlatform_watchOS
:
5303 case ld::kPlatform_watchOSSimulator
:
5304 case ld::kPlatform_bridgeOS
:
5305 case ld::kPlatform_tvOS
:
5306 case ld::kPlatform_tvOSSimulator
:
5307 warning("-flat_namespace is deprecated on %s", platformName(platform
));
5315 // check -stack_addr
5316 if ( fStackAddr
!= 0 ) {
5317 switch (fArchitecture
) {
5320 if ( fStackAddr
> 0xFFFFFFFF )
5321 throw "-stack_addr must be < 4G for 32-bit processes";
5323 case CPU_TYPE_X86_64
:
5324 case CPU_TYPE_ARM64
:
5327 if ( (fStackAddr
& -4096) != fStackAddr
)
5328 throw "-stack_addr must be multiples of 4K";
5329 if ( fStackSize
== 0 )
5330 throw "-stack_addr must be used with -stack_size";
5333 // check -stack_size
5334 if ( fStackSize
!= 0 ) {
5335 switch (fArchitecture
) {
5337 if ( platforms().contains(ld::kPlatform_macOS
) ) {
5338 if ( fStackSize
> 0xFFFFFFFF )
5339 throw "-stack_size must be < 4GB for 32-bit processes";
5340 if ( fStackAddr
== 0 )
5341 fStackAddr
= 0xC0000000;
5342 if ( (fStackAddr
> 0xB0000000) && ((fStackAddr
-fStackSize
) < 0xB0000000) )
5343 warning("custom stack placement overlaps and will disable shared region");
5346 if ( fStackSize
> 0x1F000000 )
5347 throw "-stack_size must be < 496MB";
5348 if ( fStackAddr
== 0 )
5349 fStackAddr
= 0xC0000000;
5353 if ( fStackSize
> 0x1F000000 )
5354 throw "-stack_size must be < 496MB";
5355 if ( fStackAddr
== 0 )
5356 fStackAddr
= 0x1F000000;
5357 if ( fStackAddr
> 0x20000000)
5358 throw "-stack_addr must be < 0x20000000 for arm";
5360 case CPU_TYPE_X86_64
:
5361 if ( platforms().contains(ld::kPlatform_macOS
) ) {
5362 if ( fStackSize
> 0x10000000000 )
5363 throw "-stack_size must be <= 1TB";
5364 if ( fStackAddr
== 0 ) {
5365 fStackAddr
= 0x00007FFF5C000000LL
;
5369 if ( fStackSize
> 0x20000000 )
5370 throw "-stack_size must be <= 512MB";
5371 if ( fStackAddr
== 0 ) {
5372 fStackAddr
= 0x120000000;
5375 case CPU_TYPE_ARM64
:
5376 if ( fStackSize
> 0x20000000 )
5377 throw "-stack_size must be <= 512MB";
5378 if ( fStackAddr
== 0 )
5379 fStackAddr
= 0x120000000;
5383 if ( (fStackSize
& (-fSegmentAlignment
)) != fStackSize
)
5384 throwf("-stack_size must be multiple of segment alignment (%lldKB)", fSegmentAlignment
/1024);
5385 switch ( fOutputKind
) {
5386 case Options::kDynamicExecutable
:
5387 case Options::kStaticExecutable
:
5388 // custom stack size only legal when building main executable
5390 case Options::kDynamicLibrary
:
5391 case Options::kDynamicBundle
:
5392 case Options::kObjectFile
:
5393 case Options::kDyld
:
5394 case Options::kPreload
:
5395 case Options::kKextBundle
:
5396 throw "-stack_size option can only be used when linking a main executable";
5398 if ( fStackSize
> fStackAddr
)
5399 throwf("-stack_size (0x%08llX) must be smaller than -stack_addr (0x%08llX)", fStackSize
, fStackAddr
);
5402 // check that -allow_stack_execute is only used with main executables
5403 if ( fExecutableStack
) {
5404 switch ( fOutputKind
) {
5405 case Options::kDynamicExecutable
:
5406 case Options::kStaticExecutable
:
5407 // -allow_stack_execute size only legal when building main executable
5409 case Options::kDynamicLibrary
:
5410 case Options::kDynamicBundle
:
5411 case Options::kObjectFile
:
5412 case Options::kDyld
:
5413 case Options::kPreload
:
5414 case Options::kKextBundle
:
5415 throw "-allow_stack_execute option can only be used when linking a main executable";
5419 // check that -allow_heap_execute is only used with i386 main executables
5420 if ( fDisableNonExecutableHeap
) {
5421 if ( fArchitecture
!= CPU_TYPE_I386
)
5422 throw "-allow_heap_execute option can only be used when linking for i386";
5423 switch ( fOutputKind
) {
5424 case Options::kDynamicExecutable
:
5425 // -allow_heap_execute only legal when building main executable
5427 case Options::kStaticExecutable
:
5428 case Options::kDynamicLibrary
:
5429 case Options::kDynamicBundle
:
5430 case Options::kObjectFile
:
5431 case Options::kDyld
:
5432 case Options::kPreload
:
5433 case Options::kKextBundle
:
5434 throw "-allow_heap_execute option can only be used when linking a main executable";
5438 // check -client_name is only used when making a bundle or main executable
5439 if ( fClientName
!= NULL
) {
5440 switch ( fOutputKind
) {
5441 case Options::kDynamicExecutable
:
5442 case Options::kDynamicBundle
:
5444 case Options::kStaticExecutable
:
5445 case Options::kDynamicLibrary
:
5446 case Options::kObjectFile
:
5447 case Options::kDyld
:
5448 case Options::kPreload
:
5449 case Options::kKextBundle
:
5450 throw "-client_name can only be used with -bundle";
5454 // check -init is only used when building a dylib
5455 if ( (fInitFunctionName
!= NULL
) && (fOutputKind
!= Options::kDynamicLibrary
) )
5456 throw "-init can only be used with -dynamiclib";
5458 // check -bundle_loader only used with -bundle
5459 if ( (fBundleLoader
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
5460 throw "-bundle_loader can only be used with -bundle";
5462 // check -dtrace not used with -r
5463 if ( (fDtraceScriptName
!= NULL
) && (fOutputKind
== Options::kObjectFile
) )
5464 throw "-dtrace can only be used when creating final linked images";
5466 // check -d can only be used with -r
5467 if ( fMakeTentativeDefinitionsReal
&& (fOutputKind
!= Options::kObjectFile
) )
5468 throw "-d can only be used with -r";
5470 // check that -root_safe is not used with -r
5471 if ( fRootSafe
&& (fOutputKind
== Options::kObjectFile
) )
5472 throw "-root_safe cannot be used with -r";
5474 // check that -setuid_safe is not used with -r
5475 if ( fSetuidSafe
&& (fOutputKind
== Options::kObjectFile
) )
5476 throw "-setuid_safe cannot be used with -r";
5478 // <rdar://problem/12781832> compiler driver no longer uses -objc_abi_version, it uses -ios_simulator_version_min instead
5479 if ( !fObjCABIVersion1Override
&& !fObjCABIVersion2Override
&& targetIOSSimulator() )
5480 fObjCABIVersion2Override
= true;
5482 // rdar://problem/4718189 map ObjC class names to new runtime names
5483 bool alterObjC1ClassNamesToObjC2
= false;
5484 switch (fArchitecture
) {
5486 // i386 only uses new symbols when using objc2 ABI
5487 if ( fObjCABIVersion2Override
)
5488 alterObjC1ClassNamesToObjC2
= true;
5490 case CPU_TYPE_X86_64
:
5492 case CPU_TYPE_ARM64
:
5493 alterObjC1ClassNamesToObjC2
= true;
5497 // make sure all required exported symbols exist
5498 std::vector
<const char*> impliedExports
;
5499 for (NameSet::iterator it
=fExportSymbols
.regularBegin(); it
!= fExportSymbols
.regularEnd(); ++it
) {
5500 const char* name
= *it
;
5501 const int len
= strlen(name
);
5502 if ( (strcmp(&name
[len
-3], ".eh") == 0) || (strncmp(name
, ".objc_category_name_", 20) == 0) ) {
5503 // never export .eh symbols
5504 warning("ignoring %s in export list", name
);
5506 else if ( (fArchitecture
== CPU_TYPE_I386
) && !fObjCABIVersion2Override
&& (strncmp(name
, "_OBJC_CLASS_$", 13) == 0) ) {
5507 warning("ignoring Objc2 Class symbol %s in i386 export list", name
);
5508 fRemovedExports
.insert(name
);
5510 else if ( alterObjC1ClassNamesToObjC2
&& (strncmp(name
, ".objc_class_name_", 17) == 0) ) {
5511 // linking ObjC2 ABI, but have ObjC1 ABI name in export list. Change it to intended name
5512 fRemovedExports
.insert(name
);
5514 asprintf(&temp
, "_OBJC_CLASS_$_%s", &name
[17]);
5515 impliedExports
.push_back(temp
);
5516 asprintf(&temp
, "_OBJC_METACLASS_$_%s", &name
[17]);
5517 impliedExports
.push_back(temp
);
5520 fInitialUndefines
.push_back(name
);
5523 fExportSymbols
.remove(fRemovedExports
);
5524 for (std::vector
<const char*>::iterator it
=impliedExports
.begin(); it
!= impliedExports
.end(); ++it
) {
5525 const char* name
= *it
;
5526 fExportSymbols
.insert(name
);
5527 fInitialUndefines
.push_back(name
);
5530 // make sure all required re-exported symbols exist
5531 for (NameSet::iterator it
=fReExportSymbols
.regularBegin(); it
!= fReExportSymbols
.regularEnd(); ++it
) {
5532 fInitialUndefines
.push_back(*it
);
5535 // make sure that -init symbol exists
5536 if ( fInitFunctionName
!= NULL
)
5537 fInitialUndefines
.push_back(fInitFunctionName
);
5539 // make sure that entry symbol exists
5540 switch ( fOutputKind
) {
5541 case Options::kDynamicExecutable
:
5542 case Options::kStaticExecutable
:
5543 case Options::kDyld
:
5544 case Options::kPreload
:
5545 fInitialUndefines
.push_back(fEntryName
);
5547 case Options::kDynamicLibrary
:
5548 case Options::kDynamicBundle
:
5549 case Options::kObjectFile
:
5550 case Options::kKextBundle
:
5554 // make sure every alias base exists
5555 for (std::vector
<AliasPair
>::iterator it
=fAliases
.begin(); it
!= fAliases
.end(); ++it
) {
5556 fInitialUndefines
.push_back(it
->realName
);
5559 // check custom segments
5560 if ( fCustomSegmentAddresses
.size() != 0 ) {
5561 // verify no segment is in zero page
5562 if ( fZeroPageSize
!= ULLONG_MAX
) {
5563 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
5564 if ( it
->address
< fZeroPageSize
)
5565 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it
->name
, it
->address
);
5568 // verify no duplicates
5569 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
5570 for (std::vector
<SegmentStart
>::iterator it2
= fCustomSegmentAddresses
.begin(); it2
!= fCustomSegmentAddresses
.end(); ++it2
) {
5571 if ( (it
->address
== it2
->address
) && (it
!= it2
) )
5572 throwf("duplicate -segaddr addresses for %s and %s", it
->name
, it2
->name
);
5574 // a custom segment address of zero will disable the use of a zero page
5575 if ( it
->address
== 0 )
5580 if ( fZeroPageSize
== ULLONG_MAX
) {
5581 // zero page size not specified on command line, set default
5582 switch (fArchitecture
) {
5585 // first 4KB for 32-bit architectures
5586 fZeroPageSize
= 0x1000;
5588 case CPU_TYPE_ARM64
:
5589 case CPU_TYPE_X86_64
:
5590 // first 4GB for x86_64 on all OS's
5591 fZeroPageSize
= 0x100000000ULL
;
5594 // if -arch not used, default to 4K zero-page
5595 fZeroPageSize
= 0x1000;
5599 switch ( fOutputKind
) {
5600 case Options::kDynamicExecutable
:
5601 case Options::kStaticExecutable
:
5602 // -pagezero_size size only legal when building main executable
5604 case Options::kDynamicLibrary
:
5605 case Options::kDynamicBundle
:
5606 case Options::kObjectFile
:
5607 case Options::kDyld
:
5608 case Options::kPreload
:
5609 case Options::kKextBundle
:
5610 if ( fZeroPageSize
!= 0 )
5611 throw "-pagezero_size option can only be used when linking a main executable";
5615 // if main executable with custom base address, model zero page as custom segment
5616 if ( (fOutputKind
== Options::kDynamicExecutable
) && (fBaseAddress
!= 0) && (fZeroPageSize
!= 0) ) {
5618 seg
.name
= "__PAGEZERO";
5620 fCustomSegmentAddresses
.push_back(seg
);
5623 // -dead_strip and -r are incompatible
5624 if ( fDeadStrip
&& (fOutputKind
== Options::kObjectFile
) )
5625 throw "-r and -dead_strip cannot be used together";
5627 // can't use -rpath unless targeting 10.5 or later
5628 if ( fRPaths
.size() > 0 ) {
5629 if ( !platforms().minOS(ld::version2008
) )
5630 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
5631 switch ( fOutputKind
) {
5632 case Options::kDynamicExecutable
:
5633 case Options::kDynamicLibrary
:
5634 case Options::kDynamicBundle
:
5636 case Options::kStaticExecutable
:
5637 case Options::kObjectFile
:
5638 case Options::kDyld
:
5639 case Options::kPreload
:
5640 case Options::kKextBundle
:
5641 throw "-rpath can only be used when creating a dynamic final linked image";
5645 if ( fPositionIndependentExecutable
) {
5646 switch ( fOutputKind
) {
5647 case Options::kDynamicExecutable
:
5648 // check -pie is only used when building a dynamic main executable for 10.5
5649 if ( !platforms().minOS(ld::supportsPIE
) ) {
5650 throw "-pie requires targetting a newer minimum version";
5653 case Options::kStaticExecutable
:
5654 case Options::kPreload
:
5655 // -pie is ok with -static or -preload
5657 case Options::kDynamicLibrary
:
5658 case Options::kDynamicBundle
:
5659 warning("-pie being ignored. It is only used when linking a main executable");
5660 fPositionIndependentExecutable
= false;
5662 case Options::kObjectFile
:
5663 case Options::kDyld
:
5664 case Options::kKextBundle
:
5665 throw "-pie can only be used when linking a main executable";
5669 // check -read_only_relocs is not used with x86_64 or arm64
5670 if ( fAllowTextRelocs
) {
5671 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
!= kKextBundle
) ) {
5672 warning("-read_only_relocs cannot be used with x86_64");
5673 fAllowTextRelocs
= false;
5675 else if ( fArchitecture
== CPU_TYPE_ARM64
) {
5676 warning("-read_only_relocs cannot be used with arm64");
5680 // check -mark_auto_dead_strip is only used with dylibs
5681 if ( fMarkDeadStrippableDylib
) {
5682 if ( fOutputKind
!= Options::kDynamicLibrary
) {
5683 warning("-mark_auto_dead_strip can only be used when creating a dylib");
5684 fMarkDeadStrippableDylib
= false;
5688 // -force_cpusubtype_ALL is not supported for ARM
5689 if ( fForceSubtypeAll
) {
5690 if ( fArchitecture
== CPU_TYPE_ARM
) {
5691 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
5695 // -reexported_symbols_list can only be used with -dynamiclib
5696 if ( !fReExportSymbols
.empty() ) {
5697 if ( fOutputKind
!= Options::kDynamicLibrary
)
5698 throw "-reexported_symbols_list can only used used when created dynamic libraries";
5699 if ( !platforms().minOS(ld::version2010
) )
5700 throw "targeted OS version does not support -reexported_symbols_list";
5703 // -dyld_env can only be used with main executables
5704 if ( (fOutputKind
!= Options::kDynamicExecutable
) && (fDyldEnvironExtras
.size() != 0) )
5705 throw "-dyld_env can only used used when created main executables";
5707 // -segment_order can only be used with -preload or -static
5708 if ( !fSegmentOrder
.empty() && ((fOutputKind
!= Options::kPreload
) && (fOutputKind
!= kStaticExecutable
)) )
5709 throw "-segment_order can only used used with -preload output";
5711 // warn about bitcode option combinations
5712 if ( !fBundleBitcode
) {
5713 if ( fVerifyBitcode
)
5714 warning("-bitcode_verify is ignored without -bitcode_bundle");
5715 else if ( fHideSymbols
)
5716 warning("-bitcode_hide_symbols is ignored without -bitcode_bundle");
5718 if ( fReverseMapPath
!= NULL
&& !fHideSymbols
) {
5719 throw "-bitcode_symbol_map can only be used with -bitcode_hide_symbols";
5721 // auto fix up the process type for strip -S.
5722 // when there is only one input and output type is object file, downgrade kBitcodeProcess to kBitcodeAsData.
5723 if ( fOutputKind
== Options::kObjectFile
&& fInputFiles
.size() == 1 && fBitcodeKind
== Options::kBitcodeProcess
)
5724 fBitcodeKind
= Options::kBitcodeAsData
;
5726 // <rdar://problem/17598404> warn if building an embedded iOS dylib for pre-iOS 8
5727 // <rdar://problem/18935714> How can we suppress "ld: warning: embedded dylibs/frameworks only run on iOS 8 or later" when building XCTest?
5728 if ( (fOutputKind
== Options::kDynamicLibrary
) && (fDylibInstallName
!= NULL
) ) {
5729 if ( platforms().contains(ld::kPlatform_iOS
) && !platforms().minOS(ld::iOS_8_0
) && (fDylibInstallName
[0] == '@') && !fEncryptableForceOff
)
5730 warning("embedded dylibs/frameworks only run on iOS 8 or later");
5733 // produce nicer error when no input
5734 if ( fInputFiles
.empty() ) {
5735 throw "no object files specified";
5738 // Check zippered combinations.
5739 if (platforms().count() > 2) {
5740 throw "Illegal platform count. Only 2 platforms at a maximum can be specified";
5743 // Convert from -ios_version_min to -ios_simulator_version_min for now until clang has been updated
5744 if (architecture() == CPU_TYPE_X86_64
|| architecture() == CPU_TYPE_X86
) {
5745 if (platforms().contains(ld::kPlatform_iOS
)) {
5746 uint32_t version
= platforms().minOS(ld::kPlatform_iOS
);
5747 fPlatforms
.erase(ld::kPlatform_iOS
);
5748 // HACK infer the build environment from the SDK path
5749 bool macOSSDK
= false;
5750 for (const auto& sdkPath
: fSDKPaths
) {
5751 if (strstr(sdkPath
, "MacOSX10") != 0) {
5757 fPlatforms
.add({ ld::kPlatform_iOSMac
, version
});
5758 warning("URGENT: -ios_version_min is invalid for architecture x86/x86_64, inferring -iosmac_version_min. "
5759 "This will be an error in the future.");
5761 fPlatforms
.add({ ld::kPlatform_iOSSimulator
, version
});
5762 warning("URGENT: -ios_version_min is invalid for architecture x86/x86_64, inferring -ios_simulator_version_min. "
5763 "This will be an error in the future.");
5768 if (platforms().count() == 2) {
5769 if (!platforms().minOS(ld::mac10_14
))
5770 throw "Zippered macOS version platform must be at least 10.14";
5771 if (!platforms().minOS(ld::iOS_12_0
))
5772 throw "Zippered iosmac version platform must be at least 12.0";
5775 if (platforms().contains(ld::kPlatform_iOSMac
) && !platforms().minOS(ld::iOS_12_0
)) {
5776 throw "iosmac platform version must be at least 12.0";
5779 // <rdar://problem/38155581> ld64 shouldn't allow final executables to have more than one version load command
5780 if ( platforms().contains(ld::kPlatform_iOSMac
) && platforms().contains(ld::kPlatform_macOS
) ) {
5781 if ( (fOutputKind
!= Options::kDynamicLibrary
) && (fOutputKind
!= Options::kDynamicBundle
) ) {
5782 warning("Only dylibs and bundles can be zippered, changing output to be macOS only.");
5783 fPlatforms
.erase(ld::kPlatform_iOSMac
);
5787 // <rdar://problem/39095109> Linker warning for i386 macOS binaries
5788 if ( (architecture() == CPU_TYPE_I386
) && platforms().contains(ld::kPlatform_macOS
) ) {
5789 bool internalSDK
= false;
5790 for (const char* sdkPath
: fSDKPaths
) {
5791 std::string possiblePath
= std::string(sdkPath
) + "/AppleInternal/";
5792 struct stat statBuffer
;
5793 if ( stat(possiblePath
.c_str(), &statBuffer
) == 0 ) {
5799 warning("The i386 architecture is deprecated for macOS (remove from the Xcode build setting: ARCHS)");
5804 void Options::checkForClassic(int argc
, const char* argv
[])
5807 bool archFound
= false;
5808 bool staticFound
= false;
5809 bool dtraceFound
= false;
5810 bool kextFound
= false;
5811 bool rFound
= false;
5812 bool creatingMachKernel
= false;
5813 bool newLinker
= false;
5815 // build command line buffer in case ld crashes
5816 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
5817 CRSetCrashLogMessage(crashreporterBuffer
);
5819 const char* srcRoot
= getenv("SRCROOT");
5820 if ( srcRoot
!= NULL
) {
5821 strlcpy(crashreporterBuffer
, "SRCROOT=", crashreporterBufferSize
);
5822 strlcat(crashreporterBuffer
, srcRoot
, crashreporterBufferSize
);
5823 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
5826 strlcat(crashreporterBuffer
, LD_VERS
, crashreporterBufferSize
);
5827 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
5829 strlcat(crashreporterBuffer
, "ld ", crashreporterBufferSize
);
5830 for(int i
=1; i
< argc
; ++i
) {
5831 strlcat(crashreporterBuffer
, argv
[i
], crashreporterBufferSize
);
5832 strlcat(crashreporterBuffer
, " ", crashreporterBufferSize
);
5835 for(int i
=0; i
< argc
; ++i
) {
5836 const char* arg
= argv
[i
];
5837 if ( arg
[0] == '-' ) {
5838 if ( strcmp(arg
, "-arch") == 0 ) {
5839 parseArch(argv
[++i
]);
5842 else if ( strcmp(arg
, "-static") == 0 ) {
5845 else if ( strcmp(arg
, "-kext") == 0 ) {
5848 else if ( strcmp(arg
, "-dtrace") == 0 ) {
5851 else if ( strcmp(arg
, "-r") == 0 ) {
5854 else if ( strcmp(arg
, "-new_linker") == 0 ) {
5857 else if ( strcmp(arg
, "-classic_linker") == 0 ) {
5858 // ld_classic does not understand this option, so remove it
5859 for(int j
=i
; j
< argc
; ++j
)
5860 argv
[j
] = argv
[j
+1];
5861 warning("using ld_classic");
5862 this->gotoClassicLinker(argc
-1, argv
);
5864 else if ( strcmp(arg
, "-o") == 0 ) {
5865 const char* outfile
= argv
[++i
];
5866 if ( (outfile
!= NULL
) && (strstr(outfile
, "/mach_kernel") != NULL
) )
5867 creatingMachKernel
= true;
5873 void Options::gotoClassicLinker(int argc
, const char* argv
[])
5875 argv
[0] = "ld_classic";
5876 // ld_classic does not support -iphoneos_version_min, so change
5877 for(int j
=0; j
< argc
; ++j
) {
5878 if ( (strcmp(argv
[j
], "-iphoneos_version_min") == 0) || (strcmp(argv
[j
], "-ios_version_min") == 0) ) {
5879 argv
[j
] = "-macosx_version_min";
5885 // ld classic does not understand -kext (change to -static -r)
5886 for(int j
=0; j
< argc
; ++j
) {
5887 if ( strcmp(argv
[j
], "-kext") == 0)
5889 else if ( strcmp(argv
[j
], "-dynamic") == 0)
5890 argv
[j
] = "-static";
5892 // ld classic does not understand -demangle
5893 for(int j
=0; j
< argc
; ++j
) {
5894 if ( strcmp(argv
[j
], "-demangle") == 0)
5895 argv
[j
] = "-noprebind";
5897 // in -v mode, print command line passed to ld_classic
5898 for(int i
=0; i
< argc
; ++i
) {
5899 if ( strcmp(argv
[i
], "-v") == 0 ) {
5900 for(int j
=0; j
< argc
; ++j
)
5901 printf("%s ", argv
[j
]);
5906 char rawPath
[PATH_MAX
];
5907 char path
[PATH_MAX
];
5908 uint32_t bufSize
= PATH_MAX
;
5909 if ( _NSGetExecutablePath(rawPath
, &bufSize
) != -1 ) {
5910 if ( realpath(rawPath
, path
) != NULL
) {
5911 char* lastSlash
= strrchr(path
, '/');
5912 if ( lastSlash
!= NULL
) {
5913 strcpy(lastSlash
+1, "ld_classic");
5915 execvp(path
, (char**)argv
);
5919 // in case of error in above, try searching for ld_classic via PATH
5920 execvp(argv
[0], (char**)argv
);
5921 fprintf(stderr
, "can't exec ld_classic\n");
5926 // Note, returned string buffer is own by this function.
5927 // It should not be freed
5928 // It will be reused, so clients need to strdup() if they want
5929 // to use it long term.
5930 const char* Options::demangleSymbol(const char* sym
) const
5932 // only try to demangle symbols if -demangle on command line
5936 static size_t size
= 1024;
5937 static char* buff
= (char*)malloc(size
);
5940 // only try to demangle symbols that look like Swift symbols
5941 if ( strncmp(sym
, "_$", 2) == 0 ) {
5942 size_t demangledSize
= fnd_get_demangled_name(&sym
[1], buff
, size
);
5943 if ( demangledSize
> size
) {
5944 size
= demangledSize
+2;
5945 buff
= (char*)realloc(buff
, size
);
5946 demangledSize
= fnd_get_demangled_name(&sym
[1], buff
, size
);
5948 if ( demangledSize
!= 0 )
5953 // only try to demangle symbols that look like C++ symbols
5954 if ( strncmp(sym
, "__Z", 3) != 0 )
5958 char* result
= abi::__cxa_demangle(&sym
[1], buff
, &size
, &status
);
5959 if ( result
!= NULL
) {
5960 // if demangling successful, keep buffer for next demangle
5968 void Options::writeDependencyInfo() const
5970 // do nothing if -dependency_info not used
5971 if ( !dumpDependencyInfo() )
5974 // <rdar://problem/30750137> sort entries for build reproducibility
5975 std::sort(fDependencies
.begin(), fDependencies
.end(), [](const DependencyEntry
& a
, const DependencyEntry
& b
) -> bool {
5976 if ( a
.opcode
!= b
.opcode
)
5977 return (a
.opcode
< b
.opcode
);
5978 return (a
.path
< b
.path
);
5981 // one time open() of -dependency_info file
5982 int fd
= open(this->dependencyInfoPath(), O_WRONLY
| O_TRUNC
| O_CREAT
, 0666);
5984 throwf("Could not open or create -dependency_info file: %s", this->dependencyInfoPath());
5987 uint8_t version
= depLinkerVersion
;
5988 if ( write(fd
, &version
, 1) == -1 )
5989 throwf("write() to -dependency_info failed, errno=%d", errno
);
5990 extern const char ldVersionString
[];
5991 if ( write(fd
, ldVersionString
, strlen(ldVersionString
)+1) == -1 )
5992 throwf("write() to -dependency_info failed, errno=%d", errno
);
5994 // write each dependency
5995 for (const auto& entry
: fDependencies
) {
5996 //printf("%d %s\n", entry.opcode, entry.path.c_str());
5997 if ( write(fd
, &entry
.opcode
, 1) == -1 )
5998 throwf("write() to -dependency_info failed, errno=%d", errno
);
5999 if ( write(fd
, entry
.path
.c_str(), entry
.path
.size()+1) == -1 )
6000 throwf("write() to -dependency_info failed, errno=%d", errno
);
6007 void Options::addDependency(uint8_t opcode
, const char* path
) const
6009 if ( !this->dumpDependencyInfo() )
6012 char realPath
[PATH_MAX
];
6013 if ( path
[0] != '/' ) {
6014 if ( realpath(path
, realPath
) != NULL
) {
6019 DependencyEntry entry
;
6020 entry
.opcode
= opcode
;
6022 fDependencies
.push_back(entry
);
6026 void Options::writeToTraceFile(const char* buffer
, size_t len
) const
6028 // one time open() of custom LD_TRACE_FILE
6029 if ( fTraceFileDescriptor
== -1 ) {
6030 if ( fTraceOutputFile
!= NULL
) {
6031 fTraceFileDescriptor
= open(fTraceOutputFile
, O_WRONLY
| O_APPEND
| O_CREAT
, 0666);
6032 if ( fTraceFileDescriptor
== -1 )
6033 throwf("Could not open or create trace file (errno=%d): %s", errno
, fTraceOutputFile
);
6036 fTraceFileDescriptor
= fileno(stderr
);
6041 ssize_t amountWritten
= write(fTraceFileDescriptor
, buffer
, len
);
6042 if ( amountWritten
== -1 )
6043 /* Failure to write shouldn't fail the build. */
6045 buffer
+= amountWritten
;
6046 len
-= amountWritten
;