From 68bd9547c5870aa06cb04227675835159cea01f9 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sun, 7 Feb 2021 20:31:48 +0000 Subject: [PATCH] fuzz_arm: Correctly print thumb instruction listing --- src/common/llvm_disassemble.cpp | 30 ++++++++++++++++++++++++------ src/common/llvm_disassemble.h | 2 +- tests/A32/fuzz_arm.cpp | 7 ++----- tests/print_info.cpp | 2 +- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/common/llvm_disassemble.cpp b/src/common/llvm_disassemble.cpp index 88e79937..d3483107 100644 --- a/src/common/llvm_disassemble.cpp +++ b/src/common/llvm_disassemble.cpp @@ -54,20 +54,38 @@ std::string DisassembleX64(const void* begin, const void* end) { return result; } -std::string DisassembleAArch32([[maybe_unused]] u32 instruction, [[maybe_unused]] u64 pc) { +std::string DisassembleAArch32([[maybe_unused]] bool is_thumb, [[maybe_unused]] u32 pc, [[maybe_unused]] const u8* instructions, [[maybe_unused]] size_t length) { std::string result; #ifdef DYNARMIC_USE_LLVM LLVMInitializeARMTargetInfo(); LLVMInitializeARMTargetMC(); LLVMInitializeARMDisassembler(); - LLVMDisasmContextRef llvm_ctx = LLVMCreateDisasm("armv8-arm", nullptr, 0, nullptr, nullptr); + LLVMDisasmContextRef llvm_ctx = LLVMCreateDisasm(is_thumb ? "thumbv8-arm" : "armv8-arm", nullptr, 0, nullptr, nullptr); LLVMSetDisasmOptions(llvm_ctx, LLVMDisassembler_Option_AsmPrinterVariant); - char buffer[80]; - size_t inst_size = LLVMDisasmInstruction(llvm_ctx, (u8*)&instruction, sizeof(instruction), pc, buffer, sizeof(buffer)); - result = inst_size > 0 ? buffer : ""; - result += '\n'; + char buffer[1024]; + while (length) { + size_t inst_size = LLVMDisasmInstruction(llvm_ctx, const_cast(instructions), length, pc, buffer, sizeof(buffer)); + + result += fmt::format("{:08x} ", pc); + for (size_t i = 0; i < 4; i++) { + if (i < inst_size) { + result += fmt::format("{:02x}", instructions[inst_size - i - 1]); + } else { + result += " "; + } + } + result += inst_size > 0 ? buffer : ""; + result += '\n'; + + if (inst_size == 0) inst_size = is_thumb ? 2 : 4; + if (length <= inst_size) break; + + pc += inst_size; + instructions += inst_size; + length -= inst_size; + } LLVMDisasmDispose(llvm_ctx); #else diff --git a/src/common/llvm_disassemble.h b/src/common/llvm_disassemble.h index a49ca2fd..0d9ac6a9 100644 --- a/src/common/llvm_disassemble.h +++ b/src/common/llvm_disassemble.h @@ -12,7 +12,7 @@ namespace Dynarmic::Common { std::string DisassembleX64(const void* pos, const void* end); -std::string DisassembleAArch32(u32 instruction, u64 pc = 0); +std::string DisassembleAArch32(bool is_thumb, u32 pc, const u8* instructions, size_t length); std::string DisassembleAArch64(u32 instruction, u64 pc = 0); } // namespace Dynarmic::Common diff --git a/tests/A32/fuzz_arm.cpp b/tests/A32/fuzz_arm.cpp index 41b37733..2c69f754 100644 --- a/tests/A32/fuzz_arm.cpp +++ b/tests/A32/fuzz_arm.cpp @@ -16,8 +16,8 @@ #include "common/common_types.h" #include "common/fp/fpcr.h" #include "common/fp/fpsr.h" +#include "common/llvm_disassemble.h" #include "common/scope_exit.h" -#include "frontend/A32/disassembler/disassembler.h" #include "frontend/A32/location_descriptor.h" #include "frontend/A32/translate/translate.h" #include "frontend/A32/types.h" @@ -247,10 +247,7 @@ static void RunTestInstance(Dynarmic::A32::Jit& jit, SCOPE_FAIL { fmt::print("Instruction Listing:\n"); - for (u32 instruction : instructions) { - fmt::print("{:08x} {}\n", instruction, A32::DisassembleArm(instruction)); - } - fmt::print("\n"); + fmt::print("{}\n", Common::DisassembleAArch32(std::is_same_v, initial_pc, (const u8*)instructions.data(), instructions.size() * sizeof(instructions[0]))); fmt::print("Initial register listing:\n"); for (size_t i = 0; i < regs.size(); ++i) { diff --git a/tests/print_info.cpp b/tests/print_info.cpp index ccb1f1d6..48cbf587 100644 --- a/tests/print_info.cpp +++ b/tests/print_info.cpp @@ -54,7 +54,7 @@ const char* GetNameOfA64Instruction(u32 instruction) { } void PrintA32Instruction(u32 instruction) { - fmt::print("{:08x} {}\n", instruction, Common::DisassembleAArch32(instruction)); + fmt::print("{:08x} {}\n", instruction, Common::DisassembleAArch32(false, 0, (u8*)&instruction, sizeof(instruction))); fmt::print("Name: {}\n", GetNameOfA32Instruction(instruction)); const A32::LocationDescriptor location{0, {}, {}};