diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote')
20 files changed, 1584 insertions, 1173 deletions
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index bd87521..0c4df7e 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/contrib/llvm/tools/lldb/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(); } } @@ -319,10 +319,9 @@ GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet, Timeout<std::micro> timeout, bool sync_on_timeout) { uint8_t buffer[8192]; - Error error; + Status 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) @@ -935,9 +933,9 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len, return GDBRemoteCommunication::PacketType::Invalid; } -Error GDBRemoteCommunication::StartListenThread(const char *hostname, - uint16_t port) { - Error error; +Status GDBRemoteCommunication::StartListenThread(const char *hostname, + uint16_t port) { + Status error; if (m_listen_thread.IsJoinable()) { error.SetErrorString("listen thread already running"); } else { @@ -964,7 +962,7 @@ bool GDBRemoteCommunication::JoinListenThread() { lldb::thread_result_t GDBRemoteCommunication::ListenThread(lldb::thread_arg_t arg) { GDBRemoteCommunication *comm = (GDBRemoteCommunication *)arg; - Error error; + Status error; ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)comm->GetConnection(); @@ -977,7 +975,7 @@ GDBRemoteCommunication::ListenThread(lldb::thread_arg_t arg) { return NULL; } -Error GDBRemoteCommunication::StartDebugserverProcess( +Status GDBRemoteCommunication::StartDebugserverProcess( const char *url, Platform *platform, ProcessLaunchInfo &launch_info, uint16_t *port, const Args *inferior_args, int pass_comm_fd) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); @@ -986,7 +984,7 @@ Error GDBRemoteCommunication::StartDebugserverProcess( __FUNCTION__, url ? url : "<empty>", port ? *port : uint16_t(0)); - Error error; + Status error; // If we locate debugserver, keep that located version around static FileSpec g_debugserver_file_spec; @@ -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() " @@ -1303,12 +1310,20 @@ void GDBRemoteCommunication::DumpHistory(Stream &strm) { m_history.Dump(strm); } GDBRemoteCommunication::ScopedTimeout::ScopedTimeout( GDBRemoteCommunication &gdb_comm, std::chrono::seconds timeout) - : m_gdb_comm(gdb_comm) { - m_saved_timeout = m_gdb_comm.SetPacketTimeout(timeout); + : m_gdb_comm(gdb_comm), m_timeout_modified(false) { + auto curr_timeout = gdb_comm.GetPacketTimeout(); + // Only update the timeout if the timeout is greater than the current + // timeout. If the current timeout is larger, then just use that. + if (curr_timeout < timeout) { + m_timeout_modified = true; + m_saved_timeout = m_gdb_comm.SetPacketTimeout(timeout); + } } GDBRemoteCommunication::ScopedTimeout::~ScopedTimeout() { - m_gdb_comm.SetPacketTimeout(m_saved_timeout); + // Only restore the timeout if we set it in the constructor. + if (m_timeout_modified) + m_gdb_comm.SetPacketTimeout(m_saved_timeout); } // This function is called via the Communications class read thread when bytes diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h index 1f3fa17..ce90de3 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -65,9 +65,9 @@ public: enum class PacketResult { Success = 0, // Success - ErrorSendFailed, // Error sending the packet + ErrorSendFailed, // Status sending the packet ErrorSendAck, // Didn't get an ack back after sending a packet - ErrorReplyFailed, // Error getting the reply + ErrorReplyFailed, // Status getting the reply ErrorReplyTimeout, // Timed out waiting for reply ErrorReplyInvalid, // Got a reply but it wasn't valid for the packet that // was sent @@ -89,6 +89,10 @@ public: private: GDBRemoteCommunication &m_gdb_comm; std::chrono::seconds m_saved_timeout; + // Don't ever reduce the timeout for a packet, only increase it. If the + // requested timeout if less than the current timeout, we don't set it + // and won't need to restore it. + bool m_timeout_modified; }; GDBRemoteCommunication(const char *comm_name, const char *listener_name); @@ -127,7 +131,7 @@ public: // Start a debugserver instance on the current host using the // supplied connection URL. //------------------------------------------------------------------ - Error StartDebugserverProcess( + Status StartDebugserverProcess( const char *url, Platform *platform, // If non nullptr, then check with the platform for // the GDB server binary if it can't be located @@ -251,8 +255,8 @@ protected: // on m_bytes. The checksum was for the compressed packet. bool DecompressPacket(); - Error StartListenThread(const char *hostname = "127.0.0.1", - uint16_t port = 0); + Status StartListenThread(const char *hostname = "127.0.0.1", + uint16_t port = 0); bool JoinListenThread(); diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index b70f090..e6fd386 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -18,21 +18,19 @@ #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/StreamString.h" // Project includes #include "ProcessGDBRemote.h" @@ -87,6 +85,8 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() m_supports_jThreadExtendedInfo(eLazyBoolCalculate), m_supports_jLoadedDynamicLibrariesInfos(eLazyBoolCalculate), m_supports_jGetSharedCacheInfo(eLazyBoolCalculate), + m_supports_QPassSignals(eLazyBoolCalculate), + m_supports_error_string_reply(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), @@ -113,7 +113,7 @@ GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient() { Disconnect(); } -bool GDBRemoteCommunicationClient::HandshakeWithServer(Error *error_ptr) { +bool GDBRemoteCommunicationClient::HandshakeWithServer(Status *error_ptr) { ResetDiscoverableSettings(false); // Start the read thread after we send the handshake ack since if we @@ -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 + @@ -585,6 +597,21 @@ bool GDBRemoteCommunicationClient::GetThreadExtendedInfoSupported() { return m_supports_jThreadExtendedInfo; } +void GDBRemoteCommunicationClient::EnableErrorStringInPacket() { + if (m_supports_error_string_reply == eLazyBoolCalculate) { + StringExtractorGDBRemote response; + // We try to enable error strings in remote packets + // but if we fail, we just work in the older way. + m_supports_error_string_reply = eLazyBoolNo; + if (SendPacketAndWaitForResponse("QEnableErrorStrings", response, false) == + PacketResult::Success) { + if (response.IsOKResponse()) { + m_supports_error_string_reply = eLazyBoolYes; + } + } + } +} + bool GDBRemoteCommunicationClient::GetLoadedDynamicLibrariesInfosSupported() { if (m_supports_jLoadedDynamicLibrariesInfos == eLazyBoolCalculate) { StringExtractorGDBRemote response; @@ -1382,8 +1409,8 @@ bool GDBRemoteCommunicationClient::DeallocateMemory(addr_t addr) { return false; } -Error GDBRemoteCommunicationClient::Detach(bool keep_stopped) { - Error error; +Status GDBRemoteCommunicationClient::Detach(bool keep_stopped) { + Status error; if (keep_stopped) { if (m_supports_detach_stay_stopped == eLazyBoolCalculate) { @@ -1422,9 +1449,9 @@ Error GDBRemoteCommunicationClient::Detach(bool keep_stopped) { return error; } -Error GDBRemoteCommunicationClient::GetMemoryRegionInfo( +Status GDBRemoteCommunicationClient::GetMemoryRegionInfo( lldb::addr_t addr, lldb_private::MemoryRegionInfo ®ion_info) { - Error error; + Status error; region_info.Clear(); if (m_supports_memory_region_info != eLazyBoolNo) { @@ -1491,13 +1518,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; @@ -1512,8 +1544,8 @@ Error GDBRemoteCommunicationClient::GetMemoryRegionInfo( return error; } -Error GDBRemoteCommunicationClient::GetWatchpointSupportInfo(uint32_t &num) { - Error error; +Status GDBRemoteCommunicationClient::GetWatchpointSupportInfo(uint32_t &num) { + Status error; if (m_supports_watchpoint_support_info == eLazyBoolYes) { num = m_num_supported_hardware_watchpoints; @@ -1551,18 +1583,18 @@ Error GDBRemoteCommunicationClient::GetWatchpointSupportInfo(uint32_t &num) { return error; } -lldb_private::Error GDBRemoteCommunicationClient::GetWatchpointSupportInfo( +lldb_private::Status GDBRemoteCommunicationClient::GetWatchpointSupportInfo( uint32_t &num, bool &after, const ArchSpec &arch) { - Error error(GetWatchpointSupportInfo(num)); + Status error(GetWatchpointSupportInfo(num)); if (error.Success()) error = GetWatchpointsTriggerAfterInstruction(after, arch); return error; } -lldb_private::Error +lldb_private::Status GDBRemoteCommunicationClient::GetWatchpointsTriggerAfterInstruction( bool &after, const ArchSpec &arch) { - Error error; + Status error; llvm::Triple::ArchType atype = arch.GetMachine(); // we assume watchpoints will happen after running the relevant opcode @@ -1660,7 +1692,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 +1939,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 +1950,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 +1994,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 +2227,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 +2282,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(); } @@ -2524,7 +2554,7 @@ uint8_t GDBRemoteCommunicationClient::SendGDBStoppointTypePacket( if (response.IsOKResponse()) return 0; - // Error while setting breakpoint, send back specific error + // Status while setting breakpoint, send back specific error if (response.IsErrorResponse()) return response.GetError(); @@ -2620,7 +2650,7 @@ lldb::addr_t GDBRemoteCommunicationClient::GetShlibInfoAddr() { return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); } -lldb_private::Error GDBRemoteCommunicationClient::RunShellCommand( +lldb_private::Status GDBRemoteCommunicationClient::RunShellCommand( const char *command, // Shouldn't be NULL const FileSpec & working_dir, // Pass empty FileSpec to use the current working directory @@ -2646,32 +2676,32 @@ lldb_private::Error GDBRemoteCommunicationClient::RunShellCommand( if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == PacketResult::Success) { if (response.GetChar() != 'F') - return Error("malformed reply"); + return Status("malformed reply"); if (response.GetChar() != ',') - return Error("malformed reply"); + return Status("malformed reply"); uint32_t exitcode = response.GetHexMaxU32(false, UINT32_MAX); if (exitcode == UINT32_MAX) - return Error("unable to run remote process"); + return Status("unable to run remote process"); else if (status_ptr) *status_ptr = exitcode; if (response.GetChar() != ',') - return Error("malformed reply"); + return Status("malformed reply"); uint32_t signo = response.GetHexMaxU32(false, UINT32_MAX); if (signo_ptr) *signo_ptr = signo; if (response.GetChar() != ',') - return Error("malformed reply"); + return Status("malformed reply"); std::string output; response.GetEscapedBinaryData(output); if (command_output) command_output->assign(output); - return Error(); + return Status(); } - return Error("unable to send packet"); + return Status("unable to send packet"); } -Error GDBRemoteCommunicationClient::MakeDirectory(const FileSpec &file_spec, - uint32_t file_permissions) { +Status GDBRemoteCommunicationClient::MakeDirectory(const FileSpec &file_spec, + uint32_t file_permissions) { std::string path{file_spec.GetPath(false)}; lldb_private::StreamString stream; stream.PutCString("qPlatform_mkdir:"); @@ -2683,16 +2713,17 @@ Error GDBRemoteCommunicationClient::MakeDirectory(const FileSpec &file_spec, if (SendPacketAndWaitForResponse(packet, response, false) != PacketResult::Success) - return Error("failed to send '%s' packet", packet.str().c_str()); + return Status("failed to send '%s' packet", packet.str().c_str()); if (response.GetChar() != 'F') - return Error("invalid response to '%s' packet", packet.str().c_str()); + return Status("invalid response to '%s' packet", packet.str().c_str()); - return Error(response.GetU32(UINT32_MAX), eErrorTypePOSIX); + return Status(response.GetU32(UINT32_MAX), eErrorTypePOSIX); } -Error GDBRemoteCommunicationClient::SetFilePermissions( - const FileSpec &file_spec, uint32_t file_permissions) { +Status +GDBRemoteCommunicationClient::SetFilePermissions(const FileSpec &file_spec, + uint32_t file_permissions) { std::string path{file_spec.GetPath(false)}; lldb_private::StreamString stream; stream.PutCString("qPlatform_chmod:"); @@ -2704,16 +2735,16 @@ Error GDBRemoteCommunicationClient::SetFilePermissions( if (SendPacketAndWaitForResponse(packet, response, false) != PacketResult::Success) - return Error("failed to send '%s' packet", stream.GetData()); + return Status("failed to send '%s' packet", stream.GetData()); if (response.GetChar() != 'F') - return Error("invalid response to '%s' packet", stream.GetData()); + return Status("invalid response to '%s' packet", stream.GetData()); - return Error(response.GetU32(UINT32_MAX), eErrorTypePOSIX); + return Status(response.GetU32(UINT32_MAX), eErrorTypePOSIX); } static uint64_t ParseHostIOPacketResponse(StringExtractorGDBRemote &response, - uint64_t fail_result, Error &error) { + uint64_t fail_result, Status &error) { response.SetFilePos(0); if (response.GetChar() != 'F') return fail_result; @@ -2733,7 +2764,7 @@ static uint64_t ParseHostIOPacketResponse(StringExtractorGDBRemote &response, lldb::user_id_t GDBRemoteCommunicationClient::OpenFile(const lldb_private::FileSpec &file_spec, uint32_t flags, mode_t mode, - Error &error) { + Status &error) { std::string path(file_spec.GetPath(false)); lldb_private::StreamString stream; stream.PutCString("vFile:open:"); @@ -2752,7 +2783,8 @@ GDBRemoteCommunicationClient::OpenFile(const lldb_private::FileSpec &file_spec, return UINT64_MAX; } -bool GDBRemoteCommunicationClient::CloseFile(lldb::user_id_t fd, Error &error) { +bool GDBRemoteCommunicationClient::CloseFile(lldb::user_id_t fd, + Status &error) { lldb_private::StreamString stream; stream.Printf("vFile:close:%i", (int)fd); StringExtractorGDBRemote response; @@ -2781,10 +2813,11 @@ lldb::user_id_t GDBRemoteCommunicationClient::GetFileSize( return UINT64_MAX; } -Error GDBRemoteCommunicationClient::GetFilePermissions( - const FileSpec &file_spec, uint32_t &file_permissions) { +Status +GDBRemoteCommunicationClient::GetFilePermissions(const FileSpec &file_spec, + uint32_t &file_permissions) { std::string path{file_spec.GetPath(false)}; - Error error; + Status error; lldb_private::StreamString stream; stream.PutCString("vFile:mode:"); stream.PutCStringAsRawHex8(path.c_str()); @@ -2819,7 +2852,7 @@ Error GDBRemoteCommunicationClient::GetFilePermissions( uint64_t GDBRemoteCommunicationClient::ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst, uint64_t dst_len, - Error &error) { + Status &error) { lldb_private::StreamString stream; stream.Printf("vFile:pread:%i,%" PRId64 ",%" PRId64, (int)fd, dst_len, offset); @@ -2853,7 +2886,7 @@ uint64_t GDBRemoteCommunicationClient::WriteFile(lldb::user_id_t fd, uint64_t offset, const void *src, uint64_t src_len, - Error &error) { + Status &error) { lldb_private::StreamGDBRemote stream; stream.Printf("vFile:pwrite:%i,%" PRId64 ",", (int)fd, offset); stream.PutEscapedBytes(src, src_len); @@ -2881,10 +2914,10 @@ uint64_t GDBRemoteCommunicationClient::WriteFile(lldb::user_id_t fd, return 0; } -Error GDBRemoteCommunicationClient::CreateSymlink(const FileSpec &src, - const FileSpec &dst) { +Status GDBRemoteCommunicationClient::CreateSymlink(const FileSpec &src, + const FileSpec &dst) { std::string src_path{src.GetPath(false)}, dst_path{dst.GetPath(false)}; - Error error; + Status error; lldb_private::StreamGDBRemote stream; stream.PutCString("vFile:symlink:"); // the unix symlink() command reverses its parameters where the dst if first, @@ -2915,9 +2948,9 @@ Error GDBRemoteCommunicationClient::CreateSymlink(const FileSpec &src, return error; } -Error GDBRemoteCommunicationClient::Unlink(const FileSpec &file_spec) { +Status GDBRemoteCommunicationClient::Unlink(const FileSpec &file_spec) { std::string path{file_spec.GetPath(false)}; - Error error; + Status error; lldb_private::StreamGDBRemote stream; stream.PutCString("vFile:unlink:"); // the unix symlink() command reverses its parameters where the dst if first, @@ -3134,6 +3167,213 @@ bool GDBRemoteCommunicationClient::SyncThreadState(lldb::tid_t tid) { response.IsOKResponse(); } +lldb::user_id_t +GDBRemoteCommunicationClient::SendStartTracePacket(const TraceOptions &options, + Status &error) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + lldb::user_id_t ret_uid = LLDB_INVALID_UID; + + StreamGDBRemote escaped_packet; + escaped_packet.PutCString("jTraceStart:"); + + StructuredData::Dictionary json_packet; + json_packet.AddIntegerItem("type", options.getType()); + json_packet.AddIntegerItem("buffersize", options.getTraceBufferSize()); + json_packet.AddIntegerItem("metabuffersize", options.getMetaDataBufferSize()); + + if (options.getThreadID() != LLDB_INVALID_THREAD_ID) + json_packet.AddIntegerItem("threadid", options.getThreadID()); + + StructuredData::DictionarySP custom_params = options.getTraceParams(); + if (custom_params) + json_packet.AddItem("params", custom_params); + + StreamString json_string; + json_packet.Dump(json_string, false); + escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize()); + + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response, + true) == + GDBRemoteCommunication::PacketResult::Success) { + if (!response.IsNormalResponse()) { + error = response.GetStatus(); + LLDB_LOG(log, "Target does not support Tracing , error {0}", error); + } else { + ret_uid = response.GetHexMaxU64(false, LLDB_INVALID_UID); + } + } else { + LLDB_LOG(log, "failed to send packet"); + error.SetErrorStringWithFormat("failed to send packet: '%s'", + escaped_packet.GetData()); + } + return ret_uid; +} + +Status +GDBRemoteCommunicationClient::SendStopTracePacket(lldb::user_id_t uid, + lldb::tid_t thread_id) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + StringExtractorGDBRemote response; + Status error; + + StructuredData::Dictionary json_packet; + StreamGDBRemote escaped_packet; + StreamString json_string; + escaped_packet.PutCString("jTraceStop:"); + + json_packet.AddIntegerItem("traceid", uid); + + if (thread_id != LLDB_INVALID_THREAD_ID) + json_packet.AddIntegerItem("threadid", thread_id); + + json_packet.Dump(json_string, false); + + escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize()); + + if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response, + true) == + GDBRemoteCommunication::PacketResult::Success) { + if (!response.IsOKResponse()) { + error = response.GetStatus(); + LLDB_LOG(log, "stop tracing failed"); + } + } else { + LLDB_LOG(log, "failed to send packet"); + error.SetErrorStringWithFormat( + "failed to send packet: '%s' with error '%d'", escaped_packet.GetData(), + response.GetError()); + } + return error; +} + +Status GDBRemoteCommunicationClient::SendGetDataPacket( + lldb::user_id_t uid, lldb::tid_t thread_id, + llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) { + + StreamGDBRemote escaped_packet; + escaped_packet.PutCString("jTraceBufferRead:"); + return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset); +} + +Status GDBRemoteCommunicationClient::SendGetMetaDataPacket( + lldb::user_id_t uid, lldb::tid_t thread_id, + llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) { + + StreamGDBRemote escaped_packet; + escaped_packet.PutCString("jTraceMetaRead:"); + return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset); +} + +Status +GDBRemoteCommunicationClient::SendGetTraceConfigPacket(lldb::user_id_t uid, + TraceOptions &options) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + StringExtractorGDBRemote response; + Status error; + + StreamString json_string; + StreamGDBRemote escaped_packet; + escaped_packet.PutCString("jTraceConfigRead:"); + + StructuredData::Dictionary json_packet; + json_packet.AddIntegerItem("traceid", uid); + + if (options.getThreadID() != LLDB_INVALID_THREAD_ID) + json_packet.AddIntegerItem("threadid", options.getThreadID()); + + json_packet.Dump(json_string, false); + escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize()); + + if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response, + true) == + GDBRemoteCommunication::PacketResult::Success) { + if (response.IsNormalResponse()) { + uint64_t type = std::numeric_limits<uint64_t>::max(); + uint64_t buffersize = std::numeric_limits<uint64_t>::max(); + uint64_t metabuffersize = std::numeric_limits<uint64_t>::max(); + + auto json_object = StructuredData::ParseJSON(response.Peek()); + + if (!json_object || + json_object->GetType() != lldb::eStructuredDataTypeDictionary) { + error.SetErrorString("Invalid Configuration obtained"); + return error; + } + + auto json_dict = json_object->GetAsDictionary(); + + json_dict->GetValueForKeyAsInteger<uint64_t>("metabuffersize", + metabuffersize); + options.setMetaDataBufferSize(metabuffersize); + + json_dict->GetValueForKeyAsInteger<uint64_t>("buffersize", buffersize); + options.setTraceBufferSize(buffersize); + + json_dict->GetValueForKeyAsInteger<uint64_t>("type", type); + options.setType(static_cast<lldb::TraceType>(type)); + + StructuredData::ObjectSP custom_params_sp = + json_dict->GetValueForKey("params"); + if (custom_params_sp) { + if (custom_params_sp->GetType() != + lldb::eStructuredDataTypeDictionary) { + error.SetErrorString("Invalid Configuration obtained"); + return error; + } else + options.setTraceParams( + static_pointer_cast<StructuredData::Dictionary>( + custom_params_sp)); + } + } else { + error = response.GetStatus(); + } + } else { + LLDB_LOG(log, "failed to send packet"); + error.SetErrorStringWithFormat("failed to send packet: '%s'", + escaped_packet.GetData()); + } + return error; +} + +Status GDBRemoteCommunicationClient::SendGetTraceDataPacket( + StreamGDBRemote &packet, lldb::user_id_t uid, lldb::tid_t thread_id, + llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + Status error; + + StructuredData::Dictionary json_packet; + + json_packet.AddIntegerItem("traceid", uid); + json_packet.AddIntegerItem("offset", offset); + json_packet.AddIntegerItem("buffersize", buffer.size()); + + if (thread_id != LLDB_INVALID_THREAD_ID) + json_packet.AddIntegerItem("threadid", thread_id); + + StreamString json_string; + json_packet.Dump(json_string, false); + + packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize()); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet.GetString(), response, true) == + GDBRemoteCommunication::PacketResult::Success) { + if (response.IsNormalResponse()) { + size_t filled_size = response.GetHexBytesAvail(buffer); + buffer = llvm::MutableArrayRef<uint8_t>(buffer.data(), filled_size); + } else { + error = response.GetStatus(); + buffer = buffer.slice(buffer.size()); + } + } else { + LLDB_LOG(log, "failed to send packet"); + error.SetErrorStringWithFormat("failed to send packet: '%s'", + packet.GetData()); + buffer = buffer.slice(buffer.size()); + } + return error; +} + bool GDBRemoteCommunicationClient::GetModuleInfo( const FileSpec &module_file_spec, const lldb_private::ArchSpec &arch_spec, ModuleSpec &module_spec) { @@ -3193,7 +3433,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()); } } @@ -3206,12 +3446,12 @@ ParseModuleSpec(StructuredData::Dictionary *dict) { if (!dict) return llvm::None; - std::string string; + llvm::StringRef string; uint64_t integer; if (!dict->GetValueForKeyAsString("uuid", string)) return llvm::None; - result.GetUUID().SetFromCString(string.c_str(), string.size()); + result.GetUUID().SetFromStringRef(string, string.size()); if (!dict->GetValueForKeyAsInteger("file_offset", integer)) return llvm::None; @@ -3223,11 +3463,12 @@ ParseModuleSpec(StructuredData::Dictionary *dict) { if (!dict->GetValueForKeyAsString("triple", string)) return llvm::None; - result.GetArchitecture().SetTriple(string.c_str()); + result.GetArchitecture().SetTriple(string); 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 +3495,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 || @@ -3292,7 +3536,7 @@ GDBRemoteCommunicationClient::GetModulesInfo( bool GDBRemoteCommunicationClient::ReadExtFeature( const lldb_private::ConstString object, const lldb_private::ConstString annex, std::string &out, - lldb_private::Error &err) { + lldb_private::Status &err) { std::stringstream output; StringExtractorGDBRemote chunk; @@ -3571,9 +3815,29 @@ GDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() { : nullptr; } -Error GDBRemoteCommunicationClient::ConfigureRemoteStructuredData( +Status 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 Status("Sending QPassSignals packet failed"); + + if (response.IsOKResponse()) { + return Status(); + } else { + return Status("Unknown error happened during sending QPassSignals packet."); + } +} + +Status GDBRemoteCommunicationClient::ConfigureRemoteStructuredData( const ConstString &type_name, const StructuredData::ObjectSP &config_sp) { - Error error; + Status error; if (type_name.GetLength() == 0) { error.SetErrorString("invalid type_name argument"); diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 83162a6..712d85e 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -23,8 +23,9 @@ // Other libraries and framework includes // Project includes #include "lldb/Core/ArchSpec.h" -#include "lldb/Core/StructuredData.h" #include "lldb/Target/Process.h" +#include "lldb/Utility/StreamGDBRemote.h" +#include "lldb/Utility/StructuredData.h" #include "llvm/ADT/Optional.h" @@ -41,7 +42,7 @@ public: // After connecting, send the handshake to the server to make sure // we are communicating with it. //------------------------------------------------------------------ - bool HandshakeWithServer(Error *error_ptr); + bool HandshakeWithServer(Status *error_ptr); // For packets which specify a range of output to be returned, // return all of the output via a series of request packets of the form @@ -230,17 +231,17 @@ public: bool DeallocateMemory(lldb::addr_t addr); - Error Detach(bool keep_stopped); + Status Detach(bool keep_stopped); - Error GetMemoryRegionInfo(lldb::addr_t addr, MemoryRegionInfo &range_info); + Status GetMemoryRegionInfo(lldb::addr_t addr, MemoryRegionInfo &range_info); - Error GetWatchpointSupportInfo(uint32_t &num); + Status GetWatchpointSupportInfo(uint32_t &num); - Error GetWatchpointSupportInfo(uint32_t &num, bool &after, - const ArchSpec &arch); + Status GetWatchpointSupportInfo(uint32_t &num, bool &after, + const ArchSpec &arch); - Error GetWatchpointsTriggerAfterInstruction(bool &after, - const ArchSpec &arch); + Status GetWatchpointsTriggerAfterInstruction(bool &after, + const ArchSpec &arch); const ArchSpec &GetHostArchitecture(); @@ -339,6 +340,8 @@ public: bool GetQXferAuxvReadSupported(); + void EnableErrorStringInPacket(); + bool GetQXferLibrariesReadSupported(); bool GetQXferLibrariesSVR4ReadSupported(); @@ -347,6 +350,8 @@ public: bool GetEchoSupported(); + bool GetQPassSignalsSupported(); + bool GetAugmentedLibrariesSVR4ReadSupported(); bool GetQXferFeaturesReadSupported(); @@ -363,33 +368,33 @@ public: bool &sequence_mutex_unavailable); lldb::user_id_t OpenFile(const FileSpec &file_spec, uint32_t flags, - mode_t mode, Error &error); + mode_t mode, Status &error); - bool CloseFile(lldb::user_id_t fd, Error &error); + bool CloseFile(lldb::user_id_t fd, Status &error); lldb::user_id_t GetFileSize(const FileSpec &file_spec); - Error GetFilePermissions(const FileSpec &file_spec, - uint32_t &file_permissions); + Status GetFilePermissions(const FileSpec &file_spec, + uint32_t &file_permissions); - Error SetFilePermissions(const FileSpec &file_spec, - uint32_t file_permissions); + Status SetFilePermissions(const FileSpec &file_spec, + uint32_t file_permissions); uint64_t ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst, - uint64_t dst_len, Error &error); + uint64_t dst_len, Status &error); uint64_t WriteFile(lldb::user_id_t fd, uint64_t offset, const void *src, - uint64_t src_len, Error &error); + uint64_t src_len, Status &error); - Error CreateSymlink(const FileSpec &src, const FileSpec &dst); + Status CreateSymlink(const FileSpec &src, const FileSpec &dst); - Error Unlink(const FileSpec &file_spec); + Status Unlink(const FileSpec &file_spec); - Error MakeDirectory(const FileSpec &file_spec, uint32_t mode); + Status MakeDirectory(const FileSpec &file_spec, uint32_t mode); bool GetFileExists(const FileSpec &file_spec); - Error RunShellCommand( + Status RunShellCommand( const char *command, // Shouldn't be nullptr const FileSpec &working_dir, // Pass empty FileSpec to use the current // working directory @@ -446,10 +451,13 @@ public: bool ReadExtFeature(const lldb_private::ConstString object, const lldb_private::ConstString annex, std::string &out, - lldb_private::Error &err); + lldb_private::Status &err); void ServeSymbolLookups(lldb_private::Process *process); + // Sends QPassSignals packet to the server with given signals to ignore. + Status SendSignalsToIgnore(llvm::ArrayRef<int32_t> signals); + //------------------------------------------------------------------ /// Return the feature set supported by the gdb-remote server. /// @@ -490,10 +498,25 @@ public: /// /// @see \b Process::ConfigureStructuredData(...) for details. //------------------------------------------------------------------ - Error + Status ConfigureRemoteStructuredData(const ConstString &type_name, const StructuredData::ObjectSP &config_sp); + lldb::user_id_t SendStartTracePacket(const TraceOptions &options, + Status &error); + + Status SendStopTracePacket(lldb::user_id_t uid, lldb::tid_t thread_id); + + Status SendGetDataPacket(lldb::user_id_t uid, lldb::tid_t thread_id, + llvm::MutableArrayRef<uint8_t> &buffer, + size_t offset = 0); + + Status SendGetMetaDataPacket(lldb::user_id_t uid, lldb::tid_t thread_id, + llvm::MutableArrayRef<uint8_t> &buffer, + size_t offset = 0); + + Status SendGetTraceConfigPacket(lldb::user_id_t uid, TraceOptions &options); + protected: LazyBool m_supports_not_sending_acks; LazyBool m_supports_thread_suffix; @@ -527,6 +550,8 @@ protected: LazyBool m_supports_jThreadExtendedInfo; LazyBool m_supports_jLoadedDynamicLibrariesInfos; LazyBool m_supports_jGetSharedCacheInfo; + LazyBool m_supports_QPassSignals; + LazyBool m_supports_error_string_reply; bool m_supports_qProcessInfoPID : 1, m_supports_qfProcessInfo : 1, m_supports_qUserName : 1, m_supports_qGroupName : 1, @@ -581,6 +606,11 @@ protected: lldb::tid_t tid, StreamString &&payload, StringExtractorGDBRemote &response, bool send_async); + Status SendGetTraceDataPacket(StreamGDBRemote &packet, lldb::user_id_t uid, + lldb::tid_t thread_id, + llvm::MutableArrayRef<uint8_t> &buffer, + size_t offset); + private: DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationClient); }; diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index 934824e..4be92b7 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -20,6 +20,7 @@ // Project includes #include "ProcessGDBRemoteLog.h" #include "Utility/StringExtractorGDBRemote.h" +#include "lldb/Utility/StreamString.h" using namespace lldb; using namespace lldb_private; @@ -27,7 +28,12 @@ using namespace lldb_private::process_gdb_remote; GDBRemoteCommunicationServer::GDBRemoteCommunicationServer( const char *comm_name, const char *listener_name) - : GDBRemoteCommunication(comm_name, listener_name), m_exit_now(false) {} + : GDBRemoteCommunication(comm_name, listener_name), m_exit_now(false) { + RegisterPacketHandler( + StringExtractorGDBRemote::eServerPacketType_QEnableErrorStrings, + [this](StringExtractorGDBRemote packet, Status &error, bool &interrupt, + bool &quit) { return this->Handle_QErrorStringEnable(packet); }); +} GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() {} @@ -39,7 +45,7 @@ void GDBRemoteCommunicationServer::RegisterPacketHandler( GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServer::GetPacketAndSendResponse( - Timeout<std::micro> timeout, Error &error, bool &interrupt, bool &quit) { + Timeout<std::micro> timeout, Status &error, bool &interrupt, bool &quit) { StringExtractorGDBRemote packet; PacketResult packet_result = WaitForPacketNoLock(packet, timeout, false); @@ -100,6 +106,24 @@ GDBRemoteCommunicationServer::SendErrorResponse(uint8_t err) { } GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServer::SendErrorResponse(const Status &error) { + if (m_send_error_strings) { + lldb_private::StreamString packet; + packet.Printf("E%2.2x;", static_cast<uint8_t>(error.GetError())); + packet.PutCStringAsRawHex8(error.AsCString()); + return SendPacketNoLock(packet.GetString()); + } else + return SendErrorResponse(error.GetError()); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServer::Handle_QErrorStringEnable( + StringExtractorGDBRemote &packet) { + m_send_error_strings = true; + return SendOKResponse(); +} + +GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServer::SendIllFormedResponse( const StringExtractorGDBRemote &failed_packet, const char *message) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS)); diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h index 0c583e6..a353524 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -31,8 +31,8 @@ class GDBRemoteCommunicationServer : public GDBRemoteCommunication { public: using PortMap = std::map<uint16_t, lldb::pid_t>; using PacketHandler = - std::function<PacketResult(StringExtractorGDBRemote &packet, Error &error, - bool &interrupt, bool &quit)>; + std::function<PacketResult(StringExtractorGDBRemote &packet, + Status &error, bool &interrupt, bool &quit)>; GDBRemoteCommunicationServer(const char *comm_name, const char *listener_name); @@ -44,7 +44,7 @@ public: PacketHandler handler); PacketResult GetPacketAndSendResponse(Timeout<std::micro> timeout, - Error &error, bool &interrupt, + Status &error, bool &interrupt, bool &quit); // After connecting, do a little handshake with the client to make sure @@ -57,6 +57,13 @@ protected: bool m_exit_now; // use in asynchronous handling to indicate process should // exit. + bool m_send_error_strings; // If the client enables this then + // we will send error strings as well. + + PacketResult Handle_QErrorStringEnable(StringExtractorGDBRemote &packet); + + PacketResult SendErrorResponse(const Status &error); + PacketResult SendUnimplementedResponse(const char *packet); PacketResult SendErrorResponse(uint8_t error); diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp index e4e6810..f53db50 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ b/contrib/llvm/tools/lldb/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; @@ -525,7 +523,7 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_Open( File::ConvertOpenOptionsForPOSIXOpen(packet.GetHexMaxU32(false, 0)); if (packet.GetChar() == ',') { mode_t mode = packet.GetHexMaxU32(false, 0600); - Error error; + Status error; const FileSpec path_spec{path, true}; int fd = ::open(path_spec.GetCString(), flags, mode); const int save_errno = fd == -1 ? errno : 0; @@ -546,7 +544,7 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_Close( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("vFile:close:")); int fd = packet.GetS32(-1); - Error error; + Status error; int err = -1; int save_errno = 0; if (fd >= 0) { @@ -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()); } @@ -664,7 +663,7 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_Mode( std::string path; packet.GetHexByteString(path); if (!path.empty()) { - Error error; + Status error; const uint32_t mode = File::GetPermissions(FileSpec{path, true}, error); StreamString response; response.Printf("F%u", mode); @@ -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(','); @@ -703,7 +702,7 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_symlink( packet.GetHexByteStringTerminatedBy(dst, ','); packet.GetChar(); // Skip ',' char packet.GetHexByteString(src); - Error error = FileSystem::Symlink(FileSpec{src, true}, FileSpec{dst, false}); + Status error = FileSystem::Symlink(FileSpec{src, true}, FileSpec{dst, false}); StreamString response; response.Printf("F%u,%u", error.GetError(), error.GetError()); return SendPacketNoLock(response.GetString()); @@ -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}); + Status error(llvm::sys::fs::remove(path)); StreamString response; response.Printf("F%u,%u", error.GetError(), error.GetError()); return SendPacketNoLock(response.GetString()); @@ -737,7 +736,7 @@ GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell( packet.GetHexByteString(working_dir); int status, signo; std::string output; - Error err = + Status err = Host::RunShellCommand(path.c_str(), FileSpec{working_dir, true}, &status, &signo, &output, timeout); StreamGDBRemote response; @@ -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); + Status 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); + Status 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 @@ -1045,14 +1046,9 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) { if (success) { m_process_launch_error = LaunchProcess(); - if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) { + if (m_process_launch_error.Success()) return SendOKResponse(); - } else { - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("LLGSPacketHandler::%s failed to launch exe: %s", - __FUNCTION__, m_process_launch_error.AsCString()); - } + LLDB_LOG(log, "failed to launch exe: {0}", m_process_launch_error); } return SendErrorResponse(8); } @@ -1091,12 +1087,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()); @@ -1140,7 +1135,7 @@ GDBRemoteCommunicationServerCommon::Handle_jModulesInfo( packet_array->GetItemAtIndex(i)->GetAsDictionary(); if (!query) continue; - std::string file, triple; + llvm::StringRef file, triple; if (!query->GetValueForKeyAsString("file", file) || !query->GetValueForKeyAsString("triple", triple)) continue; @@ -1278,9 +1273,10 @@ FileSpec GDBRemoteCommunicationServerCommon::FindModuleFile( #endif } -ModuleSpec GDBRemoteCommunicationServerCommon::GetModuleInfo( - const std::string &module_path, const std::string &triple) { - ArchSpec arch(triple.c_str()); +ModuleSpec +GDBRemoteCommunicationServerCommon::GetModuleInfo(llvm::StringRef module_path, + llvm::StringRef triple) { + ArchSpec arch(triple); const FileSpec req_module_path_spec(module_path, true); const FileSpec module_path_spec = diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h index 321a922..e9ab8f1 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h @@ -38,7 +38,7 @@ public: protected: ProcessLaunchInfo m_process_launch_info; - Error m_process_launch_error; + Status m_process_launch_error; ProcessInstanceInfoList m_proc_infos; uint32_t m_proc_infos_index; bool m_thread_suffix_supported; @@ -130,7 +130,7 @@ protected: PacketResult (T::*handler)(StringExtractorGDBRemote &packet)) { RegisterPacketHandler(packet_type, [this, handler](StringExtractorGDBRemote packet, - Error &error, bool &interrupt, + Status &error, bool &interrupt, bool &quit) { return (static_cast<T *>(this)->*handler)(packet); }); @@ -144,17 +144,16 @@ protected: /// with all the information for a child process to be launched. /// /// @return - /// An Error object indicating the success or failure of the + /// An Status object indicating the success or failure of the /// launch. //------------------------------------------------------------------ - virtual Error LaunchProcess() = 0; + virtual Status LaunchProcess() = 0; virtual FileSpec FindModuleFile(const std::string &module_path, const ArchSpec &arch); private: - ModuleSpec GetModuleInfo(const std::string &module_path, - const std::string &triple); + ModuleSpec GetModuleInfo(llvm::StringRef module_path, llvm::StringRef triple); }; } // namespace process_gdb_remote diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index bf72673..9294359 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/contrib/llvm/tools/lldb/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,28 @@ #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/PosixApi.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 +50,6 @@ #include "ProcessGDBRemote.h" #include "ProcessGDBRemoteLog.h" #include "Utility/StringExtractorGDBRemote.h" -#include "Utility/UriParser.h" using namespace lldb; using namespace lldb_private; @@ -74,16 +74,11 @@ enum GDBRemoteServerError { // GDBRemoteCommunicationServerLLGS constructor //---------------------------------------------------------------------- GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS( - MainLoop &mainloop) + MainLoop &mainloop, const NativeProcessProtocol::Factory &process_factory) : GDBRemoteCommunicationServerCommon("gdb-remote.server", "gdb-remote.server.rx_packet"), - m_mainloop(mainloop), m_current_tid(LLDB_INVALID_THREAD_ID), - 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) { + m_mainloop(mainloop), m_process_factory(process_factory), + m_stdio_communication("process.stdio") { RegisterPacketHandlers(); } @@ -181,37 +176,57 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() { &GDBRemoteCommunicationServerLLGS::Handle_Z); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_z, &GDBRemoteCommunicationServerLLGS::Handle_z); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_QPassSignals, + &GDBRemoteCommunicationServerLLGS::Handle_QPassSignals); + + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_jTraceStart, + &GDBRemoteCommunicationServerLLGS::Handle_jTraceStart); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_jTraceBufferRead, + &GDBRemoteCommunicationServerLLGS::Handle_jTraceRead); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_jTraceMetaRead, + &GDBRemoteCommunicationServerLLGS::Handle_jTraceRead); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_jTraceStop, + &GDBRemoteCommunicationServerLLGS::Handle_jTraceStop); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_jTraceConfigRead, + &GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead); RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k, - [this](StringExtractorGDBRemote packet, Error &error, + [this](StringExtractorGDBRemote packet, Status &error, bool &interrupt, bool &quit) { quit = true; return this->Handle_k(packet); }); } -Error GDBRemoteCommunicationServerLLGS::SetLaunchArguments( - const char *const args[], int argc) { +Status +GDBRemoteCommunicationServerLLGS::SetLaunchArguments(const char *const args[], + int argc) { if ((argc < 1) || !args || !args[0] || !args[0][0]) - return Error("%s: no process command line specified to launch", - __FUNCTION__); + return Status("%s: no process command line specified to launch", + __FUNCTION__); m_process_launch_info.SetArguments(const_cast<const char **>(args), true); - return Error(); + return Status(); } -Error GDBRemoteCommunicationServerLLGS::SetLaunchFlags( - unsigned int launch_flags) { +Status +GDBRemoteCommunicationServerLLGS::SetLaunchFlags(unsigned int launch_flags) { m_process_launch_info.GetFlags().Set(launch_flags); - return Error(); + return Status(); } -Error GDBRemoteCommunicationServerLLGS::LaunchProcess() { +Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (!m_process_launch_info.GetArguments().GetArgumentCount()) - return Error("%s: no process command line specified to launch", - __FUNCTION__); + return Status("%s: no process command line specified to launch", + __FUNCTION__); const bool should_forward_stdio = m_process_launch_info.GetFileActionForFD(STDIN_FILENO) == nullptr || @@ -223,19 +238,20 @@ Error GDBRemoteCommunicationServerLLGS::LaunchProcess() { const bool default_to_use_pty = true; m_process_launch_info.FinalizeFileActions(nullptr, default_to_use_pty); - Error error; { std::lock_guard<std::recursive_mutex> guard(m_debugged_process_mutex); - assert(!m_debugged_process_sp && "lldb-server creating debugged " + assert(!m_debugged_process_up && "lldb-server creating debugged " "process but one already exists"); - error = NativeProcessProtocol::Launch(m_process_launch_info, *this, - m_mainloop, m_debugged_process_sp); - } - - if (!error.Success()) { - fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__, - m_process_launch_info.GetArguments().GetArgumentAtIndex(0)); - return error; + auto process_or = + m_process_factory.Launch(m_process_launch_info, *this, m_mainloop); + if (!process_or) { + Status status(process_or.takeError()); + llvm::errs() << llvm::formatv( + "failed to launch executable `{0}`: {1}", + m_process_launch_info.GetArguments().GetArgumentAtIndex(0), status); + return status; + } + m_debugged_process_up = std::move(*process_or); } // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol @@ -248,22 +264,21 @@ Error GDBRemoteCommunicationServerLLGS::LaunchProcess() { // nullptr means it's not redirected to file or pty (in case of LLGS local) // at least one of stdio will be transferred pty<->gdb-remote // we need to give the pty master handle to this object to read and/or write - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " setting up stdout/stderr redirection via $O gdb-remote commands", - __FUNCTION__, m_debugged_process_sp->GetID()); + LLDB_LOG(log, + "pid = {0}: setting up stdout/stderr redirection via $O " + "gdb-remote commands", + m_debugged_process_up->GetID()); // Setup stdout/stderr mapping from inferior to $O - auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor(); + auto terminal_fd = m_debugged_process_up->GetTerminalFileDescriptor(); if (terminal_fd >= 0) { if (log) log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s setting " "inferior STDIO fd to %d", __FUNCTION__, terminal_fd); - error = SetSTDIOFileDescriptor(terminal_fd); - if (error.Fail()) - return error; + Status status = SetSTDIOFileDescriptor(terminal_fd); + if (status.Fail()) + return status; } else { if (log) log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " @@ -271,23 +286,20 @@ Error GDBRemoteCommunicationServerLLGS::LaunchProcess() { __FUNCTION__, terminal_fd); } } else { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " skipping stdout/stderr redirection via $O: inferior will " - "communicate over client-provided file descriptors", - __FUNCTION__, m_debugged_process_sp->GetID()); + LLDB_LOG(log, + "pid = {0} skipping stdout/stderr redirection via $O: inferior " + "will communicate over client-provided file descriptors", + m_debugged_process_up->GetID()); } printf("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments().GetArgumentAtIndex(0), - m_process_launch_info.GetProcessID()); + m_debugged_process_up->GetID()); - return error; + return Status(); } -Error GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { - Error error; - +Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64, @@ -295,32 +307,33 @@ Error GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { // Before we try to attach, make sure we aren't already monitoring something // else. - if (m_debugged_process_sp && - m_debugged_process_sp->GetID() != LLDB_INVALID_PROCESS_ID) - return Error("cannot attach to a process %" PRIu64 - " when another process with pid %" PRIu64 - " is being debugged.", - pid, m_debugged_process_sp->GetID()); + if (m_debugged_process_up && + m_debugged_process_up->GetID() != LLDB_INVALID_PROCESS_ID) + return Status("cannot attach to a process %" PRIu64 + " when another process with pid %" PRIu64 + " is being debugged.", + pid, m_debugged_process_up->GetID()); // Try to attach. - error = NativeProcessProtocol::Attach(pid, *this, m_mainloop, - m_debugged_process_sp); - if (!error.Success()) { - fprintf(stderr, "%s: failed to attach to process %" PRIu64 ": %s", - __FUNCTION__, pid, error.AsCString()); - return error; + auto process_or = m_process_factory.Attach(pid, *this, m_mainloop); + if (!process_or) { + Status status(process_or.takeError()); + llvm::errs() << llvm::formatv("failed to attach to process {0}: {1}", pid, + status); + return status; } + m_debugged_process_up = std::move(*process_or); // Setup stdout/stderr mapping from inferior. - auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor(); + auto terminal_fd = m_debugged_process_up->GetTerminalFileDescriptor(); if (terminal_fd >= 0) { if (log) log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s setting " "inferior STDIO fd to %d", __FUNCTION__, terminal_fd); - error = SetSTDIOFileDescriptor(terminal_fd); - if (error.Fail()) - return error; + Status status = SetSTDIOFileDescriptor(terminal_fd); + if (status.Fail()) + return status; } else { if (log) log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " @@ -329,8 +342,7 @@ Error GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { } printf("Attached to process %" PRIu64 "...\n", pid); - - return error; + return Status(); } void GDBRemoteCommunicationServerLLGS::InitializeDelegate( @@ -352,53 +364,23 @@ GDBRemoteCommunicationServerLLGS::SendWResponse( Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); // send W notification - ExitType exit_type = ExitType::eExitTypeInvalid; - int return_code = 0; - std::string exit_description; - - const bool got_exit_info = - process->GetExitStatus(&exit_type, &return_code, exit_description); - if (!got_exit_info) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - ", failed to retrieve process exit status", - __FUNCTION__, process->GetID()); + auto wait_status = process->GetExitStatus(); + if (!wait_status) { + LLDB_LOG(log, "pid = {0}, failed to retrieve process exit status", + process->GetID()); StreamGDBRemote response; response.PutChar('E'); response.PutHex8(GDBRemoteServerError::eErrorExitStatus); return SendPacketNoLock(response.GetString()); - } else { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - ", returning exit type %d, return code %d [%s]", - __FUNCTION__, process->GetID(), exit_type, return_code, - exit_description.c_str()); - - StreamGDBRemote response; - - char return_type_code; - switch (exit_type) { - case ExitType::eExitTypeExit: - return_type_code = 'W'; - break; - case ExitType::eExitTypeSignal: - return_type_code = 'X'; - break; - case ExitType::eExitTypeStop: - return_type_code = 'S'; - break; - case ExitType::eExitTypeInvalid: - return_type_code = 'E'; - break; - } - response.PutChar(return_type_code); + } - // POSIX exit status limited to unsigned 8 bits. - response.PutHex8(return_code); + LLDB_LOG(log, "pid = {0}, returning exit type {1}", process->GetID(), + *wait_status); - return SendPacketNoLock(response.GetString()); - } + StreamGDBRemote response; + response.Format("{0:g}", *wait_status); + return SendPacketNoLock(response.GetString()); } static void AppendHexValue(StreamString &response, const uint8_t *buf, @@ -415,10 +397,11 @@ 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); + Status error = reg_ctx_sp->ReadRegister(®_info, reg_value); if (error.Success()) reg_value_p = ®_value; // else log. @@ -426,7 +409,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 +420,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 +445,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); @@ -489,7 +469,7 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread, // registers. RegisterValue reg_value; - Error error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value); + Status 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", @@ -501,7 +481,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 +547,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) @@ -614,18 +596,15 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); // Ensure we have a debugged process. - if (!m_debugged_process_sp || - (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) return SendErrorResponse(50); - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s preparing packet for pid %" PRIu64 - " tid %" PRIu64, - __FUNCTION__, m_debugged_process_sp->GetID(), tid); + LLDB_LOG(log, "preparing packet for pid {0} tid {1}", + m_debugged_process_up->GetID(), tid); // Ensure we can get info on the given thread. - NativeThreadProtocolSP thread_sp(m_debugged_process_sp->GetThreadByID(tid)); + NativeThreadProtocolSP thread_sp(m_debugged_process_up->GetThreadByID(tid)); if (!thread_sp) return SendErrorResponse(51); @@ -646,13 +625,11 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( // Output the T packet with the thread response.PutChar('T'); int signum = tid_stop_info.details.signal.signo; - if (log) { - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " tid %" PRIu64 - " got signal signo = %d, reason = %d, exc_type = %" PRIu64, - __FUNCTION__, m_debugged_process_sp->GetID(), tid, signum, - tid_stop_info.reason, tid_stop_info.details.exception.type); - } + LLDB_LOG( + log, + "pid {0}, tid {1}, got signal signo = {2}, reason = {3}, exc_type = {4}", + m_debugged_process_up->GetID(), tid, signum, int(tid_stop_info.reason), + tid_stop_info.details.exception.type); // Print the signal number. response.PutHex8(signum & 0xff); @@ -690,9 +667,9 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( uint32_t thread_index = 0; NativeThreadProtocolSP listed_thread_sp; for (listed_thread_sp = - m_debugged_process_sp->GetThreadAtIndex(thread_index); + m_debugged_process_up->GetThreadAtIndex(thread_index); listed_thread_sp; ++thread_index, - listed_thread_sp = m_debugged_process_sp->GetThreadAtIndex( + listed_thread_sp = m_debugged_process_up->GetThreadAtIndex( thread_index)) { if (thread_index > 0) response.PutChar(','); @@ -709,18 +686,52 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( if (thread_index > 0) { const bool threads_with_valid_stop_info_only = true; JSONArray::SP threads_info_sp = GetJSONThreadsInfo( - *m_debugged_process_sp, threads_with_valid_stop_info_only); + *m_debugged_process_up, threads_with_valid_stop_info_only); if (threads_info_sp) { response.PutCString("jstopinfo:"); StreamString unescaped_response; threads_info_sp->Write(unescaped_response); response.PutCStringAsRawHex8(unescaped_response.GetData()); response.PutChar(';'); - } else if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to prepare a " - "jstopinfo field for pid %" PRIu64, - __FUNCTION__, m_debugged_process_sp->GetID()); + } else + LLDB_LOG(log, "failed to prepare a jstopinfo field for pid {0}", + m_debugged_process_up->GetID()); } + + uint32_t i = 0; + response.PutCString("thread-pcs"); + char delimiter = ':'; + for (NativeThreadProtocolSP thread_sp; + (thread_sp = m_debugged_process_up->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; + Status 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(';'); } // @@ -757,11 +768,11 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( } else if (reg_info_p->value_regs == nullptr) { // Only expediate registers that are not contained in other registers. RegisterValue reg_value; - Error error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value); + Status error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value); 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) @@ -924,7 +935,7 @@ void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() { bool interrupt = false; bool done = false; - Error error; + Status error; while (true) { const PacketResult result = GetPacketAndSendResponse( std::chrono::microseconds(0), error, interrupt, done); @@ -942,12 +953,12 @@ void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() { } } -Error GDBRemoteCommunicationServerLLGS::InitializeConnection( +Status GDBRemoteCommunicationServerLLGS::InitializeConnection( std::unique_ptr<Connection> &&connection) { IOObjectSP read_object_sp = connection->GetReadObject(); GDBRemoteCommunicationServer::SetConnection(connection.release()); - Error error; + Status error; m_network_handle_up = m_mainloop.RegisterReadObject( read_object_sp, [this](MainLoopBase &) { DataAvailableCallback(); }, error); @@ -969,8 +980,8 @@ GDBRemoteCommunicationServerLLGS::SendONotification(const char *buffer, return SendPacketNoLock(response.GetString()); } -Error GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor(int fd) { - Error error; +Status GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor(int fd) { + Status error; // Set up the reading/handling of process I/O std::unique_ptr<ConnectionFileDescriptor> conn_up( @@ -988,7 +999,7 @@ Error GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor(int fd) { return error; } - return Error(); + return Status(); } void GDBRemoteCommunicationServerLLGS::StartSTDIOForwarding() { @@ -996,7 +1007,7 @@ void GDBRemoteCommunicationServerLLGS::StartSTDIOForwarding() { if (!m_stdio_communication.IsConnected()) return; - Error error; + Status error; lldbassert(!m_stdio_handle_up); m_stdio_handle_up = m_mainloop.RegisterReadObject( m_stdio_communication.GetConnection()->GetReadObject(), @@ -1019,7 +1030,7 @@ void GDBRemoteCommunicationServerLLGS::StopSTDIOForwarding() { void GDBRemoteCommunicationServerLLGS::SendProcessOutput() { char buffer[1024]; ConnectionStatus status; - Error error; + Status error; while (true) { size_t bytes_read = m_stdio_communication.Read( buffer, sizeof buffer, std::chrono::microseconds(0), status, &error); @@ -1047,14 +1058,239 @@ void GDBRemoteCommunicationServerLLGS::SendProcessOutput() { } GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_jTraceStart( + StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + // Fail if we don't have a current process. + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse(68); + + if (!packet.ConsumeFront("jTraceStart:")) + return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet "); + + TraceOptions options; + uint64_t type = std::numeric_limits<uint64_t>::max(); + uint64_t buffersize = std::numeric_limits<uint64_t>::max(); + lldb::tid_t tid = LLDB_INVALID_THREAD_ID; + uint64_t metabuffersize = std::numeric_limits<uint64_t>::max(); + + auto json_object = StructuredData::ParseJSON(packet.Peek()); + + if (!json_object || + json_object->GetType() != lldb::eStructuredDataTypeDictionary) + return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet "); + + auto json_dict = json_object->GetAsDictionary(); + + json_dict->GetValueForKeyAsInteger("metabuffersize", metabuffersize); + options.setMetaDataBufferSize(metabuffersize); + + json_dict->GetValueForKeyAsInteger("buffersize", buffersize); + options.setTraceBufferSize(buffersize); + + json_dict->GetValueForKeyAsInteger("type", type); + options.setType(static_cast<lldb::TraceType>(type)); + + json_dict->GetValueForKeyAsInteger("threadid", tid); + options.setThreadID(tid); + + StructuredData::ObjectSP custom_params_sp = + json_dict->GetValueForKey("params"); + if (custom_params_sp && + custom_params_sp->GetType() != lldb::eStructuredDataTypeDictionary) + return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet "); + + options.setTraceParams( + static_pointer_cast<StructuredData::Dictionary>(custom_params_sp)); + + if (buffersize == std::numeric_limits<uint64_t>::max() || + type != lldb::TraceType::eTraceTypeProcessorTrace) { + LLDB_LOG(log, "Ill formed packet buffersize = {0} type = {1}", buffersize, + type); + return SendIllFormedResponse(packet, "JTrace:start: Ill formed packet "); + } + + Status error; + lldb::user_id_t uid = LLDB_INVALID_UID; + uid = m_debugged_process_up->StartTrace(options, error); + LLDB_LOG(log, "uid is {0} , error is {1}", uid, error.GetError()); + if (error.Fail()) + return SendErrorResponse(error); + + StreamGDBRemote response; + response.Printf("%" PRIx64, uid); + return SendPacketNoLock(response.GetString()); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_jTraceStop( + StringExtractorGDBRemote &packet) { + // Fail if we don't have a current process. + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse(68); + + if (!packet.ConsumeFront("jTraceStop:")) + return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet "); + + lldb::user_id_t uid = LLDB_INVALID_UID; + lldb::tid_t tid = LLDB_INVALID_THREAD_ID; + + auto json_object = StructuredData::ParseJSON(packet.Peek()); + + if (!json_object || + json_object->GetType() != lldb::eStructuredDataTypeDictionary) + return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet "); + + auto json_dict = json_object->GetAsDictionary(); + + if (!json_dict->GetValueForKeyAsInteger("traceid", uid)) + return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet "); + + json_dict->GetValueForKeyAsInteger("threadid", tid); + + Status error = m_debugged_process_up->StopTrace(uid, tid); + + if (error.Fail()) + return SendErrorResponse(error); + + return SendOKResponse(); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead( + StringExtractorGDBRemote &packet) { + + // Fail if we don't have a current process. + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse(68); + + if (!packet.ConsumeFront("jTraceConfigRead:")) + return SendIllFormedResponse(packet, + "jTraceConfigRead: Ill formed packet "); + + lldb::user_id_t uid = LLDB_INVALID_UID; + lldb::tid_t threadid = LLDB_INVALID_THREAD_ID; + + auto json_object = StructuredData::ParseJSON(packet.Peek()); + + if (!json_object || + json_object->GetType() != lldb::eStructuredDataTypeDictionary) + return SendIllFormedResponse(packet, + "jTraceConfigRead: Ill formed packet "); + + auto json_dict = json_object->GetAsDictionary(); + + if (!json_dict->GetValueForKeyAsInteger("traceid", uid)) + return SendIllFormedResponse(packet, + "jTraceConfigRead: Ill formed packet "); + + json_dict->GetValueForKeyAsInteger("threadid", threadid); + + TraceOptions options; + StreamGDBRemote response; + + options.setThreadID(threadid); + Status error = m_debugged_process_up->GetTraceConfig(uid, options); + + if (error.Fail()) + return SendErrorResponse(error); + + StreamGDBRemote escaped_response; + StructuredData::Dictionary json_packet; + + json_packet.AddIntegerItem("type", options.getType()); + json_packet.AddIntegerItem("buffersize", options.getTraceBufferSize()); + json_packet.AddIntegerItem("metabuffersize", options.getMetaDataBufferSize()); + + StructuredData::DictionarySP custom_params = options.getTraceParams(); + if (custom_params) + json_packet.AddItem("params", custom_params); + + StreamString json_string; + json_packet.Dump(json_string, false); + escaped_response.PutEscapedBytes(json_string.GetData(), + json_string.GetSize()); + return SendPacketNoLock(escaped_response.GetString()); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_jTraceRead( + StringExtractorGDBRemote &packet) { + + // Fail if we don't have a current process. + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse(68); + + enum PacketType { MetaData, BufferData }; + PacketType tracetype = MetaData; + + if (packet.ConsumeFront("jTraceBufferRead:")) + tracetype = BufferData; + else if (packet.ConsumeFront("jTraceMetaRead:")) + tracetype = MetaData; + else { + return SendIllFormedResponse(packet, "jTrace: Ill formed packet "); + } + + lldb::user_id_t uid = LLDB_INVALID_UID; + + uint64_t byte_count = std::numeric_limits<uint64_t>::max(); + lldb::tid_t tid = LLDB_INVALID_THREAD_ID; + uint64_t offset = std::numeric_limits<uint64_t>::max(); + + auto json_object = StructuredData::ParseJSON(packet.Peek()); + + if (!json_object || + json_object->GetType() != lldb::eStructuredDataTypeDictionary) + return SendIllFormedResponse(packet, "jTrace: Ill formed packet "); + + auto json_dict = json_object->GetAsDictionary(); + + if (!json_dict->GetValueForKeyAsInteger("traceid", uid) || + !json_dict->GetValueForKeyAsInteger("offset", offset) || + !json_dict->GetValueForKeyAsInteger("buffersize", byte_count)) + return SendIllFormedResponse(packet, "jTrace: Ill formed packet "); + + json_dict->GetValueForKeyAsInteger("threadid", tid); + + // Allocate the response buffer. + std::unique_ptr<uint8_t[]> buffer (new (std::nothrow) uint8_t[byte_count]); + if (!buffer) + return SendErrorResponse(0x78); + + StreamGDBRemote response; + Status error; + llvm::MutableArrayRef<uint8_t> buf(buffer.get(), byte_count); + + if (tracetype == BufferData) + error = m_debugged_process_up->GetData(uid, tid, buf, offset); + else if (tracetype == MetaData) + error = m_debugged_process_up->GetMetaData(uid, tid, buf, offset); + + if (error.Fail()) + return SendErrorResponse(error); + + for (auto i : buf) + response.PutHex8(i); + + StreamGDBRemote escaped_response; + escaped_response.PutEscapedBytes(response.GetData(), response.GetSize()); + return SendPacketNoLock(escaped_response.GetString()); +} + +GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo( StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. - if (!m_debugged_process_sp || - (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) return SendErrorResponse(68); - lldb::pid_t pid = m_debugged_process_sp->GetID(); + lldb::pid_t pid = m_debugged_process_up->GetID(); if (pid == LLDB_INVALID_PROCESS_ID) return SendErrorResponse(1); @@ -1071,16 +1307,16 @@ GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo( GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qC(StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. - if (!m_debugged_process_sp || - (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) return SendErrorResponse(68); // Make sure we set the current thread so g and p packets return // the data the gdb will expect. - lldb::tid_t tid = m_debugged_process_sp->GetCurrentThreadID(); + lldb::tid_t tid = m_debugged_process_up->GetCurrentThreadID(); SetCurrentThreadID(tid); - NativeThreadProtocolSP thread_sp = m_debugged_process_sp->GetCurrentThread(); + NativeThreadProtocolSP thread_sp = m_debugged_process_up->GetCurrentThread(); if (!thread_sp) return SendErrorResponse(69); @@ -1096,20 +1332,15 @@ GDBRemoteCommunicationServerLLGS::Handle_k(StringExtractorGDBRemote &packet) { StopSTDIOForwarding(); - if (!m_debugged_process_sp) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s No debugged process found.", - __FUNCTION__); + if (!m_debugged_process_up) { + LLDB_LOG(log, "No debugged process found."); return PacketResult::Success; } - Error error = m_debugged_process_sp->Kill(); - if (error.Fail() && log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to kill debugged " - "process %" PRIu64 ": %s", - __FUNCTION__, m_debugged_process_sp->GetID(), - error.AsCString()); + Status error = m_debugged_process_up->Kill(); + if (error.Fail()) + LLDB_LOG(log, "Failed to kill debugged process {0}: {1}", + m_debugged_process_up->GetID(), error); // No OK response for kill packet. // return SendOKResponse (); @@ -1157,7 +1388,7 @@ GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) { log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); // Ensure we have a native process. - if (!m_debugged_process_sp) { + if (!m_debugged_process_up) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s no debugged process " "shared pointer", @@ -1187,7 +1418,7 @@ GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) { } ResumeActionList resume_actions(StateType::eStateRunning, 0); - Error error; + Status error; // We have two branches: what to do if a continue thread is specified (in // which case we target @@ -1210,26 +1441,20 @@ GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) { } else { // Send the signal to the process since we weren't targeting a specific // continue thread with the signal. - error = m_debugged_process_sp->Signal(signo); + error = m_debugged_process_up->Signal(signo); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to send " - "signal for process %" PRIu64 ": %s", - __FUNCTION__, m_debugged_process_sp->GetID(), - error.AsCString()); + LLDB_LOG(log, "failed to send signal for process {0}: {1}", + m_debugged_process_up->GetID(), error); return SendErrorResponse(0x52); } } // Resume the threads. - error = m_debugged_process_sp->Resume(resume_actions); + error = m_debugged_process_up->Resume(resume_actions); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to resume " - "threads for process %" PRIu64 ": %s", - __FUNCTION__, m_debugged_process_sp->GetID(), - error.AsCString()); + LLDB_LOG(log, "failed to resume threads for process {0}: {1}", + m_debugged_process_up->GetID(), error); return SendErrorResponse(0x38); } @@ -1249,15 +1474,13 @@ GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) { // For now just support all continue. const bool has_continue_address = (packet.GetBytesLeft() > 0); if (has_continue_address) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s not implemented for " - "c{address} variant [%s remains]", - __FUNCTION__, packet.Peek()); + LLDB_LOG(log, "not implemented for c[address] variant [{0} remains]", + packet.Peek()); return SendUnimplementedResponse(packet.GetStringRef().c_str()); } // Ensure we have a native process. - if (!m_debugged_process_sp) { + if (!m_debugged_process_up) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s no debugged process " "shared pointer", @@ -1268,22 +1491,14 @@ GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) { // Build the ResumeActionList ResumeActionList actions(StateType::eStateRunning, 0); - Error error = m_debugged_process_sp->Resume(actions); + Status error = m_debugged_process_up->Resume(actions); if (error.Fail()) { - if (log) { - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s c failed for process %" PRIu64 - ": %s", - __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString()); - } + LLDB_LOG(log, "c failed for process {0}: {1}", + m_debugged_process_up->GetID(), error); return SendErrorResponse(GDBRemoteServerError::eErrorResume); } - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s continued process %" PRIu64, - __FUNCTION__, m_debugged_process_sp->GetID()); - + LLDB_LOG(log, "continued process {0}", m_debugged_process_up->GetID()); // No response required from continue. return PacketResult::Success; } @@ -1327,11 +1542,8 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont( } // Ensure we have a native process. - if (!m_debugged_process_sp) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s no debugged process " - "shared pointer", - __FUNCTION__); + if (!m_debugged_process_up) { + LLDB_LOG(log, "no debugged process"); return SendErrorResponse(0x36); } @@ -1392,44 +1604,30 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont( thread_actions.Append(thread_action); } - Error error = m_debugged_process_sp->Resume(thread_actions); + Status error = m_debugged_process_up->Resume(thread_actions); if (error.Fail()) { - if (log) { - log->Printf("GDBRemoteCommunicationServerLLGS::%s vCont failed for " - "process %" PRIu64 ": %s", - __FUNCTION__, m_debugged_process_sp->GetID(), - error.AsCString()); - } + LLDB_LOG(log, "vCont failed for process {0}: {1}", + m_debugged_process_up->GetID(), error); return SendErrorResponse(GDBRemoteServerError::eErrorResume); } - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s continued process %" PRIu64, - __FUNCTION__, m_debugged_process_sp->GetID()); - + LLDB_LOG(log, "continued process {0}", m_debugged_process_up->GetID()); // No response required from vCont. return PacketResult::Success; } void GDBRemoteCommunicationServerLLGS::SetCurrentThreadID(lldb::tid_t tid) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s setting current thread " - "id to %" PRIu64, - __FUNCTION__, tid); + LLDB_LOG(log, "setting current thread id to {0}", tid); m_current_tid = tid; - if (m_debugged_process_sp) - m_debugged_process_sp->SetCurrentThreadID(m_current_tid); + if (m_debugged_process_up) + m_debugged_process_up->SetCurrentThreadID(m_current_tid); } void GDBRemoteCommunicationServerLLGS::SetContinueThreadID(lldb::tid_t tid) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s setting continue thread " - "id to %" PRIu64, - __FUNCTION__, tid); + LLDB_LOG(log, "setting continue thread id to {0}", tid); m_continue_tid = tid; } @@ -1440,10 +1638,10 @@ GDBRemoteCommunicationServerLLGS::Handle_stop_reason( // Handle the $? gdbremote command. // If no process, indicate error - if (!m_debugged_process_sp) + if (!m_debugged_process_up) return SendErrorResponse(02); - return SendStopReasonForState(m_debugged_process_sp->GetState()); + return SendStopReasonForState(m_debugged_process_up->GetState()); } GDBRemoteCommunication::PacketResult @@ -1464,7 +1662,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReasonForState( case eStateSuspended: case eStateStopped: case eStateCrashed: { - lldb::tid_t tid = m_debugged_process_sp->GetCurrentThreadID(); + lldb::tid_t tid = m_debugged_process_up->GetCurrentThreadID(); // Make sure we set the current thread so g and p packets return // the data the gdb will expect. SetCurrentThreadID(tid); @@ -1474,15 +1672,11 @@ GDBRemoteCommunicationServerLLGS::SendStopReasonForState( case eStateInvalid: case eStateUnloaded: case eStateExited: - return SendWResponse(m_debugged_process_sp.get()); + return SendWResponse(m_debugged_process_up.get()); default: - if (log) { - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - ", current state reporting not handled: %s", - __FUNCTION__, m_debugged_process_sp->GetID(), - StateAsCString(process_state)); - } + LLDB_LOG(log, "pid {0}, current state reporting not handled: {1}", + m_debugged_process_up->GetID(), process_state); break; } @@ -1493,12 +1687,12 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo( StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. - if (!m_debugged_process_sp || - (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) return SendErrorResponse(68); // Ensure we have a thread. - NativeThreadProtocolSP thread_sp(m_debugged_process_sp->GetThreadAtIndex(0)); + NativeThreadProtocolSP thread_sp(m_debugged_process_up->GetThreadAtIndex(0)); if (!thread_sp) return SendErrorResponse(69); @@ -1702,47 +1896,33 @@ GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo( Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); // Fail if we don't have a current process. - if (!m_debugged_process_sp || - (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s() no process (%s), " - "returning OK", - __FUNCTION__, - m_debugged_process_sp ? "invalid process id" - : "null m_debugged_process_sp"); + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { + LLDB_LOG(log, "no process ({0}), returning OK", + m_debugged_process_up ? "invalid process id" + : "null m_debugged_process_up"); return SendOKResponse(); } StreamGDBRemote response; response.PutChar('m'); - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s() starting thread iteration", - __FUNCTION__); - + LLDB_LOG(log, "starting thread iteration"); NativeThreadProtocolSP thread_sp; uint32_t thread_index; for (thread_index = 0, - thread_sp = m_debugged_process_sp->GetThreadAtIndex(thread_index); + thread_sp = m_debugged_process_up->GetThreadAtIndex(thread_index); thread_sp; ++thread_index, - thread_sp = m_debugged_process_sp->GetThreadAtIndex(thread_index)) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s() iterated thread %" PRIu32 - "(%s, tid=0x%" PRIx64 ")", - __FUNCTION__, thread_index, thread_sp ? "is not null" : "null", - thread_sp ? thread_sp->GetID() : LLDB_INVALID_THREAD_ID); + thread_sp = m_debugged_process_up->GetThreadAtIndex(thread_index)) { + LLDB_LOG(log, "iterated thread {0}({1}, tid={2})", thread_index, + thread_sp ? "is not null" : "null", + thread_sp ? thread_sp->GetID() : LLDB_INVALID_THREAD_ID); if (thread_index > 0) response.PutChar(','); response.Printf("%" PRIx64, thread_sp->GetID()); } - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s() finished thread iteration", - __FUNCTION__); - + LLDB_LOG(log, "finished thread iteration"); return SendPacketNoLock(response.GetString()); } @@ -1783,11 +1963,10 @@ GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) { // Get the thread's register context. NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext()); if (!reg_context_sp) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 - " failed, no register context available for the thread", - __FUNCTION__, m_debugged_process_sp->GetID(), thread_sp->GetID()); + LLDB_LOG( + log, + "pid {0} tid {1} failed, no register context available for the thread", + m_debugged_process_up->GetID(), thread_sp->GetID()); return SendErrorResponse(0x15); } @@ -1817,7 +1996,7 @@ GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) { // Retrieve the value RegisterValue reg_value; - Error error = reg_context_sp->ReadRegister(reg_info, reg_value); + Status error = reg_context_sp->ReadRegister(reg_info, reg_value); if (error.Fail()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, read of " @@ -1870,8 +2049,8 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { // Get process architecture. ArchSpec process_arch; - if (!m_debugged_process_sp || - !m_debugged_process_sp->GetArchitecture(process_arch)) { + if (!m_debugged_process_up || + !m_debugged_process_up->GetArchitecture(process_arch)) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to retrieve " "inferior architecture", @@ -1900,7 +2079,7 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { log->Printf( "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " failed, no register context available for the thread", - __FUNCTION__, m_debugged_process_sp->GetID(), thread_sp->GetID()); + __FUNCTION__, m_debugged_process_up->GetID(), thread_sp->GetID()); return SendErrorResponse(0x15); } @@ -1937,7 +2116,7 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { StreamGDBRemote response; RegisterValue reg_value(reg_bytes, reg_size, process_arch.GetByteOrder()); - Error error = reg_context_sp->WriteRegister(reg_info, reg_value); + Status error = reg_context_sp->WriteRegister(reg_info, reg_value); if (error.Fail()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, write of " @@ -1954,8 +2133,8 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); // Fail if we don't have a current process. - if (!m_debugged_process_sp || - (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed, no process available", @@ -1998,7 +2177,7 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) { // Ensure we have the given thread when not specifying -1 (all threads) or 0 // (any thread). if (tid != LLDB_INVALID_THREAD_ID && tid != 0) { - NativeThreadProtocolSP thread_sp(m_debugged_process_sp->GetThreadByID(tid)); + NativeThreadProtocolSP thread_sp(m_debugged_process_up->GetThreadByID(tid)); if (!thread_sp) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64 @@ -2032,8 +2211,8 @@ GDBRemoteCommunicationServerLLGS::Handle_I(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); // Fail if we don't have a current process. - if (!m_debugged_process_sp || - (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed, no process available", @@ -2052,7 +2231,7 @@ GDBRemoteCommunicationServerLLGS::Handle_I(StringExtractorGDBRemote &packet) { // TODO: enqueue this block in circular buffer and send window size to // remote host ConnectionStatus status; - Error error; + Status error; m_stdio_communication.Write(tmp, read, status, &error); if (error.Fail()) { return SendErrorResponse(0x15); @@ -2068,30 +2247,21 @@ GDBRemoteCommunicationServerLLGS::Handle_interrupt( Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); // Fail if we don't have a current process. - if (!m_debugged_process_sp || - (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, no process available", - __FUNCTION__); + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { + LLDB_LOG(log, "failed, no process available"); return SendErrorResponse(0x15); } // Interrupt the process. - Error error = m_debugged_process_sp->Interrupt(); + Status error = m_debugged_process_up->Interrupt(); if (error.Fail()) { - if (log) { - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed for process %" PRIu64 - ": %s", - __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString()); - } + LLDB_LOG(log, "failed for process {0}: {1}", m_debugged_process_up->GetID(), + error); return SendErrorResponse(GDBRemoteServerError::eErrorResume); } - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s stopped process %" PRIu64, - __FUNCTION__, m_debugged_process_sp->GetID()); + LLDB_LOG(log, "stopped process {0}", m_debugged_process_up->GetID()); // No response required from stop all. return PacketResult::Success; @@ -2102,8 +2272,8 @@ GDBRemoteCommunicationServerLLGS::Handle_memory_read( StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (!m_debugged_process_sp || - (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed, no process available", @@ -2145,13 +2315,13 @@ GDBRemoteCommunicationServerLLGS::Handle_memory_read( // Retrieve the process memory. size_t bytes_read = 0; - Error error = m_debugged_process_sp->ReadMemoryWithoutTrap( + Status error = m_debugged_process_up->ReadMemoryWithoutTrap( read_addr, &buf[0], byte_count, bytes_read); if (error.Fail()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " mem 0x%" PRIx64 ": failed to read. Error: %s", - __FUNCTION__, m_debugged_process_sp->GetID(), read_addr, + __FUNCTION__, m_debugged_process_up->GetID(), read_addr, error.AsCString()); return SendErrorResponse(0x08); } @@ -2160,7 +2330,7 @@ GDBRemoteCommunicationServerLLGS::Handle_memory_read( if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " mem 0x%" PRIx64 ": read 0 of %" PRIu64 " requested bytes", - __FUNCTION__, m_debugged_process_sp->GetID(), read_addr, + __FUNCTION__, m_debugged_process_up->GetID(), read_addr, byte_count); return SendErrorResponse(0x08); } @@ -2183,8 +2353,8 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (!m_debugged_process_sp || - (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed, no process available", @@ -2212,10 +2382,7 @@ GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) { const uint64_t byte_count = packet.GetHexMaxU64(false, 0); if (byte_count == 0) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s nothing to write: " - "zero-length packet", - __FUNCTION__); + LLDB_LOG(log, "nothing to write: zero-length packet"); return PacketResult::Success; } @@ -2233,12 +2400,11 @@ GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) { StreamGDBRemote response; const uint64_t convert_count = packet.GetHexBytes(buf, 0); if (convert_count != byte_count) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " mem 0x%" PRIx64 ": asked to write %" PRIu64 - " bytes, but only found %" PRIu64 " to convert.", - __FUNCTION__, m_debugged_process_sp->GetID(), write_addr, - byte_count, convert_count); + LLDB_LOG(log, + "pid {0} mem {1:x}: asked to write {2} bytes, but only found {3} " + "to convert.", + m_debugged_process_up->GetID(), write_addr, byte_count, + convert_count); return SendIllFormedResponse(packet, "M content byte length specified did " "not match hex-encoded content " "length"); @@ -2246,23 +2412,17 @@ GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) { // Write the process memory. size_t bytes_written = 0; - Error error = m_debugged_process_sp->WriteMemory(write_addr, &buf[0], - byte_count, bytes_written); + Status error = m_debugged_process_up->WriteMemory(write_addr, &buf[0], + byte_count, bytes_written); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " mem 0x%" PRIx64 ": failed to write. Error: %s", - __FUNCTION__, m_debugged_process_sp->GetID(), write_addr, - error.AsCString()); + LLDB_LOG(log, "pid {0} mem {1:x}: failed to write. Error: {2}", + m_debugged_process_up->GetID(), write_addr, error); return SendErrorResponse(0x09); } if (bytes_written == 0) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " mem 0x%" PRIx64 ": wrote 0 of %" PRIu64 " requested bytes", - __FUNCTION__, m_debugged_process_sp->GetID(), write_addr, - byte_count); + LLDB_LOG(log, "pid {0} mem {1:x}: wrote 0 of {2} requested bytes", + m_debugged_process_up->GetID(), write_addr, byte_count); return SendErrorResponse(0x09); } @@ -2282,8 +2442,8 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported( // Ensure we have a process running; otherwise, we can't figure this out // since we won't have a NativeProcessProtocol. - if (!m_debugged_process_sp || - (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed, no process available", @@ -2293,8 +2453,8 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported( // Test if we can get any region back when asking for the region around NULL. MemoryRegionInfo region_info; - const Error error = - m_debugged_process_sp->GetMemoryRegionInfo(0, region_info); + const Status error = + m_debugged_process_up->GetMemoryRegionInfo(0, region_info); if (error.Fail()) { // We don't support memory region info collection for this // NativeProcessProtocol. @@ -2310,8 +2470,8 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo( Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); // Ensure we have a process. - if (!m_debugged_process_sp || - (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed, no process available", @@ -2331,8 +2491,8 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo( // Get the memory region info for the target address. MemoryRegionInfo region_info; - const Error error = - m_debugged_process_sp->GetMemoryRegionInfo(read_addr, region_info); + const Status error = + m_debugged_process_up->GetMemoryRegionInfo(read_addr, region_info); if (error.Fail()) { // Return the error message. @@ -2376,13 +2536,10 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo( GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) { // Ensure we have a process. - if (!m_debugged_process_sp || - (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, no process available", - __FUNCTION__); + LLDB_LOG(log, "failed, no process available"); return SendErrorResponse(0x15); } @@ -2449,29 +2606,23 @@ GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) { if (want_breakpoint) { // Try to set the breakpoint. - const Error error = - m_debugged_process_sp->SetBreakpoint(addr, size, want_hardware); + const Status error = + m_debugged_process_up->SetBreakpoint(addr, size, want_hardware); if (error.Success()) return SendOKResponse(); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " failed to set breakpoint: %s", - __FUNCTION__, m_debugged_process_sp->GetID(), - error.AsCString()); + LLDB_LOG(log, "pid {0} failed to set breakpoint: {1}", + m_debugged_process_up->GetID(), error); return SendErrorResponse(0x09); } else { // Try to set the watchpoint. - const Error error = m_debugged_process_sp->SetWatchpoint( + const Status error = m_debugged_process_up->SetWatchpoint( addr, size, watch_flags, want_hardware); if (error.Success()) return SendOKResponse(); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " failed to set watchpoint: %s", - __FUNCTION__, m_debugged_process_sp->GetID(), - error.AsCString()); + LLDB_LOG(log, "pid {0} failed to set watchpoint: {1}", + m_debugged_process_up->GetID(), error); return SendErrorResponse(0x09); } } @@ -2479,13 +2630,10 @@ GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) { GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) { // Ensure we have a process. - if (!m_debugged_process_sp || - (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, no process available", - __FUNCTION__); + LLDB_LOG(log, "failed, no process available"); return SendErrorResponse(0x15); } @@ -2496,12 +2644,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,27 +2694,22 @@ GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) { if (want_breakpoint) { // Try to clear the breakpoint. - const Error error = m_debugged_process_sp->RemoveBreakpoint(addr); + const Status error = + m_debugged_process_up->RemoveBreakpoint(addr, want_hardware); if (error.Success()) return SendOKResponse(); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " failed to remove breakpoint: %s", - __FUNCTION__, m_debugged_process_sp->GetID(), - error.AsCString()); + LLDB_LOG(log, "pid {0} failed to remove breakpoint: {1}", + m_debugged_process_up->GetID(), error); return SendErrorResponse(0x09); } else { // Try to clear the watchpoint. - const Error error = m_debugged_process_sp->RemoveWatchpoint(addr); + const Status error = m_debugged_process_up->RemoveWatchpoint(addr); if (error.Success()) return SendOKResponse(); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " failed to remove watchpoint: %s", - __FUNCTION__, m_debugged_process_sp->GetID(), - error.AsCString()); + LLDB_LOG(log, "pid {0} failed to remove watchpoint: {1}", + m_debugged_process_up->GetID(), error); return SendErrorResponse(0x09); } } @@ -2574,8 +2719,8 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); // Ensure we have a process. - if (!m_debugged_process_sp || - (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed, no process available", @@ -2594,7 +2739,7 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { // Double check that we have such a thread. // TODO investigate: on MacOSX we might need to do an UpdateThreads () here. - NativeThreadProtocolSP thread_sp = m_debugged_process_sp->GetThreadByID(tid); + NativeThreadProtocolSP thread_sp = m_debugged_process_up->GetThreadByID(tid); if (!thread_sp || thread_sp->GetID() != tid) return SendErrorResponse(0x33); @@ -2607,12 +2752,12 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { // All other threads stop while we're single stepping a thread. actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0); - Error error = m_debugged_process_sp->Resume(actions); + Status error = m_debugged_process_up->Resume(actions); if (error.Fail()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " Resume() failed with error: %s", - __FUNCTION__, m_debugged_process_sp->GetID(), tid, + __FUNCTION__, m_debugged_process_up->GetID(), tid, error.AsCString()); return SendErrorResponse(0x49); } @@ -2625,7 +2770,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,10 +2798,10 @@ 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)) { + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed, no process available", @@ -2665,55 +2810,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_up->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 @@ -2743,23 +2878,19 @@ GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState( // Grab the register context for the thread. NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext()); if (!reg_context_sp) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 - " failed, no register context available for the thread", - __FUNCTION__, m_debugged_process_sp->GetID(), thread_sp->GetID()); + LLDB_LOG( + log, + "pid {0} tid {1} failed, no register context available for the thread", + m_debugged_process_up->GetID(), thread_sp->GetID()); return SendErrorResponse(0x15); } // Save registers to a buffer. DataBufferSP register_data_sp; - Error error = reg_context_sp->ReadAllRegisterValues(register_data_sp); + Status error = reg_context_sp->ReadAllRegisterValues(register_data_sp); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " failed to save all register values: %s", - __FUNCTION__, m_debugged_process_sp->GetID(), - error.AsCString()); + LLDB_LOG(log, "pid {0} failed to save all register values: {1}", + m_debugged_process_up->GetID(), error); return SendErrorResponse(0x75); } @@ -2793,10 +2924,8 @@ GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState( const uint32_t save_id = packet.GetU32(0); if (save_id == 0) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s QRestoreRegisterState " - "packet has malformed save id, expecting decimal uint32_t", - __FUNCTION__); + LLDB_LOG(log, "QRestoreRegisterState packet has malformed save id, " + "expecting decimal uint32_t"); return SendErrorResponse(0x76); } @@ -2814,11 +2943,10 @@ GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState( // Grab the register context for the thread. NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext()); if (!reg_context_sp) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 - " failed, no register context available for the thread", - __FUNCTION__, m_debugged_process_sp->GetID(), thread_sp->GetID()); + LLDB_LOG( + log, + "pid {0} tid {1} failed, no register context available for the thread", + m_debugged_process_up->GetID(), thread_sp->GetID()); return SendErrorResponse(0x15); } @@ -2830,10 +2958,9 @@ GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState( // Find the register set buffer for the given save id. auto it = m_saved_registers_map.find(save_id); if (it == m_saved_registers_map.end()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " does not have a register set save buffer for id %" PRIu32, - __FUNCTION__, m_debugged_process_sp->GetID(), save_id); + LLDB_LOG(log, + "pid {0} does not have a register set save buffer for id {1}", + m_debugged_process_up->GetID(), save_id); return SendErrorResponse(0x77); } register_data_sp = it->second; @@ -2842,13 +2969,10 @@ GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState( m_saved_registers_map.erase(it); } - Error error = reg_context_sp->WriteAllRegisterValues(register_data_sp); + Status error = reg_context_sp->WriteAllRegisterValues(register_data_sp); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " failed to restore all register values: %s", - __FUNCTION__, m_debugged_process_sp->GetID(), - error.AsCString()); + LLDB_LOG(log, "pid {0} failed to restore all register values: {1}", + m_debugged_process_up->GetID(), error); return SendErrorResponse(0x77); } @@ -2877,7 +3001,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttach( "pid %" PRIu64, __FUNCTION__, pid); - Error error = AttachToProcess(pid); + Status error = AttachToProcess(pid); if (error.Fail()) { if (log) @@ -2888,7 +3012,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttach( } // Notify we attached by sending a stop packet. - return SendStopReasonForState(m_debugged_process_sp->GetState()); + return SendStopReasonForState(m_debugged_process_up->GetState()); } GDBRemoteCommunication::PacketResult @@ -2898,8 +3022,8 @@ GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) { StopSTDIOForwarding(); // Fail if we don't have a current process. - if (!m_debugged_process_sp || - (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed, no process available", @@ -2921,16 +3045,16 @@ GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) { return SendIllFormedResponse(packet, "D failed to parse the process id"); } - if (pid != LLDB_INVALID_PROCESS_ID && m_debugged_process_sp->GetID() != pid) { + if (pid != LLDB_INVALID_PROCESS_ID && m_debugged_process_up->GetID() != pid) { return SendIllFormedResponse(packet, "Invalid pid"); } - const Error error = m_debugged_process_sp->Detach(); + const Status error = m_debugged_process_up->Detach(); if (error.Fail()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to detach from " "pid %" PRIu64 ": %s\n", - __FUNCTION__, m_debugged_process_sp->GetID(), + __FUNCTION__, m_debugged_process_up->GetID(), error.AsCString()); return SendErrorResponse(0x01); } @@ -2961,24 +3085,18 @@ GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo( Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); // Ensure we have a debugged process. - if (!m_debugged_process_sp || - (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) return SendErrorResponse(50); - - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s preparing packet for pid " - "%" PRIu64, - __FUNCTION__, m_debugged_process_sp->GetID()); + LLDB_LOG(log, "preparing packet for pid {0}", m_debugged_process_up->GetID()); StreamString response; const bool threads_with_valid_stop_info_only = false; JSONArray::SP threads_array_sp = GetJSONThreadsInfo( - *m_debugged_process_sp, threads_with_valid_stop_info_only); + *m_debugged_process_up, threads_with_valid_stop_info_only); if (!threads_array_sp) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to prepare a " - "packet for pid %" PRIu64, - __FUNCTION__, m_debugged_process_sp->GetID()); + LLDB_LOG(log, "failed to prepare a packet for pid {0}", + m_debugged_process_up->GetID()); return SendErrorResponse(52); } @@ -2992,8 +3110,8 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo( StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. - if (!m_debugged_process_sp || - m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID) + if (!m_debugged_process_up || + m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID) return SendErrorResponse(68); packet.SetFilePos(strlen("qWatchpointSupportInfo")); @@ -3002,9 +3120,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_up->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()); } @@ -3012,8 +3135,8 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress( StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. - if (!m_debugged_process_sp || - m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID) + if (!m_debugged_process_up || + m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID) return SendErrorResponse(67); packet.SetFilePos(strlen("qFileLoadAddress:")); @@ -3024,8 +3147,8 @@ GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress( packet.GetHexByteString(file_name); lldb::addr_t file_load_address = LLDB_INVALID_ADDRESS; - Error error = - m_debugged_process_sp->GetFileLoadAddress(file_name, file_load_address); + Status error = + m_debugged_process_up->GetFileLoadAddress(file_name, file_load_address); if (error.Fail()) return SendErrorResponse(69); @@ -3037,6 +3160,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_up) + return SendErrorResponse(68); + + Status error = m_debugged_process_up->IgnoreSignals(signals); + if (error.Fail()) + return SendErrorResponse(69); + + return SendOKResponse(); +} + void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); @@ -3044,7 +3201,7 @@ void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() { if (m_stdio_communication.IsConnected()) { auto connection = m_stdio_communication.GetConnection(); if (connection) { - Error error; + Status error; connection->Disconnect(&error); if (error.Success()) { @@ -3067,8 +3224,8 @@ NativeThreadProtocolSP GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( NativeThreadProtocolSP thread_sp; // We have no thread if we don't have a process. - if (!m_debugged_process_sp || - m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID) + if (!m_debugged_process_up || + m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID) return thread_sp; // If the client hasn't asked for thread suffix support, there will not be a @@ -3080,9 +3237,9 @@ NativeThreadProtocolSP GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( return thread_sp; else if (current_tid == 0) { // Pick a thread. - return m_debugged_process_sp->GetThreadAtIndex(0); + return m_debugged_process_up->GetThreadAtIndex(0); } else - return m_debugged_process_sp->GetThreadByID(current_tid); + return m_debugged_process_up->GetThreadByID(current_tid); } Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); @@ -3112,7 +3269,7 @@ NativeThreadProtocolSP GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( packet.SetFilePos(packet.GetFilePos() + strlen("thread:")); const lldb::tid_t tid = packet.GetHexMaxU64(false, 0); if (tid != 0) - return m_debugged_process_sp->GetThreadByID(tid); + return m_debugged_process_up->GetThreadByID(tid); return thread_sp; } @@ -3122,9 +3279,9 @@ lldb::tid_t GDBRemoteCommunicationServerLLGS::GetCurrentThreadID() const { // Use whatever the debug process says is the current thread id // since the protocol either didn't specify or specified we want // any/all threads marked as the current thread. - if (!m_debugged_process_sp) + if (!m_debugged_process_up) return LLDB_INVALID_THREAD_ID; - return m_debugged_process_sp->GetCurrentThreadID(); + return m_debugged_process_up->GetCurrentThreadID(); } // Use the specific current thread id set by the gdb remote protocol. return m_current_tid; @@ -3136,28 +3293,18 @@ 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 GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string &module_path, const ArchSpec &arch) { - if (m_debugged_process_sp) { + if (m_debugged_process_up) { FileSpec file_spec; - if (m_debugged_process_sp + if (m_debugged_process_up ->GetLoadedModuleFileSpec(module_path.c_str(), file_spec) .Success()) { if (file_spec.Exists()) diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index fa52cda..7119947 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -39,7 +39,9 @@ public: //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ - GDBRemoteCommunicationServerLLGS(MainLoop &mainloop); + GDBRemoteCommunicationServerLLGS( + MainLoop &mainloop, + const NativeProcessProtocol::Factory &process_factory); //------------------------------------------------------------------ /// Specify the program to launch and its arguments. @@ -51,10 +53,10 @@ public: /// The number of elements in the args array of cstring pointers. /// /// @return - /// An Error object indicating the success or failure of making + /// An Status object indicating the success or failure of making /// the setting. //------------------------------------------------------------------ - Error SetLaunchArguments(const char *const args[], int argc); + Status SetLaunchArguments(const char *const args[], int argc); //------------------------------------------------------------------ /// Specify the launch flags for the process. @@ -63,10 +65,10 @@ public: /// The launch flags to use when launching this process. /// /// @return - /// An Error object indicating the success or failure of making + /// An Status object indicating the success or failure of making /// the setting. //------------------------------------------------------------------ - Error SetLaunchFlags(unsigned int launch_flags); + Status SetLaunchFlags(unsigned int launch_flags); //------------------------------------------------------------------ /// Launch a process with the current launch settings. @@ -76,10 +78,10 @@ public: /// with all the information for a child process to be launched. /// /// @return - /// An Error object indicating the success or failure of the + /// An Status object indicating the success or failure of the /// launch. //------------------------------------------------------------------ - Error LaunchProcess() override; + Status LaunchProcess() override; //------------------------------------------------------------------ /// Attach to a process. @@ -88,10 +90,10 @@ public: /// configured Platform. /// /// @return - /// An Error object indicating the success or failure of the + /// An Status object indicating the success or failure of the /// attach operation. //------------------------------------------------------------------ - Error AttachToProcess(lldb::pid_t pid); + Status AttachToProcess(lldb::pid_t pid); //------------------------------------------------------------------ // NativeProcessProtocol::NativeDelegate overrides @@ -103,25 +105,26 @@ public: void DidExec(NativeProcessProtocol *process) override; - Error InitializeConnection(std::unique_ptr<Connection> &&connection); + Status InitializeConnection(std::unique_ptr<Connection> &&connection); protected: MainLoop &m_mainloop; MainLoop::ReadHandleUP m_network_handle_up; - lldb::tid_t m_current_tid; - lldb::tid_t m_continue_tid; + const NativeProcessProtocol::Factory &m_process_factory; + lldb::tid_t m_current_tid = LLDB_INVALID_THREAD_ID; + lldb::tid_t m_continue_tid = LLDB_INVALID_THREAD_ID; std::recursive_mutex m_debugged_process_mutex; - NativeProcessProtocolSP m_debugged_process_sp; + std::unique_ptr<NativeProcessProtocol> m_debugged_process_up; Communication m_stdio_communication; MainLoop::ReadHandleUP m_stdio_handle_up; - lldb::StateType m_inferior_prev_state; - lldb::DataBufferSP m_active_auxv_buffer_sp; + lldb::StateType m_inferior_prev_state = lldb::StateType::eStateInvalid; + 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; - bool m_handshake_completed : 1; + uint32_t m_next_saved_registers_id = 1; + bool m_handshake_completed = false; PacketResult SendONotification(const char *buffer, uint32_t len); @@ -189,6 +192,14 @@ protected: PacketResult Handle_QSaveRegisterState(StringExtractorGDBRemote &packet); + PacketResult Handle_jTraceStart(StringExtractorGDBRemote &packet); + + PacketResult Handle_jTraceRead(StringExtractorGDBRemote &packet); + + PacketResult Handle_jTraceStop(StringExtractorGDBRemote &packet); + + PacketResult Handle_jTraceConfigRead(StringExtractorGDBRemote &packet); + PacketResult Handle_QRestoreRegisterState(StringExtractorGDBRemote &packet); PacketResult Handle_vAttach(StringExtractorGDBRemote &packet); @@ -203,6 +214,8 @@ protected: PacketResult Handle_qFileLoadAddress(StringExtractorGDBRemote &packet); + PacketResult Handle_QPassSignals(StringExtractorGDBRemote &packet); + void SetCurrentThreadID(lldb::tid_t tid); lldb::tid_t GetCurrentThreadID() const; @@ -211,7 +224,7 @@ protected: lldb::tid_t GetContinueThreadID() const { return m_continue_tid; } - Error SetSTDIOFileDescriptor(int fd); + Status SetSTDIOFileDescriptor(int fd); FileSpec FindModuleFile(const std::string &module_path, const ArchSpec &arch) override; diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp index 1106974..977c34c 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp +++ b/contrib/llvm/tools/lldb/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/StructuredData.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, Status &error, + bool &interrupt, bool &quit) { error.SetErrorString("interrupt received"); interrupt = true; return PacketResult::Success; @@ -95,7 +95,7 @@ GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform( //---------------------------------------------------------------------- GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() {} -Error GDBRemoteCommunicationServerPlatform::LaunchGDBServer( +Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer( const lldb_private::Args &args, std::string hostname, lldb::pid_t &pid, uint16_t &port, std::string &socket_name) { if (port == UINT16_MAX) @@ -147,7 +147,7 @@ Error GDBRemoteCommunicationServerPlatform::LaunchGDBServer( port_ptr = nullptr; } - Error error = StartDebugserverProcess( + Status error = StartDebugserverProcess( url.str().c_str(), nullptr, debugserver_launch_info, port_ptr, &args, -1); pid = debugserver_launch_info.GetProcessID(); @@ -192,7 +192,7 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer( lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; std::string socket_name; - Error error = + Status error = LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name); if (error.Fail()) { if (log) @@ -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(); } @@ -443,10 +439,10 @@ bool GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped( return true; } -Error GDBRemoteCommunicationServerPlatform::LaunchProcess() { +Status GDBRemoteCommunicationServerPlatform::LaunchProcess() { if (!m_process_launch_info.GetArguments().GetArgumentCount()) - return Error("%s: no process command line specified to launch", - __FUNCTION__); + return Status("%s: no process command line specified to launch", + __FUNCTION__); // specify the process monitor if not already set. This should // generally be what happens since we need to reap started @@ -458,7 +454,7 @@ Error GDBRemoteCommunicationServerPlatform::LaunchProcess() { this, std::placeholders::_1), false); - Error error = Host::LaunchProcess(m_process_launch_info); + Status error = Host::LaunchProcess(m_process_launch_info); if (!error.Success()) { fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__, m_process_launch_info.GetArguments().GetArgumentAtIndex(0)); @@ -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/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h index 472d86e..aed5106 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h @@ -34,7 +34,7 @@ public: ~GDBRemoteCommunicationServerPlatform() override; - Error LaunchProcess() override; + Status LaunchProcess() override; // Set both ports to zero to let the platform automatically bind to // a port chosen by the OS. @@ -61,9 +61,9 @@ public: void SetInferiorArguments(const lldb_private::Args &args); - Error LaunchGDBServer(const lldb_private::Args &args, std::string hostname, - lldb::pid_t &pid, uint16_t &port, - std::string &socket_name); + Status LaunchGDBServer(const lldb_private::Args &args, std::string hostname, + lldb::pid_t &pid, uint16_t &port, + std::string &socket_name); void SetPendingGdbServer(lldb::pid_t pid, uint16_t port, const std::string &socket_name); diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp index 27ce67d..612c714 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ b/contrib/llvm/tools/lldb/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" @@ -96,8 +95,8 @@ bool GDBRemoteRegisterContext::ReadRegister(const RegisterInfo *reg_info, // Read the register if (ReadRegisterBytes(reg_info, m_reg_data)) { const bool partial_data_ok = false; - Error error(value.SetValueFromData(reg_info, m_reg_data, - reg_info->byte_offset, partial_data_ok)); + Status error(value.SetValueFromData( + reg_info, m_reg_data, reg_info->byte_offset, partial_data_ok)); return error.Success(); } return false; diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h index 5b3e04e..8ef91af 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h +++ b/contrib/llvm/tools/lldb/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/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 4b4d62d..e46bbeb 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -16,6 +16,7 @@ #include <netinet/in.h> #include <sys/mman.h> // for mmap #include <sys/socket.h> +#include <unistd.h> #endif #include <sys/stat.h> #include <sys/types.h> @@ -35,14 +36,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/PosixApi.h" +#include "lldb/Host/PseudoTerminal.h" #include "lldb/Host/StringConvert.h" #include "lldb/Host/Symbols.h" #include "lldb/Host/ThreadLauncher.h" @@ -65,7 +65,9 @@ #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" +#include "lldb/Utility/Timer.h" // Project includes #include "GDBRemoteRegisterContext.h" @@ -80,6 +82,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" @@ -96,8 +99,8 @@ namespace lldb { // function and get the packet history dumped to a file. void DumpProcessGDBRemotePacketHistory(void *p, const char *path) { StreamFile strm; - Error error(strm.GetFile().Open(path, File::eOpenOptionWrite | - File::eOpenOptionCanCreate)); + Status error(strm.GetFile().Open(path, File::eOpenOptionWrite | + File::eOpenOptionCanCreate)); if (error.Success()) ((ProcessGDBRemote *)p)->GetGDBRemote().DumpHistory(strm); } @@ -323,7 +326,7 @@ bool ProcessGDBRemote::ParsePythonTargetDefinition( const FileSpec &target_definition_fspec) { ScriptInterpreter *interpreter = GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); - Error error; + Status error; StructuredData::ObjectSP module_object_sp( interpreter->LoadPluginModule(target_definition_fspec, error)); if (module_object_sp) { @@ -576,7 +579,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(); } } @@ -598,7 +601,7 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) { // gets called in DidAttach, when the target architecture (and // consequently the ABI we'll get from // the process) may be wrong. - ABISP abi_to_use = ABI::FindPlugin(arch_to_use); + ABISP abi_to_use = ABI::FindPlugin(shared_from_this(), arch_to_use); AugmentRegisterInfoViaABI(reg_info, reg_name, abi_to_use); @@ -638,23 +641,23 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) { m_register_info.Finalize(GetTarget().GetArchitecture()); } -Error ProcessGDBRemote::WillLaunch(Module *module) { +Status ProcessGDBRemote::WillLaunch(Module *module) { return WillLaunchOrAttach(); } -Error ProcessGDBRemote::WillAttachToProcessWithID(lldb::pid_t pid) { +Status ProcessGDBRemote::WillAttachToProcessWithID(lldb::pid_t pid) { return WillLaunchOrAttach(); } -Error ProcessGDBRemote::WillAttachToProcessWithName(const char *process_name, - bool wait_for_launch) { +Status ProcessGDBRemote::WillAttachToProcessWithName(const char *process_name, + bool wait_for_launch) { return WillLaunchOrAttach(); } -Error ProcessGDBRemote::DoConnectRemote(Stream *strm, - llvm::StringRef remote_url) { +Status ProcessGDBRemote::DoConnectRemote(Stream *strm, + llvm::StringRef remote_url) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - Error error(WillLaunchOrAttach()); + Status error(WillLaunchOrAttach()); if (error.Fail()) return error; @@ -743,8 +746,8 @@ Error ProcessGDBRemote::DoConnectRemote(Stream *strm, return error; } -Error ProcessGDBRemote::WillLaunchOrAttach() { - Error error; +Status ProcessGDBRemote::WillLaunchOrAttach() { + Status error; m_stdio_communication.Clear(); return error; } @@ -752,10 +755,10 @@ Error ProcessGDBRemote::WillLaunchOrAttach() { //---------------------------------------------------------------------- // Process Control //---------------------------------------------------------------------- -Error ProcessGDBRemote::DoLaunch(Module *exe_module, - ProcessLaunchInfo &launch_info) { +Status ProcessGDBRemote::DoLaunch(Module *exe_module, + ProcessLaunchInfo &launch_info) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - Error error; + Status error; if (log) log->Printf("ProcessGDBRemote::%s() entered", __FUNCTION__); @@ -964,8 +967,8 @@ Error ProcessGDBRemote::DoLaunch(Module *exe_module, return error; } -Error ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) { - Error error; +Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) { + Status error; // Only connect if we have a valid connect URL Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); @@ -1030,6 +1033,7 @@ Error ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) { m_gdb_comm.GetHostInfo(); m_gdb_comm.GetVContSupported('c'); m_gdb_comm.GetVAttachOrWaitSupported(); + m_gdb_comm.EnableErrorStringInPacket(); // Ask the remote server for the default thread id if (GetTarget().GetNonStopModeEnabled()) @@ -1168,10 +1172,10 @@ void ProcessGDBRemote::DidLaunch() { DidLaunchOrAttach(process_arch); } -Error ProcessGDBRemote::DoAttachToProcessWithID( +Status ProcessGDBRemote::DoAttachToProcessWithID( lldb::pid_t attach_pid, const ProcessAttachInfo &attach_info) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - Error error; + Status error; if (log) log->Printf("ProcessGDBRemote::%s()", __FUNCTION__); @@ -1196,9 +1200,9 @@ Error ProcessGDBRemote::DoAttachToProcessWithID( return error; } -Error ProcessGDBRemote::DoAttachToProcessWithName( +Status ProcessGDBRemote::DoAttachToProcessWithName( const char *process_name, const ProcessAttachInfo &attach_info) { - Error error; + Status error; // Clear out and clean up from any current state Clear(); @@ -1235,6 +1239,32 @@ Error ProcessGDBRemote::DoAttachToProcessWithName( return error; } +lldb::user_id_t ProcessGDBRemote::StartTrace(const TraceOptions &options, + Status &error) { + return m_gdb_comm.SendStartTracePacket(options, error); +} + +Status ProcessGDBRemote::StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id) { + return m_gdb_comm.SendStopTracePacket(uid, thread_id); +} + +Status ProcessGDBRemote::GetData(lldb::user_id_t uid, lldb::tid_t thread_id, + llvm::MutableArrayRef<uint8_t> &buffer, + size_t offset) { + return m_gdb_comm.SendGetDataPacket(uid, thread_id, buffer, offset); +} + +Status ProcessGDBRemote::GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id, + llvm::MutableArrayRef<uint8_t> &buffer, + size_t offset) { + return m_gdb_comm.SendGetMetaDataPacket(uid, thread_id, buffer, offset); +} + +Status ProcessGDBRemote::GetTraceConfig(lldb::user_id_t uid, + TraceOptions &options) { + return m_gdb_comm.SendGetTraceConfigPacket(uid, options); +} + void ProcessGDBRemote::DidExit() { // When we exit, disconnect from the GDB server communications m_gdb_comm.Disconnect(); @@ -1246,18 +1276,18 @@ void ProcessGDBRemote::DidAttach(ArchSpec &process_arch) { DidLaunchOrAttach(process_arch); } -Error ProcessGDBRemote::WillResume() { +Status ProcessGDBRemote::WillResume() { m_continue_c_tids.clear(); m_continue_C_tids.clear(); m_continue_s_tids.clear(); m_continue_S_tids.clear(); m_jstopinfo_sp.reset(); m_jthreadsinfo_sp.reset(); - return Error(); + return Status(); } -Error ProcessGDBRemote::DoResume() { - Error error; +Status ProcessGDBRemote::DoResume() { + Status error; Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); if (log) log->Printf("ProcessGDBRemote::Resume()"); @@ -1616,9 +1646,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 +1665,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 +1692,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 +1793,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; @@ -2118,9 +2142,9 @@ ProcessGDBRemote::SetThreadStopInfo(StructuredData::Dictionary *thread_dict) { if (mem_cache_dict->GetValueForKeyAsInteger<lldb::addr_t>( "address", mem_cache_addr)) { if (mem_cache_addr != LLDB_INVALID_ADDRESS) { - StringExtractor bytes; - if (mem_cache_dict->GetValueForKeyAsString( - "bytes", bytes.GetStringRef())) { + llvm::StringRef str; + if (mem_cache_dict->GetValueForKeyAsString("bytes", str)) { + StringExtractor bytes(str); bytes.SetFilePos(0); const size_t byte_size = bytes.GetStringRef().size() / 2; @@ -2405,8 +2429,8 @@ void ProcessGDBRemote::RefreshStateAfterStop() { m_thread_list_real.RefreshStateAfterStop(); } -Error ProcessGDBRemote::DoHalt(bool &caused_stop) { - Error error; +Status ProcessGDBRemote::DoHalt(bool &caused_stop) { + Status error; if (m_public_state.GetValue() == eStateAttaching) { // We are being asked to halt during an attach. We need to just close @@ -2417,8 +2441,8 @@ Error ProcessGDBRemote::DoHalt(bool &caused_stop) { return error; } -Error ProcessGDBRemote::DoDetach(bool keep_stopped) { - Error error; +Status ProcessGDBRemote::DoDetach(bool keep_stopped) { + Status error; Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); if (log) log->Printf("ProcessGDBRemote::DoDetach(keep_stopped: %i)", keep_stopped); @@ -2446,8 +2470,8 @@ Error ProcessGDBRemote::DoDetach(bool keep_stopped) { return error; } -Error ProcessGDBRemote::DoDestroy() { - Error error; +Status ProcessGDBRemote::DoDestroy() { + Status error; Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); if (log) log->Printf("ProcessGDBRemote::DoDestroy()"); @@ -2729,18 +2753,21 @@ void ProcessGDBRemote::WillPublicStop() { // Process Memory //------------------------------------------------------------------ size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size, - Error &error) { + Status &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,13 +2812,15 @@ 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) { + size_t size, Status &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; @@ -2824,7 +2853,7 @@ size_t ProcessGDBRemote::DoWriteMemory(addr_t addr, const void *buf, lldb::addr_t ProcessGDBRemote::DoAllocateMemory(size_t size, uint32_t permissions, - Error &error) { + Status &error) { Log *log( GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_EXPRESSIONS)); addr_t allocated_addr = LLDB_INVALID_ADDRESS; @@ -2868,27 +2897,27 @@ lldb::addr_t ProcessGDBRemote::DoAllocateMemory(size_t size, return allocated_addr; } -Error ProcessGDBRemote::GetMemoryRegionInfo(addr_t load_addr, - MemoryRegionInfo ®ion_info) { +Status ProcessGDBRemote::GetMemoryRegionInfo(addr_t load_addr, + MemoryRegionInfo ®ion_info) { - Error error(m_gdb_comm.GetMemoryRegionInfo(load_addr, region_info)); + Status error(m_gdb_comm.GetMemoryRegionInfo(load_addr, region_info)); return error; } -Error ProcessGDBRemote::GetWatchpointSupportInfo(uint32_t &num) { +Status ProcessGDBRemote::GetWatchpointSupportInfo(uint32_t &num) { - Error error(m_gdb_comm.GetWatchpointSupportInfo(num)); + Status error(m_gdb_comm.GetWatchpointSupportInfo(num)); return error; } -Error ProcessGDBRemote::GetWatchpointSupportInfo(uint32_t &num, bool &after) { - Error error(m_gdb_comm.GetWatchpointSupportInfo( +Status ProcessGDBRemote::GetWatchpointSupportInfo(uint32_t &num, bool &after) { + Status error(m_gdb_comm.GetWatchpointSupportInfo( num, after, GetTarget().GetArchitecture())); return error; } -Error ProcessGDBRemote::DoDeallocateMemory(lldb::addr_t addr) { - Error error; +Status ProcessGDBRemote::DoDeallocateMemory(lldb::addr_t addr) { + Status error; LazyBool supported = m_gdb_comm.SupportsAllocDeallocMemory(); switch (supported) { @@ -2926,7 +2955,7 @@ Error ProcessGDBRemote::DoDeallocateMemory(lldb::addr_t addr) { // Process STDIO //------------------------------------------------------------------ size_t ProcessGDBRemote::PutSTDIN(const char *src, size_t src_len, - Error &error) { + Status &error) { if (m_stdio_communication.IsConnected()) { ConnectionStatus status; m_stdio_communication.Write(src, src_len, status, NULL); @@ -2936,8 +2965,8 @@ size_t ProcessGDBRemote::PutSTDIN(const char *src, size_t src_len, return 0; } -Error ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) { - Error error; +Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) { + Status error; assert(bp_site != NULL); // Get logging info @@ -3074,8 +3103,8 @@ Error ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) { return EnableSoftwareBreakpoint(bp_site); } -Error ProcessGDBRemote::DisableBreakpointSite(BreakpointSite *bp_site) { - Error error; +Status ProcessGDBRemote::DisableBreakpointSite(BreakpointSite *bp_site) { + Status error; assert(bp_site != NULL); addr_t addr = bp_site->GetLoadAddress(); user_id_t site_id = bp_site->GetID(); @@ -3143,8 +3172,8 @@ static GDBStoppointType GetGDBStoppointType(Watchpoint *wp) { return eWatchpointWrite; } -Error ProcessGDBRemote::EnableWatchpoint(Watchpoint *wp, bool notify) { - Error error; +Status ProcessGDBRemote::EnableWatchpoint(Watchpoint *wp, bool notify) { + Status error; if (wp) { user_id_t watchID = wp->GetID(); addr_t addr = wp->GetLoadAddress(); @@ -3180,8 +3209,8 @@ Error ProcessGDBRemote::EnableWatchpoint(Watchpoint *wp, bool notify) { return error; } -Error ProcessGDBRemote::DisableWatchpoint(Watchpoint *wp, bool notify) { - Error error; +Status ProcessGDBRemote::DisableWatchpoint(Watchpoint *wp, bool notify) { + Status error; if (wp) { user_id_t watchID = wp->GetID(); @@ -3233,8 +3262,8 @@ void ProcessGDBRemote::Clear() { m_thread_list.Clear(); } -Error ProcessGDBRemote::DoSignal(int signo) { - Error error; +Status ProcessGDBRemote::DoSignal(int signo) { + Status error; Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); if (log) log->Printf("ProcessGDBRemote::DoSignal (signal = %d)", signo); @@ -3244,15 +3273,15 @@ Error ProcessGDBRemote::DoSignal(int signo) { return error; } -Error ProcessGDBRemote::EstablishConnectionIfNeeded( - const ProcessInfo &process_info) { +Status +ProcessGDBRemote::EstablishConnectionIfNeeded(const ProcessInfo &process_info) { // Make sure we aren't already connected? if (m_gdb_comm.IsConnected()) - return Error(); + return Status(); PlatformSP platform_sp(GetTarget().GetPlatform()); if (platform_sp && !platform_sp->IsHost()) - return Error("Lost debug server connection"); + return Status("Lost debug server connection"); auto error = LaunchAndConnectToDebugserver(process_info); if (error.Fail()) { @@ -3279,11 +3308,11 @@ static bool SetCloexecFlag(int fd) { } #endif -Error ProcessGDBRemote::LaunchAndConnectToDebugserver( +Status ProcessGDBRemote::LaunchAndConnectToDebugserver( const ProcessInfo &process_info) { using namespace std::placeholders; // For _1, _2, etc. - Error error; + Status error; if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID) { // If we locate debugserver, keep that located version around static FileSpec g_debugserver_file_spec; @@ -3429,9 +3458,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); @@ -3741,6 +3770,43 @@ bool ProcessGDBRemote::NewThreadNotifyBreakpointHit( return false; } +Status 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 Status(); + + // No signals, nothing to send. + if (m_unix_signals_sp == nullptr) + return Status(); + + // 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 Status(); + } + + auto signals_to_ignore = + m_unix_signals_sp->GetFilteredSignals(false, false, false); + Status 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) { @@ -3785,11 +3851,11 @@ DynamicLoader *ProcessGDBRemote::GetDynamicLoader() { return m_dyld_ap.get(); } -Error ProcessGDBRemote::SendEventData(const char *data) { +Status ProcessGDBRemote::SendEventData(const char *data) { int return_value; bool was_supported; - Error error; + Status error; return_value = m_gdb_comm.SendLaunchEventDataPacket(data, &was_supported); if (return_value != 0) { @@ -3960,7 +4026,7 @@ StructuredData::ObjectSP ProcessGDBRemote::GetSharedCacheInfo() { return object_sp; } -Error ProcessGDBRemote::ConfigureStructuredData( +Status ProcessGDBRemote::ConfigureStructuredData( const ConstString &type_name, const StructuredData::ObjectSP &config_sp) { return m_gdb_comm.ConfigureRemoteStructuredData(type_name, config_sp); } @@ -3990,6 +4056,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; @@ -4134,8 +4215,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") { @@ -4215,7 +4295,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()); @@ -4283,7 +4363,7 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) { // request the target xml file std::string raw; - lldb_private::Error lldberr; + lldb_private::Status lldberr; if (!comm.ReadExtFeature(ConstString("features"), ConstString("target.xml"), raw, lldberr)) { return false; @@ -4297,7 +4377,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") { @@ -4344,7 +4424,7 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) { // that context we haven't // set the Target's architecture yet, so the ABI is also potentially // incorrect. - ABISP abi_to_use_sp = ABI::FindPlugin(arch_to_use); + ABISP abi_to_use_sp = ABI::FindPlugin(shared_from_this(), arch_to_use); if (feature_node) { ParseRegisters(feature_node, target_info, this->m_register_info, abi_to_use_sp, cur_reg_num, reg_offset); @@ -4375,10 +4455,10 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) { return m_register_info.GetNumRegisters() > 0; } -Error ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) { +Status ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) { // Make sure LLDB has an XML parser it can use first if (!XMLDocument::XMLEnabled()) - return Error(0, ErrorType::eErrorTypeGeneric); + return Status(0, ErrorType::eErrorTypeGeneric); Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS); if (log) @@ -4392,11 +4472,11 @@ Error ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) { // request the loaded library list std::string raw; - lldb_private::Error lldberr; + lldb_private::Status lldberr; if (!comm.ReadExtFeature(ConstString("libraries-svr4"), ConstString(""), raw, lldberr)) - return Error(0, ErrorType::eErrorTypeGeneric); + return Status(0, ErrorType::eErrorTypeGeneric); // parse the xml file in memory if (log) @@ -4404,11 +4484,11 @@ Error ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) { XMLDocument doc; if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml")) - return Error(0, ErrorType::eErrorTypeGeneric); + return Status(0, ErrorType::eErrorTypeGeneric); XMLNode root_element = doc.GetRootElement("library-list-svr4"); if (!root_element) - return Error(); + return Status(); // main link map structure llvm::StringRef main_lm = root_element.GetAttributeValue("main-lm"); @@ -4423,8 +4503,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()); @@ -4479,22 +4559,22 @@ Error ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) { // request the loaded library list std::string raw; - lldb_private::Error lldberr; + lldb_private::Status lldberr; if (!comm.ReadExtFeature(ConstString("libraries"), ConstString(""), raw, lldberr)) - return Error(0, ErrorType::eErrorTypeGeneric); + return Status(0, ErrorType::eErrorTypeGeneric); if (log) log->Printf("parsing: %s", raw.c_str()); XMLDocument doc; if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml")) - return Error(0, ErrorType::eErrorTypeGeneric); + return Status(0, ErrorType::eErrorTypeGeneric); XMLNode root_element = doc.GetRootElement("library-list"); if (!root_element) - return Error(); + return Status(); root_element.ForEachChildElementWithName( "library", [log, &list](const XMLNode &library) -> bool { @@ -4535,10 +4615,10 @@ Error ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) { log->Printf("found %" PRId32 " modules in total", (int)list.m_list.size()); } else { - return Error(0, ErrorType::eErrorTypeGeneric); + return Status(0, ErrorType::eErrorTypeGeneric); } - return Error(); + return Status(); } lldb::ModuleSP ProcessGDBRemote::LoadModuleAtAddress(const FileSpec &file, @@ -4637,15 +4717,15 @@ size_t ProcessGDBRemote::LoadModules() { return LoadModules(module_list); } -Error ProcessGDBRemote::GetFileLoadAddress(const FileSpec &file, - bool &is_loaded, - lldb::addr_t &load_addr) { +Status ProcessGDBRemote::GetFileLoadAddress(const FileSpec &file, + bool &is_loaded, + lldb::addr_t &load_addr) { is_loaded = false; load_addr = LLDB_INVALID_ADDRESS; std::string file_path = file.GetPath(false); if (file_path.empty()) - return Error("Empty file name specified"); + return Status("Empty file name specified"); StreamString packet; packet.PutCString("qFileLoadAddress:"); @@ -4655,27 +4735,28 @@ Error ProcessGDBRemote::GetFileLoadAddress(const FileSpec &file, if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response, false) != GDBRemoteCommunication::PacketResult::Success) - return Error("Sending qFileLoadAddress packet failed"); + return Status("Sending qFileLoadAddress packet failed"); if (response.IsErrorResponse()) { if (response.GetError() == 1) { // The file is not loaded into the inferior is_loaded = false; load_addr = LLDB_INVALID_ADDRESS; - return Error(); + return Status(); } - return Error( + return Status( "Fetching file load address from remote server returned an error"); } if (response.IsNormalResponse()) { is_loaded = true; load_addr = response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); - return Error(); + return Status(); } - return Error("Unknown error happened during sending the load address packet"); + return Status( + "Unknown error happened during sending the load address packet"); } void ProcessGDBRemote::ModulesDidLoad(ModuleList &module_list) { diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 6423abc..54a472d 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -22,18 +22,19 @@ // 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/Status.h" +#include "lldb/Utility/StreamGDBRemote.h" +#include "lldb/Utility/StreamString.h" #include "lldb/Utility/StringExtractor.h" +#include "lldb/Utility/StringList.h" +#include "lldb/Utility/StructuredData.h" #include "lldb/lldb-private-forward.h" #include "GDBRemoteCommunicationClient.h" @@ -78,25 +79,25 @@ public: //------------------------------------------------------------------ // Creating a new process, or attaching to an existing one //------------------------------------------------------------------ - Error WillLaunch(Module *module) override; + Status WillLaunch(Module *module) override; - Error DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) override; + Status DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) override; void DidLaunch() override; - Error WillAttachToProcessWithID(lldb::pid_t pid) override; + Status WillAttachToProcessWithID(lldb::pid_t pid) override; - Error WillAttachToProcessWithName(const char *process_name, - bool wait_for_launch) override; + Status WillAttachToProcessWithName(const char *process_name, + bool wait_for_launch) override; - Error DoConnectRemote(Stream *strm, llvm::StringRef remote_url) override; + Status DoConnectRemote(Stream *strm, llvm::StringRef remote_url) override; - Error WillLaunchOrAttach(); + Status WillLaunchOrAttach(); - Error DoAttachToProcessWithID(lldb::pid_t pid, - const ProcessAttachInfo &attach_info) override; + Status DoAttachToProcessWithID(lldb::pid_t pid, + const ProcessAttachInfo &attach_info) override; - Error + Status DoAttachToProcessWithName(const char *process_name, const ProcessAttachInfo &attach_info) override; @@ -112,19 +113,19 @@ public: //------------------------------------------------------------------ // Process Control //------------------------------------------------------------------ - Error WillResume() override; + Status WillResume() override; - Error DoResume() override; + Status DoResume() override; - Error DoHalt(bool &caused_stop) override; + Status DoHalt(bool &caused_stop) override; - Error DoDetach(bool keep_stopped) override; + Status DoDetach(bool keep_stopped) override; bool DetachRequiresHalt() override { return true; } - Error DoSignal(int signal) override; + Status DoSignal(int signal) override; - Error DoDestroy() override; + Status DoDestroy() override; void RefreshStateAfterStop() override; @@ -143,41 +144,56 @@ public: // Process Memory //------------------------------------------------------------------ size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, - Error &error) override; + Status &error) override; size_t DoWriteMemory(lldb::addr_t addr, const void *buf, size_t size, - Error &error) override; + Status &error) override; lldb::addr_t DoAllocateMemory(size_t size, uint32_t permissions, - Error &error) override; + Status &error) override; - Error GetMemoryRegionInfo(lldb::addr_t load_addr, - MemoryRegionInfo ®ion_info) override; + Status GetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo ®ion_info) override; - Error DoDeallocateMemory(lldb::addr_t ptr) override; + Status DoDeallocateMemory(lldb::addr_t ptr) override; //------------------------------------------------------------------ // Process STDIO //------------------------------------------------------------------ - size_t PutSTDIN(const char *buf, size_t buf_size, Error &error) override; + size_t PutSTDIN(const char *buf, size_t buf_size, Status &error) override; //---------------------------------------------------------------------- // Process Breakpoints //---------------------------------------------------------------------- - Error EnableBreakpointSite(BreakpointSite *bp_site) override; + Status EnableBreakpointSite(BreakpointSite *bp_site) override; - Error DisableBreakpointSite(BreakpointSite *bp_site) override; + Status DisableBreakpointSite(BreakpointSite *bp_site) override; //---------------------------------------------------------------------- // Process Watchpoints //---------------------------------------------------------------------- - Error EnableWatchpoint(Watchpoint *wp, bool notify = true) override; + Status EnableWatchpoint(Watchpoint *wp, bool notify = true) override; - Error DisableWatchpoint(Watchpoint *wp, bool notify = true) override; + Status DisableWatchpoint(Watchpoint *wp, bool notify = true) override; - Error GetWatchpointSupportInfo(uint32_t &num) override; + Status GetWatchpointSupportInfo(uint32_t &num) override; - Error GetWatchpointSupportInfo(uint32_t &num, bool &after) override; + lldb::user_id_t StartTrace(const TraceOptions &options, + Status &error) override; + + Status StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id) override; + + Status GetData(lldb::user_id_t uid, lldb::tid_t thread_id, + llvm::MutableArrayRef<uint8_t> &buffer, + size_t offset = 0) override; + + Status GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id, + llvm::MutableArrayRef<uint8_t> &buffer, + size_t offset = 0) override; + + Status GetTraceConfig(lldb::user_id_t uid, TraceOptions &options) override; + + Status GetWatchpointSupportInfo(uint32_t &num, bool &after) override; bool StartNoticingNewThreads() override; @@ -185,7 +201,7 @@ public: GDBRemoteCommunicationClient &GetGDBRemote() { return m_gdb_comm; } - Error SendEventData(const char *data) override; + Status SendEventData(const char *data) override; //---------------------------------------------------------------------- // Override DidExit so we can disconnect from the remote GDB server @@ -207,8 +223,8 @@ public: size_t LoadModules() override; - Error GetFileLoadAddress(const FileSpec &file, bool &is_loaded, - lldb::addr_t &load_addr) override; + Status GetFileLoadAddress(const FileSpec &file, bool &is_loaded, + lldb::addr_t &load_addr) override; void ModulesDidLoad(ModuleList &module_list) override; @@ -216,7 +232,7 @@ public: GetLoadedDynamicLibrariesInfos(lldb::addr_t image_list_address, lldb::addr_t image_count) override; - Error + Status ConfigureStructuredData(const ConstString &type_name, const StructuredData::ObjectSP &config_sp) override; @@ -315,9 +331,9 @@ protected: bool UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) override; - Error EstablishConnectionIfNeeded(const ProcessInfo &process_info); + Status EstablishConnectionIfNeeded(const ProcessInfo &process_info); - Error LaunchAndConnectToDebugserver(const ProcessInfo &process_info); + Status LaunchAndConnectToDebugserver(const ProcessInfo &process_info); void KillDebugserverProcess(); @@ -379,7 +395,7 @@ protected: void DidLaunchOrAttach(ArchSpec &process_arch); - Error ConnectToDebugserver(llvm::StringRef host_port); + Status ConnectToDebugserver(llvm::StringRef host_port); const char *GetDispatchQueueNameForThread(lldb::addr_t thread_dispatch_qaddr, std::string &dispatch_queue_name); @@ -390,19 +406,22 @@ protected: bool GetGDBServerRegisterInfo(ArchSpec &arch); // Query remote GDBServer for a detailed loaded library list - Error GetLoadedModuleList(LoadedModuleInfoList &); + Status GetLoadedModuleList(LoadedModuleInfoList &); lldb::ModuleSP LoadModuleAtAddress(const FileSpec &file, lldb::addr_t link_map, lldb::addr_t base_addr, bool value_is_offset); + Status 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 +436,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/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp index 899037a..8f16b83 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp +++ b/contrib/llvm/tools/lldb/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/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h index f5e92b4..3c58011 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h +++ b/contrib/llvm/tools/lldb/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/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp index ab55214..5197e8f 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/contrib/llvm/tools/lldb/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(); } diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h index 27caf42..1a5b60a 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h @@ -16,9 +16,9 @@ // Other libraries and framework includes // Project includes -#include "lldb/Core/StructuredData.h" #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/StructuredData.h" class StringExtractor; |