[Lldb-commits] [lldb] r160199 - in /lldb/trunk: include/lldb/Target/Process.h include/lldb/Target/StopInfo.h source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp source/Plugins/Process/gdb-remote/ProcessGDBRemote.h source/Target/StopInfo.cpp tools/debugserver/source/RNBRemote.cpp

Enrico Granata egranata at apple.com
Fri Jul 13 16:18:48 PDT 2012


Author: enrico
Date: Fri Jul 13 18:18:48 2012
New Revision: 160199

URL: http://llvm.org/viewvc/llvm-project?rev=160199&view=rev
Log:
<rdar://problem/11782789> Changes to the watchpoint implementation on ARM so that we single-step before stopping at the WP. This is necessary because on ARM the WP triggers before the opcode is actually executed, so we would be unable to continue since we would keep hitting the WP. We work around this by disabling the WP, single stepping and then putting the WP back in place.

Modified:
    lldb/trunk/include/lldb/Target/Process.h
    lldb/trunk/include/lldb/Target/StopInfo.h
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
    lldb/trunk/source/Target/StopInfo.cpp
    lldb/trunk/tools/debugserver/source/RNBRemote.cpp

Modified: lldb/trunk/include/lldb/Target/Process.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Process.h?rev=160199&r1=160198&r2=160199&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Process.h (original)
+++ lldb/trunk/include/lldb/Target/Process.h Fri Jul 13 18:18:48 2012
@@ -2786,6 +2786,14 @@
         return error;
     }
 
+    virtual Error
+    GetWatchpointSupportInfo (uint32_t &num, bool& after)
+    {
+        Error error;
+        error.SetErrorString ("Process::GetWatchpointSupportInfo() not supported");
+        return error;
+    }
+    
     lldb::ModuleSP
     ReadModuleFromMemory (const FileSpec& file_spec, 
                           lldb::addr_t header_addr,

Modified: lldb/trunk/include/lldb/Target/StopInfo.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/StopInfo.h?rev=160199&r1=160198&r2=160199&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/StopInfo.h (original)
+++ lldb/trunk/include/lldb/Target/StopInfo.h Fri Jul 13 18:18:48 2012
@@ -161,14 +161,15 @@
     // N.B. running to evaluate a user expression does not count. 
     bool HasTargetRunSinceMe ();
 
-private:
-    friend class Thread;
-    
-    // MakeStopInfoValid is necessary to allow saved stop infos to resurrect themselves as valid.  It should
-    // only need to be called by Thread::RestoreThreadStateFromCheckpoint.
+    // MakeStopInfoValid is necessary to allow saved stop infos to resurrect themselves as valid.
+    // It should only be used by Thread::RestoreThreadStateFromCheckpoint and to make sure the one-step
+    // needed for before-the-fact watchpoints does not prevent us from stopping
     void
     MakeStopInfoValid ();
     
+private:
+    friend class Thread;
+    
     DISALLOW_COPY_AND_ASSIGN (StopInfo);
 };
 

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp?rev=160199&r1=160198&r2=160199&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp Fri Jul 13 18:18:48 2012
@@ -49,6 +49,7 @@
     m_supports_alloc_dealloc_memory (eLazyBoolCalculate),
     m_supports_memory_region_info  (eLazyBoolCalculate),
     m_supports_watchpoint_support_info  (eLazyBoolCalculate),
+    m_watchpoints_trigger_after_instruction(eLazyBoolCalculate),
     m_supports_qProcessInfoPID (true),
     m_supports_qfProcessInfo (true),
     m_supports_qUserName (true),
@@ -1019,6 +1020,17 @@
                         if (m_os_version_major != UINT32_MAX)
                             ++num_keys_decoded;
                     }
+                    else if (name.compare("watchpoint_exceptions_received") == 0)
+                    {
+                        ++num_keys_decoded;
+                        if (strcmp(value.c_str(),"before") == 0)
+                            m_watchpoints_trigger_after_instruction = eLazyBoolNo;
+                        else if (strcmp(value.c_str(),"after") == 0)
+                            m_watchpoints_trigger_after_instruction = eLazyBoolYes;
+                        else
+                            --num_keys_decoded;
+                    }
+
                 }
                 
                 if (num_keys_decoded > 0)
@@ -1352,6 +1364,30 @@
 
 }
 
