summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt10
-rw-r--r--gdbremote_parser.cpp78
-rw-r--r--gdbremote_parser.hpp6
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>";
}