]> git.saurik.com Git - apple/ld64.git/blob - src/ld/Options.cpp
aa4f6ee85205f7c62c05704ae1916ca3e98805fb
[apple/ld64.git] / src / ld / Options.cpp
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2005-2011 Apple Inc. All rights reserved.
4 *
5 * @APPLE_LICENSE_HEADER_START@
6 *
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.
13 *
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.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25
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>
37
38 #include <vector>
39
40 #include "Options.h"
41 #include "Architectures.hpp"
42 #include "MachOFileAbstraction.hpp"
43 #include "Snapshot.h"
44
45 // upward dependency on lto::version()
46 namespace lto {
47 extern const char* version();
48 }
49
50 // magic to place command line in crash reports
51 const int crashreporterBufferSize = 2000;
52 static char crashreporterBuffer[crashreporterBufferSize];
53 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
54 #include <CrashReporterClient.h>
55 // hack until ld does not need to build on 10.6 anymore
56 struct crashreporter_annotations_t gCRAnnotations
57 __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION)))
58 = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 };
59 #else
60 extern "C" char* __crashreporter_info__;
61 __attribute__((used))
62 char* __crashreporter_info__ = crashreporterBuffer;
63 #endif
64
65
66 static bool sEmitWarnings = true;
67 static bool sFatalWarnings = false;
68 static const char* sWarningsSideFilePath = NULL;
69 static FILE* sWarningsSideFile = NULL;
70 static int sWarningsCount = 0;
71
72 void warning(const char* format, ...)
73 {
74 ++sWarningsCount;
75 if ( sEmitWarnings ) {
76 va_list list;
77 if ( sWarningsSideFilePath != NULL ) {
78 if ( sWarningsSideFile == NULL )
79 sWarningsSideFile = fopen(sWarningsSideFilePath, "a");
80 }
81 va_start(list, format);
82 fprintf(stderr, "ld: warning: ");
83 vfprintf(stderr, format, list);
84 fprintf(stderr, "\n");
85 if ( sWarningsSideFile != NULL ) {
86 fprintf(sWarningsSideFile, "ld: warning: ");
87 vfprintf(sWarningsSideFile, format, list);
88 fprintf(sWarningsSideFile, "\n");
89 fflush(sWarningsSideFile);
90 }
91 va_end(list);
92 }
93 }
94
95 void throwf(const char* format, ...)
96 {
97 va_list list;
98 char* p;
99 va_start(list, format);
100 vasprintf(&p, format, list);
101 va_end(list);
102
103 const char* t = p;
104 throw t;
105 }
106
107
108 bool Options::FileInfo::checkFileExists(const Options& options, const char *p)
109 {
110 struct stat statBuffer;
111 if (p == NULL)
112 p = path;
113 if ( stat(p, &statBuffer) == 0 ) {
114 if (p != path) path = strdup(p);
115 fileLen = statBuffer.st_size;
116 modTime = statBuffer.st_mtime;
117 return true;
118 }
119 if ( options.dumpDependencyInfo() )
120 options.dumpDependency(Options::depNotFound, p);
121 return false;
122 }
123
124
125 Options::Options(int argc, const char* argv[])
126 : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0), fArchitectureName("unknown"), fOutputKind(kDynamicExecutable),
127 fHasPreferredSubType(false), fArchSupportsThumb2(false), fPrebind(false), fBindAtLoad(false), fKeepPrivateExterns(false),
128 fNeedsModuleTable(false), fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false),
129 fInterposeMode(kInterposeNone), fDeadStrip(false), fNameSpace(kTwoLevelNameSpace),
130 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL), fFinalName(NULL), fEntryName(NULL),
131 fBaseAddress(0), fMaxAddress(0x7FFFFFFFFFFFFFFFLL),
132 fBaseWritableAddress(0), fSplitSegs(false),
133 fExportMode(kExportDefault), fLibrarySearchMode(kSearchDylibAndArchiveInEachDir),
134 fUndefinedTreatment(kUndefinedError), fMessagesPrefixedWithArchitecture(true),
135 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak),
136 fClientName(NULL),
137 fUmbrellaName(NULL), fInitFunctionName(NULL), fDotOutputFile(NULL), fExecutablePath(NULL),
138 fBundleLoader(NULL), fDtraceScriptName(NULL), fSegAddrTablePath(NULL), fMapPath(NULL),
139 fDyldInstallPath("/usr/lib/dyld"), fTempLtoObjectPath(NULL), fOverridePathlibLTO(NULL), fLtoCpu(NULL),
140 fZeroPageSize(ULLONG_MAX), fStackSize(0), fStackAddr(0), fSourceVersion(0), fSDKVersion(0), fExecutableStack(false),
141 fNonExecutableHeap(false), fDisableNonExecutableHeap(false),
142 fMinimumHeaderPad(32), fSegmentAlignment(4096),
143 fCommonsMode(kCommonsIgnoreDylibs), fUUIDMode(kUUIDContent), fLocalSymbolHandling(kLocalSymbolsAll), fWarnCommons(false),
144 fVerbose(false), fKeepRelocations(false), fWarnStabs(false),
145 fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
146 fSharedRegionEligible(false), fPrintOrderFileStatistics(false),
147 fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), fPIEOnCommandLine(false),
148 fDisablePositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
149 fDeadStripDylibs(false), fAllowTextRelocs(false), fWarnTextRelocs(false), fKextsUseStubs(false),
150 fUsingLazyDylibLinking(false), fEncryptable(true),
151 fOrderData(true), fMarkDeadStrippableDylib(false),
152 fMakeCompressedDyldInfo(true), fMakeCompressedDyldInfoForceOff(false), fNoEHLabels(false),
153 fAllowCpuSubtypeMismatches(false), fUseSimplifiedDylibReExports(false),
154 fObjCABIVersion2Override(false), fObjCABIVersion1Override(false), fCanUseUpwardDylib(false),
155 fFullyLoadArchives(false), fLoadAllObjcObjectsFromArchives(false), fFlatNamespace(false),
156 fLinkingMainExecutable(false), fForFinalLinkedImage(false), fForStatic(false),
157 fForDyld(false), fMakeTentativeDefinitionsReal(false), fWhyLoad(false), fRootSafe(false),
158 fSetuidSafe(false), fImplicitlyLinkPublicDylibs(true), fAddCompactUnwindEncoding(true),
159 fWarnCompactUnwind(false), fRemoveDwarfUnwindIfCompactExists(false),
160 fAutoOrderInitializers(true), fOptimizeZeroFill(true), fMergeZeroFill(false), fLogObjectFiles(false),
161 fLogAllFiles(false), fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false),
162 fOutputSlidable(false), fWarnWeakExports(false),
163 fObjcGcCompaction(false), fObjCGc(false), fObjCGcOnly(false),
164 fDemangle(false), fTLVSupport(false),
165 fVersionLoadCommand(false), fVersionLoadCommandForcedOn(false),
166 fVersionLoadCommandForcedOff(false), fFunctionStartsLoadCommand(false),
167 fFunctionStartsForcedOn(false), fFunctionStartsForcedOff(false),
168 fDataInCodeInfoLoadCommand(false), fDataInCodeInfoLoadCommandForcedOn(false), fDataInCodeInfoLoadCommandForcedOff(false),
169 fCanReExportSymbols(false), fObjcCategoryMerging(true), fPageAlignDataAtoms(false),
170 fNeedsThreadLoadCommand(false), fEntryPointLoadCommand(false),
171 fEntryPointLoadCommandForceOn(false), fEntryPointLoadCommandForceOff(false),
172 fSourceVersionLoadCommand(false),
173 fSourceVersionLoadCommandForceOn(false), fSourceVersionLoadCommandForceOff(false),
174 fDependentDRInfo(false), fDependentDRInfoForcedOn(false), fDependentDRInfoForcedOff(false),
175 fTargetIOSSimulator(false), fExportDynamic(false), fAbsoluteSymbols(false),
176 fAllowSimulatorToLinkWithMacOSX(false), fKeepDwarfUnwind(true),
177 fKeepDwarfUnwindForcedOn(false), fKeepDwarfUnwindForcedOff(false),
178 fVerboseOptimizationHints(false), fIgnoreOptimizationHints(false),
179 fGenerateDtraceDOF(true), fAllowBranchIslands(true), fTraceSymbolLayout(false),
180 fMarkAppExtensionSafe(false), fCheckAppExtensionSafe(false), fForceLoadSwiftLibs(false),
181 fDebugInfoStripping(kDebugInfoMinimal), fTraceOutputFile(NULL),
182 fMacVersionMin(ld::macVersionUnset), fIOSVersionMin(ld::iOSVersionUnset),
183 fSaveTempFiles(false), fSnapshotRequested(false), fPipelineFifo(NULL),
184 fDependencyInfoPath(NULL), fDependencyFileDescriptor(-1)
185 {
186 this->checkForClassic(argc, argv);
187 this->parsePreCommandLineEnvironmentSettings();
188 this->parse(argc, argv);
189 this->parsePostCommandLineEnvironmentSettings();
190 this->reconfigureDefaults();
191 this->checkIllegalOptionCombinations();
192
193 if ( this->dumpDependencyInfo() ) {
194 this->dumpDependency(depOutputFile, fOutputFile);
195 if ( fMapPath != NULL )
196 this->dumpDependency(depOutputFile, fMapPath);
197 }
198 }
199
200 Options::~Options()
201 {
202 if ( fDependencyFileDescriptor != -1 )
203 ::close(fDependencyFileDescriptor);
204 }
205
206 bool Options::errorBecauseOfWarnings() const
207 {
208 return (sFatalWarnings && (sWarningsCount > 0));
209 }
210
211
212 const char* Options::installPath() const
213 {
214 if ( fDylibInstallName != NULL )
215 return fDylibInstallName;
216 else if ( fFinalName != NULL )
217 return fFinalName;
218 else
219 return fOutputFile;
220 }
221
222
223 bool Options::interposable(const char* name) const
224 {
225 switch ( fInterposeMode ) {
226 case kInterposeNone:
227 return false;
228 case kInterposeAllExternal:
229 return true;
230 case kInterposeSome:
231 return fInterposeList.contains(name);
232 }
233 throw "internal error";
234 }
235
236
237 bool Options::printWhyLive(const char* symbolName) const
238 {
239 return ( fWhyLive.find(symbolName) != fWhyLive.end() );
240 }
241
242
243 const char* Options::dotOutputFile()
244 {
245 return fDotOutputFile;
246 }
247
248
249 bool Options::hasWildCardExportRestrictList() const
250 {
251 // has -exported_symbols_list which contains some wildcards
252 return ((fExportMode == kExportSome) && fExportSymbols.hasWildCards());
253 }
254
255 bool Options::hasWeakBitTweaks() const
256 {
257 // has -exported_symbols_list which contains some wildcards
258 return (!fForceWeakSymbols.empty() || !fForceNotWeakSymbols.empty());
259 }
260
261 bool Options::allGlobalsAreDeadStripRoots() const
262 {
263 // -exported_symbols_list means globals are not exported by default
264 if ( fExportMode == kExportSome )
265 return false;
266 //
267 switch ( fOutputKind ) {
268 case Options::kDynamicExecutable:
269 // <rdar://problem/12839986> Add the -export_dynamic flag
270 return fExportDynamic;
271 case Options::kStaticExecutable:
272 // <rdar://problem/13361218> Support the -export_dynamic flag for xnu
273 return fExportDynamic;
274 case Options::kPreload:
275 // by default unused globals in a main executable are stripped
276 return false;
277 case Options::kDynamicLibrary:
278 case Options::kDynamicBundle:
279 case Options::kObjectFile:
280 case Options::kDyld:
281 case Options::kKextBundle:
282 return true;
283 }
284 return false;
285 }
286
287
288 bool Options::keepRelocations()
289 {
290 return fKeepRelocations;
291 }
292
293 bool Options::warnStabs()
294 {
295 return fWarnStabs;
296 }
297
298 const char* Options::executablePath()
299 {
300 return fExecutablePath;
301 }
302
303 uint32_t Options::initialSegProtection(const char* segName) const
304 {
305 for(std::vector<Options::SegmentProtect>::const_iterator it = fCustomSegmentProtections.begin(); it != fCustomSegmentProtections.end(); ++it) {
306 if ( strcmp(it->name, segName) == 0 ) {
307 return it->init;
308 }
309 }
310 if ( strcmp(segName, "__PAGEZERO") == 0 ) {
311 return 0;
312 }
313 else if ( strcmp(segName, "__TEXT") == 0 ) {
314 return VM_PROT_READ | VM_PROT_EXECUTE;
315 }
316 else if ( strcmp(segName, "__LINKEDIT") == 0 ) {
317 return VM_PROT_READ;
318 }
319
320 // all others default to read-write
321 return VM_PROT_READ | VM_PROT_WRITE;
322 }
323
324 uint32_t Options::maxSegProtection(const char* segName) const
325 {
326 // iPhoneOS always uses same protection for max and initial
327 // <rdar://problem/11663436> simulator apps need to use MacOSX max-prot
328 if ( (fIOSVersionMin != ld::iOSVersionUnset) && (fArchitecture != CPU_TYPE_I386) )
329 return initialSegProtection(segName);
330
331 for(std::vector<Options::SegmentProtect>::const_iterator it = fCustomSegmentProtections.begin(); it != fCustomSegmentProtections.end(); ++it) {
332 if ( strcmp(it->name, segName) == 0 ) {
333 return it->max;
334 }
335 }
336 if ( strcmp(segName, "__PAGEZERO") == 0 ) {
337 return 0;
338 }
339 // all others default to all
340 return VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
341 }
342
343 uint64_t Options::segPageSize(const char* segName) const
344 {
345 for(std::vector<SegmentSize>::const_iterator it=fCustomSegmentSizes.begin(); it != fCustomSegmentSizes.end(); ++it) {
346 if ( strcmp(it->name, segName) == 0 )
347 return it->size;
348 }
349 return fSegmentAlignment;
350 }
351
352 uint64_t Options::customSegmentAddress(const char* segName) const
353 {
354 for(std::vector<SegmentStart>::const_iterator it=fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
355 if ( strcmp(it->name, segName) == 0 )
356 return it->address;
357 }
358 // if custom stack in use, model as segment with custom address
359 if ( (fStackSize != 0) && (strcmp("__UNIXSTACK", segName) == 0) )
360 return fStackAddr - fStackSize;
361 return 0;
362 }
363
364 bool Options::hasCustomSegmentAddress(const char* segName) const
365 {
366 for(std::vector<SegmentStart>::const_iterator it=fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
367 if ( strcmp(it->name, segName) == 0 )
368 return true;
369 }
370 // if custom stack in use, model as segment with custom address
371 if ( (fStackSize != 0) && (strcmp("__UNIXSTACK", segName) == 0) )
372 return true;
373 return false;
374 }
375
376 bool Options::hasCustomSectionAlignment(const char* segName, const char* sectName) const
377 {
378 for (std::vector<SectionAlignment>::const_iterator it = fSectionAlignments.begin(); it != fSectionAlignments.end(); ++it) {
379 if ( (strcmp(it->segmentName, segName) == 0) && (strcmp(it->sectionName, sectName) == 0) )
380 return true;
381 }
382 return false;
383 }
384
385 uint8_t Options::customSectionAlignment(const char* segName, const char* sectName) const
386 {
387 for (std::vector<SectionAlignment>::const_iterator it = fSectionAlignments.begin(); it != fSectionAlignments.end(); ++it) {
388 if ( (strcmp(it->segmentName, segName) == 0) && (strcmp(it->sectionName, sectName) == 0) )
389 return it->alignment;
390 }
391 return 0;
392 }
393
394
395 bool Options::hasExportedSymbolOrder()
396 {
397 return (fExportSymbolsOrder.size() > 0);
398 }
399
400 bool Options::exportedSymbolOrder(const char* sym, unsigned int* order) const
401 {
402 NameToOrder::const_iterator pos = fExportSymbolsOrder.find(sym);
403 if ( pos != fExportSymbolsOrder.end() ) {
404 *order = pos->second;
405 return true;
406 }
407 else {
408 *order = 0xFFFFFFFF;
409 return false;
410 }
411 }
412
413 void Options::loadSymbolOrderFile(const char* fileOfExports, NameToOrder& orderMapping)
414 {
415 // read in whole file
416 int fd = ::open(fileOfExports, O_RDONLY, 0);
417 if ( fd == -1 )
418 throwf("can't open -exported_symbols_order file: %s", fileOfExports);
419 struct stat stat_buf;
420 ::fstat(fd, &stat_buf);
421 char* p = (char*)malloc(stat_buf.st_size);
422 if ( p == NULL )
423 throwf("can't process -exported_symbols_order file: %s", fileOfExports);
424
425 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
426 throwf("can't read -exported_symbols_order file: %s", fileOfExports);
427
428 ::close(fd);
429
430 // parse into symbols and add to unordered_set
431 unsigned int count = 0;
432 char * const end = &p[stat_buf.st_size];
433 enum { lineStart, inSymbol, inComment } state = lineStart;
434 char* symbolStart = NULL;
435 for (char* s = p; s < end; ++s ) {
436 switch ( state ) {
437 case lineStart:
438 if ( *s =='#' ) {
439 state = inComment;
440 }
441 else if ( !isspace(*s) ) {
442 state = inSymbol;
443 symbolStart = s;
444 }
445 break;
446 case inSymbol:
447 if ( (*s == '\n') || (*s == '\r') ) {
448 *s = '\0';
449 // removing any trailing spaces
450 char* last = s-1;
451 while ( isspace(*last) ) {
452 *last = '\0';
453 --last;
454 }
455 orderMapping[symbolStart] = ++count;
456 symbolStart = NULL;
457 state = lineStart;
458 }
459 break;
460 case inComment:
461 if ( (*s == '\n') || (*s == '\r') )
462 state = lineStart;
463 break;
464 }
465 }
466 if ( state == inSymbol ) {
467 warning("missing line-end at end of file \"%s\"", fileOfExports);
468 int len = end-symbolStart+1;
469 char* temp = new char[len];
470 strlcpy(temp, symbolStart, len);
471
472 // remove any trailing spaces
473 char* last = &temp[len-2];
474 while ( isspace(*last) ) {
475 *last = '\0';
476 --last;
477 }
478 orderMapping[temp] = ++count;
479 }
480
481 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
482 }
483
484 bool Options::forceWeak(const char* symbolName) const
485 {
486 return fForceWeakSymbols.contains(symbolName);
487 }
488
489 bool Options::forceNotWeak(const char* symbolName) const
490 {
491 return fForceNotWeakSymbols.contains(symbolName);
492 }
493
494 bool Options::forceWeakNonWildCard(const char* symbolName) const
495 {
496 return fForceWeakSymbols.containsNonWildcard(symbolName);
497 }
498
499 bool Options::forceNotWeakNonWildcard(const char* symbolName) const
500 {
501 return fForceNotWeakSymbols.containsNonWildcard(symbolName);
502 }
503
504 bool Options::forceCoalesce(const char* symbolName) const
505 {
506 return fForceCoalesceSymbols.contains(symbolName);
507 }
508
509
510 bool Options::shouldExport(const char* symbolName) const
511 {
512 switch (fExportMode) {
513 case kExportSome:
514 return fExportSymbols.contains(symbolName);
515 case kDontExportSome:
516 return ! fDontExportSymbols.contains(symbolName);
517 case kExportDefault:
518 return true;
519 }
520 throw "internal error";
521 }
522
523 bool Options::shouldReExport(const char* symbolName) const
524 {
525 return fReExportSymbols.contains(symbolName);
526 }
527
528 bool Options::keepLocalSymbol(const char* symbolName) const
529 {
530 switch (fLocalSymbolHandling) {
531 case kLocalSymbolsAll:
532 return true;
533 case kLocalSymbolsNone:
534 return false;
535 case kLocalSymbolsSelectiveInclude:
536 return fLocalSymbolsIncluded.contains(symbolName);
537 case kLocalSymbolsSelectiveExclude:
538 return ! fLocalSymbolsExcluded.contains(symbolName);
539 }
540 throw "internal error";
541 }
542
543 const std::vector<const char*>* Options::sectionOrder(const char* segName) const
544 {
545 for (std::vector<SectionOrderList>::const_iterator it=fSectionOrder.begin(); it != fSectionOrder.end(); ++it) {
546 if ( strcmp(it->segmentName, segName) == 0 )
547 return &it->sectionOrder;
548 }
549 return NULL;
550 }
551
552
553
554 void Options::setArchitecture(cpu_type_t type, cpu_subtype_t subtype)
555 {
556 for (const ArchInfo* t=archInfoArray; t->archName != NULL; ++t) {
557 if ( (type == t->cpuType) && (subtype == t->cpuSubType) ) {
558 fArchitecture = type;
559 fSubArchitecture = subtype;
560 fArchitectureName = t->archName;
561 fHasPreferredSubType = t->isSubType;
562 fArchSupportsThumb2 = t->supportsThumb2;
563 switch ( type ) {
564 case CPU_TYPE_I386:
565 case CPU_TYPE_X86_64:
566 if ( (fMacVersionMin == ld::macVersionUnset) && (fIOSVersionMin == ld::iOSVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
567 #ifdef DEFAULT_MACOSX_MIN_VERSION
568 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION);
569 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
570 #else
571 warning("-macosx_version_min not specified, assuming 10.6");
572 fMacVersionMin = ld::mac10_6;
573 #endif
574 }
575 break;
576 case CPU_TYPE_ARM:
577 case CPU_TYPE_ARM64:
578 if ( (fMacVersionMin == ld::macVersionUnset) && (fIOSVersionMin == ld::iOSVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
579 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
580 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION);
581 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION);
582 #else
583 warning("-ios_version_min not specified, assuming 6.0");
584 setIOSVersionMin("6.0");
585 #endif
586 }
587 break;
588 }
589 fLinkSnapshot.recordArch(fArchitectureName);
590 // only use compressed LINKEDIT for:
591 // Mac OS X 10.6 or later
592 // iOS 3.1 or later
593 if ( !fMakeCompressedDyldInfo && minOS(ld::mac10_6, ld::iOS_3_1) && !fMakeCompressedDyldInfoForceOff )
594 fMakeCompressedDyldInfo = true;
595 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
596 if ( minOS(ld::mac10_5, ld::iOS_2_0) )
597 fUseSimplifiedDylibReExports = true;
598 return;
599 }
600 }
601 fArchitectureName = "unknown architecture";
602 }
603
604 void Options::parseArch(const char* arch)
605 {
606 if ( arch == NULL )
607 throw "-arch must be followed by an architecture string";
608 for (const ArchInfo* t=archInfoArray; t->archName != NULL; ++t) {
609 if ( strcmp(t->archName,arch) == 0 ) {
610 fArchitectureName = arch;
611 fArchitecture = t->cpuType;
612 fSubArchitecture = t->cpuSubType;
613 fHasPreferredSubType = t->isSubType;
614 fArchSupportsThumb2 = t->supportsThumb2;
615 return;
616 }
617 }
618 throwf("unknown/unsupported architecture name for: -arch %s", arch);
619 }
620
621 bool Options::checkForFile(const char* format, const char* dir, const char* rootName, FileInfo& result) const
622 {
623 char possiblePath[strlen(dir)+strlen(rootName)+strlen(format)+8];
624 sprintf(possiblePath, format, dir, rootName);
625 bool found = result.checkFileExists(*this, possiblePath);
626 if ( fTraceDylibSearching )
627 printf("[Logging for XBS]%sfound library: '%s'\n", (found ? " " : " not "), possiblePath);
628 return found;
629 }
630
631
632 Options::FileInfo Options::findLibrary(const char* rootName, bool dylibsOnly) const
633 {
634 FileInfo result;
635 const int rootNameLen = strlen(rootName);
636 // if rootName ends in .o there is no .a vs .dylib choice
637 if ( (rootNameLen > 3) && (strcmp(&rootName[rootNameLen-2], ".o") == 0) ) {
638 for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
639 it != fLibrarySearchPaths.end();
640 it++) {
641 const char* dir = *it;
642 if ( checkForFile("%s/%s", dir, rootName, result) )
643 return result;
644 }
645 }
646 else {
647 bool lookForDylibs = false;
648 switch ( fOutputKind ) {
649 case Options::kDynamicExecutable:
650 case Options::kDynamicLibrary:
651 case Options::kDynamicBundle:
652 case Options::kObjectFile: // <rdar://problem/15914513>
653 lookForDylibs = true;
654 break;
655 case Options::kStaticExecutable:
656 case Options::kDyld:
657 case Options::kPreload:
658 case Options::kKextBundle:
659 lookForDylibs = false;
660 break;
661 }
662 switch ( fLibrarySearchMode ) {
663 case kSearchAllDirsForDylibsThenAllDirsForArchives:
664 // first look in all directories for just for dylibs
665 if ( lookForDylibs ) {
666 for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
667 it != fLibrarySearchPaths.end();
668 it++) {
669 const char* dir = *it;
670 if ( checkForFile("%s/lib%s.dylib", dir, rootName, result) )
671 return result;
672 }
673 for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
674 it != fLibrarySearchPaths.end();
675 it++) {
676 const char* dir = *it;
677 if ( checkForFile("%s/lib%s.so", dir, rootName, result) )
678 return result;
679 }
680 }
681 // next look in all directories for just for archives
682 if ( !dylibsOnly ) {
683 for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
684 it != fLibrarySearchPaths.end();
685 it++) {
686 const char* dir = *it;
687 if ( checkForFile("%s/lib%s.a", dir, rootName, result) )
688 return result;
689 }
690 }
691 break;
692
693 case kSearchDylibAndArchiveInEachDir:
694 // look in each directory for just for a dylib then for an archive
695 for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
696 it != fLibrarySearchPaths.end();
697 it++) {
698 const char* dir = *it;
699 if ( lookForDylibs && checkForFile("%s/lib%s.dylib", dir, rootName, result) )
700 return result;
701 if ( lookForDylibs && checkForFile("%s/lib%s.so", dir, rootName, result) )
702 return result;
703 if ( !dylibsOnly && checkForFile("%s/lib%s.a", dir, rootName, result) )
704 return result;
705 }
706 break;
707 }
708 }
709 throwf("library not found for -l%s", rootName);
710 }
711
712 Options::FileInfo Options::findFramework(const char* frameworkName) const
713 {
714 if ( frameworkName == NULL )
715 throw "-framework missing next argument";
716 char temp[strlen(frameworkName)+1];
717 strcpy(temp, frameworkName);
718 const char* name = temp;
719 const char* suffix = NULL;
720 char* comma = strchr(temp, ',');
721 if ( comma != NULL ) {
722 *comma = '\0';
723 suffix = &comma[1];
724 }
725 return findFramework(name, suffix);
726 }
727
728 Options::FileInfo Options::findFramework(const char* rootName, const char* suffix) const
729 {
730 for (std::vector<const char*>::const_iterator it = fFrameworkSearchPaths.begin();
731 it != fFrameworkSearchPaths.end();
732 it++) {
733 // ??? Shouldn't we be using String here and just initializing it?
734 // ??? Use str.c_str () to pull out the string for the stat call.
735 const char* dir = *it;
736 char possiblePath[PATH_MAX];
737 strcpy(possiblePath, dir);
738 strcat(possiblePath, "/");
739 strcat(possiblePath, rootName);
740 strcat(possiblePath, ".framework/");
741 strcat(possiblePath, rootName);
742 if ( suffix != NULL ) {
743 char realPath[PATH_MAX];
744 // no symlink in framework to suffix variants, so follow main symlink
745 if ( realpath(possiblePath, realPath) != NULL ) {
746 strcpy(possiblePath, realPath);
747 strcat(possiblePath, suffix);
748 }
749 }
750 FileInfo result;
751 bool found = result.checkFileExists(*this, possiblePath);
752 if ( fTraceDylibSearching )
753 printf("[Logging for XBS]%sfound framework: '%s'\n",
754 (found ? " " : " not "), possiblePath);
755 if ( found ) {
756 return result;
757 }
758 }
759 // try without suffix
760 if ( suffix != NULL )
761 return findFramework(rootName, NULL);
762 else
763 throwf("framework not found %s", rootName);
764 }
765
766 Options::FileInfo Options::findFile(const char* path) const
767 {
768 FileInfo result;
769
770 // if absolute path and not a .o file, the use SDK prefix
771 if ( (path[0] == '/') && (strcmp(&path[strlen(path)-2], ".o") != 0) ) {
772 const int pathLen = strlen(path);
773 for (std::vector<const char*>::const_iterator it = fSDKPaths.begin(); it != fSDKPaths.end(); it++) {
774 // ??? Shouldn't we be using String here?
775 const char* sdkPathDir = *it;
776 const int sdkPathDirLen = strlen(sdkPathDir);
777 char possiblePath[sdkPathDirLen+pathLen+4];
778 strcpy(possiblePath, sdkPathDir);
779 if ( possiblePath[sdkPathDirLen-1] == '/' )
780 possiblePath[sdkPathDirLen-1] = '\0';
781 strcat(possiblePath, path);
782 if ( result.checkFileExists(*this, possiblePath) ) {
783 return result;
784 }
785 }
786 }
787 // try raw path
788 if ( result.checkFileExists(*this, path) ) {
789 return result;
790 }
791
792 // try @executable_path substitution
793 if ( (strncmp(path, "@executable_path/", 17) == 0) && (fExecutablePath != NULL) ) {
794 char newPath[strlen(fExecutablePath) + strlen(path)];
795 strcpy(newPath, fExecutablePath);
796 char* addPoint = strrchr(newPath,'/');
797 if ( addPoint != NULL )
798 strcpy(&addPoint[1], &path[17]);
799 else
800 strcpy(newPath, &path[17]);
801 if ( result.checkFileExists(*this, newPath) ) {
802 return result;
803 }
804 }
805
806 // not found
807 throwf("file not found: %s", path);
808 }
809
810 Options::FileInfo Options::findFileUsingPaths(const char* path) const
811 {
812 FileInfo result;
813
814 const char* lastSlash = strrchr(path, '/');
815 const char* leafName = (lastSlash == NULL) ? path : &lastSlash[1];
816
817 // Is this in a framework?
818 // /path/Foo.framework/Foo ==> true (Foo)
819 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
820 // /path/Foo.framework/Resources/Bar ==> false
821 bool isFramework = false;
822 if ( lastSlash != NULL ) {
823 char frameworkDir[strlen(leafName) + 20];
824 strcpy(frameworkDir, "/");
825 strcat(frameworkDir, leafName);
826 strcat(frameworkDir, ".framework/");
827 if ( strstr(path, frameworkDir) != NULL )
828 isFramework = true;
829 }
830
831 // These are abbreviated versions of the routines findFramework and findLibrary above
832 // because we already know the final name of the file that we're looking for and so
833 // don't need to try variations, just paths. We do need to add the additional bits
834 // onto the framework path though.
835 if ( isFramework ) {
836 for (std::vector<const char*>::const_iterator it = fFrameworkSearchPaths.begin();
837 it != fFrameworkSearchPaths.end();
838 it++) {
839 const char* dir = *it;
840 char possiblePath[PATH_MAX];
841 strcpy(possiblePath, dir);
842 strcat(possiblePath, "/");
843 strcat(possiblePath, leafName);
844 strcat(possiblePath, ".framework");
845
846 //fprintf(stderr,"Finding Framework: %s/%s, leafName=%s\n", possiblePath, leafName, leafName);
847 if ( checkForFile("%s/%s", possiblePath, leafName, result) )
848 return result;
849 }
850 }
851 else {
852 // if this is a .dylib inside a framework, do not search -L paths
853 // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
854 int leafLen = strlen(leafName);
855 bool embeddedDylib = ( (leafLen > 6)
856 && (strcmp(&leafName[leafLen-6], ".dylib") == 0)
857 && (strstr(path, ".framework/") != NULL) );
858 if ( !embeddedDylib ) {
859 for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
860 it != fLibrarySearchPaths.end();
861 it++) {
862 const char* dir = *it;
863 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
864 if ( checkForFile("%s/%s", dir, leafName, result) )
865 return result;
866 }
867 }
868 }
869
870 // If we didn't find it fall back to findFile.
871 return findFile(path);
872 }
873
874
875
876 void Options::parseSegAddrTable(const char* segAddrPath, const char* installPth)
877 {
878 FILE* file = fopen(segAddrPath, "r");
879 if ( file == NULL ) {
880 warning("-seg_addr_table file cannot be read: %s", segAddrPath);
881 return;
882 }
883
884 char path[PATH_MAX];
885 uint64_t firstColumAddress = 0;
886 uint64_t secondColumAddress = 0;
887 bool hasSecondColumn = false;
888 while ( fgets(path, PATH_MAX, file) != NULL ) {
889 path[PATH_MAX-1] = '\0';
890 char* eol = strchr(path, '\n');
891 if ( eol != NULL )
892 *eol = '\0';
893 // ignore lines not starting with 0x number
894 if ( (path[0] == '0') && (path[1] == 'x') ) {
895 char* p;
896 firstColumAddress = strtoull(path, &p, 16);
897 while ( isspace(*p) )
898 ++p;
899 // see if second column is a number
900 if ( (p[0] == '0') && (p[1] == 'x') ) {
901 secondColumAddress = strtoull(p, &p, 16);
902 hasSecondColumn = true;
903 while ( isspace(*p) )
904 ++p;
905 }
906 while ( isspace(*p) )
907 ++p;
908 if ( p[0] == '/' ) {
909 // remove any trailing whitespace
910 for(char* end = eol-1; (end > p) && isspace(*end); --end)
911 *end = '\0';
912 // see if this line is for the dylib being linked
913 if ( strcmp(p, installPth) == 0 ) {
914 fBaseAddress = firstColumAddress;
915 if ( hasSecondColumn ) {
916 fBaseWritableAddress = secondColumAddress;
917 fSplitSegs = true;
918 }
919 break; // out of while loop
920 }
921 }
922 }
923 }
924
925 fclose(file);
926 }
927
928 void Options::loadFileList(const char* fileOfPaths, ld::File::Ordinal baseOrdinal)
929 {
930 FILE* file;
931 const char* comma = strrchr(fileOfPaths, ',');
932 const char* prefix = NULL;
933 if ( comma != NULL ) {
934 // <rdar://problem/5907981> -filelist fails with comma in path
935 file = fopen(fileOfPaths, "r");
936 if ( file == NULL ) {
937 prefix = comma+1;
938 int realFileOfPathsLen = comma-fileOfPaths;
939 char realFileOfPaths[realFileOfPathsLen+1];
940 strncpy(realFileOfPaths,fileOfPaths, realFileOfPathsLen);
941 realFileOfPaths[realFileOfPathsLen] = '\0';
942 file = fopen(realFileOfPaths, "r");
943 if ( file == NULL )
944 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", realFileOfPaths, errno, strerror(errno));
945 if ( this->dumpDependencyInfo() )
946 this->dumpDependency(Options::depFileList, realFileOfPaths);
947 }
948 }
949 else {
950 file = fopen(fileOfPaths, "r");
951 if ( file == NULL )
952 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", fileOfPaths, errno, strerror(errno));
953 if ( this->dumpDependencyInfo() )
954 this->dumpDependency(Options::depFileList, fileOfPaths);
955 }
956
957 char path[PATH_MAX];
958 ld::File::Ordinal previousOrdinal = baseOrdinal;
959 while ( fgets(path, PATH_MAX, file) != NULL ) {
960 path[PATH_MAX-1] = '\0';
961 char* eol = strchr(path, '\n');
962 if ( eol != NULL )
963 *eol = '\0';
964 if ( prefix != NULL ) {
965 char builtPath[strlen(prefix)+strlen(path)+2];
966 strcpy(builtPath, prefix);
967 strcat(builtPath, "/");
968 strcat(builtPath, path);
969 if (fPipelineFifo != NULL) {
970 FileInfo info = FileInfo(builtPath);
971 info.ordinal = previousOrdinal.nextFileListOrdinal();
972 previousOrdinal = info.ordinal;
973 info.fromFileList = true;
974 fInputFiles.push_back(info);
975 } else {
976 FileInfo info = findFile(builtPath);
977 info.ordinal = previousOrdinal.nextFileListOrdinal();
978 previousOrdinal = info.ordinal;
979 info.fromFileList = true;
980 fInputFiles.push_back(info);
981 }
982 }
983 else {
984 if (fPipelineFifo != NULL) {
985 FileInfo info = FileInfo(path);
986 info.ordinal = previousOrdinal.nextFileListOrdinal();
987 previousOrdinal = info.ordinal;
988 info.fromFileList = true;
989 fInputFiles.push_back(info);
990 } else {
991 FileInfo info = findFile(path);
992 info.ordinal = previousOrdinal.nextFileListOrdinal();
993 previousOrdinal = info.ordinal;
994 info.fromFileList = true;
995 fInputFiles.push_back(info);
996 }
997 }
998 }
999 fclose(file);
1000 }
1001
1002
1003 void Options::SetWithWildcards::remove(const NameSet& toBeRemoved)
1004 {
1005 for(NameSet::const_iterator it=toBeRemoved.begin(); it != toBeRemoved.end(); ++it) {
1006 const char* symbolName = *it;
1007 NameSet::iterator pos = fRegular.find(symbolName);
1008 if ( pos != fRegular.end() )
1009 fRegular.erase(pos);
1010 }
1011 }
1012
1013 bool Options::SetWithWildcards::hasWildCards(const char* symbol)
1014 {
1015 // an exported symbol name containing *, ?, or [ requires wildcard matching
1016 return ( strpbrk(symbol, "*?[") != NULL );
1017 }
1018
1019 void Options::SetWithWildcards::insert(const char* symbol)
1020 {
1021 if ( hasWildCards(symbol) )
1022 fWildCard.push_back(symbol);
1023 else
1024 fRegular.insert(symbol);
1025 }
1026
1027 bool Options::SetWithWildcards::contains(const char* symbol, bool* matchBecauseOfWildcard) const
1028 {
1029 if ( matchBecauseOfWildcard != NULL )
1030 *matchBecauseOfWildcard = false;
1031 // first look at hash table on non-wildcard symbols
1032 if ( fRegular.find(symbol) != fRegular.end() )
1033 return true;
1034 // next walk list of wild card symbols looking for a match
1035 for(std::vector<const char*>::const_iterator it = fWildCard.begin(); it != fWildCard.end(); ++it) {
1036 if ( wildCardMatch(*it, symbol) ) {
1037 if ( matchBecauseOfWildcard != NULL )
1038 *matchBecauseOfWildcard = true;
1039 return true;
1040 }
1041 }
1042 return false;
1043 }
1044
1045 // Support "foo.o:_bar" to mean symbol _bar in file foo.o
1046 bool Options::SetWithWildcards::containsWithPrefix(const char* symbol, const char* file, bool& wildCardMatch) const
1047 {
1048 wildCardMatch = false;
1049 if ( contains(symbol, &wildCardMatch) )
1050 return true;
1051 if ( file == NULL )
1052 return false;
1053 const char* s = strrchr(file, '/');
1054 if ( s != NULL )
1055 file = s+1;
1056 char buff[strlen(file)+strlen(symbol)+2];
1057 sprintf(buff, "%s:%s", file, symbol);
1058 return contains(buff, &wildCardMatch);
1059 }
1060
1061 bool Options::SetWithWildcards::containsNonWildcard(const char* symbol) const
1062 {
1063 // look at hash table on non-wildcard symbols
1064 return ( fRegular.find(symbol) != fRegular.end() );
1065 }
1066
1067
1068
1069 bool Options::SetWithWildcards::inCharRange(const char*& p, unsigned char c) const
1070 {
1071 ++p; // find end
1072 const char* b = p;
1073 while ( *p != '\0' ) {
1074 if ( *p == ']') {
1075 const char* e = p;
1076 // found beginining [ and ending ]
1077 unsigned char last = '\0';
1078 for ( const char* s = b; s < e; ++s ) {
1079 if ( *s == '-' ) {
1080 unsigned char next = *(++s);
1081 if ( (last <= c) && (c <= next) )
1082 return true;
1083 ++s;
1084 }
1085 else {
1086 if ( *s == c )
1087 return true;
1088 last = *s;
1089 }
1090 }
1091 return false;
1092 }
1093 ++p;
1094 }
1095 return false;
1096 }
1097
1098 bool Options::SetWithWildcards::wildCardMatch(const char* pattern, const char* symbol) const
1099 {
1100 const char* s = symbol;
1101 for (const char* p = pattern; *p != '\0'; ++p) {
1102 switch ( *p ) {
1103 case '*':
1104 if ( p[1] == '\0' )
1105 return true;
1106 for (const char* t = s; *t != '\0'; ++t) {
1107 if ( wildCardMatch(&p[1], t) )
1108 return true;
1109 }
1110 return false;
1111 case '?':
1112 if ( *s == '\0' )
1113 return false;
1114 ++s;
1115 break;
1116 case '[':
1117 if ( ! inCharRange(p, *s) )
1118 return false;
1119 ++s;
1120 break;
1121 default:
1122 if ( *s != *p )
1123 return false;
1124 ++s;
1125 }
1126 }
1127 return (*s == '\0');
1128 }
1129
1130
1131 void Options::loadExportFile(const char* fileOfExports, const char* option, SetWithWildcards& set)
1132 {
1133 if ( fileOfExports == NULL )
1134 throwf("missing file after %s", option);
1135 // read in whole file
1136 int fd = ::open(fileOfExports, O_RDONLY, 0);
1137 if ( fd == -1 )
1138 throwf("can't open %s file: %s", option, fileOfExports);
1139 struct stat stat_buf;
1140 ::fstat(fd, &stat_buf);
1141 char* p = (char*)malloc(stat_buf.st_size);
1142 if ( p == NULL )
1143 throwf("can't process %s file: %s", option, fileOfExports);
1144
1145 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1146 throwf("can't read %s file: %s", option, fileOfExports);
1147
1148 if ( this->dumpDependencyInfo() )
1149 this->dumpDependency(Options::depMisc, fileOfExports);
1150
1151 ::close(fd);
1152
1153 // parse into symbols and add to unordered_set
1154 char * const end = &p[stat_buf.st_size];
1155 enum { lineStart, inSymbol, inComment } state = lineStart;
1156 char* symbolStart = NULL;
1157 for (char* s = p; s < end; ++s ) {
1158 switch ( state ) {
1159 case lineStart:
1160 if ( *s =='#' ) {
1161 state = inComment;
1162 }
1163 else if ( !isspace(*s) ) {
1164 state = inSymbol;
1165 symbolStart = s;
1166 }
1167 break;
1168 case inSymbol:
1169 if ( (*s == '\n') || (*s == '\r') ) {
1170 *s = '\0';
1171 // removing any trailing spaces
1172 char* last = s-1;
1173 while ( isspace(*last) ) {
1174 *last = '\0';
1175 --last;
1176 }
1177 set.insert(symbolStart);
1178 symbolStart = NULL;
1179 state = lineStart;
1180 }
1181 break;
1182 case inComment:
1183 if ( (*s == '\n') || (*s == '\r') )
1184 state = lineStart;
1185 break;
1186 }
1187 }
1188 if ( state == inSymbol ) {
1189 warning("missing line-end at end of file \"%s\"", fileOfExports);
1190 int len = end-symbolStart+1;
1191 char* temp = new char[len];
1192 strlcpy(temp, symbolStart, len);
1193
1194 // remove any trailing spaces
1195 char* last = &temp[len-2];
1196 while ( isspace(*last) ) {
1197 *last = '\0';
1198 --last;
1199 }
1200 set.insert(temp);
1201 }
1202
1203 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
1204 }
1205
1206 void Options::parseAliasFile(const char* fileOfAliases)
1207 {
1208 // read in whole file
1209 int fd = ::open(fileOfAliases, O_RDONLY, 0);
1210 if ( fd == -1 )
1211 throwf("can't open alias file: %s", fileOfAliases);
1212 struct stat stat_buf;
1213 ::fstat(fd, &stat_buf);
1214 char* p = (char*)malloc(stat_buf.st_size+1);
1215 if ( p == NULL )
1216 throwf("can't process alias file: %s", fileOfAliases);
1217
1218 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1219 throwf("can't read alias file: %s", fileOfAliases);
1220 p[stat_buf.st_size] = '\n';
1221 ::close(fd);
1222 if ( this->dumpDependencyInfo() )
1223 this->dumpDependency(Options::depMisc, fileOfAliases);
1224
1225 // parse into symbols and add to fAliases
1226 AliasPair pair;
1227 char * const end = &p[stat_buf.st_size+1];
1228 enum { lineStart, inRealName, inBetween, inAliasName, inComment } state = lineStart;
1229 int lineNumber = 1;
1230 for (char* s = p; s < end; ++s ) {
1231 switch ( state ) {
1232 case lineStart:
1233 if ( *s =='#' ) {
1234 state = inComment;
1235 }
1236 else if ( !isspace(*s) ) {
1237 state = inRealName;
1238 pair.realName = s;
1239 }
1240 break;
1241 case inRealName:
1242 if ( *s == '\n' ) {
1243 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber, fileOfAliases);
1244 ++lineNumber;
1245 state = lineStart;
1246 }
1247 else if ( isspace(*s) ) {
1248 *s = '\0';
1249 state = inBetween;
1250 }
1251 break;
1252 case inBetween:
1253 if ( *s == '\n' ) {
1254 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber, fileOfAliases);
1255 ++lineNumber;
1256 state = lineStart;
1257 }
1258 else if ( ! isspace(*s) ) {
1259 state = inAliasName;
1260 pair.alias = s;
1261 }
1262 break;
1263 case inAliasName:
1264 if ( *s =='#' ) {
1265 *s = '\0';
1266 // removing any trailing spaces
1267 char* last = s-1;
1268 while ( isspace(*last) ) {
1269 *last = '\0';
1270 --last;
1271 }
1272 fAliases.push_back(pair);
1273 state = inComment;
1274 }
1275 else if ( *s == '\n' ) {
1276 *s = '\0';
1277 // removing any trailing spaces
1278 char* last = s-1;
1279 while ( isspace(*last) ) {
1280 *last = '\0';
1281 --last;
1282 }
1283 fAliases.push_back(pair);
1284 state = lineStart;
1285 }
1286 break;
1287 case inComment:
1288 if ( *s == '\n' )
1289 state = lineStart;
1290 break;
1291 }
1292 }
1293
1294 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
1295 }
1296
1297
1298
1299 void Options::setUndefinedTreatment(const char* treatment)
1300 {
1301 if ( treatment == NULL )
1302 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
1303
1304 if ( strcmp(treatment, "warning") == 0 )
1305 fUndefinedTreatment = kUndefinedWarning;
1306 else if ( strcmp(treatment, "error") == 0 )
1307 fUndefinedTreatment = kUndefinedError;
1308 else if ( strcmp(treatment, "suppress") == 0 )
1309 fUndefinedTreatment = kUndefinedSuppress;
1310 else if ( strcmp(treatment, "dynamic_lookup") == 0 )
1311 fUndefinedTreatment = kUndefinedDynamicLookup;
1312 else
1313 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1314 }
1315
1316 Options::Treatment Options::parseTreatment(const char* treatment)
1317 {
1318 if ( treatment == NULL )
1319 return kNULL;
1320
1321 if ( strcmp(treatment, "warning") == 0 )
1322 return kWarning;
1323 else if ( strcmp(treatment, "error") == 0 )
1324 return kError;
1325 else if ( strcmp(treatment, "suppress") == 0 )
1326 return kSuppress;
1327 else
1328 return kInvalid;
1329 }
1330
1331 void Options::setMacOSXVersionMin(const char* version)
1332 {
1333 if ( version == NULL )
1334 throw "-macosx_version_min argument missing";
1335
1336 if ( (strncmp(version, "10.", 3) == 0) && isdigit(version[3]) ) {
1337 unsigned int minorVersion = 0;
1338 for (int i=3; isdigit(version[i]); ++i) {
1339 minorVersion = minorVersion*10 + (version[i] - '0');
1340 }
1341 if ( minorVersion > 255 ) {
1342 warning("Mac OS X minor version > 255 in '%s'", version);
1343 minorVersion = 255;
1344 }
1345 fMacVersionMin = (ld::MacVersionMin)(0x000A0000 | (minorVersion << 8));
1346 }
1347 else {
1348 warning("unknown option to -macosx_version_min, not 10.x");
1349 }
1350 }
1351
1352 void Options::setIOSVersionMin(const char* version)
1353 {
1354 if ( version == NULL )
1355 throw "-ios_version_min argument missing";
1356 if ( ! isdigit(version[0]) )
1357 throw "-ios_version_min argument is not a number";
1358 if ( version[1] != '.' )
1359 throw "-ios_version_min argument is missing period as second character";
1360 if ( ! isdigit(version[2]) )
1361 throw "-ios_version_min argument is not a number";
1362
1363 unsigned int majorVersion = version[0] - '0';
1364 unsigned int minorVersion = version[2] - '0';
1365 fIOSVersionMin = (ld::IOSVersionMin)((majorVersion << 16) | (minorVersion << 8));
1366 }
1367
1368 bool Options::minOS(ld::MacVersionMin requiredMacMin, ld::IOSVersionMin requirediPhoneOSMin)
1369 {
1370 if ( fMacVersionMin != ld::macVersionUnset ) {
1371 return ( fMacVersionMin >= requiredMacMin );
1372 }
1373 else {
1374 return ( fIOSVersionMin >= requirediPhoneOSMin);
1375 }
1376 }
1377
1378
1379 void Options::setWeakReferenceMismatchTreatment(const char* treatment)
1380 {
1381 if ( treatment == NULL )
1382 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1383
1384 if ( strcmp(treatment, "error") == 0 )
1385 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchError;
1386 else if ( strcmp(treatment, "weak") == 0 )
1387 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchWeak;
1388 else if ( strcmp(treatment, "non-weak") == 0 )
1389 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchNonWeak;
1390 else
1391 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1392 }
1393
1394 Options::CommonsMode Options::parseCommonsTreatment(const char* mode)
1395 {
1396 if ( mode == NULL )
1397 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1398
1399 if ( strcmp(mode, "ignore_dylibs") == 0 )
1400 return kCommonsIgnoreDylibs;
1401 else if ( strcmp(mode, "use_dylibs") == 0 )
1402 return kCommonsOverriddenByDylibs;
1403 else if ( strcmp(mode, "error") == 0 )
1404 return kCommonsConflictsDylibsError;
1405 else
1406 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1407 }
1408
1409 void Options::addDylibOverride(const char* paths)
1410 {
1411 if ( paths == NULL )
1412 throw "-dylib_file must followed by two colon separated paths";
1413 const char* colon = strchr(paths, ':');
1414 if ( colon == NULL )
1415 throw "-dylib_file must followed by two colon separated paths";
1416 int len = colon-paths;
1417 char* target = new char[len+2];
1418 strncpy(target, paths, len);
1419 target[len] = '\0';
1420 DylibOverride entry;
1421 entry.installName = target;
1422 entry.useInstead = &colon[1];
1423 fDylibOverrides.push_back(entry);
1424 }
1425
1426 uint64_t Options::parseAddress(const char* addr)
1427 {
1428 char* endptr;
1429 uint64_t result = strtoull(addr, &endptr, 16);
1430 return result;
1431 }
1432
1433 uint32_t Options::parseProtection(const char* prot)
1434 {
1435 uint32_t result = 0;
1436 for(const char* p = prot; *p != '\0'; ++p) {
1437 switch(tolower(*p)) {
1438 case 'r':
1439 result |= VM_PROT_READ;
1440 break;
1441 case 'w':
1442 result |= VM_PROT_WRITE;
1443 break;
1444 case 'x':
1445 result |= VM_PROT_EXECUTE;
1446 break;
1447 case '-':
1448 break;
1449 default:
1450 throwf("unknown -segprot lettter in %s", prot);
1451 }
1452 }
1453 return result;
1454 }
1455
1456
1457 //
1458 // Parses number of form A[.B[.B[.D[.E]]]] into a uint64_t where the bits are a24.b10.c10.d10.e10
1459 //
1460 uint64_t Options::parseVersionNumber64(const char* versionString)
1461 {
1462 uint64_t a = 0;
1463 uint64_t b = 0;
1464 uint64_t c = 0;
1465 uint64_t d = 0;
1466 uint64_t e = 0;
1467 char* end;
1468 a = strtoul(versionString, &end, 10);
1469 if ( *end == '.' ) {
1470 b = strtoul(&end[1], &end, 10);
1471 if ( *end == '.' ) {
1472 c = strtoul(&end[1], &end, 10);
1473 if ( *end == '.' ) {
1474 d = strtoul(&end[1], &end, 10);
1475 if ( *end == '.' ) {
1476 e = strtoul(&end[1], &end, 10);
1477 }
1478 }
1479 }
1480 }
1481 if ( (*end != '\0') || (a > 0xFFFFFF) || (b > 0x3FF) || (c > 0x3FF) || (d > 0x3FF) || (e > 0x3FF) )
1482 throwf("malformed 64-bit a.b.c.d.e version number: %s", versionString);
1483
1484 return (a << 40) | ( b << 30 ) | ( c << 20 ) | ( d << 10 ) | e;
1485 }
1486
1487
1488 uint32_t Options::currentVersion32() const
1489 {
1490 // warn if it does not fit into 32 bit vers number
1491 uint32_t a = (fDylibCurrentVersion >> 40) & 0xFFFF;
1492 uint32_t b = (fDylibCurrentVersion >> 30) & 0xFF;
1493 uint32_t c = (fDylibCurrentVersion >> 20) & 0xFF;
1494 uint64_t rep32 = ((uint64_t)a << 40) | ((uint64_t)b << 30) | ((uint64_t)c << 20);
1495 if ( rep32 != fDylibCurrentVersion ) {
1496 warning("truncating -current_version to fit in 32-bit space used by old mach-o format");
1497 a = (fDylibCurrentVersion >> 40) & 0xFFFFFF;
1498 if ( a > 0xFFFF )
1499 a = 0xFFFF;
1500 b = (fDylibCurrentVersion >> 30) & 0x3FF;
1501 if ( b > 0xFF )
1502 b = 0xFF;
1503 c = (fDylibCurrentVersion >> 20) & 0x3FF;
1504 if ( c > 0xFF )
1505 c = 0xFF;
1506 }
1507 return (a << 16) | ( b << 8 ) | c;
1508 }
1509
1510 //
1511 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1512 //
1513 uint32_t Options::parseVersionNumber32(const char* versionString)
1514 {
1515 uint32_t x = 0;
1516 uint32_t y = 0;
1517 uint32_t z = 0;
1518 char* end;
1519 x = strtoul(versionString, &end, 10);
1520 if ( *end == '.' ) {
1521 y = strtoul(&end[1], &end, 10);
1522 if ( *end == '.' ) {
1523 z = strtoul(&end[1], &end, 10);
1524 }
1525 }
1526 if ( (*end != '\0') || (x > 0xffff) || (y > 0xff) || (z > 0xff) )
1527 throwf("malformed 32-bit x.y.z version number: %s", versionString);
1528
1529 return (x << 16) | ( y << 8 ) | z;
1530 }
1531
1532 static const char* cstringSymbolName(const char* orderFileString)
1533 {
1534 char* result;
1535 asprintf(&result, "cstring=%s", orderFileString);
1536 // convert escaped characters
1537 char* d = result;
1538 for(const char* s=result; *s != '\0'; ++s, ++d) {
1539 if ( *s == '\\' ) {
1540 ++s;
1541 switch ( *s ) {
1542 case 'n':
1543 *d = '\n';
1544 break;
1545 case 't':
1546 *d = '\t';
1547 break;
1548 case 'v':
1549 *d = '\v';
1550 break;
1551 case 'b':
1552 *d = '\b';
1553 break;
1554 case 'r':
1555 *d = '\r';
1556 break;
1557 case 'f':
1558 *d = '\f';
1559 break;
1560 case 'a':
1561 *d = '\a';
1562 break;
1563 case '\\':
1564 *d = '\\';
1565 break;
1566 case '?':
1567 *d = '\?';
1568 break;
1569 case '\'':
1570 *d = '\r';
1571 break;
1572 case '\"':
1573 *d = '\"';
1574 break;
1575 case 'x':
1576 // hexadecimal value of char
1577 {
1578 ++s;
1579 char value = 0;
1580 while ( isxdigit(*s) ) {
1581 value *= 16;
1582 if ( isdigit(*s) )
1583 value += (*s-'0');
1584 else
1585 value += ((toupper(*s)-'A') + 10);
1586 ++s;
1587 }
1588 *d = value;
1589 }
1590 break;
1591 default:
1592 if ( isdigit(*s) ) {
1593 // octal value of char
1594 char value = 0;
1595 while ( isdigit(*s) ) {
1596 value = (value << 3) + (*s-'0');
1597 ++s;
1598 }
1599 *d = value;
1600 }
1601 }
1602 }
1603 else {
1604 *d = *s;
1605 }
1606 }
1607 *d = '\0';
1608 return result;
1609 }
1610
1611 void Options::parseOrderFile(const char* path, bool cstring)
1612 {
1613 // order files override auto-ordering
1614 fAutoOrderInitializers = false;
1615
1616 // read in whole file
1617 int fd = ::open(path, O_RDONLY, 0);
1618 if ( fd == -1 )
1619 throwf("can't open order file: %s", path);
1620 struct stat stat_buf;
1621 ::fstat(fd, &stat_buf);
1622 char* p = (char*)malloc(stat_buf.st_size+1);
1623 if ( p == NULL )
1624 throwf("can't process order file: %s", path);
1625 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1626 throwf("can't read order file: %s", path);
1627 ::close(fd);
1628 p[stat_buf.st_size] = '\n';
1629 if ( this->dumpDependencyInfo() )
1630 this->dumpDependency(Options::depMisc, path);
1631
1632 // parse into vector of pairs
1633 char * const end = &p[stat_buf.st_size+1];
1634 enum { lineStart, inSymbol, inComment } state = lineStart;
1635 char* symbolStart = NULL;
1636 for (char* s = p; s < end; ++s ) {
1637 switch ( state ) {
1638 case lineStart:
1639 if ( *s =='#' ) {
1640 state = inComment;
1641 }
1642 else if ( !isspace(*s) || cstring ) {
1643 state = inSymbol;
1644 symbolStart = s;
1645 }
1646 break;
1647 case inSymbol:
1648 if ( (*s == '\n') || (!cstring && (*s == '#')) ) {
1649 bool wasComment = (*s == '#');
1650 *s = '\0';
1651 // removing any trailing spaces
1652 char* last = s-1;
1653 while ( isspace(*last) ) {
1654 *last = '\0';
1655 --last;
1656 }
1657 // if there is an architecture prefix, only use this symbol it if matches current arch
1658 if ( strncmp(symbolStart, "ppc:", 4) == 0 ) {
1659 symbolStart = NULL;
1660 }
1661 else if ( strncmp(symbolStart, "ppc64:", 6) == 0 ) {
1662 symbolStart = NULL;
1663 }
1664 else if ( strncmp(symbolStart, "i386:", 5) == 0 ) {
1665 if ( fArchitecture == CPU_TYPE_I386 )
1666 symbolStart = &symbolStart[5];
1667 else
1668 symbolStart = NULL;
1669 }
1670 else if ( strncmp(symbolStart, "x86_64:", 7) == 0 ) {
1671 if ( fArchitecture == CPU_TYPE_X86_64 )
1672 symbolStart = &symbolStart[7];
1673 else
1674 symbolStart = NULL;
1675 }
1676 else if ( strncmp(symbolStart, "arm:", 4) == 0 ) {
1677 if ( fArchitecture == CPU_TYPE_ARM )
1678 symbolStart = &symbolStart[4];
1679 else
1680 symbolStart = NULL;
1681 }
1682 if ( symbolStart != NULL ) {
1683 char* objFileName = NULL;
1684 char* colon = strstr(symbolStart, ".o:");
1685 if ( colon != NULL ) {
1686 colon[2] = '\0';
1687 objFileName = symbolStart;
1688 symbolStart = &colon[3];
1689 }
1690 else {
1691 colon = strstr(symbolStart, ".o):");
1692 if ( colon != NULL ) {
1693 colon[3] = '\0';
1694 objFileName = symbolStart;
1695 symbolStart = &colon[4];
1696 }
1697 }
1698 // trim leading spaces
1699 while ( isspace(*symbolStart) )
1700 ++symbolStart;
1701 Options::OrderedSymbol pair;
1702 if ( cstring )
1703 pair.symbolName = cstringSymbolName(symbolStart);
1704 else
1705 pair.symbolName = symbolStart;
1706 pair.objectFileName = objFileName;
1707 fOrderedSymbols.push_back(pair);
1708 }
1709 symbolStart = NULL;
1710 if ( wasComment )
1711 state = inComment;
1712 else
1713 state = lineStart;
1714 }
1715 break;
1716 case inComment:
1717 if ( *s == '\n' )
1718 state = lineStart;
1719 break;
1720 }
1721 }
1722 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1723 }
1724
1725 void Options::parseSectionOrderFile(const char* segment, const char* section, const char* path)
1726 {
1727 if ( (strcmp(section, "__cstring") == 0) && (strcmp(segment, "__TEXT") == 0) ) {
1728 parseOrderFile(path, true);
1729 }
1730 else if ( (strncmp(section, "__literal",9) == 0) && (strcmp(segment, "__TEXT") == 0) ) {
1731 warning("sorting of __literal[4,8,16] sections not supported");
1732 }
1733 else {
1734 // ignore section information and append all symbol names to global order file
1735 parseOrderFile(path, false);
1736 }
1737 }
1738
1739 void Options::addSection(const char* segment, const char* section, const char* path)
1740 {
1741 if ( strlen(segment) > 16 )
1742 throw "-seccreate segment name max 16 chars";
1743 if ( strlen(section) > 16 ) {
1744 char* tmp = strdup(section);
1745 tmp[16] = '\0';
1746 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section, tmp);
1747 section = tmp;
1748 }
1749
1750 // read in whole file
1751 int fd = ::open(path, O_RDONLY, 0);
1752 if ( fd == -1 )
1753 throwf("can't open -sectcreate file: %s", path);
1754 struct stat stat_buf;
1755 ::fstat(fd, &stat_buf);
1756 char* p = (char*)malloc(stat_buf.st_size);
1757 if ( p == NULL )
1758 throwf("can't process -sectcreate file: %s", path);
1759 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1760 throwf("can't read -sectcreate file: %s", path);
1761 ::close(fd);
1762
1763 // record section to create
1764 ExtraSection info = { segment, section, path, (uint8_t*)p, stat_buf.st_size };
1765 fExtraSections.push_back(info);
1766 }
1767
1768 void Options::addSectionRename(const char* srcSegment, const char* srcSection, const char* dstSegment, const char* dstSection)
1769 {
1770 if ( strlen(srcSegment) > 16 )
1771 throw "-rename_section segment name max 16 chars";
1772 if ( strlen(srcSection) > 16 )
1773 throw "-rename_section section name max 16 chars";
1774 if ( strlen(dstSegment) > 16 )
1775 throw "-rename_section segment name max 16 chars";
1776 if ( strlen(dstSection) > 16 )
1777 throw "-rename_section section name max 16 chars";
1778
1779 SectionRename info;
1780 info.fromSegment = srcSegment;
1781 info.fromSection = srcSection;
1782 info.toSegment = dstSegment;
1783 info.toSection = dstSection;
1784
1785 fSectionRenames.push_back(info);
1786 }
1787
1788
1789 void Options::addSegmentRename(const char* srcSegment, const char* dstSegment)
1790 {
1791 if ( strlen(srcSegment) > 16 )
1792 throw "-rename_segment segment name max 16 chars";
1793 if ( strlen(dstSegment) > 16 )
1794 throw "-rename_segment segment name max 16 chars";
1795
1796 SegmentRename info;
1797 info.fromSegment = srcSegment;
1798 info.toSegment = dstSegment;
1799
1800 fSegmentRenames.push_back(info);
1801 }
1802
1803
1804
1805 void Options::addSymbolMove(const char* dstSegment, const char* symbolList,
1806 std::vector<SymbolsMove>& list, const char* optionName)
1807 {
1808 if ( strlen(dstSegment) > 16 )
1809 throwf("%s segment name max 16 chars", optionName);
1810
1811 SymbolsMove tmp;
1812 list.push_back(tmp);
1813 SymbolsMove& info = list.back();
1814 info.toSegment = dstSegment;
1815 loadExportFile(symbolList, optionName, info.symbols);
1816 }
1817
1818 bool Options::moveRwSymbol(const char* symName, const char* filePath, const char*& seg, bool& wildCardMatch) const
1819 {
1820 for (std::vector<SymbolsMove>::const_iterator it=fSymbolsMovesData.begin(); it != fSymbolsMovesData.end(); ++it) {
1821 const SymbolsMove& info = *it;
1822 if ( info.symbols.containsWithPrefix(symName, filePath, wildCardMatch)) {
1823 seg = info.toSegment;
1824 return true;
1825 }
1826 }
1827 return false;
1828 }
1829
1830 bool Options::moveRoSymbol(const char* symName, const char* filePath, const char*& seg, bool& wildCardMatch) const
1831 {
1832 for (std::vector<SymbolsMove>::const_iterator it=fSymbolsMovesCode.begin(); it != fSymbolsMovesCode.end(); ++it) {
1833 const SymbolsMove& info = *it;
1834 if ( info.symbols.containsWithPrefix(symName, filePath, wildCardMatch)) {
1835 seg = info.toSegment;
1836 return true;
1837 }
1838 }
1839 return false;
1840 }
1841
1842 void Options::addSectionAlignment(const char* segment, const char* section, const char* alignmentStr)
1843 {
1844 if ( strlen(segment) > 16 )
1845 throw "-sectalign segment name max 16 chars";
1846 if ( strlen(section) > 16 )
1847 throw "-sectalign section name max 16 chars";
1848
1849 // argument to -sectalign is a hexadecimal number
1850 char* endptr;
1851 unsigned long value = strtoul(alignmentStr, &endptr, 16);
1852 if ( *endptr != '\0')
1853 throw "argument for -sectalign is not a hexadecimal number";
1854 if ( value > 0x8000 )
1855 throw "argument for -sectalign must be less than or equal to 0x8000";
1856 if ( value == 0 ) {
1857 warning("zero is not a valid -sectalign");
1858 value = 1;
1859 }
1860
1861 // alignment is power of 2 (e.g. page alignment = 12)
1862 uint8_t alignment = (uint8_t)__builtin_ctz(value);
1863 if ( (unsigned long)(1 << alignment) != value ) {
1864 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
1865 segment, section, 1 << alignment);
1866 }
1867
1868 SectionAlignment info = { segment, section, alignment };
1869 fSectionAlignments.push_back(info);
1870 }
1871
1872 void Options::addLibrary(const FileInfo& info)
1873 {
1874 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
1875 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
1876 if ( strcmp(info.path, fit->path) == 0 ) {
1877 // if dylib is specified again but weak, record that it should be weak
1878 if ( info.options.fWeakImport )
1879 fit->options.fWeakImport = true;
1880 return;
1881 }
1882 }
1883 // add to list
1884 fInputFiles.push_back(info);
1885 }
1886
1887 void Options::warnObsolete(const char* arg)
1888 {
1889 warning("option %s is obsolete and being ignored", arg);
1890 }
1891
1892
1893
1894
1895 //
1896 // Process all command line arguments.
1897 //
1898 // The only error checking done here is that each option is valid and if it has arguments
1899 // that they too are valid.
1900 //
1901 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
1902 // whichever was last on the command line is used.
1903 //
1904 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
1905 //
1906 void Options::parse(int argc, const char* argv[])
1907 {
1908 // Store the original args in the link snapshot.
1909 fLinkSnapshot.recordRawArgs(argc, argv);
1910
1911 // pass one builds search list from -L and -F options
1912 this->buildSearchPaths(argc, argv);
1913
1914 // reduce re-allocations
1915 fInputFiles.reserve(32);
1916
1917 // pass two parse all other options
1918 for(int i=1; i < argc; ++i) {
1919 const char* arg = argv[i];
1920
1921 if ( arg[0] == '-' ) {
1922 // by default, copy one arg to the snapshot link command, and do no file copying
1923 int snapshotArgIndex = i;
1924 int snapshotArgCount = -1; // -1 means compute count based on change in index
1925 int snapshotFileArgIndex = -1; // -1 means no data file parameter to arg
1926
1927 // Since we don't care about the files passed, just the option names, we do this here.
1928 if (fPrintOptions)
1929 fprintf (stderr, "[Logging ld64 options]\t%s\n", arg);
1930
1931 if ( (arg[1] == 'L') || (arg[1] == 'F') ) {
1932 snapshotArgCount = 0; // stripped out of link snapshot
1933 if (arg[2] == '\0')
1934 ++i;
1935 // previously handled by buildSearchPaths()
1936 }
1937 // The one gnu style option we have to keep compatibility
1938 // with gcc. Might as well have the single hyphen one as well.
1939 else if ( (strcmp(arg, "--help") == 0)
1940 || (strcmp(arg, "-help") == 0)) {
1941 fprintf (stdout, "ld64: For information on command line options please use 'man ld'.\n");
1942 exit (0);
1943 }
1944 else if ( strcmp(arg, "-arch") == 0 ) {
1945 parseArch(argv[++i]);
1946 }
1947 else if ( strcmp(arg, "-dynamic") == 0 ) {
1948 // default
1949 }
1950 else if ( strcmp(arg, "-static") == 0 ) {
1951 fForStatic = true;
1952 if ( (fOutputKind != kObjectFile) && (fOutputKind != kKextBundle) ) {
1953 fOutputKind = kStaticExecutable;
1954 }
1955 }
1956 else if ( strcmp(arg, "-dylib") == 0 ) {
1957 fOutputKind = kDynamicLibrary;
1958 }
1959 else if ( strcmp(arg, "-bundle") == 0 ) {
1960 fOutputKind = kDynamicBundle;
1961 }
1962 else if ( strcmp(arg, "-dylinker") == 0 ) {
1963 fOutputKind = kDyld;
1964 }
1965 else if ( strcmp(arg, "-execute") == 0 ) {
1966 if ( fOutputKind != kStaticExecutable )
1967 fOutputKind = kDynamicExecutable;
1968 }
1969 else if ( strcmp(arg, "-preload") == 0 ) {
1970 fOutputKind = kPreload;
1971 }
1972 else if ( strcmp(arg, "-r") == 0 ) {
1973 fOutputKind = kObjectFile;
1974 }
1975 else if ( strcmp(arg, "-kext") == 0 ) {
1976 fOutputKind = kKextBundle;
1977 }
1978 else if ( strcmp(arg, "-o") == 0 ) {
1979 snapshotArgCount = 0;
1980 fOutputFile = argv[++i];
1981 fLinkSnapshot.setSnapshotName(fOutputFile);
1982 }
1983 else if ( strncmp(arg, "-lazy-l", 7) == 0 ) {
1984 snapshotArgCount = 0;
1985 FileInfo info = findLibrary(&arg[7], true);
1986 info.options.fLazyLoad = true;
1987 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
1988 addLibrary(info);
1989 fUsingLazyDylibLinking = true;
1990 }
1991 else if ( strcmp(arg, "-lto_library") == 0 ) {
1992 snapshotFileArgIndex = 1;
1993 fOverridePathlibLTO = argv[++i];
1994 if ( fOverridePathlibLTO == NULL )
1995 throw "missing argument to -lto_library";
1996 }
1997 else if ( (arg[1] == 'l') && (strncmp(arg,"-lazy_",6) !=0) ) {
1998 snapshotArgCount = 0;
1999 FileInfo info = findLibrary(&arg[2]);
2000 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2001 addLibrary(info);
2002 }
2003 // This causes a dylib to be weakly bound at
2004 // link time. This corresponds to weak_import.
2005 else if ( strncmp(arg, "-weak-l", 7) == 0 ) {
2006 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2007 snapshotArgCount = 0;
2008 FileInfo info = findLibrary(&arg[7]);
2009 info.options.fWeakImport = true;
2010 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2011 addLibrary(info);
2012 }
2013 // Avoid lazy binding.
2014 else if ( strcmp(arg, "-bind_at_load") == 0 ) {
2015 fBindAtLoad = true;
2016 }
2017 else if ( strcmp(arg, "-twolevel_namespace") == 0 ) {
2018 fNameSpace = kTwoLevelNameSpace;
2019 }
2020 else if ( strcmp(arg, "-flat_namespace") == 0 ) {
2021 fNameSpace = kFlatNameSpace;
2022 }
2023 // Also sets a bit to ensure dyld causes everything
2024 // in the namespace to be flat.
2025 // ??? Deprecate
2026 else if ( strcmp(arg, "-force_flat_namespace") == 0 ) {
2027 fNameSpace = kForceFlatNameSpace;
2028 }
2029 // Similar to --whole-archive.
2030 else if ( strcmp(arg, "-all_load") == 0 ) {
2031 fFullyLoadArchives = true;
2032 }
2033 else if ( strcmp(arg, "-noall_load") == 0) {
2034 warnObsolete(arg);
2035 }
2036 // Similar to -all_load
2037 else if ( strcmp(arg, "-ObjC") == 0 ) {
2038 fLoadAllObjcObjectsFromArchives = true;
2039 }
2040 // Similar to -all_load, but for the following archive only.
2041 else if ( strcmp(arg, "-force_load") == 0 ) {
2042 FileInfo info = findFile(argv[++i]);
2043 info.options.fForceLoad = true;
2044 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2045 addLibrary(info);
2046 }
2047 // Library versioning.
2048 else if ( (strcmp(arg, "-dylib_compatibility_version") == 0)
2049 || (strcmp(arg, "-compatibility_version") == 0)) {
2050 const char* vers = argv[++i];
2051 if ( vers == NULL )
2052 throw "-dylib_compatibility_version missing <version>";
2053 fDylibCompatVersion = parseVersionNumber32(vers);
2054 }
2055 else if ( (strcmp(arg, "-dylib_current_version") == 0)
2056 || (strcmp(arg, "-current_version") == 0)) {
2057 const char* vers = argv[++i];
2058 if ( vers == NULL )
2059 throw "-dylib_current_version missing <version>";
2060 fDylibCurrentVersion = parseVersionNumber64(vers);
2061 }
2062 else if ( strcmp(arg, "-sectorder") == 0 ) {
2063 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
2064 throw "-sectorder missing <segment> <section> <file-path>";
2065 snapshotFileArgIndex = 3;
2066 parseSectionOrderFile(argv[i+1], argv[i+2], argv[i+3]);
2067 i += 3;
2068 }
2069 else if ( strcmp(arg, "-order_file") == 0 ) {
2070 snapshotFileArgIndex = 1;
2071 parseOrderFile(argv[++i], false);
2072 }
2073 else if ( strcmp(arg, "-order_file_statistics") == 0 ) {
2074 fPrintOrderFileStatistics = true;
2075 }
2076 // ??? Deprecate segcreate.
2077 // -sectcreate puts whole files into a section in the output.
2078 else if ( (strcmp(arg, "-sectcreate") == 0) || (strcmp(arg, "-segcreate") == 0) ) {
2079 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
2080 throw "-sectcreate missing <segment> <section> <file-path>";
2081 snapshotFileArgIndex = 3;
2082 addSection(argv[i+1], argv[i+2], argv[i+3]);
2083 i += 3;
2084 }
2085 // Since we have a full path in binary/library names we need to be able to override it.
2086 else if ( (strcmp(arg, "-dylib_install_name") == 0)
2087 || (strcmp(arg, "-dylinker_install_name") == 0)
2088 || (strcmp(arg, "-install_name") == 0)) {
2089 fDylibInstallName = argv[++i];
2090 if ( fDylibInstallName == NULL )
2091 throw "-install_name missing <path>";
2092 }
2093 // Sets the base address of the output.
2094 else if ( (strcmp(arg, "-seg1addr") == 0) || (strcmp(arg, "-image_base") == 0) ) {
2095 const char* address = argv[++i];
2096 if ( address == NULL )
2097 throwf("%s missing <address>", arg);
2098 fBaseAddress = parseAddress(address);
2099 uint64_t temp = ((fBaseAddress+fSegmentAlignment-1) & (-fSegmentAlignment));
2100 if ( fBaseAddress != temp ) {
2101 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment);
2102 fBaseAddress = temp;
2103 }
2104 }
2105 else if ( strcmp(arg, "-e") == 0 ) {
2106 fEntryName = argv[++i];
2107 }
2108 // Same as -@ from the FSF linker.
2109 else if ( strcmp(arg, "-filelist") == 0 ) {
2110 snapshotArgCount = 0;
2111 const char* path = argv[++i];
2112 if ( (path == NULL) || (path[0] == '-') )
2113 throw "-filelist missing <path>";
2114 ld::File::Ordinal baseOrdinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2115 loadFileList(path, baseOrdinal);
2116 }
2117 else if ( strcmp(arg, "-keep_private_externs") == 0 ) {
2118 fKeepPrivateExterns = true;
2119 }
2120 else if ( strcmp(arg, "-final_output") == 0 ) {
2121 fFinalName = argv[++i];
2122 }
2123 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
2124 // just ensures that this happens for cross object file boundaries.
2125 else if ( (strcmp(arg, "-interposable") == 0) || (strcmp(arg, "-multi_module") == 0)) {
2126 switch ( fInterposeMode ) {
2127 case kInterposeNone:
2128 case kInterposeAllExternal:
2129 fInterposeMode = kInterposeAllExternal;
2130 break;
2131 case kInterposeSome:
2132 // do nothing, -interposable_list overrides -interposable"
2133 break;
2134 }
2135 }
2136 else if ( strcmp(arg, "-interposable_list") == 0 ) {
2137 snapshotFileArgIndex = 1;
2138 fInterposeMode = kInterposeSome;
2139 loadExportFile(argv[++i], "-interposable_list", fInterposeList);
2140 }
2141 // Default for -interposable/-multi_module/-single_module.
2142 else if ( strcmp(arg, "-single_module") == 0 ) {
2143 fInterposeMode = kInterposeNone;
2144 }
2145 else if ( strcmp(arg, "-exported_symbols_list") == 0 ) {
2146 snapshotFileArgIndex = 1;
2147 if ( fExportMode == kDontExportSome )
2148 throw "can't use -exported_symbols_list and -unexported_symbols_list";
2149 fExportMode = kExportSome;
2150 loadExportFile(argv[++i], "-exported_symbols_list", fExportSymbols);
2151 }
2152 else if ( strcmp(arg, "-unexported_symbols_list") == 0 ) {
2153 snapshotFileArgIndex = 1;
2154 if ( fExportMode == kExportSome )
2155 throw "can't use -unexported_symbols_list and -exported_symbols_list";
2156 fExportMode = kDontExportSome;
2157 loadExportFile(argv[++i], "-unexported_symbols_list", fDontExportSymbols);
2158 }
2159 else if ( strcmp(arg, "-exported_symbol") == 0 ) {
2160 if ( fExportMode == kDontExportSome )
2161 throw "can't use -exported_symbol and -unexported_symbols";
2162 fExportMode = kExportSome;
2163 fExportSymbols.insert(argv[++i]);
2164 }
2165 else if ( strcmp(arg, "-unexported_symbol") == 0 ) {
2166 if ( fExportMode == kExportSome )
2167 throw "can't use -unexported_symbol and -exported_symbol";
2168 fExportMode = kDontExportSome;
2169 fDontExportSymbols.insert(argv[++i]);
2170 }
2171 else if ( strcmp(arg, "-non_global_symbols_no_strip_list") == 0 ) {
2172 snapshotFileArgIndex = 1;
2173 if ( fLocalSymbolHandling == kLocalSymbolsSelectiveExclude )
2174 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2175 fLocalSymbolHandling = kLocalSymbolsSelectiveInclude;
2176 loadExportFile(argv[++i], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded);
2177 }
2178 else if ( strcmp(arg, "-non_global_symbols_strip_list") == 0 ) {
2179 snapshotFileArgIndex = 1;
2180 if ( fLocalSymbolHandling == kLocalSymbolsSelectiveInclude )
2181 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2182 fLocalSymbolHandling = kLocalSymbolsSelectiveExclude;
2183 loadExportFile(argv[++i], "-non_global_symbols_strip_list", fLocalSymbolsExcluded);
2184 }
2185 // ??? Deprecate
2186 else if ( strcmp(arg, "-no_arch_warnings") == 0 ) {
2187 fIgnoreOtherArchFiles = true;
2188 }
2189 else if ( strcmp(arg, "-force_cpusubtype_ALL") == 0 ) {
2190 fForceSubtypeAll = true;
2191 fAllowCpuSubtypeMismatches = true;
2192 }
2193 // Similar to -weak-l but uses the absolute path name to the library.
2194 else if ( strcmp(arg, "-weak_library") == 0 ) {
2195 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2196 snapshotArgCount = 0;
2197 FileInfo info = findFile(argv[++i]);
2198 info.options.fWeakImport = true;
2199 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2200 addLibrary(info);
2201 }
2202 else if ( strcmp(arg, "-lazy_library") == 0 ) {
2203 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2204 snapshotArgCount = 0;
2205 FileInfo info = findFile(argv[++i]);
2206 info.options.fLazyLoad = true;
2207 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2208 addLibrary(info);
2209 fUsingLazyDylibLinking = true;
2210 }
2211 else if ( strcmp(arg, "-framework") == 0 ) {
2212 snapshotArgCount = 0;
2213 FileInfo info = findFramework(argv[++i]);
2214 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2215 addLibrary(info);
2216 }
2217 else if ( strcmp(arg, "-weak_framework") == 0 ) {
2218 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2219 snapshotArgCount = 0;
2220 FileInfo info = findFramework(argv[++i]);
2221 info.options.fWeakImport = true;
2222 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2223 addLibrary(info);
2224 }
2225 else if ( strcmp(arg, "-lazy_framework") == 0 ) {
2226 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2227 snapshotArgCount = 0;
2228 FileInfo info = findFramework(argv[++i]);
2229 info.options.fLazyLoad = true;
2230 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2231 addLibrary(info);
2232 fUsingLazyDylibLinking = true;
2233 }
2234 else if ( strcmp(arg, "-search_paths_first") == 0 ) {
2235 // previously handled by buildSearchPaths()
2236 }
2237 else if ( strcmp(arg, "-search_dylibs_first") == 0 ) {
2238 // previously handled by buildSearchPaths()
2239 }
2240 else if ( strcmp(arg, "-undefined") == 0 ) {
2241 setUndefinedTreatment(argv[++i]);
2242 }
2243 // Debugging output flag.
2244 else if ( strcmp(arg, "-arch_multiple") == 0 ) {
2245 fMessagesPrefixedWithArchitecture = true;
2246 }
2247 // Specify what to do with relocations in read only
2248 // sections like .text. Could be errors, warnings,
2249 // or suppressed. Currently we do nothing with the
2250 // flag.
2251 else if ( strcmp(arg, "-read_only_relocs") == 0 ) {
2252 switch ( parseTreatment(argv[++i]) ) {
2253 case kNULL:
2254 case kInvalid:
2255 throw "-read_only_relocs missing [ warning | error | suppress ]";
2256 case kWarning:
2257 fWarnTextRelocs = true;
2258 fAllowTextRelocs = true;
2259 break;
2260 case kSuppress:
2261 fWarnTextRelocs = false;
2262 fAllowTextRelocs = true;
2263 break;
2264 case kError:
2265 fWarnTextRelocs = false;
2266 fAllowTextRelocs = false;
2267 break;
2268 }
2269 }
2270 else if ( strcmp(arg, "-sect_diff_relocs") == 0 ) {
2271 warnObsolete(arg);
2272 ++i;
2273 }
2274 // Warn, error or make strong a mismatch between weak
2275 // and non-weak references.
2276 else if ( strcmp(arg, "-weak_reference_mismatches") == 0 ) {
2277 setWeakReferenceMismatchTreatment(argv[++i]);
2278 }
2279 // For a deployment target of 10.3 and earlier ld64 will
2280 // prebind an executable with 0s in all addresses that
2281 // are prebound. This can then be fixed up by update_prebinding
2282 // later. Prebinding is less useful on 10.4 and greater.
2283 else if ( strcmp(arg, "-prebind") == 0 ) {
2284 fPrebind = true;
2285 }
2286 else if ( strcmp(arg, "-noprebind") == 0 ) {
2287 warnObsolete(arg);
2288 fPrebind = false;
2289 }
2290 else if ( strcmp(arg, "-prebind_allow_overlap") == 0 ) {
2291 warnObsolete(arg);
2292 }
2293 else if ( strcmp(arg, "-prebind_all_twolevel_modules") == 0 ) {
2294 warnObsolete(arg);
2295 }
2296 else if ( strcmp(arg, "-noprebind_all_twolevel_modules") == 0 ) {
2297 warnObsolete(arg);
2298 }
2299 else if ( strcmp(arg, "-nofixprebinding") == 0 ) {
2300 warnObsolete(arg);
2301 }
2302 // This should probably be deprecated when we respect -L and -F
2303 // when searching for libraries.
2304 else if ( strcmp(arg, "-dylib_file") == 0 ) {
2305 // ignore for snapshot because a stub dylib will be created in the snapshot
2306 snapshotArgCount = 0;
2307 addDylibOverride(argv[++i]);
2308 }
2309 // What to expand @executable_path to if found in dependent dylibs
2310 else if ( strcmp(arg, "-executable_path") == 0 ) {
2311 fExecutablePath = argv[++i];
2312 if ( (fExecutablePath == NULL) || (fExecutablePath[0] == '-') )
2313 throw "-executable_path missing <path>";
2314 // if a directory was passed, add / to end
2315 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2316 struct stat statBuffer;
2317 if ( stat(fExecutablePath, &statBuffer) == 0 ) {
2318 if ( (statBuffer.st_mode & S_IFMT) == S_IFDIR ) {
2319 char* pathWithSlash = new char[strlen(fExecutablePath)+2];
2320 strcpy(pathWithSlash, fExecutablePath);
2321 strcat(pathWithSlash, "/");
2322 fExecutablePath = pathWithSlash;
2323 }
2324 }
2325 }
2326 // Aligns all segments to the power of 2 boundary specified.
2327 else if ( strcmp(arg, "-segalign") == 0 ) {
2328 const char* size = argv[++i];
2329 if ( size == NULL )
2330 throw "-segalign missing <size>";
2331 fSegmentAlignment = parseAddress(size);
2332 uint8_t alignment = (uint8_t)__builtin_ctz(fSegmentAlignment);
2333 uint32_t p2aligned = (1 << alignment);
2334 if ( p2aligned != fSegmentAlignment ) {
2335 warning("alignment for -segalign %s is not a power of two, using 0x%X", size, p2aligned);
2336 fSegmentAlignment = p2aligned;
2337 }
2338 }
2339 // Puts a specified segment at a particular address that must
2340 // be a multiple of the segment alignment.
2341 else if ( strcmp(arg, "-segaddr") == 0 ) {
2342 SegmentStart seg;
2343 seg.name = argv[++i];
2344 if ( (seg.name == NULL) || (argv[i+1] == NULL) )
2345 throw "-segaddr missing segName Adddress";
2346 seg.address = parseAddress(argv[++i]);
2347 uint64_t temp = ((seg.address+fSegmentAlignment-1) & (-fSegmentAlignment));
2348 if ( seg.address != temp )
2349 warning("-segaddr %s not %lld byte aligned", seg.name, fSegmentAlignment);
2350 fCustomSegmentAddresses.push_back(seg);
2351 }
2352 // ??? Deprecate when we deprecate split-seg.
2353 else if ( strcmp(arg, "-segs_read_only_addr") == 0 ) {
2354 fBaseAddress = parseAddress(argv[++i]);
2355 }
2356 // ??? Deprecate when we deprecate split-seg.
2357 else if ( strcmp(arg, "-segs_read_write_addr") == 0 ) {
2358 fBaseWritableAddress = parseAddress(argv[++i]);
2359 fSplitSegs = true;
2360 }
2361 // ??? Deprecate when we get rid of basing at build time.
2362 else if ( strcmp(arg, "-seg_addr_table") == 0 ) {
2363 snapshotFileArgIndex = 1;
2364 const char* name = argv[++i];
2365 if ( name == NULL )
2366 throw "-seg_addr_table missing argument";
2367 fSegAddrTablePath = name;
2368 }
2369 else if ( strcmp(arg, "-seg_addr_table_filename") == 0 ) {
2370 warnObsolete(arg);
2371 ++i;
2372 }
2373 else if ( strcmp(arg, "-segprot") == 0 ) {
2374 SegmentProtect seg;
2375 seg.name = argv[++i];
2376 if ( (seg.name == NULL) || (argv[i+1] == NULL) || (argv[i+2] == NULL) )
2377 throw "-segprot missing segName max-prot init-prot";
2378 seg.max = parseProtection(argv[++i]);
2379 seg.init = parseProtection(argv[++i]);
2380 fCustomSegmentProtections.push_back(seg);
2381 }
2382 else if ( strcmp(arg, "-pagezero_size") == 0 ) {
2383 const char* size = argv[++i];
2384 if ( size == NULL )
2385 throw "-pagezero_size missing <size>";
2386 fZeroPageSize = parseAddress(size);
2387 uint64_t temp = fZeroPageSize & (-4096); // page align
2388 if ( (fZeroPageSize != temp) )
2389 warning("-pagezero_size not page aligned, rounding down");
2390 fZeroPageSize = temp;
2391 }
2392 else if ( strcmp(arg, "-stack_addr") == 0 ) {
2393 const char* address = argv[++i];
2394 if ( address == NULL )
2395 throw "-stack_addr missing <address>";
2396 fStackAddr = parseAddress(address);
2397 }
2398 else if ( strcmp(arg, "-stack_size") == 0 ) {
2399 const char* size = argv[++i];
2400 if ( size == NULL )
2401 throw "-stack_size missing <address>";
2402 fStackSize = parseAddress(size);
2403 uint64_t temp = fStackSize & (-4096); // page align
2404 if ( (fStackSize != temp) )
2405 warning("-stack_size not page aligned, rounding down");
2406 }
2407 else if ( strcmp(arg, "-allow_stack_execute") == 0 ) {
2408 fExecutableStack = true;
2409 }
2410 else if ( strcmp(arg, "-allow_heap_execute") == 0 ) {
2411 fDisableNonExecutableHeap = true;
2412 }
2413 else if ( strcmp(arg, "-sectalign") == 0 ) {
2414 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
2415 throw "-sectalign missing <segment> <section> <file-path>";
2416 addSectionAlignment(argv[i+1], argv[i+2], argv[i+3]);
2417 i += 3;
2418 }
2419 else if ( strcmp(arg, "-sectorder_detail") == 0 ) {
2420 warnObsolete(arg);
2421 }
2422 else if ( strcmp(arg, "-sectobjectsymbols") == 0 ) {
2423 warnObsolete(arg);
2424 i += 2;
2425 }
2426 else if ( strcmp(arg, "-bundle_loader") == 0 ) {
2427 snapshotFileArgIndex = 1;
2428 fBundleLoader = argv[++i];
2429 if ( (fBundleLoader == NULL) || (fBundleLoader[0] == '-') )
2430 throw "-bundle_loader missing <path>";
2431 FileInfo info = findFile(fBundleLoader);
2432 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2433 info.options.fBundleLoader = true;
2434 fInputFiles.push_back(info);
2435 }
2436 else if ( strcmp(arg, "-private_bundle") == 0 ) {
2437 warnObsolete(arg);
2438 }
2439 else if ( strcmp(arg, "-twolevel_namespace_hints") == 0 ) {
2440 // FIX FIX
2441 }
2442 // Use this flag to set default behavior for deployement targets.
2443 else if ( strcmp(arg, "-macosx_version_min") == 0 ) {
2444 const char* macVers = argv[++i];
2445 const char* envMacVers = getenv("MACOSX_DEPLOYMENT_TARGET");
2446 const char* enviPhoneVers = getenv("IPHONEOS_DEPLOYMENT_TARGET");
2447 if ( (envMacVers != NULL) && (enviPhoneVers != NULL) ) {
2448 // <rdar://problem/13774329> when conflicting deployments set, break tie by looking at syslibroot
2449 warning("both MACOSX_DEPLOYMENT_TARGET and IPHONEOS_DEPLOYMENT_TARGET are set");
2450 if ( !fSDKPaths.empty() ) {
2451 const char* sysrootPath = fSDKPaths.back();
2452 const char* lastSlash = strrchr(sysrootPath, '/');
2453 if ( strstr(lastSlash, "Simulator") != NULL )
2454 setIOSVersionMin(enviPhoneVers);
2455 else
2456 setMacOSXVersionMin(macVers);
2457 }
2458 else {
2459 setMacOSXVersionMin(macVers);
2460 }
2461 }
2462 else {
2463 setMacOSXVersionMin(macVers);
2464 }
2465 }
2466 else if ( (strcmp(arg, "-ios_version_min") == 0) || (strcmp(arg, "-iphoneos_version_min") == 0) ) {
2467 setIOSVersionMin(argv[++i]);
2468 }
2469 else if ( strcmp(arg, "-ios_simulator_version_min") == 0 ) {
2470 setIOSVersionMin(argv[++i]);
2471 fTargetIOSSimulator = true;
2472 }
2473 else if ( strcmp(arg, "-multiply_defined") == 0 ) {
2474 //warnObsolete(arg);
2475 ++i;
2476 }
2477 else if ( strcmp(arg, "-multiply_defined_unused") == 0 ) {
2478 warnObsolete(arg);
2479 ++i;
2480 }
2481 else if ( strcmp(arg, "-nomultidefs") == 0 ) {
2482 warnObsolete(arg);
2483 }
2484 // Display each file in which the argument symbol appears and whether
2485 // the file defines or references it. This option takes an argument
2486 // as -y<symbol> note that there is no space.
2487 else if ( strncmp(arg, "-y", 2) == 0 ) {
2488 warnObsolete("-y");
2489 }
2490 // Same output as -y, but output <arg> number of undefined symbols only.
2491 else if ( strcmp(arg, "-Y") == 0 ) {
2492 //warnObsolete(arg);
2493 ++i;
2494 }
2495 // This option affects all objects linked into the final result.
2496 else if ( strcmp(arg, "-m") == 0 ) {
2497 warnObsolete(arg);
2498 }
2499 else if ( (strcmp(arg, "-why_load") == 0) || (strcmp(arg, "-whyload") == 0) ) {
2500 fWhyLoad = true;
2501 }
2502 else if ( strcmp(arg, "-why_live") == 0 ) {
2503 const char* name = argv[++i];
2504 if ( name == NULL )
2505 throw "-why_live missing symbol name argument";
2506 fWhyLive.insert(name);
2507 }
2508 else if ( strcmp(arg, "-u") == 0 ) {
2509 const char* name = argv[++i];
2510 if ( name == NULL )
2511 throw "-u missing argument";
2512 fInitialUndefines.push_back(name);
2513 }
2514 else if ( strcmp(arg, "-U") == 0 ) {
2515 const char* name = argv[++i];
2516 if ( name == NULL )
2517 throw "-U missing argument";
2518 fAllowedUndefined.insert(name);
2519 }
2520 else if ( strcmp(arg, "-s") == 0 ) {
2521 warnObsolete(arg);
2522 fLocalSymbolHandling = kLocalSymbolsNone;
2523 fDebugInfoStripping = Options::kDebugInfoNone;
2524 }
2525 else if ( strcmp(arg, "-x") == 0 ) {
2526 fLocalSymbolHandling = kLocalSymbolsNone;
2527 }
2528 else if ( strcmp(arg, "-S") == 0 ) {
2529 fDebugInfoStripping = Options::kDebugInfoNone;
2530 }
2531 else if ( strcmp(arg, "-X") == 0 ) {
2532 warnObsolete(arg);
2533 }
2534 else if ( strcmp(arg, "-Si") == 0 ) {
2535 warnObsolete(arg);
2536 fDebugInfoStripping = Options::kDebugInfoFull;
2537 }
2538 else if ( strcmp(arg, "-b") == 0 ) {
2539 warnObsolete(arg);
2540 }
2541 else if ( strcmp(arg, "-Sn") == 0 ) {
2542 warnObsolete(arg);
2543 fDebugInfoStripping = Options::kDebugInfoFull;
2544 }
2545 else if ( strcmp(arg, "-Sp") == 0 ) {
2546 warnObsolete(arg);
2547 }
2548 else if ( strcmp(arg, "-dead_strip") == 0 ) {
2549 fDeadStrip = true;
2550 }
2551 else if ( strcmp(arg, "-no_dead_strip_inits_and_terms") == 0 ) {
2552 fDeadStrip = true;
2553 }
2554 else if ( strcmp(arg, "-w") == 0 ) {
2555 // previously handled by buildSearchPaths()
2556 }
2557 else if ( strcmp(arg, "-fatal_warnings") == 0 ) {
2558 // previously handled by buildSearchPaths()
2559 }
2560 else if ( strcmp(arg, "-arch_errors_fatal") == 0 ) {
2561 fErrorOnOtherArchFiles = true;
2562 }
2563 else if ( strcmp(arg, "-M") == 0 ) {
2564 // FIX FIX
2565 }
2566 else if ( strcmp(arg, "-headerpad") == 0 ) {
2567 const char* size = argv[++i];
2568 if ( size == NULL )
2569 throw "-headerpad missing argument";
2570 fMinimumHeaderPad = parseAddress(size);
2571 }
2572 else if ( strcmp(arg, "-headerpad_max_install_names") == 0 ) {
2573 fMaxMinimumHeaderPad = true;
2574 }
2575 else if ( strcmp(arg, "-t") == 0 ) {
2576 fLogAllFiles = true;
2577 }
2578 else if ( strcmp(arg, "-whatsloaded") == 0 ) {
2579 fLogObjectFiles = true;
2580 }
2581 else if ( strcmp(arg, "-A") == 0 ) {
2582 warnObsolete(arg);
2583 ++i;
2584 }
2585 else if ( strcmp(arg, "-umbrella") == 0 ) {
2586 const char* name = argv[++i];
2587 if ( name == NULL )
2588 throw "-umbrella missing argument";
2589 fUmbrellaName = name;
2590 }
2591 else if ( strcmp(arg, "-allowable_client") == 0 ) {
2592 const char* name = argv[++i];
2593
2594 if ( name == NULL )
2595 throw "-allowable_client missing argument";
2596
2597 fAllowableClients.push_back(name);
2598 }
2599 else if ( strcmp(arg, "-client_name") == 0 ) {
2600 const char* name = argv[++i];
2601
2602 if ( name == NULL )
2603 throw "-client_name missing argument";
2604
2605 fClientName = name;
2606 }
2607 else if ( strcmp(arg, "-sub_umbrella") == 0 ) {
2608 const char* name = argv[++i];
2609 if ( name == NULL )
2610 throw "-sub_umbrella missing argument";
2611 fSubUmbellas.push_back(name);
2612 }
2613 else if ( strcmp(arg, "-sub_library") == 0 ) {
2614 const char* name = argv[++i];
2615 if ( name == NULL )
2616 throw "-sub_library missing argument";
2617 fSubLibraries.push_back(name);
2618 }
2619 else if ( strcmp(arg, "-init") == 0 ) {
2620 const char* name = argv[++i];
2621 if ( name == NULL )
2622 throw "-init missing argument";
2623 fInitFunctionName = name;
2624 }
2625 else if ( strcmp(arg, "-dot") == 0 ) {
2626 const char* name = argv[++i];
2627 if ( name == NULL )
2628 throw "-dot missing argument";
2629 fDotOutputFile = name;
2630 }
2631 else if ( strcmp(arg, "-warn_commons") == 0 ) {
2632 fWarnCommons = true;
2633 }
2634 else if ( strcmp(arg, "-commons") == 0 ) {
2635 fCommonsMode = parseCommonsTreatment(argv[++i]);
2636 }
2637 else if ( strcmp(arg, "-keep_relocs") == 0 ) {
2638 fKeepRelocations = true;
2639 }
2640 else if ( strcmp(arg, "-warn_stabs") == 0 ) {
2641 fWarnStabs = true;
2642 }
2643 else if ( strcmp(arg, "-pause") == 0 ) {
2644 fPause = true;
2645 }
2646 else if ( strcmp(arg, "-print_statistics") == 0 ) {
2647 fStatistics = true;
2648 }
2649 else if ( strcmp(arg, "-d") == 0 ) {
2650 fMakeTentativeDefinitionsReal = true;
2651 }
2652 else if ( strcmp(arg, "-v") == 0 ) {
2653 // previously handled by buildSearchPaths()
2654 }
2655 else if ( strcmp(arg, "-Z") == 0 ) {
2656 // previously handled by buildSearchPaths()
2657 }
2658 else if ( strcmp(arg, "-syslibroot") == 0 ) {
2659 snapshotArgCount = 0;
2660 ++i;
2661 // previously handled by buildSearchPaths()
2662 }
2663 else if ( strcmp(arg, "-no_uuid") == 0 ) {
2664 fUUIDMode = kUUIDNone;
2665 }
2666 else if ( strcmp(arg, "-random_uuid") == 0 ) {
2667 fUUIDMode = kUUIDRandom;
2668 }
2669 else if ( strcmp(arg, "-dtrace") == 0 ) {
2670 snapshotFileArgIndex = 1;
2671 const char* name = argv[++i];
2672 if ( name == NULL )
2673 throw "-dtrace missing argument";
2674 fDtraceScriptName = name;
2675 }
2676 else if ( strcmp(arg, "-root_safe") == 0 ) {
2677 fRootSafe = true;
2678 }
2679 else if ( strcmp(arg, "-setuid_safe") == 0 ) {
2680 fSetuidSafe = true;
2681 }
2682 else if ( strcmp(arg, "-alias") == 0 ) {
2683 Options::AliasPair pair;
2684 pair.realName = argv[++i];
2685 if ( pair.realName == NULL )
2686 throw "missing argument to -alias";
2687 pair.alias = argv[++i];
2688 if ( pair.alias == NULL )
2689 throw "missing argument to -alias";
2690 fAliases.push_back(pair);
2691 }
2692 else if ( strcmp(arg, "-alias_list") == 0 ) {
2693 snapshotFileArgIndex = 1;
2694 parseAliasFile(argv[++i]);
2695 }
2696 else if ( strcmp(arg, "-save-temps") == 0 ) {
2697 fSaveTempFiles = true;
2698 }
2699 else if ( strcmp(arg, "-rpath") == 0 ) {
2700 const char* path = argv[++i];
2701 if ( path == NULL )
2702 throw "missing argument to -rpath";
2703 fRPaths.push_back(path);
2704 }
2705 else if ( strcmp(arg, "-read_only_stubs") == 0 ) {
2706 fReadOnlyx86Stubs = true;
2707 }
2708 else if ( strcmp(arg, "-slow_stubs") == 0 ) {
2709 warnObsolete(arg);
2710 }
2711 else if ( strcmp(arg, "-map") == 0 ) {
2712 fMapPath = argv[++i];
2713 if ( fMapPath == NULL )
2714 throw "missing argument to -map";
2715 }
2716 else if ( strcmp(arg, "-pie") == 0 ) {
2717 fPositionIndependentExecutable = true;
2718 fPIEOnCommandLine = true;
2719 }
2720 else if ( strcmp(arg, "-no_pie") == 0 ) {
2721 fDisablePositionIndependentExecutable = true;
2722 }
2723 else if ( strncmp(arg, "-reexport-l", 11) == 0 ) {
2724 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2725 snapshotArgCount = 0;
2726 FileInfo info = findLibrary(&arg[11], true);
2727 info.options.fReExport = true;
2728 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2729 addLibrary(info);
2730 }
2731 else if ( strcmp(arg, "-reexport_library") == 0 ) {
2732 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2733 snapshotArgCount = 0;
2734 FileInfo info = findFile(argv[++i]);
2735 info.options.fReExport = true;
2736 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2737 addLibrary(info);
2738 }
2739 else if ( strcmp(arg, "-reexport_framework") == 0 ) {
2740 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2741 snapshotArgCount = 0;
2742 FileInfo info = findFramework(argv[++i]);
2743 info.options.fReExport = true;
2744 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2745 addLibrary(info);
2746 }
2747 else if ( strncmp(arg, "-upward-l", 9) == 0 ) {
2748 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2749 snapshotArgCount = 0;
2750 FileInfo info = findLibrary(&arg[9], true);
2751 info.options.fUpward = true;
2752 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2753 addLibrary(info);
2754 }
2755 else if ( strcmp(arg, "-upward_library") == 0 ) {
2756 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2757 snapshotArgCount = 0;
2758 FileInfo info = findFile(argv[++i]);
2759 info.options.fUpward = true;
2760 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2761 addLibrary(info);
2762 }
2763 else if ( strcmp(arg, "-upward_framework") == 0 ) {
2764 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2765 snapshotArgCount = 0;
2766 FileInfo info = findFramework(argv[++i]);
2767 info.options.fUpward = true;
2768 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2769 addLibrary(info);
2770 }
2771 else if ( strcmp(arg, "-dead_strip_dylibs") == 0 ) {
2772 fDeadStripDylibs = true;
2773 }
2774 else if ( strcmp(arg, "-no_implicit_dylibs") == 0 ) {
2775 fImplicitlyLinkPublicDylibs = false;
2776 }
2777 else if ( strcmp(arg, "-new_linker") == 0 ) {
2778 // ignore
2779 }
2780 else if ( strcmp(arg, "-no_encryption") == 0 ) {
2781 fEncryptable = false;
2782 }
2783 else if ( strcmp(arg, "-no_compact_unwind") == 0 ) {
2784 fAddCompactUnwindEncoding = false;
2785 }
2786 else if ( strcmp(arg, "-mllvm") == 0 ) {
2787 const char* opts = argv[++i];
2788 if ( opts == NULL )
2789 throw "missing argument to -mllvm";
2790 fLLVMOptions.push_back(opts);
2791 }
2792 else if ( strcmp(arg, "-mcpu") == 0 ) {
2793 const char* cpu = argv[++i];
2794 if ( cpu == NULL )
2795 throw "missing argument to -mcpu";
2796 fLtoCpu = cpu;
2797 }
2798 else if ( strcmp(arg, "-no_order_inits") == 0 ) {
2799 fAutoOrderInitializers = false;
2800 }
2801 else if ( strcmp(arg, "-no_order_data") == 0 ) {
2802 fOrderData = false;
2803 }
2804 else if ( strcmp(arg, "-seg_page_size") == 0 ) {
2805 SegmentSize seg;
2806 seg.name = argv[++i];
2807 if ( (seg.name == NULL) || (argv[i+1] == NULL) )
2808 throw "-seg_page_size missing segName Adddress";
2809 seg.size = parseAddress(argv[++i]);
2810 uint64_t temp = seg.size & (-4096); // page align
2811 if ( (seg.size != temp) )
2812 warning("-seg_page_size %s not 4K aligned, rounding down", seg.name);
2813 fCustomSegmentSizes.push_back(seg);
2814 }
2815 else if ( strcmp(arg, "-mark_dead_strippable_dylib") == 0 ) {
2816 fMarkDeadStrippableDylib = true;
2817 }
2818 else if ( strcmp(arg, "-exported_symbols_order") == 0 ) {
2819 snapshotFileArgIndex = 1;
2820 loadSymbolOrderFile(argv[++i], fExportSymbolsOrder);
2821 }
2822 else if ( strcmp(arg, "-no_compact_linkedit") == 0 ) {
2823 warnObsolete("-no_compact_linkedit");
2824 }
2825 else if ( strcmp(arg, "-no_eh_labels") == 0 ) {
2826 fNoEHLabels = true;
2827 }
2828 else if ( strcmp(arg, "-warn_compact_unwind") == 0 ) {
2829 fWarnCompactUnwind = true;
2830 }
2831 else if ( strcmp(arg, "-allow_sub_type_mismatches") == 0 ) {
2832 fAllowCpuSubtypeMismatches = true;
2833 }
2834 else if ( strcmp(arg, "-no_zero_fill_sections") == 0 ) {
2835 fOptimizeZeroFill = false;
2836 }
2837 else if ( strcmp(arg, "-merge_zero_fill_sections") == 0 ) {
2838 fMergeZeroFill = true;
2839 }
2840 else if ( strcmp(arg, "-objc_abi_version") == 0 ) {
2841 const char* version = argv[++i];
2842 if ( version == NULL )
2843 throw "-objc_abi_version missing version number";
2844 if ( strcmp(version, "2") == 0 ) {
2845 fObjCABIVersion1Override = false;
2846 fObjCABIVersion2Override = true;
2847 }
2848 else if ( strcmp(version, "1") == 0 ) {
2849 fObjCABIVersion1Override = true;
2850 fObjCABIVersion2Override = false;
2851 }
2852 else
2853 warning("ignoring unrecognized argument (%s) to -objc_abi_version", version);
2854 }
2855 else if ( strcmp(arg, "-warn_weak_exports") == 0 ) {
2856 fWarnWeakExports = true;
2857 }
2858 else if ( strcmp(arg, "-objc_gc_compaction") == 0 ) {
2859 fObjcGcCompaction = true;
2860 }
2861 else if ( strcmp(arg, "-objc_gc") == 0 ) {
2862 fObjCGc = true;
2863 if ( fObjCGcOnly ) {
2864 warning("-objc_gc overriding -objc_gc_only");
2865 fObjCGcOnly = false;
2866 }
2867 }
2868 else if ( strcmp(arg, "-objc_gc_only") == 0 ) {
2869 fObjCGcOnly = true;
2870 if ( fObjCGc ) {
2871 warning("-objc_gc_only overriding -objc_gc");
2872 fObjCGc = false;
2873 }
2874 }
2875 else if ( strcmp(arg, "-demangle") == 0 ) {
2876 fDemangle = true;
2877 }
2878 else if ( strcmp(arg, "-version_load_command") == 0 ) {
2879 fVersionLoadCommandForcedOn = true;
2880 fVersionLoadCommandForcedOff = false;
2881 }
2882 else if ( strcmp(arg, "-no_version_load_command") == 0 ) {
2883 fVersionLoadCommandForcedOff = true;
2884 fVersionLoadCommandForcedOn = false;
2885 }
2886 else if ( strcmp(arg, "-function_starts") == 0 ) {
2887 fFunctionStartsForcedOn = true;
2888 fFunctionStartsForcedOff = false;
2889 }
2890 else if ( strcmp(arg, "-no_function_starts") == 0 ) {
2891 fFunctionStartsForcedOff = true;
2892 fFunctionStartsForcedOn = false;
2893 }
2894 else if ( strcmp(arg, "-no_data_in_code_info") == 0 ) {
2895 fDataInCodeInfoLoadCommandForcedOff = true;
2896 fDataInCodeInfoLoadCommandForcedOn = false;
2897 }
2898 else if ( strcmp(arg, "-data_in_code_info") == 0 ) {
2899 fDataInCodeInfoLoadCommandForcedOn = true;
2900 fDataInCodeInfoLoadCommandForcedOff = false;
2901 }
2902 else if ( strcmp(arg, "-object_path_lto") == 0 ) {
2903 fTempLtoObjectPath = argv[++i];
2904 if ( fTempLtoObjectPath == NULL )
2905 throw "missing argument to -object_path_lto";
2906 }
2907 else if ( strcmp(arg, "-no_objc_category_merging") == 0 ) {
2908 fObjcCategoryMerging = false;
2909 }
2910 else if ( strcmp(arg, "-force_symbols_weak_list") == 0 ) {
2911 snapshotFileArgIndex = 1;
2912 loadExportFile(argv[++i], "-force_symbols_weak_list", fForceWeakSymbols);
2913 }
2914 else if ( strcmp(arg, "-force_symbols_not_weak_list") == 0 ) {
2915 snapshotFileArgIndex = 1;
2916 loadExportFile(argv[++i], "-force_symbols_not_weak_list", fForceNotWeakSymbols);
2917 }
2918 else if ( strcmp(arg, "-force_symbol_weak") == 0 ) {
2919 const char* symbol = argv[++i];
2920 if ( symbol == NULL )
2921 throw "-force_symbol_weak missing <symbol>";
2922 fForceWeakSymbols.insert(symbol);
2923 }
2924 else if ( strcmp(arg, "-force_symbol_not_weak") == 0 ) {
2925 const char* symbol = argv[++i];
2926 if ( symbol == NULL )
2927 throw "-force_symbol_not_weak missing <symbol>";
2928 fForceNotWeakSymbols.insert(symbol);
2929 }
2930 else if ( strcmp(arg, "-reexported_symbols_list") == 0 ) {
2931 snapshotFileArgIndex = 1;
2932 if ( fExportMode == kExportSome )
2933 throw "can't use -exported_symbols_list and -reexported_symbols_list";
2934 loadExportFile(argv[++i], "-reexported_symbols_list", fReExportSymbols);
2935 }
2936 else if ( strcmp(arg, "-dyld_env") == 0 ) {
2937 const char* envarg = argv[++i];
2938 if ( envarg == NULL )
2939 throw "-dyld_env missing ENV=VALUE";
2940 if ( strchr(envarg, '=') == NULL )
2941 throw "-dyld_env missing ENV=VALUE";
2942 fDyldEnvironExtras.push_back(envarg);
2943 }
2944 else if ( strcmp(arg, "-page_align_data_atoms") == 0 ) {
2945 fPageAlignDataAtoms = true;
2946 }
2947 else if (strcmp(arg, "-debug_snapshot") == 0) {
2948 fLinkSnapshot.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG);
2949 fSnapshotRequested = true;
2950 }
2951 else if (strcmp(arg, "-snapshot_dir") == 0) {
2952 const char* path = argv[++i];
2953 if ( path == NULL )
2954 throw "-snapshot_dir missing path";
2955 fLinkSnapshot.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG);
2956 fLinkSnapshot.setSnapshotPath(path);
2957 fSnapshotRequested = true;
2958 }
2959 else if ( strcmp(arg, "-new_main") == 0 ) {
2960 fEntryPointLoadCommandForceOn = true;
2961 }
2962 else if ( strcmp(arg, "-no_new_main") == 0 ) {
2963 fEntryPointLoadCommandForceOff = true;
2964 }
2965 else if ( strcmp(arg, "-source_version") == 0 ) {
2966 const char* vers = argv[++i];
2967 if ( vers == NULL )
2968 throw "-source_version missing <version>";
2969 fSourceVersion = parseVersionNumber64(vers);
2970 }
2971 else if ( strcmp(arg, "-add_source_version") == 0 ) {
2972 fSourceVersionLoadCommandForceOn = true;
2973 }
2974 else if ( strcmp(arg, "-no_source_version") == 0 ) {
2975 fSourceVersionLoadCommandForceOff = true;
2976 }
2977 else if ( strcmp(arg, "-sdk_version") == 0 ) {
2978 const char* vers = argv[++i];
2979 if ( vers == NULL )
2980 throw "-sdk_version missing <version>";
2981 fSDKVersion = parseVersionNumber32(vers);
2982 }
2983 else if ( strcmp(arg, "-dependent_dr_info") == 0 ) {
2984 fDependentDRInfoForcedOn = true;
2985 }
2986 else if ( strcmp(arg, "-no_dependent_dr_info") == 0 ) {
2987 fDependentDRInfoForcedOff = true;
2988 }
2989 else if ( strcmp(arg, "-kexts_use_stubs") == 0 ) {
2990 fKextsUseStubs = true;
2991 }
2992 else if ( strcmp(argv[i], "-dependency_info") == 0 ) {
2993 snapshotArgCount = 0;
2994 ++i;
2995 // previously handled by buildSearchPaths()
2996 }
2997 else if ( strcmp(arg, "-export_dynamic") == 0 ) {
2998 fExportDynamic = true;
2999 }
3000 else if ( strcmp(arg, "-force_symbols_coalesce_list") == 0 ) {
3001 snapshotFileArgIndex = 1;
3002 loadExportFile(argv[++i], "-force_symbols_coalesce_list", fForceCoalesceSymbols);
3003 }
3004 else if ( strcmp(arg, "-add_linker_option") == 0 ) {
3005 // ex: -add_linker_option '-framework Foundation'
3006 const char* optString = argv[++i];
3007 if ( optString == NULL )
3008 throw "-add_linker_option missing <option>";
3009 // break up into list of tokens at whitespace
3010 std::vector<const char*> opts;
3011 char* buffer = strdup(optString);
3012 char* start = buffer;
3013 for (char* s = buffer; ; ++s) {
3014 if ( isspace(*s) ) {
3015 *s = '\0';
3016 opts.push_back(start);
3017 start = s+1;
3018 }
3019 else if ( *s == '\0' ) {
3020 opts.push_back(start);
3021 break;
3022 }
3023 }
3024 fLinkerOptions.push_back(opts);
3025 }
3026 else if ( strcmp(arg, "-allow_simulator_linking_to_macosx_dylibs") == 0 ) {
3027 fAllowSimulatorToLinkWithMacOSX = true;
3028 }
3029 else if ( strcmp(arg, "-keep_dwarf_unwind") == 0 ) {
3030 fKeepDwarfUnwindForcedOn = true;
3031 fKeepDwarfUnwindForcedOff = false;
3032 }
3033 else if ( strcmp(arg, "-no_keep_dwarf_unwind") == 0 ) {
3034 fKeepDwarfUnwindForcedOn = false;
3035 fKeepDwarfUnwindForcedOff = true;
3036 }
3037 else if ( strcmp(arg, "-verbose_optimization_hints") == 0 ) {
3038 fVerboseOptimizationHints = true;
3039 }
3040 else if ( strcmp(arg, "-ignore_optimization_hints") == 0 ) {
3041 fIgnoreOptimizationHints = true;
3042 }
3043 else if ( strcmp(arg, "-no_dtrace_dof") == 0 ) {
3044 fGenerateDtraceDOF = false;
3045 }
3046 else if ( strcmp(arg, "-rename_section") == 0 ) {
3047 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) || (argv[i+4]==NULL) )
3048 throw "-rename_section missing <segment> <section> <segment> <section>";
3049 addSectionRename(argv[i+1], argv[i+2], argv[i+3], argv[i+4]);
3050 i += 4;
3051 }
3052 else if ( strcmp(arg, "-rename_segment") == 0 ) {
3053 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) )
3054 throw "-rename_segment missing <existing-segment> <new-segment>";
3055 addSegmentRename(argv[i+1], argv[i+2]);
3056 i += 2;
3057 }
3058 else if ( strcmp(arg, "-move_to_ro_segment") == 0 ) {
3059 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) )
3060 throw "-move_to_ro_segment missing <segment> <symbol-list-file>";
3061 addSymbolMove(argv[i+1], argv[i+2], fSymbolsMovesCode, "-move_to_ro_segment");
3062 i += 2;
3063 }
3064 else if ( strcmp(arg, "-move_to_rw_segment") == 0 ) {
3065 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) )
3066 throw "-move_to_rw_segment missing <segment> <symbol-list-file>";
3067 addSymbolMove(argv[i+1], argv[i+2], fSymbolsMovesData, "-move_to_rw_segment");
3068 i += 2;
3069 }
3070 else if ( strcmp(arg, "-trace_symbol_layout") == 0 ) {
3071 fTraceSymbolLayout = true;
3072 }
3073 else if ( strcmp(arg, "-no_branch_islands") == 0 ) {
3074 fAllowBranchIslands = false;
3075 }
3076 else if ( strcmp(arg, "-segment_order") == 0 ) {
3077 // ex: -segment_order __TEXT:__DATA:__JUNK
3078 const char* optString = argv[++i];
3079 if ( optString == NULL )
3080 throw "-segment_order missing colon separated <segment-list>";
3081 if ( !fSegmentOrder.empty() )
3082 throw "-segment_order used more than once";
3083 // break up into list of tokens at colon
3084 char* buffer = strdup(optString);
3085 char* start = buffer;
3086 for (char* s = buffer; ; ++s) {
3087 if ( *s == ':' ) {
3088 *s = '\0';
3089 fSegmentOrder.push_back(start);
3090 start = s+1;
3091 }
3092 else if ( *s == '\0' ) {
3093 fSegmentOrder.push_back(start);
3094 break;
3095 }
3096 }
3097 }
3098 else if ( strcmp(arg, "-section_order") == 0 ) {
3099 // ex: -section_order __DATA __data:__const:__nl_pointers
3100 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) )
3101 throw "-section_order missing <segment> <section-list>";
3102 const char* segName = argv[++i];
3103 const char* optString = argv[++i];
3104 if ( sectionOrder(segName) != NULL )
3105 throwf("-section_order %s ... used more than once", segName);
3106 SectionOrderList dummy;
3107 fSectionOrder.push_back(dummy);
3108 SectionOrderList& entry = fSectionOrder.back();
3109 entry.segmentName = segName;
3110 // break up into list of tokens at colon
3111 char* buffer = strdup(optString);
3112 char* start = buffer;
3113 for (char* s = buffer; ; ++s) {
3114 if ( *s == ':' ) {
3115 *s = '\0';
3116 entry.sectionOrder.push_back(start);
3117 start = s+1;
3118 }
3119 else if ( *s == '\0' ) {
3120 entry.sectionOrder.push_back(start);
3121 break;
3122 }
3123 }
3124 }
3125 else if ( strcmp(arg, "-application_extension") == 0 ) {
3126 fMarkAppExtensionSafe = true;
3127 fCheckAppExtensionSafe = true;
3128 }
3129 else if ( strcmp(arg, "-no_application_extension") == 0 ) {
3130 fMarkAppExtensionSafe = false;
3131 fCheckAppExtensionSafe = false;
3132 }
3133 else if ( strcmp(arg, "-add_ast_path") == 0 ) {
3134 const char* path = argv[++i];
3135 if ( path == NULL )
3136 throw "-add_ast_path missing <option>";
3137 fASTFilePaths.push_back(path);
3138 }
3139 else if ( strcmp(arg, "-force_load_swift_libs") == 0 ) {
3140 fForceLoadSwiftLibs = true;
3141 }
3142 // put this last so that it does not interfer with other options starting with 'i'
3143 else if ( strncmp(arg, "-i", 2) == 0 ) {
3144 const char* colon = strchr(arg, ':');
3145 if ( colon == NULL )
3146 throwf("unknown option: %s", arg);
3147 Options::AliasPair pair;
3148 char* temp = new char[colon-arg];
3149 strlcpy(temp, &arg[2], colon-arg-1);
3150 pair.realName = &colon[1];
3151 pair.alias = temp;
3152 fAliases.push_back(pair);
3153 }
3154 else {
3155 throwf("unknown option: %s", arg);
3156 }
3157
3158 if (snapshotArgCount == -1)
3159 snapshotArgCount = i-snapshotArgIndex+1;
3160 if (snapshotArgCount > 0)
3161 fLinkSnapshot.addSnapshotLinkArg(snapshotArgIndex, snapshotArgCount, snapshotFileArgIndex);
3162 }
3163 else {
3164 FileInfo info = findFile(arg);
3165 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
3166 if ( strcmp(&info.path[strlen(info.path)-2], ".a") == 0 )
3167 addLibrary(info);
3168 else
3169 fInputFiles.push_back(info);
3170 }
3171 }
3172
3173 // if a -lazy option was used, implicitly link in lazydylib1.o
3174 if ( fUsingLazyDylibLinking ) {
3175 FileInfo info = findLibrary("lazydylib1.o");
3176 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)argc);
3177 addLibrary(info);
3178 }
3179
3180 if (fSnapshotRequested)
3181 fLinkSnapshot.createSnapshot();
3182 }
3183
3184
3185
3186 //
3187 // -syslibroot <path> is used for SDK support.
3188 // The rule is that all search paths (both explicit and default) are
3189 // checked to see if they exist in the SDK. If so, that path is
3190 // replaced with the sdk prefixed path. If not, that search path
3191 // is used as is. If multiple -syslibroot options are specified
3192 // their directory structures are logically overlayed and files
3193 // from sdks specified earlier on the command line used before later ones.
3194
3195 void Options::buildSearchPaths(int argc, const char* argv[])
3196 {
3197 bool addStandardLibraryDirectories = true;
3198 std::vector<const char*> libraryPaths;
3199 std::vector<const char*> frameworkPaths;
3200 libraryPaths.reserve(10);
3201 frameworkPaths.reserve(10);
3202 // scan through argv looking for -L, -F, -Z, and -syslibroot options
3203 for(int i=0; i < argc; ++i) {
3204 if ( (argv[i][0] == '-') && (argv[i][1] == 'L') ) {
3205 const char* libSearchDir = &argv[i][2];
3206 // Allow either "-L{path}" or "-L {path}".
3207 if (argv[i][2] == '\0') {
3208 // -L {path}. Make sure there is an argument following this.
3209 const char* path = argv[++i];
3210 if ( path == NULL )
3211 throw "-L missing argument";
3212 libSearchDir = path;
3213 }
3214 if ( libSearchDir[0] == '\0' )
3215 throw "-L must be immediately followed by a directory path (no space)";
3216 struct stat statbuf;
3217 if ( stat(libSearchDir, &statbuf) == 0 ) {
3218 if ( statbuf.st_mode & S_IFDIR )
3219 libraryPaths.push_back(libSearchDir);
3220 else
3221 warning("path '%s' following -L not a directory", libSearchDir);
3222 }
3223 else {
3224 warning("directory not found for option '-L%s'", libSearchDir);
3225 }
3226 }
3227 else if ( (argv[i][0] == '-') && (argv[i][1] == 'F') ) {
3228 const char* frameworkSearchDir = &argv[i][2];
3229 // Allow either "-F{path}" or "-F {path}".
3230 if (argv[i][2] == '\0') {
3231 // -F {path}. Make sure there is an argument following this.
3232 const char* path = argv[++i];
3233 if ( path == NULL )
3234 throw "-F missing argument";
3235 frameworkSearchDir = path;
3236 }
3237 if ( frameworkSearchDir[0] == '\0' )
3238 throw "-F must be immediately followed by a directory path (no space)";
3239 struct stat statbuf;
3240 if ( stat(frameworkSearchDir, &statbuf) == 0 ) {
3241 if ( statbuf.st_mode & S_IFDIR )
3242 frameworkPaths.push_back(frameworkSearchDir);
3243 else
3244 warning("path '%s' following -F not a directory", frameworkSearchDir);
3245 }
3246 else {
3247 warning("directory not found for option '-F%s'", frameworkSearchDir);
3248 }
3249 }
3250 else if ( strcmp(argv[i], "-Z") == 0 )
3251 addStandardLibraryDirectories = false;
3252 else if ( strcmp(argv[i], "-v") == 0 ) {
3253 fVerbose = true;
3254 extern const char ldVersionString[];
3255 fprintf(stderr, "%s", ldVersionString);
3256 fprintf(stderr, "configured to support archs: %s\n", ALL_SUPPORTED_ARCHS);
3257 // if only -v specified, exit cleanly
3258 if ( argc == 2 ) {
3259 const char* ltoVers = lto::version();
3260 if ( ltoVers != NULL )
3261 fprintf(stderr, "LTO support using: %s\n", ltoVers);
3262 exit(0);
3263 }
3264 }
3265 else if ( strcmp(argv[i], "-syslibroot") == 0 ) {
3266 const char* path = argv[++i];
3267 if ( path == NULL )
3268 throw "-syslibroot missing argument";
3269 fSDKPaths.push_back(path);
3270 }
3271 else if ( strcmp(argv[i], "-search_paths_first") == 0 ) {
3272 fLibrarySearchMode = kSearchDylibAndArchiveInEachDir;
3273 }
3274 else if ( strcmp(argv[i], "-search_dylibs_first") == 0 ) {
3275 fLibrarySearchMode = kSearchAllDirsForDylibsThenAllDirsForArchives;
3276 }
3277 else if ( strcmp(argv[i], "-w") == 0 ) {
3278 sEmitWarnings = false;
3279 }
3280 else if ( strcmp(argv[i], "-fatal_warnings") == 0 ) {
3281 sFatalWarnings = true;
3282 }
3283 else if ( strcmp(argv[i], "-dependency_info") == 0 ) {
3284 const char* path = argv[++i];
3285 if ( path == NULL )
3286 throw "-dependency_info missing <path>";
3287 fDependencyInfoPath = path;
3288 }
3289 }
3290 int standardLibraryPathsStartIndex = libraryPaths.size();
3291 int standardFrameworkPathsStartIndex = frameworkPaths.size();
3292 if ( addStandardLibraryDirectories ) {
3293 libraryPaths.push_back("/usr/lib");
3294 libraryPaths.push_back("/usr/local/lib");
3295
3296 frameworkPaths.push_back("/Library/Frameworks/");
3297 frameworkPaths.push_back("/System/Library/Frameworks/");
3298 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
3299 }
3300
3301 // <rdar://problem/5829579> Support for configure based hacks
3302 // if last -syslibroot is /, then ignore all syslibroots
3303 if ( fSDKPaths.size() > 0 ) {
3304 if ( strcmp(fSDKPaths.back(), "/") == 0 ) {
3305 fSDKPaths.clear();
3306 }
3307 }
3308
3309 // now merge sdk and library paths to make real search paths
3310 fLibrarySearchPaths.reserve(libraryPaths.size()*(fSDKPaths.size()+1));
3311 int libIndex = 0;
3312 for (std::vector<const char*>::iterator it = libraryPaths.begin(); it != libraryPaths.end(); ++it, ++libIndex) {
3313 const char* libDir = *it;
3314 bool sdkOverride = false;
3315 if ( libDir[0] == '/' ) {
3316 char betterLibDir[PATH_MAX];
3317 if ( strstr(libDir, "/..") != NULL ) {
3318 if ( realpath(libDir, betterLibDir) != NULL )
3319 libDir = strdup(betterLibDir);
3320 }
3321 const int libDirLen = strlen(libDir);
3322 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
3323 const char* sdkDir = *sdkit;
3324 const int sdkDirLen = strlen(sdkDir);
3325 char newPath[libDirLen + sdkDirLen+4];
3326 strcpy(newPath, sdkDir);
3327 if ( newPath[sdkDirLen-1] == '/' )
3328 newPath[sdkDirLen-1] = '\0';
3329 strcat(newPath, libDir);
3330 struct stat statBuffer;
3331 if ( stat(newPath, &statBuffer) == 0 ) {
3332 fLibrarySearchPaths.push_back(strdup(newPath));
3333 sdkOverride = true;
3334 }
3335 }
3336 }
3337 if ( !sdkOverride ) {
3338 if ( (libIndex >= standardLibraryPathsStartIndex) && (fSDKPaths.size() == 1) ) {
3339 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
3340 // if one SDK is specified and a standard library path is not in the SDK, don't use it
3341 }
3342 else {
3343 fLibrarySearchPaths.push_back(libDir);
3344 }
3345 }
3346 }
3347
3348 // now merge sdk and framework paths to make real search paths
3349 fFrameworkSearchPaths.reserve(frameworkPaths.size()*(fSDKPaths.size()+1));
3350 int frameIndex = 0;
3351 for (std::vector<const char*>::iterator it = frameworkPaths.begin(); it != frameworkPaths.end(); ++it, ++frameIndex) {
3352 const char* frameworkDir = *it;
3353 bool sdkOverride = false;
3354 if ( frameworkDir[0] == '/' ) {
3355 char betterFrameworkDir[PATH_MAX];
3356 if ( strstr(frameworkDir, "/..") != NULL ) {
3357 if ( realpath(frameworkDir, betterFrameworkDir) != NULL )
3358 frameworkDir = strdup(betterFrameworkDir);
3359 }
3360 const int frameworkDirLen = strlen(frameworkDir);
3361 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
3362 const char* sdkDir = *sdkit;
3363 const int sdkDirLen = strlen(sdkDir);
3364 char newPath[frameworkDirLen + sdkDirLen+4];
3365 strcpy(newPath, sdkDir);
3366 if ( newPath[sdkDirLen-1] == '/' )
3367 newPath[sdkDirLen-1] = '\0';
3368 strcat(newPath, frameworkDir);
3369 struct stat statBuffer;
3370 if ( stat(newPath, &statBuffer) == 0 ) {
3371 fFrameworkSearchPaths.push_back(strdup(newPath));
3372 sdkOverride = true;
3373 }
3374 }
3375 }
3376 if ( !sdkOverride ) {
3377 if ( (frameIndex >= standardFrameworkPathsStartIndex) && (fSDKPaths.size() == 1) ) {
3378 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
3379 // if one SDK is specified and a standard library path is not in the SDK, don't use it
3380 }
3381 else {
3382 fFrameworkSearchPaths.push_back(frameworkDir);
3383 }
3384 }
3385 }
3386
3387 if ( fVerbose ) {
3388 fprintf(stderr,"Library search paths:\n");
3389 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
3390 it != fLibrarySearchPaths.end();
3391 it++)
3392 fprintf(stderr,"\t%s\n", *it);
3393 fprintf(stderr,"Framework search paths:\n");
3394 for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin();
3395 it != fFrameworkSearchPaths.end();
3396 it++)
3397 fprintf(stderr,"\t%s\n", *it);
3398 }
3399 }
3400
3401 // this is run before the command line is parsed
3402 void Options::parsePreCommandLineEnvironmentSettings()
3403 {
3404 if ((getenv("LD_TRACE_ARCHIVES") != NULL)
3405 || (getenv("RC_TRACE_ARCHIVES") != NULL))
3406 fTraceArchives = true;
3407
3408 if ((getenv("LD_TRACE_DYLIBS") != NULL)
3409 || (getenv("RC_TRACE_DYLIBS") != NULL)) {
3410 fTraceDylibs = true;
3411 fTraceIndirectDylibs = true;
3412 }
3413
3414 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL) {
3415 fTraceDylibSearching = true;
3416 }
3417
3418 if (getenv("LD_PRINT_OPTIONS") != NULL)
3419 fPrintOptions = true;
3420
3421 if (fTraceDylibs || fTraceArchives)
3422 fTraceOutputFile = getenv("LD_TRACE_FILE");
3423
3424 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL)
3425 fPrintOrderFileStatistics = true;
3426
3427 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL)
3428 fSplitSegs = true;
3429
3430 if (getenv("LD_NO_ENCRYPT") != NULL) {
3431 fEncryptable = false;
3432 fMarkAppExtensionSafe = true; // temporary
3433 fCheckAppExtensionSafe = false;
3434 }
3435
3436 if (getenv("LD_APPLICATION_EXTENSION_SAFE") != NULL) {
3437 fMarkAppExtensionSafe = true;
3438 fCheckAppExtensionSafe = false;
3439 }
3440
3441 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL)
3442 fAllowCpuSubtypeMismatches = true;
3443
3444 sWarningsSideFilePath = getenv("LD_WARN_FILE");
3445
3446 const char* customDyldPath = getenv("LD_DYLD_PATH");
3447 if ( customDyldPath != NULL )
3448 fDyldInstallPath = customDyldPath;
3449
3450 const char* debugArchivePath = getenv("LD_DEBUG_SNAPSHOT");
3451 if (debugArchivePath != NULL) {
3452 fLinkSnapshot.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG);
3453 if (strlen(debugArchivePath) > 0)
3454 fLinkSnapshot.setSnapshotPath(debugArchivePath);
3455 fSnapshotRequested = true;
3456 }
3457
3458 const char* pipeFdString = getenv("LD_PIPELINE_FIFO");
3459 if (pipeFdString != NULL) {
3460 fPipelineFifo = pipeFdString;
3461 }
3462 }
3463
3464
3465 // this is run after the command line is parsed
3466 void Options::parsePostCommandLineEnvironmentSettings()
3467 {
3468 // when building a dynamic main executable, default any use of @executable_path to output path
3469 if ( fExecutablePath == NULL && (fOutputKind == kDynamicExecutable) ) {
3470 fExecutablePath = fOutputFile;
3471 }
3472
3473 // allow build system to set default seg_addr_table
3474 if ( fSegAddrTablePath == NULL )
3475 fSegAddrTablePath = getenv("LD_SEG_ADDR_TABLE");
3476
3477 // allow build system to turn on prebinding
3478 if ( !fPrebind ) {
3479 fPrebind = ( getenv("LD_PREBIND") != NULL );
3480 }
3481
3482 // allow build system to force on dead-code-stripping
3483 if ( !fDeadStrip ) {
3484 if ( getenv("LD_DEAD_STRIP") != NULL ) {
3485 switch (fOutputKind) {
3486 case Options::kDynamicLibrary:
3487 case Options::kDynamicExecutable:
3488 case Options::kDynamicBundle:
3489 fDeadStrip = true;
3490 break;
3491 case Options::kPreload:
3492 case Options::kObjectFile:
3493 case Options::kDyld:
3494 case Options::kStaticExecutable:
3495 case Options::kKextBundle:
3496 break;
3497 }
3498 }
3499 }
3500
3501 // allow build system to force on -warn_commons
3502 if ( getenv("LD_WARN_COMMONS") != NULL )
3503 fWarnCommons = true;
3504
3505 // allow B&I to set default -source_version
3506 if ( fSourceVersion == 0 ) {
3507 const char* vers = getenv("RC_ProjectSourceVersion");
3508 if ( vers != NULL )
3509 fSourceVersion = parseVersionNumber64(vers);
3510 }
3511
3512 }
3513
3514 void Options::reconfigureDefaults()
3515 {
3516 // sync reader options
3517 switch ( fOutputKind ) {
3518 case Options::kObjectFile:
3519 fForFinalLinkedImage = false;
3520 break;
3521 case Options::kDyld:
3522 fForDyld = true;
3523 fForFinalLinkedImage = true;
3524 fNoEHLabels = true;
3525 break;
3526 case Options::kDynamicLibrary:
3527 case Options::kDynamicBundle:
3528 case Options::kKextBundle:
3529 fForFinalLinkedImage = true;
3530 fNoEHLabels = true;
3531 break;
3532 case Options::kDynamicExecutable:
3533 case Options::kStaticExecutable:
3534 case Options::kPreload:
3535 fLinkingMainExecutable = true;
3536 fForFinalLinkedImage = true;
3537 fNoEHLabels = true;
3538 break;
3539 }
3540
3541 // set default min OS version
3542 if ( (fMacVersionMin == ld::macVersionUnset)
3543 && (fIOSVersionMin == ld::iOSVersionUnset) ) {
3544 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
3545 const char* macVers = getenv("MACOSX_DEPLOYMENT_TARGET");
3546 const char* iPhoneVers = getenv("IPHONEOS_DEPLOYMENT_TARGET");
3547 const char* iOSVers = getenv("IOS_DEPLOYMENT_TARGET");
3548 const char* iOSSimulatorVers = getenv("IOS_SIMULATOR_DEPLOYMENT_TARGET");
3549 if ( macVers != NULL )
3550 setMacOSXVersionMin(macVers);
3551 else if ( iPhoneVers != NULL )
3552 setIOSVersionMin(iPhoneVers);
3553 else if ( iOSVers != NULL )
3554 setIOSVersionMin(iOSVers);
3555 else if ( iOSSimulatorVers != NULL )
3556 setIOSVersionMin(iOSSimulatorVers);
3557 else {
3558 // if still nothing, set default based on architecture
3559 switch ( fArchitecture ) {
3560 case CPU_TYPE_I386:
3561 case CPU_TYPE_X86_64:
3562 if ( (fOutputKind != Options::kObjectFile) && (fOutputKind != Options::kPreload) ) {
3563 #ifdef DEFAULT_MACOSX_MIN_VERSION
3564 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION);
3565 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
3566 #else
3567 warning("-macosx_version_min not specified, assuming 10.6");
3568 fMacVersionMin = ld::mac10_6;
3569 #endif
3570 }
3571 break;
3572 case CPU_TYPE_ARM:
3573 if ( (fOutputKind != Options::kObjectFile) && (fOutputKind != Options::kPreload) ) {
3574 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
3575 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION);
3576 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION);
3577 #else
3578 warning("-ios_version_min not specified, assuming 6.0");
3579 setIOSVersionMin("6.0");
3580 #endif
3581 }
3582 break;
3583 default:
3584 // architecture will be infered later by examining .o files
3585 break;
3586 }
3587 }
3588 }
3589
3590
3591 // adjust min based on architecture
3592 switch ( fArchitecture ) {
3593 case CPU_TYPE_I386:
3594 if ( (fMacVersionMin < ld::mac10_4) && (fIOSVersionMin == ld::iOSVersionUnset) ) {
3595 //warning("-macosx_version_min should be 10.4 or later for i386");
3596 fMacVersionMin = ld::mac10_4;
3597 }
3598 break;
3599 case CPU_TYPE_X86_64:
3600 if ( (fMacVersionMin < ld::mac10_4) && (fIOSVersionMin == ld::iOSVersionUnset) ) {
3601 //warning("-macosx_version_min should be 10.4 or later for x86_64");
3602 fMacVersionMin = ld::mac10_4;
3603 }
3604 break;
3605 case CPU_TYPE_ARM64:
3606 if ( fIOSVersionMin < ld::iOS_7_0 ) {
3607 //warning("-mios_version_min should be 7.0 or later for arm64");
3608 fIOSVersionMin = ld::iOS_7_0;
3609 }
3610 break;
3611 }
3612
3613 // default to adding functions start for dynamic code, static code must opt-in
3614 switch ( fOutputKind ) {
3615 case Options::kPreload:
3616 case Options::kStaticExecutable:
3617 case Options::kKextBundle:
3618 if ( fDataInCodeInfoLoadCommandForcedOn )
3619 fDataInCodeInfoLoadCommand = true;
3620 if ( fFunctionStartsForcedOn )
3621 fFunctionStartsLoadCommand = true;
3622 break;
3623 case Options::kObjectFile:
3624 if ( !fDataInCodeInfoLoadCommandForcedOff )
3625 fDataInCodeInfoLoadCommand = true;
3626 if ( fFunctionStartsForcedOn )
3627 fFunctionStartsLoadCommand = true;
3628 break;
3629 case Options::kDynamicExecutable:
3630 case Options::kDyld:
3631 case Options::kDynamicLibrary:
3632 case Options::kDynamicBundle:
3633 if ( !fDataInCodeInfoLoadCommandForcedOff )
3634 fDataInCodeInfoLoadCommand = true;
3635 if ( !fFunctionStartsForcedOff )
3636 fFunctionStartsLoadCommand = true;
3637 break;
3638 }
3639
3640 // adjust kext type based on architecture
3641 if ( fOutputKind == kKextBundle ) {
3642 switch ( fArchitecture ) {
3643 case CPU_TYPE_X86_64:
3644 // x86_64 uses new MH_KEXT_BUNDLE type
3645 fMakeCompressedDyldInfo = false;
3646 fMakeCompressedDyldInfoForceOff = true;
3647 fAllowTextRelocs = true;
3648 fUndefinedTreatment = kUndefinedDynamicLookup;
3649 break;
3650 case CPU_TYPE_ARM64:
3651 // arm64 uses new MH_KEXT_BUNDLE type
3652 fMakeCompressedDyldInfo = false;
3653 fMakeCompressedDyldInfoForceOff = true;
3654 fAllowTextRelocs = false;
3655 fKextsUseStubs = true;
3656 fUndefinedTreatment = kUndefinedDynamicLookup;
3657 break;
3658 case CPU_TYPE_ARM:
3659 if ( fIOSVersionMin >= ld::iOS_5_0 ) {
3660 // iOS 5.0 and later use new MH_KEXT_BUNDLE type
3661 fMakeCompressedDyldInfo = false;
3662 fMakeCompressedDyldInfoForceOff = true;
3663 // kexts are PIC in iOS 6.0 and later
3664 fAllowTextRelocs = (fIOSVersionMin < ld::iOS_6_0);
3665 fKextsUseStubs = !fAllowTextRelocs;
3666 fUndefinedTreatment = kUndefinedDynamicLookup;
3667 break;
3668 }
3669 // else use object file
3670 case CPU_TYPE_I386:
3671 // use .o files
3672 fOutputKind = kObjectFile;
3673 break;
3674 }
3675 }
3676
3677 // disable implicit dylibs when targeting 10.3
3678 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
3679 if ( !minOS(ld::mac10_4, ld::iOS_2_0) )
3680 fImplicitlyLinkPublicDylibs = false;
3681
3682
3683 // allow build system to force linker to ignore -prebind
3684 if ( getenv("LD_FORCE_NO_PREBIND") != NULL )
3685 fPrebind = false;
3686
3687 // allow build system to force linker to ignore -seg_addr_table
3688 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL )
3689 fSegAddrTablePath = NULL;
3690
3691 // check for base address specified externally
3692 if ( (fSegAddrTablePath != NULL) && (fOutputKind == Options::kDynamicLibrary) ) {
3693 parseSegAddrTable(fSegAddrTablePath, this->installPath());
3694 // HACK to support seg_addr_table entries that are physical paths instead of install paths
3695 if ( fBaseAddress == 0 ) {
3696 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
3697 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libstdc++.6.0.4.dylib");
3698 if ( fBaseAddress == 0 )
3699 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libstdc++.6.0.9.dylib");
3700 }
3701
3702 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
3703 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libz.1.2.3.dylib");
3704
3705 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
3706 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libutil1.0.dylib");
3707 }
3708 }
3709
3710 // split segs only allowed for dylibs
3711 if ( fSplitSegs ) {
3712 // split seg only supported for i386, and arm.
3713 switch ( fArchitecture ) {
3714 case CPU_TYPE_I386:
3715 if ( fOutputKind != Options::kDynamicLibrary )
3716 fSplitSegs = false;
3717 // make sure read and write segments are proper distance apart
3718 if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x10000000) )
3719 fBaseWritableAddress = fBaseAddress + 0x10000000;
3720 break;
3721 case CPU_TYPE_ARM:
3722 if ( fOutputKind != Options::kDynamicLibrary ) {
3723 fSplitSegs = false;
3724 }
3725 else {
3726 // make sure read and write segments are proper distance apart
3727 if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x08000000) )
3728 fBaseWritableAddress = fBaseAddress + 0x08000000;
3729 }
3730 break;
3731 default:
3732 fSplitSegs = false;
3733 fBaseAddress = 0;
3734 fBaseWritableAddress = 0;
3735 }
3736 }
3737
3738 // set too-large size
3739 switch ( fArchitecture ) {
3740 case CPU_TYPE_I386:
3741 fMaxAddress = 0xFFFFFFFF;
3742 break;
3743 case CPU_TYPE_X86_64:
3744 break;
3745 case CPU_TYPE_ARM:
3746 switch ( fOutputKind ) {
3747 case Options::kDynamicExecutable:
3748 case Options::kDynamicLibrary:
3749 case Options::kDynamicBundle:
3750 // user land code is limited to low 1GB
3751 fMaxAddress = 0x2FFFFFFF;
3752 break;
3753 case Options::kStaticExecutable:
3754 case Options::kObjectFile:
3755 case Options::kDyld:
3756 case Options::kPreload:
3757 case Options::kKextBundle:
3758 fMaxAddress = 0xFFFFFFFF;
3759 break;
3760 }
3761 // range check -seg1addr for ARM
3762 if ( fBaseAddress > fMaxAddress ) {
3763 warning("ignoring -seg1addr 0x%08llX. Address out of range.", fBaseAddress);
3764 fBaseAddress = 0;
3765 }
3766 break;
3767 }
3768
3769 // <rdar://problem/6138961> -r implies no prebinding for all architectures
3770 if ( fOutputKind == Options::kObjectFile )
3771 fPrebind = false;
3772
3773 // disable prebinding depending on arch and min OS version
3774 if ( fPrebind ) {
3775 switch ( fArchitecture ) {
3776 case CPU_TYPE_I386:
3777 if ( fMacVersionMin == ld::mac10_4 ) {
3778 // in 10.4 only split seg dylibs are prebound
3779 if ( (fOutputKind != Options::kDynamicLibrary) || ! fSplitSegs )
3780 fPrebind = false;
3781 }
3782 else if ( fMacVersionMin >= ld::mac10_5 ) {
3783 // in 10.5 nothing is prebound
3784 fPrebind = false;
3785 }
3786 else if ( fIOSVersionMin != ld::iOSVersionUnset ) {
3787 // nothing in simulator is prebound
3788 fPrebind = false;
3789 }
3790 else {
3791 // in 10.3 and earlier only dylibs and main executables could be prebound
3792 switch ( fOutputKind ) {
3793 case Options::kDynamicExecutable:
3794 case Options::kDynamicLibrary:
3795 // only main executables and dylibs can be prebound
3796 break;
3797 case Options::kStaticExecutable:
3798 case Options::kDynamicBundle:
3799 case Options::kObjectFile:
3800 case Options::kDyld:
3801 case Options::kPreload:
3802 case Options::kKextBundle:
3803 // disable prebinding for everything else
3804 fPrebind = false;
3805 break;
3806 }
3807 }
3808 break;
3809 case CPU_TYPE_X86_64:
3810 fPrebind = false;
3811 break;
3812 case CPU_TYPE_ARM:
3813 switch ( fOutputKind ) {
3814 case Options::kDynamicExecutable:
3815 case Options::kDynamicLibrary:
3816 // only main executables and dylibs can be prebound
3817 break;
3818 case Options::kStaticExecutable:
3819 case Options::kDynamicBundle:
3820 case Options::kObjectFile:
3821 case Options::kDyld:
3822 case Options::kPreload:
3823 case Options::kKextBundle:
3824 // disable prebinding for everything else
3825 fPrebind = false;
3826 break;
3827 }
3828 break;
3829 }
3830 }
3831
3832 // only prebound images can be split-seg
3833 if ( fSplitSegs && !fPrebind )
3834 fSplitSegs = false;
3835
3836 // determine if info for shared region should be added
3837 if ( fOutputKind == Options::kDynamicLibrary ) {
3838 if ( minOS(ld::mac10_5, ld::iOS_3_1) )
3839 if ( !fPrebind )
3840 if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
3841 || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
3842 fSharedRegionEligible = true;
3843 }
3844 else if ( fOutputKind == Options::kDyld ) {
3845 // <rdar://problem/10111122> Enable dyld to be put into the dyld shared cache
3846 fSharedRegionEligible = true;
3847 }
3848
3849 // figure out if module table is needed for compatibility with old ld/dyld
3850 if ( fOutputKind == Options::kDynamicLibrary ) {
3851 switch ( fArchitecture ) {
3852 case CPU_TYPE_I386:
3853 if ( fIOSVersionMin != ld::iOSVersionUnset ) // simulator never needs modules
3854 break;
3855 case CPU_TYPE_ARM:
3856 if ( fPrebind )
3857 fNeedsModuleTable = true; // redo_prebinding requires a module table
3858 break;
3859 }
3860 }
3861
3862 // <rdar://problem/5366363> -r -x implies -S
3863 if ( (fOutputKind == Options::kObjectFile) && (fLocalSymbolHandling == kLocalSymbolsNone) )
3864 fDebugInfoStripping = Options::kDebugInfoNone;
3865
3866 // <rdar://problem/15252891> -r implies -no_uuid
3867 if ( fOutputKind == Options::kObjectFile )
3868 fUUIDMode = kUUIDNone;
3869
3870 // choose how to process unwind info
3871 switch ( fArchitecture ) {
3872 case CPU_TYPE_I386:
3873 case CPU_TYPE_X86_64:
3874 case CPU_TYPE_ARM64:
3875 switch ( fOutputKind ) {
3876 case Options::kObjectFile:
3877 case Options::kStaticExecutable:
3878 case Options::kPreload:
3879 case Options::kKextBundle:
3880 fAddCompactUnwindEncoding = false;
3881 break;
3882 case Options::kDyld:
3883 case Options::kDynamicLibrary:
3884 case Options::kDynamicBundle:
3885 case Options::kDynamicExecutable:
3886 //if ( fAddCompactUnwindEncoding && (fVersionMin >= ld::mac10_6) )
3887 // fRemoveDwarfUnwindIfCompactExists = true;
3888 break;
3889 }
3890 break;
3891 case CPU_TYPE_ARM:
3892 fAddCompactUnwindEncoding = false;
3893 fRemoveDwarfUnwindIfCompactExists = false;
3894 break;
3895 case 0:
3896 // if -arch is missing, assume we don't want compact unwind info
3897 fAddCompactUnwindEncoding = false;
3898 break;
3899 }
3900
3901 // only iOS executables should be encryptable
3902 switch ( fOutputKind ) {
3903 case Options::kObjectFile:
3904 case Options::kDyld:
3905 case Options::kStaticExecutable:
3906 case Options::kPreload:
3907 case Options::kKextBundle:
3908 fEncryptable = false;
3909 break;
3910 case Options::kDynamicExecutable:
3911 break;
3912 case Options::kDynamicLibrary:
3913 case Options::kDynamicBundle:
3914 // <rdar://problem/16293398> Add LC_ENCRYPTION_INFO load command to bundled frameworks
3915 if ( fIOSVersionMin < ld::iOS_8_0 )
3916 fEncryptable = false;
3917 break;
3918 }
3919 if ( (fArchitecture != CPU_TYPE_ARM) && (fArchitecture != CPU_TYPE_ARM64) )
3920 fEncryptable = false;
3921
3922 // don't move inits in dyld because dyld wants certain
3923 // entries point at stable locations at the start of __text
3924 if ( fOutputKind == Options::kDyld )
3925 fAutoOrderInitializers = false;
3926
3927
3928 // disable __data ordering for some output kinds
3929 switch ( fOutputKind ) {
3930 case Options::kObjectFile:
3931 case Options::kDyld:
3932 case Options::kStaticExecutable:
3933 case Options::kPreload:
3934 case Options::kKextBundle:
3935 fOrderData = false;
3936 break;
3937 case Options::kDynamicExecutable:
3938 case Options::kDynamicLibrary:
3939 case Options::kDynamicBundle:
3940 break;
3941 }
3942
3943 // only use compressed LINKEDIT for final linked images
3944 switch ( fOutputKind ) {
3945 case Options::kDynamicExecutable:
3946 case Options::kDynamicLibrary:
3947 case Options::kDynamicBundle:
3948 break;
3949 case Options::kPreload:
3950 case Options::kStaticExecutable:
3951 case Options::kObjectFile:
3952 case Options::kDyld:
3953 case Options::kKextBundle:
3954 fMakeCompressedDyldInfoForceOff = true;
3955 break;
3956 }
3957 if ( fMakeCompressedDyldInfoForceOff )
3958 fMakeCompressedDyldInfo = false;
3959
3960
3961 // only use compressed LINKEDIT for:
3962 // Mac OS X 10.6 or later
3963 // iOS 3.1 or later
3964 if ( fMakeCompressedDyldInfo ) {
3965 if ( !minOS(ld::mac10_6, ld::iOS_3_1) )
3966 fMakeCompressedDyldInfo = false;
3967 }
3968
3969 // only ARM and x86_64 enforces that cpu-sub-types must match
3970 switch ( fArchitecture ) {
3971 case CPU_TYPE_ARM:
3972 case CPU_TYPE_X86_64:
3973 break;
3974 case CPU_TYPE_I386:
3975 case CPU_TYPE_ARM64:
3976 fAllowCpuSubtypeMismatches = true;
3977 break;
3978 }
3979
3980
3981 // only final linked images can not optimize zero fill sections
3982 if ( fOutputKind == Options::kObjectFile )
3983 fOptimizeZeroFill = true;
3984
3985 // all undefines in -r mode
3986 // if ( fOutputKind == Options::kObjectFile )
3987 // fUndefinedTreatment = kUndefinedSuppress;
3988
3989 // only dynamic final linked images should warn about use of commmons
3990 if ( fWarnCommons ) {
3991 switch ( fOutputKind ) {
3992 case Options::kDynamicExecutable:
3993 case Options::kDynamicLibrary:
3994 case Options::kDynamicBundle:
3995 break;
3996 case Options::kPreload:
3997 case Options::kStaticExecutable:
3998 case Options::kObjectFile:
3999 case Options::kDyld:
4000 case Options::kKextBundle:
4001 fWarnCommons = false;
4002 break;
4003 }
4004 }
4005
4006 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
4007 if ( minOS(ld::mac10_5, ld::iOS_2_0) )
4008 fUseSimplifiedDylibReExports = true;
4009
4010 // Mac OS X 10.7 and iOS 4.2 support LC_LOAD_UPWARD_DYLIB
4011 if ( minOS(ld::mac10_7, ld::iOS_4_2) && (fOutputKind == kDynamicLibrary) )
4012 fCanUseUpwardDylib = true;
4013
4014 // MacOSX 10.7 defaults to PIE
4015 if ( ((fArchitecture == CPU_TYPE_X86_64) || (fArchitecture == CPU_TYPE_I386))
4016 && (fOutputKind == kDynamicExecutable)
4017 && (fMacVersionMin >= ld::mac10_7) ) {
4018 fPositionIndependentExecutable = true;
4019 }
4020
4021 // armv7 for iOS4.3 defaults to PIE
4022 if ( (fArchitecture == CPU_TYPE_ARM)
4023 && fArchSupportsThumb2
4024 && (fOutputKind == kDynamicExecutable)
4025 && (fIOSVersionMin >= ld::iOS_4_3) ) {
4026 fPositionIndependentExecutable = true;
4027 }
4028
4029 // Simulator defaults to PIE
4030 if ( fTargetIOSSimulator && (fOutputKind == kDynamicExecutable) )
4031 fPositionIndependentExecutable = true;
4032
4033 // -no_pie anywhere on command line disable PIE
4034 if ( fDisablePositionIndependentExecutable )
4035 fPositionIndependentExecutable = false;
4036
4037 // arm64 is always PIE
4038 if ( (fArchitecture == CPU_TYPE_ARM64) && (fOutputKind == kDynamicExecutable) ) {
4039 fPositionIndependentExecutable = true;
4040 }
4041
4042 // set fOutputSlidable
4043 switch ( fOutputKind ) {
4044 case Options::kObjectFile:
4045 fOutputSlidable = false;
4046 break;
4047 case Options::kStaticExecutable:
4048 case Options::kDynamicExecutable:
4049 fOutputSlidable = fPositionIndependentExecutable;
4050 break;
4051 case Options::kPreload:
4052 fOutputSlidable = fPIEOnCommandLine;
4053 break;
4054 case Options::kDyld:
4055 case Options::kDynamicLibrary:
4056 case Options::kDynamicBundle:
4057 case Options::kKextBundle:
4058 fOutputSlidable = true;
4059 break;
4060 }
4061
4062 // let linker know if thread local variables are supported
4063 if ( fMacVersionMin >= ld::mac10_7 ) {
4064 fTLVSupport = true;
4065 }
4066 else if ( (fArchitecture == CPU_TYPE_ARM64) && (fIOSVersionMin >= ld::iOS_8_0) ) {
4067 fTLVSupport = true;
4068 }
4069
4070 // default to adding version load command for dynamic code, static code must opt-in
4071 switch ( fOutputKind ) {
4072 case Options::kObjectFile:
4073 fVersionLoadCommand = false;
4074 break;
4075 case Options::kStaticExecutable:
4076 case Options::kPreload:
4077 case Options::kKextBundle:
4078 if ( fVersionLoadCommandForcedOn )
4079 fVersionLoadCommand = true;
4080 break;
4081 case Options::kDynamicExecutable:
4082 case Options::kDyld:
4083 case Options::kDynamicLibrary:
4084 case Options::kDynamicBundle:
4085 if ( !fVersionLoadCommandForcedOff )
4086 fVersionLoadCommand = true;
4087 break;
4088 }
4089
4090 // support re-export of individual symbols in MacOSX 10.7 and iOS 4.2
4091 if ( (fOutputKind == kDynamicLibrary) && minOS(ld::mac10_7, ld::iOS_4_2) )
4092 fCanReExportSymbols = true;
4093
4094 // ObjC optimization is only in dynamic final linked images
4095 switch ( fOutputKind ) {
4096 case Options::kObjectFile:
4097 case Options::kStaticExecutable:
4098 case Options::kPreload:
4099 case Options::kKextBundle:
4100 case Options::kDyld:
4101 fObjcCategoryMerging = false;
4102 break;
4103 case Options::kDynamicExecutable:
4104 case Options::kDynamicLibrary:
4105 case Options::kDynamicBundle:
4106 break;
4107 }
4108
4109 // i386 main executables linked on Mac OS X 10.7 default to NX heap
4110 // regardless of target unless overriden with -allow_heap_execute anywhere
4111 // on the command line
4112 if ( (fArchitecture == CPU_TYPE_I386) && (fOutputKind == kDynamicExecutable) && !fDisableNonExecutableHeap)
4113 fNonExecutableHeap = true;
4114
4115 // Use LC_MAIN instead of LC_UNIXTHREAD for newer OSs
4116 switch ( fOutputKind ) {
4117 case Options::kDynamicExecutable:
4118 if ( fEntryPointLoadCommandForceOn ) {
4119 fEntryPointLoadCommand = true;
4120 if ( fEntryName == NULL )
4121 fEntryName = "_main";
4122 }
4123 else if ( fEntryPointLoadCommandForceOff ) {
4124 fNeedsThreadLoadCommand = true;
4125 if ( fEntryName == NULL )
4126 fEntryName = "start";
4127 }
4128 else {
4129 // <rdar://problem/16310363> Linker should look for "_main" not "start" when building for sim regardless of min OS
4130 if ( minOS(ld::mac10_8, ld::iOS_6_0) || fTargetIOSSimulator ) {
4131 fEntryPointLoadCommand = true;
4132 if ( fEntryName == NULL )
4133 fEntryName = "_main";
4134 if ( strcmp(fEntryName, "start") == 0 ) {
4135 warning("Ignoring '-e start' because entry point 'start' is not used for the targeted OS version");
4136 fEntryName = "_main";
4137 }
4138 }
4139 else {
4140 fNeedsThreadLoadCommand = true;
4141 if ( fEntryName == NULL )
4142 fEntryName = "start";
4143 }
4144 }
4145 break;
4146 case Options::kObjectFile:
4147 case Options::kKextBundle:
4148 case Options::kDynamicLibrary:
4149 case Options::kDynamicBundle:
4150 break;
4151
4152 case Options::kStaticExecutable:
4153 case Options::kPreload:
4154 case Options::kDyld:
4155 fNeedsThreadLoadCommand = true;
4156 if ( fEntryName == NULL )
4157 fEntryName = "start"; // Perhaps these should have no default and require -e
4158 break;
4159 }
4160
4161 // add LC_SOURCE_VERSION
4162 switch ( fOutputKind ) {
4163 case Options::kDynamicExecutable:
4164 case Options::kKextBundle:
4165 case Options::kDynamicLibrary:
4166 case Options::kDynamicBundle:
4167 case Options::kDyld:
4168 case Options::kStaticExecutable:
4169 if ( fSourceVersionLoadCommandForceOn ) {
4170 fSourceVersionLoadCommand = true;
4171 }
4172 else if ( fSourceVersionLoadCommandForceOff ) {
4173 fSourceVersionLoadCommand = false;
4174 }
4175 else {
4176 if ( minOS(ld::mac10_8, ld::iOS_6_0) ) {
4177 fSourceVersionLoadCommand = true;
4178 }
4179 else
4180 fSourceVersionLoadCommand = false;
4181 }
4182 break;
4183 case Options::kObjectFile:
4184 case Options::kPreload:
4185 fSourceVersionLoadCommand = false;
4186 break;
4187 }
4188
4189
4190 // add LC_DYLIB_CODE_SIGN_DRS
4191 switch ( fOutputKind ) {
4192 case Options::kDynamicExecutable:
4193 case Options::kDynamicLibrary:
4194 case Options::kDynamicBundle:
4195 if ( fDependentDRInfoForcedOn ) {
4196 fDependentDRInfo = true;
4197 }
4198 else if ( fDependentDRInfoForcedOff ) {
4199 fDependentDRInfo = false;
4200 }
4201 else {
4202 if ( minOS(ld::mac10_8, ld::iOS_6_0) )
4203 fDependentDRInfo = true;
4204 else
4205 fDependentDRInfo = false;
4206 }
4207 break;
4208 case Options::kKextBundle:
4209 case Options::kDyld:
4210 case Options::kStaticExecutable:
4211 case Options::kObjectFile:
4212 case Options::kPreload:
4213 fDependentDRInfo = false;
4214 break;
4215 }
4216
4217 // if -sdk_version not on command line, infer from -syslibroot
4218 if ( (fSDKVersion == 0) && (fSDKPaths.size() > 0) ) {
4219 const char* sdkPath = fSDKPaths.front();
4220 const char* end = &sdkPath[strlen(sdkPath)-1];
4221 while ( !isdigit(*end) && (end > sdkPath) )
4222 --end;
4223 const char* start = end-1;
4224 while ( (isdigit(*start) || (*start == '.')) && (start > sdkPath))
4225 --start;
4226 char sdkVersionStr[32];
4227 int len = end-start+1;
4228 if ( len > 2 ) {
4229 strlcpy(sdkVersionStr, start+1, len);
4230 fSDKVersion = parseVersionNumber32(sdkVersionStr);
4231 }
4232 }
4233
4234 // if -sdk_version and -syslibroot not used, but targeting MacOSX, use current OS version
4235 if ( (fSDKVersion == 0) && (fMacVersionMin != ld::macVersionUnset) ) {
4236 // special case if RC_ProjectName and MACOSX_DEPLOYMENT_TARGET are both set that sdkversion=minos
4237 if ( getenv("RC_ProjectName") && getenv("MACOSX_DEPLOYMENT_TARGET") ) {
4238 fSDKVersion = fMacVersionMin;
4239 }
4240 else {
4241 int mib[2] = { CTL_KERN, KERN_OSRELEASE };
4242 char kernVersStr[100];
4243 size_t strlen = sizeof(kernVersStr);
4244 if ( sysctl(mib, 2, kernVersStr, &strlen, NULL, 0) != -1 ) {
4245 uint32_t kernVers = parseVersionNumber32(kernVersStr);
4246 int minor = (kernVers >> 16) - 4; // kernel major version is 4 ahead of x in 10.x
4247 fSDKVersion = 0x000A0000 + (minor << 8);
4248 }
4249 }
4250 }
4251
4252 // allow trie based absolute symbols if targeting new enough OS
4253 if ( fMakeCompressedDyldInfo ) {
4254 if ( minOS(ld::mac10_9, ld::iOS_7_0) ) {
4255 // <rdar://problem/13179029> Allow absolute symbols in export trie for device but not simulator
4256 if ( !fTargetIOSSimulator )
4257 fAbsoluteSymbols = true;
4258 }
4259 }
4260
4261 // <rdar://problem/12959510> iOS main executables now default to 16KB page size
4262 if ( (fIOSVersionMin != ld::iOSVersionUnset) && (fOutputKind == Options::kDynamicExecutable) ) {
4263 // <rdar://problem/13070042> Only third party apps should have 16KB page segments by default
4264 if ( fEncryptable ) {
4265 if ( fSegmentAlignment == 4096 )
4266 fSegmentAlignment = 4096*4;
4267 }
4268 }
4269
4270 // <rdar://problem/12258065> ARM64 needs 16KB page size for user land code
4271 // <rdar://problem/15974532> make armv7[s] use 16KB pages in user land code for iOS 8 or later
4272 if ( fSegmentAlignment == 4096 ) {
4273 if ( (fArchitecture == CPU_TYPE_ARM64)
4274 || ((fArchitecture == CPU_TYPE_ARM) && (fIOSVersionMin >= ld::iOS_8_0) &&
4275 ((fSubArchitecture == CPU_SUBTYPE_ARM_V7S) || (fSubArchitecture == CPU_SUBTYPE_ARM_V7))) ) {
4276 switch ( fOutputKind ) {
4277 case Options::kDynamicExecutable:
4278 case Options::kDynamicLibrary:
4279 case Options::kDynamicBundle:
4280 case Options::kDyld:
4281 fSegmentAlignment = 4096*4;
4282 break;
4283 case Options::kStaticExecutable:
4284 case Options::kKextBundle:
4285 case Options::kObjectFile:
4286 case Options::kPreload:
4287 break;
4288 }
4289 }
4290 }
4291
4292 // <rdar://problem/13624134> linker should not convert dwarf unwind if .o file has compact unwind section
4293 switch ( fOutputKind ) {
4294 case Options::kDynamicExecutable:
4295 case Options::kDynamicLibrary:
4296 case Options::kDynamicBundle:
4297 case Options::kDyld:
4298 if ( fKeepDwarfUnwindForcedOn ) {
4299 fKeepDwarfUnwind = true;
4300 }
4301 else if ( fKeepDwarfUnwindForcedOff ) {
4302 fKeepDwarfUnwind = false;
4303 }
4304 else {
4305 if ( minOS(ld::mac10_9, ld::iOS_7_0) )
4306 fKeepDwarfUnwind = false;
4307 else
4308 fKeepDwarfUnwind = true;
4309 }
4310 break;
4311 case Options::kKextBundle:
4312 case Options::kStaticExecutable:
4313 case Options::kObjectFile:
4314 case Options::kPreload:
4315 fKeepDwarfUnwind = true;
4316 break;
4317 }
4318
4319 }
4320
4321 void Options::checkIllegalOptionCombinations()
4322 {
4323 // check -undefined setting
4324 switch ( fUndefinedTreatment ) {
4325 case kUndefinedError:
4326 case kUndefinedDynamicLookup:
4327 // always legal
4328 break;
4329 case kUndefinedWarning:
4330 case kUndefinedSuppress:
4331 // requires flat namespace
4332 if ( fNameSpace == kTwoLevelNameSpace )
4333 throw "can't use -undefined warning or suppress with -twolevel_namespace";
4334 break;
4335 }
4336
4337 // unify -sub_umbrella with dylibs
4338 for (std::vector<const char*>::iterator it = fSubUmbellas.begin(); it != fSubUmbellas.end(); it++) {
4339 const char* subUmbrella = *it;
4340 bool found = false;
4341 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
4342 Options::FileInfo& info = *fit;
4343 const char* lastSlash = strrchr(info.path, '/');
4344 if ( lastSlash == NULL )
4345 lastSlash = info.path - 1;
4346 if ( strcmp(&lastSlash[1], subUmbrella) == 0 ) {
4347 info.options.fReExport = true;
4348 found = true;
4349 fLinkSnapshot.recordSubUmbrella(info.path);
4350 break;
4351 }
4352 }
4353 if ( ! found )
4354 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella);
4355 }
4356
4357 // unify -sub_library with dylibs
4358 for (std::vector<const char*>::iterator it = fSubLibraries.begin(); it != fSubLibraries.end(); it++) {
4359 const char* subLibrary = *it;
4360 bool found = false;
4361 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
4362 Options::FileInfo& info = *fit;
4363 const char* lastSlash = strrchr(info.path, '/');
4364 if ( lastSlash == NULL )
4365 lastSlash = info.path - 1;
4366 const char* dot = strchr(&lastSlash[1], '.');
4367 if ( dot == NULL )
4368 dot = &lastSlash[strlen(lastSlash)];
4369 if ( strncmp(&lastSlash[1], subLibrary, dot-lastSlash-1) == 0 ) {
4370 info.options.fReExport = true;
4371 found = true;
4372 fLinkSnapshot.recordSubLibrary(info.path);
4373 break;
4374 }
4375 }
4376 if ( ! found )
4377 warning("-sub_library %s does not match a supplied dylib", subLibrary);
4378 }
4379
4380 // sync reader options
4381 if ( fNameSpace != kTwoLevelNameSpace )
4382 fFlatNamespace = true;
4383
4384 // check -stack_addr
4385 if ( fStackAddr != 0 ) {
4386 switch (fArchitecture) {
4387 case CPU_TYPE_I386:
4388 case CPU_TYPE_ARM:
4389 if ( fStackAddr > 0xFFFFFFFF )
4390 throw "-stack_addr must be < 4G for 32-bit processes";
4391 break;
4392 case CPU_TYPE_X86_64:
4393 case CPU_TYPE_ARM64:
4394 break;
4395 }
4396 if ( (fStackAddr & -4096) != fStackAddr )
4397 throw "-stack_addr must be multiples of 4K";
4398 if ( fStackSize == 0 )
4399 throw "-stack_addr must be used with -stack_size";
4400 }
4401
4402 // check -stack_size
4403 if ( fStackSize != 0 ) {
4404 switch (fArchitecture) {
4405 case CPU_TYPE_I386:
4406 if ( fStackSize > 0xFFFFFFFF )
4407 throw "-stack_size must be < 4G for 32-bit processes";
4408 if ( fStackAddr == 0 ) {
4409 fStackAddr = 0xC0000000;
4410 }
4411 if ( (fStackAddr > 0xB0000000) && ((fStackAddr-fStackSize) < 0xB0000000) )
4412 warning("custom stack placement overlaps and will disable shared region");
4413 break;
4414 case CPU_TYPE_ARM:
4415 if ( fStackSize > 0x2F000000 )
4416 throw "-stack_size must be < 752MB";
4417 if ( fStackAddr == 0 )
4418 fStackAddr = 0x2F000000;
4419 if ( fStackAddr > 0x30000000)
4420 throw "-stack_addr must be < 0x30000000 for arm";
4421 break;
4422 case CPU_TYPE_X86_64:
4423 if ( fStackAddr == 0 ) {
4424 fStackAddr = 0x00007FFF5C000000LL;
4425 }
4426 break;
4427 case CPU_TYPE_ARM64:
4428 if ( fStackSize > 0x20000000 )
4429 throw "-stack_size must be < 512MB";
4430 if ( fStackAddr == 0 ) {
4431 fStackAddr = 0x120000000;
4432 }
4433 break;
4434 }
4435 if ( (fStackSize & -4096) != fStackSize )
4436 throw "-stack_size must be multiples of 4K";
4437 switch ( fOutputKind ) {
4438 case Options::kDynamicExecutable:
4439 case Options::kStaticExecutable:
4440 // custom stack size only legal when building main executable
4441 break;
4442 case Options::kDynamicLibrary:
4443 case Options::kDynamicBundle:
4444 case Options::kObjectFile:
4445 case Options::kDyld:
4446 case Options::kPreload:
4447 case Options::kKextBundle:
4448 throw "-stack_size option can only be used when linking a main executable";
4449 }
4450 if ( fStackSize > fStackAddr )
4451 throwf("-stack_size (0x%08llX) must be smaller than -stack_addr (0x%08llX)", fStackSize, fStackAddr);
4452 }
4453
4454 // check that -allow_stack_execute is only used with main executables
4455 if ( fExecutableStack ) {
4456 switch ( fOutputKind ) {
4457 case Options::kDynamicExecutable:
4458 case Options::kStaticExecutable:
4459 // -allow_stack_execute size only legal when building main executable
4460 break;
4461 case Options::kDynamicLibrary:
4462 case Options::kDynamicBundle:
4463 case Options::kObjectFile:
4464 case Options::kDyld:
4465 case Options::kPreload:
4466 case Options::kKextBundle:
4467 throw "-allow_stack_execute option can only be used when linking a main executable";
4468 }
4469 }
4470
4471 // check that -allow_heap_execute is only used with i386 main executables
4472 if ( fDisableNonExecutableHeap ) {
4473 if ( fArchitecture != CPU_TYPE_I386 )
4474 throw "-allow_heap_execute option can only be used when linking for i386";
4475 switch ( fOutputKind ) {
4476 case Options::kDynamicExecutable:
4477 // -allow_heap_execute only legal when building main executable
4478 break;
4479 case Options::kStaticExecutable:
4480 case Options::kDynamicLibrary:
4481 case Options::kDynamicBundle:
4482 case Options::kObjectFile:
4483 case Options::kDyld:
4484 case Options::kPreload:
4485 case Options::kKextBundle:
4486 throw "-allow_heap_execute option can only be used when linking a main executable";
4487 }
4488 }
4489
4490 // check -client_name is only used when making a bundle or main executable
4491 if ( fClientName != NULL ) {
4492 switch ( fOutputKind ) {
4493 case Options::kDynamicExecutable:
4494 case Options::kDynamicBundle:
4495 break;
4496 case Options::kStaticExecutable:
4497 case Options::kDynamicLibrary:
4498 case Options::kObjectFile:
4499 case Options::kDyld:
4500 case Options::kPreload:
4501 case Options::kKextBundle:
4502 throw "-client_name can only be used with -bundle";
4503 }
4504 }
4505
4506 // check -init is only used when building a dylib
4507 if ( (fInitFunctionName != NULL) && (fOutputKind != Options::kDynamicLibrary) )
4508 throw "-init can only be used with -dynamiclib";
4509
4510 // check -bundle_loader only used with -bundle
4511 if ( (fBundleLoader != NULL) && (fOutputKind != Options::kDynamicBundle) )
4512 throw "-bundle_loader can only be used with -bundle";
4513
4514 // check -dtrace not used with -r
4515 if ( (fDtraceScriptName != NULL) && (fOutputKind == Options::kObjectFile) )
4516 throw "-dtrace can only be used when creating final linked images";
4517
4518 // check -d can only be used with -r
4519 if ( fMakeTentativeDefinitionsReal && (fOutputKind != Options::kObjectFile) )
4520 throw "-d can only be used with -r";
4521
4522 // check that -root_safe is not used with -r
4523 if ( fRootSafe && (fOutputKind == Options::kObjectFile) )
4524 throw "-root_safe cannot be used with -r";
4525
4526 // check that -setuid_safe is not used with -r
4527 if ( fSetuidSafe && (fOutputKind == Options::kObjectFile) )
4528 throw "-setuid_safe cannot be used with -r";
4529
4530 // <rdar://problem/12781832> compiler driver no longer uses -objc_abi_version, it uses -ios_simulator_version_min instead
4531 if ( !fObjCABIVersion1Override && !fObjCABIVersion2Override && fTargetIOSSimulator )
4532 fObjCABIVersion2Override = true;
4533
4534 // rdar://problem/4718189 map ObjC class names to new runtime names
4535 bool alterObjC1ClassNamesToObjC2 = false;
4536 switch (fArchitecture) {
4537 case CPU_TYPE_I386:
4538 // i386 only uses new symbols when using objc2 ABI
4539 if ( fObjCABIVersion2Override )
4540 alterObjC1ClassNamesToObjC2 = true;
4541 break;
4542 case CPU_TYPE_X86_64:
4543 case CPU_TYPE_ARM:
4544 case CPU_TYPE_ARM64:
4545 alterObjC1ClassNamesToObjC2 = true;
4546 break;
4547 }
4548
4549 // make sure all required exported symbols exist
4550 std::vector<const char*> impliedExports;
4551 for (NameSet::iterator it=fExportSymbols.regularBegin(); it != fExportSymbols.regularEnd(); ++it) {
4552 const char* name = *it;
4553 const int len = strlen(name);
4554 if ( (strcmp(&name[len-3], ".eh") == 0) || (strncmp(name, ".objc_category_name_", 20) == 0) ) {
4555 // never export .eh symbols
4556 warning("ignoring %s in export list", name);
4557 }
4558 else if ( (fArchitecture == CPU_TYPE_I386) && !fObjCABIVersion2Override && (strncmp(name, "_OBJC_CLASS_$", 13) == 0) ) {
4559 warning("ignoring Objc2 Class symbol %s in i386 export list", name);
4560 fRemovedExports.insert(name);
4561 }
4562 else if ( alterObjC1ClassNamesToObjC2 && (strncmp(name, ".objc_class_name_", 17) == 0) ) {
4563 // linking ObjC2 ABI, but have ObjC1 ABI name in export list. Change it to intended name
4564 fRemovedExports.insert(name);
4565 char* temp;
4566 asprintf(&temp, "_OBJC_CLASS_$_%s", &name[17]);
4567 impliedExports.push_back(temp);
4568 asprintf(&temp, "_OBJC_METACLASS_$_%s", &name[17]);
4569 impliedExports.push_back(temp);
4570 }
4571 else {
4572 fInitialUndefines.push_back(name);
4573 }
4574 }
4575 fExportSymbols.remove(fRemovedExports);
4576 for (std::vector<const char*>::iterator it=impliedExports.begin(); it != impliedExports.end(); ++it) {
4577 const char* name = *it;
4578 fExportSymbols.insert(name);
4579 fInitialUndefines.push_back(name);
4580 }
4581
4582 // make sure all required re-exported symbols exist
4583 for (NameSet::iterator it=fReExportSymbols.regularBegin(); it != fReExportSymbols.regularEnd(); ++it) {
4584 fInitialUndefines.push_back(*it);
4585 }
4586
4587 // make sure that -init symbol exists
4588 if ( fInitFunctionName != NULL )
4589 fInitialUndefines.push_back(fInitFunctionName);
4590
4591 // make sure that entry symbol exists
4592 switch ( fOutputKind ) {
4593 case Options::kDynamicExecutable:
4594 case Options::kStaticExecutable:
4595 case Options::kDyld:
4596 case Options::kPreload:
4597 fInitialUndefines.push_back(fEntryName);
4598 break;
4599 case Options::kDynamicLibrary:
4600 case Options::kDynamicBundle:
4601 case Options::kObjectFile:
4602 case Options::kKextBundle:
4603 break;
4604 }
4605
4606 // make sure every alias base exists
4607 for (std::vector<AliasPair>::iterator it=fAliases.begin(); it != fAliases.end(); ++it) {
4608 fInitialUndefines.push_back(it->realName);
4609 }
4610
4611 // check custom segments
4612 if ( fCustomSegmentAddresses.size() != 0 ) {
4613 // verify no segment is in zero page
4614 if ( fZeroPageSize != ULLONG_MAX ) {
4615 for (std::vector<SegmentStart>::iterator it = fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
4616 if ( it->address < fZeroPageSize )
4617 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it->name, it->address);
4618 }
4619 }
4620 // verify no duplicates
4621 for (std::vector<SegmentStart>::iterator it = fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
4622 for (std::vector<SegmentStart>::iterator it2 = fCustomSegmentAddresses.begin(); it2 != fCustomSegmentAddresses.end(); ++it2) {
4623 if ( (it->address == it2->address) && (it != it2) )
4624 throwf("duplicate -segaddr addresses for %s and %s", it->name, it2->name);
4625 }
4626 // a custom segment address of zero will disable the use of a zero page
4627 if ( it->address == 0 )
4628 fZeroPageSize = 0;
4629 }
4630 }
4631
4632 if ( fZeroPageSize == ULLONG_MAX ) {
4633 // zero page size not specified on command line, set default
4634 switch (fArchitecture) {
4635 case CPU_TYPE_I386:
4636 case CPU_TYPE_ARM:
4637 // first 4KB for 32-bit architectures
4638 fZeroPageSize = 0x1000;
4639 break;
4640 case CPU_TYPE_ARM64:
4641 case CPU_TYPE_X86_64:
4642 // first 4GB for x86_64 on all OS's
4643 fZeroPageSize = 0x100000000ULL;
4644 break;
4645 default:
4646 // if -arch not used, default to 4K zero-page
4647 fZeroPageSize = 0x1000;
4648 }
4649 }
4650 else {
4651 switch ( fOutputKind ) {
4652 case Options::kDynamicExecutable:
4653 case Options::kStaticExecutable:
4654 // -pagezero_size size only legal when building main executable
4655 break;
4656 case Options::kDynamicLibrary:
4657 case Options::kDynamicBundle:
4658 case Options::kObjectFile:
4659 case Options::kDyld:
4660 case Options::kPreload:
4661 case Options::kKextBundle:
4662 if ( fZeroPageSize != 0 )
4663 throw "-pagezero_size option can only be used when linking a main executable";
4664 }
4665 }
4666
4667 // if main executable with custom base address, model zero page as custom segment
4668 if ( (fOutputKind == Options::kDynamicExecutable) && (fBaseAddress != 0) && (fZeroPageSize != 0) ) {
4669 SegmentStart seg;
4670 seg.name = "__PAGEZERO";
4671 seg.address = 0;;
4672 fCustomSegmentAddresses.push_back(seg);
4673 }
4674
4675 // -dead_strip and -r are incompatible
4676 if ( fDeadStrip && (fOutputKind == Options::kObjectFile) )
4677 throw "-r and -dead_strip cannot be used together";
4678
4679 // can't use -rpath unless targeting 10.5 or later
4680 if ( fRPaths.size() > 0 ) {
4681 if ( !minOS(ld::mac10_5, ld::iOS_2_0) )
4682 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
4683 switch ( fOutputKind ) {
4684 case Options::kDynamicExecutable:
4685 case Options::kDynamicLibrary:
4686 case Options::kDynamicBundle:
4687 break;
4688 case Options::kStaticExecutable:
4689 case Options::kObjectFile:
4690 case Options::kDyld:
4691 case Options::kPreload:
4692 case Options::kKextBundle:
4693 throw "-rpath can only be used when creating a dynamic final linked image";
4694 }
4695 }
4696
4697 if ( fPositionIndependentExecutable ) {
4698 switch ( fOutputKind ) {
4699 case Options::kDynamicExecutable:
4700 // check -pie is only used when building a dynamic main executable for 10.5
4701 if ( !minOS(ld::mac10_5, ld::iOS_4_2) ) {
4702 if ( fIOSVersionMin == ld::iOSVersionUnset )
4703 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
4704 else
4705 throw "-pie can only be used when targeting iOS 4.2 or later";
4706 }
4707 break;
4708 case Options::kStaticExecutable:
4709 case Options::kPreload:
4710 // -pie is ok with -static or -preload
4711 break;
4712 case Options::kDynamicLibrary:
4713 case Options::kDynamicBundle:
4714 warning("-pie being ignored. It is only used when linking a main executable");
4715 fPositionIndependentExecutable = false;
4716 break;
4717 case Options::kObjectFile:
4718 case Options::kDyld:
4719 case Options::kKextBundle:
4720 throw "-pie can only be used when linking a main executable";
4721 }
4722 }
4723
4724 // check -read_only_relocs is not used with x86_64
4725 if ( fAllowTextRelocs ) {
4726 if ( (fArchitecture == CPU_TYPE_X86_64) && (fOutputKind != kKextBundle) ) {
4727 warning("-read_only_relocs cannot be used with x86_64");
4728 fAllowTextRelocs = false;
4729 }
4730 }
4731
4732 // check -mark_auto_dead_strip is only used with dylibs
4733 if ( fMarkDeadStrippableDylib ) {
4734 if ( fOutputKind != Options::kDynamicLibrary ) {
4735 warning("-mark_auto_dead_strip can only be used when creating a dylib");
4736 fMarkDeadStrippableDylib = false;
4737 }
4738 }
4739
4740 // -force_cpusubtype_ALL is not supported for ARM
4741 if ( fForceSubtypeAll ) {
4742 if ( fArchitecture == CPU_TYPE_ARM ) {
4743 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
4744 }
4745 }
4746
4747 // -reexported_symbols_list can only be used with -dynamiclib
4748 if ( !fReExportSymbols.empty() ) {
4749 if ( fOutputKind != Options::kDynamicLibrary )
4750 throw "-reexported_symbols_list can only used used when created dynamic libraries";
4751 if ( !minOS(ld::mac10_7, ld::iOS_4_2) )
4752 throw "targeted OS version does not support -reexported_symbols_list";
4753 }
4754
4755 // -dyld_env can only be used with main executables
4756 if ( (fOutputKind != Options::kDynamicExecutable) && (fDyldEnvironExtras.size() != 0) )
4757 throw "-dyld_env can only used used when created main executables";
4758
4759 // -segment_order can only be used with -preload
4760 if ( !fSegmentOrder.empty() && (fOutputKind != Options::kPreload) )
4761 throw "-segment_order can only used used with -preload output";
4762
4763 // <rdar://problem/17598404> warn if building an embedded iOS dylib for pre-iOS 8
4764 if ( (fOutputKind == Options::kDynamicLibrary) && (fIOSVersionMin != ld::iOSVersionUnset) && (fDylibInstallName != NULL) ) {
4765 if ( (fIOSVersionMin < ld::iOS_8_0) && (fDylibInstallName[0] == '@') )
4766 warning("embedded dylibs/frameworks only run on iOS 8 or later");
4767 }
4768 }
4769
4770
4771 void Options::checkForClassic(int argc, const char* argv[])
4772 {
4773 // scan options
4774 bool archFound = false;
4775 bool staticFound = false;
4776 bool dtraceFound = false;
4777 bool kextFound = false;
4778 bool rFound = false;
4779 bool creatingMachKernel = false;
4780 bool newLinker = false;
4781
4782 // build command line buffer in case ld crashes
4783 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
4784 CRSetCrashLogMessage(crashreporterBuffer);
4785 #endif
4786 const char* srcRoot = getenv("SRCROOT");
4787 if ( srcRoot != NULL ) {
4788 strlcpy(crashreporterBuffer, "SRCROOT=", crashreporterBufferSize);
4789 strlcat(crashreporterBuffer, srcRoot, crashreporterBufferSize);
4790 strlcat(crashreporterBuffer, "\n", crashreporterBufferSize);
4791 }
4792 #ifdef LD_VERS
4793 strlcat(crashreporterBuffer, LD_VERS, crashreporterBufferSize);
4794 strlcat(crashreporterBuffer, "\n", crashreporterBufferSize);
4795 #endif
4796 strlcat(crashreporterBuffer, "ld ", crashreporterBufferSize);
4797 for(int i=1; i < argc; ++i) {
4798 strlcat(crashreporterBuffer, argv[i], crashreporterBufferSize);
4799 strlcat(crashreporterBuffer, " ", crashreporterBufferSize);
4800 }
4801
4802 for(int i=0; i < argc; ++i) {
4803 const char* arg = argv[i];
4804 if ( arg[0] == '-' ) {
4805 if ( strcmp(arg, "-arch") == 0 ) {
4806 parseArch(argv[++i]);
4807 archFound = true;
4808 }
4809 else if ( strcmp(arg, "-static") == 0 ) {
4810 staticFound = true;
4811 }
4812 else if ( strcmp(arg, "-kext") == 0 ) {
4813 kextFound = true;
4814 }
4815 else if ( strcmp(arg, "-dtrace") == 0 ) {
4816 dtraceFound = true;
4817 }
4818 else if ( strcmp(arg, "-r") == 0 ) {
4819 rFound = true;
4820 }
4821 else if ( strcmp(arg, "-new_linker") == 0 ) {
4822 newLinker = true;
4823 }
4824 else if ( strcmp(arg, "-classic_linker") == 0 ) {
4825 // ld_classic does not understand this option, so remove it
4826 for(int j=i; j < argc; ++j)
4827 argv[j] = argv[j+1];
4828 warning("using ld_classic");
4829 this->gotoClassicLinker(argc-1, argv);
4830 }
4831 else if ( strcmp(arg, "-o") == 0 ) {
4832 const char* outfile = argv[++i];
4833 if ( (outfile != NULL) && (strstr(outfile, "/mach_kernel") != NULL) )
4834 creatingMachKernel = true;
4835 }
4836 }
4837 }
4838 }
4839
4840 void Options::gotoClassicLinker(int argc, const char* argv[])
4841 {
4842 argv[0] = "ld_classic";
4843 // ld_classic does not support -iphoneos_version_min, so change
4844 for(int j=0; j < argc; ++j) {
4845 if ( (strcmp(argv[j], "-iphoneos_version_min") == 0) || (strcmp(argv[j], "-ios_version_min") == 0) ) {
4846 argv[j] = "-macosx_version_min";
4847 if ( j < argc-1 )
4848 argv[j+1] = "10.5";
4849 break;
4850 }
4851 }
4852 // ld classic does not understand -kext (change to -static -r)
4853 for(int j=0; j < argc; ++j) {
4854 if ( strcmp(argv[j], "-kext") == 0)
4855 argv[j] = "-r";
4856 else if ( strcmp(argv[j], "-dynamic") == 0)
4857 argv[j] = "-static";
4858 }
4859 // ld classic does not understand -demangle
4860 for(int j=0; j < argc; ++j) {
4861 if ( strcmp(argv[j], "-demangle") == 0)
4862 argv[j] = "-noprebind";
4863 }
4864 // in -v mode, print command line passed to ld_classic
4865 for(int i=0; i < argc; ++i) {
4866 if ( strcmp(argv[i], "-v") == 0 ) {
4867 for(int j=0; j < argc; ++j)
4868 printf("%s ", argv[j]);
4869 printf("\n");
4870 break;
4871 }
4872 }
4873 char rawPath[PATH_MAX];
4874 char path[PATH_MAX];
4875 uint32_t bufSize = PATH_MAX;
4876 if ( _NSGetExecutablePath(rawPath, &bufSize) != -1 ) {
4877 if ( realpath(rawPath, path) != NULL ) {
4878 char* lastSlash = strrchr(path, '/');
4879 if ( lastSlash != NULL ) {
4880 strcpy(lastSlash+1, "ld_classic");
4881 argv[0] = path;
4882 execvp(path, (char**)argv);
4883 }
4884 }
4885 }
4886 // in case of error in above, try searching for ld_classic via PATH
4887 execvp(argv[0], (char**)argv);
4888 fprintf(stderr, "can't exec ld_classic\n");
4889 exit(1);
4890 }
4891
4892
4893 // Note, returned string buffer is own by this function.
4894 // It should not be freed
4895 // It will be reused, so clients need to strdup() if they want
4896 // to use it long term.
4897 const char* Options::demangleSymbol(const char* sym) const
4898 {
4899 // only try to demangle symbols if -demangle on command line
4900 if ( !fDemangle )
4901 return sym;
4902
4903 // only try to demangle symbols that look like C++ symbols
4904 if ( strncmp(sym, "__Z", 3) != 0 )
4905 return sym;
4906
4907 static size_t size = 1024;
4908 static char* buff = (char*)malloc(size);
4909 int status;
4910
4911 char* result = abi::__cxa_demangle(&sym[1], buff, &size, &status);
4912 if ( result != NULL ) {
4913 // if demangling successful, keep buffer for next demangle
4914 buff = result;
4915 return buff;
4916 }
4917 return sym;
4918 }
4919
4920
4921 void Options::dumpDependency(uint8_t opcode, const char* path) const
4922 {
4923 if ( !this->dumpDependencyInfo() )
4924 return;
4925
4926 // one time open() of -dependency_info file
4927 if ( fDependencyFileDescriptor == -1 ) {
4928 fDependencyFileDescriptor = open(this->dependencyInfoPath(), O_WRONLY | O_TRUNC | O_CREAT, 0666);
4929 if ( fDependencyFileDescriptor == -1 )
4930 throwf("Could not open or create -dependency_info file: %s", this->dependencyInfoPath());
4931
4932 // write header
4933 uint8_t version = depLinkerVersion;
4934 if ( write(fDependencyFileDescriptor, &version, 1) == -1 )
4935 throwf("write() to -dependency_info failed, errno=%d", errno);
4936 extern const char ldVersionString[];
4937 if ( write(fDependencyFileDescriptor, ldVersionString, strlen(ldVersionString)+1) == -1 )
4938 throwf("write() to -dependency_info failed, errno=%d", errno);
4939 }
4940
4941 char realPath[PATH_MAX];
4942 if ( path[0] != '/' ) {
4943 if ( realpath(path, realPath) != NULL ) {
4944 path = realPath;
4945 }
4946 }
4947
4948 if ( write(fDependencyFileDescriptor, &opcode, 1) == -1 )
4949 throwf("write() to -dependency_info failed, errno=%d", errno);
4950 if ( write(fDependencyFileDescriptor, path, strlen(path)+1) == -1 )
4951 throwf("write() to -dependency_info failed, errno=%d", errno);
4952
4953 //fprintf(stderr, "0x%02X %s\n", opcode, path);
4954 }
4955
4956
4957