diff --git a/plugins/disassembler/include/content/views/view_disassembler.hpp b/plugins/disassembler/include/content/views/view_disassembler.hpp index ec87d974c..5fce2d71c 100644 --- a/plugins/disassembler/include/content/views/view_disassembler.hpp +++ b/plugins/disassembler/include/content/views/view_disassembler.hpp @@ -31,9 +31,10 @@ namespace hex::plugin::disasm { private: TaskHolder m_disassemblerTask; - u64 m_baseAddress = 0; + u64 m_imageLoadAddress = 0; + u64 m_imageBaseAddress = 0; ui::RegionType m_range = ui::RegionType::EntireData; - Region m_codeRegion = { 0, 0 }; + Region m_regionToDisassemble = { }; Architecture m_architecture = Architecture::ARM; cs_mode m_mode = cs_mode(0); diff --git a/plugins/disassembler/romfs/lang/de_DE.json b/plugins/disassembler/romfs/lang/de_DE.json index 7257f25a4..55c9619a6 100644 --- a/plugins/disassembler/romfs/lang/de_DE.json +++ b/plugins/disassembler/romfs/lang/de_DE.json @@ -13,17 +13,18 @@ "hex.disassembler.view.disassembler.arm.cortex_m": "Cortex-M", "hex.disassembler.view.disassembler.arm.default": "Standard", "hex.disassembler.view.disassembler.arm.thumb": "Thumb", - "hex.disassembler.view.disassembler.base": "Basisadresse", "hex.disassembler.view.disassembler.bpf.classic": "Classic", "hex.disassembler.view.disassembler.bpf.extended": "Extended", "hex.disassembler.view.disassembler.disassemble": "Disassemble", - "hex.disassembler.view.disassembler.export": "Exportieren", - "hex.disassembler.view.disassembler.export.popup.error": "Der Export zur ASM-Datei ist fehlgeschlagen.", "hex.disassembler.view.disassembler.disassembling": "Disassemblen...", "hex.disassembler.view.disassembler.disassembly.address": "Adresse", "hex.disassembler.view.disassembler.disassembly.bytes": "Byte", "hex.disassembler.view.disassembler.disassembly.offset": "Offset", "hex.disassembler.view.disassembler.disassembly.title": "Disassembly", + "hex.disassembler.view.disassembler.export": "Exportieren", + "hex.disassembler.view.disassembler.export.popup.error": "Der Export zur ASM-Datei ist fehlgeschlagen.", + "hex.disassembler.view.disassembler.image_load_address": "Load Adresse", + "hex.disassembler.view.disassembler.image_base_address": "Image Basisadresse", "hex.disassembler.view.disassembler.m680x.6301": "6301", "hex.disassembler.view.disassembler.m680x.6309": "6309", "hex.disassembler.view.disassembler.m680x.6800": "6800", diff --git a/plugins/disassembler/romfs/lang/en_US.json b/plugins/disassembler/romfs/lang/en_US.json index ef44b96c5..073c0b0d5 100644 --- a/plugins/disassembler/romfs/lang/en_US.json +++ b/plugins/disassembler/romfs/lang/en_US.json @@ -13,17 +13,18 @@ "hex.disassembler.view.disassembler.arm.cortex_m": "Cortex-M", "hex.disassembler.view.disassembler.arm.default": "Default", "hex.disassembler.view.disassembler.arm.thumb": "Thumb", - "hex.disassembler.view.disassembler.base": "Base address", "hex.disassembler.view.disassembler.bpf.classic": "Classic", "hex.disassembler.view.disassembler.bpf.extended": "Extended", + "hex.disassembler.view.disassembler.image_base_address": "Image Base Address", "hex.disassembler.view.disassembler.disassemble": "Disassemble", - "hex.disassembler.view.disassembler.export": "Export instructions as...", - "hex.disassembler.view.disassembler.export.popup.error": "Failed to export to ASM file!", "hex.disassembler.view.disassembler.disassembling": "Disassembling...", "hex.disassembler.view.disassembler.disassembly.address": "Address", "hex.disassembler.view.disassembler.disassembly.bytes": "Byte", "hex.disassembler.view.disassembler.disassembly.offset": "Offset", "hex.disassembler.view.disassembler.disassembly.title": "Disassembly", + "hex.disassembler.view.disassembler.export": "Export instructions as...", + "hex.disassembler.view.disassembler.export.popup.error": "Failed to export to ASM file!", + "hex.disassembler.view.disassembler.image_load_address": "Image Load Address", "hex.disassembler.view.disassembler.m680x.6301": "6301", "hex.disassembler.view.disassembler.m680x.6309": "6309", "hex.disassembler.view.disassembler.m680x.6800": "6800", diff --git a/plugins/disassembler/romfs/lang/es_ES.json b/plugins/disassembler/romfs/lang/es_ES.json index f227e6f9b..c8a56df7b 100644 --- a/plugins/disassembler/romfs/lang/es_ES.json +++ b/plugins/disassembler/romfs/lang/es_ES.json @@ -13,7 +13,6 @@ "hex.disassembler.view.disassembler.arm.cortex_m": "", "hex.disassembler.view.disassembler.arm.default": "Estándar", "hex.disassembler.view.disassembler.arm.thumb": "", - "hex.disassembler.view.disassembler.base": "Dirección base", "hex.disassembler.view.disassembler.bpf.classic": "Clásica", "hex.disassembler.view.disassembler.bpf.extended": "Extendida", "hex.disassembler.view.disassembler.disassemble": "Desensamblar", diff --git a/plugins/disassembler/romfs/lang/hu_HU.json b/plugins/disassembler/romfs/lang/hu_HU.json index 1bf93eb02..ca0ff0065 100644 --- a/plugins/disassembler/romfs/lang/hu_HU.json +++ b/plugins/disassembler/romfs/lang/hu_HU.json @@ -13,7 +13,6 @@ "hex.disassembler.view.disassembler.arm.cortex_m": "Cortex-M", "hex.disassembler.view.disassembler.arm.default": "Alapértelmezett", "hex.disassembler.view.disassembler.arm.thumb": "Thumb", - "hex.disassembler.view.disassembler.base": "Alapcím", "hex.disassembler.view.disassembler.bpf.classic": "Klasszikus", "hex.disassembler.view.disassembler.bpf.extended": "Bővített", "hex.disassembler.view.disassembler.disassemble": "Disassemble", diff --git a/plugins/disassembler/romfs/lang/it_IT.json b/plugins/disassembler/romfs/lang/it_IT.json index ca3ae8dbb..028b30cf1 100644 --- a/plugins/disassembler/romfs/lang/it_IT.json +++ b/plugins/disassembler/romfs/lang/it_IT.json @@ -13,7 +13,6 @@ "hex.disassembler.view.disassembler.arm.cortex_m": "Cortex-M", "hex.disassembler.view.disassembler.arm.default": "Default", "hex.disassembler.view.disassembler.arm.thumb": "Thumb", - "hex.disassembler.view.disassembler.base": "Indirizzo di base", "hex.disassembler.view.disassembler.bpf.classic": "Classico", "hex.disassembler.view.disassembler.bpf.extended": "Esteso", "hex.disassembler.view.disassembler.disassemble": "Disassembla", diff --git a/plugins/disassembler/romfs/lang/ja_JP.json b/plugins/disassembler/romfs/lang/ja_JP.json index 4156268b4..dec83d12b 100644 --- a/plugins/disassembler/romfs/lang/ja_JP.json +++ b/plugins/disassembler/romfs/lang/ja_JP.json @@ -13,7 +13,6 @@ "hex.disassembler.view.disassembler.arm.cortex_m": "Cortex-M", "hex.disassembler.view.disassembler.arm.default": "デフォルト", "hex.disassembler.view.disassembler.arm.thumb": "Thumb", - "hex.disassembler.view.disassembler.base": "ベースアドレス", "hex.disassembler.view.disassembler.bpf.classic": "クラシック", "hex.disassembler.view.disassembler.bpf.extended": "拡張", "hex.disassembler.view.disassembler.disassemble": "逆アセンブル", diff --git a/plugins/disassembler/romfs/lang/ko_KR.json b/plugins/disassembler/romfs/lang/ko_KR.json index cc579972b..9704cd060 100644 --- a/plugins/disassembler/romfs/lang/ko_KR.json +++ b/plugins/disassembler/romfs/lang/ko_KR.json @@ -13,7 +13,6 @@ "hex.disassembler.view.disassembler.arm.cortex_m": "Cortex-M", "hex.disassembler.view.disassembler.arm.default": "기본", "hex.disassembler.view.disassembler.arm.thumb": "Thumb", - "hex.disassembler.view.disassembler.base": "베이스 주소", "hex.disassembler.view.disassembler.bpf.classic": "클래식", "hex.disassembler.view.disassembler.bpf.extended": "확장", "hex.disassembler.view.disassembler.disassemble": "디스어셈블", diff --git a/plugins/disassembler/romfs/lang/pt_BR.json b/plugins/disassembler/romfs/lang/pt_BR.json index 03ede52a6..bdee4f62f 100644 --- a/plugins/disassembler/romfs/lang/pt_BR.json +++ b/plugins/disassembler/romfs/lang/pt_BR.json @@ -13,7 +13,6 @@ "hex.disassembler.view.disassembler.arm.cortex_m": "Cortex-M", "hex.disassembler.view.disassembler.arm.default": "Default", "hex.disassembler.view.disassembler.arm.thumb": "Thumb", - "hex.disassembler.view.disassembler.base": "Endereço base", "hex.disassembler.view.disassembler.bpf.classic": "Classico", "hex.disassembler.view.disassembler.bpf.extended": "Extendido", "hex.disassembler.view.disassembler.disassemble": "Desmontar", diff --git a/plugins/disassembler/romfs/lang/zh_CN.json b/plugins/disassembler/romfs/lang/zh_CN.json index 0db4338a1..731895bb1 100644 --- a/plugins/disassembler/romfs/lang/zh_CN.json +++ b/plugins/disassembler/romfs/lang/zh_CN.json @@ -13,7 +13,6 @@ "hex.disassembler.view.disassembler.arm.cortex_m": "Cortex-M", "hex.disassembler.view.disassembler.arm.default": "默认", "hex.disassembler.view.disassembler.arm.thumb": "Thumb", - "hex.disassembler.view.disassembler.base": "基地址", "hex.disassembler.view.disassembler.bpf.classic": "传统 BPF(cBPF)", "hex.disassembler.view.disassembler.bpf.extended": "扩展 BPF(eBPF)", "hex.disassembler.view.disassembler.disassemble": "反汇编", diff --git a/plugins/disassembler/romfs/lang/zh_TW.json b/plugins/disassembler/romfs/lang/zh_TW.json index 135838631..32fdbb119 100644 --- a/plugins/disassembler/romfs/lang/zh_TW.json +++ b/plugins/disassembler/romfs/lang/zh_TW.json @@ -13,7 +13,6 @@ "hex.disassembler.view.disassembler.arm.cortex_m": "Cortex-M", "hex.disassembler.view.disassembler.arm.default": "預設", "hex.disassembler.view.disassembler.arm.thumb": "Thumb", - "hex.disassembler.view.disassembler.base": "基址", "hex.disassembler.view.disassembler.bpf.classic": "經典", "hex.disassembler.view.disassembler.bpf.extended": "擴充", "hex.disassembler.view.disassembler.disassemble": "解譯", diff --git a/plugins/disassembler/source/content/views/view_disassembler.cpp b/plugins/disassembler/source/content/views/view_disassembler.cpp index 978ccaf10..9dfe64bdd 100644 --- a/plugins/disassembler/source/content/views/view_disassembler.cpp +++ b/plugins/disassembler/source/content/views/view_disassembler.cpp @@ -9,7 +9,10 @@ #include #include +#include + using namespace std::literals::string_literals; +using namespace wolv::literals; namespace hex::plugin::disasm { @@ -23,7 +26,7 @@ namespace hex::plugin::disasm { this->getWindowOpenState() = true; m_range = ui::RegionType::Region; - m_codeRegion = ImHexApi::HexEditor::getSelection()->getRegion(); + m_regionToDisassemble = ImHexApi::HexEditor::getSelection()->getRegion(); this->disassemble(); }, [this]{ @@ -40,9 +43,12 @@ namespace hex::plugin::disasm { void ViewDisassembler::disassemble() { m_disassembly.clear(); - m_disassemblerTask = TaskManager::createTask("hex.disassembler.view.disassembler.disassembling"_lang, m_codeRegion.getSize(), [this](auto &task) { + if (m_regionToDisassemble.getStartAddress() < m_imageBaseAddress) + return; + + m_disassemblerTask = TaskManager::createTask("hex.disassembler.view.disassembler.disassembling"_lang, m_regionToDisassemble.getSize(), [this](auto &task) { csh capstoneHandle; - cs_insn *instructions = nullptr; + cs_insn instruction; cs_mode mode = m_mode; @@ -53,52 +59,45 @@ namespace hex::plugin::disasm { cs_option(capstoneHandle, CS_OPT_SKIPDATA, CS_OPT_ON); auto provider = ImHexApi::Provider::get(); - std::vector buffer(2048, 0x00); - size_t size = m_codeRegion.getSize(); + std::vector buffer(1_MiB, 0x00); + + const u64 codeOffset = m_regionToDisassemble.getStartAddress() - m_imageBaseAddress; // Read the data in chunks and disassemble it - for (u64 address = 0; address < size; address += 2048) { - task.update(address); + u64 instructionLoadAddress = m_imageLoadAddress + codeOffset; + u64 instructionDataAddress = m_regionToDisassemble.getStartAddress(); + bool hadError = false; + while (instructionDataAddress < m_regionToDisassemble.getEndAddress()) { // Read a chunk of data - size_t bufferSize = std::min(u64(2048), (size - address)); - provider->read(m_codeRegion.getStartAddress() + address, buffer.data(), bufferSize); + size_t bufferSize = std::min(buffer.size(), (m_regionToDisassemble.getEndAddress() - instructionDataAddress)); + provider->read(instructionDataAddress, buffer.data(), bufferSize); // Ask capstone to disassemble the data - size_t instructionCount = cs_disasm(capstoneHandle, buffer.data(), bufferSize, m_baseAddress + address, 0, &instructions); - if (instructionCount == 0) - break; + const u8 *code = buffer.data(); + while (cs_disasm_iter(capstoneHandle, &code, &bufferSize, &instructionLoadAddress, &instruction)) { + task.update(instructionDataAddress); - // Reserve enough space for the disassembly - m_disassembly.reserve(m_disassembly.size() + instructionCount); - - // Convert the capstone instructions to our disassembly format - u64 usedBytes = 0; - for (u32 i = 0; i < instructionCount; i++) { - const auto &instr = instructions[i]; + // Convert the capstone instructions to our disassembly format Disassembly disassembly = { }; - disassembly.address = instr.address; - disassembly.offset = m_codeRegion.getStartAddress() + address + usedBytes; - disassembly.size = instr.size; - disassembly.mnemonic = instr.mnemonic; - disassembly.operators = instr.op_str; + disassembly.address = instruction.address; + disassembly.offset = instructionDataAddress - m_imageBaseAddress; + disassembly.size = instruction.size; + disassembly.mnemonic = instruction.mnemonic; + disassembly.operators = instruction.op_str; - for (u16 j = 0; j < instr.size; j++) - disassembly.bytes += hex::format("{0:02X} ", instr.bytes[j]); + for (u16 j = 0; j < instruction.size; j++) + disassembly.bytes += hex::format("{0:02X} ", instruction.bytes[j]); disassembly.bytes.pop_back(); m_disassembly.push_back(disassembly); - usedBytes += instr.size; + instructionDataAddress += instruction.size; + hadError = false; } - // 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 - if (instructionCount < bufferSize) - address -= (bufferSize - usedBytes); - - // Clean up the capstone instructions - cs_free(instructions, instructionCount); + if (hadError) break; + hadError = true; } cs_close(&capstoneHandle); @@ -141,11 +140,18 @@ namespace hex::plugin::disasm { if (ImHexApi::Provider::isValid() && provider->isReadable()) { ImGuiExt::Header("hex.disassembler.view.disassembler.position"_lang, true); - // Draw base address input - ImGuiExt::InputHexadecimal("hex.disassembler.view.disassembler.base"_lang, &m_baseAddress, ImGuiInputTextFlags_CharsHexadecimal); - // Draw region selection picker - ui::regionSelectionPicker(&m_codeRegion, provider, &m_range); + ui::regionSelectionPicker(&m_regionToDisassemble, provider, &m_range); + + // Draw base address input + ImGuiExt::InputHexadecimal("hex.disassembler.view.disassembler.image_load_address"_lang, &m_imageLoadAddress, ImGuiInputTextFlags_CharsHexadecimal); + + // Draw code region start address input + ImGui::BeginDisabled(m_range == ui::RegionType::EntireData); + { + ImGuiExt::InputHexadecimal("hex.disassembler.view.disassembler.image_base_address"_lang, &m_imageBaseAddress, ImGuiInputTextFlags_CharsHexadecimal); + } + ImGui::EndDisabled(); // Draw settings { @@ -427,7 +433,7 @@ namespace hex::plugin::disasm { } // Draw disassemble button - ImGui::BeginDisabled(m_disassemblerTask.isRunning()); + ImGui::BeginDisabled(m_disassemblerTask.isRunning() || m_regionToDisassemble.getStartAddress() < m_imageBaseAddress); { if (ImGui::Button("hex.disassembler.view.disassembler.disassemble"_lang)) this->disassemble();