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>
41 #include "Architectures.hpp"
42 #include "MachOFileAbstraction.hpp"
45 // upward dependency on lto::version()
47 extern const char* version();
50 // magic to place command line in crash reports
51 const int crashreporterBufferSize
= 2000;
52 static char crashreporterBuffer
[crashreporterBufferSize
];
53 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
54 #include <CrashReporterClient.h>
55 // hack until ld does not need to build on 10.6 anymore
56 struct crashreporter_annotations_t gCRAnnotations
57 __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION
)))
58 = { CRASHREPORTER_ANNOTATIONS_VERSION
, 0, 0, 0, 0, 0, 0 };
60 extern "C" char* __crashreporter_info__
;
62 char* __crashreporter_info__
= crashreporterBuffer
;
66 static bool sEmitWarnings
= true;
67 static bool sFatalWarnings
= false;
68 static const char* sWarningsSideFilePath
= NULL
;
69 static FILE* sWarningsSideFile
= NULL
;
70 static int sWarningsCount
= 0;
72 void warning(const char* format
, ...)
75 if ( sEmitWarnings
) {
77 if ( sWarningsSideFilePath
!= NULL
) {
78 if ( sWarningsSideFile
== NULL
)
79 sWarningsSideFile
= fopen(sWarningsSideFilePath
, "a");
81 va_start(list
, format
);
82 fprintf(stderr
, "ld: warning: ");
83 vfprintf(stderr
, format
, list
);
84 fprintf(stderr
, "\n");
85 if ( sWarningsSideFile
!= NULL
) {
86 fprintf(sWarningsSideFile
, "ld: warning: ");
87 vfprintf(sWarningsSideFile
, format
, list
);
88 fprintf(sWarningsSideFile
, "\n");
89 fflush(sWarningsSideFile
);
95 void throwf(const char* format
, ...)
99 va_start(list
, format
);
100 vasprintf(&p
, format
, list
);
108 bool Options::FileInfo::checkFileExists(const Options
& options
, const char *p
)
110 struct stat statBuffer
;
113 if ( stat(p
, &statBuffer
) == 0 ) {
114 if (p
!= path
) path
= strdup(p
);
115 fileLen
= statBuffer
.st_size
;
116 modTime
= statBuffer
.st_mtime
;
119 if ( options
.dumpDependencyInfo() )
120 options
.dumpDependency(Options::depNotFound
, p
);
125 Options::Options(int argc
, const char* argv
[])
126 : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0), fArchitectureName("unknown"), fOutputKind(kDynamicExecutable
),
127 fHasPreferredSubType(false), fArchSupportsThumb2(false), fPrebind(false), fBindAtLoad(false), fKeepPrivateExterns(false),
128 fNeedsModuleTable(false), fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false),
129 fInterposeMode(kInterposeNone
), fDeadStrip(false), fNameSpace(kTwoLevelNameSpace
),
130 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL
), fFinalName(NULL
), fEntryName("start"),
131 fBaseAddress(0), fMaxAddress(0x7FFFFFFFFFFFFFFFLL
),
132 fBaseWritableAddress(0), fSplitSegs(false),
133 fExportMode(kExportDefault
), fLibrarySearchMode(kSearchDylibAndArchiveInEachDir
),
134 fUndefinedTreatment(kUndefinedError
), fMessagesPrefixedWithArchitecture(true),
135 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak
),
137 fUmbrellaName(NULL
), fInitFunctionName(NULL
), fDotOutputFile(NULL
), fExecutablePath(NULL
),
138 fBundleLoader(NULL
), fDtraceScriptName(NULL
), fSegAddrTablePath(NULL
), fMapPath(NULL
),
139 fDyldInstallPath("/usr/lib/dyld"), fTempLtoObjectPath(NULL
), fOverridePathlibLTO(NULL
), fLtoCpu(NULL
),
140 fZeroPageSize(ULLONG_MAX
), fStackSize(0), fStackAddr(0), fSourceVersion(0), fSDKVersion(0), fExecutableStack(false),
141 fNonExecutableHeap(false), fDisableNonExecutableHeap(false),
142 fMinimumHeaderPad(32), fSegmentAlignment(4096),
143 fCommonsMode(kCommonsIgnoreDylibs
), fUUIDMode(kUUIDContent
), fLocalSymbolHandling(kLocalSymbolsAll
), fWarnCommons(false),
144 fVerbose(false), fKeepRelocations(false), fWarnStabs(false),
145 fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
146 fSharedRegionEligible(false), fPrintOrderFileStatistics(false),
147 fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), fPIEOnCommandLine(false),
148 fDisablePositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
149 fDeadStripDylibs(false), fAllowTextRelocs(false), fWarnTextRelocs(false), fKextsUseStubs(false),
150 fUsingLazyDylibLinking(false), fEncryptable(true),
151 fOrderData(true), fMarkDeadStrippableDylib(false),
152 fMakeCompressedDyldInfo(true), fMakeCompressedDyldInfoForceOff(false), fNoEHLabels(false),
153 fAllowCpuSubtypeMismatches(false), fUseSimplifiedDylibReExports(false),
154 fObjCABIVersion2Override(false), fObjCABIVersion1Override(false), fCanUseUpwardDylib(false),
155 fFullyLoadArchives(false), fLoadAllObjcObjectsFromArchives(false), fFlatNamespace(false),
156 fLinkingMainExecutable(false), fForFinalLinkedImage(false), fForStatic(false),
157 fForDyld(false), fMakeTentativeDefinitionsReal(false), fWhyLoad(false), fRootSafe(false),
158 fSetuidSafe(false), fImplicitlyLinkPublicDylibs(true), fAddCompactUnwindEncoding(true),
159 fWarnCompactUnwind(false), fRemoveDwarfUnwindIfCompactExists(false),
160 fAutoOrderInitializers(true), fOptimizeZeroFill(true), fMergeZeroFill(false), fLogObjectFiles(false),
161 fLogAllFiles(false), fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false),
162 fOutputSlidable(false), fWarnWeakExports(false),
163 fObjcGcCompaction(false), fObjCGc(false), fObjCGcOnly(false),
164 fDemangle(false), fTLVSupport(false),
165 fVersionLoadCommand(false), fVersionLoadCommandForcedOn(false),
166 fVersionLoadCommandForcedOff(false), fFunctionStartsLoadCommand(false),
167 fFunctionStartsForcedOn(false), fFunctionStartsForcedOff(false),
168 fDataInCodeInfoLoadCommand(false), fDataInCodeInfoLoadCommandForcedOn(false), fDataInCodeInfoLoadCommandForcedOff(false),
169 fCanReExportSymbols(false), fObjcCategoryMerging(true), fPageAlignDataAtoms(false),
170 fNeedsThreadLoadCommand(false), fEntryPointLoadCommand(false),
171 fEntryPointLoadCommandForceOn(false), fEntryPointLoadCommandForceOff(false),
172 fSourceVersionLoadCommand(false),
173 fSourceVersionLoadCommandForceOn(false), fSourceVersionLoadCommandForceOff(false),
174 fDependentDRInfo(false), fDependentDRInfoForcedOn(false), fDependentDRInfoForcedOff(false),
175 fTargetIOSSimulator(false), fExportDynamic(false), fAbsoluteSymbols(false),
176 fAllowSimulatorToLinkWithMacOSX(false), fKeepDwarfUnwind(true),
177 fKeepDwarfUnwindForcedOn(false), fKeepDwarfUnwindForcedOff(false),
178 fGenerateDtraceDOF(true),
179 fDebugInfoStripping(kDebugInfoMinimal
), fTraceOutputFile(NULL
),
180 fMacVersionMin(ld::macVersionUnset
), fIOSVersionMin(ld::iOSVersionUnset
),
181 fSaveTempFiles(false), fSnapshotRequested(false), fPipelineFifo(NULL
),
182 fDependencyInfoPath(NULL
), fDependencyFileDescriptor(-1)
184 this->checkForClassic(argc
, argv
);
185 this->parsePreCommandLineEnvironmentSettings();
186 this->parse(argc
, argv
);
187 this->parsePostCommandLineEnvironmentSettings();
188 this->reconfigureDefaults();
189 this->checkIllegalOptionCombinations();
191 if ( this->dumpDependencyInfo() ) {
192 this->dumpDependency(depOutputFile
, fOutputFile
);
193 if ( fMapPath
!= NULL
)
194 this->dumpDependency(depOutputFile
, fMapPath
);
200 if ( fDependencyFileDescriptor
!= -1 )
201 ::close(fDependencyFileDescriptor
);
204 bool Options::errorBecauseOfWarnings() const
206 return (sFatalWarnings
&& (sWarningsCount
> 0));
210 const char* Options::installPath() const
212 if ( fDylibInstallName
!= NULL
)
213 return fDylibInstallName
;
214 else if ( fFinalName
!= NULL
)
221 bool Options::interposable(const char* name
) const
223 switch ( fInterposeMode
) {
226 case kInterposeAllExternal
:
229 return fInterposeList
.contains(name
);
231 throw "internal error";
235 bool Options::printWhyLive(const char* symbolName
) const
237 return ( fWhyLive
.find(symbolName
) != fWhyLive
.end() );
241 const char* Options::dotOutputFile()
243 return fDotOutputFile
;
247 bool Options::hasWildCardExportRestrictList() const
249 // has -exported_symbols_list which contains some wildcards
250 return ((fExportMode
== kExportSome
) && fExportSymbols
.hasWildCards());
253 bool Options::hasWeakBitTweaks() const
255 // has -exported_symbols_list which contains some wildcards
256 return (!fForceWeakSymbols
.empty() || !fForceNotWeakSymbols
.empty());
259 bool Options::allGlobalsAreDeadStripRoots() const
261 // -exported_symbols_list means globals are not exported by default
262 if ( fExportMode
== kExportSome
)
265 switch ( fOutputKind
) {
266 case Options::kDynamicExecutable
:
267 // <rdar://problem/12839986> Add the -export_dynamic flag
268 return fExportDynamic
;
269 case Options::kStaticExecutable
:
270 // <rdar://problem/13361218> Support the -export_dynamic flag for xnu
271 return fExportDynamic
;
272 case Options::kPreload
:
273 // by default unused globals in a main executable are stripped
275 case Options::kDynamicLibrary
:
276 case Options::kDynamicBundle
:
277 case Options::kObjectFile
:
279 case Options::kKextBundle
:
286 bool Options::keepRelocations()
288 return fKeepRelocations
;
291 bool Options::warnStabs()
296 const char* Options::executablePath()
298 return fExecutablePath
;
301 uint32_t Options::initialSegProtection(const char* segName
) const
303 for(std::vector
<Options::SegmentProtect
>::const_iterator it
= fCustomSegmentProtections
.begin(); it
!= fCustomSegmentProtections
.end(); ++it
) {
304 if ( strcmp(it
->name
, segName
) == 0 ) {
308 if ( strcmp(segName
, "__PAGEZERO") == 0 ) {
311 else if ( strcmp(segName
, "__TEXT") == 0 ) {
312 return VM_PROT_READ
| VM_PROT_EXECUTE
;
314 else if ( strcmp(segName
, "__LINKEDIT") == 0 ) {
318 // all others default to read-write
319 return VM_PROT_READ
| VM_PROT_WRITE
;
322 uint32_t Options::maxSegProtection(const char* segName
) const
324 // iPhoneOS always uses same protection for max and initial
325 // <rdar://problem/11663436> simulator apps need to use MacOSX max-prot
326 if ( (fIOSVersionMin
!= ld::iOSVersionUnset
) && (fArchitecture
!= CPU_TYPE_I386
) )
327 return initialSegProtection(segName
);
329 for(std::vector
<Options::SegmentProtect
>::const_iterator it
= fCustomSegmentProtections
.begin(); it
!= fCustomSegmentProtections
.end(); ++it
) {
330 if ( strcmp(it
->name
, segName
) == 0 ) {
334 if ( strcmp(segName
, "__PAGEZERO") == 0 ) {
337 // all others default to all
338 return VM_PROT_READ
| VM_PROT_WRITE
| VM_PROT_EXECUTE
;
341 uint64_t Options::segPageSize(const char* segName
) const
343 for(std::vector
<SegmentSize
>::const_iterator it
=fCustomSegmentSizes
.begin(); it
!= fCustomSegmentSizes
.end(); ++it
) {
344 if ( strcmp(it
->name
, segName
) == 0 )
347 return fSegmentAlignment
;
350 uint64_t Options::customSegmentAddress(const char* segName
) const
352 for(std::vector
<SegmentStart
>::const_iterator it
=fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
353 if ( strcmp(it
->name
, segName
) == 0 )
356 // if custom stack in use, model as segment with custom address
357 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
358 return fStackAddr
- fStackSize
;
362 bool Options::hasCustomSegmentAddress(const char* segName
) const
364 for(std::vector
<SegmentStart
>::const_iterator it
=fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
365 if ( strcmp(it
->name
, segName
) == 0 )
368 // if custom stack in use, model as segment with custom address
369 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
374 bool Options::hasCustomSectionAlignment(const char* segName
, const char* sectName
) const
376 for (std::vector
<SectionAlignment
>::const_iterator it
= fSectionAlignments
.begin(); it
!= fSectionAlignments
.end(); ++it
) {
377 if ( (strcmp(it
->segmentName
, segName
) == 0) && (strcmp(it
->sectionName
, sectName
) == 0) )
383 uint8_t Options::customSectionAlignment(const char* segName
, const char* sectName
) const
385 for (std::vector
<SectionAlignment
>::const_iterator it
= fSectionAlignments
.begin(); it
!= fSectionAlignments
.end(); ++it
) {
386 if ( (strcmp(it
->segmentName
, segName
) == 0) && (strcmp(it
->sectionName
, sectName
) == 0) )
387 return it
->alignment
;
393 bool Options::hasExportedSymbolOrder()
395 return (fExportSymbolsOrder
.size() > 0);
398 bool Options::exportedSymbolOrder(const char* sym
, unsigned int* order
) const
400 NameToOrder::const_iterator pos
= fExportSymbolsOrder
.find(sym
);
401 if ( pos
!= fExportSymbolsOrder
.end() ) {
402 *order
= pos
->second
;
411 void Options::loadSymbolOrderFile(const char* fileOfExports
, NameToOrder
& orderMapping
)
413 // read in whole file
414 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
416 throwf("can't open -exported_symbols_order file: %s", fileOfExports
);
417 struct stat stat_buf
;
418 ::fstat(fd
, &stat_buf
);
419 char* p
= (char*)malloc(stat_buf
.st_size
);
421 throwf("can't process -exported_symbols_order file: %s", fileOfExports
);
423 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
424 throwf("can't read -exported_symbols_order file: %s", fileOfExports
);
428 // parse into symbols and add to unordered_set
429 unsigned int count
= 0;
430 char * const end
= &p
[stat_buf
.st_size
];
431 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
432 char* symbolStart
= NULL
;
433 for (char* s
= p
; s
< end
; ++s
) {
439 else if ( !isspace(*s
) ) {
445 if ( (*s
== '\n') || (*s
== '\r') ) {
447 // removing any trailing spaces
449 while ( isspace(*last
) ) {
453 orderMapping
[symbolStart
] = ++count
;
459 if ( (*s
== '\n') || (*s
== '\r') )
464 if ( state
== inSymbol
) {
465 warning("missing line-end at end of file \"%s\"", fileOfExports
);
466 int len
= end
-symbolStart
+1;
467 char* temp
= new char[len
];
468 strlcpy(temp
, symbolStart
, len
);
470 // remove any trailing spaces
471 char* last
= &temp
[len
-2];
472 while ( isspace(*last
) ) {
476 orderMapping
[temp
] = ++count
;
479 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
482 bool Options::forceWeak(const char* symbolName
) const
484 return fForceWeakSymbols
.contains(symbolName
);
487 bool Options::forceNotWeak(const char* symbolName
) const
489 return fForceNotWeakSymbols
.contains(symbolName
);
492 bool Options::forceWeakNonWildCard(const char* symbolName
) const
494 return fForceWeakSymbols
.containsNonWildcard(symbolName
);
497 bool Options::forceNotWeakNonWildcard(const char* symbolName
) const
499 return fForceNotWeakSymbols
.containsNonWildcard(symbolName
);
502 bool Options::forceCoalesce(const char* symbolName
) const
504 return fForceCoalesceSymbols
.contains(symbolName
);
508 bool Options::shouldExport(const char* symbolName
) const
510 switch (fExportMode
) {
512 return fExportSymbols
.contains(symbolName
);
513 case kDontExportSome
:
514 return ! fDontExportSymbols
.contains(symbolName
);
518 throw "internal error";
521 bool Options::shouldReExport(const char* symbolName
) const
523 return fReExportSymbols
.contains(symbolName
);
526 bool Options::keepLocalSymbol(const char* symbolName
) const
528 switch (fLocalSymbolHandling
) {
529 case kLocalSymbolsAll
:
531 case kLocalSymbolsNone
:
533 case kLocalSymbolsSelectiveInclude
:
534 return fLocalSymbolsIncluded
.contains(symbolName
);
535 case kLocalSymbolsSelectiveExclude
:
536 return ! fLocalSymbolsExcluded
.contains(symbolName
);
538 throw "internal error";
541 void Options::setArchitecture(cpu_type_t type
, cpu_subtype_t subtype
)
543 for (const ArchInfo
* t
=archInfoArray
; t
->archName
!= NULL
; ++t
) {
544 if ( (type
== t
->cpuType
) && (subtype
== t
->cpuSubType
) ) {
545 fArchitecture
= type
;
546 fSubArchitecture
= subtype
;
547 fArchitectureName
= t
->archName
;
548 fHasPreferredSubType
= t
->isSubType
;
549 fArchSupportsThumb2
= t
->supportsThumb2
;
552 case CPU_TYPE_X86_64
:
553 if ( (fMacVersionMin
== ld::macVersionUnset
) && (fIOSVersionMin
== ld::iOSVersionUnset
) && (fOutputKind
!= Options::kObjectFile
) ) {
554 #ifdef DEFAULT_MACOSX_MIN_VERSION
555 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION
);
556 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
558 warning("-macosx_version_min not specified, assuming 10.6");
559 fMacVersionMin
= ld::mac10_6
;
565 if ( (fMacVersionMin
== ld::macVersionUnset
) && (fIOSVersionMin
== ld::iOSVersionUnset
) && (fOutputKind
!= Options::kObjectFile
) ) {
566 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
567 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION
);
568 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION
);
570 warning("-ios_version_min not specified, assuming 6.0");
571 setIOSVersionMin("6.0");
576 fLinkSnapshot
.recordArch(fArchitectureName
);
577 // only use compressed LINKEDIT for:
578 // Mac OS X 10.6 or later
580 if ( !fMakeCompressedDyldInfo
&& minOS(ld::mac10_6
, ld::iOS_3_1
) && !fMakeCompressedDyldInfoForceOff
)
581 fMakeCompressedDyldInfo
= true;
582 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
583 if ( minOS(ld::mac10_5
, ld::iOS_2_0
) )
584 fUseSimplifiedDylibReExports
= true;
588 fArchitectureName
= "unknown architecture";
591 void Options::parseArch(const char* arch
)
594 throw "-arch must be followed by an architecture string";
595 for (const ArchInfo
* t
=archInfoArray
; t
->archName
!= NULL
; ++t
) {
596 if ( strcmp(t
->archName
,arch
) == 0 ) {
597 fArchitectureName
= arch
;
598 fArchitecture
= t
->cpuType
;
599 fSubArchitecture
= t
->cpuSubType
;
600 fHasPreferredSubType
= t
->isSubType
;
601 fArchSupportsThumb2
= t
->supportsThumb2
;
605 throwf("unknown/unsupported architecture name for: -arch %s", arch
);
608 bool Options::checkForFile(const char* format
, const char* dir
, const char* rootName
, FileInfo
& result
) const
610 char possiblePath
[strlen(dir
)+strlen(rootName
)+strlen(format
)+8];
611 sprintf(possiblePath
, format
, dir
, rootName
);
612 bool found
= result
.checkFileExists(*this, possiblePath
);
613 if ( fTraceDylibSearching
)
614 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), possiblePath
);
619 Options::FileInfo
Options::findLibrary(const char* rootName
, bool dylibsOnly
) const
622 const int rootNameLen
= strlen(rootName
);
623 // if rootName ends in .o there is no .a vs .dylib choice
624 if ( (rootNameLen
> 3) && (strcmp(&rootName
[rootNameLen
-2], ".o") == 0) ) {
625 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
626 it
!= fLibrarySearchPaths
.end();
628 const char* dir
= *it
;
629 if ( checkForFile("%s/%s", dir
, rootName
, result
) )
634 bool lookForDylibs
= ( fOutputKind
!= Options::kDyld
);
635 switch ( fLibrarySearchMode
) {
636 case kSearchAllDirsForDylibsThenAllDirsForArchives
:
637 // first look in all directories for just for dylibs
638 if ( lookForDylibs
) {
639 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
640 it
!= fLibrarySearchPaths
.end();
642 const char* dir
= *it
;
643 if ( checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
646 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
647 it
!= fLibrarySearchPaths
.end();
649 const char* dir
= *it
;
650 if ( checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
654 // next look in all directories for just for archives
656 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
657 it
!= fLibrarySearchPaths
.end();
659 const char* dir
= *it
;
660 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
666 case kSearchDylibAndArchiveInEachDir
:
667 // look in each directory for just for a dylib then for an archive
668 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
669 it
!= fLibrarySearchPaths
.end();
671 const char* dir
= *it
;
672 if ( lookForDylibs
&& checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
674 if ( lookForDylibs
&& checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
676 if ( !dylibsOnly
&& checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
682 throwf("library not found for -l%s", rootName
);
685 Options::FileInfo
Options::findFramework(const char* frameworkName
) const
687 if ( frameworkName
== NULL
)
688 throw "-framework missing next argument";
689 char temp
[strlen(frameworkName
)+1];
690 strcpy(temp
, frameworkName
);
691 const char* name
= temp
;
692 const char* suffix
= NULL
;
693 char* comma
= strchr(temp
, ',');
694 if ( comma
!= NULL
) {
698 return findFramework(name
, suffix
);
701 Options::FileInfo
Options::findFramework(const char* rootName
, const char* suffix
) const
703 for (std::vector
<const char*>::const_iterator it
= fFrameworkSearchPaths
.begin();
704 it
!= fFrameworkSearchPaths
.end();
706 // ??? Shouldn't we be using String here and just initializing it?
707 // ??? Use str.c_str () to pull out the string for the stat call.
708 const char* dir
= *it
;
709 char possiblePath
[PATH_MAX
];
710 strcpy(possiblePath
, dir
);
711 strcat(possiblePath
, "/");
712 strcat(possiblePath
, rootName
);
713 strcat(possiblePath
, ".framework/");
714 strcat(possiblePath
, rootName
);
715 if ( suffix
!= NULL
) {
716 char realPath
[PATH_MAX
];
717 // no symlink in framework to suffix variants, so follow main symlink
718 if ( realpath(possiblePath
, realPath
) != NULL
) {
719 strcpy(possiblePath
, realPath
);
720 strcat(possiblePath
, suffix
);
724 bool found
= result
.checkFileExists(*this, possiblePath
);
725 if ( fTraceDylibSearching
)
726 printf("[Logging for XBS]%sfound framework: '%s'\n",
727 (found
? " " : " not "), possiblePath
);
732 // try without suffix
733 if ( suffix
!= NULL
)
734 return findFramework(rootName
, NULL
);
736 throwf("framework not found %s", rootName
);
739 Options::FileInfo
Options::findFile(const char* path
) const
743 // if absolute path and not a .o file, the use SDK prefix
744 if ( (path
[0] == '/') && (strcmp(&path
[strlen(path
)-2], ".o") != 0) ) {
745 const int pathLen
= strlen(path
);
746 for (std::vector
<const char*>::const_iterator it
= fSDKPaths
.begin(); it
!= fSDKPaths
.end(); it
++) {
747 // ??? Shouldn't we be using String here?
748 const char* sdkPathDir
= *it
;
749 const int sdkPathDirLen
= strlen(sdkPathDir
);
750 char possiblePath
[sdkPathDirLen
+pathLen
+4];
751 strcpy(possiblePath
, sdkPathDir
);
752 if ( possiblePath
[sdkPathDirLen
-1] == '/' )
753 possiblePath
[sdkPathDirLen
-1] = '\0';
754 strcat(possiblePath
, path
);
755 if ( result
.checkFileExists(*this, possiblePath
) ) {
761 if ( result
.checkFileExists(*this, path
) ) {
765 // try @executable_path substitution
766 if ( (strncmp(path
, "@executable_path/", 17) == 0) && (fExecutablePath
!= NULL
) ) {
767 char newPath
[strlen(fExecutablePath
) + strlen(path
)];
768 strcpy(newPath
, fExecutablePath
);
769 char* addPoint
= strrchr(newPath
,'/');
770 if ( addPoint
!= NULL
)
771 strcpy(&addPoint
[1], &path
[17]);
773 strcpy(newPath
, &path
[17]);
774 if ( result
.checkFileExists(*this, newPath
) ) {
780 throwf("file not found: %s", path
);
783 Options::FileInfo
Options::findFileUsingPaths(const char* path
) const
787 const char* lastSlash
= strrchr(path
, '/');
788 const char* leafName
= (lastSlash
== NULL
) ? path
: &lastSlash
[1];
790 // Is this in a framework?
791 // /path/Foo.framework/Foo ==> true (Foo)
792 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
793 // /path/Foo.framework/Resources/Bar ==> false
794 bool isFramework
= false;
795 if ( lastSlash
!= NULL
) {
796 char frameworkDir
[strlen(leafName
) + 20];
797 strcpy(frameworkDir
, "/");
798 strcat(frameworkDir
, leafName
);
799 strcat(frameworkDir
, ".framework/");
800 if ( strstr(path
, frameworkDir
) != NULL
)
804 // These are abbreviated versions of the routines findFramework and findLibrary above
805 // because we already know the final name of the file that we're looking for and so
806 // don't need to try variations, just paths. We do need to add the additional bits
807 // onto the framework path though.
809 for (std::vector
<const char*>::const_iterator it
= fFrameworkSearchPaths
.begin();
810 it
!= fFrameworkSearchPaths
.end();
812 const char* dir
= *it
;
813 char possiblePath
[PATH_MAX
];
814 strcpy(possiblePath
, dir
);
815 strcat(possiblePath
, "/");
816 strcat(possiblePath
, leafName
);
817 strcat(possiblePath
, ".framework");
819 //fprintf(stderr,"Finding Framework: %s/%s, leafName=%s\n", possiblePath, leafName, leafName);
820 if ( checkForFile("%s/%s", possiblePath
, leafName
, result
) )
825 // if this is a .dylib inside a framework, do not search -L paths
826 // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
827 int leafLen
= strlen(leafName
);
828 bool embeddedDylib
= ( (leafLen
> 6)
829 && (strcmp(&leafName
[leafLen
-6], ".dylib") == 0)
830 && (strstr(path
, ".framework/") != NULL
) );
831 if ( !embeddedDylib
) {
832 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
833 it
!= fLibrarySearchPaths
.end();
835 const char* dir
= *it
;
836 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
837 if ( checkForFile("%s/%s", dir
, leafName
, result
) )
843 // If we didn't find it fall back to findFile.
844 return findFile(path
);
849 void Options::parseSegAddrTable(const char* segAddrPath
, const char* installPth
)
851 FILE* file
= fopen(segAddrPath
, "r");
852 if ( file
== NULL
) {
853 warning("-seg_addr_table file cannot be read: %s", segAddrPath
);
858 uint64_t firstColumAddress
= 0;
859 uint64_t secondColumAddress
= 0;
860 bool hasSecondColumn
= false;
861 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
862 path
[PATH_MAX
-1] = '\0';
863 char* eol
= strchr(path
, '\n');
866 // ignore lines not starting with 0x number
867 if ( (path
[0] == '0') && (path
[1] == 'x') ) {
869 firstColumAddress
= strtoull(path
, &p
, 16);
870 while ( isspace(*p
) )
872 // see if second column is a number
873 if ( (p
[0] == '0') && (p
[1] == 'x') ) {
874 secondColumAddress
= strtoull(p
, &p
, 16);
875 hasSecondColumn
= true;
876 while ( isspace(*p
) )
879 while ( isspace(*p
) )
882 // remove any trailing whitespace
883 for(char* end
= eol
-1; (end
> p
) && isspace(*end
); --end
)
885 // see if this line is for the dylib being linked
886 if ( strcmp(p
, installPth
) == 0 ) {
887 fBaseAddress
= firstColumAddress
;
888 if ( hasSecondColumn
) {
889 fBaseWritableAddress
= secondColumAddress
;
892 break; // out of while loop
901 void Options::loadFileList(const char* fileOfPaths
, ld::File::Ordinal baseOrdinal
)
904 const char* comma
= strrchr(fileOfPaths
, ',');
905 const char* prefix
= NULL
;
906 if ( comma
!= NULL
) {
907 // <rdar://problem/5907981> -filelist fails with comma in path
908 file
= fopen(fileOfPaths
, "r");
909 if ( file
== NULL
) {
911 int realFileOfPathsLen
= comma
-fileOfPaths
;
912 char realFileOfPaths
[realFileOfPathsLen
+1];
913 strncpy(realFileOfPaths
,fileOfPaths
, realFileOfPathsLen
);
914 realFileOfPaths
[realFileOfPathsLen
] = '\0';
915 file
= fopen(realFileOfPaths
, "r");
917 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", realFileOfPaths
, errno
, strerror(errno
));
918 if ( this->dumpDependencyInfo() )
919 this->dumpDependency(Options::depFileList
, realFileOfPaths
);
923 file
= fopen(fileOfPaths
, "r");
925 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", fileOfPaths
, errno
, strerror(errno
));
926 if ( this->dumpDependencyInfo() )
927 this->dumpDependency(Options::depFileList
, fileOfPaths
);
931 ld::File::Ordinal previousOrdinal
= baseOrdinal
;
932 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
933 path
[PATH_MAX
-1] = '\0';
934 char* eol
= strchr(path
, '\n');
937 if ( prefix
!= NULL
) {
938 char builtPath
[strlen(prefix
)+strlen(path
)+2];
939 strcpy(builtPath
, prefix
);
940 strcat(builtPath
, "/");
941 strcat(builtPath
, path
);
942 if (fPipelineFifo
!= NULL
) {
943 FileInfo info
= FileInfo(builtPath
);
944 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
945 previousOrdinal
= info
.ordinal
;
946 info
.fromFileList
= true;
947 fInputFiles
.push_back(info
);
949 FileInfo info
= findFile(builtPath
);
950 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
951 previousOrdinal
= info
.ordinal
;
952 info
.fromFileList
= true;
953 fInputFiles
.push_back(info
);
957 if (fPipelineFifo
!= NULL
) {
958 FileInfo info
= FileInfo(path
);
959 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
960 previousOrdinal
= info
.ordinal
;
961 info
.fromFileList
= true;
962 fInputFiles
.push_back(info
);
964 FileInfo info
= findFile(path
);
965 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
966 previousOrdinal
= info
.ordinal
;
967 info
.fromFileList
= true;
968 fInputFiles
.push_back(info
);
976 void Options::SetWithWildcards::remove(const NameSet
& toBeRemoved
)
978 for(NameSet::const_iterator it
=toBeRemoved
.begin(); it
!= toBeRemoved
.end(); ++it
) {
979 const char* symbolName
= *it
;
980 NameSet::iterator pos
= fRegular
.find(symbolName
);
981 if ( pos
!= fRegular
.end() )
986 bool Options::SetWithWildcards::hasWildCards(const char* symbol
)
988 // an exported symbol name containing *, ?, or [ requires wildcard matching
989 return ( strpbrk(symbol
, "*?[") != NULL
);
992 void Options::SetWithWildcards::insert(const char* symbol
)
994 if ( hasWildCards(symbol
) )
995 fWildCard
.push_back(symbol
);
997 fRegular
.insert(symbol
);
1000 bool Options::SetWithWildcards::contains(const char* symbol
) const
1002 // first look at hash table on non-wildcard symbols
1003 if ( fRegular
.find(symbol
) != fRegular
.end() )
1005 // next walk list of wild card symbols looking for a match
1006 for(std::vector
<const char*>::const_iterator it
= fWildCard
.begin(); it
!= fWildCard
.end(); ++it
) {
1007 if ( wildCardMatch(*it
, symbol
) )
1013 bool Options::SetWithWildcards::containsNonWildcard(const char* symbol
) const
1015 // look at hash table on non-wildcard symbols
1016 return ( fRegular
.find(symbol
) != fRegular
.end() );
1021 bool Options::SetWithWildcards::inCharRange(const char*& p
, unsigned char c
) const
1025 while ( *p
!= '\0' ) {
1028 // found beginining [ and ending ]
1029 unsigned char last
= '\0';
1030 for ( const char* s
= b
; s
< e
; ++s
) {
1032 unsigned char next
= *(++s
);
1033 if ( (last
<= c
) && (c
<= next
) )
1050 bool Options::SetWithWildcards::wildCardMatch(const char* pattern
, const char* symbol
) const
1052 const char* s
= symbol
;
1053 for (const char* p
= pattern
; *p
!= '\0'; ++p
) {
1058 for (const char* t
= s
; *t
!= '\0'; ++t
) {
1059 if ( wildCardMatch(&p
[1], t
) )
1069 if ( ! inCharRange(p
, *s
) )
1079 return (*s
== '\0');
1083 void Options::loadExportFile(const char* fileOfExports
, const char* option
, SetWithWildcards
& set
)
1085 if ( fileOfExports
== NULL
)
1086 throwf("missing file after %s", option
);
1087 // read in whole file
1088 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
1090 throwf("can't open %s file: %s", option
, fileOfExports
);
1091 struct stat stat_buf
;
1092 ::fstat(fd
, &stat_buf
);
1093 char* p
= (char*)malloc(stat_buf
.st_size
);
1095 throwf("can't process %s file: %s", option
, fileOfExports
);
1097 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1098 throwf("can't read %s file: %s", option
, fileOfExports
);
1100 if ( this->dumpDependencyInfo() )
1101 this->dumpDependency(Options::depMisc
, fileOfExports
);
1105 // parse into symbols and add to unordered_set
1106 char * const end
= &p
[stat_buf
.st_size
];
1107 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1108 char* symbolStart
= NULL
;
1109 for (char* s
= p
; s
< end
; ++s
) {
1115 else if ( !isspace(*s
) ) {
1121 if ( (*s
== '\n') || (*s
== '\r') ) {
1123 // removing any trailing spaces
1125 while ( isspace(*last
) ) {
1129 set
.insert(symbolStart
);
1135 if ( (*s
== '\n') || (*s
== '\r') )
1140 if ( state
== inSymbol
) {
1141 warning("missing line-end at end of file \"%s\"", fileOfExports
);
1142 int len
= end
-symbolStart
+1;
1143 char* temp
= new char[len
];
1144 strlcpy(temp
, symbolStart
, len
);
1146 // remove any trailing spaces
1147 char* last
= &temp
[len
-2];
1148 while ( isspace(*last
) ) {
1155 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
1158 void Options::parseAliasFile(const char* fileOfAliases
)
1160 // read in whole file
1161 int fd
= ::open(fileOfAliases
, O_RDONLY
, 0);
1163 throwf("can't open alias file: %s", fileOfAliases
);
1164 struct stat stat_buf
;
1165 ::fstat(fd
, &stat_buf
);
1166 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1168 throwf("can't process alias file: %s", fileOfAliases
);
1170 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1171 throwf("can't read alias file: %s", fileOfAliases
);
1172 p
[stat_buf
.st_size
] = '\n';
1174 if ( this->dumpDependencyInfo() )
1175 this->dumpDependency(Options::depMisc
, fileOfAliases
);
1177 // parse into symbols and add to fAliases
1179 char * const end
= &p
[stat_buf
.st_size
+1];
1180 enum { lineStart
, inRealName
, inBetween
, inAliasName
, inComment
} state
= lineStart
;
1182 for (char* s
= p
; s
< end
; ++s
) {
1188 else if ( !isspace(*s
) ) {
1195 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1199 else if ( isspace(*s
) ) {
1206 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1210 else if ( ! isspace(*s
) ) {
1211 state
= inAliasName
;
1218 // removing any trailing spaces
1220 while ( isspace(*last
) ) {
1224 fAliases
.push_back(pair
);
1227 else if ( *s
== '\n' ) {
1229 // removing any trailing spaces
1231 while ( isspace(*last
) ) {
1235 fAliases
.push_back(pair
);
1246 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
1251 void Options::setUndefinedTreatment(const char* treatment
)
1253 if ( treatment
== NULL
)
1254 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
1256 if ( strcmp(treatment
, "warning") == 0 )
1257 fUndefinedTreatment
= kUndefinedWarning
;
1258 else if ( strcmp(treatment
, "error") == 0 )
1259 fUndefinedTreatment
= kUndefinedError
;
1260 else if ( strcmp(treatment
, "suppress") == 0 )
1261 fUndefinedTreatment
= kUndefinedSuppress
;
1262 else if ( strcmp(treatment
, "dynamic_lookup") == 0 )
1263 fUndefinedTreatment
= kUndefinedDynamicLookup
;
1265 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1268 Options::Treatment
Options::parseTreatment(const char* treatment
)
1270 if ( treatment
== NULL
)
1273 if ( strcmp(treatment
, "warning") == 0 )
1275 else if ( strcmp(treatment
, "error") == 0 )
1277 else if ( strcmp(treatment
, "suppress") == 0 )
1283 void Options::setMacOSXVersionMin(const char* version
)
1285 if ( version
== NULL
)
1286 throw "-macosx_version_min argument missing";
1288 if ( (strncmp(version
, "10.", 3) == 0) && isdigit(version
[3]) ) {
1289 unsigned int minorVersion
= 0;
1290 for (int i
=3; isdigit(version
[i
]); ++i
) {
1291 minorVersion
= minorVersion
*10 + (version
[i
] - '0');
1293 if ( minorVersion
> 255 ) {
1294 warning("Mac OS X minor version > 255 in '%s'", version
);
1297 fMacVersionMin
= (ld::MacVersionMin
)(0x000A0000 | (minorVersion
<< 8));
1300 warning("unknown option to -macosx_version_min, not 10.x");
1304 void Options::setIOSVersionMin(const char* version
)
1306 if ( version
== NULL
)
1307 throw "-ios_version_min argument missing";
1308 if ( ! isdigit(version
[0]) )
1309 throw "-ios_version_min argument is not a number";
1310 if ( version
[1] != '.' )
1311 throw "-ios_version_min argument is missing period as second character";
1312 if ( ! isdigit(version
[2]) )
1313 throw "-ios_version_min argument is not a number";
1315 unsigned int majorVersion
= version
[0] - '0';
1316 unsigned int minorVersion
= version
[2] - '0';
1317 fIOSVersionMin
= (ld::IOSVersionMin
)((majorVersion
<< 16) | (minorVersion
<< 8));
1320 bool Options::minOS(ld::MacVersionMin requiredMacMin
, ld::IOSVersionMin requirediPhoneOSMin
)
1322 if ( fMacVersionMin
!= ld::macVersionUnset
) {
1323 return ( fMacVersionMin
>= requiredMacMin
);
1326 return ( fIOSVersionMin
>= requirediPhoneOSMin
);
1331 void Options::setWeakReferenceMismatchTreatment(const char* treatment
)
1333 if ( treatment
== NULL
)
1334 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1336 if ( strcmp(treatment
, "error") == 0 )
1337 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchError
;
1338 else if ( strcmp(treatment
, "weak") == 0 )
1339 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchWeak
;
1340 else if ( strcmp(treatment
, "non-weak") == 0 )
1341 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchNonWeak
;
1343 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1346 Options::CommonsMode
Options::parseCommonsTreatment(const char* mode
)
1349 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1351 if ( strcmp(mode
, "ignore_dylibs") == 0 )
1352 return kCommonsIgnoreDylibs
;
1353 else if ( strcmp(mode
, "use_dylibs") == 0 )
1354 return kCommonsOverriddenByDylibs
;
1355 else if ( strcmp(mode
, "error") == 0 )
1356 return kCommonsConflictsDylibsError
;
1358 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1361 void Options::addDylibOverride(const char* paths
)
1363 if ( paths
== NULL
)
1364 throw "-dylib_file must followed by two colon separated paths";
1365 const char* colon
= strchr(paths
, ':');
1366 if ( colon
== NULL
)
1367 throw "-dylib_file must followed by two colon separated paths";
1368 int len
= colon
-paths
;
1369 char* target
= new char[len
+2];
1370 strncpy(target
, paths
, len
);
1372 DylibOverride entry
;
1373 entry
.installName
= target
;
1374 entry
.useInstead
= &colon
[1];
1375 fDylibOverrides
.push_back(entry
);
1378 uint64_t Options::parseAddress(const char* addr
)
1381 uint64_t result
= strtoull(addr
, &endptr
, 16);
1385 uint32_t Options::parseProtection(const char* prot
)
1387 uint32_t result
= 0;
1388 for(const char* p
= prot
; *p
!= '\0'; ++p
) {
1389 switch(tolower(*p
)) {
1391 result
|= VM_PROT_READ
;
1394 result
|= VM_PROT_WRITE
;
1397 result
|= VM_PROT_EXECUTE
;
1402 throwf("unknown -segprot lettter in %s", prot
);
1410 // Parses number of form A[.B[.B[.D[.E]]]] into a uint64_t where the bits are a24.b10.c10.d10.e10
1412 uint64_t Options::parseVersionNumber64(const char* versionString
)
1420 a
= strtoul(versionString
, &end
, 10);
1421 if ( *end
== '.' ) {
1422 b
= strtoul(&end
[1], &end
, 10);
1423 if ( *end
== '.' ) {
1424 c
= strtoul(&end
[1], &end
, 10);
1425 if ( *end
== '.' ) {
1426 d
= strtoul(&end
[1], &end
, 10);
1427 if ( *end
== '.' ) {
1428 e
= strtoul(&end
[1], &end
, 10);
1433 if ( (*end
!= '\0') || (a
> 0xFFFFFF) || (b
> 0x3FF) || (c
> 0x3FF) || (d
> 0x3FF) || (e
> 0x3FF) )
1434 throwf("malformed 64-bit a.b.c.d.e version number: %s", versionString
);
1436 return (a
<< 40) | ( b
<< 30 ) | ( c
<< 20 ) | ( d
<< 10 ) | e
;
1440 uint32_t Options::currentVersion32() const
1442 // warn if it does not fit into 32 bit vers number
1443 uint32_t a
= (fDylibCurrentVersion
>> 40) & 0xFFFF;
1444 uint32_t b
= (fDylibCurrentVersion
>> 30) & 0xFF;
1445 uint32_t c
= (fDylibCurrentVersion
>> 20) & 0xFF;
1446 uint64_t rep32
= ((uint64_t)a
<< 40) | ((uint64_t)b
<< 30) | ((uint64_t)c
<< 20);
1447 if ( rep32
!= fDylibCurrentVersion
) {
1448 warning("truncating -current_version to fit in 32-bit space used by old mach-o format");
1449 a
= (fDylibCurrentVersion
>> 40) & 0xFFFFFF;
1452 b
= (fDylibCurrentVersion
>> 30) & 0x3FF;
1455 c
= (fDylibCurrentVersion
>> 20) & 0x3FF;
1459 return (a
<< 16) | ( b
<< 8 ) | c
;
1463 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1465 uint32_t Options::parseVersionNumber32(const char* versionString
)
1471 x
= strtoul(versionString
, &end
, 10);
1472 if ( *end
== '.' ) {
1473 y
= strtoul(&end
[1], &end
, 10);
1474 if ( *end
== '.' ) {
1475 z
= strtoul(&end
[1], &end
, 10);
1478 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
1479 throwf("malformed 32-bit x.y.z version number: %s", versionString
);
1481 return (x
<< 16) | ( y
<< 8 ) | z
;
1484 static const char* cstringSymbolName(const char* orderFileString
)
1487 asprintf(&result
, "cstring=%s", orderFileString
);
1488 // convert escaped characters
1490 for(const char* s
=result
; *s
!= '\0'; ++s
, ++d
) {
1528 // hexadecimal value of char
1532 while ( isxdigit(*s
) ) {
1537 value
+= ((toupper(*s
)-'A') + 10);
1544 if ( isdigit(*s
) ) {
1545 // octal value of char
1547 while ( isdigit(*s
) ) {
1548 value
= (value
<< 3) + (*s
-'0');
1563 void Options::parseOrderFile(const char* path
, bool cstring
)
1565 // order files override auto-ordering
1566 fAutoOrderInitializers
= false;
1568 // read in whole file
1569 int fd
= ::open(path
, O_RDONLY
, 0);
1571 throwf("can't open order file: %s", path
);
1572 struct stat stat_buf
;
1573 ::fstat(fd
, &stat_buf
);
1574 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1576 throwf("can't process order file: %s", path
);
1577 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1578 throwf("can't read order file: %s", path
);
1580 p
[stat_buf
.st_size
] = '\n';
1581 if ( this->dumpDependencyInfo() )
1582 this->dumpDependency(Options::depMisc
, path
);
1584 // parse into vector of pairs
1585 char * const end
= &p
[stat_buf
.st_size
+1];
1586 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1587 char* symbolStart
= NULL
;
1588 for (char* s
= p
; s
< end
; ++s
) {
1594 else if ( !isspace(*s
) || cstring
) {
1600 if ( (*s
== '\n') || (!cstring
&& (*s
== '#')) ) {
1601 bool wasComment
= (*s
== '#');
1603 // removing any trailing spaces
1605 while ( isspace(*last
) ) {
1609 // if there is an architecture prefix, only use this symbol it if matches current arch
1610 if ( strncmp(symbolStart
, "ppc:", 4) == 0 ) {
1613 else if ( strncmp(symbolStart
, "ppc64:", 6) == 0 ) {
1616 else if ( strncmp(symbolStart
, "i386:", 5) == 0 ) {
1617 if ( fArchitecture
== CPU_TYPE_I386
)
1618 symbolStart
= &symbolStart
[5];
1622 else if ( strncmp(symbolStart
, "x86_64:", 7) == 0 ) {
1623 if ( fArchitecture
== CPU_TYPE_X86_64
)
1624 symbolStart
= &symbolStart
[7];
1628 else if ( strncmp(symbolStart
, "arm:", 4) == 0 ) {
1629 if ( fArchitecture
== CPU_TYPE_ARM
)
1630 symbolStart
= &symbolStart
[4];
1634 if ( symbolStart
!= NULL
) {
1635 char* objFileName
= NULL
;
1636 char* colon
= strstr(symbolStart
, ".o:");
1637 if ( colon
!= NULL
) {
1639 objFileName
= symbolStart
;
1640 symbolStart
= &colon
[3];
1643 colon
= strstr(symbolStart
, ".o):");
1644 if ( colon
!= NULL
) {
1646 objFileName
= symbolStart
;
1647 symbolStart
= &colon
[4];
1650 // trim leading spaces
1651 while ( isspace(*symbolStart
) )
1653 Options::OrderedSymbol pair
;
1655 pair
.symbolName
= cstringSymbolName(symbolStart
);
1657 pair
.symbolName
= symbolStart
;
1658 pair
.objectFileName
= objFileName
;
1659 fOrderedSymbols
.push_back(pair
);
1674 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1677 void Options::parseSectionOrderFile(const char* segment
, const char* section
, const char* path
)
1679 if ( (strcmp(section
, "__cstring") == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1680 parseOrderFile(path
, true);
1682 else if ( (strncmp(section
, "__literal",9) == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1683 warning("sorting of __literal[4,8,16] sections not supported");
1686 // ignore section information and append all symbol names to global order file
1687 parseOrderFile(path
, false);
1691 void Options::addSection(const char* segment
, const char* section
, const char* path
)
1693 if ( strlen(segment
) > 16 )
1694 throw "-seccreate segment name max 16 chars";
1695 if ( strlen(section
) > 16 ) {
1696 char* tmp
= strdup(section
);
1698 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section
, tmp
);
1702 // read in whole file
1703 int fd
= ::open(path
, O_RDONLY
, 0);
1705 throwf("can't open -sectcreate file: %s", path
);
1706 struct stat stat_buf
;
1707 ::fstat(fd
, &stat_buf
);
1708 char* p
= (char*)malloc(stat_buf
.st_size
);
1710 throwf("can't process -sectcreate file: %s", path
);
1711 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1712 throwf("can't read -sectcreate file: %s", path
);
1715 // record section to create
1716 ExtraSection info
= { segment
, section
, path
, (uint8_t*)p
, stat_buf
.st_size
};
1717 fExtraSections
.push_back(info
);
1720 void Options::addSectionAlignment(const char* segment
, const char* section
, const char* alignmentStr
)
1722 if ( strlen(segment
) > 16 )
1723 throw "-sectalign segment name max 16 chars";
1724 if ( strlen(section
) > 16 )
1725 throw "-sectalign section name max 16 chars";
1727 // argument to -sectalign is a hexadecimal number
1729 unsigned long value
= strtoul(alignmentStr
, &endptr
, 16);
1730 if ( *endptr
!= '\0')
1731 throw "argument for -sectalign is not a hexadecimal number";
1732 if ( value
> 0x8000 )
1733 throw "argument for -sectalign must be less than or equal to 0x8000";
1735 warning("zero is not a valid -sectalign");
1739 // alignment is power of 2 (e.g. page alignment = 12)
1740 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
1741 if ( (unsigned long)(1 << alignment
) != value
) {
1742 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
1743 segment
, section
, 1 << alignment
);
1746 SectionAlignment info
= { segment
, section
, alignment
};
1747 fSectionAlignments
.push_back(info
);
1750 void Options::addLibrary(const FileInfo
& info
)
1752 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
1753 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
1754 if ( strcmp(info
.path
, fit
->path
) == 0 ) {
1755 // if dylib is specified again but weak, record that it should be weak
1756 if ( info
.options
.fWeakImport
)
1757 fit
->options
.fWeakImport
= true;
1762 fInputFiles
.push_back(info
);
1765 void Options::warnObsolete(const char* arg
)
1767 warning("option %s is obsolete and being ignored", arg
);
1774 // Process all command line arguments.
1776 // The only error checking done here is that each option is valid and if it has arguments
1777 // that they too are valid.
1779 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
1780 // whichever was last on the command line is used.
1782 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
1784 void Options::parse(int argc
, const char* argv
[])
1786 // Store the original args in the link snapshot.
1787 fLinkSnapshot
.recordRawArgs(argc
, argv
);
1789 // pass one builds search list from -L and -F options
1790 this->buildSearchPaths(argc
, argv
);
1792 // reduce re-allocations
1793 fInputFiles
.reserve(32);
1795 // pass two parse all other options
1796 for(int i
=1; i
< argc
; ++i
) {
1797 const char* arg
= argv
[i
];
1799 if ( arg
[0] == '-' ) {
1800 // by default, copy one arg to the snapshot link command, and do no file copying
1801 int snapshotArgIndex
= i
;
1802 int snapshotArgCount
= -1; // -1 means compute count based on change in index
1803 int snapshotFileArgIndex
= -1; // -1 means no data file parameter to arg
1805 // Since we don't care about the files passed, just the option names, we do this here.
1807 fprintf (stderr
, "[Logging ld64 options]\t%s\n", arg
);
1809 if ( (arg
[1] == 'L') || (arg
[1] == 'F') ) {
1810 snapshotArgCount
= 0; // stripped out of link snapshot
1813 // previously handled by buildSearchPaths()
1815 // The one gnu style option we have to keep compatibility
1816 // with gcc. Might as well have the single hyphen one as well.
1817 else if ( (strcmp(arg
, "--help") == 0)
1818 || (strcmp(arg
, "-help") == 0)) {
1819 fprintf (stdout
, "ld64: For information on command line options please use 'man ld'.\n");
1822 else if ( strcmp(arg
, "-arch") == 0 ) {
1823 parseArch(argv
[++i
]);
1825 else if ( strcmp(arg
, "-dynamic") == 0 ) {
1828 else if ( strcmp(arg
, "-static") == 0 ) {
1830 if ( (fOutputKind
!= kObjectFile
) && (fOutputKind
!= kKextBundle
) ) {
1831 fOutputKind
= kStaticExecutable
;
1834 else if ( strcmp(arg
, "-dylib") == 0 ) {
1835 fOutputKind
= kDynamicLibrary
;
1837 else if ( strcmp(arg
, "-bundle") == 0 ) {
1838 fOutputKind
= kDynamicBundle
;
1840 else if ( strcmp(arg
, "-dylinker") == 0 ) {
1841 fOutputKind
= kDyld
;
1843 else if ( strcmp(arg
, "-execute") == 0 ) {
1844 if ( fOutputKind
!= kStaticExecutable
)
1845 fOutputKind
= kDynamicExecutable
;
1847 else if ( strcmp(arg
, "-preload") == 0 ) {
1848 fOutputKind
= kPreload
;
1850 else if ( strcmp(arg
, "-r") == 0 ) {
1851 fOutputKind
= kObjectFile
;
1853 else if ( strcmp(arg
, "-kext") == 0 ) {
1854 fOutputKind
= kKextBundle
;
1856 else if ( strcmp(arg
, "-o") == 0 ) {
1857 snapshotArgCount
= 0;
1858 fOutputFile
= argv
[++i
];
1859 fLinkSnapshot
.setSnapshotName(fOutputFile
);
1861 else if ( strncmp(arg
, "-lazy-l", 7) == 0 ) {
1862 snapshotArgCount
= 0;
1863 FileInfo info
= findLibrary(&arg
[7], true);
1864 info
.options
.fLazyLoad
= true;
1865 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
1867 fUsingLazyDylibLinking
= true;
1869 else if ( strcmp(arg
, "-lto_library") == 0 ) {
1870 snapshotFileArgIndex
= 1;
1871 fOverridePathlibLTO
= argv
[++i
];
1872 if ( fOverridePathlibLTO
== NULL
)
1873 throw "missing argument to -lto_library";
1875 else if ( (arg
[1] == 'l') && (strncmp(arg
,"-lazy_",6) !=0) ) {
1876 snapshotArgCount
= 0;
1877 FileInfo info
= findLibrary(&arg
[2]);
1878 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
1881 // This causes a dylib to be weakly bound at
1882 // link time. This corresponds to weak_import.
1883 else if ( strncmp(arg
, "-weak-l", 7) == 0 ) {
1884 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
1885 snapshotArgCount
= 0;
1886 FileInfo info
= findLibrary(&arg
[7]);
1887 info
.options
.fWeakImport
= true;
1888 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
1891 // Avoid lazy binding.
1892 else if ( strcmp(arg
, "-bind_at_load") == 0 ) {
1895 else if ( strcmp(arg
, "-twolevel_namespace") == 0 ) {
1896 fNameSpace
= kTwoLevelNameSpace
;
1898 else if ( strcmp(arg
, "-flat_namespace") == 0 ) {
1899 fNameSpace
= kFlatNameSpace
;
1901 // Also sets a bit to ensure dyld causes everything
1902 // in the namespace to be flat.
1904 else if ( strcmp(arg
, "-force_flat_namespace") == 0 ) {
1905 fNameSpace
= kForceFlatNameSpace
;
1907 // Similar to --whole-archive.
1908 else if ( strcmp(arg
, "-all_load") == 0 ) {
1909 fFullyLoadArchives
= true;
1911 else if ( strcmp(arg
, "-noall_load") == 0) {
1914 // Similar to -all_load
1915 else if ( strcmp(arg
, "-ObjC") == 0 ) {
1916 fLoadAllObjcObjectsFromArchives
= true;
1918 // Similar to -all_load, but for the following archive only.
1919 else if ( strcmp(arg
, "-force_load") == 0 ) {
1920 FileInfo info
= findFile(argv
[++i
]);
1921 info
.options
.fForceLoad
= true;
1922 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
1925 // Library versioning.
1926 else if ( (strcmp(arg
, "-dylib_compatibility_version") == 0)
1927 || (strcmp(arg
, "-compatibility_version") == 0)) {
1928 const char* vers
= argv
[++i
];
1930 throw "-dylib_compatibility_version missing <version>";
1931 fDylibCompatVersion
= parseVersionNumber32(vers
);
1933 else if ( (strcmp(arg
, "-dylib_current_version") == 0)
1934 || (strcmp(arg
, "-current_version") == 0)) {
1935 const char* vers
= argv
[++i
];
1937 throw "-dylib_current_version missing <version>";
1938 fDylibCurrentVersion
= parseVersionNumber64(vers
);
1940 else if ( strcmp(arg
, "-sectorder") == 0 ) {
1941 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
1942 throw "-sectorder missing <segment> <section> <file-path>";
1943 snapshotFileArgIndex
= 3;
1944 parseSectionOrderFile(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1947 else if ( strcmp(arg
, "-order_file") == 0 ) {
1948 snapshotFileArgIndex
= 1;
1949 parseOrderFile(argv
[++i
], false);
1951 else if ( strcmp(arg
, "-order_file_statistics") == 0 ) {
1952 fPrintOrderFileStatistics
= true;
1954 // ??? Deprecate segcreate.
1955 // -sectcreate puts whole files into a section in the output.
1956 else if ( (strcmp(arg
, "-sectcreate") == 0) || (strcmp(arg
, "-segcreate") == 0) ) {
1957 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
1958 throw "-sectcreate missing <segment> <section> <file-path>";
1959 snapshotFileArgIndex
= 3;
1960 addSection(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1963 // Since we have a full path in binary/library names we need to be able to override it.
1964 else if ( (strcmp(arg
, "-dylib_install_name") == 0)
1965 || (strcmp(arg
, "-dylinker_install_name") == 0)
1966 || (strcmp(arg
, "-install_name") == 0)) {
1967 fDylibInstallName
= argv
[++i
];
1968 if ( fDylibInstallName
== NULL
)
1969 throw "-install_name missing <path>";
1971 // Sets the base address of the output.
1972 else if ( (strcmp(arg
, "-seg1addr") == 0) || (strcmp(arg
, "-image_base") == 0) ) {
1973 const char* address
= argv
[++i
];
1974 if ( address
== NULL
)
1975 throwf("%s missing <address>", arg
);
1976 fBaseAddress
= parseAddress(address
);
1977 uint64_t temp
= ((fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
1978 if ( fBaseAddress
!= temp
) {
1979 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment
);
1980 fBaseAddress
= temp
;
1983 else if ( strcmp(arg
, "-e") == 0 ) {
1984 fEntryName
= argv
[++i
];
1986 // Same as -@ from the FSF linker.
1987 else if ( strcmp(arg
, "-filelist") == 0 ) {
1988 snapshotArgCount
= 0;
1989 const char* path
= argv
[++i
];
1990 if ( (path
== NULL
) || (path
[0] == '-') )
1991 throw "-filelist missing <path>";
1992 ld::File::Ordinal baseOrdinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
1993 loadFileList(path
, baseOrdinal
);
1995 else if ( strcmp(arg
, "-keep_private_externs") == 0 ) {
1996 fKeepPrivateExterns
= true;
1998 else if ( strcmp(arg
, "-final_output") == 0 ) {
1999 fFinalName
= argv
[++i
];
2001 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
2002 // just ensures that this happens for cross object file boundaries.
2003 else if ( (strcmp(arg
, "-interposable") == 0) || (strcmp(arg
, "-multi_module") == 0)) {
2004 switch ( fInterposeMode
) {
2005 case kInterposeNone
:
2006 case kInterposeAllExternal
:
2007 fInterposeMode
= kInterposeAllExternal
;
2009 case kInterposeSome
:
2010 // do nothing, -interposable_list overrides -interposable"
2014 else if ( strcmp(arg
, "-interposable_list") == 0 ) {
2015 snapshotFileArgIndex
= 1;
2016 fInterposeMode
= kInterposeSome
;
2017 loadExportFile(argv
[++i
], "-interposable_list", fInterposeList
);
2019 // Default for -interposable/-multi_module/-single_module.
2020 else if ( strcmp(arg
, "-single_module") == 0 ) {
2021 fInterposeMode
= kInterposeNone
;
2023 else if ( strcmp(arg
, "-exported_symbols_list") == 0 ) {
2024 snapshotFileArgIndex
= 1;
2025 if ( fExportMode
== kDontExportSome
)
2026 throw "can't use -exported_symbols_list and -unexported_symbols_list";
2027 fExportMode
= kExportSome
;
2028 loadExportFile(argv
[++i
], "-exported_symbols_list", fExportSymbols
);
2030 else if ( strcmp(arg
, "-unexported_symbols_list") == 0 ) {
2031 snapshotFileArgIndex
= 1;
2032 if ( fExportMode
== kExportSome
)
2033 throw "can't use -unexported_symbols_list and -exported_symbols_list";
2034 fExportMode
= kDontExportSome
;
2035 loadExportFile(argv
[++i
], "-unexported_symbols_list", fDontExportSymbols
);
2037 else if ( strcmp(arg
, "-exported_symbol") == 0 ) {
2038 if ( fExportMode
== kDontExportSome
)
2039 throw "can't use -exported_symbol and -unexported_symbols";
2040 fExportMode
= kExportSome
;
2041 fExportSymbols
.insert(argv
[++i
]);
2043 else if ( strcmp(arg
, "-unexported_symbol") == 0 ) {
2044 if ( fExportMode
== kExportSome
)
2045 throw "can't use -unexported_symbol and -exported_symbol";
2046 fExportMode
= kDontExportSome
;
2047 fDontExportSymbols
.insert(argv
[++i
]);
2049 else if ( strcmp(arg
, "-non_global_symbols_no_strip_list") == 0 ) {
2050 snapshotFileArgIndex
= 1;
2051 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveExclude
)
2052 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2053 fLocalSymbolHandling
= kLocalSymbolsSelectiveInclude
;
2054 loadExportFile(argv
[++i
], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded
);
2056 else if ( strcmp(arg
, "-non_global_symbols_strip_list") == 0 ) {
2057 snapshotFileArgIndex
= 1;
2058 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveInclude
)
2059 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2060 fLocalSymbolHandling
= kLocalSymbolsSelectiveExclude
;
2061 loadExportFile(argv
[++i
], "-non_global_symbols_strip_list", fLocalSymbolsExcluded
);
2064 else if ( strcmp(arg
, "-no_arch_warnings") == 0 ) {
2065 fIgnoreOtherArchFiles
= true;
2067 else if ( strcmp(arg
, "-force_cpusubtype_ALL") == 0 ) {
2068 fForceSubtypeAll
= true;
2069 fAllowCpuSubtypeMismatches
= true;
2071 // Similar to -weak-l but uses the absolute path name to the library.
2072 else if ( strcmp(arg
, "-weak_library") == 0 ) {
2073 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2074 snapshotArgCount
= 0;
2075 FileInfo info
= findFile(argv
[++i
]);
2076 info
.options
.fWeakImport
= true;
2077 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2080 else if ( strcmp(arg
, "-lazy_library") == 0 ) {
2081 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2082 snapshotArgCount
= 0;
2083 FileInfo info
= findFile(argv
[++i
]);
2084 info
.options
.fLazyLoad
= true;
2085 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2087 fUsingLazyDylibLinking
= true;
2089 else if ( strcmp(arg
, "-framework") == 0 ) {
2090 snapshotArgCount
= 0;
2091 FileInfo info
= findFramework(argv
[++i
]);
2092 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2095 else if ( strcmp(arg
, "-weak_framework") == 0 ) {
2096 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2097 snapshotArgCount
= 0;
2098 FileInfo info
= findFramework(argv
[++i
]);
2099 info
.options
.fWeakImport
= true;
2100 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2103 else if ( strcmp(arg
, "-lazy_framework") == 0 ) {
2104 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2105 snapshotArgCount
= 0;
2106 FileInfo info
= findFramework(argv
[++i
]);
2107 info
.options
.fLazyLoad
= true;
2108 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2110 fUsingLazyDylibLinking
= true;
2112 else if ( strcmp(arg
, "-search_paths_first") == 0 ) {
2113 // previously handled by buildSearchPaths()
2115 else if ( strcmp(arg
, "-search_dylibs_first") == 0 ) {
2116 // previously handled by buildSearchPaths()
2118 else if ( strcmp(arg
, "-undefined") == 0 ) {
2119 setUndefinedTreatment(argv
[++i
]);
2121 // Debugging output flag.
2122 else if ( strcmp(arg
, "-arch_multiple") == 0 ) {
2123 fMessagesPrefixedWithArchitecture
= true;
2125 // Specify what to do with relocations in read only
2126 // sections like .text. Could be errors, warnings,
2127 // or suppressed. Currently we do nothing with the
2129 else if ( strcmp(arg
, "-read_only_relocs") == 0 ) {
2130 switch ( parseTreatment(argv
[++i
]) ) {
2133 throw "-read_only_relocs missing [ warning | error | suppress ]";
2135 fWarnTextRelocs
= true;
2136 fAllowTextRelocs
= true;
2139 fWarnTextRelocs
= false;
2140 fAllowTextRelocs
= true;
2143 fWarnTextRelocs
= false;
2144 fAllowTextRelocs
= false;
2148 else if ( strcmp(arg
, "-sect_diff_relocs") == 0 ) {
2152 // Warn, error or make strong a mismatch between weak
2153 // and non-weak references.
2154 else if ( strcmp(arg
, "-weak_reference_mismatches") == 0 ) {
2155 setWeakReferenceMismatchTreatment(argv
[++i
]);
2157 // For a deployment target of 10.3 and earlier ld64 will
2158 // prebind an executable with 0s in all addresses that
2159 // are prebound. This can then be fixed up by update_prebinding
2160 // later. Prebinding is less useful on 10.4 and greater.
2161 else if ( strcmp(arg
, "-prebind") == 0 ) {
2164 else if ( strcmp(arg
, "-noprebind") == 0 ) {
2168 else if ( strcmp(arg
, "-prebind_allow_overlap") == 0 ) {
2171 else if ( strcmp(arg
, "-prebind_all_twolevel_modules") == 0 ) {
2174 else if ( strcmp(arg
, "-noprebind_all_twolevel_modules") == 0 ) {
2177 else if ( strcmp(arg
, "-nofixprebinding") == 0 ) {
2180 // This should probably be deprecated when we respect -L and -F
2181 // when searching for libraries.
2182 else if ( strcmp(arg
, "-dylib_file") == 0 ) {
2183 // ignore for snapshot because a stub dylib will be created in the snapshot
2184 snapshotArgCount
= 0;
2185 addDylibOverride(argv
[++i
]);
2187 // What to expand @executable_path to if found in dependent dylibs
2188 else if ( strcmp(arg
, "-executable_path") == 0 ) {
2189 fExecutablePath
= argv
[++i
];
2190 if ( (fExecutablePath
== NULL
) || (fExecutablePath
[0] == '-') )
2191 throw "-executable_path missing <path>";
2192 // if a directory was passed, add / to end
2193 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2194 struct stat statBuffer
;
2195 if ( stat(fExecutablePath
, &statBuffer
) == 0 ) {
2196 if ( (statBuffer
.st_mode
& S_IFMT
) == S_IFDIR
) {
2197 char* pathWithSlash
= new char[strlen(fExecutablePath
)+2];
2198 strcpy(pathWithSlash
, fExecutablePath
);
2199 strcat(pathWithSlash
, "/");
2200 fExecutablePath
= pathWithSlash
;
2204 // Aligns all segments to the power of 2 boundary specified.
2205 else if ( strcmp(arg
, "-segalign") == 0 ) {
2206 const char* size
= argv
[++i
];
2208 throw "-segalign missing <size>";
2209 fSegmentAlignment
= parseAddress(size
);
2210 uint8_t alignment
= (uint8_t)__builtin_ctz(fSegmentAlignment
);
2211 uint32_t p2aligned
= (1 << alignment
);
2212 if ( p2aligned
!= fSegmentAlignment
) {
2213 warning("alignment for -segalign %s is not a power of two, using 0x%X", size
, p2aligned
);
2214 fSegmentAlignment
= p2aligned
;
2217 // Puts a specified segment at a particular address that must
2218 // be a multiple of the segment alignment.
2219 else if ( strcmp(arg
, "-segaddr") == 0 ) {
2221 seg
.name
= argv
[++i
];
2222 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2223 throw "-segaddr missing segName Adddress";
2224 seg
.address
= parseAddress(argv
[++i
]);
2225 uint64_t temp
= ((seg
.address
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
2226 if ( seg
.address
!= temp
)
2227 warning("-segaddr %s not %lld byte aligned", seg
.name
, fSegmentAlignment
);
2228 fCustomSegmentAddresses
.push_back(seg
);
2230 // ??? Deprecate when we deprecate split-seg.
2231 else if ( strcmp(arg
, "-segs_read_only_addr") == 0 ) {
2232 fBaseAddress
= parseAddress(argv
[++i
]);
2234 // ??? Deprecate when we deprecate split-seg.
2235 else if ( strcmp(arg
, "-segs_read_write_addr") == 0 ) {
2236 fBaseWritableAddress
= parseAddress(argv
[++i
]);
2239 // ??? Deprecate when we get rid of basing at build time.
2240 else if ( strcmp(arg
, "-seg_addr_table") == 0 ) {
2241 snapshotFileArgIndex
= 1;
2242 const char* name
= argv
[++i
];
2244 throw "-seg_addr_table missing argument";
2245 fSegAddrTablePath
= name
;
2247 else if ( strcmp(arg
, "-seg_addr_table_filename") == 0 ) {
2251 else if ( strcmp(arg
, "-segprot") == 0 ) {
2253 seg
.name
= argv
[++i
];
2254 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) || (argv
[i
+2] == NULL
) )
2255 throw "-segprot missing segName max-prot init-prot";
2256 seg
.max
= parseProtection(argv
[++i
]);
2257 seg
.init
= parseProtection(argv
[++i
]);
2258 fCustomSegmentProtections
.push_back(seg
);
2260 else if ( strcmp(arg
, "-pagezero_size") == 0 ) {
2261 const char* size
= argv
[++i
];
2263 throw "-pagezero_size missing <size>";
2264 fZeroPageSize
= parseAddress(size
);
2265 uint64_t temp
= fZeroPageSize
& (-4096); // page align
2266 if ( (fZeroPageSize
!= temp
) )
2267 warning("-pagezero_size not page aligned, rounding down");
2268 fZeroPageSize
= temp
;
2270 else if ( strcmp(arg
, "-stack_addr") == 0 ) {
2271 const char* address
= argv
[++i
];
2272 if ( address
== NULL
)
2273 throw "-stack_addr missing <address>";
2274 fStackAddr
= parseAddress(address
);
2276 else if ( strcmp(arg
, "-stack_size") == 0 ) {
2277 const char* size
= argv
[++i
];
2279 throw "-stack_size missing <address>";
2280 fStackSize
= parseAddress(size
);
2281 uint64_t temp
= fStackSize
& (-4096); // page align
2282 if ( (fStackSize
!= temp
) )
2283 warning("-stack_size not page aligned, rounding down");
2285 else if ( strcmp(arg
, "-allow_stack_execute") == 0 ) {
2286 fExecutableStack
= true;
2288 else if ( strcmp(arg
, "-allow_heap_execute") == 0 ) {
2289 fDisableNonExecutableHeap
= true;
2291 else if ( strcmp(arg
, "-sectalign") == 0 ) {
2292 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2293 throw "-sectalign missing <segment> <section> <file-path>";
2294 addSectionAlignment(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2297 else if ( strcmp(arg
, "-sectorder_detail") == 0 ) {
2300 else if ( strcmp(arg
, "-sectobjectsymbols") == 0 ) {
2304 else if ( strcmp(arg
, "-bundle_loader") == 0 ) {
2305 snapshotFileArgIndex
= 1;
2306 fBundleLoader
= argv
[++i
];
2307 if ( (fBundleLoader
== NULL
) || (fBundleLoader
[0] == '-') )
2308 throw "-bundle_loader missing <path>";
2309 FileInfo info
= findFile(fBundleLoader
);
2310 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2311 info
.options
.fBundleLoader
= true;
2312 fInputFiles
.push_back(info
);
2314 else if ( strcmp(arg
, "-private_bundle") == 0 ) {
2317 else if ( strcmp(arg
, "-twolevel_namespace_hints") == 0 ) {
2320 // Use this flag to set default behavior for deployement targets.
2321 else if ( strcmp(arg
, "-macosx_version_min") == 0 ) {
2322 const char* macVers
= argv
[++i
];
2323 const char* envMacVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
2324 const char* enviPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
2325 if ( (envMacVers
!= NULL
) && (enviPhoneVers
!= NULL
) ) {
2326 // <rdar://problem/13774329> when conflicting deployments set, break tie by looking at syslibroot
2327 warning("both MACOSX_DEPLOYMENT_TARGET and IPHONEOS_DEPLOYMENT_TARGET are set");
2328 if ( !fSDKPaths
.empty() ) {
2329 const char* sysrootPath
= fSDKPaths
.back();
2330 const char* lastSlash
= strrchr(sysrootPath
, '/');
2331 if ( strstr(lastSlash
, "Simulator") != NULL
)
2332 setIOSVersionMin(enviPhoneVers
);
2334 setMacOSXVersionMin(macVers
);
2337 setMacOSXVersionMin(macVers
);
2341 setMacOSXVersionMin(macVers
);
2344 else if ( (strcmp(arg
, "-ios_version_min") == 0) || (strcmp(arg
, "-iphoneos_version_min") == 0) ) {
2345 setIOSVersionMin(argv
[++i
]);
2347 else if ( strcmp(arg
, "-ios_simulator_version_min") == 0 ) {
2348 setIOSVersionMin(argv
[++i
]);
2349 fTargetIOSSimulator
= true;
2351 else if ( strcmp(arg
, "-multiply_defined") == 0 ) {
2352 //warnObsolete(arg);
2355 else if ( strcmp(arg
, "-multiply_defined_unused") == 0 ) {
2359 else if ( strcmp(arg
, "-nomultidefs") == 0 ) {
2362 // Display each file in which the argument symbol appears and whether
2363 // the file defines or references it. This option takes an argument
2364 // as -y<symbol> note that there is no space.
2365 else if ( strncmp(arg
, "-y", 2) == 0 ) {
2368 // Same output as -y, but output <arg> number of undefined symbols only.
2369 else if ( strcmp(arg
, "-Y") == 0 ) {
2370 //warnObsolete(arg);
2373 // This option affects all objects linked into the final result.
2374 else if ( strcmp(arg
, "-m") == 0 ) {
2377 else if ( (strcmp(arg
, "-why_load") == 0) || (strcmp(arg
, "-whyload") == 0) ) {
2380 else if ( strcmp(arg
, "-why_live") == 0 ) {
2381 const char* name
= argv
[++i
];
2383 throw "-why_live missing symbol name argument";
2384 fWhyLive
.insert(name
);
2386 else if ( strcmp(arg
, "-u") == 0 ) {
2387 const char* name
= argv
[++i
];
2389 throw "-u missing argument";
2390 fInitialUndefines
.push_back(name
);
2392 else if ( strcmp(arg
, "-U") == 0 ) {
2393 const char* name
= argv
[++i
];
2395 throw "-U missing argument";
2396 fAllowedUndefined
.insert(name
);
2398 else if ( strcmp(arg
, "-s") == 0 ) {
2400 fLocalSymbolHandling
= kLocalSymbolsNone
;
2401 fDebugInfoStripping
= Options::kDebugInfoNone
;
2403 else if ( strcmp(arg
, "-x") == 0 ) {
2404 fLocalSymbolHandling
= kLocalSymbolsNone
;
2406 else if ( strcmp(arg
, "-S") == 0 ) {
2407 fDebugInfoStripping
= Options::kDebugInfoNone
;
2409 else if ( strcmp(arg
, "-X") == 0 ) {
2412 else if ( strcmp(arg
, "-Si") == 0 ) {
2414 fDebugInfoStripping
= Options::kDebugInfoFull
;
2416 else if ( strcmp(arg
, "-b") == 0 ) {
2419 else if ( strcmp(arg
, "-Sn") == 0 ) {
2421 fDebugInfoStripping
= Options::kDebugInfoFull
;
2423 else if ( strcmp(arg
, "-Sp") == 0 ) {
2426 else if ( strcmp(arg
, "-dead_strip") == 0 ) {
2429 else if ( strcmp(arg
, "-no_dead_strip_inits_and_terms") == 0 ) {
2432 else if ( strcmp(arg
, "-w") == 0 ) {
2433 // previously handled by buildSearchPaths()
2435 else if ( strcmp(arg
, "-fatal_warnings") == 0 ) {
2436 // previously handled by buildSearchPaths()
2438 else if ( strcmp(arg
, "-arch_errors_fatal") == 0 ) {
2439 fErrorOnOtherArchFiles
= true;
2441 else if ( strcmp(arg
, "-M") == 0 ) {
2444 else if ( strcmp(arg
, "-headerpad") == 0 ) {
2445 const char* size
= argv
[++i
];
2447 throw "-headerpad missing argument";
2448 fMinimumHeaderPad
= parseAddress(size
);
2450 else if ( strcmp(arg
, "-headerpad_max_install_names") == 0 ) {
2451 fMaxMinimumHeaderPad
= true;
2453 else if ( strcmp(arg
, "-t") == 0 ) {
2454 fLogAllFiles
= true;
2456 else if ( strcmp(arg
, "-whatsloaded") == 0 ) {
2457 fLogObjectFiles
= true;
2459 else if ( strcmp(arg
, "-A") == 0 ) {
2463 else if ( strcmp(arg
, "-umbrella") == 0 ) {
2464 const char* name
= argv
[++i
];
2466 throw "-umbrella missing argument";
2467 fUmbrellaName
= name
;
2469 else if ( strcmp(arg
, "-allowable_client") == 0 ) {
2470 const char* name
= argv
[++i
];
2473 throw "-allowable_client missing argument";
2475 fAllowableClients
.push_back(name
);
2477 else if ( strcmp(arg
, "-client_name") == 0 ) {
2478 const char* name
= argv
[++i
];
2481 throw "-client_name missing argument";
2485 else if ( strcmp(arg
, "-sub_umbrella") == 0 ) {
2486 const char* name
= argv
[++i
];
2488 throw "-sub_umbrella missing argument";
2489 fSubUmbellas
.push_back(name
);
2491 else if ( strcmp(arg
, "-sub_library") == 0 ) {
2492 const char* name
= argv
[++i
];
2494 throw "-sub_library missing argument";
2495 fSubLibraries
.push_back(name
);
2497 else if ( strcmp(arg
, "-init") == 0 ) {
2498 const char* name
= argv
[++i
];
2500 throw "-init missing argument";
2501 fInitFunctionName
= name
;
2503 else if ( strcmp(arg
, "-dot") == 0 ) {
2504 const char* name
= argv
[++i
];
2506 throw "-dot missing argument";
2507 fDotOutputFile
= name
;
2509 else if ( strcmp(arg
, "-warn_commons") == 0 ) {
2510 fWarnCommons
= true;
2512 else if ( strcmp(arg
, "-commons") == 0 ) {
2513 fCommonsMode
= parseCommonsTreatment(argv
[++i
]);
2515 else if ( strcmp(arg
, "-keep_relocs") == 0 ) {
2516 fKeepRelocations
= true;
2518 else if ( strcmp(arg
, "-warn_stabs") == 0 ) {
2521 else if ( strcmp(arg
, "-pause") == 0 ) {
2524 else if ( strcmp(arg
, "-print_statistics") == 0 ) {
2527 else if ( strcmp(arg
, "-d") == 0 ) {
2528 fMakeTentativeDefinitionsReal
= true;
2530 else if ( strcmp(arg
, "-v") == 0 ) {
2531 // previously handled by buildSearchPaths()
2533 else if ( strcmp(arg
, "-Z") == 0 ) {
2534 // previously handled by buildSearchPaths()
2536 else if ( strcmp(arg
, "-syslibroot") == 0 ) {
2537 snapshotArgCount
= 0;
2539 // previously handled by buildSearchPaths()
2541 else if ( strcmp(arg
, "-no_uuid") == 0 ) {
2542 fUUIDMode
= kUUIDNone
;
2544 else if ( strcmp(arg
, "-random_uuid") == 0 ) {
2545 fUUIDMode
= kUUIDRandom
;
2547 else if ( strcmp(arg
, "-dtrace") == 0 ) {
2548 snapshotFileArgIndex
= 1;
2549 const char* name
= argv
[++i
];
2551 throw "-dtrace missing argument";
2552 fDtraceScriptName
= name
;
2554 else if ( strcmp(arg
, "-root_safe") == 0 ) {
2557 else if ( strcmp(arg
, "-setuid_safe") == 0 ) {
2560 else if ( strcmp(arg
, "-alias") == 0 ) {
2561 Options::AliasPair pair
;
2562 pair
.realName
= argv
[++i
];
2563 if ( pair
.realName
== NULL
)
2564 throw "missing argument to -alias";
2565 pair
.alias
= argv
[++i
];
2566 if ( pair
.alias
== NULL
)
2567 throw "missing argument to -alias";
2568 fAliases
.push_back(pair
);
2570 else if ( strcmp(arg
, "-alias_list") == 0 ) {
2571 snapshotFileArgIndex
= 1;
2572 parseAliasFile(argv
[++i
]);
2574 // put this last so that it does not interfer with other options starting with 'i'
2575 else if ( strncmp(arg
, "-i", 2) == 0 ) {
2576 const char* colon
= strchr(arg
, ':');
2577 if ( colon
== NULL
)
2578 throwf("unknown option: %s", arg
);
2579 Options::AliasPair pair
;
2580 char* temp
= new char[colon
-arg
];
2581 strlcpy(temp
, &arg
[2], colon
-arg
-1);
2582 pair
.realName
= &colon
[1];
2584 fAliases
.push_back(pair
);
2586 else if ( strcmp(arg
, "-save-temps") == 0 ) {
2587 fSaveTempFiles
= true;
2589 else if ( strcmp(arg
, "-rpath") == 0 ) {
2590 const char* path
= argv
[++i
];
2592 throw "missing argument to -rpath";
2593 fRPaths
.push_back(path
);
2595 else if ( strcmp(arg
, "-read_only_stubs") == 0 ) {
2596 fReadOnlyx86Stubs
= true;
2598 else if ( strcmp(arg
, "-slow_stubs") == 0 ) {
2601 else if ( strcmp(arg
, "-map") == 0 ) {
2602 fMapPath
= argv
[++i
];
2603 if ( fMapPath
== NULL
)
2604 throw "missing argument to -map";
2606 else if ( strcmp(arg
, "-pie") == 0 ) {
2607 fPositionIndependentExecutable
= true;
2608 fPIEOnCommandLine
= true;
2610 else if ( strcmp(arg
, "-no_pie") == 0 ) {
2611 fDisablePositionIndependentExecutable
= true;
2613 else if ( strncmp(arg
, "-reexport-l", 11) == 0 ) {
2614 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2615 snapshotArgCount
= 0;
2616 FileInfo info
= findLibrary(&arg
[11], true);
2617 info
.options
.fReExport
= true;
2618 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2621 else if ( strcmp(arg
, "-reexport_library") == 0 ) {
2622 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2623 snapshotArgCount
= 0;
2624 FileInfo info
= findFile(argv
[++i
]);
2625 info
.options
.fReExport
= true;
2626 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2629 else if ( strcmp(arg
, "-reexport_framework") == 0 ) {
2630 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2631 snapshotArgCount
= 0;
2632 FileInfo info
= findFramework(argv
[++i
]);
2633 info
.options
.fReExport
= true;
2634 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2637 else if ( strncmp(arg
, "-upward-l", 9) == 0 ) {
2638 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2639 snapshotArgCount
= 0;
2640 FileInfo info
= findLibrary(&arg
[9], true);
2641 info
.options
.fUpward
= true;
2642 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2645 else if ( strcmp(arg
, "-upward_library") == 0 ) {
2646 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2647 snapshotArgCount
= 0;
2648 FileInfo info
= findFile(argv
[++i
]);
2649 info
.options
.fUpward
= true;
2650 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2653 else if ( strcmp(arg
, "-upward_framework") == 0 ) {
2654 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2655 snapshotArgCount
= 0;
2656 FileInfo info
= findFramework(argv
[++i
]);
2657 info
.options
.fUpward
= true;
2658 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2661 else if ( strcmp(arg
, "-dead_strip_dylibs") == 0 ) {
2662 fDeadStripDylibs
= true;
2664 else if ( strcmp(arg
, "-no_implicit_dylibs") == 0 ) {
2665 fImplicitlyLinkPublicDylibs
= false;
2667 else if ( strcmp(arg
, "-new_linker") == 0 ) {
2670 else if ( strcmp(arg
, "-no_encryption") == 0 ) {
2671 fEncryptable
= false;
2673 else if ( strcmp(arg
, "-no_compact_unwind") == 0 ) {
2674 fAddCompactUnwindEncoding
= false;
2676 else if ( strcmp(arg
, "-mllvm") == 0 ) {
2677 const char* opts
= argv
[++i
];
2679 throw "missing argument to -mllvm";
2680 fLLVMOptions
.push_back(opts
);
2682 else if ( strcmp(arg
, "-mcpu") == 0 ) {
2683 const char* cpu
= argv
[++i
];
2685 throw "missing argument to -mcpu";
2688 else if ( strcmp(arg
, "-no_order_inits") == 0 ) {
2689 fAutoOrderInitializers
= false;
2691 else if ( strcmp(arg
, "-no_order_data") == 0 ) {
2694 else if ( strcmp(arg
, "-seg_page_size") == 0 ) {
2696 seg
.name
= argv
[++i
];
2697 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2698 throw "-seg_page_size missing segName Adddress";
2699 seg
.size
= parseAddress(argv
[++i
]);
2700 uint64_t temp
= seg
.size
& (-4096); // page align
2701 if ( (seg
.size
!= temp
) )
2702 warning("-seg_page_size %s not 4K aligned, rounding down", seg
.name
);
2703 fCustomSegmentSizes
.push_back(seg
);
2705 else if ( strcmp(arg
, "-mark_dead_strippable_dylib") == 0 ) {
2706 fMarkDeadStrippableDylib
= true;
2708 else if ( strcmp(arg
, "-exported_symbols_order") == 0 ) {
2709 snapshotFileArgIndex
= 1;
2710 loadSymbolOrderFile(argv
[++i
], fExportSymbolsOrder
);
2712 else if ( strcmp(arg
, "-no_compact_linkedit") == 0 ) {
2713 warnObsolete("-no_compact_linkedit");
2715 else if ( strcmp(arg
, "-no_eh_labels") == 0 ) {
2718 else if ( strcmp(arg
, "-warn_compact_unwind") == 0 ) {
2719 fWarnCompactUnwind
= true;
2721 else if ( strcmp(arg
, "-allow_sub_type_mismatches") == 0 ) {
2722 fAllowCpuSubtypeMismatches
= true;
2724 else if ( strcmp(arg
, "-no_zero_fill_sections") == 0 ) {
2725 fOptimizeZeroFill
= false;
2727 else if ( strcmp(arg
, "-merge_zero_fill_sections") == 0 ) {
2728 fMergeZeroFill
= true;
2730 else if ( strcmp(arg
, "-objc_abi_version") == 0 ) {
2731 const char* version
= argv
[++i
];
2732 if ( version
== NULL
)
2733 throw "-objc_abi_version missing version number";
2734 if ( strcmp(version
, "2") == 0 ) {
2735 fObjCABIVersion1Override
= false;
2736 fObjCABIVersion2Override
= true;
2738 else if ( strcmp(version
, "1") == 0 ) {
2739 fObjCABIVersion1Override
= true;
2740 fObjCABIVersion2Override
= false;
2743 warning("ignoring unrecognized argument (%s) to -objc_abi_version", version
);
2745 else if ( strcmp(arg
, "-warn_weak_exports") == 0 ) {
2746 fWarnWeakExports
= true;
2748 else if ( strcmp(arg
, "-objc_gc_compaction") == 0 ) {
2749 fObjcGcCompaction
= true;
2751 else if ( strcmp(arg
, "-objc_gc") == 0 ) {
2753 if ( fObjCGcOnly
) {
2754 warning("-objc_gc overriding -objc_gc_only");
2755 fObjCGcOnly
= false;
2758 else if ( strcmp(arg
, "-objc_gc_only") == 0 ) {
2761 warning("-objc_gc_only overriding -objc_gc");
2765 else if ( strcmp(arg
, "-demangle") == 0 ) {
2768 else if ( strcmp(arg
, "-version_load_command") == 0 ) {
2769 fVersionLoadCommandForcedOn
= true;
2770 fVersionLoadCommandForcedOff
= false;
2772 else if ( strcmp(arg
, "-no_version_load_command") == 0 ) {
2773 fVersionLoadCommandForcedOff
= true;
2774 fVersionLoadCommandForcedOn
= false;
2776 else if ( strcmp(arg
, "-function_starts") == 0 ) {
2777 fFunctionStartsForcedOn
= true;
2778 fFunctionStartsForcedOff
= false;
2780 else if ( strcmp(arg
, "-no_function_starts") == 0 ) {
2781 fFunctionStartsForcedOff
= true;
2782 fFunctionStartsForcedOn
= false;
2784 else if ( strcmp(arg
, "-no_data_in_code_info") == 0 ) {
2785 fDataInCodeInfoLoadCommandForcedOff
= true;
2786 fDataInCodeInfoLoadCommandForcedOn
= false;
2788 else if ( strcmp(arg
, "-data_in_code_info") == 0 ) {
2789 fDataInCodeInfoLoadCommandForcedOn
= true;
2790 fDataInCodeInfoLoadCommandForcedOff
= false;
2792 else if ( strcmp(arg
, "-object_path_lto") == 0 ) {
2793 fTempLtoObjectPath
= argv
[++i
];
2794 if ( fTempLtoObjectPath
== NULL
)
2795 throw "missing argument to -object_path_lto";
2797 else if ( strcmp(arg
, "-no_objc_category_merging") == 0 ) {
2798 fObjcCategoryMerging
= false;
2800 else if ( strcmp(arg
, "-force_symbols_weak_list") == 0 ) {
2801 snapshotFileArgIndex
= 1;
2802 loadExportFile(argv
[++i
], "-force_symbols_weak_list", fForceWeakSymbols
);
2804 else if ( strcmp(arg
, "-force_symbols_not_weak_list") == 0 ) {
2805 snapshotFileArgIndex
= 1;
2806 loadExportFile(argv
[++i
], "-force_symbols_not_weak_list", fForceNotWeakSymbols
);
2808 else if ( strcmp(arg
, "-force_symbol_weak") == 0 ) {
2809 const char* symbol
= argv
[++i
];
2810 if ( symbol
== NULL
)
2811 throw "-force_symbol_weak missing <symbol>";
2812 fForceWeakSymbols
.insert(symbol
);
2814 else if ( strcmp(arg
, "-force_symbol_not_weak") == 0 ) {
2815 const char* symbol
= argv
[++i
];
2816 if ( symbol
== NULL
)
2817 throw "-force_symbol_not_weak missing <symbol>";
2818 fForceNotWeakSymbols
.insert(symbol
);
2820 else if ( strcmp(arg
, "-reexported_symbols_list") == 0 ) {
2821 snapshotFileArgIndex
= 1;
2822 if ( fExportMode
== kExportSome
)
2823 throw "can't use -exported_symbols_list and -reexported_symbols_list";
2824 loadExportFile(argv
[++i
], "-reexported_symbols_list", fReExportSymbols
);
2826 else if ( strcmp(arg
, "-dyld_env") == 0 ) {
2827 const char* envarg
= argv
[++i
];
2828 if ( envarg
== NULL
)
2829 throw "-dyld_env missing ENV=VALUE";
2830 if ( strchr(envarg
, '=') == NULL
)
2831 throw "-dyld_env missing ENV=VALUE";
2832 fDyldEnvironExtras
.push_back(envarg
);
2834 else if ( strcmp(arg
, "-page_align_data_atoms") == 0 ) {
2835 fPageAlignDataAtoms
= true;
2837 else if (strcmp(arg
, "-debug_snapshot") == 0) {
2838 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
2839 fSnapshotRequested
= true;
2841 else if (strcmp(arg
, "-snapshot_dir") == 0) {
2842 const char* path
= argv
[++i
];
2844 throw "-snapshot_dir missing path";
2845 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
2846 fLinkSnapshot
.setSnapshotPath(path
);
2847 fSnapshotRequested
= true;
2849 else if ( strcmp(arg
, "-new_main") == 0 ) {
2850 fEntryPointLoadCommandForceOn
= true;
2852 else if ( strcmp(arg
, "-no_new_main") == 0 ) {
2853 fEntryPointLoadCommandForceOff
= true;
2855 else if ( strcmp(arg
, "-source_version") == 0 ) {
2856 const char* vers
= argv
[++i
];
2858 throw "-source_version missing <version>";
2859 fSourceVersion
= parseVersionNumber64(vers
);
2861 else if ( strcmp(arg
, "-add_source_version") == 0 ) {
2862 fSourceVersionLoadCommandForceOn
= true;
2864 else if ( strcmp(arg
, "-no_source_version") == 0 ) {
2865 fSourceVersionLoadCommandForceOff
= true;
2867 else if ( strcmp(arg
, "-sdk_version") == 0 ) {
2868 const char* vers
= argv
[++i
];
2870 throw "-sdk_version missing <version>";
2871 fSDKVersion
= parseVersionNumber32(vers
);
2873 else if ( strcmp(arg
, "-dependent_dr_info") == 0 ) {
2874 fDependentDRInfoForcedOn
= true;
2876 else if ( strcmp(arg
, "-no_dependent_dr_info") == 0 ) {
2877 fDependentDRInfoForcedOff
= true;
2879 else if ( strcmp(arg
, "-kexts_use_stubs") == 0 ) {
2880 fKextsUseStubs
= true;
2882 else if ( strcmp(argv
[i
], "-dependency_info") == 0 ) {
2884 // previously handled by buildSearchPaths()
2886 else if ( strcmp(arg
, "-export_dynamic") == 0 ) {
2887 fExportDynamic
= true;
2889 else if ( strcmp(arg
, "-force_symbols_coalesce_list") == 0 ) {
2890 snapshotFileArgIndex
= 1;
2891 loadExportFile(argv
[++i
], "-force_symbols_coalesce_list", fForceCoalesceSymbols
);
2893 else if ( strcmp(arg
, "-add_linker_option") == 0 ) {
2894 // ex: -add_linker_option '-framework Foundation'
2895 const char* optString
= argv
[++i
];
2896 if ( optString
== NULL
)
2897 throw "-add_linker_option missing <option>";
2898 // break up into list of tokens at whitespace
2899 std::vector
<const char*> opts
;
2900 char* buffer
= strdup(optString
);
2901 char* start
= buffer
;
2902 for (char* s
= buffer
; ; ++s
) {
2903 if ( isspace(*s
) ) {
2905 opts
.push_back(start
);
2908 else if ( *s
== '\0' ) {
2909 opts
.push_back(start
);
2913 fLinkerOptions
.push_back(opts
);
2915 else if ( strcmp(arg
, "-allow_simulator_linking_to_macosx_dylibs") == 0 ) {
2916 fAllowSimulatorToLinkWithMacOSX
= true;
2918 else if ( strcmp(arg
, "-keep_dwarf_unwind") == 0 ) {
2919 fKeepDwarfUnwindForcedOn
= true;
2920 fKeepDwarfUnwindForcedOff
= false;
2922 else if ( strcmp(arg
, "-no_keep_dwarf_unwind") == 0 ) {
2923 fKeepDwarfUnwindForcedOn
= false;
2924 fKeepDwarfUnwindForcedOff
= true;
2926 else if ( strcmp(arg
, "-no_dtrace_dof") == 0 ) {
2927 fGenerateDtraceDOF
= false;
2930 throwf("unknown option: %s", arg
);
2933 if (snapshotArgCount
== -1)
2934 snapshotArgCount
= i
-snapshotArgIndex
+1;
2935 if (snapshotArgCount
> 0)
2936 fLinkSnapshot
.addSnapshotLinkArg(snapshotArgIndex
, snapshotArgCount
, snapshotFileArgIndex
);
2939 FileInfo info
= findFile(arg
);
2940 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2941 if ( strcmp(&info
.path
[strlen(info
.path
)-2], ".a") == 0 )
2944 fInputFiles
.push_back(info
);
2948 // if a -lazy option was used, implicitly link in lazydylib1.o
2949 if ( fUsingLazyDylibLinking
) {
2950 FileInfo info
= findLibrary("lazydylib1.o");
2951 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)argc
);
2955 if (fSnapshotRequested
)
2956 fLinkSnapshot
.createSnapshot();
2962 // -syslibroot <path> is used for SDK support.
2963 // The rule is that all search paths (both explicit and default) are
2964 // checked to see if they exist in the SDK. If so, that path is
2965 // replaced with the sdk prefixed path. If not, that search path
2966 // is used as is. If multiple -syslibroot options are specified
2967 // their directory structures are logically overlayed and files
2968 // from sdks specified earlier on the command line used before later ones.
2970 void Options::buildSearchPaths(int argc
, const char* argv
[])
2972 bool addStandardLibraryDirectories
= true;
2973 std::vector
<const char*> libraryPaths
;
2974 std::vector
<const char*> frameworkPaths
;
2975 libraryPaths
.reserve(10);
2976 frameworkPaths
.reserve(10);
2977 // scan through argv looking for -L, -F, -Z, and -syslibroot options
2978 for(int i
=0; i
< argc
; ++i
) {
2979 if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'L') ) {
2980 const char* libSearchDir
= &argv
[i
][2];
2981 // Allow either "-L{path}" or "-L {path}".
2982 if (argv
[i
][2] == '\0') {
2983 // -L {path}. Make sure there is an argument following this.
2984 const char* path
= argv
[++i
];
2986 throw "-L missing argument";
2987 libSearchDir
= path
;
2989 if ( libSearchDir
[0] == '\0' )
2990 throw "-L must be immediately followed by a directory path (no space)";
2991 struct stat statbuf
;
2992 if ( stat(libSearchDir
, &statbuf
) == 0 ) {
2993 if ( statbuf
.st_mode
& S_IFDIR
)
2994 libraryPaths
.push_back(libSearchDir
);
2996 warning("path '%s' following -L not a directory", libSearchDir
);
2999 warning("directory not found for option '-L%s'", libSearchDir
);
3002 else if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'F') ) {
3003 const char* frameworkSearchDir
= &argv
[i
][2];
3004 // Allow either "-F{path}" or "-F {path}".
3005 if (argv
[i
][2] == '\0') {
3006 // -F {path}. Make sure there is an argument following this.
3007 const char* path
= argv
[++i
];
3009 throw "-F missing argument";
3010 frameworkSearchDir
= path
;
3012 if ( frameworkSearchDir
[0] == '\0' )
3013 throw "-F must be immediately followed by a directory path (no space)";
3014 struct stat statbuf
;
3015 if ( stat(frameworkSearchDir
, &statbuf
) == 0 ) {
3016 if ( statbuf
.st_mode
& S_IFDIR
)
3017 frameworkPaths
.push_back(frameworkSearchDir
);
3019 warning("path '%s' following -F not a directory", frameworkSearchDir
);
3022 warning("directory not found for option '-F%s'", frameworkSearchDir
);
3025 else if ( strcmp(argv
[i
], "-Z") == 0 )
3026 addStandardLibraryDirectories
= false;
3027 else if ( strcmp(argv
[i
], "-v") == 0 ) {
3029 extern const char ldVersionString
[];
3030 fprintf(stderr
, "%s", ldVersionString
);
3031 fprintf(stderr
, "configured to support archs: %s\n", ALL_SUPPORTED_ARCHS
);
3032 // if only -v specified, exit cleanly
3034 const char* ltoVers
= lto::version();
3035 if ( ltoVers
!= NULL
)
3036 fprintf(stderr
, "LTO support using: %s\n", ltoVers
);
3040 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
3041 const char* path
= argv
[++i
];
3043 throw "-syslibroot missing argument";
3044 fSDKPaths
.push_back(path
);
3046 else if ( strcmp(argv
[i
], "-search_paths_first") == 0 ) {
3047 fLibrarySearchMode
= kSearchDylibAndArchiveInEachDir
;
3049 else if ( strcmp(argv
[i
], "-search_dylibs_first") == 0 ) {
3050 fLibrarySearchMode
= kSearchAllDirsForDylibsThenAllDirsForArchives
;
3052 else if ( strcmp(argv
[i
], "-w") == 0 ) {
3053 sEmitWarnings
= false;
3055 else if ( strcmp(argv
[i
], "-fatal_warnings") == 0 ) {
3056 sFatalWarnings
= true;
3058 else if ( strcmp(argv
[i
], "-dependency_info") == 0 ) {
3059 const char* path
= argv
[++i
];
3061 throw "-dependency_info missing <path>";
3062 fDependencyInfoPath
= path
;
3065 int standardLibraryPathsStartIndex
= libraryPaths
.size();
3066 int standardFrameworkPathsStartIndex
= frameworkPaths
.size();
3067 if ( addStandardLibraryDirectories
) {
3068 libraryPaths
.push_back("/usr/lib");
3069 libraryPaths
.push_back("/usr/local/lib");
3071 frameworkPaths
.push_back("/Library/Frameworks/");
3072 frameworkPaths
.push_back("/System/Library/Frameworks/");
3073 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
3076 // <rdar://problem/5829579> Support for configure based hacks
3077 // if last -syslibroot is /, then ignore all syslibroots
3078 if ( fSDKPaths
.size() > 0 ) {
3079 if ( strcmp(fSDKPaths
.back(), "/") == 0 ) {
3084 // now merge sdk and library paths to make real search paths
3085 fLibrarySearchPaths
.reserve(libraryPaths
.size()*(fSDKPaths
.size()+1));
3087 for (std::vector
<const char*>::iterator it
= libraryPaths
.begin(); it
!= libraryPaths
.end(); ++it
, ++libIndex
) {
3088 const char* libDir
= *it
;
3089 bool sdkOverride
= false;
3090 if ( libDir
[0] == '/' ) {
3091 char betterLibDir
[PATH_MAX
];
3092 if ( strstr(libDir
, "/..") != NULL
) {
3093 if ( realpath(libDir
, betterLibDir
) != NULL
)
3094 libDir
= strdup(betterLibDir
);
3096 const int libDirLen
= strlen(libDir
);
3097 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
3098 const char* sdkDir
= *sdkit
;
3099 const int sdkDirLen
= strlen(sdkDir
);
3100 char newPath
[libDirLen
+ sdkDirLen
+4];
3101 strcpy(newPath
, sdkDir
);
3102 if ( newPath
[sdkDirLen
-1] == '/' )
3103 newPath
[sdkDirLen
-1] = '\0';
3104 strcat(newPath
, libDir
);
3105 struct stat statBuffer
;
3106 if ( stat(newPath
, &statBuffer
) == 0 ) {
3107 fLibrarySearchPaths
.push_back(strdup(newPath
));
3112 if ( !sdkOverride
) {
3113 if ( (libIndex
>= standardLibraryPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
3114 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
3115 // if one SDK is specified and a standard library path is not in the SDK, don't use it
3118 fLibrarySearchPaths
.push_back(libDir
);
3123 // now merge sdk and framework paths to make real search paths
3124 fFrameworkSearchPaths
.reserve(frameworkPaths
.size()*(fSDKPaths
.size()+1));
3126 for (std::vector
<const char*>::iterator it
= frameworkPaths
.begin(); it
!= frameworkPaths
.end(); ++it
, ++frameIndex
) {
3127 const char* frameworkDir
= *it
;
3128 bool sdkOverride
= false;
3129 if ( frameworkDir
[0] == '/' ) {
3130 char betterFrameworkDir
[PATH_MAX
];
3131 if ( strstr(frameworkDir
, "/..") != NULL
) {
3132 if ( realpath(frameworkDir
, betterFrameworkDir
) != NULL
)
3133 frameworkDir
= strdup(betterFrameworkDir
);
3135 const int frameworkDirLen
= strlen(frameworkDir
);
3136 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
3137 const char* sdkDir
= *sdkit
;
3138 const int sdkDirLen
= strlen(sdkDir
);
3139 char newPath
[frameworkDirLen
+ sdkDirLen
+4];
3140 strcpy(newPath
, sdkDir
);
3141 if ( newPath
[sdkDirLen
-1] == '/' )
3142 newPath
[sdkDirLen
-1] = '\0';
3143 strcat(newPath
, frameworkDir
);
3144 struct stat statBuffer
;
3145 if ( stat(newPath
, &statBuffer
) == 0 ) {
3146 fFrameworkSearchPaths
.push_back(strdup(newPath
));
3151 if ( !sdkOverride
) {
3152 if ( (frameIndex
>= standardFrameworkPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
3153 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
3154 // if one SDK is specified and a standard library path is not in the SDK, don't use it
3157 fFrameworkSearchPaths
.push_back(frameworkDir
);
3163 fprintf(stderr
,"Library search paths:\n");
3164 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
3165 it
!= fLibrarySearchPaths
.end();
3167 fprintf(stderr
,"\t%s\n", *it
);
3168 fprintf(stderr
,"Framework search paths:\n");
3169 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
3170 it
!= fFrameworkSearchPaths
.end();
3172 fprintf(stderr
,"\t%s\n", *it
);
3176 // this is run before the command line is parsed
3177 void Options::parsePreCommandLineEnvironmentSettings()
3179 if ((getenv("LD_TRACE_ARCHIVES") != NULL
)
3180 || (getenv("RC_TRACE_ARCHIVES") != NULL
))
3181 fTraceArchives
= true;
3183 if ((getenv("LD_TRACE_DYLIBS") != NULL
)
3184 || (getenv("RC_TRACE_DYLIBS") != NULL
)) {
3185 fTraceDylibs
= true;
3186 fTraceIndirectDylibs
= true;
3189 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL
) {
3190 fTraceDylibSearching
= true;
3193 if (getenv("LD_PRINT_OPTIONS") != NULL
)
3194 fPrintOptions
= true;
3196 if (fTraceDylibs
|| fTraceArchives
)
3197 fTraceOutputFile
= getenv("LD_TRACE_FILE");
3199 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL
)
3200 fPrintOrderFileStatistics
= true;
3202 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL
)
3205 if (getenv("LD_NO_ENCRYPT") != NULL
)
3206 fEncryptable
= false;
3208 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL
)
3209 fAllowCpuSubtypeMismatches
= true;
3211 sWarningsSideFilePath
= getenv("LD_WARN_FILE");
3213 const char* customDyldPath
= getenv("LD_DYLD_PATH");
3214 if ( customDyldPath
!= NULL
)
3215 fDyldInstallPath
= customDyldPath
;
3217 const char* debugArchivePath
= getenv("LD_DEBUG_SNAPSHOT");
3218 if (debugArchivePath
!= NULL
) {
3219 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
3220 if (strlen(debugArchivePath
) > 0)
3221 fLinkSnapshot
.setSnapshotPath(debugArchivePath
);
3222 fSnapshotRequested
= true;
3225 const char* pipeFdString
= getenv("LD_PIPELINE_FIFO");
3226 if (pipeFdString
!= NULL
) {
3227 fPipelineFifo
= pipeFdString
;
3232 // this is run after the command line is parsed
3233 void Options::parsePostCommandLineEnvironmentSettings()
3235 // when building a dynamic main executable, default any use of @executable_path to output path
3236 if ( fExecutablePath
== NULL
&& (fOutputKind
== kDynamicExecutable
) ) {
3237 fExecutablePath
= fOutputFile
;
3240 // allow build system to set default seg_addr_table
3241 if ( fSegAddrTablePath
== NULL
)
3242 fSegAddrTablePath
= getenv("LD_SEG_ADDR_TABLE");
3244 // allow build system to turn on prebinding
3246 fPrebind
= ( getenv("LD_PREBIND") != NULL
);
3249 // allow build system to force on dead-code-stripping
3250 if ( !fDeadStrip
) {
3251 if ( getenv("LD_DEAD_STRIP") != NULL
) {
3252 switch (fOutputKind
) {
3253 case Options::kDynamicLibrary
:
3254 case Options::kDynamicExecutable
:
3255 case Options::kDynamicBundle
:
3258 case Options::kPreload
:
3259 case Options::kObjectFile
:
3260 case Options::kDyld
:
3261 case Options::kStaticExecutable
:
3262 case Options::kKextBundle
:
3268 // allow build system to force on -warn_commons
3269 if ( getenv("LD_WARN_COMMONS") != NULL
)
3270 fWarnCommons
= true;
3272 // allow B&I to set default -source_version
3273 if ( fSourceVersion
== 0 ) {
3274 const char* vers
= getenv("RC_ProjectSourceVersion");
3276 fSourceVersion
= parseVersionNumber64(vers
);
3281 void Options::reconfigureDefaults()
3283 // sync reader options
3284 switch ( fOutputKind
) {
3285 case Options::kObjectFile
:
3286 fForFinalLinkedImage
= false;
3288 case Options::kDyld
:
3290 fForFinalLinkedImage
= true;
3293 case Options::kDynamicLibrary
:
3294 case Options::kDynamicBundle
:
3295 case Options::kKextBundle
:
3296 fForFinalLinkedImage
= true;
3299 case Options::kDynamicExecutable
:
3300 case Options::kStaticExecutable
:
3301 case Options::kPreload
:
3302 fLinkingMainExecutable
= true;
3303 fForFinalLinkedImage
= true;
3308 // set default min OS version
3309 if ( (fMacVersionMin
== ld::macVersionUnset
)
3310 && (fIOSVersionMin
== ld::iOSVersionUnset
) ) {
3311 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
3312 const char* macVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
3313 const char* iPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
3314 const char* iOSVers
= getenv("IOS_DEPLOYMENT_TARGET");
3315 const char* iOSSimulatorVers
= getenv("IOS_SIMULATOR_DEPLOYMENT_TARGET");
3316 if ( macVers
!= NULL
)
3317 setMacOSXVersionMin(macVers
);
3318 else if ( iPhoneVers
!= NULL
)
3319 setIOSVersionMin(iPhoneVers
);
3320 else if ( iOSVers
!= NULL
)
3321 setIOSVersionMin(iOSVers
);
3322 else if ( iOSSimulatorVers
!= NULL
)
3323 setIOSVersionMin(iOSSimulatorVers
);
3325 // if still nothing, set default based on architecture
3326 switch ( fArchitecture
) {
3328 case CPU_TYPE_X86_64
:
3329 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
3330 #ifdef DEFAULT_MACOSX_MIN_VERSION
3331 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION
);
3332 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
3334 warning("-macosx_version_min not specified, assuming 10.6");
3335 fMacVersionMin
= ld::mac10_6
;
3340 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
3341 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
3342 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION
);
3343 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION
);
3345 warning("-ios_version_min not specified, assuming 6.0");
3346 setIOSVersionMin("6.0");
3351 // architecture will be infered later by examining .o files
3358 // adjust min based on architecture
3359 switch ( fArchitecture
) {
3361 if ( (fMacVersionMin
< ld::mac10_4
) && (fIOSVersionMin
== ld::iOSVersionUnset
) ) {
3362 //warning("-macosx_version_min should be 10.4 or later for i386");
3363 fMacVersionMin
= ld::mac10_4
;
3366 case CPU_TYPE_X86_64
:
3367 if ( (fMacVersionMin
< ld::mac10_4
) && (fIOSVersionMin
== ld::iOSVersionUnset
) ) {
3368 //warning("-macosx_version_min should be 10.4 or later for x86_64");
3369 fMacVersionMin
= ld::mac10_4
;
3372 case CPU_TYPE_ARM64
:
3373 if ( fIOSVersionMin
< ld::iOS_7_0
) {
3374 //warning("-mios_version_min should be 7.0 or later for arm64");
3375 fIOSVersionMin
= ld::iOS_7_0
;
3380 // default to adding functions start for dynamic code, static code must opt-in
3381 switch ( fOutputKind
) {
3382 case Options::kPreload
:
3383 case Options::kStaticExecutable
:
3384 case Options::kKextBundle
:
3385 if ( fDataInCodeInfoLoadCommandForcedOn
)
3386 fDataInCodeInfoLoadCommand
= true;
3387 if ( fFunctionStartsForcedOn
)
3388 fFunctionStartsLoadCommand
= true;
3390 case Options::kObjectFile
:
3391 case Options::kDynamicExecutable
:
3392 case Options::kDyld
:
3393 case Options::kDynamicLibrary
:
3394 case Options::kDynamicBundle
:
3395 if ( !fDataInCodeInfoLoadCommandForcedOff
)
3396 fDataInCodeInfoLoadCommand
= true;
3397 if ( !fFunctionStartsForcedOff
)
3398 fFunctionStartsLoadCommand
= true;
3402 // adjust kext type based on architecture
3403 if ( fOutputKind
== kKextBundle
) {
3404 switch ( fArchitecture
) {
3405 case CPU_TYPE_X86_64
:
3406 // x86_64 uses new MH_KEXT_BUNDLE type
3407 fMakeCompressedDyldInfo
= false;
3408 fMakeCompressedDyldInfoForceOff
= true;
3409 fAllowTextRelocs
= true;
3410 fUndefinedTreatment
= kUndefinedDynamicLookup
;
3412 case CPU_TYPE_ARM64
:
3413 // arm64 uses new MH_KEXT_BUNDLE type
3414 fMakeCompressedDyldInfo
= false;
3415 fMakeCompressedDyldInfoForceOff
= true;
3416 fAllowTextRelocs
= false;
3417 fKextsUseStubs
= true;
3418 fUndefinedTreatment
= kUndefinedDynamicLookup
;
3421 if ( fIOSVersionMin
>= ld::iOS_5_0
) {
3422 // iOS 5.0 and later use new MH_KEXT_BUNDLE type
3423 fMakeCompressedDyldInfo
= false;
3424 fMakeCompressedDyldInfoForceOff
= true;
3425 // kexts are PIC in iOS 6.0 and later
3426 fAllowTextRelocs
= (fIOSVersionMin
< ld::iOS_6_0
);
3427 fKextsUseStubs
= !fAllowTextRelocs
;
3428 fUndefinedTreatment
= kUndefinedDynamicLookup
;
3431 // else use object file
3434 fOutputKind
= kObjectFile
;
3439 // disable implicit dylibs when targeting 10.3
3440 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
3441 if ( !minOS(ld::mac10_4
, ld::iOS_2_0
) )
3442 fImplicitlyLinkPublicDylibs
= false;
3445 // allow build system to force linker to ignore -prebind
3446 if ( getenv("LD_FORCE_NO_PREBIND") != NULL
)
3449 // allow build system to force linker to ignore -seg_addr_table
3450 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL
)
3451 fSegAddrTablePath
= NULL
;
3453 // check for base address specified externally
3454 if ( (fSegAddrTablePath
!= NULL
) && (fOutputKind
== Options::kDynamicLibrary
) ) {
3455 parseSegAddrTable(fSegAddrTablePath
, this->installPath());
3456 // HACK to support seg_addr_table entries that are physical paths instead of install paths
3457 if ( fBaseAddress
== 0 ) {
3458 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
3459 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.4.dylib");
3460 if ( fBaseAddress
== 0 )
3461 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.9.dylib");
3464 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
3465 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libz.1.2.3.dylib");
3467 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
3468 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libutil1.0.dylib");
3472 // split segs only allowed for dylibs
3474 // split seg only supported for i386, and arm.
3475 switch ( fArchitecture
) {
3477 if ( fOutputKind
!= Options::kDynamicLibrary
)
3479 // make sure read and write segments are proper distance apart
3480 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x10000000) )
3481 fBaseWritableAddress
= fBaseAddress
+ 0x10000000;
3484 if ( fOutputKind
!= Options::kDynamicLibrary
) {
3488 // make sure read and write segments are proper distance apart
3489 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x08000000) )
3490 fBaseWritableAddress
= fBaseAddress
+ 0x08000000;
3496 fBaseWritableAddress
= 0;
3500 // set too-large size
3501 switch ( fArchitecture
) {
3503 fMaxAddress
= 0xFFFFFFFF;
3505 case CPU_TYPE_X86_64
:
3508 switch ( fOutputKind
) {
3509 case Options::kDynamicExecutable
:
3510 case Options::kDynamicLibrary
:
3511 case Options::kDynamicBundle
:
3512 // user land code is limited to low 1GB
3513 fMaxAddress
= 0x2FFFFFFF;
3515 case Options::kStaticExecutable
:
3516 case Options::kObjectFile
:
3517 case Options::kDyld
:
3518 case Options::kPreload
:
3519 case Options::kKextBundle
:
3520 fMaxAddress
= 0xFFFFFFFF;
3523 // range check -seg1addr for ARM
3524 if ( fBaseAddress
> fMaxAddress
) {
3525 warning("ignoring -seg1addr 0x%08llX. Address out of range.", fBaseAddress
);
3531 // <rdar://problem/6138961> -r implies no prebinding for all architectures
3532 if ( fOutputKind
== Options::kObjectFile
)
3535 // disable prebinding depending on arch and min OS version
3537 switch ( fArchitecture
) {
3539 if ( fMacVersionMin
== ld::mac10_4
) {
3540 // in 10.4 only split seg dylibs are prebound
3541 if ( (fOutputKind
!= Options::kDynamicLibrary
) || ! fSplitSegs
)
3544 else if ( fMacVersionMin
>= ld::mac10_5
) {
3545 // in 10.5 nothing is prebound
3548 else if ( fIOSVersionMin
!= ld::iOSVersionUnset
) {
3549 // nothing in simulator is prebound
3553 // in 10.3 and earlier only dylibs and main executables could be prebound
3554 switch ( fOutputKind
) {
3555 case Options::kDynamicExecutable
:
3556 case Options::kDynamicLibrary
:
3557 // only main executables and dylibs can be prebound
3559 case Options::kStaticExecutable
:
3560 case Options::kDynamicBundle
:
3561 case Options::kObjectFile
:
3562 case Options::kDyld
:
3563 case Options::kPreload
:
3564 case Options::kKextBundle
:
3565 // disable prebinding for everything else
3571 case CPU_TYPE_X86_64
:
3575 switch ( fOutputKind
) {
3576 case Options::kDynamicExecutable
:
3577 case Options::kDynamicLibrary
:
3578 // only main executables and dylibs can be prebound
3580 case Options::kStaticExecutable
:
3581 case Options::kDynamicBundle
:
3582 case Options::kObjectFile
:
3583 case Options::kDyld
:
3584 case Options::kPreload
:
3585 case Options::kKextBundle
:
3586 // disable prebinding for everything else
3594 // only prebound images can be split-seg
3595 if ( fSplitSegs
&& !fPrebind
)
3598 // determine if info for shared region should be added
3599 if ( fOutputKind
== Options::kDynamicLibrary
) {
3600 if ( minOS(ld::mac10_5
, ld::iOS_3_1
) )
3602 if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
3603 || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
3604 fSharedRegionEligible
= true;
3606 else if ( fOutputKind
== Options::kDyld
) {
3607 // <rdar://problem/10111122> Enable dyld to be put into the dyld shared cache
3608 fSharedRegionEligible
= true;
3611 // figure out if module table is needed for compatibility with old ld/dyld
3612 if ( fOutputKind
== Options::kDynamicLibrary
) {
3613 switch ( fArchitecture
) {
3615 if ( fIOSVersionMin
!= ld::iOSVersionUnset
) // simulator never needs modules
3619 fNeedsModuleTable
= true; // redo_prebinding requires a module table
3624 // <rdar://problem/5366363> -r -x implies -S
3625 if ( (fOutputKind
== Options::kObjectFile
) && (fLocalSymbolHandling
== kLocalSymbolsNone
) )
3626 fDebugInfoStripping
= Options::kDebugInfoNone
;
3628 // choose how to process unwind info
3629 switch ( fArchitecture
) {
3631 case CPU_TYPE_X86_64
:
3632 case CPU_TYPE_ARM64
:
3633 switch ( fOutputKind
) {
3634 case Options::kObjectFile
:
3635 case Options::kStaticExecutable
:
3636 case Options::kPreload
:
3637 case Options::kKextBundle
:
3638 fAddCompactUnwindEncoding
= false;
3640 case Options::kDyld
:
3641 case Options::kDynamicLibrary
:
3642 case Options::kDynamicBundle
:
3643 case Options::kDynamicExecutable
:
3644 //if ( fAddCompactUnwindEncoding && (fVersionMin >= ld::mac10_6) )
3645 // fRemoveDwarfUnwindIfCompactExists = true;
3650 fAddCompactUnwindEncoding
= false;
3651 fRemoveDwarfUnwindIfCompactExists
= false;
3654 // if -arch is missing, assume we don't want compact unwind info
3655 fAddCompactUnwindEncoding
= false;
3659 // only iOS main executables should be encrypted
3660 if ( fOutputKind
!= Options::kDynamicExecutable
)
3661 fEncryptable
= false;
3662 if ( (fArchitecture
!= CPU_TYPE_ARM
) && (fArchitecture
!= CPU_TYPE_ARM64
) )
3663 fEncryptable
= false;
3665 // don't move inits in dyld because dyld wants certain
3666 // entries point at stable locations at the start of __text
3667 if ( fOutputKind
== Options::kDyld
)
3668 fAutoOrderInitializers
= false;
3671 // disable __data ordering for some output kinds
3672 switch ( fOutputKind
) {
3673 case Options::kObjectFile
:
3674 case Options::kDyld
:
3675 case Options::kStaticExecutable
:
3676 case Options::kPreload
:
3677 case Options::kKextBundle
:
3680 case Options::kDynamicExecutable
:
3681 case Options::kDynamicLibrary
:
3682 case Options::kDynamicBundle
:
3686 // only use compressed LINKEDIT for final linked images
3687 switch ( fOutputKind
) {
3688 case Options::kDynamicExecutable
:
3689 case Options::kDynamicLibrary
:
3690 case Options::kDynamicBundle
:
3692 case Options::kPreload
:
3693 case Options::kStaticExecutable
:
3694 case Options::kObjectFile
:
3695 case Options::kDyld
:
3696 case Options::kKextBundle
:
3697 fMakeCompressedDyldInfoForceOff
= true;
3700 if ( fMakeCompressedDyldInfoForceOff
)
3701 fMakeCompressedDyldInfo
= false;
3704 // only use compressed LINKEDIT for:
3705 // Mac OS X 10.6 or later
3707 if ( fMakeCompressedDyldInfo
) {
3708 if ( !minOS(ld::mac10_6
, ld::iOS_3_1
) )
3709 fMakeCompressedDyldInfo
= false;
3712 // only ARM enforces that cpu-sub-types must match
3713 if ( fArchitecture
!= CPU_TYPE_ARM
)
3714 fAllowCpuSubtypeMismatches
= true;
3716 // only final linked images can not optimize zero fill sections
3717 if ( fOutputKind
== Options::kObjectFile
)
3718 fOptimizeZeroFill
= true;
3720 // all undefines in -r mode
3721 // if ( fOutputKind == Options::kObjectFile )
3722 // fUndefinedTreatment = kUndefinedSuppress;
3724 // only dynamic final linked images should warn about use of commmons
3725 if ( fWarnCommons
) {
3726 switch ( fOutputKind
) {
3727 case Options::kDynamicExecutable
:
3728 case Options::kDynamicLibrary
:
3729 case Options::kDynamicBundle
:
3731 case Options::kPreload
:
3732 case Options::kStaticExecutable
:
3733 case Options::kObjectFile
:
3734 case Options::kDyld
:
3735 case Options::kKextBundle
:
3736 fWarnCommons
= false;
3741 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
3742 if ( minOS(ld::mac10_5
, ld::iOS_2_0
) )
3743 fUseSimplifiedDylibReExports
= true;
3745 // Mac OS X 10.7 and iOS 4.2 support LC_LOAD_UPWARD_DYLIB
3746 if ( minOS(ld::mac10_7
, ld::iOS_4_2
) && (fOutputKind
== kDynamicLibrary
) )
3747 fCanUseUpwardDylib
= true;
3749 // MacOSX 10.7 defaults to PIE
3750 if ( ((fArchitecture
== CPU_TYPE_X86_64
) || (fArchitecture
== CPU_TYPE_I386
))
3751 && (fOutputKind
== kDynamicExecutable
)
3752 && (fMacVersionMin
>= ld::mac10_7
) ) {
3753 fPositionIndependentExecutable
= true;
3756 // armv7 for iOS4.3 defaults to PIE
3757 if ( (fArchitecture
== CPU_TYPE_ARM
)
3758 && fArchSupportsThumb2
3759 && (fOutputKind
== kDynamicExecutable
)
3760 && (fIOSVersionMin
>= ld::iOS_4_3
) ) {
3761 fPositionIndependentExecutable
= true;
3764 // -no_pie anywhere on command line disable PIE
3765 if ( fDisablePositionIndependentExecutable
)
3766 fPositionIndependentExecutable
= false;
3768 // arm64 is always PIE
3769 if ( (fArchitecture
== CPU_TYPE_ARM64
) && (fOutputKind
== kDynamicExecutable
) ) {
3770 fPositionIndependentExecutable
= true;
3773 // set fOutputSlidable
3774 switch ( fOutputKind
) {
3775 case Options::kObjectFile
:
3776 fOutputSlidable
= false;
3778 case Options::kStaticExecutable
:
3779 case Options::kDynamicExecutable
:
3780 fOutputSlidable
= fPositionIndependentExecutable
;
3782 case Options::kPreload
:
3783 fOutputSlidable
= fPIEOnCommandLine
;
3785 case Options::kDyld
:
3786 case Options::kDynamicLibrary
:
3787 case Options::kDynamicBundle
:
3788 case Options::kKextBundle
:
3789 fOutputSlidable
= true;
3793 // let linker know if thread local variables are supported
3794 if ( fMacVersionMin
>= ld::mac10_7
) {
3798 // default to adding version load command for dynamic code, static code must opt-in
3799 switch ( fOutputKind
) {
3800 case Options::kObjectFile
:
3801 fVersionLoadCommand
= false;
3803 case Options::kStaticExecutable
:
3804 case Options::kPreload
:
3805 case Options::kKextBundle
:
3806 if ( fVersionLoadCommandForcedOn
)
3807 fVersionLoadCommand
= true;
3809 case Options::kDynamicExecutable
:
3810 case Options::kDyld
:
3811 case Options::kDynamicLibrary
:
3812 case Options::kDynamicBundle
:
3813 if ( !fVersionLoadCommandForcedOff
)
3814 fVersionLoadCommand
= true;
3818 // support re-export of individual symbols in MacOSX 10.7 and iOS 4.2
3819 if ( (fOutputKind
== kDynamicLibrary
) && minOS(ld::mac10_7
, ld::iOS_4_2
) )
3820 fCanReExportSymbols
= true;
3822 // ObjC optimization is only in dynamic final linked images
3823 switch ( fOutputKind
) {
3824 case Options::kObjectFile
:
3825 case Options::kStaticExecutable
:
3826 case Options::kPreload
:
3827 case Options::kKextBundle
:
3828 case Options::kDyld
:
3829 fObjcCategoryMerging
= false;
3831 case Options::kDynamicExecutable
:
3832 case Options::kDynamicLibrary
:
3833 case Options::kDynamicBundle
:
3837 // i386 main executables linked on Mac OS X 10.7 default to NX heap
3838 // regardless of target unless overriden with -allow_heap_execute anywhere
3839 // on the command line
3840 if ( (fArchitecture
== CPU_TYPE_I386
) && (fOutputKind
== kDynamicExecutable
) && !fDisableNonExecutableHeap
)
3841 fNonExecutableHeap
= true;
3843 // Use LC_MAIN instead of LC_UNIXTHREAD for newer OSs
3844 switch ( fOutputKind
) {
3845 case Options::kDynamicExecutable
:
3846 if ( fEntryPointLoadCommandForceOn
) {
3847 fEntryPointLoadCommand
= true;
3848 fEntryName
= "_main";
3850 else if ( fEntryPointLoadCommandForceOff
) {
3851 fNeedsThreadLoadCommand
= true;
3854 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) ) {
3855 fEntryPointLoadCommand
= true;
3856 fEntryName
= "_main";
3859 fNeedsThreadLoadCommand
= true;
3862 case Options::kObjectFile
:
3863 case Options::kKextBundle
:
3864 case Options::kDynamicLibrary
:
3865 case Options::kDynamicBundle
:
3868 case Options::kStaticExecutable
:
3869 case Options::kPreload
:
3870 case Options::kDyld
:
3871 fNeedsThreadLoadCommand
= true;
3875 // add LC_SOURCE_VERSION
3876 switch ( fOutputKind
) {
3877 case Options::kDynamicExecutable
:
3878 case Options::kKextBundle
:
3879 case Options::kDynamicLibrary
:
3880 case Options::kDynamicBundle
:
3881 case Options::kDyld
:
3882 case Options::kStaticExecutable
:
3883 if ( fSourceVersionLoadCommandForceOn
) {
3884 fSourceVersionLoadCommand
= true;
3886 else if ( fSourceVersionLoadCommandForceOff
) {
3887 fSourceVersionLoadCommand
= false;
3890 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) ) {
3891 fSourceVersionLoadCommand
= true;
3894 fSourceVersionLoadCommand
= false;
3897 case Options::kObjectFile
:
3898 case Options::kPreload
:
3899 fSourceVersionLoadCommand
= false;
3904 // add LC_DYLIB_CODE_SIGN_DRS
3905 switch ( fOutputKind
) {
3906 case Options::kDynamicExecutable
:
3907 case Options::kDynamicLibrary
:
3908 case Options::kDynamicBundle
:
3909 if ( fDependentDRInfoForcedOn
) {
3910 fDependentDRInfo
= true;
3912 else if ( fDependentDRInfoForcedOff
) {
3913 fDependentDRInfo
= false;
3916 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) )
3917 fDependentDRInfo
= true;
3919 fDependentDRInfo
= false;
3922 case Options::kKextBundle
:
3923 case Options::kDyld
:
3924 case Options::kStaticExecutable
:
3925 case Options::kObjectFile
:
3926 case Options::kPreload
:
3927 fDependentDRInfo
= false;
3931 // if -sdk_version not on command line, infer from -syslibroot
3932 if ( (fSDKVersion
== 0) && (fSDKPaths
.size() > 0) ) {
3933 const char* sdkPath
= fSDKPaths
.front();
3934 const char* end
= &sdkPath
[strlen(sdkPath
)-1];
3935 while ( !isdigit(*end
) && (end
> sdkPath
) )
3937 const char* start
= end
-1;
3938 while ( (isdigit(*start
) || (*start
== '.')) && (start
> sdkPath
))
3940 char sdkVersionStr
[32];
3941 int len
= end
-start
+1;
3943 strlcpy(sdkVersionStr
, start
+1, len
);
3944 fSDKVersion
= parseVersionNumber32(sdkVersionStr
);
3948 // if -sdk_version and -syslibroot not used, but targeting MacOSX, use current OS version
3949 if ( (fSDKVersion
== 0) && (fMacVersionMin
!= ld::macVersionUnset
) ) {
3950 // special case if RC_ProjectName and MACOSX_DEPLOYMENT_TARGET are both set that sdkversion=minos
3951 if ( getenv("RC_ProjectName") && getenv("MACOSX_DEPLOYMENT_TARGET") ) {
3952 fSDKVersion
= fMacVersionMin
;
3955 int mib
[2] = { CTL_KERN
, KERN_OSRELEASE
};
3956 char kernVersStr
[100];
3957 size_t strlen
= sizeof(kernVersStr
);
3958 if ( sysctl(mib
, 2, kernVersStr
, &strlen
, NULL
, 0) != -1 ) {
3959 uint32_t kernVers
= parseVersionNumber32(kernVersStr
);
3960 int minor
= (kernVers
>> 16) - 4; // kernel major version is 4 ahead of x in 10.x
3961 fSDKVersion
= 0x000A0000 + (minor
<< 8);
3966 // allow trie based absolute symbols if targeting new enough OS
3967 if ( fMakeCompressedDyldInfo
) {
3968 if ( minOS(ld::mac10_9
, ld::iOS_7_0
) ) {
3969 // <rdar://problem/13179029> Allow absolute symbols in export trie for device but not simulator
3970 if ( !fTargetIOSSimulator
)
3971 fAbsoluteSymbols
= true;
3975 // <rdar://problem/12959510> iOS main executables now default to 16KB page size
3976 if ( (fIOSVersionMin
!= ld::iOSVersionUnset
) && (fOutputKind
== Options::kDynamicExecutable
) ) {
3977 // <rdar://problem/13070042> Only third party apps should have 16KB page segments by default
3978 if ( fEncryptable
) {
3979 if ( fSegmentAlignment
== 4096 )
3980 fSegmentAlignment
= 4096*4;
3984 // <rdar://problem/12258065> ARM64 needs 16KB page size for user land code
3985 if ( fArchitecture
== CPU_TYPE_ARM64
) {
3986 if ( fSegmentAlignment
== 4096 ) {
3987 switch ( fOutputKind
) {
3988 case Options::kDynamicExecutable
:
3989 case Options::kDynamicLibrary
:
3990 case Options::kDynamicBundle
:
3991 case Options::kDyld
:
3992 fSegmentAlignment
= 4096*4;
3994 case Options::kStaticExecutable
:
3995 case Options::kKextBundle
:
3996 case Options::kObjectFile
:
3997 case Options::kPreload
:
4003 // <rdar://problem/13624134> linker should not convert dwarf unwind if .o file has compact unwind section
4004 switch ( fOutputKind
) {
4005 case Options::kDynamicExecutable
:
4006 case Options::kDynamicLibrary
:
4007 case Options::kDynamicBundle
:
4008 case Options::kDyld
:
4009 if ( fKeepDwarfUnwindForcedOn
) {
4010 fKeepDwarfUnwind
= true;
4012 else if ( fKeepDwarfUnwindForcedOff
) {
4013 fKeepDwarfUnwind
= false;
4016 if ( minOS(ld::mac10_9
, ld::iOS_7_0
) )
4017 fKeepDwarfUnwind
= false;
4019 fKeepDwarfUnwind
= true;
4022 case Options::kKextBundle
:
4023 case Options::kStaticExecutable
:
4024 case Options::kObjectFile
:
4025 case Options::kPreload
:
4026 fKeepDwarfUnwind
= true;
4032 void Options::checkIllegalOptionCombinations()
4034 // check -undefined setting
4035 switch ( fUndefinedTreatment
) {
4036 case kUndefinedError
:
4037 case kUndefinedDynamicLookup
:
4040 case kUndefinedWarning
:
4041 case kUndefinedSuppress
:
4042 // requires flat namespace
4043 if ( fNameSpace
== kTwoLevelNameSpace
)
4044 throw "can't use -undefined warning or suppress with -twolevel_namespace";
4048 // unify -sub_umbrella with dylibs
4049 for (std::vector
<const char*>::iterator it
= fSubUmbellas
.begin(); it
!= fSubUmbellas
.end(); it
++) {
4050 const char* subUmbrella
= *it
;
4052 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
4053 Options::FileInfo
& info
= *fit
;
4054 const char* lastSlash
= strrchr(info
.path
, '/');
4055 if ( lastSlash
== NULL
)
4056 lastSlash
= info
.path
- 1;
4057 if ( strcmp(&lastSlash
[1], subUmbrella
) == 0 ) {
4058 info
.options
.fReExport
= true;
4060 fLinkSnapshot
.recordSubUmbrella(info
.path
);
4065 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella
);
4068 // unify -sub_library with dylibs
4069 for (std::vector
<const char*>::iterator it
= fSubLibraries
.begin(); it
!= fSubLibraries
.end(); it
++) {
4070 const char* subLibrary
= *it
;
4072 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
4073 Options::FileInfo
& info
= *fit
;
4074 const char* lastSlash
= strrchr(info
.path
, '/');
4075 if ( lastSlash
== NULL
)
4076 lastSlash
= info
.path
- 1;
4077 const char* dot
= strchr(&lastSlash
[1], '.');
4079 dot
= &lastSlash
[strlen(lastSlash
)];
4080 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
4081 info
.options
.fReExport
= true;
4083 fLinkSnapshot
.recordSubLibrary(info
.path
);
4088 warning("-sub_library %s does not match a supplied dylib", subLibrary
);
4091 // sync reader options
4092 if ( fNameSpace
!= kTwoLevelNameSpace
)
4093 fFlatNamespace
= true;
4095 // check -stack_addr
4096 if ( fStackAddr
!= 0 ) {
4097 switch (fArchitecture
) {
4100 if ( fStackAddr
> 0xFFFFFFFF )
4101 throw "-stack_addr must be < 4G for 32-bit processes";
4103 case CPU_TYPE_X86_64
:
4104 case CPU_TYPE_ARM64
:
4107 if ( (fStackAddr
& -4096) != fStackAddr
)
4108 throw "-stack_addr must be multiples of 4K";
4109 if ( fStackSize
== 0 )
4110 throw "-stack_addr must be used with -stack_size";
4113 // check -stack_size
4114 if ( fStackSize
!= 0 ) {
4115 switch (fArchitecture
) {
4117 if ( fStackSize
> 0xFFFFFFFF )
4118 throw "-stack_size must be < 4G for 32-bit processes";
4119 if ( fStackAddr
== 0 ) {
4120 fStackAddr
= 0xC0000000;
4122 if ( (fStackAddr
> 0xB0000000) && ((fStackAddr
-fStackSize
) < 0xB0000000) )
4123 warning("custom stack placement overlaps and will disable shared region");
4126 if ( fStackSize
> 0x2F000000 )
4127 throw "-stack_size must be < 752MB";
4128 if ( fStackAddr
== 0 )
4129 fStackAddr
= 0x2F000000;
4130 if ( fStackAddr
> 0x30000000)
4131 throw "-stack_addr must be < 0x30000000 for arm";
4133 case CPU_TYPE_X86_64
:
4134 if ( fStackAddr
== 0 ) {
4135 fStackAddr
= 0x00007FFF5C000000LL
;
4138 case CPU_TYPE_ARM64
:
4139 if ( fStackSize
> 0x20000000 )
4140 throw "-stack_size must be < 512MB";
4141 if ( fStackAddr
== 0 ) {
4142 fStackAddr
= 0x120000000;
4146 if ( (fStackSize
& -4096) != fStackSize
)
4147 throw "-stack_size must be multiples of 4K";
4148 switch ( fOutputKind
) {
4149 case Options::kDynamicExecutable
:
4150 case Options::kStaticExecutable
:
4151 // custom stack size only legal when building main executable
4153 case Options::kDynamicLibrary
:
4154 case Options::kDynamicBundle
:
4155 case Options::kObjectFile
:
4156 case Options::kDyld
:
4157 case Options::kPreload
:
4158 case Options::kKextBundle
:
4159 throw "-stack_size option can only be used when linking a main executable";
4161 if ( fStackSize
> fStackAddr
)
4162 throwf("-stack_size (0x%08llX) must be smaller than -stack_addr (0x%08llX)", fStackSize
, fStackAddr
);
4165 // check that -allow_stack_execute is only used with main executables
4166 if ( fExecutableStack
) {
4167 switch ( fOutputKind
) {
4168 case Options::kDynamicExecutable
:
4169 case Options::kStaticExecutable
:
4170 // -allow_stack_execute size only legal when building main executable
4172 case Options::kDynamicLibrary
:
4173 case Options::kDynamicBundle
:
4174 case Options::kObjectFile
:
4175 case Options::kDyld
:
4176 case Options::kPreload
:
4177 case Options::kKextBundle
:
4178 throw "-allow_stack_execute option can only be used when linking a main executable";
4182 // check that -allow_heap_execute is only used with i386 main executables
4183 if ( fDisableNonExecutableHeap
) {
4184 if ( fArchitecture
!= CPU_TYPE_I386
)
4185 throw "-allow_heap_execute option can only be used when linking for i386";
4186 switch ( fOutputKind
) {
4187 case Options::kDynamicExecutable
:
4188 // -allow_heap_execute only legal when building main executable
4190 case Options::kStaticExecutable
:
4191 case Options::kDynamicLibrary
:
4192 case Options::kDynamicBundle
:
4193 case Options::kObjectFile
:
4194 case Options::kDyld
:
4195 case Options::kPreload
:
4196 case Options::kKextBundle
:
4197 throw "-allow_heap_execute option can only be used when linking a main executable";
4201 // check -client_name is only used when making a bundle or main executable
4202 if ( fClientName
!= NULL
) {
4203 switch ( fOutputKind
) {
4204 case Options::kDynamicExecutable
:
4205 case Options::kDynamicBundle
:
4207 case Options::kStaticExecutable
:
4208 case Options::kDynamicLibrary
:
4209 case Options::kObjectFile
:
4210 case Options::kDyld
:
4211 case Options::kPreload
:
4212 case Options::kKextBundle
:
4213 throw "-client_name can only be used with -bundle";
4217 // check -init is only used when building a dylib
4218 if ( (fInitFunctionName
!= NULL
) && (fOutputKind
!= Options::kDynamicLibrary
) )
4219 throw "-init can only be used with -dynamiclib";
4221 // check -bundle_loader only used with -bundle
4222 if ( (fBundleLoader
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
4223 throw "-bundle_loader can only be used with -bundle";
4225 // check -dtrace not used with -r
4226 if ( (fDtraceScriptName
!= NULL
) && (fOutputKind
== Options::kObjectFile
) )
4227 throw "-dtrace can only be used when creating final linked images";
4229 // check -d can only be used with -r
4230 if ( fMakeTentativeDefinitionsReal
&& (fOutputKind
!= Options::kObjectFile
) )
4231 throw "-d can only be used with -r";
4233 // check that -root_safe is not used with -r
4234 if ( fRootSafe
&& (fOutputKind
== Options::kObjectFile
) )
4235 throw "-root_safe cannot be used with -r";
4237 // check that -setuid_safe is not used with -r
4238 if ( fSetuidSafe
&& (fOutputKind
== Options::kObjectFile
) )
4239 throw "-setuid_safe cannot be used with -r";
4241 // <rdar://problem/12781832> compiler driver no longer uses -objc_abi_version, it uses -ios_simulator_version_min instead
4242 if ( !fObjCABIVersion1Override
&& !fObjCABIVersion2Override
&& fTargetIOSSimulator
)
4243 fObjCABIVersion2Override
= true;
4245 // rdar://problem/4718189 map ObjC class names to new runtime names
4246 bool alterObjC1ClassNamesToObjC2
= false;
4247 switch (fArchitecture
) {
4249 // i386 only uses new symbols when using objc2 ABI
4250 if ( fObjCABIVersion2Override
)
4251 alterObjC1ClassNamesToObjC2
= true;
4253 case CPU_TYPE_X86_64
:
4255 case CPU_TYPE_ARM64
:
4256 alterObjC1ClassNamesToObjC2
= true;
4260 // make sure all required exported symbols exist
4261 std::vector
<const char*> impliedExports
;
4262 for (NameSet::iterator it
=fExportSymbols
.regularBegin(); it
!= fExportSymbols
.regularEnd(); ++it
) {
4263 const char* name
= *it
;
4264 const int len
= strlen(name
);
4265 if ( (strcmp(&name
[len
-3], ".eh") == 0) || (strncmp(name
, ".objc_category_name_", 20) == 0) ) {
4266 // never export .eh symbols
4267 warning("ignoring %s in export list", name
);
4269 else if ( (fArchitecture
== CPU_TYPE_I386
) && !fObjCABIVersion2Override
&& (strncmp(name
, "_OBJC_CLASS_$", 13) == 0) ) {
4270 warning("ignoring Objc2 Class symbol %s in i386 export list", name
);
4271 fRemovedExports
.insert(name
);
4273 else if ( alterObjC1ClassNamesToObjC2
&& (strncmp(name
, ".objc_class_name_", 17) == 0) ) {
4274 // linking ObjC2 ABI, but have ObjC1 ABI name in export list. Change it to intended name
4275 fRemovedExports
.insert(name
);
4277 asprintf(&temp
, "_OBJC_CLASS_$_%s", &name
[17]);
4278 impliedExports
.push_back(temp
);
4279 asprintf(&temp
, "_OBJC_METACLASS_$_%s", &name
[17]);
4280 impliedExports
.push_back(temp
);
4283 fInitialUndefines
.push_back(name
);
4286 fExportSymbols
.remove(fRemovedExports
);
4287 for (std::vector
<const char*>::iterator it
=impliedExports
.begin(); it
!= impliedExports
.end(); ++it
) {
4288 const char* name
= *it
;
4289 fExportSymbols
.insert(name
);
4290 fInitialUndefines
.push_back(name
);
4293 // make sure all required re-exported symbols exist
4294 for (NameSet::iterator it
=fReExportSymbols
.regularBegin(); it
!= fReExportSymbols
.regularEnd(); ++it
) {
4295 fInitialUndefines
.push_back(*it
);
4298 // make sure that -init symbol exists
4299 if ( fInitFunctionName
!= NULL
)
4300 fInitialUndefines
.push_back(fInitFunctionName
);
4302 // make sure that entry symbol exists
4303 switch ( fOutputKind
) {
4304 case Options::kDynamicExecutable
:
4305 case Options::kStaticExecutable
:
4306 case Options::kDyld
:
4307 case Options::kPreload
:
4308 fInitialUndefines
.push_back(fEntryName
);
4310 case Options::kDynamicLibrary
:
4311 case Options::kDynamicBundle
:
4312 case Options::kObjectFile
:
4313 case Options::kKextBundle
:
4317 // make sure every alias base exists
4318 for (std::vector
<AliasPair
>::iterator it
=fAliases
.begin(); it
!= fAliases
.end(); ++it
) {
4319 fInitialUndefines
.push_back(it
->realName
);
4322 // check custom segments
4323 if ( fCustomSegmentAddresses
.size() != 0 ) {
4324 // verify no segment is in zero page
4325 if ( fZeroPageSize
!= ULLONG_MAX
) {
4326 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
4327 if ( it
->address
< fZeroPageSize
)
4328 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it
->name
, it
->address
);
4331 // verify no duplicates
4332 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
4333 for (std::vector
<SegmentStart
>::iterator it2
= fCustomSegmentAddresses
.begin(); it2
!= fCustomSegmentAddresses
.end(); ++it2
) {
4334 if ( (it
->address
== it2
->address
) && (it
!= it2
) )
4335 throwf("duplicate -segaddr addresses for %s and %s", it
->name
, it2
->name
);
4337 // a custom segment address of zero will disable the use of a zero page
4338 if ( it
->address
== 0 )
4343 if ( fZeroPageSize
== ULLONG_MAX
) {
4344 // zero page size not specified on command line, set default
4345 switch (fArchitecture
) {
4348 // first 4KB for 32-bit architectures
4349 fZeroPageSize
= 0x1000;
4351 case CPU_TYPE_ARM64
:
4352 case CPU_TYPE_X86_64
:
4353 // first 4GB for x86_64 on all OS's
4354 fZeroPageSize
= 0x100000000ULL
;
4357 // if -arch not used, default to 4K zero-page
4358 fZeroPageSize
= 0x1000;
4362 switch ( fOutputKind
) {
4363 case Options::kDynamicExecutable
:
4364 case Options::kStaticExecutable
:
4365 // -pagezero_size size only legal when building main executable
4367 case Options::kDynamicLibrary
:
4368 case Options::kDynamicBundle
:
4369 case Options::kObjectFile
:
4370 case Options::kDyld
:
4371 case Options::kPreload
:
4372 case Options::kKextBundle
:
4373 if ( fZeroPageSize
!= 0 )
4374 throw "-pagezero_size option can only be used when linking a main executable";
4378 // if main executable with custom base address, model zero page as custom segment
4379 if ( (fOutputKind
== Options::kDynamicExecutable
) && (fBaseAddress
!= 0) && (fZeroPageSize
!= 0) ) {
4381 seg
.name
= "__PAGEZERO";
4383 fCustomSegmentAddresses
.push_back(seg
);
4386 // -dead_strip and -r are incompatible
4387 if ( fDeadStrip
&& (fOutputKind
== Options::kObjectFile
) )
4388 throw "-r and -dead_strip cannot be used together";
4390 // can't use -rpath unless targeting 10.5 or later
4391 if ( fRPaths
.size() > 0 ) {
4392 if ( !minOS(ld::mac10_5
, ld::iOS_2_0
) )
4393 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
4394 switch ( fOutputKind
) {
4395 case Options::kDynamicExecutable
:
4396 case Options::kDynamicLibrary
:
4397 case Options::kDynamicBundle
:
4399 case Options::kStaticExecutable
:
4400 case Options::kObjectFile
:
4401 case Options::kDyld
:
4402 case Options::kPreload
:
4403 case Options::kKextBundle
:
4404 throw "-rpath can only be used when creating a dynamic final linked image";
4408 if ( fPositionIndependentExecutable
) {
4409 switch ( fOutputKind
) {
4410 case Options::kDynamicExecutable
:
4411 // check -pie is only used when building a dynamic main executable for 10.5
4412 if ( !minOS(ld::mac10_5
, ld::iOS_4_2
) ) {
4413 if ( fIOSVersionMin
== ld::iOSVersionUnset
)
4414 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
4416 throw "-pie can only be used when targeting iOS 4.2 or later";
4419 case Options::kStaticExecutable
:
4420 case Options::kPreload
:
4421 // -pie is ok with -static or -preload
4423 case Options::kDynamicLibrary
:
4424 case Options::kDynamicBundle
:
4425 warning("-pie being ignored. It is only used when linking a main executable");
4426 fPositionIndependentExecutable
= false;
4428 case Options::kObjectFile
:
4429 case Options::kDyld
:
4430 case Options::kKextBundle
:
4431 throw "-pie can only be used when linking a main executable";
4435 // check -read_only_relocs is not used with x86_64
4436 if ( fAllowTextRelocs
) {
4437 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
!= kKextBundle
) ) {
4438 warning("-read_only_relocs cannot be used with x86_64");
4439 fAllowTextRelocs
= false;
4443 // check -mark_auto_dead_strip is only used with dylibs
4444 if ( fMarkDeadStrippableDylib
) {
4445 if ( fOutputKind
!= Options::kDynamicLibrary
) {
4446 warning("-mark_auto_dead_strip can only be used when creating a dylib");
4447 fMarkDeadStrippableDylib
= false;
4451 // -force_cpusubtype_ALL is not supported for ARM
4452 if ( fForceSubtypeAll
) {
4453 if ( fArchitecture
== CPU_TYPE_ARM
) {
4454 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
4458 // -reexported_symbols_list can only be used with -dynamiclib
4459 if ( !fReExportSymbols
.empty() ) {
4460 if ( fOutputKind
!= Options::kDynamicLibrary
)
4461 throw "-reexported_symbols_list can only used used when created dynamic libraries";
4462 if ( !minOS(ld::mac10_7
, ld::iOS_4_2
) )
4463 throw "targeted OS version does not support -reexported_symbols_list";
4466 // -dyld_env can only be used with main executables
4467 if ( (fOutputKind
!= Options::kDynamicExecutable
) && (fDyldEnvironExtras
.size() != 0) )
4468 throw "-dyld_env can only used used when created main executables";
4472 void Options::checkForClassic(int argc
, const char* argv
[])
4475 bool archFound
= false;
4476 bool staticFound
= false;
4477 bool dtraceFound
= false;
4478 bool kextFound
= false;
4479 bool rFound
= false;
4480 bool creatingMachKernel
= false;
4481 bool newLinker
= false;
4483 // build command line buffer in case ld crashes
4484 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
4485 CRSetCrashLogMessage(crashreporterBuffer
);
4487 const char* srcRoot
= getenv("SRCROOT");
4488 if ( srcRoot
!= NULL
) {
4489 strlcpy(crashreporterBuffer
, "SRCROOT=", crashreporterBufferSize
);
4490 strlcat(crashreporterBuffer
, srcRoot
, crashreporterBufferSize
);
4491 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
4494 strlcat(crashreporterBuffer
, LD_VERS
, crashreporterBufferSize
);
4495 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
4497 strlcat(crashreporterBuffer
, "ld ", crashreporterBufferSize
);
4498 for(int i
=1; i
< argc
; ++i
) {
4499 strlcat(crashreporterBuffer
, argv
[i
], crashreporterBufferSize
);
4500 strlcat(crashreporterBuffer
, " ", crashreporterBufferSize
);
4503 for(int i
=0; i
< argc
; ++i
) {
4504 const char* arg
= argv
[i
];
4505 if ( arg
[0] == '-' ) {
4506 if ( strcmp(arg
, "-arch") == 0 ) {
4507 parseArch(argv
[++i
]);
4510 else if ( strcmp(arg
, "-static") == 0 ) {
4513 else if ( strcmp(arg
, "-kext") == 0 ) {
4516 else if ( strcmp(arg
, "-dtrace") == 0 ) {
4519 else if ( strcmp(arg
, "-r") == 0 ) {
4522 else if ( strcmp(arg
, "-new_linker") == 0 ) {
4525 else if ( strcmp(arg
, "-classic_linker") == 0 ) {
4526 // ld_classic does not understand this option, so remove it
4527 for(int j
=i
; j
< argc
; ++j
)
4528 argv
[j
] = argv
[j
+1];
4529 warning("using ld_classic");
4530 this->gotoClassicLinker(argc
-1, argv
);
4532 else if ( strcmp(arg
, "-o") == 0 ) {
4533 const char* outfile
= argv
[++i
];
4534 if ( (outfile
!= NULL
) && (strstr(outfile
, "/mach_kernel") != NULL
) )
4535 creatingMachKernel
= true;
4541 void Options::gotoClassicLinker(int argc
, const char* argv
[])
4543 argv
[0] = "ld_classic";
4544 // ld_classic does not support -iphoneos_version_min, so change
4545 for(int j
=0; j
< argc
; ++j
) {
4546 if ( (strcmp(argv
[j
], "-iphoneos_version_min") == 0) || (strcmp(argv
[j
], "-ios_version_min") == 0) ) {
4547 argv
[j
] = "-macosx_version_min";
4553 // ld classic does not understand -kext (change to -static -r)
4554 for(int j
=0; j
< argc
; ++j
) {
4555 if ( strcmp(argv
[j
], "-kext") == 0)
4557 else if ( strcmp(argv
[j
], "-dynamic") == 0)
4558 argv
[j
] = "-static";
4560 // ld classic does not understand -demangle
4561 for(int j
=0; j
< argc
; ++j
) {
4562 if ( strcmp(argv
[j
], "-demangle") == 0)
4563 argv
[j
] = "-noprebind";
4565 // in -v mode, print command line passed to ld_classic
4566 for(int i
=0; i
< argc
; ++i
) {
4567 if ( strcmp(argv
[i
], "-v") == 0 ) {
4568 for(int j
=0; j
< argc
; ++j
)
4569 printf("%s ", argv
[j
]);
4574 char rawPath
[PATH_MAX
];
4575 char path
[PATH_MAX
];
4576 uint32_t bufSize
= PATH_MAX
;
4577 if ( _NSGetExecutablePath(rawPath
, &bufSize
) != -1 ) {
4578 if ( realpath(rawPath
, path
) != NULL
) {
4579 char* lastSlash
= strrchr(path
, '/');
4580 if ( lastSlash
!= NULL
) {
4581 strcpy(lastSlash
+1, "ld_classic");
4583 execvp(path
, (char**)argv
);
4587 // in case of error in above, try searching for ld_classic via PATH
4588 execvp(argv
[0], (char**)argv
);
4589 fprintf(stderr
, "can't exec ld_classic\n");
4594 // Note, returned string buffer is own by this function.
4595 // It should not be freed
4596 // It will be reused, so clients need to strdup() if they want
4597 // to use it long term.
4598 const char* Options::demangleSymbol(const char* sym
) const
4600 // only try to demangle symbols if -demangle on command line
4604 // only try to demangle symbols that look like C++ symbols
4605 if ( strncmp(sym
, "__Z", 3) != 0 )
4608 static size_t size
= 1024;
4609 static char* buff
= (char*)malloc(size
);
4612 char* result
= abi::__cxa_demangle(&sym
[1], buff
, &size
, &status
);
4613 if ( result
!= NULL
) {
4614 // if demangling successful, keep buffer for next demangle
4622 void Options::dumpDependency(uint8_t opcode
, const char* path
) const
4624 if ( !this->dumpDependencyInfo() )
4627 // one time open() of -dependency_info file
4628 if ( fDependencyFileDescriptor
== -1 ) {
4629 fDependencyFileDescriptor
= open(this->dependencyInfoPath(), O_WRONLY
| O_TRUNC
| O_CREAT
, 0666);
4630 if ( fDependencyFileDescriptor
== -1 )
4631 throwf("Could not open or create -dependency_info file: %s", this->dependencyInfoPath());
4634 uint8_t version
= depLinkerVersion
;
4635 if ( write(fDependencyFileDescriptor
, &version
, 1) == -1 )
4636 throwf("write() to -dependency_info failed, errno=%d", errno
);
4637 extern const char ldVersionString
[];
4638 if ( write(fDependencyFileDescriptor
, ldVersionString
, strlen(ldVersionString
)+1) == -1 )
4639 throwf("write() to -dependency_info failed, errno=%d", errno
);
4642 char realPath
[PATH_MAX
];
4643 if ( path
[0] != '/' ) {
4644 if ( realpath(path
, realPath
) != NULL
) {
4649 if ( write(fDependencyFileDescriptor
, &opcode
, 1) == -1 )
4650 throwf("write() to -dependency_info failed, errno=%d", errno
);
4651 if ( write(fDependencyFileDescriptor
, path
, strlen(path
)+1) == -1 )
4652 throwf("write() to -dependency_info failed, errno=%d", errno
);
4654 //fprintf(stderr, "0x%02X %s\n", opcode, path);