]> git.saurik.com Git - apple/ld64.git/blob - src/ld/Options.cpp
ld64-302.3.1.tar.gz
[apple/ld64.git] / src / ld / Options.cpp
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2005-2011 Apple Inc. All rights reserved.
4 *
5 * @APPLE_LICENSE_HEADER_START@
6 *
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.
13 *
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.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <mach/vm_prot.h>
29 #include <sys/sysctl.h>
30 #include <mach-o/dyld.h>
31 #include <fcntl.h>
32 #include <errno.h>
33 #include <string.h>
34 #include <spawn.h>
35 #include <cxxabi.h>
36 #include <Availability.h>
37 #include <tapi/tapi.h>
38
39 #include <vector>
40 #include <map>
41 #include <sstream>
42
43 #include "Options.h"
44 #include "Architectures.hpp"
45 #include "MachOFileAbstraction.hpp"
46 #include "Snapshot.h"
47
48
49 // from FunctionNameDemangle.h
50 extern "C" size_t fnd_get_demangled_name(const char *mangledName, char *outputBuffer, size_t length);
51
52
53 // upward dependency on lto::version()
54 namespace lto {
55 extern const char* version();
56 extern unsigned static_api_version();
57 extern unsigned runtime_api_version();
58 }
59
60 // magic to place command line in crash reports
61 const int crashreporterBufferSize = 2000;
62 static char crashreporterBuffer[crashreporterBufferSize];
63 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
64 #include <CrashReporterClient.h>
65 // hack until ld does not need to build on 10.6 anymore
66 struct crashreporter_annotations_t gCRAnnotations
67 __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION)))
68 = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 };
69 #else
70 extern "C" char* __crashreporter_info__;
71 __attribute__((used))
72 char* __crashreporter_info__ = crashreporterBuffer;
73 #endif
74
75
76 static bool sEmitWarnings = true;
77 static bool sFatalWarnings = false;
78 static const char* sWarningsSideFilePath = NULL;
79 static FILE* sWarningsSideFile = NULL;
80 static int sWarningsCount = 0;
81
82 void warning(const char* format, ...)
83 {
84 ++sWarningsCount;
85 if ( sEmitWarnings ) {
86 va_list list;
87 if ( sWarningsSideFilePath != NULL ) {
88 if ( sWarningsSideFile == NULL )
89 sWarningsSideFile = fopen(sWarningsSideFilePath, "a");
90 }
91 va_start(list, format);
92 fprintf(stderr, "ld: warning: ");
93 vfprintf(stderr, format, list);
94 fprintf(stderr, "\n");
95 if ( sWarningsSideFile != NULL ) {
96 fprintf(sWarningsSideFile, "ld: warning: ");
97 vfprintf(sWarningsSideFile, format, list);
98 fprintf(sWarningsSideFile, "\n");
99 fflush(sWarningsSideFile);
100 }
101 va_end(list);
102 }
103 }
104
105 void throwf(const char* format, ...)
106 {
107 va_list list;
108 char* p;
109 va_start(list, format);
110 vasprintf(&p, format, list);
111 va_end(list);
112
113 const char* t = p;
114 throw t;
115 }
116
117
118 bool Options::FileInfo::checkFileExists(const Options& options, const char *p)
119 {
120 struct stat statBuffer;
121 if (p == NULL)
122 p = path;
123 if ( stat(p, &statBuffer) == 0 ) {
124 if (p != path) path = strdup(p);
125 modTime = statBuffer.st_mtime;
126 return true;
127 }
128 if ( options.dumpDependencyInfo() )
129 options.dumpDependency(Options::depNotFound, p);
130 // fprintf(stderr, "not found: %s\n", p);
131 return false;
132 }
133
134
135 Options::Options(int argc, const char* argv[])
136 : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0), fArchitectureName("unknown"), fOutputKind(kDynamicExecutable),
137 fHasPreferredSubType(false), fArchSupportsThumb2(false), fPrebind(false), fBindAtLoad(false), fKeepPrivateExterns(false),
138 fNeedsModuleTable(false), fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false),
139 fInterposeMode(kInterposeNone), fDeadStrip(false), fNameSpace(kTwoLevelNameSpace),
140 fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL), fFinalName(NULL), fEntryName(NULL),
141 fBaseAddress(0), fMaxAddress(0x7FFFFFFFFFFFFFFFLL),
142 fBaseWritableAddress(0), fSplitSegs(false),
143 fExportMode(kExportDefault), fLibrarySearchMode(kSearchDylibAndArchiveInEachDir),
144 fUndefinedTreatment(kUndefinedError), fMessagesPrefixedWithArchitecture(true),
145 fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak),
146 fClientName(NULL),
147 fUmbrellaName(NULL), fInitFunctionName(NULL), fDotOutputFile(NULL), fExecutablePath(NULL),
148 fBundleLoader(NULL), fDtraceScriptName(NULL), fSegAddrTablePath(NULL), fMapPath(NULL),
149 fDyldInstallPath("/usr/lib/dyld"), fLtoCachePath(NULL), fTempLtoObjectPath(NULL), fOverridePathlibLTO(NULL), fLtoCpu(NULL),
150 fZeroPageSize(ULLONG_MAX), fStackSize(0), fStackAddr(0), fSourceVersion(0), fSDKVersion(0), fExecutableStack(false),
151 fNonExecutableHeap(false), fDisableNonExecutableHeap(false),
152 fMinimumHeaderPad(32), fSegmentAlignment(4096),
153 fCommonsMode(kCommonsIgnoreDylibs), fUUIDMode(kUUIDContent), fLocalSymbolHandling(kLocalSymbolsAll), fWarnCommons(false),
154 fVerbose(false), fKeepRelocations(false), fWarnStabs(false),
155 fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
156 fSharedRegionEligible(false), fSharedRegionEligibleForceOff(false), fPrintOrderFileStatistics(false),
157 fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), fPIEOnCommandLine(false),
158 fDisablePositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
159 fDeadStripDylibs(false), fAllowTextRelocs(false), fWarnTextRelocs(false), fKextsUseStubs(false),
160 fUsingLazyDylibLinking(false), fEncryptable(true), fEncryptableForceOn(false), fEncryptableForceOff(false),
161 fOrderData(true), fMarkDeadStrippableDylib(false),
162 fMakeCompressedDyldInfo(true), fMakeCompressedDyldInfoForceOff(false), fNoEHLabels(false),
163 fAllowCpuSubtypeMismatches(false), fEnforceDylibSubtypesMatch(false), fUseSimplifiedDylibReExports(false),
164 fObjCABIVersion2Override(false), fObjCABIVersion1Override(false), fCanUseUpwardDylib(false),
165 fFullyLoadArchives(false), fLoadAllObjcObjectsFromArchives(false), fFlatNamespace(false),
166 fLinkingMainExecutable(false), fForFinalLinkedImage(false), fForStatic(false),
167 fForDyld(false), fMakeTentativeDefinitionsReal(false), fWhyLoad(false), fRootSafe(false),
168 fSetuidSafe(false), fImplicitlyLinkPublicDylibs(true), fAddCompactUnwindEncoding(true),
169 fWarnCompactUnwind(false), fRemoveDwarfUnwindIfCompactExists(false),
170 fAutoOrderInitializers(true), fOptimizeZeroFill(true), fMergeZeroFill(false), fLogObjectFiles(false),
171 fLogAllFiles(false), fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false), fTraceEmitJSON(false),
172 fOutputSlidable(false), fWarnWeakExports(false),
173 fObjcGcCompaction(false), fObjCGc(false), fObjCGcOnly(false),
174 fDemangle(false), fTLVSupport(false),
175 fVersionLoadCommand(false), fVersionLoadCommandForcedOn(false),
176 fVersionLoadCommandForcedOff(false), fBuildVersionLoadCommand(false), fFunctionStartsLoadCommand(false),
177 fFunctionStartsForcedOn(false), fFunctionStartsForcedOff(false),
178 fDataInCodeInfoLoadCommand(false), fDataInCodeInfoLoadCommandForcedOn(false), fDataInCodeInfoLoadCommandForcedOff(false),
179 fCanReExportSymbols(false), fObjcCategoryMerging(true), fPageAlignDataAtoms(false),
180 fNeedsThreadLoadCommand(false), fEntryPointLoadCommand(false),
181 fEntryPointLoadCommandForceOn(false), fEntryPointLoadCommandForceOff(false),
182 fSourceVersionLoadCommand(false),
183 fSourceVersionLoadCommandForceOn(false), fSourceVersionLoadCommandForceOff(false),
184 fTargetIOSSimulator(false), fExportDynamic(false), fAbsoluteSymbols(false),
185 fAllowSimulatorToLinkWithMacOSX(false), fKeepDwarfUnwind(true),
186 fKeepDwarfUnwindForcedOn(false), fKeepDwarfUnwindForcedOff(false),
187 fVerboseOptimizationHints(false), fIgnoreOptimizationHints(false),
188 fGenerateDtraceDOF(true), fAllowBranchIslands(true), fTraceSymbolLayout(false),
189 fMarkAppExtensionSafe(false), fCheckAppExtensionSafe(false), fForceLoadSwiftLibs(false),
190 fSharedRegionEncodingV2(false), fUseDataConstSegment(false),
191 fUseDataConstSegmentForceOn(false), fUseDataConstSegmentForceOff(false), fUseTextExecSegment(false),
192 fBundleBitcode(false), fHideSymbols(false), fVerifyBitcode(false),
193 fReverseMapUUIDRename(false), fDeDupe(true), fVerboseDeDupe(false),
194 fReverseMapPath(NULL), fLTOCodegenOnly(false),
195 fIgnoreAutoLink(false), fAllowDeadDups(false), fAllowWeakImports(true), fNoInitializers(false), fBitcodeKind(kBitcodeProcess),
196 fPlatform(kPlatformUnknown), fDebugInfoStripping(kDebugInfoMinimal), fTraceOutputFile(NULL),
197 fMacVersionMin(ld::macVersionUnset), fIOSVersionMin(ld::iOSVersionUnset), fWatchOSVersionMin(ld::wOSVersionUnset),
198 fSaveTempFiles(false), fSnapshotRequested(false), fPipelineFifo(NULL),
199 fDependencyInfoPath(NULL), fDependencyFileDescriptor(-1), fTraceFileDescriptor(-1), fMaxDefaultCommonAlign(0),
200 fUnalignedPointerTreatment(kUnalignedPointerIgnore)
201 {
202 this->checkForClassic(argc, argv);
203 this->parsePreCommandLineEnvironmentSettings();
204 this->parse(argc, argv);
205 this->parsePostCommandLineEnvironmentSettings();
206 this->reconfigureDefaults();
207 this->checkIllegalOptionCombinations();
208
209 if ( this->dumpDependencyInfo() ) {
210 this->dumpDependency(depOutputFile, fOutputFile);
211 if ( fMapPath != NULL )
212 this->dumpDependency(depOutputFile, fMapPath);
213 }
214 }
215
216 Options::~Options()
217 {
218 if ( fDependencyFileDescriptor != -1 )
219 ::close(fDependencyFileDescriptor);
220
221 if ( fTraceFileDescriptor != -1 )
222 ::close(fTraceFileDescriptor);
223 }
224
225 bool Options::errorBecauseOfWarnings() const
226 {
227 return (sFatalWarnings && (sWarningsCount > 0));
228 }
229
230
231 const char* Options::installPath() const
232 {
233 if ( fDylibInstallName != NULL )
234 return fDylibInstallName;
235 else if ( fFinalName != NULL )
236 return fFinalName;
237 else
238 return fOutputFile;
239 }
240
241
242 bool Options::interposable(const char* name) const
243 {
244 switch ( fInterposeMode ) {
245 case kInterposeNone:
246 return false;
247 case kInterposeAllExternal:
248 return true;
249 case kInterposeSome:
250 return fInterposeList.contains(name);
251 }
252 throw "internal error";
253 }
254
255
256 bool Options::printWhyLive(const char* symbolName) const
257 {
258 return fWhyLive.contains(symbolName);
259 }
260
261
262 const char* Options::dotOutputFile()
263 {
264 return fDotOutputFile;
265 }
266
267
268 bool Options::hasWildCardExportRestrictList() const
269 {
270 // has -exported_symbols_list which contains some wildcards
271 return ((fExportMode == kExportSome) && fExportSymbols.hasWildCards());
272 }
273
274 bool Options::hasWeakBitTweaks() const
275 {
276 // has -exported_symbols_list which contains some wildcards
277 return (!fForceWeakSymbols.empty() || !fForceNotWeakSymbols.empty());
278 }
279
280 bool Options::allGlobalsAreDeadStripRoots() const
281 {
282 // -exported_symbols_list means globals are not exported by default
283 if ( fExportMode == kExportSome )
284 return false;
285 //
286 switch ( fOutputKind ) {
287 case Options::kDynamicExecutable:
288 // <rdar://problem/12839986> Add the -export_dynamic flag
289 return fExportDynamic;
290 case Options::kStaticExecutable:
291 // <rdar://problem/13361218> Support the -export_dynamic flag for xnu
292 return fExportDynamic;
293 case Options::kPreload:
294 // by default unused globals in a main executable are stripped
295 return false;
296 case Options::kDynamicLibrary:
297 case Options::kDynamicBundle:
298 case Options::kObjectFile:
299 case Options::kDyld:
300 case Options::kKextBundle:
301 return true;
302 }
303 return false;
304 }
305
306
307 bool Options::keepRelocations()
308 {
309 return fKeepRelocations;
310 }
311
312 bool Options::warnStabs()
313 {
314 return fWarnStabs;
315 }
316
317 const char* Options::executablePath()
318 {
319 return fExecutablePath;
320 }
321
322 uint32_t Options::initialSegProtection(const char* segName) const
323 {
324 for(std::vector<Options::SegmentProtect>::const_iterator it = fCustomSegmentProtections.begin(); it != fCustomSegmentProtections.end(); ++it) {
325 if ( strcmp(it->name, segName) == 0 ) {
326 return it->init;
327 }
328 }
329 if ( strcmp(segName, "__TEXT") == 0 ) {
330 return ( fUseTextExecSegment ? VM_PROT_READ : (VM_PROT_READ | VM_PROT_EXECUTE) );
331 }
332 else if ( strcmp(segName, "__TEXT_EXEC") == 0 ) {
333 return VM_PROT_READ | VM_PROT_EXECUTE;
334 }
335 else if ( strcmp(segName, "__PAGEZERO") == 0 ) {
336 return 0;
337 }
338 else if ( strcmp(segName, "__LINKEDIT") == 0 ) {
339 return VM_PROT_READ;
340 }
341
342 // all others default to read-write
343 return VM_PROT_READ | VM_PROT_WRITE;
344 }
345
346 uint32_t Options::maxSegProtection(const char* segName) const
347 {
348 // iPhoneOS always uses same protection for max and initial
349 // <rdar://problem/11663436> simulator apps need to use MacOSX max-prot
350 if ( (fPlatform != kPlatformOSX) && !fTargetIOSSimulator )
351 return initialSegProtection(segName);
352
353 for(std::vector<Options::SegmentProtect>::const_iterator it = fCustomSegmentProtections.begin(); it != fCustomSegmentProtections.end(); ++it) {
354 if ( strcmp(it->name, segName) == 0 ) {
355 return it->max;
356 }
357 }
358 if ( strcmp(segName, "__PAGEZERO") == 0 ) {
359 return 0;
360 }
361 // all others default to all
362 return VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
363 }
364
365 uint64_t Options::segPageSize(const char* segName) const
366 {
367 for(std::vector<SegmentSize>::const_iterator it=fCustomSegmentSizes.begin(); it != fCustomSegmentSizes.end(); ++it) {
368 if ( strcmp(it->name, segName) == 0 )
369 return it->size;
370 }
371 return fSegmentAlignment;
372 }
373
374 uint64_t Options::customSegmentAddress(const char* segName) const
375 {
376 for(std::vector<SegmentStart>::const_iterator it=fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
377 if ( strcmp(it->name, segName) == 0 )
378 return it->address;
379 }
380 // if custom stack in use, model as segment with custom address
381 if ( (fStackSize != 0) && (strcmp("__UNIXSTACK", segName) == 0) )
382 return fStackAddr - fStackSize;
383 return 0;
384 }
385
386 bool Options::hasCustomSegmentAddress(const char* segName) const
387 {
388 for(std::vector<SegmentStart>::const_iterator it=fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
389 if ( strcmp(it->name, segName) == 0 )
390 return true;
391 }
392 // if custom stack in use, model as segment with custom address
393 if ( (fStackSize != 0) && (strcmp("__UNIXSTACK", segName) == 0) )
394 return true;
395 return false;
396 }
397
398 bool Options::hasCustomSectionAlignment(const char* segName, const char* sectName) const
399 {
400 for (std::vector<SectionAlignment>::const_iterator it = fSectionAlignments.begin(); it != fSectionAlignments.end(); ++it) {
401 if ( (strcmp(it->segmentName, segName) == 0) && (strcmp(it->sectionName, sectName) == 0) )
402 return true;
403 }
404 if ( fEncryptable && (strcmp(sectName, "__oslogstring") == 0) && (strcmp(segName, "__TEXT") == 0) )
405 return true;
406
407 return false;
408 }
409
410 uint8_t Options::customSectionAlignment(const char* segName, const char* sectName) const
411 {
412 for (std::vector<SectionAlignment>::const_iterator it = fSectionAlignments.begin(); it != fSectionAlignments.end(); ++it) {
413 if ( (strcmp(it->segmentName, segName) == 0) && (strcmp(it->sectionName, sectName) == 0) )
414 return it->alignment;
415 }
416 if ( fEncryptable && (strcmp(sectName, "__oslogstring") == 0) && (strcmp(segName, "__TEXT") == 0) )
417 return __builtin_ctz(fSegmentAlignment);
418
419 return 0;
420 }
421
422 bool Options::segmentOrderAfterFixedAddressSegment(const char* segName) const
423 {
424 bool nowPinned = false;
425 for (std::vector<const char*>::const_iterator it=fSegmentOrder.begin(); it != fSegmentOrder.end(); ++it) {
426 if ( strcmp(*it, segName) == 0 )
427 return nowPinned;
428 if ( hasCustomSegmentAddress(*it) )
429 nowPinned = true;
430 }
431 return false;
432 }
433
434 bool Options::hasExportedSymbolOrder()
435 {
436 return (fExportSymbolsOrder.size() > 0);
437 }
438
439 bool Options::exportedSymbolOrder(const char* sym, unsigned int* order) const
440 {
441 NameToOrder::const_iterator pos = fExportSymbolsOrder.find(sym);
442 if ( pos != fExportSymbolsOrder.end() ) {
443 *order = pos->second;
444 return true;
445 }
446 else {
447 *order = 0xFFFFFFFF;
448 return false;
449 }
450 }
451
452 void Options::loadSymbolOrderFile(const char* fileOfExports, NameToOrder& orderMapping)
453 {
454 // read in whole file
455 int fd = ::open(fileOfExports, O_RDONLY, 0);
456 if ( fd == -1 )
457 throwf("can't open -exported_symbols_order file: %s", fileOfExports);
458 struct stat stat_buf;
459 ::fstat(fd, &stat_buf);
460 char* p = (char*)malloc(stat_buf.st_size);
461 if ( p == NULL )
462 throwf("can't process -exported_symbols_order file: %s", fileOfExports);
463
464 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
465 throwf("can't read -exported_symbols_order file: %s", fileOfExports);
466
467 ::close(fd);
468
469 // parse into symbols and add to unordered_set
470 unsigned int count = 0;
471 char * const end = &p[stat_buf.st_size];
472 enum { lineStart, inSymbol, inComment } state = lineStart;
473 char* symbolStart = NULL;
474 for (char* s = p; s < end; ++s ) {
475 switch ( state ) {
476 case lineStart:
477 if ( *s =='#' ) {
478 state = inComment;
479 }
480 else if ( !isspace(*s) ) {
481 state = inSymbol;
482 symbolStart = s;
483 }
484 break;
485 case inSymbol:
486 if ( (*s == '\n') || (*s == '\r') ) {
487 *s = '\0';
488 // removing any trailing spaces
489 char* last = s-1;
490 while ( isspace(*last) ) {
491 *last = '\0';
492 --last;
493 }
494 orderMapping[symbolStart] = ++count;
495 symbolStart = NULL;
496 state = lineStart;
497 }
498 break;
499 case inComment:
500 if ( (*s == '\n') || (*s == '\r') )
501 state = lineStart;
502 break;
503 }
504 }
505 if ( state == inSymbol ) {
506 warning("missing line-end at end of file \"%s\"", fileOfExports);
507 int len = end-symbolStart+1;
508 char* temp = new char[len];
509 strlcpy(temp, symbolStart, len);
510
511 // remove any trailing spaces
512 char* last = &temp[len-2];
513 while ( isspace(*last) ) {
514 *last = '\0';
515 --last;
516 }
517 orderMapping[temp] = ++count;
518 }
519
520 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
521 }
522
523 bool Options::forceWeak(const char* symbolName) const
524 {
525 return fForceWeakSymbols.contains(symbolName);
526 }
527
528 bool Options::forceNotWeak(const char* symbolName) const
529 {
530 return fForceNotWeakSymbols.contains(symbolName);
531 }
532
533 bool Options::forceWeakNonWildCard(const char* symbolName) const
534 {
535 return fForceWeakSymbols.containsNonWildcard(symbolName);
536 }
537
538 bool Options::forceNotWeakNonWildcard(const char* symbolName) const
539 {
540 return fForceNotWeakSymbols.containsNonWildcard(symbolName);
541 }
542
543 bool Options::forceCoalesce(const char* symbolName) const
544 {
545 return fForceCoalesceSymbols.contains(symbolName);
546 }
547
548
549 bool Options::shouldExport(const char* symbolName) const
550 {
551 switch (fExportMode) {
552 case kExportSome:
553 return fExportSymbols.contains(symbolName);
554 case kDontExportSome:
555 return ! fDontExportSymbols.contains(symbolName);
556 case kExportDefault:
557 return true;
558 }
559 throw "internal error";
560 }
561
562 bool Options::shouldReExport(const char* symbolName) const
563 {
564 return fReExportSymbols.contains(symbolName);
565 }
566
567 bool Options::keepLocalSymbol(const char* symbolName) const
568 {
569 switch (fLocalSymbolHandling) {
570 case kLocalSymbolsAll:
571 return true;
572 case kLocalSymbolsNone:
573 return false;
574 case kLocalSymbolsSelectiveInclude:
575 return fLocalSymbolsIncluded.contains(symbolName);
576 case kLocalSymbolsSelectiveExclude:
577 return ! fLocalSymbolsExcluded.contains(symbolName);
578 }
579 throw "internal error";
580 }
581
582 const std::vector<const char*>* Options::sectionOrder(const char* segName) const
583 {
584 for (std::vector<SectionOrderList>::const_iterator it=fSectionOrder.begin(); it != fSectionOrder.end(); ++it) {
585 if ( strcmp(it->segmentName, segName) == 0 )
586 return &it->sectionOrder;
587 }
588 return NULL;
589 }
590
591 uint32_t Options::minOSversion() const
592 {
593 switch (fPlatform) {
594 case kPlatformiOS:
595 return iOSVersionMin();
596 case kPlatformOSX:
597 return macosxVersionMin();
598 case kPlatformWatchOS:
599 return watchOSVersionMin();
600 #if SUPPORT_APPLE_TV
601 case Options::kPlatform_tvOS:
602 return iOSVersionMin();
603 #endif
604 case kPlatform_bridgeOS:
605 return iOSVersionMin();
606 case kPlatformUnknown:
607 return 0;
608 }
609 return 0;
610 }
611
612 void Options::setArchitecture(cpu_type_t type, cpu_subtype_t subtype, Options::Platform platform)
613 {
614 for (const ArchInfo* t=archInfoArray; t->archName != NULL; ++t) {
615 if ( (type == t->cpuType) && (subtype == t->cpuSubType) ) {
616 fArchitecture = type;
617 fSubArchitecture = subtype;
618 fArchitectureName = t->archName;
619 fHasPreferredSubType = t->isSubType;
620 fArchSupportsThumb2 = t->supportsThumb2;
621 if ( fPlatform == kPlatformUnknown)
622 fPlatform = platform;
623 switch ( type ) {
624 case CPU_TYPE_I386:
625 case CPU_TYPE_X86_64:
626 if ( (fPlatform == kPlatformOSX) && (fOutputKind != Options::kObjectFile) && (fMacVersionMin == ld::macVersionUnset) ) {
627 #ifdef DEFAULT_MACOSX_MIN_VERSION
628 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION);
629 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
630 #else
631 warning("-macosx_version_min not specified, assuming 10.6");
632 fMacVersionMin = ld::mac10_6;
633 #endif
634 }
635 break;
636 case CPU_TYPE_ARM:
637 case CPU_TYPE_ARM64:
638 if ( (fMacVersionMin == ld::macVersionUnset) && (fIOSVersionMin == ld::iOSVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
639 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
640 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION);
641 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION);
642 #else
643 warning("-ios_version_min not specified, assuming 6.0");
644 setIOSVersionMin("6.0");
645 #endif
646 }
647 break;
648 }
649 fLinkSnapshot.recordArch(fArchitectureName);
650 // only use compressed LINKEDIT for:
651 // Mac OS X 10.6 or later
652 // iOS 3.1 or later
653 if ( !fMakeCompressedDyldInfo && minOS(ld::mac10_6, ld::iOS_3_1) && !fMakeCompressedDyldInfoForceOff )
654 fMakeCompressedDyldInfo = true;
655 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
656 if ( minOS(ld::mac10_5, ld::iOS_2_0) )
657 fUseSimplifiedDylibReExports = true;
658 return;
659 }
660 }
661 fArchitectureName = "unknown architecture";
662 }
663
664 bool Options::armUsesZeroCostExceptions() const
665 {
666 return ( (fArchitecture == CPU_TYPE_ARM) && (fSubArchitecture == CPU_SUBTYPE_ARM_V7K) );
667 }
668
669 void Options::parseArch(const char* arch)
670 {
671 if ( arch == NULL )
672 throw "-arch must be followed by an architecture string";
673 for (const ArchInfo* t=archInfoArray; t->archName != NULL; ++t) {
674 if ( strcmp(t->archName,arch) == 0 ) {
675 fArchitectureName = arch;
676 fArchitecture = t->cpuType;
677 fSubArchitecture = t->cpuSubType;
678 fHasPreferredSubType = t->isSubType;
679 fArchSupportsThumb2 = t->supportsThumb2;
680 return;
681 }
682 }
683 throwf("unknown/unsupported architecture name for: -arch %s", arch);
684 }
685
686 bool Options::checkForFile(const char* format, const char* dir, const char* rootName, FileInfo& result) const
687 {
688 char possiblePath[strlen(dir)+strlen(rootName)+strlen(format)+8];
689 sprintf(possiblePath, format, dir, rootName);
690 bool found = result.checkFileExists(*this, possiblePath);
691 if ( fTraceDylibSearching )
692 printf("[Logging for XBS]%sfound library: '%s'\n", (found ? " " : " not "), possiblePath);
693 return found;
694 }
695
696
697 Options::FileInfo Options::findLibrary(const char* rootName, bool dylibsOnly) const
698 {
699 FileInfo result;
700 const int rootNameLen = strlen(rootName);
701 // if rootName ends in .o there is no .a vs .dylib choice
702 if ( (rootNameLen > 3) && (strcmp(&rootName[rootNameLen-2], ".o") == 0) ) {
703 for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
704 it != fLibrarySearchPaths.end();
705 it++) {
706 const char* dir = *it;
707 if ( checkForFile("%s/%s", dir, rootName, result) )
708 return result;
709 }
710 }
711 else {
712 bool lookForDylibs = false;
713 switch ( fOutputKind ) {
714 case Options::kDynamicExecutable:
715 case Options::kDynamicLibrary:
716 case Options::kDynamicBundle:
717 case Options::kObjectFile: // <rdar://problem/15914513>
718 lookForDylibs = true;
719 break;
720 case Options::kStaticExecutable:
721 case Options::kDyld:
722 case Options::kPreload:
723 case Options::kKextBundle:
724 lookForDylibs = false;
725 break;
726 }
727 switch ( fLibrarySearchMode ) {
728 case kSearchAllDirsForDylibsThenAllDirsForArchives:
729 // first look in all directories for just for dylibs
730 if ( lookForDylibs ) {
731 for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
732 it != fLibrarySearchPaths.end();
733 it++) {
734 const char* dir = *it;
735 auto path = std::string(dir) + "/lib" + rootName + ".dylib";
736 if ( findFile(path, {".tbd"}, result) )
737 return result;
738 }
739 for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
740 it != fLibrarySearchPaths.end();
741 it++) {
742 const char* dir = *it;
743 if ( checkForFile("%s/lib%s.so", dir, rootName, result) )
744 return result;
745 }
746 }
747 // next look in all directories for just for archives
748 if ( !dylibsOnly ) {
749 for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
750 it != fLibrarySearchPaths.end();
751 it++) {
752 const char* dir = *it;
753 if ( checkForFile("%s/lib%s.a", dir, rootName, result) )
754 return result;
755 }
756 }
757 break;
758
759 case kSearchDylibAndArchiveInEachDir:
760 // look in each directory for just for a dylib then for an archive
761 for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
762 it != fLibrarySearchPaths.end();
763 it++) {
764 const char* dir = *it;
765 auto path = std::string(dir) + "/lib" + rootName + ".dylib";
766 if ( lookForDylibs && findFile(path, {".tbd"}, result) )
767 return result;
768 if ( lookForDylibs && checkForFile("%s/lib%s.so", dir, rootName, result) )
769 return result;
770 if ( !dylibsOnly && checkForFile("%s/lib%s.a", dir, rootName, result) )
771 return result;
772 }
773 break;
774 }
775 }
776 throwf("library not found for -l%s", rootName);
777 }
778
779 Options::FileInfo Options::findFramework(const char* frameworkName) const
780 {
781 if ( frameworkName == NULL )
782 throw "-framework missing next argument";
783 char temp[strlen(frameworkName)+1];
784 strcpy(temp, frameworkName);
785 const char* name = temp;
786 const char* suffix = NULL;
787 char* comma = strchr(temp, ',');
788 if ( comma != NULL ) {
789 *comma = '\0';
790 suffix = &comma[1];
791 }
792 return findFramework(name, suffix);
793 }
794
795 Options::FileInfo Options::findFramework(const char* rootName, const char* suffix) const
796 {
797 for (const auto* path : fFrameworkSearchPaths) {
798 auto possiblePath = std::string(path).append("/").append(rootName).append(".framework/").append(rootName);
799 if ( suffix != nullptr ) {
800 char realPath[PATH_MAX];
801 // no symlink in framework to suffix variants, so follow main symlink
802 if ( realpath(possiblePath.c_str(), realPath) != nullptr )
803 possiblePath = std::string(realPath).append(suffix);
804 }
805 FileInfo result;
806 if ( findFile(possiblePath, {".tbd"}, result) )
807 return result;
808 }
809 // try without suffix
810 if ( suffix != NULL )
811 return findFramework(rootName, NULL);
812 else
813 throwf("framework not found %s", rootName);
814 }
815
816 static std::string replace_extension(const std::string &path, const std::string &ext)
817 {
818 auto result = path;
819 auto lastSlashIdx = result.find_last_of('/');
820 auto lastDotIdx = result.find_last_of('.');
821 if (lastDotIdx != std::string::npos && lastDotIdx > lastSlashIdx)
822 result.erase(lastDotIdx, std::string::npos);
823 if ( ext.size() > 0 && ext[0] == '.' )
824 result.append(ext);
825 else
826 result.append('.' + ext);
827 return result;
828 }
829
830 bool Options::findFile(const std::string &path, const std::vector<std::string> &tbdExtensions, FileInfo& result) const
831 {
832 FileInfo tbdInfo;
833 for ( const auto &ext : tbdExtensions ) {
834 auto newPath = replace_extension(path, ext);
835 bool found = tbdInfo.checkFileExists(*this, newPath.c_str());
836 if ( fTraceDylibSearching )
837 printf("[Logging for XBS]%sfound library: '%s'\n", (found ? " " : " not "), newPath.c_str());
838 if ( found )
839 break;
840 }
841
842 FileInfo dylibInfo;
843 {
844 bool found = dylibInfo.checkFileExists(*this, path.c_str());
845 if ( fTraceDylibSearching )
846 printf("[Logging for XBS]%sfound library: '%s'\n", (found ? " " : " not "), path.c_str());
847 }
848
849 // There is only a text-based stub file or a dynamic library file.
850 if ( tbdInfo.missing() != dylibInfo.missing() ) {
851 result = tbdInfo.missing() ? dylibInfo : tbdInfo;
852 }
853 // There are both - a text-based stub file and a dynamic library file.
854 else if ( !tbdInfo.missing() && !dylibInfo.missing() ) {
855 // Check if we should prefer the text-based stub file (installapi).
856 if (tapi::LinkerInterfaceFile::shouldPreferTextBasedStubFile(tbdInfo.path)) {
857 result = tbdInfo;
858 }
859 // If the files are still in sync we can use and should use the text-based stub file.
860 else if (tapi::LinkerInterfaceFile::areEquivalent(tbdInfo.path, dylibInfo.path)) {
861 result = tbdInfo;
862 }
863 // Otherwise issue a warning and fall-back to the dynamic library file.
864 else {
865 warning("text-based stub file %s and library file %s are out of sync. Falling back to library file for linking.", tbdInfo.path, dylibInfo.path);
866 result = dylibInfo;
867 }
868 } else {
869 return false;
870 }
871
872 return true;
873 }
874
875 static bool startsWith(const std::string& str, const std::string& prefix)
876 {
877 return (str.compare(0, prefix.length(), prefix) == 0);
878 }
879
880 static std::string getDirPath(const std::string& path)
881 {
882 std::string::size_type lastSlashPos = path.find_last_of('/');
883 if ( lastSlashPos == std::string::npos )
884 return "./";
885 else
886 return path.substr(0, lastSlashPos+1);
887 }
888
889 Options::FileInfo Options::findFile(const std::string &path, const ld::dylib::File* fromDylib) const
890 {
891 FileInfo result;
892
893 // if absolute path and not a .o file, then use SDK prefix
894 if ( (path[0] == '/') && (strcmp(&path[path.size()-2], ".o") != 0) ) {
895 for (const auto* sdkPathDir : fSDKPaths) {
896 auto possiblePath = std::string(sdkPathDir) + path;
897 if ( findFile(possiblePath, {".tbd"}, result) )
898 return result;
899 }
900 }
901
902 // expand @ variables
903 if ( path[0] == '@' ) {
904 if ( startsWith(path, "@executable_path/") && (fExecutablePath != nullptr) ) {
905 std::string exeBasedPath = getDirPath(fExecutablePath) + &path[17];
906 if ( findFile(exeBasedPath, {".tbd"}, result) )
907 return result;
908 }
909 else if ( startsWith(path, "@loader_path/") && (fromDylib != nullptr) ) {
910 char absPath[PATH_MAX];
911 if ( realpath(fromDylib->path(), absPath) != NULL ) {
912 std::string loaderBasedPath = getDirPath(fromDylib->path()) + &path[13];
913 if ( findFile(loaderBasedPath, {".tbd"}, result) )
914 return result;
915 }
916 }
917 else if ( startsWith(path, "@rpath/") ) {
918 // first search any LC_RPATH supplied by dyld that re-exports dylib to be found
919 if ( fromDylib != nullptr ) {
920 for (const char* rp : fromDylib->rpaths() ) {
921 std::string rpath = rp;
922 // handle dylib that has LC_RPATH = @loader_path/blah
923 if ( startsWith(rpath, "@loader_path/") ) {
924 char absPath[PATH_MAX];
925 if ( realpath(fromDylib->path(), absPath) != NULL )
926 rpath = getDirPath(absPath) + &rpath[13];
927 else
928 rpath = getDirPath(fromDylib->path()) + &rpath[13];
929 }
930 std::string rpathBasedPath = rpath + "/" + &path[6];
931 if ( findFile(rpathBasedPath, {".tbd"}, result) )
932 return result;
933 }
934 }
935 }
936 }
937
938 // try raw path
939 if ( findFile(path, {".tbd"}, result) )
940 return result;
941
942 // not found
943 throwf("file not found: %s", path.c_str());
944 }
945
946 // search for indirect dylib first using -F and -L paths first
947 Options::FileInfo Options::findIndirectDylib(const std::string& installName, const ld::dylib::File* fromDylib) const
948 {
949 FileInfo result;
950
951 auto lastSlashPos = installName.find_last_of('/');
952 auto pos = ( lastSlashPos != std::string::npos ) ? lastSlashPos + 1 : 0;
953 auto leafName = installName.substr(pos);
954
955 // Is this in a framework?
956 // /path/Foo.framework/Foo ==> true (Foo)
957 // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
958 // /path/Foo.framework/Resources/Bar ==> false
959 bool isFramework = false;
960 if ( lastSlashPos != std::string::npos ) {
961 auto frameworkDir = std::string("/").append(leafName).append(".framework/");
962 if ( installName.rfind(frameworkDir) != std::string::npos )
963 isFramework = true;
964 }
965
966 // These are abbreviated versions of the routines findFramework and findLibrary above
967 // because we already know the final name of the file that we're looking for and so
968 // don't need to try variations, just paths. We do need to add the additional bits
969 // onto the framework path though.
970 if ( isFramework ) {
971 auto endPos = installName.rfind(".framework");
972 auto beginPos = installName.find_last_of('/', endPos);
973 auto leafPath = installName.substr(beginPos);
974 for (const auto* dir : fFrameworkSearchPaths) {
975 auto possiblePath = dir + leafPath;
976 if ( findFile(possiblePath, {".tbd"}, result) )
977 return result;
978 }
979 } else {
980 // if this is a .dylib inside a framework, do not search -L paths
981 // <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
982 bool embeddedDylib = ( (leafName.size() > 6)
983 && (leafName.find(".dylib", leafName.size()-6) != std::string::npos)
984 && (installName.find(".framework/") != std::string::npos) );
985 if ( !embeddedDylib ) {
986 for (const auto* dir : fLibrarySearchPaths) {
987 //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
988 std::string possiblePath = dir + std::string("/") + leafName;
989 if ( findFile(possiblePath, {".tbd"}, result) )
990 return result;
991 }
992 }
993 }
994
995 // If we didn't find it fall back to findFile.
996 return findFile(installName, fromDylib);
997 }
998
999
1000
1001 void Options::parseSegAddrTable(const char* segAddrPath, const char* installPth)
1002 {
1003 FILE* file = fopen(segAddrPath, "r");
1004 if ( file == NULL ) {
1005 warning("-seg_addr_table file cannot be read: %s", segAddrPath);
1006 return;
1007 }
1008
1009 char path[PATH_MAX];
1010 uint64_t firstColumAddress = 0;
1011 uint64_t secondColumAddress = 0;
1012 bool hasSecondColumn = false;
1013 while ( fgets(path, PATH_MAX, file) != NULL ) {
1014 path[PATH_MAX-1] = '\0';
1015 char* eol = strchr(path, '\n');
1016 if ( eol != NULL )
1017 *eol = '\0';
1018 // ignore lines not starting with 0x number
1019 if ( (path[0] == '0') && (path[1] == 'x') ) {
1020 char* p;
1021 firstColumAddress = strtoull(path, &p, 16);
1022 while ( isspace(*p) )
1023 ++p;
1024 // see if second column is a number
1025 if ( (p[0] == '0') && (p[1] == 'x') ) {
1026 secondColumAddress = strtoull(p, &p, 16);
1027 hasSecondColumn = true;
1028 while ( isspace(*p) )
1029 ++p;
1030 }
1031 while ( isspace(*p) )
1032 ++p;
1033 if ( p[0] == '/' ) {
1034 // remove any trailing whitespace
1035 for(char* end = eol-1; (end > p) && isspace(*end); --end)
1036 *end = '\0';
1037 // see if this line is for the dylib being linked
1038 if ( strcmp(p, installPth) == 0 ) {
1039 fBaseAddress = firstColumAddress;
1040 if ( hasSecondColumn ) {
1041 fBaseWritableAddress = secondColumAddress;
1042 fSplitSegs = true;
1043 }
1044 break; // out of while loop
1045 }
1046 }
1047 }
1048 }
1049
1050 fclose(file);
1051 }
1052
1053 void Options::loadFileList(const char* fileOfPaths, ld::File::Ordinal baseOrdinal)
1054 {
1055 FILE* file;
1056 const char* comma = strrchr(fileOfPaths, ',');
1057 const char* prefix = NULL;
1058 if ( comma != NULL ) {
1059 // <rdar://problem/5907981> -filelist fails with comma in path
1060 file = fopen(fileOfPaths, "r");
1061 if ( file == NULL ) {
1062 prefix = comma+1;
1063 int realFileOfPathsLen = comma-fileOfPaths;
1064 char realFileOfPaths[realFileOfPathsLen+1];
1065 strncpy(realFileOfPaths,fileOfPaths, realFileOfPathsLen);
1066 realFileOfPaths[realFileOfPathsLen] = '\0';
1067 file = fopen(realFileOfPaths, "r");
1068 if ( file == NULL )
1069 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", realFileOfPaths, errno, strerror(errno));
1070 if ( this->dumpDependencyInfo() )
1071 this->dumpDependency(Options::depFileList, realFileOfPaths);
1072 }
1073 }
1074 else {
1075 file = fopen(fileOfPaths, "r");
1076 if ( file == NULL )
1077 throwf("-filelist file '%s' could not be opened, errno=%d (%s)\n", fileOfPaths, errno, strerror(errno));
1078 if ( this->dumpDependencyInfo() )
1079 this->dumpDependency(Options::depFileList, fileOfPaths);
1080 }
1081
1082 char path[PATH_MAX];
1083 ld::File::Ordinal previousOrdinal = baseOrdinal;
1084 while ( fgets(path, PATH_MAX, file) != NULL ) {
1085 path[PATH_MAX-1] = '\0';
1086 char* eol = strchr(path, '\n');
1087 if ( eol != NULL )
1088 *eol = '\0';
1089 if ( prefix != NULL ) {
1090 char builtPath[strlen(prefix)+strlen(path)+2];
1091 strcpy(builtPath, prefix);
1092 strcat(builtPath, "/");
1093 strcat(builtPath, path);
1094 if (fPipelineFifo != NULL) {
1095 FileInfo info = FileInfo(builtPath);
1096 info.ordinal = previousOrdinal.nextFileListOrdinal();
1097 previousOrdinal = info.ordinal;
1098 info.fromFileList = true;
1099 fInputFiles.push_back(info);
1100 } else {
1101 FileInfo info = findFile(builtPath);
1102 info.ordinal = previousOrdinal.nextFileListOrdinal();
1103 previousOrdinal = info.ordinal;
1104 info.fromFileList = true;
1105 fInputFiles.push_back(info);
1106 }
1107 }
1108 else {
1109 if (fPipelineFifo != NULL) {
1110 FileInfo info = FileInfo(path);
1111 info.ordinal = previousOrdinal.nextFileListOrdinal();
1112 previousOrdinal = info.ordinal;
1113 info.fromFileList = true;
1114 fInputFiles.push_back(info);
1115 } else {
1116 FileInfo info = findFile(path);
1117 info.ordinal = previousOrdinal.nextFileListOrdinal();
1118 previousOrdinal = info.ordinal;
1119 info.fromFileList = true;
1120 fInputFiles.push_back(info);
1121 }
1122 }
1123 }
1124 fclose(file);
1125 }
1126
1127
1128 void Options::SetWithWildcards::remove(const NameSet& toBeRemoved)
1129 {
1130 for(NameSet::const_iterator it=toBeRemoved.begin(); it != toBeRemoved.end(); ++it) {
1131 const char* symbolName = *it;
1132 NameSet::iterator pos = fRegular.find(symbolName);
1133 if ( pos != fRegular.end() )
1134 fRegular.erase(pos);
1135 }
1136 }
1137
1138 bool Options::SetWithWildcards::hasWildCards(const char* symbol)
1139 {
1140 // an exported symbol name containing *, ?, or [ requires wildcard matching
1141 return ( strpbrk(symbol, "*?[") != NULL );
1142 }
1143
1144 void Options::SetWithWildcards::insert(const char* symbol)
1145 {
1146 if ( hasWildCards(symbol) )
1147 fWildCard.push_back(symbol);
1148 else
1149 fRegular.insert(symbol);
1150 }
1151
1152 bool Options::SetWithWildcards::contains(const char* symbol, bool* matchBecauseOfWildcard) const
1153 {
1154 if ( matchBecauseOfWildcard != NULL )
1155 *matchBecauseOfWildcard = false;
1156 // first look at hash table on non-wildcard symbols
1157 if ( fRegular.find(symbol) != fRegular.end() )
1158 return true;
1159 // next walk list of wild card symbols looking for a match
1160 for(std::vector<const char*>::const_iterator it = fWildCard.begin(); it != fWildCard.end(); ++it) {
1161 if ( wildCardMatch(*it, symbol) ) {
1162 if ( matchBecauseOfWildcard != NULL )
1163 *matchBecauseOfWildcard = true;
1164 return true;
1165 }
1166 }
1167 return false;
1168 }
1169
1170 // Support "foo.o:_bar" to mean symbol _bar in file foo.o
1171 bool Options::SetWithWildcards::containsWithPrefix(const char* symbol, const char* file, bool& wildCardMatch) const
1172 {
1173 wildCardMatch = false;
1174 if ( contains(symbol, &wildCardMatch) )
1175 return true;
1176 if ( file == NULL )
1177 return false;
1178 const char* s = strrchr(file, '/');
1179 if ( s != NULL )
1180 file = s+1;
1181 char buff[strlen(file)+strlen(symbol)+2];
1182 sprintf(buff, "%s:%s", file, symbol);
1183 return contains(buff, &wildCardMatch);
1184 }
1185
1186 bool Options::SetWithWildcards::containsNonWildcard(const char* symbol) const
1187 {
1188 // look at hash table on non-wildcard symbols
1189 return ( fRegular.find(symbol) != fRegular.end() );
1190 }
1191
1192
1193 std::vector<const char*> Options::exportsData() const
1194 {
1195 return fExportSymbols.data();
1196 }
1197
1198
1199 std::vector<const char*> Options::SetWithWildcards::data() const
1200 {
1201 std::vector<const char*> data;
1202 for (NameSet::iterator it=regularBegin(); it != regularEnd(); ++it) {
1203 data.push_back(*it);
1204 }
1205 for (std::vector<const char*>::const_iterator it=fWildCard.begin(); it != fWildCard.end(); ++it) {
1206 data.push_back(*it);
1207 }
1208 return data;
1209 }
1210
1211 bool Options::SetWithWildcards::inCharRange(const char*& p, unsigned char c) const
1212 {
1213 ++p; // find end
1214 const char* b = p;
1215 while ( *p != '\0' ) {
1216 if ( *p == ']') {
1217 const char* e = p;
1218 // found beginining [ and ending ]
1219 unsigned char last = '\0';
1220 for ( const char* s = b; s < e; ++s ) {
1221 if ( *s == '-' ) {
1222 unsigned char next = *(++s);
1223 if ( (last <= c) && (c <= next) )
1224 return true;
1225 ++s;
1226 }
1227 else {
1228 if ( *s == c )
1229 return true;
1230 last = *s;
1231 }
1232 }
1233 return false;
1234 }
1235 ++p;
1236 }
1237 return false;
1238 }
1239
1240 bool Options::SetWithWildcards::wildCardMatch(const char* pattern, const char* symbol) const
1241 {
1242 const char* s = symbol;
1243 for (const char* p = pattern; *p != '\0'; ++p) {
1244 switch ( *p ) {
1245 case '*':
1246 if ( p[1] == '\0' )
1247 return true;
1248 for (const char* t = s; *t != '\0'; ++t) {
1249 if ( wildCardMatch(&p[1], t) )
1250 return true;
1251 }
1252 return false;
1253 case '?':
1254 if ( *s == '\0' )
1255 return false;
1256 ++s;
1257 break;
1258 case '[':
1259 if ( ! inCharRange(p, *s) )
1260 return false;
1261 ++s;
1262 break;
1263 default:
1264 if ( *s != *p )
1265 return false;
1266 ++s;
1267 }
1268 }
1269 return (*s == '\0');
1270 }
1271
1272
1273 void Options::loadExportFile(const char* fileOfExports, const char* option, SetWithWildcards& set)
1274 {
1275 if ( fileOfExports == NULL )
1276 throwf("missing file after %s", option);
1277 // read in whole file
1278 int fd = ::open(fileOfExports, O_RDONLY, 0);
1279 if ( fd == -1 )
1280 throwf("can't open %s file: %s", option, fileOfExports);
1281 struct stat stat_buf;
1282 ::fstat(fd, &stat_buf);
1283 char* p = (char*)malloc(stat_buf.st_size);
1284 if ( p == NULL )
1285 throwf("can't process %s file: %s", option, fileOfExports);
1286
1287 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1288 throwf("can't read %s file: %s", option, fileOfExports);
1289
1290 if ( this->dumpDependencyInfo() )
1291 this->dumpDependency(Options::depMisc, fileOfExports);
1292
1293 ::close(fd);
1294
1295 // parse into symbols and add to unordered_set
1296 char * const end = &p[stat_buf.st_size];
1297 enum { lineStart, inSymbol, inComment } state = lineStart;
1298 char* symbolStart = NULL;
1299 for (char* s = p; s < end; ++s ) {
1300 switch ( state ) {
1301 case lineStart:
1302 if ( *s =='#' ) {
1303 state = inComment;
1304 }
1305 else if ( !isspace(*s) ) {
1306 state = inSymbol;
1307 symbolStart = s;
1308 }
1309 break;
1310 case inSymbol:
1311 if ( (*s == '\n') || (*s == '\r') ) {
1312 *s = '\0';
1313 // removing any trailing spaces
1314 char* last = s-1;
1315 while ( isspace(*last) ) {
1316 *last = '\0';
1317 --last;
1318 }
1319 set.insert(symbolStart);
1320 symbolStart = NULL;
1321 state = lineStart;
1322 }
1323 break;
1324 case inComment:
1325 if ( (*s == '\n') || (*s == '\r') )
1326 state = lineStart;
1327 break;
1328 }
1329 }
1330 if ( state == inSymbol ) {
1331 warning("missing line-end at end of file \"%s\"", fileOfExports);
1332 int len = end-symbolStart+1;
1333 char* temp = new char[len];
1334 strlcpy(temp, symbolStart, len);
1335
1336 // remove any trailing spaces
1337 char* last = &temp[len-2];
1338 while ( isspace(*last) ) {
1339 *last = '\0';
1340 --last;
1341 }
1342 set.insert(temp);
1343 }
1344
1345 // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
1346 }
1347
1348 void Options::parseAliasFile(const char* fileOfAliases)
1349 {
1350 // read in whole file
1351 int fd = ::open(fileOfAliases, O_RDONLY, 0);
1352 if ( fd == -1 )
1353 throwf("can't open alias file: %s", fileOfAliases);
1354 struct stat stat_buf;
1355 ::fstat(fd, &stat_buf);
1356 char* p = (char*)malloc(stat_buf.st_size+1);
1357 if ( p == NULL )
1358 throwf("can't process alias file: %s", fileOfAliases);
1359
1360 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1361 throwf("can't read alias file: %s", fileOfAliases);
1362 p[stat_buf.st_size] = '\n';
1363 ::close(fd);
1364 if ( this->dumpDependencyInfo() )
1365 this->dumpDependency(Options::depMisc, fileOfAliases);
1366
1367 // parse into symbols and add to fAliases
1368 AliasPair pair;
1369 char * const end = &p[stat_buf.st_size+1];
1370 enum { lineStart, inRealName, inBetween, inAliasName, inComment } state = lineStart;
1371 int lineNumber = 1;
1372 for (char* s = p; s < end; ++s ) {
1373 switch ( state ) {
1374 case lineStart:
1375 if ( *s =='#' ) {
1376 state = inComment;
1377 }
1378 else if ( !isspace(*s) ) {
1379 state = inRealName;
1380 pair.realName = s;
1381 }
1382 break;
1383 case inRealName:
1384 if ( *s == '\n' ) {
1385 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber, fileOfAliases);
1386 ++lineNumber;
1387 state = lineStart;
1388 }
1389 else if ( isspace(*s) ) {
1390 *s = '\0';
1391 state = inBetween;
1392 }
1393 break;
1394 case inBetween:
1395 if ( *s == '\n' ) {
1396 warning("line needs two symbols but has only one at line #%d in \"%s\"", lineNumber, fileOfAliases);
1397 ++lineNumber;
1398 state = lineStart;
1399 }
1400 else if ( ! isspace(*s) ) {
1401 state = inAliasName;
1402 pair.alias = s;
1403 }
1404 break;
1405 case inAliasName:
1406 if ( *s =='#' ) {
1407 *s = '\0';
1408 // removing any trailing spaces
1409 char* last = s-1;
1410 while ( isspace(*last) ) {
1411 *last = '\0';
1412 --last;
1413 }
1414 fAliases.push_back(pair);
1415 state = inComment;
1416 }
1417 else if ( *s == '\n' ) {
1418 *s = '\0';
1419 // removing any trailing spaces
1420 char* last = s-1;
1421 while ( isspace(*last) ) {
1422 *last = '\0';
1423 --last;
1424 }
1425 fAliases.push_back(pair);
1426 state = lineStart;
1427 }
1428 break;
1429 case inComment:
1430 if ( *s == '\n' )
1431 state = lineStart;
1432 break;
1433 }
1434 }
1435
1436 // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
1437 }
1438
1439
1440
1441 void Options::setUndefinedTreatment(const char* treatment)
1442 {
1443 if ( treatment == NULL )
1444 throw "-undefined missing [ warning | error | suppress | dynamic_lookup ]";
1445
1446 if ( strcmp(treatment, "warning") == 0 )
1447 fUndefinedTreatment = kUndefinedWarning;
1448 else if ( strcmp(treatment, "error") == 0 )
1449 fUndefinedTreatment = kUndefinedError;
1450 else if ( strcmp(treatment, "suppress") == 0 )
1451 fUndefinedTreatment = kUndefinedSuppress;
1452 else if ( strcmp(treatment, "dynamic_lookup") == 0 )
1453 fUndefinedTreatment = kUndefinedDynamicLookup;
1454 else
1455 throw "invalid option to -undefined [ warning | error | suppress | dynamic_lookup ]";
1456 }
1457
1458 Options::Treatment Options::parseTreatment(const char* treatment)
1459 {
1460 if ( treatment == NULL )
1461 return kNULL;
1462
1463 if ( strcmp(treatment, "warning") == 0 )
1464 return kWarning;
1465 else if ( strcmp(treatment, "error") == 0 )
1466 return kError;
1467 else if ( strcmp(treatment, "suppress") == 0 )
1468 return kSuppress;
1469 else
1470 return kInvalid;
1471 }
1472
1473 void Options::setMacOSXVersionMin(const char* version)
1474 {
1475 uint32_t value;
1476 if ( !parsePackedVersion32(version, value) ) {
1477 throwf("-macosx_version_min value malformed: '%s'", version);
1478 }
1479 fMacVersionMin = (ld::MacVersionMin)value;
1480 fPlatform = kPlatformOSX;
1481 }
1482
1483 void Options::setIOSVersionMin(const char* version)
1484 {
1485 uint32_t value;
1486 if ( !parsePackedVersion32(version, value) ) {
1487 throwf("-ios_version_min value malformed: '%s'", version);
1488 }
1489 fIOSVersionMin = (ld::IOSVersionMin)value;
1490 fPlatform = kPlatformiOS;
1491 }
1492
1493
1494 void Options::setWatchOSVersionMin(const char* version)
1495 {
1496 uint32_t value;
1497 if ( !parsePackedVersion32(version, value) ) {
1498 throwf("-watchos_version_min value malformed: '%s'", version);
1499 }
1500 fWatchOSVersionMin = (ld::WatchOSVersionMin)value;
1501 fPlatform = kPlatformWatchOS;
1502 }
1503
1504
1505 bool Options::minOS(ld::MacVersionMin requiredMacMin, ld::IOSVersionMin requirediPhoneOSMin)
1506 {
1507 if ( fMacVersionMin != ld::macVersionUnset ) {
1508 return ( fMacVersionMin >= requiredMacMin );
1509 }
1510 else {
1511 return min_iOS(requirediPhoneOSMin);
1512 }
1513 }
1514
1515 bool Options::min_iOS(ld::IOSVersionMin requirediOSMin)
1516 {
1517 if ( fWatchOSVersionMin != ld::wOSVersionUnset ) {
1518 // Hack until we fully track watch and ios versions seperately
1519 return ( (fWatchOSVersionMin + 0x00070000) >= requirediOSMin);
1520 }
1521 else if ( fPlatform == Options::kPlatform_bridgeOS ) {
1522 // Hack until we fully track bridge and ios versions seperately
1523 return ( (fIOSVersionMin + 0x00090000) >= requirediOSMin);
1524 }
1525 else {
1526 return ( fIOSVersionMin >= requirediOSMin );
1527 }
1528 }
1529
1530 void Options::setWeakReferenceMismatchTreatment(const char* treatment)
1531 {
1532 if ( treatment == NULL )
1533 throw "-weak_reference_mismatches missing [ error | weak | non-weak ]";
1534
1535 if ( strcmp(treatment, "error") == 0 )
1536 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchError;
1537 else if ( strcmp(treatment, "weak") == 0 )
1538 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchWeak;
1539 else if ( strcmp(treatment, "non-weak") == 0 )
1540 fWeakReferenceMismatchTreatment = kWeakReferenceMismatchNonWeak;
1541 else
1542 throw "invalid option to -weak_reference_mismatches [ error | weak | non-weak ]";
1543 }
1544
1545 Options::CommonsMode Options::parseCommonsTreatment(const char* mode)
1546 {
1547 if ( mode == NULL )
1548 throw "-commons missing [ ignore_dylibs | use_dylibs | error ]";
1549
1550 if ( strcmp(mode, "ignore_dylibs") == 0 )
1551 return kCommonsIgnoreDylibs;
1552 else if ( strcmp(mode, "use_dylibs") == 0 )
1553 return kCommonsOverriddenByDylibs;
1554 else if ( strcmp(mode, "error") == 0 )
1555 return kCommonsConflictsDylibsError;
1556 else
1557 throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
1558 }
1559
1560 void Options::addDylibOverride(const char* paths)
1561 {
1562 if ( paths == NULL )
1563 throw "-dylib_file must followed by two colon separated paths";
1564 const char* colon = strchr(paths, ':');
1565 if ( colon == NULL )
1566 throw "-dylib_file must followed by two colon separated paths";
1567 int len = colon-paths;
1568 char* target = new char[len+2];
1569 strncpy(target, paths, len);
1570 target[len] = '\0';
1571 DylibOverride entry;
1572 entry.installName = target;
1573 entry.useInstead = &colon[1];
1574 fDylibOverrides.push_back(entry);
1575 }
1576
1577 uint64_t Options::parseAddress(const char* addr)
1578 {
1579 char* endptr;
1580 uint64_t result = strtoull(addr, &endptr, 16);
1581 return result;
1582 }
1583
1584 uint32_t Options::parseProtection(const char* prot)
1585 {
1586 uint32_t result = 0;
1587 for(const char* p = prot; *p != '\0'; ++p) {
1588 switch(tolower(*p)) {
1589 case 'r':
1590 result |= VM_PROT_READ;
1591 break;
1592 case 'w':
1593 result |= VM_PROT_WRITE;
1594 break;
1595 case 'x':
1596 result |= VM_PROT_EXECUTE;
1597 break;
1598 case '-':
1599 break;
1600 default:
1601 throwf("unknown -segprot lettter in %s", prot);
1602 }
1603 }
1604 return result;
1605 }
1606
1607
1608 //
1609 // Parses number of form A[.B[.B[.D[.E]]]] into a uint64_t where the bits are a24.b10.c10.d10.e10
1610 //
1611 uint64_t Options::parseVersionNumber64(const char* versionString)
1612 {
1613 uint64_t a = 0;
1614 uint64_t b = 0;
1615 uint64_t c = 0;
1616 uint64_t d = 0;
1617 uint64_t e = 0;
1618 char* end;
1619 a = strtoul(versionString, &end, 10);
1620 if ( *end == '.' ) {
1621 b = strtoul(&end[1], &end, 10);
1622 if ( *end == '.' ) {
1623 c = strtoul(&end[1], &end, 10);
1624 if ( *end == '.' ) {
1625 d = strtoul(&end[1], &end, 10);
1626 if ( *end == '.' ) {
1627 e = strtoul(&end[1], &end, 10);
1628 }
1629 }
1630 }
1631 }
1632 if ( (*end != '\0') || (a > 0xFFFFFF) || (b > 0x3FF) || (c > 0x3FF) || (d > 0x3FF) || (e > 0x3FF) )
1633 throwf("malformed 64-bit a.b.c.d.e version number: %s", versionString);
1634
1635 return (a << 40) | ( b << 30 ) | ( c << 20 ) | ( d << 10 ) | e;
1636 }
1637
1638
1639 uint32_t Options::currentVersion32() const
1640 {
1641 // warn if it does not fit into 32 bit vers number
1642 uint32_t a = (fDylibCurrentVersion >> 40) & 0xFFFF;
1643 uint32_t b = (fDylibCurrentVersion >> 30) & 0xFF;
1644 uint32_t c = (fDylibCurrentVersion >> 20) & 0xFF;
1645 uint64_t rep32 = ((uint64_t)a << 40) | ((uint64_t)b << 30) | ((uint64_t)c << 20);
1646 if ( rep32 != fDylibCurrentVersion ) {
1647 warning("truncating -current_version to fit in 32-bit space used by old mach-o format");
1648 a = (fDylibCurrentVersion >> 40) & 0xFFFFFF;
1649 if ( a > 0xFFFF )
1650 a = 0xFFFF;
1651 b = (fDylibCurrentVersion >> 30) & 0x3FF;
1652 if ( b > 0xFF )
1653 b = 0xFF;
1654 c = (fDylibCurrentVersion >> 20) & 0x3FF;
1655 if ( c > 0xFF )
1656 c = 0xFF;
1657 }
1658 return (a << 16) | ( b << 8 ) | c;
1659 }
1660
1661 //
1662 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
1663 //
1664 uint32_t Options::parseVersionNumber32(const char* versionString)
1665 {
1666 uint32_t x = 0;
1667 uint32_t y = 0;
1668 uint32_t z = 0;
1669 char* end;
1670 x = strtoul(versionString, &end, 10);
1671 if ( *end == '.' ) {
1672 y = strtoul(&end[1], &end, 10);
1673 if ( *end == '.' ) {
1674 z = strtoul(&end[1], &end, 10);
1675 }
1676 }
1677 if ( (*end != '\0') || (x > 0xffff) || (y > 0xff) || (z > 0xff) )
1678 throwf("malformed 32-bit x.y.z version number: %s", versionString);
1679
1680 return (x << 16) | ( y << 8 ) | z;
1681 }
1682
1683 static const char* cstringSymbolName(const char* orderFileString)
1684 {
1685 char* result;
1686 asprintf(&result, "cstring=%s", orderFileString);
1687 // convert escaped characters
1688 char* d = result;
1689 for(const char* s=result; *s != '\0'; ++s, ++d) {
1690 if ( *s == '\\' ) {
1691 ++s;
1692 switch ( *s ) {
1693 case 'n':
1694 *d = '\n';
1695 break;
1696 case 't':
1697 *d = '\t';
1698 break;
1699 case 'v':
1700 *d = '\v';
1701 break;
1702 case 'b':
1703 *d = '\b';
1704 break;
1705 case 'r':
1706 *d = '\r';
1707 break;
1708 case 'f':
1709 *d = '\f';
1710 break;
1711 case 'a':
1712 *d = '\a';
1713 break;
1714 case '\\':
1715 *d = '\\';
1716 break;
1717 case '?':
1718 *d = '\?';
1719 break;
1720 case '\'':
1721 *d = '\r';
1722 break;
1723 case '\"':
1724 *d = '\"';
1725 break;
1726 case 'x':
1727 // hexadecimal value of char
1728 {
1729 ++s;
1730 char value = 0;
1731 while ( isxdigit(*s) ) {
1732 value *= 16;
1733 if ( isdigit(*s) )
1734 value += (*s-'0');
1735 else
1736 value += ((toupper(*s)-'A') + 10);
1737 ++s;
1738 }
1739 *d = value;
1740 }
1741 break;
1742 default:
1743 if ( isdigit(*s) ) {
1744 // octal value of char
1745 char value = 0;
1746 while ( isdigit(*s) ) {
1747 value = (value << 3) + (*s-'0');
1748 ++s;
1749 }
1750 *d = value;
1751 }
1752 }
1753 }
1754 else {
1755 *d = *s;
1756 }
1757 }
1758 *d = '\0';
1759 return result;
1760 }
1761
1762 void Options::parseOrderFile(const char* path, bool cstring)
1763 {
1764 // order files override auto-ordering
1765 fAutoOrderInitializers = false;
1766
1767 // <rdar://problem/24856050> ld64 should prefer OrderFiles from the SDK over the ones in /
1768 for (const char* sdkPath : fSDKPaths) {
1769 char fullPath[PATH_MAX];
1770 strlcpy(fullPath, sdkPath, PATH_MAX);
1771 strlcat(fullPath, "/", PATH_MAX);
1772 strlcat(fullPath, path, PATH_MAX);
1773 struct stat statBuffer;
1774 if ( stat(fullPath, &statBuffer) == 0 ) {
1775 path = strdup(fullPath);
1776 break;
1777 }
1778 }
1779
1780 // read in whole file
1781 int fd = ::open(path, O_RDONLY, 0);
1782 if ( fd == -1 )
1783 throwf("can't open order file: %s", path);
1784 struct stat stat_buf;
1785 ::fstat(fd, &stat_buf);
1786 char* p = (char*)malloc(stat_buf.st_size+1);
1787 if ( p == NULL )
1788 throwf("can't process order file: %s", path);
1789 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1790 throwf("can't read order file: %s", path);
1791 ::close(fd);
1792 p[stat_buf.st_size] = '\n';
1793 if ( this->dumpDependencyInfo() )
1794 this->dumpDependency(Options::depMisc, path);
1795
1796 // parse into vector of pairs
1797 char * const end = &p[stat_buf.st_size+1];
1798 enum { lineStart, inSymbol, inComment } state = lineStart;
1799 char* symbolStart = NULL;
1800 for (char* s = p; s < end; ++s ) {
1801 switch ( state ) {
1802 case lineStart:
1803 if ( *s =='#' ) {
1804 state = inComment;
1805 }
1806 else if ( !isspace(*s) || cstring ) {
1807 state = inSymbol;
1808 symbolStart = s;
1809 }
1810 break;
1811 case inSymbol:
1812 if ( (*s == '\n') || (!cstring && (*s == '#')) ) {
1813 bool wasComment = (*s == '#');
1814 *s = '\0';
1815 // removing any trailing spaces
1816 char* last = s-1;
1817 while ( isspace(*last) ) {
1818 *last = '\0';
1819 --last;
1820 }
1821 // if there is an architecture prefix, only use this symbol it if matches current arch
1822 if ( strncmp(symbolStart, "ppc:", 4) == 0 ) {
1823 symbolStart = NULL;
1824 }
1825 else if ( strncmp(symbolStart, "ppc64:", 6) == 0 ) {
1826 symbolStart = NULL;
1827 }
1828 else if ( strncmp(symbolStart, "i386:", 5) == 0 ) {
1829 if ( fArchitecture == CPU_TYPE_I386 )
1830 symbolStart = &symbolStart[5];
1831 else
1832 symbolStart = NULL;
1833 }
1834 else if ( strncmp(symbolStart, "x86_64:", 7) == 0 ) {
1835 if ( fArchitecture == CPU_TYPE_X86_64 )
1836 symbolStart = &symbolStart[7];
1837 else
1838 symbolStart = NULL;
1839 }
1840 else if ( strncmp(symbolStart, "arm:", 4) == 0 ) {
1841 if ( fArchitecture == CPU_TYPE_ARM )
1842 symbolStart = &symbolStart[4];
1843 else
1844 symbolStart = NULL;
1845 }
1846 else if ( strncmp(symbolStart, "arm64:", 6) == 0 ) {
1847 if ( fArchitecture == CPU_TYPE_ARM64 )
1848 symbolStart = &symbolStart[6];
1849 else
1850 symbolStart = NULL;
1851 }
1852 if ( symbolStart != NULL ) {
1853 char* objFileName = NULL;
1854 char* colon = strstr(symbolStart, ".o:");
1855 if ( colon != NULL ) {
1856 colon[2] = '\0';
1857 objFileName = symbolStart;
1858 symbolStart = &colon[3];
1859 }
1860 else {
1861 colon = strstr(symbolStart, ".o):");
1862 if ( colon != NULL ) {
1863 colon[3] = '\0';
1864 objFileName = symbolStart;
1865 symbolStart = &colon[4];
1866 }
1867 }
1868 // trim leading spaces
1869 while ( isspace(*symbolStart) )
1870 ++symbolStart;
1871 Options::OrderedSymbol pair;
1872 if ( cstring )
1873 pair.symbolName = cstringSymbolName(symbolStart);
1874 else
1875 pair.symbolName = symbolStart;
1876 pair.objectFileName = objFileName;
1877 fOrderedSymbols.push_back(pair);
1878 }
1879 symbolStart = NULL;
1880 if ( wasComment )
1881 state = inComment;
1882 else
1883 state = lineStart;
1884 }
1885 break;
1886 case inComment:
1887 if ( *s == '\n' )
1888 state = lineStart;
1889 break;
1890 }
1891 }
1892 // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
1893 }
1894
1895 void Options::parseSectionOrderFile(const char* segment, const char* section, const char* path)
1896 {
1897 if ( (strcmp(section, "__cstring") == 0) && (strcmp(segment, "__TEXT") == 0) ) {
1898 parseOrderFile(path, true);
1899 }
1900 else if ( (strncmp(section, "__literal",9) == 0) && (strcmp(segment, "__TEXT") == 0) ) {
1901 warning("sorting of __literal[4,8,16] sections not supported");
1902 }
1903 else {
1904 // ignore section information and append all symbol names to global order file
1905 parseOrderFile(path, false);
1906 }
1907 }
1908
1909 void Options::addSection(const char* segment, const char* section, const char* path)
1910 {
1911 if ( strlen(segment) > 16 )
1912 throw "-seccreate segment name max 16 chars";
1913 if ( strlen(section) > 16 ) {
1914 char* tmp = strdup(section);
1915 tmp[16] = '\0';
1916 warning("-seccreate section name (%s) truncated to 16 chars (%s)\n", section, tmp);
1917 section = tmp;
1918 }
1919
1920 // read in whole file
1921 int fd = ::open(path, O_RDONLY, 0);
1922 if ( fd == -1 )
1923 throwf("can't open -sectcreate file: %s", path);
1924 struct stat stat_buf;
1925 ::fstat(fd, &stat_buf);
1926 char* p = (char*)malloc(stat_buf.st_size);
1927 if ( p == NULL )
1928 throwf("can't process -sectcreate file: %s", path);
1929 if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
1930 throwf("can't read -sectcreate file: %s", path);
1931 ::close(fd);
1932
1933 // record section to create
1934 ExtraSection info = { segment, section, path, (uint8_t*)p, (uint64_t)stat_buf.st_size };
1935 fExtraSections.push_back(info);
1936 }
1937
1938 void Options::addSectionRename(const char* srcSegment, const char* srcSection, const char* dstSegment, const char* dstSection)
1939 {
1940 if ( strlen(srcSegment) > 16 )
1941 throw "-rename_section segment name max 16 chars";
1942 if ( strlen(srcSection) > 16 )
1943 throw "-rename_section section name max 16 chars";
1944 if ( strlen(dstSegment) > 16 )
1945 throw "-rename_section segment name max 16 chars";
1946 if ( strlen(dstSection) > 16 )
1947 throw "-rename_section section name max 16 chars";
1948
1949 SectionRename info;
1950 info.fromSegment = srcSegment;
1951 info.fromSection = srcSection;
1952 info.toSegment = dstSegment;
1953 info.toSection = dstSection;
1954
1955 fSectionRenames.push_back(info);
1956 }
1957
1958
1959 void Options::addSegmentRename(const char* srcSegment, const char* dstSegment)
1960 {
1961 if ( strlen(srcSegment) > 16 )
1962 throw "-rename_segment segment name max 16 chars";
1963 if ( strlen(dstSegment) > 16 )
1964 throw "-rename_segment segment name max 16 chars";
1965
1966 SegmentRename info;
1967 info.fromSegment = srcSegment;
1968 info.toSegment = dstSegment;
1969
1970 fSegmentRenames.push_back(info);
1971 }
1972
1973
1974
1975 void Options::addSymbolMove(const char* dstSegment, const char* symbolList,
1976 std::vector<SymbolsMove>& list, const char* optionName)
1977 {
1978 if ( strlen(dstSegment) > 16 )
1979 throwf("%s segment name max 16 chars", optionName);
1980
1981 SymbolsMove tmp;
1982 list.push_back(tmp);
1983 SymbolsMove& info = list.back();
1984 info.toSegment = dstSegment;
1985 loadExportFile(symbolList, optionName, info.symbols);
1986 }
1987
1988 bool Options::moveRwSymbol(const char* symName, const char* filePath, const char*& seg, bool& wildCardMatch) const
1989 {
1990 for (std::vector<SymbolsMove>::const_iterator it=fSymbolsMovesData.begin(); it != fSymbolsMovesData.end(); ++it) {
1991 const SymbolsMove& info = *it;
1992 if ( info.symbols.containsWithPrefix(symName, filePath, wildCardMatch)) {
1993 seg = info.toSegment;
1994 return true;
1995 }
1996 }
1997 return false;
1998 }
1999
2000 bool Options::moveRoSymbol(const char* symName, const char* filePath, const char*& seg, bool& wildCardMatch) const
2001 {
2002 for (std::vector<SymbolsMove>::const_iterator it=fSymbolsMovesCode.begin(); it != fSymbolsMovesCode.end(); ++it) {
2003 const SymbolsMove& info = *it;
2004 if ( info.symbols.containsWithPrefix(symName, filePath, wildCardMatch)) {
2005 seg = info.toSegment;
2006 return true;
2007 }
2008 }
2009 return false;
2010 }
2011
2012 void Options::addSectionAlignment(const char* segment, const char* section, const char* alignmentStr)
2013 {
2014 if ( strlen(segment) > 16 )
2015 throw "-sectalign segment name max 16 chars";
2016 if ( strlen(section) > 16 )
2017 throw "-sectalign section name max 16 chars";
2018
2019 // argument to -sectalign is a hexadecimal number
2020 char* endptr;
2021 unsigned long value = strtoul(alignmentStr, &endptr, 16);
2022 if ( *endptr != '\0')
2023 throw "argument for -sectalign is not a hexadecimal number";
2024 if ( value > 0x8000 )
2025 throw "argument for -sectalign must be less than or equal to 0x8000";
2026 if ( value == 0 ) {
2027 warning("zero is not a valid -sectalign");
2028 value = 1;
2029 }
2030
2031 // alignment is power of 2 (e.g. page alignment = 12)
2032 uint8_t alignment = (uint8_t)__builtin_ctz(value);
2033 if ( (unsigned long)(1 << alignment) != value ) {
2034 warning("alignment for -sectalign %s %s is not a power of two, using 0x%X",
2035 segment, section, 1 << alignment);
2036 }
2037
2038 SectionAlignment info = { segment, section, alignment };
2039 fSectionAlignments.push_back(info);
2040 }
2041
2042 void Options::addLibrary(const FileInfo& info)
2043 {
2044 // if this library has already been added, don't add again (archives are automatically repeatedly searched)
2045 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
2046 if ( strcmp(info.path, fit->path) == 0 ) {
2047 // if dylib is specified again but weak, record that it should be weak
2048 if ( info.options.fWeakImport )
2049 fit->options.fWeakImport = true;
2050 return;
2051 }
2052 }
2053 // add to list
2054 fInputFiles.push_back(info);
2055 }
2056
2057 void Options::warnObsolete(const char* arg)
2058 {
2059 warning("option %s is obsolete and being ignored", arg);
2060 }
2061
2062
2063 void Options::cannotBeUsedWithBitcode(const char* arg)
2064 {
2065 if ( fBundleBitcode )
2066 throwf("%s and -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES) cannot be used together", arg);
2067 }
2068
2069 std::string Options::getVersionString32(uint32_t ver) const
2070 {
2071 if (ver == 0 || ver >= 0x10000000)
2072 return "0.0.0";
2073
2074 unsigned microVersion = ver & 0xFF;
2075 unsigned minorVersion = (ver >> 8) & 0xFF;
2076 unsigned majorVersion = (ver >> 16) & 0xFF;
2077 std::stringstream versionString;
2078 versionString << majorVersion << "." << minorVersion << "." << microVersion;
2079 return versionString.str();
2080 }
2081
2082 std::string Options::getVersionString64(uint64_t ver) const
2083 {
2084 uint64_t a = (ver >> 40) & 0xFFFFFF;
2085 uint64_t b = (ver >> 30) & 0x3FF;
2086 uint64_t c = (ver >> 20) & 0x3FF;
2087 uint64_t d = (ver >> 10) & 0x3FF;
2088 uint64_t e = ver & 0x3FF;
2089 std::stringstream versionString;
2090 versionString << a << "." << b << "." << c << "." << d << "." << e;
2091 return versionString.str();
2092 }
2093
2094 // Convert X.Y[.Z] to 32-bit value xxxxyyzz
2095 bool Options::parsePackedVersion32(const std::string& versionStr, uint32_t &result)
2096 {
2097 result = 0;
2098
2099 if ( versionStr.empty() )
2100 return false;
2101
2102 size_t pos = versionStr.find('.');
2103 if ( pos == std::string::npos )
2104 return false;
2105
2106 std::string majorStr = versionStr.substr(0, pos);
2107 std::string rest = versionStr.substr(pos+1);
2108
2109 try {
2110 size_t majorEnd;
2111 int majorValue = std::stoi(majorStr, &majorEnd);
2112 if ( majorEnd != majorStr.size() )
2113 return false;
2114 if ( majorValue < 0 )
2115 return false;
2116 if ( majorValue > 65535 )
2117 return false;
2118
2119 std::string minorStr;
2120 std::string microStr;
2121 pos = rest.find('.');
2122 if ( pos == std::string::npos ) {
2123 minorStr = rest;
2124 }
2125 else {
2126 minorStr = rest.substr(0, pos);
2127 microStr = rest.substr(pos+1);
2128 }
2129
2130 size_t minorEnd;
2131 int minorValue = std::stoi(minorStr, &minorEnd);
2132 if ( minorEnd != minorStr.size() )
2133 return false;
2134 if ( minorValue < 0 )
2135 return false;
2136 if ( minorValue > 255 )
2137 return false;
2138
2139 int microValue = 0;
2140 if ( !microStr.empty() ) {
2141 size_t microEnd;
2142 microValue = std::stoi(microStr, &microEnd);
2143 if ( microEnd != microStr.size() )
2144 return false;
2145 if ( microValue < 0 )
2146 return false;
2147 if ( microValue > 255 )
2148 return false;
2149 }
2150
2151 result = (majorValue << 16) | (minorValue << 8) | microValue;
2152
2153 return true;
2154 }
2155 catch (...) {
2156 // std::stoi() throws exception on malformed input
2157 return false;
2158 }
2159 }
2160
2161 std::string Options::getSDKVersionStr() const
2162 {
2163 return getVersionString32(fSDKVersion);
2164 }
2165
2166 std::string Options::getPlatformStr() const
2167 {
2168 switch (fPlatform) {
2169 case Options::kPlatformOSX:
2170 return "MacOSX";
2171 case Options::kPlatformiOS:
2172 if (targetIOSSimulator())
2173 return "iPhoneSimulator";
2174 else
2175 return "iPhoneOS";
2176 case Options::kPlatformWatchOS:
2177 if (targetIOSSimulator())
2178 return "watchOS Simulator";
2179 else
2180 return "watchOS";
2181 #if SUPPORT_APPLE_TV
2182 case Options::kPlatform_tvOS:
2183 if (targetIOSSimulator())
2184 return "AppleTVSimulator";
2185 else
2186 return "AppleTVOS";
2187 break;
2188 #endif
2189 case Options::kPlatform_bridgeOS:
2190 return "bridgeOS";
2191 case Options::kPlatformUnknown:
2192 return "Unknown";
2193 }
2194 }
2195
2196 std::vector<std::string> Options::writeBitcodeLinkOptions() const
2197 {
2198 std::vector<std::string> linkCommand;
2199 switch ( fOutputKind ) {
2200 case Options::kDynamicLibrary:
2201 linkCommand.push_back("-dylib");
2202 linkCommand.push_back("-compatibility_version");
2203 if ( fDylibCompatVersion != 0 ) {
2204 linkCommand.push_back(getVersionString32(fDylibCompatVersion));
2205 } else {
2206 linkCommand.push_back(getVersionString32(currentVersion32()));
2207 }
2208 if ( fDylibCurrentVersion != 0 ) {
2209 linkCommand.push_back("-current_version");
2210 linkCommand.push_back(getVersionString64(fDylibCurrentVersion));
2211 }
2212 linkCommand.push_back("-install_name");
2213 linkCommand.push_back(installPath());
2214 break;
2215 case Options::kDynamicExecutable:
2216 linkCommand.push_back("-execute");
2217 break;
2218 case Options::kObjectFile:
2219 linkCommand.push_back("-r");
2220 break;
2221 default:
2222 throwf("could not write bitcode options file output kind\n");
2223 }
2224
2225 if (!fImplicitlyLinkPublicDylibs)
2226 linkCommand.push_back("-no_implicit_dylibs");
2227
2228 // Add deployment target.
2229 // Platform is allowed to be unknown for "ld -r".
2230 switch (fPlatform) {
2231 case Options::kPlatformOSX:
2232 linkCommand.push_back("-macosx_version_min");
2233 linkCommand.push_back(getVersionString32((unsigned)fMacVersionMin));
2234 break;
2235 case Options::kPlatformiOS:
2236 if (targetIOSSimulator())
2237 linkCommand.push_back("-ios_simulator_version_min");
2238 else
2239 linkCommand.push_back("-ios_version_min");
2240 linkCommand.push_back(getVersionString32((unsigned)fIOSVersionMin));
2241 break;
2242 case Options::kPlatformWatchOS:
2243 if (targetIOSSimulator())
2244 linkCommand.push_back("-watchos_simulator_version_min");
2245 else
2246 linkCommand.push_back("-watchos_version_min");
2247 linkCommand.push_back(getVersionString32((unsigned)fIOSVersionMin));
2248 break;
2249 #if SUPPORT_APPLE_TV
2250 case Options::kPlatform_tvOS:
2251 if (targetIOSSimulator())
2252 linkCommand.push_back("-tvos_simulator_version_min");
2253 else
2254 linkCommand.push_back("-tvos_version_min");
2255 linkCommand.push_back(getVersionString32((unsigned)fIOSVersionMin));
2256 break;
2257 #endif
2258 case Options::kPlatform_bridgeOS:
2259 linkCommand.push_back("-bridgeos_version_min");
2260 linkCommand.push_back(getVersionString32((unsigned)fIOSVersionMin));
2261 break;
2262 case Options::kPlatformUnknown:
2263 if ( fOutputKind != Options::kObjectFile ) {
2264 throwf("platform is unknown for final bitcode bundle,"
2265 "deployment target and min version is required for -bitcode_bundle");
2266 }
2267 break;
2268 }
2269
2270
2271 // entry name
2272 if ( fEntryName ) {
2273 linkCommand.push_back("-e");
2274 linkCommand.push_back(fEntryName);
2275 }
2276
2277 // Write rpaths
2278 if (!fRPaths.empty()) {
2279 for (std::vector<const char*>::const_iterator it=fRPaths.begin(); it != fRPaths.end(); ++it) {
2280 linkCommand.push_back("-rpath");
2281 linkCommand.push_back(*it);
2282 }
2283 }
2284
2285 // Other bitcode compatiable options
2286 if ( fObjCABIVersion1Override ) {
2287 linkCommand.push_back("-objc_abi_version");
2288 linkCommand.push_back("1");
2289 } else if ( fObjCABIVersion2Override ) {
2290 linkCommand.push_back("-objc_abi_version");
2291 linkCommand.push_back("2");
2292 }
2293 if ( fExecutablePath ) {
2294 linkCommand.push_back("-executable_path");
2295 linkCommand.push_back(fExecutablePath);
2296 }
2297 if ( fDeadStrip )
2298 linkCommand.push_back("-dead_strip");
2299 if ( fExportDynamic )
2300 linkCommand.push_back("-export_dynamic");
2301 if ( fMarkAppExtensionSafe && fCheckAppExtensionSafe )
2302 linkCommand.push_back("-application_extension");
2303
2304 if ( fSourceVersionLoadCommandForceOn )
2305 linkCommand.push_back("-add_source_version");
2306 if ( fSourceVersion != 0 ) {
2307 linkCommand.push_back("-source_version");
2308 linkCommand.push_back(getVersionString64(fSourceVersion));
2309 }
2310
2311 // linker flag added by swift driver
2312 // rdar://problem/20108072
2313 if ( !fObjcCategoryMerging )
2314 linkCommand.push_back("-no_objc_category_merging");
2315
2316 return linkCommand;
2317 }
2318
2319 //
2320 // Process all command line arguments.
2321 //
2322 // The only error checking done here is that each option is valid and if it has arguments
2323 // that they too are valid.
2324 //
2325 // The general rule is "last option wins", i.e. if both -bundle and -dylib are specified,
2326 // whichever was last on the command line is used.
2327 //
2328 // Error check for invalid combinations of options is done in checkIllegalOptionCombinations()
2329 //
2330 void Options::parse(int argc, const char* argv[])
2331 {
2332 // Store the original args in the link snapshot.
2333 fLinkSnapshot.recordRawArgs(argc, argv);
2334
2335 // pass one builds search list from -L and -F options
2336 this->buildSearchPaths(argc, argv);
2337
2338 // reduce re-allocations
2339 fInputFiles.reserve(32);
2340
2341 // pass two parse all other options
2342 for(int i=1; i < argc; ++i) {
2343 const char* arg = argv[i];
2344
2345 if ( arg[0] == '-' ) {
2346 // by default, copy one arg to the snapshot link command, and do no file copying
2347 int snapshotArgIndex = i;
2348 int snapshotArgCount = -1; // -1 means compute count based on change in index
2349 int snapshotFileArgIndex = -1; // -1 means no data file parameter to arg
2350
2351 // Since we don't care about the files passed, just the option names, we do this here.
2352 if (fPrintOptions)
2353 fprintf (stderr, "[Logging ld64 options]\t%s\n", arg);
2354
2355 if ( (arg[1] == 'L') || (arg[1] == 'F') ) {
2356 snapshotArgCount = 0; // stripped out of link snapshot
2357 if (arg[2] == '\0')
2358 ++i;
2359 // previously handled by buildSearchPaths()
2360 }
2361 // The one gnu style option we have to keep compatibility
2362 // with gcc. Might as well have the single hyphen one as well.
2363 else if ( (strcmp(arg, "--help") == 0)
2364 || (strcmp(arg, "-help") == 0)) {
2365 fprintf (stdout, "ld64: For information on command line options please use 'man ld'.\n");
2366 exit (0);
2367 }
2368 else if ( strcmp(arg, "-arch") == 0 ) {
2369 parseArch(argv[++i]);
2370 }
2371 else if ( strcmp(arg, "-dynamic") == 0 ) {
2372 // default
2373 }
2374 else if ( strcmp(arg, "-static") == 0 ) {
2375 fForStatic = true;
2376 if ( (fOutputKind != kObjectFile) && (fOutputKind != kKextBundle) ) {
2377 fOutputKind = kStaticExecutable;
2378 }
2379 cannotBeUsedWithBitcode(arg);
2380 }
2381 else if ( strcmp(arg, "-dylib") == 0 ) {
2382 fOutputKind = kDynamicLibrary;
2383 }
2384 else if ( strcmp(arg, "-bundle") == 0 ) {
2385 fOutputKind = kDynamicBundle;
2386 cannotBeUsedWithBitcode(arg);
2387 }
2388 else if ( strcmp(arg, "-dylinker") == 0 ) {
2389 fOutputKind = kDyld;
2390 cannotBeUsedWithBitcode(arg);
2391 }
2392 else if ( strcmp(arg, "-execute") == 0 ) {
2393 if ( fOutputKind != kStaticExecutable )
2394 fOutputKind = kDynamicExecutable;
2395 }
2396 else if ( strcmp(arg, "-preload") == 0 ) {
2397 fOutputKind = kPreload;
2398 cannotBeUsedWithBitcode(arg);
2399 }
2400 else if ( strcmp(arg, "-r") == 0 ) {
2401 fOutputKind = kObjectFile;
2402 }
2403 else if ( strcmp(arg, "-kext") == 0 ) {
2404 fOutputKind = kKextBundle;
2405 cannotBeUsedWithBitcode(arg);
2406 }
2407 else if ( strcmp(arg, "-o") == 0 ) {
2408 snapshotArgCount = 0;
2409 fOutputFile = argv[++i];
2410 fLinkSnapshot.setSnapshotName(fOutputFile);
2411 }
2412 else if ( strncmp(arg, "-lazy-l", 7) == 0 ) {
2413 snapshotArgCount = 0;
2414 FileInfo info = findLibrary(&arg[7], true);
2415 info.options.fLazyLoad = true;
2416 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2417 addLibrary(info);
2418 fUsingLazyDylibLinking = true;
2419 cannotBeUsedWithBitcode(arg);
2420 }
2421 else if ( strcmp(arg, "-lto_library") == 0 ) {
2422 snapshotFileArgIndex = 1;
2423 fOverridePathlibLTO = argv[++i];
2424 if ( fOverridePathlibLTO == NULL )
2425 throw "missing argument to -lto_library";
2426 }
2427 else if ( strcmp(arg, "-cache_path_lto") == 0 ) {
2428 fLtoCachePath = argv[++i];
2429 if ( fLtoCachePath == NULL )
2430 throw "missing argument to -cache_path_lto";
2431 }
2432 else if ( strcmp(arg, "-prune_interval_lto") == 0 ) {
2433 const char* value = argv[++i];
2434 if ( value == NULL )
2435 throw "missing argument to -prune_interval_lto";
2436 char* endptr;
2437 fLtoPruneInterval = strtoul(value, &endptr, 10);
2438 if ( *endptr != '\0')
2439 throw "invalid argument for -prune_interval_lto";
2440 }
2441 else if ( strcmp(arg, "-prune_after_lto") == 0 ) {
2442 const char* value = argv[++i];
2443 if ( value == NULL )
2444 throw "missing argument to -prune_after_lto";
2445 char* endptr;
2446 fLtoPruneAfter = strtoul(value, &endptr, 10);
2447 if ( *endptr != '\0')
2448 throw "invalid argument for -prune_after_lto";
2449 }
2450 else if ( strcmp(arg, "-max_relative_cache_size_lto") == 0 ) {
2451 const char* value = argv[++i];
2452 if ( value == NULL )
2453 throw "missing argument to -max_relative_cache_size_lto";
2454 char* endptr;
2455 fLtoMaxCacheSize = strtoul(value, &endptr, 10);
2456 if ( *endptr != '\0')
2457 throw "invalid argument for -max_relative_cache_size_lto";
2458 if (fLtoMaxCacheSize > 100)
2459 throw "Expect a value between 0 and 100 for -max_relative_cache_size_lto";
2460 }
2461 else if ( (arg[1] == 'l') && (strncmp(arg,"-lazy_",6) !=0) ) {
2462 snapshotArgCount = 0;
2463 FileInfo info = findLibrary(&arg[2]);
2464 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2465 addLibrary(info);
2466 }
2467 // This causes a dylib to be weakly bound at
2468 // link time. This corresponds to weak_import.
2469 else if ( strncmp(arg, "-weak-l", 7) == 0 ) {
2470 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2471 snapshotArgCount = 0;
2472 FileInfo info = findLibrary(&arg[7]);
2473 info.options.fWeakImport = true;
2474 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2475 addLibrary(info);
2476 }
2477 // Avoid lazy binding.
2478 else if ( strcmp(arg, "-bind_at_load") == 0 ) {
2479 fBindAtLoad = true;
2480 cannotBeUsedWithBitcode(arg);
2481 }
2482 else if ( strcmp(arg, "-twolevel_namespace") == 0 ) {
2483 fNameSpace = kTwoLevelNameSpace;
2484 }
2485 else if ( strcmp(arg, "-flat_namespace") == 0 ) {
2486 fNameSpace = kFlatNameSpace;
2487 cannotBeUsedWithBitcode(arg);
2488 }
2489 // Also sets a bit to ensure dyld causes everything
2490 // in the namespace to be flat.
2491 // ??? Deprecate
2492 else if ( strcmp(arg, "-force_flat_namespace") == 0 ) {
2493 fNameSpace = kForceFlatNameSpace;
2494 cannotBeUsedWithBitcode(arg);
2495 }
2496 // Similar to --whole-archive.
2497 else if ( strcmp(arg, "-all_load") == 0 ) {
2498 fFullyLoadArchives = true;
2499 }
2500 else if ( strcmp(arg, "-noall_load") == 0) {
2501 warnObsolete(arg);
2502 }
2503 // Similar to -all_load
2504 else if ( strcmp(arg, "-ObjC") == 0 ) {
2505 fLoadAllObjcObjectsFromArchives = true;
2506 }
2507 // Similar to -all_load, but for the following archive only.
2508 else if ( strcmp(arg, "-force_load") == 0 ) {
2509 FileInfo info = findFile(argv[++i]);
2510 info.options.fForceLoad = true;
2511 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2512 addLibrary(info);
2513 }
2514 // Library versioning.
2515 else if ( (strcmp(arg, "-dylib_compatibility_version") == 0)
2516 || (strcmp(arg, "-compatibility_version") == 0)) {
2517 const char* vers = argv[++i];
2518 if ( vers == NULL )
2519 throw "-dylib_compatibility_version missing <version>";
2520 fDylibCompatVersion = parseVersionNumber32(vers);
2521 }
2522 else if ( (strcmp(arg, "-dylib_current_version") == 0)
2523 || (strcmp(arg, "-current_version") == 0)) {
2524 const char* vers = argv[++i];
2525 if ( vers == NULL )
2526 throw "-dylib_current_version missing <version>";
2527 fDylibCurrentVersion = parseVersionNumber64(vers);
2528 }
2529 else if ( strcmp(arg, "-sectorder") == 0 ) {
2530 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
2531 throw "-sectorder missing <segment> <section> <file-path>";
2532 snapshotFileArgIndex = 3;
2533 parseSectionOrderFile(argv[i+1], argv[i+2], argv[i+3]);
2534 i += 3;
2535 cannotBeUsedWithBitcode(arg);
2536 }
2537 else if ( strcmp(arg, "-order_file") == 0 ) {
2538 snapshotFileArgIndex = 1;
2539 parseOrderFile(argv[++i], false);
2540 }
2541 else if ( strcmp(arg, "-order_file_statistics") == 0 ) {
2542 fPrintOrderFileStatistics = true;
2543 cannotBeUsedWithBitcode(arg);
2544 }
2545 // ??? Deprecate segcreate.
2546 // -sectcreate puts whole files into a section in the output.
2547 else if ( (strcmp(arg, "-sectcreate") == 0) || (strcmp(arg, "-segcreate") == 0) ) {
2548 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
2549 throw "-sectcreate missing <segment> <section> <file-path>";
2550 snapshotFileArgIndex = 3;
2551 addSection(argv[i+1], argv[i+2], argv[i+3]);
2552 i += 3;
2553 }
2554 // Since we have a full path in binary/library names we need to be able to override it.
2555 else if ( (strcmp(arg, "-dylib_install_name") == 0)
2556 || (strcmp(arg, "-dylinker_install_name") == 0)
2557 || (strcmp(arg, "-install_name") == 0)) {
2558 fDylibInstallName = argv[++i];
2559 if ( fDylibInstallName == NULL )
2560 throw "-install_name missing <path>";
2561 }
2562 // Sets the base address of the output.
2563 else if ( (strcmp(arg, "-seg1addr") == 0) || (strcmp(arg, "-image_base") == 0) ) {
2564 const char* address = argv[++i];
2565 if ( address == NULL )
2566 throwf("%s missing <address>", arg);
2567 fBaseAddress = parseAddress(address);
2568 uint64_t temp = ((fBaseAddress+fSegmentAlignment-1) & (-fSegmentAlignment));
2569 if ( fBaseAddress != temp ) {
2570 warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment);
2571 fBaseAddress = temp;
2572 }
2573 cannotBeUsedWithBitcode(arg);
2574 }
2575 else if ( strcmp(arg, "-e") == 0 ) {
2576 fEntryName = argv[++i];
2577 }
2578 // Same as -@ from the FSF linker.
2579 else if ( strcmp(arg, "-filelist") == 0 ) {
2580 snapshotArgCount = 0;
2581 const char* path = argv[++i];
2582 if ( (path == NULL) || (path[0] == '-') )
2583 throw "-filelist missing <path>";
2584 ld::File::Ordinal baseOrdinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2585 loadFileList(path, baseOrdinal);
2586 }
2587 else if ( strcmp(arg, "-keep_private_externs") == 0 ) {
2588 cannotBeUsedWithBitcode(arg);
2589 fKeepPrivateExterns = true;
2590 }
2591 else if ( strcmp(arg, "-final_output") == 0 ) {
2592 fFinalName = argv[++i];
2593 }
2594 // Ensure that all calls to exported symbols go through lazy pointers. Multi-module
2595 // just ensures that this happens for cross object file boundaries.
2596 else if ( (strcmp(arg, "-interposable") == 0) || (strcmp(arg, "-multi_module") == 0)) {
2597 switch ( fInterposeMode ) {
2598 case kInterposeNone:
2599 case kInterposeAllExternal:
2600 fInterposeMode = kInterposeAllExternal;
2601 break;
2602 case kInterposeSome:
2603 // do nothing, -interposable_list overrides -interposable"
2604 break;
2605 }
2606 cannotBeUsedWithBitcode(arg);
2607 }
2608 else if ( strcmp(arg, "-interposable_list") == 0 ) {
2609 snapshotFileArgIndex = 1;
2610 fInterposeMode = kInterposeSome;
2611 loadExportFile(argv[++i], "-interposable_list", fInterposeList);
2612 cannotBeUsedWithBitcode(arg);
2613 }
2614 // Default for -interposable/-multi_module/-single_module.
2615 else if ( strcmp(arg, "-single_module") == 0 ) {
2616 fInterposeMode = kInterposeNone;
2617 }
2618 else if ( strcmp(arg, "-exported_symbols_list") == 0 ) {
2619 snapshotFileArgIndex = 1;
2620 if ( fExportMode == kDontExportSome )
2621 throw "can't use -exported_symbols_list and -unexported_symbols_list";
2622 fExportMode = kExportSome;
2623 loadExportFile(argv[++i], "-exported_symbols_list", fExportSymbols);
2624 }
2625 else if ( strcmp(arg, "-unexported_symbols_list") == 0 ) {
2626 snapshotFileArgIndex = 1;
2627 if ( fExportMode == kExportSome )
2628 throw "can't use -unexported_symbols_list and -exported_symbols_list";
2629 fExportMode = kDontExportSome;
2630 loadExportFile(argv[++i], "-unexported_symbols_list", fDontExportSymbols);
2631 }
2632 else if ( strcmp(arg, "-exported_symbol") == 0 ) {
2633 if ( fExportMode == kDontExportSome )
2634 throw "can't use -exported_symbol and -unexported_symbols";
2635 fExportMode = kExportSome;
2636 fExportSymbols.insert(argv[++i]);
2637 }
2638 else if ( strcmp(arg, "-unexported_symbol") == 0 ) {
2639 if ( fExportMode == kExportSome )
2640 throw "can't use -unexported_symbol and -exported_symbol";
2641 fExportMode = kDontExportSome;
2642 fDontExportSymbols.insert(argv[++i]);
2643 }
2644 else if ( strcmp(arg, "-non_global_symbols_no_strip_list") == 0 ) {
2645 snapshotFileArgIndex = 1;
2646 if ( fLocalSymbolHandling == kLocalSymbolsSelectiveExclude )
2647 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2648 fLocalSymbolHandling = kLocalSymbolsSelectiveInclude;
2649 loadExportFile(argv[++i], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded);
2650 cannotBeUsedWithBitcode(arg);
2651 }
2652 else if ( strcmp(arg, "-non_global_symbols_strip_list") == 0 ) {
2653 snapshotFileArgIndex = 1;
2654 if ( fLocalSymbolHandling == kLocalSymbolsSelectiveInclude )
2655 throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
2656 fLocalSymbolHandling = kLocalSymbolsSelectiveExclude;
2657 loadExportFile(argv[++i], "-non_global_symbols_strip_list", fLocalSymbolsExcluded);
2658 cannotBeUsedWithBitcode(arg);
2659 }
2660 // ??? Deprecate
2661 else if ( strcmp(arg, "-no_arch_warnings") == 0 ) {
2662 fIgnoreOtherArchFiles = true;
2663 }
2664 else if ( strcmp(arg, "-force_cpusubtype_ALL") == 0 ) {
2665 fForceSubtypeAll = true;
2666 fAllowCpuSubtypeMismatches = true;
2667 cannotBeUsedWithBitcode(arg);
2668 }
2669 // Similar to -weak-l but uses the absolute path name to the library.
2670 else if ( strcmp(arg, "-weak_library") == 0 ) {
2671 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2672 snapshotArgCount = 0;
2673 FileInfo info = findFile(argv[++i]);
2674 info.options.fWeakImport = true;
2675 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2676 addLibrary(info);
2677 cannotBeUsedWithBitcode(arg);
2678 }
2679 else if ( strcmp(arg, "-lazy_library") == 0 ) {
2680 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2681 snapshotArgCount = 0;
2682 FileInfo info = findFile(argv[++i]);
2683 info.options.fLazyLoad = true;
2684 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2685 addLibrary(info);
2686 fUsingLazyDylibLinking = true;
2687 cannotBeUsedWithBitcode(arg);
2688 }
2689 else if ( strcmp(arg, "-framework") == 0 ) {
2690 snapshotArgCount = 0;
2691 FileInfo info = findFramework(argv[++i]);
2692 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2693 addLibrary(info);
2694 }
2695 else if ( strcmp(arg, "-weak_framework") == 0 ) {
2696 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2697 snapshotArgCount = 0;
2698 FileInfo info = findFramework(argv[++i]);
2699 info.options.fWeakImport = true;
2700 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2701 addLibrary(info);
2702 }
2703 else if ( strcmp(arg, "-lazy_framework") == 0 ) {
2704 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
2705 snapshotArgCount = 0;
2706 FileInfo info = findFramework(argv[++i]);
2707 info.options.fLazyLoad = true;
2708 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2709 addLibrary(info);
2710 fUsingLazyDylibLinking = true;
2711 cannotBeUsedWithBitcode(arg);
2712 }
2713 else if ( strcmp(arg, "-search_paths_first") == 0 ) {
2714 // previously handled by buildSearchPaths()
2715 }
2716 else if ( strcmp(arg, "-search_dylibs_first") == 0 ) {
2717 // previously handled by buildSearchPaths()
2718 }
2719 else if ( strcmp(arg, "-undefined") == 0 ) {
2720 setUndefinedTreatment(argv[++i]);
2721 cannotBeUsedWithBitcode(arg);
2722 }
2723 // Debugging output flag.
2724 else if ( strcmp(arg, "-arch_multiple") == 0 ) {
2725 fMessagesPrefixedWithArchitecture = true;
2726 }
2727 // Specify what to do with relocations in read only
2728 // sections like .text. Could be errors, warnings,
2729 // or suppressed. Currently we do nothing with the
2730 // flag.
2731 else if ( strcmp(arg, "-read_only_relocs") == 0 ) {
2732 switch ( parseTreatment(argv[++i]) ) {
2733 case kNULL:
2734 case kInvalid:
2735 throw "-read_only_relocs missing [ warning | error | suppress ]";
2736 case kWarning:
2737 fWarnTextRelocs = true;
2738 fAllowTextRelocs = true;
2739 cannotBeUsedWithBitcode(arg);
2740 break;
2741 case kSuppress:
2742 fWarnTextRelocs = false;
2743 fAllowTextRelocs = true;
2744 cannotBeUsedWithBitcode(arg);
2745 break;
2746 case kError:
2747 fWarnTextRelocs = false;
2748 fAllowTextRelocs = false;
2749 break;
2750 }
2751 }
2752 else if ( strcmp(arg, "-sect_diff_relocs") == 0 ) {
2753 warnObsolete(arg);
2754 ++i;
2755 }
2756 // Warn, error or make strong a mismatch between weak
2757 // and non-weak references.
2758 else if ( strcmp(arg, "-weak_reference_mismatches") == 0 ) {
2759 setWeakReferenceMismatchTreatment(argv[++i]);
2760 }
2761 // For a deployment target of 10.3 and earlier ld64 will
2762 // prebind an executable with 0s in all addresses that
2763 // are prebound. This can then be fixed up by update_prebinding
2764 // later. Prebinding is less useful on 10.4 and greater.
2765 else if ( strcmp(arg, "-prebind") == 0 ) {
2766 fPrebind = true;
2767 cannotBeUsedWithBitcode(arg);
2768 }
2769 else if ( strcmp(arg, "-noprebind") == 0 ) {
2770 warnObsolete(arg);
2771 fPrebind = false;
2772 }
2773 else if ( strcmp(arg, "-prebind_allow_overlap") == 0 ) {
2774 warnObsolete(arg);
2775 }
2776 else if ( strcmp(arg, "-prebind_all_twolevel_modules") == 0 ) {
2777 warnObsolete(arg);
2778 }
2779 else if ( strcmp(arg, "-noprebind_all_twolevel_modules") == 0 ) {
2780 warnObsolete(arg);
2781 }
2782 else if ( strcmp(arg, "-nofixprebinding") == 0 ) {
2783 warnObsolete(arg);
2784 }
2785 // This should probably be deprecated when we respect -L and -F
2786 // when searching for libraries.
2787 else if ( strcmp(arg, "-dylib_file") == 0 ) {
2788 // ignore for snapshot because a stub dylib will be created in the snapshot
2789 snapshotArgCount = 0;
2790 addDylibOverride(argv[++i]);
2791 cannotBeUsedWithBitcode(arg);
2792 }
2793 // What to expand @executable_path to if found in dependent dylibs
2794 else if ( strcmp(arg, "-executable_path") == 0 ) {
2795 fExecutablePath = argv[++i];
2796 if ( (fExecutablePath == NULL) || (fExecutablePath[0] == '-') )
2797 throw "-executable_path missing <path>";
2798 // if a directory was passed, add / to end
2799 // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
2800 struct stat statBuffer;
2801 if ( stat(fExecutablePath, &statBuffer) == 0 ) {
2802 if ( (statBuffer.st_mode & S_IFMT) == S_IFDIR ) {
2803 char* pathWithSlash = new char[strlen(fExecutablePath)+2];
2804 strcpy(pathWithSlash, fExecutablePath);
2805 strcat(pathWithSlash, "/");
2806 fExecutablePath = pathWithSlash;
2807 }
2808 }
2809 }
2810 // Aligns all segments to the power of 2 boundary specified.
2811 else if ( strcmp(arg, "-segalign") == 0 ) {
2812 const char* size = argv[++i];
2813 if ( size == NULL )
2814 throw "-segalign missing <size>";
2815 fSegmentAlignment = parseAddress(size);
2816 uint8_t alignment = (uint8_t)__builtin_ctz(fSegmentAlignment);
2817 uint32_t p2aligned = (1 << alignment);
2818 if ( p2aligned != fSegmentAlignment ) {
2819 warning("alignment for -segalign %s is not a power of two, using 0x%X", size, p2aligned);
2820 fSegmentAlignment = p2aligned;
2821 }
2822 cannotBeUsedWithBitcode(arg);
2823 }
2824 // Puts a specified segment at a particular address that must
2825 // be a multiple of the segment alignment.
2826 else if ( strcmp(arg, "-segaddr") == 0 ) {
2827 SegmentStart seg;
2828 seg.name = argv[++i];
2829 if ( (seg.name == NULL) || (argv[i+1] == NULL) )
2830 throw "-segaddr missing segName Adddress";
2831 seg.address = parseAddress(argv[++i]);
2832 uint64_t temp = ((seg.address+fSegmentAlignment-1) & (-fSegmentAlignment));
2833 if ( seg.address != temp )
2834 warning("-segaddr %s not %lld byte aligned", seg.name, fSegmentAlignment);
2835 fCustomSegmentAddresses.push_back(seg);
2836 cannotBeUsedWithBitcode(arg);
2837 }
2838 // ??? Deprecate when we deprecate split-seg.
2839 else if ( strcmp(arg, "-segs_read_only_addr") == 0 ) {
2840 fBaseAddress = parseAddress(argv[++i]);
2841 cannotBeUsedWithBitcode(arg);
2842 }
2843 // ??? Deprecate when we deprecate split-seg.
2844 else if ( strcmp(arg, "-segs_read_write_addr") == 0 ) {
2845 fBaseWritableAddress = parseAddress(argv[++i]);
2846 fSplitSegs = true;
2847 cannotBeUsedWithBitcode(arg);
2848 }
2849 // ??? Deprecate when we get rid of basing at build time.
2850 else if ( strcmp(arg, "-seg_addr_table") == 0 ) {
2851 snapshotFileArgIndex = 1;
2852 const char* name = argv[++i];
2853 if ( name == NULL )
2854 throw "-seg_addr_table missing argument";
2855 fSegAddrTablePath = name;
2856 cannotBeUsedWithBitcode(arg);
2857 }
2858 else if ( strcmp(arg, "-seg_addr_table_filename") == 0 ) {
2859 warnObsolete(arg);
2860 ++i;
2861 }
2862 else if ( strcmp(arg, "-segprot") == 0 ) {
2863 SegmentProtect seg;
2864 seg.name = argv[++i];
2865 if ( (seg.name == NULL) || (argv[i+1] == NULL) || (argv[i+2] == NULL) )
2866 throw "-segprot missing segName max-prot init-prot";
2867 seg.max = parseProtection(argv[++i]);
2868 seg.init = parseProtection(argv[++i]);
2869 if ( strcmp(seg.name, "__LINKEDIT") == 0 )
2870 warning("-segprot cannot be used to modify __LINKEDIT protections");
2871 else
2872 fCustomSegmentProtections.push_back(seg);
2873 cannotBeUsedWithBitcode(arg);
2874 }
2875 else if ( strcmp(arg, "-pagezero_size") == 0 ) {
2876 const char* size = argv[++i];
2877 if ( size == NULL )
2878 throw "-pagezero_size missing <size>";
2879 fZeroPageSize = parseAddress(size);
2880 uint64_t temp = fZeroPageSize & (-4096); // page align
2881 if ( (fZeroPageSize != temp) )
2882 warning("-pagezero_size not page aligned, rounding down");
2883 fZeroPageSize = temp;
2884 cannotBeUsedWithBitcode(arg);
2885 }
2886 else if ( strcmp(arg, "-stack_addr") == 0 ) {
2887 const char* address = argv[++i];
2888 if ( address == NULL )
2889 throw "-stack_addr missing <address>";
2890 fStackAddr = parseAddress(address);
2891 cannotBeUsedWithBitcode(arg);
2892 }
2893 else if ( strcmp(arg, "-stack_size") == 0 ) {
2894 const char* size = argv[++i];
2895 if ( size == NULL )
2896 throw "-stack_size missing <address>";
2897 fStackSize = parseAddress(size);
2898 }
2899 else if ( strcmp(arg, "-allow_stack_execute") == 0 ) {
2900 fExecutableStack = true;
2901 cannotBeUsedWithBitcode(arg);
2902 }
2903 else if ( strcmp(arg, "-allow_heap_execute") == 0 ) {
2904 fDisableNonExecutableHeap = true;
2905 cannotBeUsedWithBitcode(arg);
2906 }
2907 else if ( strcmp(arg, "-sectalign") == 0 ) {
2908 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
2909 throw "-sectalign missing <segment> <section> <file-path>";
2910 addSectionAlignment(argv[i+1], argv[i+2], argv[i+3]);
2911 i += 3;
2912 cannotBeUsedWithBitcode(arg);
2913 }
2914 else if ( strcmp(arg, "-sectorder_detail") == 0 ) {
2915 warnObsolete(arg);
2916 }
2917 else if ( strcmp(arg, "-sectobjectsymbols") == 0 ) {
2918 warnObsolete(arg);
2919 i += 2;
2920 }
2921 else if ( strcmp(arg, "-bundle_loader") == 0 ) {
2922 snapshotFileArgIndex = 1;
2923 fBundleLoader = argv[++i];
2924 if ( (fBundleLoader == NULL) || (fBundleLoader[0] == '-') )
2925 throw "-bundle_loader missing <path>";
2926 FileInfo info = findFile(fBundleLoader);
2927 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
2928 info.options.fBundleLoader = true;
2929 fInputFiles.push_back(info);
2930 }
2931 else if ( strcmp(arg, "-private_bundle") == 0 ) {
2932 warnObsolete(arg);
2933 }
2934 else if ( strcmp(arg, "-twolevel_namespace_hints") == 0 ) {
2935 // FIX FIX
2936 }
2937 // Use this flag to set default behavior for deployement targets.
2938 else if ( strcmp(arg, "-macosx_version_min") == 0 ) {
2939 const char* macVers = argv[++i];
2940 if ( macVers == NULL )
2941 throw "-macosx_version_min missing version argument";
2942 const char* envMacVers = getenv("MACOSX_DEPLOYMENT_TARGET");
2943 const char* enviPhoneVers = getenv("IPHONEOS_DEPLOYMENT_TARGET");
2944 if ( (envMacVers != NULL) && (enviPhoneVers != NULL) ) {
2945 // <rdar://problem/13774329> when conflicting deployments set, break tie by looking at syslibroot
2946 warning("both MACOSX_DEPLOYMENT_TARGET and IPHONEOS_DEPLOYMENT_TARGET are set");
2947 if ( !fSDKPaths.empty() ) {
2948 const char* sysrootPath = fSDKPaths.back();
2949 const char* lastSlash = strrchr(sysrootPath, '/');
2950 if ( strstr(lastSlash, "Simulator") != NULL )
2951 setIOSVersionMin(enviPhoneVers);
2952 else
2953 setMacOSXVersionMin(macVers);
2954 }
2955 else {
2956 setMacOSXVersionMin(macVers);
2957 }
2958 }
2959 else {
2960 setMacOSXVersionMin(macVers);
2961 }
2962 }
2963 else if ( (strcmp(arg, "-ios_version_min") == 0) || (strcmp(arg, "-iphoneos_version_min") == 0) ) {
2964 const char* vers = argv[++i];
2965 if ( vers == NULL )
2966 throw "-ios_version_min missing version argument";
2967 setIOSVersionMin(vers);
2968 }
2969 else if ( strcmp(arg, "-ios_simulator_version_min") == 0 ) {
2970 const char* vers = argv[++i];
2971 if ( vers == NULL )
2972 throw "-ios_simulator_version_min missing version argument";
2973 setIOSVersionMin(vers);
2974 fTargetIOSSimulator = true;
2975 }
2976 else if ( strcmp(arg, "-watchos_version_min") == 0 ) {
2977 const char* vers = argv[++i];
2978 if ( vers == NULL )
2979 throw "-watchos_version_min missing version argument";
2980 setWatchOSVersionMin(vers);
2981 }
2982 else if ( strcmp(arg, "-watchos_simulator_version_min") == 0 ) {
2983 const char* vers = argv[++i];
2984 if ( vers == NULL )
2985 throw "-watchos_simulator_version_min missing version argument";
2986 setWatchOSVersionMin(vers);
2987 fTargetIOSSimulator = true;
2988 }
2989 #if SUPPORT_APPLE_TV
2990 else if ( strcmp(arg, "-tvos_version_min") == 0 ) {
2991 const char* vers = argv[++i];
2992 if ( vers == NULL )
2993 throw "-tvos_version_min missing version argument";
2994 setIOSVersionMin(vers);
2995 fPlatform = kPlatform_tvOS;
2996 }
2997 else if ( strcmp(arg, "-tvos_simulator_version_min") == 0 ) {
2998 const char* vers = argv[++i];
2999 if ( vers == NULL )
3000 throw "-tvos_simulator_version_min missing version argument";
3001 setIOSVersionMin(vers);
3002 fPlatform = kPlatform_tvOS;
3003 fTargetIOSSimulator = true;
3004 }
3005 #endif
3006 else if ( strcmp(arg, "-bridgeos_version_min") == 0 ) {
3007 const char* vers = argv[++i];
3008 if ( vers == NULL )
3009 throw "-bridgeos_version_min missing version argument";
3010 setIOSVersionMin(vers);
3011 fPlatform = kPlatform_bridgeOS;
3012 }
3013 else if ( strcmp(arg, "-multiply_defined") == 0 ) {
3014 //warnObsolete(arg);
3015 ++i;
3016 }
3017 else if ( strcmp(arg, "-multiply_defined_unused") == 0 ) {
3018 warnObsolete(arg);
3019 ++i;
3020 }
3021 else if ( strcmp(arg, "-nomultidefs") == 0 ) {
3022 warnObsolete(arg);
3023 }
3024 // Display each file in which the argument symbol appears and whether
3025 // the file defines or references it. This option takes an argument
3026 // as -y<symbol> note that there is no space.
3027 else if ( strncmp(arg, "-y", 2) == 0 ) {
3028 warnObsolete("-y");
3029 }
3030 // Same output as -y, but output <arg> number of undefined symbols only.
3031 else if ( strcmp(arg, "-Y") == 0 ) {
3032 //warnObsolete(arg);
3033 ++i;
3034 }
3035 // This option affects all objects linked into the final result.
3036 else if ( strcmp(arg, "-m") == 0 ) {
3037 warnObsolete(arg);
3038 }
3039 else if ( (strcmp(arg, "-why_load") == 0) || (strcmp(arg, "-whyload") == 0) ) {
3040 fWhyLoad = true;
3041 }
3042 else if ( strcmp(arg, "-why_live") == 0 ) {
3043 const char* name = argv[++i];
3044 if ( name == NULL )
3045 throw "-why_live missing symbol name argument";
3046 fWhyLive.insert(name);
3047 }
3048 else if ( strcmp(arg, "-u") == 0 ) {
3049 const char* name = argv[++i];
3050 if ( name == NULL )
3051 throw "-u missing argument";
3052 fInitialUndefines.push_back(name);
3053 cannotBeUsedWithBitcode(arg);
3054 }
3055 else if ( strcmp(arg, "-U") == 0 ) {
3056 const char* name = argv[++i];
3057 if ( name == NULL )
3058 throw "-U missing argument";
3059 fAllowedUndefined.insert(name);
3060 cannotBeUsedWithBitcode(arg);
3061 }
3062 else if ( strcmp(arg, "-s") == 0 ) {
3063 warnObsolete(arg);
3064 fLocalSymbolHandling = kLocalSymbolsNone;
3065 fDebugInfoStripping = Options::kDebugInfoNone;
3066 }
3067 else if ( strcmp(arg, "-x") == 0 ) {
3068 fLocalSymbolHandling = kLocalSymbolsNone;
3069 }
3070 else if ( strcmp(arg, "-S") == 0 ) {
3071 fDebugInfoStripping = Options::kDebugInfoNone;
3072 }
3073 else if ( strcmp(arg, "-X") == 0 ) {
3074 warnObsolete(arg);
3075 }
3076 else if ( strcmp(arg, "-Si") == 0 ) {
3077 warnObsolete(arg);
3078 fDebugInfoStripping = Options::kDebugInfoFull;
3079 }
3080 else if ( strcmp(arg, "-b") == 0 ) {
3081 warnObsolete(arg);
3082 }
3083 else if ( strcmp(arg, "-Sn") == 0 ) {
3084 warnObsolete(arg);
3085 fDebugInfoStripping = Options::kDebugInfoFull;
3086 }
3087 else if ( strcmp(arg, "-Sp") == 0 ) {
3088 warnObsolete(arg);
3089 }
3090 else if ( strcmp(arg, "-dead_strip") == 0 ) {
3091 fDeadStrip = true;
3092 }
3093 else if ( strcmp(arg, "-no_dead_strip_inits_and_terms") == 0 ) {
3094 fDeadStrip = true;
3095 }
3096 else if ( strcmp(arg, "-w") == 0 ) {
3097 // previously handled by buildSearchPaths()
3098 }
3099 else if ( strcmp(arg, "-fatal_warnings") == 0 ) {
3100 // previously handled by buildSearchPaths()
3101 }
3102 else if ( strcmp(arg, "-arch_errors_fatal") == 0 ) {
3103 fErrorOnOtherArchFiles = true;
3104 }
3105 else if ( strcmp(arg, "-M") == 0 ) {
3106 // FIX FIX
3107 }
3108 else if ( strcmp(arg, "-headerpad") == 0 ) {
3109 const char* size = argv[++i];
3110 if ( size == NULL )
3111 throw "-headerpad missing argument";
3112 fMinimumHeaderPad = parseAddress(size);
3113 cannotBeUsedWithBitcode(arg);
3114 }
3115 else if ( strcmp(arg, "-headerpad_max_install_names") == 0 ) {
3116 // ignore -headerpad_max_install_names when compiling with bitcode
3117 // rdar://problem/20748962
3118 if ( fBundleBitcode )
3119 warning("-headerpad_max_install_names is ignored when used with -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES)");
3120 else
3121 fMaxMinimumHeaderPad = true;
3122 }
3123 else if ( strcmp(arg, "-t") == 0 ) {
3124 fLogAllFiles = true;
3125 }
3126 else if ( strcmp(arg, "-whatsloaded") == 0 ) {
3127 fLogObjectFiles = true;
3128 }
3129 else if ( strcmp(arg, "-A") == 0 ) {
3130 warnObsolete(arg);
3131 ++i;
3132 }
3133 else if ( strcmp(arg, "-umbrella") == 0 ) {
3134 const char* name = argv[++i];
3135 if ( name == NULL )
3136 throw "-umbrella missing argument";
3137 fUmbrellaName = name;
3138 cannotBeUsedWithBitcode(arg);
3139 }
3140 else if ( strcmp(arg, "-allowable_client") == 0 ) {
3141 const char* name = argv[++i];
3142
3143 if ( name == NULL )
3144 throw "-allowable_client missing argument";
3145
3146 fAllowableClients.push_back(name);
3147 cannotBeUsedWithBitcode(arg);
3148 }
3149 else if ( strcmp(arg, "-client_name") == 0 ) {
3150 const char* name = argv[++i];
3151
3152 if ( name == NULL )
3153 throw "-client_name missing argument";
3154
3155 fClientName = name;
3156 cannotBeUsedWithBitcode(arg);
3157 }
3158 else if ( strcmp(arg, "-sub_umbrella") == 0 ) {
3159 const char* name = argv[++i];
3160 if ( name == NULL )
3161 throw "-sub_umbrella missing argument";
3162 fSubUmbellas.push_back(name);
3163 cannotBeUsedWithBitcode(arg);
3164 }
3165 else if ( strcmp(arg, "-sub_library") == 0 ) {
3166 const char* name = argv[++i];
3167 if ( name == NULL )
3168 throw "-sub_library missing argument";
3169 fSubLibraries.push_back(name);
3170 cannotBeUsedWithBitcode(arg);
3171 }
3172 else if ( strcmp(arg, "-init") == 0 ) {
3173 const char* name = argv[++i];
3174 if ( name == NULL )
3175 throw "-init missing argument";
3176 fInitFunctionName = name;
3177 cannotBeUsedWithBitcode(arg);
3178 }
3179 else if ( strcmp(arg, "-dot") == 0 ) {
3180 const char* name = argv[++i];
3181 if ( name == NULL )
3182 throw "-dot missing argument";
3183 fDotOutputFile = name;
3184 cannotBeUsedWithBitcode(arg);
3185 }
3186 else if ( strcmp(arg, "-warn_commons") == 0 ) {
3187 fWarnCommons = true;
3188 }
3189 else if ( strcmp(arg, "-commons") == 0 ) {
3190 fCommonsMode = parseCommonsTreatment(argv[++i]);
3191 }
3192 else if ( strcmp(arg, "-keep_relocs") == 0 ) {
3193 fKeepRelocations = true;
3194 }
3195 else if ( strcmp(arg, "-warn_stabs") == 0 ) {
3196 fWarnStabs = true;
3197 }
3198 else if ( strcmp(arg, "-pause") == 0 ) {
3199 fPause = true;
3200 }
3201 else if ( strcmp(arg, "-print_statistics") == 0 ) {
3202 fStatistics = true;
3203 }
3204 else if ( strcmp(arg, "-d") == 0 ) {
3205 fMakeTentativeDefinitionsReal = true;
3206 }
3207 else if ( strcmp(arg, "-v") == 0 ) {
3208 // previously handled by buildSearchPaths()
3209 }
3210 else if ( strcmp(arg, "-Z") == 0 ) {
3211 // previously handled by buildSearchPaths()
3212 }
3213 else if ( strcmp(arg, "-syslibroot") == 0 ) {
3214 snapshotArgCount = 0;
3215 ++i;
3216 // previously handled by buildSearchPaths()
3217 }
3218 else if ( strcmp(arg, "-bitcode_bundle") == 0 ) {
3219 snapshotArgCount = 0;
3220 // previously handled by buildSearchPaths()
3221 }
3222 else if ( strcmp(arg, "-no_uuid") == 0 ) {
3223 fUUIDMode = kUUIDNone;
3224 cannotBeUsedWithBitcode(arg);
3225 }
3226 else if ( strcmp(arg, "-random_uuid") == 0 ) {
3227 fUUIDMode = kUUIDRandom;
3228 cannotBeUsedWithBitcode(arg);
3229 }
3230 else if ( strcmp(arg, "-dtrace") == 0 ) {
3231 snapshotFileArgIndex = 1;
3232 const char* name = argv[++i];
3233 if ( name == NULL )
3234 throw "-dtrace missing argument";
3235 fDtraceScriptName = name;
3236 cannotBeUsedWithBitcode(arg);
3237 }
3238 else if ( strcmp(arg, "-root_safe") == 0 ) {
3239 fRootSafe = true;
3240 }
3241 else if ( strcmp(arg, "-setuid_safe") == 0 ) {
3242 fSetuidSafe = true;
3243 }
3244 else if ( strcmp(arg, "-alias") == 0 ) {
3245 Options::AliasPair pair;
3246 pair.realName = argv[++i];
3247 if ( pair.realName == NULL )
3248 throw "missing argument to -alias";
3249 pair.alias = argv[++i];
3250 if ( pair.alias == NULL )
3251 throw "missing argument to -alias";
3252 fAliases.push_back(pair);
3253 cannotBeUsedWithBitcode(arg);
3254 }
3255 else if ( strcmp(arg, "-alias_list") == 0 ) {
3256 snapshotFileArgIndex = 1;
3257 parseAliasFile(argv[++i]);
3258 cannotBeUsedWithBitcode(arg);
3259 }
3260 else if ( strcmp(arg, "-save-temps") == 0 ) {
3261 fSaveTempFiles = true;
3262 }
3263 else if ( strcmp(arg, "-bitcode_hide_symbols") == 0 ) {
3264 fHideSymbols = true;
3265 }
3266 else if ( strcmp(arg, "-bitcode_verify") == 0 ) {
3267 fVerifyBitcode = true;
3268 }
3269 else if ( strcmp(arg, "-bitcode_symbol_map") == 0) {
3270 fReverseMapPath = argv[++i];
3271 if ( fReverseMapPath == NULL )
3272 throw "missing argument to -bitcode_symbol_map";
3273 struct stat statbuf;
3274 int ret = ::stat(fReverseMapPath, &statbuf);
3275 if ( ret == 0 && S_ISDIR(statbuf.st_mode)) {
3276 char tempPath[PATH_MAX];
3277 sprintf(tempPath, "%s/XXXXXX", fReverseMapPath);
3278 int tempFile = ::mkstemp(tempPath);
3279 if (tempFile == -1)
3280 throwf("could not write file to symbol map directory: %s", fReverseMapPath);
3281 ::close(tempFile);
3282 fReverseMapTempPath = std::string(tempPath);
3283 fReverseMapUUIDRename = true;
3284 } else
3285 fReverseMapTempPath = std::string(fReverseMapPath);
3286 }
3287 else if ( strcmp(argv[i], "-flto-codegen-only") == 0) {
3288 fLTOCodegenOnly = true;
3289 }
3290 else if ( strcmp(argv[i], "-ignore_auto_link") == 0) {
3291 fIgnoreAutoLink = true;
3292 }
3293 else if ( strcmp(argv[i], "-allow_dead_duplicates") == 0) {
3294 fAllowDeadDups = true;
3295 }
3296 else if ( strcmp(argv[i], "-bitcode_process_mode") == 0 ) {
3297 const char* bitcode_type = argv[++i];
3298 if ( bitcode_type == NULL )
3299 throw "missing argument to -bitcode_process_mode";
3300 else if ( strcmp(bitcode_type, "strip") == 0 )
3301 fBitcodeKind = kBitcodeStrip;
3302 else if ( strcmp(bitcode_type, "marker") == 0 )
3303 fBitcodeKind = kBitcodeMarker;
3304 else if ( strcmp(bitcode_type, "data") == 0 )
3305 fBitcodeKind = kBitcodeAsData;
3306 else if ( strcmp(bitcode_type, "bitcode") == 0 )
3307 fBitcodeKind = kBitcodeProcess;
3308 else
3309 throw "unknown argument to -bitcode_process_mode {strip,marker,data,bitcode}";
3310 }
3311 else if ( strcmp(arg, "-rpath") == 0 ) {
3312 const char* path = argv[++i];
3313 if ( path == NULL )
3314 throw "missing argument to -rpath";
3315 fRPaths.push_back(path);
3316 }
3317 else if ( strcmp(arg, "-read_only_stubs") == 0 ) {
3318 fReadOnlyx86Stubs = true;
3319 }
3320 else if ( strcmp(arg, "-slow_stubs") == 0 ) {
3321 warnObsolete(arg);
3322 }
3323 else if ( strcmp(arg, "-map") == 0 ) {
3324 fMapPath = argv[++i];
3325 if ( fMapPath == NULL )
3326 throw "missing argument to -map";
3327 }
3328 else if ( strcmp(arg, "-pie") == 0 ) {
3329 fPositionIndependentExecutable = true;
3330 fPIEOnCommandLine = true;
3331 }
3332 else if ( strcmp(arg, "-no_pie") == 0 ) {
3333 fDisablePositionIndependentExecutable = true;
3334 cannotBeUsedWithBitcode(arg);
3335 }
3336 else if ( strncmp(arg, "-reexport-l", 11) == 0 ) {
3337 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3338 snapshotArgCount = 0;
3339 FileInfo info = findLibrary(&arg[11], true);
3340 info.options.fReExport = true;
3341 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
3342 addLibrary(info);
3343 cannotBeUsedWithBitcode(arg);
3344 }
3345 else if ( strcmp(arg, "-reexport_library") == 0 ) {
3346 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3347 snapshotArgCount = 0;
3348 FileInfo info = findFile(argv[++i]);
3349 info.options.fReExport = true;
3350 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
3351 addLibrary(info);
3352 cannotBeUsedWithBitcode(arg);
3353 }
3354 else if ( strcmp(arg, "-reexport_framework") == 0 ) {
3355 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3356 snapshotArgCount = 0;
3357 FileInfo info = findFramework(argv[++i]);
3358 info.options.fReExport = true;
3359 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
3360 addLibrary(info);
3361 cannotBeUsedWithBitcode(arg);
3362 }
3363 else if ( strncmp(arg, "-upward-l", 9) == 0 ) {
3364 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3365 snapshotArgCount = 0;
3366 FileInfo info = findLibrary(&arg[9], true);
3367 info.options.fUpward = true;
3368 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
3369 addLibrary(info);
3370 cannotBeUsedWithBitcode(arg);
3371 }
3372 else if ( strcmp(arg, "-upward_library") == 0 ) {
3373 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3374 snapshotArgCount = 0;
3375 FileInfo info = findFile(argv[++i]);
3376 info.options.fUpward = true;
3377 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
3378 addLibrary(info);
3379 cannotBeUsedWithBitcode(arg);
3380 }
3381 else if ( strcmp(arg, "-upward_framework") == 0 ) {
3382 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
3383 snapshotArgCount = 0;
3384 FileInfo info = findFramework(argv[++i]);
3385 info.options.fUpward = true;
3386 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
3387 addLibrary(info);
3388 cannotBeUsedWithBitcode(arg);
3389 }
3390 else if ( strcmp(arg, "-dead_strip_dylibs") == 0 ) {
3391 fDeadStripDylibs = true;
3392 cannotBeUsedWithBitcode(arg);
3393 }
3394 else if ( strcmp(arg, "-no_implicit_dylibs") == 0 ) {
3395 fImplicitlyLinkPublicDylibs = false;
3396 }
3397 else if ( strcmp(arg, "-new_linker") == 0 ) {
3398 // ignore
3399 }
3400 else if ( strcmp(arg, "-no_encryption") == 0 ) {
3401 fEncryptableForceOff = true;
3402 cannotBeUsedWithBitcode(arg);
3403 }
3404 else if ( strcmp(arg, "-encryptable") == 0 ) {
3405 fEncryptableForceOn = true;
3406 cannotBeUsedWithBitcode(arg);
3407 }
3408 else if ( strcmp(arg, "-no_compact_unwind") == 0 ) {
3409 fAddCompactUnwindEncoding = false;
3410 cannotBeUsedWithBitcode(arg);
3411 }
3412 else if ( strcmp(arg, "-mllvm") == 0 ) {
3413 const char* opts = argv[++i];
3414 if ( opts == NULL )
3415 throw "missing argument to -mllvm";
3416 fLLVMOptions.push_back(opts);
3417 cannotBeUsedWithBitcode(arg);
3418 }
3419 else if ( strcmp(arg, "-mcpu") == 0 ) {
3420 const char* cpu = argv[++i];
3421 if ( cpu == NULL )
3422 throw "missing argument to -mcpu";
3423 fLtoCpu = cpu;
3424 cannotBeUsedWithBitcode(arg);
3425 }
3426 else if ( strcmp(arg, "-no_order_inits") == 0 ) {
3427 fAutoOrderInitializers = false;
3428 cannotBeUsedWithBitcode(arg);
3429 }
3430 else if ( strcmp(arg, "-no_order_data") == 0 ) {
3431 fOrderData = false;
3432 cannotBeUsedWithBitcode(arg);
3433 }
3434 else if ( strcmp(arg, "-seg_page_size") == 0 ) {
3435 SegmentSize seg;
3436 seg.name = argv[++i];
3437 if ( (seg.name == NULL) || (argv[i+1] == NULL) )
3438 throw "-seg_page_size missing segName Adddress";
3439 seg.size = parseAddress(argv[++i]);
3440 uint64_t temp = seg.size & (-4096); // page align
3441 if ( (seg.size != temp) )
3442 warning("-seg_page_size %s not 4K aligned, rounding down", seg.name);
3443 fCustomSegmentSizes.push_back(seg);
3444 cannotBeUsedWithBitcode(arg);
3445 }
3446 else if ( strcmp(arg, "-mark_dead_strippable_dylib") == 0 ) {
3447 fMarkDeadStrippableDylib = true;
3448 cannotBeUsedWithBitcode(arg);
3449 }
3450 else if ( strcmp(arg, "-exported_symbols_order") == 0 ) {
3451 snapshotFileArgIndex = 1;
3452 loadSymbolOrderFile(argv[++i], fExportSymbolsOrder);
3453 cannotBeUsedWithBitcode(arg);
3454 }
3455 else if ( strcmp(arg, "-no_compact_linkedit") == 0 ) {
3456 warnObsolete("-no_compact_linkedit");
3457 }
3458 else if ( strcmp(arg, "-no_eh_labels") == 0 ) {
3459 fNoEHLabels = true;
3460 cannotBeUsedWithBitcode(arg);
3461 }
3462 else if ( strcmp(arg, "-warn_compact_unwind") == 0 ) {
3463 fWarnCompactUnwind = true;
3464 }
3465 else if ( strcmp(arg, "-allow_sub_type_mismatches") == 0 ) {
3466 fAllowCpuSubtypeMismatches = true;
3467 cannotBeUsedWithBitcode(arg);
3468 }
3469 else if ( strcmp(arg, "-no_zero_fill_sections") == 0 ) {
3470 fOptimizeZeroFill = false;
3471 cannotBeUsedWithBitcode(arg);
3472 }
3473 else if ( strcmp(arg, "-merge_zero_fill_sections") == 0 ) {
3474 fMergeZeroFill = true;
3475 cannotBeUsedWithBitcode(arg);
3476 }
3477 else if ( strcmp(arg, "-objc_abi_version") == 0 ) {
3478 const char* version = argv[++i];
3479 if ( version == NULL )
3480 throw "-objc_abi_version missing version number";
3481 if ( strcmp(version, "2") == 0 ) {
3482 fObjCABIVersion1Override = false;
3483 fObjCABIVersion2Override = true;
3484 }
3485 else if ( strcmp(version, "1") == 0 ) {
3486 fObjCABIVersion1Override = true;
3487 fObjCABIVersion2Override = false;
3488 }
3489 else
3490 warning("ignoring unrecognized argument (%s) to -objc_abi_version", version);
3491 }
3492 else if ( strcmp(arg, "-warn_weak_exports") == 0 ) {
3493 fWarnWeakExports = true;
3494 }
3495 else if ( strcmp(arg, "-objc_gc_compaction") == 0 ) {
3496 fObjcGcCompaction = true;
3497 cannotBeUsedWithBitcode(arg);
3498 }
3499 else if ( strcmp(arg, "-objc_gc") == 0 ) {
3500 fObjCGc = true;
3501 if ( fObjCGcOnly ) {
3502 warning("-objc_gc overriding -objc_gc_only");
3503 fObjCGcOnly = false;
3504 }
3505 cannotBeUsedWithBitcode(arg);
3506 }
3507 else if ( strcmp(arg, "-objc_gc_only") == 0 ) {
3508 fObjCGcOnly = true;
3509 if ( fObjCGc ) {
3510 warning("-objc_gc_only overriding -objc_gc");
3511 fObjCGc = false;
3512 }
3513 cannotBeUsedWithBitcode(arg);
3514 }
3515 else if ( strcmp(arg, "-demangle") == 0 ) {
3516 fDemangle = true;
3517 }
3518 else if ( strcmp(arg, "-version_load_command") == 0 ) {
3519 fVersionLoadCommandForcedOn = true;
3520 fVersionLoadCommandForcedOff = false;
3521 }
3522 else if ( strcmp(arg, "-no_version_load_command") == 0 ) {
3523 fVersionLoadCommandForcedOff = true;
3524 fVersionLoadCommandForcedOn = false;
3525 cannotBeUsedWithBitcode(arg);
3526 }
3527 else if ( strcmp(arg, "-function_starts") == 0 ) {
3528 fFunctionStartsForcedOn = true;
3529 fFunctionStartsForcedOff = false;
3530 }
3531 else if ( strcmp(arg, "-no_function_starts") == 0 ) {
3532 fFunctionStartsForcedOff = true;
3533 fFunctionStartsForcedOn = false;
3534 cannotBeUsedWithBitcode(arg);
3535 }
3536 else if ( strcmp(arg, "-no_data_in_code_info") == 0 ) {
3537 fDataInCodeInfoLoadCommandForcedOff = true;
3538 fDataInCodeInfoLoadCommandForcedOn = false;
3539 cannotBeUsedWithBitcode(arg);
3540 }
3541 else if ( strcmp(arg, "-data_in_code_info") == 0 ) {
3542 fDataInCodeInfoLoadCommandForcedOn = true;
3543 fDataInCodeInfoLoadCommandForcedOff = false;
3544 }
3545 else if ( strcmp(arg, "-object_path_lto") == 0 ) {
3546 fTempLtoObjectPath = argv[++i];
3547 if ( fTempLtoObjectPath == NULL )
3548 throw "missing argument to -object_path_lto";
3549 }
3550 else if ( strcmp(arg, "-no_objc_category_merging") == 0 ) {
3551 fObjcCategoryMerging = false;
3552 }
3553 else if ( strcmp(arg, "-force_symbols_weak_list") == 0 ) {
3554 snapshotFileArgIndex = 1;
3555 loadExportFile(argv[++i], "-force_symbols_weak_list", fForceWeakSymbols);
3556 cannotBeUsedWithBitcode(arg);
3557 }
3558 else if ( strcmp(arg, "-force_symbols_not_weak_list") == 0 ) {
3559 snapshotFileArgIndex = 1;
3560 loadExportFile(argv[++i], "-force_symbols_not_weak_list", fForceNotWeakSymbols);
3561 cannotBeUsedWithBitcode(arg);
3562 }
3563 else if ( strcmp(arg, "-force_symbol_weak") == 0 ) {
3564 const char* symbol = argv[++i];
3565 if ( symbol == NULL )
3566 throw "-force_symbol_weak missing <symbol>";
3567 fForceWeakSymbols.insert(symbol);
3568 cannotBeUsedWithBitcode(arg);
3569 }
3570 else if ( strcmp(arg, "-force_symbol_not_weak") == 0 ) {
3571 const char* symbol = argv[++i];
3572 if ( symbol == NULL )
3573 throw "-force_symbol_not_weak missing <symbol>";
3574 fForceNotWeakSymbols.insert(symbol);
3575 cannotBeUsedWithBitcode(arg);
3576 }
3577 else if ( strcmp(arg, "-reexported_symbols_list") == 0 ) {
3578 snapshotFileArgIndex = 1;
3579 if ( fExportMode == kExportSome )
3580 throw "can't use -exported_symbols_list and -reexported_symbols_list";
3581 loadExportFile(argv[++i], "-reexported_symbols_list", fReExportSymbols);
3582 }
3583 else if ( strcmp(arg, "-dyld_env") == 0 ) {
3584 const char* envarg = argv[++i];
3585 if ( envarg == NULL )
3586 throw "-dyld_env missing ENV=VALUE";
3587 if ( strchr(envarg, '=') == NULL )
3588 throw "-dyld_env missing ENV=VALUE";
3589 fDyldEnvironExtras.push_back(envarg);
3590 cannotBeUsedWithBitcode(arg);
3591 }
3592 else if ( strcmp(arg, "-page_align_data_atoms") == 0 ) {
3593 fPageAlignDataAtoms = true;
3594 cannotBeUsedWithBitcode(arg);
3595 }
3596 else if (strcmp(arg, "-debug_snapshot") == 0) {
3597 fLinkSnapshot.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG);
3598 fSnapshotRequested = true;
3599 cannotBeUsedWithBitcode(arg);
3600 }
3601 else if (strcmp(arg, "-snapshot_dir") == 0) {
3602 const char* path = argv[++i];
3603 if ( path == NULL )
3604 throw "-snapshot_dir missing path";
3605 fLinkSnapshot.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG);
3606 fLinkSnapshot.setSnapshotPath(path);
3607 fSnapshotRequested = true;
3608 cannotBeUsedWithBitcode(arg);
3609 }
3610 else if ( strcmp(arg, "-new_main") == 0 ) {
3611 fEntryPointLoadCommandForceOn = true;
3612 cannotBeUsedWithBitcode(arg);
3613 }
3614 else if ( strcmp(arg, "-no_new_main") == 0 ) {
3615 fEntryPointLoadCommandForceOff = true;
3616 cannotBeUsedWithBitcode(arg);
3617 }
3618 else if ( strcmp(arg, "-source_version") == 0 ) {
3619 const char* vers = argv[++i];
3620 if ( vers == NULL )
3621 throw "-source_version missing <version>";
3622 fSourceVersion = parseVersionNumber64(vers);
3623 }
3624 else if ( strcmp(arg, "-add_source_version") == 0 ) {
3625 fSourceVersionLoadCommandForceOn = true;
3626 }
3627 else if ( strcmp(arg, "-no_source_version") == 0 ) {
3628 fSourceVersionLoadCommandForceOff = true;
3629 cannotBeUsedWithBitcode(arg);
3630 }
3631 else if ( strcmp(arg, "-sdk_version") == 0 ) {
3632 const char* vers = argv[++i];
3633 if ( vers == NULL )
3634 throw "-sdk_version missing <version>";
3635 fSDKVersion = parseVersionNumber32(vers);
3636 }
3637 else if ( strcmp(arg, "-dependent_dr_info") == 0 ) {
3638 warnObsolete(arg);
3639 }
3640 else if ( strcmp(arg, "-no_dependent_dr_info") == 0 ) {
3641 warnObsolete(arg);
3642 }
3643 else if ( strcmp(arg, "-kexts_use_stubs") == 0 ) {
3644 fKextsUseStubs = true;
3645 cannotBeUsedWithBitcode(arg);
3646 }
3647 else if ( strcmp(argv[i], "-dependency_info") == 0 ) {
3648 snapshotArgCount = 0;
3649 ++i;
3650 // previously handled by buildSearchPaths()
3651 }
3652 else if ( strcmp(arg, "-export_dynamic") == 0 ) {
3653 fExportDynamic = true;
3654 }
3655 else if ( strcmp(arg, "-force_symbols_coalesce_list") == 0 ) {
3656 snapshotFileArgIndex = 1;
3657 loadExportFile(argv[++i], "-force_symbols_coalesce_list", fForceCoalesceSymbols);
3658 }
3659 else if ( strcmp(arg, "-add_linker_option") == 0 ) {
3660 // ex: -add_linker_option '-framework Foundation'
3661 const char* optString = argv[++i];
3662 if ( optString == NULL )
3663 throw "-add_linker_option missing <option>";
3664 // break up into list of tokens at whitespace
3665 std::vector<const char*> opts;
3666 char* buffer = strdup(optString);
3667 char* start = buffer;
3668 for (char* s = buffer; ; ++s) {
3669 if ( isspace(*s) ) {
3670 *s = '\0';
3671 opts.push_back(start);
3672 start = s+1;
3673 }
3674 else if ( *s == '\0' ) {
3675 opts.push_back(start);
3676 break;
3677 }
3678 }
3679 fLinkerOptions.push_back(opts);
3680 cannotBeUsedWithBitcode(arg);
3681 }
3682 else if ( strcmp(arg, "-allow_simulator_linking_to_macosx_dylibs") == 0 ) {
3683 fAllowSimulatorToLinkWithMacOSX = true;
3684 cannotBeUsedWithBitcode(arg);
3685 }
3686 else if ( strcmp(arg, "-keep_dwarf_unwind") == 0 ) {
3687 fKeepDwarfUnwindForcedOn = true;
3688 fKeepDwarfUnwindForcedOff = false;
3689 cannotBeUsedWithBitcode(arg);
3690 }
3691 else if ( strcmp(arg, "-no_keep_dwarf_unwind") == 0 ) {
3692 fKeepDwarfUnwindForcedOn = false;
3693 fKeepDwarfUnwindForcedOff = true;
3694 cannotBeUsedWithBitcode(arg);
3695 }
3696 else if ( strcmp(arg, "-verbose_optimization_hints") == 0 ) {
3697 fVerboseOptimizationHints = true;
3698 }
3699 else if ( strcmp(arg, "-ignore_optimization_hints") == 0 ) {
3700 fIgnoreOptimizationHints = true;
3701 cannotBeUsedWithBitcode(arg);
3702 }
3703 else if ( strcmp(arg, "-no_dtrace_dof") == 0 ) {
3704 fGenerateDtraceDOF = false;
3705 }
3706 else if ( strcmp(arg, "-rename_section") == 0 ) {
3707 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) || (argv[i+4]==NULL) )
3708 throw "-rename_section missing <segment> <section> <segment> <section>";
3709 addSectionRename(argv[i+1], argv[i+2], argv[i+3], argv[i+4]);
3710 i += 4;
3711 cannotBeUsedWithBitcode(arg);
3712 }
3713 else if ( strcmp(arg, "-rename_segment") == 0 ) {
3714 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) )
3715 throw "-rename_segment missing <existing-segment> <new-segment>";
3716 addSegmentRename(argv[i+1], argv[i+2]);
3717 i += 2;
3718 cannotBeUsedWithBitcode(arg);
3719 }
3720 else if ( strcmp(arg, "-move_to_ro_segment") == 0 ) {
3721 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) )
3722 throw "-move_to_ro_segment missing <segment> <symbol-list-file>";
3723 addSymbolMove(argv[i+1], argv[i+2], fSymbolsMovesCode, "-move_to_ro_segment");
3724 i += 2;
3725 cannotBeUsedWithBitcode(arg);
3726 }
3727 else if ( strcmp(arg, "-move_to_rw_segment") == 0 ) {
3728 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) )
3729 throw "-move_to_rw_segment missing <segment> <symbol-list-file>";
3730 addSymbolMove(argv[i+1], argv[i+2], fSymbolsMovesData, "-move_to_rw_segment");
3731 i += 2;
3732 cannotBeUsedWithBitcode(arg);
3733 }
3734 else if ( strcmp(arg, "-trace_symbol_layout") == 0 ) {
3735 fTraceSymbolLayout = true;
3736 }
3737 else if ( strcmp(arg, "-no_branch_islands") == 0 ) {
3738 fAllowBranchIslands = false;
3739 cannotBeUsedWithBitcode(arg);
3740 }
3741 else if ( strcmp(arg, "-segment_order") == 0 ) {
3742 // ex: -segment_order __TEXT:__DATA:__JUNK
3743 const char* optString = argv[++i];
3744 if ( optString == NULL )
3745 throw "-segment_order missing colon separated <segment-list>";
3746 if ( !fSegmentOrder.empty() )
3747 throw "-segment_order used more than once";
3748 // break up into list of tokens at colon
3749 char* buffer = strdup(optString);
3750 char* start = buffer;
3751 for (char* s = buffer; ; ++s) {
3752 if ( *s == ':' ) {
3753 *s = '\0';
3754 fSegmentOrder.push_back(start);
3755 start = s+1;
3756 }
3757 else if ( *s == '\0' ) {
3758 fSegmentOrder.push_back(start);
3759 break;
3760 }
3761 }
3762 cannotBeUsedWithBitcode(arg);
3763 }
3764 else if ( strcmp(arg, "-section_order") == 0 ) {
3765 // ex: -section_order __DATA __data:__const:__nl_pointers
3766 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) )
3767 throw "-section_order missing <segment> <section-list>";
3768 const char* segName = argv[++i];
3769 const char* optString = argv[++i];
3770 if ( sectionOrder(segName) != NULL )
3771 throwf("-section_order %s ... used more than once", segName);
3772 SectionOrderList dummy;
3773 fSectionOrder.push_back(dummy);
3774 SectionOrderList& entry = fSectionOrder.back();
3775 entry.segmentName = segName;
3776 // break up into list of tokens at colon
3777 char* buffer = strdup(optString);
3778 char* start = buffer;
3779 for (char* s = buffer; ; ++s) {
3780 if ( *s == ':' ) {
3781 *s = '\0';
3782 entry.sectionOrder.push_back(start);
3783 start = s+1;
3784 }
3785 else if ( *s == '\0' ) {
3786 entry.sectionOrder.push_back(start);
3787 break;
3788 }
3789 }
3790 cannotBeUsedWithBitcode(arg);
3791 }
3792 else if ( strcmp(arg, "-application_extension") == 0 ) {
3793 fMarkAppExtensionSafe = true;
3794 fCheckAppExtensionSafe = true;
3795 }
3796 else if ( strcmp(arg, "-no_application_extension") == 0 ) {
3797 fMarkAppExtensionSafe = false;
3798 fCheckAppExtensionSafe = false;
3799 }
3800 else if ( strcmp(arg, "-add_ast_path") == 0 ) {
3801 const char* path = argv[++i];
3802 if ( path == NULL )
3803 throw "-add_ast_path missing <option>";
3804 fASTFilePaths.push_back(path);
3805 }
3806 else if ( strcmp(arg, "-force_load_swift_libs") == 0 ) {
3807 fForceLoadSwiftLibs = true;
3808 }
3809 else if ( strcmp(arg, "-not_for_dyld_shared_cache") == 0 ) {
3810 fSharedRegionEligibleForceOff = true;
3811 cannotBeUsedWithBitcode(arg);
3812 }
3813 else if ( strcmp(arg, "-dirty_data_list") == 0 ) {
3814 if ( argv[i+1] == NULL )
3815 throw "-dirty_data_list missing <symbol-list-file>";
3816 addSymbolMove("__DATA_DIRTY", argv[i+1], fSymbolsMovesData, "-dirty_data_list");
3817 ++i;
3818 cannotBeUsedWithBitcode(arg);
3819 }
3820 else if ( strcmp(arg, "-data_const") == 0 ) {
3821 fUseDataConstSegmentForceOn = true;
3822 cannotBeUsedWithBitcode(arg);
3823 }
3824 else if ( strcmp(arg, "-no_data_const") == 0 ) {
3825 fUseDataConstSegmentForceOff = true;
3826 cannotBeUsedWithBitcode(arg);
3827 }
3828 else if ( strcmp(arg, "-text_exec") == 0 ) {
3829 fUseTextExecSegment = true;
3830 cannotBeUsedWithBitcode(arg);
3831 }
3832 else if ( strcmp(arg, "-add_split_seg_info") == 0) {
3833 fSharedRegionEligible = true;
3834 cannotBeUsedWithBitcode(arg);
3835 }
3836 else if ( strcmp(arg, "-no_deduplicate") == 0 ) {
3837 fDeDupe = false;
3838 }
3839 else if ( strcmp(arg, "-verbose_deduplicate") == 0 ) {
3840 fVerboseDeDupe = true;
3841 }
3842 else if ( strcmp(arg, "-max_default_common_align") == 0 ) {
3843 const char* alignStr = argv[++i];
3844 if ( alignStr == NULL )
3845 throw "-max_default_common_align missing <align-value>";
3846 // argument is a hexadecimal number
3847 char* endptr;
3848 unsigned long value = strtoul(alignStr, &endptr, 16);
3849 if ( *endptr != '\0')
3850 throw "argument for -max_default_common_align is not a hexadecimal number";
3851 if ( value > 0x8000 )
3852 throw "argument for -max_default_common_align must be less than or equal to 0x8000";
3853 if ( value == 0 ) {
3854 warning("zero is not a valid -max_default_common_align");
3855 value = 1;
3856 }
3857 // alignment is power of 2
3858 uint8_t alignment = (uint8_t)__builtin_ctz(value);
3859 if ( (unsigned long)(1 << alignment) != value ) {
3860 warning("alignment for -max_default_common_align is not a power of two, using 0x%X", 1 << alignment);
3861 }
3862 fMaxDefaultCommonAlign = alignment;
3863 }
3864 else if ( strcmp(argv[i], "-no_weak_imports") == 0 ) {
3865 fAllowWeakImports = false;
3866 }
3867 else if ( strcmp(argv[i], "-no_inits") == 0 ) {
3868 fNoInitializers = true;
3869 }
3870 // put this last so that it does not interfer with other options starting with 'i'
3871 else if ( strncmp(arg, "-i", 2) == 0 ) {
3872 const char* colon = strchr(arg, ':');
3873 if ( colon == NULL )
3874 throwf("unknown option: %s", arg);
3875 Options::AliasPair pair;
3876 char* temp = new char[colon-arg];
3877 strlcpy(temp, &arg[2], colon-arg-1);
3878 pair.realName = &colon[1];
3879 pair.alias = temp;
3880 fAliases.push_back(pair);
3881 }
3882 else {
3883 throwf("unknown option: %s", arg);
3884 }
3885
3886 if (snapshotArgCount == -1)
3887 snapshotArgCount = i-snapshotArgIndex+1;
3888 if (snapshotArgCount > 0)
3889 fLinkSnapshot.addSnapshotLinkArg(snapshotArgIndex, snapshotArgCount, snapshotFileArgIndex);
3890 }
3891 else {
3892 FileInfo info = findFile(arg);
3893 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
3894 if ( strcmp(&info.path[strlen(info.path)-2], ".a") == 0 )
3895 addLibrary(info);
3896 else
3897 fInputFiles.push_back(info);
3898 }
3899 }
3900
3901 // if a -lazy option was used, implicitly link in lazydylib1.o
3902 if ( fUsingLazyDylibLinking ) {
3903 FileInfo info = findLibrary("lazydylib1.o");
3904 info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)argc);
3905 addLibrary(info);
3906 }
3907
3908 if (fSnapshotRequested)
3909 fLinkSnapshot.createSnapshot();
3910 }
3911
3912
3913
3914 //
3915 // -syslibroot <path> is used for SDK support.
3916 // The rule is that all search paths (both explicit and default) are
3917 // checked to see if they exist in the SDK. If so, that path is
3918 // replaced with the sdk prefixed path. If not, that search path
3919 // is used as is. If multiple -syslibroot options are specified
3920 // their directory structures are logically overlayed and files
3921 // from sdks specified earlier on the command line used before later ones.
3922
3923 void Options::buildSearchPaths(int argc, const char* argv[])
3924 {
3925 bool addStandardLibraryDirectories = true;
3926 std::vector<const char*> libraryPaths;
3927 std::vector<const char*> frameworkPaths;
3928 libraryPaths.reserve(10);
3929 frameworkPaths.reserve(10);
3930 // scan through argv looking for -L, -F, -Z, and -syslibroot options
3931 for(int i=0; i < argc; ++i) {
3932 if ( (argv[i][0] == '-') && (argv[i][1] == 'L') ) {
3933 const char* libSearchDir = &argv[i][2];
3934 // Allow either "-L{path}" or "-L {path}".
3935 if (argv[i][2] == '\0') {
3936 // -L {path}. Make sure there is an argument following this.
3937 const char* path = argv[++i];
3938 if ( path == NULL )
3939 throw "-L missing argument";
3940 libSearchDir = path;
3941 }
3942 if ( libSearchDir[0] == '\0' )
3943 throw "-L must be immediately followed by a directory path (no space)";
3944 libraryPaths.push_back(libSearchDir);
3945 }
3946 else if ( (argv[i][0] == '-') && (argv[i][1] == 'F') ) {
3947 const char* frameworkSearchDir = &argv[i][2];
3948 // Allow either "-F{path}" or "-F {path}".
3949 if (argv[i][2] == '\0') {
3950 // -F {path}. Make sure there is an argument following this.
3951 const char* path = argv[++i];
3952 if ( path == NULL )
3953 throw "-F missing argument";
3954 frameworkSearchDir = path;
3955 }
3956 if ( frameworkSearchDir[0] == '\0' )
3957 throw "-F must be immediately followed by a directory path (no space)";
3958 frameworkPaths.push_back(frameworkSearchDir);
3959 }
3960 else if ( strcmp(argv[i], "-Z") == 0 )
3961 addStandardLibraryDirectories = false;
3962 else if ( strcmp(argv[i], "-v") == 0 ) {
3963 fVerbose = true;
3964 extern const char ldVersionString[];
3965 fprintf(stderr, "%s", ldVersionString);
3966 fprintf(stderr, "configured to support archs: %s\n", ALL_SUPPORTED_ARCHS);
3967 // if only -v specified, exit cleanly
3968 if ( argc == 2 ) {
3969 const char* ltoVers = lto::version();
3970 if ( ltoVers != NULL )
3971 fprintf(stderr, "LTO support using: %s (static support for %d, runtime is %d)\n",
3972 ltoVers, lto::static_api_version(), lto::runtime_api_version());
3973 fprintf(stderr, "TAPI support using: %s\n", tapi::Version::getFullVersionAsString().c_str());
3974 exit(0);
3975 }
3976 }
3977 else if ( strcmp(argv[i], "-syslibroot") == 0 ) {
3978 const char* path = argv[++i];
3979 if ( path == NULL )
3980 throw "-syslibroot missing argument";
3981 fSDKPaths.push_back(path);
3982 }
3983 else if ( strcmp(argv[i], "-search_paths_first") == 0 ) {
3984 fLibrarySearchMode = kSearchDylibAndArchiveInEachDir;
3985 }
3986 else if ( strcmp(argv[i], "-search_dylibs_first") == 0 ) {
3987 fLibrarySearchMode = kSearchAllDirsForDylibsThenAllDirsForArchives;
3988 }
3989 else if ( strcmp(argv[i], "-w") == 0 ) {
3990 sEmitWarnings = false;
3991 }
3992 else if ( strcmp(argv[i], "-fatal_warnings") == 0 ) {
3993 sFatalWarnings = true;
3994 }
3995 else if ( strcmp(argv[i], "-dependency_info") == 0 ) {
3996 const char* path = argv[++i];
3997 if ( path == NULL )
3998 throw "-dependency_info missing <path>";
3999 fDependencyInfoPath = path;
4000 }
4001 else if ( strcmp(argv[i], "-bitcode_bundle") == 0 ) {
4002 fBundleBitcode = true;
4003 }
4004 }
4005 int standardLibraryPathsStartIndex = libraryPaths.size();
4006 int standardFrameworkPathsStartIndex = frameworkPaths.size();
4007 if ( addStandardLibraryDirectories ) {
4008 libraryPaths.push_back("/usr/lib");
4009 libraryPaths.push_back("/usr/local/lib");
4010
4011 frameworkPaths.push_back("/Library/Frameworks/");
4012 frameworkPaths.push_back("/System/Library/Frameworks/");
4013 // <rdar://problem/5433882> remove /Network/Library/Frameworks from default search path
4014 }
4015
4016 // <rdar://problem/5829579> Support for configure based hacks
4017 // if last -syslibroot is /, then ignore all syslibroots
4018 if ( fSDKPaths.size() > 0 ) {
4019 if ( strcmp(fSDKPaths.back(), "/") == 0 ) {
4020 fSDKPaths.clear();
4021 }
4022 }
4023
4024 // now merge sdk and library paths to make real search paths
4025 fLibrarySearchPaths.reserve(libraryPaths.size()*(fSDKPaths.size()+1));
4026 int libIndex = 0;
4027 for (std::vector<const char*>::iterator it = libraryPaths.begin(); it != libraryPaths.end(); ++it, ++libIndex) {
4028 const char* libDir = *it;
4029 bool sdkOverride = false;
4030 if ( libDir[0] == '/' ) {
4031 char betterLibDir[PATH_MAX];
4032 if ( strstr(libDir, "/..") != NULL ) {
4033 if ( realpath(libDir, betterLibDir) != NULL )
4034 libDir = strdup(betterLibDir);
4035 }
4036 const int libDirLen = strlen(libDir);
4037 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
4038 const char* sdkDir = *sdkit;
4039 const int sdkDirLen = strlen(sdkDir);
4040 char newPath[libDirLen + sdkDirLen+4];
4041 strcpy(newPath, sdkDir);
4042 if ( newPath[sdkDirLen-1] == '/' )
4043 newPath[sdkDirLen-1] = '\0';
4044 strcat(newPath, libDir);
4045 struct stat statBuffer;
4046 if ( stat(newPath, &statBuffer) == 0 ) {
4047 if ( (statBuffer.st_mode & S_IFDIR) == 0 ) {
4048 warning("-syslibroot and -L combined path '%s' is not a directory", newPath);
4049 }
4050 else {
4051 fLibrarySearchPaths.push_back(strdup(newPath));
4052 sdkOverride = true;
4053 }
4054 }
4055 }
4056 }
4057 if ( !sdkOverride ) {
4058 if ( (libIndex >= standardLibraryPathsStartIndex) && (fSDKPaths.size() == 1) ) {
4059 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
4060 // if one SDK is specified and a standard library path is not in the SDK, don't use it
4061 }
4062 else {
4063 struct stat statBuffer;
4064 if ( stat(libDir, &statBuffer) == 0 ) {
4065 if ( (statBuffer.st_mode & S_IFDIR) == 0 )
4066 warning("-L path '%s' is not a directory", libDir);
4067 else
4068 fLibrarySearchPaths.push_back(libDir);
4069 }
4070 else if ( !addStandardLibraryDirectories || (strcmp(libDir, "/usr/local/lib") != 0) ) {
4071 warning("directory not found for option '-L%s'", libDir);
4072 }
4073 }
4074 }
4075 }
4076
4077
4078 // now merge sdk and framework paths to make real search paths
4079 fFrameworkSearchPaths.reserve(frameworkPaths.size()*(fSDKPaths.size()+1));
4080 int frameIndex = 0;
4081 for (std::vector<const char*>::iterator it = frameworkPaths.begin(); it != frameworkPaths.end(); ++it, ++frameIndex) {
4082 const char* frameworkDir = *it;
4083 bool sdkOverride = false;
4084 if ( frameworkDir[0] == '/' ) {
4085 char betterFrameworkDir[PATH_MAX];
4086 if ( strstr(frameworkDir, "/..") != NULL ) {
4087 if ( realpath(frameworkDir, betterFrameworkDir) != NULL )
4088 frameworkDir = strdup(betterFrameworkDir);
4089 }
4090 const int frameworkDirLen = strlen(frameworkDir);
4091 for (std::vector<const char*>::iterator sdkit = fSDKPaths.begin(); sdkit != fSDKPaths.end(); sdkit++) {
4092 const char* sdkDir = *sdkit;
4093 const int sdkDirLen = strlen(sdkDir);
4094 char newPath[frameworkDirLen + sdkDirLen+4];
4095 strcpy(newPath, sdkDir);
4096 if ( newPath[sdkDirLen-1] == '/' )
4097 newPath[sdkDirLen-1] = '\0';
4098 strcat(newPath, frameworkDir);
4099 struct stat statBuffer;
4100 if ( stat(newPath, &statBuffer) == 0 ) {
4101 if ( (statBuffer.st_mode & S_IFDIR) == 0 ) {
4102 warning("-syslibroot and -F combined path '%s' is not a directory", newPath);
4103 }
4104 else {
4105 fFrameworkSearchPaths.push_back(strdup(newPath));
4106 sdkOverride = true;
4107 }
4108 }
4109 }
4110 }
4111 if ( !sdkOverride ) {
4112 if ( (frameIndex >= standardFrameworkPathsStartIndex) && (fSDKPaths.size() == 1) ) {
4113 // <rdar://problem/6438270> -syslibroot should skip standard search paths not in the SDK
4114 // if one SDK is specified and a standard library path is not in the SDK, don't use it
4115 }
4116 else {
4117 struct stat statBuffer;
4118 if ( stat(frameworkDir, &statBuffer) == 0 ) {
4119 if ( (statBuffer.st_mode & S_IFDIR) == 0 )
4120 warning("-F path '%s' is not a directory", frameworkDir);
4121 else
4122 fFrameworkSearchPaths.push_back(frameworkDir);
4123 }
4124 else if ( !addStandardLibraryDirectories || (strcmp(frameworkDir, "/Library/Frameworks/") != 0) ) {
4125 warning("directory not found for option '-F%s'", frameworkDir);
4126 }
4127 }
4128 }
4129 }
4130
4131 if ( fVerbose ) {
4132 fprintf(stderr,"Library search paths:\n");
4133 for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
4134 it != fLibrarySearchPaths.end();
4135 it++)
4136 fprintf(stderr,"\t%s\n", *it);
4137 fprintf(stderr,"Framework search paths:\n");
4138 for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin();
4139 it != fFrameworkSearchPaths.end();
4140 it++)
4141 fprintf(stderr,"\t%s\n", *it);
4142 }
4143 }
4144
4145 // this is run before the command line is parsed
4146 void Options::parsePreCommandLineEnvironmentSettings()
4147 {
4148 if ((getenv("LD_TRACE_ARCHIVES") != NULL)
4149 || (getenv("RC_TRACE_ARCHIVES") != NULL))
4150 fTraceArchives = true;
4151
4152 if ((getenv("LD_TRACE_DYLIBS") != NULL)
4153 || (getenv("RC_TRACE_DYLIBS") != NULL)) {
4154 fTraceDylibs = true;
4155 fTraceIndirectDylibs = true;
4156 }
4157
4158 if ((getenv("LD_TRACE_DEPENDENTS") != NULL)) {
4159
4160 fTraceEmitJSON = true;
4161 }
4162
4163 if (getenv("RC_TRACE_DYLIB_SEARCHING") != NULL) {
4164 fTraceDylibSearching = true;
4165 }
4166
4167 if (getenv("LD_PRINT_OPTIONS") != NULL)
4168 fPrintOptions = true;
4169
4170 if (fTraceDylibs || fTraceArchives || fTraceEmitJSON)
4171 fTraceOutputFile = getenv("LD_TRACE_FILE");
4172
4173 if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL)
4174 fPrintOrderFileStatistics = true;
4175
4176 if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL)
4177 fSplitSegs = true;
4178
4179 if (getenv("LD_NO_ENCRYPT") != NULL) {
4180 fEncryptable = false;
4181 fMarkAppExtensionSafe = true; // temporary
4182 fCheckAppExtensionSafe = false;
4183 }
4184
4185 if (getenv("LD_APPLICATION_EXTENSION_SAFE") != NULL) {
4186 fMarkAppExtensionSafe = true;
4187 fCheckAppExtensionSafe = false;
4188 }
4189
4190 if (getenv("LD_ALLOW_CPU_SUBTYPE_MISMATCHES") != NULL)
4191 fAllowCpuSubtypeMismatches = true;
4192
4193 if (getenv("LD_DYLIB_CPU_SUBTYPES_MUST_MATCH") != NULL)
4194 fEnforceDylibSubtypesMatch = true;
4195
4196 sWarningsSideFilePath = getenv("LD_WARN_FILE");
4197
4198 const char* customDyldPath = getenv("LD_DYLD_PATH");
4199 if ( customDyldPath != NULL )
4200 fDyldInstallPath = customDyldPath;
4201
4202 const char* debugArchivePath = getenv("LD_DEBUG_SNAPSHOT");
4203 if (debugArchivePath != NULL) {
4204 fLinkSnapshot.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG);
4205 if (strlen(debugArchivePath) > 0)
4206 fLinkSnapshot.setSnapshotPath(debugArchivePath);
4207 fSnapshotRequested = true;
4208 }
4209
4210 const char* pipeFdString = getenv("LD_PIPELINE_FIFO");
4211 if (pipeFdString != NULL) {
4212 fPipelineFifo = pipeFdString;
4213 }
4214 }
4215
4216
4217 // this is run after the command line is parsed
4218 void Options::parsePostCommandLineEnvironmentSettings()
4219 {
4220 // when building a dynamic main executable, default any use of @executable_path to output path
4221 if ( fExecutablePath == NULL && (fOutputKind == kDynamicExecutable) ) {
4222 fExecutablePath = fOutputFile;
4223 }
4224
4225 // allow build system to set default seg_addr_table
4226 if ( fSegAddrTablePath == NULL )
4227 fSegAddrTablePath = getenv("LD_SEG_ADDR_TABLE");
4228
4229 // allow build system to turn on prebinding
4230 if ( !fPrebind ) {
4231 fPrebind = ( getenv("LD_PREBIND") != NULL );
4232 }
4233
4234 // allow build system to force on dead-code-stripping
4235 if ( !fDeadStrip ) {
4236 if ( getenv("LD_DEAD_STRIP") != NULL ) {
4237 switch (fOutputKind) {
4238 case Options::kDynamicLibrary:
4239 case Options::kDynamicExecutable:
4240 case Options::kDynamicBundle:
4241 fDeadStrip = true;
4242 break;
4243 case Options::kPreload:
4244 case Options::kObjectFile:
4245 case Options::kDyld:
4246 case Options::kStaticExecutable:
4247 case Options::kKextBundle:
4248 break;
4249 }
4250 }
4251 }
4252
4253 // allow build system to force on -warn_commons
4254 if ( getenv("LD_WARN_COMMONS") != NULL )
4255 fWarnCommons = true;
4256
4257 // allow B&I to set default -source_version
4258 if ( fSourceVersion == 0 ) {
4259 const char* vers = getenv("RC_ProjectSourceVersion");
4260 if ( vers != NULL )
4261 fSourceVersion = parseVersionNumber64(vers);
4262 }
4263
4264 }
4265
4266
4267 static bool sharedCacheEligiblePath(const char* path)
4268 {
4269 return ( (strncmp(path, "/usr/lib/", 9) == 0) || (strncmp(path, "/System/Library/", 16) == 0) );
4270 }
4271
4272 void Options::reconfigureDefaults()
4273 {
4274 // sync reader options
4275 switch ( fOutputKind ) {
4276 case Options::kObjectFile:
4277 fForFinalLinkedImage = false;
4278 break;
4279 case Options::kDyld:
4280 fForDyld = true;
4281 fForFinalLinkedImage = true;
4282 fNoEHLabels = true;
4283 break;
4284 case Options::kDynamicLibrary:
4285 case Options::kDynamicBundle:
4286 case Options::kKextBundle:
4287 fForFinalLinkedImage = true;
4288 fNoEHLabels = true;
4289 break;
4290 case Options::kDynamicExecutable:
4291 case Options::kStaticExecutable:
4292 case Options::kPreload:
4293 fLinkingMainExecutable = true;
4294 fForFinalLinkedImage = true;
4295 fNoEHLabels = true;
4296 break;
4297 }
4298
4299 // set default min OS version
4300 if ( (fMacVersionMin == ld::macVersionUnset) && (fIOSVersionMin == ld::iOSVersionUnset) && (fWatchOSVersionMin == ld::wOSVersionUnset) ) {
4301 // if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
4302 const char* macVers = getenv("MACOSX_DEPLOYMENT_TARGET");
4303 const char* iPhoneVers = getenv("IPHONEOS_DEPLOYMENT_TARGET");
4304 const char* iOSVers = getenv("IOS_DEPLOYMENT_TARGET");
4305 const char* wOSVers = getenv("WATCHOS_DEPLOYMENT_TARGET");
4306 if ( macVers != NULL )
4307 setMacOSXVersionMin(macVers);
4308 else if ( iPhoneVers != NULL )
4309 setIOSVersionMin(iPhoneVers);
4310 else if ( iOSVers != NULL )
4311 setIOSVersionMin(iOSVers);
4312 else if ( wOSVers != NULL )
4313 setWatchOSVersionMin(wOSVers);
4314 else {
4315 // if still nothing, set default based on architecture
4316 switch ( fArchitecture ) {
4317 case CPU_TYPE_I386:
4318 case CPU_TYPE_X86_64:
4319 if ( (fOutputKind != Options::kObjectFile) && (fOutputKind != Options::kPreload) ) {
4320 #ifdef DEFAULT_MACOSX_MIN_VERSION
4321 warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION);
4322 setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
4323 #else
4324 warning("-macosx_version_min not specified, assuming 10.6");
4325 setMacOSXVersionMin("10.6");
4326 #endif
4327 }
4328 break;
4329 case CPU_TYPE_ARM:
4330 if ( (fOutputKind != Options::kObjectFile) && (fOutputKind != Options::kPreload) ) {
4331 #if defined(DEFAULT_IPHONEOS_MIN_VERSION)
4332 warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION);
4333 setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION);
4334 #else
4335 if ( fSubArchitecture == CPU_SUBTYPE_ARM_V7K ) {
4336 warning("-watchos_version_min not specified, assuming 2.0");
4337 setWatchOSVersionMin("2.0");
4338 }
4339 else {
4340 warning("-ios_version_min not specified, assuming 6.0");
4341 setIOSVersionMin("6.0");
4342 }
4343 #endif
4344 }
4345 break;
4346 default:
4347 // architecture will be infered later by examining .o files
4348 break;
4349 }
4350 }
4351 }
4352
4353
4354 // adjust min based on architecture
4355 switch ( fArchitecture ) {
4356 case CPU_TYPE_I386:
4357 if ( (fPlatform == kPlatformOSX) && (fMacVersionMin < ld::mac10_4) ) {
4358 //warning("-macosx_version_min should be 10.4 or later for i386");
4359 fMacVersionMin = ld::mac10_4;
4360 }
4361 break;
4362 case CPU_TYPE_X86_64:
4363 if ( (fPlatform == kPlatformOSX) && (fMacVersionMin < ld::mac10_4) ) {
4364 //warning("-macosx_version_min should be 10.4 or later for x86_64");
4365 fMacVersionMin = ld::mac10_4;
4366 }
4367 break;
4368 case CPU_TYPE_ARM64:
4369 if ( (fPlatform == kPlatformiOS) && (fIOSVersionMin < ld::iOS_7_0) ) {
4370 //warning("-mios_version_min should be 7.0 or later for arm64");
4371 fIOSVersionMin = ld::iOS_7_0;
4372 }
4373 break;
4374 }
4375
4376 // default to adding functions start for dynamic code, static code must opt-in
4377 switch ( fOutputKind ) {
4378 case Options::kPreload:
4379 case Options::kStaticExecutable:
4380 case Options::kKextBundle:
4381 if ( fDataInCodeInfoLoadCommandForcedOn )
4382 fDataInCodeInfoLoadCommand = true;
4383 if ( fFunctionStartsForcedOn )
4384 fFunctionStartsLoadCommand = true;
4385 break;
4386 case Options::kObjectFile:
4387 if ( !fDataInCodeInfoLoadCommandForcedOff )
4388 fDataInCodeInfoLoadCommand = true;
4389 if ( fFunctionStartsForcedOn )
4390 fFunctionStartsLoadCommand = true;
4391 break;
4392 case Options::kDynamicExecutable:
4393 case Options::kDyld:
4394 case Options::kDynamicLibrary:
4395 case Options::kDynamicBundle:
4396 if ( !fDataInCodeInfoLoadCommandForcedOff )
4397 fDataInCodeInfoLoadCommand = true;
4398 if ( !fFunctionStartsForcedOff )
4399 fFunctionStartsLoadCommand = true;
4400 break;
4401 }
4402
4403 // adjust kext type based on architecture
4404 if ( fOutputKind == kKextBundle ) {
4405 switch ( fArchitecture ) {
4406 case CPU_TYPE_X86_64:
4407 // x86_64 uses new MH_KEXT_BUNDLE type
4408 fMakeCompressedDyldInfo = false;
4409 fMakeCompressedDyldInfoForceOff = true;
4410 fAllowTextRelocs = true;
4411 fUndefinedTreatment = kUndefinedDynamicLookup;
4412 break;
4413 case CPU_TYPE_ARM64:
4414 // arm64 uses new MH_KEXT_BUNDLE type
4415 fMakeCompressedDyldInfo = false;
4416 fMakeCompressedDyldInfoForceOff = true;
4417 fAllowTextRelocs = false;
4418 fKextsUseStubs = true;
4419 fUndefinedTreatment = kUndefinedDynamicLookup;
4420 break;
4421 case CPU_TYPE_ARM:
4422 if ( min_iOS(ld::iOS_5_0) ) {
4423 // iOS 5.0 and later use new MH_KEXT_BUNDLE type
4424 fMakeCompressedDyldInfo = false;
4425 fMakeCompressedDyldInfoForceOff = true;
4426 // kexts are PIC in iOS 6.0 and later
4427 fAllowTextRelocs = !min_iOS(ld::iOS_6_0);
4428 fKextsUseStubs = !fAllowTextRelocs;
4429 fUndefinedTreatment = kUndefinedDynamicLookup;
4430 break;
4431 }
4432 // else use object file
4433 case CPU_TYPE_I386:
4434 // use .o files
4435 fOutputKind = kObjectFile;
4436 break;
4437 }
4438 }
4439
4440 // disable implicit dylibs when targeting 10.3
4441 // <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
4442 if ( !minOS(ld::mac10_4, ld::iOS_2_0) )
4443 fImplicitlyLinkPublicDylibs = false;
4444
4445
4446 // allow build system to force linker to ignore -prebind
4447 if ( getenv("LD_FORCE_NO_PREBIND") != NULL )
4448 fPrebind = false;
4449
4450 // allow build system to force linker to ignore -seg_addr_table
4451 if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL )
4452 fSegAddrTablePath = NULL;
4453
4454 // check for base address specified externally
4455 if ( (fSegAddrTablePath != NULL) && (fOutputKind == Options::kDynamicLibrary) ) {
4456 parseSegAddrTable(fSegAddrTablePath, this->installPath());
4457 // HACK to support seg_addr_table entries that are physical paths instead of install paths
4458 if ( fBaseAddress == 0 ) {
4459 if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
4460 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libstdc++.6.0.4.dylib");
4461 if ( fBaseAddress == 0 )
4462 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libstdc++.6.0.9.dylib");
4463 }
4464
4465 else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
4466 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libz.1.2.3.dylib");
4467
4468 else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
4469 parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libutil1.0.dylib");
4470 }
4471 }
4472
4473 // split segs only allowed for dylibs
4474 if ( fSplitSegs ) {
4475 // split seg only supported for i386, and arm.
4476 switch ( fArchitecture ) {
4477 case CPU_TYPE_I386:
4478 if ( fOutputKind != Options::kDynamicLibrary )
4479 fSplitSegs = false;
4480 // make sure read and write segments are proper distance apart
4481 if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x10000000) )
4482 fBaseWritableAddress = fBaseAddress + 0x10000000;
4483 break;
4484 case CPU_TYPE_ARM:
4485 if ( fOutputKind != Options::kDynamicLibrary ) {
4486 fSplitSegs = false;
4487 }
4488 else {
4489 // make sure read and write segments are proper distance apart
4490 if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x08000000) )
4491 fBaseWritableAddress = fBaseAddress + 0x08000000;
4492 }
4493 break;
4494 default:
4495 fSplitSegs = false;
4496 fBaseAddress = 0;
4497 fBaseWritableAddress = 0;
4498 }
4499 }
4500
4501 // set too-large size
4502 switch ( fArchitecture ) {
4503 case CPU_TYPE_I386:
4504 fMaxAddress = 0xFFFFFFFF;
4505 break;
4506 case CPU_TYPE_X86_64:
4507 break;
4508 case CPU_TYPE_ARM:
4509 switch ( fOutputKind ) {
4510 case Options::kDynamicExecutable:
4511 case Options::kDynamicLibrary:
4512 case Options::kDynamicBundle:
4513 // user land code is limited to low 1GB
4514 fMaxAddress = 0x2FFFFFFF;
4515 break;
4516 case Options::kStaticExecutable:
4517 case Options::kObjectFile:
4518 case Options::kDyld:
4519 case Options::kPreload:
4520 case Options::kKextBundle:
4521 fMaxAddress = 0xFFFFFFFF;
4522 break;
4523 }
4524 // range check -seg1addr for ARM
4525 if ( fBaseAddress > fMaxAddress ) {
4526 warning("ignoring -seg1addr 0x%08llX. Address out of range.", fBaseAddress);
4527 fBaseAddress = 0;
4528 }
4529 break;
4530 }
4531
4532 // <rdar://problem/6138961> -r implies no prebinding for all architectures
4533 if ( fOutputKind == Options::kObjectFile )
4534 fPrebind = false;
4535
4536 // disable prebinding depending on arch and min OS version
4537 if ( fPrebind ) {
4538 switch ( fArchitecture ) {
4539 case CPU_TYPE_I386:
4540 if ( fMacVersionMin == ld::mac10_4 ) {
4541 // in 10.4 only split seg dylibs are prebound
4542 if ( (fOutputKind != Options::kDynamicLibrary) || ! fSplitSegs )
4543 fPrebind = false;
4544 }
4545 else if ( fMacVersionMin >= ld::mac10_5 ) {
4546 // in 10.5 nothing is prebound
4547 fPrebind = false;
4548 }
4549 else if ( fIOSVersionMin != ld::iOSVersionUnset ) {
4550 // nothing in simulator is prebound
4551 fPrebind = false;
4552 }
4553 else {
4554 // in 10.3 and earlier only dylibs and main executables could be prebound
4555 switch ( fOutputKind ) {
4556 case Options::kDynamicExecutable:
4557 case Options::kDynamicLibrary:
4558 // only main executables and dylibs can be prebound
4559 break;
4560 case Options::kStaticExecutable:
4561 case Options::kDynamicBundle:
4562 case Options::kObjectFile:
4563 case Options::kDyld:
4564 case Options::kPreload:
4565 case Options::kKextBundle:
4566 // disable prebinding for everything else
4567 fPrebind = false;
4568 break;
4569 }
4570 }
4571 break;
4572 case CPU_TYPE_X86_64:
4573 fPrebind = false;
4574 break;
4575 case CPU_TYPE_ARM:
4576 switch ( fOutputKind ) {
4577 case Options::kDynamicExecutable:
4578 case Options::kDynamicLibrary:
4579 // only main executables and dylibs can be prebound
4580 break;
4581 case Options::kStaticExecutable:
4582 case Options::kDynamicBundle:
4583 case Options::kObjectFile:
4584 case Options::kDyld:
4585 case Options::kPreload:
4586 case Options::kKextBundle:
4587 // disable prebinding for everything else
4588 fPrebind = false;
4589 break;
4590 }
4591 break;
4592 }
4593 }
4594
4595 // only prebound images can be split-seg
4596 if ( fSplitSegs && !fPrebind )
4597 fSplitSegs = false;
4598
4599 // determine if info for shared region should be added
4600 if ( fOutputKind == Options::kDynamicLibrary ) {
4601 if ( minOS(ld::mac10_5, ld::iOS_3_1) )
4602 if ( !fPrebind && !fSharedRegionEligibleForceOff )
4603 if ( sharedCacheEligiblePath(this->installPath()) )
4604 fSharedRegionEligible = true;
4605 }
4606 else if ( fOutputKind == Options::kDyld ) {
4607 // <rdar://problem/10111122> Enable dyld to be put into the dyld shared cache
4608 fSharedRegionEligible = true;
4609 }
4610
4611 // automatically use __DATA_CONST in iOS dylibs
4612 if ( fSharedRegionEligible && minOS(ld::mac10_Future, ld::iOS_9_0) && !fUseDataConstSegmentForceOff && !fTargetIOSSimulator) {
4613 fUseDataConstSegment = true;
4614 }
4615 if ( fUseDataConstSegmentForceOn ) {
4616 fUseDataConstSegment = true;
4617 }
4618 // A -kext for iOS 10 ==> -data_const, -text_exec, -add_split_seg_info
4619 if ( (fOutputKind == Options::kKextBundle) && minOS(ld::mac10_Future, ld::iOS_10_0) && (fArchitecture == CPU_TYPE_ARM64) ) {
4620 fUseDataConstSegment = true;
4621 fUseTextExecSegment = true;
4622 fSharedRegionEligible = true;
4623 }
4624 if ( fUseDataConstSegment ) {
4625 addSectionRename("__DATA", "__got", "__DATA_CONST", "__got");
4626 addSectionRename("__DATA", "__la_symbol_ptr", "__DATA_CONST", "__la_symbol_ptr");
4627 addSectionRename("__DATA", "__nl_symbol_ptr", "__DATA_CONST", "__nl_symbol_ptr");
4628 addSectionRename("__DATA", "__const", "__DATA_CONST", "__const");
4629 addSectionRename("__DATA", "__cfstring", "__DATA_CONST", "__cfstring");
4630 addSectionRename("__DATA", "__mod_init_func", "__DATA_CONST", "__mod_init_func");
4631 addSectionRename("__DATA", "__mod_term_func", "__DATA_CONST", "__mod_term_func");
4632 addSectionRename("__DATA", "__objc_classlist", "__DATA_CONST", "__objc_classlist");
4633 addSectionRename("__DATA", "__objc_nlclslist", "__DATA_CONST", "__objc_nlclslist");
4634 addSectionRename("__DATA", "__objc_catlist", "__DATA_CONST", "__objc_catlist");
4635 addSectionRename("__DATA", "__objc_nlcatlist", "__DATA_CONST", "__objc_nlcatlist");
4636 addSectionRename("__DATA", "__objc_protolist", "__DATA_CONST", "__objc_protolist");
4637 addSectionRename("__DATA", "__objc_imageinfo", "__DATA_CONST", "__objc_imageinfo");
4638 addSectionRename("__DATA", "__objc_const", "__DATA_CONST", "__objc_const");
4639 }
4640 if ( fUseTextExecSegment ) {
4641 addSectionRename("__TEXT", "__text", "__TEXT_EXEC", "__text");
4642 addSectionRename("__TEXT", "__stubs", "__TEXT_EXEC", "__stubs");
4643 }
4644
4645 // Use V2 shared cache info when targetting newer OSs
4646 if ( fSharedRegionEligible && minOS(ld::mac10_12, ld::iOS_9_0)) {
4647 fSharedRegionEncodingV2 = true;
4648 if ( fPlatform == kPlatformOSX ) {
4649 fSharedRegionEncodingV2 = false;
4650 // <rdar://problem/24772435> only use v2 for Swift dylibs on Mac OS X
4651 if ( strncmp(this->installPath(), "/System/Library/PrivateFrameworks/Swift/", 40) == 0 )
4652 fSharedRegionEncodingV2 = true;
4653 // <rdar://problem/31428120> an other OS frameworks that use swift need v2
4654 for (const char* searchPath : fLibrarySearchPaths ) {
4655 if ( strstr(searchPath, "xctoolchain/usr/lib/swift/macos") != NULL ) {
4656 fSharedRegionEncodingV2 = true;
4657 break;
4658 }
4659 }
4660 }
4661 fIgnoreOptimizationHints = true;
4662 }
4663
4664 // figure out if module table is needed for compatibility with old ld/dyld
4665 if ( fOutputKind == Options::kDynamicLibrary ) {
4666 switch ( fArchitecture ) {
4667 case CPU_TYPE_I386:
4668 if ( fIOSVersionMin != ld::iOSVersionUnset ) // simulator never needs modules
4669 break;
4670 case CPU_TYPE_ARM:
4671 if ( fPrebind )
4672 fNeedsModuleTable = true; // redo_prebinding requires a module table
4673 break;
4674 }
4675 }
4676
4677 // <rdar://problem/5366363> -r -x implies -S
4678 if ( (fOutputKind == Options::kObjectFile) && (fLocalSymbolHandling == kLocalSymbolsNone) )
4679 fDebugInfoStripping = Options::kDebugInfoNone;
4680
4681 // <rdar://problem/15252891> -r implies -no_uuid
4682 if ( fOutputKind == Options::kObjectFile )
4683 fUUIDMode = kUUIDNone;
4684
4685 // choose how to process unwind info
4686 switch ( fArchitecture ) {
4687 case CPU_TYPE_I386:
4688 case CPU_TYPE_X86_64:
4689 case CPU_TYPE_ARM64:
4690 switch ( fOutputKind ) {
4691 case Options::kObjectFile:
4692 case Options::kStaticExecutable:
4693 case Options::kPreload:
4694 case Options::kKextBundle:
4695 fAddCompactUnwindEncoding = false;
4696 break;
4697 case Options::kDyld:
4698 case Options::kDynamicLibrary:
4699 case Options::kDynamicBundle:
4700 case Options::kDynamicExecutable:
4701 //if ( fAddCompactUnwindEncoding && (fVersionMin >= ld::mac10_6) )
4702 // fRemoveDwarfUnwindIfCompactExists = true;
4703 break;
4704 }
4705 break;
4706 case CPU_TYPE_ARM:
4707 if ( armUsesZeroCostExceptions() ) {
4708 switch ( fOutputKind ) {
4709 case Options::kObjectFile:
4710 case Options::kStaticExecutable:
4711 case Options::kPreload:
4712 case Options::kKextBundle:
4713 fAddCompactUnwindEncoding = false;
4714 break;
4715 case Options::kDyld:
4716 case Options::kDynamicLibrary:
4717 case Options::kDynamicBundle:
4718 case Options::kDynamicExecutable:
4719 fAddCompactUnwindEncoding = true;
4720 break;
4721 }
4722 }
4723 else {
4724 fAddCompactUnwindEncoding = false;
4725 fRemoveDwarfUnwindIfCompactExists = false;
4726 }
4727 break;
4728 case 0:
4729 // if -arch is missing, assume we don't want compact unwind info
4730 fAddCompactUnwindEncoding = false;
4731 break;
4732 }
4733
4734 // only iOS executables should be encryptable
4735 switch ( fOutputKind ) {
4736 case Options::kObjectFile:
4737 case Options::kDyld:
4738 case Options::kStaticExecutable:
4739 case Options::kPreload:
4740 case Options::kKextBundle:
4741 fEncryptable = false;
4742 break;
4743 case Options::kDynamicExecutable:
4744 break;
4745 case Options::kDynamicLibrary:
4746 case Options::kDynamicBundle:
4747 // <rdar://problem/16293398> Add LC_ENCRYPTION_INFO load command to bundled frameworks
4748 if ( !min_iOS(ld::iOS_7_0) )
4749 fEncryptable = false;
4750 break;
4751 }
4752 if ( (fArchitecture != CPU_TYPE_ARM) && (fArchitecture != CPU_TYPE_ARM64)
4753 )
4754 fEncryptable = false;
4755 if ( fEncryptableForceOn )
4756 fEncryptable = true;
4757 else if ( fEncryptableForceOff )
4758 fEncryptable = false;
4759
4760 // don't move inits in dyld because dyld wants certain
4761 // entries point at stable locations at the start of __text
4762 if ( fOutputKind == Options::kDyld )
4763 fAutoOrderInitializers = false;
4764
4765
4766 // disable __data ordering for some output kinds
4767 switch ( fOutputKind ) {
4768 case Options::kObjectFile:
4769 case Options::kDyld:
4770 case Options::kStaticExecutable:
4771 case Options::kPreload:
4772 case Options::kKextBundle:
4773 fOrderData = false;
4774 break;
4775 case Options::kDynamicExecutable:
4776 case Options::kDynamicLibrary:
4777 case Options::kDynamicBundle:
4778 break;
4779 }
4780
4781 // only use compressed LINKEDIT for final linked images
4782 switch ( fOutputKind ) {
4783 case Options::kDynamicExecutable:
4784 case Options::kDynamicLibrary:
4785 case Options::kDynamicBundle:
4786 break;
4787 case Options::kPreload:
4788 case Options::kStaticExecutable:
4789 case Options::kObjectFile:
4790 case Options::kDyld:
4791 case Options::kKextBundle:
4792 fMakeCompressedDyldInfoForceOff = true;
4793 break;
4794 }
4795 if ( fMakeCompressedDyldInfoForceOff )
4796 fMakeCompressedDyldInfo = false;
4797
4798
4799 // only use compressed LINKEDIT for:
4800 // Mac OS X 10.6 or later
4801 // iOS 3.1 or later
4802 if ( fMakeCompressedDyldInfo ) {
4803 if ( !minOS(ld::mac10_6, ld::iOS_3_1) )
4804 fMakeCompressedDyldInfo = false;
4805 }
4806
4807 // only ARM and x86_64 enforces that cpu-sub-types must match
4808 switch ( fArchitecture ) {
4809 case CPU_TYPE_ARM:
4810 break;
4811 case CPU_TYPE_X86_64:
4812 fEnforceDylibSubtypesMatch = false;
4813 break;
4814 case CPU_TYPE_I386:
4815 case CPU_TYPE_ARM64:
4816 fEnforceDylibSubtypesMatch = false;
4817 break;
4818 }
4819
4820
4821 // only final linked images can not optimize zero fill sections
4822 if ( fOutputKind == Options::kObjectFile )
4823 fOptimizeZeroFill = true;
4824
4825 // all undefines in -r mode
4826 // if ( fOutputKind == Options::kObjectFile )
4827 // fUndefinedTreatment = kUndefinedSuppress;
4828
4829 // only dynamic final linked images should warn about use of commmons
4830 if ( fWarnCommons ) {
4831 switch ( fOutputKind ) {
4832 case Options::kDynamicExecutable:
4833 case Options::kDynamicLibrary:
4834 case Options::kDynamicBundle:
4835 break;
4836 case Options::kPreload:
4837 case Options::kStaticExecutable:
4838 case Options::kObjectFile:
4839 case Options::kDyld:
4840 case Options::kKextBundle:
4841 fWarnCommons = false;
4842 break;
4843 }
4844 }
4845
4846 // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
4847 if ( minOS(ld::mac10_5, ld::iOS_2_0) )
4848 fUseSimplifiedDylibReExports = true;
4849
4850 // Mac OS X 10.7 and iOS 4.2 support LC_LOAD_UPWARD_DYLIB
4851 if ( minOS(ld::mac10_7, ld::iOS_4_2) && (fOutputKind == kDynamicLibrary) )
4852 fCanUseUpwardDylib = true;
4853
4854 // MacOSX 10.7 defaults to PIE
4855 if ( (fArchitecture == CPU_TYPE_I386)
4856 && (fOutputKind == kDynamicExecutable)
4857 && (fMacVersionMin >= ld::mac10_7) ) {
4858 fPositionIndependentExecutable = true;
4859 }
4860
4861 // armv7 for iOS4.3 defaults to PIE
4862 if ( (fArchitecture == CPU_TYPE_ARM)
4863 && fArchSupportsThumb2
4864 && (fOutputKind == kDynamicExecutable)
4865 && min_iOS(ld::iOS_4_3) ) {
4866 fPositionIndependentExecutable = true;
4867 }
4868
4869 // <rdar://problem/24535196> x86_64 defaults PIE (regardless of minOS version)
4870 if ( (fArchitecture == CPU_TYPE_X86_64) && (fOutputKind == kDynamicExecutable) && (fMacVersionMin >= ld::mac10_6) )
4871 fPositionIndependentExecutable = true;
4872
4873 // Simulator defaults to PIE
4874 if ( fTargetIOSSimulator && (fOutputKind == kDynamicExecutable) )
4875 fPositionIndependentExecutable = true;
4876
4877 // -no_pie anywhere on command line disable PIE
4878 if ( fDisablePositionIndependentExecutable )
4879 fPositionIndependentExecutable = false;
4880
4881 // arm64 is always PIE
4882 if ( ((fArchitecture == CPU_TYPE_ARM64)
4883 )
4884 && (fOutputKind == kDynamicExecutable) ) {
4885 fPositionIndependentExecutable = true;
4886 if ( fDisablePositionIndependentExecutable )
4887 warning("-no_pie ignored for arm64");
4888 }
4889
4890 // set fOutputSlidable
4891 switch ( fOutputKind ) {
4892 case Options::kObjectFile:
4893 fOutputSlidable = false;
4894 break;
4895 case Options::kStaticExecutable:
4896 case Options::kDynamicExecutable:
4897 fOutputSlidable = fPositionIndependentExecutable;
4898 break;
4899 case Options::kPreload:
4900 fOutputSlidable = fPIEOnCommandLine;
4901 break;
4902 case Options::kDyld:
4903 case Options::kDynamicLibrary:
4904 case Options::kDynamicBundle:
4905 case Options::kKextBundle:
4906 fOutputSlidable = true;
4907 break;
4908 }
4909
4910 // let linker know if thread local variables are supported
4911 if ( fMacVersionMin >= ld::mac10_7 ) {
4912 fTLVSupport = true;
4913 }
4914 else if ( ((fArchitecture == CPU_TYPE_ARM64)
4915 )
4916 && min_iOS(ld::iOS_8_0) ) {
4917 fTLVSupport = true;
4918 }
4919 else if ( (fArchitecture == CPU_TYPE_ARM) && min_iOS(ld::iOS_9_0) ) {
4920 fTLVSupport = true;
4921 }
4922 else if ( fTargetIOSSimulator && (fArchitecture == CPU_TYPE_X86_64) && min_iOS(ld::iOS_8_0) ) {
4923 fTLVSupport = true;
4924 }
4925 else if ( fTargetIOSSimulator && (fArchitecture == CPU_TYPE_I386) && min_iOS(ld::iOS_9_0) ) {
4926 fTLVSupport = true;
4927 }
4928
4929 // default to adding version load command for dynamic code, static code must opt-in
4930 switch ( fOutputKind ) {
4931 case Options::kObjectFile:
4932 fVersionLoadCommand = false;
4933 break;
4934 case Options::kStaticExecutable:
4935 case Options::kPreload:
4936 case Options::kKextBundle:
4937 if ( fVersionLoadCommandForcedOn )
4938 fVersionLoadCommand = true;
4939 break;
4940 case Options::kDynamicExecutable:
4941 case Options::kDyld:
4942 case Options::kDynamicLibrary:
4943 case Options::kDynamicBundle:
4944 if ( !fVersionLoadCommandForcedOff )
4945 fVersionLoadCommand = true;
4946 break;
4947 }
4948
4949 // support re-export of individual symbols in MacOSX 10.7 and iOS 4.2
4950 if ( (fOutputKind == kDynamicLibrary) && minOS(ld::mac10_7, ld::iOS_4_2) )
4951 fCanReExportSymbols = true;
4952
4953 // ObjC optimization is only in dynamic final linked images
4954 switch ( fOutputKind ) {
4955 case Options::kObjectFile:
4956 case Options::kStaticExecutable:
4957 case Options::kPreload:
4958 case Options::kKextBundle:
4959 case Options::kDyld:
4960 fObjcCategoryMerging = false;
4961 break;
4962 case Options::kDynamicExecutable:
4963 case Options::kDynamicLibrary:
4964 case Options::kDynamicBundle:
4965 break;
4966 }
4967
4968 // i386 main executables linked on Mac OS X 10.7 default to NX heap
4969 // regardless of target unless overriden with -allow_heap_execute anywhere
4970 // on the command line
4971 if ( (fArchitecture == CPU_TYPE_I386) && (fOutputKind == kDynamicExecutable) && !fDisableNonExecutableHeap)
4972 fNonExecutableHeap = true;
4973
4974 // Use LC_MAIN instead of LC_UNIXTHREAD for newer OSs
4975 switch ( fOutputKind ) {
4976 case Options::kDynamicExecutable:
4977 if ( fEntryPointLoadCommandForceOn ) {
4978 fEntryPointLoadCommand = true;
4979 if ( fEntryName == NULL )
4980 fEntryName = "_main";
4981 }
4982 else if ( fEntryPointLoadCommandForceOff ) {
4983 fNeedsThreadLoadCommand = true;
4984 if ( fEntryName == NULL )
4985 fEntryName = "start";
4986 }
4987 else {
4988 // <rdar://problem/16310363> Linker should look for "_main" not "start" when building for sim regardless of min OS
4989 if ( minOS(ld::mac10_8, ld::iOS_6_0) || fTargetIOSSimulator ) {
4990 fEntryPointLoadCommand = true;
4991 if ( fEntryName == NULL )
4992 fEntryName = "_main";
4993 if ( strcmp(fEntryName, "start") == 0 ) {
4994 warning("Ignoring '-e start' because entry point 'start' is not used for the targeted OS version");
4995 fEntryName = "_main";
4996 }
4997 }
4998 else {
4999 fNeedsThreadLoadCommand = true;
5000 if ( fEntryName == NULL )
5001 fEntryName = "start";
5002 }
5003 }
5004 break;
5005 case Options::kObjectFile:
5006 case Options::kKextBundle:
5007 case Options::kDynamicLibrary:
5008 case Options::kDynamicBundle:
5009 break;
5010
5011 case Options::kStaticExecutable:
5012 case Options::kPreload:
5013 case Options::kDyld:
5014 fNeedsThreadLoadCommand = true;
5015 if ( fEntryName == NULL )
5016 fEntryName = "start"; // Perhaps these should have no default and require -e
5017 break;
5018 }
5019
5020 // add LC_SOURCE_VERSION
5021 switch ( fOutputKind ) {
5022 case Options::kDynamicExecutable:
5023 case Options::kKextBundle:
5024 case Options::kDynamicLibrary:
5025 case Options::kDynamicBundle:
5026 case Options::kDyld:
5027 case Options::kStaticExecutable:
5028 if ( fSourceVersionLoadCommandForceOn ) {
5029 fSourceVersionLoadCommand = true;
5030 }
5031 else if ( fSourceVersionLoadCommandForceOff ) {
5032 fSourceVersionLoadCommand = false;
5033 }
5034 else {
5035 if ( minOS(ld::mac10_8, ld::iOS_6_0) ) {
5036 fSourceVersionLoadCommand = true;
5037 }
5038 else
5039 fSourceVersionLoadCommand = false;
5040 }
5041 break;
5042 case Options::kObjectFile:
5043 case Options::kPreload:
5044 fSourceVersionLoadCommand = false;
5045 break;
5046 }
5047
5048 // if -sdk_version not on command line, infer from -syslibroot
5049 if ( (fSDKVersion == 0) && (fSDKPaths.size() > 0) ) {
5050 const char* sdkPath = fSDKPaths.front();
5051 const char* end = &sdkPath[strlen(sdkPath)-1];
5052 while ( !isdigit(*end) && (end > sdkPath) )
5053 --end;
5054 const char* start = end-1;
5055 while ( (isdigit(*start) || (*start == '.')) && (start > sdkPath))
5056 --start;
5057 char sdkVersionStr[32];
5058 int len = end-start+1;
5059 if ( len > 2 ) {
5060 strlcpy(sdkVersionStr, start+1, len);
5061 fSDKVersion = parseVersionNumber32(sdkVersionStr);
5062 }
5063 }
5064
5065 // if -sdk_version and -syslibroot not used, but targeting MacOSX, use current OS version
5066 if ( (fSDKVersion == 0) && (fMacVersionMin != ld::macVersionUnset) ) {
5067 // special case if RC_ProjectName and MACOSX_DEPLOYMENT_TARGET are both set that sdkversion=minos
5068 if ( getenv("RC_ProjectName") && getenv("MACOSX_DEPLOYMENT_TARGET") ) {
5069 fSDKVersion = fMacVersionMin;
5070 }
5071 else {
5072 int mib[2] = { CTL_KERN, KERN_OSRELEASE };
5073 char kernVersStr[100];
5074 size_t strlen = sizeof(kernVersStr);
5075 if ( sysctl(mib, 2, kernVersStr, &strlen, NULL, 0) != -1 ) {
5076 uint32_t kernVers = parseVersionNumber32(kernVersStr);
5077 int minor = (kernVers >> 16) - 4; // kernel major version is 4 ahead of x in 10.x
5078 fSDKVersion = 0x000A0000 + (minor << 8);
5079 }
5080 }
5081 }
5082
5083 // allow trie based absolute symbols if targeting new enough OS
5084 if ( fMakeCompressedDyldInfo ) {
5085 if ( minOS(ld::mac10_9, ld::iOS_7_0) ) {
5086 fAbsoluteSymbols = true;
5087 }
5088 }
5089
5090 // <rdar://problem/12959510> iOS main executables now default to 16KB page size
5091 if ( (fIOSVersionMin != ld::iOSVersionUnset) && (fOutputKind == Options::kDynamicExecutable) ) {
5092 // <rdar://problem/13070042> Only third party apps should have 16KB page segments by default
5093 if ( fEncryptable ) {
5094 if ( fSegmentAlignment == 4096 )
5095 fSegmentAlignment = 4096*4;
5096 }
5097 }
5098
5099 // <rdar://problem/12258065> ARM64 needs 16KB page size for user land code
5100 // <rdar://problem/15974532> make armv7[s] use 16KB pages in user land code for iOS 8 or later
5101 if ( fSegmentAlignment == 4096 ) {
5102 switch ( fOutputKind ) {
5103 case Options::kDynamicExecutable:
5104 case Options::kDynamicLibrary:
5105 case Options::kDynamicBundle:
5106 case Options::kDyld:
5107 if ( ((fArchitecture == CPU_TYPE_ARM64)
5108 )
5109 || ((fArchitecture == CPU_TYPE_ARM) && min_iOS(ld::iOS_7_0)) ) {
5110 fSegmentAlignment = 4096*4;
5111 }
5112 break;
5113 case Options::kStaticExecutable:
5114 case Options::kKextBundle:
5115 // <rdar://problem/14676611> 16KB segments for arm64 kexts
5116 if ( ((fArchitecture == CPU_TYPE_ARM64)
5117 )
5118 && min_iOS(ld::iOS_9_0) ) {
5119 fSegmentAlignment = 4096*4;
5120 }
5121 break;
5122 case Options::kObjectFile:
5123 case Options::kPreload:
5124 break;
5125 }
5126 }
5127
5128
5129
5130 // <rdar://problem/13624134> linker should not convert dwarf unwind if .o file has compact unwind section
5131 switch ( fOutputKind ) {
5132 case Options::kDynamicExecutable:
5133 case Options::kDynamicLibrary:
5134 case Options::kDynamicBundle:
5135 case Options::kDyld:
5136 if ( fKeepDwarfUnwindForcedOn ) {
5137 fKeepDwarfUnwind = true;
5138 }
5139 else if ( fKeepDwarfUnwindForcedOff ) {
5140 fKeepDwarfUnwind = false;
5141 }
5142 else {
5143 if ( minOS(ld::mac10_9, ld::iOS_7_0) )
5144 fKeepDwarfUnwind = false;
5145 else
5146 fKeepDwarfUnwind = true;
5147 }
5148 break;
5149 case Options::kKextBundle:
5150 case Options::kStaticExecutable:
5151 case Options::kObjectFile:
5152 case Options::kPreload:
5153 fKeepDwarfUnwind = true;
5154 break;
5155 }
5156
5157 // Make sure -image_base matches alignment
5158 uint64_t alignedBaseAddress = (fBaseAddress+fSegmentAlignment-1) & (-fSegmentAlignment);
5159 if ( alignedBaseAddress != fBaseAddress ) {
5160 warning("base address 0x%llX is not properly aligned. Changing it to 0x%llX", fBaseAddress, alignedBaseAddress);
5161 fBaseAddress = alignedBaseAddress;
5162 }
5163
5164 // If -dirty_data_list not specified, look in $SDKROOT/AppleInternal/DirtyDataFiles/<dylib>.dirty for dirty data list
5165 if ( fSymbolsMovesData.empty() && fUseDataConstSegment && ( fDylibInstallName != NULL) && !fSDKPaths.empty() ) {
5166 const char* dylibLeaf = strrchr(fDylibInstallName, '/');
5167 if ( dylibLeaf ) {
5168 char path[PATH_MAX];
5169 strlcpy(path , fSDKPaths.front(), sizeof(path));
5170 strlcat(path , "/AppleInternal/DirtyDataFiles", sizeof(path));
5171 strlcat(path , dylibLeaf, sizeof(path));
5172 strlcat(path , ".dirty", sizeof(path));
5173 FileInfo info;
5174 if ( info.checkFileExists(*this, path) )
5175 addSymbolMove("__DATA_DIRTY", path, fSymbolsMovesData, "-dirty_data_list");
5176 }
5177 }
5178
5179
5180 // <rdar://problem/32138080> Automatically use OrderFiles found in the AppleInternal SDK
5181 if ( (fFinalName != NULL) && fOrderedSymbols.empty() && !fSDKPaths.empty() ) {
5182 char path[PATH_MAX];
5183 strlcpy(path , fSDKPaths.front(), sizeof(path));
5184 strlcat(path , "/AppleInternal/OrderFiles/", sizeof(path));
5185 strlcat(path , fFinalName, sizeof(path));
5186 strlcat(path , ".order", sizeof(path));
5187 FileInfo info;
5188 if ( info.checkFileExists(*this, path) )
5189 parseOrderFile(path, false);
5190 }
5191
5192 // <rdar://problem/20503811> Reduce the default alignment of structures/arrays to save memory in embedded systems
5193 if ( fMaxDefaultCommonAlign == 0 ) {
5194 if ( fOutputKind == Options::kPreload )
5195 fMaxDefaultCommonAlign = 8;
5196 else
5197 fMaxDefaultCommonAlign = 15;
5198 }
5199
5200 // Add warnings for issues likely to cause OS verification issues
5201 if ( fSharedRegionEligible && !fRPaths.empty() ) {
5202 // <rdar://problem/18719327> warn if -rpath is used with OS dylibs
5203 warning("OS dylibs should not add rpaths (linker option: -rpath) (Xcode build setting: LD_RUNPATH_SEARCH_PATHS)");
5204 }
5205 if ( (fOutputKind == Options::kDynamicLibrary) && (fDylibInstallName != NULL) && (fFinalName != NULL) && sharedCacheEligiblePath(fFinalName) ) {
5206 if ( strncmp(fDylibInstallName, "@rpath", 6) == 0 )
5207 warning("OS dylibs should not use @rpath for -install_name. Use absolute path instead");
5208 if ( strcmp(fDylibInstallName, fFinalName) != 0 ) {
5209 bool different = true;
5210 // some projects end up with double slash in -final_output path
5211 if ( strstr(fFinalName, "//") != NULL ) {
5212 char fixedPath[strlen(fFinalName)+1];
5213 char* t = fixedPath;
5214 bool lastWasSlash = false;
5215 for (const char* s=fFinalName; *s != '\0'; ++s) {
5216 if ( *s == '/' ) {
5217 if ( !lastWasSlash )
5218 *t++ = *s;
5219 lastWasSlash = true;
5220 }
5221 else {
5222 *t++ = *s;
5223 lastWasSlash = false;
5224 }
5225 }
5226 *t = '\0';
5227 different = (strcmp(fDylibInstallName, fixedPath) != 0);
5228 }
5229 if ( different )
5230 warning("OS dylibs -install_name should match its real absolute path");
5231 }
5232 }
5233
5234 // set if unaligned pointers are warnings or errors
5235 if ( fMacVersionMin >= ld::mac10_12 ) {
5236 // ignore unaligned pointers when targeting older macOS versions
5237 if ( fSharedRegionEligible )
5238 fUnalignedPointerTreatment = Options::kUnalignedPointerWarning;
5239 else
5240 fUnalignedPointerTreatment = Options::kUnalignedPointerIgnore;
5241 }
5242 else if ( min_iOS(ld::iOS_10_0) ) {
5243 fUnalignedPointerTreatment = Options::kUnalignedPointerWarning;
5244 }
5245 else {
5246 fUnalignedPointerTreatment = Options::kUnalignedPointerIgnore;
5247 }
5248
5249 }
5250
5251 void Options::checkIllegalOptionCombinations()
5252 {
5253 // check -undefined setting
5254 switch ( fUndefinedTreatment ) {
5255 case kUndefinedError:
5256 // always legal
5257 break;
5258 case kUndefinedDynamicLookup:
5259 switch (fPlatform) {
5260 case kPlatformOSX:
5261 break;
5262 case kPlatformiOS:
5263 case kPlatformWatchOS:
5264 case kPlatform_bridgeOS:
5265 #if SUPPORT_APPLE_TV
5266 case kPlatform_tvOS:
5267 #endif
5268 if ( fOutputKind != kKextBundle )
5269 warning("-undefined dynamic_lookup is deprecated on %s", platformName(fPlatform));
5270 break;
5271 default:
5272 break;
5273 }
5274 break;
5275 case kUndefinedWarning:
5276 case kUndefinedSuppress:
5277 // requires flat namespace
5278 if ( fNameSpace == kTwoLevelNameSpace )
5279 throw "can't use -undefined warning or suppress with -twolevel_namespace";
5280 break;
5281 }
5282
5283 // unify -sub_umbrella with dylibs
5284 for (std::vector<const char*>::iterator it = fSubUmbellas.begin(); it != fSubUmbellas.end(); it++) {
5285 const char* subUmbrella = *it;
5286 bool found = false;
5287 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
5288 Options::FileInfo& info = *fit;
5289 const char* lastSlash = strrchr(info.path, '/');
5290 if ( lastSlash == NULL )
5291 lastSlash = info.path - 1;
5292 std::string path(&lastSlash[1]);
5293 auto idx = path.find(".tbd", path.size() - 4);
5294 if (idx != std::string::npos)
5295 path.erase(idx);
5296 if ( path == subUmbrella ) {
5297 info.options.fReExport = true;
5298 found = true;
5299 fLinkSnapshot.recordSubUmbrella(info.path);
5300 break;
5301 }
5302 }
5303 if ( ! found )
5304 warning("-sub_umbrella %s does not match a supplied dylib", subUmbrella);
5305 }
5306
5307 // unify -sub_library with dylibs
5308 for (std::vector<const char*>::iterator it = fSubLibraries.begin(); it != fSubLibraries.end(); it++) {
5309 const char* subLibrary = *it;
5310 bool found = false;
5311 for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
5312 Options::FileInfo& info = *fit;
5313 const char* lastSlash = strrchr(info.path, '/');
5314 if ( lastSlash == NULL )
5315 lastSlash = info.path - 1;
5316 const char* dot = strchr(&lastSlash[1], '.');
5317 if ( dot == NULL )
5318 dot = &lastSlash[strlen(lastSlash)];
5319 if ( strncmp(&lastSlash[1], subLibrary, dot-lastSlash-1) == 0 ) {
5320 info.options.fReExport = true;
5321 found = true;
5322 fLinkSnapshot.recordSubLibrary(info.path);
5323 break;
5324 }
5325 }
5326 if ( ! found )
5327 warning("-sub_library %s does not match a supplied dylib", subLibrary);
5328 }
5329
5330 // sync reader options
5331 if ( fNameSpace != kTwoLevelNameSpace ) {
5332 fFlatNamespace = true;
5333 switch (fPlatform) {
5334 case kPlatformOSX:
5335 break;
5336 case kPlatformiOS:
5337 case kPlatformWatchOS:
5338 case kPlatform_bridgeOS:
5339 #if SUPPORT_APPLE_TV
5340 case Options::kPlatform_tvOS:
5341 #endif
5342 warning("-flat_namespace is deprecated on %s", platformName(fPlatform));
5343 break;
5344 default:
5345 break;
5346 }
5347 }
5348
5349
5350 // check -stack_addr
5351 if ( fStackAddr != 0 ) {
5352 switch (fArchitecture) {
5353 case CPU_TYPE_I386:
5354 case CPU_TYPE_ARM:
5355 if ( fStackAddr > 0xFFFFFFFF )
5356 throw "-stack_addr must be < 4G for 32-bit processes";
5357 break;
5358 case CPU_TYPE_X86_64:
5359 case CPU_TYPE_ARM64:
5360 break;
5361 }
5362 if ( (fStackAddr & -4096) != fStackAddr )
5363 throw "-stack_addr must be multiples of 4K";
5364 if ( fStackSize == 0 )
5365 throw "-stack_addr must be used with -stack_size";
5366 }
5367
5368 // check -stack_size
5369 if ( fStackSize != 0 ) {
5370 switch (fArchitecture) {
5371 case CPU_TYPE_I386:
5372 if ( fPlatform == kPlatformOSX ) {
5373 if ( fStackSize > 0xFFFFFFFF )
5374 throw "-stack_size must be < 4GB for 32-bit processes";
5375 if ( fStackAddr == 0 )
5376 fStackAddr = 0xC0000000;
5377 if ( (fStackAddr > 0xB0000000) && ((fStackAddr-fStackSize) < 0xB0000000) )
5378 warning("custom stack placement overlaps and will disable shared region");
5379 }
5380 else {
5381 if ( fStackSize > 0x1F000000 )
5382 throw "-stack_size must be < 496MB";
5383 if ( fStackAddr == 0 )
5384 fStackAddr = 0xC0000000;
5385 }
5386 break;
5387 case CPU_TYPE_ARM:
5388 if ( fStackSize > 0x1F000000 )
5389 throw "-stack_size must be < 496MB";
5390 if ( fStackAddr == 0 )
5391 fStackAddr = 0x1F000000;
5392 if ( fStackAddr > 0x20000000)
5393 throw "-stack_addr must be < 0x20000000 for arm";
5394 break;
5395 case CPU_TYPE_X86_64:
5396 if ( fPlatform == kPlatformOSX ) {
5397 if ( fStackSize > 0x10000000000 )
5398 throw "-stack_size must be <= 1TB";
5399 if ( fStackAddr == 0 ) {
5400 fStackAddr = 0x00007FFF5C000000LL;
5401 }
5402 }
5403 else {
5404 if ( fStackSize > 0x20000000 )
5405 throw "-stack_size must be <= 512MB";
5406 if ( fStackAddr == 0 ) {
5407 fStackAddr = 0x120000000;
5408 }
5409 break;
5410 case CPU_TYPE_ARM64:
5411 if ( fStackSize > 0x20000000 )
5412 throw "-stack_size must be <= 512MB";
5413 if ( fStackAddr == 0 )
5414 fStackAddr = 0x120000000;
5415 }
5416 break;
5417 }
5418 if ( (fStackSize & (-fSegmentAlignment)) != fStackSize )
5419 throwf("-stack_size must be multiple of segment alignment (%lldKB)", fSegmentAlignment/1024);
5420 switch ( fOutputKind ) {
5421 case Options::kDynamicExecutable:
5422 case Options::kStaticExecutable:
5423 // custom stack size only legal when building main executable
5424 break;
5425 case Options::kDynamicLibrary:
5426 case Options::kDynamicBundle:
5427 case Options::kObjectFile:
5428 case Options::kDyld:
5429 case Options::kPreload:
5430 case Options::kKextBundle:
5431 throw "-stack_size option can only be used when linking a main executable";
5432 }
5433 if ( fStackSize > fStackAddr )
5434 throwf("-stack_size (0x%08llX) must be smaller than -stack_addr (0x%08llX)", fStackSize, fStackAddr);
5435 }
5436
5437 // check that -allow_stack_execute is only used with main executables
5438 if ( fExecutableStack ) {
5439 switch ( fOutputKind ) {
5440 case Options::kDynamicExecutable:
5441 case Options::kStaticExecutable:
5442 // -allow_stack_execute size only legal when building main executable
5443 break;
5444 case Options::kDynamicLibrary:
5445 case Options::kDynamicBundle:
5446 case Options::kObjectFile:
5447 case Options::kDyld:
5448 case Options::kPreload:
5449 case Options::kKextBundle:
5450 throw "-allow_stack_execute option can only be used when linking a main executable";
5451 }
5452 }
5453
5454 // check that -allow_heap_execute is only used with i386 main executables
5455 if ( fDisableNonExecutableHeap ) {
5456 if ( fArchitecture != CPU_TYPE_I386 )
5457 throw "-allow_heap_execute option can only be used when linking for i386";
5458 switch ( fOutputKind ) {
5459 case Options::kDynamicExecutable:
5460 // -allow_heap_execute only legal when building main executable
5461 break;
5462 case Options::kStaticExecutable:
5463 case Options::kDynamicLibrary:
5464 case Options::kDynamicBundle:
5465 case Options::kObjectFile:
5466 case Options::kDyld:
5467 case Options::kPreload:
5468 case Options::kKextBundle:
5469 throw "-allow_heap_execute option can only be used when linking a main executable";
5470 }
5471 }
5472
5473 // check -client_name is only used when making a bundle or main executable
5474 if ( fClientName != NULL ) {
5475 switch ( fOutputKind ) {
5476 case Options::kDynamicExecutable:
5477 case Options::kDynamicBundle:
5478 break;
5479 case Options::kStaticExecutable:
5480 case Options::kDynamicLibrary:
5481 case Options::kObjectFile:
5482 case Options::kDyld:
5483 case Options::kPreload:
5484 case Options::kKextBundle:
5485 throw "-client_name can only be used with -bundle";
5486 }
5487 }
5488
5489 // check -init is only used when building a dylib
5490 if ( (fInitFunctionName != NULL) && (fOutputKind != Options::kDynamicLibrary) )
5491 throw "-init can only be used with -dynamiclib";
5492
5493 // check -bundle_loader only used with -bundle
5494 if ( (fBundleLoader != NULL) && (fOutputKind != Options::kDynamicBundle) )
5495 throw "-bundle_loader can only be used with -bundle";
5496
5497 // check -dtrace not used with -r
5498 if ( (fDtraceScriptName != NULL) && (fOutputKind == Options::kObjectFile) )
5499 throw "-dtrace can only be used when creating final linked images";
5500
5501 // check -d can only be used with -r
5502 if ( fMakeTentativeDefinitionsReal && (fOutputKind != Options::kObjectFile) )
5503 throw "-d can only be used with -r";
5504
5505 // check that -root_safe is not used with -r
5506 if ( fRootSafe && (fOutputKind == Options::kObjectFile) )
5507 throw "-root_safe cannot be used with -r";
5508
5509 // check that -setuid_safe is not used with -r
5510 if ( fSetuidSafe && (fOutputKind == Options::kObjectFile) )
5511 throw "-setuid_safe cannot be used with -r";
5512
5513 // <rdar://problem/12781832> compiler driver no longer uses -objc_abi_version, it uses -ios_simulator_version_min instead
5514 if ( !fObjCABIVersion1Override && !fObjCABIVersion2Override && fTargetIOSSimulator )
5515 fObjCABIVersion2Override = true;
5516
5517 // rdar://problem/4718189 map ObjC class names to new runtime names
5518 bool alterObjC1ClassNamesToObjC2 = false;
5519 switch (fArchitecture) {
5520 case CPU_TYPE_I386:
5521 // i386 only uses new symbols when using objc2 ABI
5522 if ( fObjCABIVersion2Override )
5523 alterObjC1ClassNamesToObjC2 = true;
5524 break;
5525 case CPU_TYPE_X86_64:
5526 case CPU_TYPE_ARM:
5527 case CPU_TYPE_ARM64:
5528 alterObjC1ClassNamesToObjC2 = true;
5529 break;
5530 }
5531
5532 // make sure all required exported symbols exist
5533 std::vector<const char*> impliedExports;
5534 for (NameSet::iterator it=fExportSymbols.regularBegin(); it != fExportSymbols.regularEnd(); ++it) {
5535 const char* name = *it;
5536 const int len = strlen(name);
5537 if ( (strcmp(&name[len-3], ".eh") == 0) || (strncmp(name, ".objc_category_name_", 20) == 0) ) {
5538 // never export .eh symbols
5539 warning("ignoring %s in export list", name);
5540 }
5541 else if ( (fArchitecture == CPU_TYPE_I386) && !fObjCABIVersion2Override && (strncmp(name, "_OBJC_CLASS_$", 13) == 0) ) {
5542 warning("ignoring Objc2 Class symbol %s in i386 export list", name);
5543 fRemovedExports.insert(name);
5544 }
5545 else if ( alterObjC1ClassNamesToObjC2 && (strncmp(name, ".objc_class_name_", 17) == 0) ) {
5546 // linking ObjC2 ABI, but have ObjC1 ABI name in export list. Change it to intended name
5547 fRemovedExports.insert(name);
5548 char* temp;
5549 asprintf(&temp, "_OBJC_CLASS_$_%s", &name[17]);
5550 impliedExports.push_back(temp);
5551 asprintf(&temp, "_OBJC_METACLASS_$_%s", &name[17]);
5552 impliedExports.push_back(temp);
5553 }
5554 else {
5555 fInitialUndefines.push_back(name);
5556 }
5557 }
5558 fExportSymbols.remove(fRemovedExports);
5559 for (std::vector<const char*>::iterator it=impliedExports.begin(); it != impliedExports.end(); ++it) {
5560 const char* name = *it;
5561 fExportSymbols.insert(name);
5562 fInitialUndefines.push_back(name);
5563 }
5564
5565 // make sure all required re-exported symbols exist
5566 for (NameSet::iterator it=fReExportSymbols.regularBegin(); it != fReExportSymbols.regularEnd(); ++it) {
5567 fInitialUndefines.push_back(*it);
5568 }
5569
5570 // make sure that -init symbol exists
5571 if ( fInitFunctionName != NULL )
5572 fInitialUndefines.push_back(fInitFunctionName);
5573
5574 // make sure that entry symbol exists
5575 switch ( fOutputKind ) {
5576 case Options::kDynamicExecutable:
5577 case Options::kStaticExecutable:
5578 case Options::kDyld:
5579 case Options::kPreload:
5580 fInitialUndefines.push_back(fEntryName);
5581 break;
5582 case Options::kDynamicLibrary:
5583 case Options::kDynamicBundle:
5584 case Options::kObjectFile:
5585 case Options::kKextBundle:
5586 break;
5587 }
5588
5589 // make sure every alias base exists
5590 for (std::vector<AliasPair>::iterator it=fAliases.begin(); it != fAliases.end(); ++it) {
5591 fInitialUndefines.push_back(it->realName);
5592 }
5593
5594 // check custom segments
5595 if ( fCustomSegmentAddresses.size() != 0 ) {
5596 // verify no segment is in zero page
5597 if ( fZeroPageSize != ULLONG_MAX ) {
5598 for (std::vector<SegmentStart>::iterator it = fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
5599 if ( it->address < fZeroPageSize )
5600 throwf("-segaddr %s 0x%llX conflicts with -pagezero_size", it->name, it->address);
5601 }
5602 }
5603 // verify no duplicates
5604 for (std::vector<SegmentStart>::iterator it = fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
5605 for (std::vector<SegmentStart>::iterator it2 = fCustomSegmentAddresses.begin(); it2 != fCustomSegmentAddresses.end(); ++it2) {
5606 if ( (it->address == it2->address) && (it != it2) )
5607 throwf("duplicate -segaddr addresses for %s and %s", it->name, it2->name);
5608 }
5609 // a custom segment address of zero will disable the use of a zero page
5610 if ( it->address == 0 )
5611 fZeroPageSize = 0;
5612 }
5613 }
5614
5615 if ( fZeroPageSize == ULLONG_MAX ) {
5616 // zero page size not specified on command line, set default
5617 switch (fArchitecture) {
5618 case CPU_TYPE_I386:
5619 case CPU_TYPE_ARM:
5620 // first 4KB for 32-bit architectures
5621 fZeroPageSize = 0x1000;
5622 break;
5623 case CPU_TYPE_ARM64:
5624 case CPU_TYPE_X86_64:
5625 // first 4GB for x86_64 on all OS's
5626 fZeroPageSize = 0x100000000ULL;
5627 break;
5628 default:
5629 // if -arch not used, default to 4K zero-page
5630 fZeroPageSize = 0x1000;
5631 }
5632 }
5633 else {
5634 switch ( fOutputKind ) {
5635 case Options::kDynamicExecutable:
5636 case Options::kStaticExecutable:
5637 // -pagezero_size size only legal when building main executable
5638 break;
5639 case Options::kDynamicLibrary:
5640 case Options::kDynamicBundle:
5641 case Options::kObjectFile:
5642 case Options::kDyld:
5643 case Options::kPreload:
5644 case Options::kKextBundle:
5645 if ( fZeroPageSize != 0 )
5646 throw "-pagezero_size option can only be used when linking a main executable";
5647 }
5648 }
5649
5650 // if main executable with custom base address, model zero page as custom segment
5651 if ( (fOutputKind == Options::kDynamicExecutable) && (fBaseAddress != 0) && (fZeroPageSize != 0) ) {
5652 SegmentStart seg;
5653 seg.name = "__PAGEZERO";
5654 seg.address = 0;;
5655 fCustomSegmentAddresses.push_back(seg);
5656 }
5657
5658 // -dead_strip and -r are incompatible
5659 if ( fDeadStrip && (fOutputKind == Options::kObjectFile) )
5660 throw "-r and -dead_strip cannot be used together";
5661
5662 // can't use -rpath unless targeting 10.5 or later
5663 if ( fRPaths.size() > 0 ) {
5664 if ( !minOS(ld::mac10_5, ld::iOS_2_0) )
5665 throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
5666 switch ( fOutputKind ) {
5667 case Options::kDynamicExecutable:
5668 case Options::kDynamicLibrary:
5669 case Options::kDynamicBundle:
5670 break;
5671 case Options::kStaticExecutable:
5672 case Options::kObjectFile:
5673 case Options::kDyld:
5674 case Options::kPreload:
5675 case Options::kKextBundle:
5676 throw "-rpath can only be used when creating a dynamic final linked image";
5677 }
5678 }
5679
5680 if ( fPositionIndependentExecutable ) {
5681 switch ( fOutputKind ) {
5682 case Options::kDynamicExecutable:
5683 // check -pie is only used when building a dynamic main executable for 10.5
5684 if ( !minOS(ld::mac10_5, ld::iOS_4_2) ) {
5685 if ( fIOSVersionMin == ld::iOSVersionUnset )
5686 throw "-pie can only be used when targeting Mac OS X 10.5 or later";
5687 else
5688 throw "-pie can only be used when targeting iOS 4.2 or later";
5689 }
5690 break;
5691 case Options::kStaticExecutable:
5692 case Options::kPreload:
5693 // -pie is ok with -static or -preload
5694 break;
5695 case Options::kDynamicLibrary:
5696 case Options::kDynamicBundle:
5697 warning("-pie being ignored. It is only used when linking a main executable");
5698 fPositionIndependentExecutable = false;
5699 break;
5700 case Options::kObjectFile:
5701 case Options::kDyld:
5702 case Options::kKextBundle:
5703 throw "-pie can only be used when linking a main executable";
5704 }
5705 }
5706
5707 // check -read_only_relocs is not used with x86_64
5708 if ( fAllowTextRelocs ) {
5709 if ( (fArchitecture == CPU_TYPE_X86_64) && (fOutputKind != kKextBundle) ) {
5710 warning("-read_only_relocs cannot be used with x86_64");
5711 fAllowTextRelocs = false;
5712 }
5713 }
5714
5715 // check -mark_auto_dead_strip is only used with dylibs
5716 if ( fMarkDeadStrippableDylib ) {
5717 if ( fOutputKind != Options::kDynamicLibrary ) {
5718 warning("-mark_auto_dead_strip can only be used when creating a dylib");
5719 fMarkDeadStrippableDylib = false;
5720 }
5721 }
5722
5723 // -force_cpusubtype_ALL is not supported for ARM
5724 if ( fForceSubtypeAll ) {
5725 if ( fArchitecture == CPU_TYPE_ARM ) {
5726 warning("-force_cpusubtype_ALL will become unsupported for ARM architectures");
5727 }
5728 }
5729
5730 // -reexported_symbols_list can only be used with -dynamiclib
5731 if ( !fReExportSymbols.empty() ) {
5732 if ( fOutputKind != Options::kDynamicLibrary )
5733 throw "-reexported_symbols_list can only used used when created dynamic libraries";
5734 if ( !minOS(ld::mac10_7, ld::iOS_4_2) )
5735 throw "targeted OS version does not support -reexported_symbols_list";
5736 }
5737
5738 // -dyld_env can only be used with main executables
5739 if ( (fOutputKind != Options::kDynamicExecutable) && (fDyldEnvironExtras.size() != 0) )
5740 throw "-dyld_env can only used used when created main executables";
5741
5742 // -segment_order can only be used with -preload or -static
5743 if ( !fSegmentOrder.empty() && ((fOutputKind != Options::kPreload) && (fOutputKind != kStaticExecutable)) )
5744 throw "-segment_order can only used used with -preload output";
5745
5746 // warn about bitcode option combinations
5747 if ( !fBundleBitcode ) {
5748 if ( fVerifyBitcode )
5749 warning("-bitcode_verify is ignored without -bitcode_bundle");
5750 else if ( fHideSymbols )
5751 warning("-bitcode_hide_symbols is ignored without -bitcode_bundle");
5752 }
5753 if ( fReverseMapPath != NULL && !fHideSymbols ) {
5754 throw "-bitcode_symbol_map can only be used with -bitcode_hide_symbols";
5755 }
5756 // auto fix up the process type for strip -S.
5757 // when there is only one input and output type is object file, downgrade kBitcodeProcess to kBitcodeAsData.
5758 if ( fOutputKind == Options::kObjectFile && fInputFiles.size() == 1 && fBitcodeKind == Options::kBitcodeProcess )
5759 fBitcodeKind = Options::kBitcodeAsData;
5760
5761 // <rdar://problem/17598404> warn if building an embedded iOS dylib for pre-iOS 8
5762 // <rdar://problem/18935714> How can we suppress "ld: warning: embedded dylibs/frameworks only run on iOS 8 or later" when building XCTest?
5763 if ( (fOutputKind == Options::kDynamicLibrary) && (fIOSVersionMin != ld::iOSVersionUnset) && (fDylibInstallName != NULL) ) {
5764 if ( !min_iOS(ld::iOS_8_0) && (fDylibInstallName[0] == '@') && !fEncryptableForceOff )
5765 warning("embedded dylibs/frameworks only run on iOS 8 or later");
5766 }
5767
5768 // bridgeOS always generates new load command
5769 if ( fVersionLoadCommand && (fPlatform == kPlatform_bridgeOS) ) {
5770 fBuildVersionLoadCommand = true;
5771 }
5772
5773 // produce nicer error when no input
5774 if ( fInputFiles.empty() ) {
5775 throw "no object files specified";
5776 }
5777 }
5778
5779
5780 void Options::checkForClassic(int argc, const char* argv[])
5781 {
5782 // scan options
5783 bool archFound = false;
5784 bool staticFound = false;
5785 bool dtraceFound = false;
5786 bool kextFound = false;
5787 bool rFound = false;
5788 bool creatingMachKernel = false;
5789 bool newLinker = false;
5790
5791 // build command line buffer in case ld crashes
5792 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
5793 CRSetCrashLogMessage(crashreporterBuffer);
5794 #endif
5795 const char* srcRoot = getenv("SRCROOT");
5796 if ( srcRoot != NULL ) {
5797 strlcpy(crashreporterBuffer, "SRCROOT=", crashreporterBufferSize);
5798 strlcat(crashreporterBuffer, srcRoot, crashreporterBufferSize);
5799 strlcat(crashreporterBuffer, "\n", crashreporterBufferSize);
5800 }
5801 #ifdef LD_VERS
5802 strlcat(crashreporterBuffer, LD_VERS, crashreporterBufferSize);
5803 strlcat(crashreporterBuffer, "\n", crashreporterBufferSize);
5804 #endif
5805 strlcat(crashreporterBuffer, "ld ", crashreporterBufferSize);
5806 for(int i=1; i < argc; ++i) {
5807 strlcat(crashreporterBuffer, argv[i], crashreporterBufferSize);
5808 strlcat(crashreporterBuffer, " ", crashreporterBufferSize);
5809 }
5810
5811 for(int i=0; i < argc; ++i) {
5812 const char* arg = argv[i];
5813 if ( arg[0] == '-' ) {
5814 if ( strcmp(arg, "-arch") == 0 ) {
5815 parseArch(argv[++i]);
5816 archFound = true;
5817 }
5818 else if ( strcmp(arg, "-static") == 0 ) {
5819 staticFound = true;
5820 }
5821 else if ( strcmp(arg, "-kext") == 0 ) {
5822 kextFound = true;
5823 }
5824 else if ( strcmp(arg, "-dtrace") == 0 ) {
5825 dtraceFound = true;
5826 }
5827 else if ( strcmp(arg, "-r") == 0 ) {
5828 rFound = true;
5829 }
5830 else if ( strcmp(arg, "-new_linker") == 0 ) {
5831 newLinker = true;
5832 }
5833 else if ( strcmp(arg, "-classic_linker") == 0 ) {
5834 // ld_classic does not understand this option, so remove it
5835 for(int j=i; j < argc; ++j)
5836 argv[j] = argv[j+1];
5837 warning("using ld_classic");
5838 this->gotoClassicLinker(argc-1, argv);
5839 }
5840 else if ( strcmp(arg, "-o") == 0 ) {
5841 const char* outfile = argv[++i];
5842 if ( (outfile != NULL) && (strstr(outfile, "/mach_kernel") != NULL) )
5843 creatingMachKernel = true;
5844 }
5845 }
5846 }
5847 }
5848
5849 void Options::gotoClassicLinker(int argc, const char* argv[])
5850 {
5851 argv[0] = "ld_classic";
5852 // ld_classic does not support -iphoneos_version_min, so change
5853 for(int j=0; j < argc; ++j) {
5854 if ( (strcmp(argv[j], "-iphoneos_version_min") == 0) || (strcmp(argv[j], "-ios_version_min") == 0) ) {
5855 argv[j] = "-macosx_version_min";
5856 if ( j < argc-1 )
5857 argv[j+1] = "10.5";
5858 break;
5859 }
5860 }
5861 // ld classic does not understand -kext (change to -static -r)
5862 for(int j=0; j < argc; ++j) {
5863 if ( strcmp(argv[j], "-kext") == 0)
5864 argv[j] = "-r";
5865 else if ( strcmp(argv[j], "-dynamic") == 0)
5866 argv[j] = "-static";
5867 }
5868 // ld classic does not understand -demangle
5869 for(int j=0; j < argc; ++j) {
5870 if ( strcmp(argv[j], "-demangle") == 0)
5871 argv[j] = "-noprebind";
5872 }
5873 // in -v mode, print command line passed to ld_classic
5874 for(int i=0; i < argc; ++i) {
5875 if ( strcmp(argv[i], "-v") == 0 ) {
5876 for(int j=0; j < argc; ++j)
5877 printf("%s ", argv[j]);
5878 printf("\n");
5879 break;
5880 }
5881 }
5882 char rawPath[PATH_MAX];
5883 char path[PATH_MAX];
5884 uint32_t bufSize = PATH_MAX;
5885 if ( _NSGetExecutablePath(rawPath, &bufSize) != -1 ) {
5886 if ( realpath(rawPath, path) != NULL ) {
5887 char* lastSlash = strrchr(path, '/');
5888 if ( lastSlash != NULL ) {
5889 strcpy(lastSlash+1, "ld_classic");
5890 argv[0] = path;
5891 execvp(path, (char**)argv);
5892 }
5893 }
5894 }
5895 // in case of error in above, try searching for ld_classic via PATH
5896 execvp(argv[0], (char**)argv);
5897 fprintf(stderr, "can't exec ld_classic\n");
5898 exit(1);
5899 }
5900
5901
5902 // Note, returned string buffer is own by this function.
5903 // It should not be freed
5904 // It will be reused, so clients need to strdup() if they want
5905 // to use it long term.
5906 const char* Options::demangleSymbol(const char* sym) const
5907 {
5908 // only try to demangle symbols if -demangle on command line
5909 if ( !fDemangle )
5910 return sym;
5911
5912 static size_t size = 1024;
5913 static char* buff = (char*)malloc(size);
5914
5915 #if DEMANGLE_SWIFT
5916 // only try to demangle symbols that look like Swift symbols
5917 if ( strncmp(sym, "__T", 3) == 0 ) {
5918 size_t demangledSize = fnd_get_demangled_name(&sym[1], buff, size);
5919 if ( demangledSize > size ) {
5920 size = demangledSize+2;
5921 buff = (char*)realloc(buff, size);
5922 demangledSize = fnd_get_demangled_name(&sym[1], buff, size);
5923 }
5924 if ( demangledSize != 0 )
5925 return buff;
5926 }
5927 #endif
5928
5929 // only try to demangle symbols that look like C++ symbols
5930 if ( strncmp(sym, "__Z", 3) != 0 )
5931 return sym;
5932
5933 int status;
5934 char* result = abi::__cxa_demangle(&sym[1], buff, &size, &status);
5935 if ( result != NULL ) {
5936 // if demangling successful, keep buffer for next demangle
5937 buff = result;
5938 return buff;
5939 }
5940 return sym;
5941 }
5942
5943
5944 void Options::dumpDependency(uint8_t opcode, const char* path) const
5945 {
5946 if ( !this->dumpDependencyInfo() )
5947 return;
5948
5949 // one time open() of -dependency_info file
5950 if ( fDependencyFileDescriptor == -1 ) {
5951 fDependencyFileDescriptor = open(this->dependencyInfoPath(), O_WRONLY | O_TRUNC | O_CREAT, 0666);
5952 if ( fDependencyFileDescriptor == -1 )
5953 throwf("Could not open or create -dependency_info file: %s", this->dependencyInfoPath());
5954
5955 // write header
5956 uint8_t version = depLinkerVersion;
5957 if ( write(fDependencyFileDescriptor, &version, 1) == -1 )
5958 throwf("write() to -dependency_info failed, errno=%d", errno);
5959 extern const char ldVersionString[];
5960 if ( write(fDependencyFileDescriptor, ldVersionString, strlen(ldVersionString)+1) == -1 )
5961 throwf("write() to -dependency_info failed, errno=%d", errno);
5962 }
5963
5964 char realPath[PATH_MAX];
5965 if ( path[0] != '/' ) {
5966 if ( realpath(path, realPath) != NULL ) {
5967 path = realPath;
5968 }
5969 }
5970
5971 if ( write(fDependencyFileDescriptor, &opcode, 1) == -1 )
5972 throwf("write() to -dependency_info failed, errno=%d", errno);
5973 if ( write(fDependencyFileDescriptor, path, strlen(path)+1) == -1 )
5974 throwf("write() to -dependency_info failed, errno=%d", errno);
5975
5976 //fprintf(stderr, "0x%02X %s\n", opcode, path);
5977 }
5978
5979
5980 void Options::writeToTraceFile(const char* buffer, size_t len) const
5981 {
5982 // one time open() of custom LD_TRACE_FILE
5983 if ( fTraceFileDescriptor == -1 ) {
5984 if ( fTraceOutputFile != NULL ) {
5985 fTraceFileDescriptor = open(fTraceOutputFile, O_WRONLY | O_APPEND | O_CREAT, 0666);
5986 if ( fTraceFileDescriptor == -1 )
5987 throwf("Could not open or create trace file (errno=%d): %s", errno, fTraceOutputFile);
5988 }
5989 else {
5990 fTraceFileDescriptor = fileno(stderr);
5991 }
5992 }
5993
5994 while (len > 0) {
5995 ssize_t amountWritten = write(fTraceFileDescriptor, buffer, len);
5996 if ( amountWritten == -1 )
5997 /* Failure to write shouldn't fail the build. */
5998 return;
5999 buffer += amountWritten;
6000 len -= amountWritten;
6001 }
6002 }
6003
6004