[Lldb-commits] [lldb] r135563 - in /lldb/trunk/source: Commands/CommandObjectExpression.cpp Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp Plugins/Process/MacOSX-Kernel/CommunicationKDP.h Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp Plugins/Process/MacOSX-Kernel/ProcessKDP.h

Greg Clayton gclayton at apple.com
Tue Jul 19 20:41:07 PDT 2011


Author: gclayton
Date: Tue Jul 19 22:41:06 2011
New Revision: 135563

URL: http://llvm.org/viewvc/llvm-project?rev=135563&view=rev
Log:
Added KDP resume, suspend, set/remove breakpoint, and kernel version support.
Also we now display a live update of the kexts that we are loading.


Modified:
    lldb/trunk/source/Commands/CommandObjectExpression.cpp
    lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.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

Modified: lldb/trunk/source/Commands/CommandObjectExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectExpression.cpp?rev=135563&r1=135562&r2=135563&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectExpression.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectExpression.cpp Tue Jul 19 22:41:06 2011
@@ -198,9 +198,12 @@
     case eInputReaderActivate:
         if (!batch_mode)
         {
-            StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
-            out_stream->Printf("%s\n", "Enter expressions, then terminate with an empty line to evaluate:");
-            out_stream->Flush();
+            StreamSP async_strm_sp(reader.GetDebugger().GetAsyncOutputStream());
+            if (async_strm_sp)
+            {
+                async_strm_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n");
+                async_strm_sp->Flush();
+            }
         }
         // Fall through
     case eInputReaderReactivate:
@@ -228,9 +231,12 @@
         reader.SetIsDone (true);
         if (!batch_mode)
         {
-            StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
-            out_stream->Printf("%s\n", "Expression evaluation cancelled.");
-            out_stream->Flush();
+            StreamSP async_strm_sp (reader.GetDebugger().GetAsyncOutputStream());
+            if (async_strm_sp)
+            {
+                async_strm_sp->PutCString("Expression evaluation cancelled.\n");
+                async_strm_sp->Flush();
+            }
         }
         break;
         

Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp?rev=135563&r1=135562&r2=135563&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp (original)
+++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp Tue Jul 19 22:41:06 2011
@@ -10,6 +10,7 @@
 #include "lldb/Breakpoint/StoppointCallbackContext.h"
 #include "lldb/Core/DataBuffer.h"
 #include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Debugger.h"
 #include "lldb/Core/Log.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/PluginManager.h"
@@ -499,8 +500,25 @@
     if (!ReadKextSummaries (kext_summary_addr, count, kext_summaries))
         return false;
 
