Rizin
unix-like reverse engineering framework and cli tools
meta.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2008-2020 nibble <nibble.ds@gmail.com>
2 // SPDX-FileCopyrightText: 2008-2020 pancake <pancake@nopcode.org>
3 // SPDX-FileCopyrightText: 2008-2020 thestr4ng3r <info@florianmaerkl.de>
4 // SPDX-License-Identifier: LGPL-3.0-only
5 
6 #include <rz_analysis.h>
7 #include <rz_core.h>
8 
10  return (type == RZ_META_TYPE_ANY || item->type == type) && (!space || item->space == space);
11 }
12 
13 typedef struct {
15  const RzSpace *space;
16 
18 } FindCtx;
19 
20 static bool find_node_cb(RzIntervalNode *node, void *user) {
21  FindCtx *ctx = user;
22  if (item_matches_filter(node->data, ctx->type, ctx->space)) {
23  ctx->node = node;
24  return false;
25  }
26  return true;
27 }
28 
30  FindCtx ctx = {
31  .type = type,
32  .space = space,
33  .node = NULL
34  };
36  return ctx.node;
37 }
38 
40  FindCtx ctx = {
41  .type = type,
42  .space = space,
43  .node = NULL
44  };
45  rz_interval_tree_all_in(&analysis->meta, addr, true, find_node_cb, &ctx);
46  return ctx.node;
47 }
48 
49 typedef struct {
51  const RzSpace *space;
52 
53  RzPVector /*RzIntervalNode*/ *result;
54 } CollectCtx;
55 
56 static bool collect_nodes_cb(RzIntervalNode *node, void *user) {
57  CollectCtx *ctx = user;
58  if (item_matches_filter(node->data, ctx->type, ctx->space)) {
59  rz_pvector_push(ctx->result, node);
60  }
61  return true;
62 }
63 
65  CollectCtx ctx = {
66  .type = type,
67  .space = space,
68  .result = rz_pvector_new(NULL)
69  };
70  if (!ctx.result) {
71  return NULL;
72  }
74  return ctx.result;
75 }
76 
78  CollectCtx ctx = {
79  .type = type,
80  .space = space,
81  .result = rz_pvector_new(NULL)
82  };
83  if (!ctx.result) {
84  return NULL;
85  }
87  return ctx.result;
88 }
89 
91  CollectCtx ctx = {
92  .type = type,
93  .space = space,
94  .result = rz_pvector_new(NULL)
95  };
96  if (!ctx.result) {
97  return NULL;
98  }
100  return ctx.result;
101 }
102 
103 static inline bool is_string_with_zeroes(RzAnalysisMetaType type, int subtype) {
104  return type == RZ_META_TYPE_STRING && subtype != RZ_STRING_ENC_8BIT && subtype != RZ_STRING_ENC_UTF8;
105 }
106 
107 static bool meta_set(RzAnalysis *a, RzAnalysisMetaType type, int subtype, ut64 from, ut64 to, const char *str) {
108  if (to < from) {
109  return false;
110  }
111  RzSpace *space = rz_spaces_current(&a->meta_spaces);
112  RzIntervalNode *node = find_node_at(a, type, space, from);
113  RzAnalysisMetaItem *item = node ? node->data : RZ_NEW0(RzAnalysisMetaItem);
114  if (!item) {
115  return false;
116  }
117  item->type = type;
118  item->subtype = subtype;
119  item->space = space;
120  item->size = to - from + 1;
121  free(item->str);
122  if (is_string_with_zeroes(type, subtype)) {
123  item->str = str ? rz_str_ndup(str, item->size) : NULL;
124  } else {
125  item->str = str ? strdup(str) : NULL;
126  }
127  if (str && !item->str) {
128  if (!node) { // If we just created this
129  free(item);
130  }
131  return false;
132  }
133  if (!node) {
134  rz_interval_tree_insert(&a->meta, from, to, item);
135  } else if (node->end != to) {
136  rz_interval_tree_resize(&a->meta, node, from, to);
137  }
138  return true;
139 }
140 
142  // By default all strings are UTF-8
143  return meta_set(a, type, RZ_STRING_ENC_UTF8, addr, addr, s);
144 }
145 
147  RzIntervalNode *node = find_node_at(a, type, rz_spaces_current(&a->meta_spaces), addr);
148  if (!node) {
149  return NULL;
150  }
151  RzAnalysisMetaItem *item = node->data;
152  return item->str;
153 }
154 
155 static void del(RzAnalysis *a, RzAnalysisMetaType type, const RzSpace *space, ut64 addr, ut64 size) {
156  RzPVector *victims = NULL;
157  if (size == UT64_MAX) {
158  // delete everything
159  victims = rz_pvector_new(NULL);
160  if (!victims) {
161  return;
162  }
164  RzAnalysisMetaItem *item;
165  rz_interval_tree_foreach (&a->meta, it, item) {
166  if (item_matches_filter(item, type, space)) {
168  }
169  }
170  } else {
171  ut64 end = size ? addr + size - 1 : addr;
172  if (end < addr) {
173  end = UT64_MAX;
174  }
175  victims = collect_nodes_intersect(a, type, space, addr, end);
176  if (!victims) {
177  return;
178  }
179  }
180  void **it;
181  rz_pvector_foreach (victims, it) {
182  rz_interval_tree_delete(&a->meta, *it, true);
183  }
184  rz_pvector_free(victims);
185 }
186 
188  del(a, type, rz_spaces_current(&a->meta_spaces), addr, size);
189 }
190 
192  return rz_meta_set_with_subtype(a, type, 0, addr, size, str);
193 }
194 
196  rz_return_val_if_fail(m, false);
197  if (size < 1) {
198  return false;
199  }
200  ut64 end = addr + size - 1;
201  if (end < addr) {
202  end = UT64_MAX;
203  }
204  return meta_set(m, type, subtype, addr, end, str);
205 }
206 
208  RzIntervalNode *node = find_node_at(a, type, rz_spaces_current(&a->meta_spaces), addr);
209  if (node && size) {
210  *size = rz_meta_item_size(node->start, node->end);
211  }
212  return node ? node->data : NULL;
213 }
214 
216  return find_node_in(a, type, rz_spaces_current(&a->meta_spaces), addr);
217 }
218 
219 RZ_API RzPVector /*<RzIntervalNode<RMetaItem> *>*/ *rz_meta_get_all_at(RzAnalysis *a, ut64 at) {
220  return collect_nodes_at(a, RZ_META_TYPE_ANY, rz_spaces_current(&a->meta_spaces), at);
221 }
222 
223 RZ_API RzPVector /*<RzIntervalNode<RMetaItem> *>*/ *rz_meta_get_all_in(RzAnalysis *a, ut64 at, RzAnalysisMetaType type) {
224  return collect_nodes_in(a, type, rz_spaces_current(&a->meta_spaces), at);
225 }
226 
229  ut64 end = start + size - 1;
230  if (end < start) {
231  end = UT64_MAX;
232  }
233  return collect_nodes_intersect(a, type, rz_spaces_current(&a->meta_spaces), start, end);
234 }
235 
237  switch (type) {
238  case RZ_META_TYPE_DATA: return "Cd";
239  case RZ_META_TYPE_CODE: return "Cc";
240  case RZ_META_TYPE_STRING: return "Cs";
241  case RZ_META_TYPE_FORMAT: return "Cf";
242  case RZ_META_TYPE_MAGIC: return "Cm";
243  case RZ_META_TYPE_HIDE: return "Ch";
244  case RZ_META_TYPE_COMMENT: return "CCu";
245  case RZ_META_TYPE_HIGHLIGHT: return "ecHi"; // not in C?
246  case RZ_META_TYPE_VARTYPE: return "Ct";
247  }
248  return "# unknown meta # ";
249 }
250 
251 RZ_API void rz_meta_rebase(RzAnalysis *analysis, ut64 diff) {
252  if (!diff) {
253  return;
254  }
255  RzIntervalTree old = analysis->meta;
256  rz_interval_tree_init(&analysis->meta, old.free);
258  RzAnalysisMetaItem *item;
259  rz_interval_tree_foreach (&old, it, item) {
261  ut64 newstart = node->start + diff;
262  ut64 newend = node->end + diff;
263  if (newend < newstart) {
264  // Can't rebase this
265  newstart = node->start;
266  newend = node->end;
267  }
268  rz_interval_tree_insert(&analysis->meta, newstart, newend, item);
269  }
270  old.free = NULL;
271  rz_interval_tree_fini(&old);
272 }
273 
275  del(a, RZ_META_TYPE_ANY, space, 0, UT64_MAX);
276 }
277 
279  ut64 sum = 0;
281  RzAnalysisMetaItem *item;
282  RzIntervalNode *prev = NULL;
283  rz_interval_tree_foreach (&a->meta, it, item) {
285  if (type != RZ_META_TYPE_ANY && item->type != type) {
286  continue;
287  }
288  ut64 start = RZ_MAX(prev ? prev->end : 0, node->start);
289  sum += node->end - start + 1;
290  prev = node;
291  }
292  return sum;
293 }
294 
296  int r = 0;
298  RzAnalysisMetaItem *item;
299  rz_interval_tree_foreach (&a->meta, it, item) {
300  if (item->space == space) {
301  r++;
302  }
303  }
304  return r;
305 }
306 
308  rz_return_if_fail(wordsz);
310 }
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
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 static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void start
Definition: sflib.h:133
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
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_API void rz_meta_set_data_at(RzAnalysis *a, ut64 addr, ut64 wordsz)
Definition: meta.c:307
RZ_API bool rz_meta_set_with_subtype(RzAnalysis *m, RzAnalysisMetaType type, int subtype, ut64 addr, ut64 size, const char *str)
Definition: meta.c:195
static RzPVector * collect_nodes_in(RzAnalysis *analysis, RzAnalysisMetaType type, RZ_NULLABLE const RzSpace *space, ut64 addr)
Definition: meta.c:77
RZ_API void rz_meta_space_unset_for(RzAnalysis *a, const RzSpace *space)
Definition: meta.c:274
static bool is_string_with_zeroes(RzAnalysisMetaType type, int subtype)
Definition: meta.c:103
RZ_API const char * rz_meta_get_string(RzAnalysis *a, RzAnalysisMetaType type, ut64 addr)
Definition: meta.c:146
RZ_API const char * rz_meta_type_to_string(int type)
Definition: meta.c:236
static bool item_matches_filter(RzAnalysisMetaItem *item, RzAnalysisMetaType type, RZ_NULLABLE const RzSpace *space)
Definition: meta.c:9
RZ_API ut64 rz_meta_get_size(RzAnalysis *a, RzAnalysisMetaType type)
Definition: meta.c:278
RZ_API void rz_meta_del(RzAnalysis *a, RzAnalysisMetaType type, ut64 addr, ut64 size)
Definition: meta.c:187
static RzPVector * collect_nodes_at(RzAnalysis *analysis, RzAnalysisMetaType type, RZ_NULLABLE const RzSpace *space, ut64 addr)
Definition: meta.c:64
static bool collect_nodes_cb(RzIntervalNode *node, void *user)
Definition: meta.c:56
RZ_API bool rz_meta_set_string(RzAnalysis *a, RzAnalysisMetaType type, ut64 addr, const char *s)
Definition: meta.c:141
RZ_API int rz_meta_space_count_for(RzAnalysis *a, const RzSpace *space)
Definition: meta.c:295
RZ_API RzPVector * rz_meta_get_all_intersect(RzAnalysis *a, ut64 start, ut64 size, RzAnalysisMetaType type)
Definition: meta.c:227
static RzIntervalNode * find_node_in(RzAnalysis *analysis, RzAnalysisMetaType type, RZ_NULLABLE const RzSpace *space, ut64 addr)
Definition: meta.c:39
static RzPVector * collect_nodes_intersect(RzAnalysis *analysis, RzAnalysisMetaType type, RZ_NULLABLE const RzSpace *space, ut64 start, ut64 end)
Definition: meta.c:90
static bool find_node_cb(RzIntervalNode *node, void *user)
Definition: meta.c:20
RZ_API void rz_meta_rebase(RzAnalysis *analysis, ut64 diff)
Definition: meta.c:251
RZ_API RzPVector * rz_meta_get_all_at(RzAnalysis *a, ut64 at)
Definition: meta.c:219
static RzIntervalNode * find_node_at(RzAnalysis *analysis, RzAnalysisMetaType type, RZ_NULLABLE const RzSpace *space, ut64 addr)
Definition: meta.c:29
RZ_API bool rz_meta_set(RzAnalysis *a, RzAnalysisMetaType type, ut64 addr, ut64 size, const char *str)
Definition: meta.c:191
RZ_API RzPVector * rz_meta_get_all_in(RzAnalysis *a, ut64 at, RzAnalysisMetaType type)
Definition: meta.c:223
static bool meta_set(RzAnalysis *a, RzAnalysisMetaType type, int subtype, ut64 from, ut64 to, const char *str)
Definition: meta.c:107
RZ_API RzAnalysisMetaItem * rz_meta_get_at(RzAnalysis *a, ut64 addr, RzAnalysisMetaType type, RZ_OUT RZ_NULLABLE ut64 *size)
Definition: meta.c:207
static void del(RzAnalysis *a, RzAnalysisMetaType type, const RzSpace *space, ut64 addr, ut64 size)
Definition: meta.c:155
RZ_API RzIntervalNode * rz_meta_get_in(RzAnalysis *a, ut64 addr, RzAnalysisMetaType type)
Definition: meta.c:215
int type
Definition: mipsasm.c:17
static RzSocket * s
Definition: rtr.c:28
RzAnalysisMetaType
Definition: rz_analysis.h:287
@ RZ_META_TYPE_VARTYPE
Definition: rz_analysis.h:297
@ RZ_META_TYPE_ANY
Definition: rz_analysis.h:288
@ RZ_META_TYPE_DATA
Definition: rz_analysis.h:289
@ RZ_META_TYPE_CODE
Definition: rz_analysis.h:290
@ RZ_META_TYPE_HIGHLIGHT
Definition: rz_analysis.h:296
@ RZ_META_TYPE_HIDE
Definition: rz_analysis.h:294
@ RZ_META_TYPE_MAGIC
Definition: rz_analysis.h:293
@ RZ_META_TYPE_STRING
Definition: rz_analysis.h:291
@ RZ_META_TYPE_COMMENT
Definition: rz_analysis.h:295
@ RZ_META_TYPE_FORMAT
Definition: rz_analysis.h:292
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_API bool rz_interval_tree_all_intersect(RzIntervalTree *tree, ut64 start, ut64 end, bool end_inclusive, RzIntervalIterCb cb, void *user)
Definition: intervaltree.c:291
RZ_API bool rz_interval_tree_delete(RzIntervalTree *tree, RzIntervalNode *node, bool free)
Definition: intervaltree.c:139
RZ_API bool rz_interval_tree_all_in(RzIntervalTree *tree, ut64 value, bool end_inclusive, RzIntervalIterCb cb, void *user)
Definition: intervaltree.c:262
RZ_API bool rz_interval_tree_resize(RzIntervalTree *tree, RzIntervalNode *node, ut64 new_start, ut64 new_end)
Definition: intervaltree.c:147
RZ_API bool rz_interval_tree_all_at(RzIntervalTree *tree, ut64 start, RzIntervalIterCb cb, void *user)
Definition: intervaltree.c:221
RZ_API void rz_interval_tree_init(RzIntervalTree *tree, RzIntervalNodeFree free)
Definition: intervaltree.c:101
static RzIntervalNode * rz_interval_tree_iter_get(RzIntervalTreeIter *it)
RZ_API bool rz_interval_tree_insert(RzIntervalTree *tree, ut64 start, ut64 end, void *data)
Definition: intervaltree.c:121
#define rz_interval_tree_foreach(tree, it, dat)
RZ_API void rz_interval_tree_fini(RzIntervalTree *tree)
Definition: intervaltree.c:114
static RzSpace * rz_spaces_current(RzSpaces *sp)
Definition: rz_spaces.h:91
RZ_API char * rz_str_ndup(RZ_NULLABLE const char *ptr, int len)
Create new copy of string ptr limited to size len.
Definition: str.c:1006
@ RZ_STRING_ENC_8BIT
Definition: rz_str.h:20
@ RZ_STRING_ENC_UTF8
Definition: rz_str.h:21
#define RZ_NULLABLE
Definition: rz_types.h:65
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_OUT
Definition: rz_types.h:51
#define RZ_MAX(x, y)
#define UT64_MAX
Definition: rz_types_base.h:86
RZ_API RzPVector * rz_pvector_new(RzPVectorFree free)
Definition: vector.c:302
static void ** rz_pvector_push(RzPVector *vec, void *x)
Definition: rz_vector.h:300
RZ_API void rz_pvector_free(RzPVector *vec)
Definition: vector.c:336
#define rz_pvector_foreach(vec, it)
Definition: rz_vector.h:334
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 a(i)
Definition: sha256.c:41
const RzSpace * space
Definition: meta.c:51
RzPVector * result
Definition: meta.c:53
RzAnalysisMetaType type
Definition: meta.c:50
Definition: meta.c:13
const RzSpace * space
Definition: meta.c:15
RzAnalysisMetaType type
Definition: meta.c:14
RzIntervalNode * node
Definition: meta.c:17
const RzSpace * space
Definition: rz_analysis.h:306
RzAnalysisMetaType type
Definition: rz_analysis.h:302
RzIntervalTree meta
Definition: rz_analysis.h:600
RzIntervalNodeFree free
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58