1 //===-- GDBRemoteCommunicationHistory.cpp -----------------------*- 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 #include "GDBRemoteCommunicationHistory.h"
11
12 // Other libraries and framework includes
13 #include "lldb/Core/StreamFile.h"
14 #include "lldb/Utility/ConstString.h"
15 #include "lldb/Utility/Log.h"
16
17 using namespace llvm;
18 using namespace lldb;
19 using namespace lldb_private;
20 using namespace lldb_private::process_gdb_remote;
21
Serialize(raw_ostream & strm) const22 void GDBRemoteCommunicationHistory::Entry::Serialize(raw_ostream &strm) const {
23 yaml::Output yout(strm);
24 yout << const_cast<GDBRemoteCommunicationHistory::Entry &>(*this);
25 strm.flush();
26 }
27
GDBRemoteCommunicationHistory(uint32_t size)28 GDBRemoteCommunicationHistory::GDBRemoteCommunicationHistory(uint32_t size)
29 : m_packets(), m_curr_idx(0), m_total_packet_count(0),
30 m_dumped_to_log(false) {
31 if (size)
32 m_packets.resize(size);
33 }
34
~GDBRemoteCommunicationHistory()35 GDBRemoteCommunicationHistory::~GDBRemoteCommunicationHistory() {}
36
AddPacket(char packet_char,PacketType type,uint32_t bytes_transmitted)37 void GDBRemoteCommunicationHistory::AddPacket(char packet_char, PacketType type,
38 uint32_t bytes_transmitted) {
39 const size_t size = m_packets.size();
40 if (size == 0)
41 return;
42
43 const uint32_t idx = GetNextIndex();
44 m_packets[idx].packet.data.assign(1, packet_char);
45 m_packets[idx].type = type;
46 m_packets[idx].bytes_transmitted = bytes_transmitted;
47 m_packets[idx].packet_idx = m_total_packet_count;
48 m_packets[idx].tid = llvm::get_threadid();
49 if (m_stream && type == ePacketTypeRecv)
50 m_packets[idx].Serialize(*m_stream);
51 }
52
AddPacket(const std::string & src,uint32_t src_len,PacketType type,uint32_t bytes_transmitted)53 void GDBRemoteCommunicationHistory::AddPacket(const std::string &src,
54 uint32_t src_len, PacketType type,
55 uint32_t bytes_transmitted) {
56 const size_t size = m_packets.size();
57 if (size == 0)
58 return;
59
60 const uint32_t idx = GetNextIndex();
61 m_packets[idx].packet.data.assign(src, 0, src_len);
62 m_packets[idx].type = type;
63 m_packets[idx].bytes_transmitted = bytes_transmitted;
64 m_packets[idx].packet_idx = m_total_packet_count;
65 m_packets[idx].tid = llvm::get_threadid();
66 if (m_stream && type == ePacketTypeRecv)
67 m_packets[idx].Serialize(*m_stream);
68 }
69
Dump(Stream & strm) const70 void GDBRemoteCommunicationHistory::Dump(Stream &strm) const {
71 const uint32_t size = GetNumPacketsInHistory();
72 const uint32_t first_idx = GetFirstSavedPacketIndex();
73 const uint32_t stop_idx = m_curr_idx + size;
74 for (uint32_t i = first_idx; i < stop_idx; ++i) {
75 const uint32_t idx = NormalizeIndex(i);
76 const Entry &entry = m_packets[idx];
77 if (entry.type == ePacketTypeInvalid || entry.packet.data.empty())
78 break;
79 strm.Printf("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s\n",
80 entry.packet_idx, entry.tid, entry.bytes_transmitted,
81 (entry.type == ePacketTypeSend) ? "send" : "read",
82 entry.packet.data.c_str());
83 }
84 }
85
Dump(Log * log) const86 void GDBRemoteCommunicationHistory::Dump(Log *log) const {
87 if (!log || m_dumped_to_log)
88 return;
89
90 m_dumped_to_log = true;
91 const uint32_t size = GetNumPacketsInHistory();
92 const uint32_t first_idx = GetFirstSavedPacketIndex();
93 const uint32_t stop_idx = m_curr_idx + size;
94 for (uint32_t i = first_idx; i < stop_idx; ++i) {
95 const uint32_t idx = NormalizeIndex(i);
96 const Entry &entry = m_packets[idx];
97 if (entry.type == ePacketTypeInvalid || entry.packet.data.empty())
98 break;
99 log->Printf("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s",
100 entry.packet_idx, entry.tid, entry.bytes_transmitted,
101 (entry.type == ePacketTypeSend) ? "send" : "read",
102 entry.packet.data.c_str());
103 }
104 }
105
106 void yaml::ScalarEnumerationTraits<GDBRemoteCommunicationHistory::PacketType>::
enumeration(IO & io,GDBRemoteCommunicationHistory::PacketType & value)107 enumeration(IO &io, GDBRemoteCommunicationHistory::PacketType &value) {
108 io.enumCase(value, "Invalid",
109 GDBRemoteCommunicationHistory::ePacketTypeInvalid);
110 io.enumCase(value, "Send", GDBRemoteCommunicationHistory::ePacketTypeSend);
111 io.enumCase(value, "Recv", GDBRemoteCommunicationHistory::ePacketTypeRecv);
112 }
113
114 void yaml::ScalarTraits<GDBRemoteCommunicationHistory::Entry::BinaryData>::
output(const GDBRemoteCommunicationHistory::Entry::BinaryData & Val,void *,raw_ostream & Out)115 output(const GDBRemoteCommunicationHistory::Entry::BinaryData &Val, void *,
116 raw_ostream &Out) {
117 Out << toHex(Val.data);
118 }
119
120 StringRef
input(StringRef Scalar,void *,GDBRemoteCommunicationHistory::Entry::BinaryData & Val)121 yaml::ScalarTraits<GDBRemoteCommunicationHistory::Entry::BinaryData>::input(
122 StringRef Scalar, void *,
123 GDBRemoteCommunicationHistory::Entry::BinaryData &Val) {
124 Val.data = fromHex(Scalar);
125 return {};
126 }
127
mapping(IO & io,GDBRemoteCommunicationHistory::Entry & Entry)128 void yaml::MappingTraits<GDBRemoteCommunicationHistory::Entry>::mapping(
129 IO &io, GDBRemoteCommunicationHistory::Entry &Entry) {
130 io.mapRequired("packet", Entry.packet);
131 io.mapRequired("type", Entry.type);
132 io.mapRequired("bytes", Entry.bytes_transmitted);
133 io.mapRequired("index", Entry.packet_idx);
134 io.mapRequired("tid", Entry.tid);
135 }
136
validate(IO & io,GDBRemoteCommunicationHistory::Entry & Entry)137 StringRef yaml::MappingTraits<GDBRemoteCommunicationHistory::Entry>::validate(
138 IO &io, GDBRemoteCommunicationHistory::Entry &Entry) {
139 if (Entry.bytes_transmitted != Entry.packet.data.size())
140 return "BinaryData size doesn't match bytes transmitted";
141
142 return {};
143 }
144