1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2005 Apple Computer, 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>
35 void throwf(const char* format
, ...)
39 va_start(list
, format
);
40 vasprintf(&p
, format
, list
);
47 Options::Options(int argc
, const char* argv
[])
48 : fOutputFile("a.out"), fArchitecture(0), fOutputKind(kDynamicExecutable
), fBindAtLoad(false),
49 fStripLocalSymbols(false), fKeepPrivateExterns(false),
50 fInterposable(false), fIgnoreOtherArchFiles(false), fForceSubtypeAll(false), fDeadStrip(kDeadStripOff
),
51 fVersionMin(kMinUnset
),fNameSpace(kTwoLevelNameSpace
),
52 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL
), fEntryName("start"), fBaseAddress(0),
53 fExportMode(kExportDefault
), fLibrarySearchMode(kSearchAllDirsForDylibsThenAllDirsForArchives
),
54 fUndefinedTreatment(kUndefinedError
), fMessagesPrefixedWithArchitecture(false), fPICTreatment(kError
),
55 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchError
), fMultiplyDefinedDynamic(kWarning
),
56 fMultiplyDefinedUnused(kSuppress
), fWarnOnMultiplyDefined(false), fClientName(NULL
),
57 fUmbrellaName(NULL
), fInitFunctionName(NULL
), fDotOutputFile(NULL
), fExecutablePath(NULL
), fBundleLoader(NULL
),
58 fZeroPageSize(ULLONG_MAX
), fStackSize(0), fStackAddr(0), fExecutableStack(false), fMinimumHeaderPad(0),
59 fCommonsMode(kCommonsIgnoreDylibs
), fWarnCommons(false), fVerbose(false), fKeepRelocations(false),
60 fEmitUUID(true),fWarnStabs(false),
61 fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
62 fMakeTentativeDefinitionsReal(false)
64 this->parsePreCommandLineEnvironmentSettings();
65 this->parse(argc
, argv
);
66 this->parsePostCommandLineEnvironmentSettings();
67 this->reconfigureDefaults();
68 this->checkIllegalOptionCombinations();
75 const ObjectFile::ReaderOptions
& Options::readerOptions()
77 return fReaderOptions
;
80 cpu_type_t
Options::architecture()
85 const char* Options::getOutputFilePath()
90 std::vector
<Options::FileInfo
>& Options::getInputFiles()
95 Options::OutputKind
Options::outputKind()
100 bool Options::stripLocalSymbols()
102 return fStripLocalSymbols
;
105 bool Options::bindAtLoad()
110 bool Options::prebind()
115 bool Options::fullyLoadArchives()
117 return fReaderOptions
.fFullyLoadArchives
;
120 Options::NameSpace
Options::nameSpace()
125 const char* Options::installPath()
127 if ( fDylibInstallName
!= NULL
)
128 return fDylibInstallName
;
133 uint32_t Options::currentVersion()
135 return fDylibCurrentVersion
;
138 uint32_t Options::compatibilityVersion()
140 return fDylibCompatVersion
;
143 const char* Options::entryName()
148 uint64_t Options::baseAddress()
153 bool Options::keepPrivateExterns()
155 return fKeepPrivateExterns
;
158 bool Options::interposable()
160 return fInterposable
;
163 bool Options::ignoreOtherArchInputFiles()
165 return fIgnoreOtherArchFiles
;
168 bool Options::forceCpuSubtypeAll()
170 return fForceSubtypeAll
;
173 bool Options::traceDylibs()
175 return fReaderOptions
.fTraceDylibs
;
178 bool Options::traceArchives()
180 return fReaderOptions
.fTraceArchives
;
183 Options::UndefinedTreatment
Options::undefinedTreatment()
185 return fUndefinedTreatment
;
188 Options::VersionMin
Options::macosxVersionMin()
193 Options::WeakReferenceMismatchTreatment
Options::weakReferenceMismatchTreatment()
195 return fWeakReferenceMismatchTreatment
;
198 Options::Treatment
Options::multipleDefinitionsInDylibs()
200 return fMultiplyDefinedDynamic
;
203 Options::Treatment
Options::overridingDefinitionInDependentDylib()
205 return fMultiplyDefinedUnused
;
208 bool Options::warnOnMultipleDefinitionsInObjectFiles()
210 return fWarnOnMultiplyDefined
;
213 const char* Options::umbrellaName()
215 return fUmbrellaName
;
218 std::vector
<const char*>& Options::allowableClients()
220 return fAllowableClients
;
223 const char* Options::clientName()
228 uint64_t Options::zeroPageSize()
230 return fZeroPageSize
;
233 bool Options::hasCustomStack()
235 return (fStackSize
!= 0);
238 uint64_t Options::customStackSize()
243 uint64_t Options::customStackAddr()
248 bool Options::hasExecutableStack()
250 return fExecutableStack
;
253 std::vector
<const char*>& Options::initialUndefines()
255 return fInitialUndefines
;
258 bool Options::printWhyLive(const char* symbolName
)
260 return ( fWhyLive
.find(symbolName
) != fWhyLive
.end() );
263 std::vector
<const char*>& Options::traceSymbols()
265 return fTraceSymbols
;
268 const char* Options::initFunctionName()
270 return fInitFunctionName
;
273 const char* Options::dotOutputFile()
275 return fDotOutputFile
;
278 bool Options::hasExportRestrictList()
280 return (fExportMode
!= kExportDefault
);
283 bool Options::allGlobalsAreDeadStripRoots()
285 // -exported_symbols_list means globals are not exported by default
286 if ( fExportMode
== kExportSome
)
289 switch ( fOutputKind
) {
290 case Options::kDynamicExecutable
:
291 case Options::kStaticExecutable
:
292 // by default unused globals in a main executable are stripped
294 case Options::kDynamicLibrary
:
295 case Options::kDynamicBundle
:
296 case Options::kObjectFile
:
303 uint32_t Options::minimumHeaderPad()
305 return fMinimumHeaderPad
;
308 std::vector
<Options::ExtraSection
>& Options::extraSections()
310 return fExtraSections
;
313 std::vector
<Options::SectionAlignment
>& Options::sectionAlignments()
315 return fSectionAlignments
;
318 Options::CommonsMode
Options::commonsMode()
323 bool Options::warnCommons()
328 bool Options::keepRelocations()
330 return fKeepRelocations
;
333 bool Options::emitUUID()
338 bool Options::warnStabs()
343 const char* Options::executablePath()
345 return fExecutablePath
;
348 Options::DeadStripMode
Options::deadStrip()
353 bool Options::shouldExport(const char* symbolName
)
355 switch (fExportMode
) {
357 return ( fExportSymbols
.find(symbolName
) != fExportSymbols
.end() );
358 case kDontExportSome
:
359 return ( fDontExportSymbols
.find(symbolName
) == fDontExportSymbols
.end() );
363 throw "internal error";
366 void Options::parseArch(const char* architecture
)
368 if ( architecture
== NULL
)
369 throw "-arch must be followed by an architecture string";
370 if ( strcmp(architecture
, "ppc") == 0 )
371 fArchitecture
= CPU_TYPE_POWERPC
;
372 else if ( strcmp(architecture
, "ppc64") == 0 )
373 fArchitecture
= CPU_TYPE_POWERPC64
;
374 else if ( strcmp(architecture
, "i386") == 0 )
375 fArchitecture
= CPU_TYPE_I386
;
376 else if ( strcmp(architecture
, "x86_64") == 0 )
377 fArchitecture
= CPU_TYPE_X86_64
;
379 throw "-arch followed by unknown architecture name";
382 bool Options::checkForFile(const char* format
, const char* dir
, const char* rootName
, FileInfo
& result
)
384 struct stat statBuffer
;
385 char possiblePath
[strlen(dir
)+strlen(rootName
)+strlen(format
)+8];
386 sprintf(possiblePath
, format
, dir
, rootName
);
387 bool found
= (stat(possiblePath
, &statBuffer
) == 0);
388 if ( fTraceDylibSearching
)
389 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), possiblePath
);
391 result
.path
= strdup(possiblePath
);
392 result
.fileLen
= statBuffer
.st_size
;
393 result
.modTime
= statBuffer
.st_mtime
;
400 Options::FileInfo
Options::findLibrary(const char* rootName
)
403 const int rootNameLen
= strlen(rootName
);
404 // if rootName ends in .o there is no .a vs .dylib choice
405 if ( (rootNameLen
> 3) && (strcmp(&rootName
[rootNameLen
-2], ".o") == 0) ) {
406 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
407 it
!= fLibrarySearchPaths
.end();
409 const char* dir
= *it
;
410 if ( checkForFile("%s/%s", dir
, rootName
, result
) )
415 bool lookForDylibs
= ( fOutputKind
!= Options::kDyld
);
416 switch ( fLibrarySearchMode
) {
417 case kSearchAllDirsForDylibsThenAllDirsForArchives
:
418 // first look in all directories for just for dylibs
419 if ( lookForDylibs
) {
420 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
421 it
!= fLibrarySearchPaths
.end();
423 const char* dir
= *it
;
424 if ( checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
428 // next look in all directories for just for archives
429 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
430 it
!= fLibrarySearchPaths
.end();
432 const char* dir
= *it
;
433 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
438 case kSearchDylibAndArchiveInEachDir
:
439 // look in each directory for just for a dylib then for an archive
440 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
441 it
!= fLibrarySearchPaths
.end();
443 const char* dir
= *it
;
444 if ( lookForDylibs
&& checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
446 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
452 throwf("library not found for -l%s", rootName
);
456 Options::FileInfo
Options::findFramework(const char* rootName
)
458 struct stat statBuffer
;
459 const int rootNameLen
= strlen(rootName
);
460 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
461 it
!= fFrameworkSearchPaths
.end();
463 // ??? Shouldn't we be using String here and just initializing it?
464 // ??? Use str.c_str () to pull out the string for the stat call.
465 const char* dir
= *it
;
466 char possiblePath
[strlen(dir
)+2*rootNameLen
+20];
467 strcpy(possiblePath
, dir
);
468 strcat(possiblePath
, "/");
469 strcat(possiblePath
, rootName
);
470 strcat(possiblePath
, ".framework/");
471 strcat(possiblePath
, rootName
);
472 bool found
= (stat(possiblePath
, &statBuffer
) == 0);
473 if ( fTraceDylibSearching
)
474 printf("[Logging for XBS]%sfound framework: '%s'\n",
475 (found
? " " : " not "), possiblePath
);
478 result
.path
= strdup(possiblePath
);
479 result
.fileLen
= statBuffer
.st_size
;
480 result
.modTime
= statBuffer
.st_mtime
;
484 throwf("framework not found %s", rootName
);
487 Options::FileInfo
Options::findFile(const char* path
)
490 struct stat statBuffer
;
492 // if absolute path and not a .o file, the use SDK prefix
493 if ( (path
[0] == '/') && (strcmp(&path
[strlen(path
)-2], ".o") != 0) ) {
494 const int pathLen
= strlen(path
);
495 for (std::vector
<const char*>::iterator it
= fSDKPaths
.begin(); it
!= fSDKPaths
.end(); it
++) {
496 // ??? Shouldn't we be using String here?
497 const char* sdkPathDir
= *it
;
498 const int sdkPathDirLen
= strlen(sdkPathDir
);
499 char possiblePath
[sdkPathDirLen
+pathLen
+4];
500 strcpy(possiblePath
, sdkPathDir
);
501 if ( possiblePath
[sdkPathDirLen
-1] == '/' )
502 possiblePath
[sdkPathDirLen
-1] = '\0';
503 strcat(possiblePath
, path
);
504 if ( stat(possiblePath
, &statBuffer
) == 0 ) {
505 result
.path
= strdup(possiblePath
);
506 result
.fileLen
= statBuffer
.st_size
;
507 result
.modTime
= statBuffer
.st_mtime
;
513 if ( stat(path
, &statBuffer
) == 0 ) {
514 result
.path
= strdup(path
);
515 result
.fileLen
= statBuffer
.st_size
;
516 result
.modTime
= statBuffer
.st_mtime
;
520 // try @executable_path substitution
521 if ( (strncmp(path
, "@executable_path/", 17) == 0) && (fExecutablePath
!= NULL
) ) {
522 char newPath
[strlen(fExecutablePath
) + strlen(path
)];
523 strcpy(newPath
, fExecutablePath
);
524 char* addPoint
= strrchr(newPath
,'/');
525 if ( addPoint
!= NULL
)
526 strcpy(&addPoint
[1], &path
[17]);
528 strcpy(newPath
, &path
[17]);
529 if ( stat(newPath
, &statBuffer
) == 0 ) {
530 result
.path
= strdup(newPath
);
531 result
.fileLen
= statBuffer
.st_size
;
532 result
.modTime
= statBuffer
.st_mtime
;
538 throwf("file not found: %s", path
);
542 void Options::loadFileList(const char* fileOfPaths
)
545 const char* comma
= strrchr(fileOfPaths
, ',');
546 const char* prefix
= NULL
;
547 if ( comma
!= NULL
) {
549 int realFileOfPathsLen
= comma
-fileOfPaths
;
550 char realFileOfPaths
[realFileOfPathsLen
+1];
551 strncpy(realFileOfPaths
,fileOfPaths
, realFileOfPathsLen
);
552 realFileOfPaths
[realFileOfPathsLen
] = '\0';
553 file
= fopen(realFileOfPaths
, "r");
555 throwf("-filelist file not found: %s\n", realFileOfPaths
);
558 file
= fopen(fileOfPaths
, "r");
560 throwf("-filelist file not found: %s\n", fileOfPaths
);
564 while ( fgets(path
, 1024, file
) != NULL
) {
565 path
[PATH_MAX
-1] = '\0';
566 char* eol
= strchr(path
, '\n');
569 if ( prefix
!= NULL
) {
570 char builtPath
[strlen(prefix
)+strlen(path
)+2];
571 strcpy(builtPath
, prefix
);
572 strcat(builtPath
, "/");
573 strcat(builtPath
, path
);
574 fInputFiles
.push_back(findFile(builtPath
));
577 fInputFiles
.push_back(findFile(path
));
584 void Options::loadExportFile(const char* fileOfExports
, const char* option
, NameSet
& set
)
586 // read in whole file
587 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
589 throwf("can't open %s file: %s", option
, fileOfExports
);
590 struct stat stat_buf
;
591 ::fstat(fd
, &stat_buf
);
592 char* p
= (char*)malloc(stat_buf
.st_size
);
594 throwf("can't process %s file: %s", option
, fileOfExports
);
596 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
597 throwf("can't read %s file: %s", option
, fileOfExports
);
601 // parse into symbols and add to hash_set
602 char * const end
= &p
[stat_buf
.st_size
];
603 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
604 char* symbolStart
= NULL
;
605 for (char* s
= p
; s
< end
; ++s
) {
611 else if ( !isspace(*s
) ) {
619 // removing any trailing spaces
621 while ( isspace(*last
) ) {
625 set
.insert(symbolStart
);
636 if ( state
== inSymbol
) {
637 fprintf(stderr
, "ld64 warning: missing line-end at end of file \"%s\"\n", fileOfExports
);
638 int len
= end
-symbolStart
+1;
639 char* temp
= new char[len
];
640 strlcpy(temp
, symbolStart
, len
);
642 // remove any trailing spaces
643 char* last
= &temp
[len
-2];
644 while ( isspace(*last
) ) {
651 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
654 void Options::setUndefinedTreatment(const char* treatment
)
656 if ( treatment
== NULL
)
657 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
659 if ( strcmp(treatment
, "warning") == 0 )
660 fUndefinedTreatment
= kUndefinedWarning
;
661 else if ( strcmp(treatment
, "error") == 0 )
662 fUndefinedTreatment
= kUndefinedError
;
663 else if ( strcmp(treatment
, "suppress") == 0 )
664 fUndefinedTreatment
= kUndefinedSuppress
;
665 else if ( strcmp(treatment
, "dynamic_lookup") == 0 )
666 fUndefinedTreatment
= kUndefinedDynamicLookup
;
668 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
671 Options::Treatment
Options::parseTreatment(const char* treatment
)
673 if ( treatment
== NULL
)
676 if ( strcmp(treatment
, "warning") == 0 )
678 else if ( strcmp(treatment
, "error") == 0 )
680 else if ( strcmp(treatment
, "suppress") == 0 )
686 void Options::setVersionMin(const char* version
)
688 if ( version
== NULL
)
689 throw "-macosx_version_min argument missing";
691 if ( (strncmp(version
, "10.", 3) == 0) && isdigit(version
[3]) ) {
692 int num
= version
[3] - '0';
713 fprintf(stderr
, "ld64: unknown option to -macosx_version_min not 10.x");
717 void Options::setWeakReferenceMismatchTreatment(const char* treatment
)
719 if ( treatment
== NULL
)
720 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
722 if ( strcmp(treatment
, "error") == 0 )
723 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchError
;
724 else if ( strcmp(treatment
, "weak") == 0 )
725 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchWeak
;
726 else if ( strcmp(treatment
, "non-weak") == 0 )
727 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchNonWeak
;
729 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
732 Options::CommonsMode
Options::parseCommonsTreatment(const char* mode
)
735 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
737 if ( strcmp(mode
, "ignore_dylibs") == 0 )
738 return kCommonsIgnoreDylibs
;
739 else if ( strcmp(mode
, "use_dylibs") == 0 )
740 return kCommonsOverriddenByDylibs
;
741 else if ( strcmp(mode
, "error") == 0 )
742 return kCommonsConflictsDylibsError
;
744 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
747 void Options::setDylibInstallNameOverride(const char* paths
)
753 uint64_t Options::parseAddress(const char* addr
)
756 uint64_t result
= strtoull(addr
, &endptr
, 16);
761 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
764 uint32_t Options::parseVersionNumber(const char* versionString
)
770 x
= strtoul(versionString
, &end
, 10);
772 y
= strtoul(&end
[1], &end
, 10);
774 z
= strtoul(&end
[1], &end
, 10);
777 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
778 throwf("malformed version number: %s", versionString
);
780 return (x
<< 16) | ( y
<< 8 ) | z
;
783 void Options::parseSectionOrderFile(const char* segment
, const char* section
, const char* path
)
785 fprintf(stderr
, "ld64: warning -sectorder not yet supported for 64-bit code\n");
788 void Options::addSection(const char* segment
, const char* section
, const char* path
)
790 if ( strlen(segment
) > 16 )
791 throw "-seccreate segment name max 16 chars";
792 if ( strlen(section
) > 16 ) {
793 char* tmp
= strdup(section
);
795 fprintf(stderr
, "ld64 warning: -seccreate section name (%s) truncated to 16 chars (%s)\n", section
, tmp
);
799 // read in whole file
800 int fd
= ::open(path
, O_RDONLY
, 0);
802 throwf("can't open -sectcreate file: %s", path
);
803 struct stat stat_buf
;
804 ::fstat(fd
, &stat_buf
);
805 char* p
= (char*)malloc(stat_buf
.st_size
);
807 throwf("can't process -sectcreate file: %s", path
);
808 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
809 throwf("can't read -sectcreate file: %s", path
);
812 // record section to create
813 ExtraSection info
= { segment
, section
, path
, (uint8_t*)p
, stat_buf
.st_size
};
814 fExtraSections
.push_back(info
);
817 void Options::addSectionAlignment(const char* segment
, const char* section
, const char* alignmentStr
)
819 if ( strlen(segment
) > 16 )
820 throw "-sectalign segment name max 16 chars";
821 if ( strlen(section
) > 16 )
822 throw "-sectalign section name max 16 chars";
824 // argument to -sectalign is a hexadecimal number
826 unsigned long value
= strtoul(alignmentStr
, &endptr
, 16);
827 if ( *endptr
!= '\0')
828 throw "argument for -sectalign is not a hexadecimal number";
829 if ( value
> 0x8000 )
830 throw "argument for -sectalign must be less than or equal to 0x8000";
832 fprintf(stderr
, "ld64 warning: zero is not a valid -sectalign\n");
836 // alignment is power of 2 (e.g. page alignment = 12)
837 uint8_t alignment
= (uint8_t)log2(value
);
839 if ( (unsigned long)(1 << alignment
) != value
) {
840 fprintf(stderr
, "ld64 warning: alignment for -sectalign %s %s is not a power of two, using 0x%X\n",
841 segment
, section
, 1 << alignment
);
844 SectionAlignment info
= { segment
, section
, alignment
};
845 fSectionAlignments
.push_back(info
);
849 // Process all command line arguments.
851 // The only error checking done here is that each option is valid and if it has arguments
852 // that they too are valid.
854 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
855 // whichever was last on the command line is used.
857 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
859 void Options::parse(int argc
, const char* argv
[])
861 // pass one builds search list from -L and -F options
862 this->buildSearchPaths(argc
, argv
);
864 // reduce re-allocations
865 fInputFiles
.reserve(32);
867 // pass two parse all other options
868 for(int i
=1; i
< argc
; ++i
) {
869 const char* arg
= argv
[i
];
871 if ( arg
[0] == '-' ) {
873 // Since we don't care about the files passed, just the option names, we do this here.
875 fprintf (stderr
, "[Logging ld64 options]\t%s\n", arg
);
877 if ( (arg
[1] == 'L') || (arg
[1] == 'F') ) {
878 // previously handled by buildSearchPaths()
880 else if ( strcmp(arg
, "-arch") == 0 ) {
881 parseArch(argv
[++i
]);
883 else if ( strcmp(arg
, "-dynamic") == 0 ) {
886 else if ( strcmp(arg
, "-static") == 0 ) {
887 fOutputKind
= kStaticExecutable
;
889 else if ( strcmp(arg
, "-dylib") == 0 ) {
890 fOutputKind
= kDynamicLibrary
;
892 else if ( strcmp(arg
, "-bundle") == 0 ) {
893 fOutputKind
= kDynamicBundle
;
895 else if ( strcmp(arg
, "-dylinker") == 0 ) {
898 else if ( strcmp(arg
, "-execute") == 0 ) {
899 if ( fOutputKind
!= kStaticExecutable
)
900 fOutputKind
= kDynamicExecutable
;
902 else if ( strcmp(arg
, "-r") == 0 ) {
903 fOutputKind
= kObjectFile
;
905 else if ( strcmp(arg
, "-o") == 0 ) {
906 fOutputFile
= argv
[++i
];
908 else if ( arg
[1] == 'l' ) {
909 fInputFiles
.push_back(findLibrary(&arg
[2]));
911 // This causes a dylib to be weakly bound at
912 // link time. This corresponds to weak_import.
913 else if ( strncmp(arg
, "-weak-l", 7) == 0 ) {
914 FileInfo info
= findLibrary(&arg
[7]);
915 info
.options
.fWeakImport
= true;
916 fInputFiles
.push_back(info
);
918 // Avoid lazy binding.
920 else if ( strcmp(arg
, "-bind_at_load") == 0 ) {
923 else if ( strcmp(arg
, "-twolevel_namespace") == 0 ) {
924 fNameSpace
= kTwoLevelNameSpace
;
926 else if ( strcmp(arg
, "-flat_namespace") == 0 ) {
927 fNameSpace
= kFlatNameSpace
;
929 // Also sets a bit to ensure dyld causes everything
930 // in the namespace to be flat.
932 else if ( strcmp(arg
, "-force_flat_namespace") == 0 ) {
933 fNameSpace
= kForceFlatNameSpace
;
935 // Similar to --whole-archive.
936 else if ( strcmp(arg
, "-all_load") == 0 ) {
937 fReaderOptions
.fFullyLoadArchives
= true;
939 // Similar to --whole-archive, but for all ObjC classes.
940 else if ( strcmp(arg
, "-ObjC") == 0 ) {
941 fReaderOptions
.fLoadObjcClassesInArchives
= true;
943 // Library versioning.
944 else if ( strcmp(arg
, "-dylib_compatibility_version") == 0 ) {
945 fDylibCompatVersion
= parseVersionNumber(argv
[++i
]);
947 else if ( strcmp(arg
, "-dylib_current_version") == 0 ) {
948 fDylibCurrentVersion
= parseVersionNumber(argv
[++i
]);
950 else if ( strcmp(arg
, "-sectorder") == 0 ) {
951 parseSectionOrderFile(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
954 // ??? Deprecate segcreate.
955 // -sectcreate puts whole files into a section in the output.
956 else if ( (strcmp(arg
, "-sectcreate") == 0) || (strcmp(arg
, "-segcreate") == 0) ) {
957 addSection(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
960 // Since we have a full path in binary/library names we need to be able to override it.
961 else if ( (strcmp(arg
, "-dylib_install_name") == 0) || (strcmp(arg
, "-dylinker_install_name") == 0) ) {
962 fDylibInstallName
= argv
[++i
];
964 // Sets the base address of the output.
965 else if ( (strcmp(arg
, "-seg1addr") == 0) || (strcmp(arg
, "-image_base") == 0) ) {
966 fBaseAddress
= parseAddress(argv
[++i
]);
968 else if ( strcmp(arg
, "-e") == 0 ) {
969 fEntryName
= argv
[++i
];
971 // Same as -@ from the FSF linker.
972 else if ( strcmp(arg
, "-filelist") == 0 ) {
973 loadFileList(argv
[++i
]);
975 else if ( strcmp(arg
, "-keep_private_externs") == 0 ) {
976 fKeepPrivateExterns
= true;
979 else if ( strcmp(arg
, "-final_output") == 0 ) {
983 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
984 // just ensures that this happens for cross object file boundaries.
985 else if ( (strcmp(arg
, "-interposable") == 0) || (strcmp(arg
, "-multi_module") == 0)) {
986 fInterposable
= true;
988 // Default for -interposable/-multi_module/-single_module.
989 else if ( strcmp(arg
, "-single_module") == 0 ) {
990 fInterposable
= false;
992 else if ( strcmp(arg
, "-exported_symbols_list") == 0 ) {
993 if ( fExportMode
== kDontExportSome
)
994 throw "can't use -exported_symbols_list and -unexported_symbols_list";
995 fExportMode
= kExportSome
;
996 loadExportFile(argv
[++i
], "-exported_symbols_list", fExportSymbols
);
998 else if ( strcmp(arg
, "-unexported_symbols_list") == 0 ) {
999 if ( fExportMode
== kExportSome
)
1000 throw "can't use -exported_symbols_list and -unexported_symbols_list";
1001 fExportMode
= kDontExportSome
;
1002 loadExportFile(argv
[++i
], "-unexported_symbols_list", fDontExportSymbols
);
1005 else if ( strcmp(arg
, "-no_arch_warnings") == 0 ) {
1006 fIgnoreOtherArchFiles
= true;
1008 else if ( strcmp(arg
, "-force_cpusubtype_ALL") == 0 ) {
1009 fForceSubtypeAll
= true;
1011 // Similar to -weak-l but uses the absolute path name to the library.
1012 else if ( strcmp(arg
, "-weak_library") == 0 ) {
1013 FileInfo info
= findFile(argv
[++i
]);
1014 info
.options
.fWeakImport
= true;
1015 fInputFiles
.push_back(info
);
1017 else if ( strcmp(arg
, "-framework") == 0 ) {
1018 fInputFiles
.push_back(findFramework(argv
[++i
]));
1020 else if ( strcmp(arg
, "-weak_framework") == 0 ) {
1021 FileInfo info
= findFramework(argv
[++i
]);
1022 info
.options
.fWeakImport
= true;
1023 fInputFiles
.push_back(info
);
1025 // ??? Deprecate when we get -Bstatic/-Bdynamic.
1026 else if ( strcmp(arg
, "-search_paths_first") == 0 ) {
1027 fLibrarySearchMode
= kSearchDylibAndArchiveInEachDir
;
1029 else if ( strcmp(arg
, "-undefined") == 0 ) {
1030 setUndefinedTreatment(argv
[++i
]);
1032 // Debugging output flag.
1033 else if ( strcmp(arg
, "-arch_multiple") == 0 ) {
1034 fMessagesPrefixedWithArchitecture
= true;
1036 // Specify what to do with relocations in read only
1037 // sections like .text. Could be errors, warnings,
1038 // or suppressed. Currently we do nothing with the
1040 else if ( strcmp(arg
, "-read_only_relocs") == 0 ) {
1041 Treatment temp
= parseTreatment(argv
[++i
]);
1043 if ( temp
== kNULL
)
1044 throw "-read_only_relocs missing [ warning | error | suppress ]";
1045 else if ( temp
== kInvalid
)
1046 throw "invalid option to -read_only_relocs [ warning | error | suppress ]";
1048 // Specifies whether or not there are intra section
1049 // relocations and what to do when found. Could be
1050 // errors, warnings, or suppressed.
1051 else if ( strcmp(arg
, "-sect_diff_relocs") == 0 ) {
1052 fPICTreatment
= parseTreatment(argv
[++i
]);
1054 if ( fPICTreatment
== kNULL
)
1055 throw "-sect_diff_relocs missing [ warning | error | suppress ]";
1056 else if ( fPICTreatment
== kInvalid
)
1057 throw "invalid option to -sect_diff_relocs [ warning | error | suppress ]";
1059 // Warn, error or make strong a mismatch between weak
1060 // and non-weak references.
1061 else if ( strcmp(arg
, "-weak_reference_mismatches") == 0 ) {
1062 setWeakReferenceMismatchTreatment(argv
[++i
]);
1064 // For a deployment target of 10.3 and earlier ld64 will
1065 // prebind an executable with 0s in all addresses that
1066 // are prebound. This can then be fixed up by update_prebinding
1067 // later. Prebinding is less useful on 10.4 and greater.
1068 else if ( strcmp(arg
, "-prebind") == 0 ) {
1071 else if ( strcmp(arg
, "-noprebind") == 0 ) {
1075 else if ( strcmp(arg
, "-prebind_allow_overlap") == 0 ) {
1076 // Do not handle and suppress warnings always.
1079 else if ( strcmp(arg
, "-prebind_all_twolevel_modules") == 0 ) {
1083 else if ( strcmp(arg
, "-noprebind_all_twolevel_modules") == 0 ) {
1086 // Sets a bit in the main executable only that causes fix_prebinding
1087 // not to run. This is always set.
1088 else if ( strcmp(arg
, "-nofixprebinding") == 0 ) {
1091 // This should probably be deprecated when we respect -L and -F
1092 // when searching for libraries.
1093 else if ( strcmp(arg
, "-dylib_file") == 0 ) {
1094 setDylibInstallNameOverride(argv
[++i
]);
1096 // Allows us to rewrite full paths to be relocatable based on
1097 // the path name of the executable.
1098 else if ( strcmp(arg
, "-executable_path") == 0 ) {
1099 fExecutablePath
= argv
[++i
];
1100 if ( (fExecutablePath
== NULL
) || (fExecutablePath
[0] == '-') )
1101 throw "-executable_path missing <path>";
1104 // Aligns all segments to the power of 2 boundary specified.
1105 else if ( strcmp(arg
, "-segalign") == 0 ) {
1109 // Puts a specified segment at a particular address that must
1110 // be a multiple of the segment alignment.
1111 else if ( strcmp(arg
, "-segaddr") == 0 ) {
1115 // ??? Deprecate when we deprecate split-seg.
1116 else if ( strcmp(arg
, "-segs_read_only_addr") == 0 ) {
1120 // ??? Deprecate when we deprecate split-seg.
1121 else if ( strcmp(arg
, "-segs_read_write_addr") == 0 ) {
1125 // ??? Deprecate when we get rid of basing at build time.
1126 else if ( strcmp(arg
, "-seg_addr_table") == 0 ) {
1131 else if ( strcmp(arg
, "-seg_addr_table_filename") == 0 ) {
1135 else if ( strcmp(arg
, "-segprot") == 0 ) {
1139 else if ( strcmp(arg
, "-pagezero_size") == 0 ) {
1140 fZeroPageSize
= parseAddress(argv
[++i
]);
1141 uint64_t temp
= fZeroPageSize
& (-4096); // page align
1142 if ( fZeroPageSize
!= temp
)
1143 fprintf(stderr
, "ld64: warning, -pagezero_size not page aligned, rounding down\n");
1144 fZeroPageSize
= temp
;
1146 else if ( strcmp(arg
, "-stack_addr") == 0 ) {
1147 fStackAddr
= parseAddress(argv
[++i
]);
1149 else if ( strcmp(arg
, "-stack_size") == 0 ) {
1150 fStackSize
= parseAddress(argv
[++i
]);
1152 else if ( strcmp(arg
, "-allow_stack_execute") == 0 ) {
1153 fExecutableStack
= true;
1155 else if ( strcmp(arg
, "-sectalign") == 0 ) {
1156 addSectionAlignment(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1159 else if ( strcmp(arg
, "-sectorder_detail") == 0 ) {
1162 else if ( strcmp(arg
, "-sectobjectsymbols") == 0 ) {
1166 else if ( strcmp(arg
, "-bundle_loader") == 0 ) {
1167 fBundleLoader
= argv
[++i
];
1168 if ( (fBundleLoader
== NULL
) || (fBundleLoader
[0] == '-') )
1169 throw "-bundle_loader missing <path>";
1170 FileInfo info
= findFile(fBundleLoader
);
1171 info
.options
.fBundleLoader
= true;
1172 fInputFiles
.push_back(info
);
1174 else if ( strcmp(arg
, "-private_bundle") == 0 ) {
1177 else if ( strcmp(arg
, "-twolevel_namespace_hints") == 0 ) {
1180 // Use this flag to set default behavior for deployement targets.
1181 else if ( strcmp(arg
, "-macosx_version_min") == 0 ) {
1182 setVersionMin(argv
[++i
]);
1184 // This option (unlike -m below) only affects how we warn
1185 // on multiple definitions inside dynamic libraries.
1186 else if ( strcmp(arg
, "-multiply_defined") == 0 ) {
1187 fMultiplyDefinedDynamic
= parseTreatment(argv
[++i
]);
1189 if ( fMultiplyDefinedDynamic
== kNULL
)
1190 throw "-multiply_defined missing [ warning | error | suppress ]";
1191 else if ( fMultiplyDefinedDynamic
== kInvalid
)
1192 throw "invalid option to -multiply_defined [ warning | error | suppress ]";
1194 else if ( strcmp(arg
, "-multiply_defined_unused") == 0 ) {
1195 fMultiplyDefinedUnused
= parseTreatment(argv
[++i
]);
1197 if ( fMultiplyDefinedUnused
== kNULL
)
1198 throw "-multiply_defined_unused missing [ warning | error | suppress ]";
1199 else if ( fMultiplyDefinedUnused
== kInvalid
)
1200 throw "invalid option to -multiply_defined_unused [ warning | error | suppress ]";
1202 else if ( strcmp(arg
, "-nomultidefs") == 0 ) {
1205 // Display each file in which the argument symbol appears and whether
1206 // the file defines or references it. This option takes an argument
1207 // as -y<symbol> note that there is no space.
1208 else if ( strncmp(arg
, "-y", 2) == 0 ) {
1209 const char* name
= &arg
[2];
1212 throw "-y missing argument";
1214 fTraceSymbols
.push_back(name
);
1216 // Same output as -y, but output <arg> number of undefined symbols only.
1217 else if ( strcmp(arg
, "-Y") == 0 ) {
1219 fLimitUndefinedSymbols
= strtoul (argv
[++i
], &endptr
, 10);
1222 throw "invalid argument for -Y [decimal number]";
1224 // This option affects all objects linked into the final result.
1225 else if ( strcmp(arg
, "-m") == 0 ) {
1226 fWarnOnMultiplyDefined
= true;
1228 else if ( (strcmp(arg
, "-why_load") == 0) || (strcmp(arg
, "-whyload") == 0) ) {
1229 fReaderOptions
.fWhyLoad
= true;
1231 else if ( strcmp(arg
, "-why_live") == 0 ) {
1232 const char* name
= argv
[++i
];
1234 throw "-why_live missing symbol name argument";
1235 fWhyLive
.insert(name
);
1237 else if ( strcmp(arg
, "-u") == 0 ) {
1238 const char* name
= argv
[++i
];
1240 throw "-u missing argument";
1241 fInitialUndefines
.push_back(name
);
1243 else if ( strcmp(arg
, "-U") == 0 ) {
1247 else if ( strcmp(arg
, "-s") == 0 ) {
1248 fStripLocalSymbols
= true;
1249 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
1251 else if ( strcmp(arg
, "-x") == 0 ) {
1252 fStripLocalSymbols
= true;
1254 else if ( strcmp(arg
, "-S") == 0 ) {
1255 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
1257 else if ( strcmp(arg
, "-X") == 0 ) {
1260 else if ( strcmp(arg
, "-Si") == 0 ) {
1261 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoFull
;
1263 else if ( strcmp(arg
, "-b") == 0 ) {
1266 else if ( strcmp(arg
, "-Sn") == 0 ) {
1267 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoFull
;
1269 else if ( strcmp(arg
, "-Sp") == 0 ) {
1270 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoMinimal
;
1272 else if ( strcmp(arg
, "-dead_strip") == 0 ) {
1273 fDeadStrip
= kDeadStripOnPlusUnusedInits
;
1275 else if ( strcmp(arg
, "-no_dead_strip_inits_and_terms") == 0 ) {
1276 fDeadStrip
= kDeadStripOn
;
1278 else if ( strcmp(arg
, "-w") == 0 ) {
1281 else if ( strcmp(arg
, "-arch_errors_fatal") == 0 ) {
1284 else if ( strcmp(arg
, "-M") == 0 ) {
1287 else if ( strcmp(arg
, "-whatsloaded") == 0 ) {
1290 else if ( strcmp(arg
, "-headerpad") == 0 ) {
1291 const char* size
= argv
[++i
];
1293 throw "-headerpad missing argument";
1294 fMinimumHeaderPad
= parseAddress(size
);
1296 else if ( strcmp(arg
, "-headerpad_max_install_names") == 0 ) {
1299 else if ( strcmp(arg
, "-t") == 0 ) {
1302 else if ( strcmp(arg
, "-A") == 0 ) {
1306 else if ( strcmp(arg
, "-umbrella") == 0 ) {
1307 const char* name
= argv
[++i
];
1309 throw "-umbrella missing argument";
1310 fUmbrellaName
= name
;
1312 else if ( strcmp(arg
, "-allowable_client") == 0 ) {
1313 const char* name
= argv
[++i
];
1316 throw "-allowable_client missing argument";
1318 fAllowableClients
.push_back(name
);
1320 else if ( strcmp(arg
, "-client_name") == 0 ) {
1321 const char* name
= argv
[++i
];
1324 throw "-client_name missing argument";
1328 else if ( strcmp(arg
, "-sub_umbrella") == 0 ) {
1329 const char* name
= argv
[++i
];
1331 throw "-sub_umbrella missing argument";
1332 fSubUmbellas
.push_back(name
);
1334 else if ( strcmp(arg
, "-sub_library") == 0 ) {
1335 const char* name
= argv
[++i
];
1337 throw "-sub_library missing argument";
1338 fSubLibraries
.push_back(name
);
1340 else if ( strcmp(arg
, "-init") == 0 ) {
1341 const char* name
= argv
[++i
];
1343 throw "-init missing argument";
1344 fInitFunctionName
= name
;
1346 else if ( strcmp(arg
, "-dot") == 0 ) {
1347 const char* name
= argv
[++i
];
1349 throw "-dot missing argument";
1350 fDotOutputFile
= name
;
1352 else if ( strcmp(arg
, "-warn_commons") == 0 ) {
1353 fWarnCommons
= true;
1355 else if ( strcmp(arg
, "-commons") == 0 ) {
1356 fCommonsMode
= parseCommonsTreatment(argv
[++i
]);
1358 else if ( strcmp(arg
, "-keep_relocs") == 0 ) {
1359 fKeepRelocations
= true;
1361 else if ( strcmp(arg
, "-warn_stabs") == 0 ) {
1364 else if ( strcmp(arg
, "-pause") == 0 ) {
1367 else if ( strcmp(arg
, "-print_statistics") == 0 ) {
1370 else if ( strcmp(arg
, "-d") == 0 ) {
1371 fMakeTentativeDefinitionsReal
= true;
1373 else if ( strcmp(arg
, "-v") == 0 ) {
1374 // previously handled by buildSearchPaths()
1376 else if ( strcmp(arg
, "-Z") == 0 ) {
1377 // previously handled by buildSearchPaths()
1379 else if ( strcmp(arg
, "-syslibroot") == 0 ) {
1381 // previously handled by buildSearchPaths()
1383 else if ( strcmp(arg
, "-no_uuid") == 0 ) {
1386 // put this last so that it does not interfer with other options starting with 'i'
1387 else if ( strncmp(arg
, "-i", 2) == 0 ) {
1388 fprintf(stderr
, "ld64: -i option (indirect symbols) not supported\n");
1391 throwf("unknown option: %s", arg
);
1395 fInputFiles
.push_back(findFile(arg
));
1403 // -syslibroot <path> is used for SDK support.
1404 // The rule is that all search paths (both explicit and default) are
1405 // checked to see if they exist in the SDK. If so, that path is
1406 // replaced with the sdk prefixed path. If not, that search path
1407 // is used as is. If multiple -syslibroot options are specified
1408 // their directory structures are logically overlayed and files
1409 // from sdks specified earlier on the command line used before later ones.
1411 void Options::buildSearchPaths(int argc
, const char* argv
[])
1413 bool addStandardLibraryDirectories
= true;
1414 std::vector
<const char*> libraryPaths
;
1415 std::vector
<const char*> frameworkPaths
;
1416 libraryPaths
.reserve(10);
1417 frameworkPaths
.reserve(10);
1418 // scan through argv looking for -L, -F, -Z, and -syslibroot options
1419 for(int i
=0; i
< argc
; ++i
) {
1420 if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'L') )
1421 libraryPaths
.push_back(&argv
[i
][2]);
1422 else if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'F') )
1423 frameworkPaths
.push_back(&argv
[i
][2]);
1424 else if ( strcmp(argv
[i
], "-Z") == 0 )
1425 addStandardLibraryDirectories
= false;
1426 else if ( strcmp(argv
[i
], "-v") == 0 ) {
1428 extern const char ld64VersionString
[];
1429 fprintf(stderr
, "%s", ld64VersionString
);
1430 // if only -v specified, exit cleanly
1434 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
1435 const char* path
= argv
[++i
];
1437 throw "-syslibroot missing argument";
1438 fSDKPaths
.push_back(path
);
1441 if ( addStandardLibraryDirectories
) {
1442 libraryPaths
.push_back("/usr/lib");
1443 libraryPaths
.push_back("/usr/local/lib");
1445 frameworkPaths
.push_back("/Library/Frameworks/");
1446 frameworkPaths
.push_back("/Network/Library/Frameworks/");
1447 frameworkPaths
.push_back("/System/Library/Frameworks/");
1450 // now merge sdk and library paths to make real search paths
1451 fLibrarySearchPaths
.reserve(libraryPaths
.size()*(fSDKPaths
.size()+1));
1452 for (std::vector
<const char*>::iterator it
= libraryPaths
.begin(); it
!= libraryPaths
.end(); it
++) {
1453 const char* libDir
= *it
;
1454 bool sdkOverride
= false;
1455 if ( libDir
[0] == '/' ) {
1456 char betterLibDir
[PATH_MAX
];
1457 if ( strstr(libDir
, "/..") != NULL
) {
1458 if ( realpath(libDir
, betterLibDir
) != NULL
)
1459 libDir
= strdup(betterLibDir
);
1461 const int libDirLen
= strlen(libDir
);
1462 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
1463 // ??? Should be using string here.
1464 const char* sdkDir
= *sdkit
;
1465 const int sdkDirLen
= strlen(sdkDir
);
1466 char newPath
[libDirLen
+ sdkDirLen
+4];
1467 strcpy(newPath
, sdkDir
);
1468 if ( newPath
[sdkDirLen
-1] == '/' )
1469 newPath
[sdkDirLen
-1] = '\0';
1470 strcat(newPath
, libDir
);
1471 struct stat statBuffer
;
1472 if ( stat(newPath
, &statBuffer
) == 0 ) {
1473 fLibrarySearchPaths
.push_back(strdup(newPath
));
1479 fLibrarySearchPaths
.push_back(libDir
);
1482 // now merge sdk and framework paths to make real search paths
1483 fFrameworkSearchPaths
.reserve(frameworkPaths
.size()*(fSDKPaths
.size()+1));
1484 for (std::vector
<const char*>::iterator it
= frameworkPaths
.begin(); it
!= frameworkPaths
.end(); it
++) {
1485 const char* frameworkDir
= *it
;
1486 bool sdkOverride
= false;
1487 if ( frameworkDir
[0] == '/' ) {
1488 char betterFrameworkDir
[PATH_MAX
];
1489 if ( strstr(frameworkDir
, "/..") != NULL
) {
1490 if ( realpath(frameworkDir
, betterFrameworkDir
) != NULL
)
1491 frameworkDir
= strdup(betterFrameworkDir
);
1493 const int frameworkDirLen
= strlen(frameworkDir
);
1494 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
1495 // ??? Should be using string here
1496 const char* sdkDir
= *sdkit
;
1497 const int sdkDirLen
= strlen(sdkDir
);
1498 char newPath
[frameworkDirLen
+ sdkDirLen
+4];
1499 strcpy(newPath
, sdkDir
);
1500 if ( newPath
[sdkDirLen
-1] == '/' )
1501 newPath
[sdkDirLen
-1] = '\0';
1502 strcat(newPath
, frameworkDir
);
1503 struct stat statBuffer
;
1504 if ( stat(newPath
, &statBuffer
) == 0 ) {
1505 fFrameworkSearchPaths
.push_back(strdup(newPath
));
1511 fFrameworkSearchPaths
.push_back(frameworkDir
);
1515 fprintf(stderr
,"Library search paths:\n");
1516 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
1517 it
!= fLibrarySearchPaths
.end();
1519 fprintf(stderr
,"\t%s\n", *it
);
1520 fprintf(stderr
,"Framework search paths:\n");
1521 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
1522 it
!= fFrameworkSearchPaths
.end();
1524 fprintf(stderr
,"\t%s\n", *it
);
1528 // this is run before the command line is parsed
1529 void Options::parsePreCommandLineEnvironmentSettings()
1531 if ((getenv("LD_TRACE_ARCHIVES") != NULL
)
1532 || (getenv("RC_TRACE_ARCHIVES") != NULL
))
1533 fReaderOptions
.fTraceArchives
= true;
1535 if ((getenv("LD_TRACE_DYLIBS") != NULL
)
1536 || (getenv("RC_TRACE_DYLIBS") != NULL
)) {
1537 fReaderOptions
.fTraceDylibs
= true;
1538 fReaderOptions
.fTraceIndirectDylibs
= true;
1541 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL
) {
1542 fTraceDylibSearching
= true;
1545 if (getenv("LD_PRINT_OPTIONS") != NULL
)
1546 fPrintOptions
= true;
1548 if (fReaderOptions
.fTraceDylibs
|| fReaderOptions
.fTraceArchives
)
1549 fReaderOptions
.fTraceOutputFile
= getenv("LD_TRACE_FILE");
1552 // this is run after the command line is parsed
1553 void Options::parsePostCommandLineEnvironmentSettings()
1555 // when building a dynamic main executable, default any use of @executable_path to output path
1556 if ( fExecutablePath
== NULL
&& (fOutputKind
== kDynamicExecutable
) ) {
1557 fExecutablePath
= fOutputFile
;
1562 void Options::reconfigureDefaults()
1564 // sync reader options
1565 switch ( fOutputKind
) {
1566 case Options::kObjectFile
:
1567 fReaderOptions
.fForFinalLinkedImage
= false;
1569 case Options::kDynamicExecutable
:
1570 case Options::kStaticExecutable
:
1571 case Options::kDynamicLibrary
:
1572 case Options::kDynamicBundle
:
1573 case Options::kDyld
:
1574 fReaderOptions
.fForFinalLinkedImage
= true;
1578 // set default min OS version
1579 if ( fVersionMin
== kMinUnset
) {
1580 switch ( fArchitecture
) {
1581 case CPU_TYPE_POWERPC
:
1582 fVersionMin
= k10_2
;
1585 case CPU_TYPE_POWERPC64
:
1586 case CPU_TYPE_X86_64
:
1587 fVersionMin
= k10_4
;
1589 // architecture not specified
1590 fVersionMin
= k10_4
;
1595 // adjust min based on architecture
1596 switch ( fArchitecture
) {
1598 if ( fVersionMin
< k10_4
) {
1599 //fprintf(stderr, "ld64 warning: -macosx_version_min should be 10.4 or later for i386\n");
1600 fVersionMin
= k10_4
;
1603 case CPU_TYPE_POWERPC64
:
1604 if ( fVersionMin
< k10_4
) {
1605 //fprintf(stderr, "ld64 warning: -macosx_version_min should be 10.4 or later for ppc64\n");
1606 fVersionMin
= k10_4
;
1609 case CPU_TYPE_X86_64
:
1610 if ( fVersionMin
< k10_4
) {
1611 //fprintf(stderr, "ld64 warning: -macosx_version_min should be 10.4 or later for x86_64\n");
1612 fVersionMin
= k10_4
;
1619 void Options::checkIllegalOptionCombinations()
1621 // check -undefined setting
1622 switch ( fUndefinedTreatment
) {
1623 case kUndefinedError
:
1624 case kUndefinedDynamicLookup
:
1627 case kUndefinedWarning
:
1628 case kUndefinedSuppress
:
1629 // requires flat namespace
1630 if ( fNameSpace
== kTwoLevelNameSpace
)
1631 throw "can't use -undefined warning or suppress with -twolevel_namespace";
1635 // unify -sub_umbrella with dylibs
1636 for (std::vector
<const char*>::iterator it
= fSubUmbellas
.begin(); it
!= fSubUmbellas
.end(); it
++) {
1637 const char* subUmbrella
= *it
;
1639 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
1640 Options::FileInfo
& info
= *fit
;
1641 const char* lastSlash
= strrchr(info
.path
, '/');
1642 if ( lastSlash
== NULL
)
1643 lastSlash
= info
.path
- 1;
1644 if ( strcmp(&lastSlash
[1], subUmbrella
) == 0 ) {
1645 info
.options
.fReExport
= true;
1651 fprintf(stderr
, "ld64 warning: -sub_umbrella %s does not match a supplied dylib\n", subUmbrella
);
1654 // unify -sub_library with dylibs
1655 for (std::vector
<const char*>::iterator it
= fSubLibraries
.begin(); it
!= fSubLibraries
.end(); it
++) {
1656 const char* subLibrary
= *it
;
1658 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
1659 Options::FileInfo
& info
= *fit
;
1660 const char* lastSlash
= strrchr(info
.path
, '/');
1661 if ( lastSlash
== NULL
)
1662 lastSlash
= info
.path
- 1;
1663 const char* dot
= strchr(&lastSlash
[1], '.');
1665 dot
= &lastSlash
[strlen(lastSlash
)];
1666 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
1667 info
.options
.fReExport
= true;
1673 fprintf(stderr
, "ld64 warning: -sub_library %s does not match a supplied dylib\n", subLibrary
);
1676 // sync reader options
1677 if ( fNameSpace
!= kTwoLevelNameSpace
)
1678 fReaderOptions
.fFlatNamespace
= true;
1680 // check -stack_addr
1681 if ( fStackAddr
!= 0 ) {
1682 switch (fArchitecture
) {
1684 case CPU_TYPE_POWERPC
:
1685 if ( fStackAddr
> 0xFFFFFFFF )
1686 throw "-stack_addr must be < 4G for 32-bit processes";
1688 case CPU_TYPE_POWERPC64
:
1689 case CPU_TYPE_X86_64
:
1692 if ( (fStackAddr
& -4096) != fStackAddr
)
1693 throw "-stack_addr must be multiples of 4K";
1694 if ( fStackSize
== 0 )
1695 throw "-stack_addr must be used with -stack_size";
1698 // check -stack_size
1699 if ( fStackSize
!= 0 ) {
1700 switch (fArchitecture
) {
1702 case CPU_TYPE_POWERPC
:
1703 if ( fStackSize
> 0xFFFFFFFF )
1704 throw "-stack_size must be < 4G for 32-bit processes";
1705 if ( fStackAddr
== 0 ) {
1706 fStackAddr
= 0xC0000000;
1708 if ( (fStackAddr
> 0xB0000000) && ((fStackAddr
-fStackSize
) < 0xB0000000) )
1709 fprintf(stderr
, "ld64 warning: custom stack placement overlaps and will disable shared region\n");
1711 case CPU_TYPE_POWERPC64
:
1712 case CPU_TYPE_X86_64
:
1713 if ( fStackAddr
== 0 ) {
1714 fStackAddr
= 0x0007FFFF00000000LL
;
1718 if ( (fStackSize
& -4096) != fStackSize
)
1719 throw "-stack_size must be multiples of 4K";
1720 switch ( fOutputKind
) {
1721 case Options::kDynamicExecutable
:
1722 case Options::kStaticExecutable
:
1723 // custom stack size only legal when building main executable
1725 case Options::kDynamicLibrary
:
1726 case Options::kDynamicBundle
:
1727 case Options::kObjectFile
:
1728 case Options::kDyld
:
1729 throw "-stack_size option can only be used when linking a main executable";
1733 // check that -allow_stack_execute is only used with main executables
1734 if ( fExecutableStack
) {
1735 switch ( fOutputKind
) {
1736 case Options::kDynamicExecutable
:
1737 case Options::kStaticExecutable
:
1738 // -allow_stack_execute size only legal when building main executable
1740 case Options::kDynamicLibrary
:
1741 case Options::kDynamicBundle
:
1742 case Options::kObjectFile
:
1743 case Options::kDyld
:
1744 throw "-allow_stack_execute option can only be used when linking a main executable";
1748 // check -client_name is only used when -bundle is specified
1749 if ( (fClientName
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
1750 throw "-client_name can only be used with -bundle";
1752 // check -init is only used when building a dylib
1753 if ( (fInitFunctionName
!= NULL
) && (fOutputKind
!= Options::kDynamicLibrary
) )
1754 throw "-init can only be used with -dynamiclib";
1756 // check -bundle_loader only used with -bundle
1757 if ( (fBundleLoader
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
1758 throw "-bundle_loader can only be used with -bundle";
1760 // check -d can only be used with -r
1761 if ( fMakeTentativeDefinitionsReal
&& (fOutputKind
!= Options::kObjectFile
) )
1762 throw "-d can only be used with -r";
1764 // make sure all required exported symbols exist
1765 for (NameSet::iterator it
=fExportSymbols
.begin(); it
!= fExportSymbols
.end(); it
++) {
1766 const char* name
= *it
;
1767 // never export .eh symbols
1768 if ( strcmp(&name
[strlen(name
)-3], ".eh") != 0 )
1769 fInitialUndefines
.push_back(name
);
1772 // make sure that -init symbol exist
1773 if ( fInitFunctionName
!= NULL
)
1774 fInitialUndefines
.push_back(fInitFunctionName
);
1776 if ( fZeroPageSize
== ULLONG_MAX
) {
1777 // zero page size not specified on command line, set default
1778 switch (fArchitecture
) {
1780 case CPU_TYPE_POWERPC
:
1781 // first 4KB for 32-bit architectures
1782 fZeroPageSize
= 0x1000;
1784 case CPU_TYPE_POWERPC64
:
1785 // first 4GB for ppc64 on 10.5
1786 if ( fVersionMin
>= k10_5
)
1787 fZeroPageSize
= 0x100000000ULL
;
1789 fZeroPageSize
= 0x1000; // 10.4 dyld may not be able to handle >4GB zero page
1791 case CPU_TYPE_X86_64
:
1792 // first 4GB for x86_64 on all OS's
1793 fZeroPageSize
= 0x100000000ULL
;
1796 // if -arch not used, default to 4K zero-page
1797 fZeroPageSize
= 0x1000;
1801 switch ( fOutputKind
) {
1802 case Options::kDynamicExecutable
:
1803 case Options::kStaticExecutable
:
1804 // -pagezero_size size only legal when building main executable
1806 case Options::kDynamicLibrary
:
1807 case Options::kDynamicBundle
:
1808 case Options::kObjectFile
:
1809 case Options::kDyld
:
1810 throw "-pagezero_size option can only be used when linking a main executable";
1814 // -dead_strip and -r are incompatible
1815 if ( (fDeadStrip
!= kDeadStripOff
) && (fOutputKind
== Options::kObjectFile
) )
1816 throw "-r and -dead_strip cannot be used together\n";