From 64637205051bb9789436cc4546ac9d8507a0c9d0 Mon Sep 17 00:00:00 2001 From: Johnny Chen Date: Wed, 23 May 2012 21:09:52 +0000 Subject: [PATCH] Add the capability to display the number of supported hardware watchpoints to the "watchpoint list" command. Add default Process::GetWatchpointSupportInfo() impl which returns an error of "not supported". Add "qWatchpointSupportInfo" packet to the gdb communication layer to support this, and modify TestWatchpointCommands.py to test it. llvm-svn: 157345 --- lldb/include/lldb/Target/Process.h | 8 ++++ lldb/source/Commands/CommandObjectWatchpoint.cpp | 9 ++++ .../gdb-remote/GDBRemoteCommunicationClient.cpp | 48 ++++++++++++++++++++++ .../gdb-remote/GDBRemoteCommunicationClient.h | 6 +++ .../Process/gdb-remote/ProcessGDBRemote.cpp | 8 ++++ .../Plugins/Process/gdb-remote/ProcessGDBRemote.h | 3 ++ .../watchpoint_commands/TestWatchpointCommands.py | 3 +- lldb/tools/debugserver/source/DNB.cpp | 12 ++++++ lldb/tools/debugserver/source/DNB.h | 1 + .../debugserver/source/MacOSX/MachProcess.cpp | 6 +++ lldb/tools/debugserver/source/MacOSX/MachProcess.h | 1 + .../tools/debugserver/source/MacOSX/MachThread.cpp | 6 +++ lldb/tools/debugserver/source/MacOSX/MachThread.h | 1 + .../debugserver/source/MacOSX/MachThreadList.cpp | 11 +++++ .../debugserver/source/MacOSX/MachThreadList.h | 2 + lldb/tools/debugserver/source/RNBRemote.cpp | 28 +++++++++++++ lldb/tools/debugserver/source/RNBRemote.h | 2 + 17 files changed, 154 insertions(+), 1 deletion(-) diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index 428e007..1d12ae0 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -2722,6 +2722,14 @@ public: return error; } + virtual Error + GetWatchpointSupportInfo (uint32_t &num) + { + Error error; + error.SetErrorString ("Process::GetWatchpointSupportInfo() not supported"); + return error; + } + lldb::ModuleSP ReadModuleFromMemory (const FileSpec& file_spec, lldb::addr_t header_addr, diff --git a/lldb/source/Commands/CommandObjectWatchpoint.cpp b/lldb/source/Commands/CommandObjectWatchpoint.cpp index 8387cb6..56b95ab 100644 --- a/lldb/source/Commands/CommandObjectWatchpoint.cpp +++ b/lldb/source/Commands/CommandObjectWatchpoint.cpp @@ -290,6 +290,15 @@ CommandObjectWatchpointList::Execute(Args& args, CommandReturnObject &result) return true; } + if (target->GetProcessSP() && target->GetProcessSP()->IsAlive()) + { + uint32_t num_supported_hardware_watchpoints; + Error error = target->GetProcessSP()->GetWatchpointSupportInfo(num_supported_hardware_watchpoints); + if (error.Success()) + result.AppendMessageWithFormat("Number of supported hardware watchpoints: %u\n", + num_supported_hardware_watchpoints); + } + const WatchpointList &watchpoints = target->GetWatchpointList(); Mutex::Locker locker; target->GetWatchpointList().GetListMutex(locker); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index ac7544d..013519c 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -48,6 +48,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) : m_qHostInfo_is_valid (eLazyBoolCalculate), m_supports_alloc_dealloc_memory (eLazyBoolCalculate), m_supports_memory_region_info (eLazyBoolCalculate), + m_supports_watchpoint_support_info (eLazyBoolCalculate), m_supports_qProcessInfoPID (true), m_supports_qfProcessInfo (true), m_supports_qUserName (true), @@ -60,6 +61,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) : m_supports_z4 (true), m_curr_tid (LLDB_INVALID_THREAD_ID), m_curr_tid_run (LLDB_INVALID_THREAD_ID), + m_num_supported_hardware_watchpoints (0), m_async_mutex (Mutex::eMutexTypeRecursive), m_async_packet_predicate (false), m_async_packet (), @@ -1286,6 +1288,52 @@ GDBRemoteCommunicationClient::GetMemoryRegionInfo (lldb::addr_t addr, } +Error +GDBRemoteCommunicationClient::GetWatchpointSupportInfo (uint32_t &num) +{ + Error error; + + if (m_supports_watchpoint_support_info == eLazyBoolYes) + { + num = m_num_supported_hardware_watchpoints; + return error; + } + + // Set num to 0 first. + num = 0; + if (m_supports_watchpoint_support_info != eLazyBoolNo) + { + char packet[64]; + const int packet_len = ::snprintf(packet, sizeof(packet), "qWatchpointSupportInfo:"); + assert (packet_len < sizeof(packet)); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse (packet, packet_len, response, false)) + { + m_supports_watchpoint_support_info = eLazyBoolYes; + std::string name; + std::string value; + while (response.GetNameColonValue(name, value)) + { + if (name.compare ("num") == 0) + { + num = Args::StringToUInt32(value.c_str(), 0, 0); + m_num_supported_hardware_watchpoints = num; + } + } + } + else + { + m_supports_watchpoint_support_info = eLazyBoolNo; + } + } + + if (m_supports_watchpoint_support_info == eLazyBoolNo) + { + error.SetErrorString("qWatchpointSupportInfo is not supported"); + } + return error; + +} int GDBRemoteCommunicationClient::SetSTDIN (char const *path) diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 4794021..fb57800 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -206,6 +206,9 @@ public: GetMemoryRegionInfo (lldb::addr_t addr, lldb_private::MemoryRegionInfo &range_info); + lldb_private::Error + GetWatchpointSupportInfo (uint32_t &num); + const lldb_private::ArchSpec & GetHostArchitecture (); @@ -354,6 +357,7 @@ protected: lldb_private::LazyBool m_qHostInfo_is_valid; lldb_private::LazyBool m_supports_alloc_dealloc_memory; lldb_private::LazyBool m_supports_memory_region_info; + lldb_private::LazyBool m_supports_watchpoint_support_info; bool m_supports_qProcessInfoPID:1, @@ -372,6 +376,8 @@ protected: lldb::tid_t m_curr_tid_run; // Current gdb remote protocol thread index for continue, step, etc + uint32_t m_num_supported_hardware_watchpoints; + // If we need to send a packet while the target is running, the m_async_XXX // member variables take care of making this happen. lldb_private::Mutex m_async_mutex; diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index d9b9206..6b5bb9a 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -1858,6 +1858,14 @@ ProcessGDBRemote::GetMemoryRegionInfo (addr_t load_addr, } Error +ProcessGDBRemote::GetWatchpointSupportInfo (uint32_t &num) +{ + + Error error (m_gdb_comm.GetWatchpointSupportInfo (num)); + return error; +} + +Error ProcessGDBRemote::DoDeallocateMemory (lldb::addr_t addr) { Error error; diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 6287c4b..9e21ded 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -204,6 +204,9 @@ public: virtual lldb_private::Error DisableWatchpoint (lldb_private::Watchpoint *wp); + virtual lldb_private::Error + GetWatchpointSupportInfo (uint32_t &num); + virtual bool StartNoticingNewThreads(); diff --git a/lldb/test/functionalities/watchpoint/watchpoint_commands/TestWatchpointCommands.py b/lldb/test/functionalities/watchpoint/watchpoint_commands/TestWatchpointCommands.py index c196d3f..5718f67 100644 --- a/lldb/test/functionalities/watchpoint/watchpoint_commands/TestWatchpointCommands.py +++ b/lldb/test/functionalities/watchpoint/watchpoint_commands/TestWatchpointCommands.py @@ -128,7 +128,8 @@ class WatchpointCommandsTestCase(TestBase): # Use the '-v' option to do verbose listing of the watchpoint. # The hit count should be 0 initially. self.expect("watchpoint list -v", - substrs = ['hit_count = 0']) + substrs = ['Number of supported hardware watchpoints:', + 'hit_count = 0']) self.runCmd("process continue") diff --git a/lldb/tools/debugserver/source/DNB.cpp b/lldb/tools/debugserver/source/DNB.cpp index f7b66c1..d668744 100644 --- a/lldb/tools/debugserver/source/DNB.cpp +++ b/lldb/tools/debugserver/source/DNB.cpp @@ -1081,6 +1081,18 @@ DNBWatchpointPrint (nub_process_t pid, nub_watch_t watchID) } //---------------------------------------------------------------------- +// Return the number of supported hardware watchpoints. +//---------------------------------------------------------------------- +uint32_t +DNBWatchpointGetNumSupportedHWP (nub_process_t pid) +{ + MachProcessSP procSP; + if (GetProcessSP (pid, procSP)) + return procSP->GetNumSupportedHardwareWatchpoints(); + return 0; +} + +//---------------------------------------------------------------------- // Read memory in the address space of process PID. This call will take // care of setting and restoring permissions and breaking up the memory // read into multiple chunks as required. diff --git a/lldb/tools/debugserver/source/DNB.h b/lldb/tools/debugserver/source/DNB.h index 1f612a6..68df124 100644 --- a/lldb/tools/debugserver/source/DNB.h +++ b/lldb/tools/debugserver/source/DNB.h @@ -138,6 +138,7 @@ nub_ssize_t DNBWatchpointGetIgnoreCount (nub_process_t pid, nub_watch_t nub_bool_t DNBWatchpointSetIgnoreCount (nub_process_t pid, nub_watch_t watchID, nub_size_t ignore_count) DNB_EXPORT; nub_bool_t DNBWatchpointSetCallback (nub_process_t pid, nub_watch_t watchID, DNBCallbackBreakpointHit callback, void *baton) DNB_EXPORT; void DNBWatchpointPrint (nub_process_t pid, nub_watch_t watchID) DNB_EXPORT; +uint32_t DNBWatchpointGetNumSupportedHWP (nub_process_t pid) DNB_EXPORT; const DNBRegisterSetInfo * DNBGetRegisterSetInfo (nub_size_t *num_reg_sets) DNB_EXPORT; diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp b/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp index 83cbe2c..dd09745 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp @@ -944,6 +944,12 @@ MachProcess::DumpWatchpoint(nub_watch_t watchID) const } } +uint32_t +MachProcess::GetNumSupportedHardwareWatchpoints () const +{ + return m_thread_list.NumSupportedHardwareWatchpoints(); +} + bool MachProcess::EnableBreakpoint(nub_break_t breakID) { diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.h b/lldb/tools/debugserver/source/MacOSX/MachProcess.h index 6d99edc..899109d 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachProcess.h +++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.h @@ -131,6 +131,7 @@ public: nub_size_t DisableAllWatchpoints (bool remove); bool EnableWatchpoint (nub_watch_t watchID); void DumpWatchpoint(nub_watch_t watchID) const; + uint32_t GetNumSupportedHardwareWatchpoints () const; DNBBreakpointList& Watchpoints() { return m_watchpoints; } const DNBBreakpointList& Watchpoints() const { return m_watchpoints; } diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp index 9a36bc7..aca47f9 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp @@ -715,6 +715,12 @@ MachThread::DisableHardwareWatchpoint (const DNBBreakpoint *wp) return false; } +uint32_t +MachThread::NumSupportedHardwareWatchpoints () const +{ + return m_arch_ap->NumSupportedHardwareWatchpoints(); +} + bool MachThread::GetIdentifierInfo () { diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.h b/lldb/tools/debugserver/source/MacOSX/MachThread.h index 7aa299b..724043a 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThread.h +++ b/lldb/tools/debugserver/source/MacOSX/MachThread.h @@ -65,6 +65,7 @@ public: uint32_t EnableHardwareWatchpoint (const DNBBreakpoint *watchpoint); bool DisableHardwareBreakpoint (const DNBBreakpoint *breakpoint); bool DisableHardwareWatchpoint (const DNBBreakpoint *watchpoint); + uint32_t NumSupportedHardwareWatchpoints () const; nub_state_t GetState(); void SetState(nub_state_t state); diff --git a/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp b/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp index 207bc77..e2aa0f2 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp @@ -509,6 +509,17 @@ MachThreadList::DisableHardwareWatchpoint (const DNBBreakpoint* wp) const } uint32_t +MachThreadList::NumSupportedHardwareWatchpoints () const +{ + PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); + const uint32_t num_threads = m_threads.size(); + // Use an arbitrary thread to retrieve the number of supported hardware watchpoints. + if (num_threads) + return m_threads[0]->NumSupportedHardwareWatchpoints(); + return 0; +} + +uint32_t MachThreadList::GetThreadIndexForThreadStoppedWithSignal (const int signo) const { PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); diff --git a/lldb/tools/debugserver/source/MacOSX/MachThreadList.h b/lldb/tools/debugserver/source/MacOSX/MachThreadList.h index b010a21..52f9e74 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThreadList.h +++ b/lldb/tools/debugserver/source/MacOSX/MachThreadList.h @@ -50,6 +50,8 @@ public: bool DisableHardwareBreakpoint (const DNBBreakpoint *bp) const; uint32_t EnableHardwareWatchpoint (const DNBBreakpoint *wp) const; bool DisableHardwareWatchpoint (const DNBBreakpoint *wp) const; + uint32_t NumSupportedHardwareWatchpoints () const; + uint32_t GetThreadIndexForThreadStoppedWithSignal (const int signo) const; MachThreadSP GetThreadByID (nub_thread_t tid) const; diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp index 3900ab9..1411761 100644 --- a/lldb/tools/debugserver/source/RNBRemote.cpp +++ b/lldb/tools/debugserver/source/RNBRemote.cpp @@ -189,6 +189,7 @@ RNBRemote::CreatePacketTable () t.push_back (Packet (allocate_memory, &RNBRemote::HandlePacket_AllocateMemory, NULL, "_M", "Allocate memory in the inferior process.")); t.push_back (Packet (deallocate_memory, &RNBRemote::HandlePacket_DeallocateMemory, NULL, "_m", "Deallocate memory in the inferior process.")); t.push_back (Packet (memory_region_info, &RNBRemote::HandlePacket_MemoryRegionInfo, NULL, "qMemoryRegionInfo", "Return size and attributes of a memory region that contains the given address")); + t.push_back (Packet (watchpoint_support_info, &RNBRemote::HandlePacket_WatchpointSupportInfo, NULL, "qWatchpointSupportInfo", "Return the number of supported hardware watchpoints")); } @@ -3361,6 +3362,33 @@ RNBRemote::HandlePacket_MemoryRegionInfo (const char *p) return SendPacket (ostrm.str()); } +rnb_err_t +RNBRemote::HandlePacket_WatchpointSupportInfo (const char *p) +{ + /* This packet simply returns the number of supported hardware watchpoints. + + Examples of use: + qWatchpointSupportInfo: + num:4 + + qWatchpointSupportInfo + OK // this packet is implemented by the remote nub + */ + + p += sizeof ("qWatchpointSupportInfo") - 1; + if (*p == '\0') + return SendPacket ("OK"); + if (*p++ != ':') + return SendPacket ("E67"); + + errno = 0; + uint32_t num = DNBWatchpointGetNumSupportedHWP (m_ctx.ProcessID()); + std::ostringstream ostrm; + + // size:4 + ostrm << "num:" << std::dec << num << ';'; + return SendPacket (ostrm.str()); +} /* 'C sig [;addr]' Resume with signal sig, optionally at address addr. */ diff --git a/lldb/tools/debugserver/source/RNBRemote.h b/lldb/tools/debugserver/source/RNBRemote.h index 489a025..23eabdd 100644 --- a/lldb/tools/debugserver/source/RNBRemote.h +++ b/lldb/tools/debugserver/source/RNBRemote.h @@ -108,6 +108,7 @@ public: set_working_dir, // 'QSetWorkingDir:' set_list_threads_in_stop_reply, // 'QListThreadsInStopReply:' memory_region_info, // 'qMemoryRegionInfo:' + watchpoint_support_info, // 'qWatchpointSupportInfo:' allocate_memory, // '_M' deallocate_memory, // '_m' @@ -202,6 +203,7 @@ public: rnb_err_t HandlePacket_AllocateMemory (const char *p); rnb_err_t HandlePacket_DeallocateMemory (const char *p); rnb_err_t HandlePacket_MemoryRegionInfo (const char *p); + rnb_err_t HandlePacket_WatchpointSupportInfo (const char *p); rnb_err_t HandlePacket_stop_process (const char *p); -- 2.7.4