#include #include #include #include #include "interface/log/LogView.hpp" #include "interface/cpu/CPUView.hpp" #include "../core/Core.hpp" #include "interface/cpu/RegView.hpp" #include "interface/cpu/SymbolMenu.hpp" #include "interface/memory/MemoryView.hpp" #include "interface/callstack/CallstackView.hpp" #include "interface/editor/EditorView.hpp" class HomeWindow : public Gtk::Window { public: void sendMessage(char id, void* param) const { DebugCommand msg{id, param}; if(sock_pair[0] != -1) { write(sock_pair[0], &msg, sizeof(DebugCommand)); } } protected: int sock_pair[2]{}; Glib::RefPtr _refBuilder; Glib::RefPtr _app = nullptr; std::shared_ptr _core = nullptr; pthread_t _th = 0; std::string _lastPath = ""; std::string _lastArgv = ""; char buffer[32] = {0}; int ep = -1; epoll_event ev1 {}; std::vector* pInsn = nullptr; public: // Elements Glib::RefPtr codeView = nullptr; Glib::RefPtr logView = nullptr; Glib::RefPtr bAttach = nullptr; Glib::RefPtr dialogAttach = nullptr; Glib::RefPtr dCancel = nullptr; Glib::RefPtr dAttach = nullptr; Glib::RefPtr bStop = nullptr; Glib::RefPtr bCont = nullptr; Glib::RefPtr bSuspend = nullptr; Glib::RefPtr debugBox = nullptr; Glib::RefPtr tExecutable = nullptr; Glib::RefPtr tArg = nullptr; Glib::RefPtr logScroll = nullptr; Glib::RefPtr HeaderBar = nullptr; Glib::RefPtr bRestart = nullptr; Glib::RefPtr regView = nullptr; Glib::RefPtr windowTitle = nullptr; Glib::RefPtr bStepinto = nullptr; Glib::RefPtr memory = nullptr; Glib::RefPtr popover1 = nullptr; Glib::RefPtr popover1Box = nullptr; Glib::RefPtr currentSymbol = nullptr; Glib::RefPtr bStepover = nullptr; Glib::RefPtr mSymbols = nullptr; Glib::RefPtr bTryParse = nullptr; Glib::RefPtr breakpoints = nullptr; Glib::RefPtr stack = nullptr; Glib::RefPtr callstack = nullptr; Glib::RefPtr bGoto = nullptr; Glib::RefPtr editor = nullptr; Glib::RefPtr bMemPush = nullptr; Glib::RefPtr bMemPull = nullptr; Glib::RefPtr bMemJump = nullptr; public: HomeWindow(BaseObjectType *cobject, const Glib::RefPtr &refBuilder, const Glib::RefPtr& app) : Gtk::Window(cobject), _refBuilder(refBuilder), _app(app), codeView(_refBuilder->get_widget_derived(_refBuilder, "code")), regView(_refBuilder->get_widget_derived(_refBuilder, "reg")), logScroll(refBuilder->get_widget("logScroll")), bAttach(refBuilder->get_widget("bAttach")), dialogAttach(refBuilder->get_widget("dialogAttach")), dCancel(refBuilder->get_widget("dCancel")), dAttach(refBuilder->get_widget("dAttach")), bStop(refBuilder->get_widget("bStop")), debugBox(refBuilder->get_widget("debugBox")), tExecutable(refBuilder->get_widget("tExecutable")), tArg(refBuilder->get_widget("tArg")), logView(_refBuilder->get_widget_derived(_refBuilder, "log")), bCont(refBuilder->get_widget("bCont")), bSuspend(refBuilder->get_widget("bSuspend")), HeaderBar(refBuilder->get_widget("HeaderBar")), bRestart(refBuilder->get_widget("bRestart")), windowTitle(refBuilder->get_widget("windowTitle")), bStepinto(refBuilder->get_widget("bStepinto")), memory(_refBuilder->get_widget_derived(_refBuilder, "memory")), popover1(refBuilder->get_widget("popover1")), popover1Box(refBuilder->get_widget("popover1Box")), currentSymbol(refBuilder->get_widget("currentSymbol")), bStepover(refBuilder->get_widget("bStepover")), mSymbols(refBuilder->get_widget_derived(_refBuilder, "mSymbols")), bTryParse(refBuilder->get_widget("bTryParse")), breakpoints(_refBuilder->get_widget_derived(_refBuilder, "breakpoints")), stack(refBuilder->get_widget("stack")), callstack(_refBuilder->get_widget_derived(_refBuilder, "callstack")), bGoto(refBuilder->get_widget("bGoto")), editor(_refBuilder->get_widget_derived(_refBuilder, "editor")), bMemPush(refBuilder->get_widget("bMemPush")), bMemPull(refBuilder->get_widget("bMemPull")), bMemJump(refBuilder->get_widget("bMemJump")) { socketpair(AF_UNIX, SOCK_STREAM, 0, sock_pair); ep = epoll_create1(0); ev1 = epoll_event{.events = EPOLLIN}; ev1.data.fd = sock_pair[0]; epoll_ctl(ep, EPOLL_CTL_ADD, sock_pair[0], &ev1); bTryParse->hide(); this->add_tick_callback([this](const Glib::RefPtr& c){ int n = epoll_wait(ep, &ev1, 1, 0); if(n > 0) { auto sz = read(sock_pair[0], buffer, sizeof(DebugCommand)); if(sz != sizeof(DebugCommand)) return true; auto msg = (DebugCommand*)buffer; switch (msg->id) { case MSG_PAUSE: UpdateUI(1, BTN_CONT | BTN_STOP | BTN_STI); break; case MSG_STOP: _core = nullptr; UpdateUI(0, BTN_ATTACH); break; case MSG_CONTINUE: UpdateUI(2, BTN_INT | BTN_STOP); break; case MSG_STARTUP: UpdateUI(0, BTN_INT | BTN_STOP); break; case MSG_REG:{ auto reg = reinterpret_cast(msg->param); UpdateUI(0, 0, reg); // The first two parameters do not take effect when reg isn't empty codeView->rip = reg->rip; break; } case MSG_QUIT: return false; case MSG_LOG: logView->add_log_data((char*)msg->param); delete[] (char*)msg->param; break; case MSG_TITLE: windowTitle->set_text((char*)msg->param); break; case MSG_MEMORY:{ auto pList = reinterpret_cast*>(msg->param); memory->set_data(*pList); break; } case MSG_ASM:{ delete pInsn; pInsn = reinterpret_cast*>(msg->param); codeView->setData(*pInsn); break; } case MSG_SELECT: codeView->Select(); break; case MSG_CURRENTSYMBOL: currentSymbol->set_text(_core->currentSymbol.name); break; case MSG_RESTART: _core = std::make_shared(_lastPath, _lastArgv); _core->pipe = sock_pair[1]; _core->remotePipe = sock_pair[0]; codeView->core = _core; breakpoints->core = _core; bAttach->set_sensitive(false); logView->clear(); break; case MSG_SYMBOLS: mSymbols->UpdateList(_core->symbols); break; case MSG_NONSYM: bTryParse->show(); break; case MSG_INSYM: bTryParse->hide(); break; case MSG_GETBREAKS: { breakpoints->clear(); auto insn = reinterpret_cast(msg->param); auto count = _core->GetBreakpoints().size(); for (size_t i = 0; i < count; i++) { char cmdAddr[32], insByte[32]; std::string bytes, cmdStr; for(int j = 0;jadd_row(cmdAddr, bytes, cmdStr, _core->ContainsBreakPoint(insn[i].address)); } delete[] insn; break; } case MSG_CALLSTACK: { auto *p = (std::stack*)msg->param; callstack->clear(); while(!p->empty()) { std::string name = "Thread: "; std::vector g; name += std::to_string(p->top().depth); p->pop(); int depth = INT_MAX; do { char strBuf[512]; depth = p->top().depth; CallstackItem i{}; i.depth = std::to_string(depth); sprintf(strBuf, "%lX", p->top().callPoint); i.callPoint = strBuf; sprintf(strBuf, "%lX", p->top().stackBase); i.stackBase = strBuf; i.symbol = p->top().symbol.name; i.module = p->top().module; g.emplace_back(i); p->pop(); }while(depth); callstack->append_group(name, g); } delete p; break; } default: break; } } return true; }); mSymbols->popoverBox = popover1Box; mSymbols->childLabel = currentSymbol; mSymbols->port = sock_pair[0]; _app->signal_activate().connect([this](){ _app->add_window(*this); this->show(); }); codeView->add_css_class("code_view"); dialogAttach->set_hide_on_close(true); bAttach->signal_clicked().connect([this](){ dialogAttach->set_transient_for(*this); dialogAttach->show(); }); dCancel->signal_clicked().connect([this](){ dialogAttach->close(); }); dAttach->signal_clicked().connect([this](){ auto s = tExecutable->get_buffer()->get_text(); std::size_t pos = s.rfind('/'); std::string filename = (pos != std::string::npos) ? s.substr(pos + 1) : s; dialogAttach->close(); _lastPath = s; _lastArgv = filename; _core = std::make_shared(s, filename); _core->pipe = sock_pair[1]; _core->remotePipe = sock_pair[0]; codeView->core = _core; breakpoints->core = _core; bAttach->set_sensitive(false); logView->clear(); }); bStop->signal_clicked().connect([this](){ if(_core) { codeView->clear(); sendMessage(MSG_STOP, nullptr); _core = nullptr; codeView->core = nullptr; breakpoints->core = nullptr; } }); bSuspend->signal_clicked().connect([this](){ sendMessage(MSG_PAUSE, nullptr); }); bCont->signal_clicked().connect([this](){ sendMessage(MSG_CONTINUE, nullptr); }); bStepinto->signal_clicked().connect([this](){ sendMessage(MSG_STEPINTO, nullptr); }); bRestart->signal_clicked().connect([this](){ if(!_lastPath.empty()) { if(!_core) { _core = std::make_shared(_lastPath, _lastArgv); _core->pipe = sock_pair[1]; _core->remotePipe = sock_pair[0]; codeView->core = _core; breakpoints->core = _core; bAttach->set_sensitive(false); logView->clear(); return; } sendMessage(MSG_RESTART, nullptr); _core = nullptr; codeView->core = nullptr; breakpoints->core = nullptr; printf("%s\n", "Pending to Restart"); } }); bStepover->signal_clicked().connect([this](){ sendMessage(MSG_STEPOVER, nullptr); }); bGoto->signal_clicked().connect([this](){ auto i = codeView->GetSelected(); _core->queueMessage(MSG_BREAKONCE, (void*)i); sendMessage(MSG_CONTINUE, nullptr); }); bTryParse->signal_clicked().connect([this](){ sendMessage(MSG_PARSE, nullptr); }); memory->signal_row_activated().connect([this](const Gtk::TreeModel::Path& p, Gtk::TreeViewColumn* c){ auto iter = memory->get_model()->get_iter(p); if(iter) { Glib::ustring addr; (*iter).get_value(0, addr); printf("%s\n", addr.c_str()); MapEntire me; _core->GetMapEntire(std::stoull(addr, nullptr, 16), me); if(me.access & EXECUTE) { auto buf = new char[512]; strcpy(buf, me.path); sendMessage(MSG_SWITCHMODULE, buf); } } }); stack->property_visible_child().signal_changed().connect([this](){ auto name = stack->get_visible_child_name(); if(name == "Breakpoints" && _core != nullptr) { if(_core) sendMessage(MSG_GETBREAKS, nullptr); }else if(name == "CPU" && _core != nullptr) { if(pInsn) codeView->setData(*pInsn); codeView->Select(); }else if(name == "Call Stack" && _core != nullptr) { if(_core) sendMessage(MSG_CALLSTACK, nullptr); } }); UpdateUI(0, BTN_ATTACH); } static Glib::RefPtr create() { auto app = Gtk::Application::create("acite.aldbg.app"); auto refBuilder = Gtk::Builder::create(); refBuilder->add_from_file("../aldbg.ui"); auto home = Gtk::Builder::get_widget_derived(refBuilder, "MainWindow", app); if (!home) { std::cerr << "No \"MainWindow\" object in main-window.ui" << std::endl; return nullptr; } auto css_provider = Gtk::CssProvider::create(); css_provider->load_from_path("../interface/style.css"); // 将 CSS 提供程序应用到屏幕 Gtk::StyleContext::add_provider_for_display(Gdk::Display::get_default(), css_provider, GTK_STYLE_PROVIDER_PRIORITY_USER); return Glib::make_refptr_for_instance(home); } enum ButtonMask { BTN_ATTACH = 0x01, BTN_STOP = 0x02, BTN_CONT = 0x04, BTN_INT = 0x08, BTN_STI = 0x10 }; void UpdateUI(int status, uint64_t buttons, user_regs_struct* reg = nullptr) { if(reg) { regView->clear(); regView->add_data("rax", reg->rax); regView->add_data("rbx", reg->rbx); regView->add_data("rcx", reg->rcx); regView->add_data("rdx", reg->rdx); regView->add_data("rbp", reg->rbp); regView->add_data("rsp", reg->rsp); regView->add_data("pc", reg->rip); return; } switch(status) { case 0: HeaderBar->remove_css_class("cont"); HeaderBar->remove_css_class("trap"); break; case 1: HeaderBar->remove_css_class("cont"); HeaderBar->add_css_class("trap"); break; case 2: HeaderBar->add_css_class("cont"); HeaderBar->remove_css_class("trap"); break; default: break; } bSuspend->set_sensitive(buttons & BTN_INT); bCont->set_sensitive(buttons & BTN_CONT); bAttach->set_sensitive(buttons & BTN_ATTACH); bStop->set_sensitive(buttons & BTN_STOP); bStepinto->set_sensitive(buttons & BTN_STI); bStepover->set_sensitive(buttons & BTN_STI); mSymbols->set_sensitive(buttons & BTN_STI); bGoto->set_sensitive(buttons & BTN_STI); bMemJump->set_sensitive(buttons & BTN_STI); bMemPull->set_sensitive(buttons & BTN_STI); bMemPush->set_sensitive(buttons & BTN_STI); } int loop() { return _app->run(); } };