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

Go to the source code of this file.

Macros

#define CMP_REG_CHANGE(x, y)   ((x) - ((RzAnalysisEsilRegChange *)(y))->idx)
 
#define CMP_MEM_CHANGE(x, y)   ((x) - ((RzAnalysisEsilMemChange *)(y))->idx)
 

Functions

static bool esil_add_mem_trace (RzAnalysisEsilTrace *etrace, RzILTraceMemOp *mem)
 
static bool esil_add_reg_trace (RzAnalysisEsilTrace *etrace, RzILTraceRegOp *reg)
 
static void htup_vector_free (HtUPKv *kv)
 
RZ_API RzAnalysisEsilTracerz_analysis_esil_trace_new (RzAnalysisEsil *esil)
 
RZ_API void rz_analysis_esil_trace_free (RzAnalysisEsilTrace *trace)
 
static void add_reg_change (RzAnalysisEsilTrace *trace, int idx, RzRegItem *ri, ut64 data)
 
static void add_mem_change (RzAnalysisEsilTrace *trace, int idx, ut64 addr, ut8 data)
 
static int trace_hook_reg_read (RzAnalysisEsil *esil, const char *name, ut64 *res, int *size)
 
static int trace_hook_reg_write (RzAnalysisEsil *esil, const char *name, ut64 *val)
 
static int trace_hook_mem_read (RzAnalysisEsil *esil, ut64 addr, ut8 *buf, int len)
 
static int trace_hook_mem_write (RzAnalysisEsil *esil, ut64 addr, const ut8 *buf, int len)
 
RZ_API RZ_BORROW RzILTraceInstruction * rz_analysis_esil_get_instruction_trace (RZ_NONNULL RzAnalysisEsilTrace *etrace, int idx)
 
RZ_API void rz_analysis_esil_trace_op (RzAnalysisEsil *esil, RZ_NONNULL RzAnalysisOp *op)
 
static bool restore_memory_cb (void *user, const ut64 key, const void *value)
 
static bool restore_register (RzAnalysisEsil *esil, RzRegItem *ri, int idx)
 
RZ_API void rz_analysis_esil_trace_restore (RzAnalysisEsil *esil, int idx)
 
static void print_instruction_ops (RzILTraceInstruction *instruction, int idx, RzILTraceInsOp focus)
 
static void print_instruction_trace (RzILTraceInstruction *instruction, int idx)
 
RZ_API void rz_analysis_esil_trace_list (RzAnalysisEsil *esil)
 
RZ_API void rz_analysis_esil_trace_show (RzAnalysisEsil *esil, int idx)
 

Variables

static int ocbs_set = false
 
static RzAnalysisEsilCallbacks ocbs = { 0 }
 

Macro Definition Documentation

◆ CMP_MEM_CHANGE

#define CMP_MEM_CHANGE (   x,
 
)    ((x) - ((RzAnalysisEsilMemChange *)(y))->idx)

Definition at line 8 of file esil_trace.c.

◆ CMP_REG_CHANGE

#define CMP_REG_CHANGE (   x,
 
)    ((x) - ((RzAnalysisEsilRegChange *)(y))->idx)

Definition at line 7 of file esil_trace.c.

Function Documentation

◆ add_mem_change()

static void add_mem_change ( RzAnalysisEsilTrace trace,
int  idx,
ut64  addr,
ut8  data 
)
static

Definition at line 110 of file esil_trace.c.

110  {
111  RzVector *vmem = ht_up_find(trace->memory, addr, NULL);
112  if (!vmem) {
114  if (!vmem) {
115  RZ_LOG_ERROR("Creating a memory vector.\n");
116  return;
117  }
118  ht_up_insert(trace->memory, addr, vmem);
119  }
120  RzAnalysisEsilMemChange mem = { idx, data };
121  rz_vector_push(vmem, &mem);
122 }
#define NULL
Definition: cris-opc.c:27
void * mem
Definition: libc.cpp:91
int idx
Definition: setup.py:197
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API void * rz_vector_push(RzVector *vec, void *x)
Definition: vector.c:197
RZ_API RzVector * rz_vector_new(size_t elem_size, RzVectorFree free, void *free_user)
Definition: vector.c:42
static int addr
Definition: z80asm.c:58

References addr, setup::idx, mem, rz_analysis_esil_trace_t::memory, NULL, RZ_LOG_ERROR, rz_vector_new(), and rz_vector_push().

Referenced by trace_hook_mem_write().

◆ add_reg_change()

static void add_reg_change ( RzAnalysisEsilTrace trace,
int  idx,
RzRegItem ri,
ut64  data 
)
static

Definition at line 95 of file esil_trace.c.

95  {
96  ut64 addr = ri->offset | (ri->arena << 16);
97  RzVector *vreg = ht_up_find(trace->registers, addr, NULL);
98  if (!vreg) {
100  if (!vreg) {
101  RZ_LOG_ERROR("Creating a register vector.\n");
102  return;
103  }
104  ht_up_insert(trace->registers, addr, vreg);
105  }
106  RzAnalysisEsilRegChange reg = { idx, data };
107  rz_vector_push(vreg, &reg);
108 }
#define reg(n)
int arena
In which arena is this reg living. Usually equals type.
Definition: rz_reg.h:127
int offset
Offset into register profile in bits.
Definition: rz_reg.h:121
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References addr, rz_reg_item_t::arena, setup::idx, NULL, rz_reg_item_t::offset, reg, rz_analysis_esil_trace_t::registers, RZ_LOG_ERROR, rz_vector_new(), rz_vector_push(), and ut64().

