summaryrefslogtreecommitdiffstats
path: root/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp')
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp420
1 files changed, 280 insertions, 140 deletions
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index a714950..dd920c0 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -34,16 +34,18 @@
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
+#include "lldb/Host/StringConvert.h"
#include "lldb/Host/TimeValue.h"
#include "lldb/Target/FileAction.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
-#include "lldb/Target/NativeRegisterContext.h"
-#include "Host/common/NativeProcessProtocol.h"
-#include "Host/common/NativeThreadProtocol.h"
+#include "lldb/Host/common/NativeRegisterContext.h"
+#include "lldb/Host/common/NativeProcessProtocol.h"
+#include "lldb/Host/common/NativeThreadProtocol.h"
// Project includes
#include "Utility/StringExtractorGDBRemote.h"
+#include "Utility/UriParser.h"
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
@@ -276,6 +278,10 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
packet_result = Handle_qPlatform_shell (packet);
break;
+ case StringExtractorGDBRemote::eServerPacketType_qWatchpointSupportInfo:
+ packet_result = Handle_qWatchpointSupportInfo (packet);
+ break;
+
case StringExtractorGDBRemote::eServerPacketType_C:
packet_result = Handle_C (packet);
break;
@@ -364,6 +370,10 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
packet_result = Handle_H (packet);
break;
+ case StringExtractorGDBRemote::eServerPacketType_I:
+ packet_result = Handle_I (packet);
+ break;
+
case StringExtractorGDBRemote::eServerPacketType_m:
packet_result = Handle_m (packet);
break;
@@ -601,14 +611,12 @@ GDBRemoteCommunicationServer::LaunchPlatformProcess ()
// add to list of spawned processes. On an lldb-gdbserver, we
// would expect there to be only one.
- lldb::pid_t pid;
- if ( (pid = m_process_launch_info.GetProcessID()) != LLDB_INVALID_PROCESS_ID )
+ const auto pid = m_process_launch_info.GetProcessID();
+ if (pid != LLDB_INVALID_PROCESS_ID)
{
// add to spawned pids
- {
- Mutex::Locker locker (m_spawned_pids_mutex);
- m_spawned_pids.insert(pid);
- }
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ m_spawned_pids.insert(pid);
}
return error;
@@ -835,12 +843,12 @@ GDBRemoteCommunicationServer::SendStopReplyPacketForThread (lldb::tid_t tid)
// Grab the reason this thread stopped.
struct ThreadStopInfo tid_stop_info;
- if (!thread_sp->GetStopReason (tid_stop_info))
+ std::string description;
+ if (!thread_sp->GetStopReason (tid_stop_info, description))
return SendErrorResponse (52);
- const bool did_exec = tid_stop_info.reason == eStopReasonExec;
// FIXME implement register handling for exec'd inferiors.
- // if (did_exec)
+ // if (tid_stop_info.reason == eStopReasonExec)
// {
// const bool force = true;
// InitializeRegisters(force);
@@ -861,25 +869,6 @@ GDBRemoteCommunicationServer::SendStopReplyPacketForThread (lldb::tid_t tid)
tid_stop_info.details.exception.type);
}
- switch (tid_stop_info.reason)
- {
- case eStopReasonSignal:
- case eStopReasonException:
- signum = thread_sp->TranslateStopInfoToGdbSignal (tid_stop_info);
- break;
- default:
- signum = 0;
- if (log)
- {
- log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " tid %" PRIu64 " has stop reason %d, using signo = 0 in stop reply response",
- __FUNCTION__,
- m_debugged_process_sp->GetID (),
- tid,
- tid_stop_info.reason);
- }
- break;
- }
-
// Print the signal number.
response.PutHex8 (signum & 0xff);
@@ -906,14 +895,6 @@ GDBRemoteCommunicationServer::SendStopReplyPacketForThread (lldb::tid_t tid)
response.PutChar (';');
}
- // FIXME look for analog
- // thread_identifier_info_data_t thread_ident_info;
- // if (DNBThreadGetIdentifierInfo (pid, tid, &thread_ident_info))
- // {
- // if (thread_ident_info.dispatch_qaddr != 0)
- // ostrm << std::hex << "qaddr:" << thread_ident_info.dispatch_qaddr << ';';
- // }
-
// If a 'QListThreadsInStopReply' was sent to enable this feature, we
// will send all thread IDs back in the "threads" key whose value is
// a list of hex thread IDs separated by commas:
@@ -978,9 +959,45 @@ GDBRemoteCommunicationServer::SendStopReplyPacketForThread (lldb::tid_t tid)
}
}
- if (did_exec)
+ const char* reason_str = nullptr;
+ switch (tid_stop_info.reason)
+ {
+ case eStopReasonTrace:
+ reason_str = "trace";
+ break;
+ case eStopReasonBreakpoint:
+ reason_str = "breakpoint";
+ break;
+ case eStopReasonWatchpoint:
+ reason_str = "watchpoint";
+ break;
+ case eStopReasonSignal:
+ reason_str = "signal";
+ break;
+ case eStopReasonException:
+ reason_str = "exception";
+ break;
+ case eStopReasonExec:
+ reason_str = "exec";
+ break;
+ case eStopReasonInstrumentation:
+ case eStopReasonInvalid:
+ case eStopReasonPlanComplete:
+ case eStopReasonThreadExiting:
+ case eStopReasonNone:
+ break;
+ }
+ if (reason_str != nullptr)
+ {
+ response.Printf ("reason:%s;", reason_str);
+ }
+
+ if (!description.empty())
{
- response.PutCString ("reason:exec;");
+ // Description may contains special chars, send as hex bytes.
+ response.PutCString ("description:");
+ response.PutCStringAsRawHex8 (description.c_str ());
+ response.PutChar (';');
}
else if ((tid_stop_info.reason == eStopReasonException) && tid_stop_info.details.exception.type)
{
@@ -1422,23 +1439,34 @@ CreateProcessInfoResponse_DebugServerStyle (const ProcessInstanceInfo &proc_info
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_qProcessInfo (StringExtractorGDBRemote &packet)
{
- // Only the gdb server handles this.
- if (!IsGdbServer ())
- return SendUnimplementedResponse (packet.GetStringRef ().c_str ());
-
- // Fail if we don't have a current process.
- if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
- return SendErrorResponse (68);
-
- ProcessInstanceInfo proc_info;
- if (Host::GetProcessInfo (m_debugged_process_sp->GetID (), proc_info))
+ lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+
+ if (IsGdbServer ())
{
- StreamString response;
- CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
- return SendPacketNoLock (response.GetData (), response.GetSize ());
+ // Fail if we don't have a current process.
+ if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse (68);
+
+ pid = m_debugged_process_sp->GetID ();
}
-
- return SendErrorResponse (1);
+ else if (m_is_platform)
+ {
+ pid = m_process_launch_info.GetProcessID ();
+ m_process_launch_info.Clear ();
+ }
+ else
+ return SendUnimplementedResponse (packet.GetStringRef ().c_str ());
+
+ if (pid == LLDB_INVALID_PROCESS_ID)
+ return SendErrorResponse (1);
+
+ ProcessInstanceInfo proc_info;
+ if (!Host::GetProcessInfo (pid, proc_info))
+ return SendErrorResponse (1);
+
+ StreamString response;
+ CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
+ return SendPacketNoLock (response.GetData (), response.GetSize ());
}
GDBRemoteCommunication::PacketResult
@@ -1512,27 +1540,27 @@ GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &pa
}
else if (key.compare("pid") == 0)
{
- match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
+ match_info.GetProcessInfo().SetProcessID (StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
}
else if (key.compare("parent_pid") == 0)
{
- match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
+ match_info.GetProcessInfo().SetParentProcessID (StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
}
else if (key.compare("uid") == 0)
{
- match_info.GetProcessInfo().SetUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
+ match_info.GetProcessInfo().SetUserID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success));
}
else if (key.compare("gid") == 0)
{
- match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
+ match_info.GetProcessInfo().SetGroupID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success));
}
else if (key.compare("euid") == 0)
{
- match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
+ match_info.GetProcessInfo().SetEffectiveUserID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success));
}
else if (key.compare("egid") == 0)
{
- match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
+ match_info.GetProcessInfo().SetEffectiveGroupID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success));
}
else if (key.compare("all_users") == 0)
{
@@ -1627,7 +1655,7 @@ GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packe
bool success = packet.GetNameColonValue(key, value);
if (success && key.compare("response_size") == 0)
{
- uint32_t response_size = Args::StringToUInt32(value.c_str(), 0, 0, &success);
+ uint32_t response_size = StringConvert::ToUInt32(value.c_str(), 0, 0, &success);
if (success)
{
if (response_size == 0)
@@ -1901,7 +1929,7 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote
if (name.compare ("host") == 0)
hostname.swap(value);
else if (name.compare ("port") == 0)
- port = Args::StringToUInt32(value.c_str(), 0, 0);
+ port = StringConvert::ToUInt32(value.c_str(), 0, 0);
}
if (port == UINT16_MAX)
port = GetNextAvailablePort();
@@ -1909,6 +1937,9 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote
// Spawn a new thread to accept the port that gets bound after
// binding to port 0 (zero).
+ // ignore the hostname send from the remote end, just use the ip address
+ // that we're currently communicating with as the hostname
+
// Spawn a debugserver and try to get the port it listens to.
ProcessLaunchInfo debugserver_launch_info;
if (hostname.empty())
@@ -1916,9 +1947,19 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote
if (log)
log->Printf("Launching debugserver with: %s:%u...\n", hostname.c_str(), port);
+ // Do not run in a new session so that it can not linger after the
+ // platform closes.
+ debugserver_launch_info.SetLaunchInSeparateProcessGroup(false);
debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false);
- Error error = StartDebugserverProcess (hostname.empty() ? NULL : hostname.c_str(),
+ std::string platform_scheme;
+ std::string platform_ip;
+ int platform_port;
+ std::string platform_path;
+ bool ok = UriParser::Parse(GetConnection()->GetURI().c_str(), platform_scheme, platform_ip, platform_port, platform_path);
+ assert(ok);
+ Error error = StartDebugserverProcess (
+ platform_ip.c_str(),
port,
debugserver_launch_info,
port);
@@ -2502,10 +2543,6 @@ GDBRemoteCommunicationServer::Handle_vCont (StringExtractorGDBRemote &packet)
thread_actions.Append (thread_action);
}
- // If a default action for all other threads wasn't mentioned
- // then we should stop the threads.
- thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
-
Error error = m_debugged_process_sp->Resume (thread_actions);
if (error.Fail ())
{
@@ -2983,7 +3020,7 @@ GDBRemoteCommunicationServer::Handle_qRegisterInfo (StringExtractorGDBRemote &pa
return SendErrorResponse (69);
// Return the end of registers response if we've iterated one past the end of the register set.
- if (reg_index >= reg_context_sp->GetRegisterCount ())
+ if (reg_index >= reg_context_sp->GetUserRegisterCount ())
return SendErrorResponse (69);
const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex(reg_index);
@@ -3184,10 +3221,10 @@ GDBRemoteCommunicationServer::Handle_p (StringExtractorGDBRemote &packet)
}
// Return the end of registers response if we've iterated one past the end of the register set.
- if (reg_index >= reg_context_sp->GetRegisterCount ())
+ if (reg_index >= reg_context_sp->GetUserRegisterCount ())
{
if (log)
- log->Printf ("GDBRemoteCommunicationServer::%s failed, requested register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetRegisterCount ());
+ log->Printf ("GDBRemoteCommunicationServer::%s failed, requested register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetUserRegisterCount ());
return SendErrorResponse (0x15);
}
@@ -3264,7 +3301,8 @@ GDBRemoteCommunicationServer::Handle_P (StringExtractorGDBRemote &packet)
}
// Parse out the value.
- const uint64_t raw_value = packet.GetHexMaxU64 (process_arch.GetByteOrder () == lldb::eByteOrderLittle, std::numeric_limits<uint64_t>::max ());
+ uint8_t reg_bytes[32]; // big enough to support up to 256 bit ymmN register
+ size_t reg_size = packet.GetHexBytesAvail (reg_bytes, sizeof(reg_bytes));
// Get the thread to use.
NativeThreadProtocolSP thread_sp = GetThreadFromSuffix (packet);
@@ -3284,7 +3322,7 @@ GDBRemoteCommunicationServer::Handle_P (StringExtractorGDBRemote &packet)
return SendErrorResponse (0x15);
}
- const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex(reg_index);
+ const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex (reg_index);
if (!reg_info)
{
if (log)
@@ -3293,20 +3331,23 @@ GDBRemoteCommunicationServer::Handle_P (StringExtractorGDBRemote &packet)
}
// Return the end of registers response if we've iterated one past the end of the register set.
- if (reg_index >= reg_context_sp->GetRegisterCount ())
+ if (reg_index >= reg_context_sp->GetUserRegisterCount ())
{
if (log)
- log->Printf ("GDBRemoteCommunicationServer::%s failed, requested register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetRegisterCount ());
+ log->Printf ("GDBRemoteCommunicationServer::%s failed, requested register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetUserRegisterCount ());
return SendErrorResponse (0x47);
}
+ if (reg_size != reg_info->byte_size)
+ {
+ return SendIllFormedResponse (packet, "P packet register size is incorrect");
+ }
// Build the reginfos response.
StreamGDBRemote response;
- // FIXME Could be suffixed with a thread: parameter.
- // That thread then needs to be fed back into the reg context retrieval above.
- Error error = reg_context_sp->WriteRegisterFromUnsigned (reg_info, raw_value);
+ RegisterValue reg_value (reg_bytes, reg_size, process_arch.GetByteOrder ());
+ Error error = reg_context_sp->WriteRegister (reg_info, reg_value);
if (error.Fail ())
{
if (log)
@@ -3394,6 +3435,46 @@ GDBRemoteCommunicationServer::Handle_H (StringExtractorGDBRemote &packet)
}
GDBRemoteCommunicationServer::PacketResult
+GDBRemoteCommunicationServer::Handle_I (StringExtractorGDBRemote &packet)
+{
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+
+ // Ensure we're llgs.
+ if (!IsGdbServer())
+ return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_I() unimplemented");
+
+ // Fail if we don't have a current process.
+ if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed, no process available", __FUNCTION__);
+ return SendErrorResponse (0x15);
+ }
+
+ packet.SetFilePos (::strlen("I"));
+ char tmp[4096];
+ for (;;)
+ {
+ size_t read = packet.GetHexBytesAvail(tmp, sizeof(tmp));
+ if (read == 0)
+ {
+ break;
+ }
+ // write directly to stdin *this might block if stdin buffer is full*
+ // TODO: enqueue this block in circular buffer and send window size to remote host
+ ConnectionStatus status;
+ Error error;
+ m_stdio_communication.Write(tmp, read, status, &error);
+ if (error.Fail())
+ {
+ return SendErrorResponse (0x15);
+ }
+ }
+
+ return SendOKResponse();
+}
+
+GDBRemoteCommunicationServer::PacketResult
GDBRemoteCommunicationServer::Handle_interrupt (StringExtractorGDBRemote &packet)
{
Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
@@ -3704,8 +3785,6 @@ GDBRemoteCommunicationServer::Handle_qMemoryRegionInfo (StringExtractorGDBRemote
GDBRemoteCommunicationServer::PacketResult
GDBRemoteCommunicationServer::Handle_Z (StringExtractorGDBRemote &packet)
{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
-
// We don't support if we're not llgs.
if (!IsGdbServer())
return SendUnimplementedResponse ("");
@@ -3713,12 +3792,13 @@ GDBRemoteCommunicationServer::Handle_Z (StringExtractorGDBRemote &packet)
// Ensure we have a process.
if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
{
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
if (log)
log->Printf ("GDBRemoteCommunicationServer::%s failed, no process available", __FUNCTION__);
return SendErrorResponse (0x15);
}
- // Parse out software or hardware breakpoint requested.
+ // Parse out software or hardware breakpoint or watchpoint requested.
packet.SetFilePos (strlen("Z"));
if (packet.GetBytesLeft() < 1)
return SendIllFormedResponse(packet, "Too short Z packet, missing software/hardware specifier");
@@ -3726,61 +3806,82 @@ GDBRemoteCommunicationServer::Handle_Z (StringExtractorGDBRemote &packet)
bool want_breakpoint = true;
bool want_hardware = false;
- const char breakpoint_type_char = packet.GetChar ();
- switch (breakpoint_type_char)
- {
- case '0': want_hardware = false; want_breakpoint = true; break;
- case '1': want_hardware = true; want_breakpoint = true; break;
- case '2': want_breakpoint = false; break;
- case '3': want_breakpoint = false; break;
- default:
+ const GDBStoppointType stoppoint_type =
+ GDBStoppointType(packet.GetS32 (eStoppointInvalid));
+ switch (stoppoint_type)
+ {
+ case eBreakpointSoftware:
+ want_hardware = false; want_breakpoint = true; break;
+ case eBreakpointHardware:
+ want_hardware = true; want_breakpoint = true; break;
+ case eWatchpointWrite:
+ want_hardware = true; want_breakpoint = false; break;
+ case eWatchpointRead:
+ want_hardware = true; want_breakpoint = false; break;
+ case eWatchpointReadWrite:
+ want_hardware = true; want_breakpoint = false; break;
+ case eStoppointInvalid:
return SendIllFormedResponse(packet, "Z packet had invalid software/hardware specifier");
}
if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',')
- return SendIllFormedResponse(packet, "Malformed Z packet, expecting comma after breakpoint type");
+ return SendIllFormedResponse(packet, "Malformed Z packet, expecting comma after stoppoint type");
- // FIXME implement watchpoint support.
- if (!want_breakpoint)
- return SendUnimplementedResponse ("watchpoint support not yet implemented");
-
- // Parse out the breakpoint address.
+ // Parse out the stoppoint address.
if (packet.GetBytesLeft() < 1)
return SendIllFormedResponse(packet, "Too short Z packet, missing address");
- const lldb::addr_t breakpoint_addr = packet.GetHexMaxU64(false, 0);
+ const lldb::addr_t addr = packet.GetHexMaxU64(false, 0);
if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',')
return SendIllFormedResponse(packet, "Malformed Z packet, expecting comma after address");
- // Parse out the breakpoint kind (i.e. size hint for opcode size).
- const uint32_t kind = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ());
- if (kind == std::numeric_limits<uint32_t>::max ())
- return SendIllFormedResponse(packet, "Malformed Z packet, failed to parse kind argument");
+ // Parse out the stoppoint size (i.e. size hint for opcode size).
+ const uint32_t size = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ());
+ if (size == std::numeric_limits<uint32_t>::max ())
+ return SendIllFormedResponse(packet, "Malformed Z packet, failed to parse size argument");
if (want_breakpoint)
{
// Try to set the breakpoint.
- const Error error = m_debugged_process_sp->SetBreakpoint (breakpoint_addr, kind, want_hardware);
+ const Error error = m_debugged_process_sp->SetBreakpoint (addr, size, want_hardware);
if (error.Success ())
return SendOKResponse ();
- else
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " failed to set breakpoint: %s", __FUNCTION__, m_debugged_process_sp->GetID (), error.AsCString ());
- return SendErrorResponse (0x09);
- }
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64
+ " failed to set breakpoint: %s",
+ __FUNCTION__,
+ m_debugged_process_sp->GetID (),
+ error.AsCString ());
+ return SendErrorResponse (0x09);
}
+ else
+ {
+ uint32_t watch_flags =
+ stoppoint_type == eWatchpointWrite
+ ? watch_flags = 0x1 // Write
+ : watch_flags = 0x3; // ReadWrite
- // FIXME fix up after watchpoints are handled.
- return SendUnimplementedResponse ("");
+ // Try to set the watchpoint.
+ const Error error = m_debugged_process_sp->SetWatchpoint (
+ addr, size, watch_flags, want_hardware);
+ if (error.Success ())
+ return SendOKResponse ();
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64
+ " failed to set watchpoint: %s",
+ __FUNCTION__,
+ m_debugged_process_sp->GetID (),
+ error.AsCString ());
+ return SendErrorResponse (0x09);
+ }
}
GDBRemoteCommunicationServer::PacketResult
GDBRemoteCommunicationServer::Handle_z (StringExtractorGDBRemote &packet)
{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
-
// We don't support if we're not llgs.
if (!IsGdbServer())
return SendUnimplementedResponse ("");
@@ -3788,66 +3889,81 @@ GDBRemoteCommunicationServer::Handle_z (StringExtractorGDBRemote &packet)
// Ensure we have a process.
if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
{
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
if (log)
log->Printf ("GDBRemoteCommunicationServer::%s failed, no process available", __FUNCTION__);
return SendErrorResponse (0x15);
}
- // Parse out software or hardware breakpoint requested.
+ // Parse out software or hardware breakpoint or watchpoint requested.
packet.SetFilePos (strlen("z"));
if (packet.GetBytesLeft() < 1)
return SendIllFormedResponse(packet, "Too short z packet, missing software/hardware specifier");
bool want_breakpoint = true;
- const char breakpoint_type_char = packet.GetChar ();
- switch (breakpoint_type_char)
+ const GDBStoppointType stoppoint_type =
+ GDBStoppointType(packet.GetS32 (eStoppointInvalid));
+ switch (stoppoint_type)
{
- case '0': want_breakpoint = true; break;
- case '1': want_breakpoint = true; break;
- case '2': want_breakpoint = false; break;
- case '3': want_breakpoint = false; break;
+ case eBreakpointHardware: want_breakpoint = true; break;
+ case eBreakpointSoftware: want_breakpoint = true; break;
+ case eWatchpointWrite: want_breakpoint = false; break;
+ case eWatchpointRead: want_breakpoint = false; break;
+ case eWatchpointReadWrite: want_breakpoint = false; break;
default:
return SendIllFormedResponse(packet, "z packet had invalid software/hardware specifier");
}
if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',')
- return SendIllFormedResponse(packet, "Malformed z packet, expecting comma after breakpoint type");
-
- // FIXME implement watchpoint support.
- if (!want_breakpoint)
- return SendUnimplementedResponse ("watchpoint support not yet implemented");
+ return SendIllFormedResponse(packet, "Malformed z packet, expecting comma after stoppoint type");
- // Parse out the breakpoint address.
+ // Parse out the stoppoint address.
if (packet.GetBytesLeft() < 1)
return SendIllFormedResponse(packet, "Too short z packet, missing address");
- const lldb::addr_t breakpoint_addr = packet.GetHexMaxU64(false, 0);
+ const lldb::addr_t addr = packet.GetHexMaxU64(false, 0);
if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',')
return SendIllFormedResponse(packet, "Malformed z packet, expecting comma after address");
- // Parse out the breakpoint kind (i.e. size hint for opcode size).
- const uint32_t kind = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ());
- if (kind == std::numeric_limits<uint32_t>::max ())
- return SendIllFormedResponse(packet, "Malformed z packet, failed to parse kind argument");
+ /*
+ // Parse out the stoppoint size (i.e. size hint for opcode size).
+ const uint32_t size = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ());
+ if (size == std::numeric_limits<uint32_t>::max ())
+ return SendIllFormedResponse(packet, "Malformed z packet, failed to parse size argument");
+ */
if (want_breakpoint)
{
// Try to clear the breakpoint.
- const Error error = m_debugged_process_sp->RemoveBreakpoint (breakpoint_addr);
+ const Error error = m_debugged_process_sp->RemoveBreakpoint (addr);
if (error.Success ())
return SendOKResponse ();
- else
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " failed to remove breakpoint: %s", __FUNCTION__, m_debugged_process_sp->GetID (), error.AsCString ());
- return SendErrorResponse (0x09);
- }
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64
+ " failed to remove breakpoint: %s",
+ __FUNCTION__,
+ m_debugged_process_sp->GetID (),
+ error.AsCString ());
+ return SendErrorResponse (0x09);
+ }
+ else
+ {
+ // Try to clear the watchpoint.
+ const Error error = m_debugged_process_sp->RemoveWatchpoint (addr);
+ if (error.Success ())
+ return SendOKResponse ();
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64
+ " failed to remove watchpoint: %s",
+ __FUNCTION__,
+ m_debugged_process_sp->GetID (),
+ error.AsCString ());
+ return SendErrorResponse (0x09);
}
-
- // FIXME fix up after watchpoints are handled.
- return SendUnimplementedResponse ("");
}
GDBRemoteCommunicationServer::PacketResult
@@ -4283,6 +4399,30 @@ GDBRemoteCommunicationServer::Handle_qThreadStopInfo (StringExtractorGDBRemote &
return SendStopReplyPacketForThread (tid);
}
+GDBRemoteCommunicationServer::PacketResult
+GDBRemoteCommunicationServer::Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet)
+{
+ // Only the gdb server handles this.
+ if (!IsGdbServer ())
+ return SendUnimplementedResponse (packet.GetStringRef ().c_str ());
+
+ // Fail if we don't have a current process.
+ if (!m_debugged_process_sp ||
+ m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)
+ return SendErrorResponse (68);
+
+ packet.SetFilePos(strlen("qWatchpointSupportInfo"));
+ if (packet.GetBytesLeft() == 0)
+ return SendOKResponse();
+ if (packet.GetChar() != ':')
+ return SendErrorResponse(67);
+
+ uint32_t num = m_debugged_process_sp->GetMaxWatchpoints();
+ StreamGDBRemote response;
+ response.Printf ("num:%d;", num);
+ return SendPacketNoLock(response.GetData(), response.GetSize());
+}
+
void
GDBRemoteCommunicationServer::FlushInferiorOutput ()
{
OpenPOWER on IntegriCloud