[Lldb-commits] [lldb] r135240 - in /lldb/trunk/source/Plugins/Process/MacOSX-Kernel: ./ CommunicationKDP.cpp CommunicationKDP.h ProcessKDP.cpp ProcessKDP.h ProcessKDPLog.cpp ProcessKDPLog.h

Greg Clayton gclayton at apple.com
Thu Jul 14 20:27:12 PDT 2011


Author: gclayton
Date: Thu Jul 14 22:27:12 2011
New Revision: 135240

URL: http://llvm.org/viewvc/llvm-project?rev=135240&view=rev
Log:
Hollowed out process plug-in to do KDP darwin kernel debugging.


Added:
    lldb/trunk/source/Plugins/Process/MacOSX-Kernel/
    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/ProcessKDPLog.cpp
    lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h

Added: 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=135240&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp (added)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp Thu Jul 14 22:27:12 2011
@@ -0,0 +1,403 @@
+//===-- CommunicationKDP.cpp ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "CommunicationKDP.h"
+
+// C Includes
+#include <limits.h>
+#include <string.h>
+
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/TimeValue.h"
+#include "lldb/Target/Process.h"
+#include "Utility/StringExtractor.h"
+
+// Project includes
+#include "ProcessKDPLog.h"
+
+#define DEBUGSERVER_BASENAME    "debugserver"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// CommunicationKDP constructor
+//----------------------------------------------------------------------
+CommunicationKDP::CommunicationKDP (const char *comm_name) :
+    Communication(comm_name),
+    m_packet_timeout (1),
+    m_sequence_mutex (Mutex::eMutexTypeRecursive),
+    m_public_is_running (false),
+    m_private_is_running (false),
+    m_send_acks (true)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+CommunicationKDP::~CommunicationKDP()
+{
+    if (IsConnected())
+    {
+        Disconnect();
+    }
+}
+
+char
+CommunicationKDP::CalculcateChecksum (const char *payload, size_t payload_length)
+{
+    int checksum = 0;
+
+    // We only need to compute the checksum if we are sending acks
+    if (GetSendAcks ())
+    {
+        for (size_t i = 0; i < payload_length; ++i)
+            checksum += payload[i];
+    }
+    return checksum & 255;
+}
+
+size_t
+CommunicationKDP::SendAck ()
+{
+    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
+    if (log)
+        log->Printf ("send packet: +");
+    ConnectionStatus status = eConnectionStatusSuccess;
+    char ack_char = '+';
+    return Write (&ack_char, 1, status, NULL);
+}
+
+size_t
+CommunicationKDP::SendNack ()
+{
+    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
+    if (log)
+        log->Printf ("send packet: -");
+    ConnectionStatus status = eConnectionStatusSuccess;
+    char nack_char = '-';
+    return Write (&nack_char, 1, status, NULL);
+}
+
+size_t
+CommunicationKDP::SendPacket (lldb_private::StreamString &payload)
+{
+    Mutex::Locker locker(m_sequence_mutex);
+    const std::string &p (payload.GetString());
+    return SendPacketNoLock (p.c_str(), p.size());
+}
+
+size_t
+CommunicationKDP::SendPacket (const char *payload)
+{
+    Mutex::Locker locker(m_sequence_mutex);
+    return SendPacketNoLock (payload, ::strlen (payload));
+}
+
+size_t
+CommunicationKDP::SendPacket (const char *payload, size_t payload_length)
+{
+    Mutex::Locker locker(m_sequence_mutex);
+    return SendPacketNoLock (payload, payload_length);
+}
+
+size_t
+CommunicationKDP::SendPacketNoLock (const char *payload, size_t payload_length)
+{
+    if (IsConnected())
+    {
+        StreamString packet(0, 4, eByteOrderBig);
+
+        packet.PutChar('$');
+        packet.Write (payload, payload_length);
+        packet.PutChar('#');
+        packet.PutHex8(CalculcateChecksum (payload, payload_length));
+
+        LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
+        if (log)
+            log->Printf ("send packet: %.*s", (int)packet.GetSize(), packet.GetData());
+        ConnectionStatus status = eConnectionStatusSuccess;
+        size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL);
+        if (bytes_written == packet.GetSize())
+        {
+            if (GetSendAcks ())
+            {
+                if (GetAck () != '+')
+                {
+                    printf("get ack failed...");
+                    return 0;
+                }
+            }
+        }
+        else
+        {
+            LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
+            if (log)
+                log->Printf ("error: failed to send packet: %.*s", (int)packet.GetSize(), packet.GetData());
+        }
+        return bytes_written;
+    }
+    return 0;
+}
+
+char
+CommunicationKDP::GetAck ()
+{
+    StringExtractor packet;
+    if (WaitForPacketWithTimeoutMicroSeconds (packet, GetPacketTimeoutInMicroSeconds ()) == 1)
+        return packet.GetChar();
+    return 0;
+}
+
+bool
+CommunicationKDP::GetSequenceMutex (Mutex::Locker& locker)
+{
+    return locker.TryLock (m_sequence_mutex.GetMutex());
+}
+
+
+bool
+CommunicationKDP::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
+{
+    return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
+}
+
+size_t
+CommunicationKDP::WaitForPacketWithTimeoutMicroSeconds (StringExtractor &packet, uint32_t timeout_usec)
+{
+    Mutex::Locker locker(m_sequence_mutex);
+    return WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec);
+}
+
+size_t
+CommunicationKDP::WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractor &packet, uint32_t timeout_usec)
+{
+    uint8_t buffer[8192];
+    Error error;
+
+    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS | KDP_LOG_VERBOSE));
+
+    // Check for a packet from our cache first without trying any reading...
+    if (CheckForPacket (NULL, 0, packet))
+        return packet.GetStringRef().size();
+
+    bool timed_out = false;
+    while (IsConnected() && !timed_out)
+    {
+        lldb::ConnectionStatus status;
+        size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error);
+        
+        if (log)
+            log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %zu",
+                         __PRETTY_FUNCTION__,
+                         timeout_usec, 
+                         Communication::ConnectionStatusAsCString (status),
+                         error.AsCString(), 
+                         bytes_read);
+
+        if (bytes_read > 0)
+        {
+            if (CheckForPacket (buffer, bytes_read, packet))
+                return packet.GetStringRef().size();
+        }
+        else
+        {
+            switch (status)
+            {
+            case eConnectionStatusTimedOut:
+                timed_out = true;
+                break;
+            case eConnectionStatusSuccess:
+                //printf ("status = success but error = %s\n", error.AsCString("<invalid>"));
+                break;
+                
+            case eConnectionStatusEndOfFile:
+            case eConnectionStatusNoConnection:
+            case eConnectionStatusLostConnection:
+            case eConnectionStatusError:
+                Disconnect();
+                break;
+            }
+        }
+    }
+    packet.Clear ();    
+    return 0;
+}
+
+bool
+CommunicationKDP::CheckForPacket (const uint8_t *src, size_t src_len, StringExtractor &packet)
+{
+    // Put the packet data into the buffer in a thread safe fashion
+    Mutex::Locker locker(m_bytes_mutex);
+    
+    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
+
+    if (src && src_len > 0)
+    {
+        if (log && log->GetVerbose())
+        {
+            StreamString s;
+            log->Printf ("CommunicationKDP::%s adding %u bytes: %.*s",
+                         __FUNCTION__, 
+                         (uint32_t)src_len, 
+                         (uint32_t)src_len, 
+                         src);
+        }
+        m_bytes.append ((const char *)src, src_len);
+    }
+
+    // Parse up the packets into gdb remote packets
+    if (!m_bytes.empty())
+    {
+        // end_idx must be one past the last valid packet byte. Start
+        // it off with an invalid value that is the same as the current
+        // index.
+        size_t content_start = 0;
+        size_t content_length = 0;
+        size_t total_length = 0;
+        size_t checksum_idx = std::string::npos;
+
+        switch (m_bytes[0])
+        {
+            case '+':       // Look for ack
+            case '-':       // Look for cancel
+            case '\x03':    // ^C to halt target
+                content_length = total_length = 1;  // The command is one byte long...
+                break;
+
+            case '$':
+                // Look for a standard gdb packet?
+                {
+                    size_t hash_pos = m_bytes.find('#');
+                    if (hash_pos != std::string::npos)
+                    {
+                        if (hash_pos + 2 < m_bytes.size())
+                        {
+                            checksum_idx = hash_pos + 1;
+                            // Skip the dollar sign
+                            content_start = 1; 
+                            // Don't include the # in the content or the $ in the content length
+                            content_length = hash_pos - 1;  
+                            
+                            total_length = hash_pos + 3; // Skip the # and the two hex checksum bytes
+                        }
+                        else
+                        {
+                            // Checksum bytes aren't all here yet
+                            content_length = std::string::npos;
+                        }
+                    }
+                }
+                break;
+
+            default:
+                {
+                    // We have an unexpected byte and we need to flush all bad 
+                    // data that is in m_bytes, so we need to find the first
+                    // byte that is a '+' (ACK), '-' (NACK), \x03 (CTRL+C interrupt),
+                    // or '$' character (start of packet header) or of course,
+                    // the end of the data in m_bytes...
+                    const size_t bytes_len = m_bytes.size();
+                    bool done = false;
+                    uint32_t idx;
+                    for (idx = 1; !done && idx < bytes_len; ++idx)
+                    {
+                        switch (m_bytes[idx])
+                        {
+                        case '+':
+                        case '-':
+                        case '\x03':
+                        case '$':
+                            done = true;
+                            break;
+                                
+                        default:
+                            break;
+                        }
+                    }
+                    if (log)
+                        log->Printf ("CommunicationKDP::%s tossing %u junk bytes: '%.*s'",
+                                     __FUNCTION__, idx, idx, m_bytes.c_str());
+                    m_bytes.erase(0, idx);
+                }
+                break;
+        }
+
+        if (content_length == std::string::npos)
+        {
+            packet.Clear();
+            return false;
+        }
+        else if (total_length > 0)
+        {
+
+            // We have a valid packet...
+            assert (content_length <= m_bytes.size());
+            assert (total_length <= m_bytes.size());
+            assert (content_length <= total_length);
+            
+            bool success = true;
+            std::string &packet_str = packet.GetStringRef();
+            packet_str.assign (m_bytes, content_start, content_length);
+            if (m_bytes[0] == '$')
+            {
+                assert (checksum_idx < m_bytes.size());
+                if (::isxdigit (m_bytes[checksum_idx+0]) || 
+                    ::isxdigit (m_bytes[checksum_idx+1]))
+                {
+                    if (GetSendAcks ())
+                    {
+                        const char *packet_checksum_cstr = &m_bytes[checksum_idx];
+                        char packet_checksum = strtol (packet_checksum_cstr, NULL, 16);
+                        char actual_checksum = CalculcateChecksum (packet_str.c_str(), packet_str.size());
+                        success = packet_checksum == actual_checksum;
+                        if (!success)
+                        {
+                            if (log)
+                                log->Printf ("error: checksum mismatch: %.*s expected 0x%2.2x, got 0x%2.2x", 
+                                             (int)(total_length), 
+                                             m_bytes.c_str(),
+                                             (uint8_t)packet_checksum,
+                                             (uint8_t)actual_checksum);
+                        }
+                        // Send the ack or nack if needed
+                        if (!success)
+                            SendNack();
+                        else
+                            SendAck();
+                    }
+                    if (success)
+                    {
+                        if (log)
+                            log->Printf ("read packet: %.*s", (int)(total_length), m_bytes.c_str());
+                    }
+                }
+                else
+                {
+                    success = false;
+                    if (log)
+                        log->Printf ("error: invalid checksum in packet: '%s'\n", (int)(total_length), m_bytes.c_str());
+                }
+            }
+            m_bytes.erase(0, total_length);
+            packet.SetFilePos(0);
+            return success;
+        }
+    }
+    packet.Clear();
+    return false;
+}
+

