Rizin
unix-like reverse engineering framework and cli tools
trace.c File Reference
#include <rz_debug.h>

Go to the source code of this file.

Functions

RZ_API RzDebugTracerz_debug_trace_new (void)
 
RZ_API void rz_debug_trace_free (RzDebugTrace *trace)
 
RZ_API int rz_debug_trace_tag (RzDebug *dbg, int tag)
 
RZ_API bool rz_debug_trace_ins_before (RzDebug *dbg)
 
RZ_API bool rz_debug_trace_ins_after (RzDebug *dbg)
 
RZ_API int rz_debug_trace_pc (RzDebug *dbg, ut64 pc)
 
RZ_API void rz_debug_trace_op (RzDebug *dbg, RzAnalysisOp *op)
 
RZ_API void rz_debug_trace_at (RzDebug *dbg, const char *str)
 
RZ_API RzDebugTracepointrz_debug_trace_get (RzDebug *dbg, ut64 addr)
 
static int cmpaddr (const void *_a, const void *_b)
 
RZ_API RZ_OWN RzListrz_debug_traces_info (RzDebug *dbg, ut64 offset)
 
static int rz_debug_trace_is_traceable (RzDebug *dbg, ut64 addr)
 
RZ_API RzDebugTracepointrz_debug_trace_add (RzDebug *dbg, ut64 addr, int size)
 
RZ_API void rz_debug_trace_reset (RzDebug *dbg)
 

Function Documentation

◆ cmpaddr()

static int cmpaddr ( const void *  _a,
const void *  _b 
)
static

Definition at line 206 of file trace.c.

206  {
207  const RzListInfo *a = _a, *b = _b;
208  return (rz_itv_begin(a->pitv) > rz_itv_begin(b->pitv)) ? 1 : (rz_itv_begin(a->pitv) < rz_itv_begin(b->pitv)) ? -1
209  : 0;
210 }
static ut64 rz_itv_begin(RzInterval itv)
Definition: rz_itv.h:34
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41

References a, b, and rz_itv_begin().

Referenced by rz_debug_traces_info().

◆ rz_debug_trace_add()

RZ_API RzDebugTracepoint* rz_debug_trace_add ( RzDebug dbg,
ut64  addr,
int  size 
)

Definition at line 261 of file trace.c.

261  {
262  RzDebugTracepoint *tp;
263  int tag = dbg->trace->tag;
265  return NULL;
266  }
269  if (!tp) {
270  return NULL;
271  }
272  tp->stamp = rz_time_now();
273  tp->addr = addr;
274  tp->tags = tag;
275  tp->size = size;
276  tp->count = ++dbg->trace->count;
277  tp->times = 1;
279  ht_pp_update(dbg->trace->ht,
280  sdb_fmt("trace.%d.%" PFMT64x, tag, addr), tp);
281  return tp;
282 }
RZ_API void rz_analysis_trace_bb(RzAnalysis *analysis, ut64 addr)
Definition: analysis.c:377
#define NULL
Definition: cris-opc.c:27
RzDebug * dbg
Definition: desil.c:30
RZ_API char * sdb_fmt(const char *fmt,...)
Definition: fmt.c:26
voidpf void uLong size
Definition: ioapi.h:138
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API ut64 rz_time_now(void)
Returns the current time in microseconds.
Definition: time.c:88
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define PFMT64x
Definition: rz_types.h:393
RzDebugTrace * trace
Definition: rz_debug.h:281
RzAnalysis * analysis
Definition: rz_debug.h:305
RzList * traces
Definition: rz_debug.h:220
static int rz_debug_trace_is_traceable(RzDebug *dbg, ut64 addr)
Definition: trace.c:250
static int addr
Definition: z80asm.c:58

References addr, rz_debug_tracepoint_t::addr, rz_debug_t::analysis, rz_debug_trace_t::count, rz_debug_tracepoint_t::count, dbg, rz_debug_trace_t::ht, NULL, PFMT64x, rz_analysis_trace_bb(), rz_debug_trace_is_traceable(), rz_list_append(), RZ_NEW0, rz_time_now(), sdb_fmt(), rz_debug_tracepoint_t::size, rz_debug_tracepoint_t::stamp, rz_debug_trace_t::tag, test-lz4-versions::tag, rz_debug_tracepoint_t::tags, rz_debug_tracepoint_t::times, rz_debug_t::trace, and rz_debug_trace_t::traces.

