radare2/libr/anal/anal.c

236 lines
5.1 KiB
C
Raw Normal View History

/* radare - LGPL - Copyright 2009-2010 */
/* nibble<.ds@gmail.com> */
/* pancake<nopcode.org> */
#include <r_anal.h>
#include <r_util.h>
R_API struct r_anal_t *r_anal_new()
{
return r_anal_init (MALLOC_STRUCT (struct r_anal_t));
}
R_API struct r_anal_t *r_anal_free(struct r_anal_t *a)
{
/* TODO: Free a->anals here */
free(a);
return NULL;
}
R_API struct r_anal_t *r_anal_init(struct r_anal_t *anal)
{
if (anal) {
anal->user = NULL;
anal->ctx = NULL;
anal->cur = NULL;
r_anal_set_bits (anal, 32);
r_anal_set_big_endian (anal, R_FALSE);
INIT_LIST_HEAD (&anal->anals);
}
return anal;
}
R_API void r_anal_set_user_ptr(struct r_anal_t *anal, void *user)
{
anal->user = user;
}
R_API int r_anal_add(struct r_anal_t *anal, struct r_anal_handle_t *foo)
{
if (foo->init)
foo->init(anal->user);
list_add_tail(&(foo->list), &(anal->anals));
return R_TRUE;
}
// TODO: Must be deprecated
R_API int r_anal_list(struct r_anal_t *anal)
{
struct list_head *pos;
list_for_each_prev(pos, &anal->anals) {
struct r_anal_handle_t *h = list_entry(pos, struct r_anal_handle_t, list);
printf(" %s: %s\n", h->name, h->desc);
}
return R_FALSE;
}
R_API int r_anal_use(struct r_anal_t *anal, const char *name)
{
struct list_head *pos;
list_for_each_prev(pos, &anal->anals) {
struct r_anal_handle_t *h = list_entry(pos, struct r_anal_handle_t, list);
if (!strcmp(h->name, name)) {
anal->cur = h;
return R_TRUE;
}
}
return R_FALSE;
}
R_API int r_anal_set_bits(struct r_anal_t *anal, int bits)
{
switch (bits) {
case 8:
case 16:
case 32:
case 64:
anal->bits = bits;
return R_TRUE;
}
return R_FALSE;
}
R_API int r_anal_set_big_endian(struct r_anal_t *anal, int bigend)
{
anal->big_endian = bigend;
return R_TRUE;
}
R_API int r_anal_set_pc(struct r_anal_t *a, ut64 pc)
{
a->pc = pc;
return R_TRUE;
}
2009-03-31 20:05:18 +00:00
R_API int r_anal_aop(struct r_anal_t *anal, struct r_anal_aop_t *aop, void *data)
2009-03-31 20:05:18 +00:00
{
if (anal && anal->cur && anal->cur->aop)
2009-03-31 20:05:18 +00:00
return anal->cur->aop(anal, aop, data);
return R_FALSE;
}
R_API struct r_anal_fcn_t *r_anal_funcions_get(struct r_anal_t *anal, ut8 *buf, ut64 len)
2009-05-01 23:08:57 +00:00
{
return NULL;
2009-05-01 23:08:57 +00:00
}
R_API struct r_anal_refline_t *r_anal_reflines_get(struct r_anal_t *anal, ut8 *buf, ut64 len, int nlines, int linesout)
{
struct r_anal_refline_t *list = MALLOC_STRUCT(struct r_anal_refline_t);
struct r_anal_refline_t *list2;
struct r_anal_aop_t aop;
ut8 *ptr = buf;
ut8 *end = buf + len;
ut64 opc = anal->pc;
2009-04-06 15:11:37 +00:00
int sz = 0, index = 0;
INIT_LIST_HEAD(&(list->list));
/* analyze code block */
while(ptr<end) {
if (nlines != -1 && --nlines == 0)
break;
#if 0
if (config.interrupted)
break;
int dt = data_type(config.seek+bsz);
if (dt != DATA_FUN && dt != DATA_CODE) {
ut64 sz = data_size(config.seek+bsz);
if (sz > 0) {
ptr= ptr +sz;
bsz=bsz+sz;
continue;
}
}
#endif
2009-04-06 15:11:37 +00:00
anal->pc += sz;
sz = r_anal_aop (anal, &aop, ptr);
if (sz > 0) {
/* store data */
switch(aop.type) {
2009-11-23 16:49:40 +00:00
case R_ANAL_OP_TYPE_CALL:
case R_ANAL_OP_TYPE_CJMP:
case R_ANAL_OP_TYPE_JMP:
if (!linesout && (aop.jump > opc+len || aop.jump < opc))
goto __next;
if (aop.jump == 0)
goto __next;
list2 = MALLOC_STRUCT(struct r_anal_refline_t);
list2->from = anal->pc;
list2->to = aop.jump;
list2->index = index++;
list_add_tail(&(list2->list), &(list->list));
break;
}
} else sz = 1;
__next:
ptr = ptr + sz;
}
anal->pc = opc;
2009-04-01 23:09:38 +00:00
return list;
}
/* umf..this should probably be outside this file */
R_API int r_anal_reflines_str(struct r_anal_t *anal, struct r_anal_refline_t *list, char *str, int opts)
{
struct r_anal_refline_t *ref;
struct list_head *pos;
int dir = 0;
char ch = ' ';
int linestyle = opts & R_ANAL_REFLINE_STYLE;
int wide = opts & R_ANAL_REFLINE_WIDE;
if (!list)
return R_FALSE;
strcpy (str, " ");
2009-04-06 15:11:37 +00:00
for (pos = linestyle?(&(list->list))->next:(&(list->list))->prev;
pos != (&(list->list)); pos = linestyle?pos->next:pos->prev) {
ref = list_entry(pos, struct r_anal_refline_t, list);
2009-04-06 15:11:37 +00:00
if (anal->pc == ref->to) dir = 1;
// TODO: use else here
2009-04-06 15:11:37 +00:00
if (anal->pc == ref->from) dir = 2;
// TODO: if dir==1
if (anal->pc == ref->to) {
if (ref->from > ref->to)
strcat(str, ".");
2009-04-06 15:11:37 +00:00
else strcat(str, "`");
ch = '-';
2009-04-06 15:11:37 +00:00
} else if (anal->pc == ref->from) {
if (ref->from > ref->to)
strcat(str, "`");
else strcat(str, ".");
ch = '=';
} else if (ref->from < ref->to) { /* down */
if (anal->pc > ref->from && anal->pc < ref->to) {
if (ch=='-'||ch=='=')
r_str_concatch(str, ch);
else strcat(str, "|");
} else r_str_concatch(str, ch);
} else { /* up */
if (anal->pc < ref->from && anal->pc > ref->to) {
if (ch=='-'||ch=='=')
r_str_concatch(str, ch);
else strcat(str, "|");
} else r_str_concatch(str, ch);
}
if (wide) {
2009-04-06 15:11:37 +00:00
if (ch == '=' || ch == '-')
r_str_concatch(str, ch);
2009-04-06 15:11:37 +00:00
else strcat(str, " ");
}
}
2009-04-06 15:11:37 +00:00
switch(dir) {
case 1: strcat(str, "-> "); break;
case 2: strcat(str, "=< "); break;
default: strcat(str, " "); break;
}
return R_TRUE;
}
// TODO: merge algorithms from r1 (do we need ebp?)
// TODO: must return a linked list or r_iter
R_API int r_anal_backtrace(struct r_anal_t *anal, const ut8 *buf, ut64 esp)
{
return R_FALSE;
}