breakpoints

This commit is contained in:
T0b1
2023-06-04 22:08:49 +02:00
parent 343a30289c
commit 78e7f5cca7
12 changed files with 341 additions and 17 deletions

View File

@@ -12,6 +12,7 @@
#include <array>
#include <cassert>
#include <cstring>
#include <algorithm>
using namespace dbgui::backend;
@@ -132,13 +133,43 @@ void LLDBBackend::handle_state_change(lldb::StateType state)
switch (state)
{
case eStateStopped:
{
this->check_reg_changes();
this->check_thread_changes();
this->check_frame_changes();
this->check_data_changes();
_state = TargetState::paused;
this->send_state_change(TargetState::paused, StateChangeReason::unknown);
// TODO: does the selected thread auto-switch?
auto sel_thread = _process->GetSelectedThread();
auto change_reason = StateChangeReason::unknown;
auto extra = 0;
switch (sel_thread.GetStopReason())
{
case eStopReasonBreakpoint:
{
// what is location id/N for breakpoints?
// does this have to do when there are multiple
// place the same source code ends up?
auto bp_id = sel_thread.GetStopReasonDataAtIndex(0);
// clang-format bugs out on this for some reason
// clang-format off
auto it = std::find_if(
_breakpoints.begin(), _breakpoints.end(),
[bp_id](const auto &el) { return el.lldb_id == bp_id; });
// clang-format on
if (it != _breakpoints.end())
{
change_reason = StateChangeReason::breakpoint;
extra = it->id;
}
break;
}
}
this->send_state_change(TargetState::paused, change_reason, extra);
break;
}
case eStateRunning:
case eStateStepping:
_state = TargetState::running;
@@ -337,7 +368,7 @@ void LLDBBackend::dump_threads()
end = start + 0x100;
}
auto buf = std::vector<uint8_t>{};
/*auto buf = std::vector<uint8_t>{};
buf.resize(end - start);
auto err = SBError{};
_target.ReadMemory(SBAddress{start, _target}, buf.data(), buf.size(), err);
@@ -359,7 +390,7 @@ void LLDBBackend::dump_threads()
{
printf("Selfprint: %s%s\n", inst.GetMnemonic(_target),
inst.GetOperands(_target));
}
}*/
//printf("Disasm: %s\n", frame.Disassemble());
} else
@@ -982,9 +1013,9 @@ dbgui::data::DataResult LLDBBackend::calc_data_res(const data::DataNode &node)
auto addr = inst.GetAddress().GetLoadAddress(_target);
const auto len = inst.GetByteSize();
SBStream stream{};
inst.GetDescription(stream);
printf("Got inst: %.*s\n", stream.GetSize(), stream.GetData());
//SBStream stream{};
//inst.GetDescription(stream);
//printf("Got inst: %.*s\n", stream.GetSize(), stream.GetData());
if (mnem.size() > 255 || op.size() > 255 || comm.size() > 255)
{
@@ -1023,6 +1054,52 @@ dbgui::data::DataResult LLDBBackend::calc_data_res(const data::DataNode &node)
exit(1);
}
void LLDBBackend::add_breakpoint(uint64_t addr, size_t id)
{
std::lock_guard g{_data_lock};
if (!_process)
{
return;
}
if (std::find_if(_breakpoints.begin(), _breakpoints.end(),
[id](const auto &el) { return el.id == id; })
!= _breakpoints.end())
{
printf("Trying to register same breakpoint id\n");
exit(1);
}
auto bp = _target.BreakpointCreateByAddress(addr);
_breakpoints.push_back(Breakpoint{.id = id, .lldb_id = bp.GetID()});
}
void LLDBBackend::remove_breakpoint(size_t id)
{
std::lock_guard g{_data_lock};
if (!_process)
{
return;
}
auto it = std::find_if(_breakpoints.begin(), _breakpoints.end(),
[id](const auto &el) { return el.id == id; });
if (it == _breakpoints.end())
{
printf("Trying to delete nonexistant breakpoint\n");
exit(1);
}
// TODO: error handling?
_target.BreakpointDelete(it->lldb_id);
// TODO: this should check if there are no pending events in the debugger event queue
// to make sure we did not hit the breakpoint before deleting it
// maybe really add like a custom event type to send to the event queue?
// afterwards it should send a bp deleted msg so the UI can sync this, too
_breakpoints.erase(it);
}
/*
Reg output for x64
Got register set General Purpose Registers