[Lldb-commits] [lldb] r164584 - in /lldb/trunk: include/lldb/Core/ include/lldb/Target/ source/API/ source/Plugins/Process/MacOSX-Kernel/ source/Plugins/Process/Utility/ source/Target/

Greg Clayton gclayton at apple.com
Mon Sep 24 19:40:07 PDT 2012


Author: gclayton
Date: Mon Sep 24 21:40:06 2012
New Revision: 164584

URL: http://llvm.org/viewvc/llvm-project?rev=164584&view=rev
Log:
<rdar://problem/9959501>

More KDP debugging process. We can not set breakpoints, hit them, resume, step and detach while running.


Modified:
    lldb/trunk/include/lldb/Core/Stream.h
    lldb/trunk/include/lldb/Target/Thread.h
    lldb/trunk/source/API/SBThread.cpp
    lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
    lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h
    lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
    lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
    lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp
    lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h
    lldb/trunk/source/Plugins/Process/Utility/StopInfoMachException.cpp
    lldb/trunk/source/Plugins/Process/Utility/StopInfoMachException.h
    lldb/trunk/source/Target/Thread.cpp

Modified: lldb/trunk/include/lldb/Core/Stream.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Stream.h?rev=164584&r1=164583&r2=164584&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Stream.h (original)
+++ lldb/trunk/include/lldb/Core/Stream.h Mon Sep 24 21:40:06 2012
@@ -590,7 +590,7 @@
     static void
     UnitTest(Stream *s);
 
-private:
+protected:
     //------------------------------------------------------------------
     // Member variables
     //------------------------------------------------------------------

Modified: lldb/trunk/include/lldb/Target/Thread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Thread.h?rev=164584&r1=164583&r2=164584&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Thread.h (original)
+++ lldb/trunk/include/lldb/Target/Thread.h Mon Sep 24 21:40:06 2012
@@ -226,6 +226,9 @@
     lldb::StopInfoSP
     GetStopInfo ();
 
+    lldb::StopReason
+    GetStopReason();
+
     // This sets the stop reason to a "blank" stop reason, so you can call functions on the thread
     // without having the called function run with whatever stop reason you stopped with.
     void
@@ -721,6 +724,27 @@
     virtual lldb::StopInfoSP
     GetPrivateStopReason () = 0;
 
+    //----------------------------------------------------------------------
+    // Gets the temporary resume state for a thread.
+    //
+    // This value gets set in each thread by complex debugger logic in
+    // Thread::WillResume() and an appropriate thread resume state will get
+    // set in each thread every time the process is resumed prior to calling
+    // Process::DoResume(). The lldb_private::Process subclass should adhere
+    // to the thread resume state request which will be one of:
+    //
+    //  eStateRunning   - thread will resume when process is resumed
+    //  eStateStepping  - thread should step 1 instruction and stop when process
+    //                    is resumed
+    //  eStateSuspended - thread should not execute any instructions when
+    //                    process is resumed
+    //----------------------------------------------------------------------
+    lldb::StateType
+    GetTemporaryResumeState() const
+    {
+        return m_temporary_resume_state;
+    }
+
 protected:
 
     friend class ThreadPlan;
@@ -764,18 +788,6 @@
     lldb::StackFrameListSP
     GetStackFrameList ();
     
