chore: add spdlog for logging, no early break in check()
This commit is contained in:
parent
645b0f607a
commit
13ded9c314
10 changed files with 62 additions and 24 deletions
|
@ -6,5 +6,7 @@ set(CMAKE_C_STANDARD 17)
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
|
find_package(spdlog REQUIRED)
|
||||||
|
|
||||||
include_directories(include)
|
include_directories(include)
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
|
|
13
difftest.toml
Normal file
13
difftest.toml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# ref = "/home/xin/repo/spike-diff/build/lib/libspike-diff.so"
|
||||||
|
# ref-prefix = "spike_"
|
||||||
|
# dut = "/home/xin/repo/ysyx-workbench/nemu/build/riscv32-nemu-interpreter-so"
|
||||||
|
# dut-prefix = "nemu_"
|
||||||
|
|
||||||
|
ref = /home/xin/repo/ysyx-workbench/nemu/build/riscv32-nemu-interpreter-so
|
||||||
|
ref-prefix = nemu_
|
||||||
|
dut = "/home/xin/repo/spike-diff/build/lib/libspike-diff.so"
|
||||||
|
dut-prefix = "spike_"
|
||||||
|
listen = "/tmp/gdbstub-diffu.sock"
|
||||||
|
# listen = "127.0.0.1:1234"
|
||||||
|
memory = "/nix/store/37986mdgsqm5m8w74k0f5llzqhxgsbnv-am-kernel-riscv32-none-elf-2024-07-10/share/am-kernels/string.bin"
|
||||||
|
# g = true
|
|
@ -112,11 +112,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1721457008,
|
"lastModified": 1721891452,
|
||||||
"narHash": "sha256-ekpve0om5hzC1Ntd3zm1cZ9oS5pnr7a2n/tueyqFOsg=",
|
"narHash": "sha256-2c9nDuXXARzoRXE67lte5kKBeFb1XmTNsvdiIbRUEgE=",
|
||||||
"ref": "refs/heads/master",
|
"ref": "refs/heads/master",
|
||||||
"rev": "e7aa3319d52fa987ac2192f63aef3dcb1b057e3a",
|
"rev": "de8ad578fc4fe527772cec23a7f660bde14c8570",
|
||||||
"revCount": 151,
|
"revCount": 152,
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.xinyang.life/xin/nur.git"
|
"url": "https://git.xinyang.life/xin/nur.git"
|
||||||
},
|
},
|
||||||
|
|
|
@ -38,14 +38,16 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
devShells.default = with pkgs; mkShell {
|
devShells.default = with pkgs; (mkShell.override { stdenv = ccacheStdenv; }) {
|
||||||
inherit (self.checks.${system}.pre-commit-check) shellHook;
|
inherit (self.checks.${system}.pre-commit-check) shellHook;
|
||||||
buildInputs = self.checks.${system}.pre-commit-check.enabledPackages;
|
buildInputs = self.checks.${system}.pre-commit-check.enabledPackages;
|
||||||
packages = [
|
packages = [
|
||||||
clang-tools
|
clang-tools
|
||||||
cmake
|
cmake
|
||||||
|
ninja
|
||||||
gdb
|
gdb
|
||||||
cli11
|
cli11
|
||||||
|
spdlog
|
||||||
mini-gdbstub
|
mini-gdbstub
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,13 +2,12 @@
|
||||||
#define _DIFFTEST_DIFFTEST_H_
|
#define _DIFFTEST_DIFFTEST_H_
|
||||||
#include "api.hpp"
|
#include "api.hpp"
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <stdexcept>
|
#include <spdlog/spdlog.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <gdbstub.h>
|
#include <gdbstub.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
class Difftest {
|
class Difftest {
|
||||||
private:
|
private:
|
||||||
Target dut;
|
Target dut;
|
||||||
|
@ -55,17 +54,22 @@ public:
|
||||||
arch_info_t get_arch() const { return *dut.isa_arch_info; }
|
arch_info_t get_arch() const { return *dut.isa_arch_info; }
|
||||||
|
|
||||||
static bool check(Target &dut, Target &ref) {
|
static bool check(Target &dut, Target &ref) {
|
||||||
|
size_t pcref, pcdut;
|
||||||
|
bool passed = true;
|
||||||
|
dut.ops.read_reg(dut.args.data(), 32, &pcdut);
|
||||||
|
ref.ops.read_reg(ref.args.data(), 32, &pcref);
|
||||||
for (int r = 0; r < dut.isa_arch_info->reg_num; r++) {
|
for (int r = 0; r < dut.isa_arch_info->reg_num; r++) {
|
||||||
size_t regdut = 0, regref = 0;
|
size_t regdut = 0, regref = 0;
|
||||||
dut.ops.read_reg(dut.args.data(), r, ®dut);
|
dut.ops.read_reg(dut.args.data(), r, ®dut);
|
||||||
ref.ops.read_reg(ref.args.data(), r, ®ref);
|
ref.ops.read_reg(ref.args.data(), r, ®ref);
|
||||||
if (regdut != regref) {
|
if (regdut != regref) {
|
||||||
std::cout << "reg: " << r << " dut: " << regdut << " ref: " << regref
|
spdlog::error("Reg {} different: \n\tPC:\t(ref) {:x}\t(dut) {:x}\n\t"
|
||||||
<< std::endl;
|
"value:\t(ref) {:x}\t(dut) {:x}",
|
||||||
throw std::runtime_error("Difftest failed");
|
r, pcref, pcdut, regref, regdut);
|
||||||
|
passed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return passed;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Iterator {
|
class Iterator {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
add_executable(diffu cli.cpp difftest.cpp gdbstub.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 spdlog::spdlog)
|
||||||
install ( TARGETS diffu )
|
install ( TARGETS diffu )
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,9 @@
|
||||||
#include <difftest.hpp>
|
#include <difftest.hpp>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <gdbstub.h>
|
#include <gdbstub.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
Difftest::Difftest(Target &&dut, std::vector<Target> &&refs) {
|
Difftest::Difftest(Target &&dut, std::vector<Target> &&refs) {
|
||||||
this->dut = std::move(dut);
|
this->dut = std::move(dut);
|
||||||
this->refs = std::move(refs);
|
this->refs = std::move(refs);
|
||||||
|
@ -36,6 +35,7 @@ void Difftest::setup(const std::filesystem::path &memory_file) {
|
||||||
for (auto it = this->begin(); it != this->end(); ++it) {
|
for (auto it = this->begin(); it != this->end(); ++it) {
|
||||||
auto &target = *it;
|
auto &target = *it;
|
||||||
target.ops.init(target.args.data());
|
target.ops.init(target.args.data());
|
||||||
|
target.ops.write_reg(target.args.data(), 32, 0x80000000UL);
|
||||||
if (target.ops.write_mem(target.args.data(), 0x80000000UL, membuf.size(),
|
if (target.ops.write_mem(target.args.data(), 0x80000000UL, membuf.size(),
|
||||||
membuf.data()) != 0)
|
membuf.data()) != 0)
|
||||||
throw std::runtime_error("write_mem failed");
|
throw std::runtime_error("write_mem failed");
|
||||||
|
@ -43,10 +43,12 @@ void Difftest::setup(const std::filesystem::path &memory_file) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Difftest::check_all() {
|
bool Difftest::check_all() {
|
||||||
|
bool passed = true;
|
||||||
for (auto &ref : refs) {
|
for (auto &ref : refs) {
|
||||||
check(dut, ref);
|
if (check(dut, ref) == false)
|
||||||
|
passed = false;
|
||||||
}
|
}
|
||||||
return true;
|
return passed;
|
||||||
}
|
}
|
||||||
|
|
||||||
Difftest::ExecRet Difftest::exec(size_t n, gdb_action_t *ret) {
|
Difftest::ExecRet Difftest::exec(size_t n, gdb_action_t *ret) {
|
||||||
|
@ -58,9 +60,12 @@ Difftest::ExecRet Difftest::exec(size_t n, gdb_action_t *ret) {
|
||||||
auto &target = *it;
|
auto &target = *it;
|
||||||
*target.do_difftest = true;
|
*target.do_difftest = true;
|
||||||
target.ops.stepi(target.args.data(), &target.last_res);
|
target.ops.stepi(target.args.data(), &target.last_res);
|
||||||
|
spdlog::trace("{} stepped once", target.meta.name);
|
||||||
if (target.is_on_breakpoint()) {
|
if (target.is_on_breakpoint()) {
|
||||||
exec_ret.at_breakpoint = true;
|
exec_ret.at_breakpoint = true;
|
||||||
pbreak = ⌖
|
pbreak = ⌖
|
||||||
|
spdlog::trace("{} on breakpoint", target.meta.name);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
exec_ret.do_difftest = *target.do_difftest && exec_ret.do_difftest;
|
exec_ret.do_difftest = *target.do_difftest && exec_ret.do_difftest;
|
||||||
}
|
}
|
||||||
|
@ -88,7 +93,10 @@ gdb_action_t Difftest::cont() {
|
||||||
while (!is_halt()) {
|
while (!is_halt()) {
|
||||||
exec_ret = exec(1, &ret);
|
exec_ret = exec(1, &ret);
|
||||||
if (exec_ret.do_difftest)
|
if (exec_ret.do_difftest)
|
||||||
check_all();
|
if (check_all() == false) {
|
||||||
|
ret.reason = gdb_action_t::ACT_BREAKPOINT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (exec_ret.at_breakpoint)
|
if (exec_ret.at_breakpoint)
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
@ -122,6 +130,7 @@ int Difftest::sync_regs_to_ref(void) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
spdlog::trace("Applied registers value from dut to ref");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
#include <CLI/Error.hpp>
|
#include <CLI/Error.hpp>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <difftest.hpp>
|
#include <difftest.hpp>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <gdbstub.h>
|
#include <gdbstub.h>
|
||||||
}
|
|
||||||
|
|
||||||
static void difftest_cont(void *args, gdb_action_t *res) {
|
static void difftest_cont(void *args, gdb_action_t *res) {
|
||||||
Difftest *diff = (Difftest *)args;
|
Difftest *diff = (Difftest *)args;
|
||||||
|
@ -65,6 +65,7 @@ std::vector<std::string> split_into_args(const std::string &command) {
|
||||||
|
|
||||||
static char *gdbstub_monitor(void *args, const char *s) {
|
static char *gdbstub_monitor(void *args, const char *s) {
|
||||||
Difftest *diff = (Difftest *)args;
|
Difftest *diff = (Difftest *)args;
|
||||||
|
spdlog::trace("monitor");
|
||||||
CLI::App parser;
|
CLI::App parser;
|
||||||
std::string ret = "";
|
std::string ret = "";
|
||||||
|
|
||||||
|
@ -110,6 +111,7 @@ static char *gdbstub_monitor(void *args, const char *s) {
|
||||||
return strdup(ret_stream.str().c_str());
|
return strdup(ret_stream.str().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int gdbstub_loop(Difftest *diff, std::string socket_addr) {
|
int gdbstub_loop(Difftest *diff, std::string socket_addr) {
|
||||||
target_ops gdbstub_ops = {.cont = difftest_cont,
|
target_ops gdbstub_ops = {.cont = difftest_cont,
|
||||||
|
@ -124,14 +126,16 @@ int gdbstub_loop(Difftest *diff, std::string socket_addr) {
|
||||||
.monitor = gdbstub_monitor};
|
.monitor = gdbstub_monitor};
|
||||||
gdbstub_t gdbstub_priv;
|
gdbstub_t gdbstub_priv;
|
||||||
|
|
||||||
std::cout << "Waiting for gdb connection at " << socket_addr << std::endl;
|
arch_info_t arch = diff->get_arch();
|
||||||
|
|
||||||
if (!gdbstub_init(&gdbstub_priv, &gdbstub_ops, diff->get_arch(),
|
if (!gdbstub_init(&gdbstub_priv, &gdbstub_ops, arch, nullptr,
|
||||||
socket_addr.c_str())) {
|
socket_addr.c_str())) {
|
||||||
std::cerr << "Failed to init socket at: " << socket_addr << std::endl;
|
spdlog::error("Failed to init socket at: {}", socket_addr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spdlog::info("Connected to gdb at {}", socket_addr);
|
||||||
|
|
||||||
bool success = gdbstub_run(&gdbstub_priv, diff);
|
bool success = gdbstub_run(&gdbstub_priv, diff);
|
||||||
gdbstub_close(&gdbstub_priv);
|
gdbstub_close(&gdbstub_priv);
|
||||||
return !success;
|
return !success;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "api.hpp"
|
#include "api.hpp"
|
||||||
#include <cstdint>
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <gdbstub.h>
|
#include <gdbstub.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
Target::Target(const std::string &name, const std::string &func_prefix,
|
Target::Target(const std::string &name, const std::string &func_prefix,
|
||||||
|
@ -11,16 +11,19 @@ Target::Target(const std::string &name, const std::string &func_prefix,
|
||||||
.libpath = path,
|
.libpath = path,
|
||||||
.dlhandle = dlopen(path.c_str(), RTLD_NOW)};
|
.dlhandle = dlopen(path.c_str(), RTLD_NOW)};
|
||||||
|
|
||||||
|
spdlog::info("Library handle: {}", meta.dlhandle);
|
||||||
if (!meta.dlhandle) {
|
if (!meta.dlhandle) {
|
||||||
throw std::runtime_error(dlerror());
|
throw std::runtime_error(dlerror());
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LOAD_SYMBOL(ops, handle, prefix, name) \
|
#define LOAD_SYMBOL(ops, handle, prefix, name) \
|
||||||
do { \
|
do { \
|
||||||
|
std::string symbol_name = func_prefix + #name; \
|
||||||
(ops).name = reinterpret_cast<decltype((ops).name)>( \
|
(ops).name = reinterpret_cast<decltype((ops).name)>( \
|
||||||
dlsym((handle), ((prefix) + #name).c_str())); \
|
dlsym((handle), symbol_name.c_str())); \
|
||||||
if (!((ops).name)) \
|
if (!((ops).name)) \
|
||||||
goto load_error; \
|
goto load_error; \
|
||||||
|
spdlog::debug("Found {} at {}", symbol_name, ((void *)((ops).name))); \
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
LOAD_SYMBOL(ops, meta.dlhandle, func_prefix, cont);
|
LOAD_SYMBOL(ops, meta.dlhandle, func_prefix, cont);
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
#include "api.hpp"
|
#include "api.hpp"
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "difftest.hpp"
|
#include "difftest.hpp"
|
||||||
|
#include <spdlog/cfg/env.h>
|
||||||
|
|
||||||
int gdbstub_loop(Difftest *, std::string);
|
int gdbstub_loop(Difftest *, std::string);
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
spdlog::cfg::load_env_levels();
|
||||||
Config config;
|
Config config;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
ret = config.cli_parse(argc, argv);
|
ret = config.cli_parse(argc, argv);
|
||||||
|
|
Loading…
Reference in a new issue