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