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>
34 void throwf(const char* format
, ...)
38 va_start(list
, format
);
39 vasprintf(&p
, format
, list
);
46 Options::Options(int argc
, const char* argv
[])
47 : fOutputFile("a.out"), fArchitecture(0), fOutputKind(kDynamicExecutable
), fBindAtLoad(false),
48 fStripLocalSymbols(false), fKeepPrivateExterns(false),
49 fInterposable(false), fIgnoreOtherArchFiles(false), fForceSubtypeAll(false), fDeadStrip(kDeadStripOff
),
50 fVersionMin(kMinUnset
),fNameSpace(kTwoLevelNameSpace
),
51 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL
), fEntryName("start"), fBaseAddress(0),
52 fExportMode(kExportDefault
), fLibrarySearchMode(kSearchAllDirsForDylibsThenAllDirsForArchives
),
53 fUndefinedTreatment(kUndefinedError
), fMessagesPrefixedWithArchitecture(false), fPICTreatment(kError
),
54 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchError
), fMultiplyDefinedDynamic(kWarning
),
55 fMultiplyDefinedUnused(kSuppress
), fWarnOnMultiplyDefined(false), fClientName(NULL
),
56 fUmbrellaName(NULL
), fInitFunctionName(NULL
), fDotOutputFile(NULL
), fExecutablePath(NULL
), fBundleLoader(NULL
),
57 fZeroPageSize(ULLONG_MAX
), fStackSize(0), fStackAddr(0), fExecutableStack(false), fMinimumHeaderPad(0),
58 fCommonsMode(kCommonsIgnoreDylibs
), fWarnCommons(false), fVerbose(false), fKeepRelocations(false),
59 fEmitUUID(true),fWarnStabs(false),
60 fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
61 fMakeTentativeDefinitionsReal(false)
63 this->parsePreCommandLineEnvironmentSettings();
64 this->parse(argc
, argv
);
65 this->parsePostCommandLineEnvironmentSettings();
66 this->reconfigureDefaults();
67 this->checkIllegalOptionCombinations();
74 const ObjectFile::ReaderOptions
& Options::readerOptions()
76 return fReaderOptions
;
79 cpu_type_t
Options::architecture()
84 const char* Options::getOutputFilePath()
89 std::vector
<Options::FileInfo
>& Options::getInputFiles()
94 Options::OutputKind
Options::outputKind()
99 bool Options::stripLocalSymbols()
101 return fStripLocalSymbols
;
104 bool Options::bindAtLoad()
109 bool Options::prebind()
114 bool Options::fullyLoadArchives()
116 return fReaderOptions
.fFullyLoadArchives
;
119 Options::NameSpace
Options::nameSpace()
124 const char* Options::installPath()
126 if ( fDylibInstallName
!= NULL
)
127 return fDylibInstallName
;
132 uint32_t Options::currentVersion()
134 return fDylibCurrentVersion
;
137 uint32_t Options::compatibilityVersion()
139 return fDylibCompatVersion
;
142 const char* Options::entryName()
147 uint64_t Options::baseAddress()
152 bool Options::keepPrivateExterns()
154 return fKeepPrivateExterns
;
157 bool Options::interposable()
159 return fInterposable
;
162 bool Options::ignoreOtherArchInputFiles()
164 return fIgnoreOtherArchFiles
;
167 bool Options::forceCpuSubtypeAll()
169 return fForceSubtypeAll
;
172 bool Options::traceDylibs()
174 return fReaderOptions
.fTraceDylibs
;
177 bool Options::traceArchives()
179 return fReaderOptions
.fTraceArchives
;
182 Options::UndefinedTreatment
Options::undefinedTreatment()
184 return fUndefinedTreatment
;
187 Options::VersionMin
Options::macosxVersionMin()
192 Options::WeakReferenceMismatchTreatment
Options::weakReferenceMismatchTreatment()
194 return fWeakReferenceMismatchTreatment
;
197 Options::Treatment
Options::multipleDefinitionsInDylibs()
199 return fMultiplyDefinedDynamic
;
202 Options::Treatment
Options::overridingDefinitionInDependentDylib()
204 return fMultiplyDefinedUnused
;
207 bool Options::warnOnMultipleDefinitionsInObjectFiles()
209 return fWarnOnMultiplyDefined
;
212 const char* Options::umbrellaName()
214 return fUmbrellaName
;
217 std::vector
<const char*>& Options::allowableClients()
219 return fAllowableClients
;
222 const char* Options::clientName()
227 uint64_t Options::zeroPageSize()
229 return fZeroPageSize
;
232 bool Options::hasCustomStack()
234 return (fStackSize
!= 0);
237 uint64_t Options::customStackSize()
242 uint64_t Options::customStackAddr()
247 bool Options::hasExecutableStack()
249 return fExecutableStack
;
252 std::vector
<const char*>& Options::initialUndefines()
254 return fInitialUndefines
;
257 bool Options::printWhyLive(const char* symbolName
)
259 return ( fWhyLive
.find(symbolName
) != fWhyLive
.end() );
262 std::vector
<const char*>& Options::traceSymbols()
264 return fTraceSymbols
;
267 const char* Options::initFunctionName()
269 return fInitFunctionName
;
272 const char* Options::dotOutputFile()
274 return fDotOutputFile
;
277 bool Options::hasExportRestrictList()
279 return (fExportMode
!= kExportDefault
);
282 bool Options::allGlobalsAreDeadStripRoots()
284 // -exported_symbols_list means globals are not exported by default
285 if ( fExportMode
== kExportSome
)
288 switch ( fOutputKind
) {
289 case Options::kDynamicExecutable
:
290 case Options::kStaticExecutable
:
291 // by default unused globals in a main executable are stripped
293 case Options::kDynamicLibrary
:
294 case Options::kDynamicBundle
:
295 case Options::kObjectFile
:
302 uint32_t Options::minimumHeaderPad()
304 return fMinimumHeaderPad
;
307 std::vector
<Options::ExtraSection
>& Options::extraSections()
309 return fExtraSections
;
312 std::vector
<Options::SectionAlignment
>& Options::sectionAlignments()
314 return fSectionAlignments
;
317 Options::CommonsMode
Options::commonsMode()
322 bool Options::warnCommons()
327 bool Options::keepRelocations()
329 return fKeepRelocations
;
332 bool Options::emitUUID()
337 bool Options::warnStabs()
342 const char* Options::executablePath()
344 return fExecutablePath
;
347 Options::DeadStripMode
Options::deadStrip()
352 bool Options::shouldExport(const char* symbolName
)
354 switch (fExportMode
) {
356 return ( fExportSymbols
.find(symbolName
) != fExportSymbols
.end() );
357 case kDontExportSome
:
358 return ( fDontExportSymbols
.find(symbolName
) == fDontExportSymbols
.end() );
362 throw "internal error";
365 void Options::parseArch(const char* architecture
)
367 if ( architecture
== NULL
)
368 throw "-arch must be followed by an architecture string";
369 if ( strcmp(architecture
, "ppc") == 0 )
370 fArchitecture
= CPU_TYPE_POWERPC
;
371 else if ( strcmp(architecture
, "ppc64") == 0 )
372 fArchitecture
= CPU_TYPE_POWERPC64
;
373 else if ( strcmp(architecture
, "i386") == 0 )
374 fArchitecture
= CPU_TYPE_I386
;
375 else if ( strcmp(architecture
, "x86_64") == 0 )
376 fArchitecture
= CPU_TYPE_X86_64
;
378 throw "-arch followed by unknown architecture name";
381 bool Options::checkForFile(const char* format
, const char* dir
, const char* rootName
, FileInfo
& result
)
383 struct stat statBuffer
;
384 char possiblePath
[strlen(dir
)+strlen(rootName
)+strlen(format
)+8];
385 sprintf(possiblePath
, format
, dir
, rootName
);
386 bool found
= (stat(possiblePath
, &statBuffer
) == 0);
387 if ( fTraceDylibSearching
)
388 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), possiblePath
);
390 result
.path
= strdup(possiblePath
);
391 result
.fileLen
= statBuffer
.st_size
;
392 result
.modTime
= statBuffer
.st_mtime
;
399 Options::FileInfo
Options::findLibrary(const char* rootName
)
402 const int rootNameLen
= strlen(rootName
);
403 // if rootName ends in .o there is no .a vs .dylib choice
404 if ( (rootNameLen
> 3) && (strcmp(&rootName
[rootNameLen
-2], ".o") == 0) ) {
405 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
406 it
!= fLibrarySearchPaths
.end();
408 const char* dir
= *it
;
409 if ( checkForFile("%s/%s", dir
, rootName
, result
) )
414 bool lookForDylibs
= ( fOutputKind
!= Options::kDyld
);
415 switch ( fLibrarySearchMode
) {
416 case kSearchAllDirsForDylibsThenAllDirsForArchives
:
417 // first look in all directories for just for dylibs
418 if ( lookForDylibs
) {
419 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
420 it
!= fLibrarySearchPaths
.end();
422 const char* dir
= *it
;
423 if ( checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
427 // next look in all directories for just for archives
428 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
429 it
!= fLibrarySearchPaths
.end();
431 const char* dir
= *it
;
432 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
437 case kSearchDylibAndArchiveInEachDir
:
438 // look in each directory for just for a dylib then for an archive
439 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
440 it
!= fLibrarySearchPaths
.end();
442 const char* dir
= *it
;
443 if ( lookForDylibs
&& checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
445 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
451 throwf("library not found for -l%s", rootName
);
455 Options::FileInfo
Options::findFramework(const char* rootName
)
457 struct stat statBuffer
;
458 const int rootNameLen
= strlen(rootName
);
459 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
460 it
!= fFrameworkSearchPaths
.end();
462 // ??? Shouldn't we be using String here and just initializing it?
463 // ??? Use str.c_str () to pull out the string for the stat call.
464 const char* dir
= *it
;
465 char possiblePath
[strlen(dir
)+2*rootNameLen
+20];
466 strcpy(possiblePath
, dir
);
467 strcat(possiblePath
, "/");
468 strcat(possiblePath
, rootName
);
469 strcat(possiblePath
, ".framework/");
470 strcat(possiblePath
, rootName
);
471 bool found
= (stat(possiblePath
, &statBuffer
) == 0);
472 if ( fTraceDylibSearching
)
473 printf("[Logging for XBS]%sfound framework: '%s'\n",
474 (found
? " " : " not "), possiblePath
);
477 result
.path
= strdup(possiblePath
);
478 result
.fileLen
= statBuffer
.st_size
;
479 result
.modTime
= statBuffer
.st_mtime
;
483 throwf("framework not found %s", rootName
);
486 Options::FileInfo
Options::findFile(const char* path
)
489 struct stat statBuffer
;
491 // if absolute path and not a .o file, the use SDK prefix
492 if ( (path
[0] == '/') && (strcmp(&path
[strlen(path
)-2], ".o") != 0) ) {
493 const int pathLen
= strlen(path
);
494 for (std::vector
<const char*>::iterator it
= fSDKPaths
.begin(); it
!= fSDKPaths
.end(); it
++) {
495 // ??? Shouldn't we be using String here?
496 const char* sdkPathDir
= *it
;
497 const int sdkPathDirLen
= strlen(sdkPathDir
);
498 char possiblePath
[sdkPathDirLen
+pathLen
+4];
499 strcpy(possiblePath
, sdkPathDir
);
500 if ( possiblePath
[sdkPathDirLen
-1] == '/' )
501 possiblePath
[sdkPathDirLen
-1] = '\0';
502 strcat(possiblePath
, path
);
503 if ( stat(possiblePath
, &statBuffer
) == 0 ) {
504 result
.path
= strdup(possiblePath
);
505 result
.fileLen
= statBuffer
.st_size
;
506 result
.modTime
= statBuffer
.st_mtime
;
512 if ( stat(path
, &statBuffer
) == 0 ) {
513 result
.path
= strdup(path
);
514 result
.fileLen
= statBuffer
.st_size
;
515 result
.modTime
= statBuffer
.st_mtime
;
519 // try @executable_path substitution
520 if ( (strncmp(path
, "@executable_path/", 17) == 0) && (fExecutablePath
!= NULL
) ) {
521 char newPath
[strlen(fExecutablePath
) + strlen(path
)];
522 strcpy(newPath
, fExecutablePath
);
523 char* addPoint
= strrchr(newPath
,'/');
524 if ( addPoint
!= NULL
)
525 strcpy(&addPoint
[1], &path
[17]);
527 strcpy(newPath
, &path
[17]);
528 if ( stat(newPath
, &statBuffer
) == 0 ) {
529 result
.path
= strdup(newPath
);
530 result
.fileLen
= statBuffer
.st_size
;
531 result
.modTime
= statBuffer
.st_mtime
;
537 throwf("file not found: %s", path
);
541 void Options::loadFileList(const char* fileOfPaths
)
544 const char* comma
= strrchr(fileOfPaths
, ',');
545 const char* prefix
= NULL
;
546 if ( comma
!= NULL
) {
548 int realFileOfPathsLen
= comma
-fileOfPaths
;
549 char realFileOfPaths
[realFileOfPathsLen
+1];
550 strncpy(realFileOfPaths
,fileOfPaths
, realFileOfPathsLen
);
551 realFileOfPaths
[realFileOfPathsLen
] = '\0';
552 file
= fopen(realFileOfPaths
, "r");
554 throwf("-filelist file not found: %s\n", realFileOfPaths
);
557 file
= fopen(fileOfPaths
, "r");
559 throwf("-filelist file not found: %s\n", fileOfPaths
);
563 while ( fgets(path
, 1024, file
) != NULL
) {
564 path
[PATH_MAX
-1] = '\0';
565 char* eol
= strchr(path
, '\n');
568 if ( prefix
!= NULL
) {
569 char builtPath
[strlen(prefix
)+strlen(path
)+2];
570 strcpy(builtPath
, prefix
);
571 strcat(builtPath
, "/");
572 strcat(builtPath
, path
);
573 fInputFiles
.push_back(findFile(builtPath
));
576 fInputFiles
.push_back(findFile(path
));
583 void Options::loadExportFile(const char* fileOfExports
, const char* option
, NameSet
& set
)
585 // read in whole file
586 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
588 throwf("can't open %s file: %s", option
, fileOfExports
);
589 struct stat stat_buf
;
590 ::fstat(fd
, &stat_buf
);
591 char* p
= (char*)malloc(stat_buf
.st_size
);
593 throwf("can't process %s file: %s", option
, fileOfExports
);
595 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
596 throwf("can't read %s file: %s", option
, fileOfExports
);
600 // parse into symbols and add to hash_set
601 char * const end
= &p
[stat_buf
.st_size
];
602 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
603 char* symbolStart
= NULL
;
604 for (char* s
= p
; s
< end
; ++s
) {
610 else if ( !isspace(*s
) ) {
618 // removing any trailing spaces
620 while ( isspace(*last
) ) {
624 set
.insert(symbolStart
);
635 if ( state
== inSymbol
) {
636 fprintf(stderr
, "ld64 warning: missing line-end at end of file \"%s\"\n", fileOfExports
);
637 int len
= end
-symbolStart
+1;
638 char* temp
= new char[len
];
639 strlcpy(temp
, symbolStart
, len
);
641 // remove any trailing spaces
642 char* last
= &temp
[len
-2];
643 while ( isspace(*last
) ) {
650 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
653 void Options::setUndefinedTreatment(const char* treatment
)
655 if ( treatment
== NULL
)
656 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
658 if ( strcmp(treatment
, "warning") == 0 )
659 fUndefinedTreatment
= kUndefinedWarning
;
660 else if ( strcmp(treatment
, "error") == 0 )
661 fUndefinedTreatment
= kUndefinedError
;
662 else if ( strcmp(treatment
, "suppress") == 0 )
663 fUndefinedTreatment
= kUndefinedSuppress
;
664 else if ( strcmp(treatment
, "dynamic_lookup") == 0 )
665 fUndefinedTreatment
= kUndefinedDynamicLookup
;
667 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
670 Options::Treatment
Options::parseTreatment(const char* treatment
)
672 if ( treatment
== NULL
)
675 if ( strcmp(treatment
, "warning") == 0 )
677 else if ( strcmp(treatment
, "error") == 0 )
679 else if ( strcmp(treatment
, "suppress") == 0 )
685 void Options::setVersionMin(const char* version
)
687 if ( version
== NULL
)
688 throw "-macosx_version_min argument missing";
690 if ( (strncmp(version
, "10.", 3) == 0) && isdigit(version
[3]) ) {
691 int num
= version
[3] - '0';
712 fprintf(stderr
, "ld64: unknown option to -macosx_version_min not 10.x");
716 void Options::setWeakReferenceMismatchTreatment(const char* treatment
)
718 if ( treatment
== NULL
)
719 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
721 if ( strcmp(treatment
, "error") == 0 )
722 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchError
;
723 else if ( strcmp(treatment
, "weak") == 0 )
724 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchWeak
;
725 else if ( strcmp(treatment
, "non-weak") == 0 )
726 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchNonWeak
;
728 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
731 Options::CommonsMode
Options::parseCommonsTreatment(const char* mode
)
734 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
736 if ( strcmp(mode
, "ignore_dylibs") == 0 )
737 return kCommonsIgnoreDylibs
;
738 else if ( strcmp(mode
, "use_dylibs") == 0 )
739 return kCommonsOverriddenByDylibs
;
740 else if ( strcmp(mode
, "error") == 0 )
741 return kCommonsConflictsDylibsError
;
743 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
746 void Options::setDylibInstallNameOverride(const char* paths
)
752 uint64_t Options::parseAddress(const char* addr
)
755 uint64_t result
= strtoull(addr
, &endptr
, 16);
760 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
763 uint32_t Options::parseVersionNumber(const char* versionString
)
769 x
= strtoul(versionString
, &end
, 10);
771 y
= strtoul(&end
[1], &end
, 10);
773 z
= strtoul(&end
[1], &end
, 10);
776 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
777 throwf("malformed version number: %s", versionString
);
779 return (x
<< 16) | ( y
<< 8 ) | z
;
782 void Options::parseSectionOrderFile(const char* segment
, const char* section
, const char* path
)
784 fprintf(stderr
, "ld64: warning -sectorder not yet supported for 64-bit code\n");
787 void Options::addSection(const char* segment
, const char* section
, const char* path
)
789 if ( strlen(segment
) > 16 )
790 throw "-seccreate segment name max 16 chars";
791 if ( strlen(section
) > 16 ) {
792 char* tmp
= strdup(section
);
794 fprintf(stderr
, "ld64 warning: -seccreate section name (%s) truncated to 16 chars (%s)\n", section
, tmp
);
798 // read in whole file
799 int fd
= ::open(path
, O_RDONLY
, 0);
801 throwf("can't open -sectcreate file: %s", path
);
802 struct stat stat_buf
;
803 ::fstat(fd
, &stat_buf
);
804 char* p
= (char*)malloc(stat_buf
.st_size
);
806 throwf("can't process -sectcreate file: %s", path
);
807 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
808 throwf("can't read -sectcreate file: %s", path
);
811 // record section to create
812 ExtraSection info
= { segment
, section
, path
, (uint8_t*)p
, stat_buf
.st_size
};
813 fExtraSections
.push_back(info
);
816 void Options::addSectionAlignment(const char* segment
, const char* section
, const char* alignmentStr
)
818 if ( strlen(segment
) > 16 )
819 throw "-sectalign segment name max 16 chars";
820 if ( strlen(section
) > 16 )
821 throw "-sectalign section name max 16 chars";
823 // argument to -sectalign is a hexadecimal number
825 unsigned long value
= strtoul(alignmentStr
, &endptr
, 16);
826 if ( *endptr
!= '\0')
827 throw "argument for -sectalign is not a hexadecimal number";
828 if ( value
> 0x8000 )
829 throw "argument for -sectalign must be less than or equal to 0x8000";
831 fprintf(stderr
, "ld64 warning: zero is not a valid -sectalign\n");
835 // alignment is power of 2 (e.g. page alignment = 12)
836 uint8_t alignment
= (uint8_t)log2(value
);
838 if ( (unsigned long)(1 << alignment
) != value
) {
839 fprintf(stderr
, "ld64 warning: alignment for -sectalign %s %s is not a power of two, using 0x%X\n",
840 segment
, section
, 1 << alignment
);
843 SectionAlignment info
= { segment
, section
, alignment
};
844 fSectionAlignments
.push_back(info
);
848 // Process all command line arguments.
850 // The only error checking done here is that each option is valid and if it has arguments
851 // that they too are valid.
853 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
854 // whichever was last on the command line is used.
856 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
858 void Options::parse(int argc
, const char* argv
[])
860 // pass one builds search list from -L and -F options
861 this->buildSearchPaths(argc
, argv
);
863 // reduce re-allocations
864 fInputFiles
.reserve(32);
866 // pass two parse all other options
867 for(int i
=1; i
< argc
; ++i
) {
868 const char* arg
= argv
[i
];
870 if ( arg
[0] == '-' ) {
872 // Since we don't care about the files passed, just the option names, we do this here.
874 fprintf (stderr
, "[Logging ld64 options]\t%s\n", arg
);
876 if ( (arg
[1] == 'L') || (arg
[1] == 'F') ) {
877 // previously handled by buildSearchPaths()
879 else if ( strcmp(arg
, "-arch") == 0 ) {
880 parseArch(argv
[++i
]);
882 else if ( strcmp(arg
, "-dynamic") == 0 ) {
885 else if ( strcmp(arg
, "-static") == 0 ) {
886 fOutputKind
= kStaticExecutable
;
888 else if ( strcmp(arg
, "-dylib") == 0 ) {
889 fOutputKind
= kDynamicLibrary
;
891 else if ( strcmp(arg
, "-bundle") == 0 ) {
892 fOutputKind
= kDynamicBundle
;
894 else if ( strcmp(arg
, "-dylinker") == 0 ) {
897 else if ( strcmp(arg
, "-execute") == 0 ) {
898 if ( fOutputKind
!= kStaticExecutable
)
899 fOutputKind
= kDynamicExecutable
;
901 else if ( strcmp(arg
, "-r") == 0 ) {
902 fOutputKind
= kObjectFile
;
904 else if ( strcmp(arg
, "-o") == 0 ) {
905 fOutputFile
= argv
[++i
];
907 else if ( arg
[1] == 'l' ) {
908 fInputFiles
.push_back(findLibrary(&arg
[2]));
910 // This causes a dylib to be weakly bound at
911 // link time. This corresponds to weak_import.
912 else if ( strncmp(arg
, "-weak-l", 7) == 0 ) {
913 FileInfo info
= findLibrary(&arg
[7]);
914 info
.options
.fWeakImport
= true;
915 fInputFiles
.push_back(info
);
917 // Avoid lazy binding.
919 else if ( strcmp(arg
, "-bind_at_load") == 0 ) {
922 else if ( strcmp(arg
, "-twolevel_namespace") == 0 ) {
923 fNameSpace
= kTwoLevelNameSpace
;
925 else if ( strcmp(arg
, "-flat_namespace") == 0 ) {
926 fNameSpace
= kFlatNameSpace
;
928 // Also sets a bit to ensure dyld causes everything
929 // in the namespace to be flat.
931 else if ( strcmp(arg
, "-force_flat_namespace") == 0 ) {
932 fNameSpace
= kForceFlatNameSpace
;
934 // Similar to --whole-archive.
935 else if ( strcmp(arg
, "-all_load") == 0 ) {
936 fReaderOptions
.fFullyLoadArchives
= true;
938 // Similar to --whole-archive, but for all ObjC classes.
939 else if ( strcmp(arg
, "-ObjC") == 0 ) {
940 fReaderOptions
.fLoadObjcClassesInArchives
= true;
942 // Library versioning.
943 else if ( strcmp(arg
, "-dylib_compatibility_version") == 0 ) {
944 fDylibCompatVersion
= parseVersionNumber(argv
[++i
]);
946 else if ( strcmp(arg
, "-dylib_current_version") == 0 ) {
947 fDylibCurrentVersion
= parseVersionNumber(argv
[++i
]);
949 else if ( strcmp(arg
, "-sectorder") == 0 ) {
950 parseSectionOrderFile(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
953 // ??? Deprecate segcreate.
954 // -sectcreate puts whole files into a section in the output.
955 else if ( (strcmp(arg
, "-sectcreate") == 0) || (strcmp(arg
, "-segcreate") == 0) ) {
956 addSection(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
959 // Since we have a full path in binary/library names we need to be able to override it.
960 else if ( (strcmp(arg
, "-dylib_install_name") == 0) || (strcmp(arg
, "-dylinker_install_name") == 0) ) {
961 fDylibInstallName
= argv
[++i
];
963 // Sets the base address of the output.
964 else if ( (strcmp(arg
, "-seg1addr") == 0) || (strcmp(arg
, "-image_base") == 0) ) {
965 fBaseAddress
= parseAddress(argv
[++i
]);
967 else if ( strcmp(arg
, "-e") == 0 ) {
968 fEntryName
= argv
[++i
];
970 // Same as -@ from the FSF linker.
971 else if ( strcmp(arg
, "-filelist") == 0 ) {
972 loadFileList(argv
[++i
]);
974 else if ( strcmp(arg
, "-keep_private_externs") == 0 ) {
975 fKeepPrivateExterns
= true;
978 else if ( strcmp(arg
, "-final_output") == 0 ) {
982 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
983 // just ensures that this happens for cross object file boundaries.
984 else if ( (strcmp(arg
, "-interposable") == 0) || (strcmp(arg
, "-multi_module") == 0)) {
985 fInterposable
= true;
987 // Default for -interposable/-multi_module/-single_module.
988 else if ( strcmp(arg
, "-single_module") == 0 ) {
989 fInterposable
= false;
991 else if ( strcmp(arg
, "-exported_symbols_list") == 0 ) {
992 if ( fExportMode
== kDontExportSome
)
993 throw "can't use -exported_symbols_list and -unexported_symbols_list";
994 fExportMode
= kExportSome
;
995 loadExportFile(argv
[++i
], "-exported_symbols_list", fExportSymbols
);
997 else if ( strcmp(arg
, "-unexported_symbols_list") == 0 ) {
998 if ( fExportMode
== kExportSome
)
999 throw "can't use -exported_symbols_list and -unexported_symbols_list";
1000 fExportMode
= kDontExportSome
;
1001 loadExportFile(argv
[++i
], "-unexported_symbols_list", fDontExportSymbols
);
1004 else if ( strcmp(arg
, "-no_arch_warnings") == 0 ) {
1005 fIgnoreOtherArchFiles
= true;
1007 else if ( strcmp(arg
, "-force_cpusubtype_ALL") == 0 ) {
1008 fForceSubtypeAll
= true;
1010 // Similar to -weak-l but uses the absolute path name to the library.
1011 else if ( strcmp(arg
, "-weak_library") == 0 ) {
1012 FileInfo info
= findFile(argv
[++i
]);
1013 info
.options
.fWeakImport
= true;
1014 fInputFiles
.push_back(info
);
1016 else if ( strcmp(arg
, "-framework") == 0 ) {
1017 fInputFiles
.push_back(findFramework(argv
[++i
]));
1019 else if ( strcmp(arg
, "-weak_framework") == 0 ) {
1020 FileInfo info
= findFramework(argv
[++i
]);
1021 info
.options
.fWeakImport
= true;
1022 fInputFiles
.push_back(info
);
1024 // ??? Deprecate when we get -Bstatic/-Bdynamic.
1025 else if ( strcmp(arg
, "-search_paths_first") == 0 ) {
1026 fLibrarySearchMode
= kSearchDylibAndArchiveInEachDir
;
1028 else if ( strcmp(arg
, "-undefined") == 0 ) {
1029 setUndefinedTreatment(argv
[++i
]);
1031 // Debugging output flag.
1032 else if ( strcmp(arg
, "-arch_multiple") == 0 ) {
1033 fMessagesPrefixedWithArchitecture
= true;
1035 // Specify what to do with relocations in read only
1036 // sections like .text. Could be errors, warnings,
1037 // or suppressed. Currently we do nothing with the
1039 else if ( strcmp(arg
, "-read_only_relocs") == 0 ) {
1040 Treatment temp
= parseTreatment(argv
[++i
]);
1042 if ( temp
== kNULL
)
1043 throw "-read_only_relocs missing [ warning | error | suppress ]";
1044 else if ( temp
== kInvalid
)
1045 throw "invalid option to -read_only_relocs [ warning | error | suppress ]";
1047 // Specifies whether or not there are intra section
1048 // relocations and what to do when found. Could be
1049 // errors, warnings, or suppressed.
1050 else if ( strcmp(arg
, "-sect_diff_relocs") == 0 ) {
1051 fPICTreatment
= parseTreatment(argv
[++i
]);
1053 if ( fPICTreatment
== kNULL
)
1054 throw "-sect_diff_relocs missing [ warning | error | suppress ]";
1055 else if ( fPICTreatment
== kInvalid
)
1056 throw "invalid option to -sect_diff_relocs [ warning | error | suppress ]";
1058 // Warn, error or make strong a mismatch between weak
1059 // and non-weak references.
1060 else if ( strcmp(arg
, "-weak_reference_mismatches") == 0 ) {
1061 setWeakReferenceMismatchTreatment(argv
[++i
]);
1063 // For a deployment target of 10.3 and earlier ld64 will
1064 // prebind an executable with 0s in all addresses that
1065 // are prebound. This can then be fixed up by update_prebinding
1066 // later. Prebinding is less useful on 10.4 and greater.
1067 else if ( strcmp(arg
, "-prebind") == 0 ) {
1070 else if ( strcmp(arg
, "-noprebind") == 0 ) {
1074 else if ( strcmp(arg
, "-prebind_allow_overlap") == 0 ) {
1075 // Do not handle and suppress warnings always.
1078 else if ( strcmp(arg
, "-prebind_all_twolevel_modules") == 0 ) {
1082 else if ( strcmp(arg
, "-noprebind_all_twolevel_modules") == 0 ) {
1085 // Sets a bit in the main executable only that causes fix_prebinding
1086 // not to run. This is always set.
1087 else if ( strcmp(arg
, "-nofixprebinding") == 0 ) {
1090 // This should probably be deprecated when we respect -L and -F
1091 // when searching for libraries.
1092 else if ( strcmp(arg
, "-dylib_file") == 0 ) {
1093 setDylibInstallNameOverride(argv
[++i
]);
1095 // Allows us to rewrite full paths to be relocatable based on
1096 // the path name of the executable.
1097 else if ( strcmp(arg
, "-executable_path") == 0 ) {
1098 fExecutablePath
= argv
[++i
];
1099 if ( (fExecutablePath
== NULL
) || (fExecutablePath
[0] == '-') )
1100 throw "-executable_path missing <path>";
1103 // Aligns all segments to the power of 2 boundary specified.
1104 else if ( strcmp(arg
, "-segalign") == 0 ) {
1108 // Puts a specified segment at a particular address that must
1109 // be a multiple of the segment alignment.
1110 else if ( strcmp(arg
, "-segaddr") == 0 ) {
1114 // ??? Deprecate when we deprecate split-seg.
1115 else if ( strcmp(arg
, "-segs_read_only_addr") == 0 ) {
1119 // ??? Deprecate when we deprecate split-seg.
1120 else if ( strcmp(arg
, "-segs_read_write_addr") == 0 ) {
1124 // ??? Deprecate when we get rid of basing at build time.
1125 else if ( strcmp(arg
, "-seg_addr_table") == 0 ) {
1130 else if ( strcmp(arg
, "-seg_addr_table_filename") == 0 ) {
1134 else if ( strcmp(arg
, "-segprot") == 0 ) {
1138 else if ( strcmp(arg
, "-pagezero_size") == 0 ) {
1139 fZeroPageSize
= parseAddress(argv
[++i
]);
1140 uint64_t temp
= fZeroPageSize
& (-4096); // page align
1141 if ( fZeroPageSize
!= temp
)
1142 fprintf(stderr
, "ld64: warning, -pagezero_size not page aligned, rounding down\n");
1143 fZeroPageSize
= temp
;
1145 else if ( strcmp(arg
, "-stack_addr") == 0 ) {
1146 fStackAddr
= parseAddress(argv
[++i
]);
1148 else if ( strcmp(arg
, "-stack_size") == 0 ) {
1149 fStackSize
= parseAddress(argv
[++i
]);
1151 else if ( strcmp(arg
, "-allow_stack_execute") == 0 ) {
1152 fExecutableStack
= true;
1154 else if ( strcmp(arg
, "-sectalign") == 0 ) {
1155 addSectionAlignment(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1158 else if ( strcmp(arg
, "-sectorder_detail") == 0 ) {
1161 else if ( strcmp(arg
, "-sectobjectsymbols") == 0 ) {
1165 else if ( strcmp(arg
, "-bundle_loader") == 0 ) {
1166 fBundleLoader
= argv
[++i
];
1167 if ( (fBundleLoader
== NULL
) || (fBundleLoader
[0] == '-') )
1168 throw "-bundle_loader missing <path>";
1169 FileInfo info
= findFile(fBundleLoader
);
1170 info
.options
.fBundleLoader
= true;
1171 fInputFiles
.push_back(info
);
1173 else if ( strcmp(arg
, "-private_bundle") == 0 ) {
1176 else if ( strcmp(arg
, "-twolevel_namespace_hints") == 0 ) {
1179 // Use this flag to set default behavior for deployement targets.
1180 else if ( strcmp(arg
, "-macosx_version_min") == 0 ) {
1181 setVersionMin(argv
[++i
]);
1183 // This option (unlike -m below) only affects how we warn
1184 // on multiple definitions inside dynamic libraries.
1185 else if ( strcmp(arg
, "-multiply_defined") == 0 ) {
1186 fMultiplyDefinedDynamic
= parseTreatment(argv
[++i
]);
1188 if ( fMultiplyDefinedDynamic
== kNULL
)
1189 throw "-multiply_defined missing [ warning | error | suppress ]";
1190 else if ( fMultiplyDefinedDynamic
== kInvalid
)
1191 throw "invalid option to -multiply_defined [ warning | error | suppress ]";
1193 else if ( strcmp(arg
, "-multiply_defined_unused") == 0 ) {
1194 fMultiplyDefinedUnused
= parseTreatment(argv
[++i
]);
1196 if ( fMultiplyDefinedUnused
== kNULL
)
1197 throw "-multiply_defined_unused missing [ warning | error | suppress ]";
1198 else if ( fMultiplyDefinedUnused
== kInvalid
)
1199 throw "invalid option to -multiply_defined_unused [ warning | error | suppress ]";
1201 else if ( strcmp(arg
, "-nomultidefs") == 0 ) {
1204 // Display each file in which the argument symbol appears and whether
1205 // the file defines or references it. This option takes an argument
1206 // as -y<symbol> note that there is no space.
1207 else if ( strncmp(arg
, "-y", 2) == 0 ) {
1208 const char* name
= &arg
[2];
1211 throw "-y missing argument";
1213 fTraceSymbols
.push_back(name
);
1215 // Same output as -y, but output <arg> number of undefined symbols only.
1216 else if ( strcmp(arg
, "-Y") == 0 ) {
1218 fLimitUndefinedSymbols
= strtoul (argv
[++i
], &endptr
, 10);
1221 throw "invalid argument for -Y [decimal number]";
1223 // This option affects all objects linked into the final result.
1224 else if ( strcmp(arg
, "-m") == 0 ) {
1225 fWarnOnMultiplyDefined
= true;
1227 else if ( (strcmp(arg
, "-why_load") == 0) || (strcmp(arg
, "-whyload") == 0) ) {
1228 fReaderOptions
.fWhyLoad
= true;
1230 else if ( strcmp(arg
, "-why_live") == 0 ) {
1231 const char* name
= argv
[++i
];
1233 throw "-why_live missing symbol name argument";
1234 fWhyLive
.insert(name
);
1236 else if ( strcmp(arg
, "-u") == 0 ) {
1237 const char* name
= argv
[++i
];
1239 throw "-u missing argument";
1240 fInitialUndefines
.push_back(name
);
1242 else if ( strcmp(arg
, "-U") == 0 ) {
1246 else if ( strcmp(arg
, "-s") == 0 ) {
1247 fStripLocalSymbols
= true;
1248 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
1250 else if ( strcmp(arg
, "-x") == 0 ) {
1251 fStripLocalSymbols
= true;
1253 else if ( strcmp(arg
, "-S") == 0 ) {
1254 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
1256 else if ( strcmp(arg
, "-X") == 0 ) {
1259 else if ( strcmp(arg
, "-Si") == 0 ) {
1260 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoFull
;
1262 else if ( strcmp(arg
, "-b") == 0 ) {
1265 else if ( strcmp(arg
, "-Sn") == 0 ) {
1266 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoFull
;
1268 else if ( strcmp(arg
, "-Sp") == 0 ) {
1269 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoMinimal
;
1271 else if ( strcmp(arg
, "-dead_strip") == 0 ) {
1272 fDeadStrip
= kDeadStripOnPlusUnusedInits
;
1274 else if ( strcmp(arg
, "-no_dead_strip_inits_and_terms") == 0 ) {
1275 fDeadStrip
= kDeadStripOn
;
1277 else if ( strcmp(arg
, "-w") == 0 ) {
1280 else if ( strcmp(arg
, "-arch_errors_fatal") == 0 ) {
1283 else if ( strcmp(arg
, "-M") == 0 ) {
1286 else if ( strcmp(arg
, "-whatsloaded") == 0 ) {
1289 else if ( strcmp(arg
, "-headerpad") == 0 ) {
1290 const char* size
= argv
[++i
];
1292 throw "-headerpad missing argument";
1293 fMinimumHeaderPad
= parseAddress(size
);
1295 else if ( strcmp(arg
, "-headerpad_max_install_names") == 0 ) {
1298 else if ( strcmp(arg
, "-t") == 0 ) {
1301 else if ( strcmp(arg
, "-A") == 0 ) {
1305 else if ( strcmp(arg
, "-umbrella") == 0 ) {
1306 const char* name
= argv
[++i
];
1308 throw "-umbrella missing argument";
1309 fUmbrellaName
= name
;
1311 else if ( strcmp(arg
, "-allowable_client") == 0 ) {
1312 const char* name
= argv
[++i
];
1315 throw "-allowable_client missing argument";
1317 fAllowableClients
.push_back(name
);
1319 else if ( strcmp(arg
, "-client_name") == 0 ) {
1320 const char* name
= argv
[++i
];
1323 throw "-client_name missing argument";
1327 else if ( strcmp(arg
, "-sub_umbrella") == 0 ) {
1328 const char* name
= argv
[++i
];
1330 throw "-sub_umbrella missing argument";
1331 fSubUmbellas
.push_back(name
);
1333 else if ( strcmp(arg
, "-sub_library") == 0 ) {
1334 const char* name
= argv
[++i
];
1336 throw "-sub_library missing argument";
1337 fSubLibraries
.push_back(name
);
1339 else if ( strcmp(arg
, "-init") == 0 ) {
1340 const char* name
= argv
[++i
];
1342 throw "-init missing argument";
1343 fInitFunctionName
= name
;
1345 else if ( strcmp(arg
, "-dot") == 0 ) {
1346 const char* name
= argv
[++i
];
1348 throw "-dot missing argument";
1349 fDotOutputFile
= name
;
1351 else if ( strcmp(arg
, "-warn_commons") == 0 ) {
1352 fWarnCommons
= true;
1354 else if ( strcmp(arg
, "-commons") == 0 ) {
1355 fCommonsMode
= parseCommonsTreatment(argv
[++i
]);
1357 else if ( strcmp(arg
, "-keep_relocs") == 0 ) {
1358 fKeepRelocations
= true;
1360 else if ( strcmp(arg
, "-warn_stabs") == 0 ) {
1363 else if ( strcmp(arg
, "-pause") == 0 ) {
1366 else if ( strcmp(arg
, "-print_statistics") == 0 ) {
1369 else if ( strcmp(arg
, "-d") == 0 ) {
1370 fMakeTentativeDefinitionsReal
= true;
1372 else if ( strcmp(arg
, "-v") == 0 ) {
1373 // previously handled by buildSearchPaths()
1375 else if ( strcmp(arg
, "-Z") == 0 ) {
1376 // previously handled by buildSearchPaths()
1378 else if ( strcmp(arg
, "-syslibroot") == 0 ) {
1380 // previously handled by buildSearchPaths()
1382 else if ( strcmp(arg
, "-no_uuid") == 0 ) {
1385 // put this last so that it does not interfer with other options starting with 'i'
1386 else if ( strncmp(arg
, "-i", 2) == 0 ) {
1387 fprintf(stderr
, "ld64: -i option (indirect symbols) not supported\n");
1390 throwf("unknown option: %s", arg
);
1394 fInputFiles
.push_back(findFile(arg
));
1402 // -syslibroot <path> is used for SDK support.
1403 // The rule is that all search paths (both explicit and default) are
1404 // checked to see if they exist in the SDK. If so, that path is
1405 // replaced with the sdk prefixed path. If not, that search path
1406 // is used as is. If multiple -syslibroot options are specified
1407 // their directory structures are logically overlayed and files
1408 // from sdks specified earlier on the command line used before later ones.
1410 void Options::buildSearchPaths(int argc
, const char* argv
[])
1412 bool addStandardLibraryDirectories
= true;
1413 std::vector
<const char*> libraryPaths
;
1414 std::vector
<const char*> frameworkPaths
;
1415 libraryPaths
.reserve(10);
1416 frameworkPaths
.reserve(10);
1417 // scan through argv looking for -L, -F, -Z, and -syslibroot options
1418 for(int i
=0; i
< argc
; ++i
) {
1419 if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'L') )
1420 libraryPaths
.push_back(&argv
[i
][2]);
1421 else if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'F') )
1422 frameworkPaths
.push_back(&argv
[i
][2]);
1423 else if ( strcmp(argv
[i
], "-Z") == 0 )
1424 addStandardLibraryDirectories
= false;
1425 else if ( strcmp(argv
[i
], "-v") == 0 ) {
1427 extern const char ld64VersionString
[];
1428 fprintf(stderr
, "%s", ld64VersionString
);
1429 // if only -v specified, exit cleanly
1433 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
1434 const char* path
= argv
[++i
];
1436 throw "-syslibroot missing argument";
1437 fSDKPaths
.push_back(path
);
1440 if ( addStandardLibraryDirectories
) {
1441 libraryPaths
.push_back("/usr/lib");
1442 libraryPaths
.push_back("/usr/local/lib");
1444 frameworkPaths
.push_back("/Library/Frameworks/");
1445 frameworkPaths
.push_back("/Network/Library/Frameworks/");
1446 frameworkPaths
.push_back("/System/Library/Frameworks/");
1449 // now merge sdk and library paths to make real search paths
1450 fLibrarySearchPaths
.reserve(libraryPaths
.size()*(fSDKPaths
.size()+1));
1451 for (std::vector
<const char*>::iterator it
= libraryPaths
.begin(); it
!= libraryPaths
.end(); it
++) {
1452 const char* libDir
= *it
;
1453 bool sdkOverride
= false;
1454 if ( libDir
[0] == '/' ) {
1455 char betterLibDir
[PATH_MAX
];
1456 if ( strstr(libDir
, "/..") != NULL
) {
1457 if ( realpath(libDir
, betterLibDir
) != NULL
)
1458 libDir
= strdup(betterLibDir
);
1460 const int libDirLen
= strlen(libDir
);
1461 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
1462 // ??? Should be using string here.
1463 const char* sdkDir
= *sdkit
;
1464 const int sdkDirLen
= strlen(sdkDir
);
1465 char newPath
[libDirLen
+ sdkDirLen
+4];
1466 strcpy(newPath
, sdkDir
);
1467 if ( newPath
[sdkDirLen
-1] == '/' )
1468 newPath
[sdkDirLen
-1] = '\0';
1469 strcat(newPath
, libDir
);
1470 struct stat statBuffer
;
1471 if ( stat(newPath
, &statBuffer
) == 0 ) {
1472 fLibrarySearchPaths
.push_back(strdup(newPath
));
1478 fLibrarySearchPaths
.push_back(libDir
);
1481 // now merge sdk and framework paths to make real search paths
1482 fFrameworkSearchPaths
.reserve(frameworkPaths
.size()*(fSDKPaths
.size()+1));
1483 for (std::vector
<const char*>::iterator it
= frameworkPaths
.begin(); it
!= frameworkPaths
.end(); it
++) {
1484 const char* frameworkDir
= *it
;
1485 bool sdkOverride
= false;
1486 if ( frameworkDir
[0] == '/' ) {
1487 char betterFrameworkDir
[PATH_MAX
];
1488 if ( strstr(frameworkDir
, "/..") != NULL
) {
1489 if ( realpath(frameworkDir
, betterFrameworkDir
) != NULL
)
1490 frameworkDir
= strdup(betterFrameworkDir
);
1492 const int frameworkDirLen
= strlen(frameworkDir
);
1493 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
1494 // ??? Should be using string here
1495 const char* sdkDir
= *sdkit
;
1496 const int sdkDirLen
= strlen(sdkDir
);
1497 char newPath
[frameworkDirLen
+ sdkDirLen
+4];
1498 strcpy(newPath
, sdkDir
);
1499 if ( newPath
[sdkDirLen
-1] == '/' )
1500 newPath
[sdkDirLen
-1] = '\0';
1501 strcat(newPath
, frameworkDir
);
1502 struct stat statBuffer
;
1503 if ( stat(newPath
, &statBuffer
) == 0 ) {
1504 fFrameworkSearchPaths
.push_back(strdup(newPath
));
1510 fFrameworkSearchPaths
.push_back(frameworkDir
);
1514 fprintf(stderr
,"Library search paths:\n");
1515 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
1516 it
!= fLibrarySearchPaths
.end();
1518 fprintf(stderr
,"\t%s\n", *it
);
1519 fprintf(stderr
,"Framework search paths:\n");
1520 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
1521 it
!= fFrameworkSearchPaths
.end();
1523 fprintf(stderr
,"\t%s\n", *it
);
1527 // this is run before the command line is parsed
1528 void Options::parsePreCommandLineEnvironmentSettings()
1530 if ((getenv("LD_TRACE_ARCHIVES") != NULL
)
1531 || (getenv("RC_TRACE_ARCHIVES") != NULL
))
1532 fReaderOptions
.fTraceArchives
= true;
1534 if ((getenv("LD_TRACE_DYLIBS") != NULL
)
1535 || (getenv("RC_TRACE_DYLIBS") != NULL
)) {
1536 fReaderOptions
.fTraceDylibs
= true;
1537 fReaderOptions
.fTraceIndirectDylibs
= true;
1540 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL
) {
1541 fTraceDylibSearching
= true;
1544 if (getenv("LD_PRINT_OPTIONS") != NULL
)
1545 fPrintOptions
= true;
1547 if (fReaderOptions
.fTraceDylibs
|| fReaderOptions
.fTraceArchives
)
1548 fReaderOptions
.fTraceOutputFile
= getenv("LD_TRACE_FILE");
1551 // this is run after the command line is parsed
1552 void Options::parsePostCommandLineEnvironmentSettings()
1554 // when building a dynamic main executable, default any use of @executable_path to output path
1555 if ( fExecutablePath
== NULL
&& (fOutputKind
== kDynamicExecutable
) ) {
1556 fExecutablePath
= fOutputFile
;
1561 void Options::reconfigureDefaults()
1563 // sync reader options
1564 switch ( fOutputKind
) {
1565 case Options::kObjectFile
:
1566 fReaderOptions
.fForFinalLinkedImage
= false;
1568 case Options::kDynamicExecutable
:
1569 case Options::kStaticExecutable
:
1570 case Options::kDynamicLibrary
:
1571 case Options::kDynamicBundle
:
1572 case Options::kDyld
:
1573 fReaderOptions
.fForFinalLinkedImage
= true;
1577 // set default min OS version
1578 if ( fVersionMin
== kMinUnset
) {
1579 switch ( fArchitecture
) {
1580 case CPU_TYPE_POWERPC
:
1581 fVersionMin
= k10_2
;
1584 case CPU_TYPE_POWERPC64
:
1585 case CPU_TYPE_X86_64
:
1586 fVersionMin
= k10_4
;
1588 // architecture not specified
1589 fVersionMin
= k10_4
;
1594 // adjust min based on architecture
1595 switch ( fArchitecture
) {
1597 if ( fVersionMin
< k10_4
) {
1598 //fprintf(stderr, "ld64 warning: -macosx_version_min should be 10.4 or later for i386\n");
1599 fVersionMin
= k10_4
;
1602 case CPU_TYPE_POWERPC64
:
1603 if ( fVersionMin
< k10_4
) {
1604 //fprintf(stderr, "ld64 warning: -macosx_version_min should be 10.4 or later for ppc64\n");
1605 fVersionMin
= k10_4
;
1608 case CPU_TYPE_X86_64
:
1609 if ( fVersionMin
< k10_4
) {
1610 //fprintf(stderr, "ld64 warning: -macosx_version_min should be 10.4 or later for x86_64\n");
1611 fVersionMin
= k10_4
;
1618 void Options::checkIllegalOptionCombinations()
1620 // check -undefined setting
1621 switch ( fUndefinedTreatment
) {
1622 case kUndefinedError
:
1623 case kUndefinedDynamicLookup
:
1626 case kUndefinedWarning
:
1627 case kUndefinedSuppress
:
1628 // requires flat namespace
1629 if ( fNameSpace
== kTwoLevelNameSpace
)
1630 throw "can't use -undefined warning or suppress with -twolevel_namespace";
1634 // unify -sub_umbrella with dylibs
1635 for (std::vector
<const char*>::iterator it
= fSubUmbellas
.begin(); it
!= fSubUmbellas
.end(); it
++) {
1636 const char* subUmbrella
= *it
;
1638 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
1639 Options::FileInfo
& info
= *fit
;
1640 const char* lastSlash
= strrchr(info
.path
, '/');
1641 if ( lastSlash
== NULL
)
1642 lastSlash
= info
.path
- 1;
1643 if ( strcmp(&lastSlash
[1], subUmbrella
) == 0 ) {
1644 info
.options
.fReExport
= true;
1650 fprintf(stderr
, "ld64 warning: -sub_umbrella %s does not match a supplied dylib\n", subUmbrella
);
1653 // unify -sub_library with dylibs
1654 for (std::vector
<const char*>::iterator it
= fSubLibraries
.begin(); it
!= fSubLibraries
.end(); it
++) {
1655 const char* subLibrary
= *it
;
1657 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
1658 Options::FileInfo
& info
= *fit
;
1659 const char* lastSlash
= strrchr(info
.path
, '/');
1660 if ( lastSlash
== NULL
)
1661 lastSlash
= info
.path
- 1;
1662 const char* dot
= strchr(&lastSlash
[1], '.');
1664 dot
= &lastSlash
[strlen(lastSlash
)];
1665 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
1666 info
.options
.fReExport
= true;
1672 fprintf(stderr
, "ld64 warning: -sub_library %s does not match a supplied dylib\n", subLibrary
);
1675 // sync reader options
1676 if ( fNameSpace
!= kTwoLevelNameSpace
)
1677 fReaderOptions
.fFlatNamespace
= true;
1679 // check -stack_addr
1680 if ( fStackAddr
!= 0 ) {
1681 switch (fArchitecture
) {
1683 case CPU_TYPE_POWERPC
:
1684 if ( fStackAddr
> 0xFFFFFFFF )
1685 throw "-stack_addr must be < 4G for 32-bit processes";
1687 case CPU_TYPE_POWERPC64
:
1688 case CPU_TYPE_X86_64
:
1691 if ( (fStackAddr
& -4096) != fStackAddr
)
1692 throw "-stack_addr must be multiples of 4K";
1693 if ( fStackSize
== 0 )
1694 throw "-stack_addr must be used with -stack_size";
1697 // check -stack_size
1698 if ( fStackSize
!= 0 ) {
1699 switch (fArchitecture
) {
1701 case CPU_TYPE_POWERPC
:
1702 if ( fStackSize
> 0xFFFFFFFF )
1703 throw "-stack_size must be < 4G for 32-bit processes";
1704 if ( fStackAddr
== 0 ) {
1705 fStackAddr
= 0xC0000000;
1707 if ( (fStackAddr
> 0xB0000000) && ((fStackAddr
-fStackSize
) < 0xB0000000) )
1708 fprintf(stderr
, "ld64 warning: custom stack placement overlaps and will disable shared region\n");
1710 case CPU_TYPE_POWERPC64
:
1711 case CPU_TYPE_X86_64
:
1712 if ( fStackAddr
== 0 ) {
1713 fStackAddr
= 0x0007FFFF00000000LL
;
1717 if ( (fStackSize
& -4096) != fStackSize
)
1718 throw "-stack_size must be multiples of 4K";
1719 switch ( fOutputKind
) {
1720 case Options::kDynamicExecutable
:
1721 case Options::kStaticExecutable
:
1722 // custom stack size only legal when building main executable
1724 case Options::kDynamicLibrary
:
1725 case Options::kDynamicBundle
:
1726 case Options::kObjectFile
:
1727 case Options::kDyld
:
1728 throw "-stack_size option can only be used when linking a main executable";
1732 // check that -allow_stack_execute is only used with main executables
1733 if ( fExecutableStack
) {
1734 switch ( fOutputKind
) {
1735 case Options::kDynamicExecutable
:
1736 case Options::kStaticExecutable
:
1737 // -allow_stack_execute size only legal when building main executable
1739 case Options::kDynamicLibrary
:
1740 case Options::kDynamicBundle
:
1741 case Options::kObjectFile
:
1742 case Options::kDyld
:
1743 throw "-allow_stack_execute option can only be used when linking a main executable";
1747 // check -client_name is only used when -bundle is specified
1748 if ( (fClientName
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
1749 throw "-client_name can only be used with -bundle";
1751 // check -init is only used when building a dylib
1752 if ( (fInitFunctionName
!= NULL
) && (fOutputKind
!= Options::kDynamicLibrary
) )
1753 throw "-init can only be used with -dynamiclib";
1755 // check -bundle_loader only used with -bundle
1756 if ( (fBundleLoader
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
1757 throw "-bundle_loader can only be used with -bundle";
1759 // check -d can only be used with -r
1760 if ( fMakeTentativeDefinitionsReal
&& (fOutputKind
!= Options::kObjectFile
) )
1761 throw "-d can only be used with -r";
1763 // make sure all required exported symbols exist
1764 for (NameSet::iterator it
=fExportSymbols
.begin(); it
!= fExportSymbols
.end(); it
++) {
1765 const char* name
= *it
;
1766 // never export .eh symbols
1767 if ( strcmp(&name
[strlen(name
)-3], ".eh") != 0 )
1768 fInitialUndefines
.push_back(name
);
1771 // make sure that -init symbol exist
1772 if ( fInitFunctionName
!= NULL
)
1773 fInitialUndefines
.push_back(fInitFunctionName
);
1775 if ( fZeroPageSize
== ULLONG_MAX
) {
1776 // zero page size not specified on command line, set default
1777 switch (fArchitecture
) {
1779 case CPU_TYPE_POWERPC
:
1780 // first 4KB for 32-bit architectures
1781 fZeroPageSize
= 0x1000;
1783 case CPU_TYPE_POWERPC64
:
1784 // first 4GB for ppc64 on 10.5
1785 if ( fVersionMin
>= k10_5
)
1786 fZeroPageSize
= 0x100000000ULL
;
1788 fZeroPageSize
= 0x1000; // 10.4 dyld may not be able to handle >4GB zero page
1790 case CPU_TYPE_X86_64
:
1791 // first 4GB for x86_64 on all OS's
1792 fZeroPageSize
= 0x100000000ULL
;
1795 // if -arch not used, default to 4K zero-page
1796 fZeroPageSize
= 0x1000;
1800 switch ( fOutputKind
) {
1801 case Options::kDynamicExecutable
:
1802 case Options::kStaticExecutable
:
1803 // -pagezero_size size only legal when building main executable
1805 case Options::kDynamicLibrary
:
1806 case Options::kDynamicBundle
:
1807 case Options::kObjectFile
:
1808 case Options::kDyld
:
1809 throw "-pagezero_size option can only be used when linking a main executable";
1813 // -dead_strip and -r are incompatible
1814 if ( (fDeadStrip
!= kDeadStripOff
) && (fOutputKind
== Options::kObjectFile
) )
1815 throw "-r and -dead_strip cannot be used together\n";