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