mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-23 13:19:54 +00:00
Fix regression in asm.trace.times ##disasm (#22835)
* Add test with esil emulation instruction tracing * Fix UAF in debug traces, vector fields are not constant
This commit is contained in:
parent
0535e9a802
commit
693a7d5ebe
@ -1,6 +1,8 @@
|
||||
/* radare - LGPL - Copyright 2008-2023 - pancake */
|
||||
/* radare - LGPL - Copyright 2008-2024 - pancake, Luc Tielen */
|
||||
|
||||
#include <r_debug.h>
|
||||
#include <r_util/r_str.h>
|
||||
#include <sdb/ht_pu.h>
|
||||
|
||||
R_VEC_TYPE(RVecDebugTracepoint, RDebugTracepoint);
|
||||
|
||||
@ -18,6 +20,7 @@ R_API RDebugTrace *r_debug_trace_new(void) {
|
||||
return NULL;
|
||||
}
|
||||
t->ht = ht_pp_new0 ();
|
||||
// t->ht = ht_pu_new0 ();
|
||||
if (!t->ht) {
|
||||
r_debug_trace_free (t);
|
||||
return NULL;
|
||||
@ -25,24 +28,26 @@ R_API RDebugTrace *r_debug_trace_new(void) {
|
||||
return t;
|
||||
}
|
||||
|
||||
R_API void r_debug_trace_free(RDebugTrace *trace) {
|
||||
if (trace) {
|
||||
RVecDebugTracepoint_free (trace->traces);
|
||||
ht_pp_free (trace->ht);
|
||||
free (trace);
|
||||
R_API void r_debug_trace_free(RDebugTrace *t) {
|
||||
if (t) {
|
||||
RVecDebugTracepoint_free (t->traces);
|
||||
ht_pp_free (t->ht);
|
||||
// ht_pu_free (t->ht);
|
||||
free (t);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: added overlap/mask support here... wtf?
|
||||
// TODO: think about tagged traces .. must return 0 or ntag :?
|
||||
R_API int r_debug_trace_tag(RDebug *dbg, int tag) {
|
||||
r_return_val_if_fail (dbg && dbg->trace, 0);
|
||||
R_RETURN_VAL_IF_FAIL (dbg && dbg->trace, 0);
|
||||
ut32 ntag = (tag > 0)? (ut32)tag: UT32_MAX;
|
||||
dbg->trace->tag = ntag;
|
||||
return ntag;
|
||||
}
|
||||
|
||||
R_API bool r_debug_trace_ins_before(RDebug *dbg) {
|
||||
R_RETURN_VAL_IF_FAIL (dbg, false);
|
||||
RListIter *it, *it_tmp;
|
||||
RAnalValue *val;
|
||||
ut8 buf_pc[32];
|
||||
@ -162,7 +167,7 @@ R_API bool r_debug_trace_ins_after(RDebug *dbg) {
|
||||
* something happened at the given pc that we need to trace
|
||||
*/
|
||||
R_API bool r_debug_trace_pc(RDebug *dbg, ut64 pc) {
|
||||
r_return_val_if_fail (dbg && dbg->trace, false);
|
||||
R_RETURN_VAL_IF_FAIL (dbg && dbg->trace, false);
|
||||
ut8 buf[32];
|
||||
RAnalOp op = {0};
|
||||
if (!dbg->iob.is_valid_offset (dbg->iob.io, pc, 0)) {
|
||||
@ -179,31 +184,32 @@ R_API bool r_debug_trace_pc(RDebug *dbg, ut64 pc) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static R_TH_LOCAL ut64 oldpc = UT64_MAX; // XXX Must trace the previously traced instruction
|
||||
|
||||
R_API void r_debug_trace_op(RDebug *dbg, RAnalOp *op) {
|
||||
r_return_if_fail (dbg && dbg->trace);
|
||||
R_RETURN_IF_FAIL (dbg && dbg->trace);
|
||||
if (dbg->trace->enabled) {
|
||||
r_esil_trace_op (dbg->anal->esil, op);
|
||||
if (oldpc != UT64_MAX) {
|
||||
r_debug_trace_add (dbg, oldpc, op->size); //XXX review what this line really do
|
||||
}
|
||||
r_debug_trace_add (dbg, op->addr, op->size);
|
||||
}
|
||||
oldpc = op->addr;
|
||||
}
|
||||
|
||||
R_API void r_debug_trace_at(RDebug *dbg, const char *str) {
|
||||
r_return_if_fail (dbg && dbg->trace);
|
||||
R_RETURN_IF_FAIL (dbg && dbg->trace);
|
||||
// TODO: parse offsets and so use ut64 instead of strstr()
|
||||
free (dbg->trace->addresses);
|
||||
dbg->trace->addresses = R_STR_ISNOTEMPTY (str)? strdup (str): NULL;
|
||||
}
|
||||
|
||||
R_API RDebugTracepoint *r_debug_trace_get(RDebug *dbg, ut64 addr) {
|
||||
r_return_val_if_fail (dbg && dbg->trace, NULL);
|
||||
int tag = dbg->trace->tag;
|
||||
r_strf_var (key, 64, "trace.%d.%"PFMT64x, tag, addr);
|
||||
return ht_pp_find (dbg->trace->ht, key, NULL);
|
||||
R_RETURN_VAL_IF_FAIL (dbg && dbg->trace, NULL);
|
||||
const int tag = dbg->trace->tag;
|
||||
r_strf_var (key, 64, "%d.%"PFMT64x, tag, addr);
|
||||
bool found = false;
|
||||
int pos = (int)(size_t)ht_pp_find (dbg->trace->ht, key, &found);
|
||||
if (found) {
|
||||
return RVecDebugTracepoint_at (dbg->trace->traces, pos - 1);
|
||||
}
|
||||
return NULL;
|
||||
// return ht_pp_find (dbg->trace->ht, key, NULL);
|
||||
}
|
||||
|
||||
static int cmpaddr(const RListInfo *a, const RListInfo *b) {
|
||||
@ -254,7 +260,7 @@ static inline void listinfo_fini(RListInfo *info) {
|
||||
free (info->extra);
|
||||
}
|
||||
|
||||
R_VEC_TYPE_WITH_FINI(RVecListInfo, RListInfo, listinfo_fini);
|
||||
R_VEC_TYPE_WITH_FINI (RVecListInfo, RListInfo, listinfo_fini);
|
||||
|
||||
static void r_debug_trace_list_table(RDebug *dbg, ut64 offset) {
|
||||
RVecListInfo info_vec;
|
||||
@ -271,7 +277,6 @@ static void r_debug_trace_list_table(RDebug *dbg, ut64 offset) {
|
||||
RVecListInfo_fini (&info_vec);
|
||||
return;
|
||||
}
|
||||
|
||||
info->pitv = (RInterval) {trace->addr, trace->size};
|
||||
info->vitv = info->pitv;
|
||||
info->perm = -1;
|
||||
@ -318,7 +323,7 @@ static void r_debug_trace_list_default(RDebug *dbg) {
|
||||
}
|
||||
|
||||
R_API void r_debug_trace_list(RDebug *dbg, int mode, ut64 offset) {
|
||||
r_return_if_fail (dbg && dbg->trace);
|
||||
R_RETURN_IF_FAIL (dbg && dbg->trace);
|
||||
switch (mode) {
|
||||
case 'j':
|
||||
r_debug_trace_list_json (dbg);
|
||||
@ -342,8 +347,7 @@ R_API void r_debug_trace_list(RDebug *dbg, int mode, ut64 offset) {
|
||||
// XXX: find better name, make it public?
|
||||
static bool r_debug_trace_is_traceable(RDebug *dbg, ut64 addr) {
|
||||
if (dbg->trace->addresses) {
|
||||
char addr_str[32];
|
||||
snprintf (addr_str, sizeof (addr_str), "0x%08"PFMT64x, addr);
|
||||
r_strf_var (addr_str, 64, "0x%08"PFMT64x, addr);
|
||||
if (!strstr (dbg->trace->addresses, addr_str)) {
|
||||
return false;
|
||||
}
|
||||
@ -352,12 +356,19 @@ static bool r_debug_trace_is_traceable(RDebug *dbg, ut64 addr) {
|
||||
}
|
||||
|
||||
R_API RDebugTracepoint *r_debug_trace_add(RDebug *dbg, ut64 addr, int size) {
|
||||
r_return_val_if_fail (dbg, NULL);
|
||||
int tag = dbg->trace->tag;
|
||||
R_RETURN_VAL_IF_FAIL (dbg, NULL);
|
||||
const int tag = dbg->trace->tag;
|
||||
if (!r_debug_trace_is_traceable (dbg, addr)) {
|
||||
return NULL;
|
||||
}
|
||||
r_anal_trace_bb (dbg->anal, addr);
|
||||
int last_times = 1;
|
||||
RDebugTracepoint *last = r_debug_trace_get (dbg, addr);
|
||||
if (last) {
|
||||
last_times = last->times + 1;
|
||||
}
|
||||
int pos = RVecDebugTracepoint_length (dbg->trace->traces) + 1;
|
||||
// emplacedback pointers are not constant, so we may rely on the index instead of ptr
|
||||
RDebugTracepoint *tp = RVecDebugTracepoint_emplace_back (dbg->trace->traces);
|
||||
if (R_LIKELY (tp)) {
|
||||
tp->stamp = r_time_now ();
|
||||
@ -365,18 +376,26 @@ R_API RDebugTracepoint *r_debug_trace_add(RDebug *dbg, ut64 addr, int size) {
|
||||
tp->tags = tag;
|
||||
tp->size = size;
|
||||
tp->count = ++dbg->trace->count;
|
||||
tp->times = 1;
|
||||
r_strf_var (key, 64, "trace.%d.%"PFMT64x, tag, addr);
|
||||
ht_pp_update (dbg->trace->ht, key, tp);
|
||||
tp->times = last_times;
|
||||
r_strf_var (key, 64, "%d.%"PFMT64x, tag, addr);
|
||||
void *ip = (void*)(size_t)(pos);
|
||||
ht_pp_update (dbg->trace->ht, key, ip);
|
||||
// for some reason pu mode doesnt work but storing integers as pointers works
|
||||
// ht_pu_update (dbg->trace->ht, key, pos);
|
||||
// ht_pp_delete (dbg->trace->ht, key);
|
||||
// ht_pu_insert (dbg->trace->ht, key, pos);
|
||||
// eprintf ("UP %s %llx\n", key, addr);
|
||||
}
|
||||
return tp;
|
||||
}
|
||||
|
||||
R_API void r_debug_trace_reset(RDebug *dbg) {
|
||||
r_return_if_fail (dbg);
|
||||
R_RETURN_IF_FAIL (dbg);
|
||||
RDebugTrace *t = dbg->trace;
|
||||
ht_pp_free (t->ht);
|
||||
t->ht = ht_pp_new0 ();
|
||||
// ht_pu_free (t->ht);
|
||||
// t->ht = ht_pu_new0 ();
|
||||
RVecDebugTracepoint_free (t->traces);
|
||||
t->traces = RVecDebugTracepoint_new ();
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* radare - LGPL - Copyright 2009-2023 - pancake */
|
||||
/* radare - LGPL - Copyright 2009-2024 - pancake */
|
||||
|
||||
#ifndef R2_DEBUG_H
|
||||
#define R2_DEBUG_H
|
||||
@ -225,7 +225,7 @@ typedef struct r_snap_entry {
|
||||
int perm;
|
||||
} RSnapEntry;
|
||||
|
||||
R_VEC_FORWARD_DECLARE(RVecDebugTracepoint);
|
||||
R_VEC_FORWARD_DECLARE (RVecDebugTracepoint);
|
||||
|
||||
typedef struct r_debug_trace_t {
|
||||
RVecDebugTracepoint *traces;
|
||||
|
32
test/db/cmd/cmd_traces
Normal file
32
test/db/cmd/cmd_traces
Normal file
@ -0,0 +1,32 @@
|
||||
NAME=asm.trace
|
||||
FILE=bins/mach0/main-loop
|
||||
CMDS=<<EOF
|
||||
af
|
||||
e asm.flags.inline=true
|
||||
e asm.comments=false
|
||||
e asm.trace=1
|
||||
e dbg.trace=1
|
||||
aeim
|
||||
e asm.bytes=0
|
||||
s main
|
||||
30ds
|
||||
pdf
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
;-- section.0.__TEXT.__text, entry0, sym._main, sym.func.100003f84:
|
||||
/ 36: int main (int argc);
|
||||
| ; arg int argc @ x0
|
||||
| ; var int64_t var_8h @ sp+0x8
|
||||
| 0x100003f84 01:0001 sub sp, sp, 0x10
|
||||
| 0x100003f88 01:0002 str wzr, [sp, 0xc]
|
||||
| 0x100003f8c 01:0003 mov w8, 3
|
||||
| 0x100003f90 01:0004 str w8, [sp, 8]
|
||||
| ,=< 0x100003f94 01:0005 b 0x100003f98
|
||||
| .`-> 0x100003f98 07:001e ldr w8, [var_8h]
|
||||
| : ;-- pc:
|
||||
| : 0x100003f9c 06:001b add w8, w8, 1
|
||||
| : 0x100003fa0 06:001c str w8, [sp, 8]
|
||||
\ `==< 0x100003fa4 06:001d b 0x100003f98
|
||||
EOF
|
||||
RUN
|
||||
|
Loading…
Reference in New Issue
Block a user