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