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