Added: 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=135240&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h (added)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h Thu Jul 14 22:27:12 2011
@@ -0,0 +1,152 @@
+//===-- CommunicationKDP.h --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommunicationKDP_h_
+#define liblldb_CommunicationKDP_h_
+
+// C Includes
+// C++ Includes
+#include <list>
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/Communication.h"
+#include "lldb/Core/Listener.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Host/Predicate.h"
+#include "lldb/Host/TimeValue.h"
+
+class StringExtractor;
+
+class CommunicationKDP : public lldb_private::Communication
+{
+public:
+    enum
+    {
+        eBroadcastBitRunPacketSent = kLoUserBroadcastBit
+    };
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    CommunicationKDP (const char *comm_name);
+
+    virtual
+    ~CommunicationKDP();
+
+    size_t
+    SendPacket (const char *payload);
+
+    size_t
+    SendPacket (const char *payload,
+                size_t payload_length);
+
+    size_t
+    SendPacket (lldb_private::StreamString &response);
+
+    // Wait for a packet within 'nsec' seconds
+    size_t
+    WaitForPacketWithTimeoutMicroSeconds (StringExtractor &response,
+                                          uint32_t usec);
+
+    char
+    GetAck ();
+
+    size_t
+    SendAck ();
+
+    size_t
+    SendNack ();
+
+    char
+    CalculcateChecksum (const char *payload,
+                        size_t payload_length);
+
+    bool
+    GetSequenceMutex(lldb_private::Mutex::Locker& locker);
+
+    bool
+    CheckForPacket (const uint8_t *src, 
+                    size_t src_len, 
+                    StringExtractor &packet);
+    bool
+    IsRunning() const
+    {
+        return m_public_is_running.GetValue();
+    }
+
+    bool
+    GetSendAcks ()
+    {
+        return m_send_acks;
+    }
+
+    //------------------------------------------------------------------
+    // Set the global packet timeout.
+    //
+    // For clients, this is the timeout that gets used when sending
+    // packets and waiting for responses. For servers, this might not
+    // get used, and if it doesn't this should be moved to the
+    // CommunicationKDPClient.
+    //------------------------------------------------------------------
+    uint32_t 
+    SetPacketTimeout (uint32_t packet_timeout)
+    {
+        const uint32_t old_packet_timeout = m_packet_timeout;
+        m_packet_timeout = packet_timeout;
+        return old_packet_timeout;
+    }
+
+    uint32_t
+    GetPacketTimeoutInMicroSeconds () const
+    {
+        return m_packet_timeout * lldb_private::TimeValue::MicroSecPerSec;
+    }
+    //------------------------------------------------------------------
+    // Start a debugserver instance on the current host using the
+    // supplied connection URL.
+    //------------------------------------------------------------------
+    lldb_private::Error
+    StartDebugserverProcess (const char *connect_url,
+                             const char *unix_socket_name,
+                             lldb_private::ProcessLaunchInfo &launch_info); 
+
+    
+protected:
+    typedef std::list<std::string> packet_collection;
+
+    size_t
+    SendPacketNoLock (const char *payload, 
+                      size_t payload_length);
+
+    size_t
+    WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractor &response, 
+                                                uint32_t timeout_usec);
+
+    bool
+    WaitForNotRunningPrivate (const lldb_private::TimeValue *timeout_ptr);
+
+    //------------------------------------------------------------------
+    // Classes that inherit from CommunicationKDP can see and modify these
+    //------------------------------------------------------------------
+    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;
+    bool m_send_acks;
+
+private:
+    //------------------------------------------------------------------
+    // For CommunicationKDP only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (CommunicationKDP);
+};
+
+#endif  // liblldb_CommunicationKDP_h_