+    Stream *s = &m_process->GetTarget().GetDebugger().GetOutputStream();
     for (uint32_t i = 0; i < count; i++)
     {
+        if (s)
+        {
+            const uint8_t *u = (const uint8_t *)kext_summaries[i].uuid.GetBytes();
+            if (u)
+            {
+                s->Printf("Loading kext: %2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X 0x%16.16llx \"%s\"...\n",
+                          u[ 0], u[ 1], u[ 2], u[ 3], u[ 4], u[ 5], u[ 6], u[ 7],
+                          u[ 8], u[ 9], u[10], u[11], u[12], u[13], u[14], u[15],
+                          kext_summaries[i].address, kext_summaries[i].name);
+            }   
+            else
+            {
+                s->Printf("0x%16.16llx \"%s\"...\n", kext_summaries[i].address, kext_summaries[i].name);
+            }
+        }
+        
         DataExtractor data; // Load command data
         if (ReadMachHeader (kext_summaries[i], &data))
         {
@@ -868,7 +886,7 @@
 {
     if (log == NULL)
         return;
-    uint8_t *u = (uint8_t *)uuid.GetBytes();
+    const uint8_t *u = (uint8_t *)uuid.GetBytes();
 
     if (address == LLDB_INVALID_ADDRESS)
     {

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=135563&r1=135562&r2=135563&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp (original)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp Tue Jul 19 22:41:06 2011
@@ -469,6 +469,33 @@
     return false;
 }
 
+const char *
+CommunicationKDP::GetKernelVersion ()
+{
+    if (m_kernel_version.empty())
+        SendRequestKernelVersion ();
+    return m_kernel_version.c_str();
+}
+
+bool
+CommunicationKDP::SendRequestKernelVersion ()
+{
+    PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
+    const CommandType command = eCommandTypeKernelVersion;
+    const uint32_t command_length = 8;
+    const uint32_t request_sequence_id = m_request_sequence_id;
+    MakeRequestPacketHeader (command, request_packet, command_length);
+    DataExtractor reply_packet;
+    if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+    {
+        const char *kernel_version_cstr = reply_packet.PeekCStr(8);
+        if (kernel_version_cstr && kernel_version_cstr[0])
+            m_kernel_version.assign (kernel_version_cstr);
+        return true;
+    }
+    return false;
+}
+
 bool
 CommunicationKDP::SendRequestDisconnect ()
 {
@@ -700,7 +727,14 @@
                             const uint32_t count = packet.GetByteSize() - offset;
                             s.Printf(" (error = 0x%8.8x <0x%x>:\n", error, count); 
                             if (count > 0)
-                                DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, count), count, 32, LLDB_INVALID_ADDRESS);
+                                packet.Dump (&s,                        // Stream to dump to
+                                             offset,                    // Offset within "packet"
+                                             eFormatBytesWithASCII,     // Format to use
+                                             1,                         // Size of each item in bytes
+                                             count,                     // Number of items
+                                             16,                        // Number per line
+                                             m_last_read_memory_addr,   // Don't show addresses before each line
+                                             0, 0);                     // No bitfields
                         }
                         break;
 
@@ -721,9 +755,26 @@
                         }
                         break;
 
+                    case eCommandTypeKernelVersion:
+                        {
+                            const char *kernel_version = packet.PeekCStr(8);
+                            s.Printf(" (version = \"%s\")", kernel_version);
+                        }
+                        break;
+                        
                     case eCommandTypeMaxBytes:
+                        {
+                            const uint32_t max_bytes = packet.GetU32 (&offset);
+                            s.Printf(" (max_bytes = 0x%8.8x (%u))", max_bytes, max_bytes);
+                        }
+                        break;
                     case eCommandTypeImagePath:
-                    case eCommandTypeKernelVersion:
+                        {
+                            const char *path = packet.GetCStr(&offset);
+                            s.Printf(" (path = \"%s\")", path);
+                        }
+                        break;
+                    default:
                         s.Printf(" (add support for dumping this packet reply!!!"); 
                         break;
                     
@@ -747,7 +798,19 @@
                     case eCommandTypeHostInfo:
                     case eCommandTypeVersion:
                     case eCommandTypeRegions:
+                    case eCommandTypeKernelVersion:
+                    case eCommandTypeMaxBytes:
+                    case eCommandTypeImagePath:
+                    case eCommandTypeSuspend:
                         // No args, just the header in the request...
+                        s.PutCString(" ()");
+                        break;
+
+                    case eCommandTypeResume:
+                        {
+                            const uint32_t cpu_mask = packet.GetU32 (&offset);
+                            s.Printf(" (cpu_mask = 0x%8.8x)", cpu_mask);
+                        }
                         break;
 
                     case eCommandTypeReadMemory:
@@ -755,6 +818,7 @@
                             const uint32_t addr = packet.GetU32 (&offset);
                             const uint32_t size = packet.GetU32 (&offset);
                             s.Printf(" (addr = 0x%8.8x, size=%u)", addr, size);
+                            m_last_read_memory_addr = addr;
                         }
                         break;
 
