* Initial import of the binary tree search algorithm
- ATM lives in r_util, but should be moved to btree.h at some point Like the kernel's list.h does. - No node tree path find optimization yet * Integrate btree with r_flag API - Accelerates the resolution of flags per offset - At some point we will need to use paralel tree's to store all the nodes optimized by different fields (name, offset, ...) * Added test program for flags and btree algorithm * Change the print format of flags in the disassembly
This commit is contained in:
parent
1129f1a2fc
commit
8cb24fdc91
|
@ -392,7 +392,7 @@ static int cmd_print(void *data, const char *input)
|
|||
if (show_bytes) {
|
||||
struct r_flag_item_t *flag = r_flag_get_i(&core->flags, core->seek+idx);
|
||||
if (flag) {
|
||||
r_cons_printf("=> %11s ", flag->name);
|
||||
r_cons_printf("*[ %10s] ", flag->name);
|
||||
} else r_cons_printf("%14s ", asmop.buf_hex);
|
||||
}
|
||||
if (pseudo) {
|
||||
|
|
|
@ -4,6 +4,19 @@
|
|||
#include <r_cons.h> // TODO: drop dependency
|
||||
#include <r_util.h> // TODO: drop dependency
|
||||
#include <stdio.h>
|
||||
#include <btree.h>
|
||||
|
||||
//static int cmp(static void *a, static void *b)
|
||||
static int cmp(const void *a, const void *b)
|
||||
{
|
||||
struct r_flag_item_t *fa = (struct r_flag_item_t *)a;
|
||||
struct r_flag_item_t *fb = (struct r_flag_item_t *)b;
|
||||
int ret = 0;
|
||||
/* we cannot use a simple substraction coz u64 > s32 :) */
|
||||
if (fa->offset > fb->offset) ret = 1;
|
||||
else if (fa->offset < fb->offset) ret = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
R_API int r_flag_init(struct r_flag_t *f)
|
||||
{
|
||||
|
@ -12,6 +25,7 @@ R_API int r_flag_init(struct r_flag_t *f)
|
|||
f->space_idx = -1;
|
||||
f->space_idx2 = -1;
|
||||
f->base = 0LL;
|
||||
f->tree = NULL; // btree_init()
|
||||
for(i=0;i<R_FLAG_SPACES_MAX;i++)
|
||||
f->space[i] = NULL;
|
||||
return 0;
|
||||
|
@ -28,8 +42,8 @@ R_API struct r_flag_item_t *r_flag_list(struct r_flag_t *f, int rad)
|
|||
struct list_head *pos;
|
||||
list_for_each_prev(pos, &f->flags) {
|
||||
struct r_flag_item_t *flag = list_entry(pos, struct r_flag_item_t, list);
|
||||
if (rad) printf("f %s %lld @ 0x%08llx\n", flag->name,
|
||||
flag->size, flag->offset);
|
||||
if (rad) printf("f %s %lld @ 0x%08llx\n",
|
||||
flag->name, flag->size, flag->offset);
|
||||
else printf("0x%08llx %lld %s\n",
|
||||
flag->offset, flag->size, flag->name);
|
||||
}
|
||||
|
@ -51,13 +65,8 @@ R_API struct r_flag_item_t *r_flag_get(struct r_flag_t *f, const char *name)
|
|||
|
||||
R_API struct r_flag_item_t *r_flag_get_i(struct r_flag_t *f, u64 off)
|
||||
{
|
||||
struct list_head *pos;
|
||||
list_for_each_prev(pos, &f->flags) {
|
||||
struct r_flag_item_t *flag = list_entry(pos, struct r_flag_item_t, list);
|
||||
if (off == flag->offset)
|
||||
return flag;
|
||||
}
|
||||
return NULL;
|
||||
struct r_flag_item_t tmp = { .offset = off };
|
||||
return btree_get(f->tree, &tmp, cmp);
|
||||
}
|
||||
|
||||
R_API int r_flag_unset(struct r_flag_t *f, const char *name)
|
||||
|
@ -65,8 +74,10 @@ R_API int r_flag_unset(struct r_flag_t *f, const char *name)
|
|||
struct r_flag_item_t *item;
|
||||
item = r_flag_get(f, name);
|
||||
/* MARK: entrypoint to remove flags */
|
||||
if (item)
|
||||
if (item) {
|
||||
btree_del(f->tree, item, cmp, NULL);
|
||||
list_del(&item->list);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -113,9 +124,11 @@ R_API int r_flag_set(struct r_flag_t *fo, const char *name, u64 addr, u32 size,
|
|||
/* MARK: entrypoint for flag addition */
|
||||
flag = malloc(sizeof(struct r_flag_item_t));
|
||||
memset(flag,'\0', sizeof(struct r_flag_item_t));
|
||||
flag->offset = addr + fo->base;
|
||||
btree_add(&fo->tree, flag, cmp);
|
||||
list_add_tail(&(flag->list), &fo->flags);
|
||||
if (flag==NULL)
|
||||
return 1;
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
strncpy(flag->name, name, R_FLAG_NAME_SIZE);
|
||||
|
@ -127,5 +140,5 @@ R_API int r_flag_set(struct r_flag_t *fo, const char *name, u64 addr, u32 size,
|
|||
flag->format = 0; // XXX
|
||||
flag->cmd = NULL;
|
||||
|
||||
return 0;
|
||||
return R_FALSE;
|
||||
}
|
||||
|
|
|
@ -56,4 +56,3 @@ R_API void r_flag_space_list(struct r_flag_t *f)
|
|||
(i==f->space_idx)?'*':' ', f->space[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
all: test
|
||||
|
||||
test:
|
||||
${CC} -g -I ../../include test.c ../*.o -lr_util -L../util -o test
|
||||
|
||||
clean:
|
||||
rm -f test
|
|
@ -0,0 +1,17 @@
|
|||
#include <r_flags.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
struct r_flag_t flags;
|
||||
struct r_flag_item_t *fi;
|
||||
|
||||
r_flag_init(&flags);
|
||||
r_flag_set(&flags, "foo", 1024, 50, 0);
|
||||
|
||||
fi = r_flag_get_i(&flags, 1024);
|
||||
if (fi) {
|
||||
printf("FLAG FOUND '%s'\n", fi->name);
|
||||
} else printf("FLAG NOT FOUND\n");
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef _INCLUDE_BTREE_H_
|
||||
#define _INCLUDE_BTREE_H_
|
||||
|
||||
#include "r_types.h"
|
||||
|
||||
struct btree_node
|
||||
{
|
||||
void *data;
|
||||
int hits; // profiling
|
||||
struct btree_node *left;
|
||||
struct btree_node *right;
|
||||
};
|
||||
|
||||
#define BTREE_CMP(x) int (* x )(const void *, const void *)
|
||||
#define BTREE_DEL(x) int (* x )(void *)
|
||||
|
||||
R_API void btree_init(struct btree_node **T);
|
||||
R_API struct btree_node *btree_remove(struct btree_node *p, BTREE_DEL(del));
|
||||
R_API void *btree_search(struct btree_node *proot, void *x, BTREE_CMP(cmp), int parent);
|
||||
R_API int btree_del(struct btree_node *proot, void *x, BTREE_CMP(cmp), BTREE_DEL(del));
|
||||
R_API void *btree_get(struct btree_node *proot, void *x, BTREE_CMP(cmp));
|
||||
R_API void btree_insert(struct btree_node *p,struct btree_node **T, BTREE_CMP(cmp));
|
||||
R_API void btree_add(struct btree_node **T, void *e, BTREE_CMP(cmp));
|
||||
R_API void btree_cleartree(struct btree_node *proot, BTREE_DEL(del));
|
||||
|
||||
#endif
|
|
@ -24,6 +24,7 @@ struct r_flag_t {
|
|||
int space_idx2;
|
||||
u64 base;
|
||||
const char *space[R_FLAG_SPACES_MAX];
|
||||
struct btree_node *tree;
|
||||
struct list_head flags;
|
||||
};
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define _INCLUDE_UTIL_R_
|
||||
|
||||
#include "r_types.h"
|
||||
#include <btree.h>
|
||||
#include "list.h"
|
||||
|
||||
/* r_cache */
|
||||
|
@ -113,4 +114,5 @@ int r_sys_usleep(int usecs);
|
|||
R_API const char *r_sys_getenv(const char *key);
|
||||
R_API int r_sys_setenv(const char *key, const char *value, int ow);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
NAME=r_util
|
||||
OBJ=mem.o num.o str.o re.o hex.o file.o alloca.o float.o prof.o cache.o sys.o
|
||||
OBJ=mem.o num.o str.o re.o hex.o file.o alloca.o float.o prof.o cache.o sys.o btree.o
|
||||
|
||||
#CFLAGS+=-O2
|
||||
#CC=gcc-4.1.1
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
/* radare - LGPL - Copyright 2009 pancake<nopcode.org> */
|
||||
|
||||
#include <btree.h>
|
||||
|
||||
R_API void btree_init(struct btree_node **T)
|
||||
{
|
||||
*T = NULL;
|
||||
}
|
||||
|
||||
R_API struct btree_node *btree_remove(struct btree_node *p, BTREE_DEL(del))
|
||||
{
|
||||
struct btree_node *rp = NULL, *f;
|
||||
if (p==NULL) return p;
|
||||
if (p->right!=NULL) {
|
||||
if (p->left!=NULL) {
|
||||
f = p;
|
||||
rp = p->right;
|
||||
while(rp->left!=NULL) {
|
||||
f = rp;
|
||||
rp = rp->left;
|
||||
}
|
||||
if (f!=p) {
|
||||
f->left = rp->right;
|
||||
rp->right = p->right;
|
||||
rp->left = p->left;
|
||||
} else rp->left = p->left;
|
||||
} else rp = p->right;
|
||||
} else rp = p->left;
|
||||
if (del) del(p->data);
|
||||
free(p);
|
||||
return(rp);
|
||||
}
|
||||
|
||||
R_API void *btree_search(struct btree_node *proot, void *x, BTREE_CMP(cmp), int parent)
|
||||
{
|
||||
struct btree_node *p = NULL;
|
||||
|
||||
if (proot!=NULL) {
|
||||
p = proot;
|
||||
if (cmp (x, proot->data)<0)
|
||||
p = btree_search (proot->left, x, cmp, parent);
|
||||
else if (cmp(x, proot->data)>0)
|
||||
p = btree_search (proot->right, x, cmp, parent);
|
||||
}
|
||||
/* node found */
|
||||
if (p) {
|
||||
if (parent)
|
||||
return proot;
|
||||
return p;
|
||||
} return NULL;
|
||||
}
|
||||
|
||||
R_API int btree_del(struct btree_node *proot, void *x, BTREE_CMP(cmp), BTREE_DEL(del))
|
||||
{
|
||||
struct btree_node *p = btree_search (proot, x, cmp, 1);
|
||||
if (p) {
|
||||
p->right = btree_remove (p->left, del);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
R_API void *btree_get(struct btree_node *proot, void *x, BTREE_CMP(cmp))
|
||||
{
|
||||
struct btree_node *p = btree_search (proot, x, cmp, 0);
|
||||
if (p) {
|
||||
p->hits++;
|
||||
return p->data;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
R_API void btree_cleartree(struct btree_node *proot, BTREE_DEL(del))
|
||||
{
|
||||
if (proot!=NULL) {
|
||||
btree_cleartree (proot->left, del);
|
||||
btree_cleartree (proot->right, del);
|
||||
if (del) del (proot->data);
|
||||
free (proot);
|
||||
}
|
||||
}
|
||||
|
||||
R_API void btree_insert(struct btree_node *p,struct btree_node **T, BTREE_CMP(cmp))
|
||||
{
|
||||
int ret = cmp (p->data,(*T)->data);
|
||||
if (ret<0) {
|
||||
if ((*T)->left) btree_insert (p, &(*T)->left, cmp);
|
||||
else (*T)->left=p;
|
||||
} else if (ret>0) {
|
||||
if ((*T)->right) btree_insert (p, &(*T)->right, cmp);
|
||||
else (*T)->right=p;
|
||||
}
|
||||
}
|
||||
|
||||
R_API void btree_add(struct btree_node **T, void *e, BTREE_CMP(cmp))
|
||||
{
|
||||
struct btree_node *p = (struct btree_node*)
|
||||
malloc(sizeof(struct btree_node));
|
||||
p->data = e;
|
||||
p->hits = 0;
|
||||
p->left = p->right = NULL;
|
||||
if (*T==NULL) *T = p;
|
||||
else btree_insert (p, T, cmp);
|
||||
}
|
||||
|
||||
/*--------------------*/
|
||||
|
||||
#if MAIN
|
||||
|
||||
struct mydata {
|
||||
unsigned long long addr;
|
||||
char *str;
|
||||
};
|
||||
|
||||
int shownode(char *str, struct mydata *m)
|
||||
{
|
||||
if (m == NULL)
|
||||
printf("==> not found\n");
|
||||
else printf("==> %s: %s, %lld\n", str, m->str, m->addr);
|
||||
return 0;
|
||||
}
|
||||
int mycmp(const void *a, const void *b)
|
||||
{
|
||||
struct mydata *ma = (struct mydata *)a;
|
||||
struct mydata *mb = (struct mydata *)b;
|
||||
if (a==NULL || b == NULL)
|
||||
return 0;
|
||||
return (int)(ma->addr-mb->addr);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
struct btree_node *bt = NULL;
|
||||
//btree_init(&bt);
|
||||
|
||||
struct mydata foo = { 10, "hello" };
|
||||
struct mydata bar = { 20, "world" };
|
||||
btree_add(&bt, &foo, mycmp);
|
||||
btree_add(&bt, &bar, mycmp);
|
||||
|
||||
printf("==== go search ====\n");
|
||||
/* find existent data */
|
||||
struct mydata *p = btree_get(bt, &bar, mycmp);
|
||||
shownode("result for 20: ", p);
|
||||
|
||||
printf("==== go search ====\n");
|
||||
/* find unexistent data */
|
||||
struct mydata nop = { 15, NULL };
|
||||
p = btree_get(bt, &nop, mycmp);
|
||||
shownode("result for 15: ", p);
|
||||
|
||||
#if 1
|
||||
printf("==== go remove 20 ====\n");
|
||||
if (btree_del(bt, &bar, mycmp, NULL))
|
||||
printf("node found and removed\n");
|
||||
else printf("oops\n");
|
||||
#endif
|
||||
|
||||
printf("==== go search ====\n");
|
||||
/* find existent data */
|
||||
p = btree_get(bt, &bar, mycmp);
|
||||
shownode("result for 20: ", p);
|
||||
|
||||
printf("==== go search ====\n");
|
||||
/* find existent data */
|
||||
p = btree_get(bt, &foo, mycmp);
|
||||
shownode("result for 10: ", p);
|
||||
|
||||
btree_cleartree(bt, NULL);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
Loading…
Reference in New Issue