mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-30 08:30:53 +00:00
* Integrate backtrace into the debugging backend
* Add 'dcs' command to continue until syscall - Need syscall analysis * Some tips for future enhacements in r_search
This commit is contained in:
parent
1219a2ae40
commit
a74926c6d0
@ -2076,6 +2076,7 @@ static int cmd_debug(void *data, const char *input) {
|
||||
" dc? show this help\n"
|
||||
" dc continue execution of all childs\n"
|
||||
" dcu [addr] continue until address\n"
|
||||
" dcs [num] continue until syscall\n"
|
||||
" dck [sig] [pid] continue sending kill 9 to process\n"
|
||||
" dc [pid] continue execution of pid\n"
|
||||
" dc[-pid] stop execution of pid\n"
|
||||
@ -2093,6 +2094,12 @@ static int cmd_debug(void *data, const char *input) {
|
||||
r_debug_select (&core->dbg, old_pid, old_pid);
|
||||
} else r_debug_continue_kill (&core->dbg, atoi (input+2));
|
||||
break;
|
||||
case 's':
|
||||
sig = r_num_math (&core->num, input+2);
|
||||
eprintf ("Continue until syscall %d\n", sig);
|
||||
r_debug_continue_syscall (&core->dbg, sig);
|
||||
/* TODO : use r_syscall here, to retrieve syscall info */
|
||||
break;
|
||||
case 'u':
|
||||
addr = r_num_math (&core->num, input+2);
|
||||
eprintf ("Continue until 0x%08llx\n", addr);
|
||||
|
@ -1,80 +0,0 @@
|
||||
#include <r_debug.h>
|
||||
|
||||
#define MAXBT 128
|
||||
|
||||
// TODO: r_reg typedef must be renamed to this shorter version
|
||||
#define RReg RRegister
|
||||
|
||||
/* TODO: Can I use this as in a coroutine? */
|
||||
static RList *backtrace_i386(RIOBind *bio, RReg *reg) {
|
||||
ut32 i, esp, ebp2;
|
||||
ut8 buf[4];
|
||||
ut32 _esp = r_reg_get_value (reg, r_reg_get (reg, "esp", R_REG_TYPE_GPR));
|
||||
RList *list = r_list_new ();
|
||||
list->free = free;
|
||||
// TODO: implement [stack] map uptrace method too
|
||||
esp = _esp;
|
||||
for (i=0; i<MAXBT; i++) {
|
||||
bio->read_at (bio->io, esp, (void *)&ebp2, 4);
|
||||
*buf = '\0';
|
||||
bio->read_at (bio->io, (ebp2-5)-(ebp2-5)%4, (void *)&buf, 4);
|
||||
|
||||
// TODO: arch_is_call() here and this fun will be portable
|
||||
if (buf[(ebp2-5)%4]==0xe8) {
|
||||
RDebugFrame *frame = R_NEW (RDebugFrame);
|
||||
frame->addr = ebp2;
|
||||
frame->size = esp-_esp;
|
||||
r_list_append (list, frame);
|
||||
eprintf ("ADDR: 0x%08x, SIZE: 0x%x\n", ebp2, esp-_esp);
|
||||
}
|
||||
esp += 4;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
// XXX: Do this work correctly?
|
||||
static RList *backtrace_x86_64(RIOBind *bio, RReg *reg) {
|
||||
int i;
|
||||
ut8 buf[4];
|
||||
ut64 ptr, ebp2;
|
||||
ut64 _rip = r_reg_get_value (reg, r_reg_get (reg, "rip", R_REG_TYPE_GPR));
|
||||
ut64 _rsp = r_reg_get_value (reg, r_reg_get (reg, "rsp", R_REG_TYPE_GPR));
|
||||
ut64 _rbp = r_reg_get_value (reg, r_reg_get (reg, "rbp", R_REG_TYPE_GPR));
|
||||
RList *list = r_list_new ();
|
||||
list->free = free;
|
||||
|
||||
bio->read_at (bio->io, _rip, &buf, 4);
|
||||
|
||||
/*
|
||||
%ebp points to the old ebp var
|
||||
%ebp+4 points to ret
|
||||
*/
|
||||
/* Handle before function prelude: push %ebp ; mov %esp, %ebp */
|
||||
if (!memcmp (buf, "\x55\x89\xe5", 3) || !memcmp (buf, "\x89\xe5\x57", 3)) {
|
||||
if (bio->read_at (bio->io, _rsp, &ptr, 4) != 4) {
|
||||
eprintf ("read error at 0x%08llx\n", _rsp);
|
||||
return R_FALSE;
|
||||
}
|
||||
eprintf ("ADDR: 0x%08llx\n", ptr); // TODO: size!
|
||||
_rbp = ptr;
|
||||
}
|
||||
|
||||
for (i=1; i<MAXBT; i++) {
|
||||
// TODO: make those two reads in a shot
|
||||
bio->read_at (bio->io, _rbp, &ebp2, 4);
|
||||
bio->read_at (bio->io, _rbp+4, &ptr, 4);
|
||||
if (ptr == 0x0 || _rbp == 0x0)
|
||||
break;
|
||||
eprintf ("ADDR: 0x%08llx\n", ptr);
|
||||
_rbp = ebp2;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
R_API RList *r_debug_frames (RDebug *dbg) {
|
||||
//if (dbg->bits == 64) {
|
||||
// return backtrace_x86_64 (dbg->bio, dbg->reg) {
|
||||
//} else {
|
||||
return backtrace_i386 (&dbg->iob, dbg->reg);
|
||||
//}
|
||||
}
|
@ -199,9 +199,9 @@ R_API int r_debug_continue_kill(struct r_debug_t *dbg, int sig) {
|
||||
int ret = R_FALSE;
|
||||
if (dbg && dbg->h && dbg->h->cont) {
|
||||
r_bp_restore (dbg->bp, R_FALSE); // set sw breakpoints
|
||||
ret = dbg->h->cont(dbg->pid, sig);
|
||||
ret = dbg->h->cont (dbg->pid, sig);
|
||||
if (dbg->h->wait)
|
||||
ret = dbg->h->wait(dbg->pid);
|
||||
ret = dbg->h->wait (dbg->pid);
|
||||
r_bp_restore (dbg->bp, R_TRUE); // unset sw breakpoints
|
||||
r_debug_recoil (dbg);
|
||||
}
|
||||
@ -241,10 +241,8 @@ R_API int r_debug_kill(struct r_debug_t *dbg, int sig) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// TODO: move into r_debug
|
||||
// TODO: we need to know the arch backend, frame size,
|
||||
// TODO: merge algorithms from r1 (do we need ebp?)
|
||||
// TODO: must return a linked list or r_iter
|
||||
R_API int r_anal_backtrace(struct r_anal_t *anal, const ut8 *buf, ut64 esp) {
|
||||
return R_FALSE;
|
||||
R_API RList *r_debug_frames (RDebug *dbg) {
|
||||
if (dbg && dbg->h && dbg->h->frames)
|
||||
return dbg->h->frames (dbg);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -58,8 +58,7 @@ R_API int r_debug_map_sync(RDebug *dbg) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
R_API int r_debug_map_alloc(RDebug *dbg, RDebugMap *map)
|
||||
{
|
||||
R_API int r_debug_map_alloc(RDebug *dbg, RDebugMap *map) {
|
||||
int ret = R_FALSE;
|
||||
if (dbg->h && dbg->h->map_alloc) {
|
||||
if (dbg->h->map_alloc (dbg, map)) {
|
||||
@ -70,8 +69,7 @@ R_API int r_debug_map_alloc(RDebug *dbg, RDebugMap *map)
|
||||
return ret;
|
||||
}
|
||||
|
||||
R_API int r_debug_map_dealloc(RDebug *dbg, RDebugMap *map)
|
||||
{
|
||||
R_API int r_debug_map_dealloc(RDebug *dbg, RDebugMap *map) {
|
||||
int ret = R_FALSE;
|
||||
ut64 addr = map->addr;
|
||||
if (dbg->h && dbg->h->map_dealloc)
|
||||
@ -82,6 +80,7 @@ R_API int r_debug_map_dealloc(RDebug *dbg, RDebugMap *map)
|
||||
//r_debug_map_free (map);
|
||||
return ret;
|
||||
}
|
||||
|
||||
R_API RDebugMap *r_debug_map_get(RDebug *dbg, ut64 addr) {
|
||||
RDebugMap *ret = NULL;
|
||||
RListIter *iter = r_list_iterator (dbg->maps);
|
||||
@ -95,22 +94,19 @@ R_API RDebugMap *r_debug_map_get(RDebug *dbg, ut64 addr) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
R_API void r_debug_map_free(RDebugMap *map)
|
||||
{
|
||||
R_API void r_debug_map_free(RDebugMap *map) {
|
||||
//r_list_unlink (dbg->maps_user, map);
|
||||
free (map->name);
|
||||
free (map);
|
||||
}
|
||||
|
||||
R_API RList *r_debug_map_list_new()
|
||||
{
|
||||
R_API RList *r_debug_map_list_new() {
|
||||
RList *list = r_list_new ();
|
||||
list->free = r_debug_map_free;
|
||||
return list;
|
||||
}
|
||||
|
||||
R_API void r_debug_map_list_free(RList *maps)
|
||||
{
|
||||
R_API void r_debug_map_list_free(RList *maps) {
|
||||
RListIter *iter = r_list_iterator (maps);
|
||||
while (r_list_iter_next (iter)) {
|
||||
RDebugMap *map = r_list_iter_get (iter);
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <signal.h>
|
||||
|
||||
#define DEBUGGER 1
|
||||
#define MAXBT 128
|
||||
|
||||
#if __WINDOWS__
|
||||
#include <windows.h>
|
||||
@ -570,9 +571,89 @@ static int r_debug_native_bp_read(int pid, ut64 addr, int hw, int rwx) {
|
||||
return R_TRUE;
|
||||
}
|
||||
#endif
|
||||
#if __i386__
|
||||
/* TODO: Can I use this as in a coroutine? */
|
||||
static RList *r_debug_native_frames(RDebug *dbg) {
|
||||
RRegister *reg = dbg->reg;
|
||||
ut32 i, _esp, esp, ebp2;
|
||||
ut8 buf[4];
|
||||
RList *list = r_list_new ();
|
||||
RIOBind *bio = &dbg->iob;
|
||||
|
||||
static int r_debug_get_arch()
|
||||
{
|
||||
list->free = free;
|
||||
_esp = r_reg_get_value (reg, r_reg_get (reg, "esp", R_REG_TYPE_GPR));
|
||||
// TODO: implement [stack] map uptrace method too
|
||||
esp = _esp;
|
||||
for (i=0; i<MAXBT; i++) {
|
||||
bio->read_at (bio->io, esp, (void *)&ebp2, 4);
|
||||
*buf = '\0';
|
||||
bio->read_at (bio->io, (ebp2-5)-(ebp2-5)%4, (void *)&buf, 4);
|
||||
|
||||
// TODO: arch_is_call() here and this fun will be portable
|
||||
if (buf[(ebp2-5)%4]==0xe8) {
|
||||
RDebugFrame *frame = R_NEW (RDebugFrame);
|
||||
frame->addr = ebp2;
|
||||
frame->size = esp-_esp;
|
||||
r_list_append (list, frame);
|
||||
}
|
||||
esp += 4;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
#elif __x86_64__
|
||||
// XXX: Do this work correctly?
|
||||
static RList *r_debug_native_frames(RDebug *dbg) {
|
||||
int i;
|
||||
ut8 buf[4];
|
||||
ut64 ptr, ebp2;
|
||||
ut64 _rip, _rsp, _rbp;
|
||||
RList *list;
|
||||
RRegister *reg = dbg->reg;
|
||||
RIOBind *bio = &dbg->iob;
|
||||
|
||||
_rip = r_reg_get_value (reg, r_reg_get (reg, "rip", R_REG_TYPE_GPR));
|
||||
_rsp = r_reg_get_value (reg, r_reg_get (reg, "rsp", R_REG_TYPE_GPR));
|
||||
_rbp = r_reg_get_value (reg, r_reg_get (reg, "rbp", R_REG_TYPE_GPR));
|
||||
|
||||
list = r_list_new ();
|
||||
list->free = free;
|
||||
bio->read_at (bio->io, _rip, &buf, 4);
|
||||
/* %rbp=old rbp, %rbp+4 points to ret */
|
||||
/* Handle before function prelude: push %rbp ; mov %rsp, %rbp */
|
||||
if (!memcmp (buf, "\x55\x89\xe5", 3) || !memcmp (buf, "\x89\xe5\x57", 3)) {
|
||||
if (bio->read_at (bio->io, _rsp, &ptr, 4) != 4) {
|
||||
eprintf ("read error at 0x%08llx\n", _rsp);
|
||||
return R_FALSE;
|
||||
}
|
||||
RDebugFrame *frame = R_NEW (RDebugFrame);
|
||||
frame->addr = ptr;
|
||||
frame->size = 0; // TODO ?
|
||||
r_list_append (list, frame);
|
||||
|
||||
_rbp = ptr;
|
||||
}
|
||||
|
||||
for (i=1; i<MAXBT; i++) {
|
||||
// TODO: make those two reads in a shot
|
||||
bio->read_at (bio->io, _rbp, &ebp2, 4);
|
||||
bio->read_at (bio->io, _rbp+4, &ptr, 4);
|
||||
if (ptr == 0x0 || _rbp == 0x0)
|
||||
break;
|
||||
|
||||
RDebugFrame *frame = R_NEW (RDebugFrame);
|
||||
frame->addr = ptr;
|
||||
frame->size = 0; // TODO ?
|
||||
r_list_append (list, frame);
|
||||
|
||||
_rbp = ebp2;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
#else
|
||||
#warning Backtrace frames not implemented for this platform
|
||||
#endif
|
||||
|
||||
static int r_debug_get_arch() {
|
||||
#if __i386__ || __x86_64__
|
||||
return R_ASM_ARCH_X86;
|
||||
#elif __powerpc__ || __POWERPC__
|
||||
@ -618,6 +699,7 @@ struct r_debug_handle_t r_debug_plugin_native = {
|
||||
.detach = &r_debug_native_detach,
|
||||
.wait = &r_debug_native_wait,
|
||||
.kill = &r_debug_native_kill,
|
||||
.frames = &r_debug_native_frames,
|
||||
.get_arch = &r_debug_get_arch,
|
||||
.reg_profile = (void *)&r_debug_native_reg_profile,
|
||||
.reg_read = &r_debug_native_reg_read,
|
||||
|
@ -9,39 +9,33 @@ R_API int r_debug_pid_list(struct r_debug_t *dbg)
|
||||
}
|
||||
|
||||
/* processes */
|
||||
R_API int r_debug_pid_parent(RDebugPid *pid)
|
||||
{
|
||||
R_API int r_debug_pid_parent(RDebugPid *pid) {
|
||||
// fork in child
|
||||
return 0;
|
||||
}
|
||||
|
||||
R_API int r_debug_pid_del(struct r_debug_t *dbg)
|
||||
{
|
||||
R_API int r_debug_pid_del(struct r_debug_t *dbg) {
|
||||
// kill da child
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
/* threads */
|
||||
R_API int r_debug_pid_add_thread(struct r_debug_t *dbg)
|
||||
{
|
||||
R_API int r_debug_pid_add_thread(struct r_debug_t *dbg) {
|
||||
// create a thread in process
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
R_API int r_debug_pid_del_thread(struct r_debug_t *dbg)
|
||||
{
|
||||
R_API int r_debug_pid_del_thread(struct r_debug_t *dbg) {
|
||||
// kill a thread in process
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
/* status */
|
||||
R_API int r_debug_pid_set_state(struct r_debug_t *dbg, int status)
|
||||
{
|
||||
R_API int r_debug_pid_set_state(struct r_debug_t *dbg, int status) {
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
/* status */
|
||||
R_API struct r_debug_pid_t *r_debug_pid_get_status(struct r_debug_t *dbg, int pid)
|
||||
{
|
||||
R_API struct r_debug_pid_t *r_debug_pid_get_status(struct r_debug_t *dbg, int pid) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -83,6 +83,7 @@ typedef struct r_debug_handle_t {
|
||||
int (*wait)(int pid);
|
||||
int (*kill)(RDebug *dbg, int sig);
|
||||
int (*contsc)(int pid, int sc);
|
||||
RList* (*frames)(RDebug *dbg);
|
||||
/* registers */
|
||||
RBreakpointCallback breakpoint;
|
||||
int (*reg_read)(struct r_debug_t *dbg, int type, ut8 *buf, int size);
|
||||
@ -165,6 +166,9 @@ R_API ut64 r_debug_reg_get(struct r_debug_t *dbg, const char *name);
|
||||
R_API void r_debug_io_bind(RDebug *dbg, RIO *io);
|
||||
R_API ut64 r_debug_execute(struct r_debug_t *dbg, ut8 *buf, int len);
|
||||
R_API int r_debug_map_sync(RDebug *dbg);
|
||||
|
||||
/* backtrace */
|
||||
R_API RList *r_debug_frames (RDebug *dbg);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -87,6 +87,9 @@ R_API ut8* r_reg_get_bytes(struct r_reg_t *reg, int type, int *size);
|
||||
R_API int r_reg_set_bytes(struct r_reg_t *reg, int type, const ut8* buf, int len);
|
||||
R_API RRegisterArena *r_reg_arena_new (int size);
|
||||
R_API int r_reg_fit_arena(struct r_reg_t *reg);
|
||||
|
||||
// TODO: r_reg typedef must be renamed to this shorter version
|
||||
#define RReg RRegister
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -2,5 +2,7 @@
|
||||
- We must think on a way to do it more algoritmically
|
||||
* Add support for stepped searchs (skip N bytes after every read)
|
||||
* Allow to enable/disable nested hits
|
||||
* Define minimum distance between hits
|
||||
* Enable/Disable chained hits
|
||||
* Added support for negated searchs (find until no keyword matches)
|
||||
- useful to find the end of a \xff block
|
||||
|
@ -12,8 +12,7 @@ static char *encodings[3] = { "ascii", "cp850", NULL };
|
||||
//static int encoding = ENCODING_ASCII; // default
|
||||
//encoding = resolve_encoding(config_get("cfg.encoding"));
|
||||
|
||||
R_API int r_search_get_encoding(const char *name)
|
||||
{
|
||||
R_API int r_search_get_encoding(const char *name) {
|
||||
int i;
|
||||
if (name != NULL)
|
||||
for(i=0;encodings[i];i++)
|
||||
@ -22,13 +21,12 @@ R_API int r_search_get_encoding(const char *name)
|
||||
return ENCODING_ASCII;
|
||||
}
|
||||
|
||||
static int is_encoded(int encoding, unsigned char c)
|
||||
{
|
||||
switch(encoding) {
|
||||
static int is_encoded(int encoding, unsigned char c) {
|
||||
switch (encoding) {
|
||||
case ENCODING_ASCII:
|
||||
break;
|
||||
case ENCODING_CP850:
|
||||
switch(c) {
|
||||
switch (c) {
|
||||
// CP850
|
||||
case 128: // cedilla
|
||||
case 133: // a grave
|
||||
|
Loading…
Reference in New Issue
Block a user