Rizin
unix-like reverse engineering framework and cli tools
cmp.c File Reference
#include <rz_cmp.h>
#include <rz_asm.h>
#include <rz_list.h>

Go to the source code of this file.

Functions

RZ_API RZ_OWN RzCompareDatarz_core_cmp_mem_mem (RzCore *core, ut64 addr1, ut64 addr2, ut32 len)
 Compare memory at addr1 with the memory at addr2. More...
 
RZ_API RZ_OWN RzCompareDatarz_core_cmp_mem_data (RzCore *core, ut64 addr, RZ_NONNULL const ut8 *data, ut32 len)
 Compare mem at addr with data data. More...
 
RZ_API int rz_core_cmp_print (RzCore *core, RZ_NONNULL const RzCompareData *cmp, RzCmdStateOutput *state)
 Print a comparison cmp according to the print mode mode. More...
 
RZ_API RZ_OWN RzListrz_core_cmp_disasm (RzCore *core, ut64 addr1, ut64 addr2, ut32 len)
 Compare the instructions at addr1 and addr2. More...
 
RZ_API void rz_core_cmp_free (RzCompareData *cmp)
 Free RzCompareData object. More...
 
RZ_API bool rz_core_cmp_disasm_print (RzCore *core, const RzList *compare, bool unified)
 Print the instruction comparison data compare. More...
 
RZ_API void rz_core_cmpwatch_free (RzCoreCmpWatcher *w)
 
RZ_API RzCoreCmpWatcherrz_core_cmpwatch_get (RzCore *core, ut64 addr)
 Get the memory watcher at address addr. More...
 
RZ_API bool rz_core_cmpwatch_add (RzCore *core, ut64 addr, int size, const char *cmd)
 Add a memory watcher at address addr od size size and command cmd. More...
 
RZ_API bool rz_core_cmpwatch_del (RzCore *core, ut64 addr)
 Delete a memory watcher at address addr. More...
 
RZ_API void rz_core_cmpwatch_show (RzCore *core, ut64 addr, RzOutputMode mode)
 Show/print the memory watcher present at address addr. More...
 
RZ_API bool rz_core_cmpwatch_update (RzCore *core, ut64 addr)
 Update the memory watcher at address addr. More...
 
RZ_API bool rz_core_cmpwatch_revert (RzCore *core, ut64 addr)
 Revert/reset a memory watcher at address addr. More...
 

Function Documentation

◆ rz_core_cmp_disasm()

RZ_API RZ_OWN RzList* rz_core_cmp_disasm ( RzCore core,
ut64  addr1,
ut64  addr2,
ut32  len 
)

Compare the instructions at addr1 and addr2.

Parameters
coreCurrent RzCore instance
addr1address to read instructions from
addr2address to read instructions from
lennumber of bytes to read instructions from
Returns
RzList<RzCompareData>* List of comparison data

Definition at line 161 of file cmp.c.

