brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.4 KiB · 35bf5eb Raw
217 lines · c
1//===-- GDBRemoteCommunication.h --------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATION_H10#define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATION_H11 12#include "GDBRemoteCommunicationHistory.h"13#include "lldb/Core/Communication.h"14#include "lldb/Host/Config.h"15#include "lldb/Host/Socket.h"16#include "lldb/Utility/Args.h"17#include "lldb/Utility/StringExtractorGDBRemote.h"18#include <mutex>19#include <string>20 21namespace lldb_private {22namespace process_gdb_remote {23 24enum GDBStoppointType {25  eStoppointInvalid = -1,26  eBreakpointSoftware = 0,27  eBreakpointHardware,28  eWatchpointWrite,29  eWatchpointRead,30  eWatchpointReadWrite31};32 33enum class CompressionType {34  None = 0,    // no compression35  ZlibDeflate, // zlib's deflate compression scheme, requires zlib or Apple's36               // libcompression37  LZFSE,       // an Apple compression scheme, requires Apple's libcompression38  LZ4, // lz compression - called "lz4 raw" in libcompression terms, compat with39       // https://code.google.com/p/lz4/40  LZMA, // Lempel–Ziv–Markov chain algorithm41};42 43// Data included in the vFile:fstat packet.44// https://sourceware.org/gdb/onlinedocs/gdb/struct-stat.html#struct-stat45struct GDBRemoteFStatData {46  llvm::support::ubig32_t gdb_st_dev;47  llvm::support::ubig32_t gdb_st_ino;48  llvm::support::ubig32_t gdb_st_mode;49  llvm::support::ubig32_t gdb_st_nlink;50  llvm::support::ubig32_t gdb_st_uid;51  llvm::support::ubig32_t gdb_st_gid;52  llvm::support::ubig32_t gdb_st_rdev;53  llvm::support::ubig64_t gdb_st_size;54  llvm::support::ubig64_t gdb_st_blksize;55  llvm::support::ubig64_t gdb_st_blocks;56  llvm::support::ubig32_t gdb_st_atime;57  llvm::support::ubig32_t gdb_st_mtime;58  llvm::support::ubig32_t gdb_st_ctime;59};60static_assert(sizeof(GDBRemoteFStatData) == 64,61              "size of GDBRemoteFStatData is not 64");62 63enum GDBErrno {64#define HANDLE_ERRNO(name, value) GDB_##name = value,65#include "Plugins/Process/gdb-remote/GDBRemoteErrno.def"66  GDB_EUNKNOWN = 999967};68 69class ProcessGDBRemote;70 71class GDBRemoteCommunication : public Communication {72public:73  enum class PacketType { Invalid = 0, Standard, Notify };74 75  enum class PacketResult {76    Success = 0,        // Success77    ErrorSendFailed,    // Status sending the packet78    ErrorSendAck,       // Didn't get an ack back after sending a packet79    ErrorReplyFailed,   // Status getting the reply80    ErrorReplyTimeout,  // Timed out waiting for reply81    ErrorReplyInvalid,  // Got a reply but it wasn't valid for the packet that82                        // was sent83    ErrorReplyAck,      // Sending reply ack failed84    ErrorDisconnected,  // We were disconnected85    ErrorNoSequenceLock // We couldn't get the sequence lock for a multi-packet86                        // request87  };88 89  // Class to change the timeout for a given scope and restore it to the90  // original value when the91  // created ScopedTimeout object got out of scope92  class ScopedTimeout {93  public:94    ScopedTimeout(GDBRemoteCommunication &gdb_comm,95                  std::chrono::seconds timeout);96    ~ScopedTimeout();97 98  private:99    GDBRemoteCommunication &m_gdb_comm;100    std::chrono::seconds m_saved_timeout;101    // Don't ever reduce the timeout for a packet, only increase it. If the102    // requested timeout if less than the current timeout, we don't set it103    // and won't need to restore it.104    bool m_timeout_modified;105  };106 107  GDBRemoteCommunication();108 109  ~GDBRemoteCommunication() override;110 111  PacketResult GetAck();112 113  size_t SendAck();114 115  size_t SendNack();116 117  char CalculcateChecksum(llvm::StringRef payload);118 119  PacketType CheckForPacket(const uint8_t *src, size_t src_len,120                            StringExtractorGDBRemote &packet);121 122  bool GetSendAcks() { return m_send_acks; }123 124  // Set the global packet timeout.125  //126  // For clients, this is the timeout that gets used when sending127  // packets and waiting for responses. For servers, this is used when waiting128  // for ACKs.129  std::chrono::seconds SetPacketTimeout(std::chrono::seconds packet_timeout) {130    const auto old_packet_timeout = m_packet_timeout;131    m_packet_timeout = packet_timeout;132    return old_packet_timeout;133  }134 135  std::chrono::seconds GetPacketTimeout() const { return m_packet_timeout; }136 137  // Start a debugserver instance on the current host using the138  // supplied connection URL.139  static Status140  StartDebugserverProcess(std::variant<llvm::StringRef, shared_fd_t> comm,141                          ProcessLaunchInfo &launch_info,142                          const Args *inferior_args);143 144  void DumpHistory(Stream &strm);145 146  /// Expand GDB run-length encoding.147  static std::optional<std::string> ExpandRLE(std::string);148 149protected:150  std::chrono::seconds m_packet_timeout;151  uint32_t m_echo_number;152  LazyBool m_supports_qEcho;153  GDBRemoteCommunicationHistory m_history;154  bool m_send_acks;155  bool m_is_platform; // Set to true if this class represents a platform,156                      // false if this class represents a debug session for157                      // a single process158 159  std::string m_bytes;160  std::recursive_mutex m_bytes_mutex;161  CompressionType m_compression_type;162 163  PacketResult SendPacketNoLock(llvm::StringRef payload);164  PacketResult SendNotificationPacketNoLock(llvm::StringRef notify_type,165                                            std::deque<std::string>& queue,166                                            llvm::StringRef payload);167  PacketResult SendRawPacketNoLock(llvm::StringRef payload,168                                   bool skip_ack = false);169 170  PacketResult ReadPacket(StringExtractorGDBRemote &response,171                          Timeout<std::micro> timeout, bool sync_on_timeout);172 173  PacketResult WaitForPacketNoLock(StringExtractorGDBRemote &response,174                                   Timeout<std::micro> timeout,175                                   bool sync_on_timeout);176 177  bool CompressionIsEnabled() {178    return m_compression_type != CompressionType::None;179  }180 181  // If compression is enabled, decompress the packet in m_bytes and update182  // m_bytes with the uncompressed version.183  // Returns 'true' packet was decompressed and m_bytes is the now-decompressed184  // text.185  // Returns 'false' if unable to decompress or if the checksum was invalid.186  //187  // NB: Once the packet has been decompressed, checksum cannot be computed188  // based189  // on m_bytes.  The checksum was for the compressed packet.190  bool DecompressPacket();191 192private:193#if HAVE_LIBCOMPRESSION194  CompressionType m_decompression_scratch_type = CompressionType::None;195  void *m_decompression_scratch = nullptr;196#endif197 198  GDBRemoteCommunication(const GDBRemoteCommunication &) = delete;199  const GDBRemoteCommunication &200  operator=(const GDBRemoteCommunication &) = delete;201};202 203} // namespace process_gdb_remote204} // namespace lldb_private205 206namespace llvm {207template <>208struct format_provider<209    lldb_private::process_gdb_remote::GDBRemoteCommunication::PacketResult> {210  static void format(const lldb_private::process_gdb_remote::211                         GDBRemoteCommunication::PacketResult &state,212                     raw_ostream &Stream, StringRef Style);213};214} // namespace llvm215 216#endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATION_H217