2018-04-10 21:52:47 +00:00
|
|
|
/* radare - LGPL - Copyright 2015-2018 - pancake */
|
2015-02-22 10:18:40 +00:00
|
|
|
|
|
|
|
#include <r_anal.h>
|
|
|
|
|
|
|
|
#define DB esil->db_trace
|
2018-04-10 21:52:47 +00:00
|
|
|
#define KEY(x) sdb_fmt ("%d."x, esil->trace_idx)
|
|
|
|
#define KEYAT(x,y) sdb_fmt ("%d."x".0x%"PFMT64x, esil->trace_idx, y)
|
|
|
|
#define KEYREG(x,y) sdb_fmt ("%d."x".%s", esil->trace_idx, y)
|
2015-02-22 10:18:40 +00:00
|
|
|
|
2015-09-14 09:31:54 +00:00
|
|
|
static int ocbs_set = false;
|
2015-02-23 00:28:25 +00:00
|
|
|
static RAnalEsilCallbacks ocbs = {0};
|
|
|
|
|
2015-09-13 23:00:09 +00:00
|
|
|
static int trace_hook_reg_read(RAnalEsil *esil, const char *name, ut64 *res, int *size) {
|
2015-02-23 00:28:25 +00:00
|
|
|
int ret = 0;
|
|
|
|
if (*name=='0') {
|
2016-08-13 10:09:14 +00:00
|
|
|
//eprintf ("Register not found in profile\n");
|
2015-02-23 00:28:25 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (ocbs.hook_reg_read) {
|
|
|
|
RAnalEsilCallbacks cbs = esil->cb;
|
|
|
|
esil->cb = ocbs;
|
2015-09-13 23:00:09 +00:00
|
|
|
ret = ocbs.hook_reg_read (esil, name, res, size);
|
2015-02-23 00:28:25 +00:00
|
|
|
esil->cb = cbs;
|
|
|
|
}
|
2015-04-11 20:19:35 +00:00
|
|
|
if (!ret && esil->cb.reg_read) {
|
2015-09-13 23:00:09 +00:00
|
|
|
ret = esil->cb.reg_read (esil, name, res, size);
|
2015-04-11 20:19:35 +00:00
|
|
|
}
|
|
|
|
if (ret) {
|
|
|
|
ut64 val = *res;
|
2016-08-13 10:09:14 +00:00
|
|
|
//eprintf ("[ESIL] REG READ %s 0x%08"PFMT64x"\n", name, val);
|
2015-04-11 20:19:35 +00:00
|
|
|
sdb_array_add (DB, KEY ("reg.read"), name, 0);
|
|
|
|
sdb_num_set (DB, KEYREG ("reg.read", name), val, 0);
|
2016-08-23 11:10:15 +00:00
|
|
|
} //else {
|
|
|
|
//eprintf ("[ESIL] REG READ %s FAILED\n", name);
|
|
|
|
//}
|
2015-02-23 00:28:25 +00:00
|
|
|
return ret;
|
2015-02-22 10:18:40 +00:00
|
|
|
}
|
|
|
|
|
2016-10-18 14:59:38 +00:00
|
|
|
static int trace_hook_reg_write(RAnalEsil *esil, const char *name, ut64 *val) {
|
2015-02-23 00:28:25 +00:00
|
|
|
int ret = 0;
|
2016-10-18 14:59:38 +00:00
|
|
|
//eprintf ("[ESIL] REG WRITE %s 0x%08"PFMT64x"\n", name, *val);
|
2015-02-22 10:18:40 +00:00
|
|
|
sdb_array_add (DB, KEY ("reg.write"), name, 0);
|
2016-10-18 14:59:38 +00:00
|
|
|
sdb_num_set (DB, KEYREG ("reg.write", name), *val, 0);
|
2015-02-23 00:28:25 +00:00
|
|
|
if (ocbs.hook_reg_write) {
|
|
|
|
RAnalEsilCallbacks cbs = esil->cb;
|
|
|
|
esil->cb = ocbs;
|
|
|
|
ret = ocbs.hook_reg_write (esil, name, val);
|
|
|
|
esil->cb = cbs;
|
|
|
|
}
|
|
|
|
return ret;
|
2015-02-22 10:18:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int trace_hook_mem_read(RAnalEsil *esil, ut64 addr, ut8 *buf, int len) {
|
2016-05-24 12:54:34 +00:00
|
|
|
char *hexbuf = calloc ((1 + len), 4);
|
2015-02-22 10:18:40 +00:00
|
|
|
int ret = 0;
|
|
|
|
if (esil->cb.mem_read) {
|
|
|
|
ret = esil->cb.mem_read (esil, addr, buf, len);
|
|
|
|
}
|
|
|
|
sdb_array_add_num (DB, KEY ("mem.read"), addr, 0);
|
|
|
|
r_hex_bin2str (buf, len, hexbuf);
|
|
|
|
sdb_set (DB, KEYAT ("mem.read.data", addr), hexbuf, 0);
|
2016-08-13 10:09:14 +00:00
|
|
|
//eprintf ("[ESIL] MEM READ 0x%08"PFMT64x" %s\n", addr, hexbuf);
|
2015-02-22 10:18:40 +00:00
|
|
|
free (hexbuf);
|
|
|
|
|
2015-02-23 00:28:25 +00:00
|
|
|
if (ocbs.hook_mem_read) {
|
|
|
|
RAnalEsilCallbacks cbs = esil->cb;
|
|
|
|
esil->cb = ocbs;
|
|
|
|
ret = ocbs.hook_mem_read (esil, addr, buf, len);
|
|
|
|
esil->cb = cbs;
|
|
|
|
}
|
2015-02-22 10:18:40 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int trace_hook_mem_write(RAnalEsil *esil, ut64 addr, const ut8 *buf, int len) {
|
2015-02-23 00:28:25 +00:00
|
|
|
int ret = 0;
|
2015-02-22 10:18:40 +00:00
|
|
|
char *hexbuf = malloc ((1+len)*3);
|
|
|
|
sdb_array_add_num (DB, KEY ("mem.write"), addr, 0);
|
|
|
|
r_hex_bin2str (buf, len, hexbuf);
|
|
|
|
sdb_set (DB, KEYAT ("mem.write.data", addr), hexbuf, 0);
|
2016-08-13 10:09:14 +00:00
|
|
|
//eprintf ("[ESIL] MEM WRITE 0x%08"PFMT64x" %s\n", addr, hexbuf);
|
2015-02-28 13:32:30 +00:00
|
|
|
free (hexbuf);
|
|
|
|
|
2015-02-23 00:28:25 +00:00
|
|
|
if (ocbs.hook_mem_write) {
|
|
|
|
RAnalEsilCallbacks cbs = esil->cb;
|
|
|
|
esil->cb = ocbs;
|
|
|
|
ret = ocbs.hook_mem_write (esil, addr, buf, len);
|
|
|
|
esil->cb = cbs;
|
|
|
|
}
|
|
|
|
return ret;
|
2015-02-22 10:18:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_anal_esil_trace (RAnalEsil *esil, RAnalOp *op) {
|
|
|
|
const char *expr = r_strbuf_get (&op->esil);
|
2016-11-14 00:17:58 +00:00
|
|
|
int esil_verbose = esil->verbose;
|
2015-02-23 00:28:25 +00:00
|
|
|
if (ocbs_set) {
|
|
|
|
eprintf ("cannot call recursively\n");
|
|
|
|
}
|
|
|
|
ocbs = esil->cb;
|
2015-09-14 09:31:54 +00:00
|
|
|
ocbs_set = true;
|
2018-08-19 01:24:10 +00:00
|
|
|
if (!DB) {
|
|
|
|
DB = sdb_new0 ();
|
|
|
|
}
|
2015-02-22 10:18:40 +00:00
|
|
|
sdb_num_set (DB, "idx", esil->trace_idx, 0);
|
|
|
|
sdb_num_set (DB, KEY ("addr"), op->addr, 0);
|
|
|
|
// sdb_set (DB, KEY ("opcode"), op->mnemonic, 0);
|
|
|
|
// sdb_set (DB, KEY ("addr"), expr, 0);
|
|
|
|
|
2016-08-13 10:09:14 +00:00
|
|
|
//eprintf ("[ESIL] ADDR 0x%08"PFMT64x"\n", op->addr);
|
2015-02-22 10:18:40 +00:00
|
|
|
//eprintf ("[ESIL] OPCODE %s\n", op->mnemonic);
|
2016-08-13 10:09:14 +00:00
|
|
|
//eprintf ("[ESIL] EXPR = %s\n", expr);
|
2015-02-22 10:18:40 +00:00
|
|
|
/* set hooks */
|
2016-11-14 00:17:58 +00:00
|
|
|
esil->verbose = 0;
|
2015-02-22 10:18:40 +00:00
|
|
|
esil->cb.hook_reg_read = trace_hook_reg_read;
|
|
|
|
esil->cb.hook_reg_write = trace_hook_reg_write;
|
|
|
|
esil->cb.hook_mem_read = trace_hook_mem_read;
|
|
|
|
esil->cb.hook_mem_write = trace_hook_mem_write;
|
|
|
|
/* evaluate esil expression */
|
|
|
|
r_anal_esil_parse (esil, expr);
|
|
|
|
/* restore hooks */
|
|
|
|
esil->cb = ocbs;
|
2015-09-14 09:31:54 +00:00
|
|
|
ocbs_set = false;
|
2016-11-14 00:17:58 +00:00
|
|
|
esil->verbose = esil_verbose;
|
2015-02-22 10:18:40 +00:00
|
|
|
esil->trace_idx ++;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_anal_esil_trace_list (RAnalEsil *esil) {
|
2016-10-20 19:12:52 +00:00
|
|
|
SdbKv *kv;
|
|
|
|
SdbListIter *iter;
|
|
|
|
SdbList *list = sdb_foreach_list (esil->db_trace, true);
|
|
|
|
ls_foreach (list, iter, kv) {
|
|
|
|
eprintf ("%s=%s\n", kv->key, kv->value);
|
|
|
|
}
|
|
|
|
ls_free (list);
|
2015-02-22 10:18:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_anal_esil_trace_show(RAnalEsil *esil, int idx) {
|
2015-08-08 18:15:13 +00:00
|
|
|
PrintfCallback p = esil->anal->cb_printf;
|
2015-02-22 10:18:40 +00:00
|
|
|
const char *str2;
|
|
|
|
const char *str;
|
|
|
|
int trace_idx = esil->trace_idx;
|
|
|
|
esil->trace_idx = idx;
|
|
|
|
|
|
|
|
str2 = sdb_const_get (DB, KEY ("addr"), 0);
|
|
|
|
if (!str2) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
p ("dr pc = %s\n", str2);
|
|
|
|
/* registers */
|
|
|
|
str = sdb_const_get (DB, KEY ("reg.read"), 0);
|
|
|
|
if (str) {
|
|
|
|
char regname[32];
|
|
|
|
const char *next, *ptr = str;
|
|
|
|
if (ptr && *ptr) {
|
|
|
|
do {
|
2018-08-19 13:51:27 +00:00
|
|
|
next = sdb_const_anext (ptr);
|
|
|
|
int len = next? (int)(size_t)(next-ptr)-1 : strlen (ptr);
|
2015-02-22 10:18:40 +00:00
|
|
|
if (len <sizeof(regname)) {
|
2018-08-19 13:51:27 +00:00
|
|
|
memcpy (regname, ptr, len);
|
2015-02-22 10:18:40 +00:00
|
|
|
regname[len] = 0;
|
|
|
|
str2 = sdb_const_get (DB, KEYREG ("reg.read", regname), 0);
|
|
|
|
p ("dr %s = %s\n", regname, str2);
|
|
|
|
} else {
|
|
|
|
eprintf ("Invalid entry in reg.read\n");
|
|
|
|
}
|
|
|
|
ptr = next;
|
|
|
|
} while (next);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* memory */
|
|
|
|
str = sdb_const_get (DB, KEY ("mem.read"), 0);
|
|
|
|
if (str) {
|
|
|
|
char addr[64];
|
|
|
|
const char *next, *ptr = str;
|
|
|
|
if (ptr && *ptr) {
|
|
|
|
do {
|
2018-08-19 13:51:27 +00:00
|
|
|
next = sdb_const_anext (ptr);
|
|
|
|
int len = next? (int)(size_t)(next-ptr)-1 : strlen (ptr);
|
2015-02-22 10:18:40 +00:00
|
|
|
if (len <sizeof(addr)) {
|
2018-08-19 13:51:27 +00:00
|
|
|
memcpy (addr, ptr, len);
|
2015-02-22 10:18:40 +00:00
|
|
|
addr[len] = 0;
|
|
|
|
str2 = sdb_const_get (DB, KEYAT ("mem.read.data",
|
|
|
|
r_num_get (NULL, addr)), 0);
|
|
|
|
p ("wx %s @ %s\n", str2, addr);
|
|
|
|
} else {
|
|
|
|
eprintf ("Invalid entry in reg.read\n");
|
|
|
|
}
|
|
|
|
ptr = next;
|
|
|
|
} while (next);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
esil->trace_idx = trace_idx;
|
|
|
|
}
|