Added: 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=135240&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp (added)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp Thu Jul 14 22:27:12 2011
@@ -0,0 +1,725 @@
+//===-- ProcessKDP.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+#include <errno.h>
+#include <stdlib.h>
+
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/State.h"
+#include "lldb/Host/Host.h"
+
+// Project includes
+#include "ProcessKDP.h"
+#include "ProcessKDPLog.h"
+//#include "ThreadKDP.h"
+#include "StopInfoMachException.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+const char *
+ProcessKDP::GetPluginNameStatic()
+{
+    return "kdp-remote";
+}
+
+const char *
+ProcessKDP::GetPluginDescriptionStatic()
+{
+    return "KDP Remote protocol based debugging plug-in for darwin kernel debugging.";
+}
+
+void
+ProcessKDP::Terminate()
+{
+    PluginManager::UnregisterPlugin (ProcessKDP::CreateInstance);
+}
+
+
+Process*
+ProcessKDP::CreateInstance (Target &target, Listener &listener)
+{
+    return new ProcessKDP (target, listener);
+}
+
+bool
+ProcessKDP::CanDebug(Target &target)
+{
+    // For now we are just making sure the file exists for a given module
+    ModuleSP exe_module_sp(target.GetExecutableModule());
+    if (exe_module_sp.get())
+    {
+        const llvm::Triple &triple_ref = target.GetArchitecture().GetTriple();
+        if (triple_ref.getOS() == llvm::Triple::Darwin && 
+            triple_ref.getVendor() == llvm::Triple::Apple)
+        {
+
+            ObjectFile *exe_objfile = exe_module_sp->GetObjectFile();
+            if (exe_objfile->GetType() == ObjectFile::eTypeExecutable && 
+                exe_objfile->GetStrata() == ObjectFile::eStrataKernel)
+                return true;
+        }
+    }
+    return false;
+}
+
+//----------------------------------------------------------------------
+// ProcessKDP constructor
+//----------------------------------------------------------------------
+ProcessKDP::ProcessKDP(Target& target, Listener &listener) :
+    Process (target, listener),
+    m_comm("lldb.process.kdp-remote.communication"),
+    m_async_broadcaster ("lldb.process.kdp-remote.async-broadcaster"),
+    m_async_thread (LLDB_INVALID_HOST_THREAD)
+{
+//    m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit,   "async thread should exit");
+//    m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue,           "async thread continue");
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+ProcessKDP::~ProcessKDP()
+{
+    Clear();
+}
+
+//----------------------------------------------------------------------
+// PluginInterface
+//----------------------------------------------------------------------
+const char *
+ProcessKDP::GetPluginName()
+{
+    return "Process debugging plug-in that uses the Darwin KDP remote protocol";
+}
+
+const char *
+ProcessKDP::GetShortPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+ProcessKDP::GetPluginVersion()
+{
+    return 1;
+}
+
+Error
+ProcessKDP::WillLaunch (Module* module)
+{
+    Error error;
+    error.SetErrorString ("launching not supported in kdp-remote plug-in");
+    return error;
+}
+
+Error
+ProcessKDP::WillAttachToProcessWithID (lldb::pid_t pid)
+{
+    Error error;
+    error.SetErrorString ("attaching to a by process ID not supported in kdp-remote plug-in");
+    return error;
+}
+
+Error
+ProcessKDP::WillAttachToProcessWithName (const char *process_name, bool wait_for_launch)
+{
+    Error error;
+    error.SetErrorString ("attaching to a by process name not supported in kdp-remote plug-in");
+    return error;
+}
+
+Error
+ProcessKDP::DoConnectRemote (const char *remote_url)
+{
+    // TODO: fill in the remote connection to the remote KDP here!
+    Error error;
+    error.SetErrorString ("attaching to a by process name not supported in kdp-remote plug-in");
+    return error;
+}
+
+//----------------------------------------------------------------------
+// Process Control
+//----------------------------------------------------------------------
+Error
+ProcessKDP::DoLaunch (Module* module,
+                      char const *argv[],
+                      char const *envp[],
+                      uint32_t launch_flags,
+                      const char *stdin_path,
+                      const char *stdout_path,
+                      const char *stderr_path,
+                      const char *working_dir)
+{
+    Error error;
+    error.SetErrorString ("launching not supported in kdp-remote plug-in");
+    return error;
+}
+
+
+Error
+ProcessKDP::DoAttachToProcessWithID (lldb::pid_t attach_pid)
+{
+    Error error;
+    error.SetErrorString ("attach to process by ID is not suppported in kdp remote debugging");
+    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)
+{
+    Error error;
+    error.SetErrorString ("attach to process by name is not suppported in kdp remote debugging");
+    return error;
+}
+
+
+void
+ProcessKDP::DidAttach ()
+{
+    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS));
+    if (log)
+        log->Printf ("ProcessKDP::DidLaunch()");
+    if (GetID() != LLDB_INVALID_PROCESS_ID)
+    {
+        // TODO: figure out the register context that we will use
+    }
+}
+
+Error
+ProcessKDP::WillResume ()
+{
+    return Error();
+}
+
+Error
+ProcessKDP::DoResume ()
+{
+    Error error;
+    error.SetErrorString ("ProcessKDP::DoResume () is not implemented yet");
+    return error;
+}
+
+uint32_t
+ProcessKDP::UpdateThreadListIfNeeded ()
+{
+    // locker will keep a mutex locked until it goes out of scope
+    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_THREAD));
+    if (log && log->GetMask().Test(KDP_LOG_VERBOSE))
+        log->Printf ("ProcessKDP::%s (pid = %i)", __FUNCTION__, GetID());
+    
+    Mutex::Locker locker (m_thread_list.GetMutex ());
+    // TODO: get the thread list here!
+    const uint32_t stop_id = GetStopID();
+    if (m_thread_list.GetSize(false) == 0 || stop_id != m_thread_list.GetStopID())
+    {
+        // Update the thread list's stop id immediately so we don't recurse into this function.
+//        ThreadList curr_thread_list (this);
+//        curr_thread_list.SetStopID(stop_id);
+//        
+//        std::vector<lldb::tid_t> thread_ids;
+//        bool sequence_mutex_unavailable = false;
+//        const size_t num_thread_ids = m_comm.GetCurrentThreadIDs (thread_ids, sequence_mutex_unavailable);
+//        if (num_thread_ids > 0)
+//        {
+//            for (size_t i=0; i<num_thread_ids; ++i)
+//            {
+//                tid_t tid = thread_ids[i];
+//                ThreadSP thread_sp (GetThreadList().FindThreadByID (tid, false));
+//                if (!thread_sp)
+//                    thread_sp.reset (new ThreadGDBRemote (*this, tid));
+//                curr_thread_list.AddThread(thread_sp);
+//            }
+//        }
+//        
+//        if (sequence_mutex_unavailable == false)
+//        {
+//            m_thread_list = curr_thread_list;
+//            SetThreadStopInfo (m_last_stop_packet);
+//        }
+    }
+    return GetThreadList().GetSize(false);
+}
+
+
+StateType
+ProcessKDP::SetThreadStopInfo (StringExtractor& stop_packet)
+{
+    // TODO: figure out why we stopped given the packet that tells us we stopped...
+    return eStateStopped;
+}
+
+void
+ProcessKDP::RefreshStateAfterStop ()
+{
+    // Let all threads recover from stopping and do any clean up based
+    // on the previous thread state (if any).
+    m_thread_list.RefreshStateAfterStop();
+    //SetThreadStopInfo (m_last_stop_packet);
+}
+
+Error
+ProcessKDP::DoHalt (bool &caused_stop)
+{
+    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
+    {
+        // 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");
+//        }
+    }
+    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 (catch_stop_event)
+        {
+            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 (paused_private_state_thread)
+        {
+            if (log)
+                log->Printf ("ProcessKDP::InterruptIfRunning() resuming private state thread");
+            ResumePrivateStateThread();
+        }
+    }
+    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;
+    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
+    if (log)
+        log->Printf ("ProcessKDP::DoDetach()");
+    
+    DisableAllBreakpointSites ();
+    
+    m_thread_list.DiscardThreadPlans();
+    
+    size_t response_size = m_comm.SendPacket ("D", 1);
+    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 ();
+    
+    m_comm.StopReadThread();
+    m_comm.Disconnect();    // Disconnect from the debug server.
+    
+    SetPrivateState (eStateDetached);
+    ResumePrivateStateThread();
+    
+    //KillDebugserverProcess ();
+    return error;
+}
+
+Error
+ProcessKDP::DoDestroy ()
+{
+    Error error;
+    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
+    if (log)
+        log->Printf ("ProcessKDP::DoDestroy()");
+    
+    // Interrupt if our inferior is running...
+    if (m_comm.IsConnected())
+    {
+        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
+        {
+            
+            StringExtractor response;
+            // TODO: Send kill packet?
+            SetExitStatus(SIGABRT, NULL);
+        }
+    }
+    StopAsyncThread ();
+    m_comm.StopReadThread();
+    m_comm.Disconnect();    // Disconnect from the debug server.
+    return error;
+}
+
+//------------------------------------------------------------------
+// Process Queries
+//------------------------------------------------------------------
+
+bool
+ProcessKDP::IsAlive ()
+{
+    return m_comm.IsConnected() && m_private_state.GetValue() != eStateExited;
+}
+
+//------------------------------------------------------------------
+// Process Memory
+//------------------------------------------------------------------
+size_t
+ProcessKDP::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error)
+{
+    error.SetErrorString ("ProcessKDP::DoReadMemory not implemented");
+    return 0;
+}
+
+size_t
+ProcessKDP::DoWriteMemory (addr_t addr, const void *buf, size_t size, Error &error)
+{
+    error.SetErrorString ("ProcessKDP::DoReadMemory not implemented");
+    return 0;
+}
+
+lldb::addr_t
+ProcessKDP::DoAllocateMemory (size_t size, uint32_t permissions, Error &error)
+{
+    error.SetErrorString ("memory allocation not suppported in kdp remote debugging");
+    return LLDB_INVALID_ADDRESS;
+}
+
+Error
+ProcessKDP::DoDeallocateMemory (lldb::addr_t addr)
+{
+    Error error;
+    error.SetErrorString ("memory deallocation not suppported in kdp remote debugging");
+    return error;
+}
+
+Error
+ProcessKDP::EnableBreakpoint (BreakpointSite *bp_site)
+{
+    return EnableSoftwareBreakpoint (bp_site);
+}
+
+Error
+ProcessKDP::DisableBreakpoint (BreakpointSite *bp_site)
+{
+    return DisableSoftwareBreakpoint (bp_site);
+}
+
+Error
+ProcessKDP::EnableWatchpoint (WatchpointLocation *wp)
+{
+    Error error;
+    error.SetErrorString ("watchpoints are not suppported in kdp remote debugging");
+    return error;
+}
+
+Error
+ProcessKDP::DisableWatchpoint (WatchpointLocation *wp)
+{
+    Error error;
+    error.SetErrorString ("watchpoints are not suppported in kdp remote debugging");
+    return error;
+}
+
+void
+ProcessKDP::Clear()
+{
+    Mutex::Locker locker (m_thread_list.GetMutex ());
+    m_thread_list.Clear();
+}
+
+Error
+ProcessKDP::DoSignal (int signo)
+{
+    Error error;
+    error.SetErrorString ("sending signals is not suppported in kdp remote debugging");
+    return error;
+}
+
+void
+ProcessKDP::Initialize()
+{
+    static bool g_initialized = false;
+    
+    if (g_initialized == false)
+    {
+        g_initialized = true;
+        PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                       GetPluginDescriptionStatic(),
+                                       CreateInstance);
+        
+        Log::Callbacks log_callbacks = {
+            ProcessKDPLog::DisableLog,
+            ProcessKDPLog::EnableLog,
+            ProcessKDPLog::ListLogCategories
+        };
+        
+        Log::RegisterLogChannel (ProcessKDP::GetPluginNameStatic(), log_callbacks);
+    }
+}
+
+bool
+ProcessKDP::StartAsyncThread ()
+{
+    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
+    
+    if (log)
+        log->Printf ("ProcessKDP::%s ()", __FUNCTION__);
+    
+    // Create a thread that watches our internal state and controls which
+    // events make it to clients (into the DCProcess event queue).
+    m_async_thread = Host::ThreadCreate ("<lldb.process.kdp-remote.async>", ProcessKDP::AsyncThread, this, NULL);
+    return IS_VALID_LLDB_HOST_THREAD(m_async_thread);
+}
+
+void
+ProcessKDP::StopAsyncThread ()
+{
+    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
+    
+    if (log)
+        log->Printf ("ProcessKDP::%s ()", __FUNCTION__);
+    
+    m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit);
+    
+    // Stop the stdio thread
+    if (IS_VALID_LLDB_HOST_THREAD(m_async_thread))
+    {
+        Host::ThreadJoin (m_async_thread, NULL, NULL);
+    }
+}
+
+
+void *
+ProcessKDP::AsyncThread (void *arg)
+{
+    ProcessKDP *process = (ProcessKDP*) arg;
+    
+    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS));
+    if (log)
+        log->Printf ("ProcessKDP::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID());
+    
+    Listener listener ("ProcessKDP::AsyncThread");
+    EventSP event_sp;
+    const uint32_t desired_event_mask = eBroadcastBitAsyncContinue |
+                                        eBroadcastBitAsyncThreadShouldExit;
+    
+    if (listener.StartListeningForEvents (&process->m_async_broadcaster, desired_event_mask) == desired_event_mask)
+    {
+        listener.StartListeningForEvents (&process->m_comm, Communication::eBroadcastBitReadThreadDidExit);
+        
+        bool done = false;
+        while (!done)
+        {
+            if (log)
+                log->Printf ("ProcessKDP::%s (arg = %p, pid = %i) listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID());
+            if (listener.WaitForEvent (NULL, event_sp))
+            {
+                const uint32_t event_type = event_sp->GetType();
+                if (event_sp->BroadcasterIs (&process->m_async_broadcaster))
+                {
+                    if (log)
+                        log->Printf ("ProcessKDP::%s (arg = %p, pid = %i) Got an event of type: %d...", __FUNCTION__, arg, process->GetID(), event_type);
+                    
+                    switch (event_type)
+                    {
+                        case eBroadcastBitAsyncContinue:
+                        {
+                            const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event_sp.get());
+                            
+                            if (continue_packet)
+                            {
+                                // TODO: do continue support here
+                                
+//                                const char *continue_cstr = (const char *)continue_packet->GetBytes ();
+//                                const size_t continue_cstr_len = continue_packet->GetByteSize ();
+//                                if (log)
+//                                    log->Printf ("ProcessKDP::%s (arg = %p, pid = %i) got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr);
+//                                
+//                                if (::strstr (continue_cstr, "vAttach") == NULL)
+//                                    process->SetPrivateState(eStateRunning);
+//                                StringExtractor response;
+//                                StateType stop_state = process->GetCommunication().SendContinuePacketAndWaitForResponse (process, continue_cstr, continue_cstr_len, response);
+//                                
+//                                switch (stop_state)
+//                                {
+//                                    case eStateStopped:
+//                                    case eStateCrashed:
+//                                    case eStateSuspended:
+//                                        process->m_last_stop_packet = response;
+//                                        process->SetPrivateState (stop_state);
+//                                        break;
+//                                        
+//                                    case eStateExited:
+//                                        process->m_last_stop_packet = response;
+//                                        response.SetFilePos(1);
+//                                        process->SetExitStatus(response.GetHexU8(), NULL);
+//                                        done = true;
+//                                        break;
+//                                        
+//                                    case eStateInvalid:
+//                                        process->SetExitStatus(-1, "lost connection");
+//                                        break;
+//                                        
+//                                    default:
+//                                        process->SetPrivateState (stop_state);
+//                                        break;
+//                                }
+                            }
+                        }
+                            break;
+                            
+                        case eBroadcastBitAsyncThreadShouldExit:
+                            if (log)
+                                log->Printf ("ProcessKDP::%s (arg = %p, pid = %i) got eBroadcastBitAsyncThreadShouldExit...", __FUNCTION__, arg, process->GetID());
+                            done = true;
+                            break;
+                            
+                        default:
+                            if (log)
+                                log->Printf ("ProcessKDP::%s (arg = %p, pid = %i) got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type);
+                            done = true;
+                            break;
+                    }
+                }
+                else if (event_sp->BroadcasterIs (&process->m_comm))
+                {
+                    if (event_type & Communication::eBroadcastBitReadThreadDidExit)
+                    {
+                        process->SetExitStatus (-1, "lost connection");
+                        done = true;
+                    }
+                }
+            }
+            else
+            {
+                if (log)
+                    log->Printf ("ProcessKDP::%s (arg = %p, pid = %i) listener.WaitForEvent (NULL, event_sp) => false", __FUNCTION__, arg, process->GetID());
+                done = true;
+            }
+        }
+    }
+    
+    if (log)
+        log->Printf ("ProcessKDP::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, arg, process->GetID());
+    
+    process->m_async_thread = LLDB_INVALID_HOST_THREAD;
+    return NULL;
+}
+
+

Added: 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=135240&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h (added)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h Thu Jul 14 22:27:12 2011
@@ -0,0 +1,283 @@
+//===-- ProcessKDP.h --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ProcessKDP_h_
+#define liblldb_ProcessKDP_h_
+
+// C Includes
+
+// C++ Includes
+#include <list>
+#include <vector>
+
+// Other libraries and framework includes
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Broadcaster.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/InputReader.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/StringList.h"
+#include "lldb/Core/ThreadSafeValue.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+
+#include "CommunicationKDP.h"
+#include "Utility/StringExtractor.h"
+
+class ThreadKDP;
+
+class ProcessKDP : public lldb_private::Process
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    static Process*
+    CreateInstance (lldb_private::Target& target, lldb_private::Listener &listener);
+    
+    static void
+    Initialize();
+    
+    static void
+    Terminate();
+    
+    static const char *
+    GetPluginNameStatic();
+    
+    static const char *
+    GetPluginDescriptionStatic();
+    
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    ProcessKDP(lldb_private::Target& target, lldb_private::Listener &listener);
+    
+    virtual
+    ~ProcessKDP();
+    
+    //------------------------------------------------------------------
+    // Check if a given Process
+    //------------------------------------------------------------------
+    virtual bool
+    CanDebug (lldb_private::Target &target);
+    
+    //    virtual uint32_t
+    //    ListProcessesMatchingName (const char *name, lldb_private::StringList &matches, std::vector<lldb::pid_t> &pids);
+    
+    //------------------------------------------------------------------
+    // Creating a new process, or attaching to an existing one
+    //------------------------------------------------------------------
+    virtual lldb_private::Error
+    WillLaunch (lldb_private::Module* module);
+    
+    virtual lldb_private::Error
+    DoLaunch (lldb_private::Module* module,
+              char const *argv[],           // Can be NULL
+              char const *envp[],           // Can be NULL
+              uint32_t flags,
+              const char *stdin_path,       // Can be NULL
+              const char *stdout_path,      // Can be NULL
+              const char *stderr_path,      // Can be NULL
+              const char *working_dir);     // Can be NULL
+    
+    virtual lldb_private::Error
+    WillAttachToProcessWithID (lldb::pid_t pid);
+    
+    virtual lldb_private::Error
+    WillAttachToProcessWithName (const char *process_name, bool wait_for_launch);
+    
+    virtual lldb_private::Error
+    DoConnectRemote (const char *remote_url);
+    
+    virtual lldb_private::Error
+    DoAttachToProcessWithID (lldb::pid_t pid);
+    
+    virtual lldb_private::Error
+    DoAttachToProcessWithName (const char *process_name, bool wait_for_launch);
+    
+    virtual void
+    DidAttach ();
+    
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual const char *
+    GetPluginName();
+    
+    virtual const char *
+    GetShortPluginName();
+    
+    virtual uint32_t
+    GetPluginVersion();
+    
+    //------------------------------------------------------------------
+    // Process Control
+    //------------------------------------------------------------------
+    virtual lldb_private::Error
+    WillResume ();
+    
+    virtual lldb_private::Error
+    DoResume ();
+    
+    virtual lldb_private::Error
+    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
+    DoDestroy ();
+    
+    virtual void
+    RefreshStateAfterStop();
+    
+    //------------------------------------------------------------------
+    // Process Queries
+    //------------------------------------------------------------------
+    virtual bool
+    IsAlive ();
+    
+    //------------------------------------------------------------------
+    // Process Memory
+    //------------------------------------------------------------------
+    virtual size_t
+    DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error);
+    
+    virtual size_t
+    DoWriteMemory (lldb::addr_t addr, const void *buf, size_t size, lldb_private::Error &error);
+    
+    virtual lldb::addr_t
+    DoAllocateMemory (size_t size, uint32_t permissions, lldb_private::Error &error);
+    
+    virtual lldb_private::Error
+    DoDeallocateMemory (lldb::addr_t ptr);
+
+    //----------------------------------------------------------------------
+    // Process Breakpoints
+    //----------------------------------------------------------------------
+    virtual lldb_private::Error
+    EnableBreakpoint (lldb_private::BreakpointSite *bp_site);
+    
+    virtual lldb_private::Error
+    DisableBreakpoint (lldb_private::BreakpointSite *bp_site);
+    
+    //----------------------------------------------------------------------
+    // Process Watchpoints
+    //----------------------------------------------------------------------
+    virtual lldb_private::Error
+    EnableWatchpoint (lldb_private::WatchpointLocation *wp_loc);
+    
+    virtual lldb_private::Error
+    DisableWatchpoint (lldb_private::WatchpointLocation *wp_loc);
+    
+protected:
+    friend class ThreadKDP;
+    friend class CommunicationKDP;
+    
+    //----------------------------------------------------------------------
+    // Accessors
+    //----------------------------------------------------------------------
+    bool
+    IsRunning ( lldb::StateType state )
+    {
+        return    state == lldb::eStateRunning || IsStepping(state);
+    }
+    
+    bool
+    IsStepping ( lldb::StateType state)
+    {
+        return    state == lldb::eStateStepping;
+    }
+
+    bool
+    CanResume ( lldb::StateType state)
+    {
+        return state == lldb::eStateStopped;
+    }
+    
+    bool
+    HasExited (lldb::StateType state)
+    {
+        return state == lldb::eStateExited;
+    }
+    
+    bool
+    ProcessIDIsValid ( ) const;
+    
+    //    static void
+    //    STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len);
+    
+    //    void
+    //    AppendSTDOUT (const char* s, size_t len);
+    
+    void
+    Clear ( );
+    
+    uint32_t
+    UpdateThreadListIfNeeded ();
+    
+    CommunicationKDP &
+    GetCommunication()
+    {
+        return m_comm;
+    }
+    
+    enum
+    {
+        eBroadcastBitAsyncContinue                  = (1 << 0),
+        eBroadcastBitAsyncThreadShouldExit          = (1 << 1)
+    };
+
+    lldb_private::Error
+    InterruptIfRunning (bool discard_thread_plans,
+                        bool catch_stop_event,
+                        lldb::EventSP &stop_event_sp);
+
+    //------------------------------------------------------------------
+    /// Broadcaster event bits definitions.
+    //------------------------------------------------------------------
+    CommunicationKDP m_comm;
+    lldb_private::Broadcaster m_async_broadcaster;
+    lldb::thread_t m_async_thread;
+
+    bool
+    StartAsyncThread ();
+    
+    void
+    StopAsyncThread ();
+    
+    static void *
+    AsyncThread (void *arg);
+    
+    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
+    //------------------------------------------------------------------
+    
+    DISALLOW_COPY_AND_ASSIGN (ProcessKDP);
+    
+};
+
+#endif  // liblldb_ProcessKDP_h_

