253.3
[darwin-xtools.git] / ld64 / src / ld / Options.cpp
bloba638cb4c499696f805f50fda2e077bb46c2f5cea
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
12 * file.
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>
27 #include <sys/stat.h>
28 #include <mach/vm_prot.h>
29 #include <sys/sysctl.h>
30 #include <mach-o/dyld.h>
31 #include <fcntl.h>
32 #include <errno.h>
33 #include <string.h>
34 #include <spawn.h>
35 #include <cxxabi.h>
36 #include <Availability.h>
38 #include <vector>
39 #include <map>
40 #include <sstream>
42 #include "Options.h"
43 #include "Architectures.hpp"
44 #include "MachOFileAbstraction.hpp"
45 #include "Snapshot.h"
48 // from FunctionNameDemangle.h
49 extern "C" size_t fnd_get_demangled_name(const char *mangledName, char *outputBuffer, size_t length);
52 // upward dependency on lto::version()
53 namespace lto {
54 extern const char* version();
57 // magic to place command line in crash reports
58 const int crashreporterBufferSize = 2000;
59 static char crashreporterBuffer[crashreporterBufferSize];
60 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
61 #include <CrashReporterClient.h>
62 // hack until ld does not need to build on 10.6 anymore
63 struct crashreporter_annotations_t gCRAnnotations
64 __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION)))
65 = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 };
66 #else
67 extern "C" char* __crashreporter_info__;
68 __attribute__((used))
69 char* __crashreporter_info__ = crashreporterBuffer;
70 #endif
73 static bool sEmitWarnings = true;
74 static bool sFatalWarnings = false;
75 static const char* sWarningsSideFilePath = NULL;
76 static FILE* sWarningsSideFile = NULL;
77 static int sWarningsCount = 0;
79 void warning(const char* format, ...)
81 ++sWarningsCount;
82 if ( sEmitWarnings ) {
83 va_list list;
84 if ( sWarningsSideFilePath != NULL ) {
85 if ( sWarningsSideFile == NULL )
86 sWarningsSideFile = fopen(sWarningsSideFilePath, "a");
88 va_start(list, format);
89 fprintf(stderr, "ld: warning: ");
90 vfprintf(stderr, format, list);
91 fprintf(stderr, "\n");
92 if ( sWarningsSideFile != NULL ) {
93 fprintf(sWarningsSideFile, "ld: warning: ");
94 vfprintf(sWarningsSideFile, format, list);
95 fprintf(sWarningsSideFile, "\n");
96 fflush(sWarningsSideFile);
98 va_end(list);
102 void throwf(const char* format, ...)
104 va_list list;
105 char* p;
106 va_start(list, format);
107 vasprintf(&p, format, list);
108 va_end(list);
110 const char* t = p;
111 throw t;
115 bool Options::FileInfo::checkFileExists(const Options& options, const char *p)
117 struct stat statBuffer;
118 if (p == NULL)
119 p = path;
120 if ( stat(p, &statBuffer) == 0 ) {
121 if (p != path) path = strdup(p);
122 fileLen = statBuffer.st_size;
123 modTime = statBuffer.st_mtime;
124 return true;
126 if ( options.dumpDependencyInfo() )
127 options.dumpDependency(Options::depNotFound, p);
128 return false;
132 Options::Options(int argc, const char* argv[])
133 : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0), fArchitectureName("unknown"), fOutputKind(kDynamicExecutable),
134 fHasPreferredSubType(false), fArchSupportsThumb2(false), fPrebind(false), fBindAtLoad(false), fKeepPrivateExterns(false),
135 fNeedsModuleTable(false), fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false),
136 fInterposeMode(kInterposeNone), fDeadStrip(false), fNameSpace(kTwoLevelNameSpace),
137 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL), fFinalName(NULL), fEntryName(NULL),
138 fBaseAddress(0), fMaxAddress(0x7FFFFFFFFFFFFFFFLL),
139 fBaseWritableAddress(0), fSplitSegs(false),
140 fExportMode(kExportDefault), fLibrarySearchMode(kSearchDylibAndArchiveInEachDir),
141 fUndefinedTreatment(kUndefinedError), fMessagesPrefixedWithArchitecture(true),
142 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak),
143 fClientName(NULL),
144 fUmbrellaName(NULL), fInitFunctionName(NULL), fDotOutputFile(NULL), fExecutablePath(NULL),
145 fBundleLoader(NULL), fDtraceScriptName(NULL), fSegAddrTablePath(NULL), fMapPath(NULL),
146 fDyldInstallPath("/usr/lib/dyld"), fTempLtoObjectPath(NULL), fOverridePathlibLTO(NULL), fLtoCpu(NULL),
147 fZeroPageSize(ULLONG_MAX), fStackSize(0), fStackAddr(0), fSourceVersion(0), fSDKVersion(0), fExecutableStack(false),
148 fNonExecutableHeap(false), fDisableNonExecutableHeap(false),
149 fMinimumHeaderPad(32), fSegmentAlignment(4096),
150 fCommonsMode(kCommonsIgnoreDylibs), fUUIDMode(kUUIDContent), fLocalSymbolHandling(kLocalSymbolsAll), fWarnCommons(false),
151 fVerbose(false), fKeepRelocations(false), fWarnStabs(false),
152 fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
153 fSharedRegionEligible(false), fSharedRegionEligibleForceOff(false), fPrintOrderFileStatistics(false),
154 fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), fPIEOnCommandLine(false),
155 fDisablePositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
156 fDeadStripDylibs(false), fAllowTextRelocs(false), fWarnTextRelocs(false), fKextsUseStubs(false),
157 fUsingLazyDylibLinking(false), fEncryptable(true), fEncryptableForceOn(false), fEncryptableForceOff(false),
158 fOrderData(true), fMarkDeadStrippableDylib(false),
159 fMakeCompressedDyldInfo(true), fMakeCompressedDyldInfoForceOff(false), fNoEHLabels(false),
160 fAllowCpuSubtypeMismatches(false), fUseSimplifiedDylibReExports(false),
161 fObjCABIVersion2Override(false), fObjCABIVersion1Override(false), fCanUseUpwardDylib(false),
162 fFullyLoadArchives(false), fLoadAllObjcObjectsFromArchives(false), fFlatNamespace(false),
163 fLinkingMainExecutable(false), fForFinalLinkedImage(false), fForStatic(false),
164 fForDyld(false), fMakeTentativeDefinitionsReal(false), fWhyLoad(false), fRootSafe(false),
165 fSetuidSafe(false), fImplicitlyLinkPublicDylibs(true), fAddCompactUnwindEncoding(true),
166 fWarnCompactUnwind(false), fRemoveDwarfUnwindIfCompactExists(false),
167 fAutoOrderInitializers(true), fOptimizeZeroFill(true), fMergeZeroFill(false), fLogObjectFiles(false),
168 fLogAllFiles(false), fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false),
169 fOutputSlidable(false), fWarnWeakExports(false),
170 fObjcGcCompaction(false), fObjCGc(false), fObjCGcOnly(false),
171 fDemangle(false), fTLVSupport(false),
172 fVersionLoadCommand(false), fVersionLoadCommandForcedOn(false),
173 fVersionLoadCommandForcedOff(false), fFunctionStartsLoadCommand(false),
174 fFunctionStartsForcedOn(false), fFunctionStartsForcedOff(false),
175 fDataInCodeInfoLoadCommand(false), fDataInCodeInfoLoadCommandForcedOn(false), fDataInCodeInfoLoadCommandForcedOff(false),
176 fCanReExportSymbols(false), fObjcCategoryMerging(true), fPageAlignDataAtoms(false),
177 fNeedsThreadLoadCommand(false), fEntryPointLoadCommand(false),
178 fEntryPointLoadCommandForceOn(false), fEntryPointLoadCommandForceOff(false),
179 fSourceVersionLoadCommand(false),
180 fSourceVersionLoadCommandForceOn(false), fSourceVersionLoadCommandForceOff(false),
181 fTargetIOSSimulator(false), fExportDynamic(false), fAbsoluteSymbols(false),
182 fAllowSimulatorToLinkWithMacOSX(false), fKeepDwarfUnwind(true),
183 fKeepDwarfUnwindForcedOn(false), fKeepDwarfUnwindForcedOff(false),
184 fVerboseOptimizationHints(false), fIgnoreOptimizationHints(false),
185 fGenerateDtraceDOF(true), fAllowBranchIslands(true), fTraceSymbolLayout(false),
186 fMarkAppExtensionSafe(false), fCheckAppExtensionSafe(false), fForceLoadSwiftLibs(false),
187 fSharedRegionEncodingV2(false), fUseDataConstSegment(false),
188 fUseDataConstSegmentForceOn(false), fUseDataConstSegmentForceOff(false),
189 fBundleBitcode(false), fHideSymbols(false), fReverseMapUUIDRename(false), fReverseMapPath(NULL), fLTOCodegenOnly(false),
190 fIgnoreAutoLink(false), fPlatform(kPlatformUnknown),
191 fDebugInfoStripping(kDebugInfoMinimal), fTraceOutputFile(NULL),
192 fMacVersionMin(ld::macVersionUnset), fIOSVersionMin(ld::iOSVersionUnset),
193 fSaveTempFiles(false), fSnapshotRequested(false), fPipelineFifo(NULL),
194 fDependencyInfoPath(NULL), fDependencyFileDescriptor(-1)
196 this->checkForClassic(argc, argv);
197 this->parsePreCommandLineEnvironmentSettings();
198 this->parse(argc, argv);
199 this->parsePostCommandLineEnvironmentSettings();
200 this->reconfigureDefaults();
201 this->checkIllegalOptionCombinations();
203 if ( this->dumpDependencyInfo() ) {
204 this->dumpDependency(depOutputFile, fOutputFile);
205 if ( fMapPath != NULL )
206 this->dumpDependency(depOutputFile, fMapPath);
210 Options::~Options()
212 if ( fDependencyFileDescriptor != -1 )
213 ::close(fDependencyFileDescriptor);
216 bool Options::errorBecauseOfWarnings() const
218 return (sFatalWarnings && (sWarningsCount > 0));
222 const char* Options::installPath() const
224 if ( fDylibInstallName != NULL )
225 return fDylibInstallName;
226 else if ( fFinalName != NULL )
227 return fFinalName;
228 else
229 return fOutputFile;
233 bool Options::interposable(const char* name) const
235 switch ( fInterposeMode ) {
236 case kInterposeNone:
237 return false;
238 case kInterposeAllExternal:
239 return true;
240 case kInterposeSome:
241 return fInterposeList.contains(name);
243 throw "internal error";
247 bool Options::printWhyLive(const char* symbolName) const
249 return fWhyLive.contains(symbolName);
253 const char* Options::dotOutputFile()
255 return fDotOutputFile;
259 bool Options::hasWildCardExportRestrictList() const
261 // has -exported_symbols_list which contains some wildcards
262 return ((fExportMode == kExportSome) && fExportSymbols.hasWildCards());
265 bool Options::hasWeakBitTweaks() const
267 // has -exported_symbols_list which contains some wildcards
268 return (!fForceWeakSymbols.empty() || !fForceNotWeakSymbols.empty());
271 bool Options::allGlobalsAreDeadStripRoots() const
273 // -exported_symbols_list means globals are not exported by default
274 if ( fExportMode == kExportSome )
275 return false;
277 switch ( fOutputKind ) {
278 case Options::kDynamicExecutable:
279 // <rdar://problem/12839986> Add the -export_dynamic flag
280 return fExportDynamic;
281 case Options::kStaticExecutable:
282 // <rdar://problem/13361218> Support the -export_dynamic flag for xnu
283 return fExportDynamic;
284 case Options::kPreload:
285 // by default unused globals in a main executable are stripped
286 return false;
287 case Options::kDynamicLibrary:
288 case Options::kDynamicBundle:
289 case Options::kObjectFile:
290 case Options::kDyld:
291 case Options::kKextBundle:
292 return true;
294 return false;
298 bool Options::keepRelocations()
300 return fKeepRelocations;
303 bool Options::warnStabs()
305 return fWarnStabs;
308 const char* Options::executablePath()
310 return fExecutablePath;
313 uint32_t Options::initialSegProtection(const char* segName) const
315 for(std::vector<Options::SegmentProtect>::const_iterator it = fCustomSegmentProtections.begin(); it != fCustomSegmentProtections.end(); ++it) {
316 if ( strcmp(it->name, segName) == 0 ) {
317 return it->init;
320 if ( strcmp(segName, "__PAGEZERO") == 0 ) {
321 return 0;
323 else if ( strcmp(segName, "__TEXT") == 0 ) {
324 return VM_PROT_READ | VM_PROT_EXECUTE;
326 else if ( strcmp(segName, "__LINKEDIT") == 0 ) {
327 return VM_PROT_READ;
330 // all others default to read-write
331 return VM_PROT_READ | VM_PROT_WRITE;
334 uint32_t Options::maxSegProtection(const char* segName) const
336 // iPhoneOS always uses same protection for max and initial
337 // <rdar://problem/11663436> simulator apps need to use MacOSX max-prot
338 if ( (fPlatform != kPlatformOSX) && !fTargetIOSSimulator )
339 return initialSegProtection(segName);
341 for(std::vector<Options::SegmentProtect>::const_iterator it = fCustomSegmentProtections.begin(); it != fCustomSegmentProtections.end(); ++it) {
342 if ( strcmp(it->name, segName) == 0 ) {
343 return it->max;
346 if ( strcmp(segName, "__PAGEZERO") == 0 ) {
347 return 0;
349 // all others default to all
350 return VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
353 uint64_t Options::segPageSize(const char* segName) const
355 for(std::vector<SegmentSize>::const_iterator it=fCustomSegmentSizes.begin(); it != fCustomSegmentSizes.end(); ++it) {
356 if ( strcmp(it->name, segName) == 0 )
357 return it->size;
359 return fSegmentAlignment;
362 uint64_t Options::customSegmentAddress(const char* segName) const
364 for(std::vector<SegmentStart>::const_iterator it=fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
365 if ( strcmp(it->name, segName) == 0 )
366 return it->address;
368 // if custom stack in use, model as segment with custom address
369 if ( (fStackSize != 0) && (strcmp("__UNIXSTACK", segName) == 0) )
370 return fStackAddr - fStackSize;
371 return 0;
374 bool Options::hasCustomSegmentAddress(const char* segName) const
376 for(std::vector<SegmentStart>::const_iterator it=fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
377 if ( strcmp(it->name, segName) == 0 )
378 return true;
380 // if custom stack in use, model as segment with custom address
381 if ( (fStackSize != 0) && (strcmp("__UNIXSTACK", segName) == 0) )
382 return true;
383 return false;
386 bool Options::hasCustomSectionAlignment(const char* segName, const char* sectName) const
388 for (std::vector<SectionAlignment>::const_iterator it = fSectionAlignments.begin(); it != fSectionAlignments.end(); ++it) {
389 if ( (strcmp(it->segmentName, segName) == 0) && (strcmp(it->sectionName, sectName) == 0) )
390 return true;
392 return false;
395 uint8_t Options::customSectionAlignment(const char* segName, const char* sectName) const
397 for (std::vector<SectionAlignment>::const_iterator it = fSectionAlignments.begin(); it != fSectionAlignments.end(); ++it) {
398 if ( (strcmp(it->segmentName, segName) == 0) && (strcmp(it->sectionName, sectName) == 0) )
399 return it->alignment;
401 return 0;
404 bool Options::segmentOrderAfterFixedAddressSegment(const char* segName) const
406 bool nowPinned = false;
407 for (std::vector<const char*>::const_iterator it=fSegmentOrder.begin(); it != fSegmentOrder.end(); ++it) {
408 if ( strcmp(*it, segName) == 0 )
409 return nowPinned;
410 if ( hasCustomSegmentAddress(*it) )
411 nowPinned = true;
413 return false;
416 bool Options::hasExportedSymbolOrder()
418 return (fExportSymbolsOrder.size() > 0);
421 bool Options::exportedSymbolOrder(const char* sym, unsigned int* order) const
423 NameToOrder::const_iterator pos = fExportSymbolsOrder.find(sym);
424 if ( pos != fExportSymbolsOrder.end() ) {
425 *order = pos->second;
426 return true;
428 else {
429 *order = 0xFFFFFFFF;
430 return false;
434 void Options::loadSymbolOrderFile(const char* fileOfExports, NameToOrder& orderMapping)
436 // read in whole file
437 int fd = ::open(fileOfExports, O_RDONLY, 0);
438 if ( fd == -1 )
439 throwf("can't open -exported_symbols_order file: %s", fileOfExports);
440 struct stat stat_buf;
441 ::fstat(fd, &stat_buf);
442 char* p = (char*)malloc(stat_buf.st_size);
443 if ( p == NULL )
444 throwf("can't process -exported_symbols_order file: %s", fileOfExports);
446 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
447 throwf("can't read -exported_symbols_order file: %s", fileOfExports);
449 ::close(fd);
451 // parse into symbols and add to unordered_set
452 unsigned int count = 0;
453 char * const end = &p[stat_buf.st_size];
454 enum { lineStart, inSymbol, inComment } state = lineStart;
455 char* symbolStart = NULL;
456 for (char* s = p; s < end; ++s ) {
457 switch ( state ) {
458 case lineStart:
459 if ( *s =='#' ) {
460 state = inComment;
462 else if ( !isspace(*s) ) {
463 state = inSymbol;
464 symbolStart = s;
466 break;
467 case inSymbol:
468 if ( (*s == '\n') || (*s == '\r') ) {
469 *s = '\0';
470 // removing any trailing spaces
471 char* last = s-1;
472 while ( isspace(*last) ) {
473 *last = '\0';
474 --last;
476 orderMapping[symbolStart] = ++count;
477 symbolStart = NULL;
478 state = lineStart;
480 break;
481 case inComment:
482 if ( (*s == '\n') || (*s == '\r') )
483 state = lineStart;
484 break;
487 if ( state == inSymbol ) {
488 warning("missing line-end at end of file \"%s\"", fileOfExports);
489 int len = end-symbolStart+1;
490 char* temp = new char[len];
491 strlcpy(temp, symbolStart, len);
493 // remove any trailing spaces
494 char* last = &temp[len-2];
495 while ( isspace(*last) ) {
496 *last = '\0';
497 --last;
499 orderMapping[temp] = ++count;
502 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
505 bool Options::forceWeak(const char* symbolName) const
507 return fForceWeakSymbols.contains(symbolName);
510 bool Options::forceNotWeak(const char* symbolName) const
512 return fForceNotWeakSymbols.contains(symbolName);
515 bool Options::forceWeakNonWildCard(const char* symbolName) const
517 return fForceWeakSymbols.containsNonWildcard(symbolName);
520 bool Options::forceNotWeakNonWildcard(const char* symbolName) const
522 return fForceNotWeakSymbols.containsNonWildcard(symbolName);
525 bool Options::forceCoalesce(const char* symbolName) const
527 return fForceCoalesceSymbols.contains(symbolName);
531 bool Options::shouldExport(const char* symbolName) const
533 switch (fExportMode) {
534 case kExportSome:
535 return fExportSymbols.contains(symbolName);
536 case kDontExportSome:
537 return ! fDontExportSymbols.contains(symbolName);
538 case kExportDefault:
539 return true;
541 throw "internal error";
544 bool Options::shouldReExport(const char* symbolName) const
546 return fReExportSymbols.contains(symbolName);
549 bool Options::keepLocalSymbol(const char* symbolName) const
551 switch (fLocalSymbolHandling) {
552 case kLocalSymbolsAll:
553 return true;
554 case kLocalSymbolsNone:
555 return false;
556 case kLocalSymbolsSelectiveInclude:
557 return fLocalSymbolsIncluded.contains(symbolName);
558 case kLocalSymbolsSelectiveExclude:
559 return ! fLocalSymbolsExcluded.contains(symbolName);
561 throw "internal error";
564 const std::vector<const char*>* Options::sectionOrder(const char* segName) const
566 for (std::vector<SectionOrderList>::const_iterator it=fSectionOrder.begin(); it != fSectionOrder.end(); ++it) {
567 if ( strcmp(it->segmentName, segName) == 0 )
568 return &it->sectionOrder;
570 return NULL;
573 uint32_t Options::minOSversion() const
575 switch (fPlatform) {
576 case kPlatformiOS:
577 return iOSVersionMin();
578 case kPlatformOSX:
579 return macosxVersionMin();
580 case kPlatformWatchOS:
581 return watchOSVersionMin();
582 #if SUPPORT_APPLE_TV
583 case Options::kPlatform_tvOS:
584 return iOSVersionMin();
585 #endif
586 default:
587 break;
589 return 0;
592 void Options::setArchitecture(cpu_type_t type, cpu_subtype_t subtype, Options::Platform platform)
594 for (const ArchInfo* t=archInfoArray; t->archName != NULL; ++t) {
595 if ( (type == t->cpuType) && (subtype == t->cpuSubType) ) {
596 fArchitecture = type;
597 fSubArchitecture = subtype;
598 fArchitectureName = t->archName;
599 fHasPreferredSubType = t->isSubType;
600 fArchSupportsThumb2 = t->supportsThumb2;
601 fPlatform = platform;
602 switch ( type ) {
603 case CPU_TYPE_I386:
604 case CPU_TYPE_X86_64:
605 if ( (fPlatform == kPlatformOSX) && (fOutputKind != Options::kObjectFile) ) {
606 #ifdef DEFAULT_MACOSX_MIN_VERSION
607 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION);
608 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
609 #else
610 warning("-macosx_version_min not specified, assuming 10.6");
611 fMacVersionMin = ld::mac10_6;
612 #endif
614 break;
615 case CPU_TYPE_ARM:
616 case CPU_TYPE_ARM64:
617 if ( (fPlatform == kPlatformiOS) && (fOutputKind != Options::kObjectFile) ) {
618 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
619 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION);
620 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION);
621 #else
622 warning("-ios_version_min not specified, assuming 6.0");
623 setIOSVersionMin("6.0");
624 #endif
626 break;
628 fLinkSnapshot.recordArch(fArchitectureName);
629 // only use compressed LINKEDIT for:
630 // Mac OS X 10.6 or later
631 // iOS 3.1 or later
632 if ( !fMakeCompressedDyldInfo && minOS(ld::mac10_6, ld::iOS_3_1) && !fMakeCompressedDyldInfoForceOff )
633 fMakeCompressedDyldInfo = true;
634 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
635 if ( minOS(ld::mac10_5, ld::iOS_2_0) )
636 fUseSimplifiedDylibReExports = true;
637 return;
640 fArchitectureName = "unknown architecture";
643 bool Options::armUsesZeroCostExceptions() const
645 return ( (fArchitecture == CPU_TYPE_ARM) && (fSubArchitecture == CPU_SUBTYPE_ARM_V7K) );
648 void Options::parseArch(const char* arch)
650 if ( arch == NULL )
651 throw "-arch must be followed by an architecture string";
652 for (const ArchInfo* t=archInfoArray; t->archName != NULL; ++t) {
653 if ( strcmp(t->archName,arch) == 0 ) {
654 fArchitectureName = arch;
655 fArchitecture = t->cpuType;
656 fSubArchitecture = t->cpuSubType;
657 fHasPreferredSubType = t->isSubType;
658 fArchSupportsThumb2 = t->supportsThumb2;
659 return;
662 throwf("unknown/unsupported architecture name for: -arch %s", arch);
665 bool Options::checkForFile(const char* format, const char* dir, const char* rootName, FileInfo& result) const
667 char possiblePath[strlen(dir)+strlen(rootName)+strlen(format)+8];
668 sprintf(possiblePath, format, dir, rootName);
669 bool found = result.checkFileExists(*this, possiblePath);
670 if ( fTraceDylibSearching )
671 printf("[Logging for XBS]%sfound library: '%s'\n", (found ? " " : " not "), possiblePath);
672 return found;
676 Options::FileInfo Options::findLibrary(const char* rootName, bool dylibsOnly) const
678 FileInfo result;
679 const int rootNameLen = strlen(rootName);
680 // if rootName ends in .o there is no .a vs .dylib choice
681 if ( (rootNameLen > 3) && (strcmp(&rootName[rootNameLen-2], ".o") == 0) ) {
682 for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
683 it != fLibrarySearchPaths.end();
684 it++) {
685 const char* dir = *it;
686 if ( checkForFile("%s/%s", dir, rootName, result) )
687 return result;
690 else {
691 bool lookForDylibs = false;
692 switch ( fOutputKind ) {
693 case Options::kDynamicExecutable:
694 case Options::kDynamicLibrary:
695 case Options::kDynamicBundle:
696 case Options::kObjectFile: // <rdar://problem/15914513>
697 lookForDylibs = true;
698 break;
699 case Options::kStaticExecutable:
700 case Options::kDyld:
701 case Options::kPreload:
702 case Options::kKextBundle:
703 lookForDylibs = false;
704 break;
706 switch ( fLibrarySearchMode ) {
707 case kSearchAllDirsForDylibsThenAllDirsForArchives:
708 // first look in all directories for just for dylibs
709 if ( lookForDylibs ) {
710 for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
711 it != fLibrarySearchPaths.end();
712 it++) {
713 const char* dir = *it;
714 if ( checkForFile("%s/lib%s.tbd", dir, rootName, result) )
715 return result;
716 if ( checkForFile("%s/lib%s.dylib", dir, rootName, result) )
717 return result;
719 for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
720 it != fLibrarySearchPaths.end();
721 it++) {
722 const char* dir = *it;
723 if ( checkForFile("%s/lib%s.so", dir, rootName, result) )
724 return result;
727 // next look in all directories for just for archives
728 if ( !dylibsOnly ) {
729 for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
730 it != fLibrarySearchPaths.end();
731 it++) {
732 const char* dir = *it;
733 if ( checkForFile("%s/lib%s.a", dir, rootName, result) )
734 return result;
737 break;
739 case kSearchDylibAndArchiveInEachDir:
740 // look in each directory for just for a dylib then for an archive
741 for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
742 it != fLibrarySearchPaths.end();
743 it++) {
744 const char* dir = *it;
745 if ( lookForDylibs && checkForFile("%s/lib%s.tbd", dir, rootName, result) )
746 return result;
747 if ( lookForDylibs && checkForFile("%s/lib%s.dylib", dir, rootName, result) )
748 return result;
749 if ( lookForDylibs && checkForFile("%s/lib%s.so", dir, rootName, result) )
750 return result;
751 if ( !dylibsOnly && checkForFile("%s/lib%s.a", dir, rootName, result) )
752 return result;
754 break;
757 throwf("library not found for -l%s", rootName);
760 Options::FileInfo Options::findFramework(const char* frameworkName) const
762 if ( frameworkName == NULL )
763 throw "-framework missing next argument";
764 char temp[strlen(frameworkName)+1];
765 strcpy(temp, frameworkName);
766 const char* name = temp;
767 const char* suffix = NULL;
768 char* comma = strchr(temp, ',');
769 if ( comma != NULL ) {
770 *comma = '\0';
771 suffix = &comma[1];
773 return findFramework(name, suffix);
776 Options::FileInfo Options::findFramework(const char* rootName, const char* suffix) const
778 for (const auto* path : fFrameworkSearchPaths) {
779 auto possiblePath = std::string(path).append("/").append(rootName).append(".framework/").append(rootName);
780 if ( suffix != nullptr ) {
781 char realPath[PATH_MAX];
782 // no symlink in framework to suffix variants, so follow main symlink
783 if ( realpath(possiblePath.c_str(), realPath) != nullptr )
784 possiblePath = std::string(realPath).append(suffix);
786 FileInfo result;
787 bool found = result.checkFileExists(*this, (possiblePath + ".tbd").c_str());
788 if ( !found )
789 found = result.checkFileExists(*this, possiblePath.c_str());
790 if ( fTraceDylibSearching )
791 printf("[Logging for XBS]%sfound framework: '%s'\n",
792 (found ? " " : " not "), possiblePath.c_str());
793 if ( found ) {
794 return result;
797 // try without suffix
798 if ( suffix != NULL )
799 return findFramework(rootName, NULL);
800 else
801 throwf("framework not found %s", rootName);
804 Options::FileInfo Options::findFile(const std::string &path) const
806 FileInfo result;
808 // if absolute path and not a .o file, then use SDK prefix
809 if ( (path[0] == '/') && (strcmp(&path[path.size()-2], ".o") != 0) ) {
810 auto tbdFile = path;
811 auto lastSlashIdx = tbdFile.find_last_of('/');
812 auto lastDotIdx = tbdFile.find_last_of('.');
813 if (lastDotIdx != std::string::npos && lastDotIdx > lastSlashIdx)
814 tbdFile.erase(lastDotIdx, std::string::npos);
815 tbdFile.append(".tbd");
817 for (const auto* sdkPathDir : fSDKPaths) {
818 auto possiblePath = std::string(sdkPathDir) + tbdFile;
819 if ( result.checkFileExists(*this, possiblePath.c_str()) )
820 return result;
821 possiblePath = std::string(sdkPathDir) + path;
822 if ( result.checkFileExists(*this, possiblePath.c_str()) )
823 return result;
826 // try raw path
828 std::string file = path;
829 auto lastDotIdx = file.find_last_of('.');
830 if (lastDotIdx != std::string::npos)
831 file.erase(lastDotIdx, std::string::npos);
832 if ( result.checkFileExists(*this, file.append(".tbd").c_str()) )
833 return result;
835 if ( result.checkFileExists(*this, path.c_str()) ) {
836 return result;
840 // try @executable_path substitution
841 if ( (path.find("@executable_path/") == 0) && (fExecutablePath != nullptr) ) {
842 char newPath[strlen(fExecutablePath) + path.size()];
843 strcpy(newPath, fExecutablePath);
844 char* addPoint = strrchr(newPath,'/');
845 if ( addPoint != nullptr )
846 strcpy(&addPoint[1], &path[17]);
847 else
848 strcpy(newPath, &path[17]);
850 std::string file = newPath;
851 auto lastDotIdx = file.find_last_of('.');
852 if (lastDotIdx != std::string::npos)
853 file.erase(lastDotIdx, std::string::npos);
854 if ( result.checkFileExists(*this, file.append(".tbd").c_str()) ) {
855 return result;
857 if ( result.checkFileExists(*this, newPath) ) {
858 return result;
862 // not found
863 throwf("file not found: %s", path.c_str());
866 Options::FileInfo Options::findFileUsingPaths(const std::string &path) const
868 FileInfo result;
870 auto lastSlashPos = path.find_last_of('/');
871 auto pos = ( lastSlashPos != std::string::npos ) ? lastSlashPos + 1 : 0;
872 auto leafName = path.substr(pos);
874 // Is this in a framework?
875 // /path/Foo.framework/Foo ==> true (Foo)
876 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
877 // /path/Foo.framework/Resources/Bar ==> false
878 bool isFramework = false;
879 if ( lastSlashPos != std::string::npos ) {
880 auto frameworkDir = std::string("/").append(leafName).append(".framework/");
881 if ( path.rfind(frameworkDir) != std::string::npos )
882 isFramework = true;
885 // These are abbreviated versions of the routines findFramework and findLibrary above
886 // because we already know the final name of the file that we're looking for and so
887 // don't need to try variations, just paths. We do need to add the additional bits
888 // onto the framework path though.
889 if ( isFramework ) {
890 auto endPos = path.rfind(".framework");
891 auto beginPos = path.find_last_of('/', endPos);
892 auto leafPath = path.substr(beginPos);
893 for (const auto* dir : fFrameworkSearchPaths) {
894 auto possiblePath = dir + leafPath;
895 if ( checkForFile("%s.%s", possiblePath.c_str(), "tbd", result) )
896 return result;
897 if ( checkForFile("%s", possiblePath.c_str(), "", result) )
898 return result;
900 } else {
901 // if this is a .dylib inside a framework, do not search -L paths
902 // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
903 bool embeddedDylib = ( (leafName.size() > 6)
904 && (leafName.find(".dylib", leafName.size()-6) != std::string::npos)
905 && (path.find(".framework/") != std::string::npos) );
906 if ( !embeddedDylib ) {
907 for (const auto* dir : fLibrarySearchPaths) {
908 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
909 if ( checkForFile("%s/%s", dir, std::string(leafName).append(".tbd").c_str(), result) )
910 return result;
911 if ( checkForFile("%s/%s", dir, leafName.c_str(), result) )
912 return result;
917 // If we didn't find it fall back to findFile.
918 return findFile(path);
923 void Options::parseSegAddrTable(const char* segAddrPath, const char* installPth)
925 FILE* file = fopen(segAddrPath, "r");
926 if ( file == NULL ) {
927 warning("-seg_addr_table file cannot be read: %s", segAddrPath);
928 return;
931 char path[PATH_MAX];
932 uint64_t firstColumAddress = 0;
933 uint64_t secondColumAddress = 0;
934 bool hasSecondColumn = false;
935 while ( fgets(path, PATH_MAX, file) != NULL ) {
936 path[PATH_MAX-1] = '\0';
937 char* eol = strchr(path, '\n');
938 if ( eol != NULL )
939 *eol = '\0';
940 // ignore lines not starting with 0x number
941 if ( (path[0] == '0') && (path[1] == 'x') ) {
942 char* p;
943 firstColumAddress = strtoull(path, &p, 16);
944 while ( isspace(*p) )
945 ++p;
946 // see if second column is a number
947 if ( (p[0] == '0') && (p[1] == 'x') ) {
948 secondColumAddress = strtoull(p, &p, 16);
949 hasSecondColumn = true;
950 while ( isspace(*p) )
951 ++p;
953 while ( isspace(*p) )
954 ++p;
955 if ( p[0] == '/' ) {
956 // remove any trailing whitespace
957 for(char* end = eol-1; (end > p) && isspace(*end); --end)
958 *end = '\0';
959 // see if this line is for the dylib being linked
960 if ( strcmp(p, installPth) == 0 ) {
961 fBaseAddress = firstColumAddress;
962 if ( hasSecondColumn ) {
963 fBaseWritableAddress = secondColumAddress;
964 fSplitSegs = true;
966 break; // out of while loop
972 fclose(file);
975 void Options::loadFileList(const char* fileOfPaths, ld::File::Ordinal baseOrdinal)
977 FILE* file;
978 const char* comma = strrchr(fileOfPaths, ',');
979 const char* prefix = NULL;
980 if ( comma != NULL ) {
981 // <rdar://problem/5907981> -filelist fails with comma in path
982 file = fopen(fileOfPaths, "r");
983 if ( file == NULL ) {
984 prefix = comma+1;
985 int realFileOfPathsLen = comma-fileOfPaths;
986 char realFileOfPaths[realFileOfPathsLen+1];
987 strncpy(realFileOfPaths,fileOfPaths, realFileOfPathsLen);
988 realFileOfPaths[realFileOfPathsLen] = '\0';
989 file = fopen(realFileOfPaths, "r");
990 if ( file == NULL )
991 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", realFileOfPaths, errno, strerror(errno));
992 if ( this->dumpDependencyInfo() )
993 this->dumpDependency(Options::depFileList, realFileOfPaths);
996 else {
997 file = fopen(fileOfPaths, "r");
998 if ( file == NULL )
999 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", fileOfPaths, errno, strerror(errno));
1000 if ( this->dumpDependencyInfo() )
1001 this->dumpDependency(Options::depFileList, fileOfPaths);
1004 char path[PATH_MAX];
1005 ld::File::Ordinal previousOrdinal = baseOrdinal;
1006 while ( fgets(path, PATH_MAX, file) != NULL ) {
1007 path[PATH_MAX-1] = '\0';
1008 char* eol = strchr(path, '\n');
1009 if ( eol != NULL )
1010 *eol = '\0';
1011 if ( prefix != NULL ) {
1012 char builtPath[strlen(prefix)+strlen(path)+2];
1013 strcpy(builtPath, prefix);
1014 strcat(builtPath, "/");
1015 strcat(builtPath, path);
1016 if (fPipelineFifo != NULL) {
1017 FileInfo info = FileInfo(builtPath);
1018 info.ordinal = previousOrdinal.nextFileListOrdinal();
1019 previousOrdinal = info.ordinal;
1020 info.fromFileList = true;
1021 fInputFiles.push_back(info);
1022 } else {
1023 FileInfo info = findFile(builtPath);
1024 info.ordinal = previousOrdinal.nextFileListOrdinal();
1025 previousOrdinal = info.ordinal;
1026 info.fromFileList = true;
1027 fInputFiles.push_back(info);
1030 else {
1031 if (fPipelineFifo != NULL) {
1032 FileInfo info = FileInfo(path);
1033 info.ordinal = previousOrdinal.nextFileListOrdinal();
1034 previousOrdinal = info.ordinal;
1035 info.fromFileList = true;
1036 fInputFiles.push_back(info);
1037 } else {
1038 FileInfo info = findFile(path);
1039 info.ordinal = previousOrdinal.nextFileListOrdinal();
1040 previousOrdinal = info.ordinal;
1041 info.fromFileList = true;
1042 fInputFiles.push_back(info);
1046 fclose(file);
1050 void Options::SetWithWildcards::remove(const NameSet& toBeRemoved)
1052 for(NameSet::const_iterator it=toBeRemoved.begin(); it != toBeRemoved.end(); ++it) {
1053 const char* symbolName = *it;
1054 NameSet::iterator pos = fRegular.find(symbolName);
1055 if ( pos != fRegular.end() )
1056 fRegular.erase(pos);
1060 bool Options::SetWithWildcards::hasWildCards(const char* symbol)
1062 // an exported symbol name containing *, ?, or [ requires wildcard matching
1063 return ( strpbrk(symbol, "*?[") != NULL );
1066 void Options::SetWithWildcards::insert(const char* symbol)
1068 if ( hasWildCards(symbol) )
1069 fWildCard.push_back(symbol);
1070 else
1071 fRegular.insert(symbol);
1074 bool Options::SetWithWildcards::contains(const char* symbol, bool* matchBecauseOfWildcard) const
1076 if ( matchBecauseOfWildcard != NULL )
1077 *matchBecauseOfWildcard = false;
1078 // first look at hash table on non-wildcard symbols
1079 if ( fRegular.find(symbol) != fRegular.end() )
1080 return true;
1081 // next walk list of wild card symbols looking for a match
1082 for(std::vector<const char*>::const_iterator it = fWildCard.begin(); it != fWildCard.end(); ++it) {
1083 if ( wildCardMatch(*it, symbol) ) {
1084 if ( matchBecauseOfWildcard != NULL )
1085 *matchBecauseOfWildcard = true;
1086 return true;
1089 return false;
1092 // Support "foo.o:_bar" to mean symbol _bar in file foo.o
1093 bool Options::SetWithWildcards::containsWithPrefix(const char* symbol, const char* file, bool& wildCardMatch) const
1095 wildCardMatch = false;
1096 if ( contains(symbol, &wildCardMatch) )
1097 return true;
1098 if ( file == NULL )
1099 return false;
1100 const char* s = strrchr(file, '/');
1101 if ( s != NULL )
1102 file = s+1;
1103 char buff[strlen(file)+strlen(symbol)+2];
1104 sprintf(buff, "%s:%s", file, symbol);
1105 return contains(buff, &wildCardMatch);
1108 bool Options::SetWithWildcards::containsNonWildcard(const char* symbol) const
1110 // look at hash table on non-wildcard symbols
1111 return ( fRegular.find(symbol) != fRegular.end() );
1115 std::vector<const char*> Options::exportsData() const
1117 return fExportSymbols.data();
1121 std::vector<const char*> Options::SetWithWildcards::data() const
1123 std::vector<const char*> data;
1124 for (NameSet::iterator it=regularBegin(); it != regularEnd(); ++it) {
1125 data.push_back(*it);
1127 for (std::vector<const char*>::const_iterator it=fWildCard.begin(); it != fWildCard.end(); ++it) {
1128 data.push_back(*it);
1130 return data;
1133 bool Options::SetWithWildcards::inCharRange(const char*& p, unsigned char c) const
1135 ++p; // find end
1136 const char* b = p;
1137 while ( *p != '\0' ) {
1138 if ( *p == ']') {
1139 const char* e = p;
1140 // found beginining [ and ending ]
1141 unsigned char last = '\0';
1142 for ( const char* s = b; s < e; ++s ) {
1143 if ( *s == '-' ) {
1144 unsigned char next = *(++s);
1145 if ( (last <= c) && (c <= next) )
1146 return true;
1147 ++s;
1149 else {
1150 if ( *s == c )
1151 return true;
1152 last = *s;
1155 return false;
1157 ++p;
1159 return false;
1162 bool Options::SetWithWildcards::wildCardMatch(const char* pattern, const char* symbol) const
1164 const char* s = symbol;
1165 for (const char* p = pattern; *p != '\0'; ++p) {
1166 switch ( *p ) {
1167 case '*':
1168 if ( p[1] == '\0' )
1169 return true;
1170 for (const char* t = s; *t != '\0'; ++t) {
1171 if ( wildCardMatch(&p[1], t) )
1172 return true;
1174 return false;
1175 case '?':
1176 if ( *s == '\0' )
1177 return false;
1178 ++s;
1179 break;
1180 case '[':
1181 if ( ! inCharRange(p, *s) )
1182 return false;
1183 ++s;
1184 break;
1185 default:
1186 if ( *s != *p )
1187 return false;
1188 ++s;
1191 return (*s == '\0');
1195 void Options::loadExportFile(const char* fileOfExports, const char* option, SetWithWildcards& set)
1197 if ( fileOfExports == NULL )
1198 throwf("missing file after %s", option);
1199 // read in whole file
1200 int fd = ::open(fileOfExports, O_RDONLY, 0);
1201 if ( fd == -1 )
1202 throwf("can't open %s file: %s", option, fileOfExports);
1203 struct stat stat_buf;
1204 ::fstat(fd, &stat_buf);
1205 char* p = (char*)malloc(stat_buf.st_size);
1206 if ( p == NULL )
1207 throwf("can't process %s file: %s", option, fileOfExports);
1209 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1210 throwf("can't read %s file: %s", option, fileOfExports);
1212 if ( this->dumpDependencyInfo() )
1213 this->dumpDependency(Options::depMisc, fileOfExports);
1215 ::close(fd);
1217 // parse into symbols and add to unordered_set
1218 char * const end = &p[stat_buf.st_size];
1219 enum { lineStart, inSymbol, inComment } state = lineStart;
1220 char* symbolStart = NULL;
1221 for (char* s = p; s < end; ++s ) {
1222 switch ( state ) {
1223 case lineStart:
1224 if ( *s =='#' ) {
1225 state = inComment;
1227 else if ( !isspace(*s) ) {
1228 state = inSymbol;
1229 symbolStart = s;
1231 break;
1232 case inSymbol:
1233 if ( (*s == '\n') || (*s == '\r') ) {
1234 *s = '\0';
1235 // removing any trailing spaces
1236 char* last = s-1;
1237 while ( isspace(*last) ) {
1238 *last = '\0';
1239 --last;
1241 set.insert(symbolStart);
1242 symbolStart = NULL;
1243 state = lineStart;
1245 break;
1246 case inComment:
1247 if ( (*s == '\n') || (*s == '\r') )
1248 state = lineStart;
1249 break;
1252 if ( state == inSymbol ) {
1253 warning("missing line-end at end of file \"%s\"", fileOfExports);
1254 int len = end-symbolStart+1;
1255 char* temp = new char[len];
1256 strlcpy(temp, symbolStart, len);
1258 // remove any trailing spaces
1259 char* last = &temp[len-2];
1260 while ( isspace(*last) ) {
1261 *last = '\0';
1262 --last;
1264 set.insert(temp);
1267 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
1270 void Options::parseAliasFile(const char* fileOfAliases)
1272 // read in whole file
1273 int fd = ::open(fileOfAliases, O_RDONLY, 0);
1274 if ( fd == -1 )
1275 throwf("can't open alias file: %s", fileOfAliases);
1276 struct stat stat_buf;
1277 ::fstat(fd, &stat_buf);
1278 char* p = (char*)malloc(stat_buf.st_size+1);
1279 if ( p == NULL )
1280 throwf("can't process alias file: %s", fileOfAliases);
1282 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1283 throwf("can't read alias file: %s", fileOfAliases);
1284 p[stat_buf.st_size] = '\n';
1285 ::close(fd);
1286 if ( this->dumpDependencyInfo() )
1287 this->dumpDependency(Options::depMisc, fileOfAliases);
1289 // parse into symbols and add to fAliases
1290 AliasPair pair;
1291 char * const end = &p[stat_buf.st_size+1];
1292 enum { lineStart, inRealName, inBetween, inAliasName, inComment } state = lineStart;
1293 int lineNumber = 1;
1294 for (char* s = p; s < end; ++s ) {
1295 switch ( state ) {
1296 case lineStart:
1297 if ( *s =='#' ) {
1298 state = inComment;
1300 else if ( !isspace(*s) ) {
1301 state = inRealName;
1302 pair.realName = s;
1304 break;
1305 case inRealName:
1306 if ( *s == '\n' ) {
1307 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber, fileOfAliases);
1308 ++lineNumber;
1309 state = lineStart;
1311 else if ( isspace(*s) ) {
1312 *s = '\0';
1313 state = inBetween;
1315 break;
1316 case inBetween:
1317 if ( *s == '\n' ) {
1318 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber, fileOfAliases);
1319 ++lineNumber;
1320 state = lineStart;
1322 else if ( ! isspace(*s) ) {
1323 state = inAliasName;
1324 pair.alias = s;
1326 break;
1327 case inAliasName:
1328 if ( *s =='#' ) {
1329 *s = '\0';
1330 // removing any trailing spaces
1331 char* last = s-1;
1332 while ( isspace(*last) ) {
1333 *last = '\0';
1334 --last;
1336 fAliases.push_back(pair);
1337 state = inComment;
1339 else if ( *s == '\n' ) {
1340 *s = '\0';
1341 // removing any trailing spaces
1342 char* last = s-1;
1343 while ( isspace(*last) ) {
1344 *last = '\0';
1345 --last;
1347 fAliases.push_back(pair);
1348 state = lineStart;
1350 break;
1351 case inComment:
1352 if ( *s == '\n' )
1353 state = lineStart;
1354 break;
1358 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
1363 void Options::setUndefinedTreatment(const char* treatment)
1365 if ( treatment == NULL )
1366 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
1368 if ( strcmp(treatment, "warning") == 0 )
1369 fUndefinedTreatment = kUndefinedWarning;
1370 else if ( strcmp(treatment, "error") == 0 )
1371 fUndefinedTreatment = kUndefinedError;
1372 else if ( strcmp(treatment, "suppress") == 0 )
1373 fUndefinedTreatment = kUndefinedSuppress;
1374 else if ( strcmp(treatment, "dynamic_lookup") == 0 )
1375 fUndefinedTreatment = kUndefinedDynamicLookup;
1376 else
1377 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1380 Options::Treatment Options::parseTreatment(const char* treatment)
1382 if ( treatment == NULL )
1383 return kNULL;
1385 if ( strcmp(treatment, "warning") == 0 )
1386 return kWarning;
1387 else if ( strcmp(treatment, "error") == 0 )
1388 return kError;
1389 else if ( strcmp(treatment, "suppress") == 0 )
1390 return kSuppress;
1391 else
1392 return kInvalid;
1395 void Options::setMacOSXVersionMin(const char* version)
1397 if ( version == NULL )
1398 throw "-macosx_version_min argument missing";
1400 if ( (strncmp(version, "10.", 3) == 0) && isdigit(version[3]) ) {
1401 unsigned int minorVersion = 0;
1402 for (int i=3; isdigit(version[i]); ++i) {
1403 minorVersion = minorVersion*10 + (version[i] - '0');
1405 if ( minorVersion > 255 ) {
1406 warning("Mac OS X minor version > 255 in '%s'", version);
1407 minorVersion = 255;
1409 fMacVersionMin = (ld::MacVersionMin)(0x000A0000 | (minorVersion << 8));
1410 fPlatform = kPlatformOSX;
1412 else {
1413 warning("unknown option to -macosx_version_min, not 10.x");
1417 void Options::setIOSVersionMin(const char* version)
1419 if ( version == NULL )
1420 throw "-ios_version_min argument missing";
1421 if ( ! isdigit(version[0]) )
1422 throw "-ios_version_min argument is not a number";
1423 if ( version[1] != '.' )
1424 throw "-ios_version_min argument is missing period as second character";
1425 if ( ! isdigit(version[2]) )
1426 throw "-ios_version_min argument is not a number";
1428 unsigned int majorVersion = version[0] - '0';
1429 unsigned int minorVersion = version[2] - '0';
1430 fIOSVersionMin = (ld::IOSVersionMin)((majorVersion << 16) | (minorVersion << 8));
1431 fPlatform = kPlatformiOS;
1435 void Options::setWatchOSVersionMin(const char* version)
1437 if ( version == NULL )
1438 throw "-watchos_version_min argument missing";
1439 if ( ! isdigit(version[0]) )
1440 throw "-watchos_version_min argument is not a number";
1441 if ( version[1] != '.' )
1442 throw "-watchos_version_min argument is missing period as second character";
1443 if ( ! isdigit(version[2]) )
1444 throw "-watchos_version_min argument is not a number";
1446 unsigned int majorVersion = version[0] - '0';
1447 unsigned int minorVersion = version[2] - '0';
1448 fWatchOSVersionMin = (ld::WatchOSVersionMin)((majorVersion << 16) | (minorVersion << 8));
1449 fPlatform = kPlatformWatchOS;
1453 bool Options::minOS(ld::MacVersionMin requiredMacMin, ld::IOSVersionMin requirediPhoneOSMin)
1455 if ( fMacVersionMin != ld::macVersionUnset ) {
1456 return ( fMacVersionMin >= requiredMacMin );
1458 else if ( fWatchOSVersionMin != ld::wOSVersionUnset ) {
1459 // Hack until we fully track watch and ios versions seperately
1460 return ( (fWatchOSVersionMin + 0x00070000) >= requirediPhoneOSMin);
1462 else {
1463 return ( fIOSVersionMin >= requirediPhoneOSMin );
1467 bool Options::min_iOS(ld::IOSVersionMin requirediOSMin)
1469 if ( fWatchOSVersionMin != ld::wOSVersionUnset ) {
1470 // Hack until we fully track watch and ios versions seperately
1471 return ( (fWatchOSVersionMin + 0x00070000) >= requirediOSMin);
1473 else {
1474 return ( fIOSVersionMin >= requirediOSMin );
1478 void Options::setWeakReferenceMismatchTreatment(const char* treatment)
1480 if ( treatment == NULL )
1481 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1483 if ( strcmp(treatment, "error") == 0 )
1484 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchError;
1485 else if ( strcmp(treatment, "weak") == 0 )
1486 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchWeak;
1487 else if ( strcmp(treatment, "non-weak") == 0 )
1488 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchNonWeak;
1489 else
1490 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1493 Options::CommonsMode Options::parseCommonsTreatment(const char* mode)
1495 if ( mode == NULL )
1496 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1498 if ( strcmp(mode, "ignore_dylibs") == 0 )
1499 return kCommonsIgnoreDylibs;
1500 else if ( strcmp(mode, "use_dylibs") == 0 )
1501 return kCommonsOverriddenByDylibs;
1502 else if ( strcmp(mode, "error") == 0 )
1503 return kCommonsConflictsDylibsError;
1504 else
1505 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1508 void Options::addDylibOverride(const char* paths)
1510 if ( paths == NULL )
1511 throw "-dylib_file must followed by two colon separated paths";
1512 const char* colon = strchr(paths, ':');
1513 if ( colon == NULL )
1514 throw "-dylib_file must followed by two colon separated paths";
1515 int len = colon-paths;
1516 char* target = new char[len+2];
1517 strncpy(target, paths, len);
1518 target[len] = '\0';
1519 DylibOverride entry;
1520 entry.installName = target;
1521 entry.useInstead = &colon[1];
1522 fDylibOverrides.push_back(entry);
1525 uint64_t Options::parseAddress(const char* addr)
1527 char* endptr;
1528 uint64_t result = strtoull(addr, &endptr, 16);
1529 return result;
1532 uint32_t Options::parseProtection(const char* prot)
1534 uint32_t result = 0;
1535 for(const char* p = prot; *p != '\0'; ++p) {
1536 switch(tolower(*p)) {
1537 case 'r':
1538 result |= VM_PROT_READ;
1539 break;
1540 case 'w':
1541 result |= VM_PROT_WRITE;
1542 break;
1543 case 'x':
1544 result |= VM_PROT_EXECUTE;
1545 break;
1546 case '-':
1547 break;
1548 default:
1549 throwf("unknown -segprot lettter in %s", prot);
1552 return result;
1557 // Parses number of form A[.B[.B[.D[.E]]]] into a uint64_t where the bits are a24.b10.c10.d10.e10
1559 uint64_t Options::parseVersionNumber64(const char* versionString)
1561 uint64_t a = 0;
1562 uint64_t b = 0;
1563 uint64_t c = 0;
1564 uint64_t d = 0;
1565 uint64_t e = 0;
1566 char* end;
1567 a = strtoul(versionString, &end, 10);
1568 if ( *end == '.' ) {
1569 b = strtoul(&end[1], &end, 10);
1570 if ( *end == '.' ) {
1571 c = strtoul(&end[1], &end, 10);
1572 if ( *end == '.' ) {
1573 d = strtoul(&end[1], &end, 10);
1574 if ( *end == '.' ) {
1575 e = strtoul(&end[1], &end, 10);
1580 if ( (*end != '\0') || (a > 0xFFFFFF) || (b > 0x3FF) || (c > 0x3FF) || (d > 0x3FF) || (e > 0x3FF) )
1581 throwf("malformed 64-bit a.b.c.d.e version number: %s", versionString);
1583 return (a << 40) | ( b << 30 ) | ( c << 20 ) | ( d << 10 ) | e;
1587 uint32_t Options::currentVersion32() const
1589 // warn if it does not fit into 32 bit vers number
1590 uint32_t a = (fDylibCurrentVersion >> 40) & 0xFFFF;
1591 uint32_t b = (fDylibCurrentVersion >> 30) & 0xFF;
1592 uint32_t c = (fDylibCurrentVersion >> 20) & 0xFF;
1593 uint64_t rep32 = ((uint64_t)a << 40) | ((uint64_t)b << 30) | ((uint64_t)c << 20);
1594 if ( rep32 != fDylibCurrentVersion ) {
1595 warning("truncating -current_version to fit in 32-bit space used by old mach-o format");
1596 a = (fDylibCurrentVersion >> 40) & 0xFFFFFF;
1597 if ( a > 0xFFFF )
1598 a = 0xFFFF;
1599 b = (fDylibCurrentVersion >> 30) & 0x3FF;
1600 if ( b > 0xFF )
1601 b = 0xFF;
1602 c = (fDylibCurrentVersion >> 20) & 0x3FF;
1603 if ( c > 0xFF )
1604 c = 0xFF;
1606 return (a << 16) | ( b << 8 ) | c;
1610 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1612 uint32_t Options::parseVersionNumber32(const char* versionString)
1614 uint32_t x = 0;
1615 uint32_t y = 0;
1616 uint32_t z = 0;
1617 char* end;
1618 x = strtoul(versionString, &end, 10);
1619 if ( *end == '.' ) {
1620 y = strtoul(&end[1], &end, 10);
1621 if ( *end == '.' ) {
1622 z = strtoul(&end[1], &end, 10);
1625 if ( (*end != '\0') || (x > 0xffff) || (y > 0xff) || (z > 0xff) )
1626 throwf("malformed 32-bit x.y.z version number: %s", versionString);
1628 return (x << 16) | ( y << 8 ) | z;
1631 static const char* cstringSymbolName(const char* orderFileString)
1633 char* result;
1634 asprintf(&result, "cstring=%s", orderFileString);
1635 // convert escaped characters
1636 char* d = result;
1637 for(const char* s=result; *s != '\0'; ++s, ++d) {
1638 if ( *s == '\\' ) {
1639 ++s;
1640 switch ( *s ) {
1641 case 'n':
1642 *d = '\n';
1643 break;
1644 case 't':
1645 *d = '\t';
1646 break;
1647 case 'v':
1648 *d = '\v';
1649 break;
1650 case 'b':
1651 *d = '\b';
1652 break;
1653 case 'r':
1654 *d = '\r';
1655 break;
1656 case 'f':
1657 *d = '\f';
1658 break;
1659 case 'a':
1660 *d = '\a';
1661 break;
1662 case '\\':
1663 *d = '\\';
1664 break;
1665 case '?':
1666 *d = '\?';
1667 break;
1668 case '\'':
1669 *d = '\r';
1670 break;
1671 case '\"':
1672 *d = '\"';
1673 break;
1674 case 'x':
1675 // hexadecimal value of char
1677 ++s;
1678 char value = 0;
1679 while ( isxdigit(*s) ) {
1680 value *= 16;
1681 if ( isdigit(*s) )
1682 value += (*s-'0');
1683 else
1684 value += ((toupper(*s)-'A') + 10);
1685 ++s;
1687 *d = value;
1689 break;
1690 default:
1691 if ( isdigit(*s) ) {
1692 // octal value of char
1693 char value = 0;
1694 while ( isdigit(*s) ) {
1695 value = (value << 3) + (*s-'0');
1696 ++s;
1698 *d = value;
1702 else {
1703 *d = *s;
1706 *d = '\0';
1707 return result;
1710 void Options::parseOrderFile(const char* path, bool cstring)
1712 // order files override auto-ordering
1713 fAutoOrderInitializers = false;
1715 // read in whole file
1716 int fd = ::open(path, O_RDONLY, 0);
1717 if ( fd == -1 )
1718 throwf("can't open order file: %s", path);
1719 struct stat stat_buf;
1720 ::fstat(fd, &stat_buf);
1721 char* p = (char*)malloc(stat_buf.st_size+1);
1722 if ( p == NULL )
1723 throwf("can't process order file: %s", path);
1724 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1725 throwf("can't read order file: %s", path);
1726 ::close(fd);
1727 p[stat_buf.st_size] = '\n';
1728 if ( this->dumpDependencyInfo() )
1729 this->dumpDependency(Options::depMisc, path);
1731 // parse into vector of pairs
1732 char * const end = &p[stat_buf.st_size+1];
1733 enum { lineStart, inSymbol, inComment } state = lineStart;
1734 char* symbolStart = NULL;
1735 for (char* s = p; s < end; ++s ) {
1736 switch ( state ) {
1737 case lineStart:
1738 if ( *s =='#' ) {
1739 state = inComment;
1741 else if ( !isspace(*s) || cstring ) {
1742 state = inSymbol;
1743 symbolStart = s;
1745 break;
1746 case inSymbol:
1747 if ( (*s == '\n') || (!cstring && (*s == '#')) ) {
1748 bool wasComment = (*s == '#');
1749 *s = '\0';
1750 // removing any trailing spaces
1751 char* last = s-1;
1752 while ( isspace(*last) ) {
1753 *last = '\0';
1754 --last;
1756 // if there is an architecture prefix, only use this symbol it if matches current arch
1757 if ( strncmp(symbolStart, "ppc:", 4) == 0 ) {
1758 symbolStart = NULL;
1760 else if ( strncmp(symbolStart, "ppc64:", 6) == 0 ) {
1761 symbolStart = NULL;
1763 else if ( strncmp(symbolStart, "i386:", 5) == 0 ) {
1764 if ( fArchitecture == CPU_TYPE_I386 )
1765 symbolStart = &symbolStart[5];
1766 else
1767 symbolStart = NULL;
1769 else if ( strncmp(symbolStart, "x86_64:", 7) == 0 ) {
1770 if ( fArchitecture == CPU_TYPE_X86_64 )
1771 symbolStart = &symbolStart[7];
1772 else
1773 symbolStart = NULL;
1775 else if ( strncmp(symbolStart, "arm:", 4) == 0 ) {
1776 if ( fArchitecture == CPU_TYPE_ARM )
1777 symbolStart = &symbolStart[4];
1778 else
1779 symbolStart = NULL;
1781 if ( symbolStart != NULL ) {
1782 char* objFileName = NULL;
1783 char* colon = strstr(symbolStart, ".o:");
1784 if ( colon != NULL ) {
1785 colon[2] = '\0';
1786 objFileName = symbolStart;
1787 symbolStart = &colon[3];
1789 else {
1790 colon = strstr(symbolStart, ".o):");
1791 if ( colon != NULL ) {
1792 colon[3] = '\0';
1793 objFileName = symbolStart;
1794 symbolStart = &colon[4];
1797 // trim leading spaces
1798 while ( isspace(*symbolStart) )
1799 ++symbolStart;
1800 Options::OrderedSymbol pair;
1801 if ( cstring )
1802 pair.symbolName = cstringSymbolName(symbolStart);
1803 else
1804 pair.symbolName = symbolStart;
1805 pair.objectFileName = objFileName;
1806 fOrderedSymbols.push_back(pair);
1808 symbolStart = NULL;
1809 if ( wasComment )
1810 state = inComment;
1811 else
1812 state = lineStart;
1814 break;
1815 case inComment:
1816 if ( *s == '\n' )
1817 state = lineStart;
1818 break;
1821 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1824 void Options::parseSectionOrderFile(const char* segment, const char* section, const char* path)
1826 if ( (strcmp(section, "__cstring") == 0) && (strcmp(segment, "__TEXT") == 0) ) {
1827 parseOrderFile(path, true);
1829 else if ( (strncmp(section, "__literal",9) == 0) && (strcmp(segment, "__TEXT") == 0) ) {
1830 warning("sorting of __literal[4,8,16] sections not supported");
1832 else {
1833 // ignore section information and append all symbol names to global order file
1834 parseOrderFile(path, false);
1838 void Options::addSection(const char* segment, const char* section, const char* path)
1840 if ( strlen(segment) > 16 )
1841 throw "-seccreate segment name max 16 chars";
1842 if ( strlen(section) > 16 ) {
1843 char* tmp = strdup(section);
1844 tmp[16] = '\0';
1845 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section, tmp);
1846 section = tmp;
1849 // read in whole file
1850 int fd = ::open(path, O_RDONLY, 0);
1851 if ( fd == -1 )
1852 throwf("can't open -sectcreate file: %s", path);
1853 struct stat stat_buf;
1854 ::fstat(fd, &stat_buf);
1855 char* p = (char*)malloc(stat_buf.st_size);
1856 if ( p == NULL )
1857 throwf("can't process -sectcreate file: %s", path);
1858 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1859 throwf("can't read -sectcreate file: %s", path);
1860 ::close(fd);
1862 // record section to create
1863 ExtraSection info = { segment, section, path, (uint8_t*)p, (uint64_t)stat_buf.st_size };
1864 fExtraSections.push_back(info);
1867 void Options::addSectionRename(const char* srcSegment, const char* srcSection, const char* dstSegment, const char* dstSection)
1869 if ( strlen(srcSegment) > 16 )
1870 throw "-rename_section segment name max 16 chars";
1871 if ( strlen(srcSection) > 16 )
1872 throw "-rename_section section name max 16 chars";
1873 if ( strlen(dstSegment) > 16 )
1874 throw "-rename_section segment name max 16 chars";
1875 if ( strlen(dstSection) > 16 )
1876 throw "-rename_section section name max 16 chars";
1878 SectionRename info;
1879 info.fromSegment = srcSegment;
1880 info.fromSection = srcSection;
1881 info.toSegment = dstSegment;
1882 info.toSection = dstSection;
1884 fSectionRenames.push_back(info);
1888 void Options::addSegmentRename(const char* srcSegment, const char* dstSegment)
1890 if ( strlen(srcSegment) > 16 )
1891 throw "-rename_segment segment name max 16 chars";
1892 if ( strlen(dstSegment) > 16 )
1893 throw "-rename_segment segment name max 16 chars";
1895 SegmentRename info;
1896 info.fromSegment = srcSegment;
1897 info.toSegment = dstSegment;
1899 fSegmentRenames.push_back(info);
1904 void Options::addSymbolMove(const char* dstSegment, const char* symbolList,
1905 std::vector<SymbolsMove>& list, const char* optionName)
1907 if ( strlen(dstSegment) > 16 )
1908 throwf("%s segment name max 16 chars", optionName);
1910 SymbolsMove tmp;
1911 list.push_back(tmp);
1912 SymbolsMove& info = list.back();
1913 info.toSegment = dstSegment;
1914 loadExportFile(symbolList, optionName, info.symbols);
1917 bool Options::moveRwSymbol(const char* symName, const char* filePath, const char*& seg, bool& wildCardMatch) const
1919 for (std::vector<SymbolsMove>::const_iterator it=fSymbolsMovesData.begin(); it != fSymbolsMovesData.end(); ++it) {
1920 const SymbolsMove& info = *it;
1921 if ( info.symbols.containsWithPrefix(symName, filePath, wildCardMatch)) {
1922 seg = info.toSegment;
1923 return true;
1926 return false;
1929 bool Options::moveRoSymbol(const char* symName, const char* filePath, const char*& seg, bool& wildCardMatch) const
1931 for (std::vector<SymbolsMove>::const_iterator it=fSymbolsMovesCode.begin(); it != fSymbolsMovesCode.end(); ++it) {
1932 const SymbolsMove& info = *it;
1933 if ( info.symbols.containsWithPrefix(symName, filePath, wildCardMatch)) {
1934 seg = info.toSegment;
1935 return true;
1938 return false;
1941 void Options::addSectionAlignment(const char* segment, const char* section, const char* alignmentStr)
1943 if ( strlen(segment) > 16 )
1944 throw "-sectalign segment name max 16 chars";
1945 if ( strlen(section) > 16 )
1946 throw "-sectalign section name max 16 chars";
1948 // argument to -sectalign is a hexadecimal number
1949 char* endptr;
1950 unsigned long value = strtoul(alignmentStr, &endptr, 16);
1951 if ( *endptr != '\0')
1952 throw "argument for -sectalign is not a hexadecimal number";
1953 if ( value > 0x8000 )
1954 throw "argument for -sectalign must be less than or equal to 0x8000";
1955 if ( value == 0 ) {
1956 warning("zero is not a valid -sectalign");
1957 value = 1;
1960 // alignment is power of 2 (e.g. page alignment = 12)
1961 uint8_t alignment = (uint8_t)__builtin_ctz(value);
1962 if ( (unsigned long)(1 << alignment) != value ) {
1963 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
1964 segment, section, 1 << alignment);
1967 SectionAlignment info = { segment, section, alignment };
1968 fSectionAlignments.push_back(info);
1971 void Options::addLibrary(const FileInfo& info)
1973 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
1974 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
1975 if ( strcmp(info.path, fit->path) == 0 ) {
1976 // if dylib is specified again but weak, record that it should be weak
1977 if ( info.options.fWeakImport )
1978 fit->options.fWeakImport = true;
1979 return;
1982 // add to list
1983 fInputFiles.push_back(info);
1986 void Options::warnObsolete(const char* arg)
1988 warning("option %s is obsolete and being ignored", arg);
1992 void Options::cannotBeUsedWithBitcode(const char* arg)
1994 if ( fBundleBitcode )
1995 throwf("%s and -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES) cannot be used together", arg);
1998 std::string Options::getVersionString32(uint32_t ver) const
2000 if (ver == 0 || ver >= 0x10000000)
2001 return "0.0.0";
2003 unsigned microVersion = ver & 0xFF;
2004 unsigned minorVersion = (ver >> 8) & 0xFF;
2005 unsigned majorVersion = (ver >> 16) & 0xFF;
2006 std::stringstream versionString;
2007 versionString << majorVersion << "." << minorVersion << "." << microVersion;
2008 return versionString.str();
2011 std::string Options::getVersionString64(uint64_t ver) const
2013 uint64_t a = (ver >> 40) & 0xFFFFFF;
2014 uint64_t b = (ver >> 30) & 0x3FF;
2015 uint64_t c = (ver >> 20) & 0x3FF;
2016 uint64_t d = (ver >> 10) & 0x3FF;
2017 uint64_t e = ver & 0x3FF;
2018 std::stringstream versionString;
2019 versionString << a << "." << b << "." << c << "." << d << "." << e;
2020 return versionString.str();
2023 std::string Options::getSDKVersionStr() const
2025 return getVersionString32(fSDKVersion);
2028 std::string Options::getPlatformStr() const
2030 switch (fPlatform) {
2031 case Options::kPlatformOSX:
2032 return "MacOSX";
2033 case Options::kPlatformiOS:
2034 if (targetIOSSimulator())
2035 return "iPhoneSimulator";
2036 else
2037 return "iPhoneOS";
2038 case Options::kPlatformWatchOS:
2039 if (targetIOSSimulator())
2040 return "watchOS Simulator";
2041 else
2042 return "watchOS";
2043 #if SUPPORT_APPLE_TV
2044 case Options::kPlatform_tvOS:
2045 if (targetIOSSimulator())
2046 return "AppleTVSimulator";
2047 else
2048 return "AppleTVOS";
2049 break;
2050 #endif
2051 case Options::kPlatformUnknown:
2052 return "Unknown";
2056 std::vector<std::string> Options::writeBitcodeLinkOptions() const
2058 std::vector<std::string> linkCommand;
2059 switch ( fOutputKind ) {
2060 case Options::kDynamicLibrary:
2061 linkCommand.push_back("-dylib");
2062 linkCommand.push_back("-compatibility_version");
2063 if ( fDylibCompatVersion != 0 ) {
2064 linkCommand.push_back(getVersionString32(fDylibCompatVersion));
2065 } else {
2066 linkCommand.push_back(getVersionString32(currentVersion32()));
2068 if ( fDylibCurrentVersion != 0 ) {
2069 linkCommand.push_back("-current_version");
2070 linkCommand.push_back(getVersionString64(fDylibCurrentVersion));
2072 linkCommand.push_back("-install_name");
2073 linkCommand.push_back(installPath());
2074 break;
2075 case Options::kDynamicExecutable:
2076 linkCommand.push_back("-execute");
2077 break;
2078 case Options::kObjectFile:
2079 linkCommand.push_back("-r");
2080 break;
2081 default:
2082 throwf("could not write bitcode options file output kind\n");
2085 if (!fImplicitlyLinkPublicDylibs)
2086 linkCommand.push_back("-no_implicit_dylibs");
2088 // Add deployment target.
2089 // Platform is allowed to be unknown for "ld -r".
2090 switch (fPlatform) {
2091 case Options::kPlatformOSX:
2092 linkCommand.push_back("-macosx_version_min");
2093 linkCommand.push_back(getVersionString32((unsigned)fMacVersionMin));
2094 break;
2095 case Options::kPlatformiOS:
2096 if (targetIOSSimulator())
2097 linkCommand.push_back("-ios_simulator_version_min");
2098 else
2099 linkCommand.push_back("-ios_version_min");
2100 linkCommand.push_back(getVersionString32((unsigned)fIOSVersionMin));
2101 break;
2102 case Options::kPlatformWatchOS:
2103 if (targetIOSSimulator())
2104 linkCommand.push_back("-watchos_simulator_version_min");
2105 else
2106 linkCommand.push_back("-watchos_version_min");
2107 linkCommand.push_back(getVersionString32((unsigned)fIOSVersionMin));
2108 break;
2109 #if SUPPORT_APPLE_TV
2110 case Options::kPlatform_tvOS:
2111 if (targetIOSSimulator())
2112 linkCommand.push_back("-tvos_simulator_version_min");
2113 else
2114 linkCommand.push_back("-tvos_version_min");
2115 linkCommand.push_back(getVersionString32((unsigned)fIOSVersionMin));
2116 break;
2117 #endif
2118 case Options::kPlatformUnknown:
2119 if ( fOutputKind != Options::kObjectFile ) {
2120 throwf("platform is unknown for final bitcode bundle,"
2121 "deployment target and min version is required for -bitcode_bundle");
2123 break;
2127 // entry name
2128 if ( fEntryName ) {
2129 linkCommand.push_back("-e");
2130 linkCommand.push_back(fEntryName);
2133 // Write rpaths
2134 if (!fRPaths.empty()) {
2135 for (std::vector<const char*>::const_iterator it=fRPaths.begin(); it != fRPaths.end(); ++it) {
2136 linkCommand.push_back("-rpath");
2137 linkCommand.push_back(*it);
2141 // Other bitcode compatiable options
2142 if ( fObjCABIVersion1Override ) {
2143 linkCommand.push_back("-objc_abi_version");
2144 linkCommand.push_back("1");
2145 } else if ( fObjCABIVersion2Override ) {
2146 linkCommand.push_back("-objc_abi_version");
2147 linkCommand.push_back("2");
2149 if ( fExecutablePath ) {
2150 linkCommand.push_back("-executable_path");
2151 linkCommand.push_back(fExecutablePath);
2153 if ( fDeadStrip )
2154 linkCommand.push_back("-dead_strip");
2155 if ( fExportDynamic )
2156 linkCommand.push_back("-export_dynamic");
2157 if ( fMarkAppExtensionSafe && fCheckAppExtensionSafe )
2158 linkCommand.push_back("-application_extension");
2160 if ( fSourceVersionLoadCommandForceOn )
2161 linkCommand.push_back("-add_source_version");
2162 if ( fSourceVersion != 0 ) {
2163 linkCommand.push_back("-source_version");
2164 linkCommand.push_back(getVersionString64(fSourceVersion));
2167 // linker flag added by swift driver
2168 // rdar://problem/20108072
2169 if ( !fObjcCategoryMerging )
2170 linkCommand.push_back("-no_objc_category_merging");
2172 return linkCommand;
2176 // Process all command line arguments.
2178 // The only error checking done here is that each option is valid and if it has arguments
2179 // that they too are valid.
2181 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
2182 // whichever was last on the command line is used.
2184 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
2186 void Options::parse(int argc, const char* argv[])
2188 // Store the original args in the link snapshot.
2189 fLinkSnapshot.recordRawArgs(argc, argv);
2191 // pass one builds search list from -L and -F options
2192 this->buildSearchPaths(argc, argv);
2194 // reduce re-allocations
2195 fInputFiles.reserve(32);
2197 // pass two parse all other options
2198 for(int i=1; i < argc; ++i) {
2199 const char* arg = argv[i];
2201 if ( arg[0] == '-' ) {
2202 // by default, copy one arg to the snapshot link command, and do no file copying
2203 int snapshotArgIndex = i;
2204 int snapshotArgCount = -1; // -1 means compute count based on change in index
2205 int snapshotFileArgIndex = -1; // -1 means no data file parameter to arg
2207 // Since we don't care about the files passed, just the option names, we do this here.
2208 if (fPrintOptions)
2209 fprintf (stderr, "[Logging ld64 options]\t%s\n", arg);
2211 if ( (arg[1] == 'L') || (arg[1] == 'F') ) {
2212 snapshotArgCount = 0; // stripped out of link snapshot
2213 if (arg[2] == '\0')
2214 ++i;
2215 // previously handled by buildSearchPaths()
2217 // The one gnu style option we have to keep compatibility
2218 // with gcc. Might as well have the single hyphen one as well.
2219 else if ( (strcmp(arg, "--help") == 0)
2220 || (strcmp(arg, "-help") == 0)) {
2221 fprintf (stdout, "ld64: For information on command line options please use 'man ld'.\n");
2222 exit (0);
2224 else if ( strcmp(arg, "-arch") == 0 ) {
2225 parseArch(argv[++i]);
2227 else if ( strcmp(arg, "-dynamic") == 0 ) {
2228 // default
2230 else if ( strcmp(arg, "-static") == 0 ) {
2231 fForStatic = true;
2232 if ( (fOutputKind != kObjectFile) && (fOutputKind != kKextBundle) ) {
2233 fOutputKind = kStaticExecutable;
2235 cannotBeUsedWithBitcode(arg);
2237 else if ( strcmp(arg, "-dylib") == 0 ) {
2238 fOutputKind = kDynamicLibrary;
2240 else if ( strcmp(arg, "-bundle") == 0 ) {
2241 fOutputKind = kDynamicBundle;
2242 cannotBeUsedWithBitcode(arg);
2244 else if ( strcmp(arg, "-dylinker") == 0 ) {
2245 fOutputKind = kDyld;
2246 cannotBeUsedWithBitcode(arg);
2248 else if ( strcmp(arg, "-execute") == 0 ) {
2249 if ( fOutputKind != kStaticExecutable )
2250 fOutputKind = kDynamicExecutable;
2252 else if ( strcmp(arg, "-preload") == 0 ) {
2253 fOutputKind = kPreload;
2254 cannotBeUsedWithBitcode(arg);
2256 else if ( strcmp(arg, "-r") == 0 ) {
2257 fOutputKind = kObjectFile;
2259 else if ( strcmp(arg, "-kext") == 0 ) {
2260 fOutputKind = kKextBundle;
2261 cannotBeUsedWithBitcode(arg);
2263 else if ( strcmp(arg, "-o") == 0 ) {
2264 snapshotArgCount = 0;
2265 fOutputFile = argv[++i];
2266 fLinkSnapshot.setSnapshotName(fOutputFile);
2268 else if ( strncmp(arg, "-lazy-l", 7) == 0 ) {
2269 snapshotArgCount = 0;
2270 FileInfo info = findLibrary(&arg[7], true);
2271 info.options.fLazyLoad = true;
2272 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2273 addLibrary(info);
2274 fUsingLazyDylibLinking = true;
2275 cannotBeUsedWithBitcode(arg);
2277 else if ( strcmp(arg, "-lto_library") == 0 ) {
2278 snapshotFileArgIndex = 1;
2279 fOverridePathlibLTO = argv[++i];
2280 if ( fOverridePathlibLTO == NULL )
2281 throw "missing argument to -lto_library";
2283 else if ( (arg[1] == 'l') && (strncmp(arg,"-lazy_",6) !=0) ) {
2284 snapshotArgCount = 0;
2285 FileInfo info = findLibrary(&arg[2]);
2286 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2287 addLibrary(info);
2289 // This causes a dylib to be weakly bound at
2290 // link time. This corresponds to weak_import.
2291 else if ( strncmp(arg, "-weak-l", 7) == 0 ) {
2292 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2293 snapshotArgCount = 0;
2294 FileInfo info = findLibrary(&arg[7]);
2295 info.options.fWeakImport = true;
2296 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2297 addLibrary(info);
2299 // Avoid lazy binding.
2300 else if ( strcmp(arg, "-bind_at_load") == 0 ) {
2301 fBindAtLoad = true;
2302 cannotBeUsedWithBitcode(arg);
2304 else if ( strcmp(arg, "-twolevel_namespace") == 0 ) {
2305 fNameSpace = kTwoLevelNameSpace;
2307 else if ( strcmp(arg, "-flat_namespace") == 0 ) {
2308 fNameSpace = kFlatNameSpace;
2309 cannotBeUsedWithBitcode(arg);
2311 // Also sets a bit to ensure dyld causes everything
2312 // in the namespace to be flat.
2313 // ??? Deprecate
2314 else if ( strcmp(arg, "-force_flat_namespace") == 0 ) {
2315 fNameSpace = kForceFlatNameSpace;
2316 cannotBeUsedWithBitcode(arg);
2318 // Similar to --whole-archive.
2319 else if ( strcmp(arg, "-all_load") == 0 ) {
2320 fFullyLoadArchives = true;
2322 else if ( strcmp(arg, "-noall_load") == 0) {
2323 warnObsolete(arg);
2325 // Similar to -all_load
2326 else if ( strcmp(arg, "-ObjC") == 0 ) {
2327 fLoadAllObjcObjectsFromArchives = true;
2329 // Similar to -all_load, but for the following archive only.
2330 else if ( strcmp(arg, "-force_load") == 0 ) {
2331 FileInfo info = findFile(argv[++i]);
2332 info.options.fForceLoad = true;
2333 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2334 addLibrary(info);
2336 // Library versioning.
2337 else if ( (strcmp(arg, "-dylib_compatibility_version") == 0)
2338 || (strcmp(arg, "-compatibility_version") == 0)) {
2339 const char* vers = argv[++i];
2340 if ( vers == NULL )
2341 throw "-dylib_compatibility_version missing <version>";
2342 fDylibCompatVersion = parseVersionNumber32(vers);
2344 else if ( (strcmp(arg, "-dylib_current_version") == 0)
2345 || (strcmp(arg, "-current_version") == 0)) {
2346 const char* vers = argv[++i];
2347 if ( vers == NULL )
2348 throw "-dylib_current_version missing <version>";
2349 fDylibCurrentVersion = parseVersionNumber64(vers);
2351 else if ( strcmp(arg, "-sectorder") == 0 ) {
2352 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
2353 throw "-sectorder missing <segment> <section> <file-path>";
2354 snapshotFileArgIndex = 3;
2355 parseSectionOrderFile(argv[i+1], argv[i+2], argv[i+3]);
2356 i += 3;
2357 cannotBeUsedWithBitcode(arg);
2359 else if ( strcmp(arg, "-order_file") == 0 ) {
2360 snapshotFileArgIndex = 1;
2361 parseOrderFile(argv[++i], false);
2362 cannotBeUsedWithBitcode(arg);
2364 else if ( strcmp(arg, "-order_file_statistics") == 0 ) {
2365 fPrintOrderFileStatistics = true;
2366 cannotBeUsedWithBitcode(arg);
2368 // ??? Deprecate segcreate.
2369 // -sectcreate puts whole files into a section in the output.
2370 else if ( (strcmp(arg, "-sectcreate") == 0) || (strcmp(arg, "-segcreate") == 0) ) {
2371 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
2372 throw "-sectcreate missing <segment> <section> <file-path>";
2373 snapshotFileArgIndex = 3;
2374 addSection(argv[i+1], argv[i+2], argv[i+3]);
2375 i += 3;
2377 // Since we have a full path in binary/library names we need to be able to override it.
2378 else if ( (strcmp(arg, "-dylib_install_name") == 0)
2379 || (strcmp(arg, "-dylinker_install_name") == 0)
2380 || (strcmp(arg, "-install_name") == 0)) {
2381 fDylibInstallName = argv[++i];
2382 if ( fDylibInstallName == NULL )
2383 throw "-install_name missing <path>";
2385 // Sets the base address of the output.
2386 else if ( (strcmp(arg, "-seg1addr") == 0) || (strcmp(arg, "-image_base") == 0) ) {
2387 const char* address = argv[++i];
2388 if ( address == NULL )
2389 throwf("%s missing <address>", arg);
2390 fBaseAddress = parseAddress(address);
2391 uint64_t temp = ((fBaseAddress+fSegmentAlignment-1) & (-fSegmentAlignment));
2392 if ( fBaseAddress != temp ) {
2393 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment);
2394 fBaseAddress = temp;
2396 cannotBeUsedWithBitcode(arg);
2398 else if ( strcmp(arg, "-e") == 0 ) {
2399 fEntryName = argv[++i];
2401 // Same as -@ from the FSF linker.
2402 else if ( strcmp(arg, "-filelist") == 0 ) {
2403 snapshotArgCount = 0;
2404 const char* path = argv[++i];
2405 if ( (path == NULL) || (path[0] == '-') )
2406 throw "-filelist missing <path>";
2407 ld::File::Ordinal baseOrdinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2408 loadFileList(path, baseOrdinal);
2410 else if ( strcmp(arg, "-keep_private_externs") == 0 ) {
2411 cannotBeUsedWithBitcode(arg);
2412 fKeepPrivateExterns = true;
2414 else if ( strcmp(arg, "-final_output") == 0 ) {
2415 fFinalName = argv[++i];
2417 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
2418 // just ensures that this happens for cross object file boundaries.
2419 else if ( (strcmp(arg, "-interposable") == 0) || (strcmp(arg, "-multi_module") == 0)) {
2420 switch ( fInterposeMode ) {
2421 case kInterposeNone:
2422 case kInterposeAllExternal:
2423 fInterposeMode = kInterposeAllExternal;
2424 break;
2425 case kInterposeSome:
2426 // do nothing, -interposable_list overrides -interposable"
2427 break;
2429 cannotBeUsedWithBitcode(arg);
2431 else if ( strcmp(arg, "-interposable_list") == 0 ) {
2432 snapshotFileArgIndex = 1;
2433 fInterposeMode = kInterposeSome;
2434 loadExportFile(argv[++i], "-interposable_list", fInterposeList);
2435 cannotBeUsedWithBitcode(arg);
2437 // Default for -interposable/-multi_module/-single_module.
2438 else if ( strcmp(arg, "-single_module") == 0 ) {
2439 fInterposeMode = kInterposeNone;
2441 else if ( strcmp(arg, "-exported_symbols_list") == 0 ) {
2442 snapshotFileArgIndex = 1;
2443 if ( fExportMode == kDontExportSome )
2444 throw "can't use -exported_symbols_list and -unexported_symbols_list";
2445 fExportMode = kExportSome;
2446 loadExportFile(argv[++i], "-exported_symbols_list", fExportSymbols);
2448 else if ( strcmp(arg, "-unexported_symbols_list") == 0 ) {
2449 snapshotFileArgIndex = 1;
2450 if ( fExportMode == kExportSome )
2451 throw "can't use -unexported_symbols_list and -exported_symbols_list";
2452 fExportMode = kDontExportSome;
2453 loadExportFile(argv[++i], "-unexported_symbols_list", fDontExportSymbols);
2454 cannotBeUsedWithBitcode(arg);
2456 else if ( strcmp(arg, "-exported_symbol") == 0 ) {
2457 if ( fExportMode == kDontExportSome )
2458 throw "can't use -exported_symbol and -unexported_symbols";
2459 fExportMode = kExportSome;
2460 fExportSymbols.insert(argv[++i]);
2462 else if ( strcmp(arg, "-unexported_symbol") == 0 ) {
2463 if ( fExportMode == kExportSome )
2464 throw "can't use -unexported_symbol and -exported_symbol";
2465 fExportMode = kDontExportSome;
2466 fDontExportSymbols.insert(argv[++i]);
2467 cannotBeUsedWithBitcode(arg);
2469 else if ( strcmp(arg, "-non_global_symbols_no_strip_list") == 0 ) {
2470 snapshotFileArgIndex = 1;
2471 if ( fLocalSymbolHandling == kLocalSymbolsSelectiveExclude )
2472 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2473 fLocalSymbolHandling = kLocalSymbolsSelectiveInclude;
2474 loadExportFile(argv[++i], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded);
2475 cannotBeUsedWithBitcode(arg);
2477 else if ( strcmp(arg, "-non_global_symbols_strip_list") == 0 ) {
2478 snapshotFileArgIndex = 1;
2479 if ( fLocalSymbolHandling == kLocalSymbolsSelectiveInclude )
2480 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2481 fLocalSymbolHandling = kLocalSymbolsSelectiveExclude;
2482 loadExportFile(argv[++i], "-non_global_symbols_strip_list", fLocalSymbolsExcluded);
2483 cannotBeUsedWithBitcode(arg);
2485 // ??? Deprecate
2486 else if ( strcmp(arg, "-no_arch_warnings") == 0 ) {
2487 fIgnoreOtherArchFiles = true;
2489 else if ( strcmp(arg, "-force_cpusubtype_ALL") == 0 ) {
2490 fForceSubtypeAll = true;
2491 fAllowCpuSubtypeMismatches = true;
2492 cannotBeUsedWithBitcode(arg);
2494 // Similar to -weak-l but uses the absolute path name to the library.
2495 else if ( strcmp(arg, "-weak_library") == 0 ) {
2496 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2497 snapshotArgCount = 0;
2498 FileInfo info = findFile(argv[++i]);
2499 info.options.fWeakImport = true;
2500 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2501 addLibrary(info);
2502 cannotBeUsedWithBitcode(arg);
2504 else if ( strcmp(arg, "-lazy_library") == 0 ) {
2505 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2506 snapshotArgCount = 0;
2507 FileInfo info = findFile(argv[++i]);
2508 info.options.fLazyLoad = true;
2509 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2510 addLibrary(info);
2511 fUsingLazyDylibLinking = true;
2512 cannotBeUsedWithBitcode(arg);
2514 else if ( strcmp(arg, "-framework") == 0 ) {
2515 snapshotArgCount = 0;
2516 FileInfo info = findFramework(argv[++i]);
2517 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2518 addLibrary(info);
2520 else if ( strcmp(arg, "-weak_framework") == 0 ) {
2521 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2522 snapshotArgCount = 0;
2523 FileInfo info = findFramework(argv[++i]);
2524 info.options.fWeakImport = true;
2525 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2526 addLibrary(info);
2528 else if ( strcmp(arg, "-lazy_framework") == 0 ) {
2529 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2530 snapshotArgCount = 0;
2531 FileInfo info = findFramework(argv[++i]);
2532 info.options.fLazyLoad = true;
2533 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2534 addLibrary(info);
2535 fUsingLazyDylibLinking = true;
2536 cannotBeUsedWithBitcode(arg);
2538 else if ( strcmp(arg, "-search_paths_first") == 0 ) {
2539 // previously handled by buildSearchPaths()
2541 else if ( strcmp(arg, "-search_dylibs_first") == 0 ) {
2542 // previously handled by buildSearchPaths()
2544 else if ( strcmp(arg, "-undefined") == 0 ) {
2545 setUndefinedTreatment(argv[++i]);
2546 cannotBeUsedWithBitcode(arg);
2548 // Debugging output flag.
2549 else if ( strcmp(arg, "-arch_multiple") == 0 ) {
2550 fMessagesPrefixedWithArchitecture = true;
2552 // Specify what to do with relocations in read only
2553 // sections like .text. Could be errors, warnings,
2554 // or suppressed. Currently we do nothing with the
2555 // flag.
2556 else if ( strcmp(arg, "-read_only_relocs") == 0 ) {
2557 switch ( parseTreatment(argv[++i]) ) {
2558 case kNULL:
2559 case kInvalid:
2560 throw "-read_only_relocs missing [ warning | error | suppress ]";
2561 case kWarning:
2562 fWarnTextRelocs = true;
2563 fAllowTextRelocs = true;
2564 cannotBeUsedWithBitcode(arg);
2565 break;
2566 case kSuppress:
2567 fWarnTextRelocs = false;
2568 fAllowTextRelocs = true;
2569 cannotBeUsedWithBitcode(arg);
2570 break;
2571 case kError:
2572 fWarnTextRelocs = false;
2573 fAllowTextRelocs = false;
2574 break;
2577 else if ( strcmp(arg, "-sect_diff_relocs") == 0 ) {
2578 warnObsolete(arg);
2579 ++i;
2581 // Warn, error or make strong a mismatch between weak
2582 // and non-weak references.
2583 else if ( strcmp(arg, "-weak_reference_mismatches") == 0 ) {
2584 setWeakReferenceMismatchTreatment(argv[++i]);
2586 // For a deployment target of 10.3 and earlier ld64 will
2587 // prebind an executable with 0s in all addresses that
2588 // are prebound. This can then be fixed up by update_prebinding
2589 // later. Prebinding is less useful on 10.4 and greater.
2590 else if ( strcmp(arg, "-prebind") == 0 ) {
2591 fPrebind = true;
2592 cannotBeUsedWithBitcode(arg);
2594 else if ( strcmp(arg, "-noprebind") == 0 ) {
2595 warnObsolete(arg);
2596 fPrebind = false;
2598 else if ( strcmp(arg, "-prebind_allow_overlap") == 0 ) {
2599 warnObsolete(arg);
2601 else if ( strcmp(arg, "-prebind_all_twolevel_modules") == 0 ) {
2602 warnObsolete(arg);
2604 else if ( strcmp(arg, "-noprebind_all_twolevel_modules") == 0 ) {
2605 warnObsolete(arg);
2607 else if ( strcmp(arg, "-nofixprebinding") == 0 ) {
2608 warnObsolete(arg);
2610 // This should probably be deprecated when we respect -L and -F
2611 // when searching for libraries.
2612 else if ( strcmp(arg, "-dylib_file") == 0 ) {
2613 // ignore for snapshot because a stub dylib will be created in the snapshot
2614 snapshotArgCount = 0;
2615 addDylibOverride(argv[++i]);
2616 cannotBeUsedWithBitcode(arg);
2618 // What to expand @executable_path to if found in dependent dylibs
2619 else if ( strcmp(arg, "-executable_path") == 0 ) {
2620 fExecutablePath = argv[++i];
2621 if ( (fExecutablePath == NULL) || (fExecutablePath[0] == '-') )
2622 throw "-executable_path missing <path>";
2623 // if a directory was passed, add / to end
2624 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2625 struct stat statBuffer;
2626 if ( stat(fExecutablePath, &statBuffer) == 0 ) {
2627 if ( (statBuffer.st_mode & S_IFMT) == S_IFDIR ) {
2628 char* pathWithSlash = new char[strlen(fExecutablePath)+2];
2629 strcpy(pathWithSlash, fExecutablePath);
2630 strcat(pathWithSlash, "/");
2631 fExecutablePath = pathWithSlash;
2635 // Aligns all segments to the power of 2 boundary specified.
2636 else if ( strcmp(arg, "-segalign") == 0 ) {
2637 const char* size = argv[++i];
2638 if ( size == NULL )
2639 throw "-segalign missing <size>";
2640 fSegmentAlignment = parseAddress(size);
2641 uint8_t alignment = (uint8_t)__builtin_ctz(fSegmentAlignment);
2642 uint32_t p2aligned = (1 << alignment);
2643 if ( p2aligned != fSegmentAlignment ) {
2644 warning("alignment for -segalign %s is not a power of two, using 0x%X", size, p2aligned);
2645 fSegmentAlignment = p2aligned;
2647 cannotBeUsedWithBitcode(arg);
2649 // Puts a specified segment at a particular address that must
2650 // be a multiple of the segment alignment.
2651 else if ( strcmp(arg, "-segaddr") == 0 ) {
2652 SegmentStart seg;
2653 seg.name = argv[++i];
2654 if ( (seg.name == NULL) || (argv[i+1] == NULL) )
2655 throw "-segaddr missing segName Adddress";
2656 seg.address = parseAddress(argv[++i]);
2657 uint64_t temp = ((seg.address+fSegmentAlignment-1) & (-fSegmentAlignment));
2658 if ( seg.address != temp )
2659 warning("-segaddr %s not %lld byte aligned", seg.name, fSegmentAlignment);
2660 fCustomSegmentAddresses.push_back(seg);
2661 cannotBeUsedWithBitcode(arg);
2663 // ??? Deprecate when we deprecate split-seg.
2664 else if ( strcmp(arg, "-segs_read_only_addr") == 0 ) {
2665 fBaseAddress = parseAddress(argv[++i]);
2666 cannotBeUsedWithBitcode(arg);
2668 // ??? Deprecate when we deprecate split-seg.
2669 else if ( strcmp(arg, "-segs_read_write_addr") == 0 ) {
2670 fBaseWritableAddress = parseAddress(argv[++i]);
2671 fSplitSegs = true;
2672 cannotBeUsedWithBitcode(arg);
2674 // ??? Deprecate when we get rid of basing at build time.
2675 else if ( strcmp(arg, "-seg_addr_table") == 0 ) {
2676 snapshotFileArgIndex = 1;
2677 const char* name = argv[++i];
2678 if ( name == NULL )
2679 throw "-seg_addr_table missing argument";
2680 fSegAddrTablePath = name;
2681 cannotBeUsedWithBitcode(arg);
2683 else if ( strcmp(arg, "-seg_addr_table_filename") == 0 ) {
2684 warnObsolete(arg);
2685 ++i;
2687 else if ( strcmp(arg, "-segprot") == 0 ) {
2688 SegmentProtect seg;
2689 seg.name = argv[++i];
2690 if ( (seg.name == NULL) || (argv[i+1] == NULL) || (argv[i+2] == NULL) )
2691 throw "-segprot missing segName max-prot init-prot";
2692 seg.max = parseProtection(argv[++i]);
2693 seg.init = parseProtection(argv[++i]);
2694 fCustomSegmentProtections.push_back(seg);
2695 cannotBeUsedWithBitcode(arg);
2697 else if ( strcmp(arg, "-pagezero_size") == 0 ) {
2698 const char* size = argv[++i];
2699 if ( size == NULL )
2700 throw "-pagezero_size missing <size>";
2701 fZeroPageSize = parseAddress(size);
2702 uint64_t temp = fZeroPageSize & (-4096); // page align
2703 if ( (fZeroPageSize != temp) )
2704 warning("-pagezero_size not page aligned, rounding down");
2705 fZeroPageSize = temp;
2706 cannotBeUsedWithBitcode(arg);
2708 else if ( strcmp(arg, "-stack_addr") == 0 ) {
2709 const char* address = argv[++i];
2710 if ( address == NULL )
2711 throw "-stack_addr missing <address>";
2712 fStackAddr = parseAddress(address);
2713 cannotBeUsedWithBitcode(arg);
2715 else if ( strcmp(arg, "-stack_size") == 0 ) {
2716 const char* size = argv[++i];
2717 if ( size == NULL )
2718 throw "-stack_size missing <address>";
2719 fStackSize = parseAddress(size);
2720 uint64_t temp = fStackSize & (-4096); // page align
2721 if ( (fStackSize != temp) )
2722 warning("-stack_size not page aligned, rounding down");
2724 else if ( strcmp(arg, "-allow_stack_execute") == 0 ) {
2725 fExecutableStack = true;
2726 cannotBeUsedWithBitcode(arg);
2728 else if ( strcmp(arg, "-allow_heap_execute") == 0 ) {
2729 fDisableNonExecutableHeap = true;
2730 cannotBeUsedWithBitcode(arg);
2732 else if ( strcmp(arg, "-sectalign") == 0 ) {
2733 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
2734 throw "-sectalign missing <segment> <section> <file-path>";
2735 addSectionAlignment(argv[i+1], argv[i+2], argv[i+3]);
2736 i += 3;
2737 cannotBeUsedWithBitcode(arg);
2739 else if ( strcmp(arg, "-sectorder_detail") == 0 ) {
2740 warnObsolete(arg);
2742 else if ( strcmp(arg, "-sectobjectsymbols") == 0 ) {
2743 warnObsolete(arg);
2744 i += 2;
2746 else if ( strcmp(arg, "-bundle_loader") == 0 ) {
2747 snapshotFileArgIndex = 1;
2748 fBundleLoader = argv[++i];
2749 if ( (fBundleLoader == NULL) || (fBundleLoader[0] == '-') )
2750 throw "-bundle_loader missing <path>";
2751 FileInfo info = findFile(fBundleLoader);
2752 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2753 info.options.fBundleLoader = true;
2754 fInputFiles.push_back(info);
2756 else if ( strcmp(arg, "-private_bundle") == 0 ) {
2757 warnObsolete(arg);
2759 else if ( strcmp(arg, "-twolevel_namespace_hints") == 0 ) {
2760 // FIX FIX
2762 // Use this flag to set default behavior for deployement targets.
2763 else if ( strcmp(arg, "-macosx_version_min") == 0 ) {
2764 const char* macVers = argv[++i];
2765 const char* envMacVers = getenv("MACOSX_DEPLOYMENT_TARGET");
2766 const char* enviPhoneVers = getenv("IPHONEOS_DEPLOYMENT_TARGET");
2767 if ( (envMacVers != NULL) && (enviPhoneVers != NULL) ) {
2768 // <rdar://problem/13774329> when conflicting deployments set, break tie by looking at syslibroot
2769 warning("both MACOSX_DEPLOYMENT_TARGET and IPHONEOS_DEPLOYMENT_TARGET are set");
2770 if ( !fSDKPaths.empty() ) {
2771 const char* sysrootPath = fSDKPaths.back();
2772 const char* lastSlash = strrchr(sysrootPath, '/');
2773 if ( strstr(lastSlash, "Simulator") != NULL )
2774 setIOSVersionMin(enviPhoneVers);
2775 else
2776 setMacOSXVersionMin(macVers);
2778 else {
2779 setMacOSXVersionMin(macVers);
2782 else {
2783 setMacOSXVersionMin(macVers);
2786 else if ( (strcmp(arg, "-ios_version_min") == 0) || (strcmp(arg, "-iphoneos_version_min") == 0) ) {
2787 setIOSVersionMin(argv[++i]);
2789 else if ( strcmp(arg, "-ios_simulator_version_min") == 0 ) {
2790 setIOSVersionMin(argv[++i]);
2791 fTargetIOSSimulator = true;
2793 else if ( strcmp(arg, "-watchos_version_min") == 0 ) {
2794 setWatchOSVersionMin(argv[++i]);
2796 else if ( strcmp(arg, "-watchos_simulator_version_min") == 0 ) {
2797 setWatchOSVersionMin(argv[++i]);
2798 fTargetIOSSimulator = true;
2800 #if SUPPORT_APPLE_TV
2801 else if ( strcmp(arg, "-tvos_version_min") == 0 ) {
2802 setIOSVersionMin(argv[++i]);
2803 fPlatform = kPlatform_tvOS;
2805 else if ( strcmp(arg, "-tvos_simulator_version_min") == 0 ) {
2806 setIOSVersionMin(argv[++i]);
2807 fPlatform = kPlatform_tvOS;
2808 fTargetIOSSimulator = true;
2810 #endif
2811 else if ( strcmp(arg, "-multiply_defined") == 0 ) {
2812 //warnObsolete(arg);
2813 ++i;
2815 else if ( strcmp(arg, "-multiply_defined_unused") == 0 ) {
2816 warnObsolete(arg);
2817 ++i;
2819 else if ( strcmp(arg, "-nomultidefs") == 0 ) {
2820 warnObsolete(arg);
2822 // Display each file in which the argument symbol appears and whether
2823 // the file defines or references it. This option takes an argument
2824 // as -y<symbol> note that there is no space.
2825 else if ( strncmp(arg, "-y", 2) == 0 ) {
2826 warnObsolete("-y");
2828 // Same output as -y, but output <arg> number of undefined symbols only.
2829 else if ( strcmp(arg, "-Y") == 0 ) {
2830 //warnObsolete(arg);
2831 ++i;
2833 // This option affects all objects linked into the final result.
2834 else if ( strcmp(arg, "-m") == 0 ) {
2835 warnObsolete(arg);
2837 else if ( (strcmp(arg, "-why_load") == 0) || (strcmp(arg, "-whyload") == 0) ) {
2838 fWhyLoad = true;
2840 else if ( strcmp(arg, "-why_live") == 0 ) {
2841 const char* name = argv[++i];
2842 if ( name == NULL )
2843 throw "-why_live missing symbol name argument";
2844 fWhyLive.insert(name);
2846 else if ( strcmp(arg, "-u") == 0 ) {
2847 const char* name = argv[++i];
2848 if ( name == NULL )
2849 throw "-u missing argument";
2850 fInitialUndefines.push_back(name);
2851 cannotBeUsedWithBitcode(arg);
2853 else if ( strcmp(arg, "-U") == 0 ) {
2854 const char* name = argv[++i];
2855 if ( name == NULL )
2856 throw "-U missing argument";
2857 fAllowedUndefined.insert(name);
2858 cannotBeUsedWithBitcode(arg);
2860 else if ( strcmp(arg, "-s") == 0 ) {
2861 warnObsolete(arg);
2862 fLocalSymbolHandling = kLocalSymbolsNone;
2863 fDebugInfoStripping = Options::kDebugInfoNone;
2865 else if ( strcmp(arg, "-x") == 0 ) {
2866 fLocalSymbolHandling = kLocalSymbolsNone;
2868 else if ( strcmp(arg, "-S") == 0 ) {
2869 fDebugInfoStripping = Options::kDebugInfoNone;
2871 else if ( strcmp(arg, "-X") == 0 ) {
2872 warnObsolete(arg);
2874 else if ( strcmp(arg, "-Si") == 0 ) {
2875 warnObsolete(arg);
2876 fDebugInfoStripping = Options::kDebugInfoFull;
2878 else if ( strcmp(arg, "-b") == 0 ) {
2879 warnObsolete(arg);
2881 else if ( strcmp(arg, "-Sn") == 0 ) {
2882 warnObsolete(arg);
2883 fDebugInfoStripping = Options::kDebugInfoFull;
2885 else if ( strcmp(arg, "-Sp") == 0 ) {
2886 warnObsolete(arg);
2888 else if ( strcmp(arg, "-dead_strip") == 0 ) {
2889 fDeadStrip = true;
2891 else if ( strcmp(arg, "-no_dead_strip_inits_and_terms") == 0 ) {
2892 fDeadStrip = true;
2894 else if ( strcmp(arg, "-w") == 0 ) {
2895 // previously handled by buildSearchPaths()
2897 else if ( strcmp(arg, "-fatal_warnings") == 0 ) {
2898 // previously handled by buildSearchPaths()
2900 else if ( strcmp(arg, "-arch_errors_fatal") == 0 ) {
2901 fErrorOnOtherArchFiles = true;
2903 else if ( strcmp(arg, "-M") == 0 ) {
2904 // FIX FIX
2906 else if ( strcmp(arg, "-headerpad") == 0 ) {
2907 const char* size = argv[++i];
2908 if ( size == NULL )
2909 throw "-headerpad missing argument";
2910 fMinimumHeaderPad = parseAddress(size);
2911 cannotBeUsedWithBitcode(arg);
2913 else if ( strcmp(arg, "-headerpad_max_install_names") == 0 ) {
2914 // ignore -headerpad_max_install_names when compiling with bitcode
2915 // rdar://problem/20748962
2916 if ( fBundleBitcode )
2917 warning("-headerpad_max_install_names is ignored when used with -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES)");
2918 else
2919 fMaxMinimumHeaderPad = true;
2921 else if ( strcmp(arg, "-t") == 0 ) {
2922 fLogAllFiles = true;
2924 else if ( strcmp(arg, "-whatsloaded") == 0 ) {
2925 fLogObjectFiles = true;
2927 else if ( strcmp(arg, "-A") == 0 ) {
2928 warnObsolete(arg);
2929 ++i;
2931 else if ( strcmp(arg, "-umbrella") == 0 ) {
2932 const char* name = argv[++i];
2933 if ( name == NULL )
2934 throw "-umbrella missing argument";
2935 fUmbrellaName = name;
2936 cannotBeUsedWithBitcode(arg);
2938 else if ( strcmp(arg, "-allowable_client") == 0 ) {
2939 const char* name = argv[++i];
2941 if ( name == NULL )
2942 throw "-allowable_client missing argument";
2944 fAllowableClients.push_back(name);
2945 cannotBeUsedWithBitcode(arg);
2947 else if ( strcmp(arg, "-client_name") == 0 ) {
2948 const char* name = argv[++i];
2950 if ( name == NULL )
2951 throw "-client_name missing argument";
2953 fClientName = name;
2954 cannotBeUsedWithBitcode(arg);
2956 else if ( strcmp(arg, "-sub_umbrella") == 0 ) {
2957 const char* name = argv[++i];
2958 if ( name == NULL )
2959 throw "-sub_umbrella missing argument";
2960 fSubUmbellas.push_back(name);
2961 cannotBeUsedWithBitcode(arg);
2963 else if ( strcmp(arg, "-sub_library") == 0 ) {
2964 const char* name = argv[++i];
2965 if ( name == NULL )
2966 throw "-sub_library missing argument";
2967 fSubLibraries.push_back(name);
2968 cannotBeUsedWithBitcode(arg);
2970 else if ( strcmp(arg, "-init") == 0 ) {
2971 const char* name = argv[++i];
2972 if ( name == NULL )
2973 throw "-init missing argument";
2974 fInitFunctionName = name;
2975 cannotBeUsedWithBitcode(arg);
2977 else if ( strcmp(arg, "-dot") == 0 ) {
2978 const char* name = argv[++i];
2979 if ( name == NULL )
2980 throw "-dot missing argument";
2981 fDotOutputFile = name;
2982 cannotBeUsedWithBitcode(arg);
2984 else if ( strcmp(arg, "-warn_commons") == 0 ) {
2985 fWarnCommons = true;
2987 else if ( strcmp(arg, "-commons") == 0 ) {
2988 fCommonsMode = parseCommonsTreatment(argv[++i]);
2990 else if ( strcmp(arg, "-keep_relocs") == 0 ) {
2991 fKeepRelocations = true;
2993 else if ( strcmp(arg, "-warn_stabs") == 0 ) {
2994 fWarnStabs = true;
2996 else if ( strcmp(arg, "-pause") == 0 ) {
2997 fPause = true;
2999 else if ( strcmp(arg, "-print_statistics") == 0 ) {
3000 fStatistics = true;
3002 else if ( strcmp(arg, "-d") == 0 ) {
3003 fMakeTentativeDefinitionsReal = true;
3005 else if ( strcmp(arg, "-v") == 0 ) {
3006 // previously handled by buildSearchPaths()
3008 else if ( strcmp(arg, "-Z") == 0 ) {
3009 // previously handled by buildSearchPaths()
3011 else if ( strcmp(arg, "-syslibroot") == 0 ) {
3012 snapshotArgCount = 0;
3013 ++i;
3014 // previously handled by buildSearchPaths()
3016 else if ( strcmp(arg, "-bitcode_bundle") == 0 ) {
3017 snapshotArgCount = 0;
3018 // previously handled by buildSearchPaths()
3020 else if ( strcmp(arg, "-no_uuid") == 0 ) {
3021 fUUIDMode = kUUIDNone;
3022 cannotBeUsedWithBitcode(arg);
3024 else if ( strcmp(arg, "-random_uuid") == 0 ) {
3025 fUUIDMode = kUUIDRandom;
3026 cannotBeUsedWithBitcode(arg);
3028 else if ( strcmp(arg, "-dtrace") == 0 ) {
3029 snapshotFileArgIndex = 1;
3030 const char* name = argv[++i];
3031 if ( name == NULL )
3032 throw "-dtrace missing argument";
3033 fDtraceScriptName = name;
3034 cannotBeUsedWithBitcode(arg);
3036 else if ( strcmp(arg, "-root_safe") == 0 ) {
3037 fRootSafe = true;
3039 else if ( strcmp(arg, "-setuid_safe") == 0 ) {
3040 fSetuidSafe = true;
3042 else if ( strcmp(arg, "-alias") == 0 ) {
3043 Options::AliasPair pair;
3044 pair.realName = argv[++i];
3045 if ( pair.realName == NULL )
3046 throw "missing argument to -alias";
3047 pair.alias = argv[++i];
3048 if ( pair.alias == NULL )
3049 throw "missing argument to -alias";
3050 fAliases.push_back(pair);
3051 cannotBeUsedWithBitcode(arg);
3053 else if ( strcmp(arg, "-alias_list") == 0 ) {
3054 snapshotFileArgIndex = 1;
3055 parseAliasFile(argv[++i]);
3056 cannotBeUsedWithBitcode(arg);
3058 else if ( strcmp(arg, "-save-temps") == 0 ) {
3059 fSaveTempFiles = true;
3061 else if ( strcmp(arg, "-bitcode_hide_symbols") == 0 ) {
3062 fHideSymbols = true;
3063 if ( !fBundleBitcode )
3064 warning("-bitcode_hide_symbols is ignored without -bitcode_bundle");
3066 else if ( strcmp(arg, "-bitcode_symbol_map") == 0) {
3067 fReverseMapPath = argv[++i];
3068 if ( fReverseMapPath == NULL )
3069 throw "missing argument to -bitcode_symbol_map";
3070 struct stat statbuf;
3071 ::stat(fReverseMapPath, &statbuf);
3072 if (S_ISDIR(statbuf.st_mode)) {
3073 char tempPath[PATH_MAX];
3074 sprintf(tempPath, "%s/XXXXXX", fReverseMapPath);
3075 int tempFile = ::mkstemp(tempPath);
3076 if (tempFile == -1)
3077 throwf("could not write file to symbol map directory: %s", fReverseMapPath);
3078 ::close(tempFile);
3079 fReverseMapTempPath = std::string(tempPath);
3080 fReverseMapUUIDRename = true;
3081 } else
3082 fReverseMapTempPath = std::string(fReverseMapPath);
3084 else if ( strcmp(argv[i], "-flto-codegen-only") == 0) {
3085 fLTOCodegenOnly = true;
3087 else if ( strcmp(argv[i], "-ignore_auto_link") == 0) {
3088 fIgnoreAutoLink = true;
3090 else if ( strcmp(arg, "-rpath") == 0 ) {
3091 const char* path = argv[++i];
3092 if ( path == NULL )
3093 throw "missing argument to -rpath";
3094 fRPaths.push_back(path);
3096 else if ( strcmp(arg, "-read_only_stubs") == 0 ) {
3097 fReadOnlyx86Stubs = true;
3099 else if ( strcmp(arg, "-slow_stubs") == 0 ) {
3100 warnObsolete(arg);
3102 else if ( strcmp(arg, "-map") == 0 ) {
3103 fMapPath = argv[++i];
3104 if ( fMapPath == NULL )
3105 throw "missing argument to -map";
3107 else if ( strcmp(arg, "-pie") == 0 ) {
3108 fPositionIndependentExecutable = true;
3109 fPIEOnCommandLine = true;
3111 else if ( strcmp(arg, "-no_pie") == 0 ) {
3112 fDisablePositionIndependentExecutable = true;
3113 cannotBeUsedWithBitcode(arg);
3115 else if ( strncmp(arg, "-reexport-l", 11) == 0 ) {
3116 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3117 snapshotArgCount = 0;
3118 FileInfo info = findLibrary(&arg[11], true);
3119 info.options.fReExport = true;
3120 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
3121 addLibrary(info);
3122 cannotBeUsedWithBitcode(arg);
3124 else if ( strcmp(arg, "-reexport_library") == 0 ) {
3125 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3126 snapshotArgCount = 0;
3127 FileInfo info = findFile(argv[++i]);
3128 info.options.fReExport = true;
3129 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
3130 addLibrary(info);
3131 cannotBeUsedWithBitcode(arg);
3133 else if ( strcmp(arg, "-reexport_framework") == 0 ) {
3134 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3135 snapshotArgCount = 0;
3136 FileInfo info = findFramework(argv[++i]);
3137 info.options.fReExport = true;
3138 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
3139 addLibrary(info);
3140 cannotBeUsedWithBitcode(arg);
3142 else if ( strncmp(arg, "-upward-l", 9) == 0 ) {
3143 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3144 snapshotArgCount = 0;
3145 FileInfo info = findLibrary(&arg[9], true);
3146 info.options.fUpward = true;
3147 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
3148 addLibrary(info);
3149 cannotBeUsedWithBitcode(arg);
3151 else if ( strcmp(arg, "-upward_library") == 0 ) {
3152 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3153 snapshotArgCount = 0;
3154 FileInfo info = findFile(argv[++i]);
3155 info.options.fUpward = true;
3156 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
3157 addLibrary(info);
3158 cannotBeUsedWithBitcode(arg);
3160 else if ( strcmp(arg, "-upward_framework") == 0 ) {
3161 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3162 snapshotArgCount = 0;
3163 FileInfo info = findFramework(argv[++i]);
3164 info.options.fUpward = true;
3165 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
3166 addLibrary(info);
3167 cannotBeUsedWithBitcode(arg);
3169 else if ( strcmp(arg, "-dead_strip_dylibs") == 0 ) {
3170 fDeadStripDylibs = true;
3171 cannotBeUsedWithBitcode(arg);
3173 else if ( strcmp(arg, "-no_implicit_dylibs") == 0 ) {
3174 fImplicitlyLinkPublicDylibs = false;
3176 else if ( strcmp(arg, "-new_linker") == 0 ) {
3177 // ignore
3179 else if ( strcmp(arg, "-no_encryption") == 0 ) {
3180 fEncryptableForceOff = true;
3181 cannotBeUsedWithBitcode(arg);
3183 else if ( strcmp(arg, "-encryptable") == 0 ) {
3184 fEncryptableForceOn = true;
3185 cannotBeUsedWithBitcode(arg);
3187 else if ( strcmp(arg, "-no_compact_unwind") == 0 ) {
3188 fAddCompactUnwindEncoding = false;
3189 cannotBeUsedWithBitcode(arg);
3191 else if ( strcmp(arg, "-mllvm") == 0 ) {
3192 const char* opts = argv[++i];
3193 if ( opts == NULL )
3194 throw "missing argument to -mllvm";
3195 fLLVMOptions.push_back(opts);
3196 cannotBeUsedWithBitcode(arg);
3198 else if ( strcmp(arg, "-mcpu") == 0 ) {
3199 const char* cpu = argv[++i];
3200 if ( cpu == NULL )
3201 throw "missing argument to -mcpu";
3202 fLtoCpu = cpu;
3203 cannotBeUsedWithBitcode(arg);
3205 else if ( strcmp(arg, "-no_order_inits") == 0 ) {
3206 fAutoOrderInitializers = false;
3207 cannotBeUsedWithBitcode(arg);
3209 else if ( strcmp(arg, "-no_order_data") == 0 ) {
3210 fOrderData = false;
3211 cannotBeUsedWithBitcode(arg);
3213 else if ( strcmp(arg, "-seg_page_size") == 0 ) {
3214 SegmentSize seg;
3215 seg.name = argv[++i];
3216 if ( (seg.name == NULL) || (argv[i+1] == NULL) )
3217 throw "-seg_page_size missing segName Adddress";
3218 seg.size = parseAddress(argv[++i]);
3219 uint64_t temp = seg.size & (-4096); // page align
3220 if ( (seg.size != temp) )
3221 warning("-seg_page_size %s not 4K aligned, rounding down", seg.name);
3222 fCustomSegmentSizes.push_back(seg);
3223 cannotBeUsedWithBitcode(arg);
3225 else if ( strcmp(arg, "-mark_dead_strippable_dylib") == 0 ) {
3226 fMarkDeadStrippableDylib = true;
3227 cannotBeUsedWithBitcode(arg);
3229 else if ( strcmp(arg, "-exported_symbols_order") == 0 ) {
3230 snapshotFileArgIndex = 1;
3231 loadSymbolOrderFile(argv[++i], fExportSymbolsOrder);
3232 cannotBeUsedWithBitcode(arg);
3234 else if ( strcmp(arg, "-no_compact_linkedit") == 0 ) {
3235 warnObsolete("-no_compact_linkedit");
3237 else if ( strcmp(arg, "-no_eh_labels") == 0 ) {
3238 fNoEHLabels = true;
3239 cannotBeUsedWithBitcode(arg);
3241 else if ( strcmp(arg, "-warn_compact_unwind") == 0 ) {
3242 fWarnCompactUnwind = true;
3244 else if ( strcmp(arg, "-allow_sub_type_mismatches") == 0 ) {
3245 fAllowCpuSubtypeMismatches = true;
3246 cannotBeUsedWithBitcode(arg);
3248 else if ( strcmp(arg, "-no_zero_fill_sections") == 0 ) {
3249 fOptimizeZeroFill = false;
3250 cannotBeUsedWithBitcode(arg);
3252 else if ( strcmp(arg, "-merge_zero_fill_sections") == 0 ) {
3253 fMergeZeroFill = true;
3254 cannotBeUsedWithBitcode(arg);
3256 else if ( strcmp(arg, "-objc_abi_version") == 0 ) {
3257 const char* version = argv[++i];
3258 if ( version == NULL )
3259 throw "-objc_abi_version missing version number";
3260 if ( strcmp(version, "2") == 0 ) {
3261 fObjCABIVersion1Override = false;
3262 fObjCABIVersion2Override = true;
3264 else if ( strcmp(version, "1") == 0 ) {
3265 fObjCABIVersion1Override = true;
3266 fObjCABIVersion2Override = false;
3268 else
3269 warning("ignoring unrecognized argument (%s) to -objc_abi_version", version);
3271 else if ( strcmp(arg, "-warn_weak_exports") == 0 ) {
3272 fWarnWeakExports = true;
3274 else if ( strcmp(arg, "-objc_gc_compaction") == 0 ) {
3275 fObjcGcCompaction = true;
3276 cannotBeUsedWithBitcode(arg);
3278 else if ( strcmp(arg, "-objc_gc") == 0 ) {
3279 fObjCGc = true;
3280 if ( fObjCGcOnly ) {
3281 warning("-objc_gc overriding -objc_gc_only");
3282 fObjCGcOnly = false;
3284 cannotBeUsedWithBitcode(arg);
3286 else if ( strcmp(arg, "-objc_gc_only") == 0 ) {
3287 fObjCGcOnly = true;
3288 if ( fObjCGc ) {
3289 warning("-objc_gc_only overriding -objc_gc");
3290 fObjCGc = false;
3292 cannotBeUsedWithBitcode(arg);
3294 else if ( strcmp(arg, "-demangle") == 0 ) {
3295 fDemangle = true;
3297 else if ( strcmp(arg, "-version_load_command") == 0 ) {
3298 fVersionLoadCommandForcedOn = true;
3299 fVersionLoadCommandForcedOff = false;
3301 else if ( strcmp(arg, "-no_version_load_command") == 0 ) {
3302 fVersionLoadCommandForcedOff = true;
3303 fVersionLoadCommandForcedOn = false;
3304 cannotBeUsedWithBitcode(arg);
3306 else if ( strcmp(arg, "-function_starts") == 0 ) {
3307 fFunctionStartsForcedOn = true;
3308 fFunctionStartsForcedOff = false;
3310 else if ( strcmp(arg, "-no_function_starts") == 0 ) {
3311 fFunctionStartsForcedOff = true;
3312 fFunctionStartsForcedOn = false;
3313 cannotBeUsedWithBitcode(arg);
3315 else if ( strcmp(arg, "-no_data_in_code_info") == 0 ) {
3316 fDataInCodeInfoLoadCommandForcedOff = true;
3317 fDataInCodeInfoLoadCommandForcedOn = false;
3318 cannotBeUsedWithBitcode(arg);
3320 else if ( strcmp(arg, "-data_in_code_info") == 0 ) {
3321 fDataInCodeInfoLoadCommandForcedOn = true;
3322 fDataInCodeInfoLoadCommandForcedOff = false;
3324 else if ( strcmp(arg, "-object_path_lto") == 0 ) {
3325 fTempLtoObjectPath = argv[++i];
3326 if ( fTempLtoObjectPath == NULL )
3327 throw "missing argument to -object_path_lto";
3329 else if ( strcmp(arg, "-no_objc_category_merging") == 0 ) {
3330 fObjcCategoryMerging = false;
3332 else if ( strcmp(arg, "-force_symbols_weak_list") == 0 ) {
3333 snapshotFileArgIndex = 1;
3334 loadExportFile(argv[++i], "-force_symbols_weak_list", fForceWeakSymbols);
3335 cannotBeUsedWithBitcode(arg);
3337 else if ( strcmp(arg, "-force_symbols_not_weak_list") == 0 ) {
3338 snapshotFileArgIndex = 1;
3339 loadExportFile(argv[++i], "-force_symbols_not_weak_list", fForceNotWeakSymbols);
3340 cannotBeUsedWithBitcode(arg);
3342 else if ( strcmp(arg, "-force_symbol_weak") == 0 ) {
3343 const char* symbol = argv[++i];
3344 if ( symbol == NULL )
3345 throw "-force_symbol_weak missing <symbol>";
3346 fForceWeakSymbols.insert(symbol);
3347 cannotBeUsedWithBitcode(arg);
3349 else if ( strcmp(arg, "-force_symbol_not_weak") == 0 ) {
3350 const char* symbol = argv[++i];
3351 if ( symbol == NULL )
3352 throw "-force_symbol_not_weak missing <symbol>";
3353 fForceNotWeakSymbols.insert(symbol);
3354 cannotBeUsedWithBitcode(arg);
3356 else if ( strcmp(arg, "-reexported_symbols_list") == 0 ) {
3357 snapshotFileArgIndex = 1;
3358 if ( fExportMode == kExportSome )
3359 throw "can't use -exported_symbols_list and -reexported_symbols_list";
3360 loadExportFile(argv[++i], "-reexported_symbols_list", fReExportSymbols);
3362 else if ( strcmp(arg, "-dyld_env") == 0 ) {
3363 const char* envarg = argv[++i];
3364 if ( envarg == NULL )
3365 throw "-dyld_env missing ENV=VALUE";
3366 if ( strchr(envarg, '=') == NULL )
3367 throw "-dyld_env missing ENV=VALUE";
3368 fDyldEnvironExtras.push_back(envarg);
3369 cannotBeUsedWithBitcode(arg);
3371 else if ( strcmp(arg, "-page_align_data_atoms") == 0 ) {
3372 fPageAlignDataAtoms = true;
3373 cannotBeUsedWithBitcode(arg);
3375 else if (strcmp(arg, "-debug_snapshot") == 0) {
3376 fLinkSnapshot.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG);
3377 fSnapshotRequested = true;
3378 cannotBeUsedWithBitcode(arg);
3380 else if (strcmp(arg, "-snapshot_dir") == 0) {
3381 const char* path = argv[++i];
3382 if ( path == NULL )
3383 throw "-snapshot_dir missing path";
3384 fLinkSnapshot.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG);
3385 fLinkSnapshot.setSnapshotPath(path);
3386 fSnapshotRequested = true;
3387 cannotBeUsedWithBitcode(arg);
3389 else if ( strcmp(arg, "-new_main") == 0 ) {
3390 fEntryPointLoadCommandForceOn = true;
3391 cannotBeUsedWithBitcode(arg);
3393 else if ( strcmp(arg, "-no_new_main") == 0 ) {
3394 fEntryPointLoadCommandForceOff = true;
3395 cannotBeUsedWithBitcode(arg);
3397 else if ( strcmp(arg, "-source_version") == 0 ) {
3398 const char* vers = argv[++i];
3399 if ( vers == NULL )
3400 throw "-source_version missing <version>";
3401 fSourceVersion = parseVersionNumber64(vers);
3403 else if ( strcmp(arg, "-add_source_version") == 0 ) {
3404 fSourceVersionLoadCommandForceOn = true;
3406 else if ( strcmp(arg, "-no_source_version") == 0 ) {
3407 fSourceVersionLoadCommandForceOff = true;
3408 cannotBeUsedWithBitcode(arg);
3410 else if ( strcmp(arg, "-sdk_version") == 0 ) {
3411 const char* vers = argv[++i];
3412 if ( vers == NULL )
3413 throw "-sdk_version missing <version>";
3414 fSDKVersion = parseVersionNumber32(vers);
3416 else if ( strcmp(arg, "-dependent_dr_info") == 0 ) {
3417 warnObsolete(arg);
3419 else if ( strcmp(arg, "-no_dependent_dr_info") == 0 ) {
3420 warnObsolete(arg);
3422 else if ( strcmp(arg, "-kexts_use_stubs") == 0 ) {
3423 fKextsUseStubs = true;
3424 cannotBeUsedWithBitcode(arg);
3426 else if ( strcmp(argv[i], "-dependency_info") == 0 ) {
3427 snapshotArgCount = 0;
3428 ++i;
3429 // previously handled by buildSearchPaths()
3431 else if ( strcmp(arg, "-export_dynamic") == 0 ) {
3432 fExportDynamic = true;
3434 else if ( strcmp(arg, "-force_symbols_coalesce_list") == 0 ) {
3435 snapshotFileArgIndex = 1;
3436 loadExportFile(argv[++i], "-force_symbols_coalesce_list", fForceCoalesceSymbols);
3438 else if ( strcmp(arg, "-add_linker_option") == 0 ) {
3439 // ex: -add_linker_option '-framework Foundation'
3440 const char* optString = argv[++i];
3441 if ( optString == NULL )
3442 throw "-add_linker_option missing <option>";
3443 // break up into list of tokens at whitespace
3444 std::vector<const char*> opts;
3445 char* buffer = strdup(optString);
3446 char* start = buffer;
3447 for (char* s = buffer; ; ++s) {
3448 if ( isspace(*s) ) {
3449 *s = '\0';
3450 opts.push_back(start);
3451 start = s+1;
3453 else if ( *s == '\0' ) {
3454 opts.push_back(start);
3455 break;
3458 fLinkerOptions.push_back(opts);
3459 cannotBeUsedWithBitcode(arg);
3461 else if ( strcmp(arg, "-allow_simulator_linking_to_macosx_dylibs") == 0 ) {
3462 fAllowSimulatorToLinkWithMacOSX = true;
3463 cannotBeUsedWithBitcode(arg);
3465 else if ( strcmp(arg, "-keep_dwarf_unwind") == 0 ) {
3466 fKeepDwarfUnwindForcedOn = true;
3467 fKeepDwarfUnwindForcedOff = false;
3468 cannotBeUsedWithBitcode(arg);
3470 else if ( strcmp(arg, "-no_keep_dwarf_unwind") == 0 ) {
3471 fKeepDwarfUnwindForcedOn = false;
3472 fKeepDwarfUnwindForcedOff = true;
3473 cannotBeUsedWithBitcode(arg);
3475 else if ( strcmp(arg, "-verbose_optimization_hints") == 0 ) {
3476 fVerboseOptimizationHints = true;
3478 else if ( strcmp(arg, "-ignore_optimization_hints") == 0 ) {
3479 fIgnoreOptimizationHints = true;
3480 cannotBeUsedWithBitcode(arg);
3482 else if ( strcmp(arg, "-no_dtrace_dof") == 0 ) {
3483 fGenerateDtraceDOF = false;
3485 else if ( strcmp(arg, "-rename_section") == 0 ) {
3486 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) || (argv[i+4]==NULL) )
3487 throw "-rename_section missing <segment> <section> <segment> <section>";
3488 addSectionRename(argv[i+1], argv[i+2], argv[i+3], argv[i+4]);
3489 i += 4;
3490 cannotBeUsedWithBitcode(arg);
3492 else if ( strcmp(arg, "-rename_segment") == 0 ) {
3493 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) )
3494 throw "-rename_segment missing <existing-segment> <new-segment>";
3495 addSegmentRename(argv[i+1], argv[i+2]);
3496 i += 2;
3497 cannotBeUsedWithBitcode(arg);
3499 else if ( strcmp(arg, "-move_to_ro_segment") == 0 ) {
3500 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) )
3501 throw "-move_to_ro_segment missing <segment> <symbol-list-file>";
3502 addSymbolMove(argv[i+1], argv[i+2], fSymbolsMovesCode, "-move_to_ro_segment");
3503 i += 2;
3504 cannotBeUsedWithBitcode(arg);
3506 else if ( strcmp(arg, "-move_to_rw_segment") == 0 ) {
3507 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) )
3508 throw "-move_to_rw_segment missing <segment> <symbol-list-file>";
3509 addSymbolMove(argv[i+1], argv[i+2], fSymbolsMovesData, "-move_to_rw_segment");
3510 i += 2;
3511 cannotBeUsedWithBitcode(arg);
3513 else if ( strcmp(arg, "-trace_symbol_layout") == 0 ) {
3514 fTraceSymbolLayout = true;
3516 else if ( strcmp(arg, "-no_branch_islands") == 0 ) {
3517 fAllowBranchIslands = false;
3518 cannotBeUsedWithBitcode(arg);
3520 else if ( strcmp(arg, "-segment_order") == 0 ) {
3521 // ex: -segment_order __TEXT:__DATA:__JUNK
3522 const char* optString = argv[++i];
3523 if ( optString == NULL )
3524 throw "-segment_order missing colon separated <segment-list>";
3525 if ( !fSegmentOrder.empty() )
3526 throw "-segment_order used more than once";
3527 // break up into list of tokens at colon
3528 char* buffer = strdup(optString);
3529 char* start = buffer;
3530 for (char* s = buffer; ; ++s) {
3531 if ( *s == ':' ) {
3532 *s = '\0';
3533 fSegmentOrder.push_back(start);
3534 start = s+1;
3536 else if ( *s == '\0' ) {
3537 fSegmentOrder.push_back(start);
3538 break;
3541 cannotBeUsedWithBitcode(arg);
3543 else if ( strcmp(arg, "-section_order") == 0 ) {
3544 // ex: -section_order __DATA __data:__const:__nl_pointers
3545 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) )
3546 throw "-section_order missing <segment> <section-list>";
3547 const char* segName = argv[++i];
3548 const char* optString = argv[++i];
3549 if ( sectionOrder(segName) != NULL )
3550 throwf("-section_order %s ... used more than once", segName);
3551 SectionOrderList dummy;
3552 fSectionOrder.push_back(dummy);
3553 SectionOrderList& entry = fSectionOrder.back();
3554 entry.segmentName = segName;
3555 // break up into list of tokens at colon
3556 char* buffer = strdup(optString);
3557 char* start = buffer;
3558 for (char* s = buffer; ; ++s) {
3559 if ( *s == ':' ) {
3560 *s = '\0';
3561 entry.sectionOrder.push_back(start);
3562 start = s+1;
3564 else if ( *s == '\0' ) {
3565 entry.sectionOrder.push_back(start);
3566 break;
3569 cannotBeUsedWithBitcode(arg);
3571 else if ( strcmp(arg, "-application_extension") == 0 ) {
3572 fMarkAppExtensionSafe = true;
3573 fCheckAppExtensionSafe = true;
3575 else if ( strcmp(arg, "-no_application_extension") == 0 ) {
3576 fMarkAppExtensionSafe = false;
3577 fCheckAppExtensionSafe = false;
3579 else if ( strcmp(arg, "-add_ast_path") == 0 ) {
3580 const char* path = argv[++i];
3581 if ( path == NULL )
3582 throw "-add_ast_path missing <option>";
3583 fASTFilePaths.push_back(path);
3585 else if ( strcmp(arg, "-force_load_swift_libs") == 0 ) {
3586 fForceLoadSwiftLibs = true;
3588 else if ( strcmp(arg, "-not_for_dyld_shared_cache") == 0 ) {
3589 fSharedRegionEligibleForceOff = true;
3590 cannotBeUsedWithBitcode(arg);
3592 else if ( strcmp(arg, "-dirty_data_list") == 0 ) {
3593 if ( argv[i+1] == NULL )
3594 throw "-dirty_data_list missing <symbol-list-file>";
3595 addSymbolMove("__DATA_DIRTY", argv[i+1], fSymbolsMovesData, "-dirty_data_list");
3596 ++i;
3597 cannotBeUsedWithBitcode(arg);
3599 else if ( strcmp(arg, "-data_const") == 0 ) {
3600 fUseDataConstSegmentForceOn = true;
3601 cannotBeUsedWithBitcode(arg);
3603 else if ( strcmp(arg, "-no_data_const") == 0 ) {
3604 fUseDataConstSegmentForceOff = true;
3605 cannotBeUsedWithBitcode(arg);
3607 // put this last so that it does not interfer with other options starting with 'i'
3608 else if ( strncmp(arg, "-i", 2) == 0 ) {
3609 const char* colon = strchr(arg, ':');
3610 if ( colon == NULL )
3611 throwf("unknown option: %s", arg);
3612 Options::AliasPair pair;
3613 char* temp = new char[colon-arg];
3614 strlcpy(temp, &arg[2], colon-arg-1);
3615 pair.realName = &colon[1];
3616 pair.alias = temp;
3617 fAliases.push_back(pair);
3619 else {
3620 throwf("unknown option: %s", arg);
3623 if (snapshotArgCount == -1)
3624 snapshotArgCount = i-snapshotArgIndex+1;
3625 if (snapshotArgCount > 0)
3626 fLinkSnapshot.addSnapshotLinkArg(snapshotArgIndex, snapshotArgCount, snapshotFileArgIndex);
3628 else {
3629 FileInfo info = findFile(arg);
3630 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
3631 if ( strcmp(&info.path[strlen(info.path)-2], ".a") == 0 )
3632 addLibrary(info);
3633 else
3634 fInputFiles.push_back(info);
3638 // if a -lazy option was used, implicitly link in lazydylib1.o
3639 if ( fUsingLazyDylibLinking ) {
3640 FileInfo info = findLibrary("lazydylib1.o");
3641 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)argc);
3642 addLibrary(info);
3645 if (fSnapshotRequested)
3646 fLinkSnapshot.createSnapshot();
3652 // -syslibroot <path> is used for SDK support.
3653 // The rule is that all search paths (both explicit and default) are
3654 // checked to see if they exist in the SDK. If so, that path is
3655 // replaced with the sdk prefixed path. If not, that search path
3656 // is used as is. If multiple -syslibroot options are specified
3657 // their directory structures are logically overlayed and files
3658 // from sdks specified earlier on the command line used before later ones.
3660 void Options::buildSearchPaths(int argc, const char* argv[])
3662 bool addStandardLibraryDirectories = true;
3663 std::vector<const char*> libraryPaths;
3664 std::vector<const char*> frameworkPaths;
3665 libraryPaths.reserve(10);
3666 frameworkPaths.reserve(10);
3667 // scan through argv looking for -L, -F, -Z, and -syslibroot options
3668 for(int i=0; i < argc; ++i) {
3669 if ( (argv[i][0] == '-') && (argv[i][1] == 'L') ) {
3670 const char* libSearchDir = &argv[i][2];
3671 // Allow either "-L{path}" or "-L {path}".
3672 if (argv[i][2] == '\0') {
3673 // -L {path}. Make sure there is an argument following this.
3674 const char* path = argv[++i];
3675 if ( path == NULL )
3676 throw "-L missing argument";
3677 libSearchDir = path;
3679 if ( libSearchDir[0] == '\0' )
3680 throw "-L must be immediately followed by a directory path (no space)";
3681 struct stat statbuf;
3682 if ( stat(libSearchDir, &statbuf) == 0 ) {
3683 if ( statbuf.st_mode & S_IFDIR )
3684 libraryPaths.push_back(libSearchDir);
3685 else
3686 warning("path '%s' following -L not a directory", libSearchDir);
3688 else {
3689 warning("directory not found for option '-L%s'", libSearchDir);
3692 else if ( (argv[i][0] == '-') && (argv[i][1] == 'F') ) {
3693 const char* frameworkSearchDir = &argv[i][2];
3694 // Allow either "-F{path}" or "-F {path}".
3695 if (argv[i][2] == '\0') {
3696 // -F {path}. Make sure there is an argument following this.
3697 const char* path = argv[++i];
3698 if ( path == NULL )
3699 throw "-F missing argument";
3700 frameworkSearchDir = path;
3702 if ( frameworkSearchDir[0] == '\0' )
3703 throw "-F must be immediately followed by a directory path (no space)";
3704 struct stat statbuf;
3705 if ( stat(frameworkSearchDir, &statbuf) == 0 ) {
3706 if ( statbuf.st_mode & S_IFDIR )
3707 frameworkPaths.push_back(frameworkSearchDir);
3708 else
3709 warning("path '%s' following -F not a directory", frameworkSearchDir);
3711 else {
3712 warning("directory not found for option '-F%s'", frameworkSearchDir);
3715 else if ( strcmp(argv[i], "-Z") == 0 )
3716 addStandardLibraryDirectories = false;
3717 else if ( strcmp(argv[i], "-v") == 0 ) {
3718 fVerbose = true;
3719 extern const char ldVersionString[];
3720 fprintf(stderr, "%s", ldVersionString);
3721 fprintf(stderr, "configured to support archs: %s\n", ALL_SUPPORTED_ARCHS);
3722 // if only -v specified, exit cleanly
3723 if ( argc == 2 ) {
3724 const char* ltoVers = lto::version();
3725 if ( ltoVers != NULL )
3726 fprintf(stderr, "LTO support using: %s\n", ltoVers);
3727 exit(0);
3730 else if ( strcmp(argv[i], "-syslibroot") == 0 ) {
3731 const char* path = argv[++i];
3732 if ( path == NULL )
3733 throw "-syslibroot missing argument";
3734 fSDKPaths.push_back(path);
3736 else if ( strcmp(argv[i], "-search_paths_first") == 0 ) {
3737 fLibrarySearchMode = kSearchDylibAndArchiveInEachDir;
3739 else if ( strcmp(argv[i], "-search_dylibs_first") == 0 ) {
3740 fLibrarySearchMode = kSearchAllDirsForDylibsThenAllDirsForArchives;
3742 else if ( strcmp(argv[i], "-w") == 0 ) {
3743 sEmitWarnings = false;
3745 else if ( strcmp(argv[i], "-fatal_warnings") == 0 ) {
3746 sFatalWarnings = true;
3748 else if ( strcmp(argv[i], "-dependency_info") == 0 ) {
3749 const char* path = argv[++i];
3750 if ( path == NULL )
3751 throw "-dependency_info missing <path>";
3752 fDependencyInfoPath = path;
3754 else if ( strcmp(argv[i], "-bitcode_bundle") == 0 ) {
3755 fBundleBitcode = true;
3758 int standardLibraryPathsStartIndex = libraryPaths.size();
3759 int standardFrameworkPathsStartIndex = frameworkPaths.size();
3760 if ( addStandardLibraryDirectories ) {
3761 libraryPaths.push_back("/usr/lib");
3762 libraryPaths.push_back("/usr/local/lib");
3764 frameworkPaths.push_back("/Library/Frameworks/");
3765 frameworkPaths.push_back("/System/Library/Frameworks/");
3766 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
3769 // <rdar://problem/5829579> Support for configure based hacks
3770 // if last -syslibroot is /, then ignore all syslibroots
3771 if ( fSDKPaths.size() > 0 ) {
3772 if ( strcmp(fSDKPaths.back(), "/") == 0 ) {
3773 fSDKPaths.clear();
3777 // now merge sdk and library paths to make real search paths
3778 fLibrarySearchPaths.reserve(libraryPaths.size()*(fSDKPaths.size()+1));
3779 int libIndex = 0;
3780 for (std::vector<const char*>::iterator it = libraryPaths.begin(); it != libraryPaths.end(); ++it, ++libIndex) {
3781 const char* libDir = *it;
3782 bool sdkOverride = false;
3783 if ( libDir[0] == '/' ) {
3784 char betterLibDir[PATH_MAX];
3785 if ( strstr(libDir, "/..") != NULL ) {
3786 if ( realpath(libDir, betterLibDir) != NULL )
3787 libDir = strdup(betterLibDir);
3789 const int libDirLen = strlen(libDir);
3790 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
3791 const char* sdkDir = *sdkit;
3792 const int sdkDirLen = strlen(sdkDir);
3793 char newPath[libDirLen + sdkDirLen+4];
3794 strcpy(newPath, sdkDir);
3795 if ( newPath[sdkDirLen-1] == '/' )
3796 newPath[sdkDirLen-1] = '\0';
3797 strcat(newPath, libDir);
3798 struct stat statBuffer;
3799 if ( stat(newPath, &statBuffer) == 0 ) {
3800 fLibrarySearchPaths.push_back(strdup(newPath));
3801 sdkOverride = true;
3805 if ( !sdkOverride ) {
3806 if ( (libIndex >= standardLibraryPathsStartIndex) && (fSDKPaths.size() == 1) ) {
3807 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
3808 // if one SDK is specified and a standard library path is not in the SDK, don't use it
3810 else {
3811 fLibrarySearchPaths.push_back(libDir);
3816 // now merge sdk and framework paths to make real search paths
3817 fFrameworkSearchPaths.reserve(frameworkPaths.size()*(fSDKPaths.size()+1));
3818 int frameIndex = 0;
3819 for (std::vector<const char*>::iterator it = frameworkPaths.begin(); it != frameworkPaths.end(); ++it, ++frameIndex) {
3820 const char* frameworkDir = *it;
3821 bool sdkOverride = false;
3822 if ( frameworkDir[0] == '/' ) {
3823 char betterFrameworkDir[PATH_MAX];
3824 if ( strstr(frameworkDir, "/..") != NULL ) {
3825 if ( realpath(frameworkDir, betterFrameworkDir) != NULL )
3826 frameworkDir = strdup(betterFrameworkDir);
3828 const int frameworkDirLen = strlen(frameworkDir);
3829 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
3830 const char* sdkDir = *sdkit;
3831 const int sdkDirLen = strlen(sdkDir);
3832 char newPath[frameworkDirLen + sdkDirLen+4];
3833 strcpy(newPath, sdkDir);
3834 if ( newPath[sdkDirLen-1] == '/' )
3835 newPath[sdkDirLen-1] = '\0';
3836 strcat(newPath, frameworkDir);
3837 struct stat statBuffer;
3838 if ( stat(newPath, &statBuffer) == 0 ) {
3839 fFrameworkSearchPaths.push_back(strdup(newPath));
3840 sdkOverride = true;
3844 if ( !sdkOverride ) {
3845 if ( (frameIndex >= standardFrameworkPathsStartIndex) && (fSDKPaths.size() == 1) ) {
3846 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
3847 // if one SDK is specified and a standard library path is not in the SDK, don't use it
3849 else {
3850 fFrameworkSearchPaths.push_back(frameworkDir);
3855 if ( fVerbose ) {
3856 fprintf(stderr,"Library search paths:\n");
3857 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
3858 it != fLibrarySearchPaths.end();
3859 it++)
3860 fprintf(stderr,"\t%s\n", *it);
3861 fprintf(stderr,"Framework search paths:\n");
3862 for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin();
3863 it != fFrameworkSearchPaths.end();
3864 it++)
3865 fprintf(stderr,"\t%s\n", *it);
3869 // this is run before the command line is parsed
3870 void Options::parsePreCommandLineEnvironmentSettings()
3872 if ((getenv("LD_TRACE_ARCHIVES") != NULL)
3873 || (getenv("RC_TRACE_ARCHIVES") != NULL))
3874 fTraceArchives = true;
3876 if ((getenv("LD_TRACE_DYLIBS") != NULL)
3877 || (getenv("RC_TRACE_DYLIBS") != NULL)) {
3878 fTraceDylibs = true;
3879 fTraceIndirectDylibs = true;
3882 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL) {
3883 fTraceDylibSearching = true;
3886 if (getenv("LD_PRINT_OPTIONS") != NULL)
3887 fPrintOptions = true;
3889 if (fTraceDylibs || fTraceArchives)
3890 fTraceOutputFile = getenv("LD_TRACE_FILE");
3892 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL)
3893 fPrintOrderFileStatistics = true;
3895 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL)
3896 fSplitSegs = true;
3898 if (getenv("LD_NO_ENCRYPT") != NULL) {
3899 fEncryptable = false;
3900 fMarkAppExtensionSafe = true; // temporary
3901 fCheckAppExtensionSafe = false;
3904 if (getenv("LD_APPLICATION_EXTENSION_SAFE") != NULL) {
3905 fMarkAppExtensionSafe = true;
3906 fCheckAppExtensionSafe = false;
3909 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL)
3910 fAllowCpuSubtypeMismatches = true;
3912 sWarningsSideFilePath = getenv("LD_WARN_FILE");
3914 const char* customDyldPath = getenv("LD_DYLD_PATH");
3915 if ( customDyldPath != NULL )
3916 fDyldInstallPath = customDyldPath;
3918 const char* debugArchivePath = getenv("LD_DEBUG_SNAPSHOT");
3919 if (debugArchivePath != NULL) {
3920 fLinkSnapshot.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG);
3921 if (strlen(debugArchivePath) > 0)
3922 fLinkSnapshot.setSnapshotPath(debugArchivePath);
3923 fSnapshotRequested = true;
3926 const char* pipeFdString = getenv("LD_PIPELINE_FIFO");
3927 if (pipeFdString != NULL) {
3928 fPipelineFifo = pipeFdString;
3933 // this is run after the command line is parsed
3934 void Options::parsePostCommandLineEnvironmentSettings()
3936 // when building a dynamic main executable, default any use of @executable_path to output path
3937 if ( fExecutablePath == NULL && (fOutputKind == kDynamicExecutable) ) {
3938 fExecutablePath = fOutputFile;
3941 // allow build system to set default seg_addr_table
3942 if ( fSegAddrTablePath == NULL )
3943 fSegAddrTablePath = getenv("LD_SEG_ADDR_TABLE");
3945 // allow build system to turn on prebinding
3946 if ( !fPrebind ) {
3947 fPrebind = ( getenv("LD_PREBIND") != NULL );
3950 // allow build system to force on dead-code-stripping
3951 if ( !fDeadStrip ) {
3952 if ( getenv("LD_DEAD_STRIP") != NULL ) {
3953 switch (fOutputKind) {
3954 case Options::kDynamicLibrary:
3955 case Options::kDynamicExecutable:
3956 case Options::kDynamicBundle:
3957 fDeadStrip = true;
3958 break;
3959 case Options::kPreload:
3960 case Options::kObjectFile:
3961 case Options::kDyld:
3962 case Options::kStaticExecutable:
3963 case Options::kKextBundle:
3964 break;
3969 // allow build system to force on -warn_commons
3970 if ( getenv("LD_WARN_COMMONS") != NULL )
3971 fWarnCommons = true;
3973 // allow B&I to set default -source_version
3974 if ( fSourceVersion == 0 ) {
3975 const char* vers = getenv("RC_ProjectSourceVersion");
3976 if ( vers != NULL )
3977 fSourceVersion = parseVersionNumber64(vers);
3982 void Options::reconfigureDefaults()
3984 // sync reader options
3985 switch ( fOutputKind ) {
3986 case Options::kObjectFile:
3987 fForFinalLinkedImage = false;
3988 break;
3989 case Options::kDyld:
3990 fForDyld = true;
3991 fForFinalLinkedImage = true;
3992 fNoEHLabels = true;
3993 break;
3994 case Options::kDynamicLibrary:
3995 case Options::kDynamicBundle:
3996 case Options::kKextBundle:
3997 fForFinalLinkedImage = true;
3998 fNoEHLabels = true;
3999 break;
4000 case Options::kDynamicExecutable:
4001 case Options::kStaticExecutable:
4002 case Options::kPreload:
4003 fLinkingMainExecutable = true;
4004 fForFinalLinkedImage = true;
4005 fNoEHLabels = true;
4006 break;
4009 // set default min OS version
4010 if ( (fMacVersionMin == ld::macVersionUnset) && (fIOSVersionMin == ld::iOSVersionUnset) && (fWatchOSVersionMin == ld::wOSVersionUnset) ) {
4011 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
4012 const char* macVers = getenv("MACOSX_DEPLOYMENT_TARGET");
4013 const char* iPhoneVers = getenv("IPHONEOS_DEPLOYMENT_TARGET");
4014 const char* iOSVers = getenv("IOS_DEPLOYMENT_TARGET");
4015 const char* wOSVers = getenv("WATCHOS_DEPLOYMENT_TARGET");
4016 if ( macVers != NULL )
4017 setMacOSXVersionMin(macVers);
4018 else if ( iPhoneVers != NULL )
4019 setIOSVersionMin(iPhoneVers);
4020 else if ( iOSVers != NULL )
4021 setIOSVersionMin(iOSVers);
4022 else if ( wOSVers != NULL )
4023 setWatchOSVersionMin(wOSVers);
4024 else {
4025 // if still nothing, set default based on architecture
4026 switch ( fArchitecture ) {
4027 case CPU_TYPE_I386:
4028 case CPU_TYPE_X86_64:
4029 if ( (fOutputKind != Options::kObjectFile) && (fOutputKind != Options::kPreload) ) {
4030 #ifdef DEFAULT_MACOSX_MIN_VERSION
4031 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION);
4032 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
4033 #else
4034 warning("-macosx_version_min not specified, assuming 10.6");
4035 setMacOSXVersionMin("10.6");
4036 #endif
4038 break;
4039 case CPU_TYPE_ARM:
4040 if ( (fOutputKind != Options::kObjectFile) && (fOutputKind != Options::kPreload) ) {
4041 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
4042 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION);
4043 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION);
4044 #else
4045 if ( fSubArchitecture == CPU_SUBTYPE_ARM_V7K ) {
4046 warning("-watchos_version_min not specified, assuming 2.0");
4047 setWatchOSVersionMin("2.0");
4049 else {
4050 warning("-ios_version_min not specified, assuming 6.0");
4051 setIOSVersionMin("6.0");
4053 #endif
4055 break;
4056 default:
4057 // architecture will be infered later by examining .o files
4058 break;
4064 // adjust min based on architecture
4065 switch ( fArchitecture ) {
4066 case CPU_TYPE_I386:
4067 if ( (fPlatform == kPlatformOSX) && (fMacVersionMin < ld::mac10_4) ) {
4068 //warning("-macosx_version_min should be 10.4 or later for i386");
4069 fMacVersionMin = ld::mac10_4;
4071 break;
4072 case CPU_TYPE_X86_64:
4073 if ( (fPlatform == kPlatformOSX) && (fMacVersionMin < ld::mac10_4) ) {
4074 //warning("-macosx_version_min should be 10.4 or later for x86_64");
4075 fMacVersionMin = ld::mac10_4;
4077 break;
4078 case CPU_TYPE_ARM64:
4079 if ( (fPlatform == kPlatformiOS) && (fIOSVersionMin < ld::iOS_7_0) ) {
4080 //warning("-mios_version_min should be 7.0 or later for arm64");
4081 fIOSVersionMin = ld::iOS_7_0;
4083 break;
4086 // default to adding functions start for dynamic code, static code must opt-in
4087 switch ( fOutputKind ) {
4088 case Options::kPreload:
4089 case Options::kStaticExecutable:
4090 case Options::kKextBundle:
4091 if ( fDataInCodeInfoLoadCommandForcedOn )
4092 fDataInCodeInfoLoadCommand = true;
4093 if ( fFunctionStartsForcedOn )
4094 fFunctionStartsLoadCommand = true;
4095 break;
4096 case Options::kObjectFile:
4097 if ( !fDataInCodeInfoLoadCommandForcedOff )
4098 fDataInCodeInfoLoadCommand = true;
4099 if ( fFunctionStartsForcedOn )
4100 fFunctionStartsLoadCommand = true;
4101 break;
4102 case Options::kDynamicExecutable:
4103 case Options::kDyld:
4104 case Options::kDynamicLibrary:
4105 case Options::kDynamicBundle:
4106 if ( !fDataInCodeInfoLoadCommandForcedOff )
4107 fDataInCodeInfoLoadCommand = true;
4108 if ( !fFunctionStartsForcedOff )
4109 fFunctionStartsLoadCommand = true;
4110 break;
4113 // adjust kext type based on architecture
4114 if ( fOutputKind == kKextBundle ) {
4115 switch ( fArchitecture ) {
4116 case CPU_TYPE_X86_64:
4117 // x86_64 uses new MH_KEXT_BUNDLE type
4118 fMakeCompressedDyldInfo = false;
4119 fMakeCompressedDyldInfoForceOff = true;
4120 fAllowTextRelocs = true;
4121 fUndefinedTreatment = kUndefinedDynamicLookup;
4122 break;
4123 case CPU_TYPE_ARM64:
4124 // arm64 uses new MH_KEXT_BUNDLE type
4125 fMakeCompressedDyldInfo = false;
4126 fMakeCompressedDyldInfoForceOff = true;
4127 fAllowTextRelocs = false;
4128 fKextsUseStubs = true;
4129 fUndefinedTreatment = kUndefinedDynamicLookup;
4130 break;
4131 case CPU_TYPE_ARM:
4132 if ( min_iOS(ld::iOS_5_0) ) {
4133 // iOS 5.0 and later use new MH_KEXT_BUNDLE type
4134 fMakeCompressedDyldInfo = false;
4135 fMakeCompressedDyldInfoForceOff = true;
4136 // kexts are PIC in iOS 6.0 and later
4137 fAllowTextRelocs = !min_iOS(ld::iOS_6_0);
4138 fKextsUseStubs = !fAllowTextRelocs;
4139 fUndefinedTreatment = kUndefinedDynamicLookup;
4140 break;
4142 // else use object file
4143 case CPU_TYPE_I386:
4144 // use .o files
4145 fOutputKind = kObjectFile;
4146 break;
4150 // disable implicit dylibs when targeting 10.3
4151 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
4152 if ( !minOS(ld::mac10_4, ld::iOS_2_0) )
4153 fImplicitlyLinkPublicDylibs = false;
4156 // allow build system to force linker to ignore -prebind
4157 if ( getenv("LD_FORCE_NO_PREBIND") != NULL )
4158 fPrebind = false;
4160 // allow build system to force linker to ignore -seg_addr_table
4161 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL )
4162 fSegAddrTablePath = NULL;
4164 // check for base address specified externally
4165 if ( (fSegAddrTablePath != NULL) && (fOutputKind == Options::kDynamicLibrary) ) {
4166 parseSegAddrTable(fSegAddrTablePath, this->installPath());
4167 // HACK to support seg_addr_table entries that are physical paths instead of install paths
4168 if ( fBaseAddress == 0 ) {
4169 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
4170 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libstdc++.6.0.4.dylib");
4171 if ( fBaseAddress == 0 )
4172 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libstdc++.6.0.9.dylib");
4175 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
4176 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libz.1.2.3.dylib");
4178 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
4179 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libutil1.0.dylib");
4183 // split segs only allowed for dylibs
4184 if ( fSplitSegs ) {
4185 // split seg only supported for i386, and arm.
4186 switch ( fArchitecture ) {
4187 case CPU_TYPE_I386:
4188 if ( fOutputKind != Options::kDynamicLibrary )
4189 fSplitSegs = false;
4190 // make sure read and write segments are proper distance apart
4191 if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x10000000) )
4192 fBaseWritableAddress = fBaseAddress + 0x10000000;
4193 break;
4194 case CPU_TYPE_ARM:
4195 if ( fOutputKind != Options::kDynamicLibrary ) {
4196 fSplitSegs = false;
4198 else {
4199 // make sure read and write segments are proper distance apart
4200 if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x08000000) )
4201 fBaseWritableAddress = fBaseAddress + 0x08000000;
4203 break;
4204 default:
4205 fSplitSegs = false;
4206 fBaseAddress = 0;
4207 fBaseWritableAddress = 0;
4211 // set too-large size
4212 switch ( fArchitecture ) {
4213 case CPU_TYPE_I386:
4214 fMaxAddress = 0xFFFFFFFF;
4215 break;
4216 case CPU_TYPE_X86_64:
4217 break;
4218 case CPU_TYPE_ARM:
4219 switch ( fOutputKind ) {
4220 case Options::kDynamicExecutable:
4221 case Options::kDynamicLibrary:
4222 case Options::kDynamicBundle:
4223 // user land code is limited to low 1GB
4224 fMaxAddress = 0x2FFFFFFF;
4225 break;
4226 case Options::kStaticExecutable:
4227 case Options::kObjectFile:
4228 case Options::kDyld:
4229 case Options::kPreload:
4230 case Options::kKextBundle:
4231 fMaxAddress = 0xFFFFFFFF;
4232 break;
4234 // range check -seg1addr for ARM
4235 if ( fBaseAddress > fMaxAddress ) {
4236 warning("ignoring -seg1addr 0x%08llX. Address out of range.", fBaseAddress);
4237 fBaseAddress = 0;
4239 break;
4242 // <rdar://problem/6138961> -r implies no prebinding for all architectures
4243 if ( fOutputKind == Options::kObjectFile )
4244 fPrebind = false;
4246 // disable prebinding depending on arch and min OS version
4247 if ( fPrebind ) {
4248 switch ( fArchitecture ) {
4249 case CPU_TYPE_I386:
4250 if ( fMacVersionMin == ld::mac10_4 ) {
4251 // in 10.4 only split seg dylibs are prebound
4252 if ( (fOutputKind != Options::kDynamicLibrary) || ! fSplitSegs )
4253 fPrebind = false;
4255 else if ( fMacVersionMin >= ld::mac10_5 ) {
4256 // in 10.5 nothing is prebound
4257 fPrebind = false;
4259 else if ( fIOSVersionMin != ld::iOSVersionUnset ) {
4260 // nothing in simulator is prebound
4261 fPrebind = false;
4263 else {
4264 // in 10.3 and earlier only dylibs and main executables could be prebound
4265 switch ( fOutputKind ) {
4266 case Options::kDynamicExecutable:
4267 case Options::kDynamicLibrary:
4268 // only main executables and dylibs can be prebound
4269 break;
4270 case Options::kStaticExecutable:
4271 case Options::kDynamicBundle:
4272 case Options::kObjectFile:
4273 case Options::kDyld:
4274 case Options::kPreload:
4275 case Options::kKextBundle:
4276 // disable prebinding for everything else
4277 fPrebind = false;
4278 break;
4281 break;
4282 case CPU_TYPE_X86_64:
4283 fPrebind = false;
4284 break;
4285 case CPU_TYPE_ARM:
4286 switch ( fOutputKind ) {
4287 case Options::kDynamicExecutable:
4288 case Options::kDynamicLibrary:
4289 // only main executables and dylibs can be prebound
4290 break;
4291 case Options::kStaticExecutable:
4292 case Options::kDynamicBundle:
4293 case Options::kObjectFile:
4294 case Options::kDyld:
4295 case Options::kPreload:
4296 case Options::kKextBundle:
4297 // disable prebinding for everything else
4298 fPrebind = false;
4299 break;
4301 break;
4305 // only prebound images can be split-seg
4306 if ( fSplitSegs && !fPrebind )
4307 fSplitSegs = false;
4309 // determine if info for shared region should be added
4310 if ( fOutputKind == Options::kDynamicLibrary ) {
4311 if ( minOS(ld::mac10_5, ld::iOS_3_1) )
4312 if ( !fPrebind && !fSharedRegionEligibleForceOff )
4313 if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
4314 || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
4315 fSharedRegionEligible = true;
4317 else if ( fOutputKind == Options::kDyld ) {
4318 // <rdar://problem/10111122> Enable dyld to be put into the dyld shared cache
4319 fSharedRegionEligible = true;
4322 // <rdar://problem/18719327> warn if -rpath is used with OS dylibs
4323 if ( fSharedRegionEligible && !fRPaths.empty() )
4324 warning("-rpath cannot be used with dylibs that will be in the dyld shared cache");
4326 // automatically use __DATA_CONST in iOS dylibs
4327 if ( fSharedRegionEligible && minOS(ld::mac10_Future, ld::iOS_9_0) && !fUseDataConstSegmentForceOff ) {
4328 fUseDataConstSegment = true;
4330 if ( fUseDataConstSegmentForceOn ) {
4331 fUseDataConstSegment = true;
4333 if ( fUseDataConstSegment ) {
4334 addSectionRename("__DATA", "__got", "__DATA_CONST", "__got");
4335 addSectionRename("__DATA", "__la_symbol_ptr", "__DATA_CONST", "__la_symbol_ptr");
4336 addSectionRename("__DATA", "__nl_symbol_ptr", "__DATA_CONST", "__nl_symbol_ptr");
4337 addSectionRename("__DATA", "__const", "__DATA_CONST", "__const");
4338 addSectionRename("__DATA", "__cfstring", "__DATA_CONST", "__cfstring");
4339 addSectionRename("__DATA", "__mod_init_func", "__DATA_CONST", "__mod_init_func");
4340 addSectionRename("__DATA", "__mod_term_func", "__DATA_CONST", "__mod_term_func");
4341 addSectionRename("__DATA", "__objc_classlist", "__DATA_CONST", "__objc_classlist");
4342 addSectionRename("__DATA", "__objc_nlclslist", "__DATA_CONST", "__objc_nlclslist");
4343 addSectionRename("__DATA", "__objc_catlist", "__DATA_CONST", "__objc_catlist");
4344 addSectionRename("__DATA", "__objc_nlcatlist", "__DATA_CONST", "__objc_nlcatlist");
4345 addSectionRename("__DATA", "__objc_protolist", "__DATA_CONST", "__objc_protolist");
4346 addSectionRename("__DATA", "__objc_imageinfo", "__DATA_CONST", "__objc_imageinfo");
4347 addSectionRename("__DATA", "__objc_const", "__DATA_CONST", "__objc_const");
4350 // Use V2 shared cache info when targetting newer OSs
4351 if ( fSharedRegionEligible && minOS(ld::mac10_Future, ld::iOS_9_0)) {
4352 fSharedRegionEncodingV2 = true;
4353 fIgnoreOptimizationHints = true;
4356 // figure out if module table is needed for compatibility with old ld/dyld
4357 if ( fOutputKind == Options::kDynamicLibrary ) {
4358 switch ( fArchitecture ) {
4359 case CPU_TYPE_I386:
4360 if ( fIOSVersionMin != ld::iOSVersionUnset ) // simulator never needs modules
4361 break;
4362 case CPU_TYPE_ARM:
4363 if ( fPrebind )
4364 fNeedsModuleTable = true; // redo_prebinding requires a module table
4365 break;
4369 // <rdar://problem/5366363> -r -x implies -S
4370 if ( (fOutputKind == Options::kObjectFile) && (fLocalSymbolHandling == kLocalSymbolsNone) )
4371 fDebugInfoStripping = Options::kDebugInfoNone;
4373 // <rdar://problem/15252891> -r implies -no_uuid
4374 if ( fOutputKind == Options::kObjectFile )
4375 fUUIDMode = kUUIDNone;
4377 // choose how to process unwind info
4378 switch ( fArchitecture ) {
4379 case CPU_TYPE_I386:
4380 case CPU_TYPE_X86_64:
4381 case CPU_TYPE_ARM64:
4382 switch ( fOutputKind ) {
4383 case Options::kObjectFile:
4384 case Options::kStaticExecutable:
4385 case Options::kPreload:
4386 case Options::kKextBundle:
4387 fAddCompactUnwindEncoding = false;
4388 break;
4389 case Options::kDyld:
4390 case Options::kDynamicLibrary:
4391 case Options::kDynamicBundle:
4392 case Options::kDynamicExecutable:
4393 //if ( fAddCompactUnwindEncoding && (fVersionMin >= ld::mac10_6) )
4394 // fRemoveDwarfUnwindIfCompactExists = true;
4395 break;
4397 break;
4398 case CPU_TYPE_ARM:
4399 if ( armUsesZeroCostExceptions() ) {
4400 switch ( fOutputKind ) {
4401 case Options::kObjectFile:
4402 case Options::kStaticExecutable:
4403 case Options::kPreload:
4404 case Options::kKextBundle:
4405 fAddCompactUnwindEncoding = false;
4406 break;
4407 case Options::kDyld:
4408 case Options::kDynamicLibrary:
4409 case Options::kDynamicBundle:
4410 case Options::kDynamicExecutable:
4411 fAddCompactUnwindEncoding = true;
4412 break;
4415 else {
4416 fAddCompactUnwindEncoding = false;
4417 fRemoveDwarfUnwindIfCompactExists = false;
4419 break;
4420 case 0:
4421 // if -arch is missing, assume we don't want compact unwind info
4422 fAddCompactUnwindEncoding = false;
4423 break;
4426 // only iOS executables should be encryptable
4427 switch ( fOutputKind ) {
4428 case Options::kObjectFile:
4429 case Options::kDyld:
4430 case Options::kStaticExecutable:
4431 case Options::kPreload:
4432 case Options::kKextBundle:
4433 fEncryptable = false;
4434 break;
4435 case Options::kDynamicExecutable:
4436 break;
4437 case Options::kDynamicLibrary:
4438 case Options::kDynamicBundle:
4439 // <rdar://problem/16293398> Add LC_ENCRYPTION_INFO load command to bundled frameworks
4440 if ( !min_iOS(ld::iOS_7_0) )
4441 fEncryptable = false;
4442 break;
4444 if ( (fArchitecture != CPU_TYPE_ARM) && (fArchitecture != CPU_TYPE_ARM64) )
4445 fEncryptable = false;
4446 if ( fEncryptableForceOn )
4447 fEncryptable = true;
4448 else if ( fEncryptableForceOff )
4449 fEncryptable = false;
4451 // don't move inits in dyld because dyld wants certain
4452 // entries point at stable locations at the start of __text
4453 if ( fOutputKind == Options::kDyld )
4454 fAutoOrderInitializers = false;
4457 // disable __data ordering for some output kinds
4458 switch ( fOutputKind ) {
4459 case Options::kObjectFile:
4460 case Options::kDyld:
4461 case Options::kStaticExecutable:
4462 case Options::kPreload:
4463 case Options::kKextBundle:
4464 fOrderData = false;
4465 break;
4466 case Options::kDynamicExecutable:
4467 case Options::kDynamicLibrary:
4468 case Options::kDynamicBundle:
4469 break;
4472 // only use compressed LINKEDIT for final linked images
4473 switch ( fOutputKind ) {
4474 case Options::kDynamicExecutable:
4475 case Options::kDynamicLibrary:
4476 case Options::kDynamicBundle:
4477 break;
4478 case Options::kPreload:
4479 case Options::kStaticExecutable:
4480 case Options::kObjectFile:
4481 case Options::kDyld:
4482 case Options::kKextBundle:
4483 fMakeCompressedDyldInfoForceOff = true;
4484 break;
4486 if ( fMakeCompressedDyldInfoForceOff )
4487 fMakeCompressedDyldInfo = false;
4490 // only use compressed LINKEDIT for:
4491 // Mac OS X 10.6 or later
4492 // iOS 3.1 or later
4493 if ( fMakeCompressedDyldInfo ) {
4494 if ( !minOS(ld::mac10_6, ld::iOS_3_1) )
4495 fMakeCompressedDyldInfo = false;
4498 // only ARM and x86_64 enforces that cpu-sub-types must match
4499 switch ( fArchitecture ) {
4500 case CPU_TYPE_ARM:
4501 case CPU_TYPE_X86_64:
4502 break;
4503 case CPU_TYPE_I386:
4504 case CPU_TYPE_ARM64:
4505 fAllowCpuSubtypeMismatches = true;
4506 break;
4510 // only final linked images can not optimize zero fill sections
4511 if ( fOutputKind == Options::kObjectFile )
4512 fOptimizeZeroFill = true;
4514 // all undefines in -r mode
4515 // if ( fOutputKind == Options::kObjectFile )
4516 // fUndefinedTreatment = kUndefinedSuppress;
4518 // only dynamic final linked images should warn about use of commmons
4519 if ( fWarnCommons ) {
4520 switch ( fOutputKind ) {
4521 case Options::kDynamicExecutable:
4522 case Options::kDynamicLibrary:
4523 case Options::kDynamicBundle:
4524 break;
4525 case Options::kPreload:
4526 case Options::kStaticExecutable:
4527 case Options::kObjectFile:
4528 case Options::kDyld:
4529 case Options::kKextBundle:
4530 fWarnCommons = false;
4531 break;
4535 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
4536 if ( minOS(ld::mac10_5, ld::iOS_2_0) )
4537 fUseSimplifiedDylibReExports = true;
4539 // Mac OS X 10.7 and iOS 4.2 support LC_LOAD_UPWARD_DYLIB
4540 if ( minOS(ld::mac10_7, ld::iOS_4_2) && (fOutputKind == kDynamicLibrary) )
4541 fCanUseUpwardDylib = true;
4543 // MacOSX 10.7 defaults to PIE
4544 if ( ((fArchitecture == CPU_TYPE_X86_64) || (fArchitecture == CPU_TYPE_I386))
4545 && (fOutputKind == kDynamicExecutable)
4546 && (fMacVersionMin >= ld::mac10_7) ) {
4547 fPositionIndependentExecutable = true;
4550 // armv7 for iOS4.3 defaults to PIE
4551 if ( (fArchitecture == CPU_TYPE_ARM)
4552 && fArchSupportsThumb2
4553 && (fOutputKind == kDynamicExecutable)
4554 && min_iOS(ld::iOS_4_3) ) {
4555 fPositionIndependentExecutable = true;
4558 // Simulator defaults to PIE
4559 if ( fTargetIOSSimulator && (fOutputKind == kDynamicExecutable) )
4560 fPositionIndependentExecutable = true;
4562 // -no_pie anywhere on command line disable PIE
4563 if ( fDisablePositionIndependentExecutable )
4564 fPositionIndependentExecutable = false;
4566 // arm64 is always PIE
4567 if ( (fArchitecture == CPU_TYPE_ARM64) && (fOutputKind == kDynamicExecutable) ) {
4568 fPositionIndependentExecutable = true;
4571 // set fOutputSlidable
4572 switch ( fOutputKind ) {
4573 case Options::kObjectFile:
4574 fOutputSlidable = false;
4575 break;
4576 case Options::kStaticExecutable:
4577 case Options::kDynamicExecutable:
4578 fOutputSlidable = fPositionIndependentExecutable;
4579 break;
4580 case Options::kPreload:
4581 fOutputSlidable = fPIEOnCommandLine;
4582 break;
4583 case Options::kDyld:
4584 case Options::kDynamicLibrary:
4585 case Options::kDynamicBundle:
4586 case Options::kKextBundle:
4587 fOutputSlidable = true;
4588 break;
4591 // let linker know if thread local variables are supported
4592 if ( fMacVersionMin >= ld::mac10_7 ) {
4593 fTLVSupport = true;
4595 else if ( (fArchitecture == CPU_TYPE_ARM64) && min_iOS(ld::iOS_8_0) ) {
4596 fTLVSupport = true;
4598 else if ( (fArchitecture == CPU_TYPE_ARM) && min_iOS(ld::iOS_9_0) ) {
4599 fTLVSupport = true;
4602 // default to adding version load command for dynamic code, static code must opt-in
4603 switch ( fOutputKind ) {
4604 case Options::kObjectFile:
4605 fVersionLoadCommand = false;
4606 break;
4607 case Options::kStaticExecutable:
4608 case Options::kPreload:
4609 case Options::kKextBundle:
4610 if ( fVersionLoadCommandForcedOn )
4611 fVersionLoadCommand = true;
4612 break;
4613 case Options::kDynamicExecutable:
4614 case Options::kDyld:
4615 case Options::kDynamicLibrary:
4616 case Options::kDynamicBundle:
4617 if ( !fVersionLoadCommandForcedOff )
4618 fVersionLoadCommand = true;
4619 break;
4622 // support re-export of individual symbols in MacOSX 10.7 and iOS 4.2
4623 if ( (fOutputKind == kDynamicLibrary) && minOS(ld::mac10_7, ld::iOS_4_2) )
4624 fCanReExportSymbols = true;
4626 // ObjC optimization is only in dynamic final linked images
4627 switch ( fOutputKind ) {
4628 case Options::kObjectFile:
4629 case Options::kStaticExecutable:
4630 case Options::kPreload:
4631 case Options::kKextBundle:
4632 case Options::kDyld:
4633 fObjcCategoryMerging = false;
4634 break;
4635 case Options::kDynamicExecutable:
4636 case Options::kDynamicLibrary:
4637 case Options::kDynamicBundle:
4638 break;
4641 // i386 main executables linked on Mac OS X 10.7 default to NX heap
4642 // regardless of target unless overriden with -allow_heap_execute anywhere
4643 // on the command line
4644 if ( (fArchitecture == CPU_TYPE_I386) && (fOutputKind == kDynamicExecutable) && !fDisableNonExecutableHeap)
4645 fNonExecutableHeap = true;
4647 // Use LC_MAIN instead of LC_UNIXTHREAD for newer OSs
4648 switch ( fOutputKind ) {
4649 case Options::kDynamicExecutable:
4650 if ( fEntryPointLoadCommandForceOn ) {
4651 fEntryPointLoadCommand = true;
4652 if ( fEntryName == NULL )
4653 fEntryName = "_main";
4655 else if ( fEntryPointLoadCommandForceOff ) {
4656 fNeedsThreadLoadCommand = true;
4657 if ( fEntryName == NULL )
4658 fEntryName = "start";
4660 else {
4661 // <rdar://problem/16310363> Linker should look for "_main" not "start" when building for sim regardless of min OS
4662 if ( minOS(ld::mac10_8, ld::iOS_6_0) || fTargetIOSSimulator ) {
4663 fEntryPointLoadCommand = true;
4664 if ( fEntryName == NULL )
4665 fEntryName = "_main";
4666 if ( strcmp(fEntryName, "start") == 0 ) {
4667 warning("Ignoring '-e start' because entry point 'start' is not used for the targeted OS version");
4668 fEntryName = "_main";
4671 else {
4672 fNeedsThreadLoadCommand = true;
4673 if ( fEntryName == NULL )
4674 fEntryName = "start";
4677 break;
4678 case Options::kObjectFile:
4679 case Options::kKextBundle:
4680 case Options::kDynamicLibrary:
4681 case Options::kDynamicBundle:
4682 break;
4684 case Options::kStaticExecutable:
4685 case Options::kPreload:
4686 case Options::kDyld:
4687 fNeedsThreadLoadCommand = true;
4688 if ( fEntryName == NULL )
4689 fEntryName = "start"; // Perhaps these should have no default and require -e
4690 break;
4693 // add LC_SOURCE_VERSION
4694 switch ( fOutputKind ) {
4695 case Options::kDynamicExecutable:
4696 case Options::kKextBundle:
4697 case Options::kDynamicLibrary:
4698 case Options::kDynamicBundle:
4699 case Options::kDyld:
4700 case Options::kStaticExecutable:
4701 if ( fSourceVersionLoadCommandForceOn ) {
4702 fSourceVersionLoadCommand = true;
4704 else if ( fSourceVersionLoadCommandForceOff ) {
4705 fSourceVersionLoadCommand = false;
4707 else {
4708 if ( minOS(ld::mac10_8, ld::iOS_6_0) ) {
4709 fSourceVersionLoadCommand = true;
4711 else
4712 fSourceVersionLoadCommand = false;
4714 break;
4715 case Options::kObjectFile:
4716 case Options::kPreload:
4717 fSourceVersionLoadCommand = false;
4718 break;
4721 // if -sdk_version not on command line, infer from -syslibroot
4722 if ( (fSDKVersion == 0) && (fSDKPaths.size() > 0) ) {
4723 const char* sdkPath = fSDKPaths.front();
4724 const char* end = &sdkPath[strlen(sdkPath)-1];
4725 while ( !isdigit(*end) && (end > sdkPath) )
4726 --end;
4727 const char* start = end-1;
4728 while ( (isdigit(*start) || (*start == '.')) && (start > sdkPath))
4729 --start;
4730 char sdkVersionStr[32];
4731 int len = end-start+1;
4732 if ( len > 2 ) {
4733 strlcpy(sdkVersionStr, start+1, len);
4734 fSDKVersion = parseVersionNumber32(sdkVersionStr);
4738 // if -sdk_version and -syslibroot not used, but targeting MacOSX, use current OS version
4739 if ( (fSDKVersion == 0) && (fMacVersionMin != ld::macVersionUnset) ) {
4740 // special case if RC_ProjectName and MACOSX_DEPLOYMENT_TARGET are both set that sdkversion=minos
4741 if ( getenv("RC_ProjectName") && getenv("MACOSX_DEPLOYMENT_TARGET") ) {
4742 fSDKVersion = fMacVersionMin;
4744 else {
4745 int mib[2] = { CTL_KERN, KERN_OSRELEASE };
4746 char kernVersStr[100];
4747 size_t strlen = sizeof(kernVersStr);
4748 if ( sysctl(mib, 2, kernVersStr, &strlen, NULL, 0) != -1 ) {
4749 uint32_t kernVers = parseVersionNumber32(kernVersStr);
4750 int minor = (kernVers >> 16) - 4; // kernel major version is 4 ahead of x in 10.x
4751 fSDKVersion = 0x000A0000 + (minor << 8);
4756 // allow trie based absolute symbols if targeting new enough OS
4757 if ( fMakeCompressedDyldInfo ) {
4758 if ( minOS(ld::mac10_9, ld::iOS_7_0) ) {
4759 fAbsoluteSymbols = true;
4763 // <rdar://problem/12959510> iOS main executables now default to 16KB page size
4764 if ( (fIOSVersionMin != ld::iOSVersionUnset) && (fOutputKind == Options::kDynamicExecutable) ) {
4765 // <rdar://problem/13070042> Only third party apps should have 16KB page segments by default
4766 if ( fEncryptable ) {
4767 if ( fSegmentAlignment == 4096 )
4768 fSegmentAlignment = 4096*4;
4772 // <rdar://problem/12258065> ARM64 needs 16KB page size for user land code
4773 // <rdar://problem/15974532> make armv7[s] use 16KB pages in user land code for iOS 8 or later
4774 if ( fSegmentAlignment == 4096 ) {
4775 switch ( fOutputKind ) {
4776 case Options::kDynamicExecutable:
4777 case Options::kDynamicLibrary:
4778 case Options::kDynamicBundle:
4779 case Options::kDyld:
4780 if ( (fArchitecture == CPU_TYPE_ARM64)
4781 || ((fArchitecture == CPU_TYPE_ARM) && min_iOS(ld::iOS_7_0)) ) {
4782 fSegmentAlignment = 4096*4;
4784 break;
4785 case Options::kStaticExecutable:
4786 case Options::kKextBundle:
4787 // <rdar://problem/14676611> 16KB segments for arm64 kexts
4788 if ( (fArchitecture == CPU_TYPE_ARM64) && min_iOS(ld::iOS_9_0) ) {
4789 fSegmentAlignment = 4096*4;
4791 break;
4792 case Options::kObjectFile:
4793 case Options::kPreload:
4794 break;
4800 // <rdar://problem/13624134> linker should not convert dwarf unwind if .o file has compact unwind section
4801 switch ( fOutputKind ) {
4802 case Options::kDynamicExecutable:
4803 case Options::kDynamicLibrary:
4804 case Options::kDynamicBundle:
4805 case Options::kDyld:
4806 if ( fKeepDwarfUnwindForcedOn ) {
4807 fKeepDwarfUnwind = true;
4809 else if ( fKeepDwarfUnwindForcedOff ) {
4810 fKeepDwarfUnwind = false;
4812 else {
4813 if ( minOS(ld::mac10_9, ld::iOS_7_0) )
4814 fKeepDwarfUnwind = false;
4815 else
4816 fKeepDwarfUnwind = true;
4818 break;
4819 case Options::kKextBundle:
4820 case Options::kStaticExecutable:
4821 case Options::kObjectFile:
4822 case Options::kPreload:
4823 fKeepDwarfUnwind = true;
4824 break;
4827 // Make sure -image_base matches alignment
4828 uint64_t alignedBaseAddress = (fBaseAddress+fSegmentAlignment-1) & (-fSegmentAlignment);
4829 if ( alignedBaseAddress != fBaseAddress ) {
4830 warning("base address 0x%llX is not properly aligned. Changing it to 0x%llX", fBaseAddress, alignedBaseAddress);
4831 fBaseAddress = alignedBaseAddress;
4834 // If -dirty_data_list not specified, look in $SDKROOT/AppleInternal/DirtyDataFiles/<dylib>.dirty for dirty data list
4835 if ( fSymbolsMovesData.empty() && fUseDataConstSegment && ( fDylibInstallName != NULL) && !fSDKPaths.empty() ) {
4836 const char* dylibLeaf = strrchr(fDylibInstallName, '/');
4837 if ( dylibLeaf ) {
4838 char path[PATH_MAX];
4839 strlcpy(path , fSDKPaths.front(), sizeof(path));
4840 strlcat(path , "/AppleInternal/DirtyDataFiles", sizeof(path));
4841 strlcat(path , dylibLeaf, sizeof(path));
4842 strlcat(path , ".dirty", sizeof(path));
4843 FileInfo info;
4844 if ( info.checkFileExists(*this, path) )
4845 addSymbolMove("__DATA_DIRTY", path, fSymbolsMovesData, "-dirty_data_list");
4851 void Options::checkIllegalOptionCombinations()
4853 // check -undefined setting
4854 switch ( fUndefinedTreatment ) {
4855 case kUndefinedError:
4856 case kUndefinedDynamicLookup:
4857 // always legal
4858 break;
4859 case kUndefinedWarning:
4860 case kUndefinedSuppress:
4861 // requires flat namespace
4862 if ( fNameSpace == kTwoLevelNameSpace )
4863 throw "can't use -undefined warning or suppress with -twolevel_namespace";
4864 break;
4867 // unify -sub_umbrella with dylibs
4868 for (std::vector<const char*>::iterator it = fSubUmbellas.begin(); it != fSubUmbellas.end(); it++) {
4869 const char* subUmbrella = *it;
4870 bool found = false;
4871 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
4872 Options::FileInfo& info = *fit;
4873 const char* lastSlash = strrchr(info.path, '/');
4874 if ( lastSlash == NULL )
4875 lastSlash = info.path - 1;
4876 if ( strcmp(&lastSlash[1], subUmbrella) == 0 ) {
4877 info.options.fReExport = true;
4878 found = true;
4879 fLinkSnapshot.recordSubUmbrella(info.path);
4880 break;
4883 if ( ! found )
4884 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella);
4887 // unify -sub_library with dylibs
4888 for (std::vector<const char*>::iterator it = fSubLibraries.begin(); it != fSubLibraries.end(); it++) {
4889 const char* subLibrary = *it;
4890 bool found = false;
4891 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
4892 Options::FileInfo& info = *fit;
4893 const char* lastSlash = strrchr(info.path, '/');
4894 if ( lastSlash == NULL )
4895 lastSlash = info.path - 1;
4896 const char* dot = strchr(&lastSlash[1], '.');
4897 if ( dot == NULL )
4898 dot = &lastSlash[strlen(lastSlash)];
4899 if ( strncmp(&lastSlash[1], subLibrary, dot-lastSlash-1) == 0 ) {
4900 info.options.fReExport = true;
4901 found = true;
4902 fLinkSnapshot.recordSubLibrary(info.path);
4903 break;
4906 if ( ! found )
4907 warning("-sub_library %s does not match a supplied dylib", subLibrary);
4910 // sync reader options
4911 if ( fNameSpace != kTwoLevelNameSpace )
4912 fFlatNamespace = true;
4914 // check -stack_addr
4915 if ( fStackAddr != 0 ) {
4916 switch (fArchitecture) {
4917 case CPU_TYPE_I386:
4918 case CPU_TYPE_ARM:
4919 if ( fStackAddr > 0xFFFFFFFF )
4920 throw "-stack_addr must be < 4G for 32-bit processes";
4921 break;
4922 case CPU_TYPE_X86_64:
4923 case CPU_TYPE_ARM64:
4924 break;
4926 if ( (fStackAddr & -4096) != fStackAddr )
4927 throw "-stack_addr must be multiples of 4K";
4928 if ( fStackSize == 0 )
4929 throw "-stack_addr must be used with -stack_size";
4932 // check -stack_size
4933 if ( fStackSize != 0 ) {
4934 switch (fArchitecture) {
4935 case CPU_TYPE_I386:
4936 if ( fStackSize > 0xFFFFFFFF )
4937 throw "-stack_size must be < 4G for 32-bit processes";
4938 if ( fStackAddr == 0 ) {
4939 fStackAddr = 0xC0000000;
4941 if ( (fStackAddr > 0xB0000000) && ((fStackAddr-fStackSize) < 0xB0000000) )
4942 warning("custom stack placement overlaps and will disable shared region");
4943 break;
4944 case CPU_TYPE_ARM:
4945 if ( fStackSize > 0x2F000000 )
4946 throw "-stack_size must be < 752MB";
4947 if ( fStackAddr == 0 )
4948 fStackAddr = 0x2F000000;
4949 if ( fStackAddr > 0x30000000)
4950 throw "-stack_addr must be < 0x30000000 for arm";
4951 break;
4952 case CPU_TYPE_X86_64:
4953 if ( fStackAddr == 0 ) {
4954 fStackAddr = 0x00007FFF5C000000LL;
4956 break;
4957 case CPU_TYPE_ARM64:
4958 if ( fStackSize > 0x20000000 )
4959 throw "-stack_size must be < 512MB";
4960 if ( fStackAddr == 0 ) {
4961 fStackAddr = 0x120000000;
4963 break;
4965 if ( (fStackSize & -4096) != fStackSize )
4966 throw "-stack_size must be multiples of 4K";
4967 switch ( fOutputKind ) {
4968 case Options::kDynamicExecutable:
4969 case Options::kStaticExecutable:
4970 // custom stack size only legal when building main executable
4971 break;
4972 case Options::kDynamicLibrary:
4973 case Options::kDynamicBundle:
4974 case Options::kObjectFile:
4975 case Options::kDyld:
4976 case Options::kPreload:
4977 case Options::kKextBundle:
4978 throw "-stack_size option can only be used when linking a main executable";
4980 if ( fStackSize > fStackAddr )
4981 throwf("-stack_size (0x%08llX) must be smaller than -stack_addr (0x%08llX)", fStackSize, fStackAddr);
4984 // check that -allow_stack_execute is only used with main executables
4985 if ( fExecutableStack ) {
4986 switch ( fOutputKind ) {
4987 case Options::kDynamicExecutable:
4988 case Options::kStaticExecutable:
4989 // -allow_stack_execute size only legal when building main executable
4990 break;
4991 case Options::kDynamicLibrary:
4992 case Options::kDynamicBundle:
4993 case Options::kObjectFile:
4994 case Options::kDyld:
4995 case Options::kPreload:
4996 case Options::kKextBundle:
4997 throw "-allow_stack_execute option can only be used when linking a main executable";
5001 // check that -allow_heap_execute is only used with i386 main executables
5002 if ( fDisableNonExecutableHeap ) {
5003 if ( fArchitecture != CPU_TYPE_I386 )
5004 throw "-allow_heap_execute option can only be used when linking for i386";
5005 switch ( fOutputKind ) {
5006 case Options::kDynamicExecutable:
5007 // -allow_heap_execute only legal when building main executable
5008 break;
5009 case Options::kStaticExecutable:
5010 case Options::kDynamicLibrary:
5011 case Options::kDynamicBundle:
5012 case Options::kObjectFile:
5013 case Options::kDyld:
5014 case Options::kPreload:
5015 case Options::kKextBundle:
5016 throw "-allow_heap_execute option can only be used when linking a main executable";
5020 // check -client_name is only used when making a bundle or main executable
5021 if ( fClientName != NULL ) {
5022 switch ( fOutputKind ) {
5023 case Options::kDynamicExecutable:
5024 case Options::kDynamicBundle:
5025 break;
5026 case Options::kStaticExecutable:
5027 case Options::kDynamicLibrary:
5028 case Options::kObjectFile:
5029 case Options::kDyld:
5030 case Options::kPreload:
5031 case Options::kKextBundle:
5032 throw "-client_name can only be used with -bundle";
5036 // check -init is only used when building a dylib
5037 if ( (fInitFunctionName != NULL) && (fOutputKind != Options::kDynamicLibrary) )
5038 throw "-init can only be used with -dynamiclib";
5040 // check -bundle_loader only used with -bundle
5041 if ( (fBundleLoader != NULL) && (fOutputKind != Options::kDynamicBundle) )
5042 throw "-bundle_loader can only be used with -bundle";
5044 // check -dtrace not used with -r
5045 if ( (fDtraceScriptName != NULL) && (fOutputKind == Options::kObjectFile) )
5046 throw "-dtrace can only be used when creating final linked images";
5048 // check -d can only be used with -r
5049 if ( fMakeTentativeDefinitionsReal && (fOutputKind != Options::kObjectFile) )
5050 throw "-d can only be used with -r";
5052 // check that -root_safe is not used with -r
5053 if ( fRootSafe && (fOutputKind == Options::kObjectFile) )
5054 throw "-root_safe cannot be used with -r";
5056 // check that -setuid_safe is not used with -r
5057 if ( fSetuidSafe && (fOutputKind == Options::kObjectFile) )
5058 throw "-setuid_safe cannot be used with -r";
5060 // <rdar://problem/12781832> compiler driver no longer uses -objc_abi_version, it uses -ios_simulator_version_min instead
5061 if ( !fObjCABIVersion1Override && !fObjCABIVersion2Override && fTargetIOSSimulator )
5062 fObjCABIVersion2Override = true;
5064 // rdar://problem/4718189 map ObjC class names to new runtime names
5065 bool alterObjC1ClassNamesToObjC2 = false;
5066 switch (fArchitecture) {
5067 case CPU_TYPE_I386:
5068 // i386 only uses new symbols when using objc2 ABI
5069 if ( fObjCABIVersion2Override )
5070 alterObjC1ClassNamesToObjC2 = true;
5071 break;
5072 case CPU_TYPE_X86_64:
5073 case CPU_TYPE_ARM:
5074 case CPU_TYPE_ARM64:
5075 alterObjC1ClassNamesToObjC2 = true;
5076 break;
5079 // make sure all required exported symbols exist
5080 std::vector<const char*> impliedExports;
5081 for (NameSet::iterator it=fExportSymbols.regularBegin(); it != fExportSymbols.regularEnd(); ++it) {
5082 const char* name = *it;
5083 const int len = strlen(name);
5084 if ( (strcmp(&name[len-3], ".eh") == 0) || (strncmp(name, ".objc_category_name_", 20) == 0) ) {
5085 // never export .eh symbols
5086 warning("ignoring %s in export list", name);
5088 else if ( (fArchitecture == CPU_TYPE_I386) && !fObjCABIVersion2Override && (strncmp(name, "_OBJC_CLASS_$", 13) == 0) ) {
5089 warning("ignoring Objc2 Class symbol %s in i386 export list", name);
5090 fRemovedExports.insert(name);
5092 else if ( alterObjC1ClassNamesToObjC2 && (strncmp(name, ".objc_class_name_", 17) == 0) ) {
5093 // linking ObjC2 ABI, but have ObjC1 ABI name in export list. Change it to intended name
5094 fRemovedExports.insert(name);
5095 char* temp;
5096 asprintf(&temp, "_OBJC_CLASS_$_%s", &name[17]);
5097 impliedExports.push_back(temp);
5098 asprintf(&temp, "_OBJC_METACLASS_$_%s", &name[17]);
5099 impliedExports.push_back(temp);
5101 else {
5102 fInitialUndefines.push_back(name);
5105 fExportSymbols.remove(fRemovedExports);
5106 for (std::vector<const char*>::iterator it=impliedExports.begin(); it != impliedExports.end(); ++it) {
5107 const char* name = *it;
5108 fExportSymbols.insert(name);
5109 fInitialUndefines.push_back(name);
5112 // make sure all required re-exported symbols exist
5113 for (NameSet::iterator it=fReExportSymbols.regularBegin(); it != fReExportSymbols.regularEnd(); ++it) {
5114 fInitialUndefines.push_back(*it);
5117 // make sure that -init symbol exists
5118 if ( fInitFunctionName != NULL )
5119 fInitialUndefines.push_back(fInitFunctionName);
5121 // make sure that entry symbol exists
5122 switch ( fOutputKind ) {
5123 case Options::kDynamicExecutable:
5124 case Options::kStaticExecutable:
5125 case Options::kDyld:
5126 case Options::kPreload:
5127 fInitialUndefines.push_back(fEntryName);
5128 break;
5129 case Options::kDynamicLibrary:
5130 case Options::kDynamicBundle:
5131 case Options::kObjectFile:
5132 case Options::kKextBundle:
5133 break;
5136 // make sure every alias base exists
5137 for (std::vector<AliasPair>::iterator it=fAliases.begin(); it != fAliases.end(); ++it) {
5138 fInitialUndefines.push_back(it->realName);
5141 // check custom segments
5142 if ( fCustomSegmentAddresses.size() != 0 ) {
5143 // verify no segment is in zero page
5144 if ( fZeroPageSize != ULLONG_MAX ) {
5145 for (std::vector<SegmentStart>::iterator it = fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
5146 if ( it->address < fZeroPageSize )
5147 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it->name, it->address);
5150 // verify no duplicates
5151 for (std::vector<SegmentStart>::iterator it = fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
5152 for (std::vector<SegmentStart>::iterator it2 = fCustomSegmentAddresses.begin(); it2 != fCustomSegmentAddresses.end(); ++it2) {
5153 if ( (it->address == it2->address) && (it != it2) )
5154 throwf("duplicate -segaddr addresses for %s and %s", it->name, it2->name);
5156 // a custom segment address of zero will disable the use of a zero page
5157 if ( it->address == 0 )
5158 fZeroPageSize = 0;
5162 if ( fZeroPageSize == ULLONG_MAX ) {
5163 // zero page size not specified on command line, set default
5164 switch (fArchitecture) {
5165 case CPU_TYPE_I386:
5166 case CPU_TYPE_ARM:
5167 // first 4KB for 32-bit architectures
5168 fZeroPageSize = 0x1000;
5169 break;
5170 case CPU_TYPE_ARM64:
5171 case CPU_TYPE_X86_64:
5172 // first 4GB for x86_64 on all OS's
5173 fZeroPageSize = 0x100000000ULL;
5174 break;
5175 default:
5176 // if -arch not used, default to 4K zero-page
5177 fZeroPageSize = 0x1000;
5180 else {
5181 switch ( fOutputKind ) {
5182 case Options::kDynamicExecutable:
5183 case Options::kStaticExecutable:
5184 // -pagezero_size size only legal when building main executable
5185 break;
5186 case Options::kDynamicLibrary:
5187 case Options::kDynamicBundle:
5188 case Options::kObjectFile:
5189 case Options::kDyld:
5190 case Options::kPreload:
5191 case Options::kKextBundle:
5192 if ( fZeroPageSize != 0 )
5193 throw "-pagezero_size option can only be used when linking a main executable";
5197 // if main executable with custom base address, model zero page as custom segment
5198 if ( (fOutputKind == Options::kDynamicExecutable) && (fBaseAddress != 0) && (fZeroPageSize != 0) ) {
5199 SegmentStart seg;
5200 seg.name = "__PAGEZERO";
5201 seg.address = 0;;
5202 fCustomSegmentAddresses.push_back(seg);
5205 // -dead_strip and -r are incompatible
5206 if ( fDeadStrip && (fOutputKind == Options::kObjectFile) )
5207 throw "-r and -dead_strip cannot be used together";
5209 // can't use -rpath unless targeting 10.5 or later
5210 if ( fRPaths.size() > 0 ) {
5211 if ( !minOS(ld::mac10_5, ld::iOS_2_0) )
5212 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
5213 switch ( fOutputKind ) {
5214 case Options::kDynamicExecutable:
5215 case Options::kDynamicLibrary:
5216 case Options::kDynamicBundle:
5217 break;
5218 case Options::kStaticExecutable:
5219 case Options::kObjectFile:
5220 case Options::kDyld:
5221 case Options::kPreload:
5222 case Options::kKextBundle:
5223 throw "-rpath can only be used when creating a dynamic final linked image";
5227 if ( fPositionIndependentExecutable ) {
5228 switch ( fOutputKind ) {
5229 case Options::kDynamicExecutable:
5230 // check -pie is only used when building a dynamic main executable for 10.5
5231 if ( !minOS(ld::mac10_5, ld::iOS_4_2) ) {
5232 if ( fIOSVersionMin == ld::iOSVersionUnset )
5233 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
5234 else
5235 throw "-pie can only be used when targeting iOS 4.2 or later";
5237 break;
5238 case Options::kStaticExecutable:
5239 case Options::kPreload:
5240 // -pie is ok with -static or -preload
5241 break;
5242 case Options::kDynamicLibrary:
5243 case Options::kDynamicBundle:
5244 warning("-pie being ignored. It is only used when linking a main executable");
5245 fPositionIndependentExecutable = false;
5246 break;
5247 case Options::kObjectFile:
5248 case Options::kDyld:
5249 case Options::kKextBundle:
5250 throw "-pie can only be used when linking a main executable";
5254 // check -read_only_relocs is not used with x86_64
5255 if ( fAllowTextRelocs ) {
5256 if ( (fArchitecture == CPU_TYPE_X86_64) && (fOutputKind != kKextBundle) ) {
5257 warning("-read_only_relocs cannot be used with x86_64");
5258 fAllowTextRelocs = false;
5262 // check -mark_auto_dead_strip is only used with dylibs
5263 if ( fMarkDeadStrippableDylib ) {
5264 if ( fOutputKind != Options::kDynamicLibrary ) {
5265 warning("-mark_auto_dead_strip can only be used when creating a dylib");
5266 fMarkDeadStrippableDylib = false;
5270 // -force_cpusubtype_ALL is not supported for ARM
5271 if ( fForceSubtypeAll ) {
5272 if ( fArchitecture == CPU_TYPE_ARM ) {
5273 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
5277 // -reexported_symbols_list can only be used with -dynamiclib
5278 if ( !fReExportSymbols.empty() ) {
5279 if ( fOutputKind != Options::kDynamicLibrary )
5280 throw "-reexported_symbols_list can only used used when created dynamic libraries";
5281 if ( !minOS(ld::mac10_7, ld::iOS_4_2) )
5282 throw "targeted OS version does not support -reexported_symbols_list";
5285 // -dyld_env can only be used with main executables
5286 if ( (fOutputKind != Options::kDynamicExecutable) && (fDyldEnvironExtras.size() != 0) )
5287 throw "-dyld_env can only used used when created main executables";
5289 // -segment_order can only be used with -preload
5290 if ( !fSegmentOrder.empty() && (fOutputKind != Options::kPreload) )
5291 throw "-segment_order can only used used with -preload output";
5293 // <rdar://problem/17598404> warn if building an embedded iOS dylib for pre-iOS 8
5294 // <rdar://problem/18935714> How can we suppress "ld: warning: embedded dylibs/frameworks only run on iOS 8 or laterÓ when building XCTest?
5295 if ( (fOutputKind == Options::kDynamicLibrary) && (fIOSVersionMin != ld::iOSVersionUnset) && (fDylibInstallName != NULL) ) {
5296 if ( !min_iOS(ld::iOS_8_0) && (fDylibInstallName[0] == '@') && !fEncryptableForceOff )
5297 warning("embedded dylibs/frameworks only run on iOS 8 or later");
5302 void Options::checkForClassic(int argc, const char* argv[])
5304 // scan options
5305 bool archFound = false;
5306 bool staticFound = false;
5307 bool dtraceFound = false;
5308 bool kextFound = false;
5309 bool rFound = false;
5310 bool creatingMachKernel = false;
5311 bool newLinker = false;
5313 // build command line buffer in case ld crashes
5314 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
5315 CRSetCrashLogMessage(crashreporterBuffer);
5316 #endif
5317 const char* srcRoot = getenv("SRCROOT");
5318 if ( srcRoot != NULL ) {
5319 strlcpy(crashreporterBuffer, "SRCROOT=", crashreporterBufferSize);
5320 strlcat(crashreporterBuffer, srcRoot, crashreporterBufferSize);
5321 strlcat(crashreporterBuffer, "\n", crashreporterBufferSize);
5323 #ifdef LD_VERS
5324 strlcat(crashreporterBuffer, LD_VERS, crashreporterBufferSize);
5325 strlcat(crashreporterBuffer, "\n", crashreporterBufferSize);
5326 #endif
5327 strlcat(crashreporterBuffer, "ld ", crashreporterBufferSize);
5328 for(int i=1; i < argc; ++i) {
5329 strlcat(crashreporterBuffer, argv[i], crashreporterBufferSize);
5330 strlcat(crashreporterBuffer, " ", crashreporterBufferSize);
5333 for(int i=0; i < argc; ++i) {
5334 const char* arg = argv[i];
5335 if ( arg[0] == '-' ) {
5336 if ( strcmp(arg, "-arch") == 0 ) {
5337 parseArch(argv[++i]);
5338 archFound = true;
5340 else if ( strcmp(arg, "-static") == 0 ) {
5341 staticFound = true;
5343 else if ( strcmp(arg, "-kext") == 0 ) {
5344 kextFound = true;
5346 else if ( strcmp(arg, "-dtrace") == 0 ) {
5347 dtraceFound = true;
5349 else if ( strcmp(arg, "-r") == 0 ) {
5350 rFound = true;
5352 else if ( strcmp(arg, "-new_linker") == 0 ) {
5353 newLinker = true;
5355 else if ( strcmp(arg, "-classic_linker") == 0 ) {
5356 // ld_classic does not understand this option, so remove it
5357 for(int j=i; j < argc; ++j)
5358 argv[j] = argv[j+1];
5359 warning("using ld_classic");
5360 this->gotoClassicLinker(argc-1, argv);
5362 else if ( strcmp(arg, "-o") == 0 ) {
5363 const char* outfile = argv[++i];
5364 if ( (outfile != NULL) && (strstr(outfile, "/mach_kernel") != NULL) )
5365 creatingMachKernel = true;
5371 void Options::gotoClassicLinker(int argc, const char* argv[])
5373 argv[0] = "ld_classic";
5374 // ld_classic does not support -iphoneos_version_min, so change
5375 for(int j=0; j < argc; ++j) {
5376 if ( (strcmp(argv[j], "-iphoneos_version_min") == 0) || (strcmp(argv[j], "-ios_version_min") == 0) ) {
5377 argv[j] = "-macosx_version_min";
5378 if ( j < argc-1 )
5379 argv[j+1] = "10.5";
5380 break;
5383 // ld classic does not understand -kext (change to -static -r)
5384 for(int j=0; j < argc; ++j) {
5385 if ( strcmp(argv[j], "-kext") == 0)
5386 argv[j] = "-r";
5387 else if ( strcmp(argv[j], "-dynamic") == 0)
5388 argv[j] = "-static";
5390 // ld classic does not understand -demangle
5391 for(int j=0; j < argc; ++j) {
5392 if ( strcmp(argv[j], "-demangle") == 0)
5393 argv[j] = "-noprebind";
5395 // in -v mode, print command line passed to ld_classic
5396 for(int i=0; i < argc; ++i) {
5397 if ( strcmp(argv[i], "-v") == 0 ) {
5398 for(int j=0; j < argc; ++j)
5399 printf("%s ", argv[j]);
5400 printf("\n");
5401 break;
5404 char rawPath[PATH_MAX];
5405 char path[PATH_MAX];
5406 uint32_t bufSize = PATH_MAX;
5407 if ( _NSGetExecutablePath(rawPath, &bufSize) != -1 ) {
5408 if ( realpath(rawPath, path) != NULL ) {
5409 char* lastSlash = strrchr(path, '/');
5410 if ( lastSlash != NULL ) {
5411 strcpy(lastSlash+1, "ld_classic");
5412 argv[0] = path;
5413 execvp(path, (char**)argv);
5417 // in case of error in above, try searching for ld_classic via PATH
5418 execvp(argv[0], (char**)argv);
5419 fprintf(stderr, "can't exec ld_classic\n");
5420 exit(1);
5424 // Note, returned string buffer is own by this function.
5425 // It should not be freed
5426 // It will be reused, so clients need to strdup() if they want
5427 // to use it long term.
5428 const char* Options::demangleSymbol(const char* sym) const
5430 // only try to demangle symbols if -demangle on command line
5431 if ( !fDemangle )
5432 return sym;
5434 static size_t size = 1024;
5435 static char* buff = (char*)malloc(size);
5437 #if DEMANGLE_SWIFT
5438 // only try to demangle symbols that look like Swift symbols
5439 if ( strncmp(sym, "__T", 3) == 0 ) {
5440 size_t demangledSize = fnd_get_demangled_name(&sym[1], buff, size);
5441 if ( demangledSize > size ) {
5442 size = demangledSize+2;
5443 buff = (char*)realloc(buff, size);
5444 demangledSize = fnd_get_demangled_name(&sym[1], buff, size);
5446 if ( demangledSize != 0 )
5447 return buff;
5449 #endif
5451 // only try to demangle symbols that look like C++ symbols
5452 if ( strncmp(sym, "__Z", 3) != 0 )
5453 return sym;
5455 int status;
5456 char* result = abi::__cxa_demangle(&sym[1], buff, &size, &status);
5457 if ( result != NULL ) {
5458 // if demangling successful, keep buffer for next demangle
5459 buff = result;
5460 return buff;
5462 return sym;
5466 void Options::dumpDependency(uint8_t opcode, const char* path) const
5468 if ( !this->dumpDependencyInfo() )
5469 return;
5471 // one time open() of -dependency_info file
5472 if ( fDependencyFileDescriptor == -1 ) {
5473 fDependencyFileDescriptor = open(this->dependencyInfoPath(), O_WRONLY | O_TRUNC | O_CREAT, 0666);
5474 if ( fDependencyFileDescriptor == -1 )
5475 throwf("Could not open or create -dependency_info file: %s", this->dependencyInfoPath());
5477 // write header
5478 uint8_t version = depLinkerVersion;
5479 if ( write(fDependencyFileDescriptor, &version, 1) == -1 )
5480 throwf("write() to -dependency_info failed, errno=%d", errno);
5481 extern const char ldVersionString[];
5482 if ( write(fDependencyFileDescriptor, ldVersionString, strlen(ldVersionString)+1) == -1 )
5483 throwf("write() to -dependency_info failed, errno=%d", errno);
5486 char realPath[PATH_MAX];
5487 if ( path[0] != '/' ) {
5488 if ( realpath(path, realPath) != NULL ) {
5489 path = realPath;
5493 if ( write(fDependencyFileDescriptor, &opcode, 1) == -1 )
5494 throwf("write() to -dependency_info failed, errno=%d", errno);
5495 if ( write(fDependencyFileDescriptor, path, strlen(path)+1) == -1 )
5496 throwf("write() to -dependency_info failed, errno=%d", errno);
5498 //fprintf(stderr, "0x%02X %s\n", opcode, path);