forked from OSchip/llvm-project
Added KDP resume, suspend, set/remove breakpoint, and kernel version support.
Also we now display a live update of the kexts that we are loading. llvm-svn: 135563
This commit is contained in:
parent
60648578ba
commit
07e66e3ebe
|
@ -198,9 +198,12 @@ CommandObjectExpression::MultiLineExpressionCallback
|
|||
case eInputReaderActivate:
|
||||
if (!batch_mode)
|
||||
{
|
||||
StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
|
||||
out_stream->Printf("%s\n", "Enter expressions, then terminate with an empty line to evaluate:");
|
||||
out_stream->Flush();
|
||||
StreamSP async_strm_sp(reader.GetDebugger().GetAsyncOutputStream());
|
||||
if (async_strm_sp)
|
||||
{
|
||||
async_strm_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n");
|
||||
async_strm_sp->Flush();
|
||||
}
|
||||
}
|
||||
// Fall through
|
||||
case eInputReaderReactivate:
|
||||
|
@ -228,9 +231,12 @@ CommandObjectExpression::MultiLineExpressionCallback
|
|||
reader.SetIsDone (true);
|
||||
if (!batch_mode)
|
||||
{
|
||||
StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
|
||||
out_stream->Printf("%s\n", "Expression evaluation cancelled.");
|
||||
out_stream->Flush();
|
||||
StreamSP async_strm_sp (reader.GetDebugger().GetAsyncOutputStream());
|
||||
if (async_strm_sp)
|
||||
{
|
||||
async_strm_sp->PutCString("Expression evaluation cancelled.\n");
|
||||
async_strm_sp->Flush();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "lldb/Breakpoint/StoppointCallbackContext.h"
|
||||
#include "lldb/Core/DataBuffer.h"
|
||||
#include "lldb/Core/DataBufferHeap.h"
|
||||
#include "lldb/Core/Debugger.h"
|
||||
#include "lldb/Core/Log.h"
|
||||
#include "lldb/Core/Module.h"
|
||||
#include "lldb/Core/PluginManager.h"
|
||||
|
@ -499,8 +500,25 @@ DynamicLoaderMacOSXKernel::ParseKextSummaries (const Address &kext_summary_addr,
|
|||
if (!ReadKextSummaries (kext_summary_addr, count, kext_summaries))
|
||||
return false;
|
||||
|
||||
Stream *s = &m_process->GetTarget().GetDebugger().GetOutputStream();
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
{
|
||||
if (s)
|
||||
{
|
||||
const uint8_t *u = (const uint8_t *)kext_summaries[i].uuid.GetBytes();
|
||||
if (u)
|
||||
{
|
||||
s->Printf("Loading kext: %2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X 0x%16.16llx \"%s\"...\n",
|
||||
u[ 0], u[ 1], u[ 2], u[ 3], u[ 4], u[ 5], u[ 6], u[ 7],
|
||||
u[ 8], u[ 9], u[10], u[11], u[12], u[13], u[14], u[15],
|
||||
kext_summaries[i].address, kext_summaries[i].name);
|
||||
}
|
||||
else
|
||||
{
|
||||
s->Printf("0x%16.16llx \"%s\"...\n", kext_summaries[i].address, kext_summaries[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
DataExtractor data; // Load command data
|
||||
if (ReadMachHeader (kext_summaries[i], &data))
|
||||
{
|
||||
|
@ -868,7 +886,7 @@ DynamicLoaderMacOSXKernel::OSKextLoadedKextSummary::PutToLog (Log *log) const
|
|||
{
|
||||
if (log == NULL)
|
||||
return;
|
||||
uint8_t *u = (uint8_t *)uuid.GetBytes();
|
||||
const uint8_t *u = (uint8_t *)uuid.GetBytes();
|
||||
|
||||
if (address == LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
|
|
|
@ -469,6 +469,33 @@ CommunicationKDP::SendRequestHostInfo ()
|
|||
return false;
|
||||
}
|
||||
|
||||
const char *
|
||||
CommunicationKDP::GetKernelVersion ()
|
||||
{
|
||||
if (m_kernel_version.empty())
|
||||
SendRequestKernelVersion ();
|
||||
return m_kernel_version.c_str();
|
||||
}
|
||||
|
||||
bool
|
||||
CommunicationKDP::SendRequestKernelVersion ()
|
||||
{
|
||||
PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
|
||||
const CommandType command = eCommandTypeKernelVersion;
|
||||
const uint32_t command_length = 8;
|
||||
const uint32_t request_sequence_id = m_request_sequence_id;
|
||||
MakeRequestPacketHeader (command, request_packet, command_length);
|
||||
DataExtractor reply_packet;
|
||||
if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
|
||||
{
|
||||
const char *kernel_version_cstr = reply_packet.PeekCStr(8);
|
||||
if (kernel_version_cstr && kernel_version_cstr[0])
|
||||
m_kernel_version.assign (kernel_version_cstr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CommunicationKDP::SendRequestDisconnect ()
|
||||
{
|
||||
|
@ -700,7 +727,14 @@ CommunicationKDP::DumpPacket (Stream &s, const DataExtractor& packet)
|
|||
const uint32_t count = packet.GetByteSize() - offset;
|
||||
s.Printf(" (error = 0x%8.8x <0x%x>:\n", error, count);
|
||||
if (count > 0)
|
||||
DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, count), count, 32, LLDB_INVALID_ADDRESS);
|
||||
packet.Dump (&s, // Stream to dump to
|
||||
offset, // Offset within "packet"
|
||||
eFormatBytesWithASCII, // Format to use
|
||||
1, // Size of each item in bytes
|
||||
count, // Number of items
|
||||
16, // Number per line
|
||||
m_last_read_memory_addr, // Don't show addresses before each line
|
||||
0, 0); // No bitfields
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -721,9 +755,26 @@ CommunicationKDP::DumpPacket (Stream &s, const DataExtractor& packet)
|
|||
}
|
||||
break;
|
||||
|
||||
case eCommandTypeMaxBytes:
|
||||
case eCommandTypeImagePath:
|
||||
case eCommandTypeKernelVersion:
|
||||
{
|
||||
const char *kernel_version = packet.PeekCStr(8);
|
||||
s.Printf(" (version = \"%s\")", kernel_version);
|
||||
}
|
||||
break;
|
||||
|
||||
case eCommandTypeMaxBytes:
|
||||
{
|
||||
const uint32_t max_bytes = packet.GetU32 (&offset);
|
||||
s.Printf(" (max_bytes = 0x%8.8x (%u))", max_bytes, max_bytes);
|
||||
}
|
||||
break;
|
||||
case eCommandTypeImagePath:
|
||||
{
|
||||
const char *path = packet.GetCStr(&offset);
|
||||
s.Printf(" (path = \"%s\")", path);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
s.Printf(" (add support for dumping this packet reply!!!");
|
||||
break;
|
||||
|
||||
|
@ -747,7 +798,19 @@ CommunicationKDP::DumpPacket (Stream &s, const DataExtractor& packet)
|
|||
case eCommandTypeHostInfo:
|
||||
case eCommandTypeVersion:
|
||||
case eCommandTypeRegions:
|
||||
case eCommandTypeKernelVersion:
|
||||
case eCommandTypeMaxBytes:
|
||||
case eCommandTypeImagePath:
|
||||
case eCommandTypeSuspend:
|
||||
// No args, just the header in the request...
|
||||
s.PutCString(" ()");
|
||||
break;
|
||||
|
||||
case eCommandTypeResume:
|
||||
{
|
||||
const uint32_t cpu_mask = packet.GetU32 (&offset);
|
||||
s.Printf(" (cpu_mask = 0x%8.8x)", cpu_mask);
|
||||
}
|
||||
break;
|
||||
|
||||
case eCommandTypeReadMemory:
|
||||
|
@ -755,6 +818,7 @@ CommunicationKDP::DumpPacket (Stream &s, const DataExtractor& packet)
|
|||
const uint32_t addr = packet.GetU32 (&offset);
|
||||
const uint32_t size = packet.GetU32 (&offset);
|
||||
s.Printf(" (addr = 0x%8.8x, size=%u)", addr, size);
|
||||
m_last_read_memory_addr = addr;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -773,6 +837,7 @@ CommunicationKDP::DumpPacket (Stream &s, const DataExtractor& packet)
|
|||
const uint64_t addr = packet.GetU64 (&offset);
|
||||
const uint32_t size = packet.GetU32 (&offset);
|
||||
s.Printf(" (addr = 0x%16.16llx, size=%u)", addr, size);
|
||||
m_last_read_memory_addr = addr;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -812,16 +877,71 @@ CommunicationKDP::DumpPacket (Stream &s, const DataExtractor& packet)
|
|||
}
|
||||
break;
|
||||
|
||||
case eCommandTypeMaxBytes:
|
||||
|
||||
case eCommandTypeLoad:
|
||||
case eCommandTypeImagePath:
|
||||
case eCommandTypeSuspend:
|
||||
case eCommandTypeResume:
|
||||
case eCommandTypeException:
|
||||
case eCommandTypeTermination:
|
||||
case eCommandTypeBreakpointSet:
|
||||
case eCommandTypeBreakpointRemove:
|
||||
{
|
||||
const uint32_t addr = packet.GetU32 (&offset);
|
||||
s.Printf(" (addr = 0x%8.8x)", addr);
|
||||
}
|
||||
break;
|
||||
|
||||
case eCommandTypeBreakpointSet64:
|
||||
case eCommandTypeBreakpointRemove64:
|
||||
{
|
||||
const uint64_t addr = packet.GetU64 (&offset);
|
||||
s.Printf(" (addr = 0x%16.16llx)", addr);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case eCommandTypeLoad:
|
||||
{
|
||||
const char *path = packet.GetCStr(&offset);
|
||||
s.Printf(" (path = \"%s\")", path);
|
||||
}
|
||||
break;
|
||||
|
||||
case eCommandTypeException:
|
||||
{
|
||||
const uint32_t count = packet.GetU32 (&offset);
|
||||
|
||||
s.Printf(" (count = %u:", count);
|
||||
for (uint32_t i=0; i<count; ++i)
|
||||
{
|
||||
const uint32_t cpu = packet.GetU32 (&offset);
|
||||
const uint32_t exc = packet.GetU32 (&offset);
|
||||
const uint32_t code = packet.GetU32 (&offset);
|
||||
const uint32_t subcode = packet.GetU32 (&offset);
|
||||
const char *exc_cstr = NULL;
|
||||
switch (exc)
|
||||
{
|
||||
case 1: exc_cstr = "EXC_BAD_ACCESS"; break;
|
||||
case 2: exc_cstr = "EXC_BAD_INSTRUCTION"; break;
|
||||
case 3: exc_cstr = "EXC_ARITHMETIC"; break;
|
||||
case 4: exc_cstr = "EXC_EMULATION"; break;
|
||||
case 5: exc_cstr = "EXC_SOFTWARE"; break;
|
||||
case 6: exc_cstr = "EXC_BREAKPOINT"; break;
|
||||
case 7: exc_cstr = "EXC_SYSCALL"; break;
|
||||
case 8: exc_cstr = "EXC_MACH_SYSCALL"; break;
|
||||
case 9: exc_cstr = "EXC_RPC_ALERT"; break;
|
||||
case 10: exc_cstr = "EXC_CRASH"; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
s.Printf ("\n cpu = 0x%8.8x, exc = %s (%u), code = %u (0x%8.8x), subcode = %u (0x%8.8x)\n",
|
||||
cpu, exc_cstr, exc, code, code, subcode, subcode);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case eCommandTypeTermination:
|
||||
{
|
||||
const uint32_t term_code = packet.GetU32 (&offset);
|
||||
const uint32_t exit_code = packet.GetU32 (&offset);
|
||||
s.Printf(" (term_code = 0x%8.8x (%u), exit_code = 0x%8.8x (%u))", term_code, term_code, exit_code, exit_code);
|
||||
}
|
||||
break;
|
||||
|
||||
case eCommandTypeReattach:
|
||||
|
@ -830,12 +950,6 @@ CommunicationKDP::DumpPacket (Stream &s, const DataExtractor& packet)
|
|||
s.Printf(" (reply_port=%u)", reply_port);
|
||||
}
|
||||
break;
|
||||
|
||||
case eCommandTypeBreakpointSet64:
|
||||
case eCommandTypeBreakpointRemove64:
|
||||
case eCommandTypeKernelVersion:
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -903,3 +1017,56 @@ CommunicationKDP::SendRequestReadRegisters (uint32_t cpu,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CommunicationKDP::SendRequestResume (uint32_t cpu_mask)
|
||||
{
|
||||
if (cpu_mask == 0)
|
||||
cpu_mask = GetCPUMask();
|
||||
PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
|
||||
const CommandType command = eCommandTypeResume;
|
||||
const uint32_t command_length = 12;
|
||||
const uint32_t request_sequence_id = m_request_sequence_id;
|
||||
MakeRequestPacketHeader (command, request_packet, command_length);
|
||||
request_packet.PutHex32(cpu_mask);
|
||||
|
||||
DataExtractor reply_packet;
|
||||
if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CommunicationKDP::SendRequestBreakpoint (bool set, addr_t addr)
|
||||
{
|
||||
PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
|
||||
bool use_64 = (GetVersion() >= 11);
|
||||
uint32_t command_addr_byte_size = use_64 ? 8 : 4;
|
||||
const CommandType command = set ? (use_64 ? eCommandTypeBreakpointSet64 : eCommandTypeBreakpointSet ):
|
||||
(use_64 ? eCommandTypeBreakpointRemove64 : eCommandTypeBreakpointRemove);
|
||||
|
||||
const uint32_t command_length = 8 + command_addr_byte_size;
|
||||
const uint32_t request_sequence_id = m_request_sequence_id;
|
||||
MakeRequestPacketHeader (command, request_packet, command_length);
|
||||
request_packet.PutMaxHex64 (addr, command_addr_byte_size);
|
||||
|
||||
DataExtractor reply_packet;
|
||||
if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CommunicationKDP::SendRequestSuspend ()
|
||||
{
|
||||
PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
|
||||
const CommandType command = eCommandTypeSuspend;
|
||||
const uint32_t command_length = 8;
|
||||
const uint32_t request_sequence_id = m_request_sequence_id;
|
||||
MakeRequestPacketHeader (command, request_packet, command_length);
|
||||
DataExtractor reply_packet;
|
||||
if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -65,6 +65,11 @@ public:
|
|||
eCommandTypeKernelVersion
|
||||
} CommandType;
|
||||
|
||||
enum
|
||||
{
|
||||
eFeatureLocalBreakpointsSupported = (1u << 0),
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KDP_PROTERR_SUCCESS = 0,
|
||||
|
@ -173,12 +178,21 @@ public:
|
|||
uint32_t dst_size,
|
||||
lldb_private::Error &error);
|
||||
|
||||
const char *
|
||||
GetKernelVersion ();
|
||||
|
||||
uint32_t
|
||||
GetVersion ();
|
||||
|
||||
uint32_t
|
||||
GetFeatureFlags ();
|
||||
|
||||
bool
|
||||
LocalBreakpointsAreSupported ()
|
||||
{
|
||||
return (GetFeatureFlags() & eFeatureLocalBreakpointsSupported) != 0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
GetCPUMask ();
|
||||
|
||||
|
@ -188,6 +202,16 @@ public:
|
|||
uint32_t
|
||||
GetCPUSubtype ();
|
||||
|
||||
// If cpu_mask is zero, then we will resume all CPUs
|
||||
bool
|
||||
SendRequestResume (uint32_t cpu_mask = 0);
|
||||
|
||||
bool
|
||||
SendRequestSuspend ();
|
||||
|
||||
bool
|
||||
SendRequestBreakpoint (bool set, lldb::addr_t addr);
|
||||
|
||||
protected:
|
||||
typedef std::list<std::string> packet_collection;
|
||||
|
||||
|
@ -216,6 +240,8 @@ protected:
|
|||
bool
|
||||
SendRequestHostInfo ();
|
||||
|
||||
bool
|
||||
SendRequestKernelVersion ();
|
||||
|
||||
void
|
||||
DumpPacket (lldb_private::Stream &s,
|
||||
|
@ -280,6 +306,8 @@ protected:
|
|||
uint32_t m_kdp_hostinfo_cpu_mask;
|
||||
uint32_t m_kdp_hostinfo_cpu_type;
|
||||
uint32_t m_kdp_hostinfo_cpu_subtype;
|
||||
std::string m_kernel_version;
|
||||
lldb::addr_t m_last_read_memory_addr; // Last memory read address for logging
|
||||
private:
|
||||
//------------------------------------------------------------------
|
||||
// For CommunicationKDP only
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
// C++ Includes
|
||||
// Other libraries and framework includes
|
||||
#include "lldb/Core/ConnectionFileDescriptor.h"
|
||||
#include "lldb/Core/Debugger.h"
|
||||
#include "lldb/Core/PluginManager.h"
|
||||
#include "lldb/Core/State.h"
|
||||
#include "lldb/Host/Host.h"
|
||||
|
@ -183,10 +184,19 @@ ProcessKDP::DoConnectRemote (const char *remote_url)
|
|||
ArchSpec kernel_arch;
|
||||
kernel_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
|
||||
m_target.SetArchitecture(kernel_arch);
|
||||
|
||||
SetID (1);
|
||||
UpdateThreadListIfNeeded ();
|
||||
SetPrivateState (eStateStopped);
|
||||
StreamSP async_strm_sp(m_target.GetDebugger().GetAsyncOutputStream());
|
||||
if (async_strm_sp)
|
||||
{
|
||||
const char *kernel_version = m_comm.GetKernelVersion ();
|
||||
if (kernel_version)
|
||||
{
|
||||
async_strm_sp->Printf ("KDP connected to %s\n", kernel_version);
|
||||
async_strm_sp->Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -237,24 +247,6 @@ ProcessKDP::DoAttachToProcessWithID (lldb::pid_t attach_pid)
|
|||
return error;
|
||||
}
|
||||
|
||||
size_t
|
||||
ProcessKDP::AttachInputReaderCallback (void *baton,
|
||||
InputReader *reader,
|
||||
lldb::InputReaderAction notification,
|
||||
const char *bytes,
|
||||
size_t bytes_len)
|
||||
{
|
||||
if (notification == eInputReaderGotToken)
|
||||
{
|
||||
// ProcessKDP *process = (ProcessKDP *)baton;
|
||||
// if (process->m_waiting_for_attach)
|
||||
// process->m_waiting_for_attach = false;
|
||||
reader->SetIsDone(true);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Error
|
||||
ProcessKDP::DoAttachToProcessWithName (const char *process_name, bool wait_for_launch)
|
||||
{
|
||||
|
@ -286,7 +278,8 @@ Error
|
|||
ProcessKDP::DoResume ()
|
||||
{
|
||||
Error error;
|
||||
error.SetErrorString ("ProcessKDP::DoResume () is not implemented yet");
|
||||
if (!m_comm.SendRequestResume ())
|
||||
error.SetErrorString ("KDP resume failed");
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -354,15 +347,8 @@ ProcessKDP::DoHalt (bool &caused_stop)
|
|||
}
|
||||
else
|
||||
{
|
||||
// TODO: add the ability to halt a running kernel
|
||||
error.SetErrorString ("halt not supported in kdp-remote plug-in");
|
||||
// if (!m_comm.SendInterrupt (locker, 2, caused_stop, timed_out))
|
||||
// {
|
||||
// if (timed_out)
|
||||
// error.SetErrorString("timed out sending interrupt packet");
|
||||
// else
|
||||
// error.SetErrorString("unknown error sending interrupt packet");
|
||||
// }
|
||||
if (!m_comm.SendRequestSuspend ())
|
||||
error.SetErrorString ("KDP halt failed");
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
@ -574,12 +560,26 @@ ProcessKDP::DoDeallocateMemory (lldb::addr_t addr)
|
|||
Error
|
||||
ProcessKDP::EnableBreakpoint (BreakpointSite *bp_site)
|
||||
{
|
||||
if (m_comm.LocalBreakpointsAreSupported ())
|
||||
{
|
||||
Error error;
|
||||
if (!m_comm.SendRequestBreakpoint(true, bp_site->GetLoadAddress()))
|
||||
error.SetErrorString ("KDP set breakpoint failed");
|
||||
return error;
|
||||
}
|
||||
return EnableSoftwareBreakpoint (bp_site);
|
||||
}
|
||||
|
||||
Error
|
||||
ProcessKDP::DisableBreakpoint (BreakpointSite *bp_site)
|
||||
{
|
||||
if (m_comm.LocalBreakpointsAreSupported ())
|
||||
{
|
||||
Error error;
|
||||
if (!m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress()))
|
||||
error.SetErrorString ("KDP remove breakpoint failed");
|
||||
return error;
|
||||
}
|
||||
return DisableSoftwareBreakpoint (bp_site);
|
||||
}
|
||||
|
||||
|
|
|
@ -265,13 +265,6 @@ protected:
|
|||
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
|
||||
|
|
Loading…
Reference in New Issue