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

Go to the source code of this file.

Functions

RZ_API RZ_OWN RzAnalysisDiffrz_analysis_diff_new (void)
 
RZ_API void rz_analysis_diff_free (RzAnalysisDiff *diff)
 
RZ_API void rz_analysis_diff_setup (RzAnalysis *analysis, int doops, double thbb, double thfcn)
 
RZ_API void rz_analysis_diff_setup_i (RzAnalysis *analysis, int doops, int thbb, int thfcn)
 
RZ_API int rz_analysis_diff_fingerprint_bb (RzAnalysis *analysis, RzAnalysisBlock *bb)
 
RZ_API size_t rz_analysis_diff_fingerprint_fcn (RzAnalysis *analysis, RzAnalysisFunction *fcn)
 
RZ_API bool rz_analysis_diff_bb (RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisFunction *fcn2)
 
RZ_API int rz_analysis_diff_fcn (RzAnalysis *analysis, RzList *fcns1, RzList *fcns2)
 
RZ_API int rz_analysis_diff_eval (RzAnalysis *analysis)
 

Function Documentation

◆ rz_analysis_diff_bb()

RZ_API bool rz_analysis_diff_bb ( RzAnalysis analysis,
RzAnalysisFunction fcn,
RzAnalysisFunction fcn2 
)

Definition at line 112 of file diff.c.

112  {
113  RzAnalysisBlock *bb, *bb2, *mbb, *mbb2;
114  RzListIter *iter, *iter2;
115  double t, ot;
116 
117  if (!analysis || !fcn || !fcn2) {
118  return false;
119  }
120  if (analysis->cur && analysis->cur->diff_bb) {
121  return (analysis->cur->diff_bb(analysis, fcn, fcn2));
122  }
123  fcn->diff->type = fcn2->diff->type = RZ_ANALYSIS_DIFF_TYPE_MATCH;
124  rz_list_foreach (fcn->bbs, iter, bb) {
125  if (bb->diff && bb->diff->type != RZ_ANALYSIS_DIFF_TYPE_NULL) {
126  continue;
127  }
128  ot = 0;
129  mbb = mbb2 = NULL;
130  rz_list_foreach (fcn2->bbs, iter2, bb2) {
131  if (!bb2->diff || bb2->diff->type == RZ_ANALYSIS_DIFF_TYPE_NULL) {
133  if (t > analysis->diff_thbb && t > ot) {
134  ot = t;
135  mbb = bb;
136  mbb2 = bb2;
137  if (t == 1) {
138  break;
139  }
140  }
141  }
142  }
143  if (mbb && mbb2) {
144  if (!mbb->diff) {
145  mbb->diff = rz_analysis_diff_new();
146  }
147  if (!mbb2->diff) {
148  mbb2->diff = rz_analysis_diff_new();
149  }
150  if (!mbb->diff || !mbb2->diff) {
151  return false;
152  }
153  if (ot == 1 || t > analysis->diff_thfcn) {
154  mbb->diff->type = mbb2->diff->type = RZ_ANALYSIS_DIFF_TYPE_MATCH;
155  } else {
156  mbb->diff->type = mbb2->diff->type =
157  fcn->diff->type = fcn2->diff->type =
159  }
160  mbb->diff->dist = mbb2->diff->dist = ot;
161  RZ_FREE(mbb->fingerprint);
162  RZ_FREE(mbb2->fingerprint);
163  mbb->diff->addr = mbb2->addr;
164  mbb2->diff->addr = mbb->addr;
165  mbb->diff->size = mbb2->size;
166  mbb2->diff->size = mbb->size;
167  } else {
168  fcn->diff->type = fcn2->diff->type = (fcn->diff->dist >= RZ_ANALYSIS_DIFF_THRESHOLD)
171  }
172  }
173  return true;
174 }
RZ_API RZ_OWN RzAnalysisDiff * rz_analysis_diff_new(void)
Definition: diff.c:9
#define NULL
Definition: cris-opc.c:27
RZ_API bool rz_diff_levenstein_distance(RZ_NONNULL const ut8 *a, ut32 la, RZ_NONNULL const ut8 *b, ut32 lb, RZ_NULLABLE ut32 *distance, RZ_NULLABLE double *similarity)
Calculates the distance between two buffers using the Levenshtein algorithm.
Definition: distance.c:68
#define RZ_ANALYSIS_DIFF_THRESHOLD
Definition: rz_analysis.h:202
@ RZ_ANALYSIS_DIFF_TYPE_MATCH
Definition: rz_analysis.h:206
@ RZ_ANALYSIS_DIFF_TYPE_UNMATCH
Definition: rz_analysis.h:207
@ RZ_ANALYSIS_DIFF_TYPE_NULL
Definition: rz_analysis.h:205
#define RZ_FREE(x)
Definition: rz_types.h:369
RzAnalysisDiff * diff
Definition: rz_analysis.h:872
RzAnalysisDiff * diff
Definition: rz_analysis.h:263
RzAnalysisDiffBBCallback diff_bb
Definition: rz_analysis.h:1262
double diff_thfcn
Definition: rz_analysis.h:573
struct rz_analysis_plugin_t * cur
Definition: rz_analysis.h:586
double diff_thbb
Definition: rz_analysis.h:572