Referenced by rz_analysis_esil_trace_op(), and trace_hook_reg_write().

◆ esil_add_mem_trace()

static bool esil_add_mem_trace ( RzAnalysisEsilTrace etrace,
RzILTraceMemOp *  mem 
)
inlinestatic

Definition at line 14 of file esil_trace.c.

14  {
15  RzILTraceInstruction *instr_trace = rz_analysis_esil_get_instruction_trace(etrace, etrace->idx);
16  return rz_analysis_il_trace_add_mem(instr_trace, mem);
17 }
RZ_API RZ_BORROW RzILTraceInstruction * rz_analysis_esil_get_instruction_trace(RZ_NONNULL RzAnalysisEsilTrace *etrace, int idx)
Definition: esil_trace.c:263
RZ_API bool rz_analysis_il_trace_add_mem(RzILTraceInstruction *trace, RzILTraceMemOp *mem)
Definition: il_trace.c:70

References rz_analysis_esil_trace_t::idx, mem, rz_analysis_esil_get_instruction_trace(), and rz_analysis_il_trace_add_mem().

Referenced by trace_hook_mem_read(), and trace_hook_mem_write().

◆ esil_add_reg_trace()

static bool esil_add_reg_trace ( RzAnalysisEsilTrace etrace,
RzILTraceRegOp *  reg 
)
inlinestatic

Definition at line 19 of file esil_trace.c.

19  {
20  RzILTraceInstruction *instr_trace = rz_analysis_esil_get_instruction_trace(etrace, etrace->idx);
21  return rz_analysis_il_trace_add_reg(instr_trace, reg);
22 }
RZ_API bool rz_analysis_il_trace_add_reg(RzILTraceInstruction *trace, RzILTraceRegOp *reg)
Definition: il_trace.c:102

References rz_analysis_esil_trace_t::idx, reg, rz_analysis_esil_get_instruction_trace(), and rz_analysis_il_trace_add_reg().

Referenced by trace_hook_reg_read(), and trace_hook_reg_write().

◆ htup_vector_free()

static void htup_vector_free ( HtUPKv *  kv)
static

Definition at line 24 of file esil_trace.c.

24  {
25  rz_vector_free(kv->value);
26 }
RZ_API void rz_vector_free(RzVector *vec)
Definition: vector.c:75

References rz_vector_free().

Referenced by rz_analysis_esil_trace_new().

◆ print_instruction_ops()

static void print_instruction_ops ( RzILTraceInstruction *  instruction,
int  idx,
RzILTraceInsOp  focus 
)
static

Definition at line 375 of file esil_trace.c.

375  {
376  bool reg = focus == RZ_IL_TRACE_INS_HAS_REG_R || focus == RZ_IL_TRACE_INS_HAS_REG_W;
377  bool read = focus == RZ_IL_TRACE_INS_HAS_REG_R || focus == RZ_IL_TRACE_INS_HAS_MEM_R;
378  const char *direction = read ? "read" : "write";
379  void **it;
380  bool first = true;
381 
382  if (reg) {
383  RzPVector *ops = read ? instruction->read_reg_ops : instruction->write_reg_ops;
384  if (!rz_pvector_empty(ops)) {
385  rz_cons_printf("%d.reg.%s=", idx, direction);
386  rz_pvector_foreach (ops, it) {
387  RzILTraceRegOp *op = (RzILTraceRegOp *)*it;
388  first ? (first = false) : rz_cons_print(",");
389  rz_cons_printf("%s", op->reg_name);
390  }
391  rz_cons_newline();
392  }
393  rz_pvector_foreach (ops, it) {
394  RzILTraceRegOp *op = (RzILTraceRegOp *)*it;
395  rz_cons_printf("%d.reg.%s.%s=%s%" PFMT64x "\n", idx, direction,
396  op->reg_name, op->value < 10 ? "" : "0x", op->value);
397  }
398  } else {
399  RzPVector *ops = read ? instruction->read_mem_ops : instruction->write_mem_ops;
400  if (!rz_pvector_empty(ops)) {
401  rz_cons_printf("%d.mem.%s=", idx, direction);
402  rz_pvector_foreach (ops, it) {
403  RzILTraceMemOp *op = (RzILTraceMemOp *)*it;
404  first ? (first = false) : rz_cons_print(",");
405  rz_cons_printf("0x%" PFMT64x, op->addr);
406  }
407  rz_cons_newline();
408  }
409  rz_pvector_foreach (ops, it) {
410  RzILTraceMemOp *op = (RzILTraceMemOp *)*it;
411  char hexstr[sizeof(op->data_buf) * 2 + 1];
412  rz_hex_bin2str(op->data_buf, RZ_MIN(sizeof(op->data_buf), op->data_len), hexstr);
413  rz_cons_printf("%d.mem.%s.data.0x%" PFMT64x "=%s\n", idx, direction, op->addr, hexstr);
414  }
415  }
416 }
static struct @29 ops[]
RZ_API void rz_cons_newline(void)
Definition: cons.c:1274
RZ_API int rz_cons_printf(const char *format,...)
Definition: cons.c:1202
RZ_API int rz_hex_bin2str(const ut8 *in, int len, char *out)
Definition: hex.c:382
#define PFMT64x
Definition: rz_types.h:393
#define RZ_MIN(x, y)
static bool rz_pvector_empty(RzPVector *vec)
Definition: rz_vector.h:246
#define rz_pvector_foreach(vec, it)
Definition: rz_vector.h:334
Definition: dis.c:32
int read(izstream &zs, T *x, Items items)
Definition: zstream.h:115

