threads and frames
This commit is contained in:
@@ -15,6 +15,16 @@ Target::Target(std::string filename)
|
||||
backend = std::make_shared<backend::LLDBBackend>(this->filename.c_str());
|
||||
}
|
||||
|
||||
Frontend::Frontend()
|
||||
{
|
||||
_open_popup_name_buf.resize(512);
|
||||
const char *str = "/home/klee/projects/dbgui/tmp/main";
|
||||
std::memcpy(_open_popup_name_buf.data(), str, strlen(str) + 1);
|
||||
_windows.push_back(Window::create_regs(window_id++));
|
||||
_windows.push_back(Window::create_threads(window_id++));
|
||||
_windows.push_back(Window::create_frames(window_id++));
|
||||
}
|
||||
|
||||
void Frontend::run_frame()
|
||||
{
|
||||
this->handle_msgs();
|
||||
@@ -38,6 +48,12 @@ void Frontend::run_frame()
|
||||
|
||||
if (ImGui::Begin("Test", nullptr, win_flags))
|
||||
{
|
||||
// TODO: if we just do SetNextWindowDockID in each of the windows
|
||||
// this seems to crash once the first window is docked to it?
|
||||
// so some id change is necessary
|
||||
// so we should try to figure out what the dock id for the "topleft"
|
||||
// window is or whatever and use that for new windows
|
||||
// spawning them floating looks bad (and might reuse saved positions)
|
||||
this->dock_id = ImGui::GetID("MyDockSpace");
|
||||
ImGui::DockSpace(this->dock_id, ImVec2{0, 0},
|
||||
ImGuiDockNodeFlags_PassthruCentralNode);
|
||||
@@ -45,6 +61,7 @@ void Frontend::run_frame()
|
||||
for (auto &window : _windows)
|
||||
{
|
||||
window.draw(*this);
|
||||
//this->dock_id = ImGui::GetWindowDockID();
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
@@ -104,8 +121,19 @@ void Frontend::draw_header()
|
||||
break;
|
||||
|
||||
case stopped: ImGui::Button("Run"); break;
|
||||
case paused: ImGui::Button("Continue"); break;
|
||||
case running: ImGui::Button("Pause"); break;
|
||||
case paused:
|
||||
if (ImGui::Button("Continue"))
|
||||
{
|
||||
this->target->backend->cont();
|
||||
// TODO: mark target already as running to prevent input?
|
||||
}
|
||||
break;
|
||||
case running:
|
||||
if (ImGui::Button("Pause"))
|
||||
{
|
||||
this->target->backend->pause();
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else
|
||||
{
|
||||
@@ -244,6 +272,22 @@ void Frontend::handle_msgs()
|
||||
case regs_changed:
|
||||
this->handle_reg_change(std::get<BackToFront::RegsChanged>(msg->data));
|
||||
break;
|
||||
case thread_changed:
|
||||
this->handle_thread_change(
|
||||
std::move(std::get<BackToFront::ThreadChange>(msg->data)));
|
||||
break;
|
||||
case thread_removed:
|
||||
this->handle_thread_remove(
|
||||
std::get<BackToFront::ThreadRemoved>(msg->data));
|
||||
break;
|
||||
case frame_changed:
|
||||
this->handle_frame_change(
|
||||
std::move(std::get<BackToFront::FrameChanged>(msg->data)));
|
||||
break;
|
||||
case frame_removed:
|
||||
this->handle_frame_remove(
|
||||
std::get<BackToFront::FrameRemoved>(msg->data));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -290,4 +334,90 @@ void Frontend::handle_reg_change(const BackToFront::RegsChanged &info)
|
||||
// TODO: opt for uint64?
|
||||
std::copy(val.begin(), val.end(), reg.bytes.begin());
|
||||
}
|
||||
}
|
||||
|
||||
void Frontend::handle_thread_remove(const BackToFront::ThreadRemoved &info)
|
||||
{
|
||||
auto &threads = this->target->threads;
|
||||
if (threads.size() >= info.idx)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
threads[info.idx] = {};
|
||||
}
|
||||
|
||||
void Frontend::handle_thread_change(BackToFront::ThreadChange &&info)
|
||||
{
|
||||
auto &threads = this->target->threads;
|
||||
if (threads.size() <= info.idx)
|
||||
{
|
||||
threads.resize(info.idx + 1);
|
||||
}
|
||||
|
||||
auto &thread = threads[info.idx];
|
||||
if (!thread)
|
||||
{
|
||||
thread = Target::Thread{
|
||||
.id = info.id,
|
||||
.ip = info.ip,
|
||||
.stop_extra = info.stop_extra,
|
||||
.stop_reason = info.stop_reason,
|
||||
};
|
||||
if (info.name)
|
||||
{
|
||||
thread->name = std::move(*info.name);
|
||||
}
|
||||
if (info.cur_display_fn)
|
||||
{
|
||||
thread->cur_display_fn = std::move(*info.cur_display_fn);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
thread->id = info.id;
|
||||
thread->ip = info.ip;
|
||||
thread->stop_reason = info.stop_reason;
|
||||
thread->stop_extra = info.stop_extra;
|
||||
if (info.name)
|
||||
{
|
||||
thread->name = std::move(*info.name);
|
||||
}
|
||||
if (info.cur_display_fn)
|
||||
{
|
||||
thread->cur_display_fn = std::move(*info.cur_display_fn);
|
||||
}
|
||||
}
|
||||
|
||||
void Frontend::handle_frame_remove(const BackToFront::FrameRemoved &info)
|
||||
{
|
||||
auto &frames = this->target->frames;
|
||||
if (frames.size() >= info.idx)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
frames[info.idx] = {};
|
||||
}
|
||||
|
||||
void Frontend::handle_frame_change(BackToFront::FrameChanged &&info)
|
||||
{
|
||||
auto &frames = this->target->frames;
|
||||
if (frames.size() <= info.idx)
|
||||
{
|
||||
frames.resize(info.idx + 1);
|
||||
}
|
||||
|
||||
auto &frame = frames[info.idx];
|
||||
if (!frame)
|
||||
{
|
||||
frame = Target::Frame{
|
||||
.ip = info.ip,
|
||||
.display_name = info.display_name,
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
frame->ip = info.ip;
|
||||
frame->display_name = info.display_name;
|
||||
}
|
||||
@@ -17,12 +17,7 @@ namespace dbgui::frontend
|
||||
|
||||
struct Frontend
|
||||
{
|
||||
Frontend()
|
||||
{
|
||||
_open_popup_name_buf.resize(512);
|
||||
const char *str = "/home/klee/projects/dbgui/tmp/main";
|
||||
std::memcpy(_open_popup_name_buf.data(), str, strlen(str) + 1);
|
||||
}
|
||||
Frontend();
|
||||
|
||||
void run_frame();
|
||||
|
||||
@@ -39,6 +34,10 @@ namespace dbgui::frontend
|
||||
void handle_state_change(const BackToFront::StateChange &);
|
||||
void handle_proc_info(BackToFront::InitialProcessInfo &&);
|
||||
void handle_reg_change(const BackToFront::RegsChanged &);
|
||||
void handle_thread_remove(const BackToFront::ThreadRemoved &);
|
||||
void handle_thread_change(BackToFront::ThreadChange &&);
|
||||
void handle_frame_remove(const BackToFront::FrameRemoved &);
|
||||
void handle_frame_change(BackToFront::FrameChanged &&);
|
||||
|
||||
bool _draw_second = false;
|
||||
|
||||
|
||||
@@ -25,6 +25,22 @@ namespace dbgui::frontend
|
||||
std::vector<Reg> regs;
|
||||
};
|
||||
|
||||
struct Thread
|
||||
{
|
||||
uint64_t id;
|
||||
uint64_t ip;
|
||||
uint64_t stop_extra;
|
||||
ThreadStopReason stop_reason;
|
||||
std::string name;
|
||||
std::string cur_display_fn;
|
||||
};
|
||||
|
||||
struct Frame
|
||||
{
|
||||
uint64_t ip;
|
||||
std::string display_name;
|
||||
};
|
||||
|
||||
Target(std::string filename);
|
||||
|
||||
TargetState state = TargetState::stopped;
|
||||
@@ -33,6 +49,8 @@ namespace dbgui::frontend
|
||||
Arch arch;
|
||||
|
||||
std::vector<RegSet> reg_sets;
|
||||
std::vector<std::optional<Thread>> threads;
|
||||
std::vector<std::optional<Frame>> frames;
|
||||
|
||||
std::shared_ptr<backend::Backend> backend = nullptr;
|
||||
};
|
||||
|
||||
@@ -11,6 +11,8 @@ void Window::draw(const Frontend &frontend)
|
||||
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;
|
||||
default: printf("Unhandled window draw: %u\n", this->type); exit(1);
|
||||
}
|
||||
}
|
||||
@@ -24,9 +26,27 @@ Window Window::create_regs(size_t id)
|
||||
.data = RegWindow{.id = id_str, .open = true}};
|
||||
}
|
||||
|
||||
Window Window::create_threads(size_t id)
|
||||
{
|
||||
auto id_str = std::string{"Threads##"};
|
||||
id_str.append(std::to_string(id));
|
||||
|
||||
return Window{.type = WindowType::threads,
|
||||
.data = ThreadWindow{.id = id_str, .open = true}};
|
||||
}
|
||||
|
||||
Window Window::create_frames(size_t id)
|
||||
{
|
||||
auto id_str = std::string{"Frames##"};
|
||||
id_str.append(std::to_string(id));
|
||||
|
||||
return Window{.type = WindowType::frames,
|
||||
.data = FrameWindow{.id = id_str, .open = true}};
|
||||
}
|
||||
|
||||
void RegWindow::draw(const Frontend &frontend)
|
||||
{
|
||||
ImGui::SetNextWindowDockID(frontend.dock_id, ImGuiCond_Appearing);
|
||||
//ImGui::SetNextWindowDockID(frontend.dock_id, ImGuiCond_Appearing);
|
||||
if (!ImGui::Begin(this->id.c_str()))
|
||||
{
|
||||
return;
|
||||
@@ -97,5 +117,112 @@ void RegWindow::draw(const Frontend &frontend)
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void ThreadWindow::draw(const Frontend &frontend)
|
||||
{
|
||||
//ImGui::SetNextWindowDockID(frontend.dock_id, ImGuiCond_Appearing);
|
||||
if (!ImGui::Begin(this->id.c_str()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!frontend.target)
|
||||
{
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ImGui::BeginTable("table", 3,
|
||||
ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg))
|
||||
{
|
||||
ImGui::TableSetupColumn("ID");
|
||||
ImGui::TableSetupColumn("Name");
|
||||
ImGui::TableSetupColumn("Location");
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
const auto &threads = frontend.target->threads;
|
||||
char buf[32];
|
||||
for (size_t idx = 0; idx < threads.size(); ++idx)
|
||||
{
|
||||
const auto &thread = threads[idx];
|
||||
if (!thread)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
|
||||
std::snprintf(buf, sizeof(buf), "%lu", thread->id);
|
||||
ImGui::Text(buf);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Text(thread->name.c_str());
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
if (thread->cur_display_fn != "")
|
||||
{
|
||||
ImGui::Text(thread->cur_display_fn.c_str());
|
||||
} else
|
||||
{
|
||||
std::snprintf(buf, sizeof(buf), "%lX", thread->ip);
|
||||
ImGui::Text(buf);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void FrameWindow::draw(const Frontend &frontend)
|
||||
{
|
||||
//ImGui::SetNextWindowDockID(frontend.dock_id, ImGuiCond_Appearing);
|
||||
if (!ImGui::Begin(this->id.c_str()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!frontend.target)
|
||||
{
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ImGui::BeginTable("table", 1,
|
||||
ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg))
|
||||
{
|
||||
ImGui::TableSetupColumn("Location");
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
const auto &frames = frontend.target->frames;
|
||||
char buf[32];
|
||||
for (size_t idx = 0; idx < frames.size(); ++idx)
|
||||
{
|
||||
const auto &frame = frames[idx];
|
||||
if (!frame)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
|
||||
if (frame->display_name != "")
|
||||
{
|
||||
ImGui::Text(frame->display_name.c_str());
|
||||
} else
|
||||
{
|
||||
std::snprintf(buf, sizeof(buf), "%lX", frame->ip);
|
||||
ImGui::Text(buf);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
@@ -17,7 +17,7 @@ namespace dbgui::frontend
|
||||
source,
|
||||
memory,
|
||||
variables,
|
||||
stack,
|
||||
frames,
|
||||
threads,
|
||||
disassembly,
|
||||
};
|
||||
@@ -55,13 +55,31 @@ namespace dbgui::frontend
|
||||
bool open;
|
||||
};
|
||||
|
||||
struct ThreadWindow
|
||||
{
|
||||
void draw(const Frontend &);
|
||||
|
||||
std::string id;
|
||||
bool open;
|
||||
};
|
||||
|
||||
struct FrameWindow
|
||||
{
|
||||
void draw(const Frontend &);
|
||||
|
||||
std::string id;
|
||||
bool open;
|
||||
};
|
||||
|
||||
struct Window
|
||||
{
|
||||
WindowType type;
|
||||
std::variant<std::monostate, RegWindow> data;
|
||||
std::variant<std::monostate, RegWindow, ThreadWindow, FrameWindow> data;
|
||||
|
||||
void draw(const 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);
|
||||
};
|
||||
} // namespace dbgui::frontend
|
||||
Reference in New Issue
Block a user