From 6ce8bfaf32dc62855d39aa1238dea81aa53c12f0 Mon Sep 17 00:00:00 2001 From: Ben <16092757+Avuxo@users.noreply.github.com> Date: Thu, 16 Sep 2021 16:45:20 -0400 Subject: [PATCH] Add API function to retrieve dissassembly as vector of strings (#644) Co-authored-by: ben --- src/dynarmic/backend/x64/a32_interface.cpp | 6 +++++- src/dynarmic/backend/x64/a64_interface.cpp | 11 +++++++++- src/dynarmic/common/fp/unpacked.h | 2 +- src/dynarmic/common/x64_disassemble.cpp | 25 ++++++++++++++++++++-- src/dynarmic/common/x64_disassemble.h | 9 +++++++- src/dynarmic/interface/A32/a32.h | 7 ++++++ src/dynarmic/interface/A64/a64.h | 7 ++++++ 7 files changed, 61 insertions(+), 6 deletions(-) diff --git a/src/dynarmic/backend/x64/a32_interface.cpp b/src/dynarmic/backend/x64/a32_interface.cpp index 69dfce08..24b48c03 100644 --- a/src/dynarmic/backend/x64/a32_interface.cpp +++ b/src/dynarmic/backend/x64/a32_interface.cpp @@ -318,8 +318,12 @@ void Jit::LoadContext(const Context& ctx) { } void Jit::DumpDisassembly() const { - const size_t size = (const char*)impl->block_of_code.getCurr() - (const char*)impl->block_of_code.GetCodeBegin(); + const size_t size = reinterpret_cast(impl->block_of_code.getCurr()) - reinterpret_cast(impl->block_of_code.GetCodeBegin()); Common::DumpDisassembledX64(impl->block_of_code.GetCodeBegin(), size); } +std::vector Jit::Disassemble() const { + const size_t size = reinterpret_cast(impl->block_of_code.getCurr()) - reinterpret_cast(impl->block_of_code.GetCodeBegin()); + return Common::DisassembleX64(impl->block_of_code.GetCodeBegin(), size); +} } // namespace Dynarmic::A32 diff --git a/src/dynarmic/backend/x64/a64_interface.cpp b/src/dynarmic/backend/x64/a64_interface.cpp index 4dc68c2f..26713a9c 100644 --- a/src/dynarmic/backend/x64/a64_interface.cpp +++ b/src/dynarmic/backend/x64/a64_interface.cpp @@ -200,10 +200,15 @@ public: } void DumpDisassembly() const { - const size_t size = (const char*)block_of_code.getCurr() - (const char*)block_of_code.GetCodeBegin(); + const size_t size = reinterpret_cast(block_of_code.getCurr()) - reinterpret_cast(block_of_code.GetCodeBegin()); Common::DumpDisassembledX64(block_of_code.GetCodeBegin(), size); } + std::vector Disassemble() const { + const size_t size = reinterpret_cast(block_of_code.getCurr()) - reinterpret_cast(block_of_code.GetCodeBegin()); + return Common::DisassembleX64(block_of_code.GetCodeBegin(), size); + } + private: static CodePtr GetCurrentBlockThunk(void* thisptr) { Jit::Impl* this_ = static_cast(thisptr); @@ -402,4 +407,8 @@ void Jit::DumpDisassembly() const { return impl->DumpDisassembly(); } +std::vector Jit::Disassemble() const { + return impl->Disassemble(); +} + } // namespace Dynarmic::A64 diff --git a/src/dynarmic/common/fp/unpacked.h b/src/dynarmic/common/fp/unpacked.h index e77c87a5..5b252805 100644 --- a/src/dynarmic/common/fp/unpacked.h +++ b/src/dynarmic/common/fp/unpacked.h @@ -46,7 +46,7 @@ constexpr FPUnpacked ToNormalized(bool sign, int exponent, u64 value) { const int highest_bit = Common::HighestSetBit(value); const int offset = static_cast(normalized_point_position) - highest_bit; value <<= offset; - exponent -= offset - normalized_point_position; + exponent -= offset - static_cast(normalized_point_position); return {sign, exponent, value}; } diff --git a/src/dynarmic/common/x64_disassemble.cpp b/src/dynarmic/common/x64_disassemble.cpp index 0cfb204d..ce32028d 100644 --- a/src/dynarmic/common/x64_disassemble.cpp +++ b/src/dynarmic/common/x64_disassemble.cpp @@ -21,15 +21,36 @@ void DumpDisassembledX64(const void* ptr, size_t size) { size_t offset = 0; ZydisDecodedInstruction instruction; - while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(&decoder, (const char*)ptr + offset, size - offset, &instruction))) { + while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(&decoder, static_cast(ptr) + offset, size - offset, &instruction))) { fmt::print("{:016x} ", (u64)ptr + offset); char buffer[256]; - ZydisFormatterFormatInstruction(&formatter, &instruction, buffer, sizeof(buffer), (u64)ptr + offset); + ZydisFormatterFormatInstruction(&formatter, &instruction, buffer, sizeof(buffer), reinterpret_cast(ptr) + offset); puts(buffer); offset += instruction.length; } } +std::vector DisassembleX64(const void* ptr, size_t size) { + std::vector result; + ZydisDecoder decoder; + ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_64); + + ZydisFormatter formatter; + ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL); + + size_t offset = 0; + ZydisDecodedInstruction instruction; + while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(&decoder, static_cast(ptr) + offset, size - offset, &instruction))) { + char buffer[256]; + ZydisFormatterFormatInstruction(&formatter, &instruction, buffer, sizeof(buffer), reinterpret_cast(ptr) + offset); + + result.push_back(fmt::format("{:016x} {}", (u64)ptr + offset, buffer)); + + offset += instruction.length; + } + + return result; +} } // namespace Dynarmic::Common diff --git a/src/dynarmic/common/x64_disassemble.h b/src/dynarmic/common/x64_disassemble.h index 4b1e6660..ec7a3378 100644 --- a/src/dynarmic/common/x64_disassemble.h +++ b/src/dynarmic/common/x64_disassemble.h @@ -5,10 +5,17 @@ #pragma once +#include +#include + #include "dynarmic/common/common_types.h" namespace Dynarmic::Common { void DumpDisassembledX64(const void* ptr, size_t size); - +/** + * Disassemble `size' bytes from `ptr' and return the disassembled lines as a vector + * of strings. + */ +std::vector DisassembleX64(const void* ptr, size_t size); } // namespace Dynarmic::Common diff --git a/src/dynarmic/interface/A32/a32.h b/src/dynarmic/interface/A32/a32.h index 99a823e5..c36f9fcb 100644 --- a/src/dynarmic/interface/A32/a32.h +++ b/src/dynarmic/interface/A32/a32.h @@ -9,6 +9,7 @@ #include #include #include +#include #include "dynarmic/interface/A32/config.h" @@ -91,6 +92,12 @@ public: /// Debugging: Dump a disassembly all compiled code to the console. void DumpDisassembly() const; + /** + * Disassemble the instructions following the current pc and return + * the resulting instructions as a vector of their string representations. + */ + std::vector Disassemble() const; + private: bool is_executing = false; diff --git a/src/dynarmic/interface/A64/a64.h b/src/dynarmic/interface/A64/a64.h index 384ad239..d908fc21 100644 --- a/src/dynarmic/interface/A64/a64.h +++ b/src/dynarmic/interface/A64/a64.h @@ -10,6 +10,7 @@ #include #include #include +#include #include "dynarmic/interface/A64/config.h" @@ -117,6 +118,12 @@ public: /// Debugging: Dump a disassembly all of compiled code to the console. void DumpDisassembly() const; + /* + * Disassemble the instructions following the current pc and return + * the resulting instructions as a vector of their string representations. + */ + std::vector Disassemble() const; + private: struct Impl; std::unique_ptr impl;