-    lldb::StateType GetTemporaryResumeState()
-    {
-        return m_temporary_resume_state;
-    }
-    
-    lldb::StateType SetTemporaryResumeState(lldb::StateType resume_state)
-    {
-        lldb::StateType old_temp_resume_state = m_temporary_resume_state;
-        m_temporary_resume_state = resume_state;
-        return old_temp_resume_state;
-    }
-    
     struct ThreadState
     {
         uint32_t           orig_stop_id;

Modified: lldb/trunk/source/API/SBThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBThread.cpp?rev=164584&r1=164583&r2=164584&view=diff
==============================================================================
--- lldb/trunk/source/API/SBThread.cpp (original)
+++ lldb/trunk/source/API/SBThread.cpp Mon Sep 24 21:40:06 2012
@@ -104,9 +104,7 @@
         Process::StopLocker stop_locker;
         if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
         {
-            StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo ();
-            if (stop_info_sp)
-                reason =  stop_info_sp->GetStopReason();
+            return exe_ctx.GetThreadPtr()->GetStopReason();
         }
         else
         {

Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp?rev=164584&r1=164583&r2=164584&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp (original)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp Mon Sep 24 21:40:06 2012
@@ -42,7 +42,7 @@
     m_byte_order (eByteOrderLittle),
     m_packet_timeout (1),
     m_sequence_mutex (Mutex::eMutexTypeRecursive),
-    m_private_is_running (false),
+    m_is_running (false),
     m_session_key (0u),
     m_request_sequence_id (0u),
     m_exception_sequence_id (0u),
@@ -99,8 +99,23 @@
                                           const PacketStreamType &request_packet, 
                                           DataExtractor &reply_packet)
 {
+    if (IsRunning())
+    {
+        LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
+        if (log)
+        {
+            PacketStreamType log_strm;
+            DumpPacket (log_strm, request_packet.GetData(), request_packet.GetSize());
+            log->Printf("error: kdp running, not sending packet: %.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData());
+        }
+        return false;
+    }
 
-    Mutex::Locker locker(m_sequence_mutex);    
+    Mutex::Locker locker(m_sequence_mutex);
+#ifdef LLDB_CONFIGURATION_DEBUG
+    // NOTE: this only works for packets that are in native endian byte order
+    assert (request_packet.GetSize() == *((uint16_t *)(request_packet.GetData() + 2)));
+#endif
     if (SendRequestPacketNoLock(request_packet))
     {
         if (WaitForPacketWithTimeoutMicroSecondsNoLock (reply_packet, GetPacketTimeoutInMicroSeconds ()))
@@ -111,7 +126,11 @@
             if ((reply_command & eCommandTypeMask) == command)
             {
                 if (request_sequence_id == reply_sequence_id)
+                {
+                    if (command == KDP_RESUMECPUS)
+                        m_is_running.SetValue(true, eBroadcastAlways);
                     return true;
+                }
             }
         }
     }
@@ -160,7 +179,7 @@
 bool
 CommunicationKDP::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
 {
-    return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
+    return m_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
 }
 
 size_t
@@ -266,6 +285,7 @@
                 request_ack_packet.PutHex8 (packet.GetU8(&offset));
                 request_ack_packet.PutHex16 (packet.GetU16(&offset));
                 request_ack_packet.PutHex32 (packet.GetU32(&offset));
+                m_is_running.SetValue(false, eBroadcastAlways);
                 // Ack to the exception or termination
                 SendRequestPacketNoLock (request_ack_packet);
             }
@@ -688,12 +708,14 @@
         if (command_name)
         {
             const bool is_reply = ExtractIsReply(first_packet_byte);
-            s.Printf ("%s {%u:%u} <0x%4.4x> %s", 
-                      is_reply ? "<--" : "-->", 
-                      key,
+            s.Printf ("(running=%i) %s %24s: 0x%2.2x 0x%2.2x 0x%4.4x 0x%8.8x ",
+                      IsRunning(),
+                      is_reply ? "<--" : "-->",
+                      command_name,
+                      first_packet_byte,
                       sequence_id,
                       length,
-                      command_name);
+                      key);
             
             if (is_reply)
             {
@@ -944,7 +966,6 @@
                         {
                             const uint32_t count = packet.GetU32 (&offset);
                             
-                            s.Printf(" (count = %u:", count);
                             for (uint32_t i=0; i<count; ++i)
                             {
                                 const uint32_t cpu = packet.GetU32 (&offset);
@@ -968,7 +989,7 @@
                                         break;
                                 }
 
-                                s.Printf ("\n  cpu = 0x%8.8x, exc = %s (%u), code = %u (0x%8.8x), subcode = %u (0x%8.8x)\n", 
+                                s.Printf ("{ cpu = 0x%8.8x, exc = %s (%u), code = %u (0x%8.8x), subcode = %u (0x%8.8x)} ", 
                                           cpu, exc_cstr, exc, code, code, subcode, subcode);
                             }
                         }
@@ -1065,7 +1086,7 @@
     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
     const CommandType command = KDP_WRITEREGS;
     // Size is header + 4 byte cpu and 4 byte flavor
-    const uint32_t command_length = 8 + 4 + 4;
+    const uint32_t command_length = 8 + 4 + 4 + src_len;
     const uint32_t request_sequence_id = m_request_sequence_id;
     MakeRequestPacketHeader (command, request_packet, command_length);
     request_packet.PutHex32 (cpu);
@@ -1085,16 +1106,14 @@
 
 
 bool
-CommunicationKDP::SendRequestResume (uint32_t cpu_mask)
+CommunicationKDP::SendRequestResume ()
 {
-    if (cpu_mask == 0)
-        cpu_mask = GetCPUMask();
     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
     const CommandType command = KDP_RESUMECPUS;
     const uint32_t command_length = 12;
     const uint32_t request_sequence_id = m_request_sequence_id;
     MakeRequestPacketHeader (command, request_packet, command_length);
-    request_packet.PutHex32(cpu_mask);
+    request_packet.PutHex32(GetCPUMask());
 
     DataExtractor reply_packet;
     if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))

Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h?rev=164584&r1=164583&r2=164584&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h (original)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h Mon Sep 24 21:40:06 2012
@@ -111,7 +111,7 @@
     bool
     IsRunning() const
     {
-        return m_public_is_running.GetValue();
+        return m_is_running.GetValue();
     }
 
     //------------------------------------------------------------------
@@ -213,9 +213,8 @@
     uint32_t
     GetCPUSubtype ();
 
-    // If cpu_mask is zero, then we will resume all CPUs
     bool
-    SendRequestResume (uint32_t cpu_mask = 0);
+    SendRequestResume ();
 
     bool
     SendRequestSuspend ();
@@ -310,8 +309,7 @@
     lldb::ByteOrder m_byte_order;
     uint32_t m_packet_timeout;
     lldb_private::Mutex m_sequence_mutex;    // Restrict access to sending/receiving packets to a single thread at a time
-    lldb_private::Predicate<bool> m_public_is_running;
-    lldb_private::Predicate<bool> m_private_is_running;
+    lldb_private::Predicate<bool> m_is_running;
     uint32_t m_session_key;
     uint8_t m_request_sequence_id;
     uint8_t m_exception_sequence_id;

Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp?rev=164584&r1=164583&r2=164584&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp (original)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp Mon Sep 24 21:40:06 2012
@@ -28,7 +28,6 @@
 #include "ProcessKDP.h"
 #include "ProcessKDPLog.h"
 #include "ThreadKDP.h"
-#include "StopInfoMachException.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -102,7 +101,8 @@
     Process (target, listener),
     m_comm("lldb.process.kdp-remote.communication"),
     m_async_broadcaster (NULL, "lldb.process.kdp-remote.async-broadcaster"),
-    m_async_thread (LLDB_INVALID_HOST_THREAD)
+    m_async_thread (LLDB_INVALID_HOST_THREAD),
+    m_destroy_in_process (false)
 {
     m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit,   "async thread should exit");
     m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue,           "async thread continue");
@@ -214,6 +214,8 @@
                     ArchSpec kernel_arch;
                     kernel_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
                     m_target.SetArchitecture(kernel_arch);
+                    // Set the thread ID
+                    UpdateThreadListIfNeeded ();
                     SetID (1);
                     GetThreadList ();
                     SetPrivateState (eStateStopped);
@@ -233,10 +235,16 @@
 //                      }            
                     }
                 }
