diff options
author | Oxore <oxore@protonmail.com> | 2022-08-30 00:22:07 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2022-08-30 00:22:07 +0300 |
commit | 026894023fa53fa32fd342d18e05f55743cf6c4b (patch) | |
tree | ba744e909c5e8c8067f535d4dcac1d295f55e228 | |
parent | 8c012736814265e198d68654ccdc597c265f4f82 (diff) |
Convince GDB that it is connected
-rw-r--r-- | CMakeLists.txt | 4 | ||||
-rw-r--r-- | gdbremote.cpp | 23 | ||||
-rw-r--r-- | gdbremote_parser.cpp | 61 | ||||
-rw-r--r-- | gdbremote_parser.hpp | 11 |
4 files changed, 72 insertions, 27 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c5bc39..e5240aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,9 +10,9 @@ set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_EXPORT_COMPILE_COMMANDS True) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -pedantic") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer -O1") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-nested-anon-types") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-nested-anon-types -Wall -Wextra -pedantic") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -fno-rtti") # Speed up compilation -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer -O1") set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer") set(emulator_sources diff --git a/gdbremote.cpp b/gdbremote.cpp index a093192..eb0fed8 100644 --- a/gdbremote.cpp +++ b/gdbremote.cpp @@ -56,6 +56,24 @@ static int setup_socket(uint16_t port) return socket_fd; } +static std::string CreateResponse(const GDBRemote::Packet& packet) +{ + using namespace GDBRemote; + if (0) { + } else if (packet.type == PacketType::kQueryHaltReason) { + return "S05"; + } else if (packet.type == PacketType::kSetThreadForCont) { + return "OK"; + } else if (packet.type == PacketType::kQueryAttached) { + return "1"; + } else if (packet.type == PacketType::kInterrupt) { + return "OK"; + } else if (packet.type == PacketType::kReadGeneralRegisters) { + return std::string(2*4*17, '0') + "00000200"; // 17 registers + PC + } + return ""; +} + int main(int argc, char *argv[]) { const int port = argc > 1 ? atoi(argv[1]) : 3333; @@ -94,9 +112,8 @@ int main(int argc, char *argv[]) } if (res->packet.length() > 0) { const auto packet = GDBRemote::Packet::Parse(res->packet); - - (void) packet; - const auto response = exchange_ctx.WrapDataToSend(); + const auto response = + exchange_ctx.WrapDataToSend(CreateResponse(packet)); printf("-> \"%s\"\n", response.c_str()); if (send(conn_fd, &response[0], response.length(), 0) == -1) perror("Send failed (response)"); diff --git a/gdbremote_parser.cpp b/gdbremote_parser.cpp index eb2e29a..d8f4f50 100644 --- a/gdbremote_parser.cpp +++ b/gdbremote_parser.cpp @@ -40,8 +40,8 @@ struct Token { if (packet_data.length() == 0) return std::vector<Token>{}; std::vector<Token> tokens{}; TokenType type{}; - size_t i, offset; - for (i = 0, offset = 0; i < packet_data.length(); i++) { + size_t i{}, offset{}; + for (; i < packet_data.length(); i++) { assert(type != TokenType::kSeparatorColon); assert(type != TokenType::kSeparatorSemicolon); assert(type != TokenType::kSeparatorComma); @@ -96,6 +96,7 @@ struct Command { } static Packet parseQueryC(const std::vector<Token>&&) { + // TODO arguments return Packet{PacketType::kQueryC}; } static Packet parseQueryFThreadInfo(const std::vector<Token>&&) @@ -113,6 +114,7 @@ struct Command { } static Packet parseQueryAttached(const std::vector<Token>&&) { + // TODO arguments return Packet{PacketType::kQueryAttached}; } static Packet parseQueryTraceStatus(const std::vector<Token>&&) @@ -137,6 +139,18 @@ struct Command { { return Packet{PacketType::kEnableExtendedMode}; } + static Packet parseInterrupt(const std::vector<Token>&&) + { + return Packet{PacketType::kInterrupt}; + } + static Packet parseContinue(const std::vector<Token>&&) + { + return Packet{PacketType::kContinue}; + } + static Packet parseReadGeneralRegisters(const std::vector<Token>&&) + { + return Packet{PacketType::kReadGeneralRegisters}; + } }; static const Command commands[] = { @@ -152,6 +166,10 @@ static const Command commands[] = { { "Hg", Command::parseSetThreadForOps }, { "vMustReplyEmpty", Command::parseMustReplyEmpty }, { "!", Command::parseEnableExtendedMode }, + { "\x03", Command::parseInterrupt }, + { "vCtrlC", Command::parseInterrupt }, + { "vCont", Command::parseContinue }, + { "g", Command::parseReadGeneralRegisters }, }; Packet Packet::Parse(std::string packet_data) @@ -190,6 +208,9 @@ std::unique_ptr<ExchangeResult> ExchangeContext::Consume(uint8_t byte) case ParsingState::kIdle: if (byte == '$') { transit(ParsingState::kPacketData); + } else if (byte == 0x03) { + _last_packet = std::string(1, 0x03); + return ExchangeResult::Ack(_last_packet); } break; case ParsingState::kPacketData: @@ -236,26 +257,24 @@ std::unique_ptr<ExchangeResult> ExchangeContext::Consume(uint8_t byte) return nullptr; } -std::string ExchangeContext::WrapDataToSend(Packet packet) -{ - switch (packet.type) { - case PacketType::kNone: - case PacketType::kVMustReplyEmpty: - case PacketType::kQuerySupported: - case PacketType::kQueryHaltReason: - case PacketType::kQueryC: - case PacketType::kQueryFThreadInfo: - case PacketType::kQuerySThreadInfo: - case PacketType::kQueryRTOSThreadInfo: - case PacketType::kQueryAttached: - case PacketType::kQueryTraceStatus: - case PacketType::kSetThreadForCont: - case PacketType::kSetThreadForOps: - case PacketType::kEnableExtendedMode: - return "$#00"; - break; +static inline uint8_t CalcPacketDataChecksum(std::string packet) { + uint8_t checksum{}; + for (const auto c: packet) { + checksum = (checksum + c) & 0xff; } - return std::string{}; + return checksum; +} + +std::string ExchangeContext::WrapDataToSend(std::string packet) +{ + const uint8_t checksum = CalcPacketDataChecksum(packet); + const uint8_t c1 = (checksum >> 4) & 0x0f; + const uint8_t c2 = checksum& 0x0f; + const char checksum_str[2] = { + static_cast<char>(c1 < 0xa ? c1 + '0' : c1 + ('a' - 0xa)), + static_cast<char>(c2 < 0xa ? c2 + '0' : c2 + ('a' - 0xa)), + }; + return "$" + packet + "#" + std::string(checksum_str, 2); } void ExchangeContext::transit(ParsingState new_state) diff --git a/gdbremote_parser.hpp b/gdbremote_parser.hpp index 6bf37bd..2e9fd88 100644 --- a/gdbremote_parser.hpp +++ b/gdbremote_parser.hpp @@ -55,6 +55,9 @@ enum class PacketType: int { kSetThreadForOps, kVMustReplyEmpty, kEnableExtendedMode, + kInterrupt, + kContinue, + kReadGeneralRegisters, }; struct PacketData { @@ -111,6 +114,12 @@ struct Packet { return "vMustReplyEmpty"; case PacketType::kEnableExtendedMode: return "!"; + case PacketType::kInterrupt: + return "vCtrlC"; + case PacketType::kContinue: + return "vCont"; + case PacketType::kReadGeneralRegisters: + return "g"; } return "<unknown>"; } @@ -152,7 +161,7 @@ public: * (i.e. '+' or '-'). Otherwise we will be unable to resend packet in case * if '-' negative acknowledge is received. */ - std::string WrapDataToSend(Packet packet=Packet{}); + std::string WrapDataToSend(std::string packet=std::string{}); /** Returns last recognized packet * |