From 5de642f998594ad043b63ff35df46b05a36922fe Mon Sep 17 00:00:00 2001 From: xinyangli Date: Tue, 16 Jul 2024 09:50:17 +0800 Subject: [PATCH] feat: export gdbstub api, connect to gdb --- include/api.hpp | 5 +++- include/difftest.hpp | 24 +++++++++++++++-- src/CMakeLists.txt | 3 +-- src/difftest.cpp | 41 ++++++++++++++++++++++++++-- src/export.cpp | 0 src/gdbstub.cpp | 64 ++++++++++++++++++++++++++++++++++++++++++++ src/loader.cpp | 1 + src/main.cpp | 7 +++-- 8 files changed, 136 insertions(+), 9 deletions(-) delete mode 100644 src/export.cpp create mode 100644 src/gdbstub.cpp diff --git a/include/api.hpp b/include/api.hpp index 8c0461c..ed19fd0 100644 --- a/include/api.hpp +++ b/include/api.hpp @@ -3,10 +3,13 @@ #include #include -#include #include #include +extern "C" { +#include +} + // Target dynamic library has to implement these functions struct DiffTargetApi { typedef void (*cont_t)(void *args, gdb_action_t *res); diff --git a/include/difftest.hpp b/include/difftest.hpp index e4fbdd2..7a12776 100644 --- a/include/difftest.hpp +++ b/include/difftest.hpp @@ -2,9 +2,11 @@ #define _DIFFTEST_DIFFTEST_H_ #include "api.hpp" #include -#include #include #include +extern "C" { +#include +} #include class Difftest { @@ -12,12 +14,30 @@ private: Target dut; std::vector refs; + // target used for read_reg, write_reg, read_mem, write_mem + Target *current_target = &dut; + public: Difftest(Target &&dut, std::vector &&refs); void setup(const std::filesystem::path &memory_file); - gdb_action_t stepi(); + + // Export API for gdbstub gdb_action_t cont(); + gdb_action_t stepi(); + int read_reg(int regno, size_t *value); + int write_reg(int regno, size_t value); + int read_mem(size_t addr, size_t len, void *val); + int write_mem(size_t addr, size_t len, void *val); + bool set_bp(size_t addr, bp_type_t type); + bool del_bp(size_t addr, bp_type_t type); + + arch_info_t get_arch() const { + std::cout << dut.arch.reg_num << std::endl; + return dut.arch; + } + + // Other APi static bool check(Target &dut, Target &ref) { for (int r = 0; r < dut.arch.reg_num; r++) { size_t regdut = 0, regref = 0; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e30dab7..696b8e9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,3 +1,2 @@ -add_executable(diffu cli.cpp difftest.cpp loader.cpp main.cpp) +add_executable(diffu cli.cpp difftest.cpp gdbstub.cpp loader.cpp main.cpp) target_link_libraries(diffu PRIVATE gdbstub) -set_target_properties(diffu PROPERTIES ENABLE_EXPORTS 1) diff --git a/src/difftest.cpp b/src/difftest.cpp index cb6aaf3..024ac2c 100644 --- a/src/difftest.cpp +++ b/src/difftest.cpp @@ -72,8 +72,6 @@ gdb_action_t Difftest::stepi() { gdb_action_t Difftest::cont() { bool breakflag = false; Target *pbreak; - check_all(); - std::cerr << "setup finished." << std::endl; while (true) { // for(auto &target : *this) { for (auto it = this->begin(); it != this->end(); ++it) { @@ -96,3 +94,42 @@ gdb_action_t Difftest::cont() { } return {gdb_action_t::ACT_NONE, 0}; } + +int Difftest::read_reg(int regno, size_t *value) { + std::cout << "read_reg(" << regno << ", " << value << ")" << std::endl; + return current_target->ops.read_reg(current_target->args.data(), regno, + value); +} + +int Difftest::write_reg(int regno, size_t value) { + return current_target->ops.write_reg(current_target->args.data(), regno, + value); +} + +int Difftest::read_mem(size_t addr, size_t len, void *val) { + return current_target->ops.read_mem(current_target->args.data(), addr, len, + val); +} + +int Difftest::write_mem(size_t addr, size_t len, void *val) { + return current_target->ops.write_mem(current_target->args.data(), addr, len, + val); +} + +bool Difftest::set_bp(size_t addr, bp_type_t type) { + bool ret = true; + for (auto it = this->begin(); it != this->end(); ++it) { + auto &target = *it; + ret = ret && target.ops.set_bp(target.args.data(), addr, type); + } + return ret; +} + +bool Difftest::del_bp(size_t addr, bp_type_t type) { + bool ret = true; + for (auto it = this->begin(); it != this->end(); ++it) { + auto &target = *it; + ret = ret && target.ops.del_bp(target.args.data(), addr, type); + } + return ret; +} diff --git a/src/export.cpp b/src/export.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/gdbstub.cpp b/src/gdbstub.cpp new file mode 100644 index 0000000..a9c9b8d --- /dev/null +++ b/src/gdbstub.cpp @@ -0,0 +1,64 @@ +#include +extern "C" { +#include +} + +static void difftest_cont(void *args, gdb_action_t *res) { + Difftest *diff = (Difftest *)args; + *res = diff->cont(); +}; + +static void difftest_stepi(void *args, gdb_action_t *res) { + Difftest *diff = (Difftest *)args; + *res = diff->stepi(); +}; + +static int difftest_read_reg(void *args, int regno, size_t *value) { + Difftest *diff = (Difftest *)args; + return diff->read_reg(regno, value); +}; + +static int difftest_write_reg(void *args, int regno, size_t value) { + Difftest *diff = (Difftest *)args; + return diff->write_reg(regno, value); +} + +static int difftest_read_mem(void *args, size_t addr, size_t len, void *val) { + Difftest *diff = (Difftest *)args; + return diff->read_mem(addr, len, val); +} + +static int difftest_write_mem(void *args, size_t addr, size_t len, void *val) { + Difftest *diff = (Difftest *)args; + return diff->write_mem(addr, len, val); +} + +static bool difftest_set_bp(void *args, size_t addr, bp_type_t type) { + Difftest *diff = (Difftest *)args; + return diff->set_bp(addr, type); +} + +static bool difftest_del_bp(void *args, size_t addr, bp_type_t type) { + Difftest *diff = (Difftest *)args; + return diff->del_bp(addr, type); +} + +int gdbstub_loop(Difftest *diff) { + target_ops gdbstub_ops = {.cont = difftest_cont, + .stepi = difftest_stepi, + .read_reg = difftest_read_reg, + .write_reg = difftest_write_reg, + .read_mem = difftest_read_mem, + .write_mem = difftest_write_mem, + .set_bp = difftest_set_bp, + .del_bp = difftest_del_bp, + .on_interrupt = NULL}; + gdbstub_t gdbstub_priv; + char socket_addr[] = "127.0.0.1:1234"; + gdbstub_init(&gdbstub_priv, &gdbstub_ops, diff->get_arch(), socket_addr); + + bool success = gdbstub_run(&gdbstub_priv, diff); + std::cout << "Waiting for gdb connection at " << socket_addr; + gdbstub_close(&gdbstub_priv); + return !success; +} \ No newline at end of file diff --git a/src/loader.cpp b/src/loader.cpp index 2378ca2..2289076 100644 --- a/src/loader.cpp +++ b/src/loader.cpp @@ -50,6 +50,7 @@ Target::Target(const std::string &name, const std::string &func_prefix, reinterpret_cast(dlsym(meta.dlhandle, "isa_arch_info")); if (!arch_sym) goto load_error; + arch = *arch_sym; return; load_error: diff --git a/src/main.cpp b/src/main.cpp index 2379e9c..4fbb945 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,6 +2,9 @@ #include "config.hpp" #include "difftest.hpp" +// extern "C" { +int gdbstub_loop(Difftest *); +// } int main(int argc, char **argv) { Config config; int ret = 0; @@ -16,8 +19,8 @@ int main(int argc, char **argv) { } Difftest difftest{std::move(dut), std::move(refs)}; - difftest.setup(config.memory_file); - difftest.cont(); + + gdbstub_loop(&difftest); return 0; }