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), fOrderData(true), fMarkDeadStrippableDylib(false),
105 fMakeClassicDyldInfo(true), fMakeCompressedDyldInfo(true), fAllowCpuSubtypeMismatches(false), fSaveTempFiles(false)
107 this->checkForClassic(argc
, argv
);
108 this->parsePreCommandLineEnvironmentSettings();
109 this->parse(argc
, argv
);
110 this->parsePostCommandLineEnvironmentSettings();
111 this->reconfigureDefaults();
112 this->checkIllegalOptionCombinations();
119 const ObjectFile::ReaderOptions
& Options::readerOptions()
121 return fReaderOptions
;
125 const char* Options::getOutputFilePath()
130 std::vector
<Options::FileInfo
>& Options::getInputFiles()
135 Options::OutputKind
Options::outputKind()
140 bool Options::bindAtLoad()
145 bool Options::prebind()
150 bool Options::fullyLoadArchives()
152 return fReaderOptions
.fFullyLoadArchives
;
155 Options::NameSpace
Options::nameSpace()
160 const char* Options::installPath()
162 if ( fDylibInstallName
!= NULL
)
163 return fDylibInstallName
;
164 else if ( fFinalName
!= NULL
)
170 uint32_t Options::currentVersion()
172 return fDylibCurrentVersion
;
175 uint32_t Options::compatibilityVersion()
177 return fDylibCompatVersion
;
180 const char* Options::entryName()
185 uint64_t Options::baseAddress()
190 bool Options::keepPrivateExterns()
192 return fKeepPrivateExterns
;
195 bool Options::interposable(const char* name
)
197 switch ( fInterposeMode
) {
200 case kInterposeAllExternal
:
203 return fInterposeList
.contains(name
);
205 throw "internal error";
208 bool Options::needsModuleTable()
210 return fNeedsModuleTable
;
213 bool Options::ignoreOtherArchInputFiles()
215 return fIgnoreOtherArchFiles
;
218 bool Options::forceCpuSubtypeAll()
220 return fForceSubtypeAll
;
223 bool Options::traceDylibs()
225 return fReaderOptions
.fTraceDylibs
;
228 bool Options::traceArchives()
230 return fReaderOptions
.fTraceArchives
;
233 Options::UndefinedTreatment
Options::undefinedTreatment()
235 return fUndefinedTreatment
;
238 Options::WeakReferenceMismatchTreatment
Options::weakReferenceMismatchTreatment()
240 return fWeakReferenceMismatchTreatment
;
243 const char* Options::umbrellaName()
245 return fUmbrellaName
;
248 std::vector
<const char*>& Options::allowableClients()
250 return fAllowableClients
;
253 const char* Options::clientName()
258 uint64_t Options::zeroPageSize()
260 return fZeroPageSize
;
263 bool Options::hasCustomStack()
265 return (fStackSize
!= 0);
268 uint64_t Options::customStackSize()
273 uint64_t Options::customStackAddr()
278 bool Options::hasExecutableStack()
280 return fExecutableStack
;
283 std::vector
<const char*>& Options::initialUndefines()
285 return fInitialUndefines
;
288 bool Options::printWhyLive(const char* symbolName
)
290 return ( fWhyLive
.find(symbolName
) != fWhyLive
.end() );
294 const char* Options::initFunctionName()
296 return fInitFunctionName
;
299 const char* Options::dotOutputFile()
301 return fDotOutputFile
;
304 bool Options::hasExportRestrictList()
306 return (fExportMode
!= kExportDefault
);
309 bool Options::hasExportMaskList()
311 return (fExportMode
== kExportSome
);
315 bool Options::hasWildCardExportRestrictList()
317 // has -exported_symbols_list which contains some wildcards
318 return ((fExportMode
== kExportSome
) && fExportSymbols
.hasWildCards());
322 bool Options::allGlobalsAreDeadStripRoots()
324 // -exported_symbols_list means globals are not exported by default
325 if ( fExportMode
== kExportSome
)
328 switch ( fOutputKind
) {
329 case Options::kDynamicExecutable
:
330 case Options::kStaticExecutable
:
331 case Options::kPreload
:
332 // by default unused globals in a main executable are stripped
334 case Options::kDynamicLibrary
:
335 case Options::kDynamicBundle
:
336 case Options::kObjectFile
:
338 case Options::kKextBundle
:
344 uint32_t Options::minimumHeaderPad()
346 return fMinimumHeaderPad
;
349 std::vector
<Options::ExtraSection
>& Options::extraSections()
351 return fExtraSections
;
354 std::vector
<Options::SectionAlignment
>& Options::sectionAlignments()
356 return fSectionAlignments
;
359 Options::CommonsMode
Options::commonsMode()
364 bool Options::warnCommons()
369 bool Options::keepRelocations()
371 return fKeepRelocations
;
374 bool Options::warnStabs()
379 const char* Options::executablePath()
381 return fExecutablePath
;
384 Options::DeadStripMode
Options::deadStrip()
389 bool Options::hasExportedSymbolOrder()
391 return (fExportSymbolsOrder
.size() > 0);
394 bool Options::exportedSymbolOrder(const char* sym
, unsigned int* order
)
396 NameToOrder::iterator pos
= fExportSymbolsOrder
.find(sym
);
397 if ( pos
!= fExportSymbolsOrder
.end() ) {
398 *order
= pos
->second
;
407 void Options::loadSymbolOrderFile(const char* fileOfExports
, NameToOrder
& orderMapping
)
409 // read in whole file
410 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
412 throwf("can't open -exported_symbols_order file: %s", fileOfExports
);
413 struct stat stat_buf
;
414 ::fstat(fd
, &stat_buf
);
415 char* p
= (char*)malloc(stat_buf
.st_size
);
417 throwf("can't process -exported_symbols_order file: %s", fileOfExports
);
419 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
420 throwf("can't read -exported_symbols_order file: %s", fileOfExports
);
424 // parse into symbols and add to hash_set
425 unsigned int count
= 0;
426 char * const end
= &p
[stat_buf
.st_size
];
427 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
428 char* symbolStart
= NULL
;
429 for (char* s
= p
; s
< end
; ++s
) {
435 else if ( !isspace(*s
) ) {
441 if ( (*s
== '\n') || (*s
== '\r') ) {
443 // removing any trailing spaces
445 while ( isspace(*last
) ) {
449 orderMapping
[symbolStart
] = ++count
;
455 if ( (*s
== '\n') || (*s
== '\r') )
460 if ( state
== inSymbol
) {
461 warning("missing line-end at end of file \"%s\"", fileOfExports
);
462 int len
= end
-symbolStart
+1;
463 char* temp
= new char[len
];
464 strlcpy(temp
, symbolStart
, len
);
466 // remove any trailing spaces
467 char* last
= &temp
[len
-2];
468 while ( isspace(*last
) ) {
472 orderMapping
[temp
] = ++count
;
475 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
479 bool Options::shouldExport(const char* symbolName
)
481 switch (fExportMode
) {
483 return fExportSymbols
.contains(symbolName
);
484 case kDontExportSome
:
485 return ! fDontExportSymbols
.contains(symbolName
);
489 throw "internal error";
492 bool Options::keepLocalSymbol(const char* symbolName
)
494 switch (fLocalSymbolHandling
) {
495 case kLocalSymbolsAll
:
497 case kLocalSymbolsNone
:
499 case kLocalSymbolsSelectiveInclude
:
500 return fLocalSymbolsIncluded
.contains(symbolName
);
501 case kLocalSymbolsSelectiveExclude
:
502 return ! fLocalSymbolsExcluded
.contains(symbolName
);
504 throw "internal error";
507 void Options::parseArch(const char* architecture
)
509 if ( architecture
== NULL
)
510 throw "-arch must be followed by an architecture string";
511 if ( strcmp(architecture
, "ppc") == 0 ) {
512 fArchitecture
= CPU_TYPE_POWERPC
;
513 fSubArchitecture
= CPU_SUBTYPE_POWERPC_ALL
;
515 else if ( strcmp(architecture
, "ppc64") == 0 ) {
516 fArchitecture
= CPU_TYPE_POWERPC64
;
517 fSubArchitecture
= CPU_SUBTYPE_POWERPC_ALL
;
519 else if ( strcmp(architecture
, "i386") == 0 ) {
520 fArchitecture
= CPU_TYPE_I386
;
521 fSubArchitecture
= CPU_SUBTYPE_I386_ALL
;
523 else if ( strcmp(architecture
, "x86_64") == 0 ) {
524 fArchitecture
= CPU_TYPE_X86_64
;
525 fSubArchitecture
= CPU_SUBTYPE_X86_64_ALL
;
527 else if ( strcmp(architecture
, "arm") == 0 ) {
528 fArchitecture
= CPU_TYPE_ARM
;
529 fSubArchitecture
= CPU_SUBTYPE_ARM_ALL
;
531 // compatibility support for cpu-sub-types
532 else if ( strcmp(architecture
, "ppc750") == 0 ) {
533 fArchitecture
= CPU_TYPE_POWERPC
;
534 fSubArchitecture
= CPU_SUBTYPE_POWERPC_750
;
535 fHasPreferredSubType
= true;
537 else if ( strcmp(architecture
, "ppc7400") == 0 ) {
538 fArchitecture
= CPU_TYPE_POWERPC
;
539 fSubArchitecture
= CPU_SUBTYPE_POWERPC_7400
;
540 fHasPreferredSubType
= true;
542 else if ( strcmp(architecture
, "ppc7450") == 0 ) {
543 fArchitecture
= CPU_TYPE_POWERPC
;
544 fSubArchitecture
= CPU_SUBTYPE_POWERPC_7450
;
545 fHasPreferredSubType
= true;
547 else if ( strcmp(architecture
, "ppc970") == 0 ) {
548 fArchitecture
= CPU_TYPE_POWERPC
;
549 fSubArchitecture
= CPU_SUBTYPE_POWERPC_970
;
550 fHasPreferredSubType
= true;
552 else if ( strcmp(architecture
, "armv6") == 0 ) {
553 fArchitecture
= CPU_TYPE_ARM
;
554 fSubArchitecture
= CPU_SUBTYPE_ARM_V6
;
555 fHasPreferredSubType
= true;
557 else if ( strcmp(architecture
, "armv5") == 0 ) {
558 fArchitecture
= CPU_TYPE_ARM
;
559 fSubArchitecture
= CPU_SUBTYPE_ARM_V5TEJ
;
560 fHasPreferredSubType
= true;
562 else if ( strcmp(architecture
, "armv4t") == 0 ) {
563 fArchitecture
= CPU_TYPE_ARM
;
564 fSubArchitecture
= CPU_SUBTYPE_ARM_V4T
;
565 fHasPreferredSubType
= true;
567 else if ( strcmp(architecture
, "xscale") == 0 ) {
568 fArchitecture
= CPU_TYPE_ARM
;
569 fSubArchitecture
= CPU_SUBTYPE_ARM_XSCALE
;
570 fHasPreferredSubType
= true;
572 else if ( strcmp(architecture
, "armv7") == 0 ) {
573 fArchitecture
= CPU_TYPE_ARM
;
574 fSubArchitecture
= CPU_SUBTYPE_ARM_V7
;
575 fHasPreferredSubType
= true;
578 throwf("unknown/unsupported architecture name for: -arch %s", architecture
);
581 bool Options::checkForFile(const char* format
, const char* dir
, const char* rootName
, FileInfo
& result
)
583 struct stat statBuffer
;
584 char possiblePath
[strlen(dir
)+strlen(rootName
)+strlen(format
)+8];
585 sprintf(possiblePath
, format
, dir
, rootName
);
586 bool found
= (stat(possiblePath
, &statBuffer
) == 0);
587 if ( fTraceDylibSearching
)
588 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), possiblePath
);
590 result
.path
= strdup(possiblePath
);
591 result
.fileLen
= statBuffer
.st_size
;
592 result
.modTime
= statBuffer
.st_mtime
;
599 Options::FileInfo
Options::findLibrary(const char* rootName
, bool dylibsOnly
)
602 const int rootNameLen
= strlen(rootName
);
603 // if rootName ends in .o there is no .a vs .dylib choice
604 if ( (rootNameLen
> 3) && (strcmp(&rootName
[rootNameLen
-2], ".o") == 0) ) {
605 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
606 it
!= fLibrarySearchPaths
.end();
608 const char* dir
= *it
;
609 if ( checkForFile("%s/%s", dir
, rootName
, result
) )
614 bool lookForDylibs
= ( fOutputKind
!= Options::kDyld
);
615 switch ( fLibrarySearchMode
) {
616 case kSearchAllDirsForDylibsThenAllDirsForArchives
:
617 // first look in all directories for just for dylibs
618 if ( lookForDylibs
) {
619 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
620 it
!= fLibrarySearchPaths
.end();
622 const char* dir
= *it
;
623 if ( checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
626 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
627 it
!= fLibrarySearchPaths
.end();
629 const char* dir
= *it
;
630 if ( checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
634 // next look in all directories for just for archives
636 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
637 it
!= fLibrarySearchPaths
.end();
639 const char* dir
= *it
;
640 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
646 case kSearchDylibAndArchiveInEachDir
:
647 // look in each directory for just for a dylib then for an archive
648 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
649 it
!= fLibrarySearchPaths
.end();
651 const char* dir
= *it
;
652 if ( lookForDylibs
&& checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
654 if ( lookForDylibs
&& checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
656 if ( !dylibsOnly
&& checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
662 throwf("library not found for -l%s", rootName
);
665 Options::FileInfo
Options::findFramework(const char* frameworkName
)
667 if ( frameworkName
== NULL
)
668 throw "-framework missing next argument";
669 char temp
[strlen(frameworkName
)+1];
670 strcpy(temp
, frameworkName
);
671 const char* name
= temp
;
672 const char* suffix
= NULL
;
673 char* comma
= strchr(temp
, ',');
674 if ( comma
!= NULL
) {
678 return findFramework(name
, suffix
);
681 Options::FileInfo
Options::findFramework(const char* rootName
, const char* suffix
)
683 struct stat statBuffer
;
684 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
685 it
!= fFrameworkSearchPaths
.end();
687 // ??? Shouldn't we be using String here and just initializing it?
688 // ??? Use str.c_str () to pull out the string for the stat call.
689 const char* dir
= *it
;
690 char possiblePath
[PATH_MAX
];
691 strcpy(possiblePath
, dir
);
692 strcat(possiblePath
, "/");
693 strcat(possiblePath
, rootName
);
694 strcat(possiblePath
, ".framework/");
695 strcat(possiblePath
, rootName
);
696 if ( suffix
!= NULL
) {
697 char realPath
[PATH_MAX
];
698 // no symlink in framework to suffix variants, so follow main symlink
699 if ( realpath(possiblePath
, realPath
) != NULL
) {
700 strcpy(possiblePath
, realPath
);
701 strcat(possiblePath
, suffix
);
704 bool found
= (stat(possiblePath
, &statBuffer
) == 0);
705 if ( fTraceDylibSearching
)
706 printf("[Logging for XBS]%sfound framework: '%s'\n",
707 (found
? " " : " not "), possiblePath
);
710 result
.path
= strdup(possiblePath
);
711 result
.fileLen
= statBuffer
.st_size
;
712 result
.modTime
= statBuffer
.st_mtime
;
716 // try without suffix
717 if ( suffix
!= NULL
)
718 return findFramework(rootName
, NULL
);
720 throwf("framework not found %s", rootName
);
723 Options::FileInfo
Options::findFile(const char* path
)
726 struct stat statBuffer
;
728 // if absolute path and not a .o file, the use SDK prefix
729 if ( (path
[0] == '/') && (strcmp(&path
[strlen(path
)-2], ".o") != 0) ) {
730 const int pathLen
= strlen(path
);
731 for (std::vector
<const char*>::iterator it
= fSDKPaths
.begin(); it
!= fSDKPaths
.end(); it
++) {
732 // ??? Shouldn't we be using String here?
733 const char* sdkPathDir
= *it
;
734 const int sdkPathDirLen
= strlen(sdkPathDir
);
735 char possiblePath
[sdkPathDirLen
+pathLen
+4];
736 strcpy(possiblePath
, sdkPathDir
);
737 if ( possiblePath
[sdkPathDirLen
-1] == '/' )
738 possiblePath
[sdkPathDirLen
-1] = '\0';
739 strcat(possiblePath
, path
);
740 if ( stat(possiblePath
, &statBuffer
) == 0 ) {
741 result
.path
= strdup(possiblePath
);
742 result
.fileLen
= statBuffer
.st_size
;
743 result
.modTime
= statBuffer
.st_mtime
;
749 if ( stat(path
, &statBuffer
) == 0 ) {
750 result
.path
= strdup(path
);
751 result
.fileLen
= statBuffer
.st_size
;
752 result
.modTime
= statBuffer
.st_mtime
;
756 // try @executable_path substitution
757 if ( (strncmp(path
, "@executable_path/", 17) == 0) && (fExecutablePath
!= NULL
) ) {
758 char newPath
[strlen(fExecutablePath
) + strlen(path
)];
759 strcpy(newPath
, fExecutablePath
);
760 char* addPoint
= strrchr(newPath
,'/');
761 if ( addPoint
!= NULL
)
762 strcpy(&addPoint
[1], &path
[17]);
764 strcpy(newPath
, &path
[17]);
765 if ( stat(newPath
, &statBuffer
) == 0 ) {
766 result
.path
= strdup(newPath
);
767 result
.fileLen
= statBuffer
.st_size
;
768 result
.modTime
= statBuffer
.st_mtime
;
774 throwf("file not found: %s", path
);
777 Options::FileInfo
Options::findFileUsingPaths(const char* path
)
781 const char* lastSlash
= strrchr(path
, '/');
782 const char* leafName
= (lastSlash
== NULL
) ? path
: &lastSlash
[1];
784 // Is this in a framework?
785 // /path/Foo.framework/Foo ==> true (Foo)
786 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
787 // /path/Foo.framework/Resources/Bar ==> false
788 bool isFramework
= false;
789 if ( lastSlash
!= NULL
) {
790 char frameworkDir
[strlen(leafName
) + 20];
791 strcpy(frameworkDir
, "/");
792 strcat(frameworkDir
, leafName
);
793 strcat(frameworkDir
, ".framework/");
794 if ( strstr(path
, frameworkDir
) != NULL
)
798 // These are abbreviated versions of the routines findFramework and findLibrary above
799 // because we already know the final name of the file that we're looking for and so
800 // don't need to try variations, just paths. We do need to add the additional bits
801 // onto the framework path though.
803 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
804 it
!= fFrameworkSearchPaths
.end();
806 const char* dir
= *it
;
807 char possiblePath
[PATH_MAX
];
808 strcpy(possiblePath
, dir
);
809 strcat(possiblePath
, "/");
810 strcat(possiblePath
, leafName
);
811 strcat(possiblePath
, ".framework");
813 //fprintf(stderr,"Finding Framework: %s/%s, leafName=%s\n", possiblePath, leafName, leafName);
814 if ( checkForFile("%s/%s", possiblePath
, leafName
, result
) )
819 // if this is a .dylib inside a framework, do not search -L paths
820 // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
821 int leafLen
= strlen(leafName
);
822 bool embeddedDylib
= ( (leafLen
> 6)
823 && (strcmp(&leafName
[leafLen
-6], ".dylib") == 0)
824 && (strstr(path
, ".framework/") != NULL
) );
825 if ( !embeddedDylib
) {
826 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
827 it
!= fLibrarySearchPaths
.end();
829 const char* dir
= *it
;
830 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
831 if ( checkForFile("%s/%s", dir
, leafName
, result
) )
837 // If we didn't find it fall back to findFile.
838 return findFile(path
);
842 void Options::parseSegAddrTable(const char* segAddrPath
, const char* installPath
)
844 FILE* file
= fopen(segAddrPath
, "r");
845 if ( file
== NULL
) {
846 warning("-seg_addr_table file cannot be read: %s", segAddrPath
);
851 uint64_t firstColumAddress
= 0;
852 uint64_t secondColumAddress
= 0;
853 bool hasSecondColumn
= false;
854 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
855 path
[PATH_MAX
-1] = '\0';
856 char* eol
= strchr(path
, '\n');
859 // ignore lines not starting with 0x number
860 if ( (path
[0] == '0') && (path
[1] == 'x') ) {
862 firstColumAddress
= strtoull(path
, &p
, 16);
863 while ( isspace(*p
) )
865 // see if second column is a number
866 if ( (p
[0] == '0') && (p
[1] == 'x') ) {
867 secondColumAddress
= strtoull(p
, &p
, 16);
868 hasSecondColumn
= true;
869 while ( isspace(*p
) )
872 while ( isspace(*p
) )
875 // remove any trailing whitespace
876 for(char* end
= eol
-1; (end
> p
) && isspace(*end
); --end
)
878 // see if this line is for the dylib being linked
879 if ( strcmp(p
, installPath
) == 0 ) {
880 fBaseAddress
= firstColumAddress
;
881 if ( hasSecondColumn
) {
882 fBaseWritableAddress
= secondColumAddress
;
885 break; // out of while loop
894 void Options::loadFileList(const char* fileOfPaths
)
897 const char* comma
= strrchr(fileOfPaths
, ',');
898 const char* prefix
= NULL
;
899 if ( comma
!= NULL
) {
900 // <rdar://problem/5907981> -filelist fails with comma in path
901 file
= fopen(fileOfPaths
, "r");
902 if ( file
== NULL
) {
904 int realFileOfPathsLen
= comma
-fileOfPaths
;
905 char realFileOfPaths
[realFileOfPathsLen
+1];
906 strncpy(realFileOfPaths
,fileOfPaths
, realFileOfPathsLen
);
907 realFileOfPaths
[realFileOfPathsLen
] = '\0';
908 file
= fopen(realFileOfPaths
, "r");
910 throwf("-filelist file not found: %s\n", realFileOfPaths
);
914 file
= fopen(fileOfPaths
, "r");
916 throwf("-filelist file not found: %s\n", fileOfPaths
);
920 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
921 path
[PATH_MAX
-1] = '\0';
922 char* eol
= strchr(path
, '\n');
925 if ( prefix
!= NULL
) {
926 char builtPath
[strlen(prefix
)+strlen(path
)+2];
927 strcpy(builtPath
, prefix
);
928 strcat(builtPath
, "/");
929 strcat(builtPath
, path
);
930 fInputFiles
.push_back(findFile(builtPath
));
933 fInputFiles
.push_back(findFile(path
));
939 bool Options::SetWithWildcards::hasWildCards(const char* symbol
)
941 // an exported symbol name containing *, ?, or [ requires wildcard matching
942 return ( strpbrk(symbol
, "*?[") != NULL
);
945 void Options::SetWithWildcards::insert(const char* symbol
)
947 if ( hasWildCards(symbol
) )
948 fWildCard
.push_back(symbol
);
950 fRegular
.insert(symbol
);
953 bool Options::SetWithWildcards::contains(const char* symbol
)
955 // first look at hash table on non-wildcard symbols
956 if ( fRegular
.find(symbol
) != fRegular
.end() )
958 // next walk list of wild card symbols looking for a match
959 for(std::vector
<const char*>::iterator it
= fWildCard
.begin(); it
!= fWildCard
.end(); ++it
) {
960 if ( wildCardMatch(*it
, symbol
) )
967 bool Options::SetWithWildcards::inCharRange(const char*& p
, unsigned char c
)
971 while ( *p
!= '\0' ) {
974 // found beginining [ and ending ]
975 unsigned char last
= '\0';
976 for ( const char* s
= b
; s
< e
; ++s
) {
978 unsigned char next
= *(++s
);
979 if ( (last
<= c
) && (c
<= next
) )
996 bool Options::SetWithWildcards::wildCardMatch(const char* pattern
, const char* symbol
)
998 const char* s
= symbol
;
999 for (const char* p
= pattern
; *p
!= '\0'; ++p
) {
1004 for (const char* t
= s
; *t
!= '\0'; ++t
) {
1005 if ( wildCardMatch(&p
[1], t
) )
1015 if ( ! inCharRange(p
, *s
) )
1025 return (*s
== '\0');
1029 void Options::loadExportFile(const char* fileOfExports
, const char* option
, SetWithWildcards
& set
)
1031 // read in whole file
1032 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
1034 throwf("can't open %s file: %s", option
, fileOfExports
);
1035 struct stat stat_buf
;
1036 ::fstat(fd
, &stat_buf
);
1037 char* p
= (char*)malloc(stat_buf
.st_size
);
1039 throwf("can't process %s file: %s", option
, fileOfExports
);
1041 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1042 throwf("can't read %s file: %s", option
, fileOfExports
);
1046 // parse into symbols and add to hash_set
1047 char * const end
= &p
[stat_buf
.st_size
];
1048 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1049 char* symbolStart
= NULL
;
1050 for (char* s
= p
; s
< end
; ++s
) {
1056 else if ( !isspace(*s
) ) {
1062 if ( (*s
== '\n') || (*s
== '\r') ) {
1064 // removing any trailing spaces
1066 while ( isspace(*last
) ) {
1070 set
.insert(symbolStart
);
1076 if ( (*s
== '\n') || (*s
== '\r') )
1081 if ( state
== inSymbol
) {
1082 warning("missing line-end at end of file \"%s\"", fileOfExports
);
1083 int len
= end
-symbolStart
+1;
1084 char* temp
= new char[len
];
1085 strlcpy(temp
, symbolStart
, len
);
1087 // remove any trailing spaces
1088 char* last
= &temp
[len
-2];
1089 while ( isspace(*last
) ) {
1096 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
1099 void Options::parseAliasFile(const char* fileOfAliases
)
1101 // read in whole file
1102 int fd
= ::open(fileOfAliases
, O_RDONLY
, 0);
1104 throwf("can't open alias file: %s", fileOfAliases
);
1105 struct stat stat_buf
;
1106 ::fstat(fd
, &stat_buf
);
1107 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1109 throwf("can't process alias file: %s", fileOfAliases
);
1111 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1112 throwf("can't read alias file: %s", fileOfAliases
);
1113 p
[stat_buf
.st_size
] = '\n';
1116 // parse into symbols and add to fAliases
1117 ObjectFile::ReaderOptions::AliasPair pair
;
1118 char * const end
= &p
[stat_buf
.st_size
+1];
1119 enum { lineStart
, inRealName
, inBetween
, inAliasName
, inComment
} state
= lineStart
;
1121 for (char* s
= p
; s
< end
; ++s
) {
1127 else if ( !isspace(*s
) ) {
1134 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1138 else if ( isspace(*s
) ) {
1145 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1149 else if ( ! isspace(*s
) ) {
1150 state
= inAliasName
;
1157 // removing any trailing spaces
1159 while ( isspace(*last
) ) {
1163 fReaderOptions
.fAliases
.push_back(pair
);
1166 else if ( *s
== '\n' ) {
1168 // removing any trailing spaces
1170 while ( isspace(*last
) ) {
1174 fReaderOptions
.fAliases
.push_back(pair
);
1185 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
1190 void Options::setUndefinedTreatment(const char* treatment
)
1192 if ( treatment
== NULL
)
1193 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
1195 if ( strcmp(treatment
, "warning") == 0 )
1196 fUndefinedTreatment
= kUndefinedWarning
;
1197 else if ( strcmp(treatment
, "error") == 0 )
1198 fUndefinedTreatment
= kUndefinedError
;
1199 else if ( strcmp(treatment
, "suppress") == 0 )
1200 fUndefinedTreatment
= kUndefinedSuppress
;
1201 else if ( strcmp(treatment
, "dynamic_lookup") == 0 )
1202 fUndefinedTreatment
= kUndefinedDynamicLookup
;
1204 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1207 Options::Treatment
Options::parseTreatment(const char* treatment
)
1209 if ( treatment
== NULL
)
1212 if ( strcmp(treatment
, "warning") == 0 )
1214 else if ( strcmp(treatment
, "error") == 0 )
1216 else if ( strcmp(treatment
, "suppress") == 0 )
1222 void Options::setMacOSXVersionMin(const char* version
)
1224 if ( version
== NULL
)
1225 throw "-macosx_version_min argument missing";
1227 if ( (strncmp(version
, "10.", 3) == 0) && isdigit(version
[3]) ) {
1228 int num
= version
[3] - '0';
1232 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_1
;
1235 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_2
;
1238 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_3
;
1241 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_4
;
1244 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_5
;
1247 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_6
;
1250 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_6
;
1255 warning("unknown option to -macosx_version_min, not 10.x");
1259 void Options::setIPhoneVersionMin(const char* version
)
1261 if ( version
== NULL
)
1262 throw "-iphoneos_version_min argument missing";
1264 if ( strncmp(version
, "1.", 2) == 0 ) {
1265 warning("pre-2.0 iPhone OS version not supported");
1266 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_0
;
1268 else if ( strncmp(version
, "2.", 2) == 0 ) {
1269 int num
= version
[2] - '0';
1272 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_0
;
1275 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_1
;
1278 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_2
;
1281 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_2
;
1285 else if ( strncmp(version
, "3.", 2) == 0 ) {
1286 int num
= version
[2] - '0';
1289 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k3_0
;
1292 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k3_0
;
1297 warning("unknown option to -iphoneos_version_min, not 2.x or 3.x");
1301 bool Options::minOS(ObjectFile::ReaderOptions::MacVersionMin requiredMacMin
, ObjectFile::ReaderOptions::IPhoneVersionMin requirediPhoneOSMin
)
1303 if ( fReaderOptions
.fMacVersionMin
!= ObjectFile::ReaderOptions::kMinMacVersionUnset
) {
1304 return ( fReaderOptions
.fMacVersionMin
>= requiredMacMin
);
1307 return ( fReaderOptions
.fIPhoneVersionMin
>= requirediPhoneOSMin
);
1312 void Options::setWeakReferenceMismatchTreatment(const char* treatment
)
1314 if ( treatment
== NULL
)
1315 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1317 if ( strcmp(treatment
, "error") == 0 )
1318 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchError
;
1319 else if ( strcmp(treatment
, "weak") == 0 )
1320 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchWeak
;
1321 else if ( strcmp(treatment
, "non-weak") == 0 )
1322 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchNonWeak
;
1324 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1327 Options::CommonsMode
Options::parseCommonsTreatment(const char* mode
)
1330 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1332 if ( strcmp(mode
, "ignore_dylibs") == 0 )
1333 return kCommonsIgnoreDylibs
;
1334 else if ( strcmp(mode
, "use_dylibs") == 0 )
1335 return kCommonsOverriddenByDylibs
;
1336 else if ( strcmp(mode
, "error") == 0 )
1337 return kCommonsConflictsDylibsError
;
1339 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1342 void Options::addDylibOverride(const char* paths
)
1344 if ( paths
== NULL
)
1345 throw "-dylib_file must followed by two colon separated paths";
1346 const char* colon
= strchr(paths
, ':');
1347 if ( colon
== NULL
)
1348 throw "-dylib_file must followed by two colon separated paths";
1349 int len
= colon
-paths
;
1350 char* target
= new char[len
+2];
1351 strncpy(target
, paths
, len
);
1353 DylibOverride entry
;
1354 entry
.installName
= target
;
1355 entry
.useInstead
= &colon
[1];
1356 fDylibOverrides
.push_back(entry
);
1359 uint64_t Options::parseAddress(const char* addr
)
1362 uint64_t result
= strtoull(addr
, &endptr
, 16);
1366 uint32_t Options::parseProtection(const char* prot
)
1368 uint32_t result
= 0;
1369 for(const char* p
= prot
; *p
!= '\0'; ++p
) {
1370 switch(tolower(*p
)) {
1372 result
|= VM_PROT_READ
;
1375 result
|= VM_PROT_WRITE
;
1378 result
|= VM_PROT_EXECUTE
;
1383 throwf("unknown -segprot lettter in %s", prot
);
1392 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1395 uint32_t Options::parseVersionNumber(const char* versionString
)
1397 unsigned long x
= 0;
1398 unsigned long y
= 0;
1399 unsigned long z
= 0;
1401 x
= strtoul(versionString
, &end
, 10);
1402 if ( *end
== '.' ) {
1403 y
= strtoul(&end
[1], &end
, 10);
1404 if ( *end
== '.' ) {
1405 z
= strtoul(&end
[1], &end
, 10);
1408 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
1409 throwf("malformed version number: %s", versionString
);
1411 return (x
<< 16) | ( y
<< 8 ) | z
;
1414 static const char* cstringSymbolName(const char* orderFileString
)
1417 asprintf(&result
, "cstring=%s", orderFileString
);
1418 // convert escaped characters
1420 for(const char* s
=result
; *s
!= '\0'; ++s
, ++d
) {
1458 // hexadecimal value of char
1462 while ( isxdigit(*s
) ) {
1467 value
+= ((toupper(*s
)-'A') + 10);
1474 if ( isdigit(*s
) ) {
1475 // octal value of char
1477 while ( isdigit(*s
) ) {
1478 value
= (value
<< 3) + (*s
-'0');
1493 void Options::parseOrderFile(const char* path
, bool cstring
)
1495 // order files override auto-ordering
1496 fReaderOptions
.fAutoOrderInitializers
= false;
1498 // read in whole file
1499 int fd
= ::open(path
, O_RDONLY
, 0);
1501 throwf("can't open order file: %s", path
);
1502 struct stat stat_buf
;
1503 ::fstat(fd
, &stat_buf
);
1504 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1506 throwf("can't process order file: %s", path
);
1507 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1508 throwf("can't read order file: %s", path
);
1510 p
[stat_buf
.st_size
] = '\n';
1512 // parse into vector of pairs
1513 char * const end
= &p
[stat_buf
.st_size
+1];
1514 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1515 char* symbolStart
= NULL
;
1516 for (char* s
= p
; s
< end
; ++s
) {
1522 else if ( !isspace(*s
) || cstring
) {
1528 if ( (*s
== '\n') || (!cstring
&& (*s
== '#')) ) {
1529 bool wasComment
= (*s
== '#');
1531 // removing any trailing spaces
1533 while ( isspace(*last
) ) {
1537 if ( strncmp(symbolStart
, "ppc:", 4) == 0 ) {
1538 if ( fArchitecture
== CPU_TYPE_POWERPC
)
1539 symbolStart
= &symbolStart
[4];
1543 // if there is an architecture prefix, only use this symbol it if matches current arch
1544 else if ( strncmp(symbolStart
, "ppc64:", 6) == 0 ) {
1545 if ( fArchitecture
== CPU_TYPE_POWERPC64
)
1546 symbolStart
= &symbolStart
[6];
1550 else if ( strncmp(symbolStart
, "i386:", 5) == 0 ) {
1551 if ( fArchitecture
== CPU_TYPE_I386
)
1552 symbolStart
= &symbolStart
[5];
1556 else if ( strncmp(symbolStart
, "x86_64:", 7) == 0 ) {
1557 if ( fArchitecture
== CPU_TYPE_X86_64
)
1558 symbolStart
= &symbolStart
[7];
1562 else if ( strncmp(symbolStart
, "arm:", 4) == 0 ) {
1563 if ( fArchitecture
== CPU_TYPE_ARM
)
1564 symbolStart
= &symbolStart
[4];
1568 if ( symbolStart
!= NULL
) {
1569 char* objFileName
= NULL
;
1570 char* colon
= strstr(symbolStart
, ".o:");
1571 if ( colon
!= NULL
) {
1573 objFileName
= symbolStart
;
1574 symbolStart
= &colon
[3];
1576 // trim leading spaces
1577 while ( isspace(*symbolStart
) )
1579 Options::OrderedSymbol pair
;
1581 pair
.symbolName
= cstringSymbolName(symbolStart
);
1583 pair
.symbolName
= symbolStart
;
1584 pair
.objectFileName
= objFileName
;
1585 fOrderedSymbols
.push_back(pair
);
1600 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1603 void Options::parseSectionOrderFile(const char* segment
, const char* section
, const char* path
)
1605 if ( (strcmp(section
, "__cstring") == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1606 parseOrderFile(path
, true);
1608 else if ( (strncmp(section
, "__literal",9) == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1609 warning("sorting of __literal[4,8,16] sections not supported");
1612 // ignore section information and append all symbol names to global order file
1613 parseOrderFile(path
, false);
1617 void Options::addSection(const char* segment
, const char* section
, const char* path
)
1619 if ( strlen(segment
) > 16 )
1620 throw "-seccreate segment name max 16 chars";
1621 if ( strlen(section
) > 16 ) {
1622 char* tmp
= strdup(section
);
1624 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section
, tmp
);
1628 // read in whole file
1629 int fd
= ::open(path
, O_RDONLY
, 0);
1631 throwf("can't open -sectcreate file: %s", path
);
1632 struct stat stat_buf
;
1633 ::fstat(fd
, &stat_buf
);
1634 char* p
= (char*)malloc(stat_buf
.st_size
);
1636 throwf("can't process -sectcreate file: %s", path
);
1637 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1638 throwf("can't read -sectcreate file: %s", path
);
1641 // record section to create
1642 ExtraSection info
= { segment
, section
, path
, (uint8_t*)p
, stat_buf
.st_size
};
1643 fExtraSections
.push_back(info
);
1646 void Options::addSectionAlignment(const char* segment
, const char* section
, const char* alignmentStr
)
1648 if ( strlen(segment
) > 16 )
1649 throw "-sectalign segment name max 16 chars";
1650 if ( strlen(section
) > 16 )
1651 throw "-sectalign section name max 16 chars";
1653 // argument to -sectalign is a hexadecimal number
1655 unsigned long value
= strtoul(alignmentStr
, &endptr
, 16);
1656 if ( *endptr
!= '\0')
1657 throw "argument for -sectalign is not a hexadecimal number";
1658 if ( value
> 0x8000 )
1659 throw "argument for -sectalign must be less than or equal to 0x8000";
1661 warning("zero is not a valid -sectalign");
1665 // alignment is power of 2 (e.g. page alignment = 12)
1666 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
1667 if ( (unsigned long)(1 << alignment
) != value
) {
1668 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
1669 segment
, section
, 1 << alignment
);
1672 SectionAlignment info
= { segment
, section
, alignment
};
1673 fSectionAlignments
.push_back(info
);
1676 void Options::addLibrary(const FileInfo
& info
)
1678 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
1679 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
1680 if ( strcmp(info
.path
, fit
->path
) == 0 ) {
1681 // if dylib is specified again but weak, record that it should be weak
1682 if ( info
.options
.fWeakImport
)
1683 fit
->options
.fWeakImport
= true;
1688 fInputFiles
.push_back(info
);
1691 void Options::warnObsolete(const char* arg
)
1693 warning("option %s is obsolete and being ignored", arg
);
1700 // Process all command line arguments.
1702 // The only error checking done here is that each option is valid and if it has arguments
1703 // that they too are valid.
1705 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
1706 // whichever was last on the command line is used.
1708 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
1710 void Options::parse(int argc
, const char* argv
[])
1712 // pass one builds search list from -L and -F options
1713 this->buildSearchPaths(argc
, argv
);
1715 // reduce re-allocations
1716 fInputFiles
.reserve(32);
1718 // pass two parse all other options
1719 for(int i
=1; i
< argc
; ++i
) {
1720 const char* arg
= argv
[i
];
1722 if ( arg
[0] == '-' ) {
1724 // Since we don't care about the files passed, just the option names, we do this here.
1726 fprintf (stderr
, "[Logging ld64 options]\t%s\n", arg
);
1728 if ( (arg
[1] == 'L') || (arg
[1] == 'F') ) {
1729 // previously handled by buildSearchPaths()
1731 // The one gnu style option we have to keep compatibility
1732 // with gcc. Might as well have the single hyphen one as well.
1733 else if ( (strcmp(arg
, "--help") == 0)
1734 || (strcmp(arg
, "-help") == 0)) {
1735 fprintf (stdout
, "ld64: For information on command line options please use 'man ld'.\n");
1738 else if ( strcmp(arg
, "-arch") == 0 ) {
1739 parseArch(argv
[++i
]);
1741 else if ( strcmp(arg
, "-dynamic") == 0 ) {
1744 else if ( strcmp(arg
, "-static") == 0 ) {
1745 fReaderOptions
.fForStatic
= true;
1746 if ( fOutputKind
!= kObjectFile
) {
1747 fOutputKind
= kStaticExecutable
;
1750 else if ( strcmp(arg
, "-dylib") == 0 ) {
1751 fOutputKind
= kDynamicLibrary
;
1753 else if ( strcmp(arg
, "-bundle") == 0 ) {
1754 fOutputKind
= kDynamicBundle
;
1756 else if ( strcmp(arg
, "-dylinker") == 0 ) {
1757 fOutputKind
= kDyld
;
1759 else if ( strcmp(arg
, "-execute") == 0 ) {
1760 if ( fOutputKind
!= kStaticExecutable
)
1761 fOutputKind
= kDynamicExecutable
;
1763 else if ( strcmp(arg
, "-preload") == 0 ) {
1764 fOutputKind
= kPreload
;
1766 else if ( strcmp(arg
, "-r") == 0 ) {
1767 fOutputKind
= kObjectFile
;
1769 else if ( strcmp(arg
, "-kext") == 0 ) {
1770 fOutputKind
= kKextBundle
;
1772 else if ( strcmp(arg
, "-o") == 0 ) {
1773 fOutputFile
= argv
[++i
];
1775 else if ( (arg
[1] == 'l') && (strncmp(arg
,"-lazy_",6) !=0) ) {
1776 addLibrary(findLibrary(&arg
[2]));
1778 // This causes a dylib to be weakly bound at
1779 // link time. This corresponds to weak_import.
1780 else if ( strncmp(arg
, "-weak-l", 7) == 0 ) {
1781 FileInfo info
= findLibrary(&arg
[7]);
1782 info
.options
.fWeakImport
= true;
1785 else if ( strncmp(arg
, "-lazy-l", 7) == 0 ) {
1786 FileInfo info
= findLibrary(&arg
[7], true);
1787 info
.options
.fLazyLoad
= true;
1789 fUsingLazyDylibLinking
= true;
1791 // Avoid lazy binding.
1793 else if ( strcmp(arg
, "-bind_at_load") == 0 ) {
1796 else if ( strcmp(arg
, "-twolevel_namespace") == 0 ) {
1797 fNameSpace
= kTwoLevelNameSpace
;
1799 else if ( strcmp(arg
, "-flat_namespace") == 0 ) {
1800 fNameSpace
= kFlatNameSpace
;
1802 // Also sets a bit to ensure dyld causes everything
1803 // in the namespace to be flat.
1805 else if ( strcmp(arg
, "-force_flat_namespace") == 0 ) {
1806 fNameSpace
= kForceFlatNameSpace
;
1808 // Similar to --whole-archive.
1809 else if ( strcmp(arg
, "-all_load") == 0 ) {
1810 fReaderOptions
.fFullyLoadArchives
= true;
1812 else if ( strcmp(arg
, "-noall_load") == 0) {
1815 // Similar to -all_load
1816 else if ( strcmp(arg
, "-ObjC") == 0 ) {
1817 fReaderOptions
.fLoadAllObjcObjectsFromArchives
= true;
1819 // Similar to -all_load, but for the following archive only.
1820 else if ( strcmp(arg
, "-force_load") == 0 ) {
1821 FileInfo info
= findFile(argv
[++i
]);
1822 info
.options
.fForceLoad
= true;
1825 // Library versioning.
1826 else if ( (strcmp(arg
, "-dylib_compatibility_version") == 0)
1827 || (strcmp(arg
, "-compatibility_version") == 0)) {
1828 const char* vers
= argv
[++i
];
1830 throw "-dylib_compatibility_version missing <version>";
1831 fDylibCompatVersion
= parseVersionNumber(vers
);
1833 else if ( (strcmp(arg
, "-dylib_current_version") == 0)
1834 || (strcmp(arg
, "-current_version") == 0)) {
1835 const char* vers
= argv
[++i
];
1837 throw "-dylib_current_version missing <version>";
1838 fDylibCurrentVersion
= parseVersionNumber(vers
);
1840 else if ( strcmp(arg
, "-sectorder") == 0 ) {
1841 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
1842 throw "-sectorder missing <segment> <section> <file-path>";
1843 parseSectionOrderFile(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1846 else if ( strcmp(arg
, "-order_file") == 0 ) {
1847 parseOrderFile(argv
[++i
], false);
1849 else if ( strcmp(arg
, "-order_file_statistics") == 0 ) {
1850 fPrintOrderFileStatistics
= true;
1852 // ??? Deprecate segcreate.
1853 // -sectcreate puts whole files into a section in the output.
1854 else if ( (strcmp(arg
, "-sectcreate") == 0) || (strcmp(arg
, "-segcreate") == 0) ) {
1855 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
1856 throw "-sectcreate missing <segment> <section> <file-path>";
1857 addSection(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1860 // Since we have a full path in binary/library names we need to be able to override it.
1861 else if ( (strcmp(arg
, "-dylib_install_name") == 0)
1862 || (strcmp(arg
, "-dylinker_install_name") == 0)
1863 || (strcmp(arg
, "-install_name") == 0)) {
1864 fDylibInstallName
= argv
[++i
];
1865 if ( fDylibInstallName
== NULL
)
1866 throw "-install_name missing <path>";
1868 // Sets the base address of the output.
1869 else if ( (strcmp(arg
, "-seg1addr") == 0) || (strcmp(arg
, "-image_base") == 0) ) {
1870 const char* address
= argv
[++i
];
1871 if ( address
== NULL
)
1872 throwf("%s missing <address>", arg
);
1873 fBaseAddress
= parseAddress(address
);
1874 uint64_t temp
= ((fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
1875 if ( fBaseAddress
!= temp
) {
1876 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment
);
1877 fBaseAddress
= temp
;
1880 else if ( strcmp(arg
, "-e") == 0 ) {
1881 fEntryName
= argv
[++i
];
1883 // Same as -@ from the FSF linker.
1884 else if ( strcmp(arg
, "-filelist") == 0 ) {
1885 const char* path
= argv
[++i
];
1886 if ( (path
== NULL
) || (path
[0] == '-') )
1887 throw "-filelist missing <path>";
1890 else if ( strcmp(arg
, "-keep_private_externs") == 0 ) {
1891 fKeepPrivateExterns
= true;
1893 else if ( strcmp(arg
, "-final_output") == 0 ) {
1894 fFinalName
= argv
[++i
];
1896 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
1897 // just ensures that this happens for cross object file boundaries.
1898 else if ( (strcmp(arg
, "-interposable") == 0) || (strcmp(arg
, "-multi_module") == 0)) {
1899 switch ( fInterposeMode
) {
1900 case kInterposeNone
:
1901 case kInterposeAllExternal
:
1902 fInterposeMode
= kInterposeAllExternal
;
1904 case kInterposeSome
:
1905 // do nothing, -interposable_list overrides -interposable"
1909 else if ( strcmp(arg
, "-interposable_list") == 0 ) {
1910 fInterposeMode
= kInterposeSome
;
1911 loadExportFile(argv
[++i
], "-interposable_list", fInterposeList
);
1913 // Default for -interposable/-multi_module/-single_module.
1914 else if ( strcmp(arg
, "-single_module") == 0 ) {
1915 fInterposeMode
= kInterposeNone
;
1917 else if ( strcmp(arg
, "-exported_symbols_list") == 0 ) {
1918 if ( fExportMode
== kDontExportSome
)
1919 throw "can't use -exported_symbols_list and -unexported_symbols_list";
1920 fExportMode
= kExportSome
;
1921 loadExportFile(argv
[++i
], "-exported_symbols_list", fExportSymbols
);
1923 else if ( strcmp(arg
, "-unexported_symbols_list") == 0 ) {
1924 if ( fExportMode
== kExportSome
)
1925 throw "can't use -unexported_symbols_list and -exported_symbols_list";
1926 fExportMode
= kDontExportSome
;
1927 loadExportFile(argv
[++i
], "-unexported_symbols_list", fDontExportSymbols
);
1929 else if ( strcmp(arg
, "-exported_symbol") == 0 ) {
1930 if ( fExportMode
== kDontExportSome
)
1931 throw "can't use -exported_symbol and -unexported_symbols";
1932 fExportMode
= kExportSome
;
1933 fExportSymbols
.insert(argv
[++i
]);
1935 else if ( strcmp(arg
, "-unexported_symbol") == 0 ) {
1936 if ( fExportMode
== kExportSome
)
1937 throw "can't use -unexported_symbol and -exported_symbol";
1938 fExportMode
= kDontExportSome
;
1939 fDontExportSymbols
.insert(argv
[++i
]);
1941 else if ( strcmp(arg
, "-non_global_symbols_no_strip_list") == 0 ) {
1942 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveExclude
)
1943 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
1944 fLocalSymbolHandling
= kLocalSymbolsSelectiveInclude
;
1945 loadExportFile(argv
[++i
], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded
);
1947 else if ( strcmp(arg
, "-non_global_symbols_strip_list") == 0 ) {
1948 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveInclude
)
1949 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
1950 fLocalSymbolHandling
= kLocalSymbolsSelectiveExclude
;
1951 loadExportFile(argv
[++i
], "-non_global_symbols_strip_list", fLocalSymbolsExcluded
);
1954 else if ( strcmp(arg
, "-no_arch_warnings") == 0 ) {
1955 fIgnoreOtherArchFiles
= true;
1957 else if ( strcmp(arg
, "-force_cpusubtype_ALL") == 0 ) {
1958 fForceSubtypeAll
= true;
1960 // Similar to -weak-l but uses the absolute path name to the library.
1961 else if ( strcmp(arg
, "-weak_library") == 0 ) {
1962 FileInfo info
= findFile(argv
[++i
]);
1963 info
.options
.fWeakImport
= true;
1966 else if ( strcmp(arg
, "-lazy_library") == 0 ) {
1967 FileInfo info
= findFile(argv
[++i
]);
1968 info
.options
.fLazyLoad
= true;
1970 fUsingLazyDylibLinking
= true;
1972 else if ( strcmp(arg
, "-framework") == 0 ) {
1973 addLibrary(findFramework(argv
[++i
]));
1975 else if ( strcmp(arg
, "-weak_framework") == 0 ) {
1976 FileInfo info
= findFramework(argv
[++i
]);
1977 info
.options
.fWeakImport
= true;
1980 else if ( strcmp(arg
, "-lazy_framework") == 0 ) {
1981 FileInfo info
= findFramework(argv
[++i
]);
1982 info
.options
.fLazyLoad
= true;
1984 fUsingLazyDylibLinking
= true;
1986 else if ( strcmp(arg
, "-search_paths_first") == 0 ) {
1987 // previously handled by buildSearchPaths()
1989 else if ( strcmp(arg
, "-undefined") == 0 ) {
1990 setUndefinedTreatment(argv
[++i
]);
1992 // Debugging output flag.
1993 else if ( strcmp(arg
, "-arch_multiple") == 0 ) {
1994 fMessagesPrefixedWithArchitecture
= true;
1996 // Specify what to do with relocations in read only
1997 // sections like .text. Could be errors, warnings,
1998 // or suppressed. Currently we do nothing with the
2000 else if ( strcmp(arg
, "-read_only_relocs") == 0 ) {
2001 switch ( parseTreatment(argv
[++i
]) ) {
2004 throw "-read_only_relocs missing [ warning | error | suppress ]";
2006 fWarnTextRelocs
= true;
2007 fAllowTextRelocs
= true;
2010 fWarnTextRelocs
= false;
2011 fAllowTextRelocs
= true;
2014 fWarnTextRelocs
= false;
2015 fAllowTextRelocs
= false;
2019 else if ( strcmp(arg
, "-sect_diff_relocs") == 0 ) {
2023 // Warn, error or make strong a mismatch between weak
2024 // and non-weak references.
2025 else if ( strcmp(arg
, "-weak_reference_mismatches") == 0 ) {
2026 setWeakReferenceMismatchTreatment(argv
[++i
]);
2028 // For a deployment target of 10.3 and earlier ld64 will
2029 // prebind an executable with 0s in all addresses that
2030 // are prebound. This can then be fixed up by update_prebinding
2031 // later. Prebinding is less useful on 10.4 and greater.
2032 else if ( strcmp(arg
, "-prebind") == 0 ) {
2035 else if ( strcmp(arg
, "-noprebind") == 0 ) {
2039 else if ( strcmp(arg
, "-prebind_allow_overlap") == 0 ) {
2042 else if ( strcmp(arg
, "-prebind_all_twolevel_modules") == 0 ) {
2045 else if ( strcmp(arg
, "-noprebind_all_twolevel_modules") == 0 ) {
2048 else if ( strcmp(arg
, "-nofixprebinding") == 0 ) {
2051 // This should probably be deprecated when we respect -L and -F
2052 // when searching for libraries.
2053 else if ( strcmp(arg
, "-dylib_file") == 0 ) {
2054 addDylibOverride(argv
[++i
]);
2056 // What to expand @executable_path to if found in dependent dylibs
2057 else if ( strcmp(arg
, "-executable_path") == 0 ) {
2058 fExecutablePath
= argv
[++i
];
2059 if ( (fExecutablePath
== NULL
) || (fExecutablePath
[0] == '-') )
2060 throw "-executable_path missing <path>";
2061 // if a directory was passed, add / to end
2062 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2063 struct stat statBuffer
;
2064 if ( stat(fExecutablePath
, &statBuffer
) == 0 ) {
2065 if ( (statBuffer
.st_mode
& S_IFMT
) == S_IFDIR
) {
2066 char* pathWithSlash
= new char[strlen(fExecutablePath
)+2];
2067 strcpy(pathWithSlash
, fExecutablePath
);
2068 strcat(pathWithSlash
, "/");
2069 fExecutablePath
= pathWithSlash
;
2073 // Aligns all segments to the power of 2 boundary specified.
2074 else if ( strcmp(arg
, "-segalign") == 0 ) {
2075 const char* size
= argv
[++i
];
2077 throw "-segalign missing <size>";
2078 fSegmentAlignment
= parseAddress(size
);
2079 uint8_t alignment
= (uint8_t)__builtin_ctz(fSegmentAlignment
);
2080 uint32_t p2aligned
= (1 << alignment
);
2081 if ( p2aligned
!= fSegmentAlignment
) {
2082 warning("alignment for -segalign %s is not a power of two, using 0x%X", size
, p2aligned
);
2083 fSegmentAlignment
= p2aligned
;
2086 // Puts a specified segment at a particular address that must
2087 // be a multiple of the segment alignment.
2088 else if ( strcmp(arg
, "-segaddr") == 0 ) {
2090 seg
.name
= argv
[++i
];
2091 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2092 throw "-segaddr missing segName Adddress";
2093 seg
.address
= parseAddress(argv
[++i
]);
2094 uint64_t temp
= seg
.address
& (-4096); // page align
2095 if ( (seg
.address
!= temp
) )
2096 warning("-segaddr %s not page aligned, rounding down", seg
.name
);
2097 fCustomSegmentAddresses
.push_back(seg
);
2099 // ??? Deprecate when we deprecate split-seg.
2100 else if ( strcmp(arg
, "-segs_read_only_addr") == 0 ) {
2101 fBaseAddress
= parseAddress(argv
[++i
]);
2103 // ??? Deprecate when we deprecate split-seg.
2104 else if ( strcmp(arg
, "-segs_read_write_addr") == 0 ) {
2105 fBaseWritableAddress
= parseAddress(argv
[++i
]);
2108 // ??? Deprecate when we get rid of basing at build time.
2109 else if ( strcmp(arg
, "-seg_addr_table") == 0 ) {
2110 const char* name
= argv
[++i
];
2112 throw "-seg_addr_table missing argument";
2113 fSegAddrTablePath
= name
;
2115 else if ( strcmp(arg
, "-seg_addr_table_filename") == 0 ) {
2119 else if ( strcmp(arg
, "-segprot") == 0 ) {
2121 seg
.name
= argv
[++i
];
2122 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) || (argv
[i
+2] == NULL
) )
2123 throw "-segprot missing segName max-prot init-prot";
2124 seg
.max
= parseProtection(argv
[++i
]);
2125 seg
.init
= parseProtection(argv
[++i
]);
2126 fCustomSegmentProtections
.push_back(seg
);
2128 else if ( strcmp(arg
, "-pagezero_size") == 0 ) {
2129 const char* size
= argv
[++i
];
2131 throw "-pagezero_size missing <size>";
2132 fZeroPageSize
= parseAddress(size
);
2133 uint64_t temp
= fZeroPageSize
& (-4096); // page align
2134 if ( (fZeroPageSize
!= temp
) )
2135 warning("-pagezero_size not page aligned, rounding down");
2136 fZeroPageSize
= temp
;
2138 else if ( strcmp(arg
, "-stack_addr") == 0 ) {
2139 const char* address
= argv
[++i
];
2140 if ( address
== NULL
)
2141 throw "-stack_addr missing <address>";
2142 fStackAddr
= parseAddress(address
);
2144 else if ( strcmp(arg
, "-stack_size") == 0 ) {
2145 const char* size
= argv
[++i
];
2147 throw "-stack_size missing <address>";
2148 fStackSize
= parseAddress(size
);
2149 uint64_t temp
= fStackSize
& (-4096); // page align
2150 if ( (fStackSize
!= temp
) )
2151 warning("-stack_size not page aligned, rounding down");
2153 else if ( strcmp(arg
, "-allow_stack_execute") == 0 ) {
2154 fExecutableStack
= true;
2156 else if ( strcmp(arg
, "-sectalign") == 0 ) {
2157 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2158 throw "-sectalign missing <segment> <section> <file-path>";
2159 addSectionAlignment(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2162 else if ( strcmp(arg
, "-sectorder_detail") == 0 ) {
2165 else if ( strcmp(arg
, "-sectobjectsymbols") == 0 ) {
2169 else if ( strcmp(arg
, "-bundle_loader") == 0 ) {
2170 fBundleLoader
= argv
[++i
];
2171 if ( (fBundleLoader
== NULL
) || (fBundleLoader
[0] == '-') )
2172 throw "-bundle_loader missing <path>";
2173 FileInfo info
= findFile(fBundleLoader
);
2174 info
.options
.fBundleLoader
= true;
2175 fInputFiles
.push_back(info
);
2177 else if ( strcmp(arg
, "-private_bundle") == 0 ) {
2180 else if ( strcmp(arg
, "-twolevel_namespace_hints") == 0 ) {
2183 // Use this flag to set default behavior for deployement targets.
2184 else if ( strcmp(arg
, "-macosx_version_min") == 0 ) {
2185 setMacOSXVersionMin(argv
[++i
]);
2187 else if ( strcmp(arg
, "-iphoneos_version_min") == 0 ) {
2188 setIPhoneVersionMin(argv
[++i
]);
2190 else if ( strcmp(arg
, "-multiply_defined") == 0 ) {
2191 //warnObsolete(arg);
2194 else if ( strcmp(arg
, "-multiply_defined_unused") == 0 ) {
2198 else if ( strcmp(arg
, "-nomultidefs") == 0 ) {
2201 // Display each file in which the argument symbol appears and whether
2202 // the file defines or references it. This option takes an argument
2203 // as -y<symbol> note that there is no space.
2204 else if ( strncmp(arg
, "-y", 2) == 0 ) {
2207 // Same output as -y, but output <arg> number of undefined symbols only.
2208 else if ( strcmp(arg
, "-Y") == 0 ) {
2209 //warnObsolete(arg);
2212 // This option affects all objects linked into the final result.
2213 else if ( strcmp(arg
, "-m") == 0 ) {
2216 else if ( (strcmp(arg
, "-why_load") == 0) || (strcmp(arg
, "-whyload") == 0) ) {
2217 fReaderOptions
.fWhyLoad
= true;
2219 else if ( strcmp(arg
, "-why_live") == 0 ) {
2220 const char* name
= argv
[++i
];
2222 throw "-why_live missing symbol name argument";
2223 fWhyLive
.insert(name
);
2225 else if ( strcmp(arg
, "-u") == 0 ) {
2226 const char* name
= argv
[++i
];
2228 throw "-u missing argument";
2229 fInitialUndefines
.push_back(name
);
2231 else if ( strcmp(arg
, "-U") == 0 ) {
2232 const char* name
= argv
[++i
];
2234 throw "-U missing argument";
2235 fAllowedUndefined
.insert(name
);
2237 else if ( strcmp(arg
, "-s") == 0 ) {
2239 fLocalSymbolHandling
= kLocalSymbolsNone
;
2240 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
2242 else if ( strcmp(arg
, "-x") == 0 ) {
2243 fLocalSymbolHandling
= kLocalSymbolsNone
;
2245 else if ( strcmp(arg
, "-S") == 0 ) {
2246 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
2248 else if ( strcmp(arg
, "-X") == 0 ) {
2251 else if ( strcmp(arg
, "-Si") == 0 ) {
2253 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoFull
;
2255 else if ( strcmp(arg
, "-b") == 0 ) {
2258 else if ( strcmp(arg
, "-Sn") == 0 ) {
2260 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoFull
;
2262 else if ( strcmp(arg
, "-Sp") == 0 ) {
2265 else if ( strcmp(arg
, "-dead_strip") == 0 ) {
2266 fDeadStrip
= kDeadStripOnPlusUnusedInits
;
2268 else if ( strcmp(arg
, "-no_dead_strip_inits_and_terms") == 0 ) {
2269 fDeadStrip
= kDeadStripOn
;
2271 else if ( strcmp(arg
, "-w") == 0 ) {
2272 // previously handled by buildSearchPaths()
2274 else if ( strcmp(arg
, "-arch_errors_fatal") == 0 ) {
2275 fErrorOnOtherArchFiles
= true;
2277 else if ( strcmp(arg
, "-M") == 0 ) {
2280 else if ( strcmp(arg
, "-headerpad") == 0 ) {
2281 const char* size
= argv
[++i
];
2283 throw "-headerpad missing argument";
2284 fMinimumHeaderPad
= parseAddress(size
);
2286 else if ( strcmp(arg
, "-headerpad_max_install_names") == 0 ) {
2287 fMaxMinimumHeaderPad
= true;
2289 else if ( strcmp(arg
, "-t") == 0 ) {
2290 fReaderOptions
.fLogAllFiles
= true;
2292 else if ( strcmp(arg
, "-whatsloaded") == 0 ) {
2293 fReaderOptions
.fLogObjectFiles
= true;
2295 else if ( strcmp(arg
, "-A") == 0 ) {
2299 else if ( strcmp(arg
, "-umbrella") == 0 ) {
2300 const char* name
= argv
[++i
];
2302 throw "-umbrella missing argument";
2303 fUmbrellaName
= name
;
2305 else if ( strcmp(arg
, "-allowable_client") == 0 ) {
2306 const char* name
= argv
[++i
];
2309 throw "-allowable_client missing argument";
2311 fAllowableClients
.push_back(name
);
2313 else if ( strcmp(arg
, "-client_name") == 0 ) {
2314 const char* name
= argv
[++i
];
2317 throw "-client_name missing argument";
2321 else if ( strcmp(arg
, "-sub_umbrella") == 0 ) {
2322 const char* name
= argv
[++i
];
2324 throw "-sub_umbrella missing argument";
2325 fSubUmbellas
.push_back(name
);
2327 else if ( strcmp(arg
, "-sub_library") == 0 ) {
2328 const char* name
= argv
[++i
];
2330 throw "-sub_library missing argument";
2331 fSubLibraries
.push_back(name
);
2333 else if ( strcmp(arg
, "-init") == 0 ) {
2334 const char* name
= argv
[++i
];
2336 throw "-init missing argument";
2337 fInitFunctionName
= name
;
2339 else if ( strcmp(arg
, "-dot") == 0 ) {
2340 const char* name
= argv
[++i
];
2342 throw "-dot missing argument";
2343 fDotOutputFile
= name
;
2345 else if ( strcmp(arg
, "-warn_commons") == 0 ) {
2346 fWarnCommons
= true;
2348 else if ( strcmp(arg
, "-commons") == 0 ) {
2349 fCommonsMode
= parseCommonsTreatment(argv
[++i
]);
2351 else if ( strcmp(arg
, "-keep_relocs") == 0 ) {
2352 fKeepRelocations
= true;
2354 else if ( strcmp(arg
, "-warn_stabs") == 0 ) {
2357 else if ( strcmp(arg
, "-pause") == 0 ) {
2360 else if ( strcmp(arg
, "-print_statistics") == 0 ) {
2363 else if ( strcmp(arg
, "-d") == 0 ) {
2364 fReaderOptions
.fMakeTentativeDefinitionsReal
= true;
2366 else if ( strcmp(arg
, "-v") == 0 ) {
2367 // previously handled by buildSearchPaths()
2369 else if ( strcmp(arg
, "-Z") == 0 ) {
2370 // previously handled by buildSearchPaths()
2372 else if ( strcmp(arg
, "-syslibroot") == 0 ) {
2374 // previously handled by buildSearchPaths()
2376 else if ( strcmp(arg
, "-no_uuid") == 0 ) {
2377 fUUIDMode
= kUUIDNone
;
2379 else if ( strcmp(arg
, "-random_uuid") == 0 ) {
2380 fUUIDMode
= kUUIDRandom
;
2382 else if ( strcmp(arg
, "-dtrace") == 0 ) {
2383 const char* name
= argv
[++i
];
2385 throw "-dtrace missing argument";
2386 fDtraceScriptName
= name
;
2388 else if ( strcmp(arg
, "-root_safe") == 0 ) {
2389 fReaderOptions
.fRootSafe
= true;
2391 else if ( strcmp(arg
, "-setuid_safe") == 0 ) {
2392 fReaderOptions
.fSetuidSafe
= true;
2394 else if ( strcmp(arg
, "-alias") == 0 ) {
2395 ObjectFile::ReaderOptions::AliasPair pair
;
2396 pair
.realName
= argv
[++i
];
2397 if ( pair
.realName
== NULL
)
2398 throw "missing argument to -alias";
2399 pair
.alias
= argv
[++i
];
2400 if ( pair
.alias
== NULL
)
2401 throw "missing argument to -alias";
2402 fReaderOptions
.fAliases
.push_back(pair
);
2404 else if ( strcmp(arg
, "-alias_list") == 0 ) {
2405 parseAliasFile(argv
[++i
]);
2407 // put this last so that it does not interfer with other options starting with 'i'
2408 else if ( strncmp(arg
, "-i", 2) == 0 ) {
2409 const char* colon
= strchr(arg
, ':');
2410 if ( colon
== NULL
)
2411 throwf("unknown option: %s", arg
);
2412 ObjectFile::ReaderOptions::AliasPair pair
;
2413 char* temp
= new char[colon
-arg
];
2414 strlcpy(temp
, &arg
[2], colon
-arg
-1);
2415 pair
.realName
= &colon
[1];
2417 fReaderOptions
.fAliases
.push_back(pair
);
2419 else if ( strcmp(arg
, "-save-temps") == 0 ) {
2420 fSaveTempFiles
= true;
2422 else if ( strcmp(arg
, "-rpath") == 0 ) {
2423 const char* path
= argv
[++i
];
2425 throw "missing argument to -rpath";
2426 fRPaths
.push_back(path
);
2428 else if ( strcmp(arg
, "-read_only_stubs") == 0 ) {
2429 fReadOnlyx86Stubs
= true;
2431 else if ( strcmp(arg
, "-slow_stubs") == 0 ) {
2434 else if ( strcmp(arg
, "-map") == 0 ) {
2435 fMapPath
= argv
[++i
];
2436 if ( fMapPath
== NULL
)
2437 throw "missing argument to -map";
2439 else if ( strcmp(arg
, "-pie") == 0 ) {
2440 fPositionIndependentExecutable
= true;
2442 else if ( strncmp(arg
, "-reexport-l", 11) == 0 ) {
2443 FileInfo info
= findLibrary(&arg
[11], true);
2444 info
.options
.fReExport
= true;
2447 else if ( strcmp(arg
, "-reexport_library") == 0 ) {
2448 FileInfo info
= findFile(argv
[++i
]);
2449 info
.options
.fReExport
= true;
2452 else if ( strcmp(arg
, "-reexport_framework") == 0 ) {
2453 FileInfo info
= findFramework(argv
[++i
]);
2454 info
.options
.fReExport
= true;
2457 else if ( strcmp(arg
, "-dead_strip_dylibs") == 0 ) {
2458 fDeadStripDylibs
= true;
2460 else if ( strcmp(arg
, "-no_implicit_dylibs") == 0 ) {
2461 fReaderOptions
.fImplicitlyLinkPublicDylibs
= false;
2463 else if ( strcmp(arg
, "-new_linker") == 0 ) {
2466 else if ( strcmp(arg
, "-no_encryption") == 0 ) {
2467 fEncryptable
= false;
2469 else if ( strcmp(arg
, "-no_compact_unwind") == 0 ) {
2470 fReaderOptions
.fAddCompactUnwindEncoding
= false;
2472 else if ( strcmp(arg
, "-mllvm") == 0 ) {
2473 const char* opts
= argv
[++i
];
2475 throw "missing argument to -mllvm";
2476 fLLVMOptions
.push_back(opts
);
2478 else if ( strcmp(arg
, "-no_order_inits") == 0 ) {
2479 fReaderOptions
.fAutoOrderInitializers
= false;
2481 else if ( strcmp(arg
, "-no_order_data") == 0 ) {
2484 else if ( strcmp(arg
, "-seg_page_size") == 0 ) {
2486 seg
.name
= argv
[++i
];
2487 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2488 throw "-seg_page_size missing segName Adddress";
2489 seg
.size
= parseAddress(argv
[++i
]);
2490 uint64_t temp
= seg
.size
& (-4096); // page align
2491 if ( (seg
.size
!= temp
) )
2492 warning("-seg_page_size %s not 4K aligned, rounding down", seg
.name
);
2493 fCustomSegmentSizes
.push_back(seg
);
2495 else if ( strcmp(arg
, "-mark_dead_strippable_dylib") == 0 ) {
2496 fMarkDeadStrippableDylib
= true;
2498 else if ( strcmp(arg
, "-exported_symbols_order") == 0 ) {
2499 loadSymbolOrderFile(argv
[++i
], fExportSymbolsOrder
);
2501 else if ( strcmp(arg
, "-no_compact_linkedit") == 0 ) {
2502 fMakeCompressedDyldInfo
= false;
2504 else if ( strcmp(arg
, "-no_eh_labels") == 0 ) {
2505 fReaderOptions
.fNoEHLabels
= true;
2507 else if ( strcmp(arg
, "-warn_compact_unwind") == 0 ) {
2508 fReaderOptions
.fWarnCompactUnwind
= true;
2510 else if ( strcmp(arg
, "-allow_sub_type_mismatches") == 0 ) {
2511 fAllowCpuSubtypeMismatches
= true;
2514 throwf("unknown option: %s", arg
);
2518 FileInfo info
= findFile(arg
);
2519 if ( strcmp(&info
.path
[strlen(info
.path
)-2], ".a") == 0 )
2522 fInputFiles
.push_back(info
);
2526 // if a -lazy option was used, implicitly link in lazydylib1.o
2527 if ( fUsingLazyDylibLinking
) {
2528 addLibrary(findLibrary("lazydylib1.o"));
2535 // -syslibroot <path> is used for SDK support.
2536 // The rule is that all search paths (both explicit and default) are
2537 // checked to see if they exist in the SDK. If so, that path is
2538 // replaced with the sdk prefixed path. If not, that search path
2539 // is used as is. If multiple -syslibroot options are specified
2540 // their directory structures are logically overlayed and files
2541 // from sdks specified earlier on the command line used before later ones.
2543 void Options::buildSearchPaths(int argc
, const char* argv
[])
2545 bool addStandardLibraryDirectories
= true;
2546 std::vector
<const char*> libraryPaths
;
2547 std::vector
<const char*> frameworkPaths
;
2548 libraryPaths
.reserve(10);
2549 frameworkPaths
.reserve(10);
2550 // scan through argv looking for -L, -F, -Z, and -syslibroot options
2551 for(int i
=0; i
< argc
; ++i
) {
2552 if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'L') )
2553 libraryPaths
.push_back(&argv
[i
][2]);
2554 else if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'F') )
2555 frameworkPaths
.push_back(&argv
[i
][2]);
2556 else if ( strcmp(argv
[i
], "-Z") == 0 )
2557 addStandardLibraryDirectories
= false;
2558 else if ( strcmp(argv
[i
], "-v") == 0 ) {
2560 extern const char ldVersionString
[];
2561 fprintf(stderr
, "%s", ldVersionString
);
2562 // if only -v specified, exit cleanly
2565 printLTOVersion(*this);
2570 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
2571 const char* path
= argv
[++i
];
2573 throw "-syslibroot missing argument";
2574 fSDKPaths
.push_back(path
);
2576 else if ( strcmp(argv
[i
], "-search_paths_first") == 0 ) {
2577 // ??? Deprecate when we get -Bstatic/-Bdynamic.
2578 fLibrarySearchMode
= kSearchDylibAndArchiveInEachDir
;
2580 else if ( strcmp(argv
[i
], "-w") == 0 ) {
2581 sEmitWarnings
= false;
2584 int standardLibraryPathsStartIndex
= libraryPaths
.size();
2585 int standardFrameworkPathsStartIndex
= frameworkPaths
.size();
2586 if ( addStandardLibraryDirectories
) {
2587 libraryPaths
.push_back("/usr/lib");
2588 libraryPaths
.push_back("/usr/local/lib");
2590 frameworkPaths
.push_back("/Library/Frameworks/");
2591 frameworkPaths
.push_back("/System/Library/Frameworks/");
2592 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
2595 // <rdar://problem/5829579> Support for configure based hacks
2596 // if last -syslibroot is /, then ignore all syslibroots
2597 if ( fSDKPaths
.size() > 0 ) {
2598 if ( strcmp(fSDKPaths
.back(), "/") == 0 ) {
2603 // now merge sdk and library paths to make real search paths
2604 fLibrarySearchPaths
.reserve(libraryPaths
.size()*(fSDKPaths
.size()+1));
2606 for (std::vector
<const char*>::iterator it
= libraryPaths
.begin(); it
!= libraryPaths
.end(); ++it
, ++libIndex
) {
2607 const char* libDir
= *it
;
2608 bool sdkOverride
= false;
2609 if ( libDir
[0] == '/' ) {
2610 char betterLibDir
[PATH_MAX
];
2611 if ( strstr(libDir
, "/..") != NULL
) {
2612 if ( realpath(libDir
, betterLibDir
) != NULL
)
2613 libDir
= strdup(betterLibDir
);
2615 const int libDirLen
= strlen(libDir
);
2616 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
2617 const char* sdkDir
= *sdkit
;
2618 const int sdkDirLen
= strlen(sdkDir
);
2619 char newPath
[libDirLen
+ sdkDirLen
+4];
2620 strcpy(newPath
, sdkDir
);
2621 if ( newPath
[sdkDirLen
-1] == '/' )
2622 newPath
[sdkDirLen
-1] = '\0';
2623 strcat(newPath
, libDir
);
2624 struct stat statBuffer
;
2625 if ( stat(newPath
, &statBuffer
) == 0 ) {
2626 fLibrarySearchPaths
.push_back(strdup(newPath
));
2631 if ( !sdkOverride
) {
2632 if ( (libIndex
>= standardLibraryPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
2633 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2634 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2637 fLibrarySearchPaths
.push_back(libDir
);
2642 // now merge sdk and framework paths to make real search paths
2643 fFrameworkSearchPaths
.reserve(frameworkPaths
.size()*(fSDKPaths
.size()+1));
2645 for (std::vector
<const char*>::iterator it
= frameworkPaths
.begin(); it
!= frameworkPaths
.end(); ++it
, ++frameIndex
) {
2646 const char* frameworkDir
= *it
;
2647 bool sdkOverride
= false;
2648 if ( frameworkDir
[0] == '/' ) {
2649 char betterFrameworkDir
[PATH_MAX
];
2650 if ( strstr(frameworkDir
, "/..") != NULL
) {
2651 if ( realpath(frameworkDir
, betterFrameworkDir
) != NULL
)
2652 frameworkDir
= strdup(betterFrameworkDir
);
2654 const int frameworkDirLen
= strlen(frameworkDir
);
2655 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
2656 const char* sdkDir
= *sdkit
;
2657 const int sdkDirLen
= strlen(sdkDir
);
2658 char newPath
[frameworkDirLen
+ sdkDirLen
+4];
2659 strcpy(newPath
, sdkDir
);
2660 if ( newPath
[sdkDirLen
-1] == '/' )
2661 newPath
[sdkDirLen
-1] = '\0';
2662 strcat(newPath
, frameworkDir
);
2663 struct stat statBuffer
;
2664 if ( stat(newPath
, &statBuffer
) == 0 ) {
2665 fFrameworkSearchPaths
.push_back(strdup(newPath
));
2670 if ( !sdkOverride
) {
2671 if ( (frameIndex
>= standardFrameworkPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
2672 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2673 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2676 fFrameworkSearchPaths
.push_back(frameworkDir
);
2682 fprintf(stderr
,"Library search paths:\n");
2683 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
2684 it
!= fLibrarySearchPaths
.end();
2686 fprintf(stderr
,"\t%s\n", *it
);
2687 fprintf(stderr
,"Framework search paths:\n");
2688 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
2689 it
!= fFrameworkSearchPaths
.end();
2691 fprintf(stderr
,"\t%s\n", *it
);
2695 // this is run before the command line is parsed
2696 void Options::parsePreCommandLineEnvironmentSettings()
2698 if ((getenv("LD_TRACE_ARCHIVES") != NULL
)
2699 || (getenv("RC_TRACE_ARCHIVES") != NULL
))
2700 fReaderOptions
.fTraceArchives
= true;
2702 if ((getenv("LD_TRACE_DYLIBS") != NULL
)
2703 || (getenv("RC_TRACE_DYLIBS") != NULL
)) {
2704 fReaderOptions
.fTraceDylibs
= true;
2705 fReaderOptions
.fTraceIndirectDylibs
= true;
2708 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL
) {
2709 fTraceDylibSearching
= true;
2712 if (getenv("LD_PRINT_OPTIONS") != NULL
)
2713 fPrintOptions
= true;
2715 if (fReaderOptions
.fTraceDylibs
|| fReaderOptions
.fTraceArchives
)
2716 fReaderOptions
.fTraceOutputFile
= getenv("LD_TRACE_FILE");
2718 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL
)
2719 fPrintOrderFileStatistics
= true;
2721 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL
)
2724 if (getenv("LD_NO_ENCRYPT") != NULL
)
2725 fEncryptable
= false;
2727 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL
)
2728 fAllowCpuSubtypeMismatches
= true;
2730 // for now disable compressed linkedit functionality
2731 if ( getenv("LD_NO_COMPACT_LINKEDIT") != NULL
) {
2732 fMakeCompressedDyldInfo
= false;
2733 fMakeClassicDyldInfo
= true;
2736 sWarningsSideFilePath
= getenv("LD_WARN_FILE");
2740 // this is run after the command line is parsed
2741 void Options::parsePostCommandLineEnvironmentSettings()
2743 // when building a dynamic main executable, default any use of @executable_path to output path
2744 if ( fExecutablePath
== NULL
&& (fOutputKind
== kDynamicExecutable
) ) {
2745 fExecutablePath
= fOutputFile
;
2748 // allow build system to set default seg_addr_table
2749 if ( fSegAddrTablePath
== NULL
)
2750 fSegAddrTablePath
= getenv("LD_SEG_ADDR_TABLE");
2752 // allow build system to turn on prebinding
2754 fPrebind
= ( getenv("LD_PREBIND") != NULL
);
2757 // allow build system to force on dead-code-stripping
2758 if ( fDeadStrip
== kDeadStripOff
) {
2759 if ( getenv("LD_DEAD_STRIP") != NULL
) {
2760 switch (fOutputKind
) {
2761 case Options::kDynamicLibrary
:
2762 case Options::kDynamicExecutable
:
2763 case Options::kDynamicBundle
:
2764 fDeadStrip
= kDeadStripOn
;
2766 case Options::kPreload
:
2767 case Options::kObjectFile
:
2768 case Options::kDyld
:
2769 case Options::kStaticExecutable
:
2770 case Options::kKextBundle
:
2776 // allow build system to force on -warn_commons
2777 if ( getenv("LD_WARN_COMMONS") != NULL
)
2778 fWarnCommons
= true;
2781 void Options::reconfigureDefaults()
2783 // sync reader options
2784 switch ( fOutputKind
) {
2785 case Options::kObjectFile
:
2786 fReaderOptions
.fForFinalLinkedImage
= false;
2788 case Options::kDyld
:
2789 fReaderOptions
.fForDyld
= true;
2790 fReaderOptions
.fForFinalLinkedImage
= true;
2791 fReaderOptions
.fNoEHLabels
= true;
2793 case Options::kDynamicLibrary
:
2794 case Options::kDynamicBundle
:
2795 case Options::kKextBundle
:
2796 fReaderOptions
.fForFinalLinkedImage
= true;
2797 fReaderOptions
.fNoEHLabels
= true;
2799 case Options::kDynamicExecutable
:
2800 case Options::kStaticExecutable
:
2801 case Options::kPreload
:
2802 fReaderOptions
.fLinkingMainExecutable
= true;
2803 fReaderOptions
.fForFinalLinkedImage
= true;
2804 fReaderOptions
.fNoEHLabels
= true;
2808 // set default min OS version
2809 if ( (fReaderOptions
.fMacVersionMin
== ObjectFile::ReaderOptions::kMinMacVersionUnset
)
2810 && (fReaderOptions
.fIPhoneVersionMin
== ObjectFile::ReaderOptions::kMinIPhoneVersionUnset
) ) {
2811 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
2812 const char* macVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
2813 const char* iPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
2814 if ( macVers
!= NULL
)
2815 setMacOSXVersionMin(macVers
);
2816 else if ( iPhoneVers
!= NULL
)
2817 setIPhoneVersionMin(iPhoneVers
);
2819 // if still nothing, set default based on architecture
2820 switch ( fArchitecture
) {
2822 case CPU_TYPE_X86_64
:
2823 case CPU_TYPE_POWERPC
:
2824 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_6
; // FIX FIX, this really should be a check of the OS version the linker is running o
2827 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_0
;
2834 // adjust min based on architecture
2835 switch ( fArchitecture
) {
2837 if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_4
) {
2838 //warning("-macosx_version_min should be 10.4 or later for i386");
2839 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_4
;
2842 case CPU_TYPE_POWERPC64
:
2843 if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_4
) {
2844 //warning("-macosx_version_min should be 10.4 or later for ppc64");
2845 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_4
;
2848 case CPU_TYPE_X86_64
:
2849 if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_4
) {
2850 //warning("-macosx_version_min should be 10.4 or later for x86_64");
2851 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_4
;
2856 // adjust kext type based on architecture
2857 if ( fOutputKind
== kKextBundle
) {
2858 switch ( fArchitecture
) {
2859 case CPU_TYPE_X86_64
:
2860 // x86_64 uses new MH_KEXT_BUNDLE type
2861 fMakeClassicDyldInfo
= true;
2862 fMakeCompressedDyldInfo
= false;
2863 fAllowTextRelocs
= true;
2864 fUndefinedTreatment
= kUndefinedDynamicLookup
;
2866 case CPU_TYPE_POWERPC
:
2870 fOutputKind
= kObjectFile
;
2875 // disable implicit dylibs when targeting 10.3
2876 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
2877 if ( !minOS(ObjectFile::ReaderOptions::k10_4
, ObjectFile::ReaderOptions::k2_0
) )
2878 fReaderOptions
.fImplicitlyLinkPublicDylibs
= false;
2881 // allow build system to force linker to ignore -prebind
2882 if ( getenv("LD_FORCE_NO_PREBIND") != NULL
)
2885 // allow build system to force linker to ignore -seg_addr_table
2886 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL
)
2887 fSegAddrTablePath
= NULL
;
2889 // check for base address specified externally
2890 if ( (fSegAddrTablePath
!= NULL
) && (fOutputKind
== Options::kDynamicLibrary
) ) {
2891 parseSegAddrTable(fSegAddrTablePath
, this->installPath());
2892 // HACK to support seg_addr_table entries that are physical paths instead of install paths
2893 if ( fBaseAddress
== 0 ) {
2894 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
2895 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.4.dylib");
2896 if ( fBaseAddress
== 0 )
2897 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.9.dylib");
2900 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
2901 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libz.1.2.3.dylib");
2903 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
2904 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libutil1.0.dylib");
2908 // split segs only allowed for dylibs
2910 // split seg only supported for ppc, i386, and arm.
2911 switch ( fArchitecture
) {
2912 case CPU_TYPE_POWERPC
:
2914 if ( fOutputKind
!= Options::kDynamicLibrary
)
2916 // make sure read and write segments are proper distance apart
2917 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x10000000) )
2918 fBaseWritableAddress
= fBaseAddress
+ 0x10000000;
2921 if ( fOutputKind
!= Options::kDynamicLibrary
) {
2925 // make sure read and write segments are proper distance apart
2926 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x08000000) )
2927 fBaseWritableAddress
= fBaseAddress
+ 0x08000000;
2933 fBaseWritableAddress
= 0;
2937 // <rdar://problem/6138961> -r implies no prebinding for all architectures
2938 if ( fOutputKind
== Options::kObjectFile
)
2941 // disable prebinding depending on arch and min OS version
2943 switch ( fArchitecture
) {
2944 case CPU_TYPE_POWERPC
:
2946 if ( fReaderOptions
.fMacVersionMin
== ObjectFile::ReaderOptions::k10_4
) {
2947 // in 10.4 only split seg dylibs are prebound
2948 if ( (fOutputKind
!= Options::kDynamicLibrary
) || ! fSplitSegs
)
2951 else if ( fReaderOptions
.fMacVersionMin
>= ObjectFile::ReaderOptions::k10_5
) {
2952 // in 10.5 nothing is prebound
2956 // in 10.3 and earlier only dylibs and main executables could be prebound
2957 switch ( fOutputKind
) {
2958 case Options::kDynamicExecutable
:
2959 case Options::kDynamicLibrary
:
2960 // only main executables and dylibs can be prebound
2962 case Options::kStaticExecutable
:
2963 case Options::kDynamicBundle
:
2964 case Options::kObjectFile
:
2965 case Options::kDyld
:
2966 case Options::kPreload
:
2967 case Options::kKextBundle
:
2968 // disable prebinding for everything else
2974 case CPU_TYPE_POWERPC64
:
2975 case CPU_TYPE_X86_64
:
2979 switch ( fOutputKind
) {
2980 case Options::kDynamicExecutable
:
2981 case Options::kDynamicLibrary
:
2982 // only main executables and dylibs can be prebound
2984 case Options::kStaticExecutable
:
2985 case Options::kDynamicBundle
:
2986 case Options::kObjectFile
:
2987 case Options::kDyld
:
2988 case Options::kPreload
:
2989 case Options::kKextBundle
:
2990 // disable prebinding for everything else
2998 // only prebound images can be split-seg
2999 if ( fSplitSegs
&& !fPrebind
)
3002 // determine if info for shared region should be added
3003 if ( fOutputKind
== Options::kDynamicLibrary
) {
3004 if ( minOS(ObjectFile::ReaderOptions::k10_5
, ObjectFile::ReaderOptions::k3_0
) )
3006 if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
3007 || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
3008 fSharedRegionEligible
= true;
3011 // figure out if module table is needed for compatibility with old ld/dyld
3012 if ( fOutputKind
== Options::kDynamicLibrary
) {
3013 switch ( fArchitecture
) {
3014 case CPU_TYPE_POWERPC
: // 10.3 and earlier dyld requires a module table
3015 case CPU_TYPE_I386
: // ld_classic for 10.4.x requires a module table
3016 if ( fReaderOptions
.fMacVersionMin
<= ObjectFile::ReaderOptions::k10_5
)
3017 fNeedsModuleTable
= true;
3021 fNeedsModuleTable
= true; // redo_prebinding requires a module table
3026 // <rdar://problem/5366363> -r -x implies -S
3027 if ( (fOutputKind
== Options::kObjectFile
) && (fLocalSymbolHandling
== kLocalSymbolsNone
) )
3028 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
3030 // choose how to process unwind info
3031 switch ( fArchitecture
) {
3033 case CPU_TYPE_X86_64
:
3034 switch ( fOutputKind
) {
3035 case Options::kObjectFile
:
3036 case Options::kStaticExecutable
:
3037 case Options::kPreload
:
3038 case Options::kKextBundle
:
3039 fReaderOptions
.fAddCompactUnwindEncoding
= false;
3041 case Options::kDyld
:
3042 case Options::kDynamicLibrary
:
3043 case Options::kDynamicBundle
:
3044 case Options::kDynamicExecutable
:
3045 //if ( fReaderOptions.fAddCompactUnwindEncoding && (fReaderOptions.fVersionMin >= ObjectFile::ReaderOptions::k10_6) )
3046 // fReaderOptions.fRemoveDwarfUnwindIfCompactExists = true;
3050 case CPU_TYPE_POWERPC
:
3051 case CPU_TYPE_POWERPC64
:
3053 fReaderOptions
.fAddCompactUnwindEncoding
= false;
3054 fReaderOptions
.fRemoveDwarfUnwindIfCompactExists
= false;
3057 // if -arch is missing, assume we don't want compact unwind info
3058 fReaderOptions
.fAddCompactUnwindEncoding
= false;
3062 // only ARM main executables can be encrypted
3063 if ( fOutputKind
!= Options::kDynamicExecutable
)
3064 fEncryptable
= false;
3065 if ( fArchitecture
!= CPU_TYPE_ARM
)
3066 fEncryptable
= false;
3068 // don't move inits in dyld because dyld wants certain
3069 // entries point at stable locations at the start of __text
3070 if ( fOutputKind
== Options::kDyld
)
3071 fReaderOptions
.fAutoOrderInitializers
= false;
3074 // disable __data ordering for some output kinds
3075 switch ( fOutputKind
) {
3076 case Options::kObjectFile
:
3077 case Options::kDyld
:
3078 case Options::kStaticExecutable
:
3079 case Options::kPreload
:
3080 case Options::kKextBundle
:
3083 case Options::kDynamicExecutable
:
3084 case Options::kDynamicLibrary
:
3085 case Options::kDynamicBundle
:
3089 // only use compressed LINKEDIT for x86_64 and i386
3090 if ( fMakeCompressedDyldInfo
) {
3091 switch (fArchitecture
) {
3093 case CPU_TYPE_X86_64
:
3094 if ( fReaderOptions
.fMacVersionMin
>= ObjectFile::ReaderOptions::k10_6
)
3095 fMakeClassicDyldInfo
= false;
3096 else if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_5
)
3097 fMakeCompressedDyldInfo
= false;
3099 case CPU_TYPE_POWERPC
:
3101 case CPU_TYPE_POWERPC64
:
3103 fMakeCompressedDyldInfo
= false;
3107 // only use compressed LINKEDIT for final linked images
3108 if ( fMakeCompressedDyldInfo
) {
3109 switch ( fOutputKind
) {
3110 case Options::kDynamicExecutable
:
3111 case Options::kDynamicLibrary
:
3112 case Options::kDynamicBundle
:
3114 case Options::kPreload
:
3115 case Options::kStaticExecutable
:
3116 case Options::kObjectFile
:
3117 case Options::kDyld
:
3118 case Options::kKextBundle
:
3119 fMakeCompressedDyldInfo
= false;
3123 fReaderOptions
.fMakeCompressedDyldInfo
= fMakeCompressedDyldInfo
;
3125 // only ARM enforces that cpu-sub-types must match
3126 if ( fArchitecture
!= CPU_TYPE_ARM
)
3127 fAllowCpuSubtypeMismatches
= true;
3130 void Options::checkIllegalOptionCombinations()
3132 // check -undefined setting
3133 switch ( fUndefinedTreatment
) {
3134 case kUndefinedError
:
3135 case kUndefinedDynamicLookup
:
3138 case kUndefinedWarning
:
3139 case kUndefinedSuppress
:
3140 // requires flat namespace
3141 if ( fNameSpace
== kTwoLevelNameSpace
)
3142 throw "can't use -undefined warning or suppress with -twolevel_namespace";
3146 // unify -sub_umbrella with dylibs
3147 for (std::vector
<const char*>::iterator it
= fSubUmbellas
.begin(); it
!= fSubUmbellas
.end(); it
++) {
3148 const char* subUmbrella
= *it
;
3150 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
3151 Options::FileInfo
& info
= *fit
;
3152 const char* lastSlash
= strrchr(info
.path
, '/');
3153 if ( lastSlash
== NULL
)
3154 lastSlash
= info
.path
- 1;
3155 if ( strcmp(&lastSlash
[1], subUmbrella
) == 0 ) {
3156 info
.options
.fReExport
= true;
3162 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella
);
3165 // unify -sub_library with dylibs
3166 for (std::vector
<const char*>::iterator it
= fSubLibraries
.begin(); it
!= fSubLibraries
.end(); it
++) {
3167 const char* subLibrary
= *it
;
3169 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
3170 Options::FileInfo
& info
= *fit
;
3171 const char* lastSlash
= strrchr(info
.path
, '/');
3172 if ( lastSlash
== NULL
)
3173 lastSlash
= info
.path
- 1;
3174 const char* dot
= strchr(&lastSlash
[1], '.');
3176 dot
= &lastSlash
[strlen(lastSlash
)];
3177 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
3178 info
.options
.fReExport
= true;
3184 warning("-sub_library %s does not match a supplied dylib", subLibrary
);
3187 // sync reader options
3188 if ( fNameSpace
!= kTwoLevelNameSpace
)
3189 fReaderOptions
.fFlatNamespace
= true;
3191 // check -stack_addr
3192 if ( fStackAddr
!= 0 ) {
3193 switch (fArchitecture
) {
3195 case CPU_TYPE_POWERPC
:
3197 if ( fStackAddr
> 0xFFFFFFFF )
3198 throw "-stack_addr must be < 4G for 32-bit processes";
3200 case CPU_TYPE_POWERPC64
:
3201 case CPU_TYPE_X86_64
:
3204 if ( (fStackAddr
& -4096) != fStackAddr
)
3205 throw "-stack_addr must be multiples of 4K";
3206 if ( fStackSize
== 0 )
3207 throw "-stack_addr must be used with -stack_size";
3210 // check -stack_size
3211 if ( fStackSize
!= 0 ) {
3212 switch (fArchitecture
) {
3214 case CPU_TYPE_POWERPC
:
3215 if ( fStackSize
> 0xFFFFFFFF )
3216 throw "-stack_size must be < 4G for 32-bit processes";
3217 if ( fStackAddr
== 0 ) {
3218 fStackAddr
= 0xC0000000;
3220 if ( (fStackAddr
> 0xB0000000) && ((fStackAddr
-fStackSize
) < 0xB0000000) )
3221 warning("custom stack placement overlaps and will disable shared region");
3224 if ( fStackSize
> 0xFFFFFFFF )
3225 throw "-stack_size must be < 4G for 32-bit processes";
3226 if ( fStackAddr
== 0 )
3227 fStackAddr
= 0x30000000;
3228 if ( fStackAddr
> 0x40000000)
3229 throw "-stack_addr must be < 1G for arm";
3230 case CPU_TYPE_POWERPC64
:
3231 case CPU_TYPE_X86_64
:
3232 if ( fStackAddr
== 0 ) {
3233 fStackAddr
= 0x00007FFF5C000000LL
;
3237 if ( (fStackSize
& -4096) != fStackSize
)
3238 throw "-stack_size must be multiples of 4K";
3239 switch ( fOutputKind
) {
3240 case Options::kDynamicExecutable
:
3241 case Options::kStaticExecutable
:
3242 // custom stack size only legal when building main executable
3244 case Options::kDynamicLibrary
:
3245 case Options::kDynamicBundle
:
3246 case Options::kObjectFile
:
3247 case Options::kDyld
:
3248 case Options::kPreload
:
3249 case Options::kKextBundle
:
3250 throw "-stack_size option can only be used when linking a main executable";
3254 // check that -allow_stack_execute is only used with main executables
3255 if ( fExecutableStack
) {
3256 switch ( fOutputKind
) {
3257 case Options::kDynamicExecutable
:
3258 case Options::kStaticExecutable
:
3259 // -allow_stack_execute size only legal when building main executable
3261 case Options::kDynamicLibrary
:
3262 case Options::kDynamicBundle
:
3263 case Options::kObjectFile
:
3264 case Options::kDyld
:
3265 case Options::kPreload
:
3266 case Options::kKextBundle
:
3267 throw "-allow_stack_execute option can only be used when linking a main executable";
3271 // check -client_name is only used when making a bundle or main executable
3272 if ( fClientName
!= NULL
) {
3273 switch ( fOutputKind
) {
3274 case Options::kDynamicExecutable
:
3275 case Options::kDynamicBundle
:
3277 case Options::kStaticExecutable
:
3278 case Options::kDynamicLibrary
:
3279 case Options::kObjectFile
:
3280 case Options::kDyld
:
3281 case Options::kPreload
:
3282 case Options::kKextBundle
:
3283 throw "-client_name can only be used with -bundle";
3287 // check -init is only used when building a dylib
3288 if ( (fInitFunctionName
!= NULL
) && (fOutputKind
!= Options::kDynamicLibrary
) )
3289 throw "-init can only be used with -dynamiclib";
3291 // check -bundle_loader only used with -bundle
3292 if ( (fBundleLoader
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
3293 throw "-bundle_loader can only be used with -bundle";
3295 // check -dtrace not used with -r
3296 if ( (fDtraceScriptName
!= NULL
) && (fOutputKind
== Options::kObjectFile
) )
3297 throw "-dtrace can only be used when creating final linked images";
3299 // check -d can only be used with -r
3300 if ( fReaderOptions
.fMakeTentativeDefinitionsReal
&& (fOutputKind
!= Options::kObjectFile
) )
3301 throw "-d can only be used with -r";
3303 // check that -root_safe is not used with -r
3304 if ( fReaderOptions
.fRootSafe
&& (fOutputKind
== Options::kObjectFile
) )
3305 throw "-root_safe cannot be used with -r";
3307 // check that -setuid_safe is not used with -r
3308 if ( fReaderOptions
.fSetuidSafe
&& (fOutputKind
== Options::kObjectFile
) )
3309 throw "-setuid_safe cannot be used with -r";
3311 // make sure all required exported symbols exist
3312 std::vector
<const char*> impliedExports
;
3313 for (NameSet::iterator it
=fExportSymbols
.regularBegin(); it
!= fExportSymbols
.regularEnd(); it
++) {
3314 const char* name
= *it
;
3315 // never export .eh symbols
3316 const int len
= strlen(name
);
3317 if ( (strcmp(&name
[len
-3], ".eh") == 0) || (strncmp(name
, ".objc_category_name_", 20) == 0) )
3318 warning("ignoring %s in export list", name
);
3320 fInitialUndefines
.push_back(name
);
3321 if ( strncmp(name
, ".objc_class_name_", 17) == 0 ) {
3322 // rdar://problem/4718189 map ObjC class names to new runtime names
3323 switch (fArchitecture
) {
3324 case CPU_TYPE_POWERPC64
:
3325 case CPU_TYPE_X86_64
:
3328 asprintf(&temp
, "_OBJC_CLASS_$_%s", &name
[17]);
3329 impliedExports
.push_back(temp
);
3330 asprintf(&temp
, "_OBJC_METACLASS_$_%s", &name
[17]);
3331 impliedExports
.push_back(temp
);
3336 for (std::vector
<const char*>::iterator it
=impliedExports
.begin(); it
!= impliedExports
.end(); it
++) {
3337 const char* name
= *it
;
3338 fExportSymbols
.insert(name
);
3339 fInitialUndefines
.push_back(name
);
3342 // make sure that -init symbol exist
3343 if ( fInitFunctionName
!= NULL
)
3344 fInitialUndefines
.push_back(fInitFunctionName
);
3346 // check custom segments
3347 if ( fCustomSegmentAddresses
.size() != 0 ) {
3348 // verify no segment is in zero page
3349 if ( fZeroPageSize
!= ULLONG_MAX
) {
3350 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
3351 if ( (it
->address
>= 0) && (it
->address
< fZeroPageSize
) )
3352 throwf("-segaddr %s 0x%X conflicts with -pagezero_size", it
->name
, it
->address
);
3355 // verify no duplicates
3356 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
3357 for (std::vector
<SegmentStart
>::iterator it2
= fCustomSegmentAddresses
.begin(); it2
!= fCustomSegmentAddresses
.end(); ++it2
) {
3358 if ( (it
->address
== it2
->address
) && (it
!= it2
) )
3359 throwf("duplicate -segaddr addresses for %s and %s", it
->name
, it2
->name
);
3361 // a custom segment address of zero will disable the use of a zero page
3362 if ( it
->address
== 0 )
3367 if ( fZeroPageSize
== ULLONG_MAX
) {
3368 // zero page size not specified on command line, set default
3369 switch (fArchitecture
) {
3371 case CPU_TYPE_POWERPC
:
3373 // first 4KB for 32-bit architectures
3374 fZeroPageSize
= 0x1000;
3376 case CPU_TYPE_POWERPC64
:
3377 // first 4GB for ppc64 on 10.5
3378 if ( fReaderOptions
.fMacVersionMin
>= ObjectFile::ReaderOptions::k10_5
)
3379 fZeroPageSize
= 0x100000000ULL
;
3381 fZeroPageSize
= 0x1000; // 10.4 dyld may not be able to handle >4GB zero page
3383 case CPU_TYPE_X86_64
:
3384 // first 4GB for x86_64 on all OS's
3385 fZeroPageSize
= 0x100000000ULL
;
3388 // if -arch not used, default to 4K zero-page
3389 fZeroPageSize
= 0x1000;
3393 switch ( fOutputKind
) {
3394 case Options::kDynamicExecutable
:
3395 case Options::kStaticExecutable
:
3396 // -pagezero_size size only legal when building main executable
3398 case Options::kDynamicLibrary
:
3399 case Options::kDynamicBundle
:
3400 case Options::kObjectFile
:
3401 case Options::kDyld
:
3402 case Options::kPreload
:
3403 case Options::kKextBundle
:
3404 if ( fZeroPageSize
!= 0 )
3405 throw "-pagezero_size option can only be used when linking a main executable";
3409 // -dead_strip and -r are incompatible
3410 if ( (fDeadStrip
!= kDeadStripOff
) && (fOutputKind
== Options::kObjectFile
) )
3411 throw "-r and -dead_strip cannot be used together";
3413 // can't use -rpath unless targeting 10.5 or later
3414 if ( fRPaths
.size() > 0 ) {
3415 if ( !minOS(ObjectFile::ReaderOptions::k10_5
, ObjectFile::ReaderOptions::k2_0
) )
3416 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
3417 switch ( fOutputKind
) {
3418 case Options::kDynamicExecutable
:
3419 case Options::kDynamicLibrary
:
3420 case Options::kDynamicBundle
:
3422 case Options::kStaticExecutable
:
3423 case Options::kObjectFile
:
3424 case Options::kDyld
:
3425 case Options::kPreload
:
3426 case Options::kKextBundle
:
3427 throw "-rpath can only be used when creating a dynamic final linked image";
3431 // check -pie is only used when building a dynamic main executable for 10.5
3432 if ( fPositionIndependentExecutable
) {
3433 switch ( fOutputKind
) {
3434 case Options::kDynamicExecutable
:
3435 case Options::kPreload
:
3437 case Options::kDynamicLibrary
:
3438 case Options::kDynamicBundle
:
3439 warning("-pie being ignored. It is only used when linking a main executable");
3441 case Options::kStaticExecutable
:
3442 case Options::kObjectFile
:
3443 case Options::kDyld
:
3444 case Options::kKextBundle
:
3445 throw "-pie can only be used when linking a main executable";
3447 if ( !minOS(ObjectFile::ReaderOptions::k10_5
, ObjectFile::ReaderOptions::k2_0
) )
3448 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
3451 // check -read_only_relocs is not used with x86_64
3452 if ( fAllowTextRelocs
) {
3453 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
!= kKextBundle
) ) {
3454 warning("-read_only_relocs cannot be used with x86_64");
3455 fAllowTextRelocs
= false;
3459 // check -mark_auto_dead_strip is only used with dylibs
3460 if ( fMarkDeadStrippableDylib
) {
3461 if ( fOutputKind
!= Options::kDynamicLibrary
) {
3462 warning("-mark_auto_dead_strip can only be used when creating a dylib");
3463 fMarkDeadStrippableDylib
= false;
3470 void Options::checkForClassic(int argc
, const char* argv
[])
3473 bool archFound
= false;
3474 bool staticFound
= false;
3475 bool dtraceFound
= false;
3476 bool kextFound
= false;
3477 bool rFound
= false;
3478 bool creatingMachKernel
= false;
3479 bool newLinker
= false;
3481 // build command line buffer in case ld crashes
3482 for(int i
=1; i
< argc
; ++i
) {
3483 strlcat(crashreporterBuffer
, argv
[i
], 1000);
3484 strlcat(crashreporterBuffer
, " ", 1000);
3487 for(int i
=0; i
< argc
; ++i
) {
3488 const char* arg
= argv
[i
];
3489 if ( arg
[0] == '-' ) {
3490 if ( strcmp(arg
, "-arch") == 0 ) {
3491 parseArch(argv
[++i
]);
3494 else if ( strcmp(arg
, "-static") == 0 ) {
3497 else if ( strcmp(arg
, "-kext") == 0 ) {
3500 else if ( strcmp(arg
, "-dtrace") == 0 ) {
3503 else if ( strcmp(arg
, "-r") == 0 ) {
3506 else if ( strcmp(arg
, "-new_linker") == 0 ) {
3509 else if ( strcmp(arg
, "-classic_linker") == 0 ) {
3510 // ld_classic does not understand this option, so remove it
3511 for(int j
=i
; j
< argc
; ++j
)
3512 argv
[j
] = argv
[j
+1];
3513 this->gotoClassicLinker(argc
-1, argv
);
3515 else if ( strcmp(arg
, "-o") == 0 ) {
3516 const char* outfile
= argv
[++i
];
3517 if ( (outfile
!= NULL
) && (strstr(outfile
, "/mach_kernel") != NULL
) )
3518 creatingMachKernel
= true;
3523 // -dtrace only supported by new linker
3528 switch ( fArchitecture
) {
3529 case CPU_TYPE_POWERPC
:
3532 // if ( staticFound && (rFound || !creatingMachKernel) ) {
3533 if ( (staticFound
|| kextFound
) && !newLinker
) {
3534 // this environment variable will disable use of ld_classic for -static links
3535 if ( getenv("LD_NO_CLASSIC_LINKER_STATIC") == NULL
) {
3536 // ld_classic does not support -iphoneos_version_min, so change
3537 for(int j
=0; j
< argc
; ++j
) {
3538 if ( strcmp(argv
[j
], "-iphoneos_version_min") == 0) {
3539 argv
[j
] = "-macosx_version_min";
3545 // ld classic does not understand -kext (change to -static -r)
3547 for(int j
=0; j
< argc
; ++j
) {
3548 if ( strcmp(argv
[j
], "-kext") == 0)
3550 else if ( strcmp(argv
[j
], "-dynamic") == 0)
3551 argv
[j
] = "-static";
3554 this->gotoClassicLinker(argc
, argv
);
3561 // work around for VSPTool
3563 this->gotoClassicLinker(argc
, argv
);
3568 void Options::gotoClassicLinker(int argc
, const char* argv
[])
3570 argv
[0] = "ld_classic";
3571 char path
[PATH_MAX
];
3572 uint32_t bufSize
= PATH_MAX
;
3573 if ( _NSGetExecutablePath(path
, &bufSize
) != -1 ) {
3574 char* lastSlash
= strrchr(path
, '/');
3575 if ( lastSlash
!= NULL
) {
3576 strcpy(lastSlash
+1, "ld_classic");
3577 execvp(path
, (char**)argv
);
3580 // in case of error in above, try searching for ld_classic via PATH
3581 execvp(argv
[0], (char**)argv
);
3582 fprintf(stderr
, "can't exec ld_classic\n");