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";