References setup::idx, ops, PFMT64x, read(), reg, rz_cons_newline(), rz_cons_printf(), rz_hex_bin2str(), RZ_MIN, rz_pvector_empty(), and rz_pvector_foreach.

Referenced by print_instruction_trace().

◆ print_instruction_trace()

static void print_instruction_trace ( RzILTraceInstruction *  instruction,
int  idx 
)
static

Definition at line 418 of file esil_trace.c.

418  {
419  rz_cons_printf("%d.addr=0x%" PFMT64x "\n", idx, instruction->addr);
420 
421  // IL ops within an instruction are printed in the order reg read, mem
422  // read, reg write, mem write that is partially based on x86 PUSH. This
423  // print order MAY NOT be the same as the actual ops order.
424  print_instruction_ops(instruction, idx, RZ_IL_TRACE_INS_HAS_REG_R);
425  print_instruction_ops(instruction, idx, RZ_IL_TRACE_INS_HAS_MEM_R);
426  print_instruction_ops(instruction, idx, RZ_IL_TRACE_INS_HAS_REG_W);
427  print_instruction_ops(instruction, idx, RZ_IL_TRACE_INS_HAS_MEM_W);
428 }
static void print_instruction_ops(RzILTraceInstruction *instruction, int idx, RzILTraceInsOp focus)
Definition: esil_trace.c:375

References setup::idx, PFMT64x, print_instruction_ops(), and rz_cons_printf().

Referenced by rz_analysis_esil_trace_list(), and rz_analysis_esil_trace_show().

◆ restore_memory_cb()

static bool restore_memory_cb ( void *  user,
const ut64  key,
const void *  value 
)
static

Definition at line 321 of file esil_trace.c.

321  {
322  size_t index;
323  RzAnalysisEsil *esil = user;
324  RzVector *vmem = (RzVector *)value;
325 
326  rz_vector_upper_bound(vmem, esil->trace->idx, index, CMP_MEM_CHANGE);
327  if (index > 0 && index <= vmem->len) {
328  RzAnalysisEsilMemChange *c = rz_vector_index_ptr(vmem, index - 1);
329  esil->analysis->iob.write_at(esil->analysis->iob.io, key, &c->data, 1);
330  }
331  return true;
332 }
size_t len
Definition: 6502dis.c:15
static int value
Definition: cmd_api.c:93
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len key
Definition: sflib.h:118
#define CMP_MEM_CHANGE(x, y)
Definition: esil_trace.c:8
static void * rz_vector_index_ptr(RzVector *vec, size_t index)
Definition: rz_vector.h:88
#define rz_vector_upper_bound(vec, x, i, cmp)
Definition: rz_vector.h:203
#define c(i)
Definition: sha256.c:43
RzAnalysis * analysis
Definition: rz_analysis.h:1043
RzAnalysisEsilTrace * trace
Definition: rz_analysis.h:1077
RzIOBind iob
Definition: rz_analysis.h:574
RzIOWriteAt write_at
Definition: rz_io.h:241
RzIO * io
Definition: rz_io.h:232

References rz_analysis_esil_t::analysis, c, CMP_MEM_CHANGE, rz_analysis_esil_trace_t::idx, rz_io_bind_t::io, rz_analysis_t::iob, key, len, rz_vector_index_ptr(), rz_vector_upper_bound, rz_analysis_esil_t::trace, value, and rz_io_bind_t::write_at.

Referenced by rz_analysis_esil_trace_restore().

◆ restore_register()

static bool restore_register ( RzAnalysisEsil esil,
RzRegItem ri,
int  idx 
)
static

Definition at line 334 of file esil_trace.c.

334  {
335  size_t index;
336  RzVector *vreg = ht_up_find(esil->trace->registers, ri->offset | (ri->arena << 16), NULL);
337  if (vreg) {
339  if (index > 0 && index <= vreg->len) {
340  RzAnalysisEsilRegChange *c = rz_vector_index_ptr(vreg, index - 1);
341  rz_reg_set_value(esil->analysis->reg, ri, c->data);
342  }
343  }
344  return true;
345 }
#define CMP_REG_CHANGE(x, y)
Definition: esil_trace.c:7
RZ_API bool rz_reg_set_value(RzReg *reg, RzRegItem *item, ut64 value)
Definition: rvalue.c:186

References rz_analysis_esil_t::analysis, rz_reg_item_t::arena, c, CMP_REG_CHANGE, setup::idx, len, NULL, rz_reg_item_t::offset, rz_analysis_t::reg, rz_analysis_esil_trace_t::registers, rz_reg_set_value(), rz_vector_index_ptr(), rz_vector_upper_bound, and rz_analysis_esil_t::trace.

Referenced by rz_analysis_esil_trace_restore().

◆ rz_analysis_esil_get_instruction_trace()

RZ_API RZ_BORROW RzILTraceInstruction* rz_analysis_esil_get_instruction_trace ( RZ_NONNULL RzAnalysisEsilTrace etrace,
int  idx 
)

