impr: Refactor disassembler system to make it more modular
This commit is contained in:
parent
f11205bba7
commit
a76c6c653d
@ -43,7 +43,6 @@ namespace hex {
|
|||||||
plugins when needed.
|
plugins when needed.
|
||||||
*/
|
*/
|
||||||
namespace ContentRegistry {
|
namespace ContentRegistry {
|
||||||
|
|
||||||
/* Settings Registry. Allows adding of new entries into the ImHex preferences window. */
|
/* Settings Registry. Allows adding of new entries into the ImHex preferences window. */
|
||||||
namespace Settings {
|
namespace Settings {
|
||||||
|
|
||||||
@ -1354,6 +1353,7 @@ namespace hex {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Data Information Registry. Allows adding new analyzers to the data information view */
|
||||||
namespace DataInformation {
|
namespace DataInformation {
|
||||||
|
|
||||||
class InformationSection {
|
class InformationSection {
|
||||||
@ -1420,6 +1420,54 @@ namespace hex {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Disassembler Registry. Allows adding new disassembler architectures */
|
||||||
|
namespace Disassembler {
|
||||||
|
|
||||||
|
struct Instruction {
|
||||||
|
u64 address;
|
||||||
|
u64 offset;
|
||||||
|
size_t size;
|
||||||
|
std::string bytes;
|
||||||
|
std::string mnemonic;
|
||||||
|
std::string operators;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Architecture {
|
||||||
|
public:
|
||||||
|
explicit Architecture(std::string name) : m_name(std::move(name)) {}
|
||||||
|
virtual ~Architecture() = default;
|
||||||
|
|
||||||
|
virtual bool start() = 0;
|
||||||
|
virtual void end() = 0;
|
||||||
|
|
||||||
|
virtual std::optional<Instruction> disassemble(u64 imageBaseAddress, u64 instructionLoadAddress, u64 instructionDataAddress, std::span<const u8> code) = 0;
|
||||||
|
virtual void drawSettings() = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] const std::string& getName() const { return m_name; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace impl {
|
||||||
|
|
||||||
|
using CreatorFunction = std::function<std::unique_ptr<Architecture>()>;
|
||||||
|
|
||||||
|
void addArchitectureCreator(CreatorFunction function);
|
||||||
|
|
||||||
|
const std::map<std::string, CreatorFunction>& getArchitectures();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::derived_from<Architecture> T>
|
||||||
|
void add(auto && ...args) {
|
||||||
|
impl::addArchitectureCreator([args...] {
|
||||||
|
return std::make_unique<T>(std::forward<decltype(args)>(args)...);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1391,4 +1391,23 @@ namespace hex {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace ContentRegistry::Disassembler {
|
||||||
|
|
||||||
|
namespace impl {
|
||||||
|
|
||||||
|
static AutoReset<std::map<std::string, impl::CreatorFunction>> s_architectures;
|
||||||
|
|
||||||
|
void addArchitectureCreator(impl::CreatorFunction function) {
|
||||||
|
const auto arch = function();
|
||||||
|
(*s_architectures)[arch->getName()] = std::move(function);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::map<std::string, impl::CreatorFunction>& getArchitectures() {
|
||||||
|
return *s_architectures;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ namespace hex::plugin::builtin {
|
|||||||
void drawContent() override {
|
void drawContent() override {
|
||||||
ImGuiExt::TextFormattedWrapped("hex.builtin.popup.crash_recover.message"_lang);
|
ImGuiExt::TextFormattedWrapped("hex.builtin.popup.crash_recover.message"_lang);
|
||||||
|
|
||||||
ImGuiExt::TextFormattedWrapped(hex::format("Error: {}: {}", llvm::itaniumDemangle(this->m_errorType), this->m_errorMessage));
|
ImGuiExt::TextFormattedWrapped(hex::format("Error: {}: {}", llvm::demangle(this->m_errorType), this->m_errorMessage));
|
||||||
|
|
||||||
if (ImGui::Button("hex.ui.common.okay"_lang)) {
|
if (ImGui::Button("hex.ui.common.okay"_lang)) {
|
||||||
this->close();
|
this->close();
|
||||||
|
@ -25,6 +25,8 @@ add_imhex_plugin(
|
|||||||
|
|
||||||
source/content/pl_visualizers/disassembler.cpp
|
source/content/pl_visualizers/disassembler.cpp
|
||||||
source/content/pl_builtin_types.cpp
|
source/content/pl_builtin_types.cpp
|
||||||
|
|
||||||
|
source/content/disassemblers/capstone_architectures.cpp
|
||||||
INCLUDES
|
INCLUDES
|
||||||
include
|
include
|
||||||
${CAPSTONE_INCLUDE_DIR}
|
${CAPSTONE_INCLUDE_DIR}
|
||||||
|
@ -6,10 +6,11 @@
|
|||||||
|
|
||||||
#include <capstone/capstone.h>
|
#include <capstone/capstone.h>
|
||||||
#include <wolv/utils/string.hpp>
|
#include <wolv/utils/string.hpp>
|
||||||
|
#include <hex/helpers/utils.hpp>
|
||||||
|
|
||||||
namespace hex::plugin::disasm {
|
namespace hex::plugin::disasm {
|
||||||
|
|
||||||
enum class Architecture : i32
|
enum class BuiltinArchitecture : i32
|
||||||
{
|
{
|
||||||
ARM = CS_ARCH_ARM,
|
ARM = CS_ARCH_ARM,
|
||||||
ARM64 = CS_ARCH_ARM64,
|
ARM64 = CS_ARCH_ARM64,
|
||||||
@ -39,18 +40,18 @@ namespace hex::plugin::disasm {
|
|||||||
MIN = ARM
|
MIN = ARM
|
||||||
};
|
};
|
||||||
|
|
||||||
class Disassembler {
|
class CapstoneDisassembler {
|
||||||
public:
|
public:
|
||||||
constexpr static cs_arch toCapstoneArchitecture(Architecture architecture) {
|
constexpr static cs_arch toCapstoneArchitecture(BuiltinArchitecture architecture) {
|
||||||
return static_cast<cs_arch>(architecture);
|
return static_cast<cs_arch>(architecture);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isSupported(Architecture architecture) {
|
static bool isSupported(BuiltinArchitecture architecture) {
|
||||||
return cs_support(toCapstoneArchitecture(architecture));
|
return cs_support(toCapstoneArchitecture(architecture));
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr static auto ArchitectureNames = []{
|
constexpr static auto ArchitectureNames = []{
|
||||||
std::array<const char *, static_cast<u32>(Architecture::MAX) + 1> names = { };
|
std::array<const char *, static_cast<u32>(BuiltinArchitecture::MAX) + 1> names = { };
|
||||||
|
|
||||||
names[CS_ARCH_ARM] = "ARM";
|
names[CS_ARCH_ARM] = "ARM";
|
||||||
names[CS_ARCH_ARM64] = "AArch64";
|
names[CS_ARCH_ARM64] = "AArch64";
|
||||||
@ -84,7 +85,7 @@ namespace hex::plugin::disasm {
|
|||||||
return supportedCount;
|
return supportedCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (supportedCount = static_cast<i32>(Architecture::MIN); supportedCount < static_cast<i32>(Architecture::MAX) + 1; supportedCount++) {
|
for (supportedCount = static_cast<i32>(BuiltinArchitecture::MIN); supportedCount < static_cast<i32>(BuiltinArchitecture::MAX) + 1; supportedCount++) {
|
||||||
if (!cs_support(supportedCount)) {
|
if (!cs_support(supportedCount)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -9,18 +9,10 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <hex/api/content_registry.hpp>
|
||||||
|
|
||||||
namespace hex::plugin::disasm {
|
namespace hex::plugin::disasm {
|
||||||
|
|
||||||
struct Disassembly {
|
|
||||||
u64 address;
|
|
||||||
u64 offset;
|
|
||||||
size_t size;
|
|
||||||
std::string bytes;
|
|
||||||
std::string mnemonic;
|
|
||||||
std::string operators;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ViewDisassembler : public View::Window {
|
class ViewDisassembler : public View::Window {
|
||||||
public:
|
public:
|
||||||
explicit ViewDisassembler();
|
explicit ViewDisassembler();
|
||||||
@ -36,10 +28,9 @@ namespace hex::plugin::disasm {
|
|||||||
ui::RegionType m_range = ui::RegionType::EntireData;
|
ui::RegionType m_range = ui::RegionType::EntireData;
|
||||||
Region m_regionToDisassemble = { };
|
Region m_regionToDisassemble = { };
|
||||||
|
|
||||||
Architecture m_architecture = Architecture::ARM;
|
std::unique_ptr<ContentRegistry::Disassembler::Architecture> m_currArchitecture = nullptr;
|
||||||
cs_mode m_mode = cs_mode(0);
|
|
||||||
|
|
||||||
std::vector<Disassembly> m_disassembly;
|
std::vector<ContentRegistry::Disassembler::Instruction> m_disassembly;
|
||||||
|
|
||||||
void disassemble();
|
void disassemble();
|
||||||
void exportToFile();
|
void exportToFile();
|
||||||
|
@ -0,0 +1,444 @@
|
|||||||
|
#include <hex/api/content_registry.hpp>
|
||||||
|
|
||||||
|
#include <content/helpers/disassembler.hpp>
|
||||||
|
#include <hex/helpers/fmt.hpp>
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
|
namespace hex::plugin::disasm {
|
||||||
|
|
||||||
|
class CapstoneArchitecture : public ContentRegistry::Disassembler::Architecture {
|
||||||
|
public:
|
||||||
|
explicit CapstoneArchitecture(BuiltinArchitecture architecture)
|
||||||
|
: Architecture(CapstoneDisassembler::ArchitectureNames[u32(architecture)]),
|
||||||
|
m_architecture(architecture) { }
|
||||||
|
|
||||||
|
bool start() override {
|
||||||
|
auto mode = m_mode;
|
||||||
|
if (m_endian == true) {
|
||||||
|
mode = cs_mode(u32(mode) | CS_MODE_LITTLE_ENDIAN);
|
||||||
|
} else {
|
||||||
|
mode = cs_mode(u32(mode) | CS_MODE_BIG_ENDIAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cs_open(CapstoneDisassembler::toCapstoneArchitecture(m_architecture), mode, &m_handle) != CS_ERR_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
cs_option(m_handle, CS_OPT_SKIPDATA, CS_OPT_ON);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void end() override {
|
||||||
|
cs_close(&m_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawSettings() override {
|
||||||
|
ImGui::RadioButton("hex.ui.common.little_endian"_lang, &m_endian, true);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::RadioButton("hex.ui.common.big_endian"_lang, &m_endian, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<ContentRegistry::Disassembler::Instruction> disassemble(u64 imageBaseAddress, u64 instructionLoadAddress, u64 instructionDataAddress, std::span<const u8> code) override {
|
||||||
|
auto *instruction = cs_malloc(m_handle);
|
||||||
|
ON_SCOPE_EXIT { cs_free(instruction, 1); };
|
||||||
|
|
||||||
|
auto ptr = code.data();
|
||||||
|
auto size = code.size_bytes();
|
||||||
|
|
||||||
|
if (!cs_disasm_iter(m_handle, &ptr, &size, &instructionLoadAddress, instruction)) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentRegistry::Disassembler::Instruction disassembly = { };
|
||||||
|
disassembly.address = instruction->address;
|
||||||
|
disassembly.offset = instructionDataAddress - imageBaseAddress;
|
||||||
|
disassembly.size = instruction->size;
|
||||||
|
disassembly.mnemonic = instruction->mnemonic;
|
||||||
|
disassembly.operators = instruction->op_str;
|
||||||
|
|
||||||
|
for (u16 j = 0; j < instruction->size; j++)
|
||||||
|
disassembly.bytes += hex::format("{0:02X} ", instruction->bytes[j]);
|
||||||
|
disassembly.bytes.pop_back();
|
||||||
|
|
||||||
|
return disassembly;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
BuiltinArchitecture m_architecture;
|
||||||
|
csh m_handle = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
cs_mode m_mode = cs_mode(0);
|
||||||
|
int m_endian = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ArchitectureARM : public CapstoneArchitecture {
|
||||||
|
public:
|
||||||
|
ArchitectureARM() : CapstoneArchitecture(BuiltinArchitecture::ARM) {}
|
||||||
|
|
||||||
|
void drawSettings() override {
|
||||||
|
ImGui::RadioButton("hex.disassembler.view.disassembler.arm.arm"_lang, &m_armMode, CS_MODE_ARM);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::RadioButton("hex.disassembler.view.disassembler.arm.thumb"_lang, &m_armMode, CS_MODE_THUMB);
|
||||||
|
|
||||||
|
ImGui::RadioButton("hex.disassembler.view.disassembler.arm.default"_lang, &m_extraMode, 0);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::RadioButton("hex.disassembler.view.disassembler.arm.cortex_m"_lang, &m_extraMode, CS_MODE_MCLASS);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::RadioButton("hex.disassembler.view.disassembler.arm.armv8"_lang, &m_extraMode, CS_MODE_V8);
|
||||||
|
|
||||||
|
m_mode = cs_mode(m_armMode | m_extraMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_armMode = CS_MODE_ARM, m_extraMode = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ArchitectureARM64 : public CapstoneArchitecture {
|
||||||
|
public:
|
||||||
|
ArchitectureARM64() : CapstoneArchitecture(BuiltinArchitecture::ARM64) {}
|
||||||
|
|
||||||
|
void drawSettings() override { }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ArchitectureMIPS : public CapstoneArchitecture {
|
||||||
|
public:
|
||||||
|
ArchitectureMIPS() : CapstoneArchitecture(BuiltinArchitecture::MIPS) {}
|
||||||
|
|
||||||
|
void drawSettings() override {
|
||||||
|
ImGui::RadioButton("hex.disassembler.view.disassembler.mips.mips32"_lang, &m_mipsMode, CS_MODE_MIPS32);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::RadioButton("hex.disassembler.view.disassembler.mips.mips64"_lang, &m_mipsMode, CS_MODE_MIPS64);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::RadioButton("hex.disassembler.view.disassembler.mips.mips32R6"_lang, &m_mipsMode, CS_MODE_MIPS32R6);
|
||||||
|
|
||||||
|
ImGui::RadioButton("hex.disassembler.view.disassembler.mips.mips2"_lang, &m_mipsMode, CS_MODE_MIPS2);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::RadioButton("hex.disassembler.view.disassembler.mips.mips3"_lang, &m_mipsMode, CS_MODE_MIPS3);
|
||||||
|
|
||||||
|
ImGui::Checkbox("hex.disassembler.view.disassembler.mips.micro"_lang, &m_microMode);
|
||||||
|
|
||||||
|
m_mode = cs_mode(m_mipsMode | (m_microMode ? CS_MODE_MICRO : cs_mode(0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_mipsMode = CS_MODE_MIPS32;
|
||||||
|
bool m_microMode = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ArchitectureX86 : public CapstoneArchitecture {
|
||||||
|
public:
|
||||||
|
ArchitectureX86() : CapstoneArchitecture(BuiltinArchitecture::X86) {}
|
||||||
|
|
||||||
|
void drawSettings() override {
|
||||||
|
ImGui::RadioButton("hex.disassembler.view.disassembler.16bit"_lang, &m_x86Mode, CS_MODE_16);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::RadioButton("hex.disassembler.view.disassembler.32bit"_lang, &m_x86Mode, CS_MODE_32);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::RadioButton("hex.disassembler.view.disassembler.64bit"_lang, &m_x86Mode, CS_MODE_64);
|
||||||
|
|
||||||
|
m_mode = cs_mode(m_x86Mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_x86Mode = CS_MODE_32;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ArchitecturePowerPC : public CapstoneArchitecture {
|
||||||
|
public:
|
||||||
|
ArchitecturePowerPC() : CapstoneArchitecture(BuiltinArchitecture::PPC) {}
|
||||||
|
|
||||||
|
void drawSettings() override {
|
||||||
|
ImGui::RadioButton("hex.disassembler.view.disassembler.32bit"_lang, &m_ppcMode, CS_MODE_32);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::RadioButton("hex.disassembler.view.disassembler.64bit"_lang, &m_ppcMode, CS_MODE_64);
|
||||||
|
|
||||||
|
ImGui::Checkbox("hex.disassembler.view.disassembler.ppc.qpx"_lang, &m_qpx);
|
||||||
|
|
||||||
|
#if CS_API_MAJOR >= 5
|
||||||
|
ImGui::Checkbox("hex.disassembler.view.disassembler.ppc.spe"_lang, &m_spe);
|
||||||
|
ImGui::Checkbox("hex.disassembler.view.disassembler.ppc.booke"_lang, &m_booke);
|
||||||
|
|
||||||
|
m_mode = cs_mode(m_ppcMode | (m_qpx ? CS_MODE_QPX : cs_mode(0)) | (m_spe ? CS_MODE_SPE : cs_mode(0)) | (m_booke ? CS_MODE_BOOKE : cs_mode(0)));
|
||||||
|
#else
|
||||||
|
m_mode = cs_mode(mode | (qpx ? CS_MODE_QPX : cs_mode(0)));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_ppcMode = CS_MODE_32;
|
||||||
|
bool m_qpx = false;
|
||||||
|
bool m_spe = false;
|
||||||
|
bool m_booke = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ArchitectureSPARC : public CapstoneArchitecture {
|
||||||
|
public:
|
||||||
|
ArchitectureSPARC() : CapstoneArchitecture(BuiltinArchitecture::SPARC) {}
|
||||||
|
|
||||||
|
void drawSettings() override {
|
||||||
|
ImGui::Checkbox("hex.disassembler.view.disassembler.sparc.v9"_lang, &m_v9Mode);
|
||||||
|
|
||||||
|
m_mode = cs_mode(m_v9Mode ? CS_MODE_V9 : cs_mode(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_v9Mode = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ArchitectureSystemZ : public CapstoneArchitecture {
|
||||||
|
public:
|
||||||
|
ArchitectureSystemZ() : CapstoneArchitecture(BuiltinArchitecture::SYSZ) {}
|
||||||
|
|
||||||
|
void drawSettings() override { }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ArchitectureXCore : public CapstoneArchitecture {
|
||||||
|
public:
|
||||||
|
ArchitectureXCore() : CapstoneArchitecture(BuiltinArchitecture::XCORE) {}
|
||||||
|
|
||||||
|
void drawSettings() override { }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ArchitectureM68K : public CapstoneArchitecture {
|
||||||
|
public:
|
||||||
|
ArchitectureM68K() : CapstoneArchitecture(BuiltinArchitecture::M68K) {}
|
||||||
|
|
||||||
|
void drawSettings() override {
|
||||||
|
std::pair<const char *, cs_mode> modes[] = {
|
||||||
|
{"hex.disassembler.view.disassembler.m68k.000"_lang, CS_MODE_M68K_000},
|
||||||
|
{ "hex.disassembler.view.disassembler.m68k.010"_lang, CS_MODE_M68K_010},
|
||||||
|
{ "hex.disassembler.view.disassembler.m68k.020"_lang, CS_MODE_M68K_020},
|
||||||
|
{ "hex.disassembler.view.disassembler.m68k.030"_lang, CS_MODE_M68K_030},
|
||||||
|
{ "hex.disassembler.view.disassembler.m68k.040"_lang, CS_MODE_M68K_040},
|
||||||
|
{ "hex.disassembler.view.disassembler.m68k.060"_lang, CS_MODE_M68K_060},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (ImGui::BeginCombo("hex.disassembler.view.disassembler.settings.mode"_lang, modes[m_selectedMode].first)) {
|
||||||
|
for (u32 i = 0; i < IM_ARRAYSIZE(modes); i++) {
|
||||||
|
if (ImGui::Selectable(modes[i].first))
|
||||||
|
m_selectedMode = i;
|
||||||
|
}
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_mode = cs_mode(modes[m_selectedMode].second);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_selectedMode = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ArchitectureTMS320C64X : public CapstoneArchitecture {
|
||||||
|
public:
|
||||||
|
ArchitectureTMS320C64X() : CapstoneArchitecture(BuiltinArchitecture::TMS320C64X) {}
|
||||||
|
|
||||||
|
void drawSettings() override { }
|
||||||
|
};
|
||||||
|
class ArchitectureM680X : public CapstoneArchitecture {
|
||||||
|
public:
|
||||||
|
ArchitectureM680X() : CapstoneArchitecture(BuiltinArchitecture::M680X) {}
|
||||||
|
|
||||||
|
void drawSettings() override {
|
||||||
|
std::pair<const char *, cs_mode> modes[] = {
|
||||||
|
{"hex.disassembler.view.disassembler.m680x.6301"_lang, CS_MODE_M680X_6301 },
|
||||||
|
{ "hex.disassembler.view.disassembler.m680x.6309"_lang, CS_MODE_M680X_6309 },
|
||||||
|
{ "hex.disassembler.view.disassembler.m680x.6800"_lang, CS_MODE_M680X_6800 },
|
||||||
|
{ "hex.disassembler.view.disassembler.m680x.6801"_lang, CS_MODE_M680X_6801 },
|
||||||
|
{ "hex.disassembler.view.disassembler.m680x.6805"_lang, CS_MODE_M680X_6805 },
|
||||||
|
{ "hex.disassembler.view.disassembler.m680x.6808"_lang, CS_MODE_M680X_6808 },
|
||||||
|
{ "hex.disassembler.view.disassembler.m680x.6809"_lang, CS_MODE_M680X_6809 },
|
||||||
|
{ "hex.disassembler.view.disassembler.m680x.6811"_lang, CS_MODE_M680X_6811 },
|
||||||
|
{ "hex.disassembler.view.disassembler.m680x.cpu12"_lang, CS_MODE_M680X_CPU12},
|
||||||
|
{ "hex.disassembler.view.disassembler.m680x.hcs08"_lang, CS_MODE_M680X_HCS08},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (ImGui::BeginCombo("hex.disassembler.view.disassembler.settings.mode"_lang, modes[m_selectedMode].first)) {
|
||||||
|
for (u32 i = 0; i < IM_ARRAYSIZE(modes); i++) {
|
||||||
|
if (ImGui::Selectable(modes[i].first))
|
||||||
|
m_selectedMode = i;
|
||||||
|
}
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_mode = cs_mode(modes[m_selectedMode].second);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_selectedMode = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ArchitectureEVM : public CapstoneArchitecture {
|
||||||
|
public:
|
||||||
|
ArchitectureEVM() : CapstoneArchitecture(BuiltinArchitecture::EVM) {}
|
||||||
|
|
||||||
|
void drawSettings() override { }
|
||||||
|
};
|
||||||
|
|
||||||
|
#if CS_API_MAJOR >= 5
|
||||||
|
|
||||||
|
class ArchitectureWASM : public CapstoneArchitecture {
|
||||||
|
public:
|
||||||
|
ArchitectureWASM() : CapstoneArchitecture(BuiltinArchitecture::WASM) {}
|
||||||
|
|
||||||
|
void drawSettings() override { }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ArchitectureRISCV : public CapstoneArchitecture {
|
||||||
|
public:
|
||||||
|
ArchitectureRISCV() : CapstoneArchitecture(BuiltinArchitecture::RISCV) {}
|
||||||
|
|
||||||
|
void drawSettings() override {
|
||||||
|
ImGui::RadioButton("hex.disassembler.view.disassembler.32bit"_lang, &m_riscvMode, CS_MODE_RISCV32);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::RadioButton("hex.disassembler.view.disassembler.64bit"_lang, &m_riscvMode, CS_MODE_RISCV64);
|
||||||
|
|
||||||
|
ImGui::Checkbox("hex.disassembler.view.disassembler.riscv.compressed"_lang, &m_compressed);
|
||||||
|
|
||||||
|
m_mode = cs_mode(m_riscvMode | (m_compressed ? CS_MODE_RISCVC : cs_mode(0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_riscvMode = CS_MODE_RISCV32;
|
||||||
|
bool m_compressed = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ArchitectureMOS65XX : public CapstoneArchitecture {
|
||||||
|
public:
|
||||||
|
ArchitectureMOS65XX() : CapstoneArchitecture(BuiltinArchitecture::MOS65XX) {}
|
||||||
|
|
||||||
|
void drawSettings() override {
|
||||||
|
std::pair<const char *, cs_mode> modes[] = {
|
||||||
|
{"hex.disassembler.view.disassembler.mos65xx.6502"_lang, CS_MODE_MOS65XX_6502 },
|
||||||
|
{ "hex.disassembler.view.disassembler.mos65xx.65c02"_lang, CS_MODE_MOS65XX_65C02 },
|
||||||
|
{ "hex.disassembler.view.disassembler.mos65xx.w65c02"_lang, CS_MODE_MOS65XX_W65C02 },
|
||||||
|
{ "hex.disassembler.view.disassembler.mos65xx.65816"_lang, CS_MODE_MOS65XX_65816 },
|
||||||
|
{ "hex.disassembler.view.disassembler.mos65xx.65816_long_m"_lang, CS_MODE_MOS65XX_65816_LONG_M },
|
||||||
|
{ "hex.disassembler.view.disassembler.mos65xx.65816_long_x"_lang, CS_MODE_MOS65XX_65816_LONG_X },
|
||||||
|
{ "hex.disassembler.view.disassembler.mos65xx.65816_long_mx"_lang, CS_MODE_MOS65XX_65816_LONG_MX},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (ImGui::BeginCombo("hex.disassembler.view.disassembler.settings.mode"_lang, modes[m_selectedMode].first)) {
|
||||||
|
for (u32 i = 0; i < IM_ARRAYSIZE(modes); i++) {
|
||||||
|
if (ImGui::Selectable(modes[i].first))
|
||||||
|
m_selectedMode = i;
|
||||||
|
}
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_mode = cs_mode(modes[m_selectedMode].second);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_selectedMode = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ArchitectureBPF : public CapstoneArchitecture {
|
||||||
|
public:
|
||||||
|
ArchitectureBPF() : CapstoneArchitecture(BuiltinArchitecture::BPF) {}
|
||||||
|
|
||||||
|
void drawSettings() override {
|
||||||
|
ImGui::RadioButton("hex.disassembler.view.disassembler.bpf.classic"_lang, &m_bpfMode, CS_MODE_BPF_CLASSIC);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::RadioButton("hex.disassembler.view.disassembler.bpf.extended"_lang, &m_bpfMode, CS_MODE_BPF_EXTENDED);
|
||||||
|
|
||||||
|
m_mode = cs_mode(m_bpfMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_bpfMode = CS_MODE_BPF_CLASSIC;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ArchitectureSuperH : public CapstoneArchitecture {
|
||||||
|
public:
|
||||||
|
ArchitectureSuperH() : CapstoneArchitecture(BuiltinArchitecture::SH) {}
|
||||||
|
|
||||||
|
void drawSettings() override {
|
||||||
|
std::pair<const char*, cs_mode> modes[] = {
|
||||||
|
{ "hex.disassembler.view.disassembler.sh.sh2"_lang, CS_MODE_SH2 },
|
||||||
|
{ "hex.disassembler.view.disassembler.sh.sh2a"_lang, CS_MODE_SH2A },
|
||||||
|
{ "hex.disassembler.view.disassembler.sh.sh3"_lang, CS_MODE_SH3 },
|
||||||
|
{ "hex.disassembler.view.disassembler.sh.sh4"_lang, CS_MODE_SH4 },
|
||||||
|
{ "hex.disassembler.view.disassembler.sh.sh4a"_lang, CS_MODE_SH4A },
|
||||||
|
};
|
||||||
|
|
||||||
|
if (ImGui::BeginCombo("hex.disassembler.view.disassembler.settings.mode"_lang, modes[m_selectedMode].first)) {
|
||||||
|
for (u32 i = 0; i < IM_ARRAYSIZE(modes); i++) {
|
||||||
|
if (ImGui::Selectable(modes[i].first))
|
||||||
|
m_selectedMode = i;
|
||||||
|
}
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Checkbox("hex.disassembler.view.disassembler.sh.fpu"_lang, &m_fpu);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Checkbox("hex.disassembler.view.disassembler.sh.dsp"_lang, &m_dsp);
|
||||||
|
|
||||||
|
m_mode = cs_mode(modes[m_selectedMode].second | (m_fpu ? CS_MODE_SHFPU : cs_mode(0)) | (m_dsp ? CS_MODE_SHDSP : cs_mode(0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_selectedMode = 0;
|
||||||
|
bool m_fpu = false;
|
||||||
|
bool m_dsp = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ArchitectureTricore : public CapstoneArchitecture {
|
||||||
|
public:
|
||||||
|
ArchitectureTricore() : CapstoneArchitecture(BuiltinArchitecture::TRICORE) {}
|
||||||
|
|
||||||
|
void drawSettings() override {
|
||||||
|
std::pair<const char*, cs_mode> modes[] = {
|
||||||
|
{ "hex.disassembler.view.disassembler.tricore.110"_lang, CS_MODE_TRICORE_110 },
|
||||||
|
{ "hex.disassembler.view.disassembler.tricore.120"_lang, CS_MODE_TRICORE_120 },
|
||||||
|
{ "hex.disassembler.view.disassembler.tricore.130"_lang, CS_MODE_TRICORE_130 },
|
||||||
|
{ "hex.disassembler.view.disassembler.tricore.131"_lang, CS_MODE_TRICORE_131 },
|
||||||
|
{ "hex.disassembler.view.disassembler.tricore.160"_lang, CS_MODE_TRICORE_160 },
|
||||||
|
{ "hex.disassembler.view.disassembler.tricore.161"_lang, CS_MODE_TRICORE_161 },
|
||||||
|
{ "hex.disassembler.view.disassembler.tricore.162"_lang, CS_MODE_TRICORE_162 },
|
||||||
|
};
|
||||||
|
|
||||||
|
if (ImGui::BeginCombo("hex.disassembler.view.disassembler.settings.mode"_lang, modes[m_selectedMode].first)) {
|
||||||
|
for (u32 i = 0; i < IM_ARRAYSIZE(modes); i++) {
|
||||||
|
if (ImGui::Selectable(modes[i].first))
|
||||||
|
m_selectedMode = i;
|
||||||
|
}
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_mode = cs_mode(modes[m_selectedMode].second);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_selectedMode = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void registerCapstoneArchitectures() {
|
||||||
|
ContentRegistry::Disassembler::add<ArchitectureARM>();
|
||||||
|
ContentRegistry::Disassembler::add<ArchitectureARM64>();
|
||||||
|
ContentRegistry::Disassembler::add<ArchitectureMIPS>();
|
||||||
|
ContentRegistry::Disassembler::add<ArchitectureX86>();
|
||||||
|
ContentRegistry::Disassembler::add<ArchitecturePowerPC>();
|
||||||
|
ContentRegistry::Disassembler::add<ArchitectureSPARC>();
|
||||||
|
ContentRegistry::Disassembler::add<ArchitectureSystemZ>();
|
||||||
|
ContentRegistry::Disassembler::add<ArchitectureXCore>();
|
||||||
|
ContentRegistry::Disassembler::add<ArchitectureM68K>();
|
||||||
|
ContentRegistry::Disassembler::add<ArchitectureTMS320C64X>();
|
||||||
|
ContentRegistry::Disassembler::add<ArchitectureM680X>();
|
||||||
|
ContentRegistry::Disassembler::add<ArchitectureEVM>();
|
||||||
|
|
||||||
|
#if CS_API_MAJOR >= 5
|
||||||
|
ContentRegistry::Disassembler::add<ArchitectureWASM>();
|
||||||
|
ContentRegistry::Disassembler::add<ArchitectureRISCV>();
|
||||||
|
ContentRegistry::Disassembler::add<ArchitectureMOS65XX>();
|
||||||
|
ContentRegistry::Disassembler::add<ArchitectureBPF>();
|
||||||
|
ContentRegistry::Disassembler::add<ArchitectureSuperH>();
|
||||||
|
ContentRegistry::Disassembler::add<ArchitectureTricore>();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -69,7 +69,7 @@ namespace hex::plugin::disasm {
|
|||||||
cs_mode mode;
|
cs_mode mode;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
std::tie(arch, mode) = Disassembler::stringToSettings(params[0].toString());
|
std::tie(arch, mode) = CapstoneDisassembler::stringToSettings(params[0].toString());
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
err::E0012.throwError(e.what());
|
err::E0012.throwError(e.what());
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ namespace hex::plugin::disasm {
|
|||||||
if (shouldReset) {
|
if (shouldReset) {
|
||||||
auto pattern = arguments[0].toPattern();
|
auto pattern = arguments[0].toPattern();
|
||||||
auto baseAddress = arguments[1].toUnsigned();
|
auto baseAddress = arguments[1].toUnsigned();
|
||||||
const auto [arch, mode] = Disassembler::stringToSettings(arguments[2].toString());
|
const auto [arch, mode] = CapstoneDisassembler::stringToSettings(arguments[2].toString());
|
||||||
|
|
||||||
disassembly.clear();
|
disassembly.clear();
|
||||||
|
|
||||||
|
@ -47,19 +47,8 @@ namespace hex::plugin::disasm {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
m_disassemblerTask = TaskManager::createTask("hex.disassembler.view.disassembler.disassembling"_lang, m_regionToDisassemble.getSize(), [this](auto &task) {
|
m_disassemblerTask = TaskManager::createTask("hex.disassembler.view.disassembler.disassembling"_lang, m_regionToDisassemble.getSize(), [this](auto &task) {
|
||||||
csh capstoneHandle;
|
|
||||||
|
|
||||||
cs_mode mode = m_mode;
|
|
||||||
|
|
||||||
// Create a capstone disassembler instance
|
// Create a capstone disassembler instance
|
||||||
if (cs_open(Disassembler::toCapstoneArchitecture(m_architecture), mode, &capstoneHandle) == CS_ERR_OK) {
|
if (m_currArchitecture->start()) {
|
||||||
auto *instruction = cs_malloc(capstoneHandle);
|
|
||||||
ON_SCOPE_EXIT { cs_free(instruction, 1); };
|
|
||||||
|
|
||||||
|
|
||||||
// Tell capstone to skip data bytes
|
|
||||||
cs_option(capstoneHandle, CS_OPT_SKIPDATA, CS_OPT_ON);
|
|
||||||
|
|
||||||
auto provider = ImHexApi::Provider::get();
|
auto provider = ImHexApi::Provider::get();
|
||||||
std::vector<u8> buffer(1_MiB, 0x00);
|
std::vector<u8> buffer(1_MiB, 0x00);
|
||||||
|
|
||||||
@ -75,34 +64,32 @@ namespace hex::plugin::disasm {
|
|||||||
size_t bufferSize = std::min<u64>(buffer.size(), (m_regionToDisassemble.getEndAddress() - instructionDataAddress));
|
size_t bufferSize = std::min<u64>(buffer.size(), (m_regionToDisassemble.getEndAddress() - instructionDataAddress));
|
||||||
provider->read(instructionDataAddress, buffer.data(), bufferSize);
|
provider->read(instructionDataAddress, buffer.data(), bufferSize);
|
||||||
|
|
||||||
|
auto code = std::span(buffer.data(), bufferSize);
|
||||||
|
|
||||||
// Ask capstone to disassemble the data
|
// Ask capstone to disassemble the data
|
||||||
const u8 *code = buffer.data();
|
while (true) {
|
||||||
while (cs_disasm_iter(capstoneHandle, &code, &bufferSize, &instructionLoadAddress, instruction)) {
|
auto instruction = m_currArchitecture->disassemble(m_imageBaseAddress, instructionLoadAddress, instructionDataAddress, code);
|
||||||
|
if (!instruction.has_value())
|
||||||
|
break;
|
||||||
|
|
||||||
task.update(instructionDataAddress);
|
task.update(instructionDataAddress);
|
||||||
|
|
||||||
// Convert the capstone instructions to our disassembly format
|
m_disassembly.push_back(instruction.value());
|
||||||
Disassembly disassembly = { };
|
|
||||||
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 < instruction->size; j++)
|
|
||||||
disassembly.bytes += hex::format("{0:02X} ", instruction->bytes[j]);
|
|
||||||
disassembly.bytes.pop_back();
|
|
||||||
|
|
||||||
m_disassembly.push_back(disassembly);
|
|
||||||
|
|
||||||
|
code = code.subspan(instruction->size);
|
||||||
instructionDataAddress += instruction->size;
|
instructionDataAddress += instruction->size;
|
||||||
|
instructionLoadAddress += instruction->size;
|
||||||
hadError = false;
|
hadError = false;
|
||||||
|
|
||||||
|
if (code.empty())
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hadError) break;
|
if (hadError) break;
|
||||||
hadError = true;
|
hadError = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
cs_close(&capstoneHandle);
|
m_currArchitecture->end();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -122,15 +109,15 @@ namespace hex::plugin::disasm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// As disassembly code can be quite long, we prefer writing each disassembled instruction to file
|
// As disassembly code can be quite long, we prefer writing each disassembled instruction to file
|
||||||
for (const Disassembly& d : m_disassembly) {
|
for (const ContentRegistry::Disassembler::Instruction& instruction : m_disassembly) {
|
||||||
// We test for a "bugged" case that should never happen - the instruction should always have a mnemonic
|
// We test for a "bugged" case that should never happen - the instruction should always have a mnemonic
|
||||||
if (d.mnemonic.empty())
|
if (instruction.mnemonic.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (d.operators.empty())
|
if (instruction.operators.empty())
|
||||||
file.writeString(hex::format("{}\n", d.mnemonic));
|
file.writeString(hex::format("{}\n", instruction.mnemonic));
|
||||||
else
|
else
|
||||||
file.writeString(hex::format("{} {}\n", d.mnemonic, d.operators));
|
file.writeString(hex::format("{} {}\n", instruction.mnemonic, instruction.operators));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -164,279 +151,30 @@ namespace hex::plugin::disasm {
|
|||||||
ImGuiExt::Header("hex.ui.common.settings"_lang);
|
ImGuiExt::Header("hex.ui.common.settings"_lang);
|
||||||
|
|
||||||
// Draw architecture selector
|
// Draw architecture selector
|
||||||
if (ImGui::Combo("hex.disassembler.view.disassembler.arch"_lang, reinterpret_cast<int *>(&m_architecture), Disassembler::ArchitectureNames.data(), Disassembler::getArchitectureSupportedCount()))
|
const auto &architectures = ContentRegistry::Disassembler::impl::getArchitectures();
|
||||||
m_mode = cs_mode(0);
|
if (architectures.empty()) {
|
||||||
|
ImGuiExt::TextSpinner("hex.disassembler.view.disassembler.arch"_lang);
|
||||||
|
} else {
|
||||||
|
if (m_currArchitecture == nullptr) {
|
||||||
|
m_currArchitecture = architectures.begin()->second();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::BeginCombo("hex.disassembler.view.disassembler.arch"_lang, m_currArchitecture->getName().c_str())) {
|
||||||
|
for (const auto &[name, creator] : architectures) {
|
||||||
|
if (ImGui::Selectable(name.c_str(), name == m_currArchitecture->getName())) {
|
||||||
|
m_currArchitecture = creator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
|
||||||
// Draw sub-settings for each architecture
|
// Draw sub-settings for each architecture
|
||||||
if (ImGuiExt::BeginBox()) {
|
if (ImGuiExt::BeginBox()) {
|
||||||
|
m_currArchitecture->drawSettings();
|
||||||
// Draw endian radio buttons. This setting is available for all architectures
|
|
||||||
static int littleEndian = true;
|
|
||||||
ImGui::RadioButton("hex.ui.common.little_endian"_lang, &littleEndian, true);
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::RadioButton("hex.ui.common.big_endian"_lang, &littleEndian, false);
|
|
||||||
|
|
||||||
ImGui::NewLine();
|
|
||||||
|
|
||||||
// Draw architecture specific settings
|
|
||||||
switch (m_architecture) {
|
|
||||||
case Architecture::ARM:
|
|
||||||
{
|
|
||||||
static int mode = CS_MODE_ARM;
|
|
||||||
ImGui::RadioButton("hex.disassembler.view.disassembler.arm.arm"_lang, &mode, CS_MODE_ARM);
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::RadioButton("hex.disassembler.view.disassembler.arm.thumb"_lang, &mode, CS_MODE_THUMB);
|
|
||||||
|
|
||||||
static int extraMode = 0;
|
|
||||||
ImGui::RadioButton("hex.disassembler.view.disassembler.arm.default"_lang, &extraMode, 0);
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::RadioButton("hex.disassembler.view.disassembler.arm.cortex_m"_lang, &extraMode, CS_MODE_MCLASS);
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::RadioButton("hex.disassembler.view.disassembler.arm.armv8"_lang, &extraMode, CS_MODE_V8);
|
|
||||||
|
|
||||||
m_mode = cs_mode(mode | extraMode);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Architecture::MIPS:
|
|
||||||
{
|
|
||||||
static int mode = CS_MODE_MIPS32;
|
|
||||||
ImGui::RadioButton("hex.disassembler.view.disassembler.mips.mips32"_lang, &mode, CS_MODE_MIPS32);
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::RadioButton("hex.disassembler.view.disassembler.mips.mips64"_lang, &mode, CS_MODE_MIPS64);
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::RadioButton("hex.disassembler.view.disassembler.mips.mips32R6"_lang, &mode, CS_MODE_MIPS32R6);
|
|
||||||
|
|
||||||
ImGui::RadioButton("hex.disassembler.view.disassembler.mips.mips2"_lang, &mode, CS_MODE_MIPS2);
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::RadioButton("hex.disassembler.view.disassembler.mips.mips3"_lang, &mode, CS_MODE_MIPS3);
|
|
||||||
|
|
||||||
static bool microMode;
|
|
||||||
ImGui::Checkbox("hex.disassembler.view.disassembler.mips.micro"_lang, µMode);
|
|
||||||
|
|
||||||
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.disassembler.view.disassembler.16bit"_lang, &mode, CS_MODE_16);
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::RadioButton("hex.disassembler.view.disassembler.32bit"_lang, &mode, CS_MODE_32);
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::RadioButton("hex.disassembler.view.disassembler.64bit"_lang, &mode, CS_MODE_64);
|
|
||||||
|
|
||||||
m_mode = cs_mode(mode);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Architecture::PPC:
|
|
||||||
{
|
|
||||||
static int mode = CS_MODE_32;
|
|
||||||
ImGui::RadioButton("hex.disassembler.view.disassembler.32bit"_lang, &mode, CS_MODE_32);
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::RadioButton("hex.disassembler.view.disassembler.64bit"_lang, &mode, CS_MODE_64);
|
|
||||||
|
|
||||||
static bool qpx = false;
|
|
||||||
ImGui::Checkbox("hex.disassembler.view.disassembler.ppc.qpx"_lang, &qpx);
|
|
||||||
|
|
||||||
#if CS_API_MAJOR >= 5
|
|
||||||
static bool spe = false;
|
|
||||||
ImGui::Checkbox("hex.disassembler.view.disassembler.ppc.spe"_lang, &spe);
|
|
||||||
static bool booke = false;
|
|
||||||
ImGui::Checkbox("hex.disassembler.view.disassembler.ppc.booke"_lang, &booke);
|
|
||||||
|
|
||||||
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
|
|
||||||
m_mode = cs_mode(mode | (qpx ? CS_MODE_QPX : cs_mode(0)));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Architecture::SPARC:
|
|
||||||
{
|
|
||||||
static bool v9Mode = false;
|
|
||||||
ImGui::Checkbox("hex.disassembler.view.disassembler.sparc.v9"_lang, &v9Mode);
|
|
||||||
|
|
||||||
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.disassembler.view.disassembler.32bit"_lang, &mode, CS_MODE_RISCV32);
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::RadioButton("hex.disassembler.view.disassembler.64bit"_lang, &mode, CS_MODE_RISCV64);
|
|
||||||
|
|
||||||
static bool compressed = false;
|
|
||||||
ImGui::Checkbox("hex.disassembler.view.disassembler.riscv.compressed"_lang, &compressed);
|
|
||||||
|
|
||||||
m_mode = cs_mode(mode | (compressed ? CS_MODE_RISCVC : cs_mode(0)));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case Architecture::M68K:
|
|
||||||
{
|
|
||||||
static int selectedMode = 0;
|
|
||||||
|
|
||||||
std::pair<const char *, cs_mode> modes[] = {
|
|
||||||
{"hex.disassembler.view.disassembler.m68k.000"_lang, CS_MODE_M68K_000},
|
|
||||||
{ "hex.disassembler.view.disassembler.m68k.010"_lang, CS_MODE_M68K_010},
|
|
||||||
{ "hex.disassembler.view.disassembler.m68k.020"_lang, CS_MODE_M68K_020},
|
|
||||||
{ "hex.disassembler.view.disassembler.m68k.030"_lang, CS_MODE_M68K_030},
|
|
||||||
{ "hex.disassembler.view.disassembler.m68k.040"_lang, CS_MODE_M68K_040},
|
|
||||||
{ "hex.disassembler.view.disassembler.m68k.060"_lang, CS_MODE_M68K_060},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (ImGui::BeginCombo("hex.disassembler.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();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_mode = cs_mode(modes[selectedMode].second);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Architecture::M680X:
|
|
||||||
{
|
|
||||||
static int selectedMode = 0;
|
|
||||||
|
|
||||||
std::pair<const char *, cs_mode> modes[] = {
|
|
||||||
{"hex.disassembler.view.disassembler.m680x.6301"_lang, CS_MODE_M680X_6301 },
|
|
||||||
{ "hex.disassembler.view.disassembler.m680x.6309"_lang, CS_MODE_M680X_6309 },
|
|
||||||
{ "hex.disassembler.view.disassembler.m680x.6800"_lang, CS_MODE_M680X_6800 },
|
|
||||||
{ "hex.disassembler.view.disassembler.m680x.6801"_lang, CS_MODE_M680X_6801 },
|
|
||||||
{ "hex.disassembler.view.disassembler.m680x.6805"_lang, CS_MODE_M680X_6805 },
|
|
||||||
{ "hex.disassembler.view.disassembler.m680x.6808"_lang, CS_MODE_M680X_6808 },
|
|
||||||
{ "hex.disassembler.view.disassembler.m680x.6809"_lang, CS_MODE_M680X_6809 },
|
|
||||||
{ "hex.disassembler.view.disassembler.m680x.6811"_lang, CS_MODE_M680X_6811 },
|
|
||||||
{ "hex.disassembler.view.disassembler.m680x.cpu12"_lang, CS_MODE_M680X_CPU12},
|
|
||||||
{ "hex.disassembler.view.disassembler.m680x.hcs08"_lang, CS_MODE_M680X_HCS08},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (ImGui::BeginCombo("hex.disassembler.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();
|
|
||||||
}
|
|
||||||
|
|
||||||
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.disassembler.view.disassembler.mos65xx.6502"_lang, CS_MODE_MOS65XX_6502 },
|
|
||||||
{ "hex.disassembler.view.disassembler.mos65xx.65c02"_lang, CS_MODE_MOS65XX_65C02 },
|
|
||||||
{ "hex.disassembler.view.disassembler.mos65xx.w65c02"_lang, CS_MODE_MOS65XX_W65C02 },
|
|
||||||
{ "hex.disassembler.view.disassembler.mos65xx.65816"_lang, CS_MODE_MOS65XX_65816 },
|
|
||||||
{ "hex.disassembler.view.disassembler.mos65xx.65816_long_m"_lang, CS_MODE_MOS65XX_65816_LONG_M },
|
|
||||||
{ "hex.disassembler.view.disassembler.mos65xx.65816_long_x"_lang, CS_MODE_MOS65XX_65816_LONG_X },
|
|
||||||
{ "hex.disassembler.view.disassembler.mos65xx.65816_long_mx"_lang, CS_MODE_MOS65XX_65816_LONG_MX},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (ImGui::BeginCombo("hex.disassembler.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();
|
|
||||||
}
|
|
||||||
|
|
||||||
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.disassembler.view.disassembler.bpf.classic"_lang, &mode, CS_MODE_BPF_CLASSIC);
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::RadioButton("hex.disassembler.view.disassembler.bpf.extended"_lang, &mode, CS_MODE_BPF_EXTENDED);
|
|
||||||
|
|
||||||
m_mode = cs_mode(mode);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Architecture::SH:
|
|
||||||
{
|
|
||||||
static u32 selectionMode = 0;
|
|
||||||
static bool fpu = false;
|
|
||||||
static bool dsp = false;
|
|
||||||
|
|
||||||
std::pair<const char*, cs_mode> modes[] = {
|
|
||||||
{ "hex.disassembler.view.disassembler.sh.sh2"_lang, CS_MODE_SH2 },
|
|
||||||
{ "hex.disassembler.view.disassembler.sh.sh2a"_lang, CS_MODE_SH2A },
|
|
||||||
{ "hex.disassembler.view.disassembler.sh.sh3"_lang, CS_MODE_SH3 },
|
|
||||||
{ "hex.disassembler.view.disassembler.sh.sh4"_lang, CS_MODE_SH4 },
|
|
||||||
{ "hex.disassembler.view.disassembler.sh.sh4a"_lang, CS_MODE_SH4A },
|
|
||||||
};
|
|
||||||
|
|
||||||
if (ImGui::BeginCombo("hex.disassembler.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();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::Checkbox("hex.disassembler.view.disassembler.sh.fpu"_lang, &fpu);
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::Checkbox("hex.disassembler.view.disassembler.sh.dsp"_lang, &dsp);
|
|
||||||
|
|
||||||
m_mode = cs_mode(modes[selectionMode].second | (fpu ? CS_MODE_SHFPU : cs_mode(0)) | (dsp ? CS_MODE_SHDSP : cs_mode(0)));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Architecture::TRICORE:
|
|
||||||
{
|
|
||||||
static u32 selectionMode = 0;
|
|
||||||
|
|
||||||
std::pair<const char*, cs_mode> modes[] = {
|
|
||||||
{ "hex.disassembler.view.disassembler.tricore.110"_lang, CS_MODE_TRICORE_110 },
|
|
||||||
{ "hex.disassembler.view.disassembler.tricore.120"_lang, CS_MODE_TRICORE_120 },
|
|
||||||
{ "hex.disassembler.view.disassembler.tricore.130"_lang, CS_MODE_TRICORE_130 },
|
|
||||||
{ "hex.disassembler.view.disassembler.tricore.131"_lang, CS_MODE_TRICORE_131 },
|
|
||||||
{ "hex.disassembler.view.disassembler.tricore.160"_lang, CS_MODE_TRICORE_160 },
|
|
||||||
{ "hex.disassembler.view.disassembler.tricore.161"_lang, CS_MODE_TRICORE_161 },
|
|
||||||
{ "hex.disassembler.view.disassembler.tricore.162"_lang, CS_MODE_TRICORE_162 },
|
|
||||||
};
|
|
||||||
|
|
||||||
if (ImGui::BeginCombo("hex.disassembler.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();
|
|
||||||
}
|
|
||||||
|
|
||||||
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:
|
|
||||||
m_mode = cs_mode(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (littleEndian) {
|
|
||||||
m_mode = cs_mode(u32(m_mode) | CS_MODE_LITTLE_ENDIAN);
|
|
||||||
} else {
|
|
||||||
m_mode = cs_mode(u32(m_mode) | CS_MODE_BIG_ENDIAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
ImGuiExt::EndBox();
|
ImGuiExt::EndBox();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Draw disassemble button
|
// Draw disassemble button
|
||||||
ImGui::BeginDisabled(m_disassemblerTask.isRunning() || m_regionToDisassemble.getStartAddress() < m_imageBaseAddress);
|
ImGui::BeginDisabled(m_disassemblerTask.isRunning() || m_regionToDisassemble.getStartAddress() < m_imageBaseAddress);
|
||||||
|
@ -17,6 +17,8 @@ namespace hex::plugin::disasm {
|
|||||||
void drawDisassemblyVisualizer(pl::ptrn::Pattern &, bool, std::span<const pl::core::Token::Literal> arguments);
|
void drawDisassemblyVisualizer(pl::ptrn::Pattern &, bool, std::span<const pl::core::Token::Literal> arguments);
|
||||||
void registerPatternLanguageTypes();
|
void registerPatternLanguageTypes();
|
||||||
|
|
||||||
|
void registerCapstoneArchitectures();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -42,4 +44,6 @@ IMHEX_PLUGIN_SETUP("Disassembler", "WerWolv", "Disassembler support") {
|
|||||||
registerViews();
|
registerViews();
|
||||||
registerPlVisualizers();
|
registerPlVisualizers();
|
||||||
registerPatternLanguageTypes();
|
registerPatternLanguageTypes();
|
||||||
|
|
||||||
|
registerCapstoneArchitectures();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user