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