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