161  {
163 
164  RzList *cmp_list = rz_list_new();
165  if (!cmp_list) {
166  goto error_goto;
167  }
168  cmp_list->free = (RzListFree)&rz_core_cmp_free;
169  RzAsmOp op, op2;
170  int i, j;
171  ut8 *buf = calloc(len + 32, 1);
172  if (!buf) {
173  goto error_goto;
174  }
175  rz_io_nread_at(core->io, addr2, buf, len + 32);
176  RzCompareData *comp;
177 
178  for (i = j = 0; i < len && j < len;) {
179  comp = RZ_NEW0(RzCompareData);
180  if (!comp) {
181  continue;
182  }
183 
184  // dis A
185  rz_asm_set_pc(core->rasm, addr1 + i);
186  (void)rz_asm_disassemble(core->rasm, &op,
187  core->block + i, len - i);
188 
189  // dis B
190  rz_asm_set_pc(core->rasm, addr2 + i);
191  (void)rz_asm_disassemble(core->rasm, &op2,
192  buf + j, len - j);
193 
194  comp->len = UT8_MAX;
195  comp->data1 = (ut8 *)strdup(rz_strbuf_get(&op.buf_asm));
196  comp->addr1 = addr1 + i;
197  comp->data2 = (ut8 *)strdup(rz_strbuf_get(&op2.buf_asm));
198  comp->addr2 = addr2 + j;
199  comp->same = !strcmp((char *)comp->data1, (char *)comp->data2); // we can assume that instructions can be represented as plain chars
200  rz_list_append(cmp_list, comp);
201 
202  if (op.size < 1) {
203  op.size = 1;
204  }
205  i += op.size;
206  if (op2.size < 1) {
207  op2.size = 1;
208  }
209  j += op2.size;
210  }
211 
212  free(buf);
213  return cmp_list;
214 
215 error_goto:
216  rz_list_free(cmp_list);
217  return NULL;
218 }
size_t len
Definition: 6502dis.c:15
ut8 op
Definition: 6502dis.c:13
lzma_index ** i
Definition: index.h:629
RZ_API int rz_asm_set_pc(RzAsm *a, ut64 pc)
Definition: asm.c:533
RZ_API int rz_asm_disassemble(RzAsm *a, RzAsmOp *op, const ut8 *buf, int len)
Definition: asm.c:543
RZ_API void rz_core_cmp_free(RzCompareData *cmp)
Free RzCompareData object.
Definition: cmp.c:226
#define NULL
Definition: cris-opc.c:27
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
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 void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
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")
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_API int rz_io_nread_at(RzIO *io, ut64 addr, ut8 *buf, int len)
Definition: io.c:338
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
RZ_API char * rz_strbuf_get(RzStrBuf *sb)
Definition: strbuf.c:321
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define UT8_MAX
ut64 addr2
Definition: rz_cmp.h:20
ut32 len
Definition: rz_cmp.h:15
bool same
Definition: rz_cmp.h:16
ut64 addr1
Definition: rz_cmp.h:19
ut8 * data1
Definition: rz_cmp.h:17
ut8 * data2
Definition: rz_cmp.h:18
RzStrBuf buf_asm
Definition: rz_asm.h:72
int size
Definition: rz_asm.h:67
RzAsm * rasm
Definition: rz_core.h:323
RzIO * io
Definition: rz_core.h:313
ut8 * block
Definition: rz_core.h:305
RzListFree free
Definition: rz_list.h:21
Definition: dis.c:32

References RzCompareData::addr1, RzCompareData::addr2, rz_core_t::block, rz_asm_op_t::buf_asm, calloc(), RzCompareData::data1, RzCompareData::data2, rz_list_t::free, free(), i, rz_core_t::io, len, RzCompareData::len, NULL, op, rz_core_t::rasm, rz_asm_disassemble(), rz_asm_set_pc(), rz_core_cmp_free(), rz_io_nread_at(), rz_list_append(), rz_list_free(), rz_list_new(), RZ_NEW0, rz_return_val_if_fail, rz_strbuf_get(), RzCompareData::same, rz_asm_op_t::size, strdup(), and UT8_MAX.

Referenced by rz_cmd_cmp_disasm_handler(), and rz_cmd_cmp_unified_disasm_handler().

◆ rz_core_cmp_disasm_print()

RZ_API bool rz_core_cmp_disasm_print ( RzCore core,
const RzList compare,
bool  unified 
)

Print the instruction comparison data compare.

Parameters
coreCurrent RzCore instance
comparelist of RzCompareData of instructions
unifiedprint in unified form
Returns
bool true if successfull

Definition at line 243 of file cmp.c.

