@@ -53,8 +53,8 @@ static bool Cmd$G(ClientSocket* client, std::string_view data);
5353static bool Cmd$m(ClientSocket* client, std::string_view data);
5454static bool Cmd$M(ClientSocket* client, std::string_view data);
5555static 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);
5858static bool Cmd$vMustReplyEmpty(ClientSocket* client, std::string_view data);
5959static 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+
324358bool GDBServer::Cmd$vMustReplyEmpty(ClientSocket* client, std::string_view data)
325359{
326360 client->SendReplyWithAck ();
0 commit comments