diff --git a/libr/include/r_meta.h b/libr/include/r_meta.h index 04a39e75e2..6f51ff4b49 100644 --- a/libr/include/r_meta.h +++ b/libr/include/r_meta.h @@ -1,22 +1,65 @@ #ifndef _INCLUDE_R_META_H_ #define _INCLUDE_R_META_H_ +#include +#include +#include + +struct r_meta_count_t { + int functions; + int xref_code; + int xref_data; + /* TODO: ... */ +}; + /* old data_t */ struct r_meta_item_t { u64 from; u64 to; - int type; - int times; u64 size; - char arg[128]; + int type; +// int times; + char *str; struct list_head list; }; struct r_meta_t { -// struct reflines_t *reflines = NULL; struct list_head data; - struct list_head comments; - struct list_head xrefs; +// struct reflines_t *reflines = NULL; +// struct list_head comments; +// struct list_head xrefs; }; +enum { + R_META_WHERE_PREV = -1, + R_META_WHERE_HERE = 0, + R_META_WHERE_NEXT = 1, +}; + +enum { + R_META_ANY = -1, + /* content type */ + R_META_DATA = 0, + R_META_CODE, + R_META_STRING, + R_META_STRUCT, + /* line */ + R_META_FUNCTION, + R_META_COMMENT, + R_META_FOLDER, + R_META_XREF_CODE, + R_META_XREF_DATA, +}; + +int r_meta_init(struct r_meta_t *m); +struct r_meta_t *r_meta_new(); +void r_meta_free(struct r_meta_t *m); +int r_meta_count(struct r_meta_t *m, int type, u64 from, u64 to, struct r_meta_count_t *c); +char *r_meta_get_string(struct r_meta_t *m, int type, u64 addr); +int r_meta_del(struct r_meta_t *m, int type, u64 from, u64 size, const char *str); +int r_meta_add(struct r_meta_t *m, int type, u64 from, u64 size, const char *str); +struct r_meta_item_t *r_meta_find(struct r_meta_t *m, u64 off, int type, int where); +const char *r_meta_type_to_string(int type); +int r_meta_list(struct r_meta_t *m, int type); + #endif diff --git a/libr/include/r_util.h b/libr/include/r_util.h index 0ef17d2cb6..4506eba871 100644 --- a/libr/include/r_util.h +++ b/libr/include/r_util.h @@ -75,6 +75,8 @@ int r_str_re_replace(const char *str, const char *reg, const char *sub); char *r_str_sub(char *string, char *pat, char *rep, int global); int r_str_escape(char *buf); char *r_str_home(const char *str); +char *r_str_concat(char *ptr, const char *string); +char *r_str_concatf(char *ptr, const char *fmt, ...); /* hex */ int r_hex_pair2bin(const char *arg); diff --git a/libr/meta/Makefile b/libr/meta/Makefile new file mode 100644 index 0000000000..c9494f0abb --- /dev/null +++ b/libr/meta/Makefile @@ -0,0 +1,4 @@ +NAME=r_meta +OBJ=meta.o + +include ../rules.mk diff --git a/libr/meta/README b/libr/meta/README index 96b3b0be6c..c28faeb586 100644 --- a/libr/meta/README +++ b/libr/meta/README @@ -10,31 +10,6 @@ r_meta ** We can store multiple linked lists depending on type of data, to reduce the search space. -enum { - R_META_DATA, - R_META_CODE, - R_META_CODE_XREF, - R_META_DATA_XREF, - R_META_STRING, - R_META_FUNCTION, - R_META_STRUCT, - R_META_COMMENT, - R_META_FOLDER -} - -struct r_meta_item_t { - int type; - u64 addr; - u64 size; - char *data; - struct list_head list; -}; - -struct r_meta_t { - struct list_head comments; - struct list_head xrefs; -}; - struct r_meta_t * meta = r_meta_new(); /* get list of xrefs to this addr */ diff --git a/libr/meta/meta.c b/libr/meta/meta.c index ffe866e2bb..c54ee551b1 100644 --- a/libr/meta/meta.c +++ b/libr/meta/meta.c @@ -2,6 +2,12 @@ #include "r_meta.h" +int r_meta_init(struct r_meta_t *m) +{ + INIT_LIST_HEAD(&m->data); + return R_TRUE; +} + struct r_meta_t *r_meta_new() { struct r_meta_t *m = MALLOC_STRUCT(struct r_meta_t); @@ -11,35 +17,173 @@ struct r_meta_t *r_meta_new() void r_meta_free(struct r_meta_t *m) { + /* TODO: memory leak */ free(m); } -int r_meta_init(struct r_meta_t *m) -{ - INIT_LIST_HEAD(&m->data); - INIT_LIST_HEAD(&m->comments); - INIT_LIST_HEAD(&m->xrefs); - return R_TRUE; -} - -/* snippet from data.c */ -/* XXX: we should add a 4th arg to define next or prev */ -u64 r_meta_prev(struct r_meta_t *m, u64 off, int type) +int r_meta_count(struct r_meta_t *m, int type, u64 from, u64 to, struct r_meta_count_t *c) { struct list_head *pos; - u64 ret = 0; + int count = 0; list_for_each(pos, &m->data) { struct r_meta_item_t *d = (struct r_meta_item_t *) list_entry(pos, struct r_meta_item_t, list); - if (d->type == type) { - if (d->from < off && d->to > off) - ret = d->from; + if (d->type == type || type == R_META_ANY) { + if (from >= d->from && d->to < to) { + if (c) { + /* */ + } + count++; + } + } + } + return count; +} + +char *r_meta_get_string(struct r_meta_t *m, int type, u64 addr) +{ + char *str = NULL; + struct list_head *pos; + + switch(type) { + case R_META_FUNCTION: + case R_META_COMMENT: + case R_META_FOLDER: + case R_META_XREF_CODE: + case R_META_XREF_DATA: + case R_META_ANY: + break; + case R_META_CODE: + case R_META_DATA: + case R_META_STRING: + case R_META_STRUCT: + /* we should remove overlapped types and so on.. */ + return "(Unsupported meta type)"; + break; + default: + fprintf(stderr, "Unhandled\n"); + return "(Unhandled meta type)"; + } + list_for_each(pos, &m->data) { + struct r_meta_item_t *d = (struct r_meta_item_t *) + list_entry(pos, struct r_meta_item_t, list); + if (d->type == type || type == R_META_ANY) { + if (d->from == addr) + switch(d->type) { + case R_META_FUNCTION: + str = r_str_concatf(str, "; FUNCTION SIZE %lld\n", d->size); + break; + case R_META_COMMENT: + str = r_str_concatf(str, "; %s\n", d->str); + break; + case R_META_FOLDER: + str = r_str_concatf(str, "; FOLDER %lld bytes\n", d->size); + break; + case R_META_XREF_CODE: + str = r_str_concatf(str, "; CODE XREF FROM 0x%08llx\n", d->to); + break; + case R_META_XREF_DATA: + str = r_str_concatf(str, "; DATA XREF FROM 0x%08llx\n", d->to); + break; + } + } + } + return str; +} + +int r_meta_del(struct r_meta_t *m, int type, u64 from, u64 size, const char *str) +{ + int ret = R_FALSE; + struct list_head *pos, *n; + + list_for_each_safe(pos, n, &m->data) { + struct r_meta_item_t *d = (struct r_meta_item_t *) + list_entry(pos, struct r_meta_item_t, list); + if (d->type == type || type == R_META_ANY) { + if (str != NULL && !strstr(d->str, str)) + continue; + if (from >= d->from && from <= d->to) { + free(d->str); + list_del(&(d->list)); + ret = R_TRUE; + } } } return ret; } +int r_meta_add(struct r_meta_t *m, int type, u64 from, u64 size, const char *str) +{ + struct r_meta_item_t *mi; + switch(type) { + case R_META_CODE: + r_meta_del(m, R_META_CODE, from, size, str); + break; + case R_META_DATA: + case R_META_STRING: + case R_META_STRUCT: + /* we should remove overlapped types and so on.. */ + case R_META_FUNCTION: + case R_META_COMMENT: + case R_META_FOLDER: + case R_META_XREF_CODE: + case R_META_XREF_DATA: + mi = MALLOC_STRUCT(struct r_meta_item_t); + mi->type = type; + mi->from = from; + mi->size = size; + mi->to = from+size; + if (str) mi->str = strdup(str); + else mi->str = NULL; + list_add(&(mi->list), &m->data); + break; + default: + return R_FALSE; + } + return R_TRUE; +} + +/* snippet from data.c */ +/* XXX: we should add a 4th arg to define next or prev */ +struct r_meta_item_t *r_meta_find(struct r_meta_t *m, u64 off, int type, int where) +{ + struct r_meta_item_t *it = NULL; + struct list_head *pos; + + list_for_each(pos, &m->data) { + struct r_meta_item_t *d = (struct r_meta_item_t *) + list_entry(pos, struct r_meta_item_t, list); + if (d->type == type || type == R_META_ANY) { + switch(where) { + case R_META_WHERE_PREV: + if (d->from < off) { + if (it) { + if (d->from > it->from) + it = d; + } else it = d; + } + break; + case R_META_WHERE_HERE: + if (d->from < off && d->to > off) + it = d; + break; + case R_META_WHERE_NEXT: + if (d->from > off) { + if (it) { + if (d->from < it->from) + it = d; + } else it = d; + } + break; + } + } + } + return it; +} + +#if 0 + /* not necessary */ //int data_get_fun_for(u64 addr, u64 *from, u64 *to) int r_meta_get_bounds(struct r_meta_t *m, u64 addr, int type, u64 *from, u64 *to) { @@ -65,3 +209,38 @@ int r_meta_get_bounds(struct r_meta_t *m, u64 addr, int type, u64 *from, u64 *to } return 0; } +#endif + +const char *r_meta_type_to_string(int type) +{ + switch(type) { + case R_META_CODE: return "Cc"; + case R_META_DATA: return "Cd"; + case R_META_STRING: return "Cs"; + case R_META_STRUCT: return "Cm"; + case R_META_FUNCTION: return "CF"; + case R_META_COMMENT: return "CC"; + case R_META_FOLDER: return "CF"; + case R_META_XREF_CODE: return "Cx"; + case R_META_XREF_DATA: return "CX"; + } + return "(...)"; +} + +int r_meta_list(struct r_meta_t *m, int type) +{ + int count = 0; + struct list_head *pos; + + list_for_each(pos, &m->data) { + struct r_meta_item_t *d = (struct r_meta_item_t *) + list_entry(pos, struct r_meta_item_t, list); + if (d->type == type || type == R_META_ANY) { + printf("%s 0x%08llx 0x%08llx %d %s\n", + r_meta_type_to_string(d->type), + d->from, d->to, (int)(d->to-d->from), d->str); + count++; + } + } + return count; +} diff --git a/libr/meta/t/Makefile b/libr/meta/t/Makefile new file mode 100644 index 0000000000..84e0d9e602 --- /dev/null +++ b/libr/meta/t/Makefile @@ -0,0 +1,5 @@ +OBJ=test.o +BIN=test +BINDEPS=r_util r_meta + +include ../../rules.mk diff --git a/libr/meta/t/test.c b/libr/meta/t/test.c new file mode 100644 index 0000000000..b6853744b7 --- /dev/null +++ b/libr/meta/t/test.c @@ -0,0 +1,17 @@ +#include + +int main() +{ + struct r_meta_t *m = r_meta_new(); + r_meta_add(m, R_META_FUNCTION, 0x8048300, 128, "main"); + r_meta_add(m, R_META_COMMENT, 0x8048300, 1, "Everything starts here"); + r_meta_add(m, R_META_FUNCTION, 0x8048200, 54, "entrypoint"); + + r_meta_list(m, R_META_ANY); + { + char *str = r_meta_get_string(m, R_META_ANY, 0x8048300); + printf("COMMENT:\n%s\n", str); + free(str); + } + return 0; +} diff --git a/libr/meta/tmp/data.c b/libr/meta/tmp/data.c index 317fd61dc2..4bca055af3 100644 --- a/libr/meta/tmp/data.c +++ b/libr/meta/tmp/data.c @@ -694,106 +694,3 @@ int data_printd(int delta) lines += data_xrefs_print(offset, -1); return lines; } - -/* variables */ - -int data_var_type_add(const char *typename, int size, const char *fmt) -{ - struct var_type_t *d = (struct var_type_t *) - malloc(sizeof(struct var_type_t)); - strncpy(d->name, typename, sizeof(d->name)); - strncpy(d->fmt, fmt, sizeof(d->fmt)); - d->size = size; - list_add(&(d->list), &vartypes); - - return 0; -} - -int data_var_type_del(const char *typename) -{ - struct list_head *pos; - u64 ret = 0; - - if (*typename==' ')typename=typename+1; - - list_for_each(pos, &vartypes) { - struct var_type_t *d = (struct var_type_t *)list_entry(pos, struct var_type_t, list); - if (!strcmp(typename, d->name)) { - list_del(&(d->list)); - return 1; - } - } - - return 0; -} - -int data_var_type_list() -{ - struct list_head *pos; - u64 ret = 0; - - list_for_each(pos, &vartypes) { - struct var_type_t *d = (struct var_type_t *)list_entry(pos, struct var_type_t, list); - cons_printf("%s %d %s\n", d->name, d->size, d->fmt); - } - return ret; - -} - -const char *data_var_type_get(const char *datatype) -{ - struct list_head *pos; - u64 ret = 0; - - list_for_each(pos, &vartypes) { - struct var_type_t *d = (struct var_type_t *)list_entry(pos, struct var_type_t, list); - //eprintf("---(%s)(%s)\n", d->name, datatype); - if (!strcmp(datatype, d->name)) - return d; - } - return NULL; -} - -int data_var_help() -{ - cons_printf( - "Usage: Cv [name] [size] [pm-format-string]\n" - " Cv int 4 d ; define 'int' type\n" - " Cv- int ; remove 'int' var type\n" - " Cv float 4 f\n"); - return 0; -} - -int data_var_cmd(const char *str) -{ - int len; - char *vstr; - char *arg, *arg2; - STRALLOC(vstr, str, len); - - if (*str==' ')str=str+1; - switch(*str) { - case '?': - return data_var_help(); - case '\0': - /* list var types */ - data_var_type_list(); - break; - case '-': - data_var_type_del(str+1); - break; - default: - arg = strchr(str, ' '); - if (arg==NULL) - return data_var_help(); - *arg='\0'; arg=arg+1; - arg2 = strchr(arg, ' '); - if (arg2==NULL) - return data_var_help(); - *arg2='\0'; arg2=arg2+1; - data_var_type_add(str, atoi(arg), arg2); - break; - } - - return 0; -} diff --git a/libr/meta/tmp/data.h b/libr/meta/tmp/data.h deleted file mode 100644 index 6e5311014f..0000000000 --- a/libr/meta/tmp/data.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef _INCLUDE_DATA_H_ -#define _INCLUDE_DATA_H_ - -extern struct reflines_t *reflines; -//extern struct list_head data; -//extern struct list_head comments; -extern struct list_head traces; - -struct data_t { - u64 from; - u64 to; - int type; - int times; - u64 size; - char arg[128]; - struct list_head list; -}; - -struct var_type_t { - char name[128]; - char fmt[128]; - unsigned int size; - struct list_head list; -}; - -struct comment_t { - u64 offset; - const char *comment; - struct list_head list; -}; - -struct xrefs_t { - u64 addr; /* offset of the cross reference */ - u64 from; /* where the code/data is referenced */ - int type; /* 0 = code, 1 = data, -1 = unknown */ - struct list_head list; -}; - -struct reflines_t { - u64 from; - u64 to; - int index; - struct list_head list; -}; - -int data_set_len(u64 off, u64 len); -void data_info(); -int data_set(u64 off, int type); -struct data_t *data_add_arg(u64 off, int type, const char *arg); -struct data_t *data_add(u64 off, int type); -u64 data_seek_to(u64 offset, int type, int idx); -struct data_t *data_get(u64 offset); -struct data_t *data_get_range(u64 offset); -struct data_t *data_get_between(u64 from, u64 to); -int data_type_range(u64 offset); -int data_type(u64 offset); -int data_end(u64 offset); -int data_size(u64 offset); -u64 data_prev(u64 off, int type); -int data_list(); -int data_xrefs_print(u64 addr, int type); -int data_xrefs_add(u64 addr, u64 from, int type); -int data_xrefs_at(u64 addr); -void data_xrefs_del(u64 addr, u64 from, int data /* data or code */); -void data_comment_del(u64 offset, const char *str); -void data_comment_add(u64 offset, const char *str); -void data_comment_list(); -void data_xrefs_here(u64 addr); -void data_xrefs_list(); -char *data_comment_get(u64 offset, int lines); -void data_comment_init(int new); -void data_reflines_init(); -int data_printd(int delta); -const char *data_var_type_format(const char *datatype); -void data_del(u64 addr, int type,int len/* data or code */); - -#endif diff --git a/libr/util/str.c b/libr/util/str.c index 99a3b9a394..40db819075 100644 --- a/libr/util/str.c +++ b/libr/util/str.c @@ -3,6 +3,7 @@ #include "r_types.h" #include "r_util.h" #include +#include /* stable code */ static const char *nullstr = ""; @@ -221,6 +222,28 @@ char *r_str_dup(char *ptr, const char *string) return ptr; } +char *r_str_concat(char *ptr, const char *string) +{ + if (!ptr) + return strdup(string); + ptr = realloc(ptr, strlen(string)+strlen(ptr)+1); + if (ptr == NULL) + return NULL; + strcat(ptr, string); + return ptr; +} + +char *r_str_concatf(char *ptr, const char *fmt, ...) +{ + char string[1024]; + va_list ap; + va_start(ap, fmt); + vsnprintf(string, 1023, fmt, ap); + ptr = r_str_concat(ptr, string); + va_end(ap); + return ptr; +} + void *r_str_free(void *ptr) { free (ptr);