diff options
author | Oxore <oxore@protonmail.com> | 2022-09-03 13:58:22 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2022-09-03 13:58:22 +0300 |
commit | f1573848a8ced69f45192b07bab9785e900d34a0 (patch) | |
tree | 3f3346fcf811fae2fa6f11f5d8295c321761c1c6 | |
parent | 1c108b02f62c0812a8a71e78854666588a811840 (diff) |
Begin implementing breakpoints support
-rw-r--r-- | CMakeLists.txt | 10 | ||||
-rw-r--r-- | gdbremote_parser.cpp | 78 | ||||
-rw-r--r-- | gdbremote_parser.hpp | 6 |
3 files changed, 46 insertions, 48 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 71ac411..7187264 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,11 +51,11 @@ target_compile_definitions(emulator PRIVATE DEBUG_TRACE_GDB_REMOTE=1 ) -# Target for GDB Remote Debugging protocol implementation testing -add_executable(gdbremote - gdbremote.cpp - gdbremote_parser.cpp - ) +## Target for GDB Remote Debugging protocol implementation testing +#add_executable(gdbremote +# gdbremote.cpp +# gdbremote_parser.cpp +# ) include_directories( . diff --git a/gdbremote_parser.cpp b/gdbremote_parser.cpp index 641590f..31e6af9 100644 --- a/gdbremote_parser.cpp +++ b/gdbremote_parser.cpp @@ -14,7 +14,6 @@ enum class TokenType: uint8_t { kSeparatorComma, kSeparatorColon, kSeparatorSemicolon, - kNumeric, kHexNumeric, kArbitrary, }; @@ -24,13 +23,6 @@ static inline bool isseparator(uint8_t byte) return ':' == byte || ';' == byte || ',' == byte; } -static inline bool IsTokenTypeSeparator(TokenType token_type) -{ - return token_type == TokenType::kSeparatorColon || - token_type == TokenType::kSeparatorComma || - token_type == TokenType::kSeparatorSemicolon; -} - static inline TokenType separatorTypeFromByte(uint8_t byte) { if (':' == byte) return TokenType::kSeparatorColon; @@ -42,12 +34,17 @@ struct Token { TokenType type{}; std::string data{}; - static std::vector<Token> Tokenize(std::string packet_data) + static std::vector<Token> Tokenize( + const std::string& packet_data, const std::string& command) { if (packet_data.length() == 0) return std::vector<Token>{}; std::vector<Token> tokens{}; + const size_t cmdlen = command.length(); + if (cmdlen > 0) { + tokens.push_back(Token{TokenType::kArbitrary, command}); + } TokenType type{}; - size_t i{}, offset{}; + size_t i{command.length()}, offset{command.length()}; for (; i < packet_data.length(); i++) { assert(type != TokenType::kSeparatorColon); assert(type != TokenType::kSeparatorSemicolon); @@ -65,10 +62,6 @@ struct Token { }); offset++; type = TokenType::kUnknown; - } else if (isdigit(byte)) { - if (type == TokenType::kUnknown) { - type = TokenType::kNumeric; - } } else if (isxdigit(byte)) { if (type != TokenType::kArbitrary) { type = TokenType::kHexNumeric; @@ -152,10 +145,9 @@ struct Command { } static Packet parseContinueVCont(const std::vector<Token>&& tokens) { - const std::string first = tokens[0].data; - constexpr size_t command_len = strlen("vCont"); + const std::string first_arg = tokens[1].data; // Check if it is "vCont?" command - if (first.length() > command_len && first[command_len] == '?') { + if (first_arg == "?") { return Packet{PacketType::kContinueAskSupported}; } // TODO arguments @@ -167,20 +159,17 @@ struct Command { } static Packet parseReadMemory(const std::vector<Token>&& tokens) { - if (tokens.size() < 3 || - tokens[0].type != TokenType::kArbitrary || - !IsTokenTypeSeparator(tokens[1].type) || - tokens[2].type != TokenType::kNumeric) - { + if (tokens.size() < 4) return Packet::None(); - } - constexpr size_t command_len = strlen("m"); - const std::string first = tokens[0].data; - const std::string second = tokens[2].data; - const uint32_t offset = strtol( - first.substr(command_len, first.length()-command_len).c_str(), - nullptr, - 16); + if (tokens[1].type != TokenType::kHexNumeric) + return Packet::None(); + if (tokens[2].type != TokenType::kSeparatorComma) + return Packet::None(); + if (tokens[3].type != TokenType::kHexNumeric) + return Packet::None(); + const std::string first = tokens[1].data; + const std::string second = tokens[3].data; + const uint32_t offset = strtol(first.c_str(), nullptr, 16); const uint32_t lenght = strtol(second.c_str(), nullptr, 16); return Packet{ PacketType::kReadMemory, @@ -195,6 +184,17 @@ struct Command { { return Packet{PacketType::kStep}; } + static Packet parseSetBreakpoint(const std::vector<Token>&&) + { + return Packet{ + PacketType::kSetBreakpoint, + }; + } + static Packet parseDeleteBreakpoint(const std::vector<Token>&&) + { + // TODO arguments + return Packet{PacketType::kDeleteBreakpoint}; + } }; static const Command commands[] = { @@ -217,25 +217,17 @@ static const Command commands[] = { { "m", Command::parseReadMemory }, { "g", Command::parseReadGeneralRegisters }, { "s", Command::parseStep }, + { "Z", Command::parseSetBreakpoint }, + { "z", Command::parseDeleteBreakpoint }, }; Packet Packet::Parse(std::string packet_data) { - const auto tokens = Token::Tokenize(packet_data); - if (tokens.size() == 0) { - printf("Warning: no tokens to parse\n"); - return Packet::None(); - } - const auto first_token = tokens[0]; for (const auto& command: commands) { const auto cmdlen = command.name.length(); - const auto toklen = first_token.data.length(); - // Make sure first token fully includes the command from the beginning - // and not necessary fully equals to it. - // TODO tokenize as if the command is always a separate token - if (cmdlen <= toklen && 0 == memcmp( - &command.name[0], &first_token.data[0], cmdlen)) - { + const auto packetlen = packet_data.length(); + if (cmdlen <= packetlen && 0 == memcmp(&command.name[0], &packet_data[0], cmdlen)) { + const auto tokens = Token::Tokenize(packet_data, command.name); return command.parse(std::move(tokens)); } } diff --git a/gdbremote_parser.hpp b/gdbremote_parser.hpp index 4f2f8f3..75c9bb7 100644 --- a/gdbremote_parser.hpp +++ b/gdbremote_parser.hpp @@ -61,6 +61,8 @@ enum class PacketType: int { kReadGeneralRegisters, kReadMemory, kStep, + kSetBreakpoint, + kDeleteBreakpoint, }; struct PacketData { @@ -137,6 +139,10 @@ struct Packet { return "m"; case PacketType::kStep: return "s"; + case PacketType::kSetBreakpoint: + return "Z"; + case PacketType::kDeleteBreakpoint: + return "z"; } return "<unknown>"; } |