+lldb_private::Error
+GDBRemoteCommunicationClient::GetWatchpointSupportInfo (uint32_t &num, bool& after)
+{
+    Error error(GetWatchpointSupportInfo(num));
+    if (error.Success())
+        error = GetWatchpointsTriggerAfterInstruction(after);
+    return error;
+}
+
+lldb_private::Error
+GDBRemoteCommunicationClient::GetWatchpointsTriggerAfterInstruction (bool &after)
+{
+    Error error;
+    
+    // we assume watchpoints will happen after running the relevant opcode
+    // and we only want to override this behavior if we have explicitly
+    // received a qHostInfo telling us otherwise
+    if (m_qHostInfo_is_valid != eLazyBoolYes)
+        after = true;
+    else
+        after = (m_watchpoints_trigger_after_instruction != eLazyBoolNo);
+    return error;
+}
+
 int
 GDBRemoteCommunicationClient::SetSTDIN (char const *path)
 {

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h?rev=160199&r1=160198&r2=160199&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h Fri Jul 13 18:18:48 2012
@@ -209,6 +209,12 @@
     lldb_private::Error
     GetWatchpointSupportInfo (uint32_t &num); 
 
+    lldb_private::Error
+    GetWatchpointSupportInfo (uint32_t &num, bool& after);
+    
+    lldb_private::Error
+    GetWatchpointsTriggerAfterInstruction (bool &after);
+
     const lldb_private::ArchSpec &
     GetHostArchitecture ();
     
@@ -358,6 +364,7 @@
     lldb_private::LazyBool m_supports_alloc_dealloc_memory;
     lldb_private::LazyBool m_supports_memory_region_info;
     lldb_private::LazyBool m_supports_watchpoint_support_info;
+    lldb_private::LazyBool m_watchpoints_trigger_after_instruction;
 
     bool
         m_supports_qProcessInfoPID:1,

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp?rev=160199&r1=160198&r2=160199&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp Fri Jul 13 18:18:48 2012
@@ -223,6 +223,11 @@
     if (sub != LLDB_INVALID_CPUTYPE)
         response.Printf ("cpusubtype:%u;", sub);
     
+    if (cpu == CPU_TYPE_ARM)
+        response.Printf("watchpoint_exceptions_received:before;");   // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
+    else
+        response.Printf("watchpoint_exceptions_received:after;");
+    
     switch (lldb::endian::InlHostByteOrder())
     {
     case eByteOrderBig:     response.PutCString ("endian:big;"); break;

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=160199&r1=160198&r2=160199&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Fri Jul 13 18:18:48 2012
@@ -2015,6 +2015,13 @@
 }
 
 Error
+ProcessGDBRemote::GetWatchpointSupportInfo (uint32_t &num, bool& after)
+{
+    Error error (m_gdb_comm.GetWatchpointSupportInfo (num, after));
+    return error;
+}
+
+Error
 ProcessGDBRemote::DoDeallocateMemory (lldb::addr_t addr)
 {
     Error error; 

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h?rev=160199&r1=160198&r2=160199&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h Fri Jul 13 18:18:48 2012
@@ -207,6 +207,9 @@
     virtual lldb_private::Error
     GetWatchpointSupportInfo (uint32_t &num);
     
+    virtual lldb_private::Error
+    GetWatchpointSupportInfo (uint32_t &num, bool& after);
+    
     virtual bool
     StartNoticingNewThreads();    
 

Modified: lldb/trunk/source/Target/StopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StopInfo.cpp?rev=160199&r1=160198&r2=160199&view=diff
==============================================================================
--- lldb/trunk/source/Target/StopInfo.cpp (original)
+++ lldb/trunk/source/Target/StopInfo.cpp Fri Jul 13 18:18:48 2012
@@ -461,6 +461,36 @@
         if (wp_sp)
         {
             ExecutionContext exe_ctx (m_thread.GetStackFrameAtIndex(0));
+            {
+                // check if this process is running on an architecture where watchpoints trigger
+				// before the associated instruction runs. if so, disable the WP, single-step and then
+				// re-enable the watchpoint
+                Process* process = exe_ctx.GetProcessPtr();
+                if (process)
+                {
+                    uint32_t num; bool wp_triggers_after;
+                    if (process->GetWatchpointSupportInfo(num, wp_triggers_after).Success())
+                    {
+                        if (!wp_triggers_after)
+                        {
+                            process->DisableWatchpoint(wp_sp.get());
+                            
+                            ThreadPlan *new_plan = m_thread.QueueThreadPlanForStepSingleInstruction(false, // step-over
+                                                                                                    false, // abort_other_plans
+                                                                                                    true); // stop_other_threads
+                            new_plan->SetIsMasterPlan (true);
+                            new_plan->SetOkayToDiscard (false);
+                            process->GetThreadList().SetSelectedThreadByID (m_thread.GetID());
+                            process->Resume ();
+                            process->WaitForProcessToStop (NULL);
+                            process->GetThreadList().SetSelectedThreadByID (m_thread.GetID());
+                            MakeStopInfoValid(); // make sure we do not fail to stop because of the single-step taken above
+                            
+                            process->EnableWatchpoint(wp_sp.get());
+                        }
+                    }
+                }
+            }
             StoppointCallbackContext context (event_ptr, exe_ctx, false);
             bool stop_requested = wp_sp->InvokeCallback (&context);
             // Also make sure that the callback hasn't continued the target.  

Modified: lldb/trunk/tools/debugserver/source/RNBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/RNBRemote.cpp?rev=160199&r1=160198&r2=160199&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/RNBRemote.cpp (original)
+++ lldb/trunk/tools/debugserver/source/RNBRemote.cpp Fri Jul 13 18:18:48 2012
@@ -3587,10 +3587,13 @@
     if (cputype == CPU_TYPE_ARM)
     {
         strm << "ostype:ios;";
+        // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
+        strm << "watchpoint_exceptions_received:before;";
     }
     else
     {
         strm << "ostype:macosx;";
+        strm << "watchpoint_exceptions_received:after;";
     }
 //    char ostype[64];
 //    len = sizeof(ostype);





More information about the lldb-commits mailing list