[a64] Implement multi-arch capstone support
This commit is contained in:
parent
6e83e2a42d
commit
fbc306f702
|
@ -11,8 +11,8 @@
|
|||
|
||||
#include <climits>
|
||||
|
||||
#include "third_party/capstone/include/capstone/arm64.h"
|
||||
#include "third_party/capstone/include/capstone/capstone.h"
|
||||
#include "third_party/capstone/include/capstone/x86.h"
|
||||
#include "xenia/base/profiling.h"
|
||||
#include "xenia/base/reset_scope.h"
|
||||
#include "xenia/base/string.h"
|
||||
|
@ -33,11 +33,22 @@ namespace a64 {
|
|||
using xe::cpu::hir::HIRBuilder;
|
||||
|
||||
A64Assembler::A64Assembler(A64Backend* backend)
|
||||
: Assembler(backend), a64_backend_(backend) {}
|
||||
: Assembler(backend), a64_backend_(backend), capstone_handle_(0) {
|
||||
if (cs_open(CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, &capstone_handle_) !=
|
||||
CS_ERR_OK) {
|
||||
assert_always("Failed to initialize capstone");
|
||||
}
|
||||
cs_option(capstone_handle_, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL);
|
||||
cs_option(capstone_handle_, CS_OPT_DETAIL, CS_OPT_OFF);
|
||||
}
|
||||
|
||||
A64Assembler::~A64Assembler() {
|
||||
// Emitter must be freed before the allocator.
|
||||
emitter_.reset();
|
||||
|
||||
if (capstone_handle_) {
|
||||
cs_close(&capstone_handle_);
|
||||
}
|
||||
}
|
||||
|
||||
bool A64Assembler::Initialize() {
|
||||
|
@ -106,7 +117,9 @@ void A64Assembler::DumpMachineCode(
|
|||
size_t remaining_code_size = code_size;
|
||||
uint64_t address = uint64_t(machine_code);
|
||||
cs_insn insn = {0};
|
||||
while (remaining_code_size) {
|
||||
while (remaining_code_size &&
|
||||
cs_disasm_iter(capstone_handle_, &code_ptr, &remaining_code_size,
|
||||
&address, &insn)) {
|
||||
// Look up source offset.
|
||||
auto code_offset =
|
||||
uint32_t(code_ptr - reinterpret_cast<uint8_t*>(machine_code));
|
||||
|
|
|
@ -46,6 +46,7 @@ class A64Assembler : public Assembler {
|
|||
private:
|
||||
A64Backend* a64_backend_;
|
||||
std::unique_ptr<A64Emitter> emitter_;
|
||||
uintptr_t capstone_handle_;
|
||||
|
||||
StringBuffer string_buffer_;
|
||||
};
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
|
||||
#include <cstddef>
|
||||
|
||||
#include "third_party/capstone/include/capstone/arm64.h"
|
||||
#include "third_party/capstone/include/capstone/capstone.h"
|
||||
|
||||
#include "xenia/base/exception_handler.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/cpu/backend/a64/a64_assembler.h"
|
||||
|
@ -64,9 +67,21 @@ class A64ThunkEmitter : public A64Emitter {
|
|||
void EmitLoadNonvolatileRegs();
|
||||
};
|
||||
|
||||
A64Backend::A64Backend() : Backend() {}
|
||||
A64Backend::A64Backend() : Backend(), code_cache_(nullptr) {
|
||||
if (cs_open(CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, &capstone_handle_) !=
|
||||
CS_ERR_OK) {
|
||||
assert_always("Failed to initialize capstone");
|
||||
}
|
||||
cs_option(capstone_handle_, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL);
|
||||
cs_option(capstone_handle_, CS_OPT_DETAIL, CS_OPT_ON);
|
||||
cs_option(capstone_handle_, CS_OPT_SKIPDATA, CS_OPT_OFF);
|
||||
}
|
||||
|
||||
A64Backend::~A64Backend() {
|
||||
if (capstone_handle_) {
|
||||
cs_close(&capstone_handle_);
|
||||
}
|
||||
|
||||
A64Emitter::FreeConstData(emitter_data_);
|
||||
ExceptionHandler::Uninstall(&ExceptionCallbackThunk, this);
|
||||
}
|
||||
|
@ -132,10 +147,99 @@ std::unique_ptr<GuestFunction> A64Backend::CreateGuestFunction(
|
|||
Module* module, uint32_t address) {
|
||||
return std::make_unique<A64Function>(module, address);
|
||||
}
|
||||
|
||||
uint64_t ReadCapstoneReg(HostThreadContext* context, arm64_reg reg) {
|
||||
switch (reg) {
|
||||
case ARM64_REG_X0:
|
||||
return context->x[0];
|
||||
case ARM64_REG_X1:
|
||||
return context->x[1];
|
||||
case ARM64_REG_X2:
|
||||
return context->x[2];
|
||||
case ARM64_REG_X3:
|
||||
return context->x[3];
|
||||
case ARM64_REG_X4:
|
||||
return context->x[4];
|
||||
case ARM64_REG_X5:
|
||||
return context->x[5];
|
||||
case ARM64_REG_X6:
|
||||
return context->x[6];
|
||||
case ARM64_REG_X7:
|
||||
return context->x[7];
|
||||
case ARM64_REG_X8:
|
||||
return context->x[8];
|
||||
case ARM64_REG_X9:
|
||||
return context->x[9];
|
||||
case ARM64_REG_X10:
|
||||
return context->x[10];
|
||||
case ARM64_REG_X11:
|
||||
return context->x[11];
|
||||
case ARM64_REG_X12:
|
||||
return context->x[12];
|
||||
case ARM64_REG_X13:
|
||||
return context->x[13];
|
||||
case ARM64_REG_X14:
|
||||
return context->x[14];
|
||||
case ARM64_REG_X15:
|
||||
return context->x[15];
|
||||
case ARM64_REG_X16:
|
||||
return context->x[16];
|
||||
case ARM64_REG_X17:
|
||||
return context->x[17];
|
||||
case ARM64_REG_X18:
|
||||
return context->x[18];
|
||||
case ARM64_REG_X19:
|
||||
return context->x[19];
|
||||
case ARM64_REG_X20:
|
||||
return context->x[20];
|
||||
case ARM64_REG_X21:
|
||||
return context->x[21];
|
||||
case ARM64_REG_X22:
|
||||
return context->x[22];
|
||||
case ARM64_REG_X23:
|
||||
return context->x[23];
|
||||
case ARM64_REG_X24:
|
||||
return context->x[24];
|
||||
case ARM64_REG_X25:
|
||||
return context->x[25];
|
||||
case ARM64_REG_X26:
|
||||
return context->x[26];
|
||||
case ARM64_REG_X27:
|
||||
return context->x[27];
|
||||
case ARM64_REG_X28:
|
||||
return context->x[28];
|
||||
case ARM64_REG_X29:
|
||||
return context->x[29];
|
||||
case ARM64_REG_X30:
|
||||
return context->x[30];
|
||||
default:
|
||||
assert_unhandled_case(reg);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t A64Backend::CalculateNextHostInstruction(ThreadDebugInfo* thread_info,
|
||||
uint64_t current_pc) {
|
||||
// TODO(wunkolo): Capstone hookup
|
||||
return current_pc += 4;
|
||||
auto machine_code_ptr = reinterpret_cast<const uint8_t*>(current_pc);
|
||||
size_t remaining_machine_code_size = 64;
|
||||
uint64_t host_address = current_pc;
|
||||
cs_insn insn = {0};
|
||||
cs_detail all_detail = {0};
|
||||
insn.detail = &all_detail;
|
||||
cs_disasm_iter(capstone_handle_, &machine_code_ptr,
|
||||
&remaining_machine_code_size, &host_address, &insn);
|
||||
auto& detail = all_detail.x86;
|
||||
switch (insn.id) {
|
||||
case ARM64_INS_B:
|
||||
case ARM64_INS_BL:
|
||||
case ARM64_INS_BLR:
|
||||
case ARM64_INS_BR:
|
||||
case ARM64_INS_RET:
|
||||
// todo(wunkolo): determine next instruction
|
||||
default:
|
||||
// Not a branching instruction - just move over it.
|
||||
return current_pc + insn.size;
|
||||
}
|
||||
}
|
||||
|
||||
void A64Backend::InstallBreakpoint(Breakpoint* breakpoint) {
|
||||
|
|
|
@ -70,7 +70,7 @@ class A64Backend : public Backend {
|
|||
static bool ExceptionCallbackThunk(Exception* ex, void* data);
|
||||
bool ExceptionCallback(Exception* ex);
|
||||
|
||||
// uintptr_t capstone_handle_ = 0;
|
||||
uintptr_t capstone_handle_ = 0;
|
||||
|
||||
std::unique_ptr<A64CodeCache> code_cache_;
|
||||
uintptr_t emitter_data_ = 0;
|
||||
|
|
|
@ -4,13 +4,37 @@ project("capstone")
|
|||
kind("StaticLib")
|
||||
language("C")
|
||||
defines({
|
||||
"CAPSTONE_X86_ATT_DISABLE",
|
||||
"CAPSTONE_DIET_NO",
|
||||
"CAPSTONE_X86_REDUCE_NO",
|
||||
"CAPSTONE_HAS_X86",
|
||||
"CAPSTONE_USE_SYS_DYN_MEM",
|
||||
"_LIB",
|
||||
})
|
||||
filter("architecture:x86_64")
|
||||
defines({
|
||||
"CAPSTONE_HAS_X86",
|
||||
"CAPSTONE_X86_ATT_DISABLE",
|
||||
"CAPSTONE_X86_REDUCE_NO",
|
||||
})
|
||||
files({
|
||||
"capstone/arch/X86/*.c",
|
||||
"capstone/arch/X86/*.h",
|
||||
"capstone/arch/X86/*.inc",
|
||||
})
|
||||
force_compile_as_c({
|
||||
"capstone/arch/X86/**.c",
|
||||
})
|
||||
filter("architecture:ARM64")
|
||||
defines({
|
||||
"CAPSTONE_HAS_ARM64",
|
||||
})
|
||||
files({
|
||||
"capstone/arch/AArch64/*.c",
|
||||
"capstone/arch/AArch64/*.h",
|
||||
"capstone/arch/AArch64/*.inc",
|
||||
})
|
||||
force_compile_as_c({
|
||||
"capstone/arch/AArch64/**.c",
|
||||
})
|
||||
filter({})
|
||||
includedirs({
|
||||
"capstone",
|
||||
"capstone/include",
|
||||
|
@ -32,12 +56,7 @@ project("capstone")
|
|||
"capstone/SStream.h",
|
||||
"capstone/utils.c",
|
||||
"capstone/utils.h",
|
||||
|
||||
"capstone/arch/X86/*.c",
|
||||
"capstone/arch/X86/*.h",
|
||||
"capstone/arch/X86/*.inc",
|
||||
})
|
||||
force_compile_as_c({
|
||||
"capstone/**.c",
|
||||
"capstone/arch/X86/**.c",
|
||||
})
|
||||
"capstone/**.c",
|
||||
})
|
Loading…
Reference in New Issue