Get instruction trace from ESIL trace by index

Parameters
etraceRzAnalysisEsilTrace *, ESIL trace
idxint, index of instruction
Returns
RzILTraceInstruction *, instruction trace at index

Definition at line 263 of file esil_trace.c.

263  {
264  rz_return_val_if_fail(etrace, NULL);
265  if (idx < 0 || idx >= rz_pvector_len(etrace->instructions)) {
266  return NULL;
267  }
268  return rz_pvector_at(etrace->instructions, idx);
269 }
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
static size_t rz_pvector_len(const RzPVector *vec)
Definition: rz_vector.h:231
static void * rz_pvector_at(const RzPVector *vec, size_t index)
Definition: rz_vector.h:236

References setup::idx, NULL, rz_pvector_at(), rz_pvector_len(), and rz_return_val_if_fail.

Referenced by esil_add_mem_trace(), esil_add_reg_trace(), get_addr(), handle_stack_canary(), propagate_types_among_used_variables(), rz_analysis_esil_trace_show(), and type_match().

◆ rz_analysis_esil_trace_free()

RZ_API void rz_analysis_esil_trace_free ( RzAnalysisEsilTrace trace)

Definition at line 79 of file esil_trace.c.

79  {
80  if (!trace) {
81  return;
82  }
83  size_t i;
84  ht_up_free(trace->registers);
85  ht_up_free(trace->memory);
86  for (i = 0; i < RZ_REG_TYPE_LAST; i++) {
87  rz_reg_arena_free(trace->arena[i]);
88  }
89  free(trace->stack_data);
91  trace->instructions = NULL;
92  RZ_FREE(trace);
93 }
lzma_index ** i
Definition: index.h:629
RZ_API void rz_reg_arena_free(RzRegArena *ra)
Definition: arena.c:189
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
@ RZ_REG_TYPE_LAST
Definition: rz_reg.h:34
#define RZ_FREE(x)
Definition: rz_types.h:369
RZ_API void rz_pvector_free(RzPVector *vec)
Definition: vector.c:336
RzRegArena * arena[RZ_REG_TYPE_LAST]
Definition: rz_analysis.h:1017

References rz_analysis_esil_trace_t::arena, free(), i, rz_analysis_esil_trace_t::instructions, rz_analysis_esil_trace_t::memory, NULL, rz_analysis_esil_trace_t::registers, RZ_FREE, rz_pvector_free(), rz_reg_arena_free(), RZ_REG_TYPE_LAST, and rz_analysis_esil_trace_t::stack_data.

Referenced by analysis_emul_restore(), rz_analysis_esil_free(), rz_analysis_esil_trace_new(), rz_analysis_rzil_trace_new(), and rz_core_analysis_esil_trace_stop().

◆ rz_analysis_esil_trace_list()

RZ_API void rz_analysis_esil_trace_list ( RzAnalysisEsil esil)

List all traces

Parameters
esilRzAnalysisEsil *, ESIL instance

Definition at line 434 of file esil_trace.c.

434  {
435  rz_return_if_fail(esil);
436  if (!esil->trace) {
437  return;
438  }
439 
440  RzILTraceInstruction *instruction_trace;
441  int idx = 0;
442  void **iter;
444  instruction_trace = *iter;
445  print_instruction_trace(instruction_trace, idx);
446  idx++;
447  }
448  rz_cons_printf("idx=%d\n", idx - 1);
449 }
static void print_instruction_trace(RzILTraceInstruction *instruction, int idx)
Definition: esil_trace.c:418
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100

References setup::idx, rz_analysis_esil_trace_t::instructions, print_instruction_trace(), rz_cons_printf(), rz_pvector_foreach, rz_return_if_fail, and rz_analysis_esil_t::trace.

Referenced by rz_cmd_debug_trace_esils_handler().

◆ rz_analysis_esil_trace_new()

RZ_API RzAnalysisEsilTrace* rz_analysis_esil_trace_new ( RzAnalysisEsil esil)

Definition at line 28 of file esil_trace.c.

