summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/tools/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2020-08-03 15:06:44 +0000
committerpatrick <patrick@openbsd.org>2020-08-03 15:06:44 +0000
commitb64793999546ed8adebaeebd9d8345d18db8927d (patch)
tree4357c27b561d73b0e089727c6ed659f2ceff5f47 /gnu/llvm/tools/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
parentAdd support for UTF-8 DISPLAY-HINTs with octet length. For now only (diff)
downloadwireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.tar.xz
wireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.zip
Remove LLVM 8.0.1 files.
Diffstat (limited to 'gnu/llvm/tools/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp')
-rw-r--r--gnu/llvm/tools/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp1101
1 files changed, 0 insertions, 1101 deletions
diff --git a/gnu/llvm/tools/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp b/gnu/llvm/tools/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
deleted file mode 100644
index 61583963ddd..00000000000
--- a/gnu/llvm/tools/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
+++ /dev/null
@@ -1,1101 +0,0 @@
-//===- lib/ReaderWriter/MachO/MachOLinkingContext.cpp ---------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Common/ErrorHandler.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "ArchHandler.h"
-#include "File.h"
-#include "FlatNamespaceFile.h"
-#include "MachONormalizedFile.h"
-#include "MachOPasses.h"
-#include "SectCreateFile.h"
-#include "lld/Common/Driver.h"
-#include "lld/Core/ArchiveLibraryFile.h"
-#include "lld/Core/PassManager.h"
-#include "lld/Core/Reader.h"
-#include "lld/Core/Writer.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Demangle/Demangle.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/Path.h"
-#include <algorithm>
-
-using lld::mach_o::ArchHandler;
-using lld::mach_o::MachOFile;
-using lld::mach_o::MachODylibFile;
-using namespace llvm::MachO;
-
-namespace lld {
-
-bool MachOLinkingContext::parsePackedVersion(StringRef str, uint32_t &result) {
- result = 0;
-
- if (str.empty())
- return false;
-
- SmallVector<StringRef, 3> parts;
- llvm::SplitString(str, parts, ".");
-
- unsigned long long num;
- if (llvm::getAsUnsignedInteger(parts[0], 10, num))
- return true;
- if (num > 65535)
- return true;
- result = num << 16;
-
- if (parts.size() > 1) {
- if (llvm::getAsUnsignedInteger(parts[1], 10, num))
- return true;
- if (num > 255)
- return true;
- result |= (num << 8);
- }
-
- if (parts.size() > 2) {
- if (llvm::getAsUnsignedInteger(parts[2], 10, num))
- return true;
- if (num > 255)
- return true;
- result |= num;
- }
-
- return false;
-}
-
-bool MachOLinkingContext::parsePackedVersion(StringRef str, uint64_t &result) {
- result = 0;
-
- if (str.empty())
- return false;
-
- SmallVector<StringRef, 5> parts;
- llvm::SplitString(str, parts, ".");
-
- unsigned long long num;
- if (llvm::getAsUnsignedInteger(parts[0], 10, num))
- return true;
- if (num > 0xFFFFFF)
- return true;
- result = num << 40;
-
- unsigned Shift = 30;
- for (StringRef str : llvm::makeArrayRef(parts).slice(1)) {
- if (llvm::getAsUnsignedInteger(str, 10, num))
- return true;
- if (num > 0x3FF)
- return true;
- result |= (num << Shift);
- Shift -= 10;
- }
-
- return false;
-}
-
-MachOLinkingContext::ArchInfo MachOLinkingContext::_s_archInfos[] = {
- { "x86_64", arch_x86_64, true, CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL },
- { "i386", arch_x86, true, CPU_TYPE_I386, CPU_SUBTYPE_X86_ALL },
- { "ppc", arch_ppc, false, CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL },
- { "armv6", arch_armv6, true, CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6 },
- { "armv7", arch_armv7, true, CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7 },
- { "armv7s", arch_armv7s, true, CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7S },
- { "arm64", arch_arm64, true, CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_ALL },
- { "", arch_unknown,false, 0, 0 }
-};
-
-MachOLinkingContext::Arch
-MachOLinkingContext::archFromCpuType(uint32_t cputype, uint32_t cpusubtype) {
- for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
- if ((info->cputype == cputype) && (info->cpusubtype == cpusubtype))
- return info->arch;
- }
- return arch_unknown;
-}
-
-MachOLinkingContext::Arch
-MachOLinkingContext::archFromName(StringRef archName) {
- for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
- if (info->archName.equals(archName))
- return info->arch;
- }
- return arch_unknown;
-}
-
-StringRef MachOLinkingContext::nameFromArch(Arch arch) {
- for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
- if (info->arch == arch)
- return info->archName;
- }
- return "<unknown>";
-}
-
-uint32_t MachOLinkingContext::cpuTypeFromArch(Arch arch) {
- assert(arch != arch_unknown);
- for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
- if (info->arch == arch)
- return info->cputype;
- }
- llvm_unreachable("Unknown arch type");
-}
-
-uint32_t MachOLinkingContext::cpuSubtypeFromArch(Arch arch) {
- assert(arch != arch_unknown);
- for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
- if (info->arch == arch)
- return info->cpusubtype;
- }
- llvm_unreachable("Unknown arch type");
-}
-
-bool MachOLinkingContext::isThinObjectFile(StringRef path, Arch &arch) {
- return mach_o::normalized::isThinObjectFile(path, arch);
-}
-
-bool MachOLinkingContext::sliceFromFatFile(MemoryBufferRef mb, uint32_t &offset,
- uint32_t &size) {
- return mach_o::normalized::sliceFromFatFile(mb, _arch, offset, size);
-}
-
-MachOLinkingContext::MachOLinkingContext() {}
-
-MachOLinkingContext::~MachOLinkingContext() {
- // Atoms are allocated on BumpPtrAllocator's on File's.
- // As we transfer atoms from one file to another, we need to clear all of the
- // atoms before we remove any of the BumpPtrAllocator's.
- auto &nodes = getNodes();
- for (unsigned i = 0, e = nodes.size(); i != e; ++i) {
- FileNode *node = dyn_cast<FileNode>(nodes[i].get());
- if (!node)
- continue;
- File *file = node->getFile();
- file->clearAtoms();
- }
-}
-
-void MachOLinkingContext::configure(HeaderFileType type, Arch arch, OS os,
- uint32_t minOSVersion,
- bool exportDynamicSymbols) {
- _outputMachOType = type;
- _arch = arch;
- _os = os;
- _osMinVersion = minOSVersion;
-
- // If min OS not specified on command line, use reasonable defaults.
- // Note that we only do sensible defaults when emitting something other than
- // object and preload.
- if (_outputMachOType != llvm::MachO::MH_OBJECT &&
- _outputMachOType != llvm::MachO::MH_PRELOAD) {
- if (minOSVersion == 0) {
- switch (_arch) {
- case arch_x86_64:
- case arch_x86:
- parsePackedVersion("10.8", _osMinVersion);
- _os = MachOLinkingContext::OS::macOSX;
- break;
- case arch_armv6:
- case arch_armv7:
- case arch_armv7s:
- case arch_arm64:
- parsePackedVersion("7.0", _osMinVersion);
- _os = MachOLinkingContext::OS::iOS;
- break;
- default:
- break;
- }
- }
- }
-
- switch (_outputMachOType) {
- case llvm::MachO::MH_EXECUTE:
- // If targeting newer OS, use _main
- if (minOS("10.8", "6.0")) {
- _entrySymbolName = "_main";
- } else {
- // If targeting older OS, use start (in crt1.o)
- _entrySymbolName = "start";
- }
-
- // __PAGEZERO defaults to 4GB on 64-bit (except for PP64 which lld does not
- // support) and 4KB on 32-bit.
- if (is64Bit(_arch)) {
- _pageZeroSize = 0x100000000;
- } else {
- _pageZeroSize = 0x1000;
- }
-
- // Initial base address is __PAGEZERO size.
- _baseAddress = _pageZeroSize;
-
- // Make PIE by default when targetting newer OSs.
- switch (os) {
- case OS::macOSX:
- if (minOSVersion >= 0x000A0700) // MacOSX 10.7
- _pie = true;
- break;
- case OS::iOS:
- if (minOSVersion >= 0x00040300) // iOS 4.3
- _pie = true;
- break;
- case OS::iOS_simulator:
- _pie = true;
- break;
- case OS::unknown:
- break;
- }
- setGlobalsAreDeadStripRoots(exportDynamicSymbols);
- break;
- case llvm::MachO::MH_DYLIB:
- setGlobalsAreDeadStripRoots(exportDynamicSymbols);
- break;
- case llvm::MachO::MH_BUNDLE:
- break;
- case llvm::MachO::MH_OBJECT:
- _printRemainingUndefines = false;
- _allowRemainingUndefines = true;
- break;
- default:
- break;
- }
-
- // Set default segment page sizes based on arch.
- if (arch == arch_arm64)
- _pageSize = 4*4096;
-}
-
-uint32_t MachOLinkingContext::getCPUType() const {
- return cpuTypeFromArch(_arch);
-}
-
-uint32_t MachOLinkingContext::getCPUSubType() const {
- return cpuSubtypeFromArch(_arch);
-}
-
-bool MachOLinkingContext::is64Bit(Arch arch) {
- for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
- if (info->arch == arch) {
- return (info->cputype & CPU_ARCH_ABI64);
- }
- }
- // unknown archs are not 64-bit.
- return false;
-}
-
-bool MachOLinkingContext::isHostEndian(Arch arch) {
- assert(arch != arch_unknown);
- for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
- if (info->arch == arch) {
- return (info->littleEndian == llvm::sys::IsLittleEndianHost);
- }
- }
- llvm_unreachable("Unknown arch type");
-}
-
-bool MachOLinkingContext::isBigEndian(Arch arch) {
- assert(arch != arch_unknown);
- for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
- if (info->arch == arch) {
- return ! info->littleEndian;
- }
- }
- llvm_unreachable("Unknown arch type");
-}
-
-bool MachOLinkingContext::is64Bit() const {
- return is64Bit(_arch);
-}
-
-bool MachOLinkingContext::outputTypeHasEntry() const {
- switch (_outputMachOType) {
- case MH_EXECUTE:
- case MH_DYLINKER:
- case MH_PRELOAD:
- return true;
- default:
- return false;
- }
-}
-
-bool MachOLinkingContext::needsStubsPass() const {
- switch (_outputMachOType) {
- case MH_EXECUTE:
- return !_outputMachOTypeStatic;
- case MH_DYLIB:
- case MH_BUNDLE:
- return true;
- default:
- return false;
- }
-}
-
-bool MachOLinkingContext::needsGOTPass() const {
- // GOT pass not used in -r mode.
- if (_outputMachOType == MH_OBJECT)
- return false;
- // Only some arches use GOT pass.
- switch (_arch) {
- case arch_x86_64:
- case arch_arm64:
- return true;
- default:
- return false;
- }
-}
-
-bool MachOLinkingContext::needsCompactUnwindPass() const {
- switch (_outputMachOType) {
- case MH_EXECUTE:
- case MH_DYLIB:
- case MH_BUNDLE:
- return archHandler().needsCompactUnwind();
- default:
- return false;
- }
-}
-
-bool MachOLinkingContext::needsObjCPass() const {
- // ObjC pass is only needed if any of the inputs were ObjC.
- return _objcConstraint != objc_unknown;
-}
-
-bool MachOLinkingContext::needsShimPass() const {
- // Shim pass only used in final executables.
- if (_outputMachOType == MH_OBJECT)
- return false;
- // Only 32-bit arm arches use Shim pass.
- switch (_arch) {
- case arch_armv6:
- case arch_armv7:
- case arch_armv7s:
- return true;
- default:
- return false;
- }
-}
-
-bool MachOLinkingContext::needsTLVPass() const {
- switch (_outputMachOType) {
- case MH_BUNDLE:
- case MH_EXECUTE:
- case MH_DYLIB:
- return true;
- default:
- return false;
- }
-}
-
-StringRef MachOLinkingContext::binderSymbolName() const {
- return archHandler().stubInfo().binderSymbolName;
-}
-
-bool MachOLinkingContext::minOS(StringRef mac, StringRef iOS) const {
- uint32_t parsedVersion;
- switch (_os) {
- case OS::macOSX:
- if (parsePackedVersion(mac, parsedVersion))
- return false;
- return _osMinVersion >= parsedVersion;
- case OS::iOS:
- case OS::iOS_simulator:
- if (parsePackedVersion(iOS, parsedVersion))
- return false;
- return _osMinVersion >= parsedVersion;
- case OS::unknown:
- // If we don't know the target, then assume that we don't meet the min OS.
- // This matches the ld64 behaviour
- return false;
- }
- llvm_unreachable("invalid OS enum");
-}
-
-bool MachOLinkingContext::addEntryPointLoadCommand() const {
- if ((_outputMachOType == MH_EXECUTE) && !_outputMachOTypeStatic) {
- return minOS("10.8", "6.0");
- }
- return false;
-}
-
-bool MachOLinkingContext::addUnixThreadLoadCommand() const {
- switch (_outputMachOType) {
- case MH_EXECUTE:
- if (_outputMachOTypeStatic)
- return true;
- else
- return !minOS("10.8", "6.0");
- break;
- case MH_DYLINKER:
- case MH_PRELOAD:
- return true;
- default:
- return false;
- }
-}
-
-bool MachOLinkingContext::pathExists(StringRef path) const {
- if (!_testingFileUsage)
- return llvm::sys::fs::exists(path.str());
-
- // Otherwise, we're in test mode: only files explicitly provided on the
- // command-line exist.
- std::string key = path.str();
- std::replace(key.begin(), key.end(), '\\', '/');
- return _existingPaths.find(key) != _existingPaths.end();
-}
-
-bool MachOLinkingContext::fileExists(StringRef path) const {
- bool found = pathExists(path);
- // Log search misses.
- if (!found)
- addInputFileNotFound(path);
-
- // When testing, file is never opened, so logging is done here.
- if (_testingFileUsage && found)
- addInputFileDependency(path);
-
- return found;
-}
-
-void MachOLinkingContext::setSysLibRoots(const StringRefVector &paths) {
- _syslibRoots = paths;
-}
-
-void MachOLinkingContext::addRpath(StringRef rpath) {
- _rpaths.push_back(rpath);
-}
-
-void MachOLinkingContext::addModifiedSearchDir(StringRef libPath,
- bool isSystemPath) {
- bool addedModifiedPath = false;
-
- // -syslibroot only applies to absolute paths.
- if (libPath.startswith("/")) {
- for (auto syslibRoot : _syslibRoots) {
- SmallString<256> path(syslibRoot);
- llvm::sys::path::append(path, libPath);
- if (pathExists(path)) {
- _searchDirs.push_back(path.str().copy(_allocator));
- addedModifiedPath = true;
- }
- }
- }
-
- if (addedModifiedPath)
- return;
-
- // Finally, if only one -syslibroot is given, system paths which aren't in it
- // get suppressed.
- if (_syslibRoots.size() != 1 || !isSystemPath) {
- if (pathExists(libPath)) {
- _searchDirs.push_back(libPath);
- }
- }
-}
-
-void MachOLinkingContext::addFrameworkSearchDir(StringRef fwPath,
- bool isSystemPath) {
- bool pathAdded = false;
-
- // -syslibroot only used with to absolute framework search paths.
- if (fwPath.startswith("/")) {
- for (auto syslibRoot : _syslibRoots) {
- SmallString<256> path(syslibRoot);
- llvm::sys::path::append(path, fwPath);
- if (pathExists(path)) {
- _frameworkDirs.push_back(path.str().copy(_allocator));
- pathAdded = true;
- }
- }
- }
- // If fwPath found in any -syslibroot, then done.
- if (pathAdded)
- return;
-
- // If only one -syslibroot, system paths not in that SDK are suppressed.
- if (isSystemPath && (_syslibRoots.size() == 1))
- return;
-
- // Only use raw fwPath if that directory exists.
- if (pathExists(fwPath))
- _frameworkDirs.push_back(fwPath);
-}
-
-llvm::Optional<StringRef>
-MachOLinkingContext::searchDirForLibrary(StringRef path,
- StringRef libName) const {
- SmallString<256> fullPath;
- if (libName.endswith(".o")) {
- // A request ending in .o is special: just search for the file directly.
- fullPath.assign(path);
- llvm::sys::path::append(fullPath, libName);
- if (fileExists(fullPath))
- return fullPath.str().copy(_allocator);
- return llvm::None;
- }
-
- // Search for dynamic library
- fullPath.assign(path);
- llvm::sys::path::append(fullPath, Twine("lib") + libName + ".dylib");
- if (fileExists(fullPath))
- return fullPath.str().copy(_allocator);
-
- // If not, try for a static library
- fullPath.assign(path);
- llvm::sys::path::append(fullPath, Twine("lib") + libName + ".a");
- if (fileExists(fullPath))
- return fullPath.str().copy(_allocator);
-
- return llvm::None;
-}
-
-llvm::Optional<StringRef>
-MachOLinkingContext::searchLibrary(StringRef libName) const {
- SmallString<256> path;
- for (StringRef dir : searchDirs()) {
- llvm::Optional<StringRef> searchDir = searchDirForLibrary(dir, libName);
- if (searchDir)
- return searchDir;
- }
-
- return llvm::None;
-}
-
-llvm::Optional<StringRef>
-MachOLinkingContext::findPathForFramework(StringRef fwName) const{
- SmallString<256> fullPath;
- for (StringRef dir : frameworkDirs()) {
- fullPath.assign(dir);
- llvm::sys::path::append(fullPath, Twine(fwName) + ".framework", fwName);
- if (fileExists(fullPath))
- return fullPath.str().copy(_allocator);
- }
-
- return llvm::None;
-}
-
-bool MachOLinkingContext::validateImpl() {
- // TODO: if -arch not specified, look at arch of first .o file.
-
- if (_currentVersion && _outputMachOType != MH_DYLIB) {
- error("-current_version can only be used with dylibs");
- return false;
- }
-
- if (_compatibilityVersion && _outputMachOType != MH_DYLIB) {
- error("-compatibility_version can only be used with dylibs");
- return false;
- }
-
- if (_deadStrippableDylib && _outputMachOType != MH_DYLIB) {
- error("-mark_dead_strippable_dylib can only be used with dylibs");
- return false;
- }
-
- if (!_bundleLoader.empty() && outputMachOType() != MH_BUNDLE) {
- error("-bundle_loader can only be used with Mach-O bundles");
- return false;
- }
-
- // If -exported_symbols_list used, all exported symbols must be defined.
- if (_exportMode == ExportMode::whiteList) {
- for (const auto &symbol : _exportedSymbols)
- addInitialUndefinedSymbol(symbol.getKey());
- }
-
- // If -dead_strip, set up initial live symbols.
- if (deadStrip()) {
- // Entry point is live.
- if (outputTypeHasEntry())
- addDeadStripRoot(entrySymbolName());
- // Lazy binding helper is live.
- if (needsStubsPass())
- addDeadStripRoot(binderSymbolName());
- // If using -exported_symbols_list, make all exported symbols live.
- if (_exportMode == ExportMode::whiteList) {
- setGlobalsAreDeadStripRoots(false);
- for (const auto &symbol : _exportedSymbols)
- addDeadStripRoot(symbol.getKey());
- }
- }
-
- addOutputFileDependency(outputPath());
-
- return true;
-}
-
-void MachOLinkingContext::addPasses(PassManager &pm) {
- // objc pass should be before layout pass. Otherwise test cases may contain
- // no atoms which confuses the layout pass.
- if (needsObjCPass())
- mach_o::addObjCPass(pm, *this);
- mach_o::addLayoutPass(pm, *this);
- if (needsStubsPass())
- mach_o::addStubsPass(pm, *this);
- if (needsCompactUnwindPass())
- mach_o::addCompactUnwindPass(pm, *this);
- if (needsGOTPass())
- mach_o::addGOTPass(pm, *this);
- if (needsTLVPass())
- mach_o::addTLVPass(pm, *this);
- if (needsShimPass())
- mach_o::addShimPass(pm, *this); // Shim pass must run after stubs pass.
-}
-
-Writer &MachOLinkingContext::writer() const {
- if (!_writer)
- _writer = createWriterMachO(*this);
- return *_writer;
-}
-
-ErrorOr<std::unique_ptr<MemoryBuffer>>
-MachOLinkingContext::getMemoryBuffer(StringRef path) {
- addInputFileDependency(path);
-
- ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr =
- MemoryBuffer::getFileOrSTDIN(path);
- if (std::error_code ec = mbOrErr.getError())
- return ec;
- std::unique_ptr<MemoryBuffer> mb = std::move(mbOrErr.get());
-
- // If buffer contains a fat file, find required arch in fat buffer
- // and switch buffer to point to just that required slice.
- uint32_t offset;
- uint32_t size;
- if (sliceFromFatFile(mb->getMemBufferRef(), offset, size))
- return MemoryBuffer::getFileSlice(path, size, offset);
- return std::move(mb);
-}
-
-MachODylibFile* MachOLinkingContext::loadIndirectDylib(StringRef path) {
- ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr = getMemoryBuffer(path);
- if (mbOrErr.getError())
- return nullptr;
-
- ErrorOr<std::unique_ptr<File>> fileOrErr =
- registry().loadFile(std::move(mbOrErr.get()));
- if (!fileOrErr)
- return nullptr;
- std::unique_ptr<File> &file = fileOrErr.get();
- file->parse();
- MachODylibFile *result = reinterpret_cast<MachODylibFile *>(file.get());
- // Node object now owned by _indirectDylibs vector.
- _indirectDylibs.push_back(std::move(file));
- return result;
-}
-
-MachODylibFile* MachOLinkingContext::findIndirectDylib(StringRef path) {
- // See if already loaded.
- auto pos = _pathToDylibMap.find(path);
- if (pos != _pathToDylibMap.end())
- return pos->second;
-
- // Search -L paths if of the form "libXXX.dylib"
- std::pair<StringRef, StringRef> split = path.rsplit('/');
- StringRef leafName = split.second;
- if (leafName.startswith("lib") && leafName.endswith(".dylib")) {
- // FIXME: Need to enhance searchLibrary() to only look for .dylib
- auto libPath = searchLibrary(leafName);
- if (libPath)
- return loadIndirectDylib(libPath.getValue());
- }
-
- // Try full path with sysroot.
- for (StringRef sysPath : _syslibRoots) {
- SmallString<256> fullPath;
- fullPath.assign(sysPath);
- llvm::sys::path::append(fullPath, path);
- if (pathExists(fullPath))
- return loadIndirectDylib(fullPath);
- }
-
- // Try full path.
- if (pathExists(path)) {
- return loadIndirectDylib(path);
- }
-
- return nullptr;
-}
-
-uint32_t MachOLinkingContext::dylibCurrentVersion(StringRef installName) const {
- auto pos = _pathToDylibMap.find(installName);
- if (pos != _pathToDylibMap.end())
- return pos->second->currentVersion();
- else
- return 0x10000; // 1.0
-}
-
-uint32_t MachOLinkingContext::dylibCompatVersion(StringRef installName) const {
- auto pos = _pathToDylibMap.find(installName);
- if (pos != _pathToDylibMap.end())
- return pos->second->compatVersion();
- else
- return 0x10000; // 1.0
-}
-
-void MachOLinkingContext::createImplicitFiles(
- std::vector<std::unique_ptr<File> > &result) {
- // Add indirect dylibs by asking each linked dylib to add its indirects.
- // Iterate until no more dylibs get loaded.
- size_t dylibCount = 0;
- while (dylibCount != _allDylibs.size()) {
- dylibCount = _allDylibs.size();
- for (MachODylibFile *dylib : _allDylibs) {
- dylib->loadReExportedDylibs([this] (StringRef path) -> MachODylibFile* {
- return findIndirectDylib(path); });
- }
- }
-
- // Let writer add output type specific extras.
- writer().createImplicitFiles(result);
-
- // If undefinedMode is != error, add a FlatNamespaceFile instance. This will
- // provide a SharedLibraryAtom for symbols that aren't defined elsewhere.
- if (undefinedMode() != UndefinedMode::error) {
- result.emplace_back(new mach_o::FlatNamespaceFile(*this));
- _flatNamespaceFile = result.back().get();
- }
-}
-
-void MachOLinkingContext::registerDylib(MachODylibFile *dylib,
- bool upward) const {
- std::lock_guard<std::mutex> lock(_dylibsMutex);
-
- if (std::find(_allDylibs.begin(),
- _allDylibs.end(), dylib) == _allDylibs.end())
- _allDylibs.push_back(dylib);
- _pathToDylibMap[dylib->installName()] = dylib;
- // If path is different than install name, register path too.
- if (!dylib->path().equals(dylib->installName()))
- _pathToDylibMap[dylib->path()] = dylib;
- if (upward)
- _upwardDylibs.insert(dylib);
-}
-
-bool MachOLinkingContext::isUpwardDylib(StringRef installName) const {
- for (MachODylibFile *dylib : _upwardDylibs) {
- if (dylib->installName().equals(installName))
- return true;
- }
- return false;
-}
-
-ArchHandler &MachOLinkingContext::archHandler() const {
- if (!_archHandler)
- _archHandler = ArchHandler::create(_arch);
- return *_archHandler;
-}
-
-void MachOLinkingContext::addSectionAlignment(StringRef seg, StringRef sect,
- uint16_t align) {
- SectionAlign entry = { seg, sect, align };
- _sectAligns.push_back(entry);
-}
-
-void MachOLinkingContext::addSectCreateSection(
- StringRef seg, StringRef sect,
- std::unique_ptr<MemoryBuffer> content) {
-
- if (!_sectCreateFile) {
- auto sectCreateFile = llvm::make_unique<mach_o::SectCreateFile>();
- _sectCreateFile = sectCreateFile.get();
- getNodes().push_back(llvm::make_unique<FileNode>(std::move(sectCreateFile)));
- }
-
- assert(_sectCreateFile && "sectcreate file does not exist.");
- _sectCreateFile->addSection(seg, sect, std::move(content));
-}
-
-bool MachOLinkingContext::sectionAligned(StringRef seg, StringRef sect,
- uint16_t &align) const {
- for (const SectionAlign &entry : _sectAligns) {
- if (seg.equals(entry.segmentName) && sect.equals(entry.sectionName)) {
- align = entry.align;
- return true;
- }
- }
- return false;
-}
-
-void MachOLinkingContext::addExportSymbol(StringRef sym) {
- // Support old crufty export lists with bogus entries.
- if (sym.endswith(".eh") || sym.startswith(".objc_category_name_")) {
- llvm::errs() << "warning: ignoring " << sym << " in export list\n";
- return;
- }
- // Only i386 MacOSX uses old ABI, so don't change those.
- if ((_os != OS::macOSX) || (_arch != arch_x86)) {
- // ObjC has two differnent ABIs. Be nice and allow one export list work for
- // both ABIs by renaming symbols.
- if (sym.startswith(".objc_class_name_")) {
- std::string abi2className("_OBJC_CLASS_$_");
- abi2className += sym.substr(17);
- _exportedSymbols.insert(copy(abi2className));
- std::string abi2metaclassName("_OBJC_METACLASS_$_");
- abi2metaclassName += sym.substr(17);
- _exportedSymbols.insert(copy(abi2metaclassName));
- return;
- }
- }
-
- // FIXME: Support wildcards.
- _exportedSymbols.insert(sym);
-}
-
-bool MachOLinkingContext::exportSymbolNamed(StringRef sym) const {
- switch (_exportMode) {
- case ExportMode::globals:
- llvm_unreachable("exportSymbolNamed() should not be called in this mode");
- break;
- case ExportMode::whiteList:
- return _exportedSymbols.count(sym);
- case ExportMode::blackList:
- return !_exportedSymbols.count(sym);
- }
- llvm_unreachable("_exportMode unknown enum value");
-}
-
-std::string MachOLinkingContext::demangle(StringRef symbolName) const {
- // Only try to demangle symbols if -demangle on command line
- if (!demangleSymbols())
- return symbolName;
-
- // Only try to demangle symbols that look like C++ symbols
- if (!symbolName.startswith("__Z"))
- return symbolName;
-
- SmallString<256> symBuff;
- StringRef nullTermSym = Twine(symbolName).toNullTerminatedStringRef(symBuff);
- // Mach-O has extra leading underscore that needs to be removed.
- const char *cstr = nullTermSym.data() + 1;
- int status;
- char *demangled = llvm::itaniumDemangle(cstr, nullptr, nullptr, &status);
- if (demangled) {
- std::string result(demangled);
- // __cxa_demangle() always uses a malloc'ed buffer to return the result.
- free(demangled);
- return result;
- }
-
- return symbolName;
-}
-
-static void addDependencyInfoHelper(llvm::raw_fd_ostream *DepInfo,
- char Opcode, StringRef Path) {
- if (!DepInfo)
- return;
-
- *DepInfo << Opcode;
- *DepInfo << Path;
- *DepInfo << '\0';
-}
-
-std::error_code MachOLinkingContext::createDependencyFile(StringRef path) {
- std::error_code ec;
- _dependencyInfo = std::unique_ptr<llvm::raw_fd_ostream>(new
- llvm::raw_fd_ostream(path, ec, llvm::sys::fs::F_None));
- if (ec) {
- _dependencyInfo.reset();
- return ec;
- }
-
- addDependencyInfoHelper(_dependencyInfo.get(), 0x00, "lld" /*FIXME*/);
- return std::error_code();
-}
-
-void MachOLinkingContext::addInputFileDependency(StringRef path) const {
- addDependencyInfoHelper(_dependencyInfo.get(), 0x10, path);
-}
-
-void MachOLinkingContext::addInputFileNotFound(StringRef path) const {
- addDependencyInfoHelper(_dependencyInfo.get(), 0x11, path);
-}
-
-void MachOLinkingContext::addOutputFileDependency(StringRef path) const {
- addDependencyInfoHelper(_dependencyInfo.get(), 0x40, path);
-}
-
-void MachOLinkingContext::appendOrderedSymbol(StringRef symbol,
- StringRef filename) {
- // To support sorting static functions which may have the same name in
- // multiple .o files, _orderFiles maps the symbol name to a vector
- // of OrderFileNode each of which can specify a file prefix.
- OrderFileNode info;
- if (!filename.empty())
- info.fileFilter = copy(filename);
- info.order = _orderFileEntries++;
- _orderFiles[symbol].push_back(info);
-}
-
-bool
-MachOLinkingContext::findOrderOrdinal(const std::vector<OrderFileNode> &nodes,
- const DefinedAtom *atom,
- unsigned &ordinal) {
- const File *objFile = &atom->file();
- assert(objFile);
- StringRef objName = objFile->path();
- std::pair<StringRef, StringRef> dirAndLeaf = objName.rsplit('/');
- if (!dirAndLeaf.second.empty())
- objName = dirAndLeaf.second;
- for (const OrderFileNode &info : nodes) {
- if (info.fileFilter.empty()) {
- // Have unprefixed symbol name in order file that matches this atom.
- ordinal = info.order;
- return true;
- }
- if (info.fileFilter.equals(objName)) {
- // Have prefixed symbol name in order file that matches atom's path.
- ordinal = info.order;
- return true;
- }
- }
- return false;
-}
-
-bool MachOLinkingContext::customAtomOrderer(const DefinedAtom *left,
- const DefinedAtom *right,
- bool &leftBeforeRight) const {
- // No custom sorting if no order file entries.
- if (!_orderFileEntries)
- return false;
-
- // Order files can only order named atoms.
- StringRef leftName = left->name();
- StringRef rightName = right->name();
- if (leftName.empty() || rightName.empty())
- return false;
-
- // If neither is in order file list, no custom sorter.
- auto leftPos = _orderFiles.find(leftName);
- auto rightPos = _orderFiles.find(rightName);
- bool leftIsOrdered = (leftPos != _orderFiles.end());
- bool rightIsOrdered = (rightPos != _orderFiles.end());
- if (!leftIsOrdered && !rightIsOrdered)
- return false;
-
- // There could be multiple symbols with same name but different file prefixes.
- unsigned leftOrder;
- unsigned rightOrder;
- bool foundLeft =
- leftIsOrdered && findOrderOrdinal(leftPos->getValue(), left, leftOrder);
- bool foundRight = rightIsOrdered &&
- findOrderOrdinal(rightPos->getValue(), right, rightOrder);
- if (!foundLeft && !foundRight)
- return false;
-
- // If only one is in order file list, ordered one goes first.
- if (foundLeft != foundRight)
- leftBeforeRight = foundLeft;
- else
- leftBeforeRight = (leftOrder < rightOrder);
-
- return true;
-}
-
-static bool isLibrary(const std::unique_ptr<Node> &elem) {
- if (FileNode *node = dyn_cast<FileNode>(const_cast<Node *>(elem.get()))) {
- File *file = node->getFile();
- return isa<SharedLibraryFile>(file) || isa<ArchiveLibraryFile>(file);
- }
- return false;
-}
-
-// The darwin linker processes input files in two phases. The first phase
-// links in all object (.o) files in command line order. The second phase
-// links in libraries in command line order.
-// In this function we reorder the input files so that all the object files
-// comes before any library file. We also make a group for the library files
-// so that the Resolver will reiterate over the libraries as long as we find
-// new undefines from libraries.
-void MachOLinkingContext::finalizeInputFiles() {
- std::vector<std::unique_ptr<Node>> &elements = getNodes();
- std::stable_sort(elements.begin(), elements.end(),
- [](const std::unique_ptr<Node> &a,
- const std::unique_ptr<Node> &b) {
- return !isLibrary(a) && isLibrary(b);
- });
- size_t numLibs = std::count_if(elements.begin(), elements.end(), isLibrary);
- elements.push_back(llvm::make_unique<GroupEnd>(numLibs));
-}
-
-llvm::Error MachOLinkingContext::handleLoadedFile(File &file) {
- auto *machoFile = dyn_cast<MachOFile>(&file);
- if (!machoFile)
- return llvm::Error::success();
-
- // Check that the arch of the context matches that of the file.
- // Also set the arch of the context if it didn't have one.
- if (_arch == arch_unknown) {
- _arch = machoFile->arch();
- } else if (machoFile->arch() != arch_unknown && machoFile->arch() != _arch) {
- // Archs are different.
- return llvm::make_error<GenericError>(file.path() +
- Twine(" cannot be linked due to incompatible architecture"));
- }
-
- // Check that the OS of the context matches that of the file.
- // Also set the OS of the context if it didn't have one.
- if (_os == OS::unknown) {
- _os = machoFile->OS();
- } else if (machoFile->OS() != OS::unknown && machoFile->OS() != _os) {
- // OSes are different.
- return llvm::make_error<GenericError>(file.path() +
- Twine(" cannot be linked due to incompatible operating systems"));
- }
-
- // Check that if the objc info exists, that it is compatible with the target
- // OS.
- switch (machoFile->objcConstraint()) {
- case objc_unknown:
- // The file is not compiled with objc, so skip the checks.
- break;
- case objc_gc_only:
- case objc_supports_gc:
- llvm_unreachable("GC support should already have thrown an error");
- case objc_retainReleaseForSimulator:
- // The file is built with simulator objc, so make sure that the context
- // is also building with simulator support.
- if (_os != OS::iOS_simulator)
- return llvm::make_error<GenericError>(file.path() +
- Twine(" cannot be linked. It contains ObjC built for the simulator"
- " while we are linking a non-simulator target"));
- assert((_objcConstraint == objc_unknown ||
- _objcConstraint == objc_retainReleaseForSimulator) &&
- "Must be linking with retain/release for the simulator");
- _objcConstraint = objc_retainReleaseForSimulator;
- break;
- case objc_retainRelease:
- // The file is built without simulator objc, so make sure that the
- // context is also building without simulator support.
- if (_os == OS::iOS_simulator)
- return llvm::make_error<GenericError>(file.path() +
- Twine(" cannot be linked. It contains ObjC built for a non-simulator"
- " target while we are linking a simulator target"));
- assert((_objcConstraint == objc_unknown ||
- _objcConstraint == objc_retainRelease) &&
- "Must be linking with retain/release for a non-simulator target");
- _objcConstraint = objc_retainRelease;
- break;
- }
-
- // Check that the swift version of the context matches that of the file.
- // Also set the swift version of the context if it didn't have one.
- if (!_swiftVersion) {
- _swiftVersion = machoFile->swiftVersion();
- } else if (machoFile->swiftVersion() &&
- machoFile->swiftVersion() != _swiftVersion) {
- // Swift versions are different.
- return llvm::make_error<GenericError>("different swift versions");
- }
-
- return llvm::Error::success();
-}
-
-} // end namespace lld