Initial support for structure offsets

This commit is contained in:
Anton Kochkov 2017-10-31 23:22:20 +08:00 committed by Anton Kochkov
parent 44f6f1f6ae
commit 1ebaad02dc
6 changed files with 191 additions and 1 deletions

View File

@ -55,6 +55,9 @@ static void setHint(RAnal *a, const char *type, ut64 addr, const char *s, ut64 p
}
}
R_API void r_anal_hint_set_offset(RAnal *a, ut64 addr, const char* typeoff) {
setHint (a, "Offset:", addr, r_str_trim_const (typeoff), 0);
}
R_API void r_anal_hint_set_jump(RAnal *a, ut64 addr, ut64 ptr) {
setHint (a, "jump:", addr, NULL, ptr);
}
@ -112,6 +115,9 @@ R_API void r_anal_hint_unset_syntax(RAnal *a, ut64 addr) {
R_API void r_anal_hint_unset_pointer(RAnal *a, ut64 addr) {
unsetHint(a, "ptr:", addr);
}
R_API void r_anal_hint_unset_offset(RAnal *a, ut64 addr) {
unsetHint (a, "Offset:", addr);
}
R_API void r_anal_hint_unset_jump(RAnal *a, ut64 addr) {
unsetHint (a, "jump:", addr);
}
@ -125,6 +131,7 @@ R_API void r_anal_hint_free(RAnalHint *h) {
free (h->esil);
free (h->opcode);
free (h->syntax);
free (h->offset);
free (h);
}
}
@ -162,6 +169,7 @@ R_API RAnalHint *r_anal_hint_from_string(RAnal *a, ut64 addr, const char *str) {
case 's': hint->size = sdb_atoi (nxt); break;
case 'S': hint->syntax = (char*)sdb_decode (nxt, 0); break;
case 'o': hint->opcode = (char*)sdb_decode (nxt, 0); break;
case 'O': hint->offset = (char*)sdb_decode (nxt, 0); break;
case 'e': hint->esil = (char*)sdb_decode (nxt, 0); break;
case 'a': hint->arch = (char*)sdb_decode (nxt, 0); break;
}

View File

@ -1931,6 +1931,8 @@ static void anop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, csh
// number of bits shifted is greater than the size of the
// destination.
op->type = R_ANAL_OP_TYPE_SHL;
op->src[0] = r_anal_value_new ();
op->src[0]->imm = INSOP(1).imm;
break;
case X86_INS_SAR:
case X86_INS_SARX:
@ -1949,6 +1951,8 @@ static void anop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, csh
case X86_INS_SHRX:
// TODO: Set CF: See case X86_INS_SAL for more details.
op->type = R_ANAL_OP_TYPE_SHR;
op->src[0] = r_anal_value_new ();
op->src[0]->imm = INSOP(1).imm;
break;
case X86_INS_CMP:
case X86_INS_CMPPD:

View File

