MachOLinkingContext.cpp revision 303239
1280461Sdim//===- lib/ReaderWriter/MachO/MachOLinkingContext.cpp ---------------------===//
2280461Sdim//
3280461Sdim//                             The LLVM Linker
4280461Sdim//
5280461Sdim// This file is distributed under the University of Illinois Open Source
6280461Sdim// License. See LICENSE.TXT for details.
7280461Sdim//
8280461Sdim//===----------------------------------------------------------------------===//
9280461Sdim
10280461Sdim#include "lld/ReaderWriter/MachOLinkingContext.h"
11280461Sdim#include "ArchHandler.h"
12280461Sdim#include "File.h"
13292934Sdim#include "FlatNamespaceFile.h"
14280461Sdim#include "MachONormalizedFile.h"
15280461Sdim#include "MachOPasses.h"
16292934Sdim#include "SectCreateFile.h"
17280461Sdim#include "lld/Core/ArchiveLibraryFile.h"
18280461Sdim#include "lld/Core/PassManager.h"
19280461Sdim#include "lld/Core/Reader.h"
20280461Sdim#include "lld/Core/Writer.h"
21280461Sdim#include "lld/Driver/Driver.h"
22280461Sdim#include "llvm/ADT/STLExtras.h"
23280461Sdim#include "llvm/ADT/StringExtras.h"
24280461Sdim#include "llvm/ADT/Triple.h"
25280461Sdim#include "llvm/Config/config.h"
26280461Sdim#include "llvm/Support/Debug.h"
27280461Sdim#include "llvm/Support/Errc.h"
28280461Sdim#include "llvm/Support/Host.h"
29280461Sdim#include "llvm/Support/MachO.h"
30280461Sdim#include "llvm/Support/Path.h"
31280461Sdim#include <algorithm>
32280461Sdim
33280461Sdim#if defined(HAVE_CXXABI_H)
34280461Sdim#include <cxxabi.h>
35280461Sdim#endif
36280461Sdim
37280461Sdimusing lld::mach_o::ArchHandler;
38303239Sdimusing lld::mach_o::MachOFile;
39280461Sdimusing lld::mach_o::MachODylibFile;
40280461Sdimusing namespace llvm::MachO;
41280461Sdim
42280461Sdimnamespace lld {
43280461Sdim
44280461Sdimbool MachOLinkingContext::parsePackedVersion(StringRef str, uint32_t &result) {
45280461Sdim  result = 0;
46280461Sdim
47280461Sdim  if (str.empty())
48280461Sdim    return false;
49280461Sdim
50280461Sdim  SmallVector<StringRef, 3> parts;
51280461Sdim  llvm::SplitString(str, parts, ".");
52280461Sdim
53280461Sdim  unsigned long long num;
54280461Sdim  if (llvm::getAsUnsignedInteger(parts[0], 10, num))
55280461Sdim    return true;
56280461Sdim  if (num > 65535)
57280461Sdim    return true;
58280461Sdim  result = num << 16;
59280461Sdim
60280461Sdim  if (parts.size() > 1) {
61280461Sdim    if (llvm::getAsUnsignedInteger(parts[1], 10, num))
62280461Sdim      return true;
63280461Sdim    if (num > 255)
64280461Sdim      return true;
65280461Sdim    result |= (num << 8);
66280461Sdim  }
67280461Sdim
68280461Sdim  if (parts.size() > 2) {
69280461Sdim    if (llvm::getAsUnsignedInteger(parts[2], 10, num))
70280461Sdim      return true;
71280461Sdim    if (num > 255)
72280461Sdim      return true;
73280461Sdim    result |= num;
74280461Sdim  }
75280461Sdim
76280461Sdim  return false;
77280461Sdim}
78280461Sdim
79303239Sdimbool MachOLinkingContext::parsePackedVersion(StringRef str, uint64_t &result) {
80303239Sdim  result = 0;
81303239Sdim
82303239Sdim  if (str.empty())
83303239Sdim    return false;
84303239Sdim
85303239Sdim  SmallVector<StringRef, 5> parts;
86303239Sdim  llvm::SplitString(str, parts, ".");
87303239Sdim
88303239Sdim  unsigned long long num;
89303239Sdim  if (llvm::getAsUnsignedInteger(parts[0], 10, num))
90303239Sdim    return true;
91303239Sdim  if (num > 0xFFFFFF)
92303239Sdim    return true;
93303239Sdim  result = num << 40;
94303239Sdim
95303239Sdim  unsigned Shift = 30;
96303239Sdim  for (StringRef str : llvm::makeArrayRef(parts).slice(1)) {
97303239Sdim    if (llvm::getAsUnsignedInteger(str, 10, num))
98303239Sdim      return true;
99303239Sdim    if (num > 0x3FF)
100303239Sdim      return true;
101303239Sdim    result |= (num << Shift);
102303239Sdim    Shift -= 10;
103303239Sdim  }
104303239Sdim
105303239Sdim  return false;
106303239Sdim}
107303239Sdim
108280461SdimMachOLinkingContext::ArchInfo MachOLinkingContext::_s_archInfos[] = {
109280461Sdim  { "x86_64", arch_x86_64, true,  CPU_TYPE_X86_64,  CPU_SUBTYPE_X86_64_ALL },
110280461Sdim  { "i386",   arch_x86,    true,  CPU_TYPE_I386,    CPU_SUBTYPE_X86_ALL },
111280461Sdim  { "ppc",    arch_ppc,    false, CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL },
112280461Sdim  { "armv6",  arch_armv6,  true,  CPU_TYPE_ARM,     CPU_SUBTYPE_ARM_V6 },
113280461Sdim  { "armv7",  arch_armv7,  true,  CPU_TYPE_ARM,     CPU_SUBTYPE_ARM_V7 },
114280461Sdim  { "armv7s", arch_armv7s, true,  CPU_TYPE_ARM,     CPU_SUBTYPE_ARM_V7S },
115280461Sdim  { "arm64",  arch_arm64,  true,  CPU_TYPE_ARM64,   CPU_SUBTYPE_ARM64_ALL },
116280461Sdim  { "",       arch_unknown,false, 0,                0 }
117280461Sdim};
118280461Sdim
119280461SdimMachOLinkingContext::Arch
120280461SdimMachOLinkingContext::archFromCpuType(uint32_t cputype, uint32_t cpusubtype) {
121280461Sdim  for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
122280461Sdim    if ((info->cputype == cputype) && (info->cpusubtype == cpusubtype))
123280461Sdim      return info->arch;
124280461Sdim  }
125280461Sdim  return arch_unknown;
126280461Sdim}
127280461Sdim
128280461SdimMachOLinkingContext::Arch
129280461SdimMachOLinkingContext::archFromName(StringRef archName) {
130280461Sdim  for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
131280461Sdim    if (info->archName.equals(archName))
132280461Sdim      return info->arch;
133280461Sdim  }
134280461Sdim  return arch_unknown;
135280461Sdim}
136280461Sdim
137280461SdimStringRef MachOLinkingContext::nameFromArch(Arch arch) {
138280461Sdim  for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
139280461Sdim    if (info->arch == arch)
140280461Sdim      return info->archName;
141280461Sdim  }
142280461Sdim  return "<unknown>";
143280461Sdim}
144280461Sdim
145280461Sdimuint32_t MachOLinkingContext::cpuTypeFromArch(Arch arch) {
146280461Sdim  assert(arch != arch_unknown);
147280461Sdim  for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
148280461Sdim    if (info->arch == arch)
149280461Sdim      return info->cputype;
150280461Sdim  }
151280461Sdim  llvm_unreachable("Unknown arch type");
152280461Sdim}
153280461Sdim
154280461Sdimuint32_t MachOLinkingContext::cpuSubtypeFromArch(Arch arch) {
155280461Sdim  assert(arch != arch_unknown);
156280461Sdim  for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
157280461Sdim    if (info->arch == arch)
158280461Sdim      return info->cpusubtype;
159280461Sdim  }
160280461Sdim  llvm_unreachable("Unknown arch type");
161280461Sdim}
162280461Sdim
163280461Sdimbool MachOLinkingContext::isThinObjectFile(StringRef path, Arch &arch) {
164280461Sdim  return mach_o::normalized::isThinObjectFile(path, arch);
165280461Sdim}
166280461Sdim
167292934Sdimbool MachOLinkingContext::sliceFromFatFile(MemoryBufferRef mb, uint32_t &offset,
168280461Sdim                                           uint32_t &size) {
169280461Sdim  return mach_o::normalized::sliceFromFatFile(mb, _arch, offset, size);
170280461Sdim}
171280461Sdim
172303239SdimMachOLinkingContext::MachOLinkingContext() {}
173280461Sdim
174303239SdimMachOLinkingContext::~MachOLinkingContext() {
175303239Sdim  // Atoms are allocated on BumpPtrAllocator's on File's.
176303239Sdim  // As we transfer atoms from one file to another, we need to clear all of the
177303239Sdim  // atoms before we remove any of the BumpPtrAllocator's.
178303239Sdim  auto &nodes = getNodes();
179303239Sdim  for (unsigned i = 0, e = nodes.size(); i != e; ++i) {
180303239Sdim    FileNode *node = dyn_cast<FileNode>(nodes[i].get());
181303239Sdim    if (!node)
182303239Sdim      continue;
183303239Sdim    File *file = node->getFile();
184303239Sdim    file->clearAtoms();
185303239Sdim  }
186303239Sdim}
187280461Sdim
188280461Sdimvoid MachOLinkingContext::configure(HeaderFileType type, Arch arch, OS os,
189303239Sdim                                    uint32_t minOSVersion,
190303239Sdim                                    bool exportDynamicSymbols) {
191280461Sdim  _outputMachOType = type;
192280461Sdim  _arch = arch;
193280461Sdim  _os = os;
194280461Sdim  _osMinVersion = minOSVersion;
195280461Sdim
196280461Sdim  // If min OS not specified on command line, use reasonable defaults.
197303239Sdim  // Note that we only do sensible defaults when emitting something other than
198303239Sdim  // object and preload.
199303239Sdim  if (_outputMachOType != llvm::MachO::MH_OBJECT &&
200303239Sdim      _outputMachOType != llvm::MachO::MH_PRELOAD) {
201303239Sdim    if (minOSVersion == 0) {
202303239Sdim      switch (_arch) {
203303239Sdim      case arch_x86_64:
204303239Sdim      case arch_x86:
205303239Sdim        parsePackedVersion("10.8", _osMinVersion);
206303239Sdim        _os = MachOLinkingContext::OS::macOSX;
207303239Sdim        break;
208303239Sdim      case arch_armv6:
209303239Sdim      case arch_armv7:
210303239Sdim      case arch_armv7s:
211303239Sdim      case arch_arm64:
212303239Sdim        parsePackedVersion("7.0", _osMinVersion);
213303239Sdim        _os = MachOLinkingContext::OS::iOS;
214303239Sdim        break;
215303239Sdim      default:
216303239Sdim        break;
217303239Sdim      }
218280461Sdim    }
219280461Sdim  }
220280461Sdim
221280461Sdim  switch (_outputMachOType) {
222280461Sdim  case llvm::MachO::MH_EXECUTE:
223280461Sdim    // If targeting newer OS, use _main
224280461Sdim    if (minOS("10.8", "6.0")) {
225280461Sdim      _entrySymbolName = "_main";
226280461Sdim    } else {
227280461Sdim      // If targeting older OS, use start (in crt1.o)
228280461Sdim      _entrySymbolName = "start";
229280461Sdim    }
230280461Sdim
231280461Sdim    // __PAGEZERO defaults to 4GB on 64-bit (except for PP64 which lld does not
232280461Sdim    // support) and 4KB on 32-bit.
233280461Sdim    if (is64Bit(_arch)) {
234280461Sdim      _pageZeroSize = 0x100000000;
235280461Sdim    } else {
236280461Sdim      _pageZeroSize = 0x1000;
237280461Sdim    }
238280461Sdim
239292934Sdim    // Initial base address is __PAGEZERO size.
240292934Sdim    _baseAddress = _pageZeroSize;
241292934Sdim
242280461Sdim    // Make PIE by default when targetting newer OSs.
243280461Sdim    switch (os) {
244280461Sdim      case OS::macOSX:
245280461Sdim        if (minOSVersion >= 0x000A0700) // MacOSX 10.7
246280461Sdim          _pie = true;
247280461Sdim        break;
248280461Sdim      case OS::iOS:
249280461Sdim        if (minOSVersion >= 0x00040300) // iOS 4.3
250280461Sdim          _pie = true;
251280461Sdim       break;
252280461Sdim       case OS::iOS_simulator:
253280461Sdim        _pie = true;
254280461Sdim       break;
255280461Sdim       case OS::unknown:
256280461Sdim       break;
257280461Sdim    }
258303239Sdim    setGlobalsAreDeadStripRoots(exportDynamicSymbols);
259280461Sdim    break;
260280461Sdim  case llvm::MachO::MH_DYLIB:
261303239Sdim    setGlobalsAreDeadStripRoots(exportDynamicSymbols);
262280461Sdim    break;
263280461Sdim  case llvm::MachO::MH_BUNDLE:
264280461Sdim    break;
265280461Sdim  case llvm::MachO::MH_OBJECT:
266280461Sdim    _printRemainingUndefines = false;
267280461Sdim    _allowRemainingUndefines = true;
268280461Sdim  default:
269280461Sdim    break;
270280461Sdim  }
271280461Sdim
272280461Sdim  // Set default segment page sizes based on arch.
273280461Sdim  if (arch == arch_arm64)
274280461Sdim    _pageSize = 4*4096;
275280461Sdim}
276280461Sdim
277280461Sdimuint32_t MachOLinkingContext::getCPUType() const {
278280461Sdim  return cpuTypeFromArch(_arch);
279280461Sdim}
280280461Sdim
281280461Sdimuint32_t MachOLinkingContext::getCPUSubType() const {
282280461Sdim  return cpuSubtypeFromArch(_arch);
283280461Sdim}
284280461Sdim
285280461Sdimbool MachOLinkingContext::is64Bit(Arch arch) {
286280461Sdim  for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
287280461Sdim    if (info->arch == arch) {
288280461Sdim      return (info->cputype & CPU_ARCH_ABI64);
289280461Sdim    }
290280461Sdim  }
291280461Sdim  // unknown archs are not 64-bit.
292280461Sdim  return false;
293280461Sdim}
294280461Sdim
295280461Sdimbool MachOLinkingContext::isHostEndian(Arch arch) {
296280461Sdim  assert(arch != arch_unknown);
297280461Sdim  for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
298280461Sdim    if (info->arch == arch) {
299280461Sdim      return (info->littleEndian == llvm::sys::IsLittleEndianHost);
300280461Sdim    }
301280461Sdim  }
302280461Sdim  llvm_unreachable("Unknown arch type");
303280461Sdim}
304280461Sdim
305280461Sdimbool MachOLinkingContext::isBigEndian(Arch arch) {
306280461Sdim  assert(arch != arch_unknown);
307280461Sdim  for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
308280461Sdim    if (info->arch == arch) {
309280461Sdim      return ! info->littleEndian;
310280461Sdim    }
311280461Sdim  }
312280461Sdim  llvm_unreachable("Unknown arch type");
313280461Sdim}
314280461Sdim
315280461Sdimbool MachOLinkingContext::is64Bit() const {
316280461Sdim  return is64Bit(_arch);
317280461Sdim}
318280461Sdim
319280461Sdimbool MachOLinkingContext::outputTypeHasEntry() const {
320280461Sdim  switch (_outputMachOType) {
321280461Sdim  case MH_EXECUTE:
322280461Sdim  case MH_DYLINKER:
323280461Sdim  case MH_PRELOAD:
324280461Sdim    return true;
325280461Sdim  default:
326280461Sdim    return false;
327280461Sdim  }
328280461Sdim}
329280461Sdim
330280461Sdimbool MachOLinkingContext::needsStubsPass() const {
331280461Sdim  switch (_outputMachOType) {
332280461Sdim  case MH_EXECUTE:
333280461Sdim    return !_outputMachOTypeStatic;
334280461Sdim  case MH_DYLIB:
335280461Sdim  case MH_BUNDLE:
336280461Sdim    return true;
337280461Sdim  default:
338280461Sdim    return false;
339280461Sdim  }
340280461Sdim}
341280461Sdim
342280461Sdimbool MachOLinkingContext::needsGOTPass() const {
343280461Sdim  // GOT pass not used in -r mode.
344280461Sdim  if (_outputMachOType == MH_OBJECT)
345280461Sdim    return false;
346280461Sdim  // Only some arches use GOT pass.
347280461Sdim  switch (_arch) {
348280461Sdim    case arch_x86_64:
349280461Sdim    case arch_arm64:
350280461Sdim      return true;
351280461Sdim    default:
352280461Sdim      return false;
353280461Sdim  }
354280461Sdim}
355280461Sdim
356280461Sdimbool MachOLinkingContext::needsCompactUnwindPass() const {
357280461Sdim  switch (_outputMachOType) {
358280461Sdim  case MH_EXECUTE:
359280461Sdim  case MH_DYLIB:
360280461Sdim  case MH_BUNDLE:
361280461Sdim    return archHandler().needsCompactUnwind();
362280461Sdim  default:
363280461Sdim    return false;
364280461Sdim  }
365280461Sdim}
366280461Sdim
367303239Sdimbool MachOLinkingContext::needsObjCPass() const {
368303239Sdim  // ObjC pass is only needed if any of the inputs were ObjC.
369303239Sdim  return _objcConstraint != objc_unknown;
370303239Sdim}
371303239Sdim
372280461Sdimbool MachOLinkingContext::needsShimPass() const {
373280461Sdim  // Shim pass only used in final executables.
374280461Sdim  if (_outputMachOType == MH_OBJECT)
375280461Sdim    return false;
376280461Sdim  // Only 32-bit arm arches use Shim pass.
377280461Sdim  switch (_arch) {
378280461Sdim  case arch_armv6:
379280461Sdim  case arch_armv7:
380280461Sdim  case arch_armv7s:
381280461Sdim    return true;
382280461Sdim  default:
383280461Sdim    return false;
384280461Sdim  }
385280461Sdim}
386280461Sdim
387292934Sdimbool MachOLinkingContext::needsTLVPass() const {
388292934Sdim  switch (_outputMachOType) {
389292934Sdim  case MH_BUNDLE:
390292934Sdim  case MH_EXECUTE:
391292934Sdim  case MH_DYLIB:
392292934Sdim    return true;
393292934Sdim  default:
394292934Sdim    return false;
395292934Sdim  }
396292934Sdim}
397292934Sdim
398280461SdimStringRef MachOLinkingContext::binderSymbolName() const {
399280461Sdim  return archHandler().stubInfo().binderSymbolName;
400280461Sdim}
401280461Sdim
402280461Sdimbool MachOLinkingContext::minOS(StringRef mac, StringRef iOS) const {
403280461Sdim  uint32_t parsedVersion;
404280461Sdim  switch (_os) {
405280461Sdim  case OS::macOSX:
406280461Sdim    if (parsePackedVersion(mac, parsedVersion))
407280461Sdim      return false;
408280461Sdim    return _osMinVersion >= parsedVersion;
409280461Sdim  case OS::iOS:
410280461Sdim  case OS::iOS_simulator:
411280461Sdim    if (parsePackedVersion(iOS, parsedVersion))
412280461Sdim      return false;
413280461Sdim    return _osMinVersion >= parsedVersion;
414280461Sdim  case OS::unknown:
415303239Sdim    // If we don't know the target, then assume that we don't meet the min OS.
416303239Sdim    // This matches the ld64 behaviour
417303239Sdim    return false;
418280461Sdim  }
419303239Sdim  llvm_unreachable("invalid OS enum");
420280461Sdim}
421280461Sdim
422280461Sdimbool MachOLinkingContext::addEntryPointLoadCommand() const {
423280461Sdim  if ((_outputMachOType == MH_EXECUTE) && !_outputMachOTypeStatic) {
424280461Sdim    return minOS("10.8", "6.0");
425280461Sdim  }
426280461Sdim  return false;
427280461Sdim}
428280461Sdim
429280461Sdimbool MachOLinkingContext::addUnixThreadLoadCommand() const {
430280461Sdim  switch (_outputMachOType) {
431280461Sdim  case MH_EXECUTE:
432280461Sdim    if (_outputMachOTypeStatic)
433280461Sdim      return true;
434280461Sdim    else
435280461Sdim      return !minOS("10.8", "6.0");
436280461Sdim    break;
437280461Sdim  case MH_DYLINKER:
438280461Sdim  case MH_PRELOAD:
439280461Sdim    return true;
440280461Sdim  default:
441280461Sdim    return false;
442280461Sdim  }
443280461Sdim}
444280461Sdim
445280461Sdimbool MachOLinkingContext::pathExists(StringRef path) const {
446280461Sdim  if (!_testingFileUsage)
447280461Sdim    return llvm::sys::fs::exists(path.str());
448280461Sdim
449280461Sdim  // Otherwise, we're in test mode: only files explicitly provided on the
450280461Sdim  // command-line exist.
451280461Sdim  std::string key = path.str();
452280461Sdim  std::replace(key.begin(), key.end(), '\\', '/');
453280461Sdim  return _existingPaths.find(key) != _existingPaths.end();
454280461Sdim}
455280461Sdim
456280461Sdimbool MachOLinkingContext::fileExists(StringRef path) const {
457280461Sdim  bool found = pathExists(path);
458280461Sdim  // Log search misses.
459280461Sdim  if (!found)
460280461Sdim    addInputFileNotFound(path);
461280461Sdim
462280461Sdim  // When testing, file is never opened, so logging is done here.
463280461Sdim  if (_testingFileUsage && found)
464280461Sdim    addInputFileDependency(path);
465280461Sdim
466280461Sdim  return found;
467280461Sdim}
468280461Sdim
469280461Sdimvoid MachOLinkingContext::setSysLibRoots(const StringRefVector &paths) {
470280461Sdim  _syslibRoots = paths;
471280461Sdim}
472280461Sdim
473280461Sdimvoid MachOLinkingContext::addRpath(StringRef rpath) {
474280461Sdim  _rpaths.push_back(rpath);
475280461Sdim}
476280461Sdim
477280461Sdimvoid MachOLinkingContext::addModifiedSearchDir(StringRef libPath,
478280461Sdim                                               bool isSystemPath) {
479280461Sdim  bool addedModifiedPath = false;
480280461Sdim
481280461Sdim  // -syslibroot only applies to absolute paths.
482280461Sdim  if (libPath.startswith("/")) {
483280461Sdim    for (auto syslibRoot : _syslibRoots) {
484280461Sdim      SmallString<256> path(syslibRoot);
485280461Sdim      llvm::sys::path::append(path, libPath);
486280461Sdim      if (pathExists(path)) {
487280461Sdim        _searchDirs.push_back(path.str().copy(_allocator));
488280461Sdim        addedModifiedPath = true;
489280461Sdim      }
490280461Sdim    }
491280461Sdim  }
492280461Sdim
493280461Sdim  if (addedModifiedPath)
494280461Sdim    return;
495280461Sdim
496280461Sdim  // Finally, if only one -syslibroot is given, system paths which aren't in it
497280461Sdim  // get suppressed.
498280461Sdim  if (_syslibRoots.size() != 1 || !isSystemPath) {
499280461Sdim    if (pathExists(libPath)) {
500280461Sdim      _searchDirs.push_back(libPath);
501280461Sdim    }
502280461Sdim  }
503280461Sdim}
504280461Sdim
505280461Sdimvoid MachOLinkingContext::addFrameworkSearchDir(StringRef fwPath,
506280461Sdim                                                bool isSystemPath) {
507280461Sdim  bool pathAdded = false;
508280461Sdim
509280461Sdim  // -syslibroot only used with to absolute framework search paths.
510280461Sdim  if (fwPath.startswith("/")) {
511280461Sdim    for (auto syslibRoot : _syslibRoots) {
512280461Sdim      SmallString<256> path(syslibRoot);
513280461Sdim      llvm::sys::path::append(path, fwPath);
514280461Sdim      if (pathExists(path)) {
515280461Sdim        _frameworkDirs.push_back(path.str().copy(_allocator));
516280461Sdim        pathAdded = true;
517280461Sdim      }
518280461Sdim    }
519280461Sdim  }
520280461Sdim  // If fwPath found in any -syslibroot, then done.
521280461Sdim  if (pathAdded)
522280461Sdim    return;
523280461Sdim
524280461Sdim  // If only one -syslibroot, system paths not in that SDK are suppressed.
525280461Sdim  if (isSystemPath && (_syslibRoots.size() == 1))
526280461Sdim    return;
527280461Sdim
528280461Sdim  // Only use raw fwPath if that directory exists.
529280461Sdim  if (pathExists(fwPath))
530280461Sdim    _frameworkDirs.push_back(fwPath);
531280461Sdim}
532280461Sdim
533303239Sdimllvm::Optional<StringRef>
534280461SdimMachOLinkingContext::searchDirForLibrary(StringRef path,
535280461Sdim                                         StringRef libName) const {
536280461Sdim  SmallString<256> fullPath;
537280461Sdim  if (libName.endswith(".o")) {
538280461Sdim    // A request ending in .o is special: just search for the file directly.
539280461Sdim    fullPath.assign(path);
540280461Sdim    llvm::sys::path::append(fullPath, libName);
541280461Sdim    if (fileExists(fullPath))
542280461Sdim      return fullPath.str().copy(_allocator);
543303239Sdim    return llvm::None;
544280461Sdim  }
545280461Sdim
546280461Sdim  // Search for dynamic library
547280461Sdim  fullPath.assign(path);
548280461Sdim  llvm::sys::path::append(fullPath, Twine("lib") + libName + ".dylib");
549280461Sdim  if (fileExists(fullPath))
550280461Sdim    return fullPath.str().copy(_allocator);
551280461Sdim
552280461Sdim  // If not, try for a static library
553280461Sdim  fullPath.assign(path);
554280461Sdim  llvm::sys::path::append(fullPath, Twine("lib") + libName + ".a");
555280461Sdim  if (fileExists(fullPath))
556280461Sdim    return fullPath.str().copy(_allocator);
557280461Sdim
558303239Sdim  return llvm::None;
559280461Sdim}
560280461Sdim
561303239Sdimllvm::Optional<StringRef>
562303239SdimMachOLinkingContext::searchLibrary(StringRef libName) const {
563280461Sdim  SmallString<256> path;
564280461Sdim  for (StringRef dir : searchDirs()) {
565303239Sdim    llvm::Optional<StringRef> searchDir = searchDirForLibrary(dir, libName);
566303239Sdim    if (searchDir)
567303239Sdim      return searchDir;
568280461Sdim  }
569280461Sdim
570303239Sdim  return llvm::None;
571280461Sdim}
572280461Sdim
573303239Sdimllvm::Optional<StringRef>
574303239SdimMachOLinkingContext::findPathForFramework(StringRef fwName) const{
575280461Sdim  SmallString<256> fullPath;
576280461Sdim  for (StringRef dir : frameworkDirs()) {
577280461Sdim    fullPath.assign(dir);
578280461Sdim    llvm::sys::path::append(fullPath, Twine(fwName) + ".framework", fwName);
579280461Sdim    if (fileExists(fullPath))
580280461Sdim      return fullPath.str().copy(_allocator);
581280461Sdim  }
582280461Sdim
583303239Sdim  return llvm::None;
584280461Sdim}
585280461Sdim
586280461Sdimbool MachOLinkingContext::validateImpl(raw_ostream &diagnostics) {
587280461Sdim  // TODO: if -arch not specified, look at arch of first .o file.
588280461Sdim
589280461Sdim  if (_currentVersion && _outputMachOType != MH_DYLIB) {
590280461Sdim    diagnostics << "error: -current_version can only be used with dylibs\n";
591280461Sdim    return false;
592280461Sdim  }
593280461Sdim
594280461Sdim  if (_compatibilityVersion && _outputMachOType != MH_DYLIB) {
595280461Sdim    diagnostics
596280461Sdim        << "error: -compatibility_version can only be used with dylibs\n";
597280461Sdim    return false;
598280461Sdim  }
599280461Sdim
600280461Sdim  if (_deadStrippableDylib && _outputMachOType != MH_DYLIB) {
601280461Sdim    diagnostics
602280461Sdim        << "error: -mark_dead_strippable_dylib can only be used with dylibs.\n";
603280461Sdim    return false;
604280461Sdim  }
605280461Sdim
606280461Sdim  if (!_bundleLoader.empty() && outputMachOType() != MH_BUNDLE) {
607280461Sdim    diagnostics
608280461Sdim        << "error: -bundle_loader can only be used with Mach-O bundles\n";
609280461Sdim    return false;
610280461Sdim  }
611280461Sdim
612280461Sdim  // If -exported_symbols_list used, all exported symbols must be defined.
613280461Sdim  if (_exportMode == ExportMode::whiteList) {
614280461Sdim    for (const auto &symbol : _exportedSymbols)
615280461Sdim      addInitialUndefinedSymbol(symbol.getKey());
616280461Sdim  }
617280461Sdim
618280461Sdim  // If -dead_strip, set up initial live symbols.
619280461Sdim  if (deadStrip()) {
620280461Sdim    // Entry point is live.
621280461Sdim    if (outputTypeHasEntry())
622280461Sdim      addDeadStripRoot(entrySymbolName());
623280461Sdim    // Lazy binding helper is live.
624280461Sdim    if (needsStubsPass())
625280461Sdim      addDeadStripRoot(binderSymbolName());
626280461Sdim    // If using -exported_symbols_list, make all exported symbols live.
627280461Sdim    if (_exportMode == ExportMode::whiteList) {
628280461Sdim      setGlobalsAreDeadStripRoots(false);
629280461Sdim      for (const auto &symbol : _exportedSymbols)
630280461Sdim        addDeadStripRoot(symbol.getKey());
631280461Sdim    }
632280461Sdim  }
633280461Sdim
634280461Sdim  addOutputFileDependency(outputPath());
635280461Sdim
636280461Sdim  return true;
637280461Sdim}
638280461Sdim
639280461Sdimvoid MachOLinkingContext::addPasses(PassManager &pm) {
640303239Sdim  // objc pass should be before layout pass.  Otherwise test cases may contain
641303239Sdim  // no atoms which confuses the layout pass.
642303239Sdim  if (needsObjCPass())
643303239Sdim    mach_o::addObjCPass(pm, *this);
644280461Sdim  mach_o::addLayoutPass(pm, *this);
645280461Sdim  if (needsStubsPass())
646280461Sdim    mach_o::addStubsPass(pm, *this);
647280461Sdim  if (needsCompactUnwindPass())
648280461Sdim    mach_o::addCompactUnwindPass(pm, *this);
649280461Sdim  if (needsGOTPass())
650280461Sdim    mach_o::addGOTPass(pm, *this);
651292934Sdim  if (needsTLVPass())
652292934Sdim    mach_o::addTLVPass(pm, *this);
653280461Sdim  if (needsShimPass())
654280461Sdim    mach_o::addShimPass(pm, *this); // Shim pass must run after stubs pass.
655280461Sdim}
656280461Sdim
657280461SdimWriter &MachOLinkingContext::writer() const {
658280461Sdim  if (!_writer)
659280461Sdim    _writer = createWriterMachO(*this);
660280461Sdim  return *_writer;
661280461Sdim}
662280461Sdim
663280461SdimErrorOr<std::unique_ptr<MemoryBuffer>>
664280461SdimMachOLinkingContext::getMemoryBuffer(StringRef path) {
665280461Sdim  addInputFileDependency(path);
666280461Sdim
667280461Sdim  ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr =
668280461Sdim    MemoryBuffer::getFileOrSTDIN(path);
669280461Sdim  if (std::error_code ec = mbOrErr.getError())
670280461Sdim    return ec;
671280461Sdim  std::unique_ptr<MemoryBuffer> mb = std::move(mbOrErr.get());
672280461Sdim
673280461Sdim  // If buffer contains a fat file, find required arch in fat buffer
674280461Sdim  // and switch buffer to point to just that required slice.
675280461Sdim  uint32_t offset;
676280461Sdim  uint32_t size;
677292934Sdim  if (sliceFromFatFile(mb->getMemBufferRef(), offset, size))
678280461Sdim    return MemoryBuffer::getFileSlice(path, size, offset);
679280461Sdim  return std::move(mb);
680280461Sdim}
681280461Sdim
682280461SdimMachODylibFile* MachOLinkingContext::loadIndirectDylib(StringRef path) {
683280461Sdim  ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr = getMemoryBuffer(path);
684280461Sdim  if (mbOrErr.getError())
685280461Sdim    return nullptr;
686280461Sdim
687292934Sdim  ErrorOr<std::unique_ptr<File>> fileOrErr =
688292934Sdim      registry().loadFile(std::move(mbOrErr.get()));
689292934Sdim  if (!fileOrErr)
690280461Sdim    return nullptr;
691292934Sdim  std::unique_ptr<File> &file = fileOrErr.get();
692292934Sdim  file->parse();
693292934Sdim  MachODylibFile *result = reinterpret_cast<MachODylibFile *>(file.get());
694280461Sdim  // Node object now owned by _indirectDylibs vector.
695292934Sdim  _indirectDylibs.push_back(std::move(file));
696280461Sdim  return result;
697280461Sdim}
698280461Sdim
699280461SdimMachODylibFile* MachOLinkingContext::findIndirectDylib(StringRef path) {
700280461Sdim  // See if already loaded.
701280461Sdim  auto pos = _pathToDylibMap.find(path);
702280461Sdim  if (pos != _pathToDylibMap.end())
703280461Sdim    return pos->second;
704280461Sdim
705280461Sdim  // Search -L paths if of the form "libXXX.dylib"
706280461Sdim  std::pair<StringRef, StringRef> split = path.rsplit('/');
707280461Sdim  StringRef leafName = split.second;
708280461Sdim  if (leafName.startswith("lib") && leafName.endswith(".dylib")) {
709280461Sdim    // FIXME: Need to enhance searchLibrary() to only look for .dylib
710280461Sdim    auto libPath = searchLibrary(leafName);
711303239Sdim    if (libPath)
712303239Sdim      return loadIndirectDylib(libPath.getValue());
713280461Sdim  }
714280461Sdim
715280461Sdim  // Try full path with sysroot.
716280461Sdim  for (StringRef sysPath : _syslibRoots) {
717280461Sdim    SmallString<256> fullPath;
718280461Sdim    fullPath.assign(sysPath);
719280461Sdim    llvm::sys::path::append(fullPath, path);
720280461Sdim    if (pathExists(fullPath))
721280461Sdim      return loadIndirectDylib(fullPath);
722280461Sdim  }
723280461Sdim
724280461Sdim  // Try full path.
725280461Sdim  if (pathExists(path)) {
726280461Sdim    return loadIndirectDylib(path);
727280461Sdim  }
728280461Sdim
729280461Sdim  return nullptr;
730280461Sdim}
731280461Sdim
732280461Sdimuint32_t MachOLinkingContext::dylibCurrentVersion(StringRef installName) const {
733280461Sdim  auto pos = _pathToDylibMap.find(installName);
734280461Sdim  if (pos != _pathToDylibMap.end())
735280461Sdim    return pos->second->currentVersion();
736280461Sdim  else
737280461Sdim    return 0x1000; // 1.0
738280461Sdim}
739280461Sdim
740280461Sdimuint32_t MachOLinkingContext::dylibCompatVersion(StringRef installName) const {
741280461Sdim  auto pos = _pathToDylibMap.find(installName);
742280461Sdim  if (pos != _pathToDylibMap.end())
743280461Sdim    return pos->second->compatVersion();
744280461Sdim  else
745280461Sdim    return 0x1000; // 1.0
746280461Sdim}
747280461Sdim
748292934Sdimvoid MachOLinkingContext::createImplicitFiles(
749280461Sdim                            std::vector<std::unique_ptr<File> > &result) {
750280461Sdim  // Add indirect dylibs by asking each linked dylib to add its indirects.
751280461Sdim  // Iterate until no more dylibs get loaded.
752280461Sdim  size_t dylibCount = 0;
753280461Sdim  while (dylibCount != _allDylibs.size()) {
754280461Sdim    dylibCount = _allDylibs.size();
755280461Sdim    for (MachODylibFile *dylib : _allDylibs) {
756280461Sdim      dylib->loadReExportedDylibs([this] (StringRef path) -> MachODylibFile* {
757280461Sdim                                  return findIndirectDylib(path); });
758280461Sdim    }
759280461Sdim  }
760280461Sdim
761280461Sdim  // Let writer add output type specific extras.
762292934Sdim  writer().createImplicitFiles(result);
763292934Sdim
764292934Sdim  // If undefinedMode is != error, add a FlatNamespaceFile instance. This will
765292934Sdim  // provide a SharedLibraryAtom for symbols that aren't defined elsewhere.
766292934Sdim  if (undefinedMode() != UndefinedMode::error) {
767292934Sdim    result.emplace_back(new mach_o::FlatNamespaceFile(*this));
768292934Sdim    _flatNamespaceFile = result.back().get();
769292934Sdim  }
770280461Sdim}
771280461Sdim
772280461Sdimvoid MachOLinkingContext::registerDylib(MachODylibFile *dylib,
773280461Sdim                                        bool upward) const {
774292934Sdim  std::lock_guard<std::mutex> lock(_dylibsMutex);
775280461Sdim  _allDylibs.insert(dylib);
776280461Sdim  _pathToDylibMap[dylib->installName()] = dylib;
777280461Sdim  // If path is different than install name, register path too.
778280461Sdim  if (!dylib->path().equals(dylib->installName()))
779280461Sdim    _pathToDylibMap[dylib->path()] = dylib;
780280461Sdim  if (upward)
781280461Sdim    _upwardDylibs.insert(dylib);
782280461Sdim}
783280461Sdim
784280461Sdimbool MachOLinkingContext::isUpwardDylib(StringRef installName) const {
785280461Sdim  for (MachODylibFile *dylib : _upwardDylibs) {
786280461Sdim    if (dylib->installName().equals(installName))
787280461Sdim      return true;
788280461Sdim  }
789280461Sdim  return false;
790280461Sdim}
791280461Sdim
792280461SdimArchHandler &MachOLinkingContext::archHandler() const {
793280461Sdim  if (!_archHandler)
794280461Sdim    _archHandler = ArchHandler::create(_arch);
795280461Sdim  return *_archHandler;
796280461Sdim}
797280461Sdim
798280461Sdimvoid MachOLinkingContext::addSectionAlignment(StringRef seg, StringRef sect,
799292934Sdim                                              uint16_t align) {
800292934Sdim  SectionAlign entry = { seg, sect, align };
801280461Sdim  _sectAligns.push_back(entry);
802280461Sdim}
803280461Sdim
804292934Sdimvoid MachOLinkingContext::addSectCreateSection(
805292934Sdim                                        StringRef seg, StringRef sect,
806292934Sdim                                        std::unique_ptr<MemoryBuffer> content) {
807292934Sdim
808292934Sdim  if (!_sectCreateFile) {
809292934Sdim    auto sectCreateFile = llvm::make_unique<mach_o::SectCreateFile>();
810292934Sdim    _sectCreateFile = sectCreateFile.get();
811292934Sdim    getNodes().push_back(llvm::make_unique<FileNode>(std::move(sectCreateFile)));
812292934Sdim  }
813292934Sdim
814292934Sdim  assert(_sectCreateFile && "sectcreate file does not exist.");
815292934Sdim  _sectCreateFile->addSection(seg, sect, std::move(content));
816292934Sdim}
817292934Sdim
818280461Sdimbool MachOLinkingContext::sectionAligned(StringRef seg, StringRef sect,
819292934Sdim                                         uint16_t &align) const {
820280461Sdim  for (const SectionAlign &entry : _sectAligns) {
821280461Sdim    if (seg.equals(entry.segmentName) && sect.equals(entry.sectionName)) {
822292934Sdim      align = entry.align;
823280461Sdim      return true;
824280461Sdim    }
825280461Sdim  }
826280461Sdim  return false;
827280461Sdim}
828280461Sdim
829280461Sdimvoid MachOLinkingContext::addExportSymbol(StringRef sym) {
830280461Sdim  // Support old crufty export lists with bogus entries.
831280461Sdim  if (sym.endswith(".eh") || sym.startswith(".objc_category_name_")) {
832280461Sdim    llvm::errs() << "warning: ignoring " << sym << " in export list\n";
833280461Sdim    return;
834280461Sdim  }
835280461Sdim  // Only i386 MacOSX uses old ABI, so don't change those.
836280461Sdim  if ((_os != OS::macOSX) || (_arch != arch_x86)) {
837280461Sdim    // ObjC has two differnent ABIs.  Be nice and allow one export list work for
838280461Sdim    // both ABIs by renaming symbols.
839280461Sdim    if (sym.startswith(".objc_class_name_")) {
840280461Sdim      std::string abi2className("_OBJC_CLASS_$_");
841280461Sdim      abi2className += sym.substr(17);
842280461Sdim      _exportedSymbols.insert(copy(abi2className));
843280461Sdim      std::string abi2metaclassName("_OBJC_METACLASS_$_");
844280461Sdim      abi2metaclassName += sym.substr(17);
845280461Sdim      _exportedSymbols.insert(copy(abi2metaclassName));
846280461Sdim      return;
847280461Sdim    }
848280461Sdim  }
849280461Sdim
850280461Sdim  // FIXME: Support wildcards.
851280461Sdim  _exportedSymbols.insert(sym);
852280461Sdim}
853280461Sdim
854280461Sdimbool MachOLinkingContext::exportSymbolNamed(StringRef sym) const {
855280461Sdim  switch (_exportMode) {
856280461Sdim  case ExportMode::globals:
857280461Sdim    llvm_unreachable("exportSymbolNamed() should not be called in this mode");
858280461Sdim    break;
859280461Sdim  case ExportMode::whiteList:
860280461Sdim    return _exportedSymbols.count(sym);
861280461Sdim  case ExportMode::blackList:
862280461Sdim    return !_exportedSymbols.count(sym);
863280461Sdim  }
864280461Sdim  llvm_unreachable("_exportMode unknown enum value");
865280461Sdim}
866280461Sdim
867280461Sdimstd::string MachOLinkingContext::demangle(StringRef symbolName) const {
868280461Sdim  // Only try to demangle symbols if -demangle on command line
869280461Sdim  if (!demangleSymbols())
870280461Sdim    return symbolName;
871280461Sdim
872280461Sdim  // Only try to demangle symbols that look like C++ symbols
873280461Sdim  if (!symbolName.startswith("__Z"))
874280461Sdim    return symbolName;
875280461Sdim
876280461Sdim#if defined(HAVE_CXXABI_H)
877280461Sdim  SmallString<256> symBuff;
878280461Sdim  StringRef nullTermSym = Twine(symbolName).toNullTerminatedStringRef(symBuff);
879280461Sdim  // Mach-O has extra leading underscore that needs to be removed.
880280461Sdim  const char *cstr = nullTermSym.data() + 1;
881280461Sdim  int status;
882280461Sdim  char *demangled = abi::__cxa_demangle(cstr, nullptr, nullptr, &status);
883292934Sdim  if (demangled) {
884280461Sdim    std::string result(demangled);
885280461Sdim    // __cxa_demangle() always uses a malloc'ed buffer to return the result.
886280461Sdim    free(demangled);
887280461Sdim    return result;
888280461Sdim  }
889280461Sdim#endif
890280461Sdim
891280461Sdim  return symbolName;
892280461Sdim}
893280461Sdim
894280461Sdimstd::error_code MachOLinkingContext::createDependencyFile(StringRef path) {
895280461Sdim  std::error_code ec;
896280461Sdim  _dependencyInfo = std::unique_ptr<llvm::raw_fd_ostream>(new
897280461Sdim                         llvm::raw_fd_ostream(path, ec, llvm::sys::fs::F_None));
898280461Sdim  if (ec) {
899280461Sdim    _dependencyInfo.reset();
900280461Sdim    return ec;
901280461Sdim  }
902280461Sdim
903280461Sdim  char linkerVersionOpcode = 0x00;
904280461Sdim  *_dependencyInfo << linkerVersionOpcode;
905280461Sdim  *_dependencyInfo << "lld";     // FIXME
906280461Sdim  *_dependencyInfo << '\0';
907280461Sdim
908280461Sdim  return std::error_code();
909280461Sdim}
910280461Sdim
911280461Sdimvoid MachOLinkingContext::addInputFileDependency(StringRef path) const {
912280461Sdim  if (!_dependencyInfo)
913280461Sdim    return;
914280461Sdim
915280461Sdim  char inputFileOpcode = 0x10;
916280461Sdim  *_dependencyInfo << inputFileOpcode;
917280461Sdim  *_dependencyInfo << path;
918280461Sdim  *_dependencyInfo << '\0';
919280461Sdim}
920280461Sdim
921280461Sdimvoid MachOLinkingContext::addInputFileNotFound(StringRef path) const {
922280461Sdim  if (!_dependencyInfo)
923280461Sdim    return;
924280461Sdim
925280461Sdim  char inputFileOpcode = 0x11;
926280461Sdim  *_dependencyInfo << inputFileOpcode;
927280461Sdim  *_dependencyInfo << path;
928280461Sdim  *_dependencyInfo << '\0';
929280461Sdim}
930280461Sdim
931280461Sdimvoid MachOLinkingContext::addOutputFileDependency(StringRef path) const {
932280461Sdim  if (!_dependencyInfo)
933280461Sdim    return;
934280461Sdim
935280461Sdim  char outputFileOpcode = 0x40;
936280461Sdim  *_dependencyInfo << outputFileOpcode;
937280461Sdim  *_dependencyInfo << path;
938280461Sdim  *_dependencyInfo << '\0';
939280461Sdim}
940280461Sdim
941280461Sdimvoid MachOLinkingContext::appendOrderedSymbol(StringRef symbol,
942280461Sdim                                              StringRef filename) {
943280461Sdim  // To support sorting static functions which may have the same name in
944280461Sdim  // multiple .o files, _orderFiles maps the symbol name to a vector
945280461Sdim  // of OrderFileNode each of which can specify a file prefix.
946280461Sdim  OrderFileNode info;
947280461Sdim  if (!filename.empty())
948280461Sdim    info.fileFilter = copy(filename);
949280461Sdim  info.order = _orderFileEntries++;
950280461Sdim  _orderFiles[symbol].push_back(info);
951280461Sdim}
952280461Sdim
953280461Sdimbool
954280461SdimMachOLinkingContext::findOrderOrdinal(const std::vector<OrderFileNode> &nodes,
955280461Sdim                                      const DefinedAtom *atom,
956280461Sdim                                      unsigned &ordinal) {
957280461Sdim  const File *objFile = &atom->file();
958280461Sdim  assert(objFile);
959280461Sdim  StringRef objName = objFile->path();
960280461Sdim  std::pair<StringRef, StringRef> dirAndLeaf = objName.rsplit('/');
961280461Sdim  if (!dirAndLeaf.second.empty())
962280461Sdim    objName = dirAndLeaf.second;
963280461Sdim  for (const OrderFileNode &info : nodes) {
964280461Sdim    if (info.fileFilter.empty()) {
965280461Sdim      // Have unprefixed symbol name in order file that matches this atom.
966280461Sdim      ordinal = info.order;
967280461Sdim      return true;
968280461Sdim    }
969280461Sdim    if (info.fileFilter.equals(objName)) {
970280461Sdim      // Have prefixed symbol name in order file that matches atom's path.
971280461Sdim      ordinal = info.order;
972280461Sdim      return true;
973280461Sdim    }
974280461Sdim  }
975280461Sdim  return false;
976280461Sdim}
977280461Sdim
978280461Sdimbool MachOLinkingContext::customAtomOrderer(const DefinedAtom *left,
979280461Sdim                                            const DefinedAtom *right,
980280461Sdim                                            bool &leftBeforeRight) const {
981280461Sdim  // No custom sorting if no order file entries.
982280461Sdim  if (!_orderFileEntries)
983280461Sdim    return false;
984280461Sdim
985280461Sdim  // Order files can only order named atoms.
986280461Sdim  StringRef leftName = left->name();
987280461Sdim  StringRef rightName = right->name();
988280461Sdim  if (leftName.empty() || rightName.empty())
989280461Sdim    return false;
990280461Sdim
991280461Sdim  // If neither is in order file list, no custom sorter.
992280461Sdim  auto leftPos = _orderFiles.find(leftName);
993280461Sdim  auto rightPos = _orderFiles.find(rightName);
994280461Sdim  bool leftIsOrdered = (leftPos != _orderFiles.end());
995280461Sdim  bool rightIsOrdered = (rightPos != _orderFiles.end());
996280461Sdim  if (!leftIsOrdered && !rightIsOrdered)
997280461Sdim    return false;
998280461Sdim
999280461Sdim  // There could be multiple symbols with same name but different file prefixes.
1000280461Sdim  unsigned leftOrder;
1001280461Sdim  unsigned rightOrder;
1002280461Sdim  bool foundLeft =
1003280461Sdim      leftIsOrdered && findOrderOrdinal(leftPos->getValue(), left, leftOrder);
1004280461Sdim  bool foundRight = rightIsOrdered &&
1005280461Sdim                    findOrderOrdinal(rightPos->getValue(), right, rightOrder);
1006280461Sdim  if (!foundLeft && !foundRight)
1007280461Sdim    return false;
1008280461Sdim
1009280461Sdim  // If only one is in order file list, ordered one goes first.
1010280461Sdim  if (foundLeft != foundRight)
1011280461Sdim    leftBeforeRight = foundLeft;
1012280461Sdim  else
1013280461Sdim    leftBeforeRight = (leftOrder < rightOrder);
1014280461Sdim
1015280461Sdim  return true;
1016280461Sdim}
1017280461Sdim
1018280461Sdimstatic bool isLibrary(const std::unique_ptr<Node> &elem) {
1019280461Sdim  if (FileNode *node = dyn_cast<FileNode>(const_cast<Node *>(elem.get()))) {
1020280461Sdim    File *file = node->getFile();
1021280461Sdim    return isa<SharedLibraryFile>(file) || isa<ArchiveLibraryFile>(file);
1022280461Sdim  }
1023280461Sdim  return false;
1024280461Sdim}
1025280461Sdim
1026280461Sdim// The darwin linker processes input files in two phases.  The first phase
1027280461Sdim// links in all object (.o) files in command line order. The second phase
1028280461Sdim// links in libraries in command line order.
1029280461Sdim// In this function we reorder the input files so that all the object files
1030280461Sdim// comes before any library file. We also make a group for the library files
1031280461Sdim// so that the Resolver will reiterate over the libraries as long as we find
1032280461Sdim// new undefines from libraries.
1033280461Sdimvoid MachOLinkingContext::finalizeInputFiles() {
1034280461Sdim  std::vector<std::unique_ptr<Node>> &elements = getNodes();
1035280461Sdim  std::stable_sort(elements.begin(), elements.end(),
1036280461Sdim                   [](const std::unique_ptr<Node> &a,
1037280461Sdim                      const std::unique_ptr<Node> &b) {
1038280461Sdim                     return !isLibrary(a) && isLibrary(b);
1039280461Sdim                   });
1040280461Sdim  size_t numLibs = std::count_if(elements.begin(), elements.end(), isLibrary);
1041280461Sdim  elements.push_back(llvm::make_unique<GroupEnd>(numLibs));
1042280461Sdim}
1043280461Sdim
1044303239Sdimllvm::Error MachOLinkingContext::handleLoadedFile(File &file) {
1045303239Sdim  auto *machoFile = dyn_cast<MachOFile>(&file);
1046303239Sdim  if (!machoFile)
1047303239Sdim    return llvm::Error();
1048303239Sdim
1049303239Sdim  // Check that the arch of the context matches that of the file.
1050303239Sdim  // Also set the arch of the context if it didn't have one.
1051303239Sdim  if (_arch == arch_unknown) {
1052303239Sdim    _arch = machoFile->arch();
1053303239Sdim  } else if (machoFile->arch() != arch_unknown && machoFile->arch() != _arch) {
1054303239Sdim    // Archs are different.
1055303239Sdim    return llvm::make_error<GenericError>(file.path() +
1056303239Sdim                  Twine(" cannot be linked due to incompatible architecture"));
1057303239Sdim  }
1058303239Sdim
1059303239Sdim  // Check that the OS of the context matches that of the file.
1060303239Sdim  // Also set the OS of the context if it didn't have one.
1061303239Sdim  if (_os == OS::unknown) {
1062303239Sdim    _os = machoFile->OS();
1063303239Sdim  } else if (machoFile->OS() != OS::unknown && machoFile->OS() != _os) {
1064303239Sdim    // OSes are different.
1065303239Sdim    return llvm::make_error<GenericError>(file.path() +
1066303239Sdim              Twine(" cannot be linked due to incompatible operating systems"));
1067303239Sdim  }
1068303239Sdim
1069303239Sdim  // Check that if the objc info exists, that it is compatible with the target
1070303239Sdim  // OS.
1071303239Sdim  switch (machoFile->objcConstraint()) {
1072303239Sdim    case objc_unknown:
1073303239Sdim      // The file is not compiled with objc, so skip the checks.
1074303239Sdim      break;
1075303239Sdim    case objc_gc_only:
1076303239Sdim    case objc_supports_gc:
1077303239Sdim      llvm_unreachable("GC support should already have thrown an error");
1078303239Sdim    case objc_retainReleaseForSimulator:
1079303239Sdim      // The file is built with simulator objc, so make sure that the context
1080303239Sdim      // is also building with simulator support.
1081303239Sdim      if (_os != OS::iOS_simulator)
1082303239Sdim        return llvm::make_error<GenericError>(file.path() +
1083303239Sdim          Twine(" cannot be linked.  It contains ObjC built for the simulator"
1084303239Sdim                " while we are linking a non-simulator target"));
1085303239Sdim      assert((_objcConstraint == objc_unknown ||
1086303239Sdim              _objcConstraint == objc_retainReleaseForSimulator) &&
1087303239Sdim             "Must be linking with retain/release for the simulator");
1088303239Sdim      _objcConstraint = objc_retainReleaseForSimulator;
1089303239Sdim      break;
1090303239Sdim    case objc_retainRelease:
1091303239Sdim      // The file is built without simulator objc, so make sure that the
1092303239Sdim      // context is also building without simulator support.
1093303239Sdim      if (_os == OS::iOS_simulator)
1094303239Sdim        return llvm::make_error<GenericError>(file.path() +
1095303239Sdim          Twine(" cannot be linked.  It contains ObjC built for a non-simulator"
1096303239Sdim                " target while we are linking a simulator target"));
1097303239Sdim      assert((_objcConstraint == objc_unknown ||
1098303239Sdim              _objcConstraint == objc_retainRelease) &&
1099303239Sdim             "Must be linking with retain/release for a non-simulator target");
1100303239Sdim      _objcConstraint = objc_retainRelease;
1101303239Sdim      break;
1102303239Sdim  }
1103303239Sdim
1104303239Sdim  // Check that the swift version of the context matches that of the file.
1105303239Sdim  // Also set the swift version of the context if it didn't have one.
1106303239Sdim  if (!_swiftVersion) {
1107303239Sdim    _swiftVersion = machoFile->swiftVersion();
1108303239Sdim  } else if (machoFile->swiftVersion() &&
1109303239Sdim             machoFile->swiftVersion() != _swiftVersion) {
1110303239Sdim    // Swift versions are different.
1111303239Sdim    return llvm::make_error<GenericError>("different swift versions");
1112303239Sdim  }
1113303239Sdim
1114303239Sdim  return llvm::Error();
1115303239Sdim}
1116303239Sdim
1117280461Sdim} // end namespace lld
1118