diff --git a/include/dynarmic/A64/a64.h b/include/dynarmic/A64/a64.h index 73a19706..26238583 100644 --- a/include/dynarmic/A64/a64.h +++ b/include/dynarmic/A64/a64.h @@ -10,6 +10,7 @@ #include #include #include +#include #include @@ -100,6 +101,12 @@ public: */ 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: struct Impl; std::unique_ptr impl; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 48c1c673..0ec2974b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -132,6 +132,9 @@ if (ARCHITECTURE_x86_64) backend_x64/callback.h backend_x64/constant_pool.cpp 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.h backend_x64/emit_x64_crc32.cpp diff --git a/src/backend_x64/a32_interface.cpp b/src/backend_x64/a32_interface.cpp index 1583c042..48d63457 100644 --- a/src/backend_x64/a32_interface.cpp +++ b/src/backend_x64/a32_interface.cpp @@ -19,6 +19,7 @@ #include "backend_x64/block_of_code.h" #include "backend_x64/callback.h" #include "backend_x64/devirtualize.h" +#include "backend_x64/disassemble_x64.h" #include "backend_x64/jitstate_info.h" #include "common/assert.h" #include "common/common_types.h" @@ -73,38 +74,7 @@ struct Jit::Impl { std::string Disassemble(const IR::LocationDescriptor& descriptor) { auto block = GetBasicBlock(descriptor); std::string result = fmt::format("address: {}\nsize: {} bytes\n", 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(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(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 - + result += DisassembleX64(block.entrypoint, reinterpret_cast(block.entrypoint) + block.size); return result; } diff --git a/src/backend_x64/a64_interface.cpp b/src/backend_x64/a64_interface.cpp index fa88aa46..e80930e3 100644 --- a/src/backend_x64/a64_interface.cpp +++ b/src/backend_x64/a64_interface.cpp @@ -13,6 +13,7 @@ #include "backend_x64/a64_jitstate.h" #include "backend_x64/block_of_code.h" #include "backend_x64/devirtualize.h" +#include "backend_x64/disassemble_x64.h" #include "backend_x64/jitstate_info.h" #include "common/assert.h" #include "common/scope_exit.h" @@ -160,6 +161,10 @@ public: return is_executing; } + std::string Disassemble() const { + return DisassembleX64(block_of_code.GetCodeBegin(), block_of_code.getCurr()); + } + private: static CodePtr GetCurrentBlockThunk(void* thisptr) { Jit::Impl* this_ = reinterpret_cast(thisptr); @@ -318,4 +323,8 @@ bool Jit::IsExecuting() const { return impl->IsExecuting(); } +std::string Jit::Disassemble() const { + return impl->Disassemble(); +} + } // namespace Dynarmic::A64 diff --git a/src/backend_x64/block_of_code.cpp b/src/backend_x64/block_of_code.cpp index 46aec346..e2d7a354 100644 --- a/src/backend_x64/block_of_code.cpp +++ b/src/backend_x64/block_of_code.cpp @@ -210,6 +210,10 @@ void BlockOfCode::SwitchToNearCode() { SetCodePtr(near_code_ptr); } +CodePtr BlockOfCode::GetCodeBegin() const { + return near_code_begin; +} + void* BlockOfCode::AllocateFromCodeSpace(size_t alloc_size) { if (size_ + alloc_size >= maxSize_) { throw Xbyak::Error(Xbyak::ERR_CODE_IS_TOO_BIG); diff --git a/src/backend_x64/block_of_code.h b/src/backend_x64/block_of_code.h index 59ec0e6e..e839bac5 100644 --- a/src/backend_x64/block_of_code.h +++ b/src/backend_x64/block_of_code.h @@ -77,6 +77,8 @@ public: void SwitchToFarCode(); void SwitchToNearCode(); + CodePtr GetCodeBegin() const; + const void* GetReturnFromRunCodeAddress() const { return return_from_run_code[0]; } diff --git a/src/backend_x64/disassemble_x64.cpp b/src/backend_x64/disassemble_x64.cpp new file mode 100644 index 00000000..a93e41fb --- /dev/null +++ b/src/backend_x64/disassemble_x64.cpp @@ -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 + +#include + +#ifdef DYNARMIC_USE_LLVM +#include +#include +#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(begin); + size_t remaining = reinterpret_cast(end) - reinterpret_cast(pos); + while (pos < end) { + char buffer[80]; + size_t inst_size = LLVMDisasmInstruction(llvm_ctx, const_cast(pos), remaining, reinterpret_cast(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 diff --git a/src/backend_x64/disassemble_x64.h b/src/backend_x64/disassemble_x64.h new file mode 100644 index 00000000..f1daf7ee --- /dev/null +++ b/src/backend_x64/disassemble_x64.h @@ -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 + +namespace Dynarmic::BackendX64 { + +std::string DisassembleX64(const void* pos, const void* end); + +} // namespace Dynarmic::BackendX64