Skip to content

Commit

Permalink
Visualize current paused position with debugger
Browse files Browse the repository at this point in the history
  • Loading branch information
mls-m5 committed Nov 3, 2023
1 parent 101ff13 commit 30f90ca
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 29 deletions.
73 changes: 52 additions & 21 deletions src/plugin/gdbdebugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ void GdbDebugger::run() {
return;
}

updateBreakpointInfo();

_connection.send("run &");
}

Expand Down Expand Up @@ -120,11 +122,6 @@ void GdbDebugger::stepOut() {
_connection.send("finish &");
}

void GdbDebugger::toggleBreakpoint(SourceLocation loc) {
// TODO: Handle unsetting
setBreakpoint(loc);
}

void GdbDebugger::stateCallback(std::function<void(DebuggerState)> f) {
_callback = f;
}
Expand All @@ -134,11 +131,19 @@ void GdbDebugger::breakpointListCallback(
_breakpointListCallback = f;
}

void GdbDebugger::setBreakpoint(SourceLocation loc) {
_connection.send("b " + loc.path.string() + ":" +
std::to_string(loc.position.y() + 1));
waitForDone();
_breakpointInfos.clear();
void GdbDebugger::toggleBreakpoint(SourceLocation loc) {
if (deleteBreakpoint(loc)) {
return;
}
setBreakpoint(loc);
}

void GdbDebugger::updateBreakpointInfo() {
// We cannot simply clear the list since we need to send a message to those
// who need to remove breakpoints
for (auto &it : _breakpointInfos) {
it.second.clear();
}
_connection.send("info b"); // Request information about all set breakpoints
// New breakpoint infos will be added in the input thread
waitForDone();
Expand All @@ -148,7 +153,41 @@ void GdbDebugger::setBreakpoint(SourceLocation loc) {
}
}

void GdbDebugger::deleteBreakpoint(SourceLocation loc) {}
void GdbDebugger::setBreakpoint(SourceLocation loc) {
_connection.send("b " + loc.path.string() + ":" +
std::to_string(loc.position.y() + 1));
waitForDone();
updateBreakpointInfo();
}

bool GdbDebugger::deleteBreakpoint(SourceLocation loc) {
auto didFind = false;
for (auto &file : _breakpointInfos) {
auto ec = std::error_code{};
if (!std::filesystem::equivalent(file.first, loc.path, ec)) {
continue;
}
for (size_t i = 0; i < file.second.size();) {
auto &info = file.second.at(i);
if (loc.position.y() == info.lineNumber) {
_connection.send("delete breakpoint " +
std::to_string(info.breakpointNumber));
waitForDone();
file.second.erase(file.second.begin() + i);
didFind = true;
}
else {
++i;
}
}
break; // Only do one file
}

if (didFind) {
updateBreakpointInfo();
}
return didFind;
}

GdbDebugger::WaitResult GdbDebugger::waitForDone() {
_isWaiting = true;
Expand All @@ -165,7 +204,6 @@ void GdbDebugger::changeState(DebuggerState state) {
}

void GdbDebugger::inputThread(std::istream &in) {

std::smatch matches;

for (std::string line; std::getline(in, line);) {
Expand Down Expand Up @@ -201,14 +239,14 @@ void GdbDebugger::inputThread(std::istream &in) {

if (line.starts_with("~")) {
static const auto re = std::regex{
R"(~"(\d+)\s+breakpoint\s+.* in ([^\s]+) at ([^\s]+):(\d+))"};
R"(~"(\d+)\s+breakpoint\s+.* in (.+) at (.+):(\d+))"};

auto match = std::smatch{};

if (std::regex_search(line, match, re)) {
auto file = match[3].str();
_breakpointInfos[file].push_back({
.breakpointNumber = match[1].str(),
.breakpointNumber = std::stoi(match[1].str()),
.functionSignature = match[2].str(),
.filePath = match[3].str(),
.lineNumber = std::stoul(match[4].str()) - 1,
Expand All @@ -225,15 +263,8 @@ void GdbDebugger::inputThread(std::istream &in) {
static const auto stopExpression = std::regex(
R"_(stopped,reason="([^"]+)",.*?addr="([^"]+)",.*?func="([^"]+)",.*?file="([^"]+)",.*?fullname="([^"]+)",.*?line="([^"]+)")_");
if (std::regex_search(line, matches, stopExpression)) {
// std::cout << "Reason: " << matches[1].str() <<
// std::endl; std::cout << "Address: " <<
// matches[2].str() << std::endl; std::cout << "Function:
// " << matches[3].str() << std::endl; std::cout <<
// "File: " << matches[4].str() << std::endl;
auto fullName = matches[5].str();
// std::cout << "Fullname: " << fullName << std::endl;
auto line = matches[6].str();
// std::cout << "Line: " << line << std::endl;

auto state = DebuggerState{};
state.location.position = {0, std::stoul(line) - 1};
Expand Down
5 changes: 4 additions & 1 deletion src/plugin/gdbdebugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class GdbDebugger : public IDebugger {

void toggleBreakpoint(SourceLocation) override;
void setBreakpoint(SourceLocation) override;
void deleteBreakpoint(SourceLocation) override;
bool deleteBreakpoint(SourceLocation) override;

private:
enum WaitResult {
Expand All @@ -67,6 +67,9 @@ class GdbDebugger : public IDebugger {
std::function<void(std::string_view)> _gdbStatusCallback;
std::function<void(const BreakpointList &)> _breakpointListCallback;

/// Query list of breakpoints from gdb
void updateBreakpointInfo();

void inputThread(std::istream &in);

lsp::Connection _connection;
Expand Down
6 changes: 4 additions & 2 deletions src/plugin/idebugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ struct DebuggerState {
};

struct BreakpointInfo {
std::string breakpointNumber;
int breakpointNumber;
std::string functionSignature;
std::string filePath;
size_t lineNumber; // medit line number, starting with 0
Expand Down Expand Up @@ -84,7 +84,9 @@ class IDebugger {

virtual void toggleBreakpoint(SourceLocation) = 0;
virtual void setBreakpoint(SourceLocation) = 0;
virtual void deleteBreakpoint(SourceLocation) = 0;

/// Try to remove a breakpoint. Return true if successfull
virtual bool deleteBreakpoint(SourceLocation) = 0;

// Watchpoints
// Conditions
Expand Down
43 changes: 38 additions & 5 deletions src/plugin/rundebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,17 @@
#include "text/fstring.h"
#include "views/editor.h"
#include "views/mainwindow.h"
#include <filesystem>
#include <string>
#include <string_view>

namespace {

// Used to remove cursor when program exits
std::filesystem::path lastRunningPosition = {};

} // namespace

void debug(std::shared_ptr<IEnvironment> env) {
auto debugger = env->core().debugger();

Expand Down Expand Up @@ -42,18 +50,43 @@ void debug(std::shared_ptr<IEnvironment> env) {
});
};

static constexpr auto runningDebuggerName = "running-debugger-name";

auto stateCallback = [wenv = env->weak_from_this()](DebuggerState state) {
auto env = wenv.lock();
if (state.state == DebuggerState::Running) {
return;
env->statusMessage(FString{"running application"});
}

/// Todo create some indicator
if (!lastRunningPosition.empty()) {
env->context().guiQueue().addTask([env] {
env->core().files().publishDiagnostics(
lastRunningPosition, runningDebuggerName, {});
});
}

if (state.state == DebuggerState::Stopped) {
return;
env->statusMessage(FString{"running application"});
}

env->context().guiQueue().addTask([state, env] {
env->mainWindow().open(state.location.path,
state.location.position.x(),
state.location.position.y());

auto d = std::vector<Diagnostics::Diagnostic>{};
d.push_back(Diagnostics::Diagnostic{
.type = DiagnosticType::RunningPosition,
.source = runningDebuggerName,
.message = "Paused position",
.range = {.begin = state.location.position,
.end = state.location.position},
});
env->core().files().publishDiagnostics(
state.location.path, runningDebuggerName, std::move(d));
lastRunningPosition = state.location.path;
});
};

Expand All @@ -63,21 +96,21 @@ void debug(std::shared_ptr<IEnvironment> env) {
/// Todo create some indicator
env->context().guiQueue().addTask([infos = std::move(infos), env] {
for (auto &it : infos) {
constexpr auto diagnosticName = "debugger";
auto d = std::vector<Diagnostics::Diagnostic>{};

for (auto &info : it.second) {
d.push_back({
.type = DiagnosticType::Breakpoint,
.source = "debugger",
.message = "breakpoint line " +
std::to_string(info.lineNumber + 1),
.source = diagnosticName,
.message = "breakpoint ",
.range = {.begin = {0, info.lineNumber},
.end = {1, info.lineNumber}},
});
}

env->core().files().publishDiagnostics(
it.first, "gdb", std::move(d));
it.first, diagnosticName, std::move(d));
}
});
};
Expand Down

0 comments on commit 30f90ca

Please sign in to comment.