feat: export gdbstub api, connect to gdb

This commit is contained in:
xinyangli 2024-07-16 09:50:17 +08:00
parent cac75f1698
commit 5de642f998
Signed by: xin
SSH key fingerprint: SHA256:qZ/tzd8lYRtUFSrfBDBMcUqV4GHKxqeqRA3huItgvbk
8 changed files with 136 additions and 9 deletions

View file

@ -3,10 +3,13 @@
#include <cstddef> #include <cstddef>
#include <filesystem> #include <filesystem>
#include <gdbstub.h>
#include <string> #include <string>
#include <vector> #include <vector>
extern "C" {
#include <gdbstub.h>
}
// Target dynamic library has to implement these functions // Target dynamic library has to implement these functions
struct DiffTargetApi { struct DiffTargetApi {
typedef void (*cont_t)(void *args, gdb_action_t *res); typedef void (*cont_t)(void *args, gdb_action_t *res);

View file

@ -2,9 +2,11 @@
#define _DIFFTEST_DIFFTEST_H_ #define _DIFFTEST_DIFFTEST_H_
#include "api.hpp" #include "api.hpp"
#include <filesystem> #include <filesystem>
#include <gdbstub.h>
#include <stdexcept> #include <stdexcept>
#include <vector> #include <vector>
extern "C" {
#include <gdbstub.h>
}
#include <iostream> #include <iostream>
class Difftest { class Difftest {
@ -12,12 +14,30 @@ private:
Target dut; Target dut;
std::vector<Target> refs; std::vector<Target> refs;
// target used for read_reg, write_reg, read_mem, write_mem
Target *current_target = &dut;
public: public:
Difftest(Target &&dut, std::vector<Target> &&refs); Difftest(Target &&dut, std::vector<Target> &&refs);
void setup(const std::filesystem::path &memory_file); void setup(const std::filesystem::path &memory_file);
gdb_action_t stepi();
// Export API for gdbstub
gdb_action_t cont(); 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) { static bool check(Target &dut, Target &ref) {
for (int r = 0; r < dut.arch.reg_num; r++) { for (int r = 0; r < dut.arch.reg_num; r++) {
size_t regdut = 0, regref = 0; size_t regdut = 0, regref = 0;

View file

@ -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) target_link_libraries(diffu PRIVATE gdbstub)
set_target_properties(diffu PROPERTIES ENABLE_EXPORTS 1)

View file

@ -72,8 +72,6 @@ gdb_action_t Difftest::stepi() {
gdb_action_t Difftest::cont() { gdb_action_t Difftest::cont() {
bool breakflag = false; bool breakflag = false;
Target *pbreak; Target *pbreak;
check_all();
std::cerr << "setup finished." << std::endl;
while (true) { while (true) {
// for(auto &target : *this) { // for(auto &target : *this) {
for (auto it = this->begin(); it != this->end(); ++it) { 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}; 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;
}

View file

64
src/gdbstub.cpp Normal file
View file

@ -0,0 +1,64 @@
#include <difftest.hpp>
extern "C" {
#include <gdbstub.h>
}
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;
}

View file

@ -50,6 +50,7 @@ Target::Target(const std::string &name, const std::string &func_prefix,
reinterpret_cast<arch_info_t *>(dlsym(meta.dlhandle, "isa_arch_info")); reinterpret_cast<arch_info_t *>(dlsym(meta.dlhandle, "isa_arch_info"));
if (!arch_sym) if (!arch_sym)
goto load_error; goto load_error;
arch = *arch_sym;
return; return;
load_error: load_error:

View file

@ -2,6 +2,9 @@
#include "config.hpp" #include "config.hpp"
#include "difftest.hpp" #include "difftest.hpp"
// extern "C" {
int gdbstub_loop(Difftest *);
// }
int main(int argc, char **argv) { int main(int argc, char **argv) {
Config config; Config config;
int ret = 0; int ret = 0;
@ -16,8 +19,8 @@ int main(int argc, char **argv) {
} }
Difftest difftest{std::move(dut), std::move(refs)}; Difftest difftest{std::move(dut), std::move(refs)};
difftest.setup(config.memory_file);
difftest.cont(); gdbstub_loop(&difftest);
return 0; return 0;
} }