|  | //===-- GDBRemoteCommunicationHistory.cpp ---------------------------------===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "GDBRemoteCommunicationHistory.h" | 
|  |  | 
|  | // Other libraries and framework includes | 
|  | #include "lldb/Core/StreamFile.h" | 
|  | #include "lldb/Utility/ConstString.h" | 
|  | #include "lldb/Utility/Log.h" | 
|  |  | 
|  | using namespace llvm; | 
|  | using namespace lldb; | 
|  | using namespace lldb_private; | 
|  | using namespace lldb_private::process_gdb_remote; | 
|  |  | 
|  | GDBRemoteCommunicationHistory::GDBRemoteCommunicationHistory(uint32_t size) | 
|  | : m_packets(), m_curr_idx(0), m_total_packet_count(0), | 
|  | m_dumped_to_log(false) { | 
|  | if (size) | 
|  | m_packets.resize(size); | 
|  | } | 
|  |  | 
|  | GDBRemoteCommunicationHistory::~GDBRemoteCommunicationHistory() {} | 
|  |  | 
|  | void GDBRemoteCommunicationHistory::AddPacket(char packet_char, | 
|  | GDBRemotePacket::Type type, | 
|  | uint32_t bytes_transmitted) { | 
|  | const size_t size = m_packets.size(); | 
|  | if (size == 0) | 
|  | return; | 
|  |  | 
|  | const uint32_t idx = GetNextIndex(); | 
|  | m_packets[idx].packet.data.assign(1, packet_char); | 
|  | m_packets[idx].type = type; | 
|  | m_packets[idx].bytes_transmitted = bytes_transmitted; | 
|  | m_packets[idx].packet_idx = m_total_packet_count; | 
|  | m_packets[idx].tid = llvm::get_threadid(); | 
|  | if (m_recorder) | 
|  | m_recorder->Record(m_packets[idx]); | 
|  | } | 
|  |  | 
|  | void GDBRemoteCommunicationHistory::AddPacket(const std::string &src, | 
|  | uint32_t src_len, | 
|  | GDBRemotePacket::Type type, | 
|  | uint32_t bytes_transmitted) { | 
|  | const size_t size = m_packets.size(); | 
|  | if (size == 0) | 
|  | return; | 
|  |  | 
|  | const uint32_t idx = GetNextIndex(); | 
|  | m_packets[idx].packet.data.assign(src, 0, src_len); | 
|  | m_packets[idx].type = type; | 
|  | m_packets[idx].bytes_transmitted = bytes_transmitted; | 
|  | m_packets[idx].packet_idx = m_total_packet_count; | 
|  | m_packets[idx].tid = llvm::get_threadid(); | 
|  | if (m_recorder) | 
|  | m_recorder->Record(m_packets[idx]); | 
|  | } | 
|  |  | 
|  | void GDBRemoteCommunicationHistory::Dump(Stream &strm) const { | 
|  | const uint32_t size = GetNumPacketsInHistory(); | 
|  | const uint32_t first_idx = GetFirstSavedPacketIndex(); | 
|  | const uint32_t stop_idx = m_curr_idx + size; | 
|  | for (uint32_t i = first_idx; i < stop_idx; ++i) { | 
|  | const uint32_t idx = NormalizeIndex(i); | 
|  | const GDBRemotePacket &entry = m_packets[idx]; | 
|  | if (entry.type == GDBRemotePacket::ePacketTypeInvalid || | 
|  | entry.packet.data.empty()) | 
|  | break; | 
|  | strm.Printf("history[%u] ", entry.packet_idx); | 
|  | entry.Dump(strm); | 
|  | } | 
|  | } | 
|  |  | 
|  | void GDBRemoteCommunicationHistory::Dump(Log *log) const { | 
|  | if (!log || m_dumped_to_log) | 
|  | return; | 
|  |  | 
|  | m_dumped_to_log = true; | 
|  | const uint32_t size = GetNumPacketsInHistory(); | 
|  | const uint32_t first_idx = GetFirstSavedPacketIndex(); | 
|  | const uint32_t stop_idx = m_curr_idx + size; | 
|  | for (uint32_t i = first_idx; i < stop_idx; ++i) { | 
|  | const uint32_t idx = NormalizeIndex(i); | 
|  | const GDBRemotePacket &entry = m_packets[idx]; | 
|  | if (entry.type == GDBRemotePacket::ePacketTypeInvalid || | 
|  | entry.packet.data.empty()) | 
|  | break; | 
|  | LLDB_LOGF(log, "history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s", | 
|  | entry.packet_idx, entry.tid, entry.bytes_transmitted, | 
|  | (entry.type == GDBRemotePacket::ePacketTypeSend) ? "send" | 
|  | : "read", | 
|  | entry.packet.data.c_str()); | 
|  | } | 
|  | } | 
|  |  |