1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2005-2011 Apple Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
22 * @APPLE_LICENSE_HEADER_END@
26 #include <sys/types.h>
28 #include <mach/vm_prot.h>
29 #include <sys/sysctl.h>
30 #include <mach-o/dyld.h>
36 #include <Availability.h>
37 #include <tapi/tapi.h>
44 #include "Architectures.hpp"
45 #include "MachOFileAbstraction.hpp"
49 // from FunctionNameDemangle.h
50 extern "C" size_t fnd_get_demangled_name(const char *mangledName
, char *outputBuffer
, size_t length
);
53 // upward dependency on lto::version()
55 extern const char* version();
58 // magic to place command line in crash reports
59 const int crashreporterBufferSize
= 2000;
60 static char crashreporterBuffer
[crashreporterBufferSize
];
61 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
62 #include <CrashReporterClient.h>
63 // hack until ld does not need to build on 10.6 anymore
64 struct crashreporter_annotations_t gCRAnnotations
65 __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION
)))
66 = { CRASHREPORTER_ANNOTATIONS_VERSION
, 0, 0, 0, 0, 0, 0 };
68 extern "C" char* __crashreporter_info__
;
70 char* __crashreporter_info__
= crashreporterBuffer
;
74 static bool sEmitWarnings
= true;
75 static bool sFatalWarnings
= false;
76 static const char* sWarningsSideFilePath
= NULL
;
77 static FILE* sWarningsSideFile
= NULL
;
78 static int sWarningsCount
= 0;
80 void warning(const char* format
, ...)
83 if ( sEmitWarnings
) {
85 if ( sWarningsSideFilePath
!= NULL
) {
86 if ( sWarningsSideFile
== NULL
)
87 sWarningsSideFile
= fopen(sWarningsSideFilePath
, "a");
89 va_start(list
, format
);
90 fprintf(stderr
, "ld: warning: ");
91 vfprintf(stderr
, format
, list
);
92 fprintf(stderr
, "\n");
93 if ( sWarningsSideFile
!= NULL
) {
94 fprintf(sWarningsSideFile
, "ld: warning: ");
95 vfprintf(sWarningsSideFile
, format
, list
);
96 fprintf(sWarningsSideFile
, "\n");
97 fflush(sWarningsSideFile
);
103 void throwf(const char* format
, ...)
107 va_start(list
, format
);
108 vasprintf(&p
, format
, list
);
116 bool Options::FileInfo::checkFileExists(const Options
& options
, const char *p
)
118 struct stat statBuffer
;
121 if ( stat(p
, &statBuffer
) == 0 ) {
122 if (p
!= path
) path
= strdup(p
);
123 modTime
= statBuffer
.st_mtime
;
126 if ( options
.dumpDependencyInfo() )
127 options
.dumpDependency(Options::depNotFound
, p
);
128 // fprintf(stderr, "not found: %s\n", p);
133 Options::Options(int argc
, const char* argv
[])
134 : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0), fArchitectureName("unknown"), fOutputKind(kDynamicExecutable
),
135 fHasPreferredSubType(false), fArchSupportsThumb2(false), fPrebind(false), fBindAtLoad(false), fKeepPrivateExterns(false),
136 fNeedsModuleTable(false), fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false),
137 fInterposeMode(kInterposeNone
), fDeadStrip(false), fNameSpace(kTwoLevelNameSpace
),
138 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL
), fFinalName(NULL
), fEntryName(NULL
),
139 fBaseAddress(0), fMaxAddress(0x7FFFFFFFFFFFFFFFLL
),
140 fBaseWritableAddress(0), fSplitSegs(false),
141 fExportMode(kExportDefault
), fLibrarySearchMode(kSearchDylibAndArchiveInEachDir
),
142 fUndefinedTreatment(kUndefinedError
), fMessagesPrefixedWithArchitecture(true),
143 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak
),
145 fUmbrellaName(NULL
), fInitFunctionName(NULL
), fDotOutputFile(NULL
), fExecutablePath(NULL
),
146 fBundleLoader(NULL
), fDtraceScriptName(NULL
), fSegAddrTablePath(NULL
), fMapPath(NULL
),
147 fDyldInstallPath("/usr/lib/dyld"), fLtoCachePath(NULL
), fTempLtoObjectPath(NULL
), fOverridePathlibLTO(NULL
), fLtoCpu(NULL
),
148 fZeroPageSize(ULLONG_MAX
), fStackSize(0), fStackAddr(0), fSourceVersion(0), fSDKVersion(0), fExecutableStack(false),
149 fNonExecutableHeap(false), fDisableNonExecutableHeap(false),
150 fMinimumHeaderPad(32), fSegmentAlignment(4096),
151 fCommonsMode(kCommonsIgnoreDylibs
), fUUIDMode(kUUIDContent
), fLocalSymbolHandling(kLocalSymbolsAll
), fWarnCommons(false),
152 fVerbose(false), fKeepRelocations(false), fWarnStabs(false),
153 fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
154 fSharedRegionEligible(false), fSharedRegionEligibleForceOff(false), fPrintOrderFileStatistics(false),
155 fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), fPIEOnCommandLine(false),
156 fDisablePositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
157 fDeadStripDylibs(false), fAllowTextRelocs(false), fWarnTextRelocs(false), fKextsUseStubs(false),
158 fUsingLazyDylibLinking(false), fEncryptable(true), fEncryptableForceOn(false), fEncryptableForceOff(false),
159 fOrderData(true), fMarkDeadStrippableDylib(false),
160 fMakeCompressedDyldInfo(true), fMakeCompressedDyldInfoForceOff(false), fNoEHLabels(false),
161 fAllowCpuSubtypeMismatches(false), fEnforceDylibSubtypesMatch(false), fUseSimplifiedDylibReExports(false),
162 fObjCABIVersion2Override(false), fObjCABIVersion1Override(false), fCanUseUpwardDylib(false),
163 fFullyLoadArchives(false), fLoadAllObjcObjectsFromArchives(false), fFlatNamespace(false),
164 fLinkingMainExecutable(false), fForFinalLinkedImage(false), fForStatic(false),
165 fForDyld(false), fMakeTentativeDefinitionsReal(false), fWhyLoad(false), fRootSafe(false),
166 fSetuidSafe(false), fImplicitlyLinkPublicDylibs(true), fAddCompactUnwindEncoding(true),
167 fWarnCompactUnwind(false), fRemoveDwarfUnwindIfCompactExists(false),
168 fAutoOrderInitializers(true), fOptimizeZeroFill(true), fMergeZeroFill(false), fLogObjectFiles(false),
169 fLogAllFiles(false), fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false), fTraceEmitJSON(false),
170 fOutputSlidable(false), fWarnWeakExports(false),
171 fObjcGcCompaction(false), fObjCGc(false), fObjCGcOnly(false),
172 fDemangle(false), fTLVSupport(false),
173 fVersionLoadCommand(false), fVersionLoadCommandForcedOn(false),
174 fVersionLoadCommandForcedOff(false), fFunctionStartsLoadCommand(false),
175 fFunctionStartsForcedOn(false), fFunctionStartsForcedOff(false),
176 fDataInCodeInfoLoadCommand(false), fDataInCodeInfoLoadCommandForcedOn(false), fDataInCodeInfoLoadCommandForcedOff(false),
177 fCanReExportSymbols(false), fObjcCategoryMerging(true), fPageAlignDataAtoms(false),
178 fNeedsThreadLoadCommand(false), fEntryPointLoadCommand(false),
179 fEntryPointLoadCommandForceOn(false), fEntryPointLoadCommandForceOff(false),
180 fSourceVersionLoadCommand(false),
181 fSourceVersionLoadCommandForceOn(false), fSourceVersionLoadCommandForceOff(false),
182 fTargetIOSSimulator(false), fExportDynamic(false), fAbsoluteSymbols(false),
183 fAllowSimulatorToLinkWithMacOSX(false), fKeepDwarfUnwind(true),
184 fKeepDwarfUnwindForcedOn(false), fKeepDwarfUnwindForcedOff(false),
185 fVerboseOptimizationHints(false), fIgnoreOptimizationHints(false),
186 fGenerateDtraceDOF(true), fAllowBranchIslands(true), fTraceSymbolLayout(false),
187 fMarkAppExtensionSafe(false), fCheckAppExtensionSafe(false), fForceLoadSwiftLibs(false),
188 fSharedRegionEncodingV2(false), fUseDataConstSegment(false),
189 fUseDataConstSegmentForceOn(false), fUseDataConstSegmentForceOff(false), fUseTextExecSegment(false),
190 fBundleBitcode(false), fHideSymbols(false), fVerifyBitcode(false),
191 fReverseMapUUIDRename(false), fDeDupe(true), fVerboseDeDupe(false),
192 fReverseMapPath(NULL
), fLTOCodegenOnly(false),
193 fIgnoreAutoLink(false), fAllowDeadDups(false), fAllowWeakImports(true), fBitcodeKind(kBitcodeProcess
),
194 fPlatform(kPlatformUnknown
), fDebugInfoStripping(kDebugInfoMinimal
), fTraceOutputFile(NULL
),
195 fMacVersionMin(ld::macVersionUnset
), fIOSVersionMin(ld::iOSVersionUnset
), fWatchOSVersionMin(ld::wOSVersionUnset
),
196 fSaveTempFiles(false), fSnapshotRequested(false), fPipelineFifo(NULL
),
197 fDependencyInfoPath(NULL
), fDependencyFileDescriptor(-1), fTraceFileDescriptor(-1), fMaxDefaultCommonAlign(0)
199 this->checkForClassic(argc
, argv
);
200 this->parsePreCommandLineEnvironmentSettings();
201 this->parse(argc
, argv
);
202 this->parsePostCommandLineEnvironmentSettings();
203 this->reconfigureDefaults();
204 this->checkIllegalOptionCombinations();
206 if ( this->dumpDependencyInfo() ) {
207 this->dumpDependency(depOutputFile
, fOutputFile
);
208 if ( fMapPath
!= NULL
)
209 this->dumpDependency(depOutputFile
, fMapPath
);
215 if ( fDependencyFileDescriptor
!= -1 )
216 ::close(fDependencyFileDescriptor
);
218 if ( fTraceFileDescriptor
!= -1 )
219 ::close(fTraceFileDescriptor
);
222 bool Options::errorBecauseOfWarnings() const
224 return (sFatalWarnings
&& (sWarningsCount
> 0));
228 const char* Options::installPath() const
230 if ( fDylibInstallName
!= NULL
)
231 return fDylibInstallName
;
232 else if ( fFinalName
!= NULL
)
239 bool Options::interposable(const char* name
) const
241 switch ( fInterposeMode
) {
244 case kInterposeAllExternal
:
247 return fInterposeList
.contains(name
);
249 throw "internal error";
253 bool Options::printWhyLive(const char* symbolName
) const
255 return fWhyLive
.contains(symbolName
);
259 const char* Options::dotOutputFile()
261 return fDotOutputFile
;
265 bool Options::hasWildCardExportRestrictList() const
267 // has -exported_symbols_list which contains some wildcards
268 return ((fExportMode
== kExportSome
) && fExportSymbols
.hasWildCards());
271 bool Options::hasWeakBitTweaks() const
273 // has -exported_symbols_list which contains some wildcards
274 return (!fForceWeakSymbols
.empty() || !fForceNotWeakSymbols
.empty());
277 bool Options::allGlobalsAreDeadStripRoots() const
279 // -exported_symbols_list means globals are not exported by default
280 if ( fExportMode
== kExportSome
)
283 switch ( fOutputKind
) {
284 case Options::kDynamicExecutable
:
285 // <rdar://problem/12839986> Add the -export_dynamic flag
286 return fExportDynamic
;
287 case Options::kStaticExecutable
:
288 // <rdar://problem/13361218> Support the -export_dynamic flag for xnu
289 return fExportDynamic
;
290 case Options::kPreload
:
291 // by default unused globals in a main executable are stripped
293 case Options::kDynamicLibrary
:
294 case Options::kDynamicBundle
:
295 case Options::kObjectFile
:
297 case Options::kKextBundle
:
304 bool Options::keepRelocations()
306 return fKeepRelocations
;
309 bool Options::warnStabs()
314 const char* Options::executablePath()
316 return fExecutablePath
;
319 uint32_t Options::initialSegProtection(const char* segName
) const
321 for(std::vector
<Options::SegmentProtect
>::const_iterator it
= fCustomSegmentProtections
.begin(); it
!= fCustomSegmentProtections
.end(); ++it
) {
322 if ( strcmp(it
->name
, segName
) == 0 ) {
326 if ( strcmp(segName
, "__TEXT") == 0 ) {
327 return ( fUseTextExecSegment
? VM_PROT_READ
: (VM_PROT_READ
| VM_PROT_EXECUTE
) );
329 else if ( strcmp(segName
, "__TEXT_EXEC") == 0 ) {
330 return VM_PROT_READ
| VM_PROT_EXECUTE
;
332 else if ( strcmp(segName
, "__PAGEZERO") == 0 ) {
335 else if ( strcmp(segName
, "__LINKEDIT") == 0 ) {
339 // all others default to read-write
340 return VM_PROT_READ
| VM_PROT_WRITE
;
343 uint32_t Options::maxSegProtection(const char* segName
) const
345 // iPhoneOS always uses same protection for max and initial
346 // <rdar://problem/11663436> simulator apps need to use MacOSX max-prot
347 if ( (fPlatform
!= kPlatformOSX
) && !fTargetIOSSimulator
)
348 return initialSegProtection(segName
);
350 for(std::vector
<Options::SegmentProtect
>::const_iterator it
= fCustomSegmentProtections
.begin(); it
!= fCustomSegmentProtections
.end(); ++it
) {
351 if ( strcmp(it
->name
, segName
) == 0 ) {
355 if ( strcmp(segName
, "__PAGEZERO") == 0 ) {
358 // all others default to all
359 return VM_PROT_READ
| VM_PROT_WRITE
| VM_PROT_EXECUTE
;
362 uint64_t Options::segPageSize(const char* segName
) const
364 for(std::vector
<SegmentSize
>::const_iterator it
=fCustomSegmentSizes
.begin(); it
!= fCustomSegmentSizes
.end(); ++it
) {
365 if ( strcmp(it
->name
, segName
) == 0 )
368 return fSegmentAlignment
;
371 uint64_t Options::customSegmentAddress(const char* segName
) const
373 for(std::vector
<SegmentStart
>::const_iterator it
=fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
374 if ( strcmp(it
->name
, segName
) == 0 )
377 // if custom stack in use, model as segment with custom address
378 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
379 return fStackAddr
- fStackSize
;
383 bool Options::hasCustomSegmentAddress(const char* segName
) const
385 for(std::vector
<SegmentStart
>::const_iterator it
=fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
386 if ( strcmp(it
->name
, segName
) == 0 )
389 // if custom stack in use, model as segment with custom address
390 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
395 bool Options::hasCustomSectionAlignment(const char* segName
, const char* sectName
) const
397 for (std::vector
<SectionAlignment
>::const_iterator it
= fSectionAlignments
.begin(); it
!= fSectionAlignments
.end(); ++it
) {
398 if ( (strcmp(it
->segmentName
, segName
) == 0) && (strcmp(it
->sectionName
, sectName
) == 0) )
401 if ( fEncryptable
&& (strcmp(sectName
, "__oslogstring") == 0) && (strcmp(segName
, "__TEXT") == 0) )
407 uint8_t Options::customSectionAlignment(const char* segName
, const char* sectName
) const
409 for (std::vector
<SectionAlignment
>::const_iterator it
= fSectionAlignments
.begin(); it
!= fSectionAlignments
.end(); ++it
) {
410 if ( (strcmp(it
->segmentName
, segName
) == 0) && (strcmp(it
->sectionName
, sectName
) == 0) )
411 return it
->alignment
;
413 if ( fEncryptable
&& (strcmp(sectName
, "__oslogstring") == 0) && (strcmp(segName
, "__TEXT") == 0) )
414 return __builtin_ctz(fSegmentAlignment
);
419 bool Options::segmentOrderAfterFixedAddressSegment(const char* segName
) const
421 bool nowPinned
= false;
422 for (std::vector
<const char*>::const_iterator it
=fSegmentOrder
.begin(); it
!= fSegmentOrder
.end(); ++it
) {
423 if ( strcmp(*it
, segName
) == 0 )
425 if ( hasCustomSegmentAddress(*it
) )
431 bool Options::hasExportedSymbolOrder()
433 return (fExportSymbolsOrder
.size() > 0);
436 bool Options::exportedSymbolOrder(const char* sym
, unsigned int* order
) const
438 NameToOrder::const_iterator pos
= fExportSymbolsOrder
.find(sym
);
439 if ( pos
!= fExportSymbolsOrder
.end() ) {
440 *order
= pos
->second
;
449 void Options::loadSymbolOrderFile(const char* fileOfExports
, NameToOrder
& orderMapping
)
451 // read in whole file
452 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
454 throwf("can't open -exported_symbols_order file: %s", fileOfExports
);
455 struct stat stat_buf
;
456 ::fstat(fd
, &stat_buf
);
457 char* p
= (char*)malloc(stat_buf
.st_size
);
459 throwf("can't process -exported_symbols_order file: %s", fileOfExports
);
461 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
462 throwf("can't read -exported_symbols_order file: %s", fileOfExports
);
466 // parse into symbols and add to unordered_set
467 unsigned int count
= 0;
468 char * const end
= &p
[stat_buf
.st_size
];
469 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
470 char* symbolStart
= NULL
;
471 for (char* s
= p
; s
< end
; ++s
) {
477 else if ( !isspace(*s
) ) {
483 if ( (*s
== '\n') || (*s
== '\r') ) {
485 // removing any trailing spaces
487 while ( isspace(*last
) ) {
491 orderMapping
[symbolStart
] = ++count
;
497 if ( (*s
== '\n') || (*s
== '\r') )
502 if ( state
== inSymbol
) {
503 warning("missing line-end at end of file \"%s\"", fileOfExports
);
504 int len
= end
-symbolStart
+1;
505 char* temp
= new char[len
];
506 strlcpy(temp
, symbolStart
, len
);
508 // remove any trailing spaces
509 char* last
= &temp
[len
-2];
510 while ( isspace(*last
) ) {
514 orderMapping
[temp
] = ++count
;
517 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
520 bool Options::forceWeak(const char* symbolName
) const
522 return fForceWeakSymbols
.contains(symbolName
);
525 bool Options::forceNotWeak(const char* symbolName
) const
527 return fForceNotWeakSymbols
.contains(symbolName
);
530 bool Options::forceWeakNonWildCard(const char* symbolName
) const
532 return fForceWeakSymbols
.containsNonWildcard(symbolName
);
535 bool Options::forceNotWeakNonWildcard(const char* symbolName
) const
537 return fForceNotWeakSymbols
.containsNonWildcard(symbolName
);
540 bool Options::forceCoalesce(const char* symbolName
) const
542 return fForceCoalesceSymbols
.contains(symbolName
);
546 bool Options::shouldExport(const char* symbolName
) const
548 switch (fExportMode
) {
550 return fExportSymbols
.contains(symbolName
);
551 case kDontExportSome
:
552 return ! fDontExportSymbols
.contains(symbolName
);
556 throw "internal error";
559 bool Options::shouldReExport(const char* symbolName
) const
561 return fReExportSymbols
.contains(symbolName
);
564 bool Options::keepLocalSymbol(const char* symbolName
) const
566 switch (fLocalSymbolHandling
) {
567 case kLocalSymbolsAll
:
569 case kLocalSymbolsNone
:
571 case kLocalSymbolsSelectiveInclude
:
572 return fLocalSymbolsIncluded
.contains(symbolName
);
573 case kLocalSymbolsSelectiveExclude
:
574 return ! fLocalSymbolsExcluded
.contains(symbolName
);
576 throw "internal error";
579 const std::vector
<const char*>* Options::sectionOrder(const char* segName
) const
581 for (std::vector
<SectionOrderList
>::const_iterator it
=fSectionOrder
.begin(); it
!= fSectionOrder
.end(); ++it
) {
582 if ( strcmp(it
->segmentName
, segName
) == 0 )
583 return &it
->sectionOrder
;
588 uint32_t Options::minOSversion() const
592 return iOSVersionMin();
594 return macosxVersionMin();
595 case kPlatformWatchOS
:
596 return watchOSVersionMin();
598 case Options::kPlatform_tvOS
:
599 return iOSVersionMin();
607 void Options::setArchitecture(cpu_type_t type
, cpu_subtype_t subtype
, Options::Platform platform
)
609 for (const ArchInfo
* t
=archInfoArray
; t
->archName
!= NULL
; ++t
) {
610 if ( (type
== t
->cpuType
) && (subtype
== t
->cpuSubType
) ) {
611 fArchitecture
= type
;
612 fSubArchitecture
= subtype
;
613 fArchitectureName
= t
->archName
;
614 fHasPreferredSubType
= t
->isSubType
;
615 fArchSupportsThumb2
= t
->supportsThumb2
;
616 fPlatform
= platform
;
619 case CPU_TYPE_X86_64
:
620 if ( (fPlatform
== kPlatformOSX
) && (fOutputKind
!= Options::kObjectFile
) && (fMacVersionMin
== ld::macVersionUnset
) ) {
621 #ifdef DEFAULT_MACOSX_MIN_VERSION
622 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION
);
623 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
625 warning("-macosx_version_min not specified, assuming 10.6");
626 fMacVersionMin
= ld::mac10_6
;
632 if ( (fMacVersionMin
== ld::macVersionUnset
) && (fIOSVersionMin
== ld::iOSVersionUnset
) && (fOutputKind
!= Options::kObjectFile
) ) {
633 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
634 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION
);
635 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION
);
637 warning("-ios_version_min not specified, assuming 6.0");
638 setIOSVersionMin("6.0");
643 fLinkSnapshot
.recordArch(fArchitectureName
);
644 // only use compressed LINKEDIT for:
645 // Mac OS X 10.6 or later
647 if ( !fMakeCompressedDyldInfo
&& minOS(ld::mac10_6
, ld::iOS_3_1
) && !fMakeCompressedDyldInfoForceOff
)
648 fMakeCompressedDyldInfo
= true;
649 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
650 if ( minOS(ld::mac10_5
, ld::iOS_2_0
) )
651 fUseSimplifiedDylibReExports
= true;
655 fArchitectureName
= "unknown architecture";
658 bool Options::armUsesZeroCostExceptions() const
660 return ( (fArchitecture
== CPU_TYPE_ARM
) && (fSubArchitecture
== CPU_SUBTYPE_ARM_V7K
) );
663 void Options::parseArch(const char* arch
)
666 throw "-arch must be followed by an architecture string";
667 for (const ArchInfo
* t
=archInfoArray
; t
->archName
!= NULL
; ++t
) {
668 if ( strcmp(t
->archName
,arch
) == 0 ) {
669 fArchitectureName
= arch
;
670 fArchitecture
= t
->cpuType
;
671 fSubArchitecture
= t
->cpuSubType
;
672 fHasPreferredSubType
= t
->isSubType
;
673 fArchSupportsThumb2
= t
->supportsThumb2
;
677 throwf("unknown/unsupported architecture name for: -arch %s", arch
);
680 bool Options::checkForFile(const char* format
, const char* dir
, const char* rootName
, FileInfo
& result
) const
682 char possiblePath
[strlen(dir
)+strlen(rootName
)+strlen(format
)+8];
683 sprintf(possiblePath
, format
, dir
, rootName
);
684 bool found
= result
.checkFileExists(*this, possiblePath
);
685 if ( fTraceDylibSearching
)
686 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), possiblePath
);
691 Options::FileInfo
Options::findLibrary(const char* rootName
, bool dylibsOnly
) const
694 const int rootNameLen
= strlen(rootName
);
695 // if rootName ends in .o there is no .a vs .dylib choice
696 if ( (rootNameLen
> 3) && (strcmp(&rootName
[rootNameLen
-2], ".o") == 0) ) {
697 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
698 it
!= fLibrarySearchPaths
.end();
700 const char* dir
= *it
;
701 if ( checkForFile("%s/%s", dir
, rootName
, result
) )
706 bool lookForDylibs
= false;
707 switch ( fOutputKind
) {
708 case Options::kDynamicExecutable
:
709 case Options::kDynamicLibrary
:
710 case Options::kDynamicBundle
:
711 case Options::kObjectFile
: // <rdar://problem/15914513>
712 lookForDylibs
= true;
714 case Options::kStaticExecutable
:
716 case Options::kPreload
:
717 case Options::kKextBundle
:
718 lookForDylibs
= false;
721 switch ( fLibrarySearchMode
) {
722 case kSearchAllDirsForDylibsThenAllDirsForArchives
:
723 // first look in all directories for just for dylibs
724 if ( lookForDylibs
) {
725 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
726 it
!= fLibrarySearchPaths
.end();
728 const char* dir
= *it
;
729 auto path
= std::string(dir
) + "/lib" + rootName
+ ".dylib";
730 if ( findFile(path
, {".tbd"}, result
) )
733 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
734 it
!= fLibrarySearchPaths
.end();
736 const char* dir
= *it
;
737 if ( checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
741 // next look in all directories for just for archives
743 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
744 it
!= fLibrarySearchPaths
.end();
746 const char* dir
= *it
;
747 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
753 case kSearchDylibAndArchiveInEachDir
:
754 // look in each directory for just for a dylib then for an archive
755 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
756 it
!= fLibrarySearchPaths
.end();
758 const char* dir
= *it
;
759 auto path
= std::string(dir
) + "/lib" + rootName
+ ".dylib";
760 if ( lookForDylibs
&& findFile(path
, {".tbd"}, result
) )
762 if ( lookForDylibs
&& checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
764 if ( !dylibsOnly
&& checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
770 throwf("library not found for -l%s", rootName
);
773 Options::FileInfo
Options::findFramework(const char* frameworkName
) const
775 if ( frameworkName
== NULL
)
776 throw "-framework missing next argument";
777 char temp
[strlen(frameworkName
)+1];
778 strcpy(temp
, frameworkName
);
779 const char* name
= temp
;
780 const char* suffix
= NULL
;
781 char* comma
= strchr(temp
, ',');
782 if ( comma
!= NULL
) {
786 return findFramework(name
, suffix
);
789 Options::FileInfo
Options::findFramework(const char* rootName
, const char* suffix
) const
791 for (const auto* path
: fFrameworkSearchPaths
) {
792 auto possiblePath
= std::string(path
).append("/").append(rootName
).append(".framework/").append(rootName
);
793 if ( suffix
!= nullptr ) {
794 char realPath
[PATH_MAX
];
795 // no symlink in framework to suffix variants, so follow main symlink
796 if ( realpath(possiblePath
.c_str(), realPath
) != nullptr )
797 possiblePath
= std::string(realPath
).append(suffix
);
800 if ( findFile(possiblePath
, {".tbd"}, result
) )
803 // try without suffix
804 if ( suffix
!= NULL
)
805 return findFramework(rootName
, NULL
);
807 throwf("framework not found %s", rootName
);
810 static std::string
replace_extension(const std::string
&path
, const std::string
&ext
)
813 auto lastSlashIdx
= result
.find_last_of('/');
814 auto lastDotIdx
= result
.find_last_of('.');
815 if (lastDotIdx
!= std::string::npos
&& lastDotIdx
> lastSlashIdx
)
816 result
.erase(lastDotIdx
, std::string::npos
);
817 if ( ext
.size() > 0 && ext
[0] == '.' )
820 result
.append('.' + ext
);
824 bool Options::findFile(const std::string
&path
, const std::vector
<std::string
> &tbdExtensions
, FileInfo
& result
) const
827 for ( const auto &ext
: tbdExtensions
) {
828 auto newPath
= replace_extension(path
, ext
);
829 bool found
= tbdInfo
.checkFileExists(*this, newPath
.c_str());
830 if ( fTraceDylibSearching
)
831 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), newPath
.c_str());
838 bool found
= dylibInfo
.checkFileExists(*this, path
.c_str());
839 if ( fTraceDylibSearching
)
840 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), path
.c_str());
843 // There is only a text-based stub file or a dynamic library file.
844 if ( tbdInfo
.missing() != dylibInfo
.missing() ) {
845 result
= tbdInfo
.missing() ? dylibInfo
: tbdInfo
;
847 // There are both - a text-based stub file and a dynamic library file.
848 else if ( !tbdInfo
.missing() && !dylibInfo
.missing() ) {
849 // Check if we should prefer the text-based stub file (installapi).
850 if (tapi::LinkerInterfaceFile::shouldPreferTextBasedStubFile(tbdInfo
.path
)) {
853 // If the files are still in sync we can use and should use the text-based stub file.
854 else if (tapi::LinkerInterfaceFile::areEquivalent(tbdInfo
.path
, dylibInfo
.path
)) {
857 // Otherwise issue a warning and fall-back to the dynamic library file.
859 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
);
869 static bool startsWith(const std::string
& str
, const std::string
& prefix
)
871 return (str
.compare(0, prefix
.length(), prefix
) == 0);
874 static std::string
getDirPath(const std::string
& path
)
876 std::string::size_type lastSlashPos
= path
.find_last_of('/');
877 if ( lastSlashPos
== std::string::npos
)
880 return path
.substr(0, lastSlashPos
+1);
883 Options::FileInfo
Options::findFile(const std::string
&path
, const ld::dylib::File
* fromDylib
) const
887 // if absolute path and not a .o file, then use SDK prefix
888 if ( (path
[0] == '/') && (strcmp(&path
[path
.size()-2], ".o") != 0) ) {
889 for (const auto* sdkPathDir
: fSDKPaths
) {
890 auto possiblePath
= std::string(sdkPathDir
) + path
;
891 if ( findFile(possiblePath
, {".tbd"}, result
) )
896 // expand @ variables
897 if ( path
[0] == '@' ) {
898 if ( startsWith(path
, "@executable_path/") && (fExecutablePath
!= nullptr) ) {
899 std::string exeBasedPath
= getDirPath(fExecutablePath
) + &path
[17];
900 if ( findFile(exeBasedPath
, {".tbd"}, result
) )
903 else if ( startsWith(path
, "@loader_path/") && (fromDylib
!= nullptr) ) {
904 char absPath
[PATH_MAX
];
905 if ( realpath(fromDylib
->path(), absPath
) != NULL
) {
906 std::string loaderBasedPath
= getDirPath(fromDylib
->path()) + &path
[13];
907 if ( findFile(loaderBasedPath
, {".tbd"}, result
) )
911 else if ( startsWith(path
, "@rpath/") ) {
912 // first search any LC_RPATH supplied by dyld that re-exports dylib to be found
913 if ( fromDylib
!= nullptr ) {
914 for (const char* rp
: fromDylib
->rpaths() ) {
915 std::string rpath
= rp
;
916 // handle dylib that has LC_RPATH = @loader_path/blah
917 if ( startsWith(rpath
, "@loader_path/") ) {
918 char absPath
[PATH_MAX
];
919 if ( realpath(fromDylib
->path(), absPath
) != NULL
)
920 rpath
= getDirPath(absPath
) + &rpath
[13];
922 rpath
= getDirPath(fromDylib
->path()) + &rpath
[13];
924 std::string rpathBasedPath
= rpath
+ "/" + &path
[6];
925 if ( findFile(rpathBasedPath
, {".tbd"}, result
) )
933 if ( findFile(path
, {".tbd"}, result
) )
937 throwf("file not found: %s", path
.c_str());
940 // search for indirect dylib first using -F and -L paths first
941 Options::FileInfo
Options::findIndirectDylib(const std::string
& installName
, const ld::dylib::File
* fromDylib
) const
945 auto lastSlashPos
= installName
.find_last_of('/');
946 auto pos
= ( lastSlashPos
!= std::string::npos
) ? lastSlashPos
+ 1 : 0;
947 auto leafName
= installName
.substr(pos
);
949 // Is this in a framework?
950 // /path/Foo.framework/Foo ==> true (Foo)
951 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
952 // /path/Foo.framework/Resources/Bar ==> false
953 bool isFramework
= false;
954 if ( lastSlashPos
!= std::string::npos
) {
955 auto frameworkDir
= std::string("/").append(leafName
).append(".framework/");
956 if ( installName
.rfind(frameworkDir
) != std::string::npos
)
960 // These are abbreviated versions of the routines findFramework and findLibrary above
961 // because we already know the final name of the file that we're looking for and so
962 // don't need to try variations, just paths. We do need to add the additional bits
963 // onto the framework path though.
965 auto endPos
= installName
.rfind(".framework");
966 auto beginPos
= installName
.find_last_of('/', endPos
);
967 auto leafPath
= installName
.substr(beginPos
);
968 for (const auto* dir
: fFrameworkSearchPaths
) {
969 auto possiblePath
= dir
+ leafPath
;
970 if ( findFile(possiblePath
, {".tbd"}, result
) )
974 // if this is a .dylib inside a framework, do not search -L paths
975 // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
976 bool embeddedDylib
= ( (leafName
.size() > 6)
977 && (leafName
.find(".dylib", leafName
.size()-6) != std::string::npos
)
978 && (installName
.find(".framework/") != std::string::npos
) );
979 if ( !embeddedDylib
) {
980 for (const auto* dir
: fLibrarySearchPaths
) {
981 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
982 std::string possiblePath
= dir
+ std::string("/") + leafName
;
983 if ( findFile(possiblePath
, {".tbd"}, result
) )
989 // If we didn't find it fall back to findFile.
990 return findFile(installName
, fromDylib
);
995 void Options::parseSegAddrTable(const char* segAddrPath
, const char* installPth
)
997 FILE* file
= fopen(segAddrPath
, "r");
998 if ( file
== NULL
) {
999 warning("-seg_addr_table file cannot be read: %s", segAddrPath
);
1003 char path
[PATH_MAX
];
1004 uint64_t firstColumAddress
= 0;
1005 uint64_t secondColumAddress
= 0;
1006 bool hasSecondColumn
= false;
1007 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
1008 path
[PATH_MAX
-1] = '\0';
1009 char* eol
= strchr(path
, '\n');
1012 // ignore lines not starting with 0x number
1013 if ( (path
[0] == '0') && (path
[1] == 'x') ) {
1015 firstColumAddress
= strtoull(path
, &p
, 16);
1016 while ( isspace(*p
) )
1018 // see if second column is a number
1019 if ( (p
[0] == '0') && (p
[1] == 'x') ) {
1020 secondColumAddress
= strtoull(p
, &p
, 16);
1021 hasSecondColumn
= true;
1022 while ( isspace(*p
) )
1025 while ( isspace(*p
) )
1027 if ( p
[0] == '/' ) {
1028 // remove any trailing whitespace
1029 for(char* end
= eol
-1; (end
> p
) && isspace(*end
); --end
)
1031 // see if this line is for the dylib being linked
1032 if ( strcmp(p
, installPth
) == 0 ) {
1033 fBaseAddress
= firstColumAddress
;
1034 if ( hasSecondColumn
) {
1035 fBaseWritableAddress
= secondColumAddress
;
1038 break; // out of while loop
1047 void Options::loadFileList(const char* fileOfPaths
, ld::File::Ordinal baseOrdinal
)
1050 const char* comma
= strrchr(fileOfPaths
, ',');
1051 const char* prefix
= NULL
;
1052 if ( comma
!= NULL
) {
1053 // <rdar://problem/5907981> -filelist fails with comma in path
1054 file
= fopen(fileOfPaths
, "r");
1055 if ( file
== NULL
) {
1057 int realFileOfPathsLen
= comma
-fileOfPaths
;
1058 char realFileOfPaths
[realFileOfPathsLen
+1];
1059 strncpy(realFileOfPaths
,fileOfPaths
, realFileOfPathsLen
);
1060 realFileOfPaths
[realFileOfPathsLen
] = '\0';
1061 file
= fopen(realFileOfPaths
, "r");
1063 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", realFileOfPaths
, errno
, strerror(errno
));
1064 if ( this->dumpDependencyInfo() )
1065 this->dumpDependency(Options::depFileList
, realFileOfPaths
);
1069 file
= fopen(fileOfPaths
, "r");
1071 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", fileOfPaths
, errno
, strerror(errno
));
1072 if ( this->dumpDependencyInfo() )
1073 this->dumpDependency(Options::depFileList
, fileOfPaths
);
1076 char path
[PATH_MAX
];
1077 ld::File::Ordinal previousOrdinal
= baseOrdinal
;
1078 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
1079 path
[PATH_MAX
-1] = '\0';
1080 char* eol
= strchr(path
, '\n');
1083 if ( prefix
!= NULL
) {
1084 char builtPath
[strlen(prefix
)+strlen(path
)+2];
1085 strcpy(builtPath
, prefix
);
1086 strcat(builtPath
, "/");
1087 strcat(builtPath
, path
);
1088 if (fPipelineFifo
!= NULL
) {
1089 FileInfo info
= FileInfo(builtPath
);
1090 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1091 previousOrdinal
= info
.ordinal
;
1092 info
.fromFileList
= true;
1093 fInputFiles
.push_back(info
);
1095 FileInfo info
= findFile(builtPath
);
1096 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1097 previousOrdinal
= info
.ordinal
;
1098 info
.fromFileList
= true;
1099 fInputFiles
.push_back(info
);
1103 if (fPipelineFifo
!= NULL
) {
1104 FileInfo info
= FileInfo(path
);
1105 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1106 previousOrdinal
= info
.ordinal
;
1107 info
.fromFileList
= true;
1108 fInputFiles
.push_back(info
);
1110 FileInfo info
= findFile(path
);
1111 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1112 previousOrdinal
= info
.ordinal
;
1113 info
.fromFileList
= true;
1114 fInputFiles
.push_back(info
);
1122 void Options::SetWithWildcards::remove(const NameSet
& toBeRemoved
)
1124 for(NameSet::const_iterator it
=toBeRemoved
.begin(); it
!= toBeRemoved
.end(); ++it
) {
1125 const char* symbolName
= *it
;
1126 NameSet::iterator pos
= fRegular
.find(symbolName
);
1127 if ( pos
!= fRegular
.end() )
1128 fRegular
.erase(pos
);
1132 bool Options::SetWithWildcards::hasWildCards(const char* symbol
)
1134 // an exported symbol name containing *, ?, or [ requires wildcard matching
1135 return ( strpbrk(symbol
, "*?[") != NULL
);
1138 void Options::SetWithWildcards::insert(const char* symbol
)
1140 if ( hasWildCards(symbol
) )
1141 fWildCard
.push_back(symbol
);
1143 fRegular
.insert(symbol
);
1146 bool Options::SetWithWildcards::contains(const char* symbol
, bool* matchBecauseOfWildcard
) const
1148 if ( matchBecauseOfWildcard
!= NULL
)
1149 *matchBecauseOfWildcard
= false;
1150 // first look at hash table on non-wildcard symbols
1151 if ( fRegular
.find(symbol
) != fRegular
.end() )
1153 // next walk list of wild card symbols looking for a match
1154 for(std::vector
<const char*>::const_iterator it
= fWildCard
.begin(); it
!= fWildCard
.end(); ++it
) {
1155 if ( wildCardMatch(*it
, symbol
) ) {
1156 if ( matchBecauseOfWildcard
!= NULL
)
1157 *matchBecauseOfWildcard
= true;
1164 // Support "foo.o:_bar" to mean symbol _bar in file foo.o
1165 bool Options::SetWithWildcards::containsWithPrefix(const char* symbol
, const char* file
, bool& wildCardMatch
) const
1167 wildCardMatch
= false;
1168 if ( contains(symbol
, &wildCardMatch
) )
1172 const char* s
= strrchr(file
, '/');
1175 char buff
[strlen(file
)+strlen(symbol
)+2];
1176 sprintf(buff
, "%s:%s", file
, symbol
);
1177 return contains(buff
, &wildCardMatch
);
1180 bool Options::SetWithWildcards::containsNonWildcard(const char* symbol
) const
1182 // look at hash table on non-wildcard symbols
1183 return ( fRegular
.find(symbol
) != fRegular
.end() );
1187 std::vector
<const char*> Options::exportsData() const
1189 return fExportSymbols
.data();
1193 std::vector
<const char*> Options::SetWithWildcards::data() const
1195 std::vector
<const char*> data
;
1196 for (NameSet::iterator it
=regularBegin(); it
!= regularEnd(); ++it
) {
1197 data
.push_back(*it
);
1199 for (std::vector
<const char*>::const_iterator it
=fWildCard
.begin(); it
!= fWildCard
.end(); ++it
) {
1200 data
.push_back(*it
);
1205 bool Options::SetWithWildcards::inCharRange(const char*& p
, unsigned char c
) const
1209 while ( *p
!= '\0' ) {
1212 // found beginining [ and ending ]
1213 unsigned char last
= '\0';
1214 for ( const char* s
= b
; s
< e
; ++s
) {
1216 unsigned char next
= *(++s
);
1217 if ( (last
<= c
) && (c
<= next
) )
1234 bool Options::SetWithWildcards::wildCardMatch(const char* pattern
, const char* symbol
) const
1236 const char* s
= symbol
;
1237 for (const char* p
= pattern
; *p
!= '\0'; ++p
) {
1242 for (const char* t
= s
; *t
!= '\0'; ++t
) {
1243 if ( wildCardMatch(&p
[1], t
) )
1253 if ( ! inCharRange(p
, *s
) )
1263 return (*s
== '\0');
1267 void Options::loadExportFile(const char* fileOfExports
, const char* option
, SetWithWildcards
& set
)
1269 if ( fileOfExports
== NULL
)
1270 throwf("missing file after %s", option
);
1271 // read in whole file
1272 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
1274 throwf("can't open %s file: %s", option
, fileOfExports
);
1275 struct stat stat_buf
;
1276 ::fstat(fd
, &stat_buf
);
1277 char* p
= (char*)malloc(stat_buf
.st_size
);
1279 throwf("can't process %s file: %s", option
, fileOfExports
);
1281 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1282 throwf("can't read %s file: %s", option
, fileOfExports
);
1284 if ( this->dumpDependencyInfo() )
1285 this->dumpDependency(Options::depMisc
, fileOfExports
);
1289 // parse into symbols and add to unordered_set
1290 char * const end
= &p
[stat_buf
.st_size
];
1291 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1292 char* symbolStart
= NULL
;
1293 for (char* s
= p
; s
< end
; ++s
) {
1299 else if ( !isspace(*s
) ) {
1305 if ( (*s
== '\n') || (*s
== '\r') ) {
1307 // removing any trailing spaces
1309 while ( isspace(*last
) ) {
1313 set
.insert(symbolStart
);
1319 if ( (*s
== '\n') || (*s
== '\r') )
1324 if ( state
== inSymbol
) {
1325 warning("missing line-end at end of file \"%s\"", fileOfExports
);
1326 int len
= end
-symbolStart
+1;
1327 char* temp
= new char[len
];
1328 strlcpy(temp
, symbolStart
, len
);
1330 // remove any trailing spaces
1331 char* last
= &temp
[len
-2];
1332 while ( isspace(*last
) ) {
1339 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
1342 void Options::parseAliasFile(const char* fileOfAliases
)
1344 // read in whole file
1345 int fd
= ::open(fileOfAliases
, O_RDONLY
, 0);
1347 throwf("can't open alias file: %s", fileOfAliases
);
1348 struct stat stat_buf
;
1349 ::fstat(fd
, &stat_buf
);
1350 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1352 throwf("can't process alias file: %s", fileOfAliases
);
1354 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1355 throwf("can't read alias file: %s", fileOfAliases
);
1356 p
[stat_buf
.st_size
] = '\n';
1358 if ( this->dumpDependencyInfo() )
1359 this->dumpDependency(Options::depMisc
, fileOfAliases
);
1361 // parse into symbols and add to fAliases
1363 char * const end
= &p
[stat_buf
.st_size
+1];
1364 enum { lineStart
, inRealName
, inBetween
, inAliasName
, inComment
} state
= lineStart
;
1366 for (char* s
= p
; s
< end
; ++s
) {
1372 else if ( !isspace(*s
) ) {
1379 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1383 else if ( isspace(*s
) ) {
1390 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1394 else if ( ! isspace(*s
) ) {
1395 state
= inAliasName
;
1402 // removing any trailing spaces
1404 while ( isspace(*last
) ) {
1408 fAliases
.push_back(pair
);
1411 else if ( *s
== '\n' ) {
1413 // removing any trailing spaces
1415 while ( isspace(*last
) ) {
1419 fAliases
.push_back(pair
);
1430 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
1435 void Options::setUndefinedTreatment(const char* treatment
)
1437 if ( treatment
== NULL
)
1438 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
1440 if ( strcmp(treatment
, "warning") == 0 )
1441 fUndefinedTreatment
= kUndefinedWarning
;
1442 else if ( strcmp(treatment
, "error") == 0 )
1443 fUndefinedTreatment
= kUndefinedError
;
1444 else if ( strcmp(treatment
, "suppress") == 0 )
1445 fUndefinedTreatment
= kUndefinedSuppress
;
1446 else if ( strcmp(treatment
, "dynamic_lookup") == 0 )
1447 fUndefinedTreatment
= kUndefinedDynamicLookup
;
1449 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1452 Options::Treatment
Options::parseTreatment(const char* treatment
)
1454 if ( treatment
== NULL
)
1457 if ( strcmp(treatment
, "warning") == 0 )
1459 else if ( strcmp(treatment
, "error") == 0 )
1461 else if ( strcmp(treatment
, "suppress") == 0 )
1467 void Options::setMacOSXVersionMin(const char* version
)
1470 if ( !parsePackedVersion32(version
, value
) ) {
1471 throwf("-macosx_version_min value malformed: '%s'", version
);
1473 fMacVersionMin
= (ld::MacVersionMin
)value
;
1474 fPlatform
= kPlatformOSX
;
1477 void Options::setIOSVersionMin(const char* version
)
1480 if ( !parsePackedVersion32(version
, value
) ) {
1481 throwf("-ios_version_min value malformed: '%s'", version
);
1483 fIOSVersionMin
= (ld::IOSVersionMin
)value
;
1484 fPlatform
= kPlatformiOS
;
1488 void Options::setWatchOSVersionMin(const char* version
)
1491 if ( !parsePackedVersion32(version
, value
) ) {
1492 throwf("-watchos_version_min value malformed: '%s'", version
);
1494 fWatchOSVersionMin
= (ld::WatchOSVersionMin
)value
;
1495 fPlatform
= kPlatformWatchOS
;
1499 bool Options::minOS(ld::MacVersionMin requiredMacMin
, ld::IOSVersionMin requirediPhoneOSMin
)
1501 if ( fMacVersionMin
!= ld::macVersionUnset
) {
1502 return ( fMacVersionMin
>= requiredMacMin
);
1504 else if ( fWatchOSVersionMin
!= ld::wOSVersionUnset
) {
1505 // Hack until we fully track watch and ios versions seperately
1506 return ( (fWatchOSVersionMin
+ 0x00070000) >= requirediPhoneOSMin
);
1509 return ( fIOSVersionMin
>= requirediPhoneOSMin
);
1513 bool Options::min_iOS(ld::IOSVersionMin requirediOSMin
)
1515 if ( fWatchOSVersionMin
!= ld::wOSVersionUnset
) {
1516 // Hack until we fully track watch and ios versions seperately
1517 return ( (fWatchOSVersionMin
+ 0x00070000) >= requirediOSMin
);
1520 return ( fIOSVersionMin
>= requirediOSMin
);
1524 void Options::setWeakReferenceMismatchTreatment(const char* treatment
)
1526 if ( treatment
== NULL
)
1527 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1529 if ( strcmp(treatment
, "error") == 0 )
1530 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchError
;
1531 else if ( strcmp(treatment
, "weak") == 0 )
1532 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchWeak
;
1533 else if ( strcmp(treatment
, "non-weak") == 0 )
1534 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchNonWeak
;
1536 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1539 Options::CommonsMode
Options::parseCommonsTreatment(const char* mode
)
1542 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1544 if ( strcmp(mode
, "ignore_dylibs") == 0 )
1545 return kCommonsIgnoreDylibs
;
1546 else if ( strcmp(mode
, "use_dylibs") == 0 )
1547 return kCommonsOverriddenByDylibs
;
1548 else if ( strcmp(mode
, "error") == 0 )
1549 return kCommonsConflictsDylibsError
;
1551 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1554 void Options::addDylibOverride(const char* paths
)
1556 if ( paths
== NULL
)
1557 throw "-dylib_file must followed by two colon separated paths";
1558 const char* colon
= strchr(paths
, ':');
1559 if ( colon
== NULL
)
1560 throw "-dylib_file must followed by two colon separated paths";
1561 int len
= colon
-paths
;
1562 char* target
= new char[len
+2];
1563 strncpy(target
, paths
, len
);
1565 DylibOverride entry
;
1566 entry
.installName
= target
;
1567 entry
.useInstead
= &colon
[1];
1568 fDylibOverrides
.push_back(entry
);
1571 uint64_t Options::parseAddress(const char* addr
)
1574 uint64_t result
= strtoull(addr
, &endptr
, 16);
1578 uint32_t Options::parseProtection(const char* prot
)
1580 uint32_t result
= 0;
1581 for(const char* p
= prot
; *p
!= '\0'; ++p
) {
1582 switch(tolower(*p
)) {
1584 result
|= VM_PROT_READ
;
1587 result
|= VM_PROT_WRITE
;
1590 result
|= VM_PROT_EXECUTE
;
1595 throwf("unknown -segprot lettter in %s", prot
);
1603 // Parses number of form A[.B[.B[.D[.E]]]] into a uint64_t where the bits are a24.b10.c10.d10.e10
1605 uint64_t Options::parseVersionNumber64(const char* versionString
)
1613 a
= strtoul(versionString
, &end
, 10);
1614 if ( *end
== '.' ) {
1615 b
= strtoul(&end
[1], &end
, 10);
1616 if ( *end
== '.' ) {
1617 c
= strtoul(&end
[1], &end
, 10);
1618 if ( *end
== '.' ) {
1619 d
= strtoul(&end
[1], &end
, 10);
1620 if ( *end
== '.' ) {
1621 e
= strtoul(&end
[1], &end
, 10);
1626 if ( (*end
!= '\0') || (a
> 0xFFFFFF) || (b
> 0x3FF) || (c
> 0x3FF) || (d
> 0x3FF) || (e
> 0x3FF) )
1627 throwf("malformed 64-bit a.b.c.d.e version number: %s", versionString
);
1629 return (a
<< 40) | ( b
<< 30 ) | ( c
<< 20 ) | ( d
<< 10 ) | e
;
1633 uint32_t Options::currentVersion32() const
1635 // warn if it does not fit into 32 bit vers number
1636 uint32_t a
= (fDylibCurrentVersion
>> 40) & 0xFFFF;
1637 uint32_t b
= (fDylibCurrentVersion
>> 30) & 0xFF;
1638 uint32_t c
= (fDylibCurrentVersion
>> 20) & 0xFF;
1639 uint64_t rep32
= ((uint64_t)a
<< 40) | ((uint64_t)b
<< 30) | ((uint64_t)c
<< 20);
1640 if ( rep32
!= fDylibCurrentVersion
) {
1641 warning("truncating -current_version to fit in 32-bit space used by old mach-o format");
1642 a
= (fDylibCurrentVersion
>> 40) & 0xFFFFFF;
1645 b
= (fDylibCurrentVersion
>> 30) & 0x3FF;
1648 c
= (fDylibCurrentVersion
>> 20) & 0x3FF;
1652 return (a
<< 16) | ( b
<< 8 ) | c
;
1656 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1658 uint32_t Options::parseVersionNumber32(const char* versionString
)
1664 x
= strtoul(versionString
, &end
, 10);
1665 if ( *end
== '.' ) {
1666 y
= strtoul(&end
[1], &end
, 10);
1667 if ( *end
== '.' ) {
1668 z
= strtoul(&end
[1], &end
, 10);
1671 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
1672 throwf("malformed 32-bit x.y.z version number: %s", versionString
);
1674 return (x
<< 16) | ( y
<< 8 ) | z
;
1677 static const char* cstringSymbolName(const char* orderFileString
)
1680 asprintf(&result
, "cstring=%s", orderFileString
);
1681 // convert escaped characters
1683 for(const char* s
=result
; *s
!= '\0'; ++s
, ++d
) {
1721 // hexadecimal value of char
1725 while ( isxdigit(*s
) ) {
1730 value
+= ((toupper(*s
)-'A') + 10);
1737 if ( isdigit(*s
) ) {
1738 // octal value of char
1740 while ( isdigit(*s
) ) {
1741 value
= (value
<< 3) + (*s
-'0');
1756 void Options::parseOrderFile(const char* path
, bool cstring
)
1758 // order files override auto-ordering
1759 fAutoOrderInitializers
= false;
1761 // <rdar://problem/24856050> ld64 should prefer OrderFiles from the SDK over the ones in /
1762 for (const char* sdkPath
: fSDKPaths
) {
1763 char fullPath
[PATH_MAX
];
1764 strlcpy(fullPath
, sdkPath
, PATH_MAX
);
1765 strlcat(fullPath
, "/", PATH_MAX
);
1766 strlcat(fullPath
, path
, PATH_MAX
);
1767 struct stat statBuffer
;
1768 if ( stat(fullPath
, &statBuffer
) == 0 ) {
1769 path
= strdup(fullPath
);
1774 // read in whole file
1775 int fd
= ::open(path
, O_RDONLY
, 0);
1777 throwf("can't open order file: %s", path
);
1778 struct stat stat_buf
;
1779 ::fstat(fd
, &stat_buf
);
1780 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1782 throwf("can't process order file: %s", path
);
1783 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1784 throwf("can't read order file: %s", path
);
1786 p
[stat_buf
.st_size
] = '\n';
1787 if ( this->dumpDependencyInfo() )
1788 this->dumpDependency(Options::depMisc
, path
);
1790 // parse into vector of pairs
1791 char * const end
= &p
[stat_buf
.st_size
+1];
1792 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1793 char* symbolStart
= NULL
;
1794 for (char* s
= p
; s
< end
; ++s
) {
1800 else if ( !isspace(*s
) || cstring
) {
1806 if ( (*s
== '\n') || (!cstring
&& (*s
== '#')) ) {
1807 bool wasComment
= (*s
== '#');
1809 // removing any trailing spaces
1811 while ( isspace(*last
) ) {
1815 // if there is an architecture prefix, only use this symbol it if matches current arch
1816 if ( strncmp(symbolStart
, "ppc:", 4) == 0 ) {
1819 else if ( strncmp(symbolStart
, "ppc64:", 6) == 0 ) {
1822 else if ( strncmp(symbolStart
, "i386:", 5) == 0 ) {
1823 if ( fArchitecture
== CPU_TYPE_I386
)
1824 symbolStart
= &symbolStart
[5];
1828 else if ( strncmp(symbolStart
, "x86_64:", 7) == 0 ) {
1829 if ( fArchitecture
== CPU_TYPE_X86_64
)
1830 symbolStart
= &symbolStart
[7];
1834 else if ( strncmp(symbolStart
, "arm:", 4) == 0 ) {
1835 if ( fArchitecture
== CPU_TYPE_ARM
)
1836 symbolStart
= &symbolStart
[4];
1840 else if ( strncmp(symbolStart
, "arm64:", 6) == 0 ) {
1841 if ( fArchitecture
== CPU_TYPE_ARM64
)
1842 symbolStart
= &symbolStart
[6];
1846 if ( symbolStart
!= NULL
) {
1847 char* objFileName
= NULL
;
1848 char* colon
= strstr(symbolStart
, ".o:");
1849 if ( colon
!= NULL
) {
1851 objFileName
= symbolStart
;
1852 symbolStart
= &colon
[3];
1855 colon
= strstr(symbolStart
, ".o):");
1856 if ( colon
!= NULL
) {
1858 objFileName
= symbolStart
;
1859 symbolStart
= &colon
[4];
1862 // trim leading spaces
1863 while ( isspace(*symbolStart
) )
1865 Options::OrderedSymbol pair
;
1867 pair
.symbolName
= cstringSymbolName(symbolStart
);
1869 pair
.symbolName
= symbolStart
;
1870 pair
.objectFileName
= objFileName
;
1871 fOrderedSymbols
.push_back(pair
);
1886 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1889 void Options::parseSectionOrderFile(const char* segment
, const char* section
, const char* path
)
1891 if ( (strcmp(section
, "__cstring") == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1892 parseOrderFile(path
, true);
1894 else if ( (strncmp(section
, "__literal",9) == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1895 warning("sorting of __literal[4,8,16] sections not supported");
1898 // ignore section information and append all symbol names to global order file
1899 parseOrderFile(path
, false);
1903 void Options::addSection(const char* segment
, const char* section
, const char* path
)
1905 if ( strlen(segment
) > 16 )
1906 throw "-seccreate segment name max 16 chars";
1907 if ( strlen(section
) > 16 ) {
1908 char* tmp
= strdup(section
);
1910 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section
, tmp
);
1914 // read in whole file
1915 int fd
= ::open(path
, O_RDONLY
, 0);
1917 throwf("can't open -sectcreate file: %s", path
);
1918 struct stat stat_buf
;
1919 ::fstat(fd
, &stat_buf
);
1920 char* p
= (char*)malloc(stat_buf
.st_size
);
1922 throwf("can't process -sectcreate file: %s", path
);
1923 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1924 throwf("can't read -sectcreate file: %s", path
);
1927 // record section to create
1928 ExtraSection info
= { segment
, section
, path
, (uint8_t*)p
, (uint64_t)stat_buf
.st_size
};
1929 fExtraSections
.push_back(info
);
1932 void Options::addSectionRename(const char* srcSegment
, const char* srcSection
, const char* dstSegment
, const char* dstSection
)
1934 if ( strlen(srcSegment
) > 16 )
1935 throw "-rename_section segment name max 16 chars";
1936 if ( strlen(srcSection
) > 16 )
1937 throw "-rename_section section name max 16 chars";
1938 if ( strlen(dstSegment
) > 16 )
1939 throw "-rename_section segment name max 16 chars";
1940 if ( strlen(dstSection
) > 16 )
1941 throw "-rename_section section name max 16 chars";
1944 info
.fromSegment
= srcSegment
;
1945 info
.fromSection
= srcSection
;
1946 info
.toSegment
= dstSegment
;
1947 info
.toSection
= dstSection
;
1949 fSectionRenames
.push_back(info
);
1953 void Options::addSegmentRename(const char* srcSegment
, const char* dstSegment
)
1955 if ( strlen(srcSegment
) > 16 )
1956 throw "-rename_segment segment name max 16 chars";
1957 if ( strlen(dstSegment
) > 16 )
1958 throw "-rename_segment segment name max 16 chars";
1961 info
.fromSegment
= srcSegment
;
1962 info
.toSegment
= dstSegment
;
1964 fSegmentRenames
.push_back(info
);
1969 void Options::addSymbolMove(const char* dstSegment
, const char* symbolList
,
1970 std::vector
<SymbolsMove
>& list
, const char* optionName
)
1972 if ( strlen(dstSegment
) > 16 )
1973 throwf("%s segment name max 16 chars", optionName
);
1976 list
.push_back(tmp
);
1977 SymbolsMove
& info
= list
.back();
1978 info
.toSegment
= dstSegment
;
1979 loadExportFile(symbolList
, optionName
, info
.symbols
);
1982 bool Options::moveRwSymbol(const char* symName
, const char* filePath
, const char*& seg
, bool& wildCardMatch
) const
1984 for (std::vector
<SymbolsMove
>::const_iterator it
=fSymbolsMovesData
.begin(); it
!= fSymbolsMovesData
.end(); ++it
) {
1985 const SymbolsMove
& info
= *it
;
1986 if ( info
.symbols
.containsWithPrefix(symName
, filePath
, wildCardMatch
)) {
1987 seg
= info
.toSegment
;
1994 bool Options::moveRoSymbol(const char* symName
, const char* filePath
, const char*& seg
, bool& wildCardMatch
) const
1996 for (std::vector
<SymbolsMove
>::const_iterator it
=fSymbolsMovesCode
.begin(); it
!= fSymbolsMovesCode
.end(); ++it
) {
1997 const SymbolsMove
& info
= *it
;
1998 if ( info
.symbols
.containsWithPrefix(symName
, filePath
, wildCardMatch
)) {
1999 seg
= info
.toSegment
;
2006 void Options::addSectionAlignment(const char* segment
, const char* section
, const char* alignmentStr
)
2008 if ( strlen(segment
) > 16 )
2009 throw "-sectalign segment name max 16 chars";
2010 if ( strlen(section
) > 16 )
2011 throw "-sectalign section name max 16 chars";
2013 // argument to -sectalign is a hexadecimal number
2015 unsigned long value
= strtoul(alignmentStr
, &endptr
, 16);
2016 if ( *endptr
!= '\0')
2017 throw "argument for -sectalign is not a hexadecimal number";
2018 if ( value
> 0x8000 )
2019 throw "argument for -sectalign must be less than or equal to 0x8000";
2021 warning("zero is not a valid -sectalign");
2025 // alignment is power of 2 (e.g. page alignment = 12)
2026 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
2027 if ( (unsigned long)(1 << alignment
) != value
) {
2028 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
2029 segment
, section
, 1 << alignment
);
2032 SectionAlignment info
= { segment
, section
, alignment
};
2033 fSectionAlignments
.push_back(info
);
2036 void Options::addLibrary(const FileInfo
& info
)
2038 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
2039 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
2040 if ( strcmp(info
.path
, fit
->path
) == 0 ) {
2041 // if dylib is specified again but weak, record that it should be weak
2042 if ( info
.options
.fWeakImport
)
2043 fit
->options
.fWeakImport
= true;
2048 fInputFiles
.push_back(info
);
2051 void Options::warnObsolete(const char* arg
)
2053 warning("option %s is obsolete and being ignored", arg
);
2057 void Options::cannotBeUsedWithBitcode(const char* arg
)
2059 if ( fBundleBitcode
)
2060 throwf("%s and -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES) cannot be used together", arg
);
2063 std::string
Options::getVersionString32(uint32_t ver
) const
2065 if (ver
== 0 || ver
>= 0x10000000)
2068 unsigned microVersion
= ver
& 0xFF;
2069 unsigned minorVersion
= (ver
>> 8) & 0xFF;
2070 unsigned majorVersion
= (ver
>> 16) & 0xFF;
2071 std::stringstream versionString
;
2072 versionString
<< majorVersion
<< "." << minorVersion
<< "." << microVersion
;
2073 return versionString
.str();
2076 std::string
Options::getVersionString64(uint64_t ver
) const
2078 uint64_t a
= (ver
>> 40) & 0xFFFFFF;
2079 uint64_t b
= (ver
>> 30) & 0x3FF;
2080 uint64_t c
= (ver
>> 20) & 0x3FF;
2081 uint64_t d
= (ver
>> 10) & 0x3FF;
2082 uint64_t e
= ver
& 0x3FF;
2083 std::stringstream versionString
;
2084 versionString
<< a
<< "." << b
<< "." << c
<< "." << d
<< "." << e
;
2085 return versionString
.str();
2088 // Convert X.Y[.Z] to 32-bit value xxxxyyzz
2089 bool Options::parsePackedVersion32(const std::string
& versionStr
, uint32_t &result
)
2093 if ( versionStr
.empty() )
2096 size_t pos
= versionStr
.find('.');
2097 if ( pos
== std::string::npos
)
2100 std::string majorStr
= versionStr
.substr(0, pos
);
2101 std::string rest
= versionStr
.substr(pos
+1);
2105 int majorValue
= std::stoi(majorStr
, &majorEnd
);
2106 if ( majorEnd
!= majorStr
.size() )
2108 if ( majorValue
< 0 )
2110 if ( majorValue
> 65535 )
2113 std::string minorStr
;
2114 std::string microStr
;
2115 pos
= rest
.find('.');
2116 if ( pos
== std::string::npos
) {
2120 minorStr
= rest
.substr(0, pos
);
2121 microStr
= rest
.substr(pos
+1);
2125 int minorValue
= std::stoi(minorStr
, &minorEnd
);
2126 if ( minorEnd
!= minorStr
.size() )
2128 if ( minorValue
< 0 )
2130 if ( minorValue
> 255 )
2134 if ( !microStr
.empty() ) {
2136 microValue
= std::stoi(microStr
, µEnd
);
2137 if ( microEnd
!= microStr
.size() )
2139 if ( microValue
< 0 )
2141 if ( microValue
> 255 )
2145 result
= (majorValue
<< 16) | (minorValue
<< 8) | microValue
;
2150 // std::stoi() throws exception on malformed input
2155 std::string
Options::getSDKVersionStr() const
2157 return getVersionString32(fSDKVersion
);
2160 std::string
Options::getPlatformStr() const
2162 switch (fPlatform
) {
2163 case Options::kPlatformOSX
:
2165 case Options::kPlatformiOS
:
2166 if (targetIOSSimulator())
2167 return "iPhoneSimulator";
2170 case Options::kPlatformWatchOS
:
2171 if (targetIOSSimulator())
2172 return "watchOS Simulator";
2175 #if SUPPORT_APPLE_TV
2176 case Options::kPlatform_tvOS
:
2177 if (targetIOSSimulator())
2178 return "AppleTVSimulator";
2183 case Options::kPlatformUnknown
:
2188 std::vector
<std::string
> Options::writeBitcodeLinkOptions() const
2190 std::vector
<std::string
> linkCommand
;
2191 switch ( fOutputKind
) {
2192 case Options::kDynamicLibrary
:
2193 linkCommand
.push_back("-dylib");
2194 linkCommand
.push_back("-compatibility_version");
2195 if ( fDylibCompatVersion
!= 0 ) {
2196 linkCommand
.push_back(getVersionString32(fDylibCompatVersion
));
2198 linkCommand
.push_back(getVersionString32(currentVersion32()));
2200 if ( fDylibCurrentVersion
!= 0 ) {
2201 linkCommand
.push_back("-current_version");
2202 linkCommand
.push_back(getVersionString64(fDylibCurrentVersion
));
2204 linkCommand
.push_back("-install_name");
2205 linkCommand
.push_back(installPath());
2207 case Options::kDynamicExecutable
:
2208 linkCommand
.push_back("-execute");
2210 case Options::kObjectFile
:
2211 linkCommand
.push_back("-r");
2214 throwf("could not write bitcode options file output kind\n");
2217 if (!fImplicitlyLinkPublicDylibs
)
2218 linkCommand
.push_back("-no_implicit_dylibs");
2220 // Add deployment target.
2221 // Platform is allowed to be unknown for "ld -r".
2222 switch (fPlatform
) {
2223 case Options::kPlatformOSX
:
2224 linkCommand
.push_back("-macosx_version_min");
2225 linkCommand
.push_back(getVersionString32((unsigned)fMacVersionMin
));
2227 case Options::kPlatformiOS
:
2228 if (targetIOSSimulator())
2229 linkCommand
.push_back("-ios_simulator_version_min");
2231 linkCommand
.push_back("-ios_version_min");
2232 linkCommand
.push_back(getVersionString32((unsigned)fIOSVersionMin
));
2234 case Options::kPlatformWatchOS
:
2235 if (targetIOSSimulator())
2236 linkCommand
.push_back("-watchos_simulator_version_min");
2238 linkCommand
.push_back("-watchos_version_min");
2239 linkCommand
.push_back(getVersionString32((unsigned)fIOSVersionMin
));
2241 #if SUPPORT_APPLE_TV
2242 case Options::kPlatform_tvOS
:
2243 if (targetIOSSimulator())
2244 linkCommand
.push_back("-tvos_simulator_version_min");
2246 linkCommand
.push_back("-tvos_version_min");
2247 linkCommand
.push_back(getVersionString32((unsigned)fIOSVersionMin
));
2250 case Options::kPlatformUnknown
:
2251 if ( fOutputKind
!= Options::kObjectFile
) {
2252 throwf("platform is unknown for final bitcode bundle,"
2253 "deployment target and min version is required for -bitcode_bundle");
2261 linkCommand
.push_back("-e");
2262 linkCommand
.push_back(fEntryName
);
2266 if (!fRPaths
.empty()) {
2267 for (std::vector
<const char*>::const_iterator it
=fRPaths
.begin(); it
!= fRPaths
.end(); ++it
) {
2268 linkCommand
.push_back("-rpath");
2269 linkCommand
.push_back(*it
);
2273 // Other bitcode compatiable options
2274 if ( fObjCABIVersion1Override
) {
2275 linkCommand
.push_back("-objc_abi_version");
2276 linkCommand
.push_back("1");
2277 } else if ( fObjCABIVersion2Override
) {
2278 linkCommand
.push_back("-objc_abi_version");
2279 linkCommand
.push_back("2");
2281 if ( fExecutablePath
) {
2282 linkCommand
.push_back("-executable_path");
2283 linkCommand
.push_back(fExecutablePath
);
2286 linkCommand
.push_back("-dead_strip");
2287 if ( fExportDynamic
)
2288 linkCommand
.push_back("-export_dynamic");
2289 if ( fMarkAppExtensionSafe
&& fCheckAppExtensionSafe
)
2290 linkCommand
.push_back("-application_extension");
2292 if ( fSourceVersionLoadCommandForceOn
)
2293 linkCommand
.push_back("-add_source_version");
2294 if ( fSourceVersion
!= 0 ) {
2295 linkCommand
.push_back("-source_version");
2296 linkCommand
.push_back(getVersionString64(fSourceVersion
));
2299 // linker flag added by swift driver
2300 // rdar://problem/20108072
2301 if ( !fObjcCategoryMerging
)
2302 linkCommand
.push_back("-no_objc_category_merging");
2308 // Process all command line arguments.
2310 // The only error checking done here is that each option is valid and if it has arguments
2311 // that they too are valid.
2313 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
2314 // whichever was last on the command line is used.
2316 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
2318 void Options::parse(int argc
, const char* argv
[])
2320 // Store the original args in the link snapshot.
2321 fLinkSnapshot
.recordRawArgs(argc
, argv
);
2323 // pass one builds search list from -L and -F options
2324 this->buildSearchPaths(argc
, argv
);
2326 // reduce re-allocations
2327 fInputFiles
.reserve(32);
2329 // pass two parse all other options
2330 for(int i
=1; i
< argc
; ++i
) {
2331 const char* arg
= argv
[i
];
2333 if ( arg
[0] == '-' ) {
2334 // by default, copy one arg to the snapshot link command, and do no file copying
2335 int snapshotArgIndex
= i
;
2336 int snapshotArgCount
= -1; // -1 means compute count based on change in index
2337 int snapshotFileArgIndex
= -1; // -1 means no data file parameter to arg
2339 // Since we don't care about the files passed, just the option names, we do this here.
2341 fprintf (stderr
, "[Logging ld64 options]\t%s\n", arg
);
2343 if ( (arg
[1] == 'L') || (arg
[1] == 'F') ) {
2344 snapshotArgCount
= 0; // stripped out of link snapshot
2347 // previously handled by buildSearchPaths()
2349 // The one gnu style option we have to keep compatibility
2350 // with gcc. Might as well have the single hyphen one as well.
2351 else if ( (strcmp(arg
, "--help") == 0)
2352 || (strcmp(arg
, "-help") == 0)) {
2353 fprintf (stdout
, "ld64: For information on command line options please use 'man ld'.\n");
2356 else if ( strcmp(arg
, "-arch") == 0 ) {
2357 parseArch(argv
[++i
]);
2359 else if ( strcmp(arg
, "-dynamic") == 0 ) {
2362 else if ( strcmp(arg
, "-static") == 0 ) {
2364 if ( (fOutputKind
!= kObjectFile
) && (fOutputKind
!= kKextBundle
) ) {
2365 fOutputKind
= kStaticExecutable
;
2367 cannotBeUsedWithBitcode(arg
);
2369 else if ( strcmp(arg
, "-dylib") == 0 ) {
2370 fOutputKind
= kDynamicLibrary
;
2372 else if ( strcmp(arg
, "-bundle") == 0 ) {
2373 fOutputKind
= kDynamicBundle
;
2374 cannotBeUsedWithBitcode(arg
);
2376 else if ( strcmp(arg
, "-dylinker") == 0 ) {
2377 fOutputKind
= kDyld
;
2378 cannotBeUsedWithBitcode(arg
);
2380 else if ( strcmp(arg
, "-execute") == 0 ) {
2381 if ( fOutputKind
!= kStaticExecutable
)
2382 fOutputKind
= kDynamicExecutable
;
2384 else if ( strcmp(arg
, "-preload") == 0 ) {
2385 fOutputKind
= kPreload
;
2386 cannotBeUsedWithBitcode(arg
);
2388 else if ( strcmp(arg
, "-r") == 0 ) {
2389 fOutputKind
= kObjectFile
;
2391 else if ( strcmp(arg
, "-kext") == 0 ) {
2392 fOutputKind
= kKextBundle
;
2393 cannotBeUsedWithBitcode(arg
);
2395 else if ( strcmp(arg
, "-o") == 0 ) {
2396 snapshotArgCount
= 0;
2397 fOutputFile
= argv
[++i
];
2398 fLinkSnapshot
.setSnapshotName(fOutputFile
);
2400 else if ( strncmp(arg
, "-lazy-l", 7) == 0 ) {
2401 snapshotArgCount
= 0;
2402 FileInfo info
= findLibrary(&arg
[7], true);
2403 info
.options
.fLazyLoad
= true;
2404 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2406 fUsingLazyDylibLinking
= true;
2407 cannotBeUsedWithBitcode(arg
);
2409 else if ( strcmp(arg
, "-lto_library") == 0 ) {
2410 snapshotFileArgIndex
= 1;
2411 fOverridePathlibLTO
= argv
[++i
];
2412 if ( fOverridePathlibLTO
== NULL
)
2413 throw "missing argument to -lto_library";
2415 else if ( strcmp(arg
, "-cache_path_lto") == 0 ) {
2416 fLtoCachePath
= argv
[++i
];
2417 if ( fLtoCachePath
== NULL
)
2418 throw "missing argument to -cache_path_lto";
2420 else if ( strcmp(arg
, "-prune_interval_lto") == 0 ) {
2421 const char* value
= argv
[++i
];
2422 if ( value
== NULL
)
2423 throw "missing argument to -prune_interval_lto";
2425 fLtoPruneInterval
= strtoul(value
, &endptr
, 10);
2426 if ( *endptr
!= '\0')
2427 throw "invalid argument for -prune_interval_lto";
2429 else if ( strcmp(arg
, "-prune_after_lto") == 0 ) {
2430 const char* value
= argv
[++i
];
2431 if ( value
== NULL
)
2432 throw "missing argument to -prune_after_lto";
2434 fLtoPruneAfter
= strtoul(value
, &endptr
, 10);
2435 if ( *endptr
!= '\0')
2436 throw "invalid argument for -prune_after_lto";
2438 else if ( strcmp(arg
, "-max_relative_cache_size_lto") == 0 ) {
2439 const char* value
= argv
[++i
];
2440 if ( value
== NULL
)
2441 throw "missing argument to -max_relative_cache_size_lto";
2443 fLtoMaxCacheSize
= strtoul(value
, &endptr
, 10);
2444 if ( *endptr
!= '\0')
2445 throw "invalid argument for -max_relative_cache_size_lto";
2446 if (fLtoMaxCacheSize
> 100)
2447 throw "Expect a value between 0 and 100 for -max_relative_cache_size_lto";
2449 else if ( (arg
[1] == 'l') && (strncmp(arg
,"-lazy_",6) !=0) ) {
2450 snapshotArgCount
= 0;
2451 FileInfo info
= findLibrary(&arg
[2]);
2452 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2455 // This causes a dylib to be weakly bound at
2456 // link time. This corresponds to weak_import.
2457 else if ( strncmp(arg
, "-weak-l", 7) == 0 ) {
2458 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2459 snapshotArgCount
= 0;
2460 FileInfo info
= findLibrary(&arg
[7]);
2461 info
.options
.fWeakImport
= true;
2462 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2465 // Avoid lazy binding.
2466 else if ( strcmp(arg
, "-bind_at_load") == 0 ) {
2468 cannotBeUsedWithBitcode(arg
);
2470 else if ( strcmp(arg
, "-twolevel_namespace") == 0 ) {
2471 fNameSpace
= kTwoLevelNameSpace
;
2473 else if ( strcmp(arg
, "-flat_namespace") == 0 ) {
2474 fNameSpace
= kFlatNameSpace
;
2475 cannotBeUsedWithBitcode(arg
);
2477 // Also sets a bit to ensure dyld causes everything
2478 // in the namespace to be flat.
2480 else if ( strcmp(arg
, "-force_flat_namespace") == 0 ) {
2481 fNameSpace
= kForceFlatNameSpace
;
2482 cannotBeUsedWithBitcode(arg
);
2484 // Similar to --whole-archive.
2485 else if ( strcmp(arg
, "-all_load") == 0 ) {
2486 fFullyLoadArchives
= true;
2488 else if ( strcmp(arg
, "-noall_load") == 0) {
2491 // Similar to -all_load
2492 else if ( strcmp(arg
, "-ObjC") == 0 ) {
2493 fLoadAllObjcObjectsFromArchives
= true;
2495 // Similar to -all_load, but for the following archive only.
2496 else if ( strcmp(arg
, "-force_load") == 0 ) {
2497 FileInfo info
= findFile(argv
[++i
]);
2498 info
.options
.fForceLoad
= true;
2499 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2502 // Library versioning.
2503 else if ( (strcmp(arg
, "-dylib_compatibility_version") == 0)
2504 || (strcmp(arg
, "-compatibility_version") == 0)) {
2505 const char* vers
= argv
[++i
];
2507 throw "-dylib_compatibility_version missing <version>";
2508 fDylibCompatVersion
= parseVersionNumber32(vers
);
2510 else if ( (strcmp(arg
, "-dylib_current_version") == 0)
2511 || (strcmp(arg
, "-current_version") == 0)) {
2512 const char* vers
= argv
[++i
];
2514 throw "-dylib_current_version missing <version>";
2515 fDylibCurrentVersion
= parseVersionNumber64(vers
);
2517 else if ( strcmp(arg
, "-sectorder") == 0 ) {
2518 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2519 throw "-sectorder missing <segment> <section> <file-path>";
2520 snapshotFileArgIndex
= 3;
2521 parseSectionOrderFile(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2523 cannotBeUsedWithBitcode(arg
);
2525 else if ( strcmp(arg
, "-order_file") == 0 ) {
2526 snapshotFileArgIndex
= 1;
2527 parseOrderFile(argv
[++i
], false);
2529 else if ( strcmp(arg
, "-order_file_statistics") == 0 ) {
2530 fPrintOrderFileStatistics
= true;
2531 cannotBeUsedWithBitcode(arg
);
2533 // ??? Deprecate segcreate.
2534 // -sectcreate puts whole files into a section in the output.
2535 else if ( (strcmp(arg
, "-sectcreate") == 0) || (strcmp(arg
, "-segcreate") == 0) ) {
2536 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2537 throw "-sectcreate missing <segment> <section> <file-path>";
2538 snapshotFileArgIndex
= 3;
2539 addSection(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2542 // Since we have a full path in binary/library names we need to be able to override it.
2543 else if ( (strcmp(arg
, "-dylib_install_name") == 0)
2544 || (strcmp(arg
, "-dylinker_install_name") == 0)
2545 || (strcmp(arg
, "-install_name") == 0)) {
2546 fDylibInstallName
= argv
[++i
];
2547 if ( fDylibInstallName
== NULL
)
2548 throw "-install_name missing <path>";
2550 // Sets the base address of the output.
2551 else if ( (strcmp(arg
, "-seg1addr") == 0) || (strcmp(arg
, "-image_base") == 0) ) {
2552 const char* address
= argv
[++i
];
2553 if ( address
== NULL
)
2554 throwf("%s missing <address>", arg
);
2555 fBaseAddress
= parseAddress(address
);
2556 uint64_t temp
= ((fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
2557 if ( fBaseAddress
!= temp
) {
2558 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment
);
2559 fBaseAddress
= temp
;
2561 cannotBeUsedWithBitcode(arg
);
2563 else if ( strcmp(arg
, "-e") == 0 ) {
2564 fEntryName
= argv
[++i
];
2566 // Same as -@ from the FSF linker.
2567 else if ( strcmp(arg
, "-filelist") == 0 ) {
2568 snapshotArgCount
= 0;
2569 const char* path
= argv
[++i
];
2570 if ( (path
== NULL
) || (path
[0] == '-') )
2571 throw "-filelist missing <path>";
2572 ld::File::Ordinal baseOrdinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2573 loadFileList(path
, baseOrdinal
);
2575 else if ( strcmp(arg
, "-keep_private_externs") == 0 ) {
2576 cannotBeUsedWithBitcode(arg
);
2577 fKeepPrivateExterns
= true;
2579 else if ( strcmp(arg
, "-final_output") == 0 ) {
2580 fFinalName
= argv
[++i
];
2582 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
2583 // just ensures that this happens for cross object file boundaries.
2584 else if ( (strcmp(arg
, "-interposable") == 0) || (strcmp(arg
, "-multi_module") == 0)) {
2585 switch ( fInterposeMode
) {
2586 case kInterposeNone
:
2587 case kInterposeAllExternal
:
2588 fInterposeMode
= kInterposeAllExternal
;
2590 case kInterposeSome
:
2591 // do nothing, -interposable_list overrides -interposable"
2594 cannotBeUsedWithBitcode(arg
);
2596 else if ( strcmp(arg
, "-interposable_list") == 0 ) {
2597 snapshotFileArgIndex
= 1;
2598 fInterposeMode
= kInterposeSome
;
2599 loadExportFile(argv
[++i
], "-interposable_list", fInterposeList
);
2600 cannotBeUsedWithBitcode(arg
);
2602 // Default for -interposable/-multi_module/-single_module.
2603 else if ( strcmp(arg
, "-single_module") == 0 ) {
2604 fInterposeMode
= kInterposeNone
;
2606 else if ( strcmp(arg
, "-exported_symbols_list") == 0 ) {
2607 snapshotFileArgIndex
= 1;
2608 if ( fExportMode
== kDontExportSome
)
2609 throw "can't use -exported_symbols_list and -unexported_symbols_list";
2610 fExportMode
= kExportSome
;
2611 loadExportFile(argv
[++i
], "-exported_symbols_list", fExportSymbols
);
2613 else if ( strcmp(arg
, "-unexported_symbols_list") == 0 ) {
2614 snapshotFileArgIndex
= 1;
2615 if ( fExportMode
== kExportSome
)
2616 throw "can't use -unexported_symbols_list and -exported_symbols_list";
2617 fExportMode
= kDontExportSome
;
2618 loadExportFile(argv
[++i
], "-unexported_symbols_list", fDontExportSymbols
);
2620 else if ( strcmp(arg
, "-exported_symbol") == 0 ) {
2621 if ( fExportMode
== kDontExportSome
)
2622 throw "can't use -exported_symbol and -unexported_symbols";
2623 fExportMode
= kExportSome
;
2624 fExportSymbols
.insert(argv
[++i
]);
2626 else if ( strcmp(arg
, "-unexported_symbol") == 0 ) {
2627 if ( fExportMode
== kExportSome
)
2628 throw "can't use -unexported_symbol and -exported_symbol";
2629 fExportMode
= kDontExportSome
;
2630 fDontExportSymbols
.insert(argv
[++i
]);
2632 else if ( strcmp(arg
, "-non_global_symbols_no_strip_list") == 0 ) {
2633 snapshotFileArgIndex
= 1;
2634 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveExclude
)
2635 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2636 fLocalSymbolHandling
= kLocalSymbolsSelectiveInclude
;
2637 loadExportFile(argv
[++i
], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded
);
2638 cannotBeUsedWithBitcode(arg
);
2640 else if ( strcmp(arg
, "-non_global_symbols_strip_list") == 0 ) {
2641 snapshotFileArgIndex
= 1;
2642 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveInclude
)
2643 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2644 fLocalSymbolHandling
= kLocalSymbolsSelectiveExclude
;
2645 loadExportFile(argv
[++i
], "-non_global_symbols_strip_list", fLocalSymbolsExcluded
);
2646 cannotBeUsedWithBitcode(arg
);
2649 else if ( strcmp(arg
, "-no_arch_warnings") == 0 ) {
2650 fIgnoreOtherArchFiles
= true;
2652 else if ( strcmp(arg
, "-force_cpusubtype_ALL") == 0 ) {
2653 fForceSubtypeAll
= true;
2654 fAllowCpuSubtypeMismatches
= true;
2655 cannotBeUsedWithBitcode(arg
);
2657 // Similar to -weak-l but uses the absolute path name to the library.
2658 else if ( strcmp(arg
, "-weak_library") == 0 ) {
2659 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2660 snapshotArgCount
= 0;
2661 FileInfo info
= findFile(argv
[++i
]);
2662 info
.options
.fWeakImport
= true;
2663 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2665 cannotBeUsedWithBitcode(arg
);
2667 else if ( strcmp(arg
, "-lazy_library") == 0 ) {
2668 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2669 snapshotArgCount
= 0;
2670 FileInfo info
= findFile(argv
[++i
]);
2671 info
.options
.fLazyLoad
= true;
2672 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2674 fUsingLazyDylibLinking
= true;
2675 cannotBeUsedWithBitcode(arg
);
2677 else if ( strcmp(arg
, "-framework") == 0 ) {
2678 snapshotArgCount
= 0;
2679 FileInfo info
= findFramework(argv
[++i
]);
2680 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2683 else if ( strcmp(arg
, "-weak_framework") == 0 ) {
2684 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2685 snapshotArgCount
= 0;
2686 FileInfo info
= findFramework(argv
[++i
]);
2687 info
.options
.fWeakImport
= true;
2688 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2691 else if ( strcmp(arg
, "-lazy_framework") == 0 ) {
2692 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2693 snapshotArgCount
= 0;
2694 FileInfo info
= findFramework(argv
[++i
]);
2695 info
.options
.fLazyLoad
= true;
2696 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2698 fUsingLazyDylibLinking
= true;
2699 cannotBeUsedWithBitcode(arg
);
2701 else if ( strcmp(arg
, "-search_paths_first") == 0 ) {
2702 // previously handled by buildSearchPaths()
2704 else if ( strcmp(arg
, "-search_dylibs_first") == 0 ) {
2705 // previously handled by buildSearchPaths()
2707 else if ( strcmp(arg
, "-undefined") == 0 ) {
2708 setUndefinedTreatment(argv
[++i
]);
2709 cannotBeUsedWithBitcode(arg
);
2711 // Debugging output flag.
2712 else if ( strcmp(arg
, "-arch_multiple") == 0 ) {
2713 fMessagesPrefixedWithArchitecture
= true;
2715 // Specify what to do with relocations in read only
2716 // sections like .text. Could be errors, warnings,
2717 // or suppressed. Currently we do nothing with the
2719 else if ( strcmp(arg
, "-read_only_relocs") == 0 ) {
2720 switch ( parseTreatment(argv
[++i
]) ) {
2723 throw "-read_only_relocs missing [ warning | error | suppress ]";
2725 fWarnTextRelocs
= true;
2726 fAllowTextRelocs
= true;
2727 cannotBeUsedWithBitcode(arg
);
2730 fWarnTextRelocs
= false;
2731 fAllowTextRelocs
= true;
2732 cannotBeUsedWithBitcode(arg
);
2735 fWarnTextRelocs
= false;
2736 fAllowTextRelocs
= false;
2740 else if ( strcmp(arg
, "-sect_diff_relocs") == 0 ) {
2744 // Warn, error or make strong a mismatch between weak
2745 // and non-weak references.
2746 else if ( strcmp(arg
, "-weak_reference_mismatches") == 0 ) {
2747 setWeakReferenceMismatchTreatment(argv
[++i
]);
2749 // For a deployment target of 10.3 and earlier ld64 will
2750 // prebind an executable with 0s in all addresses that
2751 // are prebound. This can then be fixed up by update_prebinding
2752 // later. Prebinding is less useful on 10.4 and greater.
2753 else if ( strcmp(arg
, "-prebind") == 0 ) {
2755 cannotBeUsedWithBitcode(arg
);
2757 else if ( strcmp(arg
, "-noprebind") == 0 ) {
2761 else if ( strcmp(arg
, "-prebind_allow_overlap") == 0 ) {
2764 else if ( strcmp(arg
, "-prebind_all_twolevel_modules") == 0 ) {
2767 else if ( strcmp(arg
, "-noprebind_all_twolevel_modules") == 0 ) {
2770 else if ( strcmp(arg
, "-nofixprebinding") == 0 ) {
2773 // This should probably be deprecated when we respect -L and -F
2774 // when searching for libraries.
2775 else if ( strcmp(arg
, "-dylib_file") == 0 ) {
2776 // ignore for snapshot because a stub dylib will be created in the snapshot
2777 snapshotArgCount
= 0;
2778 addDylibOverride(argv
[++i
]);
2779 cannotBeUsedWithBitcode(arg
);
2781 // What to expand @executable_path to if found in dependent dylibs
2782 else if ( strcmp(arg
, "-executable_path") == 0 ) {
2783 fExecutablePath
= argv
[++i
];
2784 if ( (fExecutablePath
== NULL
) || (fExecutablePath
[0] == '-') )
2785 throw "-executable_path missing <path>";
2786 // if a directory was passed, add / to end
2787 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2788 struct stat statBuffer
;
2789 if ( stat(fExecutablePath
, &statBuffer
) == 0 ) {
2790 if ( (statBuffer
.st_mode
& S_IFMT
) == S_IFDIR
) {
2791 char* pathWithSlash
= new char[strlen(fExecutablePath
)+2];
2792 strcpy(pathWithSlash
, fExecutablePath
);
2793 strcat(pathWithSlash
, "/");
2794 fExecutablePath
= pathWithSlash
;
2798 // Aligns all segments to the power of 2 boundary specified.
2799 else if ( strcmp(arg
, "-segalign") == 0 ) {
2800 const char* size
= argv
[++i
];
2802 throw "-segalign missing <size>";
2803 fSegmentAlignment
= parseAddress(size
);
2804 uint8_t alignment
= (uint8_t)__builtin_ctz(fSegmentAlignment
);
2805 uint32_t p2aligned
= (1 << alignment
);
2806 if ( p2aligned
!= fSegmentAlignment
) {
2807 warning("alignment for -segalign %s is not a power of two, using 0x%X", size
, p2aligned
);
2808 fSegmentAlignment
= p2aligned
;
2810 cannotBeUsedWithBitcode(arg
);
2812 // Puts a specified segment at a particular address that must
2813 // be a multiple of the segment alignment.
2814 else if ( strcmp(arg
, "-segaddr") == 0 ) {
2816 seg
.name
= argv
[++i
];
2817 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2818 throw "-segaddr missing segName Adddress";
2819 seg
.address
= parseAddress(argv
[++i
]);
2820 uint64_t temp
= ((seg
.address
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
2821 if ( seg
.address
!= temp
)
2822 warning("-segaddr %s not %lld byte aligned", seg
.name
, fSegmentAlignment
);
2823 fCustomSegmentAddresses
.push_back(seg
);
2824 cannotBeUsedWithBitcode(arg
);
2826 // ??? Deprecate when we deprecate split-seg.
2827 else if ( strcmp(arg
, "-segs_read_only_addr") == 0 ) {
2828 fBaseAddress
= parseAddress(argv
[++i
]);
2829 cannotBeUsedWithBitcode(arg
);
2831 // ??? Deprecate when we deprecate split-seg.
2832 else if ( strcmp(arg
, "-segs_read_write_addr") == 0 ) {
2833 fBaseWritableAddress
= parseAddress(argv
[++i
]);
2835 cannotBeUsedWithBitcode(arg
);
2837 // ??? Deprecate when we get rid of basing at build time.
2838 else if ( strcmp(arg
, "-seg_addr_table") == 0 ) {
2839 snapshotFileArgIndex
= 1;
2840 const char* name
= argv
[++i
];
2842 throw "-seg_addr_table missing argument";
2843 fSegAddrTablePath
= name
;
2844 cannotBeUsedWithBitcode(arg
);
2846 else if ( strcmp(arg
, "-seg_addr_table_filename") == 0 ) {
2850 else if ( strcmp(arg
, "-segprot") == 0 ) {
2852 seg
.name
= argv
[++i
];
2853 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) || (argv
[i
+2] == NULL
) )
2854 throw "-segprot missing segName max-prot init-prot";
2855 seg
.max
= parseProtection(argv
[++i
]);
2856 seg
.init
= parseProtection(argv
[++i
]);
2857 if ( strcmp(seg
.name
, "__LINKEDIT") == 0 )
2858 warning("-segprot cannot be used to modify __LINKEDIT protections");
2860 fCustomSegmentProtections
.push_back(seg
);
2861 cannotBeUsedWithBitcode(arg
);
2863 else if ( strcmp(arg
, "-pagezero_size") == 0 ) {
2864 const char* size
= argv
[++i
];
2866 throw "-pagezero_size missing <size>";
2867 fZeroPageSize
= parseAddress(size
);
2868 uint64_t temp
= fZeroPageSize
& (-4096); // page align
2869 if ( (fZeroPageSize
!= temp
) )
2870 warning("-pagezero_size not page aligned, rounding down");
2871 fZeroPageSize
= temp
;
2872 cannotBeUsedWithBitcode(arg
);
2874 else if ( strcmp(arg
, "-stack_addr") == 0 ) {
2875 const char* address
= argv
[++i
];
2876 if ( address
== NULL
)
2877 throw "-stack_addr missing <address>";
2878 fStackAddr
= parseAddress(address
);
2879 cannotBeUsedWithBitcode(arg
);
2881 else if ( strcmp(arg
, "-stack_size") == 0 ) {
2882 const char* size
= argv
[++i
];
2884 throw "-stack_size missing <address>";
2885 fStackSize
= parseAddress(size
);
2887 else if ( strcmp(arg
, "-allow_stack_execute") == 0 ) {
2888 fExecutableStack
= true;
2889 cannotBeUsedWithBitcode(arg
);
2891 else if ( strcmp(arg
, "-allow_heap_execute") == 0 ) {
2892 fDisableNonExecutableHeap
= true;
2893 cannotBeUsedWithBitcode(arg
);
2895 else if ( strcmp(arg
, "-sectalign") == 0 ) {
2896 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2897 throw "-sectalign missing <segment> <section> <file-path>";
2898 addSectionAlignment(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2900 cannotBeUsedWithBitcode(arg
);
2902 else if ( strcmp(arg
, "-sectorder_detail") == 0 ) {
2905 else if ( strcmp(arg
, "-sectobjectsymbols") == 0 ) {
2909 else if ( strcmp(arg
, "-bundle_loader") == 0 ) {
2910 snapshotFileArgIndex
= 1;
2911 fBundleLoader
= argv
[++i
];
2912 if ( (fBundleLoader
== NULL
) || (fBundleLoader
[0] == '-') )
2913 throw "-bundle_loader missing <path>";
2914 FileInfo info
= findFile(fBundleLoader
);
2915 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2916 info
.options
.fBundleLoader
= true;
2917 fInputFiles
.push_back(info
);
2919 else if ( strcmp(arg
, "-private_bundle") == 0 ) {
2922 else if ( strcmp(arg
, "-twolevel_namespace_hints") == 0 ) {
2925 // Use this flag to set default behavior for deployement targets.
2926 else if ( strcmp(arg
, "-macosx_version_min") == 0 ) {
2927 const char* macVers
= argv
[++i
];
2928 if ( macVers
== NULL
)
2929 throw "-macosx_version_min missing version argument";
2930 const char* envMacVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
2931 const char* enviPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
2932 if ( (envMacVers
!= NULL
) && (enviPhoneVers
!= NULL
) ) {
2933 // <rdar://problem/13774329> when conflicting deployments set, break tie by looking at syslibroot
2934 warning("both MACOSX_DEPLOYMENT_TARGET and IPHONEOS_DEPLOYMENT_TARGET are set");
2935 if ( !fSDKPaths
.empty() ) {
2936 const char* sysrootPath
= fSDKPaths
.back();
2937 const char* lastSlash
= strrchr(sysrootPath
, '/');
2938 if ( strstr(lastSlash
, "Simulator") != NULL
)
2939 setIOSVersionMin(enviPhoneVers
);
2941 setMacOSXVersionMin(macVers
);
2944 setMacOSXVersionMin(macVers
);
2948 setMacOSXVersionMin(macVers
);
2951 else if ( (strcmp(arg
, "-ios_version_min") == 0) || (strcmp(arg
, "-iphoneos_version_min") == 0) ) {
2952 const char* vers
= argv
[++i
];
2954 throw "-ios_version_min missing version argument";
2955 setIOSVersionMin(vers
);
2957 else if ( strcmp(arg
, "-ios_simulator_version_min") == 0 ) {
2958 const char* vers
= argv
[++i
];
2960 throw "-ios_simulator_version_min missing version argument";
2961 setIOSVersionMin(vers
);
2962 fTargetIOSSimulator
= true;
2964 else if ( strcmp(arg
, "-watchos_version_min") == 0 ) {
2965 const char* vers
= argv
[++i
];
2967 throw "-watchos_version_min missing version argument";
2968 setWatchOSVersionMin(vers
);
2970 else if ( strcmp(arg
, "-watchos_simulator_version_min") == 0 ) {
2971 const char* vers
= argv
[++i
];
2973 throw "-watchos_simulator_version_min missing version argument";
2974 setWatchOSVersionMin(vers
);
2975 fTargetIOSSimulator
= true;
2977 #if SUPPORT_APPLE_TV
2978 else if ( strcmp(arg
, "-tvos_version_min") == 0 ) {
2979 const char* vers
= argv
[++i
];
2981 throw "-tvos_version_min missing version argument";
2982 setIOSVersionMin(vers
);
2983 fPlatform
= kPlatform_tvOS
;
2985 else if ( strcmp(arg
, "-tvos_simulator_version_min") == 0 ) {
2986 const char* vers
= argv
[++i
];
2988 throw "-tvos_simulator_version_min missing version argument";
2989 setIOSVersionMin(vers
);
2990 fPlatform
= kPlatform_tvOS
;
2991 fTargetIOSSimulator
= true;
2994 else if ( strcmp(arg
, "-multiply_defined") == 0 ) {
2995 //warnObsolete(arg);
2998 else if ( strcmp(arg
, "-multiply_defined_unused") == 0 ) {
3002 else if ( strcmp(arg
, "-nomultidefs") == 0 ) {
3005 // Display each file in which the argument symbol appears and whether
3006 // the file defines or references it. This option takes an argument
3007 // as -y<symbol> note that there is no space.
3008 else if ( strncmp(arg
, "-y", 2) == 0 ) {
3011 // Same output as -y, but output <arg> number of undefined symbols only.
3012 else if ( strcmp(arg
, "-Y") == 0 ) {
3013 //warnObsolete(arg);
3016 // This option affects all objects linked into the final result.
3017 else if ( strcmp(arg
, "-m") == 0 ) {
3020 else if ( (strcmp(arg
, "-why_load") == 0) || (strcmp(arg
, "-whyload") == 0) ) {
3023 else if ( strcmp(arg
, "-why_live") == 0 ) {
3024 const char* name
= argv
[++i
];
3026 throw "-why_live missing symbol name argument";
3027 fWhyLive
.insert(name
);
3029 else if ( strcmp(arg
, "-u") == 0 ) {
3030 const char* name
= argv
[++i
];
3032 throw "-u missing argument";
3033 fInitialUndefines
.push_back(name
);
3034 cannotBeUsedWithBitcode(arg
);
3036 else if ( strcmp(arg
, "-U") == 0 ) {
3037 const char* name
= argv
[++i
];
3039 throw "-U missing argument";
3040 fAllowedUndefined
.insert(name
);
3041 cannotBeUsedWithBitcode(arg
);
3043 else if ( strcmp(arg
, "-s") == 0 ) {
3045 fLocalSymbolHandling
= kLocalSymbolsNone
;
3046 fDebugInfoStripping
= Options::kDebugInfoNone
;
3048 else if ( strcmp(arg
, "-x") == 0 ) {
3049 fLocalSymbolHandling
= kLocalSymbolsNone
;
3051 else if ( strcmp(arg
, "-S") == 0 ) {
3052 fDebugInfoStripping
= Options::kDebugInfoNone
;
3054 else if ( strcmp(arg
, "-X") == 0 ) {
3057 else if ( strcmp(arg
, "-Si") == 0 ) {
3059 fDebugInfoStripping
= Options::kDebugInfoFull
;
3061 else if ( strcmp(arg
, "-b") == 0 ) {
3064 else if ( strcmp(arg
, "-Sn") == 0 ) {
3066 fDebugInfoStripping
= Options::kDebugInfoFull
;
3068 else if ( strcmp(arg
, "-Sp") == 0 ) {
3071 else if ( strcmp(arg
, "-dead_strip") == 0 ) {
3074 else if ( strcmp(arg
, "-no_dead_strip_inits_and_terms") == 0 ) {
3077 else if ( strcmp(arg
, "-w") == 0 ) {
3078 // previously handled by buildSearchPaths()
3080 else if ( strcmp(arg
, "-fatal_warnings") == 0 ) {
3081 // previously handled by buildSearchPaths()
3083 else if ( strcmp(arg
, "-arch_errors_fatal") == 0 ) {
3084 fErrorOnOtherArchFiles
= true;
3086 else if ( strcmp(arg
, "-M") == 0 ) {
3089 else if ( strcmp(arg
, "-headerpad") == 0 ) {
3090 const char* size
= argv
[++i
];
3092 throw "-headerpad missing argument";
3093 fMinimumHeaderPad
= parseAddress(size
);
3094 cannotBeUsedWithBitcode(arg
);
3096 else if ( strcmp(arg
, "-headerpad_max_install_names") == 0 ) {
3097 // ignore -headerpad_max_install_names when compiling with bitcode
3098 // rdar://problem/20748962
3099 if ( fBundleBitcode
)
3100 warning("-headerpad_max_install_names is ignored when used with -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES)");
3102 fMaxMinimumHeaderPad
= true;
3104 else if ( strcmp(arg
, "-t") == 0 ) {
3105 fLogAllFiles
= true;
3107 else if ( strcmp(arg
, "-whatsloaded") == 0 ) {
3108 fLogObjectFiles
= true;
3110 else if ( strcmp(arg
, "-A") == 0 ) {
3114 else if ( strcmp(arg
, "-umbrella") == 0 ) {
3115 const char* name
= argv
[++i
];
3117 throw "-umbrella missing argument";
3118 fUmbrellaName
= name
;
3119 cannotBeUsedWithBitcode(arg
);
3121 else if ( strcmp(arg
, "-allowable_client") == 0 ) {
3122 const char* name
= argv
[++i
];
3125 throw "-allowable_client missing argument";
3127 fAllowableClients
.push_back(name
);
3128 cannotBeUsedWithBitcode(arg
);
3130 else if ( strcmp(arg
, "-client_name") == 0 ) {
3131 const char* name
= argv
[++i
];
3134 throw "-client_name missing argument";
3137 cannotBeUsedWithBitcode(arg
);
3139 else if ( strcmp(arg
, "-sub_umbrella") == 0 ) {
3140 const char* name
= argv
[++i
];
3142 throw "-sub_umbrella missing argument";
3143 fSubUmbellas
.push_back(name
);
3144 cannotBeUsedWithBitcode(arg
);
3146 else if ( strcmp(arg
, "-sub_library") == 0 ) {
3147 const char* name
= argv
[++i
];
3149 throw "-sub_library missing argument";
3150 fSubLibraries
.push_back(name
);
3151 cannotBeUsedWithBitcode(arg
);
3153 else if ( strcmp(arg
, "-init") == 0 ) {
3154 const char* name
= argv
[++i
];
3156 throw "-init missing argument";
3157 fInitFunctionName
= name
;
3158 cannotBeUsedWithBitcode(arg
);
3160 else if ( strcmp(arg
, "-dot") == 0 ) {
3161 const char* name
= argv
[++i
];
3163 throw "-dot missing argument";
3164 fDotOutputFile
= name
;
3165 cannotBeUsedWithBitcode(arg
);
3167 else if ( strcmp(arg
, "-warn_commons") == 0 ) {
3168 fWarnCommons
= true;
3170 else if ( strcmp(arg
, "-commons") == 0 ) {
3171 fCommonsMode
= parseCommonsTreatment(argv
[++i
]);
3173 else if ( strcmp(arg
, "-keep_relocs") == 0 ) {
3174 fKeepRelocations
= true;
3176 else if ( strcmp(arg
, "-warn_stabs") == 0 ) {
3179 else if ( strcmp(arg
, "-pause") == 0 ) {
3182 else if ( strcmp(arg
, "-print_statistics") == 0 ) {
3185 else if ( strcmp(arg
, "-d") == 0 ) {
3186 fMakeTentativeDefinitionsReal
= true;
3188 else if ( strcmp(arg
, "-v") == 0 ) {
3189 // previously handled by buildSearchPaths()
3191 else if ( strcmp(arg
, "-Z") == 0 ) {
3192 // previously handled by buildSearchPaths()
3194 else if ( strcmp(arg
, "-syslibroot") == 0 ) {
3195 snapshotArgCount
= 0;
3197 // previously handled by buildSearchPaths()
3199 else if ( strcmp(arg
, "-bitcode_bundle") == 0 ) {
3200 snapshotArgCount
= 0;
3201 // previously handled by buildSearchPaths()
3203 else if ( strcmp(arg
, "-no_uuid") == 0 ) {
3204 fUUIDMode
= kUUIDNone
;
3205 cannotBeUsedWithBitcode(arg
);
3207 else if ( strcmp(arg
, "-random_uuid") == 0 ) {
3208 fUUIDMode
= kUUIDRandom
;
3209 cannotBeUsedWithBitcode(arg
);
3211 else if ( strcmp(arg
, "-dtrace") == 0 ) {
3212 snapshotFileArgIndex
= 1;
3213 const char* name
= argv
[++i
];
3215 throw "-dtrace missing argument";
3216 fDtraceScriptName
= name
;
3217 cannotBeUsedWithBitcode(arg
);
3219 else if ( strcmp(arg
, "-root_safe") == 0 ) {
3222 else if ( strcmp(arg
, "-setuid_safe") == 0 ) {
3225 else if ( strcmp(arg
, "-alias") == 0 ) {
3226 Options::AliasPair pair
;
3227 pair
.realName
= argv
[++i
];
3228 if ( pair
.realName
== NULL
)
3229 throw "missing argument to -alias";
3230 pair
.alias
= argv
[++i
];
3231 if ( pair
.alias
== NULL
)
3232 throw "missing argument to -alias";
3233 fAliases
.push_back(pair
);
3234 cannotBeUsedWithBitcode(arg
);
3236 else if ( strcmp(arg
, "-alias_list") == 0 ) {
3237 snapshotFileArgIndex
= 1;
3238 parseAliasFile(argv
[++i
]);
3239 cannotBeUsedWithBitcode(arg
);
3241 else if ( strcmp(arg
, "-save-temps") == 0 ) {
3242 fSaveTempFiles
= true;
3244 else if ( strcmp(arg
, "-bitcode_hide_symbols") == 0 ) {
3245 fHideSymbols
= true;
3247 else if ( strcmp(arg
, "-bitcode_verify") == 0 ) {
3248 fVerifyBitcode
= true;
3250 else if ( strcmp(arg
, "-bitcode_symbol_map") == 0) {
3251 fReverseMapPath
= argv
[++i
];
3252 if ( fReverseMapPath
== NULL
)
3253 throw "missing argument to -bitcode_symbol_map";
3254 struct stat statbuf
;
3255 ::stat(fReverseMapPath
, &statbuf
);
3256 if (S_ISDIR(statbuf
.st_mode
)) {
3257 char tempPath
[PATH_MAX
];
3258 sprintf(tempPath
, "%s/XXXXXX", fReverseMapPath
);
3259 int tempFile
= ::mkstemp(tempPath
);
3261 throwf("could not write file to symbol map directory: %s", fReverseMapPath
);
3263 fReverseMapTempPath
= std::string(tempPath
);
3264 fReverseMapUUIDRename
= true;
3266 fReverseMapTempPath
= std::string(fReverseMapPath
);
3268 else if ( strcmp(argv
[i
], "-flto-codegen-only") == 0) {
3269 fLTOCodegenOnly
= true;
3271 else if ( strcmp(argv
[i
], "-ignore_auto_link") == 0) {
3272 fIgnoreAutoLink
= true;
3274 else if ( strcmp(argv
[i
], "-allow_dead_duplicates") == 0) {
3275 fAllowDeadDups
= true;
3277 else if ( strcmp(argv
[i
], "-bitcode_process_mode") == 0 ) {
3278 const char* bitcode_type
= argv
[++i
];
3279 if ( bitcode_type
== NULL
)
3280 throw "missing argument to -bitcode_process_mode";
3281 else if ( strcmp(bitcode_type
, "strip") == 0 )
3282 fBitcodeKind
= kBitcodeStrip
;
3283 else if ( strcmp(bitcode_type
, "marker") == 0 )
3284 fBitcodeKind
= kBitcodeMarker
;
3285 else if ( strcmp(bitcode_type
, "data") == 0 )
3286 fBitcodeKind
= kBitcodeAsData
;
3287 else if ( strcmp(bitcode_type
, "bitcode") == 0 )
3288 fBitcodeKind
= kBitcodeProcess
;
3290 throw "unknown argument to -bitcode_process_mode {strip,marker,data,bitcode}";
3292 else if ( strcmp(arg
, "-rpath") == 0 ) {
3293 const char* path
= argv
[++i
];
3295 throw "missing argument to -rpath";
3296 fRPaths
.push_back(path
);
3298 else if ( strcmp(arg
, "-read_only_stubs") == 0 ) {
3299 fReadOnlyx86Stubs
= true;
3301 else if ( strcmp(arg
, "-slow_stubs") == 0 ) {
3304 else if ( strcmp(arg
, "-map") == 0 ) {
3305 fMapPath
= argv
[++i
];
3306 if ( fMapPath
== NULL
)
3307 throw "missing argument to -map";
3309 else if ( strcmp(arg
, "-pie") == 0 ) {
3310 fPositionIndependentExecutable
= true;
3311 fPIEOnCommandLine
= true;
3313 else if ( strcmp(arg
, "-no_pie") == 0 ) {
3314 fDisablePositionIndependentExecutable
= true;
3315 cannotBeUsedWithBitcode(arg
);
3317 else if ( strncmp(arg
, "-reexport-l", 11) == 0 ) {
3318 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3319 snapshotArgCount
= 0;
3320 FileInfo info
= findLibrary(&arg
[11], true);
3321 info
.options
.fReExport
= true;
3322 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3324 cannotBeUsedWithBitcode(arg
);
3326 else if ( strcmp(arg
, "-reexport_library") == 0 ) {
3327 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3328 snapshotArgCount
= 0;
3329 FileInfo info
= findFile(argv
[++i
]);
3330 info
.options
.fReExport
= true;
3331 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3333 cannotBeUsedWithBitcode(arg
);
3335 else if ( strcmp(arg
, "-reexport_framework") == 0 ) {
3336 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3337 snapshotArgCount
= 0;
3338 FileInfo info
= findFramework(argv
[++i
]);
3339 info
.options
.fReExport
= true;
3340 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3342 cannotBeUsedWithBitcode(arg
);
3344 else if ( strncmp(arg
, "-upward-l", 9) == 0 ) {
3345 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3346 snapshotArgCount
= 0;
3347 FileInfo info
= findLibrary(&arg
[9], true);
3348 info
.options
.fUpward
= true;
3349 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3351 cannotBeUsedWithBitcode(arg
);
3353 else if ( strcmp(arg
, "-upward_library") == 0 ) {
3354 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3355 snapshotArgCount
= 0;
3356 FileInfo info
= findFile(argv
[++i
]);
3357 info
.options
.fUpward
= true;
3358 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3360 cannotBeUsedWithBitcode(arg
);
3362 else if ( strcmp(arg
, "-upward_framework") == 0 ) {
3363 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3364 snapshotArgCount
= 0;
3365 FileInfo info
= findFramework(argv
[++i
]);
3366 info
.options
.fUpward
= true;
3367 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3369 cannotBeUsedWithBitcode(arg
);
3371 else if ( strcmp(arg
, "-dead_strip_dylibs") == 0 ) {
3372 fDeadStripDylibs
= true;
3373 cannotBeUsedWithBitcode(arg
);
3375 else if ( strcmp(arg
, "-no_implicit_dylibs") == 0 ) {
3376 fImplicitlyLinkPublicDylibs
= false;
3378 else if ( strcmp(arg
, "-new_linker") == 0 ) {
3381 else if ( strcmp(arg
, "-no_encryption") == 0 ) {
3382 fEncryptableForceOff
= true;
3383 cannotBeUsedWithBitcode(arg
);
3385 else if ( strcmp(arg
, "-encryptable") == 0 ) {
3386 fEncryptableForceOn
= true;
3387 cannotBeUsedWithBitcode(arg
);
3389 else if ( strcmp(arg
, "-no_compact_unwind") == 0 ) {
3390 fAddCompactUnwindEncoding
= false;
3391 cannotBeUsedWithBitcode(arg
);
3393 else if ( strcmp(arg
, "-mllvm") == 0 ) {
3394 const char* opts
= argv
[++i
];
3396 throw "missing argument to -mllvm";
3397 fLLVMOptions
.push_back(opts
);
3398 cannotBeUsedWithBitcode(arg
);
3400 else if ( strcmp(arg
, "-mcpu") == 0 ) {
3401 const char* cpu
= argv
[++i
];
3403 throw "missing argument to -mcpu";
3405 cannotBeUsedWithBitcode(arg
);
3407 else if ( strcmp(arg
, "-no_order_inits") == 0 ) {
3408 fAutoOrderInitializers
= false;
3409 cannotBeUsedWithBitcode(arg
);
3411 else if ( strcmp(arg
, "-no_order_data") == 0 ) {
3413 cannotBeUsedWithBitcode(arg
);
3415 else if ( strcmp(arg
, "-seg_page_size") == 0 ) {
3417 seg
.name
= argv
[++i
];
3418 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
3419 throw "-seg_page_size missing segName Adddress";
3420 seg
.size
= parseAddress(argv
[++i
]);
3421 uint64_t temp
= seg
.size
& (-4096); // page align
3422 if ( (seg
.size
!= temp
) )
3423 warning("-seg_page_size %s not 4K aligned, rounding down", seg
.name
);
3424 fCustomSegmentSizes
.push_back(seg
);
3425 cannotBeUsedWithBitcode(arg
);
3427 else if ( strcmp(arg
, "-mark_dead_strippable_dylib") == 0 ) {
3428 fMarkDeadStrippableDylib
= true;
3429 cannotBeUsedWithBitcode(arg
);
3431 else if ( strcmp(arg
, "-exported_symbols_order") == 0 ) {
3432 snapshotFileArgIndex
= 1;
3433 loadSymbolOrderFile(argv
[++i
], fExportSymbolsOrder
);
3434 cannotBeUsedWithBitcode(arg
);
3436 else if ( strcmp(arg
, "-no_compact_linkedit") == 0 ) {
3437 warnObsolete("-no_compact_linkedit");
3439 else if ( strcmp(arg
, "-no_eh_labels") == 0 ) {
3441 cannotBeUsedWithBitcode(arg
);
3443 else if ( strcmp(arg
, "-warn_compact_unwind") == 0 ) {
3444 fWarnCompactUnwind
= true;
3446 else if ( strcmp(arg
, "-allow_sub_type_mismatches") == 0 ) {
3447 fAllowCpuSubtypeMismatches
= true;
3448 cannotBeUsedWithBitcode(arg
);
3450 else if ( strcmp(arg
, "-no_zero_fill_sections") == 0 ) {
3451 fOptimizeZeroFill
= false;
3452 cannotBeUsedWithBitcode(arg
);
3454 else if ( strcmp(arg
, "-merge_zero_fill_sections") == 0 ) {
3455 fMergeZeroFill
= true;
3456 cannotBeUsedWithBitcode(arg
);
3458 else if ( strcmp(arg
, "-objc_abi_version") == 0 ) {
3459 const char* version
= argv
[++i
];
3460 if ( version
== NULL
)
3461 throw "-objc_abi_version missing version number";
3462 if ( strcmp(version
, "2") == 0 ) {
3463 fObjCABIVersion1Override
= false;
3464 fObjCABIVersion2Override
= true;
3466 else if ( strcmp(version
, "1") == 0 ) {
3467 fObjCABIVersion1Override
= true;
3468 fObjCABIVersion2Override
= false;
3471 warning("ignoring unrecognized argument (%s) to -objc_abi_version", version
);
3473 else if ( strcmp(arg
, "-warn_weak_exports") == 0 ) {
3474 fWarnWeakExports
= true;
3476 else if ( strcmp(arg
, "-objc_gc_compaction") == 0 ) {
3477 fObjcGcCompaction
= true;
3478 cannotBeUsedWithBitcode(arg
);
3480 else if ( strcmp(arg
, "-objc_gc") == 0 ) {
3482 if ( fObjCGcOnly
) {
3483 warning("-objc_gc overriding -objc_gc_only");
3484 fObjCGcOnly
= false;
3486 cannotBeUsedWithBitcode(arg
);
3488 else if ( strcmp(arg
, "-objc_gc_only") == 0 ) {
3491 warning("-objc_gc_only overriding -objc_gc");
3494 cannotBeUsedWithBitcode(arg
);
3496 else if ( strcmp(arg
, "-demangle") == 0 ) {
3499 else if ( strcmp(arg
, "-version_load_command") == 0 ) {
3500 fVersionLoadCommandForcedOn
= true;
3501 fVersionLoadCommandForcedOff
= false;
3503 else if ( strcmp(arg
, "-no_version_load_command") == 0 ) {
3504 fVersionLoadCommandForcedOff
= true;
3505 fVersionLoadCommandForcedOn
= false;
3506 cannotBeUsedWithBitcode(arg
);
3508 else if ( strcmp(arg
, "-function_starts") == 0 ) {
3509 fFunctionStartsForcedOn
= true;
3510 fFunctionStartsForcedOff
= false;
3512 else if ( strcmp(arg
, "-no_function_starts") == 0 ) {
3513 fFunctionStartsForcedOff
= true;
3514 fFunctionStartsForcedOn
= false;
3515 cannotBeUsedWithBitcode(arg
);
3517 else if ( strcmp(arg
, "-no_data_in_code_info") == 0 ) {
3518 fDataInCodeInfoLoadCommandForcedOff
= true;
3519 fDataInCodeInfoLoadCommandForcedOn
= false;
3520 cannotBeUsedWithBitcode(arg
);
3522 else if ( strcmp(arg
, "-data_in_code_info") == 0 ) {
3523 fDataInCodeInfoLoadCommandForcedOn
= true;
3524 fDataInCodeInfoLoadCommandForcedOff
= false;
3526 else if ( strcmp(arg
, "-object_path_lto") == 0 ) {
3527 fTempLtoObjectPath
= argv
[++i
];
3528 if ( fTempLtoObjectPath
== NULL
)
3529 throw "missing argument to -object_path_lto";
3531 else if ( strcmp(arg
, "-no_objc_category_merging") == 0 ) {
3532 fObjcCategoryMerging
= false;
3534 else if ( strcmp(arg
, "-force_symbols_weak_list") == 0 ) {
3535 snapshotFileArgIndex
= 1;
3536 loadExportFile(argv
[++i
], "-force_symbols_weak_list", fForceWeakSymbols
);
3537 cannotBeUsedWithBitcode(arg
);
3539 else if ( strcmp(arg
, "-force_symbols_not_weak_list") == 0 ) {
3540 snapshotFileArgIndex
= 1;
3541 loadExportFile(argv
[++i
], "-force_symbols_not_weak_list", fForceNotWeakSymbols
);
3542 cannotBeUsedWithBitcode(arg
);
3544 else if ( strcmp(arg
, "-force_symbol_weak") == 0 ) {
3545 const char* symbol
= argv
[++i
];
3546 if ( symbol
== NULL
)
3547 throw "-force_symbol_weak missing <symbol>";
3548 fForceWeakSymbols
.insert(symbol
);
3549 cannotBeUsedWithBitcode(arg
);
3551 else if ( strcmp(arg
, "-force_symbol_not_weak") == 0 ) {
3552 const char* symbol
= argv
[++i
];
3553 if ( symbol
== NULL
)
3554 throw "-force_symbol_not_weak missing <symbol>";
3555 fForceNotWeakSymbols
.insert(symbol
);
3556 cannotBeUsedWithBitcode(arg
);
3558 else if ( strcmp(arg
, "-reexported_symbols_list") == 0 ) {
3559 snapshotFileArgIndex
= 1;
3560 if ( fExportMode
== kExportSome
)
3561 throw "can't use -exported_symbols_list and -reexported_symbols_list";
3562 loadExportFile(argv
[++i
], "-reexported_symbols_list", fReExportSymbols
);
3564 else if ( strcmp(arg
, "-dyld_env") == 0 ) {
3565 const char* envarg
= argv
[++i
];
3566 if ( envarg
== NULL
)
3567 throw "-dyld_env missing ENV=VALUE";
3568 if ( strchr(envarg
, '=') == NULL
)
3569 throw "-dyld_env missing ENV=VALUE";
3570 fDyldEnvironExtras
.push_back(envarg
);
3571 cannotBeUsedWithBitcode(arg
);
3573 else if ( strcmp(arg
, "-page_align_data_atoms") == 0 ) {
3574 fPageAlignDataAtoms
= true;
3575 cannotBeUsedWithBitcode(arg
);
3577 else if (strcmp(arg
, "-debug_snapshot") == 0) {
3578 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
3579 fSnapshotRequested
= true;
3580 cannotBeUsedWithBitcode(arg
);
3582 else if (strcmp(arg
, "-snapshot_dir") == 0) {
3583 const char* path
= argv
[++i
];
3585 throw "-snapshot_dir missing path";
3586 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
3587 fLinkSnapshot
.setSnapshotPath(path
);
3588 fSnapshotRequested
= true;
3589 cannotBeUsedWithBitcode(arg
);
3591 else if ( strcmp(arg
, "-new_main") == 0 ) {
3592 fEntryPointLoadCommandForceOn
= true;
3593 cannotBeUsedWithBitcode(arg
);
3595 else if ( strcmp(arg
, "-no_new_main") == 0 ) {
3596 fEntryPointLoadCommandForceOff
= true;
3597 cannotBeUsedWithBitcode(arg
);
3599 else if ( strcmp(arg
, "-source_version") == 0 ) {
3600 const char* vers
= argv
[++i
];
3602 throw "-source_version missing <version>";
3603 fSourceVersion
= parseVersionNumber64(vers
);
3605 else if ( strcmp(arg
, "-add_source_version") == 0 ) {
3606 fSourceVersionLoadCommandForceOn
= true;
3608 else if ( strcmp(arg
, "-no_source_version") == 0 ) {
3609 fSourceVersionLoadCommandForceOff
= true;
3610 cannotBeUsedWithBitcode(arg
);
3612 else if ( strcmp(arg
, "-sdk_version") == 0 ) {
3613 const char* vers
= argv
[++i
];
3615 throw "-sdk_version missing <version>";
3616 fSDKVersion
= parseVersionNumber32(vers
);
3618 else if ( strcmp(arg
, "-dependent_dr_info") == 0 ) {
3621 else if ( strcmp(arg
, "-no_dependent_dr_info") == 0 ) {
3624 else if ( strcmp(arg
, "-kexts_use_stubs") == 0 ) {
3625 fKextsUseStubs
= true;
3626 cannotBeUsedWithBitcode(arg
);
3628 else if ( strcmp(argv
[i
], "-dependency_info") == 0 ) {
3629 snapshotArgCount
= 0;
3631 // previously handled by buildSearchPaths()
3633 else if ( strcmp(arg
, "-export_dynamic") == 0 ) {
3634 fExportDynamic
= true;
3636 else if ( strcmp(arg
, "-force_symbols_coalesce_list") == 0 ) {
3637 snapshotFileArgIndex
= 1;
3638 loadExportFile(argv
[++i
], "-force_symbols_coalesce_list", fForceCoalesceSymbols
);
3640 else if ( strcmp(arg
, "-add_linker_option") == 0 ) {
3641 // ex: -add_linker_option '-framework Foundation'
3642 const char* optString
= argv
[++i
];
3643 if ( optString
== NULL
)
3644 throw "-add_linker_option missing <option>";
3645 // break up into list of tokens at whitespace
3646 std::vector
<const char*> opts
;
3647 char* buffer
= strdup(optString
);
3648 char* start
= buffer
;
3649 for (char* s
= buffer
; ; ++s
) {
3650 if ( isspace(*s
) ) {
3652 opts
.push_back(start
);
3655 else if ( *s
== '\0' ) {
3656 opts
.push_back(start
);
3660 fLinkerOptions
.push_back(opts
);
3661 cannotBeUsedWithBitcode(arg
);
3663 else if ( strcmp(arg
, "-allow_simulator_linking_to_macosx_dylibs") == 0 ) {
3664 fAllowSimulatorToLinkWithMacOSX
= true;
3665 cannotBeUsedWithBitcode(arg
);
3667 else if ( strcmp(arg
, "-keep_dwarf_unwind") == 0 ) {
3668 fKeepDwarfUnwindForcedOn
= true;
3669 fKeepDwarfUnwindForcedOff
= false;
3670 cannotBeUsedWithBitcode(arg
);
3672 else if ( strcmp(arg
, "-no_keep_dwarf_unwind") == 0 ) {
3673 fKeepDwarfUnwindForcedOn
= false;
3674 fKeepDwarfUnwindForcedOff
= true;
3675 cannotBeUsedWithBitcode(arg
);
3677 else if ( strcmp(arg
, "-verbose_optimization_hints") == 0 ) {
3678 fVerboseOptimizationHints
= true;
3680 else if ( strcmp(arg
, "-ignore_optimization_hints") == 0 ) {
3681 fIgnoreOptimizationHints
= true;
3682 cannotBeUsedWithBitcode(arg
);
3684 else if ( strcmp(arg
, "-no_dtrace_dof") == 0 ) {
3685 fGenerateDtraceDOF
= false;
3687 else if ( strcmp(arg
, "-rename_section") == 0 ) {
3688 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) || (argv
[i
+4]==NULL
) )
3689 throw "-rename_section missing <segment> <section> <segment> <section>";
3690 addSectionRename(argv
[i
+1], argv
[i
+2], argv
[i
+3], argv
[i
+4]);
3692 cannotBeUsedWithBitcode(arg
);
3694 else if ( strcmp(arg
, "-rename_segment") == 0 ) {
3695 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3696 throw "-rename_segment missing <existing-segment> <new-segment>";
3697 addSegmentRename(argv
[i
+1], argv
[i
+2]);
3699 cannotBeUsedWithBitcode(arg
);
3701 else if ( strcmp(arg
, "-move_to_ro_segment") == 0 ) {
3702 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3703 throw "-move_to_ro_segment missing <segment> <symbol-list-file>";
3704 addSymbolMove(argv
[i
+1], argv
[i
+2], fSymbolsMovesCode
, "-move_to_ro_segment");
3706 cannotBeUsedWithBitcode(arg
);
3708 else if ( strcmp(arg
, "-move_to_rw_segment") == 0 ) {
3709 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3710 throw "-move_to_rw_segment missing <segment> <symbol-list-file>";
3711 addSymbolMove(argv
[i
+1], argv
[i
+2], fSymbolsMovesData
, "-move_to_rw_segment");
3713 cannotBeUsedWithBitcode(arg
);
3715 else if ( strcmp(arg
, "-trace_symbol_layout") == 0 ) {
3716 fTraceSymbolLayout
= true;
3718 else if ( strcmp(arg
, "-no_branch_islands") == 0 ) {
3719 fAllowBranchIslands
= false;
3720 cannotBeUsedWithBitcode(arg
);
3722 else if ( strcmp(arg
, "-segment_order") == 0 ) {
3723 // ex: -segment_order __TEXT:__DATA:__JUNK
3724 const char* optString
= argv
[++i
];
3725 if ( optString
== NULL
)
3726 throw "-segment_order missing colon separated <segment-list>";
3727 if ( !fSegmentOrder
.empty() )
3728 throw "-segment_order used more than once";
3729 // break up into list of tokens at colon
3730 char* buffer
= strdup(optString
);
3731 char* start
= buffer
;
3732 for (char* s
= buffer
; ; ++s
) {
3735 fSegmentOrder
.push_back(start
);
3738 else if ( *s
== '\0' ) {
3739 fSegmentOrder
.push_back(start
);
3743 cannotBeUsedWithBitcode(arg
);
3745 else if ( strcmp(arg
, "-section_order") == 0 ) {
3746 // ex: -section_order __DATA __data:__const:__nl_pointers
3747 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3748 throw "-section_order missing <segment> <section-list>";
3749 const char* segName
= argv
[++i
];
3750 const char* optString
= argv
[++i
];
3751 if ( sectionOrder(segName
) != NULL
)
3752 throwf("-section_order %s ... used more than once", segName
);
3753 SectionOrderList dummy
;
3754 fSectionOrder
.push_back(dummy
);
3755 SectionOrderList
& entry
= fSectionOrder
.back();
3756 entry
.segmentName
= segName
;
3757 // break up into list of tokens at colon
3758 char* buffer
= strdup(optString
);
3759 char* start
= buffer
;
3760 for (char* s
= buffer
; ; ++s
) {
3763 entry
.sectionOrder
.push_back(start
);
3766 else if ( *s
== '\0' ) {
3767 entry
.sectionOrder
.push_back(start
);
3771 cannotBeUsedWithBitcode(arg
);
3773 else if ( strcmp(arg
, "-application_extension") == 0 ) {
3774 fMarkAppExtensionSafe
= true;
3775 fCheckAppExtensionSafe
= true;
3777 else if ( strcmp(arg
, "-no_application_extension") == 0 ) {
3778 fMarkAppExtensionSafe
= false;
3779 fCheckAppExtensionSafe
= false;
3781 else if ( strcmp(arg
, "-add_ast_path") == 0 ) {
3782 const char* path
= argv
[++i
];
3784 throw "-add_ast_path missing <option>";
3785 fASTFilePaths
.push_back(path
);
3787 else if ( strcmp(arg
, "-force_load_swift_libs") == 0 ) {
3788 fForceLoadSwiftLibs
= true;
3790 else if ( strcmp(arg
, "-not_for_dyld_shared_cache") == 0 ) {
3791 fSharedRegionEligibleForceOff
= true;
3792 cannotBeUsedWithBitcode(arg
);
3794 else if ( strcmp(arg
, "-dirty_data_list") == 0 ) {
3795 if ( argv
[i
+1] == NULL
)
3796 throw "-dirty_data_list missing <symbol-list-file>";
3797 addSymbolMove("__DATA_DIRTY", argv
[i
+1], fSymbolsMovesData
, "-dirty_data_list");
3799 cannotBeUsedWithBitcode(arg
);
3801 else if ( strcmp(arg
, "-data_const") == 0 ) {
3802 fUseDataConstSegmentForceOn
= true;
3803 cannotBeUsedWithBitcode(arg
);
3805 else if ( strcmp(arg
, "-no_data_const") == 0 ) {
3806 fUseDataConstSegmentForceOff
= true;
3807 cannotBeUsedWithBitcode(arg
);
3809 else if ( strcmp(arg
, "-text_exec") == 0 ) {
3810 fUseTextExecSegment
= true;
3811 cannotBeUsedWithBitcode(arg
);
3813 else if ( strcmp(arg
, "-add_split_seg_info") == 0) {
3814 fSharedRegionEligible
= true;
3815 cannotBeUsedWithBitcode(arg
);
3817 else if ( strcmp(arg
, "-no_deduplicate") == 0 ) {
3820 else if ( strcmp(arg
, "-verbose_deduplicate") == 0 ) {
3821 fVerboseDeDupe
= true;
3823 else if ( strcmp(arg
, "-max_default_common_align") == 0 ) {
3824 const char* alignStr
= argv
[++i
];
3825 if ( alignStr
== NULL
)
3826 throw "-max_default_common_align missing <align-value>";
3827 // argument is a hexadecimal number
3829 unsigned long value
= strtoul(alignStr
, &endptr
, 16);
3830 if ( *endptr
!= '\0')
3831 throw "argument for -max_default_common_align is not a hexadecimal number";
3832 if ( value
> 0x8000 )
3833 throw "argument for -max_default_common_align must be less than or equal to 0x8000";
3835 warning("zero is not a valid -max_default_common_align");
3838 // alignment is power of 2
3839 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
3840 if ( (unsigned long)(1 << alignment
) != value
) {
3841 warning("alignment for -max_default_common_align is not a power of two, using 0x%X", 1 << alignment
);
3843 fMaxDefaultCommonAlign
= alignment
;
3845 else if ( strcmp(argv
[i
], "-no_weak_imports") == 0 ) {
3846 fAllowWeakImports
= false;
3848 // put this last so that it does not interfer with other options starting with 'i'
3849 else if ( strncmp(arg
, "-i", 2) == 0 ) {
3850 const char* colon
= strchr(arg
, ':');
3851 if ( colon
== NULL
)
3852 throwf("unknown option: %s", arg
);
3853 Options::AliasPair pair
;
3854 char* temp
= new char[colon
-arg
];
3855 strlcpy(temp
, &arg
[2], colon
-arg
-1);
3856 pair
.realName
= &colon
[1];
3858 fAliases
.push_back(pair
);
3861 throwf("unknown option: %s", arg
);
3864 if (snapshotArgCount
== -1)
3865 snapshotArgCount
= i
-snapshotArgIndex
+1;
3866 if (snapshotArgCount
> 0)
3867 fLinkSnapshot
.addSnapshotLinkArg(snapshotArgIndex
, snapshotArgCount
, snapshotFileArgIndex
);
3870 FileInfo info
= findFile(arg
);
3871 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3872 if ( strcmp(&info
.path
[strlen(info
.path
)-2], ".a") == 0 )
3875 fInputFiles
.push_back(info
);
3879 // if a -lazy option was used, implicitly link in lazydylib1.o
3880 if ( fUsingLazyDylibLinking
) {
3881 FileInfo info
= findLibrary("lazydylib1.o");
3882 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)argc
);
3886 if (fSnapshotRequested
)
3887 fLinkSnapshot
.createSnapshot();
3893 // -syslibroot <path> is used for SDK support.
3894 // The rule is that all search paths (both explicit and default) are
3895 // checked to see if they exist in the SDK. If so, that path is
3896 // replaced with the sdk prefixed path. If not, that search path
3897 // is used as is. If multiple -syslibroot options are specified
3898 // their directory structures are logically overlayed and files
3899 // from sdks specified earlier on the command line used before later ones.
3901 void Options::buildSearchPaths(int argc
, const char* argv
[])
3903 bool addStandardLibraryDirectories
= true;
3904 std::vector
<const char*> libraryPaths
;
3905 std::vector
<const char*> frameworkPaths
;
3906 libraryPaths
.reserve(10);
3907 frameworkPaths
.reserve(10);
3908 // scan through argv looking for -L, -F, -Z, and -syslibroot options
3909 for(int i
=0; i
< argc
; ++i
) {
3910 if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'L') ) {
3911 const char* libSearchDir
= &argv
[i
][2];
3912 // Allow either "-L{path}" or "-L {path}".
3913 if (argv
[i
][2] == '\0') {
3914 // -L {path}. Make sure there is an argument following this.
3915 const char* path
= argv
[++i
];
3917 throw "-L missing argument";
3918 libSearchDir
= path
;
3920 if ( libSearchDir
[0] == '\0' )
3921 throw "-L must be immediately followed by a directory path (no space)";
3922 libraryPaths
.push_back(libSearchDir
);
3924 else if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'F') ) {
3925 const char* frameworkSearchDir
= &argv
[i
][2];
3926 // Allow either "-F{path}" or "-F {path}".
3927 if (argv
[i
][2] == '\0') {
3928 // -F {path}. Make sure there is an argument following this.
3929 const char* path
= argv
[++i
];
3931 throw "-F missing argument";
3932 frameworkSearchDir
= path
;
3934 if ( frameworkSearchDir
[0] == '\0' )
3935 throw "-F must be immediately followed by a directory path (no space)";
3936 frameworkPaths
.push_back(frameworkSearchDir
);
3938 else if ( strcmp(argv
[i
], "-Z") == 0 )
3939 addStandardLibraryDirectories
= false;
3940 else if ( strcmp(argv
[i
], "-v") == 0 ) {
3942 extern const char ldVersionString
[];
3943 fprintf(stderr
, "%s", ldVersionString
);
3944 fprintf(stderr
, "configured to support archs: %s\n", ALL_SUPPORTED_ARCHS
);
3945 // if only -v specified, exit cleanly
3947 const char* ltoVers
= lto::version();
3948 if ( ltoVers
!= NULL
)
3949 fprintf(stderr
, "LTO support using: %s\n", ltoVers
);
3950 fprintf(stderr
, "TAPI support using: %s\n", tapi::Version::getFullVersionAsString().c_str());
3954 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
3955 const char* path
= argv
[++i
];
3957 throw "-syslibroot missing argument";
3958 fSDKPaths
.push_back(path
);
3960 else if ( strcmp(argv
[i
], "-search_paths_first") == 0 ) {
3961 fLibrarySearchMode
= kSearchDylibAndArchiveInEachDir
;
3963 else if ( strcmp(argv
[i
], "-search_dylibs_first") == 0 ) {
3964 fLibrarySearchMode
= kSearchAllDirsForDylibsThenAllDirsForArchives
;
3966 else if ( strcmp(argv
[i
], "-w") == 0 ) {
3967 sEmitWarnings
= false;
3969 else if ( strcmp(argv
[i
], "-fatal_warnings") == 0 ) {
3970 sFatalWarnings
= true;
3972 else if ( strcmp(argv
[i
], "-dependency_info") == 0 ) {
3973 const char* path
= argv
[++i
];
3975 throw "-dependency_info missing <path>";
3976 fDependencyInfoPath
= path
;
3978 else if ( strcmp(argv
[i
], "-bitcode_bundle") == 0 ) {
3979 fBundleBitcode
= true;
3982 int standardLibraryPathsStartIndex
= libraryPaths
.size();
3983 int standardFrameworkPathsStartIndex
= frameworkPaths
.size();
3984 if ( addStandardLibraryDirectories
) {
3985 libraryPaths
.push_back("/usr/lib");
3986 libraryPaths
.push_back("/usr/local/lib");
3988 frameworkPaths
.push_back("/Library/Frameworks/");
3989 frameworkPaths
.push_back("/System/Library/Frameworks/");
3990 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
3993 // <rdar://problem/5829579> Support for configure based hacks
3994 // if last -syslibroot is /, then ignore all syslibroots
3995 if ( fSDKPaths
.size() > 0 ) {
3996 if ( strcmp(fSDKPaths
.back(), "/") == 0 ) {
4001 // now merge sdk and library paths to make real search paths
4002 fLibrarySearchPaths
.reserve(libraryPaths
.size()*(fSDKPaths
.size()+1));
4004 for (std::vector
<const char*>::iterator it
= libraryPaths
.begin(); it
!= libraryPaths
.end(); ++it
, ++libIndex
) {
4005 const char* libDir
= *it
;
4006 bool sdkOverride
= false;
4007 if ( libDir
[0] == '/' ) {
4008 char betterLibDir
[PATH_MAX
];
4009 if ( strstr(libDir
, "/..") != NULL
) {
4010 if ( realpath(libDir
, betterLibDir
) != NULL
)
4011 libDir
= strdup(betterLibDir
);
4013 const int libDirLen
= strlen(libDir
);
4014 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
4015 const char* sdkDir
= *sdkit
;
4016 const int sdkDirLen
= strlen(sdkDir
);
4017 char newPath
[libDirLen
+ sdkDirLen
+4];
4018 strcpy(newPath
, sdkDir
);
4019 if ( newPath
[sdkDirLen
-1] == '/' )
4020 newPath
[sdkDirLen
-1] = '\0';
4021 strcat(newPath
, libDir
);
4022 struct stat statBuffer
;
4023 if ( stat(newPath
, &statBuffer
) == 0 ) {
4024 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 ) {
4025 warning("-syslibroot and -L combined path '%s' is not a directory", newPath
);
4028 fLibrarySearchPaths
.push_back(strdup(newPath
));
4034 if ( !sdkOverride
) {
4035 if ( (libIndex
>= standardLibraryPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
4036 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
4037 // if one SDK is specified and a standard library path is not in the SDK, don't use it
4040 struct stat statBuffer
;
4041 if ( stat(libDir
, &statBuffer
) == 0 ) {
4042 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 )
4043 warning("-L path '%s' is not a directory", libDir
);
4045 fLibrarySearchPaths
.push_back(libDir
);
4047 else if ( !addStandardLibraryDirectories
|| (strcmp(libDir
, "/usr/local/lib") != 0) ) {
4048 warning("directory not found for option '-L%s'", libDir
);
4055 // now merge sdk and framework paths to make real search paths
4056 fFrameworkSearchPaths
.reserve(frameworkPaths
.size()*(fSDKPaths
.size()+1));
4058 for (std::vector
<const char*>::iterator it
= frameworkPaths
.begin(); it
!= frameworkPaths
.end(); ++it
, ++frameIndex
) {
4059 const char* frameworkDir
= *it
;
4060 bool sdkOverride
= false;
4061 if ( frameworkDir
[0] == '/' ) {
4062 char betterFrameworkDir
[PATH_MAX
];
4063 if ( strstr(frameworkDir
, "/..") != NULL
) {
4064 if ( realpath(frameworkDir
, betterFrameworkDir
) != NULL
)
4065 frameworkDir
= strdup(betterFrameworkDir
);
4067 const int frameworkDirLen
= strlen(frameworkDir
);
4068 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
4069 const char* sdkDir
= *sdkit
;
4070 const int sdkDirLen
= strlen(sdkDir
);
4071 char newPath
[frameworkDirLen
+ sdkDirLen
+4];
4072 strcpy(newPath
, sdkDir
);
4073 if ( newPath
[sdkDirLen
-1] == '/' )
4074 newPath
[sdkDirLen
-1] = '\0';
4075 strcat(newPath
, frameworkDir
);
4076 struct stat statBuffer
;
4077 if ( stat(newPath
, &statBuffer
) == 0 ) {
4078 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 ) {
4079 warning("-syslibroot and -F combined path '%s' is not a directory", newPath
);
4082 fFrameworkSearchPaths
.push_back(strdup(newPath
));
4088 if ( !sdkOverride
) {
4089 if ( (frameIndex
>= standardFrameworkPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
4090 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
4091 // if one SDK is specified and a standard library path is not in the SDK, don't use it
4094 struct stat statBuffer
;
4095 if ( stat(frameworkDir
, &statBuffer
) == 0 ) {
4096 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 )
4097 warning("-F path '%s' is not a directory", frameworkDir
);
4099 fFrameworkSearchPaths
.push_back(frameworkDir
);
4101 else if ( !addStandardLibraryDirectories
|| (strcmp(frameworkDir
, "/Library/Frameworks/") != 0) ) {
4102 warning("directory not found for option '-F%s'", frameworkDir
);
4109 fprintf(stderr
,"Library search paths:\n");
4110 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
4111 it
!= fLibrarySearchPaths
.end();
4113 fprintf(stderr
,"\t%s\n", *it
);
4114 fprintf(stderr
,"Framework search paths:\n");
4115 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
4116 it
!= fFrameworkSearchPaths
.end();
4118 fprintf(stderr
,"\t%s\n", *it
);
4122 // this is run before the command line is parsed
4123 void Options::parsePreCommandLineEnvironmentSettings()
4125 if ((getenv("LD_TRACE_ARCHIVES") != NULL
)
4126 || (getenv("RC_TRACE_ARCHIVES") != NULL
))
4127 fTraceArchives
= true;
4129 if ((getenv("LD_TRACE_DYLIBS") != NULL
)
4130 || (getenv("RC_TRACE_DYLIBS") != NULL
)) {
4131 fTraceDylibs
= true;
4132 fTraceIndirectDylibs
= true;
4135 if ((getenv("LD_TRACE_DEPENDENTS") != NULL
)) {
4137 fTraceEmitJSON
= true;
4140 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL
) {
4141 fTraceDylibSearching
= true;
4144 if (getenv("LD_PRINT_OPTIONS") != NULL
)
4145 fPrintOptions
= true;
4147 if (fTraceDylibs
|| fTraceArchives
|| fTraceEmitJSON
)
4148 fTraceOutputFile
= getenv("LD_TRACE_FILE");
4150 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL
)
4151 fPrintOrderFileStatistics
= true;
4153 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL
)
4156 if (getenv("LD_NO_ENCRYPT") != NULL
) {
4157 fEncryptable
= false;
4158 fMarkAppExtensionSafe
= true; // temporary
4159 fCheckAppExtensionSafe
= false;
4162 if (getenv("LD_APPLICATION_EXTENSION_SAFE") != NULL
) {
4163 fMarkAppExtensionSafe
= true;
4164 fCheckAppExtensionSafe
= false;
4167 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL
)
4168 fAllowCpuSubtypeMismatches
= true;
4170 if (getenv("LD_DYLIB_CPU_SUBTYPES_MUST_MATCH") != NULL
)
4171 fEnforceDylibSubtypesMatch
= true;
4173 sWarningsSideFilePath
= getenv("LD_WARN_FILE");
4175 const char* customDyldPath
= getenv("LD_DYLD_PATH");
4176 if ( customDyldPath
!= NULL
)
4177 fDyldInstallPath
= customDyldPath
;
4179 const char* debugArchivePath
= getenv("LD_DEBUG_SNAPSHOT");
4180 if (debugArchivePath
!= NULL
) {
4181 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
4182 if (strlen(debugArchivePath
) > 0)
4183 fLinkSnapshot
.setSnapshotPath(debugArchivePath
);
4184 fSnapshotRequested
= true;
4187 const char* pipeFdString
= getenv("LD_PIPELINE_FIFO");
4188 if (pipeFdString
!= NULL
) {
4189 fPipelineFifo
= pipeFdString
;
4194 // this is run after the command line is parsed
4195 void Options::parsePostCommandLineEnvironmentSettings()
4197 // when building a dynamic main executable, default any use of @executable_path to output path
4198 if ( fExecutablePath
== NULL
&& (fOutputKind
== kDynamicExecutable
) ) {
4199 fExecutablePath
= fOutputFile
;
4202 // allow build system to set default seg_addr_table
4203 if ( fSegAddrTablePath
== NULL
)
4204 fSegAddrTablePath
= getenv("LD_SEG_ADDR_TABLE");
4206 // allow build system to turn on prebinding
4208 fPrebind
= ( getenv("LD_PREBIND") != NULL
);
4211 // allow build system to force on dead-code-stripping
4212 if ( !fDeadStrip
) {
4213 if ( getenv("LD_DEAD_STRIP") != NULL
) {
4214 switch (fOutputKind
) {
4215 case Options::kDynamicLibrary
:
4216 case Options::kDynamicExecutable
:
4217 case Options::kDynamicBundle
:
4220 case Options::kPreload
:
4221 case Options::kObjectFile
:
4222 case Options::kDyld
:
4223 case Options::kStaticExecutable
:
4224 case Options::kKextBundle
:
4230 // allow build system to force on -warn_commons
4231 if ( getenv("LD_WARN_COMMONS") != NULL
)
4232 fWarnCommons
= true;
4234 // allow B&I to set default -source_version
4235 if ( fSourceVersion
== 0 ) {
4236 const char* vers
= getenv("RC_ProjectSourceVersion");
4238 fSourceVersion
= parseVersionNumber64(vers
);
4243 void Options::reconfigureDefaults()
4245 // sync reader options
4246 switch ( fOutputKind
) {
4247 case Options::kObjectFile
:
4248 fForFinalLinkedImage
= false;
4250 case Options::kDyld
:
4252 fForFinalLinkedImage
= true;
4255 case Options::kDynamicLibrary
:
4256 case Options::kDynamicBundle
:
4257 case Options::kKextBundle
:
4258 fForFinalLinkedImage
= true;
4261 case Options::kDynamicExecutable
:
4262 case Options::kStaticExecutable
:
4263 case Options::kPreload
:
4264 fLinkingMainExecutable
= true;
4265 fForFinalLinkedImage
= true;
4270 // set default min OS version
4271 if ( (fMacVersionMin
== ld::macVersionUnset
) && (fIOSVersionMin
== ld::iOSVersionUnset
) && (fWatchOSVersionMin
== ld::wOSVersionUnset
) ) {
4272 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
4273 const char* macVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
4274 const char* iPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
4275 const char* iOSVers
= getenv("IOS_DEPLOYMENT_TARGET");
4276 const char* wOSVers
= getenv("WATCHOS_DEPLOYMENT_TARGET");
4277 if ( macVers
!= NULL
)
4278 setMacOSXVersionMin(macVers
);
4279 else if ( iPhoneVers
!= NULL
)
4280 setIOSVersionMin(iPhoneVers
);
4281 else if ( iOSVers
!= NULL
)
4282 setIOSVersionMin(iOSVers
);
4283 else if ( wOSVers
!= NULL
)
4284 setWatchOSVersionMin(wOSVers
);
4286 // if still nothing, set default based on architecture
4287 switch ( fArchitecture
) {
4289 case CPU_TYPE_X86_64
:
4290 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
4291 #ifdef DEFAULT_MACOSX_MIN_VERSION
4292 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION
);
4293 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
4295 warning("-macosx_version_min not specified, assuming 10.6");
4296 setMacOSXVersionMin("10.6");
4301 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
4302 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
4303 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION
);
4304 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION
);
4306 if ( fSubArchitecture
== CPU_SUBTYPE_ARM_V7K
) {
4307 warning("-watchos_version_min not specified, assuming 2.0");
4308 setWatchOSVersionMin("2.0");
4311 warning("-ios_version_min not specified, assuming 6.0");
4312 setIOSVersionMin("6.0");
4318 // architecture will be infered later by examining .o files
4325 // adjust min based on architecture
4326 switch ( fArchitecture
) {
4328 if ( (fPlatform
== kPlatformOSX
) && (fMacVersionMin
< ld::mac10_4
) ) {
4329 //warning("-macosx_version_min should be 10.4 or later for i386");
4330 fMacVersionMin
= ld::mac10_4
;
4333 case CPU_TYPE_X86_64
:
4334 if ( (fPlatform
== kPlatformOSX
) && (fMacVersionMin
< ld::mac10_4
) ) {
4335 //warning("-macosx_version_min should be 10.4 or later for x86_64");
4336 fMacVersionMin
= ld::mac10_4
;
4339 case CPU_TYPE_ARM64
:
4340 if ( (fPlatform
== kPlatformiOS
) && (fIOSVersionMin
< ld::iOS_7_0
) ) {
4341 //warning("-mios_version_min should be 7.0 or later for arm64");
4342 fIOSVersionMin
= ld::iOS_7_0
;
4347 // default to adding functions start for dynamic code, static code must opt-in
4348 switch ( fOutputKind
) {
4349 case Options::kPreload
:
4350 case Options::kStaticExecutable
:
4351 case Options::kKextBundle
:
4352 if ( fDataInCodeInfoLoadCommandForcedOn
)
4353 fDataInCodeInfoLoadCommand
= true;
4354 if ( fFunctionStartsForcedOn
)
4355 fFunctionStartsLoadCommand
= true;
4357 case Options::kObjectFile
:
4358 if ( !fDataInCodeInfoLoadCommandForcedOff
)
4359 fDataInCodeInfoLoadCommand
= true;
4360 if ( fFunctionStartsForcedOn
)
4361 fFunctionStartsLoadCommand
= true;
4363 case Options::kDynamicExecutable
:
4364 case Options::kDyld
:
4365 case Options::kDynamicLibrary
:
4366 case Options::kDynamicBundle
:
4367 if ( !fDataInCodeInfoLoadCommandForcedOff
)
4368 fDataInCodeInfoLoadCommand
= true;
4369 if ( !fFunctionStartsForcedOff
)
4370 fFunctionStartsLoadCommand
= true;
4374 // adjust kext type based on architecture
4375 if ( fOutputKind
== kKextBundle
) {
4376 switch ( fArchitecture
) {
4377 case CPU_TYPE_X86_64
:
4378 // x86_64 uses new MH_KEXT_BUNDLE type
4379 fMakeCompressedDyldInfo
= false;
4380 fMakeCompressedDyldInfoForceOff
= true;
4381 fAllowTextRelocs
= true;
4382 fUndefinedTreatment
= kUndefinedDynamicLookup
;
4384 case CPU_TYPE_ARM64
:
4385 // arm64 uses new MH_KEXT_BUNDLE type
4386 fMakeCompressedDyldInfo
= false;
4387 fMakeCompressedDyldInfoForceOff
= true;
4388 fAllowTextRelocs
= false;
4389 fKextsUseStubs
= true;
4390 fUndefinedTreatment
= kUndefinedDynamicLookup
;
4393 if ( min_iOS(ld::iOS_5_0
) ) {
4394 // iOS 5.0 and later use new MH_KEXT_BUNDLE type
4395 fMakeCompressedDyldInfo
= false;
4396 fMakeCompressedDyldInfoForceOff
= true;
4397 // kexts are PIC in iOS 6.0 and later
4398 fAllowTextRelocs
= !min_iOS(ld::iOS_6_0
);
4399 fKextsUseStubs
= !fAllowTextRelocs
;
4400 fUndefinedTreatment
= kUndefinedDynamicLookup
;
4403 // else use object file
4406 fOutputKind
= kObjectFile
;
4411 // disable implicit dylibs when targeting 10.3
4412 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
4413 if ( !minOS(ld::mac10_4
, ld::iOS_2_0
) )
4414 fImplicitlyLinkPublicDylibs
= false;
4417 // allow build system to force linker to ignore -prebind
4418 if ( getenv("LD_FORCE_NO_PREBIND") != NULL
)
4421 // allow build system to force linker to ignore -seg_addr_table
4422 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL
)
4423 fSegAddrTablePath
= NULL
;
4425 // check for base address specified externally
4426 if ( (fSegAddrTablePath
!= NULL
) && (fOutputKind
== Options::kDynamicLibrary
) ) {
4427 parseSegAddrTable(fSegAddrTablePath
, this->installPath());
4428 // HACK to support seg_addr_table entries that are physical paths instead of install paths
4429 if ( fBaseAddress
== 0 ) {
4430 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
4431 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.4.dylib");
4432 if ( fBaseAddress
== 0 )
4433 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.9.dylib");
4436 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
4437 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libz.1.2.3.dylib");
4439 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
4440 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libutil1.0.dylib");
4444 // split segs only allowed for dylibs
4446 // split seg only supported for i386, and arm.
4447 switch ( fArchitecture
) {
4449 if ( fOutputKind
!= Options::kDynamicLibrary
)
4451 // make sure read and write segments are proper distance apart
4452 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x10000000) )
4453 fBaseWritableAddress
= fBaseAddress
+ 0x10000000;
4456 if ( fOutputKind
!= Options::kDynamicLibrary
) {
4460 // make sure read and write segments are proper distance apart
4461 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x08000000) )
4462 fBaseWritableAddress
= fBaseAddress
+ 0x08000000;
4468 fBaseWritableAddress
= 0;
4472 // set too-large size
4473 switch ( fArchitecture
) {
4475 fMaxAddress
= 0xFFFFFFFF;
4477 case CPU_TYPE_X86_64
:
4480 switch ( fOutputKind
) {
4481 case Options::kDynamicExecutable
:
4482 case Options::kDynamicLibrary
:
4483 case Options::kDynamicBundle
:
4484 // user land code is limited to low 1GB
4485 fMaxAddress
= 0x2FFFFFFF;
4487 case Options::kStaticExecutable
:
4488 case Options::kObjectFile
:
4489 case Options::kDyld
:
4490 case Options::kPreload
:
4491 case Options::kKextBundle
:
4492 fMaxAddress
= 0xFFFFFFFF;
4495 // range check -seg1addr for ARM
4496 if ( fBaseAddress
> fMaxAddress
) {
4497 warning("ignoring -seg1addr 0x%08llX. Address out of range.", fBaseAddress
);
4503 // <rdar://problem/6138961> -r implies no prebinding for all architectures
4504 if ( fOutputKind
== Options::kObjectFile
)
4507 // disable prebinding depending on arch and min OS version
4509 switch ( fArchitecture
) {
4511 if ( fMacVersionMin
== ld::mac10_4
) {
4512 // in 10.4 only split seg dylibs are prebound
4513 if ( (fOutputKind
!= Options::kDynamicLibrary
) || ! fSplitSegs
)
4516 else if ( fMacVersionMin
>= ld::mac10_5
) {
4517 // in 10.5 nothing is prebound
4520 else if ( fIOSVersionMin
!= ld::iOSVersionUnset
) {
4521 // nothing in simulator is prebound
4525 // in 10.3 and earlier only dylibs and main executables could be prebound
4526 switch ( fOutputKind
) {
4527 case Options::kDynamicExecutable
:
4528 case Options::kDynamicLibrary
:
4529 // only main executables and dylibs can be prebound
4531 case Options::kStaticExecutable
:
4532 case Options::kDynamicBundle
:
4533 case Options::kObjectFile
:
4534 case Options::kDyld
:
4535 case Options::kPreload
:
4536 case Options::kKextBundle
:
4537 // disable prebinding for everything else
4543 case CPU_TYPE_X86_64
:
4547 switch ( fOutputKind
) {
4548 case Options::kDynamicExecutable
:
4549 case Options::kDynamicLibrary
:
4550 // only main executables and dylibs can be prebound
4552 case Options::kStaticExecutable
:
4553 case Options::kDynamicBundle
:
4554 case Options::kObjectFile
:
4555 case Options::kDyld
:
4556 case Options::kPreload
:
4557 case Options::kKextBundle
:
4558 // disable prebinding for everything else
4566 // only prebound images can be split-seg
4567 if ( fSplitSegs
&& !fPrebind
)
4570 // determine if info for shared region should be added
4571 if ( fOutputKind
== Options::kDynamicLibrary
) {
4572 if ( minOS(ld::mac10_5
, ld::iOS_3_1
) && !fTargetIOSSimulator
)
4573 if ( !fPrebind
&& !fSharedRegionEligibleForceOff
)
4574 if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
4575 || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
4576 fSharedRegionEligible
= true;
4578 else if ( fOutputKind
== Options::kDyld
) {
4579 // <rdar://problem/10111122> Enable dyld to be put into the dyld shared cache
4580 fSharedRegionEligible
= true;
4583 // <rdar://problem/18719327> warn if -rpath is used with OS dylibs
4584 if ( fSharedRegionEligible
&& !fRPaths
.empty() )
4585 warning("-rpath cannot be used with dylibs that will be in the dyld shared cache");
4587 // automatically use __DATA_CONST in iOS dylibs
4588 if ( fSharedRegionEligible
&& minOS(ld::mac10_Future
, ld::iOS_9_0
) && !fUseDataConstSegmentForceOff
) {
4589 fUseDataConstSegment
= true;
4591 if ( fUseDataConstSegmentForceOn
) {
4592 fUseDataConstSegment
= true;
4594 // A -kext for iOS 10 ==> -data_const, -text_exec, -add_split_seg_info
4595 if ( (fOutputKind
== Options::kKextBundle
) && minOS(ld::mac10_Future
, ld::iOS_10_0
) && (fArchitecture
== CPU_TYPE_ARM64
) ) {
4596 fUseDataConstSegment
= true;
4597 fUseTextExecSegment
= true;
4598 fSharedRegionEligible
= true;
4600 if ( fUseDataConstSegment
) {
4601 addSectionRename("__DATA", "__got", "__DATA_CONST", "__got");
4602 addSectionRename("__DATA", "__la_symbol_ptr", "__DATA_CONST", "__la_symbol_ptr");
4603 addSectionRename("__DATA", "__nl_symbol_ptr", "__DATA_CONST", "__nl_symbol_ptr");
4604 addSectionRename("__DATA", "__const", "__DATA_CONST", "__const");
4605 addSectionRename("__DATA", "__cfstring", "__DATA_CONST", "__cfstring");
4606 addSectionRename("__DATA", "__mod_init_func", "__DATA_CONST", "__mod_init_func");
4607 addSectionRename("__DATA", "__mod_term_func", "__DATA_CONST", "__mod_term_func");
4608 addSectionRename("__DATA", "__objc_classlist", "__DATA_CONST", "__objc_classlist");
4609 addSectionRename("__DATA", "__objc_nlclslist", "__DATA_CONST", "__objc_nlclslist");
4610 addSectionRename("__DATA", "__objc_catlist", "__DATA_CONST", "__objc_catlist");
4611 addSectionRename("__DATA", "__objc_nlcatlist", "__DATA_CONST", "__objc_nlcatlist");
4612 addSectionRename("__DATA", "__objc_protolist", "__DATA_CONST", "__objc_protolist");
4613 addSectionRename("__DATA", "__objc_imageinfo", "__DATA_CONST", "__objc_imageinfo");
4614 addSectionRename("__DATA", "__objc_const", "__DATA_CONST", "__objc_const");
4616 if ( fUseTextExecSegment
) {
4617 addSectionRename("__TEXT", "__text", "__TEXT_EXEC", "__text");
4618 addSectionRename("__TEXT", "__stubs", "__TEXT_EXEC", "__stubs");
4621 // Use V2 shared cache info when targetting newer OSs
4622 if ( fSharedRegionEligible
&& minOS(ld::mac10_12
, ld::iOS_9_0
)) {
4623 fSharedRegionEncodingV2
= true;
4624 // <rdar://problem/24772435> only use v2 for Swift dylibs on Mac OS X
4625 if ( (fPlatform
== kPlatformOSX
) && (strncmp(this->installPath(), "/System/Library/PrivateFrameworks/Swift/", 40) != 0) )
4626 fSharedRegionEncodingV2
= false;
4627 fIgnoreOptimizationHints
= true;
4630 // figure out if module table is needed for compatibility with old ld/dyld
4631 if ( fOutputKind
== Options::kDynamicLibrary
) {
4632 switch ( fArchitecture
) {
4634 if ( fIOSVersionMin
!= ld::iOSVersionUnset
) // simulator never needs modules
4638 fNeedsModuleTable
= true; // redo_prebinding requires a module table
4643 // <rdar://problem/5366363> -r -x implies -S
4644 if ( (fOutputKind
== Options::kObjectFile
) && (fLocalSymbolHandling
== kLocalSymbolsNone
) )
4645 fDebugInfoStripping
= Options::kDebugInfoNone
;
4647 // <rdar://problem/15252891> -r implies -no_uuid
4648 if ( fOutputKind
== Options::kObjectFile
)
4649 fUUIDMode
= kUUIDNone
;
4651 // choose how to process unwind info
4652 switch ( fArchitecture
) {
4654 case CPU_TYPE_X86_64
:
4655 case CPU_TYPE_ARM64
:
4656 switch ( fOutputKind
) {
4657 case Options::kObjectFile
:
4658 case Options::kStaticExecutable
:
4659 case Options::kPreload
:
4660 case Options::kKextBundle
:
4661 fAddCompactUnwindEncoding
= false;
4663 case Options::kDyld
:
4664 case Options::kDynamicLibrary
:
4665 case Options::kDynamicBundle
:
4666 case Options::kDynamicExecutable
:
4667 //if ( fAddCompactUnwindEncoding && (fVersionMin >= ld::mac10_6) )
4668 // fRemoveDwarfUnwindIfCompactExists = true;
4673 if ( armUsesZeroCostExceptions() ) {
4674 switch ( fOutputKind
) {
4675 case Options::kObjectFile
:
4676 case Options::kStaticExecutable
:
4677 case Options::kPreload
:
4678 case Options::kKextBundle
:
4679 fAddCompactUnwindEncoding
= false;
4681 case Options::kDyld
:
4682 case Options::kDynamicLibrary
:
4683 case Options::kDynamicBundle
:
4684 case Options::kDynamicExecutable
:
4685 fAddCompactUnwindEncoding
= true;
4690 fAddCompactUnwindEncoding
= false;
4691 fRemoveDwarfUnwindIfCompactExists
= false;
4695 // if -arch is missing, assume we don't want compact unwind info
4696 fAddCompactUnwindEncoding
= false;
4700 // only iOS executables should be encryptable
4701 switch ( fOutputKind
) {
4702 case Options::kObjectFile
:
4703 case Options::kDyld
:
4704 case Options::kStaticExecutable
:
4705 case Options::kPreload
:
4706 case Options::kKextBundle
:
4707 fEncryptable
= false;
4709 case Options::kDynamicExecutable
:
4711 case Options::kDynamicLibrary
:
4712 case Options::kDynamicBundle
:
4713 // <rdar://problem/16293398> Add LC_ENCRYPTION_INFO load command to bundled frameworks
4714 if ( !min_iOS(ld::iOS_7_0
) )
4715 fEncryptable
= false;
4718 if ( (fArchitecture
!= CPU_TYPE_ARM
) && (fArchitecture
!= CPU_TYPE_ARM64
)
4720 fEncryptable
= false;
4721 if ( fEncryptableForceOn
)
4722 fEncryptable
= true;
4723 else if ( fEncryptableForceOff
)
4724 fEncryptable
= false;
4726 // don't move inits in dyld because dyld wants certain
4727 // entries point at stable locations at the start of __text
4728 if ( fOutputKind
== Options::kDyld
)
4729 fAutoOrderInitializers
= false;
4732 // disable __data ordering for some output kinds
4733 switch ( fOutputKind
) {
4734 case Options::kObjectFile
:
4735 case Options::kDyld
:
4736 case Options::kStaticExecutable
:
4737 case Options::kPreload
:
4738 case Options::kKextBundle
:
4741 case Options::kDynamicExecutable
:
4742 case Options::kDynamicLibrary
:
4743 case Options::kDynamicBundle
:
4747 // only use compressed LINKEDIT for final linked images
4748 switch ( fOutputKind
) {
4749 case Options::kDynamicExecutable
:
4750 case Options::kDynamicLibrary
:
4751 case Options::kDynamicBundle
:
4753 case Options::kPreload
:
4754 case Options::kStaticExecutable
:
4755 case Options::kObjectFile
:
4756 case Options::kDyld
:
4757 case Options::kKextBundle
:
4758 fMakeCompressedDyldInfoForceOff
= true;
4761 if ( fMakeCompressedDyldInfoForceOff
)
4762 fMakeCompressedDyldInfo
= false;
4765 // only use compressed LINKEDIT for:
4766 // Mac OS X 10.6 or later
4768 if ( fMakeCompressedDyldInfo
) {
4769 if ( !minOS(ld::mac10_6
, ld::iOS_3_1
) )
4770 fMakeCompressedDyldInfo
= false;
4773 // only ARM and x86_64 enforces that cpu-sub-types must match
4774 switch ( fArchitecture
) {
4777 case CPU_TYPE_X86_64
:
4778 fEnforceDylibSubtypesMatch
= false;
4781 case CPU_TYPE_ARM64
:
4782 fEnforceDylibSubtypesMatch
= false;
4787 // only final linked images can not optimize zero fill sections
4788 if ( fOutputKind
== Options::kObjectFile
)
4789 fOptimizeZeroFill
= true;
4791 // all undefines in -r mode
4792 // if ( fOutputKind == Options::kObjectFile )
4793 // fUndefinedTreatment = kUndefinedSuppress;
4795 // only dynamic final linked images should warn about use of commmons
4796 if ( fWarnCommons
) {
4797 switch ( fOutputKind
) {
4798 case Options::kDynamicExecutable
:
4799 case Options::kDynamicLibrary
:
4800 case Options::kDynamicBundle
:
4802 case Options::kPreload
:
4803 case Options::kStaticExecutable
:
4804 case Options::kObjectFile
:
4805 case Options::kDyld
:
4806 case Options::kKextBundle
:
4807 fWarnCommons
= false;
4812 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
4813 if ( minOS(ld::mac10_5
, ld::iOS_2_0
) )
4814 fUseSimplifiedDylibReExports
= true;
4816 // Mac OS X 10.7 and iOS 4.2 support LC_LOAD_UPWARD_DYLIB
4817 if ( minOS(ld::mac10_7
, ld::iOS_4_2
) && (fOutputKind
== kDynamicLibrary
) )
4818 fCanUseUpwardDylib
= true;
4820 // MacOSX 10.7 defaults to PIE
4821 if ( (fArchitecture
== CPU_TYPE_I386
)
4822 && (fOutputKind
== kDynamicExecutable
)
4823 && (fMacVersionMin
>= ld::mac10_7
) ) {
4824 fPositionIndependentExecutable
= true;
4827 // armv7 for iOS4.3 defaults to PIE
4828 if ( (fArchitecture
== CPU_TYPE_ARM
)
4829 && fArchSupportsThumb2
4830 && (fOutputKind
== kDynamicExecutable
)
4831 && min_iOS(ld::iOS_4_3
) ) {
4832 fPositionIndependentExecutable
= true;
4835 // <rdar://problem/24535196> x86_64 defaults PIE (regardless of minOS version)
4836 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
== kDynamicExecutable
) && (fMacVersionMin
>= ld::mac10_6
) )
4837 fPositionIndependentExecutable
= true;
4839 // Simulator defaults to PIE
4840 if ( fTargetIOSSimulator
&& (fOutputKind
== kDynamicExecutable
) )
4841 fPositionIndependentExecutable
= true;
4843 // -no_pie anywhere on command line disable PIE
4844 if ( fDisablePositionIndependentExecutable
)
4845 fPositionIndependentExecutable
= false;
4847 // arm64 is always PIE
4848 if ( ((fArchitecture
== CPU_TYPE_ARM64
)
4850 && (fOutputKind
== kDynamicExecutable
) ) {
4851 fPositionIndependentExecutable
= true;
4852 if ( fDisablePositionIndependentExecutable
)
4853 warning("-no_pie ignored for arm64");
4856 // set fOutputSlidable
4857 switch ( fOutputKind
) {
4858 case Options::kObjectFile
:
4859 fOutputSlidable
= false;
4861 case Options::kStaticExecutable
:
4862 case Options::kDynamicExecutable
:
4863 fOutputSlidable
= fPositionIndependentExecutable
;
4865 case Options::kPreload
:
4866 fOutputSlidable
= fPIEOnCommandLine
;
4868 case Options::kDyld
:
4869 case Options::kDynamicLibrary
:
4870 case Options::kDynamicBundle
:
4871 case Options::kKextBundle
:
4872 fOutputSlidable
= true;
4876 // let linker know if thread local variables are supported
4877 if ( fMacVersionMin
>= ld::mac10_7
) {
4880 else if ( ((fArchitecture
== CPU_TYPE_ARM64
)
4882 && min_iOS(ld::iOS_8_0
) ) {
4885 else if ( (fArchitecture
== CPU_TYPE_ARM
) && min_iOS(ld::iOS_9_0
) ) {
4888 else if ( fTargetIOSSimulator
&& (fArchitecture
== CPU_TYPE_X86_64
) && min_iOS(ld::iOS_8_0
) ) {
4891 else if ( fTargetIOSSimulator
&& (fArchitecture
== CPU_TYPE_I386
) && min_iOS(ld::iOS_9_0
) ) {
4895 // default to adding version load command for dynamic code, static code must opt-in
4896 switch ( fOutputKind
) {
4897 case Options::kObjectFile
:
4898 fVersionLoadCommand
= false;
4900 case Options::kStaticExecutable
:
4901 case Options::kPreload
:
4902 case Options::kKextBundle
:
4903 if ( fVersionLoadCommandForcedOn
)
4904 fVersionLoadCommand
= true;
4906 case Options::kDynamicExecutable
:
4907 case Options::kDyld
:
4908 case Options::kDynamicLibrary
:
4909 case Options::kDynamicBundle
:
4910 if ( !fVersionLoadCommandForcedOff
)
4911 fVersionLoadCommand
= true;
4915 // support re-export of individual symbols in MacOSX 10.7 and iOS 4.2
4916 if ( (fOutputKind
== kDynamicLibrary
) && minOS(ld::mac10_7
, ld::iOS_4_2
) )
4917 fCanReExportSymbols
= true;
4919 // ObjC optimization is only in dynamic final linked images
4920 switch ( fOutputKind
) {
4921 case Options::kObjectFile
:
4922 case Options::kStaticExecutable
:
4923 case Options::kPreload
:
4924 case Options::kKextBundle
:
4925 case Options::kDyld
:
4926 fObjcCategoryMerging
= false;
4928 case Options::kDynamicExecutable
:
4929 case Options::kDynamicLibrary
:
4930 case Options::kDynamicBundle
:
4934 // i386 main executables linked on Mac OS X 10.7 default to NX heap
4935 // regardless of target unless overriden with -allow_heap_execute anywhere
4936 // on the command line
4937 if ( (fArchitecture
== CPU_TYPE_I386
) && (fOutputKind
== kDynamicExecutable
) && !fDisableNonExecutableHeap
)
4938 fNonExecutableHeap
= true;
4940 // Use LC_MAIN instead of LC_UNIXTHREAD for newer OSs
4941 switch ( fOutputKind
) {
4942 case Options::kDynamicExecutable
:
4943 if ( fEntryPointLoadCommandForceOn
) {
4944 fEntryPointLoadCommand
= true;
4945 if ( fEntryName
== NULL
)
4946 fEntryName
= "_main";
4948 else if ( fEntryPointLoadCommandForceOff
) {
4949 fNeedsThreadLoadCommand
= true;
4950 if ( fEntryName
== NULL
)
4951 fEntryName
= "start";
4954 // <rdar://problem/16310363> Linker should look for "_main" not "start" when building for sim regardless of min OS
4955 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) || fTargetIOSSimulator
) {
4956 fEntryPointLoadCommand
= true;
4957 if ( fEntryName
== NULL
)
4958 fEntryName
= "_main";
4959 if ( strcmp(fEntryName
, "start") == 0 ) {
4960 warning("Ignoring '-e start' because entry point 'start' is not used for the targeted OS version");
4961 fEntryName
= "_main";
4965 fNeedsThreadLoadCommand
= true;
4966 if ( fEntryName
== NULL
)
4967 fEntryName
= "start";
4971 case Options::kObjectFile
:
4972 case Options::kKextBundle
:
4973 case Options::kDynamicLibrary
:
4974 case Options::kDynamicBundle
:
4977 case Options::kStaticExecutable
:
4978 case Options::kPreload
:
4979 case Options::kDyld
:
4980 fNeedsThreadLoadCommand
= true;
4981 if ( fEntryName
== NULL
)
4982 fEntryName
= "start"; // Perhaps these should have no default and require -e
4986 // add LC_SOURCE_VERSION
4987 switch ( fOutputKind
) {
4988 case Options::kDynamicExecutable
:
4989 case Options::kKextBundle
:
4990 case Options::kDynamicLibrary
:
4991 case Options::kDynamicBundle
:
4992 case Options::kDyld
:
4993 case Options::kStaticExecutable
:
4994 if ( fSourceVersionLoadCommandForceOn
) {
4995 fSourceVersionLoadCommand
= true;
4997 else if ( fSourceVersionLoadCommandForceOff
) {
4998 fSourceVersionLoadCommand
= false;
5001 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) ) {
5002 fSourceVersionLoadCommand
= true;
5005 fSourceVersionLoadCommand
= false;
5008 case Options::kObjectFile
:
5009 case Options::kPreload
:
5010 fSourceVersionLoadCommand
= false;
5014 // if -sdk_version not on command line, infer from -syslibroot
5015 if ( (fSDKVersion
== 0) && (fSDKPaths
.size() > 0) ) {
5016 const char* sdkPath
= fSDKPaths
.front();
5017 const char* end
= &sdkPath
[strlen(sdkPath
)-1];
5018 while ( !isdigit(*end
) && (end
> sdkPath
) )
5020 const char* start
= end
-1;
5021 while ( (isdigit(*start
) || (*start
== '.')) && (start
> sdkPath
))
5023 char sdkVersionStr
[32];
5024 int len
= end
-start
+1;
5026 strlcpy(sdkVersionStr
, start
+1, len
);
5027 fSDKVersion
= parseVersionNumber32(sdkVersionStr
);
5031 // if -sdk_version and -syslibroot not used, but targeting MacOSX, use current OS version
5032 if ( (fSDKVersion
== 0) && (fMacVersionMin
!= ld::macVersionUnset
) ) {
5033 // special case if RC_ProjectName and MACOSX_DEPLOYMENT_TARGET are both set that sdkversion=minos
5034 if ( getenv("RC_ProjectName") && getenv("MACOSX_DEPLOYMENT_TARGET") ) {
5035 fSDKVersion
= fMacVersionMin
;
5038 int mib
[2] = { CTL_KERN
, KERN_OSRELEASE
};
5039 char kernVersStr
[100];
5040 size_t strlen
= sizeof(kernVersStr
);
5041 if ( sysctl(mib
, 2, kernVersStr
, &strlen
, NULL
, 0) != -1 ) {
5042 uint32_t kernVers
= parseVersionNumber32(kernVersStr
);
5043 int minor
= (kernVers
>> 16) - 4; // kernel major version is 4 ahead of x in 10.x
5044 fSDKVersion
= 0x000A0000 + (minor
<< 8);
5049 // allow trie based absolute symbols if targeting new enough OS
5050 if ( fMakeCompressedDyldInfo
) {
5051 if ( minOS(ld::mac10_9
, ld::iOS_7_0
) ) {
5052 fAbsoluteSymbols
= true;
5056 // <rdar://problem/12959510> iOS main executables now default to 16KB page size
5057 if ( (fIOSVersionMin
!= ld::iOSVersionUnset
) && (fOutputKind
== Options::kDynamicExecutable
) ) {
5058 // <rdar://problem/13070042> Only third party apps should have 16KB page segments by default
5059 if ( fEncryptable
) {
5060 if ( fSegmentAlignment
== 4096 )
5061 fSegmentAlignment
= 4096*4;
5065 // <rdar://problem/12258065> ARM64 needs 16KB page size for user land code
5066 // <rdar://problem/15974532> make armv7[s] use 16KB pages in user land code for iOS 8 or later
5067 if ( fSegmentAlignment
== 4096 ) {
5068 switch ( fOutputKind
) {
5069 case Options::kDynamicExecutable
:
5070 case Options::kDynamicLibrary
:
5071 case Options::kDynamicBundle
:
5072 case Options::kDyld
:
5073 if ( ((fArchitecture
== CPU_TYPE_ARM64
)
5075 || ((fArchitecture
== CPU_TYPE_ARM
) && min_iOS(ld::iOS_7_0
)) ) {
5076 fSegmentAlignment
= 4096*4;
5079 case Options::kStaticExecutable
:
5080 case Options::kKextBundle
:
5081 // <rdar://problem/14676611> 16KB segments for arm64 kexts
5082 if ( ((fArchitecture
== CPU_TYPE_ARM64
)
5084 && min_iOS(ld::iOS_9_0
) ) {
5085 fSegmentAlignment
= 4096*4;
5088 case Options::kObjectFile
:
5089 case Options::kPreload
:
5096 // <rdar://problem/13624134> linker should not convert dwarf unwind if .o file has compact unwind section
5097 switch ( fOutputKind
) {
5098 case Options::kDynamicExecutable
:
5099 case Options::kDynamicLibrary
:
5100 case Options::kDynamicBundle
:
5101 case Options::kDyld
:
5102 if ( fKeepDwarfUnwindForcedOn
) {
5103 fKeepDwarfUnwind
= true;
5105 else if ( fKeepDwarfUnwindForcedOff
) {
5106 fKeepDwarfUnwind
= false;
5109 if ( minOS(ld::mac10_9
, ld::iOS_7_0
) )
5110 fKeepDwarfUnwind
= false;
5112 fKeepDwarfUnwind
= true;
5115 case Options::kKextBundle
:
5116 case Options::kStaticExecutable
:
5117 case Options::kObjectFile
:
5118 case Options::kPreload
:
5119 fKeepDwarfUnwind
= true;
5123 // Make sure -image_base matches alignment
5124 uint64_t alignedBaseAddress
= (fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
);
5125 if ( alignedBaseAddress
!= fBaseAddress
) {
5126 warning("base address 0x%llX is not properly aligned. Changing it to 0x%llX", fBaseAddress
, alignedBaseAddress
);
5127 fBaseAddress
= alignedBaseAddress
;
5130 // If -dirty_data_list not specified, look in $SDKROOT/AppleInternal/DirtyDataFiles/<dylib>.dirty for dirty data list
5131 if ( fSymbolsMovesData
.empty() && fUseDataConstSegment
&& ( fDylibInstallName
!= NULL
) && !fSDKPaths
.empty() ) {
5132 const char* dylibLeaf
= strrchr(fDylibInstallName
, '/');
5134 char path
[PATH_MAX
];
5135 strlcpy(path
, fSDKPaths
.front(), sizeof(path
));
5136 strlcat(path
, "/AppleInternal/DirtyDataFiles", sizeof(path
));
5137 strlcat(path
, dylibLeaf
, sizeof(path
));
5138 strlcat(path
, ".dirty", sizeof(path
));
5140 if ( info
.checkFileExists(*this, path
) )
5141 addSymbolMove("__DATA_DIRTY", path
, fSymbolsMovesData
, "-dirty_data_list");
5145 // <rdar://problem/20503811> Reduce the default alignment of structures/arrays to save memory in embedded systems
5146 if ( fMaxDefaultCommonAlign
== 0 ) {
5147 if ( fOutputKind
== Options::kPreload
)
5148 fMaxDefaultCommonAlign
= 8;
5150 fMaxDefaultCommonAlign
= 15;
5154 void Options::checkIllegalOptionCombinations()
5156 // check -undefined setting
5157 switch ( fUndefinedTreatment
) {
5158 case kUndefinedError
:
5161 case kUndefinedDynamicLookup
:
5162 switch (fPlatform
) {
5166 case kPlatformWatchOS
:
5167 #if SUPPORT_APPLE_TV
5168 case kPlatform_tvOS
:
5170 if ( fOutputKind
!= kKextBundle
)
5171 warning("-undefined dynamic_lookup is deprecated on %s", platformName(fPlatform
));
5177 case kUndefinedWarning
:
5178 case kUndefinedSuppress
:
5179 // requires flat namespace
5180 if ( fNameSpace
== kTwoLevelNameSpace
)
5181 throw "can't use -undefined warning or suppress with -twolevel_namespace";
5185 // unify -sub_umbrella with dylibs
5186 for (std::vector
<const char*>::iterator it
= fSubUmbellas
.begin(); it
!= fSubUmbellas
.end(); it
++) {
5187 const char* subUmbrella
= *it
;
5189 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
5190 Options::FileInfo
& info
= *fit
;
5191 const char* lastSlash
= strrchr(info
.path
, '/');
5192 if ( lastSlash
== NULL
)
5193 lastSlash
= info
.path
- 1;
5194 std::string
path(&lastSlash
[1]);
5195 auto idx
= path
.find(".tbd", path
.size() - 4);
5196 if (idx
!= std::string::npos
)
5198 if ( path
== subUmbrella
) {
5199 info
.options
.fReExport
= true;
5201 fLinkSnapshot
.recordSubUmbrella(info
.path
);
5206 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella
);
5209 // unify -sub_library with dylibs
5210 for (std::vector
<const char*>::iterator it
= fSubLibraries
.begin(); it
!= fSubLibraries
.end(); it
++) {
5211 const char* subLibrary
= *it
;
5213 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
5214 Options::FileInfo
& info
= *fit
;
5215 const char* lastSlash
= strrchr(info
.path
, '/');
5216 if ( lastSlash
== NULL
)
5217 lastSlash
= info
.path
- 1;
5218 const char* dot
= strchr(&lastSlash
[1], '.');
5220 dot
= &lastSlash
[strlen(lastSlash
)];
5221 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
5222 info
.options
.fReExport
= true;
5224 fLinkSnapshot
.recordSubLibrary(info
.path
);
5229 warning("-sub_library %s does not match a supplied dylib", subLibrary
);
5232 // sync reader options
5233 if ( fNameSpace
!= kTwoLevelNameSpace
) {
5234 fFlatNamespace
= true;
5235 switch (fPlatform
) {
5239 case kPlatformWatchOS
:
5240 #if SUPPORT_APPLE_TV
5241 case Options::kPlatform_tvOS
:
5243 warning("-flat_namespace is deprecated on %s", platformName(fPlatform
));
5251 // check -stack_addr
5252 if ( fStackAddr
!= 0 ) {
5253 switch (fArchitecture
) {
5256 if ( fStackAddr
> 0xFFFFFFFF )
5257 throw "-stack_addr must be < 4G for 32-bit processes";
5259 case CPU_TYPE_X86_64
:
5260 case CPU_TYPE_ARM64
:
5263 if ( (fStackAddr
& -4096) != fStackAddr
)
5264 throw "-stack_addr must be multiples of 4K";
5265 if ( fStackSize
== 0 )
5266 throw "-stack_addr must be used with -stack_size";
5269 // check -stack_size
5270 if ( fStackSize
!= 0 ) {
5271 switch (fArchitecture
) {
5273 if ( fPlatform
== kPlatformOSX
) {
5274 if ( fStackSize
> 0xFFFFFFFF )
5275 throw "-stack_size must be < 4GB for 32-bit processes";
5276 if ( fStackAddr
== 0 )
5277 fStackAddr
= 0xC0000000;
5278 if ( (fStackAddr
> 0xB0000000) && ((fStackAddr
-fStackSize
) < 0xB0000000) )
5279 warning("custom stack placement overlaps and will disable shared region");
5282 if ( fStackSize
> 0x1F000000 )
5283 throw "-stack_size must be < 496MB";
5284 if ( fStackAddr
== 0 )
5285 fStackAddr
= 0xC0000000;
5289 if ( fStackSize
> 0x1F000000 )
5290 throw "-stack_size must be < 496MB";
5291 if ( fStackAddr
== 0 )
5292 fStackAddr
= 0x1F000000;
5293 if ( fStackAddr
> 0x20000000)
5294 throw "-stack_addr must be < 0x20000000 for arm";
5296 case CPU_TYPE_X86_64
:
5297 if ( fPlatform
== kPlatformOSX
) {
5298 if ( fStackSize
> 0x10000000000 )
5299 throw "-stack_size must be <= 1TB";
5300 if ( fStackAddr
== 0 ) {
5301 fStackAddr
= 0x00007FFF5C000000LL
;
5305 if ( fStackSize
> 0x20000000 )
5306 throw "-stack_size must be <= 512MB";
5307 if ( fStackAddr
== 0 ) {
5308 fStackAddr
= 0x120000000;
5311 case CPU_TYPE_ARM64
:
5312 if ( fStackSize
> 0x20000000 )
5313 throw "-stack_size must be <= 512MB";
5314 if ( fStackAddr
== 0 )
5315 fStackAddr
= 0x120000000;
5319 if ( (fStackSize
& (-fSegmentAlignment
)) != fStackSize
)
5320 throwf("-stack_size must be multiple of segment alignment (%lldKB)", fSegmentAlignment
/1024);
5321 switch ( fOutputKind
) {
5322 case Options::kDynamicExecutable
:
5323 case Options::kStaticExecutable
:
5324 // custom stack size only legal when building main executable
5326 case Options::kDynamicLibrary
:
5327 case Options::kDynamicBundle
:
5328 case Options::kObjectFile
:
5329 case Options::kDyld
:
5330 case Options::kPreload
:
5331 case Options::kKextBundle
:
5332 throw "-stack_size option can only be used when linking a main executable";
5334 if ( fStackSize
> fStackAddr
)
5335 throwf("-stack_size (0x%08llX) must be smaller than -stack_addr (0x%08llX)", fStackSize
, fStackAddr
);
5338 // check that -allow_stack_execute is only used with main executables
5339 if ( fExecutableStack
) {
5340 switch ( fOutputKind
) {
5341 case Options::kDynamicExecutable
:
5342 case Options::kStaticExecutable
:
5343 // -allow_stack_execute size only legal when building main executable
5345 case Options::kDynamicLibrary
:
5346 case Options::kDynamicBundle
:
5347 case Options::kObjectFile
:
5348 case Options::kDyld
:
5349 case Options::kPreload
:
5350 case Options::kKextBundle
:
5351 throw "-allow_stack_execute option can only be used when linking a main executable";
5355 // check that -allow_heap_execute is only used with i386 main executables
5356 if ( fDisableNonExecutableHeap
) {
5357 if ( fArchitecture
!= CPU_TYPE_I386
)
5358 throw "-allow_heap_execute option can only be used when linking for i386";
5359 switch ( fOutputKind
) {
5360 case Options::kDynamicExecutable
:
5361 // -allow_heap_execute only legal when building main executable
5363 case Options::kStaticExecutable
:
5364 case Options::kDynamicLibrary
:
5365 case Options::kDynamicBundle
:
5366 case Options::kObjectFile
:
5367 case Options::kDyld
:
5368 case Options::kPreload
:
5369 case Options::kKextBundle
:
5370 throw "-allow_heap_execute option can only be used when linking a main executable";
5374 // check -client_name is only used when making a bundle or main executable
5375 if ( fClientName
!= NULL
) {
5376 switch ( fOutputKind
) {
5377 case Options::kDynamicExecutable
:
5378 case Options::kDynamicBundle
:
5380 case Options::kStaticExecutable
:
5381 case Options::kDynamicLibrary
:
5382 case Options::kObjectFile
:
5383 case Options::kDyld
:
5384 case Options::kPreload
:
5385 case Options::kKextBundle
:
5386 throw "-client_name can only be used with -bundle";
5390 // check -init is only used when building a dylib
5391 if ( (fInitFunctionName
!= NULL
) && (fOutputKind
!= Options::kDynamicLibrary
) )
5392 throw "-init can only be used with -dynamiclib";
5394 // check -bundle_loader only used with -bundle
5395 if ( (fBundleLoader
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
5396 throw "-bundle_loader can only be used with -bundle";
5398 // check -dtrace not used with -r
5399 if ( (fDtraceScriptName
!= NULL
) && (fOutputKind
== Options::kObjectFile
) )
5400 throw "-dtrace can only be used when creating final linked images";
5402 // check -d can only be used with -r
5403 if ( fMakeTentativeDefinitionsReal
&& (fOutputKind
!= Options::kObjectFile
) )
5404 throw "-d can only be used with -r";
5406 // check that -root_safe is not used with -r
5407 if ( fRootSafe
&& (fOutputKind
== Options::kObjectFile
) )
5408 throw "-root_safe cannot be used with -r";
5410 // check that -setuid_safe is not used with -r
5411 if ( fSetuidSafe
&& (fOutputKind
== Options::kObjectFile
) )
5412 throw "-setuid_safe cannot be used with -r";
5414 // <rdar://problem/12781832> compiler driver no longer uses -objc_abi_version, it uses -ios_simulator_version_min instead
5415 if ( !fObjCABIVersion1Override
&& !fObjCABIVersion2Override
&& fTargetIOSSimulator
)
5416 fObjCABIVersion2Override
= true;
5418 // rdar://problem/4718189 map ObjC class names to new runtime names
5419 bool alterObjC1ClassNamesToObjC2
= false;
5420 switch (fArchitecture
) {
5422 // i386 only uses new symbols when using objc2 ABI
5423 if ( fObjCABIVersion2Override
)
5424 alterObjC1ClassNamesToObjC2
= true;
5426 case CPU_TYPE_X86_64
:
5428 case CPU_TYPE_ARM64
:
5429 alterObjC1ClassNamesToObjC2
= true;
5433 // make sure all required exported symbols exist
5434 std::vector
<const char*> impliedExports
;
5435 for (NameSet::iterator it
=fExportSymbols
.regularBegin(); it
!= fExportSymbols
.regularEnd(); ++it
) {
5436 const char* name
= *it
;
5437 const int len
= strlen(name
);
5438 if ( (strcmp(&name
[len
-3], ".eh") == 0) || (strncmp(name
, ".objc_category_name_", 20) == 0) ) {
5439 // never export .eh symbols
5440 warning("ignoring %s in export list", name
);
5442 else if ( (fArchitecture
== CPU_TYPE_I386
) && !fObjCABIVersion2Override
&& (strncmp(name
, "_OBJC_CLASS_$", 13) == 0) ) {
5443 warning("ignoring Objc2 Class symbol %s in i386 export list", name
);
5444 fRemovedExports
.insert(name
);
5446 else if ( alterObjC1ClassNamesToObjC2
&& (strncmp(name
, ".objc_class_name_", 17) == 0) ) {
5447 // linking ObjC2 ABI, but have ObjC1 ABI name in export list. Change it to intended name
5448 fRemovedExports
.insert(name
);
5450 asprintf(&temp
, "_OBJC_CLASS_$_%s", &name
[17]);
5451 impliedExports
.push_back(temp
);
5452 asprintf(&temp
, "_OBJC_METACLASS_$_%s", &name
[17]);
5453 impliedExports
.push_back(temp
);
5456 fInitialUndefines
.push_back(name
);
5459 fExportSymbols
.remove(fRemovedExports
);
5460 for (std::vector
<const char*>::iterator it
=impliedExports
.begin(); it
!= impliedExports
.end(); ++it
) {
5461 const char* name
= *it
;
5462 fExportSymbols
.insert(name
);
5463 fInitialUndefines
.push_back(name
);
5466 // make sure all required re-exported symbols exist
5467 for (NameSet::iterator it
=fReExportSymbols
.regularBegin(); it
!= fReExportSymbols
.regularEnd(); ++it
) {
5468 fInitialUndefines
.push_back(*it
);
5471 // make sure that -init symbol exists
5472 if ( fInitFunctionName
!= NULL
)
5473 fInitialUndefines
.push_back(fInitFunctionName
);
5475 // make sure that entry symbol exists
5476 switch ( fOutputKind
) {
5477 case Options::kDynamicExecutable
:
5478 case Options::kStaticExecutable
:
5479 case Options::kDyld
:
5480 case Options::kPreload
:
5481 fInitialUndefines
.push_back(fEntryName
);
5483 case Options::kDynamicLibrary
:
5484 case Options::kDynamicBundle
:
5485 case Options::kObjectFile
:
5486 case Options::kKextBundle
:
5490 // make sure every alias base exists
5491 for (std::vector
<AliasPair
>::iterator it
=fAliases
.begin(); it
!= fAliases
.end(); ++it
) {
5492 fInitialUndefines
.push_back(it
->realName
);
5495 // check custom segments
5496 if ( fCustomSegmentAddresses
.size() != 0 ) {
5497 // verify no segment is in zero page
5498 if ( fZeroPageSize
!= ULLONG_MAX
) {
5499 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
5500 if ( it
->address
< fZeroPageSize
)
5501 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it
->name
, it
->address
);
5504 // verify no duplicates
5505 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
5506 for (std::vector
<SegmentStart
>::iterator it2
= fCustomSegmentAddresses
.begin(); it2
!= fCustomSegmentAddresses
.end(); ++it2
) {
5507 if ( (it
->address
== it2
->address
) && (it
!= it2
) )
5508 throwf("duplicate -segaddr addresses for %s and %s", it
->name
, it2
->name
);
5510 // a custom segment address of zero will disable the use of a zero page
5511 if ( it
->address
== 0 )
5516 if ( fZeroPageSize
== ULLONG_MAX
) {
5517 // zero page size not specified on command line, set default
5518 switch (fArchitecture
) {
5521 // first 4KB for 32-bit architectures
5522 fZeroPageSize
= 0x1000;
5524 case CPU_TYPE_ARM64
:
5525 case CPU_TYPE_X86_64
:
5526 // first 4GB for x86_64 on all OS's
5527 fZeroPageSize
= 0x100000000ULL
;
5530 // if -arch not used, default to 4K zero-page
5531 fZeroPageSize
= 0x1000;
5535 switch ( fOutputKind
) {
5536 case Options::kDynamicExecutable
:
5537 case Options::kStaticExecutable
:
5538 // -pagezero_size size only legal when building main executable
5540 case Options::kDynamicLibrary
:
5541 case Options::kDynamicBundle
:
5542 case Options::kObjectFile
:
5543 case Options::kDyld
:
5544 case Options::kPreload
:
5545 case Options::kKextBundle
:
5546 if ( fZeroPageSize
!= 0 )
5547 throw "-pagezero_size option can only be used when linking a main executable";
5551 // if main executable with custom base address, model zero page as custom segment
5552 if ( (fOutputKind
== Options::kDynamicExecutable
) && (fBaseAddress
!= 0) && (fZeroPageSize
!= 0) ) {
5554 seg
.name
= "__PAGEZERO";
5556 fCustomSegmentAddresses
.push_back(seg
);
5559 // -dead_strip and -r are incompatible
5560 if ( fDeadStrip
&& (fOutputKind
== Options::kObjectFile
) )
5561 throw "-r and -dead_strip cannot be used together";
5563 // can't use -rpath unless targeting 10.5 or later
5564 if ( fRPaths
.size() > 0 ) {
5565 if ( !minOS(ld::mac10_5
, ld::iOS_2_0
) )
5566 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
5567 switch ( fOutputKind
) {
5568 case Options::kDynamicExecutable
:
5569 case Options::kDynamicLibrary
:
5570 case Options::kDynamicBundle
:
5572 case Options::kStaticExecutable
:
5573 case Options::kObjectFile
:
5574 case Options::kDyld
:
5575 case Options::kPreload
:
5576 case Options::kKextBundle
:
5577 throw "-rpath can only be used when creating a dynamic final linked image";
5581 if ( fPositionIndependentExecutable
) {
5582 switch ( fOutputKind
) {
5583 case Options::kDynamicExecutable
:
5584 // check -pie is only used when building a dynamic main executable for 10.5
5585 if ( !minOS(ld::mac10_5
, ld::iOS_4_2
) ) {
5586 if ( fIOSVersionMin
== ld::iOSVersionUnset
)
5587 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
5589 throw "-pie can only be used when targeting iOS 4.2 or later";
5592 case Options::kStaticExecutable
:
5593 case Options::kPreload
:
5594 // -pie is ok with -static or -preload
5596 case Options::kDynamicLibrary
:
5597 case Options::kDynamicBundle
:
5598 warning("-pie being ignored. It is only used when linking a main executable");
5599 fPositionIndependentExecutable
= false;
5601 case Options::kObjectFile
:
5602 case Options::kDyld
:
5603 case Options::kKextBundle
:
5604 throw "-pie can only be used when linking a main executable";
5608 // check -read_only_relocs is not used with x86_64
5609 if ( fAllowTextRelocs
) {
5610 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
!= kKextBundle
) ) {
5611 warning("-read_only_relocs cannot be used with x86_64");
5612 fAllowTextRelocs
= false;
5616 // check -mark_auto_dead_strip is only used with dylibs
5617 if ( fMarkDeadStrippableDylib
) {
5618 if ( fOutputKind
!= Options::kDynamicLibrary
) {
5619 warning("-mark_auto_dead_strip can only be used when creating a dylib");
5620 fMarkDeadStrippableDylib
= false;
5624 // -force_cpusubtype_ALL is not supported for ARM
5625 if ( fForceSubtypeAll
) {
5626 if ( fArchitecture
== CPU_TYPE_ARM
) {
5627 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
5631 // -reexported_symbols_list can only be used with -dynamiclib
5632 if ( !fReExportSymbols
.empty() ) {
5633 if ( fOutputKind
!= Options::kDynamicLibrary
)
5634 throw "-reexported_symbols_list can only used used when created dynamic libraries";
5635 if ( !minOS(ld::mac10_7
, ld::iOS_4_2
) )
5636 throw "targeted OS version does not support -reexported_symbols_list";
5639 // -dyld_env can only be used with main executables
5640 if ( (fOutputKind
!= Options::kDynamicExecutable
) && (fDyldEnvironExtras
.size() != 0) )
5641 throw "-dyld_env can only used used when created main executables";
5643 // -segment_order can only be used with -preload or -static
5644 if ( !fSegmentOrder
.empty() && ((fOutputKind
!= Options::kPreload
) && (fOutputKind
!= kStaticExecutable
)) )
5645 throw "-segment_order can only used used with -preload output";
5647 // warn about bitcode option combinations
5648 if ( !fBundleBitcode
) {
5649 if ( fVerifyBitcode
)
5650 warning("-bitcode_verify is ignored without -bitcode_bundle");
5651 else if ( fHideSymbols
)
5652 warning("-bitcode_hide_symbols is ignored without -bitcode_bundle");
5654 if ( fReverseMapPath
!= NULL
&& !fHideSymbols
) {
5655 throw "-bitcode_symbol_map can only be used with -bitcode_hide_symbols";
5657 // auto fix up the process type for strip -S.
5658 // when there is only one input and output type is object file, downgrade kBitcodeProcess to kBitcodeAsData.
5659 if ( fOutputKind
== Options::kObjectFile
&& fInputFiles
.size() == 1 && fBitcodeKind
== Options::kBitcodeProcess
)
5660 fBitcodeKind
= Options::kBitcodeAsData
;
5662 // <rdar://problem/17598404> warn if building an embedded iOS dylib for pre-iOS 8
5663 // <rdar://problem/18935714> How can we suppress "ld: warning: embedded dylibs/frameworks only run on iOS 8 or later" when building XCTest?
5664 if ( (fOutputKind
== Options::kDynamicLibrary
) && (fIOSVersionMin
!= ld::iOSVersionUnset
) && (fDylibInstallName
!= NULL
) ) {
5665 if ( !min_iOS(ld::iOS_8_0
) && (fDylibInstallName
[0] == '@') && !fEncryptableForceOff
)
5666 warning("embedded dylibs/frameworks only run on iOS 8 or later");
5670 // produce nicer error when no input
5671 if ( fInputFiles
.empty() ) {
5672 throw "no object files specified";
5677 void Options::checkForClassic(int argc
, const char* argv
[])
5680 bool archFound
= false;
5681 bool staticFound
= false;
5682 bool dtraceFound
= false;
5683 bool kextFound
= false;
5684 bool rFound
= false;
5685 bool creatingMachKernel
= false;
5686 bool newLinker
= false;
5688 // build command line buffer in case ld crashes
5689 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
5690 CRSetCrashLogMessage(crashreporterBuffer
);
5692 const char* srcRoot
= getenv("SRCROOT");
5693 if ( srcRoot
!= NULL
) {
5694 strlcpy(crashreporterBuffer
, "SRCROOT=", crashreporterBufferSize
);
5695 strlcat(crashreporterBuffer
, srcRoot
, crashreporterBufferSize
);
5696 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
5699 strlcat(crashreporterBuffer
, LD_VERS
, crashreporterBufferSize
);
5700 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
5702 strlcat(crashreporterBuffer
, "ld ", crashreporterBufferSize
);
5703 for(int i
=1; i
< argc
; ++i
) {
5704 strlcat(crashreporterBuffer
, argv
[i
], crashreporterBufferSize
);
5705 strlcat(crashreporterBuffer
, " ", crashreporterBufferSize
);
5708 for(int i
=0; i
< argc
; ++i
) {
5709 const char* arg
= argv
[i
];
5710 if ( arg
[0] == '-' ) {
5711 if ( strcmp(arg
, "-arch") == 0 ) {
5712 parseArch(argv
[++i
]);
5715 else if ( strcmp(arg
, "-static") == 0 ) {
5718 else if ( strcmp(arg
, "-kext") == 0 ) {
5721 else if ( strcmp(arg
, "-dtrace") == 0 ) {
5724 else if ( strcmp(arg
, "-r") == 0 ) {
5727 else if ( strcmp(arg
, "-new_linker") == 0 ) {
5730 else if ( strcmp(arg
, "-classic_linker") == 0 ) {
5731 // ld_classic does not understand this option, so remove it
5732 for(int j
=i
; j
< argc
; ++j
)
5733 argv
[j
] = argv
[j
+1];
5734 warning("using ld_classic");
5735 this->gotoClassicLinker(argc
-1, argv
);
5737 else if ( strcmp(arg
, "-o") == 0 ) {
5738 const char* outfile
= argv
[++i
];
5739 if ( (outfile
!= NULL
) && (strstr(outfile
, "/mach_kernel") != NULL
) )
5740 creatingMachKernel
= true;
5746 void Options::gotoClassicLinker(int argc
, const char* argv
[])
5748 argv
[0] = "ld_classic";
5749 // ld_classic does not support -iphoneos_version_min, so change
5750 for(int j
=0; j
< argc
; ++j
) {
5751 if ( (strcmp(argv
[j
], "-iphoneos_version_min") == 0) || (strcmp(argv
[j
], "-ios_version_min") == 0) ) {
5752 argv
[j
] = "-macosx_version_min";
5758 // ld classic does not understand -kext (change to -static -r)
5759 for(int j
=0; j
< argc
; ++j
) {
5760 if ( strcmp(argv
[j
], "-kext") == 0)
5762 else if ( strcmp(argv
[j
], "-dynamic") == 0)
5763 argv
[j
] = "-static";
5765 // ld classic does not understand -demangle
5766 for(int j
=0; j
< argc
; ++j
) {
5767 if ( strcmp(argv
[j
], "-demangle") == 0)
5768 argv
[j
] = "-noprebind";
5770 // in -v mode, print command line passed to ld_classic
5771 for(int i
=0; i
< argc
; ++i
) {
5772 if ( strcmp(argv
[i
], "-v") == 0 ) {
5773 for(int j
=0; j
< argc
; ++j
)
5774 printf("%s ", argv
[j
]);
5779 char rawPath
[PATH_MAX
];
5780 char path
[PATH_MAX
];
5781 uint32_t bufSize
= PATH_MAX
;
5782 if ( _NSGetExecutablePath(rawPath
, &bufSize
) != -1 ) {
5783 if ( realpath(rawPath
, path
) != NULL
) {
5784 char* lastSlash
= strrchr(path
, '/');
5785 if ( lastSlash
!= NULL
) {
5786 strcpy(lastSlash
+1, "ld_classic");
5788 execvp(path
, (char**)argv
);
5792 // in case of error in above, try searching for ld_classic via PATH
5793 execvp(argv
[0], (char**)argv
);
5794 fprintf(stderr
, "can't exec ld_classic\n");
5799 // Note, returned string buffer is own by this function.
5800 // It should not be freed
5801 // It will be reused, so clients need to strdup() if they want
5802 // to use it long term.
5803 const char* Options::demangleSymbol(const char* sym
) const
5805 // only try to demangle symbols if -demangle on command line
5809 static size_t size
= 1024;
5810 static char* buff
= (char*)malloc(size
);
5813 // only try to demangle symbols that look like Swift symbols
5814 if ( strncmp(sym
, "__T", 3) == 0 ) {
5815 size_t demangledSize
= fnd_get_demangled_name(&sym
[1], buff
, size
);
5816 if ( demangledSize
> size
) {
5817 size
= demangledSize
+2;
5818 buff
= (char*)realloc(buff
, size
);
5819 demangledSize
= fnd_get_demangled_name(&sym
[1], buff
, size
);
5821 if ( demangledSize
!= 0 )
5826 // only try to demangle symbols that look like C++ symbols
5827 if ( strncmp(sym
, "__Z", 3) != 0 )
5831 char* result
= abi::__cxa_demangle(&sym
[1], buff
, &size
, &status
);
5832 if ( result
!= NULL
) {
5833 // if demangling successful, keep buffer for next demangle
5841 void Options::dumpDependency(uint8_t opcode
, const char* path
) const
5843 if ( !this->dumpDependencyInfo() )
5846 // one time open() of -dependency_info file
5847 if ( fDependencyFileDescriptor
== -1 ) {
5848 fDependencyFileDescriptor
= open(this->dependencyInfoPath(), O_WRONLY
| O_TRUNC
| O_CREAT
, 0666);
5849 if ( fDependencyFileDescriptor
== -1 )
5850 throwf("Could not open or create -dependency_info file: %s", this->dependencyInfoPath());
5853 uint8_t version
= depLinkerVersion
;
5854 if ( write(fDependencyFileDescriptor
, &version
, 1) == -1 )
5855 throwf("write() to -dependency_info failed, errno=%d", errno
);
5856 extern const char ldVersionString
[];
5857 if ( write(fDependencyFileDescriptor
, ldVersionString
, strlen(ldVersionString
)+1) == -1 )
5858 throwf("write() to -dependency_info failed, errno=%d", errno
);
5861 char realPath
[PATH_MAX
];
5862 if ( path
[0] != '/' ) {
5863 if ( realpath(path
, realPath
) != NULL
) {
5868 if ( write(fDependencyFileDescriptor
, &opcode
, 1) == -1 )
5869 throwf("write() to -dependency_info failed, errno=%d", errno
);
5870 if ( write(fDependencyFileDescriptor
, path
, strlen(path
)+1) == -1 )
5871 throwf("write() to -dependency_info failed, errno=%d", errno
);
5873 //fprintf(stderr, "0x%02X %s\n", opcode, path);
5877 void Options::writeToTraceFile(const char* buffer
, size_t len
) const
5879 // one time open() of custom LD_TRACE_FILE
5880 if ( fTraceFileDescriptor
== -1 ) {
5881 if ( fTraceOutputFile
!= NULL
) {
5882 fTraceFileDescriptor
= open(fTraceOutputFile
, O_WRONLY
| O_APPEND
| O_CREAT
, 0666);
5883 if ( fTraceFileDescriptor
== -1 )
5884 throwf("Could not open or create trace file (errno=%d): %s", errno
, fTraceOutputFile
);
5887 fTraceFileDescriptor
= fileno(stderr
);
5892 ssize_t amountWritten
= write(fTraceFileDescriptor
, buffer
, len
);
5893 if ( amountWritten
== -1 )
5894 /* Failure to write shouldn't fail the build. */
5896 buffer
+= amountWritten
;
5897 len
-= amountWritten
;