aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp')
-rw-r--r--contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp703
1 files changed, 472 insertions, 231 deletions
diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index 123a8198a89b..63174ef55219 100644
--- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -35,6 +35,7 @@
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/GDBRemote.h"
#include "lldb/Utility/LLDBAssert.h"
+#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/State.h"
@@ -106,6 +107,8 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() {
&GDBRemoteCommunicationServerLLGS::Handle_P);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC,
&GDBRemoteCommunicationServerLLGS::Handle_qC);
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_T,
+ &GDBRemoteCommunicationServerLLGS::Handle_T);
RegisterMemberFunctionHandler(
StringExtractorGDBRemote::eServerPacketType_qfThreadInfo,
&GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo);
@@ -232,8 +235,22 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() {
});
RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_vKill,
+ &GDBRemoteCommunicationServerLLGS::Handle_vKill);
+
+ RegisterMemberFunctionHandler(
StringExtractorGDBRemote::eServerPacketType_qLLDBSaveCore,
&GDBRemoteCommunicationServerLLGS::Handle_qSaveCore);
+
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QNonStop,
+ &GDBRemoteCommunicationServerLLGS::Handle_QNonStop);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_vStopped,
+ &GDBRemoteCommunicationServerLLGS::Handle_vStopped);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_vCtrlC,
+ &GDBRemoteCommunicationServerLLGS::Handle_vCtrlC);
}
void GDBRemoteCommunicationServerLLGS::SetLaunchInfo(const ProcessLaunchInfo &info) {
@@ -241,7 +258,7 @@ void GDBRemoteCommunicationServerLLGS::SetLaunchInfo(const ProcessLaunchInfo &in
}
Status GDBRemoteCommunicationServerLLGS::LaunchProcess() {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
if (!m_process_launch_info.GetArguments().GetArgumentCount())
return Status("%s: no process command line specified to launch",
@@ -323,7 +340,7 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() {
}
Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64,
__FUNCTION__, pid);
@@ -370,7 +387,7 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) {
Status GDBRemoteCommunicationServerLLGS::AttachWaitProcess(
llvm::StringRef process_name, bool include_existing) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
std::chrono::milliseconds polling_interval = std::chrono::milliseconds(1);
@@ -440,7 +457,7 @@ Status GDBRemoteCommunicationServerLLGS::AttachWaitProcess(
void GDBRemoteCommunicationServerLLGS::InitializeDelegate(
NativeProcessProtocol *process) {
assert(process && "process cannot be NULL");
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
if (log) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s called with "
@@ -454,7 +471,7 @@ GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::SendWResponse(
NativeProcessProtocol *process) {
assert(process && "process cannot be NULL");
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
// send W notification
auto wait_status = process->GetExitStatus();
@@ -471,8 +488,17 @@ GDBRemoteCommunicationServerLLGS::SendWResponse(
LLDB_LOG(log, "pid = {0}, returning exit type {1}", process->GetID(),
*wait_status);
+ // If the process was killed through vKill, return "OK".
+ if (m_vkilled_processes.find(process->GetID()) != m_vkilled_processes.end())
+ return SendOKResponse();
+
StreamGDBRemote response;
response.Format("{0:g}", *wait_status);
+ if (bool(m_extensions_supported & NativeProcessProtocol::Extension::multiprocess))
+ response.Format(";process:{0:x-}", process->GetID());
+ if (m_non_stop)
+ return SendNotificationPacketNoLock("Stop", m_stop_notification_queue,
+ response.GetString());
return SendPacketNoLock(response.GetString());
}
@@ -608,7 +634,7 @@ static void WriteRegisterValueInHexFixedWidth(
static llvm::Optional<json::Object>
GetRegistersAsJSON(NativeThreadProtocol &thread) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+ Log *log = GetLog(LLDBLog::Thread);
NativeRegisterContext& reg_ctx = thread.GetRegisterContext();
@@ -693,26 +719,21 @@ static const char *GetStopReasonString(StopReason stop_reason) {
static llvm::Expected<json::Array>
GetJSONThreadsInfo(NativeProcessProtocol &process, bool abridged) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
+ Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
json::Array threads_array;
// Ensure we can get info on the given thread.
- uint32_t thread_idx = 0;
- for (NativeThreadProtocol *thread;
- (thread = process.GetThreadAtIndex(thread_idx)) != nullptr;
- ++thread_idx) {
-
- lldb::tid_t tid = thread->GetID();
-
+ for (NativeThreadProtocol &thread : process.Threads()) {
+ lldb::tid_t tid = thread.GetID();
// Grab the reason this thread stopped.
struct ThreadStopInfo tid_stop_info;
std::string description;
- if (!thread->GetStopReason(tid_stop_info, description))
+ if (!thread.GetStopReason(tid_stop_info, description))
return llvm::make_error<llvm::StringError>(
"failed to get stop reason", llvm::inconvertibleErrorCode());
- const int signum = tid_stop_info.details.signal.signo;
+ const int signum = tid_stop_info.signo;
if (log) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
@@ -725,7 +746,7 @@ GetJSONThreadsInfo(NativeProcessProtocol &process, bool abridged) {
json::Object thread_obj;
if (!abridged) {
- if (llvm::Optional<json::Object> registers = GetRegistersAsJSON(*thread))
+ if (llvm::Optional<json::Object> registers = GetRegistersAsJSON(thread))
thread_obj.try_emplace("registers", std::move(*registers));
}
@@ -734,7 +755,7 @@ GetJSONThreadsInfo(NativeProcessProtocol &process, bool abridged) {
if (signum != 0)
thread_obj.try_emplace("signal", signum);
- const std::string thread_name = thread->GetName();
+ const std::string thread_name = thread.GetName();
if (!thread_name.empty())
thread_obj.try_emplace("name", thread_name);
@@ -763,29 +784,22 @@ GetJSONThreadsInfo(NativeProcessProtocol &process, bool abridged) {
return threads_array;
}
-GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
- lldb::tid_t tid) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
+StreamString
+GDBRemoteCommunicationServerLLGS::PrepareStopReplyPacketForThread(
+ NativeThreadProtocol &thread) {
+ Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
- // Ensure we have a debugged process.
- if (!m_current_process ||
- (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
- return SendErrorResponse(50);
+ NativeProcessProtocol &process = thread.GetProcess();
- LLDB_LOG(log, "preparing packet for pid {0} tid {1}",
- m_current_process->GetID(), tid);
-
- // Ensure we can get info on the given thread.
- NativeThreadProtocol *thread = m_current_process->GetThreadByID(tid);
- if (!thread)
- return SendErrorResponse(51);
+ LLDB_LOG(log, "preparing packet for pid {0} tid {1}", process.GetID(),
+ thread.GetID());
// Grab the reason this thread stopped.
+ StreamString response;
struct ThreadStopInfo tid_stop_info;
std::string description;
- if (!thread->GetStopReason(tid_stop_info, description))
- return SendErrorResponse(52);
+ if (!thread.GetStopReason(tid_stop_info, description))
+ return response;
// FIXME implement register handling for exec'd inferiors.
// if (tid_stop_info.reason == eStopReasonExec) {
@@ -793,24 +807,25 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
// InitializeRegisters(force);
// }
- StreamString response;
// Output the T packet with the thread
response.PutChar('T');
- int signum = tid_stop_info.details.signal.signo;
+ int signum = tid_stop_info.signo;
LLDB_LOG(
log,
"pid {0}, tid {1}, got signal signo = {2}, reason = {3}, exc_type = {4}",
- m_current_process->GetID(), tid, signum, int(tid_stop_info.reason),
+ process.GetID(), thread.GetID(), signum, int(tid_stop_info.reason),
tid_stop_info.details.exception.type);
// Print the signal number.
response.PutHex8(signum & 0xff);
- // Include the tid.
- response.Printf("thread:%" PRIx64 ";", tid);
+ // Include the (pid and) tid.
+ response.PutCString("thread:");
+ AppendThreadIDToResponse(response, process.GetID(), thread.GetID());
+ response.PutChar(';');
// Include the thread name if there is one.
- const std::string thread_name = thread->GetName();
+ const std::string thread_name = thread.GetName();
if (!thread_name.empty()) {
size_t thread_name_len = thread_name.length();
@@ -836,14 +851,12 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
if (m_list_threads_in_stop_reply) {
response.PutCString("threads:");
- uint32_t thread_index = 0;
- NativeThreadProtocol *listed_thread;
- for (listed_thread = m_current_process->GetThreadAtIndex(thread_index);
- listed_thread; ++thread_index,
- listed_thread = m_current_process->GetThreadAtIndex(thread_index)) {
- if (thread_index > 0)
+ uint32_t thread_num = 0;
+ for (NativeThreadProtocol &listed_thread : process.Threads()) {
+ if (thread_num > 0)
response.PutChar(',');
- response.Printf("%" PRIx64, listed_thread->GetID());
+ response.Printf("%" PRIx64, listed_thread.GetID());
+ ++thread_num;
}
response.PutChar(';');
@@ -852,7 +865,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
// is hex ascii JSON that contains the thread IDs thread stop info only for
// threads that have stop reasons. Only send this if we have more than one
// thread otherwise this packet has all the info it needs.
- if (thread_index > 1) {
+ if (thread_num > 1) {
const bool threads_with_valid_stop_info_only = true;
llvm::Expected<json::Array> threads_info = GetJSONThreadsInfo(
*m_current_process, threads_with_valid_stop_info_only);
@@ -865,16 +878,14 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
} else {
LLDB_LOG_ERROR(log, threads_info.takeError(),
"failed to prepare a jstopinfo field for pid {1}: {0}",
- m_current_process->GetID());
+ process.GetID());
}
}
- uint32_t i = 0;
response.PutCString("thread-pcs");
char delimiter = ':';
- for (NativeThreadProtocol *thread;
- (thread = m_current_process->GetThreadAtIndex(i)) != nullptr; ++i) {
- NativeRegisterContext& reg_ctx = thread->GetRegisterContext();
+ for (NativeThreadProtocol &thread : process.Threads()) {
+ NativeRegisterContext &reg_ctx = thread.GetRegisterContext();
uint32_t reg_to_read = reg_ctx.ConvertRegisterKindToRegisterNumber(
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
@@ -905,7 +916,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
//
// Grab the register context.
- NativeRegisterContext& reg_ctx = thread->GetRegisterContext();
+ NativeRegisterContext &reg_ctx = thread.GetRegisterContext();
const auto expedited_regs =
reg_ctx.GetExpeditedRegisters(ExpeditedRegs::Full);
@@ -922,8 +933,9 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
&reg_value, lldb::eByteOrderBig);
response.PutChar(';');
} else {
- LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s failed to read "
- "register '%s' index %" PRIu32 ": %s",
+ LLDB_LOGF(log,
+ "GDBRemoteCommunicationServerLLGS::%s failed to read "
+ "register '%s' index %" PRIu32 ": %s",
__FUNCTION__,
reg_info_p->name ? reg_info_p->name : "<unnamed-register>",
reg_num, error.AsCString());
@@ -972,17 +984,53 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
tid_stop_info.details.fork.child_tid);
}
+ return response;
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
+ NativeProcessProtocol &process, lldb::tid_t tid, bool force_synchronous) {
+ // Ensure we can get info on the given thread.
+ NativeThreadProtocol *thread = process.GetThreadByID(tid);
+ if (!thread)
+ return SendErrorResponse(51);
+
+ StreamString response = PrepareStopReplyPacketForThread(*thread);
+ if (response.Empty())
+ return SendErrorResponse(42);
+
+ if (m_non_stop && !force_synchronous) {
+ PacketResult ret = SendNotificationPacketNoLock(
+ "Stop", m_stop_notification_queue, response.GetString());
+ // Queue notification events for the remaining threads.
+ EnqueueStopReplyPackets(tid);
+ return ret;
+ }
+
return SendPacketNoLock(response.GetString());
}
+void GDBRemoteCommunicationServerLLGS::EnqueueStopReplyPackets(
+ lldb::tid_t thread_to_skip) {
+ if (!m_non_stop)
+ return;
+
+ for (NativeThreadProtocol &listed_thread : m_current_process->Threads()) {
+ if (listed_thread.GetID() != thread_to_skip)
+ m_stop_notification_queue.push_back(
+ PrepareStopReplyPacketForThread(listed_thread).GetString().str());
+ }
+}
+
void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited(
NativeProcessProtocol *process) {
assert(process && "process cannot be NULL");
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
- PacketResult result = SendStopReasonForState(StateType::eStateExited);
+ PacketResult result = SendStopReasonForState(
+ *process, StateType::eStateExited, /*force_synchronous=*/false);
if (result != PacketResult::Success) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s failed to send stop "
@@ -990,20 +1038,37 @@ void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited(
__FUNCTION__, process->GetID());
}
- // Close the pipe to the inferior terminal i/o if we launched it and set one
- // up.
- MaybeCloseInferiorTerminalConnection();
-
- // We are ready to exit the debug monitor.
- m_exit_now = true;
- m_mainloop.RequestTermination();
+ if (m_current_process == process)
+ m_current_process = nullptr;
+ if (m_continue_process == process)
+ m_continue_process = nullptr;
+
+ lldb::pid_t pid = process->GetID();
+ m_mainloop.AddPendingCallback([this, pid](MainLoopBase &loop) {
+ m_debugged_processes.erase(pid);
+ auto vkill_it = m_vkilled_processes.find(pid);
+ if (vkill_it != m_vkilled_processes.end())
+ m_vkilled_processes.erase(vkill_it);
+ // Terminate the main loop only if vKill has not been used.
+ // When running in non-stop mode, wait for the vStopped to clear
+ // the notification queue.
+ else if (m_debugged_processes.empty() && !m_non_stop) {
+ // Close the pipe to the inferior terminal i/o if we launched it and set
+ // one up.
+ MaybeCloseInferiorTerminalConnection();
+
+ // We are ready to exit the debug monitor.
+ m_exit_now = true;
+ loop.RequestTermination();
+ }
+ });
}
void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped(
NativeProcessProtocol *process) {
assert(process && "process cannot be NULL");
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
// Send the stop reason unless this is the stop after the launch or attach.
@@ -1014,7 +1079,8 @@ void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped(
break;
default:
// In all other cases, send the stop reason.
- PacketResult result = SendStopReasonForState(StateType::eStateStopped);
+ PacketResult result = SendStopReasonForState(
+ *process, StateType::eStateStopped, /*force_synchronous=*/false);
if (result != PacketResult::Success) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s failed to send stop "
@@ -1028,7 +1094,7 @@ void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped(
void GDBRemoteCommunicationServerLLGS::ProcessStateChanged(
NativeProcessProtocol *process, lldb::StateType state) {
assert(process && "process cannot be NULL");
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
if (log) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s called with "
@@ -1038,7 +1104,6 @@ void GDBRemoteCommunicationServerLLGS::ProcessStateChanged(
switch (state) {
case StateType::eStateRunning:
- StartSTDIOForwarding();
break;
case StateType::eStateStopped:
@@ -1163,7 +1228,7 @@ void GDBRemoteCommunicationServerLLGS::StartSTDIOForwarding() {
return;
Status error;
- lldbassert(!m_stdio_handle_up);
+ assert(!m_stdio_handle_up);
m_stdio_handle_up = m_mainloop.RegisterReadObject(
m_stdio_communication.GetConnection()->GetReadObject(),
[this](MainLoopBase &) { SendProcessOutput(); }, error);
@@ -1171,11 +1236,8 @@ void GDBRemoteCommunicationServerLLGS::StartSTDIOForwarding() {
if (!m_stdio_handle_up) {
// Not much we can do about the failure. Log it and continue without
// forwarding.
- if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS))
- LLDB_LOGF(log,
- "GDBRemoteCommunicationServerLLGS::%s Failed to set up stdio "
- "forwarding: %s",
- __FUNCTION__, error.AsCString());
+ if (Log *log = GetLog(LLDBLog::Process))
+ LLDB_LOG(log, "Failed to set up stdio forwarding: {0}", error);
}
}
@@ -1198,7 +1260,7 @@ void GDBRemoteCommunicationServerLLGS::SendProcessOutput() {
case eConnectionStatusEndOfFile:
case eConnectionStatusError:
case eConnectionStatusNoConnection:
- if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS))
+ if (Log *log = GetLog(LLDBLog::Process))
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s Stopping stdio "
"forwarding as communication returned status %d (error: "
@@ -1349,29 +1411,61 @@ GDBRemoteCommunicationServerLLGS::Handle_qC(StringExtractorGDBRemote &packet) {
return SendErrorResponse(69);
StreamString response;
- response.Printf("QC%" PRIx64, thread->GetID());
+ response.PutCString("QC");
+ AppendThreadIDToResponse(response, m_current_process->GetID(),
+ thread->GetID());
return SendPacketNoLock(response.GetString());
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_k(StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
StopSTDIOForwarding();
- if (!m_current_process) {
+ if (m_debugged_processes.empty()) {
LLDB_LOG(log, "No debugged process found.");
return PacketResult::Success;
}
- Status error = m_current_process->Kill();
+ for (auto it = m_debugged_processes.begin(); it != m_debugged_processes.end();
+ ++it) {
+ LLDB_LOG(log, "Killing process {0}", it->first);
+ Status error = it->second->Kill();
+ if (error.Fail())
+ LLDB_LOG(log, "Failed to kill debugged process {0}: {1}", it->first,
+ error);
+ }
+
+ // The response to kill packet is undefined per the spec. LLDB
+ // follows the same rules as for continue packets, i.e. no response
+ // in all-stop mode, and "OK" in non-stop mode; in both cases this
+ // is followed by the actual stop reason.
+ return SendContinueSuccessResponse();
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_vKill(
+ StringExtractorGDBRemote &packet) {
+ StopSTDIOForwarding();
+
+ packet.SetFilePos(6); // vKill;
+ uint32_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16);
+ if (pid == LLDB_INVALID_PROCESS_ID)
+ return SendIllFormedResponse(packet,
+ "vKill failed to parse the process id");
+
+ auto it = m_debugged_processes.find(pid);
+ if (it == m_debugged_processes.end())
+ return SendErrorResponse(42);
+
+ Status error = it->second->Kill();
if (error.Fail())
- LLDB_LOG(log, "Failed to kill debugged process {0}: {1}",
- m_current_process->GetID(), error);
+ return SendErrorResponse(error.ToError());
- // No OK response for kill packet.
- // return SendOKResponse ();
+ // OK response is sent when the process dies.
+ m_vkilled_processes.insert(pid);
return PacketResult::Success;
}
@@ -1425,7 +1519,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QListThreadsInStopReply(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
+ Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
// Ensure we have a native process.
@@ -1500,13 +1594,14 @@ GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) {
return SendErrorResponse(0x38);
}
- // Don't send an "OK" packet; response is the stopped/exited message.
- return PacketResult::Success;
+ // Don't send an "OK" packet, except in non-stop mode;
+ // otherwise, the response is the stopped/exited message.
+ return SendContinueSuccessResponse();
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
+ Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
packet.SetFilePos(packet.GetFilePos() + ::strlen("c"));
@@ -1540,15 +1635,15 @@ GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) {
}
LLDB_LOG(log, "continued process {0}", m_continue_process->GetID());
- // No response required from continue.
- return PacketResult::Success;
+
+ return SendContinueSuccessResponse();
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_vCont_actions(
StringExtractorGDBRemote &packet) {
StreamString response;
- response.Printf("vCont;c;C;s;S");
+ response.Printf("vCont;c;C;s;S;t");
return SendPacketNoLock(response.GetString());
}
@@ -1556,7 +1651,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont_actions(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_vCont(
StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s handling vCont packet",
__FUNCTION__);
@@ -1570,24 +1665,16 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont(
return SendIllFormedResponse(packet, "Missing action from vCont package");
}
- // Check if this is all continue (no options or ";c").
- if (::strcmp(packet.Peek(), ";c") == 0) {
- // Move past the ';', then do a simple 'c'.
- packet.SetFilePos(packet.GetFilePos() + 1);
- return Handle_c(packet);
- } else if (::strcmp(packet.Peek(), ";s") == 0) {
+ if (::strcmp(packet.Peek(), ";s") == 0) {
// Move past the ';', then do a simple 's'.
packet.SetFilePos(packet.GetFilePos() + 1);
return Handle_s(packet);
+ } else if (m_non_stop && ::strcmp(packet.Peek(), ";t") == 0) {
+ // TODO: add full support for "t" action
+ return SendOKResponse();
}
- // Ensure we have a native process.
- if (!m_continue_process) {
- LLDB_LOG(log, "no debugged process");
- return SendErrorResponse(0x36);
- }
-
- ResumeActionList thread_actions;
+ std::unordered_map<lldb::pid_t, ResumeActionList> thread_actions;
while (packet.GetBytesLeft() && *packet.Peek() == ';') {
// Skip the semi-colon.
@@ -1625,43 +1712,78 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont(
thread_action.state = eStateStepping;
break;
+ case 't':
+ // Stop
+ thread_action.state = eStateSuspended;
+ break;
+
default:
return SendIllFormedResponse(packet, "Unsupported vCont action");
break;
}
+ lldb::pid_t pid = StringExtractorGDBRemote::AllProcesses;
+ lldb::tid_t tid = StringExtractorGDBRemote::AllThreads;
+
// Parse out optional :{thread-id} value.
if (packet.GetBytesLeft() && (*packet.Peek() == ':')) {
// Consume the separator.
packet.GetChar();
- llvm::Expected<lldb::tid_t> tid_ret =
- ReadTid(packet, /*allow_all=*/true, m_continue_process->GetID());
- if (!tid_ret)
- return SendErrorResponse(tid_ret.takeError());
+ auto pid_tid = packet.GetPidTid(StringExtractorGDBRemote::AllProcesses);
+ if (!pid_tid)
+ return SendIllFormedResponse(packet, "Malformed thread-id");
+
+ pid = pid_tid->first;
+ tid = pid_tid->second;
+ }
- thread_action.tid = tid_ret.get();
- if (thread_action.tid == StringExtractorGDBRemote::AllThreads)
- thread_action.tid = LLDB_INVALID_THREAD_ID;
+ if (pid == StringExtractorGDBRemote::AllProcesses) {
+ if (m_debugged_processes.size() > 1)
+ return SendIllFormedResponse(
+ packet, "Resuming multiple processes not supported yet");
+ if (!m_continue_process) {
+ LLDB_LOG(log, "no debugged process");
+ return SendErrorResponse(0x36);
+ }
+ pid = m_continue_process->GetID();
}
- thread_actions.Append(thread_action);
+ if (tid == StringExtractorGDBRemote::AllThreads)
+ tid = LLDB_INVALID_THREAD_ID;
+
+ thread_action.tid = tid;
+
+ thread_actions[pid].Append(thread_action);
}
- Status error = m_continue_process->Resume(thread_actions);
- if (error.Fail()) {
- LLDB_LOG(log, "vCont failed for process {0}: {1}",
- m_continue_process->GetID(), error);
- return SendErrorResponse(GDBRemoteServerError::eErrorResume);
+ assert(thread_actions.size() >= 1);
+ if (thread_actions.size() > 1)
+ return SendIllFormedResponse(
+ packet, "Resuming multiple processes not supported yet");
+
+ for (std::pair<lldb::pid_t, ResumeActionList> x : thread_actions) {
+ auto process_it = m_debugged_processes.find(x.first);
+ if (process_it == m_debugged_processes.end()) {
+ LLDB_LOG(log, "vCont failed for process {0}: process not debugged",
+ x.first);
+ return SendErrorResponse(GDBRemoteServerError::eErrorResume);
+ }
+
+ Status error = process_it->second->Resume(x.second);
+ if (error.Fail()) {
+ LLDB_LOG(log, "vCont failed for process {0}: {1}", x.first, error);
+ return SendErrorResponse(GDBRemoteServerError::eErrorResume);
+ }
+
+ LLDB_LOG(log, "continued process {0}", x.first);
}
- LLDB_LOG(log, "continued process {0}", m_continue_process->GetID());
- // No response required from vCont.
- return PacketResult::Success;
+ return SendContinueSuccessResponse();
}
void GDBRemoteCommunicationServerLLGS::SetCurrentThreadID(lldb::tid_t tid) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+ Log *log = GetLog(LLDBLog::Thread);
LLDB_LOG(log, "setting current thread id to {0}", tid);
m_current_tid = tid;
@@ -1670,7 +1792,7 @@ void GDBRemoteCommunicationServerLLGS::SetCurrentThreadID(lldb::tid_t tid) {
}
void GDBRemoteCommunicationServerLLGS::SetContinueThreadID(lldb::tid_t tid) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+ Log *log = GetLog(LLDBLog::Thread);
LLDB_LOG(log, "setting continue thread id to {0}", tid);
m_continue_tid = tid;
@@ -1681,17 +1803,47 @@ GDBRemoteCommunicationServerLLGS::Handle_stop_reason(
StringExtractorGDBRemote &packet) {
// Handle the $? gdbremote command.
+ if (m_non_stop) {
+ // Clear the notification queue first, except for pending exit
+ // notifications.
+ llvm::erase_if(m_stop_notification_queue, [](const std::string &x) {
+ return x.front() != 'W' && x.front() != 'X';
+ });
+
+ if (m_current_process) {
+ // Queue stop reply packets for all active threads. Start with
+ // the current thread (for clients that don't actually support multiple
+ // stop reasons).
+ NativeThreadProtocol *thread = m_current_process->GetCurrentThread();
+ if (thread)
+ m_stop_notification_queue.push_back(
+ PrepareStopReplyPacketForThread(*thread).GetString().str());
+ EnqueueStopReplyPackets(thread ? thread->GetID()
+ : LLDB_INVALID_THREAD_ID);
+ }
+
+ // If the notification queue is empty (i.e. everything is running), send OK.
+ if (m_stop_notification_queue.empty())
+ return SendOKResponse();
+
+ // Send the first item from the new notification queue synchronously.
+ return SendPacketNoLock(m_stop_notification_queue.front());
+ }
+
// If no process, indicate error
if (!m_current_process)
return SendErrorResponse(02);
- return SendStopReasonForState(m_current_process->GetState());
+ return SendStopReasonForState(*m_current_process,
+ m_current_process->GetState(),
+ /*force_synchronous=*/true);
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::SendStopReasonForState(
- lldb::StateType process_state) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ NativeProcessProtocol &process, lldb::StateType process_state,
+ bool force_synchronous) {
+ Log *log = GetLog(LLDBLog::Process);
switch (process_state) {
case eStateAttaching:
@@ -1706,22 +1858,21 @@ GDBRemoteCommunicationServerLLGS::SendStopReasonForState(
case eStateSuspended:
case eStateStopped:
case eStateCrashed: {
- assert(m_current_process != nullptr);
- lldb::tid_t tid = m_current_process->GetCurrentThreadID();
+ lldb::tid_t tid = process.GetCurrentThreadID();
// Make sure we set the current thread so g and p packets return the data
// the gdb will expect.
SetCurrentThreadID(tid);
- return SendStopReplyPacketForThread(tid);
+ return SendStopReplyPacketForThread(process, tid, force_synchronous);
}
case eStateInvalid:
case eStateUnloaded:
case eStateExited:
- return SendWResponse(m_current_process);
+ return SendWResponse(&process);
default:
LLDB_LOG(log, "pid {0}, current state reporting not handled: {1}",
- m_current_process->GetID(), process_state);
+ process.GetID(), process_state);
break;
}
@@ -1819,38 +1970,38 @@ GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo(
return SendPacketNoLock(response.GetString());
}
+void GDBRemoteCommunicationServerLLGS::AddProcessThreads(
+ StreamGDBRemote &response, NativeProcessProtocol &process, bool &had_any) {
+ Log *log = GetLog(LLDBLog::Thread);
+
+ lldb::pid_t pid = process.GetID();
+ if (pid == LLDB_INVALID_PROCESS_ID)
+ return;
+
+ LLDB_LOG(log, "iterating over threads of process {0}", process.GetID());
+ for (NativeThreadProtocol &thread : process.Threads()) {
+ LLDB_LOG(log, "iterated thread tid={0}", thread.GetID());
+ response.PutChar(had_any ? ',' : 'm');
+ AppendThreadIDToResponse(response, pid, thread.GetID());
+ had_any = true;
+ }
+}
+
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo(
StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
-
- // Fail if we don't have a current process.
- if (!m_current_process ||
- (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
- LLDB_LOG(log, "no process ({0}), returning OK",
- m_current_process ? "invalid process id"
- : "null m_current_process");
- return SendOKResponse();
- }
+ assert(m_debugged_processes.size() == 1 ||
+ bool(m_extensions_supported &
+ NativeProcessProtocol::Extension::multiprocess));
+ bool had_any = false;
StreamGDBRemote response;
- response.PutChar('m');
- LLDB_LOG(log, "starting thread iteration");
- NativeThreadProtocol *thread;
- uint32_t thread_index;
- for (thread_index = 0,
- thread = m_current_process->GetThreadAtIndex(thread_index);
- thread; ++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)
- response.PutChar(',');
- response.Printf("%" PRIx64, thread->GetID());
- }
+ for (auto &pid_ptr : m_debugged_processes)
+ AddProcessThreads(response, *pid_ptr.second, had_any);
- LLDB_LOG(log, "finished thread iteration");
+ if (!had_any)
+ return SendOKResponse();
return SendPacketNoLock(response.GetString());
}
@@ -1864,7 +2015,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_g(StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+ Log *log = GetLog(LLDBLog::Thread);
// Move past packet name.
packet.SetFilePos(strlen("g"));
@@ -1919,7 +2070,7 @@ GDBRemoteCommunicationServerLLGS::Handle_g(StringExtractorGDBRemote &packet) {
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+ Log *log = GetLog(LLDBLog::Thread);
// Parse out the register number from the request.
packet.SetFilePos(strlen("p"));
@@ -1995,7 +2146,7 @@ GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) {
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+ Log *log = GetLog(LLDBLog::Thread);
// Ensure there is more content.
if (packet.GetBytesLeft() < 1)
@@ -2075,7 +2226,7 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) {
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+ Log *log = GetLog(LLDBLog::Thread);
// Parse out which variant of $H is requested.
packet.SetFilePos(strlen("H"));
@@ -2166,7 +2317,7 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) {
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_I(StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+ Log *log = GetLog(LLDBLog::Thread);
// Fail if we don't have a current process.
if (!m_current_process ||
@@ -2202,7 +2353,7 @@ GDBRemoteCommunicationServerLLGS::Handle_I(StringExtractorGDBRemote &packet) {
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_interrupt(
StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
+ Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
// Fail if we don't have a current process.
if (!m_current_process ||
@@ -2228,7 +2379,7 @@ GDBRemoteCommunicationServerLLGS::Handle_interrupt(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_memory_read(
StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
if (!m_current_process ||
(m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
@@ -2308,7 +2459,7 @@ GDBRemoteCommunicationServerLLGS::Handle_memory_read(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle__M(StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
if (!m_current_process ||
(m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
@@ -2357,7 +2508,7 @@ GDBRemoteCommunicationServerLLGS::Handle__M(StringExtractorGDBRemote &packet) {
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle__m(StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
if (!m_current_process ||
(m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
@@ -2385,7 +2536,7 @@ GDBRemoteCommunicationServerLLGS::Handle__m(StringExtractorGDBRemote &packet) {
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
if (!m_current_process ||
(m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
@@ -2465,7 +2616,7 @@ GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) {
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported(
StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
// Currently only the NativeProcessProtocol knows if it can handle a
// qMemoryRegionInfoSupported request, but we're not guaranteed to be
@@ -2498,7 +2649,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo(
StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
// Ensure we have a process.
if (!m_current_process ||
@@ -2580,7 +2731,7 @@ GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) {
// Ensure we have a process.
if (!m_current_process ||
(m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
LLDB_LOG(log, "failed, no process available");
return SendErrorResponse(0x15);
}
@@ -2652,7 +2803,7 @@ GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) {
m_current_process->SetBreakpoint(addr, size, want_hardware);
if (error.Success())
return SendOKResponse();
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+ Log *log = GetLog(LLDBLog::Breakpoints);
LLDB_LOG(log, "pid {0} failed to set breakpoint: {1}",
m_current_process->GetID(), error);
return SendErrorResponse(0x09);
@@ -2662,7 +2813,7 @@ GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) {
addr, size, watch_flags, want_hardware);
if (error.Success())
return SendOKResponse();
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ Log *log = GetLog(LLDBLog::Watchpoints);
LLDB_LOG(log, "pid {0} failed to set watchpoint: {1}",
m_current_process->GetID(), error);
return SendErrorResponse(0x09);
@@ -2674,7 +2825,7 @@ GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
// Ensure we have a process.
if (!m_current_process ||
(m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
LLDB_LOG(log, "failed, no process available");
return SendErrorResponse(0x15);
}
@@ -2740,7 +2891,7 @@ GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
m_current_process->RemoveBreakpoint(addr, want_hardware);
if (error.Success())
return SendOKResponse();
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+ Log *log = GetLog(LLDBLog::Breakpoints);
LLDB_LOG(log, "pid {0} failed to remove breakpoint: {1}",
m_current_process->GetID(), error);
return SendErrorResponse(0x09);
@@ -2749,7 +2900,7 @@ GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
const Status error = m_current_process->RemoveWatchpoint(addr);
if (error.Success())
return SendOKResponse();
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ Log *log = GetLog(LLDBLog::Watchpoints);
LLDB_LOG(log, "pid {0} failed to remove watchpoint: {1}",
m_current_process->GetID(), error);
return SendErrorResponse(0x09);
@@ -2758,7 +2909,7 @@ GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
+ Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
// Ensure we have a process.
if (!m_continue_process ||
@@ -2803,8 +2954,9 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) {
return SendErrorResponse(0x49);
}
- // No response here - the stop or exit will come from the resulting action.
- return PacketResult::Success;
+ // No response here, unless in non-stop mode.
+ // Otherwise, the stop or exit will come from the resulting action.
+ return SendContinueSuccessResponse();
}
llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
@@ -2815,7 +2967,7 @@ GDBRemoteCommunicationServerLLGS::BuildTargetXml() {
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"No thread available");
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
+ Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
// Get the register context for the first thread.
NativeRegisterContext &reg_context = thread->GetRegisterContext();
@@ -3032,7 +3184,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qXfer(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState(
StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+ Log *log = GetLog(LLDBLog::Thread);
// Move past packet name.
packet.SetFilePos(strlen("QSaveRegisterState"));
@@ -3052,7 +3204,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState(
NativeRegisterContext& reg_context = thread->GetRegisterContext();
// Save registers to a buffer.
- DataBufferSP register_data_sp;
+ WritableDataBufferSP register_data_sp;
Status error = reg_context.ReadAllRegisterValues(register_data_sp);
if (error.Fail()) {
LLDB_LOG(log, "pid {0} failed to save all register values: {1}",
@@ -3080,7 +3232,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState(
StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+ Log *log = GetLog(LLDBLog::Thread);
// Parse out save id.
packet.SetFilePos(strlen("QRestoreRegisterState:"));
@@ -3141,7 +3293,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_vAttach(
StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
// Consume the ';' after vAttach.
packet.SetFilePos(strlen("vAttach"));
@@ -3171,13 +3323,16 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttach(
}
// Notify we attached by sending a stop packet.
- return SendStopReasonForState(m_current_process->GetState());
+ assert(m_current_process);
+ return SendStopReasonForState(*m_current_process,
+ m_current_process->GetState(),
+ /*force_synchronous=*/false);
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_vAttachWait(
StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
// Consume the ';' after the identifier.
packet.SetFilePos(strlen("vAttachWait"));
@@ -3201,7 +3356,10 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttachWait(
}
// Notify we attached by sending a stop packet.
- return SendStopReasonForState(m_current_process->GetState());
+ assert(m_current_process);
+ return SendStopReasonForState(*m_current_process,
+ m_current_process->GetState(),
+ /*force_synchronous=*/false);
}
GDBRemoteCommunication::PacketResult
@@ -3213,7 +3371,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qVAttachOrWaitSupported(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_vAttachOrWait(
StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
// Consume the ';' after the identifier.
packet.SetFilePos(strlen("vAttachOrWait"));
@@ -3237,13 +3395,16 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttachOrWait(
}
// Notify we attached by sending a stop packet.
- return SendStopReasonForState(m_current_process->GetState());
+ assert(m_current_process);
+ return SendStopReasonForState(*m_current_process,
+ m_current_process->GetState(),
+ /*force_synchronous=*/false);
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_vRun(
StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
llvm::StringRef s = packet.GetStringRef();
if (!s.consume_front("vRun;"))
@@ -3265,8 +3426,12 @@ GDBRemoteCommunicationServerLLGS::Handle_vRun(
m_process_launch_info.GetExecutableFile().SetFile(
m_process_launch_info.GetArguments()[0].ref(), FileSpec::Style::native);
m_process_launch_error = LaunchProcess();
- if (m_process_launch_error.Success())
- return SendStopReasonForState(m_current_process->GetState());
+ if (m_process_launch_error.Success()) {
+ assert(m_current_process);
+ return SendStopReasonForState(*m_current_process,
+ m_current_process->GetState(),
+ /*force_synchronous=*/true);
+ }
LLDB_LOG(log, "failed to launch exe: {0}", m_process_launch_error);
}
return SendErrorResponse(8);
@@ -3274,6 +3439,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vRun(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) {
+ Log *log = GetLog(LLDBLog::Process);
StopSTDIOForwarding();
lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
@@ -3297,6 +3463,9 @@ GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) {
for (auto it = m_debugged_processes.begin();
it != m_debugged_processes.end();) {
if (pid == LLDB_INVALID_PROCESS_ID || pid == it->first) {
+ LLDB_LOGF(log,
+ "GDBRemoteCommunicationServerLLGS::%s detaching %" PRId64,
+ __FUNCTION__, it->first);
if (llvm::Error e = it->second->Detach().ToError())
detach_error = llvm::joinErrors(std::move(detach_error), std::move(e));
else {
@@ -3322,7 +3491,11 @@ GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) {
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo(
StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+ Log *log = GetLog(LLDBLog::Thread);
+
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse(50);
packet.SetFilePos(strlen("qThreadStopInfo"));
const lldb::tid_t tid = packet.GetHexMaxU64(false, LLDB_INVALID_THREAD_ID);
@@ -3333,13 +3506,14 @@ GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo(
__FUNCTION__, packet.GetStringRef().data());
return SendErrorResponse(0x15);
}
- return SendStopReplyPacketForThread(tid);
+ return SendStopReplyPacketForThread(*m_current_process, tid,
+ /*force_synchronous=*/true);
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo(
StringExtractorGDBRemote &) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
+ Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
// Ensure we have a debugged process.
if (!m_current_process ||
@@ -3455,7 +3629,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QPassSignals(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qMemTags(
StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
// Ensure we have a process.
if (!m_current_process ||
@@ -3536,7 +3710,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemTags(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_QMemTags(
StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
// Ensure we have a process.
if (!m_current_process ||
@@ -3656,8 +3830,91 @@ GDBRemoteCommunicationServerLLGS::Handle_qSaveCore(
return SendPacketNoLock(response.GetString());
}
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_QNonStop(
+ StringExtractorGDBRemote &packet) {
+ StringRef packet_str{packet.GetStringRef()};
+ assert(packet_str.startswith("QNonStop:"));
+ packet_str.consume_front("QNonStop:");
+ if (packet_str == "0") {
+ m_non_stop = false;
+ // TODO: stop all threads
+ } else if (packet_str == "1") {
+ m_non_stop = true;
+ } else
+ return SendErrorResponse(Status("Invalid QNonStop packet"));
+ return SendOKResponse();
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_vStopped(
+ StringExtractorGDBRemote &packet) {
+ // Per the protocol, the first message put into the queue is sent
+ // immediately. However, it remains the queue until the client ACKs
+ // it via vStopped -- then we pop it and send the next message.
+ // The process repeats until the last message in the queue is ACK-ed,
+ // in which case the vStopped packet sends an OK response.
+
+ if (m_stop_notification_queue.empty())
+ return SendErrorResponse(Status("No pending notification to ack"));
+ m_stop_notification_queue.pop_front();
+ if (!m_stop_notification_queue.empty())
+ return SendPacketNoLock(m_stop_notification_queue.front());
+ // If this was the last notification and all the processes exited,
+ // terminate the server.
+ if (m_debugged_processes.empty()) {
+ m_exit_now = true;
+ m_mainloop.RequestTermination();
+ }
+ return SendOKResponse();
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_vCtrlC(
+ StringExtractorGDBRemote &packet) {
+ if (!m_non_stop)
+ return SendErrorResponse(Status("vCtrl is only valid in non-stop mode"));
+
+ PacketResult interrupt_res = Handle_interrupt(packet);
+ // If interrupting the process failed, pass the result through.
+ if (interrupt_res != PacketResult::Success)
+ return interrupt_res;
+ // Otherwise, vCtrlC should issue an OK response (normal interrupts do not).
+ return SendOKResponse();
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_T(StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(strlen("T"));
+ auto pid_tid = packet.GetPidTid(m_current_process ? m_current_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;
+
+ // Technically, this would also be caught by the PID check but let's be more
+ // explicit about the error.
+ 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(1);
+
+ // Check the thread ID
+ if (!new_process_it->second->GetThreadByID(tid))
+ return SendErrorResponse(2);
+
+ return SendOKResponse();
+}
+
void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
// Tell the stdio connection to shut down.
if (m_stdio_communication.IsConnected()) {
@@ -3701,7 +3958,7 @@ NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix(
return m_current_process->GetThreadByID(current_tid);
}
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+ Log *log = GetLog(LLDBLog::Thread);
// Parse out the ';'.
if (packet.GetBytesLeft() < 1 || packet.GetChar() != ';') {
@@ -3752,7 +4009,7 @@ uint32_t GDBRemoteCommunicationServerLLGS::GetNextSavedRegistersID() {
}
void GDBRemoteCommunicationServerLLGS::ClearProcessSpecificData() {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log = GetLog(LLDBLog::Process);
LLDB_LOG(log, "clearing {0} xfer buffers", m_xfer_buffer_map.size());
m_xfer_buffer_map.clear();
@@ -3799,38 +4056,6 @@ 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 =
@@ -3839,6 +4064,7 @@ std::vector<std::string> GDBRemoteCommunicationServerLLGS::HandleFeatures(
"QThreadSuffixSupported+",
"QListThreadsInStopReply+",
"qXfer:features:read+",
+ "QNonStop+",
});
// report server-only features
@@ -3893,6 +4119,21 @@ void GDBRemoteCommunicationServerLLGS::SetEnabledExtensions(
process.SetEnabledExtensions(flags);
}
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::SendContinueSuccessResponse() {
+ // TODO: how to handle forwarding in non-stop mode?
+ StartSTDIOForwarding();
+ return m_non_stop ? SendOKResponse() : PacketResult::Success;
+}
+
+void GDBRemoteCommunicationServerLLGS::AppendThreadIDToResponse(
+ Stream &response, lldb::pid_t pid, lldb::tid_t tid) {
+ if (bool(m_extensions_supported &
+ NativeProcessProtocol::Extension::multiprocess))
+ response.Format("p{0:x-}.", pid);
+ response.Format("{0:x-}", tid);
+}
+
std::string
lldb_private::process_gdb_remote::LLGSArgToURL(llvm::StringRef url_arg,
bool reverse_connect) {