rizin/librz/debug/p/debug_io.c
2024-11-08 18:46:13 +08:00

168 lines
3.6 KiB
C

// SPDX-FileCopyrightText: 2016-2018 pancake <pancake@nopcode.org>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_io.h>
#include <rz_debug.h>
#define IO_MAPS_PERM_SZ 32
#define IO_MAPS_NAME_SZ 512
static bool __io_step(RzDebug *dbg) {
free(dbg->iob.system(dbg->iob.io, "ds"));
return true;
}
static bool __io_step_over(RzDebug *dbg) {
free(dbg->iob.system(dbg->iob.io, "dso"));
return true;
}
static RzList /*<RzDebugMap *>*/ *__io_maps(RzDebug *dbg) {
RzList *list = rz_list_new();
char *str = dbg->iob.system(dbg->iob.io, "dm");
if (!str) {
rz_list_free(list);
return NULL;
}
char *ostr = str;
ut64 map_start, map_end;
char perm[IO_MAPS_PERM_SZ + 1];
char name[IO_MAPS_NAME_SZ + 1];
for (;;) {
char *nl = strchr(str, '\n');
if (nl) {
*nl = 0;
*name = 0;
*perm = 0;
map_start = map_end = 0LL;
if (!strncmp(str, "sys ", 4)) {
char *sp = strchr(str + 4, ' ');
if (sp) {
str = sp + 1;
} else {
str += 4;
}
}
char *_s_ = strstr(str, " s ");
if (_s_) {
memmove(_s_, _s_ + 2, strlen(_s_));
}
_s_ = strstr(str, " ? ");
if (_s_) {
memmove(_s_, _s_ + 2, strlen(_s_));
}
sscanf(str, "0x%" PFMT64x " - 0x%" PFMT64x " %" RZ_STR_DEF(IO_MAPS_PERM_SZ) "s %" RZ_STR_DEF(IO_MAPS_NAME_SZ) "s",
&map_start, &map_end, perm, name);
if (map_end != 0LL) {
RzDebugMap *map = rz_debug_map_new(name, map_start, map_end, rz_str_rwx(perm), 0);
rz_list_append(list, map);
}
str = nl + 1;
} else {
break;
}
}
free(ostr);
rz_cons_reset();
return list;
}
static RzDebugReasonType __io_wait(RzDebug *dbg, int pid) {
/* do nothing */
return RZ_DEBUG_REASON_NONE;
}
static int __io_attach(RzDebug *dbg, int pid) {
return true;
}
// "drp" register profile
static char *__io_reg_profile(RzDebug *dbg) {
rz_cons_push();
char *drp = dbg->iob.system(dbg->iob.io, "drp");
if (drp) {
return drp;
}
char *buf = rz_cons_get_buffer_dup();
if (RZ_STR_ISNOTEMPTY(buf)) {
rz_cons_pop();
return buf;
}
free(buf);
rz_cons_pop();
return rz_analysis_get_reg_profile(dbg->analysis);
}
// "dr8" read register state
static int __reg_read(RzDebug *dbg, int type, ut8 *buf, int size) {
char *dr8 = dbg->iob.system(dbg->iob.io, "dr8");
if (!dr8) {
char *fb = rz_cons_get_buffer_dup();
if (RZ_STR_ISEMPTY(fb)) {
free(fb);
eprintf("debug.io: Failed to get dr8 from io\n");
return -1;
}
dr8 = fb;
rz_cons_reset();
}
ut8 *bregs = calloc(1, strlen(dr8));
if (!bregs) {
free(dr8);
return -1;
}
rz_str_trim((char *)bregs);
int sz = rz_hex_str2bin(dr8, bregs);
if (sz > 0) {
memcpy(buf, bregs, RZ_MIN(size, sz));
free(bregs);
free(dr8);
return size;
} else {
// eprintf ("SIZE %d (%s)\n", sz, regs);
}
free(bregs);
free(dr8);
return -1;
}
// "dc" continue execution
static int __io_continue(RzDebug *dbg, int pid, int tid, int sig) {
dbg->iob.system(dbg->iob.io, "dc");
rz_cons_flush();
return true;
}
// "dk" send kill signal
static bool __io_kill(RzDebug *dbg, int pid, int tid, int sig) {
char tmpbuf[32];
const char *cmd = rz_strf(tmpbuf, "dk %d", sig);
dbg->iob.system(dbg->iob.io, cmd);
rz_cons_flush();
return true;
}
RzDebugPlugin rz_debug_plugin_io = {
.name = "io",
.license = "MIT",
.arch = "any", // TODO: exception!
.bits = RZ_SYS_BITS_32 | RZ_SYS_BITS_64,
.step = __io_step,
.map_get = __io_maps,
.attach = &__io_attach,
.wait = &__io_wait,
.reg_read = __reg_read,
.cont = __io_continue,
.kill = __io_kill,
.reg_profile = __io_reg_profile,
.step_over = __io_step_over,
.canstep = 1,
};
#ifndef RZ_PLUGIN_INCORE
RZ_API RzLibStruct rizin_plugin = {
.type = RZ_LIB_TYPE_DBG,
.data = &rz_debug_plugin_io,
.version = RZ_VERSION
};
#endif