28  {
29  rz_return_val_if_fail(esil && esil->stack_addr && esil->stack_size, NULL);
30  size_t i;
32  if (!trace) {
33  return NULL;
34  }
35  trace->registers = ht_up_new(NULL, htup_vector_free, NULL);
36  if (!trace->registers) {
37  RZ_LOG_ERROR("esil: Cannot allocate hashmap for trace registers\n");
38  goto error;
39  }
40  trace->memory = ht_up_new(NULL, htup_vector_free, NULL);
41  if (!trace->memory) {
42  RZ_LOG_ERROR("esil: Cannot allocate hashmap for trace memory\n");
43  goto error;
44  }
46  if (!trace->instructions) {
47  RZ_LOG_ERROR("esil: Cannot allocate vector for trace instructions\n");
48  goto error;
49  }
50  // Save initial ESIL stack memory
51  trace->stack_addr = esil->stack_addr;
52  trace->stack_size = esil->stack_size;
53  trace->stack_data = malloc(esil->stack_size);
54  if (!trace->stack_data) {
55  RZ_LOG_ERROR("esil: Cannot allocate stack for trace\n");
56  goto error;
57  }
58  esil->analysis->iob.read_at(esil->analysis->iob.io, trace->stack_addr,
59  trace->stack_data, trace->stack_size);
60  // Save initial registers arenas
61  for (i = 0; i < RZ_REG_TYPE_LAST; i++) {
62  RzRegArena *a = esil->analysis->reg->regset[i].arena;
63  RzRegArena *b = rz_reg_arena_new(a->size);
64  if (!b) {
65  RZ_LOG_ERROR("esil: Cannot allocate register arena for trace\n");
66  goto error;
67  }
68  if (b->bytes && a->bytes && b->size > 0) {
69  memcpy(b->bytes, a->bytes, b->size);
70  }
71  trace->arena[i] = b;
72  }
73  return trace;
74 error:
76  return NULL;
77 }
RZ_API RzRegArena * rz_reg_arena_new(size_t size)
Definition: arena.c:170
static void htup_vector_free(HtUPKv *kv)
Definition: esil_trace.c:24
RZ_API void rz_analysis_esil_trace_free(RzAnalysisEsilTrace *trace)
Definition: esil_trace.c:79
RZ_API void rz_analysis_il_trace_instruction_free(RzILTraceInstruction *instruction)
Definition: il_trace.c:53
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
void * malloc(size_t size)
Definition: malloc.c:123
#define RZ_NEW0(x)
Definition: rz_types.h:284
RZ_API RzPVector * rz_pvector_new(RzPVectorFree free)
Definition: vector.c:302
void(* RzPVectorFree)(void *e)
Definition: rz_vector.h:43
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41
RzIOReadAt read_at
Definition: rz_io.h:240
RzRegArena * arena
Definition: rz_reg.h:136
RzRegSet regset[RZ_REG_TYPE_LAST]
Definition: rz_reg.h:150
void error(const char *msg)
Definition: untgz.c:593

References a, rz_analysis_esil_t::analysis, rz_analysis_esil_trace_t::arena, rz_reg_set_t::arena, b, error(), htup_vector_free(), i, rz_analysis_esil_trace_t::instructions, rz_io_bind_t::io, rz_analysis_t::iob, malloc(), memcpy(), rz_analysis_esil_trace_t::memory, NULL, rz_io_bind_t::read_at, rz_analysis_t::reg, rz_analysis_esil_trace_t::registers, rz_reg_t::regset, rz_analysis_esil_trace_free(), rz_analysis_il_trace_instruction_free(), RZ_LOG_ERROR, RZ_NEW0, rz_pvector_new(), rz_reg_arena_new(), RZ_REG_TYPE_LAST, rz_return_val_if_fail, rz_analysis_esil_trace_t::stack_addr, rz_analysis_esil_t::stack_addr, rz_analysis_esil_trace_t::stack_data, rz_analysis_esil_trace_t::stack_size, and rz_analysis_esil_t::stack_size.

Referenced by analysis_emul_init(), rz_analysis_esil_trace_op(), and rz_core_analysis_esil_trace_start().

◆ rz_analysis_esil_trace_op()

RZ_API void rz_analysis_esil_trace_op ( RzAnalysisEsil esil,
RZ_NONNULL RzAnalysisOp op 
)

Definition at line 271 of file esil_trace.c.

271  {
272  rz_return_if_fail(esil && op);
273  const char *expr = rz_strbuf_get(&op->esil);
274  if (RZ_STR_ISEMPTY(expr)) {
275  // do nothing
276  return;
277  }
278  if (!esil->trace) {
279  esil->trace = rz_analysis_esil_trace_new(esil);
280  if (!esil->trace) {
281  return;
282  }
283  }
284  /* restore from trace when `idx` is not at the end */
285  if (esil->trace->idx != esil->trace->end_idx) {
286  rz_analysis_esil_trace_restore(esil, esil->trace->idx + 1);
287  return;
288  }
289  /* save old callbacks */
290  int esil_verbose = esil->verbose;
291  if (ocbs_set) {
292  RZ_LOG_ERROR("esil: Cannot call recursively\n");
293  }
294  ocbs = esil->cb;
295  ocbs_set = true;
296 
297  RzILTraceInstruction *instruction = rz_analysis_il_trace_instruction_new(op->addr);
299 
300  RzRegItem *pc_ri = rz_reg_get(esil->analysis->reg, "PC", -1);
301  add_reg_change(esil->trace, esil->trace->idx, pc_ri, op->addr);
302  /* set hooks */
303  esil->verbose = 0;
308 
309  /* evaluate esil expression */
312  /* restore hooks */
313  esil->cb = ocbs;
314  ocbs_set = false;
315  esil->verbose = esil_verbose;
316  /* increment idx */
317  esil->trace->idx++;
318  esil->trace->end_idx++;
319 }
static RzNumCalcValue expr(RzNum *, RzNumCalc *, int)
Definition: calc.c:167
RZ_API void rz_analysis_esil_stack_free(RzAnalysisEsil *esil)
Definition: esil.c:3103
RZ_API bool rz_analysis_esil_parse(RzAnalysisEsil *esil, const char *str)
Definition: esil.c:2998
RZ_API RzAnalysisEsilTrace * rz_analysis_esil_trace_new(RzAnalysisEsil *esil)
Definition: esil_trace.c:28
static void add_reg_change(RzAnalysisEsilTrace *trace, int idx, RzRegItem *ri, ut64 data)
Definition: esil_trace.c:95
RZ_API void rz_analysis_esil_trace_restore(RzAnalysisEsil *esil, int idx)
Definition: esil_trace.c:347
static RzAnalysisEsilCallbacks ocbs
Definition: esil_trace.c:11
static int ocbs_set
Definition: esil_trace.c:10
static int trace_hook_reg_read(RzAnalysisEsil *esil, const char *name, ut64 *res, int *size)
Definition: esil_trace.c:124
static int trace_hook_reg_write(RzAnalysisEsil *esil, const char *name, ut64 *val)
Definition: esil_trace.c:156
static int trace_hook_mem_read(RzAnalysisEsil *esil, ut64 addr, ut8 *buf, int len)
Definition: esil_trace.c:183
static int trace_hook_mem_write(RzAnalysisEsil *esil, ut64 addr, const ut8 *buf, int len)
Definition: esil_trace.c:219
RZ_API RzILTraceInstruction * rz_analysis_il_trace_instruction_new(ut64 addr)
Definition: il_trace.c:24
RZ_API RzRegItem * rz_reg_get(RzReg *reg, const char *name, int type)
Definition: reg.c:344
#define RZ_STR_ISEMPTY(x)
Definition: rz_str.h:67
RZ_API char * rz_strbuf_get(RzStrBuf *sb)
Definition: strbuf.c:321
static void ** rz_pvector_push(RzPVector *vec, void *x)
Definition: rz_vector.h:300
int(* hook_mem_read)(ANALYSIS_ESIL *esil, ut64 addr, ut8 *buf, int len)
Definition: rz_analysis.h:1032
int(* hook_reg_read)(ANALYSIS_ESIL *esil, const char *name, ut64 *res, int *size)
Definition: rz_analysis.h:1036
int(* hook_mem_write)(ANALYSIS_ESIL *esil, ut64 addr, const ut8 *buf, int len)
Definition: rz_analysis.h:1034
RzAnalysisEsilHookRegWriteCB hook_reg_write
Definition: rz_analysis.h:1038
RzAnalysisEsilCallbacks cb
Definition: rz_analysis.h:1078

