Skip to content

Commit 3a367b3

Browse files
[lldb-server][NFC] Factor out code handling breakpoint packets
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. #192910
1 parent 2abeafc commit 3a367b3

2 files changed

Lines changed: 176 additions & 106 deletions

File tree

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

Lines changed: 148 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -2903,155 +2903,172 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo(
29032903
return SendPacketNoLock(response.GetString());
29042904
}
29052905

2906-
GDBRemoteCommunication::PacketResult
2907-
GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) {
2906+
namespace {
2907+
/// Helper struct to expand a GDBStoppointType into flags.
2908+
struct BreakpointKind {
2909+
bool want_hardware;
2910+
bool want_breakpoint;
2911+
uint32_t watch_flags;
2912+
2913+
/// Invalid types must be handled prior to calling this.
2914+
BreakpointKind(GDBStoppointType stoppoint_type) {
2915+
switch (stoppoint_type) {
2916+
case eBreakpointSoftware:
2917+
want_hardware = false;
2918+
want_breakpoint = true;
2919+
break;
2920+
case eBreakpointHardware:
2921+
want_hardware = true;
2922+
want_breakpoint = true;
2923+
break;
2924+
case eWatchpointWrite:
2925+
watch_flags = 1;
2926+
want_hardware = true;
2927+
want_breakpoint = false;
2928+
break;
2929+
case eWatchpointRead:
2930+
watch_flags = 2;
2931+
want_hardware = true;
2932+
want_breakpoint = false;
2933+
break;
2934+
case eWatchpointReadWrite:
2935+
watch_flags = 3;
2936+
want_hardware = true;
2937+
want_breakpoint = false;
2938+
break;
2939+
default:
2940+
llvm_unreachable("unhandled GDBStoppointType");
2941+
}
2942+
}
2943+
};
2944+
2945+
/// If stoppoint_type is a valid type, create a BreakpointKind, otherwise
2946+
/// returns nullopt.
2947+
std::optional<BreakpointKind>
2948+
getBreakpointKind(GDBStoppointType stoppoint_type) {
2949+
switch (stoppoint_type) {
2950+
case eBreakpointSoftware:
2951+
case eBreakpointHardware:
2952+
case eWatchpointWrite:
2953+
case eWatchpointRead:
2954+
case eWatchpointReadWrite:
2955+
return BreakpointKind(stoppoint_type);
2956+
case eStoppointInvalid:
2957+
break;
2958+
}
2959+
return std::nullopt;
2960+
}
2961+
} // namespace
2962+
2963+
GDBRemoteCommunicationServerLLGS::BreakpointResult
2964+
GDBRemoteCommunicationServerLLGS::ExecuteSetBreakpoint(
2965+
llvm::StringRef packet_str) {
29082966
// Ensure we have a process.
29092967
if (!m_current_process ||
29102968
(m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
29112969
Log *log = GetLog(LLDBLog::Process);
29122970
LLDB_LOG(log, "failed, no process available");
2913-
return SendErrorResponse(0x15);
2971+
return BreakpointResult::CreateError(0x15);
29142972
}
29152973

2974+
StringExtractorGDBRemote packet(packet_str);
2975+
29162976
// Parse out software or hardware breakpoint or watchpoint requested.
29172977
packet.SetFilePos(strlen("Z"));
29182978
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;
2979+
return BreakpointResult::CreateIllFormed(
2980+
"Too short Z packet, missing software/hardware specifier");
29252981

29262982
const GDBStoppointType stoppoint_type =
29272983
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-
}
2984+
std::optional<BreakpointKind> bp_kind = getBreakpointKind(stoppoint_type);
2985+
if (!bp_kind)
2986+
return BreakpointResult::CreateIllFormed(
2987+
"Z packet had invalid software/hardware specifier");
29562988

29572989
if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
2958-
return SendIllFormedResponse(
2959-
packet, "Malformed Z packet, expecting comma after stoppoint type");
2990+
return BreakpointResult::CreateIllFormed(
2991+
"Malformed Z packet, expecting comma after stoppoint type");
29602992

29612993
// Parse out the stoppoint address.
29622994
if (packet.GetBytesLeft() < 1)
2963-
return SendIllFormedResponse(packet, "Too short Z packet, missing address");
2995+
return BreakpointResult::CreateIllFormed(
2996+
"Too short Z packet, missing address");
29642997
const lldb::addr_t addr = packet.GetHexMaxU64(false, 0);
29652998

29662999
if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
2967-
return SendIllFormedResponse(
2968-
packet, "Malformed Z packet, expecting comma after address");
3000+
return BreakpointResult::CreateIllFormed(
3001+
"Malformed Z packet, expecting comma after address");
29693002

29703003
// Parse out the stoppoint size (i.e. size hint for opcode size).
29713004
const uint32_t size =
29723005
packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
29733006
if (size == std::numeric_limits<uint32_t>::max())
2974-
return SendIllFormedResponse(
2975-
packet, "Malformed Z packet, failed to parse size argument");
3007+
return BreakpointResult::CreateIllFormed(
3008+
"Malformed Z packet, failed to parse size argument");
29763009

2977-
if (want_breakpoint) {
3010+
if (bp_kind->want_breakpoint) {
29783011
// Try to set the breakpoint.
29793012
const Status error =
2980-
m_current_process->SetBreakpoint(addr, size, want_hardware);
3013+
m_current_process->SetBreakpoint(addr, size, bp_kind->want_hardware);
29813014
if (error.Success())
2982-
return SendOKResponse();
3015+
return BreakpointResult::CreateOK();
29833016
Log *log = GetLog(LLDBLog::Breakpoints);
29843017
LLDB_LOG(log, "pid {0} failed to set breakpoint: {1}",
29853018
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-
}
3019+
return BreakpointResult::CreateError(0x09);
3020+
}
3021+
3022+
// Try to set the watchpoint.
3023+
const Status error = m_current_process->SetWatchpoint(
3024+
addr, size, bp_kind->watch_flags, bp_kind->want_hardware);
3025+
if (error.Success())
3026+
return BreakpointResult::CreateOK();
3027+
Log *log = GetLog(LLDBLog::Watchpoints);
3028+
LLDB_LOG(log, "pid {0} failed to set watchpoint: {1}",
3029+
m_current_process->GetID(), error);
3030+
return BreakpointResult::CreateError(0x09);
29983031
}
29993032

3000-
GDBRemoteCommunication::PacketResult
3001-
GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
3033+
GDBRemoteCommunicationServerLLGS::BreakpointResult
3034+
GDBRemoteCommunicationServerLLGS::ExecuteRemoveBreakpoint(
3035+
llvm::StringRef packet_str) {
30023036
// Ensure we have a process.
30033037
if (!m_current_process ||
30043038
(m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
30053039
Log *log = GetLog(LLDBLog::Process);
30063040
LLDB_LOG(log, "failed, no process available");
3007-
return SendErrorResponse(0x15);
3041+
return BreakpointResult::CreateError(0x15);
30083042
}
30093043

3044+
StringExtractorGDBRemote packet(packet_str);
3045+
30103046
// Parse out software or hardware breakpoint or watchpoint requested.
30113047
packet.SetFilePos(strlen("z"));
30123048
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;
3049+
return BreakpointResult::CreateIllFormed(
3050+
"Too short z packet, missing software/hardware specifier");
30183051

30193052
const GDBStoppointType stoppoint_type =
30203053
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-
}
3054+
std::optional<BreakpointKind> bp_kind = getBreakpointKind(stoppoint_type);
3055+
if (!bp_kind)
3056+
return BreakpointResult::CreateIllFormed(
3057+
"z packet had invalid software/hardware specifier");
30423058

30433059
if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
3044-
return SendIllFormedResponse(
3045-
packet, "Malformed z packet, expecting comma after stoppoint type");
3060+
return BreakpointResult::CreateIllFormed(
3061+
"Malformed z packet, expecting comma after stoppoint type");
30463062

30473063
// Parse out the stoppoint address.
30483064
if (packet.GetBytesLeft() < 1)
3049-
return SendIllFormedResponse(packet, "Too short z packet, missing address");
3065+
return BreakpointResult::CreateIllFormed(
3066+
"Too short z packet, missing address");
30503067
const lldb::addr_t addr = packet.GetHexMaxU64(false, 0);
30513068

30523069
if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
3053-
return SendIllFormedResponse(
3054-
packet, "Malformed z packet, expecting comma after address");
3070+
return BreakpointResult::CreateIllFormed(
3071+
"Malformed z packet, expecting comma after address");
30553072

30563073
/*
30573074
// Parse out the stoppoint size (i.e. size hint for opcode size).
@@ -3062,26 +3079,51 @@ GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
30623079
size argument");
30633080
*/
30643081

3065-
if (want_breakpoint) {
3082+
if (bp_kind->want_breakpoint) {
30663083
// Try to clear the breakpoint.
30673084
const Status error =
3068-
m_current_process->RemoveBreakpoint(addr, want_hardware);
3085+
m_current_process->RemoveBreakpoint(addr, bp_kind->want_hardware);
30693086
if (error.Success())
3070-
return SendOKResponse();
3087+
return BreakpointResult::CreateOK();
30713088
Log *log = GetLog(LLDBLog::Breakpoints);
30723089
LLDB_LOG(log, "pid {0} failed to remove breakpoint: {1}",
30733090
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);
3091+
return BreakpointResult::CreateError(0x09);
3092+
}
3093+
// Try to clear the watchpoint.
3094+
const Status error = m_current_process->RemoveWatchpoint(addr);
3095+
if (error.Success())
3096+
return BreakpointResult::CreateOK();
3097+
Log *log = GetLog(LLDBLog::Watchpoints);
3098+
LLDB_LOG(log, "pid {0} failed to remove watchpoint: {1}",
3099+
m_current_process->GetID(), error);
3100+
return BreakpointResult::CreateError(0x09);
3101+
}
3102+
3103+
GDBRemoteCommunication::PacketResult
3104+
GDBRemoteCommunicationServerLLGS::SendBreakpointResponse(
3105+
StringExtractorGDBRemote &packet, const BreakpointResult &result) {
3106+
switch (result.kind) {
3107+
case BreakpointResult::Kind::OK:
3108+
return SendOKResponse();
3109+
case BreakpointResult::Kind::Error:
3110+
return SendErrorResponse(result.error_code);
3111+
case BreakpointResult::Kind::IllFormed:
3112+
return SendIllFormedResponse(packet, result.message.c_str());
30843113
}
3114+
llvm_unreachable("unhandled BreakpointResult kind");
3115+
}
3116+
3117+
GDBRemoteCommunication::PacketResult
3118+
GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) {
3119+
return SendBreakpointResponse(packet,
3120+
ExecuteSetBreakpoint(packet.GetStringRef()));
3121+
}
3122+
3123+
GDBRemoteCommunication::PacketResult
3124+
GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
3125+
return SendBreakpointResponse(packet,
3126+
ExecuteRemoveBreakpoint(packet.GetStringRef()));
30853127
}
30863128

30873129
GDBRemoteCommunication::PacketResult

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

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

310+
/// Helper struct for the Execute{Set,Remove}Breakpoint methods.
311+
struct BreakpointResult {
312+
enum class Kind { OK, Error, IllFormed };
313+
314+
Kind kind;
315+
uint8_t error_code = 0; // Only meaningful when kind == Error.
316+
std::string message; // Only meaningful when kind == IllFormed.
317+
318+
static BreakpointResult CreateOK() { return {Kind::OK, 0, {}}; }
319+
static BreakpointResult CreateError(uint8_t code) {
320+
return {Kind::Error, code, {}};
321+
}
322+
static BreakpointResult CreateIllFormed(std::string msg) {
323+
return {Kind::IllFormed, 0, std::move(msg)};
324+
}
325+
};
326+
327+
/// Core logic for a Z (set breakpoint/watchpoint) request.
328+
BreakpointResult ExecuteSetBreakpoint(llvm::StringRef packet_str);
329+
330+
/// Core logic for a z (remove breakpoint/watchpoint) request.
331+
BreakpointResult ExecuteRemoveBreakpoint(llvm::StringRef packet_str);
332+
333+
/// Convert a BreakpointResult into a PacketResult, sending the appropriate
334+
/// response.
335+
PacketResult SendBreakpointResponse(StringExtractorGDBRemote &packet,
336+
const BreakpointResult &result);
337+
310338
void HandleInferiorState_Exited(NativeProcessProtocol *process);
311339

312340
void HandleInferiorState_Stopped(NativeProcessProtocol *process);

0 commit comments

Comments
 (0)