2021-12-07 22:47:41 +01:00
|
|
|
#include "content/views/view_disassembler.hpp"
|
2020-11-22 23:07:50 +01:00
|
|
|
|
2021-01-13 17:28:27 +01:00
|
|
|
#include <hex/providers/provider.hpp>
|
2021-08-29 22:15:18 +02:00
|
|
|
#include <hex/helpers/fmt.hpp>
|
2020-11-22 23:07:50 +01:00
|
|
|
|
|
|
|
#include <cstring>
|
2021-02-22 11:56:33 +01:00
|
|
|
#include <thread>
|
|
|
|
|
2020-11-22 23:07:50 +01:00
|
|
|
using namespace std::literals::string_literals;
|
|
|
|
|
2021-12-07 22:47:41 +01:00
|
|
|
namespace hex::plugin::builtin {
|
2020-11-22 23:07:50 +01:00
|
|
|
|
2021-12-07 22:47:41 +01:00
|
|
|
ViewDisassembler::ViewDisassembler() : View("hex.builtin.view.disassembler.name") {
|
2022-07-30 22:01:49 +02:00
|
|
|
EventManager::subscribe<EventProviderDeleted>(this, [this](const auto*) {
|
2021-12-05 22:09:43 +01:00
|
|
|
this->m_disassembly.clear();
|
|
|
|
});
|
2020-11-22 23:07:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ViewDisassembler::~ViewDisassembler() {
|
2021-03-27 11:36:36 +01:00
|
|
|
EventManager::unsubscribe<EventDataChanged>(this);
|
|
|
|
EventManager::unsubscribe<EventRegionSelected>(this);
|
2022-07-30 22:01:49 +02:00
|
|
|
EventManager::unsubscribe<EventProviderDeleted>(this);
|
2020-11-22 23:07:50 +01:00
|
|
|
}
|
|
|
|
|
2021-02-22 11:56:33 +01:00
|
|
|
void ViewDisassembler::disassemble() {
|
|
|
|
this->m_disassembly.clear();
|
2020-11-22 23:07:50 +01:00
|
|
|
|
2022-08-17 16:15:36 +02:00
|
|
|
this->m_disassemblerTask = TaskManager::createTask("hex.builtin.view.disassembler.disassembling", this->m_codeRegion.getSize(), [this](auto &task) {
|
2020-11-22 23:07:50 +01:00
|
|
|
csh capstoneHandle;
|
|
|
|
cs_insn *instructions = nullptr;
|
|
|
|
|
2022-01-24 23:56:02 +01:00
|
|
|
cs_mode mode = this->m_mode;
|
2020-11-22 23:07:50 +01:00
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
// Create a capstone disassembler instance
|
2022-03-04 20:52:39 +01:00
|
|
|
if (cs_open(Disassembler::toCapstoneArchitecture(this->m_architecture), mode, &capstoneHandle) == CS_ERR_OK) {
|
2020-11-22 23:07:50 +01:00
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
// Tell capstone to skip data bytes
|
2021-05-23 23:04:20 +02:00
|
|
|
cs_option(capstoneHandle, CS_OPT_SKIPDATA, CS_OPT_ON);
|
|
|
|
|
2021-09-21 02:29:54 +02:00
|
|
|
auto provider = ImHexApi::Provider::get();
|
2020-11-22 23:07:50 +01:00
|
|
|
std::vector<u8> buffer(2048, 0x00);
|
2022-08-07 12:20:40 +02:00
|
|
|
size_t size = this->m_codeRegion.getSize();
|
2021-12-16 23:48:52 +01:00
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
// Read the data in chunks and disassemble it
|
2021-12-16 23:48:52 +01:00
|
|
|
for (u64 address = 0; address < size; address += 2048) {
|
|
|
|
task.update(address);
|
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
// Read a chunk of data
|
2022-08-07 12:20:40 +02:00
|
|
|
size_t bufferSize = std::min(u64(2048), (size - address));
|
|
|
|
provider->read(this->m_codeRegion.getStartAddress() + address, buffer.data(), bufferSize);
|
2020-11-22 23:07:50 +01:00
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
// Ask capstone to disassemble the data
|
2020-11-28 16:15:12 +01:00
|
|
|
size_t instructionCount = cs_disasm(capstoneHandle, buffer.data(), bufferSize, this->m_baseAddress + address, 0, &instructions);
|
2020-11-22 23:07:50 +01:00
|
|
|
if (instructionCount == 0)
|
|
|
|
break;
|
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
// Reserve enough space for the disassembly
|
2022-01-24 23:56:02 +01:00
|
|
|
this->m_disassembly.reserve(this->m_disassembly.size() + instructionCount);
|
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
// Convert the capstone instructions to our disassembly format
|
2020-11-22 23:07:50 +01:00
|
|
|
u64 usedBytes = 0;
|
2022-01-24 23:56:02 +01:00
|
|
|
for (u32 i = 0; i < instructionCount; i++) {
|
2022-02-01 22:09:44 +01:00
|
|
|
const auto &instr = instructions[i];
|
2022-03-27 00:01:28 +01:00
|
|
|
Disassembly disassembly = { };
|
2022-02-01 22:09:44 +01:00
|
|
|
disassembly.address = instr.address;
|
2022-08-07 12:20:40 +02:00
|
|
|
disassembly.offset = this->m_codeRegion.getStartAddress() + address + usedBytes;
|
2022-02-01 22:09:44 +01:00
|
|
|
disassembly.size = instr.size;
|
|
|
|
disassembly.mnemonic = instr.mnemonic;
|
|
|
|
disassembly.operators = instr.op_str;
|
2020-11-22 23:07:50 +01:00
|
|
|
|
2022-01-24 23:56:02 +01:00
|
|
|
for (u16 j = 0; j < instr.size; j++)
|
|
|
|
disassembly.bytes += hex::format("{0:02X} ", instr.bytes[j]);
|
2020-11-22 23:07:50 +01:00
|
|
|
disassembly.bytes.pop_back();
|
|
|
|
|
|
|
|
this->m_disassembly.push_back(disassembly);
|
|
|
|
|
2022-01-24 23:56:02 +01:00
|
|
|
usedBytes += instr.size;
|
2020-11-22 23:07:50 +01:00
|
|
|
}
|
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
// If capstone couldn't disassemble all bytes in the buffer, we might have cut off an instruction
|
|
|
|
// Adjust the address,so it's being disassembled when we read the next chunk
|
2020-11-22 23:07:50 +01:00
|
|
|
if (instructionCount < bufferSize)
|
|
|
|
address -= (bufferSize - usedBytes);
|
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
// Clean up the capstone instructions
|
2020-11-22 23:07:50 +01:00
|
|
|
cs_free(instructions, instructionCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
cs_close(&capstoneHandle);
|
|
|
|
}
|
2022-08-17 16:15:36 +02:00
|
|
|
});
|
2021-02-22 11:56:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ViewDisassembler::drawContent() {
|
2020-11-22 23:07:50 +01:00
|
|
|
|
2021-12-07 22:47:41 +01:00
|
|
|
if (ImGui::Begin(View::toWindowName("hex.builtin.view.disassembler.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
2020-11-22 23:07:50 +01:00
|
|
|
|
2021-09-21 02:29:54 +02:00
|
|
|
auto provider = ImHexApi::Provider::get();
|
|
|
|
if (ImHexApi::Provider::isValid() && provider->isReadable()) {
|
2021-12-07 22:47:41 +01:00
|
|
|
ImGui::TextUnformatted("hex.builtin.view.disassembler.position"_lang);
|
2020-11-28 16:15:12 +01:00
|
|
|
ImGui::Separator();
|
2020-11-22 23:07:50 +01:00
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
// Draw base address input
|
2022-08-07 12:20:40 +02:00
|
|
|
ImGui::InputHexadecimal("hex.builtin.view.disassembler.base"_lang, &this->m_baseAddress, ImGuiInputTextFlags_CharsHexadecimal);
|
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
// Draw region selection picker
|
2023-04-10 14:08:21 +02:00
|
|
|
ui::regionSelectionPicker(&this->m_codeRegion, provider, &this->m_range);
|
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
// Draw settings
|
|
|
|
{
|
|
|
|
ImGui::Header("hex.builtin.common.settings"_lang);
|
|
|
|
|
|
|
|
// Draw architecture selector
|
|
|
|
if (ImGui::Combo("hex.builtin.view.disassembler.arch"_lang, reinterpret_cast<int *>(&this->m_architecture), Disassembler::ArchitectureNames.data(), Disassembler::getArchitectureSupportedCount()))
|
|
|
|
this->m_mode = cs_mode(0);
|
|
|
|
|
|
|
|
// Draw sub-settings for each architecture
|
|
|
|
if (ImGui::BeginChild("modes", ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 6), true, ImGuiWindowFlags_AlwaysAutoResize)) {
|
|
|
|
|
|
|
|
// Draw endian radio buttons. This setting is available for all architectures
|
|
|
|
static int littleEndian = true;
|
|
|
|
ImGui::RadioButton("hex.builtin.common.little_endian"_lang, &littleEndian, true);
|
|
|
|
ImGui::SameLine();
|
|
|
|
ImGui::RadioButton("hex.builtin.common.big_endian"_lang, &littleEndian, false);
|
|
|
|
|
|
|
|
ImGui::NewLine();
|
|
|
|
|
|
|
|
// Draw architecture specific settings
|
|
|
|
switch (this->m_architecture) {
|
|
|
|
case Architecture::ARM:
|
|
|
|
{
|
|
|
|
static int mode = CS_MODE_ARM;
|
|
|
|
ImGui::RadioButton("hex.builtin.view.disassembler.arm.arm"_lang, &mode, CS_MODE_ARM);
|
|
|
|
ImGui::SameLine();
|
|
|
|
ImGui::RadioButton("hex.builtin.view.disassembler.arm.thumb"_lang, &mode, CS_MODE_THUMB);
|
|
|
|
|
|
|
|
static int extraMode = 0;
|
|
|
|
ImGui::RadioButton("hex.builtin.view.disassembler.arm.default"_lang, &extraMode, 0);
|
|
|
|
ImGui::SameLine();
|
|
|
|
ImGui::RadioButton("hex.builtin.view.disassembler.arm.cortex_m"_lang, &extraMode, CS_MODE_MCLASS);
|
|
|
|
ImGui::SameLine();
|
|
|
|
ImGui::RadioButton("hex.builtin.view.disassembler.arm.armv8"_lang, &extraMode, CS_MODE_V8);
|
|
|
|
|
|
|
|
this->m_mode = cs_mode(mode | extraMode);
|
2022-02-01 22:09:44 +01:00
|
|
|
}
|
2023-08-29 12:14:12 +02:00
|
|
|
break;
|
|
|
|
case Architecture::MIPS:
|
|
|
|
{
|
|
|
|
static int mode = CS_MODE_MIPS32;
|
|
|
|
ImGui::RadioButton("hex.builtin.view.disassembler.mips.mips32"_lang, &mode, CS_MODE_MIPS32);
|
|
|
|
ImGui::SameLine();
|
|
|
|
ImGui::RadioButton("hex.builtin.view.disassembler.mips.mips64"_lang, &mode, CS_MODE_MIPS64);
|
|
|
|
ImGui::SameLine();
|
|
|
|
ImGui::RadioButton("hex.builtin.view.disassembler.mips.mips32R6"_lang, &mode, CS_MODE_MIPS32R6);
|
|
|
|
|
|
|
|
ImGui::RadioButton("hex.builtin.view.disassembler.mips.mips2"_lang, &mode, CS_MODE_MIPS2);
|
|
|
|
ImGui::SameLine();
|
|
|
|
ImGui::RadioButton("hex.builtin.view.disassembler.mips.mips3"_lang, &mode, CS_MODE_MIPS3);
|
|
|
|
|
|
|
|
static bool microMode;
|
|
|
|
ImGui::Checkbox("hex.builtin.view.disassembler.mips.micro"_lang, µMode);
|
|
|
|
|
|
|
|
this->m_mode = cs_mode(mode | (microMode ? CS_MODE_MICRO : cs_mode(0)));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Architecture::X86:
|
|
|
|
{
|
|
|
|
static int mode = CS_MODE_32;
|
|
|
|
ImGui::RadioButton("hex.builtin.view.disassembler.16bit"_lang, &mode, CS_MODE_16);
|
|
|
|
ImGui::SameLine();
|
|
|
|
ImGui::RadioButton("hex.builtin.view.disassembler.32bit"_lang, &mode, CS_MODE_32);
|
|
|
|
ImGui::SameLine();
|
|
|
|
ImGui::RadioButton("hex.builtin.view.disassembler.64bit"_lang, &mode, CS_MODE_64);
|
|
|
|
|
|
|
|
this->m_mode = cs_mode(mode);
|
2022-01-24 23:56:02 +01:00
|
|
|
}
|
2023-08-29 12:14:12 +02:00
|
|
|
break;
|
|
|
|
case Architecture::PPC:
|
|
|
|
{
|
|
|
|
static int mode = CS_MODE_32;
|
|
|
|
ImGui::RadioButton("hex.builtin.view.disassembler.32bit"_lang, &mode, CS_MODE_32);
|
|
|
|
ImGui::SameLine();
|
|
|
|
ImGui::RadioButton("hex.builtin.view.disassembler.64bit"_lang, &mode, CS_MODE_64);
|
|
|
|
|
|
|
|
static bool qpx = false;
|
|
|
|
ImGui::Checkbox("hex.builtin.view.disassembler.ppc.qpx"_lang, &qpx);
|
|
|
|
|
|
|
|
#if CS_API_MAJOR >= 5
|
|
|
|
static bool spe = false;
|
|
|
|
ImGui::Checkbox("hex.builtin.view.disassembler.ppc.spe"_lang, &spe);
|
|
|
|
static bool booke = false;
|
|
|
|
ImGui::Checkbox("hex.builtin.view.disassembler.ppc.booke"_lang, &booke);
|
|
|
|
|
|
|
|
this->m_mode = cs_mode(mode | (qpx ? CS_MODE_QPX : cs_mode(0)) | (spe ? CS_MODE_SPE : cs_mode(0)) | (booke ? CS_MODE_BOOKE : cs_mode(0)));
|
|
|
|
#else
|
|
|
|
this->m_mode = cs_mode(mode | (qpx ? CS_MODE_QPX : cs_mode(0)));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Architecture::SPARC:
|
|
|
|
{
|
|
|
|
static bool v9Mode = false;
|
|
|
|
ImGui::Checkbox("hex.builtin.view.disassembler.sparc.v9"_lang, &v9Mode);
|
2022-02-01 22:09:44 +01:00
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
this->m_mode = cs_mode(v9Mode ? CS_MODE_V9 : cs_mode(0));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#if CS_API_MAJOR >= 5
|
|
|
|
case Architecture::RISCV:
|
|
|
|
{
|
|
|
|
static int mode = CS_MODE_RISCV32;
|
|
|
|
ImGui::RadioButton("hex.builtin.view.disassembler.32bit"_lang, &mode, CS_MODE_RISCV32);
|
|
|
|
ImGui::SameLine();
|
|
|
|
ImGui::RadioButton("hex.builtin.view.disassembler.64bit"_lang, &mode, CS_MODE_RISCV64);
|
|
|
|
|
|
|
|
static bool compressed = false;
|
|
|
|
ImGui::Checkbox("hex.builtin.view.disassembler.riscv.compressed"_lang, &compressed);
|
|
|
|
|
|
|
|
this->m_mode = cs_mode(mode | (compressed ? CS_MODE_RISCVC : cs_mode(0)));
|
2022-02-01 22:09:44 +01:00
|
|
|
}
|
2023-08-29 12:14:12 +02:00
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case Architecture::M68K:
|
|
|
|
{
|
|
|
|
static int selectedMode = 0;
|
|
|
|
|
|
|
|
std::pair<const char *, cs_mode> modes[] = {
|
|
|
|
{"hex.builtin.view.disassembler.m68k.000"_lang, CS_MODE_M68K_000},
|
|
|
|
{ "hex.builtin.view.disassembler.m68k.010"_lang, CS_MODE_M68K_010},
|
|
|
|
{ "hex.builtin.view.disassembler.m68k.020"_lang, CS_MODE_M68K_020},
|
|
|
|
{ "hex.builtin.view.disassembler.m68k.030"_lang, CS_MODE_M68K_030},
|
|
|
|
{ "hex.builtin.view.disassembler.m68k.040"_lang, CS_MODE_M68K_040},
|
|
|
|
{ "hex.builtin.view.disassembler.m68k.060"_lang, CS_MODE_M68K_060},
|
|
|
|
};
|
|
|
|
|
|
|
|
if (ImGui::BeginCombo("hex.builtin.view.disassembler.settings.mode"_lang, modes[selectedMode].first)) {
|
|
|
|
for (u32 i = 0; i < IM_ARRAYSIZE(modes); i++) {
|
|
|
|
if (ImGui::Selectable(modes[i].first))
|
|
|
|
selectedMode = i;
|
|
|
|
}
|
|
|
|
ImGui::EndCombo();
|
|
|
|
}
|
2022-01-24 23:56:02 +01:00
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
this->m_mode = cs_mode(modes[selectedMode].second);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Architecture::M680X:
|
|
|
|
{
|
|
|
|
static int selectedMode = 0;
|
|
|
|
|
|
|
|
std::pair<const char *, cs_mode> modes[] = {
|
|
|
|
{"hex.builtin.view.disassembler.m680x.6301"_lang, CS_MODE_M680X_6301 },
|
|
|
|
{ "hex.builtin.view.disassembler.m680x.6309"_lang, CS_MODE_M680X_6309 },
|
|
|
|
{ "hex.builtin.view.disassembler.m680x.6800"_lang, CS_MODE_M680X_6800 },
|
|
|
|
{ "hex.builtin.view.disassembler.m680x.6801"_lang, CS_MODE_M680X_6801 },
|
|
|
|
{ "hex.builtin.view.disassembler.m680x.6805"_lang, CS_MODE_M680X_6805 },
|
|
|
|
{ "hex.builtin.view.disassembler.m680x.6808"_lang, CS_MODE_M680X_6808 },
|
|
|
|
{ "hex.builtin.view.disassembler.m680x.6809"_lang, CS_MODE_M680X_6809 },
|
|
|
|
{ "hex.builtin.view.disassembler.m680x.6811"_lang, CS_MODE_M680X_6811 },
|
|
|
|
{ "hex.builtin.view.disassembler.m680x.cpu12"_lang, CS_MODE_M680X_CPU12},
|
|
|
|
{ "hex.builtin.view.disassembler.m680x.hcs08"_lang, CS_MODE_M680X_HCS08},
|
|
|
|
};
|
|
|
|
|
|
|
|
if (ImGui::BeginCombo("hex.builtin.view.disassembler.settings.mode"_lang, modes[selectedMode].first)) {
|
|
|
|
for (u32 i = 0; i < IM_ARRAYSIZE(modes); i++) {
|
|
|
|
if (ImGui::Selectable(modes[i].first))
|
|
|
|
selectedMode = i;
|
|
|
|
}
|
|
|
|
ImGui::EndCombo();
|
|
|
|
}
|
2022-02-01 22:09:44 +01:00
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
this->m_mode = cs_mode(modes[selectedMode].second);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#if CS_API_MAJOR >= 5
|
|
|
|
case Architecture::MOS65XX:
|
|
|
|
{
|
|
|
|
static int selectedMode = 0;
|
|
|
|
|
|
|
|
std::pair<const char *, cs_mode> modes[] = {
|
|
|
|
{"hex.builtin.view.disassembler.mos65xx.6502"_lang, CS_MODE_MOS65XX_6502 },
|
|
|
|
{ "hex.builtin.view.disassembler.mos65xx.65c02"_lang, CS_MODE_MOS65XX_65C02 },
|
|
|
|
{ "hex.builtin.view.disassembler.mos65xx.w65c02"_lang, CS_MODE_MOS65XX_W65C02 },
|
|
|
|
{ "hex.builtin.view.disassembler.mos65xx.65816"_lang, CS_MODE_MOS65XX_65816 },
|
|
|
|
{ "hex.builtin.view.disassembler.mos65xx.65816_long_m"_lang, CS_MODE_MOS65XX_65816_LONG_M },
|
|
|
|
{ "hex.builtin.view.disassembler.mos65xx.65816_long_x"_lang, CS_MODE_MOS65XX_65816_LONG_X },
|
|
|
|
{ "hex.builtin.view.disassembler.mos65xx.65816_long_mx"_lang, CS_MODE_MOS65XX_65816_LONG_MX},
|
|
|
|
};
|
|
|
|
|
|
|
|
if (ImGui::BeginCombo("hex.builtin.view.disassembler.settings.mode"_lang, modes[selectedMode].first)) {
|
|
|
|
for (u32 i = 0; i < IM_ARRAYSIZE(modes); i++) {
|
|
|
|
if (ImGui::Selectable(modes[i].first))
|
|
|
|
selectedMode = i;
|
|
|
|
}
|
|
|
|
ImGui::EndCombo();
|
2023-08-26 12:21:44 +02:00
|
|
|
}
|
2023-08-29 12:14:12 +02:00
|
|
|
|
|
|
|
this->m_mode = cs_mode(modes[selectedMode].second);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if CS_API_MAJOR >= 5
|
|
|
|
case Architecture::BPF:
|
|
|
|
{
|
|
|
|
static int mode = CS_MODE_BPF_CLASSIC;
|
|
|
|
ImGui::RadioButton("hex.builtin.view.disassembler.bpf.classic"_lang, &mode, CS_MODE_BPF_CLASSIC);
|
|
|
|
ImGui::SameLine();
|
|
|
|
ImGui::RadioButton("hex.builtin.view.disassembler.bpf.extended"_lang, &mode, CS_MODE_BPF_EXTENDED);
|
|
|
|
|
|
|
|
this->m_mode = cs_mode(mode);
|
2023-08-26 12:21:44 +02:00
|
|
|
}
|
2023-08-29 12:14:12 +02:00
|
|
|
break;
|
|
|
|
case Architecture::SH:
|
|
|
|
{
|
|
|
|
static u32 selectionMode = 0;
|
|
|
|
static bool fpu = false;
|
|
|
|
static bool dsp = false;
|
|
|
|
|
|
|
|
std::pair<const char*, cs_mode> modes[] = {
|
|
|
|
{ "hex.builtin.view.disassembler.sh.sh2"_lang, CS_MODE_SH2 },
|
|
|
|
{ "hex.builtin.view.disassembler.sh.sh2a"_lang, CS_MODE_SH2A },
|
|
|
|
{ "hex.builtin.view.disassembler.sh.sh3"_lang, CS_MODE_SH3 },
|
|
|
|
{ "hex.builtin.view.disassembler.sh.sh4"_lang, CS_MODE_SH4 },
|
|
|
|
{ "hex.builtin.view.disassembler.sh.sh4a"_lang, CS_MODE_SH4A },
|
|
|
|
};
|
|
|
|
|
|
|
|
if (ImGui::BeginCombo("hex.builtin.view.disassembler.settings.mode"_lang, modes[selectionMode].first)) {
|
|
|
|
for (u32 i = 0; i < IM_ARRAYSIZE(modes); i++) {
|
|
|
|
if (ImGui::Selectable(modes[i].first))
|
|
|
|
selectionMode = i;
|
|
|
|
}
|
|
|
|
ImGui::EndCombo();
|
|
|
|
}
|
2023-08-26 12:21:44 +02:00
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
ImGui::Checkbox("hex.builtin.view.disassembler.sh.fpu"_lang, &fpu);
|
|
|
|
ImGui::SameLine();
|
|
|
|
ImGui::Checkbox("hex.builtin.view.disassembler.sh.dsp"_lang, &dsp);
|
2023-08-26 12:21:44 +02:00
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
this->m_mode = cs_mode(modes[selectionMode].second | (fpu ? CS_MODE_SHFPU : cs_mode(0)) | (dsp ? CS_MODE_SHDSP : cs_mode(0)));
|
2023-08-26 12:21:44 +02:00
|
|
|
}
|
2023-08-29 12:14:12 +02:00
|
|
|
break;
|
|
|
|
case Architecture::TRICORE:
|
|
|
|
{
|
|
|
|
static u32 selectionMode = 0;
|
|
|
|
|
|
|
|
std::pair<const char*, cs_mode> modes[] = {
|
|
|
|
{ "hex.builtin.view.disassembler.tricore.110"_lang, CS_MODE_TRICORE_110 },
|
|
|
|
{ "hex.builtin.view.disassembler.tricore.120"_lang, CS_MODE_TRICORE_120 },
|
|
|
|
{ "hex.builtin.view.disassembler.tricore.130"_lang, CS_MODE_TRICORE_130 },
|
|
|
|
{ "hex.builtin.view.disassembler.tricore.131"_lang, CS_MODE_TRICORE_131 },
|
|
|
|
{ "hex.builtin.view.disassembler.tricore.160"_lang, CS_MODE_TRICORE_160 },
|
|
|
|
{ "hex.builtin.view.disassembler.tricore.161"_lang, CS_MODE_TRICORE_161 },
|
|
|
|
{ "hex.builtin.view.disassembler.tricore.162"_lang, CS_MODE_TRICORE_162 },
|
|
|
|
};
|
|
|
|
|
|
|
|
if (ImGui::BeginCombo("hex.builtin.view.disassembler.settings.mode"_lang, modes[selectionMode].first)) {
|
|
|
|
for (u32 i = 0; i < IM_ARRAYSIZE(modes); i++) {
|
|
|
|
if (ImGui::Selectable(modes[i].first))
|
|
|
|
selectionMode = i;
|
|
|
|
}
|
|
|
|
ImGui::EndCombo();
|
|
|
|
}
|
2023-08-26 12:21:44 +02:00
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
this->m_mode = cs_mode(modes[selectionMode].second);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Architecture::WASM:
|
|
|
|
#endif
|
|
|
|
case Architecture::EVM:
|
|
|
|
case Architecture::TMS320C64X:
|
|
|
|
case Architecture::ARM64:
|
|
|
|
case Architecture::SYSZ:
|
|
|
|
case Architecture::XCORE:
|
|
|
|
this->m_mode = cs_mode(0);
|
|
|
|
break;
|
|
|
|
}
|
2020-11-22 23:07:50 +01:00
|
|
|
}
|
2023-08-29 12:14:12 +02:00
|
|
|
ImGui::EndChild();
|
2020-11-22 23:07:50 +01:00
|
|
|
}
|
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
// Draw disassemble button
|
2022-08-17 16:15:36 +02:00
|
|
|
ImGui::BeginDisabled(this->m_disassemblerTask.isRunning());
|
2022-05-27 20:42:07 +02:00
|
|
|
{
|
2021-12-07 22:47:41 +01:00
|
|
|
if (ImGui::Button("hex.builtin.view.disassembler.disassemble"_lang))
|
2021-02-22 11:56:33 +01:00
|
|
|
this->disassemble();
|
2022-05-27 20:42:07 +02:00
|
|
|
}
|
|
|
|
ImGui::EndDisabled();
|
2021-02-22 11:56:33 +01:00
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
// Draw a spinner if the disassembler is running
|
2022-08-17 16:15:36 +02:00
|
|
|
if (this->m_disassemblerTask.isRunning()) {
|
2021-02-22 11:56:33 +01:00
|
|
|
ImGui::SameLine();
|
2021-12-07 22:47:41 +01:00
|
|
|
ImGui::TextSpinner("hex.builtin.view.disassembler.disassembling"_lang);
|
2021-02-22 11:56:33 +01:00
|
|
|
}
|
|
|
|
|
2020-11-22 23:07:50 +01:00
|
|
|
ImGui::NewLine();
|
2020-11-28 16:15:12 +01:00
|
|
|
|
2021-12-07 22:47:41 +01:00
|
|
|
ImGui::TextUnformatted("hex.builtin.view.disassembler.disassembly.title"_lang);
|
2020-11-22 23:07:50 +01:00
|
|
|
ImGui::Separator();
|
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
// Draw disassembly table
|
2022-01-24 23:56:02 +01:00
|
|
|
if (ImGui::BeginTable("##disassembly", 4, ImGuiTableFlags_ScrollY | ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable)) {
|
2020-11-23 15:22:26 +01:00
|
|
|
ImGui::TableSetupScrollFreeze(0, 1);
|
2021-12-07 22:47:41 +01:00
|
|
|
ImGui::TableSetupColumn("hex.builtin.view.disassembler.disassembly.address"_lang);
|
|
|
|
ImGui::TableSetupColumn("hex.builtin.view.disassembler.disassembly.offset"_lang);
|
|
|
|
ImGui::TableSetupColumn("hex.builtin.view.disassembler.disassembly.bytes"_lang);
|
|
|
|
ImGui::TableSetupColumn("hex.builtin.view.disassembler.disassembly.title"_lang);
|
2020-11-23 15:22:26 +01:00
|
|
|
|
2022-08-17 16:15:36 +02:00
|
|
|
if (!this->m_disassemblerTask.isRunning()) {
|
2022-01-10 21:38:52 +01:00
|
|
|
ImGuiListClipper clipper;
|
|
|
|
clipper.Begin(this->m_disassembly.size());
|
|
|
|
|
|
|
|
ImGui::TableHeadersRow();
|
|
|
|
while (clipper.Step()) {
|
2022-03-27 00:01:28 +01:00
|
|
|
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
|
2022-01-10 21:38:52 +01:00
|
|
|
const auto &instruction = this->m_disassembly[i];
|
2023-08-29 12:14:12 +02:00
|
|
|
|
2022-01-10 21:38:52 +01:00
|
|
|
ImGui::TableNextRow();
|
|
|
|
ImGui::TableNextColumn();
|
2023-08-29 12:14:12 +02:00
|
|
|
|
|
|
|
// Draw a selectable label for the address
|
|
|
|
ImGui::PushID(i);
|
|
|
|
if (ImGui::Selectable("##DisassemblyLine", false, ImGuiSelectableFlags_SpanAllColumns)) {
|
2022-02-08 18:38:54 +01:00
|
|
|
ImHexApi::HexEditor::setSelection(instruction.offset, instruction.size);
|
2022-01-10 21:38:52 +01:00
|
|
|
}
|
2023-08-29 12:14:12 +02:00
|
|
|
ImGui::PopID();
|
|
|
|
|
|
|
|
// Draw instruction address
|
2022-01-10 21:38:52 +01:00
|
|
|
ImGui::SameLine();
|
|
|
|
ImGui::TextFormatted("0x{0:X}", instruction.address);
|
2023-08-29 12:14:12 +02:00
|
|
|
|
|
|
|
// Draw instruction offset
|
2022-01-10 21:38:52 +01:00
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::TextFormatted("0x{0:X}", instruction.offset);
|
2023-08-29 12:14:12 +02:00
|
|
|
|
|
|
|
// Draw instruction bytes
|
2022-01-10 21:38:52 +01:00
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::TextUnformatted(instruction.bytes.c_str());
|
2023-08-29 12:14:12 +02:00
|
|
|
|
|
|
|
// Draw instruction mnemonic and operands
|
2022-01-10 21:38:52 +01:00
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::TextFormattedColored(ImColor(0xFFD69C56), "{}", instruction.mnemonic);
|
|
|
|
ImGui::SameLine();
|
|
|
|
ImGui::TextUnformatted(instruction.operators.c_str());
|
2020-11-22 23:07:50 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-10 21:38:52 +01:00
|
|
|
clipper.End();
|
|
|
|
}
|
2020-11-22 23:07:50 +01:00
|
|
|
|
2020-11-23 15:22:26 +01:00
|
|
|
ImGui::EndTable();
|
2020-11-22 23:07:50 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ImGui::End();
|
|
|
|
}
|
|
|
|
|
2023-05-20 13:37:45 +02:00
|
|
|
}
|