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 22 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 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 35 GDBRemoteCommunicationHistory::~GDBRemoteCommunicationHistory() {} 36 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 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 70 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 86 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>:: 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>:: 115 output(const GDBRemoteCommunicationHistory::Entry::BinaryData &Val, void *, 116 raw_ostream &Out) { 117 Out << toHex(Val.data); 118 } 119 120 StringRef 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 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 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