rizin/librz/debug/p/native/bt.c
مصطفي محمود كمال الدين 29b04fa460
librz/debug: native debugger plugin for RISC-V (#5966)
* added breakpoints and stepping

* add link register to allow single-stepping a ret instruction, fix stacktraces
* refactor to avoid passing the IO layer structs to the breakpoint function
* add tests, refine the stacktrace to not include non-function
* add register information for core file parsing
* core file generation for RISC-V
* make tests run under riscv-64
* make tests run under riscv-32
2026-04-26 16:28:07 +08:00

108 lines
2.5 KiB
C

// SPDX-FileCopyrightText: 2009-2018 pancake <pancake@nopcode.org>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_analysis.h>
#if __WINDOWS__
#include "bt/windows-all.c"
#endif
#include "bt/generic-x86.c"
#include "bt/generic-x64.c"
#include "bt/fuzzy-all.c"
typedef RzList *(*RzDebugFrameCallback)(RzDebug *dbg, ut64 at);
static void prepend_link_register(RzDebug *dbg, RzList /*<RzDebugFrame *>*/ *list) {
bool is_riscv = dbg->arch && !strcmp(dbg->arch, "riscv");
if (!is_riscv)
return;
RzDebugFrame *frame;
const char *pcname;
if (list) {
pcname = rz_reg_get_name(dbg->reg, RZ_REG_NAME_LR);
if (pcname) {
ut64 addr = rz_reg_getv(dbg->reg, pcname);
frame = RZ_NEW0(RzDebugFrame);
frame->addr = addr;
frame->size = 0;
rz_list_prepend(list, frame);
}
}
}
static void prepend_current_pc(RzDebug *dbg, RzList /*<RzDebugFrame *>*/ *list) {
RzDebugFrame *frame;
const char *pcname;
if (list) {
pcname = rz_reg_get_name(dbg->reg, RZ_REG_NAME_PC);
if (pcname) {
ut64 addr = rz_reg_getv(dbg->reg, pcname);
frame = RZ_NEW0(RzDebugFrame);
frame->addr = addr;
frame->size = 0;
rz_list_prepend(list, frame);
}
}
}
#if HAVE_PTRACE
struct frames_proxy_args {
RzDebugFrameCallback cb;
RzDebug *dbg;
ut64 at;
};
static void *backtrace_proxy(void *user) {
struct frames_proxy_args *args = user;
if (args->cb) {
return args->cb(args->dbg, args->at);
}
return NULL;
}
#endif
static RzList /*<RzDebugFrame *>*/ *rz_debug_native_frames(RzDebug *dbg, ut64 at) {
RzDebugFrameCallback cb = NULL;
if (dbg->btalgo) {
if (!strcmp(dbg->btalgo, "fuzzy")) {
cb = backtrace_fuzzy;
} else if (!strcmp(dbg->btalgo, "analysis")) {
if (!strcmp(dbg->arch, "x86")) {
if (dbg->bits == RZ_SYS_BITS_64) {
cb = backtrace_x86_64_analysis;
} else {
cb = backtrace_x86_32_analysis;
}
} else {
eprintf("Analysis backtrace not available for current architecture (%s)\n", dbg->arch);
return NULL;
}
}
}
if (!cb) {
#if __WINDOWS__
cb = backtrace_windows;
#else
if (dbg->bits == RZ_SYS_BITS_64) {
cb = backtrace_x86_64;
} else {
cb = backtrace_x86_32;
}
#endif
}
RzList *list;
if (dbg->btalgo && !strcmp(dbg->btalgo, "trace")) {
list = rz_list_clone(dbg->call_frames);
} else {
#if HAVE_PTRACE
struct frames_proxy_args args = { cb, dbg, at };
list = rz_debug_ptrace_func(dbg, backtrace_proxy, &args);
#else
list = cb(dbg, at);
#endif
}
prepend_link_register(dbg, list);
prepend_current_pc(dbg, list);
return list;
}