Referenced by rz_cmd_debug_trace_add_addrs_handler(), rz_cmd_debug_trace_add_handler(), and rz_debug_trace_op().

◆ rz_debug_trace_at()

RZ_API void rz_debug_trace_at ( RzDebug dbg,
const char *  str 
)

Definition at line 194 of file trace.c.

194  {
195  // TODO: parse offsets and so use ut64 instead of strstr()
196  free(dbg->trace->addresses);
197  dbg->trace->addresses = (str && *str) ? strdup(str) : NULL;
198 }
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
char * addresses
Definition: rz_debug.h:226

References rz_debug_trace_t::addresses, dbg, free(), NULL, cmd_descs_generate::str, strdup(), and rz_debug_t::trace.

Referenced by rz_cmd_debug_trace_addr().

◆ rz_debug_trace_free()

RZ_API void rz_debug_trace_free ( RzDebugTrace trace)

Definition at line 29 of file trace.c.

29  {
30  if (!trace) {
31  return;
32  }
33  rz_list_purge(trace->traces);
34  free(trace->traces);
35  ht_pp_free(trace->ht);
36  RZ_FREE(trace);
37 }
RZ_API void rz_list_purge(RZ_NONNULL RzList *list)
Empties the list without freeing the list pointer.
Definition: list.c:120
#define RZ_FREE(x)
Definition: rz_types.h:369

References free(), rz_debug_trace_t::ht, RZ_FREE, rz_list_purge(), and rz_debug_trace_t::traces.

Referenced by analysis_emul_restore(), rz_cmd_debug_traces_reset_handler(), rz_debug_free(), and rz_debug_trace_new().

◆ rz_debug_trace_get()

RZ_API RzDebugTracepoint* rz_debug_trace_get ( RzDebug dbg,
ut64  addr 
)

◆ rz_debug_trace_ins_after()

RZ_API bool rz_debug_trace_ins_after ( RzDebug dbg)

Definition at line 110 of file trace.c.

110  {
112  RzListIter *it;
114 
115  // Add reg/mem write change
117  rz_list_foreach (dbg->cur_op->access, it, val) {
118  if (!(val->access & RZ_ANALYSIS_ACC_W)) {
119  continue;
120  }
121 
122  switch (val->type) {
123  case RZ_ANALYSIS_VAL_REG: {
124  if (!val->reg) {
125  RZ_LOG_ERROR("invalid register, unable to trace register state\n");
126  continue;
127  }
128  ut64 data = rz_reg_get_value(dbg->reg, val->reg);
129 
130  // add reg write
131  rz_debug_session_add_reg_change(dbg->session, val->reg->arena, val->reg->offset, data);
132  break;
133  }
134  case RZ_ANALYSIS_VAL_MEM: {
135  ut8 buf[32] = { 0 };
136  if (!dbg->iob.read_at(dbg->iob.io, val->base, buf, val->memref)) {
137  eprintf("Error reading memory at 0x%" PFMT64x "\n", val->base);
138  break;
139  }
140 
141  // add mem write
142  size_t i;
143  for (i = 0; i < val->memref; i++) {
145  }
146  break;
147  }
148  default:
149  break;
150  }
151  }
153  dbg->cur_op = NULL;
154  return true;
155 }
lzma_index ** i
Definition: index.h:629
ut16 val
Definition: armass64_const.h:6
RZ_API int rz_debug_reg_sync(RzDebug *dbg, int type, int write)
Definition: dreg.c:9
RZ_API bool rz_debug_session_add_reg_change(RzDebugSession *session, int arena, ut64 offset, ut64 data)
Definition: dsession.c:218
RZ_API bool rz_debug_session_add_mem_change(RzDebugSession *session, ut64 addr, ut8 data)
Definition: dsession.c:233
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
RZ_API void rz_analysis_op_free(void *op)
Definition: op.c:61
#define eprintf(x, y...)
Definition: rlcc.c:7
RZ_API ut64 rz_reg_get_value(RzReg *reg, RzRegItem *item)
Definition: rvalue.c:114
@ RZ_ANALYSIS_VAL_REG
Definition: rz_analysis.h:768
@ RZ_ANALYSIS_VAL_MEM
Definition: rz_analysis.h:769
@ RZ_ANALYSIS_ACC_W
Definition: rz_analysis.h:763
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
@ RZ_REG_TYPE_ANY
Definition: rz_reg.h:35
RzDebugSession * session
Definition: rz_debug.h:311
RzAnalysisOp * cur_op
Definition: rz_debug.h:310
RzReg * reg
Definition: rz_debug.h:286
RzIOBind iob
Definition: rz_debug.h:293
RzIOReadAt read_at
Definition: rz_io.h:240
RzIO * io
Definition: rz_io.h:232
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References rz_analysis_op_t::access, rz_debug_t::cur_op, dbg, eprintf, i, rz_io_bind_t::io, rz_debug_t::iob, NULL, PFMT64x, rz_io_bind_t::read_at, rz_debug_t::reg, RZ_ANALYSIS_ACC_W, rz_analysis_op_free(), RZ_ANALYSIS_VAL_MEM, RZ_ANALYSIS_VAL_REG, rz_debug_reg_sync(), rz_debug_session_add_mem_change(), rz_debug_session_add_reg_change(), RZ_LOG_ERROR, rz_reg_get_value(), RZ_REG_TYPE_ANY, rz_return_val_if_fail, rz_debug_t::session, ut64(), and val.

