]> git.saurik.com Git - apple/ld64.git/blob - src/ld/Options.cpp
01ce10f31027f0279b93e36e87a59072e2d929ba
[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 {
2524 throwf("unknown option: %s", arg);
2525 }
2526 }
2527 else {
2528 FileInfo info = findFile(arg);
2529 if ( strcmp(&info.path[strlen(info.path)-2], ".a") == 0 )
2530 addLibrary(info);
2531 else
2532 fInputFiles.push_back(info);
2533 }
2534 }
2535
2536 // if a -lazy option was used, implicitly link in lazydylib1.o
2537 if ( fUsingLazyDylibLinking ) {
2538 addLibrary(findLibrary("lazydylib1.o"));
2539 }
2540 }
2541
2542
2543
2544 //
2545 // -syslibroot <path> is used for SDK support.
2546 // The rule is that all search paths (both explicit and default) are
2547 // checked to see if they exist in the SDK. If so, that path is
2548 // replaced with the sdk prefixed path. If not, that search path
2549 // is used as is. If multiple -syslibroot options are specified
2550 // their directory structures are logically overlayed and files
2551 // from sdks specified earlier on the command line used before later ones.
2552
2553 void Options::buildSearchPaths(int argc, const char* argv[])
2554 {
2555 bool addStandardLibraryDirectories = true;
2556 std::vector<const char*> libraryPaths;
2557 std::vector<const char*> frameworkPaths;
2558 libraryPaths.reserve(10);
2559 frameworkPaths.reserve(10);
2560 // scan through argv looking for -L, -F, -Z, and -syslibroot options
2561 for(int i=0; i < argc; ++i) {
2562 if ( (argv[i][0] == '-') && (argv[i][1] == 'L') ) {
2563 const char* libSearchDir = &argv[i][2];
2564 if ( libSearchDir[0] == '\0' )
2565 throw "-L must be immediately followed by a directory path (no space)";
2566 struct stat statbuf;
2567 if ( stat(libSearchDir, &statbuf) == 0 ) {
2568 if ( statbuf.st_mode & S_IFDIR )
2569 libraryPaths.push_back(libSearchDir);
2570 else
2571 warning("path '%s' following -L not a directory", libSearchDir);
2572 }
2573 else {
2574 warning("directory '%s' following -L not found", libSearchDir);
2575 }
2576 }
2577 else if ( (argv[i][0] == '-') && (argv[i][1] == 'F') ) {
2578 const char* frameworkSearchDir = &argv[i][2];
2579 if ( frameworkSearchDir[0] == '\0' )
2580 throw "-F must be immediately followed by a directory path (no space)";
2581 struct stat statbuf;
2582 if ( stat(frameworkSearchDir, &statbuf) == 0 ) {
2583 if ( statbuf.st_mode & S_IFDIR )
2584 frameworkPaths.push_back(frameworkSearchDir);
2585 else
2586 warning("path '%s' following -F not a directory", frameworkSearchDir);
2587 }
2588 else {
2589 warning("directory '%s' following -F not found", frameworkSearchDir);
2590 }
2591 }
2592 else if ( strcmp(argv[i], "-Z") == 0 )
2593 addStandardLibraryDirectories = false;
2594 else if ( strcmp(argv[i], "-v") == 0 ) {
2595 fVerbose = true;
2596 extern const char ldVersionString[];
2597 fprintf(stderr, "%s", ldVersionString);
2598 // if only -v specified, exit cleanly
2599 if ( argc == 2 ) {
2600 #if LTO_SUPPORT
2601 printLTOVersion(*this);
2602 #endif
2603 exit(0);
2604 }
2605 }
2606 else if ( strcmp(argv[i], "-syslibroot") == 0 ) {
2607 const char* path = argv[++i];
2608 if ( path == NULL )
2609 throw "-syslibroot missing argument";
2610 fSDKPaths.push_back(path);
2611 }
2612 else if ( strcmp(argv[i], "-search_paths_first") == 0 ) {
2613 // ??? Deprecate when we get -Bstatic/-Bdynamic.
2614 fLibrarySearchMode = kSearchDylibAndArchiveInEachDir;
2615 }
2616 else if ( strcmp(argv[i], "-w") == 0 ) {
2617 sEmitWarnings = false;
2618 }
2619 }
2620 int standardLibraryPathsStartIndex = libraryPaths.size();
2621 int standardFrameworkPathsStartIndex = frameworkPaths.size();
2622 if ( addStandardLibraryDirectories ) {
2623 libraryPaths.push_back("/usr/lib");
2624 libraryPaths.push_back("/usr/local/lib");
2625
2626 frameworkPaths.push_back("/Library/Frameworks/");
2627 frameworkPaths.push_back("/System/Library/Frameworks/");
2628 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
2629 }
2630
2631 // <rdar://problem/5829579> Support for configure based hacks
2632 // if last -syslibroot is /, then ignore all syslibroots
2633 if ( fSDKPaths.size() > 0 ) {
2634 if ( strcmp(fSDKPaths.back(), "/") == 0 ) {
2635 fSDKPaths.clear();
2636 }
2637 }
2638
2639 // now merge sdk and library paths to make real search paths
2640 fLibrarySearchPaths.reserve(libraryPaths.size()*(fSDKPaths.size()+1));
2641 int libIndex = 0;
2642 for (std::vector<const char*>::iterator it = libraryPaths.begin(); it != libraryPaths.end(); ++it, ++libIndex) {
2643 const char* libDir = *it;
2644 bool sdkOverride = false;
2645 if ( libDir[0] == '/' ) {
2646 char betterLibDir[PATH_MAX];
2647 if ( strstr(libDir, "/..") != NULL ) {
2648 if ( realpath(libDir, betterLibDir) != NULL )
2649 libDir = strdup(betterLibDir);
2650 }
2651 const int libDirLen = strlen(libDir);
2652 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
2653 const char* sdkDir = *sdkit;
2654 const int sdkDirLen = strlen(sdkDir);
2655 char newPath[libDirLen + sdkDirLen+4];
2656 strcpy(newPath, sdkDir);
2657 if ( newPath[sdkDirLen-1] == '/' )
2658 newPath[sdkDirLen-1] = '\0';
2659 strcat(newPath, libDir);
2660 struct stat statBuffer;
2661 if ( stat(newPath, &statBuffer) == 0 ) {
2662 fLibrarySearchPaths.push_back(strdup(newPath));
2663 sdkOverride = true;
2664 }
2665 }
2666 }
2667 if ( !sdkOverride ) {
2668 if ( (libIndex >= standardLibraryPathsStartIndex) && (fSDKPaths.size() == 1) ) {
2669 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2670 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2671 }
2672 else {
2673 fLibrarySearchPaths.push_back(libDir);
2674 }
2675 }
2676 }
2677
2678 // now merge sdk and framework paths to make real search paths
2679 fFrameworkSearchPaths.reserve(frameworkPaths.size()*(fSDKPaths.size()+1));
2680 int frameIndex = 0;
2681 for (std::vector<const char*>::iterator it = frameworkPaths.begin(); it != frameworkPaths.end(); ++it, ++frameIndex) {
2682 const char* frameworkDir = *it;
2683 bool sdkOverride = false;
2684 if ( frameworkDir[0] == '/' ) {
2685 char betterFrameworkDir[PATH_MAX];
2686 if ( strstr(frameworkDir, "/..") != NULL ) {
2687 if ( realpath(frameworkDir, betterFrameworkDir) != NULL )
2688 frameworkDir = strdup(betterFrameworkDir);
2689 }
2690 const int frameworkDirLen = strlen(frameworkDir);
2691 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
2692 const char* sdkDir = *sdkit;
2693 const int sdkDirLen = strlen(sdkDir);
2694 char newPath[frameworkDirLen + sdkDirLen+4];
2695 strcpy(newPath, sdkDir);
2696 if ( newPath[sdkDirLen-1] == '/' )
2697 newPath[sdkDirLen-1] = '\0';
2698 strcat(newPath, frameworkDir);
2699 struct stat statBuffer;
2700 if ( stat(newPath, &statBuffer) == 0 ) {
2701 fFrameworkSearchPaths.push_back(strdup(newPath));
2702 sdkOverride = true;
2703 }
2704 }
2705 }
2706 if ( !sdkOverride ) {
2707 if ( (frameIndex >= standardFrameworkPathsStartIndex) && (fSDKPaths.size() == 1) ) {
2708 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2709 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2710 }
2711 else {
2712 fFrameworkSearchPaths.push_back(frameworkDir);
2713 }
2714 }
2715 }
2716
2717 if ( fVerbose ) {
2718 fprintf(stderr,"Library search paths:\n");
2719 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
2720 it != fLibrarySearchPaths.end();
2721 it++)
2722 fprintf(stderr,"\t%s\n", *it);
2723 fprintf(stderr,"Framework search paths:\n");
2724 for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin();
2725 it != fFrameworkSearchPaths.end();
2726 it++)
2727 fprintf(stderr,"\t%s\n", *it);
2728 }
2729 }
2730
2731 // this is run before the command line is parsed
2732 void Options::parsePreCommandLineEnvironmentSettings()
2733 {
2734 if ((getenv("LD_TRACE_ARCHIVES") != NULL)
2735 || (getenv("RC_TRACE_ARCHIVES") != NULL))
2736 fReaderOptions.fTraceArchives = true;
2737
2738 if ((getenv("LD_TRACE_DYLIBS") != NULL)
2739 || (getenv("RC_TRACE_DYLIBS") != NULL)) {
2740 fReaderOptions.fTraceDylibs = true;
2741 fReaderOptions.fTraceIndirectDylibs = true;
2742 }
2743
2744 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL) {
2745 fTraceDylibSearching = true;
2746 }
2747
2748 if (getenv("LD_PRINT_OPTIONS") != NULL)
2749 fPrintOptions = true;
2750
2751 if (fReaderOptions.fTraceDylibs || fReaderOptions.fTraceArchives)
2752 fReaderOptions.fTraceOutputFile = getenv("LD_TRACE_FILE");
2753
2754 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL)
2755 fPrintOrderFileStatistics = true;
2756
2757 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL)
2758 fSplitSegs = true;
2759
2760 if (getenv("LD_NO_ENCRYPT") != NULL)
2761 fEncryptable = false;
2762
2763 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL)
2764 fAllowCpuSubtypeMismatches = true;
2765
2766 // for now disable compressed linkedit functionality
2767 if ( getenv("LD_NO_COMPACT_LINKEDIT") != NULL ) {
2768 fMakeCompressedDyldInfo = false;
2769 fMakeClassicDyldInfo = true;
2770 }
2771 // temporary until projects adopt -no_pie
2772 if ( getenv("LD_NO_PIE") != NULL ) {
2773 warning("LD_NO_PIE being used to disble building a position independent executable");
2774 fDisablePositionIndependentExecutable = true;
2775 }
2776
2777 sWarningsSideFilePath = getenv("LD_WARN_FILE");
2778 }
2779
2780
2781 // this is run after the command line is parsed
2782 void Options::parsePostCommandLineEnvironmentSettings()
2783 {
2784 // when building a dynamic main executable, default any use of @executable_path to output path
2785 if ( fExecutablePath == NULL && (fOutputKind == kDynamicExecutable) ) {
2786 fExecutablePath = fOutputFile;
2787 }
2788
2789 // allow build system to set default seg_addr_table
2790 if ( fSegAddrTablePath == NULL )
2791 fSegAddrTablePath = getenv("LD_SEG_ADDR_TABLE");
2792
2793 // allow build system to turn on prebinding
2794 if ( !fPrebind ) {
2795 fPrebind = ( getenv("LD_PREBIND") != NULL );
2796 }
2797
2798 // allow build system to force on dead-code-stripping
2799 if ( fDeadStrip == kDeadStripOff ) {
2800 if ( getenv("LD_DEAD_STRIP") != NULL ) {
2801 switch (fOutputKind) {
2802 case Options::kDynamicLibrary:
2803 case Options::kDynamicExecutable:
2804 case Options::kDynamicBundle:
2805 fDeadStrip = kDeadStripOn;
2806 break;
2807 case Options::kPreload:
2808 case Options::kObjectFile:
2809 case Options::kDyld:
2810 case Options::kStaticExecutable:
2811 case Options::kKextBundle:
2812 break;
2813 }
2814 }
2815 }
2816
2817 // allow build system to force on -warn_commons
2818 if ( getenv("LD_WARN_COMMONS") != NULL )
2819 fWarnCommons = true;
2820
2821 }
2822
2823 void Options::reconfigureDefaults()
2824 {
2825 // sync reader options
2826 switch ( fOutputKind ) {
2827 case Options::kObjectFile:
2828 fReaderOptions.fForFinalLinkedImage = false;
2829 break;
2830 case Options::kDyld:
2831 fReaderOptions.fForDyld = true;
2832 fReaderOptions.fForFinalLinkedImage = true;
2833 fReaderOptions.fNoEHLabels = true;
2834 break;
2835 case Options::kDynamicLibrary:
2836 case Options::kDynamicBundle:
2837 case Options::kKextBundle:
2838 fReaderOptions.fForFinalLinkedImage = true;
2839 fReaderOptions.fNoEHLabels = true;
2840 break;
2841 case Options::kDynamicExecutable:
2842 case Options::kStaticExecutable:
2843 case Options::kPreload:
2844 fReaderOptions.fLinkingMainExecutable = true;
2845 fReaderOptions.fForFinalLinkedImage = true;
2846 fReaderOptions.fNoEHLabels = true;
2847 break;
2848 }
2849
2850 // set default min OS version
2851 if ( (fReaderOptions.fMacVersionMin == ObjectFile::ReaderOptions::kMinMacVersionUnset)
2852 && (fReaderOptions.fIPhoneVersionMin == ObjectFile::ReaderOptions::kMinIPhoneVersionUnset) ) {
2853 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
2854 const char* macVers = getenv("MACOSX_DEPLOYMENT_TARGET");
2855 const char* iPhoneVers = getenv("IPHONEOS_DEPLOYMENT_TARGET");
2856 if ( macVers != NULL )
2857 setMacOSXVersionMin(macVers);
2858 else if ( iPhoneVers != NULL )
2859 setIPhoneVersionMin(iPhoneVers);
2860 else {
2861 // if still nothing, set default based on architecture
2862 switch ( fArchitecture ) {
2863 case CPU_TYPE_I386:
2864 case CPU_TYPE_X86_64:
2865 case CPU_TYPE_POWERPC:
2866 fReaderOptions.fMacVersionMin = ObjectFile::ReaderOptions::k10_6; // FIX FIX, this really should be a check of the OS version the linker is running o
2867 break;
2868 case CPU_TYPE_ARM:
2869 fReaderOptions.fIPhoneVersionMin = ObjectFile::ReaderOptions::k2_0;
2870 break;
2871 }
2872 }
2873 }
2874
2875
2876 // adjust min based on architecture
2877 switch ( fArchitecture ) {
2878 case CPU_TYPE_I386:
2879 if ( fReaderOptions.fMacVersionMin < ObjectFile::ReaderOptions::k10_4 ) {
2880 //warning("-macosx_version_min should be 10.4 or later for i386");
2881 fReaderOptions.fMacVersionMin = ObjectFile::ReaderOptions::k10_4;
2882 }
2883 break;
2884 case CPU_TYPE_POWERPC64:
2885 if ( fReaderOptions.fMacVersionMin < ObjectFile::ReaderOptions::k10_4 ) {
2886 //warning("-macosx_version_min should be 10.4 or later for ppc64");
2887 fReaderOptions.fMacVersionMin = ObjectFile::ReaderOptions::k10_4;
2888 }
2889 break;
2890 case CPU_TYPE_X86_64:
2891 if ( fReaderOptions.fMacVersionMin < ObjectFile::ReaderOptions::k10_4 ) {
2892 //warning("-macosx_version_min should be 10.4 or later for x86_64");
2893 fReaderOptions.fMacVersionMin = ObjectFile::ReaderOptions::k10_4;
2894 }
2895 break;
2896 }
2897
2898 // adjust kext type based on architecture
2899 if ( fOutputKind == kKextBundle ) {
2900 switch ( fArchitecture ) {
2901 case CPU_TYPE_X86_64:
2902 // x86_64 uses new MH_KEXT_BUNDLE type
2903 fMakeClassicDyldInfo = true;
2904 fMakeCompressedDyldInfo = false;
2905 fAllowTextRelocs = true;
2906 fUndefinedTreatment = kUndefinedDynamicLookup;
2907 break;
2908 case CPU_TYPE_POWERPC:
2909 case CPU_TYPE_I386:
2910 case CPU_TYPE_ARM:
2911 // use .o files
2912 fOutputKind = kObjectFile;
2913 break;
2914 }
2915 }
2916
2917 // disable implicit dylibs when targeting 10.3
2918 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
2919 if ( !minOS(ObjectFile::ReaderOptions::k10_4, ObjectFile::ReaderOptions::k2_0) )
2920 fReaderOptions.fImplicitlyLinkPublicDylibs = false;
2921
2922
2923 // allow build system to force linker to ignore -prebind
2924 if ( getenv("LD_FORCE_NO_PREBIND") != NULL )
2925 fPrebind = false;
2926
2927 // allow build system to force linker to ignore -seg_addr_table
2928 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL )
2929 fSegAddrTablePath = NULL;
2930
2931 // check for base address specified externally
2932 if ( (fSegAddrTablePath != NULL) && (fOutputKind == Options::kDynamicLibrary) ) {
2933 parseSegAddrTable(fSegAddrTablePath, this->installPath());
2934 // HACK to support seg_addr_table entries that are physical paths instead of install paths
2935 if ( fBaseAddress == 0 ) {
2936 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
2937 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libstdc++.6.0.4.dylib");
2938 if ( fBaseAddress == 0 )
2939 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libstdc++.6.0.9.dylib");
2940 }
2941
2942 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
2943 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libz.1.2.3.dylib");
2944
2945 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
2946 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libutil1.0.dylib");
2947 }
2948 }
2949
2950 // split segs only allowed for dylibs
2951 if ( fSplitSegs ) {
2952 // split seg only supported for ppc, i386, and arm.
2953 switch ( fArchitecture ) {
2954 case CPU_TYPE_POWERPC:
2955 case CPU_TYPE_I386:
2956 if ( fOutputKind != Options::kDynamicLibrary )
2957 fSplitSegs = false;
2958 // make sure read and write segments are proper distance apart
2959 if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x10000000) )
2960 fBaseWritableAddress = fBaseAddress + 0x10000000;
2961 break;
2962 case CPU_TYPE_ARM:
2963 if ( fOutputKind != Options::kDynamicLibrary ) {
2964 fSplitSegs = false;
2965 }
2966 else {
2967 // make sure read and write segments are proper distance apart
2968 if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x08000000) )
2969 fBaseWritableAddress = fBaseAddress + 0x08000000;
2970 }
2971 break;
2972 default:
2973 fSplitSegs = false;
2974 fBaseAddress = 0;
2975 fBaseWritableAddress = 0;
2976 }
2977 }
2978
2979 // <rdar://problem/6138961> -r implies no prebinding for all architectures
2980 if ( fOutputKind == Options::kObjectFile )
2981 fPrebind = false;
2982
2983 // disable prebinding depending on arch and min OS version
2984 if ( fPrebind ) {
2985 switch ( fArchitecture ) {
2986 case CPU_TYPE_POWERPC:
2987 case CPU_TYPE_I386:
2988 if ( fReaderOptions.fMacVersionMin == ObjectFile::ReaderOptions::k10_4 ) {
2989 // in 10.4 only split seg dylibs are prebound
2990 if ( (fOutputKind != Options::kDynamicLibrary) || ! fSplitSegs )
2991 fPrebind = false;
2992 }
2993 else if ( fReaderOptions.fMacVersionMin >= ObjectFile::ReaderOptions::k10_5 ) {
2994 // in 10.5 nothing is prebound
2995 fPrebind = false;
2996 }
2997 else {
2998 // in 10.3 and earlier only dylibs and main executables could be prebound
2999 switch ( fOutputKind ) {
3000 case Options::kDynamicExecutable:
3001 case Options::kDynamicLibrary:
3002 // only main executables and dylibs can be prebound
3003 break;
3004 case Options::kStaticExecutable:
3005 case Options::kDynamicBundle:
3006 case Options::kObjectFile:
3007 case Options::kDyld:
3008 case Options::kPreload:
3009 case Options::kKextBundle:
3010 // disable prebinding for everything else
3011 fPrebind = false;
3012 break;
3013 }
3014 }
3015 break;
3016 case CPU_TYPE_POWERPC64:
3017 case CPU_TYPE_X86_64:
3018 fPrebind = false;
3019 break;
3020 case CPU_TYPE_ARM:
3021 switch ( fOutputKind ) {
3022 case Options::kDynamicExecutable:
3023 case Options::kDynamicLibrary:
3024 // only main executables and dylibs can be prebound
3025 break;
3026 case Options::kStaticExecutable:
3027 case Options::kDynamicBundle:
3028 case Options::kObjectFile:
3029 case Options::kDyld:
3030 case Options::kPreload:
3031 case Options::kKextBundle:
3032 // disable prebinding for everything else
3033 fPrebind = false;
3034 break;
3035 }
3036 break;
3037 }
3038 }
3039
3040 // only prebound images can be split-seg
3041 if ( fSplitSegs && !fPrebind )
3042 fSplitSegs = false;
3043
3044 // determine if info for shared region should be added
3045 if ( fOutputKind == Options::kDynamicLibrary ) {
3046 if ( minOS(ObjectFile::ReaderOptions::k10_5, ObjectFile::ReaderOptions::k3_1) )
3047 if ( !fPrebind )
3048 if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
3049 || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
3050 fSharedRegionEligible = true;
3051 }
3052
3053 // figure out if module table is needed for compatibility with old ld/dyld
3054 if ( fOutputKind == Options::kDynamicLibrary ) {
3055 switch ( fArchitecture ) {
3056 case CPU_TYPE_POWERPC: // 10.3 and earlier dyld requires a module table
3057 case CPU_TYPE_I386: // ld_classic for 10.4.x requires a module table
3058 if ( fReaderOptions.fMacVersionMin <= ObjectFile::ReaderOptions::k10_5 )
3059 fNeedsModuleTable = true;
3060 break;
3061 case CPU_TYPE_ARM:
3062 if ( fPrebind )
3063 fNeedsModuleTable = true; // redo_prebinding requires a module table
3064 break;
3065 }
3066 }
3067
3068 // <rdar://problem/5366363> -r -x implies -S
3069 if ( (fOutputKind == Options::kObjectFile) && (fLocalSymbolHandling == kLocalSymbolsNone) )
3070 fReaderOptions.fDebugInfoStripping = ObjectFile::ReaderOptions::kDebugInfoNone;
3071
3072 // choose how to process unwind info
3073 switch ( fArchitecture ) {
3074 case CPU_TYPE_I386:
3075 case CPU_TYPE_X86_64:
3076 switch ( fOutputKind ) {
3077 case Options::kObjectFile:
3078 case Options::kStaticExecutable:
3079 case Options::kPreload:
3080 case Options::kKextBundle:
3081 fReaderOptions.fAddCompactUnwindEncoding = false;
3082 break;
3083 case Options::kDyld:
3084 case Options::kDynamicLibrary:
3085 case Options::kDynamicBundle:
3086 case Options::kDynamicExecutable:
3087 //if ( fReaderOptions.fAddCompactUnwindEncoding && (fReaderOptions.fVersionMin >= ObjectFile::ReaderOptions::k10_6) )
3088 // fReaderOptions.fRemoveDwarfUnwindIfCompactExists = true;
3089 break;
3090 }
3091 break;
3092 case CPU_TYPE_POWERPC:
3093 case CPU_TYPE_POWERPC64:
3094 case CPU_TYPE_ARM:
3095 fReaderOptions.fAddCompactUnwindEncoding = false;
3096 fReaderOptions.fRemoveDwarfUnwindIfCompactExists = false;
3097 break;
3098 case 0:
3099 // if -arch is missing, assume we don't want compact unwind info
3100 fReaderOptions.fAddCompactUnwindEncoding = false;
3101 break;
3102 }
3103
3104 // only ARM main executables can be encrypted
3105 if ( fOutputKind != Options::kDynamicExecutable )
3106 fEncryptable = false;
3107 if ( fArchitecture != CPU_TYPE_ARM )
3108 fEncryptable = false;
3109
3110 // don't move inits in dyld because dyld wants certain
3111 // entries point at stable locations at the start of __text
3112 if ( fOutputKind == Options::kDyld )
3113 fReaderOptions.fAutoOrderInitializers = false;
3114
3115
3116 // disable __data ordering for some output kinds
3117 switch ( fOutputKind ) {
3118 case Options::kObjectFile:
3119 case Options::kDyld:
3120 case Options::kStaticExecutable:
3121 case Options::kPreload:
3122 case Options::kKextBundle:
3123 fOrderData = false;
3124 break;
3125 case Options::kDynamicExecutable:
3126 case Options::kDynamicLibrary:
3127 case Options::kDynamicBundle:
3128 break;
3129 }
3130
3131 // only use compressed LINKEDIT for:
3132 // x86_64 and i386 on Mac OS X 10.6 or later
3133 // arm on iPhoneOS 3.1 or later
3134 if ( fMakeCompressedDyldInfo ) {
3135 switch (fArchitecture) {
3136 case CPU_TYPE_I386:
3137 case CPU_TYPE_X86_64:
3138 if ( fReaderOptions.fMacVersionMin >= ObjectFile::ReaderOptions::k10_6 )
3139 fMakeClassicDyldInfo = false;
3140 else if ( fReaderOptions.fMacVersionMin < ObjectFile::ReaderOptions::k10_5 )
3141 fMakeCompressedDyldInfo = false;
3142 break;
3143 case CPU_TYPE_ARM:
3144 if ( fReaderOptions.fIPhoneVersionMin >= ObjectFile::ReaderOptions::k3_1 )
3145 fMakeClassicDyldInfo = false;
3146 else if ( fReaderOptions.fIPhoneVersionMin < ObjectFile::ReaderOptions::k3_1 )
3147 fMakeCompressedDyldInfo = false;
3148 break;
3149 case CPU_TYPE_POWERPC:
3150 case CPU_TYPE_POWERPC64:
3151 default:
3152 fMakeCompressedDyldInfo = false;
3153 }
3154 }
3155
3156
3157 // only use compressed LINKEDIT for final linked images
3158 if ( fMakeCompressedDyldInfo ) {
3159 switch ( fOutputKind ) {
3160 case Options::kDynamicExecutable:
3161 case Options::kDynamicLibrary:
3162 case Options::kDynamicBundle:
3163 break;
3164 case Options::kPreload:
3165 case Options::kStaticExecutable:
3166 case Options::kObjectFile:
3167 case Options::kDyld:
3168 case Options::kKextBundle:
3169 fMakeCompressedDyldInfo = false;
3170 break;
3171 }
3172 }
3173 fReaderOptions.fMakeCompressedDyldInfo = fMakeCompressedDyldInfo;
3174
3175 // only ARM enforces that cpu-sub-types must match
3176 if ( fArchitecture != CPU_TYPE_ARM )
3177 fAllowCpuSubtypeMismatches = true;
3178
3179 // only final linked images can not optimize zero fill sections
3180 if ( fOutputKind == Options::kObjectFile )
3181 fReaderOptions.fOptimizeZeroFill = true;
3182
3183 // only dynamic final linked images should warn about use of commmons
3184 if ( fWarnCommons ) {
3185 switch ( fOutputKind ) {
3186 case Options::kDynamicExecutable:
3187 case Options::kDynamicLibrary:
3188 case Options::kDynamicBundle:
3189 break;
3190 case Options::kPreload:
3191 case Options::kStaticExecutable:
3192 case Options::kObjectFile:
3193 case Options::kDyld:
3194 case Options::kKextBundle:
3195 fWarnCommons = false;
3196 break;
3197 }
3198 }
3199
3200 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
3201 if ( minOS(ObjectFile::ReaderOptions::k10_5, ObjectFile::ReaderOptions::k2_0) )
3202 fUseSimplifiedDylibReExports = true;
3203
3204 // x86_64 for MacOSX 10.7 defaults to PIE
3205 if ( (fArchitecture == CPU_TYPE_X86_64) && (fOutputKind == kDynamicExecutable)
3206 && (fReaderOptions.fMacVersionMin >= ObjectFile::ReaderOptions::k10_7) ) {
3207 fPositionIndependentExecutable = true;
3208 }
3209 }
3210
3211 void Options::checkIllegalOptionCombinations()
3212 {
3213 // check -undefined setting
3214 switch ( fUndefinedTreatment ) {
3215 case kUndefinedError:
3216 case kUndefinedDynamicLookup:
3217 // always legal
3218 break;
3219 case kUndefinedWarning:
3220 case kUndefinedSuppress:
3221 // requires flat namespace
3222 if ( fNameSpace == kTwoLevelNameSpace )
3223 throw "can't use -undefined warning or suppress with -twolevel_namespace";
3224 break;
3225 }
3226
3227 // unify -sub_umbrella with dylibs
3228 for (std::vector<const char*>::iterator it = fSubUmbellas.begin(); it != fSubUmbellas.end(); it++) {
3229 const char* subUmbrella = *it;
3230 bool found = false;
3231 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
3232 Options::FileInfo& info = *fit;
3233 const char* lastSlash = strrchr(info.path, '/');
3234 if ( lastSlash == NULL )
3235 lastSlash = info.path - 1;
3236 if ( strcmp(&lastSlash[1], subUmbrella) == 0 ) {
3237 info.options.fReExport = true;
3238 found = true;
3239 break;
3240 }
3241 }
3242 if ( ! found )
3243 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella);
3244 }
3245
3246 // unify -sub_library with dylibs
3247 for (std::vector<const char*>::iterator it = fSubLibraries.begin(); it != fSubLibraries.end(); it++) {
3248 const char* subLibrary = *it;
3249 bool found = false;
3250 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
3251 Options::FileInfo& info = *fit;
3252 const char* lastSlash = strrchr(info.path, '/');
3253 if ( lastSlash == NULL )
3254 lastSlash = info.path - 1;
3255 const char* dot = strchr(&lastSlash[1], '.');
3256 if ( dot == NULL )
3257 dot = &lastSlash[strlen(lastSlash)];
3258 if ( strncmp(&lastSlash[1], subLibrary, dot-lastSlash-1) == 0 ) {
3259 info.options.fReExport = true;
3260 found = true;
3261 break;
3262 }
3263 }
3264 if ( ! found )
3265 warning("-sub_library %s does not match a supplied dylib", subLibrary);
3266 }
3267
3268 // sync reader options
3269 if ( fNameSpace != kTwoLevelNameSpace )
3270 fReaderOptions.fFlatNamespace = true;
3271
3272 // check -stack_addr
3273 if ( fStackAddr != 0 ) {
3274 switch (fArchitecture) {
3275 case CPU_TYPE_I386:
3276 case CPU_TYPE_POWERPC:
3277 case CPU_TYPE_ARM:
3278 if ( fStackAddr > 0xFFFFFFFF )
3279 throw "-stack_addr must be < 4G for 32-bit processes";
3280 break;
3281 case CPU_TYPE_POWERPC64:
3282 case CPU_TYPE_X86_64:
3283 break;
3284 }
3285 if ( (fStackAddr & -4096) != fStackAddr )
3286 throw "-stack_addr must be multiples of 4K";
3287 if ( fStackSize == 0 )
3288 throw "-stack_addr must be used with -stack_size";
3289 }
3290
3291 // check -stack_size
3292 if ( fStackSize != 0 ) {
3293 switch (fArchitecture) {
3294 case CPU_TYPE_I386:
3295 case CPU_TYPE_POWERPC:
3296 if ( fStackSize > 0xFFFFFFFF )
3297 throw "-stack_size must be < 4G for 32-bit processes";
3298 if ( fStackAddr == 0 ) {
3299 fStackAddr = 0xC0000000;
3300 }
3301 if ( (fStackAddr > 0xB0000000) && ((fStackAddr-fStackSize) < 0xB0000000) )
3302 warning("custom stack placement overlaps and will disable shared region");
3303 break;
3304 case CPU_TYPE_ARM:
3305 if ( fStackSize > 0x2F000000 )
3306 throw "-stack_size must be < 752MB";
3307 if ( fStackAddr == 0 )
3308 fStackAddr = 0x2F000000;
3309 if ( fStackAddr > 0x30000000)
3310 throw "-stack_addr must be < 0x30000000 for arm";
3311 case CPU_TYPE_POWERPC64:
3312 case CPU_TYPE_X86_64:
3313 if ( fStackAddr == 0 ) {
3314 fStackAddr = 0x00007FFF5C000000LL;
3315 }
3316 break;
3317 }
3318 if ( (fStackSize & -4096) != fStackSize )
3319 throw "-stack_size must be multiples of 4K";
3320 switch ( fOutputKind ) {
3321 case Options::kDynamicExecutable:
3322 case Options::kStaticExecutable:
3323 // custom stack size only legal when building main executable
3324 break;
3325 case Options::kDynamicLibrary:
3326 case Options::kDynamicBundle:
3327 case Options::kObjectFile:
3328 case Options::kDyld:
3329 case Options::kPreload:
3330 case Options::kKextBundle:
3331 throw "-stack_size option can only be used when linking a main executable";
3332 }
3333 }
3334
3335 // check that -allow_stack_execute is only used with main executables
3336 if ( fExecutableStack ) {
3337 switch ( fOutputKind ) {
3338 case Options::kDynamicExecutable:
3339 case Options::kStaticExecutable:
3340 // -allow_stack_execute size only legal when building main executable
3341 break;
3342 case Options::kDynamicLibrary:
3343 case Options::kDynamicBundle:
3344 case Options::kObjectFile:
3345 case Options::kDyld:
3346 case Options::kPreload:
3347 case Options::kKextBundle:
3348 throw "-allow_stack_execute option can only be used when linking a main executable";
3349 }
3350 }
3351
3352 // check -client_name is only used when making a bundle or main executable
3353 if ( fClientName != NULL ) {
3354 switch ( fOutputKind ) {
3355 case Options::kDynamicExecutable:
3356 case Options::kDynamicBundle:
3357 break;
3358 case Options::kStaticExecutable:
3359 case Options::kDynamicLibrary:
3360 case Options::kObjectFile:
3361 case Options::kDyld:
3362 case Options::kPreload:
3363 case Options::kKextBundle:
3364 throw "-client_name can only be used with -bundle";
3365 }
3366 }
3367
3368 // check -init is only used when building a dylib
3369 if ( (fInitFunctionName != NULL) && (fOutputKind != Options::kDynamicLibrary) )
3370 throw "-init can only be used with -dynamiclib";
3371
3372 // check -bundle_loader only used with -bundle
3373 if ( (fBundleLoader != NULL) && (fOutputKind != Options::kDynamicBundle) )
3374 throw "-bundle_loader can only be used with -bundle";
3375
3376 // check -dtrace not used with -r
3377 if ( (fDtraceScriptName != NULL) && (fOutputKind == Options::kObjectFile) )
3378 throw "-dtrace can only be used when creating final linked images";
3379
3380 // check -d can only be used with -r
3381 if ( fReaderOptions.fMakeTentativeDefinitionsReal && (fOutputKind != Options::kObjectFile) )
3382 throw "-d can only be used with -r";
3383
3384 // check that -root_safe is not used with -r
3385 if ( fReaderOptions.fRootSafe && (fOutputKind == Options::kObjectFile) )
3386 throw "-root_safe cannot be used with -r";
3387
3388 // check that -setuid_safe is not used with -r
3389 if ( fReaderOptions.fSetuidSafe && (fOutputKind == Options::kObjectFile) )
3390 throw "-setuid_safe cannot be used with -r";
3391
3392 // make sure all required exported symbols exist
3393 std::vector<const char*> impliedExports;
3394 for (NameSet::iterator it=fExportSymbols.regularBegin(); it != fExportSymbols.regularEnd(); it++) {
3395 const char* name = *it;
3396 // never export .eh symbols
3397 const int len = strlen(name);
3398 if ( (strcmp(&name[len-3], ".eh") == 0) || (strncmp(name, ".objc_category_name_", 20) == 0) )
3399 warning("ignoring %s in export list", name);
3400 else
3401 fInitialUndefines.push_back(name);
3402 if ( strncmp(name, ".objc_class_name_", 17) == 0 ) {
3403 // rdar://problem/4718189 map ObjC class names to new runtime names
3404 switch (fArchitecture) {
3405 case CPU_TYPE_I386:
3406 // i386 only uses new symbols when using objc2 ABI
3407 if ( !fObjCABIVersion2POverride )
3408 break;
3409 // when using objc2 ABI to same as archs below
3410 case CPU_TYPE_POWERPC64:
3411 case CPU_TYPE_X86_64:
3412 case CPU_TYPE_ARM:
3413 char* temp;
3414 asprintf(&temp, "_OBJC_CLASS_$_%s", &name[17]);
3415 impliedExports.push_back(temp);
3416 asprintf(&temp, "_OBJC_METACLASS_$_%s", &name[17]);
3417 impliedExports.push_back(temp);
3418 break;
3419 }
3420 }
3421 }
3422 for (std::vector<const char*>::iterator it=impliedExports.begin(); it != impliedExports.end(); it++) {
3423 const char* name = *it;
3424 fExportSymbols.insert(name);
3425 fInitialUndefines.push_back(name);
3426 }
3427
3428 // make sure that -init symbol exist
3429 if ( fInitFunctionName != NULL )
3430 fInitialUndefines.push_back(fInitFunctionName);
3431
3432 // check custom segments
3433 if ( fCustomSegmentAddresses.size() != 0 ) {
3434 // verify no segment is in zero page
3435 if ( fZeroPageSize != ULLONG_MAX ) {
3436 for (std::vector<SegmentStart>::iterator it = fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
3437 if ( (it->address >= 0) && (it->address < fZeroPageSize) )
3438 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it->name, it->address);
3439 }
3440 }
3441 // verify no duplicates
3442 for (std::vector<SegmentStart>::iterator it = fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
3443 for (std::vector<SegmentStart>::iterator it2 = fCustomSegmentAddresses.begin(); it2 != fCustomSegmentAddresses.end(); ++it2) {
3444 if ( (it->address == it2->address) && (it != it2) )
3445 throwf("duplicate -segaddr addresses for %s and %s", it->name, it2->name);
3446 }
3447 // a custom segment address of zero will disable the use of a zero page
3448 if ( it->address == 0 )
3449 fZeroPageSize = 0;
3450 }
3451 }
3452
3453 if ( fZeroPageSize == ULLONG_MAX ) {
3454 // zero page size not specified on command line, set default
3455 switch (fArchitecture) {
3456 case CPU_TYPE_I386:
3457 case CPU_TYPE_POWERPC:
3458 case CPU_TYPE_ARM:
3459 // first 4KB for 32-bit architectures
3460 fZeroPageSize = 0x1000;
3461 break;
3462 case CPU_TYPE_POWERPC64:
3463 // first 4GB for ppc64 on 10.5
3464 if ( fReaderOptions.fMacVersionMin >= ObjectFile::ReaderOptions::k10_5 )
3465 fZeroPageSize = 0x100000000ULL;
3466 else
3467 fZeroPageSize = 0x1000; // 10.4 dyld may not be able to handle >4GB zero page
3468 break;
3469 case CPU_TYPE_X86_64:
3470 // first 4GB for x86_64 on all OS's
3471 fZeroPageSize = 0x100000000ULL;
3472 break;
3473 default:
3474 // if -arch not used, default to 4K zero-page
3475 fZeroPageSize = 0x1000;
3476 }
3477 }
3478 else {
3479 switch ( fOutputKind ) {
3480 case Options::kDynamicExecutable:
3481 case Options::kStaticExecutable:
3482 // -pagezero_size size only legal when building main executable
3483 break;
3484 case Options::kDynamicLibrary:
3485 case Options::kDynamicBundle:
3486 case Options::kObjectFile:
3487 case Options::kDyld:
3488 case Options::kPreload:
3489 case Options::kKextBundle:
3490 if ( fZeroPageSize != 0 )
3491 throw "-pagezero_size option can only be used when linking a main executable";
3492 }
3493 }
3494
3495 // -dead_strip and -r are incompatible
3496 if ( (fDeadStrip != kDeadStripOff) && (fOutputKind == Options::kObjectFile) )
3497 throw "-r and -dead_strip cannot be used together";
3498
3499 // can't use -rpath unless targeting 10.5 or later
3500 if ( fRPaths.size() > 0 ) {
3501 if ( !minOS(ObjectFile::ReaderOptions::k10_5, ObjectFile::ReaderOptions::k2_0) )
3502 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
3503 switch ( fOutputKind ) {
3504 case Options::kDynamicExecutable:
3505 case Options::kDynamicLibrary:
3506 case Options::kDynamicBundle:
3507 break;
3508 case Options::kStaticExecutable:
3509 case Options::kObjectFile:
3510 case Options::kDyld:
3511 case Options::kPreload:
3512 case Options::kKextBundle:
3513 throw "-rpath can only be used when creating a dynamic final linked image";
3514 }
3515 }
3516
3517 // check -pie is only used when building a dynamic main executable for 10.5
3518 if ( fPositionIndependentExecutable ) {
3519 switch ( fOutputKind ) {
3520 case Options::kDynamicExecutable:
3521 // -no_pie anywhere on command line disable PIE
3522 if ( fDisablePositionIndependentExecutable )
3523 fPositionIndependentExecutable = false;
3524 break;
3525 case Options::kPreload:
3526 break;
3527 case Options::kDynamicLibrary:
3528 case Options::kDynamicBundle:
3529 warning("-pie being ignored. It is only used when linking a main executable");
3530 break;
3531 case Options::kStaticExecutable:
3532 case Options::kObjectFile:
3533 case Options::kDyld:
3534 case Options::kKextBundle:
3535 throw "-pie can only be used when linking a main executable";
3536 }
3537 if ( !minOS(ObjectFile::ReaderOptions::k10_5, ObjectFile::ReaderOptions::k2_0) )
3538 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
3539 }
3540
3541 // check -read_only_relocs is not used with x86_64
3542 if ( fAllowTextRelocs ) {
3543 if ( (fArchitecture == CPU_TYPE_X86_64) && (fOutputKind != kKextBundle) ) {
3544 warning("-read_only_relocs cannot be used with x86_64");
3545 fAllowTextRelocs = false;
3546 }
3547 }
3548
3549 // check -mark_auto_dead_strip is only used with dylibs
3550 if ( fMarkDeadStrippableDylib ) {
3551 if ( fOutputKind != Options::kDynamicLibrary ) {
3552 warning("-mark_auto_dead_strip can only be used when creating a dylib");
3553 fMarkDeadStrippableDylib = false;
3554 }
3555 }
3556
3557 // -force_cpusubtype_ALL is not supported for ARM
3558 if ( fForceSubtypeAll ) {
3559 if ( fArchitecture == CPU_TYPE_ARM ) {
3560 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
3561 }
3562 }
3563 }
3564
3565
3566 void Options::checkForClassic(int argc, const char* argv[])
3567 {
3568 // scan options
3569 bool archFound = false;
3570 bool staticFound = false;
3571 bool dtraceFound = false;
3572 bool kextFound = false;
3573 bool rFound = false;
3574 bool creatingMachKernel = false;
3575 bool newLinker = false;
3576
3577 // build command line buffer in case ld crashes
3578 for(int i=1; i < argc; ++i) {
3579 strlcat(crashreporterBuffer, argv[i], 1000);
3580 strlcat(crashreporterBuffer, " ", 1000);
3581 }
3582
3583 for(int i=0; i < argc; ++i) {
3584 const char* arg = argv[i];
3585 if ( arg[0] == '-' ) {
3586 if ( strcmp(arg, "-arch") == 0 ) {
3587 parseArch(argv[++i]);
3588 archFound = true;
3589 }
3590 else if ( strcmp(arg, "-static") == 0 ) {
3591 staticFound = true;
3592 }
3593 else if ( strcmp(arg, "-kext") == 0 ) {
3594 kextFound = true;
3595 }
3596 else if ( strcmp(arg, "-dtrace") == 0 ) {
3597 dtraceFound = true;
3598 }
3599 else if ( strcmp(arg, "-r") == 0 ) {
3600 rFound = true;
3601 }
3602 else if ( strcmp(arg, "-new_linker") == 0 ) {
3603 newLinker = true;
3604 }
3605 else if ( strcmp(arg, "-classic_linker") == 0 ) {
3606 // ld_classic does not understand this option, so remove it
3607 for(int j=i; j < argc; ++j)
3608 argv[j] = argv[j+1];
3609 this->gotoClassicLinker(argc-1, argv);
3610 }
3611 else if ( strcmp(arg, "-o") == 0 ) {
3612 const char* outfile = argv[++i];
3613 if ( (outfile != NULL) && (strstr(outfile, "/mach_kernel") != NULL) )
3614 creatingMachKernel = true;
3615 }
3616 }
3617 }
3618
3619 // -dtrace only supported by new linker
3620 if( dtraceFound )
3621 return;
3622
3623 if( archFound ) {
3624 switch ( fArchitecture ) {
3625 case CPU_TYPE_POWERPC:
3626 case CPU_TYPE_I386:
3627 case CPU_TYPE_ARM:
3628 // if ( staticFound && (rFound || !creatingMachKernel) ) {
3629 if ( (staticFound || kextFound) && !newLinker ) {
3630 // this environment variable will disable use of ld_classic for -static links
3631 if ( getenv("LD_NO_CLASSIC_LINKER_STATIC") == NULL ) {
3632 // ld_classic does not support -iphoneos_version_min, so change
3633 for(int j=0; j < argc; ++j) {
3634 if ( strcmp(argv[j], "-iphoneos_version_min") == 0) {
3635 argv[j] = "-macosx_version_min";
3636 if ( j < argc-1 )
3637 argv[j+1] = "10.5";
3638 break;
3639 }
3640 }
3641 // ld classic does not understand -kext (change to -static -r)
3642 if ( kextFound ) {
3643 for(int j=0; j < argc; ++j) {
3644 if ( strcmp(argv[j], "-kext") == 0)
3645 argv[j] = "-r";
3646 else if ( strcmp(argv[j], "-dynamic") == 0)
3647 argv[j] = "-static";
3648 }
3649 }
3650 this->gotoClassicLinker(argc, argv);
3651 }
3652 }
3653 break;
3654 }
3655 }
3656 else {
3657 // work around for VSPTool
3658 if ( staticFound )
3659 this->gotoClassicLinker(argc, argv);
3660 }
3661
3662 }
3663
3664 void Options::gotoClassicLinker(int argc, const char* argv[])
3665 {
3666 argv[0] = "ld_classic";
3667 char rawPath[PATH_MAX];
3668 char path[PATH_MAX];
3669 uint32_t bufSize = PATH_MAX;
3670 if ( _NSGetExecutablePath(rawPath, &bufSize) != -1 ) {
3671 if ( realpath(rawPath, path) != NULL ) {
3672 char* lastSlash = strrchr(path, '/');
3673 if ( lastSlash != NULL ) {
3674 strcpy(lastSlash+1, "ld_classic");
3675 argv[0] = path;
3676 execvp(path, (char**)argv);
3677 }
3678 }
3679 }
3680 // in case of error in above, try searching for ld_classic via PATH
3681 execvp(argv[0], (char**)argv);
3682 fprintf(stderr, "can't exec ld_classic\n");
3683 exit(1);
3684 }