mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-20 14:29:27 +00:00
ExecutionEngine: Preliminary support for dynamically loadable coff objects
Provide basic support for dynamically loadable coff objects. Only handles a subset of x64 currently. Patch by Andy Ayers! Differential Revision: http://reviews.llvm.org/D7793 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@231574 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ed0266d8ee
commit
2c08439cf9
@ -2,6 +2,8 @@ add_llvm_library(LLVMRuntimeDyld
|
||||
RTDyldMemoryManager.cpp
|
||||
RuntimeDyld.cpp
|
||||
RuntimeDyldChecker.cpp
|
||||
RuntimeDyldCOFF.cpp
|
||||
RuntimeDyldELF.cpp
|
||||
RuntimeDyldMachO.cpp
|
||||
Targets/RuntimeDyldCOFFX86_64.cpp
|
||||
)
|
||||
|
@ -13,10 +13,12 @@
|
||||
|
||||
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
||||
#include "RuntimeDyldCheckerImpl.h"
|
||||
#include "RuntimeDyldCOFF.h"
|
||||
#include "RuntimeDyldELF.h"
|
||||
#include "RuntimeDyldImpl.h"
|
||||
#include "RuntimeDyldMachO.h"
|
||||
#include "llvm/Object/ELFObjectFile.h"
|
||||
#include "llvm/Object/COFF.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/MutexGuard.h"
|
||||
|
||||
@ -264,6 +266,20 @@ static bool isRequiredForExecution(const SectionRef &Section) {
|
||||
const ObjectFile *Obj = Section.getObject();
|
||||
if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj))
|
||||
return ELFObj->getSectionFlags(Section) & ELF::SHF_ALLOC;
|
||||
if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj)) {
|
||||
const coff_section *CoffSection = COFFObj->getCOFFSection(Section);
|
||||
// Avoid loading zero-sized COFF sections.
|
||||
// In PE files, VirtualSize gives the section size, and SizeOfRawData
|
||||
// may be zero for sections with content. In Obj files, SizeOfRawData
|
||||
// gives the section size, and VirtualSize is always zero. Hence
|
||||
// the need to check for both cases below.
|
||||
bool HasContent = (CoffSection->VirtualSize > 0)
|
||||
|| (CoffSection->SizeOfRawData > 0);
|
||||
bool IsDiscardable = CoffSection->Characteristics &
|
||||
(COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_LNK_INFO);
|
||||
return HasContent && !IsDiscardable;
|
||||
}
|
||||
|
||||
assert(isa<MachOObjectFile>(Obj));
|
||||
return true;
|
||||
}
|
||||
@ -273,6 +289,15 @@ static bool isReadOnlyData(const SectionRef &Section) {
|
||||
if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj))
|
||||
return !(ELFObj->getSectionFlags(Section) &
|
||||
(ELF::SHF_WRITE | ELF::SHF_EXECINSTR));
|
||||
if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj))
|
||||
return ((COFFObj->getCOFFSection(Section)->Characteristics &
|
||||
(COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
|
||||
| COFF::IMAGE_SCN_MEM_READ
|
||||
| COFF::IMAGE_SCN_MEM_WRITE))
|
||||
==
|
||||
(COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
|
||||
| COFF::IMAGE_SCN_MEM_READ));
|
||||
|
||||
assert(isa<MachOObjectFile>(Obj));
|
||||
return false;
|
||||
}
|
||||
@ -281,6 +306,9 @@ static bool isZeroInit(const SectionRef &Section) {
|
||||
const ObjectFile *Obj = Section.getObject();
|
||||
if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj))
|
||||
return ELFObj->getSectionType(Section) == ELF::SHT_NOBITS;
|
||||
if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj))
|
||||
return COFFObj->getCOFFSection(Section)->Characteristics &
|
||||
COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
|
||||
|
||||
auto *MachO = cast<MachOObjectFile>(Obj);
|
||||
unsigned SectionType = MachO->getSectionType(Section);
|
||||
@ -512,7 +540,6 @@ unsigned RuntimeDyldImpl::emitSection(const ObjectFile &Obj,
|
||||
const SectionRef &Section, bool IsCode) {
|
||||
|
||||
StringRef data;
|
||||
Check(Section.getContents(data));
|
||||
uint64_t Alignment64 = Section.getAlignment();
|
||||
|
||||
unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL;
|
||||
@ -542,6 +569,7 @@ unsigned RuntimeDyldImpl::emitSection(const ObjectFile &Obj,
|
||||
// Some sections, such as debug info, don't need to be loaded for execution.
|
||||
// Leave those where they are.
|
||||
if (IsRequired) {
|
||||
Check(Section.getContents(data));
|
||||
Allocate = DataSize + PaddingSize + StubBufSize;
|
||||
Addr = IsCode ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID,
|
||||
Name)
|
||||
@ -816,6 +844,15 @@ RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) {
|
||||
|
||||
RuntimeDyld::~RuntimeDyld() {}
|
||||
|
||||
static std::unique_ptr<RuntimeDyldCOFF>
|
||||
createRuntimeDyldCOFF(Triple::ArchType Arch, RTDyldMemoryManager *MM,
|
||||
bool ProcessAllSections, RuntimeDyldCheckerImpl *Checker) {
|
||||
std::unique_ptr<RuntimeDyldCOFF> Dyld(RuntimeDyldCOFF::create(Arch, MM));
|
||||
Dyld->setProcessAllSections(ProcessAllSections);
|
||||
Dyld->setRuntimeDyldChecker(Checker);
|
||||
return Dyld;
|
||||
}
|
||||
|
||||
static std::unique_ptr<RuntimeDyldELF>
|
||||
createRuntimeDyldELF(RTDyldMemoryManager *MM, bool ProcessAllSections,
|
||||
RuntimeDyldCheckerImpl *Checker) {
|
||||
@ -843,6 +880,10 @@ RuntimeDyld::loadObject(const ObjectFile &Obj) {
|
||||
Dyld = createRuntimeDyldMachO(
|
||||
static_cast<Triple::ArchType>(Obj.getArch()), MM,
|
||||
ProcessAllSections, Checker);
|
||||
else if (Obj.isCOFF())
|
||||
Dyld = createRuntimeDyldCOFF(
|
||||
static_cast<Triple::ArchType>(Obj.getArch()), MM,
|
||||
ProcessAllSections, Checker);
|
||||
else
|
||||
report_fatal_error("Incompatible object format!");
|
||||
}
|
||||
|
85
lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp
Normal file
85
lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
//===-- 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/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 : public RuntimeDyld::LoadedObjectInfo {
|
||||
public:
|
||||
LoadedCOFFObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx,
|
||||
unsigned EndIdx)
|
||||
: RuntimeDyld::LoadedObjectInfo(RTDyld, BeginIdx, EndIdx) {}
|
||||
|
||||
OwningBinary<ObjectFile>
|
||||
getObjectForDebug(const ObjectFile &Obj) const override {
|
||||
return OwningBinary<ObjectFile>();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
|
||||
std::unique_ptr<RuntimeDyldCOFF>
|
||||
llvm::RuntimeDyldCOFF::create(Triple::ArchType Arch, RTDyldMemoryManager *MM) {
|
||||
switch (Arch) {
|
||||
default:
|
||||
llvm_unreachable("Unsupported target for RuntimeDyldCOFF.");
|
||||
break;
|
||||
case Triple::x86_64:
|
||||
return make_unique<RuntimeDyldCOFFX86_64>(MM);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
|
||||
RuntimeDyldCOFF::loadObject(const object::ObjectFile &O) {
|
||||
unsigned SectionStartIdx, SectionEndIdx;
|
||||
std::tie(SectionStartIdx, SectionEndIdx) = loadObjectImpl(O);
|
||||
return llvm::make_unique<LoadedCOFFObjectInfo>(*this, SectionStartIdx,
|
||||
SectionEndIdx);
|
||||
}
|
||||
|
||||
uint64_t RuntimeDyldCOFF::getSymbolOffset(const SymbolRef &Sym) {
|
||||
uint64_t Address;
|
||||
if (std::error_code EC = Sym.getAddress(Address))
|
||||
return UnknownAddressOrSize;
|
||||
|
||||
if (Address == UnknownAddressOrSize)
|
||||
return UnknownAddressOrSize;
|
||||
|
||||
const ObjectFile *Obj = Sym.getObject();
|
||||
section_iterator SecI(Obj->section_end());
|
||||
if (std::error_code EC = Sym.getSection(SecI))
|
||||
return UnknownAddressOrSize;
|
||||
|
||||
if (SecI == Obj->section_end())
|
||||
return UnknownAddressOrSize;
|
||||
|
||||
uint64_t SectionAddress = SecI->getAddress();
|
||||
return Address - SectionAddress;
|
||||
}
|
||||
|
||||
bool RuntimeDyldCOFF::isCompatibleFile(const object::ObjectFile &Obj) const {
|
||||
return Obj.isCOFF();
|
||||
}
|
||||
|
||||
} // namespace llvm
|
46
lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h
Normal file
46
lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h
Normal file
@ -0,0 +1,46 @@
|
||||
//===-- 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"
|
||||
#include "llvm/ADT/DenseMap.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,
|
||||
RTDyldMemoryManager *MM);
|
||||
|
||||
protected:
|
||||
RuntimeDyldCOFF(RTDyldMemoryManager *MM) : RuntimeDyldImpl(MM) {}
|
||||
uint64_t getSymbolOffset(const SymbolRef &Sym);
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#undef DEBUG_TYPE
|
||||
|
||||
#endif
|
@ -20,16 +20,6 @@
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
namespace {
|
||||
// Helper for extensive error checking in debug builds.
|
||||
std::error_code Check(std::error_code Err) {
|
||||
if (Err) {
|
||||
report_fatal_error(Err.message());
|
||||
}
|
||||
return Err;
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
class RuntimeDyldELF : public RuntimeDyldImpl {
|
||||
|
||||
|
@ -36,6 +36,16 @@ using namespace llvm::object;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
namespace {
|
||||
// Helper for extensive error checking in debug builds.
|
||||
std::error_code Check(std::error_code Err) {
|
||||
if (Err) {
|
||||
report_fatal_error(Err.message());
|
||||
}
|
||||
return Err;
|
||||
}
|
||||
} // end anonymous namespace
|
||||
|
||||
class Twine;
|
||||
|
||||
/// SectionEntry - represents a section emitted into memory by the dynamic
|
||||
|
@ -0,0 +1,189 @@
|
||||
//===-- RuntimeDyldCOFFX86_64.cpp - 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "RuntimeDyldCOFFX86_64.h"
|
||||
|
||||
#define DEBUG_TYPE "dyld"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
void RuntimeDyldCOFFX86_64::registerEHFrames() {
|
||||
if (!MemMgr)
|
||||
return;
|
||||
for (auto const &EHFrameSID : UnregisteredEHFrameSections) {
|
||||
uint8_t *EHFrameAddr = Sections[EHFrameSID].Address;
|
||||
uint64_t EHFrameLoadAddr = Sections[EHFrameSID].LoadAddress;
|
||||
size_t EHFrameSize = Sections[EHFrameSID].Size;
|
||||
MemMgr->registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize);
|
||||
RegisteredEHFrameSections.push_back(EHFrameSID);
|
||||
}
|
||||
UnregisteredEHFrameSections.clear();
|
||||
}
|
||||
|
||||
void RuntimeDyldCOFFX86_64::deregisterEHFrames() {
|
||||
// Stub
|
||||
}
|
||||
|
||||
// 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 RuntimeDyldCOFFX86_64::resolveRelocation(const RelocationEntry &RE,
|
||||
uint64_t Value) {
|
||||
const SectionEntry &Section = Sections[RE.SectionID];
|
||||
uint8_t *Target = Section.Address + 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: {
|
||||
uint32_t *TargetAddress = (uint32_t *)Target;
|
||||
uint64_t FinalAddress = Section.LoadAddress + 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");
|
||||
*TargetAddress = Result;
|
||||
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.
|
||||
uint32_t *TargetAddress = (uint32_t *)Target;
|
||||
*TargetAddress = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case COFF::IMAGE_REL_AMD64_ADDR64: {
|
||||
uint64_t *TargetAddress = (uint64_t *)Target;
|
||||
*TargetAddress = Value + RE.Addend;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
llvm_unreachable("Relocation type not implemented yet!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
relocation_iterator RuntimeDyldCOFFX86_64::processRelocationRef(
|
||||
unsigned SectionID, relocation_iterator RelI, const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &ObjSectionToID, StubMap &Stubs) {
|
||||
|
||||
// Find the symbol referred to in the relocation, and
|
||||
// get its section and offset.
|
||||
//
|
||||
// Insist for now that all symbols be resolvable within
|
||||
// the scope of this object file.
|
||||
symbol_iterator Symbol = RelI->getSymbol();
|
||||
if (Symbol == Obj.symbol_end())
|
||||
report_fatal_error("Unknown symbol in relocation");
|
||||
unsigned TargetSectionID = 0;
|
||||
uint64_t TargetOffset = UnknownAddressOrSize;
|
||||
const COFFObjectFile *COFFObj = cast<COFFObjectFile>(&Obj);
|
||||
section_iterator SecI(Obj.section_end());
|
||||
Symbol->getSection(SecI);
|
||||
if (SecI == Obj.section_end())
|
||||
report_fatal_error("Unknown section in relocation");
|
||||
bool IsCode = SecI->isText();
|
||||
TargetSectionID = findOrEmitSection(Obj, *SecI, IsCode, ObjSectionToID);
|
||||
TargetOffset = getSymbolOffset(*Symbol);
|
||||
|
||||
// Determine the Addend used to adjust the relocation value.
|
||||
uint64_t RelType;
|
||||
Check(RelI->getType(RelType));
|
||||
uint64_t Offset;
|
||||
Check(RelI->getOffset(Offset));
|
||||
uint64_t Addend = 0;
|
||||
SectionEntry &Section = Sections[SectionID];
|
||||
uintptr_t ObjTarget = Section.ObjAddress + 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: {
|
||||
uint32_t *Displacement = (uint32_t *)ObjTarget;
|
||||
Addend = *Displacement;
|
||||
break;
|
||||
}
|
||||
|
||||
case COFF::IMAGE_REL_AMD64_ADDR64: {
|
||||
uint64_t *Displacement = (uint64_t *)ObjTarget;
|
||||
Addend = *Displacement;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
StringRef TargetName;
|
||||
Symbol->getName(TargetName);
|
||||
DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
|
||||
<< " RelType: " << RelType << " TargetName: " << TargetName
|
||||
<< " Addend " << Addend << "\n");
|
||||
|
||||
RelocationEntry RE(SectionID, Offset, RelType, TargetOffset + Addend);
|
||||
addRelocationForSection(RE, TargetSectionID);
|
||||
|
||||
return ++RelI;
|
||||
}
|
||||
|
||||
void RuntimeDyldCOFFX86_64::finalizeLoad(const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &SectionMap) {
|
||||
// Look for and record the EH frame section IDs.
|
||||
for (const auto &SectionPair : SectionMap) {
|
||||
const SectionRef &Section = SectionPair.first;
|
||||
StringRef Name;
|
||||
Check(Section.getName(Name));
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
//===-- 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 "llvm/Object/COFF.h"
|
||||
#include "llvm/Support/COFF.h"
|
||||
#include "../RuntimeDyldCOFF.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
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(RTDyldMemoryManager *MM) : RuntimeDyldCOFF(MM) {}
|
||||
|
||||
unsigned getMaxStubSize() override {
|
||||
return 6; // 2-byte jmp instruction + 32-bit relative address
|
||||
}
|
||||
|
||||
void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override;
|
||||
|
||||
relocation_iterator processRelocationRef(unsigned SectionID,
|
||||
relocation_iterator RelI,
|
||||
const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &ObjSectionToID,
|
||||
StubMap &Stubs) override;
|
||||
|
||||
unsigned getStubAlignment() override { return 1; }
|
||||
void registerEHFrames() override;
|
||||
void deregisterEHFrames() override;
|
||||
void finalizeLoad(const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &SectionMap) override;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#undef DEBUG_TYPE
|
||||
|
||||
#endif
|
@ -190,7 +190,9 @@ std::error_code COFFObjectFile::getSymbolType(DataRefImpl Ref,
|
||||
Result = SymbolRef::ST_Data;
|
||||
} else if (Symb.isFileRecord()) {
|
||||
Result = SymbolRef::ST_File;
|
||||
} else if (SectionNumber == COFF::IMAGE_SYM_DEBUG) {
|
||||
} else if (SectionNumber == COFF::IMAGE_SYM_DEBUG ||
|
||||
Symb.isSectionDefinition()) {
|
||||
// TODO: perhaps we need a new symbol type ST_Section.
|
||||
Result = SymbolRef::ST_Debug;
|
||||
} else if (!COFF::isReservedSectionNumber(SectionNumber)) {
|
||||
const coff_section *Section = nullptr;
|
||||
@ -359,12 +361,17 @@ bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
|
||||
|
||||
bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
|
||||
const coff_section *Sec = toSec(Ref);
|
||||
return Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
|
||||
const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
|
||||
COFF::IMAGE_SCN_MEM_READ |
|
||||
COFF::IMAGE_SCN_MEM_WRITE;
|
||||
return (Sec->Characteristics & BssFlags) == BssFlags;
|
||||
}
|
||||
|
||||
bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
|
||||
const coff_section *Sec = toSec(Ref);
|
||||
return Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
|
||||
// In COFF, a virtual section won't have any in-file
|
||||
// content, so the file pointer to the content will be zero.
|
||||
return Sec->PointerToRawData == 0;
|
||||
}
|
||||
|
||||
bool COFFObjectFile::sectionContainsSymbol(DataRefImpl SecRef,
|
||||
|
31
test/ExecutionEngine/RuntimeDyld/X86/COFF_x86_64
Normal file
31
test/ExecutionEngine/RuntimeDyld/X86/COFF_x86_64
Normal file
@ -0,0 +1,31 @@
|
||||
# RUN: llvm-mc -triple=x86_64-pc-win32 -filetype=obj -o %T/COFF_x86_64.o %s
|
||||
# RUN: llvm-rtdyld -triple=x86_64-pc-win32 -verify -check=%s %/T/COFF_x86_64.o
|
||||
.text
|
||||
.def F;
|
||||
.scl 2;
|
||||
.type 32;
|
||||
.endef
|
||||
.globl __real400921f9f01b866e
|
||||
.section .rdata,"dr",discard,__real400921f9f01b866e
|
||||
.align 8
|
||||
__real400921f9f01b866e:
|
||||
.quad 4614256650576692846 # double 3.1415899999999999
|
||||
.text
|
||||
.globl F
|
||||
.global inst1
|
||||
.align 16, 0x90
|
||||
F: # @F
|
||||
.Ltmp0:
|
||||
.seh_proc F
|
||||
# BB#0: # %entry
|
||||
.Ltmp1:
|
||||
.seh_endprologue
|
||||
# rtdyld-check: decode_operand(inst1, 4) = __real400921f9f01b866e - next_pc(inst1)
|
||||
inst1:
|
||||
movsd __real400921f9f01b866e(%rip), %xmm0 # xmm0 = mem[0],zero
|
||||
retq
|
||||
.Leh_func_end0:
|
||||
.Ltmp2:
|
||||
.seh_endproc
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user