Referenced by rz_debug_step(), and rz_debug_step_over().

◆ rz_debug_trace_ins_before()

RZ_API bool rz_debug_trace_ins_before ( RzDebug dbg)

Definition at line 46 of file trace.c.

46  {
47  RzListIter *it, *it_tmp;
49  ut8 buf_pc[32];
50 
51  // Analyze current instruction
53  if (!dbg->iob.read_at) {
54  return false;
55  }
56  if (!dbg->iob.read_at(dbg->iob.io, pc, buf_pc, sizeof(buf_pc))) {
57  return false;
58  }
60  if (!dbg->cur_op) {
61  return false;
62  }
63  if (rz_analysis_op(dbg->analysis, dbg->cur_op, pc, buf_pc, sizeof(buf_pc), RZ_ANALYSIS_OP_MASK_VAL) < 1) {
65  dbg->cur_op = NULL;
66  return false;
67  }
68 
69  // resolve mem write address
70  rz_list_foreach_safe (dbg->cur_op->access, it, it_tmp, val) {
71  switch (val->type) {
73  if (!(val->access & RZ_ANALYSIS_ACC_W)) {
75  }
76  break;
78  if (val->memref > 32) {
79  eprintf("Error: adding changes to %d bytes in memory.\n", val->memref);
81  break;
82  }
83 
84  if (val->access & RZ_ANALYSIS_ACC_W) {
85  // resolve memory address
86  ut64 addr = 0;
87  addr += val->delta;
88  if (val->seg) {
89  addr += rz_reg_get_value(dbg->reg, val->seg);
90  }
91  if (val->reg) {
92  addr += rz_reg_get_value(dbg->reg, val->reg);
93  }
94  if (val->regdelta) {
95  int mul = val->mul ? val->mul : 1;
96  addr += mul * rz_reg_get_value(dbg->reg, val->regdelta);
97  }
98  // resolve address into base for ins_after
99  val->base = addr;
100  } else {
102  }
103  default:
104  break;
105  }
106  }
107  return true;
108 }
static RzILOpEffect * mul(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:539
RZ_API ut64 rz_debug_reg_get(RzDebug *dbg, const char *name)
Definition: dreg.c:99
RZ_API void rz_list_delete(RZ_NONNULL RzList *list, RZ_NONNULL RzListIter *iter)
Removes an entry in the list by using the RzListIter pointer.
Definition: list.c:162
RZ_API int rz_analysis_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask)
Definition: op.c:96
@ RZ_ANALYSIS_OP_MASK_VAL
Definition: rz_analysis.h:442
@ RZ_REG_NAME_PC
Definition: rz_reg.h:43
char * name[RZ_REG_NAME_LAST]
Definition: rz_reg.h:149

References rz_analysis_op_t::access, addr, rz_debug_t::analysis, rz_debug_t::cur_op, dbg, eprintf, rz_io_bind_t::io, rz_debug_t::iob, mul(), rz_reg_t::name, NULL, pc, rz_io_bind_t::read_at, rz_debug_t::reg, RZ_ANALYSIS_ACC_W, rz_analysis_op(), rz_analysis_op_free(), RZ_ANALYSIS_OP_MASK_VAL, RZ_ANALYSIS_VAL_MEM, RZ_ANALYSIS_VAL_REG, rz_debug_reg_get(), rz_list_delete(), RZ_NEW0, rz_reg_get_value(), RZ_REG_NAME_PC, ut64(), and val.

