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