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
);
2524 throwf("unknown option: %s", arg
);
2528 FileInfo info
= findFile(arg
);
2529 if ( strcmp(&info
.path
[strlen(info
.path
)-2], ".a") == 0 )
2532 fInputFiles
.push_back(info
);
2536 // if a -lazy option was used, implicitly link in lazydylib1.o
2537 if ( fUsingLazyDylibLinking
) {
2538 addLibrary(findLibrary("lazydylib1.o"));
2545 // -syslibroot <path> is used for SDK support.
2546 // The rule is that all search paths (both explicit and default) are
2547 // checked to see if they exist in the SDK. If so, that path is
2548 // replaced with the sdk prefixed path. If not, that search path
2549 // is used as is. If multiple -syslibroot options are specified
2550 // their directory structures are logically overlayed and files
2551 // from sdks specified earlier on the command line used before later ones.
2553 void Options::buildSearchPaths(int argc
, const char* argv
[])
2555 bool addStandardLibraryDirectories
= true;
2556 std::vector
<const char*> libraryPaths
;
2557 std::vector
<const char*> frameworkPaths
;
2558 libraryPaths
.reserve(10);
2559 frameworkPaths
.reserve(10);
2560 // scan through argv looking for -L, -F, -Z, and -syslibroot options
2561 for(int i
=0; i
< argc
; ++i
) {
2562 if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'L') ) {
2563 const char* libSearchDir
= &argv
[i
][2];
2564 if ( libSearchDir
[0] == '\0' )
2565 throw "-L must be immediately followed by a directory path (no space)";
2566 struct stat statbuf
;
2567 if ( stat(libSearchDir
, &statbuf
) == 0 ) {
2568 if ( statbuf
.st_mode
& S_IFDIR
)
2569 libraryPaths
.push_back(libSearchDir
);
2571 warning("path '%s' following -L not a directory", libSearchDir
);
2574 warning("directory '%s' following -L not found", libSearchDir
);
2577 else if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'F') ) {
2578 const char* frameworkSearchDir
= &argv
[i
][2];
2579 if ( frameworkSearchDir
[0] == '\0' )
2580 throw "-F must be immediately followed by a directory path (no space)";
2581 struct stat statbuf
;
2582 if ( stat(frameworkSearchDir
, &statbuf
) == 0 ) {
2583 if ( statbuf
.st_mode
& S_IFDIR
)
2584 frameworkPaths
.push_back(frameworkSearchDir
);
2586 warning("path '%s' following -F not a directory", frameworkSearchDir
);
2589 warning("directory '%s' following -F not found", frameworkSearchDir
);
2592 else if ( strcmp(argv
[i
], "-Z") == 0 )
2593 addStandardLibraryDirectories
= false;
2594 else if ( strcmp(argv
[i
], "-v") == 0 ) {
2596 extern const char ldVersionString
[];
2597 fprintf(stderr
, "%s", ldVersionString
);
2598 // if only -v specified, exit cleanly
2601 printLTOVersion(*this);
2606 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
2607 const char* path
= argv
[++i
];
2609 throw "-syslibroot missing argument";
2610 fSDKPaths
.push_back(path
);
2612 else if ( strcmp(argv
[i
], "-search_paths_first") == 0 ) {
2613 // ??? Deprecate when we get -Bstatic/-Bdynamic.
2614 fLibrarySearchMode
= kSearchDylibAndArchiveInEachDir
;
2616 else if ( strcmp(argv
[i
], "-w") == 0 ) {
2617 sEmitWarnings
= false;
2620 int standardLibraryPathsStartIndex
= libraryPaths
.size();
2621 int standardFrameworkPathsStartIndex
= frameworkPaths
.size();
2622 if ( addStandardLibraryDirectories
) {
2623 libraryPaths
.push_back("/usr/lib");
2624 libraryPaths
.push_back("/usr/local/lib");
2626 frameworkPaths
.push_back("/Library/Frameworks/");
2627 frameworkPaths
.push_back("/System/Library/Frameworks/");
2628 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
2631 // <rdar://problem/5829579> Support for configure based hacks
2632 // if last -syslibroot is /, then ignore all syslibroots
2633 if ( fSDKPaths
.size() > 0 ) {
2634 if ( strcmp(fSDKPaths
.back(), "/") == 0 ) {
2639 // now merge sdk and library paths to make real search paths
2640 fLibrarySearchPaths
.reserve(libraryPaths
.size()*(fSDKPaths
.size()+1));
2642 for (std::vector
<const char*>::iterator it
= libraryPaths
.begin(); it
!= libraryPaths
.end(); ++it
, ++libIndex
) {
2643 const char* libDir
= *it
;
2644 bool sdkOverride
= false;
2645 if ( libDir
[0] == '/' ) {
2646 char betterLibDir
[PATH_MAX
];
2647 if ( strstr(libDir
, "/..") != NULL
) {
2648 if ( realpath(libDir
, betterLibDir
) != NULL
)
2649 libDir
= strdup(betterLibDir
);
2651 const int libDirLen
= strlen(libDir
);
2652 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
2653 const char* sdkDir
= *sdkit
;
2654 const int sdkDirLen
= strlen(sdkDir
);
2655 char newPath
[libDirLen
+ sdkDirLen
+4];
2656 strcpy(newPath
, sdkDir
);
2657 if ( newPath
[sdkDirLen
-1] == '/' )
2658 newPath
[sdkDirLen
-1] = '\0';
2659 strcat(newPath
, libDir
);
2660 struct stat statBuffer
;
2661 if ( stat(newPath
, &statBuffer
) == 0 ) {
2662 fLibrarySearchPaths
.push_back(strdup(newPath
));
2667 if ( !sdkOverride
) {
2668 if ( (libIndex
>= standardLibraryPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
2669 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2670 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2673 fLibrarySearchPaths
.push_back(libDir
);
2678 // now merge sdk and framework paths to make real search paths
2679 fFrameworkSearchPaths
.reserve(frameworkPaths
.size()*(fSDKPaths
.size()+1));
2681 for (std::vector
<const char*>::iterator it
= frameworkPaths
.begin(); it
!= frameworkPaths
.end(); ++it
, ++frameIndex
) {
2682 const char* frameworkDir
= *it
;
2683 bool sdkOverride
= false;
2684 if ( frameworkDir
[0] == '/' ) {
2685 char betterFrameworkDir
[PATH_MAX
];
2686 if ( strstr(frameworkDir
, "/..") != NULL
) {
2687 if ( realpath(frameworkDir
, betterFrameworkDir
) != NULL
)
2688 frameworkDir
= strdup(betterFrameworkDir
);
2690 const int frameworkDirLen
= strlen(frameworkDir
);
2691 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
2692 const char* sdkDir
= *sdkit
;
2693 const int sdkDirLen
= strlen(sdkDir
);
2694 char newPath
[frameworkDirLen
+ sdkDirLen
+4];
2695 strcpy(newPath
, sdkDir
);
2696 if ( newPath
[sdkDirLen
-1] == '/' )
2697 newPath
[sdkDirLen
-1] = '\0';
2698 strcat(newPath
, frameworkDir
);
2699 struct stat statBuffer
;
2700 if ( stat(newPath
, &statBuffer
) == 0 ) {
2701 fFrameworkSearchPaths
.push_back(strdup(newPath
));
2706 if ( !sdkOverride
) {
2707 if ( (frameIndex
>= standardFrameworkPathsStartIndex
) && (fSDKPaths
.size() == 1) ) {
2708 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2709 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2712 fFrameworkSearchPaths
.push_back(frameworkDir
);
2718 fprintf(stderr
,"Library search paths:\n");
2719 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
2720 it
!= fLibrarySearchPaths
.end();
2722 fprintf(stderr
,"\t%s\n", *it
);
2723 fprintf(stderr
,"Framework search paths:\n");
2724 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
2725 it
!= fFrameworkSearchPaths
.end();
2727 fprintf(stderr
,"\t%s\n", *it
);
2731 // this is run before the command line is parsed
2732 void Options::parsePreCommandLineEnvironmentSettings()
2734 if ((getenv("LD_TRACE_ARCHIVES") != NULL
)
2735 || (getenv("RC_TRACE_ARCHIVES") != NULL
))
2736 fReaderOptions
.fTraceArchives
= true;
2738 if ((getenv("LD_TRACE_DYLIBS") != NULL
)
2739 || (getenv("RC_TRACE_DYLIBS") != NULL
)) {
2740 fReaderOptions
.fTraceDylibs
= true;
2741 fReaderOptions
.fTraceIndirectDylibs
= true;
2744 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL
) {
2745 fTraceDylibSearching
= true;
2748 if (getenv("LD_PRINT_OPTIONS") != NULL
)
2749 fPrintOptions
= true;
2751 if (fReaderOptions
.fTraceDylibs
|| fReaderOptions
.fTraceArchives
)
2752 fReaderOptions
.fTraceOutputFile
= getenv("LD_TRACE_FILE");
2754 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL
)
2755 fPrintOrderFileStatistics
= true;
2757 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL
)
2760 if (getenv("LD_NO_ENCRYPT") != NULL
)
2761 fEncryptable
= false;
2763 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL
)
2764 fAllowCpuSubtypeMismatches
= true;
2766 // for now disable compressed linkedit functionality
2767 if ( getenv("LD_NO_COMPACT_LINKEDIT") != NULL
) {
2768 fMakeCompressedDyldInfo
= false;
2769 fMakeClassicDyldInfo
= true;
2771 // temporary until projects adopt -no_pie
2772 if ( getenv("LD_NO_PIE") != NULL
) {
2773 warning("LD_NO_PIE being used to disble building a position independent executable");
2774 fDisablePositionIndependentExecutable
= true;
2777 sWarningsSideFilePath
= getenv("LD_WARN_FILE");
2781 // this is run after the command line is parsed
2782 void Options::parsePostCommandLineEnvironmentSettings()
2784 // when building a dynamic main executable, default any use of @executable_path to output path
2785 if ( fExecutablePath
== NULL
&& (fOutputKind
== kDynamicExecutable
) ) {
2786 fExecutablePath
= fOutputFile
;
2789 // allow build system to set default seg_addr_table
2790 if ( fSegAddrTablePath
== NULL
)
2791 fSegAddrTablePath
= getenv("LD_SEG_ADDR_TABLE");
2793 // allow build system to turn on prebinding
2795 fPrebind
= ( getenv("LD_PREBIND") != NULL
);
2798 // allow build system to force on dead-code-stripping
2799 if ( fDeadStrip
== kDeadStripOff
) {
2800 if ( getenv("LD_DEAD_STRIP") != NULL
) {
2801 switch (fOutputKind
) {
2802 case Options::kDynamicLibrary
:
2803 case Options::kDynamicExecutable
:
2804 case Options::kDynamicBundle
:
2805 fDeadStrip
= kDeadStripOn
;
2807 case Options::kPreload
:
2808 case Options::kObjectFile
:
2809 case Options::kDyld
:
2810 case Options::kStaticExecutable
:
2811 case Options::kKextBundle
:
2817 // allow build system to force on -warn_commons
2818 if ( getenv("LD_WARN_COMMONS") != NULL
)
2819 fWarnCommons
= true;
2823 void Options::reconfigureDefaults()
2825 // sync reader options
2826 switch ( fOutputKind
) {
2827 case Options::kObjectFile
:
2828 fReaderOptions
.fForFinalLinkedImage
= false;
2830 case Options::kDyld
:
2831 fReaderOptions
.fForDyld
= true;
2832 fReaderOptions
.fForFinalLinkedImage
= true;
2833 fReaderOptions
.fNoEHLabels
= true;
2835 case Options::kDynamicLibrary
:
2836 case Options::kDynamicBundle
:
2837 case Options::kKextBundle
:
2838 fReaderOptions
.fForFinalLinkedImage
= true;
2839 fReaderOptions
.fNoEHLabels
= true;
2841 case Options::kDynamicExecutable
:
2842 case Options::kStaticExecutable
:
2843 case Options::kPreload
:
2844 fReaderOptions
.fLinkingMainExecutable
= true;
2845 fReaderOptions
.fForFinalLinkedImage
= true;
2846 fReaderOptions
.fNoEHLabels
= true;
2850 // set default min OS version
2851 if ( (fReaderOptions
.fMacVersionMin
== ObjectFile::ReaderOptions::kMinMacVersionUnset
)
2852 && (fReaderOptions
.fIPhoneVersionMin
== ObjectFile::ReaderOptions::kMinIPhoneVersionUnset
) ) {
2853 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
2854 const char* macVers
= getenv("MACOSX_DEPLOYMENT_TARGET");
2855 const char* iPhoneVers
= getenv("IPHONEOS_DEPLOYMENT_TARGET");
2856 if ( macVers
!= NULL
)
2857 setMacOSXVersionMin(macVers
);
2858 else if ( iPhoneVers
!= NULL
)
2859 setIPhoneVersionMin(iPhoneVers
);
2861 // if still nothing, set default based on architecture
2862 switch ( fArchitecture
) {
2864 case CPU_TYPE_X86_64
:
2865 case CPU_TYPE_POWERPC
:
2866 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_6
; // FIX FIX, this really should be a check of the OS version the linker is running o
2869 fReaderOptions
.fIPhoneVersionMin
= ObjectFile::ReaderOptions::k2_0
;
2876 // adjust min based on architecture
2877 switch ( fArchitecture
) {
2879 if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_4
) {
2880 //warning("-macosx_version_min should be 10.4 or later for i386");
2881 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_4
;
2884 case CPU_TYPE_POWERPC64
:
2885 if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_4
) {
2886 //warning("-macosx_version_min should be 10.4 or later for ppc64");
2887 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_4
;
2890 case CPU_TYPE_X86_64
:
2891 if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_4
) {
2892 //warning("-macosx_version_min should be 10.4 or later for x86_64");
2893 fReaderOptions
.fMacVersionMin
= ObjectFile::ReaderOptions::k10_4
;
2898 // adjust kext type based on architecture
2899 if ( fOutputKind
== kKextBundle
) {
2900 switch ( fArchitecture
) {
2901 case CPU_TYPE_X86_64
:
2902 // x86_64 uses new MH_KEXT_BUNDLE type
2903 fMakeClassicDyldInfo
= true;
2904 fMakeCompressedDyldInfo
= false;
2905 fAllowTextRelocs
= true;
2906 fUndefinedTreatment
= kUndefinedDynamicLookup
;
2908 case CPU_TYPE_POWERPC
:
2912 fOutputKind
= kObjectFile
;
2917 // disable implicit dylibs when targeting 10.3
2918 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
2919 if ( !minOS(ObjectFile::ReaderOptions::k10_4
, ObjectFile::ReaderOptions::k2_0
) )
2920 fReaderOptions
.fImplicitlyLinkPublicDylibs
= false;
2923 // allow build system to force linker to ignore -prebind
2924 if ( getenv("LD_FORCE_NO_PREBIND") != NULL
)
2927 // allow build system to force linker to ignore -seg_addr_table
2928 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL
)
2929 fSegAddrTablePath
= NULL
;
2931 // check for base address specified externally
2932 if ( (fSegAddrTablePath
!= NULL
) && (fOutputKind
== Options::kDynamicLibrary
) ) {
2933 parseSegAddrTable(fSegAddrTablePath
, this->installPath());
2934 // HACK to support seg_addr_table entries that are physical paths instead of install paths
2935 if ( fBaseAddress
== 0 ) {
2936 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
2937 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.4.dylib");
2938 if ( fBaseAddress
== 0 )
2939 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libstdc++.6.0.9.dylib");
2942 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
2943 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libz.1.2.3.dylib");
2945 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
2946 parseSegAddrTable(fSegAddrTablePath
, "/usr/lib/libutil1.0.dylib");
2950 // split segs only allowed for dylibs
2952 // split seg only supported for ppc, i386, and arm.
2953 switch ( fArchitecture
) {
2954 case CPU_TYPE_POWERPC
:
2956 if ( fOutputKind
!= Options::kDynamicLibrary
)
2958 // make sure read and write segments are proper distance apart
2959 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x10000000) )
2960 fBaseWritableAddress
= fBaseAddress
+ 0x10000000;
2963 if ( fOutputKind
!= Options::kDynamicLibrary
) {
2967 // make sure read and write segments are proper distance apart
2968 if ( fSplitSegs
&& (fBaseWritableAddress
-fBaseAddress
!= 0x08000000) )
2969 fBaseWritableAddress
= fBaseAddress
+ 0x08000000;
2975 fBaseWritableAddress
= 0;
2979 // <rdar://problem/6138961> -r implies no prebinding for all architectures
2980 if ( fOutputKind
== Options::kObjectFile
)
2983 // disable prebinding depending on arch and min OS version
2985 switch ( fArchitecture
) {
2986 case CPU_TYPE_POWERPC
:
2988 if ( fReaderOptions
.fMacVersionMin
== ObjectFile::ReaderOptions::k10_4
) {
2989 // in 10.4 only split seg dylibs are prebound
2990 if ( (fOutputKind
!= Options::kDynamicLibrary
) || ! fSplitSegs
)
2993 else if ( fReaderOptions
.fMacVersionMin
>= ObjectFile::ReaderOptions::k10_5
) {
2994 // in 10.5 nothing is prebound
2998 // in 10.3 and earlier only dylibs and main executables could be prebound
2999 switch ( fOutputKind
) {
3000 case Options::kDynamicExecutable
:
3001 case Options::kDynamicLibrary
:
3002 // only main executables and dylibs can be prebound
3004 case Options::kStaticExecutable
:
3005 case Options::kDynamicBundle
:
3006 case Options::kObjectFile
:
3007 case Options::kDyld
:
3008 case Options::kPreload
:
3009 case Options::kKextBundle
:
3010 // disable prebinding for everything else
3016 case CPU_TYPE_POWERPC64
:
3017 case CPU_TYPE_X86_64
:
3021 switch ( fOutputKind
) {
3022 case Options::kDynamicExecutable
:
3023 case Options::kDynamicLibrary
:
3024 // only main executables and dylibs can be prebound
3026 case Options::kStaticExecutable
:
3027 case Options::kDynamicBundle
:
3028 case Options::kObjectFile
:
3029 case Options::kDyld
:
3030 case Options::kPreload
:
3031 case Options::kKextBundle
:
3032 // disable prebinding for everything else
3040 // only prebound images can be split-seg
3041 if ( fSplitSegs
&& !fPrebind
)
3044 // determine if info for shared region should be added
3045 if ( fOutputKind
== Options::kDynamicLibrary
) {
3046 if ( minOS(ObjectFile::ReaderOptions::k10_5
, ObjectFile::ReaderOptions::k3_1
) )
3048 if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
3049 || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
3050 fSharedRegionEligible
= true;
3053 // figure out if module table is needed for compatibility with old ld/dyld
3054 if ( fOutputKind
== Options::kDynamicLibrary
) {
3055 switch ( fArchitecture
) {
3056 case CPU_TYPE_POWERPC
: // 10.3 and earlier dyld requires a module table
3057 case CPU_TYPE_I386
: // ld_classic for 10.4.x requires a module table
3058 if ( fReaderOptions
.fMacVersionMin
<= ObjectFile::ReaderOptions::k10_5
)
3059 fNeedsModuleTable
= true;
3063 fNeedsModuleTable
= true; // redo_prebinding requires a module table
3068 // <rdar://problem/5366363> -r -x implies -S
3069 if ( (fOutputKind
== Options::kObjectFile
) && (fLocalSymbolHandling
== kLocalSymbolsNone
) )
3070 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
3072 // choose how to process unwind info
3073 switch ( fArchitecture
) {
3075 case CPU_TYPE_X86_64
:
3076 switch ( fOutputKind
) {
3077 case Options::kObjectFile
:
3078 case Options::kStaticExecutable
:
3079 case Options::kPreload
:
3080 case Options::kKextBundle
:
3081 fReaderOptions
.fAddCompactUnwindEncoding
= false;
3083 case Options::kDyld
:
3084 case Options::kDynamicLibrary
:
3085 case Options::kDynamicBundle
:
3086 case Options::kDynamicExecutable
:
3087 //if ( fReaderOptions.fAddCompactUnwindEncoding && (fReaderOptions.fVersionMin >= ObjectFile::ReaderOptions::k10_6) )
3088 // fReaderOptions.fRemoveDwarfUnwindIfCompactExists = true;
3092 case CPU_TYPE_POWERPC
:
3093 case CPU_TYPE_POWERPC64
:
3095 fReaderOptions
.fAddCompactUnwindEncoding
= false;
3096 fReaderOptions
.fRemoveDwarfUnwindIfCompactExists
= false;
3099 // if -arch is missing, assume we don't want compact unwind info
3100 fReaderOptions
.fAddCompactUnwindEncoding
= false;
3104 // only ARM main executables can be encrypted
3105 if ( fOutputKind
!= Options::kDynamicExecutable
)
3106 fEncryptable
= false;
3107 if ( fArchitecture
!= CPU_TYPE_ARM
)
3108 fEncryptable
= false;
3110 // don't move inits in dyld because dyld wants certain
3111 // entries point at stable locations at the start of __text
3112 if ( fOutputKind
== Options::kDyld
)
3113 fReaderOptions
.fAutoOrderInitializers
= false;
3116 // disable __data ordering for some output kinds
3117 switch ( fOutputKind
) {
3118 case Options::kObjectFile
:
3119 case Options::kDyld
:
3120 case Options::kStaticExecutable
:
3121 case Options::kPreload
:
3122 case Options::kKextBundle
:
3125 case Options::kDynamicExecutable
:
3126 case Options::kDynamicLibrary
:
3127 case Options::kDynamicBundle
:
3131 // only use compressed LINKEDIT for:
3132 // x86_64 and i386 on Mac OS X 10.6 or later
3133 // arm on iPhoneOS 3.1 or later
3134 if ( fMakeCompressedDyldInfo
) {
3135 switch (fArchitecture
) {
3137 case CPU_TYPE_X86_64
:
3138 if ( fReaderOptions
.fMacVersionMin
>= ObjectFile::ReaderOptions::k10_6
)
3139 fMakeClassicDyldInfo
= false;
3140 else if ( fReaderOptions
.fMacVersionMin
< ObjectFile::ReaderOptions::k10_5
)
3141 fMakeCompressedDyldInfo
= false;
3144 if ( fReaderOptions
.fIPhoneVersionMin
>= ObjectFile::ReaderOptions::k3_1
)
3145 fMakeClassicDyldInfo
= false;
3146 else if ( fReaderOptions
.fIPhoneVersionMin
< ObjectFile::ReaderOptions::k3_1
)
3147 fMakeCompressedDyldInfo
= false;
3149 case CPU_TYPE_POWERPC
:
3150 case CPU_TYPE_POWERPC64
:
3152 fMakeCompressedDyldInfo
= false;
3157 // only use compressed LINKEDIT for final linked images
3158 if ( fMakeCompressedDyldInfo
) {
3159 switch ( fOutputKind
) {
3160 case Options::kDynamicExecutable
:
3161 case Options::kDynamicLibrary
:
3162 case Options::kDynamicBundle
:
3164 case Options::kPreload
:
3165 case Options::kStaticExecutable
:
3166 case Options::kObjectFile
:
3167 case Options::kDyld
:
3168 case Options::kKextBundle
:
3169 fMakeCompressedDyldInfo
= false;
3173 fReaderOptions
.fMakeCompressedDyldInfo
= fMakeCompressedDyldInfo
;
3175 // only ARM enforces that cpu-sub-types must match
3176 if ( fArchitecture
!= CPU_TYPE_ARM
)
3177 fAllowCpuSubtypeMismatches
= true;
3179 // only final linked images can not optimize zero fill sections
3180 if ( fOutputKind
== Options::kObjectFile
)
3181 fReaderOptions
.fOptimizeZeroFill
= true;
3183 // only dynamic final linked images should warn about use of commmons
3184 if ( fWarnCommons
) {
3185 switch ( fOutputKind
) {
3186 case Options::kDynamicExecutable
:
3187 case Options::kDynamicLibrary
:
3188 case Options::kDynamicBundle
:
3190 case Options::kPreload
:
3191 case Options::kStaticExecutable
:
3192 case Options::kObjectFile
:
3193 case Options::kDyld
:
3194 case Options::kKextBundle
:
3195 fWarnCommons
= false;
3200 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
3201 if ( minOS(ObjectFile::ReaderOptions::k10_5
, ObjectFile::ReaderOptions::k2_0
) )
3202 fUseSimplifiedDylibReExports
= true;
3204 // x86_64 for MacOSX 10.7 defaults to PIE
3205 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
== kDynamicExecutable
)
3206 && (fReaderOptions
.fMacVersionMin
>= ObjectFile::ReaderOptions::k10_7
) ) {
3207 fPositionIndependentExecutable
= true;
3211 void Options::checkIllegalOptionCombinations()
3213 // check -undefined setting
3214 switch ( fUndefinedTreatment
) {
3215 case kUndefinedError
:
3216 case kUndefinedDynamicLookup
:
3219 case kUndefinedWarning
:
3220 case kUndefinedSuppress
:
3221 // requires flat namespace
3222 if ( fNameSpace
== kTwoLevelNameSpace
)
3223 throw "can't use -undefined warning or suppress with -twolevel_namespace";
3227 // unify -sub_umbrella with dylibs
3228 for (std::vector
<const char*>::iterator it
= fSubUmbellas
.begin(); it
!= fSubUmbellas
.end(); it
++) {
3229 const char* subUmbrella
= *it
;
3231 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
3232 Options::FileInfo
& info
= *fit
;
3233 const char* lastSlash
= strrchr(info
.path
, '/');
3234 if ( lastSlash
== NULL
)
3235 lastSlash
= info
.path
- 1;
3236 if ( strcmp(&lastSlash
[1], subUmbrella
) == 0 ) {
3237 info
.options
.fReExport
= true;
3243 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella
);
3246 // unify -sub_library with dylibs
3247 for (std::vector
<const char*>::iterator it
= fSubLibraries
.begin(); it
!= fSubLibraries
.end(); it
++) {
3248 const char* subLibrary
= *it
;
3250 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
3251 Options::FileInfo
& info
= *fit
;
3252 const char* lastSlash
= strrchr(info
.path
, '/');
3253 if ( lastSlash
== NULL
)
3254 lastSlash
= info
.path
- 1;
3255 const char* dot
= strchr(&lastSlash
[1], '.');
3257 dot
= &lastSlash
[strlen(lastSlash
)];
3258 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
3259 info
.options
.fReExport
= true;
3265 warning("-sub_library %s does not match a supplied dylib", subLibrary
);
3268 // sync reader options
3269 if ( fNameSpace
!= kTwoLevelNameSpace
)
3270 fReaderOptions
.fFlatNamespace
= true;
3272 // check -stack_addr
3273 if ( fStackAddr
!= 0 ) {
3274 switch (fArchitecture
) {
3276 case CPU_TYPE_POWERPC
:
3278 if ( fStackAddr
> 0xFFFFFFFF )
3279 throw "-stack_addr must be < 4G for 32-bit processes";
3281 case CPU_TYPE_POWERPC64
:
3282 case CPU_TYPE_X86_64
:
3285 if ( (fStackAddr
& -4096) != fStackAddr
)
3286 throw "-stack_addr must be multiples of 4K";
3287 if ( fStackSize
== 0 )
3288 throw "-stack_addr must be used with -stack_size";
3291 // check -stack_size
3292 if ( fStackSize
!= 0 ) {
3293 switch (fArchitecture
) {
3295 case CPU_TYPE_POWERPC
:
3296 if ( fStackSize
> 0xFFFFFFFF )
3297 throw "-stack_size must be < 4G for 32-bit processes";
3298 if ( fStackAddr
== 0 ) {
3299 fStackAddr
= 0xC0000000;
3301 if ( (fStackAddr
> 0xB0000000) && ((fStackAddr
-fStackSize
) < 0xB0000000) )
3302 warning("custom stack placement overlaps and will disable shared region");
3305 if ( fStackSize
> 0x2F000000 )
3306 throw "-stack_size must be < 752MB";
3307 if ( fStackAddr
== 0 )
3308 fStackAddr
= 0x2F000000;
3309 if ( fStackAddr
> 0x30000000)
3310 throw "-stack_addr must be < 0x30000000 for arm";
3311 case CPU_TYPE_POWERPC64
:
3312 case CPU_TYPE_X86_64
:
3313 if ( fStackAddr
== 0 ) {
3314 fStackAddr
= 0x00007FFF5C000000LL
;
3318 if ( (fStackSize
& -4096) != fStackSize
)
3319 throw "-stack_size must be multiples of 4K";
3320 switch ( fOutputKind
) {
3321 case Options::kDynamicExecutable
:
3322 case Options::kStaticExecutable
:
3323 // custom stack size only legal when building main executable
3325 case Options::kDynamicLibrary
:
3326 case Options::kDynamicBundle
:
3327 case Options::kObjectFile
:
3328 case Options::kDyld
:
3329 case Options::kPreload
:
3330 case Options::kKextBundle
:
3331 throw "-stack_size option can only be used when linking a main executable";
3335 // check that -allow_stack_execute is only used with main executables
3336 if ( fExecutableStack
) {
3337 switch ( fOutputKind
) {
3338 case Options::kDynamicExecutable
:
3339 case Options::kStaticExecutable
:
3340 // -allow_stack_execute size only legal when building main executable
3342 case Options::kDynamicLibrary
:
3343 case Options::kDynamicBundle
:
3344 case Options::kObjectFile
:
3345 case Options::kDyld
:
3346 case Options::kPreload
:
3347 case Options::kKextBundle
:
3348 throw "-allow_stack_execute option can only be used when linking a main executable";
3352 // check -client_name is only used when making a bundle or main executable
3353 if ( fClientName
!= NULL
) {
3354 switch ( fOutputKind
) {
3355 case Options::kDynamicExecutable
:
3356 case Options::kDynamicBundle
:
3358 case Options::kStaticExecutable
:
3359 case Options::kDynamicLibrary
:
3360 case Options::kObjectFile
:
3361 case Options::kDyld
:
3362 case Options::kPreload
:
3363 case Options::kKextBundle
:
3364 throw "-client_name can only be used with -bundle";
3368 // check -init is only used when building a dylib
3369 if ( (fInitFunctionName
!= NULL
) && (fOutputKind
!= Options::kDynamicLibrary
) )
3370 throw "-init can only be used with -dynamiclib";
3372 // check -bundle_loader only used with -bundle
3373 if ( (fBundleLoader
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
3374 throw "-bundle_loader can only be used with -bundle";
3376 // check -dtrace not used with -r
3377 if ( (fDtraceScriptName
!= NULL
) && (fOutputKind
== Options::kObjectFile
) )
3378 throw "-dtrace can only be used when creating final linked images";
3380 // check -d can only be used with -r
3381 if ( fReaderOptions
.fMakeTentativeDefinitionsReal
&& (fOutputKind
!= Options::kObjectFile
) )
3382 throw "-d can only be used with -r";
3384 // check that -root_safe is not used with -r
3385 if ( fReaderOptions
.fRootSafe
&& (fOutputKind
== Options::kObjectFile
) )
3386 throw "-root_safe cannot be used with -r";
3388 // check that -setuid_safe is not used with -r
3389 if ( fReaderOptions
.fSetuidSafe
&& (fOutputKind
== Options::kObjectFile
) )
3390 throw "-setuid_safe cannot be used with -r";
3392 // make sure all required exported symbols exist
3393 std::vector
<const char*> impliedExports
;
3394 for (NameSet::iterator it
=fExportSymbols
.regularBegin(); it
!= fExportSymbols
.regularEnd(); it
++) {
3395 const char* name
= *it
;
3396 // never export .eh symbols
3397 const int len
= strlen(name
);
3398 if ( (strcmp(&name
[len
-3], ".eh") == 0) || (strncmp(name
, ".objc_category_name_", 20) == 0) )
3399 warning("ignoring %s in export list", name
);
3401 fInitialUndefines
.push_back(name
);
3402 if ( strncmp(name
, ".objc_class_name_", 17) == 0 ) {
3403 // rdar://problem/4718189 map ObjC class names to new runtime names
3404 switch (fArchitecture
) {
3406 // i386 only uses new symbols when using objc2 ABI
3407 if ( !fObjCABIVersion2POverride
)
3409 // when using objc2 ABI to same as archs below
3410 case CPU_TYPE_POWERPC64
:
3411 case CPU_TYPE_X86_64
:
3414 asprintf(&temp
, "_OBJC_CLASS_$_%s", &name
[17]);
3415 impliedExports
.push_back(temp
);
3416 asprintf(&temp
, "_OBJC_METACLASS_$_%s", &name
[17]);
3417 impliedExports
.push_back(temp
);
3422 for (std::vector
<const char*>::iterator it
=impliedExports
.begin(); it
!= impliedExports
.end(); it
++) {
3423 const char* name
= *it
;
3424 fExportSymbols
.insert(name
);
3425 fInitialUndefines
.push_back(name
);
3428 // make sure that -init symbol exist
3429 if ( fInitFunctionName
!= NULL
)
3430 fInitialUndefines
.push_back(fInitFunctionName
);
3432 // check custom segments
3433 if ( fCustomSegmentAddresses
.size() != 0 ) {
3434 // verify no segment is in zero page
3435 if ( fZeroPageSize
!= ULLONG_MAX
) {
3436 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
3437 if ( (it
->address
>= 0) && (it
->address
< fZeroPageSize
) )
3438 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it
->name
, it
->address
);
3441 // verify no duplicates
3442 for (std::vector
<SegmentStart
>::iterator it
= fCustomSegmentAddresses
.begin(); it
!= fCustomSegmentAddresses
.end(); ++it
) {
3443 for (std::vector
<SegmentStart
>::iterator it2
= fCustomSegmentAddresses
.begin(); it2
!= fCustomSegmentAddresses
.end(); ++it2
) {
3444 if ( (it
->address
== it2
->address
) && (it
!= it2
) )
3445 throwf("duplicate -segaddr addresses for %s and %s", it
->name
, it2
->name
);
3447 // a custom segment address of zero will disable the use of a zero page
3448 if ( it
->address
== 0 )
3453 if ( fZeroPageSize
== ULLONG_MAX
) {
3454 // zero page size not specified on command line, set default
3455 switch (fArchitecture
) {
3457 case CPU_TYPE_POWERPC
:
3459 // first 4KB for 32-bit architectures
3460 fZeroPageSize
= 0x1000;
3462 case CPU_TYPE_POWERPC64
:
3463 // first 4GB for ppc64 on 10.5
3464 if ( fReaderOptions
.fMacVersionMin
>= ObjectFile::ReaderOptions::k10_5
)
3465 fZeroPageSize
= 0x100000000ULL
;
3467 fZeroPageSize
= 0x1000; // 10.4 dyld may not be able to handle >4GB zero page
3469 case CPU_TYPE_X86_64
:
3470 // first 4GB for x86_64 on all OS's
3471 fZeroPageSize
= 0x100000000ULL
;
3474 // if -arch not used, default to 4K zero-page
3475 fZeroPageSize
= 0x1000;
3479 switch ( fOutputKind
) {
3480 case Options::kDynamicExecutable
:
3481 case Options::kStaticExecutable
:
3482 // -pagezero_size size only legal when building main executable
3484 case Options::kDynamicLibrary
:
3485 case Options::kDynamicBundle
:
3486 case Options::kObjectFile
:
3487 case Options::kDyld
:
3488 case Options::kPreload
:
3489 case Options::kKextBundle
:
3490 if ( fZeroPageSize
!= 0 )
3491 throw "-pagezero_size option can only be used when linking a main executable";
3495 // -dead_strip and -r are incompatible
3496 if ( (fDeadStrip
!= kDeadStripOff
) && (fOutputKind
== Options::kObjectFile
) )
3497 throw "-r and -dead_strip cannot be used together";
3499 // can't use -rpath unless targeting 10.5 or later
3500 if ( fRPaths
.size() > 0 ) {
3501 if ( !minOS(ObjectFile::ReaderOptions::k10_5
, ObjectFile::ReaderOptions::k2_0
) )
3502 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
3503 switch ( fOutputKind
) {
3504 case Options::kDynamicExecutable
:
3505 case Options::kDynamicLibrary
:
3506 case Options::kDynamicBundle
:
3508 case Options::kStaticExecutable
:
3509 case Options::kObjectFile
:
3510 case Options::kDyld
:
3511 case Options::kPreload
:
3512 case Options::kKextBundle
:
3513 throw "-rpath can only be used when creating a dynamic final linked image";
3517 // check -pie is only used when building a dynamic main executable for 10.5
3518 if ( fPositionIndependentExecutable
) {
3519 switch ( fOutputKind
) {
3520 case Options::kDynamicExecutable
:
3521 // -no_pie anywhere on command line disable PIE
3522 if ( fDisablePositionIndependentExecutable
)
3523 fPositionIndependentExecutable
= false;
3525 case Options::kPreload
:
3527 case Options::kDynamicLibrary
:
3528 case Options::kDynamicBundle
:
3529 warning("-pie being ignored. It is only used when linking a main executable");
3531 case Options::kStaticExecutable
:
3532 case Options::kObjectFile
:
3533 case Options::kDyld
:
3534 case Options::kKextBundle
:
3535 throw "-pie can only be used when linking a main executable";
3537 if ( !minOS(ObjectFile::ReaderOptions::k10_5
, ObjectFile::ReaderOptions::k2_0
) )
3538 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
3541 // check -read_only_relocs is not used with x86_64
3542 if ( fAllowTextRelocs
) {
3543 if ( (fArchitecture
== CPU_TYPE_X86_64
) && (fOutputKind
!= kKextBundle
) ) {
3544 warning("-read_only_relocs cannot be used with x86_64");
3545 fAllowTextRelocs
= false;
3549 // check -mark_auto_dead_strip is only used with dylibs
3550 if ( fMarkDeadStrippableDylib
) {
3551 if ( fOutputKind
!= Options::kDynamicLibrary
) {
3552 warning("-mark_auto_dead_strip can only be used when creating a dylib");
3553 fMarkDeadStrippableDylib
= false;
3557 // -force_cpusubtype_ALL is not supported for ARM
3558 if ( fForceSubtypeAll
) {
3559 if ( fArchitecture
== CPU_TYPE_ARM
) {
3560 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
3566 void Options::checkForClassic(int argc
, const char* argv
[])
3569 bool archFound
= false;
3570 bool staticFound
= false;
3571 bool dtraceFound
= false;
3572 bool kextFound
= false;
3573 bool rFound
= false;
3574 bool creatingMachKernel
= false;
3575 bool newLinker
= false;
3577 // build command line buffer in case ld crashes
3578 for(int i
=1; i
< argc
; ++i
) {
3579 strlcat(crashreporterBuffer
, argv
[i
], 1000);
3580 strlcat(crashreporterBuffer
, " ", 1000);
3583 for(int i
=0; i
< argc
; ++i
) {
3584 const char* arg
= argv
[i
];
3585 if ( arg
[0] == '-' ) {
3586 if ( strcmp(arg
, "-arch") == 0 ) {
3587 parseArch(argv
[++i
]);
3590 else if ( strcmp(arg
, "-static") == 0 ) {
3593 else if ( strcmp(arg
, "-kext") == 0 ) {
3596 else if ( strcmp(arg
, "-dtrace") == 0 ) {
3599 else if ( strcmp(arg
, "-r") == 0 ) {
3602 else if ( strcmp(arg
, "-new_linker") == 0 ) {
3605 else if ( strcmp(arg
, "-classic_linker") == 0 ) {
3606 // ld_classic does not understand this option, so remove it
3607 for(int j
=i
; j
< argc
; ++j
)
3608 argv
[j
] = argv
[j
+1];
3609 this->gotoClassicLinker(argc
-1, argv
);
3611 else if ( strcmp(arg
, "-o") == 0 ) {
3612 const char* outfile
= argv
[++i
];
3613 if ( (outfile
!= NULL
) && (strstr(outfile
, "/mach_kernel") != NULL
) )
3614 creatingMachKernel
= true;
3619 // -dtrace only supported by new linker
3624 switch ( fArchitecture
) {
3625 case CPU_TYPE_POWERPC
:
3628 // if ( staticFound && (rFound || !creatingMachKernel) ) {
3629 if ( (staticFound
|| kextFound
) && !newLinker
) {
3630 // this environment variable will disable use of ld_classic for -static links
3631 if ( getenv("LD_NO_CLASSIC_LINKER_STATIC") == NULL
) {
3632 // ld_classic does not support -iphoneos_version_min, so change
3633 for(int j
=0; j
< argc
; ++j
) {
3634 if ( strcmp(argv
[j
], "-iphoneos_version_min") == 0) {
3635 argv
[j
] = "-macosx_version_min";
3641 // ld classic does not understand -kext (change to -static -r)
3643 for(int j
=0; j
< argc
; ++j
) {
3644 if ( strcmp(argv
[j
], "-kext") == 0)
3646 else if ( strcmp(argv
[j
], "-dynamic") == 0)
3647 argv
[j
] = "-static";
3650 this->gotoClassicLinker(argc
, argv
);
3657 // work around for VSPTool
3659 this->gotoClassicLinker(argc
, argv
);
3664 void Options::gotoClassicLinker(int argc
, const char* argv
[])
3666 argv
[0] = "ld_classic";
3667 char rawPath
[PATH_MAX
];
3668 char path
[PATH_MAX
];
3669 uint32_t bufSize
= PATH_MAX
;
3670 if ( _NSGetExecutablePath(rawPath
, &bufSize
) != -1 ) {
3671 if ( realpath(rawPath
, path
) != NULL
) {
3672 char* lastSlash
= strrchr(path
, '/');
3673 if ( lastSlash
!= NULL
) {
3674 strcpy(lastSlash
+1, "ld_classic");
3676 execvp(path
, (char**)argv
);
3680 // in case of error in above, try searching for ld_classic via PATH
3681 execvp(argv
[0], (char**)argv
);
3682 fprintf(stderr
, "can't exec ld_classic\n");