1 /* radare - LGPL - Copyright 2013-2020 - pancake */
2 
3 #include <r_anal.h>
4 
5 // Common base-struct for hints which affect an entire range as opposed to only one single address
6 // They are saved in a RBTree per hint type.
7 // Each ranged record in a tree affects every address address greater or equal to its specified address until
8 // the next record or the end of the address space.
9 typedef struct r_anal_ranged_hint_record_base_t {
10 	RBNode rb;
11 	ut64 addr;
12 } RAnalRangedHintRecordBase;
13 
14 typedef struct r_anal_arch_hint_record_t {
15 	RAnalRangedHintRecordBase base; // MUST be the first member!
16 	char *arch; // NULL => reset to global
17 } RAnalArchHintRecord;
18 
19 typedef struct r_anal_bits_hint_record_t {
20 	RAnalRangedHintRecordBase base; // MUST be the first member!
21 	int bits; // 0 => reset to global
22 } RAnalBitsHintRecord;
23 
ranged_hint_record_cmp(const void * incoming,const RBNode * in_tree,void * user)24 static int ranged_hint_record_cmp(const void *incoming, const RBNode *in_tree, void *user) {
25 	ut64 addr = *(const ut64 *)incoming;
26 	const RAnalRangedHintRecordBase *in_tree_record = container_of (in_tree, const RAnalRangedHintRecordBase, rb);
27 	if (addr < in_tree_record->addr) {
28 		return -1;
29 	} else if (addr > in_tree_record->addr) {
30 		return 1;
31 	}
32 	return 0;
33 }
34 
addr_hint_record_fini(void * element,void * user)35 static void addr_hint_record_fini(void *element, void *user) {
36 	(void)user;
37 	RAnalAddrHintRecord *record = element;
38 	switch (record->type) {
39 	case R_ANAL_ADDR_HINT_TYPE_TYPE_OFFSET:
40 		free (record->type_offset);
41 		break;
42 	case R_ANAL_ADDR_HINT_TYPE_SYNTAX:
43 		free (record->syntax);
44 		break;
45 	case R_ANAL_ADDR_HINT_TYPE_OPCODE:
46 		free (record->opcode);
47 		break;
48 	case R_ANAL_ADDR_HINT_TYPE_ESIL:
49 		free (record->esil);
50 		break;
51 	default:
52 		break;
53 	}
54 }
55 
addr_hint_record_ht_free(HtUPKv * kv)56 static void addr_hint_record_ht_free(HtUPKv *kv) {
57 	r_vector_free (kv->value);
58 }
59 
bits_hint_record_free_rb(RBNode * node,void * user)60 static void bits_hint_record_free_rb(RBNode *node, void *user) {
61 	free (container_of (node, RAnalRangedHintRecordBase, rb));
62 }
63 
arch_hint_record_free_rb(RBNode * node,void * user)64 static void arch_hint_record_free_rb(RBNode *node, void *user) {
65 	RAnalArchHintRecord *record = (RAnalArchHintRecord *)container_of (node, RAnalRangedHintRecordBase, rb);
66 	free (record->arch);
67 	free (record);
68 }
69 
70 // used in anal.c, but no API needed
r_anal_hint_storage_init(RAnal * a)71 void r_anal_hint_storage_init(RAnal *a) {
72 	a->addr_hints = ht_up_new (NULL, addr_hint_record_ht_free, NULL);
73 	a->arch_hints = NULL;
74 	a->bits_hints = NULL;
75 }
76 
77 // used in anal.c, but no API needed
r_anal_hint_storage_fini(RAnal * a)78 void r_anal_hint_storage_fini(RAnal *a) {
79 	ht_up_free (a->addr_hints);
80 	r_rbtree_free (a->arch_hints, arch_hint_record_free_rb, NULL);
81 	r_rbtree_free (a->bits_hints, bits_hint_record_free_rb, NULL);
82 }
83 
r_anal_hint_clear(RAnal * a)84 R_API void r_anal_hint_clear(RAnal *a) {
85 	r_anal_hint_storage_fini (a);
86 	r_anal_hint_storage_init (a);
87 }
88 
89 typedef struct {
90 	HtUP *ht;
91 	ut64 addr;
92 	ut64 size;
93 } DeleteRangeCtx;
94 
addr_hint_range_delete_cb(void * user,const ut64 key,const void * value)95 static bool addr_hint_range_delete_cb(void *user, const ut64 key, const void *value) {
96 	DeleteRangeCtx *ctx = user;
97 	if (key < ctx->addr || key >= ctx->addr + ctx->size) {
98 		return true;
99 	}
100 	ht_up_delete (ctx->ht, key);
101 	return true;
102 }
103 
r_anal_hint_del(RAnal * a,ut64 addr,ut64 size)104 R_API void r_anal_hint_del(RAnal *a, ut64 addr, ut64 size) {
105 	if (size <= 1) {
106 		// only single address
107 		ht_up_delete (a->addr_hints, addr);
108 		r_anal_hint_unset_arch (a, addr);
109 		r_anal_hint_unset_bits (a, addr);
110 		return;
111 	}
112 	// ranged delete
113 	DeleteRangeCtx ctx = { a->addr_hints, addr, size };
114 	ht_up_foreach (a->addr_hints, addr_hint_range_delete_cb, &ctx);
115 	while (true) { // arch
116 		RBNode *node = r_rbtree_lower_bound (a->arch_hints, &addr, ranged_hint_record_cmp, NULL);
117 		if (!node) {
118 			return;
119 		}
120 		RAnalRangedHintRecordBase *base = container_of (node, RAnalRangedHintRecordBase, rb);
121 		if (base->addr >= addr + size) {
122 			break;
123 		}
124 		r_anal_hint_unset_arch (a, base->addr);
125 	}
126 	while (true) { // bits
127 		RBNode *node = r_rbtree_lower_bound (a->bits_hints, &addr, ranged_hint_record_cmp, NULL);
128 		if (!node) {
129 			return;
130 		}
131 		RAnalRangedHintRecordBase *base = container_of (node, RAnalRangedHintRecordBase, rb);
132 		if (base->addr >= addr + size) {
133 			break;
134 		}
135 		r_anal_hint_unset_bits (a, base->addr);
136 	}
137 }
138 
unset_addr_hint_record(RAnal * anal,RAnalAddrHintType type,ut64 addr)139 static void unset_addr_hint_record(RAnal *anal, RAnalAddrHintType type, ut64 addr) {
140 	RVector *records = ht_up_find (anal->addr_hints, addr, NULL);
141 	if (!records) {
142 		return;
143 	}
144 	size_t i;
145 	for (i = 0; i < records->len; i++) {
146 		RAnalAddrHintRecord *record = r_vector_index_ptr (records, i);
147 		if (record->type == type) {
148 			addr_hint_record_fini (record, NULL);
149 			r_vector_remove_at (records, i, NULL);
150 			return;
151 		}
152 	}
153 }
154 
155 // create or return the existing addr hint record of the given type at addr
ensure_addr_hint_record(RAnal * anal,RAnalAddrHintType type,ut64 addr)156 static RAnalAddrHintRecord *ensure_addr_hint_record(RAnal *anal, RAnalAddrHintType type, ut64 addr) {
157 	RVector *records = ht_up_find (anal->addr_hints, addr, NULL);
158 	if (!records) {
159 		records = r_vector_new (sizeof (RAnalAddrHintRecord), addr_hint_record_fini, NULL);
160 		if (!records) {
161 			return NULL;
162 		}
163 		ht_up_insert (anal->addr_hints, addr, records);
164 	}
165 	void *pos;
166 	r_vector_foreach (records, pos) {
167 		RAnalAddrHintRecord *record = pos;
168 		if (record->type == type) {
169 			return record;
170 		}
171 	}
172 	RAnalAddrHintRecord *record = r_vector_push (records, NULL);
173 	memset (record, 0, sizeof (*record));
174 	record->type = type;
175 	return record;
176 }
177 
178 #define SET_HINT(type, setcode) do { \
179 	RAnalAddrHintRecord *r = ensure_addr_hint_record (a, type, addr); \
180 	if (!r) { \
181 		break; \
182 	} \
183 	setcode \
184 } while(0)
185 
ensure_ranged_hint_record(RBTree * tree,ut64 addr,size_t sz)186 static RAnalRangedHintRecordBase *ensure_ranged_hint_record(RBTree *tree, ut64 addr, size_t sz) {
187 	RBNode *node = r_rbtree_find (*tree, &addr, ranged_hint_record_cmp, NULL);
188 	if (node) {
189 		return container_of (node, RAnalRangedHintRecordBase, rb);
190 	}
191 	RAnalRangedHintRecordBase *record = malloc (sz);
192 	memset (record, 0, sz);
193 	if (!record) {
194 		return NULL;
195 	}
196 	record->addr = addr;
197 	r_rbtree_insert (tree, &addr, &record->rb, ranged_hint_record_cmp, NULL);
198 	return record;
199 }
200 
r_anal_hint_set_offset(RAnal * a,ut64 addr,const char * typeoff)201 R_API void r_anal_hint_set_offset(RAnal *a, ut64 addr, const char *typeoff) {
202 	SET_HINT (R_ANAL_ADDR_HINT_TYPE_TYPE_OFFSET,
203 			  free (r->type_offset);
204 		r->type_offset = strdup (typeoff);
205 	);
206 }
207 
r_anal_hint_set_nword(RAnal * a,ut64 addr,int nword)208 R_API void r_anal_hint_set_nword(RAnal *a, ut64 addr, int nword) {
209 	SET_HINT (R_ANAL_ADDR_HINT_TYPE_NWORD, r->nword = nword;);
210 }
211 
r_anal_hint_set_jump(RAnal * a,ut64 addr,ut64 jump)212 R_API void r_anal_hint_set_jump(RAnal *a, ut64 addr, ut64 jump) {
213 	SET_HINT (R_ANAL_ADDR_HINT_TYPE_JUMP, r->jump = jump;);
214 }
215 
r_anal_hint_set_fail(RAnal * a,ut64 addr,ut64 fail)216 R_API void r_anal_hint_set_fail(RAnal *a, ut64 addr, ut64 fail) {
217 	SET_HINT (R_ANAL_ADDR_HINT_TYPE_FAIL, r->fail = fail;);
218 }
219 
r_anal_hint_set_newbits(RAnal * a,ut64 addr,int bits)220 R_API void r_anal_hint_set_newbits(RAnal *a, ut64 addr, int bits) {
221 	SET_HINT (R_ANAL_ADDR_HINT_TYPE_NEW_BITS, r->newbits = bits;);
222 }
223 
r_anal_hint_set_high(RAnal * a,ut64 addr)224 R_API void r_anal_hint_set_high(RAnal *a, ut64 addr) {
225 	SET_HINT (R_ANAL_ADDR_HINT_TYPE_HIGH,);
226 }
227 
r_anal_hint_set_immbase(RAnal * a,ut64 addr,int base)228 R_API void r_anal_hint_set_immbase(RAnal *a, ut64 addr, int base) {
229 	if (base) {
230 		SET_HINT (R_ANAL_ADDR_HINT_TYPE_IMMBASE, r->immbase = base;);
231 	} else {
232 		unset_addr_hint_record (a, R_ANAL_ADDR_HINT_TYPE_IMMBASE, addr);
233 	}
234 }
235 
r_anal_hint_set_pointer(RAnal * a,ut64 addr,ut64 ptr)236 R_API void r_anal_hint_set_pointer(RAnal *a, ut64 addr, ut64 ptr) {
237 	SET_HINT (R_ANAL_ADDR_HINT_TYPE_PTR, r->ptr = ptr;);
238 }
239 
r_anal_hint_set_ret(RAnal * a,ut64 addr,ut64 val)240 R_API void r_anal_hint_set_ret(RAnal *a, ut64 addr, ut64 val) {
241 	SET_HINT (R_ANAL_ADDR_HINT_TYPE_RET, r->retval = val;);
242 }
243 
r_anal_hint_set_syntax(RAnal * a,ut64 addr,const char * syn)244 R_API void r_anal_hint_set_syntax(RAnal *a, ut64 addr, const char *syn) {
245 	SET_HINT (R_ANAL_ADDR_HINT_TYPE_SYNTAX,
246 			  free (r->syntax);
247 		r->syntax = strdup (syn);
248 	);
249 }
250 
r_anal_hint_set_opcode(RAnal * a,ut64 addr,const char * opcode)251 R_API void r_anal_hint_set_opcode(RAnal *a, ut64 addr, const char *opcode) {
252 	SET_HINT (R_ANAL_ADDR_HINT_TYPE_OPCODE,
253 			  free (r->opcode);
254 		r->opcode = strdup (opcode);
255 	);
256 }
257 
r_anal_hint_set_esil(RAnal * a,ut64 addr,const char * esil)258 R_API void r_anal_hint_set_esil(RAnal *a, ut64 addr, const char *esil) {
259 	SET_HINT (R_ANAL_ADDR_HINT_TYPE_ESIL,
260 			  free (r->esil);
261 		r->esil = strdup (esil);
262 	);
263 }
264 
r_anal_hint_set_type(RAnal * a,ut64 addr,int type)265 R_API void r_anal_hint_set_type (RAnal *a, ut64 addr, int type) {
266 	SET_HINT (R_ANAL_ADDR_HINT_TYPE_OPTYPE, r->optype = type;);
267 }
268 
r_anal_hint_set_size(RAnal * a,ut64 addr,ut64 size)269 R_API void r_anal_hint_set_size(RAnal *a, ut64 addr, ut64 size) {
270 	SET_HINT (R_ANAL_ADDR_HINT_TYPE_SIZE, r->size = size;);
271 }
272 
r_anal_hint_set_stackframe(RAnal * a,ut64 addr,ut64 size)273 R_API void r_anal_hint_set_stackframe(RAnal *a, ut64 addr, ut64 size) {
274 	SET_HINT (R_ANAL_ADDR_HINT_TYPE_STACKFRAME, r->stackframe = size;);
275 }
276 
r_anal_hint_set_val(RAnal * a,ut64 addr,ut64 v)277 R_API void r_anal_hint_set_val(RAnal *a, ut64 addr, ut64 v) {
278 	SET_HINT (R_ANAL_ADDR_HINT_TYPE_VAL, r->val = v;);
279 }
280 
r_anal_hint_set_arch(RAnal * a,ut64 addr,const char * arch)281 R_API void r_anal_hint_set_arch(RAnal *a, ut64 addr, const char *arch) {
282 	RAnalArchHintRecord *record = (RAnalArchHintRecord *)ensure_ranged_hint_record (&a->arch_hints, addr, sizeof (RAnalArchHintRecord));
283 	if (!record) {
284 		return;
285 	}
286 	free (record->arch);
287 	record->arch = arch ? strdup (arch) : NULL;
288 }
289 
r_anal_hint_set_bits(RAnal * a,ut64 addr,int bits)290 R_API void r_anal_hint_set_bits(RAnal *a, ut64 addr, int bits) {
291 	RAnalBitsHintRecord *record = (RAnalBitsHintRecord *)ensure_ranged_hint_record (&a->bits_hints, addr, sizeof (RAnalBitsHintRecord));
292 	if (!record) {
293 		return;
294 	}
295 	record->bits = bits;
296 	if (a->hint_cbs.on_bits) {
297 		a->hint_cbs.on_bits (a, addr, bits, true);
298 	}
299 }
300 
r_anal_hint_unset_size(RAnal * a,ut64 addr)301 R_API void r_anal_hint_unset_size(RAnal *a, ut64 addr) {
302 	unset_addr_hint_record (a, R_ANAL_ADDR_HINT_TYPE_SIZE, addr);
303 }
304 
r_anal_hint_unset_esil(RAnal * a,ut64 addr)305 R_API void r_anal_hint_unset_esil(RAnal *a, ut64 addr) {
306 	unset_addr_hint_record (a, R_ANAL_ADDR_HINT_TYPE_ESIL, addr);
307 }
308 
r_anal_hint_unset_opcode(RAnal * a,ut64 addr)309 R_API void r_anal_hint_unset_opcode(RAnal *a, ut64 addr) {
310 	unset_addr_hint_record (a, R_ANAL_ADDR_HINT_TYPE_OPCODE, addr);
311 }
312 
r_anal_hint_unset_high(RAnal * a,ut64 addr)313 R_API void r_anal_hint_unset_high(RAnal *a, ut64 addr) {
314 	unset_addr_hint_record (a, R_ANAL_ADDR_HINT_TYPE_HIGH, addr);
315 }
316 
r_anal_hint_unset_immbase(RAnal * a,ut64 addr)317 R_API void r_anal_hint_unset_immbase(RAnal *a, ut64 addr) {
318 	unset_addr_hint_record (a, R_ANAL_ADDR_HINT_TYPE_IMMBASE, addr);
319 }
320 
r_anal_hint_unset_nword(RAnal * a,ut64 addr)321 R_API void r_anal_hint_unset_nword(RAnal *a, ut64 addr) {
322 	unset_addr_hint_record (a, R_ANAL_ADDR_HINT_TYPE_NWORD, addr);
323 }
324 
r_anal_hint_unset_syntax(RAnal * a,ut64 addr)325 R_API void r_anal_hint_unset_syntax(RAnal *a, ut64 addr) {
326 	unset_addr_hint_record (a, R_ANAL_ADDR_HINT_TYPE_SYNTAX, addr);
327 }
328 
r_anal_hint_unset_pointer(RAnal * a,ut64 addr)329 R_API void r_anal_hint_unset_pointer(RAnal *a, ut64 addr) {
330 	unset_addr_hint_record (a, R_ANAL_ADDR_HINT_TYPE_PTR, addr);
331 }
332 
r_anal_hint_unset_ret(RAnal * a,ut64 addr)333 R_API void r_anal_hint_unset_ret(RAnal *a, ut64 addr) {
334 	unset_addr_hint_record (a, R_ANAL_ADDR_HINT_TYPE_RET, addr);
335 }
336 
r_anal_hint_unset_offset(RAnal * a,ut64 addr)337 R_API void r_anal_hint_unset_offset(RAnal *a, ut64 addr) {
338 	unset_addr_hint_record (a, R_ANAL_ADDR_HINT_TYPE_TYPE_OFFSET, addr);
339 }
340 
r_anal_hint_unset_jump(RAnal * a,ut64 addr)341 R_API void r_anal_hint_unset_jump(RAnal *a, ut64 addr) {
342 	unset_addr_hint_record (a, R_ANAL_ADDR_HINT_TYPE_JUMP, addr);
343 }
344 
r_anal_hint_unset_fail(RAnal * a,ut64 addr)345 R_API void r_anal_hint_unset_fail(RAnal *a, ut64 addr) {
346 	unset_addr_hint_record (a, R_ANAL_ADDR_HINT_TYPE_FAIL, addr);
347 }
348 
r_anal_hint_unset_newbits(RAnal * a,ut64 addr)349 R_API void r_anal_hint_unset_newbits(RAnal *a, ut64 addr) {
350 	unset_addr_hint_record (a, R_ANAL_ADDR_HINT_TYPE_NEW_BITS, addr);
351 }
352 
r_anal_hint_unset_val(RAnal * a,ut64 addr)353 R_API void r_anal_hint_unset_val (RAnal *a, ut64 addr) {
354 	unset_addr_hint_record (a, R_ANAL_ADDR_HINT_TYPE_VAL, addr);
355 }
356 
r_anal_hint_unset_type(RAnal * a,ut64 addr)357 R_API void r_anal_hint_unset_type (RAnal *a, ut64 addr) {
358 	unset_addr_hint_record (a, R_ANAL_ADDR_HINT_TYPE_OPTYPE, addr);
359 }
360 
r_anal_hint_unset_stackframe(RAnal * a,ut64 addr)361 R_API void r_anal_hint_unset_stackframe(RAnal *a, ut64 addr) {
362 	unset_addr_hint_record (a, R_ANAL_ADDR_HINT_TYPE_STACKFRAME, addr);
363 }
364 
r_anal_hint_unset_arch(RAnal * a,ut64 addr)365 R_API void r_anal_hint_unset_arch(RAnal *a, ut64 addr) {
366 	r_rbtree_delete (&a->arch_hints, &addr, ranged_hint_record_cmp, NULL, arch_hint_record_free_rb, NULL);
367 }
368 
r_anal_hint_unset_bits(RAnal * a,ut64 addr)369 R_API void r_anal_hint_unset_bits(RAnal *a, ut64 addr) {
370 	r_rbtree_delete (&a->bits_hints, &addr, ranged_hint_record_cmp, NULL, bits_hint_record_free_rb, NULL);
371 }
372 
r_anal_hint_free(RAnalHint * h)373 R_API void r_anal_hint_free(RAnalHint *h) {
374 	if (h) {
375 		free (h->arch);
376 		free (h->esil);
377 		free (h->opcode);
378 		free (h->syntax);
379 		free (h->offset);
380 		free (h);
381 	}
382 }
383 
r_anal_hint_arch_at(RAnal * anal,ut64 addr,R_NULLABLE ut64 * hint_addr)384 R_API R_NULLABLE R_BORROW const char *r_anal_hint_arch_at(RAnal *anal, ut64 addr, R_NULLABLE ut64 *hint_addr) {
385 	RBNode *node = r_rbtree_upper_bound (anal->arch_hints, &addr, ranged_hint_record_cmp, NULL);
386 	if (!node) {
387 		if (hint_addr) {
388 			*hint_addr = UT64_MAX;
389 		}
390 		return NULL;
391 	}
392 	RAnalArchHintRecord *record = (RAnalArchHintRecord *)container_of (node, RAnalRangedHintRecordBase, rb);
393 	if (hint_addr) {
394 		*hint_addr = record->base.addr;
395 	}
396 	return record->arch;
397 }
398 
r_anal_hint_bits_at(RAnal * anal,ut64 addr,R_NULLABLE ut64 * hint_addr)399 R_API int r_anal_hint_bits_at(RAnal *anal, ut64 addr, R_NULLABLE ut64 *hint_addr) {
400 	RBNode *node = r_rbtree_upper_bound (anal->bits_hints, &addr, ranged_hint_record_cmp, NULL);
401 	if (!node) {
402 		if (hint_addr) {
403 			*hint_addr = UT64_MAX;
404 		}
405 		return 0;
406 	}
407 	RAnalBitsHintRecord *record = (RAnalBitsHintRecord *)container_of (node, RAnalRangedHintRecordBase, rb);
408 	if (hint_addr) {
409 		*hint_addr = record->base.addr;
410 	}
411 	return record->bits;
412 }
413 
r_anal_addr_hints_at(RAnal * anal,ut64 addr)414 R_API R_NULLABLE const RVector/*<const RAnalAddrHintRecord>*/ *r_anal_addr_hints_at(RAnal *anal, ut64 addr) {
415 	return ht_up_find (anal->addr_hints, addr, NULL);
416 }
417 
418 typedef struct {
419 	RAnalAddrHintRecordsCb cb;
420 	void *user;
421 } AddrHintForeachCtx;
422 
addr_hint_foreach_cb(void * user,const ut64 key,const void * value)423 static bool addr_hint_foreach_cb(void *user, const ut64 key, const void *value) {
424 	AddrHintForeachCtx *ctx = user;
425 	return ctx->cb (key, value, ctx->user);
426 }
427 
r_anal_addr_hints_foreach(RAnal * anal,RAnalAddrHintRecordsCb cb,void * user)428 R_API void r_anal_addr_hints_foreach(RAnal *anal, RAnalAddrHintRecordsCb cb, void *user) {
429 	AddrHintForeachCtx ctx = { cb, user };
430 	ht_up_foreach (anal->addr_hints, addr_hint_foreach_cb, &ctx);
431 }
432 
r_anal_arch_hints_foreach(RAnal * anal,RAnalArchHintCb cb,void * user)433 R_API void r_anal_arch_hints_foreach(RAnal *anal, RAnalArchHintCb cb, void *user) {
434 	RBIter iter;
435 	RAnalRangedHintRecordBase *record;
436 	r_rbtree_foreach (anal->arch_hints, iter, record, RAnalRangedHintRecordBase, rb) {
437 		bool cont = cb (record->addr, ((RAnalArchHintRecord *)record)->arch, user);
438 		if (!cont) {
439 			break;
440 		}
441 	}
442 }
443 
r_anal_bits_hints_foreach(RAnal * anal,RAnalBitsHintCb cb,void * user)444 R_API void r_anal_bits_hints_foreach(RAnal *anal, RAnalBitsHintCb cb, void *user) {
445 	RBIter iter;
446 	RAnalRangedHintRecordBase *record;
447 	r_rbtree_foreach (anal->bits_hints, iter, record, RAnalRangedHintRecordBase, rb) {
448 		bool cont = cb (record->addr, ((RAnalBitsHintRecord *)record)->bits, user);
449 		if (!cont) {
450 			break;
451 		}
452 	}
453 }
454 
hint_merge(RAnalHint * hint,RAnalAddrHintRecord * record)455 static void hint_merge(RAnalHint *hint, RAnalAddrHintRecord *record) {
456 	switch (record->type) {
457 	case R_ANAL_ADDR_HINT_TYPE_IMMBASE:
458 		hint->immbase = record->immbase;
459 		break;
460 	case R_ANAL_ADDR_HINT_TYPE_JUMP:
461 		hint->jump = record->jump;
462 		break;
463 	case R_ANAL_ADDR_HINT_TYPE_FAIL:
464 		hint->fail = record->fail;
465 		break;
466 	case R_ANAL_ADDR_HINT_TYPE_STACKFRAME:
467 		hint->stackframe = record->stackframe;
468 		break;
469 	case R_ANAL_ADDR_HINT_TYPE_PTR:
470 		hint->ptr = record->ptr;
471 		break;
472 	case R_ANAL_ADDR_HINT_TYPE_NWORD:
473 		hint->nword = record->nword;
474 		break;
475 	case R_ANAL_ADDR_HINT_TYPE_RET:
476 		hint->ret = record->retval;
477 		break;
478 	case R_ANAL_ADDR_HINT_TYPE_NEW_BITS:
479 		hint->new_bits = record->newbits;
480 		break;
481 	case R_ANAL_ADDR_HINT_TYPE_SIZE:
482 		hint->size = record->size;
483 		break;
484 	case R_ANAL_ADDR_HINT_TYPE_SYNTAX:
485 		hint->syntax = record->syntax ? strdup (record->syntax) : NULL;
486 		break;
487 	case R_ANAL_ADDR_HINT_TYPE_OPTYPE:
488 		hint->type = record->optype;
489 		break;
490 	case R_ANAL_ADDR_HINT_TYPE_OPCODE:
491 		hint->opcode = record->opcode ? strdup (record->opcode) : NULL;
492 		break;
493 	case R_ANAL_ADDR_HINT_TYPE_TYPE_OFFSET:
494 		hint->offset = record->type_offset ? strdup (record->type_offset) : NULL;
495 		break;
496 	case R_ANAL_ADDR_HINT_TYPE_ESIL:
497 		hint->esil = record->esil ? strdup (record->esil) : NULL;
498 		break;
499 	case R_ANAL_ADDR_HINT_TYPE_HIGH:
500 		hint->high = true;
501 		break;
502 	case R_ANAL_ADDR_HINT_TYPE_VAL:
503 		hint->val = record->val;
504 		break;
505 	}
506 }
507 
r_anal_hint_get(RAnal * a,ut64 addr)508 R_API RAnalHint *r_anal_hint_get(RAnal *a, ut64 addr) {
509 	RAnalHint *hint = R_NEW0 (RAnalHint);
510 	if (!hint) {
511 		return NULL;
512 	}
513 	hint->addr = addr;
514 	hint->jump = UT64_MAX;
515 	hint->fail = UT64_MAX;
516 	hint->ret = UT64_MAX;
517 	hint->val = UT64_MAX;
518 	hint->stackframe = UT64_MAX;
519 	const RVector *records = r_anal_addr_hints_at (a, addr);
520 	if (records) {
521 		RAnalAddrHintRecord *record;
522 		r_vector_foreach (records, record) {
523 			hint_merge (hint, record);
524 		}
525 	}
526 	const char *arch = r_anal_hint_arch_at (a, addr, NULL);
527 	hint->arch = arch ? strdup (arch) : NULL;
528 	hint->bits = r_anal_hint_bits_at (a, addr, NULL);
529 	if ((!records || r_vector_empty (records)) && !hint->arch && !hint->bits) {
530 		// no hints found
531 		free (hint);
532 		return NULL;
533 	}
534 	return hint;
535 }
536