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') && (version
[2] == '0') )
1273 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_0
;
1274 else if ( (version
[0] == '2') && (version
[2] == '1') )
1275 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_1
;
1276 else if ( (version
[0] == '2') && (version
[2] >= '2') )
1277 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_2
;
1278 else if ( (version
[0] == '3') && (version
[2] == '0') )
1279 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k3_0
;
1280 else if ( (version
[0] == '3') && (version
[2] == '1') )
1281 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k3_1
;
1282 else if ( (version
[0] == '3') && (version
[2] >= '2') )
1283 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k3_2
;
1284 else if ( (version
[0] >= '4') )
1285 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k4_0
;
1287 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_0
;
1288 warning("unknown option to -iphoneos_version_min, not 2.x, 3.x, or 4.x");
1292 bool Options::minOS(ObjectFile::ReaderOptions::MacVersionMin requiredMacMin
, ObjectFile::ReaderOptions::IPhoneVersionMin requirediPhoneOSMin
)
1294 if ( fReaderOptions
.fMacVersionMin
!= ObjectFile::ReaderOptions::kMinMacVersionUnset
) {
1295 return ( fReaderOptions
.fMacVersionMin
>= requiredMacMin
);
1298 return ( fReaderOptions
.fIPhoneVersionMin
>= requirediPhoneOSMin
);
1303 void Options::setWeakReferenceMismatchTreatment(const char* treatment
)
1305 if ( treatment
== NULL
)
1306 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1308 if ( strcmp(treatment
, "error") == 0 )
1309 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchError
;
1310 else if ( strcmp(treatment
, "weak") == 0 )
1311 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchWeak
;
1312 else if ( strcmp(treatment
, "non-weak") == 0 )
1313 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchNonWeak
;
1315 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1318 Options::CommonsMode
Options::parseCommonsTreatment(const char* mode
)
1321 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1323 if ( strcmp(mode
, "ignore_dylibs") == 0 )
1324 return kCommonsIgnoreDylibs
;
1325 else if ( strcmp(mode
, "use_dylibs") == 0 )
1326 return kCommonsOverriddenByDylibs
;
1327 else if ( strcmp(mode
, "error") == 0 )
1328 return kCommonsConflictsDylibsError
;
1330 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1333 void Options::addDylibOverride(const char* paths
)
1335 if ( paths
== NULL
)
1336 throw "-dylib_file must followed by two colon separated paths";
1337 const char* colon
= strchr(paths
, ':');
1338 if ( colon
== NULL
)
1339 throw "-dylib_file must followed by two colon separated paths";
1340 int len
= colon
-paths
;
1341 char* target
= new char[len
+2];
1342 strncpy(target
, paths
, len
);
1344 DylibOverride entry
;
1345 entry
.installName
= target
;
1346 entry
.useInstead
= &colon
[1];
1347 fDylibOverrides
.push_back(entry
);
1350 uint64_t Options::parseAddress(const char* addr
)
1353 uint64_t result
= strtoull(addr
, &endptr
, 16);
1357 uint32_t Options::parseProtection(const char* prot
)
1359 uint32_t result
= 0;
1360 for(const char* p
= prot
; *p
!= '\0'; ++p
) {
1361 switch(tolower(*p
)) {
1363 result
|= VM_PROT_READ
;
1366 result
|= VM_PROT_WRITE
;
1369 result
|= VM_PROT_EXECUTE
;
1374 throwf("unknown -segprot lettter in %s", prot
);
1383 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1386 uint32_t Options::parseVersionNumber(const char* versionString
)
1388 unsigned long x
= 0;
1389 unsigned long y
= 0;
1390 unsigned long z
= 0;
1392 x
= strtoul(versionString
, &end
, 10);
1393 if ( *end
== '.' ) {
1394 y
= strtoul(&end
[1], &end
, 10);
1395 if ( *end
== '.' ) {
1396 z
= strtoul(&end
[1], &end
, 10);
1399 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
1400 throwf("malformed version number: %s", versionString
);
1402 return (x
<< 16) | ( y
<< 8 ) | z
;
1405 static const char* cstringSymbolName(const char* orderFileString
)
1408 asprintf(&result
, "cstring=%s", orderFileString
);
1409 // convert escaped characters
1411 for(const char* s
=result
; *s
!= '\0'; ++s
, ++d
) {
1449 // hexadecimal value of char
1453 while ( isxdigit(*s
) ) {
1458 value
+= ((toupper(*s
)-'A') + 10);
1465 if ( isdigit(*s
) ) {
1466 // octal value of char
1468 while ( isdigit(*s
) ) {
1469 value
= (value
<< 3) + (*s
-'0');
1484 void Options::parseOrderFile(const char* path
, bool cstring
)
1486 // order files override auto-ordering
1487 fReaderOptions
.fAutoOrderInitializers
= false;
1489 // read in whole file
1490 int fd
= ::open(path
, O_RDONLY
, 0);
1492 throwf("can't open order file: %s", path
);
1493 struct stat stat_buf
;
1494 ::fstat(fd
, &stat_buf
);
1495 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1497 throwf("can't process order file: %s", path
);
1498 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1499 throwf("can't read order file: %s", path
);
1501 p
[stat_buf
.st_size
] = '\n';
1503 // parse into vector of pairs
1504 char * const end
= &p
[stat_buf
.st_size
+1];
1505 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1506 char* symbolStart
= NULL
;
1507 for (char* s
= p
; s
< end
; ++s
) {
1513 else if ( !isspace(*s
) || cstring
) {
1519 if ( (*s
== '\n') || (!cstring
&& (*s
== '#')) ) {
1520 bool wasComment
= (*s
== '#');
1522 // removing any trailing spaces
1524 while ( isspace(*last
) ) {
1528 if ( strncmp(symbolStart
, "ppc:", 4) == 0 ) {
1529 if ( fArchitecture
== CPU_TYPE_POWERPC
)
1530 symbolStart
= &symbolStart
[4];
1534 // if there is an architecture prefix, only use this symbol it if matches current arch
1535 else if ( strncmp(symbolStart
, "ppc64:", 6) == 0 ) {
1536 if ( fArchitecture
== CPU_TYPE_POWERPC64
)
1537 symbolStart
= &symbolStart
[6];
1541 else if ( strncmp(symbolStart
, "i386:", 5) == 0 ) {
1542 if ( fArchitecture
== CPU_TYPE_I386
)
1543 symbolStart
= &symbolStart
[5];
1547 else if ( strncmp(symbolStart
, "x86_64:", 7) == 0 ) {
1548 if ( fArchitecture
== CPU_TYPE_X86_64
)
1549 symbolStart
= &symbolStart
[7];
1553 else if ( strncmp(symbolStart
, "arm:", 4) == 0 ) {
1554 if ( fArchitecture
== CPU_TYPE_ARM
)
1555 symbolStart
= &symbolStart
[4];
1559 if ( symbolStart
!= NULL
) {
1560 char* objFileName
= NULL
;
1561 char* colon
= strstr(symbolStart
, ".o:");
1562 if ( colon
!= NULL
) {
1564 objFileName
= symbolStart
;
1565 symbolStart
= &colon
[3];
1567 // trim leading spaces
1568 while ( isspace(*symbolStart
) )
1570 Options::OrderedSymbol pair
;
1572 pair
.symbolName
= cstringSymbolName(symbolStart
);
1574 pair
.symbolName
= symbolStart
;
1575 pair
.objectFileName
= objFileName
;
1576 fOrderedSymbols
.push_back(pair
);
1591 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1594 void Options::parseSectionOrderFile(const char* segment
, const char* section
, const char* path
)
1596 if ( (strcmp(section
, "__cstring") == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1597 parseOrderFile(path
, true);
1599 else if ( (strncmp(section
, "__literal",9) == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1600 warning("sorting of __literal[4,8,16] sections not supported");
1603 // ignore section information and append all symbol names to global order file
1604 parseOrderFile(path
, false);
1608 void Options::addSection(const char* segment
, const char* section
, const char* path
)
1610 if ( strlen(segment
) > 16 )
1611 throw "-seccreate segment name max 16 chars";
1612 if ( strlen(section
) > 16 ) {
1613 char* tmp
= strdup(section
);
1615 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section
, tmp
);
1619 // read in whole file
1620 int fd
= ::open(path
, O_RDONLY
, 0);
1622 throwf("can't open -sectcreate file: %s", path
);
1623 struct stat stat_buf
;
1624 ::fstat(fd
, &stat_buf
);
1625 char* p
= (char*)malloc(stat_buf
.st_size
);
1627 throwf("can't process -sectcreate file: %s", path
);
1628 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1629 throwf("can't read -sectcreate file: %s", path
);
1632 // record section to create
1633 ExtraSection info
= { segment
, section
, path
, (uint8_t*)p
, stat_buf
.st_size
};
1634 fExtraSections
.push_back(info
);
1637 void Options::addSectionAlignment(const char* segment
, const char* section
, const char* alignmentStr
)
1639 if ( strlen(segment
) > 16 )
1640 throw "-sectalign segment name max 16 chars";
1641 if ( strlen(section
) > 16 )
1642 throw "-sectalign section name max 16 chars";
1644 // argument to -sectalign is a hexadecimal number
1646 unsigned long value
= strtoul(alignmentStr
, &endptr
, 16);
1647 if ( *endptr
!= '\0')
1648 throw "argument for -sectalign is not a hexadecimal number";
1649 if ( value
> 0x8000 )
1650 throw "argument for -sectalign must be less than or equal to 0x8000";
1652 warning("zero is not a valid -sectalign");
1656 // alignment is power of 2 (e.g. page alignment = 12)
1657 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
1658 if ( (unsigned long)(1 << alignment
) != value
) {
1659 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
1660 segment
, section
, 1 << alignment
);
1663 SectionAlignment info
= { segment
, section
, alignment
};
1664 fSectionAlignments
.push_back(info
);
1667 void Options::addLibrary(const FileInfo
& info
)
1669 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
1670 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
1671 if ( strcmp(info
.path
, fit
->path
) == 0 ) {
1672 // if dylib is specified again but weak, record that it should be weak
1673 if ( info
.options
.fWeakImport
)
1674 fit
->options
.fWeakImport
= true;
1679 fInputFiles
.push_back(info
);
1682 void Options::warnObsolete(const char* arg
)
1684 warning("option %s is obsolete and being ignored", arg
);
1691 // Process all command line arguments.
1693 // The only error checking done here is that each option is valid and if it has arguments
1694 // that they too are valid.
1696 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
1697 // whichever was last on the command line is used.
1699 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
1701 void Options::parse(int argc
, const char* argv
[])
1703 // pass one builds search list from -L and -F options
1704 this->buildSearchPaths(argc
, argv
);
1706 // reduce re-allocations
1707 fInputFiles
.reserve(32);
1709 // pass two parse all other options
1710 for(int i
=1; i
< argc
; ++i
) {
1711 const char* arg
= argv
[i
];
1713 if ( arg
[0] == '-' ) {
1715 // Since we don't care about the files passed, just the option names, we do this here.
1717 fprintf (stderr
, "[Logging ld64 options]\t%s\n", arg
);
1719 if ( (arg
[1] == 'L') || (arg
[1] == 'F') ) {
1720 // previously handled by buildSearchPaths()
1722 // The one gnu style option we have to keep compatibility
1723 // with gcc. Might as well have the single hyphen one as well.
1724 else if ( (strcmp(arg
, "--help") == 0)
1725 || (strcmp(arg
, "-help") == 0)) {
1726 fprintf (stdout
, "ld64: For information on command line options please use 'man ld'.\n");
1729 else if ( strcmp(arg
, "-arch") == 0 ) {
1730 parseArch(argv
[++i
]);
1732 else if ( strcmp(arg
, "-dynamic") == 0 ) {
1735 else if ( strcmp(arg
, "-static") == 0 ) {
1736 fReaderOptions
.fForStatic
= true;
1737 if ( fOutputKind
!= kObjectFile
) {
1738 fOutputKind
= kStaticExecutable
;
1741 else if ( strcmp(arg
, "-dylib") == 0 ) {
1742 fOutputKind
= kDynamicLibrary
;
1744 else if ( strcmp(arg
, "-bundle") == 0 ) {
1745 fOutputKind
= kDynamicBundle
;
1747 else if ( strcmp(arg
, "-dylinker") == 0 ) {
1748 fOutputKind
= kDyld
;
1750 else if ( strcmp(arg
, "-execute") == 0 ) {
1751 if ( fOutputKind
!= kStaticExecutable
)
1752 fOutputKind
= kDynamicExecutable
;
1754 else if ( strcmp(arg
, "-preload") == 0 ) {
1755 fOutputKind
= kPreload
;
1757 else if ( strcmp(arg
, "-r") == 0 ) {
1758 fOutputKind
= kObjectFile
;
1760 else if ( strcmp(arg
, "-kext") == 0 ) {
1761 fOutputKind
= kKextBundle
;
1763 else if ( strcmp(arg
, "-o") == 0 ) {
1764 fOutputFile
= argv
[++i
];
1766 else if ( (arg
[1] == 'l') && (strncmp(arg
,"-lazy_",6) !=0) ) {
1767 addLibrary(findLibrary(&arg
[2]));
1769 // This causes a dylib to be weakly bound at
1770 // link time. This corresponds to weak_import.
1771 else if ( strncmp(arg
, "-weak-l", 7) == 0 ) {
1772 FileInfo info
= findLibrary(&arg
[7]);
1773 info
.options
.fWeakImport
= true;
1776 else if ( strncmp(arg
, "-lazy-l", 7) == 0 ) {
1777 FileInfo info
= findLibrary(&arg
[7], true);
1778 info
.options
.fLazyLoad
= true;
1780 fUsingLazyDylibLinking
= true;
1782 // Avoid lazy binding.
1784 else if ( strcmp(arg
, "-bind_at_load") == 0 ) {
1787 else if ( strcmp(arg
, "-twolevel_namespace") == 0 ) {
1788 fNameSpace
= kTwoLevelNameSpace
;
1790 else if ( strcmp(arg
, "-flat_namespace") == 0 ) {
1791 fNameSpace
= kFlatNameSpace
;
1793 // Also sets a bit to ensure dyld causes everything
1794 // in the namespace to be flat.
1796 else if ( strcmp(arg
, "-force_flat_namespace") == 0 ) {
1797 fNameSpace
= kForceFlatNameSpace
;
1799 // Similar to --whole-archive.
1800 else if ( strcmp(arg
, "-all_load") == 0 ) {
1801 fReaderOptions
.fFullyLoadArchives
= true;
1803 else if ( strcmp(arg
, "-noall_load") == 0) {
1806 // Similar to -all_load
1807 else if ( strcmp(arg
, "-ObjC") == 0 ) {
1808 fReaderOptions
.fLoadAllObjcObjectsFromArchives
= true;
1810 // Similar to -all_load, but for the following archive only.
1811 else if ( strcmp(arg
, "-force_load") == 0 ) {
1812 FileInfo info
= findFile(argv
[++i
]);
1813 info
.options
.fForceLoad
= true;
1816 // Library versioning.
1817 else if ( (strcmp(arg
, "-dylib_compatibility_version") == 0)
1818 || (strcmp(arg
, "-compatibility_version") == 0)) {
1819 const char* vers
= argv
[++i
];
1821 throw "-dylib_compatibility_version missing <version>";
1822 fDylibCompatVersion
= parseVersionNumber(vers
);
1824 else if ( (strcmp(arg
, "-dylib_current_version") == 0)
1825 || (strcmp(arg
, "-current_version") == 0)) {
1826 const char* vers
= argv
[++i
];
1828 throw "-dylib_current_version missing <version>";
1829 fDylibCurrentVersion
= parseVersionNumber(vers
);
1831 else if ( strcmp(arg
, "-sectorder") == 0 ) {
1832 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
1833 throw "-sectorder missing <segment> <section> <file-path>";
1834 parseSectionOrderFile(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1837 else if ( strcmp(arg
, "-order_file") == 0 ) {
1838 parseOrderFile(argv
[++i
], false);
1840 else if ( strcmp(arg
, "-order_file_statistics") == 0 ) {
1841 fPrintOrderFileStatistics
= true;
1843 // ??? Deprecate segcreate.
1844 // -sectcreate puts whole files into a section in the output.
1845 else if ( (strcmp(arg
, "-sectcreate") == 0) || (strcmp(arg
, "-segcreate") == 0) ) {
1846 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
1847 throw "-sectcreate missing <segment> <section> <file-path>";
1848 addSection(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1851 // Since we have a full path in binary/library names we need to be able to override it.
1852 else if ( (strcmp(arg
, "-dylib_install_name") == 0)
1853 || (strcmp(arg
, "-dylinker_install_name") == 0)
1854 || (strcmp(arg
, "-install_name") == 0)) {
1855 fDylibInstallName
= argv
[++i
];
1856 if ( fDylibInstallName
== NULL
)
1857 throw "-install_name missing <path>";
1859 // Sets the base address of the output.
1860 else if ( (strcmp(arg
, "-seg1addr") == 0) || (strcmp(arg
, "-image_base") == 0) ) {
1861 const char* address
= argv
[++i
];
1862 if ( address
== NULL
)
1863 throwf("%s missing <address>", arg
);
1864 fBaseAddress
= parseAddress(address
);
1865 uint64_t temp
= ((fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
1866 if ( fBaseAddress
!= temp
) {
1867 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment
);
1868 fBaseAddress
= temp
;
1871 else if ( strcmp(arg
, "-e") == 0 ) {
1872 fEntryName
= argv
[++i
];
1874 // Same as -@ from the FSF linker.
1875 else if ( strcmp(arg
, "-filelist") == 0 ) {
1876 const char* path
= argv
[++i
];
1877 if ( (path
== NULL
) || (path
[0] == '-') )
1878 throw "-filelist missing <path>";
1881 else if ( strcmp(arg
, "-keep_private_externs") == 0 ) {
1882 fKeepPrivateExterns
= true;
1884 else if ( strcmp(arg
, "-final_output") == 0 ) {
1885 fFinalName
= argv
[++i
];
1887 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
1888 // just ensures that this happens for cross object file boundaries.
1889 else if ( (strcmp(arg
, "-interposable") == 0) || (strcmp(arg
, "-multi_module") == 0)) {
1890 switch ( fInterposeMode
) {
1891 case kInterposeNone
:
1892 case kInterposeAllExternal
:
1893 fInterposeMode
= kInterposeAllExternal
;
1895 case kInterposeSome
:
1896 // do nothing, -interposable_list overrides -interposable"
1900 else if ( strcmp(arg
, "-interposable_list") == 0 ) {
1901 fInterposeMode
= kInterposeSome
;
1902 loadExportFile(argv
[++i
], "-interposable_list", fInterposeList
);
1904 // Default for -interposable/-multi_module/-single_module.
1905 else if ( strcmp(arg
, "-single_module") == 0 ) {
1906 fInterposeMode
= kInterposeNone
;
1908 else if ( strcmp(arg
, "-exported_symbols_list") == 0 ) {
1909 if ( fExportMode
== kDontExportSome
)
1910 throw "can't use -exported_symbols_list and -unexported_symbols_list";
1911 fExportMode
= kExportSome
;
1912 loadExportFile(argv
[++i
], "-exported_symbols_list", fExportSymbols
);
1914 else if ( strcmp(arg
, "-unexported_symbols_list") == 0 ) {
1915 if ( fExportMode
== kExportSome
)
1916 throw "can't use -unexported_symbols_list and -exported_symbols_list";
1917 fExportMode
= kDontExportSome
;
1918 loadExportFile(argv
[++i
], "-unexported_symbols_list", fDontExportSymbols
);
1920 else if ( strcmp(arg
, "-exported_symbol") == 0 ) {
1921 if ( fExportMode
== kDontExportSome
)
1922 throw "can't use -exported_symbol and -unexported_symbols";
1923 fExportMode
= kExportSome
;
1924 fExportSymbols
.insert(argv
[++i
]);
1926 else if ( strcmp(arg
, "-unexported_symbol") == 0 ) {
1927 if ( fExportMode
== kExportSome
)
1928 throw "can't use -unexported_symbol and -exported_symbol";
1929 fExportMode
= kDontExportSome
;
1930 fDontExportSymbols
.insert(argv
[++i
]);
1932 else if ( strcmp(arg
, "-non_global_symbols_no_strip_list") == 0 ) {
1933 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveExclude
)
1934 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
1935 fLocalSymbolHandling
= kLocalSymbolsSelectiveInclude
;
1936 loadExportFile(argv
[++i
], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded
);
1938 else if ( strcmp(arg
, "-non_global_symbols_strip_list") == 0 ) {
1939 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveInclude
)
1940 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
1941 fLocalSymbolHandling
= kLocalSymbolsSelectiveExclude
;
1942 loadExportFile(argv
[++i
], "-non_global_symbols_strip_list", fLocalSymbolsExcluded
);
1945 else if ( strcmp(arg
, "-no_arch_warnings") == 0 ) {
1946 fIgnoreOtherArchFiles
= true;
1948 else if ( strcmp(arg
, "-force_cpusubtype_ALL") == 0 ) {
1949 fForceSubtypeAll
= true;
1951 // Similar to -weak-l but uses the absolute path name to the library.
1952 else if ( strcmp(arg
, "-weak_library") == 0 ) {
1953 FileInfo info
= findFile(argv
[++i
]);
1954 info
.options
.fWeakImport
= true;
1957 else if ( strcmp(arg
, "-lazy_library") == 0 ) {
1958 FileInfo info
= findFile(argv
[++i
]);
1959 info
.options
.fLazyLoad
= true;
1961 fUsingLazyDylibLinking
= true;
1963 else if ( strcmp(arg
, "-framework") == 0 ) {
1964 addLibrary(findFramework(argv
[++i
]));
1966 else if ( strcmp(arg
, "-weak_framework") == 0 ) {
1967 FileInfo info
= findFramework(argv
[++i
]);
1968 info
.options
.fWeakImport
= true;
1971 else if ( strcmp(arg
, "-lazy_framework") == 0 ) {
1972 FileInfo info
= findFramework(argv
[++i
]);
1973 info
.options
.fLazyLoad
= true;
1975 fUsingLazyDylibLinking
= true;
1977 else if ( strcmp(arg
, "-search_paths_first") == 0 ) {
1978 // previously handled by buildSearchPaths()
1980 else if ( strcmp(arg
, "-undefined") == 0 ) {
1981 setUndefinedTreatment(argv
[++i
]);
1983 // Debugging output flag.
1984 else if ( strcmp(arg
, "-arch_multiple") == 0 ) {
1985 fMessagesPrefixedWithArchitecture
= true;
1987 // Specify what to do with relocations in read only
1988 // sections like .text. Could be errors, warnings,
1989 // or suppressed. Currently we do nothing with the
1991 else if ( strcmp(arg
, "-read_only_relocs") == 0 ) {
1992 switch ( parseTreatment(argv
[++i
]) ) {
1995 throw "-read_only_relocs missing [ warning | error | suppress ]";
1997 fWarnTextRelocs
= true;
1998 fAllowTextRelocs
= true;
2001 fWarnTextRelocs
= false;
2002 fAllowTextRelocs
= true;
2005 fWarnTextRelocs
= false;
2006 fAllowTextRelocs
= false;
2010 else if ( strcmp(arg
, "-sect_diff_relocs") == 0 ) {
2014 // Warn, error or make strong a mismatch between weak
2015 // and non-weak references.
2016 else if ( strcmp(arg
, "-weak_reference_mismatches") == 0 ) {
2017 setWeakReferenceMismatchTreatment(argv
[++i
]);
2019 // For a deployment target of 10.3 and earlier ld64 will
2020 // prebind an executable with 0s in all addresses that
2021 // are prebound. This can then be fixed up by update_prebinding
2022 // later. Prebinding is less useful on 10.4 and greater.
2023 else if ( strcmp(arg
, "-prebind") == 0 ) {
2026 else if ( strcmp(arg
, "-noprebind") == 0 ) {
2030 else if ( strcmp(arg
, "-prebind_allow_overlap") == 0 ) {
2033 else if ( strcmp(arg
, "-prebind_all_twolevel_modules") == 0 ) {
2036 else if ( strcmp(arg
, "-noprebind_all_twolevel_modules") == 0 ) {
2039 else if ( strcmp(arg
, "-nofixprebinding") == 0 ) {
2042 // This should probably be deprecated when we respect -L and -F
2043 // when searching for libraries.
2044 else if ( strcmp(arg
, "-dylib_file") == 0 ) {
2045 addDylibOverride(argv
[++i
]);
2047 // What to expand @executable_path to if found in dependent dylibs
2048 else if ( strcmp(arg
, "-executable_path") == 0 ) {
2049 fExecutablePath
= argv
[++i
];
2050 if ( (fExecutablePath
== NULL
) || (fExecutablePath
[0] == '-') )
2051 throw "-executable_path missing <path>";
2052 // if a directory was passed, add / to end
2053 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2054 struct stat statBuffer
;
2055 if ( stat(fExecutablePath
, &statBuffer
) == 0 ) {
2056 if ( (statBuffer
.st_mode
& S_IFMT
) == S_IFDIR
) {
2057 char* pathWithSlash
= new char[strlen(fExecutablePath
)+2];
2058 strcpy(pathWithSlash
, fExecutablePath
);
2059 strcat(pathWithSlash
, "/");
2060 fExecutablePath
= pathWithSlash
;
2064 // Aligns all segments to the power of 2 boundary specified.
2065 else if ( strcmp(arg
, "-segalign") == 0 ) {
2066 const char* size
= argv
[++i
];
2068 throw "-segalign missing <size>";
2069 fSegmentAlignment
= parseAddress(size
);
2070 uint8_t alignment
= (uint8_t)__builtin_ctz(fSegmentAlignment
);
2071 uint32_t p2aligned
= (1 << alignment
);
2072 if ( p2aligned
!= fSegmentAlignment
) {
2073 warning("alignment for -segalign %s is not a power of two, using 0x%X", size
, p2aligned
);
2074 fSegmentAlignment
= p2aligned
;
2077 // Puts a specified segment at a particular address that must
2078 // be a multiple of the segment alignment.
2079 else if ( strcmp(arg
, "-segaddr") == 0 ) {
2081 seg
.name
= argv
[++i
];
2082 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2083 throw "-segaddr missing segName Adddress";
2084 seg
.address
= parseAddress(argv
[++i
]);
2085 uint64_t temp
= seg
.address
& (-4096); // page align
2086 if ( (seg
.address
!= temp
) )
2087 warning("-segaddr %s not page aligned, rounding down", seg
.name
);
2088 fCustomSegmentAddresses
.push_back(seg
);
2090 // ??? Deprecate when we deprecate split-seg.
2091 else if ( strcmp(arg
, "-segs_read_only_addr") == 0 ) {
2092 fBaseAddress
= parseAddress(argv
[++i
]);
2094 // ??? Deprecate when we deprecate split-seg.
2095 else if ( strcmp(arg
, "-segs_read_write_addr") == 0 ) {
2096 fBaseWritableAddress
= parseAddress(argv
[++i
]);
2099 // ??? Deprecate when we get rid of basing at build time.
2100 else if ( strcmp(arg
, "-seg_addr_table") == 0 ) {
2101 const char* name
= argv
[++i
];
2103 throw "-seg_addr_table missing argument";
2104 fSegAddrTablePath
= name
;
2106 else if ( strcmp(arg
, "-seg_addr_table_filename") == 0 ) {
2110 else if ( strcmp(arg
, "-segprot") == 0 ) {
2112 seg
.name
= argv
[++i
];
2113 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) || (argv
[i
+2] == NULL
) )
2114 throw "-segprot missing segName max-prot init-prot";
2115 seg
.max
= parseProtection(argv
[++i
]);
2116 seg
.init
= parseProtection(argv
[++i
]);
2117 fCustomSegmentProtections
.push_back(seg
);
2119 else if ( strcmp(arg
, "-pagezero_size") == 0 ) {
2120 const char* size
= argv
[++i
];
2122 throw "-pagezero_size missing <size>";
2123 fZeroPageSize
= parseAddress(size
);
2124 uint64_t temp
= fZeroPageSize
& (-4096); // page align
2125 if ( (fZeroPageSize
!= temp
) )
2126 warning("-pagezero_size not page aligned, rounding down");
2127 fZeroPageSize
= temp
;
2129 else if ( strcmp(arg
, "-stack_addr") == 0 ) {
2130 const char* address
= argv
[++i
];
2131 if ( address
== NULL
)
2132 throw "-stack_addr missing <address>";
2133 fStackAddr
= parseAddress(address
);
2135 else if ( strcmp(arg
, "-stack_size") == 0 ) {
2136 const char* size
= argv
[++i
];
2138 throw "-stack_size missing <address>";
2139 fStackSize
= parseAddress(size
);
2140 uint64_t temp
= fStackSize
& (-4096); // page align
2141 if ( (fStackSize
!= temp
) )
2142 warning("-stack_size not page aligned, rounding down");
2144 else if ( strcmp(arg
, "-allow_stack_execute") == 0 ) {
2145 fExecutableStack
= true;
2147 else if ( strcmp(arg
, "-sectalign") == 0 ) {
2148 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2149 throw "-sectalign missing <segment> <section> <file-path>";
2150 addSectionAlignment(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2153 else if ( strcmp(arg
, "-sectorder_detail") == 0 ) {
2156 else if ( strcmp(arg
, "-sectobjectsymbols") == 0 ) {
2160 else if ( strcmp(arg
, "-bundle_loader") == 0 ) {
2161 fBundleLoader
= argv
[++i
];
2162 if ( (fBundleLoader
== NULL
) || (fBundleLoader
[0] == '-') )
2163 throw "-bundle_loader missing <path>";
2164 FileInfo info
= findFile(fBundleLoader
);
2165 info
.options
.fBundleLoader
= true;
2166 fInputFiles
.push_back(info
);
2168 else if ( strcmp(arg
, "-private_bundle") == 0 ) {
2171 else if ( strcmp(arg
, "-twolevel_namespace_hints") == 0 ) {
2174 // Use this flag to set default behavior for deployement targets.
2175 else if ( strcmp(arg
, "-macosx_version_min") == 0 ) {
2176 setMacOSXVersionMin(argv
[++i
]);
2178 else if ( strcmp(arg
, "-iphoneos_version_min") == 0 ) {
2179 setIPhoneVersionMin(argv
[++i
]);
2181 else if ( strcmp(arg
, "-multiply_defined") == 0 ) {
2182 //warnObsolete(arg);
2185 else if ( strcmp(arg
, "-multiply_defined_unused") == 0 ) {
2189 else if ( strcmp(arg
, "-nomultidefs") == 0 ) {
2192 // Display each file in which the argument symbol appears and whether
2193 // the file defines or references it. This option takes an argument
2194 // as -y<symbol> note that there is no space.
2195 else if ( strncmp(arg
, "-y", 2) == 0 ) {
2198 // Same output as -y, but output <arg> number of undefined symbols only.
2199 else if ( strcmp(arg
, "-Y") == 0 ) {
2200 //warnObsolete(arg);
2203 // This option affects all objects linked into the final result.
2204 else if ( strcmp(arg
, "-m") == 0 ) {
2207 else if ( (strcmp(arg
, "-why_load") == 0) || (strcmp(arg
, "-whyload") == 0) ) {
2208 fReaderOptions
.fWhyLoad
= true;
2210 else if ( strcmp(arg
, "-why_live") == 0 ) {
2211 const char* name
= argv
[++i
];
2213 throw "-why_live missing symbol name argument";
2214 fWhyLive
.insert(name
);
2216 else if ( strcmp(arg
, "-u") == 0 ) {
2217 const char* name
= argv
[++i
];
2219 throw "-u missing argument";
2220 fInitialUndefines
.push_back(name
);
2222 else if ( strcmp(arg
, "-U") == 0 ) {
2223 const char* name
= argv
[++i
];
2225 throw "-U missing argument";
2226 fAllowedUndefined
.insert(name
);
2228 else if ( strcmp(arg
, "-s") == 0 ) {
2230 fLocalSymbolHandling
= kLocalSymbolsNone
;
2231 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
2233 else if ( strcmp(arg
, "-x") == 0 ) {
2234 fLocalSymbolHandling
= kLocalSymbolsNone
;
2236 else if ( strcmp(arg
, "-S") == 0 ) {
2237 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
2239 else if ( strcmp(arg
, "-X") == 0 ) {
2242 else if ( strcmp(arg
, "-Si") == 0 ) {
2244 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoFull
;
2246 else if ( strcmp(arg
, "-b") == 0 ) {
2249 else if ( strcmp(arg
, "-Sn") == 0 ) {
2251 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoFull
;
2253 else if ( strcmp(arg
, "-Sp") == 0 ) {
2256 else if ( strcmp(arg
, "-dead_strip") == 0 ) {
2257 fDeadStrip
= kDeadStripOnPlusUnusedInits
;
2259 else if ( strcmp(arg
, "-no_dead_strip_inits_and_terms") == 0 ) {
2260 fDeadStrip
= kDeadStripOn
;
2262 else if ( strcmp(arg
, "-w") == 0 ) {
2263 // previously handled by buildSearchPaths()
2265 else if ( strcmp(arg
, "-arch_errors_fatal") == 0 ) {
2266 fErrorOnOtherArchFiles
= true;
2268 else if ( strcmp(arg
, "-M") == 0 ) {
2271 else if ( strcmp(arg
, "-headerpad") == 0 ) {
2272 const char* size
= argv
[++i
];
2274 throw "-headerpad missing argument";
2275 fMinimumHeaderPad
= parseAddress(size
);
2277 else if ( strcmp(arg
, "-headerpad_max_install_names") == 0 ) {
2278 fMaxMinimumHeaderPad
= true;
2280 else if ( strcmp(arg
, "-t") == 0 ) {
2281 fReaderOptions
.fLogAllFiles
= true;
2283 else if ( strcmp(arg
, "-whatsloaded") == 0 ) {
2284 fReaderOptions
.fLogObjectFiles
= true;
2286 else if ( strcmp(arg
, "-A") == 0 ) {
2290 else if ( strcmp(arg
, "-umbrella") == 0 ) {
2291 const char* name
= argv
[++i
];
2293 throw "-umbrella missing argument";
2294 fUmbrellaName
= name
;
2296 else if ( strcmp(arg
, "-allowable_client") == 0 ) {
2297 const char* name
= argv
[++i
];
2300 throw "-allowable_client missing argument";
2302 fAllowableClients
.push_back(name
);
2304 else if ( strcmp(arg
, "-client_name") == 0 ) {
2305 const char* name
= argv
[++i
];
2308 throw "-client_name missing argument";
2312 else if ( strcmp(arg
, "-sub_umbrella") == 0 ) {
2313 const char* name
= argv
[++i
];
2315 throw "-sub_umbrella missing argument";
2316 fSubUmbellas
.push_back(name
);
2318 else if ( strcmp(arg
, "-sub_library") == 0 ) {
2319 const char* name
= argv
[++i
];
2321 throw "-sub_library missing argument";
2322 fSubLibraries
.push_back(name
);
2324 else if ( strcmp(arg
, "-init") == 0 ) {
2325 const char* name
= argv
[++i
];
2327 throw "-init missing argument";
2328 fInitFunctionName
= name
;
2330 else if ( strcmp(arg
, "-dot") == 0 ) {
2331 const char* name
= argv
[++i
];
2333 throw "-dot missing argument";
2334 fDotOutputFile
= name
;
2336 else if ( strcmp(arg
, "-warn_commons") == 0 ) {
2337 fWarnCommons
= true;
2339 else if ( strcmp(arg
, "-commons") == 0 ) {
2340 fCommonsMode
= parseCommonsTreatment(argv
[++i
]);
2342 else if ( strcmp(arg
, "-keep_relocs") == 0 ) {
2343 fKeepRelocations
= true;
2345 else if ( strcmp(arg
, "-warn_stabs") == 0 ) {
2348 else if ( strcmp(arg
, "-pause") == 0 ) {
2351 else if ( strcmp(arg
, "-print_statistics") == 0 ) {
2354 else if ( strcmp(arg
, "-d") == 0 ) {
2355 fReaderOptions
.fMakeTentativeDefinitionsReal
= true;
2357 else if ( strcmp(arg
, "-v") == 0 ) {
2358 // previously handled by buildSearchPaths()
2360 else if ( strcmp(arg
, "-Z") == 0 ) {
2361 // previously handled by buildSearchPaths()
2363 else if ( strcmp(arg
, "-syslibroot") == 0 ) {
2365 // previously handled by buildSearchPaths()
2367 else if ( strcmp(arg
, "-no_uuid") == 0 ) {
2368 fUUIDMode
= kUUIDNone
;
2370 else if ( strcmp(arg
, "-random_uuid") == 0 ) {
2371 fUUIDMode
= kUUIDRandom
;
2373 else if ( strcmp(arg
, "-dtrace") == 0 ) {
2374 const char* name
= argv
[++i
];
2376 throw "-dtrace missing argument";
2377 fDtraceScriptName
= name
;
2379 else if ( strcmp(arg
, "-root_safe") == 0 ) {
2380 fReaderOptions
.fRootSafe
= true;
2382 else if ( strcmp(arg
, "-setuid_safe") == 0 ) {
2383 fReaderOptions
.fSetuidSafe
= true;
2385 else if ( strcmp(arg
, "-alias") == 0 ) {
2386 ObjectFile::ReaderOptions::AliasPair pair
;
2387 pair
.realName
= argv
[++i
];
2388 if ( pair
.realName
== NULL
)
2389 throw "missing argument to -alias";
2390 pair
.alias
= argv
[++i
];
2391 if ( pair
.alias
== NULL
)
2392 throw "missing argument to -alias";
2393 fReaderOptions
.fAliases
.push_back(pair
);
2395 else if ( strcmp(arg
, "-alias_list") == 0 ) {
2396 parseAliasFile(argv
[++i
]);
2398 // put this last so that it does not interfer with other options starting with 'i'
2399 else if ( strncmp(arg
, "-i", 2) == 0 ) {
2400 const char* colon
= strchr(arg
, ':');
2401 if ( colon
== NULL
)
2402 throwf("unknown option: %s", arg
);
2403 ObjectFile::ReaderOptions::AliasPair pair
;
2404 char* temp
= new char[colon
-arg
];
2405 strlcpy(temp
, &arg
[2], colon
-arg
-1);
2406 pair
.realName
= &colon
[1];
2408 fReaderOptions
.fAliases
.push_back(pair
);
2410 else if ( strcmp(arg
, "-save-temps") == 0 ) {
2411 fSaveTempFiles
= true;
2413 else if ( strcmp(arg
, "-rpath") == 0 ) {
2414 const char* path
= argv
[++i
];
2416 throw "missing argument to -rpath";
2417 fRPaths
.push_back(path
);
2419 else if ( strcmp(arg
, "-read_only_stubs") == 0 ) {
2420 fReadOnlyx86Stubs
= true;
2422 else if ( strcmp(arg
, "-slow_stubs") == 0 ) {
2425 else if ( strcmp(arg
, "-map") == 0 ) {
2426 fMapPath
= argv
[++i
];
2427 if ( fMapPath
== NULL
)
2428 throw "missing argument to -map";
2430 else if ( strcmp(arg
, "-pie") == 0 ) {
2431 fPositionIndependentExecutable
= true;
2433 else if ( strncmp(arg
, "-reexport-l", 11) == 0 ) {
2434 FileInfo info
= findLibrary(&arg
[11], true);
2435 info
.options
.fReExport
= true;
2438 else if ( strcmp(arg
, "-reexport_library") == 0 ) {
2439 FileInfo info
= findFile(argv
[++i
]);
2440 info
.options
.fReExport
= true;
2443 else if ( strcmp(arg
, "-reexport_framework") == 0 ) {
2444 FileInfo info
= findFramework(argv
[++i
]);
2445 info
.options
.fReExport
= true;
2448 else if ( strcmp(arg
, "-dead_strip_dylibs") == 0 ) {
2449 fDeadStripDylibs
= true;
2451 else if ( strcmp(arg
, "-no_implicit_dylibs") == 0 ) {
2452 fReaderOptions
.fImplicitlyLinkPublicDylibs
= false;
2454 else if ( strcmp(arg
, "-new_linker") == 0 ) {
2457 else if ( strcmp(arg
, "-no_encryption") == 0 ) {
2458 fEncryptable
= false;
2460 else if ( strcmp(arg
, "-no_compact_unwind") == 0 ) {
2461 fReaderOptions
.fAddCompactUnwindEncoding
= false;
2463 else if ( strcmp(arg
, "-mllvm") == 0 ) {
2464 const char* opts
= argv
[++i
];
2466 throw "missing argument to -mllvm";
2467 fLLVMOptions
.push_back(opts
);
2469 else if ( strcmp(arg
, "-no_order_inits") == 0 ) {
2470 fReaderOptions
.fAutoOrderInitializers
= false;
2472 else if ( strcmp(arg
, "-no_order_data") == 0 ) {
2475 else if ( strcmp(arg
, "-seg_page_size") == 0 ) {
2477 seg
.name
= argv
[++i
];
2478 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2479 throw "-seg_page_size missing segName Adddress";
2480 seg
.size
= parseAddress(argv
[++i
]);
2481 uint64_t temp
= seg
.size
& (-4096); // page align
2482 if ( (seg
.size
!= temp
) )
2483 warning("-seg_page_size %s not 4K aligned, rounding down", seg
.name
);
2484 fCustomSegmentSizes
.push_back(seg
);
2486 else if ( strcmp(arg
, "-mark_dead_strippable_dylib") == 0 ) {
2487 fMarkDeadStrippableDylib
= true;
2489 else if ( strcmp(arg
, "-exported_symbols_order") == 0 ) {
2490 loadSymbolOrderFile(argv
[++i
], fExportSymbolsOrder
);
2492 else if ( strcmp(arg
, "-no_compact_linkedit") == 0 ) {
2493 fMakeCompressedDyldInfo
= false;
2495 else if ( strcmp(arg
, "-no_eh_labels") == 0 ) {
2496 fReaderOptions
.fNoEHLabels
= true;
2498 else if ( strcmp(arg
, "-warn_compact_unwind") == 0 ) {
2499 fReaderOptions
.fWarnCompactUnwind
= true;
2501 else if ( strcmp(arg
, "-allow_sub_type_mismatches") == 0 ) {
2502 fAllowCpuSubtypeMismatches
= true;
2504 else if ( strcmp(arg
, "-no_zero_fill_sections") == 0 ) {
2505 fReaderOptions
.fOptimizeZeroFill
= false;
2508 throwf("unknown option: %s", arg
);
2512 FileInfo info
= findFile(arg
);
2513 if ( strcmp(&info
.path
[strlen(info
.path
)-2], ".a") == 0 )
2516 fInputFiles
.push_back(info
);
2520 // if a -lazy option was used, implicitly link in lazydylib1.o
2521 if ( fUsingLazyDylibLinking
) {
2522 addLibrary(findLibrary("lazydylib1.o"));
2529 // -syslibroot <path> is used for SDK support.
2530 // The rule is that all search paths (both explicit and default) are
2531 // checked to see if they exist in the SDK. If so, that path is
2532 // replaced with the sdk prefixed path. If not, that search path
2533 // is used as is. If multiple -syslibroot options are specified
2534 // their directory structures are logically overlayed and files
2535 // from sdks specified earlier on the command line used before later ones.
2537 void Options::buildSearchPaths(int argc
, const char* argv
[])
2539 bool addStandardLibraryDirectories
= true;
2540 std::vector
<const char*> libraryPaths
;
2541 std::vector
<const char*> frameworkPaths
;
2542 libraryPaths
.reserve(10);
2543 frameworkPaths
.reserve(10);
2544 // scan through argv looking for -L, -F, -Z, and -syslibroot options
2545 for(int i
=0; i
< argc
; ++i
) {
2546 if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'L') ) {
2547 const char* libSearchDir
= &argv
[i
][2];
2548 if ( libSearchDir
[0] == '\0' )
2549 throw "-L must be immediately followed by a directory path (no space)";
2550 struct stat statbuf
;
2551 if ( stat(libSearchDir
, &statbuf
) == 0 ) {
2552 if ( statbuf
.st_mode
& S_IFDIR
)
2553 libraryPaths
.push_back(libSearchDir
);
2555 warning("path '%s' following -L not a directory", libSearchDir
);
2558 warning("directory '%s' following -L not found", libSearchDir
);
2561 else if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'F') ) {
2562 const char* frameworkSearchDir
= &argv
[i
][2];
2563 if ( frameworkSearchDir
[0] == '\0' )
2564 throw "-F must be immediately followed by a directory path (no space)";
2565 struct stat statbuf
;
2566 if ( stat(frameworkSearchDir
, &statbuf
) == 0 ) {
2567 if ( statbuf
.st_mode
& S_IFDIR
)
2568 frameworkPaths
.push_back(frameworkSearchDir
);
2570 warning("path '%s' following -F not a directory", frameworkSearchDir
);
2573 warning("directory '%s' following -F not found", frameworkSearchDir
);
2576 else if ( strcmp(argv
[i
], "-Z") == 0 )
2577 addStandardLibraryDirectories
= false;
2578 else if ( strcmp(argv
[i
], "-v") == 0 ) {
2580 extern const char ldVersionString
[];
2581 fprintf(stderr
, "%s", ldVersionString
);
2582 // if only -v specified, exit cleanly
2585 printLTOVersion(*this);
2590 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
2591 const char* path
= argv
[++i
];
2593 throw "-syslibroot missing argument";
2594 fSDKPaths
.push_back(path
);
2596 else if ( strcmp(argv
[i
], "-search_paths_first") == 0 ) {
2597 // ??? Deprecate when we get -Bstatic/-Bdynamic.
2598 fLibrarySearchMode
= kSearchDylibAndArchiveInEachDir
;
2600 else if ( strcmp(argv
[i
], "-w") == 0 ) {
2601 sEmitWarnings
= false;
2604 int standardLibraryPathsStartIndex
= libraryPaths
.size();
2605 int standardFrameworkPathsStartIndex
= frameworkPaths
.size();
2606 if ( addStandardLibraryDirectories
) {
2607 libraryPaths
.push_back("/usr/lib");
2608 libraryPaths
.push_back("/usr/local/lib");
2610 frameworkPaths
.push_back("/Library/Frameworks/");
2611 frameworkPaths
.push_back("/System/Library/Frameworks/");
2612 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
2615 // <rdar://problem/5829579> Support for configure based hacks
2616 // if last -syslibroot is /, then ignore all syslibroots
2617 if ( fSDKPaths
.size() > 0 ) {
2618 if ( strcmp(fSDKPaths
.back(), "/") == 0 ) {
2623 // now merge sdk and library paths to make real search paths
2624 fLibrarySearchPaths
.reserve(libraryPaths
.size()*(fSDKPaths
.size()+1));
2626 for (std::vector
<const char*>::iterator it
= libraryPaths
.begin(); it
!= libraryPaths
.end(); ++it
, ++libIndex
) {
2627 const char* libDir
= *it
;
2628 bool sdkOverride
= false;
2629 if ( libDir
[0] == '/' ) {
2630 char betterLibDir
[PATH_MAX
];
2631 if ( strstr(libDir
, "/..") != NULL
) {
2632 if ( realpath(libDir
, betterLibDir
) != NULL
)
2633 libDir
= strdup(betterLibDir
);
2635 const int libDirLen
= strlen(libDir
);
2636 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
2637 const char* sdkDir
= *sdkit
;
2638 const int sdkDirLen
= strlen(sdkDir
);
2639 char newPath
[libDirLen
+ sdkDirLen
+4];
2640 strcpy(newPath
, sdkDir
);
2641 if ( newPath
[sdkDirLen
-1] == '/' )
2642 newPath
[sdkDirLen
-1] = '\0';
2643 strcat(newPath
, libDir
);
2644 struct stat statBuffer
;
2645 if ( stat(newPath
, &statBuffer
) == 0 ) {
2646 fLibrarySearchPaths
.push_back(strdup(newPath
));
2651 if ( !sdkOverride
) {
2652 if ( (libIndex
>= standardLibraryPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
2653 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2654 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2657 fLibrarySearchPaths
.push_back(libDir
);
2662 // now merge sdk and framework paths to make real search paths
2663 fFrameworkSearchPaths
.reserve(frameworkPaths
.size()*(fSDKPaths
.size()+1));
2665 for (std::vector
<const char*>::iterator it
= frameworkPaths
.begin(); it
!= frameworkPaths
.end(); ++it
, ++frameIndex
) {
2666 const char* frameworkDir
= *it
;
2667 bool sdkOverride
= false;
2668 if ( frameworkDir
[0] == '/' ) {
2669 char betterFrameworkDir
[PATH_MAX
];
2670 if ( strstr(frameworkDir
, "/..") != NULL
) {
2671 if ( realpath(frameworkDir
, betterFrameworkDir
) != NULL
)
2672 frameworkDir
= strdup(betterFrameworkDir
);
2674 const int frameworkDirLen
= strlen(frameworkDir
);
2675 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
2676 const char* sdkDir
= *sdkit
;
2677 const int sdkDirLen
= strlen(sdkDir
);
2678 char newPath
[frameworkDirLen
+ sdkDirLen
+4];
2679 strcpy(newPath
, sdkDir
);
2680 if ( newPath
[sdkDirLen
-1] == '/' )
2681 newPath
[sdkDirLen
-1] = '\0';
2682 strcat(newPath
, frameworkDir
);
2683 struct stat statBuffer
;
2684 if ( stat(newPath
, &statBuffer
) == 0 ) {
2685 fFrameworkSearchPaths
.push_back(strdup(newPath
));
2690 if ( !sdkOverride
) {
2691 if ( (frameIndex
>= standardFrameworkPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
2692 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2693 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2696 fFrameworkSearchPaths
.push_back(frameworkDir
);
2702 fprintf(stderr
,"Library search paths:\n");
2703 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
2704 it
!= fLibrarySearchPaths
.end();
2706 fprintf(stderr
,"\t%s\n", *it
);
2707 fprintf(stderr
,"Framework search paths:\n");
2708 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
2709 it
!= fFrameworkSearchPaths
.end();
2711 fprintf(stderr
,"\t%s\n", *it
);
2715 // this is run before the command line is parsed
2716 void Options::parsePreCommandLineEnvironmentSettings()
2718 if ((getenv("LD_TRACE_ARCHIVES") != NULL
)
2719 || (getenv("RC_TRACE_ARCHIVES") != NULL
))
2720 fReaderOptions
.fTraceArchives
= true;
2722 if ((getenv("LD_TRACE_DYLIBS") != NULL
)
2723 || (getenv("RC_TRACE_DYLIBS") != NULL
)) {
2724 fReaderOptions
.fTraceDylibs
= true;
2725 fReaderOptions
.fTraceIndirectDylibs
= true;
2728 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL
) {
2729 fTraceDylibSearching
= true;
2732 if (getenv("LD_PRINT_OPTIONS") != NULL
)
2733 fPrintOptions
= true;
2735 if (fReaderOptions
.fTraceDylibs
|| fReaderOptions
.fTraceArchives
)
2736 fReaderOptions
.fTraceOutputFile
= getenv("LD_TRACE_FILE");
2738 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL
)
2739 fPrintOrderFileStatistics
= true;
2741 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL
)
2744 if (getenv("LD_NO_ENCRYPT") != NULL
)
2745 fEncryptable
= false;
2747 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL
)
2748 fAllowCpuSubtypeMismatches
= true;
2750 // for now disable compressed linkedit functionality
2751 if ( getenv("LD_NO_COMPACT_LINKEDIT") != NULL
) {
2752 fMakeCompressedDyldInfo
= false;
2753 fMakeClassicDyldInfo
= true;
2756 sWarningsSideFilePath
= getenv("LD_WARN_FILE");
2760 // this is run after the command line is parsed
2761 void Options::parsePostCommandLineEnvironmentSettings()
2763 // when building a dynamic main executable, default any use of @executable_path to output path
2764 if ( fExecutablePath
== NULL
&& (fOutputKind
== kDynamicExecutable
) ) {
2765 fExecutablePath
= fOutputFile
;
2768 // allow build system to set default seg_addr_table
2769 if ( fSegAddrTablePath
== NULL
)
2770 fSegAddrTablePath
= getenv("LD_SEG_ADDR_TABLE");
2772 // allow build system to turn on prebinding
2774 fPrebind
= ( getenv("LD_PREBIND") != NULL
);
2777 // allow build system to force on dead-code-stripping
2778 if ( fDeadStrip
== kDeadStripOff
) {
2779 if ( getenv("LD_DEAD_STRIP") != NULL
) {
2780 switch (fOutputKind
) {
2781 case Options::kDynamicLibrary
:
2782 case Options::kDynamicExecutable
:
2783 case Options::kDynamicBundle
:
2784 fDeadStrip
= kDeadStripOn
;
2786 case Options::kPreload
:
2787 case Options::kObjectFile
:
2788 case Options::kDyld
:
2789 case Options::kStaticExecutable
:
2790 case Options::kKextBundle
:
2796 // allow build system to force on -warn_commons
2797 if ( getenv("LD_WARN_COMMONS") != NULL
)
2798 fWarnCommons
= true;
2802 void Options::reconfigureDefaults()
2804 // sync reader options
2805 switch ( fOutputKind
) {
2806 case Options::kObjectFile
:
2807 fReaderOptions
.fForFinalLinkedImage
= false;
2809 case Options::kDyld
:
2810 fReaderOptions
.fForDyld
= true;
2811 fReaderOptions
.fForFinalLinkedImage
= true;
2812 fReaderOptions
.fNoEHLabels
= true;
2814 case Options::kDynamicLibrary
:
2815 case Options::kDynamicBundle
:
2816 case Options::kKextBundle
:
2817 fReaderOptions
.fForFinalLinkedImage
= true;
2818 fReaderOptions
.fNoEHLabels
= true;
2820 case Options::kDynamicExecutable
:
2821 case Options::kStaticExecutable
:
2822 case Options::kPreload
:
2823 fReaderOptions
.fLinkingMainExecutable
= true;
2824 fReaderOptions
.fForFinalLinkedImage
= true;
2825 fReaderOptions
.fNoEHLabels
= true;
2829 // set default min OS version
2830 if ( (fReaderOptions
.fMacVersionMin
== ObjectFile::ReaderOptions::kMinMacVersionUnset
)
2831 && (fReaderOptions
.fIPhoneVersionMin
== ObjectFile::ReaderOptions::kMinIPhoneVersionUnset
) ) {
2832 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
2833 const char* macVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
2834 const char* iPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
2835 if ( macVers
!= NULL
)
2836 setMacOSXVersionMin(macVers
);
2837 else if ( iPhoneVers
!= NULL
)
2838 setIPhoneVersionMin(iPhoneVers
);
2840 // if still nothing, set default based on architecture
2841 switch ( fArchitecture
) {
2843 case CPU_TYPE_X86_64
:
2844 case CPU_TYPE_POWERPC
:
2845 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_6
; // FIX FIX, this really should be a check of the OS version the linker is running o
2848 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_0
;
2855 // adjust min based on architecture
2856 switch ( fArchitecture
) {
2858 if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_4
) {
2859 //warning("-macosx_version_min should be 10.4 or later for i386");
2860 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_4
;
2863 case CPU_TYPE_POWERPC64
:
2864 if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_4
) {
2865 //warning("-macosx_version_min should be 10.4 or later for ppc64");
2866 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_4
;
2869 case CPU_TYPE_X86_64
:
2870 if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_4
) {
2871 //warning("-macosx_version_min should be 10.4 or later for x86_64");
2872 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_4
;
2877 // adjust kext type based on architecture
2878 if ( fOutputKind
== kKextBundle
) {
2879 switch ( fArchitecture
) {
2880 case CPU_TYPE_X86_64
:
2881 // x86_64 uses new MH_KEXT_BUNDLE type
2882 fMakeClassicDyldInfo
= true;
2883 fMakeCompressedDyldInfo
= false;
2884 fAllowTextRelocs
= true;
2885 fUndefinedTreatment
= kUndefinedDynamicLookup
;
2887 case CPU_TYPE_POWERPC
:
2891 fOutputKind
= kObjectFile
;
2896 // disable implicit dylibs when targeting 10.3
2897 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
2898 if ( !minOS(ObjectFile::ReaderOptions::k10_4
, ObjectFile::ReaderOptions::k2_0
) )
2899 fReaderOptions
.fImplicitlyLinkPublicDylibs
= false;
2902 // allow build system to force linker to ignore -prebind
2903 if ( getenv("LD_FORCE_NO_PREBIND") != NULL
)
2906 // allow build system to force linker to ignore -seg_addr_table
2907 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL
)
2908 fSegAddrTablePath
= NULL
;
2910 // check for base address specified externally
2911 if ( (fSegAddrTablePath
!= NULL
) && (fOutputKind
== Options::kDynamicLibrary
) ) {
2912 parseSegAddrTable(fSegAddrTablePath
, this->installPath());
2913 // HACK to support seg_addr_table entries that are physical paths instead of install paths
2914 if ( fBaseAddress
== 0 ) {
2915 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
2916 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.4.dylib");
2917 if ( fBaseAddress
== 0 )
2918 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.9.dylib");
2921 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
2922 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libz.1.2.3.dylib");
2924 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
2925 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libutil1.0.dylib");
2929 // split segs only allowed for dylibs
2931 // split seg only supported for ppc, i386, and arm.
2932 switch ( fArchitecture
) {
2933 case CPU_TYPE_POWERPC
:
2935 if ( fOutputKind
!= Options::kDynamicLibrary
)
2937 // make sure read and write segments are proper distance apart
2938 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x10000000) )
2939 fBaseWritableAddress
= fBaseAddress
+ 0x10000000;
2942 if ( fOutputKind
!= Options::kDynamicLibrary
) {
2946 // make sure read and write segments are proper distance apart
2947 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x08000000) )
2948 fBaseWritableAddress
= fBaseAddress
+ 0x08000000;
2954 fBaseWritableAddress
= 0;
2958 // <rdar://problem/6138961> -r implies no prebinding for all architectures
2959 if ( fOutputKind
== Options::kObjectFile
)
2962 // disable prebinding depending on arch and min OS version
2964 switch ( fArchitecture
) {
2965 case CPU_TYPE_POWERPC
:
2967 if ( fReaderOptions
.fMacVersionMin
== ObjectFile::ReaderOptions::k10_4
) {
2968 // in 10.4 only split seg dylibs are prebound
2969 if ( (fOutputKind
!= Options::kDynamicLibrary
) || ! fSplitSegs
)
2972 else if ( fReaderOptions
.fMacVersionMin
>= ObjectFile::ReaderOptions::k10_5
) {
2973 // in 10.5 nothing is prebound
2977 // in 10.3 and earlier only dylibs and main executables could be prebound
2978 switch ( fOutputKind
) {
2979 case Options::kDynamicExecutable
:
2980 case Options::kDynamicLibrary
:
2981 // only main executables and dylibs can be prebound
2983 case Options::kStaticExecutable
:
2984 case Options::kDynamicBundle
:
2985 case Options::kObjectFile
:
2986 case Options::kDyld
:
2987 case Options::kPreload
:
2988 case Options::kKextBundle
:
2989 // disable prebinding for everything else
2995 case CPU_TYPE_POWERPC64
:
2996 case CPU_TYPE_X86_64
:
3000 switch ( fOutputKind
) {
3001 case Options::kDynamicExecutable
:
3002 case Options::kDynamicLibrary
:
3003 // only main executables and dylibs can be prebound
3005 case Options::kStaticExecutable
:
3006 case Options::kDynamicBundle
:
3007 case Options::kObjectFile
:
3008 case Options::kDyld
:
3009 case Options::kPreload
:
3010 case Options::kKextBundle
:
3011 // disable prebinding for everything else
3019 // only prebound images can be split-seg
3020 if ( fSplitSegs
&& !fPrebind
)
3023 // determine if info for shared region should be added
3024 if ( fOutputKind
== Options::kDynamicLibrary
) {
3025 if ( minOS(ObjectFile::ReaderOptions::k10_5
, ObjectFile::ReaderOptions::k3_1
) )
3027 if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
3028 || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
3029 fSharedRegionEligible
= true;
3032 // figure out if module table is needed for compatibility with old ld/dyld
3033 if ( fOutputKind
== Options::kDynamicLibrary
) {
3034 switch ( fArchitecture
) {
3035 case CPU_TYPE_POWERPC
: // 10.3 and earlier dyld requires a module table
3036 case CPU_TYPE_I386
: // ld_classic for 10.4.x requires a module table
3037 if ( fReaderOptions
.fMacVersionMin
<= ObjectFile::ReaderOptions::k10_5
)
3038 fNeedsModuleTable
= true;
3042 fNeedsModuleTable
= true; // redo_prebinding requires a module table
3047 // <rdar://problem/5366363> -r -x implies -S
3048 if ( (fOutputKind
== Options::kObjectFile
) && (fLocalSymbolHandling
== kLocalSymbolsNone
) )
3049 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
3051 // choose how to process unwind info
3052 switch ( fArchitecture
) {
3054 case CPU_TYPE_X86_64
:
3055 switch ( fOutputKind
) {
3056 case Options::kObjectFile
:
3057 case Options::kStaticExecutable
:
3058 case Options::kPreload
:
3059 case Options::kKextBundle
:
3060 fReaderOptions
.fAddCompactUnwindEncoding
= false;
3062 case Options::kDyld
:
3063 case Options::kDynamicLibrary
:
3064 case Options::kDynamicBundle
:
3065 case Options::kDynamicExecutable
:
3066 //if ( fReaderOptions.fAddCompactUnwindEncoding && (fReaderOptions.fVersionMin >= ObjectFile::ReaderOptions::k10_6) )
3067 // fReaderOptions.fRemoveDwarfUnwindIfCompactExists = true;
3071 case CPU_TYPE_POWERPC
:
3072 case CPU_TYPE_POWERPC64
:
3074 fReaderOptions
.fAddCompactUnwindEncoding
= false;
3075 fReaderOptions
.fRemoveDwarfUnwindIfCompactExists
= false;
3078 // if -arch is missing, assume we don't want compact unwind info
3079 fReaderOptions
.fAddCompactUnwindEncoding
= false;
3083 // only ARM main executables can be encrypted
3084 if ( fOutputKind
!= Options::kDynamicExecutable
)
3085 fEncryptable
= false;
3086 if ( fArchitecture
!= CPU_TYPE_ARM
)
3087 fEncryptable
= false;
3089 // don't move inits in dyld because dyld wants certain
3090 // entries point at stable locations at the start of __text
3091 if ( fOutputKind
== Options::kDyld
)
3092 fReaderOptions
.fAutoOrderInitializers
= false;
3095 // disable __data ordering for some output kinds
3096 switch ( fOutputKind
) {
3097 case Options::kObjectFile
:
3098 case Options::kDyld
:
3099 case Options::kStaticExecutable
:
3100 case Options::kPreload
:
3101 case Options::kKextBundle
:
3104 case Options::kDynamicExecutable
:
3105 case Options::kDynamicLibrary
:
3106 case Options::kDynamicBundle
:
3110 // only use compressed LINKEDIT for:
3111 // x86_64 and i386 on Mac OS X 10.6 or later
3112 // arm on iPhoneOS 3.1 or later
3113 if ( fMakeCompressedDyldInfo
) {
3114 switch (fArchitecture
) {
3116 case CPU_TYPE_X86_64
:
3117 if ( fReaderOptions
.fMacVersionMin
>= ObjectFile::ReaderOptions::k10_6
)
3118 fMakeClassicDyldInfo
= false;
3119 else if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_5
)
3120 fMakeCompressedDyldInfo
= false;
3123 if ( fReaderOptions
.fIPhoneVersionMin
>= ObjectFile::ReaderOptions::k3_1
)
3124 fMakeClassicDyldInfo
= false;
3125 else if ( fReaderOptions
.fIPhoneVersionMin
< ObjectFile::ReaderOptions::k3_1
)
3126 fMakeCompressedDyldInfo
= false;
3128 case CPU_TYPE_POWERPC
:
3129 case CPU_TYPE_POWERPC64
:
3131 fMakeCompressedDyldInfo
= false;
3136 // only use compressed LINKEDIT for final linked images
3137 if ( fMakeCompressedDyldInfo
) {
3138 switch ( fOutputKind
) {
3139 case Options::kDynamicExecutable
:
3140 case Options::kDynamicLibrary
:
3141 case Options::kDynamicBundle
:
3143 case Options::kPreload
:
3144 case Options::kStaticExecutable
:
3145 case Options::kObjectFile
:
3146 case Options::kDyld
:
3147 case Options::kKextBundle
:
3148 fMakeCompressedDyldInfo
= false;
3152 fReaderOptions
.fMakeCompressedDyldInfo
= fMakeCompressedDyldInfo
;
3154 // only ARM enforces that cpu-sub-types must match
3155 if ( fArchitecture
!= CPU_TYPE_ARM
)
3156 fAllowCpuSubtypeMismatches
= true;
3158 // only final linked images can not optimize zero fill sections
3159 if ( fOutputKind
== Options::kObjectFile
)
3160 fReaderOptions
.fOptimizeZeroFill
= true;
3162 // only dynamic final linked images should warn about use of commmons
3163 if ( fWarnCommons
) {
3164 switch ( fOutputKind
) {
3165 case Options::kDynamicExecutable
:
3166 case Options::kDynamicLibrary
:
3167 case Options::kDynamicBundle
:
3169 case Options::kPreload
:
3170 case Options::kStaticExecutable
:
3171 case Options::kObjectFile
:
3172 case Options::kDyld
:
3173 case Options::kKextBundle
:
3174 fWarnCommons
= false;
3179 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
3180 if ( minOS(ObjectFile::ReaderOptions::k10_5
, ObjectFile::ReaderOptions::k2_0
) )
3181 fUseSimplifiedDylibReExports
= true;
3184 void Options::checkIllegalOptionCombinations()
3186 // check -undefined setting
3187 switch ( fUndefinedTreatment
) {
3188 case kUndefinedError
:
3189 case kUndefinedDynamicLookup
:
3192 case kUndefinedWarning
:
3193 case kUndefinedSuppress
:
3194 // requires flat namespace
3195 if ( fNameSpace
== kTwoLevelNameSpace
)
3196 throw "can't use -undefined warning or suppress with -twolevel_namespace";
3200 // unify -sub_umbrella with dylibs
3201 for (std::vector
<const char*>::iterator it
= fSubUmbellas
.begin(); it
!= fSubUmbellas
.end(); it
++) {
3202 const char* subUmbrella
= *it
;
3204 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
3205 Options::FileInfo
& info
= *fit
;
3206 const char* lastSlash
= strrchr(info
.path
, '/');
3207 if ( lastSlash
== NULL
)
3208 lastSlash
= info
.path
- 1;
3209 if ( strcmp(&lastSlash
[1], subUmbrella
) == 0 ) {
3210 info
.options
.fReExport
= true;
3216 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella
);
3219 // unify -sub_library with dylibs
3220 for (std::vector
<const char*>::iterator it
= fSubLibraries
.begin(); it
!= fSubLibraries
.end(); it
++) {
3221 const char* subLibrary
= *it
;
3223 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
3224 Options::FileInfo
& info
= *fit
;
3225 const char* lastSlash
= strrchr(info
.path
, '/');
3226 if ( lastSlash
== NULL
)
3227 lastSlash
= info
.path
- 1;
3228 const char* dot
= strchr(&lastSlash
[1], '.');
3230 dot
= &lastSlash
[strlen(lastSlash
)];
3231 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
3232 info
.options
.fReExport
= true;
3238 warning("-sub_library %s does not match a supplied dylib", subLibrary
);
3241 // sync reader options
3242 if ( fNameSpace
!= kTwoLevelNameSpace
)
3243 fReaderOptions
.fFlatNamespace
= true;
3245 // check -stack_addr
3246 if ( fStackAddr
!= 0 ) {
3247 switch (fArchitecture
) {
3249 case CPU_TYPE_POWERPC
:
3251 if ( fStackAddr
> 0xFFFFFFFF )
3252 throw "-stack_addr must be < 4G for 32-bit processes";
3254 case CPU_TYPE_POWERPC64
:
3255 case CPU_TYPE_X86_64
:
3258 if ( (fStackAddr
& -4096) != fStackAddr
)
3259 throw "-stack_addr must be multiples of 4K";
3260 if ( fStackSize
== 0 )
3261 throw "-stack_addr must be used with -stack_size";
3264 // check -stack_size
3265 if ( fStackSize
!= 0 ) {
3266 switch (fArchitecture
) {
3268 case CPU_TYPE_POWERPC
:
3269 if ( fStackSize
> 0xFFFFFFFF )
3270 throw "-stack_size must be < 4G for 32-bit processes";
3271 if ( fStackAddr
== 0 ) {
3272 fStackAddr
= 0xC0000000;
3274 if ( (fStackAddr
> 0xB0000000) && ((fStackAddr
-fStackSize
) < 0xB0000000) )
3275 warning("custom stack placement overlaps and will disable shared region");
3278 if ( fStackSize
> 0x2F000000 )
3279 throw "-stack_size must be < 752MB";
3280 if ( fStackAddr
== 0 )
3281 fStackAddr
= 0x2F000000;
3282 if ( fStackAddr
> 0x30000000)
3283 throw "-stack_addr must be < 0x30000000 for arm";
3284 case CPU_TYPE_POWERPC64
:
3285 case CPU_TYPE_X86_64
:
3286 if ( fStackAddr
== 0 ) {
3287 fStackAddr
= 0x00007FFF5C000000LL
;
3291 if ( (fStackSize
& -4096) != fStackSize
)
3292 throw "-stack_size must be multiples of 4K";
3293 switch ( fOutputKind
) {
3294 case Options::kDynamicExecutable
:
3295 case Options::kStaticExecutable
:
3296 // custom stack size only legal when building main executable
3298 case Options::kDynamicLibrary
:
3299 case Options::kDynamicBundle
:
3300 case Options::kObjectFile
:
3301 case Options::kDyld
:
3302 case Options::kPreload
:
3303 case Options::kKextBundle
:
3304 throw "-stack_size option can only be used when linking a main executable";
3308 // check that -allow_stack_execute is only used with main executables
3309 if ( fExecutableStack
) {
3310 switch ( fOutputKind
) {
3311 case Options::kDynamicExecutable
:
3312 case Options::kStaticExecutable
:
3313 // -allow_stack_execute size only legal when building main executable
3315 case Options::kDynamicLibrary
:
3316 case Options::kDynamicBundle
:
3317 case Options::kObjectFile
:
3318 case Options::kDyld
:
3319 case Options::kPreload
:
3320 case Options::kKextBundle
:
3321 throw "-allow_stack_execute option can only be used when linking a main executable";
3325 // check -client_name is only used when making a bundle or main executable
3326 if ( fClientName
!= NULL
) {
3327 switch ( fOutputKind
) {
3328 case Options::kDynamicExecutable
:
3329 case Options::kDynamicBundle
:
3331 case Options::kStaticExecutable
:
3332 case Options::kDynamicLibrary
:
3333 case Options::kObjectFile
:
3334 case Options::kDyld
:
3335 case Options::kPreload
:
3336 case Options::kKextBundle
:
3337 throw "-client_name can only be used with -bundle";
3341 // check -init is only used when building a dylib
3342 if ( (fInitFunctionName
!= NULL
) && (fOutputKind
!= Options::kDynamicLibrary
) )
3343 throw "-init can only be used with -dynamiclib";
3345 // check -bundle_loader only used with -bundle
3346 if ( (fBundleLoader
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
3347 throw "-bundle_loader can only be used with -bundle";
3349 // check -dtrace not used with -r
3350 if ( (fDtraceScriptName
!= NULL
) && (fOutputKind
== Options::kObjectFile
) )
3351 throw "-dtrace can only be used when creating final linked images";
3353 // check -d can only be used with -r
3354 if ( fReaderOptions
.fMakeTentativeDefinitionsReal
&& (fOutputKind
!= Options::kObjectFile
) )
3355 throw "-d can only be used with -r";
3357 // check that -root_safe is not used with -r
3358 if ( fReaderOptions
.fRootSafe
&& (fOutputKind
== Options::kObjectFile
) )
3359 throw "-root_safe cannot be used with -r";
3361 // check that -setuid_safe is not used with -r
3362 if ( fReaderOptions
.fSetuidSafe
&& (fOutputKind
== Options::kObjectFile
) )
3363 throw "-setuid_safe cannot be used with -r";
3365 // make sure all required exported symbols exist
3366 std::vector
<const char*> impliedExports
;
3367 for (NameSet::iterator it
=fExportSymbols
.regularBegin(); it
!= fExportSymbols
.regularEnd(); it
++) {
3368 const char* name
= *it
;
3369 // never export .eh symbols
3370 const int len
= strlen(name
);
3371 if ( (strcmp(&name
[len
-3], ".eh") == 0) || (strncmp(name
, ".objc_category_name_", 20) == 0) )
3372 warning("ignoring %s in export list", name
);
3374 fInitialUndefines
.push_back(name
);
3375 if ( strncmp(name
, ".objc_class_name_", 17) == 0 ) {
3376 // rdar://problem/4718189 map ObjC class names to new runtime names
3377 switch (fArchitecture
) {
3378 case CPU_TYPE_POWERPC64
:
3379 case CPU_TYPE_X86_64
:
3382 asprintf(&temp
, "_OBJC_CLASS_$_%s", &name
[17]);
3383 impliedExports
.push_back(temp
);
3384 asprintf(&temp
, "_OBJC_METACLASS_$_%s", &name
[17]);
3385 impliedExports
.push_back(temp
);
3390 for (std::vector
<const char*>::iterator it
=impliedExports
.begin(); it
!= impliedExports
.end(); it
++) {
3391 const char* name
= *it
;
3392 fExportSymbols
.insert(name
);
3393 fInitialUndefines
.push_back(name
);
3396 // make sure that -init symbol exist
3397 if ( fInitFunctionName
!= NULL
)
3398 fInitialUndefines
.push_back(fInitFunctionName
);
3400 // check custom segments
3401 if ( fCustomSegmentAddresses
.size() != 0 ) {
3402 // verify no segment is in zero page
3403 if ( fZeroPageSize
!= ULLONG_MAX
) {
3404 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
3405 if ( (it
->address
>= 0) && (it
->address
< fZeroPageSize
) )
3406 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it
->name
, it
->address
);
3409 // verify no duplicates
3410 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
3411 for (std::vector
<SegmentStart
>::iterator it2
= fCustomSegmentAddresses
.begin(); it2
!= fCustomSegmentAddresses
.end(); ++it2
) {
3412 if ( (it
->address
== it2
->address
) && (it
!= it2
) )
3413 throwf("duplicate -segaddr addresses for %s and %s", it
->name
, it2
->name
);
3415 // a custom segment address of zero will disable the use of a zero page
3416 if ( it
->address
== 0 )
3421 if ( fZeroPageSize
== ULLONG_MAX
) {
3422 // zero page size not specified on command line, set default
3423 switch (fArchitecture
) {
3425 case CPU_TYPE_POWERPC
:
3427 // first 4KB for 32-bit architectures
3428 fZeroPageSize
= 0x1000;
3430 case CPU_TYPE_POWERPC64
:
3431 // first 4GB for ppc64 on 10.5
3432 if ( fReaderOptions
.fMacVersionMin
>= ObjectFile::ReaderOptions::k10_5
)
3433 fZeroPageSize
= 0x100000000ULL
;
3435 fZeroPageSize
= 0x1000; // 10.4 dyld may not be able to handle >4GB zero page
3437 case CPU_TYPE_X86_64
:
3438 // first 4GB for x86_64 on all OS's
3439 fZeroPageSize
= 0x100000000ULL
;
3442 // if -arch not used, default to 4K zero-page
3443 fZeroPageSize
= 0x1000;
3447 switch ( fOutputKind
) {
3448 case Options::kDynamicExecutable
:
3449 case Options::kStaticExecutable
:
3450 // -pagezero_size size only legal when building main executable
3452 case Options::kDynamicLibrary
:
3453 case Options::kDynamicBundle
:
3454 case Options::kObjectFile
:
3455 case Options::kDyld
:
3456 case Options::kPreload
:
3457 case Options::kKextBundle
:
3458 if ( fZeroPageSize
!= 0 )
3459 throw "-pagezero_size option can only be used when linking a main executable";
3463 // -dead_strip and -r are incompatible
3464 if ( (fDeadStrip
!= kDeadStripOff
) && (fOutputKind
== Options::kObjectFile
) )
3465 throw "-r and -dead_strip cannot be used together";
3467 // can't use -rpath unless targeting 10.5 or later
3468 if ( fRPaths
.size() > 0 ) {
3469 if ( !minOS(ObjectFile::ReaderOptions::k10_5
, ObjectFile::ReaderOptions::k2_0
) )
3470 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
3471 switch ( fOutputKind
) {
3472 case Options::kDynamicExecutable
:
3473 case Options::kDynamicLibrary
:
3474 case Options::kDynamicBundle
:
3476 case Options::kStaticExecutable
:
3477 case Options::kObjectFile
:
3478 case Options::kDyld
:
3479 case Options::kPreload
:
3480 case Options::kKextBundle
:
3481 throw "-rpath can only be used when creating a dynamic final linked image";
3485 // check -pie is only used when building a dynamic main executable for 10.5
3486 if ( fPositionIndependentExecutable
) {
3487 switch ( fOutputKind
) {
3488 case Options::kDynamicExecutable
:
3489 case Options::kPreload
:
3491 case Options::kDynamicLibrary
:
3492 case Options::kDynamicBundle
:
3493 warning("-pie being ignored. It is only used when linking a main executable");
3495 case Options::kStaticExecutable
:
3496 case Options::kObjectFile
:
3497 case Options::kDyld
:
3498 case Options::kKextBundle
:
3499 throw "-pie can only be used when linking a main executable";
3501 if ( !minOS(ObjectFile::ReaderOptions::k10_5
, ObjectFile::ReaderOptions::k2_0
) )
3502 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
3505 // check -read_only_relocs is not used with x86_64
3506 if ( fAllowTextRelocs
) {
3507 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
!= kKextBundle
) ) {
3508 warning("-read_only_relocs cannot be used with x86_64");
3509 fAllowTextRelocs
= false;
3513 // check -mark_auto_dead_strip is only used with dylibs
3514 if ( fMarkDeadStrippableDylib
) {
3515 if ( fOutputKind
!= Options::kDynamicLibrary
) {
3516 warning("-mark_auto_dead_strip can only be used when creating a dylib");
3517 fMarkDeadStrippableDylib
= false;
3521 // -force_cpusubtype_ALL is not supported for ARM
3522 if ( fForceSubtypeAll
) {
3523 if ( fArchitecture
== CPU_TYPE_ARM
) {
3524 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
3530 void Options::checkForClassic(int argc
, const char* argv
[])
3533 bool archFound
= false;
3534 bool staticFound
= false;
3535 bool dtraceFound
= false;
3536 bool kextFound
= false;
3537 bool rFound
= false;
3538 bool creatingMachKernel
= false;
3539 bool newLinker
= false;
3541 // build command line buffer in case ld crashes
3542 for(int i
=1; i
< argc
; ++i
) {
3543 strlcat(crashreporterBuffer
, argv
[i
], 1000);
3544 strlcat(crashreporterBuffer
, " ", 1000);
3547 for(int i
=0; i
< argc
; ++i
) {
3548 const char* arg
= argv
[i
];
3549 if ( arg
[0] == '-' ) {
3550 if ( strcmp(arg
, "-arch") == 0 ) {
3551 parseArch(argv
[++i
]);
3554 else if ( strcmp(arg
, "-static") == 0 ) {
3557 else if ( strcmp(arg
, "-kext") == 0 ) {
3560 else if ( strcmp(arg
, "-dtrace") == 0 ) {
3563 else if ( strcmp(arg
, "-r") == 0 ) {
3566 else if ( strcmp(arg
, "-new_linker") == 0 ) {
3569 else if ( strcmp(arg
, "-classic_linker") == 0 ) {
3570 // ld_classic does not understand this option, so remove it
3571 for(int j
=i
; j
< argc
; ++j
)
3572 argv
[j
] = argv
[j
+1];
3573 this->gotoClassicLinker(argc
-1, argv
);
3575 else if ( strcmp(arg
, "-o") == 0 ) {
3576 const char* outfile
= argv
[++i
];
3577 if ( (outfile
!= NULL
) && (strstr(outfile
, "/mach_kernel") != NULL
) )
3578 creatingMachKernel
= true;
3583 // -dtrace only supported by new linker
3588 switch ( fArchitecture
) {
3589 case CPU_TYPE_POWERPC
:
3592 // if ( staticFound && (rFound || !creatingMachKernel) ) {
3593 if ( (staticFound
|| kextFound
) && !newLinker
) {
3594 // this environment variable will disable use of ld_classic for -static links
3595 if ( getenv("LD_NO_CLASSIC_LINKER_STATIC") == NULL
) {
3596 // ld_classic does not support -iphoneos_version_min, so change
3597 for(int j
=0; j
< argc
; ++j
) {
3598 if ( strcmp(argv
[j
], "-iphoneos_version_min") == 0) {
3599 argv
[j
] = "-macosx_version_min";
3605 // ld classic does not understand -kext (change to -static -r)
3607 for(int j
=0; j
< argc
; ++j
) {
3608 if ( strcmp(argv
[j
], "-kext") == 0)
3610 else if ( strcmp(argv
[j
], "-dynamic") == 0)
3611 argv
[j
] = "-static";
3614 this->gotoClassicLinker(argc
, argv
);
3621 // work around for VSPTool
3623 this->gotoClassicLinker(argc
, argv
);
3628 void Options::gotoClassicLinker(int argc
, const char* argv
[])
3630 argv
[0] = "ld_classic";
3631 char rawPath
[PATH_MAX
];
3632 char path
[PATH_MAX
];
3633 uint32_t bufSize
= PATH_MAX
;
3634 if ( _NSGetExecutablePath(rawPath
, &bufSize
) != -1 ) {
3635 if ( realpath(rawPath
, path
) != NULL
) {
3636 char* lastSlash
= strrchr(path
, '/');
3637 if ( lastSlash
!= NULL
) {
3638 strcpy(lastSlash
+1, "ld_classic");
3640 execvp(path
, (char**)argv
);
3644 // in case of error in above, try searching for ld_classic via PATH
3645 execvp(argv
[0], (char**)argv
);
3646 fprintf(stderr
, "can't exec ld_classic\n");