]> git.saurik.com Git - apple/ld64.git/blob - src/Options.cpp
ld64-85.2.2.tar.gz
[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 {
2315 throwf("unknown option: %s", arg);
2316 }
2317 }
2318 else {
2319 FileInfo info = findFile(arg);
2320 if ( strcmp(&info.path[strlen(info.path)-2], ".a") == 0 )
2321 addLibrary(info);
2322 else
2323 fInputFiles.push_back(info);
2324 }
2325 }
2326
2327 // if a -lazy option was used, implicitly link in lazydylib1.o
2328 if ( fUsingLazyDylibLinking ) {
2329 addLibrary(findLibrary("lazydylib1.o"));
2330 }
2331 }
2332
2333
2334
2335 //
2336 // -syslibroot <path> is used for SDK support.
2337 // The rule is that all search paths (both explicit and default) are
2338 // checked to see if they exist in the SDK. If so, that path is
2339 // replaced with the sdk prefixed path. If not, that search path
2340 // is used as is. If multiple -syslibroot options are specified
2341 // their directory structures are logically overlayed and files
2342 // from sdks specified earlier on the command line used before later ones.
2343
2344 void Options::buildSearchPaths(int argc, const char* argv[])
2345 {
2346 bool addStandardLibraryDirectories = true;
2347 std::vector<const char*> libraryPaths;
2348 std::vector<const char*> frameworkPaths;
2349 libraryPaths.reserve(10);
2350 frameworkPaths.reserve(10);
2351 // scan through argv looking for -L, -F, -Z, and -syslibroot options
2352 for(int i=0; i < argc; ++i) {
2353 if ( (argv[i][0] == '-') && (argv[i][1] == 'L') )
2354 libraryPaths.push_back(&argv[i][2]);
2355 else if ( (argv[i][0] == '-') && (argv[i][1] == 'F') )
2356 frameworkPaths.push_back(&argv[i][2]);
2357 else if ( strcmp(argv[i], "-Z") == 0 )
2358 addStandardLibraryDirectories = false;
2359 else if ( strcmp(argv[i], "-v") == 0 ) {
2360 fVerbose = true;
2361 extern const char ldVersionString[];
2362 fprintf(stderr, "%s", ldVersionString);
2363 // if only -v specified, exit cleanly
2364 if ( argc == 2 ) {
2365 #if LTO_SUPPORT
2366 printLTOVersion(*this);
2367 #endif
2368 exit(0);
2369 }
2370 }
2371 else if ( strcmp(argv[i], "-syslibroot") == 0 ) {
2372 const char* path = argv[++i];
2373 if ( path == NULL )
2374 throw "-syslibroot missing argument";
2375 fSDKPaths.push_back(path);
2376 }
2377 else if ( strcmp(argv[i], "-search_paths_first") == 0 ) {
2378 // ??? Deprecate when we get -Bstatic/-Bdynamic.
2379 fLibrarySearchMode = kSearchDylibAndArchiveInEachDir;
2380 }
2381 else if ( strcmp(argv[i], "-w") == 0 ) {
2382 sEmitWarnings = false;
2383 }
2384 }
2385 if ( addStandardLibraryDirectories ) {
2386 libraryPaths.push_back("/usr/lib");
2387 libraryPaths.push_back("/usr/local/lib");
2388
2389 frameworkPaths.push_back("/Library/Frameworks/");
2390 frameworkPaths.push_back("/System/Library/Frameworks/");
2391 // <rdar://problem/5433882> remove /Network from default search path
2392 //frameworkPaths.push_back("/Network/Library/Frameworks/");
2393 }
2394
2395 // <rdar://problem/5829579> Support for configure based hacks
2396 // if last -syslibroot is /, then ignore all syslibroots
2397 if ( fSDKPaths.size() > 0 ) {
2398 if ( strcmp(fSDKPaths.back(), "/") == 0 ) {
2399 fSDKPaths.clear();
2400 }
2401 }
2402
2403 // now merge sdk and library paths to make real search paths
2404 fLibrarySearchPaths.reserve(libraryPaths.size()*(fSDKPaths.size()+1));
2405 for (std::vector<const char*>::iterator it = libraryPaths.begin(); it != libraryPaths.end(); it++) {
2406 const char* libDir = *it;
2407 bool sdkOverride = false;
2408 if ( libDir[0] == '/' ) {
2409 char betterLibDir[PATH_MAX];
2410 if ( strstr(libDir, "/..") != NULL ) {
2411 if ( realpath(libDir, betterLibDir) != NULL )
2412 libDir = strdup(betterLibDir);
2413 }
2414 const int libDirLen = strlen(libDir);
2415 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
2416 // ??? Should be using string here.
2417 const char* sdkDir = *sdkit;
2418 const int sdkDirLen = strlen(sdkDir);
2419 char newPath[libDirLen + sdkDirLen+4];
2420 strcpy(newPath, sdkDir);
2421 if ( newPath[sdkDirLen-1] == '/' )
2422 newPath[sdkDirLen-1] = '\0';
2423 strcat(newPath, libDir);
2424 struct stat statBuffer;
2425 if ( stat(newPath, &statBuffer) == 0 ) {
2426 fLibrarySearchPaths.push_back(strdup(newPath));
2427 sdkOverride = true;
2428 }
2429 }
2430 }
2431 if ( !sdkOverride )
2432 fLibrarySearchPaths.push_back(libDir);
2433 }
2434
2435 // now merge sdk and framework paths to make real search paths
2436 fFrameworkSearchPaths.reserve(frameworkPaths.size()*(fSDKPaths.size()+1));
2437 for (std::vector<const char*>::iterator it = frameworkPaths.begin(); it != frameworkPaths.end(); it++) {
2438 const char* frameworkDir = *it;
2439 bool sdkOverride = false;
2440 if ( frameworkDir[0] == '/' ) {
2441 char betterFrameworkDir[PATH_MAX];
2442 if ( strstr(frameworkDir, "/..") != NULL ) {
2443 if ( realpath(frameworkDir, betterFrameworkDir) != NULL )
2444 frameworkDir = strdup(betterFrameworkDir);
2445 }
2446 const int frameworkDirLen = strlen(frameworkDir);
2447 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
2448 // ??? Should be using string here
2449 const char* sdkDir = *sdkit;
2450 const int sdkDirLen = strlen(sdkDir);
2451 char newPath[frameworkDirLen + sdkDirLen+4];
2452 strcpy(newPath, sdkDir);
2453 if ( newPath[sdkDirLen-1] == '/' )
2454 newPath[sdkDirLen-1] = '\0';
2455 strcat(newPath, frameworkDir);
2456 struct stat statBuffer;
2457 if ( stat(newPath, &statBuffer) == 0 ) {
2458 fFrameworkSearchPaths.push_back(strdup(newPath));
2459 sdkOverride = true;
2460 }
2461 }
2462 }
2463 if ( !sdkOverride )
2464 fFrameworkSearchPaths.push_back(frameworkDir);
2465 }
2466
2467 if ( fVerbose ) {
2468 fprintf(stderr,"Library search paths:\n");
2469 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
2470 it != fLibrarySearchPaths.end();
2471 it++)
2472 fprintf(stderr,"\t%s\n", *it);
2473 fprintf(stderr,"Framework search paths:\n");
2474 for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin();
2475 it != fFrameworkSearchPaths.end();
2476 it++)
2477 fprintf(stderr,"\t%s\n", *it);
2478 }
2479 }
2480
2481 // this is run before the command line is parsed
2482 void Options::parsePreCommandLineEnvironmentSettings()
2483 {
2484 if ((getenv("LD_TRACE_ARCHIVES") != NULL)
2485 || (getenv("RC_TRACE_ARCHIVES") != NULL))
2486 fReaderOptions.fTraceArchives = true;
2487
2488 if ((getenv("LD_TRACE_DYLIBS") != NULL)
2489 || (getenv("RC_TRACE_DYLIBS") != NULL)) {
2490 fReaderOptions.fTraceDylibs = true;
2491 fReaderOptions.fTraceIndirectDylibs = true;
2492 }
2493
2494 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL) {
2495 fTraceDylibSearching = true;
2496 }
2497
2498 if (getenv("LD_PRINT_OPTIONS") != NULL)
2499 fPrintOptions = true;
2500
2501 if (fReaderOptions.fTraceDylibs || fReaderOptions.fTraceArchives)
2502 fReaderOptions.fTraceOutputFile = getenv("LD_TRACE_FILE");
2503
2504 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL)
2505 fPrintOrderFileStatistics = true;
2506
2507 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL)
2508 fSplitSegs = true;
2509
2510 if (getenv("LD_NO_ENCRYPT") != NULL)
2511 fEncryptable = false;
2512
2513 sWarningsSideFilePath = getenv("LD_WARN_FILE");
2514 }
2515
2516
2517 // this is run after the command line is parsed
2518 void Options::parsePostCommandLineEnvironmentSettings()
2519 {
2520 // when building a dynamic main executable, default any use of @executable_path to output path
2521 if ( fExecutablePath == NULL && (fOutputKind == kDynamicExecutable) ) {
2522 fExecutablePath = fOutputFile;
2523 }
2524
2525 // allow build system to set default seg_addr_table
2526 if ( fSegAddrTablePath == NULL )
2527 fSegAddrTablePath = getenv("LD_SEG_ADDR_TABLE");
2528
2529 // allow build system to turn on prebinding
2530 if ( !fPrebind ) {
2531 fPrebind = ( getenv("LD_PREBIND") != NULL );
2532 }
2533
2534 // allow build system to force on dead-code-stripping
2535 if ( fDeadStrip == kDeadStripOff ) {
2536 if ( getenv("LD_DEAD_STRIP") != NULL ) {
2537 switch (fOutputKind) {
2538 case Options::kDynamicLibrary:
2539 case Options::kDynamicExecutable:
2540 case Options::kDynamicBundle:
2541 fDeadStrip = kDeadStripOn;
2542 break;
2543 case Options::kObjectFile:
2544 case Options::kDyld:
2545 case Options::kStaticExecutable:
2546 break;
2547 }
2548 }
2549 }
2550
2551 // allow build system to force on -warn_commons
2552 if ( getenv("LD_WARN_COMMONS") != NULL )
2553 fWarnCommons = true;
2554 }
2555
2556 void Options::reconfigureDefaults()
2557 {
2558 // sync reader options
2559 switch ( fOutputKind ) {
2560 case Options::kObjectFile:
2561 fReaderOptions.fForFinalLinkedImage = false;
2562 break;
2563 case Options::kDyld:
2564 fReaderOptions.fForDyld = true;
2565 fReaderOptions.fForFinalLinkedImage = true;
2566 break;
2567 case Options::kDynamicLibrary:
2568 case Options::kDynamicBundle:
2569 fReaderOptions.fForFinalLinkedImage = true;
2570 break;
2571 case Options::kDynamicExecutable:
2572 case Options::kStaticExecutable:
2573 fReaderOptions.fLinkingMainExecutable = true;
2574 fReaderOptions.fForFinalLinkedImage = true;
2575 break;
2576 }
2577
2578 // set default min OS version
2579 if ( fReaderOptions.fVersionMin == ObjectFile::ReaderOptions::kMinUnset ) {
2580 // if -macosx_version_min not used, try environment variable
2581 const char* envVers = getenv("MACOSX_DEPLOYMENT_TARGET");
2582 if ( envVers != NULL )
2583 setMacOSXVersionMin(envVers);
2584 // if -macosx_version_min and environment variable not used assume current OS version
2585 if ( fReaderOptions.fVersionMin == ObjectFile::ReaderOptions::kMinUnset )
2586 fReaderOptions.fVersionMin = ObjectFile::ReaderOptions::k10_5; // FIX FIX, this really should be a check of the OS version the linker is running on
2587 }
2588
2589 // adjust min based on architecture
2590 switch ( fArchitecture ) {
2591 case CPU_TYPE_I386:
2592 if ( fReaderOptions.fVersionMin < ObjectFile::ReaderOptions::k10_4 ) {
2593 //warning("-macosx_version_min should be 10.4 or later for i386");
2594 fReaderOptions.fVersionMin = ObjectFile::ReaderOptions::k10_4;
2595 }
2596 break;
2597 case CPU_TYPE_POWERPC64:
2598 if ( fReaderOptions.fVersionMin < ObjectFile::ReaderOptions::k10_4 ) {
2599 //warning("-macosx_version_min should be 10.4 or later for ppc64");
2600 fReaderOptions.fVersionMin = ObjectFile::ReaderOptions::k10_4;
2601 }
2602 break;
2603 case CPU_TYPE_X86_64:
2604 if ( fReaderOptions.fVersionMin < ObjectFile::ReaderOptions::k10_4 ) {
2605 //warning("-macosx_version_min should be 10.4 or later for x86_64");
2606 fReaderOptions.fVersionMin = ObjectFile::ReaderOptions::k10_4;
2607 }
2608 break;
2609 }
2610
2611 // disable implicit dylibs when targetting 10.3
2612 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
2613 if ( fReaderOptions.fVersionMin <= ObjectFile::ReaderOptions::k10_3 )
2614 fReaderOptions.fImplicitlyLinkPublicDylibs = false;
2615
2616
2617 // determine if info for shared region should be added
2618 if ( fOutputKind == Options::kDynamicLibrary ) {
2619 if ( fReaderOptions.fVersionMin >= ObjectFile::ReaderOptions::k10_5 )
2620 if ( fArchitecture != CPU_TYPE_ARM )
2621 fSharedRegionEligible = true;
2622 }
2623
2624 // allow build system to force linker to ignore seg_addr_table
2625 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL )
2626 fSegAddrTablePath = NULL;
2627
2628 // check for base address specified externally
2629 if ( (fSegAddrTablePath != NULL) && (fOutputKind == Options::kDynamicLibrary) ) {
2630 parseSegAddrTable(fSegAddrTablePath, this->installPath());
2631 // HACK to support seg_addr_table entries that are physical paths instead of install paths
2632 if ( fBaseAddress == 0 ) {
2633 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 )
2634 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libstdc++.6.0.4.dylib");
2635
2636 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
2637 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libz.1.2.3.dylib");
2638
2639 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
2640 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libutil1.0.dylib");
2641 }
2642 }
2643
2644 // split segs only allowed for dylibs
2645 if ( fSplitSegs ) {
2646 // split seg only supported for ppc, i386, and arm.
2647 switch ( fArchitecture ) {
2648 case CPU_TYPE_POWERPC:
2649 case CPU_TYPE_I386:
2650 if ( fOutputKind != Options::kDynamicLibrary )
2651 fSplitSegs = false;
2652 // make sure read and write segments are proper distance apart
2653 if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x10000000) )
2654 fBaseWritableAddress = fBaseAddress + 0x10000000;
2655 break;
2656 case CPU_TYPE_ARM:
2657 if ( fOutputKind != Options::kDynamicLibrary ) {
2658 fSplitSegs = false;
2659 }
2660 else {
2661 // make sure read and write segments are proper distance apart
2662 if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x08000000) )
2663 fBaseWritableAddress = fBaseAddress + 0x08000000;
2664 }
2665 break;
2666 default:
2667 fSplitSegs = false;
2668 fBaseAddress = 0;
2669 fBaseWritableAddress = 0;
2670 }
2671 }
2672
2673 // disable prebinding depending on arch and min OS version
2674 if ( fPrebind ) {
2675 switch ( fArchitecture ) {
2676 case CPU_TYPE_POWERPC:
2677 case CPU_TYPE_I386:
2678 if ( fReaderOptions.fVersionMin == ObjectFile::ReaderOptions::k10_4 ) {
2679 // in 10.4 only split seg dylibs are prebound
2680 if ( (fOutputKind != Options::kDynamicLibrary) || ! fSplitSegs )
2681 fPrebind = false;
2682 }
2683 else if ( fReaderOptions.fVersionMin >= ObjectFile::ReaderOptions::k10_5 ) {
2684 // in 10.5 nothing is prebound
2685 fPrebind = false;
2686 }
2687 else {
2688 // in 10.3 and earlier only dylibs and main executables could be prebound
2689 switch ( fOutputKind ) {
2690 case Options::kDynamicExecutable:
2691 case Options::kDynamicLibrary:
2692 // only main executables and dylibs can be prebound
2693 break;
2694 case Options::kStaticExecutable:
2695 case Options::kDynamicBundle:
2696 case Options::kObjectFile:
2697 case Options::kDyld:
2698 // disable prebinding for everything else
2699 fPrebind = false;
2700 break;
2701 }
2702 }
2703 break;
2704 case CPU_TYPE_POWERPC64:
2705 case CPU_TYPE_X86_64:
2706 fPrebind = false;
2707 break;
2708 case CPU_TYPE_ARM:
2709 switch ( fOutputKind ) {
2710 case Options::kDynamicExecutable:
2711 case Options::kDynamicLibrary:
2712 // only main executables and dylibs can be prebound
2713 break;
2714 case Options::kStaticExecutable:
2715 case Options::kDynamicBundle:
2716 case Options::kObjectFile:
2717 case Options::kDyld:
2718 // disable prebinding for everything else
2719 fPrebind = false;
2720 break;
2721 }
2722 break;
2723 }
2724 }
2725
2726 // only prebound images can be split-seg
2727 if ( fSplitSegs && !fPrebind )
2728 fSplitSegs = false;
2729
2730 // figure out if module table is needed for compatibility with old ld/dyld
2731 if ( fOutputKind == Options::kDynamicLibrary ) {
2732 switch ( fArchitecture ) {
2733 case CPU_TYPE_POWERPC: // 10.3 and earlier dyld requires a module table
2734 case CPU_TYPE_I386: // ld_classic for 10.4.x requires a module table
2735 if ( fReaderOptions.fVersionMin <= ObjectFile::ReaderOptions::k10_5 )
2736 fNeedsModuleTable = true;
2737 break;
2738 case CPU_TYPE_ARM:
2739 fNeedsModuleTable = true; // redo_prebinding requires a module table
2740 break;
2741 }
2742 }
2743
2744 // <rdar://problem/5366363> -r -x implies -S
2745 if ( (fOutputKind == Options::kObjectFile) && (fLocalSymbolHandling == kLocalSymbolsNone) )
2746 fReaderOptions.fDebugInfoStripping = ObjectFile::ReaderOptions::kDebugInfoNone;
2747
2748 // only ARM main executables can be encrypted
2749 if ( fOutputKind != Options::kDynamicExecutable )
2750 fEncryptable = false;
2751 if ( fArchitecture != CPU_TYPE_ARM )
2752 fEncryptable = false;
2753 }
2754
2755 void Options::checkIllegalOptionCombinations()
2756 {
2757 // check -undefined setting
2758 switch ( fUndefinedTreatment ) {
2759 case kUndefinedError:
2760 case kUndefinedDynamicLookup:
2761 // always legal
2762 break;
2763 case kUndefinedWarning:
2764 case kUndefinedSuppress:
2765 // requires flat namespace
2766 if ( fNameSpace == kTwoLevelNameSpace )
2767 throw "can't use -undefined warning or suppress with -twolevel_namespace";
2768 break;
2769 }
2770
2771 // unify -sub_umbrella with dylibs
2772 for (std::vector<const char*>::iterator it = fSubUmbellas.begin(); it != fSubUmbellas.end(); it++) {
2773 const char* subUmbrella = *it;
2774 bool found = false;
2775 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
2776 Options::FileInfo& info = *fit;
2777 const char* lastSlash = strrchr(info.path, '/');
2778 if ( lastSlash == NULL )
2779 lastSlash = info.path - 1;
2780 if ( strcmp(&lastSlash[1], subUmbrella) == 0 ) {
2781 info.options.fReExport = true;
2782 found = true;
2783 break;
2784 }
2785 }
2786 if ( ! found )
2787 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella);
2788 }
2789
2790 // unify -sub_library with dylibs
2791 for (std::vector<const char*>::iterator it = fSubLibraries.begin(); it != fSubLibraries.end(); it++) {
2792 const char* subLibrary = *it;
2793 bool found = false;
2794 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
2795 Options::FileInfo& info = *fit;
2796 const char* lastSlash = strrchr(info.path, '/');
2797 if ( lastSlash == NULL )
2798 lastSlash = info.path - 1;
2799 const char* dot = strchr(&lastSlash[1], '.');
2800 if ( dot == NULL )
2801 dot = &lastSlash[strlen(lastSlash)];
2802 if ( strncmp(&lastSlash[1], subLibrary, dot-lastSlash-1) == 0 ) {
2803 info.options.fReExport = true;
2804 found = true;
2805 break;
2806 }
2807 }
2808 if ( ! found )
2809 warning("-sub_library %s does not match a supplied dylib", subLibrary);
2810 }
2811
2812 // sync reader options
2813 if ( fNameSpace != kTwoLevelNameSpace )
2814 fReaderOptions.fFlatNamespace = true;
2815
2816 // check -stack_addr
2817 if ( fStackAddr != 0 ) {
2818 switch (fArchitecture) {
2819 case CPU_TYPE_I386:
2820 case CPU_TYPE_POWERPC:
2821 case CPU_TYPE_ARM:
2822 if ( fStackAddr > 0xFFFFFFFF )
2823 throw "-stack_addr must be < 4G for 32-bit processes";
2824 break;
2825 case CPU_TYPE_POWERPC64:
2826 case CPU_TYPE_X86_64:
2827 break;
2828 }
2829 if ( (fStackAddr & -4096) != fStackAddr )
2830 throw "-stack_addr must be multiples of 4K";
2831 if ( fStackSize == 0 )
2832 throw "-stack_addr must be used with -stack_size";
2833 }
2834
2835 // check -stack_size
2836 if ( fStackSize != 0 ) {
2837 switch (fArchitecture) {
2838 case CPU_TYPE_I386:
2839 case CPU_TYPE_POWERPC:
2840 if ( fStackSize > 0xFFFFFFFF )
2841 throw "-stack_size must be < 4G for 32-bit processes";
2842 if ( fStackAddr == 0 ) {
2843 fStackAddr = 0xC0000000;
2844 }
2845 if ( (fStackAddr > 0xB0000000) && ((fStackAddr-fStackSize) < 0xB0000000) )
2846 warning("custom stack placement overlaps and will disable shared region");
2847 break;
2848 case CPU_TYPE_ARM:
2849 if ( fStackSize > 0xFFFFFFFF )
2850 throw "-stack_size must be < 4G for 32-bit processes";
2851 if ( fStackAddr == 0 )
2852 fStackAddr = 0x30000000;
2853 if ( fStackAddr > 0x40000000)
2854 throw "-stack_addr must be < 1G for arm";
2855 case CPU_TYPE_POWERPC64:
2856 case CPU_TYPE_X86_64:
2857 if ( fStackAddr == 0 ) {
2858 fStackAddr = 0x00007FFF5C000000LL;
2859 }
2860 break;
2861 }
2862 if ( (fStackSize & -4096) != fStackSize )
2863 throw "-stack_size must be multiples of 4K";
2864 switch ( fOutputKind ) {
2865 case Options::kDynamicExecutable:
2866 case Options::kStaticExecutable:
2867 // custom stack size only legal when building main executable
2868 break;
2869 case Options::kDynamicLibrary:
2870 case Options::kDynamicBundle:
2871 case Options::kObjectFile:
2872 case Options::kDyld:
2873 throw "-stack_size option can only be used when linking a main executable";
2874 }
2875 }
2876
2877 // check that -allow_stack_execute is only used with main executables
2878 if ( fExecutableStack ) {
2879 switch ( fOutputKind ) {
2880 case Options::kDynamicExecutable:
2881 case Options::kStaticExecutable:
2882 // -allow_stack_execute size only legal when building main executable
2883 break;
2884 case Options::kDynamicLibrary:
2885 case Options::kDynamicBundle:
2886 case Options::kObjectFile:
2887 case Options::kDyld:
2888 throw "-allow_stack_execute option can only be used when linking a main executable";
2889 }
2890 }
2891
2892 // check -client_name is only used when making a bundle or main executable
2893 if ( fClientName != NULL ) {
2894 switch ( fOutputKind ) {
2895 case Options::kDynamicExecutable:
2896 case Options::kDynamicBundle:
2897 break;
2898 case Options::kStaticExecutable:
2899 case Options::kDynamicLibrary:
2900 case Options::kObjectFile:
2901 case Options::kDyld:
2902 throw "-client_name can only be used with -bundle";
2903 }
2904 }
2905
2906 // check -init is only used when building a dylib
2907 if ( (fInitFunctionName != NULL) && (fOutputKind != Options::kDynamicLibrary) )
2908 throw "-init can only be used with -dynamiclib";
2909
2910 // check -bundle_loader only used with -bundle
2911 if ( (fBundleLoader != NULL) && (fOutputKind != Options::kDynamicBundle) )
2912 throw "-bundle_loader can only be used with -bundle";
2913
2914 // check -dtrace not used with -r
2915 if ( (fDtraceScriptName != NULL) && (fOutputKind == Options::kObjectFile) )
2916 throw "-dtrace can only be used when creating final linked images";
2917
2918 // check -d can only be used with -r
2919 if ( fReaderOptions.fMakeTentativeDefinitionsReal && (fOutputKind != Options::kObjectFile) )
2920 throw "-d can only be used with -r";
2921
2922 // check that -root_safe is not used with -r
2923 if ( fReaderOptions.fRootSafe && (fOutputKind == Options::kObjectFile) )
2924 throw "-root_safe cannot be used with -r";
2925
2926 // check that -setuid_safe is not used with -r
2927 if ( fReaderOptions.fSetuidSafe && (fOutputKind == Options::kObjectFile) )
2928 throw "-setuid_safe cannot be used with -r";
2929
2930 // make sure all required exported symbols exist
2931 std::vector<const char*> impliedExports;
2932 for (NameSet::iterator it=fExportSymbols.regularBegin(); it != fExportSymbols.regularEnd(); it++) {
2933 const char* name = *it;
2934 // never export .eh symbols
2935 const int len = strlen(name);
2936 if ( (strcmp(&name[len-3], ".eh") == 0) || (strncmp(name, ".objc_category_name_", 20) == 0) )
2937 warning("ignoring %s in export list", name);
2938 else
2939 fInitialUndefines.push_back(name);
2940 if ( strncmp(name, ".objc_class_name_", 17) == 0 ) {
2941 // rdar://problem/4718189 map ObjC class names to new runtime names
2942 switch (fArchitecture) {
2943 case CPU_TYPE_POWERPC64:
2944 case CPU_TYPE_X86_64:
2945 case CPU_TYPE_ARM:
2946 char* temp;
2947 asprintf(&temp, "_OBJC_CLASS_$_%s", &name[17]);
2948 impliedExports.push_back(temp);
2949 asprintf(&temp, "_OBJC_METACLASS_$_%s", &name[17]);
2950 impliedExports.push_back(temp);
2951 break;
2952 }
2953 }
2954 }
2955 for (std::vector<const char*>::iterator it=impliedExports.begin(); it != impliedExports.end(); it++) {
2956 const char* name = *it;
2957 fExportSymbols.insert(name);
2958 fInitialUndefines.push_back(name);
2959 }
2960
2961 // make sure that -init symbol exist
2962 if ( fInitFunctionName != NULL )
2963 fInitialUndefines.push_back(fInitFunctionName);
2964
2965 // check custom segments
2966 if ( fCustomSegmentAddresses.size() != 0 ) {
2967 // verify no segment is in zero page
2968 if ( fZeroPageSize != ULLONG_MAX ) {
2969 for (std::vector<SegmentStart>::iterator it = fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
2970 if ( (it->address >= 0) && (it->address < fZeroPageSize) )
2971 throwf("-segaddr %s 0x%X conflicts with -pagezero_size", it->name, it->address);
2972 }
2973 }
2974 // verify no duplicates
2975 for (std::vector<SegmentStart>::iterator it = fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
2976 for (std::vector<SegmentStart>::iterator it2 = fCustomSegmentAddresses.begin(); it2 != fCustomSegmentAddresses.end(); ++it2) {
2977 if ( (it->address == it2->address) && (it != it2) )
2978 throwf("duplicate -segaddr addresses for %s and %s", it->name, it2->name);
2979 }
2980 // a custom segment address of zero will disable the use of a zero page
2981 if ( it->address == 0 )
2982 fZeroPageSize = 0;
2983 }
2984 }
2985
2986 if ( fZeroPageSize == ULLONG_MAX ) {
2987 // zero page size not specified on command line, set default
2988 switch (fArchitecture) {
2989 case CPU_TYPE_I386:
2990 case CPU_TYPE_POWERPC:
2991 case CPU_TYPE_ARM:
2992 // first 4KB for 32-bit architectures
2993 fZeroPageSize = 0x1000;
2994 break;
2995 case CPU_TYPE_POWERPC64:
2996 // first 4GB for ppc64 on 10.5
2997 if ( fReaderOptions.fVersionMin >= ObjectFile::ReaderOptions::k10_5 )
2998 fZeroPageSize = 0x100000000ULL;
2999 else
3000 fZeroPageSize = 0x1000; // 10.4 dyld may not be able to handle >4GB zero page
3001 break;
3002 case CPU_TYPE_X86_64:
3003 // first 4GB for x86_64 on all OS's
3004 fZeroPageSize = 0x100000000ULL;
3005 break;
3006 default:
3007 // if -arch not used, default to 4K zero-page
3008 fZeroPageSize = 0x1000;
3009 }
3010 }
3011 else {
3012 switch ( fOutputKind ) {
3013 case Options::kDynamicExecutable:
3014 case Options::kStaticExecutable:
3015 // -pagezero_size size only legal when building main executable
3016 break;
3017 case Options::kDynamicLibrary:
3018 case Options::kDynamicBundle:
3019 case Options::kObjectFile:
3020 case Options::kDyld:
3021 if ( fZeroPageSize != 0 )
3022 throw "-pagezero_size option can only be used when linking a main executable";
3023 }
3024 }
3025
3026 // -dead_strip and -r are incompatible
3027 if ( (fDeadStrip != kDeadStripOff) && (fOutputKind == Options::kObjectFile) )
3028 throw "-r and -dead_strip cannot be used together";
3029
3030 // can't use -rpath unless targeting 10.5 or later
3031 if ( fRPaths.size() > 0 ) {
3032 if ( fReaderOptions.fVersionMin < ObjectFile::ReaderOptions::k10_5 )
3033 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
3034 switch ( fOutputKind ) {
3035 case Options::kDynamicExecutable:
3036 case Options::kDynamicLibrary:
3037 case Options::kDynamicBundle:
3038 break;
3039 case Options::kStaticExecutable:
3040 case Options::kObjectFile:
3041 case Options::kDyld:
3042 throw "-rpath can only be used when creating a dynamic final linked image";
3043 }
3044 }
3045
3046 // check -pie is only used when building a dynamic main executable for 10.5
3047 if ( fPositionIndependentExecutable ) {
3048 if ( fOutputKind != Options::kDynamicExecutable )
3049 throw "-pie can only be used when linking a main executable";
3050 if ( fReaderOptions.fVersionMin < ObjectFile::ReaderOptions::k10_5 )
3051 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
3052 }
3053 }
3054
3055
3056
3057 void Options::checkForClassic(int argc, const char* argv[])
3058 {
3059 // scan options
3060 bool archFound = false;
3061 bool staticFound = false;
3062 bool dtraceFound = false;
3063 bool rFound = false;
3064 bool creatingMachKernel = false;
3065 bool newLinker = false;
3066
3067 for(int i=0; i < argc; ++i) {
3068 const char* arg = argv[i];
3069 if ( arg[0] == '-' ) {
3070 if ( strcmp(arg, "-arch") == 0 ) {
3071 parseArch(argv[++i]);
3072 archFound = true;
3073 }
3074 else if ( strcmp(arg, "-static") == 0 ) {
3075 staticFound = true;
3076 }
3077 else if ( strcmp(arg, "-dtrace") == 0 ) {
3078 dtraceFound = true;
3079 }
3080 else if ( strcmp(arg, "-r") == 0 ) {
3081 rFound = true;
3082 }
3083 else if ( strcmp(arg, "-new_linker") == 0 ) {
3084 newLinker = true;
3085 }
3086 else if ( strcmp(arg, "-classic_linker") == 0 ) {
3087 // ld_classic does not understand this option, so remove it
3088 for(int j=i; j < argc; ++j)
3089 argv[j] = argv[j+1];
3090 this->gotoClassicLinker(argc-1, argv);
3091 }
3092 else if ( strcmp(arg, "-o") == 0 ) {
3093 const char* outfile = argv[++i];
3094 if ( (outfile != NULL) && (strstr(outfile, "/mach_kernel") != NULL) )
3095 creatingMachKernel = true;
3096 }
3097 }
3098 }
3099
3100 // -dtrace only supported by new linker
3101 if( dtraceFound )
3102 return;
3103
3104 if( archFound ) {
3105 switch ( fArchitecture ) {
3106 case CPU_TYPE_POWERPC:
3107 case CPU_TYPE_I386:
3108 case CPU_TYPE_ARM:
3109 // if ( staticFound && (rFound || !creatingMachKernel) ) {
3110 if ( staticFound && !newLinker ) {
3111 // this environment variable will disable use of ld_classic for -static links
3112 if ( getenv("LD_NO_CLASSIC_LINKER_STATIC") == NULL ) {
3113 // ld_classic does not support -aspen_version_min, so change
3114 for(int j=0; j < argc; ++j) {
3115 if ( (strcmp(argv[j], "-aspen_version_min") == 0)
3116 || (strcmp(argv[j], "-iphone_version_min") == 0)
3117 || (strcmp(argv[j], "-iphoneos_version_min") == 0) ) {
3118 argv[j] = "-macosx_version_min";
3119 if ( j < argc-1 )
3120 argv[j+1] = "10.5";
3121 break;
3122 }
3123 }
3124 this->gotoClassicLinker(argc, argv);
3125 }
3126 }
3127 break;
3128 }
3129 }
3130 else {
3131 // work around for VSPTool
3132 if ( staticFound )
3133 this->gotoClassicLinker(argc, argv);
3134 }
3135
3136 }
3137
3138 void Options::gotoClassicLinker(int argc, const char* argv[])
3139 {
3140 argv[0] = "ld_classic";
3141 execvp(argv[0], (char**)argv);
3142 fprintf(stderr, "can't exec ld_classic\n");
3143 exit(1);
3144 }