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 __attribute__((noreturn
))
35 void throwf(const char* format
, ...)
39 va_start(list
, format
);
40 vasprintf(&p
, format
, list
);
48 Options::Options(int argc
, const char* argv
[])
49 : fOutputFile("a.out"), fArchitecture(CPU_TYPE_POWERPC64
), fOutputKind(kDynamicExecutable
), fBindAtLoad(false),
50 fStripLocalSymbols(false), fKeepPrivateExterns(false),
51 fInterposable(false), fIgnoreOtherArchFiles(false), fForceSubtypeAll(false), fNameSpace(kTwoLevelNameSpace
),
52 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL
), fEntryName("start"), fBaseAddress(0),
53 fExportMode(kExportDefault
), fLibrarySearchMode(kSearchAllDirsForDylibsThenAllDirsForArchives
),
54 fUndefinedTreatment(kUndefinedError
), fMessagesPrefixedWithArchitecture(false), fPICTreatment(kPICError
),
55 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchError
),
56 fUmbrellaName(NULL
), fInitFunctionName(NULL
), fZeroPageSize(0x1000), fStackSize(0), fStackAddr(0), fMinimumHeaderPad(0),
57 fCommonsMode(kCommonsIgnoreDylibs
), fWarnCommons(false), fVerbose(false)
59 this->parsePreCommandLineEnvironmentSettings();
60 this->parse(argc
, argv
);
61 this->parsePostCommandLineEnvironmentSettings();
62 this->checkIllegalOptionCombinations();
70 ObjectFile::ReaderOptions
& Options::readerOptions()
72 return fReaderOptions
;
75 cpu_type_t
Options::architecture()
81 const char* Options::getOutputFilePath()
87 std::vector
<Options::FileInfo
>& Options::getInputFiles()
92 Options::OutputKind
Options::outputKind()
97 bool Options::stripLocalSymbols()
99 return fStripLocalSymbols
;
102 bool Options::stripDebugInfo()
104 return fReaderOptions
.fStripDebugInfo
;
107 bool Options::bindAtLoad()
112 bool Options::fullyLoadArchives()
114 return fReaderOptions
.fFullyLoadArchives
;
117 Options::NameSpace
Options::nameSpace()
122 const char* Options::installPath()
124 if ( fDylibInstallName
!= NULL
)
125 return fDylibInstallName
;
130 uint32_t Options::currentVersion()
132 return fDylibCurrentVersion
;
135 uint32_t Options::compatibilityVersion()
137 return fDylibCompatVersion
;
140 const char* Options::entryName()
145 uint64_t Options::baseAddress()
150 bool Options::keepPrivateExterns()
152 return fKeepPrivateExterns
;
155 bool Options::interposable()
157 return fInterposable
;
160 bool Options::ignoreOtherArchInputFiles()
162 return fIgnoreOtherArchFiles
;
165 bool Options::forceCpuSubtypeAll()
167 return fForceSubtypeAll
;
170 bool Options::traceDylibs()
172 return fReaderOptions
.fTraceDylibs
;
175 bool Options::traceArchives()
177 return fReaderOptions
.fTraceArchives
;
180 Options::UndefinedTreatment
Options::undefinedTreatment()
182 return fUndefinedTreatment
;
185 Options::WeakReferenceMismatchTreatment
Options::weakReferenceMismatchTreatment()
187 return fWeakReferenceMismatchTreatment
;
190 const char* Options::umbrellaName()
192 return fUmbrellaName
;
195 uint64_t Options::zeroPageSize()
197 return fZeroPageSize
;
200 bool Options::hasCustomStack()
202 return (fStackSize
!= 0);
205 uint64_t Options::customStackSize()
210 uint64_t Options::customStackAddr()
215 std::vector
<const char*>& Options::initialUndefines()
217 return fInitialUndefines
;
220 const char* Options::initFunctionName()
222 return fInitFunctionName
;
225 bool Options::hasExportRestrictList()
227 return (fExportMode
!= kExportDefault
);
230 uint32_t Options::minimumHeaderPad()
232 return fMinimumHeaderPad
;
235 std::vector
<Options::ExtraSection
>& Options::extraSections()
237 return fExtraSections
;
240 std::vector
<Options::SectionAlignment
>& Options::sectionAlignments()
242 return fSectionAlignments
;
246 Options::CommonsMode
Options::commonsMode()
251 bool Options::warnCommons()
256 bool Options::shouldExport(const char* symbolName
)
258 switch (fExportMode
) {
260 return ( fExportSymbols
.find(symbolName
) != fExportSymbols
.end() );
261 case kDontExportSome
:
262 return ( fDontExportSymbols
.find(symbolName
) == fDontExportSymbols
.end() );
266 throw "internal error";
270 void Options::parseArch(const char* architecture
)
272 if ( architecture
== NULL
)
273 throw "-arch must be followed by an architecture string";
274 if ( strcmp(architecture
, "ppc") == 0 )
275 fArchitecture
= CPU_TYPE_POWERPC
;
276 else if ( strcmp(architecture
, "ppc64") == 0 )
277 fArchitecture
= CPU_TYPE_POWERPC64
;
278 else if ( strcmp(architecture
, "i386") == 0 )
279 fArchitecture
= CPU_TYPE_I386
;
281 throw "-arch followed by unknown architecture name";
284 bool Options::checkForFile(const char* format
, const char* dir
, const char* rootName
, FileInfo
& result
)
286 struct stat statBuffer
;
287 char possiblePath
[strlen(dir
)+strlen(rootName
)+20];
288 sprintf(possiblePath
, format
, dir
, rootName
);
289 if ( stat(possiblePath
, &statBuffer
) == 0 ) {
290 result
.path
= strdup(possiblePath
);
291 result
.fileLen
= statBuffer
.st_size
;
298 Options::FileInfo
Options::findLibrary(const char* rootName
)
301 const int rootNameLen
= strlen(rootName
);
302 // if rootName ends in .o there is no .a vs .dylib choice
303 if ( (rootNameLen
> 3) && (strcmp(&rootName
[rootNameLen
-2], ".o") == 0) ) {
304 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin(); it
!= fLibrarySearchPaths
.end(); it
++) {
305 const char* dir
= *it
;
306 if ( checkForFile("%s/%s", dir
, rootName
, result
) )
311 bool lookForDylibs
= ( fOutputKind
!= Options::kDyld
);
312 switch ( fLibrarySearchMode
) {
313 case kSearchAllDirsForDylibsThenAllDirsForArchives
:
314 // first look in all directories for just for dylibs
315 if ( lookForDylibs
) {
316 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin(); it
!= fLibrarySearchPaths
.end(); it
++) {
317 const char* dir
= *it
;
318 if ( checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
322 // next look in all directories for just for archives
323 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin(); it
!= fLibrarySearchPaths
.end(); it
++) {
324 const char* dir
= *it
;
325 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
330 case kSearchDylibAndArchiveInEachDir
:
331 // look in each directory for just for a dylib then for an archive
332 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin(); it
!= fLibrarySearchPaths
.end(); it
++) {
333 const char* dir
= *it
;
334 if ( lookForDylibs
&& checkForFile("%s/lib%s.dylib", dir
, rootName
, result
) )
336 if ( checkForFile("%s/lib%s.a", dir
, rootName
, result
) )
342 throwf("library not found for -l%s", rootName
);
346 Options::FileInfo
Options::findFramework(const char* rootName
)
348 struct stat statBuffer
;
349 const int rootNameLen
= strlen(rootName
);
350 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin(); it
!= fFrameworkSearchPaths
.end(); it
++) {
351 const char* dir
= *it
;
352 char possiblePath
[strlen(dir
)+2*rootNameLen
+20];
353 strcpy(possiblePath
, dir
);
354 strcat(possiblePath
, "/");
355 strcat(possiblePath
, rootName
);
356 strcat(possiblePath
, ".framework/");
357 strcat(possiblePath
, rootName
);
358 if ( stat(possiblePath
, &statBuffer
) == 0 ) {
360 result
.path
= strdup(possiblePath
);
361 result
.fileLen
= statBuffer
.st_size
;
365 throwf("framework not found %s", rootName
);
368 Options::FileInfo
Options::findFile(const char* path
)
371 struct stat statBuffer
;
373 // if absolute path and not a .o file, the use SDK prefix
374 if ( (path
[0] == '/') && (strcmp(&path
[strlen(path
)-2], ".o") != 0) ) {
375 const int pathLen
= strlen(path
);
376 for (std::vector
<const char*>::iterator it
= fSDKPaths
.begin(); it
!= fSDKPaths
.end(); it
++) {
377 const char* sdkPathDir
= *it
;
378 const int sdkPathDirLen
= strlen(sdkPathDir
);
379 char possiblePath
[sdkPathDirLen
+pathLen
+4];
380 strcpy(possiblePath
, sdkPathDir
);
381 if ( possiblePath
[sdkPathDirLen
-1] == '/' )
382 possiblePath
[sdkPathDirLen
-1] = '\0';
383 strcat(possiblePath
, path
);
384 if ( stat(possiblePath
, &statBuffer
) == 0 ) {
385 result
.path
= strdup(possiblePath
);
386 result
.fileLen
= statBuffer
.st_size
;
392 if ( stat(path
, &statBuffer
) == 0 ) {
393 result
.path
= strdup(path
);
394 result
.fileLen
= statBuffer
.st_size
;
398 throwf("file not found: %s", path
);
402 void Options::loadFileList(const char* fileOfPaths
)
404 FILE* file
= fopen(fileOfPaths
, "r");
406 throwf("-filelist file not found: %s\n", fileOfPaths
);
409 while ( fgets(path
, 1024, file
) != NULL
) {
411 char* eol
= strchr(path
, '\n');
415 fInputFiles
.push_back(findFile(path
));
421 void Options::loadExportFile(const char* fileOfExports
, const char* option
, NameSet
& set
)
423 // read in whole file
424 int fd
= ::open(fileOfExports
, O_RDONLY
, 0);
426 throwf("can't open %s file: %s", option
, fileOfExports
);
427 struct stat stat_buf
;
428 ::fstat(fd
, &stat_buf
);
429 char* p
= (char*)malloc(stat_buf
.st_size
);
431 throwf("can't process %s file: %s", option
, fileOfExports
);
433 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
434 throwf("can't read %s file: %s", option
, fileOfExports
);
438 // parse into symbols and add to hash_set
439 char * const end
= &p
[stat_buf
.st_size
];
440 enum { lineStart
, inSymbol
, inComment
} state
= lineStart
;
441 char* symbolStart
= NULL
;
442 for (char* s
= p
; s
< end
; ++s
) {
448 else if ( !isspace(*s
) ) {
456 // removing any trailing spaces
458 while ( isspace(*last
) ) {
462 set
.insert(symbolStart
);
473 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
476 void Options::setUndefinedTreatment(const char* treatment
)
478 if ( treatment
== NULL
)
479 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
481 if ( strcmp(treatment
, "warning") == 0 )
482 fUndefinedTreatment
= kUndefinedWarning
;
483 else if ( strcmp(treatment
, "error") == 0 )
484 fUndefinedTreatment
= kUndefinedError
;
485 else if ( strcmp(treatment
, "suppress") == 0 )
486 fUndefinedTreatment
= kUndefinedSuppress
;
487 else if ( strcmp(treatment
, "dynamic_lookup") == 0 )
488 fUndefinedTreatment
= kUndefinedDynamicLookup
;
490 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
493 void Options::setReadOnlyRelocTreatment(const char* treatment
)
495 if ( treatment
== NULL
)
496 throw "-read_only_relocs missing [ warning | error | suppress ]";
498 if ( strcmp(treatment
, "warning") == 0 )
499 throw "-read_only_relocs warning not supported";
500 else if ( strcmp(treatment
, "suppress") == 0 )
501 throw "-read_only_relocs suppress not supported";
502 else if ( strcmp(treatment
, "error") != 0 )
503 throw "invalid option to -read_only_relocs [ warning | error | suppress | dynamic_lookup ]";
506 void Options::setPICTreatment(const char* treatment
)
508 if ( treatment
== NULL
)
509 throw "-sect_diff_relocs missing [ warning | error | suppress ]";
511 if ( strcmp(treatment
, "warning") == 0 )
512 fPICTreatment
= kPICWarning
;
513 else if ( strcmp(treatment
, "error") == 0 )
514 fPICTreatment
= kPICError
;
515 else if ( strcmp(treatment
, "suppress") == 0 )
516 fPICTreatment
= kPICSuppress
;
518 throw "invalid option to -sect_diff_relocs [ warning | error | suppress ]";
521 void Options::setWeakReferenceMismatchTreatment(const char* treatment
)
523 if ( treatment
== NULL
)
524 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
526 if ( strcmp(treatment
, "error") == 0 )
527 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchError
;
528 else if ( strcmp(treatment
, "weak") == 0 )
529 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchWeak
;
530 else if ( strcmp(treatment
, "non-weak") == 0 )
531 fWeakReferenceMismatchTreatment
= kWeakReferenceMismatchNonWeak
;
533 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
536 Options::CommonsMode
Options::parseCommonsTreatment(const char* mode
)
539 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
541 if ( strcmp(mode
, "ignore_dylibs") == 0 )
542 return kCommonsIgnoreDylibs
;
543 else if ( strcmp(mode
, "use_dylibs") == 0 )
544 return kCommonsOverriddenByDylibs
;
545 else if ( strcmp(mode
, "error") == 0 )
546 return kCommonsConflictsDylibsError
;
548 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
552 void Options::setDylibInstallNameOverride(const char* paths
)
558 void Options::setExecutablePath(const char* path
)
567 uint64_t Options::parseAddress(const char* addr
)
570 uint64_t result
= strtoull(addr
, &endptr
, 16);
577 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
580 uint32_t Options::parseVersionNumber(const char* versionString
)
586 x
= strtoul(versionString
, &end
, 10);
588 y
= strtoul(&end
[1], &end
, 10);
590 z
= strtoul(&end
[1], &end
, 10);
593 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
594 throwf("malformed version number: %s", versionString
);
596 return (x
<< 16) | ( y
<< 8 ) | z
;
599 void Options::parseSectionOrderFile(const char* segment
, const char* section
, const char* path
)
601 fprintf(stderr
, "ld64: warning -sectorder not yet supported for 64-bit code\n");
604 void Options::addSection(const char* segment
, const char* section
, const char* path
)
606 if ( strlen(segment
) > 16 )
607 throw "-seccreate segment name max 16 chars";
608 if ( strlen(section
) > 16 )
609 throw "-seccreate section name max 16 chars";
611 // read in whole file
612 int fd
= ::open(path
, O_RDONLY
, 0);
614 throwf("can't open -sectcreate file: %s", path
);
615 struct stat stat_buf
;
616 ::fstat(fd
, &stat_buf
);
617 char* p
= (char*)malloc(stat_buf
.st_size
);
619 throwf("can't process -sectcreate file: %s", path
);
620 if ( read(fd
, p
, stat_buf
.st_size
) != stat_buf
.st_size
)
621 throwf("can't read -sectcreate file: %s", path
);
624 // record section to create
625 ExtraSection info
= { segment
, section
, path
, (uint8_t*)p
, stat_buf
.st_size
};
626 fExtraSections
.push_back(info
);
629 void Options::addSectionAlignment(const char* segment
, const char* section
, const char* alignmentStr
)
631 if ( strlen(segment
) > 16 )
632 throw "-sectalign segment name max 16 chars";
633 if ( strlen(section
) > 16 )
634 throw "-sectalign section name max 16 chars";
637 unsigned long value
= strtoul(alignmentStr
, &endptr
, 16);
638 if ( *endptr
!= '\0')
639 throw "argument for -sectalign is not a hexadecimal number";
640 if ( value
> 0x8000 )
641 throw "argument for -sectalign must be less than or equal to 0x8000";
642 uint8_t alignment
= 0;
643 for(unsigned long x
=value
; x
!= 1; x
>>= 1)
645 if ( (unsigned long)(1 << alignment
) != value
)
646 throw "argument for -sectalign is not a power of two";
648 SectionAlignment info
= { segment
, section
, alignment
};
649 fSectionAlignments
.push_back(info
);
653 void Options::parse(int argc
, const char* argv
[])
655 // pass one builds search list from -L and -F options
656 this->buildSearchPaths(argc
, argv
);
658 // pass two parse all other options
659 for(int i
=1; i
< argc
; ++i
) {
660 const char* arg
= argv
[i
];
662 if ( arg
[0] == '-' ) {
663 if ( (arg
[1] == 'L') || (arg
[1] == 'F') ) {
664 // previously handled by buildSearchPaths()
666 else if ( strcmp(arg
, "-arch") == 0 ) {
667 parseArch(argv
[++i
]);
669 else if ( strcmp(arg
, "-dynamic") == 0 ) {
672 else if ( strcmp(arg
, "-static") == 0 ) {
673 fOutputKind
= kStaticExecutable
;
675 else if ( strcmp(arg
, "-dylib") == 0 ) {
676 fOutputKind
= kDynamicLibrary
;
678 else if ( strcmp(arg
, "-bundle") == 0 ) {
679 fOutputKind
= kDynamicBundle
;
681 else if ( strcmp(arg
, "-dylinker") == 0 ) {
684 else if ( strcmp(arg
, "-execute") == 0 ) {
685 if ( fOutputKind
!= kStaticExecutable
)
686 fOutputKind
= kDynamicExecutable
;
688 else if ( strcmp(arg
, "-r") == 0 ) {
689 fOutputKind
= kObjectFile
;
691 else if ( strcmp(arg
, "-o") == 0 ) {
692 fOutputFile
= argv
[++i
];
694 else if ( arg
[1] == 'l' ) {
695 fInputFiles
.push_back(findLibrary(&arg
[2]));
697 else if ( strcmp(arg
, "-weak-l") == 0 ) {
698 FileInfo info
= findLibrary(&arg
[2]);
699 info
.options
.fWeakImport
= true;
700 fInputFiles
.push_back(info
);
702 else if ( strcmp(arg
, "-bind_at_load") == 0 ) {
705 else if ( strcmp(arg
, "-twolevel_namespace") == 0 ) {
706 fNameSpace
= kTwoLevelNameSpace
;
708 else if ( strcmp(arg
, "-flat_namespace") == 0 ) {
709 fNameSpace
= kFlatNameSpace
;
711 else if ( strcmp(arg
, "-force_flat_namespace") == 0 ) {
712 fNameSpace
= kForceFlatNameSpace
;
714 else if ( strcmp(arg
, "-all_load") == 0 ) {
715 fReaderOptions
.fFullyLoadArchives
= true;
717 else if ( strcmp(arg
, "-ObjC") == 0 ) {
718 fReaderOptions
.fLoadObjcClassesInArchives
= true;
720 else if ( strcmp(arg
, "-dylib_compatibility_version") == 0 ) {
721 fDylibCompatVersion
= parseVersionNumber(argv
[++i
]);
723 else if ( strcmp(arg
, "-dylib_current_version") == 0 ) {
724 fDylibCurrentVersion
= parseVersionNumber(argv
[++i
]);
726 else if ( strcmp(arg
, "-sectorder") == 0 ) {
727 parseSectionOrderFile(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
730 else if ( (strcmp(arg
, "-sectcreate") == 0) || (strcmp(arg
, "-segcreate") == 0) ) {
731 addSection(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
734 else if ( (strcmp(arg
, "-dylib_install_name") == 0) || (strcmp(arg
, "-dylinker_install_name") == 0) ) {
735 fDylibInstallName
= argv
[++i
];
737 else if ( strcmp(arg
, "-seg1addr") == 0 ) {
738 fBaseAddress
= parseAddress(argv
[++i
]);
740 else if ( strcmp(arg
, "-e") == 0 ) {
741 fEntryName
= argv
[++i
];
743 else if ( strcmp(arg
, "-filelist") == 0 ) {
744 loadFileList(argv
[++i
]);
746 else if ( strcmp(arg
, "-keep_private_externs") == 0 ) {
747 fKeepPrivateExterns
= true;
749 else if ( strcmp(arg
, "-final_output") == 0 ) {
753 else if ( (strcmp(arg
, "-interposable") == 0) || (strcmp(arg
, "-multi_module") == 0)) {
754 fInterposable
= true;
756 else if ( strcmp(arg
, "-single_module") == 0 ) {
757 fInterposable
= false;
759 else if ( strcmp(arg
, "-exported_symbols_list") == 0 ) {
760 if ( fExportMode
== kDontExportSome
)
761 throw "can't use -exported_symbols_list and -unexported_symbols_list";
762 fExportMode
= kExportSome
;
763 loadExportFile(argv
[++i
], "-exported_symbols_list", fExportSymbols
);
765 else if ( strcmp(arg
, "-unexported_symbols_list") == 0 ) {
766 if ( fExportMode
== kExportSome
)
767 throw "can't use -exported_symbols_list and -unexported_symbols_list";
768 fExportMode
= kDontExportSome
;
769 loadExportFile(argv
[++i
], "-unexported_symbols_list", fDontExportSymbols
);
771 else if ( strcmp(arg
, "-no_arch_warnings") == 0 ) {
772 fIgnoreOtherArchFiles
= true;
774 else if ( strcmp(arg
, "-force_cpusubtype_ALL") == 0 ) {
775 fForceSubtypeAll
= true;
777 else if ( strcmp(arg
, "-weak_library") == 0 ) {
778 FileInfo info
= findFile(argv
[++i
]);
779 info
.options
.fWeakImport
= true;
780 fInputFiles
.push_back(info
);
782 else if ( strcmp(arg
, "-framework") == 0 ) {
783 fInputFiles
.push_back(findFramework(argv
[++i
]));
785 else if ( strcmp(arg
, "-weak_framework") == 0 ) {
786 FileInfo info
= findFramework(argv
[++i
]);
787 info
.options
.fWeakImport
= true;
788 fInputFiles
.push_back(info
);
790 else if ( strcmp(arg
, "-search_paths_first") == 0 ) {
791 fLibrarySearchMode
= kSearchDylibAndArchiveInEachDir
;
793 else if ( strcmp(arg
, "-undefined") == 0 ) {
794 setUndefinedTreatment(argv
[++i
]);
796 else if ( strcmp(arg
, "-arch_multiple") == 0 ) {
797 fMessagesPrefixedWithArchitecture
= true;
799 else if ( strcmp(arg
, "-read_only_relocs") == 0 ) {
800 setReadOnlyRelocTreatment(argv
[++i
]);
802 else if ( strcmp(arg
, "-sect_diff_relocs") == 0 ) {
803 setPICTreatment(argv
[++i
]);
805 else if ( strcmp(arg
, "-weak_reference_mismatches") == 0 ) {
806 setWeakReferenceMismatchTreatment(argv
[++i
]);
808 else if ( strcmp(arg
, "-prebind") == 0 ) {
811 else if ( strcmp(arg
, "-noprebind") == 0 ) {
814 else if ( strcmp(arg
, "-prebind_allow_overlap") == 0 ) {
817 else if ( strcmp(arg
, "-prebind_all_twolevel_modules") == 0 ) {
820 else if ( strcmp(arg
, "-noprebind_all_twolevel_modules") == 0 ) {
823 else if ( strcmp(arg
, "-nofixprebinding") == 0 ) {
826 else if ( strcmp(arg
, "-dylib_file") == 0 ) {
827 setDylibInstallNameOverride(argv
[++i
]);
829 else if ( strcmp(arg
, "-executable_path") == 0 ) {
830 setExecutablePath(argv
[++i
]);
832 else if ( strcmp(arg
, "-segalign") == 0 ) {
836 else if ( strcmp(arg
, "-segaddr") == 0 ) {
840 else if ( strcmp(arg
, "-segs_read_only_addr") == 0 ) {
844 else if ( strcmp(arg
, "-segs_read_write_addr") == 0 ) {
848 else if ( strcmp(arg
, "-seg_addr_table") == 0 ) {
852 else if ( strcmp(arg
, "-seg_addr_table_filename") == 0 ) {
856 else if ( strcmp(arg
, "-segprot") == 0 ) {
860 else if ( strcmp(arg
, "-pagezero_size") == 0 ) {
861 fZeroPageSize
= parseAddress(argv
[++i
]);
862 fZeroPageSize
&= (-4096); // page align
864 else if ( strcmp(arg
, "-stack_addr") == 0 ) {
865 fStackAddr
= parseAddress(argv
[++i
]);
867 else if ( strcmp(arg
, "-stack_size") == 0 ) {
868 fStackSize
= parseAddress(argv
[++i
]);
870 else if ( strcmp(arg
, "-sectalign") == 0 ) {
871 addSectionAlignment(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
874 else if ( strcmp(arg
, "-sectorder_detail") == 0 ) {
877 else if ( strcmp(arg
, "-sectobjectsymbols") == 0 ) {
881 else if ( strcmp(arg
, "-bundle_loader") == 0 ) {
885 else if ( strcmp(arg
, "-private_bundle") == 0 ) {
888 else if ( strcmp(arg
, "-twolevel_namespace_hints") == 0 ) {
891 else if ( strcmp(arg
, "-macosx_version_min") == 0 ) {
892 // This flag isn't needed yet, so just ignore it.
895 else if ( strcmp(arg
, "-multiply_defined") == 0 ) {
899 else if ( strcmp(arg
, "-multiply_defined_unused") == 0 ) {
903 else if ( strcmp(arg
, "-nomultidefs") == 0 ) {
906 else if ( arg
[1] == 'y' ) {
909 else if ( strcmp(arg
, "-Y") == 0 ) {
913 else if ( strcmp(arg
, "-m") == 0 ) {
916 else if ( strcmp(arg
, "-whyload") == 0 ) {
919 else if ( strcmp(arg
, "-u") == 0 ) {
920 const char* name
= argv
[++i
];
922 throw "-u missing argument";
923 fInitialUndefines
.push_back(name
);
925 else if ( strcmp(arg
, "-i") == 0 ) {
928 else if ( strcmp(arg
, "-U") == 0 ) {
932 else if ( strcmp(arg
, "-s") == 0 ) {
935 else if ( strcmp(arg
, "-x") == 0 ) {
938 else if ( strcmp(arg
, "-S") == 0 ) {
941 else if ( strcmp(arg
, "-X") == 0 ) {
944 else if ( strcmp(arg
, "-Si") == 0 ) {
947 else if ( strcmp(arg
, "-b") == 0 ) {
950 else if ( strcmp(arg
, "-Sn") == 0 ) {
953 else if ( strcmp(arg
, "-dead_strip") == 0 ) {
955 fprintf(stderr
, "ld64: warning -dead_strip not yet supported for 64-bit code\n");
957 else if ( strcmp(arg
, "-w") == 0 ) {
960 else if ( strcmp(arg
, "-arch_errors_fatal") == 0 ) {
963 else if ( strcmp(arg
, "-M") == 0 ) {
966 else if ( strcmp(arg
, "-whatsloaded") == 0 ) {
969 else if ( strcmp(arg
, "-headerpad") == 0 ) {
970 const char* size
= argv
[++i
];
972 throw "-headerpad missing argument";
973 fMinimumHeaderPad
= parseAddress(size
);
975 else if ( strcmp(arg
, "-headerpad_max_install_names") == 0 ) {
978 else if ( strcmp(arg
, "-t") == 0 ) {
981 else if ( strcmp(arg
, "-A") == 0 ) {
985 else if ( strcmp(arg
, "-umbrella") == 0 ) {
986 const char* name
= argv
[++i
];
988 throw "-umbrella missing argument";
989 fUmbrellaName
= name
;
991 else if ( strcmp(arg
, "-allowable_client") == 0 ) {
995 else if ( strcmp(arg
, "-client_name") == 0 ) {
999 else if ( strcmp(arg
, "-sub_umbrella") == 0 ) {
1000 const char* name
= argv
[++i
];
1002 throw "-sub_umbrella missing argument";
1003 fSubUmbellas
.push_back(name
);
1005 else if ( strcmp(arg
, "-sub_library") == 0 ) {
1006 const char* name
= argv
[++i
];
1008 throw "-sub_library missing argument";
1009 fSubLibraries
.push_back(name
);
1011 else if ( strcmp(arg
, "-init") == 0 ) {
1012 const char* name
= argv
[++i
];
1014 throw "-init missing argument";
1015 fInitFunctionName
= name
;
1017 else if ( strcmp(arg
, "-warn_commons") == 0 ) {
1018 fWarnCommons
= true;
1020 else if ( strcmp(arg
, "-commons") == 0 ) {
1021 fCommonsMode
= parseCommonsTreatment(argv
[++i
]);
1023 else if ( strcmp(arg
, "-v") == 0 ) {
1024 // previously handled by buildSearchPaths()
1026 else if ( strcmp(arg
, "-Z") == 0 ) {
1027 // previously handled by buildSearchPaths()
1029 else if ( strcmp(arg
, "-syslibroot") == 0 ) {
1031 // previously handled by buildSearchPaths()
1034 fprintf(stderr
, "unknown option: %s\n", arg
);
1038 fInputFiles
.push_back(findFile(arg
));
1046 // -syslibroot <path> is used for SDK support.
1047 // The rule is that all search paths (both explicit and default) are
1048 // checked to see if they exist in the SDK. If so, that path is
1049 // replaced with the sdk prefixed path. If not, that search path
1050 // is used as is. If multiple -syslibroot options are specified
1051 // their directory structures are logically overlayed and files
1052 // from sdks specified earlier on the command line used before later ones.
1054 void Options::buildSearchPaths(int argc
, const char* argv
[])
1056 bool addStandardLibraryDirectories
= true;
1057 std::vector
<const char*> libraryPaths
;
1058 std::vector
<const char*> frameworkPaths
;
1059 // scan through argv looking for -L, -F, -Z, and -syslibroot options
1060 for(int i
=0; i
< argc
; ++i
) {
1061 if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'L') )
1062 libraryPaths
.push_back(&argv
[i
][2]);
1063 else if ( (argv
[i
][0] == '-') && (argv
[i
][1] == 'F') )
1064 frameworkPaths
.push_back(&argv
[i
][2]);
1065 else if ( strcmp(argv
[i
], "-Z") == 0 )
1066 addStandardLibraryDirectories
= false;
1067 else if ( strcmp(argv
[i
], "-v") == 0 ) {
1069 extern const char ld64VersionString
[];
1070 fprintf(stderr
, "%s", ld64VersionString
);
1071 // if only -v specified, exit cleanly
1075 else if ( strcmp(argv
[i
], "-syslibroot") == 0 ) {
1076 const char* path
= argv
[++i
];
1078 throw "-syslibroot missing argument";
1079 fSDKPaths
.push_back(path
);
1082 if ( addStandardLibraryDirectories
) {
1083 libraryPaths
.push_back("/usr/lib");
1084 libraryPaths
.push_back("/usr/local/lib");
1086 frameworkPaths
.push_back("/Library/Frameworks/");
1087 frameworkPaths
.push_back("/Network/Library/Frameworks/");
1088 frameworkPaths
.push_back("/System/Library/Frameworks/");
1091 // now merge sdk and library paths to make real search paths
1092 for (std::vector
<const char*>::iterator it
= libraryPaths
.begin(); it
!= libraryPaths
.end(); it
++) {
1093 const char* libDir
= *it
;
1094 bool sdkOverride
= false;
1095 if ( libDir
[0] == '/' ) {
1096 char betterLibDir
[PATH_MAX
];
1097 if ( strstr(libDir
, "/..") != NULL
) {
1098 if ( realpath(libDir
, betterLibDir
) != NULL
)
1099 libDir
= betterLibDir
;
1101 const int libDirLen
= strlen(libDir
);
1102 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
1103 const char* sdkDir
= *sdkit
;
1104 const int sdkDirLen
= strlen(sdkDir
);
1105 char newPath
[libDirLen
+ sdkDirLen
+4];
1106 strcpy(newPath
, sdkDir
);
1107 if ( newPath
[sdkDirLen
-1] == '/' )
1108 newPath
[sdkDirLen
-1] = '\0';
1109 strcat(newPath
, libDir
);
1110 struct stat statBuffer
;
1111 if ( stat(newPath
, &statBuffer
) == 0 ) {
1112 fLibrarySearchPaths
.push_back(strdup(newPath
));
1118 fLibrarySearchPaths
.push_back(libDir
);
1121 // now merge sdk and framework paths to make real search paths
1122 for (std::vector
<const char*>::iterator it
= frameworkPaths
.begin(); it
!= frameworkPaths
.end(); it
++) {
1123 const char* frameworkDir
= *it
;
1124 bool sdkOverride
= false;
1125 if ( frameworkDir
[0] == '/' ) {
1126 char betterFrameworkDir
[PATH_MAX
];
1127 if ( strstr(frameworkDir
, "/..") != NULL
) {
1128 if ( realpath(frameworkDir
, betterFrameworkDir
) != NULL
)
1129 frameworkDir
= betterFrameworkDir
;
1131 const int frameworkDirLen
= strlen(frameworkDir
);
1132 for (std::vector
<const char*>::iterator sdkit
= fSDKPaths
.begin(); sdkit
!= fSDKPaths
.end(); sdkit
++) {
1133 const char* sdkDir
= *sdkit
;
1134 const int sdkDirLen
= strlen(sdkDir
);
1135 char newPath
[frameworkDirLen
+ sdkDirLen
+4];
1136 strcpy(newPath
, sdkDir
);
1137 if ( newPath
[sdkDirLen
-1] == '/' )
1138 newPath
[sdkDirLen
-1] = '\0';
1139 strcat(newPath
, frameworkDir
);
1140 struct stat statBuffer
;
1141 if ( stat(newPath
, &statBuffer
) == 0 ) {
1142 fFrameworkSearchPaths
.push_back(strdup(newPath
));
1148 fFrameworkSearchPaths
.push_back(frameworkDir
);
1152 fprintf(stderr
,"Library search paths:\n");
1153 for (std::vector
<const char*>::iterator it
= fLibrarySearchPaths
.begin(); it
!= fLibrarySearchPaths
.end(); it
++)
1154 fprintf(stderr
,"\t%s\n", *it
);
1155 fprintf(stderr
,"Framework search paths:\n");
1156 for (std::vector
<const char*>::iterator it
= fFrameworkSearchPaths
.begin(); it
!= fFrameworkSearchPaths
.end(); it
++)
1157 fprintf(stderr
,"\t%s\n", *it
);
1161 // this is run before the command line is parsed
1162 void Options::parsePreCommandLineEnvironmentSettings()
1164 if ( getenv("RC_TRACE_ARCHIVES") != NULL
)
1165 fReaderOptions
.fTraceArchives
= true;
1167 if ( getenv("RC_TRACE_DYLIBS") != NULL
) {
1168 fReaderOptions
.fTraceDylibs
= true;
1169 fReaderOptions
.fTraceIndirectDylibs
= true;
1173 // this is run after the command line is parsed
1174 void Options::parsePostCommandLineEnvironmentSettings()
1179 void Options::checkIllegalOptionCombinations()
1181 // check -undefined setting
1182 switch ( fUndefinedTreatment
) {
1183 case kUndefinedError
:
1184 case kUndefinedDynamicLookup
:
1187 case kUndefinedWarning
:
1188 case kUndefinedSuppress
:
1189 // requires flat namespace
1190 if ( fNameSpace
== kTwoLevelNameSpace
)
1191 throw "can't use -undefined warning or suppress with -twolevel_namespace";
1195 // unify -sub_umbrella with dylibs
1196 for (std::vector
<const char*>::iterator it
= fSubUmbellas
.begin(); it
!= fSubUmbellas
.end(); it
++) {
1197 const char* subUmbrella
= *it
;
1199 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
1200 Options::FileInfo
& info
= *fit
;
1201 const char* lastSlash
= strrchr(info
.path
, '/');
1202 if ( lastSlash
== NULL
)
1203 lastSlash
= info
.path
- 1;
1204 if ( strcmp(&lastSlash
[1], subUmbrella
) == 0 ) {
1205 info
.options
.fReExport
= true;
1211 fprintf(stderr
, "ld64 warning: -sub_umbrella %s does not match a supplied dylib\n", subUmbrella
);
1214 // unify -sub_library with dylibs
1215 for (std::vector
<const char*>::iterator it
= fSubLibraries
.begin(); it
!= fSubLibraries
.end(); it
++) {
1216 const char* subLibrary
= *it
;
1218 for (std::vector
<Options::FileInfo
>::iterator fit
= fInputFiles
.begin(); fit
!= fInputFiles
.end(); fit
++) {
1219 Options::FileInfo
& info
= *fit
;
1220 const char* lastSlash
= strrchr(info
.path
, '/');
1221 if ( lastSlash
== NULL
)
1222 lastSlash
= info
.path
- 1;
1223 const char* dot
= strchr(lastSlash
, '.');
1225 dot
= &lastSlash
[strlen(lastSlash
)];
1226 if ( strncmp(&lastSlash
[1], subLibrary
, dot
-lastSlash
-1) == 0 ) {
1227 info
.options
.fReExport
= true;
1233 fprintf(stderr
, "ld64 warning: -sub_library %s does not match a supplied dylib\n", subLibrary
);
1236 // sync reader options
1237 if ( fNameSpace
!= kTwoLevelNameSpace
)
1238 fReaderOptions
.fFlatNamespace
= true;
1240 // check -stack_addr
1241 if ( fStackAddr
!= 0 ) {
1242 switch (fArchitecture
) {
1244 case CPU_TYPE_POWERPC
:
1245 if ( fStackAddr
> 0xFFFFFFFF )
1246 throw "-stack_addr must be < 4G for 32-bit processes";
1248 case CPU_TYPE_POWERPC64
:
1251 if ( (fStackAddr
& -4096) != fStackAddr
)
1252 throw "-stack_addr must be multiples of 4K";
1253 if ( fStackSize
== 0 )
1254 throw "-stack_addr must be used with -stack_size";
1257 // check -stack_size
1258 if ( fStackSize
!= 0 ) {
1259 switch (fArchitecture
) {
1261 case CPU_TYPE_POWERPC
:
1262 if ( fStackSize
> 0xFFFFFFFF )
1263 throw "-stack_size must be < 4G for 32-bit processes";
1264 if ( fStackAddr
== 0 ) {
1265 fprintf(stderr
, "ld64 warning: -stack_addr not specified, using the default 0xC0000000\n");
1266 fStackAddr
= 0xC0000000;
1269 case CPU_TYPE_POWERPC64
:
1270 if ( fStackAddr
== 0 ) {
1271 fprintf(stderr
, "ld64 warning: -stack_addr not specified, using the default 0x0008000000000000\n");
1272 fStackAddr
= 0x0008000000000000LL
;
1276 if ( (fStackSize
& -4096) != fStackSize
)
1277 throw "-stack_size must be multiples of 4K";
1278 switch ( fOutputKind
) {
1279 case Options::kDynamicExecutable
:
1280 case Options::kStaticExecutable
:
1281 // custom stack size only legeal when building main executable
1283 case Options::kDynamicLibrary
:
1284 case Options::kDynamicBundle
:
1285 case Options::kObjectFile
:
1286 case Options::kDyld
:
1287 throw "-stack_size option can only be used when linking a main executable";
1291 // check -init is only used when building a dylib
1292 if ( (fInitFunctionName
!= NULL
) && (fOutputKind
!= Options::kDynamicLibrary
) )
1293 throw "-init can only be used with -dynamiclib";
1295 // make sure all required exported symbols exist
1296 for (NameSet::iterator it
=fExportSymbols
.begin(); it
!= fExportSymbols
.end(); it
++)
1297 fInitialUndefines
.push_back(*it
);