+                else
+                {
+                    puts ("KDP_CONNECT failed"); // REMOVE THIS
+                    error.SetErrorString("KDP_REATTACH failed");
+                }
             }
             else
             {
-                error.SetErrorString("KDP reattach failed");
+                puts ("KDP_REATTACH failed"); // REMOVE THIS
+                error.SetErrorString("KDP_REATTACH failed");
             }
         }
         else
@@ -320,42 +328,46 @@
     if (!IS_VALID_LLDB_HOST_THREAD(m_async_thread))
         StartAsyncThread ();
 
-    const uint32_t num_threads = m_thread_list.GetSize();
-    uint32_t resume_cpu_mask = 0;
+    bool resume = false;
     
-    for (uint32_t idx = 0; idx < num_threads; ++idx)
+    // With KDP there is only one thread we can tell what to do
+    ThreadSP kernel_thread_sp (GetKernelThread(m_thread_list, m_thread_list));
+    if (kernel_thread_sp)
     {
-        ThreadSP thread_sp (m_thread_list.GetThreadAtIndex(idx));
-        const StateType thread_resume_state = thread_sp->GetState();
+        const StateType thread_resume_state = kernel_thread_sp->GetTemporaryResumeState();
         switch (thread_resume_state)
         {
-            case eStateStopped:
             case eStateSuspended:
                 // Nothing to do here when a thread will stay suspended
                 // we just leave the CPU mask bit set to zero for the thread
+                puts("REMOVE THIS: ProcessKDP::DoResume () -- thread suspended");
                 break;
                 
             case eStateStepping:
-            case eStateRunning:
-                thread_sp->GetRegisterContext()->HardwareSingleStep (thread_resume_state == eStateStepping);
-                // Thread ID is the bit we need for the CPU mask
-                resume_cpu_mask |= thread_sp->GetID();
+                puts("REMOVE THIS: ProcessKDP::DoResume () -- thread stepping");
+                kernel_thread_sp->GetRegisterContext()->HardwareSingleStep (true);
+                resume = true;
                 break;
-                
+    
+            case eStateRunning:
+                puts("REMOVE THIS: ProcessKDP::DoResume () -- thread running");
+                kernel_thread_sp->GetRegisterContext()->HardwareSingleStep (false);
+                resume = true;
                 break;
-                
+
             default:
+                // The only valid thread resume states are listed above
                 assert (!"invalid thread resume state");
                 break;
         }
     }
