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