/
George_Smith
/
GDBManager
Обзор
Документация
Войти
/
George_Smith
/
GDBManager
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
gdbengine.cpp
187 строк
6 KB
Георгий Кузнецов
Controlling GDB via the MI Interface
09 фев 2026, 12:46
09 фев 2026, 12:46
2b0ef22
Код
Авторство
О чём код?
#include "gdbengine.h" #include <unistd.h> #include <sys/wait.h> /* Parser key="value" */ void GdbEngine::parseResults(std::string payload, GdbResponse& res) { size_t i = 0; while (i < payload.size()) { /* Skip commas and spaces */ if (payload[i] == ',' || payload[i] == ' ') { i++; continue; } /* Find key */ size_t equal_pos = payload.find('=', i); if (equal_pos == std::string::npos) break; std::string key = payload.substr(i, equal_pos - i); i = equal_pos + 1; /* Identifying the value type */ if (i < payload.size() && payload[i] == '"') { /* A regular string in quotes */ size_t start_quote = i + 1; size_t end_quote = payload.find('"', start_quote); if (end_quote == std::string::npos) break; res.results[key] = payload.substr(start_quote, end_quote - start_quote); i = end_quote + 1; } else if (i < payload.size() && payload[i] == '{') { /* NESTED OBJECT (example, frame={...}) */ int brace_depth = 1; size_t j = i + 1; size_t start_content = j; while (j < payload.size() && brace_depth > 0) { if (payload[j] == '{') brace_depth++; if (payload[j] == '}') brace_depth--; j++; } std::string inner_content = payload.substr(start_content, j - start_content - 1); /* RECURSION: call the same parser for the content inside the brackets */ parseResults(inner_content, res); i = j; } else if (i < payload.size() && payload[i] == '[') { /* List (example., args=[]) - for now, just skip it or save it as text */ size_t bracket_end = payload.find(']', i); res.results[key] = "[]"; i = (bracket_end == std::string::npos) ? payload.size() : bracket_end + 1; } } } void GdbEngine::readLoop() { char buffer[2048]; std::string line; while (true) { ssize_t n = read(out_pipe[0], buffer, sizeof(buffer) - 1); if (n <= 0) break; buffer[n] = '\0'; for (int i = 0; i < n; ++i) { if (buffer[i] == '\n') { processLine(line); line.clear(); } else { line += buffer[i]; } } } } void GdbEngine::processLine(const std::string& raw) { if (raw.empty() || raw == "(gdb) ") return; GdbResponse res; size_t i = 0; /* Extract the token (if present) */ while (i < raw.size() && isdigit(raw[i])) { res.token = res.token * 10 + (raw[i] - '0'); i++; } if (i < raw.size()) { res.type = raw[i]; std::string payload = raw.substr(i + 1); size_t comma = payload.find(','); if (comma != std::string::npos) { res.className = payload.substr(0, comma); parseResults(payload.substr(comma + 1), res); } else { res.className = payload; } } if (on_event) on_event(res); } bool GdbEngine::launch(const std::string& path) { pipe(in_pipe); pipe(out_pipe); gdb_pid = fork(); if (gdb_pid == 0) { setpgid(0, 0); // Create a new process group for signals dup2(in_pipe[0], STDIN_FILENO); dup2(out_pipe[1], STDOUT_FILENO); execlp(path.c_str(), path.c_str(), "--interpreter=mi2", nullptr); _exit(1); } close(in_pipe[0]); close(out_pipe[1]); reader_thread = std::thread(&GdbEngine::readLoop, this); return true; } void GdbEngine::send(const std::string& cmd, int token) { std::lock_guard<std::mutex> lock(write_mutex); std::string full = (token > 0 ? std::to_string(token) : "") + cmd + "\n"; write(in_pipe[1], full.c_str(), full.length()); } /* Send SIGINT process group GDB (button pasue)*/ void GdbEngine::interrupt() { if (gdb_pid > 0) { kill(-gdb_pid, SIGINT); } } void GdbEngine::setHandler(Callback cb) { on_event = cb; } /* Specify the file to debug * Analogous to selecting a project in an IDE */ void GdbManager::loadProcess(const std::string& executablePath) { // -file-exec-and-symbols load code and the symbol table (function name, variables) send("-file-exec-and-symbols " + executablePath); } /* Set breakpoint * Takes (filename, line_number). */ void GdbManager::setBreakpoint(const std::string& filename, int line) { // Format: -break-insert filename:line send("-break-insert " + filename + ":" + std::to_string(line)); } /* Remove breakpoint * Takes (filename, line_number). */ void GdbManager::removeBreakpoint(const std::string& filename, int line) { send("-break-delete " + filename + ":" + std::to_string(line)); } /* Remove breakpoint * Takes (breakpoint id). */ void GdbManager::removeBreakpoint(int breakpointId) { send("-break-delete " + std::to_string(breakpointId)); } /* Start debug */ void GdbManager::run() { send("-exec-run"); } /* Step control */ void GdbManager::stepOver() { send("-exec-next"); } // Перейти на след. строку void GdbManager::stepInto() { send("-exec-step"); } // Зайти внутрь функции void GdbManager::stepOut() { send("-exec-finish"); } // Выйти из функции void GdbManager::continueExecution() { send("-exec-continue"); } // Продолжить до след. брейкпоинта /* Remove debug (gdbserver) */ void GdbManager::connectToRemote(const std::string& host, int port) { send("-target-select remote " + host + ":" + std::to_string(port)); }