References rz_analysis_diff_t::addr, rz_analysis_bb_t::addr, rz_analysis_function_t::bbs, rz_analysis_t::cur, rz_analysis_function_t::diff, rz_analysis_bb_t::diff, rz_analysis_plugin_t::diff_bb, rz_analysis_t::diff_thbb, rz_analysis_t::diff_thfcn, rz_analysis_diff_t::dist, rz_analysis_bb_t::fingerprint, NULL, rz_analysis_diff_new(), RZ_ANALYSIS_DIFF_THRESHOLD, RZ_ANALYSIS_DIFF_TYPE_MATCH, RZ_ANALYSIS_DIFF_TYPE_NULL, RZ_ANALYSIS_DIFF_TYPE_UNMATCH, rz_diff_levenstein_distance(), RZ_FREE, rz_analysis_diff_t::size, rz_analysis_bb_t::size, and rz_analysis_diff_t::type.

Referenced by rz_analysis_diff_fcn().

◆ rz_analysis_diff_eval()

RZ_API int rz_analysis_diff_eval ( RzAnalysis analysis)

Definition at line 283 of file diff.c.

283  {
284  if (analysis && analysis->cur && analysis->cur->diff_eval) {
285  return (analysis->cur->diff_eval(analysis));
286  }
287  return true; // XXX: shouldn't this be false?
288 }
RzAnalysisDiffEvalCallback diff_eval
Definition: rz_analysis.h:1264

References rz_analysis_t::cur, and rz_analysis_plugin_t::diff_eval.

◆ rz_analysis_diff_fcn()

RZ_API int rz_analysis_diff_fcn ( RzAnalysis analysis,
RzList fcns1,
RzList fcns2 
)

Definition at line 176 of file diff.c.

