1 //===-- GDBRemoteCommunicationHistory.h--------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef liblldb_GDBRemoteCommunicationHistory_h_
11 #define liblldb_GDBRemoteCommunicationHistory_h_
12 
13 #include <string>
14 #include <vector>
15 
16 #include "lldb/lldb-public.h"
17 #include "llvm/Support/YAMLTraits.h"
18 #include "llvm/Support/raw_ostream.h"
19 
20 namespace lldb_private {
21 namespace process_gdb_remote {
22 
23 /// The history keeps a circular buffer of GDB remote packets. The history is
24 /// used for logging and replaying GDB remote packets.
25 class GDBRemoteCommunicationHistory {
26 public:
27   friend llvm::yaml::MappingTraits<GDBRemoteCommunicationHistory>;
28 
29   enum PacketType { ePacketTypeInvalid = 0, ePacketTypeSend, ePacketTypeRecv };
30 
31   /// Entry in the ring buffer containing the packet data, its type, size and
32   /// index. Entries can be serialized to file.
33   struct Entry {
EntryEntry34     Entry()
35         : packet(), type(ePacketTypeInvalid), bytes_transmitted(0),
36           packet_idx(0), tid(LLDB_INVALID_THREAD_ID) {}
37 
ClearEntry38     void Clear() {
39       packet.data.clear();
40       type = ePacketTypeInvalid;
41       bytes_transmitted = 0;
42       packet_idx = 0;
43       tid = LLDB_INVALID_THREAD_ID;
44     }
45 
46     struct BinaryData {
47       std::string data;
48     };
49 
50     void Serialize(llvm::raw_ostream &strm) const;
51 
52     BinaryData packet;
53     PacketType type;
54     uint32_t bytes_transmitted;
55     uint32_t packet_idx;
56     lldb::tid_t tid;
57   };
58 
59   GDBRemoteCommunicationHistory(uint32_t size = 0);
60 
61   ~GDBRemoteCommunicationHistory();
62 
63   // For single char packets for ack, nack and /x03
64   void AddPacket(char packet_char, PacketType type, uint32_t bytes_transmitted);
65 
66   void AddPacket(const std::string &src, uint32_t src_len, PacketType type,
67                  uint32_t bytes_transmitted);
68 
69   void Dump(Stream &strm) const;
70   void Dump(Log *log) const;
DidDumpToLog()71   bool DidDumpToLog() const { return m_dumped_to_log; }
72 
SetStream(llvm::raw_ostream * strm)73   void SetStream(llvm::raw_ostream *strm) { m_stream = strm; }
74 
75 private:
GetFirstSavedPacketIndex()76   uint32_t GetFirstSavedPacketIndex() const {
77     if (m_total_packet_count < m_packets.size())
78       return 0;
79     else
80       return m_curr_idx + 1;
81   }
82 
GetNumPacketsInHistory()83   uint32_t GetNumPacketsInHistory() const {
84     if (m_total_packet_count < m_packets.size())
85       return m_total_packet_count;
86     else
87       return (uint32_t)m_packets.size();
88   }
89 
GetNextIndex()90   uint32_t GetNextIndex() {
91     ++m_total_packet_count;
92     const uint32_t idx = m_curr_idx;
93     m_curr_idx = NormalizeIndex(idx + 1);
94     return idx;
95   }
96 
NormalizeIndex(uint32_t i)97   uint32_t NormalizeIndex(uint32_t i) const {
98     return m_packets.empty() ? 0 : i % m_packets.size();
99   }
100 
101   std::vector<Entry> m_packets;
102   uint32_t m_curr_idx;
103   uint32_t m_total_packet_count;
104   mutable bool m_dumped_to_log;
105   llvm::raw_ostream *m_stream = nullptr;
106 };
107 
108 } // namespace process_gdb_remote
109 } // namespace lldb_private
110 
LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry)111 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(
112     lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry)
113 
114 namespace llvm {
115 namespace yaml {
116 
117 template <>
118 struct ScalarEnumerationTraits<lldb_private::process_gdb_remote::
119                                    GDBRemoteCommunicationHistory::PacketType> {
120   static void enumeration(IO &io,
121                           lldb_private::process_gdb_remote::
122                               GDBRemoteCommunicationHistory::PacketType &value);
123 };
124 
125 template <>
126 struct ScalarTraits<lldb_private::process_gdb_remote::
127                         GDBRemoteCommunicationHistory::Entry::BinaryData> {
128   static void output(const lldb_private::process_gdb_remote::
129                          GDBRemoteCommunicationHistory::Entry::BinaryData &,
130                      void *, raw_ostream &);
131 
132   static StringRef
133   input(StringRef, void *,
134         lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry::
135             BinaryData &);
136 
137   static QuotingType mustQuote(StringRef S) { return QuotingType::None; }
138 };
139 
140 template <>
141 struct MappingTraits<
142     lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry> {
143   static void
144   mapping(IO &io,
145           lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry
146               &Entry);
147 
148   static StringRef validate(
149       IO &io,
150       lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry &);
151 };
152 
153 } // namespace yaml
154 } // namespace llvm
155 
156 #endif // liblldb_GDBRemoteCommunicationHistory_h_
157