@@ -773,6 +837,7 @@
                             const uint64_t addr = packet.GetU64 (&offset);
                             const uint32_t size = packet.GetU32 (&offset);
                             s.Printf(" (addr = 0x%16.16llx, size=%u)", addr, size);
+                            m_last_read_memory_addr = addr;
                         }
                         break;
 
@@ -812,16 +877,71 @@
                         }
                         break;
 
-                    case eCommandTypeMaxBytes:
+
+                    case eCommandTypeBreakpointSet:
+                    case eCommandTypeBreakpointRemove:
+                        {
+                            const uint32_t addr = packet.GetU32 (&offset);
+                            s.Printf(" (addr = 0x%8.8x)", addr);
+                        }
+                        break;
+
+                    case eCommandTypeBreakpointSet64:
+                    case eCommandTypeBreakpointRemove64:
+                        {
+                            const uint64_t addr = packet.GetU64 (&offset);
+                            s.Printf(" (addr = 0x%16.16llx)", addr);
+                        }
+                        break;
+
 
                     case eCommandTypeLoad:
-                    case eCommandTypeImagePath:
-                    case eCommandTypeSuspend:
-                    case eCommandTypeResume:
+                        {
+                            const char *path = packet.GetCStr(&offset);
+                            s.Printf(" (path = \"%s\")", path);
+                        }
+                        break;
+
                     case eCommandTypeException:
+                        {
+                            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);
+                                const uint32_t exc = packet.GetU32 (&offset);
+                                const uint32_t code = packet.GetU32 (&offset);
+                                const uint32_t subcode = packet.GetU32 (&offset);
+                                const char *exc_cstr = NULL;
+                                switch (exc)
+                                {
+                                    case 1:  exc_cstr = "EXC_BAD_ACCESS"; break;
+                                    case 2:  exc_cstr = "EXC_BAD_INSTRUCTION"; break;
+                                    case 3:  exc_cstr = "EXC_ARITHMETIC"; break;
+                                    case 4:  exc_cstr = "EXC_EMULATION"; break;
+                                    case 5:  exc_cstr = "EXC_SOFTWARE"; break;
+                                    case 6:  exc_cstr = "EXC_BREAKPOINT"; break;
+                                    case 7:  exc_cstr = "EXC_SYSCALL"; break;
+                                    case 8:  exc_cstr = "EXC_MACH_SYSCALL"; break;
+                                    case 9:  exc_cstr = "EXC_RPC_ALERT"; break;
+                                    case 10: exc_cstr = "EXC_CRASH"; break;
+                                    default:
+                                        break;
+                                }
+
+                                s.Printf ("\n  cpu = 0x%8.8x, exc = %s (%u), code = %u (0x%8.8x), subcode = %u (0x%8.8x)\n", 
+                                          cpu, exc_cstr, exc, code, code, subcode, subcode);
+                            }
+                        }
+                        break;
+
                     case eCommandTypeTermination:
-                    case eCommandTypeBreakpointSet:
-                    case eCommandTypeBreakpointRemove:
+                        {
+                            const uint32_t term_code = packet.GetU32 (&offset);
+                            const uint32_t exit_code = packet.GetU32 (&offset);
+                            s.Printf(" (term_code = 0x%8.8x (%u), exit_code = 0x%8.8x (%u))", term_code, term_code, exit_code, exit_code);
+                        }
                         break;
 
                     case eCommandTypeReattach:
@@ -830,12 +950,6 @@
                             s.Printf(" (reply_port=%u)", reply_port);
                         }
                         break;
-
-                    case eCommandTypeBreakpointSet64:
-                    case eCommandTypeBreakpointRemove64:
-                    case eCommandTypeKernelVersion:
-                        
-                        break;
                 }
             }
         }
@@ -903,3 +1017,56 @@
     return 0;
 }
 