176  {
177  RzAnalysisFunction *fcn, *fcn2, *mfcn, *mfcn2;
178  RzListIter *iter, *iter2;
179  double t, ot, sizes_div;
180 
181  if (!analysis) {
182  return false;
183  }
184  if (analysis->cur && analysis->cur->diff_fcn) {
185  return (analysis->cur->diff_fcn(analysis, fcns1, fcns2));
186  }
187  /* Compare functions with the same name */
188  rz_list_foreach (fcns1, iter, fcn) {
189  rz_list_foreach (fcns2, iter2, fcn2) {
190  if (fcn->name && fcn2->name && strcmp(fcn->name, fcn2->name)) {
191  continue;
192  }
194  fcn2->fingerprint, fcn2->fingerprint_size, NULL, &t);
195  /* Set flag in matched functions */
196  fcn->diff->type = fcn2->diff->type = (t >= RZ_ANALYSIS_DIFF_THRESHOLD)
199  fcn->diff->dist = fcn2->diff->dist = t;
200  RZ_FREE(fcn->fingerprint);
201  RZ_FREE(fcn2->fingerprint);
202  fcn->diff->addr = fcn2->addr;
203  fcn2->diff->addr = fcn->addr;
204  fcn->diff->size = fcn2->fingerprint_size;
205  fcn2->diff->size = fcn->fingerprint_size;
206  RZ_FREE(fcn->diff->name);
207  if (fcn2->name) {
208  fcn->diff->name = strdup(fcn2->name);
209  }
210  RZ_FREE(fcn2->diff->name);
211  if (fcn->name) {
212  fcn2->diff->name = strdup(fcn->name);
213  }
214  rz_analysis_diff_bb(analysis, fcn, fcn2);
215  break;
216  }
217  }
218  /* Compare remaining functions */
219  rz_list_foreach (fcns1, iter, fcn) {
220  if (fcn->diff->type != RZ_ANALYSIS_DIFF_TYPE_NULL) {
221  continue;
222  } else if (!fcn->fingerprint_size) {
223  continue;
224  } else if (fcn->type != RZ_ANALYSIS_FCN_TYPE_FCN && fcn->type != RZ_ANALYSIS_FCN_TYPE_SYM) {
225  continue;
226  }
227  ot = 0.0;
228  mfcn = mfcn2 = NULL;
229  rz_list_foreach (fcns2, iter2, fcn2) {
230  if (fcn2->diff->type != RZ_ANALYSIS_DIFF_TYPE_NULL) {
231  continue;
232  } else if (!fcn2->fingerprint_size) {
233  continue;
234  } else if (fcn2->type != RZ_ANALYSIS_FCN_TYPE_FCN && fcn2->type != RZ_ANALYSIS_FCN_TYPE_SYM) {
235  continue;
236  }
237  if (fcn->fingerprint_size > fcn2->fingerprint_size) {
238  sizes_div = fcn2->fingerprint_size;
239  sizes_div /= fcn->fingerprint_size;
240  } else {
241  sizes_div = fcn->fingerprint_size;
242  sizes_div /= fcn2->fingerprint_size;
243  }
244  if (sizes_div < RZ_ANALYSIS_DIFF_THRESHOLD) {
245  continue;
246  }
248  if (t > ot) {
249  ot = t;
250  mfcn = fcn;
251  mfcn2 = fcn2;
252  if (ot >= RZ_ANALYSIS_DIFF_THRESHOLD) {
253  break;
254  }
255  }
256  }
257  if (mfcn && mfcn2) {
258  mfcn->diff->dist = mfcn2->diff->dist = ot;
259  /* Set flag in matched functions */
260  mfcn->diff->type = mfcn2->diff->type = (ot > RZ_ANALYSIS_DIFF_THRESHOLD)
263  RZ_FREE(mfcn->fingerprint);
264  RZ_FREE(mfcn2->fingerprint);
265  mfcn->diff->addr = mfcn2->addr;
266  mfcn2->diff->addr = mfcn->addr;
267  mfcn->diff->size = mfcn2->fingerprint_size;
268  mfcn2->diff->size = mfcn->fingerprint_size;
269  RZ_FREE(mfcn->diff->name);
270  if (mfcn2->name) {
271  mfcn->diff->name = strdup(mfcn2->name);
272  }
273  RZ_FREE(mfcn2->diff->name);
274  if (mfcn->name) {
275  mfcn2->diff->name = strdup(mfcn->name);
276  }
277  rz_analysis_diff_bb(analysis, mfcn, mfcn2);
278  }
279  }
280  return true;
281 }
RZ_API bool rz_analysis_diff_bb(RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisFunction *fcn2)
Definition: diff.c:112
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")
@ RZ_ANALYSIS_FCN_TYPE_SYM
Definition: rz_analysis.h:195
@ RZ_ANALYSIS_FCN_TYPE_FCN
Definition: rz_analysis.h:193
RzAnalysisDiffFcnCallback diff_fcn
Definition: rz_analysis.h:1263

