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.


git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@157345 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Commands/CommandObjectWatchpoint.cpp b/source/Commands/CommandObjectWatchpoint.cpp
index 8387cb6..56b95ab 100644
--- a/source/Commands/CommandObjectWatchpoint.cpp
+++ b/source/Commands/CommandObjectWatchpoint.cpp
@@ -290,6 +290,15 @@
         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/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index ac7544d..013519c 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -48,6 +48,7 @@
     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 @@
     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 @@
 
 }
 
+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/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index 4794021..fb57800 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -206,6 +206,9 @@
     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 @@
     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 @@
     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/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index d9b9206..6b5bb9a 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -1858,6 +1858,14 @@
 }
 
 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/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 6287c4b..9e21ded 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -204,6 +204,9 @@
     virtual lldb_private::Error
     DisableWatchpoint (lldb_private::Watchpoint *wp);
 
+    virtual lldb_private::Error
+    GetWatchpointSupportInfo (uint32_t &num);
+    
     virtual bool
     StartNoticingNewThreads();