1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2005-2008 Apple Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
22 * @APPLE_LICENSE_HEADER_END@
26 #include <sys/types.h>
28 #include <mach/vm_prot.h>
29 #include <mach-o/dyld.h>
33 #include "configure.h"
35 #include "Architectures.hpp"
36 #include "MachOFileAbstraction.hpp"
38 extern void printLTOVersion(Options
&opts
);
40 // magic to place command line in crash reports
41 extern "C" char* __crashreporter_info__
;
42 static char crashreporterBuffer
[1000];
43 char* __crashreporter_info__
= crashreporterBuffer
;
45 static bool sEmitWarnings
= true;
46 static const char* sWarningsSideFilePath
= NULL
;
47 static FILE* sWarningsSideFile
= NULL
;
49 void warning(const char* format
, ...)
51 if ( sEmitWarnings
) {
53 if ( sWarningsSideFilePath
!= NULL
) {
54 if ( sWarningsSideFile
== NULL
)
55 sWarningsSideFile
= fopen(sWarningsSideFilePath
, "a");
57 va_start(list
, format
);
58 fprintf(stderr
, "ld: warning: ");
59 vfprintf(stderr
, format
, list
);
60 fprintf(stderr
, "\n");
61 if ( sWarningsSideFile
!= NULL
) {
62 fprintf(sWarningsSideFile
, "ld: warning: ");
63 vfprintf(sWarningsSideFile
, format
, list
);
64 fprintf(sWarningsSideFile
, "\n");
65 fflush(sWarningsSideFile
);
71 void throwf(const char* format
, ...)
75 va_start(list
, format
);
76 vasprintf(&p
, format
, list
);
83 Options::Options(int argc
, const char* argv
[])
84 : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0), fOutputKind(kDynamicExecutable
),
85 fHasPreferredSubType(false), fPrebind(false), fBindAtLoad(false), fKeepPrivateExterns(false),
86 fNeedsModuleTable(false), fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false),
87 fInterposeMode(kInterposeNone
), fDeadStrip(kDeadStripOff
), fNameSpace(kTwoLevelNameSpace
),
88 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL
), fFinalName(NULL
), fEntryName("start"), fBaseAddress(0),
89 fBaseWritableAddress(0), fSplitSegs(false),
90 fExportMode(kExportDefault
), fLibrarySearchMode(kSearchAllDirsForDylibsThenAllDirsForArchives
),
91 fUndefinedTreatment(kUndefinedError
), fMessagesPrefixedWithArchitecture(false),
92 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak
),
94 fUmbrellaName(NULL
), fInitFunctionName(NULL
), fDotOutputFile(NULL
), fExecutablePath(NULL
),
95 fBundleLoader(NULL
), fDtraceScriptName(NULL
), fSegAddrTablePath(NULL
), fMapPath(NULL
),
96 fZeroPageSize(ULLONG_MAX
), fStackSize(0), fStackAddr(0), fExecutableStack(false),
97 fMinimumHeaderPad(32), fSegmentAlignment(4096),
98 fCommonsMode(kCommonsIgnoreDylibs
), fUUIDMode(kUUIDContent
), fLocalSymbolHandling(kLocalSymbolsAll
), fWarnCommons(false),
99 fVerbose(false), fKeepRelocations(false), fWarnStabs(false),
100 fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
101 fSharedRegionEligible(false), fPrintOrderFileStatistics(false),
102 fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
103 fDeadStripDylibs(false), fAllowTextRelocs(false), fWarnTextRelocs(false),
104 fUsingLazyDylibLinking(false), fEncryptable(true),
105 fOrderData(true), fMarkDeadStrippableDylib(false),
106 fMakeClassicDyldInfo(true), fMakeCompressedDyldInfo(true), fAllowCpuSubtypeMismatches(false), fSaveTempFiles(false)
108 this->checkForClassic(argc
, argv
);
109 this->parsePreCommandLineEnvironmentSettings();
110 this->parse(argc
, argv
);
111 this->parsePostCommandLineEnvironmentSettings();
112 this->reconfigureDefaults();
113 this->checkIllegalOptionCombinations();
120 const ObjectFile::ReaderOptions
& Options::readerOptions()
122 return fReaderOptions
;
126 const char* Options::getOutputFilePath()
131 std::vector
<Options::FileInfo
>& Options::getInputFiles()
136 Options::OutputKind
Options::outputKind()
141 bool Options::bindAtLoad()
146 bool Options::prebind()
151 bool Options::fullyLoadArchives()
153 return fReaderOptions
.fFullyLoadArchives
;
156 Options::NameSpace
Options::nameSpace()
161 const char* Options::installPath()
163 if ( fDylibInstallName
!= NULL
)
164 return fDylibInstallName
;
165 else if ( fFinalName
!= NULL
)
171 uint32_t Options::currentVersion()
173 return fDylibCurrentVersion
;
176 uint32_t Options::compatibilityVersion()
178 return fDylibCompatVersion
;
181 const char* Options::entryName()
186 uint64_t Options::baseAddress()
191 bool Options::keepPrivateExterns()
193 return fKeepPrivateExterns
;
196 bool Options::interposable(const char* name
)
198 switch ( fInterposeMode
) {
201 case kInterposeAllExternal
:
204 return fInterposeList
.contains(name
);
206 throw "internal error";
209 bool Options::needsModuleTable()
211 return fNeedsModuleTable
;
214 bool Options::ignoreOtherArchInputFiles()
216 return fIgnoreOtherArchFiles
;
219 bool Options::forceCpuSubtypeAll()
221 return fForceSubtypeAll
;
224 bool Options::traceDylibs()
226 return fReaderOptions
.fTraceDylibs
;
229 bool Options::traceArchives()
231 return fReaderOptions
.fTraceArchives
;
234 Options::UndefinedTreatment
Options::undefinedTreatment()
236 return fUndefinedTreatment
;
239 Options::WeakReferenceMismatchTreatment
Options::weakReferenceMismatchTreatment()
241 return fWeakReferenceMismatchTreatment
;
244 const char* Options::umbrellaName()
246 return fUmbrellaName
;
249 std::vector
<const char*>& Options::allowableClients()
251 return fAllowableClients
;
254 const char* Options::clientName()
259 uint64_t Options::zeroPageSize()
261 return fZeroPageSize
;
264 bool Options::hasCustomStack()
266 return (fStackSize
!= 0);
269 uint64_t Options::customStackSize()
274 uint64_t Options::customStackAddr()
279 bool Options::hasExecutableStack()
281 return fExecutableStack
;
284 std::vector
<const char*>& Options::initialUndefines()
286 return fInitialUndefines
;
289 bool Options::printWhyLive(const char* symbolName
)
291 return ( fWhyLive
.find(symbolName
) != fWhyLive
.end() );
295 const char* Options::initFunctionName()
297 return fInitFunctionName
;
300 const char* Options::dotOutputFile()
302 return fDotOutputFile
;
305 bool Options::hasExportRestrictList()
307 return (fExportMode
!= kExportDefault
);
310 bool Options::hasExportMaskList()
312 return (fExportMode
== kExportSome
);
316 bool Options::hasWildCardExportRestrictList()
318 // has -exported_symbols_list which contains some wildcards
319 return ((fExportMode
== kExportSome
) && fExportSymbols
.hasWildCards());
323 bool Options::allGlobalsAreDeadStripRoots()
325 // -exported_symbols_list means globals are not exported by default
326 if ( fExportMode
== kExportSome
)
329 switch ( fOutputKind
) {
330 case Options::kDynamicExecutable
:
331 case Options::kStaticExecutable
:
332 case Options::kPreload
:
333 // by default unused globals in a main executable are stripped
335 case Options::kDynamicLibrary
:
336 case Options::kDynamicBundle
:
337 case Options::kObjectFile
:
339 case Options::kKextBundle
:
345 uint32_t Options::minimumHeaderPad()
347 return fMinimumHeaderPad
;
350 std::vector
<Options::ExtraSection
>& Options::extraSections()
352 return fExtraSections
;
355 std::vector
<Options::SectionAlignment
>& Options::sectionAlignments()
357 return fSectionAlignments
;
360 Options::CommonsMode
Options::commonsMode()
365 bool Options::warnCommons()
370 bool Options::keepRelocations()
372 return fKeepRelocations
;
375 bool Options::warnStabs()
380 const char* Options::executablePath()
382 return fExecutablePath
;
385 Options::DeadStripMode
Options::deadStrip()
390 bool Options::hasExportedSymbolOrder()
392 return (fExportSymbolsOrder
.size() > 0);
395 bool Options::exportedSymbolOrder(const char* sym
, unsigned int* order
)
397 NameToOrder::iterator pos
= fExportSymbolsOrder
.find(sym
);
398 if ( pos
!= fExportSymbolsOrder
.end() ) {
399 *order
= pos
->second
;
408 void Options::loadSymbolOrderFile(const char* fileOfExports
, NameToOrder
& orderMapping
)
410 // read in whole file
411 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
413 throwf("can't open -exported_symbols_order file: %s", fileOfExports
);
414 struct stat stat_buf
;
415 ::fstat(fd
, &stat_buf
);
416 char* p
= (char*)malloc(stat_buf
.st_size
);
418 throwf("can't process -exported_symbols_order file: %s", fileOfExports
);
420 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
421 throwf("can't read -exported_symbols_order file: %s", fileOfExports
);
425 // parse into symbols and add to hash_set
426 unsigned int count
= 0;
427 char * const end
= &p
[stat_buf
.st_size
];
428 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
429 char* symbolStart
= NULL
;
430 for (char* s
= p
; s
< end
; ++s
) {
436 else if ( !isspace(*s
) ) {
442 if ( (*s
== '\n') || (*s
== '\r') ) {
444 // removing any trailing spaces
446 while ( isspace(*last
) ) {
450 orderMapping
[symbolStart
] = ++count
;
456 if ( (*s
== '\n') || (*s
== '\r') )
461 if ( state
== inSymbol
) {
462 warning("missing line-end at end of file \"%s\"", fileOfExports
);
463 int len
= end
-symbolStart
+1;
464 char* temp
= new char[len
];
465 strlcpy(temp
, symbolStart
, len
);
467 // remove any trailing spaces
468 char* last
= &temp
[len
-2];
469 while ( isspace(*last
) ) {
473 orderMapping
[temp
] = ++count
;
476 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
480 bool Options::shouldExport(const char* symbolName
)
482 switch (fExportMode
) {
484 return fExportSymbols
.contains(symbolName
);
485 case kDontExportSome
:
486 return ! fDontExportSymbols
.contains(symbolName
);
490 throw "internal error";
493 bool Options::keepLocalSymbol(const char* symbolName
)
495 switch (fLocalSymbolHandling
) {
496 case kLocalSymbolsAll
:
498 case kLocalSymbolsNone
:
500 case kLocalSymbolsSelectiveInclude
:
501 return fLocalSymbolsIncluded
.contains(symbolName
);
502 case kLocalSymbolsSelectiveExclude
:
503 return ! fLocalSymbolsExcluded
.contains(symbolName
);
505 throw "internal error";
508 void Options::parseArch(const char* architecture
)
510 if ( architecture
== NULL
)
511 throw "-arch must be followed by an architecture string";
512 if ( strcmp(architecture
, "ppc") == 0 ) {
513 fArchitecture
= CPU_TYPE_POWERPC
;
514 fSubArchitecture
= CPU_SUBTYPE_POWERPC_ALL
;
516 else if ( strcmp(architecture
, "ppc64") == 0 ) {
517 fArchitecture
= CPU_TYPE_POWERPC64
;
518 fSubArchitecture
= CPU_SUBTYPE_POWERPC_ALL
;
520 else if ( strcmp(architecture
, "i386") == 0 ) {
521 fArchitecture
= CPU_TYPE_I386
;
522 fSubArchitecture
= CPU_SUBTYPE_I386_ALL
;
524 else if ( strcmp(architecture
, "x86_64") == 0 ) {
525 fArchitecture
= CPU_TYPE_X86_64
;
526 fSubArchitecture
= CPU_SUBTYPE_X86_64_ALL
;
528 else if ( strcmp(architecture
, "arm") == 0 ) {
529 fArchitecture
= CPU_TYPE_ARM
;
530 fSubArchitecture
= CPU_SUBTYPE_ARM_ALL
;
532 // compatibility support for cpu-sub-types
533 else if ( strcmp(architecture
, "ppc750") == 0 ) {
534 fArchitecture
= CPU_TYPE_POWERPC
;
535 fSubArchitecture
= CPU_SUBTYPE_POWERPC_750
;
536 fHasPreferredSubType
= true;
538 else if ( strcmp(architecture
, "ppc7400") == 0 ) {
539 fArchitecture
= CPU_TYPE_POWERPC
;
540 fSubArchitecture
= CPU_SUBTYPE_POWERPC_7400
;
541 fHasPreferredSubType
= true;
543 else if ( strcmp(architecture
, "ppc7450") == 0 ) {
544 fArchitecture
= CPU_TYPE_POWERPC
;
545 fSubArchitecture
= CPU_SUBTYPE_POWERPC_7450
;
546 fHasPreferredSubType
= true;
548 else if ( strcmp(architecture
, "ppc970") == 0 ) {
549 fArchitecture
= CPU_TYPE_POWERPC
;
550 fSubArchitecture
= CPU_SUBTYPE_POWERPC_970
;
551 fHasPreferredSubType
= true;
553 else if ( strcmp(architecture
, "armv6") == 0 ) {
554 fArchitecture
= CPU_TYPE_ARM
;
555 fSubArchitecture
= CPU_SUBTYPE_ARM_V6
;
556 fHasPreferredSubType
= true;
558 else if ( strcmp(architecture
, "armv5") == 0 ) {
559 fArchitecture
= CPU_TYPE_ARM
;
560 fSubArchitecture
= CPU_SUBTYPE_ARM_V5TEJ
;
561 fHasPreferredSubType
= true;
563 else if ( strcmp(architecture
, "armv4t") == 0 ) {
564 fArchitecture
= CPU_TYPE_ARM
;
565 fSubArchitecture
= CPU_SUBTYPE_ARM_V4T
;
566 fHasPreferredSubType
= true;
568 else if ( strcmp(architecture
, "xscale") == 0 ) {
569 fArchitecture
= CPU_TYPE_ARM
;
570 fSubArchitecture
= CPU_SUBTYPE_ARM_XSCALE
;
571 fHasPreferredSubType
= true;
573 else if ( strcmp(architecture
, "armv7") == 0 ) {
574 fArchitecture
= CPU_TYPE_ARM
;
575 fSubArchitecture
= CPU_SUBTYPE_ARM_V7
;
576 fHasPreferredSubType
= true;
579 throwf("unknown/unsupported architecture name for: -arch %s", architecture
);
582 bool Options::checkForFile(const char* format
, const char* dir
, const char* rootName
, FileInfo
& result
)
584 struct stat statBuffer
;
585 char possiblePath
[strlen(dir
)+strlen(rootName
)+strlen(format
)+8];
586 sprintf(possiblePath
, format
, dir
, rootName
);
587 bool found
= (stat(possiblePath
, &statBuffer
) == 0);
588 if ( fTraceDylibSearching
)
589 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), possiblePath
);
591 result
.path
= strdup(possiblePath
);
592 result
.fileLen
= statBuffer
.st_size
;
593 result
.modTime
= statBuffer
.st_mtime
;
600 Options::FileInfo
Options::findLibrary(const char* rootName
, bool dylibsOnly
)
603 const int rootNameLen
= strlen(rootName
);
604 // if rootName ends in .o there is no .a vs .dylib choice
605 if ( (rootNameLen
> 3) && (strcmp(&rootName
[rootNameLen
-2], ".o") == 0) ) {
606 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
607 it
!= fLibrarySearchPaths
.end();
609 const char* dir
= *it
;
610 if ( checkForFile("%s/%s", dir
, rootName
, result
) )
615 bool lookForDylibs
= ( fOutputKind
!= Options::kDyld
);
616 switch ( fLibrarySearchMode
) {
617 case kSearchAllDirsForDylibsThenAllDirsForArchives
:
618 // first look in all directories for just for dylibs
619 if ( lookForDylibs
) {
620 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
621 it
!= fLibrarySearchPaths
.end();
623 const char* dir
= *it
;
624 if ( checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
627 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
628 it
!= fLibrarySearchPaths
.end();
630 const char* dir
= *it
;
631 if ( checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
635 // next look in all directories for just for archives
637 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
638 it
!= fLibrarySearchPaths
.end();
640 const char* dir
= *it
;
641 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
647 case kSearchDylibAndArchiveInEachDir
:
648 // look in each directory for just for a dylib then for an archive
649 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
650 it
!= fLibrarySearchPaths
.end();
652 const char* dir
= *it
;
653 if ( lookForDylibs
&& checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
655 if ( lookForDylibs
&& checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
657 if ( !dylibsOnly
&& checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
663 throwf("library not found for -l%s", rootName
);
666 Options::FileInfo
Options::findFramework(const char* frameworkName
)
668 if ( frameworkName
== NULL
)
669 throw "-framework missing next argument";
670 char temp
[strlen(frameworkName
)+1];
671 strcpy(temp
, frameworkName
);
672 const char* name
= temp
;
673 const char* suffix
= NULL
;
674 char* comma
= strchr(temp
, ',');
675 if ( comma
!= NULL
) {
679 return findFramework(name
, suffix
);
682 Options::FileInfo
Options::findFramework(const char* rootName
, const char* suffix
)
684 struct stat statBuffer
;
685 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
686 it
!= fFrameworkSearchPaths
.end();
688 // ??? Shouldn't we be using String here and just initializing it?
689 // ??? Use str.c_str () to pull out the string for the stat call.
690 const char* dir
= *it
;
691 char possiblePath
[PATH_MAX
];
692 strcpy(possiblePath
, dir
);
693 strcat(possiblePath
, "/");
694 strcat(possiblePath
, rootName
);
695 strcat(possiblePath
, ".framework/");
696 strcat(possiblePath
, rootName
);
697 if ( suffix
!= NULL
) {
698 char realPath
[PATH_MAX
];
699 // no symlink in framework to suffix variants, so follow main symlink
700 if ( realpath(possiblePath
, realPath
) != NULL
) {
701 strcpy(possiblePath
, realPath
);
702 strcat(possiblePath
, suffix
);
705 bool found
= (stat(possiblePath
, &statBuffer
) == 0);
706 if ( fTraceDylibSearching
)
707 printf("[Logging for XBS]%sfound framework: '%s'\n",
708 (found
? " " : " not "), possiblePath
);
711 result
.path
= strdup(possiblePath
);
712 result
.fileLen
= statBuffer
.st_size
;
713 result
.modTime
= statBuffer
.st_mtime
;
717 // try without suffix
718 if ( suffix
!= NULL
)
719 return findFramework(rootName
, NULL
);
721 throwf("framework not found %s", rootName
);
724 Options::FileInfo
Options::findFile(const char* path
)
727 struct stat statBuffer
;
729 // if absolute path and not a .o file, the use SDK prefix
730 if ( (path
[0] == '/') && (strcmp(&path
[strlen(path
)-2], ".o") != 0) ) {
731 const int pathLen
= strlen(path
);
732 for (std::vector
<const char*>::iterator it
= fSDKPaths
.begin(); it
!= fSDKPaths
.end(); it
++) {
733 // ??? Shouldn't we be using String here?
734 const char* sdkPathDir
= *it
;
735 const int sdkPathDirLen
= strlen(sdkPathDir
);
736 char possiblePath
[sdkPathDirLen
+pathLen
+4];
737 strcpy(possiblePath
, sdkPathDir
);
738 if ( possiblePath
[sdkPathDirLen
-1] == '/' )
739 possiblePath
[sdkPathDirLen
-1] = '\0';
740 strcat(possiblePath
, path
);
741 if ( stat(possiblePath
, &statBuffer
) == 0 ) {
742 result
.path
= strdup(possiblePath
);
743 result
.fileLen
= statBuffer
.st_size
;
744 result
.modTime
= statBuffer
.st_mtime
;
750 if ( stat(path
, &statBuffer
) == 0 ) {
751 result
.path
= strdup(path
);
752 result
.fileLen
= statBuffer
.st_size
;
753 result
.modTime
= statBuffer
.st_mtime
;
757 // try @executable_path substitution
758 if ( (strncmp(path
, "@executable_path/", 17) == 0) && (fExecutablePath
!= NULL
) ) {
759 char newPath
[strlen(fExecutablePath
) + strlen(path
)];
760 strcpy(newPath
, fExecutablePath
);
761 char* addPoint
= strrchr(newPath
,'/');
762 if ( addPoint
!= NULL
)
763 strcpy(&addPoint
[1], &path
[17]);
765 strcpy(newPath
, &path
[17]);
766 if ( stat(newPath
, &statBuffer
) == 0 ) {
767 result
.path
= strdup(newPath
);
768 result
.fileLen
= statBuffer
.st_size
;
769 result
.modTime
= statBuffer
.st_mtime
;
775 throwf("file not found: %s", path
);
778 Options::FileInfo
Options::findFileUsingPaths(const char* path
)
782 const char* lastSlash
= strrchr(path
, '/');
783 const char* leafName
= (lastSlash
== NULL
) ? path
: &lastSlash
[1];
785 // Is this in a framework?
786 // /path/Foo.framework/Foo ==> true (Foo)
787 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
788 // /path/Foo.framework/Resources/Bar ==> false
789 bool isFramework
= false;
790 if ( lastSlash
!= NULL
) {
791 char frameworkDir
[strlen(leafName
) + 20];
792 strcpy(frameworkDir
, "/");
793 strcat(frameworkDir
, leafName
);
794 strcat(frameworkDir
, ".framework/");
795 if ( strstr(path
, frameworkDir
) != NULL
)
799 // These are abbreviated versions of the routines findFramework and findLibrary above
800 // because we already know the final name of the file that we're looking for and so
801 // don't need to try variations, just paths. We do need to add the additional bits
802 // onto the framework path though.
804 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
805 it
!= fFrameworkSearchPaths
.end();
807 const char* dir
= *it
;
808 char possiblePath
[PATH_MAX
];
809 strcpy(possiblePath
, dir
);
810 strcat(possiblePath
, "/");
811 strcat(possiblePath
, leafName
);
812 strcat(possiblePath
, ".framework");
814 //fprintf(stderr,"Finding Framework: %s/%s, leafName=%s\n", possiblePath, leafName, leafName);
815 if ( checkForFile("%s/%s", possiblePath
, leafName
, result
) )
820 // if this is a .dylib inside a framework, do not search -L paths
821 // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
822 int leafLen
= strlen(leafName
);
823 bool embeddedDylib
= ( (leafLen
> 6)
824 && (strcmp(&leafName
[leafLen
-6], ".dylib") == 0)
825 && (strstr(path
, ".framework/") != NULL
) );
826 if ( !embeddedDylib
) {
827 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
828 it
!= fLibrarySearchPaths
.end();
830 const char* dir
= *it
;
831 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
832 if ( checkForFile("%s/%s", dir
, leafName
, result
) )
838 // If we didn't find it fall back to findFile.
839 return findFile(path
);
843 void Options::parseSegAddrTable(const char* segAddrPath
, const char* installPath
)
845 FILE* file
= fopen(segAddrPath
, "r");
846 if ( file
== NULL
) {
847 warning("-seg_addr_table file cannot be read: %s", segAddrPath
);
852 uint64_t firstColumAddress
= 0;
853 uint64_t secondColumAddress
= 0;
854 bool hasSecondColumn
= false;
855 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
856 path
[PATH_MAX
-1] = '\0';
857 char* eol
= strchr(path
, '\n');
860 // ignore lines not starting with 0x number
861 if ( (path
[0] == '0') && (path
[1] == 'x') ) {
863 firstColumAddress
= strtoull(path
, &p
, 16);
864 while ( isspace(*p
) )
866 // see if second column is a number
867 if ( (p
[0] == '0') && (p
[1] == 'x') ) {
868 secondColumAddress
= strtoull(p
, &p
, 16);
869 hasSecondColumn
= true;
870 while ( isspace(*p
) )
873 while ( isspace(*p
) )
876 // remove any trailing whitespace
877 for(char* end
= eol
-1; (end
> p
) && isspace(*end
); --end
)
879 // see if this line is for the dylib being linked
880 if ( strcmp(p
, installPath
) == 0 ) {
881 fBaseAddress
= firstColumAddress
;
882 if ( hasSecondColumn
) {
883 fBaseWritableAddress
= secondColumAddress
;
886 break; // out of while loop
895 void Options::loadFileList(const char* fileOfPaths
)
898 const char* comma
= strrchr(fileOfPaths
, ',');
899 const char* prefix
= NULL
;
900 if ( comma
!= NULL
) {
901 // <rdar://problem/5907981> -filelist fails with comma in path
902 file
= fopen(fileOfPaths
, "r");
903 if ( file
== NULL
) {
905 int realFileOfPathsLen
= comma
-fileOfPaths
;
906 char realFileOfPaths
[realFileOfPathsLen
+1];
907 strncpy(realFileOfPaths
,fileOfPaths
, realFileOfPathsLen
);
908 realFileOfPaths
[realFileOfPathsLen
] = '\0';
909 file
= fopen(realFileOfPaths
, "r");
911 throwf("-filelist file not found: %s\n", realFileOfPaths
);
915 file
= fopen(fileOfPaths
, "r");
917 throwf("-filelist file not found: %s\n", fileOfPaths
);
921 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
922 path
[PATH_MAX
-1] = '\0';
923 char* eol
= strchr(path
, '\n');
926 if ( prefix
!= NULL
) {
927 char builtPath
[strlen(prefix
)+strlen(path
)+2];
928 strcpy(builtPath
, prefix
);
929 strcat(builtPath
, "/");
930 strcat(builtPath
, path
);
931 fInputFiles
.push_back(findFile(builtPath
));
934 fInputFiles
.push_back(findFile(path
));
940 bool Options::SetWithWildcards::hasWildCards(const char* symbol
)
942 // an exported symbol name containing *, ?, or [ requires wildcard matching
943 return ( strpbrk(symbol
, "*?[") != NULL
);
946 void Options::SetWithWildcards::insert(const char* symbol
)
948 if ( hasWildCards(symbol
) )
949 fWildCard
.push_back(symbol
);
951 fRegular
.insert(symbol
);
954 bool Options::SetWithWildcards::contains(const char* symbol
)
956 // first look at hash table on non-wildcard symbols
957 if ( fRegular
.find(symbol
) != fRegular
.end() )
959 // next walk list of wild card symbols looking for a match
960 for(std::vector
<const char*>::iterator it
= fWildCard
.begin(); it
!= fWildCard
.end(); ++it
) {
961 if ( wildCardMatch(*it
, symbol
) )
968 bool Options::SetWithWildcards::inCharRange(const char*& p
, unsigned char c
)
972 while ( *p
!= '\0' ) {
975 // found beginining [ and ending ]
976 unsigned char last
= '\0';
977 for ( const char* s
= b
; s
< e
; ++s
) {
979 unsigned char next
= *(++s
);
980 if ( (last
<= c
) && (c
<= next
) )
997 bool Options::SetWithWildcards::wildCardMatch(const char* pattern
, const char* symbol
)
999 const char* s
= symbol
;
1000 for (const char* p
= pattern
; *p
!= '\0'; ++p
) {
1005 for (const char* t
= s
; *t
!= '\0'; ++t
) {
1006 if ( wildCardMatch(&p
[1], t
) )
1016 if ( ! inCharRange(p
, *s
) )
1026 return (*s
== '\0');
1030 void Options::loadExportFile(const char* fileOfExports
, const char* option
, SetWithWildcards
& set
)
1032 // read in whole file
1033 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
1035 throwf("can't open %s file: %s", option
, fileOfExports
);
1036 struct stat stat_buf
;
1037 ::fstat(fd
, &stat_buf
);
1038 char* p
= (char*)malloc(stat_buf
.st_size
);
1040 throwf("can't process %s file: %s", option
, fileOfExports
);
1042 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1043 throwf("can't read %s file: %s", option
, fileOfExports
);
1047 // parse into symbols and add to hash_set
1048 char * const end
= &p
[stat_buf
.st_size
];
1049 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1050 char* symbolStart
= NULL
;
1051 for (char* s
= p
; s
< end
; ++s
) {
1057 else if ( !isspace(*s
) ) {
1063 if ( (*s
== '\n') || (*s
== '\r') ) {
1065 // removing any trailing spaces
1067 while ( isspace(*last
) ) {
1071 set
.insert(symbolStart
);
1077 if ( (*s
== '\n') || (*s
== '\r') )
1082 if ( state
== inSymbol
) {
1083 warning("missing line-end at end of file \"%s\"", fileOfExports
);
1084 int len
= end
-symbolStart
+1;
1085 char* temp
= new char[len
];
1086 strlcpy(temp
, symbolStart
, len
);
1088 // remove any trailing spaces
1089 char* last
= &temp
[len
-2];
1090 while ( isspace(*last
) ) {
1097 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
1100 void Options::parseAliasFile(const char* fileOfAliases
)
1102 // read in whole file
1103 int fd
= ::open(fileOfAliases
, O_RDONLY
, 0);
1105 throwf("can't open alias file: %s", fileOfAliases
);
1106 struct stat stat_buf
;
1107 ::fstat(fd
, &stat_buf
);
1108 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1110 throwf("can't process alias file: %s", fileOfAliases
);
1112 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1113 throwf("can't read alias file: %s", fileOfAliases
);
1114 p
[stat_buf
.st_size
] = '\n';
1117 // parse into symbols and add to fAliases
1118 ObjectFile::ReaderOptions::AliasPair pair
;
1119 char * const end
= &p
[stat_buf
.st_size
+1];
1120 enum { lineStart
, inRealName
, inBetween
, inAliasName
, inComment
} state
= lineStart
;
1122 for (char* s
= p
; s
< end
; ++s
) {
1128 else if ( !isspace(*s
) ) {
1135 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1139 else if ( isspace(*s
) ) {
1146 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1150 else if ( ! isspace(*s
) ) {
1151 state
= inAliasName
;
1158 // removing any trailing spaces
1160 while ( isspace(*last
) ) {
1164 fReaderOptions
.fAliases
.push_back(pair
);
1167 else if ( *s
== '\n' ) {
1169 // removing any trailing spaces
1171 while ( isspace(*last
) ) {
1175 fReaderOptions
.fAliases
.push_back(pair
);
1186 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
1191 void Options::setUndefinedTreatment(const char* treatment
)
1193 if ( treatment
== NULL
)
1194 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
1196 if ( strcmp(treatment
, "warning") == 0 )
1197 fUndefinedTreatment
= kUndefinedWarning
;
1198 else if ( strcmp(treatment
, "error") == 0 )
1199 fUndefinedTreatment
= kUndefinedError
;
1200 else if ( strcmp(treatment
, "suppress") == 0 )
1201 fUndefinedTreatment
= kUndefinedSuppress
;
1202 else if ( strcmp(treatment
, "dynamic_lookup") == 0 )
1203 fUndefinedTreatment
= kUndefinedDynamicLookup
;
1205 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1208 Options::Treatment
Options::parseTreatment(const char* treatment
)
1210 if ( treatment
== NULL
)
1213 if ( strcmp(treatment
, "warning") == 0 )
1215 else if ( strcmp(treatment
, "error") == 0 )
1217 else if ( strcmp(treatment
, "suppress") == 0 )
1223 void Options::setMacOSXVersionMin(const char* version
)
1225 if ( version
== NULL
)
1226 throw "-macosx_version_min argument missing";
1228 if ( (strncmp(version
, "10.", 3) == 0) && isdigit(version
[3]) ) {
1229 int num
= version
[3] - '0';
1233 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_1
;
1236 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_2
;
1239 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_3
;
1242 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_4
;
1245 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_5
;
1248 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_6
;
1251 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_6
;
1256 warning("unknown option to -macosx_version_min, not 10.x");
1260 void Options::setIPhoneVersionMin(const char* version
)
1262 if ( version
== NULL
)
1263 throw "-iphoneos_version_min argument missing";
1265 if ( strncmp(version
, "1.", 2) == 0 ) {
1266 warning("pre-2.0 iPhone OS version not supported");
1267 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_0
;
1269 else if ( strncmp(version
, "2.", 2) == 0 ) {
1270 int num
= version
[2] - '0';
1273 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_0
;
1276 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_1
;
1279 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_2
;
1282 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_2
;
1286 else if ( strncmp(version
, "3.", 2) == 0 ) {
1287 int num
= version
[2] - '0';
1290 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k3_0
;
1293 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k3_0
;
1298 warning("unknown option to -iphoneos_version_min, not 2.x or 3.x");
1302 bool Options::minOS(ObjectFile::ReaderOptions::MacVersionMin requiredMacMin
, ObjectFile::ReaderOptions::IPhoneVersionMin requirediPhoneOSMin
)
1304 if ( fReaderOptions
.fMacVersionMin
!= ObjectFile::ReaderOptions::kMinMacVersionUnset
) {
1305 return ( fReaderOptions
.fMacVersionMin
>= requiredMacMin
);
1308 return ( fReaderOptions
.fIPhoneVersionMin
>= requirediPhoneOSMin
);
1313 void Options::setWeakReferenceMismatchTreatment(const char* treatment
)
1315 if ( treatment
== NULL
)
1316 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1318 if ( strcmp(treatment
, "error") == 0 )
1319 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchError
;
1320 else if ( strcmp(treatment
, "weak") == 0 )
1321 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchWeak
;
1322 else if ( strcmp(treatment
, "non-weak") == 0 )
1323 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchNonWeak
;
1325 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1328 Options::CommonsMode
Options::parseCommonsTreatment(const char* mode
)
1331 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1333 if ( strcmp(mode
, "ignore_dylibs") == 0 )
1334 return kCommonsIgnoreDylibs
;
1335 else if ( strcmp(mode
, "use_dylibs") == 0 )
1336 return kCommonsOverriddenByDylibs
;
1337 else if ( strcmp(mode
, "error") == 0 )
1338 return kCommonsConflictsDylibsError
;
1340 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1343 void Options::addDylibOverride(const char* paths
)
1345 if ( paths
== NULL
)
1346 throw "-dylib_file must followed by two colon separated paths";
1347 const char* colon
= strchr(paths
, ':');
1348 if ( colon
== NULL
)
1349 throw "-dylib_file must followed by two colon separated paths";
1350 int len
= colon
-paths
;
1351 char* target
= new char[len
+2];
1352 strncpy(target
, paths
, len
);
1354 DylibOverride entry
;
1355 entry
.installName
= target
;
1356 entry
.useInstead
= &colon
[1];
1357 fDylibOverrides
.push_back(entry
);
1360 uint64_t Options::parseAddress(const char* addr
)
1363 uint64_t result
= strtoull(addr
, &endptr
, 16);
1367 uint32_t Options::parseProtection(const char* prot
)
1369 uint32_t result
= 0;
1370 for(const char* p
= prot
; *p
!= '\0'; ++p
) {
1371 switch(tolower(*p
)) {
1373 result
|= VM_PROT_READ
;
1376 result
|= VM_PROT_WRITE
;
1379 result
|= VM_PROT_EXECUTE
;
1384 throwf("unknown -segprot lettter in %s", prot
);
1393 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1396 uint32_t Options::parseVersionNumber(const char* versionString
)
1398 unsigned long x
= 0;
1399 unsigned long y
= 0;
1400 unsigned long z
= 0;
1402 x
= strtoul(versionString
, &end
, 10);
1403 if ( *end
== '.' ) {
1404 y
= strtoul(&end
[1], &end
, 10);
1405 if ( *end
== '.' ) {
1406 z
= strtoul(&end
[1], &end
, 10);
1409 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
1410 throwf("malformed version number: %s", versionString
);
1412 return (x
<< 16) | ( y
<< 8 ) | z
;
1415 static const char* cstringSymbolName(const char* orderFileString
)
1418 asprintf(&result
, "cstring=%s", orderFileString
);
1419 // convert escaped characters
1421 for(const char* s
=result
; *s
!= '\0'; ++s
, ++d
) {
1459 // hexadecimal value of char
1463 while ( isxdigit(*s
) ) {
1468 value
+= ((toupper(*s
)-'A') + 10);
1475 if ( isdigit(*s
) ) {
1476 // octal value of char
1478 while ( isdigit(*s
) ) {
1479 value
= (value
<< 3) + (*s
-'0');
1494 void Options::parseOrderFile(const char* path
, bool cstring
)
1496 // order files override auto-ordering
1497 fReaderOptions
.fAutoOrderInitializers
= false;
1499 // read in whole file
1500 int fd
= ::open(path
, O_RDONLY
, 0);
1502 throwf("can't open order file: %s", path
);
1503 struct stat stat_buf
;
1504 ::fstat(fd
, &stat_buf
);
1505 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1507 throwf("can't process order file: %s", path
);
1508 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1509 throwf("can't read order file: %s", path
);
1511 p
[stat_buf
.st_size
] = '\n';
1513 // parse into vector of pairs
1514 char * const end
= &p
[stat_buf
.st_size
+1];
1515 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1516 char* symbolStart
= NULL
;
1517 for (char* s
= p
; s
< end
; ++s
) {
1523 else if ( !isspace(*s
) || cstring
) {
1529 if ( (*s
== '\n') || (!cstring
&& (*s
== '#')) ) {
1530 bool wasComment
= (*s
== '#');
1532 // removing any trailing spaces
1534 while ( isspace(*last
) ) {
1538 if ( strncmp(symbolStart
, "ppc:", 4) == 0 ) {
1539 if ( fArchitecture
== CPU_TYPE_POWERPC
)
1540 symbolStart
= &symbolStart
[4];
1544 // if there is an architecture prefix, only use this symbol it if matches current arch
1545 else if ( strncmp(symbolStart
, "ppc64:", 6) == 0 ) {
1546 if ( fArchitecture
== CPU_TYPE_POWERPC64
)
1547 symbolStart
= &symbolStart
[6];
1551 else if ( strncmp(symbolStart
, "i386:", 5) == 0 ) {
1552 if ( fArchitecture
== CPU_TYPE_I386
)
1553 symbolStart
= &symbolStart
[5];
1557 else if ( strncmp(symbolStart
, "x86_64:", 7) == 0 ) {
1558 if ( fArchitecture
== CPU_TYPE_X86_64
)
1559 symbolStart
= &symbolStart
[7];
1563 else if ( strncmp(symbolStart
, "arm:", 4) == 0 ) {
1564 if ( fArchitecture
== CPU_TYPE_ARM
)
1565 symbolStart
= &symbolStart
[4];
1569 if ( symbolStart
!= NULL
) {
1570 char* objFileName
= NULL
;
1571 char* colon
= strstr(symbolStart
, ".o:");
1572 if ( colon
!= NULL
) {
1574 objFileName
= symbolStart
;
1575 symbolStart
= &colon
[3];
1577 // trim leading spaces
1578 while ( isspace(*symbolStart
) )
1580 Options::OrderedSymbol pair
;
1582 pair
.symbolName
= cstringSymbolName(symbolStart
);
1584 pair
.symbolName
= symbolStart
;
1585 pair
.objectFileName
= objFileName
;
1586 fOrderedSymbols
.push_back(pair
);
1601 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1604 void Options::parseSectionOrderFile(const char* segment
, const char* section
, const char* path
)
1606 if ( (strcmp(section
, "__cstring") == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1607 parseOrderFile(path
, true);
1609 else if ( (strncmp(section
, "__literal",9) == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1610 warning("sorting of __literal[4,8,16] sections not supported");
1613 // ignore section information and append all symbol names to global order file
1614 parseOrderFile(path
, false);
1618 void Options::addSection(const char* segment
, const char* section
, const char* path
)
1620 if ( strlen(segment
) > 16 )
1621 throw "-seccreate segment name max 16 chars";
1622 if ( strlen(section
) > 16 ) {
1623 char* tmp
= strdup(section
);
1625 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section
, tmp
);
1629 // read in whole file
1630 int fd
= ::open(path
, O_RDONLY
, 0);
1632 throwf("can't open -sectcreate file: %s", path
);
1633 struct stat stat_buf
;
1634 ::fstat(fd
, &stat_buf
);
1635 char* p
= (char*)malloc(stat_buf
.st_size
);
1637 throwf("can't process -sectcreate file: %s", path
);
1638 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1639 throwf("can't read -sectcreate file: %s", path
);
1642 // record section to create
1643 ExtraSection info
= { segment
, section
, path
, (uint8_t*)p
, stat_buf
.st_size
};
1644 fExtraSections
.push_back(info
);
1647 void Options::addSectionAlignment(const char* segment
, const char* section
, const char* alignmentStr
)
1649 if ( strlen(segment
) > 16 )
1650 throw "-sectalign segment name max 16 chars";
1651 if ( strlen(section
) > 16 )
1652 throw "-sectalign section name max 16 chars";
1654 // argument to -sectalign is a hexadecimal number
1656 unsigned long value
= strtoul(alignmentStr
, &endptr
, 16);
1657 if ( *endptr
!= '\0')
1658 throw "argument for -sectalign is not a hexadecimal number";
1659 if ( value
> 0x8000 )
1660 throw "argument for -sectalign must be less than or equal to 0x8000";
1662 warning("zero is not a valid -sectalign");
1666 // alignment is power of 2 (e.g. page alignment = 12)
1667 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
1668 if ( (unsigned long)(1 << alignment
) != value
) {
1669 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
1670 segment
, section
, 1 << alignment
);
1673 SectionAlignment info
= { segment
, section
, alignment
};
1674 fSectionAlignments
.push_back(info
);
1677 void Options::addLibrary(const FileInfo
& info
)
1679 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
1680 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
1681 if ( strcmp(info
.path
, fit
->path
) == 0 ) {
1682 // if dylib is specified again but weak, record that it should be weak
1683 if ( info
.options
.fWeakImport
)
1684 fit
->options
.fWeakImport
= true;
1689 fInputFiles
.push_back(info
);
1692 void Options::warnObsolete(const char* arg
)
1694 warning("option %s is obsolete and being ignored", arg
);
1701 // Process all command line arguments.
1703 // The only error checking done here is that each option is valid and if it has arguments
1704 // that they too are valid.
1706 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
1707 // whichever was last on the command line is used.
1709 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
1711 void Options::parse(int argc
, const char* argv
[])
1713 // pass one builds search list from -L and -F options
1714 this->buildSearchPaths(argc
, argv
);
1716 // reduce re-allocations
1717 fInputFiles
.reserve(32);
1719 // pass two parse all other options
1720 for(int i
=1; i
< argc
; ++i
) {
1721 const char* arg
= argv
[i
];
1723 if ( arg
[0] == '-' ) {
1725 // Since we don't care about the files passed, just the option names, we do this here.
1727 fprintf (stderr
, "[Logging ld64 options]\t%s\n", arg
);
1729 if ( (arg
[1] == 'L') || (arg
[1] == 'F') ) {
1730 // previously handled by buildSearchPaths()
1732 // The one gnu style option we have to keep compatibility
1733 // with gcc. Might as well have the single hyphen one as well.
1734 else if ( (strcmp(arg
, "--help") == 0)
1735 || (strcmp(arg
, "-help") == 0)) {
1736 fprintf (stdout
, "ld64: For information on command line options please use 'man ld'.\n");
1739 else if ( strcmp(arg
, "-arch") == 0 ) {
1740 parseArch(argv
[++i
]);
1742 else if ( strcmp(arg
, "-dynamic") == 0 ) {
1745 else if ( strcmp(arg
, "-static") == 0 ) {
1746 fReaderOptions
.fForStatic
= true;
1747 if ( fOutputKind
!= kObjectFile
) {
1748 fOutputKind
= kStaticExecutable
;
1751 else if ( strcmp(arg
, "-dylib") == 0 ) {
1752 fOutputKind
= kDynamicLibrary
;
1754 else if ( strcmp(arg
, "-bundle") == 0 ) {
1755 fOutputKind
= kDynamicBundle
;
1757 else if ( strcmp(arg
, "-dylinker") == 0 ) {
1758 fOutputKind
= kDyld
;
1760 else if ( strcmp(arg
, "-execute") == 0 ) {
1761 if ( fOutputKind
!= kStaticExecutable
)
1762 fOutputKind
= kDynamicExecutable
;
1764 else if ( strcmp(arg
, "-preload") == 0 ) {
1765 fOutputKind
= kPreload
;
1767 else if ( strcmp(arg
, "-r") == 0 ) {
1768 fOutputKind
= kObjectFile
;
1770 else if ( strcmp(arg
, "-kext") == 0 ) {
1771 fOutputKind
= kKextBundle
;
1773 else if ( strcmp(arg
, "-o") == 0 ) {
1774 fOutputFile
= argv
[++i
];
1776 else if ( (arg
[1] == 'l') && (strncmp(arg
,"-lazy_",6) !=0) ) {
1777 addLibrary(findLibrary(&arg
[2]));
1779 // This causes a dylib to be weakly bound at
1780 // link time. This corresponds to weak_import.
1781 else if ( strncmp(arg
, "-weak-l", 7) == 0 ) {
1782 FileInfo info
= findLibrary(&arg
[7]);
1783 info
.options
.fWeakImport
= true;
1786 else if ( strncmp(arg
, "-lazy-l", 7) == 0 ) {
1787 FileInfo info
= findLibrary(&arg
[7], true);
1788 info
.options
.fLazyLoad
= true;
1790 fUsingLazyDylibLinking
= true;
1792 // Avoid lazy binding.
1794 else if ( strcmp(arg
, "-bind_at_load") == 0 ) {
1797 else if ( strcmp(arg
, "-twolevel_namespace") == 0 ) {
1798 fNameSpace
= kTwoLevelNameSpace
;
1800 else if ( strcmp(arg
, "-flat_namespace") == 0 ) {
1801 fNameSpace
= kFlatNameSpace
;
1803 // Also sets a bit to ensure dyld causes everything
1804 // in the namespace to be flat.
1806 else if ( strcmp(arg
, "-force_flat_namespace") == 0 ) {
1807 fNameSpace
= kForceFlatNameSpace
;
1809 // Similar to --whole-archive.
1810 else if ( strcmp(arg
, "-all_load") == 0 ) {
1811 fReaderOptions
.fFullyLoadArchives
= true;
1813 else if ( strcmp(arg
, "-noall_load") == 0) {
1816 // Similar to -all_load
1817 else if ( strcmp(arg
, "-ObjC") == 0 ) {
1818 fReaderOptions
.fLoadAllObjcObjectsFromArchives
= true;
1820 // Similar to -all_load, but for the following archive only.
1821 else if ( strcmp(arg
, "-force_load") == 0 ) {
1822 FileInfo info
= findFile(argv
[++i
]);
1823 info
.options
.fForceLoad
= true;
1826 // Library versioning.
1827 else if ( (strcmp(arg
, "-dylib_compatibility_version") == 0)
1828 || (strcmp(arg
, "-compatibility_version") == 0)) {
1829 const char* vers
= argv
[++i
];
1831 throw "-dylib_compatibility_version missing <version>";
1832 fDylibCompatVersion
= parseVersionNumber(vers
);
1834 else if ( (strcmp(arg
, "-dylib_current_version") == 0)
1835 || (strcmp(arg
, "-current_version") == 0)) {
1836 const char* vers
= argv
[++i
];
1838 throw "-dylib_current_version missing <version>";
1839 fDylibCurrentVersion
= parseVersionNumber(vers
);
1841 else if ( strcmp(arg
, "-sectorder") == 0 ) {
1842 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
1843 throw "-sectorder missing <segment> <section> <file-path>";
1844 parseSectionOrderFile(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1847 else if ( strcmp(arg
, "-order_file") == 0 ) {
1848 parseOrderFile(argv
[++i
], false);
1850 else if ( strcmp(arg
, "-order_file_statistics") == 0 ) {
1851 fPrintOrderFileStatistics
= true;
1853 // ??? Deprecate segcreate.
1854 // -sectcreate puts whole files into a section in the output.
1855 else if ( (strcmp(arg
, "-sectcreate") == 0) || (strcmp(arg
, "-segcreate") == 0) ) {
1856 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
1857 throw "-sectcreate missing <segment> <section> <file-path>";
1858 addSection(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1861 // Since we have a full path in binary/library names we need to be able to override it.
1862 else if ( (strcmp(arg
, "-dylib_install_name") == 0)
1863 || (strcmp(arg
, "-dylinker_install_name") == 0)
1864 || (strcmp(arg
, "-install_name") == 0)) {
1865 fDylibInstallName
= argv
[++i
];
1866 if ( fDylibInstallName
== NULL
)
1867 throw "-install_name missing <path>";
1869 // Sets the base address of the output.
1870 else if ( (strcmp(arg
, "-seg1addr") == 0) || (strcmp(arg
, "-image_base") == 0) ) {
1871 const char* address
= argv
[++i
];
1872 if ( address
== NULL
)
1873 throwf("%s missing <address>", arg
);
1874 fBaseAddress
= parseAddress(address
);
1875 uint64_t temp
= ((fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
1876 if ( fBaseAddress
!= temp
) {
1877 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment
);
1878 fBaseAddress
= temp
;
1881 else if ( strcmp(arg
, "-e") == 0 ) {
1882 fEntryName
= argv
[++i
];
1884 // Same as -@ from the FSF linker.
1885 else if ( strcmp(arg
, "-filelist") == 0 ) {
1886 const char* path
= argv
[++i
];
1887 if ( (path
== NULL
) || (path
[0] == '-') )
1888 throw "-filelist missing <path>";
1891 else if ( strcmp(arg
, "-keep_private_externs") == 0 ) {
1892 fKeepPrivateExterns
= true;
1894 else if ( strcmp(arg
, "-final_output") == 0 ) {
1895 fFinalName
= argv
[++i
];
1897 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
1898 // just ensures that this happens for cross object file boundaries.
1899 else if ( (strcmp(arg
, "-interposable") == 0) || (strcmp(arg
, "-multi_module") == 0)) {
1900 switch ( fInterposeMode
) {
1901 case kInterposeNone
:
1902 case kInterposeAllExternal
:
1903 fInterposeMode
= kInterposeAllExternal
;
1905 case kInterposeSome
:
1906 // do nothing, -interposable_list overrides -interposable"
1910 else if ( strcmp(arg
, "-interposable_list") == 0 ) {
1911 fInterposeMode
= kInterposeSome
;
1912 loadExportFile(argv
[++i
], "-interposable_list", fInterposeList
);
1914 // Default for -interposable/-multi_module/-single_module.
1915 else if ( strcmp(arg
, "-single_module") == 0 ) {
1916 fInterposeMode
= kInterposeNone
;
1918 else if ( strcmp(arg
, "-exported_symbols_list") == 0 ) {
1919 if ( fExportMode
== kDontExportSome
)
1920 throw "can't use -exported_symbols_list and -unexported_symbols_list";
1921 fExportMode
= kExportSome
;
1922 loadExportFile(argv
[++i
], "-exported_symbols_list", fExportSymbols
);
1924 else if ( strcmp(arg
, "-unexported_symbols_list") == 0 ) {
1925 if ( fExportMode
== kExportSome
)
1926 throw "can't use -unexported_symbols_list and -exported_symbols_list";
1927 fExportMode
= kDontExportSome
;
1928 loadExportFile(argv
[++i
], "-unexported_symbols_list", fDontExportSymbols
);
1930 else if ( strcmp(arg
, "-exported_symbol") == 0 ) {
1931 if ( fExportMode
== kDontExportSome
)
1932 throw "can't use -exported_symbol and -unexported_symbols";
1933 fExportMode
= kExportSome
;
1934 fExportSymbols
.insert(argv
[++i
]);
1936 else if ( strcmp(arg
, "-unexported_symbol") == 0 ) {
1937 if ( fExportMode
== kExportSome
)
1938 throw "can't use -unexported_symbol and -exported_symbol";
1939 fExportMode
= kDontExportSome
;
1940 fDontExportSymbols
.insert(argv
[++i
]);
1942 else if ( strcmp(arg
, "-non_global_symbols_no_strip_list") == 0 ) {
1943 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveExclude
)
1944 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
1945 fLocalSymbolHandling
= kLocalSymbolsSelectiveInclude
;
1946 loadExportFile(argv
[++i
], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded
);
1948 else if ( strcmp(arg
, "-non_global_symbols_strip_list") == 0 ) {
1949 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveInclude
)
1950 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
1951 fLocalSymbolHandling
= kLocalSymbolsSelectiveExclude
;
1952 loadExportFile(argv
[++i
], "-non_global_symbols_strip_list", fLocalSymbolsExcluded
);
1955 else if ( strcmp(arg
, "-no_arch_warnings") == 0 ) {
1956 fIgnoreOtherArchFiles
= true;
1958 else if ( strcmp(arg
, "-force_cpusubtype_ALL") == 0 ) {
1959 fForceSubtypeAll
= true;
1961 // Similar to -weak-l but uses the absolute path name to the library.
1962 else if ( strcmp(arg
, "-weak_library") == 0 ) {
1963 FileInfo info
= findFile(argv
[++i
]);
1964 info
.options
.fWeakImport
= true;
1967 else if ( strcmp(arg
, "-lazy_library") == 0 ) {
1968 FileInfo info
= findFile(argv
[++i
]);
1969 info
.options
.fLazyLoad
= true;
1971 fUsingLazyDylibLinking
= true;
1973 else if ( strcmp(arg
, "-framework") == 0 ) {
1974 addLibrary(findFramework(argv
[++i
]));
1976 else if ( strcmp(arg
, "-weak_framework") == 0 ) {
1977 FileInfo info
= findFramework(argv
[++i
]);
1978 info
.options
.fWeakImport
= true;
1981 else if ( strcmp(arg
, "-lazy_framework") == 0 ) {
1982 FileInfo info
= findFramework(argv
[++i
]);
1983 info
.options
.fLazyLoad
= true;
1985 fUsingLazyDylibLinking
= true;
1987 else if ( strcmp(arg
, "-search_paths_first") == 0 ) {
1988 // previously handled by buildSearchPaths()
1990 else if ( strcmp(arg
, "-undefined") == 0 ) {
1991 setUndefinedTreatment(argv
[++i
]);
1993 // Debugging output flag.
1994 else if ( strcmp(arg
, "-arch_multiple") == 0 ) {
1995 fMessagesPrefixedWithArchitecture
= true;
1997 // Specify what to do with relocations in read only
1998 // sections like .text. Could be errors, warnings,
1999 // or suppressed. Currently we do nothing with the
2001 else if ( strcmp(arg
, "-read_only_relocs") == 0 ) {
2002 switch ( parseTreatment(argv
[++i
]) ) {
2005 throw "-read_only_relocs missing [ warning | error | suppress ]";
2007 fWarnTextRelocs
= true;
2008 fAllowTextRelocs
= true;
2011 fWarnTextRelocs
= false;
2012 fAllowTextRelocs
= true;
2015 fWarnTextRelocs
= false;
2016 fAllowTextRelocs
= false;
2020 else if ( strcmp(arg
, "-sect_diff_relocs") == 0 ) {
2024 // Warn, error or make strong a mismatch between weak
2025 // and non-weak references.
2026 else if ( strcmp(arg
, "-weak_reference_mismatches") == 0 ) {
2027 setWeakReferenceMismatchTreatment(argv
[++i
]);
2029 // For a deployment target of 10.3 and earlier ld64 will
2030 // prebind an executable with 0s in all addresses that
2031 // are prebound. This can then be fixed up by update_prebinding
2032 // later. Prebinding is less useful on 10.4 and greater.
2033 else if ( strcmp(arg
, "-prebind") == 0 ) {
2036 else if ( strcmp(arg
, "-noprebind") == 0 ) {
2040 else if ( strcmp(arg
, "-prebind_allow_overlap") == 0 ) {
2043 else if ( strcmp(arg
, "-prebind_all_twolevel_modules") == 0 ) {
2046 else if ( strcmp(arg
, "-noprebind_all_twolevel_modules") == 0 ) {
2049 else if ( strcmp(arg
, "-nofixprebinding") == 0 ) {
2052 // This should probably be deprecated when we respect -L and -F
2053 // when searching for libraries.
2054 else if ( strcmp(arg
, "-dylib_file") == 0 ) {
2055 addDylibOverride(argv
[++i
]);
2057 // What to expand @executable_path to if found in dependent dylibs
2058 else if ( strcmp(arg
, "-executable_path") == 0 ) {
2059 fExecutablePath
= argv
[++i
];
2060 if ( (fExecutablePath
== NULL
) || (fExecutablePath
[0] == '-') )
2061 throw "-executable_path missing <path>";
2062 // if a directory was passed, add / to end
2063 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2064 struct stat statBuffer
;
2065 if ( stat(fExecutablePath
, &statBuffer
) == 0 ) {
2066 if ( (statBuffer
.st_mode
& S_IFMT
) == S_IFDIR
) {
2067 char* pathWithSlash
= new char[strlen(fExecutablePath
)+2];
2068 strcpy(pathWithSlash
, fExecutablePath
);
2069 strcat(pathWithSlash
, "/");
2070 fExecutablePath
= pathWithSlash
;
2074 // Aligns all segments to the power of 2 boundary specified.
2075 else if ( strcmp(arg
, "-segalign") == 0 ) {
2076 const char* size
= argv
[++i
];
2078 throw "-segalign missing <size>";
2079 fSegmentAlignment
= parseAddress(size
);
2080 uint8_t alignment
= (uint8_t)__builtin_ctz(fSegmentAlignment
);
2081 uint32_t p2aligned
= (1 << alignment
);
2082 if ( p2aligned
!= fSegmentAlignment
) {
2083 warning("alignment for -segalign %s is not a power of two, using 0x%X", size
, p2aligned
);
2084 fSegmentAlignment
= p2aligned
;
2087 // Puts a specified segment at a particular address that must
2088 // be a multiple of the segment alignment.
2089 else if ( strcmp(arg
, "-segaddr") == 0 ) {
2091 seg
.name
= argv
[++i
];
2092 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2093 throw "-segaddr missing segName Adddress";
2094 seg
.address
= parseAddress(argv
[++i
]);
2095 uint64_t temp
= seg
.address
& (-4096); // page align
2096 if ( (seg
.address
!= temp
) )
2097 warning("-segaddr %s not page aligned, rounding down", seg
.name
);
2098 fCustomSegmentAddresses
.push_back(seg
);
2100 // ??? Deprecate when we deprecate split-seg.
2101 else if ( strcmp(arg
, "-segs_read_only_addr") == 0 ) {
2102 fBaseAddress
= parseAddress(argv
[++i
]);
2104 // ??? Deprecate when we deprecate split-seg.
2105 else if ( strcmp(arg
, "-segs_read_write_addr") == 0 ) {
2106 fBaseWritableAddress
= parseAddress(argv
[++i
]);
2109 // ??? Deprecate when we get rid of basing at build time.
2110 else if ( strcmp(arg
, "-seg_addr_table") == 0 ) {
2111 const char* name
= argv
[++i
];
2113 throw "-seg_addr_table missing argument";
2114 fSegAddrTablePath
= name
;
2116 else if ( strcmp(arg
, "-seg_addr_table_filename") == 0 ) {
2120 else if ( strcmp(arg
, "-segprot") == 0 ) {
2122 seg
.name
= argv
[++i
];
2123 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) || (argv
[i
+2] == NULL
) )
2124 throw "-segprot missing segName max-prot init-prot";
2125 seg
.max
= parseProtection(argv
[++i
]);
2126 seg
.init
= parseProtection(argv
[++i
]);
2127 fCustomSegmentProtections
.push_back(seg
);
2129 else if ( strcmp(arg
, "-pagezero_size") == 0 ) {
2130 const char* size
= argv
[++i
];
2132 throw "-pagezero_size missing <size>";
2133 fZeroPageSize
= parseAddress(size
);
2134 uint64_t temp
= fZeroPageSize
& (-4096); // page align
2135 if ( (fZeroPageSize
!= temp
) )
2136 warning("-pagezero_size not page aligned, rounding down");
2137 fZeroPageSize
= temp
;
2139 else if ( strcmp(arg
, "-stack_addr") == 0 ) {
2140 const char* address
= argv
[++i
];
2141 if ( address
== NULL
)
2142 throw "-stack_addr missing <address>";
2143 fStackAddr
= parseAddress(address
);
2145 else if ( strcmp(arg
, "-stack_size") == 0 ) {
2146 const char* size
= argv
[++i
];
2148 throw "-stack_size missing <address>";
2149 fStackSize
= parseAddress(size
);
2150 uint64_t temp
= fStackSize
& (-4096); // page align
2151 if ( (fStackSize
!= temp
) )
2152 warning("-stack_size not page aligned, rounding down");
2154 else if ( strcmp(arg
, "-allow_stack_execute") == 0 ) {
2155 fExecutableStack
= true;
2157 else if ( strcmp(arg
, "-sectalign") == 0 ) {
2158 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2159 throw "-sectalign missing <segment> <section> <file-path>";
2160 addSectionAlignment(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2163 else if ( strcmp(arg
, "-sectorder_detail") == 0 ) {
2166 else if ( strcmp(arg
, "-sectobjectsymbols") == 0 ) {
2170 else if ( strcmp(arg
, "-bundle_loader") == 0 ) {
2171 fBundleLoader
= argv
[++i
];
2172 if ( (fBundleLoader
== NULL
) || (fBundleLoader
[0] == '-') )
2173 throw "-bundle_loader missing <path>";
2174 FileInfo info
= findFile(fBundleLoader
);
2175 info
.options
.fBundleLoader
= true;
2176 fInputFiles
.push_back(info
);
2178 else if ( strcmp(arg
, "-private_bundle") == 0 ) {
2181 else if ( strcmp(arg
, "-twolevel_namespace_hints") == 0 ) {
2184 // Use this flag to set default behavior for deployement targets.
2185 else if ( strcmp(arg
, "-macosx_version_min") == 0 ) {
2186 setMacOSXVersionMin(argv
[++i
]);
2188 else if ( strcmp(arg
, "-iphoneos_version_min") == 0 ) {
2189 setIPhoneVersionMin(argv
[++i
]);
2191 else if ( strcmp(arg
, "-multiply_defined") == 0 ) {
2192 //warnObsolete(arg);
2195 else if ( strcmp(arg
, "-multiply_defined_unused") == 0 ) {
2199 else if ( strcmp(arg
, "-nomultidefs") == 0 ) {
2202 // Display each file in which the argument symbol appears and whether
2203 // the file defines or references it. This option takes an argument
2204 // as -y<symbol> note that there is no space.
2205 else if ( strncmp(arg
, "-y", 2) == 0 ) {
2208 // Same output as -y, but output <arg> number of undefined symbols only.
2209 else if ( strcmp(arg
, "-Y") == 0 ) {
2210 //warnObsolete(arg);
2213 // This option affects all objects linked into the final result.
2214 else if ( strcmp(arg
, "-m") == 0 ) {
2217 else if ( (strcmp(arg
, "-why_load") == 0) || (strcmp(arg
, "-whyload") == 0) ) {
2218 fReaderOptions
.fWhyLoad
= true;
2220 else if ( strcmp(arg
, "-why_live") == 0 ) {
2221 const char* name
= argv
[++i
];
2223 throw "-why_live missing symbol name argument";
2224 fWhyLive
.insert(name
);
2226 else if ( strcmp(arg
, "-u") == 0 ) {
2227 const char* name
= argv
[++i
];
2229 throw "-u missing argument";
2230 fInitialUndefines
.push_back(name
);
2232 else if ( strcmp(arg
, "-U") == 0 ) {
2233 const char* name
= argv
[++i
];
2235 throw "-U missing argument";
2236 fAllowedUndefined
.insert(name
);
2238 else if ( strcmp(arg
, "-s") == 0 ) {
2240 fLocalSymbolHandling
= kLocalSymbolsNone
;
2241 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
2243 else if ( strcmp(arg
, "-x") == 0 ) {
2244 fLocalSymbolHandling
= kLocalSymbolsNone
;
2246 else if ( strcmp(arg
, "-S") == 0 ) {
2247 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
2249 else if ( strcmp(arg
, "-X") == 0 ) {
2252 else if ( strcmp(arg
, "-Si") == 0 ) {
2254 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoFull
;
2256 else if ( strcmp(arg
, "-b") == 0 ) {
2259 else if ( strcmp(arg
, "-Sn") == 0 ) {
2261 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoFull
;
2263 else if ( strcmp(arg
, "-Sp") == 0 ) {
2266 else if ( strcmp(arg
, "-dead_strip") == 0 ) {
2267 fDeadStrip
= kDeadStripOnPlusUnusedInits
;
2269 else if ( strcmp(arg
, "-no_dead_strip_inits_and_terms") == 0 ) {
2270 fDeadStrip
= kDeadStripOn
;
2272 else if ( strcmp(arg
, "-w") == 0 ) {
2273 // previously handled by buildSearchPaths()
2275 else if ( strcmp(arg
, "-arch_errors_fatal") == 0 ) {
2276 fErrorOnOtherArchFiles
= true;
2278 else if ( strcmp(arg
, "-M") == 0 ) {
2281 else if ( strcmp(arg
, "-headerpad") == 0 ) {
2282 const char* size
= argv
[++i
];
2284 throw "-headerpad missing argument";
2285 fMinimumHeaderPad
= parseAddress(size
);
2287 else if ( strcmp(arg
, "-headerpad_max_install_names") == 0 ) {
2288 fMaxMinimumHeaderPad
= true;
2290 else if ( strcmp(arg
, "-t") == 0 ) {
2291 fReaderOptions
.fLogAllFiles
= true;
2293 else if ( strcmp(arg
, "-whatsloaded") == 0 ) {
2294 fReaderOptions
.fLogObjectFiles
= true;
2296 else if ( strcmp(arg
, "-A") == 0 ) {
2300 else if ( strcmp(arg
, "-umbrella") == 0 ) {
2301 const char* name
= argv
[++i
];
2303 throw "-umbrella missing argument";
2304 fUmbrellaName
= name
;
2306 else if ( strcmp(arg
, "-allowable_client") == 0 ) {
2307 const char* name
= argv
[++i
];
2310 throw "-allowable_client missing argument";
2312 fAllowableClients
.push_back(name
);
2314 else if ( strcmp(arg
, "-client_name") == 0 ) {
2315 const char* name
= argv
[++i
];
2318 throw "-client_name missing argument";
2322 else if ( strcmp(arg
, "-sub_umbrella") == 0 ) {
2323 const char* name
= argv
[++i
];
2325 throw "-sub_umbrella missing argument";
2326 fSubUmbellas
.push_back(name
);
2328 else if ( strcmp(arg
, "-sub_library") == 0 ) {
2329 const char* name
= argv
[++i
];
2331 throw "-sub_library missing argument";
2332 fSubLibraries
.push_back(name
);
2334 else if ( strcmp(arg
, "-init") == 0 ) {
2335 const char* name
= argv
[++i
];
2337 throw "-init missing argument";
2338 fInitFunctionName
= name
;
2340 else if ( strcmp(arg
, "-dot") == 0 ) {
2341 const char* name
= argv
[++i
];
2343 throw "-dot missing argument";
2344 fDotOutputFile
= name
;
2346 else if ( strcmp(arg
, "-warn_commons") == 0 ) {
2347 fWarnCommons
= true;
2349 else if ( strcmp(arg
, "-commons") == 0 ) {
2350 fCommonsMode
= parseCommonsTreatment(argv
[++i
]);
2352 else if ( strcmp(arg
, "-keep_relocs") == 0 ) {
2353 fKeepRelocations
= true;
2355 else if ( strcmp(arg
, "-warn_stabs") == 0 ) {
2358 else if ( strcmp(arg
, "-pause") == 0 ) {
2361 else if ( strcmp(arg
, "-print_statistics") == 0 ) {
2364 else if ( strcmp(arg
, "-d") == 0 ) {
2365 fReaderOptions
.fMakeTentativeDefinitionsReal
= true;
2367 else if ( strcmp(arg
, "-v") == 0 ) {
2368 // previously handled by buildSearchPaths()
2370 else if ( strcmp(arg
, "-Z") == 0 ) {
2371 // previously handled by buildSearchPaths()
2373 else if ( strcmp(arg
, "-syslibroot") == 0 ) {
2375 // previously handled by buildSearchPaths()
2377 else if ( strcmp(arg
, "-no_uuid") == 0 ) {
2378 fUUIDMode
= kUUIDNone
;
2380 else if ( strcmp(arg
, "-random_uuid") == 0 ) {
2381 fUUIDMode
= kUUIDRandom
;
2383 else if ( strcmp(arg
, "-dtrace") == 0 ) {
2384 const char* name
= argv
[++i
];
2386 throw "-dtrace missing argument";
2387 fDtraceScriptName
= name
;
2389 else if ( strcmp(arg
, "-root_safe") == 0 ) {
2390 fReaderOptions
.fRootSafe
= true;
2392 else if ( strcmp(arg
, "-setuid_safe") == 0 ) {
2393 fReaderOptions
.fSetuidSafe
= true;
2395 else if ( strcmp(arg
, "-alias") == 0 ) {
2396 ObjectFile::ReaderOptions::AliasPair pair
;
2397 pair
.realName
= argv
[++i
];
2398 if ( pair
.realName
== NULL
)
2399 throw "missing argument to -alias";
2400 pair
.alias
= argv
[++i
];
2401 if ( pair
.alias
== NULL
)
2402 throw "missing argument to -alias";
2403 fReaderOptions
.fAliases
.push_back(pair
);
2405 else if ( strcmp(arg
, "-alias_list") == 0 ) {
2406 parseAliasFile(argv
[++i
]);
2408 // put this last so that it does not interfer with other options starting with 'i'
2409 else if ( strncmp(arg
, "-i", 2) == 0 ) {
2410 const char* colon
= strchr(arg
, ':');
2411 if ( colon
== NULL
)
2412 throwf("unknown option: %s", arg
);
2413 ObjectFile::ReaderOptions::AliasPair pair
;
2414 char* temp
= new char[colon
-arg
];
2415 strlcpy(temp
, &arg
[2], colon
-arg
-1);
2416 pair
.realName
= &colon
[1];
2418 fReaderOptions
.fAliases
.push_back(pair
);
2420 else if ( strcmp(arg
, "-save-temps") == 0 ) {
2421 fSaveTempFiles
= true;
2423 else if ( strcmp(arg
, "-rpath") == 0 ) {
2424 const char* path
= argv
[++i
];
2426 throw "missing argument to -rpath";
2427 fRPaths
.push_back(path
);
2429 else if ( strcmp(arg
, "-read_only_stubs") == 0 ) {
2430 fReadOnlyx86Stubs
= true;
2432 else if ( strcmp(arg
, "-slow_stubs") == 0 ) {
2435 else if ( strcmp(arg
, "-map") == 0 ) {
2436 fMapPath
= argv
[++i
];
2437 if ( fMapPath
== NULL
)
2438 throw "missing argument to -map";
2440 else if ( strcmp(arg
, "-pie") == 0 ) {
2441 fPositionIndependentExecutable
= true;
2443 else if ( strncmp(arg
, "-reexport-l", 11) == 0 ) {
2444 FileInfo info
= findLibrary(&arg
[11], true);
2445 info
.options
.fReExport
= true;
2448 else if ( strcmp(arg
, "-reexport_library") == 0 ) {
2449 FileInfo info
= findFile(argv
[++i
]);
2450 info
.options
.fReExport
= true;
2453 else if ( strcmp(arg
, "-reexport_framework") == 0 ) {
2454 FileInfo info
= findFramework(argv
[++i
]);
2455 info
.options
.fReExport
= true;
2458 else if ( strcmp(arg
, "-dead_strip_dylibs") == 0 ) {
2459 fDeadStripDylibs
= true;
2461 else if ( strcmp(arg
, "-no_implicit_dylibs") == 0 ) {
2462 fReaderOptions
.fImplicitlyLinkPublicDylibs
= false;
2464 else if ( strcmp(arg
, "-new_linker") == 0 ) {
2467 else if ( strcmp(arg
, "-no_encryption") == 0 ) {
2468 fEncryptable
= false;
2470 else if ( strcmp(arg
, "-no_compact_unwind") == 0 ) {
2471 fReaderOptions
.fAddCompactUnwindEncoding
= false;
2473 else if ( strcmp(arg
, "-mllvm") == 0 ) {
2474 const char* opts
= argv
[++i
];
2476 throw "missing argument to -mllvm";
2477 fLLVMOptions
.push_back(opts
);
2479 else if ( strcmp(arg
, "-no_order_inits") == 0 ) {
2480 fReaderOptions
.fAutoOrderInitializers
= false;
2482 else if ( strcmp(arg
, "-no_order_data") == 0 ) {
2485 else if ( strcmp(arg
, "-seg_page_size") == 0 ) {
2487 seg
.name
= argv
[++i
];
2488 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2489 throw "-seg_page_size missing segName Adddress";
2490 seg
.size
= parseAddress(argv
[++i
]);
2491 uint64_t temp
= seg
.size
& (-4096); // page align
2492 if ( (seg
.size
!= temp
) )
2493 warning("-seg_page_size %s not 4K aligned, rounding down", seg
.name
);
2494 fCustomSegmentSizes
.push_back(seg
);
2496 else if ( strcmp(arg
, "-mark_dead_strippable_dylib") == 0 ) {
2497 fMarkDeadStrippableDylib
= true;
2499 else if ( strcmp(arg
, "-exported_symbols_order") == 0 ) {
2500 loadSymbolOrderFile(argv
[++i
], fExportSymbolsOrder
);
2502 else if ( strcmp(arg
, "-no_compact_linkedit") == 0 ) {
2503 fMakeCompressedDyldInfo
= false;
2505 else if ( strcmp(arg
, "-no_eh_labels") == 0 ) {
2506 fReaderOptions
.fNoEHLabels
= true;
2508 else if ( strcmp(arg
, "-warn_compact_unwind") == 0 ) {
2509 fReaderOptions
.fWarnCompactUnwind
= true;
2511 else if ( strcmp(arg
, "-allow_sub_type_mismatches") == 0 ) {
2512 fAllowCpuSubtypeMismatches
= true;
2514 else if ( strcmp(arg
, "-no_zero_fill_sections") == 0 ) {
2515 fReaderOptions
.fOptimizeZeroFill
= false;
2518 throwf("unknown option: %s", arg
);
2522 FileInfo info
= findFile(arg
);
2523 if ( strcmp(&info
.path
[strlen(info
.path
)-2], ".a") == 0 )
2526 fInputFiles
.push_back(info
);
2530 // if a -lazy option was used, implicitly link in lazydylib1.o
2531 if ( fUsingLazyDylibLinking
) {
2532 addLibrary(findLibrary("lazydylib1.o"));
2539 // -syslibroot <path> is used for SDK support.
2540 // The rule is that all search paths (both explicit and default) are
2541 // checked to see if they exist in the SDK. If so, that path is
2542 // replaced with the sdk prefixed path. If not, that search path
2543 // is used as is. If multiple -syslibroot options are specified
2544 // their directory structures are logically overlayed and files
2545 // from sdks specified earlier on the command line used before later ones.
2547 void Options::buildSearchPaths(int argc
, const char* argv
[])
2549 bool addStandardLibraryDirectories
= true;
2550 std::vector
<const char*> libraryPaths
;
2551 std::vector
<const char*> frameworkPaths
;
2552 libraryPaths
.reserve(10);
2553 frameworkPaths
.reserve(10);
2554 // scan through argv looking for -L, -F, -Z, and -syslibroot options
2555 for(int i
=0; i
< argc
; ++i
) {
2556 if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'L') )
2557 libraryPaths
.push_back(&argv
[i
][2]);
2558 else if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'F') )
2559 frameworkPaths
.push_back(&argv
[i
][2]);
2560 else if ( strcmp(argv
[i
], "-Z") == 0 )
2561 addStandardLibraryDirectories
= false;
2562 else if ( strcmp(argv
[i
], "-v") == 0 ) {
2564 extern const char ldVersionString
[];
2565 fprintf(stderr
, "%s", ldVersionString
);
2566 // if only -v specified, exit cleanly
2569 printLTOVersion(*this);
2574 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
2575 const char* path
= argv
[++i
];
2577 throw "-syslibroot missing argument";
2578 fSDKPaths
.push_back(path
);
2580 else if ( strcmp(argv
[i
], "-search_paths_first") == 0 ) {
2581 // ??? Deprecate when we get -Bstatic/-Bdynamic.
2582 fLibrarySearchMode
= kSearchDylibAndArchiveInEachDir
;
2584 else if ( strcmp(argv
[i
], "-w") == 0 ) {
2585 sEmitWarnings
= false;
2588 int standardLibraryPathsStartIndex
= libraryPaths
.size();
2589 int standardFrameworkPathsStartIndex
= frameworkPaths
.size();
2590 if ( addStandardLibraryDirectories
) {
2591 libraryPaths
.push_back("/usr/lib");
2592 libraryPaths
.push_back("/usr/local/lib");
2594 frameworkPaths
.push_back("/Library/Frameworks/");
2595 frameworkPaths
.push_back("/System/Library/Frameworks/");
2596 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
2599 // <rdar://problem/5829579> Support for configure based hacks
2600 // if last -syslibroot is /, then ignore all syslibroots
2601 if ( fSDKPaths
.size() > 0 ) {
2602 if ( strcmp(fSDKPaths
.back(), "/") == 0 ) {
2607 // now merge sdk and library paths to make real search paths
2608 fLibrarySearchPaths
.reserve(libraryPaths
.size()*(fSDKPaths
.size()+1));
2610 for (std::vector
<const char*>::iterator it
= libraryPaths
.begin(); it
!= libraryPaths
.end(); ++it
, ++libIndex
) {
2611 const char* libDir
= *it
;
2612 bool sdkOverride
= false;
2613 if ( libDir
[0] == '/' ) {
2614 char betterLibDir
[PATH_MAX
];
2615 if ( strstr(libDir
, "/..") != NULL
) {
2616 if ( realpath(libDir
, betterLibDir
) != NULL
)
2617 libDir
= strdup(betterLibDir
);
2619 const int libDirLen
= strlen(libDir
);
2620 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
2621 const char* sdkDir
= *sdkit
;
2622 const int sdkDirLen
= strlen(sdkDir
);
2623 char newPath
[libDirLen
+ sdkDirLen
+4];
2624 strcpy(newPath
, sdkDir
);
2625 if ( newPath
[sdkDirLen
-1] == '/' )
2626 newPath
[sdkDirLen
-1] = '\0';
2627 strcat(newPath
, libDir
);
2628 struct stat statBuffer
;
2629 if ( stat(newPath
, &statBuffer
) == 0 ) {
2630 fLibrarySearchPaths
.push_back(strdup(newPath
));
2635 if ( !sdkOverride
) {
2636 if ( (libIndex
>= standardLibraryPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
2637 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2638 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2641 fLibrarySearchPaths
.push_back(libDir
);
2646 // now merge sdk and framework paths to make real search paths
2647 fFrameworkSearchPaths
.reserve(frameworkPaths
.size()*(fSDKPaths
.size()+1));
2649 for (std::vector
<const char*>::iterator it
= frameworkPaths
.begin(); it
!= frameworkPaths
.end(); ++it
, ++frameIndex
) {
2650 const char* frameworkDir
= *it
;
2651 bool sdkOverride
= false;
2652 if ( frameworkDir
[0] == '/' ) {
2653 char betterFrameworkDir
[PATH_MAX
];
2654 if ( strstr(frameworkDir
, "/..") != NULL
) {
2655 if ( realpath(frameworkDir
, betterFrameworkDir
) != NULL
)
2656 frameworkDir
= strdup(betterFrameworkDir
);
2658 const int frameworkDirLen
= strlen(frameworkDir
);
2659 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
2660 const char* sdkDir
= *sdkit
;
2661 const int sdkDirLen
= strlen(sdkDir
);
2662 char newPath
[frameworkDirLen
+ sdkDirLen
+4];
2663 strcpy(newPath
, sdkDir
);
2664 if ( newPath
[sdkDirLen
-1] == '/' )
2665 newPath
[sdkDirLen
-1] = '\0';
2666 strcat(newPath
, frameworkDir
);
2667 struct stat statBuffer
;
2668 if ( stat(newPath
, &statBuffer
) == 0 ) {
2669 fFrameworkSearchPaths
.push_back(strdup(newPath
));
2674 if ( !sdkOverride
) {
2675 if ( (frameIndex
>= standardFrameworkPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
2676 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2677 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2680 fFrameworkSearchPaths
.push_back(frameworkDir
);
2686 fprintf(stderr
,"Library search paths:\n");
2687 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
2688 it
!= fLibrarySearchPaths
.end();
2690 fprintf(stderr
,"\t%s\n", *it
);
2691 fprintf(stderr
,"Framework search paths:\n");
2692 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
2693 it
!= fFrameworkSearchPaths
.end();
2695 fprintf(stderr
,"\t%s\n", *it
);
2699 // this is run before the command line is parsed
2700 void Options::parsePreCommandLineEnvironmentSettings()
2702 if ((getenv("LD_TRACE_ARCHIVES") != NULL
)
2703 || (getenv("RC_TRACE_ARCHIVES") != NULL
))
2704 fReaderOptions
.fTraceArchives
= true;
2706 if ((getenv("LD_TRACE_DYLIBS") != NULL
)
2707 || (getenv("RC_TRACE_DYLIBS") != NULL
)) {
2708 fReaderOptions
.fTraceDylibs
= true;
2709 fReaderOptions
.fTraceIndirectDylibs
= true;
2712 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL
) {
2713 fTraceDylibSearching
= true;
2716 if (getenv("LD_PRINT_OPTIONS") != NULL
)
2717 fPrintOptions
= true;
2719 if (fReaderOptions
.fTraceDylibs
|| fReaderOptions
.fTraceArchives
)
2720 fReaderOptions
.fTraceOutputFile
= getenv("LD_TRACE_FILE");
2722 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL
)
2723 fPrintOrderFileStatistics
= true;
2725 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL
)
2728 if (getenv("LD_NO_ENCRYPT") != NULL
)
2729 fEncryptable
= false;
2731 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL
)
2732 fAllowCpuSubtypeMismatches
= true;
2734 // for now disable compressed linkedit functionality
2735 if ( getenv("LD_NO_COMPACT_LINKEDIT") != NULL
) {
2736 fMakeCompressedDyldInfo
= false;
2737 fMakeClassicDyldInfo
= true;
2740 sWarningsSideFilePath
= getenv("LD_WARN_FILE");
2744 // this is run after the command line is parsed
2745 void Options::parsePostCommandLineEnvironmentSettings()
2747 // when building a dynamic main executable, default any use of @executable_path to output path
2748 if ( fExecutablePath
== NULL
&& (fOutputKind
== kDynamicExecutable
) ) {
2749 fExecutablePath
= fOutputFile
;
2752 // allow build system to set default seg_addr_table
2753 if ( fSegAddrTablePath
== NULL
)
2754 fSegAddrTablePath
= getenv("LD_SEG_ADDR_TABLE");
2756 // allow build system to turn on prebinding
2758 fPrebind
= ( getenv("LD_PREBIND") != NULL
);
2761 // allow build system to force on dead-code-stripping
2762 if ( fDeadStrip
== kDeadStripOff
) {
2763 if ( getenv("LD_DEAD_STRIP") != NULL
) {
2764 switch (fOutputKind
) {
2765 case Options::kDynamicLibrary
:
2766 case Options::kDynamicExecutable
:
2767 case Options::kDynamicBundle
:
2768 fDeadStrip
= kDeadStripOn
;
2770 case Options::kPreload
:
2771 case Options::kObjectFile
:
2772 case Options::kDyld
:
2773 case Options::kStaticExecutable
:
2774 case Options::kKextBundle
:
2780 // allow build system to force on -warn_commons
2781 if ( getenv("LD_WARN_COMMONS") != NULL
)
2782 fWarnCommons
= true;
2786 void Options::reconfigureDefaults()
2788 // sync reader options
2789 switch ( fOutputKind
) {
2790 case Options::kObjectFile
:
2791 fReaderOptions
.fForFinalLinkedImage
= false;
2793 case Options::kDyld
:
2794 fReaderOptions
.fForDyld
= true;
2795 fReaderOptions
.fForFinalLinkedImage
= true;
2796 fReaderOptions
.fNoEHLabels
= true;
2798 case Options::kDynamicLibrary
:
2799 case Options::kDynamicBundle
:
2800 case Options::kKextBundle
:
2801 fReaderOptions
.fForFinalLinkedImage
= true;
2802 fReaderOptions
.fNoEHLabels
= true;
2804 case Options::kDynamicExecutable
:
2805 case Options::kStaticExecutable
:
2806 case Options::kPreload
:
2807 fReaderOptions
.fLinkingMainExecutable
= true;
2808 fReaderOptions
.fForFinalLinkedImage
= true;
2809 fReaderOptions
.fNoEHLabels
= true;
2813 // set default min OS version
2814 if ( (fReaderOptions
.fMacVersionMin
== ObjectFile::ReaderOptions::kMinMacVersionUnset
)
2815 && (fReaderOptions
.fIPhoneVersionMin
== ObjectFile::ReaderOptions::kMinIPhoneVersionUnset
) ) {
2816 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
2817 const char* macVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
2818 const char* iPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
2819 if ( macVers
!= NULL
)
2820 setMacOSXVersionMin(macVers
);
2821 else if ( iPhoneVers
!= NULL
)
2822 setIPhoneVersionMin(iPhoneVers
);
2824 // if still nothing, set default based on architecture
2825 switch ( fArchitecture
) {
2827 case CPU_TYPE_X86_64
:
2828 case CPU_TYPE_POWERPC
:
2829 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_6
; // FIX FIX, this really should be a check of the OS version the linker is running o
2832 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_0
;
2839 // adjust min based on architecture
2840 switch ( fArchitecture
) {
2842 if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_4
) {
2843 //warning("-macosx_version_min should be 10.4 or later for i386");
2844 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_4
;
2847 case CPU_TYPE_POWERPC64
:
2848 if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_4
) {
2849 //warning("-macosx_version_min should be 10.4 or later for ppc64");
2850 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_4
;
2853 case CPU_TYPE_X86_64
:
2854 if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_4
) {
2855 //warning("-macosx_version_min should be 10.4 or later for x86_64");
2856 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_4
;
2861 // adjust kext type based on architecture
2862 if ( fOutputKind
== kKextBundle
) {
2863 switch ( fArchitecture
) {
2864 case CPU_TYPE_X86_64
:
2865 // x86_64 uses new MH_KEXT_BUNDLE type
2866 fMakeClassicDyldInfo
= true;
2867 fMakeCompressedDyldInfo
= false;
2868 fAllowTextRelocs
= true;
2869 fUndefinedTreatment
= kUndefinedDynamicLookup
;
2871 case CPU_TYPE_POWERPC
:
2875 fOutputKind
= kObjectFile
;
2880 // disable implicit dylibs when targeting 10.3
2881 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
2882 if ( !minOS(ObjectFile::ReaderOptions::k10_4
, ObjectFile::ReaderOptions::k2_0
) )
2883 fReaderOptions
.fImplicitlyLinkPublicDylibs
= false;
2886 // allow build system to force linker to ignore -prebind
2887 if ( getenv("LD_FORCE_NO_PREBIND") != NULL
)
2890 // allow build system to force linker to ignore -seg_addr_table
2891 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL
)
2892 fSegAddrTablePath
= NULL
;
2894 // check for base address specified externally
2895 if ( (fSegAddrTablePath
!= NULL
) && (fOutputKind
== Options::kDynamicLibrary
) ) {
2896 parseSegAddrTable(fSegAddrTablePath
, this->installPath());
2897 // HACK to support seg_addr_table entries that are physical paths instead of install paths
2898 if ( fBaseAddress
== 0 ) {
2899 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
2900 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.4.dylib");
2901 if ( fBaseAddress
== 0 )
2902 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.9.dylib");
2905 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
2906 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libz.1.2.3.dylib");
2908 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
2909 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libutil1.0.dylib");
2913 // split segs only allowed for dylibs
2915 // split seg only supported for ppc, i386, and arm.
2916 switch ( fArchitecture
) {
2917 case CPU_TYPE_POWERPC
:
2919 if ( fOutputKind
!= Options::kDynamicLibrary
)
2921 // make sure read and write segments are proper distance apart
2922 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x10000000) )
2923 fBaseWritableAddress
= fBaseAddress
+ 0x10000000;
2926 if ( fOutputKind
!= Options::kDynamicLibrary
) {
2930 // make sure read and write segments are proper distance apart
2931 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x08000000) )
2932 fBaseWritableAddress
= fBaseAddress
+ 0x08000000;
2938 fBaseWritableAddress
= 0;
2942 // <rdar://problem/6138961> -r implies no prebinding for all architectures
2943 if ( fOutputKind
== Options::kObjectFile
)
2946 // disable prebinding depending on arch and min OS version
2948 switch ( fArchitecture
) {
2949 case CPU_TYPE_POWERPC
:
2951 if ( fReaderOptions
.fMacVersionMin
== ObjectFile::ReaderOptions::k10_4
) {
2952 // in 10.4 only split seg dylibs are prebound
2953 if ( (fOutputKind
!= Options::kDynamicLibrary
) || ! fSplitSegs
)
2956 else if ( fReaderOptions
.fMacVersionMin
>= ObjectFile::ReaderOptions::k10_5
) {
2957 // in 10.5 nothing is prebound
2961 // in 10.3 and earlier only dylibs and main executables could be prebound
2962 switch ( fOutputKind
) {
2963 case Options::kDynamicExecutable
:
2964 case Options::kDynamicLibrary
:
2965 // only main executables and dylibs can be prebound
2967 case Options::kStaticExecutable
:
2968 case Options::kDynamicBundle
:
2969 case Options::kObjectFile
:
2970 case Options::kDyld
:
2971 case Options::kPreload
:
2972 case Options::kKextBundle
:
2973 // disable prebinding for everything else
2979 case CPU_TYPE_POWERPC64
:
2980 case CPU_TYPE_X86_64
:
2984 switch ( fOutputKind
) {
2985 case Options::kDynamicExecutable
:
2986 case Options::kDynamicLibrary
:
2987 // only main executables and dylibs can be prebound
2989 case Options::kStaticExecutable
:
2990 case Options::kDynamicBundle
:
2991 case Options::kObjectFile
:
2992 case Options::kDyld
:
2993 case Options::kPreload
:
2994 case Options::kKextBundle
:
2995 // disable prebinding for everything else
3003 // only prebound images can be split-seg
3004 if ( fSplitSegs
&& !fPrebind
)
3007 // determine if info for shared region should be added
3008 if ( fOutputKind
== Options::kDynamicLibrary
) {
3009 if ( minOS(ObjectFile::ReaderOptions::k10_5
, ObjectFile::ReaderOptions::k3_0
) )
3011 if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
3012 || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
3013 fSharedRegionEligible
= true;
3016 // figure out if module table is needed for compatibility with old ld/dyld
3017 if ( fOutputKind
== Options::kDynamicLibrary
) {
3018 switch ( fArchitecture
) {
3019 case CPU_TYPE_POWERPC
: // 10.3 and earlier dyld requires a module table
3020 case CPU_TYPE_I386
: // ld_classic for 10.4.x requires a module table
3021 if ( fReaderOptions
.fMacVersionMin
<= ObjectFile::ReaderOptions::k10_5
)
3022 fNeedsModuleTable
= true;
3026 fNeedsModuleTable
= true; // redo_prebinding requires a module table
3031 // <rdar://problem/5366363> -r -x implies -S
3032 if ( (fOutputKind
== Options::kObjectFile
) && (fLocalSymbolHandling
== kLocalSymbolsNone
) )
3033 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
3035 // choose how to process unwind info
3036 switch ( fArchitecture
) {
3038 case CPU_TYPE_X86_64
:
3039 switch ( fOutputKind
) {
3040 case Options::kObjectFile
:
3041 case Options::kStaticExecutable
:
3042 case Options::kPreload
:
3043 case Options::kKextBundle
:
3044 fReaderOptions
.fAddCompactUnwindEncoding
= false;
3046 case Options::kDyld
:
3047 case Options::kDynamicLibrary
:
3048 case Options::kDynamicBundle
:
3049 case Options::kDynamicExecutable
:
3050 //if ( fReaderOptions.fAddCompactUnwindEncoding && (fReaderOptions.fVersionMin >= ObjectFile::ReaderOptions::k10_6) )
3051 // fReaderOptions.fRemoveDwarfUnwindIfCompactExists = true;
3055 case CPU_TYPE_POWERPC
:
3056 case CPU_TYPE_POWERPC64
:
3058 fReaderOptions
.fAddCompactUnwindEncoding
= false;
3059 fReaderOptions
.fRemoveDwarfUnwindIfCompactExists
= false;
3062 // if -arch is missing, assume we don't want compact unwind info
3063 fReaderOptions
.fAddCompactUnwindEncoding
= false;
3067 // only ARM main executables can be encrypted
3068 if ( fOutputKind
!= Options::kDynamicExecutable
)
3069 fEncryptable
= false;
3070 if ( fArchitecture
!= CPU_TYPE_ARM
)
3071 fEncryptable
= false;
3073 // don't move inits in dyld because dyld wants certain
3074 // entries point at stable locations at the start of __text
3075 if ( fOutputKind
== Options::kDyld
)
3076 fReaderOptions
.fAutoOrderInitializers
= false;
3079 // disable __data ordering for some output kinds
3080 switch ( fOutputKind
) {
3081 case Options::kObjectFile
:
3082 case Options::kDyld
:
3083 case Options::kStaticExecutable
:
3084 case Options::kPreload
:
3085 case Options::kKextBundle
:
3088 case Options::kDynamicExecutable
:
3089 case Options::kDynamicLibrary
:
3090 case Options::kDynamicBundle
:
3094 // only use compressed LINKEDIT for x86_64 and i386
3095 if ( fMakeCompressedDyldInfo
) {
3096 switch (fArchitecture
) {
3098 case CPU_TYPE_X86_64
:
3099 if ( fReaderOptions
.fMacVersionMin
>= ObjectFile::ReaderOptions::k10_6
)
3100 fMakeClassicDyldInfo
= false;
3101 else if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_5
)
3102 fMakeCompressedDyldInfo
= false;
3104 case CPU_TYPE_POWERPC
:
3106 case CPU_TYPE_POWERPC64
:
3108 fMakeCompressedDyldInfo
= false;
3112 // only use compressed LINKEDIT for final linked images
3113 if ( fMakeCompressedDyldInfo
) {
3114 switch ( fOutputKind
) {
3115 case Options::kDynamicExecutable
:
3116 case Options::kDynamicLibrary
:
3117 case Options::kDynamicBundle
:
3119 case Options::kPreload
:
3120 case Options::kStaticExecutable
:
3121 case Options::kObjectFile
:
3122 case Options::kDyld
:
3123 case Options::kKextBundle
:
3124 fMakeCompressedDyldInfo
= false;
3128 fReaderOptions
.fMakeCompressedDyldInfo
= fMakeCompressedDyldInfo
;
3130 // only ARM enforces that cpu-sub-types must match
3131 if ( fArchitecture
!= CPU_TYPE_ARM
)
3132 fAllowCpuSubtypeMismatches
= true;
3134 // only final linked images can not optimize zero fill sections
3135 if ( fOutputKind
== Options::kObjectFile
)
3136 fReaderOptions
.fOptimizeZeroFill
= true;
3140 void Options::checkIllegalOptionCombinations()
3142 // check -undefined setting
3143 switch ( fUndefinedTreatment
) {
3144 case kUndefinedError
:
3145 case kUndefinedDynamicLookup
:
3148 case kUndefinedWarning
:
3149 case kUndefinedSuppress
:
3150 // requires flat namespace
3151 if ( fNameSpace
== kTwoLevelNameSpace
)
3152 throw "can't use -undefined warning or suppress with -twolevel_namespace";
3156 // unify -sub_umbrella with dylibs
3157 for (std::vector
<const char*>::iterator it
= fSubUmbellas
.begin(); it
!= fSubUmbellas
.end(); it
++) {
3158 const char* subUmbrella
= *it
;
3160 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
3161 Options::FileInfo
& info
= *fit
;
3162 const char* lastSlash
= strrchr(info
.path
, '/');
3163 if ( lastSlash
== NULL
)
3164 lastSlash
= info
.path
- 1;
3165 if ( strcmp(&lastSlash
[1], subUmbrella
) == 0 ) {
3166 info
.options
.fReExport
= true;
3172 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella
);
3175 // unify -sub_library with dylibs
3176 for (std::vector
<const char*>::iterator it
= fSubLibraries
.begin(); it
!= fSubLibraries
.end(); it
++) {
3177 const char* subLibrary
= *it
;
3179 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
3180 Options::FileInfo
& info
= *fit
;
3181 const char* lastSlash
= strrchr(info
.path
, '/');
3182 if ( lastSlash
== NULL
)
3183 lastSlash
= info
.path
- 1;
3184 const char* dot
= strchr(&lastSlash
[1], '.');
3186 dot
= &lastSlash
[strlen(lastSlash
)];
3187 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
3188 info
.options
.fReExport
= true;
3194 warning("-sub_library %s does not match a supplied dylib", subLibrary
);
3197 // sync reader options
3198 if ( fNameSpace
!= kTwoLevelNameSpace
)
3199 fReaderOptions
.fFlatNamespace
= true;
3201 // check -stack_addr
3202 if ( fStackAddr
!= 0 ) {
3203 switch (fArchitecture
) {
3205 case CPU_TYPE_POWERPC
:
3207 if ( fStackAddr
> 0xFFFFFFFF )
3208 throw "-stack_addr must be < 4G for 32-bit processes";
3210 case CPU_TYPE_POWERPC64
:
3211 case CPU_TYPE_X86_64
:
3214 if ( (fStackAddr
& -4096) != fStackAddr
)
3215 throw "-stack_addr must be multiples of 4K";
3216 if ( fStackSize
== 0 )
3217 throw "-stack_addr must be used with -stack_size";
3220 // check -stack_size
3221 if ( fStackSize
!= 0 ) {
3222 switch (fArchitecture
) {
3224 case CPU_TYPE_POWERPC
:
3225 if ( fStackSize
> 0xFFFFFFFF )
3226 throw "-stack_size must be < 4G for 32-bit processes";
3227 if ( fStackAddr
== 0 ) {
3228 fStackAddr
= 0xC0000000;
3230 if ( (fStackAddr
> 0xB0000000) && ((fStackAddr
-fStackSize
) < 0xB0000000) )
3231 warning("custom stack placement overlaps and will disable shared region");
3234 if ( fStackSize
> 0xFFFFFFFF )
3235 throw "-stack_size must be < 4G for 32-bit processes";
3236 if ( fStackAddr
== 0 )
3237 fStackAddr
= 0x30000000;
3238 if ( fStackAddr
> 0x40000000)
3239 throw "-stack_addr must be < 1G for arm";
3240 case CPU_TYPE_POWERPC64
:
3241 case CPU_TYPE_X86_64
:
3242 if ( fStackAddr
== 0 ) {
3243 fStackAddr
= 0x00007FFF5C000000LL
;
3247 if ( (fStackSize
& -4096) != fStackSize
)
3248 throw "-stack_size must be multiples of 4K";
3249 switch ( fOutputKind
) {
3250 case Options::kDynamicExecutable
:
3251 case Options::kStaticExecutable
:
3252 // custom stack size only legal when building main executable
3254 case Options::kDynamicLibrary
:
3255 case Options::kDynamicBundle
:
3256 case Options::kObjectFile
:
3257 case Options::kDyld
:
3258 case Options::kPreload
:
3259 case Options::kKextBundle
:
3260 throw "-stack_size option can only be used when linking a main executable";
3264 // check that -allow_stack_execute is only used with main executables
3265 if ( fExecutableStack
) {
3266 switch ( fOutputKind
) {
3267 case Options::kDynamicExecutable
:
3268 case Options::kStaticExecutable
:
3269 // -allow_stack_execute size only legal when building main executable
3271 case Options::kDynamicLibrary
:
3272 case Options::kDynamicBundle
:
3273 case Options::kObjectFile
:
3274 case Options::kDyld
:
3275 case Options::kPreload
:
3276 case Options::kKextBundle
:
3277 throw "-allow_stack_execute option can only be used when linking a main executable";
3281 // check -client_name is only used when making a bundle or main executable
3282 if ( fClientName
!= NULL
) {
3283 switch ( fOutputKind
) {
3284 case Options::kDynamicExecutable
:
3285 case Options::kDynamicBundle
:
3287 case Options::kStaticExecutable
:
3288 case Options::kDynamicLibrary
:
3289 case Options::kObjectFile
:
3290 case Options::kDyld
:
3291 case Options::kPreload
:
3292 case Options::kKextBundle
:
3293 throw "-client_name can only be used with -bundle";
3297 // check -init is only used when building a dylib
3298 if ( (fInitFunctionName
!= NULL
) && (fOutputKind
!= Options::kDynamicLibrary
) )
3299 throw "-init can only be used with -dynamiclib";
3301 // check -bundle_loader only used with -bundle
3302 if ( (fBundleLoader
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
3303 throw "-bundle_loader can only be used with -bundle";
3305 // check -dtrace not used with -r
3306 if ( (fDtraceScriptName
!= NULL
) && (fOutputKind
== Options::kObjectFile
) )
3307 throw "-dtrace can only be used when creating final linked images";
3309 // check -d can only be used with -r
3310 if ( fReaderOptions
.fMakeTentativeDefinitionsReal
&& (fOutputKind
!= Options::kObjectFile
) )
3311 throw "-d can only be used with -r";
3313 // check that -root_safe is not used with -r
3314 if ( fReaderOptions
.fRootSafe
&& (fOutputKind
== Options::kObjectFile
) )
3315 throw "-root_safe cannot be used with -r";
3317 // check that -setuid_safe is not used with -r
3318 if ( fReaderOptions
.fSetuidSafe
&& (fOutputKind
== Options::kObjectFile
) )
3319 throw "-setuid_safe cannot be used with -r";
3321 // make sure all required exported symbols exist
3322 std::vector
<const char*> impliedExports
;
3323 for (NameSet::iterator it
=fExportSymbols
.regularBegin(); it
!= fExportSymbols
.regularEnd(); it
++) {
3324 const char* name
= *it
;
3325 // never export .eh symbols
3326 const int len
= strlen(name
);
3327 if ( (strcmp(&name
[len
-3], ".eh") == 0) || (strncmp(name
, ".objc_category_name_", 20) == 0) )
3328 warning("ignoring %s in export list", name
);
3330 fInitialUndefines
.push_back(name
);
3331 if ( strncmp(name
, ".objc_class_name_", 17) == 0 ) {
3332 // rdar://problem/4718189 map ObjC class names to new runtime names
3333 switch (fArchitecture
) {
3334 case CPU_TYPE_POWERPC64
:
3335 case CPU_TYPE_X86_64
:
3338 asprintf(&temp
, "_OBJC_CLASS_$_%s", &name
[17]);
3339 impliedExports
.push_back(temp
);
3340 asprintf(&temp
, "_OBJC_METACLASS_$_%s", &name
[17]);
3341 impliedExports
.push_back(temp
);
3346 for (std::vector
<const char*>::iterator it
=impliedExports
.begin(); it
!= impliedExports
.end(); it
++) {
3347 const char* name
= *it
;
3348 fExportSymbols
.insert(name
);
3349 fInitialUndefines
.push_back(name
);
3352 // make sure that -init symbol exist
3353 if ( fInitFunctionName
!= NULL
)
3354 fInitialUndefines
.push_back(fInitFunctionName
);
3356 // check custom segments
3357 if ( fCustomSegmentAddresses
.size() != 0 ) {
3358 // verify no segment is in zero page
3359 if ( fZeroPageSize
!= ULLONG_MAX
) {
3360 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
3361 if ( (it
->address
>= 0) && (it
->address
< fZeroPageSize
) )
3362 throwf("-segaddr %s 0x%X conflicts with -pagezero_size", it
->name
, it
->address
);
3365 // verify no duplicates
3366 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
3367 for (std::vector
<SegmentStart
>::iterator it2
= fCustomSegmentAddresses
.begin(); it2
!= fCustomSegmentAddresses
.end(); ++it2
) {
3368 if ( (it
->address
== it2
->address
) && (it
!= it2
) )
3369 throwf("duplicate -segaddr addresses for %s and %s", it
->name
, it2
->name
);
3371 // a custom segment address of zero will disable the use of a zero page
3372 if ( it
->address
== 0 )
3377 if ( fZeroPageSize
== ULLONG_MAX
) {
3378 // zero page size not specified on command line, set default
3379 switch (fArchitecture
) {
3381 case CPU_TYPE_POWERPC
:
3383 // first 4KB for 32-bit architectures
3384 fZeroPageSize
= 0x1000;
3386 case CPU_TYPE_POWERPC64
:
3387 // first 4GB for ppc64 on 10.5
3388 if ( fReaderOptions
.fMacVersionMin
>= ObjectFile::ReaderOptions::k10_5
)
3389 fZeroPageSize
= 0x100000000ULL
;
3391 fZeroPageSize
= 0x1000; // 10.4 dyld may not be able to handle >4GB zero page
3393 case CPU_TYPE_X86_64
:
3394 // first 4GB for x86_64 on all OS's
3395 fZeroPageSize
= 0x100000000ULL
;
3398 // if -arch not used, default to 4K zero-page
3399 fZeroPageSize
= 0x1000;
3403 switch ( fOutputKind
) {
3404 case Options::kDynamicExecutable
:
3405 case Options::kStaticExecutable
:
3406 // -pagezero_size size only legal when building main executable
3408 case Options::kDynamicLibrary
:
3409 case Options::kDynamicBundle
:
3410 case Options::kObjectFile
:
3411 case Options::kDyld
:
3412 case Options::kPreload
:
3413 case Options::kKextBundle
:
3414 if ( fZeroPageSize
!= 0 )
3415 throw "-pagezero_size option can only be used when linking a main executable";
3419 // -dead_strip and -r are incompatible
3420 if ( (fDeadStrip
!= kDeadStripOff
) && (fOutputKind
== Options::kObjectFile
) )
3421 throw "-r and -dead_strip cannot be used together";
3423 // can't use -rpath unless targeting 10.5 or later
3424 if ( fRPaths
.size() > 0 ) {
3425 if ( !minOS(ObjectFile::ReaderOptions::k10_5
, ObjectFile::ReaderOptions::k2_0
) )
3426 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
3427 switch ( fOutputKind
) {
3428 case Options::kDynamicExecutable
:
3429 case Options::kDynamicLibrary
:
3430 case Options::kDynamicBundle
:
3432 case Options::kStaticExecutable
:
3433 case Options::kObjectFile
:
3434 case Options::kDyld
:
3435 case Options::kPreload
:
3436 case Options::kKextBundle
:
3437 throw "-rpath can only be used when creating a dynamic final linked image";
3441 // check -pie is only used when building a dynamic main executable for 10.5
3442 if ( fPositionIndependentExecutable
) {
3443 switch ( fOutputKind
) {
3444 case Options::kDynamicExecutable
:
3445 case Options::kPreload
:
3447 case Options::kDynamicLibrary
:
3448 case Options::kDynamicBundle
:
3449 warning("-pie being ignored. It is only used when linking a main executable");
3451 case Options::kStaticExecutable
:
3452 case Options::kObjectFile
:
3453 case Options::kDyld
:
3454 case Options::kKextBundle
:
3455 throw "-pie can only be used when linking a main executable";
3457 if ( !minOS(ObjectFile::ReaderOptions::k10_5
, ObjectFile::ReaderOptions::k2_0
) )
3458 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
3461 // check -read_only_relocs is not used with x86_64
3462 if ( fAllowTextRelocs
) {
3463 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
!= kKextBundle
) ) {
3464 warning("-read_only_relocs cannot be used with x86_64");
3465 fAllowTextRelocs
= false;
3469 // check -mark_auto_dead_strip is only used with dylibs
3470 if ( fMarkDeadStrippableDylib
) {
3471 if ( fOutputKind
!= Options::kDynamicLibrary
) {
3472 warning("-mark_auto_dead_strip can only be used when creating a dylib");
3473 fMarkDeadStrippableDylib
= false;
3477 // -force_cpusubtype_ALL is not supported for ARM
3478 if ( fForceSubtypeAll
) {
3479 if ( fArchitecture
== CPU_TYPE_ARM
) {
3480 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
3486 void Options::checkForClassic(int argc
, const char* argv
[])
3489 bool archFound
= false;
3490 bool staticFound
= false;
3491 bool dtraceFound
= false;
3492 bool kextFound
= false;
3493 bool rFound
= false;
3494 bool creatingMachKernel
= false;
3495 bool newLinker
= false;
3497 // build command line buffer in case ld crashes
3498 for(int i
=1; i
< argc
; ++i
) {
3499 strlcat(crashreporterBuffer
, argv
[i
], 1000);
3500 strlcat(crashreporterBuffer
, " ", 1000);
3503 for(int i
=0; i
< argc
; ++i
) {
3504 const char* arg
= argv
[i
];
3505 if ( arg
[0] == '-' ) {
3506 if ( strcmp(arg
, "-arch") == 0 ) {
3507 parseArch(argv
[++i
]);
3510 else if ( strcmp(arg
, "-static") == 0 ) {
3513 else if ( strcmp(arg
, "-kext") == 0 ) {
3516 else if ( strcmp(arg
, "-dtrace") == 0 ) {
3519 else if ( strcmp(arg
, "-r") == 0 ) {
3522 else if ( strcmp(arg
, "-new_linker") == 0 ) {
3525 else if ( strcmp(arg
, "-classic_linker") == 0 ) {
3526 // ld_classic does not understand this option, so remove it
3527 for(int j
=i
; j
< argc
; ++j
)
3528 argv
[j
] = argv
[j
+1];
3529 this->gotoClassicLinker(argc
-1, argv
);
3531 else if ( strcmp(arg
, "-o") == 0 ) {
3532 const char* outfile
= argv
[++i
];
3533 if ( (outfile
!= NULL
) && (strstr(outfile
, "/mach_kernel") != NULL
) )
3534 creatingMachKernel
= true;
3539 // -dtrace only supported by new linker
3544 switch ( fArchitecture
) {
3545 case CPU_TYPE_POWERPC
:
3548 // if ( staticFound && (rFound || !creatingMachKernel) ) {
3549 if ( (staticFound
|| kextFound
) && !newLinker
) {
3550 // this environment variable will disable use of ld_classic for -static links
3551 if ( getenv("LD_NO_CLASSIC_LINKER_STATIC") == NULL
) {
3552 // ld_classic does not support -iphoneos_version_min, so change
3553 for(int j
=0; j
< argc
; ++j
) {
3554 if ( strcmp(argv
[j
], "-iphoneos_version_min") == 0) {
3555 argv
[j
] = "-macosx_version_min";
3561 // ld classic does not understand -kext (change to -static -r)
3563 for(int j
=0; j
< argc
; ++j
) {
3564 if ( strcmp(argv
[j
], "-kext") == 0)
3566 else if ( strcmp(argv
[j
], "-dynamic") == 0)
3567 argv
[j
] = "-static";
3570 this->gotoClassicLinker(argc
, argv
);
3577 // work around for VSPTool
3579 this->gotoClassicLinker(argc
, argv
);
3584 void Options::gotoClassicLinker(int argc
, const char* argv
[])
3586 argv
[0] = "ld_classic";
3587 char path
[PATH_MAX
];
3588 uint32_t bufSize
= PATH_MAX
;
3589 if ( _NSGetExecutablePath(path
, &bufSize
) != -1 ) {
3590 char* lastSlash
= strrchr(path
, '/');
3591 if ( lastSlash
!= NULL
) {
3592 strcpy(lastSlash
+1, "ld_classic");
3593 execvp(path
, (char**)argv
);
3596 // in case of error in above, try searching for ld_classic via PATH
3597 execvp(argv
[0], (char**)argv
);
3598 fprintf(stderr
, "can't exec ld_classic\n");