diff options
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote')
15 files changed, 139 insertions, 109 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 144ae103faa4..7cea013eea7f 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -31,6 +31,7 @@ #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/RegularExpression.h" +#include "lldb/Utility/Reproducer.h" #include "lldb/Utility/StreamString.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/ScopedPrinter.h" @@ -49,7 +50,7 @@ #include <compression.h> #endif -#if defined(HAVE_LIBZ) +#if LLVM_ENABLE_ZLIB #include <zlib.h> #endif @@ -581,7 +582,7 @@ bool GDBRemoteCommunication::DecompressPacket() { } #endif -#if defined(HAVE_LIBZ) +#if LLVM_ENABLE_ZLIB if (decompressed_bytes == 0 && decompressed_bufsize != ULONG_MAX && decompressed_buffer != nullptr && m_compression_type == CompressionType::ZlibDeflate) { @@ -1243,8 +1244,9 @@ Status GDBRemoteCommunication::StartDebugserverProcess( void GDBRemoteCommunication::DumpHistory(Stream &strm) { m_history.Dump(strm); } -void GDBRemoteCommunication::SetHistoryStream(llvm::raw_ostream *strm) { - m_history.SetStream(strm); +void GDBRemoteCommunication::SetPacketRecorder( + repro::PacketRecorder *recorder) { + m_history.SetRecorder(recorder); } llvm::Error diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h index bb777a5c26a7..0b670018bd69 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -27,6 +27,9 @@ #include "lldb/lldb-public.h" namespace lldb_private { +namespace repro { +class PacketRecorder; +} namespace process_gdb_remote { enum GDBStoppointType { @@ -133,7 +136,8 @@ public: // fork/exec to avoid having to connect/accept void DumpHistory(Stream &strm); - void SetHistoryStream(llvm::raw_ostream *strm); + + void SetPacketRecorder(repro::PacketRecorder *recorder); static llvm::Error ConnectLocally(GDBRemoteCommunication &client, GDBRemoteCommunication &server); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index feb9f0589cee..b2f1ee527e8b 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -543,21 +543,24 @@ GDBRemoteCommunicationClient::SendThreadSpecificPacketAndWaitForResponse( // // Takes a valid thread ID because p needs to apply to a thread. bool GDBRemoteCommunicationClient::GetpPacketSupported(lldb::tid_t tid) { - if (m_supports_p == eLazyBoolCalculate) { - m_supports_p = eLazyBoolNo; - StreamString payload; - payload.PutCString("p0"); - StringExtractorGDBRemote response; - if (SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), - response, false) == - PacketResult::Success && - response.IsNormalResponse()) { - m_supports_p = eLazyBoolYes; - } - } + if (m_supports_p == eLazyBoolCalculate) + m_supports_p = GetThreadPacketSupported(tid, "p0"); return m_supports_p; } +LazyBool GDBRemoteCommunicationClient::GetThreadPacketSupported( + lldb::tid_t tid, llvm::StringRef packetStr) { + StreamString payload; + payload.PutCString(packetStr); + StringExtractorGDBRemote response; + if (SendThreadSpecificPacketAndWaitForResponse( + tid, std::move(payload), response, false) == PacketResult::Success && + response.IsNormalResponse()) { + return eLazyBoolYes; + } + return eLazyBoolNo; +} + StructuredData::ObjectSP GDBRemoteCommunicationClient::GetThreadsInfo() { // Get information on all threads at one using the "jThreadsInfo" packet StructuredData::ObjectSP object_sp; @@ -1042,7 +1045,7 @@ void GDBRemoteCommunicationClient::MaybeEnableCompression( } #endif -#if defined(HAVE_LIBZ) +#if LLVM_ENABLE_ZLIB if (avail_type == CompressionType::None) { for (auto compression : supported_compressions) { if (compression == "zlib-deflate") { @@ -3737,7 +3740,7 @@ bool GDBRemoteCommunicationClient::ReadExtFeature( case ('m'): if (str.length() > 1) output << &str[1]; - offset += size; + offset += str.length() - 1; break; // unknown chunk diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 574cd0fd70c5..11fd40bce44f 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -89,7 +89,7 @@ public: /// Sends a GDB remote protocol 'A' packet that delivers program /// arguments to the remote server. /// - /// \param[in] argv + /// \param[in] launch_info /// A NULL terminated array of const C strings to use as the /// arguments. /// @@ -155,7 +155,7 @@ public: /// Sets the path to use for stdin/out/err for a process /// that will be launched with the 'A' packet. /// - /// \param[in] path + /// \param[in] file_spec /// The path to use for stdin/out/err /// /// \return @@ -596,6 +596,8 @@ protected: Status GetQXferMemoryMapRegionInfo(lldb::addr_t addr, MemoryRegionInfo ®ion); + LazyBool GetThreadPacketSupported(lldb::tid_t tid, llvm::StringRef packetStr); + private: DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationClient); }; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp index d2cc32f63f20..9e5646985f87 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp @@ -40,8 +40,8 @@ void GDBRemoteCommunicationHistory::AddPacket(char packet_char, m_packets[idx].bytes_transmitted = bytes_transmitted; m_packets[idx].packet_idx = m_total_packet_count; m_packets[idx].tid = llvm::get_threadid(); - if (m_stream) - m_packets[idx].Serialize(*m_stream); + if (m_recorder) + m_recorder->Record(m_packets[idx]); } void GDBRemoteCommunicationHistory::AddPacket(const std::string &src, @@ -58,8 +58,8 @@ void GDBRemoteCommunicationHistory::AddPacket(const std::string &src, m_packets[idx].bytes_transmitted = bytes_transmitted; m_packets[idx].packet_idx = m_total_packet_count; m_packets[idx].tid = llvm::get_threadid(); - if (m_stream) - m_packets[idx].Serialize(*m_stream); + if (m_recorder) + m_recorder->Record(m_packets[idx]); } void GDBRemoteCommunicationHistory::Dump(Stream &strm) const { diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h index c006fbd34a4b..ee265ef86dff 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h @@ -13,11 +13,15 @@ #include <vector> #include "lldb/Utility/GDBRemote.h" +#include "lldb/Utility/Reproducer.h" #include "lldb/lldb-public.h" #include "llvm/Support/YAMLTraits.h" #include "llvm/Support/raw_ostream.h" namespace lldb_private { +namespace repro { +class PacketRecorder; +} namespace process_gdb_remote { /// The history keeps a circular buffer of GDB remote packets. The history is @@ -41,7 +45,7 @@ public: void Dump(Log *log) const; bool DidDumpToLog() const { return m_dumped_to_log; } - void SetStream(llvm::raw_ostream *strm) { m_stream = strm; } + void SetRecorder(repro::PacketRecorder *recorder) { m_recorder = recorder; } private: uint32_t GetFirstSavedPacketIndex() const { @@ -73,7 +77,7 @@ private: uint32_t m_curr_idx; uint32_t m_total_packet_count; mutable bool m_dumped_to_log; - llvm::raw_ostream *m_stream = nullptr; + repro::PacketRecorder *m_recorder = nullptr; }; } // namespace process_gdb_remote diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp index 2d26c550dc76..15c73e78bd44 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp @@ -143,7 +143,14 @@ GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse( entry.packet.data); LLDB_LOG(log, "GDBRemoteCommunicationReplayServer actual packet: '{0}'", packet.GetStringRef()); - assert(false && "Encountered unexpected packet during replay"); +#ifndef NDEBUG + // This behaves like a regular assert, but prints the expected and + // received packet before aborting. + printf("Reproducer expected packet: '%s'\n", entry.packet.data.c_str()); + printf("Reproducer received packet: '%s'\n", + packet.GetStringRef().data()); + llvm::report_fatal_error("Encountered unexpected packet during replay"); +#endif return PacketResult::ErrorSendFailed; } @@ -204,9 +211,9 @@ bool GDBRemoteCommunicationReplayServer::StartAsyncThread() { "<lldb.gdb-replay.async>", GDBRemoteCommunicationReplayServer::AsyncThread, this); if (!async_thread) { - LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), - "failed to launch host thread: {}", - llvm::toString(async_thread.takeError())); + LLDB_LOG_ERROR(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), + async_thread.takeError(), + "failed to launch host thread: {}"); return false; } m_async_thread = *async_thread; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp index 37980d914dc2..4b5fc0774a6d 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -429,7 +429,7 @@ GDBRemoteCommunicationServerCommon::Handle_qsProcessInfo( GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qUserName( StringExtractorGDBRemote &packet) { -#if !defined(LLDB_DISABLE_POSIX) +#if LLDB_ENABLE_POSIX Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); LLDB_LOGF(log, "GDBRemoteCommunicationServerCommon::%s begin", __FUNCTION__); @@ -452,7 +452,7 @@ GDBRemoteCommunicationServerCommon::Handle_qUserName( GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qGroupName( StringExtractorGDBRemote &packet) { -#if !defined(LLDB_DISABLE_POSIX) +#if LLDB_ENABLE_POSIX // Packet format: "qGroupName:%i" where %i is the gid packet.SetFilePos(::strlen("qGroupName:")); uint32_t gid = packet.GetU32(UINT32_MAX); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index ad1a39b57969..f33f0ee66304 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -669,9 +669,9 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( response.PutStringAsRawHex8(unescaped_response.GetData()); response.PutChar(';'); } else { - LLDB_LOG(log, "failed to prepare a jstopinfo field for pid {0}:", - m_debugged_process_up->GetID(), - llvm::toString(threads_info.takeError())); + LLDB_LOG_ERROR(log, threads_info.takeError(), + "failed to prepare a jstopinfo field for pid {1}: {0}", + m_debugged_process_up->GetID()); } } @@ -2013,7 +2013,7 @@ GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) { } const uint8_t *const data = - reinterpret_cast<const uint8_t *>(reg_value.GetBytes()); + static_cast<const uint8_t *>(reg_value.GetBytes()); if (!data) { LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s failed to get data " @@ -3087,9 +3087,9 @@ GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo( llvm::Expected<json::Value> threads_info = GetJSONThreadsInfo( *m_debugged_process_up, threads_with_valid_stop_info_only); if (!threads_info) { - LLDB_LOG(log, "failed to prepare a packet for pid {0}: {1}", - m_debugged_process_up->GetID(), - llvm::toString(threads_info.takeError())); + LLDB_LOG_ERROR(log, threads_info.takeError(), + "failed to prepare a packet for pid {1}: {0}", + m_debugged_process_up->GetID()); return SendErrorResponse(52); } diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp index c06c9527708e..ec1a54afd727 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -31,9 +31,11 @@ using namespace lldb_private::process_gdb_remote; // GDBRemoteRegisterContext constructor GDBRemoteRegisterContext::GDBRemoteRegisterContext( ThreadGDBRemote &thread, uint32_t concrete_frame_idx, - GDBRemoteDynamicRegisterInfo ®_info, bool read_all_at_once) + GDBRemoteDynamicRegisterInfo ®_info, bool read_all_at_once, + bool write_all_at_once) : RegisterContext(thread, concrete_frame_idx), m_reg_info(reg_info), - m_reg_valid(), m_reg_data(), m_read_all_at_once(read_all_at_once) { + m_reg_valid(), m_reg_data(), m_read_all_at_once(read_all_at_once), + m_write_all_at_once(write_all_at_once) { // Resize our vector of bools to contain one bool for every register. We will // use these boolean values to know when a register value is valid in // m_reg_data. @@ -87,6 +89,9 @@ bool GDBRemoteRegisterContext::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) { // Read the register if (ReadRegisterBytes(reg_info, m_reg_data)) { + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + if (m_reg_valid[reg] == false) + return false; const bool partial_data_ok = false; Status error(value.SetValueFromData( reg_info, m_reg_data, reg_info->byte_offset, partial_data_ok)); @@ -203,6 +208,18 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info, if (buffer_sp->GetByteSize() >= m_reg_data.GetByteSize()) { SetAllRegisterValid(true); return true; + } else if (buffer_sp->GetByteSize() > 0) { + const int regcount = m_reg_info.GetNumRegisters(); + for (int i = 0; i < regcount; i++) { + struct RegisterInfo *reginfo = m_reg_info.GetRegisterInfoAtIndex(i); + if (reginfo->byte_offset + reginfo->byte_size + <= buffer_sp->GetByteSize()) { + m_reg_valid[i] = true; + } else { + m_reg_valid[i] = false; + } + } + return true; } else { Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_THREAD | GDBR_LOG_PACKETS)); @@ -333,7 +350,7 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info, { GDBRemoteClientBase::Lock lock(gdb_comm, false); if (lock) { - if (m_read_all_at_once) { + if (m_write_all_at_once) { // Invalidate all register values InvalidateIfNeeded(true); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h index 25e9b716f8cb..b42c87b5991b 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h @@ -41,7 +41,7 @@ class GDBRemoteRegisterContext : public RegisterContext { public: GDBRemoteRegisterContext(ThreadGDBRemote &thread, uint32_t concrete_frame_idx, GDBRemoteDynamicRegisterInfo ®_info, - bool read_all_at_once); + bool read_all_at_once, bool write_all_at_once); ~GDBRemoteRegisterContext() override; @@ -114,6 +114,7 @@ protected: std::vector<bool> m_reg_valid; DataExtractor m_reg_data; bool m_read_all_at_once; + bool m_write_all_at_once; private: // Helper function for ReadRegisterBytes(). diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index f1762abc55f8..a49db5d9a934 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -10,7 +10,7 @@ #include <errno.h> #include <stdlib.h> -#ifndef LLDB_DISABLE_POSIX +#if LLDB_ENABLE_POSIX #include <netinet/in.h> #include <sys/mman.h> #include <sys/socket.h> @@ -154,6 +154,11 @@ public: nullptr, idx, g_processgdbremote_properties[idx].default_uint_value != 0); } + + bool GetUseGPacketForReading() const { + const uint32_t idx = ePropertyUseGPacketForReading; + return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); + } }; typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP; @@ -274,12 +279,9 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, "async thread did exit"); if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) { - repro::ProcessGDBRemoteProvider &provider = - g->GetOrCreate<repro::ProcessGDBRemoteProvider>(); - // Set the history stream to the stream owned by the provider. - m_gdb_comm.SetHistoryStream(provider.GetHistoryStream()); - // Make sure to clear the stream again when we're finished. - provider.SetCallback([&]() { m_gdb_comm.SetHistoryStream(nullptr); }); + repro::GDBRemoteProvider &provider = + g->GetOrCreate<repro::GDBRemoteProvider>(); + m_gdb_comm.SetPacketRecorder(provider.GetNewPacketRecorder()); } Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_ASYNC)); @@ -309,6 +311,9 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, GetGlobalPluginProperties()->GetPacketTimeout(); if (timeout_seconds > 0) m_gdb_comm.SetPacketTimeout(std::chrono::seconds(timeout_seconds)); + + m_use_g_packet_for_reading = + GetGlobalPluginProperties()->GetUseGPacketForReading(); } // Destructor @@ -380,36 +385,6 @@ bool ProcessGDBRemote::ParsePythonTargetDefinition( return false; } -// If the remote stub didn't give us eh_frame or DWARF register numbers for a -// register, see if the ABI can provide them. -// DWARF and eh_frame register numbers are defined as a part of the ABI. -static void AugmentRegisterInfoViaABI(RegisterInfo ®_info, - ConstString reg_name, ABISP abi_sp) { - if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM || - reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM) { - if (abi_sp) { - RegisterInfo abi_reg_info; - if (abi_sp->GetRegisterInfoByName(reg_name, abi_reg_info)) { - if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM && - abi_reg_info.kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM) { - reg_info.kinds[eRegisterKindEHFrame] = - abi_reg_info.kinds[eRegisterKindEHFrame]; - } - if (reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM && - abi_reg_info.kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM) { - reg_info.kinds[eRegisterKindDWARF] = - abi_reg_info.kinds[eRegisterKindDWARF]; - } - if (reg_info.kinds[eRegisterKindGeneric] == LLDB_INVALID_REGNUM && - abi_reg_info.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) { - reg_info.kinds[eRegisterKindGeneric] = - abi_reg_info.kinds[eRegisterKindGeneric]; - } - } - } - } -} - static size_t SplitCommaSeparatedRegisterNumberString( const llvm::StringRef &comma_separated_regiter_numbers, std::vector<uint32_t> ®nums, int base) { @@ -607,12 +582,12 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) { reg_info.invalidate_regs = invalidate_regs.data(); } + reg_info.name = reg_name.AsCString(); // We have to make a temporary ABI here, and not use the GetABI because // this code 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(shared_from_this(), arch_to_use); - - AugmentRegisterInfoViaABI(reg_info, reg_name, abi_to_use); + if (ABISP abi_sp = ABI::FindPlugin(shared_from_this(), arch_to_use)) + abi_sp->AugmentRegisterInfo(reg_info); m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name); } else { @@ -2374,21 +2349,22 @@ void ProcessGDBRemote::RefreshStateAfterStop() { m_thread_ids.clear(); m_thread_pcs.clear(); + // Set the thread stop info. It might have a "threads" key whose value is a // list of all thread IDs in the current process, so m_thread_ids might get // set. + // Check to see if SetThreadStopInfo() filled in m_thread_ids? + if (m_thread_ids.empty()) { + // No, we need to fetch the thread list manually + UpdateThreadIDList(); + } + + // We might set some stop info's so make sure the thread list is up to + // date before we do that or we might overwrite what was computed here. + UpdateThreadListIfNeeded(); // Scope for the lock { - // Check to see if SetThreadStopInfo() filled in m_thread_ids? - if (m_thread_ids.empty()) { - // No, we need to fetch the thread list manually - UpdateThreadIDList(); - } - // We might set some stop info's so make sure the thread list is up to - // date before we do that or we might overwrite what was computed here. - UpdateThreadListIfNeeded(); - // Lock the thread stack while we access it std::lock_guard<std::recursive_mutex> guard(m_last_stop_packet_mutex); // Get the number of stop packets on the stack @@ -3384,17 +3360,20 @@ Status ProcessGDBRemote::ConnectToReplayServer(repro::Loader *loader) { if (!loader) return Status("No loader provided."); - // Construct replay history path. - FileSpec history_file = - loader->GetFile<repro::ProcessGDBRemoteProvider::Info>(); - if (!history_file) - return Status("No provider for gdb-remote."); + static std::unique_ptr<repro::MultiLoader<repro::GDBRemoteProvider>> + multi_loader = repro::MultiLoader<repro::GDBRemoteProvider>::Create( + repro::Reproducer::Instance().GetLoader()); - // Enable replay mode. - m_replay_mode = true; + if (!multi_loader) + return Status("No gdb remote provider found."); + + llvm::Optional<std::string> history_file = multi_loader->GetNextFile(); + if (!history_file) + return Status("No gdb remote packet log found."); // Load replay history. - if (auto error = m_gdb_replay_server.LoadReplayHistory(history_file)) + if (auto error = + m_gdb_replay_server.LoadReplayHistory(FileSpec(*history_file))) return Status("Unable to load replay history"); // Make a local connection. @@ -3402,6 +3381,9 @@ Status ProcessGDBRemote::ConnectToReplayServer(repro::Loader *loader) { m_gdb_replay_server)) return Status("Unable to connect to replay server"); + // Enable replay mode. + m_replay_mode = true; + // Start server thread. m_gdb_replay_server.StartAsyncThread(); @@ -3627,9 +3609,9 @@ bool ProcessGDBRemote::StartAsyncThread() { llvm::Expected<HostThread> async_thread = ThreadLauncher::LaunchThread( "<lldb.process.gdb-remote.async>", ProcessGDBRemote::AsyncThread, this); if (!async_thread) { - LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), - "failed to launch host thread: {}", - llvm::toString(async_thread.takeError())); + LLDB_LOG_ERROR(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), + async_thread.takeError(), + "failed to launch host thread: {}"); return false; } m_async_thread = *async_thread; @@ -4475,7 +4457,9 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, } ++cur_reg_num; - AugmentRegisterInfoViaABI(reg_info, reg_name, abi_sp); + reg_info.name = reg_name.AsCString(); + if (abi_sp) + abi_sp->AugmentRegisterInfo(reg_info); dyn_reg_info.AddRegister(reg_info, reg_name, alt_name, set_name); return true; // Keep iterating through all "reg" elements diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 0e3e3b39d9c8..9ea3940103b6 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -284,6 +284,7 @@ protected: lldb::CommandObjectSP m_command_sp; int64_t m_breakpoint_pc_offset; lldb::tid_t m_initial_tid; // The initial thread ID, given by stub on attach + bool m_use_g_packet_for_reading; bool m_replay_mode; bool m_allow_flash_writes; diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td index 16e7723e3061..9cbe3d40ca2c 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td @@ -13,4 +13,8 @@ let Definition = "processgdbremote" in { Global, DefaultFalse, Desc<"If true, the libraries-svr4 feature will be used to get a hold of the process's loaded modules.">; + def UseGPacketForReading: Property<"use-g-packet-for-reading", "Boolean">, + Global, + DefaultFalse, + Desc<"Specify if the server should use 'g' packets to read registers.">; } diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp index 8a6a58c55450..9da481979f73 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -301,13 +301,14 @@ ThreadGDBRemote::CreateRegisterContextForFrame(StackFrame *frame) { if (process_sp) { ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get()); - // read_all_registers_at_once will be true if 'p' packet is not - // supported. + bool pSupported = + gdb_process->GetGDBRemote().GetpPacketSupported(GetID()); bool read_all_registers_at_once = - !gdb_process->GetGDBRemote().GetpPacketSupported(GetID()); + !pSupported || gdb_process->m_use_g_packet_for_reading; + bool write_all_registers_at_once = !pSupported; reg_ctx_sp = std::make_shared<GDBRemoteRegisterContext>( *this, concrete_frame_idx, gdb_process->m_register_info, - read_all_registers_at_once); + read_all_registers_at_once, write_all_registers_at_once); } } else { Unwind *unwinder = GetUnwinder(); |