References rz_analysis_diff_t::addr, rz_analysis_function_t::addr, rz_analysis_t::cur, rz_analysis_function_t::diff, rz_analysis_plugin_t::diff_fcn, rz_analysis_diff_t::dist, rz_analysis_function_t::fingerprint, rz_analysis_function_t::fingerprint_size, rz_analysis_diff_t::name, rz_analysis_function_t::name, NULL, rz_analysis_diff_bb(), RZ_ANALYSIS_DIFF_THRESHOLD, RZ_ANALYSIS_DIFF_TYPE_MATCH, RZ_ANALYSIS_DIFF_TYPE_NULL, RZ_ANALYSIS_DIFF_TYPE_UNMATCH, RZ_ANALYSIS_FCN_TYPE_FCN, RZ_ANALYSIS_FCN_TYPE_SYM, rz_diff_levenstein_distance(), RZ_FREE, rz_analysis_diff_t::size, strdup(), rz_analysis_diff_t::type, and rz_analysis_function_t::type.

Referenced by rz_core_gdiff_2_files(), rz_core_gdiff_function_1_file(), and rz_core_gdiff_function_2_files().

◆ rz_analysis_diff_fingerprint_bb()

RZ_API int rz_analysis_diff_fingerprint_bb ( RzAnalysis analysis,
RzAnalysisBlock bb 
)

Definition at line 49 of file diff.c.

49  {
51  ut8 *buf;
52  int oplen, idx = 0;
53 
54  if (!analysis) {
55  return -1;
56  }
57  if (analysis->cur && analysis->cur->fingerprint_bb) {
58  return (analysis->cur->fingerprint_bb(analysis, bb));
59  }
60  if (!(bb->fingerprint = malloc(1 + bb->size))) {
61  return -1;
62  }
63  if (!(buf = malloc(bb->size + 1))) {
64  free(bb->fingerprint);
65  return -1;
66  }
67  if (analysis->iob.read_at(analysis->iob.io, bb->addr, buf, bb->size)) {
68  memcpy(bb->fingerprint, buf, bb->size);
69  if (analysis->diff_ops) { // diff using only the opcode
70  if (!(op = rz_analysis_op_new())) {
71  free(bb->fingerprint);
72  free(buf);
73  return -1;
74  }
75  while (idx < bb->size) {
76  if ((oplen = rz_analysis_op(analysis, op, 0, buf + idx, bb->size - idx, RZ_ANALYSIS_OP_MASK_BASIC)) < 1) {
77  break;
78  }
79  if (op->nopcode != 0) {
80  memset(bb->fingerprint + idx + op->nopcode, 0, oplen - op->nopcode);
81  }
82  idx += oplen;
83  }
84  free(op);
85  }
86  }
87  free(buf);
88  return bb->size;
89 }
ut8 op
Definition: 6502dis.c:13
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
void * malloc(size_t size)
Definition: malloc.c:123
int idx
Definition: setup.py:197
RZ_API RzAnalysisOp * rz_analysis_op_new(void)
Definition: op.c:9
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_BASIC
Definition: rz_analysis.h:440
RzAnalysisFPBBCallback fingerprint_bb
Definition: rz_analysis.h:1260
RzIOBind iob
Definition: rz_analysis.h:574
RzIOReadAt read_at
Definition: rz_io.h:240
RzIO * io
Definition: rz_io.h:232
Definition: dis.c:32

References rz_analysis_bb_t::addr, rz_analysis_t::cur, rz_analysis_t::diff_ops, rz_analysis_bb_t::fingerprint, rz_analysis_plugin_t::fingerprint_bb, free(), setup::idx, rz_io_bind_t::io, rz_analysis_t::iob, malloc(), memcpy(), memset(), op, rz_io_bind_t::read_at, rz_analysis_op(), RZ_ANALYSIS_OP_MASK_BASIC, rz_analysis_op_new(), and rz_analysis_bb_t::size.

