summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2022-08-30 00:22:07 +0300
committerOxore <oxore@protonmail.com>2022-08-30 00:22:07 +0300
commit026894023fa53fa32fd342d18e05f55743cf6c4b (patch)
treeba744e909c5e8c8067f535d4dcac1d295f55e228
parent8c012736814265e198d68654ccdc597c265f4f82 (diff)
Convince GDB that it is connected
-rw-r--r--CMakeLists.txt4
-rw-r--r--gdbremote.cpp23
-rw-r--r--gdbremote_parser.cpp61
-rw-r--r--gdbremote_parser.hpp11
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
*