[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