* Initial working implementation of r_meta
- Added test program that sets and gets metadata. - It needs much more features and stuff - Integration with r_core is mandatory! :) - Hard simplification from the old r1 code * Added r_str_concat and r_str_concatf in r_util
This commit is contained in:
parent
26b5e48ede
commit
05651257c9
|
@ -1,22 +1,65 @@
|
|||
#ifndef _INCLUDE_R_META_H_
|
||||
#define _INCLUDE_R_META_H_
|
||||
|
||||
#include <r_types.h>
|
||||
#include <r_util.h>
|
||||
#include <list.h>
|
||||
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
NAME=r_meta
|
||||
OBJ=meta.o
|
||||
|
||||
include ../rules.mk
|
|
@ -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 */
|
||||
|
|
209
libr/meta/meta.c
209
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;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
OBJ=test.o
|
||||
BIN=test
|
||||
BINDEPS=r_util r_meta
|
||||
|
||||
include ../../rules.mk
|
|
@ -0,0 +1,17 @@
|
|||
#include <r_meta.h>
|
||||
|
||||
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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -3,6 +3,7 @@
|
|||
#include "r_types.h"
|
||||
#include "r_util.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/* 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);
|
||||
|
|
Loading…
Reference in New Issue