]> git.saurik.com Git - apple/ld64.git/blame - src/Options.cpp
ld64-21.tar.gz
[apple/ld64.git] / src / Options.cpp
CommitLineData
c2646906
A
1/*
2 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <fcntl.h>
28
29
30#include "Options.h"
31
32 __attribute__((noreturn))
33void throwf(const char* format, ...)
34{
35 va_list list;
36 char* p;
37 va_start(list, format);
38 vasprintf(&p, format, list);
39 va_end(list);
40
41 const char* t = p;
42 throw t;
43}
44
45
46Options::Options(int argc, const char* argv[])
47 : fOutputFile("a.out"), fArchitecture(CPU_TYPE_POWERPC64), fOutputKind(kDynamicExecutable), fBindAtLoad(false),
48 fStripLocalSymbols(false), fKeepPrivateExterns(false),
49 fInterposable(false), fIgnoreOtherArchFiles(false), fForceSubtypeAll(false), fNameSpace(kTwoLevelNameSpace),
50 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL), fEntryName("start"), fBaseAddress(0),
51 fExportMode(kExportDefault), fLibrarySearchMode(kSearchAllDirsForDylibsThenAllDirsForArchives),
52 fUndefinedTreatment(kUndefinedError), fMessagesPrefixedWithArchitecture(false), fPICTreatment(kPICError),
53 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchError),
54 fUmbrellaName(NULL), fInitFunctionName(NULL), fZeroPageSize(0x1000), fStackSize(0), fStackAddr(0), fMinimumHeaderPad(0),
55 fCommonsMode(kCommonsIgnoreDylibs), fWarnCommons(false)
56{
57 this->parsePreCommandLineEnvironmentSettings();
58 this->parse(argc, argv);
59 this->parsePostCommandLineEnvironmentSettings();
60 this->checkIllegalOptionCombinations();
61}
62
63Options::~Options()
64{
65}
66
67
68ObjectFile::ReaderOptions& Options::readerOptions()
69{
70 return fReaderOptions;
71}
72
73cpu_type_t Options::architecture()
74{
75 return fArchitecture;
76}
77
78
79const char* Options::getOutputFilePath()
80{
81 return fOutputFile;
82}
83
84
85std::vector<Options::FileInfo>& Options::getInputFiles()
86{
87 return fInputFiles;
88}
89
90Options::OutputKind Options::outputKind()
91{
92 return fOutputKind;
93}
94
95bool Options::stripLocalSymbols()
96{
97 return fStripLocalSymbols;
98}
99
100bool Options::stripDebugInfo()
101{
102 return fReaderOptions.fStripDebugInfo;
103}
104
105bool Options::bindAtLoad()
106{
107 return fBindAtLoad;
108}
109
110bool Options::fullyLoadArchives()
111{
112 return fReaderOptions.fFullyLoadArchives;
113}
114
115Options::NameSpace Options::nameSpace()
116{
117 return fNameSpace;
118}
119
120const char* Options::installPath()
121{
122 if ( fDylibInstallName != NULL )
123 return fDylibInstallName;
124 else
125 return fOutputFile;
126}
127
128uint32_t Options::currentVersion()
129{
130 return fDylibCurrentVersion;
131}
132
133uint32_t Options::compatibilityVersion()
134{
135 return fDylibCompatVersion;
136}
137
138const char* Options::entryName()
139{
140 return fEntryName;
141}
142
143uint64_t Options::baseAddress()
144{
145 return fBaseAddress;
146}
147
148bool Options::keepPrivateExterns()
149{
150 return fKeepPrivateExterns;
151}
152
153bool Options::interposable()
154{
155 return fInterposable;
156}
157
158bool Options::ignoreOtherArchInputFiles()
159{
160 return fIgnoreOtherArchFiles;
161}
162
163bool Options::forceCpuSubtypeAll()
164{
165 return fForceSubtypeAll;
166}
167
168bool Options::traceDylibs()
169{
170 return fReaderOptions.fTraceDylibs;
171}
172
173bool Options::traceArchives()
174{
175 return fReaderOptions.fTraceArchives;
176}
177
178Options::UndefinedTreatment Options::undefinedTreatment()
179{
180 return fUndefinedTreatment;
181}
182
183Options::WeakReferenceMismatchTreatment Options::weakReferenceMismatchTreatment()
184{
185 return fWeakReferenceMismatchTreatment;
186}
187
188const char* Options::umbrellaName()
189{
190 return fUmbrellaName;
191}
192
193uint64_t Options::zeroPageSize()
194{
195 return fZeroPageSize;
196}
197
198bool Options::hasCustomStack()
199{
200 return (fStackSize != 0);
201}
202
203uint64_t Options::customStackSize()
204{
205 return fStackSize;
206}
207
208uint64_t Options::customStackAddr()
209{
210 return fStackAddr;
211}
212
213std::vector<const char*>& Options::initialUndefines()
214{
215 return fInitialUndefines;
216}
217
218const char* Options::initFunctionName()
219{
220 return fInitFunctionName;
221}
222
223bool Options::hasExportRestrictList()
224{
225 return (fExportMode != kExportDefault);
226}
227
228uint32_t Options::minimumHeaderPad()
229{
230 return fMinimumHeaderPad;
231}
232
233std::vector<Options::ExtraSection>& Options::extraSections()
234{
235 return fExtraSections;
236}
237
238std::vector<Options::SectionAlignment>& Options::sectionAlignments()
239{
240 return fSectionAlignments;
241}
242
243
244Options::CommonsMode Options::commonsMode()
245{
246 return fCommonsMode;
247}
248
249bool Options::warnCommons()
250{
251 return fWarnCommons;
252}
253
254
255bool Options::shouldExport(const char* symbolName)
256{
257 switch (fExportMode) {
258 case kExportSome:
259 return ( fExportSymbols.find(symbolName) != fExportSymbols.end() );
260 case kDontExportSome:
261 return ( fDontExportSymbols.find(symbolName) == fDontExportSymbols.end() );
262 case kExportDefault:
263 return true;
264 }
265 throw "internal error";
266}
267
268
269void Options::parseArch(const char* architecture)
270{
271 if ( architecture == NULL )
272 throw "-arch must be followed by an architecture string";
273 if ( strcmp(architecture, "ppc") == 0 )
274 fArchitecture = CPU_TYPE_POWERPC;
275 else if ( strcmp(architecture, "ppc64") == 0 )
276 fArchitecture = CPU_TYPE_POWERPC64;
277 else if ( strcmp(architecture, "i386") == 0 )
278 fArchitecture = CPU_TYPE_I386;
279 else
280 throw "-arch followed by unknown architecture name";
281}
282
283bool Options::checkForFile(const char* format, const char* dir, const char* rootName, FileInfo& result)
284{
285 struct stat statBuffer;
286 char possiblePath[strlen(dir)+strlen(rootName)+20];
287 sprintf(possiblePath, format, dir, rootName);
288 if ( stat(possiblePath, &statBuffer) == 0 ) {
289 result.path = strdup(possiblePath);
290 result.fileLen = statBuffer.st_size;
291 return true;
292 }
293 return false;
294}
295
296
297Options::FileInfo Options::findLibrary(const char* rootName)
298{
299 FileInfo result;
300 const int rootNameLen = strlen(rootName);
301 // if rootName ends in .o there is no .a vs .dylib choice
302 if ( (rootNameLen > 3) && (strcmp(&rootName[rootNameLen-2], ".o") == 0) ) {
303 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin(); it != fLibrarySearchPaths.end(); it++) {
304 const char* dir = *it;
305 if ( checkForFile("%s/%s", dir, rootName, result) )
306 return result;
307 }
308 }
309 else {
310 bool lookForDylibs = ( fOutputKind != Options::kDyld);
311 switch ( fLibrarySearchMode ) {
312 case kSearchAllDirsForDylibsThenAllDirsForArchives:
313 // first look in all directories for just for dylibs
314 if ( lookForDylibs ) {
315 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin(); it != fLibrarySearchPaths.end(); it++) {
316 const char* dir = *it;
317 if ( checkForFile("%s/lib%s.dylib", dir, rootName, result) )
318 return result;
319 }
320 }
321 // next look in all directories for just for archives
322 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin(); it != fLibrarySearchPaths.end(); it++) {
323 const char* dir = *it;
324 if ( checkForFile("%s/lib%s.a", dir, rootName, result) )
325 return result;
326 }
327 break;
328
329 case kSearchDylibAndArchiveInEachDir:
330 // look in each directory for just for a dylib then for an archive
331 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin(); it != fLibrarySearchPaths.end(); it++) {
332 const char* dir = *it;
333 if ( lookForDylibs && checkForFile("%s/lib%s.dylib", dir, rootName, result) )
334 return result;
335 if ( checkForFile("%s/lib%s.a", dir, rootName, result) )
336 return result;
337 }
338 break;
339 }
340 }
341 throwf("library not found for -l%s", rootName);
342}
343
344
345Options::FileInfo Options::findFramework(const char* rootName)
346{
347 struct stat statBuffer;
348 const int rootNameLen = strlen(rootName);
349 for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin(); it != fFrameworkSearchPaths.end(); it++) {
350 const char* dir = *it;
351 char possiblePath[strlen(dir)+2*rootNameLen+20];
352 strcpy(possiblePath, dir);
353 strcat(possiblePath, "/");
354 strcat(possiblePath, rootName);
355 strcat(possiblePath, ".framework/");
356 strcat(possiblePath, rootName);
357 if ( stat(possiblePath, &statBuffer) == 0 ) {
358 FileInfo result;
359 result.path = strdup(possiblePath);
360 result.fileLen = statBuffer.st_size;
361 return result;
362 }
363 }
364 throwf("framework not found %s", rootName);
365}
366
367
368Options::FileInfo Options::makeFileInfo(const char* path)
369{
370 struct stat statBuffer;
371 if ( stat(path, &statBuffer) == 0 ) {
372 FileInfo result;
373 result.path = strdup(path);
374 result.fileLen = statBuffer.st_size;
375 return result;
376 }
377 else {
378 throwf("file not found: %s", path);
379 }
380}
381
382void Options::loadFileList(const char* fileOfPaths)
383{
384 FILE* file = fopen(fileOfPaths, "r");
385 if ( file == NULL )
386 throwf("-filelist file not found: %s\n", fileOfPaths);
387
388 char path[1024];
389 while ( fgets(path, 1024, file) != NULL ) {
390 path[1023] = '\0';
391 char* eol = strchr(path, '\n');
392 if ( eol != NULL )
393 *eol = '\0';
394
395 fInputFiles.push_back(makeFileInfo(path));
396 }
397 fclose(file);
398}
399
400
401void Options::loadExportFile(const char* fileOfExports, const char* option, NameSet& set)
402{
403 // read in whole file
404 int fd = ::open(fileOfExports, O_RDONLY, 0);
405 if ( fd == -1 )
406 throwf("can't open %s file: %s", option, fileOfExports);
407 struct stat stat_buf;
408 ::fstat(fd, &stat_buf);
409 char* p = (char*)malloc(stat_buf.st_size);
410 if ( p == NULL )
411 throwf("can't process %s file: %s", option, fileOfExports);
412
413 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
414 throwf("can't read %s file: %s", option, fileOfExports);
415
416 ::close(fd);
417
418 // parse into symbols and add to hash_set
419 char * const end = &p[stat_buf.st_size];
420 enum { lineStart, inSymbol, inComment } state = lineStart;
421 char* symbolStart = NULL;
422 for (char* s = p; s < end; ++s ) {
423 switch ( state ) {
424 case lineStart:
425 if ( *s =='#' ) {
426 state = inComment;
427 }
428 else if ( !isspace(*s) ) {
429 state = inSymbol;
430 symbolStart = s;
431 }
432 break;
433 case inSymbol:
434 if ( *s == '\n' ) {
435 *s = '\0';
436 // removing any trailing spaces
437 char* last = s-1;
438 while ( isspace(*last) ) {
439 *last = '\0';
440 --last;
441 }
442 set.insert(symbolStart);
443 symbolStart = NULL;
444 state = lineStart;
445 }
446 break;
447 case inComment:
448 if ( *s == '\n' )
449 state = lineStart;
450 break;
451 }
452 }
453 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
454}
455
456void Options::setUndefinedTreatment(const char* treatment)
457{
458 if ( treatment == NULL )
459 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
460
461 if ( strcmp(treatment, "warning") == 0 )
462 fUndefinedTreatment = kUndefinedWarning;
463 else if ( strcmp(treatment, "error") == 0 )
464 fUndefinedTreatment = kUndefinedError;
465 else if ( strcmp(treatment, "suppress") == 0 )
466 fUndefinedTreatment = kUndefinedSuppress;
467 else if ( strcmp(treatment, "dynamic_lookup") == 0 )
468 fUndefinedTreatment = kUndefinedDynamicLookup;
469 else
470 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
471}
472
473void Options::setReadOnlyRelocTreatment(const char* treatment)
474{
475 if ( treatment == NULL )
476 throw "-read_only_relocs missing [ warning | error | suppress ]";
477
478 if ( strcmp(treatment, "warning") == 0 )
479 throw "-read_only_relocs warning not supported";
480 else if ( strcmp(treatment, "suppress") == 0 )
481 throw "-read_only_relocs suppress not supported";
482 else if ( strcmp(treatment, "error") != 0 )
483 throw "invalid option to -read_only_relocs [ warning | error | suppress | dynamic_lookup ]";
484}
485
486void Options::setPICTreatment(const char* treatment)
487{
488 if ( treatment == NULL )
489 throw "-sect_diff_relocs missing [ warning | error | suppress ]";
490
491 if ( strcmp(treatment, "warning") == 0 )
492 fPICTreatment = kPICWarning;
493 else if ( strcmp(treatment, "error") == 0 )
494 fPICTreatment = kPICError;
495 else if ( strcmp(treatment, "suppress") == 0 )
496 fPICTreatment = kPICSuppress;
497 else
498 throw "invalid option to -sect_diff_relocs [ warning | error | suppress ]";
499}
500
501void Options::setWeakReferenceMismatchTreatment(const char* treatment)
502{
503 if ( treatment == NULL )
504 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
505
506 if ( strcmp(treatment, "error") == 0 )
507 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchError;
508 else if ( strcmp(treatment, "weak") == 0 )
509 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchWeak;
510 else if ( strcmp(treatment, "non-weak") == 0 )
511 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchNonWeak;
512 else
513 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
514}
515
516Options::CommonsMode Options::parseCommonsTreatment(const char* mode)
517{
518 if ( mode == NULL )
519 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
520
521 if ( strcmp(mode, "ignore_dylibs") == 0 )
522 return kCommonsIgnoreDylibs;
523 else if ( strcmp(mode, "use_dylibs") == 0 )
524 return kCommonsOverriddenByDylibs;
525 else if ( strcmp(mode, "error") == 0 )
526 return kCommonsConflictsDylibsError;
527 else
528 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
529}
530
531
532void Options::setDylibInstallNameOverride(const char* paths)
533{
534
535
536}
537
538void Options::setExecutablePath(const char* path)
539{
540
541
542}
543
544
545
546
547uint64_t Options::parseAddress(const char* addr)
548{
549 char* endptr;
550 uint64_t result = strtoull(addr, &endptr, 16);
551 return result;
552}
553
554
555
556//
557// Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
558//
559//
560uint32_t Options::parseVersionNumber(const char* versionString)
561{
562 unsigned long x = 0;
563 unsigned long y = 0;
564 unsigned long z = 0;
565 char* end;
566 x = strtoul(versionString, &end, 10);
567 if ( *end == '.' ) {
568 y = strtoul(&end[1], &end, 10);
569 if ( *end == '.' ) {
570 z = strtoul(&end[1], &end, 10);
571 }
572 }
573 if ( (*end != '\0') || (x > 0xffff) || (y > 0xff) || (z > 0xff) )
574 throwf("malformed version number: %s", versionString);
575
576 return (x << 16) | ( y << 8 ) | z;
577}
578
579void Options::parseSectionOrderFile(const char* segment, const char* section, const char* path)
580{
581 fprintf(stderr, "ld64: warning -sectorder not yet supported for 64-bit code\n");
582}
583
584void Options::addSection(const char* segment, const char* section, const char* path)
585{
586 if ( strlen(segment) > 16 )
587 throw "-seccreate segment name max 16 chars";
588 if ( strlen(section) > 16 )
589 throw "-seccreate section name max 16 chars";
590
591 // read in whole file
592 int fd = ::open(path, O_RDONLY, 0);
593 if ( fd == -1 )
594 throwf("can't open -sectcreate file: %s", path);
595 struct stat stat_buf;
596 ::fstat(fd, &stat_buf);
597 char* p = (char*)malloc(stat_buf.st_size);
598 if ( p == NULL )
599 throwf("can't process -sectcreate file: %s", path);
600 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
601 throwf("can't read -sectcreate file: %s", path);
602 ::close(fd);
603
604 // record section to create
605 ExtraSection info = { segment, section, path, (uint8_t*)p, stat_buf.st_size };
606 fExtraSections.push_back(info);
607}
608
609void Options::addSectionAlignment(const char* segment, const char* section, const char* alignmentStr)
610{
611 if ( strlen(segment) > 16 )
612 throw "-sectalign segment name max 16 chars";
613 if ( strlen(section) > 16 )
614 throw "-sectalign section name max 16 chars";
615
616 char* endptr;
617 unsigned long value = strtoul(alignmentStr, &endptr, 16);
618 if ( *endptr != '\0')
619 throw "argument for -sectalign is not a hexadecimal number";
620 if ( value > 0x8000 )
621 throw "argument for -sectalign must be less than or equal to 0x8000";
622 uint8_t alignment = 0;
623 for(unsigned long x=value; x != 1; x >>= 1)
624 ++alignment;
625 if ( (unsigned long)(1 << alignment) != value )
626 throw "argument for -sectalign is not a power of two";
627
628 SectionAlignment info = { segment, section, alignment };
629 fSectionAlignments.push_back(info);
630}
631
632
633void Options::parse(int argc, const char* argv[])
634{
635 // pass one builds search list from -L and -F options
636 this->buildSearchPaths(argc, argv);
637
638 // pass two parse all other options
639 for(int i=1; i < argc; ++i) {
640 const char* arg = argv[i];
641
642 if ( arg[0] == '-' ) {
643 if ( (arg[1] == 'L') || (arg[1] == 'F') ) {
644 // previously handled
645 }
646 else if ( strcmp(arg, "-arch") == 0 ) {
647 parseArch(argv[++i]);
648 }
649 else if ( strcmp(arg, "-dynamic") == 0 ) {
650 // default
651 }
652 else if ( strcmp(arg, "-static") == 0 ) {
653 fOutputKind = kStaticExecutable;
654 }
655 else if ( strcmp(arg, "-dylib") == 0 ) {
656 fOutputKind = kDynamicLibrary;
657 }
658 else if ( strcmp(arg, "-bundle") == 0 ) {
659 fOutputKind = kDynamicBundle;
660 }
661 else if ( strcmp(arg, "-dylinker") == 0 ) {
662 fOutputKind = kDyld;
663 }
664 else if ( strcmp(arg, "-execute") == 0 ) {
665 if ( fOutputKind != kStaticExecutable )
666 fOutputKind = kDynamicExecutable;
667 }
668 else if ( strcmp(arg, "-r") == 0 ) {
669 fOutputKind = kObjectFile;
670 }
671 else if ( strcmp(arg, "-o") == 0 ) {
672 fOutputFile = argv[++i];
673 }
674 else if ( arg[1] == 'l' ) {
675 fInputFiles.push_back(findLibrary(&arg[2]));
676 }
677 else if ( strcmp(arg, "-weak-l") == 0 ) {
678 FileInfo info = findLibrary(&arg[2]);
679 info.options.fWeakImport = true;
680 fInputFiles.push_back(info);
681 }
682 else if ( strcmp(arg, "-bind_at_load") == 0 ) {
683 fBindAtLoad = true;
684 }
685 else if ( strcmp(arg, "-twolevel_namespace") == 0 ) {
686 fNameSpace = kTwoLevelNameSpace;
687 }
688 else if ( strcmp(arg, "-flat_namespace") == 0 ) {
689 fNameSpace = kFlatNameSpace;
690 }
691 else if ( strcmp(arg, "-force_flat_namespace") == 0 ) {
692 fNameSpace = kForceFlatNameSpace;
693 }
694 else if ( strcmp(arg, "-all_load") == 0 ) {
695 fReaderOptions.fFullyLoadArchives = true;
696 }
697 else if ( strcmp(arg, "-ObjC") == 0 ) {
698 fReaderOptions.fLoadObjcClassesInArchives = true;
699 }
700 else if ( strcmp(arg, "-dylib_compatibility_version") == 0 ) {
701 fDylibCompatVersion = parseVersionNumber(argv[++i]);
702 }
703 else if ( strcmp(arg, "-dylib_current_version") == 0 ) {
704 fDylibCurrentVersion = parseVersionNumber(argv[++i]);
705 }
706 else if ( strcmp(arg, "-sectorder") == 0 ) {
707 parseSectionOrderFile(argv[i+1], argv[i+2], argv[i+3]);
708 i += 3;
709 }
710 else if ( (strcmp(arg, "-sectcreate") == 0) || (strcmp(arg, "-segcreate") == 0) ) {
711 addSection(argv[i+1], argv[i+2], argv[i+3]);
712 i += 3;
713 }
714 else if ( (strcmp(arg, "-dylib_install_name") == 0) || (strcmp(arg, "-dylinker_install_name") == 0) ) {
715 fDylibInstallName = argv[++i];
716 }
717 else if ( strcmp(arg, "-seg1addr") == 0 ) {
718 fBaseAddress = parseAddress(argv[++i]);
719 }
720 else if ( strcmp(arg, "-e") == 0 ) {
721 fEntryName = argv[++i];
722 }
723 else if ( strcmp(arg, "-filelist") == 0 ) {
724 loadFileList(argv[++i]);
725 }
726 else if ( strcmp(arg, "-keep_private_externs") == 0 ) {
727 fKeepPrivateExterns = true;
728 }
729 else if ( strcmp(arg, "-final_output") == 0 ) {
730 ++i;
731 // ignore for now
732 }
733 else if ( (strcmp(arg, "-interposable") == 0) || (strcmp(arg, "-multi_module") == 0)) {
734 fInterposable = true;
735 }
736 else if ( strcmp(arg, "-single_module") == 0 ) {
737 fInterposable = false;
738 }
739 else if ( strcmp(arg, "-exported_symbols_list") == 0 ) {
740 if ( fExportMode == kDontExportSome )
741 throw "can't use -exported_symbols_list and -unexported_symbols_list";
742 fExportMode = kExportSome;
743 loadExportFile(argv[++i], "-exported_symbols_list", fExportSymbols);
744 }
745 else if ( strcmp(arg, "-unexported_symbols_list") == 0 ) {
746 if ( fExportMode == kExportSome )
747 throw "can't use -exported_symbols_list and -unexported_symbols_list";
748 fExportMode = kDontExportSome;
749 loadExportFile(argv[++i], "-unexported_symbols_list", fDontExportSymbols);
750 }
751 else if ( strcmp(arg, "-no_arch_warnings") == 0 ) {
752 fIgnoreOtherArchFiles = true;
753 }
754 else if ( strcmp(arg, "-force_cpusubtype_ALL") == 0 ) {
755 fForceSubtypeAll = true;
756 }
757 else if ( strcmp(arg, "-weak_library") == 0 ) {
758 FileInfo info = makeFileInfo(argv[++i]);
759 info.options.fWeakImport = true;
760 fInputFiles.push_back(info);
761 }
762 else if ( strcmp(arg, "-framework") == 0 ) {
763 fInputFiles.push_back(findFramework(argv[++i]));
764 }
765 else if ( strcmp(arg, "-weak_framework") == 0 ) {
766 FileInfo info = findFramework(argv[++i]);
767 info.options.fWeakImport = true;
768 fInputFiles.push_back(info);
769 }
770 else if ( strcmp(arg, "-search_paths_first") == 0 ) {
771 fLibrarySearchMode = kSearchDylibAndArchiveInEachDir;
772 }
773 else if ( strcmp(arg, "-undefined") == 0 ) {
774 setUndefinedTreatment(argv[++i]);
775 }
776 else if ( strcmp(arg, "-arch_multiple") == 0 ) {
777 fMessagesPrefixedWithArchitecture = true;
778 }
779 else if ( strcmp(arg, "-read_only_relocs") == 0 ) {
780 setReadOnlyRelocTreatment(argv[++i]);
781 }
782 else if ( strcmp(arg, "-sect_diff_relocs") == 0 ) {
783 setPICTreatment(argv[++i]);
784 }
785 else if ( strcmp(arg, "-weak_reference_mismatches") == 0 ) {
786 setWeakReferenceMismatchTreatment(argv[++i]);
787 }
788 else if ( strcmp(arg, "-prebind") == 0 ) {
789 // FIX FIX
790 }
791 else if ( strcmp(arg, "-noprebind") == 0 ) {
792 // FIX FIX
793 }
794 else if ( strcmp(arg, "-prebind_allow_overlap") == 0 ) {
795 // FIX FIX
796 }
797 else if ( strcmp(arg, "-prebind_all_twolevel_modules") == 0 ) {
798 // FIX FIX
799 }
800 else if ( strcmp(arg, "-noprebind_all_twolevel_modules") == 0 ) {
801 // FIX FIX
802 }
803 else if ( strcmp(arg, "-nofixprebinding") == 0 ) {
804 // FIX FIX
805 }
806 else if ( strcmp(arg, "-dylib_file") == 0 ) {
807 setDylibInstallNameOverride(argv[++i]);
808 }
809 else if ( strcmp(arg, "-executable_path") == 0 ) {
810 setExecutablePath(argv[++i]);
811 }
812 else if ( strcmp(arg, "-segalign") == 0 ) {
813 // FIX FIX
814 ++i;
815 }
816 else if ( strcmp(arg, "-segaddr") == 0 ) {
817 // FIX FIX
818 i += 2;
819 }
820 else if ( strcmp(arg, "-segs_read_only_addr") == 0 ) {
821 // FIX FIX
822 ++i;
823 }
824 else if ( strcmp(arg, "-segs_read_write_addr") == 0 ) {
825 // FIX FIX
826 ++i;
827 }
828 else if ( strcmp(arg, "-seg_addr_table") == 0 ) {
829 // FIX FIX
830 ++i;
831 }
832 else if ( strcmp(arg, "-seg_addr_table_filename") == 0 ) {
833 // FIX FIX
834 ++i;
835 }
836 else if ( strcmp(arg, "-segprot") == 0 ) {
837 // FIX FIX
838 i += 3;
839 }
840 else if ( strcmp(arg, "-pagezero_size") == 0 ) {
841 fZeroPageSize = parseAddress(argv[++i]);
842 fZeroPageSize &= (-4096); // page align
843 }
844 else if ( strcmp(arg, "-stack_addr") == 0 ) {
845 fStackAddr = parseAddress(argv[++i]);
846 }
847 else if ( strcmp(arg, "-stack_size") == 0 ) {
848 fStackSize = parseAddress(argv[++i]);
849 }
850 else if ( strcmp(arg, "-sectalign") == 0 ) {
851 addSectionAlignment(argv[i+1], argv[i+2], argv[i+3]);
852 i += 3;
853 }
854 else if ( strcmp(arg, "-sectorder_detail") == 0 ) {
855 // FIX FIX
856 }
857 else if ( strcmp(arg, "-sectobjectsymbols") == 0 ) {
858 // FIX FIX
859 i += 2;
860 }
861 else if ( strcmp(arg, "-bundle_loader") == 0 ) {
862 // FIX FIX
863 ++i;
864 }
865 else if ( strcmp(arg, "-private_bundle") == 0 ) {
866 // FIX FIX
867 }
868 else if ( strcmp(arg, "-twolevel_namespace_hints") == 0 ) {
869 // FIX FIX
870 }
871 else if ( strcmp(arg, "-multiply_defined") == 0 ) {
872 // FIX FIX
873 ++i;
874 }
875 else if ( strcmp(arg, "-multiply_defined_unused") == 0 ) {
876 // FIX FIX
877 ++i;
878 }
879 else if ( strcmp(arg, "-nomultidefs") == 0 ) {
880 // FIX FIX
881 }
882 else if ( arg[1] == 'y' ) {
883 // FIX FIX
884 }
885 else if ( strcmp(arg, "-Y") == 0 ) {
886 ++i;
887 // FIX FIX
888 }
889 else if ( strcmp(arg, "-m") == 0 ) {
890 // FIX FIX
891 }
892 else if ( strcmp(arg, "-whyload") == 0 ) {
893 // FIX FIX
894 }
895 else if ( strcmp(arg, "-u") == 0 ) {
896 const char* name = argv[++i];
897 if ( name == NULL )
898 throw "-u missing argument";
899 fInitialUndefines.push_back(name);
900 }
901 else if ( strcmp(arg, "-i") == 0 ) {
902 // FIX FIX
903 }
904 else if ( strcmp(arg, "-U") == 0 ) {
905 // FIX FIX
906 ++i;
907 }
908 else if ( strcmp(arg, "-s") == 0 ) {
909 // FIX FIX
910 }
911 else if ( strcmp(arg, "-x") == 0 ) {
912 // FIX FIX
913 }
914 else if ( strcmp(arg, "-S") == 0 ) {
915 // FIX FIX
916 }
917 else if ( strcmp(arg, "-X") == 0 ) {
918 // FIX FIX
919 }
920 else if ( strcmp(arg, "-Si") == 0 ) {
921 // FIX FIX
922 }
923 else if ( strcmp(arg, "-b") == 0 ) {
924 // FIX FIX
925 }
926 else if ( strcmp(arg, "-Sn") == 0 ) {
927 // FIX FIX
928 }
929 else if ( strcmp(arg, "-dead_strip") == 0 ) {
930 // FIX FIX
931 fprintf(stderr, "ld64: warning -dead_strip not yet supported for 64-bit code\n");
932 }
933 else if ( strcmp(arg, "-v") == 0 ) {
934 extern const char ld64VersionString[];
935 fprintf(stderr, "%s", ld64VersionString);
936 // if only -v specified, exit cleanly
937 if ( argc == 2 )
938 exit(0);
939 }
940 else if ( strcmp(arg, "-w") == 0 ) {
941 // FIX FIX
942 }
943 else if ( strcmp(arg, "-arch_errors_fatal") == 0 ) {
944 // FIX FIX
945 }
946 else if ( strcmp(arg, "-M") == 0 ) {
947 // FIX FIX
948 }
949 else if ( strcmp(arg, "-whatsloaded") == 0 ) {
950 // FIX FIX
951 }
952 else if ( strcmp(arg, "-headerpad") == 0 ) {
953 const char* size = argv[++i];
954 if ( size == NULL )
955 throw "-headerpad missing argument";
956 fMinimumHeaderPad = parseAddress(size);
957 }
958 else if ( strcmp(arg, "-headerpad_max_install_names") == 0 ) {
959 // FIX FIX
960 }
961 else if ( strcmp(arg, "-t") == 0 ) {
962 // FIX FIX
963 }
964 else if ( strcmp(arg, "-A") == 0 ) {
965 // FIX FIX
966 ++i;
967 }
968 else if ( strcmp(arg, "-umbrella") == 0 ) {
969 const char* name = argv[++i];
970 if ( name == NULL )
971 throw "-umbrella missing argument";
972 fUmbrellaName = name;
973 }
974 else if ( strcmp(arg, "-allowable_client") == 0 ) {
975 // FIX FIX
976 ++i;
977 }
978 else if ( strcmp(arg, "-client_name") == 0 ) {
979 // FIX FIX
980 ++i;
981 }
982 else if ( strcmp(arg, "-sub_umbrella") == 0 ) {
983 const char* name = argv[++i];
984 if ( name == NULL )
985 throw "-sub_umbrella missing argument";
986 fSubUmbellas.push_back(name);
987 }
988 else if ( strcmp(arg, "-sub_library") == 0 ) {
989 const char* name = argv[++i];
990 if ( name == NULL )
991 throw "-sub_library missing argument";
992 fSubLibraries.push_back(name);
993 }
994 else if ( strcmp(arg, "-init") == 0 ) {
995 const char* name = argv[++i];
996 if ( name == NULL )
997 throw "-init missing argument";
998 fInitFunctionName = name;
999 }
1000 else if ( strcmp(arg, "-warn_commons") == 0 ) {
1001 fWarnCommons = true;
1002 }
1003 else if ( strcmp(arg, "-commons") == 0 ) {
1004 fCommonsMode = parseCommonsTreatment(argv[++i]);
1005 }
1006
1007 else {
1008 fprintf(stderr, "unknown option: %s\n", arg);
1009 }
1010 }
1011 else {
1012 fInputFiles.push_back(makeFileInfo(arg));
1013 }
1014 }
1015}
1016
1017void Options::buildSearchPaths(int argc, const char* argv[])
1018{
1019 bool addStandardLibraryDirectories = true;
1020 // scan through argv looking for -L and -F options
1021 for(int i=0; i < argc; ++i) {
1022 if ( (argv[i][0] == '-') && (argv[i][1] == 'L') )
1023 fLibrarySearchPaths.push_back(&argv[i][2]);
1024 else if ( (argv[i][0] == '-') && (argv[i][1] == 'F') )
1025 fFrameworkSearchPaths.push_back(&argv[i][2]);
1026 else if ( strcmp(argv[i], "-Z") == 0 )
1027 addStandardLibraryDirectories = false;
1028 }
1029 if ( addStandardLibraryDirectories ) {
1030 fLibrarySearchPaths.push_back("/usr/lib");
1031 fLibrarySearchPaths.push_back("/usr/local/lib");
1032
1033 fFrameworkSearchPaths.push_back("/Library/Frameworks/");
1034 fFrameworkSearchPaths.push_back("/Network/Library/Frameworks/");
1035 fFrameworkSearchPaths.push_back("/System/Library/Frameworks/");
1036 }
1037}
1038
1039// this is run before the command line is parsed
1040void Options::parsePreCommandLineEnvironmentSettings()
1041{
1042 if ( getenv("RC_TRACE_ARCHIVES") != NULL)
1043 fReaderOptions.fTraceArchives = true;
1044
1045 if ( getenv("RC_TRACE_DYLIBS") != NULL) {
1046 fReaderOptions.fTraceDylibs = true;
1047 fReaderOptions.fTraceIndirectDylibs = true;
1048 }
1049}
1050
1051// this is run after the command line is parsed
1052void Options::parsePostCommandLineEnvironmentSettings()
1053{
1054
1055}
1056
1057void Options::checkIllegalOptionCombinations()
1058{
1059 // check -undefined setting
1060 switch ( fUndefinedTreatment ) {
1061 case kUndefinedError:
1062 case kUndefinedDynamicLookup:
1063 // always legal
1064 break;
1065 case kUndefinedWarning:
1066 case kUndefinedSuppress:
1067 // requires flat namespace
1068 if ( fNameSpace == kTwoLevelNameSpace )
1069 throw "can't use -undefined warning or suppress with -twolevel_namespace";
1070 break;
1071 }
1072
1073 // unify -sub_umbrella with dylibs
1074 for (std::vector<const char*>::iterator it = fSubUmbellas.begin(); it != fSubUmbellas.end(); it++) {
1075 const char* subUmbrella = *it;
1076 bool found = false;
1077 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
1078 Options::FileInfo& info = *fit;
1079 const char* lastSlash = strrchr(info.path, '/');
1080 if ( lastSlash == NULL )
1081 lastSlash = info.path - 1;
1082 if ( strcmp(&lastSlash[1], subUmbrella) == 0 ) {
1083 info.options.fReExport = true;
1084 found = true;
1085 break;
1086 }
1087 }
1088 if ( ! found )
1089 fprintf(stderr, "ld64 warning: -sub_umbrella %s does not match a supplied dylib\n", subUmbrella);
1090 }
1091
1092 // unify -sub_library with dylibs
1093 for (std::vector<const char*>::iterator it = fSubLibraries.begin(); it != fSubLibraries.end(); it++) {
1094 const char* subLibrary = *it;
1095 bool found = false;
1096 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
1097 Options::FileInfo& info = *fit;
1098 const char* lastSlash = strrchr(info.path, '/');
1099 if ( lastSlash == NULL )
1100 lastSlash = info.path - 1;
1101 const char* dot = strchr(lastSlash, '.');
1102 if ( dot == NULL )
1103 dot = &lastSlash[strlen(lastSlash)];
1104 if ( strncmp(&lastSlash[1], subLibrary, dot-lastSlash-1) == 0 ) {
1105 info.options.fReExport = true;
1106 found = true;
1107 break;
1108 }
1109 }
1110 if ( ! found )
1111 fprintf(stderr, "ld64 warning: -sub_library %s does not match a supplied dylib\n", subLibrary);
1112 }
1113
1114 // sync reader options
1115 if ( fNameSpace != kTwoLevelNameSpace )
1116 fReaderOptions.fFlatNamespace = true;
1117
1118 // check -stack_addr
1119 if ( fStackAddr != 0 ) {
1120 switch (fArchitecture) {
1121 case CPU_TYPE_I386:
1122 case CPU_TYPE_POWERPC:
1123 if ( fStackAddr > 0xFFFFFFFF )
1124 throw "-stack_addr must be < 4G for 32-bit processes";
1125 break;
1126 case CPU_TYPE_POWERPC64:
1127 break;
1128 }
1129 if ( (fStackAddr & -4096) != fStackAddr )
1130 throw "-stack_addr must be multiples of 4K";
1131 if ( fStackSize == 0 )
1132 throw "-stack_addr must be used with -stack_size";
1133 }
1134
1135 // check -stack_size
1136 if ( fStackSize != 0 ) {
1137 switch (fArchitecture) {
1138 case CPU_TYPE_I386:
1139 case CPU_TYPE_POWERPC:
1140 if ( fStackSize > 0xFFFFFFFF )
1141 throw "-stack_size must be < 4G for 32-bit processes";
1142 if ( fStackAddr == 0 ) {
1143 fprintf(stderr, "ld64 warning: -stack_addr not specified, using the default 0xC0000000\n");
1144 fStackAddr = 0xC0000000;
1145 }
1146 break;
1147 case CPU_TYPE_POWERPC64:
1148 if ( fStackAddr == 0 ) {
1149 fprintf(stderr, "ld64 warning: -stack_addr not specified, using the default 0x0008000000000000\n");
1150 fStackAddr = 0x0008000000000000LL;
1151 }
1152 break;
1153 }
1154 if ( (fStackSize & -4096) != fStackSize )
1155 throw "-stack_size must be multiples of 4K";
1156 switch ( fOutputKind ) {
1157 case Options::kDynamicExecutable:
1158 case Options::kStaticExecutable:
1159 // custom stack size only legeal when building main executable
1160 break;
1161 case Options::kDynamicLibrary:
1162 case Options::kDynamicBundle:
1163 case Options::kObjectFile:
1164 case Options::kDyld:
1165 throw "-stack_size option can only be used when linking a main executable";
1166 }
1167 }
1168
1169 // check -init is only used when building a dylib
1170 if ( (fInitFunctionName != NULL) && (fOutputKind != Options::kDynamicLibrary) )
1171 throw "-init can only be used with -dynamiclib";
1172}
1173
1174