aboutsummaryrefslogtreecommitdiff
path: root/source/Plugins/Process/gdb-remote
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/Process/gdb-remote')
-rw-r--r--source/Plugins/Process/gdb-remote/CMakeLists.txt28
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp55
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp133
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h6
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp66
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp180
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h4
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp34
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp7
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h4
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp153
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.h12
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp221
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h19
-rw-r--r--source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp18
15 files changed, 472 insertions, 468 deletions
diff --git a/source/Plugins/Process/gdb-remote/CMakeLists.txt b/source/Plugins/Process/gdb-remote/CMakeLists.txt
index b28522725868..3d008f42499d 100644
--- a/source/Plugins/Process/gdb-remote/CMakeLists.txt
+++ b/source/Plugins/Process/gdb-remote/CMakeLists.txt
@@ -2,7 +2,20 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
include_directories(${LIBXML2_INCLUDE_DIR})
endif()
-add_lldb_library(lldbPluginProcessGDBRemote
+set(LLDB_PLUGINS
+ lldbPluginProcessUtility
+ lldbPluginPlatformMacOSX
+)
+
+if(CMAKE_SYSTEM_NAME MATCHES "Linux|Android")
+ list(APPEND LLDB_PLUGINS lldbPluginProcessLinux)
+endif()
+
+if(CMAKE_SYSTEM_NAME MATCHES "NetBSD")
+ list(APPEND LLDB_PLUGINS lldbPluginProcessNetBSD)
+endif()
+
+add_lldb_library(lldbPluginProcessGDBRemote PLUGIN
GDBRemoteClientBase.cpp
GDBRemoteCommunication.cpp
GDBRemoteCommunicationClient.cpp
@@ -14,4 +27,17 @@ add_lldb_library(lldbPluginProcessGDBRemote
ProcessGDBRemote.cpp
ProcessGDBRemoteLog.cpp
ThreadGDBRemote.cpp
+
+ LINK_LIBS
+ lldbBreakpoint
+ lldbCore
+ lldbDataFormatters
+ lldbHost
+ lldbInterpreter
+ lldbSymbol
+ lldbTarget
+ lldbUtility
+ ${LLDB_PLUGINS}
+ LINK_COMPONENTS
+ Support
)
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index bd87521fe6e7..7ef253decad6 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -16,12 +16,8 @@
// C++ Includes
// Other libraries and framework includes
-#include "lldb/Core/Log.h"
-#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/StreamFile.h"
-#include "lldb/Core/StreamString.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
-#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/Pipe.h"
@@ -30,6 +26,10 @@
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegularExpression.h"
+#include "lldb/Utility/StreamString.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ScopedPrinter.h"
@@ -72,7 +72,7 @@ void GDBRemoteCommunication::History::AddPacket(char packet_char,
m_packets[idx].type = type;
m_packets[idx].bytes_transmitted = bytes_transmitted;
m_packets[idx].packet_idx = m_total_packet_count;
- m_packets[idx].tid = Host::GetCurrentThreadID();
+ m_packets[idx].tid = llvm::get_threadid();
}
}
@@ -87,7 +87,7 @@ void GDBRemoteCommunication::History::AddPacket(const std::string &src,
m_packets[idx].type = type;
m_packets[idx].bytes_transmitted = bytes_transmitted;
m_packets[idx].packet_idx = m_total_packet_count;
- m_packets[idx].tid = Host::GetCurrentThreadID();
+ m_packets[idx].tid = llvm::get_threadid();
}
}
@@ -321,8 +321,7 @@ GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet,
uint8_t buffer[8192];
Error error;
- Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS |
- GDBR_LOG_VERBOSE));
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS));
// Check for a packet from our cache first without trying any reading...
if (CheckForPacket(NULL, 0, packet) != PacketType::Invalid)
@@ -334,12 +333,11 @@ GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet,
lldb::ConnectionStatus status = eConnectionStatusNoConnection;
size_t bytes_read = Read(buffer, sizeof(buffer), timeout, status, &error);
- if (log)
- log->Printf("%s: Read (buffer, (sizeof(buffer), timeout = %ld us, "
- "status = %s, error = %s) => bytes_read = %" PRIu64,
- LLVM_PRETTY_FUNCTION, long(timeout ? timeout->count() : -1),
- Communication::ConnectionStatusAsCString(status),
- error.AsCString(), (uint64_t)bytes_read);
+ LLDB_LOGV(log,
+ "Read(buffer, sizeof(buffer), timeout = {0}, "
+ "status = {1}, error = {2}) => bytes_read = {3}",
+ timeout, Communication::ConnectionStatusAsCString(status), error,
+ bytes_read);
if (bytes_read > 0) {
if (CheckForPacket(buffer, bytes_read, packet) != PacketType::Invalid)
@@ -607,10 +605,10 @@ bool GDBRemoteCommunication::DecompressPacket() {
m_compression_type == CompressionType::LZFSE ||
m_compression_type == CompressionType::LZ4)) {
compression_algorithm compression_type;
- if (m_compression_type == CompressionType::ZlibDeflate)
- compression_type = COMPRESSION_ZLIB;
- else if (m_compression_type == CompressionType::LZFSE)
+ if (m_compression_type == CompressionType::LZFSE)
compression_type = COMPRESSION_LZFSE;
+ else if (m_compression_type == CompressionType::ZlibDeflate)
+ compression_type = COMPRESSION_ZLIB;
else if (m_compression_type == CompressionType::LZ4)
compression_type = COMPRESSION_LZ4_RAW;
else if (m_compression_type == CompressionType::LZMA)
@@ -1085,8 +1083,7 @@ Error GDBRemoteCommunication::StartDebugserverProcess(
// port is null when debug server should listen on domain socket -
// we're not interested in port value but rather waiting for debug server
// to become available.
- if (pass_comm_fd == -1 &&
- ((port != nullptr && *port == 0) || port == nullptr)) {
+ if (pass_comm_fd == -1) {
if (url) {
// Create a temporary file to get the stdout/stderr and redirect the
// output of the command into this file. We will later read this file
@@ -1258,11 +1255,21 @@ Error GDBRemoteCommunication::StartDebugserverProcess(
port_cstr, num_bytes, std::chrono::seconds{10}, num_bytes);
if (error.Success() && (port != nullptr)) {
assert(num_bytes > 0 && port_cstr[num_bytes - 1] == '\0');
- *port = StringConvert::ToUInt32(port_cstr, 0);
- if (log)
- log->Printf("GDBRemoteCommunication::%s() "
- "debugserver listens %u port",
- __FUNCTION__, *port);
+ uint16_t child_port = StringConvert::ToUInt32(port_cstr, 0);
+ if (*port == 0 || *port == child_port) {
+ *port = child_port;
+ if (log)
+ log->Printf("GDBRemoteCommunication::%s() "
+ "debugserver listens %u port",
+ __FUNCTION__, *port);
+ } else {
+ if (log)
+ log->Printf("GDBRemoteCommunication::%s() "
+ "debugserver listening on port "
+ "%d but requested port was %d",
+ __FUNCTION__, (uint32_t)child_port,
+ (uint32_t)(*port));
+ }
} else {
if (log)
log->Printf("GDBRemoteCommunication::%s() "
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index b70f0903dbd5..2e94fa94331d 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -18,21 +18,20 @@
#include <sstream>
// Other libraries and framework includes
-#include "lldb/Core/DataBufferHeap.h"
-#include "lldb/Core/Log.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/State.h"
-#include "lldb/Core/StreamGDBRemote.h"
-#include "lldb/Core/StreamString.h"
#include "lldb/Host/HostInfo.h"
-#include "lldb/Host/StringConvert.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/UnixSignals.h"
+#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/JSON.h"
#include "lldb/Utility/LLDBAssert.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/StreamGDBRemote.h"
+#include "lldb/Utility/StreamString.h"
// Project includes
#include "ProcessGDBRemote.h"
@@ -87,6 +86,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient()
m_supports_jThreadExtendedInfo(eLazyBoolCalculate),
m_supports_jLoadedDynamicLibrariesInfos(eLazyBoolCalculate),
m_supports_jGetSharedCacheInfo(eLazyBoolCalculate),
+ m_supports_QPassSignals(eLazyBoolCalculate),
m_supports_qProcessInfoPID(true), m_supports_qfProcessInfo(true),
m_supports_qUserName(true), m_supports_qGroupName(true),
m_supports_qThreadStopInfo(true), m_supports_z0(true),
@@ -150,6 +150,13 @@ bool GDBRemoteCommunicationClient::GetEchoSupported() {
return m_supports_qEcho == eLazyBoolYes;
}
+bool GDBRemoteCommunicationClient::GetQPassSignalsSupported() {
+ if (m_supports_QPassSignals == eLazyBoolCalculate) {
+ GetRemoteQSupported();
+ }
+ return m_supports_QPassSignals == eLazyBoolYes;
+}
+
bool GDBRemoteCommunicationClient::GetAugmentedLibrariesSVR4ReadSupported() {
if (m_supports_augmented_libraries_svr4_read == eLazyBoolCalculate) {
GetRemoteQSupported();
@@ -419,6 +426,11 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() {
else
m_supports_qEcho = eLazyBoolNo;
+ if (::strstr(response_cstr, "QPassSignals+"))
+ m_supports_QPassSignals = eLazyBoolYes;
+ else
+ m_supports_QPassSignals = eLazyBoolNo;
+
const char *packet_size_str = ::strstr(response_cstr, "PacketSize=");
if (packet_size_str) {
StringExtractorGDBRemote packet_response(packet_size_str +
@@ -1491,13 +1503,18 @@ Error GDBRemoteCommunicationClient::GetMemoryRegionInfo(
}
}
- // We got a valid address range back but no permissions -- which means
- // this is an unmapped page
- if (region_info.GetRange().IsValid() && saw_permissions == false) {
- region_info.SetReadable(MemoryRegionInfo::eNo);
- region_info.SetWritable(MemoryRegionInfo::eNo);
- region_info.SetExecutable(MemoryRegionInfo::eNo);
- region_info.SetMapped(MemoryRegionInfo::eNo);
+ if (region_info.GetRange().IsValid()) {
+ // We got a valid address range back but no permissions -- which means
+ // this is an unmapped page
+ if (!saw_permissions) {
+ region_info.SetReadable(MemoryRegionInfo::eNo);
+ region_info.SetWritable(MemoryRegionInfo::eNo);
+ region_info.SetExecutable(MemoryRegionInfo::eNo);
+ region_info.SetMapped(MemoryRegionInfo::eNo);
+ }
+ } else {
+ // We got an invalid address range back
+ error.SetErrorString("Server returned invalid range");
}
} else {
m_supports_memory_region_info = eLazyBoolNo;
@@ -1660,7 +1677,7 @@ bool GDBRemoteCommunicationClient::GetWorkingDir(FileSpec &working_dir) {
return false;
std::string cwd;
response.GetHexByteString(cwd);
- working_dir.SetFile(cwd, false, GetHostArchitecture());
+ working_dir.SetFile(cwd, false, GetHostArchitecture().GetTriple());
return !cwd.empty();
}
return false;
@@ -1907,6 +1924,7 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) {
llvm::Triple triple(llvm::Twine("-") + vendor_name + "-" + os_name);
assert(triple.getObjectFormat() != llvm::Triple::UnknownObjectFormat);
+ assert(triple.getObjectFormat() != llvm::Triple::Wasm);
switch (triple.getObjectFormat()) {
case llvm::Triple::MachO:
m_process_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
@@ -1917,6 +1935,10 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) {
case llvm::Triple::COFF:
m_process_arch.SetArchitecture(eArchTypeCOFF, cpu, sub);
break;
+ case llvm::Triple::Wasm:
+ if (log)
+ log->Printf("error: not supported target architecture");
+ return false;
case llvm::Triple::UnknownObjectFormat:
if (log)
log->Printf("error: failed to determine target architecture");
@@ -1957,29 +1979,29 @@ uint32_t GDBRemoteCommunicationClient::FindProcesses(
bool has_name_match = false;
if (name && name[0]) {
has_name_match = true;
- NameMatchType name_match_type = match_info.GetNameMatchType();
+ NameMatch name_match_type = match_info.GetNameMatchType();
switch (name_match_type) {
- case eNameMatchIgnore:
+ case NameMatch::Ignore:
has_name_match = false;
break;
- case eNameMatchEquals:
+ case NameMatch::Equals:
packet.PutCString("name_match:equals;");
break;
- case eNameMatchContains:
+ case NameMatch::Contains:
packet.PutCString("name_match:contains;");
break;
- case eNameMatchStartsWith:
+ case NameMatch::StartsWith:
packet.PutCString("name_match:starts_with;");
break;
- case eNameMatchEndsWith:
+ case NameMatch::EndsWith:
packet.PutCString("name_match:ends_with;");
break;
- case eNameMatchRegularExpression:
+ case NameMatch::RegularExpression:
packet.PutCString("name_match:regex;");
break;
}
@@ -2190,23 +2212,19 @@ void GDBRemoteCommunicationClient::TestPacketSpeed(const uint32_t num_packets,
const duration<float> standard_deviation =
calculate_standard_deviation(packet_times);
if (json) {
- strm.Printf("%s\n {\"send_size\" : %6" PRIu32
- ", \"recv_size\" : %6" PRIu32
- ", \"total_time_nsec\" : %12" PRIu64
- ", \"standard_deviation_nsec\" : %9" PRIu64 " }",
+ strm.Format("{0}\n {{\"send_size\" : {1,6}, \"recv_size\" : "
+ "{2,6}, \"total_time_nsec\" : {3,12:ns-}, "
+ "\"standard_deviation_nsec\" : {4,9:ns-f0}}",
result_idx > 0 ? "," : "", send_size, recv_size,
- duration_cast<nanoseconds>(total_time).count(),
- duration_cast<nanoseconds>(standard_deviation).count());
+ total_time, standard_deviation);
++result_idx;
} else {
- strm.Printf(
- "qSpeedTest(send=%-7u, recv=%-7u) in %.9f"
- " sec for %9.2f packets/sec (%10.6f ms per packet) with standard "
- "deviation of %10.6f ms\n",
- send_size, recv_size, duration<float>(total_time).count(),
- packets_per_second,
- duration<float, std::milli>(average_per_packet).count(),
- duration<float, std::milli>(standard_deviation).count());
+ strm.Format("qSpeedTest(send={0,7}, recv={1,7}) in {2:s+f9} for "
+ "{3,9:f2} packets/s ({4,10:ms+f6} per packet) with "
+ "standard deviation of {5,10:ms+f6}\n",
+ send_size, recv_size, duration<float>(total_time),
+ packets_per_second, duration<float>(average_per_packet),
+ standard_deviation);
}
strm.Flush();
}
@@ -2249,21 +2267,18 @@ void GDBRemoteCommunicationClient::TestPacketSpeed(const uint32_t num_packets,
const auto average_per_packet = total_time / packet_count;
if (json) {
- strm.Printf("%s\n {\"send_size\" : %6" PRIu32
- ", \"recv_size\" : %6" PRIu32
- ", \"total_time_nsec\" : %12" PRIu64 " }",
+ strm.Format("{0}\n {{\"send_size\" : {1,6}, \"recv_size\" : "
+ "{2,6}, \"total_time_nsec\" : {3,12:ns-}}",
result_idx > 0 ? "," : "", send_size, recv_size,
- duration_cast<nanoseconds>(total_time).count());
+ total_time);
++result_idx;
} else {
- strm.Printf("qSpeedTest(send=%-7u, recv=%-7u) %6u packets needed to "
- "receive %2.1fMB in %.9f"
- " sec for %f MB/sec for %9.2f packets/sec (%10.6f ms per "
- "packet)\n",
+ strm.Format("qSpeedTest(send={0,7}, recv={1,7}) {2,6} packets needed "
+ "to receive {3:f1}MB in {4:s+f9} for {5} MB/sec for "
+ "{6,9:f2} packets/sec ({7,10:ms+f6} per packet)\n",
send_size, recv_size, packet_count, k_recv_amount_mb,
- duration<float>(total_time).count(), mb_second,
- packets_per_second,
- duration<float, std::milli>(average_per_packet).count());
+ duration<float>(total_time), mb_second,
+ packets_per_second, duration<float>(average_per_packet));
}
strm.Flush();
}
@@ -3193,7 +3208,7 @@ bool GDBRemoteCommunicationClient::GetModuleInfo(
StringExtractor extractor(value);
std::string path;
extractor.GetHexByteString(path);
- module_spec.GetFileSpec() = FileSpec(path, false, arch_spec);
+ module_spec.GetFileSpec() = FileSpec(path, false, arch_spec.GetTriple());
}
}
@@ -3227,7 +3242,8 @@ ParseModuleSpec(StructuredData::Dictionary *dict) {
if (!dict->GetValueForKeyAsString("file_path", string))
return llvm::None;
- result.GetFileSpec() = FileSpec(string, false, result.GetArchitecture());
+ result.GetFileSpec() =
+ FileSpec(string, false, result.GetArchitecture().GetTriple());
return result;
}
@@ -3254,6 +3270,9 @@ GDBRemoteCommunicationClient::GetModulesInfo(
payload.PutEscapedBytes(unescaped_payload.GetString().data(),
unescaped_payload.GetSize());
+ // Increase the timeout for jModulesInfo since this packet can take longer.
+ ScopedTimeout timeout(*this, std::chrono::seconds(10));
+
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse(payload.GetString(), response, false) !=
PacketResult::Success ||
@@ -3571,6 +3590,26 @@ GDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() {
: nullptr;
}
+Error GDBRemoteCommunicationClient::SendSignalsToIgnore(
+ llvm::ArrayRef<int32_t> signals) {
+ // Format packet:
+ // QPassSignals:<hex_sig1>;<hex_sig2>...;<hex_sigN>
+ auto range = llvm::make_range(signals.begin(), signals.end());
+ std::string packet = formatv("QPassSignals:{0:$[;]@(x-2)}", range).str();
+
+ StringExtractorGDBRemote response;
+ auto send_status = SendPacketAndWaitForResponse(packet, response, false);
+
+ if (send_status != GDBRemoteCommunication::PacketResult::Success)
+ return Error("Sending QPassSignals packet failed");
+
+ if (response.IsOKResponse()) {
+ return Error();
+ } else {
+ return Error("Unknown error happened during sending QPassSignals packet.");
+ }
+}
+
Error GDBRemoteCommunicationClient::ConfigureRemoteStructuredData(
const ConstString &type_name, const StructuredData::ObjectSP &config_sp) {
Error error;
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index 83162a662e06..63b9708cc9a0 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -347,6 +347,8 @@ public:
bool GetEchoSupported();
+ bool GetQPassSignalsSupported();
+
bool GetAugmentedLibrariesSVR4ReadSupported();
bool GetQXferFeaturesReadSupported();
@@ -450,6 +452,9 @@ public:
void ServeSymbolLookups(lldb_private::Process *process);
+ // Sends QPassSignals packet to the server with given signals to ignore.
+ Error SendSignalsToIgnore(llvm::ArrayRef<int32_t> signals);
+
//------------------------------------------------------------------
/// Return the feature set supported by the gdb-remote server.
///
@@ -527,6 +532,7 @@ protected:
LazyBool m_supports_jThreadExtendedInfo;
LazyBool m_supports_jLoadedDynamicLibrariesInfos;
LazyBool m_supports_jGetSharedCacheInfo;
+ LazyBool m_supports_QPassSignals;
bool m_supports_qProcessInfoPID : 1, m_supports_qfProcessInfo : 1,
m_supports_qUserName : 1, m_supports_qGroupName : 1,
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
index e4e6810f665c..66c1b15ff857 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -22,23 +22,22 @@
#include <cstring>
// Other libraries and framework includes
-#include "lldb/Core/Log.h"
#include "lldb/Core/ModuleSpec.h"
-#include "lldb/Core/StreamGDBRemote.h"
-#include "lldb/Core/StreamString.h"
#include "lldb/Host/Config.h"
-#include "lldb/Host/Endian.h"
#include "lldb/Host/File.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
-#include "lldb/Host/StringConvert.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/FileAction.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
+#include "lldb/Utility/Endian.h"
#include "lldb/Utility/JSON.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/StreamGDBRemote.h"
+#include "lldb/Utility/StreamString.h"
#include "llvm/ADT/Triple.h"
// Project includes
@@ -360,16 +359,15 @@ GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo(
extractor.GetHexByteString(file);
match_info.GetProcessInfo().GetExecutableFile().SetFile(file, false);
} else if (key.equals("name_match")) {
- NameMatchType name_match =
- llvm::StringSwitch<NameMatchType>(value)
- .Case("equals", eNameMatchEquals)
- .Case("starts_with", eNameMatchStartsWith)
- .Case("ends_with", eNameMatchEndsWith)
- .Case("contains", eNameMatchContains)
- .Case("regex", eNameMatchRegularExpression)
- .Default(eNameMatchIgnore);
+ NameMatch name_match = llvm::StringSwitch<NameMatch>(value)
+ .Case("equals", NameMatch::Equals)
+ .Case("starts_with", NameMatch::StartsWith)
+ .Case("ends_with", NameMatch::EndsWith)
+ .Case("contains", NameMatch::Contains)
+ .Case("regex", NameMatch::RegularExpression)
+ .Default(NameMatch::Ignore);
match_info.SetNameMatchType(name_match);
- if (name_match == eNameMatchIgnore)
+ if (name_match == NameMatch::Ignore)
return SendErrorResponse(2);
} else if (key.equals("pid")) {
lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
@@ -643,14 +641,15 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_Size(
std::string path;
packet.GetHexByteString(path);
if (!path.empty()) {
- lldb::user_id_t retcode = FileSystem::GetFileSize(FileSpec(path, false));
+ uint64_t Size;
+ if (llvm::sys::fs::file_size(path, Size))
+ return SendErrorResponse(5);
StreamString response;
response.PutChar('F');
- response.PutHex64(retcode);
- if (retcode == UINT64_MAX) {
+ response.PutHex64(Size);
+ if (Size == UINT64_MAX) {
response.PutChar(',');
- response.PutHex64(
- retcode); // TODO: replace with Host::GetSyswideErrorCode()
+ response.PutHex64(Size); // TODO: replace with Host::GetSyswideErrorCode()
}
return SendPacketNoLock(response.GetString());
}
@@ -682,7 +681,7 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_Exists(
std::string path;
packet.GetHexByteString(path);
if (!path.empty()) {
- bool retcode = FileSystem::GetFileExists(FileSpec(path, false));
+ bool retcode = llvm::sys::fs::exists(path);
StreamString response;
response.PutChar('F');
response.PutChar(',');
@@ -715,7 +714,7 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_unlink(
packet.SetFilePos(::strlen("vFile:unlink:"));
std::string path;
packet.GetHexByteString(path);
- Error error = FileSystem::Unlink(FileSpec{path, true});
+ Error error(llvm::sys::fs::remove(path));
StreamString response;
response.Printf("F%u,%u", error.GetError(), error.GetError());
return SendPacketNoLock(response.GetString());
@@ -772,15 +771,15 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_MD5(
std::string path;
packet.GetHexByteString(path);
if (!path.empty()) {
- uint64_t a, b;
StreamGDBRemote response;
- if (!FileSystem::CalculateMD5(FileSpec(path, false), a, b)) {
+ auto Result = llvm::sys::fs::md5_contents(path);
+ if (!Result) {
response.PutCString("F,");
response.PutCString("x");
} else {
response.PutCString("F,");
- response.PutHex64(a);
- response.PutHex64(b);
+ response.PutHex64(Result->low());
+ response.PutHex64(Result->high());
}
return SendPacketNoLock(response.GetString());
}
@@ -795,7 +794,7 @@ GDBRemoteCommunicationServerCommon::Handle_qPlatform_mkdir(
if (packet.GetChar() == ',') {
std::string path;
packet.GetHexByteString(path);
- Error error = FileSystem::MakeDirectory(FileSpec{path, false}, mode);
+ Error error(llvm::sys::fs::create_directory(path, mode));
StreamGDBRemote response;
response.Printf("F%u", error.GetError());
@@ -810,11 +809,12 @@ GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod(
StringExtractorGDBRemote &packet) {
packet.SetFilePos(::strlen("qPlatform_chmod:"));
- mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
+ auto perms =
+ static_cast<llvm::sys::fs::perms>(packet.GetHexMaxU32(false, UINT32_MAX));
if (packet.GetChar() == ',') {
std::string path;
packet.GetHexByteString(path);
- Error error = FileSystem::SetFilePermissions(FileSpec{path, true}, mode);
+ Error error(llvm::sys::fs::setPermissions(path, perms));
StreamGDBRemote response;
response.Printf("F%u", error.GetError());
@@ -838,7 +838,8 @@ GDBRemoteCommunicationServerCommon::Handle_qSupported(
response.PutCString(";QThreadSuffixSupported+");
response.PutCString(";QListThreadsInStopReply+");
response.PutCString(";qEcho+");
-#if defined(__linux__)
+#if defined(__linux__) || defined(__NetBSD__)
+ response.PutCString(";QPassSignals+");
response.PutCString(";qXfer:auxv:read+");
#endif
@@ -1091,12 +1092,11 @@ GDBRemoteCommunicationServerCommon::Handle_qModuleInfo(
StreamGDBRemote response;
if (uuid_str.empty()) {
- std::string md5_hash;
- if (!FileSystem::CalculateMD5AsString(matched_module_spec.GetFileSpec(),
- file_offset, file_size, md5_hash))
+ auto Result = llvm::sys::fs::md5_contents(matched_module_spec.GetFileSpec().GetPath());
+ if (!Result)
return SendErrorResponse(5);
response.PutCString("md5:");
- response.PutCStringAsRawHex8(md5_hash.c_str());
+ response.PutCStringAsRawHex8(Result->digest().c_str());
} else {
response.PutCString("uuid:");
response.PutCStringAsRawHex8(uuid_str.c_str());
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index bf72673f1769..290889ec662a 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -12,7 +12,7 @@
#include "lldb/Host/Config.h"
#include "GDBRemoteCommunicationServerLLGS.h"
-#include "lldb/Core/StreamGDBRemote.h"
+#include "lldb/Utility/StreamGDBRemote.h"
// C Includes
// C++ Includes
@@ -21,27 +21,27 @@
#include <thread>
// Other libraries and framework includes
-#include "lldb/Core/DataBuffer.h"
-#include "lldb/Core/Log.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/State.h"
-#include "lldb/Core/StreamString.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/Debug.h"
-#include "lldb/Host/Endian.h"
#include "lldb/Host/File.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
-#include "lldb/Host/StringConvert.h"
#include "lldb/Host/common/NativeProcessProtocol.h"
#include "lldb/Host/common/NativeRegisterContext.h"
#include "lldb/Host/common/NativeThreadProtocol.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Target/FileAction.h"
#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Utility/DataBuffer.h"
+#include "lldb/Utility/Endian.h"
#include "lldb/Utility/JSON.h"
#include "lldb/Utility/LLDBAssert.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/StreamString.h"
+#include "lldb/Utility/UriParser.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/ScopedPrinter.h"
@@ -49,7 +49,6 @@
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
#include "Utility/StringExtractorGDBRemote.h"
-#include "Utility/UriParser.h"
using namespace lldb;
using namespace lldb_private;
@@ -81,7 +80,6 @@ GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS(
m_continue_tid(LLDB_INVALID_THREAD_ID), m_debugged_process_mutex(),
m_debugged_process_sp(), m_stdio_communication("process.stdio"),
m_inferior_prev_state(StateType::eStateInvalid),
- m_active_auxv_buffer_sp(), m_saved_registers_mutex(),
m_saved_registers_map(), m_next_saved_registers_id(1),
m_handshake_completed(false) {
RegisterPacketHandlers();
@@ -181,6 +179,9 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() {
&GDBRemoteCommunicationServerLLGS::Handle_Z);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_z,
&GDBRemoteCommunicationServerLLGS::Handle_z);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QPassSignals,
+ &GDBRemoteCommunicationServerLLGS::Handle_QPassSignals);
RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k,
[this](StringExtractorGDBRemote packet, Error &error,
@@ -415,7 +416,8 @@ static void AppendHexValue(StreamString &response, const uint8_t *buf,
static void WriteRegisterValueInHexFixedWidth(
StreamString &response, NativeRegisterContextSP &reg_ctx_sp,
- const RegisterInfo &reg_info, const RegisterValue *reg_value_p) {
+ const RegisterInfo &reg_info, const RegisterValue *reg_value_p,
+ lldb::ByteOrder byte_order) {
RegisterValue reg_value;
if (!reg_value_p) {
Error error = reg_ctx_sp->ReadRegister(&reg_info, reg_value);
@@ -426,7 +428,8 @@ static void WriteRegisterValueInHexFixedWidth(
if (reg_value_p) {
AppendHexValue(response, (const uint8_t *)reg_value_p->GetBytes(),
- reg_value_p->GetByteSize(), false);
+ reg_value_p->GetByteSize(),
+ byte_order == lldb::eByteOrderLittle);
} else {
// Zero-out any unreadable values.
if (reg_info.byte_size > 0) {
@@ -436,8 +439,7 @@ static void WriteRegisterValueInHexFixedWidth(
}
}
-static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread,
- bool abridged) {
+static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
NativeRegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
@@ -462,11 +464,8 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread,
static const uint32_t k_expedited_registers[] = {
LLDB_REGNUM_GENERIC_PC, LLDB_REGNUM_GENERIC_SP, LLDB_REGNUM_GENERIC_FP,
LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM};
- static const uint32_t k_abridged_expedited_registers[] = {
- LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM};
- for (const uint32_t *generic_reg_p = abridged ? k_abridged_expedited_registers
- : k_expedited_registers;
+ for (const uint32_t *generic_reg_p = k_expedited_registers;
*generic_reg_p != LLDB_INVALID_REGNUM; ++generic_reg_p) {
uint32_t reg_num = reg_ctx_sp->ConvertRegisterKindToRegisterNumber(
eRegisterKindGeneric, *generic_reg_p);
@@ -501,7 +500,7 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread,
StreamString stream;
WriteRegisterValueInHexFixedWidth(stream, reg_ctx_sp, *reg_info_p,
- &reg_value);
+ &reg_value, lldb::eByteOrderBig);
register_object_sp->SetObject(
llvm::to_string(reg_num),
@@ -567,8 +566,10 @@ static JSONArray::SP GetJSONThreadsInfo(NativeProcessProtocol &process,
JSONObject::SP thread_obj_sp = std::make_shared<JSONObject>();
threads_array_sp->AppendObject(thread_obj_sp);
- if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread_sp, abridged))
- thread_obj_sp->SetObject("registers", registers_sp);
+ if (!abridged) {
+ if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread_sp))
+ thread_obj_sp->SetObject("registers", registers_sp);
+ }
thread_obj_sp->SetObject("tid", std::make_shared<JSONNumber>(tid));
if (signum != 0)
@@ -721,6 +722,41 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
"jstopinfo field for pid %" PRIu64,
__FUNCTION__, m_debugged_process_sp->GetID());
}
+
+ uint32_t i = 0;
+ response.PutCString("thread-pcs");
+ char delimiter = ':';
+ for (NativeThreadProtocolSP thread_sp;
+ (thread_sp = m_debugged_process_sp->GetThreadAtIndex(i)) != nullptr;
+ ++i) {
+ NativeRegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext();
+ if (!reg_ctx_sp)
+ continue;
+
+ uint32_t reg_to_read = reg_ctx_sp->ConvertRegisterKindToRegisterNumber(
+ eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ const RegisterInfo *const reg_info_p =
+ reg_ctx_sp->GetRegisterInfoAtIndex(reg_to_read);
+
+ RegisterValue reg_value;
+ Error error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("%s failed to read register '%s' index %" PRIu32 ": %s",
+ __FUNCTION__,
+ reg_info_p->name ? reg_info_p->name
+ : "<unnamed-register>",
+ reg_to_read, error.AsCString());
+ continue;
+ }
+
+ response.PutChar(delimiter);
+ delimiter = ',';
+ WriteRegisterValueInHexFixedWidth(response, reg_ctx_sp, *reg_info_p,
+ &reg_value, endian::InlHostByteOrder());
+ }
+
+ response.PutChar(';');
}
//
@@ -761,7 +797,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
if (error.Success()) {
response.Printf("%.02x:", *reg_num_p);
WriteRegisterValueInHexFixedWidth(response, reg_ctx_sp, *reg_info_p,
- &reg_value);
+ &reg_value, lldb::eByteOrderBig);
response.PutChar(';');
} else {
if (log)
@@ -2496,12 +2532,14 @@ GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
packet, "Too short z packet, missing software/hardware specifier");
bool want_breakpoint = true;
+ bool want_hardware = false;
const GDBStoppointType stoppoint_type =
GDBStoppointType(packet.GetS32(eStoppointInvalid));
switch (stoppoint_type) {
case eBreakpointHardware:
want_breakpoint = true;
+ want_hardware = true;
break;
case eBreakpointSoftware:
want_breakpoint = true;
@@ -2544,7 +2582,8 @@ GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
if (want_breakpoint) {
// Try to clear the breakpoint.
- const Error error = m_debugged_process_sp->RemoveBreakpoint(addr);
+ const Error error =
+ m_debugged_process_sp->RemoveBreakpoint(addr, want_hardware);
if (error.Success())
return SendOKResponse();
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
@@ -2625,7 +2664,7 @@ GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qXfer_auxv_read(
StringExtractorGDBRemote &packet) {
// *BSD impls should be able to do this too.
-#if defined(__linux__)
+#if defined(__linux__) || defined(__NetBSD__)
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
// Parse out the offset.
@@ -2653,7 +2692,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qXfer_auxv_read(
"qXfer:auxv:read:: packet missing length");
// Grab the auxv data if we need it.
- if (!m_active_auxv_buffer_sp) {
+ if (!m_active_auxv_buffer_up) {
// Make sure we have a valid process.
if (!m_debugged_process_sp ||
(m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
@@ -2665,55 +2704,45 @@ GDBRemoteCommunicationServerLLGS::Handle_qXfer_auxv_read(
}
// Grab the auxv data.
- m_active_auxv_buffer_sp = Host::GetAuxvData(m_debugged_process_sp->GetID());
- if (!m_active_auxv_buffer_sp ||
- m_active_auxv_buffer_sp->GetByteSize() == 0) {
- // Hmm, no auxv data, call that an error.
- if (log)
- log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, no auxv data "
- "retrieved",
- __FUNCTION__);
- m_active_auxv_buffer_sp.reset();
- return SendErrorResponse(0x11);
+ auto buffer_or_error = m_debugged_process_sp->GetAuxvData();
+ if (!buffer_or_error) {
+ std::error_code ec = buffer_or_error.getError();
+ LLDB_LOG(log, "no auxv data retrieved: {0}", ec.message());
+ return SendErrorResponse(ec.value());
}
+ m_active_auxv_buffer_up = std::move(*buffer_or_error);
}
- // FIXME find out if/how I lock the stream here.
-
StreamGDBRemote response;
bool done_with_buffer = false;
- if (auxv_offset >= m_active_auxv_buffer_sp->GetByteSize()) {
+ llvm::StringRef buffer = m_active_auxv_buffer_up->getBuffer();
+ if (auxv_offset >= buffer.size()) {
// We have nothing left to send. Mark the buffer as complete.
response.PutChar('l');
done_with_buffer = true;
} else {
// Figure out how many bytes are available starting at the given offset.
- const uint64_t bytes_remaining =
- m_active_auxv_buffer_sp->GetByteSize() - auxv_offset;
-
- // Figure out how many bytes we're going to read.
- const uint64_t bytes_to_read =
- (auxv_length > bytes_remaining) ? bytes_remaining : auxv_length;
+ buffer = buffer.drop_front(auxv_offset);
// Mark the response type according to whether we're reading the remainder
// of the auxv data.
- if (bytes_to_read >= bytes_remaining) {
+ if (auxv_length >= buffer.size()) {
// There will be nothing left to read after this
response.PutChar('l');
done_with_buffer = true;
} else {
// There will still be bytes to read after this request.
response.PutChar('m');
+ buffer = buffer.take_front(auxv_length);
}
// Now write the data in encoded binary form.
- response.PutEscapedBytes(m_active_auxv_buffer_sp->GetBytes() + auxv_offset,
- bytes_to_read);
+ response.PutEscapedBytes(buffer.data(), buffer.size());
}
if (done_with_buffer)
- m_active_auxv_buffer_sp.reset();
+ m_active_auxv_buffer_up.reset();
return SendPacketNoLock(response.GetString());
#else
@@ -3002,9 +3031,14 @@ GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo(
if (packet.GetChar() != ':')
return SendErrorResponse(67);
- uint32_t num = m_debugged_process_sp->GetMaxWatchpoints();
+ auto hw_debug_cap = m_debugged_process_sp->GetHardwareDebugSupportInfo();
+
StreamGDBRemote response;
- response.Printf("num:%d;", num);
+ if (hw_debug_cap == llvm::None)
+ response.Printf("num:0;");
+ else
+ response.Printf("num:%d;", hw_debug_cap->second);
+
return SendPacketNoLock(response.GetString());
}
@@ -3037,6 +3071,40 @@ GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress(
return SendPacketNoLock(response.GetString());
}
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_QPassSignals(
+ StringExtractorGDBRemote &packet) {
+ std::vector<int> signals;
+ packet.SetFilePos(strlen("QPassSignals:"));
+
+ // Read sequence of hex signal numbers divided by a semicolon and
+ // optionally spaces.
+ while (packet.GetBytesLeft() > 0) {
+ int signal = packet.GetS32(-1, 16);
+ if (signal < 0)
+ return SendIllFormedResponse(packet, "Failed to parse signal number.");
+ signals.push_back(signal);
+
+ packet.SkipSpaces();
+ char separator = packet.GetChar();
+ if (separator == '\0')
+ break; // End of string
+ if (separator != ';')
+ return SendIllFormedResponse(packet, "Invalid separator,"
+ " expected semicolon.");
+ }
+
+ // Fail if we don't have a current process.
+ if (!m_debugged_process_sp)
+ return SendErrorResponse(68);
+
+ Error error = m_debugged_process_sp->IgnoreSignals(signals);
+ if (error.Fail())
+ return SendErrorResponse(69);
+
+ return SendOKResponse();
+}
+
void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
@@ -3136,20 +3204,10 @@ uint32_t GDBRemoteCommunicationServerLLGS::GetNextSavedRegistersID() {
}
void GDBRemoteCommunicationServerLLGS::ClearProcessSpecificData() {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | GDBR_LOG_PROCESS));
- if (log)
- log->Printf("GDBRemoteCommunicationServerLLGS::%s()", __FUNCTION__);
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
-// Clear any auxv cached data.
-// *BSD impls should be able to do this too.
-#if defined(__linux__)
- if (log)
- log->Printf("GDBRemoteCommunicationServerLLGS::%s clearing auxv buffer "
- "(previously %s)",
- __FUNCTION__,
- m_active_auxv_buffer_sp ? "was set" : "was not set");
- m_active_auxv_buffer_sp.reset();
-#endif
+ LLDB_LOG(log, "clearing auxv buffer: {0}", m_active_auxv_buffer_up.get());
+ m_active_auxv_buffer_up.reset();
}
FileSpec
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
index fa52cdaab493..a47927e1c640 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
@@ -117,7 +117,7 @@ protected:
MainLoop::ReadHandleUP m_stdio_handle_up;
lldb::StateType m_inferior_prev_state;
- lldb::DataBufferSP m_active_auxv_buffer_sp;
+ std::unique_ptr<llvm::MemoryBuffer> m_active_auxv_buffer_up;
std::mutex m_saved_registers_mutex;
std::unordered_map<uint32_t, lldb::DataBufferSP> m_saved_registers_map;
uint32_t m_next_saved_registers_id;
@@ -203,6 +203,8 @@ protected:
PacketResult Handle_qFileLoadAddress(StringExtractorGDBRemote &packet);
+ PacketResult Handle_QPassSignals(StringExtractorGDBRemote &packet);
+
void SetCurrentThreadID(lldb::tid_t tid);
lldb::tid_t GetCurrentThreadID() const;
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
index 11069749186a..ae1c1adb5b45 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
@@ -20,25 +20,25 @@
// Other libraries and framework includes
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Threading.h"
-#include "lldb/Core/Log.h"
-#include "lldb/Core/StreamGDBRemote.h"
-#include "lldb/Core/StreamString.h"
#include "lldb/Core/StructuredData.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
-#include "lldb/Host/StringConvert.h"
#include "lldb/Target/FileAction.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Utility/JSON.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/StreamGDBRemote.h"
+#include "lldb/Utility/StreamString.h"
+#include "lldb/Utility/UriParser.h"
// Project includes
#include "Utility/StringExtractorGDBRemote.h"
-#include "Utility/UriParser.h"
using namespace lldb;
using namespace lldb_private;
@@ -82,8 +82,8 @@ GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(
&GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo);
RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt,
- [this](StringExtractorGDBRemote packet, Error &error,
- bool &interrupt, bool &quit) {
+ [](StringExtractorGDBRemote packet, Error &error,
+ bool &interrupt, bool &quit) {
error.SetErrorString("interrupt received");
interrupt = true;
return PacketResult::Success;
@@ -353,15 +353,13 @@ GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir(
StringExtractorGDBRemote &packet) {
- // If this packet is sent to a platform, then change the current working
- // directory
- char cwd[PATH_MAX];
- if (getcwd(cwd, sizeof(cwd)) == NULL)
- return SendErrorResponse(errno);
+ llvm::SmallString<64> cwd;
+ if (std::error_code ec = llvm::sys::fs::current_path(cwd))
+ return SendErrorResponse(ec.value());
StreamString response;
- response.PutBytesAsRawHex8(cwd, strlen(cwd));
+ response.PutBytesAsRawHex8(cwd.data(), cwd.size());
return SendPacketNoLock(response.GetString());
}
@@ -372,10 +370,8 @@ GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir(
std::string path;
packet.GetHexByteString(path);
- // If this packet is sent to a platform, then change the current working
- // directory
- if (::chdir(path.c_str()) != 0)
- return SendErrorResponse(errno);
+ if (std::error_code ec = llvm::sys::fs::set_current_path(path))
+ return SendErrorResponse(ec.value());
return SendOKResponse();
}
@@ -532,9 +528,9 @@ bool GDBRemoteCommunicationServerPlatform::FreePortForProcess(lldb::pid_t pid) {
const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() {
static FileSpec g_domainsocket_dir;
- static std::once_flag g_once_flag;
+ static llvm::once_flag g_once_flag;
- std::call_once(g_once_flag, []() {
+ llvm::call_once(g_once_flag, []() {
const char *domainsocket_dir_env =
::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
if (domainsocket_dir_env != nullptr)
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index 27ce67ded783..ea4acc74893a 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -12,14 +12,13 @@
// C Includes
// C++ Includes
// Other libraries and framework includes
-#include "lldb/Core/DataBufferHeap.h"
-#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
-#include "lldb/Core/StreamString.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Target.h"
-#include "lldb/Utility/Utils.h"
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/StreamString.h"
// Project includes
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
index 5b3e04eb588e..8ef91af55e0f 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -17,9 +17,9 @@
// Other libraries and framework includes
// Project includes
#include "Plugins/Process/Utility/DynamicRegisterInfo.h"
-#include "lldb/Core/ConstString.h"
-#include "lldb/Core/DataExtractor.h"
#include "lldb/Target/RegisterContext.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/DataExtractor.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index fac52901e763..c4ae5e36d9ad 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -35,14 +35,13 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
-#include "lldb/Core/StreamString.h"
#include "lldb/Core/Timer.h"
#include "lldb/Core/Value.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
-#include "lldb/Host/FileSpec.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostThread.h"
+#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Host/Symbols.h"
#include "lldb/Host/ThreadLauncher.h"
@@ -65,7 +64,8 @@
#include "lldb/Target/TargetList.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
#include "lldb/Utility/CleanUp.h"
-#include "lldb/Utility/PseudoTerminal.h"
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/StreamString.h"
// Project includes
#include "GDBRemoteRegisterContext.h"
@@ -80,6 +80,7 @@
#include "lldb/Host/Host.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Threading.h"
#include "llvm/Support/raw_ostream.h"
#define DEBUGSERVER_BASENAME "debugserver"
@@ -576,7 +577,7 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
uint32_t ret_val =
opcode_extractor.GetHexBytesAvail(dwarf_opcode_bytes);
assert(dwarf_opcode_len == ret_val);
-
+ UNUSED_IF_ASSERT_DISABLED(ret_val);
reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data();
}
}
@@ -1616,9 +1617,7 @@ bool ProcessGDBRemote::UpdateThreadList(ThreadList &old_thread_list,
ThreadList &new_thread_list) {
// locker will keep a mutex locked until it goes out of scope
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_THREAD));
- if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
- log->Printf("ProcessGDBRemote::%s (pid = %" PRIu64 ")", __FUNCTION__,
- GetID());
+ LLDB_LOGV(log, "pid = {0}", GetID());
size_t num_thread_ids = m_thread_ids.size();
// The "m_thread_ids" thread ID list should always be updated after each stop
@@ -1637,39 +1636,14 @@ bool ProcessGDBRemote::UpdateThreadList(ThreadList &old_thread_list,
old_thread_list_copy.RemoveThreadByProtocolID(tid, false));
if (!thread_sp) {
thread_sp.reset(new ThreadGDBRemote(*this, tid));
- if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
- log->Printf("ProcessGDBRemote::%s Making new thread: %p for thread "
- "ID: 0x%" PRIx64 ".\n",
- __FUNCTION__, static_cast<void *>(thread_sp.get()),
- thread_sp->GetID());
+ LLDB_LOGV(log, "Making new thread: {0} for thread ID: {1:x}.",
+ thread_sp.get(), thread_sp->GetID());
} else {
- if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
- log->Printf("ProcessGDBRemote::%s Found old thread: %p for thread "
- "ID: 0x%" PRIx64 ".\n",
- __FUNCTION__, static_cast<void *>(thread_sp.get()),
- thread_sp->GetID());
- }
- // The m_thread_pcs vector has pc values in big-endian order, not
- // target-endian, unlike most
- // of the register read/write packets in gdb-remote protocol.
- // Early in the process startup, we may not yet have set the process
- // ByteOrder so we ignore these;
- // they are a performance improvement over fetching thread register values
- // individually, the
- // method we will fall back to if needed.
- if (m_thread_ids.size() == m_thread_pcs.size() && thread_sp.get() &&
- GetByteOrder() != eByteOrderInvalid) {
- ThreadGDBRemote *gdb_thread =
- static_cast<ThreadGDBRemote *>(thread_sp.get());
- RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext());
- if (reg_ctx_sp) {
- uint32_t pc_regnum = reg_ctx_sp->ConvertRegisterKindToRegisterNumber(
- eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
- if (pc_regnum != LLDB_INVALID_REGNUM) {
- gdb_thread->PrivateSetRegisterValue(pc_regnum, m_thread_pcs[i]);
- }
- }
+ LLDB_LOGV(log, "Found old thread: {0} for thread ID: {1:x}.",
+ thread_sp.get(), thread_sp->GetID());
}
+
+ SetThreadPc(thread_sp, i);
new_thread_list.AddThreadSortedByIndexID(thread_sp);
}
}
@@ -1689,6 +1663,22 @@ bool ProcessGDBRemote::UpdateThreadList(ThreadList &old_thread_list,
return true;
}
+void ProcessGDBRemote::SetThreadPc(const ThreadSP &thread_sp, uint64_t index) {
+ if (m_thread_ids.size() == m_thread_pcs.size() && thread_sp.get() &&
+ GetByteOrder() != eByteOrderInvalid) {
+ ThreadGDBRemote *gdb_thread =
+ static_cast<ThreadGDBRemote *>(thread_sp.get());
+ RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext());
+ if (reg_ctx_sp) {
+ uint32_t pc_regnum = reg_ctx_sp->ConvertRegisterKindToRegisterNumber(
+ eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ if (pc_regnum != LLDB_INVALID_REGNUM) {
+ gdb_thread->PrivateSetRegisterValue(pc_regnum, m_thread_pcs[index]);
+ }
+ }
+ }
+}
+
bool ProcessGDBRemote::GetThreadStopInfoFromJSON(
ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp) {
// See if we got thread stop infos for all threads via the "jThreadsInfo"
@@ -1774,6 +1764,11 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
static_cast<ThreadGDBRemote *>(thread_sp.get());
gdb_thread->GetRegisterContext()->InvalidateIfNeeded(true);
+ auto iter = std::find(m_thread_ids.begin(), m_thread_ids.end(), tid);
+ if (iter != m_thread_ids.end()) {
+ SetThreadPc(thread_sp, iter - m_thread_ids.begin());
+ }
+
for (const auto &pair : expedited_register_map) {
StringExtractor reg_value_extractor;
reg_value_extractor.GetStringRef() = pair.second;
@@ -2729,16 +2724,19 @@ void ProcessGDBRemote::WillPublicStop() {
size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size,
Error &error) {
GetMaxMemorySize();
- if (size > m_max_memory_size) {
+ bool binary_memory_read = m_gdb_comm.GetxPacketSupported();
+ // M and m packets take 2 bytes for 1 byte of memory
+ size_t max_memory_size =
+ binary_memory_read ? m_max_memory_size : m_max_memory_size / 2;
+ if (size > max_memory_size) {
// Keep memory read sizes down to a sane limit. This function will be
// called multiple times in order to complete the task by
// lldb_private::Process so it is ok to do this.
- size = m_max_memory_size;
+ size = max_memory_size;
}
char packet[64];
int packet_len;
- bool binary_memory_read = m_gdb_comm.GetxPacketSupported();
packet_len = ::snprintf(packet, sizeof(packet), "%c%" PRIx64 ",%" PRIx64,
binary_memory_read ? 'x' : 'm', (uint64_t)addr,
(uint64_t)size);
@@ -2785,11 +2783,13 @@ size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size,
size_t ProcessGDBRemote::DoWriteMemory(addr_t addr, const void *buf,
size_t size, Error &error) {
GetMaxMemorySize();
- if (size > m_max_memory_size) {
+ // M and m packets take 2 bytes for 1 byte of memory
+ size_t max_memory_size = m_max_memory_size / 2;
+ if (size > max_memory_size) {
// Keep memory read sizes down to a sane limit. This function will be
// called multiple times in order to complete the task by
// lldb_private::Process so it is ok to do this.
- size = m_max_memory_size;
+ size = max_memory_size;
}
StreamString packet;
@@ -3427,9 +3427,9 @@ void ProcessGDBRemote::KillDebugserverProcess() {
}
void ProcessGDBRemote::Initialize() {
- static std::once_flag g_once_flag;
+ static llvm::once_flag g_once_flag;
- std::call_once(g_once_flag, []() {
+ llvm::call_once(g_once_flag, []() {
PluginManager::RegisterPlugin(GetPluginNameStatic(),
GetPluginDescriptionStatic(), CreateInstance,
DebuggerInitialize);
@@ -3739,6 +3739,43 @@ bool ProcessGDBRemote::NewThreadNotifyBreakpointHit(
return false;
}
+Error ProcessGDBRemote::UpdateAutomaticSignalFiltering() {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ LLDB_LOG(log, "Check if need to update ignored signals");
+
+ // QPassSignals package is not supported by the server,
+ // there is no way we can ignore any signals on server side.
+ if (!m_gdb_comm.GetQPassSignalsSupported())
+ return Error();
+
+ // No signals, nothing to send.
+ if (m_unix_signals_sp == nullptr)
+ return Error();
+
+ // Signals' version hasn't changed, no need to send anything.
+ uint64_t new_signals_version = m_unix_signals_sp->GetVersion();
+ if (new_signals_version == m_last_signals_version) {
+ LLDB_LOG(log, "Signals' version hasn't changed. version={0}",
+ m_last_signals_version);
+ return Error();
+ }
+
+ auto signals_to_ignore =
+ m_unix_signals_sp->GetFilteredSignals(false, false, false);
+ Error error = m_gdb_comm.SendSignalsToIgnore(signals_to_ignore);
+
+ LLDB_LOG(log,
+ "Signals' version changed. old version={0}, new version={1}, "
+ "signals ignored={2}, update result={3}",
+ m_last_signals_version, new_signals_version,
+ signals_to_ignore.size(), error);
+
+ if (error.Success())
+ m_last_signals_version = new_signals_version;
+
+ return error;
+}
+
bool ProcessGDBRemote::StartNoticingNewThreads() {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
if (m_thread_create_bp_sp) {
@@ -3988,6 +4025,21 @@ void ProcessGDBRemote::GetMaxMemorySize() {
stub_max_size = reasonable_largeish_default;
}
+ // Memory packet have other overheads too like Maddr,size:#NN
+ // Instead of calculating the bytes taken by size and addr every
+ // time, we take a maximum guess here.
+ if (stub_max_size > 70)
+ stub_max_size -= 32 + 32 + 6;
+ else {
+ // In unlikely scenario that max packet size is less then 70, we will
+ // hope that data being written is small enough to fit.
+ Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(
+ GDBR_LOG_COMM | GDBR_LOG_MEMORY));
+ if (log)
+ log->Warning("Packet size is too small. "
+ "LLDB may face problems while writing memory");
+ }
+
m_max_memory_size = stub_max_size;
} else {
m_max_memory_size = conservative_default;
@@ -4132,8 +4184,7 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info,
reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type,
&reg_name, &alt_name, &set_name, &value_regs,
&invalidate_regs, &encoding_set, &format_set,
- &reg_info, &cur_reg_num, &reg_offset,
- &dwarf_opcode_bytes](
+ &reg_info, &reg_offset, &dwarf_opcode_bytes](
const llvm::StringRef &name,
const llvm::StringRef &value) -> bool {
if (name == "name") {
@@ -4213,7 +4264,7 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info,
uint32_t ret_val =
opcode_extractor.GetHexBytesAvail(dwarf_opcode_bytes);
assert(dwarf_opcode_len == ret_val);
-
+ UNUSED_IF_ASSERT_DISABLED(ret_val);
reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data();
} else {
printf("unhandled attribute %s = %s\n", name.data(), value.data());
@@ -4295,7 +4346,7 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) {
XMLNode target_node = xml_document.GetRootElement("target");
if (target_node) {
XMLNode feature_node;
- target_node.ForEachChildElement([&target_info, this, &feature_node](
+ target_node.ForEachChildElement([&target_info, &feature_node](
const XMLNode &node) -> bool {
llvm::StringRef name = node.GetName();
if (name == "architecture") {
@@ -4421,8 +4472,8 @@ Error ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) {
LoadedModuleInfoList::LoadedModuleInfo module;
library.ForEachAttribute(
- [log, &module](const llvm::StringRef &name,
- const llvm::StringRef &value) -> bool {
+ [&module](const llvm::StringRef &name,
+ const llvm::StringRef &value) -> bool {
if (name == "name")
module.set_name(value.str());
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 6423abc55836..a1794d0f5050 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -22,18 +22,18 @@
// Project includes
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Broadcaster.h"
-#include "lldb/Core/ConstString.h"
-#include "lldb/Core/Error.h"
#include "lldb/Core/LoadedModuleInfoList.h"
#include "lldb/Core/ModuleSpec.h"
-#include "lldb/Core/StreamString.h"
-#include "lldb/Core/StringList.h"
#include "lldb/Core/StructuredData.h"
#include "lldb/Core/ThreadSafeValue.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/Error.h"
+#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/StringExtractor.h"
+#include "lldb/Utility/StringList.h"
#include "lldb/lldb-private-forward.h"
#include "GDBRemoteCommunicationClient.h"
@@ -397,12 +397,15 @@ protected:
lldb::addr_t base_addr,
bool value_is_offset);
+ Error UpdateAutomaticSignalFiltering() override;
+
private:
//------------------------------------------------------------------
// For ProcessGDBRemote only
//------------------------------------------------------------------
std::string m_partial_profile_data;
std::map<uint64_t, uint32_t> m_thread_id_to_used_usec_map;
+ uint64_t m_last_signals_version = 0;
static bool NewThreadNotifyBreakpointHit(void *baton,
StoppointCallbackContext *context,
@@ -417,6 +420,7 @@ private:
void HandleStopReply() override;
void HandleAsyncStructuredDataPacket(llvm::StringRef data) override;
+ void SetThreadPc(const lldb::ThreadSP &thread_sp, uint64_t index);
using ModuleCacheKey = std::pair<std::string, std::string>;
// KeyInfo for the cached module spec DenseMap.
// The invariant is that all real keys will have the file and architecture
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp
index 899037ae98aa..8f16b83907cf 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp
@@ -8,210 +8,37 @@
//===----------------------------------------------------------------------===//
#include "ProcessGDBRemoteLog.h"
-
-#include <mutex>
-
-#include "lldb/Core/StreamFile.h"
-#include "lldb/Interpreter/Args.h"
-
#include "ProcessGDBRemote.h"
+#include "llvm/Support/Threading.h"
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;
-// We want to avoid global constructors where code needs to be run so here we
-// control access to our static g_log_sp by hiding it in a singleton function
-// that will construct the static g_lob_sp the first time this function is
-// called.
-static bool g_log_enabled = false;
-static Log *g_log = NULL;
-static Log *GetLog() {
- if (!g_log_enabled)
- return NULL;
- return g_log;
-}
+static constexpr Log::Category g_categories[] = {
+ {{"async"}, {"log asynchronous activity"}, GDBR_LOG_ASYNC},
+ {{"break"}, {"log breakpoints"}, GDBR_LOG_BREAKPOINTS},
+ {{"comm"}, {"log communication activity"}, GDBR_LOG_COMM},
+ {{"packets"}, {"log gdb remote packets"}, GDBR_LOG_PACKETS},
+ {{"memory"}, {"log memory reads and writes"}, GDBR_LOG_MEMORY},
+ {{"data-short"},
+ {"log memory bytes for memory reads and writes for short transactions "
+ "only"},
+ GDBR_LOG_MEMORY_DATA_SHORT},
+ {{"data-long"},
+ {"log memory bytes for memory reads and writes for all transactions"},
+ GDBR_LOG_MEMORY_DATA_LONG},
+ {{"process"}, {"log process events and activities"}, GDBR_LOG_PROCESS},
+ {{"step"}, {"log step related activities"}, GDBR_LOG_STEP},
+ {{"thread"}, {"log thread events and activities"}, GDBR_LOG_THREAD},
+ {{"watch"}, {"log watchpoint related activities"}, GDBR_LOG_WATCHPOINTS},
+};
+
+Log::Channel ProcessGDBRemoteLog::g_channel(g_categories, GDBR_LOG_DEFAULT);
void ProcessGDBRemoteLog::Initialize() {
- static ConstString g_name("gdb-remote");
- static std::once_flag g_once_flag;
-
- std::call_once(g_once_flag, []() {
- Log::Callbacks log_callbacks = {DisableLog, EnableLog, ListLogCategories};
-
- Log::RegisterLogChannel(g_name, log_callbacks);
+ static llvm::once_flag g_once_flag;
+ llvm::call_once(g_once_flag, []() {
+ Log::Register("gdb-remote", g_channel);
});
}
-
-Log *ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(uint32_t mask) {
- Log *log(GetLog());
- if (log && mask) {
- uint32_t log_mask = log->GetMask().Get();
- if ((log_mask & mask) != mask)
- return NULL;
- }
- return log;
-}
-
-Log *ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(uint32_t mask) {
- Log *log(GetLog());
- if (log && log->GetMask().Get() & mask)
- return log;
- return NULL;
-}
-
-void ProcessGDBRemoteLog::DisableLog(const char **categories,
- Stream *feedback_strm) {
- Log *log(GetLog());
- if (log) {
- uint32_t flag_bits = 0;
-
- if (categories && categories[0]) {
- flag_bits = log->GetMask().Get();
- for (size_t i = 0; categories[i] != NULL; ++i) {
- const char *arg = categories[i];
-
- if (::strcasecmp(arg, "all") == 0)
- flag_bits &= ~GDBR_LOG_ALL;
- else if (::strcasecmp(arg, "async") == 0)
- flag_bits &= ~GDBR_LOG_ASYNC;
- else if (::strncasecmp(arg, "break", 5) == 0)
- flag_bits &= ~GDBR_LOG_BREAKPOINTS;
- else if (::strncasecmp(arg, "comm", 4) == 0)
- flag_bits &= ~GDBR_LOG_COMM;
- else if (::strcasecmp(arg, "default") == 0)
- flag_bits &= ~GDBR_LOG_DEFAULT;
- else if (::strcasecmp(arg, "packets") == 0)
- flag_bits &= ~GDBR_LOG_PACKETS;
- else if (::strcasecmp(arg, "memory") == 0)
- flag_bits &= ~GDBR_LOG_MEMORY;
- else if (::strcasecmp(arg, "data-short") == 0)
- flag_bits &= ~GDBR_LOG_MEMORY_DATA_SHORT;
- else if (::strcasecmp(arg, "data-long") == 0)
- flag_bits &= ~GDBR_LOG_MEMORY_DATA_LONG;
- else if (::strcasecmp(arg, "process") == 0)
- flag_bits &= ~GDBR_LOG_PROCESS;
- else if (::strcasecmp(arg, "step") == 0)
- flag_bits &= ~GDBR_LOG_STEP;
- else if (::strcasecmp(arg, "thread") == 0)
- flag_bits &= ~GDBR_LOG_THREAD;
- else if (::strcasecmp(arg, "verbose") == 0)
- flag_bits &= ~GDBR_LOG_VERBOSE;
- else if (::strncasecmp(arg, "watch", 5) == 0)
- flag_bits &= ~GDBR_LOG_WATCHPOINTS;
- else {
- feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
- ListLogCategories(feedback_strm);
- }
- }
- }
-
- if (flag_bits == 0)
- g_log_enabled = false;
- else
- log->GetMask().Reset(flag_bits);
- }
-
- return;
-}
-
-Log *ProcessGDBRemoteLog::EnableLog(StreamSP &log_stream_sp,
- uint32_t log_options,
- const char **categories,
- Stream *feedback_strm) {
- // Try see if there already is a log - that way we can reuse its settings.
- // We could reuse the log in toto, but we don't know that the stream is the
- // same.
- uint32_t flag_bits = 0;
- if (g_log)
- flag_bits = g_log->GetMask().Get();
-
- // Now make a new log with this stream if one was provided
- if (log_stream_sp) {
- if (g_log)
- g_log->SetStream(log_stream_sp);
- else
- g_log = new Log(log_stream_sp);
- }
-
- if (g_log) {
- bool got_unknown_category = false;
- for (size_t i = 0; categories[i] != NULL; ++i) {
- const char *arg = categories[i];
-
- if (::strcasecmp(arg, "all") == 0)
- flag_bits |= GDBR_LOG_ALL;
- else if (::strcasecmp(arg, "async") == 0)
- flag_bits |= GDBR_LOG_ASYNC;
- else if (::strncasecmp(arg, "break", 5) == 0)
- flag_bits |= GDBR_LOG_BREAKPOINTS;
- else if (::strncasecmp(arg, "comm", 4) == 0)
- flag_bits |= GDBR_LOG_COMM;
- else if (::strcasecmp(arg, "default") == 0)
- flag_bits |= GDBR_LOG_DEFAULT;
- else if (::strcasecmp(arg, "packets") == 0)
- flag_bits |= GDBR_LOG_PACKETS;
- else if (::strcasecmp(arg, "memory") == 0)
- flag_bits |= GDBR_LOG_MEMORY;
- else if (::strcasecmp(arg, "data-short") == 0)
- flag_bits |= GDBR_LOG_MEMORY_DATA_SHORT;
- else if (::strcasecmp(arg, "data-long") == 0)
- flag_bits |= GDBR_LOG_MEMORY_DATA_LONG;
- else if (::strcasecmp(arg, "process") == 0)
- flag_bits |= GDBR_LOG_PROCESS;
- else if (::strcasecmp(arg, "step") == 0)
- flag_bits |= GDBR_LOG_STEP;
- else if (::strcasecmp(arg, "thread") == 0)
- flag_bits |= GDBR_LOG_THREAD;
- else if (::strcasecmp(arg, "verbose") == 0)
- flag_bits |= GDBR_LOG_VERBOSE;
- else if (::strncasecmp(arg, "watch", 5) == 0)
- flag_bits |= GDBR_LOG_WATCHPOINTS;
- else {
- feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
- if (got_unknown_category == false) {
- got_unknown_category = true;
- ListLogCategories(feedback_strm);
- }
- }
- }
- if (flag_bits == 0)
- flag_bits = GDBR_LOG_DEFAULT;
- g_log->GetMask().Reset(flag_bits);
- g_log->GetOptions().Reset(log_options);
- }
- g_log_enabled = true;
- return g_log;
-}
-
-void ProcessGDBRemoteLog::ListLogCategories(Stream *strm) {
- strm->Printf(
- "Logging categories for '%s':\n"
- " all - turn on all available logging categories\n"
- " async - log asynchronous activity\n"
- " break - log breakpoints\n"
- " communication - log communication activity\n"
- " default - enable the default set of logging categories for liblldb\n"
- " packets - log gdb remote packets\n"
- " memory - log memory reads and writes\n"
- " data-short - log memory bytes for memory reads and writes for short "
- "transactions only\n"
- " data-long - log memory bytes for memory reads and writes for all "
- "transactions\n"
- " process - log process events and activities\n"
- " thread - log thread events and activities\n"
- " step - log step related activities\n"
- " verbose - enable verbose logging\n"
- " watch - log watchpoint related activities\n",
- ProcessGDBRemote::GetPluginNameStatic().GetCString());
-}
-
-void ProcessGDBRemoteLog::LogIf(uint32_t mask, const char *format, ...) {
- Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(mask));
- if (log) {
- va_list args;
- va_start(args, format);
- log->VAPrintf(format, args);
- va_end(args);
- }
-}
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h
index f5e92b450614..3c5801176690 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h
@@ -15,9 +15,8 @@
// Other libraries and framework includes
// Project includes
-#include "lldb/Core/Log.h"
+#include "lldb/Utility/Log.h"
-#define GDBR_LOG_VERBOSE (1u << 0)
#define GDBR_LOG_PROCESS (1u << 1)
#define GDBR_LOG_THREAD (1u << 2)
#define GDBR_LOG_PACKETS (1u << 3)
@@ -37,21 +36,13 @@ namespace lldb_private {
namespace process_gdb_remote {
class ProcessGDBRemoteLog {
+ static Log::Channel g_channel;
+
public:
static void Initialize();
- static Log *GetLogIfAllCategoriesSet(uint32_t mask = 0);
-
- static Log *GetLogIfAnyCategoryIsSet(uint32_t mask);
-
- static void DisableLog(const char **categories, Stream *feedback_strm);
-
- static Log *EnableLog(lldb::StreamSP &log_stream_sp, uint32_t log_options,
- const char **categories, Stream *feedback_strm);
-
- static void ListLogCategories(Stream *strm);
-
- static void LogIf(uint32_t mask, const char *format, ...);
+ static Log *GetLogIfAllCategoriesSet(uint32_t mask) { return g_channel.GetLogIfAll(mask); }
+ static Log *GetLogIfAnyCategoryIsSet(uint32_t mask) { return g_channel.GetLogIfAny(mask); }
};
} // namespace process_gdb_remote
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index ab552145a18b..5197e8f9adfc 100644
--- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -11,9 +11,7 @@
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/ArchSpec.h"
-#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/State.h"
-#include "lldb/Core/StreamString.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -22,6 +20,8 @@
#include "lldb/Target/Target.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Target/Unwind.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/StreamString.h"
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
@@ -41,18 +41,16 @@ ThreadGDBRemote::ThreadGDBRemote(Process &process, lldb::tid_t tid)
m_dispatch_queue_t(LLDB_INVALID_ADDRESS), m_queue_kind(eQueueKindUnknown),
m_queue_serial_number(LLDB_INVALID_QUEUE_ID),
m_associated_with_libdispatch_queue(eLazyBoolCalculate) {
- ProcessGDBRemoteLog::LogIf(
- GDBR_LOG_THREAD,
- "%p: ThreadGDBRemote::ThreadGDBRemote (pid = %i, tid = 0x%4.4x)", this,
- process.GetID(), GetID());
+ Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD));
+ LLDB_LOG(log, "this = {0}, pid = {1}, tid = {2}", this, process.GetID(),
+ GetID());
}
ThreadGDBRemote::~ThreadGDBRemote() {
ProcessSP process_sp(GetProcess());
- ProcessGDBRemoteLog::LogIf(
- GDBR_LOG_THREAD,
- "%p: ThreadGDBRemote::~ThreadGDBRemote (pid = %i, tid = 0x%4.4x)", this,
- process_sp ? process_sp->GetID() : LLDB_INVALID_PROCESS_ID, GetID());
+ Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD));
+ LLDB_LOG(log, "this = {0}, pid = {1}, tid = {2}", this,
+ process_sp ? process_sp->GetID() : LLDB_INVALID_PROCESS_ID, GetID());
DestroyThread();
}