243  {
244  rz_return_val_if_fail(core && compare, false);
245  char colpad[80];
246  int hascolor = rz_config_get_i(core->config, "scr.color");
247  int cols = rz_config_get_i(core->config, "hex.cols") * 2;
249  RzListIter *it;
251 
252  if (unified) {
253  rz_list_foreach (compare, it, cmp) {
254  if (cmp->same) {
255  rz_cons_printf(" 0x%08" PFMT64x " %s\n",
256  cmp->addr1, cmp->data1);
257  } else {
258  if (hascolor) {
259  rz_cons_print(pal->graph_false);
260  }
261  rz_cons_printf("-0x%08" PFMT64x " %s\n",
262  cmp->addr1, cmp->data1);
263  if (hascolor) {
264  rz_cons_print(pal->graph_true);
265  }
266  rz_cons_printf("+0x%08" PFMT64x " %s\n",
267  cmp->addr2, cmp->data2);
268  if (hascolor) {
269  rz_cons_print(Color_RESET);
270  }
271  }
272  }
273  } else {
274  rz_list_foreach (compare, it, cmp) {
275  memset(colpad, ' ', sizeof(colpad));
276  int pos = strlen((char *)cmp->data1);
277  pos = (pos > cols) ? 0 : cols - pos;
278  colpad[pos] = 0;
279  if (hascolor) {
280  rz_cons_print(cmp->same ? pal->graph_true : pal->graph_false);
281  }
282  rz_cons_printf(" 0x%08" PFMT64x " %s %s",
283  cmp->addr1, cmp->data1, colpad);
284  rz_cons_printf("%c 0x%08" PFMT64x " %s\n",
285  cmp->same ? '=' : '!', cmp->addr2, cmp->data2);
286  if (hascolor) {
287  rz_cons_print(Color_RESET);
288  }
289  }
290  }
291 
292  return true;
293 }
static RzILOpEffect * cmp(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:942
RZ_API ut64 rz_config_get_i(RzConfig *cfg, RZ_NONNULL const char *name)
Definition: config.c:119
RZ_API RzCons * rz_cons_singleton(void)
Definition: cons.c:300
RZ_API int rz_cons_printf(const char *format,...)
Definition: cons.c:1202
return memset(p, 0, total)
static int compare(const char *s1, const char *s2, int l1, int l2)
Definition: chmd.c:864
#define Color_RESET
Definition: rz_cons.h:617
#define PFMT64x
Definition: rz_types.h:393
RzConsPrintablePalette pal
Definition: rz_cons.h:491
RzConsContext * context
Definition: rz_cons.h:502
RzConfig * config
Definition: rz_core.h:300
int pos
Definition: main.c:11

References cmp(), Color_RESET, compare(), rz_core_t::config, rz_cons_t::context, rz_cons_printable_palette_t::graph_false, rz_cons_printable_palette_t::graph_true, memset(), rz_cons_context_t::pal, PFMT64x, pos, rz_config_get_i(), rz_cons_printf(), rz_cons_singleton(), and rz_return_val_if_fail.

Referenced by rz_cmd_cmp_disasm_handler(), and rz_cmd_cmp_unified_disasm_handler().

◆ rz_core_cmp_free()

RZ_API void rz_core_cmp_free ( RzCompareData cmp)

Free RzCompareData object.

Parameters
cmpRzCompareData object to be freed
Returns
void

Definition at line 226 of file cmp.c.

226  {
227  if (!cmp) {
228  return;
229  }
230  RZ_FREE(cmp->data1);
231  RZ_FREE(cmp->data2);
232  free(cmp);
233 }
#define RZ_FREE(x)
Definition: rz_types.h:369

References cmp(), free(), and RZ_FREE.

Referenced by rz_cmd_cmp_addr_handler(), rz_cmd_cmp_bits_handler(), rz_cmd_cmp_bytes_handler(), rz_cmd_cmp_file_handler(), rz_cmd_cmp_hex_block_hexdiff_handler(), rz_cmd_cmp_hexpair_string_handler(), rz_cmd_cmp_string_handler(), rz_cmd_cmp_unified_handler(), and rz_core_cmp_disasm().

◆ rz_core_cmp_mem_data()

RZ_API RZ_OWN RzCompareData* rz_core_cmp_mem_data ( RzCore core,
ut64  addr,
RZ_NONNULL const ut8 data,
ut32  len 
)

Compare mem at addr with data data.

Parameters
coreCurrent RzCore instance
addraddress to read data from
dataData to be compared
lenNumber of bytes to compare
Returns
RzCompareData* A pointer to RzCompareData comparison (the data1 corresponds to the data at addr (and addr1 = addr) and data2 is the str data (and addr2 = UT32_MAX))

Definition at line 56 of file cmp.c.

56  {
57  rz_return_val_if_fail(core && data, NULL);
58 
59  ut8 *buf1 = malloc(len * sizeof(ut8));
60  if (!buf1) {
61  RZ_LOG_ERROR("Cannot read at address: 0x%" PFMT64x "\n", addr);
62  goto error_goto;
63  }
64  if (rz_io_nread_at(core->io, addr, buf1, len) != len) {
65  RZ_LOG_ERROR("Cannot read %u bytes at provided address: 0x%" PFMT64x "\n", len, addr);
66  goto error_goto;
67  }
69  if (!cmp) {
70  goto error_goto;
71  }
72  cmp->len = len;
73  cmp->data1 = buf1;
74  cmp->addr1 = addr;
75  cmp->data2 = rz_mem_dup(data, len);
76  cmp->addr2 = UT64_MAX;
77  cmp->same = rz_mem_eq(cmp->data1, cmp->data2, len);
78  return cmp;
79 
80 error_goto:
81  free(buf1);
82  return NULL;
83 }
void * malloc(size_t size)
Definition: malloc.c:123
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API void * rz_mem_dup(const void *s, int l)
Definition: mem.c:319
RZ_API int rz_mem_eq(const ut8 *a, const ut8 *b, int len)
Compares memory a with b over len bytes.
Definition: mem.c:31
#define UT64_MAX
Definition: rz_types_base.h:86
static int addr
Definition: z80asm.c:58

References addr, cmp(), free(), rz_core_t::io, len, malloc(), NULL, PFMT64x, rz_io_nread_at(), RZ_LOG_ERROR, rz_mem_dup(), rz_mem_eq(), RZ_NEW0, rz_return_val_if_fail, and UT64_MAX.

Referenced by rz_cmd_cmp_bytes_handler(), rz_cmd_cmp_file_handler(), rz_cmd_cmp_hex_block_hexdiff_handler(), rz_cmd_cmp_hexpair_string_handler(), and rz_cmd_cmp_string_handler().

◆ rz_core_cmp_mem_mem()

RZ_API RZ_OWN RzCompareData* rz_core_cmp_mem_mem ( RzCore core,
ut64  addr1,
ut64  addr2,
ut32  len 
)

Compare memory at addr1 with the memory at addr2.

Parameters
coreCurrent RzCore instance
addr1address to read data from
addr2address to read data from
lenNumber of bytes to compare
Returns
RzCompareData* A pointer to RzCompareData comparison

Definition at line 17 of file cmp.c.

17  {
19 
20  ut8 *buf1 = malloc(len * sizeof(ut8));
21  ut8 *buf2 = malloc(len * sizeof(ut8));
22  if (!buf1 || !buf2) {
23  goto error_goto;
24  }
25  if (!(rz_io_nread_at(core->io, addr1, buf1, len) == len && rz_io_nread_at(core->io, addr2, buf2, len) == len)) {
26  RZ_LOG_ERROR("Cannot read %u bytes at provided addresses: 0x%" PFMT64x " 0x%" PFMT64x "\n", len, addr1, addr2);
27  goto error_goto;
28  }
30  if (!cmp) {
31  goto error_goto;
32  }
33  cmp->len = len;
34  cmp->data1 = buf1;
35  cmp->addr1 = addr1;
36  cmp->data2 = buf2;
37  cmp->addr2 = addr2;
38  cmp->same = rz_mem_eq(cmp->data1, cmp->data2, len);
39  return cmp;
40 
41 error_goto:
42  free(buf1);
43  free(buf2);
44  return NULL;
45 }
static uint32_t const uint8_t * buf2
Definition: memcmplen.h:43

References buf2, cmp(), free(), rz_core_t::io, len, malloc(), NULL, PFMT64x, rz_io_nread_at(), RZ_LOG_ERROR, rz_mem_eq(), RZ_NEW0, and rz_return_val_if_fail.

Referenced by rz_cmd_cmp_addr_handler(), rz_cmd_cmp_bits_handler(), and rz_cmd_cmp_unified_handler().

◆ rz_core_cmp_print()

RZ_API int rz_core_cmp_print ( RzCore core,
RZ_NONNULL const RzCompareData cmp,
RzCmdStateOutput state 
)

Print a comparison cmp according to the print mode mode.

Parameters
coreCurrent RzCore instance
cmpRzCompareData instance to be printed
stateRzCmdStateOutput to be used (options: standard, json) (NULL means standard)
Returns
int Number of lines/diffs printed (-1 if failed)

Definition at line 93 of file cmp.c.

93  {
94  rz_return_val_if_fail(core && cmp, -1);
95 
96  int i, eq = 0;
97  bool data_str = cmp->addr2 == UT64_MAX;
98  if (cmp->len == UT8_MAX) {
99  return -1;
100  }
102  PJ *pj = NULL;
103  if (state) {
104  mode = state->mode;
105  pj = state->d.pj;
106  }
107  if (mode == RZ_OUTPUT_MODE_JSON) {
108  pj_o(pj);
109  pj_k(pj, "diff_bytes");
110  pj_a(pj);
111  }
112  for (i = 0; i < cmp->len; i++) {
113  if (cmp->data1[i] == cmp->data2[i]) {
114  eq++;
115  continue;
116  }
117  switch (mode) {
119  rz_cons_printf("0x%08" PFMT64x, cmp->addr1 + i);
120  if (!data_str) {
121  rz_cons_printf(" -> 0x%08" PFMT64x, cmp->addr2 + i);
122  }
123  rz_cons_printf(" (byte=%.2d) %02x '%c' -> %02x '%c'\n", i + 1,
124  cmp->data1[i], (IS_PRINTABLE(cmp->data1[i])) ? cmp->data1[i] : ' ',
125  cmp->data2[i], (IS_PRINTABLE(cmp->data2[i])) ? cmp->data2[i] : ' ');
126  break;
127  case RZ_OUTPUT_MODE_JSON:
128  pj_o(pj);
129  pj_kn(pj, "offset1", cmp->addr1 + i);
130  pj_kn(pj, "offset2", data_str ? i : cmp->addr2 + i);
131  pj_ki(pj, "rel_offset", i);
132  pj_ki(pj, "value1", (int)cmp->data1[i]);
133  pj_ki(pj, "value2", (int)cmp->data2[i]);
134  pj_end(pj);
135  break;
136  default:
138  }
139  }
140  if (mode == RZ_OUTPUT_MODE_STANDARD) {
141  rz_cons_printf("Compare %d/%d equal bytes (%d%%)\n", eq, cmp->len, (int)(100.0 * eq / cmp->len));
142  } else if (mode == RZ_OUTPUT_MODE_JSON) {
143  pj_end(pj);
144  pj_ki(pj, "equal_bytes", eq);
145  pj_ki(pj, "total_bytes", cmp->len);
146  pj_end(pj); // End array
147  pj_end(pj); // End object
148  }
149  return cmp->len - eq;
150 }
const char int mode
Definition: ioapi.h:137
#define rz_warn_if_reached()
Definition: rz_assert.h:29
RZ_API PJ * pj_ki(PJ *j, const char *k, int d)
Definition: pj.c:149
RZ_API PJ * pj_k(PJ *j, const char *k)
Definition: pj.c:104
RZ_API PJ * pj_end(PJ *j)
Definition: pj.c:87
RZ_API PJ * pj_o(PJ *j)
Definition: pj.c:75
RZ_API PJ * pj_kn(PJ *j, const char *k, ut64 n)
Definition: pj.c:121
RZ_API PJ * pj_a(PJ *j)
Definition: pj.c:81
#define IS_PRINTABLE(x)
Definition: rz_str_util.h:10
RzOutputMode
Enum to describe the way data are printed.
Definition: rz_types.h:38
@ RZ_OUTPUT_MODE_JSON
Definition: rz_types.h:40
@ RZ_OUTPUT_MODE_STANDARD
Definition: rz_types.h:39
Definition: rz_pj.h:12
Definition: dis.h:43

References cmp(), eq, i, IS_PRINTABLE, NULL, PFMT64x, pj_a(), pj_end(), pj_k(), pj_ki(), pj_kn(), pj_o(), rz_cons_printf(), RZ_OUTPUT_MODE_JSON, RZ_OUTPUT_MODE_STANDARD, rz_return_val_if_fail, rz_warn_if_reached, UT64_MAX, and UT8_MAX.

Referenced by rz_cmd_cmp_addr_handler(), rz_cmd_cmp_bytes_handler(), rz_cmd_cmp_file_handler(), rz_cmd_cmp_hex_block_hexdiff_handler(), rz_cmd_cmp_hexpair_string_handler(), and rz_cmd_cmp_string_handler().