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