15ffd83dbSDimitry Andric //===-- GDBRemoteCommunicationHistory.cpp ---------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "GDBRemoteCommunicationHistory.h"
100b57cec5SDimitry Andric
110b57cec5SDimitry Andric // Other libraries and framework includes
120b57cec5SDimitry Andric #include "lldb/Utility/ConstString.h"
130b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
140b57cec5SDimitry Andric
150b57cec5SDimitry Andric using namespace llvm;
160b57cec5SDimitry Andric using namespace lldb;
170b57cec5SDimitry Andric using namespace lldb_private;
180b57cec5SDimitry Andric using namespace lldb_private::process_gdb_remote;
190b57cec5SDimitry Andric
GDBRemoteCommunicationHistory(uint32_t size)200b57cec5SDimitry Andric GDBRemoteCommunicationHistory::GDBRemoteCommunicationHistory(uint32_t size)
21*fe6060f1SDimitry Andric : m_packets() {
220b57cec5SDimitry Andric if (size)
230b57cec5SDimitry Andric m_packets.resize(size);
240b57cec5SDimitry Andric }
250b57cec5SDimitry Andric
26*fe6060f1SDimitry Andric GDBRemoteCommunicationHistory::~GDBRemoteCommunicationHistory() = default;
270b57cec5SDimitry Andric
AddPacket(char packet_char,GDBRemotePacket::Type type,uint32_t bytes_transmitted)289dba64beSDimitry Andric void GDBRemoteCommunicationHistory::AddPacket(char packet_char,
299dba64beSDimitry Andric GDBRemotePacket::Type type,
300b57cec5SDimitry Andric uint32_t bytes_transmitted) {
310b57cec5SDimitry Andric const size_t size = m_packets.size();
320b57cec5SDimitry Andric if (size == 0)
330b57cec5SDimitry Andric return;
340b57cec5SDimitry Andric
350b57cec5SDimitry Andric const uint32_t idx = GetNextIndex();
360b57cec5SDimitry Andric m_packets[idx].packet.data.assign(1, packet_char);
370b57cec5SDimitry Andric m_packets[idx].type = type;
380b57cec5SDimitry Andric m_packets[idx].bytes_transmitted = bytes_transmitted;
390b57cec5SDimitry Andric m_packets[idx].packet_idx = m_total_packet_count;
400b57cec5SDimitry Andric m_packets[idx].tid = llvm::get_threadid();
410b57cec5SDimitry Andric }
420b57cec5SDimitry Andric
AddPacket(const std::string & src,uint32_t src_len,GDBRemotePacket::Type type,uint32_t bytes_transmitted)430b57cec5SDimitry Andric void GDBRemoteCommunicationHistory::AddPacket(const std::string &src,
449dba64beSDimitry Andric uint32_t src_len,
459dba64beSDimitry Andric GDBRemotePacket::Type type,
460b57cec5SDimitry Andric uint32_t bytes_transmitted) {
470b57cec5SDimitry Andric const size_t size = m_packets.size();
480b57cec5SDimitry Andric if (size == 0)
490b57cec5SDimitry Andric return;
500b57cec5SDimitry Andric
510b57cec5SDimitry Andric const uint32_t idx = GetNextIndex();
520b57cec5SDimitry Andric m_packets[idx].packet.data.assign(src, 0, src_len);
530b57cec5SDimitry Andric m_packets[idx].type = type;
540b57cec5SDimitry Andric m_packets[idx].bytes_transmitted = bytes_transmitted;
550b57cec5SDimitry Andric m_packets[idx].packet_idx = m_total_packet_count;
560b57cec5SDimitry Andric m_packets[idx].tid = llvm::get_threadid();
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric
Dump(Stream & strm) const590b57cec5SDimitry Andric void GDBRemoteCommunicationHistory::Dump(Stream &strm) const {
600b57cec5SDimitry Andric const uint32_t size = GetNumPacketsInHistory();
610b57cec5SDimitry Andric const uint32_t first_idx = GetFirstSavedPacketIndex();
620b57cec5SDimitry Andric const uint32_t stop_idx = m_curr_idx + size;
630b57cec5SDimitry Andric for (uint32_t i = first_idx; i < stop_idx; ++i) {
640b57cec5SDimitry Andric const uint32_t idx = NormalizeIndex(i);
659dba64beSDimitry Andric const GDBRemotePacket &entry = m_packets[idx];
669dba64beSDimitry Andric if (entry.type == GDBRemotePacket::ePacketTypeInvalid ||
679dba64beSDimitry Andric entry.packet.data.empty())
680b57cec5SDimitry Andric break;
699dba64beSDimitry Andric strm.Printf("history[%u] ", entry.packet_idx);
709dba64beSDimitry Andric entry.Dump(strm);
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric
Dump(Log * log) const740b57cec5SDimitry Andric void GDBRemoteCommunicationHistory::Dump(Log *log) const {
750b57cec5SDimitry Andric if (!log || m_dumped_to_log)
760b57cec5SDimitry Andric return;
770b57cec5SDimitry Andric
780b57cec5SDimitry Andric m_dumped_to_log = true;
790b57cec5SDimitry Andric const uint32_t size = GetNumPacketsInHistory();
800b57cec5SDimitry Andric const uint32_t first_idx = GetFirstSavedPacketIndex();
810b57cec5SDimitry Andric const uint32_t stop_idx = m_curr_idx + size;
820b57cec5SDimitry Andric for (uint32_t i = first_idx; i < stop_idx; ++i) {
830b57cec5SDimitry Andric const uint32_t idx = NormalizeIndex(i);
849dba64beSDimitry Andric const GDBRemotePacket &entry = m_packets[idx];
859dba64beSDimitry Andric if (entry.type == GDBRemotePacket::ePacketTypeInvalid ||
869dba64beSDimitry Andric entry.packet.data.empty())
870b57cec5SDimitry Andric break;
889dba64beSDimitry Andric LLDB_LOGF(log, "history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s",
890b57cec5SDimitry Andric entry.packet_idx, entry.tid, entry.bytes_transmitted,
909dba64beSDimitry Andric (entry.type == GDBRemotePacket::ePacketTypeSend) ? "send"
919dba64beSDimitry Andric : "read",
920b57cec5SDimitry Andric entry.packet.data.c_str());
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric
96