@ -119,6 +119,74 @@ R_API int r_anal_type_get_size(RAnal *anal, const char *type) {
return 0;
}
// FIXME: Make it recursive
static int get_types_by_offset(RAnal *anal, RList *offtypes, int offset, const char *k, const char *v) {
char buf[256] = {0};
//r_cons_printf ("tk %s=%s\n", k, v);
// TODO: Add unions support
if (!strncmp (v, "struct", 6) && strncmp (k, "struct.", 7)) {
const char *typename = k;
int typesize = 0;
char* query = sdb_fmt (-1, "struct.%s", k);
char *members = sdb_get (anal->sdb_types, query, 0);
char *next, *ptr = members;
if (members) {
// Search for members, summarize the size
int typesize = 0;
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
int elements = r_num_math (NULL, tmp);
if (elements == 0) {
elements = 1;
}
// TODO: Handle also alignment, unions, etc
// If previous types size matches the offset
if ((typesize / 8) == offset) {
// Add them in the list
buf[0] = '\0';
sprintf (buf, "%s.%s", k, name);
r_list_append (offtypes, strdup (buf));
}
typesize += r_anal_type_get_size (anal, subtype) * elements;
}
free (subtype);
ptr = next;
} while (next);
free (members);
}
}
return 0;
}
R_API RList* r_anal_type_get_by_offset(RAnal *anal, ut64 offset) {
RList *offtypes = r_list_new ();
SdbList *ls = sdb_foreach_list (anal->sdb_types, true);
SdbListIter *lsi;
SdbKv *kv;
ls_foreach (ls, lsi, kv) {
get_types_by_offset (anal, offtypes, offset, kv->key, kv->value);
}
ls_free (ls);
return offtypes;
}
R_API char* r_anal_type_to_str (RAnal *a, const char *type) {
// convert to C text... maybe that should be in format string..
return NULL;
@ -146,6 +214,17 @@ R_API int r_anal_type_link(RAnal *anal, const char *type, ut64 addr) {
return false;
}
R_API int r_anal_type_link_offset(RAnal *anal, const char *type, ut64 addr) {
if (sdb_const_get (anal->sdb_types, type, 0)) {
char *laddr = r_str_newf ("offset.%08"PFMT64x, addr);
sdb_set (anal->sdb_types, laddr, type, 0);
free (laddr);
return true;
}
// eprintf ("Cannot find type\n");
return false;
}
R_API int r_anal_type_unlink(RAnal *anal, ut64 addr) {
char *laddr = sdb_fmt (-1, "link.%08"PFMT64x, addr);
sdb_unset (anal->sdb_types, laddr, 0);

View File

@ -14,6 +14,7 @@ static const char *help_msg_t[] = {
"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",
@ -39,6 +40,14 @@ static const char *help_msg_t_minus[] = {
NULL
};
static const char *help_msg_ta[] = {
"USAGE ta[...]", "", "",
"tas", " <offset>", "List all matching structure offsets",
"ta", " <struct member>", "Change immediate to structure offset",
"ta?", "", "show this help",
NULL
};
static const char *help_msg_tc[] = {
"USAGE tc[...]", " [cctype]", "",
"tc", "", "List all loaded structs",
@ -107,6 +116,7 @@ static const char *help_msg_tu[] = {
static void cmd_type_init(RCore *core) {
DEFINE_CMD_DESCRIPTOR (core, t);
DEFINE_CMD_DESCRIPTOR_SPECIAL (core, t-, t_minus);
DEFINE_CMD_DESCRIPTOR (core, ta);
DEFINE_CMD_DESCRIPTOR (core, tc);
DEFINE_CMD_DESCRIPTOR (core, td);
DEFINE_CMD_DESCRIPTOR (core, te);
@ -559,6 +569,85 @@ static int cmd_type(void *data, const char *input) {
eprintf ("Invalid use of td. See td? for help\n");
}
break;
// ta - link immediate type offset to an address
case 'a': // "ta"
switch (input[1]) {
case 's': {
char *off = strdup (input + 2);
r_str_chop (off);
int toff = r_num_math (NULL, off);
if (toff) {
RList *typeoffs = r_anal_type_get_by_offset (core->anal, toff);
RListIter *iter;
char *ty;
r_list_foreach (typeoffs, iter, ty) {
r_cons_printf ("%s\n", ty);
}
}
break;
}
case ' ': {
char *type = strdup (input + 2);
char *ptr = strchr (type, '=');
ut64 offimm = 0;
int i = 0;
ut64 addr;
if (ptr) {
*ptr++ = 0;
r_str_chop (ptr);
if (ptr && *ptr) {
addr = r_num_math (core->num, ptr);
} else {
eprintf ("address is unvalid\n");
free (type);
break;
}
} else {
addr = core->offset;
}
r_str_chop (type);
RAsmOp asmop;
RAnalOp op;
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);
ret = r_anal_op (core->anal, &op, core->offset, code, core->blocksize);
if (ret >= 0) {
// HACK: Just convert only the first imm seen
for (i = 0; i < 3; i++) {
if (op.src[i] && op.src[i]->imm) {
offimm = op.src[i]->imm;
//eprintf ("imm = %d\n", offimm);
}
}
if (offimm != 0) {
// TODO: Allow to select from multiple choices
RList* otypes = r_anal_type_get_by_offset (core->anal, offimm);
RListIter *iter;
char *otype = NULL;
r_list_foreach (otypes, iter, otype) {
if (!strcmp(type, otype)) {
//eprintf ("Adding type offset %s\n", type);
r_anal_type_link_offset (core->anal, type, addr);
r_anal_hint_set_offset (core->anal, addr, otype);
break;
}
}
if (!otype) {
eprintf ("wrong type for opcode offset\n");
}
}
}
free (type);
}
break;
case '?':
r_core_cmd_help (core, help_msg_ta);
break;
}
break;
// tl - link a type to an address
case 'l': // "tl"
switch (input[1]) {

View File

@ -677,6 +677,7 @@ typedef struct r_anal_hint_t {
char *opcode;
char *syntax;
char *esil;
char *offset;
int size;
int bits;
int immbase;
@ -1182,6 +1183,7 @@ R_API RAnalFunction *r_listrange_find_root(RListRange* s, ut64 addr);
/* --------- */ /* REFACTOR */ /* ---------- */
/* type.c */
R_API int r_anal_type_get_size (RAnal *anal, const char *type);
R_API RList* r_anal_type_get_by_offset(RAnal *anal, ut64 offset);
R_API RAnalType *r_anal_type_new(void);
R_API void r_anal_type_add(RAnal *l, RAnalType *t);
R_API void r_anal_type_del(RAnal *l, const char *name);
@ -1201,6 +1203,7 @@ R_API void r_anal_type_header (RAnal *anal, const char *hdr);
R_API int r_anal_type_link (RAnal *anal, const char *val, ut64 addr);
R_API int r_anal_type_unlink(RAnal *anal, ut64 addr);
R_API int r_anal_type_link_offset (RAnal *anal, const char *val, ut64 addr);
R_API char *r_anal_type_format (RAnal *anal, const char *t);
R_API int r_anal_type_set(RAnal *anal, ut64 at, const char *field, ut64 val);
R_API int r_anal_type_func_exist(RAnal *anal, const char *func_name);
@ -1547,6 +1550,7 @@ R_API void r_anal_hint_free (RAnalHint *h);
R_API RAnalHint *r_anal_hint_get(RAnal *anal, ut64 addr);
R_API void r_anal_hint_set_syntax (RAnal *a, ut64 addr, const char *syn);
R_API void r_anal_hint_set_jump (RAnal *a, ut64 addr, ut64 ptr);
R_API void r_anal_hint_set_offset (RAnal *a, ut64 addr, const char *typeoff);
R_API void r_anal_hint_set_immbase (RAnal *a, ut64 addr, int base);
R_API void r_anal_hint_set_fail (RAnal *a, ut64 addr, ut64 ptr);
R_API void r_anal_hint_set_length (RAnal *a, ut64 addr, int length);
@ -1563,6 +1567,7 @@ R_API void r_anal_hint_unset_opcode(RAnal *a, ut64 addr);
R_API void r_anal_hint_unset_arch(RAnal *a, ut64 addr);
R_API void r_anal_hint_unset_syntax(RAnal *a, ut64 addr);
R_API void r_anal_hint_unset_pointer(RAnal *a, ut64 addr);
R_API void r_anal_hint_unset_offset(RAnal *a, ut64 addr);
R_API void r_anal_hint_unset_jump(RAnal *a, ut64 addr);
R_API void r_anal_hint_unset_fail(RAnal *a, ut64 addr);
R_API int r_anal_esil_eval(RAnal *anal, const char *str);

View File

@ -328,9 +328,14 @@ static int filter(RParse *p, RFlag *f, char *data, char *str, int len, bool big_
}
if (p->hint) {
int pnumleft, immbase = p->hint->immbase;
char num[256], *pnum, *tmp;
char num[256] = {0}, *pnum, *tmp;
bool is_hex = false;
int tmp_count;
if (p->hint->offset) {
*ptr = 0;
snprintf (str, len, "%s%s%s", data, p->hint->offset, (ptr != ptr2)? ptr2: "");
return true;
}
strncpy (num, ptr, sizeof (num)-2);
pnum = num;
if (!strncmp (pnum, "0x", 2)) {