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