Manage types enum more properly (#10139)

This commit is contained in:
sivaramaaa 2018-05-21 05:24:50 +05:30 committed by radare
parent d5af26b3da
commit 97de3ff035
8 changed files with 173 additions and 161 deletions

View File

@ -947,7 +947,6 @@ static void cmd_print_format(RCore *core, const char *_input, const ut8* block,
core->print->reg = core->dbg->reg;
core->print->get_register = r_reg_get;
core->print->get_register_value = r_reg_get_value;
core->print->sdb_types = core->anal->sdb_types;
int o_blocksize = core->blocksize;

View File

@ -14,17 +14,13 @@ static const char *help_msg_t[] = {
"t*", "", "List types info in r2 commands",
"t-", " <name>", "Delete types by its name",
"t-*", "", "Remove all types",
//"t-!", "", "Use to open $EDITOR",
"ta", " <type>", "Mark immediate as a type offset",
"tb", " <enum> <value>", "Show matching enum bitfield for given number",
"tc", " ([cctype])", "calling conventions listing and manipulations",
"te", "[?]", "List all loaded enums",
"te", " <enum> <value>", "Show name for given enum number",
"td", "[?] <string>", "Load types from string",
"tf", "", "List all loaded functions signatures",
"tk", " <sdb-query>", "Perform sdb query",
"tl", "[?]", "Show/Link type to an address",
//"to", "", "List opened files",
"tn", "[?] [-][addr]", "manage noreturn function attributes and marks",
"to", " -", "Open cfg.editor to load types",
"to", " <path>", "Load types from C header file",
@ -33,7 +29,6 @@ static const char *help_msg_t[] = {
"ts", "[?]", "print loaded struct types",
"tu", "[?]", "print loaded union types",
"tt", "[?]", "List all loaded typedefs",
//"| ts k=v k=v @ link.addr set fields at given linked type\n"
NULL
};
@ -67,7 +62,7 @@ static const char *help_msg_to[] = {
static const char *help_msg_tc[] = {
"Usage: tc[...]", " [cctype]", "",
"tc", "", "List all loaded structs",
"tc", "", "List all loaded calling convention",
"tc", " [cctype]", "Show convention rules for this type",
"tc=", "([cctype])", "Select (or show) default calling convention",
"tc-", "[cctype]", "TODO: remove given calling convention",
@ -88,7 +83,9 @@ static const char *help_msg_td[] = {
static const char *help_msg_te[] = {
"Usage: te[...]", "", "",
"te", "", "List all loaded enums",
"te", " <enum>", "Print all values of enum for given name",
"te", " <enum> <value>", "Show name for given enum number",
"teb", " <enum> <name>", "Show matching enum bitfield for given name",
"te?", "", "show this help",
NULL
};
@ -495,30 +492,39 @@ static int cmd_type(void *data, const char *input) {
break;
}
} break;
case 'b': {
char *p, *s = (strlen (input) > 1)? strdup (input + 2): NULL;
const char *isenum;
p = s? strchr (s, ' '): NULL;
if (p) {
*p++ = 0;
// dupp in core.c (see getbitfield())
isenum = sdb_const_get (TDB, s, 0);
if (isenum && !strcmp (isenum, "enum")) {
*--p = '.';
const char *res = sdb_const_get (TDB, s, 0);
if (res)
r_cons_println (res);
else eprintf ("Invalid enum member\n");
} else {
eprintf ("This is not an enum\n");
}
} else {
eprintf ("Missing value\n");
case 'e': { // "te"
char *res = NULL, *temp = strchr(input, ' ');
Sdb *TDB = core->anal->sdb_types;
char *name = temp ? strdup (temp + 1): NULL;
char *member_name = name ? strchr (name, ' '): NULL;
if (member_name) {
*member_name++ = 0;
}
free (s);
} break;
case 'e': {
if (!input[1]) {
if (name && !r_type_isenum (TDB, name)) {
eprintf ("%s is not an enum\n", name);
break;
}
switch (input[1]) {
case '?' :
r_core_cmd_help (core, help_msg_te);
break;
case 'b' :
res = r_type_enum_member (TDB, name, member_name, 0);
break;
case ' ' : {
RListIter *iter;
RTypeEnum *member = R_NEW0 (RTypeEnum);
if (member_name) {
res = r_type_enum_member (TDB, name, NULL, r_num_math (core->num, member_name));
} else {
RList *list = r_type_get_enum (TDB, name);
r_list_foreach (list, iter, member) {
r_cons_printf ("%s = %s\n", member->name, member->val);
}
}
} break;
case '\0' : {
char *name = NULL;
SdbKv *kv;
SdbListIter *iter;
@ -532,33 +538,15 @@ static int cmd_type(void *data, const char *input) {
}
}
}
free (name);
ls_free (l);
break;
} break;
}
if (input[1] == '?') {
r_core_cmd_help (core, help_msg_te);
break;
free (name);
if (res) {
r_cons_println (res);
} else if (member_name) {
eprintf ("Invalid enum member\n");
}
char *p, *s = strdup (input + 2);
const char *isenum;
p = strchr (s, ' ');
if (p) {
*p++ = 0;
isenum = sdb_const_get (TDB, s, 0);
if (isenum && !strncmp (isenum, "enum", 4)) {
const char *q = sdb_fmt ("%s.0x%x", s, (ut32)r_num_math (core->num, p));
const char *res = sdb_const_get (TDB, q, 0);
if (res)
r_cons_println (res);
} else {
eprintf ("This is not an enum\n");
}
} else {
//eprintf ("Missing value\n");
r_core_cmdf (core, "t~&%s,=0x", s);
}
free (s);
} break;
case ' ':
showFormat (core, input + 1, 0);

View File

@ -1457,55 +1457,6 @@ static void update_sdb(RCore *core) {
}
}
// dupped in cmd_type.c
static char *getenumname(void *_core, const char *name, ut64 val) {
const char *isenum;
RCore *core = (RCore*)_core;
isenum = sdb_const_get (core->anal->sdb_types, name, 0);
if (isenum && !strncmp (isenum, "enum", 4)) {
const char *q = sdb_fmt ("%s.0x%x", name, val);
return sdb_get (core->anal->sdb_types, q, 0);
} else {
eprintf ("This is not an enum (%s)\n", name);
}
return NULL;
}
// TODO: dupped in cmd_type.c
static char *getbitfield(void *_core, const char *name, ut64 val) {
const char *isenum, *q, *res;
RCore *core = (RCore*)_core;
char *ret = NULL;
int i;
isenum = sdb_const_get (core->anal->sdb_types, name, 0);
if (isenum && !strcmp (isenum, "enum")) {
int isFirst = true;
ret = r_str_appendf (ret, "0x%08"PFMT64x" : ", val);
for (i = 0; i < 32; i++) {
if (!(val & (1 << i))) {
continue;
}
q = sdb_fmt ("%s.0x%x", name, (1<<i));
res = sdb_const_get (core->anal->sdb_types, q, 0);
if (isFirst) {
isFirst = false;
} else {
ret = r_str_append (ret, " | ");
}
if (res) {
ret = r_str_append (ret, res);
} else {
ret = r_str_appendf (ret, "0x%x", (1<<i));
}
}
} else {
eprintf ("This is not an enum\n");
}
return ret;
}
#define MINLEN 1
static int is_string (const ut8 *buf, int size, int *len) {
int i;
@ -1770,8 +1721,6 @@ R_API bool r_core_init(RCore *core) {
core->print = r_print_new ();
core->print->user = core;
core->print->num = core->num;
core->print->get_enumname = getenumname;
core->print->get_bitfield = getbitfield;
core->print->offname = r_core_print_offname;
core->print->cb_printf = r_cons_printf;
core->print->cb_color = r_cons_rainbow_get;
@ -1850,6 +1799,7 @@ R_API bool r_core_init(RCore *core) {
core->anal->cb.on_fcn_new = on_fcn_new;
core->anal->cb.on_fcn_delete = on_fcn_delete;
core->anal->cb.on_fcn_rename = on_fcn_rename;
core->print->sdb_types = core->anal->sdb_types;
core->assembler->syscall = r_syscall_ref (core->anal->syscall); // BIND syscall anal/asm
r_anal_set_user_ptr (core->anal, core);
core->anal->cb_printf = (void *) r_cons_printf;

View File

@ -50,8 +50,6 @@ typedef struct r_print_t {
char *(*cb_color)(int idx, int last, bool bg);
int (*disasm)(void *p, ut64 addr);
void (*oprintf)(const char *str, ...);
char* (*get_bitfield)(void *user, const char *name, ut64 value);
char* (*get_enumname)(void *user, const char *name, ut64 value);
int interrupt;
int big_endian;
int width;

View File

@ -5,8 +5,17 @@
extern "C" {
#endif
typedef struct r_type_enum {
const char *name;
const char *val;
}RTypeEnum;
R_API int r_type_set(Sdb *TDB, ut64 at, const char *field, ut64 val);
R_API void r_type_del(Sdb *TDB, const char *name);
R_API bool r_type_isenum(Sdb *TDB, const char *name);
R_API char *r_type_enum_member(Sdb *TDB, const char *name, const char *member, ut64 val);
R_API char *r_type_enum_getbitfield(Sdb *TDB, const char *name, ut64 val);
R_API RList* r_type_get_enum (Sdb *TDB, const char *name);
R_API int r_type_get_bitsize (Sdb *TDB, const char *type);
R_API RList* r_type_get_by_offset(Sdb *TDB, ut64 offset);
R_API int r_type_link (Sdb *TDB, const char *val, ut64 addr);

View File

@ -1110,9 +1110,7 @@ static void r_print_format_bitfield(const RPrint* p, ut64 seeki, char* fmtname,
if (MUSTSEE && !SEEVALUE) {
p->cb_printf ("0x%08"PFMT64x" = ", seeki);
}
if (p->get_bitfield) {
bitfield = p->get_bitfield (p->user, fmtname, addr);
}
bitfield = r_type_enum_getbitfield (p->sdb_types, fmtname, addr);
if (bitfield && *bitfield) {
if (MUSTSEEJSON) p->cb_printf ("\"%s\"}", bitfield);
else if (MUSTSEE) p->cb_printf (" %s (bitfield) = %s\n", fieldname, bitfield);
@ -1135,9 +1133,7 @@ static void r_print_format_enum (const RPrint* p, ut64 seeki, char* fmtname,
if (MUSTSEE && !SEEVALUE) {
p->cb_printf ("0x%08"PFMT64x" = ", seeki);
}
if (p->get_enumname) {
enumvalue = p->get_enumname (p->user, fmtname, addr);
}
enumvalue = r_type_enum_member (p->sdb_types, fmtname, NULL, addr);
if (enumvalue && *enumvalue) {
if (mode & R_PRINT_DOT) {
p->cb_printf ("%s.%s", fmtname, enumvalue);

View File

@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2013-2018 - pancake, oddcoder */
/* radare - LGPL - Copyright 2013-2018 - pancake, oddcoder, sivaramaaa */
#include "r_util.h"
@ -21,53 +21,81 @@ R_API int r_type_set(Sdb *TDB, ut64 at, const char *field, ut64 val) {
return false;
}
R_API void r_type_del(Sdb *TDB, const char *name) {
const char *kind = sdb_const_get (TDB, name, 0);
if (!kind) {
return;
R_API bool r_type_isenum(Sdb *TDB, const char *name) {
if (!name) {
return false;
}
if (!strcmp (kind, "type")) {
sdb_unset (TDB, sdb_fmt ("type.%s", name), 0);
sdb_unset (TDB, sdb_fmt ("type.%s.size", name), 0);
sdb_unset (TDB, sdb_fmt ("type.%s.meta", name), 0);
sdb_unset (TDB, name, 0);
} else if (!strcmp (kind, "struct") || !strcmp (kind, "union")) {
int i, n = sdb_array_length(TDB, sdb_fmt ("%s.%s", kind, name));
char *elements_key = r_str_newf ("%s.%s", kind, name);
for (i = 0; i< n; i++) {
char *p = sdb_array_get (TDB, elements_key, i, NULL);
sdb_unset (TDB, sdb_fmt ("%s.%s", elements_key, p), 0);
free (p);
}
sdb_unset (TDB, elements_key, 0);
sdb_unset (TDB, name, 0);
free (elements_key);
} else if (!strcmp (kind, "func")) {
int i, n = sdb_num_get (TDB, sdb_fmt ("func.%s.args", name), 0);
for (i = 0; i < n; i++) {
sdb_unset (TDB, sdb_fmt ("func.%s.arg.%d", name, i), 0);
}
sdb_unset (TDB, sdb_fmt ("func.%s.ret", name), 0);
sdb_unset (TDB, sdb_fmt ("func.%s.cc", name), 0);
sdb_unset (TDB, sdb_fmt ("func.%s.noreturn", name), 0);
sdb_unset (TDB, sdb_fmt ("func.%s.args", name), 0);
sdb_unset (TDB, name, 0);
} else if (!strcmp (kind, "enum")) {
int i;
for (i=0;; i++) {
const char *tmp = sdb_const_get (TDB, sdb_fmt ("%s.0x%x", name, i), 0);
if (!tmp) {
break;
}
sdb_unset (TDB, sdb_fmt ("%s.%s", name, tmp), 0);
sdb_unset (TDB, sdb_fmt ("%s.0x%x", name, i), 0);
}
sdb_unset (TDB, name, 0);
const char *type = sdb_const_get (TDB, name, 0);
if (type && !strcmp (type, "enum")) {
return true;
} else {
eprintf ("Unrecognized type \"%s\"\n", kind);
return false;
}
}
R_API RList* r_type_get_enum (Sdb *TDB, const char *name) {
RList *res = r_list_new ();
char *p, *val, var[128], var2[128];
int n;
if (!r_type_isenum (TDB, name)) {
return NULL;
}
snprintf (var, sizeof (var), "enum.%s", name);
for (n = 0; (p = sdb_array_get (TDB, var, n, NULL)); n++) {
RTypeEnum *member = R_NEW0 (RTypeEnum);
snprintf (var2, sizeof (var2), "%s.%s", var, p);
val = sdb_array_get (TDB, var2, 0, NULL);
member->name = p;
member->val = val;
r_list_append (res, member);
}
return res;
}
R_API char *r_type_enum_member(Sdb *TDB, const char *name, const char *member, ut64 val) {
const char *q;
if (!r_type_isenum (TDB, name)) {
return NULL;
}
if (member) {
q = sdb_fmt ("enum.%s.%s", name, member);
} else {
q = sdb_fmt ("enum.%s.0x%x", name, val);
}
return sdb_get (TDB, q, 0);
}
R_API char *r_type_enum_getbitfield(Sdb *TDB, const char *name, ut64 val) {
char *q, *ret = NULL;
const char *res;
int i;
if (!r_type_isenum (TDB, name)) {
return NULL;
}
bool isFirst = true;
ret = r_str_appendf (ret, "0x%08"PFMT64x" : ", val);
for (i = 0; i < 32; i++) {
if (!(val & (1 << i))) {
continue;
}
q = sdb_fmt ("enum.%s.0x%x", name, (1<<i));
res = sdb_const_get (TDB, q, 0);
if (isFirst) {
isFirst = false;
} else {
ret = r_str_append (ret, " | ");
}
if (res) {
ret = r_str_append (ret, res);
} else {
ret = r_str_appendf (ret, "0x%x", (1<<i));
}
}
return ret;
}
R_API int r_type_get_bitsize(Sdb *TDB, const char *type) {
char *query;
/* Filter out the structure keyword if type looks like "struct mystruc" */
@ -315,6 +343,51 @@ R_API char *r_type_format(Sdb *TDB, const char *t) {
return NULL;
}
R_API void r_type_del(Sdb *TDB, const char *name) {
const char *kind = sdb_const_get (TDB, name, 0);
if (!kind) {
return;
}
if (!strcmp (kind, "type")) {
sdb_unset (TDB, sdb_fmt ("type.%s", name), 0);
sdb_unset (TDB, sdb_fmt ("type.%s.size", name), 0);
sdb_unset (TDB, sdb_fmt ("type.%s.meta", name), 0);
sdb_unset (TDB, name, 0);
} else if (!strcmp (kind, "struct") || !strcmp (kind, "union")) {
int i, n = sdb_array_length(TDB, sdb_fmt ("%s.%s", kind, name));
char *elements_key = r_str_newf ("%s.%s", kind, name);
for (i = 0; i< n; i++) {
char *p = sdb_array_get (TDB, elements_key, i, NULL);
sdb_unset (TDB, sdb_fmt ("%s.%s", elements_key, p), 0);
free (p);
}
sdb_unset (TDB, elements_key, 0);
sdb_unset (TDB, name, 0);
free (elements_key);
} else if (!strcmp (kind, "func")) {
int i, n = sdb_num_get (TDB, sdb_fmt ("func.%s.args", name), 0);
for (i = 0; i < n; i++) {
sdb_unset (TDB, sdb_fmt ("func.%s.arg.%d", name, i), 0);
}
sdb_unset (TDB, sdb_fmt ("func.%s.ret", name), 0);
sdb_unset (TDB, sdb_fmt ("func.%s.cc", name), 0);
sdb_unset (TDB, sdb_fmt ("func.%s.noreturn", name), 0);
sdb_unset (TDB, sdb_fmt ("func.%s.args", name), 0);
sdb_unset (TDB, name, 0);
} else if (!strcmp (kind, "enum")) {
RList *list = r_type_get_enum (TDB, name);
RTypeEnum *member = R_NEW0 (RTypeEnum);
RListIter *iter;
r_list_foreach (list, iter, member) {
sdb_unset (TDB, sdb_fmt ("enum.%s.%s", name, member->name), 0);
sdb_unset (TDB, sdb_fmt ("enum.%s.0x%x", name, member->val), 0);
}
sdb_unset (TDB, name, 0);
} else {
eprintf ("Unrecognized type \"%s\"\n", kind);
}
}
// Function prototypes api
R_API int r_type_func_exist(Sdb *TDB, const char *func_name) {
const char *fcn = sdb_const_get (TDB, func_name, 0);

View File

@ -991,8 +991,6 @@ do_decl:
if (!strcmp (name, "{")) {
// UNNAMED
fprintf (stderr, "anonymous enums are ignored\n");
} else {
tcc_appendf ("%s=enum\n", name);
}
for (;;) {
v = tok;
@ -1006,9 +1004,10 @@ do_decl:
}
if (strcmp (name, "{")) {
char *varstr = get_tok_str (v, NULL);
// eprintf("%s.%s @ 0x%"PFMT64x"\n", name, varstr, c);
tcc_appendf ("%s.%s=0x%"PFMT64x "\n", name, varstr, c);
tcc_appendf ("%s.0x%"PFMT64x "=%s\n", name, c, varstr);
tcc_appendf ("%s=enum\n", name);
tcc_appendf ("[+]enum.%s=%s\n",name, varstr);
tcc_appendf ("enum.%s.%s=0x%"PFMT64x "\n", name, varstr, c);
tcc_appendf ("enum.%s.0x%"PFMT64x "=%s\n", name, c, varstr);
// TODO: if token already defined throw an error
// if (varstr isInside (arrayOfvars)) { erprintf ("ERROR: DUP VAR IN ENUM\n"); }
}