disassembly and new font
This commit is contained in:
@@ -23,6 +23,7 @@ Frontend::Frontend()
|
||||
_windows.push_back(Window::create_regs(window_id++));
|
||||
_windows.push_back(Window::create_threads(window_id++));
|
||||
_windows.push_back(Window::create_frames(window_id++));
|
||||
_windows.push_back(Window::create_disas(window_id++));
|
||||
}
|
||||
|
||||
void Frontend::run_frame()
|
||||
@@ -68,14 +69,21 @@ void Frontend::run_frame()
|
||||
ImGui::DockSpace(this->dock_id, ImVec2{0, 0},
|
||||
ImGuiDockNodeFlags_PassthruCentralNode);
|
||||
|
||||
for (auto &window : _windows)
|
||||
size_t window_idx = 0;
|
||||
while (window_idx < _windows.size())
|
||||
{
|
||||
window.draw(*this);
|
||||
auto &window = _windows[window_idx];
|
||||
if (window.draw(*this))
|
||||
{
|
||||
_windows.erase(_windows.begin() + window_idx);
|
||||
} else
|
||||
{
|
||||
window_idx++;
|
||||
}
|
||||
//this->dock_id = ImGui::GetWindowDockID();
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
this->draw_status();
|
||||
}
|
||||
@@ -225,8 +233,8 @@ void Frontend::draw_status()
|
||||
ImGui::Text("Happy status bar");
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void Frontend::draw_open_popup()
|
||||
@@ -305,6 +313,15 @@ void Frontend::handle_msgs()
|
||||
this->handle_frame_remove(
|
||||
std::get<BackToFront::FrameRemoved>(msg->data));
|
||||
break;
|
||||
case data_result:
|
||||
{
|
||||
const auto &result = std::get<BackToFront::DataResult>(msg->data);
|
||||
printf("Result ID: %lu\n", result.result.id);
|
||||
for (auto &window : _windows)
|
||||
{
|
||||
window.handle_data_res(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ namespace dbgui::frontend
|
||||
TargetState state = TargetState::stopped;
|
||||
std::string filename;
|
||||
uint64_t id;
|
||||
size_t data_node_id = 0;
|
||||
Arch arch;
|
||||
|
||||
std::vector<RegSet> reg_sets;
|
||||
|
||||
@@ -4,15 +4,20 @@
|
||||
using namespace dbgui;
|
||||
using namespace dbgui::frontend;
|
||||
|
||||
void Window::draw(const Frontend &frontend)
|
||||
bool Window::draw(Frontend &frontend)
|
||||
{
|
||||
switch (this->type)
|
||||
{
|
||||
using enum WindowType;
|
||||
|
||||
case regs: std::get<RegWindow>(this->data).draw(frontend); break;
|
||||
case threads: std::get<ThreadWindow>(this->data).draw(frontend); break;
|
||||
case frames: std::get<FrameWindow>(this->data).draw(frontend); break;
|
||||
case regs: return std::get<RegWindow>(this->data).draw(frontend); break;
|
||||
case threads:
|
||||
return std::get<ThreadWindow>(this->data).draw(frontend);
|
||||
break;
|
||||
case frames: return std::get<FrameWindow>(this->data).draw(frontend); break;
|
||||
case disassembly:
|
||||
return std::get<DisasmWindow>(this->data).draw(frontend);
|
||||
break;
|
||||
default: printf("Unhandled window draw: %u\n", this->type); exit(1);
|
||||
}
|
||||
}
|
||||
@@ -44,18 +49,29 @@ Window Window::create_frames(size_t id)
|
||||
.data = FrameWindow{.id = id_str, .open = true}};
|
||||
}
|
||||
|
||||
void RegWindow::draw(const Frontend &frontend)
|
||||
Window Window::create_disas(size_t id)
|
||||
{
|
||||
auto id_str = std::string{"Disassembly##"};
|
||||
id_str.append(std::to_string(id));
|
||||
|
||||
return Window{.type = WindowType::disassembly,
|
||||
.data =
|
||||
DisasmWindow{.id = id_str, .open = true, .first = true}};
|
||||
}
|
||||
|
||||
bool RegWindow::draw(const Frontend &frontend)
|
||||
{
|
||||
//ImGui::SetNextWindowDockID(frontend.dock_id, ImGuiCond_Appearing);
|
||||
if (!ImGui::Begin(this->id.c_str()))
|
||||
{
|
||||
return;
|
||||
ImGui::End();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!frontend.target)
|
||||
{
|
||||
ImGui::End();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ImGui::BeginTable("table", 1,
|
||||
@@ -136,20 +152,22 @@ void RegWindow::draw(const Frontend &frontend)
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
return false;
|
||||
}
|
||||
|
||||
void ThreadWindow::draw(const Frontend &frontend)
|
||||
bool ThreadWindow::draw(const Frontend &frontend)
|
||||
{
|
||||
//ImGui::SetNextWindowDockID(frontend.dock_id, ImGuiCond_Appearing);
|
||||
if (!ImGui::Begin(this->id.c_str()))
|
||||
{
|
||||
return;
|
||||
ImGui::End();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!frontend.target)
|
||||
{
|
||||
ImGui::End();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ImGui::BeginTable("table", 3,
|
||||
@@ -194,20 +212,22 @@ void ThreadWindow::draw(const Frontend &frontend)
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
return false;
|
||||
}
|
||||
|
||||
void FrameWindow::draw(const Frontend &frontend)
|
||||
bool FrameWindow::draw(const Frontend &frontend)
|
||||
{
|
||||
//ImGui::SetNextWindowDockID(frontend.dock_id, ImGuiCond_Appearing);
|
||||
if (!ImGui::Begin(this->id.c_str()))
|
||||
{
|
||||
return;
|
||||
ImGui::End();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!frontend.target)
|
||||
{
|
||||
ImGui::End();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ImGui::BeginTable("table", 1,
|
||||
@@ -243,4 +263,265 @@ void FrameWindow::draw(const Frontend &frontend)
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DisasmWindow::draw(Frontend &frontend)
|
||||
{
|
||||
if (!ImGui::Begin(this->id.c_str()))
|
||||
{
|
||||
ImGui::End();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!frontend.target)
|
||||
{
|
||||
this->insts.clear();
|
||||
this->first = true;
|
||||
this->ip_unsuccessful = true;
|
||||
this->disas_unsuccessful = true;
|
||||
ImGui::End();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (frontend.target->state == TargetState::stopped
|
||||
|| frontend.target->state == TargetState::startup)
|
||||
{
|
||||
this->ip_unsuccessful = true;
|
||||
this->disas_unsuccessful = true;
|
||||
ImGui::End();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (first)
|
||||
{
|
||||
auto found = false;
|
||||
uint16_t set_idx, reg_idx;
|
||||
for (size_t i = 0; i < frontend.target->reg_sets.size(); ++i)
|
||||
{
|
||||
const auto &set = frontend.target->reg_sets[i];
|
||||
for (size_t j = 0; j < set.regs.size(); ++j)
|
||||
{
|
||||
if (frontend.target->arch == Arch::x86_64 && set.regs[j].name == "rip")
|
||||
{
|
||||
found = true;
|
||||
set_idx = i;
|
||||
reg_idx = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
ImGui::End();
|
||||
this->ip_unsuccessful = true;
|
||||
this->disas_unsuccessful = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
this->ip_src_id = frontend.target->data_node_id++;
|
||||
this->disas_src_id = frontend.target->data_node_id++;
|
||||
frontend.target->backend->add_data_node(data::DataNode{
|
||||
.id = this->ip_src_id,
|
||||
.type = data::DataNode::Type::data_source,
|
||||
.data = data::DataSource{
|
||||
.type = data::DataSource::Type::reg,
|
||||
.data = data::DataSource::Reg{.set = set_idx, .idx = reg_idx}}});
|
||||
|
||||
frontend.target->backend->add_data_node(
|
||||
data::DataNode{.id = this->disas_src_id,
|
||||
.type = data::DataNode::Type::disassemble,
|
||||
.data = data::Disassemble{.src_id = this->ip_src_id}});
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
auto pad = ImGui::GetStyle().CellPadding;
|
||||
pad.x += 10.f;
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, pad);
|
||||
if (ImGui::BeginTable("table", 2,
|
||||
ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollY
|
||||
| ImGuiTableFlags_RowBg | ImGuiTableFlags_PadOuterX))
|
||||
{
|
||||
ImGui::TableSetupScrollFreeze(0, 1);
|
||||
ImGui::TableSetupColumn("Address");
|
||||
ImGui::TableSetupColumn("Instruction");
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
for (size_t idx = 0; idx < insts.size(); ++idx)
|
||||
{
|
||||
const auto &inst = insts[idx];
|
||||
//printf("Inst at %lx with '%s'\n", inst.addr, inst.fmt_str.c_str());
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
|
||||
if (!this->ip_unsuccessful && inst.addr == ip)
|
||||
{
|
||||
// TODO: color config
|
||||
const auto col =
|
||||
ImGui::GetColorU32(ImGui::GetStyleColorVec4(ImGuiCol_Button));
|
||||
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, col);
|
||||
if (this->ip_changed)
|
||||
{
|
||||
ImGui::SetScrollHereY();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: make some unified handler for int vars
|
||||
ImGui::PushID(idx);
|
||||
ImGui::Text("%lX", inst.addr);
|
||||
if (ImGui::IsItemHovered()
|
||||
&& ImGui::IsMouseClicked(ImGuiMouseButton_Right))
|
||||
{
|
||||
ImGui::OpenPopup("Context");
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopup("Context"))
|
||||
{
|
||||
if (ImGui::Selectable("Copy"))
|
||||
{
|
||||
char buf[32];
|
||||
std::snprintf(buf, sizeof(buf), "%lX", inst.addr);
|
||||
ImGui::SetClipboardText(buf);
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
const int mnem_space = max_mnem_len - inst.mnem_len + 1;
|
||||
const int op_space = max_op_len - inst.op_len + 1;
|
||||
ImGui::Text(inst.fmt_str.c_str(), mnem_space, ' ', op_space, ' ');
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::End();
|
||||
|
||||
ip_changed = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
void Window::handle_data_res(const BackToFront::DataResult &result)
|
||||
{
|
||||
switch (this->type)
|
||||
{
|
||||
using enum WindowType;
|
||||
|
||||
case disassembly:
|
||||
std::get<DisasmWindow>(this->data).handle_data_res(result);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
void DisasmWindow::handle_data_res(
|
||||
const BackToFront::DataResult &result_wrapper)
|
||||
{
|
||||
const auto &result = result_wrapper.result;
|
||||
if (result.id == this->ip_src_id)
|
||||
{
|
||||
if (!result.success || result.type.type != data::TypeInfo::Type::u64)
|
||||
{
|
||||
this->ip_unsuccessful = true;
|
||||
return;
|
||||
}
|
||||
|
||||
this->ip_unsuccessful = false;
|
||||
this->ip_changed = true;
|
||||
this->ip = *reinterpret_cast<const uint64_t *>(result.data.data());
|
||||
printf("IP changed to %lX\n", this->ip);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.id != this->disas_src_id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.success || result.type.type != data::TypeInfo::Type::custom)
|
||||
{
|
||||
this->disas_unsuccessful = true;
|
||||
this->insts.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
this->disas_unsuccessful = false;
|
||||
this->insts.clear();
|
||||
|
||||
// parse insts
|
||||
// struct Inst {
|
||||
// uint64_t addr;
|
||||
// uint8_t mnem_len;
|
||||
// uint8_t op_len;
|
||||
// uint8_t comment_len;
|
||||
// uint8_t inst_len;
|
||||
// char mnem[];
|
||||
// char op[];
|
||||
// char comment[];
|
||||
// };
|
||||
|
||||
char buf[256];
|
||||
size_t idx = 0;
|
||||
|
||||
uint8_t max_mnem_len = 0;
|
||||
uint8_t max_op_len = 0;
|
||||
while (idx < result.data.size())
|
||||
{
|
||||
if (result.data.size() - idx < 12)
|
||||
{
|
||||
break;
|
||||
}
|
||||
uint64_t addr = *reinterpret_cast<const uint64_t *>(&result.data[idx]);
|
||||
uint8_t mnem_len =
|
||||
*reinterpret_cast<const uint8_t *>(&result.data[idx + 8]);
|
||||
uint8_t op_len = *reinterpret_cast<const uint8_t *>(&result.data[idx + 9]);
|
||||
uint8_t comment_len =
|
||||
*reinterpret_cast<const uint8_t *>(&result.data[idx + 10]);
|
||||
// dc about inst_len rn
|
||||
idx += 12;
|
||||
if (result.data.size() - idx < mnem_len + op_len + comment_len)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (comment_len)
|
||||
{
|
||||
std::snprintf(buf, sizeof(buf), "%.*s%%*c%.*s%%.*c ; %.*s", mnem_len,
|
||||
&result.data[idx], op_len, &result.data[idx + mnem_len],
|
||||
comment_len, &result.data[idx + mnem_len + op_len]);
|
||||
} else
|
||||
{
|
||||
std::snprintf(buf, sizeof(buf), "%.*s%%*c%.*s%%.*c", mnem_len,
|
||||
&result.data[idx], op_len, &result.data[idx + mnem_len]);
|
||||
}
|
||||
idx += mnem_len + op_len + comment_len;
|
||||
|
||||
if (mnem_len > max_mnem_len)
|
||||
{
|
||||
max_mnem_len = mnem_len;
|
||||
}
|
||||
if (op_len > max_op_len)
|
||||
{
|
||||
max_op_len = op_len;
|
||||
}
|
||||
|
||||
insts.push_back(Instruction{.fmt_str = buf,
|
||||
.addr = addr,
|
||||
.mnem_len = mnem_len,
|
||||
.op_len = op_len,
|
||||
.comm_len = comment_len});
|
||||
}
|
||||
|
||||
this->max_mnem_len = max_mnem_len;
|
||||
this->max_op_len = max_op_len;
|
||||
}
|
||||
@@ -49,7 +49,7 @@ namespace dbgui::frontend
|
||||
|
||||
std::vector<Reg> regs;*/
|
||||
|
||||
void draw(const Frontend &);
|
||||
bool draw(const Frontend &);
|
||||
|
||||
std::string id;
|
||||
bool open;
|
||||
@@ -57,7 +57,7 @@ namespace dbgui::frontend
|
||||
|
||||
struct ThreadWindow
|
||||
{
|
||||
void draw(const Frontend &);
|
||||
bool draw(const Frontend &);
|
||||
|
||||
std::string id;
|
||||
bool open;
|
||||
@@ -65,21 +65,54 @@ namespace dbgui::frontend
|
||||
|
||||
struct FrameWindow
|
||||
{
|
||||
void draw(const Frontend &);
|
||||
bool draw(const Frontend &);
|
||||
|
||||
std::string id;
|
||||
bool open;
|
||||
};
|
||||
|
||||
struct DisasmWindow
|
||||
{
|
||||
struct Instruction
|
||||
{
|
||||
// "<mnem>%*c<op>%*c[ ; <comment>]"
|
||||
std::string fmt_str;
|
||||
uint64_t addr;
|
||||
uint8_t mnem_len, op_len, comm_len;
|
||||
};
|
||||
|
||||
bool draw(Frontend &);
|
||||
|
||||
void handle_data_res(const BackToFront::DataResult &result);
|
||||
|
||||
std::string id;
|
||||
bool open;
|
||||
bool first;
|
||||
bool ip_unsuccessful;
|
||||
bool disas_unsuccessful;
|
||||
bool ip_changed;
|
||||
|
||||
size_t ip_src_id, disas_src_id;
|
||||
uint64_t ip;
|
||||
uint8_t max_mnem_len, max_op_len;
|
||||
std::vector<Instruction> insts;
|
||||
};
|
||||
|
||||
struct Window
|
||||
{
|
||||
WindowType type;
|
||||
std::variant<std::monostate, RegWindow, ThreadWindow, FrameWindow> data;
|
||||
std::variant<std::monostate, RegWindow, ThreadWindow, FrameWindow,
|
||||
DisasmWindow>
|
||||
data;
|
||||
|
||||
void draw(const Frontend &);
|
||||
// if true, window is closed and should be deleted
|
||||
bool draw(Frontend &);
|
||||
|
||||
static Window create_regs(size_t window_id);
|
||||
static Window create_threads(size_t window_id);
|
||||
static Window create_frames(size_t window_id);
|
||||
static Window create_disas(size_t window_id);
|
||||
|
||||
void handle_data_res(const BackToFront::DataResult &result);
|
||||
};
|
||||
} // namespace dbgui::frontend
|
||||
Reference in New Issue
Block a user