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
);
107 bool Options::FileInfo::checkFileExists(const char *p
)
109 struct stat statBuffer
;
110 if (p
== NULL
) p
= path
;
111 if ( stat(p
, &statBuffer
) == 0 ) {
112 if (p
!= path
) path
= strdup(p
);
113 fileLen
= statBuffer
.st_size
;
114 modTime
= statBuffer
.st_mtime
;
120 Options::Options(int argc
, const char* argv
[])
121 : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0), fArchitectureName("unknown"), fOutputKind(kDynamicExecutable
),
122 fHasPreferredSubType(false), fArchSupportsThumb2(false), fPrebind(false), fBindAtLoad(false), fKeepPrivateExterns(false),
123 fNeedsModuleTable(false), fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false),
124 fInterposeMode(kInterposeNone
), fDeadStrip(false), fNameSpace(kTwoLevelNameSpace
),
125 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL
), fFinalName(NULL
), fEntryName("start"),
126 fBaseAddress(0), fMaxAddress(0x7FFFFFFFFFFFFFFFLL
),
127 fBaseWritableAddress(0), fSplitSegs(false),
128 fExportMode(kExportDefault
), fLibrarySearchMode(kSearchDylibAndArchiveInEachDir
),
129 fUndefinedTreatment(kUndefinedError
), fMessagesPrefixedWithArchitecture(true),
130 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak
),
132 fUmbrellaName(NULL
), fInitFunctionName(NULL
), fDotOutputFile(NULL
), fExecutablePath(NULL
),
133 fBundleLoader(NULL
), fDtraceScriptName(NULL
), fSegAddrTablePath(NULL
), fMapPath(NULL
),
134 fDyldInstallPath("/usr/lib/dyld"), fTempLtoObjectPath(NULL
), fOverridePathlibLTO(NULL
),
135 fZeroPageSize(ULLONG_MAX
), fStackSize(0), fStackAddr(0), fSourceVersion(0), fSDKVersion(0), fExecutableStack(false),
136 fNonExecutableHeap(false), fDisableNonExecutableHeap(false),
137 fMinimumHeaderPad(32), fSegmentAlignment(4096),
138 fCommonsMode(kCommonsIgnoreDylibs
), fUUIDMode(kUUIDContent
), fLocalSymbolHandling(kLocalSymbolsAll
), fWarnCommons(false),
139 fVerbose(false), fKeepRelocations(false), fWarnStabs(false),
140 fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
141 fSharedRegionEligible(false), fPrintOrderFileStatistics(false),
142 fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), fPIEOnCommandLine(false),
143 fDisablePositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
144 fDeadStripDylibs(false), fAllowTextRelocs(false), fWarnTextRelocs(false), fKextsUseStubs(false),
145 fUsingLazyDylibLinking(false), fEncryptable(true),
146 fOrderData(true), fMarkDeadStrippableDylib(false),
147 fMakeCompressedDyldInfo(true), fMakeCompressedDyldInfoForceOff(false), fNoEHLabels(false),
148 fAllowCpuSubtypeMismatches(false), fUseSimplifiedDylibReExports(false),
149 fObjCABIVersion2Override(false), fObjCABIVersion1Override(false), fCanUseUpwardDylib(false),
150 fFullyLoadArchives(false), fLoadAllObjcObjectsFromArchives(false), fFlatNamespace(false),
151 fLinkingMainExecutable(false), fForFinalLinkedImage(false), fForStatic(false),
152 fForDyld(false), fMakeTentativeDefinitionsReal(false), fWhyLoad(false), fRootSafe(false),
153 fSetuidSafe(false), fImplicitlyLinkPublicDylibs(true), fAddCompactUnwindEncoding(true),
154 fWarnCompactUnwind(false), fRemoveDwarfUnwindIfCompactExists(false),
155 fAutoOrderInitializers(true), fOptimizeZeroFill(true), fMergeZeroFill(false), fLogObjectFiles(false),
156 fLogAllFiles(false), fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false),
157 fOutputSlidable(false), fWarnWeakExports(false),
158 fObjcGcCompaction(false), fObjCGc(false), fObjCGcOnly(false),
159 fDemangle(false), fTLVSupport(false),
160 fVersionLoadCommand(false), fVersionLoadCommandForcedOn(false),
161 fVersionLoadCommandForcedOff(false), fFunctionStartsLoadCommand(false),
162 fFunctionStartsForcedOn(false), fFunctionStartsForcedOff(false),
163 fDataInCodeInfoLoadCommand(false), fDataInCodeInfoLoadCommandForcedOn(false), fDataInCodeInfoLoadCommandForcedOff(false),
164 fCanReExportSymbols(false), fObjcCategoryMerging(true), fPageAlignDataAtoms(false),
165 fNeedsThreadLoadCommand(false), fEntryPointLoadCommand(false),
166 fEntryPointLoadCommandForceOn(false), fEntryPointLoadCommandForceOff(false),
167 fSourceVersionLoadCommand(false),
168 fSourceVersionLoadCommandForceOn(false), fSourceVersionLoadCommandForceOff(false),
169 fDependentDRInfo(false), fDependentDRInfoForcedOn(false), fDependentDRInfoForcedOff(false),
170 fDebugInfoStripping(kDebugInfoMinimal
), fTraceOutputFile(NULL
),
171 fMacVersionMin(ld::macVersionUnset
), fIOSVersionMin(ld::iOSVersionUnset
),
172 fSaveTempFiles(false), fSnapshotRequested(false), fPipelineFifo(NULL
)
174 this->checkForClassic(argc
, argv
);
175 this->parsePreCommandLineEnvironmentSettings();
176 this->parse(argc
, argv
);
177 this->parsePostCommandLineEnvironmentSettings();
178 this->reconfigureDefaults();
179 this->checkIllegalOptionCombinations();
186 bool Options::errorBecauseOfWarnings() const
188 return (sFatalWarnings
&& (sWarningsCount
> 0));
192 const char* Options::installPath() const
194 if ( fDylibInstallName
!= NULL
)
195 return fDylibInstallName
;
196 else if ( fFinalName
!= NULL
)
203 bool Options::interposable(const char* name
) const
205 switch ( fInterposeMode
) {
208 case kInterposeAllExternal
:
211 return fInterposeList
.contains(name
);
213 throw "internal error";
217 bool Options::printWhyLive(const char* symbolName
) const
219 return ( fWhyLive
.find(symbolName
) != fWhyLive
.end() );
223 const char* Options::dotOutputFile()
225 return fDotOutputFile
;
229 bool Options::hasWildCardExportRestrictList() const
231 // has -exported_symbols_list which contains some wildcards
232 return ((fExportMode
== kExportSome
) && fExportSymbols
.hasWildCards());
235 bool Options::hasWeakBitTweaks() const
237 // has -exported_symbols_list which contains some wildcards
238 return (!fForceWeakSymbols
.empty() || !fForceNotWeakSymbols
.empty());
241 bool Options::allGlobalsAreDeadStripRoots() const
243 // -exported_symbols_list means globals are not exported by default
244 if ( fExportMode
== kExportSome
)
247 switch ( fOutputKind
) {
248 case Options::kDynamicExecutable
:
249 case Options::kStaticExecutable
:
250 case Options::kPreload
:
251 // by default unused globals in a main executable are stripped
253 case Options::kDynamicLibrary
:
254 case Options::kDynamicBundle
:
255 case Options::kObjectFile
:
257 case Options::kKextBundle
:
264 bool Options::keepRelocations()
266 return fKeepRelocations
;
269 bool Options::warnStabs()
274 const char* Options::executablePath()
276 return fExecutablePath
;
280 uint32_t Options::initialSegProtection(const char* segName
) const
282 for(std::vector
<Options::SegmentProtect
>::const_iterator it
= fCustomSegmentProtections
.begin(); it
!= fCustomSegmentProtections
.end(); ++it
) {
283 if ( strcmp(it
->name
, segName
) == 0 ) {
287 if ( strcmp(segName
, "__PAGEZERO") == 0 ) {
290 else if ( strcmp(segName
, "__TEXT") == 0 ) {
291 return VM_PROT_READ
| VM_PROT_EXECUTE
;
293 else if ( strcmp(segName
, "__LINKEDIT") == 0 ) {
297 // all others default to read-write
298 return VM_PROT_READ
| VM_PROT_WRITE
;
301 uint32_t Options::maxSegProtection(const char* segName
) const
303 // iPhoneOS always uses same protection for max and initial
304 // <rdar://problem/11663436> simulator apps need to use MacOSX max-prot
305 if ( (fIOSVersionMin
!= ld::iOSVersionUnset
) && (fArchitecture
!= CPU_TYPE_I386
) )
306 return initialSegProtection(segName
);
308 for(std::vector
<Options::SegmentProtect
>::const_iterator it
= fCustomSegmentProtections
.begin(); it
!= fCustomSegmentProtections
.end(); ++it
) {
309 if ( strcmp(it
->name
, segName
) == 0 ) {
313 if ( strcmp(segName
, "__PAGEZERO") == 0 ) {
316 // all others default to all
317 return VM_PROT_READ
| VM_PROT_WRITE
| VM_PROT_EXECUTE
;
320 uint64_t Options::segPageSize(const char* segName
) const
322 for(std::vector
<SegmentSize
>::const_iterator it
=fCustomSegmentSizes
.begin(); it
!= fCustomSegmentSizes
.end(); ++it
) {
323 if ( strcmp(it
->name
, segName
) == 0 )
326 return fSegmentAlignment
;
329 uint64_t Options::customSegmentAddress(const char* segName
) const
331 for(std::vector
<SegmentStart
>::const_iterator it
=fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
332 if ( strcmp(it
->name
, segName
) == 0 )
335 // if custom stack in use, model as segment with custom address
336 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
337 return fStackAddr
- fStackSize
;
341 bool Options::hasCustomSegmentAddress(const char* segName
) const
343 for(std::vector
<SegmentStart
>::const_iterator it
=fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
344 if ( strcmp(it
->name
, segName
) == 0 )
347 // if custom stack in use, model as segment with custom address
348 if ( (fStackSize
!= 0) && (strcmp("__UNIXSTACK", segName
) == 0) )
353 bool Options::hasCustomSectionAlignment(const char* segName
, const char* sectName
) const
355 for (std::vector
<SectionAlignment
>::const_iterator it
= fSectionAlignments
.begin(); it
!= fSectionAlignments
.end(); ++it
) {
356 if ( (strcmp(it
->segmentName
, segName
) == 0) && (strcmp(it
->sectionName
, sectName
) == 0) )
362 uint8_t Options::customSectionAlignment(const char* segName
, const char* sectName
) const
364 for (std::vector
<SectionAlignment
>::const_iterator it
= fSectionAlignments
.begin(); it
!= fSectionAlignments
.end(); ++it
) {
365 if ( (strcmp(it
->segmentName
, segName
) == 0) && (strcmp(it
->sectionName
, sectName
) == 0) )
366 return it
->alignment
;
372 bool Options::hasExportedSymbolOrder()
374 return (fExportSymbolsOrder
.size() > 0);
377 bool Options::exportedSymbolOrder(const char* sym
, unsigned int* order
) const
379 NameToOrder::const_iterator pos
= fExportSymbolsOrder
.find(sym
);
380 if ( pos
!= fExportSymbolsOrder
.end() ) {
381 *order
= pos
->second
;
390 void Options::loadSymbolOrderFile(const char* fileOfExports
, NameToOrder
& orderMapping
)
392 // read in whole file
393 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
395 throwf("can't open -exported_symbols_order file: %s", fileOfExports
);
396 struct stat stat_buf
;
397 ::fstat(fd
, &stat_buf
);
398 char* p
= (char*)malloc(stat_buf
.st_size
);
400 throwf("can't process -exported_symbols_order file: %s", fileOfExports
);
402 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
403 throwf("can't read -exported_symbols_order file: %s", fileOfExports
);
407 // parse into symbols and add to unordered_set
408 unsigned int count
= 0;
409 char * const end
= &p
[stat_buf
.st_size
];
410 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
411 char* symbolStart
= NULL
;
412 for (char* s
= p
; s
< end
; ++s
) {
418 else if ( !isspace(*s
) ) {
424 if ( (*s
== '\n') || (*s
== '\r') ) {
426 // removing any trailing spaces
428 while ( isspace(*last
) ) {
432 orderMapping
[symbolStart
] = ++count
;
438 if ( (*s
== '\n') || (*s
== '\r') )
443 if ( state
== inSymbol
) {
444 warning("missing line-end at end of file \"%s\"", fileOfExports
);
445 int len
= end
-symbolStart
+1;
446 char* temp
= new char[len
];
447 strlcpy(temp
, symbolStart
, len
);
449 // remove any trailing spaces
450 char* last
= &temp
[len
-2];
451 while ( isspace(*last
) ) {
455 orderMapping
[temp
] = ++count
;
458 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
461 bool Options::forceWeak(const char* symbolName
) const
463 return fForceWeakSymbols
.contains(symbolName
);
466 bool Options::forceNotWeak(const char* symbolName
) const
468 return fForceNotWeakSymbols
.contains(symbolName
);
471 bool Options::forceWeakNonWildCard(const char* symbolName
) const
473 return fForceWeakSymbols
.containsNonWildcard(symbolName
);
476 bool Options::forceNotWeakNonWildcard(const char* symbolName
) const
478 return fForceNotWeakSymbols
.containsNonWildcard(symbolName
);
482 bool Options::shouldExport(const char* symbolName
) const
484 switch (fExportMode
) {
486 return fExportSymbols
.contains(symbolName
);
487 case kDontExportSome
:
488 return ! fDontExportSymbols
.contains(symbolName
);
492 throw "internal error";
495 bool Options::shouldReExport(const char* symbolName
) const
497 return fReExportSymbols
.contains(symbolName
);
500 bool Options::keepLocalSymbol(const char* symbolName
) const
502 switch (fLocalSymbolHandling
) {
503 case kLocalSymbolsAll
:
505 case kLocalSymbolsNone
:
507 case kLocalSymbolsSelectiveInclude
:
508 return fLocalSymbolsIncluded
.contains(symbolName
);
509 case kLocalSymbolsSelectiveExclude
:
510 return ! fLocalSymbolsExcluded
.contains(symbolName
);
512 throw "internal error";
515 void Options::setArchitecture(cpu_type_t type
, cpu_subtype_t subtype
)
517 for (const ArchInfo
* t
=archInfoArray
; t
->archName
!= NULL
; ++t
) {
518 if ( (type
== t
->cpuType
) && (subtype
== t
->cpuSubType
) ) {
519 fArchitecture
= type
;
520 fSubArchitecture
= subtype
;
521 fArchitectureName
= t
->archName
;
522 fHasPreferredSubType
= t
->isSubType
;
523 fArchSupportsThumb2
= t
->supportsThumb2
;
526 case CPU_TYPE_X86_64
:
527 if ( (fMacVersionMin
== ld::macVersionUnset
) && (fIOSVersionMin
== ld::iOSVersionUnset
) && (fOutputKind
!= Options::kObjectFile
) ) {
528 #ifdef DEFAULT_MACOSX_MIN_VERSION
529 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION
);
530 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
532 warning("-macosx_version_min not specified, assuming 10.6");
533 fMacVersionMin
= ld::mac10_6
;
536 if ( !fMakeCompressedDyldInfo
&& minOS(ld::mac10_6
, ld::iOS_3_1
) && !fMakeCompressedDyldInfoForceOff
)
537 fMakeCompressedDyldInfo
= true;
540 if ( (fMacVersionMin
== ld::macVersionUnset
) && (fIOSVersionMin
== ld::iOSVersionUnset
) && (fOutputKind
!= Options::kObjectFile
) ) {
541 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
542 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION
);
543 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION
);
544 #elif defined(DEFAULT_MACOSX_MIN_VERSION)
545 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION
);
546 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
548 warning("-macosx_version_min not specified, assuming 10.6");
549 fMacVersionMin
= ld::mac10_6
;
552 if ( !fMakeCompressedDyldInfo
&& minOS(ld::mac10_6
, ld::iOS_3_1
) && !fMakeCompressedDyldInfoForceOff
)
553 fMakeCompressedDyldInfo
= true;
556 fLinkSnapshot
.recordArch(fArchitectureName
);
560 fArchitectureName
= "unknown architecture";
563 void Options::parseArch(const char* arch
)
566 throw "-arch must be followed by an architecture string";
567 for (const ArchInfo
* t
=archInfoArray
; t
->archName
!= NULL
; ++t
) {
568 if ( strcmp(t
->archName
,arch
) == 0 ) {
569 fArchitectureName
= arch
;
570 fArchitecture
= t
->cpuType
;
571 fSubArchitecture
= t
->cpuSubType
;
572 fHasPreferredSubType
= t
->isSubType
;
573 fArchSupportsThumb2
= t
->supportsThumb2
;
577 throwf("unknown/unsupported architecture name for: -arch %s", arch
);
580 bool Options::checkForFile(const char* format
, const char* dir
, const char* rootName
, FileInfo
& result
) const
582 char possiblePath
[strlen(dir
)+strlen(rootName
)+strlen(format
)+8];
583 sprintf(possiblePath
, format
, dir
, rootName
);
584 bool found
= result
.checkFileExists(possiblePath
);
585 if ( fTraceDylibSearching
)
586 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), possiblePath
);
591 Options::FileInfo
Options::findLibrary(const char* rootName
, bool dylibsOnly
)
594 const int rootNameLen
= strlen(rootName
);
595 // if rootName ends in .o there is no .a vs .dylib choice
596 if ( (rootNameLen
> 3) && (strcmp(&rootName
[rootNameLen
-2], ".o") == 0) ) {
597 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
598 it
!= fLibrarySearchPaths
.end();
600 const char* dir
= *it
;
601 if ( checkForFile("%s/%s", dir
, rootName
, result
) )
606 bool lookForDylibs
= ( fOutputKind
!= Options::kDyld
);
607 switch ( fLibrarySearchMode
) {
608 case kSearchAllDirsForDylibsThenAllDirsForArchives
:
609 // first look in all directories for just for dylibs
610 if ( lookForDylibs
) {
611 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
612 it
!= fLibrarySearchPaths
.end();
614 const char* dir
= *it
;
615 if ( checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
618 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
619 it
!= fLibrarySearchPaths
.end();
621 const char* dir
= *it
;
622 if ( checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
626 // next look in all directories for just for archives
628 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
629 it
!= fLibrarySearchPaths
.end();
631 const char* dir
= *it
;
632 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
638 case kSearchDylibAndArchiveInEachDir
:
639 // look in each directory for just for a dylib then for an archive
640 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
641 it
!= fLibrarySearchPaths
.end();
643 const char* dir
= *it
;
644 if ( lookForDylibs
&& checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
646 if ( lookForDylibs
&& checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
648 if ( !dylibsOnly
&& checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
654 throwf("library not found for -l%s", rootName
);
657 Options::FileInfo
Options::findFramework(const char* frameworkName
)
659 if ( frameworkName
== NULL
)
660 throw "-framework missing next argument";
661 char temp
[strlen(frameworkName
)+1];
662 strcpy(temp
, frameworkName
);
663 const char* name
= temp
;
664 const char* suffix
= NULL
;
665 char* comma
= strchr(temp
, ',');
666 if ( comma
!= NULL
) {
670 return findFramework(name
, suffix
);
673 Options::FileInfo
Options::findFramework(const char* rootName
, const char* suffix
)
675 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
676 it
!= fFrameworkSearchPaths
.end();
678 // ??? Shouldn't we be using String here and just initializing it?
679 // ??? Use str.c_str () to pull out the string for the stat call.
680 const char* dir
= *it
;
681 char possiblePath
[PATH_MAX
];
682 strcpy(possiblePath
, dir
);
683 strcat(possiblePath
, "/");
684 strcat(possiblePath
, rootName
);
685 strcat(possiblePath
, ".framework/");
686 strcat(possiblePath
, rootName
);
687 if ( suffix
!= NULL
) {
688 char realPath
[PATH_MAX
];
689 // no symlink in framework to suffix variants, so follow main symlink
690 if ( realpath(possiblePath
, realPath
) != NULL
) {
691 strcpy(possiblePath
, realPath
);
692 strcat(possiblePath
, suffix
);
696 bool found
= result
.checkFileExists(possiblePath
);
697 if ( fTraceDylibSearching
)
698 printf("[Logging for XBS]%sfound framework: '%s'\n",
699 (found
? " " : " not "), possiblePath
);
704 // try without suffix
705 if ( suffix
!= NULL
)
706 return findFramework(rootName
, NULL
);
708 throwf("framework not found %s", rootName
);
711 Options::FileInfo
Options::findFile(const char* path
) const
715 // if absolute path and not a .o file, the use SDK prefix
716 if ( (path
[0] == '/') && (strcmp(&path
[strlen(path
)-2], ".o") != 0) ) {
717 const int pathLen
= strlen(path
);
718 for (std::vector
<const char*>::const_iterator it
= fSDKPaths
.begin(); it
!= fSDKPaths
.end(); it
++) {
719 // ??? Shouldn't we be using String here?
720 const char* sdkPathDir
= *it
;
721 const int sdkPathDirLen
= strlen(sdkPathDir
);
722 char possiblePath
[sdkPathDirLen
+pathLen
+4];
723 strcpy(possiblePath
, sdkPathDir
);
724 if ( possiblePath
[sdkPathDirLen
-1] == '/' )
725 possiblePath
[sdkPathDirLen
-1] = '\0';
726 strcat(possiblePath
, path
);
727 if ( result
.checkFileExists(possiblePath
) ) {
733 if ( result
.checkFileExists(path
) ) {
737 // try @executable_path substitution
738 if ( (strncmp(path
, "@executable_path/", 17) == 0) && (fExecutablePath
!= NULL
) ) {
739 char newPath
[strlen(fExecutablePath
) + strlen(path
)];
740 strcpy(newPath
, fExecutablePath
);
741 char* addPoint
= strrchr(newPath
,'/');
742 if ( addPoint
!= NULL
)
743 strcpy(&addPoint
[1], &path
[17]);
745 strcpy(newPath
, &path
[17]);
746 if ( result
.checkFileExists(newPath
) ) {
752 throwf("file not found: %s", path
);
755 Options::FileInfo
Options::findFileUsingPaths(const char* path
) const
759 const char* lastSlash
= strrchr(path
, '/');
760 const char* leafName
= (lastSlash
== NULL
) ? path
: &lastSlash
[1];
762 // Is this in a framework?
763 // /path/Foo.framework/Foo ==> true (Foo)
764 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
765 // /path/Foo.framework/Resources/Bar ==> false
766 bool isFramework
= false;
767 if ( lastSlash
!= NULL
) {
768 char frameworkDir
[strlen(leafName
) + 20];
769 strcpy(frameworkDir
, "/");
770 strcat(frameworkDir
, leafName
);
771 strcat(frameworkDir
, ".framework/");
772 if ( strstr(path
, frameworkDir
) != NULL
)
776 // These are abbreviated versions of the routines findFramework and findLibrary above
777 // because we already know the final name of the file that we're looking for and so
778 // don't need to try variations, just paths. We do need to add the additional bits
779 // onto the framework path though.
781 for (std::vector
<const char*>::const_iterator it
= fFrameworkSearchPaths
.begin();
782 it
!= fFrameworkSearchPaths
.end();
784 const char* dir
= *it
;
785 char possiblePath
[PATH_MAX
];
786 strcpy(possiblePath
, dir
);
787 strcat(possiblePath
, "/");
788 strcat(possiblePath
, leafName
);
789 strcat(possiblePath
, ".framework");
791 //fprintf(stderr,"Finding Framework: %s/%s, leafName=%s\n", possiblePath, leafName, leafName);
792 if ( checkForFile("%s/%s", possiblePath
, leafName
, result
) )
797 // if this is a .dylib inside a framework, do not search -L paths
798 // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
799 int leafLen
= strlen(leafName
);
800 bool embeddedDylib
= ( (leafLen
> 6)
801 && (strcmp(&leafName
[leafLen
-6], ".dylib") == 0)
802 && (strstr(path
, ".framework/") != NULL
) );
803 if ( !embeddedDylib
) {
804 for (std::vector
<const char*>::const_iterator it
= fLibrarySearchPaths
.begin();
805 it
!= fLibrarySearchPaths
.end();
807 const char* dir
= *it
;
808 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
809 if ( checkForFile("%s/%s", dir
, leafName
, result
) )
815 // If we didn't find it fall back to findFile.
816 return findFile(path
);
820 void Options::parseSegAddrTable(const char* segAddrPath
, const char* installPth
)
822 FILE* file
= fopen(segAddrPath
, "r");
823 if ( file
== NULL
) {
824 warning("-seg_addr_table file cannot be read: %s", segAddrPath
);
829 uint64_t firstColumAddress
= 0;
830 uint64_t secondColumAddress
= 0;
831 bool hasSecondColumn
= false;
832 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
833 path
[PATH_MAX
-1] = '\0';
834 char* eol
= strchr(path
, '\n');
837 // ignore lines not starting with 0x number
838 if ( (path
[0] == '0') && (path
[1] == 'x') ) {
840 firstColumAddress
= strtoull(path
, &p
, 16);
841 while ( isspace(*p
) )
843 // see if second column is a number
844 if ( (p
[0] == '0') && (p
[1] == 'x') ) {
845 secondColumAddress
= strtoull(p
, &p
, 16);
846 hasSecondColumn
= true;
847 while ( isspace(*p
) )
850 while ( isspace(*p
) )
853 // remove any trailing whitespace
854 for(char* end
= eol
-1; (end
> p
) && isspace(*end
); --end
)
856 // see if this line is for the dylib being linked
857 if ( strcmp(p
, installPth
) == 0 ) {
858 fBaseAddress
= firstColumAddress
;
859 if ( hasSecondColumn
) {
860 fBaseWritableAddress
= secondColumAddress
;
863 break; // out of while loop
872 void Options::loadFileList(const char* fileOfPaths
, ld::File::Ordinal baseOrdinal
)
875 const char* comma
= strrchr(fileOfPaths
, ',');
876 const char* prefix
= NULL
;
877 if ( comma
!= NULL
) {
878 // <rdar://problem/5907981> -filelist fails with comma in path
879 file
= fopen(fileOfPaths
, "r");
880 if ( file
== NULL
) {
882 int realFileOfPathsLen
= comma
-fileOfPaths
;
883 char realFileOfPaths
[realFileOfPathsLen
+1];
884 strncpy(realFileOfPaths
,fileOfPaths
, realFileOfPathsLen
);
885 realFileOfPaths
[realFileOfPathsLen
] = '\0';
886 file
= fopen(realFileOfPaths
, "r");
888 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", realFileOfPaths
, errno
, strerror(errno
));
892 file
= fopen(fileOfPaths
, "r");
894 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", fileOfPaths
, errno
, strerror(errno
));
898 ld::File::Ordinal previousOrdinal
= baseOrdinal
;
899 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
900 path
[PATH_MAX
-1] = '\0';
901 char* eol
= strchr(path
, '\n');
904 if ( prefix
!= NULL
) {
905 char builtPath
[strlen(prefix
)+strlen(path
)+2];
906 strcpy(builtPath
, prefix
);
907 strcat(builtPath
, "/");
908 strcat(builtPath
, path
);
909 if (fPipelineFifo
!= NULL
) {
910 FileInfo info
= FileInfo(builtPath
);
911 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
912 previousOrdinal
= info
.ordinal
;
913 info
.fromFileList
= true;
914 fInputFiles
.push_back(info
);
916 FileInfo info
= findFile(builtPath
);
917 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
918 previousOrdinal
= info
.ordinal
;
919 info
.fromFileList
= true;
920 fInputFiles
.push_back(info
);
924 if (fPipelineFifo
!= NULL
) {
925 FileInfo info
= FileInfo(path
);
926 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
927 previousOrdinal
= info
.ordinal
;
928 info
.fromFileList
= true;
929 fInputFiles
.push_back(info
);
931 FileInfo info
= findFile(path
);
932 info
.ordinal
= previousOrdinal
.nextFileListOrdinal();
933 previousOrdinal
= info
.ordinal
;
934 info
.fromFileList
= true;
935 fInputFiles
.push_back(info
);
943 void Options::SetWithWildcards::remove(const NameSet
& toBeRemoved
)
945 for(NameSet::const_iterator it
=toBeRemoved
.begin(); it
!= toBeRemoved
.end(); ++it
) {
946 const char* symbolName
= *it
;
947 NameSet::iterator pos
= fRegular
.find(symbolName
);
948 if ( pos
!= fRegular
.end() )
953 bool Options::SetWithWildcards::hasWildCards(const char* symbol
)
955 // an exported symbol name containing *, ?, or [ requires wildcard matching
956 return ( strpbrk(symbol
, "*?[") != NULL
);
959 void Options::SetWithWildcards::insert(const char* symbol
)
961 if ( hasWildCards(symbol
) )
962 fWildCard
.push_back(symbol
);
964 fRegular
.insert(symbol
);
967 bool Options::SetWithWildcards::contains(const char* symbol
) const
969 // first look at hash table on non-wildcard symbols
970 if ( fRegular
.find(symbol
) != fRegular
.end() )
972 // next walk list of wild card symbols looking for a match
973 for(std::vector
<const char*>::const_iterator it
= fWildCard
.begin(); it
!= fWildCard
.end(); ++it
) {
974 if ( wildCardMatch(*it
, symbol
) )
980 bool Options::SetWithWildcards::containsNonWildcard(const char* symbol
) const
982 // look at hash table on non-wildcard symbols
983 return ( fRegular
.find(symbol
) != fRegular
.end() );
988 bool Options::SetWithWildcards::inCharRange(const char*& p
, unsigned char c
) const
992 while ( *p
!= '\0' ) {
995 // found beginining [ and ending ]
996 unsigned char last
= '\0';
997 for ( const char* s
= b
; s
< e
; ++s
) {
999 unsigned char next
= *(++s
);
1000 if ( (last
<= c
) && (c
<= next
) )
1017 bool Options::SetWithWildcards::wildCardMatch(const char* pattern
, const char* symbol
) const
1019 const char* s
= symbol
;
1020 for (const char* p
= pattern
; *p
!= '\0'; ++p
) {
1025 for (const char* t
= s
; *t
!= '\0'; ++t
) {
1026 if ( wildCardMatch(&p
[1], t
) )
1036 if ( ! inCharRange(p
, *s
) )
1046 return (*s
== '\0');
1050 void Options::loadExportFile(const char* fileOfExports
, const char* option
, SetWithWildcards
& set
)
1052 if ( fileOfExports
== NULL
)
1053 throwf("missing file after %s", option
);
1054 // read in whole file
1055 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
1057 throwf("can't open %s file: %s", option
, fileOfExports
);
1058 struct stat stat_buf
;
1059 ::fstat(fd
, &stat_buf
);
1060 char* p
= (char*)malloc(stat_buf
.st_size
);
1062 throwf("can't process %s file: %s", option
, fileOfExports
);
1064 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1065 throwf("can't read %s file: %s", option
, fileOfExports
);
1069 // parse into symbols and add to unordered_set
1070 char * const end
= &p
[stat_buf
.st_size
];
1071 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1072 char* symbolStart
= NULL
;
1073 for (char* s
= p
; s
< end
; ++s
) {
1079 else if ( !isspace(*s
) ) {
1085 if ( (*s
== '\n') || (*s
== '\r') ) {
1087 // removing any trailing spaces
1089 while ( isspace(*last
) ) {
1093 set
.insert(symbolStart
);
1099 if ( (*s
== '\n') || (*s
== '\r') )
1104 if ( state
== inSymbol
) {
1105 warning("missing line-end at end of file \"%s\"", fileOfExports
);
1106 int len
= end
-symbolStart
+1;
1107 char* temp
= new char[len
];
1108 strlcpy(temp
, symbolStart
, len
);
1110 // remove any trailing spaces
1111 char* last
= &temp
[len
-2];
1112 while ( isspace(*last
) ) {
1119 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
1122 void Options::parseAliasFile(const char* fileOfAliases
)
1124 // read in whole file
1125 int fd
= ::open(fileOfAliases
, O_RDONLY
, 0);
1127 throwf("can't open alias file: %s", fileOfAliases
);
1128 struct stat stat_buf
;
1129 ::fstat(fd
, &stat_buf
);
1130 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1132 throwf("can't process alias file: %s", fileOfAliases
);
1134 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1135 throwf("can't read alias file: %s", fileOfAliases
);
1136 p
[stat_buf
.st_size
] = '\n';
1139 // parse into symbols and add to fAliases
1141 char * const end
= &p
[stat_buf
.st_size
+1];
1142 enum { lineStart
, inRealName
, inBetween
, inAliasName
, inComment
} state
= lineStart
;
1144 for (char* s
= p
; s
< end
; ++s
) {
1150 else if ( !isspace(*s
) ) {
1157 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1161 else if ( isspace(*s
) ) {
1168 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1172 else if ( ! isspace(*s
) ) {
1173 state
= inAliasName
;
1180 // removing any trailing spaces
1182 while ( isspace(*last
) ) {
1186 fAliases
.push_back(pair
);
1189 else if ( *s
== '\n' ) {
1191 // removing any trailing spaces
1193 while ( isspace(*last
) ) {
1197 fAliases
.push_back(pair
);
1208 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
1213 void Options::setUndefinedTreatment(const char* treatment
)
1215 if ( treatment
== NULL
)
1216 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
1218 if ( strcmp(treatment
, "warning") == 0 )
1219 fUndefinedTreatment
= kUndefinedWarning
;
1220 else if ( strcmp(treatment
, "error") == 0 )
1221 fUndefinedTreatment
= kUndefinedError
;
1222 else if ( strcmp(treatment
, "suppress") == 0 )
1223 fUndefinedTreatment
= kUndefinedSuppress
;
1224 else if ( strcmp(treatment
, "dynamic_lookup") == 0 )
1225 fUndefinedTreatment
= kUndefinedDynamicLookup
;
1227 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1230 Options::Treatment
Options::parseTreatment(const char* treatment
)
1232 if ( treatment
== NULL
)
1235 if ( strcmp(treatment
, "warning") == 0 )
1237 else if ( strcmp(treatment
, "error") == 0 )
1239 else if ( strcmp(treatment
, "suppress") == 0 )
1245 void Options::setMacOSXVersionMin(const char* version
)
1247 if ( version
== NULL
)
1248 throw "-macosx_version_min argument missing";
1250 if ( (strncmp(version
, "10.", 3) == 0) && isdigit(version
[3]) ) {
1251 unsigned int minorVersion
= version
[3] - '0';
1252 fMacVersionMin
= (ld::MacVersionMin
)(0x000A0000 | (minorVersion
<< 8));
1255 warning("unknown option to -macosx_version_min, not 10.x");
1259 void Options::setIOSVersionMin(const char* version
)
1261 if ( version
== NULL
)
1262 throw "-ios_version_min argument missing";
1263 if ( ! isdigit(version
[0]) )
1264 throw "-ios_version_min argument is not a number";
1265 if ( version
[1] != '.' )
1266 throw "-ios_version_min argument is missing period as second character";
1267 if ( ! isdigit(version
[2]) )
1268 throw "-ios_version_min argument is not a number";
1270 unsigned int majorVersion
= version
[0] - '0';
1271 unsigned int minorVersion
= version
[2] - '0';
1272 fIOSVersionMin
= (ld::IOSVersionMin
)((majorVersion
<< 16) | (minorVersion
<< 8));
1275 bool Options::minOS(ld::MacVersionMin requiredMacMin
, ld::IOSVersionMin requirediPhoneOSMin
)
1277 if ( fMacVersionMin
!= ld::macVersionUnset
) {
1278 return ( fMacVersionMin
>= requiredMacMin
);
1281 return ( fIOSVersionMin
>= requirediPhoneOSMin
);
1286 void Options::setWeakReferenceMismatchTreatment(const char* treatment
)
1288 if ( treatment
== NULL
)
1289 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1291 if ( strcmp(treatment
, "error") == 0 )
1292 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchError
;
1293 else if ( strcmp(treatment
, "weak") == 0 )
1294 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchWeak
;
1295 else if ( strcmp(treatment
, "non-weak") == 0 )
1296 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchNonWeak
;
1298 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1301 Options::CommonsMode
Options::parseCommonsTreatment(const char* mode
)
1304 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1306 if ( strcmp(mode
, "ignore_dylibs") == 0 )
1307 return kCommonsIgnoreDylibs
;
1308 else if ( strcmp(mode
, "use_dylibs") == 0 )
1309 return kCommonsOverriddenByDylibs
;
1310 else if ( strcmp(mode
, "error") == 0 )
1311 return kCommonsConflictsDylibsError
;
1313 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1316 void Options::addDylibOverride(const char* paths
)
1318 if ( paths
== NULL
)
1319 throw "-dylib_file must followed by two colon separated paths";
1320 const char* colon
= strchr(paths
, ':');
1321 if ( colon
== NULL
)
1322 throw "-dylib_file must followed by two colon separated paths";
1323 int len
= colon
-paths
;
1324 char* target
= new char[len
+2];
1325 strncpy(target
, paths
, len
);
1327 DylibOverride entry
;
1328 entry
.installName
= target
;
1329 entry
.useInstead
= &colon
[1];
1330 fDylibOverrides
.push_back(entry
);
1333 uint64_t Options::parseAddress(const char* addr
)
1336 uint64_t result
= strtoull(addr
, &endptr
, 16);
1340 uint32_t Options::parseProtection(const char* prot
)
1342 uint32_t result
= 0;
1343 for(const char* p
= prot
; *p
!= '\0'; ++p
) {
1344 switch(tolower(*p
)) {
1346 result
|= VM_PROT_READ
;
1349 result
|= VM_PROT_WRITE
;
1352 result
|= VM_PROT_EXECUTE
;
1357 throwf("unknown -segprot lettter in %s", prot
);
1365 // Parses number of form A[.B[.B[.D[.E]]]] into a uint64_t where the bits are a24.b10.c10.d10.e10
1367 uint64_t Options::parseVersionNumber64(const char* versionString
)
1375 a
= strtoul(versionString
, &end
, 10);
1376 if ( *end
== '.' ) {
1377 b
= strtoul(&end
[1], &end
, 10);
1378 if ( *end
== '.' ) {
1379 c
= strtoul(&end
[1], &end
, 10);
1380 if ( *end
== '.' ) {
1381 d
= strtoul(&end
[1], &end
, 10);
1382 if ( *end
== '.' ) {
1383 e
= strtoul(&end
[1], &end
, 10);
1388 if ( (*end
!= '\0') || (a
> 0xFFFFFF) || (b
> 0x3FF) || (c
> 0x3FF) || (d
> 0x3FF) || (e
> 0x3FF) )
1389 throwf("malformed 64-bit a.b.c.d.e version number: %s", versionString
);
1391 return (a
<< 40) | ( b
<< 30 ) | ( c
<< 20 ) | ( d
<< 10 ) | e
;
1395 uint32_t Options::currentVersion32() const
1397 // warn if it does not fit into 32 bit vers number
1398 uint32_t a
= (fDylibCurrentVersion
>> 40) & 0xFFFF;
1399 uint32_t b
= (fDylibCurrentVersion
>> 30) & 0xFF;
1400 uint32_t c
= (fDylibCurrentVersion
>> 20) & 0xFF;
1401 uint64_t rep32
= ((uint64_t)a
<< 40) | ((uint64_t)b
<< 30) | ((uint64_t)c
<< 20);
1402 if ( rep32
!= fDylibCurrentVersion
) {
1403 warning("truncating -current_version to fit in 32-bit space used by old mach-o format");
1404 a
= (fDylibCurrentVersion
>> 40) & 0xFFFFFF;
1407 b
= (fDylibCurrentVersion
>> 30) & 0x3FF;
1410 c
= (fDylibCurrentVersion
>> 20) & 0x3FF;
1414 return (a
<< 16) | ( b
<< 8 ) | c
;
1418 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1420 uint32_t Options::parseVersionNumber32(const char* versionString
)
1426 x
= strtoul(versionString
, &end
, 10);
1427 if ( *end
== '.' ) {
1428 y
= strtoul(&end
[1], &end
, 10);
1429 if ( *end
== '.' ) {
1430 z
= strtoul(&end
[1], &end
, 10);
1433 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
1434 throwf("malformed 32-bit x.y.z version number: %s", versionString
);
1436 return (x
<< 16) | ( y
<< 8 ) | z
;
1439 static const char* cstringSymbolName(const char* orderFileString
)
1442 asprintf(&result
, "cstring=%s", orderFileString
);
1443 // convert escaped characters
1445 for(const char* s
=result
; *s
!= '\0'; ++s
, ++d
) {
1483 // hexadecimal value of char
1487 while ( isxdigit(*s
) ) {
1492 value
+= ((toupper(*s
)-'A') + 10);
1499 if ( isdigit(*s
) ) {
1500 // octal value of char
1502 while ( isdigit(*s
) ) {
1503 value
= (value
<< 3) + (*s
-'0');
1518 void Options::parseOrderFile(const char* path
, bool cstring
)
1520 // order files override auto-ordering
1521 fAutoOrderInitializers
= false;
1523 // read in whole file
1524 int fd
= ::open(path
, O_RDONLY
, 0);
1526 throwf("can't open order file: %s", path
);
1527 struct stat stat_buf
;
1528 ::fstat(fd
, &stat_buf
);
1529 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1531 throwf("can't process order file: %s", path
);
1532 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1533 throwf("can't read order file: %s", path
);
1535 p
[stat_buf
.st_size
] = '\n';
1537 // parse into vector of pairs
1538 char * const end
= &p
[stat_buf
.st_size
+1];
1539 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1540 char* symbolStart
= NULL
;
1541 for (char* s
= p
; s
< end
; ++s
) {
1547 else if ( !isspace(*s
) || cstring
) {
1553 if ( (*s
== '\n') || (!cstring
&& (*s
== '#')) ) {
1554 bool wasComment
= (*s
== '#');
1556 // removing any trailing spaces
1558 while ( isspace(*last
) ) {
1562 // if there is an architecture prefix, only use this symbol it if matches current arch
1563 if ( strncmp(symbolStart
, "ppc:", 4) == 0 ) {
1566 else if ( strncmp(symbolStart
, "ppc64:", 6) == 0 ) {
1569 else if ( strncmp(symbolStart
, "i386:", 5) == 0 ) {
1570 if ( fArchitecture
== CPU_TYPE_I386
)
1571 symbolStart
= &symbolStart
[5];
1575 else if ( strncmp(symbolStart
, "x86_64:", 7) == 0 ) {
1576 if ( fArchitecture
== CPU_TYPE_X86_64
)
1577 symbolStart
= &symbolStart
[7];
1581 else if ( strncmp(symbolStart
, "arm:", 4) == 0 ) {
1582 if ( fArchitecture
== CPU_TYPE_ARM
)
1583 symbolStart
= &symbolStart
[4];
1587 if ( symbolStart
!= NULL
) {
1588 char* objFileName
= NULL
;
1589 char* colon
= strstr(symbolStart
, ".o:");
1590 if ( colon
!= NULL
) {
1592 objFileName
= symbolStart
;
1593 symbolStart
= &colon
[3];
1595 // trim leading spaces
1596 while ( isspace(*symbolStart
) )
1598 Options::OrderedSymbol pair
;
1600 pair
.symbolName
= cstringSymbolName(symbolStart
);
1602 pair
.symbolName
= symbolStart
;
1603 pair
.objectFileName
= objFileName
;
1604 fOrderedSymbols
.push_back(pair
);
1619 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1622 void Options::parseSectionOrderFile(const char* segment
, const char* section
, const char* path
)
1624 if ( (strcmp(section
, "__cstring") == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1625 parseOrderFile(path
, true);
1627 else if ( (strncmp(section
, "__literal",9) == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1628 warning("sorting of __literal[4,8,16] sections not supported");
1631 // ignore section information and append all symbol names to global order file
1632 parseOrderFile(path
, false);
1636 void Options::addSection(const char* segment
, const char* section
, const char* path
)
1638 if ( strlen(segment
) > 16 )
1639 throw "-seccreate segment name max 16 chars";
1640 if ( strlen(section
) > 16 ) {
1641 char* tmp
= strdup(section
);
1643 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section
, tmp
);
1647 // read in whole file
1648 int fd
= ::open(path
, O_RDONLY
, 0);
1650 throwf("can't open -sectcreate file: %s", path
);
1651 struct stat stat_buf
;
1652 ::fstat(fd
, &stat_buf
);
1653 char* p
= (char*)malloc(stat_buf
.st_size
);
1655 throwf("can't process -sectcreate file: %s", path
);
1656 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1657 throwf("can't read -sectcreate file: %s", path
);
1660 // record section to create
1661 ExtraSection info
= { segment
, section
, path
, (uint8_t*)p
, stat_buf
.st_size
};
1662 fExtraSections
.push_back(info
);
1665 void Options::addSectionAlignment(const char* segment
, const char* section
, const char* alignmentStr
)
1667 if ( strlen(segment
) > 16 )
1668 throw "-sectalign segment name max 16 chars";
1669 if ( strlen(section
) > 16 )
1670 throw "-sectalign section name max 16 chars";
1672 // argument to -sectalign is a hexadecimal number
1674 unsigned long value
= strtoul(alignmentStr
, &endptr
, 16);
1675 if ( *endptr
!= '\0')
1676 throw "argument for -sectalign is not a hexadecimal number";
1677 if ( value
> 0x8000 )
1678 throw "argument for -sectalign must be less than or equal to 0x8000";
1680 warning("zero is not a valid -sectalign");
1684 // alignment is power of 2 (e.g. page alignment = 12)
1685 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
1686 if ( (unsigned long)(1 << alignment
) != value
) {
1687 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
1688 segment
, section
, 1 << alignment
);
1691 SectionAlignment info
= { segment
, section
, alignment
};
1692 fSectionAlignments
.push_back(info
);
1695 void Options::addLibrary(const FileInfo
& info
)
1697 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
1698 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
1699 if ( strcmp(info
.path
, fit
->path
) == 0 ) {
1700 // if dylib is specified again but weak, record that it should be weak
1701 if ( info
.options
.fWeakImport
)
1702 fit
->options
.fWeakImport
= true;
1707 fInputFiles
.push_back(info
);
1710 void Options::warnObsolete(const char* arg
)
1712 warning("option %s is obsolete and being ignored", arg
);
1719 // Process all command line arguments.
1721 // The only error checking done here is that each option is valid and if it has arguments
1722 // that they too are valid.
1724 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
1725 // whichever was last on the command line is used.
1727 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
1729 void Options::parse(int argc
, const char* argv
[])
1731 // Store the original args in the link snapshot.
1732 fLinkSnapshot
.recordRawArgs(argc
, argv
);
1734 // pass one builds search list from -L and -F options
1735 this->buildSearchPaths(argc
, argv
);
1737 // reduce re-allocations
1738 fInputFiles
.reserve(32);
1740 // pass two parse all other options
1741 for(int i
=1; i
< argc
; ++i
) {
1742 const char* arg
= argv
[i
];
1744 if ( arg
[0] == '-' ) {
1745 // by default, copy one arg to the snapshot link command, and do no file copying
1746 int snapshotArgIndex
= i
;
1747 int snapshotArgCount
= -1; // -1 means compute count based on change in index
1748 int snapshotFileArgIndex
= -1; // -1 means no data file parameter to arg
1750 // Since we don't care about the files passed, just the option names, we do this here.
1752 fprintf (stderr
, "[Logging ld64 options]\t%s\n", arg
);
1754 if ( (arg
[1] == 'L') || (arg
[1] == 'F') ) {
1755 snapshotArgCount
= 0; // stripped out of link snapshot
1758 // previously handled by buildSearchPaths()
1760 // The one gnu style option we have to keep compatibility
1761 // with gcc. Might as well have the single hyphen one as well.
1762 else if ( (strcmp(arg
, "--help") == 0)
1763 || (strcmp(arg
, "-help") == 0)) {
1764 fprintf (stdout
, "ld64: For information on command line options please use 'man ld'.\n");
1767 else if ( strcmp(arg
, "-arch") == 0 ) {
1768 parseArch(argv
[++i
]);
1770 else if ( strcmp(arg
, "-dynamic") == 0 ) {
1773 else if ( strcmp(arg
, "-static") == 0 ) {
1775 if ( (fOutputKind
!= kObjectFile
) && (fOutputKind
!= kKextBundle
) ) {
1776 fOutputKind
= kStaticExecutable
;
1779 else if ( strcmp(arg
, "-dylib") == 0 ) {
1780 fOutputKind
= kDynamicLibrary
;
1782 else if ( strcmp(arg
, "-bundle") == 0 ) {
1783 fOutputKind
= kDynamicBundle
;
1785 else if ( strcmp(arg
, "-dylinker") == 0 ) {
1786 fOutputKind
= kDyld
;
1788 else if ( strcmp(arg
, "-execute") == 0 ) {
1789 if ( fOutputKind
!= kStaticExecutable
)
1790 fOutputKind
= kDynamicExecutable
;
1792 else if ( strcmp(arg
, "-preload") == 0 ) {
1793 fOutputKind
= kPreload
;
1795 else if ( strcmp(arg
, "-r") == 0 ) {
1796 fOutputKind
= kObjectFile
;
1798 else if ( strcmp(arg
, "-kext") == 0 ) {
1799 fOutputKind
= kKextBundle
;
1801 else if ( strcmp(arg
, "-o") == 0 ) {
1802 snapshotArgCount
= 0;
1803 fOutputFile
= argv
[++i
];
1804 fLinkSnapshot
.setSnapshotName(fOutputFile
);
1806 else if ( strncmp(arg
, "-lazy-l", 7) == 0 ) {
1807 snapshotArgCount
= 0;
1808 FileInfo info
= findLibrary(&arg
[7], true);
1809 info
.options
.fLazyLoad
= true;
1810 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
1812 fUsingLazyDylibLinking
= true;
1814 else if ( strcmp(arg
, "-lto_library") == 0 ) {
1815 snapshotFileArgIndex
= 1;
1816 fOverridePathlibLTO
= argv
[++i
];
1817 if ( fOverridePathlibLTO
== NULL
)
1818 throw "missing argument to -lto_library";
1820 else if ( (arg
[1] == 'l') && (strncmp(arg
,"-lazy_",6) !=0) ) {
1821 snapshotArgCount
= 0;
1822 FileInfo info
= findLibrary(&arg
[2]);
1823 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
1826 // This causes a dylib to be weakly bound at
1827 // link time. This corresponds to weak_import.
1828 else if ( strncmp(arg
, "-weak-l", 7) == 0 ) {
1829 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
1830 snapshotArgCount
= 0;
1831 FileInfo info
= findLibrary(&arg
[7]);
1832 info
.options
.fWeakImport
= true;
1833 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
1836 // Avoid lazy binding.
1837 else if ( strcmp(arg
, "-bind_at_load") == 0 ) {
1840 else if ( strcmp(arg
, "-twolevel_namespace") == 0 ) {
1841 fNameSpace
= kTwoLevelNameSpace
;
1843 else if ( strcmp(arg
, "-flat_namespace") == 0 ) {
1844 fNameSpace
= kFlatNameSpace
;
1846 // Also sets a bit to ensure dyld causes everything
1847 // in the namespace to be flat.
1849 else if ( strcmp(arg
, "-force_flat_namespace") == 0 ) {
1850 fNameSpace
= kForceFlatNameSpace
;
1852 // Similar to --whole-archive.
1853 else if ( strcmp(arg
, "-all_load") == 0 ) {
1854 fFullyLoadArchives
= true;
1856 else if ( strcmp(arg
, "-noall_load") == 0) {
1859 // Similar to -all_load
1860 else if ( strcmp(arg
, "-ObjC") == 0 ) {
1861 fLoadAllObjcObjectsFromArchives
= true;
1863 // Similar to -all_load, but for the following archive only.
1864 else if ( strcmp(arg
, "-force_load") == 0 ) {
1865 FileInfo info
= findFile(argv
[++i
]);
1866 info
.options
.fForceLoad
= true;
1867 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
1870 // Library versioning.
1871 else if ( (strcmp(arg
, "-dylib_compatibility_version") == 0)
1872 || (strcmp(arg
, "-compatibility_version") == 0)) {
1873 const char* vers
= argv
[++i
];
1875 throw "-dylib_compatibility_version missing <version>";
1876 fDylibCompatVersion
= parseVersionNumber32(vers
);
1878 else if ( (strcmp(arg
, "-dylib_current_version") == 0)
1879 || (strcmp(arg
, "-current_version") == 0)) {
1880 const char* vers
= argv
[++i
];
1882 throw "-dylib_current_version missing <version>";
1883 fDylibCurrentVersion
= parseVersionNumber64(vers
);
1885 else if ( strcmp(arg
, "-sectorder") == 0 ) {
1886 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
1887 throw "-sectorder missing <segment> <section> <file-path>";
1888 snapshotFileArgIndex
= 3;
1889 parseSectionOrderFile(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1892 else if ( strcmp(arg
, "-order_file") == 0 ) {
1893 snapshotFileArgIndex
= 1;
1894 parseOrderFile(argv
[++i
], false);
1896 else if ( strcmp(arg
, "-order_file_statistics") == 0 ) {
1897 fPrintOrderFileStatistics
= true;
1899 // ??? Deprecate segcreate.
1900 // -sectcreate puts whole files into a section in the output.
1901 else if ( (strcmp(arg
, "-sectcreate") == 0) || (strcmp(arg
, "-segcreate") == 0) ) {
1902 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
1903 throw "-sectcreate missing <segment> <section> <file-path>";
1904 snapshotFileArgIndex
= 3;
1905 addSection(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1908 // Since we have a full path in binary/library names we need to be able to override it.
1909 else if ( (strcmp(arg
, "-dylib_install_name") == 0)
1910 || (strcmp(arg
, "-dylinker_install_name") == 0)
1911 || (strcmp(arg
, "-install_name") == 0)) {
1912 fDylibInstallName
= argv
[++i
];
1913 if ( fDylibInstallName
== NULL
)
1914 throw "-install_name missing <path>";
1916 // Sets the base address of the output.
1917 else if ( (strcmp(arg
, "-seg1addr") == 0) || (strcmp(arg
, "-image_base") == 0) ) {
1918 const char* address
= argv
[++i
];
1919 if ( address
== NULL
)
1920 throwf("%s missing <address>", arg
);
1921 fBaseAddress
= parseAddress(address
);
1922 uint64_t temp
= ((fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
1923 if ( fBaseAddress
!= temp
) {
1924 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment
);
1925 fBaseAddress
= temp
;
1928 else if ( strcmp(arg
, "-e") == 0 ) {
1929 fEntryName
= argv
[++i
];
1931 // Same as -@ from the FSF linker.
1932 else if ( strcmp(arg
, "-filelist") == 0 ) {
1933 snapshotArgCount
= 0;
1934 const char* path
= argv
[++i
];
1935 if ( (path
== NULL
) || (path
[0] == '-') )
1936 throw "-filelist missing <path>";
1937 ld::File::Ordinal baseOrdinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
1938 loadFileList(path
, baseOrdinal
);
1940 else if ( strcmp(arg
, "-keep_private_externs") == 0 ) {
1941 fKeepPrivateExterns
= true;
1943 else if ( strcmp(arg
, "-final_output") == 0 ) {
1944 fFinalName
= argv
[++i
];
1946 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
1947 // just ensures that this happens for cross object file boundaries.
1948 else if ( (strcmp(arg
, "-interposable") == 0) || (strcmp(arg
, "-multi_module") == 0)) {
1949 switch ( fInterposeMode
) {
1950 case kInterposeNone
:
1951 case kInterposeAllExternal
:
1952 fInterposeMode
= kInterposeAllExternal
;
1954 case kInterposeSome
:
1955 // do nothing, -interposable_list overrides -interposable"
1959 else if ( strcmp(arg
, "-interposable_list") == 0 ) {
1960 snapshotFileArgIndex
= 1;
1961 fInterposeMode
= kInterposeSome
;
1962 loadExportFile(argv
[++i
], "-interposable_list", fInterposeList
);
1964 // Default for -interposable/-multi_module/-single_module.
1965 else if ( strcmp(arg
, "-single_module") == 0 ) {
1966 fInterposeMode
= kInterposeNone
;
1968 else if ( strcmp(arg
, "-exported_symbols_list") == 0 ) {
1969 snapshotFileArgIndex
= 1;
1970 if ( fExportMode
== kDontExportSome
)
1971 throw "can't use -exported_symbols_list and -unexported_symbols_list";
1972 fExportMode
= kExportSome
;
1973 loadExportFile(argv
[++i
], "-exported_symbols_list", fExportSymbols
);
1975 else if ( strcmp(arg
, "-unexported_symbols_list") == 0 ) {
1976 snapshotFileArgIndex
= 1;
1977 if ( fExportMode
== kExportSome
)
1978 throw "can't use -unexported_symbols_list and -exported_symbols_list";
1979 fExportMode
= kDontExportSome
;
1980 loadExportFile(argv
[++i
], "-unexported_symbols_list", fDontExportSymbols
);
1982 else if ( strcmp(arg
, "-exported_symbol") == 0 ) {
1983 if ( fExportMode
== kDontExportSome
)
1984 throw "can't use -exported_symbol and -unexported_symbols";
1985 fExportMode
= kExportSome
;
1986 fExportSymbols
.insert(argv
[++i
]);
1988 else if ( strcmp(arg
, "-unexported_symbol") == 0 ) {
1989 if ( fExportMode
== kExportSome
)
1990 throw "can't use -unexported_symbol and -exported_symbol";
1991 fExportMode
= kDontExportSome
;
1992 fDontExportSymbols
.insert(argv
[++i
]);
1994 else if ( strcmp(arg
, "-non_global_symbols_no_strip_list") == 0 ) {
1995 snapshotFileArgIndex
= 1;
1996 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveExclude
)
1997 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
1998 fLocalSymbolHandling
= kLocalSymbolsSelectiveInclude
;
1999 loadExportFile(argv
[++i
], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded
);
2001 else if ( strcmp(arg
, "-non_global_symbols_strip_list") == 0 ) {
2002 snapshotFileArgIndex
= 1;
2003 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveInclude
)
2004 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2005 fLocalSymbolHandling
= kLocalSymbolsSelectiveExclude
;
2006 loadExportFile(argv
[++i
], "-non_global_symbols_strip_list", fLocalSymbolsExcluded
);
2009 else if ( strcmp(arg
, "-no_arch_warnings") == 0 ) {
2010 fIgnoreOtherArchFiles
= true;
2012 else if ( strcmp(arg
, "-force_cpusubtype_ALL") == 0 ) {
2013 fForceSubtypeAll
= true;
2014 fAllowCpuSubtypeMismatches
= true;
2016 // Similar to -weak-l but uses the absolute path name to the library.
2017 else if ( strcmp(arg
, "-weak_library") == 0 ) {
2018 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2019 snapshotArgCount
= 0;
2020 FileInfo info
= findFile(argv
[++i
]);
2021 info
.options
.fWeakImport
= true;
2022 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2025 else if ( strcmp(arg
, "-lazy_library") == 0 ) {
2026 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2027 snapshotArgCount
= 0;
2028 FileInfo info
= findFile(argv
[++i
]);
2029 info
.options
.fLazyLoad
= true;
2030 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2032 fUsingLazyDylibLinking
= true;
2034 else if ( strcmp(arg
, "-framework") == 0 ) {
2035 snapshotArgCount
= 0;
2036 FileInfo info
= findFramework(argv
[++i
]);
2037 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2040 else if ( strcmp(arg
, "-weak_framework") == 0 ) {
2041 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2042 snapshotArgCount
= 0;
2043 FileInfo info
= findFramework(argv
[++i
]);
2044 info
.options
.fWeakImport
= true;
2045 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2048 else if ( strcmp(arg
, "-lazy_framework") == 0 ) {
2049 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2050 snapshotArgCount
= 0;
2051 FileInfo info
= findFramework(argv
[++i
]);
2052 info
.options
.fLazyLoad
= true;
2053 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2055 fUsingLazyDylibLinking
= true;
2057 else if ( strcmp(arg
, "-search_paths_first") == 0 ) {
2058 // previously handled by buildSearchPaths()
2060 else if ( strcmp(arg
, "-search_dylibs_first") == 0 ) {
2061 // previously handled by buildSearchPaths()
2063 else if ( strcmp(arg
, "-undefined") == 0 ) {
2064 setUndefinedTreatment(argv
[++i
]);
2066 // Debugging output flag.
2067 else if ( strcmp(arg
, "-arch_multiple") == 0 ) {
2068 fMessagesPrefixedWithArchitecture
= true;
2070 // Specify what to do with relocations in read only
2071 // sections like .text. Could be errors, warnings,
2072 // or suppressed. Currently we do nothing with the
2074 else if ( strcmp(arg
, "-read_only_relocs") == 0 ) {
2075 switch ( parseTreatment(argv
[++i
]) ) {
2078 throw "-read_only_relocs missing [ warning | error | suppress ]";
2080 fWarnTextRelocs
= true;
2081 fAllowTextRelocs
= true;
2084 fWarnTextRelocs
= false;
2085 fAllowTextRelocs
= true;
2088 fWarnTextRelocs
= false;
2089 fAllowTextRelocs
= false;
2093 else if ( strcmp(arg
, "-sect_diff_relocs") == 0 ) {
2097 // Warn, error or make strong a mismatch between weak
2098 // and non-weak references.
2099 else if ( strcmp(arg
, "-weak_reference_mismatches") == 0 ) {
2100 setWeakReferenceMismatchTreatment(argv
[++i
]);
2102 // For a deployment target of 10.3 and earlier ld64 will
2103 // prebind an executable with 0s in all addresses that
2104 // are prebound. This can then be fixed up by update_prebinding
2105 // later. Prebinding is less useful on 10.4 and greater.
2106 else if ( strcmp(arg
, "-prebind") == 0 ) {
2109 else if ( strcmp(arg
, "-noprebind") == 0 ) {
2113 else if ( strcmp(arg
, "-prebind_allow_overlap") == 0 ) {
2116 else if ( strcmp(arg
, "-prebind_all_twolevel_modules") == 0 ) {
2119 else if ( strcmp(arg
, "-noprebind_all_twolevel_modules") == 0 ) {
2122 else if ( strcmp(arg
, "-nofixprebinding") == 0 ) {
2125 // This should probably be deprecated when we respect -L and -F
2126 // when searching for libraries.
2127 else if ( strcmp(arg
, "-dylib_file") == 0 ) {
2128 // ignore for snapshot because a stub dylib will be created in the snapshot
2129 snapshotArgCount
= 0;
2130 addDylibOverride(argv
[++i
]);
2132 // What to expand @executable_path to if found in dependent dylibs
2133 else if ( strcmp(arg
, "-executable_path") == 0 ) {
2134 fExecutablePath
= argv
[++i
];
2135 if ( (fExecutablePath
== NULL
) || (fExecutablePath
[0] == '-') )
2136 throw "-executable_path missing <path>";
2137 // if a directory was passed, add / to end
2138 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2139 struct stat statBuffer
;
2140 if ( stat(fExecutablePath
, &statBuffer
) == 0 ) {
2141 if ( (statBuffer
.st_mode
& S_IFMT
) == S_IFDIR
) {
2142 char* pathWithSlash
= new char[strlen(fExecutablePath
)+2];
2143 strcpy(pathWithSlash
, fExecutablePath
);
2144 strcat(pathWithSlash
, "/");
2145 fExecutablePath
= pathWithSlash
;
2149 // Aligns all segments to the power of 2 boundary specified.
2150 else if ( strcmp(arg
, "-segalign") == 0 ) {
2151 const char* size
= argv
[++i
];
2153 throw "-segalign missing <size>";
2154 fSegmentAlignment
= parseAddress(size
);
2155 uint8_t alignment
= (uint8_t)__builtin_ctz(fSegmentAlignment
);
2156 uint32_t p2aligned
= (1 << alignment
);
2157 if ( p2aligned
!= fSegmentAlignment
) {
2158 warning("alignment for -segalign %s is not a power of two, using 0x%X", size
, p2aligned
);
2159 fSegmentAlignment
= p2aligned
;
2162 // Puts a specified segment at a particular address that must
2163 // be a multiple of the segment alignment.
2164 else if ( strcmp(arg
, "-segaddr") == 0 ) {
2166 seg
.name
= argv
[++i
];
2167 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2168 throw "-segaddr missing segName Adddress";
2169 seg
.address
= parseAddress(argv
[++i
]);
2170 uint64_t temp
= ((seg
.address
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
2171 if ( seg
.address
!= temp
)
2172 warning("-segaddr %s not %lld byte aligned", seg
.name
, fSegmentAlignment
);
2173 fCustomSegmentAddresses
.push_back(seg
);
2175 // ??? Deprecate when we deprecate split-seg.
2176 else if ( strcmp(arg
, "-segs_read_only_addr") == 0 ) {
2177 fBaseAddress
= parseAddress(argv
[++i
]);
2179 // ??? Deprecate when we deprecate split-seg.
2180 else if ( strcmp(arg
, "-segs_read_write_addr") == 0 ) {
2181 fBaseWritableAddress
= parseAddress(argv
[++i
]);
2184 // ??? Deprecate when we get rid of basing at build time.
2185 else if ( strcmp(arg
, "-seg_addr_table") == 0 ) {
2186 snapshotFileArgIndex
= 1;
2187 const char* name
= argv
[++i
];
2189 throw "-seg_addr_table missing argument";
2190 fSegAddrTablePath
= name
;
2192 else if ( strcmp(arg
, "-seg_addr_table_filename") == 0 ) {
2196 else if ( strcmp(arg
, "-segprot") == 0 ) {
2198 seg
.name
= argv
[++i
];
2199 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) || (argv
[i
+2] == NULL
) )
2200 throw "-segprot missing segName max-prot init-prot";
2201 seg
.max
= parseProtection(argv
[++i
]);
2202 seg
.init
= parseProtection(argv
[++i
]);
2203 fCustomSegmentProtections
.push_back(seg
);
2205 else if ( strcmp(arg
, "-pagezero_size") == 0 ) {
2206 const char* size
= argv
[++i
];
2208 throw "-pagezero_size missing <size>";
2209 fZeroPageSize
= parseAddress(size
);
2210 uint64_t temp
= fZeroPageSize
& (-4096); // page align
2211 if ( (fZeroPageSize
!= temp
) )
2212 warning("-pagezero_size not page aligned, rounding down");
2213 fZeroPageSize
= temp
;
2215 else if ( strcmp(arg
, "-stack_addr") == 0 ) {
2216 const char* address
= argv
[++i
];
2217 if ( address
== NULL
)
2218 throw "-stack_addr missing <address>";
2219 fStackAddr
= parseAddress(address
);
2221 else if ( strcmp(arg
, "-stack_size") == 0 ) {
2222 const char* size
= argv
[++i
];
2224 throw "-stack_size missing <address>";
2225 fStackSize
= parseAddress(size
);
2226 uint64_t temp
= fStackSize
& (-4096); // page align
2227 if ( (fStackSize
!= temp
) )
2228 warning("-stack_size not page aligned, rounding down");
2230 else if ( strcmp(arg
, "-allow_stack_execute") == 0 ) {
2231 fExecutableStack
= true;
2233 else if ( strcmp(arg
, "-allow_heap_execute") == 0 ) {
2234 fDisableNonExecutableHeap
= true;
2236 else if ( strcmp(arg
, "-sectalign") == 0 ) {
2237 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2238 throw "-sectalign missing <segment> <section> <file-path>";
2239 addSectionAlignment(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2242 else if ( strcmp(arg
, "-sectorder_detail") == 0 ) {
2245 else if ( strcmp(arg
, "-sectobjectsymbols") == 0 ) {
2249 else if ( strcmp(arg
, "-bundle_loader") == 0 ) {
2250 snapshotFileArgIndex
= 1;
2251 fBundleLoader
= argv
[++i
];
2252 if ( (fBundleLoader
== NULL
) || (fBundleLoader
[0] == '-') )
2253 throw "-bundle_loader missing <path>";
2254 FileInfo info
= findFile(fBundleLoader
);
2255 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2256 info
.options
.fBundleLoader
= true;
2257 fInputFiles
.push_back(info
);
2259 else if ( strcmp(arg
, "-private_bundle") == 0 ) {
2262 else if ( strcmp(arg
, "-twolevel_namespace_hints") == 0 ) {
2265 // Use this flag to set default behavior for deployement targets.
2266 else if ( strcmp(arg
, "-macosx_version_min") == 0 ) {
2267 setMacOSXVersionMin(argv
[++i
]);
2269 else if ( (strcmp(arg
, "-ios_version_min") == 0) || (strcmp(arg
, "-iphoneos_version_min") == 0) ) {
2270 setIOSVersionMin(argv
[++i
]);
2272 else if ( strcmp(arg
, "-ios_simulator_version_min") == 0 ) {
2273 setIOSVersionMin(argv
[++i
]);
2275 else if ( strcmp(arg
, "-multiply_defined") == 0 ) {
2276 //warnObsolete(arg);
2279 else if ( strcmp(arg
, "-multiply_defined_unused") == 0 ) {
2283 else if ( strcmp(arg
, "-nomultidefs") == 0 ) {
2286 // Display each file in which the argument symbol appears and whether
2287 // the file defines or references it. This option takes an argument
2288 // as -y<symbol> note that there is no space.
2289 else if ( strncmp(arg
, "-y", 2) == 0 ) {
2292 // Same output as -y, but output <arg> number of undefined symbols only.
2293 else if ( strcmp(arg
, "-Y") == 0 ) {
2294 //warnObsolete(arg);
2297 // This option affects all objects linked into the final result.
2298 else if ( strcmp(arg
, "-m") == 0 ) {
2301 else if ( (strcmp(arg
, "-why_load") == 0) || (strcmp(arg
, "-whyload") == 0) ) {
2304 else if ( strcmp(arg
, "-why_live") == 0 ) {
2305 const char* name
= argv
[++i
];
2307 throw "-why_live missing symbol name argument";
2308 fWhyLive
.insert(name
);
2310 else if ( strcmp(arg
, "-u") == 0 ) {
2311 const char* name
= argv
[++i
];
2313 throw "-u missing argument";
2314 fInitialUndefines
.push_back(name
);
2316 else if ( strcmp(arg
, "-U") == 0 ) {
2317 const char* name
= argv
[++i
];
2319 throw "-U missing argument";
2320 fAllowedUndefined
.insert(name
);
2322 else if ( strcmp(arg
, "-s") == 0 ) {
2324 fLocalSymbolHandling
= kLocalSymbolsNone
;
2325 fDebugInfoStripping
= Options::kDebugInfoNone
;
2327 else if ( strcmp(arg
, "-x") == 0 ) {
2328 fLocalSymbolHandling
= kLocalSymbolsNone
;
2330 else if ( strcmp(arg
, "-S") == 0 ) {
2331 fDebugInfoStripping
= Options::kDebugInfoNone
;
2333 else if ( strcmp(arg
, "-X") == 0 ) {
2336 else if ( strcmp(arg
, "-Si") == 0 ) {
2338 fDebugInfoStripping
= Options::kDebugInfoFull
;
2340 else if ( strcmp(arg
, "-b") == 0 ) {
2343 else if ( strcmp(arg
, "-Sn") == 0 ) {
2345 fDebugInfoStripping
= Options::kDebugInfoFull
;
2347 else if ( strcmp(arg
, "-Sp") == 0 ) {
2350 else if ( strcmp(arg
, "-dead_strip") == 0 ) {
2353 else if ( strcmp(arg
, "-no_dead_strip_inits_and_terms") == 0 ) {
2356 else if ( strcmp(arg
, "-w") == 0 ) {
2357 // previously handled by buildSearchPaths()
2359 else if ( strcmp(arg
, "-fatal_warnings") == 0 ) {
2360 // previously handled by buildSearchPaths()
2362 else if ( strcmp(arg
, "-arch_errors_fatal") == 0 ) {
2363 fErrorOnOtherArchFiles
= true;
2365 else if ( strcmp(arg
, "-M") == 0 ) {
2368 else if ( strcmp(arg
, "-headerpad") == 0 ) {
2369 const char* size
= argv
[++i
];
2371 throw "-headerpad missing argument";
2372 fMinimumHeaderPad
= parseAddress(size
);
2374 else if ( strcmp(arg
, "-headerpad_max_install_names") == 0 ) {
2375 fMaxMinimumHeaderPad
= true;
2377 else if ( strcmp(arg
, "-t") == 0 ) {
2378 fLogAllFiles
= true;
2380 else if ( strcmp(arg
, "-whatsloaded") == 0 ) {
2381 fLogObjectFiles
= true;
2383 else if ( strcmp(arg
, "-A") == 0 ) {
2387 else if ( strcmp(arg
, "-umbrella") == 0 ) {
2388 const char* name
= argv
[++i
];
2390 throw "-umbrella missing argument";
2391 fUmbrellaName
= name
;
2393 else if ( strcmp(arg
, "-allowable_client") == 0 ) {
2394 const char* name
= argv
[++i
];
2397 throw "-allowable_client missing argument";
2399 fAllowableClients
.push_back(name
);
2401 else if ( strcmp(arg
, "-client_name") == 0 ) {
2402 const char* name
= argv
[++i
];
2405 throw "-client_name missing argument";
2409 else if ( strcmp(arg
, "-sub_umbrella") == 0 ) {
2410 const char* name
= argv
[++i
];
2412 throw "-sub_umbrella missing argument";
2413 fSubUmbellas
.push_back(name
);
2415 else if ( strcmp(arg
, "-sub_library") == 0 ) {
2416 const char* name
= argv
[++i
];
2418 throw "-sub_library missing argument";
2419 fSubLibraries
.push_back(name
);
2421 else if ( strcmp(arg
, "-init") == 0 ) {
2422 const char* name
= argv
[++i
];
2424 throw "-init missing argument";
2425 fInitFunctionName
= name
;
2427 else if ( strcmp(arg
, "-dot") == 0 ) {
2428 const char* name
= argv
[++i
];
2430 throw "-dot missing argument";
2431 fDotOutputFile
= name
;
2433 else if ( strcmp(arg
, "-warn_commons") == 0 ) {
2434 fWarnCommons
= true;
2436 else if ( strcmp(arg
, "-commons") == 0 ) {
2437 fCommonsMode
= parseCommonsTreatment(argv
[++i
]);
2439 else if ( strcmp(arg
, "-keep_relocs") == 0 ) {
2440 fKeepRelocations
= true;
2442 else if ( strcmp(arg
, "-warn_stabs") == 0 ) {
2445 else if ( strcmp(arg
, "-pause") == 0 ) {
2448 else if ( strcmp(arg
, "-print_statistics") == 0 ) {
2451 else if ( strcmp(arg
, "-d") == 0 ) {
2452 fMakeTentativeDefinitionsReal
= true;
2454 else if ( strcmp(arg
, "-v") == 0 ) {
2455 // previously handled by buildSearchPaths()
2457 else if ( strcmp(arg
, "-Z") == 0 ) {
2458 // previously handled by buildSearchPaths()
2460 else if ( strcmp(arg
, "-syslibroot") == 0 ) {
2461 snapshotArgCount
= 0;
2463 // previously handled by buildSearchPaths()
2465 else if ( strcmp(arg
, "-no_uuid") == 0 ) {
2466 fUUIDMode
= kUUIDNone
;
2468 else if ( strcmp(arg
, "-random_uuid") == 0 ) {
2469 fUUIDMode
= kUUIDRandom
;
2471 else if ( strcmp(arg
, "-dtrace") == 0 ) {
2472 snapshotFileArgIndex
= 1;
2473 const char* name
= argv
[++i
];
2475 throw "-dtrace missing argument";
2476 fDtraceScriptName
= name
;
2478 else if ( strcmp(arg
, "-root_safe") == 0 ) {
2481 else if ( strcmp(arg
, "-setuid_safe") == 0 ) {
2484 else if ( strcmp(arg
, "-alias") == 0 ) {
2485 Options::AliasPair pair
;
2486 pair
.realName
= argv
[++i
];
2487 if ( pair
.realName
== NULL
)
2488 throw "missing argument to -alias";
2489 pair
.alias
= argv
[++i
];
2490 if ( pair
.alias
== NULL
)
2491 throw "missing argument to -alias";
2492 fAliases
.push_back(pair
);
2494 else if ( strcmp(arg
, "-alias_list") == 0 ) {
2495 snapshotFileArgIndex
= 1;
2496 parseAliasFile(argv
[++i
]);
2498 // put this last so that it does not interfer with other options starting with 'i'
2499 else if ( strncmp(arg
, "-i", 2) == 0 ) {
2500 const char* colon
= strchr(arg
, ':');
2501 if ( colon
== NULL
)
2502 throwf("unknown option: %s", arg
);
2503 Options::AliasPair pair
;
2504 char* temp
= new char[colon
-arg
];
2505 strlcpy(temp
, &arg
[2], colon
-arg
-1);
2506 pair
.realName
= &colon
[1];
2508 fAliases
.push_back(pair
);
2510 else if ( strcmp(arg
, "-save-temps") == 0 ) {
2511 fSaveTempFiles
= true;
2513 else if ( strcmp(arg
, "-rpath") == 0 ) {
2514 const char* path
= argv
[++i
];
2516 throw "missing argument to -rpath";
2517 fRPaths
.push_back(path
);
2519 else if ( strcmp(arg
, "-read_only_stubs") == 0 ) {
2520 fReadOnlyx86Stubs
= true;
2522 else if ( strcmp(arg
, "-slow_stubs") == 0 ) {
2525 else if ( strcmp(arg
, "-map") == 0 ) {
2526 fMapPath
= argv
[++i
];
2527 if ( fMapPath
== NULL
)
2528 throw "missing argument to -map";
2530 else if ( strcmp(arg
, "-pie") == 0 ) {
2531 fPositionIndependentExecutable
= true;
2532 fPIEOnCommandLine
= true;
2534 else if ( strcmp(arg
, "-no_pie") == 0 ) {
2535 fDisablePositionIndependentExecutable
= true;
2537 else if ( strncmp(arg
, "-reexport-l", 11) == 0 ) {
2538 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2539 snapshotArgCount
= 0;
2540 FileInfo info
= findLibrary(&arg
[11], true);
2541 info
.options
.fReExport
= true;
2542 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2545 else if ( strcmp(arg
, "-reexport_library") == 0 ) {
2546 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2547 snapshotArgCount
= 0;
2548 FileInfo info
= findFile(argv
[++i
]);
2549 info
.options
.fReExport
= true;
2550 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2553 else if ( strcmp(arg
, "-reexport_framework") == 0 ) {
2554 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2555 snapshotArgCount
= 0;
2556 FileInfo info
= findFramework(argv
[++i
]);
2557 info
.options
.fReExport
= true;
2558 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2561 else if ( strncmp(arg
, "-upward-l", 9) == 0 ) {
2562 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2563 snapshotArgCount
= 0;
2564 FileInfo info
= findLibrary(&arg
[9], true);
2565 info
.options
.fUpward
= true;
2566 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2569 else if ( strcmp(arg
, "-upward_library") == 0 ) {
2570 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2571 snapshotArgCount
= 0;
2572 FileInfo info
= findFile(argv
[++i
]);
2573 info
.options
.fUpward
= true;
2574 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2577 else if ( strcmp(arg
, "-upward_framework") == 0 ) {
2578 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2579 snapshotArgCount
= 0;
2580 FileInfo info
= findFramework(argv
[++i
]);
2581 info
.options
.fUpward
= true;
2582 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2585 else if ( strcmp(arg
, "-dead_strip_dylibs") == 0 ) {
2586 fDeadStripDylibs
= true;
2588 else if ( strcmp(arg
, "-no_implicit_dylibs") == 0 ) {
2589 fImplicitlyLinkPublicDylibs
= false;
2591 else if ( strcmp(arg
, "-new_linker") == 0 ) {
2594 else if ( strcmp(arg
, "-no_encryption") == 0 ) {
2595 fEncryptable
= false;
2597 else if ( strcmp(arg
, "-no_compact_unwind") == 0 ) {
2598 fAddCompactUnwindEncoding
= false;
2600 else if ( strcmp(arg
, "-mllvm") == 0 ) {
2601 const char* opts
= argv
[++i
];
2603 throw "missing argument to -mllvm";
2604 fLLVMOptions
.push_back(opts
);
2606 else if ( strcmp(arg
, "-no_order_inits") == 0 ) {
2607 fAutoOrderInitializers
= false;
2609 else if ( strcmp(arg
, "-no_order_data") == 0 ) {
2612 else if ( strcmp(arg
, "-seg_page_size") == 0 ) {
2614 seg
.name
= argv
[++i
];
2615 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2616 throw "-seg_page_size missing segName Adddress";
2617 seg
.size
= parseAddress(argv
[++i
]);
2618 uint64_t temp
= seg
.size
& (-4096); // page align
2619 if ( (seg
.size
!= temp
) )
2620 warning("-seg_page_size %s not 4K aligned, rounding down", seg
.name
);
2621 fCustomSegmentSizes
.push_back(seg
);
2623 else if ( strcmp(arg
, "-mark_dead_strippable_dylib") == 0 ) {
2624 fMarkDeadStrippableDylib
= true;
2626 else if ( strcmp(arg
, "-exported_symbols_order") == 0 ) {
2627 snapshotFileArgIndex
= 1;
2628 loadSymbolOrderFile(argv
[++i
], fExportSymbolsOrder
);
2630 else if ( strcmp(arg
, "-no_compact_linkedit") == 0 ) {
2631 warnObsolete("-no_compact_linkedit");
2633 else if ( strcmp(arg
, "-no_eh_labels") == 0 ) {
2636 else if ( strcmp(arg
, "-warn_compact_unwind") == 0 ) {
2637 fWarnCompactUnwind
= true;
2639 else if ( strcmp(arg
, "-allow_sub_type_mismatches") == 0 ) {
2640 fAllowCpuSubtypeMismatches
= true;
2642 else if ( strcmp(arg
, "-no_zero_fill_sections") == 0 ) {
2643 fOptimizeZeroFill
= false;
2645 else if ( strcmp(arg
, "-merge_zero_fill_sections") == 0 ) {
2646 fMergeZeroFill
= true;
2648 else if ( strcmp(arg
, "-objc_abi_version") == 0 ) {
2649 const char* version
= argv
[++i
];
2650 if ( version
== NULL
)
2651 throw "-objc_abi_version missing version number";
2652 if ( strcmp(version
, "2") == 0 ) {
2653 fObjCABIVersion1Override
= false;
2654 fObjCABIVersion2Override
= true;
2656 else if ( strcmp(version
, "1") == 0 ) {
2657 fObjCABIVersion1Override
= true;
2658 fObjCABIVersion2Override
= false;
2661 warning("ignoring unrecognized argument (%s) to -objc_abi_version", version
);
2663 else if ( strcmp(arg
, "-warn_weak_exports") == 0 ) {
2664 fWarnWeakExports
= true;
2666 else if ( strcmp(arg
, "-objc_gc_compaction") == 0 ) {
2667 fObjcGcCompaction
= true;
2669 else if ( strcmp(arg
, "-objc_gc") == 0 ) {
2671 if ( fObjCGcOnly
) {
2672 warning("-objc_gc overriding -objc_gc_only");
2673 fObjCGcOnly
= false;
2676 else if ( strcmp(arg
, "-objc_gc_only") == 0 ) {
2679 warning("-objc_gc_only overriding -objc_gc");
2683 else if ( strcmp(arg
, "-demangle") == 0 ) {
2686 else if ( strcmp(arg
, "-version_load_command") == 0 ) {
2687 fVersionLoadCommandForcedOn
= true;
2688 fVersionLoadCommandForcedOff
= false;
2690 else if ( strcmp(arg
, "-no_version_load_command") == 0 ) {
2691 fVersionLoadCommandForcedOff
= true;
2692 fVersionLoadCommandForcedOn
= false;
2694 else if ( strcmp(arg
, "-function_starts") == 0 ) {
2695 fFunctionStartsForcedOn
= true;
2696 fFunctionStartsForcedOff
= false;
2698 else if ( strcmp(arg
, "-no_function_starts") == 0 ) {
2699 fFunctionStartsForcedOff
= true;
2700 fFunctionStartsForcedOn
= false;
2702 else if ( strcmp(arg
, "-no_data_in_code_info") == 0 ) {
2703 fDataInCodeInfoLoadCommandForcedOff
= true;
2704 fDataInCodeInfoLoadCommandForcedOn
= false;
2706 else if ( strcmp(arg
, "-data_in_code_info") == 0 ) {
2707 fDataInCodeInfoLoadCommandForcedOn
= true;
2708 fDataInCodeInfoLoadCommandForcedOff
= false;
2710 else if ( strcmp(arg
, "-object_path_lto") == 0 ) {
2711 fTempLtoObjectPath
= argv
[++i
];
2712 if ( fTempLtoObjectPath
== NULL
)
2713 throw "missing argument to -object_path_lto";
2715 else if ( strcmp(arg
, "-no_objc_category_merging") == 0 ) {
2716 fObjcCategoryMerging
= false;
2718 else if ( strcmp(arg
, "-force_symbols_weak_list") == 0 ) {
2719 snapshotFileArgIndex
= 1;
2720 loadExportFile(argv
[++i
], "-force_symbols_weak_list", fForceWeakSymbols
);
2722 else if ( strcmp(arg
, "-force_symbols_not_weak_list") == 0 ) {
2723 snapshotFileArgIndex
= 1;
2724 loadExportFile(argv
[++i
], "-force_symbols_not_weak_list", fForceNotWeakSymbols
);
2726 else if ( strcmp(arg
, "-force_symbol_weak") == 0 ) {
2727 const char* symbol
= argv
[++i
];
2728 if ( symbol
== NULL
)
2729 throw "-force_symbol_weak missing <symbol>";
2730 fForceWeakSymbols
.insert(symbol
);
2732 else if ( strcmp(arg
, "-force_symbol_not_weak") == 0 ) {
2733 const char* symbol
= argv
[++i
];
2734 if ( symbol
== NULL
)
2735 throw "-force_symbol_not_weak missing <symbol>";
2736 fForceNotWeakSymbols
.insert(symbol
);
2738 else if ( strcmp(arg
, "-reexported_symbols_list") == 0 ) {
2739 snapshotFileArgIndex
= 1;
2740 if ( fExportMode
== kExportSome
)
2741 throw "can't use -exported_symbols_list and -reexported_symbols_list";
2742 loadExportFile(argv
[++i
], "-reexported_symbols_list", fReExportSymbols
);
2744 else if ( strcmp(arg
, "-dyld_env") == 0 ) {
2745 const char* envarg
= argv
[++i
];
2746 if ( envarg
== NULL
)
2747 throw "-dyld_env missing ENV=VALUE";
2748 if ( strchr(envarg
, '=') == NULL
)
2749 throw "-dyld_env missing ENV=VALUE";
2750 fDyldEnvironExtras
.push_back(envarg
);
2752 else if ( strcmp(arg
, "-page_align_data_atoms") == 0 ) {
2753 fPageAlignDataAtoms
= true;
2755 else if (strcmp(arg
, "-debug_snapshot") == 0) {
2756 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
2757 fSnapshotRequested
= true;
2759 else if ( strcmp(arg
, "-new_main") == 0 ) {
2760 fEntryPointLoadCommandForceOn
= true;
2762 else if ( strcmp(arg
, "-no_new_main") == 0 ) {
2763 fEntryPointLoadCommandForceOff
= true;
2765 else if ( strcmp(arg
, "-source_version") == 0 ) {
2766 const char* vers
= argv
[++i
];
2768 throw "-source_version missing <version>";
2769 fSourceVersion
= parseVersionNumber64(vers
);
2771 else if ( strcmp(arg
, "-add_source_version") == 0 ) {
2772 fSourceVersionLoadCommandForceOn
= true;
2774 else if ( strcmp(arg
, "-no_source_version") == 0 ) {
2775 fSourceVersionLoadCommandForceOff
= true;
2777 else if ( strcmp(arg
, "-sdk_version") == 0 ) {
2778 const char* vers
= argv
[++i
];
2780 throw "-sdk_version missing <version>";
2781 fSDKVersion
= parseVersionNumber32(vers
);
2783 else if ( strcmp(arg
, "-dependent_dr_info") == 0 ) {
2784 fDependentDRInfoForcedOn
= true;
2786 else if ( strcmp(arg
, "-no_dependent_dr_info") == 0 ) {
2787 fDependentDRInfoForcedOff
= true;
2789 else if ( strcmp(arg
, "-kexts_use_stubs") == 0 ) {
2790 fKextsUseStubs
= true;
2793 throwf("unknown option: %s", arg
);
2796 if (snapshotArgCount
== -1)
2797 snapshotArgCount
= i
-snapshotArgIndex
+1;
2798 if (snapshotArgCount
> 0)
2799 fLinkSnapshot
.addSnapshotLinkArg(snapshotArgIndex
, snapshotArgCount
, snapshotFileArgIndex
);
2802 FileInfo info
= findFile(arg
);
2803 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)i
);
2804 if ( strcmp(&info
.path
[strlen(info
.path
)-2], ".a") == 0 )
2807 fInputFiles
.push_back(info
);
2811 // if a -lazy option was used, implicitly link in lazydylib1.o
2812 if ( fUsingLazyDylibLinking
) {
2813 FileInfo info
= findLibrary("lazydylib1.o");
2814 info
.ordinal
= ld::File::Ordinal::makeArgOrdinal((uint16_t)argc
);
2818 if (fSnapshotRequested
)
2819 fLinkSnapshot
.createSnapshot();
2825 // -syslibroot <path> is used for SDK support.
2826 // The rule is that all search paths (both explicit and default) are
2827 // checked to see if they exist in the SDK. If so, that path is
2828 // replaced with the sdk prefixed path. If not, that search path
2829 // is used as is. If multiple -syslibroot options are specified
2830 // their directory structures are logically overlayed and files
2831 // from sdks specified earlier on the command line used before later ones.
2833 void Options::buildSearchPaths(int argc
, const char* argv
[])
2835 bool addStandardLibraryDirectories
= true;
2836 std::vector
<const char*> libraryPaths
;
2837 std::vector
<const char*> frameworkPaths
;
2838 libraryPaths
.reserve(10);
2839 frameworkPaths
.reserve(10);
2840 // scan through argv looking for -L, -F, -Z, and -syslibroot options
2841 for(int i
=0; i
< argc
; ++i
) {
2842 if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'L') ) {
2843 const char* libSearchDir
= &argv
[i
][2];
2844 // Allow either "-L{path}" or "-L {path}".
2845 if (argv
[i
][2] == '\0') {
2846 // -L {path}. Make sure there is an argument following this.
2847 const char* path
= argv
[++i
];
2849 throw "-L missing argument";
2850 libSearchDir
= path
;
2852 if ( libSearchDir
[0] == '\0' )
2853 throw "-L must be immediately followed by a directory path (no space)";
2854 struct stat statbuf
;
2855 if ( stat(libSearchDir
, &statbuf
) == 0 ) {
2856 if ( statbuf
.st_mode
& S_IFDIR
)
2857 libraryPaths
.push_back(libSearchDir
);
2859 warning("path '%s' following -L not a directory", libSearchDir
);
2862 warning("directory not found for option '-L%s'", libSearchDir
);
2865 else if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'F') ) {
2866 const char* frameworkSearchDir
= &argv
[i
][2];
2867 // Allow either "-F{path}" or "-F {path}".
2868 if (argv
[i
][2] == '\0') {
2869 // -F {path}. Make sure there is an argument following this.
2870 const char* path
= argv
[++i
];
2872 throw "-F missing argument";
2873 frameworkSearchDir
= path
;
2875 if ( frameworkSearchDir
[0] == '\0' )
2876 throw "-F must be immediately followed by a directory path (no space)";
2877 struct stat statbuf
;
2878 if ( stat(frameworkSearchDir
, &statbuf
) == 0 ) {
2879 if ( statbuf
.st_mode
& S_IFDIR
)
2880 frameworkPaths
.push_back(frameworkSearchDir
);
2882 warning("path '%s' following -F not a directory", frameworkSearchDir
);
2885 warning("directory not found for option '-F%s'", frameworkSearchDir
);
2888 else if ( strcmp(argv
[i
], "-Z") == 0 )
2889 addStandardLibraryDirectories
= false;
2890 else if ( strcmp(argv
[i
], "-v") == 0 ) {
2892 extern const char ldVersionString
[];
2893 fprintf(stderr
, "%s", ldVersionString
);
2894 fprintf(stderr
, "configured to support archs: %s\n", ALL_SUPPORTED_ARCHS
);
2895 // if only -v specified, exit cleanly
2897 const char* ltoVers
= lto::version();
2898 if ( ltoVers
!= NULL
)
2899 fprintf(stderr
, "LTO support using: %s\n", ltoVers
);
2903 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
2904 const char* path
= argv
[++i
];
2906 throw "-syslibroot missing argument";
2907 fSDKPaths
.push_back(path
);
2909 else if ( strcmp(argv
[i
], "-search_paths_first") == 0 ) {
2910 fLibrarySearchMode
= kSearchDylibAndArchiveInEachDir
;
2912 else if ( strcmp(argv
[i
], "-search_dylibs_first") == 0 ) {
2913 fLibrarySearchMode
= kSearchAllDirsForDylibsThenAllDirsForArchives
;
2915 else if ( strcmp(argv
[i
], "-w") == 0 ) {
2916 sEmitWarnings
= false;
2918 else if ( strcmp(argv
[i
], "-fatal_warnings") == 0 ) {
2919 sFatalWarnings
= true;
2922 int standardLibraryPathsStartIndex
= libraryPaths
.size();
2923 int standardFrameworkPathsStartIndex
= frameworkPaths
.size();
2924 if ( addStandardLibraryDirectories
) {
2925 libraryPaths
.push_back("/usr/lib");
2926 libraryPaths
.push_back("/usr/local/lib");
2928 frameworkPaths
.push_back("/Library/Frameworks/");
2929 frameworkPaths
.push_back("/System/Library/Frameworks/");
2930 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
2933 // <rdar://problem/5829579> Support for configure based hacks
2934 // if last -syslibroot is /, then ignore all syslibroots
2935 if ( fSDKPaths
.size() > 0 ) {
2936 if ( strcmp(fSDKPaths
.back(), "/") == 0 ) {
2941 // now merge sdk and library paths to make real search paths
2942 fLibrarySearchPaths
.reserve(libraryPaths
.size()*(fSDKPaths
.size()+1));
2944 for (std::vector
<const char*>::iterator it
= libraryPaths
.begin(); it
!= libraryPaths
.end(); ++it
, ++libIndex
) {
2945 const char* libDir
= *it
;
2946 bool sdkOverride
= false;
2947 if ( libDir
[0] == '/' ) {
2948 char betterLibDir
[PATH_MAX
];
2949 if ( strstr(libDir
, "/..") != NULL
) {
2950 if ( realpath(libDir
, betterLibDir
) != NULL
)
2951 libDir
= strdup(betterLibDir
);
2953 const int libDirLen
= strlen(libDir
);
2954 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
2955 const char* sdkDir
= *sdkit
;
2956 const int sdkDirLen
= strlen(sdkDir
);
2957 char newPath
[libDirLen
+ sdkDirLen
+4];
2958 strcpy(newPath
, sdkDir
);
2959 if ( newPath
[sdkDirLen
-1] == '/' )
2960 newPath
[sdkDirLen
-1] = '\0';
2961 strcat(newPath
, libDir
);
2962 struct stat statBuffer
;
2963 if ( stat(newPath
, &statBuffer
) == 0 ) {
2964 fLibrarySearchPaths
.push_back(strdup(newPath
));
2969 if ( !sdkOverride
) {
2970 if ( (libIndex
>= standardLibraryPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
2971 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2972 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2975 fLibrarySearchPaths
.push_back(libDir
);
2980 // now merge sdk and framework paths to make real search paths
2981 fFrameworkSearchPaths
.reserve(frameworkPaths
.size()*(fSDKPaths
.size()+1));
2983 for (std::vector
<const char*>::iterator it
= frameworkPaths
.begin(); it
!= frameworkPaths
.end(); ++it
, ++frameIndex
) {
2984 const char* frameworkDir
= *it
;
2985 bool sdkOverride
= false;
2986 if ( frameworkDir
[0] == '/' ) {
2987 char betterFrameworkDir
[PATH_MAX
];
2988 if ( strstr(frameworkDir
, "/..") != NULL
) {
2989 if ( realpath(frameworkDir
, betterFrameworkDir
) != NULL
)
2990 frameworkDir
= strdup(betterFrameworkDir
);
2992 const int frameworkDirLen
= strlen(frameworkDir
);
2993 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
2994 const char* sdkDir
= *sdkit
;
2995 const int sdkDirLen
= strlen(sdkDir
);
2996 char newPath
[frameworkDirLen
+ sdkDirLen
+4];
2997 strcpy(newPath
, sdkDir
);
2998 if ( newPath
[sdkDirLen
-1] == '/' )
2999 newPath
[sdkDirLen
-1] = '\0';
3000 strcat(newPath
, frameworkDir
);
3001 struct stat statBuffer
;
3002 if ( stat(newPath
, &statBuffer
) == 0 ) {
3003 fFrameworkSearchPaths
.push_back(strdup(newPath
));
3008 if ( !sdkOverride
) {
3009 if ( (frameIndex
>= standardFrameworkPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
3010 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
3011 // if one SDK is specified and a standard library path is not in the SDK, don't use it
3014 fFrameworkSearchPaths
.push_back(frameworkDir
);
3020 fprintf(stderr
,"Library search paths:\n");
3021 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
3022 it
!= fLibrarySearchPaths
.end();
3024 fprintf(stderr
,"\t%s\n", *it
);
3025 fprintf(stderr
,"Framework search paths:\n");
3026 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
3027 it
!= fFrameworkSearchPaths
.end();
3029 fprintf(stderr
,"\t%s\n", *it
);
3033 // this is run before the command line is parsed
3034 void Options::parsePreCommandLineEnvironmentSettings()
3036 if ((getenv("LD_TRACE_ARCHIVES") != NULL
)
3037 || (getenv("RC_TRACE_ARCHIVES") != NULL
))
3038 fTraceArchives
= true;
3040 if ((getenv("LD_TRACE_DYLIBS") != NULL
)
3041 || (getenv("RC_TRACE_DYLIBS") != NULL
)) {
3042 fTraceDylibs
= true;
3043 fTraceIndirectDylibs
= true;
3046 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL
) {
3047 fTraceDylibSearching
= true;
3050 if (getenv("LD_PRINT_OPTIONS") != NULL
)
3051 fPrintOptions
= true;
3053 if (fTraceDylibs
|| fTraceArchives
)
3054 fTraceOutputFile
= getenv("LD_TRACE_FILE");
3056 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL
)
3057 fPrintOrderFileStatistics
= true;
3059 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL
)
3062 if (getenv("LD_NO_ENCRYPT") != NULL
)
3063 fEncryptable
= false;
3065 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL
)
3066 fAllowCpuSubtypeMismatches
= true;
3068 sWarningsSideFilePath
= getenv("LD_WARN_FILE");
3070 const char* customDyldPath
= getenv("LD_DYLD_PATH");
3071 if ( customDyldPath
!= NULL
)
3072 fDyldInstallPath
= customDyldPath
;
3074 const char* debugArchivePath
= getenv("LD_DEBUG_SNAPSHOT");
3075 if (debugArchivePath
!= NULL
) {
3076 fLinkSnapshot
.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
3077 if (strlen(debugArchivePath
) > 0)
3078 fLinkSnapshot
.setSnapshotPath(debugArchivePath
);
3079 fSnapshotRequested
= true;
3082 const char* pipeFdString
= getenv("LD_PIPELINE_FIFO");
3083 if (pipeFdString
!= NULL
) {
3084 fPipelineFifo
= pipeFdString
;
3089 // this is run after the command line is parsed
3090 void Options::parsePostCommandLineEnvironmentSettings()
3092 // when building a dynamic main executable, default any use of @executable_path to output path
3093 if ( fExecutablePath
== NULL
&& (fOutputKind
== kDynamicExecutable
) ) {
3094 fExecutablePath
= fOutputFile
;
3097 // allow build system to set default seg_addr_table
3098 if ( fSegAddrTablePath
== NULL
)
3099 fSegAddrTablePath
= getenv("LD_SEG_ADDR_TABLE");
3101 // allow build system to turn on prebinding
3103 fPrebind
= ( getenv("LD_PREBIND") != NULL
);
3106 // allow build system to force on dead-code-stripping
3107 if ( !fDeadStrip
) {
3108 if ( getenv("LD_DEAD_STRIP") != NULL
) {
3109 switch (fOutputKind
) {
3110 case Options::kDynamicLibrary
:
3111 case Options::kDynamicExecutable
:
3112 case Options::kDynamicBundle
:
3115 case Options::kPreload
:
3116 case Options::kObjectFile
:
3117 case Options::kDyld
:
3118 case Options::kStaticExecutable
:
3119 case Options::kKextBundle
:
3125 // allow build system to force on -warn_commons
3126 if ( getenv("LD_WARN_COMMONS") != NULL
)
3127 fWarnCommons
= true;
3129 // allow B&I to set default -source_version
3130 if ( fSourceVersion
== 0 ) {
3131 const char* vers
= getenv("RC_ProjectSourceVersion");
3133 fSourceVersion
= parseVersionNumber64(vers
);
3138 void Options::reconfigureDefaults()
3140 // sync reader options
3141 switch ( fOutputKind
) {
3142 case Options::kObjectFile
:
3143 fForFinalLinkedImage
= false;
3145 case Options::kDyld
:
3147 fForFinalLinkedImage
= true;
3150 case Options::kDynamicLibrary
:
3151 case Options::kDynamicBundle
:
3152 case Options::kKextBundle
:
3153 fForFinalLinkedImage
= true;
3156 case Options::kDynamicExecutable
:
3157 case Options::kStaticExecutable
:
3158 case Options::kPreload
:
3159 fLinkingMainExecutable
= true;
3160 fForFinalLinkedImage
= true;
3165 // set default min OS version
3166 if ( (fMacVersionMin
== ld::macVersionUnset
)
3167 && (fIOSVersionMin
== ld::iOSVersionUnset
) ) {
3168 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
3169 const char* macVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
3170 const char* iPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
3171 const char* iOSVers
= getenv("IOS_DEPLOYMENT_TARGET");
3172 const char* iOSSimulatorVers
= getenv("IOS_SIMULATOR_DEPLOYMENT_TARGET");
3173 if ( macVers
!= NULL
)
3174 setMacOSXVersionMin(macVers
);
3175 else if ( iPhoneVers
!= NULL
)
3176 setIOSVersionMin(iPhoneVers
);
3177 else if ( iOSVers
!= NULL
)
3178 setIOSVersionMin(iOSVers
);
3179 else if ( iOSSimulatorVers
!= NULL
)
3180 setIOSVersionMin(iOSSimulatorVers
);
3182 // if still nothing, set default based on architecture
3183 switch ( fArchitecture
) {
3185 case CPU_TYPE_X86_64
:
3186 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
3187 #ifdef DEFAULT_MACOSX_MIN_VERSION
3188 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION
);
3189 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
3191 warning("-macosx_version_min not specified, assuming 10.6");
3192 fMacVersionMin
= ld::mac10_6
;
3197 if ( (fOutputKind
!= Options::kObjectFile
) && (fOutputKind
!= Options::kPreload
) ) {
3198 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
3199 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION
);
3200 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION
);
3201 #elif defined(DEFAULT_MACOSX_MIN_VERSION)
3202 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION
);
3203 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION
);
3205 warning("-macosx_version_min not specified, assuming 10.6");
3206 fMacVersionMin
= ld::mac10_6
;
3211 // architecture will be infered ;ater by examining .o files
3218 // adjust min based on architecture
3219 switch ( fArchitecture
) {
3221 if ( (fMacVersionMin
< ld::mac10_4
) && (fIOSVersionMin
== ld::iOSVersionUnset
) ) {
3222 //warning("-macosx_version_min should be 10.4 or later for i386");
3223 fMacVersionMin
= ld::mac10_4
;
3226 case CPU_TYPE_X86_64
:
3227 if ( (fMacVersionMin
< ld::mac10_4
) && (fIOSVersionMin
== ld::iOSVersionUnset
) ) {
3228 //warning("-macosx_version_min should be 10.4 or later for x86_64");
3229 fMacVersionMin
= ld::mac10_4
;
3234 // default to adding functions start for dynamic code, static code must opt-in
3235 switch ( fOutputKind
) {
3236 case Options::kPreload
:
3237 case Options::kStaticExecutable
:
3238 case Options::kKextBundle
:
3239 if ( fDataInCodeInfoLoadCommandForcedOn
)
3240 fDataInCodeInfoLoadCommand
= true;
3241 if ( fFunctionStartsForcedOn
)
3242 fFunctionStartsLoadCommand
= true;
3244 case Options::kObjectFile
:
3245 case Options::kDynamicExecutable
:
3246 case Options::kDyld
:
3247 case Options::kDynamicLibrary
:
3248 case Options::kDynamicBundle
:
3249 if ( !fDataInCodeInfoLoadCommandForcedOff
)
3250 fDataInCodeInfoLoadCommand
= true;
3251 if ( !fFunctionStartsForcedOff
)
3252 fFunctionStartsLoadCommand
= true;
3256 // adjust kext type based on architecture
3257 if ( fOutputKind
== kKextBundle
) {
3258 switch ( fArchitecture
) {
3259 case CPU_TYPE_X86_64
:
3260 // x86_64 uses new MH_KEXT_BUNDLE type
3261 fMakeCompressedDyldInfo
= false;
3262 fMakeCompressedDyldInfoForceOff
= true;
3263 fAllowTextRelocs
= true;
3264 fUndefinedTreatment
= kUndefinedDynamicLookup
;
3267 if ( fIOSVersionMin
>= ld::iOS_5_0
) {
3268 // iOS 5.0 and later use new MH_KEXT_BUNDLE type
3269 fMakeCompressedDyldInfo
= false;
3270 fMakeCompressedDyldInfoForceOff
= true;
3271 // kexts are PIC in iOS 6.0 and later
3272 fAllowTextRelocs
= (fIOSVersionMin
< ld::iOS_6_0
);
3273 fKextsUseStubs
= !fAllowTextRelocs
;
3274 fUndefinedTreatment
= kUndefinedDynamicLookup
;
3277 // else use object file
3280 fOutputKind
= kObjectFile
;
3285 // disable implicit dylibs when targeting 10.3
3286 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
3287 if ( !minOS(ld::mac10_4
, ld::iOS_2_0
) )
3288 fImplicitlyLinkPublicDylibs
= false;
3291 // allow build system to force linker to ignore -prebind
3292 if ( getenv("LD_FORCE_NO_PREBIND") != NULL
)
3295 // allow build system to force linker to ignore -seg_addr_table
3296 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL
)
3297 fSegAddrTablePath
= NULL
;
3299 // check for base address specified externally
3300 if ( (fSegAddrTablePath
!= NULL
) && (fOutputKind
== Options::kDynamicLibrary
) ) {
3301 parseSegAddrTable(fSegAddrTablePath
, this->installPath());
3302 // HACK to support seg_addr_table entries that are physical paths instead of install paths
3303 if ( fBaseAddress
== 0 ) {
3304 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
3305 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.4.dylib");
3306 if ( fBaseAddress
== 0 )
3307 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.9.dylib");
3310 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
3311 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libz.1.2.3.dylib");
3313 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
3314 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libutil1.0.dylib");
3318 // split segs only allowed for dylibs
3320 // split seg only supported for i386, and arm.
3321 switch ( fArchitecture
) {
3323 if ( fOutputKind
!= Options::kDynamicLibrary
)
3325 // make sure read and write segments are proper distance apart
3326 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x10000000) )
3327 fBaseWritableAddress
= fBaseAddress
+ 0x10000000;
3330 if ( fOutputKind
!= Options::kDynamicLibrary
) {
3334 // make sure read and write segments are proper distance apart
3335 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x08000000) )
3336 fBaseWritableAddress
= fBaseAddress
+ 0x08000000;
3342 fBaseWritableAddress
= 0;
3346 // set too-large size
3347 switch ( fArchitecture
) {
3349 fMaxAddress
= 0xFFFFFFFF;
3351 case CPU_TYPE_X86_64
:
3354 switch ( fOutputKind
) {
3355 case Options::kDynamicExecutable
:
3356 case Options::kDynamicLibrary
:
3357 case Options::kDynamicBundle
:
3358 // user land code is limited to low 1GB
3359 fMaxAddress
= 0x2FFFFFFF;
3361 case Options::kStaticExecutable
:
3362 case Options::kObjectFile
:
3363 case Options::kDyld
:
3364 case Options::kPreload
:
3365 case Options::kKextBundle
:
3366 fMaxAddress
= 0xFFFFFFFF;
3369 // range check -seg1addr for ARM
3370 if ( fBaseAddress
> fMaxAddress
) {
3371 warning("ignoring -seg1addr 0x%08llX. Address out of range.", fBaseAddress
);
3377 // <rdar://problem/6138961> -r implies no prebinding for all architectures
3378 if ( fOutputKind
== Options::kObjectFile
)
3381 // disable prebinding depending on arch and min OS version
3383 switch ( fArchitecture
) {
3385 if ( fMacVersionMin
== ld::mac10_4
) {
3386 // in 10.4 only split seg dylibs are prebound
3387 if ( (fOutputKind
!= Options::kDynamicLibrary
) || ! fSplitSegs
)
3390 else if ( fMacVersionMin
>= ld::mac10_5
) {
3391 // in 10.5 nothing is prebound
3394 else if ( fIOSVersionMin
!= ld::iOSVersionUnset
) {
3395 // nothing in simulator is prebound
3399 // in 10.3 and earlier only dylibs and main executables could be prebound
3400 switch ( fOutputKind
) {
3401 case Options::kDynamicExecutable
:
3402 case Options::kDynamicLibrary
:
3403 // only main executables and dylibs can be prebound
3405 case Options::kStaticExecutable
:
3406 case Options::kDynamicBundle
:
3407 case Options::kObjectFile
:
3408 case Options::kDyld
:
3409 case Options::kPreload
:
3410 case Options::kKextBundle
:
3411 // disable prebinding for everything else
3417 case CPU_TYPE_X86_64
:
3421 switch ( fOutputKind
) {
3422 case Options::kDynamicExecutable
:
3423 case Options::kDynamicLibrary
:
3424 // only main executables and dylibs can be prebound
3426 case Options::kStaticExecutable
:
3427 case Options::kDynamicBundle
:
3428 case Options::kObjectFile
:
3429 case Options::kDyld
:
3430 case Options::kPreload
:
3431 case Options::kKextBundle
:
3432 // disable prebinding for everything else
3440 // only prebound images can be split-seg
3441 if ( fSplitSegs
&& !fPrebind
)
3444 // determine if info for shared region should be added
3445 if ( fOutputKind
== Options::kDynamicLibrary
) {
3446 if ( minOS(ld::mac10_5
, ld::iOS_3_1
) )
3448 if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
3449 || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
3450 fSharedRegionEligible
= true;
3452 else if ( fOutputKind
== Options::kDyld
) {
3453 // <rdar://problem/10111122> Enable dyld to be put into the dyld shared cache
3454 fSharedRegionEligible
= true;
3457 // figure out if module table is needed for compatibility with old ld/dyld
3458 if ( fOutputKind
== Options::kDynamicLibrary
) {
3459 switch ( fArchitecture
) {
3461 if ( fIOSVersionMin
!= ld::iOSVersionUnset
) // simulator never needs modules
3465 fNeedsModuleTable
= true; // redo_prebinding requires a module table
3470 // <rdar://problem/5366363> -r -x implies -S
3471 if ( (fOutputKind
== Options::kObjectFile
) && (fLocalSymbolHandling
== kLocalSymbolsNone
) )
3472 fDebugInfoStripping
= Options::kDebugInfoNone
;
3474 // choose how to process unwind info
3475 switch ( fArchitecture
) {
3477 case CPU_TYPE_X86_64
:
3478 switch ( fOutputKind
) {
3479 case Options::kObjectFile
:
3480 case Options::kStaticExecutable
:
3481 case Options::kPreload
:
3482 case Options::kKextBundle
:
3483 fAddCompactUnwindEncoding
= false;
3485 case Options::kDyld
:
3486 case Options::kDynamicLibrary
:
3487 case Options::kDynamicBundle
:
3488 case Options::kDynamicExecutable
:
3489 //if ( fAddCompactUnwindEncoding && (fVersionMin >= ld::mac10_6) )
3490 // fRemoveDwarfUnwindIfCompactExists = true;
3495 fAddCompactUnwindEncoding
= false;
3496 fRemoveDwarfUnwindIfCompactExists
= false;
3499 // if -arch is missing, assume we don't want compact unwind info
3500 fAddCompactUnwindEncoding
= false;
3504 // only ARM main executables can be encrypted
3505 if ( fOutputKind
!= Options::kDynamicExecutable
)
3506 fEncryptable
= false;
3507 if ( fArchitecture
!= CPU_TYPE_ARM
)
3508 fEncryptable
= false;
3510 // don't move inits in dyld because dyld wants certain
3511 // entries point at stable locations at the start of __text
3512 if ( fOutputKind
== Options::kDyld
)
3513 fAutoOrderInitializers
= false;
3516 // disable __data ordering for some output kinds
3517 switch ( fOutputKind
) {
3518 case Options::kObjectFile
:
3519 case Options::kDyld
:
3520 case Options::kStaticExecutable
:
3521 case Options::kPreload
:
3522 case Options::kKextBundle
:
3525 case Options::kDynamicExecutable
:
3526 case Options::kDynamicLibrary
:
3527 case Options::kDynamicBundle
:
3531 // only use compressed LINKEDIT for final linked images
3532 switch ( fOutputKind
) {
3533 case Options::kDynamicExecutable
:
3534 case Options::kDynamicLibrary
:
3535 case Options::kDynamicBundle
:
3537 case Options::kPreload
:
3538 case Options::kStaticExecutable
:
3539 case Options::kObjectFile
:
3540 case Options::kDyld
:
3541 case Options::kKextBundle
:
3542 fMakeCompressedDyldInfoForceOff
= true;
3545 if ( fMakeCompressedDyldInfoForceOff
)
3546 fMakeCompressedDyldInfo
= false;
3549 // only use compressed LINKEDIT for:
3550 // Mac OS X 10.6 or later
3552 if ( fMakeCompressedDyldInfo
) {
3553 if ( !minOS(ld::mac10_6
, ld::iOS_3_1
) )
3554 fMakeCompressedDyldInfo
= false;
3558 // only ARM enforces that cpu-sub-types must match
3559 if ( fArchitecture
!= CPU_TYPE_ARM
)
3560 fAllowCpuSubtypeMismatches
= true;
3562 // only final linked images can not optimize zero fill sections
3563 if ( fOutputKind
== Options::kObjectFile
)
3564 fOptimizeZeroFill
= true;
3566 // all undefines in -r mode
3567 // if ( fOutputKind == Options::kObjectFile )
3568 // fUndefinedTreatment = kUndefinedSuppress;
3570 // only dynamic final linked images should warn about use of commmons
3571 if ( fWarnCommons
) {
3572 switch ( fOutputKind
) {
3573 case Options::kDynamicExecutable
:
3574 case Options::kDynamicLibrary
:
3575 case Options::kDynamicBundle
:
3577 case Options::kPreload
:
3578 case Options::kStaticExecutable
:
3579 case Options::kObjectFile
:
3580 case Options::kDyld
:
3581 case Options::kKextBundle
:
3582 fWarnCommons
= false;
3587 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
3588 if ( minOS(ld::mac10_5
, ld::iOS_2_0
) )
3589 fUseSimplifiedDylibReExports
= true;
3591 // Mac OS X 10.7 and iOS 4.2 support LC_LOAD_UPWARD_DYLIB
3592 if ( minOS(ld::mac10_7
, ld::iOS_4_2
) && (fOutputKind
== kDynamicLibrary
) )
3593 fCanUseUpwardDylib
= true;
3595 // MacOSX 10.7 defaults to PIE
3596 if ( ((fArchitecture
== CPU_TYPE_X86_64
) || (fArchitecture
== CPU_TYPE_I386
))
3597 && (fOutputKind
== kDynamicExecutable
)
3598 && (fMacVersionMin
>= ld::mac10_7
) ) {
3599 fPositionIndependentExecutable
= true;
3602 // armv7 for iOS4.3 defaults to PIE
3603 if ( (fArchitecture
== CPU_TYPE_ARM
)
3604 && fArchSupportsThumb2
3605 && (fOutputKind
== kDynamicExecutable
)
3606 && (fIOSVersionMin
>= ld::iOS_4_3
) ) {
3607 fPositionIndependentExecutable
= true;
3610 // -no_pie anywhere on command line disable PIE
3611 if ( fDisablePositionIndependentExecutable
)
3612 fPositionIndependentExecutable
= false;
3614 // set fOutputSlidable
3615 switch ( fOutputKind
) {
3616 case Options::kObjectFile
:
3617 fOutputSlidable
= false;
3619 case Options::kStaticExecutable
:
3620 case Options::kDynamicExecutable
:
3621 fOutputSlidable
= fPositionIndependentExecutable
;
3623 case Options::kPreload
:
3624 fOutputSlidable
= fPIEOnCommandLine
;
3626 case Options::kDyld
:
3627 case Options::kDynamicLibrary
:
3628 case Options::kDynamicBundle
:
3629 case Options::kKextBundle
:
3630 fOutputSlidable
= true;
3634 // let linker know if thread local variables are supported
3635 if ( fMacVersionMin
>= ld::mac10_7
) {
3639 // default to adding version load command for dynamic code, static code must opt-in
3640 switch ( fOutputKind
) {
3641 case Options::kObjectFile
:
3642 fVersionLoadCommand
= false;
3644 case Options::kStaticExecutable
:
3645 case Options::kPreload
:
3646 case Options::kKextBundle
:
3647 if ( fVersionLoadCommandForcedOn
)
3648 fVersionLoadCommand
= true;
3650 case Options::kDynamicExecutable
:
3651 case Options::kDyld
:
3652 case Options::kDynamicLibrary
:
3653 case Options::kDynamicBundle
:
3654 if ( !fVersionLoadCommandForcedOff
)
3655 fVersionLoadCommand
= true;
3656 // <rdar://problem/9945513> for now, don't create version load commands for iOS simulator builds
3657 if ( fVersionLoadCommand
&& (fArchitecture
== CPU_TYPE_I386
) ) {
3658 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
3659 if ( strstr(*sdkit
, "/iPhoneSimulator.platform/") != NULL
)
3660 fVersionLoadCommand
= false;
3666 // support re-export of individual symbols in MacOSX 10.7 and iOS 4.2
3667 if ( (fOutputKind
== kDynamicLibrary
) && minOS(ld::mac10_7
, ld::iOS_4_2
) )
3668 fCanReExportSymbols
= true;
3670 // ObjC optimization is only in dynamic final linked images
3671 switch ( fOutputKind
) {
3672 case Options::kObjectFile
:
3673 case Options::kStaticExecutable
:
3674 case Options::kPreload
:
3675 case Options::kKextBundle
:
3676 case Options::kDyld
:
3677 fObjcCategoryMerging
= false;
3679 case Options::kDynamicExecutable
:
3680 case Options::kDynamicLibrary
:
3681 case Options::kDynamicBundle
:
3685 // i386 main executables linked on Mac OS X 10.7 default to NX heap
3686 // regardless of target unless overriden with -allow_heap_execute anywhere
3687 // on the command line
3688 if ( (fArchitecture
== CPU_TYPE_I386
) && (fOutputKind
== kDynamicExecutable
) && !fDisableNonExecutableHeap
)
3689 fNonExecutableHeap
= true;
3691 // Use LC_MAIN instead of LC_UNIXTHREAD for newer OSs
3692 switch ( fOutputKind
) {
3693 case Options::kDynamicExecutable
:
3694 if ( fEntryPointLoadCommandForceOn
) {
3695 fEntryPointLoadCommand
= true;
3696 fEntryName
= "_main";
3698 else if ( fEntryPointLoadCommandForceOff
) {
3699 fNeedsThreadLoadCommand
= true;
3702 if ( (fIOSVersionMin
!= ld::iOSVersionUnset
) && (fArchitecture
== CPU_TYPE_I386
) ) {
3703 // don't use LC_MAIN for simulator until min host OS is 10.8 for simulator
3704 fNeedsThreadLoadCommand
= true;
3705 fEntryPointLoadCommand
= false;
3707 else if ( minOS(ld::mac10_8
, ld::iOS_6_0
) ) {
3708 fEntryPointLoadCommand
= true;
3709 fEntryName
= "_main";
3712 fNeedsThreadLoadCommand
= true;
3715 case Options::kObjectFile
:
3716 case Options::kKextBundle
:
3717 case Options::kDynamicLibrary
:
3718 case Options::kDynamicBundle
:
3721 case Options::kStaticExecutable
:
3722 case Options::kPreload
:
3723 case Options::kDyld
:
3724 fNeedsThreadLoadCommand
= true;
3728 // add LC_SOURCE_VERSION
3729 switch ( fOutputKind
) {
3730 case Options::kDynamicExecutable
:
3731 case Options::kKextBundle
:
3732 case Options::kDynamicLibrary
:
3733 case Options::kDynamicBundle
:
3734 case Options::kDyld
:
3735 case Options::kStaticExecutable
:
3736 if ( fSourceVersionLoadCommandForceOn
) {
3737 fSourceVersionLoadCommand
= true;
3739 else if ( fSourceVersionLoadCommandForceOff
) {
3740 fSourceVersionLoadCommand
= false;
3743 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) ) {
3744 fSourceVersionLoadCommand
= true;
3747 fSourceVersionLoadCommand
= false;
3750 case Options::kObjectFile
:
3751 case Options::kPreload
:
3752 fSourceVersionLoadCommand
= false;
3757 // add LC_DYLIB_CODE_SIGN_DRS
3758 switch ( fOutputKind
) {
3759 case Options::kDynamicExecutable
:
3760 case Options::kDynamicLibrary
:
3761 case Options::kDynamicBundle
:
3762 if ( fDependentDRInfoForcedOn
) {
3763 fDependentDRInfo
= true;
3765 else if ( fDependentDRInfoForcedOff
) {
3766 fDependentDRInfo
= false;
3769 if ( minOS(ld::mac10_8
, ld::iOS_6_0
) )
3770 fDependentDRInfo
= true;
3772 fDependentDRInfo
= false;
3775 case Options::kKextBundle
:
3776 case Options::kDyld
:
3777 case Options::kStaticExecutable
:
3778 case Options::kObjectFile
:
3779 case Options::kPreload
:
3780 fDependentDRInfo
= false;
3784 // if -sdk_version not on command line, infer from -syslibroot
3785 if ( (fSDKVersion
== 0) && (fSDKPaths
.size() > 0) ) {
3786 const char* sdkPath
= fSDKPaths
.front();
3787 const char* end
= &sdkPath
[strlen(sdkPath
)-1];
3788 while ( !isdigit(*end
) && (end
> sdkPath
) )
3790 const char* start
= end
-1;
3791 while ( (isdigit(*start
) || (*start
== '.')) && (start
> sdkPath
))
3793 char sdkVersionStr
[32];
3794 int len
= end
-start
+1;
3796 strlcpy(sdkVersionStr
, start
+1, len
);
3797 fSDKVersion
= parseVersionNumber32(sdkVersionStr
);
3801 // if -sdk_version and -syslibroot not used, but targeting MacOSX, use current OS version
3802 if ( (fSDKVersion
== 0) && (fMacVersionMin
!= ld::macVersionUnset
) ) {
3803 // special case if RC_ProjectName and MACOSX_DEPLOYMENT_TARGET are both set that sdkversion=minos
3804 if ( getenv("RC_ProjectName") && getenv("MACOSX_DEPLOYMENT_TARGET") ) {
3805 fSDKVersion
= fMacVersionMin
;
3808 int mib
[2] = { CTL_KERN
, KERN_OSRELEASE
};
3809 char kernVersStr
[100];
3810 size_t strlen
= sizeof(kernVersStr
);
3811 if ( sysctl(mib
, 2, kernVersStr
, &strlen
, NULL
, 0) != -1 ) {
3812 uint32_t kernVers
= parseVersionNumber32(kernVersStr
);
3813 int minor
= (kernVers
>> 16) - 4; // kernel major version is 4 ahead of x in 10.x
3814 fSDKVersion
= 0x000A0000 + (minor
<< 8);
3821 void Options::checkIllegalOptionCombinations()
3823 // check -undefined setting
3824 switch ( fUndefinedTreatment
) {
3825 case kUndefinedError
:
3826 case kUndefinedDynamicLookup
:
3829 case kUndefinedWarning
:
3830 case kUndefinedSuppress
:
3831 // requires flat namespace
3832 if ( fNameSpace
== kTwoLevelNameSpace
)
3833 throw "can't use -undefined warning or suppress with -twolevel_namespace";
3837 // unify -sub_umbrella with dylibs
3838 for (std::vector
<const char*>::iterator it
= fSubUmbellas
.begin(); it
!= fSubUmbellas
.end(); it
++) {
3839 const char* subUmbrella
= *it
;
3841 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
3842 Options::FileInfo
& info
= *fit
;
3843 const char* lastSlash
= strrchr(info
.path
, '/');
3844 if ( lastSlash
== NULL
)
3845 lastSlash
= info
.path
- 1;
3846 if ( strcmp(&lastSlash
[1], subUmbrella
) == 0 ) {
3847 info
.options
.fReExport
= true;
3849 fLinkSnapshot
.recordSubUmbrella(info
.path
);
3854 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella
);
3857 // unify -sub_library with dylibs
3858 for (std::vector
<const char*>::iterator it
= fSubLibraries
.begin(); it
!= fSubLibraries
.end(); it
++) {
3859 const char* subLibrary
= *it
;
3861 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
3862 Options::FileInfo
& info
= *fit
;
3863 const char* lastSlash
= strrchr(info
.path
, '/');
3864 if ( lastSlash
== NULL
)
3865 lastSlash
= info
.path
- 1;
3866 const char* dot
= strchr(&lastSlash
[1], '.');
3868 dot
= &lastSlash
[strlen(lastSlash
)];
3869 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
3870 info
.options
.fReExport
= true;
3872 fLinkSnapshot
.recordSubLibrary(info
.path
);
3877 warning("-sub_library %s does not match a supplied dylib", subLibrary
);
3880 // sync reader options
3881 if ( fNameSpace
!= kTwoLevelNameSpace
)
3882 fFlatNamespace
= true;
3884 // check -stack_addr
3885 if ( fStackAddr
!= 0 ) {
3886 switch (fArchitecture
) {
3889 if ( fStackAddr
> 0xFFFFFFFF )
3890 throw "-stack_addr must be < 4G for 32-bit processes";
3892 case CPU_TYPE_X86_64
:
3895 if ( (fStackAddr
& -4096) != fStackAddr
)
3896 throw "-stack_addr must be multiples of 4K";
3897 if ( fStackSize
== 0 )
3898 throw "-stack_addr must be used with -stack_size";
3901 // check -stack_size
3902 if ( fStackSize
!= 0 ) {
3903 switch (fArchitecture
) {
3905 if ( fStackSize
> 0xFFFFFFFF )
3906 throw "-stack_size must be < 4G for 32-bit processes";
3907 if ( fStackAddr
== 0 ) {
3908 fStackAddr
= 0xC0000000;
3910 if ( (fStackAddr
> 0xB0000000) && ((fStackAddr
-fStackSize
) < 0xB0000000) )
3911 warning("custom stack placement overlaps and will disable shared region");
3914 if ( fStackSize
> 0x2F000000 )
3915 throw "-stack_size must be < 752MB";
3916 if ( fStackAddr
== 0 )
3917 fStackAddr
= 0x2F000000;
3918 if ( fStackAddr
> 0x30000000)
3919 throw "-stack_addr must be < 0x30000000 for arm";
3920 case CPU_TYPE_X86_64
:
3921 if ( fStackAddr
== 0 ) {
3922 fStackAddr
= 0x00007FFF5C000000LL
;
3926 if ( (fStackSize
& -4096) != fStackSize
)
3927 throw "-stack_size must be multiples of 4K";
3928 switch ( fOutputKind
) {
3929 case Options::kDynamicExecutable
:
3930 case Options::kStaticExecutable
:
3931 // custom stack size only legal when building main executable
3933 case Options::kDynamicLibrary
:
3934 case Options::kDynamicBundle
:
3935 case Options::kObjectFile
:
3936 case Options::kDyld
:
3937 case Options::kPreload
:
3938 case Options::kKextBundle
:
3939 throw "-stack_size option can only be used when linking a main executable";
3941 if ( fStackSize
> fStackAddr
)
3942 throwf("-stack_size (0x%08llX) must be smaller than -stack_addr (0x%08llX)", fStackSize
, fStackAddr
);
3945 // check that -allow_stack_execute is only used with main executables
3946 if ( fExecutableStack
) {
3947 switch ( fOutputKind
) {
3948 case Options::kDynamicExecutable
:
3949 case Options::kStaticExecutable
:
3950 // -allow_stack_execute size only legal when building main executable
3952 case Options::kDynamicLibrary
:
3953 case Options::kDynamicBundle
:
3954 case Options::kObjectFile
:
3955 case Options::kDyld
:
3956 case Options::kPreload
:
3957 case Options::kKextBundle
:
3958 throw "-allow_stack_execute option can only be used when linking a main executable";
3962 // check that -allow_heap_execute is only used with i386 main executables
3963 if ( fDisableNonExecutableHeap
) {
3964 if ( fArchitecture
!= CPU_TYPE_I386
)
3965 throw "-allow_heap_execute option can only be used when linking for i386";
3966 switch ( fOutputKind
) {
3967 case Options::kDynamicExecutable
:
3968 // -allow_heap_execute only legal when building main executable
3970 case Options::kStaticExecutable
:
3971 case Options::kDynamicLibrary
:
3972 case Options::kDynamicBundle
:
3973 case Options::kObjectFile
:
3974 case Options::kDyld
:
3975 case Options::kPreload
:
3976 case Options::kKextBundle
:
3977 throw "-allow_heap_execute option can only be used when linking a main executable";
3981 // check -client_name is only used when making a bundle or main executable
3982 if ( fClientName
!= NULL
) {
3983 switch ( fOutputKind
) {
3984 case Options::kDynamicExecutable
:
3985 case Options::kDynamicBundle
:
3987 case Options::kStaticExecutable
:
3988 case Options::kDynamicLibrary
:
3989 case Options::kObjectFile
:
3990 case Options::kDyld
:
3991 case Options::kPreload
:
3992 case Options::kKextBundle
:
3993 throw "-client_name can only be used with -bundle";
3997 // check -init is only used when building a dylib
3998 if ( (fInitFunctionName
!= NULL
) && (fOutputKind
!= Options::kDynamicLibrary
) )
3999 throw "-init can only be used with -dynamiclib";
4001 // check -bundle_loader only used with -bundle
4002 if ( (fBundleLoader
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
4003 throw "-bundle_loader can only be used with -bundle";
4005 // check -dtrace not used with -r
4006 if ( (fDtraceScriptName
!= NULL
) && (fOutputKind
== Options::kObjectFile
) )
4007 throw "-dtrace can only be used when creating final linked images";
4009 // check -d can only be used with -r
4010 if ( fMakeTentativeDefinitionsReal
&& (fOutputKind
!= Options::kObjectFile
) )
4011 throw "-d can only be used with -r";
4013 // check that -root_safe is not used with -r
4014 if ( fRootSafe
&& (fOutputKind
== Options::kObjectFile
) )
4015 throw "-root_safe cannot be used with -r";
4017 // check that -setuid_safe is not used with -r
4018 if ( fSetuidSafe
&& (fOutputKind
== Options::kObjectFile
) )
4019 throw "-setuid_safe cannot be used with -r";
4021 // rdar://problem/4718189 map ObjC class names to new runtime names
4022 bool alterObjC1ClassNamesToObjC2
= false;
4023 switch (fArchitecture
) {
4025 // i386 only uses new symbols when using objc2 ABI
4026 if ( fObjCABIVersion2Override
)
4027 alterObjC1ClassNamesToObjC2
= true;
4029 case CPU_TYPE_X86_64
:
4031 alterObjC1ClassNamesToObjC2
= true;
4035 // make sure all required exported symbols exist
4036 std::vector
<const char*> impliedExports
;
4037 for (NameSet::iterator it
=fExportSymbols
.regularBegin(); it
!= fExportSymbols
.regularEnd(); ++it
) {
4038 const char* name
= *it
;
4039 const int len
= strlen(name
);
4040 if ( (strcmp(&name
[len
-3], ".eh") == 0) || (strncmp(name
, ".objc_category_name_", 20) == 0) ) {
4041 // never export .eh symbols
4042 warning("ignoring %s in export list", name
);
4044 else if ( (fArchitecture
== CPU_TYPE_I386
) && !fObjCABIVersion2Override
&& (strncmp(name
, "_OBJC_CLASS_$", 13) == 0) ) {
4045 warning("ignoring Objc2 Class symbol %s in i386 export list", name
);
4046 fRemovedExports
.insert(name
);
4048 else if ( alterObjC1ClassNamesToObjC2
&& (strncmp(name
, ".objc_class_name_", 17) == 0) ) {
4049 // linking ObjC2 ABI, but have ObjC1 ABI name in export list. Change it to intended name
4050 fRemovedExports
.insert(name
);
4052 asprintf(&temp
, "_OBJC_CLASS_$_%s", &name
[17]);
4053 impliedExports
.push_back(temp
);
4054 asprintf(&temp
, "_OBJC_METACLASS_$_%s", &name
[17]);
4055 impliedExports
.push_back(temp
);
4058 fInitialUndefines
.push_back(name
);
4061 fExportSymbols
.remove(fRemovedExports
);
4062 for (std::vector
<const char*>::iterator it
=impliedExports
.begin(); it
!= impliedExports
.end(); ++it
) {
4063 const char* name
= *it
;
4064 fExportSymbols
.insert(name
);
4065 fInitialUndefines
.push_back(name
);
4068 // make sure all required re-exported symbols exist
4069 for (NameSet::iterator it
=fReExportSymbols
.regularBegin(); it
!= fReExportSymbols
.regularEnd(); ++it
) {
4070 fInitialUndefines
.push_back(*it
);
4073 // make sure that -init symbol exists
4074 if ( fInitFunctionName
!= NULL
)
4075 fInitialUndefines
.push_back(fInitFunctionName
);
4077 // make sure that entry symbol exists
4078 switch ( fOutputKind
) {
4079 case Options::kDynamicExecutable
:
4080 case Options::kStaticExecutable
:
4081 case Options::kDyld
:
4082 case Options::kPreload
:
4083 fInitialUndefines
.push_back(fEntryName
);
4085 case Options::kDynamicLibrary
:
4086 case Options::kDynamicBundle
:
4087 case Options::kObjectFile
:
4088 case Options::kKextBundle
:
4092 // make sure every alias base exists
4093 for (std::vector
<AliasPair
>::iterator it
=fAliases
.begin(); it
!= fAliases
.end(); ++it
) {
4094 fInitialUndefines
.push_back(it
->realName
);
4097 // check custom segments
4098 if ( fCustomSegmentAddresses
.size() != 0 ) {
4099 // verify no segment is in zero page
4100 if ( fZeroPageSize
!= ULLONG_MAX
) {
4101 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
4102 if ( it
->address
< fZeroPageSize
)
4103 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it
->name
, it
->address
);
4106 // verify no duplicates
4107 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
4108 for (std::vector
<SegmentStart
>::iterator it2
= fCustomSegmentAddresses
.begin(); it2
!= fCustomSegmentAddresses
.end(); ++it2
) {
4109 if ( (it
->address
== it2
->address
) && (it
!= it2
) )
4110 throwf("duplicate -segaddr addresses for %s and %s", it
->name
, it2
->name
);
4112 // a custom segment address of zero will disable the use of a zero page
4113 if ( it
->address
== 0 )
4118 if ( fZeroPageSize
== ULLONG_MAX
) {
4119 // zero page size not specified on command line, set default
4120 switch (fArchitecture
) {
4123 // first 4KB for 32-bit architectures
4124 fZeroPageSize
= 0x1000;
4126 case CPU_TYPE_X86_64
:
4127 // first 4GB for x86_64 on all OS's
4128 fZeroPageSize
= 0x100000000ULL
;
4131 // if -arch not used, default to 4K zero-page
4132 fZeroPageSize
= 0x1000;
4136 switch ( fOutputKind
) {
4137 case Options::kDynamicExecutable
:
4138 case Options::kStaticExecutable
:
4139 // -pagezero_size size only legal when building main executable
4141 case Options::kDynamicLibrary
:
4142 case Options::kDynamicBundle
:
4143 case Options::kObjectFile
:
4144 case Options::kDyld
:
4145 case Options::kPreload
:
4146 case Options::kKextBundle
:
4147 if ( fZeroPageSize
!= 0 )
4148 throw "-pagezero_size option can only be used when linking a main executable";
4152 // if main executable with custom base address, model zero page as custom segment
4153 if ( (fOutputKind
== Options::kDynamicExecutable
) && (fBaseAddress
!= 0) && (fZeroPageSize
!= 0) ) {
4155 seg
.name
= "__PAGEZERO";
4157 fCustomSegmentAddresses
.push_back(seg
);
4160 // -dead_strip and -r are incompatible
4161 if ( fDeadStrip
&& (fOutputKind
== Options::kObjectFile
) )
4162 throw "-r and -dead_strip cannot be used together";
4164 // can't use -rpath unless targeting 10.5 or later
4165 if ( fRPaths
.size() > 0 ) {
4166 if ( !minOS(ld::mac10_5
, ld::iOS_2_0
) )
4167 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
4168 switch ( fOutputKind
) {
4169 case Options::kDynamicExecutable
:
4170 case Options::kDynamicLibrary
:
4171 case Options::kDynamicBundle
:
4173 case Options::kStaticExecutable
:
4174 case Options::kObjectFile
:
4175 case Options::kDyld
:
4176 case Options::kPreload
:
4177 case Options::kKextBundle
:
4178 throw "-rpath can only be used when creating a dynamic final linked image";
4182 if ( fPositionIndependentExecutable
) {
4183 switch ( fOutputKind
) {
4184 case Options::kDynamicExecutable
:
4185 // check -pie is only used when building a dynamic main executable for 10.5
4186 if ( !minOS(ld::mac10_5
, ld::iOS_4_2
) ) {
4187 if ( fIOSVersionMin
== ld::iOSVersionUnset
)
4188 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
4190 throw "-pie can only be used when targeting iOS 4.2 or later";
4193 case Options::kStaticExecutable
:
4194 case Options::kPreload
:
4195 // -pie is ok with -static or -preload
4197 case Options::kDynamicLibrary
:
4198 case Options::kDynamicBundle
:
4199 warning("-pie being ignored. It is only used when linking a main executable");
4200 fPositionIndependentExecutable
= false;
4202 case Options::kObjectFile
:
4203 case Options::kDyld
:
4204 case Options::kKextBundle
:
4205 throw "-pie can only be used when linking a main executable";
4209 // check -read_only_relocs is not used with x86_64
4210 if ( fAllowTextRelocs
) {
4211 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
!= kKextBundle
) ) {
4212 warning("-read_only_relocs cannot be used with x86_64");
4213 fAllowTextRelocs
= false;
4217 // check -mark_auto_dead_strip is only used with dylibs
4218 if ( fMarkDeadStrippableDylib
) {
4219 if ( fOutputKind
!= Options::kDynamicLibrary
) {
4220 warning("-mark_auto_dead_strip can only be used when creating a dylib");
4221 fMarkDeadStrippableDylib
= false;
4225 // -force_cpusubtype_ALL is not supported for ARM
4226 if ( fForceSubtypeAll
) {
4227 if ( fArchitecture
== CPU_TYPE_ARM
) {
4228 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
4232 // -reexported_symbols_list can only be used with -dynamiclib
4233 if ( !fReExportSymbols
.empty() ) {
4234 if ( fOutputKind
!= Options::kDynamicLibrary
)
4235 throw "-reexported_symbols_list can only used used when created dynamic libraries";
4236 if ( !minOS(ld::mac10_7
, ld::iOS_4_2
) )
4237 throw "targeted OS version does not support -reexported_symbols_list";
4240 // -dyld_env can only be used with main executables
4241 if ( (fOutputKind
!= Options::kDynamicExecutable
) && (fDyldEnvironExtras
.size() != 0) )
4242 throw "-dyld_env can only used used when created main executables";
4246 void Options::checkForClassic(int argc
, const char* argv
[])
4249 bool archFound
= false;
4250 bool staticFound
= false;
4251 bool dtraceFound
= false;
4252 bool kextFound
= false;
4253 bool rFound
= false;
4254 bool creatingMachKernel
= false;
4255 bool newLinker
= false;
4257 // build command line buffer in case ld crashes
4258 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
4259 CRSetCrashLogMessage(crashreporterBuffer
);
4261 const char* srcRoot
= getenv("SRCROOT");
4262 if ( srcRoot
!= NULL
) {
4263 strlcpy(crashreporterBuffer
, "SRCROOT=", crashreporterBufferSize
);
4264 strlcat(crashreporterBuffer
, srcRoot
, crashreporterBufferSize
);
4265 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
4268 strlcat(crashreporterBuffer
, LD_VERS
, crashreporterBufferSize
);
4269 strlcat(crashreporterBuffer
, "\n", crashreporterBufferSize
);
4271 strlcat(crashreporterBuffer
, "ld ", crashreporterBufferSize
);
4272 for(int i
=1; i
< argc
; ++i
) {
4273 strlcat(crashreporterBuffer
, argv
[i
], crashreporterBufferSize
);
4274 strlcat(crashreporterBuffer
, " ", crashreporterBufferSize
);
4277 for(int i
=0; i
< argc
; ++i
) {
4278 const char* arg
= argv
[i
];
4279 if ( arg
[0] == '-' ) {
4280 if ( strcmp(arg
, "-arch") == 0 ) {
4281 parseArch(argv
[++i
]);
4284 else if ( strcmp(arg
, "-static") == 0 ) {
4287 else if ( strcmp(arg
, "-kext") == 0 ) {
4290 else if ( strcmp(arg
, "-dtrace") == 0 ) {
4293 else if ( strcmp(arg
, "-r") == 0 ) {
4296 else if ( strcmp(arg
, "-new_linker") == 0 ) {
4299 else if ( strcmp(arg
, "-classic_linker") == 0 ) {
4300 // ld_classic does not understand this option, so remove it
4301 for(int j
=i
; j
< argc
; ++j
)
4302 argv
[j
] = argv
[j
+1];
4303 warning("using ld_classic");
4304 this->gotoClassicLinker(argc
-1, argv
);
4306 else if ( strcmp(arg
, "-o") == 0 ) {
4307 const char* outfile
= argv
[++i
];
4308 if ( (outfile
!= NULL
) && (strstr(outfile
, "/mach_kernel") != NULL
) )
4309 creatingMachKernel
= true;
4315 void Options::gotoClassicLinker(int argc
, const char* argv
[])
4317 argv
[0] = "ld_classic";
4318 // ld_classic does not support -iphoneos_version_min, so change
4319 for(int j
=0; j
< argc
; ++j
) {
4320 if ( (strcmp(argv
[j
], "-iphoneos_version_min") == 0) || (strcmp(argv
[j
], "-ios_version_min") == 0) ) {
4321 argv
[j
] = "-macosx_version_min";
4327 // ld classic does not understand -kext (change to -static -r)
4328 for(int j
=0; j
< argc
; ++j
) {
4329 if ( strcmp(argv
[j
], "-kext") == 0)
4331 else if ( strcmp(argv
[j
], "-dynamic") == 0)
4332 argv
[j
] = "-static";
4334 // ld classic does not understand -demangle
4335 for(int j
=0; j
< argc
; ++j
) {
4336 if ( strcmp(argv
[j
], "-demangle") == 0)
4337 argv
[j
] = "-noprebind";
4339 // in -v mode, print command line passed to ld_classic
4340 for(int i
=0; i
< argc
; ++i
) {
4341 if ( strcmp(argv
[i
], "-v") == 0 ) {
4342 for(int j
=0; j
< argc
; ++j
)
4343 printf("%s ", argv
[j
]);
4348 char rawPath
[PATH_MAX
];
4349 char path
[PATH_MAX
];
4350 uint32_t bufSize
= PATH_MAX
;
4351 if ( _NSGetExecutablePath(rawPath
, &bufSize
) != -1 ) {
4352 if ( realpath(rawPath
, path
) != NULL
) {
4353 char* lastSlash
= strrchr(path
, '/');
4354 if ( lastSlash
!= NULL
) {
4355 strcpy(lastSlash
+1, "ld_classic");
4357 execvp(path
, (char**)argv
);
4361 // in case of error in above, try searching for ld_classic via PATH
4362 execvp(argv
[0], (char**)argv
);
4363 fprintf(stderr
, "can't exec ld_classic\n");
4368 // Note, returned string buffer is own by this function.
4369 // It should not be freed
4370 // It will be reused, so clients need to strdup() if they want
4371 // to use it long term.
4372 const char* Options::demangleSymbol(const char* sym
) const
4374 // only try to demangle symbols if -demangle on command line
4378 // only try to demangle symbols that look like C++ symbols
4379 if ( strncmp(sym
, "__Z", 3) != 0 )
4382 static size_t size
= 1024;
4383 static char* buff
= (char*)malloc(size
);
4386 char* result
= abi::__cxa_demangle(&sym
[1], buff
, &size
, &status
);
4387 if ( result
!= NULL
) {
4388 // if demangling successful, keep buffer for next demangle