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