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