Import the debug.evm plugin from radare2-extras ##debug

This commit is contained in:
pancake 2024-02-09 18:58:16 +01:00 committed by GitHub
parent c1c630220d
commit dcdf4be163
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 298 additions and 0 deletions

View File

@ -186,6 +186,7 @@ crypto.serpent
crypto.sm4
crypto.xor
debug.bf
debug.evm
debug.rv32ima
debug.bochs
debug.esil

View File

@ -18,6 +18,7 @@ r_debug_sources = [
#'p/debug_rv32ima.c',
'p/debug_gdb.c',
'p/debug_io.c',
'p/debug_evm.c',
'p/debug_native.c',
'p/debug_null.c',
'p/debug_qnx.c',

281
libr/debug/p/debug_evm.c Normal file
View File

@ -0,0 +1,281 @@
/* 2017 - montekki */
// #include <r_asm.h>
#include <r_debug.h>
typedef struct {
size_t curr_instruction;
ut64 *breakpoints;
size_t breakpoints_capacity;
size_t breakpoints_length;
} RIOEvmState;
typedef struct {
ut8 depth;
ut8 error;
unsigned pc;
unsigned gas;
unsigned gas_cost;
ut8 *memory;
size_t memlength;
ut8 *stack;
size_t stack_length;
char *op;
} RIOEvmOp;
typedef struct {
void *curl;
char *host;
int port;
char *tx;
char *tx_full;
char *tx_to;
char *tx_from;
char *to_code_resp;
char *to_code;
ut8 *code;
size_t code_size;
char *response;
size_t curr_resp_size;
RIOEvmOp *ops;
size_t ops_size;
size_t curr_op;
} RIOEvm;
// XXX remove those globals
static R_TH_LOCAL RIOEvm *rio = NULL;
static R_TH_LOCAL RIOEvmState *rios = NULL;
static bool r_debug_evm_step(RDebug *dbg) {
if (!rio->ops_size || rios->curr_instruction >= rio->ops_size) {
return false;
}
rios->curr_instruction++;
rio->curr_op = rios->curr_instruction;
return true;
}
static RList* r_debug_evm_threads(RDebug *dbg, int pid) {
return NULL;
}
static bool r_debug_evm_reg_read(RDebug *dbg, int type, ut8 *buf, int size) {
if (!rios || !rio || !rio->ops_size) {
return false;
}
((ut16*)(buf))[0] = (ut16)rio->ops[rios->curr_instruction].pc;
((ut16*)(buf))[1] = (ut16)0x8fff;
return true;
}
static RList *r_debug_evm_map_get(RDebug *dbg) {
RList *list;
RDebugMap *map;
if (rio && !rio->ops_size) {
return NULL;
}
list = r_list_new();
map = r_debug_map_new ("code", 0x0000, 0x7FFF, r_str_rwx("rwx"), 0);
r_list_append (list, map);
map = r_debug_map_new ("stack", 0x8FFF, 0xFFFF, r_str_rwx("rwx"), 0);
r_list_append (list, map);
map = r_debug_map_new ("memory", 0x10000, 0x1FFFF, r_str_rwx("rwx"), 0);
r_list_append (list, map);
return list;
}
static bool r_debug_evm_reg_write(RDebug *dbg, int type, const ut8 *buf, int size) {
return false;
}
static ssize_t find_breakpoint(ut64 addr, ut64 *addrs, size_t addrs_len);
static bool r_debug_evm_continue(RDebug *dbg, int pid, int tid, int sig) {
size_t i;
ssize_t bpt_addr;
if (!rio->ops_size) {
return false;
}
bpt_addr = find_breakpoint(rio->ops[rios->curr_instruction].pc,
rios->breakpoints, rios->breakpoints_length);
if (bpt_addr >= 0 && rio->ops[rios->curr_instruction].pc == rios->breakpoints[bpt_addr]) {
rios->curr_instruction++;
}
for (i = rios->curr_instruction; i < rio->ops_size; i++) {
bpt_addr = find_breakpoint(rio->ops[i].pc, rios->breakpoints, rios->breakpoints_length);
if (bpt_addr >= 0) {
rios->curr_instruction = i;
rio->curr_op = rios->curr_instruction;
return true;
}
}
return true;
}
static RDebugReasonType r_debug_evm_wait(RDebug *dbg, int pid) {
return R_DEBUG_REASON_UNKNOWN;
}
#define DEFAULT_BPT_AR_CAPACITY 64
static bool r_debug_evm_attach(RDebug *dbg, int pid) {
RIODesc *d = dbg->iob.io->desc;
if (!rios) {
rios = R_NEW0 (RIOEvmState);
rios->breakpoints = (ut64 *)calloc (sizeof (ut64), DEFAULT_BPT_AR_CAPACITY);
rios->breakpoints_length = 0;
rios->breakpoints_capacity = DEFAULT_BPT_AR_CAPACITY;
}
if (d && d->plugin && d->plugin->meta.name && d->data) {
if (!strcmp ("evm", d->plugin->meta.name)) {
rio = d->data;
}
}
return true;
}
static bool r_debug_evm_detach(RDebug *dbg, int pid) {
return true;
}
static const char *r_debug_evm_reg_profile(RDebug *dbg, int pid) {
return strdup (
"=PC pc\n"
"=SP sp\n"
"gpr pc .16 0 0\n"
"gpr sp .16 2 0\n"
);
}
static ssize_t find_breakpoint(ut64 addr, ut64 *addrs, size_t addrs_len) {
if (addrs_len <= 0) {
return -1;
}
size_t middle = addrs_len / 2;
if (addrs[middle] == addr) {
return middle;
}
if (addrs[middle] < addr) {
return find_breakpoint (addr, addrs + middle + 1, addrs_len - middle - 1);
}
return find_breakpoint (addr, addrs, middle);
}
static int compare_addrs(const void *a1, const void *a2) {
return *(ut64*)a1 - *(ut64*)a2;
}
static int r_debug_evm_breakpoint (struct r_bp_t *bp, RBreakpointItem *b, bool set) {
if (!b || !rio->ops_size) {
return false;
}
if (set) {
ssize_t idx = find_breakpoint(b->addr, rios->breakpoints, rios->breakpoints_length);
if (idx >= 0) {
return true;
}
if (rios->breakpoints_length >= rios->breakpoints_capacity) {
rios->breakpoints = realloc(rios->breakpoints,
rios->breakpoints_capacity + 64);
rios->breakpoints_capacity += 64;
}
rios->breakpoints[rios->breakpoints_length] = b->addr;
rios->breakpoints_length++;
qsort (rios->breakpoints, rios->breakpoints_length, sizeof (ut64), compare_addrs);
} else {
size_t i;
ssize_t idx = find_breakpoint(b->addr, rios->breakpoints, rios->breakpoints_length);
if (idx < 0) {
return false;
}
for (i = idx; i < rios->breakpoints_length - 1; i++) {
rios->breakpoints[i] = rios->breakpoints[i + 1];
}
rios->breakpoints_length -= 1;
}
return true;
}
static bool r_debug_evm_kill(RDebug *dbg, int pid, int tid, int sig) {
return true;
}
static bool r_debug_evm_select(RDebug *dbg, int pid, int tid) {
return true;
}
static RDebugInfo* r_debug_evm_info(RDebug *dbg, const char *arg) {
RDebugInfo *rdi = R_NEW0 (RDebugInfo);
// meh
return rdi;
}
static RList* r_debug_evm_frames(RDebug *dbg, ut64 at) {
return NULL;
}
RDebugPlugin r_debug_plugin_evm = {
.meta = {
.name = "evm",
.license = "LGPL3",
.author = "montekki",
.desc = "evm debugger backend",
},
.arch = "evm",
.bits = R_SYS_BITS_16 | R_SYS_BITS_8,
.step = r_debug_evm_step,
.cont = r_debug_evm_continue,
.attach = &r_debug_evm_attach,
.detach = &r_debug_evm_detach,
.threads = &r_debug_evm_threads,
.canstep = 1,
.wait = &r_debug_evm_wait,
.map_get = r_debug_evm_map_get,
.breakpoint = r_debug_evm_breakpoint,
.reg_read = r_debug_evm_reg_read,
.reg_write = r_debug_evm_reg_write,
.reg_profile = (void *)r_debug_evm_reg_profile,
.kill = &r_debug_evm_kill,
.info = &r_debug_evm_info,
.select = &r_debug_evm_select,
.frames = &r_debug_evm_frames,
};
#ifndef CORELIB
RLibStruct radare_plugin = {
.type = R_LIB_TYPE_DBG,
.data = &r_debug_plugin_evm,
.version = R2_VERSION
};
#endif

14
libr/debug/p/evm.mk Normal file
View File

@ -0,0 +1,14 @@
#LDFLAGS+=-lcurl
#-include ../../global.mk
#-include ../../../global.mk
OBJ_EVM=debug_evm.o
STATIC_OBJ+=${OBJ_EVM}
TARGET_EVM=debug_evm.${LIBEXT}
ALL_TARGETS+=${TARGET_EVM}
${TARGET_EVM}: ${OBJ_EVM}
${CC} $(call libname,debug_evm) ${CFLAGS} -o ${TARGET_EVM} \
${LDFLAGS} ${OBJ_EVM} ${LINKFLAGS}

View File

@ -666,6 +666,7 @@ extern RDebugPlugin r_debug_plugin_bf;
extern RDebugPlugin r_debug_plugin_io;
extern RDebugPlugin r_debug_plugin_winkd;
extern RDebugPlugin r_debug_plugin_windbg;
extern RDebugPlugin r_debug_plugin_evm;
extern RDebugPlugin r_debug_plugin_bochs;
extern RDebugPlugin r_debug_plugin_qnx;
extern RDebugPlugin r_debug_plugin_null;