-    if (log)
-        log->Printf ("ProcessKDP::DoResume () sending resume with cpu_mask = 0x%8.8x",
-                     resume_cpu_mask);
-    if (resume_cpu_mask)
+
+    if (resume)
     {
+        if (log)
+            log->Printf ("ProcessKDP::DoResume () sending resume");
         
-        if (m_comm.SendRequestResume (resume_cpu_mask))
+        if (m_comm.SendRequestResume ())
         {
             m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue);
             SetPrivateState(eStateRunning);
@@ -365,12 +377,30 @@
     }
     else
     {
-        error.SetErrorString ("all threads suspended");        
+        error.SetErrorString ("kernel thread is suspended");        
     }
     
     return error;
 }
 
+lldb::ThreadSP
+ProcessKDP::GetKernelThread(ThreadList &old_thread_list, ThreadList &new_thread_list)
+{
+    // KDP only tells us about one thread/core. Any other threads will usually
+    // be the ones that are read from memory by the OS plug-ins.
+    const lldb::tid_t kernel_tid = 1;
+    ThreadSP thread_sp (old_thread_list.FindThreadByID (kernel_tid, false));
+    if (!thread_sp)
+    {
+        thread_sp.reset(new ThreadKDP (shared_from_this(), kernel_tid));
+        new_thread_list.AddThread(thread_sp);
+    }
+    return thread_sp;
+}
+
+
+
+
 bool
 ProcessKDP::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
 {
@@ -379,20 +409,10 @@
     if (log && log->GetMask().Test(KDP_LOG_VERBOSE))
         log->Printf ("ProcessKDP::%s (pid = %llu)", __FUNCTION__, GetID());
     
-    // We currently are making only one thread per core and we
-    // actually don't know about actual threads. Eventually we
-    // want to get the thread list from memory and note which
-    // threads are on CPU as those are the only ones that we 
-    // will be able to resume.
-    const uint32_t cpu_mask = m_comm.GetCPUMask();
-    for (uint32_t cpu_mask_bit = 1; cpu_mask_bit & cpu_mask; cpu_mask_bit <<= 1)
-    {
-        lldb::tid_t tid = cpu_mask_bit;
-        ThreadSP thread_sp (old_thread_list.FindThreadByID (tid, false));
-        if (!thread_sp)
-            thread_sp.reset(new ThreadKDP (shared_from_this(), tid));
-        new_thread_list.AddThread(thread_sp);
-    }
+    // Even though there is a CPU mask, it doesn't mean to can see each CPU
+    // indivudually, there is really only one. Lets call this thread 1.
+    GetKernelThread (old_thread_list, new_thread_list);
+
     return new_thread_list.GetSize(false) > 0;
 }
 