Referenced by rz_debug_step(), and rz_debug_step_over().

◆ rz_debug_trace_is_traceable()

static int rz_debug_trace_is_traceable ( RzDebug dbg,
ut64  addr 
)
static

Definition at line 250 of file trace.c.

250  {
251  if (dbg->trace->addresses) {
252  char addr_str[32];
253  snprintf(addr_str, sizeof(addr_str), "0x%08" PFMT64x, addr);
254  if (!strstr(dbg->trace->addresses, addr_str)) {
255  return false;
256  }
257  }
258  return true;
259 }
snprintf
Definition: kernel.h:364

References addr, rz_debug_trace_t::addresses, dbg, PFMT64x, snprintf, and rz_debug_t::trace.

Referenced by rz_debug_trace_add().

◆ rz_debug_trace_new()

RZ_API RzDebugTrace* rz_debug_trace_new ( void  )

Definition at line 7 of file trace.c.

7  {
9  if (!t) {
10  return NULL;
11  }
12  t->tag = 1; // UT32_MAX;
13  t->addresses = NULL;
14  t->enabled = false;
15  t->traces = rz_list_new();
16  if (!t->traces) {
18  return NULL;
19  }
20  t->traces->free = free;
21  t->ht = ht_pp_new0();
22  if (!t->ht) {
24  return NULL;
25  }
26  return t;
27 }
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
RzListFree free
Definition: rz_list.h:21
RZ_API void rz_debug_trace_free(RzDebugTrace *trace)
Definition: trace.c:29

References rz_debug_trace_t::addresses, rz_debug_trace_t::enabled, rz_list_t::free, free(), rz_debug_trace_t::ht, NULL, rz_debug_trace_free(), rz_list_new(), RZ_NEW0, rz_debug_trace_t::tag, and rz_debug_trace_t::traces.

Referenced by analysis_emul_init(), rz_cmd_debug_traces_reset_handler(), and rz_debug_new().

◆ rz_debug_trace_op()

RZ_API void rz_debug_trace_op ( RzDebug dbg,
RzAnalysisOp op 
)

Definition at line 177 of file trace.c.

177  {
178  static ut64 oldpc = UT64_MAX; // Must trace the previously traced instruction
179  if (dbg->trace->enabled) {
180  if (dbg->analysis->esil) {
182  } else {
183  if (dbg->verbose) {
184  eprintf("Run aeim to get dbg->analysis->esil initialized\n");
185  }
186  }
187  }
188  if (oldpc != UT64_MAX) {
189  rz_debug_trace_add(dbg, oldpc, op->size); // XXX review what this line really do
190  }
191  oldpc = op->addr;
192 }
RZ_API void rz_analysis_esil_trace_op(RzAnalysisEsil *esil, RZ_NONNULL RzAnalysisOp *op)
Definition: esil_trace.c:271
#define UT64_MAX
Definition: rz_types_base.h:86
struct rz_analysis_esil_t * esil
Definition: rz_analysis.h:584
bool verbose
Definition: rz_debug.h:319
RZ_API RzDebugTracepoint * rz_debug_trace_add(RzDebug *dbg, ut64 addr, int size)
Definition: trace.c:261
Definition: dis.c:32

References rz_debug_t::analysis, dbg, rz_debug_trace_t::enabled, eprintf, rz_analysis_t::esil, rz_analysis_esil_trace_op(), rz_debug_trace_add(), rz_debug_t::trace, ut64(), UT64_MAX, and rz_debug_t::verbose.

Referenced by rz_core_esil_step(), and rz_debug_trace_pc().

◆ rz_debug_trace_pc()

RZ_API int rz_debug_trace_pc ( RzDebug dbg,
ut64  pc 
)

Definition at line 160 of file trace.c.

