forked from OSchip/llvm-project
RuntimeDyld: add COFF i386 support
This adds support for COFF I386. This is sufficient for code execution in a 32-bit JIT, though, imported symbols need to custom lowered for the redirection. llvm-svn: 251761
This commit is contained in:
parent
f67c32466d
commit
50406b92ec
|
@ -12,6 +12,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "RuntimeDyldCOFF.h"
|
||||
#include "Targets/RuntimeDyldCOFFI386.h"
|
||||
#include "Targets/RuntimeDyldCOFFX86_64.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
|
@ -47,6 +48,8 @@ llvm::RuntimeDyldCOFF::create(Triple::ArchType Arch,
|
|||
default:
|
||||
llvm_unreachable("Unsupported target for RuntimeDyldCOFF.");
|
||||
break;
|
||||
case Triple::x86:
|
||||
return make_unique<RuntimeDyldCOFFI386>(MemMgr, Resolver);
|
||||
case Triple::x86_64:
|
||||
return make_unique<RuntimeDyldCOFFX86_64>(MemMgr, Resolver);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,199 @@
|
|||
//===--- 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 "llvm/Object/COFF.h"
|
||||
#include "llvm/Support/COFF.h"
|
||||
#include "../RuntimeDyldCOFF.h"
|
||||
|
||||
#define DEBUG_TYPE "dyld"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class RuntimeDyldCOFFI386 : public RuntimeDyldCOFF {
|
||||
public:
|
||||
RuntimeDyldCOFFI386(RuntimeDyld::MemoryManager &MM,
|
||||
RuntimeDyld::SymbolResolver &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; }
|
||||
|
||||
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");
|
||||
|
||||
ErrorOr<StringRef> TargetNameOrErr = Symbol->getName();
|
||||
if (auto EC = TargetNameOrErr.getError())
|
||||
report_fatal_error(EC.message());
|
||||
StringRef TargetName = *TargetNameOrErr;
|
||||
|
||||
auto Section = *Symbol->getSection();
|
||||
|
||||
uint64_t RelType = RelI->getType();
|
||||
uint64_t Offset = RelI->getOffset();
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
SmallString<32> RelTypeName;
|
||||
RelI->getTypeName(RelTypeName);
|
||||
#endif
|
||||
DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
|
||||
<< " RelType: " << RelTypeName << " TargetName: " << TargetName
|
||||
<< "\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 {
|
||||
TargetSectionID =
|
||||
findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID);
|
||||
|
||||
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, 0, 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));
|
||||
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.Address + 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].LoadAddress + RE.Addend;
|
||||
assert(static_cast<int32_t>(Result) <= INT32_MAX &&
|
||||
"relocation overflow");
|
||||
assert(static_cast<int32_t>(Result) >= INT32_MIN &&
|
||||
"relocation underflow");
|
||||
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].LoadAddress as an approximation of ImageBase
|
||||
uint64_t Result = Sections[RE.Sections.SectionA].LoadAddress + RE.Addend -
|
||||
Sections[0].LoadAddress;
|
||||
assert(static_cast<int32_t>(Result) <= INT32_MAX &&
|
||||
"relocation overflow");
|
||||
assert(static_cast<int32_t>(Result) >= INT32_MIN &&
|
||||
"relocation underflow");
|
||||
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 = Sections[RE.Sections.SectionA].LoadAddress -
|
||||
Section.LoadAddress + RE.Addend - 4 - RE.Offset;
|
||||
assert(static_cast<int32_t>(Result) <= INT32_MAX &&
|
||||
"relocation overflow");
|
||||
assert(static_cast<int32_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<int16_t>(RE.SectionID) <= INT16_MAX &&
|
||||
"relocation overflow");
|
||||
assert(static_cast<int16_t>(RE.SectionID) >= INT16_MIN &&
|
||||
"relocation underflow");
|
||||
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<int32_t>(RE.Addend) <= INT32_MAX &&
|
||||
"relocation overflow");
|
||||
assert(static_cast<int32_t>(RE.Addend) >= INT32_MIN &&
|
||||
"relocation underflow");
|
||||
DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
|
||||
<< " RelType: IMAGE_REL_I386_SECREL Value: " << RE.Addend
|
||||
<< '\n');
|
||||
writeBytesUnaligned(RE.Addend, Target, 2);
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("unsupported relocation type");
|
||||
}
|
||||
}
|
||||
|
||||
void registerEHFrames() override {}
|
||||
void deregisterEHFrames() override {}
|
||||
|
||||
void finalizeLoad(const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &SectionMap) override {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
// RUN: llvm-mc -triple i686-windows -filetype obj -o %t.obj %s
|
||||
// RUN: llvm-rtdyld -triple i686-windows -dummy-extern _OutputDebugStringA@4=0xfffffffe -dummy-extern _ExitProcess@4=0xffffffff -verify -check=%s %t.obj
|
||||
|
||||
.text
|
||||
|
||||
.def _main
|
||||
.scl 2
|
||||
.type 32
|
||||
.endef
|
||||
.global _main
|
||||
_main:
|
||||
rel1:
|
||||
call _function // IMAGE_REL_I386_REL32
|
||||
# rtdyld-check: decode_operand(rel1, 0) = (_function-_main-4-1)
|
||||
xorl %eax, %eax
|
||||
retl
|
||||
|
||||
.def _function
|
||||
.scl 2
|
||||
.type 32
|
||||
.endef
|
||||
_function:
|
||||
rel2:
|
||||
pushl string
|
||||
rel3:
|
||||
calll *__imp__OutputDebugStringA // IMAGE_REL_I386_DIR32
|
||||
# rtdyld-check: decode_operand(rel3, 3) = __imp__OutputDebugStringA
|
||||
addl $4, %esp
|
||||
pushl $0
|
||||
rel4:
|
||||
calll *__imp__ExitProcess // IMAGE_REL_I386_DIR32
|
||||
# rtdyld-check: decode_operand(rel4, 3) = __imp__ExitProcess
|
||||
addl $4, %esp
|
||||
retl
|
||||
|
||||
.data
|
||||
|
||||
.global __imp__OutputDebugStringA
|
||||
.align 4
|
||||
__imp__OutputDebugStringA:
|
||||
.long "_OutputDebugStringA@4" // IMAGE_REL_I386_DIR32
|
||||
# rtdyld-check: *{4}__imp__OutputDebugStringA = 0xfffffffe
|
||||
|
||||
.global __imp__ExitProcess
|
||||
.align 4
|
||||
__imp__ExitProcess:
|
||||
.long "_ExitProcess@4" // IMAGE_REL_I386_DIR32
|
||||
# rtdyld-check: *{4}__imp__ExitProcess = 0xffffffff
|
||||
|
||||
.global string
|
||||
.align 1
|
||||
string:
|
||||
.asciz "Hello World!\n"
|
||||
|
||||
.global relocations
|
||||
relocations:
|
||||
rel5:
|
||||
.long _function@imgrel // IMAGE_REL_I386_DIR32NB
|
||||
# rtdyld-check: *{4}rel5 = _function - section_addr(COFF_i386.s.tmp.obj, .text)
|
||||
rel6:
|
||||
# rtdyld-check: *{2}rel6 = 1
|
||||
.secidx __imp__OutputDebugStringA // IMAGE_REL_I386_SECTION
|
||||
rel7:
|
||||
# rtdyld-check: *{4}rel7 = relocations - section_addr(COFF_i386.s.tmp.obj, .data)
|
||||
.secrel32 relocations // IMAGE_REL_I386_SECREL
|
||||
|
Loading…
Reference in New Issue