You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.167
Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
parent
e19d552987
commit
b084638f15
@ -1,13 +0,0 @@
|
||||
add_llvm_library(LLVMRuntimeDyld
|
||||
JITSymbol.cpp
|
||||
RTDyldMemoryManager.cpp
|
||||
RuntimeDyld.cpp
|
||||
RuntimeDyldChecker.cpp
|
||||
RuntimeDyldCOFF.cpp
|
||||
RuntimeDyldELF.cpp
|
||||
RuntimeDyldMachO.cpp
|
||||
Targets/RuntimeDyldELFMips.cpp
|
||||
|
||||
DEPENDS
|
||||
intrinsics_gen
|
||||
)
|
@ -1,49 +0,0 @@
|
||||
//===----------- JITSymbol.cpp - JITSymbol class implementation -----------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// JITSymbol class implementation plus helper functions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ExecutionEngine/JITSymbol.h"
|
||||
#include "llvm/IR/GlobalValue.h"
|
||||
#include "llvm/Object/SymbolicFile.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
JITSymbolFlags llvm::JITSymbolFlags::fromGlobalValue(const GlobalValue &GV) {
|
||||
JITSymbolFlags Flags = JITSymbolFlags::None;
|
||||
if (GV.hasWeakLinkage() || GV.hasLinkOnceLinkage())
|
||||
Flags |= JITSymbolFlags::Weak;
|
||||
if (GV.hasCommonLinkage())
|
||||
Flags |= JITSymbolFlags::Common;
|
||||
if (!GV.hasLocalLinkage() && !GV.hasHiddenVisibility())
|
||||
Flags |= JITSymbolFlags::Exported;
|
||||
return Flags;
|
||||
}
|
||||
|
||||
JITSymbolFlags
|
||||
llvm::JITSymbolFlags::fromObjectSymbol(const object::BasicSymbolRef &Symbol) {
|
||||
JITSymbolFlags Flags = JITSymbolFlags::None;
|
||||
if (Symbol.getFlags() & object::BasicSymbolRef::SF_Weak)
|
||||
Flags |= JITSymbolFlags::Weak;
|
||||
if (Symbol.getFlags() & object::BasicSymbolRef::SF_Common)
|
||||
Flags |= JITSymbolFlags::Common;
|
||||
if (Symbol.getFlags() & object::BasicSymbolRef::SF_Exported)
|
||||
Flags |= JITSymbolFlags::Exported;
|
||||
return Flags;
|
||||
}
|
||||
|
||||
ARMJITSymbolFlags llvm::ARMJITSymbolFlags::fromObjectSymbol(
|
||||
const object::BasicSymbolRef &Symbol) {
|
||||
ARMJITSymbolFlags Flags;
|
||||
if (Symbol.getFlags() & object::BasicSymbolRef::SF_Thumb)
|
||||
Flags |= ARMJITSymbolFlags::Thumb;
|
||||
return Flags;
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
;===- ./lib/ExecutionEngine/RuntimeDyld/LLVMBuild.txt ----------*- Conf -*--===;
|
||||
;
|
||||
; The LLVM Compiler Infrastructure
|
||||
;
|
||||
; This file is distributed under the University of Illinois Open Source
|
||||
; License. See LICENSE.TXT for details.
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
;
|
||||
; This is an LLVMBuild description file for the components in this subdirectory.
|
||||
;
|
||||
; For more information on the LLVMBuild system, please see:
|
||||
;
|
||||
; http://llvm.org/docs/LLVMBuild.html
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
|
||||
[component_0]
|
||||
type = Library
|
||||
name = RuntimeDyld
|
||||
parent = ExecutionEngine
|
||||
required_libraries = MC Object Support
|
@ -1,301 +0,0 @@
|
||||
//===-- RTDyldMemoryManager.cpp - Memory manager for MC-JIT -----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Implementation of the runtime dynamic memory manager base class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Config/config.h"
|
||||
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/DynamicLibrary.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include <cstdlib>
|
||||
|
||||
#ifdef __linux__
|
||||
// These includes used by RTDyldMemoryManager::getPointerToNamedFunction()
|
||||
// for Glibc trickery. See comments in this function for more information.
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace llvm {
|
||||
|
||||
RTDyldMemoryManager::~RTDyldMemoryManager() {}
|
||||
|
||||
// Determine whether we can register EH tables.
|
||||
#if (defined(__GNUC__) && !defined(__ARM_EABI__) && !defined(__ia64__) && \
|
||||
!defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__))
|
||||
#define HAVE_EHTABLE_SUPPORT 1
|
||||
#else
|
||||
#define HAVE_EHTABLE_SUPPORT 0
|
||||
#endif
|
||||
|
||||
#if HAVE_EHTABLE_SUPPORT
|
||||
extern "C" void __register_frame(void *);
|
||||
extern "C" void __deregister_frame(void *);
|
||||
#else
|
||||
// The building compiler does not have __(de)register_frame but
|
||||
// it may be found at runtime in a dynamically-loaded library.
|
||||
// For example, this happens when building LLVM with Visual C++
|
||||
// but using the MingW runtime.
|
||||
void __register_frame(void *p) {
|
||||
static bool Searched = false;
|
||||
static void((*rf)(void *)) = 0;
|
||||
|
||||
if (!Searched) {
|
||||
Searched = true;
|
||||
*(void **)&rf =
|
||||
llvm::sys::DynamicLibrary::SearchForAddressOfSymbol("__register_frame");
|
||||
}
|
||||
if (rf)
|
||||
rf(p);
|
||||
}
|
||||
|
||||
void __deregister_frame(void *p) {
|
||||
static bool Searched = false;
|
||||
static void((*df)(void *)) = 0;
|
||||
|
||||
if (!Searched) {
|
||||
Searched = true;
|
||||
*(void **)&df = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(
|
||||
"__deregister_frame");
|
||||
}
|
||||
if (df)
|
||||
df(p);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
static const char *processFDE(const char *Entry, bool isDeregister) {
|
||||
const char *P = Entry;
|
||||
uint32_t Length = *((const uint32_t *)P);
|
||||
P += 4;
|
||||
uint32_t Offset = *((const uint32_t *)P);
|
||||
if (Offset != 0) {
|
||||
if (isDeregister)
|
||||
__deregister_frame(const_cast<char *>(Entry));
|
||||
else
|
||||
__register_frame(const_cast<char *>(Entry));
|
||||
}
|
||||
return P + Length;
|
||||
}
|
||||
|
||||
// This implementation handles frame registration for local targets.
|
||||
// Memory managers for remote targets should re-implement this function
|
||||
// and use the LoadAddr parameter.
|
||||
void RTDyldMemoryManager::registerEHFramesInProcess(uint8_t *Addr,
|
||||
size_t Size) {
|
||||
// On OS X OS X __register_frame takes a single FDE as an argument.
|
||||
// See http://lists.llvm.org/pipermail/llvm-dev/2013-April/061737.html
|
||||
// and projects/libunwind/src/UnwindLevel1-gcc-ext.c.
|
||||
const char *P = (const char *)Addr;
|
||||
const char *End = P + Size;
|
||||
do {
|
||||
P = processFDE(P, false);
|
||||
} while(P != End);
|
||||
}
|
||||
|
||||
void RTDyldMemoryManager::deregisterEHFramesInProcess(uint8_t *Addr,
|
||||
size_t Size) {
|
||||
const char *P = (const char *)Addr;
|
||||
const char *End = P + Size;
|
||||
do {
|
||||
P = processFDE(P, true);
|
||||
} while(P != End);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void RTDyldMemoryManager::registerEHFramesInProcess(uint8_t *Addr,
|
||||
size_t Size) {
|
||||
// On Linux __register_frame takes a single argument:
|
||||
// a pointer to the start of the .eh_frame section.
|
||||
|
||||
// How can it find the end? Because crtendS.o is linked
|
||||
// in and it has an .eh_frame section with four zero chars.
|
||||
__register_frame(Addr);
|
||||
}
|
||||
|
||||
void RTDyldMemoryManager::deregisterEHFramesInProcess(uint8_t *Addr,
|
||||
size_t Size) {
|
||||
__deregister_frame(Addr);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void RTDyldMemoryManager::registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
|
||||
size_t Size) {
|
||||
registerEHFramesInProcess(Addr, Size);
|
||||
EHFrames.push_back({Addr, Size});
|
||||
}
|
||||
|
||||
void RTDyldMemoryManager::deregisterEHFrames() {
|
||||
for (auto &Frame : EHFrames)
|
||||
deregisterEHFramesInProcess(Frame.Addr, Frame.Size);
|
||||
EHFrames.clear();
|
||||
}
|
||||
|
||||
static int jit_noop() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ARM math functions are statically linked on Android from libgcc.a, but not
|
||||
// available at runtime for dynamic linking. On Linux these are usually placed
|
||||
// in libgcc_s.so so can be found by normal dynamic lookup.
|
||||
#if defined(__BIONIC__) && defined(__arm__)
|
||||
// List of functions which are statically linked on Android and can be generated
|
||||
// by LLVM. This is done as a nested macro which is used once to declare the
|
||||
// imported functions with ARM_MATH_DECL and once to compare them to the
|
||||
// user-requested symbol in getSymbolAddress with ARM_MATH_CHECK. The test
|
||||
// assumes that all functions start with __aeabi_ and getSymbolAddress must be
|
||||
// modified if that changes.
|
||||
#define ARM_MATH_IMPORTS(PP) \
|
||||
PP(__aeabi_d2f) \
|
||||
PP(__aeabi_d2iz) \
|
||||
PP(__aeabi_d2lz) \
|
||||
PP(__aeabi_d2uiz) \
|
||||
PP(__aeabi_d2ulz) \
|
||||
PP(__aeabi_dadd) \
|
||||
PP(__aeabi_dcmpeq) \
|
||||
PP(__aeabi_dcmpge) \
|
||||
PP(__aeabi_dcmpgt) \
|
||||
PP(__aeabi_dcmple) \
|
||||
PP(__aeabi_dcmplt) \
|
||||
PP(__aeabi_dcmpun) \
|
||||
PP(__aeabi_ddiv) \
|
||||
PP(__aeabi_dmul) \
|
||||
PP(__aeabi_dsub) \
|
||||
PP(__aeabi_f2d) \
|
||||
PP(__aeabi_f2iz) \
|
||||
PP(__aeabi_f2lz) \
|
||||
PP(__aeabi_f2uiz) \
|
||||
PP(__aeabi_f2ulz) \
|
||||
PP(__aeabi_fadd) \
|
||||
PP(__aeabi_fcmpeq) \
|
||||
PP(__aeabi_fcmpge) \
|
||||
PP(__aeabi_fcmpgt) \
|
||||
PP(__aeabi_fcmple) \
|
||||
PP(__aeabi_fcmplt) \
|
||||
PP(__aeabi_fcmpun) \
|
||||
PP(__aeabi_fdiv) \
|
||||
PP(__aeabi_fmul) \
|
||||
PP(__aeabi_fsub) \
|
||||
PP(__aeabi_i2d) \
|
||||
PP(__aeabi_i2f) \
|
||||
PP(__aeabi_idiv) \
|
||||
PP(__aeabi_idivmod) \
|
||||
PP(__aeabi_l2d) \
|
||||
PP(__aeabi_l2f) \
|
||||
PP(__aeabi_lasr) \
|
||||
PP(__aeabi_ldivmod) \
|
||||
PP(__aeabi_llsl) \
|
||||
PP(__aeabi_llsr) \
|
||||
PP(__aeabi_lmul) \
|
||||
PP(__aeabi_ui2d) \
|
||||
PP(__aeabi_ui2f) \
|
||||
PP(__aeabi_uidiv) \
|
||||
PP(__aeabi_uidivmod) \
|
||||
PP(__aeabi_ul2d) \
|
||||
PP(__aeabi_ul2f) \
|
||||
PP(__aeabi_uldivmod)
|
||||
|
||||
// Declare statically linked math functions on ARM. The function declarations
|
||||
// here do not have the correct prototypes for each function in
|
||||
// ARM_MATH_IMPORTS, but it doesn't matter because only the symbol addresses are
|
||||
// needed. In particular the __aeabi_*divmod functions do not have calling
|
||||
// conventions which match any C prototype.
|
||||
#define ARM_MATH_DECL(name) extern "C" void name();
|
||||
ARM_MATH_IMPORTS(ARM_MATH_DECL)
|
||||
#undef ARM_MATH_DECL
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && defined(__GLIBC__) && \
|
||||
(defined(__i386__) || defined(__x86_64__))
|
||||
extern "C" LLVM_ATTRIBUTE_WEAK void __morestack();
|
||||
#endif
|
||||
|
||||
uint64_t
|
||||
RTDyldMemoryManager::getSymbolAddressInProcess(const std::string &Name) {
|
||||
// This implementation assumes that the host program is the target.
|
||||
// Clients generating code for a remote target should implement their own
|
||||
// memory manager.
|
||||
#if defined(__linux__) && defined(__GLIBC__)
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Function stubs that are invoked instead of certain library calls
|
||||
//
|
||||
// Force the following functions to be linked in to anything that uses the
|
||||
// JIT. This is a hack designed to work around the all-too-clever Glibc
|
||||
// strategy of making these functions work differently when inlined vs. when
|
||||
// not inlined, and hiding their real definitions in a separate archive file
|
||||
// that the dynamic linker can't see. For more info, search for
|
||||
// 'libc_nonshared.a' on Google, or read http://llvm.org/PR274.
|
||||
if (Name == "stat") return (uint64_t)&stat;
|
||||
if (Name == "fstat") return (uint64_t)&fstat;
|
||||
if (Name == "lstat") return (uint64_t)&lstat;
|
||||
if (Name == "stat64") return (uint64_t)&stat64;
|
||||
if (Name == "fstat64") return (uint64_t)&fstat64;
|
||||
if (Name == "lstat64") return (uint64_t)&lstat64;
|
||||
if (Name == "atexit") return (uint64_t)&atexit;
|
||||
if (Name == "mknod") return (uint64_t)&mknod;
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
// __morestack lives in libgcc, a static library.
|
||||
if (&__morestack && Name == "__morestack")
|
||||
return (uint64_t)&__morestack;
|
||||
#endif
|
||||
#endif // __linux__ && __GLIBC__
|
||||
|
||||
// See ARM_MATH_IMPORTS definition for explanation
|
||||
#if defined(__BIONIC__) && defined(__arm__)
|
||||
if (Name.compare(0, 8, "__aeabi_") == 0) {
|
||||
// Check if the user has requested any of the functions listed in
|
||||
// ARM_MATH_IMPORTS, and if so redirect to the statically linked symbol.
|
||||
#define ARM_MATH_CHECK(fn) if (Name == #fn) return (uint64_t)&fn;
|
||||
ARM_MATH_IMPORTS(ARM_MATH_CHECK)
|
||||
#undef ARM_MATH_CHECK
|
||||
}
|
||||
#endif
|
||||
|
||||
// We should not invoke parent's ctors/dtors from generated main()!
|
||||
// On Mingw and Cygwin, the symbol __main is resolved to
|
||||
// callee's(eg. tools/lli) one, to invoke wrong duplicated ctors
|
||||
// (and register wrong callee's dtors with atexit(3)).
|
||||
// We expect ExecutionEngine::runStaticConstructorsDestructors()
|
||||
// is called before ExecutionEngine::runFunctionAsMain() is called.
|
||||
if (Name == "__main") return (uint64_t)&jit_noop;
|
||||
|
||||
const char *NameStr = Name.c_str();
|
||||
|
||||
// DynamicLibrary::SearchForAddresOfSymbol expects an unmangled 'C' symbol
|
||||
// name so ff we're on Darwin, strip the leading '_' off.
|
||||
#ifdef __APPLE__
|
||||
if (NameStr[0] == '_')
|
||||
++NameStr;
|
||||
#endif
|
||||
|
||||
return (uint64_t)sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr);
|
||||
}
|
||||
|
||||
void *RTDyldMemoryManager::getPointerToNamedFunction(const std::string &Name,
|
||||
bool AbortOnFailure) {
|
||||
uint64_t Addr = getSymbolAddress(Name);
|
||||
|
||||
if (!Addr && AbortOnFailure)
|
||||
report_fatal_error("Program used external function '" + Name +
|
||||
"' which could not be resolved!");
|
||||
|
||||
return (void*)Addr;
|
||||
}
|
||||
|
||||
} // namespace llvm
|
File diff suppressed because it is too large
Load Diff
@ -1,83 +0,0 @@
|
||||
//===-- RuntimeDyldCOFF.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Implementation of COFF support for the MC-JIT runtime dynamic linker.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "RuntimeDyldCOFF.h"
|
||||
#include "Targets/RuntimeDyldCOFFI386.h"
|
||||
#include "Targets/RuntimeDyldCOFFThumb.h"
|
||||
#include "Targets/RuntimeDyldCOFFX86_64.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
|
||||
#define DEBUG_TYPE "dyld"
|
||||
|
||||
namespace {
|
||||
|
||||
class LoadedCOFFObjectInfo final
|
||||
: public LoadedObjectInfoHelper<LoadedCOFFObjectInfo,
|
||||
RuntimeDyld::LoadedObjectInfo> {
|
||||
public:
|
||||
LoadedCOFFObjectInfo(
|
||||
RuntimeDyldImpl &RTDyld,
|
||||
RuntimeDyld::LoadedObjectInfo::ObjSectionToIDMap ObjSecToIDMap)
|
||||
: LoadedObjectInfoHelper(RTDyld, std::move(ObjSecToIDMap)) {}
|
||||
|
||||
OwningBinary<ObjectFile>
|
||||
getObjectForDebug(const ObjectFile &Obj) const override {
|
||||
return OwningBinary<ObjectFile>();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
|
||||
std::unique_ptr<RuntimeDyldCOFF>
|
||||
llvm::RuntimeDyldCOFF::create(Triple::ArchType Arch,
|
||||
RuntimeDyld::MemoryManager &MemMgr,
|
||||
JITSymbolResolver &Resolver) {
|
||||
switch (Arch) {
|
||||
default: llvm_unreachable("Unsupported target for RuntimeDyldCOFF.");
|
||||
case Triple::x86:
|
||||
return make_unique<RuntimeDyldCOFFI386>(MemMgr, Resolver);
|
||||
case Triple::thumb:
|
||||
return make_unique<RuntimeDyldCOFFThumb>(MemMgr, Resolver);
|
||||
case Triple::x86_64:
|
||||
return make_unique<RuntimeDyldCOFFX86_64>(MemMgr, Resolver);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
|
||||
RuntimeDyldCOFF::loadObject(const object::ObjectFile &O) {
|
||||
if (auto ObjSectionToIDOrErr = loadObjectImpl(O)) {
|
||||
return llvm::make_unique<LoadedCOFFObjectInfo>(*this, *ObjSectionToIDOrErr);
|
||||
} else {
|
||||
HasError = true;
|
||||
raw_string_ostream ErrStream(ErrorStr);
|
||||
logAllUnhandledErrors(ObjSectionToIDOrErr.takeError(), ErrStream, "");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t RuntimeDyldCOFF::getSymbolOffset(const SymbolRef &Sym) {
|
||||
// The value in a relocatable COFF object is the offset.
|
||||
return Sym.getValue();
|
||||
}
|
||||
|
||||
bool RuntimeDyldCOFF::isCompatibleFile(const object::ObjectFile &Obj) const {
|
||||
return Obj.isCOFF();
|
||||
}
|
||||
|
||||
} // namespace llvm
|
@ -1,49 +0,0 @@
|
||||
//===-- RuntimeDyldCOFF.h - Run-time dynamic linker for MC-JIT ---*- C++ -*-==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// COFF support for MC-JIT runtime dynamic linker.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_RUNTIME_DYLD_COFF_H
|
||||
#define LLVM_RUNTIME_DYLD_COFF_H
|
||||
|
||||
#include "RuntimeDyldImpl.h"
|
||||
|
||||
#define DEBUG_TYPE "dyld"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
// Common base class for COFF dynamic linker support.
|
||||
// Concrete subclasses for each target can be found in ./Targets.
|
||||
class RuntimeDyldCOFF : public RuntimeDyldImpl {
|
||||
|
||||
public:
|
||||
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
|
||||
loadObject(const object::ObjectFile &Obj) override;
|
||||
bool isCompatibleFile(const object::ObjectFile &Obj) const override;
|
||||
|
||||
static std::unique_ptr<RuntimeDyldCOFF>
|
||||
create(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MemMgr,
|
||||
JITSymbolResolver &Resolver);
|
||||
|
||||
protected:
|
||||
RuntimeDyldCOFF(RuntimeDyld::MemoryManager &MemMgr,
|
||||
JITSymbolResolver &Resolver)
|
||||
: RuntimeDyldImpl(MemMgr, Resolver) {}
|
||||
uint64_t getSymbolOffset(const SymbolRef &Sym);
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#undef DEBUG_TYPE
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,78 +0,0 @@
|
||||
//===-- RuntimeDyldCheckerImpl.h -- RuntimeDyld test framework --*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDCHECKERIMPL_H
|
||||
#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDCHECKERIMPL_H
|
||||
|
||||
#include "RuntimeDyldImpl.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class RuntimeDyldCheckerImpl {
|
||||
friend class RuntimeDyldChecker;
|
||||
friend class RuntimeDyldImpl;
|
||||
friend class RuntimeDyldCheckerExprEval;
|
||||
friend class RuntimeDyldELF;
|
||||
|
||||
public:
|
||||
RuntimeDyldCheckerImpl(RuntimeDyld &RTDyld, MCDisassembler *Disassembler,
|
||||
MCInstPrinter *InstPrinter,
|
||||
llvm::raw_ostream &ErrStream);
|
||||
|
||||
bool check(StringRef CheckExpr) const;
|
||||
bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const;
|
||||
|
||||
private:
|
||||
|
||||
// StubMap typedefs.
|
||||
typedef std::map<std::string, uint64_t> StubOffsetsMap;
|
||||
struct SectionAddressInfo {
|
||||
uint64_t SectionID;
|
||||
StubOffsetsMap StubOffsets;
|
||||
};
|
||||
typedef std::map<std::string, SectionAddressInfo> SectionMap;
|
||||
typedef std::map<std::string, SectionMap> StubMap;
|
||||
|
||||
RuntimeDyldImpl &getRTDyld() const { return *RTDyld.Dyld; }
|
||||
|
||||
bool isSymbolValid(StringRef Symbol) const;
|
||||
uint64_t getSymbolLocalAddr(StringRef Symbol) const;
|
||||
uint64_t getSymbolRemoteAddr(StringRef Symbol) const;
|
||||
uint64_t readMemoryAtAddr(uint64_t Addr, unsigned Size) const;
|
||||
|
||||
std::pair<const SectionAddressInfo*, std::string> findSectionAddrInfo(
|
||||
StringRef FileName,
|
||||
StringRef SectionName) const;
|
||||
|
||||
std::pair<uint64_t, std::string> getSectionAddr(StringRef FileName,
|
||||
StringRef SectionName,
|
||||
bool IsInsideLoad) const;
|
||||
|
||||
std::pair<uint64_t, std::string> getStubAddrFor(StringRef FileName,
|
||||
StringRef SectionName,
|
||||
StringRef Symbol,
|
||||
bool IsInsideLoad) const;
|
||||
StringRef getSubsectionStartingAt(StringRef Name) const;
|
||||
|
||||
Optional<uint64_t> getSectionLoadAddress(void *LocalAddr) const;
|
||||
|
||||
void registerSection(StringRef FilePath, unsigned SectionID);
|
||||
void registerStubMap(StringRef FilePath, unsigned SectionID,
|
||||
const RuntimeDyldImpl::StubMap &RTDyldStubs);
|
||||
|
||||
RuntimeDyld &RTDyld;
|
||||
MCDisassembler *Disassembler;
|
||||
MCInstPrinter *InstPrinter;
|
||||
llvm::raw_ostream &ErrStream;
|
||||
|
||||
StubMap Stubs;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,190 +0,0 @@
|
||||
//===-- RuntimeDyldELF.h - Run-time dynamic linker for MC-JIT ---*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// ELF support for MC-JIT runtime dynamic linker.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDELF_H
|
||||
#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDELF_H
|
||||
|
||||
#include "RuntimeDyldImpl.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
namespace object {
|
||||
class ELFObjectFileBase;
|
||||
}
|
||||
|
||||
class RuntimeDyldELF : public RuntimeDyldImpl {
|
||||
|
||||
void resolveRelocation(const SectionEntry &Section, uint64_t Offset,
|
||||
uint64_t Value, uint32_t Type, int64_t Addend,
|
||||
uint64_t SymOffset = 0, SID SectionID = 0);
|
||||
|
||||
void resolveX86_64Relocation(const SectionEntry &Section, uint64_t Offset,
|
||||
uint64_t Value, uint32_t Type, int64_t Addend,
|
||||
uint64_t SymOffset);
|
||||
|
||||
void resolveX86Relocation(const SectionEntry &Section, uint64_t Offset,
|
||||
uint32_t Value, uint32_t Type, int32_t Addend);
|
||||
|
||||
void resolveAArch64Relocation(const SectionEntry &Section, uint64_t Offset,
|
||||
uint64_t Value, uint32_t Type, int64_t Addend);
|
||||
|
||||
bool resolveAArch64ShortBranch(unsigned SectionID, relocation_iterator RelI,
|
||||
const RelocationValueRef &Value);
|
||||
|
||||
void resolveAArch64Branch(unsigned SectionID, const RelocationValueRef &Value,
|
||||
relocation_iterator RelI, StubMap &Stubs);
|
||||
|
||||
void resolveARMRelocation(const SectionEntry &Section, uint64_t Offset,
|
||||
uint32_t Value, uint32_t Type, int32_t Addend);
|
||||
|
||||
void resolvePPC32Relocation(const SectionEntry &Section, uint64_t Offset,
|
||||
uint64_t Value, uint32_t Type, int64_t Addend);
|
||||
|
||||
void resolvePPC64Relocation(const SectionEntry &Section, uint64_t Offset,
|
||||
uint64_t Value, uint32_t Type, int64_t Addend);
|
||||
|
||||
void resolveSystemZRelocation(const SectionEntry &Section, uint64_t Offset,
|
||||
uint64_t Value, uint32_t Type, int64_t Addend);
|
||||
|
||||
void resolveBPFRelocation(const SectionEntry &Section, uint64_t Offset,
|
||||
uint64_t Value, uint32_t Type, int64_t Addend);
|
||||
|
||||
unsigned getMaxStubSize() override {
|
||||
if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be)
|
||||
return 20; // movz; movk; movk; movk; br
|
||||
if (Arch == Triple::arm || Arch == Triple::thumb)
|
||||
return 8; // 32-bit instruction and 32-bit address
|
||||
else if (IsMipsO32ABI || IsMipsN32ABI)
|
||||
return 16;
|
||||
else if (IsMipsN64ABI)
|
||||
return 32;
|
||||
else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le)
|
||||
return 44;
|
||||
else if (Arch == Triple::x86_64)
|
||||
return 6; // 2-byte jmp instruction + 32-bit relative address
|
||||
else if (Arch == Triple::systemz)
|
||||
return 16;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned getStubAlignment() override {
|
||||
if (Arch == Triple::systemz)
|
||||
return 8;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
void setMipsABI(const ObjectFile &Obj) override;
|
||||
|
||||
Error findPPC64TOCSection(const ELFObjectFileBase &Obj,
|
||||
ObjSectionToIDMap &LocalSections,
|
||||
RelocationValueRef &Rel);
|
||||
Error findOPDEntrySection(const ELFObjectFileBase &Obj,
|
||||
ObjSectionToIDMap &LocalSections,
|
||||
RelocationValueRef &Rel);
|
||||
protected:
|
||||
size_t getGOTEntrySize() override;
|
||||
|
||||
private:
|
||||
SectionEntry &getSection(unsigned SectionID) { return Sections[SectionID]; }
|
||||
|
||||
// Allocate no GOT entries for use in the given section.
|
||||
uint64_t allocateGOTEntries(unsigned no);
|
||||
|
||||
// Find GOT entry corresponding to relocation or create new one.
|
||||
uint64_t findOrAllocGOTEntry(const RelocationValueRef &Value,
|
||||
unsigned GOTRelType);
|
||||
|
||||
// Resolve the relvative address of GOTOffset in Section ID and place
|
||||
// it at the given Offset
|
||||
void resolveGOTOffsetRelocation(unsigned SectionID, uint64_t Offset,
|
||||
uint64_t GOTOffset, uint32_t Type);
|
||||
|
||||
// For a GOT entry referenced from SectionID, compute a relocation entry
|
||||
// that will place the final resolved value in the GOT slot
|
||||
RelocationEntry computeGOTOffsetRE(uint64_t GOTOffset, uint64_t SymbolOffset,
|
||||
unsigned Type);
|
||||
|
||||
// Compute the address in memory where we can find the placeholder
|
||||
void *computePlaceholderAddress(unsigned SectionID, uint64_t Offset) const;
|
||||
|
||||
// Split out common case for createing the RelocationEntry for when the relocation requires
|
||||
// no particular advanced processing.
|
||||
void processSimpleRelocation(unsigned SectionID, uint64_t Offset, unsigned RelType, RelocationValueRef Value);
|
||||
|
||||
// Return matching *LO16 relocation (Mips specific)
|
||||
uint32_t getMatchingLoRelocation(uint32_t RelType,
|
||||
bool IsLocal = false) const;
|
||||
|
||||
// The tentative ID for the GOT section
|
||||
unsigned GOTSectionID;
|
||||
|
||||
// Records the current number of allocated slots in the GOT
|
||||
// (This would be equivalent to GOTEntries.size() were it not for relocations
|
||||
// that consume more than one slot)
|
||||
unsigned CurrentGOTIndex;
|
||||
|
||||
protected:
|
||||
// A map from section to a GOT section that has entries for section's GOT
|
||||
// relocations. (Mips64 specific)
|
||||
DenseMap<SID, SID> SectionToGOTMap;
|
||||
|
||||
private:
|
||||
// A map to avoid duplicate got entries (Mips64 specific)
|
||||
StringMap<uint64_t> GOTSymbolOffsets;
|
||||
|
||||
// *HI16 relocations will be added for resolving when we find matching
|
||||
// *LO16 part. (Mips specific)
|
||||
SmallVector<std::pair<RelocationValueRef, RelocationEntry>, 8> PendingRelocs;
|
||||
|
||||
// When a module is loaded we save the SectionID of the EH frame section
|
||||
// in a table until we receive a request to register all unregistered
|
||||
// EH frame sections with the memory manager.
|
||||
SmallVector<SID, 2> UnregisteredEHFrameSections;
|
||||
|
||||
// Map between GOT relocation value and corresponding GOT offset
|
||||
std::map<RelocationValueRef, uint64_t> GOTOffsetMap;
|
||||
|
||||
bool relocationNeedsGot(const RelocationRef &R) const override;
|
||||
bool relocationNeedsStub(const RelocationRef &R) const override;
|
||||
|
||||
public:
|
||||
RuntimeDyldELF(RuntimeDyld::MemoryManager &MemMgr,
|
||||
JITSymbolResolver &Resolver);
|
||||
~RuntimeDyldELF() override;
|
||||
|
||||
static std::unique_ptr<RuntimeDyldELF>
|
||||
create(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MemMgr,
|
||||
JITSymbolResolver &Resolver);
|
||||
|
||||
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
|
||||
loadObject(const object::ObjectFile &O) override;
|
||||
|
||||
void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override;
|
||||
Expected<relocation_iterator>
|
||||
processRelocationRef(unsigned SectionID, relocation_iterator RelI,
|
||||
const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &ObjSectionToID,
|
||||
StubMap &Stubs) override;
|
||||
bool isCompatibleFile(const object::ObjectFile &Obj) const override;
|
||||
void registerEHFrames() override;
|
||||
Error finalizeLoad(const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &SectionMap) override;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,378 +0,0 @@
|
||||
//===-- RuntimeDyldMachO.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-=//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Implementation of the MC-JIT runtime dynamic linker.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "RuntimeDyldMachO.h"
|
||||
#include "Targets/RuntimeDyldMachOAArch64.h"
|
||||
#include "Targets/RuntimeDyldMachOARM.h"
|
||||
#include "Targets/RuntimeDyldMachOI386.h"
|
||||
#include "Targets/RuntimeDyldMachOX86_64.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
|
||||
#define DEBUG_TYPE "dyld"
|
||||
|
||||
namespace {
|
||||
|
||||
class LoadedMachOObjectInfo final
|
||||
: public LoadedObjectInfoHelper<LoadedMachOObjectInfo,
|
||||
RuntimeDyld::LoadedObjectInfo> {
|
||||
public:
|
||||
LoadedMachOObjectInfo(RuntimeDyldImpl &RTDyld,
|
||||
ObjSectionToIDMap ObjSecToIDMap)
|
||||
: LoadedObjectInfoHelper(RTDyld, std::move(ObjSecToIDMap)) {}
|
||||
|
||||
OwningBinary<ObjectFile>
|
||||
getObjectForDebug(const ObjectFile &Obj) const override {
|
||||
return OwningBinary<ObjectFile>();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
|
||||
int64_t RuntimeDyldMachO::memcpyAddend(const RelocationEntry &RE) const {
|
||||
unsigned NumBytes = 1 << RE.Size;
|
||||
uint8_t *Src = Sections[RE.SectionID].getAddress() + RE.Offset;
|
||||
|
||||
return static_cast<int64_t>(readBytesUnaligned(Src, NumBytes));
|
||||
}
|
||||
|
||||
Expected<relocation_iterator>
|
||||
RuntimeDyldMachO::processScatteredVANILLA(
|
||||
unsigned SectionID, relocation_iterator RelI,
|
||||
const ObjectFile &BaseObjT,
|
||||
RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID,
|
||||
bool TargetIsLocalThumbFunc) {
|
||||
const MachOObjectFile &Obj =
|
||||
static_cast<const MachOObjectFile&>(BaseObjT);
|
||||
MachO::any_relocation_info RE =
|
||||
Obj.getRelocation(RelI->getRawDataRefImpl());
|
||||
|
||||
SectionEntry &Section = Sections[SectionID];
|
||||
uint32_t RelocType = Obj.getAnyRelocationType(RE);
|
||||
bool IsPCRel = Obj.getAnyRelocationPCRel(RE);
|
||||
unsigned Size = Obj.getAnyRelocationLength(RE);
|
||||
uint64_t Offset = RelI->getOffset();
|
||||
uint8_t *LocalAddress = Section.getAddressWithOffset(Offset);
|
||||
unsigned NumBytes = 1 << Size;
|
||||
int64_t Addend = readBytesUnaligned(LocalAddress, NumBytes);
|
||||
|
||||
unsigned SymbolBaseAddr = Obj.getScatteredRelocationValue(RE);
|
||||
section_iterator TargetSI = getSectionByAddress(Obj, SymbolBaseAddr);
|
||||
assert(TargetSI != Obj.section_end() && "Can't find section for symbol");
|
||||
uint64_t SectionBaseAddr = TargetSI->getAddress();
|
||||
SectionRef TargetSection = *TargetSI;
|
||||
bool IsCode = TargetSection.isText();
|
||||
uint32_t TargetSectionID = ~0U;
|
||||
if (auto TargetSectionIDOrErr =
|
||||
findOrEmitSection(Obj, TargetSection, IsCode, ObjSectionToID))
|
||||
TargetSectionID = *TargetSectionIDOrErr;
|
||||
else
|
||||
return TargetSectionIDOrErr.takeError();
|
||||
|
||||
Addend -= SectionBaseAddr;
|
||||
RelocationEntry R(SectionID, Offset, RelocType, Addend, IsPCRel, Size);
|
||||
R.IsTargetThumbFunc = TargetIsLocalThumbFunc;
|
||||
|
||||
addRelocationForSection(R, TargetSectionID);
|
||||
|
||||
return ++RelI;
|
||||
}
|
||||
|
||||
|
||||
Expected<RelocationValueRef>
|
||||
RuntimeDyldMachO::getRelocationValueRef(
|
||||
const ObjectFile &BaseTObj, const relocation_iterator &RI,
|
||||
const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID) {
|
||||
|
||||
const MachOObjectFile &Obj =
|
||||
static_cast<const MachOObjectFile &>(BaseTObj);
|
||||
MachO::any_relocation_info RelInfo =
|
||||
Obj.getRelocation(RI->getRawDataRefImpl());
|
||||
RelocationValueRef Value;
|
||||
|
||||
bool IsExternal = Obj.getPlainRelocationExternal(RelInfo);
|
||||
if (IsExternal) {
|
||||
symbol_iterator Symbol = RI->getSymbol();
|
||||
StringRef TargetName;
|
||||
if (auto TargetNameOrErr = Symbol->getName())
|
||||
TargetName = *TargetNameOrErr;
|
||||
else
|
||||
return TargetNameOrErr.takeError();
|
||||
RTDyldSymbolTable::const_iterator SI =
|
||||
GlobalSymbolTable.find(TargetName.data());
|
||||
if (SI != GlobalSymbolTable.end()) {
|
||||
const auto &SymInfo = SI->second;
|
||||
Value.SectionID = SymInfo.getSectionID();
|
||||
Value.Offset = SymInfo.getOffset() + RE.Addend;
|
||||
} else {
|
||||
Value.SymbolName = TargetName.data();
|
||||
Value.Offset = RE.Addend;
|
||||
}
|
||||
} else {
|
||||
SectionRef Sec = Obj.getAnyRelocationSection(RelInfo);
|
||||
bool IsCode = Sec.isText();
|
||||
if (auto SectionIDOrErr = findOrEmitSection(Obj, Sec, IsCode,
|
||||
ObjSectionToID))
|
||||
Value.SectionID = *SectionIDOrErr;
|
||||
else
|
||||
return SectionIDOrErr.takeError();
|
||||
uint64_t Addr = Sec.getAddress();
|
||||
Value.Offset = RE.Addend - Addr;
|
||||
}
|
||||
|
||||
return Value;
|
||||
}
|
||||
|
||||
void RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value,
|
||||
const relocation_iterator &RI,
|
||||
unsigned OffsetToNextPC) {
|
||||
auto &O = *cast<MachOObjectFile>(RI->getObject());
|
||||
section_iterator SecI = O.getRelocationRelocatedSection(RI);
|
||||
Value.Offset += RI->getOffset() + OffsetToNextPC + SecI->getAddress();
|
||||
}
|
||||
|
||||
void RuntimeDyldMachO::dumpRelocationToResolve(const RelocationEntry &RE,
|
||||
uint64_t Value) const {
|
||||
const SectionEntry &Section = Sections[RE.SectionID];
|
||||
uint8_t *LocalAddress = Section.getAddress() + RE.Offset;
|
||||
uint64_t FinalAddress = Section.getLoadAddress() + RE.Offset;
|
||||
|
||||
dbgs() << "resolveRelocation Section: " << RE.SectionID
|
||||
<< " LocalAddress: " << format("%p", LocalAddress)
|
||||
<< " FinalAddress: " << format("0x%016" PRIx64, FinalAddress)
|
||||
<< " Value: " << format("0x%016" PRIx64, Value) << " Addend: " << RE.Addend
|
||||
<< " isPCRel: " << RE.IsPCRel << " MachoType: " << RE.RelType
|
||||
<< " Size: " << (1 << RE.Size) << "\n";
|
||||
}
|
||||
|
||||
section_iterator
|
||||
RuntimeDyldMachO::getSectionByAddress(const MachOObjectFile &Obj,
|
||||
uint64_t Addr) {
|
||||
section_iterator SI = Obj.section_begin();
|
||||
section_iterator SE = Obj.section_end();
|
||||
|
||||
for (; SI != SE; ++SI) {
|
||||
uint64_t SAddr = SI->getAddress();
|
||||
uint64_t SSize = SI->getSize();
|
||||
if ((Addr >= SAddr) && (Addr < SAddr + SSize))
|
||||
return SI;
|
||||
}
|
||||
|
||||
return SE;
|
||||
}
|
||||
|
||||
|
||||
// Populate __pointers section.
|
||||
Error RuntimeDyldMachO::populateIndirectSymbolPointersSection(
|
||||
const MachOObjectFile &Obj,
|
||||
const SectionRef &PTSection,
|
||||
unsigned PTSectionID) {
|
||||
assert(!Obj.is64Bit() &&
|
||||
"Pointer table section not supported in 64-bit MachO.");
|
||||
|
||||
MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand();
|
||||
MachO::section Sec32 = Obj.getSection(PTSection.getRawDataRefImpl());
|
||||
uint32_t PTSectionSize = Sec32.size;
|
||||
unsigned FirstIndirectSymbol = Sec32.reserved1;
|
||||
const unsigned PTEntrySize = 4;
|
||||
unsigned NumPTEntries = PTSectionSize / PTEntrySize;
|
||||
unsigned PTEntryOffset = 0;
|
||||
|
||||
assert((PTSectionSize % PTEntrySize) == 0 &&
|
||||
"Pointers section does not contain a whole number of stubs?");
|
||||
|
||||
DEBUG(dbgs() << "Populating pointer table section "
|
||||
<< Sections[PTSectionID].getName() << ", Section ID "
|
||||
<< PTSectionID << ", " << NumPTEntries << " entries, "
|
||||
<< PTEntrySize << " bytes each:\n");
|
||||
|
||||
for (unsigned i = 0; i < NumPTEntries; ++i) {
|
||||
unsigned SymbolIndex =
|
||||
Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i);
|
||||
symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex);
|
||||
StringRef IndirectSymbolName;
|
||||
if (auto IndirectSymbolNameOrErr = SI->getName())
|
||||
IndirectSymbolName = *IndirectSymbolNameOrErr;
|
||||
else
|
||||
return IndirectSymbolNameOrErr.takeError();
|
||||
DEBUG(dbgs() << " " << IndirectSymbolName << ": index " << SymbolIndex
|
||||
<< ", PT offset: " << PTEntryOffset << "\n");
|
||||
RelocationEntry RE(PTSectionID, PTEntryOffset,
|
||||
MachO::GENERIC_RELOC_VANILLA, 0, false, 2);
|
||||
addRelocationForSymbol(RE, IndirectSymbolName);
|
||||
PTEntryOffset += PTEntrySize;
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile &Obj) const {
|
||||
return Obj.isMachO();
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
Error
|
||||
RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &SectionMap) {
|
||||
unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID;
|
||||
unsigned TextSID = RTDYLD_INVALID_SECTION_ID;
|
||||
unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID;
|
||||
|
||||
for (const auto &Section : Obj.sections()) {
|
||||
StringRef Name;
|
||||
Section.getName(Name);
|
||||
|
||||
// Force emission of the __text, __eh_frame, and __gcc_except_tab sections
|
||||
// if they're present. Otherwise call down to the impl to handle other
|
||||
// sections that have already been emitted.
|
||||
if (Name == "__text") {
|
||||
if (auto TextSIDOrErr = findOrEmitSection(Obj, Section, true, SectionMap))
|
||||
TextSID = *TextSIDOrErr;
|
||||
else
|
||||
return TextSIDOrErr.takeError();
|
||||
} else if (Name == "__eh_frame") {
|
||||
if (auto EHFrameSIDOrErr = findOrEmitSection(Obj, Section, false,
|
||||
SectionMap))
|
||||
EHFrameSID = *EHFrameSIDOrErr;
|
||||
else
|
||||
return EHFrameSIDOrErr.takeError();
|
||||
} else if (Name == "__gcc_except_tab") {
|
||||
if (auto ExceptTabSIDOrErr = findOrEmitSection(Obj, Section, true,
|
||||
SectionMap))
|
||||
ExceptTabSID = *ExceptTabSIDOrErr;
|
||||
else
|
||||
return ExceptTabSIDOrErr.takeError();
|
||||
} else {
|
||||
auto I = SectionMap.find(Section);
|
||||
if (I != SectionMap.end())
|
||||
if (auto Err = impl().finalizeSection(Obj, I->second, Section))
|
||||
return Err;
|
||||
}
|
||||
}
|
||||
UnregisteredEHFrameSections.push_back(
|
||||
EHFrameRelatedSections(EHFrameSID, TextSID, ExceptTabSID));
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
unsigned char *RuntimeDyldMachOCRTPBase<Impl>::processFDE(uint8_t *P,
|
||||
int64_t DeltaForText,
|
||||
int64_t DeltaForEH) {
|
||||
typedef typename Impl::TargetPtrT TargetPtrT;
|
||||
|
||||
DEBUG(dbgs() << "Processing FDE: Delta for text: " << DeltaForText
|
||||
<< ", Delta for EH: " << DeltaForEH << "\n");
|
||||
uint32_t Length = readBytesUnaligned(P, 4);
|
||||
P += 4;
|
||||
uint8_t *Ret = P + Length;
|
||||
uint32_t Offset = readBytesUnaligned(P, 4);
|
||||
if (Offset == 0) // is a CIE
|
||||
return Ret;
|
||||
|
||||
P += 4;
|
||||
TargetPtrT FDELocation = readBytesUnaligned(P, sizeof(TargetPtrT));
|
||||
TargetPtrT NewLocation = FDELocation - DeltaForText;
|
||||
writeBytesUnaligned(NewLocation, P, sizeof(TargetPtrT));
|
||||
|
||||
P += sizeof(TargetPtrT);
|
||||
|
||||
// Skip the FDE address range
|
||||
P += sizeof(TargetPtrT);
|
||||
|
||||
uint8_t Augmentationsize = *P;
|
||||
P += 1;
|
||||
if (Augmentationsize != 0) {
|
||||
TargetPtrT LSDA = readBytesUnaligned(P, sizeof(TargetPtrT));
|
||||
TargetPtrT NewLSDA = LSDA - DeltaForEH;
|
||||
writeBytesUnaligned(NewLSDA, P, sizeof(TargetPtrT));
|
||||
}
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
static int64_t computeDelta(SectionEntry *A, SectionEntry *B) {
|
||||
int64_t ObjDistance = static_cast<int64_t>(A->getObjAddress()) -
|
||||
static_cast<int64_t>(B->getObjAddress());
|
||||
int64_t MemDistance = A->getLoadAddress() - B->getLoadAddress();
|
||||
return ObjDistance - MemDistance;
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
void RuntimeDyldMachOCRTPBase<Impl>::registerEHFrames() {
|
||||
|
||||
for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) {
|
||||
EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i];
|
||||
if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID ||
|
||||
SectionInfo.TextSID == RTDYLD_INVALID_SECTION_ID)
|
||||
continue;
|
||||
SectionEntry *Text = &Sections[SectionInfo.TextSID];
|
||||
SectionEntry *EHFrame = &Sections[SectionInfo.EHFrameSID];
|
||||
SectionEntry *ExceptTab = nullptr;
|
||||
if (SectionInfo.ExceptTabSID != RTDYLD_INVALID_SECTION_ID)
|
||||
ExceptTab = &Sections[SectionInfo.ExceptTabSID];
|
||||
|
||||
int64_t DeltaForText = computeDelta(Text, EHFrame);
|
||||
int64_t DeltaForEH = 0;
|
||||
if (ExceptTab)
|
||||
DeltaForEH = computeDelta(ExceptTab, EHFrame);
|
||||
|
||||
uint8_t *P = EHFrame->getAddress();
|
||||
uint8_t *End = P + EHFrame->getSize();
|
||||
while (P != End) {
|
||||
P = processFDE(P, DeltaForText, DeltaForEH);
|
||||
}
|
||||
|
||||
MemMgr.registerEHFrames(EHFrame->getAddress(), EHFrame->getLoadAddress(),
|
||||
EHFrame->getSize());
|
||||
}
|
||||
UnregisteredEHFrameSections.clear();
|
||||
}
|
||||
|
||||
std::unique_ptr<RuntimeDyldMachO>
|
||||
RuntimeDyldMachO::create(Triple::ArchType Arch,
|
||||
RuntimeDyld::MemoryManager &MemMgr,
|
||||
JITSymbolResolver &Resolver) {
|
||||
switch (Arch) {
|
||||
default:
|
||||
llvm_unreachable("Unsupported target for RuntimeDyldMachO.");
|
||||
break;
|
||||
case Triple::arm:
|
||||
return make_unique<RuntimeDyldMachOARM>(MemMgr, Resolver);
|
||||
case Triple::aarch64:
|
||||
return make_unique<RuntimeDyldMachOAArch64>(MemMgr, Resolver);
|
||||
case Triple::x86:
|
||||
return make_unique<RuntimeDyldMachOI386>(MemMgr, Resolver);
|
||||
case Triple::x86_64:
|
||||
return make_unique<RuntimeDyldMachOX86_64>(MemMgr, Resolver);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
|
||||
RuntimeDyldMachO::loadObject(const object::ObjectFile &O) {
|
||||
if (auto ObjSectionToIDOrErr = loadObjectImpl(O))
|
||||
return llvm::make_unique<LoadedMachOObjectInfo>(*this,
|
||||
*ObjSectionToIDOrErr);
|
||||
else {
|
||||
HasError = true;
|
||||
raw_string_ostream ErrStream(ErrorStr);
|
||||
logAllUnhandledErrors(ObjSectionToIDOrErr.takeError(), ErrStream, "");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
@ -1,168 +0,0 @@
|
||||
//===-- RuntimeDyldMachO.h - Run-time dynamic linker for MC-JIT ---*- C++ -*-=//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// MachO support for MC-JIT runtime dynamic linker.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDMACHO_H
|
||||
#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDMACHO_H
|
||||
|
||||
#include "RuntimeDyldImpl.h"
|
||||
#include "llvm/Object/MachO.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
|
||||
#define DEBUG_TYPE "dyld"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
|
||||
namespace llvm {
|
||||
class RuntimeDyldMachO : public RuntimeDyldImpl {
|
||||
protected:
|
||||
struct SectionOffsetPair {
|
||||
unsigned SectionID;
|
||||
uint64_t Offset;
|
||||
};
|
||||
|
||||
struct EHFrameRelatedSections {
|
||||
EHFrameRelatedSections()
|
||||
: EHFrameSID(RTDYLD_INVALID_SECTION_ID),
|
||||
TextSID(RTDYLD_INVALID_SECTION_ID),
|
||||
ExceptTabSID(RTDYLD_INVALID_SECTION_ID) {}
|
||||
|
||||
EHFrameRelatedSections(SID EH, SID T, SID Ex)
|
||||
: EHFrameSID(EH), TextSID(T), ExceptTabSID(Ex) {}
|
||||
SID EHFrameSID;
|
||||
SID TextSID;
|
||||
SID ExceptTabSID;
|
||||
};
|
||||
|
||||
// When a module is loaded we save the SectionID of the EH frame section
|
||||
// in a table until we receive a request to register all unregistered
|
||||
// EH frame sections with the memory manager.
|
||||
SmallVector<EHFrameRelatedSections, 2> UnregisteredEHFrameSections;
|
||||
|
||||
RuntimeDyldMachO(RuntimeDyld::MemoryManager &MemMgr,
|
||||
JITSymbolResolver &Resolver)
|
||||
: RuntimeDyldImpl(MemMgr, Resolver) {}
|
||||
|
||||
/// This convenience method uses memcpy to extract a contiguous addend (the
|
||||
/// addend size and offset are taken from the corresponding fields of the RE).
|
||||
int64_t memcpyAddend(const RelocationEntry &RE) const;
|
||||
|
||||
/// Given a relocation_iterator for a non-scattered relocation, construct a
|
||||
/// RelocationEntry and fill in the common fields. The 'Addend' field is *not*
|
||||
/// filled in, since immediate encodings are highly target/opcode specific.
|
||||
/// For targets/opcodes with simple, contiguous immediates (e.g. X86) the
|
||||
/// memcpyAddend method can be used to read the immediate.
|
||||
RelocationEntry getRelocationEntry(unsigned SectionID,
|
||||
const ObjectFile &BaseTObj,
|
||||
const relocation_iterator &RI) const {
|
||||
const MachOObjectFile &Obj =
|
||||
static_cast<const MachOObjectFile &>(BaseTObj);
|
||||
MachO::any_relocation_info RelInfo =
|
||||
Obj.getRelocation(RI->getRawDataRefImpl());
|
||||
|
||||
bool IsPCRel = Obj.getAnyRelocationPCRel(RelInfo);
|
||||
unsigned Size = Obj.getAnyRelocationLength(RelInfo);
|
||||
uint64_t Offset = RI->getOffset();
|
||||
MachO::RelocationInfoType RelType =
|
||||
static_cast<MachO::RelocationInfoType>(Obj.getAnyRelocationType(RelInfo));
|
||||
|
||||
return RelocationEntry(SectionID, Offset, RelType, 0, IsPCRel, Size);
|
||||
}
|
||||
|
||||
/// Process a scattered vanilla relocation.
|
||||
Expected<relocation_iterator>
|
||||
processScatteredVANILLA(unsigned SectionID, relocation_iterator RelI,
|
||||
const ObjectFile &BaseObjT,
|
||||
RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID,
|
||||
bool TargetIsLocalThumbFunc = false);
|
||||
|
||||
/// Construct a RelocationValueRef representing the relocation target.
|
||||
/// For Symbols in known sections, this will return a RelocationValueRef
|
||||
/// representing a (SectionID, Offset) pair.
|
||||
/// For Symbols whose section is not known, this will return a
|
||||
/// (SymbolName, Offset) pair, where the Offset is taken from the instruction
|
||||
/// immediate (held in RE.Addend).
|
||||
/// In both cases the Addend field is *NOT* fixed up to be PC-relative. That
|
||||
/// should be done by the caller where appropriate by calling makePCRel on
|
||||
/// the RelocationValueRef.
|
||||
Expected<RelocationValueRef>
|
||||
getRelocationValueRef(const ObjectFile &BaseTObj,
|
||||
const relocation_iterator &RI,
|
||||
const RelocationEntry &RE,
|
||||
ObjSectionToIDMap &ObjSectionToID);
|
||||
|
||||
/// Make the RelocationValueRef addend PC-relative.
|
||||
void makeValueAddendPCRel(RelocationValueRef &Value,
|
||||
const relocation_iterator &RI,
|
||||
unsigned OffsetToNextPC);
|
||||
|
||||
/// Dump information about the relocation entry (RE) and resolved value.
|
||||
void dumpRelocationToResolve(const RelocationEntry &RE, uint64_t Value) const;
|
||||
|
||||
// Return a section iterator for the section containing the given address.
|
||||
static section_iterator getSectionByAddress(const MachOObjectFile &Obj,
|
||||
uint64_t Addr);
|
||||
|
||||
|
||||
// Populate __pointers section.
|
||||
Error populateIndirectSymbolPointersSection(const MachOObjectFile &Obj,
|
||||
const SectionRef &PTSection,
|
||||
unsigned PTSectionID);
|
||||
|
||||
public:
|
||||
|
||||
/// Create a RuntimeDyldMachO instance for the given target architecture.
|
||||
static std::unique_ptr<RuntimeDyldMachO>
|
||||
create(Triple::ArchType Arch,
|
||||
RuntimeDyld::MemoryManager &MemMgr,
|
||||
JITSymbolResolver &Resolver);
|
||||
|
||||
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
|
||||
loadObject(const object::ObjectFile &O) override;
|
||||
|
||||
SectionEntry &getSection(unsigned SectionID) { return Sections[SectionID]; }
|
||||
|
||||
bool isCompatibleFile(const object::ObjectFile &Obj) const override;
|
||||
};
|
||||
|
||||
/// RuntimeDyldMachOTarget - Templated base class for generic MachO linker
|
||||
/// algorithms and data structures.
|
||||
///
|
||||
/// Concrete, target specific sub-classes can be accessed via the impl()
|
||||
/// methods. (i.e. the RuntimeDyldMachO hierarchy uses the Curiously
|
||||
/// Recurring Template Idiom). Concrete subclasses for each target
|
||||
/// can be found in ./Targets.
|
||||
template <typename Impl>
|
||||
class RuntimeDyldMachOCRTPBase : public RuntimeDyldMachO {
|
||||
private:
|
||||
Impl &impl() { return static_cast<Impl &>(*this); }
|
||||
const Impl &impl() const { return static_cast<const Impl &>(*this); }
|
||||
|
||||
unsigned char *processFDE(uint8_t *P, int64_t DeltaForText,
|
||||
int64_t DeltaForEH);
|
||||
|
||||
public:
|
||||
RuntimeDyldMachOCRTPBase(RuntimeDyld::MemoryManager &MemMgr,
|
||||
JITSymbolResolver &Resolver)
|
||||
: RuntimeDyldMachO(MemMgr, Resolver) {}
|
||||
|
||||
Error finalizeLoad(const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &SectionMap) override;
|
||||
void registerEHFrames() override;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#undef DEBUG_TYPE
|
||||
|
||||
#endif
|
@ -1,215 +0,0 @@
|
||||
//===--- RuntimeDyldCOFFI386.h --- COFF/X86_64 specific code ---*- C++ --*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// COFF x86 support for MC-JIT runtime dynamic linker.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFI386_H
|
||||
#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFI386_H
|
||||
|
||||
#include "../RuntimeDyldCOFF.h"
|
||||
#include "llvm/BinaryFormat/COFF.h"
|
||||
#include "llvm/Object/COFF.h"
|
||||
|
||||
#define DEBUG_TYPE "dyld"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class RuntimeDyldCOFFI386 : public RuntimeDyldCOFF {
|
||||
public:
|
||||
RuntimeDyldCOFFI386(RuntimeDyld::MemoryManager &MM,
|
||||
JITSymbolResolver &Resolver)
|
||||
: RuntimeDyldCOFF(MM, Resolver) {}
|
||||
|
||||
unsigned getMaxStubSize() override {
|
||||
return 8; // 2-byte jmp instruction + 32-bit relative address + 2 byte pad
|
||||
}
|
||||
|
||||
unsigned getStubAlignment() override { return 1; }
|
||||
|
||||
Expected<relocation_iterator>
|
||||
processRelocationRef(unsigned SectionID,
|
||||
relocation_iterator RelI,
|
||||
const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &ObjSectionToID,
|
||||
StubMap &Stubs) override {
|
||||
|
||||
auto Symbol = RelI->getSymbol();
|
||||
if (Symbol == Obj.symbol_end())
|
||||
report_fatal_error("Unknown symbol in relocation");
|
||||
|
||||
Expected<StringRef> TargetNameOrErr = Symbol->getName();
|
||||
if (!TargetNameOrErr)
|
||||
return TargetNameOrErr.takeError();
|
||||
StringRef TargetName = *TargetNameOrErr;
|
||||
|
||||
auto SectionOrErr = Symbol->getSection();
|
||||
if (!SectionOrErr)
|
||||
return SectionOrErr.takeError();
|
||||
auto Section = *SectionOrErr;
|
||||
|
||||
uint64_t RelType = RelI->getType();
|
||||
uint64_t Offset = RelI->getOffset();
|
||||
|
||||
// Determine the Addend used to adjust the relocation value.
|
||||
uint64_t Addend = 0;
|
||||
SectionEntry &AddendSection = Sections[SectionID];
|
||||
uintptr_t ObjTarget = AddendSection.getObjAddress() + Offset;
|
||||
uint8_t *Displacement = (uint8_t *)ObjTarget;
|
||||
|
||||
switch (RelType) {
|
||||
case COFF::IMAGE_REL_I386_DIR32:
|
||||
case COFF::IMAGE_REL_I386_DIR32NB:
|
||||
case COFF::IMAGE_REL_I386_SECREL:
|
||||
case COFF::IMAGE_REL_I386_REL32: {
|
||||
Addend = readBytesUnaligned(Displacement, 4);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
SmallString<32> RelTypeName;
|
||||
RelI->getTypeName(RelTypeName);
|
||||
#endif
|
||||
DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
|
||||
<< " RelType: " << RelTypeName << " TargetName: " << TargetName
|
||||
<< " Addend " << Addend << "\n");
|
||||
|
||||
unsigned TargetSectionID = -1;
|
||||
if (Section == Obj.section_end()) {
|
||||
RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0);
|
||||
addRelocationForSymbol(RE, TargetName);
|
||||
} else {
|
||||
if (auto TargetSectionIDOrErr =
|
||||
findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID))
|
||||
TargetSectionID = *TargetSectionIDOrErr;
|
||||
else
|
||||
return TargetSectionIDOrErr.takeError();
|
||||
|
||||
switch (RelType) {
|
||||
case COFF::IMAGE_REL_I386_ABSOLUTE:
|
||||
// This relocation is ignored.
|
||||
break;
|
||||
case COFF::IMAGE_REL_I386_DIR32:
|
||||
case COFF::IMAGE_REL_I386_DIR32NB:
|
||||
case COFF::IMAGE_REL_I386_REL32: {
|
||||
RelocationEntry RE =
|
||||
RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
|
||||
getSymbolOffset(*Symbol), 0, 0, false, 0);
|
||||
addRelocationForSection(RE, TargetSectionID);
|
||||
break;
|
||||
}
|
||||
case COFF::IMAGE_REL_I386_SECTION: {
|
||||
RelocationEntry RE =
|
||||
RelocationEntry(TargetSectionID, Offset, RelType, 0);
|
||||
addRelocationForSection(RE, TargetSectionID);
|
||||
break;
|
||||
}
|
||||
case COFF::IMAGE_REL_I386_SECREL: {
|
||||
RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType,
|
||||
getSymbolOffset(*Symbol) + Addend);
|
||||
addRelocationForSection(RE, TargetSectionID);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
llvm_unreachable("unsupported relocation type");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ++RelI;
|
||||
}
|
||||
|
||||
void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
|
||||
const auto Section = Sections[RE.SectionID];
|
||||
uint8_t *Target = Section.getAddressWithOffset(RE.Offset);
|
||||
|
||||
switch (RE.RelType) {
|
||||
case COFF::IMAGE_REL_I386_ABSOLUTE:
|
||||
// This relocation is ignored.
|
||||
break;
|
||||
case COFF::IMAGE_REL_I386_DIR32: {
|
||||
// The target's 32-bit VA.
|
||||
uint64_t Result =
|
||||
RE.Sections.SectionA == static_cast<uint32_t>(-1)
|
||||
? Value
|
||||
: Sections[RE.Sections.SectionA].getLoadAddressWithOffset(
|
||||
RE.Addend);
|
||||
assert(Result <= UINT32_MAX && "relocation overflow");
|
||||
DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
|
||||
<< " RelType: IMAGE_REL_I386_DIR32"
|
||||
<< " TargetSection: " << RE.Sections.SectionA
|
||||
<< " Value: " << format("0x%08" PRIx32, Result) << '\n');
|
||||
writeBytesUnaligned(Result, Target, 4);
|
||||
break;
|
||||
}
|
||||
case COFF::IMAGE_REL_I386_DIR32NB: {
|
||||
// The target's 32-bit RVA.
|
||||
// NOTE: use Section[0].getLoadAddress() as an approximation of ImageBase
|
||||
uint64_t Result =
|
||||
Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend) -
|
||||
Sections[0].getLoadAddress();
|
||||
assert(Result <= UINT32_MAX && "relocation overflow");
|
||||
DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
|
||||
<< " RelType: IMAGE_REL_I386_DIR32NB"
|
||||
<< " TargetSection: " << RE.Sections.SectionA
|
||||
<< " Value: " << format("0x%08" PRIx32, Result) << '\n');
|
||||
writeBytesUnaligned(Result, Target, 4);
|
||||
break;
|
||||
}
|
||||
case COFF::IMAGE_REL_I386_REL32: {
|
||||
// 32-bit relative displacement to the target.
|
||||
uint64_t Result = RE.Sections.SectionA == static_cast<uint32_t>(-1)
|
||||
? Value
|
||||
: Sections[RE.Sections.SectionA].getLoadAddress();
|
||||
Result = Result - Section.getLoadAddress() + RE.Addend - 4 - RE.Offset;
|
||||
assert(static_cast<int64_t>(Result) <= INT32_MAX &&
|
||||
"relocation overflow");
|
||||
assert(static_cast<int64_t>(Result) >= INT32_MIN &&
|
||||
"relocation underflow");
|
||||
DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
|
||||
<< " RelType: IMAGE_REL_I386_REL32"
|
||||
<< " TargetSection: " << RE.Sections.SectionA
|
||||
<< " Value: " << format("0x%08" PRIx32, Result) << '\n');
|
||||
writeBytesUnaligned(Result, Target, 4);
|
||||
break;
|
||||
}
|
||||
case COFF::IMAGE_REL_I386_SECTION:
|
||||
// 16-bit section index of the section that contains the target.
|
||||
assert(static_cast<uint32_t>(RE.SectionID) <= UINT16_MAX &&
|
||||
"relocation overflow");
|
||||
DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
|
||||
<< " RelType: IMAGE_REL_I386_SECTION Value: " << RE.SectionID
|
||||
<< '\n');
|
||||
writeBytesUnaligned(RE.SectionID, Target, 2);
|
||||
break;
|
||||
case COFF::IMAGE_REL_I386_SECREL:
|
||||
// 32-bit offset of the target from the beginning of its section.
|
||||
assert(static_cast<uint64_t>(RE.Addend) <= UINT32_MAX &&
|
||||
"relocation overflow");
|
||||
DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
|
||||
<< " RelType: IMAGE_REL_I386_SECREL Value: " << RE.Addend
|
||||
<< '\n');
|
||||
writeBytesUnaligned(RE.Addend, Target, 4);
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("unsupported relocation type");
|
||||
}
|
||||
}
|
||||
|
||||
void registerEHFrames() override {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,310 +0,0 @@
|
||||
//===--- RuntimeDyldCOFFThumb.h --- COFF/Thumb specific code ---*- C++ --*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// COFF thumb support for MC-JIT runtime dynamic linker.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFTHUMB_H
|
||||
#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFTHUMB_H
|
||||
|
||||
#include "../RuntimeDyldCOFF.h"
|
||||
#include "llvm/BinaryFormat/COFF.h"
|
||||
#include "llvm/Object/COFF.h"
|
||||
|
||||
#define DEBUG_TYPE "dyld"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
static bool isThumbFunc(symbol_iterator Symbol, const ObjectFile &Obj,
|
||||
section_iterator Section) {
|
||||
Expected<SymbolRef::Type> SymTypeOrErr = Symbol->getType();
|
||||
if (!SymTypeOrErr) {
|
||||
std::string Buf;
|
||||
raw_string_ostream OS(Buf);
|
||||
logAllUnhandledErrors(SymTypeOrErr.takeError(), OS, "");
|
||||
OS.flush();
|
||||
report_fatal_error(Buf);
|
||||
}
|
||||
|
||||
if (*SymTypeOrErr != SymbolRef::ST_Function)
|
||||
return false;
|
||||
|
||||
// We check the IMAGE_SCN_MEM_16BIT flag in the section of the symbol to tell
|
||||
// if it's thumb or not
|
||||
return cast<COFFObjectFile>(Obj).getCOFFSection(*Section)->Characteristics &
|
||||
COFF::IMAGE_SCN_MEM_16BIT;
|
||||
}
|
||||
|
||||
class RuntimeDyldCOFFThumb : public RuntimeDyldCOFF {
|
||||
public:
|
||||
RuntimeDyldCOFFThumb(RuntimeDyld::MemoryManager &MM,
|
||||
JITSymbolResolver &Resolver)
|
||||
: RuntimeDyldCOFF(MM, Resolver) {}
|
||||
|
||||
unsigned getMaxStubSize() override {
|
||||
return 16; // 8-byte load instructions, 4-byte jump, 4-byte padding
|
||||
}
|
||||
|
||||
unsigned getStubAlignment() override { return 1; }
|
||||
|
||||
Expected<relocation_iterator>
|
||||
processRelocationRef(unsigned SectionID,
|
||||
relocation_iterator RelI,
|
||||
const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &ObjSectionToID,
|
||||
StubMap &Stubs) override {
|
||||
auto Symbol = RelI->getSymbol();
|
||||
if (Symbol == Obj.symbol_end())
|
||||
report_fatal_error("Unknown symbol in relocation");
|
||||
|
||||
Expected<StringRef> TargetNameOrErr = Symbol->getName();
|
||||
if (!TargetNameOrErr)
|
||||
return TargetNameOrErr.takeError();
|
||||
StringRef TargetName = *TargetNameOrErr;
|
||||
|
||||
auto SectionOrErr = Symbol->getSection();
|
||||
if (!SectionOrErr)
|
||||
return SectionOrErr.takeError();
|
||||
auto Section = *SectionOrErr;
|
||||
|
||||
uint64_t RelType = RelI->getType();
|
||||
uint64_t Offset = RelI->getOffset();
|
||||
|
||||
// Determine the Addend used to adjust the relocation value.
|
||||
uint64_t Addend = 0;
|
||||
SectionEntry &AddendSection = Sections[SectionID];
|
||||
uintptr_t ObjTarget = AddendSection.getObjAddress() + Offset;
|
||||
uint8_t *Displacement = (uint8_t *)ObjTarget;
|
||||
|
||||
switch (RelType) {
|
||||
case COFF::IMAGE_REL_ARM_ADDR32:
|
||||
case COFF::IMAGE_REL_ARM_ADDR32NB:
|
||||
case COFF::IMAGE_REL_ARM_SECREL:
|
||||
Addend = readBytesUnaligned(Displacement, 4);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
SmallString<32> RelTypeName;
|
||||
RelI->getTypeName(RelTypeName);
|
||||
#endif
|
||||
DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
|
||||
<< " RelType: " << RelTypeName << " TargetName: " << TargetName
|
||||
<< " Addend " << Addend << "\n");
|
||||
|
||||
unsigned TargetSectionID = -1;
|
||||
if (Section == Obj.section_end()) {
|
||||
RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0);
|
||||
addRelocationForSymbol(RE, TargetName);
|
||||
} else {
|
||||
if (auto TargetSectionIDOrErr =
|
||||
findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID))
|
||||
TargetSectionID = *TargetSectionIDOrErr;
|
||||
else
|
||||
return TargetSectionIDOrErr.takeError();
|
||||
|
||||
// We need to find out if the relocation is relative to a thumb function
|
||||
// so that we include the ISA selection bit when resolve the relocation
|
||||
bool IsTargetThumbFunc = isThumbFunc(Symbol, Obj, Section);
|
||||
|
||||
switch (RelType) {
|
||||
default: llvm_unreachable("unsupported relocation type");
|
||||
case COFF::IMAGE_REL_ARM_ABSOLUTE:
|
||||
// This relocation is ignored.
|
||||
break;
|
||||
case COFF::IMAGE_REL_ARM_ADDR32: {
|
||||
RelocationEntry RE = RelocationEntry(
|
||||
SectionID, Offset, RelType, Addend, TargetSectionID,
|
||||
getSymbolOffset(*Symbol), 0, 0, false, 0, IsTargetThumbFunc);
|
||||
addRelocationForSection(RE, TargetSectionID);
|
||||
break;
|
||||
}
|
||||
case COFF::IMAGE_REL_ARM_ADDR32NB: {
|
||||
RelocationEntry RE =
|
||||
RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
|
||||
getSymbolOffset(*Symbol), 0, 0, false, 0);
|
||||
addRelocationForSection(RE, TargetSectionID);
|
||||
break;
|
||||
}
|
||||
case COFF::IMAGE_REL_ARM_SECTION: {
|
||||
RelocationEntry RE =
|
||||
RelocationEntry(TargetSectionID, Offset, RelType, 0);
|
||||
addRelocationForSection(RE, TargetSectionID);
|
||||
break;
|
||||
}
|
||||
case COFF::IMAGE_REL_ARM_SECREL: {
|
||||
RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType,
|
||||
getSymbolOffset(*Symbol) + Addend);
|
||||
addRelocationForSection(RE, TargetSectionID);
|
||||
break;
|
||||
}
|
||||
case COFF::IMAGE_REL_ARM_MOV32T: {
|
||||
RelocationEntry RE = RelocationEntry(
|
||||
SectionID, Offset, RelType, Addend, TargetSectionID,
|
||||
getSymbolOffset(*Symbol), 0, 0, false, 0, IsTargetThumbFunc);
|
||||
addRelocationForSection(RE, TargetSectionID);
|
||||
break;
|
||||
}
|
||||
case COFF::IMAGE_REL_ARM_BRANCH20T:
|
||||
case COFF::IMAGE_REL_ARM_BRANCH24T:
|
||||
case COFF::IMAGE_REL_ARM_BLX23T: {
|
||||
RelocationEntry RE =
|
||||
RelocationEntry(SectionID, Offset, RelType,
|
||||
getSymbolOffset(*Symbol) + Addend, true, 0);
|
||||
addRelocationForSection(RE, TargetSectionID);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ++RelI;
|
||||
}
|
||||
|
||||
void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
|
||||
const auto Section = Sections[RE.SectionID];
|
||||
uint8_t *Target = Section.getAddressWithOffset(RE.Offset);
|
||||
int ISASelectionBit = RE.IsTargetThumbFunc ? 1 : 0;
|
||||
|
||||
switch (RE.RelType) {
|
||||
default: llvm_unreachable("unsupported relocation type");
|
||||
case COFF::IMAGE_REL_ARM_ABSOLUTE:
|
||||
// This relocation is ignored.
|
||||
break;
|
||||
case COFF::IMAGE_REL_ARM_ADDR32: {
|
||||
// The target's 32-bit VA.
|
||||
uint64_t Result =
|
||||
RE.Sections.SectionA == static_cast<uint32_t>(-1)
|
||||
? Value
|
||||
: Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend);
|
||||
Result |= ISASelectionBit;
|
||||
assert(Result <= UINT32_MAX && "relocation overflow");
|
||||
DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
|
||||
<< " RelType: IMAGE_REL_ARM_ADDR32"
|
||||
<< " TargetSection: " << RE.Sections.SectionA
|
||||
<< " Value: " << format("0x%08" PRIx32, Result) << '\n');
|
||||
writeBytesUnaligned(Result, Target, 4);
|
||||
break;
|
||||
}
|
||||
case COFF::IMAGE_REL_ARM_ADDR32NB: {
|
||||
// The target's 32-bit RVA.
|
||||
// NOTE: use Section[0].getLoadAddress() as an approximation of ImageBase
|
||||
uint64_t Result = Sections[RE.Sections.SectionA].getLoadAddress() -
|
||||
Sections[0].getLoadAddress() + RE.Addend;
|
||||
assert(Result <= UINT32_MAX && "relocation overflow");
|
||||
DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
|
||||
<< " RelType: IMAGE_REL_ARM_ADDR32NB"
|
||||
<< " TargetSection: " << RE.Sections.SectionA
|
||||
<< " Value: " << format("0x%08" PRIx32, Result) << '\n');
|
||||
Result |= ISASelectionBit;
|
||||
writeBytesUnaligned(Result, Target, 4);
|
||||
break;
|
||||
}
|
||||
case COFF::IMAGE_REL_ARM_SECTION:
|
||||
// 16-bit section index of the section that contains the target.
|
||||
assert(static_cast<uint32_t>(RE.SectionID) <= UINT16_MAX &&
|
||||
"relocation overflow");
|
||||
DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
|
||||
<< " RelType: IMAGE_REL_ARM_SECTION Value: " << RE.SectionID
|
||||
<< '\n');
|
||||
writeBytesUnaligned(RE.SectionID, Target, 2);
|
||||
break;
|
||||
case COFF::IMAGE_REL_ARM_SECREL:
|
||||
// 32-bit offset of the target from the beginning of its section.
|
||||
assert(static_cast<uint64_t>(RE.Addend) <= UINT32_MAX &&
|
||||
"relocation overflow");
|
||||
DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
|
||||
<< " RelType: IMAGE_REL_ARM_SECREL Value: " << RE.Addend
|
||||
<< '\n');
|
||||
writeBytesUnaligned(RE.Addend, Target, 2);
|
||||
break;
|
||||
case COFF::IMAGE_REL_ARM_MOV32T: {
|
||||
// 32-bit VA of the target applied to a contiguous MOVW+MOVT pair.
|
||||
uint64_t Result =
|
||||
Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend);
|
||||
assert(Result <= UINT32_MAX && "relocation overflow");
|
||||
DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
|
||||
<< " RelType: IMAGE_REL_ARM_MOV32T"
|
||||
<< " TargetSection: " << RE.Sections.SectionA
|
||||
<< " Value: " << format("0x%08" PRIx32, Result) << '\n');
|
||||
|
||||
// MOVW(T3): |11110|i|10|0|1|0|0|imm4|0|imm3|Rd|imm8|
|
||||
// imm32 = zext imm4:i:imm3:imm8
|
||||
// MOVT(T1): |11110|i|10|1|1|0|0|imm4|0|imm3|Rd|imm8|
|
||||
// imm16 = imm4:i:imm3:imm8
|
||||
|
||||
auto EncodeImmediate = [](uint8_t *Bytes, uint16_t Immediate) {
|
||||
Bytes[0] |= ((Immediate & 0xf000) >> 12);
|
||||
Bytes[1] |= ((Immediate & 0x0800) >> 11);
|
||||
Bytes[2] |= ((Immediate & 0x00ff) >> 0);
|
||||
Bytes[3] |= (((Immediate & 0x0700) >> 8) << 4);
|
||||
};
|
||||
|
||||
EncodeImmediate(&Target[0],
|
||||
(static_cast<uint32_t>(Result) >> 00) | ISASelectionBit);
|
||||
EncodeImmediate(&Target[4], static_cast<uint32_t>(Result) >> 16);
|
||||
|
||||
break;
|
||||
}
|
||||
case COFF::IMAGE_REL_ARM_BRANCH20T: {
|
||||
// The most significant 20-bits of the signed 21-bit relative displacement
|
||||
uint64_t Value =
|
||||
RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4;
|
||||
assert(static_cast<int64_t>(RE.Addend) <= INT32_MAX &&
|
||||
"relocation overflow");
|
||||
assert(static_cast<int64_t>(RE.Addend) >= INT32_MIN &&
|
||||
"relocation underflow");
|
||||
DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
|
||||
<< " RelType: IMAGE_REL_ARM_BRANCH20T"
|
||||
<< " Value: " << static_cast<int32_t>(Value) << '\n');
|
||||
static_cast<void>(Value);
|
||||
llvm_unreachable("unimplemented relocation");
|
||||
break;
|
||||
}
|
||||
case COFF::IMAGE_REL_ARM_BRANCH24T: {
|
||||
// The most significant 24-bits of the signed 25-bit relative displacement
|
||||
uint64_t Value =
|
||||
RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4;
|
||||
assert(static_cast<int64_t>(RE.Addend) <= INT32_MAX &&
|
||||
"relocation overflow");
|
||||
assert(static_cast<int64_t>(RE.Addend) >= INT32_MIN &&
|
||||
"relocation underflow");
|
||||
DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
|
||||
<< " RelType: IMAGE_REL_ARM_BRANCH24T"
|
||||
<< " Value: " << static_cast<int32_t>(Value) << '\n');
|
||||
static_cast<void>(Value);
|
||||
llvm_unreachable("unimplemented relocation");
|
||||
break;
|
||||
}
|
||||
case COFF::IMAGE_REL_ARM_BLX23T: {
|
||||
// The most significant 24-bits of the signed 25-bit relative displacement
|
||||
uint64_t Value =
|
||||
RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4;
|
||||
assert(static_cast<int64_t>(RE.Addend) <= INT32_MAX &&
|
||||
"relocation overflow");
|
||||
assert(static_cast<int64_t>(RE.Addend) >= INT32_MIN &&
|
||||
"relocation underflow");
|
||||
DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
|
||||
<< " RelType: IMAGE_REL_ARM_BLX23T"
|
||||
<< " Value: " << static_cast<int32_t>(Value) << '\n');
|
||||
static_cast<void>(Value);
|
||||
llvm_unreachable("unimplemented relocation");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void registerEHFrames() override {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -1,219 +0,0 @@
|
||||
//===-- RuntimeDyldCOFFX86_64.h --- COFF/X86_64 specific code ---*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// COFF x86_x64 support for MC-JIT runtime dynamic linker.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFF86_64_H
|
||||
#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFF86_64_H
|
||||
|
||||
#include "../RuntimeDyldCOFF.h"
|
||||
#include "llvm/BinaryFormat/COFF.h"
|
||||
#include "llvm/Object/COFF.h"
|
||||
|
||||
#define DEBUG_TYPE "dyld"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class RuntimeDyldCOFFX86_64 : public RuntimeDyldCOFF {
|
||||
|
||||
private:
|
||||
// When a module is loaded we save the SectionID of the unwind
|
||||
// sections in a table until we receive a request to register all
|
||||
// unregisteredEH frame sections with the memory manager.
|
||||
SmallVector<SID, 2> UnregisteredEHFrameSections;
|
||||
SmallVector<SID, 2> RegisteredEHFrameSections;
|
||||
|
||||
public:
|
||||
RuntimeDyldCOFFX86_64(RuntimeDyld::MemoryManager &MM,
|
||||
JITSymbolResolver &Resolver)
|
||||
: RuntimeDyldCOFF(MM, Resolver) {}
|
||||
|
||||
unsigned getMaxStubSize() override {
|
||||
return 6; // 2-byte jmp instruction + 32-bit relative address
|
||||
}
|
||||
|
||||
// The target location for the relocation is described by RE.SectionID and
|
||||
// RE.Offset. RE.SectionID can be used to find the SectionEntry. Each
|
||||
// SectionEntry has three members describing its location.
|
||||
// SectionEntry::Address is the address at which the section has been loaded
|
||||
// into memory in the current (host) process. SectionEntry::LoadAddress is
|
||||
// the address that the section will have in the target process.
|
||||
// SectionEntry::ObjAddress is the address of the bits for this section in the
|
||||
// original emitted object image (also in the current address space).
|
||||
//
|
||||
// Relocations will be applied as if the section were loaded at
|
||||
// SectionEntry::LoadAddress, but they will be applied at an address based
|
||||
// on SectionEntry::Address. SectionEntry::ObjAddress will be used to refer
|
||||
// to Target memory contents if they are required for value calculations.
|
||||
//
|
||||
// The Value parameter here is the load address of the symbol for the
|
||||
// relocation to be applied. For relocations which refer to symbols in the
|
||||
// current object Value will be the LoadAddress of the section in which
|
||||
// the symbol resides (RE.Addend provides additional information about the
|
||||
// symbol location). For external symbols, Value will be the address of the
|
||||
// symbol in the target address space.
|
||||
void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
|
||||
const SectionEntry &Section = Sections[RE.SectionID];
|
||||
uint8_t *Target = Section.getAddressWithOffset(RE.Offset);
|
||||
|
||||
switch (RE.RelType) {
|
||||
|
||||
case COFF::IMAGE_REL_AMD64_REL32:
|
||||
case COFF::IMAGE_REL_AMD64_REL32_1:
|
||||
case COFF::IMAGE_REL_AMD64_REL32_2:
|
||||
case COFF::IMAGE_REL_AMD64_REL32_3:
|
||||
case COFF::IMAGE_REL_AMD64_REL32_4:
|
||||
case COFF::IMAGE_REL_AMD64_REL32_5: {
|
||||
uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset);
|
||||
// Delta is the distance from the start of the reloc to the end of the
|
||||
// instruction with the reloc.
|
||||
uint64_t Delta = 4 + (RE.RelType - COFF::IMAGE_REL_AMD64_REL32);
|
||||
Value -= FinalAddress + Delta;
|
||||
uint64_t Result = Value + RE.Addend;
|
||||
assert(((int64_t)Result <= INT32_MAX) && "Relocation overflow");
|
||||
assert(((int64_t)Result >= INT32_MIN) && "Relocation underflow");
|
||||
writeBytesUnaligned(Result, Target, 4);
|
||||
break;
|
||||
}
|
||||
|
||||
case COFF::IMAGE_REL_AMD64_ADDR32NB: {
|
||||
// Note ADDR32NB requires a well-established notion of
|
||||
// image base. This address must be less than or equal
|
||||
// to every section's load address, and all sections must be
|
||||
// within a 32 bit offset from the base.
|
||||
//
|
||||
// For now we just set these to zero.
|
||||
writeBytesUnaligned(0, Target, 4);
|
||||
break;
|
||||
}
|
||||
|
||||
case COFF::IMAGE_REL_AMD64_ADDR64: {
|
||||
writeBytesUnaligned(Value + RE.Addend, Target, 8);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
llvm_unreachable("Relocation type not implemented yet!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Expected<relocation_iterator>
|
||||
processRelocationRef(unsigned SectionID,
|
||||
relocation_iterator RelI,
|
||||
const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &ObjSectionToID,
|
||||
StubMap &Stubs) override {
|
||||
// If possible, find the symbol referred to in the relocation,
|
||||
// and the section that contains it.
|
||||
symbol_iterator Symbol = RelI->getSymbol();
|
||||
if (Symbol == Obj.symbol_end())
|
||||
report_fatal_error("Unknown symbol in relocation");
|
||||
auto SectionOrError = Symbol->getSection();
|
||||
if (!SectionOrError)
|
||||
return SectionOrError.takeError();
|
||||
section_iterator SecI = *SectionOrError;
|
||||
// If there is no section, this must be an external reference.
|
||||
const bool IsExtern = SecI == Obj.section_end();
|
||||
|
||||
// Determine the Addend used to adjust the relocation value.
|
||||
uint64_t RelType = RelI->getType();
|
||||
uint64_t Offset = RelI->getOffset();
|
||||
uint64_t Addend = 0;
|
||||
SectionEntry &Section = Sections[SectionID];
|
||||
uintptr_t ObjTarget = Section.getObjAddress() + Offset;
|
||||
|
||||
switch (RelType) {
|
||||
|
||||
case COFF::IMAGE_REL_AMD64_REL32:
|
||||
case COFF::IMAGE_REL_AMD64_REL32_1:
|
||||
case COFF::IMAGE_REL_AMD64_REL32_2:
|
||||
case COFF::IMAGE_REL_AMD64_REL32_3:
|
||||
case COFF::IMAGE_REL_AMD64_REL32_4:
|
||||
case COFF::IMAGE_REL_AMD64_REL32_5:
|
||||
case COFF::IMAGE_REL_AMD64_ADDR32NB: {
|
||||
uint8_t *Displacement = (uint8_t *)ObjTarget;
|
||||
Addend = readBytesUnaligned(Displacement, 4);
|
||||
break;
|
||||
}
|
||||
|
||||
case COFF::IMAGE_REL_AMD64_ADDR64: {
|
||||
uint8_t *Displacement = (uint8_t *)ObjTarget;
|
||||
Addend = readBytesUnaligned(Displacement, 8);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Expected<StringRef> TargetNameOrErr = Symbol->getName();
|
||||
if (!TargetNameOrErr)
|
||||
return TargetNameOrErr.takeError();
|
||||
StringRef TargetName = *TargetNameOrErr;
|
||||
|
||||
DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
|
||||
<< " RelType: " << RelType << " TargetName: " << TargetName
|
||||
<< " Addend " << Addend << "\n");
|
||||
|
||||
if (IsExtern) {
|
||||
RelocationEntry RE(SectionID, Offset, RelType, Addend);
|
||||
addRelocationForSymbol(RE, TargetName);
|
||||
} else {
|
||||
bool IsCode = SecI->isText();
|
||||
unsigned TargetSectionID;
|
||||
if (auto TargetSectionIDOrErr =
|
||||
findOrEmitSection(Obj, *SecI, IsCode, ObjSectionToID))
|
||||
TargetSectionID = *TargetSectionIDOrErr;
|
||||
else
|
||||
return TargetSectionIDOrErr.takeError();
|
||||
uint64_t TargetOffset = getSymbolOffset(*Symbol);
|
||||
RelocationEntry RE(SectionID, Offset, RelType, TargetOffset + Addend);
|
||||
addRelocationForSection(RE, TargetSectionID);
|
||||
}
|
||||
|
||||
return ++RelI;
|
||||
}
|
||||
|
||||
unsigned getStubAlignment() override { return 1; }
|
||||
void registerEHFrames() override {
|
||||
for (auto const &EHFrameSID : UnregisteredEHFrameSections) {
|
||||
uint8_t *EHFrameAddr = Sections[EHFrameSID].getAddress();
|
||||
uint64_t EHFrameLoadAddr = Sections[EHFrameSID].getLoadAddress();
|
||||
size_t EHFrameSize = Sections[EHFrameSID].getSize();
|
||||
MemMgr.registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize);
|
||||
RegisteredEHFrameSections.push_back(EHFrameSID);
|
||||
}
|
||||
UnregisteredEHFrameSections.clear();
|
||||
}
|
||||
Error finalizeLoad(const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &SectionMap) override {
|
||||
// Look for and record the EH frame section IDs.
|
||||
for (const auto &SectionPair : SectionMap) {
|
||||
const SectionRef &Section = SectionPair.first;
|
||||
StringRef Name;
|
||||
if (auto EC = Section.getName(Name))
|
||||
return errorCodeToError(EC);
|
||||
// Note unwind info is split across .pdata and .xdata, so this
|
||||
// may not be sufficiently general for all users.
|
||||
if (Name == ".xdata") {
|
||||
UnregisteredEHFrameSections.push_back(SectionPair.second);
|
||||
}
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#undef DEBUG_TYPE
|
||||
|
||||
#endif
|
@ -1,321 +0,0 @@
|
||||
//===-- RuntimeDyldELFMips.cpp ---- ELF/Mips specific code. -----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "RuntimeDyldELFMips.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
|
||||
#define DEBUG_TYPE "dyld"
|
||||
|
||||
void RuntimeDyldELFMips::resolveRelocation(const RelocationEntry &RE,
|
||||
uint64_t Value) {
|
||||
const SectionEntry &Section = Sections[RE.SectionID];
|
||||
if (IsMipsO32ABI)
|
||||
resolveMIPSO32Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend);
|
||||
else if (IsMipsN32ABI) {
|
||||
resolveMIPSN32Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend,
|
||||
RE.SymOffset, RE.SectionID);
|
||||
} else if (IsMipsN64ABI)
|
||||
resolveMIPSN64Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend,
|
||||
RE.SymOffset, RE.SectionID);
|
||||
else
|
||||
llvm_unreachable("Mips ABI not handled");
|
||||
}
|
||||
|
||||
uint64_t RuntimeDyldELFMips::evaluateRelocation(const RelocationEntry &RE,
|
||||
uint64_t Value,
|
||||
uint64_t Addend) {
|
||||
if (IsMipsN32ABI) {
|
||||
const SectionEntry &Section = Sections[RE.SectionID];
|
||||
Value = evaluateMIPS64Relocation(Section, RE.Offset, Value, RE.RelType,
|
||||
Addend, RE.SymOffset, RE.SectionID);
|
||||
return Value;
|
||||
}
|
||||
llvm_unreachable("Not reachable");
|
||||
}
|
||||
|
||||
void RuntimeDyldELFMips::applyRelocation(const RelocationEntry &RE,
|
||||
uint64_t Value) {
|
||||
if (IsMipsN32ABI) {
|
||||
const SectionEntry &Section = Sections[RE.SectionID];
|
||||
applyMIPSRelocation(Section.getAddressWithOffset(RE.Offset), Value,
|
||||
RE.RelType);
|
||||
return;
|
||||
}
|
||||
llvm_unreachable("Not reachable");
|
||||
}
|
||||
|
||||
int64_t
|
||||
RuntimeDyldELFMips::evaluateMIPS32Relocation(const SectionEntry &Section,
|
||||
uint64_t Offset, uint64_t Value,
|
||||
uint32_t Type) {
|
||||
|
||||
DEBUG(dbgs() << "evaluateMIPS32Relocation, LocalAddress: 0x"
|
||||
<< format("%llx", Section.getAddressWithOffset(Offset))
|
||||
<< " FinalAddress: 0x"
|
||||
<< format("%llx", Section.getLoadAddressWithOffset(Offset))
|
||||
<< " Value: 0x" << format("%llx", Value) << " Type: 0x"
|
||||
<< format("%x", Type) << "\n");
|
||||
|
||||
switch (Type) {
|
||||
default:
|
||||
llvm_unreachable("Unknown relocation type!");
|
||||
return Value;
|
||||
case ELF::R_MIPS_32:
|
||||
return Value;
|
||||
case ELF::R_MIPS_26:
|
||||
return Value >> 2;
|
||||
case ELF::R_MIPS_HI16:
|
||||
// Get the higher 16-bits. Also add 1 if bit 15 is 1.
|
||||
return (Value + 0x8000) >> 16;
|
||||
case ELF::R_MIPS_LO16:
|
||||
return Value;
|
||||
case ELF::R_MIPS_PC32: {
|
||||
uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
|
||||
return Value - FinalAddress;
|
||||
}
|
||||
case ELF::R_MIPS_PC16: {
|
||||
uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
|
||||
return (Value - FinalAddress) >> 2;
|
||||
}
|
||||
case ELF::R_MIPS_PC19_S2: {
|
||||
uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
|
||||
return (Value - (FinalAddress & ~0x3)) >> 2;
|
||||
}
|
||||
case ELF::R_MIPS_PC21_S2: {
|
||||
uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
|
||||
return (Value - FinalAddress) >> 2;
|
||||
}
|
||||
case ELF::R_MIPS_PC26_S2: {
|
||||
uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
|
||||
return (Value - FinalAddress) >> 2;
|
||||
}
|
||||
case ELF::R_MIPS_PCHI16: {
|
||||
uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
|
||||
return (Value - FinalAddress + 0x8000) >> 16;
|
||||
}
|
||||
case ELF::R_MIPS_PCLO16: {
|
||||
uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
|
||||
return Value - FinalAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int64_t RuntimeDyldELFMips::evaluateMIPS64Relocation(
|
||||
const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type,
|
||||
int64_t Addend, uint64_t SymOffset, SID SectionID) {
|
||||
|
||||
DEBUG(dbgs() << "evaluateMIPS64Relocation, LocalAddress: 0x"
|
||||
<< format("%llx", Section.getAddressWithOffset(Offset))
|
||||
<< " FinalAddress: 0x"
|
||||
<< format("%llx", Section.getLoadAddressWithOffset(Offset))
|
||||
<< " Value: 0x" << format("%llx", Value) << " Type: 0x"
|
||||
<< format("%x", Type) << " Addend: 0x" << format("%llx", Addend)
|
||||
<< " Offset: " << format("%llx" PRIx64, Offset)
|
||||
<< " SID: " << format("%d", SectionID)
|
||||
<< " SymOffset: " << format("%x", SymOffset) << "\n");
|
||||
|
||||
switch (Type) {
|
||||
default:
|
||||
llvm_unreachable("Not implemented relocation type!");
|
||||
break;
|
||||
case ELF::R_MIPS_JALR:
|
||||
case ELF::R_MIPS_NONE:
|
||||
break;
|
||||
case ELF::R_MIPS_32:
|
||||
case ELF::R_MIPS_64:
|
||||
return Value + Addend;
|
||||
case ELF::R_MIPS_26:
|
||||
return ((Value + Addend) >> 2) & 0x3ffffff;
|
||||
case ELF::R_MIPS_GPREL16: {
|
||||
uint64_t GOTAddr = getSectionLoadAddress(SectionToGOTMap[SectionID]);
|
||||
return Value + Addend - (GOTAddr + 0x7ff0);
|
||||
}
|
||||
case ELF::R_MIPS_SUB:
|
||||
return Value - Addend;
|
||||
case ELF::R_MIPS_HI16:
|
||||
// Get the higher 16-bits. Also add 1 if bit 15 is 1.
|
||||
return ((Value + Addend + 0x8000) >> 16) & 0xffff;
|
||||
case ELF::R_MIPS_LO16:
|
||||
return (Value + Addend) & 0xffff;
|
||||
case ELF::R_MIPS_HIGHER:
|
||||
return ((Value + Addend + 0x80008000) >> 32) & 0xffff;
|
||||
case ELF::R_MIPS_HIGHEST:
|
||||
return ((Value + Addend + 0x800080008000) >> 48) & 0xffff;
|
||||
case ELF::R_MIPS_CALL16:
|
||||
case ELF::R_MIPS_GOT_DISP:
|
||||
case ELF::R_MIPS_GOT_PAGE: {
|
||||
uint8_t *LocalGOTAddr =
|
||||
getSectionAddress(SectionToGOTMap[SectionID]) + SymOffset;
|
||||
uint64_t GOTEntry = readBytesUnaligned(LocalGOTAddr, getGOTEntrySize());
|
||||
|
||||
Value += Addend;
|
||||
if (Type == ELF::R_MIPS_GOT_PAGE)
|
||||
Value = (Value + 0x8000) & ~0xffff;
|
||||
|
||||
if (GOTEntry)
|
||||
assert(GOTEntry == Value &&
|
||||
"GOT entry has two different addresses.");
|
||||
else
|
||||
writeBytesUnaligned(Value, LocalGOTAddr, getGOTEntrySize());
|
||||
|
||||
return (SymOffset - 0x7ff0) & 0xffff;
|
||||
}
|
||||
case ELF::R_MIPS_GOT_OFST: {
|
||||
int64_t page = (Value + Addend + 0x8000) & ~0xffff;
|
||||
return (Value + Addend - page) & 0xffff;
|
||||
}
|
||||
case ELF::R_MIPS_GPREL32: {
|
||||
uint64_t GOTAddr = getSectionLoadAddress(SectionToGOTMap[SectionID]);
|
||||
return Value + Addend - (GOTAddr + 0x7ff0);
|
||||
}
|
||||
case ELF::R_MIPS_PC16: {
|
||||
uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
|
||||
return ((Value + Addend - FinalAddress) >> 2) & 0xffff;
|
||||
}
|
||||
case ELF::R_MIPS_PC32: {
|
||||
uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
|
||||
return Value + Addend - FinalAddress;
|
||||
}
|
||||
case ELF::R_MIPS_PC18_S3: {
|
||||
uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
|
||||
return ((Value + Addend - (FinalAddress & ~0x7)) >> 3) & 0x3ffff;
|
||||
}
|
||||
case ELF::R_MIPS_PC19_S2: {
|
||||
uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
|
||||
return ((Value + Addend - (FinalAddress & ~0x3)) >> 2) & 0x7ffff;
|
||||
}
|
||||
case ELF::R_MIPS_PC21_S2: {
|
||||
uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
|
||||
return ((Value + Addend - FinalAddress) >> 2) & 0x1fffff;
|
||||
}
|
||||
case ELF::R_MIPS_PC26_S2: {
|
||||
uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
|
||||
return ((Value + Addend - FinalAddress) >> 2) & 0x3ffffff;
|
||||
}
|
||||
case ELF::R_MIPS_PCHI16: {
|
||||
uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
|
||||
return ((Value + Addend - FinalAddress + 0x8000) >> 16) & 0xffff;
|
||||
}
|
||||
case ELF::R_MIPS_PCLO16: {
|
||||
uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
|
||||
return (Value + Addend - FinalAddress) & 0xffff;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RuntimeDyldELFMips::applyMIPSRelocation(uint8_t *TargetPtr, int64_t Value,
|
||||
uint32_t Type) {
|
||||
uint32_t Insn = readBytesUnaligned(TargetPtr, 4);
|
||||
|
||||
switch (Type) {
|
||||
default:
|
||||
llvm_unreachable("Unknown relocation type!");
|
||||
break;
|
||||
case ELF::R_MIPS_GPREL16:
|
||||
case ELF::R_MIPS_HI16:
|
||||
case ELF::R_MIPS_LO16:
|
||||
case ELF::R_MIPS_HIGHER:
|
||||
case ELF::R_MIPS_HIGHEST:
|
||||
case ELF::R_MIPS_PC16:
|
||||
case ELF::R_MIPS_PCHI16:
|
||||
case ELF::R_MIPS_PCLO16:
|
||||
case ELF::R_MIPS_CALL16:
|
||||
case ELF::R_MIPS_GOT_DISP:
|
||||
case ELF::R_MIPS_GOT_PAGE:
|
||||
case ELF::R_MIPS_GOT_OFST:
|
||||
Insn = (Insn & 0xffff0000) | (Value & 0x0000ffff);
|
||||
writeBytesUnaligned(Insn, TargetPtr, 4);
|
||||
break;
|
||||
case ELF::R_MIPS_PC18_S3:
|
||||
Insn = (Insn & 0xfffc0000) | (Value & 0x0003ffff);
|
||||
writeBytesUnaligned(Insn, TargetPtr, 4);
|
||||
break;
|
||||
case ELF::R_MIPS_PC19_S2:
|
||||
Insn = (Insn & 0xfff80000) | (Value & 0x0007ffff);
|
||||
writeBytesUnaligned(Insn, TargetPtr, 4);
|
||||
break;
|
||||
case ELF::R_MIPS_PC21_S2:
|
||||
Insn = (Insn & 0xffe00000) | (Value & 0x001fffff);
|
||||
writeBytesUnaligned(Insn, TargetPtr, 4);
|
||||
break;
|
||||
case ELF::R_MIPS_26:
|
||||
case ELF::R_MIPS_PC26_S2:
|
||||
Insn = (Insn & 0xfc000000) | (Value & 0x03ffffff);
|
||||
writeBytesUnaligned(Insn, TargetPtr, 4);
|
||||
break;
|
||||
case ELF::R_MIPS_32:
|
||||
case ELF::R_MIPS_GPREL32:
|
||||
case ELF::R_MIPS_PC32:
|
||||
writeBytesUnaligned(Value & 0xffffffff, TargetPtr, 4);
|
||||
break;
|
||||
case ELF::R_MIPS_64:
|
||||
case ELF::R_MIPS_SUB:
|
||||
writeBytesUnaligned(Value, TargetPtr, 8);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RuntimeDyldELFMips::resolveMIPSN32Relocation(
|
||||
const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type,
|
||||
int64_t Addend, uint64_t SymOffset, SID SectionID) {
|
||||
int64_t CalculatedValue = evaluateMIPS64Relocation(
|
||||
Section, Offset, Value, Type, Addend, SymOffset, SectionID);
|
||||
applyMIPSRelocation(Section.getAddressWithOffset(Offset), CalculatedValue,
|
||||
Type);
|
||||
}
|
||||
|
||||
void RuntimeDyldELFMips::resolveMIPSN64Relocation(
|
||||
const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type,
|
||||
int64_t Addend, uint64_t SymOffset, SID SectionID) {
|
||||
uint32_t r_type = Type & 0xff;
|
||||
uint32_t r_type2 = (Type >> 8) & 0xff;
|
||||
uint32_t r_type3 = (Type >> 16) & 0xff;
|
||||
|
||||
// RelType is used to keep information for which relocation type we are
|
||||
// applying relocation.
|
||||
uint32_t RelType = r_type;
|
||||
int64_t CalculatedValue = evaluateMIPS64Relocation(Section, Offset, Value,
|
||||
RelType, Addend,
|
||||
SymOffset, SectionID);
|
||||
if (r_type2 != ELF::R_MIPS_NONE) {
|
||||
RelType = r_type2;
|
||||
CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType,
|
||||
CalculatedValue, SymOffset,
|
||||
SectionID);
|
||||
}
|
||||
if (r_type3 != ELF::R_MIPS_NONE) {
|
||||
RelType = r_type3;
|
||||
CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType,
|
||||
CalculatedValue, SymOffset,
|
||||
SectionID);
|
||||
}
|
||||
applyMIPSRelocation(Section.getAddressWithOffset(Offset), CalculatedValue,
|
||||
RelType);
|
||||
}
|
||||
|
||||
void RuntimeDyldELFMips::resolveMIPSO32Relocation(const SectionEntry &Section,
|
||||
uint64_t Offset,
|
||||
uint32_t Value, uint32_t Type,
|
||||
int32_t Addend) {
|
||||
uint8_t *TargetPtr = Section.getAddressWithOffset(Offset);
|
||||
Value += Addend;
|
||||
|
||||
DEBUG(dbgs() << "resolveMIPSO32Relocation, LocalAddress: "
|
||||
<< Section.getAddressWithOffset(Offset) << " FinalAddress: "
|
||||
<< format("%p", Section.getLoadAddressWithOffset(Offset))
|
||||
<< " Value: " << format("%x", Value)
|
||||
<< " Type: " << format("%x", Type)
|
||||
<< " Addend: " << format("%x", Addend)
|
||||
<< " SymOffset: " << format("%x", Offset) << "\n");
|
||||
|
||||
Value = evaluateMIPS32Relocation(Section, Offset, Value, Type);
|
||||
|
||||
applyMIPSRelocation(TargetPtr, Value, Type);
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
//===-- RuntimeDyldELFMips.h ---- ELF/Mips specific code. -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDELFMIPS_H
|
||||
#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDELFMIPS_H
|
||||
|
||||
#include "../RuntimeDyldELF.h"
|
||||
#include <string>
|
||||
|
||||
#define DEBUG_TYPE "dyld"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class RuntimeDyldELFMips : public RuntimeDyldELF {
|
||||
public:
|
||||
|
||||
typedef uint64_t TargetPtrT;
|
||||
|
||||
RuntimeDyldELFMips(RuntimeDyld::MemoryManager &MM,
|
||||
JITSymbolResolver &Resolver)
|
||||
: RuntimeDyldELF(MM, Resolver) {}
|
||||
|
||||
void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override;
|
||||
|
||||
protected:
|
||||
void resolveMIPSO32Relocation(const SectionEntry &Section, uint64_t Offset,
|
||||
uint32_t Value, uint32_t Type, int32_t Addend);
|
||||
void resolveMIPSN32Relocation(const SectionEntry &Section, uint64_t Offset,
|
||||
uint64_t Value, uint32_t Type, int64_t Addend,
|
||||
uint64_t SymOffset, SID SectionID);
|
||||
void resolveMIPSN64Relocation(const SectionEntry &Section, uint64_t Offset,
|
||||
uint64_t Value, uint32_t Type, int64_t Addend,
|
||||
uint64_t SymOffset, SID SectionID);
|
||||
|
||||
private:
|
||||
/// \brief A object file specific relocation resolver
|
||||
/// \param RE The relocation to be resolved
|
||||
/// \param Value Target symbol address to apply the relocation action
|
||||
uint64_t evaluateRelocation(const RelocationEntry &RE, uint64_t Value,
|
||||
uint64_t Addend);
|
||||
|
||||
/// \brief A object file specific relocation resolver
|
||||
/// \param RE The relocation to be resolved
|
||||
/// \param Value Target symbol address to apply the relocation action
|
||||
void applyRelocation(const RelocationEntry &RE, uint64_t Value);
|
||||
|
||||
int64_t evaluateMIPS32Relocation(const SectionEntry &Section, uint64_t Offset,
|
||||
uint64_t Value, uint32_t Type);
|
||||
int64_t evaluateMIPS64Relocation(const SectionEntry &Section,
|
||||
uint64_t Offset, uint64_t Value,
|
||||
uint32_t Type, int64_t Addend,
|
||||
uint64_t SymOffset, SID SectionID);
|
||||
|
||||
void applyMIPSRelocation(uint8_t *TargetPtr, int64_t CalculatedValue,
|
||||
uint32_t Type);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#undef DEBUG_TYPE
|
||||
|
||||
#endif
|
@ -1,467 +0,0 @@
|
||||
//===-- RuntimeDyldMachOAArch64.h -- MachO/AArch64 specific code. -*- C++ -*-=//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOAARCH64_H
|
||||
#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOAARCH64_H
|
||||
|
||||
#include "../RuntimeDyldMachO.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
||||
#define DEBUG_TYPE "dyld"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class RuntimeDyldMachOAArch64
|
||||
: public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOAArch64> {
|
||||
public:
|
||||
|
||||
typedef uint64_t TargetPtrT;
|
||||
|
||||
RuntimeDyldMachOAArch64(RuntimeDyld::MemoryManager &MM,
|
||||
JITSymbolResolver &Resolver)
|
||||
: RuntimeDyldMachOCRTPBase(MM, Resolver) {}
|
||||
|
||||
unsigned getMaxStubSize() override { return 8; }
|
||||
|
||||
unsigned getStubAlignment() override { return 8; }
|
||||
|
||||
/// Extract the addend encoded in the instruction / memory location.
|
||||
int64_t decodeAddend(const RelocationEntry &RE) const {
|
||||
const SectionEntry &Section = Sections[RE.SectionID];
|
||||
uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset);
|
||||
unsigned NumBytes = 1 << RE.Size;
|
||||
int64_t Addend = 0;
|
||||
// Verify that the relocation has the correct size and alignment.
|
||||
switch (RE.RelType) {
|
||||
default:
|
||||
llvm_unreachable("Unsupported relocation type!");
|
||||
case MachO::ARM64_RELOC_UNSIGNED:
|
||||
assert((NumBytes == 4 || NumBytes == 8) && "Invalid relocation size.");
|
||||
break;
|
||||
case MachO::ARM64_RELOC_BRANCH26:
|
||||
case MachO::ARM64_RELOC_PAGE21:
|
||||
case MachO::ARM64_RELOC_PAGEOFF12:
|
||||
case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
|
||||
case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
|
||||
assert(NumBytes == 4 && "Invalid relocation size.");
|
||||
assert((((uintptr_t)LocalAddress & 0x3) == 0) &&
|
||||
"Instruction address is not aligned to 4 bytes.");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (RE.RelType) {
|
||||
default:
|
||||
llvm_unreachable("Unsupported relocation type!");
|
||||
case MachO::ARM64_RELOC_UNSIGNED:
|
||||
// This could be an unaligned memory location.
|
||||
if (NumBytes == 4)
|
||||
Addend = *reinterpret_cast<support::ulittle32_t *>(LocalAddress);
|
||||
else
|
||||
Addend = *reinterpret_cast<support::ulittle64_t *>(LocalAddress);
|
||||
break;
|
||||
case MachO::ARM64_RELOC_BRANCH26: {
|
||||
// Verify that the relocation points to the expected branch instruction.
|
||||
auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
|
||||
assert((*p & 0xFC000000) == 0x14000000 && "Expected branch instruction.");
|
||||
|
||||
// Get the 26 bit addend encoded in the branch instruction and sign-extend
|
||||
// to 64 bit. The lower 2 bits are always zeros and are therefore implicit
|
||||
// (<< 2).
|
||||
Addend = (*p & 0x03FFFFFF) << 2;
|
||||
Addend = SignExtend64(Addend, 28);
|
||||
break;
|
||||
}
|
||||
case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
|
||||
case MachO::ARM64_RELOC_PAGE21: {
|
||||
// Verify that the relocation points to the expected adrp instruction.
|
||||
auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
|
||||
assert((*p & 0x9F000000) == 0x90000000 && "Expected adrp instruction.");
|
||||
|
||||
// Get the 21 bit addend encoded in the adrp instruction and sign-extend
|
||||
// to 64 bit. The lower 12 bits (4096 byte page) are always zeros and are
|
||||
// therefore implicit (<< 12).
|
||||
Addend = ((*p & 0x60000000) >> 29) | ((*p & 0x01FFFFE0) >> 3) << 12;
|
||||
Addend = SignExtend64(Addend, 33);
|
||||
break;
|
||||
}
|
||||
case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: {
|
||||
// Verify that the relocation points to one of the expected load / store
|
||||
// instructions.
|
||||
auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
|
||||
(void)p;
|
||||
assert((*p & 0x3B000000) == 0x39000000 &&
|
||||
"Only expected load / store instructions.");
|
||||
LLVM_FALLTHROUGH;
|
||||
}
|
||||
case MachO::ARM64_RELOC_PAGEOFF12: {
|
||||
// Verify that the relocation points to one of the expected load / store
|
||||
// or add / sub instructions.
|
||||
auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
|
||||
assert((((*p & 0x3B000000) == 0x39000000) ||
|
||||
((*p & 0x11C00000) == 0x11000000) ) &&
|
||||
"Expected load / store or add/sub instruction.");
|
||||
|
||||
// Get the 12 bit addend encoded in the instruction.
|
||||
Addend = (*p & 0x003FFC00) >> 10;
|
||||
|
||||
// Check which instruction we are decoding to obtain the implicit shift
|
||||
// factor of the instruction.
|
||||
int ImplicitShift = 0;
|
||||
if ((*p & 0x3B000000) == 0x39000000) { // << load / store
|
||||
// For load / store instructions the size is encoded in bits 31:30.
|
||||
ImplicitShift = ((*p >> 30) & 0x3);
|
||||
if (ImplicitShift == 0) {
|
||||
// Check if this a vector op to get the correct shift value.
|
||||
if ((*p & 0x04800000) == 0x04800000)
|
||||
ImplicitShift = 4;
|
||||
}
|
||||
}
|
||||
// Compensate for implicit shift.
|
||||
Addend <<= ImplicitShift;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Addend;
|
||||
}
|
||||
|
||||
/// Extract the addend encoded in the instruction.
|
||||
void encodeAddend(uint8_t *LocalAddress, unsigned NumBytes,
|
||||
MachO::RelocationInfoType RelType, int64_t Addend) const {
|
||||
// Verify that the relocation has the correct alignment.
|
||||
switch (RelType) {
|
||||
default:
|
||||
llvm_unreachable("Unsupported relocation type!");
|
||||
case MachO::ARM64_RELOC_UNSIGNED:
|
||||
assert((NumBytes == 4 || NumBytes == 8) && "Invalid relocation size.");
|
||||
break;
|
||||
case MachO::ARM64_RELOC_BRANCH26:
|
||||
case MachO::ARM64_RELOC_PAGE21:
|
||||
case MachO::ARM64_RELOC_PAGEOFF12:
|
||||
case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
|
||||
case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
|
||||
assert(NumBytes == 4 && "Invalid relocation size.");
|
||||
assert((((uintptr_t)LocalAddress & 0x3) == 0) &&
|
||||
"Instruction address is not aligned to 4 bytes.");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (RelType) {
|
||||
default:
|
||||
llvm_unreachable("Unsupported relocation type!");
|
||||
case MachO::ARM64_RELOC_UNSIGNED:
|
||||
// This could be an unaligned memory location.
|
||||
if (NumBytes == 4)
|
||||
*reinterpret_cast<support::ulittle32_t *>(LocalAddress) = Addend;
|
||||
else
|
||||
*reinterpret_cast<support::ulittle64_t *>(LocalAddress) = Addend;
|
||||
break;
|
||||
case MachO::ARM64_RELOC_BRANCH26: {
|
||||
auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
|
||||
// Verify that the relocation points to the expected branch instruction.
|
||||
assert((*p & 0xFC000000) == 0x14000000 && "Expected branch instruction.");
|
||||
|
||||
// Verify addend value.
|
||||
assert((Addend & 0x3) == 0 && "Branch target is not aligned");
|
||||
assert(isInt<28>(Addend) && "Branch target is out of range.");
|
||||
|
||||
// Encode the addend as 26 bit immediate in the branch instruction.
|
||||
*p = (*p & 0xFC000000) | ((uint32_t)(Addend >> 2) & 0x03FFFFFF);
|
||||
break;
|
||||
}
|
||||
case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
|
||||
case MachO::ARM64_RELOC_PAGE21: {
|
||||
// Verify that the relocation points to the expected adrp instruction.
|
||||
auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
|
||||
assert((*p & 0x9F000000) == 0x90000000 && "Expected adrp instruction.");
|
||||
|
||||
// Check that the addend fits into 21 bits (+ 12 lower bits).
|
||||
assert((Addend & 0xFFF) == 0 && "ADRP target is not page aligned.");
|
||||
assert(isInt<33>(Addend) && "Invalid page reloc value.");
|
||||
|
||||
// Encode the addend into the instruction.
|
||||
uint32_t ImmLoValue = ((uint64_t)Addend << 17) & 0x60000000;
|
||||
uint32_t ImmHiValue = ((uint64_t)Addend >> 9) & 0x00FFFFE0;
|
||||
*p = (*p & 0x9F00001F) | ImmHiValue | ImmLoValue;
|
||||
break;
|
||||
}
|
||||
case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: {
|
||||
// Verify that the relocation points to one of the expected load / store
|
||||
// instructions.
|
||||
auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
|
||||
assert((*p & 0x3B000000) == 0x39000000 &&
|
||||
"Only expected load / store instructions.");
|
||||
(void)p;
|
||||
LLVM_FALLTHROUGH;
|
||||
}
|
||||
case MachO::ARM64_RELOC_PAGEOFF12: {
|
||||
// Verify that the relocation points to one of the expected load / store
|
||||
// or add / sub instructions.
|
||||
auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
|
||||
assert((((*p & 0x3B000000) == 0x39000000) ||
|
||||
((*p & 0x11C00000) == 0x11000000) ) &&
|
||||
"Expected load / store or add/sub instruction.");
|
||||
|
||||
// Check which instruction we are decoding to obtain the implicit shift
|
||||
// factor of the instruction and verify alignment.
|
||||
int ImplicitShift = 0;
|
||||
if ((*p & 0x3B000000) == 0x39000000) { // << load / store
|
||||
// For load / store instructions the size is encoded in bits 31:30.
|
||||
ImplicitShift = ((*p >> 30) & 0x3);
|
||||
switch (ImplicitShift) {
|
||||
case 0:
|
||||
// Check if this a vector op to get the correct shift value.
|
||||
if ((*p & 0x04800000) == 0x04800000) {
|
||||
ImplicitShift = 4;
|
||||
assert(((Addend & 0xF) == 0) &&
|
||||
"128-bit LDR/STR not 16-byte aligned.");
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
assert(((Addend & 0x1) == 0) && "16-bit LDR/STR not 2-byte aligned.");
|
||||
break;
|
||||
case 2:
|
||||
assert(((Addend & 0x3) == 0) && "32-bit LDR/STR not 4-byte aligned.");
|
||||
break;
|
||||
case 3:
|
||||
assert(((Addend & 0x7) == 0) && "64-bit LDR/STR not 8-byte aligned.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Compensate for implicit shift.
|
||||
Addend >>= ImplicitShift;
|
||||
assert(isUInt<12>(Addend) && "Addend cannot be encoded.");
|
||||
|
||||
// Encode the addend into the instruction.
|
||||
*p = (*p & 0xFFC003FF) | ((uint32_t)(Addend << 10) & 0x003FFC00);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Expected<relocation_iterator>
|
||||
processRelocationRef(unsigned SectionID, relocation_iterator RelI,
|
||||
const ObjectFile &BaseObjT,
|
||||
ObjSectionToIDMap &ObjSectionToID,
|
||||
StubMap &Stubs) override {
|
||||
const MachOObjectFile &Obj =
|
||||
static_cast<const MachOObjectFile &>(BaseObjT);
|
||||
MachO::any_relocation_info RelInfo =
|
||||
Obj.getRelocation(RelI->getRawDataRefImpl());
|
||||
|
||||
if (Obj.isRelocationScattered(RelInfo))
|
||||
return make_error<RuntimeDyldError>("Scattered relocations not supported "
|
||||
"for MachO AArch64");
|
||||
|
||||
// ARM64 has an ARM64_RELOC_ADDEND relocation type that carries an explicit
|
||||
// addend for the following relocation. If found: (1) store the associated
|
||||
// addend, (2) consume the next relocation, and (3) use the stored addend to
|
||||
// override the addend.
|
||||
int64_t ExplicitAddend = 0;
|
||||
if (Obj.getAnyRelocationType(RelInfo) == MachO::ARM64_RELOC_ADDEND) {
|
||||
assert(!Obj.getPlainRelocationExternal(RelInfo));
|
||||
assert(!Obj.getAnyRelocationPCRel(RelInfo));
|
||||
assert(Obj.getAnyRelocationLength(RelInfo) == 2);
|
||||
int64_t RawAddend = Obj.getPlainRelocationSymbolNum(RelInfo);
|
||||
// Sign-extend the 24-bit to 64-bit.
|
||||
ExplicitAddend = SignExtend64(RawAddend, 24);
|
||||
++RelI;
|
||||
RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl());
|
||||
}
|
||||
|
||||
if (Obj.getAnyRelocationType(RelInfo) == MachO::ARM64_RELOC_SUBTRACTOR)
|
||||
return processSubtractRelocation(SectionID, RelI, Obj, ObjSectionToID);
|
||||
|
||||
RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI));
|
||||
RE.Addend = decodeAddend(RE);
|
||||
|
||||
assert((ExplicitAddend == 0 || RE.Addend == 0) && "Relocation has "\
|
||||
"ARM64_RELOC_ADDEND and embedded addend in the instruction.");
|
||||
if (ExplicitAddend)
|
||||
RE.Addend = ExplicitAddend;
|
||||
|
||||
RelocationValueRef Value;
|
||||
if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID))
|
||||
Value = *ValueOrErr;
|
||||
else
|
||||
return ValueOrErr.takeError();
|
||||
|
||||
bool IsExtern = Obj.getPlainRelocationExternal(RelInfo);
|
||||
if (!IsExtern && RE.IsPCRel)
|
||||
makeValueAddendPCRel(Value, RelI, 1 << RE.Size);
|
||||
|
||||
RE.Addend = Value.Offset;
|
||||
|
||||
if (RE.RelType == MachO::ARM64_RELOC_GOT_LOAD_PAGE21 ||
|
||||
RE.RelType == MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12)
|
||||
processGOTRelocation(RE, Value, Stubs);
|
||||
else {
|
||||
if (Value.SymbolName)
|
||||
addRelocationForSymbol(RE, Value.SymbolName);
|
||||
else
|
||||
addRelocationForSection(RE, Value.SectionID);
|
||||
}
|
||||
|
||||
return ++RelI;
|
||||
}
|
||||
|
||||
void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
|
||||
DEBUG(dumpRelocationToResolve(RE, Value));
|
||||
|
||||
const SectionEntry &Section = Sections[RE.SectionID];
|
||||
uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset);
|
||||
MachO::RelocationInfoType RelType =
|
||||
static_cast<MachO::RelocationInfoType>(RE.RelType);
|
||||
|
||||
switch (RelType) {
|
||||
default:
|
||||
llvm_unreachable("Invalid relocation type!");
|
||||
case MachO::ARM64_RELOC_UNSIGNED: {
|
||||
assert(!RE.IsPCRel && "PCRel and ARM64_RELOC_UNSIGNED not supported");
|
||||
// Mask in the target value a byte at a time (we don't have an alignment
|
||||
// guarantee for the target address, so this is safest).
|
||||
if (RE.Size < 2)
|
||||
llvm_unreachable("Invalid size for ARM64_RELOC_UNSIGNED");
|
||||
|
||||
encodeAddend(LocalAddress, 1 << RE.Size, RelType, Value + RE.Addend);
|
||||
break;
|
||||
}
|
||||
case MachO::ARM64_RELOC_BRANCH26: {
|
||||
assert(RE.IsPCRel && "not PCRel and ARM64_RELOC_BRANCH26 not supported");
|
||||
// Check if branch is in range.
|
||||
uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset);
|
||||
int64_t PCRelVal = Value - FinalAddress + RE.Addend;
|
||||
encodeAddend(LocalAddress, /*Size=*/4, RelType, PCRelVal);
|
||||
break;
|
||||
}
|
||||
case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
|
||||
case MachO::ARM64_RELOC_PAGE21: {
|
||||
assert(RE.IsPCRel && "not PCRel and ARM64_RELOC_PAGE21 not supported");
|
||||
// Adjust for PC-relative relocation and offset.
|
||||
uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset);
|
||||
int64_t PCRelVal =
|
||||
((Value + RE.Addend) & (-4096)) - (FinalAddress & (-4096));
|
||||
encodeAddend(LocalAddress, /*Size=*/4, RelType, PCRelVal);
|
||||
break;
|
||||
}
|
||||
case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
|
||||
case MachO::ARM64_RELOC_PAGEOFF12: {
|
||||
assert(!RE.IsPCRel && "PCRel and ARM64_RELOC_PAGEOFF21 not supported");
|
||||
// Add the offset from the symbol.
|
||||
Value += RE.Addend;
|
||||
// Mask out the page address and only use the lower 12 bits.
|
||||
Value &= 0xFFF;
|
||||
encodeAddend(LocalAddress, /*Size=*/4, RelType, Value);
|
||||
break;
|
||||
}
|
||||
case MachO::ARM64_RELOC_SUBTRACTOR: {
|
||||
uint64_t SectionABase = Sections[RE.Sections.SectionA].getLoadAddress();
|
||||
uint64_t SectionBBase = Sections[RE.Sections.SectionB].getLoadAddress();
|
||||
assert((Value == SectionABase || Value == SectionBBase) &&
|
||||
"Unexpected SUBTRACTOR relocation value.");
|
||||
Value = SectionABase - SectionBBase + RE.Addend;
|
||||
writeBytesUnaligned(Value, LocalAddress, 1 << RE.Size);
|
||||
break;
|
||||
}
|
||||
case MachO::ARM64_RELOC_POINTER_TO_GOT:
|
||||
case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21:
|
||||
case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
|
||||
llvm_unreachable("Relocation type not yet implemented!");
|
||||
case MachO::ARM64_RELOC_ADDEND:
|
||||
llvm_unreachable("ARM64_RELOC_ADDEND should have been handeled by "
|
||||
"processRelocationRef!");
|
||||
}
|
||||
}
|
||||
|
||||
Error finalizeSection(const ObjectFile &Obj, unsigned SectionID,
|
||||
const SectionRef &Section) {
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
private:
|
||||
void processGOTRelocation(const RelocationEntry &RE,
|
||||
RelocationValueRef &Value, StubMap &Stubs) {
|
||||
assert(RE.Size == 2);
|
||||
SectionEntry &Section = Sections[RE.SectionID];
|
||||
StubMap::const_iterator i = Stubs.find(Value);
|
||||
int64_t Offset;
|
||||
if (i != Stubs.end())
|
||||
Offset = static_cast<int64_t>(i->second);
|
||||
else {
|
||||
// FIXME: There must be a better way to do this then to check and fix the
|
||||
// alignment every time!!!
|
||||
uintptr_t BaseAddress = uintptr_t(Section.getAddress());
|
||||
uintptr_t StubAlignment = getStubAlignment();
|
||||
uintptr_t StubAddress =
|
||||
(BaseAddress + Section.getStubOffset() + StubAlignment - 1) &
|
||||
-StubAlignment;
|
||||
unsigned StubOffset = StubAddress - BaseAddress;
|
||||
Stubs[Value] = StubOffset;
|
||||
assert(((StubAddress % getStubAlignment()) == 0) &&
|
||||
"GOT entry not aligned");
|
||||
RelocationEntry GOTRE(RE.SectionID, StubOffset,
|
||||
MachO::ARM64_RELOC_UNSIGNED, Value.Offset,
|
||||
/*IsPCRel=*/false, /*Size=*/3);
|
||||
if (Value.SymbolName)
|
||||
addRelocationForSymbol(GOTRE, Value.SymbolName);
|
||||
else
|
||||
addRelocationForSection(GOTRE, Value.SectionID);
|
||||
Section.advanceStubOffset(getMaxStubSize());
|
||||
Offset = static_cast<int64_t>(StubOffset);
|
||||
}
|
||||
RelocationEntry TargetRE(RE.SectionID, RE.Offset, RE.RelType, Offset,
|
||||
RE.IsPCRel, RE.Size);
|
||||
addRelocationForSection(TargetRE, RE.SectionID);
|
||||
}
|
||||
|
||||
Expected<relocation_iterator>
|
||||
processSubtractRelocation(unsigned SectionID, relocation_iterator RelI,
|
||||
const ObjectFile &BaseObjT,
|
||||
ObjSectionToIDMap &ObjSectionToID) {
|
||||
const MachOObjectFile &Obj =
|
||||
static_cast<const MachOObjectFile&>(BaseObjT);
|
||||
MachO::any_relocation_info RE =
|
||||
Obj.getRelocation(RelI->getRawDataRefImpl());
|
||||
|
||||
unsigned Size = Obj.getAnyRelocationLength(RE);
|
||||
uint64_t Offset = RelI->getOffset();
|
||||
uint8_t *LocalAddress = Sections[SectionID].getAddressWithOffset(Offset);
|
||||
unsigned NumBytes = 1 << Size;
|
||||
|
||||
Expected<StringRef> SubtrahendNameOrErr = RelI->getSymbol()->getName();
|
||||
if (!SubtrahendNameOrErr)
|
||||
return SubtrahendNameOrErr.takeError();
|
||||
auto SubtrahendI = GlobalSymbolTable.find(*SubtrahendNameOrErr);
|
||||
unsigned SectionBID = SubtrahendI->second.getSectionID();
|
||||
uint64_t SectionBOffset = SubtrahendI->second.getOffset();
|
||||
int64_t Addend =
|
||||
SignExtend64(readBytesUnaligned(LocalAddress, NumBytes), NumBytes * 8);
|
||||
|
||||
++RelI;
|
||||
Expected<StringRef> MinuendNameOrErr = RelI->getSymbol()->getName();
|
||||
if (!MinuendNameOrErr)
|
||||
return MinuendNameOrErr.takeError();
|
||||
auto MinuendI = GlobalSymbolTable.find(*MinuendNameOrErr);
|
||||
unsigned SectionAID = MinuendI->second.getSectionID();
|
||||
uint64_t SectionAOffset = MinuendI->second.getOffset();
|
||||
|
||||
RelocationEntry R(SectionID, Offset, MachO::ARM64_RELOC_SUBTRACTOR, (uint64_t)Addend,
|
||||
SectionAID, SectionAOffset, SectionBID, SectionBOffset,
|
||||
false, Size);
|
||||
|
||||
addRelocationForSection(R, SectionAID);
|
||||
|
||||
return ++RelI;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#undef DEBUG_TYPE
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user