Added: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp?rev=135240&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp (added)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp Thu Jul 14 22:27:12 2011
@@ -0,0 +1,183 @@
+//===-- ProcessKDPLog.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ProcessKDPLog.h"
+
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Core/StreamFile.h"
+
+#include "ProcessKDP.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+// We want to avoid global constructors where code needs to be run so here we
+// control access to our static g_log_sp by hiding it in a singleton function
+// that will construct the static g_lob_sp the first time this function is 
+// called.
+static LogSP &
+GetLog ()
+{
+    static LogSP g_log_sp;
+    return g_log_sp;
+}
+
+LogSP
+ProcessKDPLog::GetLogIfAllCategoriesSet (uint32_t mask)
+{
+    LogSP log(GetLog ());
+    if (log && mask)
+    {
+        uint32_t log_mask = log->GetMask().Get();
+        if ((log_mask & mask) != mask)
+            return LogSP();
+    }
+    return log;
+}
+
+void
+ProcessKDPLog::DisableLog (Args &args, Stream *feedback_strm)
+{
+    LogSP log (GetLog ());
+    if (log)
+    {
+        uint32_t flag_bits = 0;
+        
+        const size_t argc = args.GetArgumentCount ();
+        if (argc > 0)
+        {
+            flag_bits = log->GetMask().Get();
+            for (size_t i = 0; i < argc; ++i)
+            {
+                const char *arg = args.GetArgumentAtIndex (i);
+                
+
+                if      (::strcasecmp (arg, "all")        == 0 ) flag_bits &= ~KDP_LOG_ALL;
+                else if (::strcasecmp (arg, "async")      == 0 ) flag_bits &= ~KDP_LOG_ASYNC;
+                else if (::strncasecmp (arg, "break", 5)  == 0 ) flag_bits &= ~KDP_LOG_BREAKPOINTS;
+                else if (::strncasecmp (arg, "comm", 4)   == 0 ) flag_bits &= ~KDP_LOG_COMM;
+                else if (::strcasecmp (arg, "default")    == 0 ) flag_bits &= ~KDP_LOG_DEFAULT;
+                else if (::strcasecmp (arg, "packets")    == 0 ) flag_bits &= ~KDP_LOG_PACKETS;
+                else if (::strcasecmp (arg, "memory")     == 0 ) flag_bits &= ~KDP_LOG_MEMORY;
+                else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits &= ~KDP_LOG_MEMORY_DATA_SHORT;
+                else if (::strcasecmp (arg, "data-long")  == 0 ) flag_bits &= ~KDP_LOG_MEMORY_DATA_LONG;
+                else if (::strcasecmp (arg, "process")    == 0 ) flag_bits &= ~KDP_LOG_PROCESS;
+                else if (::strcasecmp (arg, "step")       == 0 ) flag_bits &= ~KDP_LOG_STEP;
+                else if (::strcasecmp (arg, "thread")     == 0 ) flag_bits &= ~KDP_LOG_THREAD;
+                else if (::strcasecmp (arg, "verbose")    == 0 ) flag_bits &= ~KDP_LOG_VERBOSE;
+                else if (::strncasecmp (arg, "watch", 5)  == 0 ) flag_bits &= ~KDP_LOG_WATCHPOINTS;
+                else
+                {
+                    feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
+                    ListLogCategories (feedback_strm);
+                }
+                
+            }
+        }
+        
+        if (flag_bits == 0)
+            GetLog ().reset();
+        else
+            log->GetMask().Reset (flag_bits);
+    }
+    
+    return;
+}
+
+LogSP
+ProcessKDPLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, Args &args, Stream *feedback_strm)
+{
+    // Try see if there already is a log - that way we can reuse its settings.
+    // We could reuse the log in toto, but we don't know that the stream is the same.
+    uint32_t flag_bits = 0;
+    LogSP log(GetLog ());
+    if (log)
+        flag_bits = log->GetMask().Get();
+
+    // Now make a new log with this stream if one was provided
+    if (log_stream_sp)
+    {
+        log = make_shared<Log>(log_stream_sp);
+        GetLog () = log;
+    }
+
+    if (log)
+    {
+        bool got_unknown_category = false;
+        const size_t argc = args.GetArgumentCount();
+        for (size_t i=0; i<argc; ++i)
+        {
+            const char *arg = args.GetArgumentAtIndex(i);
+
+            if      (::strcasecmp (arg, "all")        == 0 ) flag_bits |= KDP_LOG_ALL;
+            else if (::strcasecmp (arg, "async")      == 0 ) flag_bits |= KDP_LOG_ASYNC;
+            else if (::strncasecmp (arg, "break", 5)  == 0 ) flag_bits |= KDP_LOG_BREAKPOINTS;
+            else if (::strncasecmp (arg, "comm", 4)   == 0 ) flag_bits |= KDP_LOG_COMM;
+            else if (::strcasecmp (arg, "default")    == 0 ) flag_bits |= KDP_LOG_DEFAULT;
+            else if (::strcasecmp (arg, "packets")    == 0 ) flag_bits |= KDP_LOG_PACKETS;
+            else if (::strcasecmp (arg, "memory")     == 0 ) flag_bits |= KDP_LOG_MEMORY;
+            else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits |= KDP_LOG_MEMORY_DATA_SHORT;
+            else if (::strcasecmp (arg, "data-long")  == 0 ) flag_bits |= KDP_LOG_MEMORY_DATA_LONG;
+            else if (::strcasecmp (arg, "process")    == 0 ) flag_bits |= KDP_LOG_PROCESS;
+            else if (::strcasecmp (arg, "step")       == 0 ) flag_bits |= KDP_LOG_STEP;
+            else if (::strcasecmp (arg, "thread")     == 0 ) flag_bits |= KDP_LOG_THREAD;
+            else if (::strcasecmp (arg, "verbose")    == 0 ) flag_bits |= KDP_LOG_VERBOSE;
+            else if (::strncasecmp (arg, "watch", 5)  == 0 ) flag_bits |= KDP_LOG_WATCHPOINTS;
+            else
+            {
+                feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
+                if (got_unknown_category == false)
+                {
+                    got_unknown_category = true;
+                    ListLogCategories (feedback_strm);
+                }
+            }
+        }
+        if (flag_bits == 0)
+            flag_bits = KDP_LOG_DEFAULT;
+        log->GetMask().Reset(flag_bits);
+        log->GetOptions().Reset(log_options);
+    }
+    return log;
+}
+
+void
+ProcessKDPLog::ListLogCategories (Stream *strm)
+{
+    strm->Printf("Logging categories for '%s':\n"
+        "\tall - turn on all available logging categories\n"
+        "\tasync - log asynchronous activity\n"
+        "\tbreak - log breakpoints\n"
+        "\tcommunication - log communication activity\n"
+        "\tdefault - enable the default set of logging categories for liblldb\n"
+        "\tpackets - log gdb remote packets\n"
+        "\tmemory - log memory reads and writes\n"
+        "\tdata-short - log memory bytes for memory reads and writes for short transactions only\n"
+        "\tdata-long - log memory bytes for memory reads and writes for all transactions\n"
+        "\tprocess - log process events and activities\n"
+        "\tthread - log thread events and activities\n"
+        "\tstep - log step related activities\n"
+        "\tverbose - enable verbose logging\n"
+        "\twatch - log watchpoint related activities\n", ProcessKDP::GetPluginNameStatic());
+}
+
+
+void
+ProcessKDPLog::LogIf (uint32_t mask, const char *format, ...)
+{
+    LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (mask));
+    if (log)
+    {
+        va_list args;
+        va_start (args, format);
+        log->VAPrintf (format, args);
+        va_end (args);
+    }
+}

