feat: export gdbstub api, connect to gdb
This commit is contained in:
parent
cac75f1698
commit
5de642f998
8 changed files with 136 additions and 9 deletions
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
64
src/gdbstub.cpp
Normal file
64
src/gdbstub.cpp
Normal 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;
|
||||||
|
}
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue