Rizin
unix-like reverse engineering framework and cli tools
xrefs.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2009-2019 pancake <pancake@nopcode.org>
2 // SPDX-FileCopyrightText: 2009-2019 nibble <nibble.ds@gmail.com>
3 // SPDX-FileCopyrightText: 2009-2019 defragger <rlaemmert@gmail.com>
4 // SPDX-FileCopyrightText: 2009-2019 ret2libc <sirmy15@gmail.com>
5 // SPDX-License-Identifier: LGPL-3.0-only
6 
7 #include <rz_analysis.h>
8 #include <rz_cons.h>
9 
10 #if 0
11 DICT
12 ====
13 
14 refs 10->20 C 16->10 J 20->10 C
15 
16  xrefs 20->[10 C] 10 -> [16 J, 20 C]
17 
18  10 : call 20 16 : jmp 10 20 : call 10
19 #endif
20 
21 // XXX: is it possible to have multiple type for the same (from, to) pair?
22 // if it is, things need to be adjusted
23 
26  if (xref) {
27  xref->from = from;
28  xref->to = to;
29  xref->type = (type == -1) ? RZ_ANALYSIS_XREF_TYPE_CODE : type;
30  }
31  return xref;
32 }
33 
35  free(xref);
36 }
37 
38 RZ_API RzList /*<RzAnalysisXRef *>*/ *rz_analysis_xref_list_new() {
39  return rz_list_newf((RzListFree)free);
40 }
41 
42 static void xrefs_ht_free(HtUPKv *kv) {
43  ht_up_free(kv->value);
44 }
45 
46 static void xrefs_ref_free(HtUPKv *kv) {
47  rz_analysis_xref_free(kv->value);
48 }
49 
50 static bool appendRef(void *u, const ut64 k, const void *v) {
51  RzList *list = (RzList *)u;
52  RzAnalysisXRef *xref = (RzAnalysisXRef *)v;
53  RzAnalysisXRef *cloned = rz_analysis_xref_new(xref->from, xref->to, xref->type);
54  if (cloned) {
55  rz_list_append(list, cloned);
56  return true;
57  }
58  return false;
59 }
60 
61 static bool mylistrefs_cb(void *list, const ut64 k, const void *v) {
62  HtUP *ht = (HtUP *)v;
63  ht_up_foreach(ht, appendRef, list);
64  return true;
65 }
66 
67 static int ref_cmp(const RzAnalysisXRef *a, const RzAnalysisXRef *b) {
68  if (a->from < b->from) {
69  return -1;
70  }
71  if (a->from > b->from) {
72  return 1;
73  }
74  if (a->to < b->to) {
75  return -1;
76  }
77  if (a->to > b->to) {
78  return 1;
79  }
80  return 0;
81 }
82 
83 static void sortxrefs(RzList *list) {
85 }
86 
87 static void listxrefs(HtUP *m, ut64 addr, RzList *list) {
88  if (addr == UT64_MAX) {
89  ht_up_foreach(m, mylistrefs_cb, list);
90  } else {
91  HtUP *d = ht_up_find(m, addr, NULL);
92  if (d) {
93  ht_up_foreach(d, appendRef, list);
94  }
95  }
96 }
97 
98 static bool set_xref(HtUP *m, RzAnalysisXRef *xref, bool from2to) {
99  ut64 key1 = from2to ? xref->from : xref->to;
100  HtUP *ht = ht_up_find(m, key1, NULL);
101  if (!ht) {
102  // RzAnalysis::ht_xrefs_to is responsible for releasing of pointers.
103  HtUPKvFreeFunc cb = from2to ? NULL : xrefs_ref_free;
104  ht = ht_up_new(NULL, cb, NULL);
105  if (!ht) {
106  return false;
107  }
108  if (!ht_up_insert(m, key1, ht)) {
109  return false;
110  }
111  }
112  ut64 key2 = from2to ? xref->to : xref->from;
113  return ht_up_update(ht, key2, xref);
114 }
115 
116 // Set a cross reference from FROM to TO.
118  if (!analysis || from == to) {
119  return false;
120  }
121  if (analysis->iob.is_valid_offset) {
122  if (!analysis->iob.is_valid_offset(analysis->iob.io, from, 0)) {
123  return false;
124  }
125  if (!analysis->iob.is_valid_offset(analysis->iob.io, to, 0)) {
126  return false;
127  }
128  }
130  if (!xref) {
131  return false;
132  }
133  if (!set_xref(analysis->ht_xrefs_from, xref, true)) {
134  // Pointer isn't added to <ht_xrefs_from> so we have to release it
135  rz_analysis_xref_free(xref);
136  return false;
137  }
138  if (!set_xref(analysis->ht_xrefs_to, xref, false)) {
139  // Delete the entry in <ht_xrefs_from>
140  rz_analysis_xrefs_deln(analysis, from, to, type);
141  // Pointer isn't added to <ht_xrefs_to> so we have to release it
142  rz_analysis_xref_free(xref);
143  return false;
144  }
145  return true;
146 }
147 
149  if (!analysis) {
150  return false;
151  }
152  HtUP *ht1 = ht_up_find(analysis->ht_xrefs_from, from, NULL);
153  if (ht1) {
154  ht_up_delete(ht1, to);
155  }
156  HtUP *ht2 = ht_up_find(analysis->ht_xrefs_to, to, NULL);
157  if (ht2) {
158  ht_up_delete(ht2, from);
159  }
160  return true;
161 }
162 
164  bool res = false;
170  return res;
171 }
172 
173 RZ_API RzList /*<RzAnalysisXRef *>*/ *rz_analysis_xrefs_get_to(RzAnalysis *analysis, ut64 addr) {
175  if (!list) {
176  return NULL;
177  }
178  listxrefs(analysis->ht_xrefs_to, addr, list);
179  sortxrefs(list);
180  if (rz_list_empty(list)) {
182  list = NULL;
183  }
184  return list;
185 }
186 
187 RZ_API RzList /*<RzAnalysisXRef *>*/ *rz_analysis_xrefs_get_from(RzAnalysis *analysis, ut64 addr) {
189  if (!list) {
190  return NULL;
191  }
192  listxrefs(analysis->ht_xrefs_from, addr, list);
193  sortxrefs(list);
194  if (rz_list_empty(list)) {
196  list = NULL;
197  }
198  return list;
199 }
200 
206 RZ_API RZ_OWN RzList /*<RzAnalysisXRef *>*/ *rz_analysis_xrefs_list(RzAnalysis *analysis) {
207  rz_return_val_if_fail(analysis, NULL);
209  if (list) {
210  listxrefs(analysis->ht_xrefs_from, UT64_MAX, list);
211  sortxrefs(list);
212  }
213  return list;
214 }
215 
217  switch (type) {
219  return "CODE";
221  return "CALL";
223  return "DATA";
225  return "STRING";
227  default:
228  return "UNKNOWN";
229  }
230 }
231 
233  switch (ch) {
239  return (RzAnalysisXRefType)ch;
240  default:
242  }
243 }
244 
246  ht_up_free(analysis->ht_xrefs_from);
247  analysis->ht_xrefs_from = NULL;
248  ht_up_free(analysis->ht_xrefs_to);
249  analysis->ht_xrefs_to = NULL;
250 
251  HtUP *tmp = ht_up_new(NULL, xrefs_ht_free, NULL);
252  if (!tmp) {
253  return false;
254  }
255  analysis->ht_xrefs_from = tmp;
256 
257  tmp = ht_up_new(NULL, xrefs_ht_free, NULL);
258  if (!tmp) {
259  ht_up_free(analysis->ht_xrefs_from);
260  analysis->ht_xrefs_from = NULL;
261  return false;
262  }
263  analysis->ht_xrefs_to = tmp;
264  return true;
265 }
266 
267 static bool count_cb(void *user, const ut64 k, const void *v) {
268  (*(ut64 *)user) += ((HtUP *)v)->count;
269  return true;
270 }
271 
273  ut64 ret = 0;
274  ht_up_foreach(analysis->ht_xrefs_to, count_cb, &ret);
275  return ret;
276 }
277 
278 static RzList *fcn_get_refs(RzAnalysisFunction *fcn, HtUP *ht) {
279  RzListIter *iter;
280  RzAnalysisBlock *bb;
282  if (!list) {
283  return NULL;
284  }
285  rz_list_foreach (fcn->bbs, iter, bb) {
286  int i;
287 
288  for (i = 0; i < bb->ninstr; i++) {
289  ut64 at = bb->addr + rz_analysis_block_get_op_offset(bb, i);
290  listxrefs(ht, at, list);
291  }
292  }
293  sortxrefs(list);
294  return list;
295 }
296 
299  return fcn_get_refs(fcn, fcn->analysis->ht_xrefs_from);
300 }
301 
304  return fcn_get_refs(fcn, fcn->analysis->ht_xrefs_to);
305 }
306 
308  switch (t) {
310  return "null";
312  return "code";
314  return "call";
316  return "data";
318  return "string";
319  }
320  return "unknown";
321 }
#define jmp
lzma_index ** i
Definition: index.h:629
#define C(x)
Definition: arc.h:167
int call(int a, int b)
Definition: bcj_test.c:25
RZ_API ut16 rz_analysis_block_get_op_offset(RzAnalysisBlock *block, size_t i)
Definition: block.c:1006
#define RZ_API
#define NULL
Definition: cris-opc.c:27
const char * k
Definition: dsignal.c:11
const char * v
Definition: dsignal.c:12
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
@ DICT
Definition: inflate.h:31
static void list(RzEgg *egg)
Definition: rz-gg.c:52
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
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 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
int type
Definition: mipsasm.c:17
#define J
Definition: rsp_idec.c:366
RzAnalysisXRefType
Definition: rz_analysis.h:898
@ RZ_ANALYSIS_XREF_TYPE_CODE
Definition: rz_analysis.h:900
@ RZ_ANALYSIS_XREF_TYPE_NULL
Definition: rz_analysis.h:899
@ RZ_ANALYSIS_XREF_TYPE_STRING
Definition: rz_analysis.h:903
@ RZ_ANALYSIS_XREF_TYPE_CALL
Definition: rz_analysis.h:901
@ RZ_ANALYSIS_XREF_TYPE_DATA
Definition: rz_analysis.h:902
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
int(* RzListComparator)(const void *value, const void *list_data)
Definition: rz_list.h:33
#define RZ_OWN
Definition: rz_types.h:62
#define RZ_NEW(x)
Definition: rz_types.h:285
#define UT64_MAX
Definition: rz_types_base.h:86
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr from
Definition: sfsocketcall.h:123
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr socklen_t static fromlen const void const struct sockaddr to
Definition: sfsocketcall.h:125
#define d(i)
Definition: sha256.c:44
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41
struct rz_analysis_t * analysis
Definition: rz_analysis.h:267
RzAnalysisXRefType type
Definition: rz_analysis.h:909
HtUP * ht_xrefs_to
Definition: rz_analysis.h:592
HtUP * ht_xrefs_from
Definition: rz_analysis.h:591
RzIOBind iob
Definition: rz_analysis.h:574
RzIOIsValidOff is_valid_offset
Definition: rz_io.h:257
RzIO * io
Definition: rz_io.h:232
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int ref_cmp(const RzAnalysisXRef *a, const RzAnalysisXRef *b)
Definition: xrefs.c:67
static bool set_xref(HtUP *m, RzAnalysisXRef *xref, bool from2to)
Definition: xrefs.c:98
RZ_API RZ_OWN RzList * rz_analysis_xrefs_list(RzAnalysis *analysis)
Get list of all xrefs.
Definition: xrefs.c:206
static bool count_cb(void *user, const ut64 k, const void *v)
Definition: xrefs.c:267
RZ_API RzList * rz_analysis_xref_list_new()
Definition: xrefs.c:38
RZ_API RzList * rz_analysis_xrefs_get_from(RzAnalysis *analysis, ut64 addr)
Definition: xrefs.c:187
RZ_API RzList * rz_analysis_xrefs_get_to(RzAnalysis *analysis, ut64 addr)
Definition: xrefs.c:173
static RzAnalysisXRef * rz_analysis_xref_new(ut64 from, ut64 to, ut64 type)
Definition: xrefs.c:24
static RzList * fcn_get_refs(RzAnalysisFunction *fcn, HtUP *ht)
Definition: xrefs.c:278
RZ_API RzList * rz_analysis_function_get_xrefs_to(RzAnalysisFunction *fcn)
Definition: xrefs.c:302
RZ_API ut64 rz_analysis_xrefs_count(RzAnalysis *analysis)
Definition: xrefs.c:272
RZ_API const char * rz_analysis_ref_type_tostring(RzAnalysisXRefType t)
Definition: xrefs.c:307
static void listxrefs(HtUP *m, ut64 addr, RzList *list)
Definition: xrefs.c:87
RZ_API bool rz_analysis_xrefs_init(RzAnalysis *analysis)
Definition: xrefs.c:245
static void xrefs_ref_free(HtUPKv *kv)
Definition: xrefs.c:46
RZ_API const char * rz_analysis_xrefs_type_tostring(RzAnalysisXRefType type)
Definition: xrefs.c:216
static void xrefs_ht_free(HtUPKv *kv)
Definition: xrefs.c:42
RZ_API bool rz_analysis_xrefs_set(RzAnalysis *analysis, ut64 from, ut64 to, RzAnalysisXRefType type)
Definition: xrefs.c:117
static void rz_analysis_xref_free(RzAnalysisXRef *xref)
Definition: xrefs.c:34
static bool mylistrefs_cb(void *list, const ut64 k, const void *v)
Definition: xrefs.c:61
static void sortxrefs(RzList *list)
Definition: xrefs.c:83
RZ_API bool rz_analysis_xrefs_deln(RzAnalysis *analysis, ut64 from, ut64 to, RzAnalysisXRefType type)
Definition: xrefs.c:148
RZ_API bool rz_analysis_xref_del(RzAnalysis *analysis, ut64 from, ut64 to)
Definition: xrefs.c:163
static bool appendRef(void *u, const ut64 k, const void *v)
Definition: xrefs.c:50
RZ_API RzList * rz_analysis_function_get_xrefs_from(RzAnalysisFunction *fcn)
Definition: xrefs.c:297
RZ_API RzAnalysisXRefType rz_analysis_xrefs_type(char ch)
Definition: xrefs.c:232
static const char * cb[]
Definition: z80_tab.h:176
static int addr
Definition: z80asm.c:58