1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
//===-- GDBRemote.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 "lldb/Utility/GDBRemote.h"
#include "lldb/Utility/Flags.h"
#include "lldb/Utility/Stream.h"
#include <stdio.h>
using namespace lldb;
using namespace lldb_private::repro;
using namespace lldb_private;
using namespace llvm;
StreamGDBRemote::StreamGDBRemote() : StreamString() {}
StreamGDBRemote::StreamGDBRemote(uint32_t flags, uint32_t addr_size,
ByteOrder byte_order)
: StreamString(flags, addr_size, byte_order) {}
StreamGDBRemote::~StreamGDBRemote() {}
int StreamGDBRemote::PutEscapedBytes(const void *s, size_t src_len) {
int bytes_written = 0;
const uint8_t *src = static_cast<const uint8_t *>(s);
bool binary_is_set = m_flags.Test(eBinary);
m_flags.Clear(eBinary);
while (src_len) {
uint8_t byte = *src;
src++;
src_len--;
if (byte == 0x23 || byte == 0x24 || byte == 0x7d || byte == 0x2a) {
bytes_written += PutChar(0x7d);
byte ^= 0x20;
}
bytes_written += PutChar(byte);
};
if (binary_is_set)
m_flags.Set(eBinary);
return bytes_written;
}
llvm::StringRef GDBRemotePacket::GetTypeStr() const {
switch (type) {
case GDBRemotePacket::ePacketTypeSend:
return "send";
case GDBRemotePacket::ePacketTypeRecv:
return "read";
case GDBRemotePacket::ePacketTypeInvalid:
return "invalid";
}
llvm_unreachable("All enum cases should be handled");
}
void GDBRemotePacket::Dump(Stream &strm) const {
strm.Printf("tid=0x%4.4" PRIx64 " <%4u> %s packet: %s\n", tid,
bytes_transmitted, GetTypeStr().data(), packet.data.c_str());
}
void yaml::ScalarEnumerationTraits<GDBRemotePacket::Type>::enumeration(
IO &io, GDBRemotePacket::Type &value) {
io.enumCase(value, "Invalid", GDBRemotePacket::ePacketTypeInvalid);
io.enumCase(value, "Send", GDBRemotePacket::ePacketTypeSend);
io.enumCase(value, "Recv", GDBRemotePacket::ePacketTypeRecv);
}
void yaml::ScalarTraits<GDBRemotePacket::BinaryData>::output(
const GDBRemotePacket::BinaryData &Val, void *, raw_ostream &Out) {
Out << toHex(Val.data);
}
StringRef yaml::ScalarTraits<GDBRemotePacket::BinaryData>::input(
StringRef Scalar, void *, GDBRemotePacket::BinaryData &Val) {
Val.data = fromHex(Scalar);
return {};
}
void yaml::MappingTraits<GDBRemotePacket>::mapping(IO &io,
GDBRemotePacket &Packet) {
io.mapRequired("packet", Packet.packet);
io.mapRequired("type", Packet.type);
io.mapRequired("bytes", Packet.bytes_transmitted);
io.mapRequired("index", Packet.packet_idx);
io.mapRequired("tid", Packet.tid);
}
StringRef
yaml::MappingTraits<GDBRemotePacket>::validate(IO &io,
GDBRemotePacket &Packet) {
return {};
}
void GDBRemoteProvider::Keep() {
std::vector<std::string> files;
for (auto &recorder : m_packet_recorders) {
files.push_back(recorder->GetFilename().GetPath());
}
FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file);
std::error_code ec;
llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text);
if (ec)
return;
yaml::Output yout(os);
yout << files;
}
void GDBRemoteProvider::Discard() { m_packet_recorders.clear(); }
llvm::Expected<std::unique_ptr<PacketRecorder>>
PacketRecorder::Create(const FileSpec &filename) {
std::error_code ec;
auto recorder = std::make_unique<PacketRecorder>(std::move(filename), ec);
if (ec)
return llvm::errorCodeToError(ec);
return std::move(recorder);
}
PacketRecorder *GDBRemoteProvider::GetNewPacketRecorder() {
std::size_t i = m_packet_recorders.size() + 1;
std::string filename = (llvm::Twine(Info::name) + llvm::Twine("-") +
llvm::Twine(i) + llvm::Twine(".yaml"))
.str();
auto recorder_or_error =
PacketRecorder::Create(GetRoot().CopyByAppendingPathComponent(filename));
if (!recorder_or_error) {
llvm::consumeError(recorder_or_error.takeError());
return nullptr;
}
m_packet_recorders.push_back(std::move(*recorder_or_error));
return m_packet_recorders.back().get();
}
void PacketRecorder::Record(const GDBRemotePacket &packet) {
if (!m_record)
return;
yaml::Output yout(m_os);
yout << const_cast<GDBRemotePacket &>(packet);
m_os.flush();
}
llvm::raw_ostream *GDBRemoteProvider::GetHistoryStream() {
FileSpec history_file = GetRoot().CopyByAppendingPathComponent(Info::file);
std::error_code EC;
m_stream_up = std::make_unique<raw_fd_ostream>(history_file.GetPath(), EC,
sys::fs::OpenFlags::OF_Text);
return m_stream_up.get();
}
char GDBRemoteProvider::ID = 0;
const char *GDBRemoteProvider::Info::file = "gdb-remote.yaml";
const char *GDBRemoteProvider::Info::name = "gdb-remote";
|