A64: Add Disassemble method
This commit is contained in:
parent
cc0eb18a0b
commit
bafb39ebc5
8 changed files with 98 additions and 32 deletions
|
@ -10,6 +10,7 @@
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <dynarmic/A64/config.h>
|
#include <dynarmic/A64/config.h>
|
||||||
|
|
||||||
|
@ -100,6 +101,12 @@ public:
|
||||||
*/
|
*/
|
||||||
bool IsExecuting() const;
|
bool IsExecuting() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Debugging: Disassemble all of compiled code.
|
||||||
|
* @return A string containing disassembly of all host machine code produced.
|
||||||
|
*/
|
||||||
|
std::string Disassemble() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Impl;
|
struct Impl;
|
||||||
std::unique_ptr<Impl> impl;
|
std::unique_ptr<Impl> impl;
|
||||||
|
|
|
@ -132,6 +132,9 @@ if (ARCHITECTURE_x86_64)
|
||||||
backend_x64/callback.h
|
backend_x64/callback.h
|
||||||
backend_x64/constant_pool.cpp
|
backend_x64/constant_pool.cpp
|
||||||
backend_x64/constant_pool.h
|
backend_x64/constant_pool.h
|
||||||
|
backend_x64/devirtualize.h
|
||||||
|
backend_x64/disassemble_x64.cpp
|
||||||
|
backend_x64/disassemble_x64.h
|
||||||
backend_x64/emit_x64.cpp
|
backend_x64/emit_x64.cpp
|
||||||
backend_x64/emit_x64.h
|
backend_x64/emit_x64.h
|
||||||
backend_x64/emit_x64_crc32.cpp
|
backend_x64/emit_x64_crc32.cpp
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "backend_x64/block_of_code.h"
|
#include "backend_x64/block_of_code.h"
|
||||||
#include "backend_x64/callback.h"
|
#include "backend_x64/callback.h"
|
||||||
#include "backend_x64/devirtualize.h"
|
#include "backend_x64/devirtualize.h"
|
||||||
|
#include "backend_x64/disassemble_x64.h"
|
||||||
#include "backend_x64/jitstate_info.h"
|
#include "backend_x64/jitstate_info.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
@ -73,38 +74,7 @@ struct Jit::Impl {
|
||||||
std::string Disassemble(const IR::LocationDescriptor& descriptor) {
|
std::string Disassemble(const IR::LocationDescriptor& descriptor) {
|
||||||
auto block = GetBasicBlock(descriptor);
|
auto block = GetBasicBlock(descriptor);
|
||||||
std::string result = fmt::format("address: {}\nsize: {} bytes\n", block.entrypoint, block.size);
|
std::string result = fmt::format("address: {}\nsize: {} bytes\n", block.entrypoint, block.size);
|
||||||
|
result += DisassembleX64(block.entrypoint, reinterpret_cast<const char*>(block.entrypoint) + block.size);
|
||||||
#ifdef DYNARMIC_USE_LLVM
|
|
||||||
LLVMInitializeX86TargetInfo();
|
|
||||||
LLVMInitializeX86TargetMC();
|
|
||||||
LLVMInitializeX86Disassembler();
|
|
||||||
LLVMDisasmContextRef llvm_ctx = LLVMCreateDisasm("x86_64", nullptr, 0, nullptr, nullptr);
|
|
||||||
LLVMSetDisasmOptions(llvm_ctx, LLVMDisassembler_Option_AsmPrinterVariant);
|
|
||||||
|
|
||||||
const u8* pos = static_cast<const u8*>(block.entrypoint);
|
|
||||||
const u8* end = pos + block.size;
|
|
||||||
size_t remaining = block.size;
|
|
||||||
|
|
||||||
while (pos < end) {
|
|
||||||
char buffer[80];
|
|
||||||
size_t inst_size = LLVMDisasmInstruction(llvm_ctx, const_cast<u8*>(pos), remaining, (u64)pos, buffer, sizeof(buffer));
|
|
||||||
ASSERT(inst_size);
|
|
||||||
for (const u8* i = pos; i < pos + inst_size; i++)
|
|
||||||
result += fmt::format("{:02x} ", *i);
|
|
||||||
for (size_t i = inst_size; i < 10; i++)
|
|
||||||
result += " ";
|
|
||||||
result += buffer;
|
|
||||||
result += '\n';
|
|
||||||
|
|
||||||
pos += inst_size;
|
|
||||||
remaining -= inst_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
LLVMDisasmDispose(llvm_ctx);
|
|
||||||
#else
|
|
||||||
result.append("(recompile with DYNARMIC_USE_LLVM=ON to disassemble the generated x86_64 code)\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "backend_x64/a64_jitstate.h"
|
#include "backend_x64/a64_jitstate.h"
|
||||||
#include "backend_x64/block_of_code.h"
|
#include "backend_x64/block_of_code.h"
|
||||||
#include "backend_x64/devirtualize.h"
|
#include "backend_x64/devirtualize.h"
|
||||||
|
#include "backend_x64/disassemble_x64.h"
|
||||||
#include "backend_x64/jitstate_info.h"
|
#include "backend_x64/jitstate_info.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/scope_exit.h"
|
#include "common/scope_exit.h"
|
||||||
|
@ -160,6 +161,10 @@ public:
|
||||||
return is_executing;
|
return is_executing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Disassemble() const {
|
||||||
|
return DisassembleX64(block_of_code.GetCodeBegin(), block_of_code.getCurr());
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static CodePtr GetCurrentBlockThunk(void* thisptr) {
|
static CodePtr GetCurrentBlockThunk(void* thisptr) {
|
||||||
Jit::Impl* this_ = reinterpret_cast<Jit::Impl*>(thisptr);
|
Jit::Impl* this_ = reinterpret_cast<Jit::Impl*>(thisptr);
|
||||||
|
@ -318,4 +323,8 @@ bool Jit::IsExecuting() const {
|
||||||
return impl->IsExecuting();
|
return impl->IsExecuting();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Jit::Disassemble() const {
|
||||||
|
return impl->Disassemble();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Dynarmic::A64
|
} // namespace Dynarmic::A64
|
||||||
|
|
|
@ -210,6 +210,10 @@ void BlockOfCode::SwitchToNearCode() {
|
||||||
SetCodePtr(near_code_ptr);
|
SetCodePtr(near_code_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CodePtr BlockOfCode::GetCodeBegin() const {
|
||||||
|
return near_code_begin;
|
||||||
|
}
|
||||||
|
|
||||||
void* BlockOfCode::AllocateFromCodeSpace(size_t alloc_size) {
|
void* BlockOfCode::AllocateFromCodeSpace(size_t alloc_size) {
|
||||||
if (size_ + alloc_size >= maxSize_) {
|
if (size_ + alloc_size >= maxSize_) {
|
||||||
throw Xbyak::Error(Xbyak::ERR_CODE_IS_TOO_BIG);
|
throw Xbyak::Error(Xbyak::ERR_CODE_IS_TOO_BIG);
|
||||||
|
|
|
@ -77,6 +77,8 @@ public:
|
||||||
void SwitchToFarCode();
|
void SwitchToFarCode();
|
||||||
void SwitchToNearCode();
|
void SwitchToNearCode();
|
||||||
|
|
||||||
|
CodePtr GetCodeBegin() const;
|
||||||
|
|
||||||
const void* GetReturnFromRunCodeAddress() const {
|
const void* GetReturnFromRunCodeAddress() const {
|
||||||
return return_from_run_code[0];
|
return return_from_run_code[0];
|
||||||
}
|
}
|
||||||
|
|
58
src/backend_x64/disassemble_x64.cpp
Normal file
58
src/backend_x64/disassemble_x64.cpp
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2018 MerryMage
|
||||||
|
* This software may be used and distributed according to the terms of the GNU
|
||||||
|
* General Public License version 2 or any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#ifdef DYNARMIC_USE_LLVM
|
||||||
|
#include <llvm-c/Disassembler.h>
|
||||||
|
#include <llvm-c/Target.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "backend_x64/disassemble_x64.h"
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
namespace Dynarmic::BackendX64 {
|
||||||
|
|
||||||
|
std::string DisassembleX64(const void* begin, const void* end) {
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
#ifdef DYNARMIC_USE_LLVM
|
||||||
|
LLVMInitializeX86TargetInfo();
|
||||||
|
LLVMInitializeX86TargetMC();
|
||||||
|
LLVMInitializeX86Disassembler();
|
||||||
|
LLVMDisasmContextRef llvm_ctx = LLVMCreateDisasm("x86_64", nullptr, 0, nullptr, nullptr);
|
||||||
|
LLVMSetDisasmOptions(llvm_ctx, LLVMDisassembler_Option_AsmPrinterVariant);
|
||||||
|
|
||||||
|
const u8* pos = reinterpret_cast<const u8*>(begin);
|
||||||
|
size_t remaining = reinterpret_cast<size_t>(end) - reinterpret_cast<size_t>(pos);
|
||||||
|
while (pos < end) {
|
||||||
|
char buffer[80];
|
||||||
|
size_t inst_size = LLVMDisasmInstruction(llvm_ctx, const_cast<u8*>(pos), remaining, reinterpret_cast<u64>(pos), buffer, sizeof(buffer));
|
||||||
|
ASSERT(inst_size);
|
||||||
|
for (const u8* i = pos; i < pos + inst_size; i++)
|
||||||
|
result += fmt::format("{:02x} ", *i);
|
||||||
|
for (size_t i = inst_size; i < 10; i++)
|
||||||
|
result += " ";
|
||||||
|
result += buffer;
|
||||||
|
result += '\n';
|
||||||
|
|
||||||
|
pos += inst_size;
|
||||||
|
remaining -= inst_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVMDisasmDispose(llvm_ctx);
|
||||||
|
#else
|
||||||
|
result += fmt::format("(recompile with DYNARMIC_USE_LLVM=ON to disassemble the generated x86_64 code)\n");
|
||||||
|
result += fmt::format("start: {:016x}, end: {:016x}\n", begin, end);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Dynarmic::BackendX64
|
13
src/backend_x64/disassemble_x64.h
Normal file
13
src/backend_x64/disassemble_x64.h
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2018 MerryMage
|
||||||
|
* This software may be used and distributed according to the terms of the GNU
|
||||||
|
* General Public License version 2 or any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Dynarmic::BackendX64 {
|
||||||
|
|
||||||
|
std::string DisassembleX64(const void* pos, const void* end);
|
||||||
|
|
||||||
|
} // namespace Dynarmic::BackendX64
|
Loading…
Reference in a new issue