* 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:
pancake 2009-09-14 00:37:28 +02:00
parent 669ce0a815
commit 91ad40d663
34 changed files with 1315 additions and 268 deletions

View File

@ -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

View File

@ -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;
}

54
libr/bp/handle.c Normal file
View File

@ -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);
}
}

60
libr/bp/io.c Normal file
View File

@ -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;
}

694
libr/bp/parser.c Normal file
View File

@ -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

50
libr/bp/parser.h Normal file
View File

@ -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

24
libr/bp/traptrace.c Normal file
View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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)
{

View File

@ -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(&regs,0, sizeof(regs));
ptrace(PTRACE_GETREGS, pid, 0, &regs);
#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,

View File

@ -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 */

View File

@ -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");

View File

@ -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,

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -1,4 +1,4 @@
NAME=r_reg
OBJ=reg.o
OBJ=reg.o regset.o
include ../rules.mk

65
libr/reg/p/reg_x86.c Normal file
View File

@ -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;
}

View File

@ -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(&reg->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, &reg->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;
}

55
libr/reg/regset.c Normal file
View File

@ -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;
}

47
libr/vapi/r_bp.vapi Normal file
View File

@ -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;
}
}
}

View File

@ -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 */

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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