mirror of
https://github.com/radareorg/radare2.git
synced 2024-12-04 03:11:28 +00:00
113 lines
2.6 KiB
C
113 lines
2.6 KiB
C
/* radare - LGPL - Copyright 2013-2017 - pancake */
|
|
|
|
#include "r_util.h"
|
|
#include "r_types.h"
|
|
#include "r_parse.h"
|
|
#include "libr_tcc.h"
|
|
|
|
/* parse C code and return it in key-value form */
|
|
|
|
static void appendstring(const char *msg, char **s) {
|
|
if (!s) {
|
|
printf ("%s\n", msg);
|
|
} else if (*s) {
|
|
char *p = malloc (strlen (msg) + strlen (*s) + 1);
|
|
if (!p) return;
|
|
strcpy (p, *s);
|
|
free (*s);
|
|
*s = p;
|
|
strcpy (p + strlen (p), msg);
|
|
} else {
|
|
*s = strdup (msg);
|
|
}
|
|
}
|
|
|
|
static int typeload(void *p, const char *k, const char *v) {
|
|
if (!p) {
|
|
return -1;
|
|
}
|
|
int btype = 0;
|
|
RAnal *anal = (RAnal*)p;
|
|
//r_cons_printf ("tk %s=%s\n", k, v);
|
|
// TODO: Add unions support
|
|
if (!strncmp (v, "struct", 6) && strncmp(k, "struct.", 7)) {
|
|
// structure
|
|
btype = VT_STRUCT;
|
|
const char *typename = k;
|
|
int typesize = 0;
|
|
// TODO: Add typesize here
|
|
char* query = sdb_fmt (-1, "struct.%s", k);
|
|
char *members = sdb_get (anal->sdb_types, query, 0);
|
|
char *next, *ptr = members;
|
|
if (members) {
|
|
do {
|
|
char *name = sdb_anext (ptr, &next);
|
|
if (!name) {
|
|
break;
|
|
}
|
|
query = sdb_fmt (-1, "struct.%s.%s", k, name);
|
|
char *subtype = sdb_get (anal->sdb_types, query, 0);
|
|
if (!subtype) {
|
|
break;
|
|
}
|
|
char *tmp = strchr (subtype, ',');
|
|
if (tmp) {
|
|
*tmp++ = 0;
|
|
tmp = strchr (tmp, ',');
|
|
if (tmp) {
|
|
*tmp++ = 0;
|
|
}
|
|
char *subname = tmp;
|
|
// TODO: Go recurse here
|
|
query = sdb_fmt (-1, "struct.%s.%s.meta", subtype, subname);
|
|
btype = sdb_num_get (anal->sdb_types, query, 0);
|
|
tcc_sym_push (subtype, 0, btype);
|
|
}
|
|
free (subtype);
|
|
ptr = next;
|
|
} while (next);
|
|
free (members);
|
|
}
|
|
tcc_sym_push ((char *)typename, typesize, btype);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
R_API char *r_parse_c_file(RAnal *anal, const char *path) {
|
|
char *str = NULL;
|
|
TCCState *T = tcc_new (anal->cpu, anal->bits, anal->os);
|
|
if (!T) return NULL;
|
|
tcc_set_callback (T, &appendstring, &str);
|
|
sdb_foreach (anal->sdb_types, typeload, anal);
|
|
if (tcc_add_file (T, path) == -1) {
|
|
free (str);
|
|
str = NULL;
|
|
}
|
|
tcc_delete (T);
|
|
return str;
|
|
}
|
|
|
|
R_API char *r_parse_c_string(RAnal *anal, const char *code) {
|
|
char *str = NULL;
|
|
TCCState *T = tcc_new (anal->cpu, anal->bits, anal->os);
|
|
if (!T) return NULL;
|
|
tcc_set_callback (T, &appendstring, &str);
|
|
sdb_foreach (anal->sdb_types, typeload, NULL);
|
|
tcc_compile_string (T, code);
|
|
tcc_delete (T);
|
|
return str;
|
|
}
|
|
|
|
R_API int r_parse_is_c_file (const char *file) {
|
|
const char *ext = r_str_lchr (file, '.');
|
|
if (ext) {
|
|
ext = ext + 1;
|
|
if (!strcmp (ext, "cparse")
|
|
|| !strcmp (ext, "c")
|
|
|| !strcmp (ext, "h")) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|