disassembly and new font

This commit is contained in:
T0b1
2023-06-03 21:58:56 +02:00
parent 4f0f320ac4
commit 343a30289c
15 changed files with 3631 additions and 32 deletions

View File

@@ -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;
}