]> git.saurik.com Git - apple/ld64.git/blame - src/Options.cpp
ld64-77.tar.gz
[apple/ld64.git] / src / Options.cpp
CommitLineData
d696c285 1/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
6e880c60 2 *
a61fdf0a 3 * Copyright (c) 2005-2007 Apple Inc. All rights reserved.
c2646906
A
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>
a61fdf0a 28#include <mach/vm_prot.h>
d696c285 29#include <math.h>
c2646906 30#include <fcntl.h>
6e880c60 31#include <vector>
c2646906 32
c2646906
A
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[])
a61fdf0a
A
48 : fOutputFile("a.out"), fArchitecture(0), fOutputKind(kDynamicExecutable), fPrebind(false), fBindAtLoad(false),
49 fKeepPrivateExterns(false),
50 fInterposable(false), fNeedsModuleTable(false), fIgnoreOtherArchFiles(false), fForceSubtypeAll(false),
51 fDeadStrip(kDeadStripOff), fNameSpace(kTwoLevelNameSpace),
52 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL), fFinalName(NULL), fEntryName("start"), fBaseAddress(0),
53 fBaseWritableAddress(0), fSplitSegs(false),
d696c285 54 fExportMode(kExportDefault), fLibrarySearchMode(kSearchAllDirsForDylibsThenAllDirsForArchives),
a61fdf0a
A
55 fUndefinedTreatment(kUndefinedError), fMessagesPrefixedWithArchitecture(false),
56 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak),
57 fClientName(NULL),
58 fUmbrellaName(NULL), fInitFunctionName(NULL), fDotOutputFile(NULL), fExecutablePath(NULL),
59 fBundleLoader(NULL), fDtraceScriptName(NULL), fSegAddrTablePath(NULL), fMapPath(NULL),
60 fZeroPageSize(ULLONG_MAX), fStackSize(0), fStackAddr(0), fExecutableStack(false), fMinimumHeaderPad(32),
61 fCommonsMode(kCommonsIgnoreDylibs), fUUIDMode(kUUIDContent), fLocalSymbolHandling(kLocalSymbolsAll), fWarnCommons(false),
62 fVerbose(false), fKeepRelocations(false), fWarnStabs(false),
69a49097 63 fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
a61fdf0a
A
64 fSharedRegionEligible(false), fPrintOrderFileStatistics(false),
65 fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
66 fDeadStripDylibs(false), fSuppressWarnings(false), fSaveTempFiles(false)
c2646906 67{
a61fdf0a 68 this->checkForClassic(argc, argv);
c2646906
A
69 this->parsePreCommandLineEnvironmentSettings();
70 this->parse(argc, argv);
71 this->parsePostCommandLineEnvironmentSettings();
69a49097 72 this->reconfigureDefaults();
c2646906
A
73 this->checkIllegalOptionCombinations();
74}
75
76Options::~Options()
77{
78}
79
d696c285 80const ObjectFile::ReaderOptions& Options::readerOptions()
c2646906
A
81{
82 return fReaderOptions;
83}
84
85cpu_type_t Options::architecture()
86{
87 return fArchitecture;
88}
89
c2646906
A
90const char* Options::getOutputFilePath()
91{
92 return fOutputFile;
93}
94
c2646906
A
95std::vector<Options::FileInfo>& Options::getInputFiles()
96{
97 return fInputFiles;
98}
99
100Options::OutputKind Options::outputKind()
101{
102 return fOutputKind;
103}
104
d696c285 105bool Options::bindAtLoad()
c2646906 106{
d696c285 107 return fBindAtLoad;
c2646906
A
108}
109
d696c285 110bool Options::prebind()
c2646906 111{
d696c285 112 return fPrebind;
c2646906
A
113}
114
115bool Options::fullyLoadArchives()
116{
117 return fReaderOptions.fFullyLoadArchives;
118}
119
120Options::NameSpace Options::nameSpace()
121{
122 return fNameSpace;
123}
124
125const char* Options::installPath()
126{
d696c285 127 if ( fDylibInstallName != NULL )
c2646906 128 return fDylibInstallName;
a61fdf0a
A
129 else if ( fFinalName != NULL )
130 return fFinalName;
c2646906
A
131 else
132 return fOutputFile;
133}
134
135uint32_t Options::currentVersion()
136{
137 return fDylibCurrentVersion;
138}
139
140uint32_t Options::compatibilityVersion()
141{
142 return fDylibCompatVersion;
143}
144
145const char* Options::entryName()
146{
147 return fEntryName;
148}
149
150uint64_t Options::baseAddress()
151{
152 return fBaseAddress;
153}
154
155bool Options::keepPrivateExterns()
156{
157 return fKeepPrivateExterns;
158}
159
160bool Options::interposable()
161{
162 return fInterposable;
163}
164
a61fdf0a
A
165bool Options::needsModuleTable()
166{
167 return fNeedsModuleTable;
168}
169
c2646906
A
170bool Options::ignoreOtherArchInputFiles()
171{
172 return fIgnoreOtherArchFiles;
173}
174
175bool Options::forceCpuSubtypeAll()
176{
177 return fForceSubtypeAll;
178}
179
180bool Options::traceDylibs()
181{
182 return fReaderOptions.fTraceDylibs;
183}
184
185bool Options::traceArchives()
186{
187 return fReaderOptions.fTraceArchives;
188}
189
190Options::UndefinedTreatment Options::undefinedTreatment()
191{
192 return fUndefinedTreatment;
193}
194
a61fdf0a 195ObjectFile::ReaderOptions::VersionMin Options::macosxVersionMin()
d696c285 196{
a61fdf0a 197 return fReaderOptions.fVersionMin;
d696c285
A
198}
199
c2646906
A
200Options::WeakReferenceMismatchTreatment Options::weakReferenceMismatchTreatment()
201{
202 return fWeakReferenceMismatchTreatment;
203}
204
205const char* Options::umbrellaName()
206{
207 return fUmbrellaName;
208}
209
d696c285
A
210std::vector<const char*>& Options::allowableClients()
211{
212 return fAllowableClients;
213}
214
215const char* Options::clientName()
216{
217 return fClientName;
218}
219
c2646906
A
220uint64_t Options::zeroPageSize()
221{
222 return fZeroPageSize;
223}
224
225bool Options::hasCustomStack()
226{
227 return (fStackSize != 0);
228}
d696c285 229
c2646906
A
230uint64_t Options::customStackSize()
231{
232 return fStackSize;
233}
234
235uint64_t Options::customStackAddr()
236{
237 return fStackAddr;
238}
239
d696c285
A
240bool Options::hasExecutableStack()
241{
242 return fExecutableStack;
243}
244
c2646906
A
245std::vector<const char*>& Options::initialUndefines()
246{
247 return fInitialUndefines;
248}
249
69a49097
A
250bool Options::printWhyLive(const char* symbolName)
251{
252 return ( fWhyLive.find(symbolName) != fWhyLive.end() );
253}
254
d696c285 255
c2646906
A
256const char* Options::initFunctionName()
257{
258 return fInitFunctionName;
259}
260
d696c285
A
261const char* Options::dotOutputFile()
262{
263 return fDotOutputFile;
264}
265
c2646906
A
266bool Options::hasExportRestrictList()
267{
268 return (fExportMode != kExportDefault);
269}
270
69a49097
A
271bool Options::allGlobalsAreDeadStripRoots()
272{
273 // -exported_symbols_list means globals are not exported by default
a61fdf0a 274 if ( fExportMode == kExportSome )
69a49097
A
275 return false;
276 //
277 switch ( fOutputKind ) {
278 case Options::kDynamicExecutable:
279 case Options::kStaticExecutable:
280 // by default unused globals in a main executable are stripped
281 return false;
282 case Options::kDynamicLibrary:
283 case Options::kDynamicBundle:
284 case Options::kObjectFile:
285 case Options::kDyld:
286 return true;
287 }
288 return false;
289}
290
c2646906
A
291uint32_t Options::minimumHeaderPad()
292{
293 return fMinimumHeaderPad;
294}
295
296std::vector<Options::ExtraSection>& Options::extraSections()
297{
298 return fExtraSections;
299}
300
301std::vector<Options::SectionAlignment>& Options::sectionAlignments()
302{
303 return fSectionAlignments;
304}
305
c2646906
A
306Options::CommonsMode Options::commonsMode()
307{
308 return fCommonsMode;
309}
310
311bool Options::warnCommons()
312{
313 return fWarnCommons;
314}
315
d696c285
A
316bool Options::keepRelocations()
317{
318 return fKeepRelocations;
319}
320
d696c285
A
321bool Options::warnStabs()
322{
323 return fWarnStabs;
324}
325
326const char* Options::executablePath()
327{
328 return fExecutablePath;
329}
330
331Options::DeadStripMode Options::deadStrip()
332{
333 return fDeadStrip;
334}
335
c2646906
A
336bool Options::shouldExport(const char* symbolName)
337{
338 switch (fExportMode) {
339 case kExportSome:
a61fdf0a 340 return fExportSymbols.contains(symbolName);
c2646906 341 case kDontExportSome:
a61fdf0a 342 return ! fDontExportSymbols.contains(symbolName);
c2646906
A
343 case kExportDefault:
344 return true;
345 }
346 throw "internal error";
347}
348
a61fdf0a
A
349bool Options::keepLocalSymbol(const char* symbolName)
350{
351 switch (fLocalSymbolHandling) {
352 case kLocalSymbolsAll:
353 return true;
354 case kLocalSymbolsNone:
355 return false;
356 case kLocalSymbolsSelectiveInclude:
357 return fLocalSymbolsIncluded.contains(symbolName);
358 case kLocalSymbolsSelectiveExclude:
359 return ! fLocalSymbolsExcluded.contains(symbolName);
360 }
361 throw "internal error";
362}
363
c2646906
A
364void Options::parseArch(const char* architecture)
365{
366 if ( architecture == NULL )
367 throw "-arch must be followed by an architecture string";
368 if ( strcmp(architecture, "ppc") == 0 )
369 fArchitecture = CPU_TYPE_POWERPC;
370 else if ( strcmp(architecture, "ppc64") == 0 )
371 fArchitecture = CPU_TYPE_POWERPC64;
372 else if ( strcmp(architecture, "i386") == 0 )
373 fArchitecture = CPU_TYPE_I386;
69a49097
A
374 else if ( strcmp(architecture, "x86_64") == 0 )
375 fArchitecture = CPU_TYPE_X86_64;
74cfe461
A
376 // compatibility support for cpu-sub-types
377 else if ( (strcmp(architecture, "ppc750") == 0)
378 || (strcmp(architecture, "ppc7400") == 0)
379 || (strcmp(architecture, "ppc7450") == 0)
380 || (strcmp(architecture, "ppc970") == 0) )
381 fArchitecture = CPU_TYPE_POWERPC;
d696c285 382 else
74cfe461 383 throwf(" unknown/unsupported architecture name for: -arch %s", architecture);
c2646906
A
384}
385
386bool Options::checkForFile(const char* format, const char* dir, const char* rootName, FileInfo& result)
387{
388 struct stat statBuffer;
d696c285 389 char possiblePath[strlen(dir)+strlen(rootName)+strlen(format)+8];
c2646906 390 sprintf(possiblePath, format, dir, rootName);
d696c285
A
391 bool found = (stat(possiblePath, &statBuffer) == 0);
392 if ( fTraceDylibSearching )
393 printf("[Logging for XBS]%sfound library: '%s'\n", (found ? " " : " not "), possiblePath);
394 if ( found ) {
c2646906
A
395 result.path = strdup(possiblePath);
396 result.fileLen = statBuffer.st_size;
d696c285 397 result.modTime = statBuffer.st_mtime;
c2646906
A
398 return true;
399 }
400 return false;
d696c285 401}
c2646906
A
402
403
404Options::FileInfo Options::findLibrary(const char* rootName)
405{
406 FileInfo result;
407 const int rootNameLen = strlen(rootName);
408 // if rootName ends in .o there is no .a vs .dylib choice
409 if ( (rootNameLen > 3) && (strcmp(&rootName[rootNameLen-2], ".o") == 0) ) {
d696c285
A
410 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
411 it != fLibrarySearchPaths.end();
412 it++) {
c2646906
A
413 const char* dir = *it;
414 if ( checkForFile("%s/%s", dir, rootName, result) )
415 return result;
416 }
417 }
418 else {
419 bool lookForDylibs = ( fOutputKind != Options::kDyld);
420 switch ( fLibrarySearchMode ) {
d696c285 421 case kSearchAllDirsForDylibsThenAllDirsForArchives:
c2646906
A
422 // first look in all directories for just for dylibs
423 if ( lookForDylibs ) {
d696c285
A
424 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
425 it != fLibrarySearchPaths.end();
426 it++) {
c2646906
A
427 const char* dir = *it;
428 if ( checkForFile("%s/lib%s.dylib", dir, rootName, result) )
429 return result;
430 }
a61fdf0a
A
431 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
432 it != fLibrarySearchPaths.end();
433 it++) {
434 const char* dir = *it;
435 if ( checkForFile("%s/lib%s.so", dir, rootName, result) )
436 return result;
437 }
c2646906
A
438 }
439 // next look in all directories for just for archives
d696c285
A
440 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
441 it != fLibrarySearchPaths.end();
442 it++) {
c2646906
A
443 const char* dir = *it;
444 if ( checkForFile("%s/lib%s.a", dir, rootName, result) )
445 return result;
446 }
447 break;
448
449 case kSearchDylibAndArchiveInEachDir:
450 // look in each directory for just for a dylib then for an archive
d696c285
A
451 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
452 it != fLibrarySearchPaths.end();
453 it++) {
c2646906
A
454 const char* dir = *it;
455 if ( lookForDylibs && checkForFile("%s/lib%s.dylib", dir, rootName, result) )
456 return result;
a61fdf0a
A
457 if ( lookForDylibs && checkForFile("%s/lib%s.so", dir, rootName, result) )
458 return result;
c2646906
A
459 if ( checkForFile("%s/lib%s.a", dir, rootName, result) )
460 return result;
461 }
462 break;
463 }
464 }
465 throwf("library not found for -l%s", rootName);
466}
467
74cfe461
A
468Options::FileInfo Options::findFramework(const char* frameworkName)
469{
470 if ( frameworkName == NULL )
a61fdf0a 471 throw "-framework missing next argument";
74cfe461
A
472 char temp[strlen(frameworkName)+1];
473 strcpy(temp, frameworkName);
474 const char* name = temp;
475 const char* suffix = NULL;
476 char* comma = strchr(temp, ',');
477 if ( comma != NULL ) {
478 *comma = '\0';
479 suffix = &comma[1];
480 }
481 return findFramework(name, suffix);
482}
c2646906 483
74cfe461 484Options::FileInfo Options::findFramework(const char* rootName, const char* suffix)
c2646906
A
485{
486 struct stat statBuffer;
d696c285
A
487 for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin();
488 it != fFrameworkSearchPaths.end();
489 it++) {
490 // ??? Shouldn't we be using String here and just initializing it?
491 // ??? Use str.c_str () to pull out the string for the stat call.
c2646906 492 const char* dir = *it;
74cfe461 493 char possiblePath[PATH_MAX];
c2646906
A
494 strcpy(possiblePath, dir);
495 strcat(possiblePath, "/");
496 strcat(possiblePath, rootName);
497 strcat(possiblePath, ".framework/");
498 strcat(possiblePath, rootName);
74cfe461
A
499 if ( suffix != NULL ) {
500 char realPath[PATH_MAX];
501 // no symlink in framework to suffix variants, so follow main symlink
502 if ( realpath(possiblePath, realPath) != NULL ) {
503 strcpy(possiblePath, realPath);
504 strcat(possiblePath, suffix);
505 }
506 }
d696c285
A
507 bool found = (stat(possiblePath, &statBuffer) == 0);
508 if ( fTraceDylibSearching )
509 printf("[Logging for XBS]%sfound framework: '%s'\n",
510 (found ? " " : " not "), possiblePath);
511 if ( found ) {
c2646906
A
512 FileInfo result;
513 result.path = strdup(possiblePath);
514 result.fileLen = statBuffer.st_size;
d696c285 515 result.modTime = statBuffer.st_mtime;
c2646906
A
516 return result;
517 }
518 }
74cfe461 519 // try without suffix
a61fdf0a 520 if ( suffix != NULL )
74cfe461
A
521 return findFramework(rootName, NULL);
522 else
523 throwf("framework not found %s", rootName);
c2646906
A
524}
525
6e880c60 526Options::FileInfo Options::findFile(const char* path)
c2646906 527{
6e880c60 528 FileInfo result;
c2646906 529 struct stat statBuffer;
d696c285 530
6e880c60
A
531 // if absolute path and not a .o file, the use SDK prefix
532 if ( (path[0] == '/') && (strcmp(&path[strlen(path)-2], ".o") != 0) ) {
533 const int pathLen = strlen(path);
534 for (std::vector<const char*>::iterator it = fSDKPaths.begin(); it != fSDKPaths.end(); it++) {
d696c285 535 // ??? Shouldn't we be using String here?
6e880c60
A
536 const char* sdkPathDir = *it;
537 const int sdkPathDirLen = strlen(sdkPathDir);
538 char possiblePath[sdkPathDirLen+pathLen+4];
539 strcpy(possiblePath, sdkPathDir);
540 if ( possiblePath[sdkPathDirLen-1] == '/' )
541 possiblePath[sdkPathDirLen-1] = '\0';
542 strcat(possiblePath, path);
543 if ( stat(possiblePath, &statBuffer) == 0 ) {
544 result.path = strdup(possiblePath);
545 result.fileLen = statBuffer.st_size;
d696c285 546 result.modTime = statBuffer.st_mtime;
6e880c60
A
547 return result;
548 }
549 }
550 }
551 // try raw path
c2646906 552 if ( stat(path, &statBuffer) == 0 ) {
c2646906
A
553 result.path = strdup(path);
554 result.fileLen = statBuffer.st_size;
d696c285 555 result.modTime = statBuffer.st_mtime;
c2646906
A
556 return result;
557 }
d696c285
A
558
559 // try @executable_path substitution
560 if ( (strncmp(path, "@executable_path/", 17) == 0) && (fExecutablePath != NULL) ) {
561 char newPath[strlen(fExecutablePath) + strlen(path)];
562 strcpy(newPath, fExecutablePath);
563 char* addPoint = strrchr(newPath,'/');
564 if ( addPoint != NULL )
565 strcpy(&addPoint[1], &path[17]);
566 else
567 strcpy(newPath, &path[17]);
568 if ( stat(newPath, &statBuffer) == 0 ) {
569 result.path = strdup(newPath);
570 result.fileLen = statBuffer.st_size;
571 result.modTime = statBuffer.st_mtime;
572 return result;
573 }
574 }
575
6e880c60
A
576 // not found
577 throwf("file not found: %s", path);
c2646906
A
578}
579
a61fdf0a
A
580Options::FileInfo Options::findFileUsingPaths(const char* path)
581{
582 FileInfo result;
583
584 const char* lastSlash = strrchr(path, '/');
585 const char* leafName = (lastSlash == NULL) ? path : &lastSlash[1];
586
587 // Is this in a framework?
588 // /path/Foo.framework/Foo ==> true (Foo)
589 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
590 // /path/Foo.framework/Resources/Bar ==> false
591 bool isFramework = false;
592 if ( lastSlash != NULL ) {
593 char frameworkDir[strlen(leafName) + 20];
594 strcpy(frameworkDir, "/");
595 strcat(frameworkDir, leafName);
596 strcat(frameworkDir, ".framework/");
597 if ( strstr(path, frameworkDir) != NULL )
598 isFramework = true;
599 }
600
601 // These are abbreviated versions of the routines findFramework and findLibrary above
602 // because we already know the final name of the file that we're looking for and so
603 // don't need to try variations, just paths. We do need to add the additional bits
604 // onto the framework path though.
605 if ( isFramework ) {
606 for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin();
607 it != fFrameworkSearchPaths.end();
608 it++) {
609 const char* dir = *it;
610 char possiblePath[PATH_MAX];
611 strcpy(possiblePath, dir);
612 strcat(possiblePath, "/");
613 strcat(possiblePath, leafName);
614 strcat(possiblePath, ".framework");
615
616 //fprintf(stderr,"Finding Framework: %s/%s, leafName=%s\n", possiblePath, leafName, leafName);
617 if ( checkForFile("%s/%s", possiblePath, leafName, result) )
618 return result;
619 }
620 }
621 else {
622 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
623 it != fLibrarySearchPaths.end();
624 it++) {
625 const char* dir = *it;
626 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
627 if ( checkForFile("%s/%s", dir, leafName, result) )
628 return result;
629 }
630 }
631
632 // If we didn't find it fall back to findFile.
633 return findFile(path);
634}
635
636
637void Options::parseSegAddrTable(const char* segAddrPath, const char* installPath)
638{
639 FILE* file = fopen(segAddrPath, "r");
640 if ( file == NULL ) {
641 fprintf(stderr, "ld64: warning, -seg_addr_table file cannot be read: %s\n", segAddrPath);
642 return;
643 }
644
645 char path[PATH_MAX];
646 uint64_t firstColumAddress = 0;
647 uint64_t secondColumAddress = 0;
648 bool hasSecondColumn = false;
649 while ( fgets(path, PATH_MAX, file) != NULL ) {
650 path[PATH_MAX-1] = '\0';
651 char* eol = strchr(path, '\n');
652 if ( eol != NULL )
653 *eol = '\0';
654 // ignore lines not starting with 0x number
655 if ( (path[0] == '0') && (path[1] == 'x') ) {
656 char* p;
657 firstColumAddress = strtoull(path, &p, 16);
658 while ( isspace(*p) )
659 ++p;
660 // see if second column is a number
661 if ( (p[0] == '0') && (p[1] == 'x') ) {
662 secondColumAddress = strtoull(p, &p, 16);
663 hasSecondColumn = true;
664 while ( isspace(*p) )
665 ++p;
666 }
667 while ( isspace(*p) )
668 ++p;
669 if ( p[0] == '/' ) {
670 // remove any trailing whitespace
671 for(char* end = eol-1; (end > p) && isspace(*end); --end)
672 *end = '\0';
673 // see if this line is for the dylib being linked
674 if ( strcmp(p, installPath) == 0 ) {
675 fBaseAddress = firstColumAddress;
676 if ( hasSecondColumn ) {
677 fBaseWritableAddress = secondColumAddress;
678 fSplitSegs = true;
679 }
680 break; // out of while loop
681 }
682 }
683 }
684 }
685
686 fclose(file);
687}
6e880c60 688
c2646906
A
689void Options::loadFileList(const char* fileOfPaths)
690{
69a49097
A
691 FILE* file;
692 const char* comma = strrchr(fileOfPaths, ',');
693 const char* prefix = NULL;
694 if ( comma != NULL ) {
695 prefix = comma+1;
696 int realFileOfPathsLen = comma-fileOfPaths;
697 char realFileOfPaths[realFileOfPathsLen+1];
698 strncpy(realFileOfPaths,fileOfPaths, realFileOfPathsLen);
699 realFileOfPaths[realFileOfPathsLen] = '\0';
700 file = fopen(realFileOfPaths, "r");
701 if ( file == NULL )
702 throwf("-filelist file not found: %s\n", realFileOfPaths);
703 }
704 else {
705 file = fopen(fileOfPaths, "r");
706 if ( file == NULL )
707 throwf("-filelist file not found: %s\n", fileOfPaths);
708 }
d696c285 709
69a49097 710 char path[PATH_MAX];
a61fdf0a 711 while ( fgets(path, PATH_MAX, file) != NULL ) {
69a49097 712 path[PATH_MAX-1] = '\0';
c2646906
A
713 char* eol = strchr(path, '\n');
714 if ( eol != NULL )
715 *eol = '\0';
69a49097
A
716 if ( prefix != NULL ) {
717 char builtPath[strlen(prefix)+strlen(path)+2];
718 strcpy(builtPath, prefix);
719 strcat(builtPath, "/");
720 strcat(builtPath, path);
721 fInputFiles.push_back(findFile(builtPath));
722 }
723 else {
724 fInputFiles.push_back(findFile(path));
725 }
c2646906
A
726 }
727 fclose(file);
728}
729
a61fdf0a
A
730bool Options::SetWithWildcards::hasWildCards(const char* symbol)
731{
732 // an exported symbol name containing *, ?, or [ requires wildcard matching
733 return ( strpbrk(symbol, "*?[") != NULL );
734}
735
736void Options::SetWithWildcards::insert(const char* symbol)
737{
738 if ( hasWildCards(symbol) )
739 fWildCard.push_back(symbol);
740 else
741 fRegular.insert(symbol);
742}
743
744bool Options::SetWithWildcards::contains(const char* symbol)
745{
746 // first look at hash table on non-wildcard symbols
747 if ( fRegular.find(symbol) != fRegular.end() )
748 return true;
749 // next walk list of wild card symbols looking for a match
750 for(std::vector<const char*>::iterator it = fWildCard.begin(); it != fWildCard.end(); ++it) {
751 if ( wildCardMatch(*it, symbol) )
752 return true;
753 }
754 return false;
755}
756
757
758bool Options::SetWithWildcards::inCharRange(const char*& p, unsigned char c)
759{
760 ++p; // find end
761 const char* b = p;
762 while ( *p != '\0' ) {
763 if ( *p == ']') {
764 const char* e = p;
765 // found beginining [ and ending ]
766 unsigned char last = '\0';
767 for ( const char* s = b; s < e; ++s ) {
768 if ( *s == '-' ) {
769 unsigned char next = *(++s);
770 if ( (last <= c) && (c <= next) )
771 return true;
772 ++s;
773 }
774 else {
775 if ( *s == c )
776 return true;
777 last = *s;
778 }
779 }
780 return false;
781 }
782 ++p;
783 }
784 return false;
785}
786
787bool Options::SetWithWildcards::wildCardMatch(const char* pattern, const char* symbol)
788{
789 const char* s = symbol;
790 for (const char* p = pattern; *p != '\0'; ++p) {
791 switch ( *p ) {
792 case '*':
793 if ( p[1] == '\0' )
794 return true;
795 for (const char* t = s; *t != '\0'; ++t) {
796 if ( wildCardMatch(&p[1], t) )
797 return true;
798 }
799 return false;
800 case '?':
801 if ( *s == '\0' )
802 return false;
803 ++s;
804 break;
805 case '[':
806 if ( ! inCharRange(p, *s) )
807 return false;
808 ++s;
809 break;
810 default:
811 if ( *s != *p )
812 return false;
813 ++s;
814 }
815 }
816 return (*s == '\0');
817}
818
c2646906 819
a61fdf0a 820void Options::loadExportFile(const char* fileOfExports, const char* option, SetWithWildcards& set)
c2646906
A
821{
822 // read in whole file
823 int fd = ::open(fileOfExports, O_RDONLY, 0);
824 if ( fd == -1 )
825 throwf("can't open %s file: %s", option, fileOfExports);
826 struct stat stat_buf;
827 ::fstat(fd, &stat_buf);
828 char* p = (char*)malloc(stat_buf.st_size);
829 if ( p == NULL )
830 throwf("can't process %s file: %s", option, fileOfExports);
d696c285 831
c2646906
A
832 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
833 throwf("can't read %s file: %s", option, fileOfExports);
d696c285 834
c2646906 835 ::close(fd);
d696c285 836
c2646906
A
837 // parse into symbols and add to hash_set
838 char * const end = &p[stat_buf.st_size];
839 enum { lineStart, inSymbol, inComment } state = lineStart;
840 char* symbolStart = NULL;
841 for (char* s = p; s < end; ++s ) {
842 switch ( state ) {
d696c285
A
843 case lineStart:
844 if ( *s =='#' ) {
845 state = inComment;
846 }
847 else if ( !isspace(*s) ) {
848 state = inSymbol;
849 symbolStart = s;
850 }
851 break;
852 case inSymbol:
a61fdf0a 853 if ( (*s == '\n') || (*s == '\r') ) {
d696c285
A
854 *s = '\0';
855 // removing any trailing spaces
856 char* last = s-1;
857 while ( isspace(*last) ) {
858 *last = '\0';
859 --last;
c2646906 860 }
d696c285
A
861 set.insert(symbolStart);
862 symbolStart = NULL;
863 state = lineStart;
864 }
865 break;
866 case inComment:
a61fdf0a 867 if ( (*s == '\n') || (*s == '\r') )
d696c285
A
868 state = lineStart;
869 break;
870 }
871 }
872 if ( state == inSymbol ) {
873 fprintf(stderr, "ld64 warning: missing line-end at end of file \"%s\"\n", fileOfExports);
874 int len = end-symbolStart+1;
875 char* temp = new char[len];
876 strlcpy(temp, symbolStart, len);
877
878 // remove any trailing spaces
879 char* last = &temp[len-2];
880 while ( isspace(*last) ) {
881 *last = '\0';
882 --last;
c2646906 883 }
d696c285 884 set.insert(temp);
c2646906 885 }
d696c285 886
c2646906
A
887 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
888}
889
a61fdf0a
A
890void Options::parseAliasFile(const char* fileOfAliases)
891{
892 // read in whole file
893 int fd = ::open(fileOfAliases, O_RDONLY, 0);
894 if ( fd == -1 )
895 throwf("can't open alias file: %s", fileOfAliases);
896 struct stat stat_buf;
897 ::fstat(fd, &stat_buf);
898 char* p = (char*)malloc(stat_buf.st_size+1);
899 if ( p == NULL )
900 throwf("can't process alias file: %s", fileOfAliases);
901
902 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
903 throwf("can't read alias file: %s", fileOfAliases);
904 p[stat_buf.st_size] = '\n';
905 ::close(fd);
906
907 // parse into symbols and add to fAliases
908 ObjectFile::ReaderOptions::AliasPair pair;
909 char * const end = &p[stat_buf.st_size+1];
910 enum { lineStart, inRealName, inBetween, inAliasName, inComment } state = lineStart;
911 int lineNumber = 1;
912 for (char* s = p; s < end; ++s ) {
913 switch ( state ) {
914 case lineStart:
915 if ( *s =='#' ) {
916 state = inComment;
917 }
918 else if ( !isspace(*s) ) {
919 state = inRealName;
920 pair.realName = s;
921 }
922 break;
923 case inRealName:
924 if ( *s == '\n' ) {
925 fprintf(stderr, "ld64 warning: line needs two symbols but has only one at line #%d in \"%s\"\n", lineNumber, fileOfAliases);
926 ++lineNumber;
927 state = lineStart;
928 }
929 else if ( isspace(*s) ) {
930 *s = '\0';
931 state = inBetween;
932 }
933 break;
934 case inBetween:
935 if ( *s == '\n' ) {
936 fprintf(stderr, "ld64 warning: line needs two symbols but has only one at line #%d in \"%s\"\n", lineNumber, fileOfAliases);
937 ++lineNumber;
938 state = lineStart;
939 }
940 else if ( ! isspace(*s) ) {
941 state = inAliasName;
942 pair.alias = s;
943 }
944 break;
945 case inAliasName:
946 if ( *s =='#' ) {
947 *s = '\0';
948 // removing any trailing spaces
949 char* last = s-1;
950 while ( isspace(*last) ) {
951 *last = '\0';
952 --last;
953 }
954 fReaderOptions.fAliases.push_back(pair);
955 state = inComment;
956 }
957 else if ( *s == '\n' ) {
958 *s = '\0';
959 // removing any trailing spaces
960 char* last = s-1;
961 while ( isspace(*last) ) {
962 *last = '\0';
963 --last;
964 }
965 fReaderOptions.fAliases.push_back(pair);
966 state = lineStart;
967 }
968 break;
969 case inComment:
970 if ( *s == '\n' )
971 state = lineStart;
972 break;
973 }
974 }
975
976 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
977}
978
979
980
c2646906
A
981void Options::setUndefinedTreatment(const char* treatment)
982{
d696c285 983 if ( treatment == NULL )
c2646906
A
984 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
985
986 if ( strcmp(treatment, "warning") == 0 )
987 fUndefinedTreatment = kUndefinedWarning;
988 else if ( strcmp(treatment, "error") == 0 )
989 fUndefinedTreatment = kUndefinedError;
990 else if ( strcmp(treatment, "suppress") == 0 )
991 fUndefinedTreatment = kUndefinedSuppress;
992 else if ( strcmp(treatment, "dynamic_lookup") == 0 )
993 fUndefinedTreatment = kUndefinedDynamicLookup;
994 else
995 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
996}
997
d696c285 998Options::Treatment Options::parseTreatment(const char* treatment)
c2646906 999{
d696c285
A
1000 if ( treatment == NULL )
1001 return kNULL;
c2646906
A
1002
1003 if ( strcmp(treatment, "warning") == 0 )
d696c285
A
1004 return kWarning;
1005 else if ( strcmp(treatment, "error") == 0 )
1006 return kError;
c2646906 1007 else if ( strcmp(treatment, "suppress") == 0 )
d696c285
A
1008 return kSuppress;
1009 else
1010 return kInvalid;
c2646906
A
1011}
1012
d696c285
A
1013void Options::setVersionMin(const char* version)
1014{
1015 if ( version == NULL )
1016 throw "-macosx_version_min argument missing";
1017
69a49097
A
1018 if ( (strncmp(version, "10.", 3) == 0) && isdigit(version[3]) ) {
1019 int num = version[3] - '0';
1020 switch ( num ) {
1021 case 0:
1022 case 1:
a61fdf0a 1023 fReaderOptions.fVersionMin = ObjectFile::ReaderOptions::k10_1;
69a49097
A
1024 break;
1025 case 2:
a61fdf0a 1026 fReaderOptions.fVersionMin = ObjectFile::ReaderOptions::k10_2;
69a49097
A
1027 break;
1028 case 3:
a61fdf0a 1029 fReaderOptions.fVersionMin = ObjectFile::ReaderOptions::k10_3;
69a49097
A
1030 break;
1031 case 4:
a61fdf0a 1032 fReaderOptions.fVersionMin = ObjectFile::ReaderOptions::k10_4;
69a49097
A
1033 break;
1034 default:
a61fdf0a 1035 fReaderOptions.fVersionMin = ObjectFile::ReaderOptions::k10_5;
69a49097
A
1036 break;
1037 }
1038 }
1039 else {
1040 fprintf(stderr, "ld64: unknown option to -macosx_version_min not 10.x");
1041 }
c2646906
A
1042}
1043
1044void Options::setWeakReferenceMismatchTreatment(const char* treatment)
1045{
d696c285 1046 if ( treatment == NULL )
c2646906
A
1047 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1048
1049 if ( strcmp(treatment, "error") == 0 )
1050 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchError;
1051 else if ( strcmp(treatment, "weak") == 0 )
1052 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchWeak;
1053 else if ( strcmp(treatment, "non-weak") == 0 )
1054 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchNonWeak;
1055 else
1056 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1057}
1058
1059Options::CommonsMode Options::parseCommonsTreatment(const char* mode)
1060{
d696c285 1061 if ( mode == NULL )
c2646906
A
1062 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1063
1064 if ( strcmp(mode, "ignore_dylibs") == 0 )
1065 return kCommonsIgnoreDylibs;
1066 else if ( strcmp(mode, "use_dylibs") == 0 )
1067 return kCommonsOverriddenByDylibs;
1068 else if ( strcmp(mode, "error") == 0 )
1069 return kCommonsConflictsDylibsError;
1070 else
1071 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1072}
1073
a61fdf0a 1074void Options::addDylibOverride(const char* paths)
c2646906 1075{
a61fdf0a
A
1076 if ( paths == NULL )
1077 throw "-dylib_file must followed by two colon separated paths";
1078 const char* colon = strchr(paths, ':');
1079 if ( colon == NULL )
1080 throw "-dylib_file must followed by two colon separated paths";
1081 int len = colon-paths;
1082 char* target = new char[len+2];
1083 strncpy(target, paths, len);
1084 target[len] = '\0';
1085 DylibOverride entry;
1086 entry.installName = target;
1087 entry.useInstead = &colon[1];
1088 fDylibOverrides.push_back(entry);
c2646906
A
1089}
1090
c2646906
A
1091uint64_t Options::parseAddress(const char* addr)
1092{
1093 char* endptr;
1094 uint64_t result = strtoull(addr, &endptr, 16);
1095 return result;
1096}
1097
a61fdf0a
A
1098uint32_t Options::parseProtection(const char* prot)
1099{
1100 uint32_t result = 0;
1101 for(const char* p = prot; *p != '\0'; ++p) {
1102 switch(tolower(*p)) {
1103 case 'r':
1104 result |= VM_PROT_READ;
1105 break;
1106 case 'w':
1107 result |= VM_PROT_WRITE;
1108 break;
1109 case 'x':
1110 result |= VM_PROT_EXECUTE;
1111 break;
1112 case '-':
1113 break;
1114 default:
1115 throwf("unknown -segprot lettter in %s", prot);
1116 }
1117 }
1118 return result;
1119}
1120
1121
1122
c2646906 1123//
d696c285 1124// Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
c2646906
A
1125//
1126//
1127uint32_t Options::parseVersionNumber(const char* versionString)
1128{
1129 unsigned long x = 0;
1130 unsigned long y = 0;
1131 unsigned long z = 0;
1132 char* end;
1133 x = strtoul(versionString, &end, 10);
1134 if ( *end == '.' ) {
1135 y = strtoul(&end[1], &end, 10);
1136 if ( *end == '.' ) {
1137 z = strtoul(&end[1], &end, 10);
1138 }
1139 }
1140 if ( (*end != '\0') || (x > 0xffff) || (y > 0xff) || (z > 0xff) )
1141 throwf("malformed version number: %s", versionString);
1142
1143 return (x << 16) | ( y << 8 ) | z;
1144}
1145
a61fdf0a
A
1146static const char* cstringSymbolName(const char* orderFileString)
1147{
1148 char* result;
1149 asprintf(&result, "cstring=%s", orderFileString);
1150 // convert escaped characters
1151 char* d = result;
1152 for(const char* s=result; *s != '\0'; ++s, ++d) {
1153 if ( *s == '\\' ) {
1154 ++s;
1155 switch ( *s ) {
1156 case 'n':
1157 *d = '\n';
1158 break;
1159 case 't':
1160 *d = '\t';
1161 break;
1162 case 'v':
1163 *d = '\v';
1164 break;
1165 case 'b':
1166 *d = '\b';
1167 break;
1168 case 'r':
1169 *d = '\r';
1170 break;
1171 case 'f':
1172 *d = '\f';
1173 break;
1174 case 'a':
1175 *d = '\a';
1176 break;
1177 case '\\':
1178 *d = '\\';
1179 break;
1180 case '?':
1181 *d = '\?';
1182 break;
1183 case '\'':
1184 *d = '\r';
1185 break;
1186 case '\"':
1187 *d = '\"';
1188 break;
1189 case 'x':
1190 // hexadecimal value of char
1191 {
1192 ++s;
1193 char value = 0;
1194 while ( isxdigit(*s) ) {
1195 value *= 16;
1196 if ( isdigit(*s) )
1197 value += (*s-'0');
1198 else
1199 value += ((toupper(*s)-'A') + 10);
1200 ++s;
1201 }
1202 *d = value;
1203 }
1204 break;
1205 default:
1206 if ( isdigit(*s) ) {
1207 // octal value of char
1208 char value = 0;
1209 while ( isdigit(*s) ) {
1210 value = (value << 3) + (*s-'0');
1211 ++s;
1212 }
1213 *d = value;
1214 }
1215 }
1216 }
1217 else {
1218 *d = *s;
1219 }
1220 }
1221 *d = '\0';
1222 return result;
1223}
1224
1225void Options::parseOrderFile(const char* path, bool cstring)
1226{
1227 // read in whole file
1228 int fd = ::open(path, O_RDONLY, 0);
1229 if ( fd == -1 )
1230 throwf("can't open order file: %s", path);
1231 struct stat stat_buf;
1232 ::fstat(fd, &stat_buf);
1233 char* p = (char*)malloc(stat_buf.st_size+1);
1234 if ( p == NULL )
1235 throwf("can't process order file: %s", path);
1236 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1237 throwf("can't read order file: %s", path);
1238 ::close(fd);
1239 p[stat_buf.st_size] = '\n';
1240
1241 // parse into vector of pairs
1242 char * const end = &p[stat_buf.st_size+1];
1243 enum { lineStart, inSymbol, inComment } state = lineStart;
1244 char* symbolStart = NULL;
1245 for (char* s = p; s < end; ++s ) {
1246 switch ( state ) {
1247 case lineStart:
1248 if ( *s =='#' ) {
1249 state = inComment;
1250 }
1251 else if ( !isspace(*s) || cstring ) {
1252 state = inSymbol;
1253 symbolStart = s;
1254 }
1255 break;
1256 case inSymbol:
1257 if ( (*s == '\n') || (!cstring && (*s == '#')) ) {
1258 bool wasComment = (*s == '#');
1259 *s = '\0';
1260 // removing any trailing spaces
1261 char* last = s-1;
1262 while ( isspace(*last) ) {
1263 *last = '\0';
1264 --last;
1265 }
1266 if ( strncmp(symbolStart, "ppc:", 4) == 0 ) {
1267 if ( fArchitecture == CPU_TYPE_POWERPC )
1268 symbolStart = &symbolStart[4];
1269 else
1270 symbolStart = NULL;
1271 }
1272 // if there is an architecture prefix, only use this symbol it if matches current arch
1273 else if ( strncmp(symbolStart, "ppc64:", 6) == 0 ) {
1274 if ( fArchitecture == CPU_TYPE_POWERPC64 )
1275 symbolStart = &symbolStart[6];
1276 else
1277 symbolStart = NULL;
1278 }
1279 else if ( strncmp(symbolStart, "i386:", 5) == 0 ) {
1280 if ( fArchitecture == CPU_TYPE_I386 )
1281 symbolStart = &symbolStart[5];
1282 else
1283 symbolStart = NULL;
1284 }
1285 else if ( strncmp(symbolStart, "x86_64:", 7) == 0 ) {
1286 if ( fArchitecture == CPU_TYPE_X86_64 )
1287 symbolStart = &symbolStart[7];
1288 else
1289 symbolStart = NULL;
1290 }
1291 if ( symbolStart != NULL ) {
1292 char* objFileName = NULL;
1293 char* colon = strstr(symbolStart, ".o:");
1294 if ( colon != NULL ) {
1295 colon[2] = '\0';
1296 objFileName = symbolStart;
1297 symbolStart = &colon[3];
1298 }
1299 // trim leading spaces
1300 while ( isspace(*symbolStart) )
1301 ++symbolStart;
1302 Options::OrderedSymbol pair;
1303 if ( cstring )
1304 pair.symbolName = cstringSymbolName(symbolStart);
1305 else
1306 pair.symbolName = symbolStart;
1307 pair.objectFileName = objFileName;
1308 fOrderedSymbols.push_back(pair);
1309 }
1310 symbolStart = NULL;
1311 if ( wasComment )
1312 state = inComment;
1313 else
1314 state = lineStart;
1315 }
1316 break;
1317 case inComment:
1318 if ( *s == '\n' )
1319 state = lineStart;
1320 break;
1321 }
1322 }
1323 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1324}
1325
c2646906
A
1326void Options::parseSectionOrderFile(const char* segment, const char* section, const char* path)
1327{
a61fdf0a
A
1328 if ( (strcmp(section, "__cstring") == 0) && (strcmp(segment, "__TEXT") == 0) ) {
1329 parseOrderFile(path, true);
1330 }
1331 else if ( (strncmp(section, "__literal",9) == 0) && (strcmp(segment, "__TEXT") == 0) ) {
1332 fprintf(stderr, "ld64 warning: sorting of __literal[4,8,16] sections not supported\n");
1333 }
1334 else {
1335 // ignore section information and append all symbol names to global order file
1336 parseOrderFile(path, false);
1337 }
c2646906
A
1338}
1339
1340void Options::addSection(const char* segment, const char* section, const char* path)
1341{
1342 if ( strlen(segment) > 16 )
1343 throw "-seccreate segment name max 16 chars";
d696c285
A
1344 if ( strlen(section) > 16 ) {
1345 char* tmp = strdup(section);
1346 tmp[16] = '\0';
1347 fprintf(stderr, "ld64 warning: -seccreate section name (%s) truncated to 16 chars (%s)\n", section, tmp);
1348 section = tmp;
1349 }
c2646906
A
1350
1351 // read in whole file
1352 int fd = ::open(path, O_RDONLY, 0);
1353 if ( fd == -1 )
1354 throwf("can't open -sectcreate file: %s", path);
1355 struct stat stat_buf;
1356 ::fstat(fd, &stat_buf);
1357 char* p = (char*)malloc(stat_buf.st_size);
1358 if ( p == NULL )
1359 throwf("can't process -sectcreate file: %s", path);
1360 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1361 throwf("can't read -sectcreate file: %s", path);
1362 ::close(fd);
d696c285 1363
c2646906
A
1364 // record section to create
1365 ExtraSection info = { segment, section, path, (uint8_t*)p, stat_buf.st_size };
1366 fExtraSections.push_back(info);
1367}
1368
1369void Options::addSectionAlignment(const char* segment, const char* section, const char* alignmentStr)
1370{
1371 if ( strlen(segment) > 16 )
1372 throw "-sectalign segment name max 16 chars";
1373 if ( strlen(section) > 16 )
1374 throw "-sectalign section name max 16 chars";
1375
d696c285 1376 // argument to -sectalign is a hexadecimal number
c2646906
A
1377 char* endptr;
1378 unsigned long value = strtoul(alignmentStr, &endptr, 16);
1379 if ( *endptr != '\0')
1380 throw "argument for -sectalign is not a hexadecimal number";
1381 if ( value > 0x8000 )
1382 throw "argument for -sectalign must be less than or equal to 0x8000";
d696c285
A
1383 if ( value == 0 ) {
1384 fprintf(stderr, "ld64 warning: zero is not a valid -sectalign\n");
1385 value = 1;
1386 }
a61fdf0a 1387
d696c285 1388 // alignment is power of 2 (e.g. page alignment = 12)
a61fdf0a 1389 uint8_t alignment = (uint8_t)__builtin_ctz(value);
d696c285 1390 if ( (unsigned long)(1 << alignment) != value ) {
a61fdf0a 1391 fprintf(stderr, "ld64 warning: alignment for -sectalign %s %s is not a power of two, using 0x%X\n",
d696c285
A
1392 segment, section, 1 << alignment);
1393 }
c2646906
A
1394
1395 SectionAlignment info = { segment, section, alignment };
1396 fSectionAlignments.push_back(info);
1397}
1398
a61fdf0a
A
1399void Options::addLibrary(const FileInfo& info)
1400{
1401 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
1402 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
1403 if ( strcmp(info.path, fit->path) == 0 ) {
1404 // if dylib is specified again but weak, record that it should be weak
1405 if ( info.options.fWeakImport )
1406 fit->options.fWeakImport = true;
1407 return;
1408 }
1409 }
1410 // add to list
1411 fInputFiles.push_back(info);
1412}
1413
1414void Options::warnObsolete(const char* arg)
1415{
1416 if ( emitWarnings() )
1417 fprintf(stderr, "ld64: warning: option %s is obsolete and being ignored\n", arg);
1418}
1419
1420
1421
1422
d696c285
A
1423//
1424// Process all command line arguments.
1425//
1426// The only error checking done here is that each option is valid and if it has arguments
1427// that they too are valid.
1428//
1429// The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
1430// whichever was last on the command line is used.
1431//
1432// Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
1433//
c2646906
A
1434void Options::parse(int argc, const char* argv[])
1435{
1436 // pass one builds search list from -L and -F options
1437 this->buildSearchPaths(argc, argv);
d696c285
A
1438
1439 // reduce re-allocations
1440 fInputFiles.reserve(32);
1441
c2646906
A
1442 // pass two parse all other options
1443 for(int i=1; i < argc; ++i) {
1444 const char* arg = argv[i];
d696c285 1445
c2646906 1446 if ( arg[0] == '-' ) {
d696c285
A
1447
1448 // Since we don't care about the files passed, just the option names, we do this here.
1449 if (fPrintOptions)
1450 fprintf (stderr, "[Logging ld64 options]\t%s\n", arg);
1451
c2646906 1452 if ( (arg[1] == 'L') || (arg[1] == 'F') ) {
6e880c60 1453 // previously handled by buildSearchPaths()
c2646906 1454 }
a61fdf0a
A
1455 // The one gnu style option we have to keep compatibility
1456 // with gcc. Might as well have the single hyphen one as well.
1457 else if ( (strcmp(arg, "--help") == 0)
1458 || (strcmp(arg, "-help") == 0)) {
1459 fprintf (stdout, "ld64: For information on command line options please use 'man ld'.\n");
1460 exit (0);
1461 }
c2646906
A
1462 else if ( strcmp(arg, "-arch") == 0 ) {
1463 parseArch(argv[++i]);
1464 }
1465 else if ( strcmp(arg, "-dynamic") == 0 ) {
1466 // default
1467 }
1468 else if ( strcmp(arg, "-static") == 0 ) {
a61fdf0a
A
1469 if ( fOutputKind != kObjectFile )
1470 fOutputKind = kStaticExecutable;
1471 fReaderOptions.fForStatic = true;
c2646906
A
1472 }
1473 else if ( strcmp(arg, "-dylib") == 0 ) {
1474 fOutputKind = kDynamicLibrary;
1475 }
1476 else if ( strcmp(arg, "-bundle") == 0 ) {
1477 fOutputKind = kDynamicBundle;
1478 }
1479 else if ( strcmp(arg, "-dylinker") == 0 ) {
1480 fOutputKind = kDyld;
1481 }
1482 else if ( strcmp(arg, "-execute") == 0 ) {
1483 if ( fOutputKind != kStaticExecutable )
1484 fOutputKind = kDynamicExecutable;
1485 }
1486 else if ( strcmp(arg, "-r") == 0 ) {
1487 fOutputKind = kObjectFile;
1488 }
1489 else if ( strcmp(arg, "-o") == 0 ) {
1490 fOutputFile = argv[++i];
1491 }
1492 else if ( arg[1] == 'l' ) {
a61fdf0a 1493 addLibrary(findLibrary(&arg[2]));
c2646906 1494 }
d696c285
A
1495 // This causes a dylib to be weakly bound at
1496 // link time. This corresponds to weak_import.
1497 else if ( strncmp(arg, "-weak-l", 7) == 0 ) {
1498 FileInfo info = findLibrary(&arg[7]);
c2646906 1499 info.options.fWeakImport = true;
a61fdf0a 1500 addLibrary(info);
c2646906 1501 }
d696c285
A
1502 // Avoid lazy binding.
1503 // ??? Deprecate.
c2646906
A
1504 else if ( strcmp(arg, "-bind_at_load") == 0 ) {
1505 fBindAtLoad = true;
1506 }
1507 else if ( strcmp(arg, "-twolevel_namespace") == 0 ) {
1508 fNameSpace = kTwoLevelNameSpace;
1509 }
1510 else if ( strcmp(arg, "-flat_namespace") == 0 ) {
1511 fNameSpace = kFlatNameSpace;
1512 }
d696c285
A
1513 // Also sets a bit to ensure dyld causes everything
1514 // in the namespace to be flat.
1515 // ??? Deprecate
c2646906
A
1516 else if ( strcmp(arg, "-force_flat_namespace") == 0 ) {
1517 fNameSpace = kForceFlatNameSpace;
1518 }
d696c285 1519 // Similar to --whole-archive.
c2646906
A
1520 else if ( strcmp(arg, "-all_load") == 0 ) {
1521 fReaderOptions.fFullyLoadArchives = true;
1522 }
a61fdf0a
A
1523 else if ( strcmp(arg, "-noall_load") == 0) {
1524 warnObsolete(arg);
1525 }
1526 // Similar to -all_load
c2646906 1527 else if ( strcmp(arg, "-ObjC") == 0 ) {
a61fdf0a 1528 fReaderOptions.fLoadAllObjcObjectsFromArchives = true;
c2646906 1529 }
d696c285 1530 // Library versioning.
a61fdf0a
A
1531 else if ( (strcmp(arg, "-dylib_compatibility_version") == 0)
1532 || (strcmp(arg, "-compatibility_version") == 0)) {
1533 const char* vers = argv[++i];
1534 if ( vers == NULL )
1535 throw "-dylib_compatibility_version missing <version>";
1536 fDylibCompatVersion = parseVersionNumber(vers);
1537 }
1538 else if ( (strcmp(arg, "-dylib_current_version") == 0)
1539 || (strcmp(arg, "-current_version") == 0)) {
1540 const char* vers = argv[++i];
1541 if ( vers == NULL )
1542 throw "-dylib_current_version missing <version>";
1543 fDylibCurrentVersion = parseVersionNumber(vers);
c2646906
A
1544 }
1545 else if ( strcmp(arg, "-sectorder") == 0 ) {
a61fdf0a
A
1546 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
1547 throw "-sectorder missing <segment> <section> <file-path>";
c2646906
A
1548 parseSectionOrderFile(argv[i+1], argv[i+2], argv[i+3]);
1549 i += 3;
1550 }
a61fdf0a
A
1551 else if ( strcmp(arg, "-order_file") == 0 ) {
1552 parseOrderFile(argv[++i], false);
1553 }
1554 else if ( strcmp(arg, "-order_file_statistics") == 0 ) {
1555 fPrintOrderFileStatistics = true;
1556 }
d696c285
A
1557 // ??? Deprecate segcreate.
1558 // -sectcreate puts whole files into a section in the output.
c2646906 1559 else if ( (strcmp(arg, "-sectcreate") == 0) || (strcmp(arg, "-segcreate") == 0) ) {
a61fdf0a
A
1560 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
1561 throw "-sectcreate missing <segment> <section> <file-path>";
c2646906
A
1562 addSection(argv[i+1], argv[i+2], argv[i+3]);
1563 i += 3;
1564 }
d696c285 1565 // Since we have a full path in binary/library names we need to be able to override it.
a61fdf0a
A
1566 else if ( (strcmp(arg, "-dylib_install_name") == 0)
1567 || (strcmp(arg, "-dylinker_install_name") == 0)
1568 || (strcmp(arg, "-install_name") == 0)) {
c2646906 1569 fDylibInstallName = argv[++i];
a61fdf0a
A
1570 if ( fDylibInstallName == NULL )
1571 throw "-install_name missing <path>";
c2646906 1572 }
d696c285 1573 // Sets the base address of the output.
69a49097 1574 else if ( (strcmp(arg, "-seg1addr") == 0) || (strcmp(arg, "-image_base") == 0) ) {
a61fdf0a
A
1575 const char* address = argv[++i];
1576 if ( address == NULL )
1577 throwf("%s missing <address>", arg);
1578 fBaseAddress = parseAddress(address);
c2646906
A
1579 }
1580 else if ( strcmp(arg, "-e") == 0 ) {
1581 fEntryName = argv[++i];
1582 }
d696c285 1583 // Same as -@ from the FSF linker.
c2646906 1584 else if ( strcmp(arg, "-filelist") == 0 ) {
a61fdf0a
A
1585 const char* path = argv[++i];
1586 if ( (path == NULL) || (path[0] == '-') )
1587 throw "-filelist missing <path>";
1588 loadFileList(path);
c2646906
A
1589 }
1590 else if ( strcmp(arg, "-keep_private_externs") == 0 ) {
1591 fKeepPrivateExterns = true;
1592 }
1593 else if ( strcmp(arg, "-final_output") == 0 ) {
a61fdf0a 1594 fFinalName = argv[++i];
c2646906 1595 }
d696c285
A
1596 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
1597 // just ensures that this happens for cross object file boundaries.
c2646906
A
1598 else if ( (strcmp(arg, "-interposable") == 0) || (strcmp(arg, "-multi_module") == 0)) {
1599 fInterposable = true;
1600 }
d696c285 1601 // Default for -interposable/-multi_module/-single_module.
c2646906
A
1602 else if ( strcmp(arg, "-single_module") == 0 ) {
1603 fInterposable = false;
1604 }
1605 else if ( strcmp(arg, "-exported_symbols_list") == 0 ) {
1606 if ( fExportMode == kDontExportSome )
1607 throw "can't use -exported_symbols_list and -unexported_symbols_list";
1608 fExportMode = kExportSome;
1609 loadExportFile(argv[++i], "-exported_symbols_list", fExportSymbols);
1610 }
1611 else if ( strcmp(arg, "-unexported_symbols_list") == 0 ) {
1612 if ( fExportMode == kExportSome )
a61fdf0a 1613 throw "can't use -unexported_symbols_list and -exported_symbols_list";
c2646906
A
1614 fExportMode = kDontExportSome;
1615 loadExportFile(argv[++i], "-unexported_symbols_list", fDontExportSymbols);
1616 }
a61fdf0a
A
1617 else if ( strcmp(arg, "-exported_symbol") == 0 ) {
1618 if ( fExportMode == kDontExportSome )
1619 throw "can't use -exported_symbol and -unexported_symbols";
1620 fExportMode = kExportSome;
1621 fExportSymbols.insert(argv[++i]);
1622 }
1623 else if ( strcmp(arg, "-unexported_symbol") == 0 ) {
1624 if ( fExportMode == kExportSome )
1625 throw "can't use -unexported_symbol and -exported_symbol";
1626 fExportMode = kDontExportSome;
1627 fDontExportSymbols.insert(argv[++i]);
1628 }
1629 else if ( strcmp(arg, "-non_global_symbols_no_strip_list") == 0 ) {
1630 if ( fLocalSymbolHandling == kLocalSymbolsSelectiveExclude )
1631 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
1632 fLocalSymbolHandling = kLocalSymbolsSelectiveInclude;
1633 loadExportFile(argv[++i], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded);
1634 }
1635 else if ( strcmp(arg, "-non_global_symbols_strip_list") == 0 ) {
1636 if ( fLocalSymbolHandling == kLocalSymbolsSelectiveInclude )
1637 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
1638 fLocalSymbolHandling = kLocalSymbolsSelectiveExclude;
1639 loadExportFile(argv[++i], "-non_global_symbols_strip_list", fLocalSymbolsExcluded);
1640 }
d696c285 1641 // ??? Deprecate
c2646906
A
1642 else if ( strcmp(arg, "-no_arch_warnings") == 0 ) {
1643 fIgnoreOtherArchFiles = true;
1644 }
1645 else if ( strcmp(arg, "-force_cpusubtype_ALL") == 0 ) {
1646 fForceSubtypeAll = true;
1647 }
d696c285 1648 // Similar to -weak-l but uses the absolute path name to the library.
c2646906 1649 else if ( strcmp(arg, "-weak_library") == 0 ) {
6e880c60 1650 FileInfo info = findFile(argv[++i]);
c2646906 1651 info.options.fWeakImport = true;
a61fdf0a 1652 addLibrary(info);
c2646906
A
1653 }
1654 else if ( strcmp(arg, "-framework") == 0 ) {
a61fdf0a 1655 addLibrary(findFramework(argv[++i]));
c2646906
A
1656 }
1657 else if ( strcmp(arg, "-weak_framework") == 0 ) {
1658 FileInfo info = findFramework(argv[++i]);
1659 info.options.fWeakImport = true;
a61fdf0a 1660 addLibrary(info);
c2646906
A
1661 }
1662 else if ( strcmp(arg, "-search_paths_first") == 0 ) {
a61fdf0a 1663 // previously handled by buildSearchPaths()
c2646906
A
1664 }
1665 else if ( strcmp(arg, "-undefined") == 0 ) {
1666 setUndefinedTreatment(argv[++i]);
1667 }
d696c285 1668 // Debugging output flag.
c2646906
A
1669 else if ( strcmp(arg, "-arch_multiple") == 0 ) {
1670 fMessagesPrefixedWithArchitecture = true;
1671 }
d696c285
A
1672 // Specify what to do with relocations in read only
1673 // sections like .text. Could be errors, warnings,
1674 // or suppressed. Currently we do nothing with the
1675 // flag.
c2646906 1676 else if ( strcmp(arg, "-read_only_relocs") == 0 ) {
d696c285
A
1677 Treatment temp = parseTreatment(argv[++i]);
1678
1679 if ( temp == kNULL )
1680 throw "-read_only_relocs missing [ warning | error | suppress ]";
1681 else if ( temp == kInvalid )
1682 throw "invalid option to -read_only_relocs [ warning | error | suppress ]";
c2646906
A
1683 }
1684 else if ( strcmp(arg, "-sect_diff_relocs") == 0 ) {
a61fdf0a
A
1685 warnObsolete(arg);
1686 ++i;
c2646906 1687 }
d696c285
A
1688 // Warn, error or make strong a mismatch between weak
1689 // and non-weak references.
c2646906
A
1690 else if ( strcmp(arg, "-weak_reference_mismatches") == 0 ) {
1691 setWeakReferenceMismatchTreatment(argv[++i]);
1692 }
d696c285
A
1693 // For a deployment target of 10.3 and earlier ld64 will
1694 // prebind an executable with 0s in all addresses that
1695 // are prebound. This can then be fixed up by update_prebinding
1696 // later. Prebinding is less useful on 10.4 and greater.
c2646906 1697 else if ( strcmp(arg, "-prebind") == 0 ) {
d696c285 1698 fPrebind = true;
c2646906
A
1699 }
1700 else if ( strcmp(arg, "-noprebind") == 0 ) {
a61fdf0a 1701 warnObsolete(arg);
d696c285 1702 fPrebind = false;
c2646906
A
1703 }
1704 else if ( strcmp(arg, "-prebind_allow_overlap") == 0 ) {
a61fdf0a 1705 warnObsolete(arg);
c2646906
A
1706 }
1707 else if ( strcmp(arg, "-prebind_all_twolevel_modules") == 0 ) {
a61fdf0a 1708 warnObsolete(arg);
c2646906
A
1709 }
1710 else if ( strcmp(arg, "-noprebind_all_twolevel_modules") == 0 ) {
a61fdf0a 1711 warnObsolete(arg);
c2646906
A
1712 }
1713 else if ( strcmp(arg, "-nofixprebinding") == 0 ) {
a61fdf0a 1714 warnObsolete(arg);
c2646906 1715 }
d696c285
A
1716 // This should probably be deprecated when we respect -L and -F
1717 // when searching for libraries.
c2646906 1718 else if ( strcmp(arg, "-dylib_file") == 0 ) {
a61fdf0a 1719 addDylibOverride(argv[++i]);
c2646906 1720 }
a61fdf0a 1721 // What to expand @executable_path to if found in dependent dylibs
c2646906 1722 else if ( strcmp(arg, "-executable_path") == 0 ) {
d696c285
A
1723 fExecutablePath = argv[++i];
1724 if ( (fExecutablePath == NULL) || (fExecutablePath[0] == '-') )
1725 throw "-executable_path missing <path>";
a61fdf0a
A
1726 // if a directory was passed, add / to end
1727 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
1728 struct stat statBuffer;
1729 if ( stat(fExecutablePath, &statBuffer) == 0 ) {
1730 if ( (statBuffer.st_mode & S_IFMT) == S_IFDIR ) {
1731 char* pathWithSlash = new char[strlen(fExecutablePath)+2];
1732 strcpy(pathWithSlash, fExecutablePath);
1733 strcat(pathWithSlash, "/");
1734 fExecutablePath = pathWithSlash;
1735 }
1736 }
c2646906 1737 }
d696c285 1738 // Aligns all segments to the power of 2 boundary specified.
c2646906 1739 else if ( strcmp(arg, "-segalign") == 0 ) {
a61fdf0a 1740 warnObsolete(arg);
d696c285 1741 ++i;
c2646906 1742 }
d696c285
A
1743 // Puts a specified segment at a particular address that must
1744 // be a multiple of the segment alignment.
c2646906 1745 else if ( strcmp(arg, "-segaddr") == 0 ) {
a61fdf0a
A
1746 SegmentStart seg;
1747 seg.name = argv[++i];
1748 if ( (seg.name == NULL) || (argv[i+1] == NULL) )
1749 throw "-segaddr missing segName Adddress";
1750 seg.address = parseAddress(argv[++i]);
1751 uint64_t temp = seg.address & (-4096); // page align
1752 if ( (seg.address != temp) && emitWarnings() )
1753 fprintf(stderr, "ld64: warning, -segaddr %s not page aligned, rounding down\n", seg.name);
1754 fCustomSegmentAddresses.push_back(seg);
c2646906 1755 }
d696c285 1756 // ??? Deprecate when we deprecate split-seg.
c2646906 1757 else if ( strcmp(arg, "-segs_read_only_addr") == 0 ) {
a61fdf0a 1758 fBaseAddress = parseAddress(argv[++i]);
c2646906 1759 }
d696c285 1760 // ??? Deprecate when we deprecate split-seg.
c2646906 1761 else if ( strcmp(arg, "-segs_read_write_addr") == 0 ) {
a61fdf0a
A
1762 fBaseWritableAddress = parseAddress(argv[++i]);
1763 fSplitSegs = true;
c2646906 1764 }
d696c285 1765 // ??? Deprecate when we get rid of basing at build time.
c2646906 1766 else if ( strcmp(arg, "-seg_addr_table") == 0 ) {
a61fdf0a
A
1767 const char* name = argv[++i];
1768 if ( name == NULL )
1769 throw "-seg_addr_table missing argument";
1770 fSegAddrTablePath = name;
c2646906
A
1771 }
1772 else if ( strcmp(arg, "-seg_addr_table_filename") == 0 ) {
a61fdf0a 1773 warnObsolete(arg);
d696c285 1774 ++i;
c2646906
A
1775 }
1776 else if ( strcmp(arg, "-segprot") == 0 ) {
a61fdf0a
A
1777 SegmentProtect seg;
1778 seg.name = argv[++i];
1779 if ( (seg.name == NULL) || (argv[i+1] == NULL) || (argv[i+2] == NULL) )
1780 throw "-segprot missing segName max-prot init-prot";
1781 seg.max = parseProtection(argv[++i]);
1782 seg.init = parseProtection(argv[++i]);
1783 fCustomSegmentProtections.push_back(seg);
c2646906
A
1784 }
1785 else if ( strcmp(arg, "-pagezero_size") == 0 ) {
a61fdf0a
A
1786 const char* size = argv[++i];
1787 if ( size == NULL )
1788 throw "-pagezero_size missing <size>";
1789 fZeroPageSize = parseAddress(size);
69a49097 1790 uint64_t temp = fZeroPageSize & (-4096); // page align
a61fdf0a 1791 if ( (fZeroPageSize != temp) && emitWarnings() )
69a49097
A
1792 fprintf(stderr, "ld64: warning, -pagezero_size not page aligned, rounding down\n");
1793 fZeroPageSize = temp;
c2646906
A
1794 }
1795 else if ( strcmp(arg, "-stack_addr") == 0 ) {
a61fdf0a
A
1796 const char* address = argv[++i];
1797 if ( address == NULL )
1798 throw "-stack_addr missing <address>";
1799 fStackAddr = parseAddress(address);
c2646906
A
1800 }
1801 else if ( strcmp(arg, "-stack_size") == 0 ) {
a61fdf0a
A
1802 const char* size = argv[++i];
1803 if ( size == NULL )
1804 throw "-stack_size missing <address>";
1805 fStackSize = parseAddress(size);
1806 uint64_t temp = fStackSize & (-4096); // page align
1807 if ( (fStackSize != temp) && emitWarnings() )
1808 fprintf(stderr, "ld64: warning, -stack_size not page aligned, rounding down\n");
c2646906 1809 }
d696c285
A
1810 else if ( strcmp(arg, "-allow_stack_execute") == 0 ) {
1811 fExecutableStack = true;
1812 }
c2646906 1813 else if ( strcmp(arg, "-sectalign") == 0 ) {
a61fdf0a
A
1814 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
1815 throw "-sectalign missing <segment> <section> <file-path>";
c2646906
A
1816 addSectionAlignment(argv[i+1], argv[i+2], argv[i+3]);
1817 i += 3;
1818 }
1819 else if ( strcmp(arg, "-sectorder_detail") == 0 ) {
a61fdf0a 1820 warnObsolete(arg);
c2646906
A
1821 }
1822 else if ( strcmp(arg, "-sectobjectsymbols") == 0 ) {
a61fdf0a 1823 warnObsolete(arg);
c2646906
A
1824 i += 2;
1825 }
1826 else if ( strcmp(arg, "-bundle_loader") == 0 ) {
69a49097
A
1827 fBundleLoader = argv[++i];
1828 if ( (fBundleLoader == NULL) || (fBundleLoader[0] == '-') )
1829 throw "-bundle_loader missing <path>";
1830 FileInfo info = findFile(fBundleLoader);
1831 info.options.fBundleLoader = true;
1832 fInputFiles.push_back(info);
c2646906
A
1833 }
1834 else if ( strcmp(arg, "-private_bundle") == 0 ) {
a61fdf0a 1835 warnObsolete(arg);
c2646906
A
1836 }
1837 else if ( strcmp(arg, "-twolevel_namespace_hints") == 0 ) {
1838 // FIX FIX
1839 }
d696c285 1840 // Use this flag to set default behavior for deployement targets.
c7f24d34 1841 else if ( strcmp(arg, "-macosx_version_min") == 0 ) {
d696c285 1842 setVersionMin(argv[++i]);
c7f24d34 1843 }
c2646906 1844 else if ( strcmp(arg, "-multiply_defined") == 0 ) {
a61fdf0a
A
1845 //warnObsolete(arg);
1846 ++i;
c2646906
A
1847 }
1848 else if ( strcmp(arg, "-multiply_defined_unused") == 0 ) {
a61fdf0a
A
1849 warnObsolete(arg);
1850 ++i;
c2646906
A
1851 }
1852 else if ( strcmp(arg, "-nomultidefs") == 0 ) {
a61fdf0a 1853 warnObsolete(arg);
c2646906 1854 }
d696c285
A
1855 // Display each file in which the argument symbol appears and whether
1856 // the file defines or references it. This option takes an argument
1857 // as -y<symbol> note that there is no space.
1858 else if ( strncmp(arg, "-y", 2) == 0 ) {
a61fdf0a 1859 warnObsolete("-y");
c2646906 1860 }
d696c285 1861 // Same output as -y, but output <arg> number of undefined symbols only.
c2646906 1862 else if ( strcmp(arg, "-Y") == 0 ) {
a61fdf0a
A
1863 //warnObsolete(arg);
1864 ++i;
c2646906 1865 }
d696c285 1866 // This option affects all objects linked into the final result.
c2646906 1867 else if ( strcmp(arg, "-m") == 0 ) {
a61fdf0a 1868 warnObsolete(arg);
c2646906 1869 }
69a49097
A
1870 else if ( (strcmp(arg, "-why_load") == 0) || (strcmp(arg, "-whyload") == 0) ) {
1871 fReaderOptions.fWhyLoad = true;
1872 }
1873 else if ( strcmp(arg, "-why_live") == 0 ) {
1874 const char* name = argv[++i];
1875 if ( name == NULL )
1876 throw "-why_live missing symbol name argument";
1877 fWhyLive.insert(name);
c2646906
A
1878 }
1879 else if ( strcmp(arg, "-u") == 0 ) {
1880 const char* name = argv[++i];
1881 if ( name == NULL )
1882 throw "-u missing argument";
1883 fInitialUndefines.push_back(name);
1884 }
c2646906 1885 else if ( strcmp(arg, "-U") == 0 ) {
a61fdf0a
A
1886 const char* name = argv[++i];
1887 if ( name == NULL )
1888 throw "-U missing argument";
1889 fAllowedUndefined.insert(name);
c2646906
A
1890 }
1891 else if ( strcmp(arg, "-s") == 0 ) {
a61fdf0a
A
1892 warnObsolete(arg);
1893 fLocalSymbolHandling = kLocalSymbolsNone;
d696c285 1894 fReaderOptions.fDebugInfoStripping = ObjectFile::ReaderOptions::kDebugInfoNone;
c2646906
A
1895 }
1896 else if ( strcmp(arg, "-x") == 0 ) {
a61fdf0a 1897 fLocalSymbolHandling = kLocalSymbolsNone;
c2646906
A
1898 }
1899 else if ( strcmp(arg, "-S") == 0 ) {
d696c285 1900 fReaderOptions.fDebugInfoStripping = ObjectFile::ReaderOptions::kDebugInfoNone;
c2646906
A
1901 }
1902 else if ( strcmp(arg, "-X") == 0 ) {
a61fdf0a 1903 warnObsolete(arg);
c2646906
A
1904 }
1905 else if ( strcmp(arg, "-Si") == 0 ) {
a61fdf0a 1906 warnObsolete(arg);
d696c285 1907 fReaderOptions.fDebugInfoStripping = ObjectFile::ReaderOptions::kDebugInfoFull;
c2646906
A
1908 }
1909 else if ( strcmp(arg, "-b") == 0 ) {
a61fdf0a 1910 warnObsolete(arg);
c2646906
A
1911 }
1912 else if ( strcmp(arg, "-Sn") == 0 ) {
a61fdf0a 1913 warnObsolete(arg);
d696c285
A
1914 fReaderOptions.fDebugInfoStripping = ObjectFile::ReaderOptions::kDebugInfoFull;
1915 }
1916 else if ( strcmp(arg, "-Sp") == 0 ) {
a61fdf0a 1917 warnObsolete(arg);
c2646906
A
1918 }
1919 else if ( strcmp(arg, "-dead_strip") == 0 ) {
69a49097 1920 fDeadStrip = kDeadStripOnPlusUnusedInits;
d696c285
A
1921 }
1922 else if ( strcmp(arg, "-no_dead_strip_inits_and_terms") == 0 ) {
69a49097 1923 fDeadStrip = kDeadStripOn;
c2646906 1924 }
c2646906 1925 else if ( strcmp(arg, "-w") == 0 ) {
a61fdf0a 1926 // previously handled by buildSearchPaths()
c2646906
A
1927 }
1928 else if ( strcmp(arg, "-arch_errors_fatal") == 0 ) {
1929 // FIX FIX
1930 }
1931 else if ( strcmp(arg, "-M") == 0 ) {
1932 // FIX FIX
1933 }
c2646906
A
1934 else if ( strcmp(arg, "-headerpad") == 0 ) {
1935 const char* size = argv[++i];
1936 if ( size == NULL )
1937 throw "-headerpad missing argument";
1938 fMinimumHeaderPad = parseAddress(size);
1939 }
1940 else if ( strcmp(arg, "-headerpad_max_install_names") == 0 ) {
a61fdf0a 1941 fMaxMinimumHeaderPad = true;
c2646906
A
1942 }
1943 else if ( strcmp(arg, "-t") == 0 ) {
a61fdf0a
A
1944 fReaderOptions.fLogAllFiles = true;
1945 }
1946 else if ( strcmp(arg, "-whatsloaded") == 0 ) {
1947 fReaderOptions.fLogObjectFiles = true;
c2646906
A
1948 }
1949 else if ( strcmp(arg, "-A") == 0 ) {
a61fdf0a 1950 warnObsolete(arg);
d696c285 1951 ++i;
c2646906
A
1952 }
1953 else if ( strcmp(arg, "-umbrella") == 0 ) {
1954 const char* name = argv[++i];
1955 if ( name == NULL )
1956 throw "-umbrella missing argument";
1957 fUmbrellaName = name;
1958 }
1959 else if ( strcmp(arg, "-allowable_client") == 0 ) {
d696c285
A
1960 const char* name = argv[++i];
1961
1962 if ( name == NULL )
1963 throw "-allowable_client missing argument";
1964
1965 fAllowableClients.push_back(name);
c2646906
A
1966 }
1967 else if ( strcmp(arg, "-client_name") == 0 ) {
d696c285
A
1968 const char* name = argv[++i];
1969
1970 if ( name == NULL )
1971 throw "-client_name missing argument";
1972
1973 fClientName = name;
c2646906
A
1974 }
1975 else if ( strcmp(arg, "-sub_umbrella") == 0 ) {
1976 const char* name = argv[++i];
1977 if ( name == NULL )
1978 throw "-sub_umbrella missing argument";
1979 fSubUmbellas.push_back(name);
1980 }
1981 else if ( strcmp(arg, "-sub_library") == 0 ) {
1982 const char* name = argv[++i];
1983 if ( name == NULL )
1984 throw "-sub_library missing argument";
1985 fSubLibraries.push_back(name);
1986 }
1987 else if ( strcmp(arg, "-init") == 0 ) {
1988 const char* name = argv[++i];
1989 if ( name == NULL )
1990 throw "-init missing argument";
1991 fInitFunctionName = name;
1992 }
d696c285
A
1993 else if ( strcmp(arg, "-dot") == 0 ) {
1994 const char* name = argv[++i];
1995 if ( name == NULL )
1996 throw "-dot missing argument";
1997 fDotOutputFile = name;
1998 }
c2646906
A
1999 else if ( strcmp(arg, "-warn_commons") == 0 ) {
2000 fWarnCommons = true;
2001 }
2002 else if ( strcmp(arg, "-commons") == 0 ) {
2003 fCommonsMode = parseCommonsTreatment(argv[++i]);
2004 }
d696c285
A
2005 else if ( strcmp(arg, "-keep_relocs") == 0 ) {
2006 fKeepRelocations = true;
2007 }
2008 else if ( strcmp(arg, "-warn_stabs") == 0 ) {
2009 fWarnStabs = true;
2010 }
2011 else if ( strcmp(arg, "-pause") == 0 ) {
2012 fPause = true;
2013 }
2014 else if ( strcmp(arg, "-print_statistics") == 0 ) {
2015 fStatistics = true;
2016 }
69a49097 2017 else if ( strcmp(arg, "-d") == 0 ) {
a61fdf0a 2018 fReaderOptions.fMakeTentativeDefinitionsReal = true;
69a49097 2019 }
6e880c60
A
2020 else if ( strcmp(arg, "-v") == 0 ) {
2021 // previously handled by buildSearchPaths()
2022 }
2023 else if ( strcmp(arg, "-Z") == 0 ) {
2024 // previously handled by buildSearchPaths()
2025 }
2026 else if ( strcmp(arg, "-syslibroot") == 0 ) {
2027 ++i;
2028 // previously handled by buildSearchPaths()
2029 }
d696c285 2030 else if ( strcmp(arg, "-no_uuid") == 0 ) {
a61fdf0a
A
2031 fUUIDMode = kUUIDNone;
2032 }
2033 else if ( strcmp(arg, "-random_uuid") == 0 ) {
2034 fUUIDMode = kUUIDRandom;
2035 }
2036 else if ( strcmp(arg, "-dtrace") == 0 ) {
2037 const char* name = argv[++i];
2038 if ( name == NULL )
2039 throw "-dtrace missing argument";
2040 fDtraceScriptName = name;
2041 }
2042 else if ( strcmp(arg, "-root_safe") == 0 ) {
2043 fReaderOptions.fRootSafe = true;
2044 }
2045 else if ( strcmp(arg, "-setuid_safe") == 0 ) {
2046 fReaderOptions.fSetuidSafe = true;
2047 }
2048 else if ( strcmp(arg, "-alias") == 0 ) {
2049 ObjectFile::ReaderOptions::AliasPair pair;
2050 pair.realName = argv[++i];
2051 if ( pair.realName == NULL )
2052 throw "missing argument to -alias";
2053 pair.alias = argv[++i];
2054 if ( pair.alias == NULL )
2055 throw "missing argument to -alias";
2056 fReaderOptions.fAliases.push_back(pair);
2057 }
2058 else if ( strcmp(arg, "-alias_list") == 0 ) {
2059 parseAliasFile(argv[++i]);
d696c285
A
2060 }
2061 // put this last so that it does not interfer with other options starting with 'i'
2062 else if ( strncmp(arg, "-i", 2) == 0 ) {
a61fdf0a
A
2063 const char* colon = strchr(arg, ':');
2064 if ( colon == NULL )
2065 throwf("unknown option: %s", arg);
2066 ObjectFile::ReaderOptions::AliasPair pair;
2067 char* temp = new char[colon-arg];
2068 strlcpy(temp, &arg[2], colon-arg-1);
2069 pair.realName = &colon[1];
2070 pair.alias = temp;
2071 fReaderOptions.fAliases.push_back(pair);
2072 }
2073 else if ( strcmp(arg, "-save-temps") == 0 ) {
2074 fSaveTempFiles = true;
2075 }
2076 else if ( strcmp(arg, "-rpath") == 0 ) {
2077 const char* path = argv[++i];
2078 if ( path == NULL )
2079 throw "missing argument to -rpath";
2080 fRPaths.push_back(path);
2081 }
2082 else if ( strcmp(arg, "-read_only_stubs") == 0 ) {
2083 fReadOnlyx86Stubs = true;
2084 }
2085 else if ( strcmp(arg, "-map") == 0 ) {
2086 fMapPath = argv[++i];
2087 if ( fMapPath == NULL )
2088 throw "missing argument to -map";
2089 }
2090 else if ( strcmp(arg, "-pie") == 0 ) {
2091 fPositionIndependentExecutable = true;
2092 }
2093 else if ( strncmp(arg, "-reexport-l", 11) == 0 ) {
2094 FileInfo info = findLibrary(&arg[11]);
2095 info.options.fReExport = true;
2096 addLibrary(info);
2097 }
2098 else if ( strcmp(arg, "-reexport_library") == 0 ) {
2099 FileInfo info = findFile(argv[++i]);
2100 info.options.fReExport = true;
2101 addLibrary(info);
2102 }
2103 else if ( strcmp(arg, "-reexport_framework") == 0 ) {
2104 FileInfo info = findFramework(argv[++i]);
2105 info.options.fReExport = true;
2106 addLibrary(info);
2107 }
2108 else if ( strcmp(arg, "-dead_strip_dylibs") == 0 ) {
2109 fDeadStripDylibs = true;
2110 }
2111 else if ( strcmp(arg, "-new_linker") == 0 ) {
2112 // ignore
d696c285 2113 }
c2646906 2114 else {
d696c285 2115 throwf("unknown option: %s", arg);
c2646906
A
2116 }
2117 }
2118 else {
a61fdf0a
A
2119 FileInfo info = findFile(arg);
2120 if ( strcmp(&info.path[strlen(info.path)-2], ".a") == 0 )
2121 addLibrary(info);
2122 else
2123 fInputFiles.push_back(info);
c2646906
A
2124 }
2125 }
2126}
2127
69a49097
A
2128
2129
d696c285
A
2130//
2131// -syslibroot <path> is used for SDK support.
6e880c60
A
2132// The rule is that all search paths (both explicit and default) are
2133// checked to see if they exist in the SDK. If so, that path is
2134// replaced with the sdk prefixed path. If not, that search path
2135// is used as is. If multiple -syslibroot options are specified
2136// their directory structures are logically overlayed and files
2137// from sdks specified earlier on the command line used before later ones.
d696c285 2138
c2646906
A
2139void Options::buildSearchPaths(int argc, const char* argv[])
2140{
2141 bool addStandardLibraryDirectories = true;
6e880c60
A
2142 std::vector<const char*> libraryPaths;
2143 std::vector<const char*> frameworkPaths;
d696c285
A
2144 libraryPaths.reserve(10);
2145 frameworkPaths.reserve(10);
6e880c60 2146 // scan through argv looking for -L, -F, -Z, and -syslibroot options
c2646906
A
2147 for(int i=0; i < argc; ++i) {
2148 if ( (argv[i][0] == '-') && (argv[i][1] == 'L') )
6e880c60 2149 libraryPaths.push_back(&argv[i][2]);
c2646906 2150 else if ( (argv[i][0] == '-') && (argv[i][1] == 'F') )
6e880c60 2151 frameworkPaths.push_back(&argv[i][2]);
c2646906
A
2152 else if ( strcmp(argv[i], "-Z") == 0 )
2153 addStandardLibraryDirectories = false;
6e880c60
A
2154 else if ( strcmp(argv[i], "-v") == 0 ) {
2155 fVerbose = true;
a61fdf0a
A
2156 extern const char ldVersionString[];
2157 fprintf(stderr, "%s", ldVersionString);
6e880c60
A
2158 // if only -v specified, exit cleanly
2159 if ( argc == 2 )
2160 exit(0);
2161 }
2162 else if ( strcmp(argv[i], "-syslibroot") == 0 ) {
2163 const char* path = argv[++i];
2164 if ( path == NULL )
2165 throw "-syslibroot missing argument";
2166 fSDKPaths.push_back(path);
2167 }
a61fdf0a
A
2168 else if ( strcmp(argv[i], "-search_paths_first") == 0 ) {
2169 // ??? Deprecate when we get -Bstatic/-Bdynamic.
2170 fLibrarySearchMode = kSearchDylibAndArchiveInEachDir;
2171 }
2172 else if ( strcmp(argv[i], "-w") == 0 ) {
2173 fSuppressWarnings = true;
2174 }
c2646906
A
2175 }
2176 if ( addStandardLibraryDirectories ) {
6e880c60
A
2177 libraryPaths.push_back("/usr/lib");
2178 libraryPaths.push_back("/usr/local/lib");
d696c285 2179
6e880c60 2180 frameworkPaths.push_back("/Library/Frameworks/");
6e880c60 2181 frameworkPaths.push_back("/System/Library/Frameworks/");
a61fdf0a 2182 frameworkPaths.push_back("/Network/Library/Frameworks/");
6e880c60 2183 }
d696c285 2184
6e880c60 2185 // now merge sdk and library paths to make real search paths
d696c285 2186 fLibrarySearchPaths.reserve(libraryPaths.size()*(fSDKPaths.size()+1));
6e880c60
A
2187 for (std::vector<const char*>::iterator it = libraryPaths.begin(); it != libraryPaths.end(); it++) {
2188 const char* libDir = *it;
2189 bool sdkOverride = false;
2190 if ( libDir[0] == '/' ) {
2191 char betterLibDir[PATH_MAX];
2192 if ( strstr(libDir, "/..") != NULL ) {
2193 if ( realpath(libDir, betterLibDir) != NULL )
d696c285 2194 libDir = strdup(betterLibDir);
6e880c60
A
2195 }
2196 const int libDirLen = strlen(libDir);
2197 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
d696c285 2198 // ??? Should be using string here.
6e880c60
A
2199 const char* sdkDir = *sdkit;
2200 const int sdkDirLen = strlen(sdkDir);
2201 char newPath[libDirLen + sdkDirLen+4];
2202 strcpy(newPath, sdkDir);
2203 if ( newPath[sdkDirLen-1] == '/' )
2204 newPath[sdkDirLen-1] = '\0';
2205 strcat(newPath, libDir);
2206 struct stat statBuffer;
2207 if ( stat(newPath, &statBuffer) == 0 ) {
2208 fLibrarySearchPaths.push_back(strdup(newPath));
2209 sdkOverride = true;
2210 }
2211 }
2212 }
d696c285 2213 if ( !sdkOverride )
6e880c60
A
2214 fLibrarySearchPaths.push_back(libDir);
2215 }
d696c285 2216
6e880c60 2217 // now merge sdk and framework paths to make real search paths
d696c285 2218 fFrameworkSearchPaths.reserve(frameworkPaths.size()*(fSDKPaths.size()+1));
6e880c60
A
2219 for (std::vector<const char*>::iterator it = frameworkPaths.begin(); it != frameworkPaths.end(); it++) {
2220 const char* frameworkDir = *it;
2221 bool sdkOverride = false;
2222 if ( frameworkDir[0] == '/' ) {
2223 char betterFrameworkDir[PATH_MAX];
2224 if ( strstr(frameworkDir, "/..") != NULL ) {
2225 if ( realpath(frameworkDir, betterFrameworkDir) != NULL )
d696c285 2226 frameworkDir = strdup(betterFrameworkDir);
6e880c60
A
2227 }
2228 const int frameworkDirLen = strlen(frameworkDir);
2229 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
d696c285 2230 // ??? Should be using string here
6e880c60
A
2231 const char* sdkDir = *sdkit;
2232 const int sdkDirLen = strlen(sdkDir);
2233 char newPath[frameworkDirLen + sdkDirLen+4];
2234 strcpy(newPath, sdkDir);
2235 if ( newPath[sdkDirLen-1] == '/' )
2236 newPath[sdkDirLen-1] = '\0';
2237 strcat(newPath, frameworkDir);
2238 struct stat statBuffer;
2239 if ( stat(newPath, &statBuffer) == 0 ) {
2240 fFrameworkSearchPaths.push_back(strdup(newPath));
2241 sdkOverride = true;
2242 }
2243 }
2244 }
d696c285 2245 if ( !sdkOverride )
6e880c60
A
2246 fFrameworkSearchPaths.push_back(frameworkDir);
2247 }
d696c285 2248
6e880c60
A
2249 if ( fVerbose ) {
2250 fprintf(stderr,"Library search paths:\n");
d696c285
A
2251 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
2252 it != fLibrarySearchPaths.end();
2253 it++)
6e880c60
A
2254 fprintf(stderr,"\t%s\n", *it);
2255 fprintf(stderr,"Framework search paths:\n");
d696c285
A
2256 for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin();
2257 it != fFrameworkSearchPaths.end();
2258 it++)
6e880c60 2259 fprintf(stderr,"\t%s\n", *it);
c2646906
A
2260 }
2261}
2262
2263// this is run before the command line is parsed
2264void Options::parsePreCommandLineEnvironmentSettings()
2265{
d696c285
A
2266 if ((getenv("LD_TRACE_ARCHIVES") != NULL)
2267 || (getenv("RC_TRACE_ARCHIVES") != NULL))
c2646906 2268 fReaderOptions.fTraceArchives = true;
d696c285
A
2269
2270 if ((getenv("LD_TRACE_DYLIBS") != NULL)
2271 || (getenv("RC_TRACE_DYLIBS") != NULL)) {
c2646906
A
2272 fReaderOptions.fTraceDylibs = true;
2273 fReaderOptions.fTraceIndirectDylibs = true;
2274 }
d696c285
A
2275
2276 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL) {
2277 fTraceDylibSearching = true;
2278 }
2279
2280 if (getenv("LD_PRINT_OPTIONS") != NULL)
2281 fPrintOptions = true;
2282
2283 if (fReaderOptions.fTraceDylibs || fReaderOptions.fTraceArchives)
2284 fReaderOptions.fTraceOutputFile = getenv("LD_TRACE_FILE");
a61fdf0a
A
2285
2286 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL)
2287 fPrintOrderFileStatistics = true;
c2646906
A
2288}
2289
2290// this is run after the command line is parsed
2291void Options::parsePostCommandLineEnvironmentSettings()
2292{
d696c285
A
2293 // when building a dynamic main executable, default any use of @executable_path to output path
2294 if ( fExecutablePath == NULL && (fOutputKind == kDynamicExecutable) ) {
2295 fExecutablePath = fOutputFile;
2296 }
a61fdf0a
A
2297
2298 // allow build system to set default seg_addr_table
2299 if ( fSegAddrTablePath == NULL )
2300 fSegAddrTablePath = getenv("LD_SEG_ADDR_TABLE");
2301
2302 // allow build system to turn on prebinding
2303 if ( !fPrebind ) {
2304 fPrebind = ( getenv("LD_PREBIND") != NULL );
2305 }
69a49097
A
2306}
2307
2308void Options::reconfigureDefaults()
2309{
2310 // sync reader options
2311 switch ( fOutputKind ) {
2312 case Options::kObjectFile:
2313 fReaderOptions.fForFinalLinkedImage = false;
2314 break;
a61fdf0a
A
2315 case Options::kDyld:
2316 fReaderOptions.fForDyld = true;
2317 fReaderOptions.fForFinalLinkedImage = true;
2318 break;
69a49097
A
2319 case Options::kDynamicLibrary:
2320 case Options::kDynamicBundle:
a61fdf0a
A
2321 fReaderOptions.fForFinalLinkedImage = true;
2322 break;
2323 case Options::kDynamicExecutable:
2324 case Options::kStaticExecutable:
2325 fReaderOptions.fLinkingMainExecutable = true;
69a49097
A
2326 fReaderOptions.fForFinalLinkedImage = true;
2327 break;
2328 }
2329
2330 // set default min OS version
a61fdf0a
A
2331 if ( fReaderOptions.fVersionMin == ObjectFile::ReaderOptions::kMinUnset ) {
2332 // if -macosx_version_min not used, try environment variable
2333 const char* envVers = getenv("MACOSX_DEPLOYMENT_TARGET");
2334 if ( envVers != NULL )
2335 setVersionMin(envVers);
2336 // if -macosx_version_min and environment variable not used assume current OS version
2337 if ( fReaderOptions.fVersionMin == ObjectFile::ReaderOptions::kMinUnset )
2338 fReaderOptions.fVersionMin = ObjectFile::ReaderOptions::k10_5; // FIX FIX, this really should be a check of the OS version the linker is running on
69a49097
A
2339 }
2340
2341 // adjust min based on architecture
2342 switch ( fArchitecture ) {
2343 case CPU_TYPE_I386:
a61fdf0a 2344 if ( fReaderOptions.fVersionMin < ObjectFile::ReaderOptions::k10_4 ) {
69a49097 2345 //fprintf(stderr, "ld64 warning: -macosx_version_min should be 10.4 or later for i386\n");
a61fdf0a 2346 fReaderOptions.fVersionMin = ObjectFile::ReaderOptions::k10_4;
69a49097
A
2347 }
2348 break;
2349 case CPU_TYPE_POWERPC64:
a61fdf0a 2350 if ( fReaderOptions.fVersionMin < ObjectFile::ReaderOptions::k10_4 ) {
69a49097 2351 //fprintf(stderr, "ld64 warning: -macosx_version_min should be 10.4 or later for ppc64\n");
a61fdf0a 2352 fReaderOptions.fVersionMin = ObjectFile::ReaderOptions::k10_4;
69a49097
A
2353 }
2354 break;
2355 case CPU_TYPE_X86_64:
a61fdf0a 2356 if ( fReaderOptions.fVersionMin < ObjectFile::ReaderOptions::k10_4 ) {
69a49097 2357 //fprintf(stderr, "ld64 warning: -macosx_version_min should be 10.4 or later for x86_64\n");
a61fdf0a 2358 fReaderOptions.fVersionMin = ObjectFile::ReaderOptions::k10_4;
69a49097
A
2359 }
2360 break;
2361 }
a61fdf0a
A
2362
2363 // determine if info for shared region should be added
2364 if ( fOutputKind == Options::kDynamicLibrary ) {
2365 if ( fReaderOptions.fVersionMin >= ObjectFile::ReaderOptions::k10_5 )
2366 fSharedRegionEligible = true;
2367 }
2368
2369 // allow build system to force linker to ignore seg_addr_table
2370 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL )
2371 fSegAddrTablePath = NULL;
2372
2373 // check for base address specified externally
2374 if ( (fSegAddrTablePath != NULL) && (fOutputKind == Options::kDynamicLibrary) )
2375 parseSegAddrTable(fSegAddrTablePath, this->installPath());
2376
2377
2378 // split segs only allowed for dylibs
2379 if ( fSplitSegs ) {
2380 if ( fOutputKind != Options::kDynamicLibrary )
2381 fSplitSegs = false;
2382 // split seg only supported for ppc and i386
2383 switch ( fArchitecture ) {
2384 case CPU_TYPE_POWERPC:
2385 case CPU_TYPE_I386:
2386 break;
2387 default:
2388 fSplitSegs = false;
2389 fBaseAddress = 0;
2390 fBaseWritableAddress = 0;
2391 }
2392 }
2393
2394 // disable prebinding depending on arch and min OS version
2395 if ( fPrebind ) {
2396 switch ( fArchitecture ) {
2397 case CPU_TYPE_POWERPC:
2398 case CPU_TYPE_I386:
2399 if ( fReaderOptions.fVersionMin >= ObjectFile::ReaderOptions::k10_4 ) {
2400 // only split seg dylibs are prebound
2401 if ( (fOutputKind != Options::kDynamicLibrary) || ! fSplitSegs )
2402 fPrebind = false;
2403 }
2404 break;
2405 case CPU_TYPE_POWERPC64:
2406 case CPU_TYPE_X86_64:
2407 fPrebind = false;
2408 break;
2409 }
2410 }
2411
2412
2413 // figure out if module table is needed for compatibility with old ld/dyld
2414 if ( fOutputKind == Options::kDynamicLibrary ) {
2415 switch ( fArchitecture ) {
2416 case CPU_TYPE_POWERPC: // 10.3 and earlier dyld requires a module table
2417 case CPU_TYPE_I386: // ld_classic for 10.4.x requires a module table
2418 if ( fReaderOptions.fVersionMin <= ObjectFile::ReaderOptions::k10_5 )
2419 fNeedsModuleTable = true;
2420 }
2421 }
2422
69a49097 2423
c2646906
A
2424}
2425
2426void Options::checkIllegalOptionCombinations()
2427{
2428 // check -undefined setting
2429 switch ( fUndefinedTreatment ) {
2430 case kUndefinedError:
2431 case kUndefinedDynamicLookup:
2432 // always legal
2433 break;
2434 case kUndefinedWarning:
2435 case kUndefinedSuppress:
2436 // requires flat namespace
2437 if ( fNameSpace == kTwoLevelNameSpace )
2438 throw "can't use -undefined warning or suppress with -twolevel_namespace";
2439 break;
2440 }
d696c285 2441
c2646906
A
2442 // unify -sub_umbrella with dylibs
2443 for (std::vector<const char*>::iterator it = fSubUmbellas.begin(); it != fSubUmbellas.end(); it++) {
2444 const char* subUmbrella = *it;
2445 bool found = false;
2446 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
2447 Options::FileInfo& info = *fit;
2448 const char* lastSlash = strrchr(info.path, '/');
2449 if ( lastSlash == NULL )
2450 lastSlash = info.path - 1;
2451 if ( strcmp(&lastSlash[1], subUmbrella) == 0 ) {
2452 info.options.fReExport = true;
2453 found = true;
2454 break;
2455 }
2456 }
a61fdf0a 2457 if ( ! found && emitWarnings() )
c2646906
A
2458 fprintf(stderr, "ld64 warning: -sub_umbrella %s does not match a supplied dylib\n", subUmbrella);
2459 }
d696c285 2460
c2646906
A
2461 // unify -sub_library with dylibs
2462 for (std::vector<const char*>::iterator it = fSubLibraries.begin(); it != fSubLibraries.end(); it++) {
2463 const char* subLibrary = *it;
2464 bool found = false;
2465 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
2466 Options::FileInfo& info = *fit;
2467 const char* lastSlash = strrchr(info.path, '/');
2468 if ( lastSlash == NULL )
2469 lastSlash = info.path - 1;
69a49097 2470 const char* dot = strchr(&lastSlash[1], '.');
c2646906
A
2471 if ( dot == NULL )
2472 dot = &lastSlash[strlen(lastSlash)];
2473 if ( strncmp(&lastSlash[1], subLibrary, dot-lastSlash-1) == 0 ) {
2474 info.options.fReExport = true;
2475 found = true;
2476 break;
2477 }
2478 }
a61fdf0a 2479 if ( ! found && emitWarnings() )
c2646906
A
2480 fprintf(stderr, "ld64 warning: -sub_library %s does not match a supplied dylib\n", subLibrary);
2481 }
d696c285 2482
c2646906
A
2483 // sync reader options
2484 if ( fNameSpace != kTwoLevelNameSpace )
2485 fReaderOptions.fFlatNamespace = true;
2486
2487 // check -stack_addr
d696c285 2488 if ( fStackAddr != 0 ) {
c2646906
A
2489 switch (fArchitecture) {
2490 case CPU_TYPE_I386:
2491 case CPU_TYPE_POWERPC:
d696c285 2492 if ( fStackAddr > 0xFFFFFFFF )
c2646906
A
2493 throw "-stack_addr must be < 4G for 32-bit processes";
2494 break;
2495 case CPU_TYPE_POWERPC64:
69a49097 2496 case CPU_TYPE_X86_64:
c2646906
A
2497 break;
2498 }
2499 if ( (fStackAddr & -4096) != fStackAddr )
2500 throw "-stack_addr must be multiples of 4K";
2501 if ( fStackSize == 0 )
2502 throw "-stack_addr must be used with -stack_size";
2503 }
d696c285 2504
c2646906 2505 // check -stack_size
d696c285 2506 if ( fStackSize != 0 ) {
c2646906
A
2507 switch (fArchitecture) {
2508 case CPU_TYPE_I386:
2509 case CPU_TYPE_POWERPC:
d696c285 2510 if ( fStackSize > 0xFFFFFFFF )
c2646906
A
2511 throw "-stack_size must be < 4G for 32-bit processes";
2512 if ( fStackAddr == 0 ) {
c2646906
A
2513 fStackAddr = 0xC0000000;
2514 }
a61fdf0a 2515 if ( (fStackAddr > 0xB0000000) && ((fStackAddr-fStackSize) < 0xB0000000) && emitWarnings() )
69a49097 2516 fprintf(stderr, "ld64 warning: custom stack placement overlaps and will disable shared region\n");
c2646906
A
2517 break;
2518 case CPU_TYPE_POWERPC64:
69a49097 2519 case CPU_TYPE_X86_64:
c2646906 2520 if ( fStackAddr == 0 ) {
a61fdf0a 2521 fStackAddr = 0x00007FFF5C000000LL;
c2646906
A
2522 }
2523 break;
2524 }
2525 if ( (fStackSize & -4096) != fStackSize )
2526 throw "-stack_size must be multiples of 4K";
2527 switch ( fOutputKind ) {
2528 case Options::kDynamicExecutable:
2529 case Options::kStaticExecutable:
d696c285 2530 // custom stack size only legal when building main executable
c2646906
A
2531 break;
2532 case Options::kDynamicLibrary:
2533 case Options::kDynamicBundle:
2534 case Options::kObjectFile:
2535 case Options::kDyld:
2536 throw "-stack_size option can only be used when linking a main executable";
2537 }
2538 }
d696c285
A
2539
2540 // check that -allow_stack_execute is only used with main executables
2541 if ( fExecutableStack ) {
2542 switch ( fOutputKind ) {
2543 case Options::kDynamicExecutable:
2544 case Options::kStaticExecutable:
2545 // -allow_stack_execute size only legal when building main executable
2546 break;
2547 case Options::kDynamicLibrary:
2548 case Options::kDynamicBundle:
2549 case Options::kObjectFile:
2550 case Options::kDyld:
2551 throw "-allow_stack_execute option can only be used when linking a main executable";
2552 }
2553 }
2554
a61fdf0a
A
2555 // check -client_name is only used when making a bundle or main executable
2556 if ( fClientName != NULL ) {
2557 switch ( fOutputKind ) {
2558 case Options::kDynamicExecutable:
2559 case Options::kDynamicBundle:
2560 break;
2561 case Options::kStaticExecutable:
2562 case Options::kDynamicLibrary:
2563 case Options::kObjectFile:
2564 case Options::kDyld:
2565 throw "-client_name can only be used with -bundle";
2566 }
2567 }
2568
c2646906
A
2569 // check -init is only used when building a dylib
2570 if ( (fInitFunctionName != NULL) && (fOutputKind != Options::kDynamicLibrary) )
2571 throw "-init can only be used with -dynamiclib";
c2646906 2572
69a49097
A
2573 // check -bundle_loader only used with -bundle
2574 if ( (fBundleLoader != NULL) && (fOutputKind != Options::kDynamicBundle) )
2575 throw "-bundle_loader can only be used with -bundle";
2576
a61fdf0a
A
2577 // check -dtrace not used with -r
2578 if ( (fDtraceScriptName != NULL) && (fOutputKind == Options::kObjectFile) )
2579 throw "-dtrace can only be used when creating final linked images";
2580
69a49097 2581 // check -d can only be used with -r
a61fdf0a 2582 if ( fReaderOptions.fMakeTentativeDefinitionsReal && (fOutputKind != Options::kObjectFile) )
69a49097 2583 throw "-d can only be used with -r";
a61fdf0a
A
2584
2585 // check that -root_safe is not used with -r
2586 if ( fReaderOptions.fRootSafe && (fOutputKind == Options::kObjectFile) )
2587 throw "-root_safe cannot be used with -r";
2588
2589 // check that -setuid_safe is not used with -r
2590 if ( fReaderOptions.fSetuidSafe && (fOutputKind == Options::kObjectFile) )
2591 throw "-setuid_safe cannot be used with -r";
2592
d696c285 2593 // make sure all required exported symbols exist
a61fdf0a
A
2594 std::vector<const char*> impliedExports;
2595 for (NameSet::iterator it=fExportSymbols.regularBegin(); it != fExportSymbols.regularEnd(); it++) {
d696c285
A
2596 const char* name = *it;
2597 // never export .eh symbols
a61fdf0a
A
2598 const int len = strlen(name);
2599 if ( (strcmp(&name[len-3], ".eh") == 0) || (strncmp(name, ".objc_category_name_", 20) == 0) )
2600 fprintf(stderr, "ld64 warning: ignoring %s in export list\n", name);
2601 else
d696c285 2602 fInitialUndefines.push_back(name);
a61fdf0a
A
2603 if ( strncmp(name, ".objc_class_name_", 17) == 0 ) {
2604 // rdar://problem/4718189 map ObjC class names to new runtime names
2605 switch (fArchitecture) {
2606 case CPU_TYPE_POWERPC64:
2607 case CPU_TYPE_X86_64:
2608 char* temp;
2609 asprintf(&temp, "_OBJC_CLASS_$_%s", &name[17]);
2610 impliedExports.push_back(temp);
2611 asprintf(&temp, "_OBJC_METACLASS_$_%s", &name[17]);
2612 impliedExports.push_back(temp);
2613 break;
2614 }
2615 }
d696c285 2616 }
a61fdf0a
A
2617 for (std::vector<const char*>::iterator it=impliedExports.begin(); it != impliedExports.end(); it++) {
2618 const char* name = *it;
2619 fExportSymbols.insert(name);
2620 fInitialUndefines.push_back(name);
2621 }
2622
69a49097
A
2623 // make sure that -init symbol exist
2624 if ( fInitFunctionName != NULL )
2625 fInitialUndefines.push_back(fInitFunctionName);
2626
a61fdf0a
A
2627 // check custom segments
2628 if ( fCustomSegmentAddresses.size() != 0 ) {
2629 // verify no segment is in zero page
2630 if ( fZeroPageSize != ULLONG_MAX ) {
2631 for (std::vector<SegmentStart>::iterator it = fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
2632 if ( (it->address >= 0) && (it->address < fZeroPageSize) )
2633 throwf("-segaddr %s 0x%X conflicts with -pagezero_size", it->name, it->address);
2634 }
2635 }
2636 // verify no duplicates
2637 for (std::vector<SegmentStart>::iterator it = fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
2638 for (std::vector<SegmentStart>::iterator it2 = fCustomSegmentAddresses.begin(); it2 != fCustomSegmentAddresses.end(); ++it2) {
2639 if ( (it->address == it2->address) && (it != it2) )
2640 throwf("duplicate -segaddr addresses for %s and %s", it->name, it2->name);
2641 }
2642 // a custom segment address of zero will disable the use of a zero page
2643 if ( it->address == 0 )
2644 fZeroPageSize = 0;
2645 }
2646 }
2647
69a49097
A
2648 if ( fZeroPageSize == ULLONG_MAX ) {
2649 // zero page size not specified on command line, set default
2650 switch (fArchitecture) {
2651 case CPU_TYPE_I386:
2652 case CPU_TYPE_POWERPC:
2653 // first 4KB for 32-bit architectures
2654 fZeroPageSize = 0x1000;
2655 break;
2656 case CPU_TYPE_POWERPC64:
2657 // first 4GB for ppc64 on 10.5
a61fdf0a 2658 if ( fReaderOptions.fVersionMin >= ObjectFile::ReaderOptions::k10_5 )
69a49097
A
2659 fZeroPageSize = 0x100000000ULL;
2660 else
2661 fZeroPageSize = 0x1000; // 10.4 dyld may not be able to handle >4GB zero page
2662 break;
2663 case CPU_TYPE_X86_64:
2664 // first 4GB for x86_64 on all OS's
2665 fZeroPageSize = 0x100000000ULL;
2666 break;
2667 default:
2668 // if -arch not used, default to 4K zero-page
2669 fZeroPageSize = 0x1000;
2670 }
2671 }
2672 else {
2673 switch ( fOutputKind ) {
2674 case Options::kDynamicExecutable:
2675 case Options::kStaticExecutable:
2676 // -pagezero_size size only legal when building main executable
2677 break;
2678 case Options::kDynamicLibrary:
2679 case Options::kDynamicBundle:
2680 case Options::kObjectFile:
2681 case Options::kDyld:
a61fdf0a
A
2682 if ( fZeroPageSize != 0 )
2683 throw "-pagezero_size option can only be used when linking a main executable";
2684 }
69a49097
A
2685 }
2686
2687 // -dead_strip and -r are incompatible
2688 if ( (fDeadStrip != kDeadStripOff) && (fOutputKind == Options::kObjectFile) )
2689 throw "-r and -dead_strip cannot be used together\n";
c2646906 2690
a61fdf0a
A
2691 // can't use -rpath unless targeting 10.5 or later
2692 if ( fRPaths.size() > 0 ) {
2693 if ( fReaderOptions.fVersionMin < ObjectFile::ReaderOptions::k10_5 )
2694 throw "-rpath can only be used when targeting Mac OS X 10.5 or later\n";
2695 switch ( fOutputKind ) {
2696 case Options::kDynamicExecutable:
2697 case Options::kDynamicLibrary:
2698 case Options::kDynamicBundle:
2699 break;
2700 case Options::kStaticExecutable:
2701 case Options::kObjectFile:
2702 case Options::kDyld:
2703 throw "-rpath can only be used when creating a dynamic final linked image";
2704 }
2705 }
2706
2707 // check -pie is only used when building a dynamic main executable for 10.5
2708 if ( fPositionIndependentExecutable ) {
2709 if ( fOutputKind != Options::kDynamicExecutable )
2710 throw "-pie can only be used when linking a main executable";
2711 if ( fReaderOptions.fVersionMin < ObjectFile::ReaderOptions::k10_5 )
2712 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
2713 }
d696c285 2714}
74cfe461
A
2715
2716
2717
a61fdf0a
A
2718void Options::checkForClassic(int argc, const char* argv[])
2719{
2720 // scan options
2721 bool archFound = false;
2722 bool staticFound = false;
2723 bool dtraceFound = false;
2724 bool rFound = false;
2725 bool creatingMachKernel = false;
2726 bool newLinker = false;
74cfe461 2727
a61fdf0a
A
2728 for(int i=0; i < argc; ++i) {
2729 const char* arg = argv[i];
2730 if ( arg[0] == '-' ) {
2731 if ( strcmp(arg, "-arch") == 0 ) {
2732 parseArch(argv[++i]);
2733 archFound = true;
2734 }
2735 else if ( strcmp(arg, "-static") == 0 ) {
2736 staticFound = true;
2737 }
2738 else if ( strcmp(arg, "-dtrace") == 0 ) {
2739 dtraceFound = true;
2740 }
2741 else if ( strcmp(arg, "-r") == 0 ) {
2742 rFound = true;
2743 }
2744 else if ( strcmp(arg, "-new_linker") == 0 ) {
2745 newLinker = true;
2746 }
2747 else if ( strcmp(arg, "-classic_linker") == 0 ) {
2748 // ld_classic does not understand this option, so remove it
2749 for(int j=i; j < argc; ++j)
2750 argv[j] = argv[j+1];
2751 this->gotoClassicLinker(argc-1, argv);
2752 }
2753 else if ( strcmp(arg, "-o") == 0 ) {
2754 const char* outfile = argv[++i];
2755 if ( (outfile != NULL) && (strstr(outfile, "/mach_kernel") != NULL) )
2756 creatingMachKernel = true;
2757 }
2758 }
2759 }
2760
2761 // -dtrace only supported by new linker
2762 if( dtraceFound )
2763 return;
2764
2765 if( archFound ) {
2766 switch ( fArchitecture ) {
2767 case CPU_TYPE_POWERPC:
2768 case CPU_TYPE_I386:
2769// if ( staticFound && (rFound || !creatingMachKernel) ) {
2770 if ( staticFound && !newLinker ) {
2771 // this environment variable will disable use of ld_classic for -static links
2772 if ( getenv("LD_NO_CLASSIC_LINKER_STATIC") == NULL )
2773 this->gotoClassicLinker(argc, argv);
2774 }
2775 break;
2776 }
2777 }
2778 else {
2779 // work around for VSPTool
2780 if ( staticFound )
2781 this->gotoClassicLinker(argc, argv);
2782 }
2783
2784}
2785
2786void Options::gotoClassicLinker(int argc, const char* argv[])
2787{
2788 argv[0] = "ld_classic";
2789 execvp(argv[0], (char**)argv);
2790 fprintf(stderr, "can't exec ld_classic\n");
2791 exit(1);
2792}