From 07e66e3ebef8859d7b421ac5778ef92b980a16f3 Mon Sep 17 00:00:00 2001 From: Greg Clayton Date: Wed, 20 Jul 2011 03:41:06 +0000 Subject: [PATCH] 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 --- .../Commands/CommandObjectExpression.cpp | 18 +- .../DynamicLoaderMacOSXKernel.cpp | 20 +- .../MacOSX-Kernel/CommunicationKDP.cpp | 199 ++++++++++++++++-- .../Process/MacOSX-Kernel/CommunicationKDP.h | 28 +++ .../Process/MacOSX-Kernel/ProcessKDP.cpp | 58 ++--- .../Process/MacOSX-Kernel/ProcessKDP.h | 7 - 6 files changed, 271 insertions(+), 59 deletions(-) diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index 0afb0eb13db9..cab8ed549fce 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -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; diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp index d59600ce1738..2361b6394dc6 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp @@ -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) { diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp index 230dc87b3107..0b8d51dae659 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp @@ -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= 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; +} + diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h b/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h index 8c5b6d5f2ba5..e4e92c820728 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h @@ -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 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 diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp index 6d33ea286348..2d3a617a239d 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp @@ -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); } diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h index 364971308188..7f254d09e141 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h @@ -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