]> git.saurik.com Git - apple/ld64.git/commitdiff
ld64-26.0.81.tar.gz developer-tools-22 mac-os-x-10410ppc mac-os-x-10411ppc mac-os-x-1044x86 mac-os-x-1045x86 mac-os-x-1046ppc mac-os-x-1046x86 mac-os-x-1047ppc mac-os-x-1047x86 mac-os-x-1048ppc mac-os-x-1049ppc v26.0.81
authorApple <opensource@apple.com>
Wed, 7 Sep 2005 19:18:05 +0000 (19:18 +0000)
committerApple <opensource@apple.com>
Wed, 7 Sep 2005 19:18:05 +0000 (19:18 +0000)
src/Options.cpp
src/Options.cpp.orig [new file with mode: 0644]

index 6984e67ad27628635de0f0c3a3f0ce564e991cde..350612b08b315064abdcab8dbc8069e1de3229e4 100644 (file)
@@ -888,6 +888,10 @@ void Options::parse(int argc, const char* argv[])
                        else if ( strcmp(arg, "-twolevel_namespace_hints") == 0 ) {
                                // FIX FIX
                        }
+                       else if ( strcmp(arg, "-macosx_version_min") == 0 ) {
+                               // This flag isn't needed yet, so just ignore it.
+                               ++i;
+                       }
                        else if ( strcmp(arg, "-multiply_defined") == 0 ) {
                                // FIX FIX
                                ++i;
diff --git a/src/Options.cpp.orig b/src/Options.cpp.orig
new file mode 100644 (file)
index 0000000..6984e67
--- /dev/null
@@ -0,0 +1,1297 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <vector>
+
+
+#include "Options.h"
+
+ __attribute__((noreturn))
+void throwf(const char* format, ...) 
+{
+       va_list list;
+       char*   p;
+       va_start(list, format);
+       vasprintf(&p, format, list);
+       va_end(list);
+       
+       const char*     t = p;
+       throw t;
+}
+
+
+Options::Options(int argc, const char* argv[])
+ : fOutputFile("a.out"), fArchitecture(CPU_TYPE_POWERPC64), fOutputKind(kDynamicExecutable), fBindAtLoad(false),
+       fStripLocalSymbols(false),  fKeepPrivateExterns(false),
+       fInterposable(false), fIgnoreOtherArchFiles(false), fForceSubtypeAll(false), fNameSpace(kTwoLevelNameSpace),
+       fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL), fEntryName("start"), fBaseAddress(0),
+       fExportMode(kExportDefault), fLibrarySearchMode(kSearchAllDirsForDylibsThenAllDirsForArchives),
+       fUndefinedTreatment(kUndefinedError), fMessagesPrefixedWithArchitecture(false), fPICTreatment(kPICError),
+       fWeakReferenceMismatchTreatment(kWeakReferenceMismatchError), 
+       fUmbrellaName(NULL), fInitFunctionName(NULL), fZeroPageSize(0x1000), fStackSize(0), fStackAddr(0), fMinimumHeaderPad(0),
+       fCommonsMode(kCommonsIgnoreDylibs), fWarnCommons(false), fVerbose(false)
+{
+       this->parsePreCommandLineEnvironmentSettings();
+       this->parse(argc, argv);
+       this->parsePostCommandLineEnvironmentSettings();
+       this->checkIllegalOptionCombinations();
+}
+
+Options::~Options()
+{
+}
+
+
+ObjectFile::ReaderOptions& Options::readerOptions()
+{
+       return fReaderOptions;
+}
+
+cpu_type_t Options::architecture()
+{
+       return fArchitecture;
+}
+
+
+const char*    Options::getOutputFilePath()
+{
+       return fOutputFile;
+}
+
+
+std::vector<Options::FileInfo>& Options::getInputFiles()
+{
+       return fInputFiles;
+}
+
+Options::OutputKind    Options::outputKind()
+{
+       return fOutputKind;
+}
+
+bool Options::stripLocalSymbols()
+{
+       return fStripLocalSymbols;
+}
+
+bool Options::stripDebugInfo()
+{
+       return fReaderOptions.fStripDebugInfo;
+}
+
+bool Options::bindAtLoad()
+{
+       return fBindAtLoad;
+}
+
+bool Options::fullyLoadArchives()
+{
+       return fReaderOptions.fFullyLoadArchives;
+}
+
+Options::NameSpace Options::nameSpace()
+{
+       return fNameSpace;
+}
+
+const char*    Options::installPath()
+{
+       if ( fDylibInstallName != NULL ) 
+               return fDylibInstallName;
+       else
+               return fOutputFile;
+}
+
+uint32_t Options::currentVersion()
+{
+       return fDylibCurrentVersion;
+}
+
+uint32_t Options::compatibilityVersion()
+{
+       return fDylibCompatVersion;
+}
+
+const char*    Options::entryName()
+{
+       return fEntryName;
+}
+
+uint64_t Options::baseAddress()
+{
+       return fBaseAddress;
+}
+
+bool Options::keepPrivateExterns()
+{
+       return fKeepPrivateExterns;
+}
+
+bool Options::interposable()
+{
+       return fInterposable;
+}
+
+bool Options::ignoreOtherArchInputFiles()
+{
+       return fIgnoreOtherArchFiles;
+}
+
+bool Options::forceCpuSubtypeAll()
+{
+       return fForceSubtypeAll;
+}
+
+bool Options::traceDylibs()
+{
+       return fReaderOptions.fTraceDylibs;
+}
+
+bool Options::traceArchives()
+{
+       return fReaderOptions.fTraceArchives;
+}
+
+Options::UndefinedTreatment Options::undefinedTreatment()
+{
+       return fUndefinedTreatment;
+}
+
+Options::WeakReferenceMismatchTreatment        Options::weakReferenceMismatchTreatment()
+{
+       return fWeakReferenceMismatchTreatment;
+}
+
+const char* Options::umbrellaName()
+{
+       return fUmbrellaName;
+}
+
+uint64_t Options::zeroPageSize()
+{
+       return fZeroPageSize;
+}
+
+bool Options::hasCustomStack()
+{
+       return (fStackSize != 0);
+}
+       
+uint64_t Options::customStackSize()
+{
+       return fStackSize;
+}
+
+uint64_t Options::customStackAddr()
+{
+       return fStackAddr;
+}
+
+std::vector<const char*>& Options::initialUndefines()
+{
+       return fInitialUndefines;
+}
+
+const char*    Options::initFunctionName()
+{
+       return fInitFunctionName;
+}
+
+bool Options::hasExportRestrictList()
+{
+       return (fExportMode != kExportDefault);
+}
+
+uint32_t Options::minimumHeaderPad()
+{
+       return fMinimumHeaderPad;
+}
+
+std::vector<Options::ExtraSection>&    Options::extraSections()
+{
+       return fExtraSections;
+}
+
+std::vector<Options::SectionAlignment>&        Options::sectionAlignments()
+{
+       return fSectionAlignments;
+}
+
+
+Options::CommonsMode Options::commonsMode()
+{
+       return fCommonsMode;
+}
+
+bool Options::warnCommons()
+{
+       return fWarnCommons;
+}
+
+bool Options::shouldExport(const char* symbolName)
+{
+       switch (fExportMode) {
+               case kExportSome:
+                       return ( fExportSymbols.find(symbolName) != fExportSymbols.end() );
+               case kDontExportSome:
+                       return ( fDontExportSymbols.find(symbolName) == fDontExportSymbols.end() );
+               case kExportDefault:
+                       return true;
+       }
+       throw "internal error";
+}
+
+
+void Options::parseArch(const char* architecture)
+{
+       if ( architecture == NULL )
+               throw "-arch must be followed by an architecture string";
+       if ( strcmp(architecture, "ppc") == 0 )
+               fArchitecture = CPU_TYPE_POWERPC;
+       else if ( strcmp(architecture, "ppc64") == 0 )
+               fArchitecture = CPU_TYPE_POWERPC64;
+       else if ( strcmp(architecture, "i386") == 0 )
+               fArchitecture = CPU_TYPE_I386;
+       else 
+               throw "-arch followed by unknown architecture name";
+}
+
+bool Options::checkForFile(const char* format, const char* dir, const char* rootName, FileInfo& result)
+{
+       struct stat statBuffer;
+       char possiblePath[strlen(dir)+strlen(rootName)+20];
+       sprintf(possiblePath, format,  dir, rootName);
+       if ( stat(possiblePath, &statBuffer) == 0 ) {
+               result.path = strdup(possiblePath);
+               result.fileLen = statBuffer.st_size;
+               return true;
+       }
+       return false;
+} 
+
+
+Options::FileInfo Options::findLibrary(const char* rootName)
+{
+       FileInfo result;
+       const int rootNameLen = strlen(rootName);
+       // if rootName ends in .o there is no .a vs .dylib choice
+       if ( (rootNameLen > 3) && (strcmp(&rootName[rootNameLen-2], ".o") == 0) ) {
+               for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin(); it != fLibrarySearchPaths.end(); it++) {
+                       const char* dir = *it;
+                       if ( checkForFile("%s/%s", dir, rootName, result) )
+                               return result;
+               }
+       }
+       else {
+               bool lookForDylibs = ( fOutputKind != Options::kDyld);
+               switch ( fLibrarySearchMode ) {
+                       case kSearchAllDirsForDylibsThenAllDirsForArchives:
+                               // first look in all directories for just for dylibs
+                               if ( lookForDylibs ) {
+                                       for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin(); it != fLibrarySearchPaths.end(); it++) {
+                                               const char* dir = *it;
+                                               if ( checkForFile("%s/lib%s.dylib", dir, rootName, result) )
+                                                       return result;
+                                       }
+                               }
+                               // next look in all directories for just for archives
+                               for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin(); it != fLibrarySearchPaths.end(); it++) {
+                                       const char* dir = *it;
+                                       if ( checkForFile("%s/lib%s.a", dir, rootName, result) )
+                                               return result;
+                               }
+                               break;
+
+                       case kSearchDylibAndArchiveInEachDir:
+                               // look in each directory for just for a dylib then for an archive
+                               for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin(); it != fLibrarySearchPaths.end(); it++) {
+                                       const char* dir = *it;
+                                       if ( lookForDylibs && checkForFile("%s/lib%s.dylib", dir, rootName, result) )
+                                               return result;
+                                       if ( checkForFile("%s/lib%s.a", dir, rootName, result) )
+                                               return result;
+                               }
+                               break;
+               }
+       }
+       throwf("library not found for -l%s", rootName);
+}
+
+
+Options::FileInfo Options::findFramework(const char* rootName)
+{
+       struct stat statBuffer;
+       const int rootNameLen = strlen(rootName);
+       for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin(); it != fFrameworkSearchPaths.end(); it++) {
+               const char* dir = *it;
+               char possiblePath[strlen(dir)+2*rootNameLen+20];
+               strcpy(possiblePath, dir);
+               strcat(possiblePath, "/");
+               strcat(possiblePath, rootName);
+               strcat(possiblePath, ".framework/");
+               strcat(possiblePath, rootName);
+               if ( stat(possiblePath, &statBuffer) == 0 ) {
+                       FileInfo result;
+                       result.path = strdup(possiblePath);
+                       result.fileLen = statBuffer.st_size;
+                       return result;
+               }
+       }
+       throwf("framework not found %s", rootName);
+}
+
+Options::FileInfo Options::findFile(const char* path)
+{
+       FileInfo result;
+       struct stat statBuffer;
+       
+       // if absolute path and not a .o file, the use SDK prefix
+       if ( (path[0] == '/') && (strcmp(&path[strlen(path)-2], ".o") != 0) ) {
+               const int pathLen = strlen(path);
+               for (std::vector<const char*>::iterator it = fSDKPaths.begin(); it != fSDKPaths.end(); it++) {
+                       const char* sdkPathDir = *it;
+                       const int sdkPathDirLen = strlen(sdkPathDir);
+                       char possiblePath[sdkPathDirLen+pathLen+4];
+                       strcpy(possiblePath, sdkPathDir);
+                       if ( possiblePath[sdkPathDirLen-1] == '/' )
+                               possiblePath[sdkPathDirLen-1] = '\0';
+                       strcat(possiblePath, path);
+                       if ( stat(possiblePath, &statBuffer) == 0 ) {
+                               result.path = strdup(possiblePath);
+                               result.fileLen = statBuffer.st_size;
+                               return result;
+                       }
+               }
+       }
+       // try raw path
+       if ( stat(path, &statBuffer) == 0 ) {
+               result.path = strdup(path);
+               result.fileLen = statBuffer.st_size;
+               return result;
+       }
+       // not found
+       throwf("file not found: %s", path);
+}
+
+
+void Options::loadFileList(const char* fileOfPaths)
+{
+       FILE* file = fopen(fileOfPaths, "r");
+       if ( file == NULL ) 
+               throwf("-filelist file not found: %s\n", fileOfPaths);
+       
+       char path[1024];
+       while ( fgets(path, 1024, file) != NULL ) {
+               path[1023] = '\0';
+               char* eol = strchr(path, '\n');
+               if ( eol != NULL )
+                       *eol = '\0';
+                       
+               fInputFiles.push_back(findFile(path));
+       }
+       fclose(file);
+}
+
+
+void Options::loadExportFile(const char* fileOfExports, const char* option, NameSet& set)
+{
+       // read in whole file
+       int fd = ::open(fileOfExports, O_RDONLY, 0);
+       if ( fd == -1 )
+               throwf("can't open %s file: %s", option, fileOfExports);
+       struct stat stat_buf;
+       ::fstat(fd, &stat_buf);
+       char* p = (char*)malloc(stat_buf.st_size);
+       if ( p == NULL )
+               throwf("can't process %s file: %s", option, fileOfExports);
+       
+       if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
+               throwf("can't read %s file: %s", option, fileOfExports);
+       
+       ::close(fd);
+       
+       // parse into symbols and add to hash_set
+       char * const end = &p[stat_buf.st_size];
+       enum { lineStart, inSymbol, inComment } state = lineStart;
+       char* symbolStart = NULL;
+       for (char* s = p; s < end; ++s ) {
+               switch ( state ) {
+                       case lineStart:
+                               if ( *s =='#' ) {
+                                       state = inComment;
+                               }
+                               else if ( !isspace(*s) ) {
+                                       state = inSymbol;
+                                       symbolStart = s;
+                               }
+                               break;
+                       case inSymbol:
+                               if ( *s == '\n' ) {
+                                       *s = '\0';
+                                       // removing any trailing spaces
+                                       char* last = s-1;
+                                       while ( isspace(*last) ) {
+                                               *last = '\0';
+                                               --last;
+                                       }
+                                       set.insert(symbolStart);
+                                       symbolStart = NULL;
+                                       state = lineStart;
+                               }
+                               break;
+                       case inComment:
+                               if ( *s == '\n' )
+                                       state = lineStart;
+                               break;
+               }
+       }
+       // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
+}
+
+void Options::setUndefinedTreatment(const char* treatment)
+{
+       if ( treatment == NULL ) 
+               throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
+
+       if ( strcmp(treatment, "warning") == 0 )
+               fUndefinedTreatment = kUndefinedWarning;
+       else if ( strcmp(treatment, "error") == 0 )
+               fUndefinedTreatment = kUndefinedError;
+       else if ( strcmp(treatment, "suppress") == 0 )
+               fUndefinedTreatment = kUndefinedSuppress;
+       else if ( strcmp(treatment, "dynamic_lookup") == 0 )
+               fUndefinedTreatment = kUndefinedDynamicLookup;
+       else
+               throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
+}
+
+void Options::setReadOnlyRelocTreatment(const char* treatment)
+{
+       if ( treatment == NULL ) 
+               throw "-read_only_relocs missing [ warning | error | suppress ]";
+
+       if ( strcmp(treatment, "warning") == 0 )
+               throw "-read_only_relocs warning not supported";
+       else if ( strcmp(treatment, "suppress") == 0 )
+               throw "-read_only_relocs suppress not supported";
+       else if ( strcmp(treatment, "error") != 0 )
+               throw "invalid option to -read_only_relocs [ warning | error | suppress | dynamic_lookup ]";
+}
+
+void Options::setPICTreatment(const char* treatment)
+{
+       if ( treatment == NULL ) 
+               throw "-sect_diff_relocs missing [ warning | error | suppress ]";
+
+       if ( strcmp(treatment, "warning") == 0 )
+               fPICTreatment = kPICWarning;
+       else if ( strcmp(treatment, "error") == 0 )
+               fPICTreatment = kPICError;
+       else if ( strcmp(treatment, "suppress") == 0 )
+               fPICTreatment = kPICSuppress;
+       else
+               throw "invalid option to -sect_diff_relocs [ warning | error | suppress ]";
+}
+
+void Options::setWeakReferenceMismatchTreatment(const char* treatment)
+{
+       if ( treatment == NULL ) 
+               throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
+
+       if ( strcmp(treatment, "error") == 0 )
+               fWeakReferenceMismatchTreatment = kWeakReferenceMismatchError;
+       else if ( strcmp(treatment, "weak") == 0 )
+               fWeakReferenceMismatchTreatment = kWeakReferenceMismatchWeak;
+       else if ( strcmp(treatment, "non-weak") == 0 )
+               fWeakReferenceMismatchTreatment = kWeakReferenceMismatchNonWeak;
+       else
+               throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
+}
+
+Options::CommonsMode Options::parseCommonsTreatment(const char* mode)
+{
+       if ( mode == NULL ) 
+               throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
+
+       if ( strcmp(mode, "ignore_dylibs") == 0 )
+               return kCommonsIgnoreDylibs;
+       else if ( strcmp(mode, "use_dylibs") == 0 )
+               return kCommonsOverriddenByDylibs;
+       else if ( strcmp(mode, "error") == 0 )
+               return kCommonsConflictsDylibsError;
+       else
+               throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
+}
+
+
+void Options::setDylibInstallNameOverride(const char* paths)
+{
+
+
+}
+
+void Options::setExecutablePath(const char* path)
+{
+
+
+}
+
+
+
+
+uint64_t Options::parseAddress(const char* addr)
+{
+       char* endptr;
+       uint64_t result = strtoull(addr, &endptr, 16);
+       return result;
+}
+
+
+
+//
+// Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz 
+//
+//
+uint32_t Options::parseVersionNumber(const char* versionString)
+{
+       unsigned long x = 0;
+       unsigned long y = 0;
+       unsigned long z = 0;
+       char* end;
+       x = strtoul(versionString, &end, 10);
+       if ( *end == '.' ) {
+               y = strtoul(&end[1], &end, 10);
+               if ( *end == '.' ) {
+                       z = strtoul(&end[1], &end, 10);
+               }
+       }
+       if ( (*end != '\0') || (x > 0xffff) || (y > 0xff) || (z > 0xff) )
+               throwf("malformed version number: %s", versionString);
+
+       return (x << 16) | ( y << 8 ) | z;
+}
+
+void Options::parseSectionOrderFile(const char* segment, const char* section, const char* path)
+{
+       fprintf(stderr, "ld64: warning -sectorder not yet supported for 64-bit code\n");
+}
+
+void Options::addSection(const char* segment, const char* section, const char* path)
+{
+       if ( strlen(segment) > 16 )
+               throw "-seccreate segment name max 16 chars";
+       if ( strlen(section) > 16 )
+               throw "-seccreate section name max 16 chars";
+
+       // read in whole file
+       int fd = ::open(path, O_RDONLY, 0);
+       if ( fd == -1 )
+               throwf("can't open -sectcreate file: %s", path);
+       struct stat stat_buf;
+       ::fstat(fd, &stat_buf);
+       char* p = (char*)malloc(stat_buf.st_size);
+       if ( p == NULL )
+               throwf("can't process -sectcreate file: %s", path);
+       if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
+               throwf("can't read -sectcreate file: %s", path);
+       ::close(fd);
+       
+       // record section to create
+       ExtraSection info = { segment, section, path, (uint8_t*)p, stat_buf.st_size };
+       fExtraSections.push_back(info);
+}
+
+void Options::addSectionAlignment(const char* segment, const char* section, const char* alignmentStr)
+{
+       if ( strlen(segment) > 16 )
+               throw "-sectalign segment name max 16 chars";
+       if ( strlen(section) > 16 )
+               throw "-sectalign section name max 16 chars";
+
+       char* endptr;
+       unsigned long value = strtoul(alignmentStr, &endptr, 16);
+       if ( *endptr != '\0')
+               throw "argument for -sectalign is not a hexadecimal number";
+       if ( value > 0x8000 )
+               throw "argument for -sectalign must be less than or equal to 0x8000";
+       uint8_t alignment = 0;
+       for(unsigned long x=value; x != 1; x >>= 1)
+               ++alignment;
+       if ( (unsigned long)(1 << alignment) != value )
+               throw "argument for -sectalign is not a power of two";
+
+       SectionAlignment info = { segment, section, alignment };
+       fSectionAlignments.push_back(info);
+}
+
+
+void Options::parse(int argc, const char* argv[])
+{
+       // pass one builds search list from -L and -F options
+       this->buildSearchPaths(argc, argv);
+       
+       // pass two parse all other options
+       for(int i=1; i < argc; ++i) {
+               const char* arg = argv[i];
+               
+               if ( arg[0] == '-' ) {
+                       if ( (arg[1] == 'L') || (arg[1] == 'F') ) {
+                               // previously handled by buildSearchPaths()
+                       }
+                       else if ( strcmp(arg, "-arch") == 0 ) {
+                               parseArch(argv[++i]);
+                       }
+                       else if ( strcmp(arg, "-dynamic") == 0 ) {
+                               // default
+                       }
+                       else if ( strcmp(arg, "-static") == 0 ) {
+                               fOutputKind = kStaticExecutable;
+                       }
+                       else if ( strcmp(arg, "-dylib") == 0 ) {
+                               fOutputKind = kDynamicLibrary;
+                       }
+                       else if ( strcmp(arg, "-bundle") == 0 ) {
+                               fOutputKind = kDynamicBundle;
+                       }
+                       else if ( strcmp(arg, "-dylinker") == 0 ) {
+                               fOutputKind = kDyld;
+                       }
+                       else if ( strcmp(arg, "-execute") == 0 ) {
+                               if ( fOutputKind != kStaticExecutable )
+                                       fOutputKind = kDynamicExecutable;
+                       }
+                       else if ( strcmp(arg, "-r") == 0 ) {
+                               fOutputKind = kObjectFile;
+                       }
+                       else if ( strcmp(arg, "-o") == 0 ) {
+                               fOutputFile = argv[++i];
+                       }
+                       else if ( arg[1] == 'l' ) {
+                               fInputFiles.push_back(findLibrary(&arg[2]));
+                       }
+                       else if ( strcmp(arg, "-weak-l") == 0 ) {
+                               FileInfo info = findLibrary(&arg[2]);
+                               info.options.fWeakImport = true;
+                               fInputFiles.push_back(info);
+                       }
+                       else if ( strcmp(arg, "-bind_at_load") == 0 ) {
+                               fBindAtLoad = true;
+                       }
+                       else if ( strcmp(arg, "-twolevel_namespace") == 0 ) {
+                               fNameSpace = kTwoLevelNameSpace;
+                       }
+                       else if ( strcmp(arg, "-flat_namespace") == 0 ) {
+                               fNameSpace = kFlatNameSpace;
+                       }
+                       else if ( strcmp(arg, "-force_flat_namespace") == 0 ) {
+                               fNameSpace = kForceFlatNameSpace;
+                       }
+                       else if ( strcmp(arg, "-all_load") == 0 ) {
+                               fReaderOptions.fFullyLoadArchives = true;
+                       }
+                       else if ( strcmp(arg, "-ObjC") == 0 ) {
+                               fReaderOptions.fLoadObjcClassesInArchives = true;
+                       }
+                       else if ( strcmp(arg, "-dylib_compatibility_version") == 0 ) {
+                               fDylibCompatVersion = parseVersionNumber(argv[++i]);
+                       }
+                       else if ( strcmp(arg, "-dylib_current_version") == 0 ) {
+                               fDylibCurrentVersion = parseVersionNumber(argv[++i]);
+                       }
+                       else if ( strcmp(arg, "-sectorder") == 0 ) {
+                               parseSectionOrderFile(argv[i+1], argv[i+2], argv[i+3]);
+                               i += 3;
+                       }
+                       else if ( (strcmp(arg, "-sectcreate") == 0) || (strcmp(arg, "-segcreate") == 0) ) {
+                               addSection(argv[i+1], argv[i+2], argv[i+3]);
+                               i += 3;
+                       }
+                       else if ( (strcmp(arg, "-dylib_install_name") == 0) || (strcmp(arg, "-dylinker_install_name") == 0) ) {
+                               fDylibInstallName = argv[++i];
+                       }
+                       else if ( strcmp(arg, "-seg1addr") == 0 ) {
+                               fBaseAddress = parseAddress(argv[++i]);
+                       }
+                       else if ( strcmp(arg, "-e") == 0 ) {
+                               fEntryName = argv[++i];
+                       }
+                       else if ( strcmp(arg, "-filelist") == 0 ) {
+                                loadFileList(argv[++i]);
+                       }
+                       else if ( strcmp(arg, "-keep_private_externs") == 0 ) {
+                                fKeepPrivateExterns = true;
+                       }
+                       else if ( strcmp(arg, "-final_output") == 0 ) {
+                                ++i;
+                               // ignore for now
+                       }
+                       else if ( (strcmp(arg, "-interposable") == 0) || (strcmp(arg, "-multi_module") == 0)) {
+                                fInterposable = true;
+                       }
+                       else if ( strcmp(arg, "-single_module") == 0 ) {
+                                fInterposable = false;
+                       }
+                       else if ( strcmp(arg, "-exported_symbols_list") == 0 ) {
+                               if ( fExportMode == kDontExportSome )
+                                       throw "can't use -exported_symbols_list and -unexported_symbols_list";
+                               fExportMode = kExportSome;
+                               loadExportFile(argv[++i], "-exported_symbols_list", fExportSymbols);
+                       }
+                       else if ( strcmp(arg, "-unexported_symbols_list") == 0 ) {
+                               if ( fExportMode == kExportSome )
+                                       throw "can't use -exported_symbols_list and -unexported_symbols_list";
+                               fExportMode = kDontExportSome;
+                               loadExportFile(argv[++i], "-unexported_symbols_list", fDontExportSymbols);
+                       }
+                       else if ( strcmp(arg, "-no_arch_warnings") == 0 ) {
+                                fIgnoreOtherArchFiles = true;
+                       }
+                       else if ( strcmp(arg, "-force_cpusubtype_ALL") == 0 ) {
+                                fForceSubtypeAll = true;
+                       }
+                       else if ( strcmp(arg, "-weak_library") == 0 ) {
+                               FileInfo info = findFile(argv[++i]);
+                               info.options.fWeakImport = true;
+                               fInputFiles.push_back(info);
+                       }
+                       else if ( strcmp(arg, "-framework") == 0 ) {
+                               fInputFiles.push_back(findFramework(argv[++i]));
+                       }
+                       else if ( strcmp(arg, "-weak_framework") == 0 ) {
+                               FileInfo info = findFramework(argv[++i]);
+                               info.options.fWeakImport = true;
+                               fInputFiles.push_back(info);
+                       }
+                       else if ( strcmp(arg, "-search_paths_first") == 0 ) {
+                               fLibrarySearchMode = kSearchDylibAndArchiveInEachDir;
+                       }
+                       else if ( strcmp(arg, "-undefined") == 0 ) {
+                                setUndefinedTreatment(argv[++i]);
+                       }
+                       else if ( strcmp(arg, "-arch_multiple") == 0 ) {
+                                fMessagesPrefixedWithArchitecture = true;
+                       }
+                       else if ( strcmp(arg, "-read_only_relocs") == 0 ) {
+                                setReadOnlyRelocTreatment(argv[++i]);
+                       }
+                       else if ( strcmp(arg, "-sect_diff_relocs") == 0 ) {
+                                setPICTreatment(argv[++i]);
+                       }
+                       else if ( strcmp(arg, "-weak_reference_mismatches") == 0 ) {
+                                setWeakReferenceMismatchTreatment(argv[++i]);
+                       }
+                       else if ( strcmp(arg, "-prebind") == 0 ) {
+                                 // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-noprebind") == 0 ) {
+                                 // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-prebind_allow_overlap") == 0 ) {
+                                 // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-prebind_all_twolevel_modules") == 0 ) {
+                                 // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-noprebind_all_twolevel_modules") == 0 ) {
+                                 // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-nofixprebinding") == 0 ) {
+                                 // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-dylib_file") == 0 ) {
+                                setDylibInstallNameOverride(argv[++i]);
+                       }
+                       else if ( strcmp(arg, "-executable_path") == 0 ) {
+                                setExecutablePath(argv[++i]);
+                       }
+                       else if ( strcmp(arg, "-segalign") == 0 ) {
+                               // FIX FIX
+                               ++i; 
+                       }
+                       else if ( strcmp(arg, "-segaddr") == 0 ) {
+                               // FIX FIX
+                               i += 2; 
+                       }
+                       else if ( strcmp(arg, "-segs_read_only_addr") == 0 ) {
+                               // FIX FIX
+                               ++i; 
+                       }
+                       else if ( strcmp(arg, "-segs_read_write_addr") == 0 ) {
+                               // FIX FIX
+                               ++i; 
+                       }
+                       else if ( strcmp(arg, "-seg_addr_table") == 0 ) {
+                               // FIX FIX
+                               ++i; 
+                       }
+                       else if ( strcmp(arg, "-seg_addr_table_filename") == 0 ) {
+                               // FIX FIX
+                               ++i; 
+                       }
+                       else if ( strcmp(arg, "-segprot") == 0 ) {
+                               // FIX FIX
+                               i += 3; 
+                       }
+                       else if ( strcmp(arg, "-pagezero_size") == 0 ) {
+                               fZeroPageSize = parseAddress(argv[++i]);
+                               fZeroPageSize &= (-4096); // page align
+                       }
+                       else if ( strcmp(arg, "-stack_addr") == 0 ) {
+                               fStackAddr = parseAddress(argv[++i]);
+                       }
+                       else if ( strcmp(arg, "-stack_size") == 0 ) {
+                               fStackSize = parseAddress(argv[++i]);
+                       }
+                       else if ( strcmp(arg, "-sectalign") == 0 ) {
+                               addSectionAlignment(argv[i+1], argv[i+2], argv[i+3]);
+                               i += 3;
+                       }
+                       else if ( strcmp(arg, "-sectorder_detail") == 0 ) {
+                                // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-sectobjectsymbols") == 0 ) {
+                               // FIX FIX
+                               i += 2;
+                       }
+                       else if ( strcmp(arg, "-bundle_loader") == 0 ) {
+                               // FIX FIX
+                               ++i;
+                       }
+                       else if ( strcmp(arg, "-private_bundle") == 0 ) {
+                               // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-twolevel_namespace_hints") == 0 ) {
+                               // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-multiply_defined") == 0 ) {
+                               // FIX FIX
+                               ++i;
+                       }
+                       else if ( strcmp(arg, "-multiply_defined_unused") == 0 ) {
+                               // FIX FIX
+                               ++i;
+                       }
+                       else if ( strcmp(arg, "-nomultidefs") == 0 ) {
+                                // FIX FIX
+                       }
+                       else if ( arg[1] == 'y' ) {
+                                // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-Y") == 0 ) {
+                                ++i;
+                                // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-m") == 0 ) {
+                                // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-whyload") == 0 ) {
+                                // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-u") == 0 ) {
+                               const char* name = argv[++i];
+                               if ( name == NULL )
+                                       throw "-u missing argument";
+                               fInitialUndefines.push_back(name);
+                       }
+                       else if ( strcmp(arg, "-i") == 0 ) {
+                                  // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-U") == 0 ) {
+                                // FIX FIX
+                                ++i;  
+                       }
+                       else if ( strcmp(arg, "-s") == 0 ) {
+                               // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-x") == 0 ) {
+                               // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-S") == 0 ) {
+                               // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-X") == 0 ) {
+                               // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-Si") == 0 ) {
+                               // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-b") == 0 ) {
+                               // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-Sn") == 0 ) {
+                               // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-dead_strip") == 0 ) {
+                                // FIX FIX
+                                fprintf(stderr, "ld64: warning -dead_strip not yet supported for 64-bit code\n");
+                       }
+                       else if ( strcmp(arg, "-w") == 0 ) {
+                               // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-arch_errors_fatal") == 0 ) {
+                               // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-M") == 0 ) {
+                               // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-whatsloaded") == 0 ) {
+                               // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-headerpad") == 0 ) {
+                               const char* size = argv[++i];
+                               if ( size == NULL )
+                                       throw "-headerpad missing argument";
+                                fMinimumHeaderPad = parseAddress(size);
+                       }
+                       else if ( strcmp(arg, "-headerpad_max_install_names") == 0 ) {
+                               // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-t") == 0 ) {
+                               // FIX FIX
+                       }
+                       else if ( strcmp(arg, "-A") == 0 ) {
+                                // FIX FIX
+                                ++i;  
+                       }
+                       else if ( strcmp(arg, "-umbrella") == 0 ) {
+                               const char* name = argv[++i];
+                               if ( name == NULL )
+                                       throw "-umbrella missing argument";
+                               fUmbrellaName = name;
+                       }
+                       else if ( strcmp(arg, "-allowable_client") == 0 ) {
+                                // FIX FIX
+                                ++i;  
+                       }
+                       else if ( strcmp(arg, "-client_name") == 0 ) {
+                                // FIX FIX
+                                ++i;  
+                       }
+                       else if ( strcmp(arg, "-sub_umbrella") == 0 ) {
+                               const char* name = argv[++i];
+                               if ( name == NULL )
+                                       throw "-sub_umbrella missing argument";
+                                fSubUmbellas.push_back(name);
+                       }
+                       else if ( strcmp(arg, "-sub_library") == 0 ) {
+                               const char* name = argv[++i];
+                               if ( name == NULL )
+                                       throw "-sub_library missing argument";
+                                fSubLibraries.push_back(name);
+                       }
+                       else if ( strcmp(arg, "-init") == 0 ) {
+                               const char* name = argv[++i];
+                               if ( name == NULL )
+                                       throw "-init missing argument";
+                               fInitFunctionName = name;
+                       }
+                       else if ( strcmp(arg, "-warn_commons") == 0 ) {
+                               fWarnCommons = true;
+                       }
+                       else if ( strcmp(arg, "-commons") == 0 ) {
+                               fCommonsMode = parseCommonsTreatment(argv[++i]);
+                       }
+                       else if ( strcmp(arg, "-v") == 0 ) {
+                               // previously handled by buildSearchPaths()
+                       }
+                       else if ( strcmp(arg, "-Z") == 0 ) {
+                               // previously handled by buildSearchPaths()
+                       }
+                       else if ( strcmp(arg, "-syslibroot") == 0 ) {
+                               ++i;
+                               // previously handled by buildSearchPaths()
+                       }
+                       else {
+                               fprintf(stderr, "unknown option: %s\n", arg);
+                       }
+               }
+               else {
+                       fInputFiles.push_back(findFile(arg));
+               }
+       }
+}
+
+
+
+// 
+// -syslibroot <path> is used for SDK support.  
+// The rule is that all search paths (both explicit and default) are
+// checked to see if they exist in the SDK.  If so, that path is
+// replaced with the sdk prefixed path.  If not, that search path
+// is used as is.  If multiple -syslibroot options are specified
+// their directory structures are logically overlayed and files
+// from sdks specified earlier on the command line used before later ones.
+// 
+void Options::buildSearchPaths(int argc, const char* argv[])
+{
+       bool addStandardLibraryDirectories = true;
+       std::vector<const char*> libraryPaths;
+       std::vector<const char*> frameworkPaths;
+       // scan through argv looking for -L, -F, -Z, and -syslibroot options
+       for(int i=0; i < argc; ++i) {
+               if ( (argv[i][0] == '-') && (argv[i][1] == 'L') )
+                       libraryPaths.push_back(&argv[i][2]);
+               else if ( (argv[i][0] == '-') && (argv[i][1] == 'F') )
+                       frameworkPaths.push_back(&argv[i][2]);
+               else if ( strcmp(argv[i], "-Z") == 0 )
+                       addStandardLibraryDirectories = false;
+               else if ( strcmp(argv[i], "-v") == 0 ) {
+                       fVerbose = true;
+                       extern const char ld64VersionString[];
+                       fprintf(stderr, "%s", ld64VersionString);
+                        // if only -v specified, exit cleanly
+                        if ( argc == 2 )
+                               exit(0);
+               }
+               else if ( strcmp(argv[i], "-syslibroot") == 0 ) {
+                       const char* path = argv[++i];
+                       if ( path == NULL )
+                               throw "-syslibroot missing argument";
+                       fSDKPaths.push_back(path);
+               }
+       }
+       if ( addStandardLibraryDirectories ) {
+               libraryPaths.push_back("/usr/lib");
+               libraryPaths.push_back("/usr/local/lib");
+               
+               frameworkPaths.push_back("/Library/Frameworks/");
+               frameworkPaths.push_back("/Network/Library/Frameworks/");
+               frameworkPaths.push_back("/System/Library/Frameworks/");
+       }
+       
+       // now merge sdk and library paths to make real search paths
+       for (std::vector<const char*>::iterator it = libraryPaths.begin(); it != libraryPaths.end(); it++) {
+               const char* libDir = *it;
+               bool sdkOverride = false;
+               if ( libDir[0] == '/' ) {
+                       char betterLibDir[PATH_MAX];
+                       if ( strstr(libDir, "/..") != NULL ) {
+                               if ( realpath(libDir, betterLibDir) != NULL )
+                                       libDir = betterLibDir;
+                       }
+                       const int libDirLen = strlen(libDir);
+                       for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
+                               const char* sdkDir = *sdkit;
+                               const int sdkDirLen = strlen(sdkDir);
+                               char newPath[libDirLen + sdkDirLen+4];
+                               strcpy(newPath, sdkDir);
+                               if ( newPath[sdkDirLen-1] == '/' )
+                                       newPath[sdkDirLen-1] = '\0';
+                               strcat(newPath, libDir);
+                               struct stat statBuffer;
+                               if ( stat(newPath, &statBuffer) == 0 ) {
+                                       fLibrarySearchPaths.push_back(strdup(newPath));
+                                       sdkOverride = true;
+                               }
+                       }
+               }
+               if ( !sdkOverride ) 
+                       fLibrarySearchPaths.push_back(libDir);
+       }
+       
+       // now merge sdk and framework paths to make real search paths
+       for (std::vector<const char*>::iterator it = frameworkPaths.begin(); it != frameworkPaths.end(); it++) {
+               const char* frameworkDir = *it;
+               bool sdkOverride = false;
+               if ( frameworkDir[0] == '/' ) {
+                       char betterFrameworkDir[PATH_MAX];
+                       if ( strstr(frameworkDir, "/..") != NULL ) {
+                               if ( realpath(frameworkDir, betterFrameworkDir) != NULL )
+                                       frameworkDir = betterFrameworkDir;
+                       }
+                       const int frameworkDirLen = strlen(frameworkDir);
+                       for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
+                               const char* sdkDir = *sdkit;
+                               const int sdkDirLen = strlen(sdkDir);
+                               char newPath[frameworkDirLen + sdkDirLen+4];
+                               strcpy(newPath, sdkDir);
+                               if ( newPath[sdkDirLen-1] == '/' )
+                                       newPath[sdkDirLen-1] = '\0';
+                               strcat(newPath, frameworkDir);
+                               struct stat statBuffer;
+                               if ( stat(newPath, &statBuffer) == 0 ) {
+                                       fFrameworkSearchPaths.push_back(strdup(newPath));
+                                       sdkOverride = true;
+                               }
+                       }
+               }
+               if ( !sdkOverride ) 
+                       fFrameworkSearchPaths.push_back(frameworkDir);
+       }
+       
+       if ( fVerbose ) {
+               fprintf(stderr,"Library search paths:\n");
+               for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin(); it != fLibrarySearchPaths.end(); it++)
+                       fprintf(stderr,"\t%s\n", *it);
+               fprintf(stderr,"Framework search paths:\n");
+               for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin(); it != fFrameworkSearchPaths.end(); it++)
+                       fprintf(stderr,"\t%s\n", *it);
+       }
+}
+
+// this is run before the command line is parsed
+void Options::parsePreCommandLineEnvironmentSettings()
+{
+       if ( getenv("RC_TRACE_ARCHIVES") != NULL)
+           fReaderOptions.fTraceArchives = true;
+               
+       if ( getenv("RC_TRACE_DYLIBS") != NULL) {
+           fReaderOptions.fTraceDylibs = true;
+               fReaderOptions.fTraceIndirectDylibs = true;
+       }
+}
+
+// this is run after the command line is parsed
+void Options::parsePostCommandLineEnvironmentSettings()
+{
+
+}
+
+void Options::checkIllegalOptionCombinations()
+{
+       // check -undefined setting
+       switch ( fUndefinedTreatment ) {
+               case kUndefinedError:
+               case kUndefinedDynamicLookup:
+                       // always legal
+                       break;
+               case kUndefinedWarning:
+               case kUndefinedSuppress:
+                       // requires flat namespace
+                       if ( fNameSpace == kTwoLevelNameSpace )
+                               throw "can't use -undefined warning or suppress with -twolevel_namespace";
+                       break;
+       }
+       
+       // unify -sub_umbrella with dylibs
+       for (std::vector<const char*>::iterator it = fSubUmbellas.begin(); it != fSubUmbellas.end(); it++) {
+               const char* subUmbrella = *it;
+               bool found = false;
+               for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
+                       Options::FileInfo& info = *fit;
+                       const char* lastSlash = strrchr(info.path, '/');
+                       if ( lastSlash == NULL )
+                               lastSlash = info.path - 1;
+                       if ( strcmp(&lastSlash[1], subUmbrella) == 0 ) {
+                               info.options.fReExport = true;
+                               found = true;
+                               break;
+                       }
+               }
+               if ( ! found )
+                       fprintf(stderr, "ld64 warning: -sub_umbrella %s does not match a supplied dylib\n", subUmbrella);
+       }
+       
+       // unify -sub_library with dylibs
+       for (std::vector<const char*>::iterator it = fSubLibraries.begin(); it != fSubLibraries.end(); it++) {
+               const char* subLibrary = *it;
+               bool found = false;
+               for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
+                       Options::FileInfo& info = *fit;
+                       const char* lastSlash = strrchr(info.path, '/');
+                       if ( lastSlash == NULL )
+                               lastSlash = info.path - 1;
+                       const char* dot = strchr(lastSlash, '.');
+                       if ( dot == NULL )
+                               dot = &lastSlash[strlen(lastSlash)];
+                       if ( strncmp(&lastSlash[1], subLibrary, dot-lastSlash-1) == 0 ) {
+                               info.options.fReExport = true;
+                               found = true;
+                               break;
+                       }
+               }
+               if ( ! found )
+                       fprintf(stderr, "ld64 warning: -sub_library %s does not match a supplied dylib\n", subLibrary);
+       }
+       
+       // sync reader options
+       if ( fNameSpace != kTwoLevelNameSpace )
+               fReaderOptions.fFlatNamespace = true;
+
+       // check -stack_addr
+       if ( fStackAddr != 0 ) { 
+               switch (fArchitecture) {
+                       case CPU_TYPE_I386:
+                       case CPU_TYPE_POWERPC:
+                               if ( fStackAddr > 0xFFFFFFFF ) 
+                                       throw "-stack_addr must be < 4G for 32-bit processes";
+                               break;
+                       case CPU_TYPE_POWERPC64:
+                               break;
+               }
+               if ( (fStackAddr & -4096) != fStackAddr )
+                       throw "-stack_addr must be multiples of 4K";
+               if ( fStackSize  == 0 )
+                       throw "-stack_addr must be used with -stack_size";
+       }
+       
+       // check -stack_size
+       if ( fStackSize != 0 ) { 
+               switch (fArchitecture) {
+                       case CPU_TYPE_I386:
+                       case CPU_TYPE_POWERPC:
+                               if ( fStackSize > 0xFFFFFFFF ) 
+                                       throw "-stack_size must be < 4G for 32-bit processes";
+                               if ( fStackAddr == 0 ) {
+                                       fprintf(stderr, "ld64 warning: -stack_addr not specified, using the default 0xC0000000\n");
+                                       fStackAddr = 0xC0000000;
+                               }
+                               break;
+                       case CPU_TYPE_POWERPC64:
+                               if ( fStackAddr == 0 ) {
+                                       fprintf(stderr, "ld64 warning: -stack_addr not specified, using the default 0x0008000000000000\n");
+                                       fStackAddr = 0x0008000000000000LL;
+                               }
+                               break;
+               }
+               if ( (fStackSize & -4096) != fStackSize )
+                       throw "-stack_size must be multiples of 4K";
+               switch ( fOutputKind ) {
+                       case Options::kDynamicExecutable:
+                       case Options::kStaticExecutable:
+                               // custom stack size only legeal when building main executable
+                               break;
+                       case Options::kDynamicLibrary:
+                       case Options::kDynamicBundle:
+                       case Options::kObjectFile:
+                       case Options::kDyld:
+                               throw "-stack_size option can only be used when linking a main executable";
+               }
+       }
+       
+       // check -init is only used when building a dylib
+       if ( (fInitFunctionName != NULL) && (fOutputKind != Options::kDynamicLibrary) )
+               throw "-init can only be used with -dynamiclib";
+               
+       // make sure all required exported symbols exist
+       for (NameSet::iterator it=fExportSymbols.begin(); it != fExportSymbols.end(); it++)
+               fInitialUndefines.push_back(*it);
+               
+}
+
+