@@ -409,112 +429,24 @@
 {
     Error error;
     
-//    bool timed_out = false;
-    Mutex::Locker locker;
-    
-    if (m_public_state.GetValue() == eStateAttaching)
-    {
-        // We are being asked to halt during an attach. We need to just close
-        // our file handle and debugserver will go away, and we can be done...
-        m_comm.Disconnect();
-    }
-    else
-    {
-        if (!m_comm.SendRequestSuspend ())
-            error.SetErrorString ("KDP halt failed");
-    }
-    return error;
-}
-
-Error
-ProcessKDP::InterruptIfRunning (bool discard_thread_plans,
-                                bool catch_stop_event,
-                                EventSP &stop_event_sp)
-{
-    Error error;
-    
-    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
-    
-    bool paused_private_state_thread = false;
-    const bool is_running = m_comm.IsRunning();
-    if (log)
-        log->Printf ("ProcessKDP::InterruptIfRunning(discard_thread_plans=%i, catch_stop_event=%i) is_running=%i", 
-                     discard_thread_plans, 
-                     catch_stop_event,
-                     is_running);
-    
-    if (discard_thread_plans)
-    {
-        if (log)
-            log->Printf ("ProcessKDP::InterruptIfRunning() discarding all thread plans");
-        m_thread_list.DiscardThreadPlans();
-    }
-    if (is_running)
+    if (m_comm.IsRunning())
     {
-        if (catch_stop_event)
+        if (m_destroy_in_process)
         {
-            if (log)
-                log->Printf ("ProcessKDP::InterruptIfRunning() pausing private state thread");
-            PausePrivateStateThread();
-            paused_private_state_thread = true;
-        }
-        
-        bool timed_out = false;
-//        bool sent_interrupt = false;
-        Mutex::Locker locker;
-
-        // TODO: implement halt in CommunicationKDP
-//        if (!m_comm.SendInterrupt (locker, 1, sent_interrupt, timed_out))
-//        {
-//            if (timed_out)
-//                error.SetErrorString("timed out sending interrupt packet");
-//            else
-//                error.SetErrorString("unknown error sending interrupt packet");
-//            if (paused_private_state_thread)
-//                ResumePrivateStateThread();
-//            return error;
-//        }
-        
-        if (catch_stop_event)
-        {
-            // LISTEN HERE
-            TimeValue timeout_time;
-            timeout_time = TimeValue::Now();
-            timeout_time.OffsetWithSeconds(5);
-            StateType state = WaitForStateChangedEventsPrivate (&timeout_time, stop_event_sp);
-            
-            timed_out = state == eStateInvalid;
-            if (log)
-                log->Printf ("ProcessKDP::InterruptIfRunning() catch stop event: state = %s, timed-out=%i", StateAsCString(state), timed_out);
-            
-            if (timed_out)
-                error.SetErrorString("unable to verify target stopped");
+            // If we are attemping to destroy, we need to not return an error to
+            // Halt or DoDestroy won't get called.
+            // We are also currently running, so send a process stopped event
+            SetPrivateState (eStateStopped);
         }
-        
-        if (paused_private_state_thread)
+        else
         {
-            if (log)
-                log->Printf ("ProcessKDP::InterruptIfRunning() resuming private state thread");
-            ResumePrivateStateThread();
+            error.SetErrorString ("KDP cannot interrupt a running kernel");
         }
     }
     return error;
 }
 
 Error
-ProcessKDP::WillDetach ()
-{
-    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
-    if (log)
-        log->Printf ("ProcessKDP::WillDetach()");
-    
-    bool discard_thread_plans = true; 
-    bool catch_stop_event = true;
-    EventSP event_sp;
-    return InterruptIfRunning (discard_thread_plans, catch_stop_event, event_sp);
-}
-
-Error
 ProcessKDP::DoDetach()
 {
     Error error;
@@ -522,27 +454,33 @@
     if (log)
         log->Printf ("ProcessKDP::DoDetach()");
     
-    DisableAllBreakpointSites ();
-    
-    m_thread_list.DiscardThreadPlans();
-    
-    if (m_comm.IsConnected())
+    if (m_comm.IsRunning())
+    {
+        // We are running and we can't interrupt a running kernel, so we need
+        // to just close the connection to the kernel and hope for the best
+    }
+    else
     {
+        DisableAllBreakpointSites ();
+        
+        m_thread_list.DiscardThreadPlans();
+        
+        if (m_comm.IsConnected())
+        {
 
-        m_comm.SendRequestDisconnect();
+            m_comm.SendRequestDisconnect();
 
-        size_t response_size = m_comm.Disconnect ();
-        if (log)
-        {
-            if (response_size)
-                log->PutCString ("ProcessKDP::DoDetach() detach packet sent successfully");
-            else
-                log->PutCString ("ProcessKDP::DoDetach() detach packet send failed");
+            size_t response_size = m_comm.Disconnect ();
+            if (log)
+            {
+                if (response_size)
+                    log->PutCString ("ProcessKDP::DoDetach() detach packet sent successfully");
+                else
+                    log->PutCString ("ProcessKDP::DoDetach() detach packet send failed");
+            }
         }
     }
-    // Sleep for one second to let the process get all detached...
-    StopAsyncThread ();
-    
+    StopAsyncThread ();    
     m_comm.Clear();
     
     SetPrivateState (eStateDetached);
@@ -553,6 +491,14 @@
 }
 
 Error
+ProcessKDP::WillDestroy ()
+{
+    Error error;
+    m_destroy_in_process = true;
+    return error;
+}
+
+Error
 ProcessKDP::DoDestroy ()
 {
     // For KDP there really is no difference between destroy and detach
@@ -639,10 +585,18 @@
             BreakpointSite::Type bp_type = bp_site->GetType();
             if (bp_type == BreakpointSite::eExternal)
             {
-                if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress()))
+                if (m_destroy_in_process && m_comm.IsRunning())
+                {
+                    // We are trying to destroy our connection and we are running
                     bp_site->SetEnabled(false);
+                }
                 else
-                    error.SetErrorString ("KDP remove breakpoint failed");
+                {
+                    if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress()))
+                        bp_site->SetEnabled(false);
+                    else
+                        error.SetErrorString ("KDP remove breakpoint failed");
+                }
             }
             else
             {
@@ -787,8 +741,12 @@
                             is_running = true;
                             if (process->m_comm.WaitForPacketWithTimeoutMicroSeconds (exc_reply_packet, 1 * USEC_PER_SEC))
                             {
+                                ThreadSP thread_sp (process->GetKernelThread(process->GetThreadList(), process->GetThreadList()));
+                                thread_sp->GetRegisterContext()->InvalidateAllRegisters();
+                                static_cast<ThreadKDP *>(thread_sp.get())->SetStopInfoFrom_KDP_EXCEPTION (exc_reply_packet);
+
                                 // TODO: parse the stop reply packet
-                                is_running = false;
+                                is_running = false;                                
                                 process->SetPrivateState(eStateStopped);
                             }
                             else

Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h?rev=164584&r1=164583&r2=164584&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h (original)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h Mon Sep 24 21:40:06 2012
@@ -129,15 +129,15 @@
     DoHalt (bool &caused_stop);
     
     virtual lldb_private::Error
-    WillDetach ();
-    
-    virtual lldb_private::Error
     DoDetach ();
     
     virtual lldb_private::Error
     DoSignal (int signal);
     
     virtual lldb_private::Error
+    WillDestroy ();
+    
+    virtual lldb_private::Error
     DoDestroy ();
     
     virtual void
@@ -241,11 +241,9 @@
         eBroadcastBitAsyncThreadShouldExit          = (1 << 1)
     };
     
