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