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 fileLen
= statBuffer
.st_size
;
124 modTime
= statBuffer
.st_mtime
;
127 if ( options
.dumpDependencyInfo() )
128 options
.dumpDependency(Options::depNotFound
, p
);
129 // fprintf(stderr, "not found: %s\n", p);
134 Options::Options(int argc
, const char* argv
[])
135 : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0), fArchitectureName("unknown"), fOutputKind(kDynamicExecutable
),
136 fHasPreferredSubType(false), fArchSupportsThumb2(false), fPrebind(false), fBindAtLoad(false), fKeepPrivateExterns(false),
137 fNeedsModuleTable(false), fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false),
138 fInterposeMode(kInterposeNone
), fDeadStrip(false), fNameSpace(kTwoLevelNameSpace
),
139 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL
), fFinalName(NULL
), fEntryName(NULL
),
140 fBaseAddress(0), fMaxAddress(0x7FFFFFFFFFFFFFFFLL
),
141 fBaseWritableAddress(0), fSplitSegs(false),
142 fExportMode(kExportDefault
), fLibrarySearchMode(kSearchDylibAndArchiveInEachDir
),
143 fUndefinedTreatment(kUndefinedError
), fMessagesPrefixedWithArchitecture(true),
144 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak
),
146 fUmbrellaName(NULL
), fInitFunctionName(NULL
), fDotOutputFile(NULL
), fExecutablePath(NULL
),
147 fBundleLoader(NULL
), fDtraceScriptName(NULL
), fSegAddrTablePath(NULL
), fMapPath(NULL
),
148 fDyldInstallPath("/usr/lib/dyld"), fTempLtoObjectPath(NULL
), fOverridePathlibLTO(NULL
), fLtoCpu(NULL
),
149 fZeroPageSize(ULLONG_MAX
), fStackSize(0), fStackAddr(0), fSourceVersion(0), fSDKVersion(0), fExecutableStack(false),
150 fNonExecutableHeap(false), fDisableNonExecutableHeap(false),
151 fMinimumHeaderPad(32), fSegmentAlignment(4096),
152 fCommonsMode(kCommonsIgnoreDylibs
), fUUIDMode(kUUIDContent
), fLocalSymbolHandling(kLocalSymbolsAll
), fWarnCommons(false),
153 fVerbose(false), fKeepRelocations(false), fWarnStabs(false),
154 fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
155 fSharedRegionEligible(false), fSharedRegionEligibleForceOff(false), fPrintOrderFileStatistics(false),
156 fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), fPIEOnCommandLine(false),
157 fDisablePositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
158 fDeadStripDylibs(false), fAllowTextRelocs(false), fWarnTextRelocs(false), fKextsUseStubs(false),
159 fUsingLazyDylibLinking(false), fEncryptable(true), fEncryptableForceOn(false), fEncryptableForceOff(false),
160 fOrderData(true), fMarkDeadStrippableDylib(false),
161 fMakeCompressedDyldInfo(true), fMakeCompressedDyldInfoForceOff(false), fNoEHLabels(false),
162 fAllowCpuSubtypeMismatches(false), fEnforceDylibSubtypesMatch(false), fUseSimplifiedDylibReExports(false),
163 fObjCABIVersion2Override(false), fObjCABIVersion1Override(false), fCanUseUpwardDylib(false),
164 fFullyLoadArchives(false), fLoadAllObjcObjectsFromArchives(false), fFlatNamespace(false),
165 fLinkingMainExecutable(false), fForFinalLinkedImage(false), fForStatic(false),
166 fForDyld(false), fMakeTentativeDefinitionsReal(false), fWhyLoad(false), fRootSafe(false),
167 fSetuidSafe(false), fImplicitlyLinkPublicDylibs(true), fAddCompactUnwindEncoding(true),
168 fWarnCompactUnwind(false), fRemoveDwarfUnwindIfCompactExists(false),
169 fAutoOrderInitializers(true), fOptimizeZeroFill(true), fMergeZeroFill(false), fLogObjectFiles(false),
170 fLogAllFiles(false), fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false), fTraceEmitJSON(false),
171 fOutputSlidable(false), fWarnWeakExports(false),
172 fObjcGcCompaction(false), fObjCGc(false), fObjCGcOnly(false),
173 fDemangle(false), fTLVSupport(false),
174 fVersionLoadCommand(false), fVersionLoadCommandForcedOn(false),
175 fVersionLoadCommandForcedOff(false), fFunctionStartsLoadCommand(false),
176 fFunctionStartsForcedOn(false), fFunctionStartsForcedOff(false),
177 fDataInCodeInfoLoadCommand(false), fDataInCodeInfoLoadCommandForcedOn(false), fDataInCodeInfoLoadCommandForcedOff(false),
178 fCanReExportSymbols(false), fObjcCategoryMerging(true), fPageAlignDataAtoms(false),
179 fNeedsThreadLoadCommand(false), fEntryPointLoadCommand(false),
180 fEntryPointLoadCommandForceOn(false), fEntryPointLoadCommandForceOff(false),
181 fSourceVersionLoadCommand(false),
182 fSourceVersionLoadCommandForceOn(false), fSourceVersionLoadCommandForceOff(false),
183 fTargetIOSSimulator(false), fExportDynamic(false), fAbsoluteSymbols(false),
184 fAllowSimulatorToLinkWithMacOSX(false), fKeepDwarfUnwind(true),
185 fKeepDwarfUnwindForcedOn(false), fKeepDwarfUnwindForcedOff(false),
186 fVerboseOptimizationHints(false), fIgnoreOptimizationHints(false),
187 fGenerateDtraceDOF(true), fAllowBranchIslands(true), fTraceSymbolLayout(false),
188 fMarkAppExtensionSafe(false), fCheckAppExtensionSafe(false), fForceLoadSwiftLibs(false),
189 fSharedRegionEncodingV2(false), fUseDataConstSegment(false),
190 fUseDataConstSegmentForceOn(false), fUseDataConstSegmentForceOff(false), fUseTextExecSegment(false),
191 fBundleBitcode(false), fHideSymbols(false), fVerifyBitcode(false),
192 fReverseMapUUIDRename(false), fDeDupe(true), fVerboseDeDupe(false),
193 fReverseMapPath(NULL
), fLTOCodegenOnly(false),
194 fIgnoreAutoLink(false), fAllowDeadDups(false), fAllowWeakImports(true), fBitcodeKind(kBitcodeProcess
),
195 fPlatform(kPlatformUnknown
), fDebugInfoStripping(kDebugInfoMinimal
), fTraceOutputFile(NULL
),
196 fMacVersionMin(ld::macVersionUnset
), fIOSVersionMin(ld::iOSVersionUnset
), fWatchOSVersionMin(ld::wOSVersionUnset
),
197 fSaveTempFiles(false), fSnapshotRequested(false), fPipelineFifo(NULL
),
198 fDependencyInfoPath(NULL
), fDependencyFileDescriptor(-1), fMaxDefaultCommonAlign(0)
200 this->checkForClassic(argc
, argv
);
201 this->parsePreCommandLineEnvironmentSettings();
202 this->parse(argc
, argv
);
203 this->parsePostCommandLineEnvironmentSettings();
204 this->reconfigureDefaults();
205 this->checkIllegalOptionCombinations();
207 if ( this->dumpDependencyInfo() ) {
208 this->dumpDependency(depOutputFile
, fOutputFile
);
209 if ( fMapPath
!= NULL
)
210 this->dumpDependency(depOutputFile
, fMapPath
);
216 if ( fDependencyFileDescriptor
!= -1 )
217 ::close(fDependencyFileDescriptor
);
220 bool Options::errorBecauseOfWarnings() const
222 return (sFatalWarnings
&& (sWarningsCount
> 0));
226 const char* Options::installPath() const
228 if ( fDylibInstallName
!= NULL
)
229 return fDylibInstallName
;
230 else if ( fFinalName
!= NULL
)
237 bool Options::interposable(const char* name
) const
239 switch ( fInterposeMode
) {
242 case kInterposeAllExternal
:
245 return fInterposeList
.contains(name
);
247 throw "internal error";
251 bool Options::printWhyLive(const char* symbolName
) const
253 return fWhyLive
.contains(symbolName
);
257 const char* Options::dotOutputFile()
259 return fDotOutputFile
;
263 bool Options::hasWildCardExportRestrictList() const
265 // has -exported_symbols_list which contains some wildcards
266 return ((fExportMode
== kExportSome
) && fExportSymbols
.hasWildCards());
269 bool Options::hasWeakBitTweaks() const
271 // has -exported_symbols_list which contains some wildcards
272 return (!fForceWeakSymbols
.empty() || !fForceNotWeakSymbols
.empty());
275 bool Options::allGlobalsAreDeadStripRoots() const
277 // -exported_symbols_list means globals are not exported by default
278 if ( fExportMode
== kExportSome
)
281 switch ( fOutputKind
) {
282 case Options::kDynamicExecutable
:
283 // <rdar://problem/12839986> Add the -export_dynamic flag
284 return fExportDynamic
;
285 case Options::kStaticExecutable
:
286 // <rdar://problem/13361218> Support the -export_dynamic flag for xnu
287 return fExportDynamic
;
288 case Options::kPreload
:
289 // by default unused globals in a main executable are stripped
291 case Options::kDynamicLibrary
:
292 case Options::kDynamicBundle
:
293 case Options::kObjectFile
:
295 case Options::kKextBundle
:
302 bool Options::keepRelocations()
304 return fKeepRelocations
;
307 bool Options::warnStabs()
312 const char* Options::executablePath()
314 return fExecutablePath
;
317 uint32_t Options::initialSegProtection(const char* segName
) const
319 for(std::vector
<Options::SegmentProtect
>::const_iterator it
= fCustomSegmentProtections
.begin(); it
!= fCustomSegmentProtections
.end(); ++it
) {
320 if ( strcmp(it
->name
, segName
) == 0 ) {
324 if ( strcmp(segName
, "__TEXT") == 0 ) {
325 return ( fUseTextExecSegment
? VM_PROT_READ
: (VM_PROT_READ
| VM_PROT_EXECUTE
) );
327 else if ( strcmp(segName
, "__TEXT_EXEC") == 0 ) {
328 return VM_PROT_READ
| VM_PROT_EXECUTE
;
330 else if ( strcmp(segName
, "__PAGEZERO") == 0 ) {
333 else if ( strcmp(segName
, "__LINKEDIT") == 0 ) {
337 // all others default to read-write
338 return VM_PROT_READ
| VM_PROT_WRITE
;
341 uint32_t Options::maxSegProtection(const char* segName
) const
343 // iPhoneOS always uses same protection for max and initial
344 // <rdar://problem/11663436> simulator apps need to use MacOSX max-prot
345 if ( (fPlatform
!= kPlatformOSX
) && !fTargetIOSSimulator
)
346 return initialSegProtection(segName
);
348 for(std::vector
<Options::SegmentProtect
>::const_iterator it
= fCustomSegmentProtections
.begin(); it
!= fCustomSegmentProtections
.end(); ++it
) {
349 if ( strcmp(it
->name
, segName
) == 0 ) {
353 if ( strcmp(segName
, "__PAGEZERO") == 0 ) {
356 // all others default to all
357 return VM_PROT_READ
| VM_PROT_WRITE
| VM_PROT_EXECUTE
;
360 uint64_t Options::segPageSize(const char* segName
) const
362 for(std::vector
<SegmentSize
>::const_iterator it
=fCustomSegmentSizes
.begin(); it
!= fCustomSegmentSizes
.end(); ++it
) {
363 if ( strcmp(it
->name
, segName
) == 0 )
366 return fSegmentAlignment
;
369 uint64_t Options::customSegmentAddress(const char* segName
) const
371 for(std::vector
<SegmentStart
>::const_iterator it
=fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
372 if ( strcmp(it
->name
, segName
) == 0 )
375 // if custom stack in use, model as segment with custom address
376 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
377 return fStackAddr
- fStackSize
;
381 bool Options::hasCustomSegmentAddress(const char* segName
) const
383 for(std::vector
<SegmentStart
>::const_iterator it
=fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
384 if ( strcmp(it
->name
, segName
) == 0 )
387 // if custom stack in use, model as segment with custom address
388 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
393 bool Options::hasCustomSectionAlignment(const char* segName
, const char* sectName
) const
395 for (std::vector
<SectionAlignment
>::const_iterator it
= fSectionAlignments
.begin(); it
!= fSectionAlignments
.end(); ++it
) {
396 if ( (strcmp(it
->segmentName
, segName
) == 0) && (strcmp(it
->sectionName
, sectName
) == 0) )
399 if ( fEncryptable
&& (strcmp(sectName
, "__oslogstring") == 0) && (strcmp(segName
, "__TEXT") == 0) )
405 uint8_t Options::customSectionAlignment(const char* segName
, const char* sectName
) const
407 for (std::vector
<SectionAlignment
>::const_iterator it
= fSectionAlignments
.begin(); it
!= fSectionAlignments
.end(); ++it
) {
408 if ( (strcmp(it
->segmentName
, segName
) == 0) && (strcmp(it
->sectionName
, sectName
) == 0) )
409 return it
->alignment
;
411 if ( fEncryptable
&& (strcmp(sectName
, "__oslogstring") == 0) && (strcmp(segName
, "__TEXT") == 0) )
412 return __builtin_ctz(fSegmentAlignment
);
417 bool Options::segmentOrderAfterFixedAddressSegment(const char* segName
) const
419 bool nowPinned
= false;
420 for (std::vector
<const char*>::const_iterator it
=fSegmentOrder
.begin(); it
!= fSegmentOrder
.end(); ++it
) {
421 if ( strcmp(*it
, segName
) == 0 )
423 if ( hasCustomSegmentAddress(*it
) )
429 bool Options::hasExportedSymbolOrder()
431 return (fExportSymbolsOrder
.size() > 0);
434 bool Options::exportedSymbolOrder(const char* sym
, unsigned int* order
) const
436 NameToOrder::const_iterator pos
= fExportSymbolsOrder
.find(sym
);
437 if ( pos
!= fExportSymbolsOrder
.end() ) {
438 *order
= pos
->second
;
447 void Options::loadSymbolOrderFile(const char* fileOfExports
, NameToOrder
& orderMapping
)
449 // read in whole file
450 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
452 throwf("can't open -exported_symbols_order file: %s", fileOfExports
);
453 struct stat stat_buf
;
454 ::fstat(fd
, &stat_buf
);
455 char* p
= (char*)malloc(stat_buf
.st_size
);
457 throwf("can't process -exported_symbols_order file: %s", fileOfExports
);
459 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
460 throwf("can't read -exported_symbols_order file: %s", fileOfExports
);
464 // parse into symbols and add to unordered_set
465 unsigned int count
= 0;
466 char * const end
= &p
[stat_buf
.st_size
];
467 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
468 char* symbolStart
= NULL
;
469 for (char* s
= p
; s
< end
; ++s
) {
475 else if ( !isspace(*s
) ) {
481 if ( (*s
== '\n') || (*s
== '\r') ) {
483 // removing any trailing spaces
485 while ( isspace(*last
) ) {
489 orderMapping
[symbolStart
] = ++count
;
495 if ( (*s
== '\n') || (*s
== '\r') )
500 if ( state
== inSymbol
) {
501 warning("missing line-end at end of file \"%s\"", fileOfExports
);
502 int len
= end
-symbolStart
+1;
503 char* temp
= new char[len
];
504 strlcpy(temp
, symbolStart
, len
);
506 // remove any trailing spaces
507 char* last
= &temp
[len
-2];
508 while ( isspace(*last
) ) {
512 orderMapping
[temp
] = ++count
;
515 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
518 bool Options::forceWeak(const char* symbolName
) const
520 return fForceWeakSymbols
.contains(symbolName
);
523 bool Options::forceNotWeak(const char* symbolName
) const
525 return fForceNotWeakSymbols
.contains(symbolName
);
528 bool Options::forceWeakNonWildCard(const char* symbolName
) const
530 return fForceWeakSymbols
.containsNonWildcard(symbolName
);
533 bool Options::forceNotWeakNonWildcard(const char* symbolName
) const
535 return fForceNotWeakSymbols
.containsNonWildcard(symbolName
);
538 bool Options::forceCoalesce(const char* symbolName
) const
540 return fForceCoalesceSymbols
.contains(symbolName
);
544 bool Options::shouldExport(const char* symbolName
) const
546 switch (fExportMode
) {
548 return fExportSymbols
.contains(symbolName
);
549 case kDontExportSome
:
550 return ! fDontExportSymbols
.contains(symbolName
);
554 throw "internal error";
557 bool Options::shouldReExport(const char* symbolName
) const
559 return fReExportSymbols
.contains(symbolName
);
562 bool Options::keepLocalSymbol(const char* symbolName
) const
564 switch (fLocalSymbolHandling
) {
565 case kLocalSymbolsAll
:
567 case kLocalSymbolsNone
:
569 case kLocalSymbolsSelectiveInclude
:
570 return fLocalSymbolsIncluded
.contains(symbolName
);
571 case kLocalSymbolsSelectiveExclude
:
572 return ! fLocalSymbolsExcluded
.contains(symbolName
);
574 throw "internal error";
577 const std::vector
<const char*>* Options::sectionOrder(const char* segName
) const
579 for (std::vector
<SectionOrderList
>::const_iterator it
=fSectionOrder
.begin(); it
!= fSectionOrder
.end(); ++it
) {
580 if ( strcmp(it
->segmentName
, segName
) == 0 )
581 return &it
->sectionOrder
;
586 uint32_t Options::minOSversion() const
590 return iOSVersionMin();
592 return macosxVersionMin();
593 case kPlatformWatchOS
:
594 return watchOSVersionMin();
596 case Options::kPlatform_tvOS
:
597 return iOSVersionMin();
605 void Options::setArchitecture(cpu_type_t type
, cpu_subtype_t subtype
, Options::Platform platform
)
607 for (const ArchInfo
* t
=archInfoArray
; t
->archName
!= NULL
; ++t
) {
608 if ( (type
== t
->cpuType
) && (subtype
== t
->cpuSubType
) ) {
609 fArchitecture
= type
;
610 fSubArchitecture
= subtype
;
611 fArchitectureName
= t
->archName
;
612 fHasPreferredSubType
= t
->isSubType
;
613 fArchSupportsThumb2
= t
->supportsThumb2
;
614 fPlatform
= platform
;
617 case CPU_TYPE_X86_64
:
618 if ( (fPlatform
== kPlatformOSX
) && (fOutputKind
!= Options::kObjectFile
) && (fMacVersionMin
== ld::macVersionUnset
) ) {
619 #ifdef DEFAULT_MACOSX_MIN_VERSION
620 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION
);
621 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
623 warning("-macosx_version_min not specified, assuming 10.6");
624 fMacVersionMin
= ld::mac10_6
;
630 if ( (fMacVersionMin
== ld::macVersionUnset
) && (fIOSVersionMin
== ld::iOSVersionUnset
) && (fOutputKind
!= Options::kObjectFile
) ) {
631 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
632 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION
);
633 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION
);
635 warning("-ios_version_min not specified, assuming 6.0");
636 setIOSVersionMin("6.0");
641 fLinkSnapshot
.recordArch(fArchitectureName
);
642 // only use compressed LINKEDIT for:
643 // Mac OS X 10.6 or later
645 if ( !fMakeCompressedDyldInfo
&& minOS(ld::mac10_6
, ld::iOS_3_1
) && !fMakeCompressedDyldInfoForceOff
)
646 fMakeCompressedDyldInfo
= true;
647 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
648 if ( minOS(ld::mac10_5
, ld::iOS_2_0
) )
649 fUseSimplifiedDylibReExports
= true;
653 fArchitectureName
= "unknown architecture";
656 bool Options::armUsesZeroCostExceptions() const
658 return ( (fArchitecture
== CPU_TYPE_ARM
) && (fSubArchitecture
== CPU_SUBTYPE_ARM_V7K
) );
661 void Options::parseArch(const char* arch
)
664 throw "-arch must be followed by an architecture string";
665 for (const ArchInfo
* t
=archInfoArray
; t
->archName
!= NULL
; ++t
) {
666 if ( strcmp(t
->archName
,arch
) == 0 ) {
667 fArchitectureName
= arch
;
668 fArchitecture
= t
->cpuType
;
669 fSubArchitecture
= t
->cpuSubType
;
670 fHasPreferredSubType
= t
->isSubType
;
671 fArchSupportsThumb2
= t
->supportsThumb2
;
675 throwf("unknown/unsupported architecture name for: -arch %s", arch
);
678 bool Options::checkForFile(const char* format
, const char* dir
, const char* rootName
, FileInfo
& result
) const
680 char possiblePath
[strlen(dir
)+strlen(rootName
)+strlen(format
)+8];
681 sprintf(possiblePath
, format
, dir
, rootName
);
682 bool found
= result
.checkFileExists(*this, possiblePath
);
683 if ( fTraceDylibSearching
)
684 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), possiblePath
);
689 Options::FileInfo
Options::findLibrary(const char* rootName
, bool dylibsOnly
) const
692 const int rootNameLen
= strlen(rootName
);
693 // if rootName ends in .o there is no .a vs .dylib choice
694 if ( (rootNameLen
> 3) && (strcmp(&rootName
[rootNameLen
-2], ".o") == 0) ) {
695 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
696 it
!= fLibrarySearchPaths
.end();
698 const char* dir
= *it
;
699 if ( checkForFile("%s/%s", dir
, rootName
, result
) )
704 bool lookForDylibs
= false;
705 switch ( fOutputKind
) {
706 case Options::kDynamicExecutable
:
707 case Options::kDynamicLibrary
:
708 case Options::kDynamicBundle
:
709 case Options::kObjectFile
: // <rdar://problem/15914513>
710 lookForDylibs
= true;
712 case Options::kStaticExecutable
:
714 case Options::kPreload
:
715 case Options::kKextBundle
:
716 lookForDylibs
= false;
719 switch ( fLibrarySearchMode
) {
720 case kSearchAllDirsForDylibsThenAllDirsForArchives
:
721 // first look in all directories for just for dylibs
722 if ( lookForDylibs
) {
723 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
724 it
!= fLibrarySearchPaths
.end();
726 const char* dir
= *it
;
727 auto path
= std::string(dir
) + "/lib" + rootName
+ ".dylib";
728 if ( findFile(path
, {".tbd"}, result
) )
731 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
732 it
!= fLibrarySearchPaths
.end();
734 const char* dir
= *it
;
735 if ( checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
739 // next look in all directories for just for archives
741 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
742 it
!= fLibrarySearchPaths
.end();
744 const char* dir
= *it
;
745 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
751 case kSearchDylibAndArchiveInEachDir
:
752 // look in each directory for just for a dylib then for an archive
753 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
754 it
!= fLibrarySearchPaths
.end();
756 const char* dir
= *it
;
757 auto path
= std::string(dir
) + "/lib" + rootName
+ ".dylib";
758 if ( lookForDylibs
&& findFile(path
, {".tbd"}, result
) )
760 if ( lookForDylibs
&& checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
762 if ( !dylibsOnly
&& checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
768 throwf("library not found for -l%s", rootName
);
771 Options::FileInfo
Options::findFramework(const char* frameworkName
) const
773 if ( frameworkName
== NULL
)
774 throw "-framework missing next argument";
775 char temp
[strlen(frameworkName
)+1];
776 strcpy(temp
, frameworkName
);
777 const char* name
= temp
;
778 const char* suffix
= NULL
;
779 char* comma
= strchr(temp
, ',');
780 if ( comma
!= NULL
) {
784 return findFramework(name
, suffix
);
787 Options::FileInfo
Options::findFramework(const char* rootName
, const char* suffix
) const
789 for (const auto* path
: fFrameworkSearchPaths
) {
790 auto possiblePath
= std::string(path
).append("/").append(rootName
).append(".framework/").append(rootName
);
791 if ( suffix
!= nullptr ) {
792 char realPath
[PATH_MAX
];
793 // no symlink in framework to suffix variants, so follow main symlink
794 if ( realpath(possiblePath
.c_str(), realPath
) != nullptr )
795 possiblePath
= std::string(realPath
).append(suffix
);
798 if ( findFile(possiblePath
, {".tbd"}, result
) )
801 // try without suffix
802 if ( suffix
!= NULL
)
803 return findFramework(rootName
, NULL
);
805 throwf("framework not found %s", rootName
);
808 static std::string
replace_extension(const std::string
&path
, const std::string
&ext
)
811 auto lastSlashIdx
= result
.find_last_of('/');
812 auto lastDotIdx
= result
.find_last_of('.');
813 if (lastDotIdx
!= std::string::npos
&& lastDotIdx
> lastSlashIdx
)
814 result
.erase(lastDotIdx
, std::string::npos
);
815 if ( ext
.size() > 0 && ext
[0] == '.' )
818 result
.append('.' + ext
);
822 bool Options::findFile(const std::string
&path
, const std::vector
<std::string
> &tbdExtensions
, FileInfo
& result
) const
825 for ( const auto &ext
: tbdExtensions
) {
826 auto newPath
= replace_extension(path
, ext
);
827 bool found
= tbdInfo
.checkFileExists(*this, newPath
.c_str());
828 if ( fTraceDylibSearching
)
829 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), newPath
.c_str());
834 // If we found a text-based stub file, check if it should be used.
835 if ( !tbdInfo
.missing() ) {
836 if (tapi::LinkerInterfaceFile::shouldPreferTextBasedStubFile(tbdInfo
.path
)) {
843 bool found
= dylibInfo
.checkFileExists(*this, path
.c_str());
844 if ( fTraceDylibSearching
)
845 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), path
.c_str());
848 // There is only a text-based stub file.
849 if ( !tbdInfo
.missing() && dylibInfo
.missing() ) {
853 // There is only a dynamic library file.
854 else if ( tbdInfo
.missing() && !dylibInfo
.missing() ) {
858 // There are both - a text-based stub file and a dynamic library file.
859 else if ( !tbdInfo
.missing() && !dylibInfo
.missing() ) {
860 // If the files are still in synv we can use and should use the text-based stub file.
861 if (tapi::LinkerInterfaceFile::areEquivalent(tbdInfo
.path
, dylibInfo
.path
)) {
864 // Otherwise issue a warning and fall-back to the dynamic library file.
866 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
);
876 static bool startsWith(const std::string
& str
, const std::string
& prefix
)
878 return (str
.compare(0, prefix
.length(), prefix
) == 0);
881 static std::string
getDirPath(const std::string
& path
)
883 std::string::size_type lastSlashPos
= path
.find_last_of('/');
884 if ( lastSlashPos
== std::string::npos
)
887 return path
.substr(0, lastSlashPos
+1);
890 Options::FileInfo
Options::findFile(const std::string
&path
, const ld::dylib::File
* fromDylib
) const
894 // if absolute path and not a .o file, then use SDK prefix
895 if ( (path
[0] == '/') && (strcmp(&path
[path
.size()-2], ".o") != 0) ) {
896 for (const auto* sdkPathDir
: fSDKPaths
) {
897 auto possiblePath
= std::string(sdkPathDir
) + path
;
898 if ( findFile(possiblePath
, {".tbd"}, result
) )
903 // expand @ variables
904 if ( path
[0] == '@' ) {
905 if ( startsWith(path
, "@executable_path/") && (fExecutablePath
!= nullptr) ) {
906 std::string exeBasedPath
= getDirPath(fExecutablePath
) + &path
[17];
907 if ( findFile(exeBasedPath
, {".tbd"}, result
) )
910 else if ( startsWith(path
, "@loader_path/") && (fromDylib
!= nullptr) ) {
911 char absPath
[PATH_MAX
];
912 if ( realpath(fromDylib
->path(), absPath
) != NULL
) {
913 std::string loaderBasedPath
= getDirPath(fromDylib
->path()) + &path
[13];
914 if ( findFile(loaderBasedPath
, {".tbd"}, result
) )
918 else if ( startsWith(path
, "@rpath/") ) {
919 // first search any LC_RPATH supplied by dyld that re-exports dylib to be found
920 if ( fromDylib
!= nullptr ) {
921 for (const char* rp
: fromDylib
->rpaths() ) {
922 std::string rpath
= rp
;
923 // handle dylib that has LC_RPATH = @loader_path/blah
924 if ( startsWith(rpath
, "@loader_path/") ) {
925 char absPath
[PATH_MAX
];
926 if ( realpath(fromDylib
->path(), absPath
) != NULL
)
927 rpath
= getDirPath(absPath
) + &rpath
[13];
929 rpath
= getDirPath(fromDylib
->path()) + &rpath
[13];
931 std::string rpathBasedPath
= rpath
+ "/" + &path
[6];
932 if ( findFile(rpathBasedPath
, {".tbd"}, result
) )
940 if ( findFile(path
, {".tbd"}, result
) )
944 throwf("file not found: %s", path
.c_str());
947 // search for indirect dylib first using -F and -L paths first
948 Options::FileInfo
Options::findIndirectDylib(const std::string
& installName
, const ld::dylib::File
* fromDylib
) const
952 auto lastSlashPos
= installName
.find_last_of('/');
953 auto pos
= ( lastSlashPos
!= std::string::npos
) ? lastSlashPos
+ 1 : 0;
954 auto leafName
= installName
.substr(pos
);
956 // Is this in a framework?
957 // /path/Foo.framework/Foo ==> true (Foo)
958 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
959 // /path/Foo.framework/Resources/Bar ==> false
960 bool isFramework
= false;
961 if ( lastSlashPos
!= std::string::npos
) {
962 auto frameworkDir
= std::string("/").append(leafName
).append(".framework/");
963 if ( installName
.rfind(frameworkDir
) != std::string::npos
)
967 // These are abbreviated versions of the routines findFramework and findLibrary above
968 // because we already know the final name of the file that we're looking for and so
969 // don't need to try variations, just paths. We do need to add the additional bits
970 // onto the framework path though.
972 auto endPos
= installName
.rfind(".framework");
973 auto beginPos
= installName
.find_last_of('/', endPos
);
974 auto leafPath
= installName
.substr(beginPos
);
975 for (const auto* dir
: fFrameworkSearchPaths
) {
976 auto possiblePath
= dir
+ leafPath
;
977 if ( findFile(possiblePath
, {".tbd"}, result
) )
981 // if this is a .dylib inside a framework, do not search -L paths
982 // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
983 bool embeddedDylib
= ( (leafName
.size() > 6)
984 && (leafName
.find(".dylib", leafName
.size()-6) != std::string::npos
)
985 && (installName
.find(".framework/") != std::string::npos
) );
986 if ( !embeddedDylib
) {
987 for (const auto* dir
: fLibrarySearchPaths
) {
988 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
989 std::string possiblePath
= dir
+ std::string("/") + leafName
;
990 if ( findFile(possiblePath
, {".tbd"}, result
) )
996 // If we didn't find it fall back to findFile.
997 return findFile(installName
, fromDylib
);
1002 void Options::parseSegAddrTable(const char* segAddrPath
, const char* installPth
)
1004 FILE* file
= fopen(segAddrPath
, "r");
1005 if ( file
== NULL
) {
1006 warning("-seg_addr_table file cannot be read: %s", segAddrPath
);
1010 char path
[PATH_MAX
];
1011 uint64_t firstColumAddress
= 0;
1012 uint64_t secondColumAddress
= 0;
1013 bool hasSecondColumn
= false;
1014 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
1015 path
[PATH_MAX
-1] = '\0';
1016 char* eol
= strchr(path
, '\n');
1019 // ignore lines not starting with 0x number
1020 if ( (path
[0] == '0') && (path
[1] == 'x') ) {
1022 firstColumAddress
= strtoull(path
, &p
, 16);
1023 while ( isspace(*p
) )
1025 // see if second column is a number
1026 if ( (p
[0] == '0') && (p
[1] == 'x') ) {
1027 secondColumAddress
= strtoull(p
, &p
, 16);
1028 hasSecondColumn
= true;
1029 while ( isspace(*p
) )
1032 while ( isspace(*p
) )
1034 if ( p
[0] == '/' ) {
1035 // remove any trailing whitespace
1036 for(char* end
= eol
-1; (end
> p
) && isspace(*end
); --end
)
1038 // see if this line is for the dylib being linked
1039 if ( strcmp(p
, installPth
) == 0 ) {
1040 fBaseAddress
= firstColumAddress
;
1041 if ( hasSecondColumn
) {
1042 fBaseWritableAddress
= secondColumAddress
;
1045 break; // out of while loop
1054 void Options::loadFileList(const char* fileOfPaths
, ld::File::Ordinal baseOrdinal
)
1057 const char* comma
= strrchr(fileOfPaths
, ',');
1058 const char* prefix
= NULL
;
1059 if ( comma
!= NULL
) {
1060 // <rdar://problem/5907981> -filelist fails with comma in path
1061 file
= fopen(fileOfPaths
, "r");
1062 if ( file
== NULL
) {
1064 int realFileOfPathsLen
= comma
-fileOfPaths
;
1065 char realFileOfPaths
[realFileOfPathsLen
+1];
1066 strncpy(realFileOfPaths
,fileOfPaths
, realFileOfPathsLen
);
1067 realFileOfPaths
[realFileOfPathsLen
] = '\0';
1068 file
= fopen(realFileOfPaths
, "r");
1070 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", realFileOfPaths
, errno
, strerror(errno
));
1071 if ( this->dumpDependencyInfo() )
1072 this->dumpDependency(Options::depFileList
, realFileOfPaths
);
1076 file
= fopen(fileOfPaths
, "r");
1078 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", fileOfPaths
, errno
, strerror(errno
));
1079 if ( this->dumpDependencyInfo() )
1080 this->dumpDependency(Options::depFileList
, fileOfPaths
);
1083 char path
[PATH_MAX
];
1084 ld::File::Ordinal previousOrdinal
= baseOrdinal
;
1085 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
1086 path
[PATH_MAX
-1] = '\0';
1087 char* eol
= strchr(path
, '\n');
1090 if ( prefix
!= NULL
) {
1091 char builtPath
[strlen(prefix
)+strlen(path
)+2];
1092 strcpy(builtPath
, prefix
);
1093 strcat(builtPath
, "/");
1094 strcat(builtPath
, path
);
1095 if (fPipelineFifo
!= NULL
) {
1096 FileInfo info
= FileInfo(builtPath
);
1097 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1098 previousOrdinal
= info
.ordinal
;
1099 info
.fromFileList
= true;
1100 fInputFiles
.push_back(info
);
1102 FileInfo info
= findFile(builtPath
);
1103 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1104 previousOrdinal
= info
.ordinal
;
1105 info
.fromFileList
= true;
1106 fInputFiles
.push_back(info
);
1110 if (fPipelineFifo
!= NULL
) {
1111 FileInfo info
= FileInfo(path
);
1112 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1113 previousOrdinal
= info
.ordinal
;
1114 info
.fromFileList
= true;
1115 fInputFiles
.push_back(info
);
1117 FileInfo info
= findFile(path
);
1118 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
1119 previousOrdinal
= info
.ordinal
;
1120 info
.fromFileList
= true;
1121 fInputFiles
.push_back(info
);
1129 void Options::SetWithWildcards::remove(const NameSet
& toBeRemoved
)
1131 for(NameSet::const_iterator it
=toBeRemoved
.begin(); it
!= toBeRemoved
.end(); ++it
) {
1132 const char* symbolName
= *it
;
1133 NameSet::iterator pos
= fRegular
.find(symbolName
);
1134 if ( pos
!= fRegular
.end() )
1135 fRegular
.erase(pos
);
1139 bool Options::SetWithWildcards::hasWildCards(const char* symbol
)
1141 // an exported symbol name containing *, ?, or [ requires wildcard matching
1142 return ( strpbrk(symbol
, "*?[") != NULL
);
1145 void Options::SetWithWildcards::insert(const char* symbol
)
1147 if ( hasWildCards(symbol
) )
1148 fWildCard
.push_back(symbol
);
1150 fRegular
.insert(symbol
);
1153 bool Options::SetWithWildcards::contains(const char* symbol
, bool* matchBecauseOfWildcard
) const
1155 if ( matchBecauseOfWildcard
!= NULL
)
1156 *matchBecauseOfWildcard
= false;
1157 // first look at hash table on non-wildcard symbols
1158 if ( fRegular
.find(symbol
) != fRegular
.end() )
1160 // next walk list of wild card symbols looking for a match
1161 for(std::vector
<const char*>::const_iterator it
= fWildCard
.begin(); it
!= fWildCard
.end(); ++it
) {
1162 if ( wildCardMatch(*it
, symbol
) ) {
1163 if ( matchBecauseOfWildcard
!= NULL
)
1164 *matchBecauseOfWildcard
= true;
1171 // Support "foo.o:_bar" to mean symbol _bar in file foo.o
1172 bool Options::SetWithWildcards::containsWithPrefix(const char* symbol
, const char* file
, bool& wildCardMatch
) const
1174 wildCardMatch
= false;
1175 if ( contains(symbol
, &wildCardMatch
) )
1179 const char* s
= strrchr(file
, '/');
1182 char buff
[strlen(file
)+strlen(symbol
)+2];
1183 sprintf(buff
, "%s:%s", file
, symbol
);
1184 return contains(buff
, &wildCardMatch
);
1187 bool Options::SetWithWildcards::containsNonWildcard(const char* symbol
) const
1189 // look at hash table on non-wildcard symbols
1190 return ( fRegular
.find(symbol
) != fRegular
.end() );
1194 std::vector
<const char*> Options::exportsData() const
1196 return fExportSymbols
.data();
1200 std::vector
<const char*> Options::SetWithWildcards::data() const
1202 std::vector
<const char*> data
;
1203 for (NameSet::iterator it
=regularBegin(); it
!= regularEnd(); ++it
) {
1204 data
.push_back(*it
);
1206 for (std::vector
<const char*>::const_iterator it
=fWildCard
.begin(); it
!= fWildCard
.end(); ++it
) {
1207 data
.push_back(*it
);
1212 bool Options::SetWithWildcards::inCharRange(const char*& p
, unsigned char c
) const
1216 while ( *p
!= '\0' ) {
1219 // found beginining [ and ending ]
1220 unsigned char last
= '\0';
1221 for ( const char* s
= b
; s
< e
; ++s
) {
1223 unsigned char next
= *(++s
);
1224 if ( (last
<= c
) && (c
<= next
) )
1241 bool Options::SetWithWildcards::wildCardMatch(const char* pattern
, const char* symbol
) const
1243 const char* s
= symbol
;
1244 for (const char* p
= pattern
; *p
!= '\0'; ++p
) {
1249 for (const char* t
= s
; *t
!= '\0'; ++t
) {
1250 if ( wildCardMatch(&p
[1], t
) )
1260 if ( ! inCharRange(p
, *s
) )
1270 return (*s
== '\0');
1274 void Options::loadExportFile(const char* fileOfExports
, const char* option
, SetWithWildcards
& set
)
1276 if ( fileOfExports
== NULL
)
1277 throwf("missing file after %s", option
);
1278 // read in whole file
1279 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
1281 throwf("can't open %s file: %s", option
, fileOfExports
);
1282 struct stat stat_buf
;
1283 ::fstat(fd
, &stat_buf
);
1284 char* p
= (char*)malloc(stat_buf
.st_size
);
1286 throwf("can't process %s file: %s", option
, fileOfExports
);
1288 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1289 throwf("can't read %s file: %s", option
, fileOfExports
);
1291 if ( this->dumpDependencyInfo() )
1292 this->dumpDependency(Options::depMisc
, fileOfExports
);
1296 // parse into symbols and add to unordered_set
1297 char * const end
= &p
[stat_buf
.st_size
];
1298 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1299 char* symbolStart
= NULL
;
1300 for (char* s
= p
; s
< end
; ++s
) {
1306 else if ( !isspace(*s
) ) {
1312 if ( (*s
== '\n') || (*s
== '\r') ) {
1314 // removing any trailing spaces
1316 while ( isspace(*last
) ) {
1320 set
.insert(symbolStart
);
1326 if ( (*s
== '\n') || (*s
== '\r') )
1331 if ( state
== inSymbol
) {
1332 warning("missing line-end at end of file \"%s\"", fileOfExports
);
1333 int len
= end
-symbolStart
+1;
1334 char* temp
= new char[len
];
1335 strlcpy(temp
, symbolStart
, len
);
1337 // remove any trailing spaces
1338 char* last
= &temp
[len
-2];
1339 while ( isspace(*last
) ) {
1346 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
1349 void Options::parseAliasFile(const char* fileOfAliases
)
1351 // read in whole file
1352 int fd
= ::open(fileOfAliases
, O_RDONLY
, 0);
1354 throwf("can't open alias file: %s", fileOfAliases
);
1355 struct stat stat_buf
;
1356 ::fstat(fd
, &stat_buf
);
1357 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1359 throwf("can't process alias file: %s", fileOfAliases
);
1361 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1362 throwf("can't read alias file: %s", fileOfAliases
);
1363 p
[stat_buf
.st_size
] = '\n';
1365 if ( this->dumpDependencyInfo() )
1366 this->dumpDependency(Options::depMisc
, fileOfAliases
);
1368 // parse into symbols and add to fAliases
1370 char * const end
= &p
[stat_buf
.st_size
+1];
1371 enum { lineStart
, inRealName
, inBetween
, inAliasName
, inComment
} state
= lineStart
;
1373 for (char* s
= p
; s
< end
; ++s
) {
1379 else if ( !isspace(*s
) ) {
1386 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1390 else if ( isspace(*s
) ) {
1397 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1401 else if ( ! isspace(*s
) ) {
1402 state
= inAliasName
;
1409 // removing any trailing spaces
1411 while ( isspace(*last
) ) {
1415 fAliases
.push_back(pair
);
1418 else if ( *s
== '\n' ) {
1420 // removing any trailing spaces
1422 while ( isspace(*last
) ) {
1426 fAliases
.push_back(pair
);
1437 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
1442 void Options::setUndefinedTreatment(const char* treatment
)
1444 if ( treatment
== NULL
)
1445 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
1447 if ( strcmp(treatment
, "warning") == 0 )
1448 fUndefinedTreatment
= kUndefinedWarning
;
1449 else if ( strcmp(treatment
, "error") == 0 )
1450 fUndefinedTreatment
= kUndefinedError
;
1451 else if ( strcmp(treatment
, "suppress") == 0 )
1452 fUndefinedTreatment
= kUndefinedSuppress
;
1453 else if ( strcmp(treatment
, "dynamic_lookup") == 0 )
1454 fUndefinedTreatment
= kUndefinedDynamicLookup
;
1456 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1459 Options::Treatment
Options::parseTreatment(const char* treatment
)
1461 if ( treatment
== NULL
)
1464 if ( strcmp(treatment
, "warning") == 0 )
1466 else if ( strcmp(treatment
, "error") == 0 )
1468 else if ( strcmp(treatment
, "suppress") == 0 )
1474 void Options::setMacOSXVersionMin(const char* version
)
1477 if ( !parsePackedVersion32(version
, value
) ) {
1478 throwf("-macosx_version_min value malformed: '%s'", version
);
1480 fMacVersionMin
= (ld::MacVersionMin
)value
;
1481 fPlatform
= kPlatformOSX
;
1484 void Options::setIOSVersionMin(const char* version
)
1487 if ( !parsePackedVersion32(version
, value
) ) {
1488 throwf("-ios_version_min value malformed: '%s'", version
);
1490 fIOSVersionMin
= (ld::IOSVersionMin
)value
;
1491 fPlatform
= kPlatformiOS
;
1495 void Options::setWatchOSVersionMin(const char* version
)
1498 if ( !parsePackedVersion32(version
, value
) ) {
1499 throwf("-watchos_version_min value malformed: '%s'", version
);
1501 fWatchOSVersionMin
= (ld::WatchOSVersionMin
)value
;
1502 fPlatform
= kPlatformWatchOS
;
1506 bool Options::minOS(ld::MacVersionMin requiredMacMin
, ld::IOSVersionMin requirediPhoneOSMin
)
1508 if ( fMacVersionMin
!= ld::macVersionUnset
) {
1509 return ( fMacVersionMin
>= requiredMacMin
);
1511 else if ( fWatchOSVersionMin
!= ld::wOSVersionUnset
) {
1512 // Hack until we fully track watch and ios versions seperately
1513 return ( (fWatchOSVersionMin
+ 0x00070000) >= requirediPhoneOSMin
);
1516 return ( fIOSVersionMin
>= requirediPhoneOSMin
);
1520 bool Options::min_iOS(ld::IOSVersionMin requirediOSMin
)
1522 if ( fWatchOSVersionMin
!= ld::wOSVersionUnset
) {
1523 // Hack until we fully track watch and ios versions seperately
1524 return ( (fWatchOSVersionMin
+ 0x00070000) >= requirediOSMin
);
1527 return ( fIOSVersionMin
>= requirediOSMin
);
1531 void Options::setWeakReferenceMismatchTreatment(const char* treatment
)
1533 if ( treatment
== NULL
)
1534 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1536 if ( strcmp(treatment
, "error") == 0 )
1537 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchError
;
1538 else if ( strcmp(treatment
, "weak") == 0 )
1539 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchWeak
;
1540 else if ( strcmp(treatment
, "non-weak") == 0 )
1541 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchNonWeak
;
1543 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1546 Options::CommonsMode
Options::parseCommonsTreatment(const char* mode
)
1549 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1551 if ( strcmp(mode
, "ignore_dylibs") == 0 )
1552 return kCommonsIgnoreDylibs
;
1553 else if ( strcmp(mode
, "use_dylibs") == 0 )
1554 return kCommonsOverriddenByDylibs
;
1555 else if ( strcmp(mode
, "error") == 0 )
1556 return kCommonsConflictsDylibsError
;
1558 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1561 void Options::addDylibOverride(const char* paths
)
1563 if ( paths
== NULL
)
1564 throw "-dylib_file must followed by two colon separated paths";
1565 const char* colon
= strchr(paths
, ':');
1566 if ( colon
== NULL
)
1567 throw "-dylib_file must followed by two colon separated paths";
1568 int len
= colon
-paths
;
1569 char* target
= new char[len
+2];
1570 strncpy(target
, paths
, len
);
1572 DylibOverride entry
;
1573 entry
.installName
= target
;
1574 entry
.useInstead
= &colon
[1];
1575 fDylibOverrides
.push_back(entry
);
1578 uint64_t Options::parseAddress(const char* addr
)
1581 uint64_t result
= strtoull(addr
, &endptr
, 16);
1585 uint32_t Options::parseProtection(const char* prot
)
1587 uint32_t result
= 0;
1588 for(const char* p
= prot
; *p
!= '\0'; ++p
) {
1589 switch(tolower(*p
)) {
1591 result
|= VM_PROT_READ
;
1594 result
|= VM_PROT_WRITE
;
1597 result
|= VM_PROT_EXECUTE
;
1602 throwf("unknown -segprot lettter in %s", prot
);
1610 // Parses number of form A[.B[.B[.D[.E]]]] into a uint64_t where the bits are a24.b10.c10.d10.e10
1612 uint64_t Options::parseVersionNumber64(const char* versionString
)
1620 a
= strtoul(versionString
, &end
, 10);
1621 if ( *end
== '.' ) {
1622 b
= strtoul(&end
[1], &end
, 10);
1623 if ( *end
== '.' ) {
1624 c
= strtoul(&end
[1], &end
, 10);
1625 if ( *end
== '.' ) {
1626 d
= strtoul(&end
[1], &end
, 10);
1627 if ( *end
== '.' ) {
1628 e
= strtoul(&end
[1], &end
, 10);
1633 if ( (*end
!= '\0') || (a
> 0xFFFFFF) || (b
> 0x3FF) || (c
> 0x3FF) || (d
> 0x3FF) || (e
> 0x3FF) )
1634 throwf("malformed 64-bit a.b.c.d.e version number: %s", versionString
);
1636 return (a
<< 40) | ( b
<< 30 ) | ( c
<< 20 ) | ( d
<< 10 ) | e
;
1640 uint32_t Options::currentVersion32() const
1642 // warn if it does not fit into 32 bit vers number
1643 uint32_t a
= (fDylibCurrentVersion
>> 40) & 0xFFFF;
1644 uint32_t b
= (fDylibCurrentVersion
>> 30) & 0xFF;
1645 uint32_t c
= (fDylibCurrentVersion
>> 20) & 0xFF;
1646 uint64_t rep32
= ((uint64_t)a
<< 40) | ((uint64_t)b
<< 30) | ((uint64_t)c
<< 20);
1647 if ( rep32
!= fDylibCurrentVersion
) {
1648 warning("truncating -current_version to fit in 32-bit space used by old mach-o format");
1649 a
= (fDylibCurrentVersion
>> 40) & 0xFFFFFF;
1652 b
= (fDylibCurrentVersion
>> 30) & 0x3FF;
1655 c
= (fDylibCurrentVersion
>> 20) & 0x3FF;
1659 return (a
<< 16) | ( b
<< 8 ) | c
;
1663 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1665 uint32_t Options::parseVersionNumber32(const char* versionString
)
1671 x
= strtoul(versionString
, &end
, 10);
1672 if ( *end
== '.' ) {
1673 y
= strtoul(&end
[1], &end
, 10);
1674 if ( *end
== '.' ) {
1675 z
= strtoul(&end
[1], &end
, 10);
1678 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
1679 throwf("malformed 32-bit x.y.z version number: %s", versionString
);
1681 return (x
<< 16) | ( y
<< 8 ) | z
;
1684 static const char* cstringSymbolName(const char* orderFileString
)
1687 asprintf(&result
, "cstring=%s", orderFileString
);
1688 // convert escaped characters
1690 for(const char* s
=result
; *s
!= '\0'; ++s
, ++d
) {
1728 // hexadecimal value of char
1732 while ( isxdigit(*s
) ) {
1737 value
+= ((toupper(*s
)-'A') + 10);
1744 if ( isdigit(*s
) ) {
1745 // octal value of char
1747 while ( isdigit(*s
) ) {
1748 value
= (value
<< 3) + (*s
-'0');
1763 void Options::parseOrderFile(const char* path
, bool cstring
)
1765 // order files override auto-ordering
1766 fAutoOrderInitializers
= false;
1768 // <rdar://problem/24856050> ld64 should prefer OrderFiles from the SDK over the ones in /
1769 for (const char* sdkPath
: fSDKPaths
) {
1770 char fullPath
[PATH_MAX
];
1771 strlcpy(fullPath
, sdkPath
, PATH_MAX
);
1772 strlcat(fullPath
, "/", PATH_MAX
);
1773 strlcat(fullPath
, path
, PATH_MAX
);
1774 struct stat statBuffer
;
1775 if ( stat(fullPath
, &statBuffer
) == 0 ) {
1776 path
= strdup(fullPath
);
1781 // read in whole file
1782 int fd
= ::open(path
, O_RDONLY
, 0);
1784 throwf("can't open order file: %s", path
);
1785 struct stat stat_buf
;
1786 ::fstat(fd
, &stat_buf
);
1787 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1789 throwf("can't process order file: %s", path
);
1790 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1791 throwf("can't read order file: %s", path
);
1793 p
[stat_buf
.st_size
] = '\n';
1794 if ( this->dumpDependencyInfo() )
1795 this->dumpDependency(Options::depMisc
, path
);
1797 // parse into vector of pairs
1798 char * const end
= &p
[stat_buf
.st_size
+1];
1799 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1800 char* symbolStart
= NULL
;
1801 for (char* s
= p
; s
< end
; ++s
) {
1807 else if ( !isspace(*s
) || cstring
) {
1813 if ( (*s
== '\n') || (!cstring
&& (*s
== '#')) ) {
1814 bool wasComment
= (*s
== '#');
1816 // removing any trailing spaces
1818 while ( isspace(*last
) ) {
1822 // if there is an architecture prefix, only use this symbol it if matches current arch
1823 if ( strncmp(symbolStart
, "ppc:", 4) == 0 ) {
1826 else if ( strncmp(symbolStart
, "ppc64:", 6) == 0 ) {
1829 else if ( strncmp(symbolStart
, "i386:", 5) == 0 ) {
1830 if ( fArchitecture
== CPU_TYPE_I386
)
1831 symbolStart
= &symbolStart
[5];
1835 else if ( strncmp(symbolStart
, "x86_64:", 7) == 0 ) {
1836 if ( fArchitecture
== CPU_TYPE_X86_64
)
1837 symbolStart
= &symbolStart
[7];
1841 else if ( strncmp(symbolStart
, "arm:", 4) == 0 ) {
1842 if ( fArchitecture
== CPU_TYPE_ARM
)
1843 symbolStart
= &symbolStart
[4];
1847 else if ( strncmp(symbolStart
, "arm64:", 6) == 0 ) {
1848 if ( fArchitecture
== CPU_TYPE_ARM64
)
1849 symbolStart
= &symbolStart
[6];
1853 if ( symbolStart
!= NULL
) {
1854 char* objFileName
= NULL
;
1855 char* colon
= strstr(symbolStart
, ".o:");
1856 if ( colon
!= NULL
) {
1858 objFileName
= symbolStart
;
1859 symbolStart
= &colon
[3];
1862 colon
= strstr(symbolStart
, ".o):");
1863 if ( colon
!= NULL
) {
1865 objFileName
= symbolStart
;
1866 symbolStart
= &colon
[4];
1869 // trim leading spaces
1870 while ( isspace(*symbolStart
) )
1872 Options::OrderedSymbol pair
;
1874 pair
.symbolName
= cstringSymbolName(symbolStart
);
1876 pair
.symbolName
= symbolStart
;
1877 pair
.objectFileName
= objFileName
;
1878 fOrderedSymbols
.push_back(pair
);
1893 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1896 void Options::parseSectionOrderFile(const char* segment
, const char* section
, const char* path
)
1898 if ( (strcmp(section
, "__cstring") == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1899 parseOrderFile(path
, true);
1901 else if ( (strncmp(section
, "__literal",9) == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1902 warning("sorting of __literal[4,8,16] sections not supported");
1905 // ignore section information and append all symbol names to global order file
1906 parseOrderFile(path
, false);
1910 void Options::addSection(const char* segment
, const char* section
, const char* path
)
1912 if ( strlen(segment
) > 16 )
1913 throw "-seccreate segment name max 16 chars";
1914 if ( strlen(section
) > 16 ) {
1915 char* tmp
= strdup(section
);
1917 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section
, tmp
);
1921 // read in whole file
1922 int fd
= ::open(path
, O_RDONLY
, 0);
1924 throwf("can't open -sectcreate file: %s", path
);
1925 struct stat stat_buf
;
1926 ::fstat(fd
, &stat_buf
);
1927 char* p
= (char*)malloc(stat_buf
.st_size
);
1929 throwf("can't process -sectcreate file: %s", path
);
1930 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1931 throwf("can't read -sectcreate file: %s", path
);
1934 // record section to create
1935 ExtraSection info
= { segment
, section
, path
, (uint8_t*)p
, (uint64_t)stat_buf
.st_size
};
1936 fExtraSections
.push_back(info
);
1939 void Options::addSectionRename(const char* srcSegment
, const char* srcSection
, const char* dstSegment
, const char* dstSection
)
1941 if ( strlen(srcSegment
) > 16 )
1942 throw "-rename_section segment name max 16 chars";
1943 if ( strlen(srcSection
) > 16 )
1944 throw "-rename_section section name max 16 chars";
1945 if ( strlen(dstSegment
) > 16 )
1946 throw "-rename_section segment name max 16 chars";
1947 if ( strlen(dstSection
) > 16 )
1948 throw "-rename_section section name max 16 chars";
1951 info
.fromSegment
= srcSegment
;
1952 info
.fromSection
= srcSection
;
1953 info
.toSegment
= dstSegment
;
1954 info
.toSection
= dstSection
;
1956 fSectionRenames
.push_back(info
);
1960 void Options::addSegmentRename(const char* srcSegment
, const char* dstSegment
)
1962 if ( strlen(srcSegment
) > 16 )
1963 throw "-rename_segment segment name max 16 chars";
1964 if ( strlen(dstSegment
) > 16 )
1965 throw "-rename_segment segment name max 16 chars";
1968 info
.fromSegment
= srcSegment
;
1969 info
.toSegment
= dstSegment
;
1971 fSegmentRenames
.push_back(info
);
1976 void Options::addSymbolMove(const char* dstSegment
, const char* symbolList
,
1977 std::vector
<SymbolsMove
>& list
, const char* optionName
)
1979 if ( strlen(dstSegment
) > 16 )
1980 throwf("%s segment name max 16 chars", optionName
);
1983 list
.push_back(tmp
);
1984 SymbolsMove
& info
= list
.back();
1985 info
.toSegment
= dstSegment
;
1986 loadExportFile(symbolList
, optionName
, info
.symbols
);
1989 bool Options::moveRwSymbol(const char* symName
, const char* filePath
, const char*& seg
, bool& wildCardMatch
) const
1991 for (std::vector
<SymbolsMove
>::const_iterator it
=fSymbolsMovesData
.begin(); it
!= fSymbolsMovesData
.end(); ++it
) {
1992 const SymbolsMove
& info
= *it
;
1993 if ( info
.symbols
.containsWithPrefix(symName
, filePath
, wildCardMatch
)) {
1994 seg
= info
.toSegment
;
2001 bool Options::moveRoSymbol(const char* symName
, const char* filePath
, const char*& seg
, bool& wildCardMatch
) const
2003 for (std::vector
<SymbolsMove
>::const_iterator it
=fSymbolsMovesCode
.begin(); it
!= fSymbolsMovesCode
.end(); ++it
) {
2004 const SymbolsMove
& info
= *it
;
2005 if ( info
.symbols
.containsWithPrefix(symName
, filePath
, wildCardMatch
)) {
2006 seg
= info
.toSegment
;
2013 void Options::addSectionAlignment(const char* segment
, const char* section
, const char* alignmentStr
)
2015 if ( strlen(segment
) > 16 )
2016 throw "-sectalign segment name max 16 chars";
2017 if ( strlen(section
) > 16 )
2018 throw "-sectalign section name max 16 chars";
2020 // argument to -sectalign is a hexadecimal number
2022 unsigned long value
= strtoul(alignmentStr
, &endptr
, 16);
2023 if ( *endptr
!= '\0')
2024 throw "argument for -sectalign is not a hexadecimal number";
2025 if ( value
> 0x8000 )
2026 throw "argument for -sectalign must be less than or equal to 0x8000";
2028 warning("zero is not a valid -sectalign");
2032 // alignment is power of 2 (e.g. page alignment = 12)
2033 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
2034 if ( (unsigned long)(1 << alignment
) != value
) {
2035 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
2036 segment
, section
, 1 << alignment
);
2039 SectionAlignment info
= { segment
, section
, alignment
};
2040 fSectionAlignments
.push_back(info
);
2043 void Options::addLibrary(const FileInfo
& info
)
2045 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
2046 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
2047 if ( strcmp(info
.path
, fit
->path
) == 0 ) {
2048 // if dylib is specified again but weak, record that it should be weak
2049 if ( info
.options
.fWeakImport
)
2050 fit
->options
.fWeakImport
= true;
2055 fInputFiles
.push_back(info
);
2058 void Options::warnObsolete(const char* arg
)
2060 warning("option %s is obsolete and being ignored", arg
);
2064 void Options::cannotBeUsedWithBitcode(const char* arg
)
2066 if ( fBundleBitcode
)
2067 throwf("%s and -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES) cannot be used together", arg
);
2070 std::string
Options::getVersionString32(uint32_t ver
) const
2072 if (ver
== 0 || ver
>= 0x10000000)
2075 unsigned microVersion
= ver
& 0xFF;
2076 unsigned minorVersion
= (ver
>> 8) & 0xFF;
2077 unsigned majorVersion
= (ver
>> 16) & 0xFF;
2078 std::stringstream versionString
;
2079 versionString
<< majorVersion
<< "." << minorVersion
<< "." << microVersion
;
2080 return versionString
.str();
2083 std::string
Options::getVersionString64(uint64_t ver
) const
2085 uint64_t a
= (ver
>> 40) & 0xFFFFFF;
2086 uint64_t b
= (ver
>> 30) & 0x3FF;
2087 uint64_t c
= (ver
>> 20) & 0x3FF;
2088 uint64_t d
= (ver
>> 10) & 0x3FF;
2089 uint64_t e
= ver
& 0x3FF;
2090 std::stringstream versionString
;
2091 versionString
<< a
<< "." << b
<< "." << c
<< "." << d
<< "." << e
;
2092 return versionString
.str();
2095 // Convert X.Y[.Z] to 32-bit value xxxxyyzz
2096 bool Options::parsePackedVersion32(const std::string
& versionStr
, uint32_t &result
)
2100 if ( versionStr
.empty() )
2103 size_t pos
= versionStr
.find('.');
2104 if ( pos
== std::string::npos
)
2107 std::string majorStr
= versionStr
.substr(0, pos
);
2108 std::string rest
= versionStr
.substr(pos
+1);
2112 int majorValue
= std::stoi(majorStr
, &majorEnd
);
2113 if ( majorEnd
!= majorStr
.size() )
2115 if ( majorValue
< 0 )
2117 if ( majorValue
> 65535 )
2120 std::string minorStr
;
2121 std::string microStr
;
2122 pos
= rest
.find('.');
2123 if ( pos
== std::string::npos
) {
2127 minorStr
= rest
.substr(0, pos
);
2128 microStr
= rest
.substr(pos
+1);
2132 int minorValue
= std::stoi(minorStr
, &minorEnd
);
2133 if ( minorEnd
!= minorStr
.size() )
2135 if ( minorValue
< 0 )
2137 if ( minorValue
> 255 )
2141 if ( !microStr
.empty() ) {
2143 microValue
= std::stoi(microStr
, µEnd
);
2144 if ( microEnd
!= microStr
.size() )
2146 if ( microValue
< 0 )
2148 if ( microValue
> 255 )
2152 result
= (majorValue
<< 16) | (minorValue
<< 8) | microValue
;
2157 // std::stoi() throws exception on malformed input
2162 std::string
Options::getSDKVersionStr() const
2164 return getVersionString32(fSDKVersion
);
2167 std::string
Options::getPlatformStr() const
2169 switch (fPlatform
) {
2170 case Options::kPlatformOSX
:
2172 case Options::kPlatformiOS
:
2173 if (targetIOSSimulator())
2174 return "iPhoneSimulator";
2177 case Options::kPlatformWatchOS
:
2178 if (targetIOSSimulator())
2179 return "watchOS Simulator";
2182 #if SUPPORT_APPLE_TV
2183 case Options::kPlatform_tvOS
:
2184 if (targetIOSSimulator())
2185 return "AppleTVSimulator";
2190 case Options::kPlatformUnknown
:
2195 std::vector
<std::string
> Options::writeBitcodeLinkOptions() const
2197 std::vector
<std::string
> linkCommand
;
2198 switch ( fOutputKind
) {
2199 case Options::kDynamicLibrary
:
2200 linkCommand
.push_back("-dylib");
2201 linkCommand
.push_back("-compatibility_version");
2202 if ( fDylibCompatVersion
!= 0 ) {
2203 linkCommand
.push_back(getVersionString32(fDylibCompatVersion
));
2205 linkCommand
.push_back(getVersionString32(currentVersion32()));
2207 if ( fDylibCurrentVersion
!= 0 ) {
2208 linkCommand
.push_back("-current_version");
2209 linkCommand
.push_back(getVersionString64(fDylibCurrentVersion
));
2211 linkCommand
.push_back("-install_name");
2212 linkCommand
.push_back(installPath());
2214 case Options::kDynamicExecutable
:
2215 linkCommand
.push_back("-execute");
2217 case Options::kObjectFile
:
2218 linkCommand
.push_back("-r");
2221 throwf("could not write bitcode options file output kind\n");
2224 if (!fImplicitlyLinkPublicDylibs
)
2225 linkCommand
.push_back("-no_implicit_dylibs");
2227 // Add deployment target.
2228 // Platform is allowed to be unknown for "ld -r".
2229 switch (fPlatform
) {
2230 case Options::kPlatformOSX
:
2231 linkCommand
.push_back("-macosx_version_min");
2232 linkCommand
.push_back(getVersionString32((unsigned)fMacVersionMin
));
2234 case Options::kPlatformiOS
:
2235 if (targetIOSSimulator())
2236 linkCommand
.push_back("-ios_simulator_version_min");
2238 linkCommand
.push_back("-ios_version_min");
2239 linkCommand
.push_back(getVersionString32((unsigned)fIOSVersionMin
));
2241 case Options::kPlatformWatchOS
:
2242 if (targetIOSSimulator())
2243 linkCommand
.push_back("-watchos_simulator_version_min");
2245 linkCommand
.push_back("-watchos_version_min");
2246 linkCommand
.push_back(getVersionString32((unsigned)fIOSVersionMin
));
2248 #if SUPPORT_APPLE_TV
2249 case Options::kPlatform_tvOS
:
2250 if (targetIOSSimulator())
2251 linkCommand
.push_back("-tvos_simulator_version_min");
2253 linkCommand
.push_back("-tvos_version_min");
2254 linkCommand
.push_back(getVersionString32((unsigned)fIOSVersionMin
));
2257 case Options::kPlatformUnknown
:
2258 if ( fOutputKind
!= Options::kObjectFile
) {
2259 throwf("platform is unknown for final bitcode bundle,"
2260 "deployment target and min version is required for -bitcode_bundle");
2268 linkCommand
.push_back("-e");
2269 linkCommand
.push_back(fEntryName
);
2273 if (!fRPaths
.empty()) {
2274 for (std::vector
<const char*>::const_iterator it
=fRPaths
.begin(); it
!= fRPaths
.end(); ++it
) {
2275 linkCommand
.push_back("-rpath");
2276 linkCommand
.push_back(*it
);
2280 // Other bitcode compatiable options
2281 if ( fObjCABIVersion1Override
) {
2282 linkCommand
.push_back("-objc_abi_version");
2283 linkCommand
.push_back("1");
2284 } else if ( fObjCABIVersion2Override
) {
2285 linkCommand
.push_back("-objc_abi_version");
2286 linkCommand
.push_back("2");
2288 if ( fExecutablePath
) {
2289 linkCommand
.push_back("-executable_path");
2290 linkCommand
.push_back(fExecutablePath
);
2293 linkCommand
.push_back("-dead_strip");
2294 if ( fExportDynamic
)
2295 linkCommand
.push_back("-export_dynamic");
2296 if ( fMarkAppExtensionSafe
&& fCheckAppExtensionSafe
)
2297 linkCommand
.push_back("-application_extension");
2299 if ( fSourceVersionLoadCommandForceOn
)
2300 linkCommand
.push_back("-add_source_version");
2301 if ( fSourceVersion
!= 0 ) {
2302 linkCommand
.push_back("-source_version");
2303 linkCommand
.push_back(getVersionString64(fSourceVersion
));
2306 // linker flag added by swift driver
2307 // rdar://problem/20108072
2308 if ( !fObjcCategoryMerging
)
2309 linkCommand
.push_back("-no_objc_category_merging");
2315 // Process all command line arguments.
2317 // The only error checking done here is that each option is valid and if it has arguments
2318 // that they too are valid.
2320 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
2321 // whichever was last on the command line is used.
2323 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
2325 void Options::parse(int argc
, const char* argv
[])
2327 // Store the original args in the link snapshot.
2328 fLinkSnapshot
.recordRawArgs(argc
, argv
);
2330 // pass one builds search list from -L and -F options
2331 this->buildSearchPaths(argc
, argv
);
2333 // reduce re-allocations
2334 fInputFiles
.reserve(32);
2336 // pass two parse all other options
2337 for(int i
=1; i
< argc
; ++i
) {
2338 const char* arg
= argv
[i
];
2340 if ( arg
[0] == '-' ) {
2341 // by default, copy one arg to the snapshot link command, and do no file copying
2342 int snapshotArgIndex
= i
;
2343 int snapshotArgCount
= -1; // -1 means compute count based on change in index
2344 int snapshotFileArgIndex
= -1; // -1 means no data file parameter to arg
2346 // Since we don't care about the files passed, just the option names, we do this here.
2348 fprintf (stderr
, "[Logging ld64 options]\t%s\n", arg
);
2350 if ( (arg
[1] == 'L') || (arg
[1] == 'F') ) {
2351 snapshotArgCount
= 0; // stripped out of link snapshot
2354 // previously handled by buildSearchPaths()
2356 // The one gnu style option we have to keep compatibility
2357 // with gcc. Might as well have the single hyphen one as well.
2358 else if ( (strcmp(arg
, "--help") == 0)
2359 || (strcmp(arg
, "-help") == 0)) {
2360 fprintf (stdout
, "ld64: For information on command line options please use 'man ld'.\n");
2363 else if ( strcmp(arg
, "-arch") == 0 ) {
2364 parseArch(argv
[++i
]);
2366 else if ( strcmp(arg
, "-dynamic") == 0 ) {
2369 else if ( strcmp(arg
, "-static") == 0 ) {
2371 if ( (fOutputKind
!= kObjectFile
) && (fOutputKind
!= kKextBundle
) ) {
2372 fOutputKind
= kStaticExecutable
;
2374 cannotBeUsedWithBitcode(arg
);
2376 else if ( strcmp(arg
, "-dylib") == 0 ) {
2377 fOutputKind
= kDynamicLibrary
;
2379 else if ( strcmp(arg
, "-bundle") == 0 ) {
2380 fOutputKind
= kDynamicBundle
;
2381 cannotBeUsedWithBitcode(arg
);
2383 else if ( strcmp(arg
, "-dylinker") == 0 ) {
2384 fOutputKind
= kDyld
;
2385 cannotBeUsedWithBitcode(arg
);
2387 else if ( strcmp(arg
, "-execute") == 0 ) {
2388 if ( fOutputKind
!= kStaticExecutable
)
2389 fOutputKind
= kDynamicExecutable
;
2391 else if ( strcmp(arg
, "-preload") == 0 ) {
2392 fOutputKind
= kPreload
;
2393 cannotBeUsedWithBitcode(arg
);
2395 else if ( strcmp(arg
, "-r") == 0 ) {
2396 fOutputKind
= kObjectFile
;
2398 else if ( strcmp(arg
, "-kext") == 0 ) {
2399 fOutputKind
= kKextBundle
;
2400 cannotBeUsedWithBitcode(arg
);
2402 else if ( strcmp(arg
, "-o") == 0 ) {
2403 snapshotArgCount
= 0;
2404 fOutputFile
= argv
[++i
];
2405 fLinkSnapshot
.setSnapshotName(fOutputFile
);
2407 else if ( strncmp(arg
, "-lazy-l", 7) == 0 ) {
2408 snapshotArgCount
= 0;
2409 FileInfo info
= findLibrary(&arg
[7], true);
2410 info
.options
.fLazyLoad
= true;
2411 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2413 fUsingLazyDylibLinking
= true;
2414 cannotBeUsedWithBitcode(arg
);
2416 else if ( strcmp(arg
, "-lto_library") == 0 ) {
2417 snapshotFileArgIndex
= 1;
2418 fOverridePathlibLTO
= argv
[++i
];
2419 if ( fOverridePathlibLTO
== NULL
)
2420 throw "missing argument to -lto_library";
2422 else if ( strcmp(arg
, "-cache_path_lto") == 0 ) {
2423 fLtoCachePath
= argv
[++i
];
2424 if ( fLtoCachePath
== NULL
)
2425 throw "missing argument to -cache_path_lto";
2427 else if ( strcmp(arg
, "-prune_interval_lto") == 0 ) {
2428 const char* value
= argv
[++i
];
2429 if ( value
== NULL
)
2430 throw "missing argument to -prune_interval_lto";
2432 fLtoPruneInterval
= strtoul(value
, &endptr
, 10);
2433 if ( *endptr
!= '\0')
2434 throw "invalid argument for -prune_interval_lto";
2436 else if ( strcmp(arg
, "-prune_after_lto") == 0 ) {
2437 const char* value
= argv
[++i
];
2438 if ( value
== NULL
)
2439 throw "missing argument to -prune_after_lto";
2441 fLtoPruneAfter
= strtoul(value
, &endptr
, 10);
2442 if ( *endptr
!= '\0')
2443 throw "invalid argument for -prune_after_lto";
2445 else if ( strcmp(arg
, "-max_relative_cache_size_lto") == 0 ) {
2446 const char* value
= argv
[++i
];
2447 if ( value
== NULL
)
2448 throw "missing argument to -max_relative_cache_size_lto";
2450 fLtoMaxCacheSize
= strtoul(value
, &endptr
, 10);
2451 if ( *endptr
!= '\0')
2452 throw "invalid argument for -max_relative_cache_size_lto";
2453 if (fLtoMaxCacheSize
> 100)
2454 throw "Expect a value between 0 and 100 for -max_relative_cache_size_lto";
2456 else if ( (arg
[1] == 'l') && (strncmp(arg
,"-lazy_",6) !=0) ) {
2457 snapshotArgCount
= 0;
2458 FileInfo info
= findLibrary(&arg
[2]);
2459 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2462 // This causes a dylib to be weakly bound at
2463 // link time. This corresponds to weak_import.
2464 else if ( strncmp(arg
, "-weak-l", 7) == 0 ) {
2465 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2466 snapshotArgCount
= 0;
2467 FileInfo info
= findLibrary(&arg
[7]);
2468 info
.options
.fWeakImport
= true;
2469 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2472 // Avoid lazy binding.
2473 else if ( strcmp(arg
, "-bind_at_load") == 0 ) {
2475 cannotBeUsedWithBitcode(arg
);
2477 else if ( strcmp(arg
, "-twolevel_namespace") == 0 ) {
2478 fNameSpace
= kTwoLevelNameSpace
;
2480 else if ( strcmp(arg
, "-flat_namespace") == 0 ) {
2481 fNameSpace
= kFlatNameSpace
;
2482 cannotBeUsedWithBitcode(arg
);
2484 // Also sets a bit to ensure dyld causes everything
2485 // in the namespace to be flat.
2487 else if ( strcmp(arg
, "-force_flat_namespace") == 0 ) {
2488 fNameSpace
= kForceFlatNameSpace
;
2489 cannotBeUsedWithBitcode(arg
);
2491 // Similar to --whole-archive.
2492 else if ( strcmp(arg
, "-all_load") == 0 ) {
2493 fFullyLoadArchives
= true;
2495 else if ( strcmp(arg
, "-noall_load") == 0) {
2498 // Similar to -all_load
2499 else if ( strcmp(arg
, "-ObjC") == 0 ) {
2500 fLoadAllObjcObjectsFromArchives
= true;
2502 // Similar to -all_load, but for the following archive only.
2503 else if ( strcmp(arg
, "-force_load") == 0 ) {
2504 FileInfo info
= findFile(argv
[++i
]);
2505 info
.options
.fForceLoad
= true;
2506 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2509 // Library versioning.
2510 else if ( (strcmp(arg
, "-dylib_compatibility_version") == 0)
2511 || (strcmp(arg
, "-compatibility_version") == 0)) {
2512 const char* vers
= argv
[++i
];
2514 throw "-dylib_compatibility_version missing <version>";
2515 fDylibCompatVersion
= parseVersionNumber32(vers
);
2517 else if ( (strcmp(arg
, "-dylib_current_version") == 0)
2518 || (strcmp(arg
, "-current_version") == 0)) {
2519 const char* vers
= argv
[++i
];
2521 throw "-dylib_current_version missing <version>";
2522 fDylibCurrentVersion
= parseVersionNumber64(vers
);
2524 else if ( strcmp(arg
, "-sectorder") == 0 ) {
2525 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2526 throw "-sectorder missing <segment> <section> <file-path>";
2527 snapshotFileArgIndex
= 3;
2528 parseSectionOrderFile(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2530 cannotBeUsedWithBitcode(arg
);
2532 else if ( strcmp(arg
, "-order_file") == 0 ) {
2533 snapshotFileArgIndex
= 1;
2534 parseOrderFile(argv
[++i
], false);
2536 else if ( strcmp(arg
, "-order_file_statistics") == 0 ) {
2537 fPrintOrderFileStatistics
= true;
2538 cannotBeUsedWithBitcode(arg
);
2540 // ??? Deprecate segcreate.
2541 // -sectcreate puts whole files into a section in the output.
2542 else if ( (strcmp(arg
, "-sectcreate") == 0) || (strcmp(arg
, "-segcreate") == 0) ) {
2543 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2544 throw "-sectcreate missing <segment> <section> <file-path>";
2545 snapshotFileArgIndex
= 3;
2546 addSection(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2549 // Since we have a full path in binary/library names we need to be able to override it.
2550 else if ( (strcmp(arg
, "-dylib_install_name") == 0)
2551 || (strcmp(arg
, "-dylinker_install_name") == 0)
2552 || (strcmp(arg
, "-install_name") == 0)) {
2553 fDylibInstallName
= argv
[++i
];
2554 if ( fDylibInstallName
== NULL
)
2555 throw "-install_name missing <path>";
2557 // Sets the base address of the output.
2558 else if ( (strcmp(arg
, "-seg1addr") == 0) || (strcmp(arg
, "-image_base") == 0) ) {
2559 const char* address
= argv
[++i
];
2560 if ( address
== NULL
)
2561 throwf("%s missing <address>", arg
);
2562 fBaseAddress
= parseAddress(address
);
2563 uint64_t temp
= ((fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
2564 if ( fBaseAddress
!= temp
) {
2565 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment
);
2566 fBaseAddress
= temp
;
2568 cannotBeUsedWithBitcode(arg
);
2570 else if ( strcmp(arg
, "-e") == 0 ) {
2571 fEntryName
= argv
[++i
];
2573 // Same as -@ from the FSF linker.
2574 else if ( strcmp(arg
, "-filelist") == 0 ) {
2575 snapshotArgCount
= 0;
2576 const char* path
= argv
[++i
];
2577 if ( (path
== NULL
) || (path
[0] == '-') )
2578 throw "-filelist missing <path>";
2579 ld::File::Ordinal baseOrdinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2580 loadFileList(path
, baseOrdinal
);
2582 else if ( strcmp(arg
, "-keep_private_externs") == 0 ) {
2583 cannotBeUsedWithBitcode(arg
);
2584 fKeepPrivateExterns
= true;
2586 else if ( strcmp(arg
, "-final_output") == 0 ) {
2587 fFinalName
= argv
[++i
];
2589 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
2590 // just ensures that this happens for cross object file boundaries.
2591 else if ( (strcmp(arg
, "-interposable") == 0) || (strcmp(arg
, "-multi_module") == 0)) {
2592 switch ( fInterposeMode
) {
2593 case kInterposeNone
:
2594 case kInterposeAllExternal
:
2595 fInterposeMode
= kInterposeAllExternal
;
2597 case kInterposeSome
:
2598 // do nothing, -interposable_list overrides -interposable"
2601 cannotBeUsedWithBitcode(arg
);
2603 else if ( strcmp(arg
, "-interposable_list") == 0 ) {
2604 snapshotFileArgIndex
= 1;
2605 fInterposeMode
= kInterposeSome
;
2606 loadExportFile(argv
[++i
], "-interposable_list", fInterposeList
);
2607 cannotBeUsedWithBitcode(arg
);
2609 // Default for -interposable/-multi_module/-single_module.
2610 else if ( strcmp(arg
, "-single_module") == 0 ) {
2611 fInterposeMode
= kInterposeNone
;
2613 else if ( strcmp(arg
, "-exported_symbols_list") == 0 ) {
2614 snapshotFileArgIndex
= 1;
2615 if ( fExportMode
== kDontExportSome
)
2616 throw "can't use -exported_symbols_list and -unexported_symbols_list";
2617 fExportMode
= kExportSome
;
2618 loadExportFile(argv
[++i
], "-exported_symbols_list", fExportSymbols
);
2620 else if ( strcmp(arg
, "-unexported_symbols_list") == 0 ) {
2621 snapshotFileArgIndex
= 1;
2622 if ( fExportMode
== kExportSome
)
2623 throw "can't use -unexported_symbols_list and -exported_symbols_list";
2624 fExportMode
= kDontExportSome
;
2625 loadExportFile(argv
[++i
], "-unexported_symbols_list", fDontExportSymbols
);
2627 else if ( strcmp(arg
, "-exported_symbol") == 0 ) {
2628 if ( fExportMode
== kDontExportSome
)
2629 throw "can't use -exported_symbol and -unexported_symbols";
2630 fExportMode
= kExportSome
;
2631 fExportSymbols
.insert(argv
[++i
]);
2633 else if ( strcmp(arg
, "-unexported_symbol") == 0 ) {
2634 if ( fExportMode
== kExportSome
)
2635 throw "can't use -unexported_symbol and -exported_symbol";
2636 fExportMode
= kDontExportSome
;
2637 fDontExportSymbols
.insert(argv
[++i
]);
2639 else if ( strcmp(arg
, "-non_global_symbols_no_strip_list") == 0 ) {
2640 snapshotFileArgIndex
= 1;
2641 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveExclude
)
2642 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2643 fLocalSymbolHandling
= kLocalSymbolsSelectiveInclude
;
2644 loadExportFile(argv
[++i
], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded
);
2645 cannotBeUsedWithBitcode(arg
);
2647 else if ( strcmp(arg
, "-non_global_symbols_strip_list") == 0 ) {
2648 snapshotFileArgIndex
= 1;
2649 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveInclude
)
2650 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2651 fLocalSymbolHandling
= kLocalSymbolsSelectiveExclude
;
2652 loadExportFile(argv
[++i
], "-non_global_symbols_strip_list", fLocalSymbolsExcluded
);
2653 cannotBeUsedWithBitcode(arg
);
2656 else if ( strcmp(arg
, "-no_arch_warnings") == 0 ) {
2657 fIgnoreOtherArchFiles
= true;
2659 else if ( strcmp(arg
, "-force_cpusubtype_ALL") == 0 ) {
2660 fForceSubtypeAll
= true;
2661 fAllowCpuSubtypeMismatches
= true;
2662 cannotBeUsedWithBitcode(arg
);
2664 // Similar to -weak-l but uses the absolute path name to the library.
2665 else if ( strcmp(arg
, "-weak_library") == 0 ) {
2666 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2667 snapshotArgCount
= 0;
2668 FileInfo info
= findFile(argv
[++i
]);
2669 info
.options
.fWeakImport
= true;
2670 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2672 cannotBeUsedWithBitcode(arg
);
2674 else if ( strcmp(arg
, "-lazy_library") == 0 ) {
2675 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2676 snapshotArgCount
= 0;
2677 FileInfo info
= findFile(argv
[++i
]);
2678 info
.options
.fLazyLoad
= true;
2679 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2681 fUsingLazyDylibLinking
= true;
2682 cannotBeUsedWithBitcode(arg
);
2684 else if ( strcmp(arg
, "-framework") == 0 ) {
2685 snapshotArgCount
= 0;
2686 FileInfo info
= findFramework(argv
[++i
]);
2687 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2690 else if ( strcmp(arg
, "-weak_framework") == 0 ) {
2691 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2692 snapshotArgCount
= 0;
2693 FileInfo info
= findFramework(argv
[++i
]);
2694 info
.options
.fWeakImport
= true;
2695 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2698 else if ( strcmp(arg
, "-lazy_framework") == 0 ) {
2699 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2700 snapshotArgCount
= 0;
2701 FileInfo info
= findFramework(argv
[++i
]);
2702 info
.options
.fLazyLoad
= true;
2703 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2705 fUsingLazyDylibLinking
= true;
2706 cannotBeUsedWithBitcode(arg
);
2708 else if ( strcmp(arg
, "-search_paths_first") == 0 ) {
2709 // previously handled by buildSearchPaths()
2711 else if ( strcmp(arg
, "-search_dylibs_first") == 0 ) {
2712 // previously handled by buildSearchPaths()
2714 else if ( strcmp(arg
, "-undefined") == 0 ) {
2715 setUndefinedTreatment(argv
[++i
]);
2716 cannotBeUsedWithBitcode(arg
);
2718 // Debugging output flag.
2719 else if ( strcmp(arg
, "-arch_multiple") == 0 ) {
2720 fMessagesPrefixedWithArchitecture
= true;
2722 // Specify what to do with relocations in read only
2723 // sections like .text. Could be errors, warnings,
2724 // or suppressed. Currently we do nothing with the
2726 else if ( strcmp(arg
, "-read_only_relocs") == 0 ) {
2727 switch ( parseTreatment(argv
[++i
]) ) {
2730 throw "-read_only_relocs missing [ warning | error | suppress ]";
2732 fWarnTextRelocs
= true;
2733 fAllowTextRelocs
= true;
2734 cannotBeUsedWithBitcode(arg
);
2737 fWarnTextRelocs
= false;
2738 fAllowTextRelocs
= true;
2739 cannotBeUsedWithBitcode(arg
);
2742 fWarnTextRelocs
= false;
2743 fAllowTextRelocs
= false;
2747 else if ( strcmp(arg
, "-sect_diff_relocs") == 0 ) {
2751 // Warn, error or make strong a mismatch between weak
2752 // and non-weak references.
2753 else if ( strcmp(arg
, "-weak_reference_mismatches") == 0 ) {
2754 setWeakReferenceMismatchTreatment(argv
[++i
]);
2756 // For a deployment target of 10.3 and earlier ld64 will
2757 // prebind an executable with 0s in all addresses that
2758 // are prebound. This can then be fixed up by update_prebinding
2759 // later. Prebinding is less useful on 10.4 and greater.
2760 else if ( strcmp(arg
, "-prebind") == 0 ) {
2762 cannotBeUsedWithBitcode(arg
);
2764 else if ( strcmp(arg
, "-noprebind") == 0 ) {
2768 else if ( strcmp(arg
, "-prebind_allow_overlap") == 0 ) {
2771 else if ( strcmp(arg
, "-prebind_all_twolevel_modules") == 0 ) {
2774 else if ( strcmp(arg
, "-noprebind_all_twolevel_modules") == 0 ) {
2777 else if ( strcmp(arg
, "-nofixprebinding") == 0 ) {
2780 // This should probably be deprecated when we respect -L and -F
2781 // when searching for libraries.
2782 else if ( strcmp(arg
, "-dylib_file") == 0 ) {
2783 // ignore for snapshot because a stub dylib will be created in the snapshot
2784 snapshotArgCount
= 0;
2785 addDylibOverride(argv
[++i
]);
2786 cannotBeUsedWithBitcode(arg
);
2788 // What to expand @executable_path to if found in dependent dylibs
2789 else if ( strcmp(arg
, "-executable_path") == 0 ) {
2790 fExecutablePath
= argv
[++i
];
2791 if ( (fExecutablePath
== NULL
) || (fExecutablePath
[0] == '-') )
2792 throw "-executable_path missing <path>";
2793 // if a directory was passed, add / to end
2794 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2795 struct stat statBuffer
;
2796 if ( stat(fExecutablePath
, &statBuffer
) == 0 ) {
2797 if ( (statBuffer
.st_mode
& S_IFMT
) == S_IFDIR
) {
2798 char* pathWithSlash
= new char[strlen(fExecutablePath
)+2];
2799 strcpy(pathWithSlash
, fExecutablePath
);
2800 strcat(pathWithSlash
, "/");
2801 fExecutablePath
= pathWithSlash
;
2805 // Aligns all segments to the power of 2 boundary specified.
2806 else if ( strcmp(arg
, "-segalign") == 0 ) {
2807 const char* size
= argv
[++i
];
2809 throw "-segalign missing <size>";
2810 fSegmentAlignment
= parseAddress(size
);
2811 uint8_t alignment
= (uint8_t)__builtin_ctz(fSegmentAlignment
);
2812 uint32_t p2aligned
= (1 << alignment
);
2813 if ( p2aligned
!= fSegmentAlignment
) {
2814 warning("alignment for -segalign %s is not a power of two, using 0x%X", size
, p2aligned
);
2815 fSegmentAlignment
= p2aligned
;
2817 cannotBeUsedWithBitcode(arg
);
2819 // Puts a specified segment at a particular address that must
2820 // be a multiple of the segment alignment.
2821 else if ( strcmp(arg
, "-segaddr") == 0 ) {
2823 seg
.name
= argv
[++i
];
2824 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2825 throw "-segaddr missing segName Adddress";
2826 seg
.address
= parseAddress(argv
[++i
]);
2827 uint64_t temp
= ((seg
.address
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
2828 if ( seg
.address
!= temp
)
2829 warning("-segaddr %s not %lld byte aligned", seg
.name
, fSegmentAlignment
);
2830 fCustomSegmentAddresses
.push_back(seg
);
2831 cannotBeUsedWithBitcode(arg
);
2833 // ??? Deprecate when we deprecate split-seg.
2834 else if ( strcmp(arg
, "-segs_read_only_addr") == 0 ) {
2835 fBaseAddress
= parseAddress(argv
[++i
]);
2836 cannotBeUsedWithBitcode(arg
);
2838 // ??? Deprecate when we deprecate split-seg.
2839 else if ( strcmp(arg
, "-segs_read_write_addr") == 0 ) {
2840 fBaseWritableAddress
= parseAddress(argv
[++i
]);
2842 cannotBeUsedWithBitcode(arg
);
2844 // ??? Deprecate when we get rid of basing at build time.
2845 else if ( strcmp(arg
, "-seg_addr_table") == 0 ) {
2846 snapshotFileArgIndex
= 1;
2847 const char* name
= argv
[++i
];
2849 throw "-seg_addr_table missing argument";
2850 fSegAddrTablePath
= name
;
2851 cannotBeUsedWithBitcode(arg
);
2853 else if ( strcmp(arg
, "-seg_addr_table_filename") == 0 ) {
2857 else if ( strcmp(arg
, "-segprot") == 0 ) {
2859 seg
.name
= argv
[++i
];
2860 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) || (argv
[i
+2] == NULL
) )
2861 throw "-segprot missing segName max-prot init-prot";
2862 seg
.max
= parseProtection(argv
[++i
]);
2863 seg
.init
= parseProtection(argv
[++i
]);
2864 if ( strcmp(seg
.name
, "__LINKEDIT") == 0 )
2865 warning("-segprot cannot be used to modify __LINKEDIT protections");
2867 fCustomSegmentProtections
.push_back(seg
);
2868 cannotBeUsedWithBitcode(arg
);
2870 else if ( strcmp(arg
, "-pagezero_size") == 0 ) {
2871 const char* size
= argv
[++i
];
2873 throw "-pagezero_size missing <size>";
2874 fZeroPageSize
= parseAddress(size
);
2875 uint64_t temp
= fZeroPageSize
& (-4096); // page align
2876 if ( (fZeroPageSize
!= temp
) )
2877 warning("-pagezero_size not page aligned, rounding down");
2878 fZeroPageSize
= temp
;
2879 cannotBeUsedWithBitcode(arg
);
2881 else if ( strcmp(arg
, "-stack_addr") == 0 ) {
2882 const char* address
= argv
[++i
];
2883 if ( address
== NULL
)
2884 throw "-stack_addr missing <address>";
2885 fStackAddr
= parseAddress(address
);
2886 cannotBeUsedWithBitcode(arg
);
2888 else if ( strcmp(arg
, "-stack_size") == 0 ) {
2889 const char* size
= argv
[++i
];
2891 throw "-stack_size missing <address>";
2892 fStackSize
= parseAddress(size
);
2894 else if ( strcmp(arg
, "-allow_stack_execute") == 0 ) {
2895 fExecutableStack
= true;
2896 cannotBeUsedWithBitcode(arg
);
2898 else if ( strcmp(arg
, "-allow_heap_execute") == 0 ) {
2899 fDisableNonExecutableHeap
= true;
2900 cannotBeUsedWithBitcode(arg
);
2902 else if ( strcmp(arg
, "-sectalign") == 0 ) {
2903 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2904 throw "-sectalign missing <segment> <section> <file-path>";
2905 addSectionAlignment(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2907 cannotBeUsedWithBitcode(arg
);
2909 else if ( strcmp(arg
, "-sectorder_detail") == 0 ) {
2912 else if ( strcmp(arg
, "-sectobjectsymbols") == 0 ) {
2916 else if ( strcmp(arg
, "-bundle_loader") == 0 ) {
2917 snapshotFileArgIndex
= 1;
2918 fBundleLoader
= argv
[++i
];
2919 if ( (fBundleLoader
== NULL
) || (fBundleLoader
[0] == '-') )
2920 throw "-bundle_loader missing <path>";
2921 FileInfo info
= findFile(fBundleLoader
);
2922 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2923 info
.options
.fBundleLoader
= true;
2924 fInputFiles
.push_back(info
);
2926 else if ( strcmp(arg
, "-private_bundle") == 0 ) {
2929 else if ( strcmp(arg
, "-twolevel_namespace_hints") == 0 ) {
2932 // Use this flag to set default behavior for deployement targets.
2933 else if ( strcmp(arg
, "-macosx_version_min") == 0 ) {
2934 const char* macVers
= argv
[++i
];
2935 if ( macVers
== NULL
)
2936 throw "-macosx_version_min missing version argument";
2937 const char* envMacVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
2938 const char* enviPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
2939 if ( (envMacVers
!= NULL
) && (enviPhoneVers
!= NULL
) ) {
2940 // <rdar://problem/13774329> when conflicting deployments set, break tie by looking at syslibroot
2941 warning("both MACOSX_DEPLOYMENT_TARGET and IPHONEOS_DEPLOYMENT_TARGET are set");
2942 if ( !fSDKPaths
.empty() ) {
2943 const char* sysrootPath
= fSDKPaths
.back();
2944 const char* lastSlash
= strrchr(sysrootPath
, '/');
2945 if ( strstr(lastSlash
, "Simulator") != NULL
)
2946 setIOSVersionMin(enviPhoneVers
);
2948 setMacOSXVersionMin(macVers
);
2951 setMacOSXVersionMin(macVers
);
2955 setMacOSXVersionMin(macVers
);
2958 else if ( (strcmp(arg
, "-ios_version_min") == 0) || (strcmp(arg
, "-iphoneos_version_min") == 0) ) {
2959 const char* vers
= argv
[++i
];
2961 throw "-ios_version_min missing version argument";
2962 setIOSVersionMin(vers
);
2964 else if ( strcmp(arg
, "-ios_simulator_version_min") == 0 ) {
2965 const char* vers
= argv
[++i
];
2967 throw "-ios_simulator_version_min missing version argument";
2968 setIOSVersionMin(vers
);
2969 fTargetIOSSimulator
= true;
2971 else if ( strcmp(arg
, "-watchos_version_min") == 0 ) {
2972 const char* vers
= argv
[++i
];
2974 throw "-watchos_version_min missing version argument";
2975 setWatchOSVersionMin(vers
);
2977 else if ( strcmp(arg
, "-watchos_simulator_version_min") == 0 ) {
2978 const char* vers
= argv
[++i
];
2980 throw "-watchos_simulator_version_min missing version argument";
2981 setWatchOSVersionMin(vers
);
2982 fTargetIOSSimulator
= true;
2984 #if SUPPORT_APPLE_TV
2985 else if ( strcmp(arg
, "-tvos_version_min") == 0 ) {
2986 const char* vers
= argv
[++i
];
2988 throw "-tvos_version_min missing version argument";
2989 setIOSVersionMin(vers
);
2990 fPlatform
= kPlatform_tvOS
;
2992 else if ( strcmp(arg
, "-tvos_simulator_version_min") == 0 ) {
2993 const char* vers
= argv
[++i
];
2995 throw "-tvos_simulator_version_min missing version argument";
2996 setIOSVersionMin(vers
);
2997 fPlatform
= kPlatform_tvOS
;
2998 fTargetIOSSimulator
= true;
3001 else if ( strcmp(arg
, "-multiply_defined") == 0 ) {
3002 //warnObsolete(arg);
3005 else if ( strcmp(arg
, "-multiply_defined_unused") == 0 ) {
3009 else if ( strcmp(arg
, "-nomultidefs") == 0 ) {
3012 // Display each file in which the argument symbol appears and whether
3013 // the file defines or references it. This option takes an argument
3014 // as -y<symbol> note that there is no space.
3015 else if ( strncmp(arg
, "-y", 2) == 0 ) {
3018 // Same output as -y, but output <arg> number of undefined symbols only.
3019 else if ( strcmp(arg
, "-Y") == 0 ) {
3020 //warnObsolete(arg);
3023 // This option affects all objects linked into the final result.
3024 else if ( strcmp(arg
, "-m") == 0 ) {
3027 else if ( (strcmp(arg
, "-why_load") == 0) || (strcmp(arg
, "-whyload") == 0) ) {
3030 else if ( strcmp(arg
, "-why_live") == 0 ) {
3031 const char* name
= argv
[++i
];
3033 throw "-why_live missing symbol name argument";
3034 fWhyLive
.insert(name
);
3036 else if ( strcmp(arg
, "-u") == 0 ) {
3037 const char* name
= argv
[++i
];
3039 throw "-u missing argument";
3040 fInitialUndefines
.push_back(name
);
3041 cannotBeUsedWithBitcode(arg
);
3043 else if ( strcmp(arg
, "-U") == 0 ) {
3044 const char* name
= argv
[++i
];
3046 throw "-U missing argument";
3047 fAllowedUndefined
.insert(name
);
3048 cannotBeUsedWithBitcode(arg
);
3050 else if ( strcmp(arg
, "-s") == 0 ) {
3052 fLocalSymbolHandling
= kLocalSymbolsNone
;
3053 fDebugInfoStripping
= Options::kDebugInfoNone
;
3055 else if ( strcmp(arg
, "-x") == 0 ) {
3056 fLocalSymbolHandling
= kLocalSymbolsNone
;
3058 else if ( strcmp(arg
, "-S") == 0 ) {
3059 fDebugInfoStripping
= Options::kDebugInfoNone
;
3061 else if ( strcmp(arg
, "-X") == 0 ) {
3064 else if ( strcmp(arg
, "-Si") == 0 ) {
3066 fDebugInfoStripping
= Options::kDebugInfoFull
;
3068 else if ( strcmp(arg
, "-b") == 0 ) {
3071 else if ( strcmp(arg
, "-Sn") == 0 ) {
3073 fDebugInfoStripping
= Options::kDebugInfoFull
;
3075 else if ( strcmp(arg
, "-Sp") == 0 ) {
3078 else if ( strcmp(arg
, "-dead_strip") == 0 ) {
3081 else if ( strcmp(arg
, "-no_dead_strip_inits_and_terms") == 0 ) {
3084 else if ( strcmp(arg
, "-w") == 0 ) {
3085 // previously handled by buildSearchPaths()
3087 else if ( strcmp(arg
, "-fatal_warnings") == 0 ) {
3088 // previously handled by buildSearchPaths()
3090 else if ( strcmp(arg
, "-arch_errors_fatal") == 0 ) {
3091 fErrorOnOtherArchFiles
= true;
3093 else if ( strcmp(arg
, "-M") == 0 ) {
3096 else if ( strcmp(arg
, "-headerpad") == 0 ) {
3097 const char* size
= argv
[++i
];
3099 throw "-headerpad missing argument";
3100 fMinimumHeaderPad
= parseAddress(size
);
3101 cannotBeUsedWithBitcode(arg
);
3103 else if ( strcmp(arg
, "-headerpad_max_install_names") == 0 ) {
3104 // ignore -headerpad_max_install_names when compiling with bitcode
3105 // rdar://problem/20748962
3106 if ( fBundleBitcode
)
3107 warning("-headerpad_max_install_names is ignored when used with -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES)");
3109 fMaxMinimumHeaderPad
= true;
3111 else if ( strcmp(arg
, "-t") == 0 ) {
3112 fLogAllFiles
= true;
3114 else if ( strcmp(arg
, "-whatsloaded") == 0 ) {
3115 fLogObjectFiles
= true;
3117 else if ( strcmp(arg
, "-A") == 0 ) {
3121 else if ( strcmp(arg
, "-umbrella") == 0 ) {
3122 const char* name
= argv
[++i
];
3124 throw "-umbrella missing argument";
3125 fUmbrellaName
= name
;
3126 cannotBeUsedWithBitcode(arg
);
3128 else if ( strcmp(arg
, "-allowable_client") == 0 ) {
3129 const char* name
= argv
[++i
];
3132 throw "-allowable_client missing argument";
3134 fAllowableClients
.push_back(name
);
3135 cannotBeUsedWithBitcode(arg
);
3137 else if ( strcmp(arg
, "-client_name") == 0 ) {
3138 const char* name
= argv
[++i
];
3141 throw "-client_name missing argument";
3144 cannotBeUsedWithBitcode(arg
);
3146 else if ( strcmp(arg
, "-sub_umbrella") == 0 ) {
3147 const char* name
= argv
[++i
];
3149 throw "-sub_umbrella missing argument";
3150 fSubUmbellas
.push_back(name
);
3151 cannotBeUsedWithBitcode(arg
);
3153 else if ( strcmp(arg
, "-sub_library") == 0 ) {
3154 const char* name
= argv
[++i
];
3156 throw "-sub_library missing argument";
3157 fSubLibraries
.push_back(name
);
3158 cannotBeUsedWithBitcode(arg
);
3160 else if ( strcmp(arg
, "-init") == 0 ) {
3161 const char* name
= argv
[++i
];
3163 throw "-init missing argument";
3164 fInitFunctionName
= name
;
3165 cannotBeUsedWithBitcode(arg
);
3167 else if ( strcmp(arg
, "-dot") == 0 ) {
3168 const char* name
= argv
[++i
];
3170 throw "-dot missing argument";
3171 fDotOutputFile
= name
;
3172 cannotBeUsedWithBitcode(arg
);
3174 else if ( strcmp(arg
, "-warn_commons") == 0 ) {
3175 fWarnCommons
= true;
3177 else if ( strcmp(arg
, "-commons") == 0 ) {
3178 fCommonsMode
= parseCommonsTreatment(argv
[++i
]);
3180 else if ( strcmp(arg
, "-keep_relocs") == 0 ) {
3181 fKeepRelocations
= true;
3183 else if ( strcmp(arg
, "-warn_stabs") == 0 ) {
3186 else if ( strcmp(arg
, "-pause") == 0 ) {
3189 else if ( strcmp(arg
, "-print_statistics") == 0 ) {
3192 else if ( strcmp(arg
, "-d") == 0 ) {
3193 fMakeTentativeDefinitionsReal
= true;
3195 else if ( strcmp(arg
, "-v") == 0 ) {
3196 // previously handled by buildSearchPaths()
3198 else if ( strcmp(arg
, "-Z") == 0 ) {
3199 // previously handled by buildSearchPaths()
3201 else if ( strcmp(arg
, "-syslibroot") == 0 ) {
3202 snapshotArgCount
= 0;
3204 // previously handled by buildSearchPaths()
3206 else if ( strcmp(arg
, "-bitcode_bundle") == 0 ) {
3207 snapshotArgCount
= 0;
3208 // previously handled by buildSearchPaths()
3210 else if ( strcmp(arg
, "-no_uuid") == 0 ) {
3211 fUUIDMode
= kUUIDNone
;
3212 cannotBeUsedWithBitcode(arg
);
3214 else if ( strcmp(arg
, "-random_uuid") == 0 ) {
3215 fUUIDMode
= kUUIDRandom
;
3216 cannotBeUsedWithBitcode(arg
);
3218 else if ( strcmp(arg
, "-dtrace") == 0 ) {
3219 snapshotFileArgIndex
= 1;
3220 const char* name
= argv
[++i
];
3222 throw "-dtrace missing argument";
3223 fDtraceScriptName
= name
;
3224 cannotBeUsedWithBitcode(arg
);
3226 else if ( strcmp(arg
, "-root_safe") == 0 ) {
3229 else if ( strcmp(arg
, "-setuid_safe") == 0 ) {
3232 else if ( strcmp(arg
, "-alias") == 0 ) {
3233 Options::AliasPair pair
;
3234 pair
.realName
= argv
[++i
];
3235 if ( pair
.realName
== NULL
)
3236 throw "missing argument to -alias";
3237 pair
.alias
= argv
[++i
];
3238 if ( pair
.alias
== NULL
)
3239 throw "missing argument to -alias";
3240 fAliases
.push_back(pair
);
3241 cannotBeUsedWithBitcode(arg
);
3243 else if ( strcmp(arg
, "-alias_list") == 0 ) {
3244 snapshotFileArgIndex
= 1;
3245 parseAliasFile(argv
[++i
]);
3246 cannotBeUsedWithBitcode(arg
);
3248 else if ( strcmp(arg
, "-save-temps") == 0 ) {
3249 fSaveTempFiles
= true;
3251 else if ( strcmp(arg
, "-bitcode_hide_symbols") == 0 ) {
3252 fHideSymbols
= true;
3254 else if ( strcmp(arg
, "-bitcode_verify") == 0 ) {
3255 fVerifyBitcode
= true;
3257 else if ( strcmp(arg
, "-bitcode_symbol_map") == 0) {
3258 fReverseMapPath
= argv
[++i
];
3259 if ( fReverseMapPath
== NULL
)
3260 throw "missing argument to -bitcode_symbol_map";
3261 struct stat statbuf
;
3262 ::stat(fReverseMapPath
, &statbuf
);
3263 if (S_ISDIR(statbuf
.st_mode
)) {
3264 char tempPath
[PATH_MAX
];
3265 sprintf(tempPath
, "%s/XXXXXX", fReverseMapPath
);
3266 int tempFile
= ::mkstemp(tempPath
);
3268 throwf("could not write file to symbol map directory: %s", fReverseMapPath
);
3270 fReverseMapTempPath
= std::string(tempPath
);
3271 fReverseMapUUIDRename
= true;
3273 fReverseMapTempPath
= std::string(fReverseMapPath
);
3275 else if ( strcmp(argv
[i
], "-flto-codegen-only") == 0) {
3276 fLTOCodegenOnly
= true;
3278 else if ( strcmp(argv
[i
], "-ignore_auto_link") == 0) {
3279 fIgnoreAutoLink
= true;
3281 else if ( strcmp(argv
[i
], "-allow_dead_duplicates") == 0) {
3282 fAllowDeadDups
= true;
3284 else if ( strcmp(argv
[i
], "-bitcode_process_mode") == 0 ) {
3285 const char* bitcode_type
= argv
[++i
];
3286 if ( bitcode_type
== NULL
)
3287 throw "missing argument to -bitcode_process_mode";
3288 else if ( strcmp(bitcode_type
, "strip") == 0 )
3289 fBitcodeKind
= kBitcodeStrip
;
3290 else if ( strcmp(bitcode_type
, "marker") == 0 )
3291 fBitcodeKind
= kBitcodeMarker
;
3292 else if ( strcmp(bitcode_type
, "data") == 0 )
3293 fBitcodeKind
= kBitcodeAsData
;
3294 else if ( strcmp(bitcode_type
, "bitcode") == 0 )
3295 fBitcodeKind
= kBitcodeProcess
;
3297 throw "unknown argument to -bitcode_process_mode {strip,marker,data,bitcode}";
3299 else if ( strcmp(arg
, "-rpath") == 0 ) {
3300 const char* path
= argv
[++i
];
3302 throw "missing argument to -rpath";
3303 fRPaths
.push_back(path
);
3305 else if ( strcmp(arg
, "-read_only_stubs") == 0 ) {
3306 fReadOnlyx86Stubs
= true;
3308 else if ( strcmp(arg
, "-slow_stubs") == 0 ) {
3311 else if ( strcmp(arg
, "-map") == 0 ) {
3312 fMapPath
= argv
[++i
];
3313 if ( fMapPath
== NULL
)
3314 throw "missing argument to -map";
3316 else if ( strcmp(arg
, "-pie") == 0 ) {
3317 fPositionIndependentExecutable
= true;
3318 fPIEOnCommandLine
= true;
3320 else if ( strcmp(arg
, "-no_pie") == 0 ) {
3321 fDisablePositionIndependentExecutable
= true;
3322 cannotBeUsedWithBitcode(arg
);
3324 else if ( strncmp(arg
, "-reexport-l", 11) == 0 ) {
3325 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3326 snapshotArgCount
= 0;
3327 FileInfo info
= findLibrary(&arg
[11], true);
3328 info
.options
.fReExport
= true;
3329 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3331 cannotBeUsedWithBitcode(arg
);
3333 else if ( strcmp(arg
, "-reexport_library") == 0 ) {
3334 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3335 snapshotArgCount
= 0;
3336 FileInfo info
= findFile(argv
[++i
]);
3337 info
.options
.fReExport
= true;
3338 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3340 cannotBeUsedWithBitcode(arg
);
3342 else if ( strcmp(arg
, "-reexport_framework") == 0 ) {
3343 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3344 snapshotArgCount
= 0;
3345 FileInfo info
= findFramework(argv
[++i
]);
3346 info
.options
.fReExport
= true;
3347 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3349 cannotBeUsedWithBitcode(arg
);
3351 else if ( strncmp(arg
, "-upward-l", 9) == 0 ) {
3352 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3353 snapshotArgCount
= 0;
3354 FileInfo info
= findLibrary(&arg
[9], true);
3355 info
.options
.fUpward
= true;
3356 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3358 cannotBeUsedWithBitcode(arg
);
3360 else if ( strcmp(arg
, "-upward_library") == 0 ) {
3361 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3362 snapshotArgCount
= 0;
3363 FileInfo info
= findFile(argv
[++i
]);
3364 info
.options
.fUpward
= true;
3365 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3367 cannotBeUsedWithBitcode(arg
);
3369 else if ( strcmp(arg
, "-upward_framework") == 0 ) {
3370 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3371 snapshotArgCount
= 0;
3372 FileInfo info
= findFramework(argv
[++i
]);
3373 info
.options
.fUpward
= true;
3374 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3376 cannotBeUsedWithBitcode(arg
);
3378 else if ( strcmp(arg
, "-dead_strip_dylibs") == 0 ) {
3379 fDeadStripDylibs
= true;
3380 cannotBeUsedWithBitcode(arg
);
3382 else if ( strcmp(arg
, "-no_implicit_dylibs") == 0 ) {
3383 fImplicitlyLinkPublicDylibs
= false;
3385 else if ( strcmp(arg
, "-new_linker") == 0 ) {
3388 else if ( strcmp(arg
, "-no_encryption") == 0 ) {
3389 fEncryptableForceOff
= true;
3390 cannotBeUsedWithBitcode(arg
);
3392 else if ( strcmp(arg
, "-encryptable") == 0 ) {
3393 fEncryptableForceOn
= true;
3394 cannotBeUsedWithBitcode(arg
);
3396 else if ( strcmp(arg
, "-no_compact_unwind") == 0 ) {
3397 fAddCompactUnwindEncoding
= false;
3398 cannotBeUsedWithBitcode(arg
);
3400 else if ( strcmp(arg
, "-mllvm") == 0 ) {
3401 const char* opts
= argv
[++i
];
3403 throw "missing argument to -mllvm";
3404 fLLVMOptions
.push_back(opts
);
3405 cannotBeUsedWithBitcode(arg
);
3407 else if ( strcmp(arg
, "-mcpu") == 0 ) {
3408 const char* cpu
= argv
[++i
];
3410 throw "missing argument to -mcpu";
3412 cannotBeUsedWithBitcode(arg
);
3414 else if ( strcmp(arg
, "-no_order_inits") == 0 ) {
3415 fAutoOrderInitializers
= false;
3416 cannotBeUsedWithBitcode(arg
);
3418 else if ( strcmp(arg
, "-no_order_data") == 0 ) {
3420 cannotBeUsedWithBitcode(arg
);
3422 else if ( strcmp(arg
, "-seg_page_size") == 0 ) {
3424 seg
.name
= argv
[++i
];
3425 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
3426 throw "-seg_page_size missing segName Adddress";
3427 seg
.size
= parseAddress(argv
[++i
]);
3428 uint64_t temp
= seg
.size
& (-4096); // page align
3429 if ( (seg
.size
!= temp
) )
3430 warning("-seg_page_size %s not 4K aligned, rounding down", seg
.name
);
3431 fCustomSegmentSizes
.push_back(seg
);
3432 cannotBeUsedWithBitcode(arg
);
3434 else if ( strcmp(arg
, "-mark_dead_strippable_dylib") == 0 ) {
3435 fMarkDeadStrippableDylib
= true;
3436 cannotBeUsedWithBitcode(arg
);
3438 else if ( strcmp(arg
, "-exported_symbols_order") == 0 ) {
3439 snapshotFileArgIndex
= 1;
3440 loadSymbolOrderFile(argv
[++i
], fExportSymbolsOrder
);
3441 cannotBeUsedWithBitcode(arg
);
3443 else if ( strcmp(arg
, "-no_compact_linkedit") == 0 ) {
3444 warnObsolete("-no_compact_linkedit");
3446 else if ( strcmp(arg
, "-no_eh_labels") == 0 ) {
3448 cannotBeUsedWithBitcode(arg
);
3450 else if ( strcmp(arg
, "-warn_compact_unwind") == 0 ) {
3451 fWarnCompactUnwind
= true;
3453 else if ( strcmp(arg
, "-allow_sub_type_mismatches") == 0 ) {
3454 fAllowCpuSubtypeMismatches
= true;
3455 cannotBeUsedWithBitcode(arg
);
3457 else if ( strcmp(arg
, "-no_zero_fill_sections") == 0 ) {
3458 fOptimizeZeroFill
= false;
3459 cannotBeUsedWithBitcode(arg
);
3461 else if ( strcmp(arg
, "-merge_zero_fill_sections") == 0 ) {
3462 fMergeZeroFill
= true;
3463 cannotBeUsedWithBitcode(arg
);
3465 else if ( strcmp(arg
, "-objc_abi_version") == 0 ) {
3466 const char* version
= argv
[++i
];
3467 if ( version
== NULL
)
3468 throw "-objc_abi_version missing version number";
3469 if ( strcmp(version
, "2") == 0 ) {
3470 fObjCABIVersion1Override
= false;
3471 fObjCABIVersion2Override
= true;
3473 else if ( strcmp(version
, "1") == 0 ) {
3474 fObjCABIVersion1Override
= true;
3475 fObjCABIVersion2Override
= false;
3478 warning("ignoring unrecognized argument (%s) to -objc_abi_version", version
);
3480 else if ( strcmp(arg
, "-warn_weak_exports") == 0 ) {
3481 fWarnWeakExports
= true;
3483 else if ( strcmp(arg
, "-objc_gc_compaction") == 0 ) {
3484 fObjcGcCompaction
= true;
3485 cannotBeUsedWithBitcode(arg
);
3487 else if ( strcmp(arg
, "-objc_gc") == 0 ) {
3489 if ( fObjCGcOnly
) {
3490 warning("-objc_gc overriding -objc_gc_only");
3491 fObjCGcOnly
= false;
3493 cannotBeUsedWithBitcode(arg
);
3495 else if ( strcmp(arg
, "-objc_gc_only") == 0 ) {
3498 warning("-objc_gc_only overriding -objc_gc");
3501 cannotBeUsedWithBitcode(arg
);
3503 else if ( strcmp(arg
, "-demangle") == 0 ) {
3506 else if ( strcmp(arg
, "-version_load_command") == 0 ) {
3507 fVersionLoadCommandForcedOn
= true;
3508 fVersionLoadCommandForcedOff
= false;
3510 else if ( strcmp(arg
, "-no_version_load_command") == 0 ) {
3511 fVersionLoadCommandForcedOff
= true;
3512 fVersionLoadCommandForcedOn
= false;
3513 cannotBeUsedWithBitcode(arg
);
3515 else if ( strcmp(arg
, "-function_starts") == 0 ) {
3516 fFunctionStartsForcedOn
= true;
3517 fFunctionStartsForcedOff
= false;
3519 else if ( strcmp(arg
, "-no_function_starts") == 0 ) {
3520 fFunctionStartsForcedOff
= true;
3521 fFunctionStartsForcedOn
= false;
3522 cannotBeUsedWithBitcode(arg
);
3524 else if ( strcmp(arg
, "-no_data_in_code_info") == 0 ) {
3525 fDataInCodeInfoLoadCommandForcedOff
= true;
3526 fDataInCodeInfoLoadCommandForcedOn
= false;
3527 cannotBeUsedWithBitcode(arg
);
3529 else if ( strcmp(arg
, "-data_in_code_info") == 0 ) {
3530 fDataInCodeInfoLoadCommandForcedOn
= true;
3531 fDataInCodeInfoLoadCommandForcedOff
= false;
3533 else if ( strcmp(arg
, "-object_path_lto") == 0 ) {
3534 fTempLtoObjectPath
= argv
[++i
];
3535 if ( fTempLtoObjectPath
== NULL
)
3536 throw "missing argument to -object_path_lto";
3538 else if ( strcmp(arg
, "-no_objc_category_merging") == 0 ) {
3539 fObjcCategoryMerging
= false;
3541 else if ( strcmp(arg
, "-force_symbols_weak_list") == 0 ) {
3542 snapshotFileArgIndex
= 1;
3543 loadExportFile(argv
[++i
], "-force_symbols_weak_list", fForceWeakSymbols
);
3544 cannotBeUsedWithBitcode(arg
);
3546 else if ( strcmp(arg
, "-force_symbols_not_weak_list") == 0 ) {
3547 snapshotFileArgIndex
= 1;
3548 loadExportFile(argv
[++i
], "-force_symbols_not_weak_list", fForceNotWeakSymbols
);
3549 cannotBeUsedWithBitcode(arg
);
3551 else if ( strcmp(arg
, "-force_symbol_weak") == 0 ) {
3552 const char* symbol
= argv
[++i
];
3553 if ( symbol
== NULL
)
3554 throw "-force_symbol_weak missing <symbol>";
3555 fForceWeakSymbols
.insert(symbol
);
3556 cannotBeUsedWithBitcode(arg
);
3558 else if ( strcmp(arg
, "-force_symbol_not_weak") == 0 ) {
3559 const char* symbol
= argv
[++i
];
3560 if ( symbol
== NULL
)
3561 throw "-force_symbol_not_weak missing <symbol>";
3562 fForceNotWeakSymbols
.insert(symbol
);
3563 cannotBeUsedWithBitcode(arg
);
3565 else if ( strcmp(arg
, "-reexported_symbols_list") == 0 ) {
3566 snapshotFileArgIndex
= 1;
3567 if ( fExportMode
== kExportSome
)
3568 throw "can't use -exported_symbols_list and -reexported_symbols_list";
3569 loadExportFile(argv
[++i
], "-reexported_symbols_list", fReExportSymbols
);
3571 else if ( strcmp(arg
, "-dyld_env") == 0 ) {
3572 const char* envarg
= argv
[++i
];
3573 if ( envarg
== NULL
)
3574 throw "-dyld_env missing ENV=VALUE";
3575 if ( strchr(envarg
, '=') == NULL
)
3576 throw "-dyld_env missing ENV=VALUE";
3577 fDyldEnvironExtras
.push_back(envarg
);
3578 cannotBeUsedWithBitcode(arg
);
3580 else if ( strcmp(arg
, "-page_align_data_atoms") == 0 ) {
3581 fPageAlignDataAtoms
= true;
3582 cannotBeUsedWithBitcode(arg
);
3584 else if (strcmp(arg
, "-debug_snapshot") == 0) {
3585 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
3586 fSnapshotRequested
= true;
3587 cannotBeUsedWithBitcode(arg
);
3589 else if (strcmp(arg
, "-snapshot_dir") == 0) {
3590 const char* path
= argv
[++i
];
3592 throw "-snapshot_dir missing path";
3593 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
3594 fLinkSnapshot
.setSnapshotPath(path
);
3595 fSnapshotRequested
= true;
3596 cannotBeUsedWithBitcode(arg
);
3598 else if ( strcmp(arg
, "-new_main") == 0 ) {
3599 fEntryPointLoadCommandForceOn
= true;
3600 cannotBeUsedWithBitcode(arg
);
3602 else if ( strcmp(arg
, "-no_new_main") == 0 ) {
3603 fEntryPointLoadCommandForceOff
= true;
3604 cannotBeUsedWithBitcode(arg
);
3606 else if ( strcmp(arg
, "-source_version") == 0 ) {
3607 const char* vers
= argv
[++i
];
3609 throw "-source_version missing <version>";
3610 fSourceVersion
= parseVersionNumber64(vers
);
3612 else if ( strcmp(arg
, "-add_source_version") == 0 ) {
3613 fSourceVersionLoadCommandForceOn
= true;
3615 else if ( strcmp(arg
, "-no_source_version") == 0 ) {
3616 fSourceVersionLoadCommandForceOff
= true;
3617 cannotBeUsedWithBitcode(arg
);
3619 else if ( strcmp(arg
, "-sdk_version") == 0 ) {
3620 const char* vers
= argv
[++i
];
3622 throw "-sdk_version missing <version>";
3623 fSDKVersion
= parseVersionNumber32(vers
);
3625 else if ( strcmp(arg
, "-dependent_dr_info") == 0 ) {
3628 else if ( strcmp(arg
, "-no_dependent_dr_info") == 0 ) {
3631 else if ( strcmp(arg
, "-kexts_use_stubs") == 0 ) {
3632 fKextsUseStubs
= true;
3633 cannotBeUsedWithBitcode(arg
);
3635 else if ( strcmp(argv
[i
], "-dependency_info") == 0 ) {
3636 snapshotArgCount
= 0;
3638 // previously handled by buildSearchPaths()
3640 else if ( strcmp(arg
, "-export_dynamic") == 0 ) {
3641 fExportDynamic
= true;
3643 else if ( strcmp(arg
, "-force_symbols_coalesce_list") == 0 ) {
3644 snapshotFileArgIndex
= 1;
3645 loadExportFile(argv
[++i
], "-force_symbols_coalesce_list", fForceCoalesceSymbols
);
3647 else if ( strcmp(arg
, "-add_linker_option") == 0 ) {
3648 // ex: -add_linker_option '-framework Foundation'
3649 const char* optString
= argv
[++i
];
3650 if ( optString
== NULL
)
3651 throw "-add_linker_option missing <option>";
3652 // break up into list of tokens at whitespace
3653 std::vector
<const char*> opts
;
3654 char* buffer
= strdup(optString
);
3655 char* start
= buffer
;
3656 for (char* s
= buffer
; ; ++s
) {
3657 if ( isspace(*s
) ) {
3659 opts
.push_back(start
);
3662 else if ( *s
== '\0' ) {
3663 opts
.push_back(start
);
3667 fLinkerOptions
.push_back(opts
);
3668 cannotBeUsedWithBitcode(arg
);
3670 else if ( strcmp(arg
, "-allow_simulator_linking_to_macosx_dylibs") == 0 ) {
3671 fAllowSimulatorToLinkWithMacOSX
= true;
3672 cannotBeUsedWithBitcode(arg
);
3674 else if ( strcmp(arg
, "-keep_dwarf_unwind") == 0 ) {
3675 fKeepDwarfUnwindForcedOn
= true;
3676 fKeepDwarfUnwindForcedOff
= false;
3677 cannotBeUsedWithBitcode(arg
);
3679 else if ( strcmp(arg
, "-no_keep_dwarf_unwind") == 0 ) {
3680 fKeepDwarfUnwindForcedOn
= false;
3681 fKeepDwarfUnwindForcedOff
= true;
3682 cannotBeUsedWithBitcode(arg
);
3684 else if ( strcmp(arg
, "-verbose_optimization_hints") == 0 ) {
3685 fVerboseOptimizationHints
= true;
3687 else if ( strcmp(arg
, "-ignore_optimization_hints") == 0 ) {
3688 fIgnoreOptimizationHints
= true;
3689 cannotBeUsedWithBitcode(arg
);
3691 else if ( strcmp(arg
, "-no_dtrace_dof") == 0 ) {
3692 fGenerateDtraceDOF
= false;
3694 else if ( strcmp(arg
, "-rename_section") == 0 ) {
3695 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) || (argv
[i
+4]==NULL
) )
3696 throw "-rename_section missing <segment> <section> <segment> <section>";
3697 addSectionRename(argv
[i
+1], argv
[i
+2], argv
[i
+3], argv
[i
+4]);
3699 cannotBeUsedWithBitcode(arg
);
3701 else if ( strcmp(arg
, "-rename_segment") == 0 ) {
3702 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3703 throw "-rename_segment missing <existing-segment> <new-segment>";
3704 addSegmentRename(argv
[i
+1], argv
[i
+2]);
3706 cannotBeUsedWithBitcode(arg
);
3708 else if ( strcmp(arg
, "-move_to_ro_segment") == 0 ) {
3709 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3710 throw "-move_to_ro_segment missing <segment> <symbol-list-file>";
3711 addSymbolMove(argv
[i
+1], argv
[i
+2], fSymbolsMovesCode
, "-move_to_ro_segment");
3713 cannotBeUsedWithBitcode(arg
);
3715 else if ( strcmp(arg
, "-move_to_rw_segment") == 0 ) {
3716 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3717 throw "-move_to_rw_segment missing <segment> <symbol-list-file>";
3718 addSymbolMove(argv
[i
+1], argv
[i
+2], fSymbolsMovesData
, "-move_to_rw_segment");
3720 cannotBeUsedWithBitcode(arg
);
3722 else if ( strcmp(arg
, "-trace_symbol_layout") == 0 ) {
3723 fTraceSymbolLayout
= true;
3725 else if ( strcmp(arg
, "-no_branch_islands") == 0 ) {
3726 fAllowBranchIslands
= false;
3727 cannotBeUsedWithBitcode(arg
);
3729 else if ( strcmp(arg
, "-segment_order") == 0 ) {
3730 // ex: -segment_order __TEXT:__DATA:__JUNK
3731 const char* optString
= argv
[++i
];
3732 if ( optString
== NULL
)
3733 throw "-segment_order missing colon separated <segment-list>";
3734 if ( !fSegmentOrder
.empty() )
3735 throw "-segment_order used more than once";
3736 // break up into list of tokens at colon
3737 char* buffer
= strdup(optString
);
3738 char* start
= buffer
;
3739 for (char* s
= buffer
; ; ++s
) {
3742 fSegmentOrder
.push_back(start
);
3745 else if ( *s
== '\0' ) {
3746 fSegmentOrder
.push_back(start
);
3750 cannotBeUsedWithBitcode(arg
);
3752 else if ( strcmp(arg
, "-section_order") == 0 ) {
3753 // ex: -section_order __DATA __data:__const:__nl_pointers
3754 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) )
3755 throw "-section_order missing <segment> <section-list>";
3756 const char* segName
= argv
[++i
];
3757 const char* optString
= argv
[++i
];
3758 if ( sectionOrder(segName
) != NULL
)
3759 throwf("-section_order %s ... used more than once", segName
);
3760 SectionOrderList dummy
;
3761 fSectionOrder
.push_back(dummy
);
3762 SectionOrderList
& entry
= fSectionOrder
.back();
3763 entry
.segmentName
= segName
;
3764 // break up into list of tokens at colon
3765 char* buffer
= strdup(optString
);
3766 char* start
= buffer
;
3767 for (char* s
= buffer
; ; ++s
) {
3770 entry
.sectionOrder
.push_back(start
);
3773 else if ( *s
== '\0' ) {
3774 entry
.sectionOrder
.push_back(start
);
3778 cannotBeUsedWithBitcode(arg
);
3780 else if ( strcmp(arg
, "-application_extension") == 0 ) {
3781 fMarkAppExtensionSafe
= true;
3782 fCheckAppExtensionSafe
= true;
3784 else if ( strcmp(arg
, "-no_application_extension") == 0 ) {
3785 fMarkAppExtensionSafe
= false;
3786 fCheckAppExtensionSafe
= false;
3788 else if ( strcmp(arg
, "-add_ast_path") == 0 ) {
3789 const char* path
= argv
[++i
];
3791 throw "-add_ast_path missing <option>";
3792 fASTFilePaths
.push_back(path
);
3794 else if ( strcmp(arg
, "-force_load_swift_libs") == 0 ) {
3795 fForceLoadSwiftLibs
= true;
3797 else if ( strcmp(arg
, "-not_for_dyld_shared_cache") == 0 ) {
3798 fSharedRegionEligibleForceOff
= true;
3799 cannotBeUsedWithBitcode(arg
);
3801 else if ( strcmp(arg
, "-dirty_data_list") == 0 ) {
3802 if ( argv
[i
+1] == NULL
)
3803 throw "-dirty_data_list missing <symbol-list-file>";
3804 addSymbolMove("__DATA_DIRTY", argv
[i
+1], fSymbolsMovesData
, "-dirty_data_list");
3806 cannotBeUsedWithBitcode(arg
);
3808 else if ( strcmp(arg
, "-data_const") == 0 ) {
3809 fUseDataConstSegmentForceOn
= true;
3810 cannotBeUsedWithBitcode(arg
);
3812 else if ( strcmp(arg
, "-no_data_const") == 0 ) {
3813 fUseDataConstSegmentForceOff
= true;
3814 cannotBeUsedWithBitcode(arg
);
3816 else if ( strcmp(arg
, "-text_exec") == 0 ) {
3817 fUseTextExecSegment
= true;
3818 cannotBeUsedWithBitcode(arg
);
3820 else if ( strcmp(arg
, "-add_split_seg_info") == 0) {
3821 fSharedRegionEligible
= true;
3822 cannotBeUsedWithBitcode(arg
);
3824 else if ( strcmp(arg
, "-no_deduplicate") == 0 ) {
3827 else if ( strcmp(arg
, "-verbose_deduplicate") == 0 ) {
3828 fVerboseDeDupe
= true;
3830 else if ( strcmp(arg
, "-max_default_common_align") == 0 ) {
3831 const char* alignStr
= argv
[++i
];
3832 if ( alignStr
== NULL
)
3833 throw "-max_default_common_align missing <align-value>";
3834 // argument is a hexadecimal number
3836 unsigned long value
= strtoul(alignStr
, &endptr
, 16);
3837 if ( *endptr
!= '\0')
3838 throw "argument for -max_default_common_align is not a hexadecimal number";
3839 if ( value
> 0x8000 )
3840 throw "argument for -max_default_common_align must be less than or equal to 0x8000";
3842 warning("zero is not a valid -max_default_common_align");
3845 // alignment is power of 2
3846 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
3847 if ( (unsigned long)(1 << alignment
) != value
) {
3848 warning("alignment for -max_default_common_align is not a power of two, using 0x%X", 1 << alignment
);
3850 fMaxDefaultCommonAlign
= alignment
;
3852 else if ( strcmp(argv
[i
], "-no_weak_imports") == 0 ) {
3853 fAllowWeakImports
= false;
3855 // put this last so that it does not interfer with other options starting with 'i'
3856 else if ( strncmp(arg
, "-i", 2) == 0 ) {
3857 const char* colon
= strchr(arg
, ':');
3858 if ( colon
== NULL
)
3859 throwf("unknown option: %s", arg
);
3860 Options::AliasPair pair
;
3861 char* temp
= new char[colon
-arg
];
3862 strlcpy(temp
, &arg
[2], colon
-arg
-1);
3863 pair
.realName
= &colon
[1];
3865 fAliases
.push_back(pair
);
3868 throwf("unknown option: %s", arg
);
3871 if (snapshotArgCount
== -1)
3872 snapshotArgCount
= i
-snapshotArgIndex
+1;
3873 if (snapshotArgCount
> 0)
3874 fLinkSnapshot
.addSnapshotLinkArg(snapshotArgIndex
, snapshotArgCount
, snapshotFileArgIndex
);
3877 FileInfo info
= findFile(arg
);
3878 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
3879 if ( strcmp(&info
.path
[strlen(info
.path
)-2], ".a") == 0 )
3882 fInputFiles
.push_back(info
);
3886 // if a -lazy option was used, implicitly link in lazydylib1.o
3887 if ( fUsingLazyDylibLinking
) {
3888 FileInfo info
= findLibrary("lazydylib1.o");
3889 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)argc
);
3893 if (fSnapshotRequested
)
3894 fLinkSnapshot
.createSnapshot();
3900 // -syslibroot <path> is used for SDK support.
3901 // The rule is that all search paths (both explicit and default) are
3902 // checked to see if they exist in the SDK. If so, that path is
3903 // replaced with the sdk prefixed path. If not, that search path
3904 // is used as is. If multiple -syslibroot options are specified
3905 // their directory structures are logically overlayed and files
3906 // from sdks specified earlier on the command line used before later ones.
3908 void Options::buildSearchPaths(int argc
, const char* argv
[])
3910 bool addStandardLibraryDirectories
= true;
3911 std::vector
<const char*> libraryPaths
;
3912 std::vector
<const char*> frameworkPaths
;
3913 libraryPaths
.reserve(10);
3914 frameworkPaths
.reserve(10);
3915 // scan through argv looking for -L, -F, -Z, and -syslibroot options
3916 for(int i
=0; i
< argc
; ++i
) {
3917 if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'L') ) {
3918 const char* libSearchDir
= &argv
[i
][2];
3919 // Allow either "-L{path}" or "-L {path}".
3920 if (argv
[i
][2] == '\0') {
3921 // -L {path}. Make sure there is an argument following this.
3922 const char* path
= argv
[++i
];
3924 throw "-L missing argument";
3925 libSearchDir
= path
;
3927 if ( libSearchDir
[0] == '\0' )
3928 throw "-L must be immediately followed by a directory path (no space)";
3929 libraryPaths
.push_back(libSearchDir
);
3931 else if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'F') ) {
3932 const char* frameworkSearchDir
= &argv
[i
][2];
3933 // Allow either "-F{path}" or "-F {path}".
3934 if (argv
[i
][2] == '\0') {
3935 // -F {path}. Make sure there is an argument following this.
3936 const char* path
= argv
[++i
];
3938 throw "-F missing argument";
3939 frameworkSearchDir
= path
;
3941 if ( frameworkSearchDir
[0] == '\0' )
3942 throw "-F must be immediately followed by a directory path (no space)";
3943 frameworkPaths
.push_back(frameworkSearchDir
);
3945 else if ( strcmp(argv
[i
], "-Z") == 0 )
3946 addStandardLibraryDirectories
= false;
3947 else if ( strcmp(argv
[i
], "-v") == 0 ) {
3949 extern const char ldVersionString
[];
3950 fprintf(stderr
, "%s", ldVersionString
);
3951 fprintf(stderr
, "configured to support archs: %s\n", ALL_SUPPORTED_ARCHS
);
3952 // if only -v specified, exit cleanly
3954 const char* ltoVers
= lto::version();
3955 if ( ltoVers
!= NULL
)
3956 fprintf(stderr
, "LTO support using: %s\n", ltoVers
);
3957 fprintf(stderr
, "TAPI support using: %s\n", tapi::Version::getFullVersionAsString().c_str());
3961 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
3962 const char* path
= argv
[++i
];
3964 throw "-syslibroot missing argument";
3965 fSDKPaths
.push_back(path
);
3967 else if ( strcmp(argv
[i
], "-search_paths_first") == 0 ) {
3968 fLibrarySearchMode
= kSearchDylibAndArchiveInEachDir
;
3970 else if ( strcmp(argv
[i
], "-search_dylibs_first") == 0 ) {
3971 fLibrarySearchMode
= kSearchAllDirsForDylibsThenAllDirsForArchives
;
3973 else if ( strcmp(argv
[i
], "-w") == 0 ) {
3974 sEmitWarnings
= false;
3976 else if ( strcmp(argv
[i
], "-fatal_warnings") == 0 ) {
3977 sFatalWarnings
= true;
3979 else if ( strcmp(argv
[i
], "-dependency_info") == 0 ) {
3980 const char* path
= argv
[++i
];
3982 throw "-dependency_info missing <path>";
3983 fDependencyInfoPath
= path
;
3985 else if ( strcmp(argv
[i
], "-bitcode_bundle") == 0 ) {
3986 fBundleBitcode
= true;
3989 int standardLibraryPathsStartIndex
= libraryPaths
.size();
3990 int standardFrameworkPathsStartIndex
= frameworkPaths
.size();
3991 if ( addStandardLibraryDirectories
) {
3992 libraryPaths
.push_back("/usr/lib");
3993 libraryPaths
.push_back("/usr/local/lib");
3995 frameworkPaths
.push_back("/Library/Frameworks/");
3996 frameworkPaths
.push_back("/System/Library/Frameworks/");
3997 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
4000 // <rdar://problem/5829579> Support for configure based hacks
4001 // if last -syslibroot is /, then ignore all syslibroots
4002 if ( fSDKPaths
.size() > 0 ) {
4003 if ( strcmp(fSDKPaths
.back(), "/") == 0 ) {
4008 // now merge sdk and library paths to make real search paths
4009 fLibrarySearchPaths
.reserve(libraryPaths
.size()*(fSDKPaths
.size()+1));
4011 for (std::vector
<const char*>::iterator it
= libraryPaths
.begin(); it
!= libraryPaths
.end(); ++it
, ++libIndex
) {
4012 const char* libDir
= *it
;
4013 bool sdkOverride
= false;
4014 if ( libDir
[0] == '/' ) {
4015 char betterLibDir
[PATH_MAX
];
4016 if ( strstr(libDir
, "/..") != NULL
) {
4017 if ( realpath(libDir
, betterLibDir
) != NULL
)
4018 libDir
= strdup(betterLibDir
);
4020 const int libDirLen
= strlen(libDir
);
4021 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
4022 const char* sdkDir
= *sdkit
;
4023 const int sdkDirLen
= strlen(sdkDir
);
4024 char newPath
[libDirLen
+ sdkDirLen
+4];
4025 strcpy(newPath
, sdkDir
);
4026 if ( newPath
[sdkDirLen
-1] == '/' )
4027 newPath
[sdkDirLen
-1] = '\0';
4028 strcat(newPath
, libDir
);
4029 struct stat statBuffer
;
4030 if ( stat(newPath
, &statBuffer
) == 0 ) {
4031 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 ) {
4032 warning("-syslibroot and -L combined path '%s' is not a directory", newPath
);
4035 fLibrarySearchPaths
.push_back(strdup(newPath
));
4041 if ( !sdkOverride
) {
4042 if ( (libIndex
>= standardLibraryPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
4043 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
4044 // if one SDK is specified and a standard library path is not in the SDK, don't use it
4047 struct stat statBuffer
;
4048 if ( stat(libDir
, &statBuffer
) == 0 ) {
4049 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 )
4050 warning("-L path '%s' is not a directory", libDir
);
4052 fLibrarySearchPaths
.push_back(libDir
);
4054 else if ( !addStandardLibraryDirectories
|| (strcmp(libDir
, "/usr/local/lib") != 0) ) {
4055 warning("directory not found for option '-L%s'", libDir
);
4062 // now merge sdk and framework paths to make real search paths
4063 fFrameworkSearchPaths
.reserve(frameworkPaths
.size()*(fSDKPaths
.size()+1));
4065 for (std::vector
<const char*>::iterator it
= frameworkPaths
.begin(); it
!= frameworkPaths
.end(); ++it
, ++frameIndex
) {
4066 const char* frameworkDir
= *it
;
4067 bool sdkOverride
= false;
4068 if ( frameworkDir
[0] == '/' ) {
4069 char betterFrameworkDir
[PATH_MAX
];
4070 if ( strstr(frameworkDir
, "/..") != NULL
) {
4071 if ( realpath(frameworkDir
, betterFrameworkDir
) != NULL
)
4072 frameworkDir
= strdup(betterFrameworkDir
);
4074 const int frameworkDirLen
= strlen(frameworkDir
);
4075 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
4076 const char* sdkDir
= *sdkit
;
4077 const int sdkDirLen
= strlen(sdkDir
);
4078 char newPath
[frameworkDirLen
+ sdkDirLen
+4];
4079 strcpy(newPath
, sdkDir
);
4080 if ( newPath
[sdkDirLen
-1] == '/' )
4081 newPath
[sdkDirLen
-1] = '\0';
4082 strcat(newPath
, frameworkDir
);
4083 struct stat statBuffer
;
4084 if ( stat(newPath
, &statBuffer
) == 0 ) {
4085 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 ) {
4086 warning("-syslibroot and -F combined path '%s' is not a directory", newPath
);
4089 fFrameworkSearchPaths
.push_back(strdup(newPath
));
4095 if ( !sdkOverride
) {
4096 if ( (frameIndex
>= standardFrameworkPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
4097 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
4098 // if one SDK is specified and a standard library path is not in the SDK, don't use it
4101 struct stat statBuffer
;
4102 if ( stat(frameworkDir
, &statBuffer
) == 0 ) {
4103 if ( (statBuffer
.st_mode
& S_IFDIR
) == 0 )
4104 warning("-F path '%s' is not a directory", frameworkDir
);
4106 fFrameworkSearchPaths
.push_back(frameworkDir
);
4108 else if ( !addStandardLibraryDirectories
|| (strcmp(frameworkDir
, "/Library/Frameworks/") != 0) ) {
4109 warning("directory not found for option '-F%s'", frameworkDir
);
4116 fprintf(stderr
,"Library search paths:\n");
4117 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
4118 it
!= fLibrarySearchPaths
.end();
4120 fprintf(stderr
,"\t%s\n", *it
);
4121 fprintf(stderr
,"Framework search paths:\n");
4122 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
4123 it
!= fFrameworkSearchPaths
.end();
4125 fprintf(stderr
,"\t%s\n", *it
);
4129 // this is run before the command line is parsed
4130 void Options::parsePreCommandLineEnvironmentSettings()
4132 if ((getenv("LD_TRACE_ARCHIVES") != NULL
)
4133 || (getenv("RC_TRACE_ARCHIVES") != NULL
))
4134 fTraceArchives
= true;
4136 if ((getenv("LD_TRACE_DYLIBS") != NULL
)
4137 || (getenv("RC_TRACE_DYLIBS") != NULL
)) {
4138 fTraceDylibs
= true;
4139 fTraceIndirectDylibs
= true;
4142 if ((getenv("LD_TRACE_DEPENDENTS") != NULL
)) {
4144 fTraceEmitJSON
= true;
4147 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL
) {
4148 fTraceDylibSearching
= true;
4151 if (getenv("LD_PRINT_OPTIONS") != NULL
)
4152 fPrintOptions
= true;
4154 if (fTraceDylibs
|| fTraceArchives
|| fTraceEmitJSON
)
4155 fTraceOutputFile
= getenv("LD_TRACE_FILE");
4157 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL
)
4158 fPrintOrderFileStatistics
= true;
4160 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL
)
4163 if (getenv("LD_NO_ENCRYPT") != NULL
) {
4164 fEncryptable
= false;
4165 fMarkAppExtensionSafe
= true; // temporary
4166 fCheckAppExtensionSafe
= false;
4169 if (getenv("LD_APPLICATION_EXTENSION_SAFE") != NULL
) {
4170 fMarkAppExtensionSafe
= true;
4171 fCheckAppExtensionSafe
= false;
4174 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL
)
4175 fAllowCpuSubtypeMismatches
= true;
4177 if (getenv("LD_DYLIB_CPU_SUBTYPES_MUST_MATCH") != NULL
)
4178 fEnforceDylibSubtypesMatch
= true;
4180 sWarningsSideFilePath
= getenv("LD_WARN_FILE");
4182 const char* customDyldPath
= getenv("LD_DYLD_PATH");
4183 if ( customDyldPath
!= NULL
)
4184 fDyldInstallPath
= customDyldPath
;
4186 const char* debugArchivePath
= getenv("LD_DEBUG_SNAPSHOT");
4187 if (debugArchivePath
!= NULL
) {
4188 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
4189 if (strlen(debugArchivePath
) > 0)
4190 fLinkSnapshot
.setSnapshotPath(debugArchivePath
);
4191 fSnapshotRequested
= true;
4194 const char* pipeFdString
= getenv("LD_PIPELINE_FIFO");
4195 if (pipeFdString
!= NULL
) {
4196 fPipelineFifo
= pipeFdString
;
4201 // this is run after the command line is parsed
4202 void Options::parsePostCommandLineEnvironmentSettings()
4204 // when building a dynamic main executable, default any use of @executable_path to output path
4205 if ( fExecutablePath
== NULL
&& (fOutputKind
== kDynamicExecutable
) ) {
4206 fExecutablePath
= fOutputFile
;
4209 // allow build system to set default seg_addr_table
4210 if ( fSegAddrTablePath
== NULL
)
4211 fSegAddrTablePath
= getenv("LD_SEG_ADDR_TABLE");
4213 // allow build system to turn on prebinding
4215 fPrebind
= ( getenv("LD_PREBIND") != NULL
);
4218 // allow build system to force on dead-code-stripping
4219 if ( !fDeadStrip
) {
4220 if ( getenv("LD_DEAD_STRIP") != NULL
) {
4221 switch (fOutputKind
) {
4222 case Options::kDynamicLibrary
:
4223 case Options::kDynamicExecutable
:
4224 case Options::kDynamicBundle
:
4227 case Options::kPreload
:
4228 case Options::kObjectFile
:
4229 case Options::kDyld
:
4230 case Options::kStaticExecutable
:
4231 case Options::kKextBundle
:
4237 // allow build system to force on -warn_commons
4238 if ( getenv("LD_WARN_COMMONS") != NULL
)
4239 fWarnCommons
= true;
4241 // allow B&I to set default -source_version
4242 if ( fSourceVersion
== 0 ) {
4243 const char* vers
= getenv("RC_ProjectSourceVersion");
4245 fSourceVersion
= parseVersionNumber64(vers
);
4250 void Options::reconfigureDefaults()
4252 // sync reader options
4253 switch ( fOutputKind
) {
4254 case Options::kObjectFile
:
4255 fForFinalLinkedImage
= false;
4257 case Options::kDyld
:
4259 fForFinalLinkedImage
= true;
4262 case Options::kDynamicLibrary
:
4263 case Options::kDynamicBundle
:
4264 case Options::kKextBundle
:
4265 fForFinalLinkedImage
= true;
4268 case Options::kDynamicExecutable
:
4269 case Options::kStaticExecutable
:
4270 case Options::kPreload
:
4271 fLinkingMainExecutable
= true;
4272 fForFinalLinkedImage
= true;
4277 // set default min OS version
4278 if ( (fMacVersionMin
== ld::macVersionUnset
) && (fIOSVersionMin
== ld::iOSVersionUnset
) && (fWatchOSVersionMin
== ld::wOSVersionUnset
) ) {
4279 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
4280 const char* macVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
4281 const char* iPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
4282 const char* iOSVers
= getenv("IOS_DEPLOYMENT_TARGET");
4283 const char* wOSVers
= getenv("WATCHOS_DEPLOYMENT_TARGET");
4284 if ( macVers
!= NULL
)
4285 setMacOSXVersionMin(macVers
);
4286 else if ( iPhoneVers
!= NULL
)
4287 setIOSVersionMin(iPhoneVers
);
4288 else if ( iOSVers
!= NULL
)
4289 setIOSVersionMin(iOSVers
);
4290 else if ( wOSVers
!= NULL
)
4291 setWatchOSVersionMin(wOSVers
);
4293 // if still nothing, set default based on architecture
4294 switch ( fArchitecture
) {
4296 case CPU_TYPE_X86_64
:
4297 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
4298 #ifdef DEFAULT_MACOSX_MIN_VERSION
4299 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION
);
4300 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
4302 warning("-macosx_version_min not specified, assuming 10.6");
4303 setMacOSXVersionMin("10.6");
4308 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
4309 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
4310 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION
);
4311 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION
);
4313 if ( fSubArchitecture
== CPU_SUBTYPE_ARM_V7K
) {
4314 warning("-watchos_version_min not specified, assuming 2.0");
4315 setWatchOSVersionMin("2.0");
4318 warning("-ios_version_min not specified, assuming 6.0");
4319 setIOSVersionMin("6.0");
4325 // architecture will be infered later by examining .o files
4332 // adjust min based on architecture
4333 switch ( fArchitecture
) {
4335 if ( (fPlatform
== kPlatformOSX
) && (fMacVersionMin
< ld::mac10_4
) ) {
4336 //warning("-macosx_version_min should be 10.4 or later for i386");
4337 fMacVersionMin
= ld::mac10_4
;
4340 case CPU_TYPE_X86_64
:
4341 if ( (fPlatform
== kPlatformOSX
) && (fMacVersionMin
< ld::mac10_4
) ) {
4342 //warning("-macosx_version_min should be 10.4 or later for x86_64");
4343 fMacVersionMin
= ld::mac10_4
;
4346 case CPU_TYPE_ARM64
:
4347 if ( (fPlatform
== kPlatformiOS
) && (fIOSVersionMin
< ld::iOS_7_0
) ) {
4348 //warning("-mios_version_min should be 7.0 or later for arm64");
4349 fIOSVersionMin
= ld::iOS_7_0
;
4354 // default to adding functions start for dynamic code, static code must opt-in
4355 switch ( fOutputKind
) {
4356 case Options::kPreload
:
4357 case Options::kStaticExecutable
:
4358 case Options::kKextBundle
:
4359 if ( fDataInCodeInfoLoadCommandForcedOn
)
4360 fDataInCodeInfoLoadCommand
= true;
4361 if ( fFunctionStartsForcedOn
)
4362 fFunctionStartsLoadCommand
= true;
4364 case Options::kObjectFile
:
4365 if ( !fDataInCodeInfoLoadCommandForcedOff
)
4366 fDataInCodeInfoLoadCommand
= true;
4367 if ( fFunctionStartsForcedOn
)
4368 fFunctionStartsLoadCommand
= true;
4370 case Options::kDynamicExecutable
:
4371 case Options::kDyld
:
4372 case Options::kDynamicLibrary
:
4373 case Options::kDynamicBundle
:
4374 if ( !fDataInCodeInfoLoadCommandForcedOff
)
4375 fDataInCodeInfoLoadCommand
= true;
4376 if ( !fFunctionStartsForcedOff
)
4377 fFunctionStartsLoadCommand
= true;
4381 // adjust kext type based on architecture
4382 if ( fOutputKind
== kKextBundle
) {
4383 switch ( fArchitecture
) {
4384 case CPU_TYPE_X86_64
:
4385 // x86_64 uses new MH_KEXT_BUNDLE type
4386 fMakeCompressedDyldInfo
= false;
4387 fMakeCompressedDyldInfoForceOff
= true;
4388 fAllowTextRelocs
= true;
4389 fUndefinedTreatment
= kUndefinedDynamicLookup
;
4391 case CPU_TYPE_ARM64
:
4392 // arm64 uses new MH_KEXT_BUNDLE type
4393 fMakeCompressedDyldInfo
= false;
4394 fMakeCompressedDyldInfoForceOff
= true;
4395 fAllowTextRelocs
= false;
4396 fKextsUseStubs
= true;
4397 fUndefinedTreatment
= kUndefinedDynamicLookup
;
4400 if ( min_iOS(ld::iOS_5_0
) ) {
4401 // iOS 5.0 and later use new MH_KEXT_BUNDLE type
4402 fMakeCompressedDyldInfo
= false;
4403 fMakeCompressedDyldInfoForceOff
= true;
4404 // kexts are PIC in iOS 6.0 and later
4405 fAllowTextRelocs
= !min_iOS(ld::iOS_6_0
);
4406 fKextsUseStubs
= !fAllowTextRelocs
;
4407 fUndefinedTreatment
= kUndefinedDynamicLookup
;
4410 // else use object file
4413 fOutputKind
= kObjectFile
;
4418 // disable implicit dylibs when targeting 10.3
4419 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
4420 if ( !minOS(ld::mac10_4
, ld::iOS_2_0
) )
4421 fImplicitlyLinkPublicDylibs
= false;
4424 // allow build system to force linker to ignore -prebind
4425 if ( getenv("LD_FORCE_NO_PREBIND") != NULL
)
4428 // allow build system to force linker to ignore -seg_addr_table
4429 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL
)
4430 fSegAddrTablePath
= NULL
;
4432 // check for base address specified externally
4433 if ( (fSegAddrTablePath
!= NULL
) && (fOutputKind
== Options::kDynamicLibrary
) ) {
4434 parseSegAddrTable(fSegAddrTablePath
, this->installPath());
4435 // HACK to support seg_addr_table entries that are physical paths instead of install paths
4436 if ( fBaseAddress
== 0 ) {
4437 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
4438 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.4.dylib");
4439 if ( fBaseAddress
== 0 )
4440 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.9.dylib");
4443 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
4444 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libz.1.2.3.dylib");
4446 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
4447 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libutil1.0.dylib");
4451 // split segs only allowed for dylibs
4453 // split seg only supported for i386, and arm.
4454 switch ( fArchitecture
) {
4456 if ( fOutputKind
!= Options::kDynamicLibrary
)
4458 // make sure read and write segments are proper distance apart
4459 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x10000000) )
4460 fBaseWritableAddress
= fBaseAddress
+ 0x10000000;
4463 if ( fOutputKind
!= Options::kDynamicLibrary
) {
4467 // make sure read and write segments are proper distance apart
4468 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x08000000) )
4469 fBaseWritableAddress
= fBaseAddress
+ 0x08000000;
4475 fBaseWritableAddress
= 0;
4479 // set too-large size
4480 switch ( fArchitecture
) {
4482 fMaxAddress
= 0xFFFFFFFF;
4484 case CPU_TYPE_X86_64
:
4487 switch ( fOutputKind
) {
4488 case Options::kDynamicExecutable
:
4489 case Options::kDynamicLibrary
:
4490 case Options::kDynamicBundle
:
4491 // user land code is limited to low 1GB
4492 fMaxAddress
= 0x2FFFFFFF;
4494 case Options::kStaticExecutable
:
4495 case Options::kObjectFile
:
4496 case Options::kDyld
:
4497 case Options::kPreload
:
4498 case Options::kKextBundle
:
4499 fMaxAddress
= 0xFFFFFFFF;
4502 // range check -seg1addr for ARM
4503 if ( fBaseAddress
> fMaxAddress
) {
4504 warning("ignoring -seg1addr 0x%08llX. Address out of range.", fBaseAddress
);
4510 // <rdar://problem/6138961> -r implies no prebinding for all architectures
4511 if ( fOutputKind
== Options::kObjectFile
)
4514 // disable prebinding depending on arch and min OS version
4516 switch ( fArchitecture
) {
4518 if ( fMacVersionMin
== ld::mac10_4
) {
4519 // in 10.4 only split seg dylibs are prebound
4520 if ( (fOutputKind
!= Options::kDynamicLibrary
) || ! fSplitSegs
)
4523 else if ( fMacVersionMin
>= ld::mac10_5
) {
4524 // in 10.5 nothing is prebound
4527 else if ( fIOSVersionMin
!= ld::iOSVersionUnset
) {
4528 // nothing in simulator is prebound
4532 // in 10.3 and earlier only dylibs and main executables could be prebound
4533 switch ( fOutputKind
) {
4534 case Options::kDynamicExecutable
:
4535 case Options::kDynamicLibrary
:
4536 // only main executables and dylibs can be prebound
4538 case Options::kStaticExecutable
:
4539 case Options::kDynamicBundle
:
4540 case Options::kObjectFile
:
4541 case Options::kDyld
:
4542 case Options::kPreload
:
4543 case Options::kKextBundle
:
4544 // disable prebinding for everything else
4550 case CPU_TYPE_X86_64
:
4554 switch ( fOutputKind
) {
4555 case Options::kDynamicExecutable
:
4556 case Options::kDynamicLibrary
:
4557 // only main executables and dylibs can be prebound
4559 case Options::kStaticExecutable
:
4560 case Options::kDynamicBundle
:
4561 case Options::kObjectFile
:
4562 case Options::kDyld
:
4563 case Options::kPreload
:
4564 case Options::kKextBundle
:
4565 // disable prebinding for everything else
4573 // only prebound images can be split-seg
4574 if ( fSplitSegs
&& !fPrebind
)
4577 // determine if info for shared region should be added
4578 if ( fOutputKind
== Options::kDynamicLibrary
) {
4579 if ( minOS(ld::mac10_5
, ld::iOS_3_1
) && !fTargetIOSSimulator
)
4580 if ( !fPrebind
&& !fSharedRegionEligibleForceOff
)
4581 if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
4582 || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
4583 fSharedRegionEligible
= true;
4585 else if ( fOutputKind
== Options::kDyld
) {
4586 // <rdar://problem/10111122> Enable dyld to be put into the dyld shared cache
4587 fSharedRegionEligible
= true;
4590 // <rdar://problem/18719327> warn if -rpath is used with OS dylibs
4591 if ( fSharedRegionEligible
&& !fRPaths
.empty() )
4592 warning("-rpath cannot be used with dylibs that will be in the dyld shared cache");
4594 // automatically use __DATA_CONST in iOS dylibs
4595 if ( fSharedRegionEligible
&& minOS(ld::mac10_Future
, ld::iOS_9_0
) && !fUseDataConstSegmentForceOff
) {
4596 fUseDataConstSegment
= true;
4598 if ( fUseDataConstSegmentForceOn
) {
4599 fUseDataConstSegment
= true;
4601 // A -kext for iOS 10 ==> -data_const, -text_exec, -add_split_seg_info
4602 if ( (fOutputKind
== Options::kKextBundle
) && minOS(ld::mac10_Future
, ld::iOS_10_0
) && (fArchitecture
== CPU_TYPE_ARM64
) ) {
4603 fUseDataConstSegment
= true;
4604 fUseTextExecSegment
= true;
4605 fSharedRegionEligible
= true;
4607 if ( fUseDataConstSegment
) {
4608 addSectionRename("__DATA", "__got", "__DATA_CONST", "__got");
4609 addSectionRename("__DATA", "__la_symbol_ptr", "__DATA_CONST", "__la_symbol_ptr");
4610 addSectionRename("__DATA", "__nl_symbol_ptr", "__DATA_CONST", "__nl_symbol_ptr");
4611 addSectionRename("__DATA", "__const", "__DATA_CONST", "__const");
4612 addSectionRename("__DATA", "__cfstring", "__DATA_CONST", "__cfstring");
4613 addSectionRename("__DATA", "__mod_init_func", "__DATA_CONST", "__mod_init_func");
4614 addSectionRename("__DATA", "__mod_term_func", "__DATA_CONST", "__mod_term_func");
4615 addSectionRename("__DATA", "__objc_classlist", "__DATA_CONST", "__objc_classlist");
4616 addSectionRename("__DATA", "__objc_nlclslist", "__DATA_CONST", "__objc_nlclslist");
4617 addSectionRename("__DATA", "__objc_catlist", "__DATA_CONST", "__objc_catlist");
4618 addSectionRename("__DATA", "__objc_nlcatlist", "__DATA_CONST", "__objc_nlcatlist");
4619 addSectionRename("__DATA", "__objc_protolist", "__DATA_CONST", "__objc_protolist");
4620 addSectionRename("__DATA", "__objc_imageinfo", "__DATA_CONST", "__objc_imageinfo");
4621 addSectionRename("__DATA", "__objc_const", "__DATA_CONST", "__objc_const");
4623 if ( fUseTextExecSegment
) {
4624 addSectionRename("__TEXT", "__text", "__TEXT_EXEC", "__text");
4625 addSectionRename("__TEXT", "__stubs", "__TEXT_EXEC", "__stubs");
4628 // Use V2 shared cache info when targetting newer OSs
4629 if ( fSharedRegionEligible
&& minOS(ld::mac10_12
, ld::iOS_9_0
)) {
4630 fSharedRegionEncodingV2
= true;
4631 // <rdar://problem/24772435> only use v2 for Swift dylibs on Mac OS X
4632 if ( (fPlatform
== kPlatformOSX
) && (strncmp(this->installPath(), "/System/Library/PrivateFrameworks/Swift/", 40) != 0) )
4633 fSharedRegionEncodingV2
= false;
4634 fIgnoreOptimizationHints
= true;
4637 // figure out if module table is needed for compatibility with old ld/dyld
4638 if ( fOutputKind
== Options::kDynamicLibrary
) {
4639 switch ( fArchitecture
) {
4641 if ( fIOSVersionMin
!= ld::iOSVersionUnset
) // simulator never needs modules
4645 fNeedsModuleTable
= true; // redo_prebinding requires a module table
4650 // <rdar://problem/5366363> -r -x implies -S
4651 if ( (fOutputKind
== Options::kObjectFile
) && (fLocalSymbolHandling
== kLocalSymbolsNone
) )
4652 fDebugInfoStripping
= Options::kDebugInfoNone
;
4654 // <rdar://problem/15252891> -r implies -no_uuid
4655 if ( fOutputKind
== Options::kObjectFile
)
4656 fUUIDMode
= kUUIDNone
;
4658 // choose how to process unwind info
4659 switch ( fArchitecture
) {
4661 case CPU_TYPE_X86_64
:
4662 case CPU_TYPE_ARM64
:
4663 switch ( fOutputKind
) {
4664 case Options::kObjectFile
:
4665 case Options::kStaticExecutable
:
4666 case Options::kPreload
:
4667 case Options::kKextBundle
:
4668 fAddCompactUnwindEncoding
= false;
4670 case Options::kDyld
:
4671 case Options::kDynamicLibrary
:
4672 case Options::kDynamicBundle
:
4673 case Options::kDynamicExecutable
:
4674 //if ( fAddCompactUnwindEncoding && (fVersionMin >= ld::mac10_6) )
4675 // fRemoveDwarfUnwindIfCompactExists = true;
4680 if ( armUsesZeroCostExceptions() ) {
4681 switch ( fOutputKind
) {
4682 case Options::kObjectFile
:
4683 case Options::kStaticExecutable
:
4684 case Options::kPreload
:
4685 case Options::kKextBundle
:
4686 fAddCompactUnwindEncoding
= false;
4688 case Options::kDyld
:
4689 case Options::kDynamicLibrary
:
4690 case Options::kDynamicBundle
:
4691 case Options::kDynamicExecutable
:
4692 fAddCompactUnwindEncoding
= true;
4697 fAddCompactUnwindEncoding
= false;
4698 fRemoveDwarfUnwindIfCompactExists
= false;
4702 // if -arch is missing, assume we don't want compact unwind info
4703 fAddCompactUnwindEncoding
= false;
4707 // only iOS executables should be encryptable
4708 switch ( fOutputKind
) {
4709 case Options::kObjectFile
:
4710 case Options::kDyld
:
4711 case Options::kStaticExecutable
:
4712 case Options::kPreload
:
4713 case Options::kKextBundle
:
4714 fEncryptable
= false;
4716 case Options::kDynamicExecutable
:
4718 case Options::kDynamicLibrary
:
4719 case Options::kDynamicBundle
:
4720 // <rdar://problem/16293398> Add LC_ENCRYPTION_INFO load command to bundled frameworks
4721 if ( !min_iOS(ld::iOS_7_0
) )
4722 fEncryptable
= false;
4725 if ( (fArchitecture
!= CPU_TYPE_ARM
) && (fArchitecture
!= CPU_TYPE_ARM64
)
4727 fEncryptable
= false;
4728 if ( fEncryptableForceOn
)
4729 fEncryptable
= true;
4730 else if ( fEncryptableForceOff
)
4731 fEncryptable
= false;
4733 // don't move inits in dyld because dyld wants certain
4734 // entries point at stable locations at the start of __text
4735 if ( fOutputKind
== Options::kDyld
)
4736 fAutoOrderInitializers
= false;
4739 // disable __data ordering for some output kinds
4740 switch ( fOutputKind
) {
4741 case Options::kObjectFile
:
4742 case Options::kDyld
:
4743 case Options::kStaticExecutable
:
4744 case Options::kPreload
:
4745 case Options::kKextBundle
:
4748 case Options::kDynamicExecutable
:
4749 case Options::kDynamicLibrary
:
4750 case Options::kDynamicBundle
:
4754 // only use compressed LINKEDIT for final linked images
4755 switch ( fOutputKind
) {
4756 case Options::kDynamicExecutable
:
4757 case Options::kDynamicLibrary
:
4758 case Options::kDynamicBundle
:
4760 case Options::kPreload
:
4761 case Options::kStaticExecutable
:
4762 case Options::kObjectFile
:
4763 case Options::kDyld
:
4764 case Options::kKextBundle
:
4765 fMakeCompressedDyldInfoForceOff
= true;
4768 if ( fMakeCompressedDyldInfoForceOff
)
4769 fMakeCompressedDyldInfo
= false;
4772 // only use compressed LINKEDIT for:
4773 // Mac OS X 10.6 or later
4775 if ( fMakeCompressedDyldInfo
) {
4776 if ( !minOS(ld::mac10_6
, ld::iOS_3_1
) )
4777 fMakeCompressedDyldInfo
= false;
4780 // only ARM and x86_64 enforces that cpu-sub-types must match
4781 switch ( fArchitecture
) {
4784 case CPU_TYPE_X86_64
:
4785 fEnforceDylibSubtypesMatch
= false;
4788 case CPU_TYPE_ARM64
:
4789 fEnforceDylibSubtypesMatch
= false;
4794 // only final linked images can not optimize zero fill sections
4795 if ( fOutputKind
== Options::kObjectFile
)
4796 fOptimizeZeroFill
= true;
4798 // all undefines in -r mode
4799 // if ( fOutputKind == Options::kObjectFile )
4800 // fUndefinedTreatment = kUndefinedSuppress;
4802 // only dynamic final linked images should warn about use of commmons
4803 if ( fWarnCommons
) {
4804 switch ( fOutputKind
) {
4805 case Options::kDynamicExecutable
:
4806 case Options::kDynamicLibrary
:
4807 case Options::kDynamicBundle
:
4809 case Options::kPreload
:
4810 case Options::kStaticExecutable
:
4811 case Options::kObjectFile
:
4812 case Options::kDyld
:
4813 case Options::kKextBundle
:
4814 fWarnCommons
= false;
4819 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
4820 if ( minOS(ld::mac10_5
, ld::iOS_2_0
) )
4821 fUseSimplifiedDylibReExports
= true;
4823 // Mac OS X 10.7 and iOS 4.2 support LC_LOAD_UPWARD_DYLIB
4824 if ( minOS(ld::mac10_7
, ld::iOS_4_2
) && (fOutputKind
== kDynamicLibrary
) )
4825 fCanUseUpwardDylib
= true;
4827 // MacOSX 10.7 defaults to PIE
4828 if ( (fArchitecture
== CPU_TYPE_I386
)
4829 && (fOutputKind
== kDynamicExecutable
)
4830 && (fMacVersionMin
>= ld::mac10_7
) ) {
4831 fPositionIndependentExecutable
= true;
4834 // armv7 for iOS4.3 defaults to PIE
4835 if ( (fArchitecture
== CPU_TYPE_ARM
)
4836 && fArchSupportsThumb2
4837 && (fOutputKind
== kDynamicExecutable
)
4838 && min_iOS(ld::iOS_4_3
) ) {
4839 fPositionIndependentExecutable
= true;
4842 // <rdar://problem/24535196> x86_64 defaults PIE (regardless of minOS version)
4843 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
== kDynamicExecutable
) && (fMacVersionMin
>= ld::mac10_6
) )
4844 fPositionIndependentExecutable
= true;
4846 // Simulator defaults to PIE
4847 if ( fTargetIOSSimulator
&& (fOutputKind
== kDynamicExecutable
) )
4848 fPositionIndependentExecutable
= true;
4850 // -no_pie anywhere on command line disable PIE
4851 if ( fDisablePositionIndependentExecutable
)
4852 fPositionIndependentExecutable
= false;
4854 // arm64 is always PIE
4855 if ( ((fArchitecture
== CPU_TYPE_ARM64
)
4857 && (fOutputKind
== kDynamicExecutable
) ) {
4858 fPositionIndependentExecutable
= true;
4859 if ( fDisablePositionIndependentExecutable
)
4860 warning("-no_pie ignored for arm64");
4863 // set fOutputSlidable
4864 switch ( fOutputKind
) {
4865 case Options::kObjectFile
:
4866 fOutputSlidable
= false;
4868 case Options::kStaticExecutable
:
4869 case Options::kDynamicExecutable
:
4870 fOutputSlidable
= fPositionIndependentExecutable
;
4872 case Options::kPreload
:
4873 fOutputSlidable
= fPIEOnCommandLine
;
4875 case Options::kDyld
:
4876 case Options::kDynamicLibrary
:
4877 case Options::kDynamicBundle
:
4878 case Options::kKextBundle
:
4879 fOutputSlidable
= true;
4883 // let linker know if thread local variables are supported
4884 if ( fMacVersionMin
>= ld::mac10_7
) {
4887 else if ( ((fArchitecture
== CPU_TYPE_ARM64
)
4889 && min_iOS(ld::iOS_8_0
) ) {
4892 else if ( (fArchitecture
== CPU_TYPE_ARM
) && min_iOS(ld::iOS_9_0
) ) {
4895 else if ( fTargetIOSSimulator
&& (fArchitecture
== CPU_TYPE_X86_64
) && min_iOS(ld::iOS_8_0
) ) {
4898 else if ( fTargetIOSSimulator
&& (fArchitecture
== CPU_TYPE_I386
) && min_iOS(ld::iOS_9_0
) ) {
4902 // default to adding version load command for dynamic code, static code must opt-in
4903 switch ( fOutputKind
) {
4904 case Options::kObjectFile
:
4905 fVersionLoadCommand
= false;
4907 case Options::kStaticExecutable
:
4908 case Options::kPreload
:
4909 case Options::kKextBundle
:
4910 if ( fVersionLoadCommandForcedOn
)
4911 fVersionLoadCommand
= true;
4913 case Options::kDynamicExecutable
:
4914 case Options::kDyld
:
4915 case Options::kDynamicLibrary
:
4916 case Options::kDynamicBundle
:
4917 if ( !fVersionLoadCommandForcedOff
)
4918 fVersionLoadCommand
= true;
4922 // support re-export of individual symbols in MacOSX 10.7 and iOS 4.2
4923 if ( (fOutputKind
== kDynamicLibrary
) && minOS(ld::mac10_7
, ld::iOS_4_2
) )
4924 fCanReExportSymbols
= true;
4926 // ObjC optimization is only in dynamic final linked images
4927 switch ( fOutputKind
) {
4928 case Options::kObjectFile
:
4929 case Options::kStaticExecutable
:
4930 case Options::kPreload
:
4931 case Options::kKextBundle
:
4932 case Options::kDyld
:
4933 fObjcCategoryMerging
= false;
4935 case Options::kDynamicExecutable
:
4936 case Options::kDynamicLibrary
:
4937 case Options::kDynamicBundle
:
4941 // i386 main executables linked on Mac OS X 10.7 default to NX heap
4942 // regardless of target unless overriden with -allow_heap_execute anywhere
4943 // on the command line
4944 if ( (fArchitecture
== CPU_TYPE_I386
) && (fOutputKind
== kDynamicExecutable
) && !fDisableNonExecutableHeap
)
4945 fNonExecutableHeap
= true;
4947 // Use LC_MAIN instead of LC_UNIXTHREAD for newer OSs
4948 switch ( fOutputKind
) {
4949 case Options::kDynamicExecutable
:
4950 if ( fEntryPointLoadCommandForceOn
) {
4951 fEntryPointLoadCommand
= true;
4952 if ( fEntryName
== NULL
)
4953 fEntryName
= "_main";
4955 else if ( fEntryPointLoadCommandForceOff
) {
4956 fNeedsThreadLoadCommand
= true;
4957 if ( fEntryName
== NULL
)
4958 fEntryName
= "start";
4961 // <rdar://problem/16310363> Linker should look for "_main" not "start" when building for sim regardless of min OS
4962 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) || fTargetIOSSimulator
) {
4963 fEntryPointLoadCommand
= true;
4964 if ( fEntryName
== NULL
)
4965 fEntryName
= "_main";
4966 if ( strcmp(fEntryName
, "start") == 0 ) {
4967 warning("Ignoring '-e start' because entry point 'start' is not used for the targeted OS version");
4968 fEntryName
= "_main";
4972 fNeedsThreadLoadCommand
= true;
4973 if ( fEntryName
== NULL
)
4974 fEntryName
= "start";
4978 case Options::kObjectFile
:
4979 case Options::kKextBundle
:
4980 case Options::kDynamicLibrary
:
4981 case Options::kDynamicBundle
:
4984 case Options::kStaticExecutable
:
4985 case Options::kPreload
:
4986 case Options::kDyld
:
4987 fNeedsThreadLoadCommand
= true;
4988 if ( fEntryName
== NULL
)
4989 fEntryName
= "start"; // Perhaps these should have no default and require -e
4993 // add LC_SOURCE_VERSION
4994 switch ( fOutputKind
) {
4995 case Options::kDynamicExecutable
:
4996 case Options::kKextBundle
:
4997 case Options::kDynamicLibrary
:
4998 case Options::kDynamicBundle
:
4999 case Options::kDyld
:
5000 case Options::kStaticExecutable
:
5001 if ( fSourceVersionLoadCommandForceOn
) {
5002 fSourceVersionLoadCommand
= true;
5004 else if ( fSourceVersionLoadCommandForceOff
) {
5005 fSourceVersionLoadCommand
= false;
5008 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) ) {
5009 fSourceVersionLoadCommand
= true;
5012 fSourceVersionLoadCommand
= false;
5015 case Options::kObjectFile
:
5016 case Options::kPreload
:
5017 fSourceVersionLoadCommand
= false;
5021 // if -sdk_version not on command line, infer from -syslibroot
5022 if ( (fSDKVersion
== 0) && (fSDKPaths
.size() > 0) ) {
5023 const char* sdkPath
= fSDKPaths
.front();
5024 const char* end
= &sdkPath
[strlen(sdkPath
)-1];
5025 while ( !isdigit(*end
) && (end
> sdkPath
) )
5027 const char* start
= end
-1;
5028 while ( (isdigit(*start
) || (*start
== '.')) && (start
> sdkPath
))
5030 char sdkVersionStr
[32];
5031 int len
= end
-start
+1;
5033 strlcpy(sdkVersionStr
, start
+1, len
);
5034 fSDKVersion
= parseVersionNumber32(sdkVersionStr
);
5038 // if -sdk_version and -syslibroot not used, but targeting MacOSX, use current OS version
5039 if ( (fSDKVersion
== 0) && (fMacVersionMin
!= ld::macVersionUnset
) ) {
5040 // special case if RC_ProjectName and MACOSX_DEPLOYMENT_TARGET are both set that sdkversion=minos
5041 if ( getenv("RC_ProjectName") && getenv("MACOSX_DEPLOYMENT_TARGET") ) {
5042 fSDKVersion
= fMacVersionMin
;
5045 int mib
[2] = { CTL_KERN
, KERN_OSRELEASE
};
5046 char kernVersStr
[100];
5047 size_t strlen
= sizeof(kernVersStr
);
5048 if ( sysctl(mib
, 2, kernVersStr
, &strlen
, NULL
, 0) != -1 ) {
5049 uint32_t kernVers
= parseVersionNumber32(kernVersStr
);
5050 int minor
= (kernVers
>> 16) - 4; // kernel major version is 4 ahead of x in 10.x
5051 fSDKVersion
= 0x000A0000 + (minor
<< 8);
5056 // allow trie based absolute symbols if targeting new enough OS
5057 if ( fMakeCompressedDyldInfo
) {
5058 if ( minOS(ld::mac10_9
, ld::iOS_7_0
) ) {
5059 fAbsoluteSymbols
= true;
5063 // <rdar://problem/12959510> iOS main executables now default to 16KB page size
5064 if ( (fIOSVersionMin
!= ld::iOSVersionUnset
) && (fOutputKind
== Options::kDynamicExecutable
) ) {
5065 // <rdar://problem/13070042> Only third party apps should have 16KB page segments by default
5066 if ( fEncryptable
) {
5067 if ( fSegmentAlignment
== 4096 )
5068 fSegmentAlignment
= 4096*4;
5072 // <rdar://problem/12258065> ARM64 needs 16KB page size for user land code
5073 // <rdar://problem/15974532> make armv7[s] use 16KB pages in user land code for iOS 8 or later
5074 if ( fSegmentAlignment
== 4096 ) {
5075 switch ( fOutputKind
) {
5076 case Options::kDynamicExecutable
:
5077 case Options::kDynamicLibrary
:
5078 case Options::kDynamicBundle
:
5079 case Options::kDyld
:
5080 if ( ((fArchitecture
== CPU_TYPE_ARM64
)
5082 || ((fArchitecture
== CPU_TYPE_ARM
) && min_iOS(ld::iOS_7_0
)) ) {
5083 fSegmentAlignment
= 4096*4;
5086 case Options::kStaticExecutable
:
5087 case Options::kKextBundle
:
5088 // <rdar://problem/14676611> 16KB segments for arm64 kexts
5089 if ( ((fArchitecture
== CPU_TYPE_ARM64
)
5091 && min_iOS(ld::iOS_9_0
) ) {
5092 fSegmentAlignment
= 4096*4;
5095 case Options::kObjectFile
:
5096 case Options::kPreload
:
5103 // <rdar://problem/13624134> linker should not convert dwarf unwind if .o file has compact unwind section
5104 switch ( fOutputKind
) {
5105 case Options::kDynamicExecutable
:
5106 case Options::kDynamicLibrary
:
5107 case Options::kDynamicBundle
:
5108 case Options::kDyld
:
5109 if ( fKeepDwarfUnwindForcedOn
) {
5110 fKeepDwarfUnwind
= true;
5112 else if ( fKeepDwarfUnwindForcedOff
) {
5113 fKeepDwarfUnwind
= false;
5116 if ( minOS(ld::mac10_9
, ld::iOS_7_0
) )
5117 fKeepDwarfUnwind
= false;
5119 fKeepDwarfUnwind
= true;
5122 case Options::kKextBundle
:
5123 case Options::kStaticExecutable
:
5124 case Options::kObjectFile
:
5125 case Options::kPreload
:
5126 fKeepDwarfUnwind
= true;
5130 // Make sure -image_base matches alignment
5131 uint64_t alignedBaseAddress
= (fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
);
5132 if ( alignedBaseAddress
!= fBaseAddress
) {
5133 warning("base address 0x%llX is not properly aligned. Changing it to 0x%llX", fBaseAddress
, alignedBaseAddress
);
5134 fBaseAddress
= alignedBaseAddress
;
5137 // If -dirty_data_list not specified, look in $SDKROOT/AppleInternal/DirtyDataFiles/<dylib>.dirty for dirty data list
5138 if ( fSymbolsMovesData
.empty() && fUseDataConstSegment
&& ( fDylibInstallName
!= NULL
) && !fSDKPaths
.empty() ) {
5139 const char* dylibLeaf
= strrchr(fDylibInstallName
, '/');
5141 char path
[PATH_MAX
];
5142 strlcpy(path
, fSDKPaths
.front(), sizeof(path
));
5143 strlcat(path
, "/AppleInternal/DirtyDataFiles", sizeof(path
));
5144 strlcat(path
, dylibLeaf
, sizeof(path
));
5145 strlcat(path
, ".dirty", sizeof(path
));
5147 if ( info
.checkFileExists(*this, path
) )
5148 addSymbolMove("__DATA_DIRTY", path
, fSymbolsMovesData
, "-dirty_data_list");
5152 // <rdar://problem/20503811> Reduce the default alignment of structures/arrays to save memory in embedded systems
5153 if ( fMaxDefaultCommonAlign
== 0 ) {
5154 if ( fOutputKind
== Options::kPreload
)
5155 fMaxDefaultCommonAlign
= 8;
5157 fMaxDefaultCommonAlign
= 15;
5161 void Options::checkIllegalOptionCombinations()
5163 // check -undefined setting
5164 switch ( fUndefinedTreatment
) {
5165 case kUndefinedError
:
5168 case kUndefinedDynamicLookup
:
5169 switch (fPlatform
) {
5173 case kPlatformWatchOS
:
5174 #if SUPPORT_APPLE_TV
5175 case kPlatform_tvOS
:
5177 if ( fOutputKind
!= kKextBundle
)
5178 warning("-undefined dynamic_lookup is deprecated on %s", platformName(fPlatform
));
5184 case kUndefinedWarning
:
5185 case kUndefinedSuppress
:
5186 // requires flat namespace
5187 if ( fNameSpace
== kTwoLevelNameSpace
)
5188 throw "can't use -undefined warning or suppress with -twolevel_namespace";
5192 // unify -sub_umbrella with dylibs
5193 for (std::vector
<const char*>::iterator it
= fSubUmbellas
.begin(); it
!= fSubUmbellas
.end(); it
++) {
5194 const char* subUmbrella
= *it
;
5196 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
5197 Options::FileInfo
& info
= *fit
;
5198 const char* lastSlash
= strrchr(info
.path
, '/');
5199 if ( lastSlash
== NULL
)
5200 lastSlash
= info
.path
- 1;
5201 std::string
path(&lastSlash
[1]);
5202 auto idx
= path
.find(".tbd", path
.size() - 4);
5203 if (idx
!= std::string::npos
)
5205 if ( path
== subUmbrella
) {
5206 info
.options
.fReExport
= true;
5208 fLinkSnapshot
.recordSubUmbrella(info
.path
);
5213 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella
);
5216 // unify -sub_library with dylibs
5217 for (std::vector
<const char*>::iterator it
= fSubLibraries
.begin(); it
!= fSubLibraries
.end(); it
++) {
5218 const char* subLibrary
= *it
;
5220 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
5221 Options::FileInfo
& info
= *fit
;
5222 const char* lastSlash
= strrchr(info
.path
, '/');
5223 if ( lastSlash
== NULL
)
5224 lastSlash
= info
.path
- 1;
5225 const char* dot
= strchr(&lastSlash
[1], '.');
5227 dot
= &lastSlash
[strlen(lastSlash
)];
5228 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
5229 info
.options
.fReExport
= true;
5231 fLinkSnapshot
.recordSubLibrary(info
.path
);
5236 warning("-sub_library %s does not match a supplied dylib", subLibrary
);
5239 // sync reader options
5240 if ( fNameSpace
!= kTwoLevelNameSpace
) {
5241 fFlatNamespace
= true;
5242 switch (fPlatform
) {
5246 case kPlatformWatchOS
:
5247 #if SUPPORT_APPLE_TV
5248 case Options::kPlatform_tvOS
:
5250 warning("-flat_namespace is deprecated on %s", platformName(fPlatform
));
5258 // check -stack_addr
5259 if ( fStackAddr
!= 0 ) {
5260 switch (fArchitecture
) {
5263 if ( fStackAddr
> 0xFFFFFFFF )
5264 throw "-stack_addr must be < 4G for 32-bit processes";
5266 case CPU_TYPE_X86_64
:
5267 case CPU_TYPE_ARM64
:
5270 if ( (fStackAddr
& -4096) != fStackAddr
)
5271 throw "-stack_addr must be multiples of 4K";
5272 if ( fStackSize
== 0 )
5273 throw "-stack_addr must be used with -stack_size";
5276 // check -stack_size
5277 if ( fStackSize
!= 0 ) {
5278 switch (fArchitecture
) {
5280 if ( fPlatform
== kPlatformOSX
) {
5281 if ( fStackSize
> 0xFFFFFFFF )
5282 throw "-stack_size must be < 4GB for 32-bit processes";
5283 if ( fStackAddr
== 0 )
5284 fStackAddr
= 0xC0000000;
5285 if ( (fStackAddr
> 0xB0000000) && ((fStackAddr
-fStackSize
) < 0xB0000000) )
5286 warning("custom stack placement overlaps and will disable shared region");
5289 if ( fStackSize
> 0x1F000000 )
5290 throw "-stack_size must be < 496MB";
5291 if ( fStackAddr
== 0 )
5292 fStackAddr
= 0xC0000000;
5296 if ( fStackSize
> 0x1F000000 )
5297 throw "-stack_size must be < 496MB";
5298 if ( fStackAddr
== 0 )
5299 fStackAddr
= 0x1F000000;
5300 if ( fStackAddr
> 0x20000000)
5301 throw "-stack_addr must be < 0x20000000 for arm";
5303 case CPU_TYPE_X86_64
:
5304 if ( fPlatform
== kPlatformOSX
) {
5305 if ( fStackSize
> 0x10000000000 )
5306 throw "-stack_size must be <= 1TB";
5307 if ( fStackAddr
== 0 ) {
5308 fStackAddr
= 0x00007FFF5C000000LL
;
5312 if ( fStackSize
> 0x20000000 )
5313 throw "-stack_size must be <= 512MB";
5314 if ( fStackAddr
== 0 ) {
5315 fStackAddr
= 0x120000000;
5318 case CPU_TYPE_ARM64
:
5319 if ( fStackSize
> 0x20000000 )
5320 throw "-stack_size must be <= 512MB";
5321 if ( fStackAddr
== 0 )
5322 fStackAddr
= 0x120000000;
5326 if ( (fStackSize
& (-fSegmentAlignment
)) != fStackSize
)
5327 throwf("-stack_size must be multiple of segment alignment (%lldKB)", fSegmentAlignment
/1024);
5328 switch ( fOutputKind
) {
5329 case Options::kDynamicExecutable
:
5330 case Options::kStaticExecutable
:
5331 // custom stack size only legal when building main executable
5333 case Options::kDynamicLibrary
:
5334 case Options::kDynamicBundle
:
5335 case Options::kObjectFile
:
5336 case Options::kDyld
:
5337 case Options::kPreload
:
5338 case Options::kKextBundle
:
5339 throw "-stack_size option can only be used when linking a main executable";
5341 if ( fStackSize
> fStackAddr
)
5342 throwf("-stack_size (0x%08llX) must be smaller than -stack_addr (0x%08llX)", fStackSize
, fStackAddr
);
5345 // check that -allow_stack_execute is only used with main executables
5346 if ( fExecutableStack
) {
5347 switch ( fOutputKind
) {
5348 case Options::kDynamicExecutable
:
5349 case Options::kStaticExecutable
:
5350 // -allow_stack_execute size only legal when building main executable
5352 case Options::kDynamicLibrary
:
5353 case Options::kDynamicBundle
:
5354 case Options::kObjectFile
:
5355 case Options::kDyld
:
5356 case Options::kPreload
:
5357 case Options::kKextBundle
:
5358 throw "-allow_stack_execute option can only be used when linking a main executable";
5362 // check that -allow_heap_execute is only used with i386 main executables
5363 if ( fDisableNonExecutableHeap
) {
5364 if ( fArchitecture
!= CPU_TYPE_I386
)
5365 throw "-allow_heap_execute option can only be used when linking for i386";
5366 switch ( fOutputKind
) {
5367 case Options::kDynamicExecutable
:
5368 // -allow_heap_execute only legal when building main executable
5370 case Options::kStaticExecutable
:
5371 case Options::kDynamicLibrary
:
5372 case Options::kDynamicBundle
:
5373 case Options::kObjectFile
:
5374 case Options::kDyld
:
5375 case Options::kPreload
:
5376 case Options::kKextBundle
:
5377 throw "-allow_heap_execute option can only be used when linking a main executable";
5381 // check -client_name is only used when making a bundle or main executable
5382 if ( fClientName
!= NULL
) {
5383 switch ( fOutputKind
) {
5384 case Options::kDynamicExecutable
:
5385 case Options::kDynamicBundle
:
5387 case Options::kStaticExecutable
:
5388 case Options::kDynamicLibrary
:
5389 case Options::kObjectFile
:
5390 case Options::kDyld
:
5391 case Options::kPreload
:
5392 case Options::kKextBundle
:
5393 throw "-client_name can only be used with -bundle";
5397 // check -init is only used when building a dylib
5398 if ( (fInitFunctionName
!= NULL
) && (fOutputKind
!= Options::kDynamicLibrary
) )
5399 throw "-init can only be used with -dynamiclib";
5401 // check -bundle_loader only used with -bundle
5402 if ( (fBundleLoader
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
5403 throw "-bundle_loader can only be used with -bundle";
5405 // check -dtrace not used with -r
5406 if ( (fDtraceScriptName
!= NULL
) && (fOutputKind
== Options::kObjectFile
) )
5407 throw "-dtrace can only be used when creating final linked images";
5409 // check -d can only be used with -r
5410 if ( fMakeTentativeDefinitionsReal
&& (fOutputKind
!= Options::kObjectFile
) )
5411 throw "-d can only be used with -r";
5413 // check that -root_safe is not used with -r
5414 if ( fRootSafe
&& (fOutputKind
== Options::kObjectFile
) )
5415 throw "-root_safe cannot be used with -r";
5417 // check that -setuid_safe is not used with -r
5418 if ( fSetuidSafe
&& (fOutputKind
== Options::kObjectFile
) )
5419 throw "-setuid_safe cannot be used with -r";
5421 // <rdar://problem/12781832> compiler driver no longer uses -objc_abi_version, it uses -ios_simulator_version_min instead
5422 if ( !fObjCABIVersion1Override
&& !fObjCABIVersion2Override
&& fTargetIOSSimulator
)
5423 fObjCABIVersion2Override
= true;
5425 // rdar://problem/4718189 map ObjC class names to new runtime names
5426 bool alterObjC1ClassNamesToObjC2
= false;
5427 switch (fArchitecture
) {
5429 // i386 only uses new symbols when using objc2 ABI
5430 if ( fObjCABIVersion2Override
)
5431 alterObjC1ClassNamesToObjC2
= true;
5433 case CPU_TYPE_X86_64
:
5435 case CPU_TYPE_ARM64
:
5436 alterObjC1ClassNamesToObjC2
= true;
5440 // make sure all required exported symbols exist
5441 std::vector
<const char*> impliedExports
;
5442 for (NameSet::iterator it
=fExportSymbols
.regularBegin(); it
!= fExportSymbols
.regularEnd(); ++it
) {
5443 const char* name
= *it
;
5444 const int len
= strlen(name
);
5445 if ( (strcmp(&name
[len
-3], ".eh") == 0) || (strncmp(name
, ".objc_category_name_", 20) == 0) ) {
5446 // never export .eh symbols
5447 warning("ignoring %s in export list", name
);
5449 else if ( (fArchitecture
== CPU_TYPE_I386
) && !fObjCABIVersion2Override
&& (strncmp(name
, "_OBJC_CLASS_$", 13) == 0) ) {
5450 warning("ignoring Objc2 Class symbol %s in i386 export list", name
);
5451 fRemovedExports
.insert(name
);
5453 else if ( alterObjC1ClassNamesToObjC2
&& (strncmp(name
, ".objc_class_name_", 17) == 0) ) {
5454 // linking ObjC2 ABI, but have ObjC1 ABI name in export list. Change it to intended name
5455 fRemovedExports
.insert(name
);
5457 asprintf(&temp
, "_OBJC_CLASS_$_%s", &name
[17]);
5458 impliedExports
.push_back(temp
);
5459 asprintf(&temp
, "_OBJC_METACLASS_$_%s", &name
[17]);
5460 impliedExports
.push_back(temp
);
5463 fInitialUndefines
.push_back(name
);
5466 fExportSymbols
.remove(fRemovedExports
);
5467 for (std::vector
<const char*>::iterator it
=impliedExports
.begin(); it
!= impliedExports
.end(); ++it
) {
5468 const char* name
= *it
;
5469 fExportSymbols
.insert(name
);
5470 fInitialUndefines
.push_back(name
);
5473 // make sure all required re-exported symbols exist
5474 for (NameSet::iterator it
=fReExportSymbols
.regularBegin(); it
!= fReExportSymbols
.regularEnd(); ++it
) {
5475 fInitialUndefines
.push_back(*it
);
5478 // make sure that -init symbol exists
5479 if ( fInitFunctionName
!= NULL
)
5480 fInitialUndefines
.push_back(fInitFunctionName
);
5482 // make sure that entry symbol exists
5483 switch ( fOutputKind
) {
5484 case Options::kDynamicExecutable
:
5485 case Options::kStaticExecutable
:
5486 case Options::kDyld
:
5487 case Options::kPreload
:
5488 fInitialUndefines
.push_back(fEntryName
);
5490 case Options::kDynamicLibrary
:
5491 case Options::kDynamicBundle
:
5492 case Options::kObjectFile
:
5493 case Options::kKextBundle
:
5497 // make sure every alias base exists
5498 for (std::vector
<AliasPair
>::iterator it
=fAliases
.begin(); it
!= fAliases
.end(); ++it
) {
5499 fInitialUndefines
.push_back(it
->realName
);
5502 // check custom segments
5503 if ( fCustomSegmentAddresses
.size() != 0 ) {
5504 // verify no segment is in zero page
5505 if ( fZeroPageSize
!= ULLONG_MAX
) {
5506 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
5507 if ( it
->address
< fZeroPageSize
)
5508 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it
->name
, it
->address
);
5511 // verify no duplicates
5512 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
5513 for (std::vector
<SegmentStart
>::iterator it2
= fCustomSegmentAddresses
.begin(); it2
!= fCustomSegmentAddresses
.end(); ++it2
) {
5514 if ( (it
->address
== it2
->address
) && (it
!= it2
) )
5515 throwf("duplicate -segaddr addresses for %s and %s", it
->name
, it2
->name
);
5517 // a custom segment address of zero will disable the use of a zero page
5518 if ( it
->address
== 0 )
5523 if ( fZeroPageSize
== ULLONG_MAX
) {
5524 // zero page size not specified on command line, set default
5525 switch (fArchitecture
) {
5528 // first 4KB for 32-bit architectures
5529 fZeroPageSize
= 0x1000;
5531 case CPU_TYPE_ARM64
:
5532 case CPU_TYPE_X86_64
:
5533 // first 4GB for x86_64 on all OS's
5534 fZeroPageSize
= 0x100000000ULL
;
5537 // if -arch not used, default to 4K zero-page
5538 fZeroPageSize
= 0x1000;
5542 switch ( fOutputKind
) {
5543 case Options::kDynamicExecutable
:
5544 case Options::kStaticExecutable
:
5545 // -pagezero_size size only legal when building main executable
5547 case Options::kDynamicLibrary
:
5548 case Options::kDynamicBundle
:
5549 case Options::kObjectFile
:
5550 case Options::kDyld
:
5551 case Options::kPreload
:
5552 case Options::kKextBundle
:
5553 if ( fZeroPageSize
!= 0 )
5554 throw "-pagezero_size option can only be used when linking a main executable";
5558 // if main executable with custom base address, model zero page as custom segment
5559 if ( (fOutputKind
== Options::kDynamicExecutable
) && (fBaseAddress
!= 0) && (fZeroPageSize
!= 0) ) {
5561 seg
.name
= "__PAGEZERO";
5563 fCustomSegmentAddresses
.push_back(seg
);
5566 // -dead_strip and -r are incompatible
5567 if ( fDeadStrip
&& (fOutputKind
== Options::kObjectFile
) )
5568 throw "-r and -dead_strip cannot be used together";
5570 // can't use -rpath unless targeting 10.5 or later
5571 if ( fRPaths
.size() > 0 ) {
5572 if ( !minOS(ld::mac10_5
, ld::iOS_2_0
) )
5573 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
5574 switch ( fOutputKind
) {
5575 case Options::kDynamicExecutable
:
5576 case Options::kDynamicLibrary
:
5577 case Options::kDynamicBundle
:
5579 case Options::kStaticExecutable
:
5580 case Options::kObjectFile
:
5581 case Options::kDyld
:
5582 case Options::kPreload
:
5583 case Options::kKextBundle
:
5584 throw "-rpath can only be used when creating a dynamic final linked image";
5588 if ( fPositionIndependentExecutable
) {
5589 switch ( fOutputKind
) {
5590 case Options::kDynamicExecutable
:
5591 // check -pie is only used when building a dynamic main executable for 10.5
5592 if ( !minOS(ld::mac10_5
, ld::iOS_4_2
) ) {
5593 if ( fIOSVersionMin
== ld::iOSVersionUnset
)
5594 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
5596 throw "-pie can only be used when targeting iOS 4.2 or later";
5599 case Options::kStaticExecutable
:
5600 case Options::kPreload
:
5601 // -pie is ok with -static or -preload
5603 case Options::kDynamicLibrary
:
5604 case Options::kDynamicBundle
:
5605 warning("-pie being ignored. It is only used when linking a main executable");
5606 fPositionIndependentExecutable
= false;
5608 case Options::kObjectFile
:
5609 case Options::kDyld
:
5610 case Options::kKextBundle
:
5611 throw "-pie can only be used when linking a main executable";
5615 // check -read_only_relocs is not used with x86_64
5616 if ( fAllowTextRelocs
) {
5617 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
!= kKextBundle
) ) {
5618 warning("-read_only_relocs cannot be used with x86_64");
5619 fAllowTextRelocs
= false;
5623 // check -mark_auto_dead_strip is only used with dylibs
5624 if ( fMarkDeadStrippableDylib
) {
5625 if ( fOutputKind
!= Options::kDynamicLibrary
) {
5626 warning("-mark_auto_dead_strip can only be used when creating a dylib");
5627 fMarkDeadStrippableDylib
= false;
5631 // -force_cpusubtype_ALL is not supported for ARM
5632 if ( fForceSubtypeAll
) {
5633 if ( fArchitecture
== CPU_TYPE_ARM
) {
5634 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
5638 // -reexported_symbols_list can only be used with -dynamiclib
5639 if ( !fReExportSymbols
.empty() ) {
5640 if ( fOutputKind
!= Options::kDynamicLibrary
)
5641 throw "-reexported_symbols_list can only used used when created dynamic libraries";
5642 if ( !minOS(ld::mac10_7
, ld::iOS_4_2
) )
5643 throw "targeted OS version does not support -reexported_symbols_list";
5646 // -dyld_env can only be used with main executables
5647 if ( (fOutputKind
!= Options::kDynamicExecutable
) && (fDyldEnvironExtras
.size() != 0) )
5648 throw "-dyld_env can only used used when created main executables";
5650 // -segment_order can only be used with -preload or -static
5651 if ( !fSegmentOrder
.empty() && ((fOutputKind
!= Options::kPreload
) && (fOutputKind
!= kStaticExecutable
)) )
5652 throw "-segment_order can only used used with -preload output";
5654 // warn about bitcode option combinations
5655 if ( !fBundleBitcode
) {
5656 if ( fVerifyBitcode
)
5657 warning("-bitcode_verify is ignored without -bitcode_bundle");
5658 else if ( fHideSymbols
)
5659 warning("-bitcode_hide_symbols is ignored without -bitcode_bundle");
5661 if ( fReverseMapPath
!= NULL
&& !fHideSymbols
) {
5662 throw "-bitcode_symbol_map can only be used with -bitcode_hide_symbols";
5664 if ( fBitcodeKind
!= kBitcodeProcess
&&
5665 fOutputKind
!= Options::kObjectFile
) {
5666 throw "-bitcode_process_mode can only be used together with -r";
5668 // auto fix up the process type for strip -S.
5669 // when there is only one input and output type is object file, downgrade kBitcodeProcess to kBitcodeAsData.
5670 if ( fOutputKind
== Options::kObjectFile
&& fInputFiles
.size() == 1 && fBitcodeKind
== Options::kBitcodeProcess
)
5671 fBitcodeKind
= Options::kBitcodeAsData
;
5673 // <rdar://problem/17598404> warn if building an embedded iOS dylib for pre-iOS 8
5674 // <rdar://problem/18935714> How can we suppress "ld: warning: embedded dylibs/frameworks only run on iOS 8 or later" when building XCTest?
5675 if ( (fOutputKind
== Options::kDynamicLibrary
) && (fIOSVersionMin
!= ld::iOSVersionUnset
) && (fDylibInstallName
!= NULL
) ) {
5676 if ( !min_iOS(ld::iOS_8_0
) && (fDylibInstallName
[0] == '@') && !fEncryptableForceOff
)
5677 warning("embedded dylibs/frameworks only run on iOS 8 or later");
5681 // produce nicer error when no input
5682 if ( fInputFiles
.empty() ) {
5683 throw "no object files specified";
5688 void Options::checkForClassic(int argc
, const char* argv
[])
5691 bool archFound
= false;
5692 bool staticFound
= false;
5693 bool dtraceFound
= false;
5694 bool kextFound
= false;
5695 bool rFound
= false;
5696 bool creatingMachKernel
= false;
5697 bool newLinker
= false;
5699 // build command line buffer in case ld crashes
5700 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
5701 CRSetCrashLogMessage(crashreporterBuffer
);
5703 const char* srcRoot
= getenv("SRCROOT");
5704 if ( srcRoot
!= NULL
) {
5705 strlcpy(crashreporterBuffer
, "SRCROOT=", crashreporterBufferSize
);
5706 strlcat(crashreporterBuffer
, srcRoot
, crashreporterBufferSize
);
5707 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
5710 strlcat(crashreporterBuffer
, LD_VERS
, crashreporterBufferSize
);
5711 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
5713 strlcat(crashreporterBuffer
, "ld ", crashreporterBufferSize
);
5714 for(int i
=1; i
< argc
; ++i
) {
5715 strlcat(crashreporterBuffer
, argv
[i
], crashreporterBufferSize
);
5716 strlcat(crashreporterBuffer
, " ", crashreporterBufferSize
);
5719 for(int i
=0; i
< argc
; ++i
) {
5720 const char* arg
= argv
[i
];
5721 if ( arg
[0] == '-' ) {
5722 if ( strcmp(arg
, "-arch") == 0 ) {
5723 parseArch(argv
[++i
]);
5726 else if ( strcmp(arg
, "-static") == 0 ) {
5729 else if ( strcmp(arg
, "-kext") == 0 ) {
5732 else if ( strcmp(arg
, "-dtrace") == 0 ) {
5735 else if ( strcmp(arg
, "-r") == 0 ) {
5738 else if ( strcmp(arg
, "-new_linker") == 0 ) {
5741 else if ( strcmp(arg
, "-classic_linker") == 0 ) {
5742 // ld_classic does not understand this option, so remove it
5743 for(int j
=i
; j
< argc
; ++j
)
5744 argv
[j
] = argv
[j
+1];
5745 warning("using ld_classic");
5746 this->gotoClassicLinker(argc
-1, argv
);
5748 else if ( strcmp(arg
, "-o") == 0 ) {
5749 const char* outfile
= argv
[++i
];
5750 if ( (outfile
!= NULL
) && (strstr(outfile
, "/mach_kernel") != NULL
) )
5751 creatingMachKernel
= true;
5757 void Options::gotoClassicLinker(int argc
, const char* argv
[])
5759 argv
[0] = "ld_classic";
5760 // ld_classic does not support -iphoneos_version_min, so change
5761 for(int j
=0; j
< argc
; ++j
) {
5762 if ( (strcmp(argv
[j
], "-iphoneos_version_min") == 0) || (strcmp(argv
[j
], "-ios_version_min") == 0) ) {
5763 argv
[j
] = "-macosx_version_min";
5769 // ld classic does not understand -kext (change to -static -r)
5770 for(int j
=0; j
< argc
; ++j
) {
5771 if ( strcmp(argv
[j
], "-kext") == 0)
5773 else if ( strcmp(argv
[j
], "-dynamic") == 0)
5774 argv
[j
] = "-static";
5776 // ld classic does not understand -demangle
5777 for(int j
=0; j
< argc
; ++j
) {
5778 if ( strcmp(argv
[j
], "-demangle") == 0)
5779 argv
[j
] = "-noprebind";
5781 // in -v mode, print command line passed to ld_classic
5782 for(int i
=0; i
< argc
; ++i
) {
5783 if ( strcmp(argv
[i
], "-v") == 0 ) {
5784 for(int j
=0; j
< argc
; ++j
)
5785 printf("%s ", argv
[j
]);
5790 char rawPath
[PATH_MAX
];
5791 char path
[PATH_MAX
];
5792 uint32_t bufSize
= PATH_MAX
;
5793 if ( _NSGetExecutablePath(rawPath
, &bufSize
) != -1 ) {
5794 if ( realpath(rawPath
, path
) != NULL
) {
5795 char* lastSlash
= strrchr(path
, '/');
5796 if ( lastSlash
!= NULL
) {
5797 strcpy(lastSlash
+1, "ld_classic");
5799 execvp(path
, (char**)argv
);
5803 // in case of error in above, try searching for ld_classic via PATH
5804 execvp(argv
[0], (char**)argv
);
5805 fprintf(stderr
, "can't exec ld_classic\n");
5810 // Note, returned string buffer is own by this function.
5811 // It should not be freed
5812 // It will be reused, so clients need to strdup() if they want
5813 // to use it long term.
5814 const char* Options::demangleSymbol(const char* sym
) const
5816 // only try to demangle symbols if -demangle on command line
5820 static size_t size
= 1024;
5821 static char* buff
= (char*)malloc(size
);
5824 // only try to demangle symbols that look like Swift symbols
5825 if ( strncmp(sym
, "__T", 3) == 0 ) {
5826 size_t demangledSize
= fnd_get_demangled_name(&sym
[1], buff
, size
);
5827 if ( demangledSize
> size
) {
5828 size
= demangledSize
+2;
5829 buff
= (char*)realloc(buff
, size
);
5830 demangledSize
= fnd_get_demangled_name(&sym
[1], buff
, size
);
5832 if ( demangledSize
!= 0 )
5837 // only try to demangle symbols that look like C++ symbols
5838 if ( strncmp(sym
, "__Z", 3) != 0 )
5842 char* result
= abi::__cxa_demangle(&sym
[1], buff
, &size
, &status
);
5843 if ( result
!= NULL
) {
5844 // if demangling successful, keep buffer for next demangle
5852 void Options::dumpDependency(uint8_t opcode
, const char* path
) const
5854 if ( !this->dumpDependencyInfo() )
5857 // one time open() of -dependency_info file
5858 if ( fDependencyFileDescriptor
== -1 ) {
5859 fDependencyFileDescriptor
= open(this->dependencyInfoPath(), O_WRONLY
| O_TRUNC
| O_CREAT
, 0666);
5860 if ( fDependencyFileDescriptor
== -1 )
5861 throwf("Could not open or create -dependency_info file: %s", this->dependencyInfoPath());
5864 uint8_t version
= depLinkerVersion
;
5865 if ( write(fDependencyFileDescriptor
, &version
, 1) == -1 )
5866 throwf("write() to -dependency_info failed, errno=%d", errno
);
5867 extern const char ldVersionString
[];
5868 if ( write(fDependencyFileDescriptor
, ldVersionString
, strlen(ldVersionString
)+1) == -1 )
5869 throwf("write() to -dependency_info failed, errno=%d", errno
);
5872 char realPath
[PATH_MAX
];
5873 if ( path
[0] != '/' ) {
5874 if ( realpath(path
, realPath
) != NULL
) {
5879 if ( write(fDependencyFileDescriptor
, &opcode
, 1) == -1 )
5880 throwf("write() to -dependency_info failed, errno=%d", errno
);
5881 if ( write(fDependencyFileDescriptor
, path
, strlen(path
)+1) == -1 )
5882 throwf("write() to -dependency_info failed, errno=%d", errno
);
5884 //fprintf(stderr, "0x%02X %s\n", opcode, path);