summaryrefslogtreecommitdiff
path: root/gdbremote_parser.cpp
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2022-08-27 15:12:08 +0300
committerOxore <oxore@protonmail.com>2022-08-27 15:13:13 +0300
commit9580a9a8daa4426914f396a694903ab880ecd3f2 (patch)
tree46394ea036316ffccf3357bcc35f1c18635ae890 /gdbremote_parser.cpp
parent903b8dbcaad887f6e14cc8cffc22ddda08dc9f85 (diff)
Add initial gdbremote implementation
Diffstat (limited to 'gdbremote_parser.cpp')
-rw-r--r--gdbremote_parser.cpp119
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 "?";
+}