diff options
author | Oxore <oxore@protonmail.com> | 2022-08-27 15:12:08 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2022-08-27 15:13:13 +0300 |
commit | 9580a9a8daa4426914f396a694903ab880ecd3f2 (patch) | |
tree | 46394ea036316ffccf3357bcc35f1c18635ae890 /gdbremote_parser.cpp | |
parent | 903b8dbcaad887f6e14cc8cffc22ddda08dc9f85 (diff) |
Add initial gdbremote implementation
Diffstat (limited to 'gdbremote_parser.cpp')
-rw-r--r-- | gdbremote_parser.cpp | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/gdbremote_parser.cpp b/gdbremote_parser.cpp new file mode 100644 index 0000000..e3f4aae --- /dev/null +++ b/gdbremote_parser.cpp @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: Unlicense + */ + +#include "gdbremote_parser.hpp" + +using namespace GDBRemote; + +static inline bool is_hex_digit(uint8_t byte) +{ + return byte >= '0' && byte <= '9' + || byte >= 'A' && byte < 'F' + || byte >= 'a' && byte <= 'f'; +} + +static inline uint8_t parseChecksumFromHexChars(uint8_t first, uint8_t second) +{ + // Assume, that given bytes are valid hex digits in ASCII + first = ((first & 0x40) ? (first + 9) : first) & 0x0f; + second = ((second & 0x40) ? (second + 9) : second) & 0x0f; + return ((first << 4) | second) & 0xff; +} + +std::unique_ptr<ExchangeResult> ExchangeContext::Consume(uint8_t byte) +{ + switch (_parsing_state) { + case ParsingState::kIdle: + if (byte == '$') { + transit(ParsingState::kPacketData); + } + break; + case ParsingState::kPacketData: + if (byte == '#') { + transit(ParsingState::kChecksum1); + } else { + _checksum = (_checksum + byte) & 0xff; + _packet_data += byte; + } + break; + case ParsingState::kPacketDataBinSecond: + // TODO escaped and binary data + break; + case ParsingState::kChecksum1: + if (is_hex_digit(byte)) { + transit(ParsingState::kChecksum2); + _given_checksum_first_byte = byte; + } else { + transit(ParsingState::kIdle); + return ExchangeResult::Nak(); + } + break; + case ParsingState::kChecksum2: + const uint8_t checksum = _checksum; + std::string packet_data(std::move(_packet_data)); + transit(ParsingState::kIdle); + if (is_hex_digit(byte)) { + const uint8_t given_checksum = + parseChecksumFromHexChars(_given_checksum_first_byte, byte); + if (given_checksum == checksum) { + return ExchangeResult::Ack(packet_data); + } else { + printf( + "Checksum mismatch received: %02X, expected: %02X\n", + given_checksum, checksum); + printf("Packet data: \"%s\"\n", packet_data.c_str()); + return ExchangeResult::Nak(); + } + } else { + return ExchangeResult::Nak(); + } + break; + } + return nullptr; +} + +std::string ExchangeContext::WrapDataToSend(Packet packet) +{ + (void) packet; + return std::string{}; +} + +void ExchangeContext::transit(ParsingState new_state) +{ + printf( + "GDBRemote ParsingState: %s -> %s\n", + parsingStateToString(_parsing_state), + parsingStateToString(new_state)); + switch (new_state) { + case ParsingState::kIdle: + _checksum = 0; + _packet_data.clear(); + break; + case ParsingState::kPacketData: + break; + case ParsingState::kPacketDataBinSecond: + break; + case ParsingState::kChecksum1: + break; + case ParsingState::kChecksum2: + break; + } + _parsing_state = new_state; +} + +const char* ExchangeContext::parsingStateToString(ParsingState state) +{ + switch (state) { + case ParsingState::kIdle: + return "Idle"; + case ParsingState::kPacketData: + return "PacketData"; + case ParsingState::kPacketDataBinSecond: + return "PacketDataBinSecond"; + case ParsingState::kChecksum1: + return "Checksum1"; + case ParsingState::kChecksum2: + return "Checksum2"; + } + return "?"; +} |