1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2005-2008 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>
29 #include <mach-o/dyld.h>
33 #include "configure.h"
35 #include "Architectures.hpp"
36 #include "MachOFileAbstraction.hpp"
38 extern void printLTOVersion(Options
&opts
);
40 // magic to place command line in crash reports
41 extern "C" char* __crashreporter_info__
;
42 static char crashreporterBuffer
[1000];
43 char* __crashreporter_info__
= crashreporterBuffer
;
45 static bool sEmitWarnings
= true;
46 static const char* sWarningsSideFilePath
= NULL
;
47 static FILE* sWarningsSideFile
= NULL
;
49 void warning(const char* format
, ...)
51 if ( sEmitWarnings
) {
53 if ( sWarningsSideFilePath
!= NULL
) {
54 if ( sWarningsSideFile
== NULL
)
55 sWarningsSideFile
= fopen(sWarningsSideFilePath
, "a");
57 va_start(list
, format
);
58 fprintf(stderr
, "ld: warning: ");
59 vfprintf(stderr
, format
, list
);
60 fprintf(stderr
, "\n");
61 if ( sWarningsSideFile
!= NULL
) {
62 fprintf(sWarningsSideFile
, "ld: warning: ");
63 vfprintf(sWarningsSideFile
, format
, list
);
64 fprintf(sWarningsSideFile
, "\n");
65 fflush(sWarningsSideFile
);
71 void throwf(const char* format
, ...)
75 va_start(list
, format
);
76 vasprintf(&p
, format
, list
);
83 Options::Options(int argc
, const char* argv
[])
84 : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0), fOutputKind(kDynamicExecutable
),
85 fHasPreferredSubType(false), fPrebind(false), fBindAtLoad(false), fKeepPrivateExterns(false),
86 fNeedsModuleTable(false), fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false),
87 fInterposeMode(kInterposeNone
), fDeadStrip(kDeadStripOff
), fNameSpace(kTwoLevelNameSpace
),
88 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL
), fFinalName(NULL
), fEntryName("start"), fBaseAddress(0),
89 fBaseWritableAddress(0), fSplitSegs(false),
90 fExportMode(kExportDefault
), fLibrarySearchMode(kSearchAllDirsForDylibsThenAllDirsForArchives
),
91 fUndefinedTreatment(kUndefinedError
), fMessagesPrefixedWithArchitecture(false),
92 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak
),
94 fUmbrellaName(NULL
), fInitFunctionName(NULL
), fDotOutputFile(NULL
), fExecutablePath(NULL
),
95 fBundleLoader(NULL
), fDtraceScriptName(NULL
), fSegAddrTablePath(NULL
), fMapPath(NULL
),
96 fZeroPageSize(ULLONG_MAX
), fStackSize(0), fStackAddr(0), fExecutableStack(false),
97 fMinimumHeaderPad(32), fSegmentAlignment(4096),
98 fCommonsMode(kCommonsIgnoreDylibs
), fUUIDMode(kUUIDContent
), fLocalSymbolHandling(kLocalSymbolsAll
), fWarnCommons(false),
99 fVerbose(false), fKeepRelocations(false), fWarnStabs(false),
100 fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
101 fSharedRegionEligible(false), fPrintOrderFileStatistics(false),
102 fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
103 fDeadStripDylibs(false), fAllowTextRelocs(false), fWarnTextRelocs(false),
104 fUsingLazyDylibLinking(false), fEncryptable(true),
105 fOrderData(true), fMarkDeadStrippableDylib(false),
106 fMakeClassicDyldInfo(true), fMakeCompressedDyldInfo(true), fAllowCpuSubtypeMismatches(false),
107 fUseSimplifiedDylibReExports(false), fSaveTempFiles(false)
109 this->checkForClassic(argc
, argv
);
110 this->parsePreCommandLineEnvironmentSettings();
111 this->parse(argc
, argv
);
112 this->parsePostCommandLineEnvironmentSettings();
113 this->reconfigureDefaults();
114 this->checkIllegalOptionCombinations();
121 const ObjectFile::ReaderOptions
& Options::readerOptions()
123 return fReaderOptions
;
127 const char* Options::getOutputFilePath()
132 std::vector
<Options::FileInfo
>& Options::getInputFiles()
137 Options::OutputKind
Options::outputKind()
142 bool Options::bindAtLoad()
147 bool Options::prebind()
152 bool Options::fullyLoadArchives()
154 return fReaderOptions
.fFullyLoadArchives
;
157 Options::NameSpace
Options::nameSpace()
162 const char* Options::installPath()
164 if ( fDylibInstallName
!= NULL
)
165 return fDylibInstallName
;
166 else if ( fFinalName
!= NULL
)
172 uint32_t Options::currentVersion()
174 return fDylibCurrentVersion
;
177 uint32_t Options::compatibilityVersion()
179 return fDylibCompatVersion
;
182 const char* Options::entryName()
187 uint64_t Options::baseAddress()
192 bool Options::keepPrivateExterns()
194 return fKeepPrivateExterns
;
197 bool Options::interposable(const char* name
)
199 switch ( fInterposeMode
) {
202 case kInterposeAllExternal
:
205 return fInterposeList
.contains(name
);
207 throw "internal error";
210 bool Options::needsModuleTable()
212 return fNeedsModuleTable
;
215 bool Options::ignoreOtherArchInputFiles()
217 return fIgnoreOtherArchFiles
;
220 bool Options::forceCpuSubtypeAll()
222 return fForceSubtypeAll
;
225 bool Options::traceDylibs()
227 return fReaderOptions
.fTraceDylibs
;
230 bool Options::traceArchives()
232 return fReaderOptions
.fTraceArchives
;
235 Options::UndefinedTreatment
Options::undefinedTreatment()
237 return fUndefinedTreatment
;
240 Options::WeakReferenceMismatchTreatment
Options::weakReferenceMismatchTreatment()
242 return fWeakReferenceMismatchTreatment
;
245 const char* Options::umbrellaName()
247 return fUmbrellaName
;
250 std::vector
<const char*>& Options::allowableClients()
252 return fAllowableClients
;
255 const char* Options::clientName()
260 uint64_t Options::zeroPageSize()
262 return fZeroPageSize
;
265 bool Options::hasCustomStack()
267 return (fStackSize
!= 0);
270 uint64_t Options::customStackSize()
275 uint64_t Options::customStackAddr()
280 bool Options::hasExecutableStack()
282 return fExecutableStack
;
285 std::vector
<const char*>& Options::initialUndefines()
287 return fInitialUndefines
;
290 bool Options::printWhyLive(const char* symbolName
)
292 return ( fWhyLive
.find(symbolName
) != fWhyLive
.end() );
296 const char* Options::initFunctionName()
298 return fInitFunctionName
;
301 const char* Options::dotOutputFile()
303 return fDotOutputFile
;
306 bool Options::hasExportRestrictList()
308 return (fExportMode
!= kExportDefault
);
311 bool Options::hasExportMaskList()
313 return (fExportMode
== kExportSome
);
317 bool Options::hasWildCardExportRestrictList()
319 // has -exported_symbols_list which contains some wildcards
320 return ((fExportMode
== kExportSome
) && fExportSymbols
.hasWildCards());
324 bool Options::allGlobalsAreDeadStripRoots()
326 // -exported_symbols_list means globals are not exported by default
327 if ( fExportMode
== kExportSome
)
330 switch ( fOutputKind
) {
331 case Options::kDynamicExecutable
:
332 case Options::kStaticExecutable
:
333 case Options::kPreload
:
334 // by default unused globals in a main executable are stripped
336 case Options::kDynamicLibrary
:
337 case Options::kDynamicBundle
:
338 case Options::kObjectFile
:
340 case Options::kKextBundle
:
346 uint32_t Options::minimumHeaderPad()
348 return fMinimumHeaderPad
;
351 std::vector
<Options::ExtraSection
>& Options::extraSections()
353 return fExtraSections
;
356 std::vector
<Options::SectionAlignment
>& Options::sectionAlignments()
358 return fSectionAlignments
;
361 Options::CommonsMode
Options::commonsMode()
366 bool Options::warnCommons()
371 bool Options::keepRelocations()
373 return fKeepRelocations
;
376 bool Options::warnStabs()
381 const char* Options::executablePath()
383 return fExecutablePath
;
386 Options::DeadStripMode
Options::deadStrip()
391 bool Options::hasExportedSymbolOrder()
393 return (fExportSymbolsOrder
.size() > 0);
396 bool Options::exportedSymbolOrder(const char* sym
, unsigned int* order
)
398 NameToOrder::iterator pos
= fExportSymbolsOrder
.find(sym
);
399 if ( pos
!= fExportSymbolsOrder
.end() ) {
400 *order
= pos
->second
;
409 void Options::loadSymbolOrderFile(const char* fileOfExports
, NameToOrder
& orderMapping
)
411 // read in whole file
412 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
414 throwf("can't open -exported_symbols_order file: %s", fileOfExports
);
415 struct stat stat_buf
;
416 ::fstat(fd
, &stat_buf
);
417 char* p
= (char*)malloc(stat_buf
.st_size
);
419 throwf("can't process -exported_symbols_order file: %s", fileOfExports
);
421 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
422 throwf("can't read -exported_symbols_order file: %s", fileOfExports
);
426 // parse into symbols and add to hash_set
427 unsigned int count
= 0;
428 char * const end
= &p
[stat_buf
.st_size
];
429 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
430 char* symbolStart
= NULL
;
431 for (char* s
= p
; s
< end
; ++s
) {
437 else if ( !isspace(*s
) ) {
443 if ( (*s
== '\n') || (*s
== '\r') ) {
445 // removing any trailing spaces
447 while ( isspace(*last
) ) {
451 orderMapping
[symbolStart
] = ++count
;
457 if ( (*s
== '\n') || (*s
== '\r') )
462 if ( state
== inSymbol
) {
463 warning("missing line-end at end of file \"%s\"", fileOfExports
);
464 int len
= end
-symbolStart
+1;
465 char* temp
= new char[len
];
466 strlcpy(temp
, symbolStart
, len
);
468 // remove any trailing spaces
469 char* last
= &temp
[len
-2];
470 while ( isspace(*last
) ) {
474 orderMapping
[temp
] = ++count
;
477 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
481 bool Options::shouldExport(const char* symbolName
)
483 switch (fExportMode
) {
485 return fExportSymbols
.contains(symbolName
);
486 case kDontExportSome
:
487 return ! fDontExportSymbols
.contains(symbolName
);
491 throw "internal error";
494 bool Options::keepLocalSymbol(const char* symbolName
)
496 switch (fLocalSymbolHandling
) {
497 case kLocalSymbolsAll
:
499 case kLocalSymbolsNone
:
501 case kLocalSymbolsSelectiveInclude
:
502 return fLocalSymbolsIncluded
.contains(symbolName
);
503 case kLocalSymbolsSelectiveExclude
:
504 return ! fLocalSymbolsExcluded
.contains(symbolName
);
506 throw "internal error";
509 void Options::parseArch(const char* architecture
)
511 if ( architecture
== NULL
)
512 throw "-arch must be followed by an architecture string";
513 if ( strcmp(architecture
, "ppc") == 0 ) {
514 fArchitecture
= CPU_TYPE_POWERPC
;
515 fSubArchitecture
= CPU_SUBTYPE_POWERPC_ALL
;
517 else if ( strcmp(architecture
, "ppc64") == 0 ) {
518 fArchitecture
= CPU_TYPE_POWERPC64
;
519 fSubArchitecture
= CPU_SUBTYPE_POWERPC_ALL
;
521 else if ( strcmp(architecture
, "i386") == 0 ) {
522 fArchitecture
= CPU_TYPE_I386
;
523 fSubArchitecture
= CPU_SUBTYPE_I386_ALL
;
525 else if ( strcmp(architecture
, "x86_64") == 0 ) {
526 fArchitecture
= CPU_TYPE_X86_64
;
527 fSubArchitecture
= CPU_SUBTYPE_X86_64_ALL
;
529 else if ( strcmp(architecture
, "arm") == 0 ) {
530 fArchitecture
= CPU_TYPE_ARM
;
531 fSubArchitecture
= CPU_SUBTYPE_ARM_ALL
;
533 // compatibility support for cpu-sub-types
534 else if ( strcmp(architecture
, "ppc750") == 0 ) {
535 fArchitecture
= CPU_TYPE_POWERPC
;
536 fSubArchitecture
= CPU_SUBTYPE_POWERPC_750
;
537 fHasPreferredSubType
= true;
539 else if ( strcmp(architecture
, "ppc7400") == 0 ) {
540 fArchitecture
= CPU_TYPE_POWERPC
;
541 fSubArchitecture
= CPU_SUBTYPE_POWERPC_7400
;
542 fHasPreferredSubType
= true;
544 else if ( strcmp(architecture
, "ppc7450") == 0 ) {
545 fArchitecture
= CPU_TYPE_POWERPC
;
546 fSubArchitecture
= CPU_SUBTYPE_POWERPC_7450
;
547 fHasPreferredSubType
= true;
549 else if ( strcmp(architecture
, "ppc970") == 0 ) {
550 fArchitecture
= CPU_TYPE_POWERPC
;
551 fSubArchitecture
= CPU_SUBTYPE_POWERPC_970
;
552 fHasPreferredSubType
= true;
554 else if ( strcmp(architecture
, "armv6") == 0 ) {
555 fArchitecture
= CPU_TYPE_ARM
;
556 fSubArchitecture
= CPU_SUBTYPE_ARM_V6
;
557 fHasPreferredSubType
= true;
559 else if ( strcmp(architecture
, "armv5") == 0 ) {
560 fArchitecture
= CPU_TYPE_ARM
;
561 fSubArchitecture
= CPU_SUBTYPE_ARM_V5TEJ
;
562 fHasPreferredSubType
= true;
564 else if ( strcmp(architecture
, "armv4t") == 0 ) {
565 fArchitecture
= CPU_TYPE_ARM
;
566 fSubArchitecture
= CPU_SUBTYPE_ARM_V4T
;
567 fHasPreferredSubType
= true;
569 else if ( strcmp(architecture
, "xscale") == 0 ) {
570 fArchitecture
= CPU_TYPE_ARM
;
571 fSubArchitecture
= CPU_SUBTYPE_ARM_XSCALE
;
572 fHasPreferredSubType
= true;
574 else if ( strcmp(architecture
, "armv7") == 0 ) {
575 fArchitecture
= CPU_TYPE_ARM
;
576 fSubArchitecture
= CPU_SUBTYPE_ARM_V7
;
577 fHasPreferredSubType
= true;
580 throwf("unknown/unsupported architecture name for: -arch %s", architecture
);
583 bool Options::checkForFile(const char* format
, const char* dir
, const char* rootName
, FileInfo
& result
)
585 struct stat statBuffer
;
586 char possiblePath
[strlen(dir
)+strlen(rootName
)+strlen(format
)+8];
587 sprintf(possiblePath
, format
, dir
, rootName
);
588 bool found
= (stat(possiblePath
, &statBuffer
) == 0);
589 if ( fTraceDylibSearching
)
590 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), possiblePath
);
592 result
.path
= strdup(possiblePath
);
593 result
.fileLen
= statBuffer
.st_size
;
594 result
.modTime
= statBuffer
.st_mtime
;
601 Options::FileInfo
Options::findLibrary(const char* rootName
, bool dylibsOnly
)
604 const int rootNameLen
= strlen(rootName
);
605 // if rootName ends in .o there is no .a vs .dylib choice
606 if ( (rootNameLen
> 3) && (strcmp(&rootName
[rootNameLen
-2], ".o") == 0) ) {
607 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
608 it
!= fLibrarySearchPaths
.end();
610 const char* dir
= *it
;
611 if ( checkForFile("%s/%s", dir
, rootName
, result
) )
616 bool lookForDylibs
= ( fOutputKind
!= Options::kDyld
);
617 switch ( fLibrarySearchMode
) {
618 case kSearchAllDirsForDylibsThenAllDirsForArchives
:
619 // first look in all directories for just for dylibs
620 if ( lookForDylibs
) {
621 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
622 it
!= fLibrarySearchPaths
.end();
624 const char* dir
= *it
;
625 if ( checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
628 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
629 it
!= fLibrarySearchPaths
.end();
631 const char* dir
= *it
;
632 if ( checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
636 // next look in all directories for just for archives
638 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
639 it
!= fLibrarySearchPaths
.end();
641 const char* dir
= *it
;
642 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
648 case kSearchDylibAndArchiveInEachDir
:
649 // look in each directory for just for a dylib then for an archive
650 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
651 it
!= fLibrarySearchPaths
.end();
653 const char* dir
= *it
;
654 if ( lookForDylibs
&& checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
656 if ( lookForDylibs
&& checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
658 if ( !dylibsOnly
&& checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
664 throwf("library not found for -l%s", rootName
);
667 Options::FileInfo
Options::findFramework(const char* frameworkName
)
669 if ( frameworkName
== NULL
)
670 throw "-framework missing next argument";
671 char temp
[strlen(frameworkName
)+1];
672 strcpy(temp
, frameworkName
);
673 const char* name
= temp
;
674 const char* suffix
= NULL
;
675 char* comma
= strchr(temp
, ',');
676 if ( comma
!= NULL
) {
680 return findFramework(name
, suffix
);
683 Options::FileInfo
Options::findFramework(const char* rootName
, const char* suffix
)
685 struct stat statBuffer
;
686 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
687 it
!= fFrameworkSearchPaths
.end();
689 // ??? Shouldn't we be using String here and just initializing it?
690 // ??? Use str.c_str () to pull out the string for the stat call.
691 const char* dir
= *it
;
692 char possiblePath
[PATH_MAX
];
693 strcpy(possiblePath
, dir
);
694 strcat(possiblePath
, "/");
695 strcat(possiblePath
, rootName
);
696 strcat(possiblePath
, ".framework/");
697 strcat(possiblePath
, rootName
);
698 if ( suffix
!= NULL
) {
699 char realPath
[PATH_MAX
];
700 // no symlink in framework to suffix variants, so follow main symlink
701 if ( realpath(possiblePath
, realPath
) != NULL
) {
702 strcpy(possiblePath
, realPath
);
703 strcat(possiblePath
, suffix
);
706 bool found
= (stat(possiblePath
, &statBuffer
) == 0);
707 if ( fTraceDylibSearching
)
708 printf("[Logging for XBS]%sfound framework: '%s'\n",
709 (found
? " " : " not "), possiblePath
);
712 result
.path
= strdup(possiblePath
);
713 result
.fileLen
= statBuffer
.st_size
;
714 result
.modTime
= statBuffer
.st_mtime
;
718 // try without suffix
719 if ( suffix
!= NULL
)
720 return findFramework(rootName
, NULL
);
722 throwf("framework not found %s", rootName
);
725 Options::FileInfo
Options::findFile(const char* path
)
728 struct stat statBuffer
;
730 // if absolute path and not a .o file, the use SDK prefix
731 if ( (path
[0] == '/') && (strcmp(&path
[strlen(path
)-2], ".o") != 0) ) {
732 const int pathLen
= strlen(path
);
733 for (std::vector
<const char*>::iterator it
= fSDKPaths
.begin(); it
!= fSDKPaths
.end(); it
++) {
734 // ??? Shouldn't we be using String here?
735 const char* sdkPathDir
= *it
;
736 const int sdkPathDirLen
= strlen(sdkPathDir
);
737 char possiblePath
[sdkPathDirLen
+pathLen
+4];
738 strcpy(possiblePath
, sdkPathDir
);
739 if ( possiblePath
[sdkPathDirLen
-1] == '/' )
740 possiblePath
[sdkPathDirLen
-1] = '\0';
741 strcat(possiblePath
, path
);
742 if ( stat(possiblePath
, &statBuffer
) == 0 ) {
743 result
.path
= strdup(possiblePath
);
744 result
.fileLen
= statBuffer
.st_size
;
745 result
.modTime
= statBuffer
.st_mtime
;
751 if ( stat(path
, &statBuffer
) == 0 ) {
752 result
.path
= strdup(path
);
753 result
.fileLen
= statBuffer
.st_size
;
754 result
.modTime
= statBuffer
.st_mtime
;
758 // try @executable_path substitution
759 if ( (strncmp(path
, "@executable_path/", 17) == 0) && (fExecutablePath
!= NULL
) ) {
760 char newPath
[strlen(fExecutablePath
) + strlen(path
)];
761 strcpy(newPath
, fExecutablePath
);
762 char* addPoint
= strrchr(newPath
,'/');
763 if ( addPoint
!= NULL
)
764 strcpy(&addPoint
[1], &path
[17]);
766 strcpy(newPath
, &path
[17]);
767 if ( stat(newPath
, &statBuffer
) == 0 ) {
768 result
.path
= strdup(newPath
);
769 result
.fileLen
= statBuffer
.st_size
;
770 result
.modTime
= statBuffer
.st_mtime
;
776 throwf("file not found: %s", path
);
779 Options::FileInfo
Options::findFileUsingPaths(const char* path
)
783 const char* lastSlash
= strrchr(path
, '/');
784 const char* leafName
= (lastSlash
== NULL
) ? path
: &lastSlash
[1];
786 // Is this in a framework?
787 // /path/Foo.framework/Foo ==> true (Foo)
788 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
789 // /path/Foo.framework/Resources/Bar ==> false
790 bool isFramework
= false;
791 if ( lastSlash
!= NULL
) {
792 char frameworkDir
[strlen(leafName
) + 20];
793 strcpy(frameworkDir
, "/");
794 strcat(frameworkDir
, leafName
);
795 strcat(frameworkDir
, ".framework/");
796 if ( strstr(path
, frameworkDir
) != NULL
)
800 // These are abbreviated versions of the routines findFramework and findLibrary above
801 // because we already know the final name of the file that we're looking for and so
802 // don't need to try variations, just paths. We do need to add the additional bits
803 // onto the framework path though.
805 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
806 it
!= fFrameworkSearchPaths
.end();
808 const char* dir
= *it
;
809 char possiblePath
[PATH_MAX
];
810 strcpy(possiblePath
, dir
);
811 strcat(possiblePath
, "/");
812 strcat(possiblePath
, leafName
);
813 strcat(possiblePath
, ".framework");
815 //fprintf(stderr,"Finding Framework: %s/%s, leafName=%s\n", possiblePath, leafName, leafName);
816 if ( checkForFile("%s/%s", possiblePath
, leafName
, result
) )
821 // if this is a .dylib inside a framework, do not search -L paths
822 // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
823 int leafLen
= strlen(leafName
);
824 bool embeddedDylib
= ( (leafLen
> 6)
825 && (strcmp(&leafName
[leafLen
-6], ".dylib") == 0)
826 && (strstr(path
, ".framework/") != NULL
) );
827 if ( !embeddedDylib
) {
828 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
829 it
!= fLibrarySearchPaths
.end();
831 const char* dir
= *it
;
832 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
833 if ( checkForFile("%s/%s", dir
, leafName
, result
) )
839 // If we didn't find it fall back to findFile.
840 return findFile(path
);
844 void Options::parseSegAddrTable(const char* segAddrPath
, const char* installPath
)
846 FILE* file
= fopen(segAddrPath
, "r");
847 if ( file
== NULL
) {
848 warning("-seg_addr_table file cannot be read: %s", segAddrPath
);
853 uint64_t firstColumAddress
= 0;
854 uint64_t secondColumAddress
= 0;
855 bool hasSecondColumn
= false;
856 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
857 path
[PATH_MAX
-1] = '\0';
858 char* eol
= strchr(path
, '\n');
861 // ignore lines not starting with 0x number
862 if ( (path
[0] == '0') && (path
[1] == 'x') ) {
864 firstColumAddress
= strtoull(path
, &p
, 16);
865 while ( isspace(*p
) )
867 // see if second column is a number
868 if ( (p
[0] == '0') && (p
[1] == 'x') ) {
869 secondColumAddress
= strtoull(p
, &p
, 16);
870 hasSecondColumn
= true;
871 while ( isspace(*p
) )
874 while ( isspace(*p
) )
877 // remove any trailing whitespace
878 for(char* end
= eol
-1; (end
> p
) && isspace(*end
); --end
)
880 // see if this line is for the dylib being linked
881 if ( strcmp(p
, installPath
) == 0 ) {
882 fBaseAddress
= firstColumAddress
;
883 if ( hasSecondColumn
) {
884 fBaseWritableAddress
= secondColumAddress
;
887 break; // out of while loop
896 void Options::loadFileList(const char* fileOfPaths
)
899 const char* comma
= strrchr(fileOfPaths
, ',');
900 const char* prefix
= NULL
;
901 if ( comma
!= NULL
) {
902 // <rdar://problem/5907981> -filelist fails with comma in path
903 file
= fopen(fileOfPaths
, "r");
904 if ( file
== NULL
) {
906 int realFileOfPathsLen
= comma
-fileOfPaths
;
907 char realFileOfPaths
[realFileOfPathsLen
+1];
908 strncpy(realFileOfPaths
,fileOfPaths
, realFileOfPathsLen
);
909 realFileOfPaths
[realFileOfPathsLen
] = '\0';
910 file
= fopen(realFileOfPaths
, "r");
912 throwf("-filelist file not found: %s\n", realFileOfPaths
);
916 file
= fopen(fileOfPaths
, "r");
918 throwf("-filelist file not found: %s\n", fileOfPaths
);
922 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
923 path
[PATH_MAX
-1] = '\0';
924 char* eol
= strchr(path
, '\n');
927 if ( prefix
!= NULL
) {
928 char builtPath
[strlen(prefix
)+strlen(path
)+2];
929 strcpy(builtPath
, prefix
);
930 strcat(builtPath
, "/");
931 strcat(builtPath
, path
);
932 fInputFiles
.push_back(findFile(builtPath
));
935 fInputFiles
.push_back(findFile(path
));
941 bool Options::SetWithWildcards::hasWildCards(const char* symbol
)
943 // an exported symbol name containing *, ?, or [ requires wildcard matching
944 return ( strpbrk(symbol
, "*?[") != NULL
);
947 void Options::SetWithWildcards::insert(const char* symbol
)
949 if ( hasWildCards(symbol
) )
950 fWildCard
.push_back(symbol
);
952 fRegular
.insert(symbol
);
955 bool Options::SetWithWildcards::contains(const char* symbol
)
957 // first look at hash table on non-wildcard symbols
958 if ( fRegular
.find(symbol
) != fRegular
.end() )
960 // next walk list of wild card symbols looking for a match
961 for(std::vector
<const char*>::iterator it
= fWildCard
.begin(); it
!= fWildCard
.end(); ++it
) {
962 if ( wildCardMatch(*it
, symbol
) )
969 bool Options::SetWithWildcards::inCharRange(const char*& p
, unsigned char c
)
973 while ( *p
!= '\0' ) {
976 // found beginining [ and ending ]
977 unsigned char last
= '\0';
978 for ( const char* s
= b
; s
< e
; ++s
) {
980 unsigned char next
= *(++s
);
981 if ( (last
<= c
) && (c
<= next
) )
998 bool Options::SetWithWildcards::wildCardMatch(const char* pattern
, const char* symbol
)
1000 const char* s
= symbol
;
1001 for (const char* p
= pattern
; *p
!= '\0'; ++p
) {
1006 for (const char* t
= s
; *t
!= '\0'; ++t
) {
1007 if ( wildCardMatch(&p
[1], t
) )
1017 if ( ! inCharRange(p
, *s
) )
1027 return (*s
== '\0');
1031 void Options::loadExportFile(const char* fileOfExports
, const char* option
, SetWithWildcards
& set
)
1033 // read in whole file
1034 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
1036 throwf("can't open %s file: %s", option
, fileOfExports
);
1037 struct stat stat_buf
;
1038 ::fstat(fd
, &stat_buf
);
1039 char* p
= (char*)malloc(stat_buf
.st_size
);
1041 throwf("can't process %s file: %s", option
, fileOfExports
);
1043 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1044 throwf("can't read %s file: %s", option
, fileOfExports
);
1048 // parse into symbols and add to hash_set
1049 char * const end
= &p
[stat_buf
.st_size
];
1050 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1051 char* symbolStart
= NULL
;
1052 for (char* s
= p
; s
< end
; ++s
) {
1058 else if ( !isspace(*s
) ) {
1064 if ( (*s
== '\n') || (*s
== '\r') ) {
1066 // removing any trailing spaces
1068 while ( isspace(*last
) ) {
1072 set
.insert(symbolStart
);
1078 if ( (*s
== '\n') || (*s
== '\r') )
1083 if ( state
== inSymbol
) {
1084 warning("missing line-end at end of file \"%s\"", fileOfExports
);
1085 int len
= end
-symbolStart
+1;
1086 char* temp
= new char[len
];
1087 strlcpy(temp
, symbolStart
, len
);
1089 // remove any trailing spaces
1090 char* last
= &temp
[len
-2];
1091 while ( isspace(*last
) ) {
1098 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
1101 void Options::parseAliasFile(const char* fileOfAliases
)
1103 // read in whole file
1104 int fd
= ::open(fileOfAliases
, O_RDONLY
, 0);
1106 throwf("can't open alias file: %s", fileOfAliases
);
1107 struct stat stat_buf
;
1108 ::fstat(fd
, &stat_buf
);
1109 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1111 throwf("can't process alias file: %s", fileOfAliases
);
1113 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1114 throwf("can't read alias file: %s", fileOfAliases
);
1115 p
[stat_buf
.st_size
] = '\n';
1118 // parse into symbols and add to fAliases
1119 ObjectFile::ReaderOptions::AliasPair pair
;
1120 char * const end
= &p
[stat_buf
.st_size
+1];
1121 enum { lineStart
, inRealName
, inBetween
, inAliasName
, inComment
} state
= lineStart
;
1123 for (char* s
= p
; s
< end
; ++s
) {
1129 else if ( !isspace(*s
) ) {
1136 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1140 else if ( isspace(*s
) ) {
1147 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1151 else if ( ! isspace(*s
) ) {
1152 state
= inAliasName
;
1159 // removing any trailing spaces
1161 while ( isspace(*last
) ) {
1165 fReaderOptions
.fAliases
.push_back(pair
);
1168 else if ( *s
== '\n' ) {
1170 // removing any trailing spaces
1172 while ( isspace(*last
) ) {
1176 fReaderOptions
.fAliases
.push_back(pair
);
1187 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
1192 void Options::setUndefinedTreatment(const char* treatment
)
1194 if ( treatment
== NULL
)
1195 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
1197 if ( strcmp(treatment
, "warning") == 0 )
1198 fUndefinedTreatment
= kUndefinedWarning
;
1199 else if ( strcmp(treatment
, "error") == 0 )
1200 fUndefinedTreatment
= kUndefinedError
;
1201 else if ( strcmp(treatment
, "suppress") == 0 )
1202 fUndefinedTreatment
= kUndefinedSuppress
;
1203 else if ( strcmp(treatment
, "dynamic_lookup") == 0 )
1204 fUndefinedTreatment
= kUndefinedDynamicLookup
;
1206 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1209 Options::Treatment
Options::parseTreatment(const char* treatment
)
1211 if ( treatment
== NULL
)
1214 if ( strcmp(treatment
, "warning") == 0 )
1216 else if ( strcmp(treatment
, "error") == 0 )
1218 else if ( strcmp(treatment
, "suppress") == 0 )
1224 void Options::setMacOSXVersionMin(const char* version
)
1226 if ( version
== NULL
)
1227 throw "-macosx_version_min argument missing";
1229 if ( (strncmp(version
, "10.", 3) == 0) && isdigit(version
[3]) ) {
1230 int num
= version
[3] - '0';
1234 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_1
;
1237 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_2
;
1240 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_3
;
1243 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_4
;
1246 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_5
;
1249 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_6
;
1252 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_6
;
1257 warning("unknown option to -macosx_version_min, not 10.x");
1261 void Options::setIPhoneVersionMin(const char* version
)
1263 if ( version
== NULL
)
1264 throw "-iphoneos_version_min argument missing";
1265 if ( ! isdigit(version
[0]) )
1266 throw "-iphoneos_version_min argument is not a number";
1267 if ( version
[1] != '.' )
1268 throw "-iphoneos_version_min argument is missing period as second character";
1269 if ( ! isdigit(version
[2]) )
1270 throw "-iphoneos_version_min argument is not a number";
1272 if ( version
[0] == '2' )
1273 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_0
;
1274 else if ( (version
[0] == '3') && (version
[2] == '0') )
1275 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_0
;
1276 else if ( (version
[0] == '3') && (version
[2] >= '1') )
1277 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k3_1
;
1278 else if ( (version
[0] >= '4') )
1279 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k3_1
;
1281 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_0
;
1282 warning("unknown option to -iphoneos_version_min, not 2.x, 3.x, or 4.x");
1286 bool Options::minOS(ObjectFile::ReaderOptions::MacVersionMin requiredMacMin
, ObjectFile::ReaderOptions::IPhoneVersionMin requirediPhoneOSMin
)
1288 if ( fReaderOptions
.fMacVersionMin
!= ObjectFile::ReaderOptions::kMinMacVersionUnset
) {
1289 return ( fReaderOptions
.fMacVersionMin
>= requiredMacMin
);
1292 return ( fReaderOptions
.fIPhoneVersionMin
>= requirediPhoneOSMin
);
1297 void Options::setWeakReferenceMismatchTreatment(const char* treatment
)
1299 if ( treatment
== NULL
)
1300 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1302 if ( strcmp(treatment
, "error") == 0 )
1303 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchError
;
1304 else if ( strcmp(treatment
, "weak") == 0 )
1305 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchWeak
;
1306 else if ( strcmp(treatment
, "non-weak") == 0 )
1307 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchNonWeak
;
1309 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1312 Options::CommonsMode
Options::parseCommonsTreatment(const char* mode
)
1315 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1317 if ( strcmp(mode
, "ignore_dylibs") == 0 )
1318 return kCommonsIgnoreDylibs
;
1319 else if ( strcmp(mode
, "use_dylibs") == 0 )
1320 return kCommonsOverriddenByDylibs
;
1321 else if ( strcmp(mode
, "error") == 0 )
1322 return kCommonsConflictsDylibsError
;
1324 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1327 void Options::addDylibOverride(const char* paths
)
1329 if ( paths
== NULL
)
1330 throw "-dylib_file must followed by two colon separated paths";
1331 const char* colon
= strchr(paths
, ':');
1332 if ( colon
== NULL
)
1333 throw "-dylib_file must followed by two colon separated paths";
1334 int len
= colon
-paths
;
1335 char* target
= new char[len
+2];
1336 strncpy(target
, paths
, len
);
1338 DylibOverride entry
;
1339 entry
.installName
= target
;
1340 entry
.useInstead
= &colon
[1];
1341 fDylibOverrides
.push_back(entry
);
1344 uint64_t Options::parseAddress(const char* addr
)
1347 uint64_t result
= strtoull(addr
, &endptr
, 16);
1351 uint32_t Options::parseProtection(const char* prot
)
1353 uint32_t result
= 0;
1354 for(const char* p
= prot
; *p
!= '\0'; ++p
) {
1355 switch(tolower(*p
)) {
1357 result
|= VM_PROT_READ
;
1360 result
|= VM_PROT_WRITE
;
1363 result
|= VM_PROT_EXECUTE
;
1368 throwf("unknown -segprot lettter in %s", prot
);
1377 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1380 uint32_t Options::parseVersionNumber(const char* versionString
)
1382 unsigned long x
= 0;
1383 unsigned long y
= 0;
1384 unsigned long z
= 0;
1386 x
= strtoul(versionString
, &end
, 10);
1387 if ( *end
== '.' ) {
1388 y
= strtoul(&end
[1], &end
, 10);
1389 if ( *end
== '.' ) {
1390 z
= strtoul(&end
[1], &end
, 10);
1393 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
1394 throwf("malformed version number: %s", versionString
);
1396 return (x
<< 16) | ( y
<< 8 ) | z
;
1399 static const char* cstringSymbolName(const char* orderFileString
)
1402 asprintf(&result
, "cstring=%s", orderFileString
);
1403 // convert escaped characters
1405 for(const char* s
=result
; *s
!= '\0'; ++s
, ++d
) {
1443 // hexadecimal value of char
1447 while ( isxdigit(*s
) ) {
1452 value
+= ((toupper(*s
)-'A') + 10);
1459 if ( isdigit(*s
) ) {
1460 // octal value of char
1462 while ( isdigit(*s
) ) {
1463 value
= (value
<< 3) + (*s
-'0');
1478 void Options::parseOrderFile(const char* path
, bool cstring
)
1480 // order files override auto-ordering
1481 fReaderOptions
.fAutoOrderInitializers
= false;
1483 // read in whole file
1484 int fd
= ::open(path
, O_RDONLY
, 0);
1486 throwf("can't open order file: %s", path
);
1487 struct stat stat_buf
;
1488 ::fstat(fd
, &stat_buf
);
1489 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1491 throwf("can't process order file: %s", path
);
1492 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1493 throwf("can't read order file: %s", path
);
1495 p
[stat_buf
.st_size
] = '\n';
1497 // parse into vector of pairs
1498 char * const end
= &p
[stat_buf
.st_size
+1];
1499 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1500 char* symbolStart
= NULL
;
1501 for (char* s
= p
; s
< end
; ++s
) {
1507 else if ( !isspace(*s
) || cstring
) {
1513 if ( (*s
== '\n') || (!cstring
&& (*s
== '#')) ) {
1514 bool wasComment
= (*s
== '#');
1516 // removing any trailing spaces
1518 while ( isspace(*last
) ) {
1522 if ( strncmp(symbolStart
, "ppc:", 4) == 0 ) {
1523 if ( fArchitecture
== CPU_TYPE_POWERPC
)
1524 symbolStart
= &symbolStart
[4];
1528 // if there is an architecture prefix, only use this symbol it if matches current arch
1529 else if ( strncmp(symbolStart
, "ppc64:", 6) == 0 ) {
1530 if ( fArchitecture
== CPU_TYPE_POWERPC64
)
1531 symbolStart
= &symbolStart
[6];
1535 else if ( strncmp(symbolStart
, "i386:", 5) == 0 ) {
1536 if ( fArchitecture
== CPU_TYPE_I386
)
1537 symbolStart
= &symbolStart
[5];
1541 else if ( strncmp(symbolStart
, "x86_64:", 7) == 0 ) {
1542 if ( fArchitecture
== CPU_TYPE_X86_64
)
1543 symbolStart
= &symbolStart
[7];
1547 else if ( strncmp(symbolStart
, "arm:", 4) == 0 ) {
1548 if ( fArchitecture
== CPU_TYPE_ARM
)
1549 symbolStart
= &symbolStart
[4];
1553 if ( symbolStart
!= NULL
) {
1554 char* objFileName
= NULL
;
1555 char* colon
= strstr(symbolStart
, ".o:");
1556 if ( colon
!= NULL
) {
1558 objFileName
= symbolStart
;
1559 symbolStart
= &colon
[3];
1561 // trim leading spaces
1562 while ( isspace(*symbolStart
) )
1564 Options::OrderedSymbol pair
;
1566 pair
.symbolName
= cstringSymbolName(symbolStart
);
1568 pair
.symbolName
= symbolStart
;
1569 pair
.objectFileName
= objFileName
;
1570 fOrderedSymbols
.push_back(pair
);
1585 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1588 void Options::parseSectionOrderFile(const char* segment
, const char* section
, const char* path
)
1590 if ( (strcmp(section
, "__cstring") == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1591 parseOrderFile(path
, true);
1593 else if ( (strncmp(section
, "__literal",9) == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1594 warning("sorting of __literal[4,8,16] sections not supported");
1597 // ignore section information and append all symbol names to global order file
1598 parseOrderFile(path
, false);
1602 void Options::addSection(const char* segment
, const char* section
, const char* path
)
1604 if ( strlen(segment
) > 16 )
1605 throw "-seccreate segment name max 16 chars";
1606 if ( strlen(section
) > 16 ) {
1607 char* tmp
= strdup(section
);
1609 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section
, tmp
);
1613 // read in whole file
1614 int fd
= ::open(path
, O_RDONLY
, 0);
1616 throwf("can't open -sectcreate file: %s", path
);
1617 struct stat stat_buf
;
1618 ::fstat(fd
, &stat_buf
);
1619 char* p
= (char*)malloc(stat_buf
.st_size
);
1621 throwf("can't process -sectcreate file: %s", path
);
1622 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1623 throwf("can't read -sectcreate file: %s", path
);
1626 // record section to create
1627 ExtraSection info
= { segment
, section
, path
, (uint8_t*)p
, stat_buf
.st_size
};
1628 fExtraSections
.push_back(info
);
1631 void Options::addSectionAlignment(const char* segment
, const char* section
, const char* alignmentStr
)
1633 if ( strlen(segment
) > 16 )
1634 throw "-sectalign segment name max 16 chars";
1635 if ( strlen(section
) > 16 )
1636 throw "-sectalign section name max 16 chars";
1638 // argument to -sectalign is a hexadecimal number
1640 unsigned long value
= strtoul(alignmentStr
, &endptr
, 16);
1641 if ( *endptr
!= '\0')
1642 throw "argument for -sectalign is not a hexadecimal number";
1643 if ( value
> 0x8000 )
1644 throw "argument for -sectalign must be less than or equal to 0x8000";
1646 warning("zero is not a valid -sectalign");
1650 // alignment is power of 2 (e.g. page alignment = 12)
1651 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
1652 if ( (unsigned long)(1 << alignment
) != value
) {
1653 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
1654 segment
, section
, 1 << alignment
);
1657 SectionAlignment info
= { segment
, section
, alignment
};
1658 fSectionAlignments
.push_back(info
);
1661 void Options::addLibrary(const FileInfo
& info
)
1663 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
1664 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
1665 if ( strcmp(info
.path
, fit
->path
) == 0 ) {
1666 // if dylib is specified again but weak, record that it should be weak
1667 if ( info
.options
.fWeakImport
)
1668 fit
->options
.fWeakImport
= true;
1673 fInputFiles
.push_back(info
);
1676 void Options::warnObsolete(const char* arg
)
1678 warning("option %s is obsolete and being ignored", arg
);
1685 // Process all command line arguments.
1687 // The only error checking done here is that each option is valid and if it has arguments
1688 // that they too are valid.
1690 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
1691 // whichever was last on the command line is used.
1693 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
1695 void Options::parse(int argc
, const char* argv
[])
1697 // pass one builds search list from -L and -F options
1698 this->buildSearchPaths(argc
, argv
);
1700 // reduce re-allocations
1701 fInputFiles
.reserve(32);
1703 // pass two parse all other options
1704 for(int i
=1; i
< argc
; ++i
) {
1705 const char* arg
= argv
[i
];
1707 if ( arg
[0] == '-' ) {
1709 // Since we don't care about the files passed, just the option names, we do this here.
1711 fprintf (stderr
, "[Logging ld64 options]\t%s\n", arg
);
1713 if ( (arg
[1] == 'L') || (arg
[1] == 'F') ) {
1714 // previously handled by buildSearchPaths()
1716 // The one gnu style option we have to keep compatibility
1717 // with gcc. Might as well have the single hyphen one as well.
1718 else if ( (strcmp(arg
, "--help") == 0)
1719 || (strcmp(arg
, "-help") == 0)) {
1720 fprintf (stdout
, "ld64: For information on command line options please use 'man ld'.\n");
1723 else if ( strcmp(arg
, "-arch") == 0 ) {
1724 parseArch(argv
[++i
]);
1726 else if ( strcmp(arg
, "-dynamic") == 0 ) {
1729 else if ( strcmp(arg
, "-static") == 0 ) {
1730 fReaderOptions
.fForStatic
= true;
1731 if ( fOutputKind
!= kObjectFile
) {
1732 fOutputKind
= kStaticExecutable
;
1735 else if ( strcmp(arg
, "-dylib") == 0 ) {
1736 fOutputKind
= kDynamicLibrary
;
1738 else if ( strcmp(arg
, "-bundle") == 0 ) {
1739 fOutputKind
= kDynamicBundle
;
1741 else if ( strcmp(arg
, "-dylinker") == 0 ) {
1742 fOutputKind
= kDyld
;
1744 else if ( strcmp(arg
, "-execute") == 0 ) {
1745 if ( fOutputKind
!= kStaticExecutable
)
1746 fOutputKind
= kDynamicExecutable
;
1748 else if ( strcmp(arg
, "-preload") == 0 ) {
1749 fOutputKind
= kPreload
;
1751 else if ( strcmp(arg
, "-r") == 0 ) {
1752 fOutputKind
= kObjectFile
;
1754 else if ( strcmp(arg
, "-kext") == 0 ) {
1755 fOutputKind
= kKextBundle
;
1757 else if ( strcmp(arg
, "-o") == 0 ) {
1758 fOutputFile
= argv
[++i
];
1760 else if ( (arg
[1] == 'l') && (strncmp(arg
,"-lazy_",6) !=0) ) {
1761 addLibrary(findLibrary(&arg
[2]));
1763 // This causes a dylib to be weakly bound at
1764 // link time. This corresponds to weak_import.
1765 else if ( strncmp(arg
, "-weak-l", 7) == 0 ) {
1766 FileInfo info
= findLibrary(&arg
[7]);
1767 info
.options
.fWeakImport
= true;
1770 else if ( strncmp(arg
, "-lazy-l", 7) == 0 ) {
1771 FileInfo info
= findLibrary(&arg
[7], true);
1772 info
.options
.fLazyLoad
= true;
1774 fUsingLazyDylibLinking
= true;
1776 // Avoid lazy binding.
1778 else if ( strcmp(arg
, "-bind_at_load") == 0 ) {
1781 else if ( strcmp(arg
, "-twolevel_namespace") == 0 ) {
1782 fNameSpace
= kTwoLevelNameSpace
;
1784 else if ( strcmp(arg
, "-flat_namespace") == 0 ) {
1785 fNameSpace
= kFlatNameSpace
;
1787 // Also sets a bit to ensure dyld causes everything
1788 // in the namespace to be flat.
1790 else if ( strcmp(arg
, "-force_flat_namespace") == 0 ) {
1791 fNameSpace
= kForceFlatNameSpace
;
1793 // Similar to --whole-archive.
1794 else if ( strcmp(arg
, "-all_load") == 0 ) {
1795 fReaderOptions
.fFullyLoadArchives
= true;
1797 else if ( strcmp(arg
, "-noall_load") == 0) {
1800 // Similar to -all_load
1801 else if ( strcmp(arg
, "-ObjC") == 0 ) {
1802 fReaderOptions
.fLoadAllObjcObjectsFromArchives
= true;
1804 // Similar to -all_load, but for the following archive only.
1805 else if ( strcmp(arg
, "-force_load") == 0 ) {
1806 FileInfo info
= findFile(argv
[++i
]);
1807 info
.options
.fForceLoad
= true;
1810 // Library versioning.
1811 else if ( (strcmp(arg
, "-dylib_compatibility_version") == 0)
1812 || (strcmp(arg
, "-compatibility_version") == 0)) {
1813 const char* vers
= argv
[++i
];
1815 throw "-dylib_compatibility_version missing <version>";
1816 fDylibCompatVersion
= parseVersionNumber(vers
);
1818 else if ( (strcmp(arg
, "-dylib_current_version") == 0)
1819 || (strcmp(arg
, "-current_version") == 0)) {
1820 const char* vers
= argv
[++i
];
1822 throw "-dylib_current_version missing <version>";
1823 fDylibCurrentVersion
= parseVersionNumber(vers
);
1825 else if ( strcmp(arg
, "-sectorder") == 0 ) {
1826 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
1827 throw "-sectorder missing <segment> <section> <file-path>";
1828 parseSectionOrderFile(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1831 else if ( strcmp(arg
, "-order_file") == 0 ) {
1832 parseOrderFile(argv
[++i
], false);
1834 else if ( strcmp(arg
, "-order_file_statistics") == 0 ) {
1835 fPrintOrderFileStatistics
= true;
1837 // ??? Deprecate segcreate.
1838 // -sectcreate puts whole files into a section in the output.
1839 else if ( (strcmp(arg
, "-sectcreate") == 0) || (strcmp(arg
, "-segcreate") == 0) ) {
1840 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
1841 throw "-sectcreate missing <segment> <section> <file-path>";
1842 addSection(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1845 // Since we have a full path in binary/library names we need to be able to override it.
1846 else if ( (strcmp(arg
, "-dylib_install_name") == 0)
1847 || (strcmp(arg
, "-dylinker_install_name") == 0)
1848 || (strcmp(arg
, "-install_name") == 0)) {
1849 fDylibInstallName
= argv
[++i
];
1850 if ( fDylibInstallName
== NULL
)
1851 throw "-install_name missing <path>";
1853 // Sets the base address of the output.
1854 else if ( (strcmp(arg
, "-seg1addr") == 0) || (strcmp(arg
, "-image_base") == 0) ) {
1855 const char* address
= argv
[++i
];
1856 if ( address
== NULL
)
1857 throwf("%s missing <address>", arg
);
1858 fBaseAddress
= parseAddress(address
);
1859 uint64_t temp
= ((fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
1860 if ( fBaseAddress
!= temp
) {
1861 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment
);
1862 fBaseAddress
= temp
;
1865 else if ( strcmp(arg
, "-e") == 0 ) {
1866 fEntryName
= argv
[++i
];
1868 // Same as -@ from the FSF linker.
1869 else if ( strcmp(arg
, "-filelist") == 0 ) {
1870 const char* path
= argv
[++i
];
1871 if ( (path
== NULL
) || (path
[0] == '-') )
1872 throw "-filelist missing <path>";
1875 else if ( strcmp(arg
, "-keep_private_externs") == 0 ) {
1876 fKeepPrivateExterns
= true;
1878 else if ( strcmp(arg
, "-final_output") == 0 ) {
1879 fFinalName
= argv
[++i
];
1881 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
1882 // just ensures that this happens for cross object file boundaries.
1883 else if ( (strcmp(arg
, "-interposable") == 0) || (strcmp(arg
, "-multi_module") == 0)) {
1884 switch ( fInterposeMode
) {
1885 case kInterposeNone
:
1886 case kInterposeAllExternal
:
1887 fInterposeMode
= kInterposeAllExternal
;
1889 case kInterposeSome
:
1890 // do nothing, -interposable_list overrides -interposable"
1894 else if ( strcmp(arg
, "-interposable_list") == 0 ) {
1895 fInterposeMode
= kInterposeSome
;
1896 loadExportFile(argv
[++i
], "-interposable_list", fInterposeList
);
1898 // Default for -interposable/-multi_module/-single_module.
1899 else if ( strcmp(arg
, "-single_module") == 0 ) {
1900 fInterposeMode
= kInterposeNone
;
1902 else if ( strcmp(arg
, "-exported_symbols_list") == 0 ) {
1903 if ( fExportMode
== kDontExportSome
)
1904 throw "can't use -exported_symbols_list and -unexported_symbols_list";
1905 fExportMode
= kExportSome
;
1906 loadExportFile(argv
[++i
], "-exported_symbols_list", fExportSymbols
);
1908 else if ( strcmp(arg
, "-unexported_symbols_list") == 0 ) {
1909 if ( fExportMode
== kExportSome
)
1910 throw "can't use -unexported_symbols_list and -exported_symbols_list";
1911 fExportMode
= kDontExportSome
;
1912 loadExportFile(argv
[++i
], "-unexported_symbols_list", fDontExportSymbols
);
1914 else if ( strcmp(arg
, "-exported_symbol") == 0 ) {
1915 if ( fExportMode
== kDontExportSome
)
1916 throw "can't use -exported_symbol and -unexported_symbols";
1917 fExportMode
= kExportSome
;
1918 fExportSymbols
.insert(argv
[++i
]);
1920 else if ( strcmp(arg
, "-unexported_symbol") == 0 ) {
1921 if ( fExportMode
== kExportSome
)
1922 throw "can't use -unexported_symbol and -exported_symbol";
1923 fExportMode
= kDontExportSome
;
1924 fDontExportSymbols
.insert(argv
[++i
]);
1926 else if ( strcmp(arg
, "-non_global_symbols_no_strip_list") == 0 ) {
1927 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveExclude
)
1928 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
1929 fLocalSymbolHandling
= kLocalSymbolsSelectiveInclude
;
1930 loadExportFile(argv
[++i
], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded
);
1932 else if ( strcmp(arg
, "-non_global_symbols_strip_list") == 0 ) {
1933 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveInclude
)
1934 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
1935 fLocalSymbolHandling
= kLocalSymbolsSelectiveExclude
;
1936 loadExportFile(argv
[++i
], "-non_global_symbols_strip_list", fLocalSymbolsExcluded
);
1939 else if ( strcmp(arg
, "-no_arch_warnings") == 0 ) {
1940 fIgnoreOtherArchFiles
= true;
1942 else if ( strcmp(arg
, "-force_cpusubtype_ALL") == 0 ) {
1943 fForceSubtypeAll
= true;
1945 // Similar to -weak-l but uses the absolute path name to the library.
1946 else if ( strcmp(arg
, "-weak_library") == 0 ) {
1947 FileInfo info
= findFile(argv
[++i
]);
1948 info
.options
.fWeakImport
= true;
1951 else if ( strcmp(arg
, "-lazy_library") == 0 ) {
1952 FileInfo info
= findFile(argv
[++i
]);
1953 info
.options
.fLazyLoad
= true;
1955 fUsingLazyDylibLinking
= true;
1957 else if ( strcmp(arg
, "-framework") == 0 ) {
1958 addLibrary(findFramework(argv
[++i
]));
1960 else if ( strcmp(arg
, "-weak_framework") == 0 ) {
1961 FileInfo info
= findFramework(argv
[++i
]);
1962 info
.options
.fWeakImport
= true;
1965 else if ( strcmp(arg
, "-lazy_framework") == 0 ) {
1966 FileInfo info
= findFramework(argv
[++i
]);
1967 info
.options
.fLazyLoad
= true;
1969 fUsingLazyDylibLinking
= true;
1971 else if ( strcmp(arg
, "-search_paths_first") == 0 ) {
1972 // previously handled by buildSearchPaths()
1974 else if ( strcmp(arg
, "-undefined") == 0 ) {
1975 setUndefinedTreatment(argv
[++i
]);
1977 // Debugging output flag.
1978 else if ( strcmp(arg
, "-arch_multiple") == 0 ) {
1979 fMessagesPrefixedWithArchitecture
= true;
1981 // Specify what to do with relocations in read only
1982 // sections like .text. Could be errors, warnings,
1983 // or suppressed. Currently we do nothing with the
1985 else if ( strcmp(arg
, "-read_only_relocs") == 0 ) {
1986 switch ( parseTreatment(argv
[++i
]) ) {
1989 throw "-read_only_relocs missing [ warning | error | suppress ]";
1991 fWarnTextRelocs
= true;
1992 fAllowTextRelocs
= true;
1995 fWarnTextRelocs
= false;
1996 fAllowTextRelocs
= true;
1999 fWarnTextRelocs
= false;
2000 fAllowTextRelocs
= false;
2004 else if ( strcmp(arg
, "-sect_diff_relocs") == 0 ) {
2008 // Warn, error or make strong a mismatch between weak
2009 // and non-weak references.
2010 else if ( strcmp(arg
, "-weak_reference_mismatches") == 0 ) {
2011 setWeakReferenceMismatchTreatment(argv
[++i
]);
2013 // For a deployment target of 10.3 and earlier ld64 will
2014 // prebind an executable with 0s in all addresses that
2015 // are prebound. This can then be fixed up by update_prebinding
2016 // later. Prebinding is less useful on 10.4 and greater.
2017 else if ( strcmp(arg
, "-prebind") == 0 ) {
2020 else if ( strcmp(arg
, "-noprebind") == 0 ) {
2024 else if ( strcmp(arg
, "-prebind_allow_overlap") == 0 ) {
2027 else if ( strcmp(arg
, "-prebind_all_twolevel_modules") == 0 ) {
2030 else if ( strcmp(arg
, "-noprebind_all_twolevel_modules") == 0 ) {
2033 else if ( strcmp(arg
, "-nofixprebinding") == 0 ) {
2036 // This should probably be deprecated when we respect -L and -F
2037 // when searching for libraries.
2038 else if ( strcmp(arg
, "-dylib_file") == 0 ) {
2039 addDylibOverride(argv
[++i
]);
2041 // What to expand @executable_path to if found in dependent dylibs
2042 else if ( strcmp(arg
, "-executable_path") == 0 ) {
2043 fExecutablePath
= argv
[++i
];
2044 if ( (fExecutablePath
== NULL
) || (fExecutablePath
[0] == '-') )
2045 throw "-executable_path missing <path>";
2046 // if a directory was passed, add / to end
2047 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2048 struct stat statBuffer
;
2049 if ( stat(fExecutablePath
, &statBuffer
) == 0 ) {
2050 if ( (statBuffer
.st_mode
& S_IFMT
) == S_IFDIR
) {
2051 char* pathWithSlash
= new char[strlen(fExecutablePath
)+2];
2052 strcpy(pathWithSlash
, fExecutablePath
);
2053 strcat(pathWithSlash
, "/");
2054 fExecutablePath
= pathWithSlash
;
2058 // Aligns all segments to the power of 2 boundary specified.
2059 else if ( strcmp(arg
, "-segalign") == 0 ) {
2060 const char* size
= argv
[++i
];
2062 throw "-segalign missing <size>";
2063 fSegmentAlignment
= parseAddress(size
);
2064 uint8_t alignment
= (uint8_t)__builtin_ctz(fSegmentAlignment
);
2065 uint32_t p2aligned
= (1 << alignment
);
2066 if ( p2aligned
!= fSegmentAlignment
) {
2067 warning("alignment for -segalign %s is not a power of two, using 0x%X", size
, p2aligned
);
2068 fSegmentAlignment
= p2aligned
;
2071 // Puts a specified segment at a particular address that must
2072 // be a multiple of the segment alignment.
2073 else if ( strcmp(arg
, "-segaddr") == 0 ) {
2075 seg
.name
= argv
[++i
];
2076 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2077 throw "-segaddr missing segName Adddress";
2078 seg
.address
= parseAddress(argv
[++i
]);
2079 uint64_t temp
= seg
.address
& (-4096); // page align
2080 if ( (seg
.address
!= temp
) )
2081 warning("-segaddr %s not page aligned, rounding down", seg
.name
);
2082 fCustomSegmentAddresses
.push_back(seg
);
2084 // ??? Deprecate when we deprecate split-seg.
2085 else if ( strcmp(arg
, "-segs_read_only_addr") == 0 ) {
2086 fBaseAddress
= parseAddress(argv
[++i
]);
2088 // ??? Deprecate when we deprecate split-seg.
2089 else if ( strcmp(arg
, "-segs_read_write_addr") == 0 ) {
2090 fBaseWritableAddress
= parseAddress(argv
[++i
]);
2093 // ??? Deprecate when we get rid of basing at build time.
2094 else if ( strcmp(arg
, "-seg_addr_table") == 0 ) {
2095 const char* name
= argv
[++i
];
2097 throw "-seg_addr_table missing argument";
2098 fSegAddrTablePath
= name
;
2100 else if ( strcmp(arg
, "-seg_addr_table_filename") == 0 ) {
2104 else if ( strcmp(arg
, "-segprot") == 0 ) {
2106 seg
.name
= argv
[++i
];
2107 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) || (argv
[i
+2] == NULL
) )
2108 throw "-segprot missing segName max-prot init-prot";
2109 seg
.max
= parseProtection(argv
[++i
]);
2110 seg
.init
= parseProtection(argv
[++i
]);
2111 fCustomSegmentProtections
.push_back(seg
);
2113 else if ( strcmp(arg
, "-pagezero_size") == 0 ) {
2114 const char* size
= argv
[++i
];
2116 throw "-pagezero_size missing <size>";
2117 fZeroPageSize
= parseAddress(size
);
2118 uint64_t temp
= fZeroPageSize
& (-4096); // page align
2119 if ( (fZeroPageSize
!= temp
) )
2120 warning("-pagezero_size not page aligned, rounding down");
2121 fZeroPageSize
= temp
;
2123 else if ( strcmp(arg
, "-stack_addr") == 0 ) {
2124 const char* address
= argv
[++i
];
2125 if ( address
== NULL
)
2126 throw "-stack_addr missing <address>";
2127 fStackAddr
= parseAddress(address
);
2129 else if ( strcmp(arg
, "-stack_size") == 0 ) {
2130 const char* size
= argv
[++i
];
2132 throw "-stack_size missing <address>";
2133 fStackSize
= parseAddress(size
);
2134 uint64_t temp
= fStackSize
& (-4096); // page align
2135 if ( (fStackSize
!= temp
) )
2136 warning("-stack_size not page aligned, rounding down");
2138 else if ( strcmp(arg
, "-allow_stack_execute") == 0 ) {
2139 fExecutableStack
= true;
2141 else if ( strcmp(arg
, "-sectalign") == 0 ) {
2142 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2143 throw "-sectalign missing <segment> <section> <file-path>";
2144 addSectionAlignment(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2147 else if ( strcmp(arg
, "-sectorder_detail") == 0 ) {
2150 else if ( strcmp(arg
, "-sectobjectsymbols") == 0 ) {
2154 else if ( strcmp(arg
, "-bundle_loader") == 0 ) {
2155 fBundleLoader
= argv
[++i
];
2156 if ( (fBundleLoader
== NULL
) || (fBundleLoader
[0] == '-') )
2157 throw "-bundle_loader missing <path>";
2158 FileInfo info
= findFile(fBundleLoader
);
2159 info
.options
.fBundleLoader
= true;
2160 fInputFiles
.push_back(info
);
2162 else if ( strcmp(arg
, "-private_bundle") == 0 ) {
2165 else if ( strcmp(arg
, "-twolevel_namespace_hints") == 0 ) {
2168 // Use this flag to set default behavior for deployement targets.
2169 else if ( strcmp(arg
, "-macosx_version_min") == 0 ) {
2170 setMacOSXVersionMin(argv
[++i
]);
2172 else if ( strcmp(arg
, "-iphoneos_version_min") == 0 ) {
2173 setIPhoneVersionMin(argv
[++i
]);
2175 else if ( strcmp(arg
, "-multiply_defined") == 0 ) {
2176 //warnObsolete(arg);
2179 else if ( strcmp(arg
, "-multiply_defined_unused") == 0 ) {
2183 else if ( strcmp(arg
, "-nomultidefs") == 0 ) {
2186 // Display each file in which the argument symbol appears and whether
2187 // the file defines or references it. This option takes an argument
2188 // as -y<symbol> note that there is no space.
2189 else if ( strncmp(arg
, "-y", 2) == 0 ) {
2192 // Same output as -y, but output <arg> number of undefined symbols only.
2193 else if ( strcmp(arg
, "-Y") == 0 ) {
2194 //warnObsolete(arg);
2197 // This option affects all objects linked into the final result.
2198 else if ( strcmp(arg
, "-m") == 0 ) {
2201 else if ( (strcmp(arg
, "-why_load") == 0) || (strcmp(arg
, "-whyload") == 0) ) {
2202 fReaderOptions
.fWhyLoad
= true;
2204 else if ( strcmp(arg
, "-why_live") == 0 ) {
2205 const char* name
= argv
[++i
];
2207 throw "-why_live missing symbol name argument";
2208 fWhyLive
.insert(name
);
2210 else if ( strcmp(arg
, "-u") == 0 ) {
2211 const char* name
= argv
[++i
];
2213 throw "-u missing argument";
2214 fInitialUndefines
.push_back(name
);
2216 else if ( strcmp(arg
, "-U") == 0 ) {
2217 const char* name
= argv
[++i
];
2219 throw "-U missing argument";
2220 fAllowedUndefined
.insert(name
);
2222 else if ( strcmp(arg
, "-s") == 0 ) {
2224 fLocalSymbolHandling
= kLocalSymbolsNone
;
2225 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
2227 else if ( strcmp(arg
, "-x") == 0 ) {
2228 fLocalSymbolHandling
= kLocalSymbolsNone
;
2230 else if ( strcmp(arg
, "-S") == 0 ) {
2231 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
2233 else if ( strcmp(arg
, "-X") == 0 ) {
2236 else if ( strcmp(arg
, "-Si") == 0 ) {
2238 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoFull
;
2240 else if ( strcmp(arg
, "-b") == 0 ) {
2243 else if ( strcmp(arg
, "-Sn") == 0 ) {
2245 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoFull
;
2247 else if ( strcmp(arg
, "-Sp") == 0 ) {
2250 else if ( strcmp(arg
, "-dead_strip") == 0 ) {
2251 fDeadStrip
= kDeadStripOnPlusUnusedInits
;
2253 else if ( strcmp(arg
, "-no_dead_strip_inits_and_terms") == 0 ) {
2254 fDeadStrip
= kDeadStripOn
;
2256 else if ( strcmp(arg
, "-w") == 0 ) {
2257 // previously handled by buildSearchPaths()
2259 else if ( strcmp(arg
, "-arch_errors_fatal") == 0 ) {
2260 fErrorOnOtherArchFiles
= true;
2262 else if ( strcmp(arg
, "-M") == 0 ) {
2265 else if ( strcmp(arg
, "-headerpad") == 0 ) {
2266 const char* size
= argv
[++i
];
2268 throw "-headerpad missing argument";
2269 fMinimumHeaderPad
= parseAddress(size
);
2271 else if ( strcmp(arg
, "-headerpad_max_install_names") == 0 ) {
2272 fMaxMinimumHeaderPad
= true;
2274 else if ( strcmp(arg
, "-t") == 0 ) {
2275 fReaderOptions
.fLogAllFiles
= true;
2277 else if ( strcmp(arg
, "-whatsloaded") == 0 ) {
2278 fReaderOptions
.fLogObjectFiles
= true;
2280 else if ( strcmp(arg
, "-A") == 0 ) {
2284 else if ( strcmp(arg
, "-umbrella") == 0 ) {
2285 const char* name
= argv
[++i
];
2287 throw "-umbrella missing argument";
2288 fUmbrellaName
= name
;
2290 else if ( strcmp(arg
, "-allowable_client") == 0 ) {
2291 const char* name
= argv
[++i
];
2294 throw "-allowable_client missing argument";
2296 fAllowableClients
.push_back(name
);
2298 else if ( strcmp(arg
, "-client_name") == 0 ) {
2299 const char* name
= argv
[++i
];
2302 throw "-client_name missing argument";
2306 else if ( strcmp(arg
, "-sub_umbrella") == 0 ) {
2307 const char* name
= argv
[++i
];
2309 throw "-sub_umbrella missing argument";
2310 fSubUmbellas
.push_back(name
);
2312 else if ( strcmp(arg
, "-sub_library") == 0 ) {
2313 const char* name
= argv
[++i
];
2315 throw "-sub_library missing argument";
2316 fSubLibraries
.push_back(name
);
2318 else if ( strcmp(arg
, "-init") == 0 ) {
2319 const char* name
= argv
[++i
];
2321 throw "-init missing argument";
2322 fInitFunctionName
= name
;
2324 else if ( strcmp(arg
, "-dot") == 0 ) {
2325 const char* name
= argv
[++i
];
2327 throw "-dot missing argument";
2328 fDotOutputFile
= name
;
2330 else if ( strcmp(arg
, "-warn_commons") == 0 ) {
2331 fWarnCommons
= true;
2333 else if ( strcmp(arg
, "-commons") == 0 ) {
2334 fCommonsMode
= parseCommonsTreatment(argv
[++i
]);
2336 else if ( strcmp(arg
, "-keep_relocs") == 0 ) {
2337 fKeepRelocations
= true;
2339 else if ( strcmp(arg
, "-warn_stabs") == 0 ) {
2342 else if ( strcmp(arg
, "-pause") == 0 ) {
2345 else if ( strcmp(arg
, "-print_statistics") == 0 ) {
2348 else if ( strcmp(arg
, "-d") == 0 ) {
2349 fReaderOptions
.fMakeTentativeDefinitionsReal
= true;
2351 else if ( strcmp(arg
, "-v") == 0 ) {
2352 // previously handled by buildSearchPaths()
2354 else if ( strcmp(arg
, "-Z") == 0 ) {
2355 // previously handled by buildSearchPaths()
2357 else if ( strcmp(arg
, "-syslibroot") == 0 ) {
2359 // previously handled by buildSearchPaths()
2361 else if ( strcmp(arg
, "-no_uuid") == 0 ) {
2362 fUUIDMode
= kUUIDNone
;
2364 else if ( strcmp(arg
, "-random_uuid") == 0 ) {
2365 fUUIDMode
= kUUIDRandom
;
2367 else if ( strcmp(arg
, "-dtrace") == 0 ) {
2368 const char* name
= argv
[++i
];
2370 throw "-dtrace missing argument";
2371 fDtraceScriptName
= name
;
2373 else if ( strcmp(arg
, "-root_safe") == 0 ) {
2374 fReaderOptions
.fRootSafe
= true;
2376 else if ( strcmp(arg
, "-setuid_safe") == 0 ) {
2377 fReaderOptions
.fSetuidSafe
= true;
2379 else if ( strcmp(arg
, "-alias") == 0 ) {
2380 ObjectFile::ReaderOptions::AliasPair pair
;
2381 pair
.realName
= argv
[++i
];
2382 if ( pair
.realName
== NULL
)
2383 throw "missing argument to -alias";
2384 pair
.alias
= argv
[++i
];
2385 if ( pair
.alias
== NULL
)
2386 throw "missing argument to -alias";
2387 fReaderOptions
.fAliases
.push_back(pair
);
2389 else if ( strcmp(arg
, "-alias_list") == 0 ) {
2390 parseAliasFile(argv
[++i
]);
2392 // put this last so that it does not interfer with other options starting with 'i'
2393 else if ( strncmp(arg
, "-i", 2) == 0 ) {
2394 const char* colon
= strchr(arg
, ':');
2395 if ( colon
== NULL
)
2396 throwf("unknown option: %s", arg
);
2397 ObjectFile::ReaderOptions::AliasPair pair
;
2398 char* temp
= new char[colon
-arg
];
2399 strlcpy(temp
, &arg
[2], colon
-arg
-1);
2400 pair
.realName
= &colon
[1];
2402 fReaderOptions
.fAliases
.push_back(pair
);
2404 else if ( strcmp(arg
, "-save-temps") == 0 ) {
2405 fSaveTempFiles
= true;
2407 else if ( strcmp(arg
, "-rpath") == 0 ) {
2408 const char* path
= argv
[++i
];
2410 throw "missing argument to -rpath";
2411 fRPaths
.push_back(path
);
2413 else if ( strcmp(arg
, "-read_only_stubs") == 0 ) {
2414 fReadOnlyx86Stubs
= true;
2416 else if ( strcmp(arg
, "-slow_stubs") == 0 ) {
2419 else if ( strcmp(arg
, "-map") == 0 ) {
2420 fMapPath
= argv
[++i
];
2421 if ( fMapPath
== NULL
)
2422 throw "missing argument to -map";
2424 else if ( strcmp(arg
, "-pie") == 0 ) {
2425 fPositionIndependentExecutable
= true;
2427 else if ( strncmp(arg
, "-reexport-l", 11) == 0 ) {
2428 FileInfo info
= findLibrary(&arg
[11], true);
2429 info
.options
.fReExport
= true;
2432 else if ( strcmp(arg
, "-reexport_library") == 0 ) {
2433 FileInfo info
= findFile(argv
[++i
]);
2434 info
.options
.fReExport
= true;
2437 else if ( strcmp(arg
, "-reexport_framework") == 0 ) {
2438 FileInfo info
= findFramework(argv
[++i
]);
2439 info
.options
.fReExport
= true;
2442 else if ( strcmp(arg
, "-dead_strip_dylibs") == 0 ) {
2443 fDeadStripDylibs
= true;
2445 else if ( strcmp(arg
, "-no_implicit_dylibs") == 0 ) {
2446 fReaderOptions
.fImplicitlyLinkPublicDylibs
= false;
2448 else if ( strcmp(arg
, "-new_linker") == 0 ) {
2451 else if ( strcmp(arg
, "-no_encryption") == 0 ) {
2452 fEncryptable
= false;
2454 else if ( strcmp(arg
, "-no_compact_unwind") == 0 ) {
2455 fReaderOptions
.fAddCompactUnwindEncoding
= false;
2457 else if ( strcmp(arg
, "-mllvm") == 0 ) {
2458 const char* opts
= argv
[++i
];
2460 throw "missing argument to -mllvm";
2461 fLLVMOptions
.push_back(opts
);
2463 else if ( strcmp(arg
, "-no_order_inits") == 0 ) {
2464 fReaderOptions
.fAutoOrderInitializers
= false;
2466 else if ( strcmp(arg
, "-no_order_data") == 0 ) {
2469 else if ( strcmp(arg
, "-seg_page_size") == 0 ) {
2471 seg
.name
= argv
[++i
];
2472 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2473 throw "-seg_page_size missing segName Adddress";
2474 seg
.size
= parseAddress(argv
[++i
]);
2475 uint64_t temp
= seg
.size
& (-4096); // page align
2476 if ( (seg
.size
!= temp
) )
2477 warning("-seg_page_size %s not 4K aligned, rounding down", seg
.name
);
2478 fCustomSegmentSizes
.push_back(seg
);
2480 else if ( strcmp(arg
, "-mark_dead_strippable_dylib") == 0 ) {
2481 fMarkDeadStrippableDylib
= true;
2483 else if ( strcmp(arg
, "-exported_symbols_order") == 0 ) {
2484 loadSymbolOrderFile(argv
[++i
], fExportSymbolsOrder
);
2486 else if ( strcmp(arg
, "-no_compact_linkedit") == 0 ) {
2487 fMakeCompressedDyldInfo
= false;
2489 else if ( strcmp(arg
, "-no_eh_labels") == 0 ) {
2490 fReaderOptions
.fNoEHLabels
= true;
2492 else if ( strcmp(arg
, "-warn_compact_unwind") == 0 ) {
2493 fReaderOptions
.fWarnCompactUnwind
= true;
2495 else if ( strcmp(arg
, "-allow_sub_type_mismatches") == 0 ) {
2496 fAllowCpuSubtypeMismatches
= true;
2498 else if ( strcmp(arg
, "-no_zero_fill_sections") == 0 ) {
2499 fReaderOptions
.fOptimizeZeroFill
= false;
2502 throwf("unknown option: %s", arg
);
2506 FileInfo info
= findFile(arg
);
2507 if ( strcmp(&info
.path
[strlen(info
.path
)-2], ".a") == 0 )
2510 fInputFiles
.push_back(info
);
2514 // if a -lazy option was used, implicitly link in lazydylib1.o
2515 if ( fUsingLazyDylibLinking
) {
2516 addLibrary(findLibrary("lazydylib1.o"));
2523 // -syslibroot <path> is used for SDK support.
2524 // The rule is that all search paths (both explicit and default) are
2525 // checked to see if they exist in the SDK. If so, that path is
2526 // replaced with the sdk prefixed path. If not, that search path
2527 // is used as is. If multiple -syslibroot options are specified
2528 // their directory structures are logically overlayed and files
2529 // from sdks specified earlier on the command line used before later ones.
2531 void Options::buildSearchPaths(int argc
, const char* argv
[])
2533 bool addStandardLibraryDirectories
= true;
2534 std::vector
<const char*> libraryPaths
;
2535 std::vector
<const char*> frameworkPaths
;
2536 libraryPaths
.reserve(10);
2537 frameworkPaths
.reserve(10);
2538 // scan through argv looking for -L, -F, -Z, and -syslibroot options
2539 for(int i
=0; i
< argc
; ++i
) {
2540 if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'L') )
2541 libraryPaths
.push_back(&argv
[i
][2]);
2542 else if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'F') )
2543 frameworkPaths
.push_back(&argv
[i
][2]);
2544 else if ( strcmp(argv
[i
], "-Z") == 0 )
2545 addStandardLibraryDirectories
= false;
2546 else if ( strcmp(argv
[i
], "-v") == 0 ) {
2548 extern const char ldVersionString
[];
2549 fprintf(stderr
, "%s", ldVersionString
);
2550 // if only -v specified, exit cleanly
2553 printLTOVersion(*this);
2558 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
2559 const char* path
= argv
[++i
];
2561 throw "-syslibroot missing argument";
2562 fSDKPaths
.push_back(path
);
2564 else if ( strcmp(argv
[i
], "-search_paths_first") == 0 ) {
2565 // ??? Deprecate when we get -Bstatic/-Bdynamic.
2566 fLibrarySearchMode
= kSearchDylibAndArchiveInEachDir
;
2568 else if ( strcmp(argv
[i
], "-w") == 0 ) {
2569 sEmitWarnings
= false;
2572 int standardLibraryPathsStartIndex
= libraryPaths
.size();
2573 int standardFrameworkPathsStartIndex
= frameworkPaths
.size();
2574 if ( addStandardLibraryDirectories
) {
2575 libraryPaths
.push_back("/usr/lib");
2576 libraryPaths
.push_back("/usr/local/lib");
2578 frameworkPaths
.push_back("/Library/Frameworks/");
2579 frameworkPaths
.push_back("/System/Library/Frameworks/");
2580 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
2583 // <rdar://problem/5829579> Support for configure based hacks
2584 // if last -syslibroot is /, then ignore all syslibroots
2585 if ( fSDKPaths
.size() > 0 ) {
2586 if ( strcmp(fSDKPaths
.back(), "/") == 0 ) {
2591 // now merge sdk and library paths to make real search paths
2592 fLibrarySearchPaths
.reserve(libraryPaths
.size()*(fSDKPaths
.size()+1));
2594 for (std::vector
<const char*>::iterator it
= libraryPaths
.begin(); it
!= libraryPaths
.end(); ++it
, ++libIndex
) {
2595 const char* libDir
= *it
;
2596 bool sdkOverride
= false;
2597 if ( libDir
[0] == '/' ) {
2598 char betterLibDir
[PATH_MAX
];
2599 if ( strstr(libDir
, "/..") != NULL
) {
2600 if ( realpath(libDir
, betterLibDir
) != NULL
)
2601 libDir
= strdup(betterLibDir
);
2603 const int libDirLen
= strlen(libDir
);
2604 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
2605 const char* sdkDir
= *sdkit
;
2606 const int sdkDirLen
= strlen(sdkDir
);
2607 char newPath
[libDirLen
+ sdkDirLen
+4];
2608 strcpy(newPath
, sdkDir
);
2609 if ( newPath
[sdkDirLen
-1] == '/' )
2610 newPath
[sdkDirLen
-1] = '\0';
2611 strcat(newPath
, libDir
);
2612 struct stat statBuffer
;
2613 if ( stat(newPath
, &statBuffer
) == 0 ) {
2614 fLibrarySearchPaths
.push_back(strdup(newPath
));
2619 if ( !sdkOverride
) {
2620 if ( (libIndex
>= standardLibraryPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
2621 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2622 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2625 fLibrarySearchPaths
.push_back(libDir
);
2630 // now merge sdk and framework paths to make real search paths
2631 fFrameworkSearchPaths
.reserve(frameworkPaths
.size()*(fSDKPaths
.size()+1));
2633 for (std::vector
<const char*>::iterator it
= frameworkPaths
.begin(); it
!= frameworkPaths
.end(); ++it
, ++frameIndex
) {
2634 const char* frameworkDir
= *it
;
2635 bool sdkOverride
= false;
2636 if ( frameworkDir
[0] == '/' ) {
2637 char betterFrameworkDir
[PATH_MAX
];
2638 if ( strstr(frameworkDir
, "/..") != NULL
) {
2639 if ( realpath(frameworkDir
, betterFrameworkDir
) != NULL
)
2640 frameworkDir
= strdup(betterFrameworkDir
);
2642 const int frameworkDirLen
= strlen(frameworkDir
);
2643 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
2644 const char* sdkDir
= *sdkit
;
2645 const int sdkDirLen
= strlen(sdkDir
);
2646 char newPath
[frameworkDirLen
+ sdkDirLen
+4];
2647 strcpy(newPath
, sdkDir
);
2648 if ( newPath
[sdkDirLen
-1] == '/' )
2649 newPath
[sdkDirLen
-1] = '\0';
2650 strcat(newPath
, frameworkDir
);
2651 struct stat statBuffer
;
2652 if ( stat(newPath
, &statBuffer
) == 0 ) {
2653 fFrameworkSearchPaths
.push_back(strdup(newPath
));
2658 if ( !sdkOverride
) {
2659 if ( (frameIndex
>= standardFrameworkPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
2660 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2661 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2664 fFrameworkSearchPaths
.push_back(frameworkDir
);
2670 fprintf(stderr
,"Library search paths:\n");
2671 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
2672 it
!= fLibrarySearchPaths
.end();
2674 fprintf(stderr
,"\t%s\n", *it
);
2675 fprintf(stderr
,"Framework search paths:\n");
2676 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
2677 it
!= fFrameworkSearchPaths
.end();
2679 fprintf(stderr
,"\t%s\n", *it
);
2683 // this is run before the command line is parsed
2684 void Options::parsePreCommandLineEnvironmentSettings()
2686 if ((getenv("LD_TRACE_ARCHIVES") != NULL
)
2687 || (getenv("RC_TRACE_ARCHIVES") != NULL
))
2688 fReaderOptions
.fTraceArchives
= true;
2690 if ((getenv("LD_TRACE_DYLIBS") != NULL
)
2691 || (getenv("RC_TRACE_DYLIBS") != NULL
)) {
2692 fReaderOptions
.fTraceDylibs
= true;
2693 fReaderOptions
.fTraceIndirectDylibs
= true;
2696 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL
) {
2697 fTraceDylibSearching
= true;
2700 if (getenv("LD_PRINT_OPTIONS") != NULL
)
2701 fPrintOptions
= true;
2703 if (fReaderOptions
.fTraceDylibs
|| fReaderOptions
.fTraceArchives
)
2704 fReaderOptions
.fTraceOutputFile
= getenv("LD_TRACE_FILE");
2706 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL
)
2707 fPrintOrderFileStatistics
= true;
2709 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL
)
2712 if (getenv("LD_NO_ENCRYPT") != NULL
)
2713 fEncryptable
= false;
2715 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL
)
2716 fAllowCpuSubtypeMismatches
= true;
2718 // for now disable compressed linkedit functionality
2719 if ( getenv("LD_NO_COMPACT_LINKEDIT") != NULL
) {
2720 fMakeCompressedDyldInfo
= false;
2721 fMakeClassicDyldInfo
= true;
2724 sWarningsSideFilePath
= getenv("LD_WARN_FILE");
2728 // this is run after the command line is parsed
2729 void Options::parsePostCommandLineEnvironmentSettings()
2731 // when building a dynamic main executable, default any use of @executable_path to output path
2732 if ( fExecutablePath
== NULL
&& (fOutputKind
== kDynamicExecutable
) ) {
2733 fExecutablePath
= fOutputFile
;
2736 // allow build system to set default seg_addr_table
2737 if ( fSegAddrTablePath
== NULL
)
2738 fSegAddrTablePath
= getenv("LD_SEG_ADDR_TABLE");
2740 // allow build system to turn on prebinding
2742 fPrebind
= ( getenv("LD_PREBIND") != NULL
);
2745 // allow build system to force on dead-code-stripping
2746 if ( fDeadStrip
== kDeadStripOff
) {
2747 if ( getenv("LD_DEAD_STRIP") != NULL
) {
2748 switch (fOutputKind
) {
2749 case Options::kDynamicLibrary
:
2750 case Options::kDynamicExecutable
:
2751 case Options::kDynamicBundle
:
2752 fDeadStrip
= kDeadStripOn
;
2754 case Options::kPreload
:
2755 case Options::kObjectFile
:
2756 case Options::kDyld
:
2757 case Options::kStaticExecutable
:
2758 case Options::kKextBundle
:
2764 // allow build system to force on -warn_commons
2765 if ( getenv("LD_WARN_COMMONS") != NULL
)
2766 fWarnCommons
= true;
2770 void Options::reconfigureDefaults()
2772 // sync reader options
2773 switch ( fOutputKind
) {
2774 case Options::kObjectFile
:
2775 fReaderOptions
.fForFinalLinkedImage
= false;
2777 case Options::kDyld
:
2778 fReaderOptions
.fForDyld
= true;
2779 fReaderOptions
.fForFinalLinkedImage
= true;
2780 fReaderOptions
.fNoEHLabels
= true;
2782 case Options::kDynamicLibrary
:
2783 case Options::kDynamicBundle
:
2784 case Options::kKextBundle
:
2785 fReaderOptions
.fForFinalLinkedImage
= true;
2786 fReaderOptions
.fNoEHLabels
= true;
2788 case Options::kDynamicExecutable
:
2789 case Options::kStaticExecutable
:
2790 case Options::kPreload
:
2791 fReaderOptions
.fLinkingMainExecutable
= true;
2792 fReaderOptions
.fForFinalLinkedImage
= true;
2793 fReaderOptions
.fNoEHLabels
= true;
2797 // set default min OS version
2798 if ( (fReaderOptions
.fMacVersionMin
== ObjectFile::ReaderOptions::kMinMacVersionUnset
)
2799 && (fReaderOptions
.fIPhoneVersionMin
== ObjectFile::ReaderOptions::kMinIPhoneVersionUnset
) ) {
2800 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
2801 const char* macVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
2802 const char* iPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
2803 if ( macVers
!= NULL
)
2804 setMacOSXVersionMin(macVers
);
2805 else if ( iPhoneVers
!= NULL
)
2806 setIPhoneVersionMin(iPhoneVers
);
2808 // if still nothing, set default based on architecture
2809 switch ( fArchitecture
) {
2811 case CPU_TYPE_X86_64
:
2812 case CPU_TYPE_POWERPC
:
2813 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_6
; // FIX FIX, this really should be a check of the OS version the linker is running o
2816 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_0
;
2823 // adjust min based on architecture
2824 switch ( fArchitecture
) {
2826 if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_4
) {
2827 //warning("-macosx_version_min should be 10.4 or later for i386");
2828 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_4
;
2831 case CPU_TYPE_POWERPC64
:
2832 if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_4
) {
2833 //warning("-macosx_version_min should be 10.4 or later for ppc64");
2834 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_4
;
2837 case CPU_TYPE_X86_64
:
2838 if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_4
) {
2839 //warning("-macosx_version_min should be 10.4 or later for x86_64");
2840 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_4
;
2845 // adjust kext type based on architecture
2846 if ( fOutputKind
== kKextBundle
) {
2847 switch ( fArchitecture
) {
2848 case CPU_TYPE_X86_64
:
2849 // x86_64 uses new MH_KEXT_BUNDLE type
2850 fMakeClassicDyldInfo
= true;
2851 fMakeCompressedDyldInfo
= false;
2852 fAllowTextRelocs
= true;
2853 fUndefinedTreatment
= kUndefinedDynamicLookup
;
2855 case CPU_TYPE_POWERPC
:
2859 fOutputKind
= kObjectFile
;
2864 // disable implicit dylibs when targeting 10.3
2865 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
2866 if ( !minOS(ObjectFile::ReaderOptions::k10_4
, ObjectFile::ReaderOptions::k2_0
) )
2867 fReaderOptions
.fImplicitlyLinkPublicDylibs
= false;
2870 // allow build system to force linker to ignore -prebind
2871 if ( getenv("LD_FORCE_NO_PREBIND") != NULL
)
2874 // allow build system to force linker to ignore -seg_addr_table
2875 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL
)
2876 fSegAddrTablePath
= NULL
;
2878 // check for base address specified externally
2879 if ( (fSegAddrTablePath
!= NULL
) && (fOutputKind
== Options::kDynamicLibrary
) ) {
2880 parseSegAddrTable(fSegAddrTablePath
, this->installPath());
2881 // HACK to support seg_addr_table entries that are physical paths instead of install paths
2882 if ( fBaseAddress
== 0 ) {
2883 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
2884 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.4.dylib");
2885 if ( fBaseAddress
== 0 )
2886 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.9.dylib");
2889 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
2890 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libz.1.2.3.dylib");
2892 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
2893 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libutil1.0.dylib");
2897 // split segs only allowed for dylibs
2899 // split seg only supported for ppc, i386, and arm.
2900 switch ( fArchitecture
) {
2901 case CPU_TYPE_POWERPC
:
2903 if ( fOutputKind
!= Options::kDynamicLibrary
)
2905 // make sure read and write segments are proper distance apart
2906 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x10000000) )
2907 fBaseWritableAddress
= fBaseAddress
+ 0x10000000;
2910 if ( fOutputKind
!= Options::kDynamicLibrary
) {
2914 // make sure read and write segments are proper distance apart
2915 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x08000000) )
2916 fBaseWritableAddress
= fBaseAddress
+ 0x08000000;
2922 fBaseWritableAddress
= 0;
2926 // <rdar://problem/6138961> -r implies no prebinding for all architectures
2927 if ( fOutputKind
== Options::kObjectFile
)
2930 // disable prebinding depending on arch and min OS version
2932 switch ( fArchitecture
) {
2933 case CPU_TYPE_POWERPC
:
2935 if ( fReaderOptions
.fMacVersionMin
== ObjectFile::ReaderOptions::k10_4
) {
2936 // in 10.4 only split seg dylibs are prebound
2937 if ( (fOutputKind
!= Options::kDynamicLibrary
) || ! fSplitSegs
)
2940 else if ( fReaderOptions
.fMacVersionMin
>= ObjectFile::ReaderOptions::k10_5
) {
2941 // in 10.5 nothing is prebound
2945 // in 10.3 and earlier only dylibs and main executables could be prebound
2946 switch ( fOutputKind
) {
2947 case Options::kDynamicExecutable
:
2948 case Options::kDynamicLibrary
:
2949 // only main executables and dylibs can be prebound
2951 case Options::kStaticExecutable
:
2952 case Options::kDynamicBundle
:
2953 case Options::kObjectFile
:
2954 case Options::kDyld
:
2955 case Options::kPreload
:
2956 case Options::kKextBundle
:
2957 // disable prebinding for everything else
2963 case CPU_TYPE_POWERPC64
:
2964 case CPU_TYPE_X86_64
:
2968 switch ( fOutputKind
) {
2969 case Options::kDynamicExecutable
:
2970 case Options::kDynamicLibrary
:
2971 // only main executables and dylibs can be prebound
2973 case Options::kStaticExecutable
:
2974 case Options::kDynamicBundle
:
2975 case Options::kObjectFile
:
2976 case Options::kDyld
:
2977 case Options::kPreload
:
2978 case Options::kKextBundle
:
2979 // disable prebinding for everything else
2987 // only prebound images can be split-seg
2988 if ( fSplitSegs
&& !fPrebind
)
2991 // determine if info for shared region should be added
2992 if ( fOutputKind
== Options::kDynamicLibrary
) {
2993 if ( minOS(ObjectFile::ReaderOptions::k10_5
, ObjectFile::ReaderOptions::k3_1
) )
2995 if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
2996 || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
2997 fSharedRegionEligible
= true;
3000 // figure out if module table is needed for compatibility with old ld/dyld
3001 if ( fOutputKind
== Options::kDynamicLibrary
) {
3002 switch ( fArchitecture
) {
3003 case CPU_TYPE_POWERPC
: // 10.3 and earlier dyld requires a module table
3004 case CPU_TYPE_I386
: // ld_classic for 10.4.x requires a module table
3005 if ( fReaderOptions
.fMacVersionMin
<= ObjectFile::ReaderOptions::k10_5
)
3006 fNeedsModuleTable
= true;
3010 fNeedsModuleTable
= true; // redo_prebinding requires a module table
3015 // <rdar://problem/5366363> -r -x implies -S
3016 if ( (fOutputKind
== Options::kObjectFile
) && (fLocalSymbolHandling
== kLocalSymbolsNone
) )
3017 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
3019 // choose how to process unwind info
3020 switch ( fArchitecture
) {
3022 case CPU_TYPE_X86_64
:
3023 switch ( fOutputKind
) {
3024 case Options::kObjectFile
:
3025 case Options::kStaticExecutable
:
3026 case Options::kPreload
:
3027 case Options::kKextBundle
:
3028 fReaderOptions
.fAddCompactUnwindEncoding
= false;
3030 case Options::kDyld
:
3031 case Options::kDynamicLibrary
:
3032 case Options::kDynamicBundle
:
3033 case Options::kDynamicExecutable
:
3034 //if ( fReaderOptions.fAddCompactUnwindEncoding && (fReaderOptions.fVersionMin >= ObjectFile::ReaderOptions::k10_6) )
3035 // fReaderOptions.fRemoveDwarfUnwindIfCompactExists = true;
3039 case CPU_TYPE_POWERPC
:
3040 case CPU_TYPE_POWERPC64
:
3042 fReaderOptions
.fAddCompactUnwindEncoding
= false;
3043 fReaderOptions
.fRemoveDwarfUnwindIfCompactExists
= false;
3046 // if -arch is missing, assume we don't want compact unwind info
3047 fReaderOptions
.fAddCompactUnwindEncoding
= false;
3051 // only ARM main executables can be encrypted
3052 if ( fOutputKind
!= Options::kDynamicExecutable
)
3053 fEncryptable
= false;
3054 if ( fArchitecture
!= CPU_TYPE_ARM
)
3055 fEncryptable
= false;
3057 // don't move inits in dyld because dyld wants certain
3058 // entries point at stable locations at the start of __text
3059 if ( fOutputKind
== Options::kDyld
)
3060 fReaderOptions
.fAutoOrderInitializers
= false;
3063 // disable __data ordering for some output kinds
3064 switch ( fOutputKind
) {
3065 case Options::kObjectFile
:
3066 case Options::kDyld
:
3067 case Options::kStaticExecutable
:
3068 case Options::kPreload
:
3069 case Options::kKextBundle
:
3072 case Options::kDynamicExecutable
:
3073 case Options::kDynamicLibrary
:
3074 case Options::kDynamicBundle
:
3078 // only use compressed LINKEDIT for:
3079 // x86_64 and i386 on Mac OS X 10.6 or later
3080 // arm on iPhoneOS 3.1 or later
3081 if ( fMakeCompressedDyldInfo
) {
3082 switch (fArchitecture
) {
3084 case CPU_TYPE_X86_64
:
3085 if ( fReaderOptions
.fMacVersionMin
>= ObjectFile::ReaderOptions::k10_6
)
3086 fMakeClassicDyldInfo
= false;
3087 else if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_5
)
3088 fMakeCompressedDyldInfo
= false;
3091 if ( fReaderOptions
.fIPhoneVersionMin
>= ObjectFile::ReaderOptions::k3_1
)
3092 fMakeClassicDyldInfo
= false;
3093 else if ( fReaderOptions
.fIPhoneVersionMin
< ObjectFile::ReaderOptions::k3_1
)
3094 fMakeCompressedDyldInfo
= false;
3096 case CPU_TYPE_POWERPC
:
3097 case CPU_TYPE_POWERPC64
:
3099 fMakeCompressedDyldInfo
= false;
3104 // only use compressed LINKEDIT for final linked images
3105 if ( fMakeCompressedDyldInfo
) {
3106 switch ( fOutputKind
) {
3107 case Options::kDynamicExecutable
:
3108 case Options::kDynamicLibrary
:
3109 case Options::kDynamicBundle
:
3111 case Options::kPreload
:
3112 case Options::kStaticExecutable
:
3113 case Options::kObjectFile
:
3114 case Options::kDyld
:
3115 case Options::kKextBundle
:
3116 fMakeCompressedDyldInfo
= false;
3120 fReaderOptions
.fMakeCompressedDyldInfo
= fMakeCompressedDyldInfo
;
3122 // only ARM enforces that cpu-sub-types must match
3123 if ( fArchitecture
!= CPU_TYPE_ARM
)
3124 fAllowCpuSubtypeMismatches
= true;
3126 // only final linked images can not optimize zero fill sections
3127 if ( fOutputKind
== Options::kObjectFile
)
3128 fReaderOptions
.fOptimizeZeroFill
= true;
3130 // only dynamic final linked images should warn about use of commmons
3131 if ( fWarnCommons
) {
3132 switch ( fOutputKind
) {
3133 case Options::kDynamicExecutable
:
3134 case Options::kDynamicLibrary
:
3135 case Options::kDynamicBundle
:
3137 case Options::kPreload
:
3138 case Options::kStaticExecutable
:
3139 case Options::kObjectFile
:
3140 case Options::kDyld
:
3141 case Options::kKextBundle
:
3142 fWarnCommons
= false;
3147 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
3148 if ( minOS(ObjectFile::ReaderOptions::k10_5
, ObjectFile::ReaderOptions::k2_0
) )
3149 fUseSimplifiedDylibReExports
= true;
3152 void Options::checkIllegalOptionCombinations()
3154 // check -undefined setting
3155 switch ( fUndefinedTreatment
) {
3156 case kUndefinedError
:
3157 case kUndefinedDynamicLookup
:
3160 case kUndefinedWarning
:
3161 case kUndefinedSuppress
:
3162 // requires flat namespace
3163 if ( fNameSpace
== kTwoLevelNameSpace
)
3164 throw "can't use -undefined warning or suppress with -twolevel_namespace";
3168 // unify -sub_umbrella with dylibs
3169 for (std::vector
<const char*>::iterator it
= fSubUmbellas
.begin(); it
!= fSubUmbellas
.end(); it
++) {
3170 const char* subUmbrella
= *it
;
3172 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
3173 Options::FileInfo
& info
= *fit
;
3174 const char* lastSlash
= strrchr(info
.path
, '/');
3175 if ( lastSlash
== NULL
)
3176 lastSlash
= info
.path
- 1;
3177 if ( strcmp(&lastSlash
[1], subUmbrella
) == 0 ) {
3178 info
.options
.fReExport
= true;
3184 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella
);
3187 // unify -sub_library with dylibs
3188 for (std::vector
<const char*>::iterator it
= fSubLibraries
.begin(); it
!= fSubLibraries
.end(); it
++) {
3189 const char* subLibrary
= *it
;
3191 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
3192 Options::FileInfo
& info
= *fit
;
3193 const char* lastSlash
= strrchr(info
.path
, '/');
3194 if ( lastSlash
== NULL
)
3195 lastSlash
= info
.path
- 1;
3196 const char* dot
= strchr(&lastSlash
[1], '.');
3198 dot
= &lastSlash
[strlen(lastSlash
)];
3199 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
3200 info
.options
.fReExport
= true;
3206 warning("-sub_library %s does not match a supplied dylib", subLibrary
);
3209 // sync reader options
3210 if ( fNameSpace
!= kTwoLevelNameSpace
)
3211 fReaderOptions
.fFlatNamespace
= true;
3213 // check -stack_addr
3214 if ( fStackAddr
!= 0 ) {
3215 switch (fArchitecture
) {
3217 case CPU_TYPE_POWERPC
:
3219 if ( fStackAddr
> 0xFFFFFFFF )
3220 throw "-stack_addr must be < 4G for 32-bit processes";
3222 case CPU_TYPE_POWERPC64
:
3223 case CPU_TYPE_X86_64
:
3226 if ( (fStackAddr
& -4096) != fStackAddr
)
3227 throw "-stack_addr must be multiples of 4K";
3228 if ( fStackSize
== 0 )
3229 throw "-stack_addr must be used with -stack_size";
3232 // check -stack_size
3233 if ( fStackSize
!= 0 ) {
3234 switch (fArchitecture
) {
3236 case CPU_TYPE_POWERPC
:
3237 if ( fStackSize
> 0xFFFFFFFF )
3238 throw "-stack_size must be < 4G for 32-bit processes";
3239 if ( fStackAddr
== 0 ) {
3240 fStackAddr
= 0xC0000000;
3242 if ( (fStackAddr
> 0xB0000000) && ((fStackAddr
-fStackSize
) < 0xB0000000) )
3243 warning("custom stack placement overlaps and will disable shared region");
3246 if ( fStackSize
> 0x2F000000 )
3247 throw "-stack_size must be < 752MB";
3248 if ( fStackAddr
== 0 )
3249 fStackAddr
= 0x2F000000;
3250 if ( fStackAddr
> 0x30000000)
3251 throw "-stack_addr must be < 0x30000000 for arm";
3252 case CPU_TYPE_POWERPC64
:
3253 case CPU_TYPE_X86_64
:
3254 if ( fStackAddr
== 0 ) {
3255 fStackAddr
= 0x00007FFF5C000000LL
;
3259 if ( (fStackSize
& -4096) != fStackSize
)
3260 throw "-stack_size must be multiples of 4K";
3261 switch ( fOutputKind
) {
3262 case Options::kDynamicExecutable
:
3263 case Options::kStaticExecutable
:
3264 // custom stack size only legal when building main executable
3266 case Options::kDynamicLibrary
:
3267 case Options::kDynamicBundle
:
3268 case Options::kObjectFile
:
3269 case Options::kDyld
:
3270 case Options::kPreload
:
3271 case Options::kKextBundle
:
3272 throw "-stack_size option can only be used when linking a main executable";
3276 // check that -allow_stack_execute is only used with main executables
3277 if ( fExecutableStack
) {
3278 switch ( fOutputKind
) {
3279 case Options::kDynamicExecutable
:
3280 case Options::kStaticExecutable
:
3281 // -allow_stack_execute size only legal when building main executable
3283 case Options::kDynamicLibrary
:
3284 case Options::kDynamicBundle
:
3285 case Options::kObjectFile
:
3286 case Options::kDyld
:
3287 case Options::kPreload
:
3288 case Options::kKextBundle
:
3289 throw "-allow_stack_execute option can only be used when linking a main executable";
3293 // check -client_name is only used when making a bundle or main executable
3294 if ( fClientName
!= NULL
) {
3295 switch ( fOutputKind
) {
3296 case Options::kDynamicExecutable
:
3297 case Options::kDynamicBundle
:
3299 case Options::kStaticExecutable
:
3300 case Options::kDynamicLibrary
:
3301 case Options::kObjectFile
:
3302 case Options::kDyld
:
3303 case Options::kPreload
:
3304 case Options::kKextBundle
:
3305 throw "-client_name can only be used with -bundle";
3309 // check -init is only used when building a dylib
3310 if ( (fInitFunctionName
!= NULL
) && (fOutputKind
!= Options::kDynamicLibrary
) )
3311 throw "-init can only be used with -dynamiclib";
3313 // check -bundle_loader only used with -bundle
3314 if ( (fBundleLoader
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
3315 throw "-bundle_loader can only be used with -bundle";
3317 // check -dtrace not used with -r
3318 if ( (fDtraceScriptName
!= NULL
) && (fOutputKind
== Options::kObjectFile
) )
3319 throw "-dtrace can only be used when creating final linked images";
3321 // check -d can only be used with -r
3322 if ( fReaderOptions
.fMakeTentativeDefinitionsReal
&& (fOutputKind
!= Options::kObjectFile
) )
3323 throw "-d can only be used with -r";
3325 // check that -root_safe is not used with -r
3326 if ( fReaderOptions
.fRootSafe
&& (fOutputKind
== Options::kObjectFile
) )
3327 throw "-root_safe cannot be used with -r";
3329 // check that -setuid_safe is not used with -r
3330 if ( fReaderOptions
.fSetuidSafe
&& (fOutputKind
== Options::kObjectFile
) )
3331 throw "-setuid_safe cannot be used with -r";
3333 // make sure all required exported symbols exist
3334 std::vector
<const char*> impliedExports
;
3335 for (NameSet::iterator it
=fExportSymbols
.regularBegin(); it
!= fExportSymbols
.regularEnd(); it
++) {
3336 const char* name
= *it
;
3337 // never export .eh symbols
3338 const int len
= strlen(name
);
3339 if ( (strcmp(&name
[len
-3], ".eh") == 0) || (strncmp(name
, ".objc_category_name_", 20) == 0) )
3340 warning("ignoring %s in export list", name
);
3342 fInitialUndefines
.push_back(name
);
3343 if ( strncmp(name
, ".objc_class_name_", 17) == 0 ) {
3344 // rdar://problem/4718189 map ObjC class names to new runtime names
3345 switch (fArchitecture
) {
3346 case CPU_TYPE_POWERPC64
:
3347 case CPU_TYPE_X86_64
:
3350 asprintf(&temp
, "_OBJC_CLASS_$_%s", &name
[17]);
3351 impliedExports
.push_back(temp
);
3352 asprintf(&temp
, "_OBJC_METACLASS_$_%s", &name
[17]);
3353 impliedExports
.push_back(temp
);
3358 for (std::vector
<const char*>::iterator it
=impliedExports
.begin(); it
!= impliedExports
.end(); it
++) {
3359 const char* name
= *it
;
3360 fExportSymbols
.insert(name
);
3361 fInitialUndefines
.push_back(name
);
3364 // make sure that -init symbol exist
3365 if ( fInitFunctionName
!= NULL
)
3366 fInitialUndefines
.push_back(fInitFunctionName
);
3368 // check custom segments
3369 if ( fCustomSegmentAddresses
.size() != 0 ) {
3370 // verify no segment is in zero page
3371 if ( fZeroPageSize
!= ULLONG_MAX
) {
3372 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
3373 if ( (it
->address
>= 0) && (it
->address
< fZeroPageSize
) )
3374 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it
->name
, it
->address
);
3377 // verify no duplicates
3378 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
3379 for (std::vector
<SegmentStart
>::iterator it2
= fCustomSegmentAddresses
.begin(); it2
!= fCustomSegmentAddresses
.end(); ++it2
) {
3380 if ( (it
->address
== it2
->address
) && (it
!= it2
) )
3381 throwf("duplicate -segaddr addresses for %s and %s", it
->name
, it2
->name
);
3383 // a custom segment address of zero will disable the use of a zero page
3384 if ( it
->address
== 0 )
3389 if ( fZeroPageSize
== ULLONG_MAX
) {
3390 // zero page size not specified on command line, set default
3391 switch (fArchitecture
) {
3393 case CPU_TYPE_POWERPC
:
3395 // first 4KB for 32-bit architectures
3396 fZeroPageSize
= 0x1000;
3398 case CPU_TYPE_POWERPC64
:
3399 // first 4GB for ppc64 on 10.5
3400 if ( fReaderOptions
.fMacVersionMin
>= ObjectFile::ReaderOptions::k10_5
)
3401 fZeroPageSize
= 0x100000000ULL
;
3403 fZeroPageSize
= 0x1000; // 10.4 dyld may not be able to handle >4GB zero page
3405 case CPU_TYPE_X86_64
:
3406 // first 4GB for x86_64 on all OS's
3407 fZeroPageSize
= 0x100000000ULL
;
3410 // if -arch not used, default to 4K zero-page
3411 fZeroPageSize
= 0x1000;
3415 switch ( fOutputKind
) {
3416 case Options::kDynamicExecutable
:
3417 case Options::kStaticExecutable
:
3418 // -pagezero_size size only legal when building main executable
3420 case Options::kDynamicLibrary
:
3421 case Options::kDynamicBundle
:
3422 case Options::kObjectFile
:
3423 case Options::kDyld
:
3424 case Options::kPreload
:
3425 case Options::kKextBundle
:
3426 if ( fZeroPageSize
!= 0 )
3427 throw "-pagezero_size option can only be used when linking a main executable";
3431 // -dead_strip and -r are incompatible
3432 if ( (fDeadStrip
!= kDeadStripOff
) && (fOutputKind
== Options::kObjectFile
) )
3433 throw "-r and -dead_strip cannot be used together";
3435 // can't use -rpath unless targeting 10.5 or later
3436 if ( fRPaths
.size() > 0 ) {
3437 if ( !minOS(ObjectFile::ReaderOptions::k10_5
, ObjectFile::ReaderOptions::k2_0
) )
3438 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
3439 switch ( fOutputKind
) {
3440 case Options::kDynamicExecutable
:
3441 case Options::kDynamicLibrary
:
3442 case Options::kDynamicBundle
:
3444 case Options::kStaticExecutable
:
3445 case Options::kObjectFile
:
3446 case Options::kDyld
:
3447 case Options::kPreload
:
3448 case Options::kKextBundle
:
3449 throw "-rpath can only be used when creating a dynamic final linked image";
3453 // check -pie is only used when building a dynamic main executable for 10.5
3454 if ( fPositionIndependentExecutable
) {
3455 switch ( fOutputKind
) {
3456 case Options::kDynamicExecutable
:
3457 case Options::kPreload
:
3459 case Options::kDynamicLibrary
:
3460 case Options::kDynamicBundle
:
3461 warning("-pie being ignored. It is only used when linking a main executable");
3463 case Options::kStaticExecutable
:
3464 case Options::kObjectFile
:
3465 case Options::kDyld
:
3466 case Options::kKextBundle
:
3467 throw "-pie can only be used when linking a main executable";
3469 if ( !minOS(ObjectFile::ReaderOptions::k10_5
, ObjectFile::ReaderOptions::k2_0
) )
3470 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
3473 // check -read_only_relocs is not used with x86_64
3474 if ( fAllowTextRelocs
) {
3475 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
!= kKextBundle
) ) {
3476 warning("-read_only_relocs cannot be used with x86_64");
3477 fAllowTextRelocs
= false;
3481 // check -mark_auto_dead_strip is only used with dylibs
3482 if ( fMarkDeadStrippableDylib
) {
3483 if ( fOutputKind
!= Options::kDynamicLibrary
) {
3484 warning("-mark_auto_dead_strip can only be used when creating a dylib");
3485 fMarkDeadStrippableDylib
= false;
3489 // -force_cpusubtype_ALL is not supported for ARM
3490 if ( fForceSubtypeAll
) {
3491 if ( fArchitecture
== CPU_TYPE_ARM
) {
3492 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
3498 void Options::checkForClassic(int argc
, const char* argv
[])
3501 bool archFound
= false;
3502 bool staticFound
= false;
3503 bool dtraceFound
= false;
3504 bool kextFound
= false;
3505 bool rFound
= false;
3506 bool creatingMachKernel
= false;
3507 bool newLinker
= false;
3509 // build command line buffer in case ld crashes
3510 for(int i
=1; i
< argc
; ++i
) {
3511 strlcat(crashreporterBuffer
, argv
[i
], 1000);
3512 strlcat(crashreporterBuffer
, " ", 1000);
3515 for(int i
=0; i
< argc
; ++i
) {
3516 const char* arg
= argv
[i
];
3517 if ( arg
[0] == '-' ) {
3518 if ( strcmp(arg
, "-arch") == 0 ) {
3519 parseArch(argv
[++i
]);
3522 else if ( strcmp(arg
, "-static") == 0 ) {
3525 else if ( strcmp(arg
, "-kext") == 0 ) {
3528 else if ( strcmp(arg
, "-dtrace") == 0 ) {
3531 else if ( strcmp(arg
, "-r") == 0 ) {
3534 else if ( strcmp(arg
, "-new_linker") == 0 ) {
3537 else if ( strcmp(arg
, "-classic_linker") == 0 ) {
3538 // ld_classic does not understand this option, so remove it
3539 for(int j
=i
; j
< argc
; ++j
)
3540 argv
[j
] = argv
[j
+1];
3541 this->gotoClassicLinker(argc
-1, argv
);
3543 else if ( strcmp(arg
, "-o") == 0 ) {
3544 const char* outfile
= argv
[++i
];
3545 if ( (outfile
!= NULL
) && (strstr(outfile
, "/mach_kernel") != NULL
) )
3546 creatingMachKernel
= true;
3551 // -dtrace only supported by new linker
3556 switch ( fArchitecture
) {
3557 case CPU_TYPE_POWERPC
:
3560 // if ( staticFound && (rFound || !creatingMachKernel) ) {
3561 if ( (staticFound
|| kextFound
) && !newLinker
) {
3562 // this environment variable will disable use of ld_classic for -static links
3563 if ( getenv("LD_NO_CLASSIC_LINKER_STATIC") == NULL
) {
3564 // ld_classic does not support -iphoneos_version_min, so change
3565 for(int j
=0; j
< argc
; ++j
) {
3566 if ( strcmp(argv
[j
], "-iphoneos_version_min") == 0) {
3567 argv
[j
] = "-macosx_version_min";
3573 // ld classic does not understand -kext (change to -static -r)
3575 for(int j
=0; j
< argc
; ++j
) {
3576 if ( strcmp(argv
[j
], "-kext") == 0)
3578 else if ( strcmp(argv
[j
], "-dynamic") == 0)
3579 argv
[j
] = "-static";
3582 this->gotoClassicLinker(argc
, argv
);
3589 // work around for VSPTool
3591 this->gotoClassicLinker(argc
, argv
);
3596 void Options::gotoClassicLinker(int argc
, const char* argv
[])
3598 argv
[0] = "ld_classic";
3599 char rawPath
[PATH_MAX
];
3600 char path
[PATH_MAX
];
3601 uint32_t bufSize
= PATH_MAX
;
3602 if ( _NSGetExecutablePath(rawPath
, &bufSize
) != -1 ) {
3603 if ( realpath(rawPath
, path
) != NULL
) {
3604 char* lastSlash
= strrchr(path
, '/');
3605 if ( lastSlash
!= NULL
) {
3606 strcpy(lastSlash
+1, "ld_classic");
3608 execvp(path
, (char**)argv
);
3612 // in case of error in above, try searching for ld_classic via PATH
3613 execvp(argv
[0], (char**)argv
);
3614 fprintf(stderr
, "can't exec ld_classic\n");