1280461Sdim//===- lib/ReaderWriter/MachO/MachOLinkingContext.cpp ---------------------===// 2280461Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6280461Sdim// 7280461Sdim//===----------------------------------------------------------------------===// 8280461Sdim 9341825Sdim#include "lld/Common/ErrorHandler.h" 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; 264344779Sdim break; 265280461Sdim default: 266280461Sdim break; 267280461Sdim } 268280461Sdim 269280461Sdim // Set default segment page sizes based on arch. 270280461Sdim if (arch == arch_arm64) 271280461Sdim _pageSize = 4*4096; 272280461Sdim} 273280461Sdim 274280461Sdimuint32_t MachOLinkingContext::getCPUType() const { 275280461Sdim return cpuTypeFromArch(_arch); 276280461Sdim} 277280461Sdim 278280461Sdimuint32_t MachOLinkingContext::getCPUSubType() const { 279280461Sdim return cpuSubtypeFromArch(_arch); 280280461Sdim} 281280461Sdim 282280461Sdimbool MachOLinkingContext::is64Bit(Arch arch) { 283280461Sdim for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) { 284280461Sdim if (info->arch == arch) { 285280461Sdim return (info->cputype & CPU_ARCH_ABI64); 286280461Sdim } 287280461Sdim } 288280461Sdim // unknown archs are not 64-bit. 289280461Sdim return false; 290280461Sdim} 291280461Sdim 292280461Sdimbool MachOLinkingContext::isHostEndian(Arch arch) { 293280461Sdim assert(arch != arch_unknown); 294280461Sdim for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) { 295280461Sdim if (info->arch == arch) { 296280461Sdim return (info->littleEndian == llvm::sys::IsLittleEndianHost); 297280461Sdim } 298280461Sdim } 299280461Sdim llvm_unreachable("Unknown arch type"); 300280461Sdim} 301280461Sdim 302280461Sdimbool MachOLinkingContext::isBigEndian(Arch arch) { 303280461Sdim assert(arch != arch_unknown); 304280461Sdim for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) { 305280461Sdim if (info->arch == arch) { 306280461Sdim return ! info->littleEndian; 307280461Sdim } 308280461Sdim } 309280461Sdim llvm_unreachable("Unknown arch type"); 310280461Sdim} 311280461Sdim 312280461Sdimbool MachOLinkingContext::is64Bit() const { 313280461Sdim return is64Bit(_arch); 314280461Sdim} 315280461Sdim 316280461Sdimbool MachOLinkingContext::outputTypeHasEntry() const { 317280461Sdim switch (_outputMachOType) { 318280461Sdim case MH_EXECUTE: 319280461Sdim case MH_DYLINKER: 320280461Sdim case MH_PRELOAD: 321280461Sdim return true; 322280461Sdim default: 323280461Sdim return false; 324280461Sdim } 325280461Sdim} 326280461Sdim 327280461Sdimbool MachOLinkingContext::needsStubsPass() const { 328280461Sdim switch (_outputMachOType) { 329280461Sdim case MH_EXECUTE: 330280461Sdim return !_outputMachOTypeStatic; 331280461Sdim case MH_DYLIB: 332280461Sdim case MH_BUNDLE: 333280461Sdim return true; 334280461Sdim default: 335280461Sdim return false; 336280461Sdim } 337280461Sdim} 338280461Sdim 339280461Sdimbool MachOLinkingContext::needsGOTPass() const { 340280461Sdim // GOT pass not used in -r mode. 341280461Sdim if (_outputMachOType == MH_OBJECT) 342280461Sdim return false; 343280461Sdim // Only some arches use GOT pass. 344280461Sdim switch (_arch) { 345280461Sdim case arch_x86_64: 346280461Sdim case arch_arm64: 347280461Sdim return true; 348280461Sdim default: 349280461Sdim return false; 350280461Sdim } 351280461Sdim} 352280461Sdim 353280461Sdimbool MachOLinkingContext::needsCompactUnwindPass() const { 354280461Sdim switch (_outputMachOType) { 355280461Sdim case MH_EXECUTE: 356280461Sdim case MH_DYLIB: 357280461Sdim case MH_BUNDLE: 358280461Sdim return archHandler().needsCompactUnwind(); 359280461Sdim default: 360280461Sdim return false; 361280461Sdim } 362280461Sdim} 363280461Sdim 364303239Sdimbool MachOLinkingContext::needsObjCPass() const { 365303239Sdim // ObjC pass is only needed if any of the inputs were ObjC. 366303239Sdim return _objcConstraint != objc_unknown; 367303239Sdim} 368303239Sdim 369280461Sdimbool MachOLinkingContext::needsShimPass() const { 370280461Sdim // Shim pass only used in final executables. 371280461Sdim if (_outputMachOType == MH_OBJECT) 372280461Sdim return false; 373280461Sdim // Only 32-bit arm arches use Shim pass. 374280461Sdim switch (_arch) { 375280461Sdim case arch_armv6: 376280461Sdim case arch_armv7: 377280461Sdim case arch_armv7s: 378280461Sdim return true; 379280461Sdim default: 380280461Sdim return false; 381280461Sdim } 382280461Sdim} 383280461Sdim 384292934Sdimbool MachOLinkingContext::needsTLVPass() const { 385292934Sdim switch (_outputMachOType) { 386292934Sdim case MH_BUNDLE: 387292934Sdim case MH_EXECUTE: 388292934Sdim case MH_DYLIB: 389292934Sdim return true; 390292934Sdim default: 391292934Sdim return false; 392292934Sdim } 393292934Sdim} 394292934Sdim 395280461SdimStringRef MachOLinkingContext::binderSymbolName() const { 396280461Sdim return archHandler().stubInfo().binderSymbolName; 397280461Sdim} 398280461Sdim 399280461Sdimbool MachOLinkingContext::minOS(StringRef mac, StringRef iOS) const { 400280461Sdim uint32_t parsedVersion; 401280461Sdim switch (_os) { 402280461Sdim case OS::macOSX: 403280461Sdim if (parsePackedVersion(mac, parsedVersion)) 404280461Sdim return false; 405280461Sdim return _osMinVersion >= parsedVersion; 406280461Sdim case OS::iOS: 407280461Sdim case OS::iOS_simulator: 408280461Sdim if (parsePackedVersion(iOS, parsedVersion)) 409280461Sdim return false; 410280461Sdim return _osMinVersion >= parsedVersion; 411280461Sdim case OS::unknown: 412303239Sdim // If we don't know the target, then assume that we don't meet the min OS. 413303239Sdim // This matches the ld64 behaviour 414303239Sdim return false; 415280461Sdim } 416303239Sdim llvm_unreachable("invalid OS enum"); 417280461Sdim} 418280461Sdim 419280461Sdimbool MachOLinkingContext::addEntryPointLoadCommand() const { 420280461Sdim if ((_outputMachOType == MH_EXECUTE) && !_outputMachOTypeStatic) { 421280461Sdim return minOS("10.8", "6.0"); 422280461Sdim } 423280461Sdim return false; 424280461Sdim} 425280461Sdim 426280461Sdimbool MachOLinkingContext::addUnixThreadLoadCommand() const { 427280461Sdim switch (_outputMachOType) { 428280461Sdim case MH_EXECUTE: 429280461Sdim if (_outputMachOTypeStatic) 430280461Sdim return true; 431280461Sdim else 432280461Sdim return !minOS("10.8", "6.0"); 433280461Sdim break; 434280461Sdim case MH_DYLINKER: 435280461Sdim case MH_PRELOAD: 436280461Sdim return true; 437280461Sdim default: 438280461Sdim return false; 439280461Sdim } 440280461Sdim} 441280461Sdim 442280461Sdimbool MachOLinkingContext::pathExists(StringRef path) const { 443280461Sdim if (!_testingFileUsage) 444280461Sdim return llvm::sys::fs::exists(path.str()); 445280461Sdim 446280461Sdim // Otherwise, we're in test mode: only files explicitly provided on the 447280461Sdim // command-line exist. 448280461Sdim std::string key = path.str(); 449280461Sdim std::replace(key.begin(), key.end(), '\\', '/'); 450280461Sdim return _existingPaths.find(key) != _existingPaths.end(); 451280461Sdim} 452280461Sdim 453280461Sdimbool MachOLinkingContext::fileExists(StringRef path) const { 454280461Sdim bool found = pathExists(path); 455280461Sdim // Log search misses. 456280461Sdim if (!found) 457280461Sdim addInputFileNotFound(path); 458280461Sdim 459280461Sdim // When testing, file is never opened, so logging is done here. 460280461Sdim if (_testingFileUsage && found) 461280461Sdim addInputFileDependency(path); 462280461Sdim 463280461Sdim return found; 464280461Sdim} 465280461Sdim 466280461Sdimvoid MachOLinkingContext::setSysLibRoots(const StringRefVector &paths) { 467280461Sdim _syslibRoots = paths; 468280461Sdim} 469280461Sdim 470280461Sdimvoid MachOLinkingContext::addRpath(StringRef rpath) { 471280461Sdim _rpaths.push_back(rpath); 472280461Sdim} 473280461Sdim 474280461Sdimvoid MachOLinkingContext::addModifiedSearchDir(StringRef libPath, 475280461Sdim bool isSystemPath) { 476280461Sdim bool addedModifiedPath = false; 477280461Sdim 478280461Sdim // -syslibroot only applies to absolute paths. 479280461Sdim if (libPath.startswith("/")) { 480280461Sdim for (auto syslibRoot : _syslibRoots) { 481280461Sdim SmallString<256> path(syslibRoot); 482280461Sdim llvm::sys::path::append(path, libPath); 483280461Sdim if (pathExists(path)) { 484280461Sdim _searchDirs.push_back(path.str().copy(_allocator)); 485280461Sdim addedModifiedPath = true; 486280461Sdim } 487280461Sdim } 488280461Sdim } 489280461Sdim 490280461Sdim if (addedModifiedPath) 491280461Sdim return; 492280461Sdim 493280461Sdim // Finally, if only one -syslibroot is given, system paths which aren't in it 494280461Sdim // get suppressed. 495280461Sdim if (_syslibRoots.size() != 1 || !isSystemPath) { 496280461Sdim if (pathExists(libPath)) { 497280461Sdim _searchDirs.push_back(libPath); 498280461Sdim } 499280461Sdim } 500280461Sdim} 501280461Sdim 502280461Sdimvoid MachOLinkingContext::addFrameworkSearchDir(StringRef fwPath, 503280461Sdim bool isSystemPath) { 504280461Sdim bool pathAdded = false; 505280461Sdim 506280461Sdim // -syslibroot only used with to absolute framework search paths. 507280461Sdim if (fwPath.startswith("/")) { 508280461Sdim for (auto syslibRoot : _syslibRoots) { 509280461Sdim SmallString<256> path(syslibRoot); 510280461Sdim llvm::sys::path::append(path, fwPath); 511280461Sdim if (pathExists(path)) { 512280461Sdim _frameworkDirs.push_back(path.str().copy(_allocator)); 513280461Sdim pathAdded = true; 514280461Sdim } 515280461Sdim } 516280461Sdim } 517280461Sdim // If fwPath found in any -syslibroot, then done. 518280461Sdim if (pathAdded) 519280461Sdim return; 520280461Sdim 521280461Sdim // If only one -syslibroot, system paths not in that SDK are suppressed. 522280461Sdim if (isSystemPath && (_syslibRoots.size() == 1)) 523280461Sdim return; 524280461Sdim 525280461Sdim // Only use raw fwPath if that directory exists. 526280461Sdim if (pathExists(fwPath)) 527280461Sdim _frameworkDirs.push_back(fwPath); 528280461Sdim} 529280461Sdim 530303239Sdimllvm::Optional<StringRef> 531280461SdimMachOLinkingContext::searchDirForLibrary(StringRef path, 532280461Sdim StringRef libName) const { 533280461Sdim SmallString<256> fullPath; 534280461Sdim if (libName.endswith(".o")) { 535280461Sdim // A request ending in .o is special: just search for the file directly. 536280461Sdim fullPath.assign(path); 537280461Sdim llvm::sys::path::append(fullPath, libName); 538280461Sdim if (fileExists(fullPath)) 539280461Sdim return fullPath.str().copy(_allocator); 540303239Sdim return llvm::None; 541280461Sdim } 542280461Sdim 543280461Sdim // Search for dynamic library 544280461Sdim fullPath.assign(path); 545280461Sdim llvm::sys::path::append(fullPath, Twine("lib") + libName + ".dylib"); 546280461Sdim if (fileExists(fullPath)) 547280461Sdim return fullPath.str().copy(_allocator); 548280461Sdim 549280461Sdim // If not, try for a static library 550280461Sdim fullPath.assign(path); 551280461Sdim llvm::sys::path::append(fullPath, Twine("lib") + libName + ".a"); 552280461Sdim if (fileExists(fullPath)) 553280461Sdim return fullPath.str().copy(_allocator); 554280461Sdim 555303239Sdim return llvm::None; 556280461Sdim} 557280461Sdim 558303239Sdimllvm::Optional<StringRef> 559303239SdimMachOLinkingContext::searchLibrary(StringRef libName) const { 560280461Sdim SmallString<256> path; 561280461Sdim for (StringRef dir : searchDirs()) { 562303239Sdim llvm::Optional<StringRef> searchDir = searchDirForLibrary(dir, libName); 563303239Sdim if (searchDir) 564303239Sdim return searchDir; 565280461Sdim } 566280461Sdim 567303239Sdim return llvm::None; 568280461Sdim} 569280461Sdim 570303239Sdimllvm::Optional<StringRef> 571303239SdimMachOLinkingContext::findPathForFramework(StringRef fwName) const{ 572280461Sdim SmallString<256> fullPath; 573280461Sdim for (StringRef dir : frameworkDirs()) { 574280461Sdim fullPath.assign(dir); 575280461Sdim llvm::sys::path::append(fullPath, Twine(fwName) + ".framework", fwName); 576280461Sdim if (fileExists(fullPath)) 577280461Sdim return fullPath.str().copy(_allocator); 578280461Sdim } 579280461Sdim 580303239Sdim return llvm::None; 581280461Sdim} 582280461Sdim 583341825Sdimbool MachOLinkingContext::validateImpl() { 584280461Sdim // TODO: if -arch not specified, look at arch of first .o file. 585280461Sdim 586280461Sdim if (_currentVersion && _outputMachOType != MH_DYLIB) { 587341825Sdim error("-current_version can only be used with dylibs"); 588280461Sdim return false; 589280461Sdim } 590280461Sdim 591280461Sdim if (_compatibilityVersion && _outputMachOType != MH_DYLIB) { 592341825Sdim error("-compatibility_version can only be used with dylibs"); 593280461Sdim return false; 594280461Sdim } 595280461Sdim 596280461Sdim if (_deadStrippableDylib && _outputMachOType != MH_DYLIB) { 597341825Sdim error("-mark_dead_strippable_dylib can only be used with dylibs"); 598280461Sdim return false; 599280461Sdim } 600280461Sdim 601280461Sdim if (!_bundleLoader.empty() && outputMachOType() != MH_BUNDLE) { 602341825Sdim error("-bundle_loader can only be used with Mach-O bundles"); 603280461Sdim return false; 604280461Sdim } 605280461Sdim 606280461Sdim // If -exported_symbols_list used, all exported symbols must be defined. 607280461Sdim if (_exportMode == ExportMode::whiteList) { 608280461Sdim for (const auto &symbol : _exportedSymbols) 609280461Sdim addInitialUndefinedSymbol(symbol.getKey()); 610280461Sdim } 611280461Sdim 612280461Sdim // If -dead_strip, set up initial live symbols. 613280461Sdim if (deadStrip()) { 614280461Sdim // Entry point is live. 615280461Sdim if (outputTypeHasEntry()) 616280461Sdim addDeadStripRoot(entrySymbolName()); 617280461Sdim // Lazy binding helper is live. 618280461Sdim if (needsStubsPass()) 619280461Sdim addDeadStripRoot(binderSymbolName()); 620280461Sdim // If using -exported_symbols_list, make all exported symbols live. 621280461Sdim if (_exportMode == ExportMode::whiteList) { 622280461Sdim setGlobalsAreDeadStripRoots(false); 623280461Sdim for (const auto &symbol : _exportedSymbols) 624280461Sdim addDeadStripRoot(symbol.getKey()); 625280461Sdim } 626280461Sdim } 627280461Sdim 628280461Sdim addOutputFileDependency(outputPath()); 629280461Sdim 630280461Sdim return true; 631280461Sdim} 632280461Sdim 633280461Sdimvoid MachOLinkingContext::addPasses(PassManager &pm) { 634303239Sdim // objc pass should be before layout pass. Otherwise test cases may contain 635303239Sdim // no atoms which confuses the layout pass. 636303239Sdim if (needsObjCPass()) 637303239Sdim mach_o::addObjCPass(pm, *this); 638280461Sdim mach_o::addLayoutPass(pm, *this); 639280461Sdim if (needsStubsPass()) 640280461Sdim mach_o::addStubsPass(pm, *this); 641280461Sdim if (needsCompactUnwindPass()) 642280461Sdim mach_o::addCompactUnwindPass(pm, *this); 643280461Sdim if (needsGOTPass()) 644280461Sdim mach_o::addGOTPass(pm, *this); 645292934Sdim if (needsTLVPass()) 646292934Sdim mach_o::addTLVPass(pm, *this); 647280461Sdim if (needsShimPass()) 648280461Sdim mach_o::addShimPass(pm, *this); // Shim pass must run after stubs pass. 649280461Sdim} 650280461Sdim 651280461SdimWriter &MachOLinkingContext::writer() const { 652280461Sdim if (!_writer) 653280461Sdim _writer = createWriterMachO(*this); 654280461Sdim return *_writer; 655280461Sdim} 656280461Sdim 657280461SdimErrorOr<std::unique_ptr<MemoryBuffer>> 658280461SdimMachOLinkingContext::getMemoryBuffer(StringRef path) { 659280461Sdim addInputFileDependency(path); 660280461Sdim 661280461Sdim ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr = 662280461Sdim MemoryBuffer::getFileOrSTDIN(path); 663280461Sdim if (std::error_code ec = mbOrErr.getError()) 664280461Sdim return ec; 665280461Sdim std::unique_ptr<MemoryBuffer> mb = std::move(mbOrErr.get()); 666280461Sdim 667280461Sdim // If buffer contains a fat file, find required arch in fat buffer 668280461Sdim // and switch buffer to point to just that required slice. 669280461Sdim uint32_t offset; 670280461Sdim uint32_t size; 671292934Sdim if (sliceFromFatFile(mb->getMemBufferRef(), offset, size)) 672280461Sdim return MemoryBuffer::getFileSlice(path, size, offset); 673280461Sdim return std::move(mb); 674280461Sdim} 675280461Sdim 676280461SdimMachODylibFile* MachOLinkingContext::loadIndirectDylib(StringRef path) { 677280461Sdim ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr = getMemoryBuffer(path); 678280461Sdim if (mbOrErr.getError()) 679280461Sdim return nullptr; 680280461Sdim 681292934Sdim ErrorOr<std::unique_ptr<File>> fileOrErr = 682292934Sdim registry().loadFile(std::move(mbOrErr.get())); 683292934Sdim if (!fileOrErr) 684280461Sdim return nullptr; 685292934Sdim std::unique_ptr<File> &file = fileOrErr.get(); 686292934Sdim file->parse(); 687292934Sdim MachODylibFile *result = reinterpret_cast<MachODylibFile *>(file.get()); 688280461Sdim // Node object now owned by _indirectDylibs vector. 689292934Sdim _indirectDylibs.push_back(std::move(file)); 690280461Sdim return result; 691280461Sdim} 692280461Sdim 693280461SdimMachODylibFile* MachOLinkingContext::findIndirectDylib(StringRef path) { 694280461Sdim // See if already loaded. 695280461Sdim auto pos = _pathToDylibMap.find(path); 696280461Sdim if (pos != _pathToDylibMap.end()) 697280461Sdim return pos->second; 698280461Sdim 699280461Sdim // Search -L paths if of the form "libXXX.dylib" 700280461Sdim std::pair<StringRef, StringRef> split = path.rsplit('/'); 701280461Sdim StringRef leafName = split.second; 702280461Sdim if (leafName.startswith("lib") && leafName.endswith(".dylib")) { 703280461Sdim // FIXME: Need to enhance searchLibrary() to only look for .dylib 704280461Sdim auto libPath = searchLibrary(leafName); 705303239Sdim if (libPath) 706303239Sdim return loadIndirectDylib(libPath.getValue()); 707280461Sdim } 708280461Sdim 709280461Sdim // Try full path with sysroot. 710280461Sdim for (StringRef sysPath : _syslibRoots) { 711280461Sdim SmallString<256> fullPath; 712280461Sdim fullPath.assign(sysPath); 713280461Sdim llvm::sys::path::append(fullPath, path); 714280461Sdim if (pathExists(fullPath)) 715280461Sdim return loadIndirectDylib(fullPath); 716280461Sdim } 717280461Sdim 718280461Sdim // Try full path. 719280461Sdim if (pathExists(path)) { 720280461Sdim return loadIndirectDylib(path); 721280461Sdim } 722280461Sdim 723280461Sdim return nullptr; 724280461Sdim} 725280461Sdim 726280461Sdimuint32_t MachOLinkingContext::dylibCurrentVersion(StringRef installName) const { 727280461Sdim auto pos = _pathToDylibMap.find(installName); 728280461Sdim if (pos != _pathToDylibMap.end()) 729280461Sdim return pos->second->currentVersion(); 730280461Sdim else 731314564Sdim return 0x10000; // 1.0 732280461Sdim} 733280461Sdim 734280461Sdimuint32_t MachOLinkingContext::dylibCompatVersion(StringRef installName) const { 735280461Sdim auto pos = _pathToDylibMap.find(installName); 736280461Sdim if (pos != _pathToDylibMap.end()) 737280461Sdim return pos->second->compatVersion(); 738280461Sdim else 739314564Sdim return 0x10000; // 1.0 740280461Sdim} 741280461Sdim 742292934Sdimvoid MachOLinkingContext::createImplicitFiles( 743280461Sdim std::vector<std::unique_ptr<File> > &result) { 744280461Sdim // Add indirect dylibs by asking each linked dylib to add its indirects. 745280461Sdim // Iterate until no more dylibs get loaded. 746280461Sdim size_t dylibCount = 0; 747280461Sdim while (dylibCount != _allDylibs.size()) { 748280461Sdim dylibCount = _allDylibs.size(); 749280461Sdim for (MachODylibFile *dylib : _allDylibs) { 750280461Sdim dylib->loadReExportedDylibs([this] (StringRef path) -> MachODylibFile* { 751280461Sdim return findIndirectDylib(path); }); 752280461Sdim } 753280461Sdim } 754280461Sdim 755280461Sdim // Let writer add output type specific extras. 756292934Sdim writer().createImplicitFiles(result); 757292934Sdim 758292934Sdim // If undefinedMode is != error, add a FlatNamespaceFile instance. This will 759292934Sdim // provide a SharedLibraryAtom for symbols that aren't defined elsewhere. 760292934Sdim if (undefinedMode() != UndefinedMode::error) { 761292934Sdim result.emplace_back(new mach_o::FlatNamespaceFile(*this)); 762292934Sdim _flatNamespaceFile = result.back().get(); 763292934Sdim } 764280461Sdim} 765280461Sdim 766280461Sdimvoid MachOLinkingContext::registerDylib(MachODylibFile *dylib, 767280461Sdim bool upward) const { 768292934Sdim std::lock_guard<std::mutex> lock(_dylibsMutex); 769314564Sdim 770353358Sdim if (!llvm::count(_allDylibs, dylib)) 771314564Sdim _allDylibs.push_back(dylib); 772280461Sdim _pathToDylibMap[dylib->installName()] = dylib; 773280461Sdim // If path is different than install name, register path too. 774280461Sdim if (!dylib->path().equals(dylib->installName())) 775280461Sdim _pathToDylibMap[dylib->path()] = dylib; 776280461Sdim if (upward) 777280461Sdim _upwardDylibs.insert(dylib); 778280461Sdim} 779280461Sdim 780280461Sdimbool MachOLinkingContext::isUpwardDylib(StringRef installName) const { 781280461Sdim for (MachODylibFile *dylib : _upwardDylibs) { 782280461Sdim if (dylib->installName().equals(installName)) 783280461Sdim return true; 784280461Sdim } 785280461Sdim return false; 786280461Sdim} 787280461Sdim 788280461SdimArchHandler &MachOLinkingContext::archHandler() const { 789280461Sdim if (!_archHandler) 790280461Sdim _archHandler = ArchHandler::create(_arch); 791280461Sdim return *_archHandler; 792280461Sdim} 793280461Sdim 794280461Sdimvoid MachOLinkingContext::addSectionAlignment(StringRef seg, StringRef sect, 795292934Sdim uint16_t align) { 796292934Sdim SectionAlign entry = { seg, sect, align }; 797280461Sdim _sectAligns.push_back(entry); 798280461Sdim} 799280461Sdim 800292934Sdimvoid MachOLinkingContext::addSectCreateSection( 801292934Sdim StringRef seg, StringRef sect, 802292934Sdim std::unique_ptr<MemoryBuffer> content) { 803292934Sdim 804292934Sdim if (!_sectCreateFile) { 805360784Sdim auto sectCreateFile = std::make_unique<mach_o::SectCreateFile>(); 806292934Sdim _sectCreateFile = sectCreateFile.get(); 807360784Sdim getNodes().push_back(std::make_unique<FileNode>(std::move(sectCreateFile))); 808292934Sdim } 809292934Sdim 810292934Sdim assert(_sectCreateFile && "sectcreate file does not exist."); 811292934Sdim _sectCreateFile->addSection(seg, sect, std::move(content)); 812292934Sdim} 813292934Sdim 814280461Sdimbool MachOLinkingContext::sectionAligned(StringRef seg, StringRef sect, 815292934Sdim uint16_t &align) const { 816280461Sdim for (const SectionAlign &entry : _sectAligns) { 817280461Sdim if (seg.equals(entry.segmentName) && sect.equals(entry.sectionName)) { 818292934Sdim align = entry.align; 819280461Sdim return true; 820280461Sdim } 821280461Sdim } 822280461Sdim return false; 823280461Sdim} 824280461Sdim 825280461Sdimvoid MachOLinkingContext::addExportSymbol(StringRef sym) { 826280461Sdim // Support old crufty export lists with bogus entries. 827280461Sdim if (sym.endswith(".eh") || sym.startswith(".objc_category_name_")) { 828280461Sdim llvm::errs() << "warning: ignoring " << sym << " in export list\n"; 829280461Sdim return; 830280461Sdim } 831280461Sdim // Only i386 MacOSX uses old ABI, so don't change those. 832280461Sdim if ((_os != OS::macOSX) || (_arch != arch_x86)) { 833360784Sdim // ObjC has two different ABIs. Be nice and allow one export list work for 834280461Sdim // both ABIs by renaming symbols. 835280461Sdim if (sym.startswith(".objc_class_name_")) { 836280461Sdim std::string abi2className("_OBJC_CLASS_$_"); 837280461Sdim abi2className += sym.substr(17); 838280461Sdim _exportedSymbols.insert(copy(abi2className)); 839280461Sdim std::string abi2metaclassName("_OBJC_METACLASS_$_"); 840280461Sdim abi2metaclassName += sym.substr(17); 841280461Sdim _exportedSymbols.insert(copy(abi2metaclassName)); 842280461Sdim return; 843280461Sdim } 844280461Sdim } 845280461Sdim 846280461Sdim // FIXME: Support wildcards. 847280461Sdim _exportedSymbols.insert(sym); 848280461Sdim} 849280461Sdim 850280461Sdimbool MachOLinkingContext::exportSymbolNamed(StringRef sym) const { 851280461Sdim switch (_exportMode) { 852280461Sdim case ExportMode::globals: 853280461Sdim llvm_unreachable("exportSymbolNamed() should not be called in this mode"); 854280461Sdim break; 855280461Sdim case ExportMode::whiteList: 856280461Sdim return _exportedSymbols.count(sym); 857280461Sdim case ExportMode::blackList: 858280461Sdim return !_exportedSymbols.count(sym); 859280461Sdim } 860280461Sdim llvm_unreachable("_exportMode unknown enum value"); 861280461Sdim} 862280461Sdim 863280461Sdimstd::string MachOLinkingContext::demangle(StringRef symbolName) const { 864280461Sdim // Only try to demangle symbols if -demangle on command line 865280461Sdim if (!demangleSymbols()) 866280461Sdim return symbolName; 867280461Sdim 868280461Sdim // Only try to demangle symbols that look like C++ symbols 869280461Sdim if (!symbolName.startswith("__Z")) 870280461Sdim return symbolName; 871280461Sdim 872280461Sdim SmallString<256> symBuff; 873280461Sdim StringRef nullTermSym = Twine(symbolName).toNullTerminatedStringRef(symBuff); 874280461Sdim // Mach-O has extra leading underscore that needs to be removed. 875280461Sdim const char *cstr = nullTermSym.data() + 1; 876280461Sdim int status; 877314564Sdim char *demangled = llvm::itaniumDemangle(cstr, nullptr, nullptr, &status); 878292934Sdim if (demangled) { 879280461Sdim std::string result(demangled); 880280461Sdim // __cxa_demangle() always uses a malloc'ed buffer to return the result. 881280461Sdim free(demangled); 882280461Sdim return result; 883280461Sdim } 884280461Sdim 885280461Sdim return symbolName; 886280461Sdim} 887280461Sdim 888314564Sdimstatic void addDependencyInfoHelper(llvm::raw_fd_ostream *DepInfo, 889314564Sdim char Opcode, StringRef Path) { 890314564Sdim if (!DepInfo) 891314564Sdim return; 892314564Sdim 893314564Sdim *DepInfo << Opcode; 894314564Sdim *DepInfo << Path; 895314564Sdim *DepInfo << '\0'; 896314564Sdim} 897314564Sdim 898280461Sdimstd::error_code MachOLinkingContext::createDependencyFile(StringRef path) { 899280461Sdim std::error_code ec; 900360784Sdim _dependencyInfo = std::unique_ptr<llvm::raw_fd_ostream>( 901360784Sdim new llvm::raw_fd_ostream(path, ec, llvm::sys::fs::OF_None)); 902280461Sdim if (ec) { 903280461Sdim _dependencyInfo.reset(); 904280461Sdim return ec; 905280461Sdim } 906280461Sdim 907314564Sdim addDependencyInfoHelper(_dependencyInfo.get(), 0x00, "lld" /*FIXME*/); 908280461Sdim return std::error_code(); 909280461Sdim} 910280461Sdim 911280461Sdimvoid MachOLinkingContext::addInputFileDependency(StringRef path) const { 912314564Sdim addDependencyInfoHelper(_dependencyInfo.get(), 0x10, path); 913280461Sdim} 914280461Sdim 915280461Sdimvoid MachOLinkingContext::addInputFileNotFound(StringRef path) const { 916314564Sdim addDependencyInfoHelper(_dependencyInfo.get(), 0x11, path); 917280461Sdim} 918280461Sdim 919280461Sdimvoid MachOLinkingContext::addOutputFileDependency(StringRef path) const { 920314564Sdim addDependencyInfoHelper(_dependencyInfo.get(), 0x40, path); 921280461Sdim} 922280461Sdim 923280461Sdimvoid MachOLinkingContext::appendOrderedSymbol(StringRef symbol, 924280461Sdim StringRef filename) { 925280461Sdim // To support sorting static functions which may have the same name in 926280461Sdim // multiple .o files, _orderFiles maps the symbol name to a vector 927280461Sdim // of OrderFileNode each of which can specify a file prefix. 928280461Sdim OrderFileNode info; 929280461Sdim if (!filename.empty()) 930280461Sdim info.fileFilter = copy(filename); 931280461Sdim info.order = _orderFileEntries++; 932280461Sdim _orderFiles[symbol].push_back(info); 933280461Sdim} 934280461Sdim 935280461Sdimbool 936280461SdimMachOLinkingContext::findOrderOrdinal(const std::vector<OrderFileNode> &nodes, 937280461Sdim const DefinedAtom *atom, 938280461Sdim unsigned &ordinal) { 939280461Sdim const File *objFile = &atom->file(); 940280461Sdim assert(objFile); 941280461Sdim StringRef objName = objFile->path(); 942280461Sdim std::pair<StringRef, StringRef> dirAndLeaf = objName.rsplit('/'); 943280461Sdim if (!dirAndLeaf.second.empty()) 944280461Sdim objName = dirAndLeaf.second; 945280461Sdim for (const OrderFileNode &info : nodes) { 946280461Sdim if (info.fileFilter.empty()) { 947280461Sdim // Have unprefixed symbol name in order file that matches this atom. 948280461Sdim ordinal = info.order; 949280461Sdim return true; 950280461Sdim } 951280461Sdim if (info.fileFilter.equals(objName)) { 952280461Sdim // Have prefixed symbol name in order file that matches atom's path. 953280461Sdim ordinal = info.order; 954280461Sdim return true; 955280461Sdim } 956280461Sdim } 957280461Sdim return false; 958280461Sdim} 959280461Sdim 960280461Sdimbool MachOLinkingContext::customAtomOrderer(const DefinedAtom *left, 961280461Sdim const DefinedAtom *right, 962280461Sdim bool &leftBeforeRight) const { 963280461Sdim // No custom sorting if no order file entries. 964280461Sdim if (!_orderFileEntries) 965280461Sdim return false; 966280461Sdim 967280461Sdim // Order files can only order named atoms. 968280461Sdim StringRef leftName = left->name(); 969280461Sdim StringRef rightName = right->name(); 970280461Sdim if (leftName.empty() || rightName.empty()) 971280461Sdim return false; 972280461Sdim 973280461Sdim // If neither is in order file list, no custom sorter. 974280461Sdim auto leftPos = _orderFiles.find(leftName); 975280461Sdim auto rightPos = _orderFiles.find(rightName); 976280461Sdim bool leftIsOrdered = (leftPos != _orderFiles.end()); 977280461Sdim bool rightIsOrdered = (rightPos != _orderFiles.end()); 978280461Sdim if (!leftIsOrdered && !rightIsOrdered) 979280461Sdim return false; 980280461Sdim 981280461Sdim // There could be multiple symbols with same name but different file prefixes. 982280461Sdim unsigned leftOrder; 983280461Sdim unsigned rightOrder; 984280461Sdim bool foundLeft = 985280461Sdim leftIsOrdered && findOrderOrdinal(leftPos->getValue(), left, leftOrder); 986280461Sdim bool foundRight = rightIsOrdered && 987280461Sdim findOrderOrdinal(rightPos->getValue(), right, rightOrder); 988280461Sdim if (!foundLeft && !foundRight) 989280461Sdim return false; 990280461Sdim 991280461Sdim // If only one is in order file list, ordered one goes first. 992280461Sdim if (foundLeft != foundRight) 993280461Sdim leftBeforeRight = foundLeft; 994280461Sdim else 995280461Sdim leftBeforeRight = (leftOrder < rightOrder); 996280461Sdim 997280461Sdim return true; 998280461Sdim} 999280461Sdim 1000280461Sdimstatic bool isLibrary(const std::unique_ptr<Node> &elem) { 1001280461Sdim if (FileNode *node = dyn_cast<FileNode>(const_cast<Node *>(elem.get()))) { 1002280461Sdim File *file = node->getFile(); 1003280461Sdim return isa<SharedLibraryFile>(file) || isa<ArchiveLibraryFile>(file); 1004280461Sdim } 1005280461Sdim return false; 1006280461Sdim} 1007280461Sdim 1008280461Sdim// The darwin linker processes input files in two phases. The first phase 1009280461Sdim// links in all object (.o) files in command line order. The second phase 1010280461Sdim// links in libraries in command line order. 1011280461Sdim// In this function we reorder the input files so that all the object files 1012280461Sdim// comes before any library file. We also make a group for the library files 1013280461Sdim// so that the Resolver will reiterate over the libraries as long as we find 1014280461Sdim// new undefines from libraries. 1015280461Sdimvoid MachOLinkingContext::finalizeInputFiles() { 1016280461Sdim std::vector<std::unique_ptr<Node>> &elements = getNodes(); 1017353358Sdim llvm::stable_sort(elements, [](const std::unique_ptr<Node> &a, 1018353358Sdim const std::unique_ptr<Node> &b) { 1019353358Sdim return !isLibrary(a) && isLibrary(b); 1020353358Sdim }); 1021280461Sdim size_t numLibs = std::count_if(elements.begin(), elements.end(), isLibrary); 1022360784Sdim elements.push_back(std::make_unique<GroupEnd>(numLibs)); 1023280461Sdim} 1024280461Sdim 1025303239Sdimllvm::Error MachOLinkingContext::handleLoadedFile(File &file) { 1026303239Sdim auto *machoFile = dyn_cast<MachOFile>(&file); 1027303239Sdim if (!machoFile) 1028314564Sdim return llvm::Error::success(); 1029303239Sdim 1030303239Sdim // Check that the arch of the context matches that of the file. 1031303239Sdim // Also set the arch of the context if it didn't have one. 1032303239Sdim if (_arch == arch_unknown) { 1033303239Sdim _arch = machoFile->arch(); 1034303239Sdim } else if (machoFile->arch() != arch_unknown && machoFile->arch() != _arch) { 1035303239Sdim // Archs are different. 1036303239Sdim return llvm::make_error<GenericError>(file.path() + 1037303239Sdim Twine(" cannot be linked due to incompatible architecture")); 1038303239Sdim } 1039303239Sdim 1040303239Sdim // Check that the OS of the context matches that of the file. 1041303239Sdim // Also set the OS of the context if it didn't have one. 1042303239Sdim if (_os == OS::unknown) { 1043303239Sdim _os = machoFile->OS(); 1044303239Sdim } else if (machoFile->OS() != OS::unknown && machoFile->OS() != _os) { 1045303239Sdim // OSes are different. 1046303239Sdim return llvm::make_error<GenericError>(file.path() + 1047303239Sdim Twine(" cannot be linked due to incompatible operating systems")); 1048303239Sdim } 1049303239Sdim 1050303239Sdim // Check that if the objc info exists, that it is compatible with the target 1051303239Sdim // OS. 1052303239Sdim switch (machoFile->objcConstraint()) { 1053303239Sdim case objc_unknown: 1054303239Sdim // The file is not compiled with objc, so skip the checks. 1055303239Sdim break; 1056303239Sdim case objc_gc_only: 1057303239Sdim case objc_supports_gc: 1058303239Sdim llvm_unreachable("GC support should already have thrown an error"); 1059303239Sdim case objc_retainReleaseForSimulator: 1060303239Sdim // The file is built with simulator objc, so make sure that the context 1061303239Sdim // is also building with simulator support. 1062303239Sdim if (_os != OS::iOS_simulator) 1063303239Sdim return llvm::make_error<GenericError>(file.path() + 1064303239Sdim Twine(" cannot be linked. It contains ObjC built for the simulator" 1065303239Sdim " while we are linking a non-simulator target")); 1066303239Sdim assert((_objcConstraint == objc_unknown || 1067303239Sdim _objcConstraint == objc_retainReleaseForSimulator) && 1068303239Sdim "Must be linking with retain/release for the simulator"); 1069303239Sdim _objcConstraint = objc_retainReleaseForSimulator; 1070303239Sdim break; 1071303239Sdim case objc_retainRelease: 1072303239Sdim // The file is built without simulator objc, so make sure that the 1073303239Sdim // context is also building without simulator support. 1074303239Sdim if (_os == OS::iOS_simulator) 1075303239Sdim return llvm::make_error<GenericError>(file.path() + 1076303239Sdim Twine(" cannot be linked. It contains ObjC built for a non-simulator" 1077303239Sdim " target while we are linking a simulator target")); 1078303239Sdim assert((_objcConstraint == objc_unknown || 1079303239Sdim _objcConstraint == objc_retainRelease) && 1080303239Sdim "Must be linking with retain/release for a non-simulator target"); 1081303239Sdim _objcConstraint = objc_retainRelease; 1082303239Sdim break; 1083303239Sdim } 1084303239Sdim 1085303239Sdim // Check that the swift version of the context matches that of the file. 1086303239Sdim // Also set the swift version of the context if it didn't have one. 1087303239Sdim if (!_swiftVersion) { 1088303239Sdim _swiftVersion = machoFile->swiftVersion(); 1089303239Sdim } else if (machoFile->swiftVersion() && 1090303239Sdim machoFile->swiftVersion() != _swiftVersion) { 1091303239Sdim // Swift versions are different. 1092303239Sdim return llvm::make_error<GenericError>("different swift versions"); 1093303239Sdim } 1094303239Sdim 1095314564Sdim return llvm::Error::success(); 1096303239Sdim} 1097303239Sdim 1098280461Sdim} // end namespace lld 1099