Skip to content

Commit 3b2c697

Browse files
felipepiovezangithub-actions[bot]
authored andcommitted
Automerge: [lldbremote][NFC] Factor out code handling breakpoint packets (#192915)
This commit extracts the code handling breakpoint packets into a helper function that can be used by a future implementation of the MultiBreakpointPacket. It is meant to be purely NFC. There are two functions handling breakpoint packets (`handle_Z` and `handle_z`) with a lot of repeated code. This commit did not attempt to merge the two, as that would make the diff much larger due to subtle differences in the error message produced by the two. The only deduplication done is in the code processing a GDBStoppointType, where a helper struct (`BreakpointKind`) and function (`std::optional<BreakpointKind> getBreakpointKind(GDBStoppointType stoppoint_type)`) was created. The following PRs are related to the MultiBreakpoint feature: * llvm/llvm-project#192910 * llvm/llvm-project#192914 * llvm/llvm-project#192915 * llvm/llvm-project#192919 * llvm/llvm-project#192962 * llvm/llvm-project#192964 * llvm/llvm-project#192971 * llvm/llvm-project#192988
2 parents eb745ad + c2ab7f2 commit 3b2c697

2 files changed

Lines changed: 152 additions & 109 deletions

File tree

lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp

Lines changed: 130 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <limits>
1616
#include <optional>
1717
#include <thread>
18+
#include <variant>
1819

1920
#include "GDBRemoteCommunicationServerLLGS.h"
2021
#include "lldb/Host/ConnectionFileDescriptor.h"
@@ -2903,155 +2904,146 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo(
29032904
return SendPacketNoLock(response.GetString());
29042905
}
29052906

2906-
GDBRemoteCommunication::PacketResult
2907-
GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) {
2907+
namespace {
2908+
struct UseBreakpoint {
2909+
bool want_hardware = false;
2910+
};
2911+
struct UseWatchpoint {
2912+
uint32_t flags;
2913+
static constexpr bool want_hardware = true;
2914+
};
2915+
struct InvalidStoppoint {};
2916+
2917+
std::variant<UseBreakpoint, UseWatchpoint, InvalidStoppoint>
2918+
getBreakpointKind(GDBStoppointType stoppoint_type) {
2919+
switch (stoppoint_type) {
2920+
case eBreakpointSoftware:
2921+
return UseBreakpoint{/*want_hardware*/ false};
2922+
case eBreakpointHardware:
2923+
return UseBreakpoint{/*want_hardware*/ true};
2924+
case eWatchpointWrite:
2925+
return UseWatchpoint{/*flags*/ 1};
2926+
case eWatchpointRead:
2927+
return UseWatchpoint{/*flags*/ 2};
2928+
case eWatchpointReadWrite:
2929+
return UseWatchpoint{/*flags*/ 3};
2930+
case eStoppointInvalid:
2931+
return InvalidStoppoint();
2932+
}
2933+
llvm_unreachable("unhandled GDBStoppointType");
2934+
}
2935+
} // namespace
2936+
2937+
GDBRemoteCommunicationServerLLGS::BreakpointResult
2938+
GDBRemoteCommunicationServerLLGS::ExecuteSetBreakpoint(
2939+
llvm::StringRef packet_str) {
29082940
// Ensure we have a process.
29092941
if (!m_current_process ||
29102942
(m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
29112943
Log *log = GetLog(LLDBLog::Process);
29122944
LLDB_LOG(log, "failed, no process available");
2913-
return SendErrorResponse(0x15);
2945+
return BreakpointError{0x15};
29142946
}
29152947

2948+
StringExtractorGDBRemote packet(packet_str);
2949+
29162950
// Parse out software or hardware breakpoint or watchpoint requested.
29172951
packet.SetFilePos(strlen("Z"));
29182952
if (packet.GetBytesLeft() < 1)
2919-
return SendIllFormedResponse(
2920-
packet, "Too short Z packet, missing software/hardware specifier");
2921-
2922-
bool want_breakpoint = true;
2923-
bool want_hardware = false;
2924-
uint32_t watch_flags = 0;
2953+
return BreakpointIllFormed{
2954+
"Too short Z packet, missing software/hardware specifier"};
29252955

29262956
const GDBStoppointType stoppoint_type =
29272957
GDBStoppointType(packet.GetS32(eStoppointInvalid));
2928-
switch (stoppoint_type) {
2929-
case eBreakpointSoftware:
2930-
want_hardware = false;
2931-
want_breakpoint = true;
2932-
break;
2933-
case eBreakpointHardware:
2934-
want_hardware = true;
2935-
want_breakpoint = true;
2936-
break;
2937-
case eWatchpointWrite:
2938-
watch_flags = 1;
2939-
want_hardware = true;
2940-
want_breakpoint = false;
2941-
break;
2942-
case eWatchpointRead:
2943-
watch_flags = 2;
2944-
want_hardware = true;
2945-
want_breakpoint = false;
2946-
break;
2947-
case eWatchpointReadWrite:
2948-
watch_flags = 3;
2949-
want_hardware = true;
2950-
want_breakpoint = false;
2951-
break;
2952-
case eStoppointInvalid:
2953-
return SendIllFormedResponse(
2954-
packet, "Z packet had invalid software/hardware specifier");
2955-
}
2958+
std::variant<UseBreakpoint, UseWatchpoint, InvalidStoppoint> bp_variant =
2959+
getBreakpointKind(stoppoint_type);
2960+
if (std::holds_alternative<InvalidStoppoint>(bp_variant))
2961+
return BreakpointIllFormed{
2962+
"Z packet had invalid software/hardware specifier"};
29562963

29572964
if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
2958-
return SendIllFormedResponse(
2959-
packet, "Malformed Z packet, expecting comma after stoppoint type");
2965+
return BreakpointIllFormed{
2966+
"Malformed Z packet, expecting comma after stoppoint type"};
29602967

29612968
// Parse out the stoppoint address.
29622969
if (packet.GetBytesLeft() < 1)
2963-
return SendIllFormedResponse(packet, "Too short Z packet, missing address");
2970+
return BreakpointIllFormed{"Too short Z packet, missing address"};
29642971
const lldb::addr_t addr = packet.GetHexMaxU64(false, 0);
29652972

29662973
if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
2967-
return SendIllFormedResponse(
2968-
packet, "Malformed Z packet, expecting comma after address");
2974+
return BreakpointIllFormed{
2975+
"Malformed Z packet, expecting comma after address"};
29692976

29702977
// Parse out the stoppoint size (i.e. size hint for opcode size).
29712978
const uint32_t size =
29722979
packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
29732980
if (size == std::numeric_limits<uint32_t>::max())
2974-
return SendIllFormedResponse(
2975-
packet, "Malformed Z packet, failed to parse size argument");
2981+
return BreakpointIllFormed{
2982+
"Malformed Z packet, failed to parse size argument"};
29762983

2977-
if (want_breakpoint) {
2978-
// Try to set the breakpoint.
2984+
// Try to set a breakpoint.
2985+
if (auto *bp_kind = std::get_if<UseBreakpoint>(&bp_variant)) {
29792986
const Status error =
2980-
m_current_process->SetBreakpoint(addr, size, want_hardware);
2987+
m_current_process->SetBreakpoint(addr, size, bp_kind->want_hardware);
29812988
if (error.Success())
2982-
return SendOKResponse();
2989+
return BreakpointOK();
29832990
Log *log = GetLog(LLDBLog::Breakpoints);
29842991
LLDB_LOG(log, "pid {0} failed to set breakpoint: {1}",
29852992
m_current_process->GetID(), error);
2986-
return SendErrorResponse(0x09);
2987-
} else {
2988-
// Try to set the watchpoint.
2989-
const Status error = m_current_process->SetWatchpoint(
2990-
addr, size, watch_flags, want_hardware);
2991-
if (error.Success())
2992-
return SendOKResponse();
2993-
Log *log = GetLog(LLDBLog::Watchpoints);
2994-
LLDB_LOG(log, "pid {0} failed to set watchpoint: {1}",
2995-
m_current_process->GetID(), error);
2996-
return SendErrorResponse(0x09);
2997-
}
2993+
return BreakpointError{0x09};
2994+
}
2995+
2996+
// Try to set a watchpoint.
2997+
auto wp_kind = std::get<UseWatchpoint>(bp_variant);
2998+
const Status error = m_current_process->SetWatchpoint(
2999+
addr, size, wp_kind.flags, wp_kind.want_hardware);
3000+
if (error.Success())
3001+
return BreakpointOK();
3002+
Log *log = GetLog(LLDBLog::Watchpoints);
3003+
LLDB_LOG(log, "pid {0} failed to set watchpoint: {1}",
3004+
m_current_process->GetID(), error);
3005+
return BreakpointError{0x09};
29983006
}
29993007

3000-
GDBRemoteCommunication::PacketResult
3001-
GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
3008+
GDBRemoteCommunicationServerLLGS::BreakpointResult
3009+
GDBRemoteCommunicationServerLLGS::ExecuteRemoveBreakpoint(
3010+
llvm::StringRef packet_str) {
30023011
// Ensure we have a process.
30033012
if (!m_current_process ||
30043013
(m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
30053014
Log *log = GetLog(LLDBLog::Process);
30063015
LLDB_LOG(log, "failed, no process available");
3007-
return SendErrorResponse(0x15);
3016+
return BreakpointError{0x15};
30083017
}
30093018

3019+
StringExtractorGDBRemote packet(packet_str);
3020+
30103021
// Parse out software or hardware breakpoint or watchpoint requested.
30113022
packet.SetFilePos(strlen("z"));
30123023
if (packet.GetBytesLeft() < 1)
3013-
return SendIllFormedResponse(
3014-
packet, "Too short z packet, missing software/hardware specifier");
3015-
3016-
bool want_breakpoint = true;
3017-
bool want_hardware = false;
3024+
return BreakpointIllFormed{
3025+
"Too short z packet, missing software/hardware specifier"};
30183026

30193027
const GDBStoppointType stoppoint_type =
30203028
GDBStoppointType(packet.GetS32(eStoppointInvalid));
3021-
switch (stoppoint_type) {
3022-
case eBreakpointHardware:
3023-
want_breakpoint = true;
3024-
want_hardware = true;
3025-
break;
3026-
case eBreakpointSoftware:
3027-
want_breakpoint = true;
3028-
break;
3029-
case eWatchpointWrite:
3030-
want_breakpoint = false;
3031-
break;
3032-
case eWatchpointRead:
3033-
want_breakpoint = false;
3034-
break;
3035-
case eWatchpointReadWrite:
3036-
want_breakpoint = false;
3037-
break;
3038-
default:
3039-
return SendIllFormedResponse(
3040-
packet, "z packet had invalid software/hardware specifier");
3041-
}
3029+
std::variant<UseBreakpoint, UseWatchpoint, InvalidStoppoint> bp_variant =
3030+
getBreakpointKind(stoppoint_type);
3031+
if (std::holds_alternative<InvalidStoppoint>(bp_variant))
3032+
return BreakpointIllFormed{
3033+
"z packet had invalid software/hardware specifier"};
30423034

30433035
if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
3044-
return SendIllFormedResponse(
3045-
packet, "Malformed z packet, expecting comma after stoppoint type");
3036+
return BreakpointIllFormed{
3037+
"Malformed z packet, expecting comma after stoppoint type"};
30463038

30473039
// Parse out the stoppoint address.
30483040
if (packet.GetBytesLeft() < 1)
3049-
return SendIllFormedResponse(packet, "Too short z packet, missing address");
3041+
return BreakpointIllFormed{"Too short z packet, missing address"};
30503042
const lldb::addr_t addr = packet.GetHexMaxU64(false, 0);
30513043

30523044
if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
3053-
return SendIllFormedResponse(
3054-
packet, "Malformed z packet, expecting comma after address");
3045+
return BreakpointIllFormed{
3046+
"Malformed z packet, expecting comma after address"};
30553047

30563048
/*
30573049
// Parse out the stoppoint size (i.e. size hint for opcode size).
@@ -3062,26 +3054,55 @@ GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
30623054
size argument");
30633055
*/
30643056

3065-
if (want_breakpoint) {
3066-
// Try to clear the breakpoint.
3057+
// Try to clear the breakpoint.
3058+
if (auto *bp_kind = std::get_if<UseBreakpoint>(&bp_variant)) {
30673059
const Status error =
3068-
m_current_process->RemoveBreakpoint(addr, want_hardware);
3060+
m_current_process->RemoveBreakpoint(addr, bp_kind->want_hardware);
30693061
if (error.Success())
3070-
return SendOKResponse();
3062+
return BreakpointOK();
30713063
Log *log = GetLog(LLDBLog::Breakpoints);
30723064
LLDB_LOG(log, "pid {0} failed to remove breakpoint: {1}",
30733065
m_current_process->GetID(), error);
3074-
return SendErrorResponse(0x09);
3075-
} else {
3076-
// Try to clear the watchpoint.
3077-
const Status error = m_current_process->RemoveWatchpoint(addr);
3078-
if (error.Success())
3079-
return SendOKResponse();
3080-
Log *log = GetLog(LLDBLog::Watchpoints);
3081-
LLDB_LOG(log, "pid {0} failed to remove watchpoint: {1}",
3082-
m_current_process->GetID(), error);
3083-
return SendErrorResponse(0x09);
3084-
}
3066+
return BreakpointError{0x09};
3067+
}
3068+
// Try to clear the watchpoint.
3069+
const Status error = m_current_process->RemoveWatchpoint(addr);
3070+
if (error.Success())
3071+
return BreakpointOK();
3072+
Log *log = GetLog(LLDBLog::Watchpoints);
3073+
LLDB_LOG(log, "pid {0} failed to remove watchpoint: {1}",
3074+
m_current_process->GetID(), error);
3075+
return BreakpointError{0x09};
3076+
}
3077+
3078+
GDBRemoteCommunication::PacketResult
3079+
GDBRemoteCommunicationServerLLGS::SendBreakpointResponse(
3080+
StringExtractorGDBRemote &packet, const BreakpointResult &result) {
3081+
return std::visit(
3082+
[&](auto &&arg) {
3083+
using T = std::decay_t<decltype(arg)>;
3084+
if constexpr (std::is_same_v<T, BreakpointOK>)
3085+
return SendOKResponse();
3086+
else if constexpr (std::is_same_v<T, BreakpointError>)
3087+
return SendErrorResponse(arg.error_code);
3088+
else if constexpr (std::is_same_v<T, BreakpointIllFormed>)
3089+
return SendIllFormedResponse(packet, arg.message.c_str());
3090+
else
3091+
static_assert(false, "non-exhaustive visitor!");
3092+
},
3093+
result);
3094+
}
3095+
3096+
GDBRemoteCommunication::PacketResult
3097+
GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) {
3098+
return SendBreakpointResponse(packet,
3099+
ExecuteSetBreakpoint(packet.GetStringRef()));
3100+
}
3101+
3102+
GDBRemoteCommunication::PacketResult
3103+
GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
3104+
return SendBreakpointResponse(packet,
3105+
ExecuteRemoveBreakpoint(packet.GetStringRef()));
30853106
}
30863107

30873108
GDBRemoteCommunication::PacketResult

lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,28 @@ class GDBRemoteCommunicationServerLLGS
307307
private:
308308
llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> BuildTargetXml();
309309

310+
struct BreakpointOK {};
311+
struct BreakpointIllFormed {
312+
std::string message;
313+
};
314+
struct BreakpointError {
315+
uint8_t error_code;
316+
};
317+
318+
using BreakpointResult =
319+
std::variant<BreakpointOK, BreakpointIllFormed, BreakpointError>;
320+
321+
/// Core logic for a Z (set breakpoint/watchpoint) request.
322+
BreakpointResult ExecuteSetBreakpoint(llvm::StringRef packet_str);
323+
324+
/// Core logic for a z (remove breakpoint/watchpoint) request.
325+
BreakpointResult ExecuteRemoveBreakpoint(llvm::StringRef packet_str);
326+
327+
/// Convert a BreakpointResult into a PacketResult, sending the appropriate
328+
/// response.
329+
PacketResult SendBreakpointResponse(StringExtractorGDBRemote &packet,
330+
const BreakpointResult &result);
331+
310332
void HandleInferiorState_Exited(NativeProcessProtocol *process);
311333

312334
void HandleInferiorState_Stopped(NativeProcessProtocol *process);

0 commit comments

Comments
 (0)