reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
  213
  214
  215
  216
  217
  218
  219
  220
  221
  222
  223
  224
  225
  226
  227
  228
  229
  230
  231
  232
  233
  234
  235
  236
  237
  238
  239
  240
  241
  242
  243
  244
  245
  246
  247
//===-- CommunicationKDP.h --------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_CommunicationKDP_h_
#define liblldb_CommunicationKDP_h_

#include <list>
#include <mutex>
#include <string>

#include "lldb/Core/Communication.h"
#include "lldb/Core/StreamBuffer.h"
#include "lldb/Utility/Listener.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;
  enum CommandType {
    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
  };

  enum { KDP_FEATURE_BP = (1u << 0) };

  enum KDPError {
    KDP_PROTERR_SUCCESS = 0,
    KDP_PROTERR_ALREADY_CONNECTED,
    KDP_PROTERR_BAD_NBYTES,
    KDP_PROTERR_BADFLAVOR
  };

  enum PacketType {
    ePacketTypeRequest = 0x00u,
    ePacketTypeReply = 0x80u,
    ePacketTypeMask = 0x80u,
    eCommandTypeMask = 0x7fu
  };
  // 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_