]> git.saurik.com Git - apple/ld64.git/blame - src/ld/Options.cpp
ld64-128.2.tar.gz
[apple/ld64.git] / src / ld / Options.cpp
CommitLineData
d696c285 1/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
6e880c60 2 *
afe874b1 3 * Copyright (c) 2005-2011 Apple Inc. All rights reserved.
c2646906
A
4 *
5 * @APPLE_LICENSE_HEADER_START@
d696c285 6 *
c2646906
A
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
12 * file.
d696c285 13 *
c2646906
A
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.
d696c285 21 *
c2646906
A
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25
26#include <sys/types.h>
27#include <sys/stat.h>
a61fdf0a 28#include <mach/vm_prot.h>
55e3d2f6 29#include <mach-o/dyld.h>
c2646906 30#include <fcntl.h>
a645023d 31
6e880c60 32#include <vector>
c2646906 33
2f2f92e4 34#include "configure.h"
c2646906 35#include "Options.h"
2f2f92e4
A
36#include "Architectures.hpp"
37#include "MachOFileAbstraction.hpp"
38
a645023d
A
39// upward dependency on lto::version()
40namespace lto {
41 extern const char* version();
42}
2f2f92e4 43
55e3d2f6 44// magic to place command line in crash reports
a645023d 45const int crashreporterBufferSize = 2000;
55e3d2f6 46extern "C" char* __crashreporter_info__;
a645023d 47static char crashreporterBuffer[crashreporterBufferSize];
55e3d2f6 48char* __crashreporter_info__ = crashreporterBuffer;
2f2f92e4
A
49
50static bool sEmitWarnings = true;
b2fa67a8 51static bool sFatalWarnings = false;
2f2f92e4
A
52static const char* sWarningsSideFilePath = NULL;
53static FILE* sWarningsSideFile = NULL;
b2fa67a8 54static int sWarningsCount = 0;
2f2f92e4
A
55
56void warning(const char* format, ...)
57{
b2fa67a8 58 ++sWarningsCount;
2f2f92e4
A
59 if ( sEmitWarnings ) {
60 va_list list;
61 if ( sWarningsSideFilePath != NULL ) {
62 if ( sWarningsSideFile == NULL )
63 sWarningsSideFile = fopen(sWarningsSideFilePath, "a");
64 }
65 va_start(list, format);
55e3d2f6 66 fprintf(stderr, "ld: warning: ");
2f2f92e4
A
67 vfprintf(stderr, format, list);
68 fprintf(stderr, "\n");
69 if ( sWarningsSideFile != NULL ) {
55e3d2f6 70 fprintf(sWarningsSideFile, "ld: warning: ");
2f2f92e4
A
71 vfprintf(sWarningsSideFile, format, list);
72 fprintf(sWarningsSideFile, "\n");
73 fflush(sWarningsSideFile);
74 }
75 va_end(list);
76 }
77}
c2646906 78
d696c285 79void throwf(const char* format, ...)
c2646906
A
80{
81 va_list list;
82 char* p;
83 va_start(list, format);
84 vasprintf(&p, format, list);
85 va_end(list);
d696c285 86
c2646906
A
87 const char* t = p;
88 throw t;
89}
90
c2646906 91Options::Options(int argc, const char* argv[])
a645023d 92 : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0), fArchitectureName("unknown"), fOutputKind(kDynamicExecutable),
afe874b1 93 fHasPreferredSubType(false), fArchSupportsThumb2(false), fPrebind(false), fBindAtLoad(false), fKeepPrivateExterns(false),
55e3d2f6 94 fNeedsModuleTable(false), fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false),
a645023d
A
95 fInterposeMode(kInterposeNone), fDeadStrip(false), fNameSpace(kTwoLevelNameSpace),
96 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL), fFinalName(NULL), fEntryName("start"),
97 fBaseAddress(0), fMaxAddress(0x7FFFFFFFFFFFFFFFLL),
a61fdf0a 98 fBaseWritableAddress(0), fSplitSegs(false),
a645023d
A
99 fExportMode(kExportDefault), fLibrarySearchMode(kSearchDylibAndArchiveInEachDir),
100 fUndefinedTreatment(kUndefinedError), fMessagesPrefixedWithArchitecture(true),
a61fdf0a
A
101 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak),
102 fClientName(NULL),
103 fUmbrellaName(NULL), fInitFunctionName(NULL), fDotOutputFile(NULL), fExecutablePath(NULL),
104 fBundleLoader(NULL), fDtraceScriptName(NULL), fSegAddrTablePath(NULL), fMapPath(NULL),
a645023d 105 fDyldInstallPath("/usr/lib/dyld"), fTempLtoObjectPath(NULL),
55e3d2f6 106 fZeroPageSize(ULLONG_MAX), fStackSize(0), fStackAddr(0), fExecutableStack(false),
a645023d 107 fNonExecutableHeap(false), fDisableNonExecutableHeap(false),
55e3d2f6 108 fMinimumHeaderPad(32), fSegmentAlignment(4096),
a61fdf0a
A
109 fCommonsMode(kCommonsIgnoreDylibs), fUUIDMode(kUUIDContent), fLocalSymbolHandling(kLocalSymbolsAll), fWarnCommons(false),
110 fVerbose(false), fKeepRelocations(false), fWarnStabs(false),
69a49097 111 fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
a61fdf0a 112 fSharedRegionEligible(false), fPrintOrderFileStatistics(false),
a645023d 113 fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), fPIEOnCommandLine(false),
d9246299 114 fDisablePositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
2f2f92e4 115 fDeadStripDylibs(false), fAllowTextRelocs(false), fWarnTextRelocs(false),
4be885f6
A
116 fUsingLazyDylibLinking(false), fEncryptable(true),
117 fOrderData(true), fMarkDeadStrippableDylib(false),
a645023d
A
118 fMakeCompressedDyldInfo(true), fMakeCompressedDyldInfoForceOff(false), fNoEHLabels(false),
119 fAllowCpuSubtypeMismatches(false), fUseSimplifiedDylibReExports(false),
120 fObjCABIVersion2Override(false), fObjCABIVersion1Override(false), fCanUseUpwardDylib(false),
121 fFullyLoadArchives(false), fLoadAllObjcObjectsFromArchives(false), fFlatNamespace(false),
122 fLinkingMainExecutable(false), fForFinalLinkedImage(false), fForStatic(false),
123 fForDyld(false), fMakeTentativeDefinitionsReal(false), fWhyLoad(false), fRootSafe(false),
124 fSetuidSafe(false), fImplicitlyLinkPublicDylibs(true), fAddCompactUnwindEncoding(true),
125 fWarnCompactUnwind(false), fRemoveDwarfUnwindIfCompactExists(false),
afe874b1 126 fAutoOrderInitializers(true), fOptimizeZeroFill(true), fMergeZeroFill(false), fLogObjectFiles(false),
a645023d
A
127 fLogAllFiles(false), fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false),
128 fOutputSlidable(false), fWarnWeakExports(false),
129 fObjcGcCompaction(false), fObjCGc(false), fObjCGcOnly(false),
130 fDemangle(false), fTLVSupport(false),
afe874b1
A
131 fVersionLoadCommand(false), fVersionLoadCommandForcedOn(false),
132 fVersionLoadCommandForcedOff(false), fFunctionStartsLoadCommand(false),
133 fFunctionStartsForcedOn(false), fFunctionStartsForcedOff(false),
134 fCanReExportSymbols(false), fObjcCategoryMerging(true), fPageAlignDataAtoms(false),
a645023d 135 fDebugInfoStripping(kDebugInfoMinimal), fTraceOutputFile(NULL),
afe874b1 136 fMacVersionMin(ld::macVersionUnset), fIOSVersionMin(ld::iOSVersionUnset),
a645023d 137 fSaveTempFiles(false)
c2646906 138{
a61fdf0a 139 this->checkForClassic(argc, argv);
c2646906
A
140 this->parsePreCommandLineEnvironmentSettings();
141 this->parse(argc, argv);
142 this->parsePostCommandLineEnvironmentSettings();
69a49097 143 this->reconfigureDefaults();
c2646906
A
144 this->checkIllegalOptionCombinations();
145}
146
147Options::~Options()
148{
149}
150
c2646906 151
b2fa67a8
A
152bool Options::errorBecauseOfWarnings() const
153{
154 return (sFatalWarnings && (sWarningsCount > 0));
155}
c2646906 156
c2646906 157
a645023d 158const char* Options::installPath() const
c2646906 159{
d696c285 160 if ( fDylibInstallName != NULL )
c2646906 161 return fDylibInstallName;
a61fdf0a
A
162 else if ( fFinalName != NULL )
163 return fFinalName;
c2646906
A
164 else
165 return fOutputFile;
166}
167
c2646906 168
a645023d 169bool Options::interposable(const char* name) const
c2646906 170{
2f2f92e4
A
171 switch ( fInterposeMode ) {
172 case kInterposeNone:
173 return false;
174 case kInterposeAllExternal:
175 return true;
176 case kInterposeSome:
177 return fInterposeList.contains(name);
178 }
179 throw "internal error";
c2646906
A
180}
181
c2646906 182
a645023d 183bool Options::printWhyLive(const char* symbolName) const
69a49097
A
184{
185 return ( fWhyLive.find(symbolName) != fWhyLive.end() );
186}
187
d696c285 188
d696c285
A
189const char* Options::dotOutputFile()
190{
191 return fDotOutputFile;
192}
193
c2646906 194
a645023d 195bool Options::hasWildCardExportRestrictList() const
2f2f92e4 196{
a645023d
A
197 // has -exported_symbols_list which contains some wildcards
198 return ((fExportMode == kExportSome) && fExportSymbols.hasWildCards());
2f2f92e4
A
199}
200
a645023d 201bool Options::hasWeakBitTweaks() const
2f2f92e4
A
202{
203 // has -exported_symbols_list which contains some wildcards
a645023d 204 return (!fForceWeakSymbols.empty() || !fForceNotWeakSymbols.empty());
2f2f92e4
A
205}
206
a645023d 207bool Options::allGlobalsAreDeadStripRoots() const
69a49097
A
208{
209 // -exported_symbols_list means globals are not exported by default
a61fdf0a 210 if ( fExportMode == kExportSome )
69a49097
A
211 return false;
212 //
213 switch ( fOutputKind ) {
214 case Options::kDynamicExecutable:
215 case Options::kStaticExecutable:
55e3d2f6 216 case Options::kPreload:
69a49097
A
217 // by default unused globals in a main executable are stripped
218 return false;
219 case Options::kDynamicLibrary:
220 case Options::kDynamicBundle:
221 case Options::kObjectFile:
222 case Options::kDyld:
55e3d2f6 223 case Options::kKextBundle:
69a49097
A
224 return true;
225 }
226 return false;
227}
228
a645023d
A
229
230bool Options::keepRelocations()
c2646906 231{
a645023d 232 return fKeepRelocations;
c2646906
A
233}
234
a645023d 235bool Options::warnStabs()
c2646906 236{
a645023d 237 return fWarnStabs;
c2646906
A
238}
239
a645023d 240const char* Options::executablePath()
c2646906 241{
a645023d 242 return fExecutablePath;
c2646906
A
243}
244
a645023d
A
245
246uint32_t Options::initialSegProtection(const char* segName) const
c2646906 247{
a645023d
A
248 for(std::vector<Options::SegmentProtect>::const_iterator it = fCustomSegmentProtections.begin(); it != fCustomSegmentProtections.end(); ++it) {
249 if ( strcmp(it->name, segName) == 0 ) {
250 return it->init;
251 }
252 }
253 if ( strcmp(segName, "__PAGEZERO") == 0 ) {
254 return 0;
255 }
256 else if ( strcmp(segName, "__TEXT") == 0 ) {
257 return VM_PROT_READ | VM_PROT_EXECUTE;
258 }
259 else if ( strcmp(segName, "__LINKEDIT") == 0 ) {
260 return VM_PROT_READ;
261 }
262
263 // all others default to read-write
264 return VM_PROT_READ | VM_PROT_WRITE;
c2646906
A
265}
266
a645023d 267uint32_t Options::maxSegProtection(const char* segName) const
c2646906 268{
a645023d 269 // iPhoneOS always uses same protection for max and initial
afe874b1 270 if ( fIOSVersionMin != ld::iOSVersionUnset )
a645023d
A
271 return initialSegProtection(segName);
272
273 for(std::vector<Options::SegmentProtect>::const_iterator it = fCustomSegmentProtections.begin(); it != fCustomSegmentProtections.end(); ++it) {
274 if ( strcmp(it->name, segName) == 0 ) {
275 return it->max;
276 }
277 }
278 if ( strcmp(segName, "__PAGEZERO") == 0 ) {
279 return 0;
280 }
281 // all others default to all
282 return VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
283}
284
285uint64_t Options::segPageSize(const char* segName) const
286{
287 for(std::vector<SegmentSize>::const_iterator it=fCustomSegmentSizes.begin(); it != fCustomSegmentSizes.end(); ++it) {
288 if ( strcmp(it->name, segName) == 0 )
289 return it->size;
290 }
291 return fSegmentAlignment;
c2646906
A
292}
293
a645023d 294uint64_t Options::customSegmentAddress(const char* segName) const
d696c285 295{
a645023d
A
296 for(std::vector<SegmentStart>::const_iterator it=fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
297 if ( strcmp(it->name, segName) == 0 )
298 return it->address;
299 }
300 // if custom stack in use, model as segment with custom address
301 if ( (fStackSize != 0) && (strcmp("__UNIXSTACK", segName) == 0) )
302 return fStackAddr - fStackSize;
303 return 0;
d696c285
A
304}
305
a645023d 306bool Options::hasCustomSegmentAddress(const char* segName) const
d696c285 307{
a645023d
A
308 for(std::vector<SegmentStart>::const_iterator it=fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
309 if ( strcmp(it->name, segName) == 0 )
310 return true;
311 }
312 // if custom stack in use, model as segment with custom address
313 if ( (fStackSize != 0) && (strcmp("__UNIXSTACK", segName) == 0) )
314 return true;
315 return false;
d696c285
A
316}
317
a645023d 318bool Options::hasCustomSectionAlignment(const char* segName, const char* sectName) const
d696c285 319{
a645023d
A
320 for (std::vector<SectionAlignment>::const_iterator it = fSectionAlignments.begin(); it != fSectionAlignments.end(); ++it) {
321 if ( (strcmp(it->segmentName, segName) == 0) && (strcmp(it->sectionName, sectName) == 0) )
322 return true;
323 }
324 return false;
d696c285
A
325}
326
a645023d 327uint8_t Options::customSectionAlignment(const char* segName, const char* sectName) const
d696c285 328{
a645023d
A
329 for (std::vector<SectionAlignment>::const_iterator it = fSectionAlignments.begin(); it != fSectionAlignments.end(); ++it) {
330 if ( (strcmp(it->segmentName, segName) == 0) && (strcmp(it->sectionName, sectName) == 0) )
331 return it->alignment;
332 }
333 return 0;
d696c285
A
334}
335
a645023d 336
55e3d2f6
A
337bool Options::hasExportedSymbolOrder()
338{
339 return (fExportSymbolsOrder.size() > 0);
340}
341
a645023d 342bool Options::exportedSymbolOrder(const char* sym, unsigned int* order) const
55e3d2f6 343{
a645023d 344 NameToOrder::const_iterator pos = fExportSymbolsOrder.find(sym);
55e3d2f6
A
345 if ( pos != fExportSymbolsOrder.end() ) {
346 *order = pos->second;
347 return true;
348 }
349 else {
350 *order = 0xFFFFFFFF;
351 return false;
352 }
353}
354
355void Options::loadSymbolOrderFile(const char* fileOfExports, NameToOrder& orderMapping)
356{
357 // read in whole file
358 int fd = ::open(fileOfExports, O_RDONLY, 0);
359 if ( fd == -1 )
360 throwf("can't open -exported_symbols_order file: %s", fileOfExports);
361 struct stat stat_buf;
362 ::fstat(fd, &stat_buf);
363 char* p = (char*)malloc(stat_buf.st_size);
364 if ( p == NULL )
365 throwf("can't process -exported_symbols_order file: %s", fileOfExports);
366
367 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
368 throwf("can't read -exported_symbols_order file: %s", fileOfExports);
369
370 ::close(fd);
371
372 // parse into symbols and add to hash_set
373 unsigned int count = 0;
374 char * const end = &p[stat_buf.st_size];
375 enum { lineStart, inSymbol, inComment } state = lineStart;
376 char* symbolStart = NULL;
377 for (char* s = p; s < end; ++s ) {
378 switch ( state ) {
379 case lineStart:
380 if ( *s =='#' ) {
381 state = inComment;
382 }
383 else if ( !isspace(*s) ) {
384 state = inSymbol;
385 symbolStart = s;
386 }
387 break;
388 case inSymbol:
389 if ( (*s == '\n') || (*s == '\r') ) {
390 *s = '\0';
391 // removing any trailing spaces
392 char* last = s-1;
393 while ( isspace(*last) ) {
394 *last = '\0';
395 --last;
396 }
397 orderMapping[symbolStart] = ++count;
398 symbolStart = NULL;
399 state = lineStart;
400 }
401 break;
402 case inComment:
403 if ( (*s == '\n') || (*s == '\r') )
404 state = lineStart;
405 break;
406 }
407 }
408 if ( state == inSymbol ) {
409 warning("missing line-end at end of file \"%s\"", fileOfExports);
410 int len = end-symbolStart+1;
411 char* temp = new char[len];
412 strlcpy(temp, symbolStart, len);
413
414 // remove any trailing spaces
415 char* last = &temp[len-2];
416 while ( isspace(*last) ) {
417 *last = '\0';
418 --last;
419 }
420 orderMapping[temp] = ++count;
421 }
422
423 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
424}
425
a645023d
A
426bool Options::forceWeak(const char* symbolName) const
427{
428 return fForceWeakSymbols.contains(symbolName);
429}
430
431bool Options::forceNotWeak(const char* symbolName) const
432{
433 return fForceNotWeakSymbols.contains(symbolName);
434}
435
436bool Options::forceWeakNonWildCard(const char* symbolName) const
437{
438 return fForceWeakSymbols.containsNonWildcard(symbolName);
439}
440
441bool Options::forceNotWeakNonWildcard(const char* symbolName) const
442{
443 return fForceNotWeakSymbols.containsNonWildcard(symbolName);
444}
445
55e3d2f6 446
a645023d 447bool Options::shouldExport(const char* symbolName) const
c2646906
A
448{
449 switch (fExportMode) {
450 case kExportSome:
a61fdf0a 451 return fExportSymbols.contains(symbolName);
c2646906 452 case kDontExportSome:
a61fdf0a 453 return ! fDontExportSymbols.contains(symbolName);
c2646906
A
454 case kExportDefault:
455 return true;
456 }
457 throw "internal error";
458}
459
a645023d
A
460bool Options::shouldReExport(const char* symbolName) const
461{
462 return fReExportSymbols.contains(symbolName);
463}
464
465bool Options::keepLocalSymbol(const char* symbolName) const
a61fdf0a
A
466{
467 switch (fLocalSymbolHandling) {
468 case kLocalSymbolsAll:
469 return true;
470 case kLocalSymbolsNone:
471 return false;
472 case kLocalSymbolsSelectiveInclude:
473 return fLocalSymbolsIncluded.contains(symbolName);
474 case kLocalSymbolsSelectiveExclude:
475 return ! fLocalSymbolsExcluded.contains(symbolName);
476 }
477 throw "internal error";
478}
479
a645023d 480void Options::setArchitecture(cpu_type_t type, cpu_subtype_t subtype)
c2646906 481{
a645023d
A
482 fArchitecture = type;
483 fSubArchitecture = subtype;
484 switch ( type ) {
a645023d
A
485 case CPU_TYPE_I386:
486 fArchitectureName = "i386";
487 if ( (fMacVersionMin == ld::macVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
488 #ifdef DEFAULT_MACOSX_MIN_VERSION
489 warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION);
490 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
491 #else
492 warning("-macosx_version_min not specificed, assuming 10.6");
493 fMacVersionMin = ld::mac10_6;
494 #endif
495 }
496 if ( !fMakeCompressedDyldInfo && (fMacVersionMin >= ld::mac10_6) && !fMakeCompressedDyldInfoForceOff )
497 fMakeCompressedDyldInfo = true;
498 break;
499 case CPU_TYPE_X86_64:
500 fArchitectureName = "x86_64";
501 if ( (fMacVersionMin == ld::macVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
502 #ifdef DEFAULT_MACOSX_MIN_VERSION
503 warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION);
504 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
505 #else
506 warning("-macosx_version_min not specificed, assuming 10.6");
507 fMacVersionMin = ld::mac10_6;
508 #endif
509 }
510 if ( !fMakeCompressedDyldInfo && (fMacVersionMin >= ld::mac10_6) && !fMakeCompressedDyldInfoForceOff )
511 fMakeCompressedDyldInfo = true;
512 break;
513 case CPU_TYPE_ARM:
afe874b1
A
514 fHasPreferredSubType = true;
515 for (const ARMSubType* t=ARMSubTypes; t->subTypeName != NULL; ++t) {
516 if ( t->subType == subtype ) {
517 fArchitectureName = t->subTypeName;
518 fArchSupportsThumb2 = t->supportsThumb2;
519 break;
520 }
a645023d 521 }
afe874b1
A
522 assert(fArchitectureName != NULL);
523 if ( (fMacVersionMin == ld::macVersionUnset) && (fIOSVersionMin == ld::iOSVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
a645023d
A
524#if defined(DEFAULT_IPHONEOS_MIN_VERSION)
525 warning("-ios_version_min not specificed, assuming " DEFAULT_IPHONEOS_MIN_VERSION);
afe874b1 526 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION);
a645023d
A
527#elif defined(DEFAULT_MACOSX_MIN_VERSION)
528 warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION);
529 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
530#else
531 warning("-macosx_version_min not specificed, assuming 10.6");
532 fMacVersionMin = ld::mac10_6;
533#endif
534 }
afe874b1 535 if ( !fMakeCompressedDyldInfo && minOS(ld::mac10_6, ld::iOS_3_1) && !fMakeCompressedDyldInfoForceOff )
a645023d
A
536 fMakeCompressedDyldInfo = true;
537 break;
538 default:
539 fArchitectureName = "unknown architecture";
540 break;
541 }
542}
543
544void Options::parseArch(const char* arch)
545{
546 if ( arch == NULL )
c2646906 547 throw "-arch must be followed by an architecture string";
a645023d 548 fArchitectureName = arch;
b2fa67a8 549 if ( strcmp(arch, "i386") == 0 ) {
c2646906 550 fArchitecture = CPU_TYPE_I386;
2f2f92e4
A
551 fSubArchitecture = CPU_SUBTYPE_I386_ALL;
552 }
a645023d 553 else if ( strcmp(arch, "x86_64") == 0 ) {
69a49097 554 fArchitecture = CPU_TYPE_X86_64;
2f2f92e4
A
555 fSubArchitecture = CPU_SUBTYPE_X86_64_ALL;
556 }
a645023d 557 else if ( strcmp(arch, "arm") == 0 ) {
2f2f92e4
A
558 fArchitecture = CPU_TYPE_ARM;
559 fSubArchitecture = CPU_SUBTYPE_ARM_ALL;
560 }
afe874b1
A
561 else {
562 for (const ARMSubType* t=ARMSubTypes; t->subTypeName != NULL; ++t) {
563 if ( strcmp(t->subTypeName,arch) == 0 ) {
564 fArchitecture = CPU_TYPE_ARM;
565 fSubArchitecture = t->subType;
566 fArchSupportsThumb2 = t->supportsThumb2;
567 fHasPreferredSubType = true;
568 return;
569 }
570 }
a645023d 571 throwf("unknown/unsupported architecture name for: -arch %s", arch);
afe874b1 572 }
c2646906
A
573}
574
a645023d 575bool Options::checkForFile(const char* format, const char* dir, const char* rootName, FileInfo& result) const
c2646906
A
576{
577 struct stat statBuffer;
d696c285 578 char possiblePath[strlen(dir)+strlen(rootName)+strlen(format)+8];
c2646906 579 sprintf(possiblePath, format, dir, rootName);
d696c285
A
580 bool found = (stat(possiblePath, &statBuffer) == 0);
581 if ( fTraceDylibSearching )
582 printf("[Logging for XBS]%sfound library: '%s'\n", (found ? " " : " not "), possiblePath);
583 if ( found ) {
c2646906
A
584 result.path = strdup(possiblePath);
585 result.fileLen = statBuffer.st_size;
d696c285 586 result.modTime = statBuffer.st_mtime;
c2646906
A
587 return true;
588 }
589 return false;
d696c285 590}
c2646906
A
591
592
2f2f92e4 593Options::FileInfo Options::findLibrary(const char* rootName, bool dylibsOnly)
c2646906
A
594{
595 FileInfo result;
596 const int rootNameLen = strlen(rootName);
597 // if rootName ends in .o there is no .a vs .dylib choice
598 if ( (rootNameLen > 3) && (strcmp(&rootName[rootNameLen-2], ".o") == 0) ) {
d696c285
A
599 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
600 it != fLibrarySearchPaths.end();
601 it++) {
c2646906
A
602 const char* dir = *it;
603 if ( checkForFile("%s/%s", dir, rootName, result) )
604 return result;
605 }
606 }
607 else {
608 bool lookForDylibs = ( fOutputKind != Options::kDyld);
609 switch ( fLibrarySearchMode ) {
d696c285 610 case kSearchAllDirsForDylibsThenAllDirsForArchives:
c2646906
A
611 // first look in all directories for just for dylibs
612 if ( lookForDylibs ) {
d696c285
A
613 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
614 it != fLibrarySearchPaths.end();
615 it++) {
c2646906
A
616 const char* dir = *it;
617 if ( checkForFile("%s/lib%s.dylib", dir, rootName, result) )
618 return result;
619 }
a61fdf0a
A
620 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
621 it != fLibrarySearchPaths.end();
622 it++) {
623 const char* dir = *it;
624 if ( checkForFile("%s/lib%s.so", dir, rootName, result) )
625 return result;
626 }
c2646906
A
627 }
628 // next look in all directories for just for archives
2f2f92e4
A
629 if ( !dylibsOnly ) {
630 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
631 it != fLibrarySearchPaths.end();
632 it++) {
633 const char* dir = *it;
634 if ( checkForFile("%s/lib%s.a", dir, rootName, result) )
635 return result;
636 }
c2646906
A
637 }
638 break;
639
640 case kSearchDylibAndArchiveInEachDir:
641 // look in each directory for just for a dylib then for an archive
d696c285
A
642 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
643 it != fLibrarySearchPaths.end();
644 it++) {
c2646906
A
645 const char* dir = *it;
646 if ( lookForDylibs && checkForFile("%s/lib%s.dylib", dir, rootName, result) )
647 return result;
a61fdf0a
A
648 if ( lookForDylibs && checkForFile("%s/lib%s.so", dir, rootName, result) )
649 return result;
2f2f92e4 650 if ( !dylibsOnly && checkForFile("%s/lib%s.a", dir, rootName, result) )
c2646906
A
651 return result;
652 }
653 break;
654 }
655 }
656 throwf("library not found for -l%s", rootName);
657}
658
74cfe461
A
659Options::FileInfo Options::findFramework(const char* frameworkName)
660{
661 if ( frameworkName == NULL )
a61fdf0a 662 throw "-framework missing next argument";
74cfe461
A
663 char temp[strlen(frameworkName)+1];
664 strcpy(temp, frameworkName);
665 const char* name = temp;
666 const char* suffix = NULL;
667 char* comma = strchr(temp, ',');
668 if ( comma != NULL ) {
669 *comma = '\0';
670 suffix = &comma[1];
671 }
672 return findFramework(name, suffix);
673}
c2646906 674
74cfe461 675Options::FileInfo Options::findFramework(const char* rootName, const char* suffix)
c2646906
A
676{
677 struct stat statBuffer;
d696c285
A
678 for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin();
679 it != fFrameworkSearchPaths.end();
680 it++) {
681 // ??? Shouldn't we be using String here and just initializing it?
682 // ??? Use str.c_str () to pull out the string for the stat call.
c2646906 683 const char* dir = *it;
74cfe461 684 char possiblePath[PATH_MAX];
c2646906
A
685 strcpy(possiblePath, dir);
686 strcat(possiblePath, "/");
687 strcat(possiblePath, rootName);
688 strcat(possiblePath, ".framework/");
689 strcat(possiblePath, rootName);
74cfe461
A
690 if ( suffix != NULL ) {
691 char realPath[PATH_MAX];
692 // no symlink in framework to suffix variants, so follow main symlink
693 if ( realpath(possiblePath, realPath) != NULL ) {
694 strcpy(possiblePath, realPath);
695 strcat(possiblePath, suffix);
696 }
697 }
d696c285
A
698 bool found = (stat(possiblePath, &statBuffer) == 0);
699 if ( fTraceDylibSearching )
700 printf("[Logging for XBS]%sfound framework: '%s'\n",
701 (found ? " " : " not "), possiblePath);
702 if ( found ) {
c2646906
A
703 FileInfo result;
704 result.path = strdup(possiblePath);
705 result.fileLen = statBuffer.st_size;
d696c285 706 result.modTime = statBuffer.st_mtime;
c2646906
A
707 return result;
708 }
709 }
74cfe461 710 // try without suffix
a61fdf0a 711 if ( suffix != NULL )
74cfe461
A
712 return findFramework(rootName, NULL);
713 else
714 throwf("framework not found %s", rootName);
c2646906
A
715}
716
a645023d 717Options::FileInfo Options::findFile(const char* path) const
c2646906 718{
6e880c60 719 FileInfo result;
c2646906 720 struct stat statBuffer;
d696c285 721
6e880c60
A
722 // if absolute path and not a .o file, the use SDK prefix
723 if ( (path[0] == '/') && (strcmp(&path[strlen(path)-2], ".o") != 0) ) {
724 const int pathLen = strlen(path);
a645023d 725 for (std::vector<const char*>::const_iterator it = fSDKPaths.begin(); it != fSDKPaths.end(); it++) {
d696c285 726 // ??? Shouldn't we be using String here?
6e880c60
A
727 const char* sdkPathDir = *it;
728 const int sdkPathDirLen = strlen(sdkPathDir);
729 char possiblePath[sdkPathDirLen+pathLen+4];
730 strcpy(possiblePath, sdkPathDir);
731 if ( possiblePath[sdkPathDirLen-1] == '/' )
732 possiblePath[sdkPathDirLen-1] = '\0';
733 strcat(possiblePath, path);
734 if ( stat(possiblePath, &statBuffer) == 0 ) {
735 result.path = strdup(possiblePath);
736 result.fileLen = statBuffer.st_size;
d696c285 737 result.modTime = statBuffer.st_mtime;
6e880c60
A
738 return result;
739 }
740 }
741 }
742 // try raw path
c2646906 743 if ( stat(path, &statBuffer) == 0 ) {
c2646906
A
744 result.path = strdup(path);
745 result.fileLen = statBuffer.st_size;
d696c285 746 result.modTime = statBuffer.st_mtime;
c2646906
A
747 return result;
748 }
d696c285
A
749
750 // try @executable_path substitution
751 if ( (strncmp(path, "@executable_path/", 17) == 0) && (fExecutablePath != NULL) ) {
752 char newPath[strlen(fExecutablePath) + strlen(path)];
753 strcpy(newPath, fExecutablePath);
754 char* addPoint = strrchr(newPath,'/');
755 if ( addPoint != NULL )
756 strcpy(&addPoint[1], &path[17]);
757 else
758 strcpy(newPath, &path[17]);
759 if ( stat(newPath, &statBuffer) == 0 ) {
760 result.path = strdup(newPath);
761 result.fileLen = statBuffer.st_size;
762 result.modTime = statBuffer.st_mtime;
763 return result;
764 }
765 }
766
6e880c60
A
767 // not found
768 throwf("file not found: %s", path);
c2646906
A
769}
770
a645023d 771Options::FileInfo Options::findFileUsingPaths(const char* path) const
a61fdf0a
A
772{
773 FileInfo result;
774
775 const char* lastSlash = strrchr(path, '/');
776 const char* leafName = (lastSlash == NULL) ? path : &lastSlash[1];
777
778 // Is this in a framework?
779 // /path/Foo.framework/Foo ==> true (Foo)
780 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
781 // /path/Foo.framework/Resources/Bar ==> false
782 bool isFramework = false;
783 if ( lastSlash != NULL ) {
784 char frameworkDir[strlen(leafName) + 20];
785 strcpy(frameworkDir, "/");
786 strcat(frameworkDir, leafName);
787 strcat(frameworkDir, ".framework/");
788 if ( strstr(path, frameworkDir) != NULL )
789 isFramework = true;
790 }
791
792 // These are abbreviated versions of the routines findFramework and findLibrary above
793 // because we already know the final name of the file that we're looking for and so
794 // don't need to try variations, just paths. We do need to add the additional bits
795 // onto the framework path though.
796 if ( isFramework ) {
a645023d 797 for (std::vector<const char*>::const_iterator it = fFrameworkSearchPaths.begin();
a61fdf0a
A
798 it != fFrameworkSearchPaths.end();
799 it++) {
800 const char* dir = *it;
801 char possiblePath[PATH_MAX];
802 strcpy(possiblePath, dir);
803 strcat(possiblePath, "/");
804 strcat(possiblePath, leafName);
805 strcat(possiblePath, ".framework");
806
807 //fprintf(stderr,"Finding Framework: %s/%s, leafName=%s\n", possiblePath, leafName, leafName);
808 if ( checkForFile("%s/%s", possiblePath, leafName, result) )
809 return result;
810 }
811 }
812 else {
2f2f92e4
A
813 // if this is a .dylib inside a framework, do not search -L paths
814 // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
815 int leafLen = strlen(leafName);
816 bool embeddedDylib = ( (leafLen > 6)
817 && (strcmp(&leafName[leafLen-6], ".dylib") == 0)
818 && (strstr(path, ".framework/") != NULL) );
819 if ( !embeddedDylib ) {
a645023d 820 for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
2f2f92e4
A
821 it != fLibrarySearchPaths.end();
822 it++) {
823 const char* dir = *it;
824 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
825 if ( checkForFile("%s/%s", dir, leafName, result) )
826 return result;
827 }
a61fdf0a
A
828 }
829 }
830
831 // If we didn't find it fall back to findFile.
832 return findFile(path);
833}
834
835
a645023d 836void Options::parseSegAddrTable(const char* segAddrPath, const char* installPth)
a61fdf0a
A
837{
838 FILE* file = fopen(segAddrPath, "r");
839 if ( file == NULL ) {
2f2f92e4 840 warning("-seg_addr_table file cannot be read: %s", segAddrPath);
a61fdf0a
A
841 return;
842 }
843
844 char path[PATH_MAX];
845 uint64_t firstColumAddress = 0;
846 uint64_t secondColumAddress = 0;
847 bool hasSecondColumn = false;
848 while ( fgets(path, PATH_MAX, file) != NULL ) {
849 path[PATH_MAX-1] = '\0';
850 char* eol = strchr(path, '\n');
851 if ( eol != NULL )
852 *eol = '\0';
853 // ignore lines not starting with 0x number
854 if ( (path[0] == '0') && (path[1] == 'x') ) {
855 char* p;
856 firstColumAddress = strtoull(path, &p, 16);
857 while ( isspace(*p) )
858 ++p;
859 // see if second column is a number
860 if ( (p[0] == '0') && (p[1] == 'x') ) {
861 secondColumAddress = strtoull(p, &p, 16);
862 hasSecondColumn = true;
863 while ( isspace(*p) )
864 ++p;
865 }
866 while ( isspace(*p) )
867 ++p;
868 if ( p[0] == '/' ) {
869 // remove any trailing whitespace
870 for(char* end = eol-1; (end > p) && isspace(*end); --end)
871 *end = '\0';
872 // see if this line is for the dylib being linked
a645023d 873 if ( strcmp(p, installPth) == 0 ) {
a61fdf0a
A
874 fBaseAddress = firstColumAddress;
875 if ( hasSecondColumn ) {
876 fBaseWritableAddress = secondColumAddress;
877 fSplitSegs = true;
878 }
879 break; // out of while loop
880 }
881 }
882 }
883 }
884
885 fclose(file);
886}
6e880c60 887
c2646906
A
888void Options::loadFileList(const char* fileOfPaths)
889{
69a49097
A
890 FILE* file;
891 const char* comma = strrchr(fileOfPaths, ',');
892 const char* prefix = NULL;
893 if ( comma != NULL ) {
55e3d2f6
A
894 // <rdar://problem/5907981> -filelist fails with comma in path
895 file = fopen(fileOfPaths, "r");
896 if ( file == NULL ) {
897 prefix = comma+1;
898 int realFileOfPathsLen = comma-fileOfPaths;
899 char realFileOfPaths[realFileOfPathsLen+1];
900 strncpy(realFileOfPaths,fileOfPaths, realFileOfPathsLen);
901 realFileOfPaths[realFileOfPathsLen] = '\0';
902 file = fopen(realFileOfPaths, "r");
903 if ( file == NULL )
904 throwf("-filelist file not found: %s\n", realFileOfPaths);
905 }
69a49097
A
906 }
907 else {
908 file = fopen(fileOfPaths, "r");
909 if ( file == NULL )
910 throwf("-filelist file not found: %s\n", fileOfPaths);
911 }
d696c285 912
69a49097 913 char path[PATH_MAX];
a61fdf0a 914 while ( fgets(path, PATH_MAX, file) != NULL ) {
69a49097 915 path[PATH_MAX-1] = '\0';
c2646906
A
916 char* eol = strchr(path, '\n');
917 if ( eol != NULL )
918 *eol = '\0';
69a49097
A
919 if ( prefix != NULL ) {
920 char builtPath[strlen(prefix)+strlen(path)+2];
921 strcpy(builtPath, prefix);
922 strcat(builtPath, "/");
923 strcat(builtPath, path);
924 fInputFiles.push_back(findFile(builtPath));
925 }
926 else {
927 fInputFiles.push_back(findFile(path));
928 }
c2646906
A
929 }
930 fclose(file);
931}
932
a645023d
A
933
934void Options::SetWithWildcards::remove(const NameSet& toBeRemoved)
935{
936 for(NameSet::const_iterator it=toBeRemoved.begin(); it != toBeRemoved.end(); ++it) {
937 const char* symbolName = *it;
938 NameSet::iterator pos = fRegular.find(symbolName);
939 if ( pos != fRegular.end() )
940 fRegular.erase(pos);
941 }
942}
943
944bool Options::SetWithWildcards::hasWildCards(const char* symbol)
a61fdf0a
A
945{
946 // an exported symbol name containing *, ?, or [ requires wildcard matching
947 return ( strpbrk(symbol, "*?[") != NULL );
948}
949
950void Options::SetWithWildcards::insert(const char* symbol)
951{
952 if ( hasWildCards(symbol) )
953 fWildCard.push_back(symbol);
954 else
955 fRegular.insert(symbol);
956}
957
a645023d 958bool Options::SetWithWildcards::contains(const char* symbol) const
a61fdf0a
A
959{
960 // first look at hash table on non-wildcard symbols
961 if ( fRegular.find(symbol) != fRegular.end() )
962 return true;
963 // next walk list of wild card symbols looking for a match
a645023d 964 for(std::vector<const char*>::const_iterator it = fWildCard.begin(); it != fWildCard.end(); ++it) {
a61fdf0a
A
965 if ( wildCardMatch(*it, symbol) )
966 return true;
967 }
968 return false;
969}
970
a645023d
A
971bool Options::SetWithWildcards::containsNonWildcard(const char* symbol) const
972{
973 // look at hash table on non-wildcard symbols
974 return ( fRegular.find(symbol) != fRegular.end() );
975}
976
977
a61fdf0a 978
a645023d 979bool Options::SetWithWildcards::inCharRange(const char*& p, unsigned char c) const
a61fdf0a
A
980{
981 ++p; // find end
982 const char* b = p;
983 while ( *p != '\0' ) {
984 if ( *p == ']') {
985 const char* e = p;
986 // found beginining [ and ending ]
987 unsigned char last = '\0';
988 for ( const char* s = b; s < e; ++s ) {
989 if ( *s == '-' ) {
990 unsigned char next = *(++s);
991 if ( (last <= c) && (c <= next) )
992 return true;
993 ++s;
994 }
995 else {
996 if ( *s == c )
997 return true;
998 last = *s;
999 }
1000 }
1001 return false;
1002 }
1003 ++p;
1004 }
1005 return false;
1006}
1007
a645023d 1008bool Options::SetWithWildcards::wildCardMatch(const char* pattern, const char* symbol) const
a61fdf0a
A
1009{
1010 const char* s = symbol;
1011 for (const char* p = pattern; *p != '\0'; ++p) {
1012 switch ( *p ) {
1013 case '*':
1014 if ( p[1] == '\0' )
1015 return true;
1016 for (const char* t = s; *t != '\0'; ++t) {
1017 if ( wildCardMatch(&p[1], t) )
1018 return true;
1019 }
1020 return false;
1021 case '?':
1022 if ( *s == '\0' )
1023 return false;
1024 ++s;
1025 break;
1026 case '[':
1027 if ( ! inCharRange(p, *s) )
1028 return false;
1029 ++s;
1030 break;
1031 default:
1032 if ( *s != *p )
1033 return false;
1034 ++s;
1035 }
1036 }
1037 return (*s == '\0');
1038}
1039
c2646906 1040
a61fdf0a 1041void Options::loadExportFile(const char* fileOfExports, const char* option, SetWithWildcards& set)
c2646906 1042{
a645023d
A
1043 if ( fileOfExports == NULL )
1044 throwf("missing file after %s", option);
c2646906
A
1045 // read in whole file
1046 int fd = ::open(fileOfExports, O_RDONLY, 0);
1047 if ( fd == -1 )
1048 throwf("can't open %s file: %s", option, fileOfExports);
1049 struct stat stat_buf;
1050 ::fstat(fd, &stat_buf);
1051 char* p = (char*)malloc(stat_buf.st_size);
1052 if ( p == NULL )
1053 throwf("can't process %s file: %s", option, fileOfExports);
d696c285 1054
c2646906
A
1055 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1056 throwf("can't read %s file: %s", option, fileOfExports);
d696c285 1057
c2646906 1058 ::close(fd);
d696c285 1059
c2646906
A
1060 // parse into symbols and add to hash_set
1061 char * const end = &p[stat_buf.st_size];
1062 enum { lineStart, inSymbol, inComment } state = lineStart;
1063 char* symbolStart = NULL;
1064 for (char* s = p; s < end; ++s ) {
1065 switch ( state ) {
d696c285
A
1066 case lineStart:
1067 if ( *s =='#' ) {
1068 state = inComment;
1069 }
1070 else if ( !isspace(*s) ) {
1071 state = inSymbol;
1072 symbolStart = s;
1073 }
1074 break;
1075 case inSymbol:
a61fdf0a 1076 if ( (*s == '\n') || (*s == '\r') ) {
d696c285
A
1077 *s = '\0';
1078 // removing any trailing spaces
1079 char* last = s-1;
1080 while ( isspace(*last) ) {
1081 *last = '\0';
1082 --last;
c2646906 1083 }
d696c285
A
1084 set.insert(symbolStart);
1085 symbolStart = NULL;
1086 state = lineStart;
1087 }
1088 break;
1089 case inComment:
a61fdf0a 1090 if ( (*s == '\n') || (*s == '\r') )
d696c285
A
1091 state = lineStart;
1092 break;
1093 }
1094 }
1095 if ( state == inSymbol ) {
2f2f92e4 1096 warning("missing line-end at end of file \"%s\"", fileOfExports);
d696c285
A
1097 int len = end-symbolStart+1;
1098 char* temp = new char[len];
1099 strlcpy(temp, symbolStart, len);
1100
1101 // remove any trailing spaces
1102 char* last = &temp[len-2];
1103 while ( isspace(*last) ) {
1104 *last = '\0';
1105 --last;
c2646906 1106 }
d696c285 1107 set.insert(temp);
c2646906 1108 }
d696c285 1109
c2646906
A
1110 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
1111}
1112
a61fdf0a
A
1113void Options::parseAliasFile(const char* fileOfAliases)
1114{
1115 // read in whole file
1116 int fd = ::open(fileOfAliases, O_RDONLY, 0);
1117 if ( fd == -1 )
1118 throwf("can't open alias file: %s", fileOfAliases);
1119 struct stat stat_buf;
1120 ::fstat(fd, &stat_buf);
1121 char* p = (char*)malloc(stat_buf.st_size+1);
1122 if ( p == NULL )
1123 throwf("can't process alias file: %s", fileOfAliases);
1124
1125 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1126 throwf("can't read alias file: %s", fileOfAliases);
1127 p[stat_buf.st_size] = '\n';
1128 ::close(fd);
1129
1130 // parse into symbols and add to fAliases
a645023d 1131 AliasPair pair;
a61fdf0a
A
1132 char * const end = &p[stat_buf.st_size+1];
1133 enum { lineStart, inRealName, inBetween, inAliasName, inComment } state = lineStart;
1134 int lineNumber = 1;
1135 for (char* s = p; s < end; ++s ) {
1136 switch ( state ) {
1137 case lineStart:
1138 if ( *s =='#' ) {
1139 state = inComment;
1140 }
1141 else if ( !isspace(*s) ) {
1142 state = inRealName;
1143 pair.realName = s;
1144 }
1145 break;
1146 case inRealName:
1147 if ( *s == '\n' ) {
2f2f92e4 1148 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber, fileOfAliases);
a61fdf0a
A
1149 ++lineNumber;
1150 state = lineStart;
1151 }
1152 else if ( isspace(*s) ) {
1153 *s = '\0';
1154 state = inBetween;
1155 }
1156 break;
1157 case inBetween:
1158 if ( *s == '\n' ) {
2f2f92e4 1159 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber, fileOfAliases);
a61fdf0a
A
1160 ++lineNumber;
1161 state = lineStart;
1162 }
1163 else if ( ! isspace(*s) ) {
1164 state = inAliasName;
1165 pair.alias = s;
1166 }
1167 break;
1168 case inAliasName:
1169 if ( *s =='#' ) {
1170 *s = '\0';
1171 // removing any trailing spaces
1172 char* last = s-1;
1173 while ( isspace(*last) ) {
1174 *last = '\0';
1175 --last;
1176 }
a645023d 1177 fAliases.push_back(pair);
a61fdf0a
A
1178 state = inComment;
1179 }
1180 else if ( *s == '\n' ) {
1181 *s = '\0';
1182 // removing any trailing spaces
1183 char* last = s-1;
1184 while ( isspace(*last) ) {
1185 *last = '\0';
1186 --last;
1187 }
a645023d 1188 fAliases.push_back(pair);
a61fdf0a
A
1189 state = lineStart;
1190 }
1191 break;
1192 case inComment:
1193 if ( *s == '\n' )
1194 state = lineStart;
1195 break;
1196 }
1197 }
1198
1199 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
1200}
1201
1202
1203
c2646906
A
1204void Options::setUndefinedTreatment(const char* treatment)
1205{
d696c285 1206 if ( treatment == NULL )
c2646906
A
1207 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
1208
1209 if ( strcmp(treatment, "warning") == 0 )
1210 fUndefinedTreatment = kUndefinedWarning;
1211 else if ( strcmp(treatment, "error") == 0 )
1212 fUndefinedTreatment = kUndefinedError;
1213 else if ( strcmp(treatment, "suppress") == 0 )
1214 fUndefinedTreatment = kUndefinedSuppress;
1215 else if ( strcmp(treatment, "dynamic_lookup") == 0 )
1216 fUndefinedTreatment = kUndefinedDynamicLookup;
1217 else
1218 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1219}
1220
d696c285 1221Options::Treatment Options::parseTreatment(const char* treatment)
c2646906 1222{
d696c285
A
1223 if ( treatment == NULL )
1224 return kNULL;
c2646906
A
1225
1226 if ( strcmp(treatment, "warning") == 0 )
d696c285
A
1227 return kWarning;
1228 else if ( strcmp(treatment, "error") == 0 )
1229 return kError;
c2646906 1230 else if ( strcmp(treatment, "suppress") == 0 )
d696c285
A
1231 return kSuppress;
1232 else
1233 return kInvalid;
c2646906
A
1234}
1235
2f2f92e4 1236void Options::setMacOSXVersionMin(const char* version)
d696c285
A
1237{
1238 if ( version == NULL )
1239 throw "-macosx_version_min argument missing";
1240
69a49097 1241 if ( (strncmp(version, "10.", 3) == 0) && isdigit(version[3]) ) {
a645023d
A
1242 unsigned int minorVersion = version[3] - '0';
1243 fMacVersionMin = (ld::MacVersionMin)(0x000A0000 | (minorVersion << 8));
69a49097
A
1244 }
1245 else {
2f2f92e4
A
1246 warning("unknown option to -macosx_version_min, not 10.x");
1247 }
1248}
1249
afe874b1 1250void Options::setIOSVersionMin(const char* version)
2f2f92e4
A
1251{
1252 if ( version == NULL )
a645023d 1253 throw "-ios_version_min argument missing";
fb24a050 1254 if ( ! isdigit(version[0]) )
a645023d 1255 throw "-ios_version_min argument is not a number";
fb24a050 1256 if ( version[1] != '.' )
a645023d 1257 throw "-ios_version_min argument is missing period as second character";
fb24a050 1258 if ( ! isdigit(version[2]) )
a645023d
A
1259 throw "-ios_version_min argument is not a number";
1260
1261 unsigned int majorVersion = version[0] - '0';
1262 unsigned int minorVersion = version[2] - '0';
afe874b1 1263 fIOSVersionMin = (ld::IOSVersionMin)((majorVersion << 16) | (minorVersion << 8));
55e3d2f6
A
1264}
1265
afe874b1 1266bool Options::minOS(ld::MacVersionMin requiredMacMin, ld::IOSVersionMin requirediPhoneOSMin)
55e3d2f6 1267{
a645023d
A
1268 if ( fMacVersionMin != ld::macVersionUnset ) {
1269 return ( fMacVersionMin >= requiredMacMin );
55e3d2f6
A
1270 }
1271 else {
afe874b1 1272 return ( fIOSVersionMin >= requirediPhoneOSMin);
69a49097 1273 }
c2646906
A
1274}
1275
55e3d2f6 1276
c2646906
A
1277void Options::setWeakReferenceMismatchTreatment(const char* treatment)
1278{
d696c285 1279 if ( treatment == NULL )
c2646906
A
1280 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1281
1282 if ( strcmp(treatment, "error") == 0 )
1283 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchError;
1284 else if ( strcmp(treatment, "weak") == 0 )
1285 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchWeak;
1286 else if ( strcmp(treatment, "non-weak") == 0 )
1287 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchNonWeak;
1288 else
1289 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1290}
1291
1292Options::CommonsMode Options::parseCommonsTreatment(const char* mode)
1293{
d696c285 1294 if ( mode == NULL )
c2646906
A
1295 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1296
1297 if ( strcmp(mode, "ignore_dylibs") == 0 )
1298 return kCommonsIgnoreDylibs;
1299 else if ( strcmp(mode, "use_dylibs") == 0 )
1300 return kCommonsOverriddenByDylibs;
1301 else if ( strcmp(mode, "error") == 0 )
1302 return kCommonsConflictsDylibsError;
1303 else
1304 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1305}
1306
a61fdf0a 1307void Options::addDylibOverride(const char* paths)
c2646906 1308{
a61fdf0a
A
1309 if ( paths == NULL )
1310 throw "-dylib_file must followed by two colon separated paths";
1311 const char* colon = strchr(paths, ':');
1312 if ( colon == NULL )
1313 throw "-dylib_file must followed by two colon separated paths";
1314 int len = colon-paths;
1315 char* target = new char[len+2];
1316 strncpy(target, paths, len);
1317 target[len] = '\0';
1318 DylibOverride entry;
1319 entry.installName = target;
1320 entry.useInstead = &colon[1];
1321 fDylibOverrides.push_back(entry);
c2646906
A
1322}
1323
c2646906
A
1324uint64_t Options::parseAddress(const char* addr)
1325{
1326 char* endptr;
1327 uint64_t result = strtoull(addr, &endptr, 16);
1328 return result;
1329}
1330
a61fdf0a
A
1331uint32_t Options::parseProtection(const char* prot)
1332{
1333 uint32_t result = 0;
1334 for(const char* p = prot; *p != '\0'; ++p) {
1335 switch(tolower(*p)) {
1336 case 'r':
1337 result |= VM_PROT_READ;
1338 break;
1339 case 'w':
1340 result |= VM_PROT_WRITE;
1341 break;
1342 case 'x':
1343 result |= VM_PROT_EXECUTE;
1344 break;
1345 case '-':
1346 break;
1347 default:
1348 throwf("unknown -segprot lettter in %s", prot);
1349 }
1350 }
1351 return result;
1352}
1353
1354
b2fa67a8
A
1355//
1356// Parses number of form A[.B[.B[.D[.E]]]] into a uint64_t where the bits are a24.b10.c10.d10.e10
1357//
1358uint64_t Options::parseVersionNumber64(const char* versionString)
1359{
1360 uint64_t a = 0;
1361 uint64_t b = 0;
1362 uint64_t c = 0;
1363 uint64_t d = 0;
1364 uint64_t e = 0;
1365 char* end;
1366 a = strtoul(versionString, &end, 10);
1367 if ( *end == '.' ) {
1368 b = strtoul(&end[1], &end, 10);
1369 if ( *end == '.' ) {
1370 c = strtoul(&end[1], &end, 10);
1371 if ( *end == '.' ) {
1372 d = strtoul(&end[1], &end, 10);
1373 if ( *end == '.' ) {
1374 e = strtoul(&end[1], &end, 10);
1375 }
1376 }
1377 }
1378 }
1379 if ( (*end != '\0') || (a > 0xFFFFFF) || (b > 0x3FF) || (c > 0x3FF) || (d > 0x3FF) || (e > 0x3FF) )
1380 throwf("malformed 64-bit a.b.c.d.e version number: %s", versionString);
1381
1382 return (a << 40) | ( b << 30 ) | ( c << 20 ) | ( d << 10 ) | e;
1383}
1384
1385
1386uint32_t Options::currentVersion32() const
1387{
1388 // warn if it does not fit into 32 bit vers number
1389 uint32_t a = (fDylibCurrentVersion >> 40) & 0xFFFF;
1390 uint32_t b = (fDylibCurrentVersion >> 30) & 0xFF;
1391 uint32_t c = (fDylibCurrentVersion >> 20) & 0xFF;
1392 uint64_t rep32 = ((uint64_t)a << 40) | ((uint64_t)b << 30) | ((uint64_t)c << 20);
1393 if ( rep32 != fDylibCurrentVersion ) {
1394 warning("truncating -current_version to fit in 32-bit space used by old mach-o format");
1395 a = (fDylibCurrentVersion >> 40) & 0xFFFFFF;
1396 if ( a > 0xFFFF )
1397 a = 0xFFFF;
1398 b = (fDylibCurrentVersion >> 30) & 0x3FF;
1399 if ( b > 0xFF )
1400 b = 0xFF;
1401 c = (fDylibCurrentVersion >> 20) & 0x3FF;
1402 if ( c > 0xFF )
1403 c = 0xFF;
1404 }
1405 return (a << 16) | ( b << 8 ) | c;
1406}
a61fdf0a 1407
c2646906 1408//
d696c285 1409// Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
c2646906 1410//
b2fa67a8 1411uint32_t Options::parseVersionNumber32(const char* versionString)
c2646906 1412{
b2fa67a8
A
1413 uint32_t x = 0;
1414 uint32_t y = 0;
1415 uint32_t z = 0;
c2646906
A
1416 char* end;
1417 x = strtoul(versionString, &end, 10);
1418 if ( *end == '.' ) {
1419 y = strtoul(&end[1], &end, 10);
1420 if ( *end == '.' ) {
1421 z = strtoul(&end[1], &end, 10);
1422 }
1423 }
1424 if ( (*end != '\0') || (x > 0xffff) || (y > 0xff) || (z > 0xff) )
b2fa67a8 1425 throwf("malformed 32-bit x.y.z version number: %s", versionString);
c2646906
A
1426
1427 return (x << 16) | ( y << 8 ) | z;
1428}
1429
a61fdf0a
A
1430static const char* cstringSymbolName(const char* orderFileString)
1431{
1432 char* result;
1433 asprintf(&result, "cstring=%s", orderFileString);
1434 // convert escaped characters
1435 char* d = result;
1436 for(const char* s=result; *s != '\0'; ++s, ++d) {
1437 if ( *s == '\\' ) {
1438 ++s;
1439 switch ( *s ) {
1440 case 'n':
1441 *d = '\n';
1442 break;
1443 case 't':
1444 *d = '\t';
1445 break;
1446 case 'v':
1447 *d = '\v';
1448 break;
1449 case 'b':
1450 *d = '\b';
1451 break;
1452 case 'r':
1453 *d = '\r';
1454 break;
1455 case 'f':
1456 *d = '\f';
1457 break;
1458 case 'a':
1459 *d = '\a';
1460 break;
1461 case '\\':
1462 *d = '\\';
1463 break;
1464 case '?':
1465 *d = '\?';
1466 break;
1467 case '\'':
1468 *d = '\r';
1469 break;
1470 case '\"':
1471 *d = '\"';
1472 break;
1473 case 'x':
1474 // hexadecimal value of char
1475 {
1476 ++s;
1477 char value = 0;
1478 while ( isxdigit(*s) ) {
1479 value *= 16;
1480 if ( isdigit(*s) )
1481 value += (*s-'0');
1482 else
1483 value += ((toupper(*s)-'A') + 10);
1484 ++s;
1485 }
1486 *d = value;
1487 }
1488 break;
1489 default:
1490 if ( isdigit(*s) ) {
1491 // octal value of char
1492 char value = 0;
1493 while ( isdigit(*s) ) {
1494 value = (value << 3) + (*s-'0');
1495 ++s;
1496 }
1497 *d = value;
1498 }
1499 }
1500 }
1501 else {
1502 *d = *s;
1503 }
1504 }
1505 *d = '\0';
1506 return result;
1507}
1508
1509void Options::parseOrderFile(const char* path, bool cstring)
1510{
55e3d2f6 1511 // order files override auto-ordering
a645023d 1512 fAutoOrderInitializers = false;
55e3d2f6 1513
a61fdf0a
A
1514 // read in whole file
1515 int fd = ::open(path, O_RDONLY, 0);
1516 if ( fd == -1 )
1517 throwf("can't open order file: %s", path);
1518 struct stat stat_buf;
1519 ::fstat(fd, &stat_buf);
1520 char* p = (char*)malloc(stat_buf.st_size+1);
1521 if ( p == NULL )
1522 throwf("can't process order file: %s", path);
1523 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1524 throwf("can't read order file: %s", path);
1525 ::close(fd);
1526 p[stat_buf.st_size] = '\n';
1527
1528 // parse into vector of pairs
1529 char * const end = &p[stat_buf.st_size+1];
1530 enum { lineStart, inSymbol, inComment } state = lineStart;
1531 char* symbolStart = NULL;
1532 for (char* s = p; s < end; ++s ) {
1533 switch ( state ) {
1534 case lineStart:
1535 if ( *s =='#' ) {
1536 state = inComment;
1537 }
1538 else if ( !isspace(*s) || cstring ) {
1539 state = inSymbol;
1540 symbolStart = s;
1541 }
1542 break;
1543 case inSymbol:
1544 if ( (*s == '\n') || (!cstring && (*s == '#')) ) {
1545 bool wasComment = (*s == '#');
1546 *s = '\0';
1547 // removing any trailing spaces
1548 char* last = s-1;
1549 while ( isspace(*last) ) {
1550 *last = '\0';
1551 --last;
1552 }
b2fa67a8 1553 // if there is an architecture prefix, only use this symbol it if matches current arch
a61fdf0a 1554 if ( strncmp(symbolStart, "ppc:", 4) == 0 ) {
b2fa67a8 1555 symbolStart = NULL;
a61fdf0a 1556 }
a61fdf0a 1557 else if ( strncmp(symbolStart, "ppc64:", 6) == 0 ) {
b2fa67a8 1558 symbolStart = NULL;
a61fdf0a
A
1559 }
1560 else if ( strncmp(symbolStart, "i386:", 5) == 0 ) {
1561 if ( fArchitecture == CPU_TYPE_I386 )
1562 symbolStart = &symbolStart[5];
1563 else
1564 symbolStart = NULL;
1565 }
1566 else if ( strncmp(symbolStart, "x86_64:", 7) == 0 ) {
1567 if ( fArchitecture == CPU_TYPE_X86_64 )
1568 symbolStart = &symbolStart[7];
1569 else
1570 symbolStart = NULL;
1571 }
2f2f92e4
A
1572 else if ( strncmp(symbolStart, "arm:", 4) == 0 ) {
1573 if ( fArchitecture == CPU_TYPE_ARM )
1574 symbolStart = &symbolStart[4];
1575 else
1576 symbolStart = NULL;
1577 }
a61fdf0a
A
1578 if ( symbolStart != NULL ) {
1579 char* objFileName = NULL;
1580 char* colon = strstr(symbolStart, ".o:");
1581 if ( colon != NULL ) {
1582 colon[2] = '\0';
1583 objFileName = symbolStart;
1584 symbolStart = &colon[3];
1585 }
1586 // trim leading spaces
1587 while ( isspace(*symbolStart) )
1588 ++symbolStart;
1589 Options::OrderedSymbol pair;
1590 if ( cstring )
1591 pair.symbolName = cstringSymbolName(symbolStart);
1592 else
1593 pair.symbolName = symbolStart;
1594 pair.objectFileName = objFileName;
1595 fOrderedSymbols.push_back(pair);
1596 }
1597 symbolStart = NULL;
1598 if ( wasComment )
1599 state = inComment;
1600 else
1601 state = lineStart;
1602 }
1603 break;
1604 case inComment:
1605 if ( *s == '\n' )
1606 state = lineStart;
1607 break;
1608 }
1609 }
1610 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1611}
1612
c2646906
A
1613void Options::parseSectionOrderFile(const char* segment, const char* section, const char* path)
1614{
a61fdf0a
A
1615 if ( (strcmp(section, "__cstring") == 0) && (strcmp(segment, "__TEXT") == 0) ) {
1616 parseOrderFile(path, true);
1617 }
1618 else if ( (strncmp(section, "__literal",9) == 0) && (strcmp(segment, "__TEXT") == 0) ) {
2f2f92e4 1619 warning("sorting of __literal[4,8,16] sections not supported");
a61fdf0a
A
1620 }
1621 else {
1622 // ignore section information and append all symbol names to global order file
1623 parseOrderFile(path, false);
1624 }
c2646906
A
1625}
1626
1627void Options::addSection(const char* segment, const char* section, const char* path)
1628{
1629 if ( strlen(segment) > 16 )
1630 throw "-seccreate segment name max 16 chars";
d696c285
A
1631 if ( strlen(section) > 16 ) {
1632 char* tmp = strdup(section);
1633 tmp[16] = '\0';
2f2f92e4 1634 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section, tmp);
d696c285
A
1635 section = tmp;
1636 }
c2646906
A
1637
1638 // read in whole file
1639 int fd = ::open(path, O_RDONLY, 0);
1640 if ( fd == -1 )
1641 throwf("can't open -sectcreate file: %s", path);
1642 struct stat stat_buf;
1643 ::fstat(fd, &stat_buf);
1644 char* p = (char*)malloc(stat_buf.st_size);
1645 if ( p == NULL )
1646 throwf("can't process -sectcreate file: %s", path);
1647 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1648 throwf("can't read -sectcreate file: %s", path);
1649 ::close(fd);
d696c285 1650
c2646906
A
1651 // record section to create
1652 ExtraSection info = { segment, section, path, (uint8_t*)p, stat_buf.st_size };
1653 fExtraSections.push_back(info);
1654}
1655
1656void Options::addSectionAlignment(const char* segment, const char* section, const char* alignmentStr)
1657{
1658 if ( strlen(segment) > 16 )
1659 throw "-sectalign segment name max 16 chars";
1660 if ( strlen(section) > 16 )
1661 throw "-sectalign section name max 16 chars";
1662
d696c285 1663 // argument to -sectalign is a hexadecimal number
c2646906
A
1664 char* endptr;
1665 unsigned long value = strtoul(alignmentStr, &endptr, 16);
1666 if ( *endptr != '\0')
1667 throw "argument for -sectalign is not a hexadecimal number";
1668 if ( value > 0x8000 )
1669 throw "argument for -sectalign must be less than or equal to 0x8000";
d696c285 1670 if ( value == 0 ) {
2f2f92e4 1671 warning("zero is not a valid -sectalign");
d696c285
A
1672 value = 1;
1673 }
a61fdf0a 1674
d696c285 1675 // alignment is power of 2 (e.g. page alignment = 12)
a61fdf0a 1676 uint8_t alignment = (uint8_t)__builtin_ctz(value);
d696c285 1677 if ( (unsigned long)(1 << alignment) != value ) {
2f2f92e4 1678 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
d696c285
A
1679 segment, section, 1 << alignment);
1680 }
c2646906
A
1681
1682 SectionAlignment info = { segment, section, alignment };
1683 fSectionAlignments.push_back(info);
1684}
1685
a61fdf0a
A
1686void Options::addLibrary(const FileInfo& info)
1687{
1688 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
1689 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
1690 if ( strcmp(info.path, fit->path) == 0 ) {
1691 // if dylib is specified again but weak, record that it should be weak
1692 if ( info.options.fWeakImport )
1693 fit->options.fWeakImport = true;
1694 return;
1695 }
1696 }
1697 // add to list
1698 fInputFiles.push_back(info);
1699}
1700
1701void Options::warnObsolete(const char* arg)
1702{
2f2f92e4 1703 warning("option %s is obsolete and being ignored", arg);
a61fdf0a
A
1704}
1705
1706
1707
1708
d696c285
A
1709//
1710// Process all command line arguments.
1711//
1712// The only error checking done here is that each option is valid and if it has arguments
1713// that they too are valid.
1714//
1715// The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
1716// whichever was last on the command line is used.
1717//
1718// Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
1719//
c2646906
A
1720void Options::parse(int argc, const char* argv[])
1721{
1722 // pass one builds search list from -L and -F options
1723 this->buildSearchPaths(argc, argv);
d696c285
A
1724
1725 // reduce re-allocations
1726 fInputFiles.reserve(32);
1727
c2646906
A
1728 // pass two parse all other options
1729 for(int i=1; i < argc; ++i) {
1730 const char* arg = argv[i];
d696c285 1731
c2646906 1732 if ( arg[0] == '-' ) {
d696c285
A
1733
1734 // Since we don't care about the files passed, just the option names, we do this here.
1735 if (fPrintOptions)
1736 fprintf (stderr, "[Logging ld64 options]\t%s\n", arg);
1737
c2646906 1738 if ( (arg[1] == 'L') || (arg[1] == 'F') ) {
a645023d
A
1739 if (arg[2] == '\0')
1740 ++i;
6e880c60 1741 // previously handled by buildSearchPaths()
c2646906 1742 }
a61fdf0a
A
1743 // The one gnu style option we have to keep compatibility
1744 // with gcc. Might as well have the single hyphen one as well.
1745 else if ( (strcmp(arg, "--help") == 0)
1746 || (strcmp(arg, "-help") == 0)) {
1747 fprintf (stdout, "ld64: For information on command line options please use 'man ld'.\n");
1748 exit (0);
1749 }
c2646906
A
1750 else if ( strcmp(arg, "-arch") == 0 ) {
1751 parseArch(argv[++i]);
1752 }
1753 else if ( strcmp(arg, "-dynamic") == 0 ) {
1754 // default
1755 }
1756 else if ( strcmp(arg, "-static") == 0 ) {
a645023d
A
1757 fForStatic = true;
1758 if ( (fOutputKind != kObjectFile) && (fOutputKind != kKextBundle) ) {
55e3d2f6
A
1759 fOutputKind = kStaticExecutable;
1760 }
c2646906
A
1761 }
1762 else if ( strcmp(arg, "-dylib") == 0 ) {
1763 fOutputKind = kDynamicLibrary;
1764 }
1765 else if ( strcmp(arg, "-bundle") == 0 ) {
1766 fOutputKind = kDynamicBundle;
1767 }
1768 else if ( strcmp(arg, "-dylinker") == 0 ) {
1769 fOutputKind = kDyld;
1770 }
1771 else if ( strcmp(arg, "-execute") == 0 ) {
1772 if ( fOutputKind != kStaticExecutable )
1773 fOutputKind = kDynamicExecutable;
1774 }
55e3d2f6
A
1775 else if ( strcmp(arg, "-preload") == 0 ) {
1776 fOutputKind = kPreload;
1777 }
c2646906
A
1778 else if ( strcmp(arg, "-r") == 0 ) {
1779 fOutputKind = kObjectFile;
1780 }
55e3d2f6
A
1781 else if ( strcmp(arg, "-kext") == 0 ) {
1782 fOutputKind = kKextBundle;
1783 }
c2646906
A
1784 else if ( strcmp(arg, "-o") == 0 ) {
1785 fOutputFile = argv[++i];
1786 }
a645023d
A
1787 else if ( strncmp(arg, "-lazy-l", 7) == 0 ) {
1788 FileInfo info = findLibrary(&arg[7], true);
1789 info.options.fLazyLoad = true;
1790 addLibrary(info);
1791 fUsingLazyDylibLinking = true;
1792 }
2f2f92e4 1793 else if ( (arg[1] == 'l') && (strncmp(arg,"-lazy_",6) !=0) ) {
a61fdf0a 1794 addLibrary(findLibrary(&arg[2]));
c2646906 1795 }
d696c285
A
1796 // This causes a dylib to be weakly bound at
1797 // link time. This corresponds to weak_import.
1798 else if ( strncmp(arg, "-weak-l", 7) == 0 ) {
1799 FileInfo info = findLibrary(&arg[7]);
c2646906 1800 info.options.fWeakImport = true;
a61fdf0a 1801 addLibrary(info);
c2646906 1802 }
d696c285 1803 // Avoid lazy binding.
c2646906
A
1804 else if ( strcmp(arg, "-bind_at_load") == 0 ) {
1805 fBindAtLoad = true;
1806 }
1807 else if ( strcmp(arg, "-twolevel_namespace") == 0 ) {
1808 fNameSpace = kTwoLevelNameSpace;
1809 }
1810 else if ( strcmp(arg, "-flat_namespace") == 0 ) {
1811 fNameSpace = kFlatNameSpace;
1812 }
d696c285
A
1813 // Also sets a bit to ensure dyld causes everything
1814 // in the namespace to be flat.
1815 // ??? Deprecate
c2646906
A
1816 else if ( strcmp(arg, "-force_flat_namespace") == 0 ) {
1817 fNameSpace = kForceFlatNameSpace;
1818 }
d696c285 1819 // Similar to --whole-archive.
c2646906 1820 else if ( strcmp(arg, "-all_load") == 0 ) {
a645023d 1821 fFullyLoadArchives = true;
c2646906 1822 }
a61fdf0a
A
1823 else if ( strcmp(arg, "-noall_load") == 0) {
1824 warnObsolete(arg);
1825 }
1826 // Similar to -all_load
c2646906 1827 else if ( strcmp(arg, "-ObjC") == 0 ) {
a645023d 1828 fLoadAllObjcObjectsFromArchives = true;
c2646906 1829 }
55e3d2f6
A
1830 // Similar to -all_load, but for the following archive only.
1831 else if ( strcmp(arg, "-force_load") == 0 ) {
1832 FileInfo info = findFile(argv[++i]);
1833 info.options.fForceLoad = true;
1834 addLibrary(info);
1835 }
d696c285 1836 // Library versioning.
a61fdf0a
A
1837 else if ( (strcmp(arg, "-dylib_compatibility_version") == 0)
1838 || (strcmp(arg, "-compatibility_version") == 0)) {
1839 const char* vers = argv[++i];
1840 if ( vers == NULL )
1841 throw "-dylib_compatibility_version missing <version>";
b2fa67a8 1842 fDylibCompatVersion = parseVersionNumber32(vers);
a61fdf0a
A
1843 }
1844 else if ( (strcmp(arg, "-dylib_current_version") == 0)
1845 || (strcmp(arg, "-current_version") == 0)) {
1846 const char* vers = argv[++i];
1847 if ( vers == NULL )
1848 throw "-dylib_current_version missing <version>";
b2fa67a8 1849 fDylibCurrentVersion = parseVersionNumber64(vers);
c2646906
A
1850 }
1851 else if ( strcmp(arg, "-sectorder") == 0 ) {
a61fdf0a
A
1852 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
1853 throw "-sectorder missing <segment> <section> <file-path>";
c2646906
A
1854 parseSectionOrderFile(argv[i+1], argv[i+2], argv[i+3]);
1855 i += 3;
1856 }
a61fdf0a
A
1857 else if ( strcmp(arg, "-order_file") == 0 ) {
1858 parseOrderFile(argv[++i], false);
1859 }
1860 else if ( strcmp(arg, "-order_file_statistics") == 0 ) {
1861 fPrintOrderFileStatistics = true;
1862 }
d696c285
A
1863 // ??? Deprecate segcreate.
1864 // -sectcreate puts whole files into a section in the output.
c2646906 1865 else if ( (strcmp(arg, "-sectcreate") == 0) || (strcmp(arg, "-segcreate") == 0) ) {
a61fdf0a
A
1866 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
1867 throw "-sectcreate missing <segment> <section> <file-path>";
c2646906
A
1868 addSection(argv[i+1], argv[i+2], argv[i+3]);
1869 i += 3;
1870 }
d696c285 1871 // Since we have a full path in binary/library names we need to be able to override it.
a61fdf0a
A
1872 else if ( (strcmp(arg, "-dylib_install_name") == 0)
1873 || (strcmp(arg, "-dylinker_install_name") == 0)
1874 || (strcmp(arg, "-install_name") == 0)) {
c2646906 1875 fDylibInstallName = argv[++i];
a61fdf0a
A
1876 if ( fDylibInstallName == NULL )
1877 throw "-install_name missing <path>";
c2646906 1878 }
d696c285 1879 // Sets the base address of the output.
69a49097 1880 else if ( (strcmp(arg, "-seg1addr") == 0) || (strcmp(arg, "-image_base") == 0) ) {
a61fdf0a
A
1881 const char* address = argv[++i];
1882 if ( address == NULL )
1883 throwf("%s missing <address>", arg);
1884 fBaseAddress = parseAddress(address);
55e3d2f6 1885 uint64_t temp = ((fBaseAddress+fSegmentAlignment-1) & (-fSegmentAlignment));
2f2f92e4 1886 if ( fBaseAddress != temp ) {
55e3d2f6 1887 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment);
2f2f92e4
A
1888 fBaseAddress = temp;
1889 }
c2646906
A
1890 }
1891 else if ( strcmp(arg, "-e") == 0 ) {
1892 fEntryName = argv[++i];
1893 }
d696c285 1894 // Same as -@ from the FSF linker.
c2646906 1895 else if ( strcmp(arg, "-filelist") == 0 ) {
a61fdf0a
A
1896 const char* path = argv[++i];
1897 if ( (path == NULL) || (path[0] == '-') )
1898 throw "-filelist missing <path>";
1899 loadFileList(path);
c2646906
A
1900 }
1901 else if ( strcmp(arg, "-keep_private_externs") == 0 ) {
1902 fKeepPrivateExterns = true;
1903 }
1904 else if ( strcmp(arg, "-final_output") == 0 ) {
a61fdf0a 1905 fFinalName = argv[++i];
c2646906 1906 }
d696c285
A
1907 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
1908 // just ensures that this happens for cross object file boundaries.
c2646906 1909 else if ( (strcmp(arg, "-interposable") == 0) || (strcmp(arg, "-multi_module") == 0)) {
2f2f92e4
A
1910 switch ( fInterposeMode ) {
1911 case kInterposeNone:
1912 case kInterposeAllExternal:
1913 fInterposeMode = kInterposeAllExternal;
1914 break;
1915 case kInterposeSome:
1916 // do nothing, -interposable_list overrides -interposable"
1917 break;
1918 }
1919 }
1920 else if ( strcmp(arg, "-interposable_list") == 0 ) {
1921 fInterposeMode = kInterposeSome;
1922 loadExportFile(argv[++i], "-interposable_list", fInterposeList);
c2646906 1923 }
d696c285 1924 // Default for -interposable/-multi_module/-single_module.
c2646906 1925 else if ( strcmp(arg, "-single_module") == 0 ) {
2f2f92e4 1926 fInterposeMode = kInterposeNone;
c2646906
A
1927 }
1928 else if ( strcmp(arg, "-exported_symbols_list") == 0 ) {
1929 if ( fExportMode == kDontExportSome )
1930 throw "can't use -exported_symbols_list and -unexported_symbols_list";
1931 fExportMode = kExportSome;
1932 loadExportFile(argv[++i], "-exported_symbols_list", fExportSymbols);
1933 }
1934 else if ( strcmp(arg, "-unexported_symbols_list") == 0 ) {
1935 if ( fExportMode == kExportSome )
a61fdf0a 1936 throw "can't use -unexported_symbols_list and -exported_symbols_list";
c2646906
A
1937 fExportMode = kDontExportSome;
1938 loadExportFile(argv[++i], "-unexported_symbols_list", fDontExportSymbols);
1939 }
a61fdf0a
A
1940 else if ( strcmp(arg, "-exported_symbol") == 0 ) {
1941 if ( fExportMode == kDontExportSome )
1942 throw "can't use -exported_symbol and -unexported_symbols";
1943 fExportMode = kExportSome;
1944 fExportSymbols.insert(argv[++i]);
1945 }
1946 else if ( strcmp(arg, "-unexported_symbol") == 0 ) {
1947 if ( fExportMode == kExportSome )
1948 throw "can't use -unexported_symbol and -exported_symbol";
1949 fExportMode = kDontExportSome;
1950 fDontExportSymbols.insert(argv[++i]);
1951 }
1952 else if ( strcmp(arg, "-non_global_symbols_no_strip_list") == 0 ) {
1953 if ( fLocalSymbolHandling == kLocalSymbolsSelectiveExclude )
1954 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
1955 fLocalSymbolHandling = kLocalSymbolsSelectiveInclude;
1956 loadExportFile(argv[++i], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded);
1957 }
1958 else if ( strcmp(arg, "-non_global_symbols_strip_list") == 0 ) {
1959 if ( fLocalSymbolHandling == kLocalSymbolsSelectiveInclude )
1960 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
1961 fLocalSymbolHandling = kLocalSymbolsSelectiveExclude;
1962 loadExportFile(argv[++i], "-non_global_symbols_strip_list", fLocalSymbolsExcluded);
1963 }
d696c285 1964 // ??? Deprecate
c2646906
A
1965 else if ( strcmp(arg, "-no_arch_warnings") == 0 ) {
1966 fIgnoreOtherArchFiles = true;
1967 }
1968 else if ( strcmp(arg, "-force_cpusubtype_ALL") == 0 ) {
afe874b1
A
1969 fForceSubtypeAll = true;
1970 fAllowCpuSubtypeMismatches = true;
c2646906 1971 }
d696c285 1972 // Similar to -weak-l but uses the absolute path name to the library.
c2646906 1973 else if ( strcmp(arg, "-weak_library") == 0 ) {
6e880c60 1974 FileInfo info = findFile(argv[++i]);
c2646906 1975 info.options.fWeakImport = true;
a61fdf0a 1976 addLibrary(info);
c2646906 1977 }
2f2f92e4
A
1978 else if ( strcmp(arg, "-lazy_library") == 0 ) {
1979 FileInfo info = findFile(argv[++i]);
1980 info.options.fLazyLoad = true;
1981 addLibrary(info);
1982 fUsingLazyDylibLinking = true;
1983 }
c2646906 1984 else if ( strcmp(arg, "-framework") == 0 ) {
a61fdf0a 1985 addLibrary(findFramework(argv[++i]));
c2646906
A
1986 }
1987 else if ( strcmp(arg, "-weak_framework") == 0 ) {
1988 FileInfo info = findFramework(argv[++i]);
1989 info.options.fWeakImport = true;
a61fdf0a 1990 addLibrary(info);
c2646906 1991 }
2f2f92e4
A
1992 else if ( strcmp(arg, "-lazy_framework") == 0 ) {
1993 FileInfo info = findFramework(argv[++i]);
1994 info.options.fLazyLoad = true;
1995 addLibrary(info);
1996 fUsingLazyDylibLinking = true;
1997 }
c2646906 1998 else if ( strcmp(arg, "-search_paths_first") == 0 ) {
a61fdf0a 1999 // previously handled by buildSearchPaths()
c2646906 2000 }
a645023d
A
2001 else if ( strcmp(arg, "-search_dylibs_first") == 0 ) {
2002 // previously handled by buildSearchPaths()
2003 }
c2646906
A
2004 else if ( strcmp(arg, "-undefined") == 0 ) {
2005 setUndefinedTreatment(argv[++i]);
2006 }
d696c285 2007 // Debugging output flag.
c2646906
A
2008 else if ( strcmp(arg, "-arch_multiple") == 0 ) {
2009 fMessagesPrefixedWithArchitecture = true;
2010 }
d696c285
A
2011 // Specify what to do with relocations in read only
2012 // sections like .text. Could be errors, warnings,
2013 // or suppressed. Currently we do nothing with the
2014 // flag.
c2646906 2015 else if ( strcmp(arg, "-read_only_relocs") == 0 ) {
2f2f92e4
A
2016 switch ( parseTreatment(argv[++i]) ) {
2017 case kNULL:
2018 case kInvalid:
2019 throw "-read_only_relocs missing [ warning | error | suppress ]";
2020 case kWarning:
2021 fWarnTextRelocs = true;
2022 fAllowTextRelocs = true;
2023 break;
2024 case kSuppress:
2025 fWarnTextRelocs = false;
2026 fAllowTextRelocs = true;
2027 break;
2028 case kError:
2029 fWarnTextRelocs = false;
2030 fAllowTextRelocs = false;
2031 break;
2032 }
c2646906
A
2033 }
2034 else if ( strcmp(arg, "-sect_diff_relocs") == 0 ) {
a61fdf0a
A
2035 warnObsolete(arg);
2036 ++i;
c2646906 2037 }
d696c285
A
2038 // Warn, error or make strong a mismatch between weak
2039 // and non-weak references.
c2646906
A
2040 else if ( strcmp(arg, "-weak_reference_mismatches") == 0 ) {
2041 setWeakReferenceMismatchTreatment(argv[++i]);
2042 }
d696c285
A
2043 // For a deployment target of 10.3 and earlier ld64 will
2044 // prebind an executable with 0s in all addresses that
2045 // are prebound. This can then be fixed up by update_prebinding
2046 // later. Prebinding is less useful on 10.4 and greater.
c2646906 2047 else if ( strcmp(arg, "-prebind") == 0 ) {
d696c285 2048 fPrebind = true;
c2646906
A
2049 }
2050 else if ( strcmp(arg, "-noprebind") == 0 ) {
a61fdf0a 2051 warnObsolete(arg);
d696c285 2052 fPrebind = false;
c2646906
A
2053 }
2054 else if ( strcmp(arg, "-prebind_allow_overlap") == 0 ) {
a61fdf0a 2055 warnObsolete(arg);
c2646906
A
2056 }
2057 else if ( strcmp(arg, "-prebind_all_twolevel_modules") == 0 ) {
a61fdf0a 2058 warnObsolete(arg);
c2646906
A
2059 }
2060 else if ( strcmp(arg, "-noprebind_all_twolevel_modules") == 0 ) {
a61fdf0a 2061 warnObsolete(arg);
c2646906
A
2062 }
2063 else if ( strcmp(arg, "-nofixprebinding") == 0 ) {
a61fdf0a 2064 warnObsolete(arg);
c2646906 2065 }
d696c285
A
2066 // This should probably be deprecated when we respect -L and -F
2067 // when searching for libraries.
c2646906 2068 else if ( strcmp(arg, "-dylib_file") == 0 ) {
a61fdf0a 2069 addDylibOverride(argv[++i]);
c2646906 2070 }
a61fdf0a 2071 // What to expand @executable_path to if found in dependent dylibs
c2646906 2072 else if ( strcmp(arg, "-executable_path") == 0 ) {
d696c285
A
2073 fExecutablePath = argv[++i];
2074 if ( (fExecutablePath == NULL) || (fExecutablePath[0] == '-') )
2075 throw "-executable_path missing <path>";
a61fdf0a
A
2076 // if a directory was passed, add / to end
2077 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2078 struct stat statBuffer;
2079 if ( stat(fExecutablePath, &statBuffer) == 0 ) {
2080 if ( (statBuffer.st_mode & S_IFMT) == S_IFDIR ) {
2081 char* pathWithSlash = new char[strlen(fExecutablePath)+2];
2082 strcpy(pathWithSlash, fExecutablePath);
2083 strcat(pathWithSlash, "/");
2084 fExecutablePath = pathWithSlash;
2085 }
2086 }
c2646906 2087 }
d696c285 2088 // Aligns all segments to the power of 2 boundary specified.
c2646906 2089 else if ( strcmp(arg, "-segalign") == 0 ) {
55e3d2f6
A
2090 const char* size = argv[++i];
2091 if ( size == NULL )
2092 throw "-segalign missing <size>";
2093 fSegmentAlignment = parseAddress(size);
2094 uint8_t alignment = (uint8_t)__builtin_ctz(fSegmentAlignment);
2095 uint32_t p2aligned = (1 << alignment);
2096 if ( p2aligned != fSegmentAlignment ) {
2097 warning("alignment for -segalign %s is not a power of two, using 0x%X", size, p2aligned);
2098 fSegmentAlignment = p2aligned;
2099 }
c2646906 2100 }
d696c285
A
2101 // Puts a specified segment at a particular address that must
2102 // be a multiple of the segment alignment.
c2646906 2103 else if ( strcmp(arg, "-segaddr") == 0 ) {
a61fdf0a
A
2104 SegmentStart seg;
2105 seg.name = argv[++i];
2106 if ( (seg.name == NULL) || (argv[i+1] == NULL) )
2107 throw "-segaddr missing segName Adddress";
2108 seg.address = parseAddress(argv[++i]);
b2fa67a8
A
2109 uint64_t temp = ((seg.address+fSegmentAlignment-1) & (-fSegmentAlignment));
2110 if ( seg.address != temp )
2111 warning("-segaddr %s not %lld byte aligned", seg.name, fSegmentAlignment);
a61fdf0a 2112 fCustomSegmentAddresses.push_back(seg);
c2646906 2113 }
d696c285 2114 // ??? Deprecate when we deprecate split-seg.
c2646906 2115 else if ( strcmp(arg, "-segs_read_only_addr") == 0 ) {
a61fdf0a 2116 fBaseAddress = parseAddress(argv[++i]);
c2646906 2117 }
d696c285 2118 // ??? Deprecate when we deprecate split-seg.
c2646906 2119 else if ( strcmp(arg, "-segs_read_write_addr") == 0 ) {
a61fdf0a
A
2120 fBaseWritableAddress = parseAddress(argv[++i]);
2121 fSplitSegs = true;
c2646906 2122 }
d696c285 2123 // ??? Deprecate when we get rid of basing at build time.
c2646906 2124 else if ( strcmp(arg, "-seg_addr_table") == 0 ) {
a61fdf0a
A
2125 const char* name = argv[++i];
2126 if ( name == NULL )
2127 throw "-seg_addr_table missing argument";
2128 fSegAddrTablePath = name;
c2646906
A
2129 }
2130 else if ( strcmp(arg, "-seg_addr_table_filename") == 0 ) {
a61fdf0a 2131 warnObsolete(arg);
d696c285 2132 ++i;
c2646906
A
2133 }
2134 else if ( strcmp(arg, "-segprot") == 0 ) {
a61fdf0a
A
2135 SegmentProtect seg;
2136 seg.name = argv[++i];
2137 if ( (seg.name == NULL) || (argv[i+1] == NULL) || (argv[i+2] == NULL) )
2138 throw "-segprot missing segName max-prot init-prot";
2139 seg.max = parseProtection(argv[++i]);
2140 seg.init = parseProtection(argv[++i]);
2141 fCustomSegmentProtections.push_back(seg);
c2646906
A
2142 }
2143 else if ( strcmp(arg, "-pagezero_size") == 0 ) {
a61fdf0a
A
2144 const char* size = argv[++i];
2145 if ( size == NULL )
2146 throw "-pagezero_size missing <size>";
2147 fZeroPageSize = parseAddress(size);
69a49097 2148 uint64_t temp = fZeroPageSize & (-4096); // page align
2f2f92e4
A
2149 if ( (fZeroPageSize != temp) )
2150 warning("-pagezero_size not page aligned, rounding down");
69a49097 2151 fZeroPageSize = temp;
c2646906
A
2152 }
2153 else if ( strcmp(arg, "-stack_addr") == 0 ) {
a61fdf0a
A
2154 const char* address = argv[++i];
2155 if ( address == NULL )
2156 throw "-stack_addr missing <address>";
2157 fStackAddr = parseAddress(address);
c2646906
A
2158 }
2159 else if ( strcmp(arg, "-stack_size") == 0 ) {
a61fdf0a
A
2160 const char* size = argv[++i];
2161 if ( size == NULL )
2162 throw "-stack_size missing <address>";
2163 fStackSize = parseAddress(size);
2164 uint64_t temp = fStackSize & (-4096); // page align
2f2f92e4
A
2165 if ( (fStackSize != temp) )
2166 warning("-stack_size not page aligned, rounding down");
c2646906 2167 }
d696c285
A
2168 else if ( strcmp(arg, "-allow_stack_execute") == 0 ) {
2169 fExecutableStack = true;
2170 }
a645023d
A
2171 else if ( strcmp(arg, "-allow_heap_execute") == 0 ) {
2172 fDisableNonExecutableHeap = true;
2173 }
c2646906 2174 else if ( strcmp(arg, "-sectalign") == 0 ) {
a61fdf0a
A
2175 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
2176 throw "-sectalign missing <segment> <section> <file-path>";
c2646906
A
2177 addSectionAlignment(argv[i+1], argv[i+2], argv[i+3]);
2178 i += 3;
2179 }
2180 else if ( strcmp(arg, "-sectorder_detail") == 0 ) {
a61fdf0a 2181 warnObsolete(arg);
c2646906
A
2182 }
2183 else if ( strcmp(arg, "-sectobjectsymbols") == 0 ) {
a61fdf0a 2184 warnObsolete(arg);
c2646906
A
2185 i += 2;
2186 }
2187 else if ( strcmp(arg, "-bundle_loader") == 0 ) {
69a49097
A
2188 fBundleLoader = argv[++i];
2189 if ( (fBundleLoader == NULL) || (fBundleLoader[0] == '-') )
2190 throw "-bundle_loader missing <path>";
2191 FileInfo info = findFile(fBundleLoader);
2192 info.options.fBundleLoader = true;
2193 fInputFiles.push_back(info);
c2646906
A
2194 }
2195 else if ( strcmp(arg, "-private_bundle") == 0 ) {
a61fdf0a 2196 warnObsolete(arg);
c2646906
A
2197 }
2198 else if ( strcmp(arg, "-twolevel_namespace_hints") == 0 ) {
2199 // FIX FIX
2200 }
d696c285 2201 // Use this flag to set default behavior for deployement targets.
c7f24d34 2202 else if ( strcmp(arg, "-macosx_version_min") == 0 ) {
2f2f92e4
A
2203 setMacOSXVersionMin(argv[++i]);
2204 }
afe874b1
A
2205 else if ( (strcmp(arg, "-ios_version_min") == 0) || (strcmp(arg, "-iphoneos_version_min") == 0) ) {
2206 setIOSVersionMin(argv[++i]);
2207 }
2208 else if ( strcmp(arg, "-ios_simulator_version_min") == 0 ) {
2209 setIOSVersionMin(argv[++i]);
c7f24d34 2210 }
c2646906 2211 else if ( strcmp(arg, "-multiply_defined") == 0 ) {
a61fdf0a
A
2212 //warnObsolete(arg);
2213 ++i;
c2646906
A
2214 }
2215 else if ( strcmp(arg, "-multiply_defined_unused") == 0 ) {
a61fdf0a
A
2216 warnObsolete(arg);
2217 ++i;
c2646906
A
2218 }
2219 else if ( strcmp(arg, "-nomultidefs") == 0 ) {
a61fdf0a 2220 warnObsolete(arg);
c2646906 2221 }
d696c285
A
2222 // Display each file in which the argument symbol appears and whether
2223 // the file defines or references it. This option takes an argument
2224 // as -y<symbol> note that there is no space.
2225 else if ( strncmp(arg, "-y", 2) == 0 ) {
a61fdf0a 2226 warnObsolete("-y");
c2646906 2227 }
d696c285 2228 // Same output as -y, but output <arg> number of undefined symbols only.
c2646906 2229 else if ( strcmp(arg, "-Y") == 0 ) {
a61fdf0a
A
2230 //warnObsolete(arg);
2231 ++i;
c2646906 2232 }
d696c285 2233 // This option affects all objects linked into the final result.
c2646906 2234 else if ( strcmp(arg, "-m") == 0 ) {
a61fdf0a 2235 warnObsolete(arg);
c2646906 2236 }
69a49097 2237 else if ( (strcmp(arg, "-why_load") == 0) || (strcmp(arg, "-whyload") == 0) ) {
a645023d 2238 fWhyLoad = true;
69a49097
A
2239 }
2240 else if ( strcmp(arg, "-why_live") == 0 ) {
2241 const char* name = argv[++i];
2242 if ( name == NULL )
2243 throw "-why_live missing symbol name argument";
2244 fWhyLive.insert(name);
c2646906
A
2245 }
2246 else if ( strcmp(arg, "-u") == 0 ) {
2247 const char* name = argv[++i];
2248 if ( name == NULL )
2249 throw "-u missing argument";
2250 fInitialUndefines.push_back(name);
2251 }
c2646906 2252 else if ( strcmp(arg, "-U") == 0 ) {
a61fdf0a
A
2253 const char* name = argv[++i];
2254 if ( name == NULL )
2255 throw "-U missing argument";
2256 fAllowedUndefined.insert(name);
c2646906
A
2257 }
2258 else if ( strcmp(arg, "-s") == 0 ) {
a61fdf0a
A
2259 warnObsolete(arg);
2260 fLocalSymbolHandling = kLocalSymbolsNone;
a645023d 2261 fDebugInfoStripping = Options::kDebugInfoNone;
c2646906
A
2262 }
2263 else if ( strcmp(arg, "-x") == 0 ) {
a61fdf0a 2264 fLocalSymbolHandling = kLocalSymbolsNone;
c2646906
A
2265 }
2266 else if ( strcmp(arg, "-S") == 0 ) {
a645023d 2267 fDebugInfoStripping = Options::kDebugInfoNone;
c2646906
A
2268 }
2269 else if ( strcmp(arg, "-X") == 0 ) {
a61fdf0a 2270 warnObsolete(arg);
c2646906
A
2271 }
2272 else if ( strcmp(arg, "-Si") == 0 ) {
a61fdf0a 2273 warnObsolete(arg);
a645023d 2274 fDebugInfoStripping = Options::kDebugInfoFull;
c2646906
A
2275 }
2276 else if ( strcmp(arg, "-b") == 0 ) {
a61fdf0a 2277 warnObsolete(arg);
c2646906
A
2278 }
2279 else if ( strcmp(arg, "-Sn") == 0 ) {
a61fdf0a 2280 warnObsolete(arg);
a645023d 2281 fDebugInfoStripping = Options::kDebugInfoFull;
d696c285
A
2282 }
2283 else if ( strcmp(arg, "-Sp") == 0 ) {
a61fdf0a 2284 warnObsolete(arg);
c2646906
A
2285 }
2286 else if ( strcmp(arg, "-dead_strip") == 0 ) {
a645023d 2287 fDeadStrip = true;
d696c285
A
2288 }
2289 else if ( strcmp(arg, "-no_dead_strip_inits_and_terms") == 0 ) {
a645023d 2290 fDeadStrip = true;
c2646906 2291 }
c2646906 2292 else if ( strcmp(arg, "-w") == 0 ) {
a61fdf0a 2293 // previously handled by buildSearchPaths()
c2646906 2294 }
b2fa67a8
A
2295 else if ( strcmp(arg, "-fatal_warnings") == 0 ) {
2296 // previously handled by buildSearchPaths()
2297 }
c2646906 2298 else if ( strcmp(arg, "-arch_errors_fatal") == 0 ) {
55e3d2f6 2299 fErrorOnOtherArchFiles = true;
c2646906
A
2300 }
2301 else if ( strcmp(arg, "-M") == 0 ) {
2302 // FIX FIX
2303 }
c2646906
A
2304 else if ( strcmp(arg, "-headerpad") == 0 ) {
2305 const char* size = argv[++i];
2306 if ( size == NULL )
2307 throw "-headerpad missing argument";
2308 fMinimumHeaderPad = parseAddress(size);
2309 }
2310 else if ( strcmp(arg, "-headerpad_max_install_names") == 0 ) {
a61fdf0a 2311 fMaxMinimumHeaderPad = true;
c2646906
A
2312 }
2313 else if ( strcmp(arg, "-t") == 0 ) {
a645023d 2314 fLogAllFiles = true;
a61fdf0a
A
2315 }
2316 else if ( strcmp(arg, "-whatsloaded") == 0 ) {
a645023d 2317 fLogObjectFiles = true;
c2646906
A
2318 }
2319 else if ( strcmp(arg, "-A") == 0 ) {
a61fdf0a 2320 warnObsolete(arg);
d696c285 2321 ++i;
c2646906
A
2322 }
2323 else if ( strcmp(arg, "-umbrella") == 0 ) {
2324 const char* name = argv[++i];
2325 if ( name == NULL )
2326 throw "-umbrella missing argument";
2327 fUmbrellaName = name;
2328 }
2329 else if ( strcmp(arg, "-allowable_client") == 0 ) {
d696c285
A
2330 const char* name = argv[++i];
2331
2332 if ( name == NULL )
2333 throw "-allowable_client missing argument";
2334
2335 fAllowableClients.push_back(name);
c2646906
A
2336 }
2337 else if ( strcmp(arg, "-client_name") == 0 ) {
d696c285
A
2338 const char* name = argv[++i];
2339
2340 if ( name == NULL )
2341 throw "-client_name missing argument";
2342
2343 fClientName = name;
c2646906
A
2344 }
2345 else if ( strcmp(arg, "-sub_umbrella") == 0 ) {
2346 const char* name = argv[++i];
2347 if ( name == NULL )
2348 throw "-sub_umbrella missing argument";
2349 fSubUmbellas.push_back(name);
2350 }
2351 else if ( strcmp(arg, "-sub_library") == 0 ) {
2352 const char* name = argv[++i];
2353 if ( name == NULL )
2354 throw "-sub_library missing argument";
2355 fSubLibraries.push_back(name);
2356 }
2357 else if ( strcmp(arg, "-init") == 0 ) {
2358 const char* name = argv[++i];
2359 if ( name == NULL )
2360 throw "-init missing argument";
2361 fInitFunctionName = name;
2362 }
d696c285
A
2363 else if ( strcmp(arg, "-dot") == 0 ) {
2364 const char* name = argv[++i];
2365 if ( name == NULL )
2366 throw "-dot missing argument";
2367 fDotOutputFile = name;
2368 }
c2646906
A
2369 else if ( strcmp(arg, "-warn_commons") == 0 ) {
2370 fWarnCommons = true;
2371 }
2372 else if ( strcmp(arg, "-commons") == 0 ) {
2373 fCommonsMode = parseCommonsTreatment(argv[++i]);
2374 }
d696c285
A
2375 else if ( strcmp(arg, "-keep_relocs") == 0 ) {
2376 fKeepRelocations = true;
2377 }
2378 else if ( strcmp(arg, "-warn_stabs") == 0 ) {
2379 fWarnStabs = true;
2380 }
2381 else if ( strcmp(arg, "-pause") == 0 ) {
2382 fPause = true;
2383 }
2384 else if ( strcmp(arg, "-print_statistics") == 0 ) {
2385 fStatistics = true;
2386 }
69a49097 2387 else if ( strcmp(arg, "-d") == 0 ) {
a645023d 2388 fMakeTentativeDefinitionsReal = true;
69a49097 2389 }
6e880c60
A
2390 else if ( strcmp(arg, "-v") == 0 ) {
2391 // previously handled by buildSearchPaths()
2392 }
2393 else if ( strcmp(arg, "-Z") == 0 ) {
2394 // previously handled by buildSearchPaths()
2395 }
2396 else if ( strcmp(arg, "-syslibroot") == 0 ) {
2397 ++i;
2398 // previously handled by buildSearchPaths()
2399 }
d696c285 2400 else if ( strcmp(arg, "-no_uuid") == 0 ) {
a61fdf0a
A
2401 fUUIDMode = kUUIDNone;
2402 }
2403 else if ( strcmp(arg, "-random_uuid") == 0 ) {
2404 fUUIDMode = kUUIDRandom;
2405 }
2406 else if ( strcmp(arg, "-dtrace") == 0 ) {
2407 const char* name = argv[++i];
2408 if ( name == NULL )
2409 throw "-dtrace missing argument";
2410 fDtraceScriptName = name;
2411 }
2412 else if ( strcmp(arg, "-root_safe") == 0 ) {
a645023d 2413 fRootSafe = true;
a61fdf0a
A
2414 }
2415 else if ( strcmp(arg, "-setuid_safe") == 0 ) {
a645023d 2416 fSetuidSafe = true;
a61fdf0a
A
2417 }
2418 else if ( strcmp(arg, "-alias") == 0 ) {
a645023d 2419 Options::AliasPair pair;
a61fdf0a
A
2420 pair.realName = argv[++i];
2421 if ( pair.realName == NULL )
2422 throw "missing argument to -alias";
2423 pair.alias = argv[++i];
2424 if ( pair.alias == NULL )
2425 throw "missing argument to -alias";
a645023d 2426 fAliases.push_back(pair);
a61fdf0a
A
2427 }
2428 else if ( strcmp(arg, "-alias_list") == 0 ) {
2429 parseAliasFile(argv[++i]);
d696c285
A
2430 }
2431 // put this last so that it does not interfer with other options starting with 'i'
2432 else if ( strncmp(arg, "-i", 2) == 0 ) {
a61fdf0a
A
2433 const char* colon = strchr(arg, ':');
2434 if ( colon == NULL )
2435 throwf("unknown option: %s", arg);
a645023d 2436 Options::AliasPair pair;
a61fdf0a
A
2437 char* temp = new char[colon-arg];
2438 strlcpy(temp, &arg[2], colon-arg-1);
2439 pair.realName = &colon[1];
2440 pair.alias = temp;
a645023d 2441 fAliases.push_back(pair);
a61fdf0a
A
2442 }
2443 else if ( strcmp(arg, "-save-temps") == 0 ) {
2444 fSaveTempFiles = true;
2445 }
2446 else if ( strcmp(arg, "-rpath") == 0 ) {
2447 const char* path = argv[++i];
2448 if ( path == NULL )
2449 throw "missing argument to -rpath";
2450 fRPaths.push_back(path);
2451 }
2452 else if ( strcmp(arg, "-read_only_stubs") == 0 ) {
2453 fReadOnlyx86Stubs = true;
2454 }
2f2f92e4 2455 else if ( strcmp(arg, "-slow_stubs") == 0 ) {
55e3d2f6 2456 warnObsolete(arg);
2f2f92e4 2457 }
a61fdf0a
A
2458 else if ( strcmp(arg, "-map") == 0 ) {
2459 fMapPath = argv[++i];
2460 if ( fMapPath == NULL )
2461 throw "missing argument to -map";
2462 }
2463 else if ( strcmp(arg, "-pie") == 0 ) {
2464 fPositionIndependentExecutable = true;
a645023d 2465 fPIEOnCommandLine = true;
a61fdf0a 2466 }
d9246299
A
2467 else if ( strcmp(arg, "-no_pie") == 0 ) {
2468 fDisablePositionIndependentExecutable = true;
2469 }
a61fdf0a 2470 else if ( strncmp(arg, "-reexport-l", 11) == 0 ) {
2f2f92e4 2471 FileInfo info = findLibrary(&arg[11], true);
a61fdf0a
A
2472 info.options.fReExport = true;
2473 addLibrary(info);
2474 }
2475 else if ( strcmp(arg, "-reexport_library") == 0 ) {
2476 FileInfo info = findFile(argv[++i]);
2477 info.options.fReExport = true;
2478 addLibrary(info);
2479 }
2480 else if ( strcmp(arg, "-reexport_framework") == 0 ) {
2481 FileInfo info = findFramework(argv[++i]);
2482 info.options.fReExport = true;
2483 addLibrary(info);
2484 }
a645023d
A
2485 else if ( strncmp(arg, "-upward-l", 9) == 0 ) {
2486 FileInfo info = findLibrary(&arg[9], true);
2487 info.options.fUpward = true;
2488 addLibrary(info);
2489 }
2490 else if ( strcmp(arg, "-upward_library") == 0 ) {
2491 FileInfo info = findFile(argv[++i]);
2492 info.options.fUpward = true;
2493 addLibrary(info);
2494 }
2495 else if ( strcmp(arg, "-upward_framework") == 0 ) {
2496 FileInfo info = findFramework(argv[++i]);
2497 info.options.fUpward = true;
2498 addLibrary(info);
2499 }
a61fdf0a
A
2500 else if ( strcmp(arg, "-dead_strip_dylibs") == 0 ) {
2501 fDeadStripDylibs = true;
2502 }
2f2f92e4 2503 else if ( strcmp(arg, "-no_implicit_dylibs") == 0 ) {
a645023d 2504 fImplicitlyLinkPublicDylibs = false;
2f2f92e4 2505 }
a61fdf0a
A
2506 else if ( strcmp(arg, "-new_linker") == 0 ) {
2507 // ignore
d696c285 2508 }
2f2f92e4
A
2509 else if ( strcmp(arg, "-no_encryption") == 0 ) {
2510 fEncryptable = false;
2511 }
55e3d2f6 2512 else if ( strcmp(arg, "-no_compact_unwind") == 0 ) {
a645023d 2513 fAddCompactUnwindEncoding = false;
55e3d2f6
A
2514 }
2515 else if ( strcmp(arg, "-mllvm") == 0 ) {
2516 const char* opts = argv[++i];
2517 if ( opts == NULL )
2518 throw "missing argument to -mllvm";
2519 fLLVMOptions.push_back(opts);
2520 }
2521 else if ( strcmp(arg, "-no_order_inits") == 0 ) {
a645023d 2522 fAutoOrderInitializers = false;
55e3d2f6
A
2523 }
2524 else if ( strcmp(arg, "-no_order_data") == 0 ) {
2525 fOrderData = false;
2526 }
2527 else if ( strcmp(arg, "-seg_page_size") == 0 ) {
2528 SegmentSize seg;
2529 seg.name = argv[++i];
2530 if ( (seg.name == NULL) || (argv[i+1] == NULL) )
2531 throw "-seg_page_size missing segName Adddress";
2532 seg.size = parseAddress(argv[++i]);
2533 uint64_t temp = seg.size & (-4096); // page align
2534 if ( (seg.size != temp) )
2535 warning("-seg_page_size %s not 4K aligned, rounding down", seg.name);
2536 fCustomSegmentSizes.push_back(seg);
2537 }
2538 else if ( strcmp(arg, "-mark_dead_strippable_dylib") == 0 ) {
2539 fMarkDeadStrippableDylib = true;
2540 }
2541 else if ( strcmp(arg, "-exported_symbols_order") == 0 ) {
2542 loadSymbolOrderFile(argv[++i], fExportSymbolsOrder);
2543 }
2544 else if ( strcmp(arg, "-no_compact_linkedit") == 0 ) {
afe874b1 2545 warnObsolete("-no_compact_linkedit");
55e3d2f6
A
2546 }
2547 else if ( strcmp(arg, "-no_eh_labels") == 0 ) {
a645023d 2548 fNoEHLabels = true;
55e3d2f6
A
2549 }
2550 else if ( strcmp(arg, "-warn_compact_unwind") == 0 ) {
a645023d 2551 fWarnCompactUnwind = true;
55e3d2f6
A
2552 }
2553 else if ( strcmp(arg, "-allow_sub_type_mismatches") == 0 ) {
2554 fAllowCpuSubtypeMismatches = true;
2555 }
4be885f6 2556 else if ( strcmp(arg, "-no_zero_fill_sections") == 0 ) {
a645023d 2557 fOptimizeZeroFill = false;
4be885f6 2558 }
afe874b1
A
2559 else if ( strcmp(arg, "-merge_zero_fill_sections") == 0 ) {
2560 fMergeZeroFill = true;
2561 }
d9246299
A
2562 else if ( strcmp(arg, "-objc_abi_version") == 0 ) {
2563 const char* version = argv[++i];
2564 if ( version == NULL )
2565 throw "-objc_abi_version missing version number";
a645023d
A
2566 if ( strcmp(version, "2") == 0 ) {
2567 fObjCABIVersion1Override = false;
2568 fObjCABIVersion2Override = true;
2569 }
2570 else if ( strcmp(version, "1") == 0 ) {
2571 fObjCABIVersion1Override = true;
2572 fObjCABIVersion2Override = false;
2573 }
d9246299
A
2574 else
2575 warning("ignoring unrecognized argument (%s) to -objc_abi_version", version);
2576 }
a645023d
A
2577 else if ( strcmp(arg, "-warn_weak_exports") == 0 ) {
2578 fWarnWeakExports = true;
2579 }
2580 else if ( strcmp(arg, "-objc_gc_compaction") == 0 ) {
2581 fObjcGcCompaction = true;
2582 }
2583 else if ( strcmp(arg, "-objc_gc") == 0 ) {
2584 fObjCGc = true;
2585 if ( fObjCGcOnly ) {
2586 warning("-objc_gc overriding -objc_gc_only");
2587 fObjCGcOnly = false;
2588 }
2589 }
2590 else if ( strcmp(arg, "-objc_gc_only") == 0 ) {
2591 fObjCGcOnly = true;
2592 if ( fObjCGc ) {
2593 warning("-objc_gc_only overriding -objc_gc");
2594 fObjCGc = false;
2595 }
2596 }
07feaf2c 2597 else if ( strcmp(arg, "-demangle") == 0 ) {
a645023d
A
2598 fDemangle = true;
2599 }
2600 else if ( strcmp(arg, "-version_load_command") == 0 ) {
afe874b1
A
2601 fVersionLoadCommandForcedOn = true;
2602 fVersionLoadCommandForcedOff = false;
a645023d
A
2603 }
2604 else if ( strcmp(arg, "-no_version_load_command") == 0 ) {
afe874b1
A
2605 fVersionLoadCommandForcedOff = true;
2606 fVersionLoadCommandForcedOn = false;
a645023d
A
2607 }
2608 else if ( strcmp(arg, "-function_starts") == 0 ) {
afe874b1
A
2609 fFunctionStartsForcedOn = true;
2610 fFunctionStartsForcedOff = false;
a645023d
A
2611 }
2612 else if ( strcmp(arg, "-no_function_starts") == 0 ) {
afe874b1
A
2613 fFunctionStartsForcedOff = true;
2614 fFunctionStartsForcedOn = false;
a645023d
A
2615 }
2616 else if ( strcmp(arg, "-object_path_lto") == 0 ) {
2617 fTempLtoObjectPath = argv[++i];
2618 if ( fTempLtoObjectPath == NULL )
2619 throw "missing argument to -object_path_lto";
2620 }
2621 else if ( strcmp(arg, "-no_objc_category_merging") == 0 ) {
2622 fObjcCategoryMerging = false;
2623 }
2624 else if ( strcmp(arg, "-force_symbols_weak_list") == 0 ) {
2625 loadExportFile(argv[++i], "-force_symbols_weak_list", fForceWeakSymbols);
2626 }
2627 else if ( strcmp(arg, "-force_symbols_not_weak_list") == 0 ) {
2628 loadExportFile(argv[++i], "-force_symbols_not_weak_list", fForceNotWeakSymbols);
2629 }
2630 else if ( strcmp(arg, "-force_symbol_weak") == 0 ) {
2631 const char* symbol = argv[++i];
2632 if ( symbol == NULL )
2633 throw "-force_symbol_weak missing <symbol>";
2634 fForceWeakSymbols.insert(symbol);
2635 }
2636 else if ( strcmp(arg, "-force_symbol_not_weak") == 0 ) {
2637 const char* symbol = argv[++i];
2638 if ( symbol == NULL )
2639 throw "-force_symbol_not_weak missing <symbol>";
2640 fForceNotWeakSymbols.insert(symbol);
2641 }
2642 else if ( strcmp(arg, "-reexported_symbols_list") == 0 ) {
2643 if ( fExportMode == kExportSome )
2644 throw "can't use -exported_symbols_list and -reexported_symbols_list";
2645 loadExportFile(argv[++i], "-reexported_symbols_list", fReExportSymbols);
2646 }
2647 else if ( strcmp(arg, "-dyld_env") == 0 ) {
2648 const char* envarg = argv[++i];
2649 if ( envarg == NULL )
2650 throw "-dyld_env missing ENV=VALUE";
2651 if ( strchr(envarg, '=') == NULL )
2652 throw "-dyld_env missing ENV=VALUE";
2653 fDyldEnvironExtras.push_back(envarg);
07feaf2c 2654 }
afe874b1
A
2655 else if ( strcmp(arg, "-page_align_data_atoms") == 0 ) {
2656 fPageAlignDataAtoms = true;
2657 }
c2646906 2658 else {
d696c285 2659 throwf("unknown option: %s", arg);
c2646906
A
2660 }
2661 }
2662 else {
a61fdf0a
A
2663 FileInfo info = findFile(arg);
2664 if ( strcmp(&info.path[strlen(info.path)-2], ".a") == 0 )
2665 addLibrary(info);
2666 else
2667 fInputFiles.push_back(info);
c2646906
A
2668 }
2669 }
2f2f92e4
A
2670
2671 // if a -lazy option was used, implicitly link in lazydylib1.o
2672 if ( fUsingLazyDylibLinking ) {
2673 addLibrary(findLibrary("lazydylib1.o"));
2674 }
c2646906
A
2675}
2676
69a49097
A
2677
2678
d696c285
A
2679//
2680// -syslibroot <path> is used for SDK support.
6e880c60
A
2681// The rule is that all search paths (both explicit and default) are
2682// checked to see if they exist in the SDK. If so, that path is
2683// replaced with the sdk prefixed path. If not, that search path
2684// is used as is. If multiple -syslibroot options are specified
2685// their directory structures are logically overlayed and files
2686// from sdks specified earlier on the command line used before later ones.
d696c285 2687
c2646906
A
2688void Options::buildSearchPaths(int argc, const char* argv[])
2689{
2690 bool addStandardLibraryDirectories = true;
6e880c60
A
2691 std::vector<const char*> libraryPaths;
2692 std::vector<const char*> frameworkPaths;
d696c285
A
2693 libraryPaths.reserve(10);
2694 frameworkPaths.reserve(10);
6e880c60 2695 // scan through argv looking for -L, -F, -Z, and -syslibroot options
c2646906 2696 for(int i=0; i < argc; ++i) {
c211e7c9
A
2697 if ( (argv[i][0] == '-') && (argv[i][1] == 'L') ) {
2698 const char* libSearchDir = &argv[i][2];
a645023d
A
2699 // Allow either "-L{path}" or "-L {path}".
2700 if (argv[i][2] == '\0') {
2701 // -L {path}. Make sure there is an argument following this.
2702 const char* path = argv[++i];
2703 if ( path == NULL )
2704 throw "-L missing argument";
2705 libSearchDir = path;
2706 }
c211e7c9
A
2707 if ( libSearchDir[0] == '\0' )
2708 throw "-L must be immediately followed by a directory path (no space)";
2709 struct stat statbuf;
2710 if ( stat(libSearchDir, &statbuf) == 0 ) {
2711 if ( statbuf.st_mode & S_IFDIR )
2712 libraryPaths.push_back(libSearchDir);
2713 else
2714 warning("path '%s' following -L not a directory", libSearchDir);
2715 }
2716 else {
a645023d 2717 warning("directory not found for option '-L%s'", libSearchDir);
c211e7c9
A
2718 }
2719 }
2720 else if ( (argv[i][0] == '-') && (argv[i][1] == 'F') ) {
2721 const char* frameworkSearchDir = &argv[i][2];
a645023d
A
2722 // Allow either "-F{path}" or "-F {path}".
2723 if (argv[i][2] == '\0') {
2724 // -F {path}. Make sure there is an argument following this.
2725 const char* path = argv[++i];
2726 if ( path == NULL )
2727 throw "-F missing argument";
2728 frameworkSearchDir = path;
2729 }
c211e7c9
A
2730 if ( frameworkSearchDir[0] == '\0' )
2731 throw "-F must be immediately followed by a directory path (no space)";
2732 struct stat statbuf;
2733 if ( stat(frameworkSearchDir, &statbuf) == 0 ) {
2734 if ( statbuf.st_mode & S_IFDIR )
2735 frameworkPaths.push_back(frameworkSearchDir);
2736 else
2737 warning("path '%s' following -F not a directory", frameworkSearchDir);
2738 }
2739 else {
a645023d 2740 warning("directory not found for option '-F%s'", frameworkSearchDir);
c211e7c9
A
2741 }
2742 }
c2646906
A
2743 else if ( strcmp(argv[i], "-Z") == 0 )
2744 addStandardLibraryDirectories = false;
6e880c60
A
2745 else if ( strcmp(argv[i], "-v") == 0 ) {
2746 fVerbose = true;
a61fdf0a
A
2747 extern const char ldVersionString[];
2748 fprintf(stderr, "%s", ldVersionString);
6e880c60 2749 // if only -v specified, exit cleanly
2f2f92e4 2750 if ( argc == 2 ) {
a645023d
A
2751 const char* ltoVers = lto::version();
2752 if ( ltoVers != NULL )
2753 fprintf(stderr, "%s\n", ltoVers);
6e880c60 2754 exit(0);
2f2f92e4 2755 }
6e880c60
A
2756 }
2757 else if ( strcmp(argv[i], "-syslibroot") == 0 ) {
2758 const char* path = argv[++i];
2759 if ( path == NULL )
2760 throw "-syslibroot missing argument";
2761 fSDKPaths.push_back(path);
2762 }
a61fdf0a 2763 else if ( strcmp(argv[i], "-search_paths_first") == 0 ) {
a61fdf0a
A
2764 fLibrarySearchMode = kSearchDylibAndArchiveInEachDir;
2765 }
a645023d
A
2766 else if ( strcmp(argv[i], "-search_dylibs_first") == 0 ) {
2767 fLibrarySearchMode = kSearchAllDirsForDylibsThenAllDirsForArchives;
2768 }
a61fdf0a 2769 else if ( strcmp(argv[i], "-w") == 0 ) {
2f2f92e4 2770 sEmitWarnings = false;
a61fdf0a 2771 }
b2fa67a8
A
2772 else if ( strcmp(argv[i], "-fatal_warnings") == 0 ) {
2773 sFatalWarnings = true;
2774 }
c2646906 2775 }
55e3d2f6
A
2776 int standardLibraryPathsStartIndex = libraryPaths.size();
2777 int standardFrameworkPathsStartIndex = frameworkPaths.size();
c2646906 2778 if ( addStandardLibraryDirectories ) {
6e880c60
A
2779 libraryPaths.push_back("/usr/lib");
2780 libraryPaths.push_back("/usr/local/lib");
d696c285 2781
6e880c60 2782 frameworkPaths.push_back("/Library/Frameworks/");
6e880c60 2783 frameworkPaths.push_back("/System/Library/Frameworks/");
55e3d2f6 2784 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
6e880c60 2785 }
d696c285 2786
77cc3118
A
2787 // <rdar://problem/5829579> Support for configure based hacks
2788 // if last -syslibroot is /, then ignore all syslibroots
2789 if ( fSDKPaths.size() > 0 ) {
2790 if ( strcmp(fSDKPaths.back(), "/") == 0 ) {
2791 fSDKPaths.clear();
2792 }
2793 }
2794
6e880c60 2795 // now merge sdk and library paths to make real search paths
d696c285 2796 fLibrarySearchPaths.reserve(libraryPaths.size()*(fSDKPaths.size()+1));
55e3d2f6
A
2797 int libIndex = 0;
2798 for (std::vector<const char*>::iterator it = libraryPaths.begin(); it != libraryPaths.end(); ++it, ++libIndex) {
6e880c60
A
2799 const char* libDir = *it;
2800 bool sdkOverride = false;
2801 if ( libDir[0] == '/' ) {
2802 char betterLibDir[PATH_MAX];
2803 if ( strstr(libDir, "/..") != NULL ) {
2804 if ( realpath(libDir, betterLibDir) != NULL )
d696c285 2805 libDir = strdup(betterLibDir);
6e880c60
A
2806 }
2807 const int libDirLen = strlen(libDir);
2808 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
2809 const char* sdkDir = *sdkit;
2810 const int sdkDirLen = strlen(sdkDir);
2811 char newPath[libDirLen + sdkDirLen+4];
2812 strcpy(newPath, sdkDir);
2813 if ( newPath[sdkDirLen-1] == '/' )
2814 newPath[sdkDirLen-1] = '\0';
2815 strcat(newPath, libDir);
2816 struct stat statBuffer;
2817 if ( stat(newPath, &statBuffer) == 0 ) {
2818 fLibrarySearchPaths.push_back(strdup(newPath));
2819 sdkOverride = true;
2820 }
2821 }
2822 }
55e3d2f6
A
2823 if ( !sdkOverride ) {
2824 if ( (libIndex >= standardLibraryPathsStartIndex) && (fSDKPaths.size() == 1) ) {
2825 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2826 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2827 }
2828 else {
2829 fLibrarySearchPaths.push_back(libDir);
2830 }
2831 }
6e880c60 2832 }
d696c285 2833
6e880c60 2834 // now merge sdk and framework paths to make real search paths
d696c285 2835 fFrameworkSearchPaths.reserve(frameworkPaths.size()*(fSDKPaths.size()+1));
55e3d2f6
A
2836 int frameIndex = 0;
2837 for (std::vector<const char*>::iterator it = frameworkPaths.begin(); it != frameworkPaths.end(); ++it, ++frameIndex) {
6e880c60
A
2838 const char* frameworkDir = *it;
2839 bool sdkOverride = false;
2840 if ( frameworkDir[0] == '/' ) {
2841 char betterFrameworkDir[PATH_MAX];
2842 if ( strstr(frameworkDir, "/..") != NULL ) {
2843 if ( realpath(frameworkDir, betterFrameworkDir) != NULL )
d696c285 2844 frameworkDir = strdup(betterFrameworkDir);
6e880c60
A
2845 }
2846 const int frameworkDirLen = strlen(frameworkDir);
2847 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
2848 const char* sdkDir = *sdkit;
2849 const int sdkDirLen = strlen(sdkDir);
2850 char newPath[frameworkDirLen + sdkDirLen+4];
2851 strcpy(newPath, sdkDir);
2852 if ( newPath[sdkDirLen-1] == '/' )
2853 newPath[sdkDirLen-1] = '\0';
2854 strcat(newPath, frameworkDir);
2855 struct stat statBuffer;
2856 if ( stat(newPath, &statBuffer) == 0 ) {
2857 fFrameworkSearchPaths.push_back(strdup(newPath));
2858 sdkOverride = true;
2859 }
2860 }
2861 }
55e3d2f6
A
2862 if ( !sdkOverride ) {
2863 if ( (frameIndex >= standardFrameworkPathsStartIndex) && (fSDKPaths.size() == 1) ) {
2864 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
2865 // if one SDK is specified and a standard library path is not in the SDK, don't use it
2866 }
2867 else {
2868 fFrameworkSearchPaths.push_back(frameworkDir);
2869 }
2870 }
6e880c60 2871 }
d696c285 2872
6e880c60
A
2873 if ( fVerbose ) {
2874 fprintf(stderr,"Library search paths:\n");
d696c285
A
2875 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
2876 it != fLibrarySearchPaths.end();
2877 it++)
6e880c60
A
2878 fprintf(stderr,"\t%s\n", *it);
2879 fprintf(stderr,"Framework search paths:\n");
d696c285
A
2880 for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin();
2881 it != fFrameworkSearchPaths.end();
2882 it++)
6e880c60 2883 fprintf(stderr,"\t%s\n", *it);
c2646906
A
2884 }
2885}
2886
2887// this is run before the command line is parsed
2888void Options::parsePreCommandLineEnvironmentSettings()
2889{
d696c285
A
2890 if ((getenv("LD_TRACE_ARCHIVES") != NULL)
2891 || (getenv("RC_TRACE_ARCHIVES") != NULL))
a645023d 2892 fTraceArchives = true;
d696c285
A
2893
2894 if ((getenv("LD_TRACE_DYLIBS") != NULL)
2895 || (getenv("RC_TRACE_DYLIBS") != NULL)) {
a645023d
A
2896 fTraceDylibs = true;
2897 fTraceIndirectDylibs = true;
c2646906 2898 }
d696c285
A
2899
2900 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL) {
2901 fTraceDylibSearching = true;
2902 }
2903
2904 if (getenv("LD_PRINT_OPTIONS") != NULL)
2905 fPrintOptions = true;
2906
a645023d
A
2907 if (fTraceDylibs || fTraceArchives)
2908 fTraceOutputFile = getenv("LD_TRACE_FILE");
a61fdf0a
A
2909
2910 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL)
2911 fPrintOrderFileStatistics = true;
2f2f92e4
A
2912
2913 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL)
2914 fSplitSegs = true;
2915
2916 if (getenv("LD_NO_ENCRYPT") != NULL)
2917 fEncryptable = false;
55e3d2f6
A
2918
2919 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL)
2920 fAllowCpuSubtypeMismatches = true;
2921
2f2f92e4 2922 sWarningsSideFilePath = getenv("LD_WARN_FILE");
a645023d
A
2923
2924 const char* customDyldPath = getenv("LD_DYLD_PATH");
2925 if ( customDyldPath != NULL )
2926 fDyldInstallPath = customDyldPath;
c2646906
A
2927}
2928
2f2f92e4 2929
c2646906
A
2930// this is run after the command line is parsed
2931void Options::parsePostCommandLineEnvironmentSettings()
2932{
d696c285
A
2933 // when building a dynamic main executable, default any use of @executable_path to output path
2934 if ( fExecutablePath == NULL && (fOutputKind == kDynamicExecutable) ) {
2935 fExecutablePath = fOutputFile;
2936 }
a61fdf0a
A
2937
2938 // allow build system to set default seg_addr_table
2939 if ( fSegAddrTablePath == NULL )
2940 fSegAddrTablePath = getenv("LD_SEG_ADDR_TABLE");
2941
2942 // allow build system to turn on prebinding
2943 if ( !fPrebind ) {
2944 fPrebind = ( getenv("LD_PREBIND") != NULL );
2945 }
2f2f92e4
A
2946
2947 // allow build system to force on dead-code-stripping
a645023d 2948 if ( !fDeadStrip ) {
2f2f92e4
A
2949 if ( getenv("LD_DEAD_STRIP") != NULL ) {
2950 switch (fOutputKind) {
2951 case Options::kDynamicLibrary:
2952 case Options::kDynamicExecutable:
2953 case Options::kDynamicBundle:
a645023d 2954 fDeadStrip = true;
2f2f92e4 2955 break;
55e3d2f6 2956 case Options::kPreload:
2f2f92e4
A
2957 case Options::kObjectFile:
2958 case Options::kDyld:
2959 case Options::kStaticExecutable:
55e3d2f6 2960 case Options::kKextBundle:
2f2f92e4
A
2961 break;
2962 }
2963 }
2964 }
2965
2966 // allow build system to force on -warn_commons
2967 if ( getenv("LD_WARN_COMMONS") != NULL )
2968 fWarnCommons = true;
4be885f6 2969
69a49097
A
2970}
2971
2972void Options::reconfigureDefaults()
2973{
2974 // sync reader options
2975 switch ( fOutputKind ) {
2976 case Options::kObjectFile:
a645023d 2977 fForFinalLinkedImage = false;
69a49097 2978 break;
a61fdf0a 2979 case Options::kDyld:
a645023d
A
2980 fForDyld = true;
2981 fForFinalLinkedImage = true;
2982 fNoEHLabels = true;
a61fdf0a 2983 break;
69a49097
A
2984 case Options::kDynamicLibrary:
2985 case Options::kDynamicBundle:
55e3d2f6 2986 case Options::kKextBundle:
a645023d
A
2987 fForFinalLinkedImage = true;
2988 fNoEHLabels = true;
a61fdf0a
A
2989 break;
2990 case Options::kDynamicExecutable:
2991 case Options::kStaticExecutable:
55e3d2f6 2992 case Options::kPreload:
a645023d
A
2993 fLinkingMainExecutable = true;
2994 fForFinalLinkedImage = true;
2995 fNoEHLabels = true;
69a49097
A
2996 break;
2997 }
2998
2999 // set default min OS version
a645023d 3000 if ( (fMacVersionMin == ld::macVersionUnset)
afe874b1 3001 && (fIOSVersionMin == ld::iOSVersionUnset) ) {
55e3d2f6
A
3002 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
3003 const char* macVers = getenv("MACOSX_DEPLOYMENT_TARGET");
3004 const char* iPhoneVers = getenv("IPHONEOS_DEPLOYMENT_TARGET");
a645023d 3005 const char* iOSVers = getenv("IOS_DEPLOYMENT_TARGET");
afe874b1 3006 const char* iOSSimulatorVers = getenv("IOS_SIMULATOR_DEPLOYMENT_TARGET");
55e3d2f6
A
3007 if ( macVers != NULL )
3008 setMacOSXVersionMin(macVers);
3009 else if ( iPhoneVers != NULL )
afe874b1 3010 setIOSVersionMin(iPhoneVers);
a645023d 3011 else if ( iOSVers != NULL )
afe874b1
A
3012 setIOSVersionMin(iOSVers);
3013 else if ( iOSSimulatorVers != NULL )
3014 setIOSVersionMin(iOSSimulatorVers);
55e3d2f6
A
3015 else {
3016 // if still nothing, set default based on architecture
3017 switch ( fArchitecture ) {
3018 case CPU_TYPE_I386:
3019 case CPU_TYPE_X86_64:
a645023d
A
3020 if ( (fOutputKind != Options::kObjectFile) && (fOutputKind != Options::kPreload) ) {
3021 #ifdef DEFAULT_MACOSX_MIN_VERSION
3022 warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION);
3023 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
3024 #else
3025 warning("-macosx_version_min not specificed, assuming 10.6");
3026 fMacVersionMin = ld::mac10_6;
3027 #endif
3028 }
55e3d2f6
A
3029 break;
3030 case CPU_TYPE_ARM:
a645023d
A
3031 if ( (fOutputKind != Options::kObjectFile) && (fOutputKind != Options::kPreload) ) {
3032 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
3033 warning("-ios_version_min not specificed, assuming " DEFAULT_IPHONEOS_MIN_VERSION);
afe874b1 3034 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION);
a645023d
A
3035 #elif defined(DEFAULT_MACOSX_MIN_VERSION)
3036 warning("-macosx_version_min not specificed, assuming " DEFAULT_MACOSX_MIN_VERSION);
3037 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
3038 #else
3039 warning("-macosx_version_min not specificed, assuming 10.6");
3040 fMacVersionMin = ld::mac10_6;
3041 #endif
3042 }
3043 break;
3044 default:
3045 // architecture will be infered ;ater by examining .o files
55e3d2f6
A
3046 break;
3047 }
3048 }
69a49097
A
3049 }
3050
55e3d2f6 3051
69a49097
A
3052 // adjust min based on architecture
3053 switch ( fArchitecture ) {
3054 case CPU_TYPE_I386:
afe874b1 3055 if ( (fMacVersionMin < ld::mac10_4) && (fIOSVersionMin == ld::iOSVersionUnset) ) {
2f2f92e4 3056 //warning("-macosx_version_min should be 10.4 or later for i386");
a645023d 3057 fMacVersionMin = ld::mac10_4;
69a49097
A
3058 }
3059 break;
69a49097 3060 case CPU_TYPE_X86_64:
a645023d 3061 if ( fMacVersionMin < ld::mac10_4 ) {
2f2f92e4 3062 //warning("-macosx_version_min should be 10.4 or later for x86_64");
a645023d 3063 fMacVersionMin = ld::mac10_4;
69a49097
A
3064 }
3065 break;
3066 }
55e3d2f6
A
3067
3068 // adjust kext type based on architecture
3069 if ( fOutputKind == kKextBundle ) {
3070 switch ( fArchitecture ) {
3071 case CPU_TYPE_X86_64:
3072 // x86_64 uses new MH_KEXT_BUNDLE type
55e3d2f6 3073 fMakeCompressedDyldInfo = false;
a645023d 3074 fMakeCompressedDyldInfoForceOff = true;
55e3d2f6
A
3075 fAllowTextRelocs = true;
3076 fUndefinedTreatment = kUndefinedDynamicLookup;
3077 break;
afe874b1
A
3078 case CPU_TYPE_ARM:
3079 if ( fIOSVersionMin >= ld::iOS_5_0 ) {
3080 // iOS 5.0 and later use new MH_KEXT_BUNDLE type
3081 fMakeCompressedDyldInfo = false;
3082 fMakeCompressedDyldInfoForceOff = true;
3083 fAllowTextRelocs = true;
3084 fUndefinedTreatment = kUndefinedDynamicLookup;
3085 break;
3086 }
3087 // else use object file
55e3d2f6 3088 case CPU_TYPE_I386:
55e3d2f6
A
3089 // use .o files
3090 fOutputKind = kObjectFile;
3091 break;
3092 }
3093 }
a61fdf0a 3094
55e3d2f6 3095 // disable implicit dylibs when targeting 10.3
2f2f92e4 3096 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
afe874b1 3097 if ( !minOS(ld::mac10_4, ld::iOS_2_0) )
a645023d 3098 fImplicitlyLinkPublicDylibs = false;
2f2f92e4
A
3099
3100
55e3d2f6
A
3101 // allow build system to force linker to ignore -prebind
3102 if ( getenv("LD_FORCE_NO_PREBIND") != NULL )
3103 fPrebind = false;
a61fdf0a 3104
55e3d2f6 3105 // allow build system to force linker to ignore -seg_addr_table
a61fdf0a
A
3106 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL )
3107 fSegAddrTablePath = NULL;
3108
3109 // check for base address specified externally
2f2f92e4 3110 if ( (fSegAddrTablePath != NULL) && (fOutputKind == Options::kDynamicLibrary) ) {
a61fdf0a 3111 parseSegAddrTable(fSegAddrTablePath, this->installPath());
2f2f92e4
A
3112 // HACK to support seg_addr_table entries that are physical paths instead of install paths
3113 if ( fBaseAddress == 0 ) {
55e3d2f6 3114 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
2f2f92e4 3115 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libstdc++.6.0.4.dylib");
55e3d2f6
A
3116 if ( fBaseAddress == 0 )
3117 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libstdc++.6.0.9.dylib");
3118 }
2f2f92e4
A
3119
3120 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
3121 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libz.1.2.3.dylib");
3122
3123 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
3124 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libutil1.0.dylib");
3125 }
3126 }
a61fdf0a 3127
a61fdf0a
A
3128 // split segs only allowed for dylibs
3129 if ( fSplitSegs ) {
b2fa67a8 3130 // split seg only supported for i386, and arm.
2f2f92e4 3131 switch ( fArchitecture ) {
2f2f92e4
A
3132 case CPU_TYPE_I386:
3133 if ( fOutputKind != Options::kDynamicLibrary )
3134 fSplitSegs = false;
3135 // make sure read and write segments are proper distance apart
3136 if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x10000000) )
3137 fBaseWritableAddress = fBaseAddress + 0x10000000;
3138 break;
3139 case CPU_TYPE_ARM:
3140 if ( fOutputKind != Options::kDynamicLibrary ) {
3141 fSplitSegs = false;
3142 }
3143 else {
3144 // make sure read and write segments are proper distance apart
3145 if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x08000000) )
3146 fBaseWritableAddress = fBaseAddress + 0x08000000;
3147 }
3148 break;
3149 default:
3150 fSplitSegs = false;
3151 fBaseAddress = 0;
3152 fBaseWritableAddress = 0;
a61fdf0a
A
3153 }
3154 }
3155
a645023d
A
3156 // set too-large size
3157 switch ( fArchitecture ) {
a645023d
A
3158 case CPU_TYPE_I386:
3159 fMaxAddress = 0xFFFFFFFF;
3160 break;
a645023d
A
3161 case CPU_TYPE_X86_64:
3162 break;
3163 case CPU_TYPE_ARM:
3164 switch ( fOutputKind ) {
3165 case Options::kDynamicExecutable:
3166 case Options::kDynamicLibrary:
3167 case Options::kDynamicBundle:
3168 // user land code is limited to low 1GB
3169 fMaxAddress = 0x2FFFFFFF;
3170 break;
3171 case Options::kStaticExecutable:
3172 case Options::kObjectFile:
3173 case Options::kDyld:
3174 case Options::kPreload:
3175 case Options::kKextBundle:
3176 fMaxAddress = 0xFFFFFFFF;
3177 break;
3178 }
3179 // range check -seg1addr for ARM
3180 if ( fBaseAddress > fMaxAddress ) {
3181 warning("ignoring -seg1addr 0x%08llX. Address out of range.", fBaseAddress);
3182 fBaseAddress = 0;
3183 }
3184 break;
3185 }
3186
55e3d2f6
A
3187 // <rdar://problem/6138961> -r implies no prebinding for all architectures
3188 if ( fOutputKind == Options::kObjectFile )
3189 fPrebind = false;
3190
a61fdf0a
A
3191 // disable prebinding depending on arch and min OS version
3192 if ( fPrebind ) {
3193 switch ( fArchitecture ) {
a61fdf0a 3194 case CPU_TYPE_I386:
a645023d 3195 if ( fMacVersionMin == ld::mac10_4 ) {
2f2f92e4 3196 // in 10.4 only split seg dylibs are prebound
a61fdf0a
A
3197 if ( (fOutputKind != Options::kDynamicLibrary) || ! fSplitSegs )
3198 fPrebind = false;
3199 }
a645023d 3200 else if ( fMacVersionMin >= ld::mac10_5 ) {
2f2f92e4
A
3201 // in 10.5 nothing is prebound
3202 fPrebind = false;
3203 }
afe874b1
A
3204 else if ( fIOSVersionMin != ld::iOSVersionUnset ) {
3205 // nothing in simulator is prebound
3206 fPrebind = false;
3207 }
2f2f92e4
A
3208 else {
3209 // in 10.3 and earlier only dylibs and main executables could be prebound
3210 switch ( fOutputKind ) {
3211 case Options::kDynamicExecutable:
3212 case Options::kDynamicLibrary:
3213 // only main executables and dylibs can be prebound
3214 break;
3215 case Options::kStaticExecutable:
3216 case Options::kDynamicBundle:
3217 case Options::kObjectFile:
3218 case Options::kDyld:
55e3d2f6
A
3219 case Options::kPreload:
3220 case Options::kKextBundle:
2f2f92e4
A
3221 // disable prebinding for everything else
3222 fPrebind = false;
3223 break;
3224 }
3225 }
a61fdf0a 3226 break;
a61fdf0a
A
3227 case CPU_TYPE_X86_64:
3228 fPrebind = false;
3229 break;
2f2f92e4
A
3230 case CPU_TYPE_ARM:
3231 switch ( fOutputKind ) {
3232 case Options::kDynamicExecutable:
3233 case Options::kDynamicLibrary:
3234 // only main executables and dylibs can be prebound
3235 break;
3236 case Options::kStaticExecutable:
3237 case Options::kDynamicBundle:
3238 case Options::kObjectFile:
3239 case Options::kDyld:
55e3d2f6
A
3240 case Options::kPreload:
3241 case Options::kKextBundle:
2f2f92e4
A
3242 // disable prebinding for everything else
3243 fPrebind = false;
3244 break;
3245 }
3246 break;
a61fdf0a
A
3247 }
3248 }
3249
2f2f92e4
A
3250 // only prebound images can be split-seg
3251 if ( fSplitSegs && !fPrebind )
3252 fSplitSegs = false;
a61fdf0a 3253
55e3d2f6
A
3254 // determine if info for shared region should be added
3255 if ( fOutputKind == Options::kDynamicLibrary ) {
afe874b1 3256 if ( minOS(ld::mac10_5, ld::iOS_3_1) )
55e3d2f6
A
3257 if ( !fPrebind )
3258 if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
3259 || (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
3260 fSharedRegionEligible = true;
3261 }
b2fa67a8
A
3262 else if ( fOutputKind == Options::kDyld ) {
3263 // <rdar://problem/10111122> Enable dyld to be put into the dyld shared cache
3264 fSharedRegionEligible = true;
3265 }
3266
a61fdf0a
A
3267 // figure out if module table is needed for compatibility with old ld/dyld
3268 if ( fOutputKind == Options::kDynamicLibrary ) {
3269 switch ( fArchitecture ) {
afe874b1
A
3270 case CPU_TYPE_I386:
3271 if ( fIOSVersionMin != ld::iOSVersionUnset ) // simulator never needs modules
3272 break;
2f2f92e4 3273 case CPU_TYPE_ARM:
55e3d2f6
A
3274 if ( fPrebind )
3275 fNeedsModuleTable = true; // redo_prebinding requires a module table
2f2f92e4 3276 break;
a61fdf0a
A
3277 }
3278 }
3279
2f2f92e4
A
3280 // <rdar://problem/5366363> -r -x implies -S
3281 if ( (fOutputKind == Options::kObjectFile) && (fLocalSymbolHandling == kLocalSymbolsNone) )
a645023d 3282 fDebugInfoStripping = Options::kDebugInfoNone;
55e3d2f6
A
3283
3284 // choose how to process unwind info
3285 switch ( fArchitecture ) {
3286 case CPU_TYPE_I386:
3287 case CPU_TYPE_X86_64:
3288 switch ( fOutputKind ) {
3289 case Options::kObjectFile:
3290 case Options::kStaticExecutable:
3291 case Options::kPreload:
3292 case Options::kKextBundle:
a645023d 3293 fAddCompactUnwindEncoding = false;
55e3d2f6
A
3294 break;
3295 case Options::kDyld:
3296 case Options::kDynamicLibrary:
3297 case Options::kDynamicBundle:
3298 case Options::kDynamicExecutable:
a645023d
A
3299 //if ( fAddCompactUnwindEncoding && (fVersionMin >= ld::mac10_6) )
3300 // fRemoveDwarfUnwindIfCompactExists = true;
55e3d2f6
A
3301 break;
3302 }
3303 break;
55e3d2f6 3304 case CPU_TYPE_ARM:
a645023d
A
3305 fAddCompactUnwindEncoding = false;
3306 fRemoveDwarfUnwindIfCompactExists = false;
55e3d2f6
A
3307 break;
3308 case 0:
3309 // if -arch is missing, assume we don't want compact unwind info
a645023d 3310 fAddCompactUnwindEncoding = false;
55e3d2f6
A
3311 break;
3312 }
3313
2f2f92e4
A
3314 // only ARM main executables can be encrypted
3315 if ( fOutputKind != Options::kDynamicExecutable )
3316 fEncryptable = false;
3317 if ( fArchitecture != CPU_TYPE_ARM )
3318 fEncryptable = false;
4be885f6 3319
55e3d2f6
A
3320 // don't move inits in dyld because dyld wants certain
3321 // entries point at stable locations at the start of __text
3322 if ( fOutputKind == Options::kDyld )
a645023d 3323 fAutoOrderInitializers = false;
55e3d2f6
A
3324
3325
3326 // disable __data ordering for some output kinds
3327 switch ( fOutputKind ) {
3328 case Options::kObjectFile:
3329 case Options::kDyld:
3330 case Options::kStaticExecutable:
3331 case Options::kPreload:
3332 case Options::kKextBundle:
3333 fOrderData = false;
3334 break;
3335 case Options::kDynamicExecutable:
3336 case Options::kDynamicLibrary:
3337 case Options::kDynamicBundle:
3338 break;
3339 }
3340
a645023d
A
3341 // only use compressed LINKEDIT for final linked images
3342 switch ( fOutputKind ) {
3343 case Options::kDynamicExecutable:
3344 case Options::kDynamicLibrary:
3345 case Options::kDynamicBundle:
3346 break;
3347 case Options::kPreload:
3348 case Options::kStaticExecutable:
3349 case Options::kObjectFile:
3350 case Options::kDyld:
3351 case Options::kKextBundle:
3352 fMakeCompressedDyldInfoForceOff = true;
3353 break;
3354 }
3355 if ( fMakeCompressedDyldInfoForceOff )
3356 fMakeCompressedDyldInfo = false;
3357
3358
fb24a050
A
3359 // only use compressed LINKEDIT for:
3360 // x86_64 and i386 on Mac OS X 10.6 or later
3361 // arm on iPhoneOS 3.1 or later
55e3d2f6
A
3362 if ( fMakeCompressedDyldInfo ) {
3363 switch (fArchitecture) {
3364 case CPU_TYPE_I386:
afe874b1
A
3365 if ( fIOSVersionMin != ld::iOSVersionUnset ) // simulator always uses compressed LINKEDIT
3366 break;
55e3d2f6 3367 case CPU_TYPE_X86_64:
a645023d 3368 if ( fMacVersionMin < ld::mac10_6 )
55e3d2f6
A
3369 fMakeCompressedDyldInfo = false;
3370 break;
55e3d2f6 3371 case CPU_TYPE_ARM:
afe874b1 3372 if ( !minOS(ld::mac10_6, ld::iOS_3_1) )
fb24a050
A
3373 fMakeCompressedDyldInfo = false;
3374 break;
55e3d2f6
A
3375 default:
3376 fMakeCompressedDyldInfo = false;
3377 }
3378 }
3379
55e3d2f6
A
3380
3381 // only ARM enforces that cpu-sub-types must match
3382 if ( fArchitecture != CPU_TYPE_ARM )
3383 fAllowCpuSubtypeMismatches = true;
4be885f6
A
3384
3385 // only final linked images can not optimize zero fill sections
3386 if ( fOutputKind == Options::kObjectFile )
a645023d
A
3387 fOptimizeZeroFill = true;
3388
3389 // all undefines in -r mode
3390// if ( fOutputKind == Options::kObjectFile )
3391// fUndefinedTreatment = kUndefinedSuppress;
fb24a050
A
3392
3393 // only dynamic final linked images should warn about use of commmons
3394 if ( fWarnCommons ) {
3395 switch ( fOutputKind ) {
3396 case Options::kDynamicExecutable:
3397 case Options::kDynamicLibrary:
3398 case Options::kDynamicBundle:
3399 break;
3400 case Options::kPreload:
3401 case Options::kStaticExecutable:
3402 case Options::kObjectFile:
3403 case Options::kDyld:
3404 case Options::kKextBundle:
3405 fWarnCommons = false;
3406 break;
3407 }
3408 }
3409
3410 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
afe874b1 3411 if ( minOS(ld::mac10_5, ld::iOS_2_0) )
fb24a050 3412 fUseSimplifiedDylibReExports = true;
a645023d
A
3413
3414 // Mac OS X 10.7 and iOS 4.2 support LC_LOAD_UPWARD_DYLIB
afe874b1 3415 if ( minOS(ld::mac10_7, ld::iOS_4_2) && (fOutputKind == kDynamicLibrary) )
a645023d 3416 fCanUseUpwardDylib = true;
d9246299 3417
afe874b1 3418 // MacOSX 10.7 defaults to PIE
60ce07c1
A
3419 if ( ((fArchitecture == CPU_TYPE_X86_64) || (fArchitecture == CPU_TYPE_I386))
3420 && (fOutputKind == kDynamicExecutable)
3421 && (fMacVersionMin >= ld::mac10_7) ) {
3422 fPositionIndependentExecutable = true;
d9246299 3423 }
a645023d
A
3424
3425 // armv7 for iOS4.3 defaults to PIE
3426 if ( (fArchitecture == CPU_TYPE_ARM)
afe874b1 3427 && fArchSupportsThumb2
a645023d 3428 && (fOutputKind == kDynamicExecutable)
afe874b1 3429 && (fIOSVersionMin >= ld::iOS_4_3) ) {
a645023d
A
3430 fPositionIndependentExecutable = true;
3431 }
3432
3433 // -no_pie anywhere on command line disable PIE
3434 if ( fDisablePositionIndependentExecutable )
3435 fPositionIndependentExecutable = false;
3436
3437 // set fOutputSlidable
3438 switch ( fOutputKind ) {
3439 case Options::kObjectFile:
3440 case Options::kStaticExecutable:
3441 fOutputSlidable = false;
3442 break;
3443 case Options::kDynamicExecutable:
3444 fOutputSlidable = fPositionIndependentExecutable;
3445 break;
3446 case Options::kPreload:
3447 fOutputSlidable = fPIEOnCommandLine;
3448 break;
3449 case Options::kDyld:
3450 case Options::kDynamicLibrary:
3451 case Options::kDynamicBundle:
3452 case Options::kKextBundle:
3453 fOutputSlidable = true;
3454 break;
3455 }
3456
3457 // let linker know if thread local variables are supported
3458 if ( fMacVersionMin >= ld::mac10_7 ) {
3459 fTLVSupport = true;
3460 }
3461
afe874b1 3462 // default to adding version load command for dynamic code, static code must opt-in
a645023d
A
3463 switch ( fOutputKind ) {
3464 case Options::kObjectFile:
afe874b1
A
3465 fVersionLoadCommand = false;
3466 break;
a645023d
A
3467 case Options::kStaticExecutable:
3468 case Options::kPreload:
3469 case Options::kKextBundle:
afe874b1
A
3470 if ( fVersionLoadCommandForcedOn )
3471 fVersionLoadCommand = true;
a645023d
A
3472 break;
3473 case Options::kDynamicExecutable:
3474 case Options::kDyld:
3475 case Options::kDynamicLibrary:
3476 case Options::kDynamicBundle:
afe874b1
A
3477 if ( !fVersionLoadCommandForcedOff )
3478 fVersionLoadCommand = true;
3479 // <rdar://problem/9945513> for now, don't create version load commands for iOS simulator builds
3480 if ( fVersionLoadCommand && (fArchitecture == CPU_TYPE_I386) ) {
3481 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
3482 if ( strstr(*sdkit, "/iPhoneSimulator.platform/") != NULL )
3483 fVersionLoadCommand = false;
3484 }
3485 }
a645023d
A
3486 break;
3487 }
3488
afe874b1
A
3489 // default to adding functions start for dynamic code, static code must opt-in
3490 switch ( fOutputKind ) {
3491 case Options::kObjectFile:
3492 fFunctionStartsLoadCommand = false;
3493 break;
3494 case Options::kPreload:
3495 case Options::kStaticExecutable:
3496 case Options::kKextBundle:
3497 if ( fFunctionStartsForcedOn )
3498 fFunctionStartsLoadCommand = true;
3499 break;
3500 case Options::kDynamicExecutable:
3501 case Options::kDyld:
3502 case Options::kDynamicLibrary:
3503 case Options::kDynamicBundle:
3504 if ( !fFunctionStartsForcedOff )
3505 fFunctionStartsLoadCommand = true;
3506 break;
3507 }
3508
a645023d 3509 // support re-export of individual symbols in MacOSX 10.7 and iOS 4.2
afe874b1 3510 if ( (fOutputKind == kDynamicLibrary) && minOS(ld::mac10_7, ld::iOS_4_2) )
a645023d
A
3511 fCanReExportSymbols = true;
3512
3513 // ObjC optimization is only in dynamic final linked images
3514 switch ( fOutputKind ) {
3515 case Options::kObjectFile:
3516 case Options::kStaticExecutable:
3517 case Options::kPreload:
3518 case Options::kKextBundle:
3519 case Options::kDyld:
3520 fObjcCategoryMerging = false;
3521 break;
3522 case Options::kDynamicExecutable:
3523 case Options::kDynamicLibrary:
3524 case Options::kDynamicBundle:
3525 break;
3526 }
3527
3528 // i386 main executables linked on Mac OS X 10.7 default to NX heap
3529 // regardless of target unless overriden with -allow_heap_execute anywhere
3530 // on the command line
3531 if ( (fArchitecture == CPU_TYPE_I386) && (fOutputKind == kDynamicExecutable) && !fDisableNonExecutableHeap)
3532 fNonExecutableHeap = true;
c2646906
A
3533}
3534
3535void Options::checkIllegalOptionCombinations()
3536{
3537 // check -undefined setting
3538 switch ( fUndefinedTreatment ) {
3539 case kUndefinedError:
3540 case kUndefinedDynamicLookup:
3541 // always legal
3542 break;
3543 case kUndefinedWarning:
3544 case kUndefinedSuppress:
3545 // requires flat namespace
3546 if ( fNameSpace == kTwoLevelNameSpace )
3547 throw "can't use -undefined warning or suppress with -twolevel_namespace";
3548 break;
3549 }
d696c285 3550
c2646906
A
3551 // unify -sub_umbrella with dylibs
3552 for (std::vector<const char*>::iterator it = fSubUmbellas.begin(); it != fSubUmbellas.end(); it++) {
3553 const char* subUmbrella = *it;
3554 bool found = false;
3555 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
3556 Options::FileInfo& info = *fit;
3557 const char* lastSlash = strrchr(info.path, '/');
3558 if ( lastSlash == NULL )
3559 lastSlash = info.path - 1;
3560 if ( strcmp(&lastSlash[1], subUmbrella) == 0 ) {
3561 info.options.fReExport = true;
3562 found = true;
3563 break;
3564 }
3565 }
2f2f92e4
A
3566 if ( ! found )
3567 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella);
c2646906 3568 }
d696c285 3569
c2646906
A
3570 // unify -sub_library with dylibs
3571 for (std::vector<const char*>::iterator it = fSubLibraries.begin(); it != fSubLibraries.end(); it++) {
3572 const char* subLibrary = *it;
3573 bool found = false;
3574 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
3575 Options::FileInfo& info = *fit;
3576 const char* lastSlash = strrchr(info.path, '/');
3577 if ( lastSlash == NULL )
3578 lastSlash = info.path - 1;
69a49097 3579 const char* dot = strchr(&lastSlash[1], '.');
c2646906
A
3580 if ( dot == NULL )
3581 dot = &lastSlash[strlen(lastSlash)];
3582 if ( strncmp(&lastSlash[1], subLibrary, dot-lastSlash-1) == 0 ) {
3583 info.options.fReExport = true;
3584 found = true;
3585 break;
3586 }
3587 }
2f2f92e4
A
3588 if ( ! found )
3589 warning("-sub_library %s does not match a supplied dylib", subLibrary);
c2646906 3590 }
d696c285 3591
c2646906
A
3592 // sync reader options
3593 if ( fNameSpace != kTwoLevelNameSpace )
a645023d 3594 fFlatNamespace = true;
c2646906
A
3595
3596 // check -stack_addr
d696c285 3597 if ( fStackAddr != 0 ) {
c2646906
A
3598 switch (fArchitecture) {
3599 case CPU_TYPE_I386:
2f2f92e4 3600 case CPU_TYPE_ARM:
d696c285 3601 if ( fStackAddr > 0xFFFFFFFF )
c2646906
A
3602 throw "-stack_addr must be < 4G for 32-bit processes";
3603 break;
69a49097 3604 case CPU_TYPE_X86_64:
c2646906
A
3605 break;
3606 }
3607 if ( (fStackAddr & -4096) != fStackAddr )
3608 throw "-stack_addr must be multiples of 4K";
3609 if ( fStackSize == 0 )
3610 throw "-stack_addr must be used with -stack_size";
3611 }
d696c285 3612
c2646906 3613 // check -stack_size
d696c285 3614 if ( fStackSize != 0 ) {
c2646906
A
3615 switch (fArchitecture) {
3616 case CPU_TYPE_I386:
d696c285 3617 if ( fStackSize > 0xFFFFFFFF )
c2646906
A
3618 throw "-stack_size must be < 4G for 32-bit processes";
3619 if ( fStackAddr == 0 ) {
c2646906
A
3620 fStackAddr = 0xC0000000;
3621 }
2f2f92e4
A
3622 if ( (fStackAddr > 0xB0000000) && ((fStackAddr-fStackSize) < 0xB0000000) )
3623 warning("custom stack placement overlaps and will disable shared region");
c2646906 3624 break;
2f2f92e4 3625 case CPU_TYPE_ARM:
fb24a050
A
3626 if ( fStackSize > 0x2F000000 )
3627 throw "-stack_size must be < 752MB";
2f2f92e4 3628 if ( fStackAddr == 0 )
fb24a050
A
3629 fStackAddr = 0x2F000000;
3630 if ( fStackAddr > 0x30000000)
3631 throw "-stack_addr must be < 0x30000000 for arm";
69a49097 3632 case CPU_TYPE_X86_64:
c2646906 3633 if ( fStackAddr == 0 ) {
a61fdf0a 3634 fStackAddr = 0x00007FFF5C000000LL;
c2646906
A
3635 }
3636 break;
3637 }
3638 if ( (fStackSize & -4096) != fStackSize )
3639 throw "-stack_size must be multiples of 4K";
3640 switch ( fOutputKind ) {
3641 case Options::kDynamicExecutable:
3642 case Options::kStaticExecutable:
d696c285 3643 // custom stack size only legal when building main executable
c2646906
A
3644 break;
3645 case Options::kDynamicLibrary:
3646 case Options::kDynamicBundle:
3647 case Options::kObjectFile:
3648 case Options::kDyld:
55e3d2f6
A
3649 case Options::kPreload:
3650 case Options::kKextBundle:
c2646906
A
3651 throw "-stack_size option can only be used when linking a main executable";
3652 }
a645023d
A
3653 if ( fStackSize > fStackAddr )
3654 throwf("-stack_size (0x%08llX) must be smaller than -stack_addr (0x%08llX)", fStackSize, fStackAddr);
c2646906 3655 }
d696c285
A
3656
3657 // check that -allow_stack_execute is only used with main executables
3658 if ( fExecutableStack ) {
3659 switch ( fOutputKind ) {
3660 case Options::kDynamicExecutable:
3661 case Options::kStaticExecutable:
3662 // -allow_stack_execute size only legal when building main executable
3663 break;
3664 case Options::kDynamicLibrary:
3665 case Options::kDynamicBundle:
3666 case Options::kObjectFile:
3667 case Options::kDyld:
55e3d2f6
A
3668 case Options::kPreload:
3669 case Options::kKextBundle:
d696c285
A
3670 throw "-allow_stack_execute option can only be used when linking a main executable";
3671 }
3672 }
3673
a645023d
A
3674 // check that -allow_heap_execute is only used with i386 main executables
3675 if ( fDisableNonExecutableHeap ) {
3676 if ( fArchitecture != CPU_TYPE_I386 )
3677 throw "-allow_heap_execute option can only be used when linking for i386";
3678 switch ( fOutputKind ) {
3679 case Options::kDynamicExecutable:
3680 // -allow_heap_execute only legal when building main executable
3681 break;
3682 case Options::kStaticExecutable:
3683 case Options::kDynamicLibrary:
3684 case Options::kDynamicBundle:
3685 case Options::kObjectFile:
3686 case Options::kDyld:
3687 case Options::kPreload:
3688 case Options::kKextBundle:
3689 throw "-allow_heap_execute option can only be used when linking a main executable";
3690 }
3691 }
3692
a61fdf0a
A
3693 // check -client_name is only used when making a bundle or main executable
3694 if ( fClientName != NULL ) {
3695 switch ( fOutputKind ) {
3696 case Options::kDynamicExecutable:
3697 case Options::kDynamicBundle:
3698 break;
3699 case Options::kStaticExecutable:
3700 case Options::kDynamicLibrary:
3701 case Options::kObjectFile:
3702 case Options::kDyld:
55e3d2f6
A
3703 case Options::kPreload:
3704 case Options::kKextBundle:
a61fdf0a
A
3705 throw "-client_name can only be used with -bundle";
3706 }
3707 }
3708
c2646906
A
3709 // check -init is only used when building a dylib
3710 if ( (fInitFunctionName != NULL) && (fOutputKind != Options::kDynamicLibrary) )
3711 throw "-init can only be used with -dynamiclib";
c2646906 3712
69a49097
A
3713 // check -bundle_loader only used with -bundle
3714 if ( (fBundleLoader != NULL) && (fOutputKind != Options::kDynamicBundle) )
3715 throw "-bundle_loader can only be used with -bundle";
3716
a61fdf0a
A
3717 // check -dtrace not used with -r
3718 if ( (fDtraceScriptName != NULL) && (fOutputKind == Options::kObjectFile) )
3719 throw "-dtrace can only be used when creating final linked images";
3720
69a49097 3721 // check -d can only be used with -r
a645023d 3722 if ( fMakeTentativeDefinitionsReal && (fOutputKind != Options::kObjectFile) )
69a49097 3723 throw "-d can only be used with -r";
a61fdf0a
A
3724
3725 // check that -root_safe is not used with -r
a645023d 3726 if ( fRootSafe && (fOutputKind == Options::kObjectFile) )
a61fdf0a
A
3727 throw "-root_safe cannot be used with -r";
3728
3729 // check that -setuid_safe is not used with -r
a645023d 3730 if ( fSetuidSafe && (fOutputKind == Options::kObjectFile) )
a61fdf0a
A
3731 throw "-setuid_safe cannot be used with -r";
3732
a645023d
A
3733 // rdar://problem/4718189 map ObjC class names to new runtime names
3734 bool alterObjC1ClassNamesToObjC2 = false;
3735 switch (fArchitecture) {
3736 case CPU_TYPE_I386:
3737 // i386 only uses new symbols when using objc2 ABI
3738 if ( fObjCABIVersion2Override )
3739 alterObjC1ClassNamesToObjC2 = true;
3740 break;
a645023d
A
3741 case CPU_TYPE_X86_64:
3742 case CPU_TYPE_ARM:
3743 alterObjC1ClassNamesToObjC2 = true;
3744 break;
3745 }
3746
d696c285 3747 // make sure all required exported symbols exist
a61fdf0a 3748 std::vector<const char*> impliedExports;
a645023d 3749 for (NameSet::iterator it=fExportSymbols.regularBegin(); it != fExportSymbols.regularEnd(); ++it) {
d696c285 3750 const char* name = *it;
a61fdf0a 3751 const int len = strlen(name);
a645023d
A
3752 if ( (strcmp(&name[len-3], ".eh") == 0) || (strncmp(name, ".objc_category_name_", 20) == 0) ) {
3753 // never export .eh symbols
2f2f92e4 3754 warning("ignoring %s in export list", name);
a645023d
A
3755 }
3756 else if ( (fArchitecture == CPU_TYPE_I386) && !fObjCABIVersion2Override && (strncmp(name, "_OBJC_CLASS_$", 13) == 0) ) {
3757 warning("ignoring Objc2 Class symbol %s in i386 export list", name);
3758 fRemovedExports.insert(name);
3759 }
3760 else if ( alterObjC1ClassNamesToObjC2 && (strncmp(name, ".objc_class_name_", 17) == 0) ) {
3761 // linking ObjC2 ABI, but have ObjC1 ABI name in export list. Change it to intended name
3762 fRemovedExports.insert(name);
3763 char* temp;
3764 asprintf(&temp, "_OBJC_CLASS_$_%s", &name[17]);
3765 impliedExports.push_back(temp);
3766 asprintf(&temp, "_OBJC_METACLASS_$_%s", &name[17]);
3767 impliedExports.push_back(temp);
3768 }
3769 else {
d696c285 3770 fInitialUndefines.push_back(name);
a61fdf0a 3771 }
d696c285 3772 }
a645023d
A
3773 fExportSymbols.remove(fRemovedExports);
3774 for (std::vector<const char*>::iterator it=impliedExports.begin(); it != impliedExports.end(); ++it) {
a61fdf0a
A
3775 const char* name = *it;
3776 fExportSymbols.insert(name);
3777 fInitialUndefines.push_back(name);
3778 }
3779
a645023d
A
3780 // make sure all required re-exported symbols exist
3781 for (NameSet::iterator it=fReExportSymbols.regularBegin(); it != fReExportSymbols.regularEnd(); ++it) {
3782 fInitialUndefines.push_back(*it);
3783 }
3784
afe874b1 3785 // make sure that -init symbol exists
69a49097
A
3786 if ( fInitFunctionName != NULL )
3787 fInitialUndefines.push_back(fInitFunctionName);
3788
afe874b1
A
3789 // make sure that entry symbol exists
3790 switch ( fOutputKind ) {
3791 case Options::kDynamicExecutable:
3792 case Options::kStaticExecutable:
3793 case Options::kDyld:
3794 case Options::kPreload:
3795 fInitialUndefines.push_back(fEntryName);
3796 break;
3797 case Options::kDynamicLibrary:
3798 case Options::kDynamicBundle:
3799 case Options::kObjectFile:
3800 case Options::kKextBundle:
3801 break;
3802 }
3803
a645023d
A
3804 // make sure every alias base exists
3805 for (std::vector<AliasPair>::iterator it=fAliases.begin(); it != fAliases.end(); ++it) {
3806 fInitialUndefines.push_back(it->realName);
3807 }
3808
a61fdf0a
A
3809 // check custom segments
3810 if ( fCustomSegmentAddresses.size() != 0 ) {
3811 // verify no segment is in zero page
3812 if ( fZeroPageSize != ULLONG_MAX ) {
3813 for (std::vector<SegmentStart>::iterator it = fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
a645023d 3814 if ( it->address < fZeroPageSize )
fb24a050 3815 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it->name, it->address);
a61fdf0a
A
3816 }
3817 }
3818 // verify no duplicates
3819 for (std::vector<SegmentStart>::iterator it = fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
3820 for (std::vector<SegmentStart>::iterator it2 = fCustomSegmentAddresses.begin(); it2 != fCustomSegmentAddresses.end(); ++it2) {
3821 if ( (it->address == it2->address) && (it != it2) )
3822 throwf("duplicate -segaddr addresses for %s and %s", it->name, it2->name);
3823 }
3824 // a custom segment address of zero will disable the use of a zero page
3825 if ( it->address == 0 )
3826 fZeroPageSize = 0;
3827 }
3828 }
3829
69a49097
A
3830 if ( fZeroPageSize == ULLONG_MAX ) {
3831 // zero page size not specified on command line, set default
3832 switch (fArchitecture) {
3833 case CPU_TYPE_I386:
2f2f92e4 3834 case CPU_TYPE_ARM:
69a49097
A
3835 // first 4KB for 32-bit architectures
3836 fZeroPageSize = 0x1000;
3837 break;
69a49097
A
3838 case CPU_TYPE_X86_64:
3839 // first 4GB for x86_64 on all OS's
3840 fZeroPageSize = 0x100000000ULL;
3841 break;
3842 default:
3843 // if -arch not used, default to 4K zero-page
3844 fZeroPageSize = 0x1000;
3845 }
3846 }
3847 else {
3848 switch ( fOutputKind ) {
3849 case Options::kDynamicExecutable:
3850 case Options::kStaticExecutable:
3851 // -pagezero_size size only legal when building main executable
3852 break;
3853 case Options::kDynamicLibrary:
3854 case Options::kDynamicBundle:
3855 case Options::kObjectFile:
3856 case Options::kDyld:
55e3d2f6
A
3857 case Options::kPreload:
3858 case Options::kKextBundle:
a61fdf0a
A
3859 if ( fZeroPageSize != 0 )
3860 throw "-pagezero_size option can only be used when linking a main executable";
3861 }
69a49097
A
3862 }
3863
a645023d
A
3864 // if main executable with custom base address, model zero page as custom segment
3865 if ( (fOutputKind == Options::kDynamicExecutable) && (fBaseAddress != 0) && (fZeroPageSize != 0) ) {
3866 SegmentStart seg;
3867 seg.name = "__PAGEZERO";
3868 seg.address = 0;;
3869 fCustomSegmentAddresses.push_back(seg);
3870 }
3871
69a49097 3872 // -dead_strip and -r are incompatible
a645023d 3873 if ( fDeadStrip && (fOutputKind == Options::kObjectFile) )
2f2f92e4 3874 throw "-r and -dead_strip cannot be used together";
c2646906 3875
a61fdf0a
A
3876 // can't use -rpath unless targeting 10.5 or later
3877 if ( fRPaths.size() > 0 ) {
afe874b1 3878 if ( !minOS(ld::mac10_5, ld::iOS_2_0) )
2f2f92e4 3879 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
a61fdf0a
A
3880 switch ( fOutputKind ) {
3881 case Options::kDynamicExecutable:
3882 case Options::kDynamicLibrary:
3883 case Options::kDynamicBundle:
3884 break;
3885 case Options::kStaticExecutable:
3886 case Options::kObjectFile:
3887 case Options::kDyld:
55e3d2f6
A
3888 case Options::kPreload:
3889 case Options::kKextBundle:
a61fdf0a
A
3890 throw "-rpath can only be used when creating a dynamic final linked image";
3891 }
3892 }
3893
3894 // check -pie is only used when building a dynamic main executable for 10.5
3895 if ( fPositionIndependentExecutable ) {
55e3d2f6
A
3896 switch ( fOutputKind ) {
3897 case Options::kDynamicExecutable:
afe874b1
A
3898 if ( !minOS(ld::mac10_5, ld::iOS_4_2) ) {
3899 if ( fIOSVersionMin == ld::iOSVersionUnset )
a645023d
A
3900 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
3901 else
3902 throw "-pie can only be used when targeting iOS 4.2 or later";
3903 }
d9246299 3904 break;
55e3d2f6
A
3905 case Options::kPreload:
3906 break;
3907 case Options::kDynamicLibrary:
3908 case Options::kDynamicBundle:
3909 warning("-pie being ignored. It is only used when linking a main executable");
a645023d 3910 fPositionIndependentExecutable = false;
55e3d2f6
A
3911 break;
3912 case Options::kStaticExecutable:
3913 case Options::kObjectFile:
3914 case Options::kDyld:
3915 case Options::kKextBundle:
3916 throw "-pie can only be used when linking a main executable";
3917 }
a61fdf0a 3918 }
55e3d2f6
A
3919
3920 // check -read_only_relocs is not used with x86_64
3921 if ( fAllowTextRelocs ) {
3922 if ( (fArchitecture == CPU_TYPE_X86_64) && (fOutputKind != kKextBundle) ) {
3923 warning("-read_only_relocs cannot be used with x86_64");
3924 fAllowTextRelocs = false;
3925 }
3926 }
3927
3928 // check -mark_auto_dead_strip is only used with dylibs
3929 if ( fMarkDeadStrippableDylib ) {
3930 if ( fOutputKind != Options::kDynamicLibrary ) {
3931 warning("-mark_auto_dead_strip can only be used when creating a dylib");
3932 fMarkDeadStrippableDylib = false;
3933 }
3934 }
3935
4be885f6
A
3936 // -force_cpusubtype_ALL is not supported for ARM
3937 if ( fForceSubtypeAll ) {
3938 if ( fArchitecture == CPU_TYPE_ARM ) {
3939 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
3940 }
3941 }
a645023d
A
3942
3943 // -reexported_symbols_list can only be used with -dynamiclib
3944 if ( !fReExportSymbols.empty() ) {
3945 if ( fOutputKind != Options::kDynamicLibrary )
3946 throw "-reexported_symbols_list can only used used when created dynamic libraries";
afe874b1 3947 if ( !minOS(ld::mac10_7, ld::iOS_4_2) )
a645023d
A
3948 throw "targeted OS version does not support -reexported_symbols_list";
3949 }
3950
3951 // -dyld_env can only be used with main executables
3952 if ( (fOutputKind != Options::kDynamicExecutable) && (fDyldEnvironExtras.size() != 0) )
3953 throw "-dyld_env can only used used when created main executables";
55e3d2f6 3954}
74cfe461
A
3955
3956
a61fdf0a
A
3957void Options::checkForClassic(int argc, const char* argv[])
3958{
3959 // scan options
3960 bool archFound = false;
3961 bool staticFound = false;
3962 bool dtraceFound = false;
55e3d2f6 3963 bool kextFound = false;
a61fdf0a
A
3964 bool rFound = false;
3965 bool creatingMachKernel = false;
3966 bool newLinker = false;
55e3d2f6
A
3967
3968 // build command line buffer in case ld crashes
a645023d
A
3969 const char* srcRoot = getenv("SRCROOT");
3970 if ( srcRoot != NULL ) {
3971 strlcpy(crashreporterBuffer, "SRCROOT=", crashreporterBufferSize);
3972 strlcat(crashreporterBuffer, srcRoot, crashreporterBufferSize);
3973 strlcat(crashreporterBuffer, "\n", crashreporterBufferSize);
3974 }
3975#ifdef LD_VERS
3976 strlcat(crashreporterBuffer, LD_VERS, crashreporterBufferSize);
3977 strlcat(crashreporterBuffer, "\n", crashreporterBufferSize);
3978#endif
3979 strlcat(crashreporterBuffer, "ld ", crashreporterBufferSize);
55e3d2f6 3980 for(int i=1; i < argc; ++i) {
a645023d
A
3981 strlcat(crashreporterBuffer, argv[i], crashreporterBufferSize);
3982 strlcat(crashreporterBuffer, " ", crashreporterBufferSize);
55e3d2f6 3983 }
74cfe461 3984
a61fdf0a
A
3985 for(int i=0; i < argc; ++i) {
3986 const char* arg = argv[i];
3987 if ( arg[0] == '-' ) {
3988 if ( strcmp(arg, "-arch") == 0 ) {
3989 parseArch(argv[++i]);
3990 archFound = true;
3991 }
3992 else if ( strcmp(arg, "-static") == 0 ) {
3993 staticFound = true;
3994 }
55e3d2f6
A
3995 else if ( strcmp(arg, "-kext") == 0 ) {
3996 kextFound = true;
3997 }
a61fdf0a
A
3998 else if ( strcmp(arg, "-dtrace") == 0 ) {
3999 dtraceFound = true;
4000 }
4001 else if ( strcmp(arg, "-r") == 0 ) {
4002 rFound = true;
4003 }
4004 else if ( strcmp(arg, "-new_linker") == 0 ) {
4005 newLinker = true;
4006 }
4007 else if ( strcmp(arg, "-classic_linker") == 0 ) {
4008 // ld_classic does not understand this option, so remove it
4009 for(int j=i; j < argc; ++j)
4010 argv[j] = argv[j+1];
b2fa67a8 4011 warning("using ld_classic");
a61fdf0a
A
4012 this->gotoClassicLinker(argc-1, argv);
4013 }
4014 else if ( strcmp(arg, "-o") == 0 ) {
4015 const char* outfile = argv[++i];
4016 if ( (outfile != NULL) && (strstr(outfile, "/mach_kernel") != NULL) )
4017 creatingMachKernel = true;
4018 }
4019 }
4020 }
a645023d 4021
a61fdf0a
A
4022 // -dtrace only supported by new linker
4023 if( dtraceFound )
4024 return;
4025
4026 if( archFound ) {
4027 switch ( fArchitecture ) {
a61fdf0a 4028 case CPU_TYPE_I386:
55e3d2f6 4029 if ( (staticFound || kextFound) && !newLinker ) {
a61fdf0a 4030 // this environment variable will disable use of ld_classic for -static links
2f2f92e4 4031 if ( getenv("LD_NO_CLASSIC_LINKER_STATIC") == NULL ) {
a61fdf0a 4032 this->gotoClassicLinker(argc, argv);
2f2f92e4 4033 }
a61fdf0a
A
4034 }
4035 break;
4036 }
4037 }
4038 else {
4039 // work around for VSPTool
b2fa67a8
A
4040 if ( staticFound ) {
4041 warning("using ld_classic");
a61fdf0a 4042 this->gotoClassicLinker(argc, argv);
b2fa67a8 4043 }
a61fdf0a
A
4044 }
4045
4046}
4047
4048void Options::gotoClassicLinker(int argc, const char* argv[])
4049{
4050 argv[0] = "ld_classic";
afe874b1
A
4051 // ld_classic does not support -iphoneos_version_min, so change
4052 for(int j=0; j < argc; ++j) {
4053 if ( (strcmp(argv[j], "-iphoneos_version_min") == 0) || (strcmp(argv[j], "-ios_version_min") == 0) ) {
4054 argv[j] = "-macosx_version_min";
4055 if ( j < argc-1 )
4056 argv[j+1] = "10.5";
4057 break;
4058 }
4059 }
4060 // ld classic does not understand -kext (change to -static -r)
4061 for(int j=0; j < argc; ++j) {
4062 if ( strcmp(argv[j], "-kext") == 0)
4063 argv[j] = "-r";
4064 else if ( strcmp(argv[j], "-dynamic") == 0)
4065 argv[j] = "-static";
4066 }
4067 // ld classic does not understand -demangle
4068 for(int j=0; j < argc; ++j) {
4069 if ( strcmp(argv[j], "-demangle") == 0)
4070 argv[j] = "-noprebind";
4071 }
a645023d
A
4072 // in -v mode, print command line passed to ld_classic
4073 for(int i=0; i < argc; ++i) {
4074 if ( strcmp(argv[i], "-v") == 0 ) {
4075 for(int j=0; j < argc; ++j)
4076 printf("%s ", argv[j]);
4077 printf("\n");
4078 break;
4079 }
4080 }
fb24a050 4081 char rawPath[PATH_MAX];
55e3d2f6
A
4082 char path[PATH_MAX];
4083 uint32_t bufSize = PATH_MAX;
fb24a050
A
4084 if ( _NSGetExecutablePath(rawPath, &bufSize) != -1 ) {
4085 if ( realpath(rawPath, path) != NULL ) {
4086 char* lastSlash = strrchr(path, '/');
4087 if ( lastSlash != NULL ) {
4088 strcpy(lastSlash+1, "ld_classic");
4089 argv[0] = path;
4090 execvp(path, (char**)argv);
4091 }
55e3d2f6
A
4092 }
4093 }
4094 // in case of error in above, try searching for ld_classic via PATH
a61fdf0a
A
4095 execvp(argv[0], (char**)argv);
4096 fprintf(stderr, "can't exec ld_classic\n");
4097 exit(1);
4098}