aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
commit344a3780b2e33f6ca763666c380202b18aab72a3 (patch)
treef0b203ee6eb71d7fdd792373e3c81eb18d6934dd /lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
parentb60736ec1405bb0a8dd40989f67ef4c93da068ab (diff)
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp')
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp1007
1 files changed, 585 insertions, 422 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index 62a09a2a432c..5e69b5793f9f 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -6,13 +6,14 @@
//
//===----------------------------------------------------------------------===//
-#include <errno.h>
+#include <cerrno>
#include "lldb/Host/Config.h"
#include <chrono>
#include <cstring>
+#include <limits>
#include <thread>
#include "GDBRemoteCommunicationServerLLGS.h"
@@ -70,6 +71,7 @@ GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS(
: GDBRemoteCommunicationServerCommon("gdb-remote.server",
"gdb-remote.server.rx_packet"),
m_mainloop(mainloop), m_process_factory(process_factory),
+ m_current_process(nullptr), m_continue_process(nullptr),
m_stdio_communication("process.stdio") {
RegisterPacketHandlers();
}
@@ -113,6 +115,12 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() {
StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
&GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir);
RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QThreadSuffixSupported,
+ &GDBRemoteCommunicationServerLLGS::Handle_QThreadSuffixSupported);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QListThreadsInStopReply,
+ &GDBRemoteCommunicationServerLLGS::Handle_QListThreadsInStopReply);
+ RegisterMemberFunctionHandler(
StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfo,
&GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo);
RegisterMemberFunctionHandler(
@@ -186,27 +194,32 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() {
&GDBRemoteCommunicationServerLLGS::Handle_QPassSignals);
RegisterMemberFunctionHandler(
- StringExtractorGDBRemote::eServerPacketType_jTraceStart,
- &GDBRemoteCommunicationServerLLGS::Handle_jTraceStart);
+ StringExtractorGDBRemote::eServerPacketType_jLLDBTraceSupported,
+ &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupported);
RegisterMemberFunctionHandler(
- StringExtractorGDBRemote::eServerPacketType_jTraceBufferRead,
- &GDBRemoteCommunicationServerLLGS::Handle_jTraceRead);
+ StringExtractorGDBRemote::eServerPacketType_jLLDBTraceStart,
+ &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStart);
RegisterMemberFunctionHandler(
- StringExtractorGDBRemote::eServerPacketType_jTraceMetaRead,
- &GDBRemoteCommunicationServerLLGS::Handle_jTraceRead);
+ StringExtractorGDBRemote::eServerPacketType_jLLDBTraceStop,
+ &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStop);
RegisterMemberFunctionHandler(
- StringExtractorGDBRemote::eServerPacketType_jTraceStop,
- &GDBRemoteCommunicationServerLLGS::Handle_jTraceStop);
+ StringExtractorGDBRemote::eServerPacketType_jLLDBTraceGetState,
+ &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetState);
RegisterMemberFunctionHandler(
- StringExtractorGDBRemote::eServerPacketType_jTraceConfigRead,
- &GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead);
- RegisterMemberFunctionHandler(
- StringExtractorGDBRemote::eServerPacketType_jLLDBTraceSupportedType,
- &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupportedType);
+ StringExtractorGDBRemote::eServerPacketType_jLLDBTraceGetBinaryData,
+ &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetBinaryData);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_g,
&GDBRemoteCommunicationServerLLGS::Handle_g);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qMemTags,
+ &GDBRemoteCommunicationServerLLGS::Handle_qMemTags);
+
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QMemTags,
+ &GDBRemoteCommunicationServerLLGS::Handle_QMemTags);
+
RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k,
[this](StringExtractorGDBRemote packet, Status &error,
bool &interrupt, bool &quit) {
@@ -245,15 +258,18 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() {
{
std::lock_guard<std::recursive_mutex> guard(m_debugged_process_mutex);
- assert(!m_debugged_process_up && "lldb-server creating debugged "
- "process but one already exists");
+ assert(m_debugged_processes.empty() && "lldb-server creating debugged "
+ "process but one already exists");
auto process_or =
m_process_factory.Launch(m_process_launch_info, *this, m_mainloop);
if (!process_or)
return Status(process_or.takeError());
- m_debugged_process_up = std::move(*process_or);
+ m_continue_process = m_current_process = process_or->get();
+ m_debugged_processes[m_current_process->GetID()] = std::move(*process_or);
}
+ SetEnabledExtensions(*m_current_process);
+
// Handle mirroring of inferior stdout/stderr over the gdb-remote protocol as
// needed. llgs local-process debugging may specify PTY paths, which will
// make these file actions non-null process launch -i/e/o will also make
@@ -266,10 +282,10 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() {
LLDB_LOG(log,
"pid = {0}: setting up stdout/stderr redirection via $O "
"gdb-remote commands",
- m_debugged_process_up->GetID());
+ m_current_process->GetID());
// Setup stdout/stderr mapping from inferior to $O
- auto terminal_fd = m_debugged_process_up->GetTerminalFileDescriptor();
+ auto terminal_fd = m_current_process->GetTerminalFileDescriptor();
if (terminal_fd >= 0) {
LLDB_LOGF(log,
"ProcessGDBRemoteCommunicationServerLLGS::%s setting "
@@ -288,12 +304,12 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() {
LLDB_LOG(log,
"pid = {0} skipping stdout/stderr redirection via $O: inferior "
"will communicate over client-provided file descriptors",
- m_debugged_process_up->GetID());
+ m_current_process->GetID());
}
printf("Launched '%s' as process %" PRIu64 "...\n",
m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
- m_debugged_process_up->GetID());
+ m_current_process->GetID());
return Status();
}
@@ -305,12 +321,11 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) {
// Before we try to attach, make sure we aren't already monitoring something
// else.
- if (m_debugged_process_up &&
- m_debugged_process_up->GetID() != LLDB_INVALID_PROCESS_ID)
+ if (!m_debugged_processes.empty())
return Status("cannot attach to process %" PRIu64
" when another process with pid %" PRIu64
" is being debugged.",
- pid, m_debugged_process_up->GetID());
+ pid, m_current_process->GetID());
// Try to attach.
auto process_or = m_process_factory.Attach(pid, *this, m_mainloop);
@@ -320,10 +335,12 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) {
status);
return status;
}
- m_debugged_process_up = std::move(*process_or);
+ m_continue_process = m_current_process = process_or->get();
+ m_debugged_processes[m_current_process->GetID()] = std::move(*process_or);
+ SetEnabledExtensions(*m_current_process);
// Setup stdout/stderr mapping from inferior.
- auto terminal_fd = m_debugged_process_up->GetTerminalFileDescriptor();
+ auto terminal_fd = m_current_process->GetTerminalFileDescriptor();
if (terminal_fd >= 0) {
LLDB_LOGF(log,
"ProcessGDBRemoteCommunicationServerLLGS::%s setting "
@@ -648,6 +665,14 @@ static const char *GetStopReasonString(StopReason stop_reason) {
return "exception";
case eStopReasonExec:
return "exec";
+ case eStopReasonProcessorTrace:
+ return "processor trace";
+ case eStopReasonFork:
+ return "fork";
+ case eStopReasonVFork:
+ return "vfork";
+ case eStopReasonVForkDone:
+ return "vforkdone";
case eStopReasonInstrumentation:
case eStopReasonInvalid:
case eStopReasonPlanComplete:
@@ -736,15 +761,15 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
// Ensure we have a debugged process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
return SendErrorResponse(50);
LLDB_LOG(log, "preparing packet for pid {0} tid {1}",
- m_debugged_process_up->GetID(), tid);
+ m_current_process->GetID(), tid);
// Ensure we can get info on the given thread.
- NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid);
+ NativeThreadProtocol *thread = m_current_process->GetThreadByID(tid);
if (!thread)
return SendErrorResponse(51);
@@ -767,7 +792,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
LLDB_LOG(
log,
"pid {0}, tid {1}, got signal signo = {2}, reason = {3}, exc_type = {4}",
- m_debugged_process_up->GetID(), tid, signum, int(tid_stop_info.reason),
+ m_current_process->GetID(), tid, signum, int(tid_stop_info.reason),
tid_stop_info.details.exception.type);
// Print the signal number.
@@ -805,9 +830,9 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
uint32_t thread_index = 0;
NativeThreadProtocol *listed_thread;
- for (listed_thread = m_debugged_process_up->GetThreadAtIndex(thread_index);
+ for (listed_thread = m_current_process->GetThreadAtIndex(thread_index);
listed_thread; ++thread_index,
- listed_thread = m_debugged_process_up->GetThreadAtIndex(thread_index)) {
+ listed_thread = m_current_process->GetThreadAtIndex(thread_index)) {
if (thread_index > 0)
response.PutChar(',');
response.Printf("%" PRIx64, listed_thread->GetID());
@@ -822,7 +847,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
if (thread_index > 1) {
const bool threads_with_valid_stop_info_only = true;
llvm::Expected<json::Array> threads_info = GetJSONThreadsInfo(
- *m_debugged_process_up, threads_with_valid_stop_info_only);
+ *m_current_process, threads_with_valid_stop_info_only);
if (threads_info) {
response.PutCString("jstopinfo:");
StreamString unescaped_response;
@@ -832,7 +857,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
} else {
LLDB_LOG_ERROR(log, threads_info.takeError(),
"failed to prepare a jstopinfo field for pid {1}: {0}",
- m_debugged_process_up->GetID());
+ m_current_process->GetID());
}
}
@@ -840,8 +865,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
response.PutCString("thread-pcs");
char delimiter = ':';
for (NativeThreadProtocol *thread;
- (thread = m_debugged_process_up->GetThreadAtIndex(i)) != nullptr;
- ++i) {
+ (thread = m_current_process->GetThreadAtIndex(i)) != nullptr; ++i) {
NativeRegisterContext& reg_ctx = thread->GetRegisterContext();
uint32_t reg_to_read = reg_ctx.ConvertRegisterKindToRegisterNumber(
@@ -924,6 +948,22 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
}
}
+ // Include child process PID/TID for forks.
+ if (tid_stop_info.reason == eStopReasonFork ||
+ tid_stop_info.reason == eStopReasonVFork) {
+ assert(bool(m_extensions_supported &
+ NativeProcessProtocol::Extension::multiprocess));
+ if (tid_stop_info.reason == eStopReasonFork)
+ assert(bool(m_extensions_supported &
+ NativeProcessProtocol::Extension::fork));
+ if (tid_stop_info.reason == eStopReasonVFork)
+ assert(bool(m_extensions_supported &
+ NativeProcessProtocol::Extension::vfork));
+ response.Printf("%s:p%" PRIx64 ".%" PRIx64 ";", reason_str,
+ tid_stop_info.details.fork.child_pid,
+ tid_stop_info.details.fork.child_tid);
+ }
+
return SendPacketNoLock(response.GetString());
}
@@ -1028,6 +1068,15 @@ void GDBRemoteCommunicationServerLLGS::DidExec(NativeProcessProtocol *process) {
ClearProcessSpecificData();
}
+void GDBRemoteCommunicationServerLLGS::NewSubprocess(
+ NativeProcessProtocol *parent_process,
+ std::unique_ptr<NativeProcessProtocol> child_process) {
+ lldb::pid_t child_pid = child_process->GetID();
+ assert(child_pid != LLDB_INVALID_PROCESS_ID);
+ assert(m_debugged_processes.find(child_pid) == m_debugged_processes.end());
+ m_debugged_processes[child_pid] = std::move(child_process);
+}
+
void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() {
Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_COMM));
@@ -1170,266 +1219,110 @@ void GDBRemoteCommunicationServerLLGS::SendProcessOutput() {
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_jTraceStart(
+GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupported(
StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- // Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
- return SendErrorResponse(68);
-
- if (!packet.ConsumeFront("jTraceStart:"))
- return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet ");
-
- TraceOptions options;
- uint64_t type = std::numeric_limits<uint64_t>::max();
- uint64_t buffersize = std::numeric_limits<uint64_t>::max();
- lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
- uint64_t metabuffersize = std::numeric_limits<uint64_t>::max();
-
- auto json_object = StructuredData::ParseJSON(packet.Peek());
-
- if (!json_object ||
- json_object->GetType() != lldb::eStructuredDataTypeDictionary)
- return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet ");
-
- auto json_dict = json_object->GetAsDictionary();
-
- json_dict->GetValueForKeyAsInteger("metabuffersize", metabuffersize);
- options.setMetaDataBufferSize(metabuffersize);
- json_dict->GetValueForKeyAsInteger("buffersize", buffersize);
- options.setTraceBufferSize(buffersize);
-
- json_dict->GetValueForKeyAsInteger("type", type);
- options.setType(static_cast<lldb::TraceType>(type));
-
- json_dict->GetValueForKeyAsInteger("threadid", tid);
- options.setThreadID(tid);
-
- StructuredData::ObjectSP custom_params_sp =
- json_dict->GetValueForKey("params");
- if (custom_params_sp &&
- custom_params_sp->GetType() != lldb::eStructuredDataTypeDictionary)
- return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet ");
-
- options.setTraceParams(
- std::static_pointer_cast<StructuredData::Dictionary>(custom_params_sp));
-
- if (buffersize == std::numeric_limits<uint64_t>::max() ||
- type != lldb::TraceType::eTraceTypeProcessorTrace) {
- LLDB_LOG(log, "Ill formed packet buffersize = {0} type = {1}", buffersize,
- type);
- return SendIllFormedResponse(packet, "JTrace:start: Ill formed packet ");
- }
-
- Status error;
- lldb::user_id_t uid = LLDB_INVALID_UID;
- uid = m_debugged_process_up->StartTrace(options, error);
- LLDB_LOG(log, "uid is {0} , error is {1}", uid, error.GetError());
- if (error.Fail())
- return SendErrorResponse(error);
+ // Fail if we don't have a current process.
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse(Status("Process not running."));
- StreamGDBRemote response;
- response.Printf("%" PRIx64, uid);
- return SendPacketNoLock(response.GetString());
+ return SendJSONResponse(m_current_process->TraceSupported());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_jTraceStop(
+GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStop(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
- return SendErrorResponse(68);
-
- if (!packet.ConsumeFront("jTraceStop:"))
- return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet ");
-
- lldb::user_id_t uid = LLDB_INVALID_UID;
- lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
-
- auto json_object = StructuredData::ParseJSON(packet.Peek());
-
- if (!json_object ||
- json_object->GetType() != lldb::eStructuredDataTypeDictionary)
- return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet ");
-
- auto json_dict = json_object->GetAsDictionary();
-
- if (!json_dict->GetValueForKeyAsInteger("traceid", uid))
- return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet ");
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse(Status("Process not running."));
- json_dict->GetValueForKeyAsInteger("threadid", tid);
+ packet.ConsumeFront("jLLDBTraceStop:");
+ Expected<TraceStopRequest> stop_request =
+ json::parse<TraceStopRequest>(packet.Peek(), "TraceStopRequest");
+ if (!stop_request)
+ return SendErrorResponse(stop_request.takeError());
- Status error = m_debugged_process_up->StopTrace(uid, tid);
-
- if (error.Fail())
- return SendErrorResponse(error);
+ if (Error err = m_current_process->TraceStop(*stop_request))
+ return SendErrorResponse(std::move(err));
return SendOKResponse();
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupportedType(
+GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStart(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
return SendErrorResponse(Status("Process not running."));
- llvm::Expected<TraceTypeInfo> supported_trace_type =
- m_debugged_process_up->GetSupportedTraceType();
- if (!supported_trace_type)
- return SendErrorResponse(supported_trace_type.takeError());
+ packet.ConsumeFront("jLLDBTraceStart:");
+ Expected<TraceStartRequest> request =
+ json::parse<TraceStartRequest>(packet.Peek(), "TraceStartRequest");
+ if (!request)
+ return SendErrorResponse(request.takeError());
- StreamGDBRemote escaped_response;
- StructuredData::Dictionary json_packet;
+ if (Error err = m_current_process->TraceStart(packet.Peek(), request->type))
+ return SendErrorResponse(std::move(err));
- json_packet.AddStringItem("name", supported_trace_type->name);
- json_packet.AddStringItem("description", supported_trace_type->description);
-
- StreamString json_string;
- json_packet.Dump(json_string, false);
- escaped_response.PutEscapedBytes(json_string.GetData(),
- json_string.GetSize());
- return SendPacketNoLock(escaped_response.GetString());
+ return SendOKResponse();
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead(
+GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetState(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
- return SendErrorResponse(68);
-
- if (!packet.ConsumeFront("jTraceConfigRead:"))
- return SendIllFormedResponse(packet,
- "jTraceConfigRead: Ill formed packet ");
-
- lldb::user_id_t uid = LLDB_INVALID_UID;
- lldb::tid_t threadid = LLDB_INVALID_THREAD_ID;
-
- auto json_object = StructuredData::ParseJSON(packet.Peek());
-
- if (!json_object ||
- json_object->GetType() != lldb::eStructuredDataTypeDictionary)
- return SendIllFormedResponse(packet,
- "jTraceConfigRead: Ill formed packet ");
-
- auto json_dict = json_object->GetAsDictionary();
-
- if (!json_dict->GetValueForKeyAsInteger("traceid", uid))
- return SendIllFormedResponse(packet,
- "jTraceConfigRead: Ill formed packet ");
-
- json_dict->GetValueForKeyAsInteger("threadid", threadid);
-
- TraceOptions options;
- StreamGDBRemote response;
-
- options.setThreadID(threadid);
- Status error = m_debugged_process_up->GetTraceConfig(uid, options);
-
- if (error.Fail())
- return SendErrorResponse(error);
-
- StreamGDBRemote escaped_response;
- StructuredData::Dictionary json_packet;
-
- json_packet.AddIntegerItem("type", options.getType());
- json_packet.AddIntegerItem("buffersize", options.getTraceBufferSize());
- json_packet.AddIntegerItem("metabuffersize", options.getMetaDataBufferSize());
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse(Status("Process not running."));
- StructuredData::DictionarySP custom_params = options.getTraceParams();
- if (custom_params)
- json_packet.AddItem("params", custom_params);
+ packet.ConsumeFront("jLLDBTraceGetState:");
+ Expected<TraceGetStateRequest> request =
+ json::parse<TraceGetStateRequest>(packet.Peek(), "TraceGetStateRequest");
+ if (!request)
+ return SendErrorResponse(request.takeError());
- StreamString json_string;
- json_packet.Dump(json_string, false);
- escaped_response.PutEscapedBytes(json_string.GetData(),
- json_string.GetSize());
- return SendPacketNoLock(escaped_response.GetString());
+ return SendJSONResponse(m_current_process->TraceGetState(request->type));
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_jTraceRead(
+GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetBinaryData(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
- return SendErrorResponse(68);
-
- enum PacketType { MetaData, BufferData };
- PacketType tracetype = MetaData;
-
- if (packet.ConsumeFront("jTraceBufferRead:"))
- tracetype = BufferData;
- else if (packet.ConsumeFront("jTraceMetaRead:"))
- tracetype = MetaData;
- else {
- return SendIllFormedResponse(packet, "jTrace: Ill formed packet ");
- }
-
- lldb::user_id_t uid = LLDB_INVALID_UID;
-
- uint64_t byte_count = std::numeric_limits<uint64_t>::max();
- lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
- uint64_t offset = std::numeric_limits<uint64_t>::max();
-
- auto json_object = StructuredData::ParseJSON(packet.Peek());
-
- if (!json_object ||
- json_object->GetType() != lldb::eStructuredDataTypeDictionary)
- return SendIllFormedResponse(packet, "jTrace: Ill formed packet ");
-
- auto json_dict = json_object->GetAsDictionary();
-
- if (!json_dict->GetValueForKeyAsInteger("traceid", uid) ||
- !json_dict->GetValueForKeyAsInteger("offset", offset) ||
- !json_dict->GetValueForKeyAsInteger("buffersize", byte_count))
- return SendIllFormedResponse(packet, "jTrace: Ill formed packet ");
-
- json_dict->GetValueForKeyAsInteger("threadid", tid);
-
- // Allocate the response buffer.
- std::unique_ptr<uint8_t[]> buffer (new (std::nothrow) uint8_t[byte_count]);
- if (!buffer)
- return SendErrorResponse(0x78);
-
- StreamGDBRemote response;
- Status error;
- llvm::MutableArrayRef<uint8_t> buf(buffer.get(), byte_count);
-
- if (tracetype == BufferData)
- error = m_debugged_process_up->GetData(uid, tid, buf, offset);
- else if (tracetype == MetaData)
- error = m_debugged_process_up->GetMetaData(uid, tid, buf, offset);
-
- if (error.Fail())
- return SendErrorResponse(error);
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse(Status("Process not running."));
- for (auto i : buf)
- response.PutHex8(i);
+ packet.ConsumeFront("jLLDBTraceGetBinaryData:");
+ llvm::Expected<TraceGetBinaryDataRequest> request =
+ llvm::json::parse<TraceGetBinaryDataRequest>(packet.Peek(),
+ "TraceGetBinaryDataRequest");
+ if (!request)
+ return SendErrorResponse(Status(request.takeError()));
- StreamGDBRemote escaped_response;
- escaped_response.PutEscapedBytes(response.GetData(), response.GetSize());
- return SendPacketNoLock(escaped_response.GetString());
+ if (Expected<std::vector<uint8_t>> bytes =
+ m_current_process->TraceGetBinaryData(*request)) {
+ StreamGDBRemote response;
+ response.PutEscapedBytes(bytes->data(), bytes->size());
+ return SendPacketNoLock(response.GetString());
+ } else
+ return SendErrorResponse(bytes.takeError());
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
return SendErrorResponse(68);
- lldb::pid_t pid = m_debugged_process_up->GetID();
+ lldb::pid_t pid = m_current_process->GetID();
if (pid == LLDB_INVALID_PROCESS_ID)
return SendErrorResponse(1);
@@ -1446,16 +1339,16 @@ GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qC(StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
return SendErrorResponse(68);
// Make sure we set the current thread so g and p packets return the data the
// gdb will expect.
- lldb::tid_t tid = m_debugged_process_up->GetCurrentThreadID();
+ lldb::tid_t tid = m_current_process->GetCurrentThreadID();
SetCurrentThreadID(tid);
- NativeThreadProtocol *thread = m_debugged_process_up->GetCurrentThread();
+ NativeThreadProtocol *thread = m_current_process->GetCurrentThread();
if (!thread)
return SendErrorResponse(69);
@@ -1471,15 +1364,15 @@ GDBRemoteCommunicationServerLLGS::Handle_k(StringExtractorGDBRemote &packet) {
StopSTDIOForwarding();
- if (!m_debugged_process_up) {
+ if (!m_current_process) {
LLDB_LOG(log, "No debugged process found.");
return PacketResult::Success;
}
- Status error = m_debugged_process_up->Kill();
+ Status error = m_current_process->Kill();
if (error.Fail())
LLDB_LOG(log, "Failed to kill debugged process {0}: {1}",
- m_debugged_process_up->GetID(), error);
+ m_current_process->GetID(), error);
// No OK response for kill packet.
// return SendOKResponse ();
@@ -1521,12 +1414,26 @@ GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir(
}
GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_QThreadSuffixSupported(
+ StringExtractorGDBRemote &packet) {
+ m_thread_suffix_supported = true;
+ return SendOKResponse();
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_QListThreadsInStopReply(
+ StringExtractorGDBRemote &packet) {
+ m_list_threads_in_stop_reply = true;
+ return SendOKResponse();
+}
+
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
// Ensure we have a native process.
- if (!m_debugged_process_up) {
+ if (!m_continue_process) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s no debugged process "
"shared pointer",
@@ -1579,20 +1486,20 @@ GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) {
} else {
// Send the signal to the process since we weren't targeting a specific
// continue thread with the signal.
- error = m_debugged_process_up->Signal(signo);
+ error = m_continue_process->Signal(signo);
if (error.Fail()) {
LLDB_LOG(log, "failed to send signal for process {0}: {1}",
- m_debugged_process_up->GetID(), error);
+ m_continue_process->GetID(), error);
return SendErrorResponse(0x52);
}
}
// Resume the threads.
- error = m_debugged_process_up->Resume(resume_actions);
+ error = m_continue_process->Resume(resume_actions);
if (error.Fail()) {
LLDB_LOG(log, "failed to resume threads for process {0}: {1}",
- m_debugged_process_up->GetID(), error);
+ m_continue_process->GetID(), error);
return SendErrorResponse(0x38);
}
@@ -1617,7 +1524,7 @@ GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) {
}
// Ensure we have a native process.
- if (!m_debugged_process_up) {
+ if (!m_continue_process) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s no debugged process "
"shared pointer",
@@ -1629,14 +1536,14 @@ GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) {
ResumeActionList actions(StateType::eStateRunning,
LLDB_INVALID_SIGNAL_NUMBER);
- Status error = m_debugged_process_up->Resume(actions);
+ Status error = m_continue_process->Resume(actions);
if (error.Fail()) {
- LLDB_LOG(log, "c failed for process {0}: {1}",
- m_debugged_process_up->GetID(), error);
+ LLDB_LOG(log, "c failed for process {0}: {1}", m_continue_process->GetID(),
+ error);
return SendErrorResponse(GDBRemoteServerError::eErrorResume);
}
- LLDB_LOG(log, "continued process {0}", m_debugged_process_up->GetID());
+ LLDB_LOG(log, "continued process {0}", m_continue_process->GetID());
// No response required from continue.
return PacketResult::Success;
}
@@ -1679,7 +1586,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont(
}
// Ensure we have a native process.
- if (!m_debugged_process_up) {
+ if (!m_continue_process) {
LLDB_LOG(log, "no debugged process");
return SendErrorResponse(0x36);
}
@@ -1732,23 +1639,27 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont(
// Consume the separator.
packet.GetChar();
- thread_action.tid = packet.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID);
- if (thread_action.tid == LLDB_INVALID_THREAD_ID)
- return SendIllFormedResponse(
- packet, "Could not parse thread number in vCont packet");
+ llvm::Expected<lldb::tid_t> tid_ret =
+ ReadTid(packet, /*allow_all=*/true, m_continue_process->GetID());
+ if (!tid_ret)
+ return SendErrorResponse(tid_ret.takeError());
+
+ thread_action.tid = tid_ret.get();
+ if (thread_action.tid == StringExtractorGDBRemote::AllThreads)
+ thread_action.tid = LLDB_INVALID_THREAD_ID;
}
thread_actions.Append(thread_action);
}
- Status error = m_debugged_process_up->Resume(thread_actions);
+ Status error = m_continue_process->Resume(thread_actions);
if (error.Fail()) {
LLDB_LOG(log, "vCont failed for process {0}: {1}",
- m_debugged_process_up->GetID(), error);
+ m_continue_process->GetID(), error);
return SendErrorResponse(GDBRemoteServerError::eErrorResume);
}
- LLDB_LOG(log, "continued process {0}", m_debugged_process_up->GetID());
+ LLDB_LOG(log, "continued process {0}", m_continue_process->GetID());
// No response required from vCont.
return PacketResult::Success;
}
@@ -1758,8 +1669,8 @@ void GDBRemoteCommunicationServerLLGS::SetCurrentThreadID(lldb::tid_t tid) {
LLDB_LOG(log, "setting current thread id to {0}", tid);
m_current_tid = tid;
- if (m_debugged_process_up)
- m_debugged_process_up->SetCurrentThreadID(m_current_tid);
+ if (m_current_process)
+ m_current_process->SetCurrentThreadID(m_current_tid);
}
void GDBRemoteCommunicationServerLLGS::SetContinueThreadID(lldb::tid_t tid) {
@@ -1775,10 +1686,10 @@ GDBRemoteCommunicationServerLLGS::Handle_stop_reason(
// Handle the $? gdbremote command.
// If no process, indicate error
- if (!m_debugged_process_up)
+ if (!m_current_process)
return SendErrorResponse(02);
- return SendStopReasonForState(m_debugged_process_up->GetState());
+ return SendStopReasonForState(m_current_process->GetState());
}
GDBRemoteCommunication::PacketResult
@@ -1799,8 +1710,8 @@ GDBRemoteCommunicationServerLLGS::SendStopReasonForState(
case eStateSuspended:
case eStateStopped:
case eStateCrashed: {
- assert(m_debugged_process_up != nullptr);
- lldb::tid_t tid = m_debugged_process_up->GetCurrentThreadID();
+ assert(m_current_process != nullptr);
+ lldb::tid_t tid = m_current_process->GetCurrentThreadID();
// Make sure we set the current thread so g and p packets return the data
// the gdb will expect.
SetCurrentThreadID(tid);
@@ -1810,11 +1721,11 @@ GDBRemoteCommunicationServerLLGS::SendStopReasonForState(
case eStateInvalid:
case eStateUnloaded:
case eStateExited:
- return SendWResponse(m_debugged_process_up.get());
+ return SendWResponse(m_current_process);
default:
LLDB_LOG(log, "pid {0}, current state reporting not handled: {1}",
- m_debugged_process_up->GetID(), process_state);
+ m_current_process->GetID(), process_state);
break;
}
@@ -1825,12 +1736,12 @@ GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
return SendErrorResponse(68);
// Ensure we have a thread.
- NativeThreadProtocol *thread = m_debugged_process_up->GetThreadAtIndex(0);
+ NativeThreadProtocol *thread = m_current_process->GetThreadAtIndex(0);
if (!thread)
return SendErrorResponse(69);
@@ -1925,11 +1836,11 @@ GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo(
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOG(log, "no process ({0}), returning OK",
- m_debugged_process_up ? "invalid process id"
- : "null m_debugged_process_up");
+ m_current_process ? "invalid process id"
+ : "null m_current_process");
return SendOKResponse();
}
@@ -1940,9 +1851,9 @@ GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo(
NativeThreadProtocol *thread;
uint32_t thread_index;
for (thread_index = 0,
- thread = m_debugged_process_up->GetThreadAtIndex(thread_index);
+ thread = m_current_process->GetThreadAtIndex(thread_index);
thread; ++thread_index,
- thread = m_debugged_process_up->GetThreadAtIndex(thread_index)) {
+ thread = m_current_process->GetThreadAtIndex(thread_index)) {
LLDB_LOG(log, "iterated thread {0}(tid={2})", thread_index,
thread->GetID());
if (thread_index > 0)
@@ -2163,9 +2074,8 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) {
// Build the reginfos response.
StreamGDBRemote response;
- RegisterValue reg_value(
- makeArrayRef(reg_bytes, reg_size),
- m_debugged_process_up->GetArchitecture().GetByteOrder());
+ RegisterValue reg_value(makeArrayRef(reg_bytes, reg_size),
+ m_current_process->GetArchitecture().GetByteOrder());
Status error = reg_context.WriteRegister(reg_info, reg_value);
if (error.Fail()) {
LLDB_LOGF(log,
@@ -2182,16 +2092,6 @@ GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
- // Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
- LLDB_LOGF(
- log,
- "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
- __FUNCTION__);
- return SendErrorResponse(0x15);
- }
-
// Parse out which variant of $H is requested.
packet.SetFilePos(strlen("H"));
if (packet.GetBytesLeft() < 1) {
@@ -2203,11 +2103,14 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) {
}
const char h_variant = packet.GetChar();
+ NativeProcessProtocol *default_process;
switch (h_variant) {
case 'g':
+ default_process = m_current_process;
break;
case 'c':
+ default_process = m_continue_process;
break;
default:
@@ -2220,14 +2123,32 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) {
}
// Parse out the thread number.
- // FIXME return a parse success/fail value. All values are valid here.
- const lldb::tid_t tid =
- packet.GetHexMaxU64(false, std::numeric_limits<lldb::tid_t>::max());
+ auto pid_tid = packet.GetPidTid(default_process ? default_process->GetID()
+ : LLDB_INVALID_PROCESS_ID);
+ if (!pid_tid)
+ return SendErrorResponse(llvm::make_error<StringError>(
+ inconvertibleErrorCode(), "Malformed thread-id"));
+
+ lldb::pid_t pid = pid_tid->first;
+ lldb::tid_t tid = pid_tid->second;
+
+ if (pid == StringExtractorGDBRemote::AllProcesses)
+ return SendUnimplementedResponse("Selecting all processes not supported");
+ if (pid == LLDB_INVALID_PROCESS_ID)
+ return SendErrorResponse(llvm::make_error<StringError>(
+ inconvertibleErrorCode(), "No current process and no PID provided"));
+
+ // Check the process ID and find respective process instance.
+ auto new_process_it = m_debugged_processes.find(pid);
+ if (new_process_it == m_debugged_processes.end())
+ return SendErrorResponse(llvm::make_error<StringError>(
+ inconvertibleErrorCode(),
+ llvm::formatv("No process with PID {0} debugged", pid)));
// Ensure we have the given thread when not specifying -1 (all threads) or 0
// (any thread).
if (tid != LLDB_INVALID_THREAD_ID && tid != 0) {
- NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid);
+ NativeThreadProtocol *thread = new_process_it->second->GetThreadByID(tid);
if (!thread) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64
@@ -2237,13 +2158,15 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) {
}
}
- // Now switch the given thread type.
+ // Now switch the given process and thread type.
switch (h_variant) {
case 'g':
+ m_current_process = new_process_it->second.get();
SetCurrentThreadID(tid);
break;
case 'c':
+ m_continue_process = new_process_it->second.get();
SetContinueThreadID(tid);
break;
@@ -2261,8 +2184,8 @@ GDBRemoteCommunicationServerLLGS::Handle_I(StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2297,21 +2220,21 @@ GDBRemoteCommunicationServerLLGS::Handle_interrupt(
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOG(log, "failed, no process available");
return SendErrorResponse(0x15);
}
// Interrupt the process.
- Status error = m_debugged_process_up->Interrupt();
+ Status error = m_current_process->Interrupt();
if (error.Fail()) {
- LLDB_LOG(log, "failed for process {0}: {1}", m_debugged_process_up->GetID(),
+ LLDB_LOG(log, "failed for process {0}: {1}", m_current_process->GetID(),
error);
return SendErrorResponse(GDBRemoteServerError::eErrorResume);
}
- LLDB_LOG(log, "stopped process {0}", m_debugged_process_up->GetID());
+ LLDB_LOG(log, "stopped process {0}", m_current_process->GetID());
// No response required from stop all.
return PacketResult::Success;
@@ -2322,8 +2245,8 @@ GDBRemoteCommunicationServerLLGS::Handle_memory_read(
StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2365,13 +2288,13 @@ GDBRemoteCommunicationServerLLGS::Handle_memory_read(
// Retrieve the process memory.
size_t bytes_read = 0;
- Status error = m_debugged_process_up->ReadMemoryWithoutTrap(
+ Status error = m_current_process->ReadMemoryWithoutTrap(
read_addr, &buf[0], byte_count, bytes_read);
if (error.Fail()) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
" mem 0x%" PRIx64 ": failed to read. Error: %s",
- __FUNCTION__, m_debugged_process_up->GetID(), read_addr,
+ __FUNCTION__, m_current_process->GetID(), read_addr,
error.AsCString());
return SendErrorResponse(0x08);
}
@@ -2380,8 +2303,7 @@ GDBRemoteCommunicationServerLLGS::Handle_memory_read(
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
" mem 0x%" PRIx64 ": read 0 of %" PRIu64 " requested bytes",
- __FUNCTION__, m_debugged_process_up->GetID(), read_addr,
- byte_count);
+ __FUNCTION__, m_current_process->GetID(), read_addr, byte_count);
return SendErrorResponse(0x08);
}
@@ -2403,8 +2325,8 @@ GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle__M(StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2439,8 +2361,7 @@ GDBRemoteCommunicationServerLLGS::Handle__M(StringExtractorGDBRemote &packet) {
}
}
- llvm::Expected<addr_t> addr =
- m_debugged_process_up->AllocateMemory(size, perms);
+ llvm::Expected<addr_t> addr = m_current_process->AllocateMemory(size, perms);
if (!addr)
return SendErrorResponse(addr.takeError());
@@ -2453,8 +2374,8 @@ GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle__m(StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2471,7 +2392,7 @@ GDBRemoteCommunicationServerLLGS::Handle__m(StringExtractorGDBRemote &packet) {
if (addr == LLDB_INVALID_ADDRESS)
return SendIllFormedResponse(packet, "Address not valid");
- if (llvm::Error Err = m_debugged_process_up->DeallocateMemory(addr))
+ if (llvm::Error Err = m_current_process->DeallocateMemory(addr))
return SendErrorResponse(std::move(Err));
return SendOKResponse();
@@ -2481,8 +2402,8 @@ GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2531,8 +2452,7 @@ GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) {
LLDB_LOG(log,
"pid {0} mem {1:x}: asked to write {2} bytes, but only found {3} "
"to convert.",
- m_debugged_process_up->GetID(), write_addr, byte_count,
- convert_count);
+ m_current_process->GetID(), write_addr, byte_count, convert_count);
return SendIllFormedResponse(packet, "M content byte length specified did "
"not match hex-encoded content "
"length");
@@ -2540,17 +2460,17 @@ GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) {
// Write the process memory.
size_t bytes_written = 0;
- Status error = m_debugged_process_up->WriteMemory(write_addr, &buf[0],
- byte_count, bytes_written);
+ Status error = m_current_process->WriteMemory(write_addr, &buf[0], byte_count,
+ bytes_written);
if (error.Fail()) {
LLDB_LOG(log, "pid {0} mem {1:x}: failed to write. Error: {2}",
- m_debugged_process_up->GetID(), write_addr, error);
+ m_current_process->GetID(), write_addr, error);
return SendErrorResponse(0x09);
}
if (bytes_written == 0) {
LLDB_LOG(log, "pid {0} mem {1:x}: wrote 0 of {2} requested bytes",
- m_debugged_process_up->GetID(), write_addr, byte_count);
+ m_current_process->GetID(), write_addr, byte_count);
return SendErrorResponse(0x09);
}
@@ -2569,8 +2489,8 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported(
// Ensure we have a process running; otherwise, we can't figure this out
// since we won't have a NativeProcessProtocol.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2580,8 +2500,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported(
// Test if we can get any region back when asking for the region around NULL.
MemoryRegionInfo region_info;
- const Status error =
- m_debugged_process_up->GetMemoryRegionInfo(0, region_info);
+ const Status error = m_current_process->GetMemoryRegionInfo(0, region_info);
if (error.Fail()) {
// We don't support memory region info collection for this
// NativeProcessProtocol.
@@ -2597,8 +2516,8 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo(
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
// Ensure we have a process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2619,7 +2538,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo(
// Get the memory region info for the target address.
MemoryRegionInfo region_info;
const Status error =
- m_debugged_process_up->GetMemoryRegionInfo(read_addr, region_info);
+ m_current_process->GetMemoryRegionInfo(read_addr, region_info);
if (error.Fail()) {
// Return the error message.
@@ -2674,8 +2593,8 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) {
// Ensure we have a process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
LLDB_LOG(log, "failed, no process available");
return SendErrorResponse(0x15);
@@ -2745,22 +2664,22 @@ GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) {
if (want_breakpoint) {
// Try to set the breakpoint.
const Status error =
- m_debugged_process_up->SetBreakpoint(addr, size, want_hardware);
+ m_current_process->SetBreakpoint(addr, size, want_hardware);
if (error.Success())
return SendOKResponse();
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
LLDB_LOG(log, "pid {0} failed to set breakpoint: {1}",
- m_debugged_process_up->GetID(), error);
+ m_current_process->GetID(), error);
return SendErrorResponse(0x09);
} else {
// Try to set the watchpoint.
- const Status error = m_debugged_process_up->SetWatchpoint(
+ const Status error = m_current_process->SetWatchpoint(
addr, size, watch_flags, want_hardware);
if (error.Success())
return SendOKResponse();
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
LLDB_LOG(log, "pid {0} failed to set watchpoint: {1}",
- m_debugged_process_up->GetID(), error);
+ m_current_process->GetID(), error);
return SendErrorResponse(0x09);
}
}
@@ -2768,8 +2687,8 @@ GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) {
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
// Ensure we have a process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
LLDB_LOG(log, "failed, no process available");
return SendErrorResponse(0x15);
@@ -2833,21 +2752,21 @@ GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
if (want_breakpoint) {
// Try to clear the breakpoint.
const Status error =
- m_debugged_process_up->RemoveBreakpoint(addr, want_hardware);
+ m_current_process->RemoveBreakpoint(addr, want_hardware);
if (error.Success())
return SendOKResponse();
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
LLDB_LOG(log, "pid {0} failed to remove breakpoint: {1}",
- m_debugged_process_up->GetID(), error);
+ m_current_process->GetID(), error);
return SendErrorResponse(0x09);
} else {
// Try to clear the watchpoint.
- const Status error = m_debugged_process_up->RemoveWatchpoint(addr);
+ const Status error = m_current_process->RemoveWatchpoint(addr);
if (error.Success())
return SendOKResponse();
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
LLDB_LOG(log, "pid {0} failed to remove watchpoint: {1}",
- m_debugged_process_up->GetID(), error);
+ m_current_process->GetID(), error);
return SendErrorResponse(0x09);
}
}
@@ -2857,8 +2776,8 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
// Ensure we have a process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_continue_process ||
+ (m_continue_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2876,7 +2795,7 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) {
// Double check that we have such a thread.
// TODO investigate: on MacOSX we might need to do an UpdateThreads () here.
- NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid);
+ NativeThreadProtocol *thread = m_continue_process->GetThreadByID(tid);
if (!thread)
return SendErrorResponse(0x33);
@@ -2889,12 +2808,12 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) {
// All other threads stop while we're single stepping a thread.
actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
- Status error = m_debugged_process_up->Resume(actions);
+ Status error = m_continue_process->Resume(actions);
if (error.Fail()) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
" tid %" PRIu64 " Resume() failed with error: %s",
- __FUNCTION__, m_debugged_process_up->GetID(), tid,
+ __FUNCTION__, m_continue_process->GetID(), tid,
error.AsCString());
return SendErrorResponse(0x49);
}
@@ -2906,7 +2825,7 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) {
llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
GDBRemoteCommunicationServerLLGS::BuildTargetXml() {
// Ensure we have a thread.
- NativeThreadProtocol *thread = m_debugged_process_up->GetThreadAtIndex(0);
+ NativeThreadProtocol *thread = m_current_process->GetThreadAtIndex(0);
if (!thread)
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"No thread available");
@@ -2921,7 +2840,7 @@ GDBRemoteCommunicationServerLLGS::BuildTargetXml() {
response.Printf("<target version=\"1.0\">");
response.Printf("<architecture>%s</architecture>",
- m_debugged_process_up->GetArchitecture()
+ m_current_process->GetArchitecture()
.GetTriple()
.getArchName()
.str()
@@ -3010,22 +2929,22 @@ llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
GDBRemoteCommunicationServerLLGS::ReadXferObject(llvm::StringRef object,
llvm::StringRef annex) {
// Make sure we have a valid process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"No process available");
}
if (object == "auxv") {
// Grab the auxv data.
- auto buffer_or_error = m_debugged_process_up->GetAuxvData();
+ auto buffer_or_error = m_current_process->GetAuxvData();
if (!buffer_or_error)
return llvm::errorCodeToError(buffer_or_error.getError());
return std::move(*buffer_or_error);
}
if (object == "libraries-svr4") {
- auto library_list = m_debugged_process_up->GetLoadedSVR4Libraries();
+ auto library_list = m_current_process->GetLoadedSVR4Libraries();
if (!library_list)
return library_list.takeError();
@@ -3148,7 +3067,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState(
Status error = reg_context.ReadAllRegisterValues(register_data_sp);
if (error.Fail()) {
LLDB_LOG(log, "pid {0} failed to save all register values: {1}",
- m_debugged_process_up->GetID(), error);
+ m_current_process->GetID(), error);
return SendErrorResponse(0x75);
}
@@ -3211,7 +3130,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState(
if (it == m_saved_registers_map.end()) {
LLDB_LOG(log,
"pid {0} does not have a register set save buffer for id {1}",
- m_debugged_process_up->GetID(), save_id);
+ m_current_process->GetID(), save_id);
return SendErrorResponse(0x77);
}
register_data_sp = it->second;
@@ -3223,7 +3142,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState(
Status error = reg_context.WriteAllRegisterValues(register_data_sp);
if (error.Fail()) {
LLDB_LOG(log, "pid {0} failed to restore all register values: {1}",
- m_debugged_process_up->GetID(), error);
+ m_current_process->GetID(), error);
return SendErrorResponse(0x77);
}
@@ -3263,7 +3182,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttach(
}
// Notify we attached by sending a stop packet.
- return SendStopReasonForState(m_debugged_process_up->GetState());
+ return SendStopReasonForState(m_current_process->GetState());
}
GDBRemoteCommunication::PacketResult
@@ -3293,7 +3212,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttachWait(
}
// Notify we attached by sending a stop packet.
- return SendStopReasonForState(m_debugged_process_up->GetState());
+ return SendStopReasonForState(m_current_process->GetState());
}
GDBRemoteCommunication::PacketResult
@@ -3329,25 +3248,13 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttachOrWait(
}
// Notify we attached by sending a stop packet.
- return SendStopReasonForState(m_debugged_process_up->GetState());
+ return SendStopReasonForState(m_current_process->GetState());
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
-
StopSTDIOForwarding();
- // Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
- LLDB_LOGF(
- log,
- "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
- __FUNCTION__);
- return SendErrorResponse(0x15);
- }
-
lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
// Consume the ';' after D.
@@ -3362,19 +3269,32 @@ GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) {
return SendIllFormedResponse(packet, "D failed to parse the process id");
}
- if (pid != LLDB_INVALID_PROCESS_ID && m_debugged_process_up->GetID() != pid) {
- return SendIllFormedResponse(packet, "Invalid pid");
- }
-
- const Status error = m_debugged_process_up->Detach();
- if (error.Fail()) {
- LLDB_LOGF(log,
- "GDBRemoteCommunicationServerLLGS::%s failed to detach from "
- "pid %" PRIu64 ": %s\n",
- __FUNCTION__, m_debugged_process_up->GetID(), error.AsCString());
- return SendErrorResponse(0x01);
+ // Detach forked children if their PID was specified *or* no PID was requested
+ // (i.e. detach-all packet).
+ llvm::Error detach_error = llvm::Error::success();
+ bool detached = false;
+ for (auto it = m_debugged_processes.begin();
+ it != m_debugged_processes.end();) {
+ if (pid == LLDB_INVALID_PROCESS_ID || pid == it->first) {
+ if (llvm::Error e = it->second->Detach().ToError())
+ detach_error = llvm::joinErrors(std::move(detach_error), std::move(e));
+ else {
+ if (it->second.get() == m_current_process)
+ m_current_process = nullptr;
+ if (it->second.get() == m_continue_process)
+ m_continue_process = nullptr;
+ it = m_debugged_processes.erase(it);
+ detached = true;
+ continue;
+ }
+ }
+ ++it;
}
+ if (detach_error)
+ return SendErrorResponse(std::move(detach_error));
+ if (!detached)
+ return SendErrorResponse(Status("PID %" PRIu64 " not traced", pid));
return SendOKResponse();
}
@@ -3384,7 +3304,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo(
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
packet.SetFilePos(strlen("qThreadStopInfo"));
- const lldb::tid_t tid = packet.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID);
+ const lldb::tid_t tid = packet.GetHexMaxU64(false, LLDB_INVALID_THREAD_ID);
if (tid == LLDB_INVALID_THREAD_ID) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s failed, could not "
@@ -3401,19 +3321,19 @@ GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo(
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
// Ensure we have a debugged process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
return SendErrorResponse(50);
- LLDB_LOG(log, "preparing packet for pid {0}", m_debugged_process_up->GetID());
+ LLDB_LOG(log, "preparing packet for pid {0}", m_current_process->GetID());
StreamString response;
const bool threads_with_valid_stop_info_only = false;
- llvm::Expected<json::Value> threads_info = GetJSONThreadsInfo(
- *m_debugged_process_up, threads_with_valid_stop_info_only);
+ llvm::Expected<json::Value> threads_info =
+ GetJSONThreadsInfo(*m_current_process, threads_with_valid_stop_info_only);
if (!threads_info) {
LLDB_LOG_ERROR(log, threads_info.takeError(),
"failed to prepare a packet for pid {1}: {0}",
- m_debugged_process_up->GetID());
+ m_current_process->GetID());
return SendErrorResponse(52);
}
@@ -3427,8 +3347,8 @@ GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)
+ if (!m_current_process ||
+ m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)
return SendErrorResponse(68);
packet.SetFilePos(strlen("qWatchpointSupportInfo"));
@@ -3437,7 +3357,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo(
if (packet.GetChar() != ':')
return SendErrorResponse(67);
- auto hw_debug_cap = m_debugged_process_up->GetHardwareDebugSupportInfo();
+ auto hw_debug_cap = m_current_process->GetHardwareDebugSupportInfo();
StreamGDBRemote response;
if (hw_debug_cap == llvm::None)
@@ -3452,8 +3372,8 @@ GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)
+ if (!m_current_process ||
+ m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)
return SendErrorResponse(67);
packet.SetFilePos(strlen("qFileLoadAddress:"));
@@ -3465,7 +3385,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress(
lldb::addr_t file_load_address = LLDB_INVALID_ADDRESS;
Status error =
- m_debugged_process_up->GetFileLoadAddress(file_name, file_load_address);
+ m_current_process->GetFileLoadAddress(file_name, file_load_address);
if (error.Fail())
return SendErrorResponse(69);
@@ -3501,16 +3421,169 @@ GDBRemoteCommunicationServerLLGS::Handle_QPassSignals(
}
// Fail if we don't have a current process.
- if (!m_debugged_process_up)
+ if (!m_current_process)
return SendErrorResponse(68);
- Status error = m_debugged_process_up->IgnoreSignals(signals);
+ Status error = m_current_process->IgnoreSignals(signals);
if (error.Fail())
return SendErrorResponse(69);
return SendOKResponse();
}
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_qMemTags(
+ StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ // Ensure we have a process.
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ LLDB_LOGF(
+ log,
+ "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
+ __FUNCTION__);
+ return SendErrorResponse(1);
+ }
+
+ // We are expecting
+ // qMemTags:<hex address>,<hex length>:<hex type>
+
+ // Address
+ packet.SetFilePos(strlen("qMemTags:"));
+ const char *current_char = packet.Peek();
+ if (!current_char || *current_char == ',')
+ return SendIllFormedResponse(packet, "Missing address in qMemTags packet");
+ const lldb::addr_t addr = packet.GetHexMaxU64(/*little_endian=*/false, 0);
+
+ // Length
+ char previous_char = packet.GetChar();
+ current_char = packet.Peek();
+ // If we don't have a separator or the length field is empty
+ if (previous_char != ',' || (current_char && *current_char == ':'))
+ return SendIllFormedResponse(packet,
+ "Invalid addr,length pair in qMemTags packet");
+
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(
+ packet, "Too short qMemtags: packet (looking for length)");
+ const size_t length = packet.GetHexMaxU64(/*little_endian=*/false, 0);
+
+ // Type
+ const char *invalid_type_err = "Invalid type field in qMemTags: packet";
+ if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':')
+ return SendIllFormedResponse(packet, invalid_type_err);
+
+ int32_t type =
+ packet.GetS32(std::numeric_limits<int32_t>::max(), /*base=*/16);
+ if (type == std::numeric_limits<int32_t>::max() ||
+ // To catch inputs like "123aardvark" that will parse but clearly aren't
+ // valid in this case.
+ packet.GetBytesLeft()) {
+ return SendIllFormedResponse(packet, invalid_type_err);
+ }
+
+ StreamGDBRemote response;
+ std::vector<uint8_t> tags;
+ Status error = m_current_process->ReadMemoryTags(type, addr, length, tags);
+ if (error.Fail())
+ return SendErrorResponse(1);
+
+ // This m is here in case we want to support multi part replies in the future.
+ // In the same manner as qfThreadInfo/qsThreadInfo.
+ response.PutChar('m');
+ response.PutBytesAsRawHex8(tags.data(), tags.size());
+ return SendPacketNoLock(response.GetString());
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_QMemTags(
+ StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ // Ensure we have a process.
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ LLDB_LOGF(
+ log,
+ "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
+ __FUNCTION__);
+ return SendErrorResponse(1);
+ }
+
+ // We are expecting
+ // QMemTags:<hex address>,<hex length>:<hex type>:<tags as hex bytes>
+
+ // Address
+ packet.SetFilePos(strlen("QMemTags:"));
+ const char *current_char = packet.Peek();
+ if (!current_char || *current_char == ',')
+ return SendIllFormedResponse(packet, "Missing address in QMemTags packet");
+ const lldb::addr_t addr = packet.GetHexMaxU64(/*little_endian=*/false, 0);
+
+ // Length
+ char previous_char = packet.GetChar();
+ current_char = packet.Peek();
+ // If we don't have a separator or the length field is empty
+ if (previous_char != ',' || (current_char && *current_char == ':'))
+ return SendIllFormedResponse(packet,
+ "Invalid addr,length pair in QMemTags packet");
+
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(
+ packet, "Too short QMemtags: packet (looking for length)");
+ const size_t length = packet.GetHexMaxU64(/*little_endian=*/false, 0);
+
+ // Type
+ const char *invalid_type_err = "Invalid type field in QMemTags: packet";
+ if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':')
+ return SendIllFormedResponse(packet, invalid_type_err);
+
+ // Our GetU64 uses strtoull which allows leading +/-, we don't want that.
+ const char *first_type_char = packet.Peek();
+ if (first_type_char && (*first_type_char == '+' || *first_type_char == '-'))
+ return SendIllFormedResponse(packet, invalid_type_err);
+
+ // The type is a signed integer but is in the packet as its raw bytes.
+ // So parse first as unsigned then cast to signed later.
+ // We extract to 64 bit, even though we only expect 32, so that we've
+ // got some invalid value we can check for.
+ uint64_t raw_type =
+ packet.GetU64(std::numeric_limits<uint64_t>::max(), /*base=*/16);
+ if (raw_type > std::numeric_limits<uint32_t>::max())
+ return SendIllFormedResponse(packet, invalid_type_err);
+ int32_t type = static_cast<int32_t>(raw_type);
+
+ // Tag data
+ if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':')
+ return SendIllFormedResponse(packet,
+ "Missing tag data in QMemTags: packet");
+
+ // Must be 2 chars per byte
+ const char *invalid_data_err = "Invalid tag data in QMemTags: packet";
+ if (packet.GetBytesLeft() % 2)
+ return SendIllFormedResponse(packet, invalid_data_err);
+
+ // This is bytes here and is unpacked into target specific tags later
+ // We cannot assume that number of bytes == length here because the server
+ // can repeat tags to fill a given range.
+ std::vector<uint8_t> tag_data;
+ // Zero length writes will not have any tag data
+ // (but we pass them on because it will still check that tagging is enabled)
+ if (packet.GetBytesLeft()) {
+ size_t byte_count = packet.GetBytesLeft() / 2;
+ tag_data.resize(byte_count);
+ size_t converted_bytes = packet.GetHexBytes(tag_data, 0);
+ if (converted_bytes != byte_count) {
+ return SendIllFormedResponse(packet, invalid_data_err);
+ }
+ }
+
+ Status status =
+ m_current_process->WriteMemoryTags(type, addr, length, tag_data);
+ return status.Success() ? SendOKResponse() : SendErrorResponse(1);
+}
+
void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
@@ -3539,8 +3612,8 @@ void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() {
NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix(
StringExtractorGDBRemote &packet) {
// We have no thread if we don't have a process.
- if (!m_debugged_process_up ||
- m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)
+ if (!m_current_process ||
+ m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)
return nullptr;
// If the client hasn't asked for thread suffix support, there will not be a
@@ -3551,9 +3624,9 @@ NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix(
return nullptr;
else if (current_tid == 0) {
// Pick a thread.
- return m_debugged_process_up->GetThreadAtIndex(0);
+ return m_current_process->GetThreadAtIndex(0);
} else
- return m_debugged_process_up->GetThreadByID(current_tid);
+ return m_current_process->GetThreadByID(current_tid);
}
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
@@ -3583,7 +3656,7 @@ NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix(
packet.SetFilePos(packet.GetFilePos() + strlen("thread:"));
const lldb::tid_t tid = packet.GetHexMaxU64(false, 0);
if (tid != 0)
- return m_debugged_process_up->GetThreadByID(tid);
+ return m_current_process->GetThreadByID(tid);
return nullptr;
}
@@ -3593,9 +3666,9 @@ lldb::tid_t GDBRemoteCommunicationServerLLGS::GetCurrentThreadID() const {
// Use whatever the debug process says is the current thread id since the
// protocol either didn't specify or specified we want any/all threads
// marked as the current thread.
- if (!m_debugged_process_up)
+ if (!m_current_process)
return LLDB_INVALID_THREAD_ID;
- return m_debugged_process_up->GetCurrentThreadID();
+ return m_current_process->GetCurrentThreadID();
}
// Use the specific current thread id set by the gdb remote protocol.
return m_current_tid;
@@ -3616,9 +3689,9 @@ void GDBRemoteCommunicationServerLLGS::ClearProcessSpecificData() {
FileSpec
GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string &module_path,
const ArchSpec &arch) {
- if (m_debugged_process_up) {
+ if (m_current_process) {
FileSpec file_spec;
- if (m_debugged_process_up
+ if (m_current_process
->GetLoadedModuleFileSpec(module_path.c_str(), file_spec)
.Success()) {
if (FileSystem::Instance().Exists(file_spec))
@@ -3653,3 +3726,93 @@ std::string GDBRemoteCommunicationServerLLGS::XMLEncodeAttributeValue(
}
return result;
}
+
+llvm::Expected<lldb::tid_t> GDBRemoteCommunicationServerLLGS::ReadTid(
+ StringExtractorGDBRemote &packet, bool allow_all, lldb::pid_t default_pid) {
+ assert(m_current_process);
+ assert(m_current_process->GetID() != LLDB_INVALID_PROCESS_ID);
+
+ auto pid_tid = packet.GetPidTid(default_pid);
+ if (!pid_tid)
+ return llvm::make_error<StringError>(inconvertibleErrorCode(),
+ "Malformed thread-id");
+
+ lldb::pid_t pid = pid_tid->first;
+ lldb::tid_t tid = pid_tid->second;
+
+ if (!allow_all && pid == StringExtractorGDBRemote::AllProcesses)
+ return llvm::make_error<StringError>(
+ inconvertibleErrorCode(),
+ llvm::formatv("PID value {0} not allowed", pid == 0 ? 0 : -1));
+
+ if (!allow_all && tid == StringExtractorGDBRemote::AllThreads)
+ return llvm::make_error<StringError>(
+ inconvertibleErrorCode(),
+ llvm::formatv("TID value {0} not allowed", tid == 0 ? 0 : -1));
+
+ if (pid != StringExtractorGDBRemote::AllProcesses) {
+ if (pid != m_current_process->GetID())
+ return llvm::make_error<StringError>(
+ inconvertibleErrorCode(), llvm::formatv("PID {0} not debugged", pid));
+ }
+
+ return tid;
+}
+
+std::vector<std::string> GDBRemoteCommunicationServerLLGS::HandleFeatures(
+ const llvm::ArrayRef<llvm::StringRef> client_features) {
+ std::vector<std::string> ret =
+ GDBRemoteCommunicationServerCommon::HandleFeatures(client_features);
+ ret.insert(ret.end(), {
+ "QThreadSuffixSupported+",
+ "QListThreadsInStopReply+",
+ "qXfer:features:read+",
+ });
+
+ // report server-only features
+ using Extension = NativeProcessProtocol::Extension;
+ Extension plugin_features = m_process_factory.GetSupportedExtensions();
+ if (bool(plugin_features & Extension::pass_signals))
+ ret.push_back("QPassSignals+");
+ if (bool(plugin_features & Extension::auxv))
+ ret.push_back("qXfer:auxv:read+");
+ if (bool(plugin_features & Extension::libraries_svr4))
+ ret.push_back("qXfer:libraries-svr4:read+");
+ if (bool(plugin_features & Extension::memory_tagging))
+ ret.push_back("memory-tagging+");
+
+ // check for client features
+ m_extensions_supported = {};
+ for (llvm::StringRef x : client_features)
+ m_extensions_supported |=
+ llvm::StringSwitch<Extension>(x)
+ .Case("multiprocess+", Extension::multiprocess)
+ .Case("fork-events+", Extension::fork)
+ .Case("vfork-events+", Extension::vfork)
+ .Default({});
+
+ m_extensions_supported &= plugin_features;
+
+ // fork & vfork require multiprocess
+ if (!bool(m_extensions_supported & Extension::multiprocess))
+ m_extensions_supported &= ~(Extension::fork | Extension::vfork);
+
+ // report only if actually supported
+ if (bool(m_extensions_supported & Extension::multiprocess))
+ ret.push_back("multiprocess+");
+ if (bool(m_extensions_supported & Extension::fork))
+ ret.push_back("fork-events+");
+ if (bool(m_extensions_supported & Extension::vfork))
+ ret.push_back("vfork-events+");
+
+ for (auto &x : m_debugged_processes)
+ SetEnabledExtensions(*x.second);
+ return ret;
+}
+
+void GDBRemoteCommunicationServerLLGS::SetEnabledExtensions(
+ NativeProcessProtocol &process) {
+ NativeProcessProtocol::Extension flags = m_extensions_supported;
+ assert(!bool(flags & ~m_process_factory.GetSupportedExtensions()));
+ process.SetEnabledExtensions(flags);
+}