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.
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@135338 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
index 2287e40..06096af 100644
--- a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
+++ b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
@@ -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;
- log->Printf("request packet: <%u>\n%s", packet_size, log_strm.GetString().c_str());
+ DataExtractor::DumpHexBytes (&log_strm, packet_data, packet_size, 0);
+
+ 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);
}
-CommunicationKDP::ErrorType
+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;
+}
+
+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;
}
diff --git a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h
index c0c7b08..4445608 100644
--- a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h
+++ b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h
@@ -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
diff --git a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
index 9e199c1..1e3158d 100644
--- a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
+++ b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
@@ -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)