+
+bool
+CommunicationKDP::SendRequestResume (uint32_t cpu_mask)
+{
+    if (cpu_mask == 0)
+        cpu_mask = GetCPUMask();
+    PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
+    const CommandType command = eCommandTypeResume;
+    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);
+
+    DataExtractor reply_packet;
+    if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+        return true;
+    return false;
+}
+
+bool
+CommunicationKDP::SendRequestBreakpoint (bool set, addr_t addr)
+{
+    PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
+    bool use_64 = (GetVersion() >= 11);
+    uint32_t command_addr_byte_size = use_64 ? 8 : 4;
+    const CommandType command = set ? (use_64 ? eCommandTypeBreakpointSet64    : eCommandTypeBreakpointSet   ):
+                                      (use_64 ? eCommandTypeBreakpointRemove64 : eCommandTypeBreakpointRemove);
+
+    const uint32_t command_length = 8 + command_addr_byte_size;
+    const uint32_t request_sequence_id = m_request_sequence_id;
+    MakeRequestPacketHeader (command, request_packet, command_length);
+    request_packet.PutMaxHex64 (addr, command_addr_byte_size);
+    
+    DataExtractor reply_packet;
+    if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+        return true;
+    return false;
+}
+
+bool
+CommunicationKDP::SendRequestSuspend ()
+{
+    PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
+    const CommandType command = eCommandTypeSuspend;
+    const uint32_t command_length = 8;
+    const uint32_t request_sequence_id = m_request_sequence_id;
+    MakeRequestPacketHeader (command, request_packet, command_length);
+    DataExtractor reply_packet;
+    if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+        return true;
+    return false;
+}
+

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=135563&r1=135562&r2=135563&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h (original)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h Tue Jul 19 22:41:06 2011
@@ -65,6 +65,11 @@
         eCommandTypeKernelVersion
     } CommandType;
 
+    enum 
+    {
+        eFeatureLocalBreakpointsSupported = (1u << 0),
+    };
+
     typedef enum
     {
         KDP_PROTERR_SUCCESS = 0,
@@ -173,12 +178,21 @@
                               uint32_t dst_size,
                               lldb_private::Error &error);
     
+    const char *
+    GetKernelVersion ();
+    
     uint32_t
     GetVersion ();
 
     uint32_t
     GetFeatureFlags ();
 
+    bool
+    LocalBreakpointsAreSupported ()
+    {
+        return (GetFeatureFlags() & eFeatureLocalBreakpointsSupported) != 0;
+    }
+
     uint32_t
     GetCPUMask ();
     
@@ -188,6 +202,16 @@
     uint32_t
     GetCPUSubtype ();
 
+    // If cpu_mask is zero, then we will resume all CPUs
+    bool
+    SendRequestResume (uint32_t cpu_mask = 0);
+
+    bool
+    SendRequestSuspend ();
+
+    bool
+    SendRequestBreakpoint (bool set, lldb::addr_t addr);
+
 protected:
     typedef std::list<std::string> packet_collection;
 
@@ -216,6 +240,8 @@
     bool
     SendRequestHostInfo ();
 
+    bool
+    SendRequestKernelVersion ();
     
     void
     DumpPacket (lldb_private::Stream &s, 
@@ -280,6 +306,8 @@
     uint32_t m_kdp_hostinfo_cpu_mask;
     uint32_t m_kdp_hostinfo_cpu_type;
     uint32_t m_kdp_hostinfo_cpu_subtype;
+    std::string m_kernel_version;
+    lldb::addr_t m_last_read_memory_addr; // Last memory read address for logging
 private:
     //------------------------------------------------------------------
     // For CommunicationKDP only

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=135563&r1=135562&r2=135563&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp (original)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp Tue Jul 19 22:41:06 2011
@@ -14,6 +14,7 @@
 // C++ Includes
 // Other libraries and framework includes
 #include "lldb/Core/ConnectionFileDescriptor.h"
+#include "lldb/Core/Debugger.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/State.h"
 #include "lldb/Host/Host.h"
@@ -183,10 +184,19 @@
                     ArchSpec kernel_arch;
                     kernel_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
                     m_target.SetArchitecture(kernel_arch);
-                    
                     SetID (1);
                     UpdateThreadListIfNeeded ();
                     SetPrivateState (eStateStopped);
+                    StreamSP async_strm_sp(m_target.GetDebugger().GetAsyncOutputStream());
+                    if (async_strm_sp)
+                    {
+                        const char *kernel_version = m_comm.GetKernelVersion ();
+                        if (kernel_version)
+                        {
+                            async_strm_sp->Printf ("KDP connected to %s\n", kernel_version);
+                            async_strm_sp->Flush();
+                        }
+                    }
                 }
             }
             else
