* 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:
pancake 2009-04-04 19:38:59 +00:00
parent 1129f1a2fc
commit 8cb24fdc91
10 changed files with 252 additions and 15 deletions

View File

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

View File

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

View File

@ -56,4 +56,3 @@ R_API void r_flag_space_list(struct r_flag_t *f)
(i==f->space_idx)?'*':' ', f->space[i]);
}
}

7
libr/flags/t/Makefile Normal file
View File

@ -0,0 +1,7 @@
all: test
test:
${CC} -g -I ../../include test.c ../*.o -lr_util -L../util -o test
clean:
rm -f test

17
libr/flags/t/test.c Normal file
View File

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

26
libr/include/btree.h Normal file
View File

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

View File

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

View File

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

View File

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

172
libr/util/btree.c Normal file
View File

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