-
-    lldb_private::Error
-    InterruptIfRunning (bool discard_thread_plans,
-                        bool catch_stop_event,
-                        lldb::EventSP &stop_event_sp);
+    lldb::ThreadSP
+    GetKernelThread (lldb_private::ThreadList &old_thread_list,
+                     lldb_private::ThreadList &new_thread_list);
 
     //------------------------------------------------------------------
     /// Broadcaster event bits definitions.
@@ -253,6 +251,7 @@
     CommunicationKDP m_comm;
     lldb_private::Broadcaster m_async_broadcaster;
     lldb::thread_t m_async_thread;
+    bool m_destroy_in_process;
 
     bool
     StartAsyncThread ();

Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp?rev=164584&r1=164583&r2=164584&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp (original)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp Mon Sep 24 21:40:06 2012
@@ -28,6 +28,7 @@
 #include "RegisterContextKDP_arm.h"
 #include "RegisterContextKDP_i386.h"
 #include "RegisterContextKDP_x86_64.h"
+#include "Plugins/Process/Utility/StopInfoMachException.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -68,31 +69,17 @@
 bool
 ThreadKDP::WillResume (StateType resume_state)
 {
-    ClearStackFrames();
     // Call the Thread::WillResume first. If we stop at a signal, the stop info
     // class for signal will set the resume signal that we need below. The signal
     // stuff obeys the Process::UnixSignal defaults. 
     Thread::WillResume(resume_state);
 
+    ClearStackFrames();
+
     lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
     if (log)
         log->Printf ("Resuming thread: %4.4llx with state: %s.", GetID(), StateAsCString(resume_state));
 
-//    ProcessKDP &process = GetKDPProcess();
-//    switch (resume_state)
-//    {
-//    case eStateSuspended:
-//    case eStateStopped:
-//        // Don't append anything for threads that should stay stopped.
-//        break;
-//
-//    case eStateRunning:
-//    case eStateStepping:
-//        break;
-//
-//    default:
-//        break;
-//    }
     return true;
 }
 
