* Major unfinished refactoring for r_debug and r_bp
- radare2 debugger is now broken - r_reg has grown a bit more - Better separation of debugger elements * r_bp now has r_bp_add_hw and r_bp_add_sw() calls - Added minimal support for breakpoint handlers - Import th0rpe's watchpoint expression parser engine * iob moved from r_debug to r_bp * Arch types has been moved into r_asm - Soft compile time dependency * Update pkg-config .pc files
This commit is contained in:
parent
669ce0a815
commit
91ad40d663
|
@ -6,7 +6,7 @@ CFLAGS+=-DCORELIB
|
|||
include ../config.mk
|
||||
include ${STATIC_BP_PLUGINS}
|
||||
STATIC_OBJS=$(subst ..,p/..,$(subst bp_,p/bp_,$(STATIC_OBJ)))
|
||||
OBJ=bp.o ${STATIC_OBJS}
|
||||
OBJ=bp.o handle.o ${STATIC_OBJS}
|
||||
|
||||
pre:
|
||||
if [ ! -e libr_bp.so ]; then rm -f ${STATIC_OBJS} ; fi
|
||||
|
|
159
libr/bp/bp.c
159
libr/bp/bp.c
|
@ -11,6 +11,7 @@ R_API int r_bp_init(struct r_bp_t *bp)
|
|||
int i;
|
||||
bp->nbps = 0;
|
||||
bp->cur = NULL;
|
||||
bp->stepcont = R_BP_CONT_NORMAL;
|
||||
INIT_LIST_HEAD(&bp->bps);
|
||||
INIT_LIST_HEAD(&bp->plugins);
|
||||
for(i=0;bp_static_plugins[i];i++)
|
||||
|
@ -21,48 +22,18 @@ R_API int r_bp_init(struct r_bp_t *bp)
|
|||
R_API struct r_bp_t *r_bp_new()
|
||||
{
|
||||
struct r_bp_t *bp = MALLOC_STRUCT(struct r_bp_t);
|
||||
r_bp_init(bp);
|
||||
if (bp) r_bp_init(bp);
|
||||
return bp;
|
||||
}
|
||||
|
||||
R_API int r_bp_handle_del(struct r_bp_t *bp, const char *name)
|
||||
R_API struct r_bp_t *r_bp_free(struct r_bp_t *bp)
|
||||
{
|
||||
#warning TODO: r_bp_handle_del
|
||||
return R_FALSE;
|
||||
/* XXX : properly destroy bp list */
|
||||
free(bp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
R_API int r_bp_handle_add(struct r_bp_t *bp, struct r_bp_handle_t *foo)
|
||||
{
|
||||
struct list_head *pos;
|
||||
if (bp == NULL) {
|
||||
eprintf("Cannot add plugin because dbg->bp is null and/or handle is null\n");
|
||||
return R_FALSE;
|
||||
}
|
||||
/* avoid dupped plugins */
|
||||
list_for_each_prev(pos, &bp->bps) {
|
||||
struct r_bp_handle_t *h = list_entry(pos, struct r_bp_handle_t, list);
|
||||
if (!strcmp(h->name, foo->name))
|
||||
return R_FALSE;
|
||||
}
|
||||
bp->nbps++;
|
||||
list_add_tail(&(foo->list), &(bp->plugins));
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
R_API int r_bp_handle_set(struct r_bp_t *bp, const char *name)
|
||||
{
|
||||
struct list_head *pos;
|
||||
list_for_each_prev(pos, &bp->plugins) {
|
||||
struct r_bp_handle_t *h = list_entry(pos, struct r_bp_handle_t, list);
|
||||
if (!strcmp(h->name, name)) {
|
||||
bp->cur = h;
|
||||
return R_TRUE;
|
||||
}
|
||||
}
|
||||
return R_FALSE;
|
||||
}
|
||||
|
||||
R_API int r_bp_getbytes(struct r_bp_t *bp, ut8 *buf, int len, int endian, int idx)
|
||||
R_API int r_bp_get_bytes(struct r_bp_t *bp, ut8 *buf, int len, int endian, int idx)
|
||||
{
|
||||
int i;
|
||||
struct r_bp_arch_t *b;
|
||||
|
@ -82,36 +53,7 @@ R_API int r_bp_getbytes(struct r_bp_t *bp, ut8 *buf, int len, int endian, int id
|
|||
return R_FALSE;
|
||||
}
|
||||
|
||||
R_API int r_bp_set_trace(struct r_bp_t *bp, ut64 addr, int set)
|
||||
{
|
||||
struct list_head *pos;
|
||||
struct r_bp_item_t *b;
|
||||
list_for_each(pos, &bp->bps) {
|
||||
b = list_entry(pos, struct r_bp_item_t, list);
|
||||
if (addr >= b->addr && addr <= b->addr+b->size) {
|
||||
b->trace = set;
|
||||
return R_TRUE;
|
||||
}
|
||||
}
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
R_API int r_bp_set_trace_bp(struct r_bp_t *bp, ut64 addr, int set)
|
||||
{
|
||||
bp->trace_all = set;
|
||||
bp->trace_bp = addr;
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
R_API struct r_bp_t *r_bp_free(struct r_bp_t *bp)
|
||||
{
|
||||
/* XXX : properly destroy bp list */
|
||||
free(bp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO: rename this method!
|
||||
R_API int r_bp_in(struct r_bp_t *bp, ut64 addr, int rwx)
|
||||
R_API int r_bp_at_addr(struct r_bp_t *bp, ut64 addr, int rwx)
|
||||
{
|
||||
struct list_head *pos;
|
||||
struct r_bp_item_t *b;
|
||||
|
@ -141,12 +83,32 @@ R_API struct r_bp_item_t *r_bp_enable(struct r_bp_t *bp, ut64 addr, int set)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
R_API int r_bp_stepy_continuation(struct r_bp_t *bp)
|
||||
{
|
||||
// TODO: implement
|
||||
return bp->stepcont;
|
||||
}
|
||||
|
||||
R_API int r_bp_add_cond(struct r_bp_t *bp, const char *cond)
|
||||
{
|
||||
// TODO: implement contitional breakpoints
|
||||
bp->stepcont = R_TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
R_API int r_bp_del_cond(struct r_bp_t *bp, int idx)
|
||||
{
|
||||
// add contitional
|
||||
bp->stepcont = R_FALSE;
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
/* TODO: detect overlapping of breakpoints */
|
||||
R_API struct r_bp_item_t *r_bp_add(struct r_bp_t *bp, const ut8 *obytes, ut64 addr, int size, int hw, int rwx)
|
||||
static struct r_bp_item_t *r_bp_add(struct r_bp_t *bp, const ut8 *obytes, ut64 addr, int size, int hw, int rwx)
|
||||
{
|
||||
int ret;
|
||||
struct r_bp_item_t *b;
|
||||
if (r_bp_in(bp, addr, rwx)) {
|
||||
if (r_bp_at_addr(bp, addr, rwx)) {
|
||||
eprintf("Breakpoint already set at this address.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -154,12 +116,14 @@ R_API struct r_bp_item_t *r_bp_add(struct r_bp_t *bp, const ut8 *obytes, ut64 ad
|
|||
b->pids[0] = 0; /* for any pid */
|
||||
b->addr = addr;
|
||||
b->size = size;
|
||||
b->enabled = 1;
|
||||
b->obytes = malloc(size);
|
||||
b->enabled = R_TRUE;
|
||||
b->bbytes = malloc(size+16);
|
||||
memcpy(b->obytes, obytes, size);
|
||||
if (obytes) {
|
||||
b->obytes = malloc(size);
|
||||
memcpy(b->obytes, obytes, size);
|
||||
} else b->obytes = NULL;
|
||||
/* XXX: endian always in little ?!?!? */
|
||||
ret = r_bp_getbytes(bp, b->bbytes, size, 0, 0);
|
||||
ret = r_bp_get_bytes(bp, b->bbytes, size, 0, 0);
|
||||
if (ret == R_FALSE) {
|
||||
fprintf(stderr, "Cannot get breakpoint bytes. No r_bp_set()?\n");
|
||||
free (b->bbytes);
|
||||
|
@ -173,6 +137,26 @@ R_API struct r_bp_item_t *r_bp_add(struct r_bp_t *bp, const ut8 *obytes, ut64 ad
|
|||
return b;
|
||||
}
|
||||
|
||||
R_API struct r_bp_item_t *r_bp_add_sw(struct r_bp_t *bp, ut64 addr, int size, int rwx)
|
||||
{
|
||||
struct r_bp_item_t *item;
|
||||
ut8 *bytes;
|
||||
bytes = malloc(size);
|
||||
if (bytes == NULL)
|
||||
return NULL;
|
||||
if (bp->iob.read_at) {
|
||||
bp->iob.read_at(bp->iob.io, addr, bytes, size);
|
||||
} else memset(bytes, 0, size);
|
||||
item = r_bp_add(bp, bytes, addr, size, R_BP_TYPE_SW, rwx);
|
||||
free(bytes);
|
||||
return item;
|
||||
}
|
||||
|
||||
R_API struct r_bp_item_t *r_bp_add_hw(struct r_bp_t *bp, ut64 addr, int size, int rwx)
|
||||
{
|
||||
return r_bp_add(bp, NULL, addr, size, R_BP_TYPE_HW, rwx);
|
||||
}
|
||||
|
||||
R_API int r_bp_del(struct r_bp_t *bp, ut64 addr)
|
||||
{
|
||||
struct list_head *pos;
|
||||
|
@ -187,21 +171,33 @@ R_API int r_bp_del(struct r_bp_t *bp, ut64 addr)
|
|||
return R_FALSE;
|
||||
}
|
||||
|
||||
R_API void r_bp_handle_list(struct r_bp_t *bp)
|
||||
// TODO: rename or drop?
|
||||
R_API int r_bp_set_trace(struct r_bp_t *bp, ut64 addr, int set)
|
||||
{
|
||||
struct r_bp_handle_t *b;
|
||||
struct list_head *pos;
|
||||
list_for_each(pos, &bp->plugins) {
|
||||
b = list_entry(pos, struct r_bp_handle_t, list);
|
||||
if (bp->cur && !strcmp(bp->cur->name, b->name))
|
||||
printf(" * %s\n", b->name);
|
||||
else printf(" - %s\n", b->name);
|
||||
|
||||
struct r_bp_item_t *b;
|
||||
list_for_each(pos, &bp->bps) {
|
||||
b = list_entry(pos, struct r_bp_item_t, list);
|
||||
if (addr >= b->addr && addr <= b->addr+b->size) {
|
||||
b->trace = set;
|
||||
return R_TRUE;
|
||||
}
|
||||
}
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
// TODO: rename or remove
|
||||
R_API int r_bp_set_trace_bp(struct r_bp_t *bp, ut64 addr, int set)
|
||||
{
|
||||
bp->trace_all = set;
|
||||
bp->trace_bp = addr;
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
// TODO: deprecate
|
||||
R_API int r_bp_list(struct r_bp_t *bp, int rad)
|
||||
{
|
||||
int n = 0;
|
||||
struct r_bp_item_t *b;
|
||||
struct list_head *pos;
|
||||
eprintf("Breakpoint list:\n");
|
||||
|
@ -216,6 +212,7 @@ R_API int r_bp_list(struct r_bp_t *bp, int rad)
|
|||
b->trace?"trace":"break",
|
||||
b->enabled?"enabled":"disabled");
|
||||
/* TODO: Show list of pids and trace points, conditionals */
|
||||
n++;
|
||||
}
|
||||
return 0;
|
||||
return n;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/* radare - LGPL - Copyright 2009 pancake<nopcode.org> */
|
||||
|
||||
#include <r_bp.h>
|
||||
|
||||
R_API int r_bp_handle_del(struct r_bp_t *bp, const char *name)
|
||||
{
|
||||
#warning TODO: r_bp_handle_del
|
||||
return R_FALSE;
|
||||
}
|
||||
|
||||
R_API int r_bp_handle_add(struct r_bp_t *bp, struct r_bp_handle_t *foo)
|
||||
{
|
||||
struct list_head *pos;
|
||||
if (bp == NULL) {
|
||||
eprintf("Cannot add plugin because dbg->bp is null and/or handle is null\n");
|
||||
return R_FALSE;
|
||||
}
|
||||
/* avoid dupped plugins */
|
||||
list_for_each_prev(pos, &bp->bps) {
|
||||
struct r_bp_handle_t *h = list_entry(pos, struct r_bp_handle_t, list);
|
||||
if (!strcmp(h->name, foo->name))
|
||||
return R_FALSE;
|
||||
}
|
||||
bp->nbps++;
|
||||
list_add_tail(&(foo->list), &(bp->plugins));
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
R_API int r_bp_handle_set(struct r_bp_t *bp, const char *name)
|
||||
{
|
||||
struct list_head *pos;
|
||||
list_for_each_prev(pos, &bp->plugins) {
|
||||
struct r_bp_handle_t *h = list_entry(pos, struct r_bp_handle_t, list);
|
||||
if (!strcmp(h->name, name)) {
|
||||
bp->cur = h;
|
||||
return R_TRUE;
|
||||
}
|
||||
}
|
||||
return R_FALSE;
|
||||
}
|
||||
|
||||
// TODO: deprecate
|
||||
R_API void r_bp_handle_list(struct r_bp_t *bp)
|
||||
{
|
||||
struct r_bp_handle_t *b;
|
||||
struct list_head *pos;
|
||||
list_for_each(pos, &bp->plugins) {
|
||||
b = list_entry(pos, struct r_bp_handle_t, list);
|
||||
printf(" %c %s\n",
|
||||
(bp->cur && !strcmp(bp->cur->name, b->name))?'*':'-',
|
||||
b->name);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
#include <r_bp.h>
|
||||
|
||||
// TODO: rename from r_debug_ ...
|
||||
R_API int r_debug_bp_enable(struct r_debug_t *dbg, ut64 addr, int set)
|
||||
{
|
||||
struct r_bp_item_t *bp = r_bp_enable(dbg->bp, addr, set);
|
||||
struct r_io_bind_t *iob;
|
||||
if (bp) {
|
||||
iob = &dbg->bp->iob;
|
||||
iob->set_fd(iob->io, dbg->pid); // HUH?
|
||||
if (set) iob->write_at(iob->io, addr, bp->bbytes, bp->size);
|
||||
else iob->write_at(iob->io, addr, bp->obytes, bp->size);
|
||||
}
|
||||
return bp!=NULL;
|
||||
}
|
||||
|
||||
// XXX this must be implemented in r_bp.. not here!!1
|
||||
R_API int r_debug_bp_add(struct r_debug_t *dbg, ut64 addr, int size, int hw, int rwx)
|
||||
{
|
||||
ut8 *buf;
|
||||
int ret = R_FALSE;
|
||||
struct r_bp_item_t *bp;
|
||||
struct r_io_bind_t *iob;
|
||||
if (dbg->bp->iob.init == R_FALSE) {
|
||||
eprintf("No dbg->read callback defined\n");
|
||||
return -1; // return -1?
|
||||
}
|
||||
iob = &dbg->bp->iob;
|
||||
/* read bytes affected */
|
||||
buf = (ut8 *)malloc(size);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
iob->set_fd(iob->io, dbg->pid);
|
||||
iob->read_at(iob->io, addr, buf, size);
|
||||
/* register breakpoint in r_bp */
|
||||
if (hw) bp = r_bp_add_sw(&dbg->bp, buf, addr, size, 0, R_BP_EXEC);
|
||||
else bp = r_bp_add_sw(&dbg->bp, buf, addr, size, 0, R_BP_EXEC);
|
||||
if (bp) {
|
||||
if (dbg->h && (!dbg->h->bp_write || !dbg->h->bp_write(dbg->pid, addr, size, hw, rwx )))
|
||||
iob->write_at(iob->io, addr, bp->bbytes, size);
|
||||
/* if already set, r_bp should return false */
|
||||
ret = R_TRUE;
|
||||
}
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* reflect all r_bp stuff in the process using dbg->bp_write
|
||||
*/
|
||||
R_API int r_debug_bp_restore(struct r_debug_t *dbg, int set)
|
||||
{
|
||||
if (set) {
|
||||
/* write bbytes from every breakpoint in r_bp */
|
||||
// r_debug_bp_enable(dbg, addr, 1)
|
||||
} else {
|
||||
/* write obytes from every breakpoint */
|
||||
// r_debug_bp_enable(dbg, addr, 0)
|
||||
}
|
||||
return R_TRUE;
|
||||
}
|
|
@ -0,0 +1,694 @@
|
|||
/* Copyright (C) 2007, 2008, 2009 - th0rpe <nopcode.org> */
|
||||
|
||||
#include "parser.h"
|
||||
|
||||
#if 0
|
||||
extern struct regs_off roff[];
|
||||
extern unsigned long get_reg(char *reg);
|
||||
struct regs_off roff[] = {
|
||||
{"eax", R_EAX_OFF},
|
||||
{"ebx", R_EBX_OFF},
|
||||
{"ecx", R_ECX_OFF},
|
||||
{"edx", R_EDX_OFF},
|
||||
{"esi", R_ESI_OFF},
|
||||
{"edi", R_EDI_OFF},
|
||||
{"esp", R_ESP_OFF},
|
||||
{"ebp", R_EBP_OFF},
|
||||
{"eip", R_EIP_OFF},
|
||||
{"eflags", R_EFLAGS_OFF},
|
||||
|
||||
#if __WINDOWS__
|
||||
{"dr0", R_DR0_OFF},
|
||||
{"dr1", R_DR1_OFF},
|
||||
{"dr2", R_DR2_OFF},
|
||||
{"dr3", R_DR3_OFF},
|
||||
{"dr6", R_DR6_OFF},
|
||||
{"dr7", R_DR7_OFF},
|
||||
#endif
|
||||
{0, 0}
|
||||
};
|
||||
#endif
|
||||
|
||||
#define ishexa(c) ((c >='0' && c <= '9') || \
|
||||
(tolower(c) >='a' && tolower(c) <= 'f'))
|
||||
|
||||
/* skip \s\t and space characters */
|
||||
char skip_chars(const char **c)
|
||||
{
|
||||
for(;**c == ' ' || **c == '\t'; *c = *c + 1)
|
||||
;
|
||||
|
||||
return **c;
|
||||
}
|
||||
|
||||
int get_tok_op(const char **c, struct tok *t)
|
||||
{
|
||||
t->op = -1;
|
||||
|
||||
if(**c == '>') {
|
||||
if(*(*c + 1) != '=') {
|
||||
t->op = _OP_GT;
|
||||
*c = *c + 1;
|
||||
} else {
|
||||
t->op = _OP_GE;
|
||||
*c = *c + 2;
|
||||
}
|
||||
|
||||
} else if(**c == '=') {
|
||||
t->op = _OP_EQ;
|
||||
*c = *c + 1;
|
||||
|
||||
} else if(**c == '<') {
|
||||
if(*(*c + 1) == '=') {
|
||||
t->op = _OP_LE;
|
||||
*c = *c + 1;
|
||||
} else if(*(*c + 1) == '>'){
|
||||
t->op = _OP_NE;
|
||||
*c = *c + 2;
|
||||
} else {
|
||||
t->op = _OP_LT;
|
||||
*c = *c + 2;
|
||||
}
|
||||
}
|
||||
|
||||
if(t->type == MEM_TOK && t->op != _OP_EQ && t->op != _OP_NE)
|
||||
return -1;
|
||||
|
||||
return t->op;
|
||||
}
|
||||
|
||||
int get_tok_value(const char **c, struct tok *t)
|
||||
{
|
||||
char aux[512];
|
||||
char *val = *c;
|
||||
int len;
|
||||
|
||||
t->val = 0;
|
||||
|
||||
/* hexadecimal value */
|
||||
if(**c == '0' && *(*c + 1) == 'x') {
|
||||
for(*c = *c + 2; ishexa(**c); *c = *c + 1) ;
|
||||
|
||||
len = *c - val - 2;
|
||||
if( len <= 0 || (t->type == REG_TOK &&
|
||||
(len >> 1) > sizeof(unsigned long)) ||
|
||||
len + 2 >= sizeof(aux)) {
|
||||
|
||||
eprintf(":error token value too large,"
|
||||
" near %s\n", val);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* copy hexadecimal string */
|
||||
memcpy(aux, val, len + 2);
|
||||
aux[len + 2] = 0;
|
||||
|
||||
if(t->type == REG_TOK) {
|
||||
t->val = malloc(sizeof(unsigned long));
|
||||
if(!t->val) {
|
||||
perror(":error malloc tok value");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*((unsigned long *)t->val) = get_math(aux);
|
||||
t->len = sizeof(unsigned long);
|
||||
} else {
|
||||
t-> val = malloc(len);
|
||||
if(!t->val) {
|
||||
perror(":error malloc tok value");
|
||||
return -1;
|
||||
}
|
||||
|
||||
t->len = hexstr2binstr((const char *)aux + 2,
|
||||
(unsigned char *)(aux + 2));
|
||||
memcpy(t->val, aux + 2, t->len);
|
||||
/*
|
||||
for(i = 0; i < t->len; i++) {
|
||||
printf("\\x%.2x\n", (unsigned char)t->val[i]);
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
/* decimal value */
|
||||
} else if(**c >= '0' && **c <= '9') {
|
||||
|
||||
for(*c = *c + 1; **c >= '0' && **c <= '9'; *c = *c + 1)
|
||||
;
|
||||
|
||||
len = *c - val;
|
||||
|
||||
/* copy decimal string */
|
||||
memcpy(aux, val, len);
|
||||
aux[len] = 0;
|
||||
|
||||
t->val = malloc(sizeof(unsigned long));
|
||||
if(!t->val) {
|
||||
eprintf(":error malloc tok value");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*((unsigned long *)t->val) = get_math(aux);
|
||||
t->len = sizeof(unsigned long);
|
||||
|
||||
} else {
|
||||
/* TODO: get value from an external script */
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct tok* get_tok(const char **c)
|
||||
{
|
||||
struct tok *t = NULL;
|
||||
char aux[60];
|
||||
const char *val;
|
||||
int ret;
|
||||
|
||||
skip_chars((const char**)c);
|
||||
|
||||
/* register */
|
||||
if(**c == '%') {
|
||||
ret = get_reg(*c + 1);
|
||||
if(ret < 0) {
|
||||
eprintf(":error invalid register near ' %s '\n",
|
||||
*c);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*c = *c + strlen(roff[ret].reg) + 1;
|
||||
|
||||
t = (struct tok *)malloc(sizeof(*t));
|
||||
if(!t) {
|
||||
perror(":error malloc parse register");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
t->off = roff[ret].off;
|
||||
|
||||
skip_chars((const char**)c);
|
||||
|
||||
/* get operation */
|
||||
if(get_tok_op(c, t) == -1) {
|
||||
eprintf(":missing or invalid operation "
|
||||
"on register ' r%s '"
|
||||
"\n", roff[ret].reg);
|
||||
goto err_get_tok;
|
||||
}
|
||||
|
||||
skip_chars((const char**)c);
|
||||
|
||||
t->type = REG_TOK;
|
||||
|
||||
/* get value */
|
||||
if(get_tok_value(c, t) == -1) {
|
||||
eprintf(":missing or invalid value "
|
||||
"on register ' r%s '"
|
||||
"\n", roff[ret].reg);
|
||||
goto err_get_tok;
|
||||
}
|
||||
|
||||
/* memory */
|
||||
} if(**c == '[') {
|
||||
|
||||
*c = *c + 1;
|
||||
|
||||
skip_chars((const char **)c);
|
||||
|
||||
val = *c;
|
||||
|
||||
/* hexadecimal address */
|
||||
if(*val != '0' || *(val + 1) != 'x') {
|
||||
eprintf(":error invalid address near ' %s '\n",
|
||||
val);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*c = *c + 2;
|
||||
|
||||
for(; ishexa(**c) ; *c = *c + 1)
|
||||
;
|
||||
|
||||
ret = *c - val - 2;
|
||||
if((ret >> 1) > sizeof(unsigned long)) {
|
||||
eprintf(":error invalid address near ' %s '\n",
|
||||
val);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
skip_chars((const char **)c);
|
||||
|
||||
if(**c != ']') {
|
||||
eprintf(":error invalid sintax near ' %s '\n",
|
||||
*c);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(aux, val, ret + 2);
|
||||
aux[ret + 2] = 0;
|
||||
|
||||
t = (struct tok *)malloc(sizeof(*t));
|
||||
if(!t) {
|
||||
perror(":error malloc parse memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*c = *c + 1;
|
||||
|
||||
skip_chars((const char**)c);
|
||||
|
||||
/* get operation */
|
||||
if(get_tok_op(c, t) == -1) {
|
||||
eprintf(":missing or invalid operation "
|
||||
"near ' %s '\n"
|
||||
, *c);
|
||||
goto err_get_tok;
|
||||
}
|
||||
|
||||
skip_chars((const char**)c);
|
||||
|
||||
t->off = get_math(aux);
|
||||
t->type = MEM_TOK;
|
||||
|
||||
/* get value */
|
||||
if(get_tok_value(c, t) == -1) {
|
||||
fprintf(stderr, ":missing or invalid value "
|
||||
"near ' %s '\n"
|
||||
, *c);
|
||||
goto err_get_tok;
|
||||
}
|
||||
}
|
||||
|
||||
return t;
|
||||
|
||||
err_get_tok:
|
||||
if(t)
|
||||
free(t);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int get_log_op(const char **c, struct tok *t, int f)
|
||||
{
|
||||
if(strncmp(*c, "and", 3) == 0) {
|
||||
if(!f)
|
||||
return -1;
|
||||
|
||||
t->log_op = LOG_AND;
|
||||
|
||||
*c = *c + 3;
|
||||
} else if(strncmp(*c, "or", 2) == 0) {
|
||||
if(!f)
|
||||
return -1;
|
||||
|
||||
t->log_op = LOG_OR;
|
||||
|
||||
*c = *c + 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void free_cond(struct tok *group)
|
||||
{
|
||||
struct list_head *pos, *aux, *group_list;
|
||||
struct tok *t;
|
||||
|
||||
assert(group->type == GROUP_TOK);
|
||||
|
||||
group_list = &group->list;
|
||||
pos = group_list->next;
|
||||
|
||||
while(pos && pos != group_list)
|
||||
{
|
||||
t = (struct tok *)((char *)pos + \
|
||||
sizeof(struct list_head) - \
|
||||
sizeof(struct tok));
|
||||
|
||||
aux = pos->next;
|
||||
|
||||
if(t->type == GROUP_TOK)
|
||||
free_cond(t);
|
||||
|
||||
list_del(&(t->next));
|
||||
|
||||
if(t->val)
|
||||
free(t->val);
|
||||
|
||||
free(t);
|
||||
|
||||
pos = aux;
|
||||
}
|
||||
|
||||
free(group);
|
||||
}
|
||||
|
||||
/* TODO: free list when error */
|
||||
struct tok* process_cond(const char **c, int top)
|
||||
{
|
||||
struct tok *t = NULL;
|
||||
struct tok *group;
|
||||
char *val;
|
||||
int f = 0;
|
||||
|
||||
val = *c;
|
||||
|
||||
/*printf("enter condition: %s\n", val); */
|
||||
|
||||
|
||||
group = (struct tok *)malloc(sizeof(*group));
|
||||
if(!group) {
|
||||
perror(":error malloc group token");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* initialize list group */
|
||||
INIT_LIST_HEAD(&group->list);
|
||||
group->type = GROUP_TOK;
|
||||
group->log_op = 0;
|
||||
|
||||
for(;**c;) {
|
||||
|
||||
skip_chars((const char **)c);
|
||||
|
||||
if(get_log_op(c, t, f) < 0) {
|
||||
eprintf(":error missing token or "
|
||||
" operator not valid near ' %s '\n", val);
|
||||
goto err_cond;
|
||||
}
|
||||
|
||||
skip_chars((const char **)c);
|
||||
|
||||
/* enter condition */
|
||||
if(**c == '(') {
|
||||
*c = *c + 1;
|
||||
t = process_cond(c, 0);
|
||||
if(!t)
|
||||
goto err_cond;
|
||||
|
||||
list_add(&t->next, &group->list);
|
||||
|
||||
if(**c != ')') {
|
||||
fprintf(stderr, ":error not closed condition "
|
||||
" near ' %s '\n",
|
||||
val);
|
||||
goto err_cond;
|
||||
}
|
||||
|
||||
*c = *c + 1;
|
||||
f = 1;
|
||||
|
||||
/* exit condition */
|
||||
} else if(**c == ')') {
|
||||
if(top != 0) {
|
||||
fprintf(stderr, ":error not opened "
|
||||
"condition near ' %s '\n",
|
||||
val);
|
||||
goto err_cond;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
/* get token */
|
||||
} else {
|
||||
t = get_tok(c);
|
||||
if(!t)
|
||||
goto err_cond;
|
||||
|
||||
t->log_op = 0;
|
||||
|
||||
/* add token at group list */
|
||||
list_add(&t->next, &group->list);
|
||||
|
||||
f = 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* printf("exit condition group\n"); */
|
||||
|
||||
return group;
|
||||
|
||||
err_cond:
|
||||
|
||||
free_cond(group);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int eval_token_reg(struct tok *t)
|
||||
{
|
||||
unsigned long reg_val;
|
||||
unsigned long val;
|
||||
int op, ret;
|
||||
|
||||
if (!config.debug)
|
||||
return 0;
|
||||
|
||||
op = t->op;
|
||||
reg_val = debug_get_regoff(&WS(regs), t->off);
|
||||
val = *(unsigned long *)(t->val);
|
||||
|
||||
switch(op) {
|
||||
case _OP_LE:
|
||||
ret = (reg_val <= val);
|
||||
break;
|
||||
|
||||
case _OP_LT:
|
||||
ret = (reg_val < val);
|
||||
break;
|
||||
|
||||
case _OP_EQ:
|
||||
ret = (reg_val == val);
|
||||
break;
|
||||
|
||||
case _OP_NE:
|
||||
ret = (reg_val != val);
|
||||
break;
|
||||
|
||||
case _OP_GE:
|
||||
ret = (reg_val >= val);
|
||||
break;
|
||||
|
||||
case _OP_GT:
|
||||
default:
|
||||
ret = (reg_val >= val);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int eval_token_mem(struct tok *t)
|
||||
{
|
||||
unsigned char rvalue[512];
|
||||
int op = t->op;
|
||||
int ret;
|
||||
|
||||
if (!config.debug)
|
||||
return 0;
|
||||
|
||||
/* printf("read_at: 0x%x %d\n", t->off, t->len); */
|
||||
if(debug_read_at(ps.tid, rvalue, t->len, t->off) <= 0)
|
||||
return 0;
|
||||
/*
|
||||
printf("val: %x %x %x %x %x %x\n", rvalue[0], rvalue[1], rvalue[2],
|
||||
t->val[0], t->val[1], t->val[2]);
|
||||
printf("memcmp: %x\n", memcmp(t->val, rvalue, t->len));
|
||||
*/
|
||||
|
||||
switch(op) {
|
||||
case _OP_EQ:
|
||||
ret = (memcmp(t->val, rvalue, t->len) == 0);
|
||||
break;
|
||||
case _OP_NE:
|
||||
default:
|
||||
ret = (memcmp(t->val, rvalue, t->len) != 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int eval_token(struct tok *t)
|
||||
{
|
||||
int type = t->type;
|
||||
int ret;
|
||||
|
||||
switch(type) {
|
||||
/* token register */
|
||||
case REG_TOK:
|
||||
ret = eval_token_reg(t);
|
||||
break;
|
||||
/* token memory */
|
||||
case MEM_TOK:
|
||||
default:
|
||||
ret = eval_token_mem(t);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int eval_cond(struct tok *group)
|
||||
{
|
||||
struct list_head *pos;
|
||||
int log_op = 0, val_cond = 1;
|
||||
|
||||
assert(group->type == GROUP_TOK);
|
||||
|
||||
/* printf("EVAL enter group\n"); */
|
||||
|
||||
list_for_each_prev(pos, &group->list) {
|
||||
|
||||
struct tok *t = (struct tok *)((char *)pos + \
|
||||
sizeof(struct list_head) - \
|
||||
sizeof(struct tok));
|
||||
|
||||
/* not evalue next 'or' conditions
|
||||
when the condition is true yet or
|
||||
the condition is false and exist next 'and'
|
||||
conditions
|
||||
*/
|
||||
|
||||
if( (val_cond && log_op == LOG_OR) ||
|
||||
(!val_cond && log_op == LOG_AND))
|
||||
continue;
|
||||
|
||||
if(t->log_op)
|
||||
log_op = t->log_op;
|
||||
|
||||
switch(t->type) {
|
||||
|
||||
case GROUP_TOK:
|
||||
val_cond = eval_cond(t);
|
||||
break;
|
||||
default:
|
||||
val_cond = eval_token(t);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* printf("EVAL exit group\n"); */
|
||||
|
||||
return val_cond;
|
||||
}
|
||||
|
||||
|
||||
void print_token(struct tok *t)
|
||||
{
|
||||
char *op;
|
||||
char *log_op;
|
||||
|
||||
switch(t->op) {
|
||||
case _OP_LE:
|
||||
op = "<=";
|
||||
break;
|
||||
|
||||
case _OP_LT:
|
||||
op = "<";
|
||||
break;
|
||||
|
||||
case _OP_EQ:
|
||||
op = "=";
|
||||
break;
|
||||
|
||||
case _OP_NE:
|
||||
op = "<>";
|
||||
break;
|
||||
|
||||
case _OP_GE:
|
||||
op = ">=";
|
||||
break;
|
||||
|
||||
case _OP_GT:
|
||||
op = ">";
|
||||
break;
|
||||
default:
|
||||
op = "none";
|
||||
}
|
||||
|
||||
if(t->log_op == LOG_OR)
|
||||
log_op = "or";
|
||||
else if(t->log_op == LOG_AND)
|
||||
log_op = "and";
|
||||
else
|
||||
log_op = "";
|
||||
|
||||
if(t->type == REG_TOK) {
|
||||
printf( "register off %i\n"
|
||||
"logical op %s\n"
|
||||
"operator %s\n"
|
||||
"value %x\n"
|
||||
,(unsigned int)t->off
|
||||
,log_op
|
||||
,op
|
||||
,(unsigned int)*((unsigned long *)t->val)
|
||||
);
|
||||
} else if(t->type == MEM_TOK) {
|
||||
printf( "memory %x\n"
|
||||
"logical op %s\n"
|
||||
"operator %s\n"
|
||||
"val %x\n"
|
||||
"len %d\n"
|
||||
,(unsigned int)t->off
|
||||
,log_op
|
||||
,op
|
||||
,(unsigned int)*((unsigned long *)t->val)
|
||||
,(unsigned int)t->len
|
||||
);
|
||||
} else {
|
||||
printf(" operator group %s\n", log_op);
|
||||
}
|
||||
}
|
||||
|
||||
void print_expr(struct tok *group)
|
||||
{
|
||||
struct list_head *pos;
|
||||
|
||||
assert(group->type == GROUP_TOK);
|
||||
|
||||
printf("enter group\n");
|
||||
|
||||
list_for_each_prev(pos, &group->list) {
|
||||
struct tok *t = (struct tok *)((char *)pos + \
|
||||
sizeof(struct list_head) - \
|
||||
sizeof(struct tok));
|
||||
|
||||
switch(t->type) {
|
||||
case GROUP_TOK:
|
||||
print_token(t);
|
||||
print_expr(t);
|
||||
break;
|
||||
|
||||
default:
|
||||
print_token(t);
|
||||
}
|
||||
}
|
||||
|
||||
printf("exit group\n");
|
||||
}
|
||||
|
||||
struct tok* parse_cond(const char *cond)
|
||||
{
|
||||
return process_cond(&cond, 1);
|
||||
}
|
||||
#if 0
|
||||
void test_parser()
|
||||
{
|
||||
struct tok *gr;
|
||||
char *v;
|
||||
char *p = "reip >= 0x01020304 and rebx = 15 "
|
||||
"and ([0x80456] = 10 or reip = 5) "
|
||||
"and ([0xff456] = 1 and reip = 2) or "
|
||||
"(reax <> 10 and recx = 4)"
|
||||
;
|
||||
v = p;
|
||||
gr = process_cond(&p, 1);
|
||||
if(gr) {
|
||||
print_expr(gr);
|
||||
printf("cond: %s\n", v);
|
||||
printf("eval cond: %d\n", eval_cond(gr));
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,50 @@
|
|||
#ifndef PARSER_H
|
||||
#define PARSER_H
|
||||
#include "../list.h"
|
||||
|
||||
struct regs_off {
|
||||
char *reg;
|
||||
int off; // XXX 32 bit only !? wtf?
|
||||
};
|
||||
|
||||
/* token types */
|
||||
enum {
|
||||
GROUP_TOK = 0,
|
||||
REG_TOK,
|
||||
MEM_TOK
|
||||
};
|
||||
|
||||
/* token structure */
|
||||
struct tok {
|
||||
ut64 off;
|
||||
int type;
|
||||
int op, log_op;
|
||||
char *val;
|
||||
int len;
|
||||
|
||||
struct list_head list;
|
||||
struct list_head next;
|
||||
};
|
||||
|
||||
/* arithmetical operations */
|
||||
enum {
|
||||
_OP_LT = 1,
|
||||
_OP_LE,
|
||||
_OP_EQ,
|
||||
_OP_NE,
|
||||
_OP_GE,
|
||||
_OP_GT
|
||||
};
|
||||
|
||||
/* logical operations */
|
||||
enum {
|
||||
LOG_OR = 1,
|
||||
LOG_AND
|
||||
};
|
||||
|
||||
char skip_chars(const char **c);
|
||||
struct tok* parse_cond(const char *cond);
|
||||
int eval_cond(struct tok *group);
|
||||
void free_cond(struct tok *group);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,24 @@
|
|||
// TODO: use r_range here??
|
||||
|
||||
// TRAPTRACE
|
||||
R_API int r_bp_add_traptrace(struct r_bp_t *bp, ut64 from, ut64 to)
|
||||
{
|
||||
// read a memory, overwrite it as breakpointing area
|
||||
// everytime it is hitted, instruction is restored
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
R_API int r_bp_del_traptrace(struct r_bp_t *bp, ut64 from, ut64 to)
|
||||
{
|
||||
// read a memory, overwrite it as breakpointing area
|
||||
// everytime it is hitted, instruction is restored
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
R_API int r_bp_restore_traptrace(struct r_bp_t *bp, ut64 from, ut64 to)
|
||||
{
|
||||
// read a memory, overwrite it as breakpointing area
|
||||
// everytime it is hitted, instruction is restored
|
||||
return R_TRUE;
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
NAME=r_core
|
||||
DEPS=r_config r_cons r_line r_io r_cmd r_util r_print r_flags r_asm r_lib r_macro r_debug r_hash r_bin r_lang r_io r_asm r_anal r_parse r_config r_macro r_print r_bininfo r_bp
|
||||
DEPS=r_config r_cons r_line r_io r_cmd r_util r_print r_flags r_asm r_lib r_macro r_debug r_hash r_bin r_lang r_io r_asm r_anal r_parse r_config r_macro r_print r_bininfo r_bp r_reg
|
||||
|
||||
OBJ=core.o cmd.o file.o config.o visual.o io.o yank.o libs.o
|
||||
|
||||
|
|
|
@ -1611,16 +1611,16 @@ static int cmd_debug(void *data, const char *input)
|
|||
if (input[1]==' ') input = input+1;
|
||||
switch(input[1]) {
|
||||
case '\0':
|
||||
r_bp_list(&core->dbg.bp, input[1]=='*');
|
||||
r_bp_list(core->dbg.bp, input[1]=='*');
|
||||
break;
|
||||
case '-':
|
||||
r_debug_bp_del(&core->dbg, r_num_math(&core->num, input+2));
|
||||
r_bp_del(core->dbg.bp, r_num_math(&core->num, input+2));
|
||||
break;
|
||||
case 'e':
|
||||
r_debug_bp_enable(&core->dbg, r_num_math(&core->num, input+2), 1);
|
||||
r_bp_enable(core->dbg.bp, r_num_math(&core->num, input+2), 1);
|
||||
break;
|
||||
case 'd':
|
||||
r_debug_bp_enable(&core->dbg, r_num_math(&core->num, input+2), 0);
|
||||
r_bp_enable(core->dbg.bp, r_num_math(&core->num, input+2), 0);
|
||||
break;
|
||||
case 'h':
|
||||
if (input[2]==' ') {
|
||||
|
@ -1639,7 +1639,7 @@ static int cmd_debug(void *data, const char *input)
|
|||
"dbh x86 ; set/list breakpoint plugin handlers\n");
|
||||
break;
|
||||
default:
|
||||
r_debug_bp_add(&core->dbg, r_num_math(&core->num, input+1), 1, 0, R_BP_EXEC);
|
||||
r_bp_add_sw(core->dbg.bp, r_num_math(&core->num, input+1), 1, R_BP_EXEC);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -156,7 +156,7 @@ R_API int r_core_init(struct r_core_t *core)
|
|||
core->io.printf = r_cons_printf;
|
||||
core->dbg.printf = r_cons_printf;
|
||||
//r_debug_set_io(&core->dbg, &__dbg_read, &__dbg_write, core);
|
||||
r_io_bind(&core->io, &core->dbg.iob);
|
||||
r_io_bind(&core->io, &(core->dbg.bp->iob));
|
||||
r_core_config_init(core);
|
||||
// XXX fix path here
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ static int __lib_bp_cb(struct r_lib_plugin_t *pl, void *user, void *data)
|
|||
struct r_bp_handle_t *hand = (struct r_bp_handle_t *)data;
|
||||
struct r_core_t *core = (struct r_core_t *)user;
|
||||
//printf(" * Added bpger handler\n");
|
||||
r_bp_handle_add(&core->dbg.bp, hand);
|
||||
r_bp_handle_add(core->dbg.bp, hand);
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
OBJ=radare2.o
|
||||
BIN=radare2
|
||||
BINDEPS=r_core r_cons r_macro r_util r_flags r_lib r_io r_hash r_cmd r_config r_asm r_bp
|
||||
BINDEPS+=r_anal r_parse r_lang r_debug r_print r_line r_bin r_search r_meta r_bininfo
|
||||
BINDEPS+=r_anal r_parse r_lang r_debug r_print r_line r_bin r_search r_meta r_bininfo r_reg
|
||||
|
||||
#LIBS=-lr_core -L..
|
||||
### shared
|
||||
|
|
|
@ -7,7 +7,7 @@ foo: pre libr_debug.so tests plugins
|
|||
include ../config.mk
|
||||
include ${STATIC_DEBUG_PLUGINS}
|
||||
STATIC_OBJS=$(subst ..,p/..,$(subst dbg_,p/dbg_,$(STATIC_OBJ)))
|
||||
OBJ=debug.o handle.o pid.o bp.o reg.o regset.o ${STATIC_OBJS}
|
||||
OBJ=debug.o handle.o pid.o reg.o ${STATIC_OBJS}
|
||||
|
||||
pre:
|
||||
@if [ ! -e libr_debug.so ]; then rm -f ${STATIC_OBJS} ; fi
|
||||
|
|
|
@ -11,9 +11,9 @@ R_API int r_debug_init(struct r_debug_t *dbg)
|
|||
dbg->regs = dbg->oregs = NULL;
|
||||
dbg->printf = printf;
|
||||
dbg->h = NULL;
|
||||
dbg->bp = r_bp_new();
|
||||
r_debug_handle_init(dbg);
|
||||
r_bp_init(&dbg->bp);
|
||||
dbg->iob.init = R_FALSE;
|
||||
dbg->bp->iob.init = R_FALSE;
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,10 @@ R_API int r_debug_attach(struct r_debug_t *dbg, int pid)
|
|||
if (dbg->h && dbg->h->attach) {
|
||||
ret = dbg->h->attach(pid);
|
||||
if (ret) {
|
||||
// TODO: get arch and set io pid
|
||||
//int arch = dbg->h->get_arch();
|
||||
//r_reg_set(dbg->reg->nregs, arch); //R_DBG_ARCH_X86);
|
||||
// dbg->bp->iob->system("pid %d", pid);
|
||||
dbg->pid = pid;
|
||||
dbg->tid = pid;
|
||||
} else fprintf(stderr, "Cannot attach to this pid\n");
|
||||
|
@ -72,20 +76,6 @@ R_API int r_debug_select(struct r_debug_t *dbg, int pid, int tid)
|
|||
return R_TRUE;
|
||||
}
|
||||
|
||||
R_API int r_debug_set_arch(struct r_debug_t *dbg, int arch)
|
||||
{
|
||||
/* XXX: use string identifiers here */
|
||||
switch(arch) {
|
||||
case R_DBG_ARCH_BF:
|
||||
// TODO: set callbacks for brainfuck debugger here
|
||||
break;
|
||||
case R_DBG_ARCH_X86:
|
||||
//r_reg_set(dbg->reg->nregs, R_DBG_ARCH_X86);
|
||||
break;
|
||||
}
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
/*--*/
|
||||
R_API int r_debug_stop_reason(struct r_debug_t *dbg)
|
||||
{
|
||||
|
@ -163,20 +153,13 @@ R_API int r_debug_continue_syscall(struct r_debug_t *dbg, int sc)
|
|||
return ret;
|
||||
}
|
||||
|
||||
// XXX wrong function name
|
||||
R_API int r_debug_use_software_steps(struct r_debug_t *dbg, int value)
|
||||
{
|
||||
/* use software breakpoints and continues */
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO: remove from here?
|
||||
R_API int r_debug_syscall(struct r_debug_t *dbg, int num)
|
||||
{
|
||||
fprintf(stderr, "TODO\n");
|
||||
return R_FALSE;
|
||||
}
|
||||
|
||||
|
||||
// TODO: Move to pid.c ?
|
||||
// TODO: do we need tid/pid
|
||||
// TODO: Do we need an intermediate signal representation for portability?
|
||||
|
@ -191,6 +174,7 @@ R_API int r_debug_kill(struct r_debug_t *dbg, int pid, int sig)
|
|||
return R_TRUE;
|
||||
}
|
||||
|
||||
// TODO move to mem.c
|
||||
/* mmu */
|
||||
R_API int r_debug_mmu_alloc(struct r_debug_t *dbg, ut64 size, ut64 *addr)
|
||||
{
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#if DEBUGGER
|
||||
|
||||
#include <r_debug.h>
|
||||
#include <r_asm.h>
|
||||
#include <r_lib.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -53,9 +54,9 @@ static int r_debug_ptrace_wait(int pid)
|
|||
return status;
|
||||
}
|
||||
|
||||
struct r_debug_regset_t * r_debug_ptrace_reg_read(int pid)
|
||||
struct r_regset_t* r_debug_ptrace_reg_read(int pid)
|
||||
{
|
||||
struct r_debug_regset_t *r = NULL;
|
||||
struct r_regset_t *r = NULL;
|
||||
// XXX this must be defined somewhere else
|
||||
#if __linux__
|
||||
#include <sys/user.h>
|
||||
|
@ -64,43 +65,43 @@ struct r_debug_regset_t * r_debug_ptrace_reg_read(int pid)
|
|||
memset(®s,0, sizeof(regs));
|
||||
ptrace(PTRACE_GETREGS, pid, 0, ®s);
|
||||
#if __WORDSIZE == 64
|
||||
r = r_debug_regset_new(17);
|
||||
r_debug_regset_set(r, 0, "rax", regs.rax);
|
||||
r_debug_regset_set(r, 1, "rbx", regs.rbx);
|
||||
r_debug_regset_set(r, 2, "rcx", regs.rcx);
|
||||
r_debug_regset_set(r, 3, "rdx", regs.rdx);
|
||||
r_debug_regset_set(r, 4, "rsi", regs.rsi);
|
||||
r_debug_regset_set(r, 5, "rdi", regs.rdi);
|
||||
r_debug_regset_set(r, 6, "rsp", regs.rsp);
|
||||
r_debug_regset_set(r, 7, "rbp", regs.rbp);
|
||||
r_debug_regset_set(r, 8, "rip", regs.rip);
|
||||
r_debug_regset_set(r, 9, "r8", regs.r8);
|
||||
r_debug_regset_set(r, 10, "r9", regs.r9);
|
||||
r_debug_regset_set(r, 11, "r10", regs.r10);
|
||||
r_debug_regset_set(r, 12, "r11", regs.r11);
|
||||
r_debug_regset_set(r, 13, "r12", regs.r12);
|
||||
r_debug_regset_set(r, 14, "r13", regs.r13);
|
||||
r_debug_regset_set(r, 15, "r14", regs.r14);
|
||||
r_debug_regset_set(r, 16, "r15", regs.r15);
|
||||
r = r_regset_new(17);
|
||||
r_regset_set(r, 0, "rax", regs.rax);
|
||||
r_regset_set(r, 1, "rbx", regs.rbx);
|
||||
r_regset_set(r, 2, "rcx", regs.rcx);
|
||||
r_regset_set(r, 3, "rdx", regs.rdx);
|
||||
r_regset_set(r, 4, "rsi", regs.rsi);
|
||||
r_regset_set(r, 5, "rdi", regs.rdi);
|
||||
r_regset_set(r, 6, "rsp", regs.rsp);
|
||||
r_regset_set(r, 7, "rbp", regs.rbp);
|
||||
r_regset_set(r, 8, "rip", regs.rip);
|
||||
r_regset_set(r, 9, "r8", regs.r8);
|
||||
r_regset_set(r, 10, "r9", regs.r9);
|
||||
r_regset_set(r, 11, "r10", regs.r10);
|
||||
r_regset_set(r, 12, "r11", regs.r11);
|
||||
r_regset_set(r, 13, "r12", regs.r12);
|
||||
r_regset_set(r, 14, "r13", regs.r13);
|
||||
r_regset_set(r, 15, "r14", regs.r14);
|
||||
r_regset_set(r, 16, "r15", regs.r15);
|
||||
#else
|
||||
/* TODO: use enum for 0, 1, 2... ? */
|
||||
/* TODO: missing eflags here */
|
||||
r = r_debug_regset_new(9);
|
||||
r_debug_regset_set(r, 0, "eax", (ut64)(ut32)regs.eax);
|
||||
r_debug_regset_set(r, 1, "ebx", (ut64)(ut32)regs.ebx);
|
||||
r_debug_regset_set(r, 2, "ecx", (ut64)(ut32)regs.ecx);
|
||||
r_debug_regset_set(r, 3, "edx", (ut64)(ut32)regs.edx);
|
||||
r_debug_regset_set(r, 4, "esi", (ut64)(ut32)regs.esi);
|
||||
r_debug_regset_set(r, 5, "edi", (ut64)(ut32)regs.edi);
|
||||
r_debug_regset_set(r, 6, "esp", (ut64)(ut32)regs.esp);
|
||||
r_debug_regset_set(r, 7, "ebp", (ut64)(ut32)regs.ebp);
|
||||
r_debug_regset_set(r, 8, "eip", (ut64)(ut32)regs.eip);
|
||||
r = r_regset_new(9);
|
||||
r_regset_set(r, 0, "eax", (ut64)(ut32)regs.eax);
|
||||
r_regset_set(r, 1, "ebx", (ut64)(ut32)regs.ebx);
|
||||
r_regset_set(r, 2, "ecx", (ut64)(ut32)regs.ecx);
|
||||
r_regset_set(r, 3, "edx", (ut64)(ut32)regs.edx);
|
||||
r_regset_set(r, 4, "esi", (ut64)(ut32)regs.esi);
|
||||
r_regset_set(r, 5, "edi", (ut64)(ut32)regs.edi);
|
||||
r_regset_set(r, 6, "esp", (ut64)(ut32)regs.esp);
|
||||
r_regset_set(r, 7, "ebp", (ut64)(ut32)regs.ebp);
|
||||
r_regset_set(r, 8, "eip", (ut64)(ut32)regs.eip);
|
||||
#endif
|
||||
#endif /* linux */
|
||||
return r;
|
||||
}
|
||||
|
||||
static int r_debug_ptrace_reg_write(int pid, struct r_debug_regset_t *regs)
|
||||
static int r_debug_ptrace_reg_write(int pid, struct r_regset_t *regs)
|
||||
{
|
||||
/* TODO */
|
||||
return 0;
|
||||
|
@ -121,6 +122,15 @@ static int r_debug_ptrace_bp_read(int pid, ut64 addr, int hw, int rwx)
|
|||
return R_TRUE;
|
||||
}
|
||||
|
||||
static int r_debug_get_arch()
|
||||
{
|
||||
#if __WORDSIZE == 64
|
||||
return R_ASM_ARCH_X86_64;
|
||||
#else
|
||||
return R_ASM_ARCH_X86;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int r_debug_ptrace_import(struct r_debug_handle_t *from)
|
||||
{
|
||||
|
@ -142,6 +152,7 @@ struct r_debug_handle_t r_debug_plugin_ptrace = {
|
|||
.attach = &r_debug_ptrace_attach,
|
||||
.detach = &r_debug_ptrace_detach,
|
||||
.wait = &r_debug_ptrace_wait,
|
||||
.get_arch = &r_debug_get_arch,
|
||||
.bp_write = &r_debug_ptrace_bp_write,
|
||||
.reg_read = &r_debug_ptrace_reg_read,
|
||||
.reg_write = &r_debug_ptrace_reg_write,
|
||||
|
|
|
@ -20,9 +20,9 @@ R_API int r_debug_reg_sync(struct r_debug_t *dbg, int write)
|
|||
return (dbg->regs != NULL);
|
||||
}
|
||||
|
||||
R_API struct r_debug_regset_t *r_debug_reg_diff(struct r_debug_t *dbg)
|
||||
R_API struct r_regset_t *r_debug_reg_diff(struct r_debug_t *dbg)
|
||||
{
|
||||
return r_debug_regset_diff(dbg->oregs, dbg->regs);
|
||||
return r_regset_diff(dbg->oregs, dbg->regs);
|
||||
}
|
||||
|
||||
R_API ut64 r_debug_reg_get(struct r_debug_t *dbg, const char *name)
|
||||
|
@ -43,23 +43,23 @@ R_API ut64 r_debug_reg_get(struct r_debug_t *dbg, const char *name)
|
|||
R_API int r_debug_reg_set(struct r_debug_t *dbg, const char *name, ut64 value)
|
||||
{
|
||||
int i;
|
||||
struct r_debug_regset_t *rs = dbg->regs;
|
||||
struct r_regset_t *rs = dbg->regs;
|
||||
if (rs)
|
||||
for(i=0; i<rs->nregs; i++) {
|
||||
if (!strcmp(name, rs->regs[i].name))
|
||||
return r_debug_regset_set(dbg->regs, i, name, value);
|
||||
return r_regset_set(dbg->regs, i, name, value);
|
||||
}
|
||||
return R_FALSE;
|
||||
}
|
||||
|
||||
R_API int r_debug_reg_list(struct r_debug_t *dbg, struct r_debug_regset_t *rs, int rad)
|
||||
R_API int r_debug_reg_list(struct r_debug_t *dbg, struct r_regset_t *rs, int rad)
|
||||
{
|
||||
int i =0;
|
||||
if (rs == NULL)
|
||||
rs = dbg->regs;
|
||||
if (rs)
|
||||
for(i=0;i<rs->nregs;i++) {
|
||||
struct r_debug_reg_t *r = &rs->regs[i];
|
||||
struct r_reg_item_t *r = &rs->regs[i];
|
||||
if (rad) dbg->printf("f %s @ 0x%08llx\n", r->name, r->value);
|
||||
else dbg->printf("%d %s 0x%08llx\n", i, r->name, r->value);
|
||||
/* TODO: add floating point support here */
|
||||
|
|
|
@ -9,7 +9,7 @@ int main(int argc, char **argv)
|
|||
int ret;
|
||||
int tid, pid;
|
||||
struct r_io_t *io;
|
||||
struct r_dbg_t *dbg;
|
||||
struct r_debug_t *dbg;
|
||||
|
||||
io = r_io_new();
|
||||
printf("Supported IO pluggins:\n");
|
||||
|
|
|
@ -9,6 +9,20 @@
|
|||
#define R_ASM_BUFSIZE 1024
|
||||
#define R_ASM_FASTCALL_ARGS 6
|
||||
|
||||
enum {
|
||||
R_ASM_ARCH_NULL = 0,
|
||||
R_ASM_ARCH_X86,
|
||||
R_ASM_ARCH_ARM,
|
||||
R_ASM_ARCH_PPC,
|
||||
R_ASM_ARCH_M68K,
|
||||
R_ASM_ARCH_JAVA,
|
||||
R_ASM_ARCH_MIPS,
|
||||
R_ASM_ARCH_SPARC,
|
||||
R_ASM_ARCH_CSR,
|
||||
R_ASM_ARCH_MSIL,
|
||||
R_ASM_ARCH_OBJD,
|
||||
R_ASM_ARCH_BF
|
||||
};
|
||||
|
||||
enum {
|
||||
R_ASM_SYN_NULL = 0,
|
||||
|
|
|
@ -2,19 +2,32 @@
|
|||
#define _INCLUDE_LIBR_BP_H_
|
||||
|
||||
#include <r_types.h>
|
||||
#include <r_io.h>
|
||||
#include "list.h"
|
||||
|
||||
#define R_BP_MAXPIDS 10
|
||||
|
||||
|
||||
#define R_BP_CONT_NORMAL 0
|
||||
#define R_BP_CONT_NORMAL 0
|
||||
|
||||
struct r_bp_arch_t {
|
||||
int length;
|
||||
int endian;
|
||||
const ut8 *bytes;
|
||||
};
|
||||
|
||||
enum {
|
||||
R_BP_TYPE_SW,
|
||||
R_BP_TYPE_HW,
|
||||
R_BP_TYPE_COND,
|
||||
R_BP_TYPE_FAULT,
|
||||
};
|
||||
|
||||
struct r_bp_handle_t {
|
||||
char *name;
|
||||
char *arch;
|
||||
int type; // R_BP_TYPE_SW
|
||||
int nbps;
|
||||
struct r_bp_arch_t *bps;
|
||||
struct list_head list;
|
||||
|
@ -27,6 +40,7 @@ struct r_bp_item_t {
|
|||
int hw;
|
||||
int trace;
|
||||
int enabled;
|
||||
int hits;
|
||||
ut8 *obytes; /* original bytes */
|
||||
ut8 *bbytes; /* breakpoint bytes */
|
||||
int pids[R_BP_MAXPIDS];
|
||||
|
@ -37,6 +51,8 @@ struct r_bp_t {
|
|||
int trace_all;
|
||||
ut64 trace_bp;
|
||||
int nbps;
|
||||
int stepcont;
|
||||
struct r_io_bind_t iob; // compile time dependency
|
||||
struct r_bp_handle_t *cur;
|
||||
struct list_head plugins;
|
||||
struct list_head bps;
|
||||
|
@ -52,7 +68,6 @@ R_API int r_bp_init(struct r_bp_t *bp);
|
|||
R_API struct r_bp_t *r_bp_new();
|
||||
R_API struct r_bp_t *r_bp_free(struct r_bp_t *bp);
|
||||
|
||||
R_API struct r_bp_item_t *r_bp_add(struct r_bp_t *bp, const ut8 *obytes, ut64 addr, int size, int hw, int rwx);
|
||||
R_API int r_bp_del(struct r_bp_t *bp, ut64 addr);
|
||||
|
||||
R_API int r_bp_handle_add(struct r_bp_t *bp, struct r_bp_handle_t *foo);
|
||||
|
@ -62,11 +77,18 @@ R_API void r_bp_handle_list(struct r_bp_t *bp);
|
|||
|
||||
R_API int r_bp_in(struct r_bp_t *bp, ut64 addr, int rwx);
|
||||
R_API int r_bp_list(struct r_bp_t *bp, int rad);
|
||||
R_API int r_bp_getbytes(struct r_bp_t *bp, ut8 *buf, int len, int endian, int idx);
|
||||
R_API int r_bp_get_bytes(struct r_bp_t *bp, ut8 *buf, int len, int endian, int idx);
|
||||
R_API int r_bp_set_trace(struct r_bp_t *bp, ut64 addr, int set);
|
||||
R_API int r_bp_set_trace_bp(struct r_bp_t *bp, ut64 addr, int set);
|
||||
R_API struct r_bp_item_t *r_bp_enable(struct r_bp_t *bp, ut64 addr, int set);
|
||||
|
||||
R_API int r_bp_add_cond(struct r_bp_t *bp, const char *cond);
|
||||
R_API int r_bp_del_cond(struct r_bp_t *bp, int idx);
|
||||
R_API int r_bp_add_fault(struct r_bp_t *bp, ut64 addr, int size, int rwx);
|
||||
|
||||
R_API struct r_bp_item_t *r_bp_add_sw(struct r_bp_t *bp, ut64 addr, int size, int rwx);
|
||||
R_API struct r_bp_item_t *r_bp_add_hw(struct r_bp_t *bp, ut64 addr, int size, int rwx);
|
||||
|
||||
/* plugin pointers */
|
||||
extern struct r_bp_handle_t r_bp_plugin_x86;
|
||||
extern struct r_bp_handle_t r_bp_plugin_arm;
|
||||
|
|
|
@ -9,37 +9,6 @@
|
|||
#include <r_syscall.h>
|
||||
#include "list.h"
|
||||
|
||||
enum {
|
||||
R_DBG_ARCH_NULL = 0,
|
||||
R_DBG_ARCH_X86,
|
||||
R_DBG_ARCH_ARM,
|
||||
R_DBG_ARCH_PPC,
|
||||
R_DBG_ARCH_M68K,
|
||||
R_DBG_ARCH_JAVA,
|
||||
R_DBG_ARCH_MIPS,
|
||||
R_DBG_ARCH_SPARC,
|
||||
R_DBG_ARCH_CSR,
|
||||
R_DBG_ARCH_MSIL,
|
||||
R_DBG_ARCH_OBJD,
|
||||
R_DBG_ARCH_BF
|
||||
};
|
||||
|
||||
#define R_DEBUG_REG_NAME_MAX 16
|
||||
struct r_debug_reg_t {
|
||||
char name[R_DEBUG_REG_NAME_MAX];
|
||||
union {
|
||||
ut64 value;
|
||||
float fvalue;
|
||||
double dvalue;
|
||||
};
|
||||
int isfloat;
|
||||
};
|
||||
|
||||
struct r_debug_regset_t {
|
||||
int nregs;
|
||||
struct r_debug_reg_t *regs;
|
||||
};
|
||||
|
||||
/* TODO: pass dbg and user data pointer everywhere */
|
||||
struct r_debug_handle_t {
|
||||
const char *name;
|
||||
|
@ -50,11 +19,12 @@ struct r_debug_handle_t {
|
|||
int (*step)(int pid); // if step() is NULL; reimplement it with traps
|
||||
int (*cont)(int pid);
|
||||
int (*wait)(int pid);
|
||||
int (*get_arch)();
|
||||
int (*contsc)(int pid, int sc);
|
||||
//int (*bp_write)(int pid, ut64 addr, int hw, int type);
|
||||
int (*bp_write)(int pid, ut64 addr, int size, int hw, int rwx);
|
||||
struct r_debug_regset_t * (*reg_read)(int pid);
|
||||
int (*reg_write)(int pid, struct r_debug_regset_t *regs);
|
||||
struct r_regset_t * (*reg_read)(int pid);
|
||||
int (*reg_write)(int pid, struct r_regset_t *regs);
|
||||
// XXX bad signature int (*bp_read)(int pid, ut64 addr, int hw, int type);
|
||||
struct list_head list;
|
||||
};
|
||||
|
@ -65,13 +35,12 @@ struct r_debug_t {
|
|||
int swstep; /* steps with software traps */
|
||||
int steps; /* counter of steps done */
|
||||
int newstate;
|
||||
struct r_debug_regset_t *oregs;
|
||||
struct r_debug_regset_t *regs;
|
||||
struct r_bp_t bp;
|
||||
struct r_regset_t *oregs;
|
||||
struct r_regset_t *regs;
|
||||
struct r_bp_t *bp;
|
||||
void *user;
|
||||
/* io */
|
||||
void (*printf)(const char *str, ...);
|
||||
struct r_io_bind_t iob; // compile time dependency
|
||||
struct r_debug_handle_t *h;
|
||||
struct list_head handlers;
|
||||
/* TODO
|
||||
|
@ -135,14 +104,14 @@ R_API int r_debug_bp_list(struct r_debug_t *dbg, int rad);
|
|||
R_API int r_debug_reg_sync(struct r_debug_t *dbg, int write);
|
||||
R_API ut64 r_debug_reg_get(struct r_debug_t *dbg, const char *name);
|
||||
R_API int r_debug_reg_set(struct r_debug_t *dbg, const char *name, ut64 value);
|
||||
R_API struct r_debug_regset_t *r_debug_reg_diff(struct r_debug_t *dbg);
|
||||
R_API int r_debug_reg_list(struct r_debug_t *dbg, struct r_debug_regset_t *rs, int rad);
|
||||
R_API struct r_regset_t *r_debug_reg_diff(struct r_debug_t *dbg);
|
||||
R_API int r_debug_reg_list(struct r_debug_t *dbg, struct r_regset_t *rs, int rad);
|
||||
|
||||
/* regset */
|
||||
R_API struct r_debug_regset_t* r_debug_regset_diff(struct r_debug_regset_t *a, struct r_debug_regset_t *b);
|
||||
R_API int r_debug_regset_set(struct r_debug_regset_t *r, int idx, const char *name, ut64 value);
|
||||
R_API struct r_debug_regset_t *r_debug_regset_new(int size);
|
||||
R_API void r_debug_regset_free(struct r_debug_regset_t *r);
|
||||
R_API struct r_regset_t* r_regset_diff(struct r_regset_t *a, struct r_regset_t *b);
|
||||
R_API int r_regset_set(struct r_regset_t *r, int idx, const char *name, ut64 value);
|
||||
R_API struct r_regset_t *r_regset_new(int size);
|
||||
R_API void r_regset_free(struct r_regset_t *r);
|
||||
|
||||
#if 0
|
||||
Missing callbacks
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
#define _INCLUDE_R_REG_H_
|
||||
|
||||
#include <r_types.h>
|
||||
#include <list.h>
|
||||
|
||||
// XXX this must be in plugins
|
||||
enum {
|
||||
R_REG_X86_EAX,
|
||||
R_REG_X86_AX,
|
||||
|
@ -16,9 +18,33 @@ enum {
|
|||
R_REG_X86_EIP,
|
||||
};
|
||||
|
||||
struct r_reg_handle_t {
|
||||
int (*is_arch)(int arch, int bits);
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
struct r_reg_t {
|
||||
int nregs;
|
||||
char **regs;
|
||||
struct r_reg_handle_t *h;
|
||||
struct list_head handles;
|
||||
};
|
||||
|
||||
#define R_REG_NAME_MAX 16
|
||||
struct r_reg_item_t {
|
||||
char name[R_REG_NAME_MAX];
|
||||
union {
|
||||
ut64 value;
|
||||
float fvalue;
|
||||
double dvalue;
|
||||
};
|
||||
int offset;
|
||||
int isfloat;
|
||||
};
|
||||
|
||||
struct r_regset_t {
|
||||
int nregs;
|
||||
struct r_reg_item_t *regs;
|
||||
};
|
||||
|
||||
int r_reg_set_arch(struct r_reg_t *reg, int arch, int bits);
|
||||
|
|
|
@ -179,6 +179,9 @@ static int __system(struct r_io_t *io, int fd, const char *cmd)
|
|||
#include <limits.h>
|
||||
/* XXX ugly hack for testing purposes */
|
||||
if (!strcmp(cmd, "pid")) {
|
||||
int pid = atoi(cmd+4);
|
||||
if (pid != 0)
|
||||
io->fd = pid;
|
||||
//printf("PID=%d\n", io->fd);
|
||||
return io->fd;
|
||||
} else
|
||||
|
|
|
@ -3,7 +3,8 @@ include ../../../config-user.mk
|
|||
CFLAGS=-I../../include -Wall -DPREFIX=\"${PREFIX}\"
|
||||
BINDEPS=
|
||||
|
||||
LANGS=lang_lua.so lang_dummy.so lang_ruby.so lang_python.so lang_perl.so
|
||||
LANGS=lang_lua.so lang_dummy.so lang_python.so lang_perl.so
|
||||
#LANGS+=lang_ruby.so
|
||||
ifeq ($(HAVE_LIB_TCC),1)
|
||||
LANGS+=lang_tcc.so
|
||||
endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
NAME=r_reg
|
||||
OBJ=reg.o
|
||||
OBJ=reg.o regset.o
|
||||
|
||||
include ../rules.mk
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
|
||||
static int x86_nregs = 10;
|
||||
static char *x86_regs[] = {
|
||||
"eax", "ebx", "ecx", "edx", "esi", "edi", "esp", "ebp", "eip",
|
||||
"ax", "bx", "cx", "dx", "si", "di", "sp", "bp", "ip", // 16 tits
|
||||
"ah","al", "bh", "bl", "ch","cl", "dh","dl", // 8 tits
|
||||
NULL };
|
||||
|
||||
#if 0
|
||||
// XXX
|
||||
- we need size of register
|
||||
struct r_reg_item_t {
|
||||
char name[16];
|
||||
char get[128];
|
||||
char set[128];
|
||||
int size;
|
||||
int delta;
|
||||
};
|
||||
|
||||
struct r_reg_arch_t {
|
||||
char *name;
|
||||
int nregs;
|
||||
struct r_reg_item_t regs[128];
|
||||
};
|
||||
|
||||
/* TODO: autogenerate it from a file in C or perl */
|
||||
struct r_reg_arch_t x86 {
|
||||
.name = "",
|
||||
.nregs = 32,
|
||||
.regs = { {
|
||||
.name = "eax",
|
||||
.size = 32,
|
||||
.delta = offsetof(r_regs_t, eax)
|
||||
},{
|
||||
.name = "ebx",
|
||||
.size = 32,
|
||||
.delta = offsetof(r_regs_t, ebx)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
switch(arch) {
|
||||
case R_ASM_ARCH_X86:
|
||||
switch(bits) {
|
||||
case 64:
|
||||
reg->nregs = x86_nregs;
|
||||
reg->regs = x86_regs;
|
||||
break;
|
||||
case 32:
|
||||
reg->nregs = x86_nregs;
|
||||
reg->regs = x86_regs;
|
||||
break;
|
||||
case 16:
|
||||
reg->nregs = x86_nregs;
|
||||
reg->regs = x86_regs;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
/* TODO: add more architectures */
|
||||
case R_ASM_ARCH_ARM:
|
||||
case R_ASM_ARCH_MIPS:
|
||||
default:
|
||||
ret = R_FALSE;
|
||||
break;
|
||||
}
|
|
@ -1,74 +1,42 @@
|
|||
#include <r_reg.h>
|
||||
#include <r_debug.h>
|
||||
#include <r_asm.h>
|
||||
|
||||
static int x86_nregs = 10;
|
||||
static char *x86_regs[] = {
|
||||
"eax", "ebx", "ecx", "edx", "esi", "edi", "esp", "ebp", "eip",
|
||||
"ax", "bx", "cx", "dx", "si", "di", "sp", "bp", "ip", // 16 tits
|
||||
"ah","al", "bh", "bl", "ch","cl", "dh","dl", // 8 tits
|
||||
NULL };
|
||||
|
||||
#if 0
|
||||
// XXX
|
||||
- we need size of register
|
||||
struct r_reg_item_t {
|
||||
char name[16];
|
||||
char get[128];
|
||||
char set[128];
|
||||
int size;
|
||||
int delta;
|
||||
};
|
||||
|
||||
struct r_reg_arch_t {
|
||||
char *name;
|
||||
int nregs;
|
||||
struct r_reg_item_t regs[128];
|
||||
};
|
||||
|
||||
/* TODO: autogenerate it from a file in C or perl */
|
||||
struct r_reg_arch_t x86 {
|
||||
.name = "",
|
||||
.nregs = 32,
|
||||
.regs = { {
|
||||
.name = "eax",
|
||||
.size = 32,
|
||||
.delta = offsetof(r_regs_t, eax)
|
||||
},{
|
||||
.name = "ebx",
|
||||
.size = 32,
|
||||
.delta = offsetof(r_regs_t, ebx)
|
||||
}
|
||||
R_API struct r_reg_t *r_reg_init(struct r_reg_t *reg)
|
||||
{
|
||||
if (reg) {
|
||||
reg->h = NULL;
|
||||
INIT_LIST_HEAD(®->handles);
|
||||
}
|
||||
return reg;
|
||||
}
|
||||
|
||||
R_API struct r_reg_t *r_reg_new()
|
||||
{
|
||||
struct r_reg_t *r = MALLOC_STRUCT(struct r_reg_t);
|
||||
return r_reg_init(r);
|
||||
}
|
||||
|
||||
R_API struct r_reg_t *r_reg_free(struct r_reg_t *reg)
|
||||
{
|
||||
if (reg) {
|
||||
// TODO: free more things here
|
||||
free(reg);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
int r_reg_set_arch(struct r_reg_t *reg, int arch, int bits)
|
||||
{
|
||||
int ret = R_TRUE;
|
||||
|
||||
switch(arch) {
|
||||
case R_DBG_ARCH_X86:
|
||||
switch(bits) {
|
||||
case 64:
|
||||
reg->nregs = x86_nregs;
|
||||
reg->regs = x86_regs;
|
||||
break;
|
||||
case 32:
|
||||
reg->nregs = x86_nregs;
|
||||
reg->regs = x86_regs;
|
||||
break;
|
||||
case 16:
|
||||
reg->nregs = x86_nregs;
|
||||
reg->regs = x86_regs;
|
||||
int ret = R_FALSE;
|
||||
struct list_head *pos;
|
||||
list_for_each(pos, ®->handles) {
|
||||
struct r_reg_handle_t *h = list_entry(pos, struct r_reg_handle_t, list);
|
||||
if (h->is_arch(arch, bits)) {
|
||||
reg->h = h;
|
||||
ret = R_TRUE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
/* TODO: add more architectures */
|
||||
case R_DBG_ARCH_ARM:
|
||||
case R_DBG_ARCH_MIPS:
|
||||
default:
|
||||
ret = R_FALSE;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/* radare - LGPL - Copyright 2009 pancake<nopcode.org> */
|
||||
|
||||
#include <r_types.h>
|
||||
#include <r_debug.h>
|
||||
|
||||
R_API struct r_regset_t *r_regset_new(int size)
|
||||
{
|
||||
struct r_regset_t *r = MALLOC_STRUCT(struct r_regset_t);
|
||||
if (r != NULL) {
|
||||
r->regs = MALLOC_STRUCTS(struct r_reg_t, size);
|
||||
if (r->regs == NULL) {
|
||||
free(r);
|
||||
r = NULL;
|
||||
} else r->nregs = size;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
R_API void r_regset_free(struct r_regset_t *r)
|
||||
{
|
||||
if (r) {
|
||||
free(r->regs);
|
||||
free(r);
|
||||
}
|
||||
}
|
||||
|
||||
R_API int r_regset_set(struct r_regset_t *r, int idx, const char *name, ut64 value)
|
||||
{
|
||||
if (idx<0 || idx>=r->nregs) {
|
||||
eprintf("Out of range register index! More registers needs to be allocated in r_regset_new()\n");
|
||||
return R_FALSE;
|
||||
}
|
||||
if (r==NULL || r->regs==NULL) {
|
||||
eprintf("No regset given in regset_set\n");
|
||||
return R_FALSE;
|
||||
}
|
||||
strncpy(r->regs[idx].name, name, R_REG_NAME_MAX);
|
||||
r->regs[idx].value = value;
|
||||
r->regs[idx].isfloat = R_FALSE;
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
R_API struct r_regset_t *r_regset_diff(struct r_regset_t *a, struct r_regset_t *b)
|
||||
{
|
||||
struct r_regset_t *rs;
|
||||
// NULL FOR TEH LULZ :D
|
||||
if (a == NULL || b == NULL)
|
||||
return NULL;
|
||||
rs = MALLOC_STRUCT(struct r_regset_t);
|
||||
if (rs != NULL) {
|
||||
memcpy(rs, a, sizeof(struct r_regset_t));
|
||||
// TODO: do the diff here
|
||||
}
|
||||
return NULL;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/* radare - LGPL - Copyright 2009 pancake<nopcode.org> */
|
||||
|
||||
[CCode (cheader_filename="r_bp.h", cprefix="r_bp", lower_case_cprefix="r_bp_")]
|
||||
namespace Radare {
|
||||
[Compact]
|
||||
[CCode (cname="struct r_bp_t", free_function="r_bp_free", cprefix="r_bp_")]
|
||||
public class Breakpoint {
|
||||
public Breakpoint();
|
||||
public void enable(uint64 addr, bool enabled);
|
||||
public bool at_addr(uint64 addr, int rwx);
|
||||
public bool add_sw(uint8* obytes, uint64 addr, int len, int rwx);
|
||||
public bool add_hw(uint8* obytes, uint64 addr, int len, int rwx);
|
||||
public bool add_fault(uint64 addr, int len, int rwx);
|
||||
public int add_cond(string cond);
|
||||
public bool del(uint64 addr);
|
||||
public bool del_cond(int idx);
|
||||
public int list(bool rfmt);
|
||||
|
||||
[CCode (cprefic="R_BP")]
|
||||
public enum Protection {
|
||||
READ,
|
||||
WRITE,
|
||||
EXEC
|
||||
}
|
||||
|
||||
[CCode (cprefic="R_BP_TYPE")]
|
||||
public enum Type {
|
||||
SW,
|
||||
HW,
|
||||
COND
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname="struct r_bp_item_t", cprefix="r_bp_item")]
|
||||
public struct Item {
|
||||
uint64 addr;
|
||||
int size;
|
||||
int rwx;
|
||||
int hw;
|
||||
int trace;
|
||||
int enabled;
|
||||
uint8* obytes;
|
||||
uint8* bbytes;
|
||||
int[] pids;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ namespace Radare {
|
|||
[Compact]
|
||||
[CCode (cname="struct r_debug_t", free_function="r_debug_free", cprefix="r_debug_")]
|
||||
public class Debug {
|
||||
public Breakpoint bp;
|
||||
public Debug();
|
||||
|
||||
/* life cycle */
|
||||
|
|
|
@ -45,6 +45,8 @@ core:
|
|||
-lr_search -Wl,-R../../search -L../../search \
|
||||
-lr_cmd -Wl,-R../../cmd -L../../cmd \
|
||||
-lr_hash -Wl,-R../../hash -L../../hash \
|
||||
-lr_reg -Wl,-R../../reg -L../../reg \
|
||||
-lr_bp -Wl,-R../../bp -L../../bp \
|
||||
-g -o core
|
||||
|
||||
search:
|
||||
|
|
|
@ -7,5 +7,5 @@ Name: r_core
|
|||
Description: radare foundation libraries
|
||||
Version:
|
||||
Requires:
|
||||
Libs: -L${libdir} -lr_core -lr_config -lr_cons -lr_line -lr_io -lr_cmd -lr_util -lr_print -lr_flags -lr_asm -lr_lib -lr_macro -lr_debug -lr_hash -lr_bin -lr_lang -lr_io -lr_asm -lr_anal -lr_parse -lr_config -lr_macro -lr_print -lr_bininfo -lr_bp
|
||||
Libs: -L${libdir} -lr_core -lr_config -lr_cons -lr_line -lr_io -lr_cmd -lr_util -lr_print -lr_flags -lr_asm -lr_lib -lr_macro -lr_debug -lr_hash -lr_bin -lr_lang -lr_io -lr_asm -lr_anal -lr_parse -lr_config -lr_macro -lr_print -lr_bininfo -lr_bp -lr_reg
|
||||
Cflags: -I${includedir}/libr
|
||||
|
|
|
@ -5,7 +5,7 @@ includedir=${prefix}/include
|
|||
|
||||
Name: r_debug
|
||||
Description: radare foundation libraries
|
||||
Version:
|
||||
Version: 0.2
|
||||
Requires:
|
||||
Libs: -L${libdir} -lr_debug
|
||||
Cflags: -I${includedir}/libr
|
||||
|
|
|
@ -5,7 +5,7 @@ includedir=${prefix}/include
|
|||
|
||||
Name: r_io
|
||||
Description: radare foundation libraries
|
||||
Version:
|
||||
Version: 0.2
|
||||
Requires:
|
||||
Libs: -L${libdir} -lr_io
|
||||
Libs: -L${libdir} -lr_io -lr_lib -lr_util
|
||||
Cflags: -I${includedir}/libr
|
||||
|
|
|
@ -5,7 +5,7 @@ includedir=${prefix}/include
|
|||
|
||||
Name: r_parse
|
||||
Description: radare foundation libraries
|
||||
Version:
|
||||
Version: 0.2
|
||||
Requires:
|
||||
Libs: -L${libdir} -lr_parse
|
||||
Libs: -L${libdir} -lr_parse -lr_lib
|
||||
Cflags: -I${includedir}/libr
|
||||
|
|
Loading…
Reference in New Issue