]> git.saurik.com Git - apple/ld64.git/blob - src/Options.cpp
1eb135b0d219cb0480fe591fb0dc6baf6cbee305
[apple/ld64.git] / src / Options.cpp
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2005 Apple Computer, 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 <math.h>
29 #include <fcntl.h>
30 #include <vector>
31
32 #include "Options.h"
33
34 void throwf(const char* format, ...)
35 {
36 va_list list;
37 char* p;
38 va_start(list, format);
39 vasprintf(&p, format, list);
40 va_end(list);
41
42 const char* t = p;
43 throw t;
44 }
45
46 Options::Options(int argc, const char* argv[])
47 : fOutputFile("a.out"), fArchitecture(0), fOutputKind(kDynamicExecutable), fBindAtLoad(false),
48 fStripLocalSymbols(false), fKeepPrivateExterns(false),
49 fInterposable(false), fIgnoreOtherArchFiles(false), fForceSubtypeAll(false), fDeadStrip(kDeadStripOff),
50 fVersionMin(kMinUnset),fNameSpace(kTwoLevelNameSpace),
51 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL), fEntryName("start"), fBaseAddress(0),
52 fExportMode(kExportDefault), fLibrarySearchMode(kSearchAllDirsForDylibsThenAllDirsForArchives),
53 fUndefinedTreatment(kUndefinedError), fMessagesPrefixedWithArchitecture(false), fPICTreatment(kError),
54 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchError), fMultiplyDefinedDynamic(kWarning),
55 fMultiplyDefinedUnused(kSuppress), fWarnOnMultiplyDefined(false), fClientName(NULL),
56 fUmbrellaName(NULL), fInitFunctionName(NULL), fDotOutputFile(NULL), fExecutablePath(NULL), fBundleLoader(NULL),
57 fZeroPageSize(ULLONG_MAX), fStackSize(0), fStackAddr(0), fExecutableStack(false), fMinimumHeaderPad(0),
58 fCommonsMode(kCommonsIgnoreDylibs), fWarnCommons(false), fVerbose(false), fKeepRelocations(false),
59 fEmitUUID(true),fWarnStabs(false),
60 fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
61 fMakeTentativeDefinitionsReal(false)
62 {
63 this->parsePreCommandLineEnvironmentSettings();
64 this->parse(argc, argv);
65 this->parsePostCommandLineEnvironmentSettings();
66 this->reconfigureDefaults();
67 this->checkIllegalOptionCombinations();
68 }
69
70 Options::~Options()
71 {
72 }
73
74 const ObjectFile::ReaderOptions& Options::readerOptions()
75 {
76 return fReaderOptions;
77 }
78
79 cpu_type_t Options::architecture()
80 {
81 return fArchitecture;
82 }
83
84 const char* Options::getOutputFilePath()
85 {
86 return fOutputFile;
87 }
88
89 std::vector<Options::FileInfo>& Options::getInputFiles()
90 {
91 return fInputFiles;
92 }
93
94 Options::OutputKind Options::outputKind()
95 {
96 return fOutputKind;
97 }
98
99 bool Options::stripLocalSymbols()
100 {
101 return fStripLocalSymbols;
102 }
103
104 bool Options::bindAtLoad()
105 {
106 return fBindAtLoad;
107 }
108
109 bool Options::prebind()
110 {
111 return fPrebind;
112 }
113
114 bool Options::fullyLoadArchives()
115 {
116 return fReaderOptions.fFullyLoadArchives;
117 }
118
119 Options::NameSpace Options::nameSpace()
120 {
121 return fNameSpace;
122 }
123
124 const char* Options::installPath()
125 {
126 if ( fDylibInstallName != NULL )
127 return fDylibInstallName;
128 else
129 return fOutputFile;
130 }
131
132 uint32_t Options::currentVersion()
133 {
134 return fDylibCurrentVersion;
135 }
136
137 uint32_t Options::compatibilityVersion()
138 {
139 return fDylibCompatVersion;
140 }
141
142 const char* Options::entryName()
143 {
144 return fEntryName;
145 }
146
147 uint64_t Options::baseAddress()
148 {
149 return fBaseAddress;
150 }
151
152 bool Options::keepPrivateExterns()
153 {
154 return fKeepPrivateExterns;
155 }
156
157 bool Options::interposable()
158 {
159 return fInterposable;
160 }
161
162 bool Options::ignoreOtherArchInputFiles()
163 {
164 return fIgnoreOtherArchFiles;
165 }
166
167 bool Options::forceCpuSubtypeAll()
168 {
169 return fForceSubtypeAll;
170 }
171
172 bool Options::traceDylibs()
173 {
174 return fReaderOptions.fTraceDylibs;
175 }
176
177 bool Options::traceArchives()
178 {
179 return fReaderOptions.fTraceArchives;
180 }
181
182 Options::UndefinedTreatment Options::undefinedTreatment()
183 {
184 return fUndefinedTreatment;
185 }
186
187 Options::VersionMin Options::macosxVersionMin()
188 {
189 return fVersionMin;
190 }
191
192 Options::WeakReferenceMismatchTreatment Options::weakReferenceMismatchTreatment()
193 {
194 return fWeakReferenceMismatchTreatment;
195 }
196
197 Options::Treatment Options::multipleDefinitionsInDylibs()
198 {
199 return fMultiplyDefinedDynamic;
200 }
201
202 Options::Treatment Options::overridingDefinitionInDependentDylib()
203 {
204 return fMultiplyDefinedUnused;
205 }
206
207 bool Options::warnOnMultipleDefinitionsInObjectFiles()
208 {
209 return fWarnOnMultiplyDefined;
210 }
211
212 const char* Options::umbrellaName()
213 {
214 return fUmbrellaName;
215 }
216
217 std::vector<const char*>& Options::allowableClients()
218 {
219 return fAllowableClients;
220 }
221
222 const char* Options::clientName()
223 {
224 return fClientName;
225 }
226
227 uint64_t Options::zeroPageSize()
228 {
229 return fZeroPageSize;
230 }
231
232 bool Options::hasCustomStack()
233 {
234 return (fStackSize != 0);
235 }
236
237 uint64_t Options::customStackSize()
238 {
239 return fStackSize;
240 }
241
242 uint64_t Options::customStackAddr()
243 {
244 return fStackAddr;
245 }
246
247 bool Options::hasExecutableStack()
248 {
249 return fExecutableStack;
250 }
251
252 std::vector<const char*>& Options::initialUndefines()
253 {
254 return fInitialUndefines;
255 }
256
257 bool Options::printWhyLive(const char* symbolName)
258 {
259 return ( fWhyLive.find(symbolName) != fWhyLive.end() );
260 }
261
262 std::vector<const char*>& Options::traceSymbols()
263 {
264 return fTraceSymbols;
265 }
266
267 const char* Options::initFunctionName()
268 {
269 return fInitFunctionName;
270 }
271
272 const char* Options::dotOutputFile()
273 {
274 return fDotOutputFile;
275 }
276
277 bool Options::hasExportRestrictList()
278 {
279 return (fExportMode != kExportDefault);
280 }
281
282 bool Options::allGlobalsAreDeadStripRoots()
283 {
284 // -exported_symbols_list means globals are not exported by default
285 if ( fExportMode == kExportSome )
286 return false;
287 //
288 switch ( fOutputKind ) {
289 case Options::kDynamicExecutable:
290 case Options::kStaticExecutable:
291 // by default unused globals in a main executable are stripped
292 return false;
293 case Options::kDynamicLibrary:
294 case Options::kDynamicBundle:
295 case Options::kObjectFile:
296 case Options::kDyld:
297 return true;
298 }
299 return false;
300 }
301
302 uint32_t Options::minimumHeaderPad()
303 {
304 return fMinimumHeaderPad;
305 }
306
307 std::vector<Options::ExtraSection>& Options::extraSections()
308 {
309 return fExtraSections;
310 }
311
312 std::vector<Options::SectionAlignment>& Options::sectionAlignments()
313 {
314 return fSectionAlignments;
315 }
316
317 Options::CommonsMode Options::commonsMode()
318 {
319 return fCommonsMode;
320 }
321
322 bool Options::warnCommons()
323 {
324 return fWarnCommons;
325 }
326
327 bool Options::keepRelocations()
328 {
329 return fKeepRelocations;
330 }
331
332 bool Options::emitUUID()
333 {
334 return fEmitUUID;
335 }
336
337 bool Options::warnStabs()
338 {
339 return fWarnStabs;
340 }
341
342 const char* Options::executablePath()
343 {
344 return fExecutablePath;
345 }
346
347 Options::DeadStripMode Options::deadStrip()
348 {
349 return fDeadStrip;
350 }
351
352 bool Options::shouldExport(const char* symbolName)
353 {
354 switch (fExportMode) {
355 case kExportSome:
356 return ( fExportSymbols.find(symbolName) != fExportSymbols.end() );
357 case kDontExportSome:
358 return ( fDontExportSymbols.find(symbolName) == fDontExportSymbols.end() );
359 case kExportDefault:
360 return true;
361 }
362 throw "internal error";
363 }
364
365 void Options::parseArch(const char* architecture)
366 {
367 if ( architecture == NULL )
368 throw "-arch must be followed by an architecture string";
369 if ( strcmp(architecture, "ppc") == 0 )
370 fArchitecture = CPU_TYPE_POWERPC;
371 else if ( strcmp(architecture, "ppc64") == 0 )
372 fArchitecture = CPU_TYPE_POWERPC64;
373 else if ( strcmp(architecture, "i386") == 0 )
374 fArchitecture = CPU_TYPE_I386;
375 else if ( strcmp(architecture, "x86_64") == 0 )
376 fArchitecture = CPU_TYPE_X86_64;
377 // compatibility support for cpu-sub-types
378 else if ( (strcmp(architecture, "ppc750") == 0)
379 || (strcmp(architecture, "ppc7400") == 0)
380 || (strcmp(architecture, "ppc7450") == 0)
381 || (strcmp(architecture, "ppc970") == 0) )
382 fArchitecture = CPU_TYPE_POWERPC;
383 else
384 throwf(" unknown/unsupported architecture name for: -arch %s", architecture);
385 }
386
387 bool Options::checkForFile(const char* format, const char* dir, const char* rootName, FileInfo& result)
388 {
389 struct stat statBuffer;
390 char possiblePath[strlen(dir)+strlen(rootName)+strlen(format)+8];
391 sprintf(possiblePath, format, dir, rootName);
392 bool found = (stat(possiblePath, &statBuffer) == 0);
393 if ( fTraceDylibSearching )
394 printf("[Logging for XBS]%sfound library: '%s'\n", (found ? " " : " not "), possiblePath);
395 if ( found ) {
396 result.path = strdup(possiblePath);
397 result.fileLen = statBuffer.st_size;
398 result.modTime = statBuffer.st_mtime;
399 return true;
400 }
401 return false;
402 }
403
404
405 Options::FileInfo Options::findLibrary(const char* rootName)
406 {
407 FileInfo result;
408 const int rootNameLen = strlen(rootName);
409 // if rootName ends in .o there is no .a vs .dylib choice
410 if ( (rootNameLen > 3) && (strcmp(&rootName[rootNameLen-2], ".o") == 0) ) {
411 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
412 it != fLibrarySearchPaths.end();
413 it++) {
414 const char* dir = *it;
415 if ( checkForFile("%s/%s", dir, rootName, result) )
416 return result;
417 }
418 }
419 else {
420 bool lookForDylibs = ( fOutputKind != Options::kDyld);
421 switch ( fLibrarySearchMode ) {
422 case kSearchAllDirsForDylibsThenAllDirsForArchives:
423 // first look in all directories for just for dylibs
424 if ( lookForDylibs ) {
425 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
426 it != fLibrarySearchPaths.end();
427 it++) {
428 const char* dir = *it;
429 if ( checkForFile("%s/lib%s.dylib", dir, rootName, result) )
430 return result;
431 }
432 }
433 // next look in all directories for just for archives
434 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
435 it != fLibrarySearchPaths.end();
436 it++) {
437 const char* dir = *it;
438 if ( checkForFile("%s/lib%s.a", dir, rootName, result) )
439 return result;
440 }
441 break;
442
443 case kSearchDylibAndArchiveInEachDir:
444 // look in each directory for just for a dylib then for an archive
445 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
446 it != fLibrarySearchPaths.end();
447 it++) {
448 const char* dir = *it;
449 if ( lookForDylibs && checkForFile("%s/lib%s.dylib", dir, rootName, result) )
450 return result;
451 if ( checkForFile("%s/lib%s.a", dir, rootName, result) )
452 return result;
453 }
454 break;
455 }
456 }
457 throwf("library not found for -l%s", rootName);
458 }
459
460 Options::FileInfo Options::findFramework(const char* frameworkName)
461 {
462 if ( frameworkName == NULL )
463 throw "-frameowrk missing next argument";
464 char temp[strlen(frameworkName)+1];
465 strcpy(temp, frameworkName);
466 const char* name = temp;
467 const char* suffix = NULL;
468 char* comma = strchr(temp, ',');
469 if ( comma != NULL ) {
470 *comma = '\0';
471 suffix = &comma[1];
472 }
473 return findFramework(name, suffix);
474 }
475
476 Options::FileInfo Options::findFramework(const char* rootName, const char* suffix)
477 {
478 struct stat statBuffer;
479 for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin();
480 it != fFrameworkSearchPaths.end();
481 it++) {
482 // ??? Shouldn't we be using String here and just initializing it?
483 // ??? Use str.c_str () to pull out the string for the stat call.
484 const char* dir = *it;
485 char possiblePath[PATH_MAX];
486 strcpy(possiblePath, dir);
487 strcat(possiblePath, "/");
488 strcat(possiblePath, rootName);
489 strcat(possiblePath, ".framework/");
490 strcat(possiblePath, rootName);
491 if ( suffix != NULL ) {
492 char realPath[PATH_MAX];
493 // no symlink in framework to suffix variants, so follow main symlink
494 if ( realpath(possiblePath, realPath) != NULL ) {
495 strcpy(possiblePath, realPath);
496 strcat(possiblePath, suffix);
497 }
498 }
499 bool found = (stat(possiblePath, &statBuffer) == 0);
500 if ( fTraceDylibSearching )
501 printf("[Logging for XBS]%sfound framework: '%s'\n",
502 (found ? " " : " not "), possiblePath);
503 if ( found ) {
504 FileInfo result;
505 result.path = strdup(possiblePath);
506 result.fileLen = statBuffer.st_size;
507 result.modTime = statBuffer.st_mtime;
508 return result;
509 }
510 }
511 // try without suffix
512 if ( suffix != NULL )
513 return findFramework(rootName, NULL);
514 else
515 throwf("framework not found %s", rootName);
516 }
517
518 Options::FileInfo Options::findFile(const char* path)
519 {
520 FileInfo result;
521 struct stat statBuffer;
522
523 // if absolute path and not a .o file, the use SDK prefix
524 if ( (path[0] == '/') && (strcmp(&path[strlen(path)-2], ".o") != 0) ) {
525 const int pathLen = strlen(path);
526 for (std::vector<const char*>::iterator it = fSDKPaths.begin(); it != fSDKPaths.end(); it++) {
527 // ??? Shouldn't we be using String here?
528 const char* sdkPathDir = *it;
529 const int sdkPathDirLen = strlen(sdkPathDir);
530 char possiblePath[sdkPathDirLen+pathLen+4];
531 strcpy(possiblePath, sdkPathDir);
532 if ( possiblePath[sdkPathDirLen-1] == '/' )
533 possiblePath[sdkPathDirLen-1] = '\0';
534 strcat(possiblePath, path);
535 if ( stat(possiblePath, &statBuffer) == 0 ) {
536 result.path = strdup(possiblePath);
537 result.fileLen = statBuffer.st_size;
538 result.modTime = statBuffer.st_mtime;
539 return result;
540 }
541 }
542 }
543 // try raw path
544 if ( stat(path, &statBuffer) == 0 ) {
545 result.path = strdup(path);
546 result.fileLen = statBuffer.st_size;
547 result.modTime = statBuffer.st_mtime;
548 return result;
549 }
550
551 // try @executable_path substitution
552 if ( (strncmp(path, "@executable_path/", 17) == 0) && (fExecutablePath != NULL) ) {
553 char newPath[strlen(fExecutablePath) + strlen(path)];
554 strcpy(newPath, fExecutablePath);
555 char* addPoint = strrchr(newPath,'/');
556 if ( addPoint != NULL )
557 strcpy(&addPoint[1], &path[17]);
558 else
559 strcpy(newPath, &path[17]);
560 if ( stat(newPath, &statBuffer) == 0 ) {
561 result.path = strdup(newPath);
562 result.fileLen = statBuffer.st_size;
563 result.modTime = statBuffer.st_mtime;
564 return result;
565 }
566 }
567
568 // not found
569 throwf("file not found: %s", path);
570 }
571
572
573 void Options::loadFileList(const char* fileOfPaths)
574 {
575 FILE* file;
576 const char* comma = strrchr(fileOfPaths, ',');
577 const char* prefix = NULL;
578 if ( comma != NULL ) {
579 prefix = comma+1;
580 int realFileOfPathsLen = comma-fileOfPaths;
581 char realFileOfPaths[realFileOfPathsLen+1];
582 strncpy(realFileOfPaths,fileOfPaths, realFileOfPathsLen);
583 realFileOfPaths[realFileOfPathsLen] = '\0';
584 file = fopen(realFileOfPaths, "r");
585 if ( file == NULL )
586 throwf("-filelist file not found: %s\n", realFileOfPaths);
587 }
588 else {
589 file = fopen(fileOfPaths, "r");
590 if ( file == NULL )
591 throwf("-filelist file not found: %s\n", fileOfPaths);
592 }
593
594 char path[PATH_MAX];
595 while ( fgets(path, 1024, file) != NULL ) {
596 path[PATH_MAX-1] = '\0';
597 char* eol = strchr(path, '\n');
598 if ( eol != NULL )
599 *eol = '\0';
600 if ( prefix != NULL ) {
601 char builtPath[strlen(prefix)+strlen(path)+2];
602 strcpy(builtPath, prefix);
603 strcat(builtPath, "/");
604 strcat(builtPath, path);
605 fInputFiles.push_back(findFile(builtPath));
606 }
607 else {
608 fInputFiles.push_back(findFile(path));
609 }
610 }
611 fclose(file);
612 }
613
614
615 void Options::loadExportFile(const char* fileOfExports, const char* option, NameSet& set)
616 {
617 // read in whole file
618 int fd = ::open(fileOfExports, O_RDONLY, 0);
619 if ( fd == -1 )
620 throwf("can't open %s file: %s", option, fileOfExports);
621 struct stat stat_buf;
622 ::fstat(fd, &stat_buf);
623 char* p = (char*)malloc(stat_buf.st_size);
624 if ( p == NULL )
625 throwf("can't process %s file: %s", option, fileOfExports);
626
627 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
628 throwf("can't read %s file: %s", option, fileOfExports);
629
630 ::close(fd);
631
632 // parse into symbols and add to hash_set
633 char * const end = &p[stat_buf.st_size];
634 enum { lineStart, inSymbol, inComment } state = lineStart;
635 char* symbolStart = NULL;
636 for (char* s = p; s < end; ++s ) {
637 switch ( state ) {
638 case lineStart:
639 if ( *s =='#' ) {
640 state = inComment;
641 }
642 else if ( !isspace(*s) ) {
643 state = inSymbol;
644 symbolStart = s;
645 }
646 break;
647 case inSymbol:
648 if ( *s == '\n' ) {
649 *s = '\0';
650 // removing any trailing spaces
651 char* last = s-1;
652 while ( isspace(*last) ) {
653 *last = '\0';
654 --last;
655 }
656 set.insert(symbolStart);
657 symbolStart = NULL;
658 state = lineStart;
659 }
660 break;
661 case inComment:
662 if ( *s == '\n' )
663 state = lineStart;
664 break;
665 }
666 }
667 if ( state == inSymbol ) {
668 fprintf(stderr, "ld64 warning: missing line-end at end of file \"%s\"\n", fileOfExports);
669 int len = end-symbolStart+1;
670 char* temp = new char[len];
671 strlcpy(temp, symbolStart, len);
672
673 // remove any trailing spaces
674 char* last = &temp[len-2];
675 while ( isspace(*last) ) {
676 *last = '\0';
677 --last;
678 }
679 set.insert(temp);
680 }
681
682 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
683 }
684
685 void Options::setUndefinedTreatment(const char* treatment)
686 {
687 if ( treatment == NULL )
688 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
689
690 if ( strcmp(treatment, "warning") == 0 )
691 fUndefinedTreatment = kUndefinedWarning;
692 else if ( strcmp(treatment, "error") == 0 )
693 fUndefinedTreatment = kUndefinedError;
694 else if ( strcmp(treatment, "suppress") == 0 )
695 fUndefinedTreatment = kUndefinedSuppress;
696 else if ( strcmp(treatment, "dynamic_lookup") == 0 )
697 fUndefinedTreatment = kUndefinedDynamicLookup;
698 else
699 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
700 }
701
702 Options::Treatment Options::parseTreatment(const char* treatment)
703 {
704 if ( treatment == NULL )
705 return kNULL;
706
707 if ( strcmp(treatment, "warning") == 0 )
708 return kWarning;
709 else if ( strcmp(treatment, "error") == 0 )
710 return kError;
711 else if ( strcmp(treatment, "suppress") == 0 )
712 return kSuppress;
713 else
714 return kInvalid;
715 }
716
717 void Options::setVersionMin(const char* version)
718 {
719 if ( version == NULL )
720 throw "-macosx_version_min argument missing";
721
722 if ( (strncmp(version, "10.", 3) == 0) && isdigit(version[3]) ) {
723 int num = version[3] - '0';
724 switch ( num ) {
725 case 0:
726 case 1:
727 fVersionMin = k10_1;
728 break;
729 case 2:
730 fVersionMin = k10_2;
731 break;
732 case 3:
733 fVersionMin = k10_3;
734 break;
735 case 4:
736 fVersionMin = k10_4;
737 break;
738 default:
739 fVersionMin = k10_5;
740 break;
741 }
742 }
743 else {
744 fprintf(stderr, "ld64: unknown option to -macosx_version_min not 10.x");
745 }
746 }
747
748 void Options::setWeakReferenceMismatchTreatment(const char* treatment)
749 {
750 if ( treatment == NULL )
751 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
752
753 if ( strcmp(treatment, "error") == 0 )
754 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchError;
755 else if ( strcmp(treatment, "weak") == 0 )
756 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchWeak;
757 else if ( strcmp(treatment, "non-weak") == 0 )
758 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchNonWeak;
759 else
760 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
761 }
762
763 Options::CommonsMode Options::parseCommonsTreatment(const char* mode)
764 {
765 if ( mode == NULL )
766 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
767
768 if ( strcmp(mode, "ignore_dylibs") == 0 )
769 return kCommonsIgnoreDylibs;
770 else if ( strcmp(mode, "use_dylibs") == 0 )
771 return kCommonsOverriddenByDylibs;
772 else if ( strcmp(mode, "error") == 0 )
773 return kCommonsConflictsDylibsError;
774 else
775 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
776 }
777
778 void Options::setDylibInstallNameOverride(const char* paths)
779 {
780
781
782 }
783
784 uint64_t Options::parseAddress(const char* addr)
785 {
786 char* endptr;
787 uint64_t result = strtoull(addr, &endptr, 16);
788 return result;
789 }
790
791 //
792 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
793 //
794 //
795 uint32_t Options::parseVersionNumber(const char* versionString)
796 {
797 unsigned long x = 0;
798 unsigned long y = 0;
799 unsigned long z = 0;
800 char* end;
801 x = strtoul(versionString, &end, 10);
802 if ( *end == '.' ) {
803 y = strtoul(&end[1], &end, 10);
804 if ( *end == '.' ) {
805 z = strtoul(&end[1], &end, 10);
806 }
807 }
808 if ( (*end != '\0') || (x > 0xffff) || (y > 0xff) || (z > 0xff) )
809 throwf("malformed version number: %s", versionString);
810
811 return (x << 16) | ( y << 8 ) | z;
812 }
813
814 void Options::parseSectionOrderFile(const char* segment, const char* section, const char* path)
815 {
816 fprintf(stderr, "ld64: warning -sectorder not yet supported for 64-bit code\n");
817 }
818
819 void Options::addSection(const char* segment, const char* section, const char* path)
820 {
821 if ( strlen(segment) > 16 )
822 throw "-seccreate segment name max 16 chars";
823 if ( strlen(section) > 16 ) {
824 char* tmp = strdup(section);
825 tmp[16] = '\0';
826 fprintf(stderr, "ld64 warning: -seccreate section name (%s) truncated to 16 chars (%s)\n", section, tmp);
827 section = tmp;
828 }
829
830 // read in whole file
831 int fd = ::open(path, O_RDONLY, 0);
832 if ( fd == -1 )
833 throwf("can't open -sectcreate file: %s", path);
834 struct stat stat_buf;
835 ::fstat(fd, &stat_buf);
836 char* p = (char*)malloc(stat_buf.st_size);
837 if ( p == NULL )
838 throwf("can't process -sectcreate file: %s", path);
839 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
840 throwf("can't read -sectcreate file: %s", path);
841 ::close(fd);
842
843 // record section to create
844 ExtraSection info = { segment, section, path, (uint8_t*)p, stat_buf.st_size };
845 fExtraSections.push_back(info);
846 }
847
848 void Options::addSectionAlignment(const char* segment, const char* section, const char* alignmentStr)
849 {
850 if ( strlen(segment) > 16 )
851 throw "-sectalign segment name max 16 chars";
852 if ( strlen(section) > 16 )
853 throw "-sectalign section name max 16 chars";
854
855 // argument to -sectalign is a hexadecimal number
856 char* endptr;
857 unsigned long value = strtoul(alignmentStr, &endptr, 16);
858 if ( *endptr != '\0')
859 throw "argument for -sectalign is not a hexadecimal number";
860 if ( value > 0x8000 )
861 throw "argument for -sectalign must be less than or equal to 0x8000";
862 if ( value == 0 ) {
863 fprintf(stderr, "ld64 warning: zero is not a valid -sectalign\n");
864 value = 1;
865 }
866
867 // alignment is power of 2 (e.g. page alignment = 12)
868 uint8_t alignment = (uint8_t)log2(value);
869
870 if ( (unsigned long)(1 << alignment) != value ) {
871 fprintf(stderr, "ld64 warning: alignment for -sectalign %s %s is not a power of two, using 0x%X\n",
872 segment, section, 1 << alignment);
873 }
874
875 SectionAlignment info = { segment, section, alignment };
876 fSectionAlignments.push_back(info);
877 }
878
879 //
880 // Process all command line arguments.
881 //
882 // The only error checking done here is that each option is valid and if it has arguments
883 // that they too are valid.
884 //
885 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
886 // whichever was last on the command line is used.
887 //
888 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
889 //
890 void Options::parse(int argc, const char* argv[])
891 {
892 // pass one builds search list from -L and -F options
893 this->buildSearchPaths(argc, argv);
894
895 // reduce re-allocations
896 fInputFiles.reserve(32);
897
898 // pass two parse all other options
899 for(int i=1; i < argc; ++i) {
900 const char* arg = argv[i];
901
902 if ( arg[0] == '-' ) {
903
904 // Since we don't care about the files passed, just the option names, we do this here.
905 if (fPrintOptions)
906 fprintf (stderr, "[Logging ld64 options]\t%s\n", arg);
907
908 if ( (arg[1] == 'L') || (arg[1] == 'F') ) {
909 // previously handled by buildSearchPaths()
910 }
911 else if ( strcmp(arg, "-arch") == 0 ) {
912 parseArch(argv[++i]);
913 }
914 else if ( strcmp(arg, "-dynamic") == 0 ) {
915 // default
916 }
917 else if ( strcmp(arg, "-static") == 0 ) {
918 fOutputKind = kStaticExecutable;
919 }
920 else if ( strcmp(arg, "-dylib") == 0 ) {
921 fOutputKind = kDynamicLibrary;
922 }
923 else if ( strcmp(arg, "-bundle") == 0 ) {
924 fOutputKind = kDynamicBundle;
925 }
926 else if ( strcmp(arg, "-dylinker") == 0 ) {
927 fOutputKind = kDyld;
928 }
929 else if ( strcmp(arg, "-execute") == 0 ) {
930 if ( fOutputKind != kStaticExecutable )
931 fOutputKind = kDynamicExecutable;
932 }
933 else if ( strcmp(arg, "-r") == 0 ) {
934 fOutputKind = kObjectFile;
935 }
936 else if ( strcmp(arg, "-o") == 0 ) {
937 fOutputFile = argv[++i];
938 }
939 else if ( arg[1] == 'l' ) {
940 fInputFiles.push_back(findLibrary(&arg[2]));
941 }
942 // This causes a dylib to be weakly bound at
943 // link time. This corresponds to weak_import.
944 else if ( strncmp(arg, "-weak-l", 7) == 0 ) {
945 FileInfo info = findLibrary(&arg[7]);
946 info.options.fWeakImport = true;
947 fInputFiles.push_back(info);
948 }
949 // Avoid lazy binding.
950 // ??? Deprecate.
951 else if ( strcmp(arg, "-bind_at_load") == 0 ) {
952 fBindAtLoad = true;
953 }
954 else if ( strcmp(arg, "-twolevel_namespace") == 0 ) {
955 fNameSpace = kTwoLevelNameSpace;
956 }
957 else if ( strcmp(arg, "-flat_namespace") == 0 ) {
958 fNameSpace = kFlatNameSpace;
959 }
960 // Also sets a bit to ensure dyld causes everything
961 // in the namespace to be flat.
962 // ??? Deprecate
963 else if ( strcmp(arg, "-force_flat_namespace") == 0 ) {
964 fNameSpace = kForceFlatNameSpace;
965 }
966 // Similar to --whole-archive.
967 else if ( strcmp(arg, "-all_load") == 0 ) {
968 fReaderOptions.fFullyLoadArchives = true;
969 }
970 // Similar to --whole-archive, but for all ObjC classes.
971 else if ( strcmp(arg, "-ObjC") == 0 ) {
972 fReaderOptions.fLoadObjcClassesInArchives = true;
973 }
974 // Library versioning.
975 else if ( strcmp(arg, "-dylib_compatibility_version") == 0 ) {
976 fDylibCompatVersion = parseVersionNumber(argv[++i]);
977 }
978 else if ( strcmp(arg, "-dylib_current_version") == 0 ) {
979 fDylibCurrentVersion = parseVersionNumber(argv[++i]);
980 }
981 else if ( strcmp(arg, "-sectorder") == 0 ) {
982 parseSectionOrderFile(argv[i+1], argv[i+2], argv[i+3]);
983 i += 3;
984 }
985 // ??? Deprecate segcreate.
986 // -sectcreate puts whole files into a section in the output.
987 else if ( (strcmp(arg, "-sectcreate") == 0) || (strcmp(arg, "-segcreate") == 0) ) {
988 addSection(argv[i+1], argv[i+2], argv[i+3]);
989 i += 3;
990 }
991 // Since we have a full path in binary/library names we need to be able to override it.
992 else if ( (strcmp(arg, "-dylib_install_name") == 0) || (strcmp(arg, "-dylinker_install_name") == 0) ) {
993 fDylibInstallName = argv[++i];
994 }
995 // Sets the base address of the output.
996 else if ( (strcmp(arg, "-seg1addr") == 0) || (strcmp(arg, "-image_base") == 0) ) {
997 fBaseAddress = parseAddress(argv[++i]);
998 }
999 else if ( strcmp(arg, "-e") == 0 ) {
1000 fEntryName = argv[++i];
1001 }
1002 // Same as -@ from the FSF linker.
1003 else if ( strcmp(arg, "-filelist") == 0 ) {
1004 loadFileList(argv[++i]);
1005 }
1006 else if ( strcmp(arg, "-keep_private_externs") == 0 ) {
1007 fKeepPrivateExterns = true;
1008 }
1009 // ??? Deprecate
1010 else if ( strcmp(arg, "-final_output") == 0 ) {
1011 ++i;
1012 // ignore for now
1013 }
1014 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
1015 // just ensures that this happens for cross object file boundaries.
1016 else if ( (strcmp(arg, "-interposable") == 0) || (strcmp(arg, "-multi_module") == 0)) {
1017 fInterposable = true;
1018 }
1019 // Default for -interposable/-multi_module/-single_module.
1020 else if ( strcmp(arg, "-single_module") == 0 ) {
1021 fInterposable = false;
1022 }
1023 else if ( strcmp(arg, "-exported_symbols_list") == 0 ) {
1024 if ( fExportMode == kDontExportSome )
1025 throw "can't use -exported_symbols_list and -unexported_symbols_list";
1026 fExportMode = kExportSome;
1027 loadExportFile(argv[++i], "-exported_symbols_list", fExportSymbols);
1028 }
1029 else if ( strcmp(arg, "-unexported_symbols_list") == 0 ) {
1030 if ( fExportMode == kExportSome )
1031 throw "can't use -exported_symbols_list and -unexported_symbols_list";
1032 fExportMode = kDontExportSome;
1033 loadExportFile(argv[++i], "-unexported_symbols_list", fDontExportSymbols);
1034 }
1035 // ??? Deprecate
1036 else if ( strcmp(arg, "-no_arch_warnings") == 0 ) {
1037 fIgnoreOtherArchFiles = true;
1038 }
1039 else if ( strcmp(arg, "-force_cpusubtype_ALL") == 0 ) {
1040 fForceSubtypeAll = true;
1041 }
1042 // Similar to -weak-l but uses the absolute path name to the library.
1043 else if ( strcmp(arg, "-weak_library") == 0 ) {
1044 FileInfo info = findFile(argv[++i]);
1045 info.options.fWeakImport = true;
1046 fInputFiles.push_back(info);
1047 }
1048 else if ( strcmp(arg, "-framework") == 0 ) {
1049 fInputFiles.push_back(findFramework(argv[++i]));
1050 }
1051 else if ( strcmp(arg, "-weak_framework") == 0 ) {
1052 FileInfo info = findFramework(argv[++i]);
1053 info.options.fWeakImport = true;
1054 fInputFiles.push_back(info);
1055 }
1056 // ??? Deprecate when we get -Bstatic/-Bdynamic.
1057 else if ( strcmp(arg, "-search_paths_first") == 0 ) {
1058 fLibrarySearchMode = kSearchDylibAndArchiveInEachDir;
1059 }
1060 else if ( strcmp(arg, "-undefined") == 0 ) {
1061 setUndefinedTreatment(argv[++i]);
1062 }
1063 // Debugging output flag.
1064 else if ( strcmp(arg, "-arch_multiple") == 0 ) {
1065 fMessagesPrefixedWithArchitecture = true;
1066 }
1067 // Specify what to do with relocations in read only
1068 // sections like .text. Could be errors, warnings,
1069 // or suppressed. Currently we do nothing with the
1070 // flag.
1071 else if ( strcmp(arg, "-read_only_relocs") == 0 ) {
1072 Treatment temp = parseTreatment(argv[++i]);
1073
1074 if ( temp == kNULL )
1075 throw "-read_only_relocs missing [ warning | error | suppress ]";
1076 else if ( temp == kInvalid )
1077 throw "invalid option to -read_only_relocs [ warning | error | suppress ]";
1078 }
1079 // Specifies whether or not there are intra section
1080 // relocations and what to do when found. Could be
1081 // errors, warnings, or suppressed.
1082 else if ( strcmp(arg, "-sect_diff_relocs") == 0 ) {
1083 fPICTreatment = parseTreatment(argv[++i]);
1084
1085 if ( fPICTreatment == kNULL )
1086 throw "-sect_diff_relocs missing [ warning | error | suppress ]";
1087 else if ( fPICTreatment == kInvalid )
1088 throw "invalid option to -sect_diff_relocs [ warning | error | suppress ]";
1089 }
1090 // Warn, error or make strong a mismatch between weak
1091 // and non-weak references.
1092 else if ( strcmp(arg, "-weak_reference_mismatches") == 0 ) {
1093 setWeakReferenceMismatchTreatment(argv[++i]);
1094 }
1095 // For a deployment target of 10.3 and earlier ld64 will
1096 // prebind an executable with 0s in all addresses that
1097 // are prebound. This can then be fixed up by update_prebinding
1098 // later. Prebinding is less useful on 10.4 and greater.
1099 else if ( strcmp(arg, "-prebind") == 0 ) {
1100 fPrebind = true;
1101 }
1102 else if ( strcmp(arg, "-noprebind") == 0 ) {
1103 fPrebind = false;
1104 }
1105 // ??? Deprecate
1106 else if ( strcmp(arg, "-prebind_allow_overlap") == 0 ) {
1107 // Do not handle and suppress warnings always.
1108 }
1109 // ??? Deprecate
1110 else if ( strcmp(arg, "-prebind_all_twolevel_modules") == 0 ) {
1111 // Ignore.
1112 }
1113 // ??? Deprecate
1114 else if ( strcmp(arg, "-noprebind_all_twolevel_modules") == 0 ) {
1115 // Ignore.
1116 }
1117 // Sets a bit in the main executable only that causes fix_prebinding
1118 // not to run. This is always set.
1119 else if ( strcmp(arg, "-nofixprebinding") == 0 ) {
1120 // Ignore.
1121 }
1122 // This should probably be deprecated when we respect -L and -F
1123 // when searching for libraries.
1124 else if ( strcmp(arg, "-dylib_file") == 0 ) {
1125 setDylibInstallNameOverride(argv[++i]);
1126 }
1127 // Allows us to rewrite full paths to be relocatable based on
1128 // the path name of the executable.
1129 else if ( strcmp(arg, "-executable_path") == 0 ) {
1130 fExecutablePath = argv[++i];
1131 if ( (fExecutablePath == NULL) || (fExecutablePath[0] == '-') )
1132 throw "-executable_path missing <path>";
1133 }
1134 // ??? Deprecate
1135 // Aligns all segments to the power of 2 boundary specified.
1136 else if ( strcmp(arg, "-segalign") == 0 ) {
1137 // Ignore.
1138 ++i;
1139 }
1140 // Puts a specified segment at a particular address that must
1141 // be a multiple of the segment alignment.
1142 else if ( strcmp(arg, "-segaddr") == 0 ) {
1143 // FIX FIX
1144 i += 2;
1145 }
1146 // ??? Deprecate when we deprecate split-seg.
1147 else if ( strcmp(arg, "-segs_read_only_addr") == 0 ) {
1148 // Ignore.
1149 ++i;
1150 }
1151 // ??? Deprecate when we deprecate split-seg.
1152 else if ( strcmp(arg, "-segs_read_write_addr") == 0 ) {
1153 // Ignore.
1154 ++i;
1155 }
1156 // ??? Deprecate when we get rid of basing at build time.
1157 else if ( strcmp(arg, "-seg_addr_table") == 0 ) {
1158 // Ignore.
1159 ++i;
1160 }
1161 // ??? Deprecate.
1162 else if ( strcmp(arg, "-seg_addr_table_filename") == 0 ) {
1163 // Ignore.
1164 ++i;
1165 }
1166 else if ( strcmp(arg, "-segprot") == 0 ) {
1167 // FIX FIX
1168 i += 3;
1169 }
1170 else if ( strcmp(arg, "-pagezero_size") == 0 ) {
1171 fZeroPageSize = parseAddress(argv[++i]);
1172 uint64_t temp = fZeroPageSize & (-4096); // page align
1173 if ( fZeroPageSize != temp )
1174 fprintf(stderr, "ld64: warning, -pagezero_size not page aligned, rounding down\n");
1175 fZeroPageSize = temp;
1176 }
1177 else if ( strcmp(arg, "-stack_addr") == 0 ) {
1178 fStackAddr = parseAddress(argv[++i]);
1179 }
1180 else if ( strcmp(arg, "-stack_size") == 0 ) {
1181 fStackSize = parseAddress(argv[++i]);
1182 }
1183 else if ( strcmp(arg, "-allow_stack_execute") == 0 ) {
1184 fExecutableStack = true;
1185 }
1186 else if ( strcmp(arg, "-sectalign") == 0 ) {
1187 addSectionAlignment(argv[i+1], argv[i+2], argv[i+3]);
1188 i += 3;
1189 }
1190 else if ( strcmp(arg, "-sectorder_detail") == 0 ) {
1191 // FIX FIX
1192 }
1193 else if ( strcmp(arg, "-sectobjectsymbols") == 0 ) {
1194 // FIX FIX
1195 i += 2;
1196 }
1197 else if ( strcmp(arg, "-bundle_loader") == 0 ) {
1198 fBundleLoader = argv[++i];
1199 if ( (fBundleLoader == NULL) || (fBundleLoader[0] == '-') )
1200 throw "-bundle_loader missing <path>";
1201 FileInfo info = findFile(fBundleLoader);
1202 info.options.fBundleLoader = true;
1203 fInputFiles.push_back(info);
1204 }
1205 else if ( strcmp(arg, "-private_bundle") == 0 ) {
1206 // FIX FIX
1207 }
1208 else if ( strcmp(arg, "-twolevel_namespace_hints") == 0 ) {
1209 // FIX FIX
1210 }
1211 // Use this flag to set default behavior for deployement targets.
1212 else if ( strcmp(arg, "-macosx_version_min") == 0 ) {
1213 setVersionMin(argv[++i]);
1214 }
1215 // This option (unlike -m below) only affects how we warn
1216 // on multiple definitions inside dynamic libraries.
1217 else if ( strcmp(arg, "-multiply_defined") == 0 ) {
1218 fMultiplyDefinedDynamic = parseTreatment(argv[++i]);
1219
1220 if ( fMultiplyDefinedDynamic == kNULL )
1221 throw "-multiply_defined missing [ warning | error | suppress ]";
1222 else if ( fMultiplyDefinedDynamic == kInvalid )
1223 throw "invalid option to -multiply_defined [ warning | error | suppress ]";
1224 }
1225 else if ( strcmp(arg, "-multiply_defined_unused") == 0 ) {
1226 fMultiplyDefinedUnused = parseTreatment(argv[++i]);
1227
1228 if ( fMultiplyDefinedUnused == kNULL )
1229 throw "-multiply_defined_unused missing [ warning | error | suppress ]";
1230 else if ( fMultiplyDefinedUnused == kInvalid )
1231 throw "invalid option to -multiply_defined_unused [ warning | error | suppress ]";
1232 }
1233 else if ( strcmp(arg, "-nomultidefs") == 0 ) {
1234 // FIX FIX
1235 }
1236 // Display each file in which the argument symbol appears and whether
1237 // the file defines or references it. This option takes an argument
1238 // as -y<symbol> note that there is no space.
1239 else if ( strncmp(arg, "-y", 2) == 0 ) {
1240 const char* name = &arg[2];
1241
1242 if ( name == NULL )
1243 throw "-y missing argument";
1244
1245 fTraceSymbols.push_back(name);
1246 }
1247 // Same output as -y, but output <arg> number of undefined symbols only.
1248 else if ( strcmp(arg, "-Y") == 0 ) {
1249 char* endptr;
1250 fLimitUndefinedSymbols = strtoul (argv[++i], &endptr, 10);
1251
1252 if(*endptr != '\0')
1253 throw "invalid argument for -Y [decimal number]";
1254 }
1255 // This option affects all objects linked into the final result.
1256 else if ( strcmp(arg, "-m") == 0 ) {
1257 fWarnOnMultiplyDefined = true;
1258 }
1259 else if ( (strcmp(arg, "-why_load") == 0) || (strcmp(arg, "-whyload") == 0) ) {
1260 fReaderOptions.fWhyLoad = true;
1261 }
1262 else if ( strcmp(arg, "-why_live") == 0 ) {
1263 const char* name = argv[++i];
1264 if ( name == NULL )
1265 throw "-why_live missing symbol name argument";
1266 fWhyLive.insert(name);
1267 }
1268 else if ( strcmp(arg, "-u") == 0 ) {
1269 const char* name = argv[++i];
1270 if ( name == NULL )
1271 throw "-u missing argument";
1272 fInitialUndefines.push_back(name);
1273 }
1274 else if ( strcmp(arg, "-U") == 0 ) {
1275 // FIX FIX
1276 ++i;
1277 }
1278 else if ( strcmp(arg, "-s") == 0 ) {
1279 fStripLocalSymbols = true;
1280 fReaderOptions.fDebugInfoStripping = ObjectFile::ReaderOptions::kDebugInfoNone;
1281 }
1282 else if ( strcmp(arg, "-x") == 0 ) {
1283 fStripLocalSymbols = true;
1284 }
1285 else if ( strcmp(arg, "-S") == 0 ) {
1286 fReaderOptions.fDebugInfoStripping = ObjectFile::ReaderOptions::kDebugInfoNone;
1287 }
1288 else if ( strcmp(arg, "-X") == 0 ) {
1289 // FIX FIX
1290 }
1291 else if ( strcmp(arg, "-Si") == 0 ) {
1292 fReaderOptions.fDebugInfoStripping = ObjectFile::ReaderOptions::kDebugInfoFull;
1293 }
1294 else if ( strcmp(arg, "-b") == 0 ) {
1295 // FIX FIX
1296 }
1297 else if ( strcmp(arg, "-Sn") == 0 ) {
1298 fReaderOptions.fDebugInfoStripping = ObjectFile::ReaderOptions::kDebugInfoFull;
1299 }
1300 else if ( strcmp(arg, "-Sp") == 0 ) {
1301 fReaderOptions.fDebugInfoStripping = ObjectFile::ReaderOptions::kDebugInfoMinimal;
1302 }
1303 else if ( strcmp(arg, "-dead_strip") == 0 ) {
1304 fDeadStrip = kDeadStripOnPlusUnusedInits;
1305 }
1306 else if ( strcmp(arg, "-no_dead_strip_inits_and_terms") == 0 ) {
1307 fDeadStrip = kDeadStripOn;
1308 }
1309 else if ( strcmp(arg, "-w") == 0 ) {
1310 // FIX FIX
1311 }
1312 else if ( strcmp(arg, "-arch_errors_fatal") == 0 ) {
1313 // FIX FIX
1314 }
1315 else if ( strcmp(arg, "-M") == 0 ) {
1316 // FIX FIX
1317 }
1318 else if ( strcmp(arg, "-whatsloaded") == 0 ) {
1319 // FIX FIX
1320 }
1321 else if ( strcmp(arg, "-headerpad") == 0 ) {
1322 const char* size = argv[++i];
1323 if ( size == NULL )
1324 throw "-headerpad missing argument";
1325 fMinimumHeaderPad = parseAddress(size);
1326 }
1327 else if ( strcmp(arg, "-headerpad_max_install_names") == 0 ) {
1328 // FIX FIX
1329 }
1330 else if ( strcmp(arg, "-t") == 0 ) {
1331 // FIX FIX
1332 }
1333 else if ( strcmp(arg, "-A") == 0 ) {
1334 // FIX FIX
1335 ++i;
1336 }
1337 else if ( strcmp(arg, "-umbrella") == 0 ) {
1338 const char* name = argv[++i];
1339 if ( name == NULL )
1340 throw "-umbrella missing argument";
1341 fUmbrellaName = name;
1342 }
1343 else if ( strcmp(arg, "-allowable_client") == 0 ) {
1344 const char* name = argv[++i];
1345
1346 if ( name == NULL )
1347 throw "-allowable_client missing argument";
1348
1349 fAllowableClients.push_back(name);
1350 }
1351 else if ( strcmp(arg, "-client_name") == 0 ) {
1352 const char* name = argv[++i];
1353
1354 if ( name == NULL )
1355 throw "-client_name missing argument";
1356
1357 fClientName = name;
1358 }
1359 else if ( strcmp(arg, "-sub_umbrella") == 0 ) {
1360 const char* name = argv[++i];
1361 if ( name == NULL )
1362 throw "-sub_umbrella missing argument";
1363 fSubUmbellas.push_back(name);
1364 }
1365 else if ( strcmp(arg, "-sub_library") == 0 ) {
1366 const char* name = argv[++i];
1367 if ( name == NULL )
1368 throw "-sub_library missing argument";
1369 fSubLibraries.push_back(name);
1370 }
1371 else if ( strcmp(arg, "-init") == 0 ) {
1372 const char* name = argv[++i];
1373 if ( name == NULL )
1374 throw "-init missing argument";
1375 fInitFunctionName = name;
1376 }
1377 else if ( strcmp(arg, "-dot") == 0 ) {
1378 const char* name = argv[++i];
1379 if ( name == NULL )
1380 throw "-dot missing argument";
1381 fDotOutputFile = name;
1382 }
1383 else if ( strcmp(arg, "-warn_commons") == 0 ) {
1384 fWarnCommons = true;
1385 }
1386 else if ( strcmp(arg, "-commons") == 0 ) {
1387 fCommonsMode = parseCommonsTreatment(argv[++i]);
1388 }
1389 else if ( strcmp(arg, "-keep_relocs") == 0 ) {
1390 fKeepRelocations = true;
1391 }
1392 else if ( strcmp(arg, "-warn_stabs") == 0 ) {
1393 fWarnStabs = true;
1394 }
1395 else if ( strcmp(arg, "-pause") == 0 ) {
1396 fPause = true;
1397 }
1398 else if ( strcmp(arg, "-print_statistics") == 0 ) {
1399 fStatistics = true;
1400 }
1401 else if ( strcmp(arg, "-d") == 0 ) {
1402 fMakeTentativeDefinitionsReal = true;
1403 }
1404 else if ( strcmp(arg, "-v") == 0 ) {
1405 // previously handled by buildSearchPaths()
1406 }
1407 else if ( strcmp(arg, "-Z") == 0 ) {
1408 // previously handled by buildSearchPaths()
1409 }
1410 else if ( strcmp(arg, "-syslibroot") == 0 ) {
1411 ++i;
1412 // previously handled by buildSearchPaths()
1413 }
1414 else if ( strcmp(arg, "-no_uuid") == 0 ) {
1415 fEmitUUID = false;
1416 }
1417 // put this last so that it does not interfer with other options starting with 'i'
1418 else if ( strncmp(arg, "-i", 2) == 0 ) {
1419 fprintf(stderr, "ld64: -i option (indirect symbols) not supported\n");
1420 }
1421 else {
1422 throwf("unknown option: %s", arg);
1423 }
1424 }
1425 else {
1426 fInputFiles.push_back(findFile(arg));
1427 }
1428 }
1429 }
1430
1431
1432
1433 //
1434 // -syslibroot <path> is used for SDK support.
1435 // The rule is that all search paths (both explicit and default) are
1436 // checked to see if they exist in the SDK. If so, that path is
1437 // replaced with the sdk prefixed path. If not, that search path
1438 // is used as is. If multiple -syslibroot options are specified
1439 // their directory structures are logically overlayed and files
1440 // from sdks specified earlier on the command line used before later ones.
1441
1442 void Options::buildSearchPaths(int argc, const char* argv[])
1443 {
1444 bool addStandardLibraryDirectories = true;
1445 std::vector<const char*> libraryPaths;
1446 std::vector<const char*> frameworkPaths;
1447 libraryPaths.reserve(10);
1448 frameworkPaths.reserve(10);
1449 // scan through argv looking for -L, -F, -Z, and -syslibroot options
1450 for(int i=0; i < argc; ++i) {
1451 if ( (argv[i][0] == '-') && (argv[i][1] == 'L') )
1452 libraryPaths.push_back(&argv[i][2]);
1453 else if ( (argv[i][0] == '-') && (argv[i][1] == 'F') )
1454 frameworkPaths.push_back(&argv[i][2]);
1455 else if ( strcmp(argv[i], "-Z") == 0 )
1456 addStandardLibraryDirectories = false;
1457 else if ( strcmp(argv[i], "-v") == 0 ) {
1458 fVerbose = true;
1459 extern const char ld64VersionString[];
1460 fprintf(stderr, "%s", ld64VersionString);
1461 // if only -v specified, exit cleanly
1462 if ( argc == 2 )
1463 exit(0);
1464 }
1465 else if ( strcmp(argv[i], "-syslibroot") == 0 ) {
1466 const char* path = argv[++i];
1467 if ( path == NULL )
1468 throw "-syslibroot missing argument";
1469 fSDKPaths.push_back(path);
1470 }
1471 }
1472 if ( addStandardLibraryDirectories ) {
1473 libraryPaths.push_back("/usr/lib");
1474 libraryPaths.push_back("/usr/local/lib");
1475
1476 frameworkPaths.push_back("/Library/Frameworks/");
1477 frameworkPaths.push_back("/Network/Library/Frameworks/");
1478 frameworkPaths.push_back("/System/Library/Frameworks/");
1479 }
1480
1481 // now merge sdk and library paths to make real search paths
1482 fLibrarySearchPaths.reserve(libraryPaths.size()*(fSDKPaths.size()+1));
1483 for (std::vector<const char*>::iterator it = libraryPaths.begin(); it != libraryPaths.end(); it++) {
1484 const char* libDir = *it;
1485 bool sdkOverride = false;
1486 if ( libDir[0] == '/' ) {
1487 char betterLibDir[PATH_MAX];
1488 if ( strstr(libDir, "/..") != NULL ) {
1489 if ( realpath(libDir, betterLibDir) != NULL )
1490 libDir = strdup(betterLibDir);
1491 }
1492 const int libDirLen = strlen(libDir);
1493 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
1494 // ??? Should be using string here.
1495 const char* sdkDir = *sdkit;
1496 const int sdkDirLen = strlen(sdkDir);
1497 char newPath[libDirLen + sdkDirLen+4];
1498 strcpy(newPath, sdkDir);
1499 if ( newPath[sdkDirLen-1] == '/' )
1500 newPath[sdkDirLen-1] = '\0';
1501 strcat(newPath, libDir);
1502 struct stat statBuffer;
1503 if ( stat(newPath, &statBuffer) == 0 ) {
1504 fLibrarySearchPaths.push_back(strdup(newPath));
1505 sdkOverride = true;
1506 }
1507 }
1508 }
1509 if ( !sdkOverride )
1510 fLibrarySearchPaths.push_back(libDir);
1511 }
1512
1513 // now merge sdk and framework paths to make real search paths
1514 fFrameworkSearchPaths.reserve(frameworkPaths.size()*(fSDKPaths.size()+1));
1515 for (std::vector<const char*>::iterator it = frameworkPaths.begin(); it != frameworkPaths.end(); it++) {
1516 const char* frameworkDir = *it;
1517 bool sdkOverride = false;
1518 if ( frameworkDir[0] == '/' ) {
1519 char betterFrameworkDir[PATH_MAX];
1520 if ( strstr(frameworkDir, "/..") != NULL ) {
1521 if ( realpath(frameworkDir, betterFrameworkDir) != NULL )
1522 frameworkDir = strdup(betterFrameworkDir);
1523 }
1524 const int frameworkDirLen = strlen(frameworkDir);
1525 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
1526 // ??? Should be using string here
1527 const char* sdkDir = *sdkit;
1528 const int sdkDirLen = strlen(sdkDir);
1529 char newPath[frameworkDirLen + sdkDirLen+4];
1530 strcpy(newPath, sdkDir);
1531 if ( newPath[sdkDirLen-1] == '/' )
1532 newPath[sdkDirLen-1] = '\0';
1533 strcat(newPath, frameworkDir);
1534 struct stat statBuffer;
1535 if ( stat(newPath, &statBuffer) == 0 ) {
1536 fFrameworkSearchPaths.push_back(strdup(newPath));
1537 sdkOverride = true;
1538 }
1539 }
1540 }
1541 if ( !sdkOverride )
1542 fFrameworkSearchPaths.push_back(frameworkDir);
1543 }
1544
1545 if ( fVerbose ) {
1546 fprintf(stderr,"Library search paths:\n");
1547 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
1548 it != fLibrarySearchPaths.end();
1549 it++)
1550 fprintf(stderr,"\t%s\n", *it);
1551 fprintf(stderr,"Framework search paths:\n");
1552 for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin();
1553 it != fFrameworkSearchPaths.end();
1554 it++)
1555 fprintf(stderr,"\t%s\n", *it);
1556 }
1557 }
1558
1559 // this is run before the command line is parsed
1560 void Options::parsePreCommandLineEnvironmentSettings()
1561 {
1562 if ((getenv("LD_TRACE_ARCHIVES") != NULL)
1563 || (getenv("RC_TRACE_ARCHIVES") != NULL))
1564 fReaderOptions.fTraceArchives = true;
1565
1566 if ((getenv("LD_TRACE_DYLIBS") != NULL)
1567 || (getenv("RC_TRACE_DYLIBS") != NULL)) {
1568 fReaderOptions.fTraceDylibs = true;
1569 fReaderOptions.fTraceIndirectDylibs = true;
1570 }
1571
1572 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL) {
1573 fTraceDylibSearching = true;
1574 }
1575
1576 if (getenv("LD_PRINT_OPTIONS") != NULL)
1577 fPrintOptions = true;
1578
1579 if (fReaderOptions.fTraceDylibs || fReaderOptions.fTraceArchives)
1580 fReaderOptions.fTraceOutputFile = getenv("LD_TRACE_FILE");
1581 }
1582
1583 // this is run after the command line is parsed
1584 void Options::parsePostCommandLineEnvironmentSettings()
1585 {
1586 // when building a dynamic main executable, default any use of @executable_path to output path
1587 if ( fExecutablePath == NULL && (fOutputKind == kDynamicExecutable) ) {
1588 fExecutablePath = fOutputFile;
1589 }
1590
1591 }
1592
1593 void Options::reconfigureDefaults()
1594 {
1595 // sync reader options
1596 switch ( fOutputKind ) {
1597 case Options::kObjectFile:
1598 fReaderOptions.fForFinalLinkedImage = false;
1599 break;
1600 case Options::kDynamicExecutable:
1601 case Options::kStaticExecutable:
1602 case Options::kDynamicLibrary:
1603 case Options::kDynamicBundle:
1604 case Options::kDyld:
1605 fReaderOptions.fForFinalLinkedImage = true;
1606 break;
1607 }
1608
1609 // set default min OS version
1610 if ( fVersionMin == kMinUnset ) {
1611 switch ( fArchitecture ) {
1612 case CPU_TYPE_POWERPC:
1613 fVersionMin = k10_2;
1614 break;
1615 case CPU_TYPE_I386:
1616 case CPU_TYPE_POWERPC64:
1617 case CPU_TYPE_X86_64:
1618 fVersionMin = k10_4;
1619 default:
1620 // architecture not specified
1621 fVersionMin = k10_4;
1622 break;
1623 }
1624 }
1625
1626 // adjust min based on architecture
1627 switch ( fArchitecture ) {
1628 case CPU_TYPE_I386:
1629 if ( fVersionMin < k10_4 ) {
1630 //fprintf(stderr, "ld64 warning: -macosx_version_min should be 10.4 or later for i386\n");
1631 fVersionMin = k10_4;
1632 }
1633 break;
1634 case CPU_TYPE_POWERPC64:
1635 if ( fVersionMin < k10_4 ) {
1636 //fprintf(stderr, "ld64 warning: -macosx_version_min should be 10.4 or later for ppc64\n");
1637 fVersionMin = k10_4;
1638 }
1639 break;
1640 case CPU_TYPE_X86_64:
1641 if ( fVersionMin < k10_4 ) {
1642 //fprintf(stderr, "ld64 warning: -macosx_version_min should be 10.4 or later for x86_64\n");
1643 fVersionMin = k10_4;
1644 }
1645 break;
1646 }
1647
1648 }
1649
1650 void Options::checkIllegalOptionCombinations()
1651 {
1652 // check -undefined setting
1653 switch ( fUndefinedTreatment ) {
1654 case kUndefinedError:
1655 case kUndefinedDynamicLookup:
1656 // always legal
1657 break;
1658 case kUndefinedWarning:
1659 case kUndefinedSuppress:
1660 // requires flat namespace
1661 if ( fNameSpace == kTwoLevelNameSpace )
1662 throw "can't use -undefined warning or suppress with -twolevel_namespace";
1663 break;
1664 }
1665
1666 // unify -sub_umbrella with dylibs
1667 for (std::vector<const char*>::iterator it = fSubUmbellas.begin(); it != fSubUmbellas.end(); it++) {
1668 const char* subUmbrella = *it;
1669 bool found = false;
1670 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
1671 Options::FileInfo& info = *fit;
1672 const char* lastSlash = strrchr(info.path, '/');
1673 if ( lastSlash == NULL )
1674 lastSlash = info.path - 1;
1675 if ( strcmp(&lastSlash[1], subUmbrella) == 0 ) {
1676 info.options.fReExport = true;
1677 found = true;
1678 break;
1679 }
1680 }
1681 if ( ! found )
1682 fprintf(stderr, "ld64 warning: -sub_umbrella %s does not match a supplied dylib\n", subUmbrella);
1683 }
1684
1685 // unify -sub_library with dylibs
1686 for (std::vector<const char*>::iterator it = fSubLibraries.begin(); it != fSubLibraries.end(); it++) {
1687 const char* subLibrary = *it;
1688 bool found = false;
1689 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
1690 Options::FileInfo& info = *fit;
1691 const char* lastSlash = strrchr(info.path, '/');
1692 if ( lastSlash == NULL )
1693 lastSlash = info.path - 1;
1694 const char* dot = strchr(&lastSlash[1], '.');
1695 if ( dot == NULL )
1696 dot = &lastSlash[strlen(lastSlash)];
1697 if ( strncmp(&lastSlash[1], subLibrary, dot-lastSlash-1) == 0 ) {
1698 info.options.fReExport = true;
1699 found = true;
1700 break;
1701 }
1702 }
1703 if ( ! found )
1704 fprintf(stderr, "ld64 warning: -sub_library %s does not match a supplied dylib\n", subLibrary);
1705 }
1706
1707 // sync reader options
1708 if ( fNameSpace != kTwoLevelNameSpace )
1709 fReaderOptions.fFlatNamespace = true;
1710
1711 // check -stack_addr
1712 if ( fStackAddr != 0 ) {
1713 switch (fArchitecture) {
1714 case CPU_TYPE_I386:
1715 case CPU_TYPE_POWERPC:
1716 if ( fStackAddr > 0xFFFFFFFF )
1717 throw "-stack_addr must be < 4G for 32-bit processes";
1718 break;
1719 case CPU_TYPE_POWERPC64:
1720 case CPU_TYPE_X86_64:
1721 break;
1722 }
1723 if ( (fStackAddr & -4096) != fStackAddr )
1724 throw "-stack_addr must be multiples of 4K";
1725 if ( fStackSize == 0 )
1726 throw "-stack_addr must be used with -stack_size";
1727 }
1728
1729 // check -stack_size
1730 if ( fStackSize != 0 ) {
1731 switch (fArchitecture) {
1732 case CPU_TYPE_I386:
1733 case CPU_TYPE_POWERPC:
1734 if ( fStackSize > 0xFFFFFFFF )
1735 throw "-stack_size must be < 4G for 32-bit processes";
1736 if ( fStackAddr == 0 ) {
1737 fStackAddr = 0xC0000000;
1738 }
1739 if ( (fStackAddr > 0xB0000000) && ((fStackAddr-fStackSize) < 0xB0000000) )
1740 fprintf(stderr, "ld64 warning: custom stack placement overlaps and will disable shared region\n");
1741 break;
1742 case CPU_TYPE_POWERPC64:
1743 case CPU_TYPE_X86_64:
1744 if ( fStackAddr == 0 ) {
1745 fStackAddr = 0x0007FFFF00000000LL;
1746 }
1747 break;
1748 }
1749 if ( (fStackSize & -4096) != fStackSize )
1750 throw "-stack_size must be multiples of 4K";
1751 switch ( fOutputKind ) {
1752 case Options::kDynamicExecutable:
1753 case Options::kStaticExecutable:
1754 // custom stack size only legal when building main executable
1755 break;
1756 case Options::kDynamicLibrary:
1757 case Options::kDynamicBundle:
1758 case Options::kObjectFile:
1759 case Options::kDyld:
1760 throw "-stack_size option can only be used when linking a main executable";
1761 }
1762 }
1763
1764 // check that -allow_stack_execute is only used with main executables
1765 if ( fExecutableStack ) {
1766 switch ( fOutputKind ) {
1767 case Options::kDynamicExecutable:
1768 case Options::kStaticExecutable:
1769 // -allow_stack_execute size only legal when building main executable
1770 break;
1771 case Options::kDynamicLibrary:
1772 case Options::kDynamicBundle:
1773 case Options::kObjectFile:
1774 case Options::kDyld:
1775 throw "-allow_stack_execute option can only be used when linking a main executable";
1776 }
1777 }
1778
1779 // check -client_name is only used when -bundle is specified
1780 if ( (fClientName != NULL) && (fOutputKind != Options::kDynamicBundle) )
1781 throw "-client_name can only be used with -bundle";
1782
1783 // check -init is only used when building a dylib
1784 if ( (fInitFunctionName != NULL) && (fOutputKind != Options::kDynamicLibrary) )
1785 throw "-init can only be used with -dynamiclib";
1786
1787 // check -bundle_loader only used with -bundle
1788 if ( (fBundleLoader != NULL) && (fOutputKind != Options::kDynamicBundle) )
1789 throw "-bundle_loader can only be used with -bundle";
1790
1791 // check -d can only be used with -r
1792 if ( fMakeTentativeDefinitionsReal && (fOutputKind != Options::kObjectFile) )
1793 throw "-d can only be used with -r";
1794
1795 // make sure all required exported symbols exist
1796 for (NameSet::iterator it=fExportSymbols.begin(); it != fExportSymbols.end(); it++) {
1797 const char* name = *it;
1798 // never export .eh symbols
1799 if ( strcmp(&name[strlen(name)-3], ".eh") != 0 )
1800 fInitialUndefines.push_back(name);
1801 }
1802
1803 // make sure that -init symbol exist
1804 if ( fInitFunctionName != NULL )
1805 fInitialUndefines.push_back(fInitFunctionName);
1806
1807 if ( fZeroPageSize == ULLONG_MAX ) {
1808 // zero page size not specified on command line, set default
1809 switch (fArchitecture) {
1810 case CPU_TYPE_I386:
1811 case CPU_TYPE_POWERPC:
1812 // first 4KB for 32-bit architectures
1813 fZeroPageSize = 0x1000;
1814 break;
1815 case CPU_TYPE_POWERPC64:
1816 // first 4GB for ppc64 on 10.5
1817 if ( fVersionMin >= k10_5 )
1818 fZeroPageSize = 0x100000000ULL;
1819 else
1820 fZeroPageSize = 0x1000; // 10.4 dyld may not be able to handle >4GB zero page
1821 break;
1822 case CPU_TYPE_X86_64:
1823 // first 4GB for x86_64 on all OS's
1824 fZeroPageSize = 0x100000000ULL;
1825 break;
1826 default:
1827 // if -arch not used, default to 4K zero-page
1828 fZeroPageSize = 0x1000;
1829 }
1830 }
1831 else {
1832 switch ( fOutputKind ) {
1833 case Options::kDynamicExecutable:
1834 case Options::kStaticExecutable:
1835 // -pagezero_size size only legal when building main executable
1836 break;
1837 case Options::kDynamicLibrary:
1838 case Options::kDynamicBundle:
1839 case Options::kObjectFile:
1840 case Options::kDyld:
1841 throw "-pagezero_size option can only be used when linking a main executable";
1842 }
1843 }
1844
1845 // -dead_strip and -r are incompatible
1846 if ( (fDeadStrip != kDeadStripOff) && (fOutputKind == Options::kObjectFile) )
1847 throw "-r and -dead_strip cannot be used together\n";
1848
1849 }
1850
1851
1852
1853