References add_reg_change(), rz_analysis_esil_t::analysis, rz_analysis_esil_t::cb, rz_analysis_esil_trace_t::end_idx, expr(), rz_analysis_esil_callbacks_t::hook_mem_read, rz_analysis_esil_callbacks_t::hook_mem_write, rz_analysis_esil_callbacks_t::hook_reg_read, rz_analysis_esil_callbacks_t::hook_reg_write, rz_analysis_esil_trace_t::idx, rz_analysis_esil_trace_t::instructions, ocbs, ocbs_set, rz_analysis_t::reg, rz_analysis_esil_parse(), rz_analysis_esil_stack_free(), rz_analysis_esil_trace_new(), rz_analysis_esil_trace_restore(), rz_analysis_il_trace_instruction_new(), RZ_LOG_ERROR, rz_pvector_push(), rz_reg_get(), rz_return_if_fail, RZ_STR_ISEMPTY, rz_strbuf_get(), rz_analysis_esil_t::trace, trace_hook_mem_read(), trace_hook_mem_write(), trace_hook_reg_read(), trace_hook_reg_write(), and rz_analysis_esil_t::verbose.

Referenced by rz_cmd_debug_traces_esil_i_handler(), and rz_debug_trace_op().

◆ rz_analysis_esil_trace_restore()

RZ_API void rz_analysis_esil_trace_restore ( RzAnalysisEsil esil,
int  idx 
)

Definition at line 347 of file esil_trace.c.

347  {
348  rz_return_if_fail(esil);
349  size_t i;
350  RzAnalysisEsilTrace *trace = esil->trace;
351  // Restore initial state when going backward
352  if (idx < esil->trace->idx) {
353  // Restore initial registers value
354  for (i = 0; i < RZ_REG_TYPE_LAST; i++) {
355  RzRegArena *a = esil->analysis->reg->regset[i].arena;
356  RzRegArena *b = trace->arena[i];
357  if (a && b) {
358  memcpy(a->bytes, b->bytes, a->size);
359  }
360  }
361  // Restore initial stack memory
362  esil->analysis->iob.write_at(esil->analysis->iob.io, trace->stack_addr,
363  trace->stack_data, trace->stack_size);
364  }
365  // Apply latest changes to registers and memory
366  esil->trace->idx = idx;
367  RzListIter *iter;
368  RzRegItem *ri;
369  rz_list_foreach (esil->analysis->reg->allregs, iter, ri) {
370  restore_register(esil, ri, idx);
371  }
372  ht_up_foreach(trace->memory, restore_memory_cb, esil);
373 }
static bool restore_register(RzAnalysisEsil *esil, RzRegItem *ri, int idx)
Definition: esil_trace.c:334
static bool restore_memory_cb(void *user, const ut64 key, const void *value)
Definition: esil_trace.c:321
RzList * allregs
Definition: rz_reg.h:151

References a, rz_reg_t::allregs, rz_analysis_esil_t::analysis, rz_analysis_esil_trace_t::arena, rz_reg_set_t::arena, b, i, rz_analysis_esil_trace_t::idx, setup::idx, rz_io_bind_t::io, rz_analysis_t::iob, memcpy(), rz_analysis_esil_trace_t::memory, rz_analysis_t::reg, rz_reg_t::regset, restore_memory_cb(), restore_register(), RZ_REG_TYPE_LAST, rz_return_if_fail, rz_analysis_esil_trace_t::stack_addr, rz_analysis_esil_trace_t::stack_data, rz_analysis_esil_trace_t::stack_size, rz_analysis_esil_t::trace, and rz_io_bind_t::write_at.