@@ -192,25 +179,50 @@
         if (m_thread_stop_reason_stop_id != process_stop_id ||
             (m_actual_stop_info_sp && !m_actual_stop_info_sp->IsValid()))
         {
-            // TODO: can we query the initial state of the thread here?
-            // For now I am just going to pretend that a SIGSTOP happened.
-
-            SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, SIGSTOP));
-
-            // If GetKDPProcess().SetThreadStopInfo() doesn't find a stop reason
-            // for this thread, then m_actual_stop_info_sp will not ever contain
-            // a valid stop reason and the "m_actual_stop_info_sp->IsValid() == false"
-            // check will never be able to tell us if we have the correct stop info
-            // for this thread and we will continually send qThreadStopInfo packets
-            // down to the remote KDP server, so we need to keep our own notion
-            // of the stop ID that m_actual_stop_info_sp is valid for (even if it
-            // contains nothing). We use m_thread_stop_reason_stop_id for this below.
-    //        m_thread_stop_reason_stop_id = process_stop_id;
-    //        m_actual_stop_info_sp.reset();
-
+            if (m_cached_stop_info_sp)
+                SetStopInfo (m_cached_stop_info_sp);
+            else
+                SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, SIGSTOP));
         }
     }
     return m_actual_stop_info_sp;
 }
 
+void
+ThreadKDP::SetStopInfoFrom_KDP_EXCEPTION (const DataExtractor &exc_reply_packet)
+{
+    uint32_t offset = 0;
+    uint8_t reply_command = exc_reply_packet.GetU8(&offset);
+    if (reply_command == CommunicationKDP::KDP_EXCEPTION)
+    {
+        offset = 8;
+        const uint32_t count = exc_reply_packet.GetU32 (&offset);
+        if (count >= 1)
+        {
+            //const uint32_t cpu = exc_reply_packet.GetU32 (&offset);
+            offset += 4; // Skip the useless CPU field
+            const uint32_t exc_type = exc_reply_packet.GetU32 (&offset);
+            const uint32_t exc_code = exc_reply_packet.GetU32 (&offset);
+            const uint32_t exc_subcode = exc_reply_packet.GetU32 (&offset);
+            // We have to make a copy of the stop info because the thread list
+            // will iterate through the threads and clear all stop infos..
+            
+            // Let the StopInfoMachException::CreateStopReasonWithMachException()
+            // function update the PC if needed as we might hit a software breakpoint
+            // and need to decrement the PC (i386 and x86_64 need this) and KDP
+            // doesn't do this for us.
+            const bool pc_already_adjusted = false;
+            const bool adjust_pc_if_needed = true;
+
+            m_cached_stop_info_sp = StopInfoMachException::CreateStopReasonWithMachException (*this,
+                                                                                              exc_type,
+                                                                                              2,
+                                                                                              exc_code,
+                                                                                              exc_subcode,
+                                                                                              0,
+                                                                                              pc_already_adjusted,
+                                                                                              adjust_pc_if_needed);            
+        }
+    }
+}
 

Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h?rev=164584&r1=164583&r2=164584&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h (original)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h Mon Sep 24 21:40:06 2012
@@ -79,6 +79,9 @@
     {
         m_thread_dispatch_qaddr = thread_dispatch_qaddr;
     }
+    
+    void
+    SetStopInfoFrom_KDP_EXCEPTION (const lldb_private::DataExtractor &exc_reply_packet);
 
 protected:
     
@@ -90,6 +93,7 @@
     std::string m_thread_name;
     std::string m_dispatch_queue_name;
     lldb::addr_t m_thread_dispatch_qaddr;
+    lldb::StopInfoSP m_cached_stop_info_sp;
     //------------------------------------------------------------------
     // Member variables.
     //------------------------------------------------------------------

Modified: lldb/trunk/source/Plugins/Process/Utility/StopInfoMachException.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/StopInfoMachException.cpp?rev=164584&r1=164583&r2=164584&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/StopInfoMachException.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/StopInfoMachException.cpp Mon Sep 24 21:40:06 2012
@@ -242,6 +242,9 @@
 }
 
 
+
+
+
 StopInfoSP
 StopInfoMachException::CreateStopReasonWithMachException 
 (
@@ -250,11 +253,14 @@
     uint32_t exc_data_count,
     uint64_t exc_code,
     uint64_t exc_sub_code,
-    uint64_t exc_sub_sub_code
+    uint64_t exc_sub_sub_code,
+    bool pc_already_adjusted,
+    bool adjust_pc_if_needed
 )
 {
     if (exc_type != 0)
     {
+        uint32_t pc_decrement = 0;
         ExecutionContext exe_ctx (thread.shared_from_this());
         Target *target = exe_ctx.GetTargetPtr();
         const llvm::Triple::ArchType cpu = target ? target->GetArchitecture().GetMachine() : llvm::Triple::UnknownArch;
@@ -300,6 +306,7 @@
         case 6: // EXC_BREAKPOINT
             {
                 bool is_software_breakpoint = false;
+                bool is_trace_if_software_breakpoint_missing = false;
                 switch (cpu)
                 {
                 case llvm::Triple::x86:
@@ -323,9 +330,16 @@
                             return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID());
                         }
                     }
-                    else if (exc_code == 2) // EXC_I386_BPT
+                    else if (exc_code == 2 ||   // EXC_I386_BPT
+                             exc_code == 3)     // EXC_I386_BPTFLT
                     {
+                        // KDP returns EXC_I386_BPTFLT for trace breakpoints
+                        if (exc_code == 3)
+                            is_trace_if_software_breakpoint_missing = true;
+
                         is_software_breakpoint = true;
+                        if (!pc_already_adjusted)
+                            pc_decrement = 1;
                     }
                     break;
 
@@ -353,8 +367,11 @@
                         // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as EXC_BAD_ACCESS
                         return StopInfo::CreateStopReasonToTrace(thread);
                     }
