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
30873108GDBRemoteCommunication::PacketResult
0 commit comments