160  {
161  ut8 buf[32];
162  RzAnalysisOp op = { 0 };
163  if (!dbg->iob.is_valid_offset(dbg->iob.io, pc, 0)) {
164  eprintf("trace_pc: cannot read memory at 0x%" PFMT64x "\n", pc);
165  return false;
166  }
167  (void)dbg->iob.read_at(dbg->iob.io, pc, buf, sizeof(buf));
168  if (rz_analysis_op(dbg->analysis, &op, pc, buf, sizeof(buf), RZ_ANALYSIS_OP_MASK_ESIL) < 1) {
169  eprintf("trace_pc: cannot get opcode size at 0x%" PFMT64x "\n", pc);
170  return false;
171  }
174  return true;
175 }
RZ_API bool rz_analysis_op_fini(RzAnalysisOp *op)
Definition: op.c:37
@ RZ_ANALYSIS_OP_MASK_ESIL
Definition: rz_analysis.h:441
RzIOIsValidOff is_valid_offset
Definition: rz_io.h:257
RZ_API void rz_debug_trace_op(RzDebug *dbg, RzAnalysisOp *op)
Definition: trace.c:177

References rz_debug_t::analysis, dbg, eprintf, rz_io_bind_t::io, rz_debug_t::iob, rz_io_bind_t::is_valid_offset, pc, PFMT64x, rz_io_bind_t::read_at, rz_analysis_op(), rz_analysis_op_fini(), RZ_ANALYSIS_OP_MASK_ESIL, and rz_debug_trace_op().

Referenced by rz_core_debug_step_one(), and rz_debug_bp_hit().

◆ rz_debug_trace_reset()

RZ_API void rz_debug_trace_reset ( RzDebug dbg)

Definition at line 284 of file trace.c.

284  {
285  RzDebugTrace *t = dbg->trace;
286  rz_list_purge(t->traces);
287  ht_pp_free(t->ht);
288  t->ht = ht_pp_new0();
289  t->traces = rz_list_new();
290  t->traces->free = free;
291 }

References dbg, rz_list_t::free, free(), rz_debug_trace_t::ht, rz_list_new(), rz_list_purge(), rz_debug_t::trace, and rz_debug_trace_t::traces.

◆ rz_debug_trace_tag()

RZ_API int rz_debug_trace_tag ( RzDebug dbg,
int  tag 
)

Definition at line 41 of file trace.c.

41  {
42  // if (tag>0 && tag<31) core->dbg->trace->tag = 1<<(sz-1);
43  return (dbg->trace->tag = (tag > 0) ? tag : UT32_MAX);
44 }
#define UT32_MAX
Definition: rz_types_base.h:99

References dbg, rz_debug_trace_t::tag, test-lz4-versions::tag, rz_debug_t::trace, and UT32_MAX.

Referenced by rz_cmd_debug_trace_tag_handler().

◆ rz_debug_traces_info()

RZ_API RZ_OWN RzList* rz_debug_traces_info ( RzDebug dbg,
ut64  offset 
)

Definition at line 218 of file trace.c.

218  {
220  int tag = dbg->trace->tag;
221  RzListIter *iter;
222  RzList *info_list = rz_list_new();
223  if (!info_list) {
224  return NULL;
225  }
226 
227  RzDebugTracepoint *trace;
228  rz_list_foreach (dbg->trace->traces, iter, trace) {
229  if (trace->tag && !(tag & trace->tag)) {
230  continue;
231  }
233  if (!info) {
234  rz_list_free(info_list);
235  return NULL;
236  }
237  info->pitv = (RzInterval){ trace->addr, trace->size };
238  info->vitv = info->pitv;
239  info->perm = -1;
240  info->name = rz_str_newf("%d", trace->times);
241  info->extra = rz_str_newf("%d", trace->count);
242  rz_list_append(info_list, info);
243  }
244 
245  rz_list_sort(info_list, cmpaddr);
246  return info_list;
247 }
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
RZ_API void rz_list_sort(RZ_NONNULL RzList *list, RZ_NONNULL RzListComparator cmp)
Sorts via merge sort or via insertion sort a list.
Definition: list.c:743
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
struct rz_interval_t RzInterval
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
static int cmpaddr(const void *_a, const void *_b)
Definition: trace.c:206

References rz_debug_tracepoint_t::addr, cmpaddr(), rz_debug_tracepoint_t::count, dbg, info(), NULL, rz_list_append(), rz_list_free(), rz_list_new(), rz_list_sort(), RZ_NEW0, rz_return_val_if_fail, rz_str_newf(), rz_debug_tracepoint_t::size, rz_debug_trace_t::tag, rz_debug_tracepoint_t::tag, test-lz4-versions::tag, rz_debug_tracepoint_t::times, rz_debug_t::trace, and rz_debug_trace_t::traces.

Referenced by rz_debug_traces_ascii().