[Lldb-commits] [lldb] r135338 - in /lldb/trunk: include/lldb/Core/ConnectionFileDescriptor.h include/lldb/Core/DataExtractor.h include/lldb/Core/StreamBuffer.h include/lldb/Core/StreamString.h include/lldb/lldb-forward.h lldb.xcodeproj/project.pbxproj source/Core/ConnectionFileDescriptor.cpp source/Core/DataExtractor.cpp source/Core/StreamString.cpp source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
Greg Clayton
gclayton at apple.com
Fri Jul 15 20:19:08 PDT 2011
Author: gclayton
Date: Fri Jul 15 22:19:08 2011
New Revision: 135338
URL: http://llvm.org/viewvc/llvm-project?rev=135338&view=rev
Log:
Completed more work on the KDP darwin kernel debugging Process plug-in.
Implemented connect, disconnect, reattach, version, and hostinfo.
Modified the ConnectionFileDescriptor class to be able to handle UDP.
Added a new Stream subclass called StreamBuffer that is backed by a
llvm::SmallVector for better efficiency.
Modified the DataExtractor class to have a static function that can
dump hex bytes into a stream. This is currently being used to dump incoming
binary packet data in the KDP plug-in.
Added:
lldb/trunk/include/lldb/Core/StreamBuffer.h
Modified:
lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h
lldb/trunk/include/lldb/Core/DataExtractor.h
lldb/trunk/include/lldb/Core/StreamString.h
lldb/trunk/include/lldb/lldb-forward.h
lldb/trunk/lldb.xcodeproj/project.pbxproj
lldb/trunk/source/Core/ConnectionFileDescriptor.cpp
lldb/trunk/source/Core/DataExtractor.cpp
lldb/trunk/source/Core/StreamString.cpp
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
Modified: lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h?rev=135338&r1=135337&r2=135338&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h (original)
+++ lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h Fri Jul 15 22:19:08 2011
@@ -11,6 +11,10 @@
#define liblldb_ConnectionFileDescriptor_h_
// C Includes
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
// C++ Includes
// Other libraries and framework includes
// Project includes
@@ -75,8 +79,16 @@
lldb::ConnectionStatus
Close (int& fd, Error *error);
+ typedef enum
+ {
+ eFDTypeFile, // Other FD requireing read/write
+ eFDTypeSocket, // Socket requiring send/recv
+ eFDTypeSocketUDP // Unconnected UDP socket requiring sendto/recvfrom
+ } FDType;
int m_fd; // Socket we use to communicate once conn established
- bool m_is_socket;
+ FDType m_fd_type;
+ struct sockaddr_storage m_udp_sockaddr;
+ socklen_t m_udp_sockaddr_len;
bool m_should_close_fd; // True if this class should close the file descriptor when it goes away.
uint32_t m_socket_timeout_usec;
Modified: lldb/trunk/include/lldb/Core/DataExtractor.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/DataExtractor.h?rev=135338&r1=135337&r2=135338&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/DataExtractor.h (original)
+++ lldb/trunk/include/lldb/Core/DataExtractor.h Fri Jul 15 22:19:08 2011
@@ -54,6 +54,11 @@
TypeSLEB128 ///< Format output as SLEB128 numbers
} Type;
+ static void
+ DumpHexBytes (Stream *s,
+ const void *src,
+ size_t src_len,
+ lldb::addr_t base_addr = LLDB_INVALID_ADDRESS);
//------------------------------------------------------------------
/// Default constructor.
///
Added: lldb/trunk/include/lldb/Core/StreamBuffer.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/StreamBuffer.h?rev=135338&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Core/StreamBuffer.h (added)
+++ lldb/trunk/include/lldb/Core/StreamBuffer.h Fri Jul 15 22:19:08 2011
@@ -0,0 +1,83 @@
+//===-- StreamBuffer.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_StreamBuffer_h_
+#define liblldb_StreamBuffer_h_
+
+#include <stdio.h>
+#include <string>
+#include "llvm/ADT/SmallVector.h"
+#include "lldb/Core/Stream.h"
+
+namespace lldb_private {
+
+template <unsigned N>
+class StreamBuffer : public Stream
+{
+public:
+ StreamBuffer () :
+ Stream (0, 4, lldb::eByteOrderBig),
+ m_packet ()
+ {
+ }
+
+
+ StreamBuffer (uint32_t flags,
+ uint32_t addr_size,
+ lldb::ByteOrder byte_order) :
+ Stream (flags, addr_size, byte_order),
+ m_packet ()
+ {
+ }
+
+ virtual
+ ~StreamBuffer ()
+ {
+ }
+
+ virtual void
+ Flush ()
+ {
+ // Nothing to do when flushing a buffer based stream...
+ }
+
+ virtual int
+ Write (const void *s, size_t length)
+ {
+ if (s && length)
+ m_packet.append ((const char *)s, ((const char *)s) + length);
+ return length;
+ }
+
+ void
+ Clear()
+ {
+ m_packet.clear();
+ }
+
+ const char *
+ GetData () const
+ {
+ return m_packet.data();
+ }
+
+ size_t
+ GetSize() const
+ {
+ return m_packet.size();
+ }
+
+protected:
+ llvm::SmallVector<char, N> m_packet;
+
+};
+
+} // namespace lldb_private
+
+#endif // #ifndef liblldb_StreamBuffer_h_
Modified: lldb/trunk/include/lldb/Core/StreamString.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/StreamString.h?rev=135338&r1=135337&r2=135338&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/StreamString.h (original)
+++ lldb/trunk/include/lldb/Core/StreamString.h Fri Jul 15 22:19:08 2011
@@ -37,9 +37,6 @@
void
Clear();
- void
- Dump(FILE *f);
-
const char *
GetData () const;
Modified: lldb/trunk/include/lldb/lldb-forward.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward.h?rev=135338&r1=135337&r2=135338&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-forward.h (original)
+++ lldb/trunk/include/lldb/lldb-forward.h Fri Jul 15 22:19:08 2011
@@ -129,6 +129,7 @@
class StoppointCallbackContext;
class StoppointLocation;
class Stream;
+template <unsigned N> class StreamBuffer;
class StreamFile;
class StreamString;
class StringList;
Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=135338&r1=135337&r2=135338&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Fri Jul 15 22:19:08 2011
@@ -638,6 +638,7 @@
261B5A5311C3F2AD00AABD0A /* SharingPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SharingPtr.h; path = include/lldb/Utility/SharingPtr.h; sourceTree = "<group>"; };
26217930133BC8640083B112 /* lldb-private-types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-private-types.h"; path = "include/lldb/lldb-private-types.h"; sourceTree = "<group>"; };
26217932133BCB850083B112 /* lldb-private-enumerations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-private-enumerations.h"; path = "include/lldb/lldb-private-enumerations.h"; sourceTree = "<group>"; };
+ 2623096E13D0EFFB006381D9 /* StreamBuffer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StreamBuffer.h; path = include/lldb/Core/StreamBuffer.h; sourceTree = "<group>"; };
263664921140A4930075843B /* Debugger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = Debugger.cpp; path = source/Core/Debugger.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
263664941140A4C10075843B /* Debugger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = Debugger.h; path = include/lldb/Core/Debugger.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
26368A3B126B697600E8659F /* darwin-debug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "darwin-debug.cpp"; path = "tools/darwin-debug/darwin-debug.cpp"; sourceTree = "<group>"; };
@@ -2003,6 +2004,7 @@
26BC7E9110F1B85900F91463 /* Stream.cpp */,
9A4F35111368A54100823F52 /* StreamAsynchronousIO.h */,
9A4F350F1368A51A00823F52 /* StreamAsynchronousIO.cpp */,
+ 2623096E13D0EFFB006381D9 /* StreamBuffer.h */,
26BC7D7A10F1B77400F91463 /* StreamFile.h */,
26BC7E9210F1B85900F91463 /* StreamFile.cpp */,
26BC7D7B10F1B77400F91463 /* StreamString.h */,
Modified: lldb/trunk/source/Core/ConnectionFileDescriptor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ConnectionFileDescriptor.cpp?rev=135338&r1=135337&r2=135338&view=diff
==============================================================================
--- lldb/trunk/source/Core/ConnectionFileDescriptor.cpp (original)
+++ lldb/trunk/source/Core/ConnectionFileDescriptor.cpp Fri Jul 15 22:19:08 2011
@@ -38,33 +38,42 @@
ConnectionFileDescriptor::ConnectionFileDescriptor () :
Connection(),
m_fd (-1),
- m_is_socket (false),
+ m_fd_type (eFDTypeFile),
+ m_udp_sockaddr (),
+ m_udp_sockaddr_len (0),
m_should_close_fd (false),
m_socket_timeout_usec(0)
{
+ memset (&m_udp_sockaddr, 0, sizeof(m_udp_sockaddr));
+
lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT,
- "%p ConnectionFileDescriptor::ConnectionFileDescriptor ()",
- this);
+ "%p ConnectionFileDescriptor::ConnectionFileDescriptor ()",
+ this);
}
ConnectionFileDescriptor::ConnectionFileDescriptor (int fd, bool owns_fd) :
Connection(),
m_fd (fd),
- m_is_socket (false),
+ m_fd_type (eFDTypeFile),
+ m_udp_sockaddr (),
+ m_udp_sockaddr_len (0),
m_should_close_fd (owns_fd),
m_socket_timeout_usec(0)
{
+ memset (&m_udp_sockaddr, 0, sizeof(m_udp_sockaddr));
lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT,
- "%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = %i, owns_fd = %i)",
- this, fd, owns_fd);
+ "%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = %i, owns_fd = %i)",
+ this,
+ fd,
+ owns_fd);
}
ConnectionFileDescriptor::~ConnectionFileDescriptor ()
{
lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT,
- "%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()",
- this);
+ "%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()",
+ this);
Disconnect (NULL);
}
@@ -78,8 +87,9 @@
ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr)
{
lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION,
- "%p ConnectionFileDescriptor::Connect (url = '%s')",
- this, s);
+ "%p ConnectionFileDescriptor::Connect (url = '%s')",
+ this,
+ s);
if (s && s[0])
{
@@ -134,7 +144,9 @@
// Try and get a socket option from this file descriptor to
// see if this is a socket and set m_is_socket accordingly.
int resuse;
- m_is_socket = GetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, resuse) == 0;
+ bool is_socket = GetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, resuse) == 0;
+ if (is_socket)
+ m_fd_type = eFDTypeSocket;
m_should_close_fd = true;
return eConnectionStatusSuccess;
}
@@ -204,28 +216,40 @@
log->Printf ("%p ConnectionFileDescriptor::Read () ::read (fd = %i, dst = %p, dst_len = %zu)...",
this, m_fd, dst, dst_len);
- if (timeout_usec == UINT32_MAX)
- {
- if (m_is_socket && SetSocketReceiveTimeout (timeout_usec))
+ ssize_t bytes_read = 0;
+ struct sockaddr_storage from;
+ socklen_t from_len = sizeof(from);
+
+ switch (m_fd_type)
+ {
+ case eFDTypeFile: // Other FD requireing read/write
+ status = BytesAvailable (timeout_usec, error_ptr);
+ if (status == eConnectionStatusSuccess)
+ bytes_read = ::read (m_fd, dst, dst_len);
+ break;
+
+ case eFDTypeSocket: // Socket requiring send/recv
+ if (SetSocketReceiveTimeout (timeout_usec))
+ {
status = eConnectionStatusSuccess;
- }
- else
- {
- if (m_is_socket && SetSocketReceiveTimeout (timeout_usec))
+ bytes_read = ::recv (m_fd, dst, dst_len, 0);
+ }
+ break;
+
+ case eFDTypeSocketUDP: // Unconnected UDP socket requiring sendto/recvfrom
+ if (SetSocketReceiveTimeout (timeout_usec))
+ {
status = eConnectionStatusSuccess;
- else
- status = BytesAvailable (timeout_usec, error_ptr);
+ ::memset (&from, 0, sizeof(from));
+ bytes_read = ::recvfrom (m_fd, dst, dst_len, 0, (struct sockaddr *)&from, &from_len);
+ }
+ break;
}
+
if (status != eConnectionStatusSuccess)
return 0;
Error error;
- ssize_t bytes_read;
- if (m_is_socket)
- bytes_read = ::recv (m_fd, dst, dst_len, 0);
- else
- bytes_read = ::read (m_fd, dst, dst_len);
-
if (bytes_read == 0)
{
error.Clear(); // End-of-file. Do not automatically close; pass along for the end-of-file handlers.
@@ -319,10 +343,26 @@
ssize_t bytes_sent = 0;
- if (m_is_socket)
- bytes_sent = ::send (m_fd, src, src_len, 0);
- else
- bytes_sent = ::write (m_fd, src, src_len);
+ switch (m_fd_type)
+ {
+ case eFDTypeFile: // Other FD requireing read/write
+ bytes_sent = ::write (m_fd, src, src_len);
+ break;
+
+ case eFDTypeSocket: // Socket requiring send/recv
+ bytes_sent = ::send (m_fd, src, src_len, 0);
+ break;
+
+ case eFDTypeSocketUDP: // Unconnected UDP socket requiring sendto/recvfrom
+ assert (m_udp_sockaddr_len != 0);
+ bytes_sent = ::sendto (m_fd,
+ src,
+ src_len,
+ 0,
+ (struct sockaddr *)&m_udp_sockaddr,
+ m_udp_sockaddr_len);
+ break;
+ }
if (bytes_sent < 0)
error.SetErrorToErrno ();
@@ -331,12 +371,38 @@
if (log)
{
- if (m_is_socket)
- log->Printf ("%p ConnectionFileDescriptor::Write() ::send (socket = %i, src = %p, src_len = %zu, flags = 0) => %zi (error = %s)",
- this, m_fd, src, src_len, bytes_sent, error.AsCString());
- else
- log->Printf ("%p ConnectionFileDescriptor::Write() ::write (fd = %i, src = %p, src_len = %zu) => %zi (error = %s)",
- this, m_fd, src, src_len, bytes_sent, error.AsCString());
+ switch (m_fd_type)
+ {
+ case eFDTypeFile: // Other FD requireing read/write
+ log->Printf ("%p ConnectionFileDescriptor::Write() ::write (fd = %i, src = %p, src_len = %zu) => %zi (error = %s)",
+ this,
+ m_fd,
+ src,
+ src_len,
+ bytes_sent,
+ error.AsCString());
+ break;
+
+ case eFDTypeSocket: // Socket requiring send/recv
+ log->Printf ("%p ConnectionFileDescriptor::Write() ::send (socket = %i, src = %p, src_len = %zu, flags = 0) => %zi (error = %s)",
+ this,
+ m_fd,
+ src,
+ src_len,
+ bytes_sent,
+ error.AsCString());
+ break;
+
+ case eFDTypeSocketUDP: // Unconnected UDP socket requiring sendto/recvfrom
+ log->Printf ("%p ConnectionFileDescriptor::Write() ::sendto (socket = %i, src = %p, src_len = %zu, flags = 0) => %zi (error = %s)",
+ this,
+ m_fd,
+ src,
+ src_len,
+ bytes_sent,
+ error.AsCString());
+ break;
+ }
}
if (error_ptr)
@@ -477,7 +543,7 @@
}
fd = -1;
}
- m_is_socket = false;
+ m_fd_type = eFDTypeFile;
if (success)
return eConnectionStatusSuccess;
else
@@ -490,7 +556,7 @@
ConnectionStatus result = eConnectionStatusError;
struct sockaddr_un saddr_un;
- m_is_socket = true;
+ m_fd_type = eFDTypeSocket;
int listen_socket = ::socket (AF_UNIX, SOCK_STREAM, 0);
if (listen_socket == -1)
@@ -537,7 +603,7 @@
ConnectionFileDescriptor::NamedSocketConnect (const char *socket_name, Error *error_ptr)
{
Close (m_fd, NULL);
- m_is_socket = true;
+ m_fd_type = eFDTypeSocket;
// Open the socket that was passed in as an option
struct sockaddr_un saddr_un;
@@ -576,7 +642,7 @@
this, listen_port_num);
Close (m_fd, NULL);
- m_is_socket = true;
+ m_fd_type = eFDTypeSocket;
int listen_port = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listen_port == -1)
{
@@ -640,7 +706,7 @@
"%p ConnectionFileDescriptor::ConnectTCP (host/port = %s)",
this, host_and_port);
Close (m_fd, NULL);
- m_is_socket = true;
+ m_fd_type = eFDTypeSocket;
RegularExpression regex ("([^:]+):([0-9]+)");
if (regex.Execute (host_and_port, 2) == false)
@@ -730,7 +796,7 @@
"%p ConnectionFileDescriptor::ConnectUDP (host/port = %s)",
this, host_and_port);
Close (m_fd, NULL);
- m_is_socket = true;
+ m_fd_type = eFDTypeSocketUDP;
RegularExpression regex ("([^:]+):([0-9]+)");
if (regex.Execute (host_and_port, 2) == false)
@@ -839,20 +905,27 @@
bool
ConnectionFileDescriptor::SetSocketReceiveTimeout (uint32_t timeout_usec)
{
- if (m_is_socket)
+ switch (m_fd_type)
{
- // Check in case timeout for m_fd has already been set to this value
- if (timeout_usec == m_socket_timeout_usec)
- return true;
- //printf ("ConnectionFileDescriptor::SetSocketReceiveTimeout (timeout_usec = %u)\n", timeout_usec);
-
- struct timeval timeout;
- timeout.tv_sec = timeout_usec / TimeValue::MicroSecPerSec;
- timeout.tv_usec = timeout_usec % TimeValue::MicroSecPerSec;
- if (::setsockopt (m_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == 0)
+ case eFDTypeFile: // Other FD requireing read/write
+ break;
+
+ case eFDTypeSocket: // Socket requiring send/recv
+ case eFDTypeSocketUDP: // Unconnected UDP socket requiring sendto/recvfrom
{
- m_socket_timeout_usec = timeout_usec;
- return true;
+ // Check in case timeout for m_fd has already been set to this value
+ if (timeout_usec == m_socket_timeout_usec)
+ return true;
+ //printf ("ConnectionFileDescriptor::SetSocketReceiveTimeout (timeout_usec = %u)\n", timeout_usec);
+
+ struct timeval timeout;
+ timeout.tv_sec = timeout_usec / TimeValue::MicroSecPerSec;
+ timeout.tv_usec = timeout_usec % TimeValue::MicroSecPerSec;
+ if (::setsockopt (m_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == 0)
+ {
+ m_socket_timeout_usec = timeout_usec;
+ return true;
+ }
}
}
return false;
Modified: lldb/trunk/source/Core/DataExtractor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/DataExtractor.cpp?rev=135338&r1=135337&r2=135338&view=diff
==============================================================================
--- lldb/trunk/source/Core/DataExtractor.cpp (original)
+++ lldb/trunk/source/Core/DataExtractor.cpp Fri Jul 15 22:19:08 2011
@@ -1789,4 +1789,19 @@
}
}
-
+void
+DataExtractor::DumpHexBytes (Stream *s,
+ const void *src,
+ size_t src_len,
+ addr_t base_addr)
+{
+ DataExtractor data (src, src_len, eByteOrderLittle, 4);
+ data.Dump (s,
+ 0, // Offset into "src"
+ eFormatBytes, // Dump as hex bytes
+ 1, // Size of each item is 1 for single bytes
+ src_len, // Number of bytes
+ 32, // Num bytes per line
+ base_addr, // Base address
+ 0, 0); // Bitfield info
+}
Modified: lldb/trunk/source/Core/StreamString.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/StreamString.cpp?rev=135338&r1=135337&r2=135338&view=diff
==============================================================================
--- lldb/trunk/source/Core/StreamString.cpp (original)
+++ lldb/trunk/source/Core/StreamString.cpp Fri Jul 15 22:19:08 2011
@@ -47,14 +47,6 @@
m_packet.clear();
}
-void
-StreamString::Dump(FILE *f)
-{
- int size = GetSize();
- if (size > 0)
- fprintf(f, "%*.*s", size, size, m_packet.c_str());
-}
-
const char *
StreamString::GetData () const
{
Modified: 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=135338&r1=135337&r2=135338&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp (original)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp Fri Jul 15 22:19:08 2011
@@ -16,14 +16,13 @@
// C++ Includes
// Other libraries and framework includes
+#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
#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"
@@ -38,13 +37,19 @@
//----------------------------------------------------------------------
CommunicationKDP::CommunicationKDP (const char *comm_name) :
Communication(comm_name),
+ m_byte_order (eByteOrderLittle),
m_packet_timeout (1),
m_sequence_mutex (Mutex::eMutexTypeRecursive),
m_public_is_running (false),
m_private_is_running (false),
- m_session_key (0),
- m_request_sequence_id (0),
- m_exception_sequence_id (0)
+ m_session_key (0u),
+ m_request_sequence_id (0u),
+ m_exception_sequence_id (0u),
+ m_kdp_version_version (0u),
+ m_kdp_version_feature (0u),
+ m_kdp_hostinfo_cpu_mask (0u),
+ m_kdp_hostinfo_cpu_type (0u),
+ m_kdp_hostinfo_cpu_subtype (0u)
{
}
@@ -60,27 +65,61 @@
}
bool
-CommunicationKDP::SendRequestPacket (const StreamString &request_packet)
+CommunicationKDP::SendRequestPacket (const PacketStreamType &request_packet)
{
Mutex::Locker locker(m_sequence_mutex);
return SendRequestPacketNoLock (request_packet);
}
+#if 0
+typedef struct {
+ uint8_t request; // Either: CommandType | ePacketTypeRequest, or CommandType | ePacketTypeReply
+ uint8_t sequence;
+ uint16_t length; // Length of entire packet including this header
+ uint32_t key; // Session key
+} kdp_hdr_t;
+#endif
+
void
-CommunicationKDP::MakeRequestPacketHeader (RequestType request_type,
- StreamString &request_packet)
+CommunicationKDP::MakeRequestPacketHeader (CommandType request_type,
+ PacketStreamType &request_packet,
+ uint16_t request_length)
{
request_packet.Clear();
- request_packet.PutHex32 (request_type); // Set the request type
- request_packet.PutHex8 (ePacketTypeRequest); // Set the packet type
- request_packet.PutHex8 (++m_request_sequence_id); // Sequence number
- request_packet.PutHex16 (0); // Pad1 and Pad2 bytes
- request_packet.PutHex32 (m_session_key); // Session key
+ request_packet.PutHex8 (request_type | ePacketTypeRequest); // Set the request type
+ request_packet.PutHex8 (m_request_sequence_id++); // Sequence number
+ request_packet.PutHex16 (request_length); // Length of the packet including this header
+ request_packet.PutHex32 (m_session_key); // Session key
}
+bool
+CommunicationKDP::SendRequestAndGetReply (const CommandType command,
+ const uint8_t request_sequence_id,
+ const PacketStreamType &request_packet,
+ DataExtractor &reply_packet)
+{
+
+ Mutex::Locker locker(m_sequence_mutex);
+ if (SendRequestPacketNoLock(request_packet))
+ {
+ if (WaitForPacketWithTimeoutMicroSecondsNoLock (reply_packet, m_packet_timeout))
+ {
+ uint32_t offset = 0;
+ const uint8_t reply_command = reply_packet.GetU8 (&offset);
+ const uint8_t reply_sequence_id = reply_packet.GetU8 (&offset);
+ if ((reply_command & eCommandTypeMask) == command)
+ {
+ if (request_sequence_id == reply_sequence_id)
+ return true;
+ }
+ }
+ }
+ reply_packet.Clear();
+ return false;
+}
bool
-CommunicationKDP::SendRequestPacketNoLock (const StreamString &request_packet)
+CommunicationKDP::SendRequestPacketNoLock (const PacketStreamType &request_packet)
{
if (IsConnected())
{
@@ -90,22 +129,11 @@
LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
if (log)
{
- StreamString log_strm;
- DataExtractor data (packet_data,
- packet_size,
- request_packet.GetByteOrder(),
- request_packet.GetAddressByteSize());
- data.Dump (&log_strm,
- 0,
- eFormatBytes,
- 1,
- packet_size,
- 32, // Num bytes per line
- 0, // Base address
- 0,
- 0);
+ PacketStreamType log_strm;
+
+ DataExtractor::DumpHexBytes (&log_strm, packet_data, packet_size, 0);
- log->Printf("request packet: <%u>\n%s", packet_size, log_strm.GetString().c_str());
+ log->Printf("request packet: <%u>\n%s", packet_size, log_strm.GetData());
}
ConnectionStatus status = eConnectionStatusSuccess;
@@ -137,14 +165,14 @@
}
size_t
-CommunicationKDP::WaitForPacketWithTimeoutMicroSeconds (StringExtractor &packet, uint32_t timeout_usec)
+CommunicationKDP::WaitForPacketWithTimeoutMicroSeconds (DataExtractor &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)
+CommunicationKDP::WaitForPacketWithTimeoutMicroSecondsNoLock (DataExtractor &packet, uint32_t timeout_usec)
{
uint8_t buffer[8192];
Error error;
@@ -153,7 +181,7 @@
// Check for a packet from our cache first without trying any reading...
if (CheckForPacket (NULL, 0, packet))
- return packet.GetStringRef().size();
+ return packet.GetByteSize();
bool timed_out = false;
while (IsConnected() && !timed_out)
@@ -172,7 +200,7 @@
if (bytes_read > 0)
{
if (CheckForPacket (buffer, bytes_read, packet))
- return packet.GetStringRef().size();
+ return packet.GetByteSize();
}
else
{
@@ -199,7 +227,7 @@
}
bool
-CommunicationKDP::CheckForPacket (const uint8_t *src, size_t src_len, StringExtractor &packet)
+CommunicationKDP::CheckForPacket (const uint8_t *src, size_t src_len, DataExtractor &packet)
{
// Put the packet data into the buffer in a thread safe fashion
Mutex::Locker locker(m_bytes_mutex);
@@ -210,43 +238,229 @@
{
if (log && log->GetVerbose())
{
- StreamString s;
- log->Printf ("CommunicationKDP::%s adding %u bytes: %.*s",
+ PacketStreamType log_strm;
+ DataExtractor::DumpHexBytes (&log_strm, src, src_len, 0);
+ log->Printf ("CommunicationKDP::%s adding %u bytes: %s",
__FUNCTION__,
(uint32_t)src_len,
- (uint32_t)src_len,
- src);
+ log_strm.GetData());
}
m_bytes.append ((const char *)src, src_len);
}
- // Parse up the packets into gdb remote packets
- if (!m_bytes.empty())
+ // Make sure we at least have enough bytes for a packet header
+ const size_t bytes_available = m_bytes.size();
+ if (bytes_available >= 8)
{
- // TODO: Figure out if we have a full packet reply
+ packet.SetData (&m_bytes[0], bytes_available, m_byte_order);
+ uint32_t offset = 0;
+ uint8_t reply_command = packet.GetU8(&offset);
+ switch (reply_command)
+ {
+ case ePacketTypeReply | eCommandTypeConnect:
+ case ePacketTypeReply | eCommandTypeDisconnect:
+ case ePacketTypeReply | eCommandTypeHostInfo:
+ case ePacketTypeReply | eCommandTypeVersion:
+ case ePacketTypeReply | eCommandTypeMaxBytes:
+ case ePacketTypeReply | eCommandTypeReadMemory:
+ case ePacketTypeReply | eCommandTypeWriteMemory:
+ case ePacketTypeReply | eCommandTypeReadRegisters:
+ case ePacketTypeReply | eCommandTypeWriteRegisters:
+ case ePacketTypeReply | eCommandTypeLoad:
+ case ePacketTypeReply | eCommandTypeImagePath:
+ case ePacketTypeReply | eCommandTypeSuspend:
+ case ePacketTypeReply | eCommandTypeResume:
+ case ePacketTypeReply | eCommandTypeException:
+ case ePacketTypeReply | eCommandTypeTermination:
+ case ePacketTypeReply | eCommandTypeBreakpointSet:
+ case ePacketTypeReply | eCommandTypeBreakpointRemove:
+ case ePacketTypeReply | eCommandTypeRegions:
+ case ePacketTypeReply | eCommandTypeReattach:
+ case ePacketTypeReply | eCommandTypeHostReboot:
+ case ePacketTypeReply | eCommandTypeReadMemory64:
+ case ePacketTypeReply | eCommandTypeWriteMemory64:
+ case ePacketTypeReply | eCommandTypeBreakpointSet64:
+ case ePacketTypeReply | eCommandTypeBreakpointRemove64:
+ case ePacketTypeReply | eCommandTypeKernelVersion:
+ {
+ offset = 2;
+ const uint16_t length = packet.GetU16 (&offset);
+ if (length <= bytes_available)
+ {
+ // We have an entire packet ready, we need to copy the data
+ // bytes into a buffer that will be owned by the packet and
+ // erase the bytes from our communcation buffer "m_bytes"
+ packet.SetData (DataBufferSP (new DataBufferHeap (&m_bytes[0], length)));
+ m_bytes.erase (0, length);
+ return true;
+ }
+ }
+ break;
+
+ default:
+ // Unrecognized reply command byte, erase this byte and try to get back on track
+ if (log)
+ log->Printf ("CommunicationKDP::%s: tossing junk byte: 0x%2.2x",
+ __FUNCTION__,
+ (uint8_t)m_bytes[0]);
+ m_bytes.erase(0, 1);
+ break;
+ }
}
packet.Clear();
return false;
}
-CommunicationKDP::ErrorType
+bool
CommunicationKDP::Connect (uint16_t reply_port,
uint16_t exc_port,
const char *greeting)
{
- StreamString request_packet (Stream::eBinary, 4, eByteOrderLittle);
- MakeRequestPacketHeader (eRequestTypeConnect, request_packet);
+ PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order);
+ if (greeting == NULL)
+ greeting = "";
+
+ const CommandType command = eCommandTypeConnect;
+ // Length is 82 uint16_t and the length of the greeting C string
+ const uint32_t command_length = 8 + 2 + 2 + ::strlen(greeting);
+ const uint32_t request_sequence_id = m_request_sequence_id;
+ MakeRequestPacketHeader (command, request_packet, command_length);
request_packet.PutHex16(reply_port);
request_packet.PutHex16(exc_port);
request_packet.PutCString(greeting);
-
- return eErrorUnimplemented;
+ DataExtractor reply_packet;
+ return SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet);
+}
+
+void
+CommunicationKDP::ClearKDPSettings ()
+{
+ m_request_sequence_id = 0;
+ m_kdp_version_version = 0;
+ m_kdp_version_feature = 0;
+ m_kdp_hostinfo_cpu_mask = 0;
+ m_kdp_hostinfo_cpu_type = 0;
+ m_kdp_hostinfo_cpu_subtype = 0;
+}
+
+bool
+CommunicationKDP::Reattach (uint16_t reply_port)
+{
+ PacketStreamType request_packet (Stream::eBinary, 4, 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;
+ const uint32_t request_sequence_id = m_request_sequence_id;
+ MakeRequestPacketHeader (command, request_packet, command_length);
+ request_packet.PutHex16(reply_port);
+ DataExtractor reply_packet;
+ if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+ {
+ // Reset the sequence ID to zero for reattach
+ ClearKDPSettings ();
+ uint32_t offset = 4;
+ m_session_key = reply_packet.GetU32 (&offset);
+ return true;
+ }
+ return false;
}
-CommunicationKDP::ErrorType
+uint32_t
+CommunicationKDP::GetVersion ()
+{
+ if (!VersionIsValid())
+ SendRequestVersion();
+ return m_kdp_version_version;
+}
+
+uint32_t
+CommunicationKDP::GetFeatureFlags ()
+{
+ if (!VersionIsValid())
+ SendRequestVersion();
+ return m_kdp_version_feature;
+}
+
+bool
+CommunicationKDP::SendRequestVersion ()
+{
+ PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order);
+ const CommandType command = eCommandTypeVersion;
+ 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))
+ {
+ // Reset the sequence ID to zero for reattach
+ uint32_t offset = 8;
+ m_kdp_version_version = reply_packet.GetU32 (&offset);
+ m_kdp_version_feature = reply_packet.GetU32 (&offset);
+ return true;
+ }
+ return false;
+}
+
+uint32_t
+CommunicationKDP::GetCPUMask ()
+{
+ if (!HostInfoIsValid())
+ SendRequestHostInfo();
+ return m_kdp_hostinfo_cpu_mask;
+}
+
+uint32_t
+CommunicationKDP::GetCPUType ()
+{
+ if (!HostInfoIsValid())
+ SendRequestHostInfo();
+ return m_kdp_hostinfo_cpu_type;
+}
+
+uint32_t
+CommunicationKDP::GetCPUSubtype ()
+{
+ if (!HostInfoIsValid())
+ SendRequestHostInfo();
+ return m_kdp_hostinfo_cpu_subtype;
+}
+
+bool
+CommunicationKDP::SendRequestHostInfo ()
+{
+ PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order);
+ const CommandType command = eCommandTypeHostInfo;
+ 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))
+ {
+ // 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);
+ return true;
+ }
+ return false;
+}
+
+bool
CommunicationKDP::Disconnect ()
{
- return eErrorUnimplemented;
+ PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order);
+ const CommandType command = eCommandTypeDisconnect;
+ 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))
+ {
+ // Are we supposed to get a reply for disconnect?
+ }
+ ClearKDPSettings ();
+ return true;
}
Modified: 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=135338&r1=135337&r2=135338&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h (original)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h Fri Jul 15 22:19:08 2011
@@ -20,12 +20,11 @@
#include "lldb/lldb-private.h"
#include "lldb/Core/Communication.h"
#include "lldb/Core/Listener.h"
+#include "lldb/Core/StreamBuffer.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:
@@ -36,49 +35,50 @@
const static uint32_t kMaxPacketSize = 1200;
const static uint32_t kMaxDataSize = 1024;
-
+ typedef lldb_private::StreamBuffer<1024> PacketStreamType;
typedef enum
{
- eRequestTypeConnect = 0u,
- eRequestTypeDisconnect,
- eRequestTypeHostInfo,
- eRequestTypeVersion,
- eRequestTypeMaxBytes,
- eRequestTypeReadMemory,
- eRequestTypeWriteMemory,
- eRequestTypeReadRegisters,
- eRequestTypeWriteRegisters,
- eRequestTypeLoad,
- eRequestTypeImagePath,
- eRequestTypeSuspend,
- eRequestTypeResume,
- eRequestTypeException,
- eRequestTypeTermination,
- eRequestTypeBreakpointSet,
- eRequestTypeBreakpointRemove,
- eRequestTypeRegions,
- eRequestTypeReattach,
- eRequestTypeHostReboot,
- eRequestTypeReadMemory64,
- eRequestTypeWriteMemory64,
- eRequestTypeBreakpointSet64,
- eRequestTypeBreakpointRemove64,
- eRequestTypeKernelVersion
- } RequestType;
+ eCommandTypeConnect = 0u,
+ eCommandTypeDisconnect,
+ eCommandTypeHostInfo,
+ eCommandTypeVersion,
+ eCommandTypeMaxBytes,
+ eCommandTypeReadMemory,
+ eCommandTypeWriteMemory,
+ eCommandTypeReadRegisters,
+ eCommandTypeWriteRegisters,
+ eCommandTypeLoad,
+ eCommandTypeImagePath,
+ eCommandTypeSuspend,
+ eCommandTypeResume,
+ eCommandTypeException,
+ eCommandTypeTermination,
+ eCommandTypeBreakpointSet,
+ eCommandTypeBreakpointRemove,
+ eCommandTypeRegions,
+ eCommandTypeReattach,
+ eCommandTypeHostReboot,
+ eCommandTypeReadMemory64,
+ eCommandTypeWriteMemory64,
+ eCommandTypeBreakpointSet64,
+ eCommandTypeBreakpointRemove64,
+ eCommandTypeKernelVersion
+ } CommandType;
- typedef enum
+ typedef enum
{
- eErrorSuccess = 0,
- eErrorAlreadyConnected,
- eErrorPacketToBig,
- eErrorInvalidRegisterFlavor,
- eErrorUnimplemented
- } ErrorType;
+ KDP_PROTERR_SUCCESS = 0,
+ KDP_PROTERR_ALREADY_CONNECTED,
+ KDP_PROTERR_BAD_NBYTES,
+ KDP_PROTERR_BADFLAVOR
+ } KDPError;
typedef enum
{
- ePacketTypeRequest = 0u,
- ePacketTypeReply = 1u
+ ePacketTypeRequest = 0x00u,
+ ePacketTypeReply = 0x80u,
+ ePacketTypeMask = 0x80u,
+ eCommandTypeMask = 0x7fu
} PacketType;
//------------------------------------------------------------------
// Constructors and Destructors
@@ -89,11 +89,11 @@
~CommunicationKDP();
bool
- SendRequestPacket (const lldb_private::StreamString &request_packet);
+ SendRequestPacket (const PacketStreamType &request_packet);
// Wait for a packet within 'nsec' seconds
size_t
- WaitForPacketWithTimeoutMicroSeconds (StringExtractor &response,
+ WaitForPacketWithTimeoutMicroSeconds (lldb_private::DataExtractor &response,
uint32_t usec);
bool
@@ -102,7 +102,7 @@
bool
CheckForPacket (const uint8_t *src,
size_t src_len,
- StringExtractor &packet);
+ lldb_private::DataExtractor &packet);
bool
IsRunning() const
{
@@ -140,34 +140,81 @@
lldb_private::ProcessLaunchInfo &launch_info);
- ErrorType
+ bool
Connect (uint16_t reply_port,
uint16_t exc_port,
const char *greeting);
- ErrorType
+ bool
+ Reattach (uint16_t reply_port);
+
+ bool
Disconnect ();
+
+ uint32_t
+ GetVersion ();
+
+ uint32_t
+ GetFeatureFlags ();
+
+ uint32_t
+ GetCPUMask ();
+
+ uint32_t
+ GetCPUType ();
+
+ uint32_t
+ GetCPUSubtype ();
protected:
typedef std::list<std::string> packet_collection;
bool
- SendRequestPacketNoLock (const lldb_private::StreamString &request_packet);
+ SendRequestPacketNoLock (const PacketStreamType &request_packet);
size_t
- WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractor &response,
+ WaitForPacketWithTimeoutMicroSecondsNoLock (lldb_private::DataExtractor &response,
uint32_t timeout_usec);
bool
WaitForNotRunningPrivate (const lldb_private::TimeValue *timeout_ptr);
void
- MakeRequestPacketHeader (RequestType request_type,
- lldb_private::StreamString &request_packet);
+ MakeRequestPacketHeader (CommandType request_type,
+ PacketStreamType &request_packet,
+ uint16_t request_length);
+ bool
+ SendRequestVersion ();
+
+
+ bool
+ VersionIsValid() const
+ {
+ return m_kdp_version_version != 0;
+ }
+
+ bool
+ HostInfoIsValid() const
+ {
+ return m_kdp_hostinfo_cpu_type != 0;
+ }
+
+ bool
+ SendRequestHostInfo ();
+
+ void
+ ClearKDPSettings ();
+
+ bool
+ SendRequestAndGetReply (const CommandType command,
+ const uint8_t request_sequence_id,
+ const PacketStreamType &request_packet,
+ lldb_private::DataExtractor &reply_packet);
//------------------------------------------------------------------
// Classes that inherit from CommunicationKDP can see and modify these
//------------------------------------------------------------------
+ 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
lldb_private::Predicate<bool> m_public_is_running;
@@ -175,6 +222,11 @@
uint32_t m_session_key;
uint8_t m_request_sequence_id;
uint8_t m_exception_sequence_id;
+ uint32_t m_kdp_version_version;
+ uint32_t m_kdp_version_feature;
+ uint32_t m_kdp_hostinfo_cpu_mask;
+ uint32_t m_kdp_hostinfo_cpu_type;
+ uint32_t m_kdp_hostinfo_cpu_subtype;
private:
//------------------------------------------------------------------
// For CommunicationKDP only
Modified: 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=135338&r1=135337&r2=135338&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp (original)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp Fri Jul 15 22:19:08 2011
@@ -63,7 +63,6 @@
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)
More information about the lldb-commits
mailing list