Added: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h?rev=135240&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h (added)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h Thu Jul 14 22:27:12 2011
@@ -0,0 +1,54 @@
+//===-- ProcessKDPLog.h -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ProcessKDPLog_h_
+#define liblldb_ProcessKDPLog_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+
+// Project includes
+#include "lldb/Core/Log.h"
+
+#define KDP_LOG_VERBOSE                  (1u << 0)
+#define KDP_LOG_PROCESS                  (1u << 1)
+#define KDP_LOG_THREAD                   (1u << 2)
+#define KDP_LOG_PACKETS                  (1u << 3)
+#define KDP_LOG_MEMORY                   (1u << 4)    // Log memory reads/writes calls
+#define KDP_LOG_MEMORY_DATA_SHORT        (1u << 5)    // Log short memory reads/writes bytes
+#define KDP_LOG_MEMORY_DATA_LONG         (1u << 6)    // Log all memory reads/writes bytes
+#define KDP_LOG_BREAKPOINTS              (1u << 7)
+#define KDP_LOG_WATCHPOINTS              (1u << 8)
+#define KDP_LOG_STEP                     (1u << 9)
+#define KDP_LOG_COMM                     (1u << 10)
+#define KDP_LOG_ASYNC                    (1u << 11)
+#define KDP_LOG_ALL                      (UINT32_MAX)
+#define KDP_LOG_DEFAULT                  KDP_LOG_PACKETS
+
+class ProcessKDPLog
+{
+public:
+    static lldb::LogSP
+    GetLogIfAllCategoriesSet(uint32_t mask = 0);
+
+    static void
+    DisableLog (lldb_private::Args &args, lldb_private::Stream *feedback_strm);
+
+    static lldb::LogSP
+    EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options, lldb_private::Args &args, lldb_private::Stream *feedback_strm);
+
+    static void
+    ListLogCategories (lldb_private::Stream *strm);
+
+    static void
+    LogIf (uint32_t mask, const char *format, ...);
+};
+
+#endif  // liblldb_ProcessKDPLog_h_





More information about the lldb-commits mailing list