-                    else
-                        is_software_breakpoint = exc_code == 1; // EXC_ARM_BREAKPOINT
+                    else if (exc_code == 1)
+                    {
+                        is_software_breakpoint = true;
+                        is_trace_if_software_breakpoint_missing = true;
+                    }
                     break;
 
                 default:
@@ -363,14 +380,22 @@
 
                 if (is_software_breakpoint)
                 {
-                    addr_t pc = thread.GetRegisterContext()->GetPC();
+                    RegisterContextSP reg_ctx_sp (thread.GetRegisterContext());
+                    addr_t pc = reg_ctx_sp->GetPC() - pc_decrement;
+
                     ProcessSP process_sp (thread.CalculateProcess());
 
                     lldb::BreakpointSiteSP bp_site_sp;
                     if (process_sp)
                         bp_site_sp = process_sp->GetBreakpointSiteList().FindByAddress(pc);
-                    if (bp_site_sp)
+                    if (bp_site_sp && bp_site_sp->IsEnabled())
                     {
+                        // Update the PC if we were asked to do so, but only do
+                        // so if we find a breakpoint that we know about cause
+                        // this could be a trap instruction in the code
+                        if (pc_decrement > 0 && adjust_pc_if_needed)
+                            reg_ctx_sp->SetPC (pc);
+
                         // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
                         // we can just report no reason.  We don't need to worry about stepping over the breakpoint here, that
                         // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
@@ -379,7 +404,8 @@
                         else
                             return StopInfoSP();
                     }
-                    else if (cpu == llvm::Triple::arm)
+                    
+                    if (is_trace_if_software_breakpoint_missing)
                     {
                         return StopInfo::CreateStopReasonToTrace (thread);
                     }

Modified: lldb/trunk/source/Plugins/Process/Utility/StopInfoMachException.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/StopInfoMachException.h?rev=164584&r1=164583&r2=164584&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/StopInfoMachException.h (original)
+++ lldb/trunk/source/Plugins/Process/Utility/StopInfoMachException.h Mon Sep 24 21:40:06 2012
@@ -61,8 +61,10 @@
                                        uint32_t exc_data_count,
                                        uint64_t exc_code, 
                                        uint64_t exc_sub_code,
-                                       uint64_t exc_sub_sub_code);
-    
+                                       uint64_t exc_sub_sub_code,
+                                       bool pc_already_adjusted = true,
+                                       bool adjust_pc_if_needed = false);
+
 protected:
     uint32_t m_exc_data_count;
     uint64_t m_exc_code;

Modified: lldb/trunk/source/Target/Thread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Thread.cpp?rev=164584&r1=164583&r2=164584&view=diff
==============================================================================
--- lldb/trunk/source/Target/Thread.cpp (original)
+++ lldb/trunk/source/Target/Thread.cpp Mon Sep 24 21:40:06 2012
@@ -204,6 +204,17 @@
     }
 }
 
+lldb::StopReason
+Thread::GetStopReason()
+{
+    lldb::StopInfoSP stop_info_sp (GetStopInfo ());
+    if (stop_info_sp)
+        stop_info_sp->GetStopReason();
+    return eStopReasonNone;
+}
+
+
+
 void
 Thread::SetStopInfo (const lldb::StopInfoSP &stop_info_sp)
 {
@@ -332,7 +343,7 @@
     m_completed_plan_stack.clear();
     m_discarded_plan_stack.clear();
 
-    SetTemporaryResumeState(resume_state);
+    m_temporary_resume_state = resume_state;
     
     // This is a little dubious, but we are trying to limit how often we actually fetch stop info from
     // the target, 'cause that slows down single stepping.  So assume that if we got to the point where





More information about the lldb-commits mailing list