2010-01-31 01:30:59 +00:00
|
|
|
/* radare - LGPL - Copyright 2009-2010 */
|
2009-03-31 22:32:26 +00:00
|
|
|
/* nibble<.ds@gmail.com> */
|
|
|
|
/* pancake<nopcode.org> */
|
2009-02-06 17:22:27 +00:00
|
|
|
|
2009-02-15 23:57:03 +00:00
|
|
|
#include <r_anal.h>
|
|
|
|
#include <r_util.h>
|
|
|
|
|
2009-04-11 21:22:20 +00:00
|
|
|
R_API struct r_anal_t *r_anal_new()
|
2009-03-14 11:39:37 +00:00
|
|
|
{
|
2010-01-31 01:30:59 +00:00
|
|
|
return r_anal_init (MALLOC_STRUCT (struct r_anal_t));
|
2009-03-14 11:39:37 +00:00
|
|
|
}
|
|
|
|
|
2009-08-14 00:37:18 +00:00
|
|
|
R_API struct r_anal_t *r_anal_free(struct r_anal_t *a)
|
2009-03-14 11:39:37 +00:00
|
|
|
{
|
2009-08-14 00:37:18 +00:00
|
|
|
/* TODO: Free a->anals here */
|
|
|
|
free(a);
|
2009-03-14 11:39:37 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-01-31 01:30:59 +00:00
|
|
|
R_API struct r_anal_t *r_anal_init(struct r_anal_t *anal)
|
2009-02-06 17:22:27 +00:00
|
|
|
{
|
2010-01-31 01:30:59 +00:00
|
|
|
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;
|
2009-02-06 17:22:27 +00:00
|
|
|
}
|
|
|
|
|
2009-04-11 21:22:20 +00:00
|
|
|
R_API void r_anal_set_user_ptr(struct r_anal_t *anal, void *user)
|
2009-02-06 17:22:27 +00:00
|
|
|
{
|
2009-02-15 23:57:03 +00:00
|
|
|
anal->user = user;
|
2009-02-06 17:22:27 +00:00
|
|
|
}
|
|
|
|
|
2009-04-11 21:22:20 +00:00
|
|
|
R_API int r_anal_add(struct r_anal_t *anal, struct r_anal_handle_t *foo)
|
2009-02-06 17:22:27 +00:00
|
|
|
{
|
2009-02-15 23:57:03 +00:00
|
|
|
if (foo->init)
|
|
|
|
foo->init(anal->user);
|
|
|
|
list_add_tail(&(foo->list), &(anal->anals));
|
2009-02-06 17:22:27 +00:00
|
|
|
return R_TRUE;
|
|
|
|
}
|
2009-02-08 23:19:06 +00:00
|
|
|
|
2009-10-12 15:41:52 +00:00
|
|
|
// TODO: Must be deprecated
|
2009-04-11 21:22:20 +00:00
|
|
|
R_API int r_anal_list(struct r_anal_t *anal)
|
2009-02-15 23:57:03 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2009-10-12 15:41:52 +00:00
|
|
|
R_API int r_anal_use(struct r_anal_t *anal, const char *name)
|
2009-02-15 23:57:03 +00:00
|
|
|
{
|
|
|
|
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);
|
2009-02-19 15:41:51 +00:00
|
|
|
if (!strcmp(h->name, name)) {
|
2009-02-15 23:57:03 +00:00
|
|
|
anal->cur = h;
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
|
2009-04-11 21:22:20 +00:00
|
|
|
R_API int r_anal_set_bits(struct r_anal_t *anal, int bits)
|
2009-02-15 23:57:03 +00:00
|
|
|
{
|
|
|
|
switch (bits) {
|
2009-08-14 00:37:18 +00:00
|
|
|
case 8:
|
2009-02-15 23:57:03 +00:00
|
|
|
case 16:
|
|
|
|
case 32:
|
|
|
|
case 64:
|
|
|
|
anal->bits = bits;
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
2009-09-25 02:04:51 +00:00
|
|
|
return R_FALSE;
|
2009-02-15 23:57:03 +00:00
|
|
|
}
|
|
|
|
|
2009-09-09 00:35:00 +00:00
|
|
|
R_API int r_anal_set_big_endian(struct r_anal_t *anal, int bigend)
|
2009-02-15 23:57:03 +00:00
|
|
|
{
|
2009-09-09 00:35:00 +00:00
|
|
|
anal->big_endian = bigend;
|
2009-02-15 23:57:03 +00:00
|
|
|
return R_TRUE;
|
|
|
|
}
|
2009-02-19 15:41:51 +00:00
|
|
|
|
2009-09-09 00:35:00 +00:00
|
|
|
R_API int r_anal_set_pc(struct r_anal_t *a, ut64 pc)
|
2009-02-19 15:41:51 +00:00
|
|
|
{
|
|
|
|
a->pc = pc;
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
2009-03-31 20:05:18 +00:00
|
|
|
|
2009-09-09 00:35:00 +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
|
|
|
{
|
2010-01-25 10:54:25 +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;
|
|
|
|
}
|
2009-03-31 22:32:26 +00:00
|
|
|
|
2009-09-09 00:35:00 +00:00
|
|
|
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
|
|
|
{
|
2009-08-19 16:38:35 +00:00
|
|
|
return NULL;
|
2009-05-01 23:08:57 +00:00
|
|
|
}
|
|
|
|
|
2009-09-09 00:35:00 +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)
|
2009-03-31 22:32:26 +00:00
|
|
|
{
|
|
|
|
struct r_anal_refline_t *list = MALLOC_STRUCT(struct r_anal_refline_t);
|
|
|
|
struct r_anal_refline_t *list2;
|
2009-04-01 22:41:10 +00:00
|
|
|
struct r_anal_aop_t aop;
|
2009-07-08 11:49:55 +00:00
|
|
|
ut8 *ptr = buf;
|
|
|
|
ut8 *end = buf + len;
|
|
|
|
ut64 opc = anal->pc;
|
2009-04-06 15:11:37 +00:00
|
|
|
int sz = 0, index = 0;
|
2009-03-31 22:32:26 +00:00
|
|
|
|
|
|
|
INIT_LIST_HEAD(&(list->list));
|
|
|
|
|
|
|
|
/* analyze code block */
|
2009-09-09 00:35:00 +00:00
|
|
|
while(ptr<end) {
|
2009-03-31 22:32:26 +00:00
|
|
|
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) {
|
2009-07-08 11:49:55 +00:00
|
|
|
ut64 sz = data_size(config.seek+bsz);
|
2009-03-31 22:32:26 +00:00
|
|
|
if (sz > 0) {
|
|
|
|
ptr= ptr +sz;
|
|
|
|
bsz=bsz+sz;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2009-04-06 15:11:37 +00:00
|
|
|
|
2009-04-02 09:36:34 +00:00
|
|
|
anal->pc += sz;
|
2010-01-31 01:30:59 +00:00
|
|
|
sz = r_anal_aop (anal, &aop, ptr);
|
2009-08-19 16:38:35 +00:00
|
|
|
if (sz > 0) {
|
2009-03-31 22:32:26 +00:00
|
|
|
/* 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:
|
2009-04-03 11:01:58 +00:00
|
|
|
if (!linesout && (aop.jump > opc+len || aop.jump < opc))
|
|
|
|
goto __next;
|
|
|
|
if (aop.jump == 0)
|
|
|
|
goto __next;
|
2009-03-31 22:32:26 +00:00
|
|
|
list2 = MALLOC_STRUCT(struct r_anal_refline_t);
|
2009-04-02 09:36:34 +00:00
|
|
|
list2->from = anal->pc;
|
2009-03-31 22:32:26 +00:00
|
|
|
list2->to = aop.jump;
|
|
|
|
list2->index = index++;
|
|
|
|
list_add_tail(&(list2->list), &(list->list));
|
|
|
|
break;
|
|
|
|
}
|
2009-08-19 16:38:35 +00:00
|
|
|
} else sz = 1;
|
2009-03-31 22:32:26 +00:00
|
|
|
__next:
|
|
|
|
ptr = ptr + sz;
|
|
|
|
}
|
2009-04-01 22:41:10 +00:00
|
|
|
|
2009-04-02 09:36:34 +00:00
|
|
|
anal->pc = opc;
|
|
|
|
|
2009-04-01 23:09:38 +00:00
|
|
|
return list;
|
2009-04-01 22:41:10 +00:00
|
|
|
}
|
|
|
|
|
2010-01-31 01:30:59 +00:00
|
|
|
/* umf..this should probably be outside this file */
|
2009-08-19 16:38:35 +00:00
|
|
|
R_API int r_anal_reflines_str(struct r_anal_t *anal, struct r_anal_refline_t *list, char *str, int opts)
|
2009-04-01 22:41:10 +00:00
|
|
|
{
|
2009-10-12 15:41:52 +00:00
|
|
|
struct r_anal_refline_t *ref;
|
2009-04-01 22:41:10 +00:00
|
|
|
struct list_head *pos;
|
2009-04-02 09:36:34 +00:00
|
|
|
int dir = 0;
|
2009-04-01 22:41:10 +00:00
|
|
|
char ch = ' ';
|
|
|
|
|
2009-04-02 09:36:34 +00:00
|
|
|
int linestyle = opts & R_ANAL_REFLINE_STYLE;
|
|
|
|
int wide = opts & R_ANAL_REFLINE_WIDE;
|
2009-04-01 22:41:10 +00:00
|
|
|
|
|
|
|
if (!list)
|
|
|
|
return R_FALSE;
|
|
|
|
|
2010-01-31 01:30:59 +00:00
|
|
|
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) {
|
2009-10-12 15:41:52 +00:00
|
|
|
ref = list_entry(pos, struct r_anal_refline_t, list);
|
2009-04-02 09:36:34 +00:00
|
|
|
|
2009-04-06 15:11:37 +00:00
|
|
|
if (anal->pc == ref->to) dir = 1;
|
2009-09-09 00:35:00 +00:00
|
|
|
// TODO: use else here
|
2009-04-06 15:11:37 +00:00
|
|
|
if (anal->pc == ref->from) dir = 2;
|
2009-04-01 22:41:10 +00:00
|
|
|
|
2009-09-09 00:35:00 +00:00
|
|
|
// TODO: if dir==1
|
2009-04-03 11:01:58 +00:00
|
|
|
if (anal->pc == ref->to) {
|
2009-04-02 13:07:26 +00:00
|
|
|
if (ref->from > ref->to)
|
|
|
|
strcat(str, ".");
|
2009-04-06 15:11:37 +00:00
|
|
|
else strcat(str, "`");
|
2009-04-02 13:07:26 +00:00
|
|
|
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);
|
|
|
|
}
|
2009-04-02 09:36:34 +00:00
|
|
|
if (wide) {
|
2009-04-06 15:11:37 +00:00
|
|
|
if (ch == '=' || ch == '-')
|
2009-04-06 12:01:56 +00:00
|
|
|
r_str_concatch(str, ch);
|
2009-04-06 15:11:37 +00:00
|
|
|
else strcat(str, " ");
|
2009-04-01 22:41:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-06 15:11:37 +00:00
|
|
|
switch(dir) {
|
|
|
|
case 1: strcat(str, "-> "); break;
|
|
|
|
case 2: strcat(str, "=< "); break;
|
|
|
|
default: strcat(str, " "); break;
|
|
|
|
}
|
2009-04-01 22:41:10 +00:00
|
|
|
|
|
|
|
return R_TRUE;
|
2009-03-31 22:32:26 +00:00
|
|
|
}
|
2009-09-14 22:06:37 +00:00
|
|
|
|
|
|
|
// TODO: merge algorithms from r1 (do we need ebp?)
|
|
|
|
// TODO: must return a linked list or r_iter
|
2009-09-25 02:04:51 +00:00
|
|
|
R_API int r_anal_backtrace(struct r_anal_t *anal, const ut8 *buf, ut64 esp)
|
2009-09-14 22:06:37 +00:00
|
|
|
{
|
2009-09-25 02:04:51 +00:00
|
|
|
return R_FALSE;
|
2009-09-14 22:06:37 +00:00
|
|
|
}
|