forked from OSchip/llvm-project
265 lines
8.4 KiB
C++
265 lines
8.4 KiB
C++
//===-- CommunicationKDP.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_CommunicationKDP_h_
|
|
#define liblldb_CommunicationKDP_h_
|
|
|
|
// C Includes
|
|
// C++ Includes
|
|
#include <list>
|
|
#include <mutex>
|
|
#include <string>
|
|
|
|
// Other libraries and framework includes
|
|
// Project includes
|
|
#include "lldb/Core/Communication.h"
|
|
#include "lldb/Core/Listener.h"
|
|
#include "lldb/Core/StreamBuffer.h"
|
|
#include "lldb/Utility/Predicate.h"
|
|
#include "lldb/lldb-private.h"
|
|
|
|
class CommunicationKDP : public lldb_private::Communication {
|
|
public:
|
|
enum { eBroadcastBitRunPacketSent = kLoUserBroadcastBit };
|
|
|
|
const static uint32_t kMaxPacketSize = 1200;
|
|
const static uint32_t kMaxDataSize = 1024;
|
|
typedef lldb_private::StreamBuffer<1024> PacketStreamType;
|
|
typedef enum {
|
|
KDP_CONNECT = 0u,
|
|
KDP_DISCONNECT,
|
|
KDP_HOSTINFO,
|
|
KDP_VERSION,
|
|
KDP_MAXBYTES,
|
|
KDP_READMEM,
|
|
KDP_WRITEMEM,
|
|
KDP_READREGS,
|
|
KDP_WRITEREGS,
|
|
KDP_LOAD,
|
|
KDP_IMAGEPATH,
|
|
KDP_SUSPEND,
|
|
KDP_RESUMECPUS,
|
|
KDP_EXCEPTION,
|
|
KDP_TERMINATION,
|
|
KDP_BREAKPOINT_SET,
|
|
KDP_BREAKPOINT_REMOVE,
|
|
KDP_REGIONS,
|
|
KDP_REATTACH,
|
|
KDP_HOSTREBOOT,
|
|
KDP_READMEM64,
|
|
KDP_WRITEMEM64,
|
|
KDP_BREAKPOINT_SET64,
|
|
KDP_BREAKPOINT_REMOVE64,
|
|
KDP_KERNELVERSION,
|
|
KDP_READPHYSMEM64,
|
|
KDP_WRITEPHYSMEM64,
|
|
KDP_READIOPORT,
|
|
KDP_WRITEIOPORT,
|
|
KDP_READMSR64,
|
|
KDP_WRITEMSR64,
|
|
KDP_DUMPINFO
|
|
} CommandType;
|
|
|
|
enum { KDP_FEATURE_BP = (1u << 0) };
|
|
|
|
typedef enum {
|
|
KDP_PROTERR_SUCCESS = 0,
|
|
KDP_PROTERR_ALREADY_CONNECTED,
|
|
KDP_PROTERR_BAD_NBYTES,
|
|
KDP_PROTERR_BADFLAVOR
|
|
} KDPError;
|
|
|
|
typedef enum {
|
|
ePacketTypeRequest = 0x00u,
|
|
ePacketTypeReply = 0x80u,
|
|
ePacketTypeMask = 0x80u,
|
|
eCommandTypeMask = 0x7fu
|
|
} PacketType;
|
|
//------------------------------------------------------------------
|
|
// Constructors and Destructors
|
|
//------------------------------------------------------------------
|
|
CommunicationKDP(const char *comm_name);
|
|
|
|
virtual ~CommunicationKDP();
|
|
|
|
bool SendRequestPacket(const PacketStreamType &request_packet);
|
|
|
|
// Wait for a packet within 'nsec' seconds
|
|
size_t
|
|
WaitForPacketWithTimeoutMicroSeconds(lldb_private::DataExtractor &response,
|
|
uint32_t usec);
|
|
|
|
bool GetSequenceMutex(std::unique_lock<std::recursive_mutex> &lock);
|
|
|
|
bool CheckForPacket(const uint8_t *src, size_t src_len,
|
|
lldb_private::DataExtractor &packet);
|
|
bool IsRunning() const { return m_is_running.GetValue(); }
|
|
|
|
//------------------------------------------------------------------
|
|
// Set the global packet timeout.
|
|
//
|
|
// For clients, this is the timeout that gets used when sending
|
|
// packets and waiting for responses. For servers, this might not
|
|
// get used, and if it doesn't this should be moved to the
|
|
// CommunicationKDPClient.
|
|
//------------------------------------------------------------------
|
|
std::chrono::seconds SetPacketTimeout(std::chrono::seconds packet_timeout) {
|
|
const auto old_packet_timeout = m_packet_timeout;
|
|
m_packet_timeout = packet_timeout;
|
|
return old_packet_timeout;
|
|
}
|
|
|
|
std::chrono::seconds GetPacketTimeout() const { return m_packet_timeout; }
|
|
|
|
//------------------------------------------------------------------
|
|
// Public Request Packets
|
|
//------------------------------------------------------------------
|
|
bool SendRequestConnect(uint16_t reply_port, uint16_t exc_port,
|
|
const char *greeting);
|
|
|
|
bool SendRequestReattach(uint16_t reply_port);
|
|
|
|
bool SendRequestDisconnect();
|
|
|
|
uint32_t SendRequestReadMemory(lldb::addr_t addr, void *dst,
|
|
uint32_t dst_size,
|
|
lldb_private::Status &error);
|
|
|
|
uint32_t SendRequestWriteMemory(lldb::addr_t addr, const void *src,
|
|
uint32_t src_len,
|
|
lldb_private::Status &error);
|
|
|
|
bool SendRawRequest(uint8_t command_byte, const void *src, uint32_t src_len,
|
|
lldb_private::DataExtractor &reply,
|
|
lldb_private::Status &error);
|
|
|
|
uint32_t SendRequestReadRegisters(uint32_t cpu, uint32_t flavor, void *dst,
|
|
uint32_t dst_size,
|
|
lldb_private::Status &error);
|
|
|
|
uint32_t SendRequestWriteRegisters(uint32_t cpu, uint32_t flavor,
|
|
const void *src, uint32_t src_size,
|
|
lldb_private::Status &error);
|
|
|
|
const char *GetKernelVersion();
|
|
|
|
// Disable KDP_IMAGEPATH for now, it seems to hang the KDP connection...
|
|
// const char *
|
|
// GetImagePath ();
|
|
|
|
uint32_t GetVersion();
|
|
|
|
uint32_t GetFeatureFlags();
|
|
|
|
bool LocalBreakpointsAreSupported() {
|
|
return (GetFeatureFlags() & KDP_FEATURE_BP) != 0;
|
|
}
|
|
|
|
uint32_t GetCPUMask();
|
|
|
|
uint32_t GetCPUType();
|
|
|
|
uint32_t GetCPUSubtype();
|
|
|
|
lldb_private::UUID GetUUID();
|
|
|
|
bool RemoteIsEFI();
|
|
|
|
bool RemoteIsDarwinKernel();
|
|
|
|
lldb::addr_t GetLoadAddress();
|
|
|
|
bool SendRequestResume();
|
|
|
|
bool SendRequestSuspend();
|
|
|
|
bool SendRequestBreakpoint(bool set, lldb::addr_t addr);
|
|
|
|
protected:
|
|
bool SendRequestPacketNoLock(const PacketStreamType &request_packet);
|
|
|
|
size_t WaitForPacketWithTimeoutMicroSecondsNoLock(
|
|
lldb_private::DataExtractor &response, uint32_t timeout_usec);
|
|
|
|
bool WaitForNotRunningPrivate(const std::chrono::microseconds &timeout);
|
|
|
|
void MakeRequestPacketHeader(CommandType request_type,
|
|
PacketStreamType &request_packet,
|
|
uint16_t request_length);
|
|
|
|
//------------------------------------------------------------------
|
|
// Protected Request Packets (use public accessors which will cache
|
|
// results.
|
|
//------------------------------------------------------------------
|
|
bool SendRequestVersion();
|
|
|
|
bool SendRequestHostInfo();
|
|
|
|
bool SendRequestKernelVersion();
|
|
|
|
// Disable KDP_IMAGEPATH for now, it seems to hang the KDP connection...
|
|
// bool
|
|
// SendRequestImagePath ();
|
|
|
|
void DumpPacket(lldb_private::Stream &s, const void *data, uint32_t data_len);
|
|
|
|
void DumpPacket(lldb_private::Stream &s,
|
|
const lldb_private::DataExtractor &extractor);
|
|
|
|
bool VersionIsValid() const { return m_kdp_version_version != 0; }
|
|
|
|
bool HostInfoIsValid() const { return m_kdp_hostinfo_cpu_type != 0; }
|
|
|
|
bool ExtractIsReply(uint8_t first_packet_byte) const {
|
|
// TODO: handle big endian...
|
|
return (first_packet_byte & ePacketTypeMask) != 0;
|
|
}
|
|
|
|
CommandType ExtractCommand(uint8_t first_packet_byte) const {
|
|
// TODO: handle big endian...
|
|
return (CommandType)(first_packet_byte & eCommandTypeMask);
|
|
}
|
|
|
|
static const char *GetCommandAsCString(uint8_t command);
|
|
|
|
void ClearKDPSettings();
|
|
|
|
bool SendRequestAndGetReply(const CommandType command,
|
|
const PacketStreamType &request_packet,
|
|
lldb_private::DataExtractor &reply_packet);
|
|
//------------------------------------------------------------------
|
|
// Classes that inherit from CommunicationKDP can see and modify these
|
|
//------------------------------------------------------------------
|
|
uint32_t m_addr_byte_size;
|
|
lldb::ByteOrder m_byte_order;
|
|
std::chrono::seconds m_packet_timeout;
|
|
std::recursive_mutex m_sequence_mutex; // Restrict access to sending/receiving
|
|
// packets to a single thread at a time
|
|
lldb_private::Predicate<bool> m_is_running;
|
|
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;
|
|
std::string m_kernel_version;
|
|
// std::string m_image_path; // Disable KDP_IMAGEPATH for now, it seems to
|
|
// hang the KDP connection...
|
|
lldb::addr_t m_last_read_memory_addr; // Last memory read address for logging
|
|
private:
|
|
//------------------------------------------------------------------
|
|
// For CommunicationKDP only
|
|
//------------------------------------------------------------------
|
|
DISALLOW_COPY_AND_ASSIGN(CommunicationKDP);
|
|
};
|
|
|
|
#endif // liblldb_CommunicationKDP_h_
|