Referenced by rz_analysis_esil_trace_op(), rz_core_esil_continue_back(), and rz_core_esil_step_back().

◆ rz_analysis_esil_trace_show()

RZ_API void rz_analysis_esil_trace_show ( RzAnalysisEsil esil,
int  idx 
)

Display an ESIL trace at index idx

Parameters
esilRzAnalysisEsil *, ESIL instance
idxint, index of trace

Definition at line 456 of file esil_trace.c.

456  {
457  rz_return_if_fail(esil);
458  if (!esil->trace) {
459  return;
460  }
461 
462  RzILTraceInstruction *instruction = rz_analysis_esil_get_instruction_trace(esil->trace, idx);
463  if (!instruction) {
464  RZ_LOG_ERROR("Invalid trace id : %d\n", idx);
465  return;
466  }
467 
469 }

References setup::idx, print_instruction_trace(), rz_analysis_esil_get_instruction_trace(), RZ_LOG_ERROR, rz_return_if_fail, and rz_analysis_esil_t::trace.

Referenced by rz_cmd_debug_trace_esil_handler().

◆ trace_hook_mem_read()

static int trace_hook_mem_read ( RzAnalysisEsil esil,
ut64  addr,
ut8 buf,
int  len 
)
static

Definition at line 183 of file esil_trace.c.

183  {
184  int ret = 0;
185  if (esil->cb.mem_read) {
186  ret = esil->cb.mem_read(esil, addr, buf, len);
187  }
188 
189  // Trace memory read behavior
190  RzILTraceMemOp *mem_read = RZ_NEW0(RzILTraceMemOp);
191  if (!mem_read) {
192  RZ_LOG_ERROR("fail to init memory read trace\n");
193  return 0;
194  }
195 
196  if (len > sizeof(mem_read->data_buf)) {
197  RZ_LOG_ERROR("read memory more than 32 bytes, cannot trace\n");
198  RZ_FREE(mem_read);
199  return 0;
200  }
201 
202  rz_mem_copy(mem_read->data_buf, sizeof(mem_read->data_buf), buf, len);
203  mem_read->data_len = len;
204  mem_read->behavior = RZ_IL_TRACE_OP_READ;
205  mem_read->addr = addr;
206  if (!esil_add_mem_trace(esil->trace, mem_read)) {
207  RZ_FREE(mem_read);
208  }
209 
210  if (ocbs.hook_mem_read) {
211  RzAnalysisEsilCallbacks cbs = esil->cb;
212  esil->cb = ocbs;
213  ret = ocbs.hook_mem_read(esil, addr, buf, len);
214  esil->cb = cbs;
215  }
216  return ret;
217 }
static int mem_read(struct mem_file *fh, void *buffer, int bytes)
Definition: cabd_memory.c:59
static bool esil_add_mem_trace(RzAnalysisEsilTrace *etrace, RzILTraceMemOp *mem)
Definition: esil_trace.c:14
voidpf void * buf
Definition: ioapi.h:138
RZ_API void * rz_mem_copy(void *dest, size_t dmax, const void *src, size_t smax)
Definition: mem.c:50
int(* mem_read)(ANALYSIS_ESIL *esil, ut64 addr, ut8 *buf, int len)
Definition: rz_analysis.h:1033

References addr, rz_analysis_esil_t::cb, esil_add_mem_trace(), rz_analysis_esil_callbacks_t::hook_mem_read, len, mem_read(), rz_analysis_esil_callbacks_t::mem_read, ocbs, RZ_FREE, RZ_LOG_ERROR, rz_mem_copy(), RZ_NEW0, and rz_analysis_esil_t::trace.

Referenced by rz_analysis_esil_trace_op().

◆ trace_hook_mem_write()

static int trace_hook_mem_write ( RzAnalysisEsil esil,
ut64  addr,
const ut8 buf,
int  len 
)
static

Definition at line 219 of file esil_trace.c.

219  {
220  size_t i;
221  int ret = 0;
222 
223  // Trace memory read behavior
224  RzILTraceMemOp *mem_write = RZ_NEW0(RzILTraceMemOp);
225  if (!mem_write) {
226  RZ_LOG_ERROR("fail to init memory write trace\n");
227  return 0;
228  }
229 
230  if (len > sizeof(mem_write->data_buf)) {
231  RZ_LOG_ERROR("write memory more than 32 bytes, cannot trace\n");
233  return 0;
234  }
235 
236  rz_mem_copy(mem_write->data_buf, sizeof(mem_write->data_buf), buf, len);
237  mem_write->data_len = len;
238  mem_write->behavior = RZ_IL_TRACE_OP_WRITE;
239  mem_write->addr = addr;
240  if (!esil_add_mem_trace(esil->trace, mem_write)) {
242  }
243 
244  for (i = 0; i < len; i++) {
245  add_mem_change(esil->trace, esil->trace->idx + 1, addr + i, buf[i]);
246  }
247 
248  if (ocbs.hook_mem_write) {
249  RzAnalysisEsilCallbacks cbs = esil->cb;
250  esil->cb = ocbs;
251  ret = ocbs.hook_mem_write(esil, addr, buf, len);
252  esil->cb = cbs;
253  }
254  return ret;
255 }
static int mem_write(struct mem_file *fh, void *buffer, int bytes)
Definition: cabd_memory.c:68
static void add_mem_change(RzAnalysisEsilTrace *trace, int idx, ut64 addr, ut8 data)
Definition: esil_trace.c:110

