83 lines
2.8 KiB
C++
83 lines
2.8 KiB
C++
/**
|
|
******************************************************************************
|
|
* Xenia : Xbox 360 Emulator Research Project *
|
|
******************************************************************************
|
|
* Copyright 2015 Ben Vanik. All rights reserved. *
|
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
|
******************************************************************************
|
|
*/
|
|
|
|
#include "Xenia.Debug.Native/disassembler.h"
|
|
|
|
#include "xenia/base/byte_order.h"
|
|
#include "xenia/base/string_buffer.h"
|
|
#include "xenia/cpu/frontend/ppc_disasm.h"
|
|
#include "third_party/capstone/include/capstone.h"
|
|
#include "third_party/capstone/include/x86.h"
|
|
|
|
namespace Xenia {
|
|
namespace Debug {
|
|
namespace Native {
|
|
|
|
using namespace System;
|
|
using namespace System::Text;
|
|
|
|
Disassembler::Disassembler()
|
|
: capstone_handle_(0), string_buffer_(new xe::StringBuffer()) {
|
|
uintptr_t capstone_handle;
|
|
if (cs_open(CS_ARCH_X86, CS_MODE_64, &capstone_handle) != CS_ERR_OK) {
|
|
System::Diagnostics::Debug::Fail("Failed to initialize capstone");
|
|
return;
|
|
}
|
|
capstone_handle_ = capstone_handle;
|
|
cs_option(capstone_handle_, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL);
|
|
cs_option(capstone_handle_, CS_OPT_DETAIL, CS_OPT_OFF);
|
|
}
|
|
|
|
Disassembler::~Disassembler() {
|
|
if (capstone_handle_) {
|
|
pin_ptr<uintptr_t> capstone_handle = &capstone_handle_;
|
|
cs_close(capstone_handle);
|
|
}
|
|
delete string_buffer_;
|
|
}
|
|
|
|
String ^ Disassembler::DisassemblePPC(IntPtr code_address, size_t code_size) {
|
|
string_buffer_->Reset();
|
|
|
|
auto code_base = reinterpret_cast<const uint32_t*>(code_address.ToPointer());
|
|
for (int i = 0; i < code_size / 4; ++i) {
|
|
xe::cpu::frontend::InstrData instr;
|
|
instr.address = uint32_t(code_address.ToInt64()) + i * 4;
|
|
instr.code = xe::byte_swap(code_base[i]);
|
|
instr.type = xe::cpu::frontend::GetInstrType(instr.code);
|
|
string_buffer_->AppendFormat("%.8X %.8X ", instr.address, instr.code);
|
|
xe::cpu::frontend::DisasmPPC(instr, string_buffer_);
|
|
string_buffer_->Append("\r\n");
|
|
}
|
|
|
|
return gcnew String(string_buffer_->ToString());
|
|
}
|
|
|
|
String ^ Disassembler::DisassembleX64(IntPtr code_address, size_t code_size) {
|
|
string_buffer_->Reset();
|
|
|
|
auto code_base = reinterpret_cast<const uint8_t*>(code_address.ToPointer());
|
|
auto code_ptr = code_base;
|
|
size_t remaining_code_size = code_size;
|
|
uint64_t address = uint64_t(code_address.ToInt64());
|
|
cs_insn insn = {0};
|
|
while (remaining_code_size &&
|
|
cs_disasm_iter(capstone_handle_, &code_ptr, &remaining_code_size,
|
|
&address, &insn)) {
|
|
string_buffer_->AppendFormat("%.8X %-6s %s\n", uint32_t(insn.address),
|
|
insn.mnemonic, insn.op_str);
|
|
}
|
|
|
|
return gcnew String(string_buffer_->ToString());
|
|
}
|
|
|
|
} // namespace Native
|
|
} // namespace Debug
|
|
} // namespace Xenia
|