]> git.saurik.com Git - apple/ld64.git/blob - src/ld/Options.cpp
492d140b4c780eb9b8d695589ad6347c6a12ac85
[apple/ld64.git] / src / ld / Options.cpp
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2005-2008 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 <mach-o/dyld.h>
30 #include <fcntl.h>
31 #include <vector>
32
33 #include "configure.h"
34 #include "Options.h"
35 #include "Architectures.hpp"
36 #include "MachOFileAbstraction.hpp"
37
38 extern void printLTOVersion(Options &opts);
39
40 // magic to place command line in crash reports
41 extern "C" char* __crashreporter_info__;
42 static char crashreporterBuffer[1000];
43 char* __crashreporter_info__ = crashreporterBuffer;
44
45 static bool sEmitWarnings = true;
46 static const char* sWarningsSideFilePath = NULL;
47 static FILE* sWarningsSideFile = NULL;
48
49 void warning(const char* format, ...)
50 {
51 if ( sEmitWarnings ) {
52 va_list list;
53 if ( sWarningsSideFilePath != NULL ) {
54 if ( sWarningsSideFile == NULL )
55 sWarningsSideFile = fopen(sWarningsSideFilePath, "a");
56 }
57 va_start(list, format);
58 fprintf(stderr, "ld: warning: ");
59 vfprintf(stderr, format, list);
60 fprintf(stderr, "\n");
61 if ( sWarningsSideFile != NULL ) {
62 fprintf(sWarningsSideFile, "ld: warning: ");
63 vfprintf(sWarningsSideFile, format, list);
64 fprintf(sWarningsSideFile, "\n");
65 fflush(sWarningsSideFile);
66 }
67 va_end(list);
68 }
69 }
70
71 void throwf(const char* format, ...)
72 {
73 va_list list;
74 char* p;
75 va_start(list, format);
76 vasprintf(&p, format, list);
77 va_end(list);
78
79 const char* t = p;
80 throw t;
81 }
82
83 Options::Options(int argc, const char* argv[])
84 : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0), fOutputKind(kDynamicExecutable),
85 fHasPreferredSubType(false), fPrebind(false), fBindAtLoad(false), fKeepPrivateExterns(false),
86 fNeedsModuleTable(false), fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false),
87 fInterposeMode(kInterposeNone), fDeadStrip(kDeadStripOff), fNameSpace(kTwoLevelNameSpace),
88 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL), fFinalName(NULL), fEntryName("start"), fBaseAddress(0),
89 fBaseWritableAddress(0), fSplitSegs(false),
90 fExportMode(kExportDefault), fLibrarySearchMode(kSearchAllDirsForDylibsThenAllDirsForArchives),
91 fUndefinedTreatment(kUndefinedError), fMessagesPrefixedWithArchitecture(false),
92 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak),
93 fClientName(NULL),
94 fUmbrellaName(NULL), fInitFunctionName(NULL), fDotOutputFile(NULL), fExecutablePath(NULL),
95 fBundleLoader(NULL), fDtraceScriptName(NULL), fSegAddrTablePath(NULL), fMapPath(NULL),
96 fZeroPageSize(ULLONG_MAX), fStackSize(0), fStackAddr(0), fExecutableStack(false),
97 fMinimumHeaderPad(32), fSegmentAlignment(4096),
98 fCommonsMode(kCommonsIgnoreDylibs), fUUIDMode(kUUIDContent), fLocalSymbolHandling(kLocalSymbolsAll), fWarnCommons(false),
99 fVerbose(false), fKeepRelocations(false), fWarnStabs(false),
100 fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
101 fSharedRegionEligible(false), fPrintOrderFileStatistics(false),
102 fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false),
103 fDisablePositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
104 fDeadStripDylibs(false), fAllowTextRelocs(false), fWarnTextRelocs(false),
105 fUsingLazyDylibLinking(false), fEncryptable(true),
106 fOrderData(true), fMarkDeadStrippableDylib(false),
107 fMakeClassicDyldInfo(true), fMakeCompressedDyldInfo(true), fAllowCpuSubtypeMismatches(false),
108 fUseSimplifiedDylibReExports(false), fObjCABIVersion2POverride(false), fSaveTempFiles(false)
109 {
110 this->checkForClassic(argc, argv);
111 this->parsePreCommandLineEnvironmentSettings();
112 this->parse(argc, argv);
113 this->parsePostCommandLineEnvironmentSettings();
114 this->reconfigureDefaults();
115 this->checkIllegalOptionCombinations();
116 }
117
118 Options::~Options()
119 {
120 }
121
122 const ObjectFile::ReaderOptions& Options::readerOptions()
123 {
124 return fReaderOptions;
125 }
126
127
128 const char* Options::getOutputFilePath()
129 {
130 return fOutputFile;
131 }
132
133 std::vector<Options::FileInfo>& Options::getInputFiles()
134 {
135 return fInputFiles;
136 }
137
138 Options::OutputKind Options::outputKind()
139 {
140 return fOutputKind;
141 }
142
143 bool Options::bindAtLoad()
144 {
145 return fBindAtLoad;
146 }
147
148 bool Options::prebind()
149 {
150 return fPrebind;
151 }
152
153 bool Options::fullyLoadArchives()
154 {
155 return fReaderOptions.fFullyLoadArchives;
156 }
157
158 Options::NameSpace Options::nameSpace()
159 {
160 return fNameSpace;
161 }
162
163 const char* Options::installPath()
164 {
165 if ( fDylibInstallName != NULL )
166 return fDylibInstallName;
167 else if ( fFinalName != NULL )
168 return fFinalName;
169 else
170 return fOutputFile;
171 }
172
173 uint32_t Options::currentVersion()
174 {
175 return fDylibCurrentVersion;
176 }
177
178 uint32_t Options::compatibilityVersion()
179 {
180 return fDylibCompatVersion;
181 }
182
183 const char* Options::entryName()
184 {
185 return fEntryName;
186 }
187
188 uint64_t Options::baseAddress()
189 {
190 return fBaseAddress;
191 }
192
193 bool Options::keepPrivateExterns()
194 {
195 return fKeepPrivateExterns;
196 }
197
198 bool Options::interposable(const char* name)
199 {
200 switch ( fInterposeMode ) {
201 case kInterposeNone:
202 return false;
203 case kInterposeAllExternal:
204 return true;
205 case kInterposeSome:
206 return fInterposeList.contains(name);
207 }
208 throw "internal error";
209 }
210
211 bool Options::needsModuleTable()
212 {
213 return fNeedsModuleTable;
214 }
215
216 bool Options::ignoreOtherArchInputFiles()
217 {
218 return fIgnoreOtherArchFiles;
219 }
220
221 bool Options::forceCpuSubtypeAll()
222 {
223 return fForceSubtypeAll;
224 }
225
226 bool Options::traceDylibs()
227 {
228 return fReaderOptions.fTraceDylibs;
229 }
230
231 bool Options::traceArchives()
232 {
233 return fReaderOptions.fTraceArchives;
234 }
235
236 Options::UndefinedTreatment Options::undefinedTreatment()
237 {
238 return fUndefinedTreatment;
239 }
240
241 Options::WeakReferenceMismatchTreatment Options::weakReferenceMismatchTreatment()
242 {
243 return fWeakReferenceMismatchTreatment;
244 }
245
246 const char* Options::umbrellaName()
247 {
248 return fUmbrellaName;
249 }
250
251 std::vector<const char*>& Options::allowableClients()
252 {
253 return fAllowableClients;
254 }
255
256 const char* Options::clientName()
257 {
258 return fClientName;
259 }
260
261 uint64_t Options::zeroPageSize()
262 {
263 return fZeroPageSize;
264 }
265
266 bool Options::hasCustomStack()
267 {
268 return (fStackSize != 0);
269 }
270
271 uint64_t Options::customStackSize()
272 {
273 return fStackSize;
274 }
275
276 uint64_t Options::customStackAddr()
277 {
278 return fStackAddr;
279 }
280
281 bool Options::hasExecutableStack()
282 {
283 return fExecutableStack;
284 }
285
286 std::vector<const char*>& Options::initialUndefines()
287 {
288 return fInitialUndefines;
289 }
290
291 bool Options::printWhyLive(const char* symbolName)
292 {
293 return ( fWhyLive.find(symbolName) != fWhyLive.end() );
294 }
295
296
297 const char* Options::initFunctionName()
298 {
299 return fInitFunctionName;
300 }
301
302 const char* Options::dotOutputFile()
303 {
304 return fDotOutputFile;
305 }
306
307 bool Options::hasExportRestrictList()
308 {
309 return (fExportMode != kExportDefault);
310 }
311
312 bool Options::hasExportMaskList()
313 {
314 return (fExportMode == kExportSome);
315 }
316
317
318 bool Options::hasWildCardExportRestrictList()
319 {
320 // has -exported_symbols_list which contains some wildcards
321 return ((fExportMode == kExportSome) && fExportSymbols.hasWildCards());
322 }
323
324
325 bool Options::allGlobalsAreDeadStripRoots()
326 {
327 // -exported_symbols_list means globals are not exported by default
328 if ( fExportMode == kExportSome )
329 return false;
330 //
331 switch ( fOutputKind ) {
332 case Options::kDynamicExecutable:
333 case Options::kStaticExecutable:
334 case Options::kPreload:
335 // by default unused globals in a main executable are stripped
336 return false;
337 case Options::kDynamicLibrary:
338 case Options::kDynamicBundle:
339 case Options::kObjectFile:
340 case Options::kDyld:
341 case Options::kKextBundle:
342 return true;
343 }
344 return false;
345 }
346
347 uint32_t Options::minimumHeaderPad()
348 {
349 return fMinimumHeaderPad;
350 }
351
352 std::vector<Options::ExtraSection>& Options::extraSections()
353 {
354 return fExtraSections;
355 }
356
357 std::vector<Options::SectionAlignment>& Options::sectionAlignments()
358 {
359 return fSectionAlignments;
360 }
361
362 Options::CommonsMode Options::commonsMode()
363 {
364 return fCommonsMode;
365 }
366
367 bool Options::warnCommons()
368 {
369 return fWarnCommons;
370 }
371
372 bool Options::keepRelocations()
373 {
374 return fKeepRelocations;
375 }
376
377 bool Options::warnStabs()
378 {
379 return fWarnStabs;
380 }
381
382 const char* Options::executablePath()
383 {
384 return fExecutablePath;
385 }
386
387 Options::DeadStripMode Options::deadStrip()
388 {
389 return fDeadStrip;
390 }
391
392 bool Options::hasExportedSymbolOrder()
393 {
394 return (fExportSymbolsOrder.size() > 0);
395 }
396
397 bool Options::exportedSymbolOrder(const char* sym, unsigned int* order)
398 {
399 NameToOrder::iterator pos = fExportSymbolsOrder.find(sym);
400 if ( pos != fExportSymbolsOrder.end() ) {
401 *order = pos->second;
402 return true;
403 }
404 else {
405 *order = 0xFFFFFFFF;
406 return false;
407 }
408 }
409
410 void Options::loadSymbolOrderFile(const char* fileOfExports, NameToOrder& orderMapping)
411 {
412 // read in whole file
413 int fd = ::open(fileOfExports, O_RDONLY, 0);
414 if ( fd == -1 )
415 throwf("can't open -exported_symbols_order file: %s", fileOfExports);
416 struct stat stat_buf;
417 ::fstat(fd, &stat_buf);
418 char* p = (char*)malloc(stat_buf.st_size);
419 if ( p == NULL )
420 throwf("can't process -exported_symbols_order file: %s", fileOfExports);
421
422 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
423 throwf("can't read -exported_symbols_order file: %s", fileOfExports);
424
425 ::close(fd);
426
427 // parse into symbols and add to hash_set
428 unsigned int count = 0;
429 char * const end = &p[stat_buf.st_size];
430 enum { lineStart, inSymbol, inComment } state = lineStart;
431 char* symbolStart = NULL;
432 for (char* s = p; s < end; ++s ) {
433 switch ( state ) {
434 case lineStart:
435 if ( *s =='#' ) {
436 state = inComment;
437 }
438 else if ( !isspace(*s) ) {
439 state = inSymbol;
440 symbolStart = s;
441 }
442 break;
443 case inSymbol:
444 if ( (*s == '\n') || (*s == '\r') ) {
445 *s = '\0';
446 // removing any trailing spaces
447 char* last = s-1;
448 while ( isspace(*last) ) {
449 *last = '\0';
450 --last;
451 }
452 orderMapping[symbolStart] = ++count;
453 symbolStart = NULL;
454 state = lineStart;
455 }
456 break;
457 case inComment:
458 if ( (*s == '\n') || (*s == '\r') )
459 state = lineStart;
460 break;
461 }
462 }
463 if ( state == inSymbol ) {
464 warning("missing line-end at end of file \"%s\"", fileOfExports);
465 int len = end-symbolStart+1;
466 char* temp = new char[len];
467 strlcpy(temp, symbolStart, len);
468
469 // remove any trailing spaces
470 char* last = &temp[len-2];
471 while ( isspace(*last) ) {
472 *last = '\0';
473 --last;
474 }
475 orderMapping[temp] = ++count;
476 }
477
478 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
479 }
480
481
482 bool Options::shouldExport(const char* symbolName)
483 {
484 switch (fExportMode) {
485 case kExportSome:
486 return fExportSymbols.contains(symbolName);
487 case kDontExportSome:
488 return ! fDontExportSymbols.contains(symbolName);
489 case kExportDefault:
490 return true;
491 }
492 throw "internal error";
493 }
494
495 bool Options::keepLocalSymbol(const char* symbolName)
496 {
497 switch (fLocalSymbolHandling) {
498 case kLocalSymbolsAll:
499 return true;
500 case kLocalSymbolsNone:
501 return false;
502 case kLocalSymbolsSelectiveInclude:
503 return fLocalSymbolsIncluded.contains(symbolName);
504 case kLocalSymbolsSelectiveExclude:
505 return ! fLocalSymbolsExcluded.contains(symbolName);
506 }
507 throw "internal error";
508 }
509
510 void Options::parseArch(const char* architecture)
511 {
512 if ( architecture == NULL )
513 throw "-arch must be followed by an architecture string";
514 if ( strcmp(architecture, "ppc") == 0 ) {
515 fArchitecture = CPU_TYPE_POWERPC;
516 fSubArchitecture = CPU_SUBTYPE_POWERPC_ALL;
517 }
518 else if ( strcmp(architecture, "ppc64") == 0 ) {
519 fArchitecture = CPU_TYPE_POWERPC64;
520 fSubArchitecture = CPU_SUBTYPE_POWERPC_ALL;
521 }
522 else if ( strcmp(architecture, "i386") == 0 ) {
523 fArchitecture = CPU_TYPE_I386;
524 fSubArchitecture = CPU_SUBTYPE_I386_ALL;
525 }
526 else if ( strcmp(architecture, "x86_64") == 0 ) {
527 fArchitecture = CPU_TYPE_X86_64;
528 fSubArchitecture = CPU_SUBTYPE_X86_64_ALL;
529 }
530 else if ( strcmp(architecture, "arm") == 0 ) {
531 fArchitecture = CPU_TYPE_ARM;
532 fSubArchitecture = CPU_SUBTYPE_ARM_ALL;
533 }
534 // compatibility support for cpu-sub-types
535 else if ( strcmp(architecture, "ppc750") == 0 ) {
536 fArchitecture = CPU_TYPE_POWERPC;
537 fSubArchitecture = CPU_SUBTYPE_POWERPC_750;
538 fHasPreferredSubType = true;
539 }
540 else if ( strcmp(architecture, "ppc7400") == 0 ) {
541 fArchitecture = CPU_TYPE_POWERPC;
542 fSubArchitecture = CPU_SUBTYPE_POWERPC_7400;
543 fHasPreferredSubType = true;
544 }
545 else if ( strcmp(architecture, "ppc7450") == 0 ) {
546 fArchitecture = CPU_TYPE_POWERPC;
547 fSubArchitecture = CPU_SUBTYPE_POWERPC_7450;
548 fHasPreferredSubType = true;
549 }
550 else if ( strcmp(architecture, "ppc970") == 0 ) {
551 fArchitecture = CPU_TYPE_POWERPC;
552 fSubArchitecture = CPU_SUBTYPE_POWERPC_970;
553 fHasPreferredSubType = true;
554 }
555 else if ( strcmp(architecture, "armv6") == 0 ) {
556 fArchitecture = CPU_TYPE_ARM;
557 fSubArchitecture = CPU_SUBTYPE_ARM_V6;
558 fHasPreferredSubType = true;
559 }
560 else if ( strcmp(architecture, "armv5") == 0 ) {
561 fArchitecture = CPU_TYPE_ARM;
562 fSubArchitecture = CPU_SUBTYPE_ARM_V5TEJ;
563 fHasPreferredSubType = true;
564 }
565 else if ( strcmp(architecture, "armv4t") == 0 ) {
566 fArchitecture = CPU_TYPE_ARM;
567 fSubArchitecture = CPU_SUBTYPE_ARM_V4T;
568 fHasPreferredSubType = true;
569 }
570 else if ( strcmp(architecture, "xscale") == 0 ) {
571 fArchitecture = CPU_TYPE_ARM;
572 fSubArchitecture = CPU_SUBTYPE_ARM_XSCALE;
573 fHasPreferredSubType = true;
574 }
575 else if ( strcmp(architecture, "armv7") == 0 ) {
576 fArchitecture = CPU_TYPE_ARM;
577 fSubArchitecture = CPU_SUBTYPE_ARM_V7;
578 fHasPreferredSubType = true;
579 }
580 else
581 throwf("unknown/unsupported architecture name for: -arch %s", architecture);
582 }
583
584 bool Options::checkForFile(const char* format, const char* dir, const char* rootName, FileInfo& result)
585 {
586 struct stat statBuffer;
587 char possiblePath[strlen(dir)+strlen(rootName)+strlen(format)+8];
588 sprintf(possiblePath, format, dir, rootName);
589 bool found = (stat(possiblePath, &statBuffer) == 0);
590 if ( fTraceDylibSearching )
591 printf("[Logging for XBS]%sfound library: '%s'\n", (found ? " " : " not "), possiblePath);
592 if ( found ) {
593 result.path = strdup(possiblePath);
594 result.fileLen = statBuffer.st_size;
595 result.modTime = statBuffer.st_mtime;
596 return true;
597 }
598 return false;
599 }
600
601
602 Options::FileInfo Options::findLibrary(const char* rootName, bool dylibsOnly)
603 {
604 FileInfo result;
605 const int rootNameLen = strlen(rootName);
606 // if rootName ends in .o there is no .a vs .dylib choice
607 if ( (rootNameLen > 3) && (strcmp(&rootName[rootNameLen-2], ".o") == 0) ) {
608 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
609 it != fLibrarySearchPaths.end();
610 it++) {
611 const char* dir = *it;
612 if ( checkForFile("%s/%s", dir, rootName, result) )
613 return result;
614 }
615 }
616 else {
617 bool lookForDylibs = ( fOutputKind != Options::kDyld);
618 switch ( fLibrarySearchMode ) {
619 case kSearchAllDirsForDylibsThenAllDirsForArchives:
620 // first look in all directories for just for dylibs
621 if ( lookForDylibs ) {
622 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
623 it != fLibrarySearchPaths.end();
624 it++) {
625 const char* dir = *it;
626 if ( checkForFile("%s/lib%s.dylib", dir, rootName, result) )
627 return result;
628 }
629 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
630 it != fLibrarySearchPaths.end();
631 it++) {
632 const char* dir = *it;
633 if ( checkForFile("%s/lib%s.so", dir, rootName, result) )
634 return result;
635 }
636 }
637 // next look in all directories for just for archives
638 if ( !dylibsOnly ) {
639 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
640 it != fLibrarySearchPaths.end();
641 it++) {
642 const char* dir = *it;
643 if ( checkForFile("%s/lib%s.a", dir, rootName, result) )
644 return result;
645 }
646 }
647 break;
648
649 case kSearchDylibAndArchiveInEachDir:
650 // look in each directory for just for a dylib then for an archive
651 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
652 it != fLibrarySearchPaths.end();
653 it++) {
654 const char* dir = *it;
655 if ( lookForDylibs && checkForFile("%s/lib%s.dylib", dir, rootName, result) )
656 return result;
657 if ( lookForDylibs && checkForFile("%s/lib%s.so", dir, rootName, result) )
658 return result;
659 if ( !dylibsOnly && checkForFile("%s/lib%s.a", dir, rootName, result) )
660 return result;
661 }
662 break;
663 }
664 }
665 throwf("library not found for -l%s", rootName);
666 }
667
668 Options::FileInfo Options::findFramework(const char* frameworkName)
669 {
670 if ( frameworkName == NULL )
671 throw "-framework missing next argument";
672 char temp[strlen(frameworkName)+1];
673 strcpy(temp, frameworkName);
674 const char* name = temp;
675 const char* suffix = NULL;
676 char* comma = strchr(temp, ',');
677 if ( comma != NULL ) {
678 *comma = '\0';
679 suffix = &comma[1];
680 }
681 return findFramework(name, suffix);
682 }
683
684 Options::FileInfo Options::findFramework(const char* rootName, const char* suffix)
685 {
686 struct stat statBuffer;
687 for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin();
688 it != fFrameworkSearchPaths.end();
689 it++) {
690 // ??? Shouldn't we be using String here and just initializing it?
691 // ??? Use str.c_str () to pull out the string for the stat call.
692 const char* dir = *it;
693 char possiblePath[PATH_MAX];
694 strcpy(possiblePath, dir);
695 strcat(possiblePath, "/");
696 strcat(possiblePath, rootName);
697 strcat(possiblePath, ".framework/");
698 strcat(possiblePath, rootName);
699 if ( suffix != NULL ) {
700 char realPath[PATH_MAX];
701 // no symlink in framework to suffix variants, so follow main symlink
702 if ( realpath(possiblePath, realPath) != NULL ) {
703 strcpy(possiblePath, realPath);
704 strcat(possiblePath, suffix);
705 }
706 }
707 bool found = (stat(possiblePath, &statBuffer) == 0);
708 if ( fTraceDylibSearching )
709 printf("[Logging for XBS]%sfound framework: '%s'\n",
710 (found ? " " : " not "), possiblePath);
711 if ( found ) {
712 FileInfo result;
713 result.path = strdup(possiblePath);
714 result.fileLen = statBuffer.st_size;
715 result.modTime = statBuffer.st_mtime;
716 return result;
717 }
718 }
719 // try without suffix
720 if ( suffix != NULL )
721 return findFramework(rootName, NULL);
722 else
723 throwf("framework not found %s", rootName);
724 }
725
726 Options::FileInfo Options::findFile(const char* path)
727 {
728 FileInfo result;
729 struct stat statBuffer;
730
731 // if absolute path and not a .o file, the use SDK prefix
732 if ( (path[0] == '/') && (strcmp(&path[strlen(path)-2], ".o") != 0) ) {
733 const int pathLen = strlen(path);
734 for (std::vector<const char*>::iterator it = fSDKPaths.begin(); it != fSDKPaths.end(); it++) {
735 // ??? Shouldn't we be using String here?
736 const char* sdkPathDir = *it;
737 const int sdkPathDirLen = strlen(sdkPathDir);
738 char possiblePath[sdkPathDirLen+pathLen+4];
739 strcpy(possiblePath, sdkPathDir);
740 if ( possiblePath[sdkPathDirLen-1] == '/' )
741 possiblePath[sdkPathDirLen-1] = '\0';
742 strcat(possiblePath, path);
743 if ( stat(possiblePath, &statBuffer) == 0 ) {
744 result.path = strdup(possiblePath);
745 result.fileLen = statBuffer.st_size;
746 result.modTime = statBuffer.st_mtime;
747 return result;
748 }
749 }
750 }
751 // try raw path
752 if ( stat(path, &statBuffer) == 0 ) {
753 result.path = strdup(path);
754 result.fileLen = statBuffer.st_size;
755 result.modTime = statBuffer.st_mtime;
756 return result;
757 }
758
759 // try @executable_path substitution
760 if ( (strncmp(path, "@executable_path/", 17) == 0) && (fExecutablePath != NULL) ) {
761 char newPath[strlen(fExecutablePath) + strlen(path)];
762 strcpy(newPath, fExecutablePath);
763 char* addPoint = strrchr(newPath,'/');
764 if ( addPoint != NULL )
765 strcpy(&addPoint[1], &path[17]);
766 else
767 strcpy(newPath, &path[17]);
768 if ( stat(newPath, &statBuffer) == 0 ) {
769 result.path = strdup(newPath);
770 result.fileLen = statBuffer.st_size;
771 result.modTime = statBuffer.st_mtime;
772 return result;
773 }
774 }
775
776 // not found
777 throwf("file not found: %s", path);
778 }
779
780 Options::FileInfo Options::findFileUsingPaths(const char* path)
781 {
782 FileInfo result;
783
784 const char* lastSlash = strrchr(path, '/');
785 const char* leafName = (lastSlash == NULL) ? path : &lastSlash[1];
786
787 // Is this in a framework?
788 // /path/Foo.framework/Foo ==> true (Foo)
789 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
790 // /path/Foo.framework/Resources/Bar ==> false
791 bool isFramework = false;
792 if ( lastSlash != NULL ) {
793 char frameworkDir[strlen(leafName) + 20];
794 strcpy(frameworkDir, "/");
795 strcat(frameworkDir, leafName);
796 strcat(frameworkDir, ".framework/");
797 if ( strstr(path, frameworkDir) != NULL )
798 isFramework = true;
799 }
800
801 // These are abbreviated versions of the routines findFramework and findLibrary above
802 // because we already know the final name of the file that we're looking for and so
803 // don't need to try variations, just paths. We do need to add the additional bits
804 // onto the framework path though.
805 if ( isFramework ) {
806 for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin();
807 it != fFrameworkSearchPaths.end();
808 it++) {
809 const char* dir = *it;
810 char possiblePath[PATH_MAX];
811 strcpy(possiblePath, dir);
812 strcat(possiblePath, "/");
813 strcat(possiblePath, leafName);
814 strcat(possiblePath, ".framework");
815
816 //fprintf(stderr,"Finding Framework: %s/%s, leafName=%s\n", possiblePath, leafName, leafName);
817 if ( checkForFile("%s/%s", possiblePath, leafName, result) )
818 return result;
819 }
820 }
821 else {
822 // if this is a .dylib inside a framework, do not search -L paths
823 // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
824 int leafLen = strlen(leafName);
825 bool embeddedDylib = ( (leafLen > 6)
826 && (strcmp(&leafName[leafLen-6], ".dylib") == 0)
827 && (strstr(path, ".framework/") != NULL) );
828 if ( !embeddedDylib ) {
829 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
830 it != fLibrarySearchPaths.end();
831 it++) {
832 const char* dir = *it;
833 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
834 if ( checkForFile("%s/%s", dir, leafName, result) )
835 return result;
836 }
837 }
838 }
839
840 // If we didn't find it fall back to findFile.
841 return findFile(path);
842 }
843
844
845 void Options::parseSegAddrTable(const char* segAddrPath, const char* installPath)
846 {
847 FILE* file = fopen(segAddrPath, "r");
848 if ( file == NULL ) {
849 warning("-seg_addr_table file cannot be read: %s", segAddrPath);
850 return;
851 }
852
853 char path[PATH_MAX];
854 uint64_t firstColumAddress = 0;
855 uint64_t secondColumAddress = 0;
856 bool hasSecondColumn = false;
857 while ( fgets(path, PATH_MAX, file) != NULL ) {
858 path[PATH_MAX-1] = '\0';
859 char* eol = strchr(path, '\n');
860 if ( eol != NULL )
861 *eol = '\0';
862 // ignore lines not starting with 0x number
863 if ( (path[0] == '0') && (path[1] == 'x') ) {
864 char* p;
865 firstColumAddress = strtoull(path, &p, 16);
866 while ( isspace(*p) )
867 ++p;
868 // see if second column is a number
869 if ( (p[0] == '0') && (p[1] == 'x') ) {
870 secondColumAddress = strtoull(p, &p, 16);
871 hasSecondColumn = true;
872 while ( isspace(*p) )
873 ++p;
874 }
875 while ( isspace(*p) )
876 ++p;
877 if ( p[0] == '/' ) {
878 // remove any trailing whitespace
879 for(char* end = eol-1; (end > p) && isspace(*end); --end)
880 *end = '\0';
881 // see if this line is for the dylib being linked
882 if ( strcmp(p, installPath) == 0 ) {
883 fBaseAddress = firstColumAddress;
884 if ( hasSecondColumn ) {
885 fBaseWritableAddress = secondColumAddress;
886 fSplitSegs = true;
887 }
888 break; // out of while loop
889 }
890 }
891 }
892 }
893
894 fclose(file);
895 }
896
897 void Options::loadFileList(const char* fileOfPaths)
898 {
899 FILE* file;
900 const char* comma = strrchr(fileOfPaths, ',');
901 const char* prefix = NULL;
902 if ( comma != NULL ) {
903 // <rdar://problem/5907981> -filelist fails with comma in path
904 file = fopen(fileOfPaths, "r");
905 if ( file == NULL ) {
906 prefix = comma+1;
907 int realFileOfPathsLen = comma-fileOfPaths;
908 char realFileOfPaths[realFileOfPathsLen+1];
909 strncpy(realFileOfPaths,fileOfPaths, realFileOfPathsLen);
910 realFileOfPaths[realFileOfPathsLen] = '\0';
911 file = fopen(realFileOfPaths, "r");
912 if ( file == NULL )
913 throwf("-filelist file not found: %s\n", realFileOfPaths);
914 }
915 }
916 else {
917 file = fopen(fileOfPaths, "r");
918 if ( file == NULL )
919 throwf("-filelist file not found: %s\n", fileOfPaths);
920 }
921
922 char path[PATH_MAX];
923 while ( fgets(path, PATH_MAX, file) != NULL ) {
924 path[PATH_MAX-1] = '\0';
925 char* eol = strchr(path, '\n');
926 if ( eol != NULL )
927 *eol = '\0';
928 if ( prefix != NULL ) {
929 char builtPath[strlen(prefix)+strlen(path)+2];
930 strcpy(builtPath, prefix);
931 strcat(builtPath, "/");
932 strcat(builtPath, path);
933 fInputFiles.push_back(findFile(builtPath));
934 }
935 else {
936 fInputFiles.push_back(findFile(path));
937 }
938 }
939 fclose(file);
940 }
941
942 bool Options::SetWithWildcards::hasWildCards(const char* symbol)
943 {
944 // an exported symbol name containing *, ?, or [ requires wildcard matching
945 return ( strpbrk(symbol, "*?[") != NULL );
946 }
947
948 void Options::SetWithWildcards::insert(const char* symbol)
949 {
950 if ( hasWildCards(symbol) )
951 fWildCard.push_back(symbol);
952 else
953 fRegular.insert(symbol);
954 }
955
956 bool Options::SetWithWildcards::contains(const char* symbol)
957 {
958 // first look at hash table on non-wildcard symbols
959 if ( fRegular.find(symbol) != fRegular.end() )
960 return true;
961 // next walk list of wild card symbols looking for a match
962 for(std::vector<const char*>::iterator it = fWildCard.begin(); it != fWildCard.end(); ++it) {
963 if ( wildCardMatch(*it, symbol) )
964 return true;
965 }
966 return false;
967 }
968
969
970 bool Options::SetWithWildcards::inCharRange(const char*& p, unsigned char c)
971 {
972 ++p; // find end
973 const char* b = p;
974 while ( *p != '\0' ) {
975 if ( *p == ']') {
976 const char* e = p;
977 // found beginining [ and ending ]
978 unsigned char last = '\0';
979 for ( const char* s = b; s < e; ++s ) {
980 if ( *s == '-' ) {
981 unsigned char next = *(++s);
982 if ( (last <= c) && (c <= next) )
983 return true;
984 ++s;
985 }
986 else {
987 if ( *s == c )
988 return true;
989 last = *s;
990 }
991 }
992 return false;
993 }
994 ++p;
995 }
996 return false;
997 }
998
999 bool Options::SetWithWildcards::wildCardMatch(const char* pattern, const char* symbol)
1000 {
1001 const char* s = symbol;
1002 for (const char* p = pattern; *p != '\0'; ++p) {
1003 switch ( *p ) {
1004 case '*':
1005 if ( p[1] == '\0' )
1006 return true;
1007 for (const char* t = s; *t != '\0'; ++t) {
1008 if ( wildCardMatch(&p[1], t) )
1009 return true;
1010 }
1011 return false;
1012 case '?':
1013 if ( *s == '\0' )
1014 return false;
1015 ++s;
1016 break;
1017 case '[':
1018 if ( ! inCharRange(p, *s) )
1019 return false;
1020 ++s;
1021 break;
1022 default:
1023 if ( *s != *p )
1024 return false;
1025 ++s;
1026 }
1027 }
1028 return (*s == '\0');
1029 }
1030
1031
1032 void Options::loadExportFile(const char* fileOfExports, const char* option, SetWithWildcards& set)
1033 {
1034 // read in whole file
1035 int fd = ::open(fileOfExports, O_RDONLY, 0);
1036 if ( fd == -1 )
1037 throwf("can't open %s file: %s", option, fileOfExports);
1038 struct stat stat_buf;
1039 ::fstat(fd, &stat_buf);
1040 char* p = (char*)malloc(stat_buf.st_size);
1041 if ( p == NULL )
1042 throwf("can't process %s file: %s", option, fileOfExports);
1043
1044 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1045 throwf("can't read %s file: %s", option, fileOfExports);
1046
1047 ::close(fd);
1048
1049 // parse into symbols and add to hash_set
1050 char * const end = &p[stat_buf.st_size];
1051 enum { lineStart, inSymbol, inComment } state = lineStart;
1052 char* symbolStart = NULL;
1053 for (char* s = p; s < end; ++s ) {
1054 switch ( state ) {
1055 case lineStart:
1056 if ( *s =='#' ) {
1057 state = inComment;
1058 }
1059 else if ( !isspace(*s) ) {
1060 state = inSymbol;
1061 symbolStart = s;
1062 }
1063 break;
1064 case inSymbol:
1065 if ( (*s == '\n') || (*s == '\r') ) {
1066 *s = '\0';
1067 // removing any trailing spaces
1068 char* last = s-1;
1069 while ( isspace(*last) ) {
1070 *last = '\0';
1071 --last;
1072 }
1073 set.insert(symbolStart);
1074 symbolStart = NULL;
1075 state = lineStart;
1076 }
1077 break;
1078 case inComment:
1079 if ( (*s == '\n') || (*s == '\r') )
1080 state = lineStart;
1081 break;
1082 }
1083 }
1084 if ( state == inSymbol ) {
1085 warning("missing line-end at end of file \"%s\"", fileOfExports);
1086 int len = end-symbolStart+1;
1087 char* temp = new char[len];
1088 strlcpy(temp, symbolStart, len);
1089
1090 // remove any trailing spaces
1091 char* last = &temp[len-2];
1092 while ( isspace(*last) ) {
1093 *last = '\0';
1094 --last;
1095 }
1096 set.insert(temp);
1097 }
1098
1099 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
1100 }
1101
1102 void Options::parseAliasFile(const char* fileOfAliases)
1103 {
1104 // read in whole file
1105 int fd = ::open(fileOfAliases, O_RDONLY, 0);
1106 if ( fd == -1 )
1107 throwf("can't open alias file: %s", fileOfAliases);
1108 struct stat stat_buf;
1109 ::fstat(fd, &stat_buf);
1110 char* p = (char*)malloc(stat_buf.st_size+1);
1111 if ( p == NULL )
1112 throwf("can't process alias file: %s", fileOfAliases);
1113
1114 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1115 throwf("can't read alias file: %s", fileOfAliases);
1116 p[stat_buf.st_size] = '\n';
1117 ::close(fd);
1118
1119 // parse into symbols and add to fAliases
1120 ObjectFile::ReaderOptions::AliasPair pair;
1121 char * const end = &p[stat_buf.st_size+1];
1122 enum { lineStart, inRealName, inBetween, inAliasName, inComment } state = lineStart;
1123 int lineNumber = 1;
1124 for (char* s = p; s < end; ++s ) {
1125 switch ( state ) {
1126 case lineStart:
1127 if ( *s =='#' ) {
1128 state = inComment;
1129 }
1130 else if ( !isspace(*s) ) {
1131 state = inRealName;
1132 pair.realName = s;
1133 }
1134 break;
1135 case inRealName:
1136 if ( *s == '\n' ) {
1137 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber, fileOfAliases);
1138 ++lineNumber;
1139 state = lineStart;
1140 }
1141 else if ( isspace(*s) ) {
1142 *s = '\0';
1143 state = inBetween;
1144 }
1145 break;
1146 case inBetween:
1147 if ( *s == '\n' ) {
1148 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber, fileOfAliases);
1149 ++lineNumber;
1150 state = lineStart;
1151 }
1152 else if ( ! isspace(*s) ) {
1153 state = inAliasName;
1154 pair.alias = s;
1155 }
1156 break;
1157 case inAliasName:
1158 if ( *s =='#' ) {
1159 *s = '\0';
1160 // removing any trailing spaces
1161 char* last = s-1;
1162 while ( isspace(*last) ) {
1163 *last = '\0';
1164 --last;
1165 }
1166 fReaderOptions.fAliases.push_back(pair);
1167 state = inComment;
1168 }
1169 else if ( *s == '\n' ) {
1170 *s = '\0';
1171 // removing any trailing spaces
1172 char* last = s-1;
1173 while ( isspace(*last) ) {
1174 *last = '\0';
1175 --last;
1176 }
1177 fReaderOptions.fAliases.push_back(pair);
1178 state = lineStart;
1179 }
1180 break;
1181 case inComment:
1182 if ( *s == '\n' )
1183 state = lineStart;
1184 break;
1185 }
1186 }
1187
1188 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
1189 }
1190
1191
1192
1193 void Options::setUndefinedTreatment(const char* treatment)
1194 {
1195 if ( treatment == NULL )
1196 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
1197
1198 if ( strcmp(treatment, "warning") == 0 )
1199 fUndefinedTreatment = kUndefinedWarning;
1200 else if ( strcmp(treatment, "error") == 0 )
1201 fUndefinedTreatment = kUndefinedError;
1202 else if ( strcmp(treatment, "suppress") == 0 )
1203 fUndefinedTreatment = kUndefinedSuppress;
1204 else if ( strcmp(treatment, "dynamic_lookup") == 0 )
1205 fUndefinedTreatment = kUndefinedDynamicLookup;
1206 else
1207 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1208 }
1209
1210 Options::Treatment Options::parseTreatment(const char* treatment)
1211 {
1212 if ( treatment == NULL )
1213 return kNULL;
1214
1215 if ( strcmp(treatment, "warning") == 0 )
1216 return kWarning;
1217 else if ( strcmp(treatment, "error") == 0 )
1218 return kError;
1219 else if ( strcmp(treatment, "suppress") == 0 )
1220 return kSuppress;
1221 else
1222 return kInvalid;
1223 }
1224
1225 void Options::setMacOSXVersionMin(const char* version)
1226 {
1227 if ( version == NULL )
1228 throw "-macosx_version_min argument missing";
1229
1230 if ( (strncmp(version, "10.", 3) == 0) && isdigit(version[3]) ) {
1231 int num = version[3] - '0';
1232 switch ( num ) {
1233 case 0:
1234 case 1:
1235 fReaderOptions.fMacVersionMin = ObjectFile::ReaderOptions::k10_1;
1236 break;
1237 case 2:
1238 fReaderOptions.fMacVersionMin = ObjectFile::ReaderOptions::k10_2;
1239 break;
1240 case 3:
1241 fReaderOptions.fMacVersionMin = ObjectFile::ReaderOptions::k10_3;
1242 break;
1243 case 4:
1244 fReaderOptions.fMacVersionMin = ObjectFile::ReaderOptions::k10_4;
1245 break;
1246 case 5:
1247 fReaderOptions.fMacVersionMin = ObjectFile::ReaderOptions::k10_5;
1248 break;
1249 case 6:
1250 fReaderOptions.fMacVersionMin = ObjectFile::ReaderOptions::k10_6;
1251 break;
1252 case 7:
1253 fReaderOptions.fMacVersionMin = ObjectFile::ReaderOptions::k10_7;
1254 break;
1255 default:
1256 fReaderOptions.fMacVersionMin = ObjectFile::ReaderOptions::k10_7;
1257 break;
1258 }
1259 }
1260 else {
1261 warning("unknown option to -macosx_version_min, not 10.x");
1262 }
1263 }
1264
1265 void Options::setIPhoneVersionMin(const char* version)
1266 {
1267 if ( version == NULL )
1268 throw "-iphoneos_version_min argument missing";
1269 if ( ! isdigit(version[0]) )
1270 throw "-iphoneos_version_min argument is not a number";
1271 if ( version[1] != '.' )
1272 throw "-iphoneos_version_min argument is missing period as second character";
1273 if ( ! isdigit(version[2]) )
1274 throw "-iphoneos_version_min argument is not a number";
1275
1276 if ( (version[0] == '2') && (version[2] == '0') )
1277 fReaderOptions.fIPhoneVersionMin = ObjectFile::ReaderOptions::k2_0;
1278 else if ( (version[0] == '2') && (version[2] == '1') )
1279 fReaderOptions.fIPhoneVersionMin = ObjectFile::ReaderOptions::k2_1;
1280 else if ( (version[0] == '2') && (version[2] >= '2') )
1281 fReaderOptions.fIPhoneVersionMin = ObjectFile::ReaderOptions::k2_2;
1282 else if ( (version[0] == '3') && (version[2] == '0') )
1283 fReaderOptions.fIPhoneVersionMin = ObjectFile::ReaderOptions::k3_0;
1284 else if ( (version[0] == '3') && (version[2] == '1') )
1285 fReaderOptions.fIPhoneVersionMin = ObjectFile::ReaderOptions::k3_1;
1286 else if ( (version[0] == '3') && (version[2] >= '2') )
1287 fReaderOptions.fIPhoneVersionMin = ObjectFile::ReaderOptions::k3_2;
1288 else if ( (version[0] >= '4') )
1289 fReaderOptions.fIPhoneVersionMin = ObjectFile::ReaderOptions::k4_0;
1290 else {
1291 fReaderOptions.fIPhoneVersionMin = ObjectFile::ReaderOptions::k2_0;
1292 warning("unknown option to -iphoneos_version_min, not 2.x, 3.x, or 4.x");
1293 }
1294 }
1295
1296 bool Options::minOS(ObjectFile::ReaderOptions::MacVersionMin requiredMacMin, ObjectFile::ReaderOptions::IPhoneVersionMin requirediPhoneOSMin)
1297 {
1298 if ( fReaderOptions.fMacVersionMin != ObjectFile::ReaderOptions::kMinMacVersionUnset ) {
1299 return ( fReaderOptions.fMacVersionMin >= requiredMacMin );
1300 }
1301 else {
1302 return ( fReaderOptions.fIPhoneVersionMin >= requirediPhoneOSMin);
1303 }
1304 }
1305
1306
1307 void Options::setWeakReferenceMismatchTreatment(const char* treatment)
1308 {
1309 if ( treatment == NULL )
1310 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1311
1312 if ( strcmp(treatment, "error") == 0 )
1313 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchError;
1314 else if ( strcmp(treatment, "weak") == 0 )
1315 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchWeak;
1316 else if ( strcmp(treatment, "non-weak") == 0 )
1317 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchNonWeak;
1318 else
1319 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1320 }
1321
1322 Options::CommonsMode Options::parseCommonsTreatment(const char* mode)
1323 {
1324 if ( mode == NULL )
1325 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1326
1327 if ( strcmp(mode, "ignore_dylibs") == 0 )
1328 return kCommonsIgnoreDylibs;
1329 else if ( strcmp(mode, "use_dylibs") == 0 )
1330 return kCommonsOverriddenByDylibs;
1331 else if ( strcmp(mode, "error") == 0 )
1332 return kCommonsConflictsDylibsError;
1333 else
1334 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1335 }
1336
1337 void Options::addDylibOverride(const char* paths)
1338 {
1339 if ( paths == NULL )
1340 throw "-dylib_file must followed by two colon separated paths";
1341 const char* colon = strchr(paths, ':');
1342 if ( colon == NULL )
1343 throw "-dylib_file must followed by two colon separated paths";
1344 int len = colon-paths;
1345 char* target = new char[len+2];
1346 strncpy(target, paths, len);
1347 target[len] = '\0';
1348 DylibOverride entry;
1349 entry.installName = target;
1350 entry.useInstead = &colon[1];
1351 fDylibOverrides.push_back(entry);
1352 }
1353
1354 uint64_t Options::parseAddress(const char* addr)
1355 {
1356 char* endptr;
1357 uint64_t result = strtoull(addr, &endptr, 16);
1358 return result;
1359 }
1360
1361 uint32_t Options::parseProtection(const char* prot)
1362 {
1363 uint32_t result = 0;
1364 for(const char* p = prot; *p != '\0'; ++p) {
1365 switch(tolower(*p)) {
1366 case 'r':
1367 result |= VM_PROT_READ;
1368 break;
1369 case 'w':
1370 result |= VM_PROT_WRITE;
1371 break;
1372 case 'x':
1373 result |= VM_PROT_EXECUTE;
1374 break;
1375 case '-':
1376 break;
1377 default:
1378 throwf("unknown -segprot lettter in %s", prot);
1379 }
1380 }
1381 return result;
1382 }
1383
1384
1385
1386 //
1387 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1388 //
1389 //
1390 uint32_t Options::parseVersionNumber(const char* versionString)
1391 {
1392 unsigned long x = 0;
1393 unsigned long y = 0;
1394 unsigned long z = 0;
1395 char* end;
1396 x = strtoul(versionString, &end, 10);
1397 if ( *end == '.' ) {
1398 y = strtoul(&end[1], &end, 10);
1399 if ( *end == '.' ) {
1400 z = strtoul(&end[1], &end, 10);
1401 }
1402 }
1403 if ( (*end != '\0') || (x > 0xffff) || (y > 0xff) || (z > 0xff) )
1404 throwf("malformed version number: %s", versionString);
1405
1406 return (x << 16) | ( y << 8 ) | z;
1407 }
1408
1409 static const char* cstringSymbolName(const char* orderFileString)
1410 {
1411 char* result;
1412 asprintf(&result, "cstring=%s", orderFileString);
1413 // convert escaped characters
1414 char* d = result;
1415 for(const char* s=result; *s != '\0'; ++s, ++d) {
1416 if ( *s == '\\' ) {
1417 ++s;
1418 switch ( *s ) {
1419 case 'n':
1420 *d = '\n';
1421 break;
1422 case 't':
1423 *d = '\t';
1424 break;
1425 case 'v':
1426 *d = '\v';
1427 break;
1428 case 'b':
1429 *d = '\b';
1430 break;
1431 case 'r':
1432 *d = '\r';
1433 break;
1434 case 'f':
1435 *d = '\f';
1436 break;
1437 case 'a':
1438 *d = '\a';
1439 break;
1440 case '\\':
1441 *d = '\\';
1442 break;
1443 case '?':
1444 *d = '\?';
1445 break;
1446 case '\'':
1447 *d = '\r';
1448 break;
1449 case '\"':
1450 *d = '\"';
1451 break;
1452 case 'x':
1453 // hexadecimal value of char
1454 {
1455 ++s;
1456 char value = 0;
1457 while ( isxdigit(*s) ) {
1458 value *= 16;
1459 if ( isdigit(*s) )
1460 value += (*s-'0');
1461 else
1462 value += ((toupper(*s)-'A') + 10);
1463 ++s;
1464 }
1465 *d = value;
1466 }
1467 break;
1468 default:
1469 if ( isdigit(*s) ) {
1470 // octal value of char
1471 char value = 0;
1472 while ( isdigit(*s) ) {
1473 value = (value << 3) + (*s-'0');
1474 ++s;
1475 }
1476 *d = value;
1477 }
1478 }
1479 }
1480 else {
1481 *d = *s;
1482 }
1483 }
1484 *d = '\0';
1485 return result;
1486 }
1487
1488 void Options::parseOrderFile(const char* path, bool cstring)
1489 {
1490 // order files override auto-ordering
1491 fReaderOptions.fAutoOrderInitializers = false;
1492
1493 // read in whole file
1494 int fd = ::open(path, O_RDONLY, 0);
1495 if ( fd == -1 )
1496 throwf("can't open order file: %s", path);
1497 struct stat stat_buf;
1498 ::fstat(fd, &stat_buf);
1499 char* p = (char*)malloc(stat_buf.st_size+1);
1500 if ( p == NULL )
1501 throwf("can't process order file: %s", path);
1502 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1503 throwf("can't read order file: %s", path);
1504 ::close(fd);
1505 p[stat_buf.st_size] = '\n';
1506
1507 // parse into vector of pairs
1508 char * const end = &p[stat_buf.st_size+1];
1509 enum { lineStart, inSymbol, inComment } state = lineStart;
1510 char* symbolStart = NULL;
1511 for (char* s = p; s < end; ++s ) {
1512 switch ( state ) {
1513 case lineStart:
1514 if ( *s =='#' ) {
1515 state = inComment;
1516 }
1517 else if ( !isspace(*s) || cstring ) {
1518 state = inSymbol;
1519 symbolStart = s;
1520 }
1521 break;
1522 case inSymbol:
1523 if ( (*s == '\n') || (!cstring && (*s == '#')) ) {
1524 bool wasComment = (*s == '#');
1525 *s = '\0';
1526 // removing any trailing spaces
1527 char* last = s-1;
1528 while ( isspace(*last) ) {
1529 *last = '\0';
1530 --last;
1531 }
1532 if ( strncmp(symbolStart, "ppc:", 4) == 0 ) {
1533 if ( fArchitecture == CPU_TYPE_POWERPC )
1534 symbolStart = &symbolStart[4];
1535 else
1536 symbolStart = NULL;
1537 }
1538 // if there is an architecture prefix, only use this symbol it if matches current arch
1539 else if ( strncmp(symbolStart, "ppc64:", 6) == 0 ) {
1540 if ( fArchitecture == CPU_TYPE_POWERPC64 )
1541 symbolStart = &symbolStart[6];
1542 else
1543 symbolStart = NULL;
1544 }
1545 else if ( strncmp(symbolStart, "i386:", 5) == 0 ) {
1546 if ( fArchitecture == CPU_TYPE_I386 )
1547 symbolStart = &symbolStart[5];
1548 else
1549 symbolStart = NULL;
1550 }
1551 else if ( strncmp(symbolStart, "x86_64:", 7) == 0 ) {
1552 if ( fArchitecture == CPU_TYPE_X86_64 )
1553 symbolStart = &symbolStart[7];
1554 else
1555 symbolStart = NULL;
1556 }
1557 else if ( strncmp(symbolStart, "arm:", 4) == 0 ) {
1558 if ( fArchitecture == CPU_TYPE_ARM )
1559 symbolStart = &symbolStart[4];
1560 else
1561 symbolStart = NULL;
1562 }
1563 if ( symbolStart != NULL ) {
1564 char* objFileName = NULL;
1565 char* colon = strstr(symbolStart, ".o:");
1566 if ( colon != NULL ) {
1567 colon[2] = '\0';
1568 objFileName = symbolStart;
1569 symbolStart = &colon[3];
1570 }
1571 // trim leading spaces
1572 while ( isspace(*symbolStart) )
1573 ++symbolStart;
1574 Options::OrderedSymbol pair;
1575 if ( cstring )
1576 pair.symbolName = cstringSymbolName(symbolStart);
1577 else
1578 pair.symbolName = symbolStart;
1579 pair.objectFileName = objFileName;
1580 fOrderedSymbols.push_back(pair);
1581 }
1582 symbolStart = NULL;
1583 if ( wasComment )
1584 state = inComment;
1585 else
1586 state = lineStart;
1587 }
1588 break;
1589 case inComment:
1590 if ( *s == '\n' )
1591 state = lineStart;
1592 break;
1593 }
1594 }
1595 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1596 }
1597
1598 void Options::parseSectionOrderFile(const char* segment, const char* section, const char* path)
1599 {
1600 if ( (strcmp(section, "__cstring") == 0) && (strcmp(segment, "__TEXT") == 0) ) {
1601 parseOrderFile(path, true);
1602 }
1603 else if ( (strncmp(section, "__literal",9) == 0) && (strcmp(segment, "__TEXT") == 0) ) {
1604 warning("sorting of __literal[4,8,16] sections not supported");
1605 }
1606 else {
1607 // ignore section information and append all symbol names to global order file
1608 parseOrderFile(path, false);
1609 }
1610 }
1611
1612 void Options::addSection(const char* segment, const char* section, const char* path)
1613 {
1614 if ( strlen(segment) > 16 )
1615 throw "-seccreate segment name max 16 chars";
1616 if ( strlen(section) > 16 ) {
1617 char* tmp = strdup(section);
1618 tmp[16] = '\0';
1619 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section, tmp);
1620 section = tmp;
1621 }
1622
1623 // read in whole file
1624 int fd = ::open(path, O_RDONLY, 0);
1625 if ( fd == -1 )
1626 throwf("can't open -sectcreate file: %s", path);
1627 struct stat stat_buf;
1628 ::fstat(fd, &stat_buf);
1629 char* p = (char*)malloc(stat_buf.st_size);
1630 if ( p == NULL )
1631 throwf("can't process -sectcreate file: %s", path);
1632 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1633 throwf("can't read -sectcreate file: %s", path);
1634 ::close(fd);
1635
1636 // record section to create
1637 ExtraSection info = { segment, section, path, (uint8_t*)p, stat_buf.st_size };
1638 fExtraSections.push_back(info);
1639 }
1640
1641 void Options::addSectionAlignment(const char* segment, const char* section, const char* alignmentStr)
1642 {
1643 if ( strlen(segment) > 16 )
1644 throw "-sectalign segment name max 16 chars";
1645 if ( strlen(section) > 16 )
1646 throw "-sectalign section name max 16 chars";
1647
1648 // argument to -sectalign is a hexadecimal number
1649 char* endptr;
1650 unsigned long value = strtoul(alignmentStr, &endptr, 16);
1651 if ( *endptr != '\0')
1652 throw "argument for -sectalign is not a hexadecimal number";
1653 if ( value > 0x8000 )
1654 throw "argument for -sectalign must be less than or equal to 0x8000";
1655 if ( value == 0 ) {
1656 warning("zero is not a valid -sectalign");
1657 value = 1;
1658 }
1659
1660 // alignment is power of 2 (e.g. page alignment = 12)
1661 uint8_t alignment = (uint8_t)__builtin_ctz(value);
1662 if ( (unsigned long)(1 << alignment) != value ) {
1663 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
1664 segment, section, 1 << alignment);
1665 }
1666
1667 SectionAlignment info = { segment, section, alignment };
1668 fSectionAlignments.push_back(info);
1669 }
1670
1671 void Options::addLibrary(const FileInfo& info)
1672 {
1673 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
1674 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
1675 if ( strcmp(info.path, fit->path) == 0 ) {
1676 // if dylib is specified again but weak, record that it should be weak
1677 if ( info.options.fWeakImport )
1678 fit->options.fWeakImport = true;
1679 return;
1680 }
1681 }
1682 // add to list
1683 fInputFiles.push_back(info);
1684 }
1685
1686 void Options::warnObsolete(const char* arg)
1687 {
1688 warning("option %s is obsolete and being ignored", arg);
1689 }
1690
1691
1692
1693
1694 //
1695 // Process all command line arguments.
1696 //
1697 // The only error checking done here is that each option is valid and if it has arguments
1698 // that they too are valid.
1699 //
1700 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
1701 // whichever was last on the command line is used.
1702 //
1703 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
1704 //
1705 void Options::parse(int argc, const char* argv[])
1706 {
1707 // pass one builds search list from -L and -F options
1708 this->buildSearchPaths(argc, argv);
1709
1710 // reduce re-allocations
1711 fInputFiles.reserve(32);
1712
1713 // pass two parse all other options
1714 for(int i=1; i < argc; ++i) {
1715 const char* arg = argv[i];
1716
1717 if ( arg[0] == '-' ) {
1718
1719 // Since we don't care about the files passed, just the option names, we do this here.
1720 if (fPrintOptions)
1721 fprintf (stderr, "[Logging ld64 options]\t%s\n", arg);
1722
1723 if ( (arg[1] == 'L') || (arg[1] == 'F') ) {
1724 // previously handled by buildSearchPaths()
1725 }
1726 // The one gnu style option we have to keep compatibility
1727 // with gcc. Might as well have the single hyphen one as well.
1728 else if ( (strcmp(arg, "--help") == 0)
1729 || (strcmp(arg, "-help") == 0)) {
1730 fprintf (stdout, "ld64: For information on command line options please use 'man ld'.\n");
1731 exit (0);
1732 }
1733 else if ( strcmp(arg, "-arch") == 0 ) {
1734 parseArch(argv[++i]);
1735 }
1736 else if ( strcmp(arg, "-dynamic") == 0 ) {
1737 // default
1738 }
1739 else if ( strcmp(arg, "-static") == 0 ) {
1740 fReaderOptions.fForStatic = true;
1741 if ( fOutputKind != kObjectFile ) {
1742 fOutputKind = kStaticExecutable;
1743 }
1744 }
1745 else if ( strcmp(arg, "-dylib") == 0 ) {
1746 fOutputKind = kDynamicLibrary;
1747 }
1748 else if ( strcmp(arg, "-bundle") == 0 ) {
1749 fOutputKind = kDynamicBundle;
1750 }
1751 else if ( strcmp(arg, "-dylinker") == 0 ) {
1752 fOutputKind = kDyld;
1753 }
1754 else if ( strcmp(arg, "-execute") == 0 ) {
1755 if ( fOutputKind != kStaticExecutable )
1756 fOutputKind = kDynamicExecutable;
1757 }
1758 else if ( strcmp(arg, "-preload") == 0 ) {
1759 fOutputKind = kPreload;
1760 }
1761 else if ( strcmp(arg, "-r") == 0 ) {
1762 fOutputKind = kObjectFile;
1763 }
1764 else if ( strcmp(arg, "-kext") == 0 ) {
1765 fOutputKind = kKextBundle;
1766 }
1767 else if ( strcmp(arg, "-o") == 0 ) {
1768 fOutputFile = argv[++i];
1769 }
1770 else if ( (arg[1] == 'l') && (strncmp(arg,"-lazy_",6) !=0) ) {
1771 addLibrary(findLibrary(&arg[2]));
1772 }
1773 // This causes a dylib to be weakly bound at
1774 // link time. This corresponds to weak_import.
1775 else if ( strncmp(arg, "-weak-l", 7) == 0 ) {
1776 FileInfo info = findLibrary(&arg[7]);
1777 info.options.fWeakImport = true;
1778 addLibrary(info);
1779 }
1780 else if ( strncmp(arg, "-lazy-l", 7) == 0 ) {
1781 FileInfo info = findLibrary(&arg[7], true);
1782 info.options.fLazyLoad = true;
1783 addLibrary(info);
1784 fUsingLazyDylibLinking = true;
1785 }
1786 // Avoid lazy binding.
1787 // ??? Deprecate.
1788 else if ( strcmp(arg, "-bind_at_load") == 0 ) {
1789 fBindAtLoad = true;
1790 }
1791 else if ( strcmp(arg, "-twolevel_namespace") == 0 ) {
1792 fNameSpace = kTwoLevelNameSpace;
1793 }
1794 else if ( strcmp(arg, "-flat_namespace") == 0 ) {
1795 fNameSpace = kFlatNameSpace;
1796 }
1797 // Also sets a bit to ensure dyld causes everything
1798 // in the namespace to be flat.
1799 // ??? Deprecate
1800 else if ( strcmp(arg, "-force_flat_namespace") == 0 ) {
1801 fNameSpace = kForceFlatNameSpace;
1802 }
1803 // Similar to --whole-archive.
1804 else if ( strcmp(arg, "-all_load") == 0 ) {
1805 fReaderOptions.fFullyLoadArchives = true;
1806 }
1807 else if ( strcmp(arg, "-noall_load") == 0) {
1808 warnObsolete(arg);
1809 }
1810 // Similar to -all_load
1811 else if ( strcmp(arg, "-ObjC") == 0 ) {
1812 fReaderOptions.fLoadAllObjcObjectsFromArchives = true;
1813 }
1814 // Similar to -all_load, but for the following archive only.
1815 else if ( strcmp(arg, "-force_load") == 0 ) {
1816 FileInfo info = findFile(argv[++i]);
1817 info.options.fForceLoad = true;
1818 addLibrary(info);
1819 }
1820 // Library versioning.
1821 else if ( (strcmp(arg, "-dylib_compatibility_version") == 0)
1822 || (strcmp(arg, "-compatibility_version") == 0)) {
1823 const char* vers = argv[++i];
1824 if ( vers == NULL )
1825 throw "-dylib_compatibility_version missing <version>";
1826 fDylibCompatVersion = parseVersionNumber(vers);
1827 }
1828 else if ( (strcmp(arg, "-dylib_current_version") == 0)
1829 || (strcmp(arg, "-current_version") == 0)) {
1830 const char* vers = argv[++i];
1831 if ( vers == NULL )
1832 throw "-dylib_current_version missing <version>";
1833 fDylibCurrentVersion = parseVersionNumber(vers);
1834 }
1835 else if ( strcmp(arg, "-sectorder") == 0 ) {
1836 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
1837 throw "-sectorder missing <segment> <section> <file-path>";
1838 parseSectionOrderFile(argv[i+1], argv[i+2], argv[i+3]);
1839 i += 3;
1840 }
1841 else if ( strcmp(arg, "-order_file") == 0 ) {
1842 parseOrderFile(argv[++i], false);
1843 }
1844 else if ( strcmp(arg, "-order_file_statistics") == 0 ) {
1845 fPrintOrderFileStatistics = true;
1846 }
1847 // ??? Deprecate segcreate.
1848 // -sectcreate puts whole files into a section in the output.
1849 else if ( (strcmp(arg, "-sectcreate") == 0) || (strcmp(arg, "-segcreate") == 0) ) {
1850 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
1851 throw "-sectcreate missing <segment> <section> <file-path>";
1852 addSection(argv[i+1], argv[i+2], argv[i+3]);
1853 i += 3;
1854 }
1855 // Since we have a full path in binary/library names we need to be able to override it.
1856 else if ( (strcmp(arg, "-dylib_install_name") == 0)
1857 || (strcmp(arg, "-dylinker_install_name") == 0)
1858 || (strcmp(arg, "-install_name") == 0)) {
1859 fDylibInstallName = argv[++i];
1860 if ( fDylibInstallName == NULL )
1861 throw "-install_name missing <path>";
1862 }
1863 // Sets the base address of the output.
1864 else if ( (strcmp(arg, "-seg1addr") == 0) || (strcmp(arg, "-image_base") == 0) ) {
1865 const char* address = argv[++i];
1866 if ( address == NULL )
1867 throwf("%s missing <address>", arg);
1868 fBaseAddress = parseAddress(address);
1869 uint64_t temp = ((fBaseAddress+fSegmentAlignment-1) & (-fSegmentAlignment));
1870 if ( fBaseAddress != temp ) {
1871 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment);
1872 fBaseAddress = temp;
1873 }
1874 }
1875 else if ( strcmp(arg, "-e") == 0 ) {
1876 fEntryName = argv[++i];
1877 }
1878 // Same as -@ from the FSF linker.
1879 else if ( strcmp(arg, "-filelist") == 0 ) {
1880 const char* path = argv[++i];
1881 if ( (path == NULL) || (path[0] == '-') )
1882 throw "-filelist missing <path>";
1883 loadFileList(path);
1884 }
1885 else if ( strcmp(arg, "-keep_private_externs") == 0 ) {
1886 fKeepPrivateExterns = true;
1887 }
1888 else if ( strcmp(arg, "-final_output") == 0 ) {
1889 fFinalName = argv[++i];
1890 }
1891 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
1892 // just ensures that this happens for cross object file boundaries.
1893 else if ( (strcmp(arg, "-interposable") == 0) || (strcmp(arg, "-multi_module") == 0)) {
1894 switch ( fInterposeMode ) {
1895 case kInterposeNone:
1896 case kInterposeAllExternal:
1897 fInterposeMode = kInterposeAllExternal;
1898 break;
1899 case kInterposeSome:
1900 // do nothing, -interposable_list overrides -interposable"
1901 break;
1902 }
1903 }
1904 else if ( strcmp(arg, "-interposable_list") == 0 ) {
1905 fInterposeMode = kInterposeSome;
1906 loadExportFile(argv[++i], "-interposable_list", fInterposeList);
1907 }
1908 // Default for -interposable/-multi_module/-single_module.
1909 else if ( strcmp(arg, "-single_module") == 0 ) {
1910 fInterposeMode = kInterposeNone;
1911 }
1912 else if ( strcmp(arg, "-exported_symbols_list") == 0 ) {
1913 if ( fExportMode == kDontExportSome )
1914 throw "can't use -exported_symbols_list and -unexported_symbols_list";
1915 fExportMode = kExportSome;
1916 loadExportFile(argv[++i], "-exported_symbols_list", fExportSymbols);
1917 }
1918 else if ( strcmp(arg, "-unexported_symbols_list") == 0 ) {
1919 if ( fExportMode == kExportSome )
1920 throw "can't use -unexported_symbols_list and -exported_symbols_list";
1921 fExportMode = kDontExportSome;
1922 loadExportFile(argv[++i], "-unexported_symbols_list", fDontExportSymbols);
1923 }
1924 else if ( strcmp(arg, "-exported_symbol") == 0 ) {
1925 if ( fExportMode == kDontExportSome )
1926 throw "can't use -exported_symbol and -unexported_symbols";
1927 fExportMode = kExportSome;
1928 fExportSymbols.insert(argv[++i]);
1929 }
1930 else if ( strcmp(arg, "-unexported_symbol") == 0 ) {
1931 if ( fExportMode == kExportSome )
1932 throw "can't use -unexported_symbol and -exported_symbol";
1933 fExportMode = kDontExportSome;
1934 fDontExportSymbols.insert(argv[++i]);
1935 }
1936 else if ( strcmp(arg, "-non_global_symbols_no_strip_list") == 0 ) {
1937 if ( fLocalSymbolHandling == kLocalSymbolsSelectiveExclude )
1938 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
1939 fLocalSymbolHandling = kLocalSymbolsSelectiveInclude;
1940 loadExportFile(argv[++i], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded);
1941 }
1942 else if ( strcmp(arg, "-non_global_symbols_strip_list") == 0 ) {
1943 if ( fLocalSymbolHandling == kLocalSymbolsSelectiveInclude )
1944 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
1945 fLocalSymbolHandling = kLocalSymbolsSelectiveExclude;
1946 loadExportFile(argv[++i], "-non_global_symbols_strip_list", fLocalSymbolsExcluded);
1947 }
1948 // ??? Deprecate
1949 else if ( strcmp(arg, "-no_arch_warnings") == 0 ) {
1950 fIgnoreOtherArchFiles = true;
1951 }
1952 else if ( strcmp(arg, "-force_cpusubtype_ALL") == 0 ) {
1953 fForceSubtypeAll = true;
1954 }
1955 // Similar to -weak-l but uses the absolute path name to the library.
1956 else if ( strcmp(arg, "-weak_library") == 0 ) {
1957 FileInfo info = findFile(argv[++i]);
1958 info.options.fWeakImport = true;
1959 addLibrary(info);
1960 }
1961 else if ( strcmp(arg, "-lazy_library") == 0 ) {
1962 FileInfo info = findFile(argv[++i]);
1963 info.options.fLazyLoad = true;
1964 addLibrary(info);
1965 fUsingLazyDylibLinking = true;
1966 }
1967 else if ( strcmp(arg, "-framework") == 0 ) {
1968 addLibrary(findFramework(argv[++i]));
1969 }
1970 else if ( strcmp(arg, "-weak_framework") == 0 ) {
1971 FileInfo info = findFramework(argv[++i]);
1972 info.options.fWeakImport = true;
1973 addLibrary(info);
1974 }
1975 else if ( strcmp(arg, "-lazy_framework") == 0 ) {
1976 FileInfo info = findFramework(argv[++i]);
1977 info.options.fLazyLoad = true;
1978 addLibrary(info);
1979 fUsingLazyDylibLinking = true;
1980 }
1981 else if ( strcmp(arg, "-search_paths_first") == 0 ) {
1982 // previously handled by buildSearchPaths()
1983 }
1984 else if ( strcmp(arg, "-undefined") == 0 ) {
1985 setUndefinedTreatment(argv[++i]);
1986 }
1987 // Debugging output flag.
1988 else if ( strcmp(arg, "-arch_multiple") == 0 ) {
1989 fMessagesPrefixedWithArchitecture = true;
1990 }
1991 // Specify what to do with relocations in read only
1992 // sections like .text. Could be errors, warnings,
1993 // or suppressed. Currently we do nothing with the
1994 // flag.
1995 else if ( strcmp(arg, "-read_only_relocs") == 0 ) {
1996 switch ( parseTreatment(argv[++i]) ) {
1997 case kNULL:
1998 case kInvalid:
1999 throw "-read_only_relocs missing [ warning | error | suppress ]";
2000 case kWarning:
2001 fWarnTextRelocs = true;
2002 fAllowTextRelocs = true;
2003 break;
2004 case kSuppress:
2005 fWarnTextRelocs = false;
2006 fAllowTextRelocs = true;
2007 break;
2008 case kError:
2009 fWarnTextRelocs = false;
2010 fAllowTextRelocs = false;
2011 break;
2012 }
2013 }
2014 else if ( strcmp(arg, "-sect_diff_relocs") == 0 ) {
2015 warnObsolete(arg);
2016 ++i;
2017 }
2018 // Warn, error or make strong a mismatch between weak
2019 // and non-weak references.
2020 else if ( strcmp(arg, "-weak_reference_mismatches") == 0 ) {
2021 setWeakReferenceMismatchTreatment(argv[++i]);
2022 }
2023 // For a deployment target of 10.3 and earlier ld64 will
2024 // prebind an executable with 0s in all addresses that
2025 // are prebound. This can then be fixed up by update_prebinding
2026 // later. Prebinding is less useful on 10.4 and greater.
2027 else if ( strcmp(arg, "-prebind") == 0 ) {
2028 fPrebind = true;
2029 }
2030 else if ( strcmp(arg, "-noprebind") == 0 ) {
2031 warnObsolete(arg);
2032 fPrebind = false;
2033 }
2034 else if ( strcmp(arg, "-prebind_allow_overlap") == 0 ) {
2035 warnObsolete(arg);
2036 }
2037 else if ( strcmp(arg, "-prebind_all_twolevel_modules") == 0 ) {
2038 warnObsolete(arg);
2039 }
2040 else if ( strcmp(arg, "-noprebind_all_twolevel_modules") == 0 ) {
2041 warnObsolete(arg);
2042 }
2043 else if ( strcmp(arg, "-nofixprebinding") == 0 ) {
2044 warnObsolete(arg);
2045 }
2046 // This should probably be deprecated when we respect -L and -F
2047 // when searching for libraries.
2048 else if ( strcmp(arg, "-dylib_file") == 0 ) {
2049 addDylibOverride(argv[++i]);
2050 }
2051 // What to expand @executable_path to if found in dependent dylibs
2052 else if ( strcmp(arg, "-executable_path") == 0 ) {
2053 fExecutablePath = argv[++i];
2054 if ( (fExecutablePath == NULL) || (fExecutablePath[0] == '-') )
2055 throw "-executable_path missing <path>";
2056 // if a directory was passed, add / to end
2057 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2058 struct stat statBuffer;
2059 if ( stat(fExecutablePath, &statBuffer) == 0 ) {
2060 if ( (statBuffer.st_mode & S_IFMT) == S_IFDIR ) {
2061 char* pathWithSlash = new char[strlen(fExecutablePath)+2];
2062 strcpy(pathWithSlash, fExecutablePath);
2063 strcat(pathWithSlash, "/");
2064 fExecutablePath = pathWithSlash;
2065 }
2066 }
2067 }
2068 // Aligns all segments to the power of 2 boundary specified.
2069 else if ( strcmp(arg, "-segalign") == 0 ) {
2070 const char* size = argv[++i];
2071 if ( size == NULL )
2072 throw "-segalign missing <size>";
2073 fSegmentAlignment = parseAddress(size);
2074 uint8_t alignment = (uint8_t)__builtin_ctz(fSegmentAlignment);
2075 uint32_t p2aligned = (1 << alignment);
2076 if ( p2aligned != fSegmentAlignment ) {
2077 warning("alignment for -segalign %s is not a power of two, using 0x%X", size, p2aligned);
2078 fSegmentAlignment = p2aligned;
2079 }
2080 }
2081 // Puts a specified segment at a particular address that must
2082 // be a multiple of the segment alignment.
2083 else if ( strcmp(arg, "-segaddr") == 0 ) {
2084 SegmentStart seg;
2085 seg.name = argv[++i];
2086 if ( (seg.name == NULL) || (argv[i+1] == NULL) )
2087 throw "-segaddr missing segName Adddress";
2088 seg.address = parseAddress(argv[++i]);
2089 uint64_t temp = seg.address & (-4096); // page align
2090 if ( (seg.address != temp) )
2091 warning("-segaddr %s not page aligned, rounding down", seg.name);
2092 fCustomSegmentAddresses.push_back(seg);
2093 }
2094 // ??? Deprecate when we deprecate split-seg.
2095 else if ( strcmp(arg, "-segs_read_only_addr") == 0 ) {
2096 fBaseAddress = parseAddress(argv[++i]);
2097 }
2098 // ??? Deprecate when we deprecate split-seg.
2099 else if ( strcmp(arg, "-segs_read_write_addr") == 0 ) {
2100 fBaseWritableAddress = parseAddress(argv[++i]);
2101 fSplitSegs = true;
2102 }
2103 // ??? Deprecate when we get rid of basing at build time.
2104 else if ( strcmp(arg, "-seg_addr_table") == 0 ) {
2105 const char* name = argv[++i];
2106 if ( name == NULL )
2107 throw "-seg_addr_table missing argument";
2108 fSegAddrTablePath = name;
2109 }
2110 else if ( strcmp(arg, "-seg_addr_table_filename") == 0 ) {
2111 warnObsolete(arg);
2112 ++i;
2113 }
2114 else if ( strcmp(arg, "-segprot") == 0 ) {
2115 SegmentProtect seg;
2116 seg.name = argv[++i];
2117 if ( (seg.name == NULL) || (argv[i+1] == NULL) || (argv[i+2] == NULL) )
2118 throw "-segprot missing segName max-prot init-prot";
2119 seg.max = parseProtection(argv[++i]);
2120 seg.init = parseProtection(argv[++i]);
2121 fCustomSegmentProtections.push_back(seg);
2122 }
2123 else if ( strcmp(arg, "-pagezero_size") == 0 ) {
2124 const char* size = argv[++i];
2125 if ( size == NULL )
2126 throw "-pagezero_size missing <size>";
2127 fZeroPageSize = parseAddress(size);
2128 uint64_t temp = fZeroPageSize & (-4096); // page align
2129 if ( (fZeroPageSize != temp) )
2130 warning("-pagezero_size not page aligned, rounding down");
2131 fZeroPageSize = temp;
2132 }
2133 else if ( strcmp(arg, "-stack_addr") == 0 ) {
2134 const char* address = argv[++i];
2135 if ( address == NULL )
2136 throw "-stack_addr missing <address>";
2137 fStackAddr = parseAddress(address);
2138 }
2139 else if ( strcmp(arg, "-stack_size") == 0 ) {
2140 const char* size = argv[++i];
2141 if ( size == NULL )
2142 throw "-stack_size missing <address>";
2143 fStackSize = parseAddress(size);
2144 uint64_t temp = fStackSize & (-4096); // page align
2145 if ( (fStackSize != temp) )
2146 warning("-stack_size not page aligned, rounding down");
2147 }
2148 else if ( strcmp(arg, "-allow_stack_execute") == 0 ) {
2149 fExecutableStack = true;
2150 }
2151 else if ( strcmp(arg, "-sectalign") == 0 ) {
2152 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
2153 throw "-sectalign missing <segment> <section> <file-path>";
2154 addSectionAlignment(argv[i+1], argv[i+2], argv[i+3]);
2155 i += 3;
2156 }
2157 else if ( strcmp(arg, "-sectorder_detail") == 0 ) {
2158 warnObsolete(arg);
2159 }
2160 else if ( strcmp(arg, "-sectobjectsymbols") == 0 ) {
2161 warnObsolete(arg);
2162 i += 2;
2163 }
2164 else if ( strcmp(arg, "-bundle_loader") == 0 ) {
2165 fBundleLoader = argv[++i];
2166 if ( (fBundleLoader == NULL) || (fBundleLoader[0] == '-') )
2167 throw "-bundle_loader missing <path>";
2168 FileInfo info = findFile(fBundleLoader);
2169 info.options.fBundleLoader = true;
2170 fInputFiles.push_back(info);
2171 }
2172 else if ( strcmp(arg, "-private_bundle") == 0 ) {
2173 warnObsolete(arg);
2174 }
2175 else if ( strcmp(arg, "-twolevel_namespace_hints") == 0 ) {
2176 // FIX FIX
2177 }
2178 // Use this flag to set default behavior for deployement targets.
2179 else if ( strcmp(arg, "-macosx_version_min") == 0 ) {
2180 setMacOSXVersionMin(argv[++i]);
2181 }
2182 else if ( strcmp(arg, "-iphoneos_version_min") == 0 ) {
2183 setIPhoneVersionMin(argv[++i]);
2184 }
2185 else if ( strcmp(arg, "-multiply_defined") == 0 ) {
2186 //warnObsolete(arg);
2187 ++i;
2188 }
2189 else if ( strcmp(arg, "-multiply_defined_unused") == 0 ) {
2190 warnObsolete(arg);
2191 ++i;
2192 }
2193 else if ( strcmp(arg, "-nomultidefs") == 0 ) {
2194 warnObsolete(arg);
2195 }
2196 // Display each file in which the argument symbol appears and whether
2197 // the file defines or references it. This option takes an argument
2198 // as -y<symbol> note that there is no space.
2199 else if ( strncmp(arg, "-y", 2) == 0 ) {
2200 warnObsolete("-y");
2201 }
2202 // Same output as -y, but output <arg> number of undefined symbols only.
2203 else if ( strcmp(arg, "-Y") == 0 ) {
2204 //warnObsolete(arg);
2205 ++i;
2206 }
2207 // This option affects all objects linked into the final result.
2208 else if ( strcmp(arg, "-m") == 0 ) {
2209 warnObsolete(arg);
2210 }
2211 else if ( (strcmp(arg, "-why_load") == 0) || (strcmp(arg, "-whyload") == 0) ) {
2212 fReaderOptions.fWhyLoad = true;
2213 }
2214 else if ( strcmp(arg, "-why_live") == 0 ) {
2215 const char* name = argv[++i];
2216 if ( name == NULL )
2217 throw "-why_live missing symbol name argument";
2218 fWhyLive.insert(name);
2219 }
2220 else if ( strcmp(arg, "-u") == 0 ) {
2221 const char* name = argv[++i];
2222 if ( name == NULL )
2223 throw "-u missing argument";
2224 fInitialUndefines.push_back(name);
2225 }
2226 else if ( strcmp(arg, "-U") == 0 ) {
2227 const char* name = argv[++i];
2228 if ( name == NULL )
2229 throw "-U missing argument";
2230 fAllowedUndefined.insert(name);
2231 }
2232 else if ( strcmp(arg, "-s") == 0 ) {
2233 warnObsolete(arg);
2234 fLocalSymbolHandling = kLocalSymbolsNone;
2235 fReaderOptions.fDebugInfoStripping = ObjectFile::ReaderOptions::kDebugInfoNone;
2236 }
2237 else if ( strcmp(arg, "-x") == 0 ) {
2238 fLocalSymbolHandling = kLocalSymbolsNone;
2239 }
2240 else if ( strcmp(arg, "-S") == 0 ) {
2241 fReaderOptions.fDebugInfoStripping = ObjectFile::ReaderOptions::kDebugInfoNone;
2242 }
2243 else if ( strcmp(arg, "-X") == 0 ) {
2244 warnObsolete(arg);
2245 }
2246 else if ( strcmp(arg, "-Si") == 0 ) {
2247 warnObsolete(arg);
2248 fReaderOptions.fDebugInfoStripping = ObjectFile::ReaderOptions::kDebugInfoFull;
2249 }
2250 else if ( strcmp(arg, "-b") == 0 ) {
2251 warnObsolete(arg);
2252 }
2253 else if ( strcmp(arg, "-Sn") == 0 ) {
2254 warnObsolete(arg);
2255 fReaderOptions.fDebugInfoStripping = ObjectFile::ReaderOptions::kDebugInfoFull;
2256 }
2257 else if ( strcmp(arg, "-Sp") == 0 ) {
2258 warnObsolete(arg);
2259 }
2260 else if ( strcmp(arg, "-dead_strip") == 0 ) {
2261 fDeadStrip = kDeadStripOnPlusUnusedInits;
2262 }
2263 else if ( strcmp(arg, "-no_dead_strip_inits_and_terms") == 0 ) {
2264 fDeadStrip = kDeadStripOn;
2265 }
2266 else if ( strcmp(arg, "-w") == 0 ) {
2267 // previously handled by buildSearchPaths()
2268 }
2269 else if ( strcmp(arg, "-arch_errors_fatal") == 0 ) {
2270 fErrorOnOtherArchFiles = true;
2271 }
2272 else if ( strcmp(arg, "-M") == 0 ) {
2273 // FIX FIX
2274 }
2275 else if ( strcmp(arg, "-headerpad") == 0 ) {
2276 const char* size = argv[++i];
2277 if ( size == NULL )
2278 throw "-headerpad missing argument";
2279 fMinimumHeaderPad = parseAddress(size);
2280 }
2281 else if ( strcmp(arg, "-headerpad_max_install_names") == 0 ) {
2282 fMaxMinimumHeaderPad = true;
2283 }
2284 else if ( strcmp(arg, "-t") == 0 ) {
2285 fReaderOptions.fLogAllFiles = true;
2286 }
2287 else if ( strcmp(arg, "-whatsloaded") == 0 ) {
2288 fReaderOptions.fLogObjectFiles = true;
2289 }
2290 else if ( strcmp(arg, "-A") == 0 ) {
2291 warnObsolete(arg);
2292 ++i;
2293 }
2294 else if ( strcmp(arg, "-umbrella") == 0 ) {
2295 const char* name = argv[++i];
2296 if ( name == NULL )
2297 throw "-umbrella missing argument";
2298 fUmbrellaName = name;
2299 }
2300 else if ( strcmp(arg, "-allowable_client") == 0 ) {
2301 const char* name = argv[++i];
2302
2303 if ( name == NULL )
2304 throw "-allowable_client missing argument";
2305
2306 fAllowableClients.push_back(name);
2307 }
2308 else if ( strcmp(arg, "-client_name") == 0 ) {
2309 const char* name = argv[++i];
2310
2311 if ( name == NULL )
2312 throw "-client_name missing argument";
2313
2314 fClientName = name;
2315 }
2316 else if ( strcmp(arg, "-sub_umbrella") == 0 ) {
2317 const char* name = argv[++i];
2318 if ( name == NULL )
2319 throw "-sub_umbrella missing argument";
2320 fSubUmbellas.push_back(name);
2321 }
2322 else if ( strcmp(arg, "-sub_library") == 0 ) {
2323 const char* name = argv[++i];
2324 if ( name == NULL )
2325 throw "-sub_library missing argument";
2326 fSubLibraries.push_back(name);
2327 }
2328 else if ( strcmp(arg, "-init") == 0 ) {
2329 const char* name = argv[++i];
2330 if ( name == NULL )
2331 throw "-init missing argument";
2332 fInitFunctionName = name;
2333 }
2334 else if ( strcmp(arg, "-dot") == 0 ) {
2335 const char* name = argv[++i];
2336 if ( name == NULL )
2337 throw "-dot missing argument";
2338 fDotOutputFile = name;
2339 }
2340 else if ( strcmp(arg, "-warn_commons") == 0 ) {
2341 fWarnCommons = true;
2342 }
2343 else if ( strcmp(arg, "-commons") == 0 ) {
2344 fCommonsMode = parseCommonsTreatment(argv[++i]);
2345 }
2346 else if ( strcmp(arg, "-keep_relocs") == 0 ) {
2347 fKeepRelocations = true;
2348 }
2349 else if ( strcmp(arg, "-warn_stabs") == 0 ) {
2350 fWarnStabs = true;
2351 }
2352 else if ( strcmp(arg, "-pause") == 0 ) {
2353 fPause = true;
2354 }
2355 else if ( strcmp(arg, "-print_statistics") == 0 ) {
2356 fStatistics = true;
2357 }
2358 else if ( strcmp(arg, "-d") == 0 ) {
2359 fReaderOptions.fMakeTentativeDefinitionsReal = true;
2360 }
2361 else if ( strcmp(arg, "-v") == 0 ) {
2362 // previously handled by buildSearchPaths()
2363 }
2364 else if ( strcmp(arg, "-Z") == 0 ) {
2365 // previously handled by buildSearchPaths()
2366 }
2367 else if ( strcmp(arg, "-syslibroot") == 0 ) {
2368 ++i;
2369 // previously handled by buildSearchPaths()
2370 }
2371 else if ( strcmp(arg, "-no_uuid") == 0 ) {
2372 fUUIDMode = kUUIDNone;
2373 }
2374 else if ( strcmp(arg, "-random_uuid") == 0 ) {
2375 fUUIDMode = kUUIDRandom;
2376 }
2377 else if ( strcmp(arg, "-dtrace") == 0 ) {
2378 const char* name = argv[++i];
2379 if ( name == NULL )
2380 throw "-dtrace missing argument";
2381 fDtraceScriptName = name;
2382 }
2383 else if ( strcmp(arg, "-root_safe") == 0 ) {
2384 fReaderOptions.fRootSafe = true;
2385 }
2386 else if ( strcmp(arg, "-setuid_safe") == 0 ) {
2387 fReaderOptions.fSetuidSafe = true;
2388 }
2389 else if ( strcmp(arg, "-alias") == 0 ) {
2390 ObjectFile::ReaderOptions::AliasPair pair;
2391 pair.realName = argv[++i];
2392 if ( pair.realName == NULL )
2393 throw "missing argument to -alias";
2394 pair.alias = argv[++i];
2395 if ( pair.alias == NULL )
2396 throw "missing argument to -alias";
2397 fReaderOptions.fAliases.push_back(pair);
2398 }
2399 else if ( strcmp(arg, "-alias_list") == 0 ) {
2400 parseAliasFile(argv[++i]);
2401 }
2402 // put this last so that it does not interfer with other options starting with 'i'
2403 else if ( strncmp(arg, "-i", 2) == 0 ) {
2404 const char* colon = strchr(arg, ':');
2405 if ( colon == NULL )
2406 throwf("unknown option: %s", arg);
2407 ObjectFile::ReaderOptions::AliasPair pair;
2408 char* temp = new char[colon-arg];
2409 strlcpy(temp, &arg[2], colon-arg-1);
2410 pair.realName = &colon[1];
2411 pair.alias = temp;
2412 fReaderOptions.fAliases.push_back(pair);
2413 }
2414 else if ( strcmp(arg, "-save-temps") == 0 ) {
2415 fSaveTempFiles = true;
2416 }
2417 else if ( strcmp(arg, "-rpath") == 0 ) {
2418 const char* path = argv[++i];
2419 if ( path == NULL )
2420 throw "missing argument to -rpath";
2421 fRPaths.push_back(path);
2422 }
2423 else if ( strcmp(arg, "-read_only_stubs") == 0 ) {
2424 fReadOnlyx86Stubs = true;
2425 }
2426 else if ( strcmp(arg, "-slow_stubs") == 0 ) {
2427 warnObsolete(arg);
2428 }
2429 else if ( strcmp(arg, "-map") == 0 ) {
2430 fMapPath = argv[++i];
2431 if ( fMapPath == NULL )
2432 throw "missing argument to -map";
2433 }
2434 else if ( strcmp(arg, "-pie") == 0 ) {
2435 fPositionIndependentExecutable = true;
2436 }
2437 else if ( strcmp(arg, "-no_pie") == 0 ) {
2438 fDisablePositionIndependentExecutable = true;
2439 }
2440 else if ( strncmp(arg, "-reexport-l", 11) == 0 ) {
2441 FileInfo info = findLibrary(&arg[11], true);
2442 info.options.fReExport = true;
2443 addLibrary(info);
2444 }
2445 else if ( strcmp(arg, "-reexport_library") == 0 ) {
2446 FileInfo info = findFile(argv[++i]);
2447 info.options.fReExport = true;
2448 addLibrary(info);
2449 }
2450 else if ( strcmp(arg, "-reexport_framework") == 0 ) {
2451 FileInfo info = findFramework(argv[++i]);
2452 info.options.fReExport = true;
2453 addLibrary(info);
2454 }
2455 else if ( strcmp(arg, "-dead_strip_dylibs") == 0 ) {
2456 fDeadStripDylibs = true;
2457 }
2458 else if ( strcmp(arg, "-no_implicit_dylibs") == 0 ) {
2459 fReaderOptions.fImplicitlyLinkPublicDylibs = false;
2460 }
2461 else if ( strcmp(arg, "-new_linker") == 0 ) {
2462 // ignore
2463 }
2464 else if ( strcmp(arg, "-no_encryption") == 0 ) {
2465 fEncryptable = false;
2466 }
2467 else if ( strcmp(arg, "-no_compact_unwind") == 0 ) {
2468 fReaderOptions.fAddCompactUnwindEncoding = false;
2469 }
2470 else if ( strcmp(arg, "-mllvm") == 0 ) {
2471 const char* opts = argv[++i];
2472 if ( opts == NULL )
2473 throw "missing argument to -mllvm";
2474 fLLVMOptions.push_back(opts);
2475 }
2476 else if ( strcmp(arg, "-no_order_inits") == 0 ) {
2477 fReaderOptions.fAutoOrderInitializers = false;
2478 }
2479 else if ( strcmp(arg, "-no_order_data") == 0 ) {
2480 fOrderData = false;
2481 }
2482 else if ( strcmp(arg, "-seg_page_size") == 0 ) {
2483 SegmentSize seg;
2484 seg.name = argv[++i];
2485 if ( (seg.name == NULL) || (argv[i+1] == NULL) )
2486 throw "-seg_page_size missing segName Adddress";
2487 seg.size = parseAddress(argv[++i]);
2488 uint64_t temp = seg.size & (-4096); // page align
2489 if ( (seg.size != temp) )
2490 warning("-seg_page_size %s not 4K aligned, rounding down", seg.name);
2491 fCustomSegmentSizes.push_back(seg);
2492 }
2493 else if ( strcmp(arg, "-mark_dead_strippable_dylib") == 0 ) {
2494 fMarkDeadStrippableDylib = true;
2495 }
2496 else if ( strcmp(arg, "-exported_symbols_order") == 0 ) {
2497 loadSymbolOrderFile(argv[++i], fExportSymbolsOrder);
2498 }
2499 else if ( strcmp(arg, "-no_compact_linkedit") == 0 ) {
2500 fMakeCompressedDyldInfo = false;
2501 }
2502 else if ( strcmp(arg, "-no_eh_labels") == 0 ) {
2503 fReaderOptions.fNoEHLabels = true;
2504 }
2505 else if ( strcmp(arg, "-warn_compact_unwind") == 0 ) {
2506 fReaderOptions.fWarnCompactUnwind = true;
2507 }
2508 else if ( strcmp(arg, "-allow_sub_type_mismatches") == 0 ) {
2509 fAllowCpuSubtypeMismatches = true;
2510 }
2511 else if ( strcmp(arg, "-no_zero_fill_sections") == 0 ) {
2512 fReaderOptions.fOptimizeZeroFill = false;
2513 }
2514 else if ( strcmp(arg, "-objc_abi_version") == 0 ) {
2515 const char* version = argv[++i];
2516 if ( version == NULL )
2517 throw "-objc_abi_version missing version number";
2518 if ( strcmp(version, "2") == 0 )
2519 fObjCABIVersion2POverride = true;
2520 else
2521 warning("ignoring unrecognized argument (%s) to -objc_abi_version", version);
2522 }
2523 else if ( strcmp(arg, "-demangle") == 0 ) {
2524 // <rdar://problem/8303976> add -demangle noop to ld64-97
2525 }
2526 else {
2527 throwf("unknown option: %s", arg);
2528 }
2529 }
2530 else {
2531 FileInfo info = findFile(arg);
2532 if ( strcmp(&info.path[strlen(info.path)-2], ".a") == 0 )
2533 addLibrary(info);
2534 else
2535 fInputFiles.push_back(info);
2536 }
2537 }
2538
2539 // if a -lazy option was used, implicitly link in lazydylib1.o
2540 if ( fUsingLazyDylibLinking ) {
2541 addLibrary(findLibrary("lazydylib1.o"));
2542 }
2543 }
2544
2545
2546
2547 //
2548 // -syslibroot <path> is used for SDK support.
2549 // The rule is that all search paths (both explicit and default) are
2550 // checked to see if they exist in the SDK. If so, that path is
2551 // replaced with the sdk prefixed path. If not, that search path
2552 // is used as is. If multiple -syslibroot options are specified
2553 // their directory structures are logically overlayed and files
2554 // from sdks specified earlier on the command line used before later ones.
2555
2556 void Options::buildSearchPaths(int argc, const char* argv[])
2557 {
2558 bool addStandardLibraryDirectories = true;
2559 std::vector<const char*> libraryPaths;
2560 std::vector<const char*> frameworkPaths;
2561 libraryPaths.reserve(10);
2562 frameworkPaths.reserve(10);
2563 // scan through argv looking for -L, -F, -Z, and -syslibroot options
2564 for(int i=0; i < argc; ++i) {
2565 if ( (argv[i][0] == '-') && (argv[i][1] == 'L') ) {
2566 const char* libSearchDir = &argv[i][2];
2567 if ( libSearchDir[0] == '\0' )
2568 throw "-L must be immediately followed by a directory path (no space)";
2569 struct stat statbuf;
2570 if ( stat(libSearchDir, &statbuf) == 0 ) {
2571 if ( statbuf.st_mode & S_IFDIR )
2572 libraryPaths.push_back(libSearchDir);
2573 else
2574 warning("path '%s' following -L not a directory", libSearchDir);
2575 }
2576 else {
2577 warning("directory '%s' following -L not found", libSearchDir);
2578 }
2579 }
2580 else if ( (argv[i][0] == '-') && (argv[i][1] == 'F') ) {
2581 const char* frameworkSearchDir = &argv[i][2];
2582 if ( frameworkSearchDir[0] == '\0' )
2583 throw "-F must be immediately followed by a directory path (no space)";
2584 struct stat statbuf;
2585 if ( stat(frameworkSearchDir, &statbuf) == 0 ) {
2586 if ( statbuf.st_mode & S_IFDIR )
2587 frameworkPaths.push_back(frameworkSearchDir);
2588 else
2589 warning("path '%s' following -F not a directory", frameworkSearchDir);
2590 }
2591 else {
2592 warning("directory '%s' following -F not found", frameworkSearchDir);
2593 }
2594 }
2595 else if ( strcmp(argv[i], "-Z") == 0 )
2596 addStandardLibraryDirectories = false;
2597 else if ( strcmp(argv[i], "-v") == 0 ) {
2598 fVerbose = true;
2599 extern const char ldVersionString[];
2600 fprintf(stderr, "%s", ldVersionString);
2601 // if only -v specified, exit cleanly
2602 if ( argc == 2 ) {
2603 #if LTO_SUPPORT
2604 printLTOVersion(*this);
2605 #endif
2606 exit(0);
2607 }
2608 }
2609 else if ( strcmp(argv[i], "-syslibroot") == 0 ) {
2610 const char* path = argv[++i];
2611 if ( path == NULL )
2612 throw "-syslibroot missing argument";
2613 fSDKPaths.push_back(path);
2614 }
2615 else if ( strcmp(argv[i], "-search_paths_first") == 0 ) {
2616 // ??? Deprecate when we get -Bstatic/-Bdynamic.
2617 fLibrarySearchMode = kSearchDylibAndArchiveInEachDir;
2618 }
2619 else if ( strcmp(argv[i], "-w") == 0 ) {
2620 sEmitWarnings = false;
2621 }
2622 }
2623 int standardLibraryPathsStartIndex = libraryPaths.size();
2624 int standardFrameworkPathsStartIndex = frameworkPaths.size();
2625 if ( addStandardLibraryDirectories ) {
2626 libraryPaths.push_back("/usr/lib");
2627 libraryPaths.push_back("/usr/local/lib");
2628
2629 frameworkPaths.push_back("/Library/Frameworks/");
2630 frameworkPaths.push_back("/System/Library/Frameworks/");
2631 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
2632 }
2633
2634 // <rdar://problem/5829579> Support for configure based hacks
2635 // if last -syslibroot is /, then ignore all syslibroots
2636 if ( fSDKPaths.size() > 0 ) {
2637 if ( strcmp(fSDKPaths.back(), "/") == 0 ) {
2638 fSDKPaths.clear();
2639 }
2640 }
2641
2642 // now merge sdk and library paths to make real search paths
2643 fLibrarySearchPaths.reserve(libraryPaths.size()*(fSDKPaths.size()+1));
2644 int libIndex = 0;
2645 for (std::vector<const char*>::iterator it = libraryPaths.begin(); it != libraryPaths.end(); ++it, ++libIndex) {
2646 const char* libDir = *it;
2647 bool sdkOverride = false;
2648 if ( libDir[0] == '/' ) {
2649 char betterLibDir[PATH_MAX];
2650 if ( strstr(libDir, "/..") != NULL ) {
2651 if ( realpath(libDir, betterLibDir) != NULL )
2652 libDir = strdup(betterLibDir);
2653 }
2654 const int libDirLen = strlen(libDir);
2655 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
2656 const char* sdkDir = *sdkit;
2657 const int sdkDirLen = strlen(sdkDir);
2658 char newPath[libDirLen + sdkDirLen+4];
2659 strcpy(newPath, sdkDir);
2660 if ( newPath[sdkDirLen-1] == '/' )
2661 newPath[sdkDirLen-1] = '\0';
2662 strcat(newPath, libDir);
2663 struct stat statBuffer;
2664 if ( stat(newPath, &statBuffer) == 0 ) {
2665 fLibrarySearchPaths.push_back(strdup(newPath));
2666 sdkOverride = true;
2667 }
2668 }
2669 }
2670 if ( !sdkOverride ) {
2671 if ( (libIndex >= standardLibraryPathsStartIndex) && (fSDKPaths.size() == 1) ) {
2672 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2673 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2674 }
2675 else {
2676 fLibrarySearchPaths.push_back(libDir);
2677 }
2678 }
2679 }
2680
2681 // now merge sdk and framework paths to make real search paths
2682 fFrameworkSearchPaths.reserve(frameworkPaths.size()*(fSDKPaths.size()+1));
2683 int frameIndex = 0;
2684 for (std::vector<const char*>::iterator it = frameworkPaths.begin(); it != frameworkPaths.end(); ++it, ++frameIndex) {
2685 const char* frameworkDir = *it;
2686 bool sdkOverride = false;
2687 if ( frameworkDir[0] == '/' ) {
2688 char betterFrameworkDir[PATH_MAX];
2689 if ( strstr(frameworkDir, "/..") != NULL ) {
2690 if ( realpath(frameworkDir, betterFrameworkDir) != NULL )
2691 frameworkDir = strdup(betterFrameworkDir);
2692 }
2693 const int frameworkDirLen = strlen(frameworkDir);
2694 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
2695 const char* sdkDir = *sdkit;
2696 const int sdkDirLen = strlen(sdkDir);
2697 char newPath[frameworkDirLen + sdkDirLen+4];
2698 strcpy(newPath, sdkDir);
2699 if ( newPath[sdkDirLen-1] == '/' )
2700 newPath[sdkDirLen-1] = '\0';
2701 strcat(newPath, frameworkDir);
2702 struct stat statBuffer;
2703 if ( stat(newPath, &statBuffer) == 0 ) {
2704 fFrameworkSearchPaths.push_back(strdup(newPath));
2705 sdkOverride = true;
2706 }
2707 }
2708 }
2709 if ( !sdkOverride ) {
2710 if ( (frameIndex >= standardFrameworkPathsStartIndex) && (fSDKPaths.size() == 1) ) {
2711 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2712 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2713 }
2714 else {
2715 fFrameworkSearchPaths.push_back(frameworkDir);
2716 }
2717 }
2718 }
2719
2720 if ( fVerbose ) {
2721 fprintf(stderr,"Library search paths:\n");
2722 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
2723 it != fLibrarySearchPaths.end();
2724 it++)
2725 fprintf(stderr,"\t%s\n", *it);
2726 fprintf(stderr,"Framework search paths:\n");
2727 for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin();
2728 it != fFrameworkSearchPaths.end();
2729 it++)
2730 fprintf(stderr,"\t%s\n", *it);
2731 }
2732 }
2733
2734 // this is run before the command line is parsed
2735 void Options::parsePreCommandLineEnvironmentSettings()
2736 {
2737 if ((getenv("LD_TRACE_ARCHIVES") != NULL)
2738 || (getenv("RC_TRACE_ARCHIVES") != NULL))
2739 fReaderOptions.fTraceArchives = true;
2740
2741 if ((getenv("LD_TRACE_DYLIBS") != NULL)
2742 || (getenv("RC_TRACE_DYLIBS") != NULL)) {
2743 fReaderOptions.fTraceDylibs = true;
2744 fReaderOptions.fTraceIndirectDylibs = true;
2745 }
2746
2747 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL) {
2748 fTraceDylibSearching = true;
2749 }
2750
2751 if (getenv("LD_PRINT_OPTIONS") != NULL)
2752 fPrintOptions = true;
2753
2754 if (fReaderOptions.fTraceDylibs || fReaderOptions.fTraceArchives)
2755 fReaderOptions.fTraceOutputFile = getenv("LD_TRACE_FILE");
2756
2757 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL)
2758 fPrintOrderFileStatistics = true;
2759
2760 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL)
2761 fSplitSegs = true;
2762
2763 if (getenv("LD_NO_ENCRYPT") != NULL)
2764 fEncryptable = false;
2765
2766 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL)
2767 fAllowCpuSubtypeMismatches = true;
2768
2769 // for now disable compressed linkedit functionality
2770 if ( getenv("LD_NO_COMPACT_LINKEDIT") != NULL ) {
2771 fMakeCompressedDyldInfo = false;
2772 fMakeClassicDyldInfo = true;
2773 }
2774 // temporary until projects adopt -no_pie
2775 if ( getenv("LD_NO_PIE") != NULL ) {
2776 warning("LD_NO_PIE being used to disble building a position independent executable");
2777 fDisablePositionIndependentExecutable = true;
2778 }
2779
2780 sWarningsSideFilePath = getenv("LD_WARN_FILE");
2781 }
2782
2783
2784 // this is run after the command line is parsed
2785 void Options::parsePostCommandLineEnvironmentSettings()
2786 {
2787 // when building a dynamic main executable, default any use of @executable_path to output path
2788 if ( fExecutablePath == NULL && (fOutputKind == kDynamicExecutable) ) {
2789 fExecutablePath = fOutputFile;
2790 }
2791
2792 // allow build system to set default seg_addr_table
2793 if ( fSegAddrTablePath == NULL )
2794 fSegAddrTablePath = getenv("LD_SEG_ADDR_TABLE");
2795
2796 // allow build system to turn on prebinding
2797 if ( !fPrebind ) {
2798 fPrebind = ( getenv("LD_PREBIND") != NULL );
2799 }
2800
2801 // allow build system to force on dead-code-stripping
2802 if ( fDeadStrip == kDeadStripOff ) {
2803 if ( getenv("LD_DEAD_STRIP") != NULL ) {
2804 switch (fOutputKind) {
2805 case Options::kDynamicLibrary:
2806 case Options::kDynamicExecutable:
2807 case Options::kDynamicBundle:
2808 fDeadStrip = kDeadStripOn;
2809 break;
2810 case Options::kPreload:
2811 case Options::kObjectFile:
2812 case Options::kDyld:
2813 case Options::kStaticExecutable:
2814 case Options::kKextBundle:
2815 break;
2816 }
2817 }
2818 }
2819
2820 // allow build system to force on -warn_commons
2821 if ( getenv("LD_WARN_COMMONS") != NULL )
2822 fWarnCommons = true;
2823
2824 }
2825
2826 void Options::reconfigureDefaults()
2827 {
2828 // sync reader options
2829 switch ( fOutputKind ) {
2830 case Options::kObjectFile:
2831 fReaderOptions.fForFinalLinkedImage = false;
2832 break;
2833 case Options::kDyld:
2834 fReaderOptions.fForDyld = true;
2835 fReaderOptions.fForFinalLinkedImage = true;
2836 fReaderOptions.fNoEHLabels = true;
2837 break;
2838 case Options::kDynamicLibrary:
2839 case Options::kDynamicBundle:
2840 case Options::kKextBundle:
2841 fReaderOptions.fForFinalLinkedImage = true;
2842 fReaderOptions.fNoEHLabels = true;
2843 break;
2844 case Options::kDynamicExecutable:
2845 case Options::kStaticExecutable:
2846 case Options::kPreload:
2847 fReaderOptions.fLinkingMainExecutable = true;
2848 fReaderOptions.fForFinalLinkedImage = true;
2849 fReaderOptions.fNoEHLabels = true;
2850 break;
2851 }
2852
2853 // set default min OS version
2854 if ( (fReaderOptions.fMacVersionMin == ObjectFile::ReaderOptions::kMinMacVersionUnset)
2855 && (fReaderOptions.fIPhoneVersionMin == ObjectFile::ReaderOptions::kMinIPhoneVersionUnset) ) {
2856 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
2857 const char* macVers = getenv("MACOSX_DEPLOYMENT_TARGET");
2858 const char* iPhoneVers = getenv("IPHONEOS_DEPLOYMENT_TARGET");
2859 if ( macVers != NULL )
2860 setMacOSXVersionMin(macVers);
2861 else if ( iPhoneVers != NULL )
2862 setIPhoneVersionMin(iPhoneVers);
2863 else {
2864 // if still nothing, set default based on architecture
2865 switch ( fArchitecture ) {
2866 case CPU_TYPE_I386:
2867 case CPU_TYPE_X86_64:
2868 case CPU_TYPE_POWERPC:
2869 fReaderOptions.fMacVersionMin = ObjectFile::ReaderOptions::k10_6; // FIX FIX, this really should be a check of the OS version the linker is running o
2870 break;
2871 case CPU_TYPE_ARM:
2872 fReaderOptions.fIPhoneVersionMin = ObjectFile::ReaderOptions::k2_0;
2873 break;
2874 }
2875 }
2876 }
2877
2878
2879 // adjust min based on architecture
2880 switch ( fArchitecture ) {
2881 case CPU_TYPE_I386:
2882 if ( fReaderOptions.fMacVersionMin < ObjectFile::ReaderOptions::k10_4 ) {
2883 //warning("-macosx_version_min should be 10.4 or later for i386");
2884 fReaderOptions.fMacVersionMin = ObjectFile::ReaderOptions::k10_4;
2885 }
2886 break;
2887 case CPU_TYPE_POWERPC64:
2888 if ( fReaderOptions.fMacVersionMin < ObjectFile::ReaderOptions::k10_4 ) {
2889 //warning("-macosx_version_min should be 10.4 or later for ppc64");
2890 fReaderOptions.fMacVersionMin = ObjectFile::ReaderOptions::k10_4;
2891 }
2892 break;
2893 case CPU_TYPE_X86_64:
2894 if ( fReaderOptions.fMacVersionMin < ObjectFile::ReaderOptions::k10_4 ) {
2895 //warning("-macosx_version_min should be 10.4 or later for x86_64");
2896 fReaderOptions.fMacVersionMin = ObjectFile::ReaderOptions::k10_4;
2897 }
2898 break;
2899 }
2900
2901 // adjust kext type based on architecture
2902 if ( fOutputKind == kKextBundle ) {
2903 switch ( fArchitecture ) {
2904 case CPU_TYPE_X86_64:
2905 // x86_64 uses new MH_KEXT_BUNDLE type
2906 fMakeClassicDyldInfo = true;
2907 fMakeCompressedDyldInfo = false;
2908 fAllowTextRelocs = true;
2909 fUndefinedTreatment = kUndefinedDynamicLookup;
2910 break;
2911 case CPU_TYPE_POWERPC:
2912 case CPU_TYPE_I386:
2913 case CPU_TYPE_ARM:
2914 // use .o files
2915 fOutputKind = kObjectFile;
2916 break;
2917 }
2918 }
2919
2920 // disable implicit dylibs when targeting 10.3
2921 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
2922 if ( !minOS(ObjectFile::ReaderOptions::k10_4, ObjectFile::ReaderOptions::k2_0) )
2923 fReaderOptions.fImplicitlyLinkPublicDylibs = false;
2924
2925
2926 // allow build system to force linker to ignore -prebind
2927 if ( getenv("LD_FORCE_NO_PREBIND") != NULL )
2928 fPrebind = false;
2929
2930 // allow build system to force linker to ignore -seg_addr_table
2931 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL )
2932 fSegAddrTablePath = NULL;
2933
2934 // check for base address specified externally
2935 if ( (fSegAddrTablePath != NULL) && (fOutputKind == Options::kDynamicLibrary) ) {
2936 parseSegAddrTable(fSegAddrTablePath, this->installPath());
2937 // HACK to support seg_addr_table entries that are physical paths instead of install paths
2938 if ( fBaseAddress == 0 ) {
2939 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
2940 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libstdc++.6.0.4.dylib");
2941 if ( fBaseAddress == 0 )
2942 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libstdc++.6.0.9.dylib");
2943 }
2944
2945 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
2946 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libz.1.2.3.dylib");
2947
2948 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
2949 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libutil1.0.dylib");
2950 }
2951 }
2952
2953 // split segs only allowed for dylibs
2954 if ( fSplitSegs ) {
2955 // split seg only supported for ppc, i386, and arm.
2956 switch ( fArchitecture ) {
2957 case CPU_TYPE_POWERPC:
2958 case CPU_TYPE_I386:
2959 if ( fOutputKind != Options::kDynamicLibrary )
2960 fSplitSegs = false;
2961 // make sure read and write segments are proper distance apart
2962 if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x10000000) )
2963 fBaseWritableAddress = fBaseAddress + 0x10000000;
2964 break;
2965 case CPU_TYPE_ARM:
2966 if ( fOutputKind != Options::kDynamicLibrary ) {
2967 fSplitSegs = false;
2968 }
2969 else {
2970 // make sure read and write segments are proper distance apart
2971 if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x08000000) )
2972 fBaseWritableAddress = fBaseAddress + 0x08000000;
2973 }
2974 break;
2975 default:
2976 fSplitSegs = false;
2977 fBaseAddress = 0;
2978 fBaseWritableAddress = 0;
2979 }
2980 }
2981
2982 // <rdar://problem/6138961> -r implies no prebinding for all architectures
2983 if ( fOutputKind == Options::kObjectFile )
2984 fPrebind = false;
2985
2986 // disable prebinding depending on arch and min OS version
2987 if ( fPrebind ) {
2988 switch ( fArchitecture ) {
2989 case CPU_TYPE_POWERPC:
2990 case CPU_TYPE_I386:
2991 if ( fReaderOptions.fMacVersionMin == ObjectFile::ReaderOptions::k10_4 ) {
2992 // in 10.4 only split seg dylibs are prebound
2993 if ( (fOutputKind != Options::kDynamicLibrary) || ! fSplitSegs )
2994 fPrebind = false;
2995 }
2996 else if ( fReaderOptions.fMacVersionMin >= ObjectFile::ReaderOptions::k10_5 ) {
2997 // in 10.5 nothing is prebound
2998 fPrebind = false;
2999 }
3000 else {
3001 // in 10.3 and earlier only dylibs and main executables could be prebound
3002 switch ( fOutputKind ) {
3003 case Options::kDynamicExecutable:
3004 case Options::kDynamicLibrary:
3005 // only main executables and dylibs can be prebound
3006 break;
3007 case Options::kStaticExecutable:
3008 case Options::kDynamicBundle:
3009 case Options::kObjectFile:
3010 case Options::kDyld:
3011 case Options::kPreload:
3012 case Options::kKextBundle:
3013 // disable prebinding for everything else
3014 fPrebind = false;
3015 break;
3016 }
3017 }
3018 break;
3019 case CPU_TYPE_POWERPC64:
3020 case CPU_TYPE_X86_64:
3021 fPrebind = false;
3022 break;
3023 case CPU_TYPE_ARM:
3024 switch ( fOutputKind ) {
3025 case Options::kDynamicExecutable:
3026 case Options::kDynamicLibrary:
3027 // only main executables and dylibs can be prebound
3028 break;
3029 case Options::kStaticExecutable:
3030 case Options::kDynamicBundle:
3031 case Options::kObjectFile:
3032 case Options::kDyld:
3033 case Options::kPreload:
3034 case Options::kKextBundle:
3035 // disable prebinding for everything else
3036 fPrebind = false;
3037 break;
3038 }
3039 break;
3040 }
3041 }
3042
3043 // only prebound images can be split-seg
3044 if ( fSplitSegs && !fPrebind )
3045 fSplitSegs = false;
3046
3047 // determine if info for shared region should be added
3048 if ( fOutputKind == Options::kDynamicLibrary ) {
3049 if ( minOS(ObjectFile::ReaderOptions::k10_5, ObjectFile::ReaderOptions::k3_1) )
3050 if ( !fPrebind )
3051 if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
3052 || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
3053 fSharedRegionEligible = true;
3054 }
3055
3056 // figure out if module table is needed for compatibility with old ld/dyld
3057 if ( fOutputKind == Options::kDynamicLibrary ) {
3058 switch ( fArchitecture ) {
3059 case CPU_TYPE_POWERPC: // 10.3 and earlier dyld requires a module table
3060 case CPU_TYPE_I386: // ld_classic for 10.4.x requires a module table
3061 if ( fReaderOptions.fMacVersionMin <= ObjectFile::ReaderOptions::k10_5 )
3062 fNeedsModuleTable = true;
3063 break;
3064 case CPU_TYPE_ARM:
3065 if ( fPrebind )
3066 fNeedsModuleTable = true; // redo_prebinding requires a module table
3067 break;
3068 }
3069 }
3070
3071 // <rdar://problem/5366363> -r -x implies -S
3072 if ( (fOutputKind == Options::kObjectFile) && (fLocalSymbolHandling == kLocalSymbolsNone) )
3073 fReaderOptions.fDebugInfoStripping = ObjectFile::ReaderOptions::kDebugInfoNone;
3074
3075 // choose how to process unwind info
3076 switch ( fArchitecture ) {
3077 case CPU_TYPE_I386:
3078 case CPU_TYPE_X86_64:
3079 switch ( fOutputKind ) {
3080 case Options::kObjectFile:
3081 case Options::kStaticExecutable:
3082 case Options::kPreload:
3083 case Options::kKextBundle:
3084 fReaderOptions.fAddCompactUnwindEncoding = false;
3085 break;
3086 case Options::kDyld:
3087 case Options::kDynamicLibrary:
3088 case Options::kDynamicBundle:
3089 case Options::kDynamicExecutable:
3090 //if ( fReaderOptions.fAddCompactUnwindEncoding && (fReaderOptions.fVersionMin >= ObjectFile::ReaderOptions::k10_6) )
3091 // fReaderOptions.fRemoveDwarfUnwindIfCompactExists = true;
3092 break;
3093 }
3094 break;
3095 case CPU_TYPE_POWERPC:
3096 case CPU_TYPE_POWERPC64:
3097 case CPU_TYPE_ARM:
3098 fReaderOptions.fAddCompactUnwindEncoding = false;
3099 fReaderOptions.fRemoveDwarfUnwindIfCompactExists = false;
3100 break;
3101 case 0:
3102 // if -arch is missing, assume we don't want compact unwind info
3103 fReaderOptions.fAddCompactUnwindEncoding = false;
3104 break;
3105 }
3106
3107 // only ARM main executables can be encrypted
3108 if ( fOutputKind != Options::kDynamicExecutable )
3109 fEncryptable = false;
3110 if ( fArchitecture != CPU_TYPE_ARM )
3111 fEncryptable = false;
3112
3113 // don't move inits in dyld because dyld wants certain
3114 // entries point at stable locations at the start of __text
3115 if ( fOutputKind == Options::kDyld )
3116 fReaderOptions.fAutoOrderInitializers = false;
3117
3118
3119 // disable __data ordering for some output kinds
3120 switch ( fOutputKind ) {
3121 case Options::kObjectFile:
3122 case Options::kDyld:
3123 case Options::kStaticExecutable:
3124 case Options::kPreload:
3125 case Options::kKextBundle:
3126 fOrderData = false;
3127 break;
3128 case Options::kDynamicExecutable:
3129 case Options::kDynamicLibrary:
3130 case Options::kDynamicBundle:
3131 break;
3132 }
3133
3134 // only use compressed LINKEDIT for:
3135 // x86_64 and i386 on Mac OS X 10.6 or later
3136 // arm on iPhoneOS 3.1 or later
3137 if ( fMakeCompressedDyldInfo ) {
3138 switch (fArchitecture) {
3139 case CPU_TYPE_I386:
3140 case CPU_TYPE_X86_64:
3141 if ( fReaderOptions.fMacVersionMin >= ObjectFile::ReaderOptions::k10_6 )
3142 fMakeClassicDyldInfo = false;
3143 else if ( fReaderOptions.fMacVersionMin < ObjectFile::ReaderOptions::k10_5 )
3144 fMakeCompressedDyldInfo = false;
3145 break;
3146 case CPU_TYPE_ARM:
3147 if ( fReaderOptions.fIPhoneVersionMin >= ObjectFile::ReaderOptions::k3_1 )
3148 fMakeClassicDyldInfo = false;
3149 else if ( fReaderOptions.fIPhoneVersionMin < ObjectFile::ReaderOptions::k3_1 )
3150 fMakeCompressedDyldInfo = false;
3151 break;
3152 case CPU_TYPE_POWERPC:
3153 case CPU_TYPE_POWERPC64:
3154 default:
3155 fMakeCompressedDyldInfo = false;
3156 }
3157 }
3158
3159
3160 // only use compressed LINKEDIT for final linked images
3161 if ( fMakeCompressedDyldInfo ) {
3162 switch ( fOutputKind ) {
3163 case Options::kDynamicExecutable:
3164 case Options::kDynamicLibrary:
3165 case Options::kDynamicBundle:
3166 break;
3167 case Options::kPreload:
3168 case Options::kStaticExecutable:
3169 case Options::kObjectFile:
3170 case Options::kDyld:
3171 case Options::kKextBundle:
3172 fMakeCompressedDyldInfo = false;
3173 break;
3174 }
3175 }
3176 fReaderOptions.fMakeCompressedDyldInfo = fMakeCompressedDyldInfo;
3177
3178 // only ARM enforces that cpu-sub-types must match
3179 if ( fArchitecture != CPU_TYPE_ARM )
3180 fAllowCpuSubtypeMismatches = true;
3181
3182 // only final linked images can not optimize zero fill sections
3183 if ( fOutputKind == Options::kObjectFile )
3184 fReaderOptions.fOptimizeZeroFill = true;
3185
3186 // only dynamic final linked images should warn about use of commmons
3187 if ( fWarnCommons ) {
3188 switch ( fOutputKind ) {
3189 case Options::kDynamicExecutable:
3190 case Options::kDynamicLibrary:
3191 case Options::kDynamicBundle:
3192 break;
3193 case Options::kPreload:
3194 case Options::kStaticExecutable:
3195 case Options::kObjectFile:
3196 case Options::kDyld:
3197 case Options::kKextBundle:
3198 fWarnCommons = false;
3199 break;
3200 }
3201 }
3202
3203 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
3204 if ( minOS(ObjectFile::ReaderOptions::k10_5, ObjectFile::ReaderOptions::k2_0) )
3205 fUseSimplifiedDylibReExports = true;
3206
3207 // x86_64 for MacOSX 10.7 defaults to PIE
3208 if ( (fArchitecture == CPU_TYPE_X86_64) && (fOutputKind == kDynamicExecutable)
3209 && (fReaderOptions.fMacVersionMin >= ObjectFile::ReaderOptions::k10_7) ) {
3210 fPositionIndependentExecutable = true;
3211 }
3212 }
3213
3214 void Options::checkIllegalOptionCombinations()
3215 {
3216 // check -undefined setting
3217 switch ( fUndefinedTreatment ) {
3218 case kUndefinedError:
3219 case kUndefinedDynamicLookup:
3220 // always legal
3221 break;
3222 case kUndefinedWarning:
3223 case kUndefinedSuppress:
3224 // requires flat namespace
3225 if ( fNameSpace == kTwoLevelNameSpace )
3226 throw "can't use -undefined warning or suppress with -twolevel_namespace";
3227 break;
3228 }
3229
3230 // unify -sub_umbrella with dylibs
3231 for (std::vector<const char*>::iterator it = fSubUmbellas.begin(); it != fSubUmbellas.end(); it++) {
3232 const char* subUmbrella = *it;
3233 bool found = false;
3234 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
3235 Options::FileInfo& info = *fit;
3236 const char* lastSlash = strrchr(info.path, '/');
3237 if ( lastSlash == NULL )
3238 lastSlash = info.path - 1;
3239 if ( strcmp(&lastSlash[1], subUmbrella) == 0 ) {
3240 info.options.fReExport = true;
3241 found = true;
3242 break;
3243 }
3244 }
3245 if ( ! found )
3246 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella);
3247 }
3248
3249 // unify -sub_library with dylibs
3250 for (std::vector<const char*>::iterator it = fSubLibraries.begin(); it != fSubLibraries.end(); it++) {
3251 const char* subLibrary = *it;
3252 bool found = false;
3253 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
3254 Options::FileInfo& info = *fit;
3255 const char* lastSlash = strrchr(info.path, '/');
3256 if ( lastSlash == NULL )
3257 lastSlash = info.path - 1;
3258 const char* dot = strchr(&lastSlash[1], '.');
3259 if ( dot == NULL )
3260 dot = &lastSlash[strlen(lastSlash)];
3261 if ( strncmp(&lastSlash[1], subLibrary, dot-lastSlash-1) == 0 ) {
3262 info.options.fReExport = true;
3263 found = true;
3264 break;
3265 }
3266 }
3267 if ( ! found )
3268 warning("-sub_library %s does not match a supplied dylib", subLibrary);
3269 }
3270
3271 // sync reader options
3272 if ( fNameSpace != kTwoLevelNameSpace )
3273 fReaderOptions.fFlatNamespace = true;
3274
3275 // check -stack_addr
3276 if ( fStackAddr != 0 ) {
3277 switch (fArchitecture) {
3278 case CPU_TYPE_I386:
3279 case CPU_TYPE_POWERPC:
3280 case CPU_TYPE_ARM:
3281 if ( fStackAddr > 0xFFFFFFFF )
3282 throw "-stack_addr must be < 4G for 32-bit processes";
3283 break;
3284 case CPU_TYPE_POWERPC64:
3285 case CPU_TYPE_X86_64:
3286 break;
3287 }
3288 if ( (fStackAddr & -4096) != fStackAddr )
3289 throw "-stack_addr must be multiples of 4K";
3290 if ( fStackSize == 0 )
3291 throw "-stack_addr must be used with -stack_size";
3292 }
3293
3294 // check -stack_size
3295 if ( fStackSize != 0 ) {
3296 switch (fArchitecture) {
3297 case CPU_TYPE_I386:
3298 case CPU_TYPE_POWERPC:
3299 if ( fStackSize > 0xFFFFFFFF )
3300 throw "-stack_size must be < 4G for 32-bit processes";
3301 if ( fStackAddr == 0 ) {
3302 fStackAddr = 0xC0000000;
3303 }
3304 if ( (fStackAddr > 0xB0000000) && ((fStackAddr-fStackSize) < 0xB0000000) )
3305 warning("custom stack placement overlaps and will disable shared region");
3306 break;
3307 case CPU_TYPE_ARM:
3308 if ( fStackSize > 0x2F000000 )
3309 throw "-stack_size must be < 752MB";
3310 if ( fStackAddr == 0 )
3311 fStackAddr = 0x2F000000;
3312 if ( fStackAddr > 0x30000000)
3313 throw "-stack_addr must be < 0x30000000 for arm";
3314 case CPU_TYPE_POWERPC64:
3315 case CPU_TYPE_X86_64:
3316 if ( fStackAddr == 0 ) {
3317 fStackAddr = 0x00007FFF5C000000LL;
3318 }
3319 break;
3320 }
3321 if ( (fStackSize & -4096) != fStackSize )
3322 throw "-stack_size must be multiples of 4K";
3323 switch ( fOutputKind ) {
3324 case Options::kDynamicExecutable:
3325 case Options::kStaticExecutable:
3326 // custom stack size only legal when building main executable
3327 break;
3328 case Options::kDynamicLibrary:
3329 case Options::kDynamicBundle:
3330 case Options::kObjectFile:
3331 case Options::kDyld:
3332 case Options::kPreload:
3333 case Options::kKextBundle:
3334 throw "-stack_size option can only be used when linking a main executable";
3335 }
3336 }
3337
3338 // check that -allow_stack_execute is only used with main executables
3339 if ( fExecutableStack ) {
3340 switch ( fOutputKind ) {
3341 case Options::kDynamicExecutable:
3342 case Options::kStaticExecutable:
3343 // -allow_stack_execute size only legal when building main executable
3344 break;
3345 case Options::kDynamicLibrary:
3346 case Options::kDynamicBundle:
3347 case Options::kObjectFile:
3348 case Options::kDyld:
3349 case Options::kPreload:
3350 case Options::kKextBundle:
3351 throw "-allow_stack_execute option can only be used when linking a main executable";
3352 }
3353 }
3354
3355 // check -client_name is only used when making a bundle or main executable
3356 if ( fClientName != NULL ) {
3357 switch ( fOutputKind ) {
3358 case Options::kDynamicExecutable:
3359 case Options::kDynamicBundle:
3360 break;
3361 case Options::kStaticExecutable:
3362 case Options::kDynamicLibrary:
3363 case Options::kObjectFile:
3364 case Options::kDyld:
3365 case Options::kPreload:
3366 case Options::kKextBundle:
3367 throw "-client_name can only be used with -bundle";
3368 }
3369 }
3370
3371 // check -init is only used when building a dylib
3372 if ( (fInitFunctionName != NULL) && (fOutputKind != Options::kDynamicLibrary) )
3373 throw "-init can only be used with -dynamiclib";
3374
3375 // check -bundle_loader only used with -bundle
3376 if ( (fBundleLoader != NULL) && (fOutputKind != Options::kDynamicBundle) )
3377 throw "-bundle_loader can only be used with -bundle";
3378
3379 // check -dtrace not used with -r
3380 if ( (fDtraceScriptName != NULL) && (fOutputKind == Options::kObjectFile) )
3381 throw "-dtrace can only be used when creating final linked images";
3382
3383 // check -d can only be used with -r
3384 if ( fReaderOptions.fMakeTentativeDefinitionsReal && (fOutputKind != Options::kObjectFile) )
3385 throw "-d can only be used with -r";
3386
3387 // check that -root_safe is not used with -r
3388 if ( fReaderOptions.fRootSafe && (fOutputKind == Options::kObjectFile) )
3389 throw "-root_safe cannot be used with -r";
3390
3391 // check that -setuid_safe is not used with -r
3392 if ( fReaderOptions.fSetuidSafe && (fOutputKind == Options::kObjectFile) )
3393 throw "-setuid_safe cannot be used with -r";
3394
3395 // make sure all required exported symbols exist
3396 std::vector<const char*> impliedExports;
3397 for (NameSet::iterator it=fExportSymbols.regularBegin(); it != fExportSymbols.regularEnd(); it++) {
3398 const char* name = *it;
3399 // never export .eh symbols
3400 const int len = strlen(name);
3401 if ( (strcmp(&name[len-3], ".eh") == 0) || (strncmp(name, ".objc_category_name_", 20) == 0) )
3402 warning("ignoring %s in export list", name);
3403 else
3404 fInitialUndefines.push_back(name);
3405 if ( strncmp(name, ".objc_class_name_", 17) == 0 ) {
3406 // rdar://problem/4718189 map ObjC class names to new runtime names
3407 switch (fArchitecture) {
3408 case CPU_TYPE_I386:
3409 // i386 only uses new symbols when using objc2 ABI
3410 if ( !fObjCABIVersion2POverride )
3411 break;
3412 // when using objc2 ABI to same as archs below
3413 case CPU_TYPE_POWERPC64:
3414 case CPU_TYPE_X86_64:
3415 case CPU_TYPE_ARM:
3416 char* temp;
3417 asprintf(&temp, "_OBJC_CLASS_$_%s", &name[17]);
3418 impliedExports.push_back(temp);
3419 asprintf(&temp, "_OBJC_METACLASS_$_%s", &name[17]);
3420 impliedExports.push_back(temp);
3421 break;
3422 }
3423 }
3424 }
3425 for (std::vector<const char*>::iterator it=impliedExports.begin(); it != impliedExports.end(); it++) {
3426 const char* name = *it;
3427 fExportSymbols.insert(name);
3428 fInitialUndefines.push_back(name);
3429 }
3430
3431 // make sure that -init symbol exist
3432 if ( fInitFunctionName != NULL )
3433 fInitialUndefines.push_back(fInitFunctionName);
3434
3435 // check custom segments
3436 if ( fCustomSegmentAddresses.size() != 0 ) {
3437 // verify no segment is in zero page
3438 if ( fZeroPageSize != ULLONG_MAX ) {
3439 for (std::vector<SegmentStart>::iterator it = fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
3440 if ( (it->address >= 0) && (it->address < fZeroPageSize) )
3441 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it->name, it->address);
3442 }
3443 }
3444 // verify no duplicates
3445 for (std::vector<SegmentStart>::iterator it = fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
3446 for (std::vector<SegmentStart>::iterator it2 = fCustomSegmentAddresses.begin(); it2 != fCustomSegmentAddresses.end(); ++it2) {
3447 if ( (it->address == it2->address) && (it != it2) )
3448 throwf("duplicate -segaddr addresses for %s and %s", it->name, it2->name);
3449 }
3450 // a custom segment address of zero will disable the use of a zero page
3451 if ( it->address == 0 )
3452 fZeroPageSize = 0;
3453 }
3454 }
3455
3456 if ( fZeroPageSize == ULLONG_MAX ) {
3457 // zero page size not specified on command line, set default
3458 switch (fArchitecture) {
3459 case CPU_TYPE_I386:
3460 case CPU_TYPE_POWERPC:
3461 case CPU_TYPE_ARM:
3462 // first 4KB for 32-bit architectures
3463 fZeroPageSize = 0x1000;
3464 break;
3465 case CPU_TYPE_POWERPC64:
3466 // first 4GB for ppc64 on 10.5
3467 if ( fReaderOptions.fMacVersionMin >= ObjectFile::ReaderOptions::k10_5 )
3468 fZeroPageSize = 0x100000000ULL;
3469 else
3470 fZeroPageSize = 0x1000; // 10.4 dyld may not be able to handle >4GB zero page
3471 break;
3472 case CPU_TYPE_X86_64:
3473 // first 4GB for x86_64 on all OS's
3474 fZeroPageSize = 0x100000000ULL;
3475 break;
3476 default:
3477 // if -arch not used, default to 4K zero-page
3478 fZeroPageSize = 0x1000;
3479 }
3480 }
3481 else {
3482 switch ( fOutputKind ) {
3483 case Options::kDynamicExecutable:
3484 case Options::kStaticExecutable:
3485 // -pagezero_size size only legal when building main executable
3486 break;
3487 case Options::kDynamicLibrary:
3488 case Options::kDynamicBundle:
3489 case Options::kObjectFile:
3490 case Options::kDyld:
3491 case Options::kPreload:
3492 case Options::kKextBundle:
3493 if ( fZeroPageSize != 0 )
3494 throw "-pagezero_size option can only be used when linking a main executable";
3495 }
3496 }
3497
3498 // -dead_strip and -r are incompatible
3499 if ( (fDeadStrip != kDeadStripOff) && (fOutputKind == Options::kObjectFile) )
3500 throw "-r and -dead_strip cannot be used together";
3501
3502 // can't use -rpath unless targeting 10.5 or later
3503 if ( fRPaths.size() > 0 ) {
3504 if ( !minOS(ObjectFile::ReaderOptions::k10_5, ObjectFile::ReaderOptions::k2_0) )
3505 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
3506 switch ( fOutputKind ) {
3507 case Options::kDynamicExecutable:
3508 case Options::kDynamicLibrary:
3509 case Options::kDynamicBundle:
3510 break;
3511 case Options::kStaticExecutable:
3512 case Options::kObjectFile:
3513 case Options::kDyld:
3514 case Options::kPreload:
3515 case Options::kKextBundle:
3516 throw "-rpath can only be used when creating a dynamic final linked image";
3517 }
3518 }
3519
3520 // check -pie is only used when building a dynamic main executable for 10.5
3521 if ( fPositionIndependentExecutable ) {
3522 switch ( fOutputKind ) {
3523 case Options::kDynamicExecutable:
3524 // -no_pie anywhere on command line disable PIE
3525 if ( fDisablePositionIndependentExecutable )
3526 fPositionIndependentExecutable = false;
3527 break;
3528 case Options::kPreload:
3529 break;
3530 case Options::kDynamicLibrary:
3531 case Options::kDynamicBundle:
3532 warning("-pie being ignored. It is only used when linking a main executable");
3533 break;
3534 case Options::kStaticExecutable:
3535 case Options::kObjectFile:
3536 case Options::kDyld:
3537 case Options::kKextBundle:
3538 throw "-pie can only be used when linking a main executable";
3539 }
3540 if ( !minOS(ObjectFile::ReaderOptions::k10_5, ObjectFile::ReaderOptions::k2_0) )
3541 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
3542 }
3543
3544 // check -read_only_relocs is not used with x86_64
3545 if ( fAllowTextRelocs ) {
3546 if ( (fArchitecture == CPU_TYPE_X86_64) && (fOutputKind != kKextBundle) ) {
3547 warning("-read_only_relocs cannot be used with x86_64");
3548 fAllowTextRelocs = false;
3549 }
3550 }
3551
3552 // check -mark_auto_dead_strip is only used with dylibs
3553 if ( fMarkDeadStrippableDylib ) {
3554 if ( fOutputKind != Options::kDynamicLibrary ) {
3555 warning("-mark_auto_dead_strip can only be used when creating a dylib");
3556 fMarkDeadStrippableDylib = false;
3557 }
3558 }
3559
3560 // -force_cpusubtype_ALL is not supported for ARM
3561 if ( fForceSubtypeAll ) {
3562 if ( fArchitecture == CPU_TYPE_ARM ) {
3563 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
3564 }
3565 }
3566 }
3567
3568
3569 void Options::checkForClassic(int argc, const char* argv[])
3570 {
3571 // scan options
3572 bool archFound = false;
3573 bool staticFound = false;
3574 bool dtraceFound = false;
3575 bool kextFound = false;
3576 bool rFound = false;
3577 bool creatingMachKernel = false;
3578 bool newLinker = false;
3579
3580 // build command line buffer in case ld crashes
3581 for(int i=1; i < argc; ++i) {
3582 strlcat(crashreporterBuffer, argv[i], 1000);
3583 strlcat(crashreporterBuffer, " ", 1000);
3584 }
3585
3586 for(int i=0; i < argc; ++i) {
3587 const char* arg = argv[i];
3588 if ( arg[0] == '-' ) {
3589 if ( strcmp(arg, "-arch") == 0 ) {
3590 parseArch(argv[++i]);
3591 archFound = true;
3592 }
3593 else if ( strcmp(arg, "-static") == 0 ) {
3594 staticFound = true;
3595 }
3596 else if ( strcmp(arg, "-kext") == 0 ) {
3597 kextFound = true;
3598 }
3599 else if ( strcmp(arg, "-dtrace") == 0 ) {
3600 dtraceFound = true;
3601 }
3602 else if ( strcmp(arg, "-r") == 0 ) {
3603 rFound = true;
3604 }
3605 else if ( strcmp(arg, "-new_linker") == 0 ) {
3606 newLinker = true;
3607 }
3608 else if ( strcmp(arg, "-classic_linker") == 0 ) {
3609 // ld_classic does not understand this option, so remove it
3610 for(int j=i; j < argc; ++j)
3611 argv[j] = argv[j+1];
3612 this->gotoClassicLinker(argc-1, argv);
3613 }
3614 else if ( strcmp(arg, "-o") == 0 ) {
3615 const char* outfile = argv[++i];
3616 if ( (outfile != NULL) && (strstr(outfile, "/mach_kernel") != NULL) )
3617 creatingMachKernel = true;
3618 }
3619 }
3620 }
3621
3622 // -dtrace only supported by new linker
3623 if( dtraceFound )
3624 return;
3625
3626 if( archFound ) {
3627 switch ( fArchitecture ) {
3628 case CPU_TYPE_POWERPC:
3629 case CPU_TYPE_I386:
3630 case CPU_TYPE_ARM:
3631 // if ( staticFound && (rFound || !creatingMachKernel) ) {
3632 if ( (staticFound || kextFound) && !newLinker ) {
3633 // this environment variable will disable use of ld_classic for -static links
3634 if ( getenv("LD_NO_CLASSIC_LINKER_STATIC") == NULL ) {
3635 // ld_classic does not support -iphoneos_version_min, so change
3636 for(int j=0; j < argc; ++j) {
3637 if ( strcmp(argv[j], "-iphoneos_version_min") == 0) {
3638 argv[j] = "-macosx_version_min";
3639 if ( j < argc-1 )
3640 argv[j+1] = "10.5";
3641 break;
3642 }
3643 }
3644 // ld classic does not understand -kext (change to -static -r)
3645 if ( kextFound ) {
3646 for(int j=0; j < argc; ++j) {
3647 if ( strcmp(argv[j], "-kext") == 0)
3648 argv[j] = "-r";
3649 else if ( strcmp(argv[j], "-dynamic") == 0)
3650 argv[j] = "-static";
3651 }
3652 }
3653 this->gotoClassicLinker(argc, argv);
3654 }
3655 }
3656 break;
3657 }
3658 }
3659 else {
3660 // work around for VSPTool
3661 if ( staticFound )
3662 this->gotoClassicLinker(argc, argv);
3663 }
3664
3665 }
3666
3667 void Options::gotoClassicLinker(int argc, const char* argv[])
3668 {
3669 argv[0] = "ld_classic";
3670 char rawPath[PATH_MAX];
3671 char path[PATH_MAX];
3672 uint32_t bufSize = PATH_MAX;
3673 if ( _NSGetExecutablePath(rawPath, &bufSize) != -1 ) {
3674 if ( realpath(rawPath, path) != NULL ) {
3675 char* lastSlash = strrchr(path, '/');
3676 if ( lastSlash != NULL ) {
3677 strcpy(lastSlash+1, "ld_classic");
3678 argv[0] = path;
3679 execvp(path, (char**)argv);
3680 }
3681 }
3682 }
3683 // in case of error in above, try searching for ld_classic via PATH
3684 execvp(argv[0], (char**)argv);
3685 fprintf(stderr, "can't exec ld_classic\n");
3686 exit(1);
3687 }