ta command now takes an optional offset argument ##types

* types: allow an offset to be set for the struct itself

Not all pointers to structs start at the beginning, thanks Microsoft
with your implementation of list entries. Therefore this commit allows
you to tweak the 'entry point' to the struct when using the ta command.
NOTE: Annoyingly this file is formatted badly so there are lots of
additions due to linting!

* ctype: handle nested structs in get_struct_memb

r_type_get_struct_memb will now parse inline structs rather than
incorrectly bailing out

* types: apply changes from review #12322
This commit is contained in:
Alex Kornitzer 2018-11-25 23:04:30 +00:00 committed by radare
parent 8c7a56d98a
commit 35363f3885
2 changed files with 101 additions and 72 deletions

View File

@ -41,7 +41,7 @@ static const char *help_msg_t_minus[] = {
static const char *help_msg_ta[] = {
"Usage: ta[...]", "", "",
"tas", " <offset>", "List all matching structure offsets",
"ta", " <struct member>", "Change immediate to structure offset",
"ta", " <struct.member> [offset]", "Change immediate to structure offset",
"taa", " [fcn]", "Analyze all/given function to convert immediate to linked structure offsets (see tl?)",
"ta?", "", "show this help",
NULL
@ -246,12 +246,11 @@ static void save_parsed_type(RCore *core, const char *parsed) {
if (type) {
char *name = NULL;
if ((name = strstr (type, "=type")) || (name = strstr (type, "=struct")) || (name = strstr (type, "=union")) ||
(name = strstr (type, "=enum")) || (name = strstr (type, "=typedef")) ||(name = strstr (type, "=func"))) {
(name = strstr (type, "=enum")) || (name = strstr (type, "=typedef")) || (name = strstr (type, "=func"))) {
*name = 0;
while (name - 1 >= type && *(name - 1) != '\n') {
name--;
}
}
if (name) {
r_core_cmdf (core, "\"t- %s\"", name);
@ -750,7 +749,7 @@ static int cmd_type(void *data, const char *input) {
}
} break;
case 'e': { // "te"
char *res = NULL, *temp = strchr(input, ' ');
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;
@ -826,7 +825,7 @@ static int cmd_type(void *data, const char *input) {
case 'b': // "teb"
res = r_type_enum_member (TDB, name, member_name, 0);
break;
case 'c' : { // "tec"
case 'c': { // "tec"
char *name = NULL;
SdbKv *kv;
SdbListIter *iter;
@ -852,14 +851,14 @@ static int cmd_type(void *data, const char *input) {
}
r_list_free (list);
}
r_cons_println ("};");
r_cons_println ("};");
}
}
}
ls_free (l);
break;
}
case ' ' :
case ' ':
if (member_name) {
res = r_type_enum_member (TDB, name, NULL, r_num_math (core->num, member_name));
} else {
@ -871,7 +870,7 @@ static int cmd_type(void *data, const char *input) {
}
}
break;
case '\0' : {
case '\0': {
char *name = NULL;
SdbKv *kv;
SdbListIter *iter;
@ -1017,7 +1016,13 @@ static int cmd_type(void *data, const char *input) {
free (off);
} break;
case ' ': {
char *type = strdup (input + 2);
const char *off = NULL;
char *type = strdup (r_str_trim_ro (input + 2));
char *idx = strchr (type, ' ');
if (idx) {
*idx++ = 0;
off = idx;
}
char *ptr = strchr (type, '=');
ut64 offimm = 0;
int i = 0;
@ -1038,8 +1043,8 @@ static int cmd_type(void *data, const char *input) {
}
r_str_trim (type);
RAsmOp asmop;
RAnalOp op = {0};
ut8 code[128] = {0};
RAnalOp op = { 0 };
ut8 code[128] = { 0 };
(void)r_io_read_at (core->io, core->offset, code, sizeof (code));
r_asm_set_pc (core->assembler, addr);
int ret = r_asm_disassemble (core->assembler, &asmop, code, core->blocksize);
@ -1063,12 +1068,16 @@ static int cmd_type(void *data, const char *input) {
}
}
if (offimm != 0) {
if (off) {
offimm += r_num_math (NULL, off);
}
// TODO: Allow to select from multiple choices
RList* otypes = r_type_get_by_offset (TDB, offimm);
RList *otypes = r_type_get_by_offset (TDB, offimm);
RListIter *iter;
char *otype = NULL;
r_list_foreach (otypes, iter, otype) {
if (!strcmp(type, otype)) {
// TODO: I don't think we should silently error, it is confusing
if (!strcmp (type, otype)) {
//eprintf ("Adding type offset %s\n", type);
r_type_link_offset (TDB, type, addr);
r_anal_hint_set_offset (core->anal, addr, otype);
@ -1163,7 +1172,7 @@ static int cmd_type(void *data, const char *input) {
break;
case 'p': { // "tp"
char *tmp = strdup (input);
char *ptr = r_str_trim (strchr (tmp , ' '));
char *ptr = r_str_trim (strchr (tmp, ' '));
if (!ptr) {
break;
}
@ -1254,60 +1263,59 @@ static int cmd_type(void *data, const char *input) {
}
break;
case 't': {
if (!input[1] || input[1]=='j') {
bool json = false;
if (input[1]=='j') {
if (!input[1] || input[1] == 'j') {
bool json = false;
if (input[1] == 'j') {
r_cons_print ("{");
}
char *name = NULL;
SdbKv *kv;
SdbListIter *iter;
SdbList *l = sdb_foreach_list (TDB, true);
ls_foreach (l, iter, kv) {
if (!strcmp (sdbkv_value (kv), "typedef")) {
if (!name || strcmp (sdbkv_value (kv), name)) {
free (name);
name = strdup (sdbkv_key (kv));
if (!input[1]) {
}
char *name = NULL;
SdbKv *kv;
SdbListIter *iter;
SdbList *l = sdb_foreach_list (TDB, true);
ls_foreach (l, iter, kv) {
if (!strcmp (sdbkv_value (kv), "typedef")) {
if (!name || strcmp (sdbkv_value (kv), name)) {
free (name);
name = strdup (sdbkv_key (kv));
if (!input[1]) {
r_cons_println (name);
} else {
if (json) {
r_cons_print (",");
}
const char *q = sdb_fmt ("typedef.%s", name);
const char *res = sdb_const_get (TDB, q, 0);
r_cons_printf ("\"%s\":\"%s\"", name, res);
json = true;
}
else {
if (json) {
r_cons_print(",");
}
const char *q = sdb_fmt ("typedef.%s", name);
const char *res = sdb_const_get (TDB, q, 0);
r_cons_printf ("\"%s\":\"%s\"", name, res);
json = true;
}
}
}
}
}
}
if (input[1] == 'j') {
r_cons_println ("}");
r_cons_println ("}");
}
free (name);
ls_free (l);
break;
}
free (name);
ls_free (l);
break;
}
if (input[1] == 'c') {
char *name = NULL;
SdbKv *kv;
SdbListIter *iter;
SdbList *l = sdb_foreach_list (TDB, true);
ls_foreach (l, iter, kv) {
if (!strcmp (sdbkv_value (kv), "typedef")) {
if (!name || strcmp (sdbkv_value (kv), name)) {
free (name);
name = strdup (sdbkv_key (kv));
const char *q = sdb_fmt ("typedef.%s", name);
const char *res = sdb_const_get (TDB, q, 0);
SdbKv *kv;
SdbListIter *iter;
SdbList *l = sdb_foreach_list (TDB, true);
ls_foreach (l, iter, kv) {
if (!strcmp (sdbkv_value (kv), "typedef")) {
if (!name || strcmp (sdbkv_value (kv), name)) {
free (name);
name = strdup (sdbkv_key (kv));
const char *q = sdb_fmt ("typedef.%s", name);
const char *res = sdb_const_get (TDB, q, 0);
if (res) {
r_cons_printf ("%s %s %s;\n", sdbkv_value (kv), res, name);
}
}
}
}
}
}
}
free (name);
ls_free (l);
break;

View File

@ -101,17 +101,17 @@ R_API char *r_type_enum_getbitfield(Sdb *TDB, const char *name, ut64 val) {
continue;
}
q = sdb_fmt ("enum.%s.0x%x", name, (1<<i));
res = sdb_const_get (TDB, q, 0);
if (isFirst) {
res = sdb_const_get (TDB, q, 0);
if (isFirst) {
isFirst = false;
} else {
} else {
ret = r_str_append (ret, " | ");
}
if (res) {
}
if (res) {
ret = r_str_append (ret, res);
} else {
} else {
ret = r_str_appendf (ret, "0x%x", (1<<i));
}
}
}
return ret;
}
@ -181,7 +181,7 @@ R_API int r_type_get_bitsize(Sdb *TDB, const char *type) {
}
R_API char *r_type_get_struct_memb(Sdb *TDB, const char *type, int offset) {
int i, typesize = 0;
int i, prev_typesize, typesize = 0;
char *res = NULL;
if (offset < 0) {
@ -216,7 +216,28 @@ R_API char *r_type_get_struct_memb(Sdb *TDB, const char *type, int offset) {
free (subtype);
break;
}
prev_typesize = typesize;
typesize += r_type_get_bitsize (TDB, subtype) * arrsz;
// Handle nested structs
if (offset < (typesize / 8)) {
char *nested_type = r_str_word_get0 (subtype, 0);
if (r_str_startswith(nested_type, "struct ") && !r_str_endswith(nested_type, " *")) {
len = r_str_split(nested_type, ' ');
if (len < 2) {
free (subtype);
break;
}
nested_type = r_str_word_get0 (nested_type, 1);
char *nested_res = r_type_get_struct_memb (TDB, nested_type, offset - (prev_typesize / 8));
if (nested_res) {
len = r_str_split(nested_res, '.');
res = r_str_newf ("%s.%s.%s", type, name, r_str_word_get0 (nested_res, len - 1));
free (nested_res);
free (subtype);
break;
}
}
}
free (subtype);
}
free (members);
@ -299,12 +320,12 @@ R_API int r_type_unlink(Sdb *TDB, ut64 addr) {
}
static void filter_type(char *t) {
for (;*t; t++) {
if (*t == ' ') {
*t = '_';
}
// memmove (t, t+1, strlen (t));
}
for (;*t; t++) {
if (*t == ' ') {
*t = '_';
}
// memmove (t, t+1, strlen (t));
}
}
R_API char *r_type_format(Sdb *TDB, const char *t) {
@ -508,7 +529,7 @@ static R_OWN char *type_func_try_guess(Sdb *TDB, R_NONNULL char *name) {
// TODO:
// - symbol names are long and noisy, some of them might not be matched due
// to additional information added around name
// to additional information added around name
R_API R_OWN char *r_type_func_guess(Sdb *TDB, R_NONNULL char *func_name) {
int offset = 0;
char *str = func_name;