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