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