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
;
377 // compatibility support for cpu-sub-types
378 else if ( (strcmp(architecture
, "ppc750") == 0)
379 || (strcmp(architecture
, "ppc7400") == 0)
380 || (strcmp(architecture
, "ppc7450") == 0)
381 || (strcmp(architecture
, "ppc970") == 0) )
382 fArchitecture
= CPU_TYPE_POWERPC
;
384 throwf(" unknown/unsupported architecture name for: -arch %s", architecture
);
387 bool Options::checkForFile(const char* format
, const char* dir
, const char* rootName
, FileInfo
& result
)
389 struct stat statBuffer
;
390 char possiblePath
[strlen(dir
)+strlen(rootName
)+strlen(format
)+8];
391 sprintf(possiblePath
, format
, dir
, rootName
);
392 bool found
= (stat(possiblePath
, &statBuffer
) == 0);
393 if ( fTraceDylibSearching
)
394 printf("[Logging for XBS]%sfound library: '%s'\n", (found
? " " : " not "), possiblePath
);
396 result
.path
= strdup(possiblePath
);
397 result
.fileLen
= statBuffer
.st_size
;
398 result
.modTime
= statBuffer
.st_mtime
;
405 Options::FileInfo
Options::findLibrary(const char* rootName
)
408 const int rootNameLen
= strlen(rootName
);
409 // if rootName ends in .o there is no .a vs .dylib choice
410 if ( (rootNameLen
> 3) && (strcmp(&rootName
[rootNameLen
-2], ".o") == 0) ) {
411 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
412 it
!= fLibrarySearchPaths
.end();
414 const char* dir
= *it
;
415 if ( checkForFile("%s/%s", dir
, rootName
, result
) )
420 bool lookForDylibs
= ( fOutputKind
!= Options::kDyld
);
421 switch ( fLibrarySearchMode
) {
422 case kSearchAllDirsForDylibsThenAllDirsForArchives
:
423 // first look in all directories for just for dylibs
424 if ( lookForDylibs
) {
425 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
426 it
!= fLibrarySearchPaths
.end();
428 const char* dir
= *it
;
429 if ( checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
433 // next look in all directories for just for archives
434 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
435 it
!= fLibrarySearchPaths
.end();
437 const char* dir
= *it
;
438 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
443 case kSearchDylibAndArchiveInEachDir
:
444 // look in each directory for just for a dylib then for an archive
445 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
446 it
!= fLibrarySearchPaths
.end();
448 const char* dir
= *it
;
449 if ( lookForDylibs
&& checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
451 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
457 throwf("library not found for -l%s", rootName
);
460 Options::FileInfo
Options::findFramework(const char* frameworkName
)
462 if ( frameworkName
== NULL
)
463 throw "-frameowrk missing next argument";
464 char temp
[strlen(frameworkName
)+1];
465 strcpy(temp
, frameworkName
);
466 const char* name
= temp
;
467 const char* suffix
= NULL
;
468 char* comma
= strchr(temp
, ',');
469 if ( comma
!= NULL
) {
473 return findFramework(name
, suffix
);
476 Options::FileInfo
Options::findFramework(const char* rootName
, const char* suffix
)
478 struct stat statBuffer
;
479 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
480 it
!= fFrameworkSearchPaths
.end();
482 // ??? Shouldn't we be using String here and just initializing it?
483 // ??? Use str.c_str () to pull out the string for the stat call.
484 const char* dir
= *it
;
485 char possiblePath
[PATH_MAX
];
486 strcpy(possiblePath
, dir
);
487 strcat(possiblePath
, "/");
488 strcat(possiblePath
, rootName
);
489 strcat(possiblePath
, ".framework/");
490 strcat(possiblePath
, rootName
);
491 if ( suffix
!= NULL
) {
492 char realPath
[PATH_MAX
];
493 // no symlink in framework to suffix variants, so follow main symlink
494 if ( realpath(possiblePath
, realPath
) != NULL
) {
495 strcpy(possiblePath
, realPath
);
496 strcat(possiblePath
, suffix
);
499 bool found
= (stat(possiblePath
, &statBuffer
) == 0);
500 if ( fTraceDylibSearching
)
501 printf("[Logging for XBS]%sfound framework: '%s'\n",
502 (found
? " " : " not "), possiblePath
);
505 result
.path
= strdup(possiblePath
);
506 result
.fileLen
= statBuffer
.st_size
;
507 result
.modTime
= statBuffer
.st_mtime
;
511 // try without suffix
512 if ( suffix
!= NULL
)
513 return findFramework(rootName
, NULL
);
515 throwf("framework not found %s", rootName
);
518 Options::FileInfo
Options::findFile(const char* path
)
521 struct stat statBuffer
;
523 // if absolute path and not a .o file, the use SDK prefix
524 if ( (path
[0] == '/') && (strcmp(&path
[strlen(path
)-2], ".o") != 0) ) {
525 const int pathLen
= strlen(path
);
526 for (std::vector
<const char*>::iterator it
= fSDKPaths
.begin(); it
!= fSDKPaths
.end(); it
++) {
527 // ??? Shouldn't we be using String here?
528 const char* sdkPathDir
= *it
;
529 const int sdkPathDirLen
= strlen(sdkPathDir
);
530 char possiblePath
[sdkPathDirLen
+pathLen
+4];
531 strcpy(possiblePath
, sdkPathDir
);
532 if ( possiblePath
[sdkPathDirLen
-1] == '/' )
533 possiblePath
[sdkPathDirLen
-1] = '\0';
534 strcat(possiblePath
, path
);
535 if ( stat(possiblePath
, &statBuffer
) == 0 ) {
536 result
.path
= strdup(possiblePath
);
537 result
.fileLen
= statBuffer
.st_size
;
538 result
.modTime
= statBuffer
.st_mtime
;
544 if ( stat(path
, &statBuffer
) == 0 ) {
545 result
.path
= strdup(path
);
546 result
.fileLen
= statBuffer
.st_size
;
547 result
.modTime
= statBuffer
.st_mtime
;
551 // try @executable_path substitution
552 if ( (strncmp(path
, "@executable_path/", 17) == 0) && (fExecutablePath
!= NULL
) ) {
553 char newPath
[strlen(fExecutablePath
) + strlen(path
)];
554 strcpy(newPath
, fExecutablePath
);
555 char* addPoint
= strrchr(newPath
,'/');
556 if ( addPoint
!= NULL
)
557 strcpy(&addPoint
[1], &path
[17]);
559 strcpy(newPath
, &path
[17]);
560 if ( stat(newPath
, &statBuffer
) == 0 ) {
561 result
.path
= strdup(newPath
);
562 result
.fileLen
= statBuffer
.st_size
;
563 result
.modTime
= statBuffer
.st_mtime
;
569 throwf("file not found: %s", path
);
573 void Options::loadFileList(const char* fileOfPaths
)
576 const char* comma
= strrchr(fileOfPaths
, ',');
577 const char* prefix
= NULL
;
578 if ( comma
!= NULL
) {
580 int realFileOfPathsLen
= comma
-fileOfPaths
;
581 char realFileOfPaths
[realFileOfPathsLen
+1];
582 strncpy(realFileOfPaths
,fileOfPaths
, realFileOfPathsLen
);
583 realFileOfPaths
[realFileOfPathsLen
] = '\0';
584 file
= fopen(realFileOfPaths
, "r");
586 throwf("-filelist file not found: %s\n", realFileOfPaths
);
589 file
= fopen(fileOfPaths
, "r");
591 throwf("-filelist file not found: %s\n", fileOfPaths
);
595 while ( fgets(path
, 1024, file
) != NULL
) {
596 path
[PATH_MAX
-1] = '\0';
597 char* eol
= strchr(path
, '\n');
600 if ( prefix
!= NULL
) {
601 char builtPath
[strlen(prefix
)+strlen(path
)+2];
602 strcpy(builtPath
, prefix
);
603 strcat(builtPath
, "/");
604 strcat(builtPath
, path
);
605 fInputFiles
.push_back(findFile(builtPath
));
608 fInputFiles
.push_back(findFile(path
));
615 void Options::loadExportFile(const char* fileOfExports
, const char* option
, NameSet
& set
)
617 // read in whole file
618 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
620 throwf("can't open %s file: %s", option
, fileOfExports
);
621 struct stat stat_buf
;
622 ::fstat(fd
, &stat_buf
);
623 char* p
= (char*)malloc(stat_buf
.st_size
);
625 throwf("can't process %s file: %s", option
, fileOfExports
);
627 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
628 throwf("can't read %s file: %s", option
, fileOfExports
);
632 // parse into symbols and add to hash_set
633 char * const end
= &p
[stat_buf
.st_size
];
634 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
635 char* symbolStart
= NULL
;
636 for (char* s
= p
; s
< end
; ++s
) {
642 else if ( !isspace(*s
) ) {
650 // removing any trailing spaces
652 while ( isspace(*last
) ) {
656 set
.insert(symbolStart
);
667 if ( state
== inSymbol
) {
668 fprintf(stderr
, "ld64 warning: missing line-end at end of file \"%s\"\n", fileOfExports
);
669 int len
= end
-symbolStart
+1;
670 char* temp
= new char[len
];
671 strlcpy(temp
, symbolStart
, len
);
673 // remove any trailing spaces
674 char* last
= &temp
[len
-2];
675 while ( isspace(*last
) ) {
682 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
685 void Options::setUndefinedTreatment(const char* treatment
)
687 if ( treatment
== NULL
)
688 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
690 if ( strcmp(treatment
, "warning") == 0 )
691 fUndefinedTreatment
= kUndefinedWarning
;
692 else if ( strcmp(treatment
, "error") == 0 )
693 fUndefinedTreatment
= kUndefinedError
;
694 else if ( strcmp(treatment
, "suppress") == 0 )
695 fUndefinedTreatment
= kUndefinedSuppress
;
696 else if ( strcmp(treatment
, "dynamic_lookup") == 0 )
697 fUndefinedTreatment
= kUndefinedDynamicLookup
;
699 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
702 Options::Treatment
Options::parseTreatment(const char* treatment
)
704 if ( treatment
== NULL
)
707 if ( strcmp(treatment
, "warning") == 0 )
709 else if ( strcmp(treatment
, "error") == 0 )
711 else if ( strcmp(treatment
, "suppress") == 0 )
717 void Options::setVersionMin(const char* version
)
719 if ( version
== NULL
)
720 throw "-macosx_version_min argument missing";
722 if ( (strncmp(version
, "10.", 3) == 0) && isdigit(version
[3]) ) {
723 int num
= version
[3] - '0';
744 fprintf(stderr
, "ld64: unknown option to -macosx_version_min not 10.x");
748 void Options::setWeakReferenceMismatchTreatment(const char* treatment
)
750 if ( treatment
== NULL
)
751 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
753 if ( strcmp(treatment
, "error") == 0 )
754 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchError
;
755 else if ( strcmp(treatment
, "weak") == 0 )
756 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchWeak
;
757 else if ( strcmp(treatment
, "non-weak") == 0 )
758 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchNonWeak
;
760 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
763 Options::CommonsMode
Options::parseCommonsTreatment(const char* mode
)
766 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
768 if ( strcmp(mode
, "ignore_dylibs") == 0 )
769 return kCommonsIgnoreDylibs
;
770 else if ( strcmp(mode
, "use_dylibs") == 0 )
771 return kCommonsOverriddenByDylibs
;
772 else if ( strcmp(mode
, "error") == 0 )
773 return kCommonsConflictsDylibsError
;
775 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
778 void Options::setDylibInstallNameOverride(const char* paths
)
784 uint64_t Options::parseAddress(const char* addr
)
787 uint64_t result
= strtoull(addr
, &endptr
, 16);
792 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
795 uint32_t Options::parseVersionNumber(const char* versionString
)
801 x
= strtoul(versionString
, &end
, 10);
803 y
= strtoul(&end
[1], &end
, 10);
805 z
= strtoul(&end
[1], &end
, 10);
808 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
809 throwf("malformed version number: %s", versionString
);
811 return (x
<< 16) | ( y
<< 8 ) | z
;
814 void Options::parseSectionOrderFile(const char* segment
, const char* section
, const char* path
)
816 fprintf(stderr
, "ld64: warning -sectorder not yet supported for 64-bit code\n");
819 void Options::addSection(const char* segment
, const char* section
, const char* path
)
821 if ( strlen(segment
) > 16 )
822 throw "-seccreate segment name max 16 chars";
823 if ( strlen(section
) > 16 ) {
824 char* tmp
= strdup(section
);
826 fprintf(stderr
, "ld64 warning: -seccreate section name (%s) truncated to 16 chars (%s)\n", section
, tmp
);
830 // read in whole file
831 int fd
= ::open(path
, O_RDONLY
, 0);
833 throwf("can't open -sectcreate file: %s", path
);
834 struct stat stat_buf
;
835 ::fstat(fd
, &stat_buf
);
836 char* p
= (char*)malloc(stat_buf
.st_size
);
838 throwf("can't process -sectcreate file: %s", path
);
839 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
840 throwf("can't read -sectcreate file: %s", path
);
843 // record section to create
844 ExtraSection info
= { segment
, section
, path
, (uint8_t*)p
, stat_buf
.st_size
};
845 fExtraSections
.push_back(info
);
848 void Options::addSectionAlignment(const char* segment
, const char* section
, const char* alignmentStr
)
850 if ( strlen(segment
) > 16 )
851 throw "-sectalign segment name max 16 chars";
852 if ( strlen(section
) > 16 )
853 throw "-sectalign section name max 16 chars";
855 // argument to -sectalign is a hexadecimal number
857 unsigned long value
= strtoul(alignmentStr
, &endptr
, 16);
858 if ( *endptr
!= '\0')
859 throw "argument for -sectalign is not a hexadecimal number";
860 if ( value
> 0x8000 )
861 throw "argument for -sectalign must be less than or equal to 0x8000";
863 fprintf(stderr
, "ld64 warning: zero is not a valid -sectalign\n");
867 // alignment is power of 2 (e.g. page alignment = 12)
868 uint8_t alignment
= (uint8_t)log2(value
);
870 if ( (unsigned long)(1 << alignment
) != value
) {
871 fprintf(stderr
, "ld64 warning: alignment for -sectalign %s %s is not a power of two, using 0x%X\n",
872 segment
, section
, 1 << alignment
);
875 SectionAlignment info
= { segment
, section
, alignment
};
876 fSectionAlignments
.push_back(info
);
880 // Process all command line arguments.
882 // The only error checking done here is that each option is valid and if it has arguments
883 // that they too are valid.
885 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
886 // whichever was last on the command line is used.
888 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
890 void Options::parse(int argc
, const char* argv
[])
892 // pass one builds search list from -L and -F options
893 this->buildSearchPaths(argc
, argv
);
895 // reduce re-allocations
896 fInputFiles
.reserve(32);
898 // pass two parse all other options
899 for(int i
=1; i
< argc
; ++i
) {
900 const char* arg
= argv
[i
];
902 if ( arg
[0] == '-' ) {
904 // Since we don't care about the files passed, just the option names, we do this here.
906 fprintf (stderr
, "[Logging ld64 options]\t%s\n", arg
);
908 if ( (arg
[1] == 'L') || (arg
[1] == 'F') ) {
909 // previously handled by buildSearchPaths()
911 else if ( strcmp(arg
, "-arch") == 0 ) {
912 parseArch(argv
[++i
]);
914 else if ( strcmp(arg
, "-dynamic") == 0 ) {
917 else if ( strcmp(arg
, "-static") == 0 ) {
918 fOutputKind
= kStaticExecutable
;
920 else if ( strcmp(arg
, "-dylib") == 0 ) {
921 fOutputKind
= kDynamicLibrary
;
923 else if ( strcmp(arg
, "-bundle") == 0 ) {
924 fOutputKind
= kDynamicBundle
;
926 else if ( strcmp(arg
, "-dylinker") == 0 ) {
929 else if ( strcmp(arg
, "-execute") == 0 ) {
930 if ( fOutputKind
!= kStaticExecutable
)
931 fOutputKind
= kDynamicExecutable
;
933 else if ( strcmp(arg
, "-r") == 0 ) {
934 fOutputKind
= kObjectFile
;
936 else if ( strcmp(arg
, "-o") == 0 ) {
937 fOutputFile
= argv
[++i
];
939 else if ( arg
[1] == 'l' ) {
940 fInputFiles
.push_back(findLibrary(&arg
[2]));
942 // This causes a dylib to be weakly bound at
943 // link time. This corresponds to weak_import.
944 else if ( strncmp(arg
, "-weak-l", 7) == 0 ) {
945 FileInfo info
= findLibrary(&arg
[7]);
946 info
.options
.fWeakImport
= true;
947 fInputFiles
.push_back(info
);
949 // Avoid lazy binding.
951 else if ( strcmp(arg
, "-bind_at_load") == 0 ) {
954 else if ( strcmp(arg
, "-twolevel_namespace") == 0 ) {
955 fNameSpace
= kTwoLevelNameSpace
;
957 else if ( strcmp(arg
, "-flat_namespace") == 0 ) {
958 fNameSpace
= kFlatNameSpace
;
960 // Also sets a bit to ensure dyld causes everything
961 // in the namespace to be flat.
963 else if ( strcmp(arg
, "-force_flat_namespace") == 0 ) {
964 fNameSpace
= kForceFlatNameSpace
;
966 // Similar to --whole-archive.
967 else if ( strcmp(arg
, "-all_load") == 0 ) {
968 fReaderOptions
.fFullyLoadArchives
= true;
970 // Similar to --whole-archive, but for all ObjC classes.
971 else if ( strcmp(arg
, "-ObjC") == 0 ) {
972 fReaderOptions
.fLoadObjcClassesInArchives
= true;
974 // Library versioning.
975 else if ( strcmp(arg
, "-dylib_compatibility_version") == 0 ) {
976 fDylibCompatVersion
= parseVersionNumber(argv
[++i
]);
978 else if ( strcmp(arg
, "-dylib_current_version") == 0 ) {
979 fDylibCurrentVersion
= parseVersionNumber(argv
[++i
]);
981 else if ( strcmp(arg
, "-sectorder") == 0 ) {
982 parseSectionOrderFile(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
985 // ??? Deprecate segcreate.
986 // -sectcreate puts whole files into a section in the output.
987 else if ( (strcmp(arg
, "-sectcreate") == 0) || (strcmp(arg
, "-segcreate") == 0) ) {
988 addSection(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
991 // Since we have a full path in binary/library names we need to be able to override it.
992 else if ( (strcmp(arg
, "-dylib_install_name") == 0) || (strcmp(arg
, "-dylinker_install_name") == 0) ) {
993 fDylibInstallName
= argv
[++i
];
995 // Sets the base address of the output.
996 else if ( (strcmp(arg
, "-seg1addr") == 0) || (strcmp(arg
, "-image_base") == 0) ) {
997 fBaseAddress
= parseAddress(argv
[++i
]);
999 else if ( strcmp(arg
, "-e") == 0 ) {
1000 fEntryName
= argv
[++i
];
1002 // Same as -@ from the FSF linker.
1003 else if ( strcmp(arg
, "-filelist") == 0 ) {
1004 loadFileList(argv
[++i
]);
1006 else if ( strcmp(arg
, "-keep_private_externs") == 0 ) {
1007 fKeepPrivateExterns
= true;
1010 else if ( strcmp(arg
, "-final_output") == 0 ) {
1014 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
1015 // just ensures that this happens for cross object file boundaries.
1016 else if ( (strcmp(arg
, "-interposable") == 0) || (strcmp(arg
, "-multi_module") == 0)) {
1017 fInterposable
= true;
1019 // Default for -interposable/-multi_module/-single_module.
1020 else if ( strcmp(arg
, "-single_module") == 0 ) {
1021 fInterposable
= false;
1023 else if ( strcmp(arg
, "-exported_symbols_list") == 0 ) {
1024 if ( fExportMode
== kDontExportSome
)
1025 throw "can't use -exported_symbols_list and -unexported_symbols_list";
1026 fExportMode
= kExportSome
;
1027 loadExportFile(argv
[++i
], "-exported_symbols_list", fExportSymbols
);
1029 else if ( strcmp(arg
, "-unexported_symbols_list") == 0 ) {
1030 if ( fExportMode
== kExportSome
)
1031 throw "can't use -exported_symbols_list and -unexported_symbols_list";
1032 fExportMode
= kDontExportSome
;
1033 loadExportFile(argv
[++i
], "-unexported_symbols_list", fDontExportSymbols
);
1036 else if ( strcmp(arg
, "-no_arch_warnings") == 0 ) {
1037 fIgnoreOtherArchFiles
= true;
1039 else if ( strcmp(arg
, "-force_cpusubtype_ALL") == 0 ) {
1040 fForceSubtypeAll
= true;
1042 // Similar to -weak-l but uses the absolute path name to the library.
1043 else if ( strcmp(arg
, "-weak_library") == 0 ) {
1044 FileInfo info
= findFile(argv
[++i
]);
1045 info
.options
.fWeakImport
= true;
1046 fInputFiles
.push_back(info
);
1048 else if ( strcmp(arg
, "-framework") == 0 ) {
1049 fInputFiles
.push_back(findFramework(argv
[++i
]));
1051 else if ( strcmp(arg
, "-weak_framework") == 0 ) {
1052 FileInfo info
= findFramework(argv
[++i
]);
1053 info
.options
.fWeakImport
= true;
1054 fInputFiles
.push_back(info
);
1056 // ??? Deprecate when we get -Bstatic/-Bdynamic.
1057 else if ( strcmp(arg
, "-search_paths_first") == 0 ) {
1058 fLibrarySearchMode
= kSearchDylibAndArchiveInEachDir
;
1060 else if ( strcmp(arg
, "-undefined") == 0 ) {
1061 setUndefinedTreatment(argv
[++i
]);
1063 // Debugging output flag.
1064 else if ( strcmp(arg
, "-arch_multiple") == 0 ) {
1065 fMessagesPrefixedWithArchitecture
= true;
1067 // Specify what to do with relocations in read only
1068 // sections like .text. Could be errors, warnings,
1069 // or suppressed. Currently we do nothing with the
1071 else if ( strcmp(arg
, "-read_only_relocs") == 0 ) {
1072 Treatment temp
= parseTreatment(argv
[++i
]);
1074 if ( temp
== kNULL
)
1075 throw "-read_only_relocs missing [ warning | error | suppress ]";
1076 else if ( temp
== kInvalid
)
1077 throw "invalid option to -read_only_relocs [ warning | error | suppress ]";
1079 // Specifies whether or not there are intra section
1080 // relocations and what to do when found. Could be
1081 // errors, warnings, or suppressed.
1082 else if ( strcmp(arg
, "-sect_diff_relocs") == 0 ) {
1083 fPICTreatment
= parseTreatment(argv
[++i
]);
1085 if ( fPICTreatment
== kNULL
)
1086 throw "-sect_diff_relocs missing [ warning | error | suppress ]";
1087 else if ( fPICTreatment
== kInvalid
)
1088 throw "invalid option to -sect_diff_relocs [ warning | error | suppress ]";
1090 // Warn, error or make strong a mismatch between weak
1091 // and non-weak references.
1092 else if ( strcmp(arg
, "-weak_reference_mismatches") == 0 ) {
1093 setWeakReferenceMismatchTreatment(argv
[++i
]);
1095 // For a deployment target of 10.3 and earlier ld64 will
1096 // prebind an executable with 0s in all addresses that
1097 // are prebound. This can then be fixed up by update_prebinding
1098 // later. Prebinding is less useful on 10.4 and greater.
1099 else if ( strcmp(arg
, "-prebind") == 0 ) {
1102 else if ( strcmp(arg
, "-noprebind") == 0 ) {
1106 else if ( strcmp(arg
, "-prebind_allow_overlap") == 0 ) {
1107 // Do not handle and suppress warnings always.
1110 else if ( strcmp(arg
, "-prebind_all_twolevel_modules") == 0 ) {
1114 else if ( strcmp(arg
, "-noprebind_all_twolevel_modules") == 0 ) {
1117 // Sets a bit in the main executable only that causes fix_prebinding
1118 // not to run. This is always set.
1119 else if ( strcmp(arg
, "-nofixprebinding") == 0 ) {
1122 // This should probably be deprecated when we respect -L and -F
1123 // when searching for libraries.
1124 else if ( strcmp(arg
, "-dylib_file") == 0 ) {
1125 setDylibInstallNameOverride(argv
[++i
]);
1127 // Allows us to rewrite full paths to be relocatable based on
1128 // the path name of the executable.
1129 else if ( strcmp(arg
, "-executable_path") == 0 ) {
1130 fExecutablePath
= argv
[++i
];
1131 if ( (fExecutablePath
== NULL
) || (fExecutablePath
[0] == '-') )
1132 throw "-executable_path missing <path>";
1135 // Aligns all segments to the power of 2 boundary specified.
1136 else if ( strcmp(arg
, "-segalign") == 0 ) {
1140 // Puts a specified segment at a particular address that must
1141 // be a multiple of the segment alignment.
1142 else if ( strcmp(arg
, "-segaddr") == 0 ) {
1146 // ??? Deprecate when we deprecate split-seg.
1147 else if ( strcmp(arg
, "-segs_read_only_addr") == 0 ) {
1151 // ??? Deprecate when we deprecate split-seg.
1152 else if ( strcmp(arg
, "-segs_read_write_addr") == 0 ) {
1156 // ??? Deprecate when we get rid of basing at build time.
1157 else if ( strcmp(arg
, "-seg_addr_table") == 0 ) {
1162 else if ( strcmp(arg
, "-seg_addr_table_filename") == 0 ) {
1166 else if ( strcmp(arg
, "-segprot") == 0 ) {
1170 else if ( strcmp(arg
, "-pagezero_size") == 0 ) {
1171 fZeroPageSize
= parseAddress(argv
[++i
]);
1172 uint64_t temp
= fZeroPageSize
& (-4096); // page align
1173 if ( fZeroPageSize
!= temp
)
1174 fprintf(stderr
, "ld64: warning, -pagezero_size not page aligned, rounding down\n");
1175 fZeroPageSize
= temp
;
1177 else if ( strcmp(arg
, "-stack_addr") == 0 ) {
1178 fStackAddr
= parseAddress(argv
[++i
]);
1180 else if ( strcmp(arg
, "-stack_size") == 0 ) {
1181 fStackSize
= parseAddress(argv
[++i
]);
1183 else if ( strcmp(arg
, "-allow_stack_execute") == 0 ) {
1184 fExecutableStack
= true;
1186 else if ( strcmp(arg
, "-sectalign") == 0 ) {
1187 addSectionAlignment(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1190 else if ( strcmp(arg
, "-sectorder_detail") == 0 ) {
1193 else if ( strcmp(arg
, "-sectobjectsymbols") == 0 ) {
1197 else if ( strcmp(arg
, "-bundle_loader") == 0 ) {
1198 fBundleLoader
= argv
[++i
];
1199 if ( (fBundleLoader
== NULL
) || (fBundleLoader
[0] == '-') )
1200 throw "-bundle_loader missing <path>";
1201 FileInfo info
= findFile(fBundleLoader
);
1202 info
.options
.fBundleLoader
= true;
1203 fInputFiles
.push_back(info
);
1205 else if ( strcmp(arg
, "-private_bundle") == 0 ) {
1208 else if ( strcmp(arg
, "-twolevel_namespace_hints") == 0 ) {
1211 // Use this flag to set default behavior for deployement targets.
1212 else if ( strcmp(arg
, "-macosx_version_min") == 0 ) {
1213 setVersionMin(argv
[++i
]);
1215 // This option (unlike -m below) only affects how we warn
1216 // on multiple definitions inside dynamic libraries.
1217 else if ( strcmp(arg
, "-multiply_defined") == 0 ) {
1218 fMultiplyDefinedDynamic
= parseTreatment(argv
[++i
]);
1220 if ( fMultiplyDefinedDynamic
== kNULL
)
1221 throw "-multiply_defined missing [ warning | error | suppress ]";
1222 else if ( fMultiplyDefinedDynamic
== kInvalid
)
1223 throw "invalid option to -multiply_defined [ warning | error | suppress ]";
1225 else if ( strcmp(arg
, "-multiply_defined_unused") == 0 ) {
1226 fMultiplyDefinedUnused
= parseTreatment(argv
[++i
]);
1228 if ( fMultiplyDefinedUnused
== kNULL
)
1229 throw "-multiply_defined_unused missing [ warning | error | suppress ]";
1230 else if ( fMultiplyDefinedUnused
== kInvalid
)
1231 throw "invalid option to -multiply_defined_unused [ warning | error | suppress ]";
1233 else if ( strcmp(arg
, "-nomultidefs") == 0 ) {
1236 // Display each file in which the argument symbol appears and whether
1237 // the file defines or references it. This option takes an argument
1238 // as -y<symbol> note that there is no space.
1239 else if ( strncmp(arg
, "-y", 2) == 0 ) {
1240 const char* name
= &arg
[2];
1243 throw "-y missing argument";
1245 fTraceSymbols
.push_back(name
);
1247 // Same output as -y, but output <arg> number of undefined symbols only.
1248 else if ( strcmp(arg
, "-Y") == 0 ) {
1250 fLimitUndefinedSymbols
= strtoul (argv
[++i
], &endptr
, 10);
1253 throw "invalid argument for -Y [decimal number]";
1255 // This option affects all objects linked into the final result.
1256 else if ( strcmp(arg
, "-m") == 0 ) {
1257 fWarnOnMultiplyDefined
= true;
1259 else if ( (strcmp(arg
, "-why_load") == 0) || (strcmp(arg
, "-whyload") == 0) ) {
1260 fReaderOptions
.fWhyLoad
= true;
1262 else if ( strcmp(arg
, "-why_live") == 0 ) {
1263 const char* name
= argv
[++i
];
1265 throw "-why_live missing symbol name argument";
1266 fWhyLive
.insert(name
);
1268 else if ( strcmp(arg
, "-u") == 0 ) {
1269 const char* name
= argv
[++i
];
1271 throw "-u missing argument";
1272 fInitialUndefines
.push_back(name
);
1274 else if ( strcmp(arg
, "-U") == 0 ) {
1278 else if ( strcmp(arg
, "-s") == 0 ) {
1279 fStripLocalSymbols
= true;
1280 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
1282 else if ( strcmp(arg
, "-x") == 0 ) {
1283 fStripLocalSymbols
= true;
1285 else if ( strcmp(arg
, "-S") == 0 ) {
1286 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoNone
;
1288 else if ( strcmp(arg
, "-X") == 0 ) {
1291 else if ( strcmp(arg
, "-Si") == 0 ) {
1292 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoFull
;
1294 else if ( strcmp(arg
, "-b") == 0 ) {
1297 else if ( strcmp(arg
, "-Sn") == 0 ) {
1298 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoFull
;
1300 else if ( strcmp(arg
, "-Sp") == 0 ) {
1301 fReaderOptions
.fDebugInfoStripping
= ObjectFile::ReaderOptions::kDebugInfoMinimal
;
1303 else if ( strcmp(arg
, "-dead_strip") == 0 ) {
1304 fDeadStrip
= kDeadStripOnPlusUnusedInits
;
1306 else if ( strcmp(arg
, "-no_dead_strip_inits_and_terms") == 0 ) {
1307 fDeadStrip
= kDeadStripOn
;
1309 else if ( strcmp(arg
, "-w") == 0 ) {
1312 else if ( strcmp(arg
, "-arch_errors_fatal") == 0 ) {
1315 else if ( strcmp(arg
, "-M") == 0 ) {
1318 else if ( strcmp(arg
, "-whatsloaded") == 0 ) {
1321 else if ( strcmp(arg
, "-headerpad") == 0 ) {
1322 const char* size
= argv
[++i
];
1324 throw "-headerpad missing argument";
1325 fMinimumHeaderPad
= parseAddress(size
);
1327 else if ( strcmp(arg
, "-headerpad_max_install_names") == 0 ) {
1330 else if ( strcmp(arg
, "-t") == 0 ) {
1333 else if ( strcmp(arg
, "-A") == 0 ) {
1337 else if ( strcmp(arg
, "-umbrella") == 0 ) {
1338 const char* name
= argv
[++i
];
1340 throw "-umbrella missing argument";
1341 fUmbrellaName
= name
;
1343 else if ( strcmp(arg
, "-allowable_client") == 0 ) {
1344 const char* name
= argv
[++i
];
1347 throw "-allowable_client missing argument";
1349 fAllowableClients
.push_back(name
);
1351 else if ( strcmp(arg
, "-client_name") == 0 ) {
1352 const char* name
= argv
[++i
];
1355 throw "-client_name missing argument";
1359 else if ( strcmp(arg
, "-sub_umbrella") == 0 ) {
1360 const char* name
= argv
[++i
];
1362 throw "-sub_umbrella missing argument";
1363 fSubUmbellas
.push_back(name
);
1365 else if ( strcmp(arg
, "-sub_library") == 0 ) {
1366 const char* name
= argv
[++i
];
1368 throw "-sub_library missing argument";
1369 fSubLibraries
.push_back(name
);
1371 else if ( strcmp(arg
, "-init") == 0 ) {
1372 const char* name
= argv
[++i
];
1374 throw "-init missing argument";
1375 fInitFunctionName
= name
;
1377 else if ( strcmp(arg
, "-dot") == 0 ) {
1378 const char* name
= argv
[++i
];
1380 throw "-dot missing argument";
1381 fDotOutputFile
= name
;
1383 else if ( strcmp(arg
, "-warn_commons") == 0 ) {
1384 fWarnCommons
= true;
1386 else if ( strcmp(arg
, "-commons") == 0 ) {
1387 fCommonsMode
= parseCommonsTreatment(argv
[++i
]);
1389 else if ( strcmp(arg
, "-keep_relocs") == 0 ) {
1390 fKeepRelocations
= true;
1392 else if ( strcmp(arg
, "-warn_stabs") == 0 ) {
1395 else if ( strcmp(arg
, "-pause") == 0 ) {
1398 else if ( strcmp(arg
, "-print_statistics") == 0 ) {
1401 else if ( strcmp(arg
, "-d") == 0 ) {
1402 fMakeTentativeDefinitionsReal
= true;
1404 else if ( strcmp(arg
, "-v") == 0 ) {
1405 // previously handled by buildSearchPaths()
1407 else if ( strcmp(arg
, "-Z") == 0 ) {
1408 // previously handled by buildSearchPaths()
1410 else if ( strcmp(arg
, "-syslibroot") == 0 ) {
1412 // previously handled by buildSearchPaths()
1414 else if ( strcmp(arg
, "-no_uuid") == 0 ) {
1417 // put this last so that it does not interfer with other options starting with 'i'
1418 else if ( strncmp(arg
, "-i", 2) == 0 ) {
1419 fprintf(stderr
, "ld64: -i option (indirect symbols) not supported\n");
1422 throwf("unknown option: %s", arg
);
1426 fInputFiles
.push_back(findFile(arg
));
1434 // -syslibroot <path> is used for SDK support.
1435 // The rule is that all search paths (both explicit and default) are
1436 // checked to see if they exist in the SDK. If so, that path is
1437 // replaced with the sdk prefixed path. If not, that search path
1438 // is used as is. If multiple -syslibroot options are specified
1439 // their directory structures are logically overlayed and files
1440 // from sdks specified earlier on the command line used before later ones.
1442 void Options::buildSearchPaths(int argc
, const char* argv
[])
1444 bool addStandardLibraryDirectories
= true;
1445 std::vector
<const char*> libraryPaths
;
1446 std::vector
<const char*> frameworkPaths
;
1447 libraryPaths
.reserve(10);
1448 frameworkPaths
.reserve(10);
1449 // scan through argv looking for -L, -F, -Z, and -syslibroot options
1450 for(int i
=0; i
< argc
; ++i
) {
1451 if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'L') )
1452 libraryPaths
.push_back(&argv
[i
][2]);
1453 else if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'F') )
1454 frameworkPaths
.push_back(&argv
[i
][2]);
1455 else if ( strcmp(argv
[i
], "-Z") == 0 )
1456 addStandardLibraryDirectories
= false;
1457 else if ( strcmp(argv
[i
], "-v") == 0 ) {
1459 extern const char ld64VersionString
[];
1460 fprintf(stderr
, "%s", ld64VersionString
);
1461 // if only -v specified, exit cleanly
1465 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
1466 const char* path
= argv
[++i
];
1468 throw "-syslibroot missing argument";
1469 fSDKPaths
.push_back(path
);
1472 if ( addStandardLibraryDirectories
) {
1473 libraryPaths
.push_back("/usr/lib");
1474 libraryPaths
.push_back("/usr/local/lib");
1476 frameworkPaths
.push_back("/Library/Frameworks/");
1477 frameworkPaths
.push_back("/Network/Library/Frameworks/");
1478 frameworkPaths
.push_back("/System/Library/Frameworks/");
1481 // now merge sdk and library paths to make real search paths
1482 fLibrarySearchPaths
.reserve(libraryPaths
.size()*(fSDKPaths
.size()+1));
1483 for (std::vector
<const char*>::iterator it
= libraryPaths
.begin(); it
!= libraryPaths
.end(); it
++) {
1484 const char* libDir
= *it
;
1485 bool sdkOverride
= false;
1486 if ( libDir
[0] == '/' ) {
1487 char betterLibDir
[PATH_MAX
];
1488 if ( strstr(libDir
, "/..") != NULL
) {
1489 if ( realpath(libDir
, betterLibDir
) != NULL
)
1490 libDir
= strdup(betterLibDir
);
1492 const int libDirLen
= strlen(libDir
);
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
[libDirLen
+ sdkDirLen
+4];
1498 strcpy(newPath
, sdkDir
);
1499 if ( newPath
[sdkDirLen
-1] == '/' )
1500 newPath
[sdkDirLen
-1] = '\0';
1501 strcat(newPath
, libDir
);
1502 struct stat statBuffer
;
1503 if ( stat(newPath
, &statBuffer
) == 0 ) {
1504 fLibrarySearchPaths
.push_back(strdup(newPath
));
1510 fLibrarySearchPaths
.push_back(libDir
);
1513 // now merge sdk and framework paths to make real search paths
1514 fFrameworkSearchPaths
.reserve(frameworkPaths
.size()*(fSDKPaths
.size()+1));
1515 for (std::vector
<const char*>::iterator it
= frameworkPaths
.begin(); it
!= frameworkPaths
.end(); it
++) {
1516 const char* frameworkDir
= *it
;
1517 bool sdkOverride
= false;
1518 if ( frameworkDir
[0] == '/' ) {
1519 char betterFrameworkDir
[PATH_MAX
];
1520 if ( strstr(frameworkDir
, "/..") != NULL
) {
1521 if ( realpath(frameworkDir
, betterFrameworkDir
) != NULL
)
1522 frameworkDir
= strdup(betterFrameworkDir
);
1524 const int frameworkDirLen
= strlen(frameworkDir
);
1525 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
1526 // ??? Should be using string here
1527 const char* sdkDir
= *sdkit
;
1528 const int sdkDirLen
= strlen(sdkDir
);
1529 char newPath
[frameworkDirLen
+ sdkDirLen
+4];
1530 strcpy(newPath
, sdkDir
);
1531 if ( newPath
[sdkDirLen
-1] == '/' )
1532 newPath
[sdkDirLen
-1] = '\0';
1533 strcat(newPath
, frameworkDir
);
1534 struct stat statBuffer
;
1535 if ( stat(newPath
, &statBuffer
) == 0 ) {
1536 fFrameworkSearchPaths
.push_back(strdup(newPath
));
1542 fFrameworkSearchPaths
.push_back(frameworkDir
);
1546 fprintf(stderr
,"Library search paths:\n");
1547 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin();
1548 it
!= fLibrarySearchPaths
.end();
1550 fprintf(stderr
,"\t%s\n", *it
);
1551 fprintf(stderr
,"Framework search paths:\n");
1552 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin();
1553 it
!= fFrameworkSearchPaths
.end();
1555 fprintf(stderr
,"\t%s\n", *it
);
1559 // this is run before the command line is parsed
1560 void Options::parsePreCommandLineEnvironmentSettings()
1562 if ((getenv("LD_TRACE_ARCHIVES") != NULL
)
1563 || (getenv("RC_TRACE_ARCHIVES") != NULL
))
1564 fReaderOptions
.fTraceArchives
= true;
1566 if ((getenv("LD_TRACE_DYLIBS") != NULL
)
1567 || (getenv("RC_TRACE_DYLIBS") != NULL
)) {
1568 fReaderOptions
.fTraceDylibs
= true;
1569 fReaderOptions
.fTraceIndirectDylibs
= true;
1572 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL
) {
1573 fTraceDylibSearching
= true;
1576 if (getenv("LD_PRINT_OPTIONS") != NULL
)
1577 fPrintOptions
= true;
1579 if (fReaderOptions
.fTraceDylibs
|| fReaderOptions
.fTraceArchives
)
1580 fReaderOptions
.fTraceOutputFile
= getenv("LD_TRACE_FILE");
1583 // this is run after the command line is parsed
1584 void Options::parsePostCommandLineEnvironmentSettings()
1586 // when building a dynamic main executable, default any use of @executable_path to output path
1587 if ( fExecutablePath
== NULL
&& (fOutputKind
== kDynamicExecutable
) ) {
1588 fExecutablePath
= fOutputFile
;
1593 void Options::reconfigureDefaults()
1595 // sync reader options
1596 switch ( fOutputKind
) {
1597 case Options::kObjectFile
:
1598 fReaderOptions
.fForFinalLinkedImage
= false;
1600 case Options::kDynamicExecutable
:
1601 case Options::kStaticExecutable
:
1602 case Options::kDynamicLibrary
:
1603 case Options::kDynamicBundle
:
1604 case Options::kDyld
:
1605 fReaderOptions
.fForFinalLinkedImage
= true;
1609 // set default min OS version
1610 if ( fVersionMin
== kMinUnset
) {
1611 switch ( fArchitecture
) {
1612 case CPU_TYPE_POWERPC
:
1613 fVersionMin
= k10_2
;
1616 case CPU_TYPE_POWERPC64
:
1617 case CPU_TYPE_X86_64
:
1618 fVersionMin
= k10_4
;
1620 // architecture not specified
1621 fVersionMin
= k10_4
;
1626 // adjust min based on architecture
1627 switch ( fArchitecture
) {
1629 if ( fVersionMin
< k10_4
) {
1630 //fprintf(stderr, "ld64 warning: -macosx_version_min should be 10.4 or later for i386\n");
1631 fVersionMin
= k10_4
;
1634 case CPU_TYPE_POWERPC64
:
1635 if ( fVersionMin
< k10_4
) {
1636 //fprintf(stderr, "ld64 warning: -macosx_version_min should be 10.4 or later for ppc64\n");
1637 fVersionMin
= k10_4
;
1640 case CPU_TYPE_X86_64
:
1641 if ( fVersionMin
< k10_4
) {
1642 //fprintf(stderr, "ld64 warning: -macosx_version_min should be 10.4 or later for x86_64\n");
1643 fVersionMin
= k10_4
;
1650 void Options::checkIllegalOptionCombinations()
1652 // check -undefined setting
1653 switch ( fUndefinedTreatment
) {
1654 case kUndefinedError
:
1655 case kUndefinedDynamicLookup
:
1658 case kUndefinedWarning
:
1659 case kUndefinedSuppress
:
1660 // requires flat namespace
1661 if ( fNameSpace
== kTwoLevelNameSpace
)
1662 throw "can't use -undefined warning or suppress with -twolevel_namespace";
1666 // unify -sub_umbrella with dylibs
1667 for (std::vector
<const char*>::iterator it
= fSubUmbellas
.begin(); it
!= fSubUmbellas
.end(); it
++) {
1668 const char* subUmbrella
= *it
;
1670 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
1671 Options::FileInfo
& info
= *fit
;
1672 const char* lastSlash
= strrchr(info
.path
, '/');
1673 if ( lastSlash
== NULL
)
1674 lastSlash
= info
.path
- 1;
1675 if ( strcmp(&lastSlash
[1], subUmbrella
) == 0 ) {
1676 info
.options
.fReExport
= true;
1682 fprintf(stderr
, "ld64 warning: -sub_umbrella %s does not match a supplied dylib\n", subUmbrella
);
1685 // unify -sub_library with dylibs
1686 for (std::vector
<const char*>::iterator it
= fSubLibraries
.begin(); it
!= fSubLibraries
.end(); it
++) {
1687 const char* subLibrary
= *it
;
1689 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
1690 Options::FileInfo
& info
= *fit
;
1691 const char* lastSlash
= strrchr(info
.path
, '/');
1692 if ( lastSlash
== NULL
)
1693 lastSlash
= info
.path
- 1;
1694 const char* dot
= strchr(&lastSlash
[1], '.');
1696 dot
= &lastSlash
[strlen(lastSlash
)];
1697 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
1698 info
.options
.fReExport
= true;
1704 fprintf(stderr
, "ld64 warning: -sub_library %s does not match a supplied dylib\n", subLibrary
);
1707 // sync reader options
1708 if ( fNameSpace
!= kTwoLevelNameSpace
)
1709 fReaderOptions
.fFlatNamespace
= true;
1711 // check -stack_addr
1712 if ( fStackAddr
!= 0 ) {
1713 switch (fArchitecture
) {
1715 case CPU_TYPE_POWERPC
:
1716 if ( fStackAddr
> 0xFFFFFFFF )
1717 throw "-stack_addr must be < 4G for 32-bit processes";
1719 case CPU_TYPE_POWERPC64
:
1720 case CPU_TYPE_X86_64
:
1723 if ( (fStackAddr
& -4096) != fStackAddr
)
1724 throw "-stack_addr must be multiples of 4K";
1725 if ( fStackSize
== 0 )
1726 throw "-stack_addr must be used with -stack_size";
1729 // check -stack_size
1730 if ( fStackSize
!= 0 ) {
1731 switch (fArchitecture
) {
1733 case CPU_TYPE_POWERPC
:
1734 if ( fStackSize
> 0xFFFFFFFF )
1735 throw "-stack_size must be < 4G for 32-bit processes";
1736 if ( fStackAddr
== 0 ) {
1737 fStackAddr
= 0xC0000000;
1739 if ( (fStackAddr
> 0xB0000000) && ((fStackAddr
-fStackSize
) < 0xB0000000) )
1740 fprintf(stderr
, "ld64 warning: custom stack placement overlaps and will disable shared region\n");
1742 case CPU_TYPE_POWERPC64
:
1743 case CPU_TYPE_X86_64
:
1744 if ( fStackAddr
== 0 ) {
1745 fStackAddr
= 0x0007FFFF00000000LL
;
1749 if ( (fStackSize
& -4096) != fStackSize
)
1750 throw "-stack_size must be multiples of 4K";
1751 switch ( fOutputKind
) {
1752 case Options::kDynamicExecutable
:
1753 case Options::kStaticExecutable
:
1754 // custom stack size only legal when building main executable
1756 case Options::kDynamicLibrary
:
1757 case Options::kDynamicBundle
:
1758 case Options::kObjectFile
:
1759 case Options::kDyld
:
1760 throw "-stack_size option can only be used when linking a main executable";
1764 // check that -allow_stack_execute is only used with main executables
1765 if ( fExecutableStack
) {
1766 switch ( fOutputKind
) {
1767 case Options::kDynamicExecutable
:
1768 case Options::kStaticExecutable
:
1769 // -allow_stack_execute size only legal when building main executable
1771 case Options::kDynamicLibrary
:
1772 case Options::kDynamicBundle
:
1773 case Options::kObjectFile
:
1774 case Options::kDyld
:
1775 throw "-allow_stack_execute option can only be used when linking a main executable";
1779 // check -client_name is only used when -bundle is specified
1780 if ( (fClientName
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
1781 throw "-client_name can only be used with -bundle";
1783 // check -init is only used when building a dylib
1784 if ( (fInitFunctionName
!= NULL
) && (fOutputKind
!= Options::kDynamicLibrary
) )
1785 throw "-init can only be used with -dynamiclib";
1787 // check -bundle_loader only used with -bundle
1788 if ( (fBundleLoader
!= NULL
) && (fOutputKind
!= Options::kDynamicBundle
) )
1789 throw "-bundle_loader can only be used with -bundle";
1791 // check -d can only be used with -r
1792 if ( fMakeTentativeDefinitionsReal
&& (fOutputKind
!= Options::kObjectFile
) )
1793 throw "-d can only be used with -r";
1795 // make sure all required exported symbols exist
1796 for (NameSet::iterator it
=fExportSymbols
.begin(); it
!= fExportSymbols
.end(); it
++) {
1797 const char* name
= *it
;
1798 // never export .eh symbols
1799 if ( strcmp(&name
[strlen(name
)-3], ".eh") != 0 )
1800 fInitialUndefines
.push_back(name
);
1803 // make sure that -init symbol exist
1804 if ( fInitFunctionName
!= NULL
)
1805 fInitialUndefines
.push_back(fInitFunctionName
);
1807 if ( fZeroPageSize
== ULLONG_MAX
) {
1808 // zero page size not specified on command line, set default
1809 switch (fArchitecture
) {
1811 case CPU_TYPE_POWERPC
:
1812 // first 4KB for 32-bit architectures
1813 fZeroPageSize
= 0x1000;
1815 case CPU_TYPE_POWERPC64
:
1816 // first 4GB for ppc64 on 10.5
1817 if ( fVersionMin
>= k10_5
)
1818 fZeroPageSize
= 0x100000000ULL
;
1820 fZeroPageSize
= 0x1000; // 10.4 dyld may not be able to handle >4GB zero page
1822 case CPU_TYPE_X86_64
:
1823 // first 4GB for x86_64 on all OS's
1824 fZeroPageSize
= 0x100000000ULL
;
1827 // if -arch not used, default to 4K zero-page
1828 fZeroPageSize
= 0x1000;
1832 switch ( fOutputKind
) {
1833 case Options::kDynamicExecutable
:
1834 case Options::kStaticExecutable
:
1835 // -pagezero_size size only legal when building main executable
1837 case Options::kDynamicLibrary
:
1838 case Options::kDynamicBundle
:
1839 case Options::kObjectFile
:
1840 case Options::kDyld
:
1841 throw "-pagezero_size option can only be used when linking a main executable";
1845 // -dead_strip and -r are incompatible
1846 if ( (fDeadStrip
!= kDeadStripOff
) && (fOutputKind
== Options::kObjectFile
) )
1847 throw "-r and -dead_strip cannot be used together\n";