6#include "../microfmt.hpp"
7#include "../reloco.hpp"
36 for (
const auto ® : AbiTraits::gdb_register_traits::layout()) {
37 encode_single_register(out, ctx, reg);
50 RELOCO_BEGIN_UNSAFE_CODE
53 emit_unavailable(out, reg.bit_size / 8);
57 const size_t byte_size = reg.bit_size / 8;
63 if (byte_size <= 64) {
64 uint8_t stack_buf[64] = {};
65 if (ctx.read_raw(reg.dwarf_index, stack_buf, byte_size)) {
66 emit_hex_bytes(out, span<const uint8_t>{stack_buf, byte_size});
68 emit_unavailable(out, byte_size);
74 const auto scratch = ctx.scratch();
75 if (byte_size <= scratch.size()) {
76 if (ctx.read_raw(reg.dwarf_index, scratch.data(), byte_size)) {
77 emit_hex_bytes(out, span<const uint8_t>{
reinterpret_cast<const uint8_t *
>(scratch.data()), byte_size});
79 emit_unavailable(out, byte_size);
83 emit_unavailable(out, byte_size);
93 static void emit_hex_bytes(
sink target, span<const uint8_t> data)
noexcept {
94 for (uint8_t b : data) {
95 target.put(microfmt::detail::hex_digits_lower[(b >> 4) & 0x0F]);
96 target.put(microfmt::detail::hex_digits_lower[b & 0x0F]);
106 static void emit_unavailable(sink target,
size_t byte_size)
noexcept {
107 for (
size_t i = 0; i < byte_size * 2; ++i) {
131 template <
typename AbiTraits>
138 for (
const auto ® : AbiTraits::gdb_register_traits::layout()) {
139 const size_t hex_len = reg.bit_size / 4;
143 if (offset + hex_len > hex_payload.size()) {
147 string_view reg_hex = hex_payload.substr(offset, hex_len);
152 if (!reg_hex.empty() && (reg_hex[0] ==
'x' || reg_hex[0] ==
'X')) {
156 if (!decode_single_register(reg_hex, ctx, reg)) {
174 RELOCO_BEGIN_UNSAFE_CODE
180 const size_t byte_size = reg.bit_size / 8;
184 if (hex_payload.size() < byte_size * 2) {
189 if (hex_payload[0] ==
'x' || hex_payload[0] ==
'X') {
194 if (byte_size <= 64) {
195 uint8_t stack_buf[64] = {};
196 const auto out_span = span<uint8_t>{stack_buf, byte_size};
198 if (!parse_hex_to_bytes(hex_payload.substr(0, byte_size * 2), out_span)) {
201 return ctx.write_raw(reg.dwarf_index, stack_buf, byte_size);
205 const auto scratch = ctx.scratch();
206 if (byte_size <= scratch.size()) {
207 const auto out_span = span<uint8_t>{
reinterpret_cast<uint8_t *
>(scratch.data()), byte_size};
209 if (!parse_hex_to_bytes(hex_payload.substr(0, byte_size * 2), out_span)) {
212 return ctx.write_raw(reg.dwarf_index, scratch.data(), byte_size);
225 RELOCO_BEGIN_UNSAFE_CODE
226 [[nodiscard]]
static bool parse_hex_to_bytes(string_view hex, span<uint8_t> out)
noexcept {
227 for (
size_t i = 0; i < out.size(); ++i) {
228 const uint8_t hi = hex_char_to_val(hex[i * 2]);
229 const uint8_t lo = hex_char_to_val(hex[i * 2 + 1]);
231 if (hi == 0xFF || lo == 0xFF) {
234 out[i] =
static_cast<uint8_t
>((hi << 4) | lo);
245 RELOCO_BEGIN_UNSAFE_CODE
246 [[nodiscard]]
static constexpr uint8_t hex_char_to_val(
char c)
noexcept {
247 if (c >=
'0' && c <=
'9')
248 return static_cast<uint8_t
>(c -
'0');
249 if (c >=
'a' && c <=
'f')
250 return static_cast<uint8_t
>(c -
'a' + 10);
251 if (c >=
'A' && c <=
'F')
252 return static_cast<uint8_t
>(c -
'A' + 10);
Decodes GDB RSP hex strings into binary values and writes them to the execution context.
Definition gdb_register_array.hpp:118
static bool decode_all_registers(string_view hex_payload, const register_context_ref &ctx) noexcept
Decodes the full register layout hex payload ('G' packet payload).
Definition gdb_register_array.hpp:132
static RELOCO_BEGIN_UNSAFE_CODE bool decode_single_register(string_view hex_payload, const register_context_ref &ctx, const register_mapping ®) noexcept
Decodes a single register hex payload ('P' packet value).
Definition gdb_register_array.hpp:175
Encodes register values from a execution context into GDB RSP hex strings.
Definition gdb_register_array.hpp:19
static void encode_all_registers(sink out, const register_context_ref &ctx) noexcept
Encodes the full register layout for a specific architecture ('g' packet response).
Definition gdb_register_array.hpp:31
static RELOCO_BEGIN_UNSAFE_CODE void encode_single_register(sink out, const register_context_ref &ctx, const register_mapping ®) noexcept
Encodes a single register based on its mapping ('p' packet response).
Definition gdb_register_array.hpp:51
Zero-allocation, type-erased handle for inspecting and modifying CPU registers from a frame context.
Definition register_context.hpp:118
#define MICROFMT_API_CLASS
Definition compat.hpp:181
Per-architecture ABI traits describing registers used during DWARF unwinding.
Definition gdb_decoders.hpp:15
reloco::sink sink
Type-erased, zero-allocation output sink.
Definition microfmt.hpp:46
RELOCO_END_UNSAFE_CODE
Definition remote_object.hpp:132
Maps a single register between GDB and DWARF definitions.
Definition gdb_registers.hpp:15