References add_mem_change(), addr, rz_analysis_esil_t::cb, esil_add_mem_trace(), rz_analysis_esil_callbacks_t::hook_mem_write, i, rz_analysis_esil_trace_t::idx, len, mem_write(), ocbs, RZ_FREE, RZ_LOG_ERROR, rz_mem_copy(), RZ_NEW0, and rz_analysis_esil_t::trace.

Referenced by rz_analysis_esil_trace_op().

◆ trace_hook_reg_read()

static int trace_hook_reg_read ( RzAnalysisEsil esil,
const char *  name,
ut64 res,
int size 
)
static

Definition at line 124 of file esil_trace.c.

124  {
125  int ret = 0;
126  if (*name == '0') {
127  // RZ_LOG_WARN("Register not found in profile\n");
128  return 0;
129  }
130  if (ocbs.hook_reg_read) {
131  RzAnalysisEsilCallbacks cbs = esil->cb;
132  esil->cb = ocbs;
133  ret = ocbs.hook_reg_read(esil, name, res, size);
134  esil->cb = cbs;
135  }
136  if (!ret && esil->cb.reg_read) {
137  ret = esil->cb.reg_read(esil, name, res, size);
138  }
139  if (ret) {
140  // Trace reg read behavior
141  RzILTraceRegOp *reg_read = RZ_NEW0(RzILTraceRegOp);
142  if (!reg_read) {
143  RZ_LOG_ERROR("failed to init reg read trace\n");
144  return 0;
145  }
146  reg_read->reg_name = rz_str_constpool_get(&esil->analysis->constpool, name);
147  reg_read->behavior = RZ_IL_TRACE_OP_READ;
148  reg_read->value = *res;
149  if (!esil_add_reg_trace(esil->trace, reg_read)) {
150  RZ_FREE(reg_read);
151  }
152  }
153  return ret;
154 }
static bool esil_add_reg_trace(RzAnalysisEsilTrace *etrace, RzILTraceRegOp *reg)
Definition: esil_trace.c:19
voidpf void uLong size
Definition: ioapi.h:138
RZ_API const char * rz_str_constpool_get(RzStrConstPool *pool, const char *str)
Definition: str_constpool.c:19
Definition: z80asm.h:102
int(* reg_read)(ANALYSIS_ESIL *esil, const char *name, ut64 *res, int *size)
Definition: rz_analysis.h:1037
RzStrConstPool constpool
Definition: rz_analysis.h:620

References rz_analysis_esil_t::analysis, rz_analysis_esil_t::cb, rz_analysis_t::constpool, esil_add_reg_trace(), rz_analysis_esil_callbacks_t::hook_reg_read, ocbs, rz_analysis_esil_callbacks_t::reg_read, RZ_FREE, RZ_LOG_ERROR, RZ_NEW0, rz_str_constpool_get(), and rz_analysis_esil_t::trace.

Referenced by rz_analysis_esil_trace_op().

◆ trace_hook_reg_write()

static int trace_hook_reg_write ( RzAnalysisEsil esil,
const char *  name,
ut64 val 
)
static

Definition at line 156 of file esil_trace.c.

156  {
157  int ret = 0;
158 
159  // add reg write to trace
160  RzILTraceRegOp *reg_write = RZ_NEW0(RzILTraceRegOp);
161  if (!reg_write) {
162  RZ_LOG_ERROR("failed to init reg write\n");
163  return ret;
164  }
165  reg_write->reg_name = rz_str_constpool_get(&esil->analysis->constpool, name);
166  reg_write->behavior = RZ_IL_TRACE_OP_WRITE;
167  reg_write->value = *val;
168  if (!esil_add_reg_trace(esil->trace, reg_write)) {
169  RZ_FREE(reg_write);
170  }
171 
172  RzRegItem *ri = rz_reg_get(esil->analysis->reg, name, -1);
173  add_reg_change(esil->trace, esil->trace->idx + 1, ri, *val);
174  if (ocbs.hook_reg_write) {
175  RzAnalysisEsilCallbacks cbs = esil->cb;
176  esil->cb = ocbs;
177  ret = ocbs.hook_reg_write(esil, name, val);
178  esil->cb = cbs;
179  }
180  return ret;
181 }
ut16 val
Definition: armass64_const.h:6

References add_reg_change(), rz_analysis_esil_t::analysis, rz_analysis_esil_t::cb, rz_analysis_t::constpool, esil_add_reg_trace(), rz_analysis_esil_callbacks_t::hook_reg_write, rz_analysis_esil_trace_t::idx, ocbs, rz_analysis_t::reg, RZ_FREE, RZ_LOG_ERROR, RZ_NEW0, rz_reg_get(), rz_str_constpool_get(), rz_analysis_esil_t::trace, and val.

Referenced by rz_analysis_esil_trace_op().

Variable Documentation

◆ ocbs

◆ ocbs_set

int ocbs_set = false
static

Definition at line 10 of file esil_trace.c.

Referenced by rz_analysis_esil_trace_op().