diff options
Diffstat (limited to 'source/Plugins/Process/gdb-remote')
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 ®_ctx_sp, - const RegisterInfo ®_info, const RegisterValue *reg_value_p) { + const RegisterInfo ®_info, const RegisterValue *reg_value_p, + lldb::ByteOrder byte_order) { RegisterValue reg_value; if (!reg_value_p) { Error error = reg_ctx_sp->ReadRegister(®_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, - ®_value); + ®_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, + ®_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, - ®_value); + ®_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, ®_name, &alt_name, &set_name, &value_regs, &invalidate_regs, &encoding_set, &format_set, - ®_info, &cur_reg_num, ®_offset, - &dwarf_opcode_bytes]( + ®_info, ®_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(); } |