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