summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/MacOSX-Kernel
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Process/MacOSX-Kernel')
-rw-r--r--lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp379
-rw-r--r--lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h54
-rw-r--r--lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp54
-rw-r--r--lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h12
-rw-r--r--lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp90
-rw-r--r--lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.h61
-rw-r--r--lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp71
-rw-r--r--lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.h49
-rw-r--r--lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp66
-rw-r--r--lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.h50
-rw-r--r--lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp247
-rw-r--r--lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h115
12 files changed, 1186 insertions, 62 deletions
diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
index 2d9522bbe3a..f84eec36840 100644
--- a/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
@@ -15,10 +15,13 @@
#include <string.h>
// C++ Includes
+#include "llvm/Support/MachO.h"
+
// Other libraries and framework includes
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Log.h"
+#include "lldb/Core/State.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/TimeValue.h"
@@ -37,6 +40,7 @@ using namespace lldb_private;
//----------------------------------------------------------------------
CommunicationKDP::CommunicationKDP (const char *comm_name) :
Communication(comm_name),
+ m_addr_byte_size (4),
m_byte_order (eByteOrderLittle),
m_packet_timeout (1),
m_sequence_mutex (Mutex::eMutexTypeRecursive),
@@ -129,13 +133,9 @@ CommunicationKDP::SendRequestPacketNoLock (const PacketStreamType &request_packe
LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
if (log)
{
- PacketStreamType log_strm;
-
- DataExtractor::DumpHexBytes (&log_strm, packet_data, packet_size, UINT32_MAX, LLDB_INVALID_ADDRESS);
-
- log->Printf("send kdp-packet: %.*s",
- (uint32_t)log_strm.GetSize(),
- log_strm.GetData());
+ PacketStreamType log_strm;
+ DumpPacket (log_strm, packet_data, packet_size);
+ log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData());
}
ConnectionStatus status = eConnectionStatusSuccess;
@@ -298,18 +298,9 @@ CommunicationKDP::CheckForPacket (const uint8_t *src, size_t src_len, DataExtrac
if (log)
{
PacketStreamType log_strm;
- packet.Dump (&log_strm, // Stream to dump to
- 0, // Offset into "packet"
- eFormatBytes, // Dump as hex bytes
- 1, // Size of each item is 1 for single bytes
- length, // Number of bytes
- UINT32_MAX, // Num bytes per line
- LLDB_INVALID_ADDRESS, // Base address
- 0, 0); // Bitfield info set to not do anything bitfield related
+ DumpPacket (log_strm, packet);
- log->Printf("recv kdp-packet: %.*s",
- (uint32_t)log_strm.GetSize(),
- log_strm.GetData());
+ log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData());
}
return true;
}
@@ -336,7 +327,7 @@ CommunicationKDP::SendRequestConnect (uint16_t reply_port,
uint16_t exc_port,
const char *greeting)
{
- PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order);
+ PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
if (greeting == NULL)
greeting = "";
@@ -369,7 +360,7 @@ CommunicationKDP::ClearKDPSettings ()
bool
CommunicationKDP::SendRequestReattach (uint16_t reply_port)
{
- PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order);
+ PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
const CommandType command = eCommandTypeReattach;
// Length is 8 bytes for the header plus 2 bytes for the reply UDP port
const uint32_t command_length = 8 + 2;
@@ -410,7 +401,7 @@ CommunicationKDP::GetFeatureFlags ()
bool
CommunicationKDP::SendRequestVersion ()
{
- PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order);
+ PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
const CommandType command = eCommandTypeVersion;
const uint32_t command_length = 8;
const uint32_t request_sequence_id = m_request_sequence_id;
@@ -454,7 +445,7 @@ CommunicationKDP::GetCPUSubtype ()
bool
CommunicationKDP::SendRequestHostInfo ()
{
- PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order);
+ PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
const CommandType command = eCommandTypeHostInfo;
const uint32_t command_length = 8;
const uint32_t request_sequence_id = m_request_sequence_id;
@@ -464,9 +455,17 @@ CommunicationKDP::SendRequestHostInfo ()
{
// Reset the sequence ID to zero for reattach
uint32_t offset = 8;
- m_kdp_hostinfo_cpu_mask = reply_packet.GetU32 (&offset);
- m_kdp_hostinfo_cpu_type = reply_packet.GetU32 (&offset);
- m_kdp_hostinfo_cpu_subtype = reply_packet.GetU32 (&offset);
+ m_kdp_hostinfo_cpu_mask = reply_packet.GetU32 (&offset);
+ m_kdp_hostinfo_cpu_type = reply_packet.GetU32 (&offset);
+ m_kdp_hostinfo_cpu_subtype = reply_packet.GetU32 (&offset);
+
+ ArchSpec kernel_arch;
+ kernel_arch.SetArchitecture (eArchTypeMachO,
+ m_kdp_hostinfo_cpu_type,
+ m_kdp_hostinfo_cpu_subtype);
+
+ m_addr_byte_size = kernel_arch.GetAddressByteSize();
+ m_byte_order = kernel_arch.GetByteOrder();
return true;
}
return false;
@@ -475,7 +474,7 @@ CommunicationKDP::SendRequestHostInfo ()
bool
CommunicationKDP::SendRequestDisconnect ()
{
- PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order);
+ PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
const CommandType command = eCommandTypeDisconnect;
const uint32_t command_length = 8;
const uint32_t request_sequence_id = m_request_sequence_id;
@@ -489,3 +488,331 @@ CommunicationKDP::SendRequestDisconnect ()
return true;
}
+uint32_t
+CommunicationKDP::SendRequestReadMemory (lldb::addr_t addr,
+ void *dst,
+ uint32_t dst_len,
+ Error &error)
+{
+ PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
+ bool use_64 = (GetVersion() >= 11);
+ uint32_t command_addr_byte_size = use_64 ? 8 : 4;
+ const CommandType command = use_64 ? eCommandTypeReadMemory64 : eCommandTypeReadMemory;
+ // Size is header + address size + uint32_t length
+ const uint32_t command_length = 8 + command_addr_byte_size + 4;
+ const uint32_t request_sequence_id = m_request_sequence_id;
+ MakeRequestPacketHeader (command, request_packet, command_length);
+ request_packet.PutMaxHex64 (addr, command_addr_byte_size);
+ request_packet.PutHex32 (dst_len);
+ DataExtractor reply_packet;
+ if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+ {
+ // Reset the sequence ID to zero for reattach
+ uint32_t offset = 8;
+ uint32_t kdp_error = reply_packet.GetU32 (&offset);
+ uint32_t src_len = reply_packet.GetByteSize() - 12;
+
+ if (src_len > 0)
+ {
+ const void *src = reply_packet.GetData(&offset, src_len);
+ if (src)
+ {
+ ::memcpy (dst, src, src_len);
+ error.Clear();
+ return src_len;
+ }
+ }
+ if (kdp_error)
+ error.SetErrorStringWithFormat ("kdp read memory failed (error %u)", kdp_error);
+ else
+ error.SetErrorString ("kdp read memory failed");
+ }
+ return 0;
+}
+
+const char *
+CommunicationKDP::GetCommandAsCString (uint8_t command)
+{
+ switch (command)
+ {
+ case eCommandTypeConnect: return "KDP_CONNECT";
+ case eCommandTypeDisconnect: return "KDP_DISCONNECT";
+ case eCommandTypeHostInfo: return "KDP_HOSTINFO";
+ case eCommandTypeVersion: return "KDP_VERSION";
+ case eCommandTypeMaxBytes: return "KDP_MAXBYTES";
+ case eCommandTypeReadMemory: return "KDP_READMEM";
+ case eCommandTypeWriteMemory: return "KDP_WRITEMEM";
+ case eCommandTypeReadRegisters: return "KDP_READREGS";
+ case eCommandTypeWriteRegisters: return "KDP_WRITEREGS";
+ case eCommandTypeLoad: return "KDP_LOAD";
+ case eCommandTypeImagePath: return "KDP_IMAGEPATH";
+ case eCommandTypeSuspend: return "KDP_SUSPEND";
+ case eCommandTypeResume: return "KDP_RESUMECPUS";
+ case eCommandTypeException: return "KDP_EXCEPTION";
+ case eCommandTypeTermination: return "KDP_TERMINATION";
+ case eCommandTypeBreakpointSet: return "KDP_BREAKPOINT_SET";
+ case eCommandTypeBreakpointRemove: return "KDP_BREAKPOINT_REMOVE";
+ case eCommandTypeRegions: return "KDP_REGIONS";
+ case eCommandTypeReattach: return "KDP_REATTACH";
+ case eCommandTypeHostReboot: return "KDP_HOSTREBOOT";
+ case eCommandTypeReadMemory64: return "KDP_READMEM64";
+ case eCommandTypeWriteMemory64: return "KDP_WRITEMEM64";
+ case eCommandTypeBreakpointSet64: return "KDP_BREAKPOINT64_SET";
+ case eCommandTypeBreakpointRemove64: return "KDP_BREAKPOINT64_REMOVE";
+ case eCommandTypeKernelVersion: return "KDP_KERNELVERSION";
+ }
+ return NULL;
+}
+
+void
+CommunicationKDP::DumpPacket (Stream &s, const void *data, uint32_t data_len)
+{
+ DataExtractor extractor (data, data_len, m_byte_order, m_addr_byte_size);
+ DumpPacket (s, extractor);
+}
+
+void
+CommunicationKDP::DumpPacket (Stream &s, const DataExtractor& packet)
+{
+ const char *error_desc = NULL;
+ if (packet.GetByteSize() < 8)
+ {
+ error_desc = "error: invalid packet (too short): ";
+ }
+ else
+ {
+ uint32_t offset = 0;
+ const uint8_t first_packet_byte = packet.GetU8 (&offset);
+ const uint8_t sequence_id = packet.GetU8 (&offset);
+ const uint16_t length = packet.GetU16 (&offset);
+ const uint32_t key = packet.GetU32 (&offset);
+ const CommandType command = ExtractCommand (first_packet_byte);
+ const char *command_name = GetCommandAsCString (command);
+ if (command_name)
+ {
+ const bool is_reply = ExtractIsReply(first_packet_byte);
+ s.Printf ("%s {%u:%u} <0x%4.4x> %s",
+ is_reply ? "<--" : "-->",
+ key,
+ sequence_id,
+ length,
+ command_name);
+
+ if (is_reply)
+ {
+ // Dump request reply packets
+ switch (command)
+ {
+ case eCommandTypeConnect:
+ {
+ const uint32_t error = packet.GetU32 (&offset);
+ s.Printf(" (error=0x%8.8x)", error);
+ }
+ break;
+
+ case eCommandTypeDisconnect:
+ case eCommandTypeReattach:
+ case eCommandTypeHostReboot:
+ // No return value for the reply, just the header to ack
+ break;
+
+ case eCommandTypeHostInfo:
+ {
+ const uint32_t cpu_mask = packet.GetU32 (&offset);
+ const uint32_t cpu_type = packet.GetU32 (&offset);
+ const uint32_t cpu_subtype = packet.GetU32 (&offset);
+ s.Printf(" (cpu_mask=0x%8.8x, cpu_type=0x%8.8x, cpu_subtype=0x%8.8x)", cpu_mask, cpu_type, cpu_subtype);
+ }
+ break;
+
+ case eCommandTypeVersion:
+ {
+ const uint32_t version = packet.GetU32 (&offset);
+ const uint32_t feature = packet.GetU32 (&offset);
+ s.Printf(" (version=0x%8.8x, feature=0x%8.8x)", version, feature);
+ }
+ break;
+
+ case eCommandTypeRegions:
+ {
+ const uint32_t region_count = packet.GetU32 (&offset);
+ s.Printf(" (count = %u", region_count);
+ for (uint32_t i=0; i<region_count; ++i)
+ {
+ const addr_t region_addr = packet.GetPointer (&offset);
+ const uint32_t region_size = packet.GetU32 (&offset);
+ const uint32_t region_prot = packet.GetU32 (&offset);
+ s.Printf("\n\tregion[%i] = { range = [0x%16.16llx - 0x%16.16llx), size = 0x%8.8x, prot = %s }", region_addr, region_addr + region_size, region_size, GetPermissionsAsCString (region_prot));
+ }
+ }
+ break;
+
+ case eCommandTypeReadMemory:
+ case eCommandTypeReadMemory64:
+ case eCommandTypeReadRegisters:
+ {
+ const uint32_t error = packet.GetU32 (&offset);
+ const uint32_t count = packet.GetByteSize() - 12;
+ s.Printf(" (error = 0x%8.8x <0x%x>:\n", error, count);
+ if (count > 0)
+ DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, count), count, 32, LLDB_INVALID_ADDRESS);
+ }
+ break;
+
+ case eCommandTypeMaxBytes:
+ case eCommandTypeWriteMemory:
+ case eCommandTypeWriteRegisters:
+ case eCommandTypeLoad:
+ case eCommandTypeImagePath:
+ case eCommandTypeSuspend:
+ case eCommandTypeResume:
+ case eCommandTypeException:
+ case eCommandTypeTermination:
+ case eCommandTypeBreakpointSet:
+ case eCommandTypeBreakpointRemove:
+ case eCommandTypeWriteMemory64:
+ case eCommandTypeBreakpointSet64:
+ case eCommandTypeBreakpointRemove64:
+ case eCommandTypeKernelVersion:
+ break;
+
+ }
+ }
+ else
+ {
+ // Dump request packets
+ switch (command)
+ {
+ case eCommandTypeConnect:
+ {
+ const uint16_t reply_port = packet.GetU16 (&offset);
+ const uint16_t exc_port = packet.GetU16 (&offset);
+ s.Printf(" (reply_port=%u, exc_port=%u, greeting=\"%s\")", reply_port, exc_port, packet.GetCStr(&offset));
+ }
+ break;
+
+ case eCommandTypeDisconnect:
+ case eCommandTypeHostReboot:
+ case eCommandTypeHostInfo:
+ case eCommandTypeVersion:
+ case eCommandTypeRegions:
+ // No args, just the header in the request...
+ break;
+
+ case eCommandTypeReadMemory:
+ {
+ const uint32_t addr = packet.GetU32 (&offset);
+ const uint32_t size = packet.GetU32 (&offset);
+ s.Printf(" (addr = 0x%8.8x, size=%u)", addr, size);
+ }
+ break;
+
+ case eCommandTypeReadMemory64:
+ {
+ const uint64_t addr = packet.GetU64 (&offset);
+ const uint32_t size = packet.GetU32 (&offset);
+ s.Printf(" (addr = 0x%16.16llx, size=%u)", addr, size);
+ }
+ break;
+
+ case eCommandTypeReadRegisters:
+ {
+ const uint32_t cpu = packet.GetU32 (&offset);
+ const uint32_t flavor = packet.GetU32 (&offset);
+ s.Printf(" (cpu = %u, flavor=%u)", cpu, flavor);
+ }
+ break;
+
+ case eCommandTypeMaxBytes:
+ case eCommandTypeWriteMemory:
+ case eCommandTypeWriteRegisters:
+ case eCommandTypeLoad:
+ case eCommandTypeImagePath:
+ case eCommandTypeSuspend:
+ case eCommandTypeResume:
+ case eCommandTypeException:
+ case eCommandTypeTermination:
+ case eCommandTypeBreakpointSet:
+ case eCommandTypeBreakpointRemove:
+ break;
+
+ case eCommandTypeReattach:
+ {
+ const uint16_t reply_port = packet.GetU16 (&offset);
+ s.Printf(" (reply_port=%u)", reply_port);
+ }
+ break;
+
+ case eCommandTypeWriteMemory64:
+ case eCommandTypeBreakpointSet64:
+ case eCommandTypeBreakpointRemove64:
+ case eCommandTypeKernelVersion:
+ break;
+ }
+ }
+ }
+ else
+ {
+ error_desc = "error: invalid packet command: ";
+ }
+ }
+
+ if (error_desc)
+ {
+ s.PutCString (error_desc);
+
+ packet.Dump (&s, // Stream to dump to
+ 0, // Offset into "packet"
+ eFormatBytes, // Dump as hex bytes
+ 1, // Size of each item is 1 for single bytes
+ packet.GetByteSize(), // Number of bytes
+ UINT32_MAX, // Num bytes per line
+ LLDB_INVALID_ADDRESS, // Base address
+ 0, 0); // Bitfield info set to not do anything bitfield related
+ }
+}
+
+uint32_t
+CommunicationKDP::SendRequestReadRegisters (uint32_t cpu,
+ uint32_t flavor,
+ void *dst,
+ uint32_t dst_len,
+ Error &error)
+{
+ PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
+ const CommandType command = eCommandTypeReadRegisters;
+ // Size is header + 4 byte cpu and 4 byte flavor
+ const uint32_t command_length = 8 + 4 + 4;
+ const uint32_t request_sequence_id = m_request_sequence_id;
+ MakeRequestPacketHeader (command, request_packet, command_length);
+ request_packet.PutHex32 (cpu);
+ request_packet.PutHex32 (flavor);
+ DataExtractor reply_packet;
+ if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+ {
+ // Reset the sequence ID to zero for reattach
+ uint32_t offset = 8;
+ uint32_t kdp_error = reply_packet.GetU32 (&offset);
+ uint32_t src_len = reply_packet.GetByteSize() - 12;
+
+ if (src_len > 0)
+ {
+ const uint32_t bytes_to_copy = std::min<uint32_t>(src_len, dst_len);
+ const void *src = reply_packet.GetData(&offset, bytes_to_copy);
+ if (src)
+ {
+ ::memcpy (dst, src, bytes_to_copy);
+ error.Clear();
+ // Return the number of bytes we could have returned regardless if
+ // we copied them or not, just so we know when things don't match up
+ return src_len;
+ }
+ }
+ if (kdp_error)
+ error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, flavor, kdp_error);
+ else
+ error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u", cpu, flavor);
+ }
+ return 0;
+}
+
diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h b/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h
index 83c8790562b..8e9d8b2235e 100644
--- a/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h
@@ -140,6 +140,9 @@ public:
lldb_private::ProcessLaunchInfo &launch_info);
+ //------------------------------------------------------------------
+ // Public Request Packets
+ //------------------------------------------------------------------
bool
SendRequestConnect (uint16_t reply_port,
uint16_t exc_port,
@@ -152,6 +155,24 @@ public:
SendRequestDisconnect ();
uint32_t
+ SendRequestReadMemory (lldb::addr_t addr,
+ void *buf,
+ uint32_t size,
+ lldb_private::Error &error);
+
+ uint32_t
+ SendRequestReadRegisters (uint32_t cpu,
+ uint32_t flavor,
+ void *dst,
+ uint32_t dst_size,
+ lldb_private::Error &error);
+// size_t
+// SendRequestWriteMemory (lldb::addr_t addr,
+// const void *buf,
+// size_t size,
+// lldb_private::Error &error);
+
+ uint32_t
GetVersion ();
uint32_t
@@ -184,9 +205,25 @@ protected:
PacketStreamType &request_packet,
uint16_t request_length);
+ //------------------------------------------------------------------
+ // Protected Request Packets (use public accessors which will cache
+ // results.
+ //------------------------------------------------------------------
bool
SendRequestVersion ();
+ bool
+ SendRequestHostInfo ();
+
+
+ void
+ DumpPacket (lldb_private::Stream &s,
+ const void *data,
+ uint32_t data_len);
+
+ void
+ DumpPacket (lldb_private::Stream &s,
+ const lldb_private::DataExtractor& extractor);
bool
VersionIsValid() const
@@ -201,7 +238,21 @@ protected:
}
bool
- SendRequestHostInfo ();
+ ExtractIsReply (uint8_t first_packet_byte) const
+ {
+ // TODO: handle big endian...
+ return (first_packet_byte & ePacketTypeMask) != 0;
+ }
+
+ CommandType
+ ExtractCommand (uint8_t first_packet_byte) const
+ {
+ // TODO: handle big endian...
+ return (CommandType)(first_packet_byte & eCommandTypeMask);
+ }
+
+ static const char *
+ GetCommandAsCString (uint8_t command);
void
ClearKDPSettings ();
@@ -214,6 +265,7 @@ protected:
//------------------------------------------------------------------
// Classes that inherit from CommunicationKDP can see and modify these
//------------------------------------------------------------------
+ uint32_t m_addr_byte_size;
lldb::ByteOrder m_byte_order;
uint32_t m_packet_timeout;
lldb_private::Mutex m_sequence_mutex; // Restrict access to sending/receiving packets to a single thread at a time
diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
index 77d3d1ced2b..6d33ea28634 100644
--- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
@@ -18,11 +18,12 @@
#include "lldb/Core/State.h"
#include "lldb/Host/Host.h"
#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
// Project includes
#include "ProcessKDP.h"
#include "ProcessKDPLog.h"
-//#include "ThreadKDP.h"
+#include "ThreadKDP.h"
#include "StopInfoMachException.h"
using namespace lldb;
@@ -182,7 +183,10 @@ ProcessKDP::DoConnectRemote (const char *remote_url)
ArchSpec kernel_arch;
kernel_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
m_target.SetArchitecture(kernel_arch);
- // TODO: thread registers based off of architecture...
+
+ SetID (1);
+ UpdateThreadListIfNeeded ();
+ SetPrivateState (eStateStopped);
}
}
else
@@ -295,34 +299,24 @@ ProcessKDP::UpdateThreadListIfNeeded ()
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())
+ if (m_thread_list.GetSize(false) == 0)
{
- // 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);
-// }
+ // We currently are making only one thread per core and we
+ // actually don't know about actual threads. Eventually we
+ // want to get the thread list from memory and note which
+ // threads are on CPU as those are the only ones that we
+ // will be able to resume.
+ ThreadList curr_thread_list (this);
+ curr_thread_list.SetStopID(stop_id);
+ const uint32_t cpu_mask = m_comm.GetCPUMask();
+ for (uint32_t cpu_mask_bit = 1; cpu_mask_bit & cpu_mask; cpu_mask_bit <<= 1)
+ {
+ // The thread ID is currently the CPU mask bit
+ ThreadSP thread_sp (new ThreadKDP (*this, cpu_mask_bit));
+ curr_thread_list.AddThread(thread_sp);
+ }
+ m_thread_list = curr_thread_list;
}
return GetThreadList().GetSize(false);
}
@@ -549,7 +543,9 @@ ProcessKDP::IsAlive ()
size_t
ProcessKDP::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error)
{
- error.SetErrorString ("ProcessKDP::DoReadMemory not implemented");
+ if (m_comm.IsConnected())
+ return m_comm.SendRequestReadMemory (addr, buf, size, error);
+ error.SetErrorString ("not connected");
return 0;
}
diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
index c967e2f41ed..36497130818 100644
--- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
@@ -183,6 +183,12 @@ public:
virtual lldb_private::Error
DisableWatchpoint (lldb_private::WatchpointLocation *wp_loc);
+ CommunicationKDP &
+ GetCommunication()
+ {
+ return m_comm;
+ }
+
protected:
friend class ThreadKDP;
friend class CommunicationKDP;
@@ -229,12 +235,6 @@ protected:
uint32_t
UpdateThreadListIfNeeded ();
- CommunicationKDP &
- GetCommunication()
- {
- return m_comm;
- }
-
enum
{
eBroadcastBitAsyncContinue = (1 << 0),
diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp
new file mode 100644
index 00000000000..fcc68658f2f
--- /dev/null
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp
@@ -0,0 +1,90 @@
+//===-- RegisterContextKDP_arm.cpp ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RegisterContextKDP_arm.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "ProcessKDP.h"
+#include "ThreadKDP.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+RegisterContextKDP_arm::RegisterContextKDP_arm(ThreadKDP &thread, uint32_t concrete_frame_idx) :
+ RegisterContextDarwin_arm (thread, concrete_frame_idx),
+ m_kdp_thread (thread)
+{
+}
+
+RegisterContextKDP_arm::~RegisterContextKDP_arm()
+{
+}
+
+int
+RegisterContextKDP_arm::DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
+{
+ Error error;
+ if (m_kdp_thread.GetKDPProcess().GetCommunication().SendRequestReadRegisters (tid,
+ GPRRegSet,
+ &gpr, sizeof(gpr),
+ error))
+ {
+ if (error.Success())
+ return 0;
+ }
+ return -1;
+}
+
+int
+RegisterContextKDP_arm::DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
+{
+ return -1;
+}
+
+int
+RegisterContextKDP_arm::DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
+{
+ return -1;
+}
+
+int
+RegisterContextKDP_arm::DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg)
+{
+ return -1;
+}
+
+int
+RegisterContextKDP_arm::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
+{
+ return -1;
+}
+
+int
+RegisterContextKDP_arm::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
+{
+ return -1;
+}
+
+int
+RegisterContextKDP_arm::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
+{
+ return -1;
+}
+
+int
+RegisterContextKDP_arm::DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg)
+{
+ return -1;
+}
+
+
diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.h b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.h
new file mode 100644
index 00000000000..1e547289d9c
--- /dev/null
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.h
@@ -0,0 +1,61 @@
+//===-- RegisterContextKDP_arm.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_RegisterContextKDP_arm_h_
+#define liblldb_RegisterContextKDP_arm_h_
+
+// C Includes
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "Plugins/Process/Utility/RegisterContextDarwin_arm.h"
+
+class ThreadKDP;
+
+class RegisterContextKDP_arm : public RegisterContextDarwin_arm
+{
+public:
+
+ RegisterContextKDP_arm (ThreadKDP &thread,
+ uint32_t concrete_frame_idx);
+
+ virtual
+ ~RegisterContextKDP_arm();
+
+protected:
+
+ virtual int
+ DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr);
+
+ int
+ DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu);
+
+ int
+ DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc);
+
+ int
+ DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg);
+
+ int
+ DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr);
+
+ int
+ DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu);
+
+ int
+ DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc);
+
+ int
+ DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg);
+
+ ThreadKDP &m_kdp_thread;
+};
+
+#endif // liblldb_RegisterContextKDP_arm_h_
diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp
new file mode 100644
index 00000000000..7b7fc0f5fee
--- /dev/null
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp
@@ -0,0 +1,71 @@
+//===-- RegisterContextKDP_i386.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 <mach/thread_act.h>
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "RegisterContextKDP_i386.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+RegisterContextKDP_i386::RegisterContextKDP_i386(Thread &thread, uint32_t concrete_frame_idx) :
+ RegisterContextDarwin_i386 (thread, concrete_frame_idx)
+{
+}
+
+RegisterContextKDP_i386::~RegisterContextKDP_i386()
+{
+}
+
+int
+RegisterContextKDP_i386::DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
+{
+ mach_msg_type_number_t count = GPRWordCount;
+ return ::thread_get_state(tid, flavor, (thread_state_t)&gpr, &count);
+}
+
+int
+RegisterContextKDP_i386::DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
+{
+ mach_msg_type_number_t count = FPUWordCount;
+ return ::thread_get_state(tid, flavor, (thread_state_t)&fpu, &count);
+}
+
+int
+RegisterContextKDP_i386::DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
+{
+ mach_msg_type_number_t count = EXCWordCount;
+ return ::thread_get_state(tid, flavor, (thread_state_t)&exc, &count);
+}
+
+int
+RegisterContextKDP_i386::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
+{
+ return ::thread_set_state(tid, flavor, (thread_state_t)&gpr, GPRWordCount);
+}
+
+int
+RegisterContextKDP_i386::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
+{
+ return ::thread_set_state(tid, flavor, (thread_state_t)&fpu, FPUWordCount);
+}
+
+int
+RegisterContextKDP_i386::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
+{
+ return ::thread_set_state(tid, flavor, (thread_state_t)&exc, EXCWordCount);
+}
+
+
diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.h b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.h
new file mode 100644
index 00000000000..641e49d8dc7
--- /dev/null
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.h
@@ -0,0 +1,49 @@
+//===-- RegisterContextKDP_i386.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_RegisterContextKDP_i386_h_
+#define liblldb_RegisterContextKDP_i386_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "Plugins/Process/Utility/RegisterContextDarwin_i386.h"
+
+class RegisterContextKDP_i386 : public RegisterContextDarwin_i386
+{
+public:
+ RegisterContextKDP_i386 (lldb_private::Thread &thread,
+ uint32_t concrete_frame_idx);
+
+ virtual
+ ~RegisterContextKDP_i386();
+
+protected:
+
+ virtual int
+ DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr);
+
+ int
+ DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu);
+
+ int
+ DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc);
+
+ int
+ DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr);
+
+ int
+ DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu);
+
+ int
+ DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc);
+};
+
+#endif // liblldb_RegisterContextKDP_i386_h_
diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp
new file mode 100644
index 00000000000..dc5a47cb1a9
--- /dev/null
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp
@@ -0,0 +1,66 @@
+//===-- RegisterContextKDP_x86_64.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 <mach/thread_act.h>
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "RegisterContextKDP_x86_64.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+RegisterContextKDP_x86_64::RegisterContextKDP_x86_64(Thread &thread, uint32_t concrete_frame_idx) :
+ RegisterContextDarwin_x86_64 (thread, concrete_frame_idx)
+{
+}
+
+RegisterContextKDP_x86_64::~RegisterContextKDP_x86_64()
+{
+}
+
+int
+RegisterContextKDP_x86_64::DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
+{
+ return -1;
+}
+
+int
+RegisterContextKDP_x86_64::DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
+{
+ return -1;
+}
+
+int
+RegisterContextKDP_x86_64::DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
+{
+ return -1;
+}
+
+int
+RegisterContextKDP_x86_64::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
+{
+ return -1;
+}
+
+int
+RegisterContextKDP_x86_64::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
+{
+ return -1;
+}
+
+int
+RegisterContextKDP_x86_64::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
+{
+ return -1;
+}
diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.h b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.h
new file mode 100644
index 00000000000..f1d41cb8302
--- /dev/null
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.h
@@ -0,0 +1,50 @@
+//===-- RegisterContextKDP_x86_64.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_RegisterContextKDP_x86_64_h_
+#define liblldb_RegisterContextKDP_x86_64_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "Plugins/Process/Utility/RegisterContextDarwin_x86_64.h"
+
+class RegisterContextKDP_x86_64 : public RegisterContextDarwin_x86_64
+{
+public:
+
+ RegisterContextKDP_x86_64 (lldb_private::Thread &thread,
+ uint32_t concrete_frame_idx);
+
+ virtual
+ ~RegisterContextKDP_x86_64();
+
+protected:
+
+ virtual int
+ DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr);
+
+ int
+ DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu);
+
+ int
+ DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc);
+
+ int
+ DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr);
+
+ int
+ DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu);
+
+ int
+ DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc);
+};
+
+#endif // liblldb_RegisterContextKDP_x86_64_h_
diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp
new file mode 100644
index 00000000000..dac551762f3
--- /dev/null
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp
@@ -0,0 +1,247 @@
+//===-- ThreadKDP.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "ThreadKDP.h"
+
+#include "llvm/Support/MachO.h"
+
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/State.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Unwind.h"
+#include "lldb/Breakpoint/WatchpointLocation.h"
+
+#include "ProcessKDP.h"
+#include "ProcessKDPLog.h"
+#include "RegisterContextKDP_arm.h"
+#include "RegisterContextKDP_i386.h"
+#include "RegisterContextKDP_x86_64.h"
+#include "Plugins/Process/Utility/UnwindLLDB.h"
+
+#if defined(__APPLE__)
+#include "UnwindMacOSXFrameBackchain.h"
+#endif
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Thread Registers
+//----------------------------------------------------------------------
+
+ThreadKDP::ThreadKDP (ProcessKDP &process, lldb::tid_t tid) :
+ Thread(process, tid),
+ m_thread_name (),
+ m_dispatch_queue_name (),
+ m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS)
+{
+ ProcessKDPLog::LogIf(KDP_LOG_THREAD, "%p: ThreadKDP::ThreadKDP (pid = %i, tid = 0x%4.4x)", this, m_process.GetID(), GetID());
+}
+
+ThreadKDP::~ThreadKDP ()
+{
+ ProcessKDPLog::LogIf(KDP_LOG_THREAD, "%p: ThreadKDP::~ThreadKDP (pid = %i, tid = 0x%4.4x)", this, m_process.GetID(), GetID());
+ DestroyThread();
+}
+
+
+const char *
+ThreadKDP::GetInfo ()
+{
+ return NULL;
+}
+
+
+const char *
+ThreadKDP::GetName ()
+{
+ if (m_thread_name.empty())
+ return NULL;
+ return m_thread_name.c_str();
+}
+
+const char *
+ThreadKDP::GetQueueName ()
+{
+ return NULL;
+}
+
+bool
+ThreadKDP::WillResume (StateType resume_state)
+{
+ ClearStackFrames();
+ // Call the Thread::WillResume first. If we stop at a signal, the stop info
+ // class for signal will set the resume signal that we need below. The signal
+ // stuff obeys the Process::UnixSignal defaults.
+ Thread::WillResume(resume_state);
+
+ lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
+ if (log)
+ log->Printf ("Resuming thread: %4.4x with state: %s.", GetID(), StateAsCString(resume_state));
+
+// ProcessKDP &process = GetKDPProcess();
+// switch (resume_state)
+// {
+// case eStateSuspended:
+// case eStateStopped:
+// // Don't append anything for threads that should stay stopped.
+// break;
+//
+// case eStateRunning:
+// case eStateStepping:
+// break;
+//
+// default:
+// break;
+// }
+ return true;
+}
+
+void
+ThreadKDP::RefreshStateAfterStop()
+{
+ // Invalidate all registers in our register context. We don't set "force" to
+ // true because the stop reply packet might have had some register values
+ // that were expedited and these will already be copied into the register
+ // context by the time this function gets called. The KDPRegisterContext
+ // class has been made smart enough to detect when it needs to invalidate
+ // which registers are valid by putting hooks in the register read and
+ // register supply functions where they check the process stop ID and do
+ // the right thing.
+ const bool force = false;
+ GetRegisterContext()->InvalidateIfNeeded (force);
+}
+
+Unwind *
+ThreadKDP::GetUnwinder ()
+{
+ if (m_unwinder_ap.get() == NULL)
+ {
+ const ArchSpec target_arch (GetProcess().GetTarget().GetArchitecture ());
+ const llvm::Triple::ArchType machine = target_arch.GetMachine();
+ switch (machine)
+ {
+ case llvm::Triple::x86_64:
+ case llvm::Triple::x86:
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ m_unwinder_ap.reset (new UnwindLLDB (*this));
+ break;
+
+ default:
+#if defined(__APPLE__)
+ m_unwinder_ap.reset (new UnwindMacOSXFrameBackchain (*this));
+#endif
+ break;
+ }
+ }
+ return m_unwinder_ap.get();
+}
+
+void
+ThreadKDP::ClearStackFrames ()
+{
+ Unwind *unwinder = GetUnwinder ();
+ if (unwinder)
+ unwinder->Clear();
+ Thread::ClearStackFrames();
+}
+
+
+bool
+ThreadKDP::ThreadIDIsValid (lldb::tid_t thread)
+{
+ return thread != 0;
+}
+
+void
+ThreadKDP::Dump(Log *log, uint32_t index)
+{
+}
+
+
+bool
+ThreadKDP::ShouldStop (bool &step_more)
+{
+ return true;
+}
+lldb::RegisterContextSP
+ThreadKDP::GetRegisterContext ()
+{
+ if (m_reg_context_sp.get() == NULL)
+ m_reg_context_sp = CreateRegisterContextForFrame (NULL);
+ return m_reg_context_sp;
+}
+
+lldb::RegisterContextSP
+ThreadKDP::CreateRegisterContextForFrame (StackFrame *frame)
+{
+ lldb::RegisterContextSP reg_ctx_sp;
+ uint32_t concrete_frame_idx = 0;
+
+ if (frame)
+ concrete_frame_idx = frame->GetConcreteFrameIndex ();
+
+ if (concrete_frame_idx == 0)
+ {
+ switch (GetKDPProcess().GetCommunication().GetCPUType())
+ {
+ case llvm::MachO::CPUTypeARM:
+ reg_ctx_sp.reset (new RegisterContextKDP_arm (*this, concrete_frame_idx));
+ break;
+ case llvm::MachO::CPUTypeI386:
+ reg_ctx_sp.reset (new RegisterContextKDP_i386 (*this, concrete_frame_idx));
+ break;
+ case llvm::MachO::CPUTypeX86_64:
+ reg_ctx_sp.reset (new RegisterContextKDP_x86_64 (*this, concrete_frame_idx));
+ break;
+ default:
+ assert (!"Add CPU type support in KDP");
+ break;
+ }
+ }
+ else if (m_unwinder_ap.get())
+ reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame (frame);
+ return reg_ctx_sp;
+}
+
+lldb::StopInfoSP
+ThreadKDP::GetPrivateStopReason ()
+{
+ const uint32_t process_stop_id = GetProcess().GetStopID();
+ if (m_thread_stop_reason_stop_id != process_stop_id ||
+ (m_actual_stop_info_sp && !m_actual_stop_info_sp->IsValid()))
+ {
+ // TODO: can we query the initial state of the thread here?
+ // For now I am just going to pretend that a SIGSTOP happened.
+
+ SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, SIGSTOP));
+
+ // If GetKDPProcess().SetThreadStopInfo() doesn't find a stop reason
+ // for this thread, then m_actual_stop_info_sp will not ever contain
+ // a valid stop reason and the "m_actual_stop_info_sp->IsValid() == false"
+ // check will never be able to tell us if we have the correct stop info
+ // for this thread and we will continually send qThreadStopInfo packets
+ // down to the remote KDP server, so we need to keep our own notion
+ // of the stop ID that m_actual_stop_info_sp is valid for (even if it
+ // contains nothing). We use m_thread_stop_reason_stop_id for this below.
+// m_thread_stop_reason_stop_id = process_stop_id;
+// m_actual_stop_info_sp.reset();
+
+ }
+ return m_actual_stop_info_sp;
+}
+
+
diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h b/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h
new file mode 100644
index 00000000000..95c2f0577e4
--- /dev/null
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h
@@ -0,0 +1,115 @@
+//===-- ThreadKDP.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_ThreadKDP_h_
+#define liblldb_ThreadKDP_h_
+
+#include <string>
+
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+
+class ProcessKDP;
+
+class ThreadKDP : public lldb_private::Thread
+{
+public:
+ ThreadKDP (ProcessKDP &process,
+ lldb::tid_t tid);
+
+ virtual
+ ~ThreadKDP ();
+
+ virtual bool
+ WillResume (lldb::StateType resume_state);
+
+ virtual void
+ RefreshStateAfterStop();
+
+ virtual const char *
+ GetInfo ();
+
+ virtual const char *
+ GetName ();
+
+ virtual const char *
+ GetQueueName ();
+
+ virtual lldb::RegisterContextSP
+ GetRegisterContext ();
+
+ virtual lldb::RegisterContextSP
+ CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+
+ virtual void
+ ClearStackFrames ();
+
+ ProcessKDP &
+ GetKDPProcess ()
+ {
+ return (ProcessKDP &)m_process;
+ }
+
+ void
+ Dump (lldb_private::Log *log, uint32_t index);
+
+ static bool
+ ThreadIDIsValid (lldb::tid_t thread);
+
+ bool
+ ShouldStop (bool &step_more);
+
+ const char *
+ GetBasicInfoAsString ();
+
+ void
+ SetName (const char *name)
+ {
+ if (name && name[0])
+ m_thread_name.assign (name);
+ else
+ m_thread_name.clear();
+ }
+
+ lldb::addr_t
+ GetThreadDispatchQAddr ()
+ {
+ return m_thread_dispatch_qaddr;
+ }
+
+ void
+ SetThreadDispatchQAddr (lldb::addr_t thread_dispatch_qaddr)
+ {
+ m_thread_dispatch_qaddr = thread_dispatch_qaddr;
+ }
+
+protected:
+
+ friend class ProcessKDP;
+
+ //------------------------------------------------------------------
+ // Member variables.
+ //------------------------------------------------------------------
+ std::string m_thread_name;
+ std::string m_dispatch_queue_name;
+ lldb::addr_t m_thread_dispatch_qaddr;
+ //------------------------------------------------------------------
+ // Member variables.
+ //------------------------------------------------------------------
+
+ virtual lldb_private::Unwind *
+ GetUnwinder ();
+
+ virtual lldb::StopInfoSP
+ GetPrivateStopReason ();
+
+
+};
+
+#endif // liblldb_ThreadKDP_h_
OpenPOWER on IntegriCloud