1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2005-2007 Apple Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
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
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.
22 * @APPLE_LICENSE_HEADER_END@
26 #include <sys/types.h>
28 #include <mach/vm_prot.h>
35 void throwf(const char* format
, ...)
39 va_start(list
, format
);
40 vasprintf(&p
, format
, list
);
47 Options::Options(int argc
, const char* argv
[])
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),
54 fExportMode(kExportDefault
), fLibrarySearchMode(kSearchAllDirsForDylibsThenAllDirsForArchives
),
55 fUndefinedTreatment(kUndefinedError
), fMessagesPrefixedWithArchitecture(false),
56 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak
),
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),
63 fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
64 fSharedRegionEligible(false), fPrintOrderFileStatistics(false),
65 fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
66 fDeadStripDylibs(false), fSuppressWarnings(false), fSaveTempFiles(false)
68 this->checkForClassic(argc
, argv
);
69 this->parsePreCommandLineEnvironmentSettings();
70 this->parse(argc
, argv
);
71 this->parsePostCommandLineEnvironmentSettings();
72 this->reconfigureDefaults();
73 this->checkIllegalOptionCombinations();
80 const ObjectFile::ReaderOptions
& Options::readerOptions()
82 return fReaderOptions
;
85 cpu_type_t
Options::architecture()
90 const char* Options::getOutputFilePath()
95 std::vector
<Options::FileInfo
>& Options::getInputFiles()
100 Options::OutputKind
Options::outputKind()
105 bool Options::bindAtLoad()
110 bool Options::prebind()
115 bool Options::fullyLoadArchives()
117 return fReaderOptions
.fFullyLoadArchives
;
120 Options::NameSpace
Options::nameSpace()
125 const char* Options::installPath()
127 if ( fDylibInstallName
!= NULL
)
128 return fDylibInstallName
;
129 else if ( fFinalName
!= NULL
)
135 uint32_t Options::currentVersion()
137 return fDylibCurrentVersion
;
140 uint32_t Options::compatibilityVersion()
142 return fDylibCompatVersion
;
145 const char* Options::entryName()
150 uint64_t Options::baseAddress()
155 bool Options::keepPrivateExterns()
157 return fKeepPrivateExterns
;
160 bool Options::interposable()
162 return fInterposable
;
165 bool Options::needsModuleTable()
167 return fNeedsModuleTable
;
170 bool Options::ignoreOtherArchInputFiles()
172 return fIgnoreOtherArchFiles
;
175 bool Options::forceCpuSubtypeAll()
177 return fForceSubtypeAll
;
180 bool Options::traceDylibs()
182 return fReaderOptions
.fTraceDylibs
;
185 bool Options::traceArchives()
187 return fReaderOptions
.fTraceArchives
;
190 Options::UndefinedTreatment
Options::undefinedTreatment()
192 return fUndefinedTreatment
;
195 ObjectFile::ReaderOptions::VersionMin
Options::macosxVersionMin()
197 return fReaderOptions
.fVersionMin
;
200 Options::WeakReferenceMismatchTreatment
Options::weakReferenceMismatchTreatment()
202 return fWeakReferenceMismatchTreatment
;
205 const char* Options::umbrellaName()
207 return fUmbrellaName
;
210 std::vector
<const char*>& Options::allowableClients()
212 return fAllowableClients
;
215 const char* Options::clientName()
220 uint64_t Options::zeroPageSize()
222 return fZeroPageSize
;
225 bool Options::hasCustomStack()
227 return (fStackSize
!= 0);
230 uint64_t Options::customStackSize()
235 uint64_t Options::customStackAddr()
240 bool Options::hasExecutableStack()
242 return fExecutableStack
;
245 std::vector
<const char*>& Options::initialUndefines()
247 return fInitialUndefines
;
250 bool Options::printWhyLive(const char* symbolName
)
252 return ( fWhyLive
.find(symbolName
) != fWhyLive
.end() );
256 const char* Options::initFunctionName()
258 return fInitFunctionName
;
261 const char* Options::dotOutputFile()
263 return fDotOutputFile
;
266 bool Options::hasExportRestrictList()
268 return (fExportMode
!= kExportDefault
);
271 bool Options::allGlobalsAreDeadStripRoots()
273 // -exported_symbols_list means globals are not exported by default
274 if ( fExportMode
== kExportSome
)
277 switch ( fOutputKind
) {
278 case Options::kDynamicExecutable
:
279 case Options::kStaticExecutable
:
280 // by default unused globals in a main executable are stripped
282 case Options::kDynamicLibrary
:
283 case Options::kDynamicBundle
:
284 case Options::kObjectFile
:
291 uint32_t Options::minimumHeaderPad()
293 return fMinimumHeaderPad
;
296 std::vector
<Options::ExtraSection
>& Options::extraSections()
298 return fExtraSections
;
301 std::vector
<Options::SectionAlignment
>& Options::sectionAlignments()
303 return fSectionAlignments
;
306 Options::CommonsMode
Options::commonsMode()
311 bool Options::warnCommons()
316 bool Options::keepRelocations()
318 return fKeepRelocations
;
321 bool Options::warnStabs()
326 const char* Options::executablePath()
328 return fExecutablePath
;
331 Options::DeadStripMode
Options::deadStrip()
336 bool Options::shouldExport(const char* symbolName
)
338 switch (fExportMode
) {
340 return fExportSymbols
.contains(symbolName
);
341 case kDontExportSome
:
342 return ! fDontExportSymbols
.contains(symbolName
);
346 throw "internal error";
349 bool Options::keepLocalSymbol(const char* symbolName
)
351 switch (fLocalSymbolHandling
) {
352 case kLocalSymbolsAll
:
354 case kLocalSymbolsNone
:
356 case kLocalSymbolsSelectiveInclude
:
357 return fLocalSymbolsIncluded
.contains(symbolName
);
358 case kLocalSymbolsSelectiveExclude
:
359 return ! fLocalSymbolsExcluded
.contains(symbolName
);
361 throw "internal error";
364 void Options::parseArch(const char* architecture
)
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
;
374 else if ( strcmp(architecture
, "x86_64") == 0 )
375 fArchitecture
= CPU_TYPE_X86_64
;
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
;
383 throwf(" unknown/unsupported architecture name for: -arch %s", architecture
);
386 bool Options::checkForFile(const char* format
, const char* dir
, const char* rootName
, FileInfo
& result
)
388 struct stat statBuffer
;
389 char possiblePath
[strlen(dir
)+strlen(rootName
)+strlen(format
)+8];
390 sprintf(possiblePath
, format
, dir
, rootName
);
391 bool found
= (stat(possiblePath
, &statBuffer
) == 0);
392 if ( fTraceDylibSearching
)
393 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), possiblePath
);
395 result
.path
= strdup(possiblePath
);
396 result
.fileLen
= statBuffer
.st_size
;
397 result
.modTime
= statBuffer
.st_mtime
;
404 Options::FileInfo
Options::findLibrary(const char* rootName
)
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) ) {
410 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
411 it
!= fLibrarySearchPaths
.end();
413 const char* dir
= *it
;
414 if ( checkForFile("%s/%s", dir
, rootName
, result
) )
419 bool lookForDylibs
= ( fOutputKind
!= Options::kDyld
);
420 switch ( fLibrarySearchMode
) {
421 case kSearchAllDirsForDylibsThenAllDirsForArchives
:
422 // first look in all directories for just for dylibs
423 if ( lookForDylibs
) {
424 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
425 it
!= fLibrarySearchPaths
.end();
427 const char* dir
= *it
;
428 if ( checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
431 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
432 it
!= fLibrarySearchPaths
.end();
434 const char* dir
= *it
;
435 if ( checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
439 // next look in all directories for just for archives
440 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
441 it
!= fLibrarySearchPaths
.end();
443 const char* dir
= *it
;
444 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
449 case kSearchDylibAndArchiveInEachDir
:
450 // look in each directory for just for a dylib then for an archive
451 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
452 it
!= fLibrarySearchPaths
.end();
454 const char* dir
= *it
;
455 if ( lookForDylibs
&& checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
457 if ( lookForDylibs
&& checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
459 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
465 throwf("library not found for -l%s", rootName
);
468 Options::FileInfo
Options::findFramework(const char* frameworkName
)
470 if ( frameworkName
== NULL
)
471 throw "-framework missing next argument";
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
) {
481 return findFramework(name
, suffix
);
484 Options::FileInfo
Options::findFramework(const char* rootName
, const char* suffix
)
486 struct stat statBuffer
;
487 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
488 it
!= fFrameworkSearchPaths
.end();
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.
492 const char* dir
= *it
;
493 char possiblePath
[PATH_MAX
];
494 strcpy(possiblePath
, dir
);
495 strcat(possiblePath
, "/");
496 strcat(possiblePath
, rootName
);
497 strcat(possiblePath
, ".framework/");
498 strcat(possiblePath
, rootName
);
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
);
507 bool found
= (stat(possiblePath
, &statBuffer
) == 0);
508 if ( fTraceDylibSearching
)
509 printf("[Logging for XBS]%sfound framework: '%s'\n",
510 (found
? " " : " not "), possiblePath
);
513 result
.path
= strdup(possiblePath
);
514 result
.fileLen
= statBuffer
.st_size
;
515 result
.modTime
= statBuffer
.st_mtime
;
519 // try without suffix
520 if ( suffix
!= NULL
)
521 return findFramework(rootName
, NULL
);
523 throwf("framework not found %s", rootName
);
526 Options::FileInfo
Options::findFile(const char* path
)
529 struct stat statBuffer
;
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
++) {
535 // ??? Shouldn't we be using String here?
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
;
546 result
.modTime
= statBuffer
.st_mtime
;
552 if ( stat(path
, &statBuffer
) == 0 ) {
553 result
.path
= strdup(path
);
554 result
.fileLen
= statBuffer
.st_size
;
555 result
.modTime
= statBuffer
.st_mtime
;
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]);
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
;
577 throwf("file not found: %s", path
);
580 Options::FileInfo
Options::findFileUsingPaths(const char* path
)
584 const char* lastSlash
= strrchr(path
, '/');
585 const char* leafName
= (lastSlash
== NULL
) ? path
: &lastSlash
[1];
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
)
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.
606 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
607 it
!= fFrameworkSearchPaths
.end();
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");
616 //fprintf(stderr,"Finding Framework: %s/%s, leafName=%s\n", possiblePath, leafName, leafName);
617 if ( checkForFile("%s/%s", possiblePath
, leafName
, result
) )
622 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
623 it
!= fLibrarySearchPaths
.end();
625 const char* dir
= *it
;
626 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
627 if ( checkForFile("%s/%s", dir
, leafName
, result
) )
632 // If we didn't find it fall back to findFile.
633 return findFile(path
);
637 void Options::parseSegAddrTable(const char* segAddrPath
, const char* installPath
)
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
);
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');
654 // ignore lines not starting with 0x number
655 if ( (path
[0] == '0') && (path
[1] == 'x') ) {
657 firstColumAddress
= strtoull(path
, &p
, 16);
658 while ( isspace(*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
) )
667 while ( isspace(*p
) )
670 // remove any trailing whitespace
671 for(char* end
= eol
-1; (end
> p
) && isspace(*end
); --end
)
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
;
680 break; // out of while loop
689 void Options::loadFileList(const char* fileOfPaths
)
692 const char* comma
= strrchr(fileOfPaths
, ',');
693 const char* prefix
= NULL
;
694 if ( comma
!= NULL
) {
696 int realFileOfPathsLen
= comma
-fileOfPaths
;
697 char realFileOfPaths
[realFileOfPathsLen
+1];
698 strncpy(realFileOfPaths
,fileOfPaths
, realFileOfPathsLen
);
699 realFileOfPaths
[realFileOfPathsLen
] = '\0';
700 file
= fopen(realFileOfPaths
, "r");
702 throwf("-filelist file not found: %s\n", realFileOfPaths
);
705 file
= fopen(fileOfPaths
, "r");
707 throwf("-filelist file not found: %s\n", fileOfPaths
);
711 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
712 path
[PATH_MAX
-1] = '\0';
713 char* eol
= strchr(path
, '\n');
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
));
724 fInputFiles
.push_back(findFile(path
));
730 bool Options::SetWithWildcards::hasWildCards(const char* symbol
)
732 // an exported symbol name containing *, ?, or [ requires wildcard matching
733 return ( strpbrk(symbol
, "*?[") != NULL
);
736 void Options::SetWithWildcards::insert(const char* symbol
)
738 if ( hasWildCards(symbol
) )
739 fWildCard
.push_back(symbol
);
741 fRegular
.insert(symbol
);
744 bool Options::SetWithWildcards::contains(const char* symbol
)
746 // first look at hash table on non-wildcard symbols
747 if ( fRegular
.find(symbol
) != fRegular
.end() )
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
) )
758 bool Options::SetWithWildcards::inCharRange(const char*& p
, unsigned char c
)
762 while ( *p
!= '\0' ) {
765 // found beginining [ and ending ]
766 unsigned char last
= '\0';
767 for ( const char* s
= b
; s
< e
; ++s
) {
769 unsigned char next
= *(++s
);
770 if ( (last
<= c
) && (c
<= next
) )
787 bool Options::SetWithWildcards::wildCardMatch(const char* pattern
, const char* symbol
)
789 const char* s
= symbol
;
790 for (const char* p
= pattern
; *p
!= '\0'; ++p
) {
795 for (const char* t
= s
; *t
!= '\0'; ++t
) {
796 if ( wildCardMatch(&p
[1], t
) )
806 if ( ! inCharRange(p
, *s
) )
820 void Options::loadExportFile(const char* fileOfExports
, const char* option
, SetWithWildcards
& set
)
822 // read in whole file
823 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
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
);
830 throwf("can't process %s file: %s", option
, fileOfExports
);
832 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
833 throwf("can't read %s file: %s", option
, fileOfExports
);
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
) {
847 else if ( !isspace(*s
) ) {
853 if ( (*s
== '\n') || (*s
== '\r') ) {
855 // removing any trailing spaces
857 while ( isspace(*last
) ) {
861 set
.insert(symbolStart
);
867 if ( (*s
== '\n') || (*s
== '\r') )
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
);
878 // remove any trailing spaces
879 char* last
= &temp
[len
-2];
880 while ( isspace(*last
) ) {
887 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
890 void Options::parseAliasFile(const char* fileOfAliases
)
892 // read in whole file
893 int fd
= ::open(fileOfAliases
, O_RDONLY
, 0);
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);
900 throwf("can't process alias file: %s", fileOfAliases
);
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';
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
;
912 for (char* s
= p
; s
< end
; ++s
) {
918 else if ( !isspace(*s
) ) {
925 fprintf(stderr
, "ld64 warning: line needs two symbols but has only one at line #%d in \"%s\"\n", lineNumber
, fileOfAliases
);
929 else if ( isspace(*s
) ) {
936 fprintf(stderr
, "ld64 warning: line needs two symbols but has only one at line #%d in \"%s\"\n", lineNumber
, fileOfAliases
);
940 else if ( ! isspace(*s
) ) {
948 // removing any trailing spaces
950 while ( isspace(*last
) ) {
954 fReaderOptions
.fAliases
.push_back(pair
);
957 else if ( *s
== '\n' ) {
959 // removing any trailing spaces
961 while ( isspace(*last
) ) {
965 fReaderOptions
.fAliases
.push_back(pair
);
976 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
981 void Options::setUndefinedTreatment(const char* treatment
)
983 if ( treatment
== NULL
)
984 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
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
;
995 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
998 Options::Treatment
Options::parseTreatment(const char* treatment
)
1000 if ( treatment
== NULL
)
1003 if ( strcmp(treatment
, "warning") == 0 )
1005 else if ( strcmp(treatment
, "error") == 0 )
1007 else if ( strcmp(treatment
, "suppress") == 0 )
1013 void Options::setVersionMin(const char* version
)
1015 if ( version
== NULL
)
1016 throw "-macosx_version_min argument missing";
1018 if ( (strncmp(version
, "10.", 3) == 0) && isdigit(version
[3]) ) {
1019 int num
= version
[3] - '0';
1023 fReaderOptions
.fVersionMin
= ObjectFile::ReaderOptions::k10_1
;
1026 fReaderOptions
.fVersionMin
= ObjectFile::ReaderOptions::k10_2
;
1029 fReaderOptions
.fVersionMin
= ObjectFile::ReaderOptions::k10_3
;
1032 fReaderOptions
.fVersionMin
= ObjectFile::ReaderOptions::k10_4
;
1035 fReaderOptions
.fVersionMin
= ObjectFile::ReaderOptions::k10_5
;
1040 fprintf(stderr
, "ld64: unknown option to -macosx_version_min not 10.x");
1044 void Options::setWeakReferenceMismatchTreatment(const char* treatment
)
1046 if ( treatment
== NULL
)
1047 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
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
;
1056 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1059 Options::CommonsMode
Options::parseCommonsTreatment(const char* mode
)
1062 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
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
;
1071 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1074 void Options::addDylibOverride(const char* paths
)
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
);
1085 DylibOverride entry
;
1086 entry
.installName
= target
;
1087 entry
.useInstead
= &colon
[1];
1088 fDylibOverrides
.push_back(entry
);
1091 uint64_t Options::parseAddress(const char* addr
)
1094 uint64_t result
= strtoull(addr
, &endptr
, 16);
1098 uint32_t Options::parseProtection(const char* prot
)
1100 uint32_t result
= 0;
1101 for(const char* p
= prot
; *p
!= '\0'; ++p
) {
1102 switch(tolower(*p
)) {
1104 result
|= VM_PROT_READ
;
1107 result
|= VM_PROT_WRITE
;
1110 result
|= VM_PROT_EXECUTE
;
1115 throwf("unknown -segprot lettter in %s", prot
);
1124 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1127 uint32_t Options::parseVersionNumber(const char* versionString
)
1129 unsigned long x
= 0;
1130 unsigned long y
= 0;
1131 unsigned long z
= 0;
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);
1140 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
1141 throwf("malformed version number: %s", versionString
);
1143 return (x
<< 16) | ( y
<< 8 ) | z
;
1146 static const char* cstringSymbolName(const char* orderFileString
)
1149 asprintf(&result
, "cstring=%s", orderFileString
);
1150 // convert escaped characters
1152 for(const char* s
=result
; *s
!= '\0'; ++s
, ++d
) {
1190 // hexadecimal value of char
1194 while ( isxdigit(*s
) ) {
1199 value
+= ((toupper(*s
)-'A') + 10);
1206 if ( isdigit(*s
) ) {
1207 // octal value of char
1209 while ( isdigit(*s
) ) {
1210 value
= (value
<< 3) + (*s
-'0');
1225 void Options::parseOrderFile(const char* path
, bool cstring
)
1227 // read in whole file
1228 int fd
= ::open(path
, O_RDONLY
, 0);
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);
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
);
1239 p
[stat_buf
.st_size
] = '\n';
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
) {
1251 else if ( !isspace(*s
) || cstring
) {
1257 if ( (*s
== '\n') || (!cstring
&& (*s
== '#')) ) {
1258 bool wasComment
= (*s
== '#');
1260 // removing any trailing spaces
1262 while ( isspace(*last
) ) {
1266 if ( strncmp(symbolStart
, "ppc:", 4) == 0 ) {
1267 if ( fArchitecture
== CPU_TYPE_POWERPC
)
1268 symbolStart
= &symbolStart
[4];
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];
1279 else if ( strncmp(symbolStart
, "i386:", 5) == 0 ) {
1280 if ( fArchitecture
== CPU_TYPE_I386
)
1281 symbolStart
= &symbolStart
[5];
1285 else if ( strncmp(symbolStart
, "x86_64:", 7) == 0 ) {
1286 if ( fArchitecture
== CPU_TYPE_X86_64
)
1287 symbolStart
= &symbolStart
[7];
1291 if ( symbolStart
!= NULL
) {
1292 char* objFileName
= NULL
;
1293 char* colon
= strstr(symbolStart
, ".o:");
1294 if ( colon
!= NULL
) {
1296 objFileName
= symbolStart
;
1297 symbolStart
= &colon
[3];
1299 // trim leading spaces
1300 while ( isspace(*symbolStart
) )
1302 Options::OrderedSymbol pair
;
1304 pair
.symbolName
= cstringSymbolName(symbolStart
);
1306 pair
.symbolName
= symbolStart
;
1307 pair
.objectFileName
= objFileName
;
1308 fOrderedSymbols
.push_back(pair
);
1323 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1326 void Options::parseSectionOrderFile(const char* segment
, const char* section
, const char* path
)
1328 if ( (strcmp(section
, "__cstring") == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1329 parseOrderFile(path
, true);
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");
1335 // ignore section information and append all symbol names to global order file
1336 parseOrderFile(path
, false);
1340 void Options::addSection(const char* segment
, const char* section
, const char* path
)
1342 if ( strlen(segment
) > 16 )
1343 throw "-seccreate segment name max 16 chars";
1344 if ( strlen(section
) > 16 ) {
1345 char* tmp
= strdup(section
);
1347 fprintf(stderr
, "ld64 warning: -seccreate section name (%s) truncated to 16 chars (%s)\n", section
, tmp
);
1351 // read in whole file
1352 int fd
= ::open(path
, O_RDONLY
, 0);
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
);
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
);
1364 // record section to create
1365 ExtraSection info
= { segment
, section
, path
, (uint8_t*)p
, stat_buf
.st_size
};
1366 fExtraSections
.push_back(info
);
1369 void Options::addSectionAlignment(const char* segment
, const char* section
, const char* alignmentStr
)
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";
1376 // argument to -sectalign is a hexadecimal number
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";
1384 fprintf(stderr
, "ld64 warning: zero is not a valid -sectalign\n");
1388 // alignment is power of 2 (e.g. page alignment = 12)
1389 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
1390 if ( (unsigned long)(1 << alignment
) != value
) {
1391 fprintf(stderr
, "ld64 warning: alignment for -sectalign %s %s is not a power of two, using 0x%X\n",
1392 segment
, section
, 1 << alignment
);
1395 SectionAlignment info
= { segment
, section
, alignment
};
1396 fSectionAlignments
.push_back(info
);
1399 void Options::addLibrary(const FileInfo
& info
)
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;
1411 fInputFiles
.push_back(info
);
1414 void Options::warnObsolete(const char* arg
)
1416 if ( emitWarnings() )
1417 fprintf(stderr
, "ld64: warning: option %s is obsolete and being ignored\n", arg
);
1424 // Process all command line arguments.
1426 // The only error checking done here is that each option is valid and if it has arguments
1427 // that they too are valid.
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.
1432 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
1434 void Options::parse(int argc
, const char* argv
[])
1436 // pass one builds search list from -L and -F options
1437 this->buildSearchPaths(argc
, argv
);
1439 // reduce re-allocations
1440 fInputFiles
.reserve(32);
1442 // pass two parse all other options
1443 for(int i
=1; i
< argc
; ++i
) {
1444 const char* arg
= argv
[i
];
1446 if ( arg
[0] == '-' ) {
1448 // Since we don't care about the files passed, just the option names, we do this here.
1450 fprintf (stderr
, "[Logging ld64 options]\t%s\n", arg
);
1452 if ( (arg
[1] == 'L') || (arg
[1] == 'F') ) {
1453 // previously handled by buildSearchPaths()
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");
1462 else if ( strcmp(arg
, "-arch") == 0 ) {
1463 parseArch(argv
[++i
]);
1465 else if ( strcmp(arg
, "-dynamic") == 0 ) {
1468 else if ( strcmp(arg
, "-static") == 0 ) {
1469 if ( fOutputKind
!= kObjectFile
)
1470 fOutputKind
= kStaticExecutable
;
1471 fReaderOptions
.fForStatic
= true;
1473 else if ( strcmp(arg
, "-dylib") == 0 ) {
1474 fOutputKind
= kDynamicLibrary
;
1476 else if ( strcmp(arg
, "-bundle") == 0 ) {
1477 fOutputKind
= kDynamicBundle
;
1479 else if ( strcmp(arg
, "-dylinker") == 0 ) {
1480 fOutputKind
= kDyld
;
1482 else if ( strcmp(arg
, "-execute") == 0 ) {
1483 if ( fOutputKind
!= kStaticExecutable
)
1484 fOutputKind
= kDynamicExecutable
;
1486 else if ( strcmp(arg
, "-r") == 0 ) {
1487 fOutputKind
= kObjectFile
;
1489 else if ( strcmp(arg
, "-o") == 0 ) {
1490 fOutputFile
= argv
[++i
];
1492 else if ( arg
[1] == 'l' ) {
1493 addLibrary(findLibrary(&arg
[2]));
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]);
1499 info
.options
.fWeakImport
= true;
1502 // Avoid lazy binding.
1504 else if ( strcmp(arg
, "-bind_at_load") == 0 ) {
1507 else if ( strcmp(arg
, "-twolevel_namespace") == 0 ) {
1508 fNameSpace
= kTwoLevelNameSpace
;
1510 else if ( strcmp(arg
, "-flat_namespace") == 0 ) {
1511 fNameSpace
= kFlatNameSpace
;
1513 // Also sets a bit to ensure dyld causes everything
1514 // in the namespace to be flat.
1516 else if ( strcmp(arg
, "-force_flat_namespace") == 0 ) {
1517 fNameSpace
= kForceFlatNameSpace
;
1519 // Similar to --whole-archive.
1520 else if ( strcmp(arg
, "-all_load") == 0 ) {
1521 fReaderOptions
.fFullyLoadArchives
= true;
1523 else if ( strcmp(arg
, "-noall_load") == 0) {
1526 // Similar to -all_load
1527 else if ( strcmp(arg
, "-ObjC") == 0 ) {
1528 fReaderOptions
.fLoadAllObjcObjectsFromArchives
= true;
1530 // Library versioning.
1531 else if ( (strcmp(arg
, "-dylib_compatibility_version") == 0)
1532 || (strcmp(arg
, "-compatibility_version") == 0)) {
1533 const char* vers
= argv
[++i
];
1535 throw "-dylib_compatibility_version missing <version>";
1536 fDylibCompatVersion
= parseVersionNumber(vers
);
1538 else if ( (strcmp(arg
, "-dylib_current_version") == 0)
1539 || (strcmp(arg
, "-current_version") == 0)) {
1540 const char* vers
= argv
[++i
];
1542 throw "-dylib_current_version missing <version>";
1543 fDylibCurrentVersion
= parseVersionNumber(vers
);
1545 else if ( strcmp(arg
, "-sectorder") == 0 ) {
1546 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
1547 throw "-sectorder missing <segment> <section> <file-path>";
1548 parseSectionOrderFile(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1551 else if ( strcmp(arg
, "-order_file") == 0 ) {
1552 parseOrderFile(argv
[++i
], false);
1554 else if ( strcmp(arg
, "-order_file_statistics") == 0 ) {
1555 fPrintOrderFileStatistics
= true;
1557 // ??? Deprecate segcreate.
1558 // -sectcreate puts whole files into a section in the output.
1559 else if ( (strcmp(arg
, "-sectcreate") == 0) || (strcmp(arg
, "-segcreate") == 0) ) {
1560 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
1561 throw "-sectcreate missing <segment> <section> <file-path>";
1562 addSection(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1565 // Since we have a full path in binary/library names we need to be able to override it.
1566 else if ( (strcmp(arg
, "-dylib_install_name") == 0)
1567 || (strcmp(arg
, "-dylinker_install_name") == 0)
1568 || (strcmp(arg
, "-install_name") == 0)) {
1569 fDylibInstallName
= argv
[++i
];
1570 if ( fDylibInstallName
== NULL
)
1571 throw "-install_name missing <path>";
1573 // Sets the base address of the output.
1574 else if ( (strcmp(arg
, "-seg1addr") == 0) || (strcmp(arg
, "-image_base") == 0) ) {
1575 const char* address
= argv
[++i
];
1576 if ( address
== NULL
)
1577 throwf("%s missing <address>", arg
);
1578 fBaseAddress
= parseAddress(address
);
1580 else if ( strcmp(arg
, "-e") == 0 ) {
1581 fEntryName
= argv
[++i
];
1583 // Same as -@ from the FSF linker.
1584 else if ( strcmp(arg
, "-filelist") == 0 ) {
1585 const char* path
= argv
[++i
];
1586 if ( (path
== NULL
) || (path
[0] == '-') )
1587 throw "-filelist missing <path>";
1590 else if ( strcmp(arg
, "-keep_private_externs") == 0 ) {
1591 fKeepPrivateExterns
= true;
1593 else if ( strcmp(arg
, "-final_output") == 0 ) {
1594 fFinalName
= argv
[++i
];
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.
1598 else if ( (strcmp(arg
, "-interposable") == 0) || (strcmp(arg
, "-multi_module") == 0)) {
1599 fInterposable
= true;
1601 // Default for -interposable/-multi_module/-single_module.
1602 else if ( strcmp(arg
, "-single_module") == 0 ) {
1603 fInterposable
= false;
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
);
1611 else if ( strcmp(arg
, "-unexported_symbols_list") == 0 ) {
1612 if ( fExportMode
== kExportSome
)
1613 throw "can't use -unexported_symbols_list and -exported_symbols_list";
1614 fExportMode
= kDontExportSome
;
1615 loadExportFile(argv
[++i
], "-unexported_symbols_list", fDontExportSymbols
);
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
]);
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
]);
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
);
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
);
1642 else if ( strcmp(arg
, "-no_arch_warnings") == 0 ) {
1643 fIgnoreOtherArchFiles
= true;
1645 else if ( strcmp(arg
, "-force_cpusubtype_ALL") == 0 ) {
1646 fForceSubtypeAll
= true;
1648 // Similar to -weak-l but uses the absolute path name to the library.
1649 else if ( strcmp(arg
, "-weak_library") == 0 ) {
1650 FileInfo info
= findFile(argv
[++i
]);
1651 info
.options
.fWeakImport
= true;
1654 else if ( strcmp(arg
, "-framework") == 0 ) {
1655 addLibrary(findFramework(argv
[++i
]));
1657 else if ( strcmp(arg
, "-weak_framework") == 0 ) {
1658 FileInfo info
= findFramework(argv
[++i
]);
1659 info
.options
.fWeakImport
= true;
1662 else if ( strcmp(arg
, "-search_paths_first") == 0 ) {
1663 // previously handled by buildSearchPaths()
1665 else if ( strcmp(arg
, "-undefined") == 0 ) {
1666 setUndefinedTreatment(argv
[++i
]);
1668 // Debugging output flag.
1669 else if ( strcmp(arg
, "-arch_multiple") == 0 ) {
1670 fMessagesPrefixedWithArchitecture
= true;
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
1676 else if ( strcmp(arg
, "-read_only_relocs") == 0 ) {
1677 Treatment temp
= parseTreatment(argv
[++i
]);
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 ]";
1684 else if ( strcmp(arg
, "-sect_diff_relocs") == 0 ) {
1688 // Warn, error or make strong a mismatch between weak
1689 // and non-weak references.
1690 else if ( strcmp(arg
, "-weak_reference_mismatches") == 0 ) {
1691 setWeakReferenceMismatchTreatment(argv
[++i
]);
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.
1697 else if ( strcmp(arg
, "-prebind") == 0 ) {
1700 else if ( strcmp(arg
, "-noprebind") == 0 ) {
1704 else if ( strcmp(arg
, "-prebind_allow_overlap") == 0 ) {
1707 else if ( strcmp(arg
, "-prebind_all_twolevel_modules") == 0 ) {
1710 else if ( strcmp(arg
, "-noprebind_all_twolevel_modules") == 0 ) {
1713 else if ( strcmp(arg
, "-nofixprebinding") == 0 ) {
1716 // This should probably be deprecated when we respect -L and -F
1717 // when searching for libraries.
1718 else if ( strcmp(arg
, "-dylib_file") == 0 ) {
1719 addDylibOverride(argv
[++i
]);
1721 // What to expand @executable_path to if found in dependent dylibs
1722 else if ( strcmp(arg
, "-executable_path") == 0 ) {
1723 fExecutablePath
= argv
[++i
];
1724 if ( (fExecutablePath
== NULL
) || (fExecutablePath
[0] == '-') )
1725 throw "-executable_path missing <path>";
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
;
1738 // Aligns all segments to the power of 2 boundary specified.
1739 else if ( strcmp(arg
, "-segalign") == 0 ) {
1743 // Puts a specified segment at a particular address that must
1744 // be a multiple of the segment alignment.
1745 else if ( strcmp(arg
, "-segaddr") == 0 ) {
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
);
1756 // ??? Deprecate when we deprecate split-seg.
1757 else if ( strcmp(arg
, "-segs_read_only_addr") == 0 ) {
1758 fBaseAddress
= parseAddress(argv
[++i
]);
1760 // ??? Deprecate when we deprecate split-seg.
1761 else if ( strcmp(arg
, "-segs_read_write_addr") == 0 ) {
1762 fBaseWritableAddress
= parseAddress(argv
[++i
]);
1765 // ??? Deprecate when we get rid of basing at build time.
1766 else if ( strcmp(arg
, "-seg_addr_table") == 0 ) {
1767 const char* name
= argv
[++i
];
1769 throw "-seg_addr_table missing argument";
1770 fSegAddrTablePath
= name
;
1772 else if ( strcmp(arg
, "-seg_addr_table_filename") == 0 ) {
1776 else if ( strcmp(arg
, "-segprot") == 0 ) {
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
);
1785 else if ( strcmp(arg
, "-pagezero_size") == 0 ) {
1786 const char* size
= argv
[++i
];
1788 throw "-pagezero_size missing <size>";
1789 fZeroPageSize
= parseAddress(size
);
1790 uint64_t temp
= fZeroPageSize
& (-4096); // page align
1791 if ( (fZeroPageSize
!= temp
) && emitWarnings() )
1792 fprintf(stderr
, "ld64: warning, -pagezero_size not page aligned, rounding down\n");
1793 fZeroPageSize
= temp
;
1795 else if ( strcmp(arg
, "-stack_addr") == 0 ) {
1796 const char* address
= argv
[++i
];
1797 if ( address
== NULL
)
1798 throw "-stack_addr missing <address>";
1799 fStackAddr
= parseAddress(address
);
1801 else if ( strcmp(arg
, "-stack_size") == 0 ) {
1802 const char* size
= argv
[++i
];
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");
1810 else if ( strcmp(arg
, "-allow_stack_execute") == 0 ) {
1811 fExecutableStack
= true;
1813 else if ( strcmp(arg
, "-sectalign") == 0 ) {
1814 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
1815 throw "-sectalign missing <segment> <section> <file-path>";
1816 addSectionAlignment(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1819 else if ( strcmp(arg
, "-sectorder_detail") == 0 ) {
1822 else if ( strcmp(arg
, "-sectobjectsymbols") == 0 ) {
1826 else if ( strcmp(arg
, "-bundle_loader") == 0 ) {
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
);
1834 else if ( strcmp(arg
, "-private_bundle") == 0 ) {
1837 else if ( strcmp(arg
, "-twolevel_namespace_hints") == 0 ) {
1840 // Use this flag to set default behavior for deployement targets.
1841 else if ( strcmp(arg
, "-macosx_version_min") == 0 ) {
1842 setVersionMin(argv
[++i
]);
1844 else if ( strcmp(arg
, "-multiply_defined") == 0 ) {
1845 //warnObsolete(arg);
1848 else if ( strcmp(arg
, "-multiply_defined_unused") == 0 ) {
1852 else if ( strcmp(arg
, "-nomultidefs") == 0 ) {
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 ) {
1861 // Same output as -y, but output <arg> number of undefined symbols only.
1862 else if ( strcmp(arg
, "-Y") == 0 ) {
1863 //warnObsolete(arg);
1866 // This option affects all objects linked into the final result.
1867 else if ( strcmp(arg
, "-m") == 0 ) {
1870 else if ( (strcmp(arg
, "-why_load") == 0) || (strcmp(arg
, "-whyload") == 0) ) {
1871 fReaderOptions
.fWhyLoad
= true;
1873 else if ( strcmp(arg
, "-why_live") == 0 ) {
1874 const char* name
= argv
[++i
];
1876 throw "-why_live missing symbol name argument";
1877 fWhyLive
.insert(name
);
1879 else if ( strcmp(arg
, "-u") == 0 ) {
1880 const char* name
= argv
[++i
];
1882 throw "-u missing argument";
1883 fInitialUndefines
.push_back(name
);
1885 else if ( strcmp(arg
, "-U") == 0 ) {
1886 const char* name
= argv
[++i
];
1888 throw "-U missing argument";
1889 fAllowedUndefined
.insert(name
);
1891 else if ( strcmp(arg
, "-s") == 0 ) {
1893 fLocalSymbolHandling
= kLocalSymbolsNone
;
1894 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
1896 else if ( strcmp(arg
, "-x") == 0 ) {
1897 fLocalSymbolHandling
= kLocalSymbolsNone
;
1899 else if ( strcmp(arg
, "-S") == 0 ) {
1900 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
1902 else if ( strcmp(arg
, "-X") == 0 ) {
1905 else if ( strcmp(arg
, "-Si") == 0 ) {
1907 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoFull
;
1909 else if ( strcmp(arg
, "-b") == 0 ) {
1912 else if ( strcmp(arg
, "-Sn") == 0 ) {
1914 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoFull
;
1916 else if ( strcmp(arg
, "-Sp") == 0 ) {
1919 else if ( strcmp(arg
, "-dead_strip") == 0 ) {
1920 fDeadStrip
= kDeadStripOnPlusUnusedInits
;
1922 else if ( strcmp(arg
, "-no_dead_strip_inits_and_terms") == 0 ) {
1923 fDeadStrip
= kDeadStripOn
;
1925 else if ( strcmp(arg
, "-w") == 0 ) {
1926 // previously handled by buildSearchPaths()
1928 else if ( strcmp(arg
, "-arch_errors_fatal") == 0 ) {
1931 else if ( strcmp(arg
, "-M") == 0 ) {
1934 else if ( strcmp(arg
, "-headerpad") == 0 ) {
1935 const char* size
= argv
[++i
];
1937 throw "-headerpad missing argument";
1938 fMinimumHeaderPad
= parseAddress(size
);
1940 else if ( strcmp(arg
, "-headerpad_max_install_names") == 0 ) {
1941 fMaxMinimumHeaderPad
= true;
1943 else if ( strcmp(arg
, "-t") == 0 ) {
1944 fReaderOptions
.fLogAllFiles
= true;
1946 else if ( strcmp(arg
, "-whatsloaded") == 0 ) {
1947 fReaderOptions
.fLogObjectFiles
= true;
1949 else if ( strcmp(arg
, "-A") == 0 ) {
1953 else if ( strcmp(arg
, "-umbrella") == 0 ) {
1954 const char* name
= argv
[++i
];
1956 throw "-umbrella missing argument";
1957 fUmbrellaName
= name
;
1959 else if ( strcmp(arg
, "-allowable_client") == 0 ) {
1960 const char* name
= argv
[++i
];
1963 throw "-allowable_client missing argument";
1965 fAllowableClients
.push_back(name
);
1967 else if ( strcmp(arg
, "-client_name") == 0 ) {
1968 const char* name
= argv
[++i
];
1971 throw "-client_name missing argument";
1975 else if ( strcmp(arg
, "-sub_umbrella") == 0 ) {
1976 const char* name
= argv
[++i
];
1978 throw "-sub_umbrella missing argument";
1979 fSubUmbellas
.push_back(name
);
1981 else if ( strcmp(arg
, "-sub_library") == 0 ) {
1982 const char* name
= argv
[++i
];
1984 throw "-sub_library missing argument";
1985 fSubLibraries
.push_back(name
);
1987 else if ( strcmp(arg
, "-init") == 0 ) {
1988 const char* name
= argv
[++i
];
1990 throw "-init missing argument";
1991 fInitFunctionName
= name
;
1993 else if ( strcmp(arg
, "-dot") == 0 ) {
1994 const char* name
= argv
[++i
];
1996 throw "-dot missing argument";
1997 fDotOutputFile
= name
;
1999 else if ( strcmp(arg
, "-warn_commons") == 0 ) {
2000 fWarnCommons
= true;
2002 else if ( strcmp(arg
, "-commons") == 0 ) {
2003 fCommonsMode
= parseCommonsTreatment(argv
[++i
]);
2005 else if ( strcmp(arg
, "-keep_relocs") == 0 ) {
2006 fKeepRelocations
= true;
2008 else if ( strcmp(arg
, "-warn_stabs") == 0 ) {
2011 else if ( strcmp(arg
, "-pause") == 0 ) {
2014 else if ( strcmp(arg
, "-print_statistics") == 0 ) {
2017 else if ( strcmp(arg
, "-d") == 0 ) {
2018 fReaderOptions
.fMakeTentativeDefinitionsReal
= true;
2020 else if ( strcmp(arg
, "-v") == 0 ) {
2021 // previously handled by buildSearchPaths()
2023 else if ( strcmp(arg
, "-Z") == 0 ) {
2024 // previously handled by buildSearchPaths()
2026 else if ( strcmp(arg
, "-syslibroot") == 0 ) {
2028 // previously handled by buildSearchPaths()
2030 else if ( strcmp(arg
, "-no_uuid") == 0 ) {
2031 fUUIDMode
= kUUIDNone
;
2033 else if ( strcmp(arg
, "-random_uuid") == 0 ) {
2034 fUUIDMode
= kUUIDRandom
;
2036 else if ( strcmp(arg
, "-dtrace") == 0 ) {
2037 const char* name
= argv
[++i
];
2039 throw "-dtrace missing argument";
2040 fDtraceScriptName
= name
;
2042 else if ( strcmp(arg
, "-root_safe") == 0 ) {
2043 fReaderOptions
.fRootSafe
= true;
2045 else if ( strcmp(arg
, "-setuid_safe") == 0 ) {
2046 fReaderOptions
.fSetuidSafe
= true;
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
);
2058 else if ( strcmp(arg
, "-alias_list") == 0 ) {
2059 parseAliasFile(argv
[++i
]);
2061 // put this last so that it does not interfer with other options starting with 'i'
2062 else if ( strncmp(arg
, "-i", 2) == 0 ) {
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];
2071 fReaderOptions
.fAliases
.push_back(pair
);
2073 else if ( strcmp(arg
, "-save-temps") == 0 ) {
2074 fSaveTempFiles
= true;
2076 else if ( strcmp(arg
, "-rpath") == 0 ) {
2077 const char* path
= argv
[++i
];
2079 throw "missing argument to -rpath";
2080 fRPaths
.push_back(path
);
2082 else if ( strcmp(arg
, "-read_only_stubs") == 0 ) {
2083 fReadOnlyx86Stubs
= true;
2085 else if ( strcmp(arg
, "-map") == 0 ) {
2086 fMapPath
= argv
[++i
];
2087 if ( fMapPath
== NULL
)
2088 throw "missing argument to -map";
2090 else if ( strcmp(arg
, "-pie") == 0 ) {
2091 fPositionIndependentExecutable
= true;
2093 else if ( strncmp(arg
, "-reexport-l", 11) == 0 ) {
2094 FileInfo info
= findLibrary(&arg
[11]);
2095 info
.options
.fReExport
= true;
2098 else if ( strcmp(arg
, "-reexport_library") == 0 ) {
2099 FileInfo info
= findFile(argv
[++i
]);
2100 info
.options
.fReExport
= true;
2103 else if ( strcmp(arg
, "-reexport_framework") == 0 ) {
2104 FileInfo info
= findFramework(argv
[++i
]);
2105 info
.options
.fReExport
= true;
2108 else if ( strcmp(arg
, "-dead_strip_dylibs") == 0 ) {
2109 fDeadStripDylibs
= true;
2111 else if ( strcmp(arg
, "-new_linker") == 0 ) {
2115 throwf("unknown option: %s", arg
);
2119 FileInfo info
= findFile(arg
);
2120 if ( strcmp(&info
.path
[strlen(info
.path
)-2], ".a") == 0 )
2123 fInputFiles
.push_back(info
);
2131 // -syslibroot <path> is used for SDK support.
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.
2139 void Options::buildSearchPaths(int argc
, const char* argv
[])
2141 bool addStandardLibraryDirectories
= true;
2142 std::vector
<const char*> libraryPaths
;
2143 std::vector
<const char*> frameworkPaths
;
2144 libraryPaths
.reserve(10);
2145 frameworkPaths
.reserve(10);
2146 // scan through argv looking for -L, -F, -Z, and -syslibroot options
2147 for(int i
=0; i
< argc
; ++i
) {
2148 if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'L') )
2149 libraryPaths
.push_back(&argv
[i
][2]);
2150 else if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'F') )
2151 frameworkPaths
.push_back(&argv
[i
][2]);
2152 else if ( strcmp(argv
[i
], "-Z") == 0 )
2153 addStandardLibraryDirectories
= false;
2154 else if ( strcmp(argv
[i
], "-v") == 0 ) {
2156 extern const char ldVersionString
[];
2157 fprintf(stderr
, "%s", ldVersionString
);
2158 // if only -v specified, exit cleanly
2162 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
2163 const char* path
= argv
[++i
];
2165 throw "-syslibroot missing argument";
2166 fSDKPaths
.push_back(path
);
2168 else if ( strcmp(argv
[i
], "-search_paths_first") == 0 ) {
2169 // ??? Deprecate when we get -Bstatic/-Bdynamic.
2170 fLibrarySearchMode
= kSearchDylibAndArchiveInEachDir
;
2172 else if ( strcmp(argv
[i
], "-w") == 0 ) {
2173 fSuppressWarnings
= true;
2176 if ( addStandardLibraryDirectories
) {
2177 libraryPaths
.push_back("/usr/lib");
2178 libraryPaths
.push_back("/usr/local/lib");
2180 frameworkPaths
.push_back("/Library/Frameworks/");
2181 frameworkPaths
.push_back("/System/Library/Frameworks/");
2182 frameworkPaths
.push_back("/Network/Library/Frameworks/");
2185 // now merge sdk and library paths to make real search paths
2186 fLibrarySearchPaths
.reserve(libraryPaths
.size()*(fSDKPaths
.size()+1));
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
)
2194 libDir
= strdup(betterLibDir
);
2196 const int libDirLen
= strlen(libDir
);
2197 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
2198 // ??? Should be using string here.
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
));
2214 fLibrarySearchPaths
.push_back(libDir
);
2217 // now merge sdk and framework paths to make real search paths
2218 fFrameworkSearchPaths
.reserve(frameworkPaths
.size()*(fSDKPaths
.size()+1));
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
)
2226 frameworkDir
= strdup(betterFrameworkDir
);
2228 const int frameworkDirLen
= strlen(frameworkDir
);
2229 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
2230 // ??? Should be using string here
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
));
2246 fFrameworkSearchPaths
.push_back(frameworkDir
);
2250 fprintf(stderr
,"Library search paths:\n");
2251 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
2252 it
!= fLibrarySearchPaths
.end();
2254 fprintf(stderr
,"\t%s\n", *it
);
2255 fprintf(stderr
,"Framework search paths:\n");
2256 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
2257 it
!= fFrameworkSearchPaths
.end();
2259 fprintf(stderr
,"\t%s\n", *it
);
2263 // this is run before the command line is parsed
2264 void Options::parsePreCommandLineEnvironmentSettings()
2266 if ((getenv("LD_TRACE_ARCHIVES") != NULL
)
2267 || (getenv("RC_TRACE_ARCHIVES") != NULL
))
2268 fReaderOptions
.fTraceArchives
= true;
2270 if ((getenv("LD_TRACE_DYLIBS") != NULL
)
2271 || (getenv("RC_TRACE_DYLIBS") != NULL
)) {
2272 fReaderOptions
.fTraceDylibs
= true;
2273 fReaderOptions
.fTraceIndirectDylibs
= true;
2276 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL
) {
2277 fTraceDylibSearching
= true;
2280 if (getenv("LD_PRINT_OPTIONS") != NULL
)
2281 fPrintOptions
= true;
2283 if (fReaderOptions
.fTraceDylibs
|| fReaderOptions
.fTraceArchives
)
2284 fReaderOptions
.fTraceOutputFile
= getenv("LD_TRACE_FILE");
2286 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL
)
2287 fPrintOrderFileStatistics
= true;
2290 // this is run after the command line is parsed
2291 void Options::parsePostCommandLineEnvironmentSettings()
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
;
2298 // allow build system to set default seg_addr_table
2299 if ( fSegAddrTablePath
== NULL
)
2300 fSegAddrTablePath
= getenv("LD_SEG_ADDR_TABLE");
2302 // allow build system to turn on prebinding
2304 fPrebind
= ( getenv("LD_PREBIND") != NULL
);
2308 void Options::reconfigureDefaults()
2310 // sync reader options
2311 switch ( fOutputKind
) {
2312 case Options::kObjectFile
:
2313 fReaderOptions
.fForFinalLinkedImage
= false;
2315 case Options::kDyld
:
2316 fReaderOptions
.fForDyld
= true;
2317 fReaderOptions
.fForFinalLinkedImage
= true;
2319 case Options::kDynamicLibrary
:
2320 case Options::kDynamicBundle
:
2321 fReaderOptions
.fForFinalLinkedImage
= true;
2323 case Options::kDynamicExecutable
:
2324 case Options::kStaticExecutable
:
2325 fReaderOptions
.fLinkingMainExecutable
= true;
2326 fReaderOptions
.fForFinalLinkedImage
= true;
2330 // set default min OS version
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
2341 // adjust min based on architecture
2342 switch ( fArchitecture
) {
2344 if ( fReaderOptions
.fVersionMin
< ObjectFile::ReaderOptions::k10_4
) {
2345 //fprintf(stderr, "ld64 warning: -macosx_version_min should be 10.4 or later for i386\n");
2346 fReaderOptions
.fVersionMin
= ObjectFile::ReaderOptions::k10_4
;
2349 case CPU_TYPE_POWERPC64
:
2350 if ( fReaderOptions
.fVersionMin
< ObjectFile::ReaderOptions::k10_4
) {
2351 //fprintf(stderr, "ld64 warning: -macosx_version_min should be 10.4 or later for ppc64\n");
2352 fReaderOptions
.fVersionMin
= ObjectFile::ReaderOptions::k10_4
;
2355 case CPU_TYPE_X86_64
:
2356 if ( fReaderOptions
.fVersionMin
< ObjectFile::ReaderOptions::k10_4
) {
2357 //fprintf(stderr, "ld64 warning: -macosx_version_min should be 10.4 or later for x86_64\n");
2358 fReaderOptions
.fVersionMin
= ObjectFile::ReaderOptions::k10_4
;
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;
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
;
2373 // check for base address specified externally
2374 if ( (fSegAddrTablePath
!= NULL
) && (fOutputKind
== Options::kDynamicLibrary
) )
2375 parseSegAddrTable(fSegAddrTablePath
, this->installPath());
2378 // split segs only allowed for dylibs
2380 if ( fOutputKind
!= Options::kDynamicLibrary
)
2382 // split seg only supported for ppc and i386
2383 switch ( fArchitecture
) {
2384 case CPU_TYPE_POWERPC
:
2390 fBaseWritableAddress
= 0;
2394 // disable prebinding depending on arch and min OS version
2396 switch ( fArchitecture
) {
2397 case CPU_TYPE_POWERPC
:
2399 if ( fReaderOptions
.fVersionMin
>= ObjectFile::ReaderOptions::k10_4
) {
2400 // only split seg dylibs are prebound
2401 if ( (fOutputKind
!= Options::kDynamicLibrary
) || ! fSplitSegs
)
2405 case CPU_TYPE_POWERPC64
:
2406 case CPU_TYPE_X86_64
:
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;
2426 void Options::checkIllegalOptionCombinations()
2428 // check -undefined setting
2429 switch ( fUndefinedTreatment
) {
2430 case kUndefinedError
:
2431 case kUndefinedDynamicLookup
:
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";
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
;
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;
2457 if ( ! found
&& emitWarnings() )
2458 fprintf(stderr
, "ld64 warning: -sub_umbrella %s does not match a supplied dylib\n", subUmbrella
);
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
;
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;
2470 const char* dot
= strchr(&lastSlash
[1], '.');
2472 dot
= &lastSlash
[strlen(lastSlash
)];
2473 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
2474 info
.options
.fReExport
= true;
2479 if ( ! found
&& emitWarnings() )
2480 fprintf(stderr
, "ld64 warning: -sub_library %s does not match a supplied dylib\n", subLibrary
);
2483 // sync reader options
2484 if ( fNameSpace
!= kTwoLevelNameSpace
)
2485 fReaderOptions
.fFlatNamespace
= true;
2487 // check -stack_addr
2488 if ( fStackAddr
!= 0 ) {
2489 switch (fArchitecture
) {
2491 case CPU_TYPE_POWERPC
:
2492 if ( fStackAddr
> 0xFFFFFFFF )
2493 throw "-stack_addr must be < 4G for 32-bit processes";
2495 case CPU_TYPE_POWERPC64
:
2496 case CPU_TYPE_X86_64
:
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";
2505 // check -stack_size
2506 if ( fStackSize
!= 0 ) {
2507 switch (fArchitecture
) {
2509 case CPU_TYPE_POWERPC
:
2510 if ( fStackSize
> 0xFFFFFFFF )
2511 throw "-stack_size must be < 4G for 32-bit processes";
2512 if ( fStackAddr
== 0 ) {
2513 fStackAddr
= 0xC0000000;
2515 if ( (fStackAddr
> 0xB0000000) && ((fStackAddr
-fStackSize
) < 0xB0000000) && emitWarnings() )
2516 fprintf(stderr
, "ld64 warning: custom stack placement overlaps and will disable shared region\n");
2518 case CPU_TYPE_POWERPC64
:
2519 case CPU_TYPE_X86_64
:
2520 if ( fStackAddr
== 0 ) {
2521 fStackAddr
= 0x00007FFF5C000000LL
;
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
:
2530 // custom stack size only legal when building main executable
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";
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
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";
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
:
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";
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";
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";
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";
2581 // check -d can only be used with -r
2582 if ( fReaderOptions
.fMakeTentativeDefinitionsReal
&& (fOutputKind
!= Options::kObjectFile
) )
2583 throw "-d can only be used with -r";
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";
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";
2593 // make sure all required exported symbols exist
2594 std::vector
<const char*> impliedExports
;
2595 for (NameSet::iterator it
=fExportSymbols
.regularBegin(); it
!= fExportSymbols
.regularEnd(); it
++) {
2596 const char* name
= *it
;
2597 // never export .eh symbols
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
);
2602 fInitialUndefines
.push_back(name
);
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
:
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
);
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
);
2623 // make sure that -init symbol exist
2624 if ( fInitFunctionName
!= NULL
)
2625 fInitialUndefines
.push_back(fInitFunctionName
);
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
);
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
);
2642 // a custom segment address of zero will disable the use of a zero page
2643 if ( it
->address
== 0 )
2648 if ( fZeroPageSize
== ULLONG_MAX
) {
2649 // zero page size not specified on command line, set default
2650 switch (fArchitecture
) {
2652 case CPU_TYPE_POWERPC
:
2653 // first 4KB for 32-bit architectures
2654 fZeroPageSize
= 0x1000;
2656 case CPU_TYPE_POWERPC64
:
2657 // first 4GB for ppc64 on 10.5
2658 if ( fReaderOptions
.fVersionMin
>= ObjectFile::ReaderOptions::k10_5
)
2659 fZeroPageSize
= 0x100000000ULL
;
2661 fZeroPageSize
= 0x1000; // 10.4 dyld may not be able to handle >4GB zero page
2663 case CPU_TYPE_X86_64
:
2664 // first 4GB for x86_64 on all OS's
2665 fZeroPageSize
= 0x100000000ULL
;
2668 // if -arch not used, default to 4K zero-page
2669 fZeroPageSize
= 0x1000;
2673 switch ( fOutputKind
) {
2674 case Options::kDynamicExecutable
:
2675 case Options::kStaticExecutable
:
2676 // -pagezero_size size only legal when building main executable
2678 case Options::kDynamicLibrary
:
2679 case Options::kDynamicBundle
:
2680 case Options::kObjectFile
:
2681 case Options::kDyld
:
2682 if ( fZeroPageSize
!= 0 )
2683 throw "-pagezero_size option can only be used when linking a main executable";
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";
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
:
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";
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";
2718 void Options::checkForClassic(int argc
, const char* argv
[])
2721 bool archFound
= false;
2722 bool staticFound
= false;
2723 bool dtraceFound
= false;
2724 bool rFound
= false;
2725 bool creatingMachKernel
= false;
2726 bool newLinker
= false;
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
]);
2735 else if ( strcmp(arg
, "-static") == 0 ) {
2738 else if ( strcmp(arg
, "-dtrace") == 0 ) {
2741 else if ( strcmp(arg
, "-r") == 0 ) {
2744 else if ( strcmp(arg
, "-new_linker") == 0 ) {
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
);
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;
2761 // -dtrace only supported by new linker
2766 switch ( fArchitecture
) {
2767 case CPU_TYPE_POWERPC
:
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
);
2779 // work around for VSPTool
2781 this->gotoClassicLinker(argc
, argv
);
2786 void Options::gotoClassicLinker(int argc
, const char* argv
[])
2788 argv
[0] = "ld_classic";
2789 execvp(argv
[0], (char**)argv
);
2790 fprintf(stderr
, "can't exec ld_classic\n");