Referenced by rz_core_gdiff_2_files(), rz_core_gdiff_function_1_file(), and rz_core_gdiff_function_2_files().

◆ rz_analysis_diff_fingerprint_fcn()

RZ_API size_t rz_analysis_diff_fingerprint_fcn ( RzAnalysis analysis,
RzAnalysisFunction fcn 
)

Definition at line 91 of file diff.c.

91  {
92  RzAnalysisBlock *bb;
94 
95  if (analysis && analysis->cur && analysis->cur->fingerprint_fcn) {
96  return (analysis->cur->fingerprint_fcn(analysis, fcn));
97  }
98 
99  fcn->fingerprint = NULL;
100  fcn->fingerprint_size = 0;
101  rz_list_foreach (fcn->bbs, iter, bb) {
102  fcn->fingerprint_size += bb->size;
103  fcn->fingerprint = realloc(fcn->fingerprint, fcn->fingerprint_size + 1);
104  if (!fcn->fingerprint) {
105  return 0;
106  }
107  memcpy(fcn->fingerprint + fcn->fingerprint_size - bb->size, bb->fingerprint, bb->size);
108  }
109  return fcn->fingerprint_size;
110 }
void * realloc(void *ptr, size_t size)
Definition: malloc.c:144
RzAnalysisFPFcnCallback fingerprint_fcn
Definition: rz_analysis.h:1261

References rz_analysis_function_t::bbs, rz_analysis_t::cur, rz_analysis_function_t::fingerprint, rz_analysis_bb_t::fingerprint, rz_analysis_plugin_t::fingerprint_fcn, rz_analysis_function_t::fingerprint_size, memcpy(), NULL, realloc(), and rz_analysis_bb_t::size.

Referenced by rz_core_gdiff_2_files(), and rz_core_gdiff_function_2_files().

◆ rz_analysis_diff_free()

RZ_API void rz_analysis_diff_free ( RzAnalysisDiff diff)

Definition at line 22 of file diff.c.

22  {
23  if (!diff) {
24  return;
25  }
26  free(diff->name);
27  free(diff);
28 }

References free(), and rz_analysis_diff_t::name.

Referenced by block_free(), function_load_cb(), rz_analysis_function_blocks_add_handler(), rz_analysis_function_create_handler(), and rz_analysis_function_free().

◆ rz_analysis_diff_new()

◆ rz_analysis_diff_setup()

RZ_API void rz_analysis_diff_setup ( RzAnalysis analysis,
int  doops,
double  thbb,
double  thfcn 
)

Definition at line 31 of file diff.c.

31  {
32  if (doops >= 0) {
33  analysis->diff_ops = doops;
34  }
35  analysis->diff_thbb = (thbb >= 0) ? thbb : RZ_ANALYSIS_THRESHOLDBB;
36  analysis->diff_thfcn = (thfcn >= 0) ? thfcn : RZ_ANALYSIS_THRESHOLDFCN;
37 }

References rz_analysis_t::diff_ops, rz_analysis_t::diff_thbb, and rz_analysis_t::diff_thfcn.

◆ rz_analysis_diff_setup_i()

RZ_API void rz_analysis_diff_setup_i ( RzAnalysis analysis,
int  doops,
int  thbb,
int  thfcn 
)

Definition at line 40 of file diff.c.

40  {
41  if (doops >= 0) {
42  analysis->diff_ops = doops;
43  }
44  analysis->diff_thbb = (thbb >= 0) ? ((double)thbb) / 100 : RZ_ANALYSIS_THRESHOLDBB;
45  analysis->diff_thfcn = (thfcn >= 0) ? ((double)thfcn) / 100 : RZ_ANALYSIS_THRESHOLDFCN;
46 }

References rz_analysis_t::diff_ops, rz_analysis_t::diff_thbb, and rz_analysis_t::diff_thfcn.