1343181Sdim//===-- GDBRemoteCommunicationHistory.h--------------------------*- C++ -*-===//
2343181Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6343181Sdim//
7343181Sdim//===----------------------------------------------------------------------===//
8343181Sdim
9343181Sdim#ifndef liblldb_GDBRemoteCommunicationHistory_h_
10343181Sdim#define liblldb_GDBRemoteCommunicationHistory_h_
11343181Sdim
12343181Sdim#include <string>
13343181Sdim#include <vector>
14343181Sdim
15360784Sdim#include "lldb/Utility/GDBRemote.h"
16360784Sdim#include "lldb/Utility/Reproducer.h"
17343181Sdim#include "lldb/lldb-public.h"
18343181Sdim#include "llvm/Support/YAMLTraits.h"
19343181Sdim#include "llvm/Support/raw_ostream.h"
20343181Sdim
21343181Sdimnamespace lldb_private {
22360784Sdimnamespace repro {
23360784Sdimclass PacketRecorder;
24360784Sdim}
25343181Sdimnamespace process_gdb_remote {
26343181Sdim
27343181Sdim/// The history keeps a circular buffer of GDB remote packets. The history is
28343181Sdim/// used for logging and replaying GDB remote packets.
29343181Sdimclass GDBRemoteCommunicationHistory {
30343181Sdimpublic:
31343181Sdim  friend llvm::yaml::MappingTraits<GDBRemoteCommunicationHistory>;
32343181Sdim
33343181Sdim  GDBRemoteCommunicationHistory(uint32_t size = 0);
34343181Sdim
35343181Sdim  ~GDBRemoteCommunicationHistory();
36343181Sdim
37343181Sdim  // For single char packets for ack, nack and /x03
38360784Sdim  void AddPacket(char packet_char, GDBRemotePacket::Type type,
39343181Sdim                 uint32_t bytes_transmitted);
40343181Sdim
41360784Sdim  void AddPacket(const std::string &src, uint32_t src_len,
42360784Sdim                 GDBRemotePacket::Type type, uint32_t bytes_transmitted);
43360784Sdim
44343181Sdim  void Dump(Stream &strm) const;
45343181Sdim  void Dump(Log *log) const;
46343181Sdim  bool DidDumpToLog() const { return m_dumped_to_log; }
47343181Sdim
48360784Sdim  void SetRecorder(repro::PacketRecorder *recorder) { m_recorder = recorder; }
49343181Sdim
50343181Sdimprivate:
51343181Sdim  uint32_t GetFirstSavedPacketIndex() const {
52343181Sdim    if (m_total_packet_count < m_packets.size())
53343181Sdim      return 0;
54343181Sdim    else
55343181Sdim      return m_curr_idx + 1;
56343181Sdim  }
57343181Sdim
58343181Sdim  uint32_t GetNumPacketsInHistory() const {
59343181Sdim    if (m_total_packet_count < m_packets.size())
60343181Sdim      return m_total_packet_count;
61343181Sdim    else
62343181Sdim      return (uint32_t)m_packets.size();
63343181Sdim  }
64343181Sdim
65343181Sdim  uint32_t GetNextIndex() {
66343181Sdim    ++m_total_packet_count;
67343181Sdim    const uint32_t idx = m_curr_idx;
68343181Sdim    m_curr_idx = NormalizeIndex(idx + 1);
69343181Sdim    return idx;
70343181Sdim  }
71343181Sdim
72343181Sdim  uint32_t NormalizeIndex(uint32_t i) const {
73343181Sdim    return m_packets.empty() ? 0 : i % m_packets.size();
74343181Sdim  }
75343181Sdim
76360784Sdim  std::vector<GDBRemotePacket> m_packets;
77343181Sdim  uint32_t m_curr_idx;
78343181Sdim  uint32_t m_total_packet_count;
79343181Sdim  mutable bool m_dumped_to_log;
80360784Sdim  repro::PacketRecorder *m_recorder = nullptr;
81343181Sdim};
82343181Sdim
83343181Sdim} // namespace process_gdb_remote
84343181Sdim} // namespace lldb_private
85343181Sdim
86343181Sdim#endif // liblldb_GDBRemoteCommunicationHistory_h_
87