mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-26 09:06:02 +00:00
Initial support for structure offsets
This commit is contained in:
parent
44f6f1f6ae
commit
1ebaad02dc
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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]) {
|
||||
|
@ -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);
|
||||
|
@ -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)) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user