Skip to content

Commit 7bae23d

Browse files
committed
GDBServer: Implement memory breakpoints
1 parent a0c06f8 commit 7bae23d

1 file changed

Lines changed: 58 additions & 24 deletions

File tree

src/core/gdb_server.cpp

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ static bool Cmd$G(ClientSocket* client, std::string_view data);
5353
static bool Cmd$m(ClientSocket* client, std::string_view data);
5454
static bool Cmd$M(ClientSocket* client, std::string_view data);
5555
static bool Cmd$s(ClientSocket* client, std::string_view data);
56-
static bool Cmd$z1(ClientSocket* client, std::string_view data);
57-
static bool Cmd$Z1(ClientSocket* client, std::string_view data);
56+
template<bool add_breakpoint>
57+
static bool Cmd$z(ClientSocket* client, std::string_view data);
5858
static bool Cmd$vMustReplyEmpty(ClientSocket* client, std::string_view data);
5959
static bool Cmd$qSupported(ClientSocket* client, std::string_view data);
6060

@@ -122,10 +122,8 @@ static constexpr std::pair<std::string_view, bool (*)(ClientSocket*, std::string
122122
{"m", Cmd$m},
123123
{"M", Cmd$M},
124124
{"s", Cmd$s},
125-
{"z0,", Cmd$z1},
126-
{"Z0,", Cmd$Z1},
127-
{"z1,", Cmd$z1},
128-
{"Z1,", Cmd$Z1},
125+
{"z", Cmd$z<false>},
126+
{"Z", Cmd$z<true>},
129127
{"vMustReplyEmpty", Cmd$vMustReplyEmpty},
130128
{"qSupported", Cmd$qSupported},
131129
};
@@ -286,41 +284,77 @@ bool GDBServer::Cmd$s(ClientSocket* client, std::string_view data)
286284
return true;
287285
}
288286

289-
/// Remove hardware breakpoint.
290-
bool GDBServer::Cmd$z1(ClientSocket* client, std::string_view data)
287+
/// Remove hardware breakpoint (z).
288+
/// Insert hardware breakpoint (Z).
289+
template<bool add_breakpoint>
290+
bool GDBServer::Cmd$z(ClientSocket* client, std::string_view data)
291291
{
292-
const std::optional<VirtualMemoryAddress> address = StringUtil::FromChars<VirtualMemoryAddress>(data, 16);
293-
if (address.has_value())
292+
std::string_view caret = data;
293+
std::optional<u32> bptype;
294+
std::optional<VirtualMemoryAddress> bpaddr;
295+
296+
// type,addr
297+
if (!(bptype = StringUtil::FromChars<u32>(caret, 10, &caret)) || caret.empty() || caret[0] != ',' ||
298+
!(bpaddr = StringUtil::FromChars<VirtualMemoryAddress>(caret.substr(1), 16)).has_value())
294299
{
295-
CPU::RemoveBreakpoint(CPU::BreakpointType::Execute, *address);
300+
ERROR_LOG("Invalid {} hw breakpoint packet: {}", add_breakpoint ? "add" : "remove", data);
301+
return false;
302+
}
303+
304+
if (bptype.value() == 0 || bptype.value() == 1) // software/hardware breakpoint
305+
{
306+
if constexpr (add_breakpoint)
307+
CPU::AddBreakpoint(CPU::BreakpointType::Execute, bpaddr.value());
308+
else
309+
CPU::RemoveBreakpoint(CPU::BreakpointType::Execute, bpaddr.value());
296310
client->SendReplyWithAck("OK");
297311
return true;
298312
}
299-
else
313+
else if (bptype.value() == 2) // write breakpoint
300314
{
301-
ERROR_LOG("Invalid address to remove hw breakpoint: ", data);
302-
client->SendReplyWithAck();
303-
return false;
304-
}
305-
}
315+
if constexpr (add_breakpoint)
316+
CPU::AddBreakpoint(CPU::BreakpointType::Write, bpaddr.value());
317+
else
318+
CPU::RemoveBreakpoint(CPU::BreakpointType::Write, bpaddr.value());
306319

307-
/// Insert hardware breakpoint.
308-
bool GDBServer::Cmd$Z1(ClientSocket* client, std::string_view data)
309-
{
310-
const std::optional<VirtualMemoryAddress> address = StringUtil::FromChars<VirtualMemoryAddress>(data, 16);
311-
if (address)
320+
client->SendReplyWithAck("OK");
321+
return true;
322+
}
323+
else if (bptype.value() == 3) // read breakpoint
324+
{
325+
if constexpr (add_breakpoint)
326+
CPU::AddBreakpoint(CPU::BreakpointType::Read, bpaddr.value());
327+
else
328+
CPU::RemoveBreakpoint(CPU::BreakpointType::Read, bpaddr.value());
329+
client->SendReplyWithAck("OK");
330+
return true;
331+
}
332+
else if (bptype.value() == 4) // read+write breakpoint
312333
{
313-
CPU::AddBreakpoint(CPU::BreakpointType::Execute, *address, false);
334+
if constexpr (add_breakpoint)
335+
{
336+
CPU::AddBreakpoint(CPU::BreakpointType::Read, bpaddr.value());
337+
CPU::AddBreakpoint(CPU::BreakpointType::Write, bpaddr.value());
338+
}
339+
else
340+
{
341+
CPU::RemoveBreakpoint(CPU::BreakpointType::Read, bpaddr.value());
342+
CPU::RemoveBreakpoint(CPU::BreakpointType::Write, bpaddr.value());
343+
}
344+
314345
client->SendReplyWithAck("OK");
315346
return true;
316347
}
317348
else
318349
{
319-
ERROR_LOG("Invalid address to insert hw breakpoint: ", data);
350+
ERROR_LOG("Unknown breakpoint type {}", bptype.value());
320351
return false;
321352
}
322353
}
323354

355+
template bool GDBServer::Cmd$z<false>(ClientSocket* client, std::string_view data);
356+
template bool GDBServer::Cmd$z<true>(ClientSocket* client, std::string_view data);
357+
324358
bool GDBServer::Cmd$vMustReplyEmpty(ClientSocket* client, std::string_view data)
325359
{
326360
client->SendReplyWithAck();

0 commit comments

Comments
 (0)