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),
103 fDisablePositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
104 fDeadStripDylibs(false), fAllowTextRelocs(false), fWarnTextRelocs(false),
105 fUsingLazyDylibLinking(false), fEncryptable(true),
106 fOrderData(true), fMarkDeadStrippableDylib(false),
107 fMakeClassicDyldInfo(true), fMakeCompressedDyldInfo(true), fAllowCpuSubtypeMismatches(false),
108 fUseSimplifiedDylibReExports(false), fObjCABIVersion2POverride(false), fSaveTempFiles(false)
110 this->checkForClassic(argc
, argv
);
111 this->parsePreCommandLineEnvironmentSettings();
112 this->parse(argc
, argv
);
113 this->parsePostCommandLineEnvironmentSettings();
114 this->reconfigureDefaults();
115 this->checkIllegalOptionCombinations();
122 const ObjectFile::ReaderOptions
& Options::readerOptions()
124 return fReaderOptions
;
128 const char* Options::getOutputFilePath()
133 std::vector
<Options::FileInfo
>& Options::getInputFiles()
138 Options::OutputKind
Options::outputKind()
143 bool Options::bindAtLoad()
148 bool Options::prebind()
153 bool Options::fullyLoadArchives()
155 return fReaderOptions
.fFullyLoadArchives
;
158 Options::NameSpace
Options::nameSpace()
163 const char* Options::installPath()
165 if ( fDylibInstallName
!= NULL
)
166 return fDylibInstallName
;
167 else if ( fFinalName
!= NULL
)
173 uint32_t Options::currentVersion()
175 return fDylibCurrentVersion
;
178 uint32_t Options::compatibilityVersion()
180 return fDylibCompatVersion
;
183 const char* Options::entryName()
188 uint64_t Options::baseAddress()
193 bool Options::keepPrivateExterns()
195 return fKeepPrivateExterns
;
198 bool Options::interposable(const char* name
)
200 switch ( fInterposeMode
) {
203 case kInterposeAllExternal
:
206 return fInterposeList
.contains(name
);
208 throw "internal error";
211 bool Options::needsModuleTable()
213 return fNeedsModuleTable
;
216 bool Options::ignoreOtherArchInputFiles()
218 return fIgnoreOtherArchFiles
;
221 bool Options::forceCpuSubtypeAll()
223 return fForceSubtypeAll
;
226 bool Options::traceDylibs()
228 return fReaderOptions
.fTraceDylibs
;
231 bool Options::traceArchives()
233 return fReaderOptions
.fTraceArchives
;
236 Options::UndefinedTreatment
Options::undefinedTreatment()
238 return fUndefinedTreatment
;
241 Options::WeakReferenceMismatchTreatment
Options::weakReferenceMismatchTreatment()
243 return fWeakReferenceMismatchTreatment
;
246 const char* Options::umbrellaName()
248 return fUmbrellaName
;
251 std::vector
<const char*>& Options::allowableClients()
253 return fAllowableClients
;
256 const char* Options::clientName()
261 uint64_t Options::zeroPageSize()
263 return fZeroPageSize
;
266 bool Options::hasCustomStack()
268 return (fStackSize
!= 0);
271 uint64_t Options::customStackSize()
276 uint64_t Options::customStackAddr()
281 bool Options::hasExecutableStack()
283 return fExecutableStack
;
286 std::vector
<const char*>& Options::initialUndefines()
288 return fInitialUndefines
;
291 bool Options::printWhyLive(const char* symbolName
)
293 return ( fWhyLive
.find(symbolName
) != fWhyLive
.end() );
297 const char* Options::initFunctionName()
299 return fInitFunctionName
;
302 const char* Options::dotOutputFile()
304 return fDotOutputFile
;
307 bool Options::hasExportRestrictList()
309 return (fExportMode
!= kExportDefault
);
312 bool Options::hasExportMaskList()
314 return (fExportMode
== kExportSome
);
318 bool Options::hasWildCardExportRestrictList()
320 // has -exported_symbols_list which contains some wildcards
321 return ((fExportMode
== kExportSome
) && fExportSymbols
.hasWildCards());
325 bool Options::allGlobalsAreDeadStripRoots()
327 // -exported_symbols_list means globals are not exported by default
328 if ( fExportMode
== kExportSome
)
331 switch ( fOutputKind
) {
332 case Options::kDynamicExecutable
:
333 case Options::kStaticExecutable
:
334 case Options::kPreload
:
335 // by default unused globals in a main executable are stripped
337 case Options::kDynamicLibrary
:
338 case Options::kDynamicBundle
:
339 case Options::kObjectFile
:
341 case Options::kKextBundle
:
347 uint32_t Options::minimumHeaderPad()
349 return fMinimumHeaderPad
;
352 std::vector
<Options::ExtraSection
>& Options::extraSections()
354 return fExtraSections
;
357 std::vector
<Options::SectionAlignment
>& Options::sectionAlignments()
359 return fSectionAlignments
;
362 Options::CommonsMode
Options::commonsMode()
367 bool Options::warnCommons()
372 bool Options::keepRelocations()
374 return fKeepRelocations
;
377 bool Options::warnStabs()
382 const char* Options::executablePath()
384 return fExecutablePath
;
387 Options::DeadStripMode
Options::deadStrip()
392 bool Options::hasExportedSymbolOrder()
394 return (fExportSymbolsOrder
.size() > 0);
397 bool Options::exportedSymbolOrder(const char* sym
, unsigned int* order
)
399 NameToOrder::iterator pos
= fExportSymbolsOrder
.find(sym
);
400 if ( pos
!= fExportSymbolsOrder
.end() ) {
401 *order
= pos
->second
;
410 void Options::loadSymbolOrderFile(const char* fileOfExports
, NameToOrder
& orderMapping
)
412 // read in whole file
413 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
415 throwf("can't open -exported_symbols_order file: %s", fileOfExports
);
416 struct stat stat_buf
;
417 ::fstat(fd
, &stat_buf
);
418 char* p
= (char*)malloc(stat_buf
.st_size
);
420 throwf("can't process -exported_symbols_order file: %s", fileOfExports
);
422 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
423 throwf("can't read -exported_symbols_order file: %s", fileOfExports
);
427 // parse into symbols and add to hash_set
428 unsigned int count
= 0;
429 char * const end
= &p
[stat_buf
.st_size
];
430 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
431 char* symbolStart
= NULL
;
432 for (char* s
= p
; s
< end
; ++s
) {
438 else if ( !isspace(*s
) ) {
444 if ( (*s
== '\n') || (*s
== '\r') ) {
446 // removing any trailing spaces
448 while ( isspace(*last
) ) {
452 orderMapping
[symbolStart
] = ++count
;
458 if ( (*s
== '\n') || (*s
== '\r') )
463 if ( state
== inSymbol
) {
464 warning("missing line-end at end of file \"%s\"", fileOfExports
);
465 int len
= end
-symbolStart
+1;
466 char* temp
= new char[len
];
467 strlcpy(temp
, symbolStart
, len
);
469 // remove any trailing spaces
470 char* last
= &temp
[len
-2];
471 while ( isspace(*last
) ) {
475 orderMapping
[temp
] = ++count
;
478 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
482 bool Options::shouldExport(const char* symbolName
)
484 switch (fExportMode
) {
486 return fExportSymbols
.contains(symbolName
);
487 case kDontExportSome
:
488 return ! fDontExportSymbols
.contains(symbolName
);
492 throw "internal error";
495 bool Options::keepLocalSymbol(const char* symbolName
)
497 switch (fLocalSymbolHandling
) {
498 case kLocalSymbolsAll
:
500 case kLocalSymbolsNone
:
502 case kLocalSymbolsSelectiveInclude
:
503 return fLocalSymbolsIncluded
.contains(symbolName
);
504 case kLocalSymbolsSelectiveExclude
:
505 return ! fLocalSymbolsExcluded
.contains(symbolName
);
507 throw "internal error";
510 void Options::parseArch(const char* architecture
)
512 if ( architecture
== NULL
)
513 throw "-arch must be followed by an architecture string";
514 if ( strcmp(architecture
, "ppc") == 0 ) {
515 fArchitecture
= CPU_TYPE_POWERPC
;
516 fSubArchitecture
= CPU_SUBTYPE_POWERPC_ALL
;
518 else if ( strcmp(architecture
, "ppc64") == 0 ) {
519 fArchitecture
= CPU_TYPE_POWERPC64
;
520 fSubArchitecture
= CPU_SUBTYPE_POWERPC_ALL
;
522 else if ( strcmp(architecture
, "i386") == 0 ) {
523 fArchitecture
= CPU_TYPE_I386
;
524 fSubArchitecture
= CPU_SUBTYPE_I386_ALL
;
526 else if ( strcmp(architecture
, "x86_64") == 0 ) {
527 fArchitecture
= CPU_TYPE_X86_64
;
528 fSubArchitecture
= CPU_SUBTYPE_X86_64_ALL
;
530 else if ( strcmp(architecture
, "arm") == 0 ) {
531 fArchitecture
= CPU_TYPE_ARM
;
532 fSubArchitecture
= CPU_SUBTYPE_ARM_ALL
;
534 // compatibility support for cpu-sub-types
535 else if ( strcmp(architecture
, "ppc750") == 0 ) {
536 fArchitecture
= CPU_TYPE_POWERPC
;
537 fSubArchitecture
= CPU_SUBTYPE_POWERPC_750
;
538 fHasPreferredSubType
= true;
540 else if ( strcmp(architecture
, "ppc7400") == 0 ) {
541 fArchitecture
= CPU_TYPE_POWERPC
;
542 fSubArchitecture
= CPU_SUBTYPE_POWERPC_7400
;
543 fHasPreferredSubType
= true;
545 else if ( strcmp(architecture
, "ppc7450") == 0 ) {
546 fArchitecture
= CPU_TYPE_POWERPC
;
547 fSubArchitecture
= CPU_SUBTYPE_POWERPC_7450
;
548 fHasPreferredSubType
= true;
550 else if ( strcmp(architecture
, "ppc970") == 0 ) {
551 fArchitecture
= CPU_TYPE_POWERPC
;
552 fSubArchitecture
= CPU_SUBTYPE_POWERPC_970
;
553 fHasPreferredSubType
= true;
555 else if ( strcmp(architecture
, "armv6") == 0 ) {
556 fArchitecture
= CPU_TYPE_ARM
;
557 fSubArchitecture
= CPU_SUBTYPE_ARM_V6
;
558 fHasPreferredSubType
= true;
560 else if ( strcmp(architecture
, "armv5") == 0 ) {
561 fArchitecture
= CPU_TYPE_ARM
;
562 fSubArchitecture
= CPU_SUBTYPE_ARM_V5TEJ
;
563 fHasPreferredSubType
= true;
565 else if ( strcmp(architecture
, "armv4t") == 0 ) {
566 fArchitecture
= CPU_TYPE_ARM
;
567 fSubArchitecture
= CPU_SUBTYPE_ARM_V4T
;
568 fHasPreferredSubType
= true;
570 else if ( strcmp(architecture
, "xscale") == 0 ) {
571 fArchitecture
= CPU_TYPE_ARM
;
572 fSubArchitecture
= CPU_SUBTYPE_ARM_XSCALE
;
573 fHasPreferredSubType
= true;
575 else if ( strcmp(architecture
, "armv7") == 0 ) {
576 fArchitecture
= CPU_TYPE_ARM
;
577 fSubArchitecture
= CPU_SUBTYPE_ARM_V7
;
578 fHasPreferredSubType
= true;
581 throwf("unknown/unsupported architecture name for: -arch %s", architecture
);
584 bool Options::checkForFile(const char* format
, const char* dir
, const char* rootName
, FileInfo
& result
)
586 struct stat statBuffer
;
587 char possiblePath
[strlen(dir
)+strlen(rootName
)+strlen(format
)+8];
588 sprintf(possiblePath
, format
, dir
, rootName
);
589 bool found
= (stat(possiblePath
, &statBuffer
) == 0);
590 if ( fTraceDylibSearching
)
591 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), possiblePath
);
593 result
.path
= strdup(possiblePath
);
594 result
.fileLen
= statBuffer
.st_size
;
595 result
.modTime
= statBuffer
.st_mtime
;
602 Options::FileInfo
Options::findLibrary(const char* rootName
, bool dylibsOnly
)
605 const int rootNameLen
= strlen(rootName
);
606 // if rootName ends in .o there is no .a vs .dylib choice
607 if ( (rootNameLen
> 3) && (strcmp(&rootName
[rootNameLen
-2], ".o") == 0) ) {
608 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
609 it
!= fLibrarySearchPaths
.end();
611 const char* dir
= *it
;
612 if ( checkForFile("%s/%s", dir
, rootName
, result
) )
617 bool lookForDylibs
= ( fOutputKind
!= Options::kDyld
);
618 switch ( fLibrarySearchMode
) {
619 case kSearchAllDirsForDylibsThenAllDirsForArchives
:
620 // first look in all directories for just for dylibs
621 if ( lookForDylibs
) {
622 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
623 it
!= fLibrarySearchPaths
.end();
625 const char* dir
= *it
;
626 if ( checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
629 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
630 it
!= fLibrarySearchPaths
.end();
632 const char* dir
= *it
;
633 if ( checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
637 // next look in all directories for just for archives
639 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
640 it
!= fLibrarySearchPaths
.end();
642 const char* dir
= *it
;
643 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
649 case kSearchDylibAndArchiveInEachDir
:
650 // look in each directory for just for a dylib then for an archive
651 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
652 it
!= fLibrarySearchPaths
.end();
654 const char* dir
= *it
;
655 if ( lookForDylibs
&& checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
657 if ( lookForDylibs
&& checkForFile("%s/lib%s.so", dir
, rootName
, result
) )
659 if ( !dylibsOnly
&& checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
665 throwf("library not found for -l%s", rootName
);
668 Options::FileInfo
Options::findFramework(const char* frameworkName
)
670 if ( frameworkName
== NULL
)
671 throw "-framework missing next argument";
672 char temp
[strlen(frameworkName
)+1];
673 strcpy(temp
, frameworkName
);
674 const char* name
= temp
;
675 const char* suffix
= NULL
;
676 char* comma
= strchr(temp
, ',');
677 if ( comma
!= NULL
) {
681 return findFramework(name
, suffix
);
684 Options::FileInfo
Options::findFramework(const char* rootName
, const char* suffix
)
686 struct stat statBuffer
;
687 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
688 it
!= fFrameworkSearchPaths
.end();
690 // ??? Shouldn't we be using String here and just initializing it?
691 // ??? Use str.c_str () to pull out the string for the stat call.
692 const char* dir
= *it
;
693 char possiblePath
[PATH_MAX
];
694 strcpy(possiblePath
, dir
);
695 strcat(possiblePath
, "/");
696 strcat(possiblePath
, rootName
);
697 strcat(possiblePath
, ".framework/");
698 strcat(possiblePath
, rootName
);
699 if ( suffix
!= NULL
) {
700 char realPath
[PATH_MAX
];
701 // no symlink in framework to suffix variants, so follow main symlink
702 if ( realpath(possiblePath
, realPath
) != NULL
) {
703 strcpy(possiblePath
, realPath
);
704 strcat(possiblePath
, suffix
);
707 bool found
= (stat(possiblePath
, &statBuffer
) == 0);
708 if ( fTraceDylibSearching
)
709 printf("[Logging for XBS]%sfound framework: '%s'\n",
710 (found
? " " : " not "), possiblePath
);
713 result
.path
= strdup(possiblePath
);
714 result
.fileLen
= statBuffer
.st_size
;
715 result
.modTime
= statBuffer
.st_mtime
;
719 // try without suffix
720 if ( suffix
!= NULL
)
721 return findFramework(rootName
, NULL
);
723 throwf("framework not found %s", rootName
);
726 Options::FileInfo
Options::findFile(const char* path
)
729 struct stat statBuffer
;
731 // if absolute path and not a .o file, the use SDK prefix
732 if ( (path
[0] == '/') && (strcmp(&path
[strlen(path
)-2], ".o") != 0) ) {
733 const int pathLen
= strlen(path
);
734 for (std::vector
<const char*>::iterator it
= fSDKPaths
.begin(); it
!= fSDKPaths
.end(); it
++) {
735 // ??? Shouldn't we be using String here?
736 const char* sdkPathDir
= *it
;
737 const int sdkPathDirLen
= strlen(sdkPathDir
);
738 char possiblePath
[sdkPathDirLen
+pathLen
+4];
739 strcpy(possiblePath
, sdkPathDir
);
740 if ( possiblePath
[sdkPathDirLen
-1] == '/' )
741 possiblePath
[sdkPathDirLen
-1] = '\0';
742 strcat(possiblePath
, path
);
743 if ( stat(possiblePath
, &statBuffer
) == 0 ) {
744 result
.path
= strdup(possiblePath
);
745 result
.fileLen
= statBuffer
.st_size
;
746 result
.modTime
= statBuffer
.st_mtime
;
752 if ( stat(path
, &statBuffer
) == 0 ) {
753 result
.path
= strdup(path
);
754 result
.fileLen
= statBuffer
.st_size
;
755 result
.modTime
= statBuffer
.st_mtime
;
759 // try @executable_path substitution
760 if ( (strncmp(path
, "@executable_path/", 17) == 0) && (fExecutablePath
!= NULL
) ) {
761 char newPath
[strlen(fExecutablePath
) + strlen(path
)];
762 strcpy(newPath
, fExecutablePath
);
763 char* addPoint
= strrchr(newPath
,'/');
764 if ( addPoint
!= NULL
)
765 strcpy(&addPoint
[1], &path
[17]);
767 strcpy(newPath
, &path
[17]);
768 if ( stat(newPath
, &statBuffer
) == 0 ) {
769 result
.path
= strdup(newPath
);
770 result
.fileLen
= statBuffer
.st_size
;
771 result
.modTime
= statBuffer
.st_mtime
;
777 throwf("file not found: %s", path
);
780 Options::FileInfo
Options::findFileUsingPaths(const char* path
)
784 const char* lastSlash
= strrchr(path
, '/');
785 const char* leafName
= (lastSlash
== NULL
) ? path
: &lastSlash
[1];
787 // Is this in a framework?
788 // /path/Foo.framework/Foo ==> true (Foo)
789 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
790 // /path/Foo.framework/Resources/Bar ==> false
791 bool isFramework
= false;
792 if ( lastSlash
!= NULL
) {
793 char frameworkDir
[strlen(leafName
) + 20];
794 strcpy(frameworkDir
, "/");
795 strcat(frameworkDir
, leafName
);
796 strcat(frameworkDir
, ".framework/");
797 if ( strstr(path
, frameworkDir
) != NULL
)
801 // These are abbreviated versions of the routines findFramework and findLibrary above
802 // because we already know the final name of the file that we're looking for and so
803 // don't need to try variations, just paths. We do need to add the additional bits
804 // onto the framework path though.
806 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
807 it
!= fFrameworkSearchPaths
.end();
809 const char* dir
= *it
;
810 char possiblePath
[PATH_MAX
];
811 strcpy(possiblePath
, dir
);
812 strcat(possiblePath
, "/");
813 strcat(possiblePath
, leafName
);
814 strcat(possiblePath
, ".framework");
816 //fprintf(stderr,"Finding Framework: %s/%s, leafName=%s\n", possiblePath, leafName, leafName);
817 if ( checkForFile("%s/%s", possiblePath
, leafName
, result
) )
822 // if this is a .dylib inside a framework, do not search -L paths
823 // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
824 int leafLen
= strlen(leafName
);
825 bool embeddedDylib
= ( (leafLen
> 6)
826 && (strcmp(&leafName
[leafLen
-6], ".dylib") == 0)
827 && (strstr(path
, ".framework/") != NULL
) );
828 if ( !embeddedDylib
) {
829 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
830 it
!= fLibrarySearchPaths
.end();
832 const char* dir
= *it
;
833 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
834 if ( checkForFile("%s/%s", dir
, leafName
, result
) )
840 // If we didn't find it fall back to findFile.
841 return findFile(path
);
845 void Options::parseSegAddrTable(const char* segAddrPath
, const char* installPath
)
847 FILE* file
= fopen(segAddrPath
, "r");
848 if ( file
== NULL
) {
849 warning("-seg_addr_table file cannot be read: %s", segAddrPath
);
854 uint64_t firstColumAddress
= 0;
855 uint64_t secondColumAddress
= 0;
856 bool hasSecondColumn
= false;
857 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
858 path
[PATH_MAX
-1] = '\0';
859 char* eol
= strchr(path
, '\n');
862 // ignore lines not starting with 0x number
863 if ( (path
[0] == '0') && (path
[1] == 'x') ) {
865 firstColumAddress
= strtoull(path
, &p
, 16);
866 while ( isspace(*p
) )
868 // see if second column is a number
869 if ( (p
[0] == '0') && (p
[1] == 'x') ) {
870 secondColumAddress
= strtoull(p
, &p
, 16);
871 hasSecondColumn
= true;
872 while ( isspace(*p
) )
875 while ( isspace(*p
) )
878 // remove any trailing whitespace
879 for(char* end
= eol
-1; (end
> p
) && isspace(*end
); --end
)
881 // see if this line is for the dylib being linked
882 if ( strcmp(p
, installPath
) == 0 ) {
883 fBaseAddress
= firstColumAddress
;
884 if ( hasSecondColumn
) {
885 fBaseWritableAddress
= secondColumAddress
;
888 break; // out of while loop
897 void Options::loadFileList(const char* fileOfPaths
)
900 const char* comma
= strrchr(fileOfPaths
, ',');
901 const char* prefix
= NULL
;
902 if ( comma
!= NULL
) {
903 // <rdar://problem/5907981> -filelist fails with comma in path
904 file
= fopen(fileOfPaths
, "r");
905 if ( file
== NULL
) {
907 int realFileOfPathsLen
= comma
-fileOfPaths
;
908 char realFileOfPaths
[realFileOfPathsLen
+1];
909 strncpy(realFileOfPaths
,fileOfPaths
, realFileOfPathsLen
);
910 realFileOfPaths
[realFileOfPathsLen
] = '\0';
911 file
= fopen(realFileOfPaths
, "r");
913 throwf("-filelist file not found: %s\n", realFileOfPaths
);
917 file
= fopen(fileOfPaths
, "r");
919 throwf("-filelist file not found: %s\n", fileOfPaths
);
923 while ( fgets(path
, PATH_MAX
, file
) != NULL
) {
924 path
[PATH_MAX
-1] = '\0';
925 char* eol
= strchr(path
, '\n');
928 if ( prefix
!= NULL
) {
929 char builtPath
[strlen(prefix
)+strlen(path
)+2];
930 strcpy(builtPath
, prefix
);
931 strcat(builtPath
, "/");
932 strcat(builtPath
, path
);
933 fInputFiles
.push_back(findFile(builtPath
));
936 fInputFiles
.push_back(findFile(path
));
942 bool Options::SetWithWildcards::hasWildCards(const char* symbol
)
944 // an exported symbol name containing *, ?, or [ requires wildcard matching
945 return ( strpbrk(symbol
, "*?[") != NULL
);
948 void Options::SetWithWildcards::insert(const char* symbol
)
950 if ( hasWildCards(symbol
) )
951 fWildCard
.push_back(symbol
);
953 fRegular
.insert(symbol
);
956 bool Options::SetWithWildcards::contains(const char* symbol
)
958 // first look at hash table on non-wildcard symbols
959 if ( fRegular
.find(symbol
) != fRegular
.end() )
961 // next walk list of wild card symbols looking for a match
962 for(std::vector
<const char*>::iterator it
= fWildCard
.begin(); it
!= fWildCard
.end(); ++it
) {
963 if ( wildCardMatch(*it
, symbol
) )
970 bool Options::SetWithWildcards::inCharRange(const char*& p
, unsigned char c
)
974 while ( *p
!= '\0' ) {
977 // found beginining [ and ending ]
978 unsigned char last
= '\0';
979 for ( const char* s
= b
; s
< e
; ++s
) {
981 unsigned char next
= *(++s
);
982 if ( (last
<= c
) && (c
<= next
) )
999 bool Options::SetWithWildcards::wildCardMatch(const char* pattern
, const char* symbol
)
1001 const char* s
= symbol
;
1002 for (const char* p
= pattern
; *p
!= '\0'; ++p
) {
1007 for (const char* t
= s
; *t
!= '\0'; ++t
) {
1008 if ( wildCardMatch(&p
[1], t
) )
1018 if ( ! inCharRange(p
, *s
) )
1028 return (*s
== '\0');
1032 void Options::loadExportFile(const char* fileOfExports
, const char* option
, SetWithWildcards
& set
)
1034 // read in whole file
1035 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
1037 throwf("can't open %s file: %s", option
, fileOfExports
);
1038 struct stat stat_buf
;
1039 ::fstat(fd
, &stat_buf
);
1040 char* p
= (char*)malloc(stat_buf
.st_size
);
1042 throwf("can't process %s file: %s", option
, fileOfExports
);
1044 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1045 throwf("can't read %s file: %s", option
, fileOfExports
);
1049 // parse into symbols and add to hash_set
1050 char * const end
= &p
[stat_buf
.st_size
];
1051 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1052 char* symbolStart
= NULL
;
1053 for (char* s
= p
; s
< end
; ++s
) {
1059 else if ( !isspace(*s
) ) {
1065 if ( (*s
== '\n') || (*s
== '\r') ) {
1067 // removing any trailing spaces
1069 while ( isspace(*last
) ) {
1073 set
.insert(symbolStart
);
1079 if ( (*s
== '\n') || (*s
== '\r') )
1084 if ( state
== inSymbol
) {
1085 warning("missing line-end at end of file \"%s\"", fileOfExports
);
1086 int len
= end
-symbolStart
+1;
1087 char* temp
= new char[len
];
1088 strlcpy(temp
, symbolStart
, len
);
1090 // remove any trailing spaces
1091 char* last
= &temp
[len
-2];
1092 while ( isspace(*last
) ) {
1099 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
1102 void Options::parseAliasFile(const char* fileOfAliases
)
1104 // read in whole file
1105 int fd
= ::open(fileOfAliases
, O_RDONLY
, 0);
1107 throwf("can't open alias file: %s", fileOfAliases
);
1108 struct stat stat_buf
;
1109 ::fstat(fd
, &stat_buf
);
1110 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1112 throwf("can't process alias file: %s", fileOfAliases
);
1114 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1115 throwf("can't read alias file: %s", fileOfAliases
);
1116 p
[stat_buf
.st_size
] = '\n';
1119 // parse into symbols and add to fAliases
1120 ObjectFile::ReaderOptions::AliasPair pair
;
1121 char * const end
= &p
[stat_buf
.st_size
+1];
1122 enum { lineStart
, inRealName
, inBetween
, inAliasName
, inComment
} state
= lineStart
;
1124 for (char* s
= p
; s
< end
; ++s
) {
1130 else if ( !isspace(*s
) ) {
1137 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1141 else if ( isspace(*s
) ) {
1148 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber
, fileOfAliases
);
1152 else if ( ! isspace(*s
) ) {
1153 state
= inAliasName
;
1160 // removing any trailing spaces
1162 while ( isspace(*last
) ) {
1166 fReaderOptions
.fAliases
.push_back(pair
);
1169 else if ( *s
== '\n' ) {
1171 // removing any trailing spaces
1173 while ( isspace(*last
) ) {
1177 fReaderOptions
.fAliases
.push_back(pair
);
1188 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
1193 void Options::setUndefinedTreatment(const char* treatment
)
1195 if ( treatment
== NULL
)
1196 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
1198 if ( strcmp(treatment
, "warning") == 0 )
1199 fUndefinedTreatment
= kUndefinedWarning
;
1200 else if ( strcmp(treatment
, "error") == 0 )
1201 fUndefinedTreatment
= kUndefinedError
;
1202 else if ( strcmp(treatment
, "suppress") == 0 )
1203 fUndefinedTreatment
= kUndefinedSuppress
;
1204 else if ( strcmp(treatment
, "dynamic_lookup") == 0 )
1205 fUndefinedTreatment
= kUndefinedDynamicLookup
;
1207 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1210 Options::Treatment
Options::parseTreatment(const char* treatment
)
1212 if ( treatment
== NULL
)
1215 if ( strcmp(treatment
, "warning") == 0 )
1217 else if ( strcmp(treatment
, "error") == 0 )
1219 else if ( strcmp(treatment
, "suppress") == 0 )
1225 void Options::setMacOSXVersionMin(const char* version
)
1227 if ( version
== NULL
)
1228 throw "-macosx_version_min argument missing";
1230 if ( (strncmp(version
, "10.", 3) == 0) && isdigit(version
[3]) ) {
1231 int num
= version
[3] - '0';
1235 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_1
;
1238 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_2
;
1241 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_3
;
1244 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_4
;
1247 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_5
;
1250 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_6
;
1253 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_7
;
1256 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_7
;
1261 warning("unknown option to -macosx_version_min, not 10.x");
1265 void Options::setIPhoneVersionMin(const char* version
)
1267 if ( version
== NULL
)
1268 throw "-iphoneos_version_min argument missing";
1269 if ( ! isdigit(version
[0]) )
1270 throw "-iphoneos_version_min argument is not a number";
1271 if ( version
[1] != '.' )
1272 throw "-iphoneos_version_min argument is missing period as second character";
1273 if ( ! isdigit(version
[2]) )
1274 throw "-iphoneos_version_min argument is not a number";
1276 if ( (version
[0] == '2') && (version
[2] == '0') )
1277 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_0
;
1278 else if ( (version
[0] == '2') && (version
[2] == '1') )
1279 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_1
;
1280 else if ( (version
[0] == '2') && (version
[2] >= '2') )
1281 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_2
;
1282 else if ( (version
[0] == '3') && (version
[2] == '0') )
1283 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k3_0
;
1284 else if ( (version
[0] == '3') && (version
[2] == '1') )
1285 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k3_1
;
1286 else if ( (version
[0] == '3') && (version
[2] >= '2') )
1287 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k3_2
;
1288 else if ( (version
[0] >= '4') )
1289 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k4_0
;
1291 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_0
;
1292 warning("unknown option to -iphoneos_version_min, not 2.x, 3.x, or 4.x");
1296 bool Options::minOS(ObjectFile::ReaderOptions::MacVersionMin requiredMacMin
, ObjectFile::ReaderOptions::IPhoneVersionMin requirediPhoneOSMin
)
1298 if ( fReaderOptions
.fMacVersionMin
!= ObjectFile::ReaderOptions::kMinMacVersionUnset
) {
1299 return ( fReaderOptions
.fMacVersionMin
>= requiredMacMin
);
1302 return ( fReaderOptions
.fIPhoneVersionMin
>= requirediPhoneOSMin
);
1307 void Options::setWeakReferenceMismatchTreatment(const char* treatment
)
1309 if ( treatment
== NULL
)
1310 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1312 if ( strcmp(treatment
, "error") == 0 )
1313 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchError
;
1314 else if ( strcmp(treatment
, "weak") == 0 )
1315 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchWeak
;
1316 else if ( strcmp(treatment
, "non-weak") == 0 )
1317 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchNonWeak
;
1319 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1322 Options::CommonsMode
Options::parseCommonsTreatment(const char* mode
)
1325 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1327 if ( strcmp(mode
, "ignore_dylibs") == 0 )
1328 return kCommonsIgnoreDylibs
;
1329 else if ( strcmp(mode
, "use_dylibs") == 0 )
1330 return kCommonsOverriddenByDylibs
;
1331 else if ( strcmp(mode
, "error") == 0 )
1332 return kCommonsConflictsDylibsError
;
1334 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1337 void Options::addDylibOverride(const char* paths
)
1339 if ( paths
== NULL
)
1340 throw "-dylib_file must followed by two colon separated paths";
1341 const char* colon
= strchr(paths
, ':');
1342 if ( colon
== NULL
)
1343 throw "-dylib_file must followed by two colon separated paths";
1344 int len
= colon
-paths
;
1345 char* target
= new char[len
+2];
1346 strncpy(target
, paths
, len
);
1348 DylibOverride entry
;
1349 entry
.installName
= target
;
1350 entry
.useInstead
= &colon
[1];
1351 fDylibOverrides
.push_back(entry
);
1354 uint64_t Options::parseAddress(const char* addr
)
1357 uint64_t result
= strtoull(addr
, &endptr
, 16);
1361 uint32_t Options::parseProtection(const char* prot
)
1363 uint32_t result
= 0;
1364 for(const char* p
= prot
; *p
!= '\0'; ++p
) {
1365 switch(tolower(*p
)) {
1367 result
|= VM_PROT_READ
;
1370 result
|= VM_PROT_WRITE
;
1373 result
|= VM_PROT_EXECUTE
;
1378 throwf("unknown -segprot lettter in %s", prot
);
1387 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1390 uint32_t Options::parseVersionNumber(const char* versionString
)
1392 unsigned long x
= 0;
1393 unsigned long y
= 0;
1394 unsigned long z
= 0;
1396 x
= strtoul(versionString
, &end
, 10);
1397 if ( *end
== '.' ) {
1398 y
= strtoul(&end
[1], &end
, 10);
1399 if ( *end
== '.' ) {
1400 z
= strtoul(&end
[1], &end
, 10);
1403 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
1404 throwf("malformed version number: %s", versionString
);
1406 return (x
<< 16) | ( y
<< 8 ) | z
;
1409 static const char* cstringSymbolName(const char* orderFileString
)
1412 asprintf(&result
, "cstring=%s", orderFileString
);
1413 // convert escaped characters
1415 for(const char* s
=result
; *s
!= '\0'; ++s
, ++d
) {
1453 // hexadecimal value of char
1457 while ( isxdigit(*s
) ) {
1462 value
+= ((toupper(*s
)-'A') + 10);
1469 if ( isdigit(*s
) ) {
1470 // octal value of char
1472 while ( isdigit(*s
) ) {
1473 value
= (value
<< 3) + (*s
-'0');
1488 void Options::parseOrderFile(const char* path
, bool cstring
)
1490 // order files override auto-ordering
1491 fReaderOptions
.fAutoOrderInitializers
= false;
1493 // read in whole file
1494 int fd
= ::open(path
, O_RDONLY
, 0);
1496 throwf("can't open order file: %s", path
);
1497 struct stat stat_buf
;
1498 ::fstat(fd
, &stat_buf
);
1499 char* p
= (char*)malloc(stat_buf
.st_size
+1);
1501 throwf("can't process order file: %s", path
);
1502 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1503 throwf("can't read order file: %s", path
);
1505 p
[stat_buf
.st_size
] = '\n';
1507 // parse into vector of pairs
1508 char * const end
= &p
[stat_buf
.st_size
+1];
1509 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
1510 char* symbolStart
= NULL
;
1511 for (char* s
= p
; s
< end
; ++s
) {
1517 else if ( !isspace(*s
) || cstring
) {
1523 if ( (*s
== '\n') || (!cstring
&& (*s
== '#')) ) {
1524 bool wasComment
= (*s
== '#');
1526 // removing any trailing spaces
1528 while ( isspace(*last
) ) {
1532 if ( strncmp(symbolStart
, "ppc:", 4) == 0 ) {
1533 if ( fArchitecture
== CPU_TYPE_POWERPC
)
1534 symbolStart
= &symbolStart
[4];
1538 // if there is an architecture prefix, only use this symbol it if matches current arch
1539 else if ( strncmp(symbolStart
, "ppc64:", 6) == 0 ) {
1540 if ( fArchitecture
== CPU_TYPE_POWERPC64
)
1541 symbolStart
= &symbolStart
[6];
1545 else if ( strncmp(symbolStart
, "i386:", 5) == 0 ) {
1546 if ( fArchitecture
== CPU_TYPE_I386
)
1547 symbolStart
= &symbolStart
[5];
1551 else if ( strncmp(symbolStart
, "x86_64:", 7) == 0 ) {
1552 if ( fArchitecture
== CPU_TYPE_X86_64
)
1553 symbolStart
= &symbolStart
[7];
1557 else if ( strncmp(symbolStart
, "arm:", 4) == 0 ) {
1558 if ( fArchitecture
== CPU_TYPE_ARM
)
1559 symbolStart
= &symbolStart
[4];
1563 if ( symbolStart
!= NULL
) {
1564 char* objFileName
= NULL
;
1565 char* colon
= strstr(symbolStart
, ".o:");
1566 if ( colon
!= NULL
) {
1568 objFileName
= symbolStart
;
1569 symbolStart
= &colon
[3];
1571 // trim leading spaces
1572 while ( isspace(*symbolStart
) )
1574 Options::OrderedSymbol pair
;
1576 pair
.symbolName
= cstringSymbolName(symbolStart
);
1578 pair
.symbolName
= symbolStart
;
1579 pair
.objectFileName
= objFileName
;
1580 fOrderedSymbols
.push_back(pair
);
1595 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1598 void Options::parseSectionOrderFile(const char* segment
, const char* section
, const char* path
)
1600 if ( (strcmp(section
, "__cstring") == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1601 parseOrderFile(path
, true);
1603 else if ( (strncmp(section
, "__literal",9) == 0) && (strcmp(segment
, "__TEXT") == 0) ) {
1604 warning("sorting of __literal[4,8,16] sections not supported");
1607 // ignore section information and append all symbol names to global order file
1608 parseOrderFile(path
, false);
1612 void Options::addSection(const char* segment
, const char* section
, const char* path
)
1614 if ( strlen(segment
) > 16 )
1615 throw "-seccreate segment name max 16 chars";
1616 if ( strlen(section
) > 16 ) {
1617 char* tmp
= strdup(section
);
1619 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section
, tmp
);
1623 // read in whole file
1624 int fd
= ::open(path
, O_RDONLY
, 0);
1626 throwf("can't open -sectcreate file: %s", path
);
1627 struct stat stat_buf
;
1628 ::fstat(fd
, &stat_buf
);
1629 char* p
= (char*)malloc(stat_buf
.st_size
);
1631 throwf("can't process -sectcreate file: %s", path
);
1632 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
1633 throwf("can't read -sectcreate file: %s", path
);
1636 // record section to create
1637 ExtraSection info
= { segment
, section
, path
, (uint8_t*)p
, stat_buf
.st_size
};
1638 fExtraSections
.push_back(info
);
1641 void Options::addSectionAlignment(const char* segment
, const char* section
, const char* alignmentStr
)
1643 if ( strlen(segment
) > 16 )
1644 throw "-sectalign segment name max 16 chars";
1645 if ( strlen(section
) > 16 )
1646 throw "-sectalign section name max 16 chars";
1648 // argument to -sectalign is a hexadecimal number
1650 unsigned long value
= strtoul(alignmentStr
, &endptr
, 16);
1651 if ( *endptr
!= '\0')
1652 throw "argument for -sectalign is not a hexadecimal number";
1653 if ( value
> 0x8000 )
1654 throw "argument for -sectalign must be less than or equal to 0x8000";
1656 warning("zero is not a valid -sectalign");
1660 // alignment is power of 2 (e.g. page alignment = 12)
1661 uint8_t alignment
= (uint8_t)__builtin_ctz(value
);
1662 if ( (unsigned long)(1 << alignment
) != value
) {
1663 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
1664 segment
, section
, 1 << alignment
);
1667 SectionAlignment info
= { segment
, section
, alignment
};
1668 fSectionAlignments
.push_back(info
);
1671 void Options::addLibrary(const FileInfo
& info
)
1673 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
1674 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
1675 if ( strcmp(info
.path
, fit
->path
) == 0 ) {
1676 // if dylib is specified again but weak, record that it should be weak
1677 if ( info
.options
.fWeakImport
)
1678 fit
->options
.fWeakImport
= true;
1683 fInputFiles
.push_back(info
);
1686 void Options::warnObsolete(const char* arg
)
1688 warning("option %s is obsolete and being ignored", arg
);
1695 // Process all command line arguments.
1697 // The only error checking done here is that each option is valid and if it has arguments
1698 // that they too are valid.
1700 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
1701 // whichever was last on the command line is used.
1703 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
1705 void Options::parse(int argc
, const char* argv
[])
1707 // pass one builds search list from -L and -F options
1708 this->buildSearchPaths(argc
, argv
);
1710 // reduce re-allocations
1711 fInputFiles
.reserve(32);
1713 // pass two parse all other options
1714 for(int i
=1; i
< argc
; ++i
) {
1715 const char* arg
= argv
[i
];
1717 if ( arg
[0] == '-' ) {
1719 // Since we don't care about the files passed, just the option names, we do this here.
1721 fprintf (stderr
, "[Logging ld64 options]\t%s\n", arg
);
1723 if ( (arg
[1] == 'L') || (arg
[1] == 'F') ) {
1724 // previously handled by buildSearchPaths()
1726 // The one gnu style option we have to keep compatibility
1727 // with gcc. Might as well have the single hyphen one as well.
1728 else if ( (strcmp(arg
, "--help") == 0)
1729 || (strcmp(arg
, "-help") == 0)) {
1730 fprintf (stdout
, "ld64: For information on command line options please use 'man ld'.\n");
1733 else if ( strcmp(arg
, "-arch") == 0 ) {
1734 parseArch(argv
[++i
]);
1736 else if ( strcmp(arg
, "-dynamic") == 0 ) {
1739 else if ( strcmp(arg
, "-static") == 0 ) {
1740 fReaderOptions
.fForStatic
= true;
1741 if ( fOutputKind
!= kObjectFile
) {
1742 fOutputKind
= kStaticExecutable
;
1745 else if ( strcmp(arg
, "-dylib") == 0 ) {
1746 fOutputKind
= kDynamicLibrary
;
1748 else if ( strcmp(arg
, "-bundle") == 0 ) {
1749 fOutputKind
= kDynamicBundle
;
1751 else if ( strcmp(arg
, "-dylinker") == 0 ) {
1752 fOutputKind
= kDyld
;
1754 else if ( strcmp(arg
, "-execute") == 0 ) {
1755 if ( fOutputKind
!= kStaticExecutable
)
1756 fOutputKind
= kDynamicExecutable
;
1758 else if ( strcmp(arg
, "-preload") == 0 ) {
1759 fOutputKind
= kPreload
;
1761 else if ( strcmp(arg
, "-r") == 0 ) {
1762 fOutputKind
= kObjectFile
;
1764 else if ( strcmp(arg
, "-kext") == 0 ) {
1765 fOutputKind
= kKextBundle
;
1767 else if ( strcmp(arg
, "-o") == 0 ) {
1768 fOutputFile
= argv
[++i
];
1770 else if ( (arg
[1] == 'l') && (strncmp(arg
,"-lazy_",6) !=0) ) {
1771 addLibrary(findLibrary(&arg
[2]));
1773 // This causes a dylib to be weakly bound at
1774 // link time. This corresponds to weak_import.
1775 else if ( strncmp(arg
, "-weak-l", 7) == 0 ) {
1776 FileInfo info
= findLibrary(&arg
[7]);
1777 info
.options
.fWeakImport
= true;
1780 else if ( strncmp(arg
, "-lazy-l", 7) == 0 ) {
1781 FileInfo info
= findLibrary(&arg
[7], true);
1782 info
.options
.fLazyLoad
= true;
1784 fUsingLazyDylibLinking
= true;
1786 // Avoid lazy binding.
1788 else if ( strcmp(arg
, "-bind_at_load") == 0 ) {
1791 else if ( strcmp(arg
, "-twolevel_namespace") == 0 ) {
1792 fNameSpace
= kTwoLevelNameSpace
;
1794 else if ( strcmp(arg
, "-flat_namespace") == 0 ) {
1795 fNameSpace
= kFlatNameSpace
;
1797 // Also sets a bit to ensure dyld causes everything
1798 // in the namespace to be flat.
1800 else if ( strcmp(arg
, "-force_flat_namespace") == 0 ) {
1801 fNameSpace
= kForceFlatNameSpace
;
1803 // Similar to --whole-archive.
1804 else if ( strcmp(arg
, "-all_load") == 0 ) {
1805 fReaderOptions
.fFullyLoadArchives
= true;
1807 else if ( strcmp(arg
, "-noall_load") == 0) {
1810 // Similar to -all_load
1811 else if ( strcmp(arg
, "-ObjC") == 0 ) {
1812 fReaderOptions
.fLoadAllObjcObjectsFromArchives
= true;
1814 // Similar to -all_load, but for the following archive only.
1815 else if ( strcmp(arg
, "-force_load") == 0 ) {
1816 FileInfo info
= findFile(argv
[++i
]);
1817 info
.options
.fForceLoad
= true;
1820 // Library versioning.
1821 else if ( (strcmp(arg
, "-dylib_compatibility_version") == 0)
1822 || (strcmp(arg
, "-compatibility_version") == 0)) {
1823 const char* vers
= argv
[++i
];
1825 throw "-dylib_compatibility_version missing <version>";
1826 fDylibCompatVersion
= parseVersionNumber(vers
);
1828 else if ( (strcmp(arg
, "-dylib_current_version") == 0)
1829 || (strcmp(arg
, "-current_version") == 0)) {
1830 const char* vers
= argv
[++i
];
1832 throw "-dylib_current_version missing <version>";
1833 fDylibCurrentVersion
= parseVersionNumber(vers
);
1835 else if ( strcmp(arg
, "-sectorder") == 0 ) {
1836 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
1837 throw "-sectorder missing <segment> <section> <file-path>";
1838 parseSectionOrderFile(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1841 else if ( strcmp(arg
, "-order_file") == 0 ) {
1842 parseOrderFile(argv
[++i
], false);
1844 else if ( strcmp(arg
, "-order_file_statistics") == 0 ) {
1845 fPrintOrderFileStatistics
= true;
1847 // ??? Deprecate segcreate.
1848 // -sectcreate puts whole files into a section in the output.
1849 else if ( (strcmp(arg
, "-sectcreate") == 0) || (strcmp(arg
, "-segcreate") == 0) ) {
1850 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
1851 throw "-sectcreate missing <segment> <section> <file-path>";
1852 addSection(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1855 // Since we have a full path in binary/library names we need to be able to override it.
1856 else if ( (strcmp(arg
, "-dylib_install_name") == 0)
1857 || (strcmp(arg
, "-dylinker_install_name") == 0)
1858 || (strcmp(arg
, "-install_name") == 0)) {
1859 fDylibInstallName
= argv
[++i
];
1860 if ( fDylibInstallName
== NULL
)
1861 throw "-install_name missing <path>";
1863 // Sets the base address of the output.
1864 else if ( (strcmp(arg
, "-seg1addr") == 0) || (strcmp(arg
, "-image_base") == 0) ) {
1865 const char* address
= argv
[++i
];
1866 if ( address
== NULL
)
1867 throwf("%s missing <address>", arg
);
1868 fBaseAddress
= parseAddress(address
);
1869 uint64_t temp
= ((fBaseAddress
+fSegmentAlignment
-1) & (-fSegmentAlignment
));
1870 if ( fBaseAddress
!= temp
) {
1871 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment
);
1872 fBaseAddress
= temp
;
1875 else if ( strcmp(arg
, "-e") == 0 ) {
1876 fEntryName
= argv
[++i
];
1878 // Same as -@ from the FSF linker.
1879 else if ( strcmp(arg
, "-filelist") == 0 ) {
1880 const char* path
= argv
[++i
];
1881 if ( (path
== NULL
) || (path
[0] == '-') )
1882 throw "-filelist missing <path>";
1885 else if ( strcmp(arg
, "-keep_private_externs") == 0 ) {
1886 fKeepPrivateExterns
= true;
1888 else if ( strcmp(arg
, "-final_output") == 0 ) {
1889 fFinalName
= argv
[++i
];
1891 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
1892 // just ensures that this happens for cross object file boundaries.
1893 else if ( (strcmp(arg
, "-interposable") == 0) || (strcmp(arg
, "-multi_module") == 0)) {
1894 switch ( fInterposeMode
) {
1895 case kInterposeNone
:
1896 case kInterposeAllExternal
:
1897 fInterposeMode
= kInterposeAllExternal
;
1899 case kInterposeSome
:
1900 // do nothing, -interposable_list overrides -interposable"
1904 else if ( strcmp(arg
, "-interposable_list") == 0 ) {
1905 fInterposeMode
= kInterposeSome
;
1906 loadExportFile(argv
[++i
], "-interposable_list", fInterposeList
);
1908 // Default for -interposable/-multi_module/-single_module.
1909 else if ( strcmp(arg
, "-single_module") == 0 ) {
1910 fInterposeMode
= kInterposeNone
;
1912 else if ( strcmp(arg
, "-exported_symbols_list") == 0 ) {
1913 if ( fExportMode
== kDontExportSome
)
1914 throw "can't use -exported_symbols_list and -unexported_symbols_list";
1915 fExportMode
= kExportSome
;
1916 loadExportFile(argv
[++i
], "-exported_symbols_list", fExportSymbols
);
1918 else if ( strcmp(arg
, "-unexported_symbols_list") == 0 ) {
1919 if ( fExportMode
== kExportSome
)
1920 throw "can't use -unexported_symbols_list and -exported_symbols_list";
1921 fExportMode
= kDontExportSome
;
1922 loadExportFile(argv
[++i
], "-unexported_symbols_list", fDontExportSymbols
);
1924 else if ( strcmp(arg
, "-exported_symbol") == 0 ) {
1925 if ( fExportMode
== kDontExportSome
)
1926 throw "can't use -exported_symbol and -unexported_symbols";
1927 fExportMode
= kExportSome
;
1928 fExportSymbols
.insert(argv
[++i
]);
1930 else if ( strcmp(arg
, "-unexported_symbol") == 0 ) {
1931 if ( fExportMode
== kExportSome
)
1932 throw "can't use -unexported_symbol and -exported_symbol";
1933 fExportMode
= kDontExportSome
;
1934 fDontExportSymbols
.insert(argv
[++i
]);
1936 else if ( strcmp(arg
, "-non_global_symbols_no_strip_list") == 0 ) {
1937 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveExclude
)
1938 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
1939 fLocalSymbolHandling
= kLocalSymbolsSelectiveInclude
;
1940 loadExportFile(argv
[++i
], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded
);
1942 else if ( strcmp(arg
, "-non_global_symbols_strip_list") == 0 ) {
1943 if ( fLocalSymbolHandling
== kLocalSymbolsSelectiveInclude
)
1944 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
1945 fLocalSymbolHandling
= kLocalSymbolsSelectiveExclude
;
1946 loadExportFile(argv
[++i
], "-non_global_symbols_strip_list", fLocalSymbolsExcluded
);
1949 else if ( strcmp(arg
, "-no_arch_warnings") == 0 ) {
1950 fIgnoreOtherArchFiles
= true;
1952 else if ( strcmp(arg
, "-force_cpusubtype_ALL") == 0 ) {
1953 fForceSubtypeAll
= true;
1955 // Similar to -weak-l but uses the absolute path name to the library.
1956 else if ( strcmp(arg
, "-weak_library") == 0 ) {
1957 FileInfo info
= findFile(argv
[++i
]);
1958 info
.options
.fWeakImport
= true;
1961 else if ( strcmp(arg
, "-lazy_library") == 0 ) {
1962 FileInfo info
= findFile(argv
[++i
]);
1963 info
.options
.fLazyLoad
= true;
1965 fUsingLazyDylibLinking
= true;
1967 else if ( strcmp(arg
, "-framework") == 0 ) {
1968 addLibrary(findFramework(argv
[++i
]));
1970 else if ( strcmp(arg
, "-weak_framework") == 0 ) {
1971 FileInfo info
= findFramework(argv
[++i
]);
1972 info
.options
.fWeakImport
= true;
1975 else if ( strcmp(arg
, "-lazy_framework") == 0 ) {
1976 FileInfo info
= findFramework(argv
[++i
]);
1977 info
.options
.fLazyLoad
= true;
1979 fUsingLazyDylibLinking
= true;
1981 else if ( strcmp(arg
, "-search_paths_first") == 0 ) {
1982 // previously handled by buildSearchPaths()
1984 else if ( strcmp(arg
, "-undefined") == 0 ) {
1985 setUndefinedTreatment(argv
[++i
]);
1987 // Debugging output flag.
1988 else if ( strcmp(arg
, "-arch_multiple") == 0 ) {
1989 fMessagesPrefixedWithArchitecture
= true;
1991 // Specify what to do with relocations in read only
1992 // sections like .text. Could be errors, warnings,
1993 // or suppressed. Currently we do nothing with the
1995 else if ( strcmp(arg
, "-read_only_relocs") == 0 ) {
1996 switch ( parseTreatment(argv
[++i
]) ) {
1999 throw "-read_only_relocs missing [ warning | error | suppress ]";
2001 fWarnTextRelocs
= true;
2002 fAllowTextRelocs
= true;
2005 fWarnTextRelocs
= false;
2006 fAllowTextRelocs
= true;
2009 fWarnTextRelocs
= false;
2010 fAllowTextRelocs
= false;
2014 else if ( strcmp(arg
, "-sect_diff_relocs") == 0 ) {
2018 // Warn, error or make strong a mismatch between weak
2019 // and non-weak references.
2020 else if ( strcmp(arg
, "-weak_reference_mismatches") == 0 ) {
2021 setWeakReferenceMismatchTreatment(argv
[++i
]);
2023 // For a deployment target of 10.3 and earlier ld64 will
2024 // prebind an executable with 0s in all addresses that
2025 // are prebound. This can then be fixed up by update_prebinding
2026 // later. Prebinding is less useful on 10.4 and greater.
2027 else if ( strcmp(arg
, "-prebind") == 0 ) {
2030 else if ( strcmp(arg
, "-noprebind") == 0 ) {
2034 else if ( strcmp(arg
, "-prebind_allow_overlap") == 0 ) {
2037 else if ( strcmp(arg
, "-prebind_all_twolevel_modules") == 0 ) {
2040 else if ( strcmp(arg
, "-noprebind_all_twolevel_modules") == 0 ) {
2043 else if ( strcmp(arg
, "-nofixprebinding") == 0 ) {
2046 // This should probably be deprecated when we respect -L and -F
2047 // when searching for libraries.
2048 else if ( strcmp(arg
, "-dylib_file") == 0 ) {
2049 addDylibOverride(argv
[++i
]);
2051 // What to expand @executable_path to if found in dependent dylibs
2052 else if ( strcmp(arg
, "-executable_path") == 0 ) {
2053 fExecutablePath
= argv
[++i
];
2054 if ( (fExecutablePath
== NULL
) || (fExecutablePath
[0] == '-') )
2055 throw "-executable_path missing <path>";
2056 // if a directory was passed, add / to end
2057 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2058 struct stat statBuffer
;
2059 if ( stat(fExecutablePath
, &statBuffer
) == 0 ) {
2060 if ( (statBuffer
.st_mode
& S_IFMT
) == S_IFDIR
) {
2061 char* pathWithSlash
= new char[strlen(fExecutablePath
)+2];
2062 strcpy(pathWithSlash
, fExecutablePath
);
2063 strcat(pathWithSlash
, "/");
2064 fExecutablePath
= pathWithSlash
;
2068 // Aligns all segments to the power of 2 boundary specified.
2069 else if ( strcmp(arg
, "-segalign") == 0 ) {
2070 const char* size
= argv
[++i
];
2072 throw "-segalign missing <size>";
2073 fSegmentAlignment
= parseAddress(size
);
2074 uint8_t alignment
= (uint8_t)__builtin_ctz(fSegmentAlignment
);
2075 uint32_t p2aligned
= (1 << alignment
);
2076 if ( p2aligned
!= fSegmentAlignment
) {
2077 warning("alignment for -segalign %s is not a power of two, using 0x%X", size
, p2aligned
);
2078 fSegmentAlignment
= p2aligned
;
2081 // Puts a specified segment at a particular address that must
2082 // be a multiple of the segment alignment.
2083 else if ( strcmp(arg
, "-segaddr") == 0 ) {
2085 seg
.name
= argv
[++i
];
2086 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2087 throw "-segaddr missing segName Adddress";
2088 seg
.address
= parseAddress(argv
[++i
]);
2089 uint64_t temp
= seg
.address
& (-4096); // page align
2090 if ( (seg
.address
!= temp
) )
2091 warning("-segaddr %s not page aligned, rounding down", seg
.name
);
2092 fCustomSegmentAddresses
.push_back(seg
);
2094 // ??? Deprecate when we deprecate split-seg.
2095 else if ( strcmp(arg
, "-segs_read_only_addr") == 0 ) {
2096 fBaseAddress
= parseAddress(argv
[++i
]);
2098 // ??? Deprecate when we deprecate split-seg.
2099 else if ( strcmp(arg
, "-segs_read_write_addr") == 0 ) {
2100 fBaseWritableAddress
= parseAddress(argv
[++i
]);
2103 // ??? Deprecate when we get rid of basing at build time.
2104 else if ( strcmp(arg
, "-seg_addr_table") == 0 ) {
2105 const char* name
= argv
[++i
];
2107 throw "-seg_addr_table missing argument";
2108 fSegAddrTablePath
= name
;
2110 else if ( strcmp(arg
, "-seg_addr_table_filename") == 0 ) {
2114 else if ( strcmp(arg
, "-segprot") == 0 ) {
2116 seg
.name
= argv
[++i
];
2117 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) || (argv
[i
+2] == NULL
) )
2118 throw "-segprot missing segName max-prot init-prot";
2119 seg
.max
= parseProtection(argv
[++i
]);
2120 seg
.init
= parseProtection(argv
[++i
]);
2121 fCustomSegmentProtections
.push_back(seg
);
2123 else if ( strcmp(arg
, "-pagezero_size") == 0 ) {
2124 const char* size
= argv
[++i
];
2126 throw "-pagezero_size missing <size>";
2127 fZeroPageSize
= parseAddress(size
);
2128 uint64_t temp
= fZeroPageSize
& (-4096); // page align
2129 if ( (fZeroPageSize
!= temp
) )
2130 warning("-pagezero_size not page aligned, rounding down");
2131 fZeroPageSize
= temp
;
2133 else if ( strcmp(arg
, "-stack_addr") == 0 ) {
2134 const char* address
= argv
[++i
];
2135 if ( address
== NULL
)
2136 throw "-stack_addr missing <address>";
2137 fStackAddr
= parseAddress(address
);
2139 else if ( strcmp(arg
, "-stack_size") == 0 ) {
2140 const char* size
= argv
[++i
];
2142 throw "-stack_size missing <address>";
2143 fStackSize
= parseAddress(size
);
2144 uint64_t temp
= fStackSize
& (-4096); // page align
2145 if ( (fStackSize
!= temp
) )
2146 warning("-stack_size not page aligned, rounding down");
2148 else if ( strcmp(arg
, "-allow_stack_execute") == 0 ) {
2149 fExecutableStack
= true;
2151 else if ( strcmp(arg
, "-sectalign") == 0 ) {
2152 if ( (argv
[i
+1]==NULL
) || (argv
[i
+2]==NULL
) || (argv
[i
+3]==NULL
) )
2153 throw "-sectalign missing <segment> <section> <file-path>";
2154 addSectionAlignment(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
2157 else if ( strcmp(arg
, "-sectorder_detail") == 0 ) {
2160 else if ( strcmp(arg
, "-sectobjectsymbols") == 0 ) {
2164 else if ( strcmp(arg
, "-bundle_loader") == 0 ) {
2165 fBundleLoader
= argv
[++i
];
2166 if ( (fBundleLoader
== NULL
) || (fBundleLoader
[0] == '-') )
2167 throw "-bundle_loader missing <path>";
2168 FileInfo info
= findFile(fBundleLoader
);
2169 info
.options
.fBundleLoader
= true;
2170 fInputFiles
.push_back(info
);
2172 else if ( strcmp(arg
, "-private_bundle") == 0 ) {
2175 else if ( strcmp(arg
, "-twolevel_namespace_hints") == 0 ) {
2178 // Use this flag to set default behavior for deployement targets.
2179 else if ( strcmp(arg
, "-macosx_version_min") == 0 ) {
2180 setMacOSXVersionMin(argv
[++i
]);
2182 else if ( strcmp(arg
, "-iphoneos_version_min") == 0 ) {
2183 setIPhoneVersionMin(argv
[++i
]);
2185 else if ( strcmp(arg
, "-multiply_defined") == 0 ) {
2186 //warnObsolete(arg);
2189 else if ( strcmp(arg
, "-multiply_defined_unused") == 0 ) {
2193 else if ( strcmp(arg
, "-nomultidefs") == 0 ) {
2196 // Display each file in which the argument symbol appears and whether
2197 // the file defines or references it. This option takes an argument
2198 // as -y<symbol> note that there is no space.
2199 else if ( strncmp(arg
, "-y", 2) == 0 ) {
2202 // Same output as -y, but output <arg> number of undefined symbols only.
2203 else if ( strcmp(arg
, "-Y") == 0 ) {
2204 //warnObsolete(arg);
2207 // This option affects all objects linked into the final result.
2208 else if ( strcmp(arg
, "-m") == 0 ) {
2211 else if ( (strcmp(arg
, "-why_load") == 0) || (strcmp(arg
, "-whyload") == 0) ) {
2212 fReaderOptions
.fWhyLoad
= true;
2214 else if ( strcmp(arg
, "-why_live") == 0 ) {
2215 const char* name
= argv
[++i
];
2217 throw "-why_live missing symbol name argument";
2218 fWhyLive
.insert(name
);
2220 else if ( strcmp(arg
, "-u") == 0 ) {
2221 const char* name
= argv
[++i
];
2223 throw "-u missing argument";
2224 fInitialUndefines
.push_back(name
);
2226 else if ( strcmp(arg
, "-U") == 0 ) {
2227 const char* name
= argv
[++i
];
2229 throw "-U missing argument";
2230 fAllowedUndefined
.insert(name
);
2232 else if ( strcmp(arg
, "-s") == 0 ) {
2234 fLocalSymbolHandling
= kLocalSymbolsNone
;
2235 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
2237 else if ( strcmp(arg
, "-x") == 0 ) {
2238 fLocalSymbolHandling
= kLocalSymbolsNone
;
2240 else if ( strcmp(arg
, "-S") == 0 ) {
2241 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
2243 else if ( strcmp(arg
, "-X") == 0 ) {
2246 else if ( strcmp(arg
, "-Si") == 0 ) {
2248 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoFull
;
2250 else if ( strcmp(arg
, "-b") == 0 ) {
2253 else if ( strcmp(arg
, "-Sn") == 0 ) {
2255 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoFull
;
2257 else if ( strcmp(arg
, "-Sp") == 0 ) {
2260 else if ( strcmp(arg
, "-dead_strip") == 0 ) {
2261 fDeadStrip
= kDeadStripOnPlusUnusedInits
;
2263 else if ( strcmp(arg
, "-no_dead_strip_inits_and_terms") == 0 ) {
2264 fDeadStrip
= kDeadStripOn
;
2266 else if ( strcmp(arg
, "-w") == 0 ) {
2267 // previously handled by buildSearchPaths()
2269 else if ( strcmp(arg
, "-arch_errors_fatal") == 0 ) {
2270 fErrorOnOtherArchFiles
= true;
2272 else if ( strcmp(arg
, "-M") == 0 ) {
2275 else if ( strcmp(arg
, "-headerpad") == 0 ) {
2276 const char* size
= argv
[++i
];
2278 throw "-headerpad missing argument";
2279 fMinimumHeaderPad
= parseAddress(size
);
2281 else if ( strcmp(arg
, "-headerpad_max_install_names") == 0 ) {
2282 fMaxMinimumHeaderPad
= true;
2284 else if ( strcmp(arg
, "-t") == 0 ) {
2285 fReaderOptions
.fLogAllFiles
= true;
2287 else if ( strcmp(arg
, "-whatsloaded") == 0 ) {
2288 fReaderOptions
.fLogObjectFiles
= true;
2290 else if ( strcmp(arg
, "-A") == 0 ) {
2294 else if ( strcmp(arg
, "-umbrella") == 0 ) {
2295 const char* name
= argv
[++i
];
2297 throw "-umbrella missing argument";
2298 fUmbrellaName
= name
;
2300 else if ( strcmp(arg
, "-allowable_client") == 0 ) {
2301 const char* name
= argv
[++i
];
2304 throw "-allowable_client missing argument";
2306 fAllowableClients
.push_back(name
);
2308 else if ( strcmp(arg
, "-client_name") == 0 ) {
2309 const char* name
= argv
[++i
];
2312 throw "-client_name missing argument";
2316 else if ( strcmp(arg
, "-sub_umbrella") == 0 ) {
2317 const char* name
= argv
[++i
];
2319 throw "-sub_umbrella missing argument";
2320 fSubUmbellas
.push_back(name
);
2322 else if ( strcmp(arg
, "-sub_library") == 0 ) {
2323 const char* name
= argv
[++i
];
2325 throw "-sub_library missing argument";
2326 fSubLibraries
.push_back(name
);
2328 else if ( strcmp(arg
, "-init") == 0 ) {
2329 const char* name
= argv
[++i
];
2331 throw "-init missing argument";
2332 fInitFunctionName
= name
;
2334 else if ( strcmp(arg
, "-dot") == 0 ) {
2335 const char* name
= argv
[++i
];
2337 throw "-dot missing argument";
2338 fDotOutputFile
= name
;
2340 else if ( strcmp(arg
, "-warn_commons") == 0 ) {
2341 fWarnCommons
= true;
2343 else if ( strcmp(arg
, "-commons") == 0 ) {
2344 fCommonsMode
= parseCommonsTreatment(argv
[++i
]);
2346 else if ( strcmp(arg
, "-keep_relocs") == 0 ) {
2347 fKeepRelocations
= true;
2349 else if ( strcmp(arg
, "-warn_stabs") == 0 ) {
2352 else if ( strcmp(arg
, "-pause") == 0 ) {
2355 else if ( strcmp(arg
, "-print_statistics") == 0 ) {
2358 else if ( strcmp(arg
, "-d") == 0 ) {
2359 fReaderOptions
.fMakeTentativeDefinitionsReal
= true;
2361 else if ( strcmp(arg
, "-v") == 0 ) {
2362 // previously handled by buildSearchPaths()
2364 else if ( strcmp(arg
, "-Z") == 0 ) {
2365 // previously handled by buildSearchPaths()
2367 else if ( strcmp(arg
, "-syslibroot") == 0 ) {
2369 // previously handled by buildSearchPaths()
2371 else if ( strcmp(arg
, "-no_uuid") == 0 ) {
2372 fUUIDMode
= kUUIDNone
;
2374 else if ( strcmp(arg
, "-random_uuid") == 0 ) {
2375 fUUIDMode
= kUUIDRandom
;
2377 else if ( strcmp(arg
, "-dtrace") == 0 ) {
2378 const char* name
= argv
[++i
];
2380 throw "-dtrace missing argument";
2381 fDtraceScriptName
= name
;
2383 else if ( strcmp(arg
, "-root_safe") == 0 ) {
2384 fReaderOptions
.fRootSafe
= true;
2386 else if ( strcmp(arg
, "-setuid_safe") == 0 ) {
2387 fReaderOptions
.fSetuidSafe
= true;
2389 else if ( strcmp(arg
, "-alias") == 0 ) {
2390 ObjectFile::ReaderOptions::AliasPair pair
;
2391 pair
.realName
= argv
[++i
];
2392 if ( pair
.realName
== NULL
)
2393 throw "missing argument to -alias";
2394 pair
.alias
= argv
[++i
];
2395 if ( pair
.alias
== NULL
)
2396 throw "missing argument to -alias";
2397 fReaderOptions
.fAliases
.push_back(pair
);
2399 else if ( strcmp(arg
, "-alias_list") == 0 ) {
2400 parseAliasFile(argv
[++i
]);
2402 // put this last so that it does not interfer with other options starting with 'i'
2403 else if ( strncmp(arg
, "-i", 2) == 0 ) {
2404 const char* colon
= strchr(arg
, ':');
2405 if ( colon
== NULL
)
2406 throwf("unknown option: %s", arg
);
2407 ObjectFile::ReaderOptions::AliasPair pair
;
2408 char* temp
= new char[colon
-arg
];
2409 strlcpy(temp
, &arg
[2], colon
-arg
-1);
2410 pair
.realName
= &colon
[1];
2412 fReaderOptions
.fAliases
.push_back(pair
);
2414 else if ( strcmp(arg
, "-save-temps") == 0 ) {
2415 fSaveTempFiles
= true;
2417 else if ( strcmp(arg
, "-rpath") == 0 ) {
2418 const char* path
= argv
[++i
];
2420 throw "missing argument to -rpath";
2421 fRPaths
.push_back(path
);
2423 else if ( strcmp(arg
, "-read_only_stubs") == 0 ) {
2424 fReadOnlyx86Stubs
= true;
2426 else if ( strcmp(arg
, "-slow_stubs") == 0 ) {
2429 else if ( strcmp(arg
, "-map") == 0 ) {
2430 fMapPath
= argv
[++i
];
2431 if ( fMapPath
== NULL
)
2432 throw "missing argument to -map";
2434 else if ( strcmp(arg
, "-pie") == 0 ) {
2435 fPositionIndependentExecutable
= true;
2437 else if ( strcmp(arg
, "-no_pie") == 0 ) {
2438 fDisablePositionIndependentExecutable
= true;
2440 else if ( strncmp(arg
, "-reexport-l", 11) == 0 ) {
2441 FileInfo info
= findLibrary(&arg
[11], true);
2442 info
.options
.fReExport
= true;
2445 else if ( strcmp(arg
, "-reexport_library") == 0 ) {
2446 FileInfo info
= findFile(argv
[++i
]);
2447 info
.options
.fReExport
= true;
2450 else if ( strcmp(arg
, "-reexport_framework") == 0 ) {
2451 FileInfo info
= findFramework(argv
[++i
]);
2452 info
.options
.fReExport
= true;
2455 else if ( strcmp(arg
, "-dead_strip_dylibs") == 0 ) {
2456 fDeadStripDylibs
= true;
2458 else if ( strcmp(arg
, "-no_implicit_dylibs") == 0 ) {
2459 fReaderOptions
.fImplicitlyLinkPublicDylibs
= false;
2461 else if ( strcmp(arg
, "-new_linker") == 0 ) {
2464 else if ( strcmp(arg
, "-no_encryption") == 0 ) {
2465 fEncryptable
= false;
2467 else if ( strcmp(arg
, "-no_compact_unwind") == 0 ) {
2468 fReaderOptions
.fAddCompactUnwindEncoding
= false;
2470 else if ( strcmp(arg
, "-mllvm") == 0 ) {
2471 const char* opts
= argv
[++i
];
2473 throw "missing argument to -mllvm";
2474 fLLVMOptions
.push_back(opts
);
2476 else if ( strcmp(arg
, "-no_order_inits") == 0 ) {
2477 fReaderOptions
.fAutoOrderInitializers
= false;
2479 else if ( strcmp(arg
, "-no_order_data") == 0 ) {
2482 else if ( strcmp(arg
, "-seg_page_size") == 0 ) {
2484 seg
.name
= argv
[++i
];
2485 if ( (seg
.name
== NULL
) || (argv
[i
+1] == NULL
) )
2486 throw "-seg_page_size missing segName Adddress";
2487 seg
.size
= parseAddress(argv
[++i
]);
2488 uint64_t temp
= seg
.size
& (-4096); // page align
2489 if ( (seg
.size
!= temp
) )
2490 warning("-seg_page_size %s not 4K aligned, rounding down", seg
.name
);
2491 fCustomSegmentSizes
.push_back(seg
);
2493 else if ( strcmp(arg
, "-mark_dead_strippable_dylib") == 0 ) {
2494 fMarkDeadStrippableDylib
= true;
2496 else if ( strcmp(arg
, "-exported_symbols_order") == 0 ) {
2497 loadSymbolOrderFile(argv
[++i
], fExportSymbolsOrder
);
2499 else if ( strcmp(arg
, "-no_compact_linkedit") == 0 ) {
2500 fMakeCompressedDyldInfo
= false;
2502 else if ( strcmp(arg
, "-no_eh_labels") == 0 ) {
2503 fReaderOptions
.fNoEHLabels
= true;
2505 else if ( strcmp(arg
, "-warn_compact_unwind") == 0 ) {
2506 fReaderOptions
.fWarnCompactUnwind
= true;
2508 else if ( strcmp(arg
, "-allow_sub_type_mismatches") == 0 ) {
2509 fAllowCpuSubtypeMismatches
= true;
2511 else if ( strcmp(arg
, "-no_zero_fill_sections") == 0 ) {
2512 fReaderOptions
.fOptimizeZeroFill
= false;
2514 else if ( strcmp(arg
, "-objc_abi_version") == 0 ) {
2515 const char* version
= argv
[++i
];
2516 if ( version
== NULL
)
2517 throw "-objc_abi_version missing version number";
2518 if ( strcmp(version
, "2") == 0 )
2519 fObjCABIVersion2POverride
= true;
2521 warning("ignoring unrecognized argument (%s) to -objc_abi_version", version
);
2523 else if ( strcmp(arg
, "-demangle") == 0 ) {
2524 // <rdar://problem/8303976> add -demangle noop to ld64-97
2527 throwf("unknown option: %s", arg
);
2531 FileInfo info
= findFile(arg
);
2532 if ( strcmp(&info
.path
[strlen(info
.path
)-2], ".a") == 0 )
2535 fInputFiles
.push_back(info
);
2539 // if a -lazy option was used, implicitly link in lazydylib1.o
2540 if ( fUsingLazyDylibLinking
) {
2541 addLibrary(findLibrary("lazydylib1.o"));
2548 // -syslibroot <path> is used for SDK support.
2549 // The rule is that all search paths (both explicit and default) are
2550 // checked to see if they exist in the SDK. If so, that path is
2551 // replaced with the sdk prefixed path. If not, that search path
2552 // is used as is. If multiple -syslibroot options are specified
2553 // their directory structures are logically overlayed and files
2554 // from sdks specified earlier on the command line used before later ones.
2556 void Options::buildSearchPaths(int argc
, const char* argv
[])
2558 bool addStandardLibraryDirectories
= true;
2559 std::vector
<const char*> libraryPaths
;
2560 std::vector
<const char*> frameworkPaths
;
2561 libraryPaths
.reserve(10);
2562 frameworkPaths
.reserve(10);
2563 // scan through argv looking for -L, -F, -Z, and -syslibroot options
2564 for(int i
=0; i
< argc
; ++i
) {
2565 if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'L') ) {
2566 const char* libSearchDir
= &argv
[i
][2];
2567 if ( libSearchDir
[0] == '\0' )
2568 throw "-L must be immediately followed by a directory path (no space)";
2569 struct stat statbuf
;
2570 if ( stat(libSearchDir
, &statbuf
) == 0 ) {
2571 if ( statbuf
.st_mode
& S_IFDIR
)
2572 libraryPaths
.push_back(libSearchDir
);
2574 warning("path '%s' following -L not a directory", libSearchDir
);
2577 warning("directory '%s' following -L not found", libSearchDir
);
2580 else if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'F') ) {
2581 const char* frameworkSearchDir
= &argv
[i
][2];
2582 if ( frameworkSearchDir
[0] == '\0' )
2583 throw "-F must be immediately followed by a directory path (no space)";
2584 struct stat statbuf
;
2585 if ( stat(frameworkSearchDir
, &statbuf
) == 0 ) {
2586 if ( statbuf
.st_mode
& S_IFDIR
)
2587 frameworkPaths
.push_back(frameworkSearchDir
);
2589 warning("path '%s' following -F not a directory", frameworkSearchDir
);
2592 warning("directory '%s' following -F not found", frameworkSearchDir
);
2595 else if ( strcmp(argv
[i
], "-Z") == 0 )
2596 addStandardLibraryDirectories
= false;
2597 else if ( strcmp(argv
[i
], "-v") == 0 ) {
2599 extern const char ldVersionString
[];
2600 fprintf(stderr
, "%s", ldVersionString
);
2601 // if only -v specified, exit cleanly
2604 printLTOVersion(*this);
2609 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
2610 const char* path
= argv
[++i
];
2612 throw "-syslibroot missing argument";
2613 fSDKPaths
.push_back(path
);
2615 else if ( strcmp(argv
[i
], "-search_paths_first") == 0 ) {
2616 // ??? Deprecate when we get -Bstatic/-Bdynamic.
2617 fLibrarySearchMode
= kSearchDylibAndArchiveInEachDir
;
2619 else if ( strcmp(argv
[i
], "-w") == 0 ) {
2620 sEmitWarnings
= false;
2623 int standardLibraryPathsStartIndex
= libraryPaths
.size();
2624 int standardFrameworkPathsStartIndex
= frameworkPaths
.size();
2625 if ( addStandardLibraryDirectories
) {
2626 libraryPaths
.push_back("/usr/lib");
2627 libraryPaths
.push_back("/usr/local/lib");
2629 frameworkPaths
.push_back("/Library/Frameworks/");
2630 frameworkPaths
.push_back("/System/Library/Frameworks/");
2631 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
2634 // <rdar://problem/5829579> Support for configure based hacks
2635 // if last -syslibroot is /, then ignore all syslibroots
2636 if ( fSDKPaths
.size() > 0 ) {
2637 if ( strcmp(fSDKPaths
.back(), "/") == 0 ) {
2642 // now merge sdk and library paths to make real search paths
2643 fLibrarySearchPaths
.reserve(libraryPaths
.size()*(fSDKPaths
.size()+1));
2645 for (std::vector
<const char*>::iterator it
= libraryPaths
.begin(); it
!= libraryPaths
.end(); ++it
, ++libIndex
) {
2646 const char* libDir
= *it
;
2647 bool sdkOverride
= false;
2648 if ( libDir
[0] == '/' ) {
2649 char betterLibDir
[PATH_MAX
];
2650 if ( strstr(libDir
, "/..") != NULL
) {
2651 if ( realpath(libDir
, betterLibDir
) != NULL
)
2652 libDir
= strdup(betterLibDir
);
2654 const int libDirLen
= strlen(libDir
);
2655 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
2656 const char* sdkDir
= *sdkit
;
2657 const int sdkDirLen
= strlen(sdkDir
);
2658 char newPath
[libDirLen
+ sdkDirLen
+4];
2659 strcpy(newPath
, sdkDir
);
2660 if ( newPath
[sdkDirLen
-1] == '/' )
2661 newPath
[sdkDirLen
-1] = '\0';
2662 strcat(newPath
, libDir
);
2663 struct stat statBuffer
;
2664 if ( stat(newPath
, &statBuffer
) == 0 ) {
2665 fLibrarySearchPaths
.push_back(strdup(newPath
));
2670 if ( !sdkOverride
) {
2671 if ( (libIndex
>= standardLibraryPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
2672 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2673 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2676 fLibrarySearchPaths
.push_back(libDir
);
2681 // now merge sdk and framework paths to make real search paths
2682 fFrameworkSearchPaths
.reserve(frameworkPaths
.size()*(fSDKPaths
.size()+1));
2684 for (std::vector
<const char*>::iterator it
= frameworkPaths
.begin(); it
!= frameworkPaths
.end(); ++it
, ++frameIndex
) {
2685 const char* frameworkDir
= *it
;
2686 bool sdkOverride
= false;
2687 if ( frameworkDir
[0] == '/' ) {
2688 char betterFrameworkDir
[PATH_MAX
];
2689 if ( strstr(frameworkDir
, "/..") != NULL
) {
2690 if ( realpath(frameworkDir
, betterFrameworkDir
) != NULL
)
2691 frameworkDir
= strdup(betterFrameworkDir
);
2693 const int frameworkDirLen
= strlen(frameworkDir
);
2694 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
2695 const char* sdkDir
= *sdkit
;
2696 const int sdkDirLen
= strlen(sdkDir
);
2697 char newPath
[frameworkDirLen
+ sdkDirLen
+4];
2698 strcpy(newPath
, sdkDir
);
2699 if ( newPath
[sdkDirLen
-1] == '/' )
2700 newPath
[sdkDirLen
-1] = '\0';
2701 strcat(newPath
, frameworkDir
);
2702 struct stat statBuffer
;
2703 if ( stat(newPath
, &statBuffer
) == 0 ) {
2704 fFrameworkSearchPaths
.push_back(strdup(newPath
));
2709 if ( !sdkOverride
) {
2710 if ( (frameIndex
>= standardFrameworkPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
2711 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2712 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2715 fFrameworkSearchPaths
.push_back(frameworkDir
);
2721 fprintf(stderr
,"Library search paths:\n");
2722 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
2723 it
!= fLibrarySearchPaths
.end();
2725 fprintf(stderr
,"\t%s\n", *it
);
2726 fprintf(stderr
,"Framework search paths:\n");
2727 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
2728 it
!= fFrameworkSearchPaths
.end();
2730 fprintf(stderr
,"\t%s\n", *it
);
2734 // this is run before the command line is parsed
2735 void Options::parsePreCommandLineEnvironmentSettings()
2737 if ((getenv("LD_TRACE_ARCHIVES") != NULL
)
2738 || (getenv("RC_TRACE_ARCHIVES") != NULL
))
2739 fReaderOptions
.fTraceArchives
= true;
2741 if ((getenv("LD_TRACE_DYLIBS") != NULL
)
2742 || (getenv("RC_TRACE_DYLIBS") != NULL
)) {
2743 fReaderOptions
.fTraceDylibs
= true;
2744 fReaderOptions
.fTraceIndirectDylibs
= true;
2747 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL
) {
2748 fTraceDylibSearching
= true;
2751 if (getenv("LD_PRINT_OPTIONS") != NULL
)
2752 fPrintOptions
= true;
2754 if (fReaderOptions
.fTraceDylibs
|| fReaderOptions
.fTraceArchives
)
2755 fReaderOptions
.fTraceOutputFile
= getenv("LD_TRACE_FILE");
2757 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL
)
2758 fPrintOrderFileStatistics
= true;
2760 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL
)
2763 if (getenv("LD_NO_ENCRYPT") != NULL
)
2764 fEncryptable
= false;
2766 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL
)
2767 fAllowCpuSubtypeMismatches
= true;
2769 // for now disable compressed linkedit functionality
2770 if ( getenv("LD_NO_COMPACT_LINKEDIT") != NULL
) {
2771 fMakeCompressedDyldInfo
= false;
2772 fMakeClassicDyldInfo
= true;
2774 // temporary until projects adopt -no_pie
2775 if ( getenv("LD_NO_PIE") != NULL
) {
2776 warning("LD_NO_PIE being used to disble building a position independent executable");
2777 fDisablePositionIndependentExecutable
= true;
2780 sWarningsSideFilePath
= getenv("LD_WARN_FILE");
2784 // this is run after the command line is parsed
2785 void Options::parsePostCommandLineEnvironmentSettings()
2787 // when building a dynamic main executable, default any use of @executable_path to output path
2788 if ( fExecutablePath
== NULL
&& (fOutputKind
== kDynamicExecutable
) ) {
2789 fExecutablePath
= fOutputFile
;
2792 // allow build system to set default seg_addr_table
2793 if ( fSegAddrTablePath
== NULL
)
2794 fSegAddrTablePath
= getenv("LD_SEG_ADDR_TABLE");
2796 // allow build system to turn on prebinding
2798 fPrebind
= ( getenv("LD_PREBIND") != NULL
);
2801 // allow build system to force on dead-code-stripping
2802 if ( fDeadStrip
== kDeadStripOff
) {
2803 if ( getenv("LD_DEAD_STRIP") != NULL
) {
2804 switch (fOutputKind
) {
2805 case Options::kDynamicLibrary
:
2806 case Options::kDynamicExecutable
:
2807 case Options::kDynamicBundle
:
2808 fDeadStrip
= kDeadStripOn
;
2810 case Options::kPreload
:
2811 case Options::kObjectFile
:
2812 case Options::kDyld
:
2813 case Options::kStaticExecutable
:
2814 case Options::kKextBundle
:
2820 // allow build system to force on -warn_commons
2821 if ( getenv("LD_WARN_COMMONS") != NULL
)
2822 fWarnCommons
= true;
2826 void Options::reconfigureDefaults()
2828 // sync reader options
2829 switch ( fOutputKind
) {
2830 case Options::kObjectFile
:
2831 fReaderOptions
.fForFinalLinkedImage
= false;
2833 case Options::kDyld
:
2834 fReaderOptions
.fForDyld
= true;
2835 fReaderOptions
.fForFinalLinkedImage
= true;
2836 fReaderOptions
.fNoEHLabels
= true;
2838 case Options::kDynamicLibrary
:
2839 case Options::kDynamicBundle
:
2840 case Options::kKextBundle
:
2841 fReaderOptions
.fForFinalLinkedImage
= true;
2842 fReaderOptions
.fNoEHLabels
= true;
2844 case Options::kDynamicExecutable
:
2845 case Options::kStaticExecutable
:
2846 case Options::kPreload
:
2847 fReaderOptions
.fLinkingMainExecutable
= true;
2848 fReaderOptions
.fForFinalLinkedImage
= true;
2849 fReaderOptions
.fNoEHLabels
= true;
2853 // set default min OS version
2854 if ( (fReaderOptions
.fMacVersionMin
== ObjectFile::ReaderOptions::kMinMacVersionUnset
)
2855 && (fReaderOptions
.fIPhoneVersionMin
== ObjectFile::ReaderOptions::kMinIPhoneVersionUnset
) ) {
2856 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
2857 const char* macVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
2858 const char* iPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
2859 if ( macVers
!= NULL
)
2860 setMacOSXVersionMin(macVers
);
2861 else if ( iPhoneVers
!= NULL
)
2862 setIPhoneVersionMin(iPhoneVers
);
2864 // if still nothing, set default based on architecture
2865 switch ( fArchitecture
) {
2867 case CPU_TYPE_X86_64
:
2868 case CPU_TYPE_POWERPC
:
2869 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_6
; // FIX FIX, this really should be a check of the OS version the linker is running o
2872 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_0
;
2879 // adjust min based on architecture
2880 switch ( fArchitecture
) {
2882 if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_4
) {
2883 //warning("-macosx_version_min should be 10.4 or later for i386");
2884 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_4
;
2887 case CPU_TYPE_POWERPC64
:
2888 if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_4
) {
2889 //warning("-macosx_version_min should be 10.4 or later for ppc64");
2890 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_4
;
2893 case CPU_TYPE_X86_64
:
2894 if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_4
) {
2895 //warning("-macosx_version_min should be 10.4 or later for x86_64");
2896 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_4
;
2901 // adjust kext type based on architecture
2902 if ( fOutputKind
== kKextBundle
) {
2903 switch ( fArchitecture
) {
2904 case CPU_TYPE_X86_64
:
2905 // x86_64 uses new MH_KEXT_BUNDLE type
2906 fMakeClassicDyldInfo
= true;
2907 fMakeCompressedDyldInfo
= false;
2908 fAllowTextRelocs
= true;
2909 fUndefinedTreatment
= kUndefinedDynamicLookup
;
2911 case CPU_TYPE_POWERPC
:
2915 fOutputKind
= kObjectFile
;
2920 // disable implicit dylibs when targeting 10.3
2921 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
2922 if ( !minOS(ObjectFile::ReaderOptions::k10_4
, ObjectFile::ReaderOptions::k2_0
) )
2923 fReaderOptions
.fImplicitlyLinkPublicDylibs
= false;
2926 // allow build system to force linker to ignore -prebind
2927 if ( getenv("LD_FORCE_NO_PREBIND") != NULL
)
2930 // allow build system to force linker to ignore -seg_addr_table
2931 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL
)
2932 fSegAddrTablePath
= NULL
;
2934 // check for base address specified externally
2935 if ( (fSegAddrTablePath
!= NULL
) && (fOutputKind
== Options::kDynamicLibrary
) ) {
2936 parseSegAddrTable(fSegAddrTablePath
, this->installPath());
2937 // HACK to support seg_addr_table entries that are physical paths instead of install paths
2938 if ( fBaseAddress
== 0 ) {
2939 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
2940 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.4.dylib");
2941 if ( fBaseAddress
== 0 )
2942 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.9.dylib");
2945 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
2946 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libz.1.2.3.dylib");
2948 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
2949 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libutil1.0.dylib");
2953 // split segs only allowed for dylibs
2955 // split seg only supported for ppc, i386, and arm.
2956 switch ( fArchitecture
) {
2957 case CPU_TYPE_POWERPC
:
2959 if ( fOutputKind
!= Options::kDynamicLibrary
)
2961 // make sure read and write segments are proper distance apart
2962 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x10000000) )
2963 fBaseWritableAddress
= fBaseAddress
+ 0x10000000;
2966 if ( fOutputKind
!= Options::kDynamicLibrary
) {
2970 // make sure read and write segments are proper distance apart
2971 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x08000000) )
2972 fBaseWritableAddress
= fBaseAddress
+ 0x08000000;
2978 fBaseWritableAddress
= 0;
2982 // <rdar://problem/6138961> -r implies no prebinding for all architectures
2983 if ( fOutputKind
== Options::kObjectFile
)
2986 // disable prebinding depending on arch and min OS version
2988 switch ( fArchitecture
) {
2989 case CPU_TYPE_POWERPC
:
2991 if ( fReaderOptions
.fMacVersionMin
== ObjectFile::ReaderOptions::k10_4
) {
2992 // in 10.4 only split seg dylibs are prebound
2993 if ( (fOutputKind
!= Options::kDynamicLibrary
) || ! fSplitSegs
)
2996 else if ( fReaderOptions
.fMacVersionMin
>= ObjectFile::ReaderOptions::k10_5
) {
2997 // in 10.5 nothing is prebound
3001 // in 10.3 and earlier only dylibs and main executables could be prebound
3002 switch ( fOutputKind
) {
3003 case Options::kDynamicExecutable
:
3004 case Options::kDynamicLibrary
:
3005 // only main executables and dylibs can be prebound
3007 case Options::kStaticExecutable
:
3008 case Options::kDynamicBundle
:
3009 case Options::kObjectFile
:
3010 case Options::kDyld
:
3011 case Options::kPreload
:
3012 case Options::kKextBundle
:
3013 // disable prebinding for everything else
3019 case CPU_TYPE_POWERPC64
:
3020 case CPU_TYPE_X86_64
:
3024 switch ( fOutputKind
) {
3025 case Options::kDynamicExecutable
:
3026 case Options::kDynamicLibrary
:
3027 // only main executables and dylibs can be prebound
3029 case Options::kStaticExecutable
:
3030 case Options::kDynamicBundle
:
3031 case Options::kObjectFile
:
3032 case Options::kDyld
:
3033 case Options::kPreload
:
3034 case Options::kKextBundle
:
3035 // disable prebinding for everything else
3043 // only prebound images can be split-seg
3044 if ( fSplitSegs
&& !fPrebind
)
3047 // determine if info for shared region should be added
3048 if ( fOutputKind
== Options::kDynamicLibrary
) {
3049 if ( minOS(ObjectFile::ReaderOptions::k10_5
, ObjectFile::ReaderOptions::k3_1
) )
3051 if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
3052 || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
3053 fSharedRegionEligible
= true;
3056 // figure out if module table is needed for compatibility with old ld/dyld
3057 if ( fOutputKind
== Options::kDynamicLibrary
) {
3058 switch ( fArchitecture
) {
3059 case CPU_TYPE_POWERPC
: // 10.3 and earlier dyld requires a module table
3060 case CPU_TYPE_I386
: // ld_classic for 10.4.x requires a module table
3061 if ( fReaderOptions
.fMacVersionMin
<= ObjectFile::ReaderOptions::k10_5
)
3062 fNeedsModuleTable
= true;
3066 fNeedsModuleTable
= true; // redo_prebinding requires a module table
3071 // <rdar://problem/5366363> -r -x implies -S
3072 if ( (fOutputKind
== Options::kObjectFile
) && (fLocalSymbolHandling
== kLocalSymbolsNone
) )
3073 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
3075 // choose how to process unwind info
3076 switch ( fArchitecture
) {
3078 case CPU_TYPE_X86_64
:
3079 switch ( fOutputKind
) {
3080 case Options::kObjectFile
:
3081 case Options::kStaticExecutable
:
3082 case Options::kPreload
:
3083 case Options::kKextBundle
:
3084 fReaderOptions
.fAddCompactUnwindEncoding
= false;
3086 case Options::kDyld
:
3087 case Options::kDynamicLibrary
:
3088 case Options::kDynamicBundle
:
3089 case Options::kDynamicExecutable
:
3090 //if ( fReaderOptions.fAddCompactUnwindEncoding && (fReaderOptions.fVersionMin >= ObjectFile::ReaderOptions::k10_6) )
3091 // fReaderOptions.fRemoveDwarfUnwindIfCompactExists = true;
3095 case CPU_TYPE_POWERPC
:
3096 case CPU_TYPE_POWERPC64
:
3098 fReaderOptions
.fAddCompactUnwindEncoding
= false;
3099 fReaderOptions
.fRemoveDwarfUnwindIfCompactExists
= false;
3102 // if -arch is missing, assume we don't want compact unwind info
3103 fReaderOptions
.fAddCompactUnwindEncoding
= false;
3107 // only ARM main executables can be encrypted
3108 if ( fOutputKind
!= Options::kDynamicExecutable
)
3109 fEncryptable
= false;
3110 if ( fArchitecture
!= CPU_TYPE_ARM
)
3111 fEncryptable
= false;
3113 // don't move inits in dyld because dyld wants certain
3114 // entries point at stable locations at the start of __text
3115 if ( fOutputKind
== Options::kDyld
)
3116 fReaderOptions
.fAutoOrderInitializers
= false;
3119 // disable __data ordering for some output kinds
3120 switch ( fOutputKind
) {
3121 case Options::kObjectFile
:
3122 case Options::kDyld
:
3123 case Options::kStaticExecutable
:
3124 case Options::kPreload
:
3125 case Options::kKextBundle
:
3128 case Options::kDynamicExecutable
:
3129 case Options::kDynamicLibrary
:
3130 case Options::kDynamicBundle
:
3134 // only use compressed LINKEDIT for:
3135 // x86_64 and i386 on Mac OS X 10.6 or later
3136 // arm on iPhoneOS 3.1 or later
3137 if ( fMakeCompressedDyldInfo
) {
3138 switch (fArchitecture
) {
3140 case CPU_TYPE_X86_64
:
3141 if ( fReaderOptions
.fMacVersionMin
>= ObjectFile::ReaderOptions::k10_6
)
3142 fMakeClassicDyldInfo
= false;
3143 else if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_5
)
3144 fMakeCompressedDyldInfo
= false;
3147 if ( fReaderOptions
.fIPhoneVersionMin
>= ObjectFile::ReaderOptions::k3_1
)
3148 fMakeClassicDyldInfo
= false;
3149 else if ( fReaderOptions
.fIPhoneVersionMin
< ObjectFile::ReaderOptions::k3_1
)
3150 fMakeCompressedDyldInfo
= false;
3152 case CPU_TYPE_POWERPC
:
3153 case CPU_TYPE_POWERPC64
:
3155 fMakeCompressedDyldInfo
= false;
3160 // only use compressed LINKEDIT for final linked images
3161 if ( fMakeCompressedDyldInfo
) {
3162 switch ( fOutputKind
) {
3163 case Options::kDynamicExecutable
:
3164 case Options::kDynamicLibrary
:
3165 case Options::kDynamicBundle
:
3167 case Options::kPreload
:
3168 case Options::kStaticExecutable
:
3169 case Options::kObjectFile
:
3170 case Options::kDyld
:
3171 case Options::kKextBundle
:
3172 fMakeCompressedDyldInfo
= false;
3176 fReaderOptions
.fMakeCompressedDyldInfo
= fMakeCompressedDyldInfo
;
3178 // only ARM enforces that cpu-sub-types must match
3179 if ( fArchitecture
!= CPU_TYPE_ARM
)
3180 fAllowCpuSubtypeMismatches
= true;
3182 // only final linked images can not optimize zero fill sections
3183 if ( fOutputKind
== Options::kObjectFile
)
3184 fReaderOptions
.fOptimizeZeroFill
= true;
3186 // only dynamic final linked images should warn about use of commmons
3187 if ( fWarnCommons
) {
3188 switch ( fOutputKind
) {
3189 case Options::kDynamicExecutable
:
3190 case Options::kDynamicLibrary
:
3191 case Options::kDynamicBundle
:
3193 case Options::kPreload
:
3194 case Options::kStaticExecutable
:
3195 case Options::kObjectFile
:
3196 case Options::kDyld
:
3197 case Options::kKextBundle
:
3198 fWarnCommons
= false;
3203 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
3204 if ( minOS(ObjectFile::ReaderOptions::k10_5
, ObjectFile::ReaderOptions::k2_0
) )
3205 fUseSimplifiedDylibReExports
= true;
3207 // x86_64 for MacOSX 10.7 defaults to PIE
3208 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
== kDynamicExecutable
)
3209 && (fReaderOptions
.fMacVersionMin
>= ObjectFile::ReaderOptions::k10_7
) ) {
3210 fPositionIndependentExecutable
= true;
3214 void Options::checkIllegalOptionCombinations()
3216 // check -undefined setting
3217 switch ( fUndefinedTreatment
) {
3218 case kUndefinedError
:
3219 case kUndefinedDynamicLookup
:
3222 case kUndefinedWarning
:
3223 case kUndefinedSuppress
:
3224 // requires flat namespace
3225 if ( fNameSpace
== kTwoLevelNameSpace
)
3226 throw "can't use -undefined warning or suppress with -twolevel_namespace";
3230 // unify -sub_umbrella with dylibs
3231 for (std::vector
<const char*>::iterator it
= fSubUmbellas
.begin(); it
!= fSubUmbellas
.end(); it
++) {
3232 const char* subUmbrella
= *it
;
3234 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
3235 Options::FileInfo
& info
= *fit
;
3236 const char* lastSlash
= strrchr(info
.path
, '/');
3237 if ( lastSlash
== NULL
)
3238 lastSlash
= info
.path
- 1;
3239 if ( strcmp(&lastSlash
[1], subUmbrella
) == 0 ) {
3240 info
.options
.fReExport
= true;
3246 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella
);
3249 // unify -sub_library with dylibs
3250 for (std::vector
<const char*>::iterator it
= fSubLibraries
.begin(); it
!= fSubLibraries
.end(); it
++) {
3251 const char* subLibrary
= *it
;
3253 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
3254 Options::FileInfo
& info
= *fit
;
3255 const char* lastSlash
= strrchr(info
.path
, '/');
3256 if ( lastSlash
== NULL
)
3257 lastSlash
= info
.path
- 1;
3258 const char* dot
= strchr(&lastSlash
[1], '.');
3260 dot
= &lastSlash
[strlen(lastSlash
)];
3261 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
3262 info
.options
.fReExport
= true;
3268 warning("-sub_library %s does not match a supplied dylib", subLibrary
);
3271 // sync reader options
3272 if ( fNameSpace
!= kTwoLevelNameSpace
)
3273 fReaderOptions
.fFlatNamespace
= true;
3275 // check -stack_addr
3276 if ( fStackAddr
!= 0 ) {
3277 switch (fArchitecture
) {
3279 case CPU_TYPE_POWERPC
:
3281 if ( fStackAddr
> 0xFFFFFFFF )
3282 throw "-stack_addr must be < 4G for 32-bit processes";
3284 case CPU_TYPE_POWERPC64
:
3285 case CPU_TYPE_X86_64
:
3288 if ( (fStackAddr
& -4096) != fStackAddr
)
3289 throw "-stack_addr must be multiples of 4K";
3290 if ( fStackSize
== 0 )
3291 throw "-stack_addr must be used with -stack_size";
3294 // check -stack_size
3295 if ( fStackSize
!= 0 ) {
3296 switch (fArchitecture
) {
3298 case CPU_TYPE_POWERPC
:
3299 if ( fStackSize
> 0xFFFFFFFF )
3300 throw "-stack_size must be < 4G for 32-bit processes";
3301 if ( fStackAddr
== 0 ) {
3302 fStackAddr
= 0xC0000000;
3304 if ( (fStackAddr
> 0xB0000000) && ((fStackAddr
-fStackSize
) < 0xB0000000) )
3305 warning("custom stack placement overlaps and will disable shared region");
3308 if ( fStackSize
> 0x2F000000 )
3309 throw "-stack_size must be < 752MB";
3310 if ( fStackAddr
== 0 )
3311 fStackAddr
= 0x2F000000;
3312 if ( fStackAddr
> 0x30000000)
3313 throw "-stack_addr must be < 0x30000000 for arm";
3314 case CPU_TYPE_POWERPC64
:
3315 case CPU_TYPE_X86_64
:
3316 if ( fStackAddr
== 0 ) {
3317 fStackAddr
= 0x00007FFF5C000000LL
;
3321 if ( (fStackSize
& -4096) != fStackSize
)
3322 throw "-stack_size must be multiples of 4K";
3323 switch ( fOutputKind
) {
3324 case Options::kDynamicExecutable
:
3325 case Options::kStaticExecutable
:
3326 // custom stack size only legal when building main executable
3328 case Options::kDynamicLibrary
:
3329 case Options::kDynamicBundle
:
3330 case Options::kObjectFile
:
3331 case Options::kDyld
:
3332 case Options::kPreload
:
3333 case Options::kKextBundle
:
3334 throw "-stack_size option can only be used when linking a main executable";
3338 // check that -allow_stack_execute is only used with main executables
3339 if ( fExecutableStack
) {
3340 switch ( fOutputKind
) {
3341 case Options::kDynamicExecutable
:
3342 case Options::kStaticExecutable
:
3343 // -allow_stack_execute size only legal when building main executable
3345 case Options::kDynamicLibrary
:
3346 case Options::kDynamicBundle
:
3347 case Options::kObjectFile
:
3348 case Options::kDyld
:
3349 case Options::kPreload
:
3350 case Options::kKextBundle
:
3351 throw "-allow_stack_execute option can only be used when linking a main executable";
3355 // check -client_name is only used when making a bundle or main executable
3356 if ( fClientName
!= NULL
) {
3357 switch ( fOutputKind
) {
3358 case Options::kDynamicExecutable
:
3359 case Options::kDynamicBundle
:
3361 case Options::kStaticExecutable
:
3362 case Options::kDynamicLibrary
:
3363 case Options::kObjectFile
:
3364 case Options::kDyld
:
3365 case Options::kPreload
:
3366 case Options::kKextBundle
:
3367 throw "-client_name can only be used with -bundle";
3371 // check -init is only used when building a dylib
3372 if ( (fInitFunctionName
!= NULL
) && (fOutputKind
!= Options::kDynamicLibrary
) )
3373 throw "-init can only be used with -dynamiclib";
3375 // check -bundle_loader only used with -bundle
3376 if ( (fBundleLoader
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
3377 throw "-bundle_loader can only be used with -bundle";
3379 // check -dtrace not used with -r
3380 if ( (fDtraceScriptName
!= NULL
) && (fOutputKind
== Options::kObjectFile
) )
3381 throw "-dtrace can only be used when creating final linked images";
3383 // check -d can only be used with -r
3384 if ( fReaderOptions
.fMakeTentativeDefinitionsReal
&& (fOutputKind
!= Options::kObjectFile
) )
3385 throw "-d can only be used with -r";
3387 // check that -root_safe is not used with -r
3388 if ( fReaderOptions
.fRootSafe
&& (fOutputKind
== Options::kObjectFile
) )
3389 throw "-root_safe cannot be used with -r";
3391 // check that -setuid_safe is not used with -r
3392 if ( fReaderOptions
.fSetuidSafe
&& (fOutputKind
== Options::kObjectFile
) )
3393 throw "-setuid_safe cannot be used with -r";
3395 // make sure all required exported symbols exist
3396 std::vector
<const char*> impliedExports
;
3397 for (NameSet::iterator it
=fExportSymbols
.regularBegin(); it
!= fExportSymbols
.regularEnd(); it
++) {
3398 const char* name
= *it
;
3399 // never export .eh symbols
3400 const int len
= strlen(name
);
3401 if ( (strcmp(&name
[len
-3], ".eh") == 0) || (strncmp(name
, ".objc_category_name_", 20) == 0) )
3402 warning("ignoring %s in export list", name
);
3404 fInitialUndefines
.push_back(name
);
3405 if ( strncmp(name
, ".objc_class_name_", 17) == 0 ) {
3406 // rdar://problem/4718189 map ObjC class names to new runtime names
3407 switch (fArchitecture
) {
3409 // i386 only uses new symbols when using objc2 ABI
3410 if ( !fObjCABIVersion2POverride
)
3412 // when using objc2 ABI to same as archs below
3413 case CPU_TYPE_POWERPC64
:
3414 case CPU_TYPE_X86_64
:
3417 asprintf(&temp
, "_OBJC_CLASS_$_%s", &name
[17]);
3418 impliedExports
.push_back(temp
);
3419 asprintf(&temp
, "_OBJC_METACLASS_$_%s", &name
[17]);
3420 impliedExports
.push_back(temp
);
3425 for (std::vector
<const char*>::iterator it
=impliedExports
.begin(); it
!= impliedExports
.end(); it
++) {
3426 const char* name
= *it
;
3427 fExportSymbols
.insert(name
);
3428 fInitialUndefines
.push_back(name
);
3431 // make sure that -init symbol exist
3432 if ( fInitFunctionName
!= NULL
)
3433 fInitialUndefines
.push_back(fInitFunctionName
);
3435 // check custom segments
3436 if ( fCustomSegmentAddresses
.size() != 0 ) {
3437 // verify no segment is in zero page
3438 if ( fZeroPageSize
!= ULLONG_MAX
) {
3439 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
3440 if ( (it
->address
>= 0) && (it
->address
< fZeroPageSize
) )
3441 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it
->name
, it
->address
);
3444 // verify no duplicates
3445 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
3446 for (std::vector
<SegmentStart
>::iterator it2
= fCustomSegmentAddresses
.begin(); it2
!= fCustomSegmentAddresses
.end(); ++it2
) {
3447 if ( (it
->address
== it2
->address
) && (it
!= it2
) )
3448 throwf("duplicate -segaddr addresses for %s and %s", it
->name
, it2
->name
);
3450 // a custom segment address of zero will disable the use of a zero page
3451 if ( it
->address
== 0 )
3456 if ( fZeroPageSize
== ULLONG_MAX
) {
3457 // zero page size not specified on command line, set default
3458 switch (fArchitecture
) {
3460 case CPU_TYPE_POWERPC
:
3462 // first 4KB for 32-bit architectures
3463 fZeroPageSize
= 0x1000;
3465 case CPU_TYPE_POWERPC64
:
3466 // first 4GB for ppc64 on 10.5
3467 if ( fReaderOptions
.fMacVersionMin
>= ObjectFile::ReaderOptions::k10_5
)
3468 fZeroPageSize
= 0x100000000ULL
;
3470 fZeroPageSize
= 0x1000; // 10.4 dyld may not be able to handle >4GB zero page
3472 case CPU_TYPE_X86_64
:
3473 // first 4GB for x86_64 on all OS's
3474 fZeroPageSize
= 0x100000000ULL
;
3477 // if -arch not used, default to 4K zero-page
3478 fZeroPageSize
= 0x1000;
3482 switch ( fOutputKind
) {
3483 case Options::kDynamicExecutable
:
3484 case Options::kStaticExecutable
:
3485 // -pagezero_size size only legal when building main executable
3487 case Options::kDynamicLibrary
:
3488 case Options::kDynamicBundle
:
3489 case Options::kObjectFile
:
3490 case Options::kDyld
:
3491 case Options::kPreload
:
3492 case Options::kKextBundle
:
3493 if ( fZeroPageSize
!= 0 )
3494 throw "-pagezero_size option can only be used when linking a main executable";
3498 // -dead_strip and -r are incompatible
3499 if ( (fDeadStrip
!= kDeadStripOff
) && (fOutputKind
== Options::kObjectFile
) )
3500 throw "-r and -dead_strip cannot be used together";
3502 // can't use -rpath unless targeting 10.5 or later
3503 if ( fRPaths
.size() > 0 ) {
3504 if ( !minOS(ObjectFile::ReaderOptions::k10_5
, ObjectFile::ReaderOptions::k2_0
) )
3505 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
3506 switch ( fOutputKind
) {
3507 case Options::kDynamicExecutable
:
3508 case Options::kDynamicLibrary
:
3509 case Options::kDynamicBundle
:
3511 case Options::kStaticExecutable
:
3512 case Options::kObjectFile
:
3513 case Options::kDyld
:
3514 case Options::kPreload
:
3515 case Options::kKextBundle
:
3516 throw "-rpath can only be used when creating a dynamic final linked image";
3520 // check -pie is only used when building a dynamic main executable for 10.5
3521 if ( fPositionIndependentExecutable
) {
3522 switch ( fOutputKind
) {
3523 case Options::kDynamicExecutable
:
3524 // -no_pie anywhere on command line disable PIE
3525 if ( fDisablePositionIndependentExecutable
)
3526 fPositionIndependentExecutable
= false;
3528 case Options::kPreload
:
3530 case Options::kDynamicLibrary
:
3531 case Options::kDynamicBundle
:
3532 warning("-pie being ignored. It is only used when linking a main executable");
3534 case Options::kStaticExecutable
:
3535 case Options::kObjectFile
:
3536 case Options::kDyld
:
3537 case Options::kKextBundle
:
3538 throw "-pie can only be used when linking a main executable";
3540 if ( !minOS(ObjectFile::ReaderOptions::k10_5
, ObjectFile::ReaderOptions::k2_0
) )
3541 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
3544 // check -read_only_relocs is not used with x86_64
3545 if ( fAllowTextRelocs
) {
3546 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
!= kKextBundle
) ) {
3547 warning("-read_only_relocs cannot be used with x86_64");
3548 fAllowTextRelocs
= false;
3552 // check -mark_auto_dead_strip is only used with dylibs
3553 if ( fMarkDeadStrippableDylib
) {
3554 if ( fOutputKind
!= Options::kDynamicLibrary
) {
3555 warning("-mark_auto_dead_strip can only be used when creating a dylib");
3556 fMarkDeadStrippableDylib
= false;
3560 // -force_cpusubtype_ALL is not supported for ARM
3561 if ( fForceSubtypeAll
) {
3562 if ( fArchitecture
== CPU_TYPE_ARM
) {
3563 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
3569 void Options::checkForClassic(int argc
, const char* argv
[])
3572 bool archFound
= false;
3573 bool staticFound
= false;
3574 bool dtraceFound
= false;
3575 bool kextFound
= false;
3576 bool rFound
= false;
3577 bool creatingMachKernel
= false;
3578 bool newLinker
= false;
3580 // build command line buffer in case ld crashes
3581 for(int i
=1; i
< argc
; ++i
) {
3582 strlcat(crashreporterBuffer
, argv
[i
], 1000);
3583 strlcat(crashreporterBuffer
, " ", 1000);
3586 for(int i
=0; i
< argc
; ++i
) {
3587 const char* arg
= argv
[i
];
3588 if ( arg
[0] == '-' ) {
3589 if ( strcmp(arg
, "-arch") == 0 ) {
3590 parseArch(argv
[++i
]);
3593 else if ( strcmp(arg
, "-static") == 0 ) {
3596 else if ( strcmp(arg
, "-kext") == 0 ) {
3599 else if ( strcmp(arg
, "-dtrace") == 0 ) {
3602 else if ( strcmp(arg
, "-r") == 0 ) {
3605 else if ( strcmp(arg
, "-new_linker") == 0 ) {
3608 else if ( strcmp(arg
, "-classic_linker") == 0 ) {
3609 // ld_classic does not understand this option, so remove it
3610 for(int j
=i
; j
< argc
; ++j
)
3611 argv
[j
] = argv
[j
+1];
3612 this->gotoClassicLinker(argc
-1, argv
);
3614 else if ( strcmp(arg
, "-o") == 0 ) {
3615 const char* outfile
= argv
[++i
];
3616 if ( (outfile
!= NULL
) && (strstr(outfile
, "/mach_kernel") != NULL
) )
3617 creatingMachKernel
= true;
3622 // -dtrace only supported by new linker
3627 switch ( fArchitecture
) {
3628 case CPU_TYPE_POWERPC
:
3631 // if ( staticFound && (rFound || !creatingMachKernel) ) {
3632 if ( (staticFound
|| kextFound
) && !newLinker
) {
3633 // this environment variable will disable use of ld_classic for -static links
3634 if ( getenv("LD_NO_CLASSIC_LINKER_STATIC") == NULL
) {
3635 // ld_classic does not support -iphoneos_version_min, so change
3636 for(int j
=0; j
< argc
; ++j
) {
3637 if ( strcmp(argv
[j
], "-iphoneos_version_min") == 0) {
3638 argv
[j
] = "-macosx_version_min";
3644 // ld classic does not understand -kext (change to -static -r)
3646 for(int j
=0; j
< argc
; ++j
) {
3647 if ( strcmp(argv
[j
], "-kext") == 0)
3649 else if ( strcmp(argv
[j
], "-dynamic") == 0)
3650 argv
[j
] = "-static";
3653 this->gotoClassicLinker(argc
, argv
);
3660 // work around for VSPTool
3662 this->gotoClassicLinker(argc
, argv
);
3667 void Options::gotoClassicLinker(int argc
, const char* argv
[])
3669 argv
[0] = "ld_classic";
3670 char rawPath
[PATH_MAX
];
3671 char path
[PATH_MAX
];
3672 uint32_t bufSize
= PATH_MAX
;
3673 if ( _NSGetExecutablePath(rawPath
, &bufSize
) != -1 ) {
3674 if ( realpath(rawPath
, path
) != NULL
) {
3675 char* lastSlash
= strrchr(path
, '/');
3676 if ( lastSlash
!= NULL
) {
3677 strcpy(lastSlash
+1, "ld_classic");
3679 execvp(path
, (char**)argv
);
3683 // in case of error in above, try searching for ld_classic via PATH
3684 execvp(argv
[0], (char**)argv
);
3685 fprintf(stderr
, "can't exec ld_classic\n");