@@ -237,24 +247,6 @@
     return error;
 }
 
-size_t
-ProcessKDP::AttachInputReaderCallback (void *baton, 
-                                       InputReader *reader, 
-                                       lldb::InputReaderAction notification,
-                                       const char *bytes, 
-                                       size_t bytes_len)
-{
-    if (notification == eInputReaderGotToken)
-    {
-//        ProcessKDP *process = (ProcessKDP *)baton;
-//        if (process->m_waiting_for_attach)
-//            process->m_waiting_for_attach = false;
-        reader->SetIsDone(true);
-        return 1;
-    }
-    return 0;
-}
-
 Error
 ProcessKDP::DoAttachToProcessWithName (const char *process_name, bool wait_for_launch)
 {
@@ -286,7 +278,8 @@
 ProcessKDP::DoResume ()
 {
     Error error;
-    error.SetErrorString ("ProcessKDP::DoResume () is not implemented yet");
+    if (!m_comm.SendRequestResume ())
+        error.SetErrorString ("KDP resume failed");
     return error;
 }
 
@@ -354,15 +347,8 @@
     }
     else
     {
-        // TODO: add the ability to halt a running kernel
-        error.SetErrorString ("halt not supported in kdp-remote plug-in");
-//        if (!m_comm.SendInterrupt (locker, 2, caused_stop, timed_out))
-//        {
-//            if (timed_out)
-//                error.SetErrorString("timed out sending interrupt packet");
-//            else
-//                error.SetErrorString("unknown error sending interrupt packet");
-//        }
+        if (!m_comm.SendRequestSuspend ())
+            error.SetErrorString ("KDP halt failed");
     }
     return error;
 }
@@ -574,12 +560,26 @@
 Error
 ProcessKDP::EnableBreakpoint (BreakpointSite *bp_site)
 {
+    if (m_comm.LocalBreakpointsAreSupported ())
+    {
+        Error error;
+        if (!m_comm.SendRequestBreakpoint(true, bp_site->GetLoadAddress()))
+            error.SetErrorString ("KDP set breakpoint failed");
+        return error;
+    }
     return EnableSoftwareBreakpoint (bp_site);
 }
 
 Error
 ProcessKDP::DisableBreakpoint (BreakpointSite *bp_site)
 {
+    if (m_comm.LocalBreakpointsAreSupported ())
+    {
+        Error error;
+        if (!m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress()))
+            error.SetErrorString ("KDP remove breakpoint failed");
+        return error;
+    }
     return DisableSoftwareBreakpoint (bp_site);
 }
 

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=135563&r1=135562&r2=135563&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h (original)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h Tue Jul 19 22:41:06 2011
@@ -265,13 +265,6 @@
     lldb::StateType
     SetThreadStopInfo (StringExtractor& stop_packet);
     
-    static size_t
-    AttachInputReaderCallback (void *baton, 
-                               lldb_private::InputReader *reader, 
-                               lldb::InputReaderAction notification,
-                               const char *bytes, 
-                               size_t bytes_len);
-    
 private:
     //------------------------------------------------------------------
     // For ProcessKDP only





More information about the lldb-commits mailing list