From 15d14d36fc7ac30cdbde8c2a78e901ba2c47e94d Mon Sep 17 00:00:00 2001 From: Oxore Date: Sun, 2 Oct 2022 00:49:39 +0300 Subject: Impl setting registers via GDB --- gdbremote_parser.cpp | 113 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 83 insertions(+), 30 deletions(-) (limited to 'gdbremote_parser.cpp') diff --git a/gdbremote_parser.cpp b/gdbremote_parser.cpp index 2c13668..8d70370 100644 --- a/gdbremote_parser.cpp +++ b/gdbremote_parser.cpp @@ -15,19 +15,21 @@ enum class TokenType: uint8_t { kSeparatorComma, kSeparatorColon, kSeparatorSemicolon, + kSeparatorEquals, kHexNumeric, kArbitrary, }; static inline bool isseparator(uint8_t byte) { - return ':' == byte || ';' == byte || ',' == byte; + return ':' == byte || ';' == byte || ',' == byte || '=' == byte; } static inline TokenType separatorTypeFromByte(uint8_t byte) { if (':' == byte) return TokenType::kSeparatorColon; if (';' == byte) return TokenType::kSeparatorSemicolon; + if ('=' == byte) return TokenType::kSeparatorEquals; return TokenType::kSeparatorComma; } @@ -49,6 +51,7 @@ struct Token { for (; i < packet_data.length(); i++) { assert(type != TokenType::kSeparatorColon); assert(type != TokenType::kSeparatorSemicolon); + assert(type != TokenType::kSeparatorEquals); assert(type != TokenType::kSeparatorComma); const uint8_t byte = packet_data[i]; if (isseparator(byte)) { @@ -90,48 +93,48 @@ static std::string DecodeBinaryHex(const std::string& data_hex) struct Command { std::string name; - Packet (*parse)(const std::vector&&); - static Packet parseNone(const std::vector&&) + Packet (*parse)(std::vector&&); + static Packet parseNone(std::vector&&) { return Packet::None(); } - static Packet parseQuerySupported(const std::vector&&) + static Packet parseQuerySupported(std::vector&&) { // TODO arguments return Packet{PacketType::kQuerySupported}; } - static Packet parseQueryHaltReason(const std::vector&&) + static Packet parseQueryHaltReason(std::vector&&) { return Packet{PacketType::kQueryHaltReason}; } - static Packet parseQueryC(const std::vector&&) + static Packet parseQueryC(std::vector&&) { // TODO arguments return Packet{PacketType::kQueryC}; } - static Packet parseQueryFThreadInfo(const std::vector&&) + static Packet parseQueryFThreadInfo(std::vector&&) { return Packet{PacketType::kQueryFThreadInfo}; } - static Packet parseQuerySThreadInfo(const std::vector&&) + static Packet parseQuerySThreadInfo(std::vector&&) { return Packet{PacketType::kQuerySThreadInfo}; } - static Packet parseQueryRTOSThreadInfo(const std::vector&&) + static Packet parseQueryRTOSThreadInfo(std::vector&&) { // TODO arguments return Packet{PacketType::kQueryRTOSThreadInfo}; } - static Packet parseQueryAttached(const std::vector&&) + static Packet parseQueryAttached(std::vector&&) { // TODO arguments return Packet{PacketType::kQueryAttached}; } - static Packet parseQueryTraceStatus(const std::vector&&) + static Packet parseQueryTraceStatus(std::vector&&) { return Packet{PacketType::kQueryTraceStatus}; } - static Packet parseQueryRcmd(const std::vector&& tokens) + static Packet parseQueryRcmd(std::vector&& tokens) { if (tokens.size() < 3) return Packet::None(); @@ -140,40 +143,38 @@ struct Command { if (tokens[2].type != TokenType::kHexNumeric) return Packet::None(); const std::string& data_encoded = tokens[2].data; - const std::string data = DecodeBinaryHex(data_encoded); - printf("%s\n", data.c_str()); return Packet{ PacketType::kQueryRcmd, - std::make_unique(std::move(data)), + std::make_unique(std::move(DecodeBinaryHex(data_encoded))), }; } - static Packet parseQStartNoAckMode(const std::vector&&) + static Packet parseQStartNoAckMode(std::vector&&) { return Packet{PacketType::kQStartNoAckMode}; } - static Packet parseSetThreadForCont(const std::vector&&) + static Packet parseSetThreadForCont(std::vector&&) { // TODO arguments return Packet{PacketType::kSetThreadForCont}; } - static Packet parseSetThreadForOps(const std::vector&&) + static Packet parseSetThreadForOps(std::vector&&) { // TODO arguments return Packet{PacketType::kSetThreadForOps}; } - static Packet parseMustReplyEmpty(const std::vector&&) + static Packet parseMustReplyEmpty(std::vector&&) { return Packet{PacketType::kVMustReplyEmpty}; } - static Packet parseEnableExtendedMode(const std::vector&&) + static Packet parseEnableExtendedMode(std::vector&&) { return Packet{PacketType::kEnableExtendedMode}; } - static Packet parseInterrupt(const std::vector&&) + static Packet parseInterrupt(std::vector&&) { return Packet{PacketType::kInterrupt}; } - static Packet parseContinueVCont(const std::vector&& tokens) + static Packet parseContinueVCont(std::vector&& tokens) { const std::string first_arg = tokens.size() > 1 ? tokens[1].data : ""; // Check if it is "vCont?" command @@ -183,11 +184,11 @@ struct Command { // TODO arguments return Packet{PacketType::kContinue}; } - static Packet parseContinue(const std::vector&&) + static Packet parseContinue(std::vector&&) { return Packet{PacketType::kContinue}; } - static Packet parseReadMemory(const std::vector&& tokens) + static Packet parseReadMemory(std::vector&& tokens) { if (tokens.size() < 4) return Packet::None(); @@ -207,7 +208,7 @@ struct Command { std::make_unique(offset, lenght), }; } - static Packet parseWriteMemory(const std::vector&& tokens) + static Packet parseWriteMemory(std::vector&& tokens) { if (tokens.size() < 6) return Packet::None(); @@ -239,15 +240,65 @@ struct Command { std::make_unique(offset, lenght, std::move(data)), }; } - static Packet parseReadGeneralRegisters(const std::vector&&) + static Packet parseReadGeneralRegisters(std::vector&&) { return Packet{PacketType::kReadGeneralRegisters}; } - static Packet parseStep(const std::vector&&) + static Packet parseWriteGeneralRegisters(std::vector&& tokens) + { + if (tokens.size() < 2) + return Packet::None(); + if (tokens[1].type != TokenType::kHexNumeric) + return Packet::None(); + const std::string& first = tokens[1].data; + constexpr size_t value_str_size = std::string_view("12345678").length(); + std::vector registers(first.length()/value_str_size); + for (size_t i = 0; i < first.length()/value_str_size; i++) { + const std::string value_str(first.substr(i * value_str_size, value_str_size)); + registers[i] = strtol(value_str.c_str(), nullptr, 16); + } + return Packet{ + PacketType::kWriteGeneralRegisters, + std::make_unique(std::move(registers)), + }; + } + static Packet parseReadRegister(std::vector&& tokens) + { + if (tokens.size() < 2) + return Packet::None(); + if (tokens[1].type != TokenType::kHexNumeric) + return Packet::None(); + const std::string& first = tokens[1].data; + const uint32_t reg_id = strtol(first.c_str(), nullptr, 16); + return Packet{ + PacketType::kReadRegister, + std::make_unique(reg_id), + }; + } + static Packet parseWriteRegister(std::vector&& tokens) + { + if (tokens.size() < 4) + return Packet::None(); + if (tokens[1].type != TokenType::kHexNumeric) + return Packet::None(); + if (tokens[2].type != TokenType::kSeparatorEquals) + 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 reg_id = strtol(first.c_str(), nullptr, 16); + const uint32_t value = strtol(second.c_str(), nullptr, 16); + return Packet{ + PacketType::kWriteRegister, + std::make_unique(reg_id, value), + }; + } + static Packet parseStep(std::vector&&) { return Packet{PacketType::kStep}; } - static Packet parseSetOrDeleteBreakpoint(const std::vector&& tokens) + static Packet parseSetOrDeleteBreakpoint(std::vector&& tokens) { if (tokens.size() < 6) return Packet::None(); @@ -302,6 +353,9 @@ static const Command commands[] = { { "m", Command::parseReadMemory }, { "M", Command::parseWriteMemory }, { "g", Command::parseReadGeneralRegisters }, + { "G", Command::parseWriteGeneralRegisters }, + { "p", Command::parseReadRegister }, + { "P", Command::parseWriteRegister }, { "s", Command::parseStep }, { "Z", Command::parseSetOrDeleteBreakpoint }, { "z", Command::parseSetOrDeleteBreakpoint }, @@ -313,8 +367,7 @@ Packet Packet::Parse(std::string packet_data) const auto cmdlen = command.name.length(); 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)); + return command.parse(std::move(Token::Tokenize(packet_data, command.name))); } } return Packet::None(); -- cgit v1.2.3