1 /* radare - LGPL - Copyright 2010-2021 - nibble, alvaro, pancake */
2
3 #include <r_anal.h>
4 #include <r_parse.h>
5 #include <r_util.h>
6
7 #define READ_AHEAD 1
8 #define SDB_KEY_BB "bb.0x%"PFMT64x ".0x%"PFMT64x
9 // XXX must be configurable by the user
10 #define JMPTBLSZ 512
11 #define JMPTBL_LEA_SEARCH_SZ 64
12 #define JMPTBL_MAXFCNSIZE 4096
13 #define R_ANAL_MAX_INCSTACK 8096
14 #define BB_ALIGN 0x10
15 #define MAX_SCAN_SIZE 0x7ffffff
16
17 /* speedup analysis by removing some function overlapping checks */
18 #define JAYRO_04 1
19
20 // 16 KB is the maximum size for a basic block
21 #define MAX_FLG_NAME_SIZE 64
22
23 #define FIX_JMP_FWD 0
24 #define D if (a->verbose)
25
26 // 64KB max size
27 // 256KB max function size
28 #define MAX_FCN_SIZE (1024 * 256)
29
30 #define DB a->sdb_fcns
31 #define EXISTS(x, ...) snprintf (key, sizeof (key) - 1, x, ## __VA_ARGS__), sdb_exists (DB, key)
32 #define SETKEY(x, ...) snprintf (key, sizeof (key) - 1, x, ## __VA_ARGS__);
33
34 typedef struct fcn_tree_iter_t {
35 int len;
36 RBNode *cur;
37 RBNode *path[R_RBTREE_MAX_HEIGHT];
38 } FcnTreeIter;
39
r_anal_fcntype_tostring(int type)40 R_API const char *r_anal_fcntype_tostring(int type) {
41 switch (type) {
42 case R_ANAL_FCN_TYPE_NULL: return "null";
43 case R_ANAL_FCN_TYPE_FCN: return "fcn";
44 case R_ANAL_FCN_TYPE_LOC: return "loc";
45 case R_ANAL_FCN_TYPE_SYM: return "sym";
46 case R_ANAL_FCN_TYPE_IMP: return "imp";
47 case R_ANAL_FCN_TYPE_INT: return "int"; // interrupt
48 case R_ANAL_FCN_TYPE_ROOT: return "root";
49 }
50 return "unk";
51 }
52
53 #if READ_AHEAD
54 static ut64 cache_addr = UT64_MAX;
55
56 // TODO: move into io :?
read_ahead(RAnal * anal,ut64 addr,ut8 * buf,int len)57 static int read_ahead(RAnal *anal, ut64 addr, ut8 *buf, int len) {
58 static ut8 cache[1024];
59 const int cache_len = sizeof (cache);
60
61 if (len < 1) {
62 return 0;
63 }
64 if (len > cache_len) {
65 int a = anal->iob.read_at (anal->iob.io, addr, buf, len); // double read
66 memcpy (cache, buf, cache_len);
67 cache_addr = addr;
68 return a;
69 }
70
71 ut64 addr_end = UT64_ADD_OVFCHK (addr, len)? UT64_MAX: addr + len;
72 ut64 cache_addr_end = UT64_ADD_OVFCHK (cache_addr, cache_len)? UT64_MAX: cache_addr + cache_len;
73 bool isCached = ((addr != UT64_MAX) && (addr >= cache_addr) && (addr_end < cache_addr_end));
74 if (isCached) {
75 memcpy (buf, cache + (addr - cache_addr), len);
76 } else {
77 anal->iob.read_at (anal->iob.io, addr, cache, sizeof (cache));
78 memcpy (buf, cache, len);
79 cache_addr = addr;
80 }
81 return len;
82 }
83 #else
read_ahead(RAnal * anal,ut64 addr,ut8 * buf,int len)84 static int read_ahead(RAnal *anal, ut64 addr, ut8 *buf, int len) {
85 return anal->iob.read_at (anal->iob.io, addr, buf, len);
86 }
87 #endif
88
r_anal_fcn_invalidate_read_ahead_cache(void)89 R_API void r_anal_fcn_invalidate_read_ahead_cache(void) {
90 #if READ_AHEAD
91 cache_addr = UT64_MAX;
92 #endif
93 }
94
cmpaddr(const void * _a,const void * _b)95 static int cmpaddr(const void *_a, const void *_b) {
96 const RAnalBlock *a = _a, *b = _b;
97 return a->addr > b->addr ? 1 : (a->addr < b->addr ? -1 : 0);
98 }
99
r_anal_function_resize(RAnalFunction * fcn,int newsize)100 R_API int r_anal_function_resize(RAnalFunction *fcn, int newsize) {
101 RAnal *anal = fcn->anal;
102 RAnalBlock *bb;
103 RListIter *iter, *iter2;
104
105 r_return_val_if_fail (fcn, false);
106
107 if (newsize < 1) {
108 return false;
109 }
110
111 // XXX this is something we should probably do for all the archs
112 bool is_arm = anal->cur->arch && !strncmp (anal->cur->arch, "arm", 3);
113 if (is_arm) {
114 return true;
115 }
116
117 ut64 eof = fcn->addr + newsize;
118 r_list_foreach_safe (fcn->bbs, iter, iter2, bb) {
119 if (bb->addr >= eof) {
120 r_anal_function_remove_block (fcn, bb);
121 continue;
122 }
123 if (bb->addr + bb->size >= eof) {
124 r_anal_block_set_size (bb, eof - bb->addr);
125 r_anal_block_update_hash (bb);
126 }
127 if (bb->jump != UT64_MAX && bb->jump >= eof) {
128 bb->jump = UT64_MAX;
129 }
130 if (bb->fail != UT64_MAX && bb->fail >= eof) {
131 bb->fail = UT64_MAX;
132 }
133 }
134 return true;
135 }
136
137 // Create a new 0-sized basic block inside the function
fcn_append_basic_block(RAnal * anal,RAnalFunction * fcn,ut64 addr)138 static RAnalBlock *fcn_append_basic_block(RAnal *anal, RAnalFunction *fcn, ut64 addr) {
139 RAnalBlock *bb = r_anal_create_block (anal, addr, 0);
140 if (!bb) {
141 return NULL;
142 }
143 r_anal_function_add_block (fcn, bb);
144 bb->stackptr = fcn->stack;
145 bb->parent_stackptr = fcn->stack;
146 return bb;
147 }
148
149 #define gotoBeach(x) ret = x; goto beach;
150
isInvalidMemory(RAnal * anal,const ut8 * buf,int len)151 static bool isInvalidMemory(RAnal *anal, const ut8 *buf, int len) {
152 if (anal->opt.nonull > 0) {
153 int i;
154 const int count = R_MIN (len, anal->opt.nonull);
155 for (i = 0; i < count; i++) {
156 if (buf[i]) {
157 break;
158 }
159 }
160 if (i == count) {
161 return true;
162 }
163 }
164 return !memcmp (buf, "\xff\xff\xff\xff", R_MIN (len, 4));
165 }
166
isSymbolNextInstruction(RAnal * anal,RAnalOp * op)167 static bool isSymbolNextInstruction(RAnal *anal, RAnalOp *op) {
168 r_return_val_if_fail (anal && op && anal->flb.get_at, false);
169
170 RFlagItem *fi = anal->flb.get_at (anal->flb.f, op->addr + op->size, false);
171 return (fi && fi->name && (strstr (fi->name, "imp.") || strstr (fi->name, "sym.")
172 || strstr (fi->name, "entry") || strstr (fi->name, "main")));
173 }
174
is_delta_pointer_table(RAnal * anal,RAnalFunction * fcn,ut64 addr,ut64 lea_ptr,ut64 * jmptbl_addr,ut64 * casetbl_addr,RAnalOp * jmp_aop)175 static bool is_delta_pointer_table(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut64 lea_ptr, ut64 *jmptbl_addr, ut64 *casetbl_addr, RAnalOp *jmp_aop) {
176 int i;
177 ut64 dst;
178 st32 jmptbl[64] = {0};
179 /* check if current instruction is followed by an ujmp */
180 ut8 buf[JMPTBL_LEA_SEARCH_SZ];
181 RAnalOp *aop = jmp_aop;
182 RAnalOp omov_aop = {0};
183 RAnalOp mov_aop = {0};
184 RAnalOp add_aop = {0};
185 RRegItem *reg_src = NULL, *o_reg_dst = NULL;
186 RAnalValue cur_scr, cur_dst = { 0 };
187 read_ahead (anal, addr, (ut8*)buf, sizeof (buf));
188 bool isValid = false;
189 for (i = 0; i + 8 < JMPTBL_LEA_SEARCH_SZ; i++) {
190 ut64 at = addr + i;
191 int left = JMPTBL_LEA_SEARCH_SZ - i;
192 int len = r_anal_op (anal, aop, at, buf + i, left, R_ANAL_OP_MASK_BASIC | R_ANAL_OP_MASK_HINT | R_ANAL_OP_MASK_VAL);
193 if (len < 1) {
194 len = 1;
195 }
196 if (aop->type == R_ANAL_OP_TYPE_UJMP || aop->type == R_ANAL_OP_TYPE_RJMP) {
197 isValid = true;
198 break;
199 }
200 if (aop->type == R_ANAL_OP_TYPE_MOV) {
201 omov_aop = mov_aop;
202 mov_aop = *aop;
203 o_reg_dst = cur_dst.reg;
204 if (mov_aop.dst) {
205 cur_dst = *mov_aop.dst;
206 }
207 if (mov_aop.src[0]) {
208 cur_scr = *mov_aop.src[0];
209 reg_src = cur_scr.regdelta;
210 }
211 }
212 if (aop->type == R_ANAL_OP_TYPE_ADD) {
213 add_aop = *aop;
214 }
215 r_anal_op_fini (aop);
216 i += len - 1;
217 }
218 if (!isValid) {
219 return false;
220 }
221
222 // check if we have a msvc 19xx style jump table using rva table entries
223 // lea reg1, [base_addr]
224 // mov reg2, dword [reg1 + tbl_off*4 + tbl_loc_off]
225 // add reg2, reg1
226 // jmp reg2
227 if (mov_aop.type && add_aop.type && mov_aop.addr < add_aop.addr && add_aop.addr < jmp_aop->addr
228 && mov_aop.disp && mov_aop.disp != UT64_MAX) {
229 // disp in this case should be tbl_loc_off
230 *jmptbl_addr += mov_aop.disp;
231 if (o_reg_dst && reg_src && o_reg_dst->offset == reg_src->offset && omov_aop.disp != UT64_MAX) {
232 // Special case for indirection
233 // lea reg1, [base_addr]
234 // movzx reg2, byte [reg1 + tbl_off + casetbl_loc_off]
235 // mov reg3, dword [reg1 + reg2*4 + tbl_loc_off]
236 // add reg3, reg1
237 // jmp reg3
238 *casetbl_addr += omov_aop.disp;
239 }
240 }
241 #if 0
242 // required for the last jmptbl.. but seems to work without it and breaks other tests
243 if (mov_aop.type && mov_aop.ptr) {
244 *jmptbl_addr += mov_aop.ptr;
245 // absjmptbl
246 lea_ptr = mov_aop.ptr;
247 }
248 #endif
249 /* check if jump table contains valid deltas */
250 read_ahead (anal, *jmptbl_addr, (ut8 *)&jmptbl, 64);
251 for (i = 0; i < 3; i++) {
252 dst = lea_ptr + (st32)r_read_le32 (jmptbl);
253 if (!anal->iob.is_valid_offset (anal->iob.io, dst, 0)) {
254 return false;
255 }
256 if (dst > fcn->addr + JMPTBL_MAXFCNSIZE) {
257 return false;
258 }
259 if (anal->opt.jmpabove && dst < (fcn->addr < JMPTBL_MAXFCNSIZE ? 0 : fcn->addr - JMPTBL_MAXFCNSIZE)) {
260 return false;
261 }
262 }
263 return true;
264 }
265
try_get_cmpval_from_parents(RAnal * anal,RAnalFunction * fcn,RAnalBlock * my_bb,const char * cmp_reg)266 static ut64 try_get_cmpval_from_parents(RAnal * anal, RAnalFunction *fcn, RAnalBlock *my_bb, const char * cmp_reg) {
267 r_return_val_if_fail (fcn && fcn->bbs && cmp_reg, UT64_MAX);
268 RListIter *iter;
269 RAnalBlock *tmp_bb;
270 r_list_foreach (fcn->bbs, iter, tmp_bb) {
271 if (tmp_bb->jump == my_bb->addr || tmp_bb->fail == my_bb->addr) {
272 if (tmp_bb->cmpreg == cmp_reg) {
273 if (tmp_bb->cond) {
274 if (tmp_bb->cond->type == R_ANAL_COND_HI || tmp_bb->cond->type == R_ANAL_COND_GT) {
275 return tmp_bb->cmpval + 1;
276 }
277 }
278 return tmp_bb->cmpval;
279 }
280 }
281 }
282 return UT64_MAX;
283 }
284
regs_exist(RAnalValue * src,RAnalValue * dst)285 static bool regs_exist(RAnalValue *src, RAnalValue *dst) {
286 r_return_val_if_fail (src && dst, false);
287 return src->reg && dst->reg && src->reg->name && dst->reg->name;
288 }
289
290 // 0 if not skipped; 1 if skipped; 2 if skipped before
skip_hp(RAnal * anal,RAnalFunction * fcn,RAnalOp * op,RAnalBlock * bb,ut64 addr,int oplen,int un_idx,int * idx)291 static int skip_hp(RAnal *anal, RAnalFunction *fcn, RAnalOp *op, RAnalBlock *bb, ut64 addr, int oplen, int un_idx, int *idx) {
292 // this step is required in order to prevent infinite recursion in some cases
293 if ((addr + un_idx - oplen) == fcn->addr) {
294 // use addr instead of op->addr to mark repeat
295 if (!anal->flb.exist_at (anal->flb.f, "skip", 4, addr)) {
296 char *name = r_str_newf ("skip.%"PFMT64x, addr);
297 anal->flb.set (anal->flb.f, name, addr, oplen);
298 free (name);
299 fcn->addr += oplen;
300 r_anal_block_relocate (bb, bb->addr + oplen, bb->size - oplen);
301 *idx = un_idx;
302 return 1;
303 }
304 return 2;
305 }
306 return 0;
307 }
308
purity_checked(HtUP * ht,RAnalFunction * fcn)309 static bool purity_checked(HtUP *ht, RAnalFunction *fcn) {
310 bool checked;
311 ht_up_find (ht, fcn->addr, &checked);
312 return checked;
313 }
314
315 /*
316 * Checks whether a given function is pure and sets its 'is_pure' field.
317 * This function marks fcn 'not pure' if fcn, or any function called by fcn, accesses data
318 * from outside, even if it only READS it.
319 * Probably worth changing it in the future, so that it marks fcn 'impure' only when it
320 * (or any function called by fcn) MODIFIES external data.
321 */
check_purity(HtUP * ht,RAnalFunction * fcn)322 static void check_purity(HtUP *ht, RAnalFunction *fcn) {
323 RListIter *iter;
324 RList *refs = r_anal_function_get_refs (fcn);
325 RAnalRef *ref;
326 ht_up_insert (ht, fcn->addr, NULL);
327 fcn->is_pure = true;
328 r_list_foreach (refs, iter, ref) {
329 if (ref->type == R_ANAL_REF_TYPE_CALL || ref->type == R_ANAL_REF_TYPE_CODE) {
330 RAnalFunction *called_fcn = r_anal_get_fcn_in (fcn->anal, ref->addr, 0);
331 if (!called_fcn) {
332 continue;
333 }
334 if (!purity_checked (ht, called_fcn)) {
335 check_purity (ht, called_fcn);
336 }
337 if (!called_fcn->is_pure) {
338 fcn->is_pure = false;
339 break;
340 }
341 }
342 if (ref->type == R_ANAL_REF_TYPE_DATA) {
343 fcn->is_pure = false;
344 break;
345 }
346 }
347 r_list_free (refs);
348 }
349
350 typedef struct {
351 ut64 op_addr;
352 ut64 leaddr;
353 } leaddr_pair;
354
bbget(RAnal * anal,ut64 addr,bool jumpmid)355 static RAnalBlock *bbget(RAnal *anal, ut64 addr, bool jumpmid) {
356 RList *intersecting = r_anal_get_blocks_in (anal, addr);
357 RListIter *iter;
358 RAnalBlock *bb;
359
360 RAnalBlock *ret = NULL;
361 r_list_foreach (intersecting, iter, bb) {
362 ut64 eaddr = bb->addr + bb->size;
363 if (((bb->addr >= eaddr && addr == bb->addr)
364 || r_anal_block_contains (bb, addr))
365 && (!jumpmid || r_anal_block_op_starts_at (bb, addr))) {
366 if (anal->opt.delay) {
367 ut8 *buf = malloc (bb->size);
368 if (anal->iob.read_at (anal->iob.io, bb->addr, buf, bb->size)) {
369 const int last_instr_idx = bb->ninstr - 1;
370 bool in_delay_slot = false;
371 int i;
372 for (i = last_instr_idx; i >= 0; i--) {
373 const ut64 off = r_anal_bb_offset_inst (bb, i);
374 const ut64 at = bb->addr + off;
375 if (addr <= at || off >= bb->size) {
376 continue;
377 }
378 RAnalOp op;
379 int size = r_anal_op (anal, &op, at, buf + off, bb->size - off, R_ANAL_OP_MASK_BASIC);
380 if (size > 0 && op.delay) {
381 if (op.delay >= last_instr_idx - i) {
382 in_delay_slot = true;
383 }
384 r_anal_op_fini (&op);
385 break;
386 }
387 r_anal_op_fini (&op);
388 }
389 if (in_delay_slot) {
390 free (buf);
391 continue;
392 }
393 }
394 free (buf);
395 }
396 ret = bb;
397 break;
398 }
399 }
400 r_list_free (intersecting);
401 return ret;
402 }
403
404 typedef struct {
405 RAnalFunction *fcn;
406 const int stack_diff;
407 } BlockTakeoverCtx;
408
fcn_takeover_block_recursive_followthrough_cb(RAnalBlock * block,void * user)409 static bool fcn_takeover_block_recursive_followthrough_cb(RAnalBlock *block, void *user) {
410 BlockTakeoverCtx *ctx = user;
411 RAnalFunction *our_fcn = ctx->fcn;
412 r_anal_block_ref (block);
413 while (!r_list_empty (block->fcns)) {
414 RAnalFunction *other_fcn = r_list_first (block->fcns);
415 if (other_fcn->addr == block->addr) {
416 return false;
417 }
418 // Steal vars from this block
419 size_t i;
420 for (i = 0; i < block->ninstr; i++) {
421 const ut64 addr = r_anal_bb_opaddr_i (block, i);
422 RPVector *vars_used = r_anal_function_get_vars_used_at (other_fcn, addr);
423 if (!vars_used) {
424 continue;
425 }
426 // vars_used will get modified if r_anal_var_remove_access_at gets called
427 RPVector *cloned_vars_used = (RPVector *)r_vector_clone ((RVector *)vars_used);
428 void **it;
429 r_pvector_foreach (cloned_vars_used, it) {
430 RAnalVar *other_var = *it;
431 const int actual_delta = other_var->kind == R_ANAL_VAR_KIND_SPV
432 ? other_var->delta + ctx->stack_diff
433 : other_var->delta + (other_fcn->bp_off - our_fcn->bp_off);
434 RAnalVar *our_var = r_anal_function_get_var (our_fcn, other_var->kind, actual_delta);
435 if (!our_var) {
436 our_var = r_anal_function_set_var (our_fcn, actual_delta, other_var->kind, other_var->type, 0, other_var->isarg, other_var->name);
437 }
438 if (our_var) {
439 RAnalVarAccess *acc = r_anal_var_get_access_at (other_var, addr);
440 r_anal_var_set_access (our_var, acc->reg, addr, acc->type, acc->stackptr);
441 }
442 r_anal_var_remove_access_at (other_var, addr);
443 if (r_vector_empty (&other_var->accesses)) {
444 r_anal_function_delete_var (other_fcn, other_var);
445 }
446 }
447 r_pvector_free (cloned_vars_used);
448 }
449
450 // TODO: remove block->ninstr from other_fcn considering delay slots
451 r_anal_function_remove_block (other_fcn, block);
452 }
453 block->stackptr -= ctx->stack_diff;
454 block->parent_stackptr -= ctx->stack_diff;
455 r_anal_function_add_block (our_fcn, block);
456 // TODO: add block->ninstr from our_fcn considering delay slots
457 r_anal_block_unref (block);
458 return true;
459 }
460
461 // Remove block and all of its recursive successors from all its functions and add them only to fcn
fcn_takeover_block_recursive(RAnalFunction * fcn,RAnalBlock * start_block)462 static void fcn_takeover_block_recursive(RAnalFunction *fcn, RAnalBlock *start_block) {
463 BlockTakeoverCtx ctx = { fcn, start_block->parent_stackptr - fcn->stack};
464 r_anal_block_recurse_followthrough (start_block, fcn_takeover_block_recursive_followthrough_cb, &ctx);
465 }
466
retpoline_reg(RAnal * anal,ut64 addr)467 static const char *retpoline_reg(RAnal *anal, ut64 addr) {
468 RFlagItem *flag = anal->flag_get (anal->flb.f, addr);
469 if (flag) {
470 const char *token = "x86_indirect_thunk_";
471 const char *thunk = strstr (flag->name, token);
472 if (thunk) {
473 return thunk + strlen (token);
474 }
475 }
476 #if 0
477 // TODO: implement following code analysis check for stripped binaries:
478 // 1) op(addr).type == CALL
479 // 2) call_dest = op(addr).addr
480 // 3) op(call_dest).type == STORE
481 // 4) op(call_dest + op(call_dest).size).type == RET
482 [0x00000a65]> pid 6
483 0x00000a65 sym.__x86_indirect_thunk_rax:
484 0x00000a65 .------- e807000000 call 0xa71
485 0x00000a6a | f390 pause
486 0x00000a6c | 0faee8 lfence
487 0x00000a6f | ebf9 jmp 0xa6a
488 0x00000a71 `----> 48890424 mov qword [rsp], rax
489 0x00000a75 c3 ret
490 #endif
491 return NULL;
492 }
493
analyze_retpoline(RAnal * anal,RAnalOp * op)494 static void analyze_retpoline(RAnal *anal, RAnalOp *op) {
495 if (anal->opt.retpoline) {
496 const char *rr = retpoline_reg (anal, op->jump);
497 if (rr) {
498 op->type = R_ANAL_OP_TYPE_RJMP;
499 op->reg = rr;
500 }
501 }
502 }
503
op_is_set_bp(RAnalOp * op,const char * bp_reg,const char * sp_reg)504 static inline bool op_is_set_bp(RAnalOp *op, const char *bp_reg, const char *sp_reg) {
505 bool has_dst_reg = op->dst && op->dst->reg && op->dst->reg->name;
506 bool has_src_reg = op->src[0] && op->src[0]->reg && op->src[0]->reg->name;
507 if (has_dst_reg && has_src_reg) {
508 return !strcmp (bp_reg, op->dst->reg->name) && !strcmp (sp_reg, op->src[0]->reg->name);
509 }
510 return false;
511 }
512
does_arch_destroys_dst(const char * arch)513 static inline bool does_arch_destroys_dst(const char *arch) {
514 return arch && (!strncmp (arch, "arm", 3) || !strcmp (arch, "riscv") || !strcmp (arch, "ppc"));
515 }
516
fcn_recurse(RAnal * anal,RAnalFunction * fcn,ut64 addr,ut64 len,int depth)517 static int fcn_recurse(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut64 len, int depth) {
518 if (depth < 1) {
519 if (anal->verbose) {
520 eprintf ("Too deep fcn_recurse at 0x%"PFMT64x "\n", addr);
521 }
522 return R_ANAL_RET_ERROR; // MUST BE TOO DEEP
523 }
524 // TODO Store all this stuff in the heap so we save memory in the stack
525 RAnalOp *op = NULL;
526 const bool continue_after_jump = anal->opt.afterjmp;
527 const int addrbytes = anal->iob.io ? anal->iob.io->addrbytes : 1;
528 char *last_reg_mov_lea_name = NULL;
529 RAnalBlock *bb = NULL;
530 RAnalBlock *bbg = NULL;
531 int ret = R_ANAL_RET_END, skip_ret = 0;
532 bool overlapped = false;
533 int oplen, idx = 0;
534 static ut64 cmpval = UT64_MAX; // inherited across functions, otherwise it breaks :?
535 bool varset = false;
536 struct {
537 int cnt;
538 int idx;
539 int after;
540 int pending;
541 int adjust;
542 int un_idx; // delay.un_idx
543 } delay = {
544 0
545 };
546 bool arch_destroys_dst = does_arch_destroys_dst (anal->cur->arch);
547 const bool is_arm = anal->cur->arch && !strncmp (anal->cur->arch, "arm", 3);
548 const bool is_x86 = is_arm ? false: anal->cur->arch && !strncmp (anal->cur->arch, "x86", 3);
549 const bool is_amd64 = is_x86 ? fcn->cc && !strcmp (fcn->cc, "amd64") : false;
550 const bool is_dalvik = is_x86? false: anal->cur->arch && !strncmp (anal->cur->arch, "dalvik", 6);
551 RRegItem *variadic_reg = NULL;
552 if (is_amd64) {
553 variadic_reg = r_reg_get (anal->reg, "rax", R_REG_TYPE_GPR);
554 }
555 bool has_variadic_reg = !!variadic_reg;
556
557 if (r_cons_is_breaked ()) {
558 return R_ANAL_RET_END;
559 }
560 if (anal->sleep) {
561 r_sys_usleep (anal->sleep);
562 }
563
564 // check if address is readable //:
565 if (!anal->iob.is_valid_offset (anal->iob.io, addr, 0)) {
566 if (addr != UT64_MAX && !anal->iob.io->va) {
567 if (anal->verbose) {
568 eprintf ("Invalid address 0x%"PFMT64x ". Try with io.va=true\n", addr);
569 }
570 }
571 return R_ANAL_RET_ERROR; // MUST BE TOO DEEP
572 }
573
574 RAnalFunction *fcn_at_addr = r_anal_get_function_at (anal, addr);
575 if (fcn_at_addr && fcn_at_addr != fcn) {
576 return R_ANAL_RET_ERROR; // MUST BE NOT FOUND
577 }
578
579 RAnalBlock *existing_bb = bbget (anal, addr, anal->opt.jmpmid && is_x86);
580 if (existing_bb) {
581 bool existing_in_fcn = r_list_contains (existing_bb->fcns, fcn);
582 existing_bb = r_anal_block_split (existing_bb, addr);
583 if (!existing_in_fcn && existing_bb) {
584 if (existing_bb->addr == fcn->addr) {
585 // our function starts directly there, so we steal what is ours!
586 fcn_takeover_block_recursive (fcn, existing_bb);
587 }
588 }
589 if (existing_bb) {
590 r_anal_block_unref (existing_bb);
591 }
592 if (anal->opt.recont) {
593 return R_ANAL_RET_END;
594 }
595 if (anal->verbose) {
596 eprintf ("r_anal_fcn_bb() fails at 0x%"PFMT64x "\n", addr);
597 }
598 return R_ANAL_RET_ERROR; // MUST BE NOT DUP
599 }
600
601 bb = fcn_append_basic_block (anal, fcn, addr);
602 // we checked before whether there is a bb at addr, so the create should have succeeded
603 r_return_val_if_fail (bb, R_ANAL_RET_ERROR);
604
605 if (!anal->leaddrs) {
606 anal->leaddrs = r_list_newf (free);
607 if (!anal->leaddrs) {
608 eprintf ("Cannot create leaddr list\n");
609 gotoBeach (R_ANAL_RET_ERROR);
610 }
611 }
612 static ut64 lea_jmptbl_ip = UT64_MAX;
613 ut64 last_reg_mov_lea_val = UT64_MAX;
614 bool last_is_reg_mov_lea = false;
615 bool last_is_push = false;
616 bool last_is_mov_lr_pc = false;
617 ut64 last_push_addr = UT64_MAX;
618 if (anal->limit && addr + idx < anal->limit->from) {
619 gotoBeach (R_ANAL_RET_END);
620 }
621 RAnalFunction *tmp_fcn = r_anal_get_fcn_in (anal, addr, 0);
622 if (tmp_fcn) {
623 // Checks if var is already analyzed at given addr
624 RList *list = r_anal_var_all_list (anal, tmp_fcn);
625 if (!r_list_empty (list)) {
626 varset = true;
627 }
628 r_list_free (list);
629 }
630 ut64 movdisp = UT64_MAX; // used by jmptbl when coded as "mov reg,[R*4+B]"
631 int maxlen = len * addrbytes;
632 if (is_dalvik) {
633 bool skipAnalysis = false;
634 if (!strncmp (fcn->name, "sym.", 4)) {
635 if (!strncmp (fcn->name + 4, "imp.", 4)) {
636 skipAnalysis = true;
637 } else if (strstr (fcn->name, "field")) {
638 skipAnalysis = true;
639 }
640 }
641 if (skipAnalysis) {
642 gotoBeach (R_ANAL_RET_END);
643 }
644 }
645 if ((maxlen - (addrbytes * idx)) > MAX_SCAN_SIZE) {
646 if (anal->verbose) {
647 eprintf ("Warning: Skipping large memory region.\n");
648 }
649 maxlen = 0;
650 }
651
652 op = r_anal_op_new ();
653 while (addrbytes * idx < maxlen) {
654 if (!last_is_reg_mov_lea) {
655 free (last_reg_mov_lea_name);
656 last_reg_mov_lea_name = NULL;
657 }
658 if (anal->limit && anal->limit->to <= addr + idx) {
659 break;
660 }
661 repeat:
662 if (r_cons_is_breaked ()) {
663 break;
664 }
665 ut8 buf[32]; // 32 bytes is enough to hold any instruction.
666 ut32 at_delta = addrbytes * idx;
667 ut64 at = addr + at_delta;
668 ut64 bytes_read = R_MIN (len - at_delta, sizeof (buf));
669 ret = read_ahead (anal, at, buf, bytes_read);
670
671 if (ret < 0) {
672 eprintf ("Failed to read\n");
673 break;
674 }
675 if (isInvalidMemory (anal, buf, bytes_read)) {
676 if (anal->verbose) {
677 eprintf ("Warning: FFFF opcode at 0x%08"PFMT64x "\n", at);
678 }
679 gotoBeach (R_ANAL_RET_ERROR)
680 }
681 r_anal_op_fini (op);
682 if ((oplen = r_anal_op (anal, op, at, buf, bytes_read, R_ANAL_OP_MASK_ESIL | R_ANAL_OP_MASK_VAL | R_ANAL_OP_MASK_HINT)) < 1) {
683 if (anal->verbose) {
684 eprintf ("Invalid instruction at 0x%"PFMT64x" with %d bits\n", at, anal->bits);
685 }
686 // gotoBeach (R_ANAL_RET_ERROR);
687 // RET_END causes infinite loops somehow
688 gotoBeach (R_ANAL_RET_END);
689 }
690 const char *bp_reg = anal->reg->name[R_REG_NAME_BP];
691 const char *sp_reg = anal->reg->name[R_REG_NAME_SP];
692 const bool has_stack_regs = bp_reg && sp_reg;
693
694 if (anal->opt.nopskip && fcn->addr == at) {
695 RFlagItem *fi = anal->flb.get_at (anal->flb.f, addr, false);
696 if (!fi || strncmp (fi->name, "sym.", 4)) {
697 if ((addr + delay.un_idx - oplen) == fcn->addr) {
698 if (r_anal_block_relocate (bb, bb->addr + oplen, bb->size - oplen)) {
699 fcn->addr += oplen;
700 idx = delay.un_idx;
701 goto repeat;
702 }
703 }
704 }
705 switch (op->type & R_ANAL_OP_TYPE_MASK) {
706 case R_ANAL_OP_TYPE_TRAP:
707 case R_ANAL_OP_TYPE_ILL:
708 case R_ANAL_OP_TYPE_NOP:
709 if (r_anal_block_relocate (bb, at + op->size, bb->size)) {
710 addr = at + op->size;
711 fcn->addr = addr;
712 goto repeat;
713 }
714 }
715 }
716 if (op->hint.new_bits) {
717 r_anal_hint_set_bits (anal, op->jump, op->hint.new_bits);
718 }
719 if (idx > 0 && !overlapped) {
720 bbg = bbget (anal, at, anal->opt.jmpmid && is_x86);
721 if (bbg && bbg != bb) {
722 bb->jump = at;
723 if (anal->opt.jmpmid && is_x86) {
724 // This happens when we purposefully walked over another block and overlapped it
725 // and now we hit an offset where the instructions match again.
726 // So we need to split the overwalked block.
727 RAnalBlock *split = r_anal_block_split (bbg, at);
728 r_anal_block_unref (split);
729 }
730 overlapped = true;
731 if (anal->verbose) {
732 eprintf ("Overlapped at 0x%08"PFMT64x "\n", at);
733 }
734 }
735 }
736 if (!overlapped) {
737 const ut64 newbbsize = bb->size + oplen;
738 if (newbbsize > MAX_FCN_SIZE) {
739 gotoBeach (R_ANAL_RET_ERROR);
740 }
741 r_anal_bb_set_offset (bb, bb->ninstr++, at - bb->addr);
742 r_anal_block_set_size (bb, newbbsize);
743 fcn->ninstr++;
744 }
745 if (anal->opt.trycatch) {
746 const char *name = anal->coreb.getName (anal->coreb.core, at);
747 if (name) {
748 if (r_str_startswith (name, "try.") && r_str_endswith (name, ".from")) {
749 char *handle = strdup (name);
750 // handle = r_str_replace (handle, ".from", ".to", 0);
751 ut64 from_addr = anal->coreb.numGet (anal->coreb.core, handle);
752 handle = r_str_replace (handle, ".from", ".catch", 0);
753 ut64 handle_addr = anal->coreb.numGet (anal->coreb.core, handle);
754 bb->jump = at + oplen;
755 if (from_addr != bb->addr) {
756 bb->fail = handle_addr;
757 ret = r_anal_fcn_bb (anal, fcn, handle_addr, depth - 1);
758 eprintf ("(%s) 0x%08"PFMT64x"\n", handle, handle_addr);
759 if (bb->size == 0) {
760 r_anal_function_remove_block (fcn, bb);
761 }
762 r_anal_block_unref (bb);
763 bb = fcn_append_basic_block (anal, fcn, addr);
764 if (!bb) {
765 gotoBeach (R_ANAL_RET_ERROR);
766 }
767 }
768 }
769 }
770 }
771 idx += oplen;
772 delay.un_idx = idx;
773 if (anal->opt.delay && op->delay > 0 && !delay.pending) {
774 // Handle first pass through a branch delay jump:
775 // Come back and handle the current instruction later.
776 // Save the location of it in `delay.idx`
777 // note, we have still increased size of basic block
778 // (and function)
779 if (anal->verbose) {
780 eprintf("Enter branch delay at 0x%08"PFMT64x ". bb->sz=%"PFMT64u"\n", at - oplen, bb->size);
781 }
782 delay.idx = idx - oplen;
783 delay.cnt = op->delay;
784 delay.pending = 1; // we need this in case the actual idx is zero...
785 delay.adjust = !overlapped; // adjustment is required later to avoid double count
786 continue;
787 }
788
789 if (delay.cnt > 0) {
790 // if we had passed a branch delay instruction, keep
791 // track of how many still to process.
792 delay.cnt--;
793 if (!delay.cnt) {
794 if (anal->verbose) {
795 eprintf("Last branch delayed opcode at 0x%08"PFMT64x ". bb->sz=%"PFMT64u"\n", addr + idx - oplen, bb->size);
796 }
797 delay.after = idx;
798 idx = delay.idx;
799 // At this point, we are still looking at the
800 // last instruction in the branch delay group.
801 // Next time, we will again be looking
802 // at the original instruction that entered
803 // the branch delay.
804 }
805 } else if (op->delay > 0 && delay.pending) {
806 if (anal->verbose) {
807 eprintf ("Revisit branch delay jump at 0x%08"PFMT64x ". bb->sz=%"PFMT64u"\n", addr + idx - oplen, bb->size);
808 }
809 // This is the second pass of the branch delaying opcode
810 // But we also already counted this instruction in the
811 // size of the current basic block, so we need to fix that
812 if (delay.adjust) {
813 r_anal_block_set_size (bb, (ut64)addrbytes * (ut64)delay.after);
814 fcn->ninstr--;
815 if (anal->verbose) {
816 eprintf ("Correct for branch delay @ %08"PFMT64x " bb.addr=%08"PFMT64x " corrected.bb=%"PFMT64u" f.uncorr=%"PFMT64u"\n",
817 addr + idx - oplen, bb->addr, bb->size, r_anal_function_linear_size (fcn));
818 }
819 }
820 // Next time, we go to the opcode after the delay count
821 // Take care not to use this below, use delay.un_idx instead ...
822 idx = delay.after;
823 delay.pending = delay.after = delay.idx = delay.adjust = 0;
824 }
825 // Note: if we got two branch delay instructions in a row due to an
826 // compiler bug or junk or something it wont get treated as a delay
827 switch (op->stackop) {
828 case R_ANAL_STACK_INC:
829 if (R_ABS (op->stackptr) < R_ANAL_MAX_INCSTACK) {
830 fcn->stack += op->stackptr;
831 if (fcn->stack > fcn->maxstack) {
832 fcn->maxstack = fcn->stack;
833 }
834 }
835 bb->stackptr += op->stackptr;
836 break;
837 case R_ANAL_STACK_RESET:
838 bb->stackptr = 0;
839 break;
840 default:
841 break;
842 }
843 if (op->ptr && op->ptr != UT64_MAX && op->ptr != UT32_MAX) {
844 // swapped parameters wtf
845 r_anal_xrefs_set (anal, op->addr, op->ptr, R_ANAL_REF_TYPE_DATA);
846 }
847 analyze_retpoline (anal, op);
848 switch (op->type & R_ANAL_OP_TYPE_MASK) {
849 case R_ANAL_OP_TYPE_CMOV:
850 case R_ANAL_OP_TYPE_MOV:
851 last_is_reg_mov_lea = false;
852 if (is_arm) { // mov lr, pc
853 const char *esil = r_strbuf_get (&op->esil);
854 if (!r_str_cmp (esil, "pc,lr,=", -1)) {
855 last_is_mov_lr_pc = true;
856 }
857 }
858 if (has_stack_regs && op_is_set_bp (op, bp_reg, sp_reg)) {
859 fcn->bp_off = fcn->stack;
860 }
861 // Is this a mov of immediate value into a register?
862 if (op->dst && op->dst->reg && op->dst->reg->name && op->val > 0 && op->val != UT64_MAX) {
863 free (last_reg_mov_lea_name);
864 if ((last_reg_mov_lea_name = strdup (op->dst->reg->name))) {
865 last_reg_mov_lea_val = op->val;
866 last_is_reg_mov_lea = true;
867 }
868 }
869 // skip mov reg, reg
870 if (anal->opt.jmptbl) {
871 if (op->scale && op->ireg) {
872 movdisp = op->disp;
873 }
874 }
875 if (anal->opt.hpskip && regs_exist (op->src[0], op->dst) && !strcmp (op->src[0]->reg->name, op->dst->reg->name)) {
876 skip_ret = skip_hp (anal, fcn, op, bb, addr, oplen, delay.un_idx, &idx);
877 if (skip_ret == 1) {
878 goto repeat;
879 }
880 if (skip_ret == 2) {
881 gotoBeach (R_ANAL_RET_END);
882 }
883 }
884 break;
885 case R_ANAL_OP_TYPE_LEA:
886 last_is_reg_mov_lea = false;
887 // if first byte in op->ptr is 0xff, then set leaddr assuming its a jumptable
888 {
889 ut8 buf[4];
890 anal->iob.read_at (anal->iob.io, op->ptr, buf, sizeof (buf));
891 if ((buf[2] == 0xff || buf[2] == 0xfe) && buf[3] == 0xff) {
892 leaddr_pair *pair = R_NEW (leaddr_pair);
893 if (!pair) {
894 eprintf ("Cannot create leaddr_pair\n");
895 gotoBeach (R_ANAL_RET_ERROR);
896 }
897 pair->op_addr = op->addr;
898 pair->leaddr = op->ptr; // XXX movdisp is dupped but seems to be trashed sometimes(?), better track leaddr separately
899 r_list_append (anal->leaddrs, pair);
900 }
901 if (has_stack_regs && op_is_set_bp (op, bp_reg, sp_reg)) {
902 fcn->bp_off = fcn->stack - op->src[0]->delta;
903 }
904 if (op->dst && op->dst->reg && op->dst->reg->name && op->ptr > 0 && op->ptr != UT64_MAX) {
905 free (last_reg_mov_lea_name);
906 if ((last_reg_mov_lea_name = strdup (op->dst->reg->name))) {
907 last_reg_mov_lea_val = op->ptr;
908 last_is_reg_mov_lea = true;
909 }
910 }
911 }
912 // skip lea reg,[reg]
913 if (anal->opt.hpskip && regs_exist (op->src[0], op->dst)
914 && !strcmp (op->src[0]->reg->name, op->dst->reg->name)) {
915 skip_ret = skip_hp (anal, fcn, op, bb, at, oplen, delay.un_idx, &idx);
916 if (skip_ret == 1) {
917 goto repeat;
918 }
919 if (skip_ret == 2) {
920 gotoBeach (R_ANAL_RET_END);
921 }
922 }
923 if (anal->opt.jmptbl) {
924 RAnalOp *jmp_aop = r_anal_op_new ();
925 ut64 jmptbl_addr = op->ptr;
926 ut64 casetbl_addr = op->ptr;
927 if (is_delta_pointer_table (anal, fcn, op->addr, op->ptr, &jmptbl_addr, &casetbl_addr, jmp_aop)) {
928 ut64 table_size, default_case = 0;
929 // we require both checks here since try_get_jmptbl_info uses
930 // BB info of the final jmptbl jump, which is no present with
931 // is_delta_pointer_table just scanning ahead
932 // try_get_delta_jmptbl_info doesn't work at times where the
933 // lea comes after the cmp/default case cjmp, which can be
934 // handled with try_get_jmptbl_info
935 ut64 addr = jmp_aop->addr;
936 if (try_get_jmptbl_info (anal, fcn, addr, bb, &table_size, &default_case)
937 || try_get_delta_jmptbl_info (anal, fcn, addr, op->addr, &table_size, &default_case)) {
938 // TODO: -1-
939 ret = casetbl_addr == op->ptr
940 ? try_walkthrough_jmptbl (anal, fcn, bb, depth, addr, jmptbl_addr, op->ptr, 4, table_size, default_case, 4)
941 : try_walkthrough_casetbl (anal, fcn, bb, depth, addr, jmptbl_addr, casetbl_addr, op->ptr, 4, table_size, default_case, 4);
942 if (ret) {
943 lea_jmptbl_ip = addr;
944 }
945 }
946 }
947 r_anal_op_free (jmp_aop);
948 }
949 break;
950 case R_ANAL_OP_TYPE_LOAD:
951 if (anal->opt.loads) {
952 if (anal->iob.is_valid_offset (anal->iob.io, op->ptr, 0)) {
953 r_meta_set (anal, R_META_TYPE_DATA, op->ptr, 4, "");
954 }
955 }
956 break;
957 // Case of valid but unused "add [rax], al"
958 case R_ANAL_OP_TYPE_ADD:
959 if (anal->opt.ijmp) {
960 if ((op->size + 4 <= bytes_read) && !memcmp (buf + op->size, "\x00\x00\x00\x00", 4)) {
961 r_anal_block_set_size (bb, bb->size - oplen);
962 op->type = R_ANAL_OP_TYPE_RET;
963 gotoBeach (R_ANAL_RET_END);
964 }
965 }
966 break;
967 case R_ANAL_OP_TYPE_ILL:
968 gotoBeach (R_ANAL_RET_END);
969 case R_ANAL_OP_TYPE_TRAP:
970 gotoBeach (R_ANAL_RET_END);
971 case R_ANAL_OP_TYPE_NOP:
972 // do nothing, because the nopskip goes before this switch
973 break;
974 case R_ANAL_OP_TYPE_JMP:
975 if (op->jump == UT64_MAX) {
976 gotoBeach (R_ANAL_RET_END);
977 }
978 {
979 RFlagItem *fi = anal->flb.get_at (anal->flb.f, op->jump, false);
980 if (fi && strstr (fi->name, "imp.")) {
981 gotoBeach (R_ANAL_RET_END);
982 }
983 }
984 if (r_cons_is_breaked ()) {
985 gotoBeach (R_ANAL_RET_END);
986 }
987 if (anal->opt.jmpref) {
988 (void) r_anal_xrefs_set (anal, op->addr, op->jump, R_ANAL_REF_TYPE_CODE);
989 }
990 if (!anal->opt.jmpabove && (op->jump < fcn->addr)) {
991 gotoBeach (R_ANAL_RET_END);
992 }
993 if (r_anal_noreturn_at (anal, op->jump)) {
994 gotoBeach (R_ANAL_RET_END);
995 }
996 {
997 bool must_eob = true;
998 RIOMap *map = anal->iob.map_get (anal->iob.io, addr);
999 if (map) {
1000 must_eob = ( ! r_io_map_contain (map, op->jump) );
1001 }
1002 if (must_eob) {
1003 op->jump = UT64_MAX;
1004 gotoBeach (R_ANAL_RET_END);
1005 }
1006 }
1007 #if FIX_JMP_FWD
1008 bb->jump = op->jump;
1009 bb->fail = UT64_MAX;
1010 FITFCNSZ ();
1011 gotoBeach (R_ANAL_RET_END);
1012 #else
1013 if (!overlapped) {
1014 bb->jump = op->jump;
1015 bb->fail = UT64_MAX;
1016 }
1017 // -1
1018 ret = r_anal_fcn_bb (anal, fcn, op->jump, depth);
1019 int tc = anal->opt.tailcall;
1020 if (tc) {
1021 // eprintf ("TAIL CALL AT 0x%llx\n", op->addr);
1022 int diff = op->jump - op->addr;
1023 if (tc < 0) {
1024 ut8 buf[32];
1025 (void)anal->iob.read_at (anal->iob.io, op->jump, (ut8 *) buf, sizeof (buf));
1026 if (r_anal_is_prelude (anal, buf, sizeof (buf))) {
1027 fcn_recurse (anal, fcn, op->jump, anal->opt.bb_max_size, depth - 1);
1028 }
1029 } else if (R_ABS (diff) > tc) {
1030 (void) r_anal_xrefs_set (anal, op->addr, op->jump, R_ANAL_REF_TYPE_CALL);
1031 fcn_recurse (anal, fcn, op->jump, anal->opt.bb_max_size, depth - 1);
1032 gotoBeach (R_ANAL_RET_END);
1033 }
1034 }
1035 goto beach;
1036 #endif
1037 break;
1038 case R_ANAL_OP_TYPE_SUB:
1039 if (op->val != UT64_MAX && op->val > 0) {
1040 // if register is not stack
1041 cmpval = op->val;
1042 }
1043 break;
1044 case R_ANAL_OP_TYPE_CMP: {
1045 ut64 val = is_x86 ? op->val : op->ptr;
1046 if (val) {
1047 cmpval = val;
1048 bb->cmpval = cmpval;
1049 bb->cmpreg = op->reg;
1050 r_anal_cond_free (bb->cond);
1051 bb->cond = r_anal_cond_new_from_op (op);
1052 }
1053 }
1054 break;
1055 case R_ANAL_OP_TYPE_CJMP:
1056 case R_ANAL_OP_TYPE_MCJMP:
1057 case R_ANAL_OP_TYPE_RCJMP:
1058 case R_ANAL_OP_TYPE_UCJMP:
1059 if (anal->opt.cjmpref) {
1060 (void) r_anal_xrefs_set (anal, op->addr, op->jump, R_ANAL_REF_TYPE_CODE);
1061 }
1062 if (!overlapped) {
1063 bb->jump = op->jump;
1064 bb->fail = op->fail;
1065 }
1066 if (bb->cond) {
1067 bb->cond->type = op->cond;
1068 }
1069 if (anal->opt.jmptbl) {
1070 if (op->ptr != UT64_MAX) {
1071 ut64 table_size, default_case;
1072 table_size = cmpval + 1;
1073 default_case = op->fail; // is this really default case?
1074 if (cmpval != UT64_MAX && default_case != UT64_MAX && (op->reg || op->ireg)) {
1075 // TODO -1
1076 if (op->ireg) {
1077 ret = try_walkthrough_jmptbl (anal, fcn, bb, depth, op->addr, op->ptr, op->ptr, anal->bits >> 3, table_size, default_case, ret);
1078 } else { // op->reg
1079 ret = walkthrough_arm_jmptbl_style (anal, fcn, bb, depth, op->addr, op->ptr, anal->bits >> 3, table_size, default_case, ret);
1080 }
1081 // check if op->jump and op->fail contain jump table location
1082 // clear jump address, because it's jump table location
1083 if (op->jump == op->ptr) {
1084 op->jump = UT64_MAX;
1085 } else if (op->fail == op->ptr) {
1086 op->fail = UT64_MAX;
1087 }
1088 cmpval = UT64_MAX;
1089 }
1090 }
1091 }
1092 int saved_stack = fcn->stack;
1093 // TODO: depth -1 in here
1094 if (continue_after_jump) {
1095 r_anal_fcn_bb (anal, fcn, op->jump, depth);
1096 fcn->stack = saved_stack;
1097 ret = r_anal_fcn_bb (anal, fcn, op->fail, depth);
1098 fcn->stack = saved_stack;
1099 } else {
1100 ret = r_anal_fcn_bb (anal, fcn, op->jump, depth);
1101 fcn->stack = saved_stack;
1102 ret = r_anal_fcn_bb (anal, fcn, op->fail, depth);
1103 fcn->stack = saved_stack;
1104 if (op->jump < fcn->addr) {
1105 if (!overlapped) {
1106 bb->jump = op->jump;
1107 bb->fail = UT64_MAX;
1108 }
1109 gotoBeach (R_ANAL_RET_END);
1110 }
1111 }
1112
1113 // XXX breaks mips analysis too !op->delay
1114 // this will be all x86, arm (at least)
1115 // without which the analysis is really slow,
1116 // presumably because each opcode would get revisited
1117 // (and already covered by a bb) many times
1118 goto beach;
1119 // For some reason, branch delayed code (MIPS) needs to continue
1120 break;
1121 case R_ANAL_OP_TYPE_UCALL:
1122 case R_ANAL_OP_TYPE_RCALL:
1123 case R_ANAL_OP_TYPE_ICALL:
1124 case R_ANAL_OP_TYPE_IRCALL:
1125 /* call [dst] */
1126 // XXX: this is TYPE_MCALL or indirect-call
1127 (void) r_anal_xrefs_set (anal, op->addr, op->ptr, R_ANAL_REF_TYPE_CALL);
1128
1129 if (r_anal_noreturn_at (anal, op->ptr)) {
1130 RAnalFunction *f = r_anal_get_function_at (anal, op->ptr);
1131 if (f) {
1132 f->is_noreturn = true;
1133 }
1134 gotoBeach (R_ANAL_RET_END);
1135 }
1136 break;
1137 case R_ANAL_OP_TYPE_CCALL:
1138 case R_ANAL_OP_TYPE_CALL:
1139 /* call dst */
1140 (void) r_anal_xrefs_set (anal, op->addr, op->jump, R_ANAL_REF_TYPE_CALL);
1141
1142 if (r_anal_noreturn_at (anal, op->jump)) {
1143 RAnalFunction *f = r_anal_get_function_at (anal, op->jump);
1144 if (f) {
1145 f->is_noreturn = true;
1146 }
1147 gotoBeach (R_ANAL_RET_END);
1148 }
1149 break;
1150 case R_ANAL_OP_TYPE_UJMP:
1151 case R_ANAL_OP_TYPE_RJMP:
1152 if (is_arm && last_is_mov_lr_pc) {
1153 break;
1154 }
1155 /* fall through */
1156 case R_ANAL_OP_TYPE_MJMP:
1157 case R_ANAL_OP_TYPE_IJMP:
1158 case R_ANAL_OP_TYPE_IRJMP:
1159 // if the next instruction is a symbol
1160 if (anal->opt.ijmp && isSymbolNextInstruction (anal, op)) {
1161 gotoBeach (R_ANAL_RET_END);
1162 }
1163 // switch statement
1164 if (anal->opt.jmptbl && lea_jmptbl_ip != op->addr) {
1165 ut8 buf[32]; // 32 bytes is enough to hold any instruction.
1166 // op->ireg since rip relative addressing produces way too many false positives otherwise
1167 // op->ireg is 0 for rip relative, "rax", etc otherwise
1168 if (op->ptr != UT64_MAX && op->ireg) { // direct jump
1169 ut64 table_size, default_case;
1170 if (try_get_jmptbl_info (anal, fcn, op->addr, bb, &table_size, &default_case)) {
1171 bool case_table = false;
1172 RAnalOp *prev_op = r_anal_op_new ();
1173 anal->iob.read_at (anal->iob.io, op->addr - op->size, buf, sizeof (buf));
1174 if (r_anal_op (anal, prev_op, op->addr - op->size, buf, sizeof (buf), R_ANAL_OP_MASK_VAL) > 0) {
1175 bool prev_op_has_dst_name = prev_op->dst && prev_op->dst->reg && prev_op->dst->reg->name;
1176 bool op_has_src_name = op->src[0] && op->src[0]->reg && op->src[0]->reg->name;
1177 bool same_reg = (op->ireg && prev_op_has_dst_name && !strcmp (op->ireg, prev_op->dst->reg->name))
1178 || (op_has_src_name && prev_op_has_dst_name && !strcmp (op->src[0]->reg->name, prev_op->dst->reg->name));
1179 if (prev_op->type == R_ANAL_OP_TYPE_MOV && prev_op->disp && prev_op->disp != UT64_MAX && same_reg) {
1180 // movzx reg, byte [reg + case_table]
1181 // jmp dword [reg*4 + jump_table]
1182 if (try_walkthrough_casetbl (anal, fcn, bb, depth - 1, op->addr, op->ptr, prev_op->disp, op->ptr, anal->bits >> 3, table_size, default_case, ret)) {
1183 ret = case_table = true;
1184 }
1185 }
1186 }
1187 r_anal_op_free (prev_op);
1188 if (!case_table) {
1189 ret = try_walkthrough_jmptbl (anal, fcn, bb, depth, op->addr, op->ptr, op->ptr, anal->bits >> 3, table_size, default_case, ret);
1190 }
1191 }
1192 } else if (op->ptr != UT64_MAX && op->reg) { // direct jump
1193 ut64 table_size, default_case;
1194 if (try_get_jmptbl_info (anal, fcn, op->addr, bb, &table_size, &default_case)) {
1195 ret = try_walkthrough_jmptbl (anal, fcn, bb, depth - 1, op->addr, op->ptr, op->ptr, anal->bits >> 3, table_size, default_case, ret);
1196 }
1197 } else if (movdisp == 0) {
1198 ut64 jmptbl_base = UT64_MAX;
1199 ut64 lea_op_off = UT64_MAX;
1200 RListIter *lea_op_iter = NULL;
1201 RListIter *iter;
1202 leaddr_pair *pair;
1203 // find nearest candidate leaddr before op->addr
1204 r_list_foreach (anal->leaddrs, iter, pair) {
1205 if (pair->op_addr >= op->addr) {
1206 continue;
1207 }
1208 if (lea_op_off == UT64_MAX || lea_op_off > op->addr - pair->op_addr) {
1209 lea_op_off = op->addr - pair->op_addr;
1210 jmptbl_base = pair->leaddr;
1211 lea_op_iter = iter;
1212 }
1213 }
1214 if (lea_op_iter) {
1215 r_list_delete (anal->leaddrs, lea_op_iter);
1216 }
1217 ut64 table_size = cmpval + 1;
1218 ret = try_walkthrough_jmptbl (anal, fcn, bb, depth - 1, op->addr, jmptbl_base, jmptbl_base, 4, table_size, -1, ret);
1219 cmpval = UT64_MAX;
1220 } else if (movdisp != UT64_MAX) {
1221 ut64 table_size, default_case;
1222
1223 if (try_get_jmptbl_info (anal, fcn, op->addr, bb, &table_size, &default_case)) {
1224 op->ptr = movdisp;
1225 ret = try_walkthrough_jmptbl (anal, fcn, bb, depth - 1, op->addr, op->ptr, op->ptr, anal->bits >> 3, table_size, default_case, ret);
1226 }
1227 movdisp = UT64_MAX;
1228 } else if (is_arm) {
1229 if (op->ptrsize == 1) { // TBB
1230 ut64 pred_cmpval = try_get_cmpval_from_parents(anal, fcn, bb, op->ireg);
1231 ut64 table_size = 0;
1232 if (pred_cmpval != UT64_MAX) {
1233 table_size += pred_cmpval;
1234 } else {
1235 table_size += cmpval;
1236 }
1237 ret = try_walkthrough_jmptbl (anal, fcn, bb, depth - 1, op->addr, op->addr + op->size,
1238 op->addr + 4, 1, table_size, UT64_MAX, ret);
1239 // skip inlined jumptable
1240 idx += table_size;
1241 }
1242 if (op->ptrsize == 2) { // LDRH on thumb/arm
1243 ut64 pred_cmpval = try_get_cmpval_from_parents(anal, fcn, bb, op->ireg);
1244 int tablesize = 1;
1245 if (pred_cmpval != UT64_MAX) {
1246 tablesize += pred_cmpval;
1247 } else {
1248 tablesize += cmpval;
1249 }
1250 ret = try_walkthrough_jmptbl (anal, fcn, bb, depth - 1, op->addr, op->addr + op->size,
1251 op->addr + 4, 2, tablesize, UT64_MAX, ret);
1252 // skip inlined jumptable
1253 idx += (tablesize * 2);
1254 }
1255 }
1256 }
1257 if (lea_jmptbl_ip == op->addr) {
1258 lea_jmptbl_ip = UT64_MAX;
1259 }
1260 if (anal->opt.ijmp) {
1261 if (continue_after_jump) {
1262 r_anal_fcn_bb (anal, fcn, op->jump, depth - 1);
1263 ret = r_anal_fcn_bb (anal, fcn, op->fail, depth - 1);
1264 if (overlapped) {
1265 goto analopfinish;
1266 }
1267 }
1268 if (r_anal_noreturn_at (anal, op->jump) || op->eob) {
1269 goto analopfinish;
1270 }
1271 } else {
1272 analopfinish:
1273 if (op->type == R_ANAL_OP_TYPE_RJMP) {
1274 gotoBeach (R_ANAL_RET_NOP);
1275 } else {
1276 gotoBeach (R_ANAL_RET_END);
1277 }
1278 }
1279 break;
1280 /* fallthru */
1281 case R_ANAL_OP_TYPE_PUSH:
1282 last_is_push = true;
1283 last_push_addr = op->val;
1284 if (anal->iob.is_valid_offset (anal->iob.io, last_push_addr, 1)) {
1285 (void) r_anal_xrefs_set (anal, op->addr, last_push_addr, R_ANAL_REF_TYPE_DATA);
1286 }
1287 break;
1288 case R_ANAL_OP_TYPE_UPUSH:
1289 if ((op->type & R_ANAL_OP_TYPE_REG) && last_is_reg_mov_lea && op->src[0] && op->src[0]->reg
1290 && op->src[0]->reg->name && !strcmp (op->src[0]->reg->name, last_reg_mov_lea_name)) {
1291 last_is_push = true;
1292 last_push_addr = last_reg_mov_lea_val;
1293 if (anal->iob.is_valid_offset (anal->iob.io, last_push_addr, 1)) {
1294 (void) r_anal_xrefs_set (anal, op->addr, last_push_addr, R_ANAL_REF_TYPE_DATA);
1295 }
1296 }
1297 break;
1298 case R_ANAL_OP_TYPE_RET:
1299 if (op->family == R_ANAL_OP_FAMILY_PRIV) {
1300 fcn->type = R_ANAL_FCN_TYPE_INT;
1301 }
1302 if (last_is_push && anal->opt.pushret) {
1303 op->type = R_ANAL_OP_TYPE_JMP;
1304 op->jump = last_push_addr;
1305 bb->jump = op->jump;
1306 ret = r_anal_fcn_bb (anal, fcn, op->jump, depth - 1);
1307 goto beach;
1308 }
1309 if (!op->cond) {
1310 if (anal->verbose) {
1311 eprintf ("RET 0x%08"PFMT64x ". overlap=%s %"PFMT64u" %"PFMT64u"\n",
1312 addr + delay.un_idx - oplen, r_str_bool (overlapped),
1313 bb->size, r_anal_function_linear_size (fcn));
1314 }
1315 gotoBeach (R_ANAL_RET_END);
1316 }
1317 break;
1318 }
1319 if (has_stack_regs && arch_destroys_dst) {
1320 if (op_is_set_bp (op, bp_reg, sp_reg) && op->src[1]) {
1321 switch (op->type & R_ANAL_OP_TYPE_MASK) {
1322 case R_ANAL_OP_TYPE_ADD:
1323 fcn->bp_off = fcn->stack - op->src[1]->imm;
1324 break;
1325 case R_ANAL_OP_TYPE_SUB:
1326 fcn->bp_off = fcn->stack + op->src[1]->imm;
1327 break;
1328 }
1329 }
1330 }
1331 if (anal->opt.vars && !varset) {
1332 r_anal_extract_vars (anal, fcn, op);
1333 }
1334 if (op->type != R_ANAL_OP_TYPE_MOV && op->type != R_ANAL_OP_TYPE_CMOV && op->type != R_ANAL_OP_TYPE_LEA) {
1335 last_is_reg_mov_lea = false;
1336 }
1337 if (op->type != R_ANAL_OP_TYPE_PUSH && op->type != R_ANAL_OP_TYPE_RPUSH) {
1338 last_is_push = false;
1339 }
1340 if (is_arm && op->type != R_ANAL_OP_TYPE_MOV) {
1341 last_is_mov_lr_pc = false;
1342 }
1343 if (has_variadic_reg && !fcn->is_variadic) {
1344 variadic_reg = r_reg_get (anal->reg, "rax", R_REG_TYPE_GPR);
1345 bool dst_is_variadic = op->dst && op->dst->reg
1346 && variadic_reg && op->dst->reg->offset == variadic_reg->offset;
1347 bool op_is_cmp = (op->type == R_ANAL_OP_TYPE_CMP) || op->type == R_ANAL_OP_TYPE_ACMP;
1348 if (dst_is_variadic && !op_is_cmp) {
1349 has_variadic_reg = false;
1350 } else if (op_is_cmp) {
1351 if (op->src[0] && op->src[0]->reg && (op->dst->reg == op->src[0]->reg) && dst_is_variadic) {
1352 fcn->is_variadic = true;
1353 }
1354 }
1355 }
1356 }
1357 beach:
1358 r_anal_op_free (op);
1359 R_FREE (last_reg_mov_lea_name);
1360 if (bb && bb->size == 0) {
1361 r_anal_function_remove_block (fcn, bb);
1362 }
1363 r_anal_block_update_hash (bb);
1364 r_anal_block_unref (bb);
1365 return ret;
1366 }
1367
r_anal_fcn_bb(RAnal * anal,RAnalFunction * fcn,ut64 addr,int depth)1368 R_API int r_anal_fcn_bb(RAnal *anal, RAnalFunction *fcn, ut64 addr, int depth) {
1369 return fcn_recurse (anal, fcn, addr, anal->opt.bb_max_size, depth - 1);
1370 }
1371
r_anal_check_fcn(RAnal * anal,ut8 * buf,ut16 bufsz,ut64 addr,ut64 low,ut64 high)1372 R_API bool r_anal_check_fcn(RAnal *anal, ut8 *buf, ut16 bufsz, ut64 addr, ut64 low, ut64 high) {
1373 RAnalOp op = {
1374 0
1375 };
1376 int i, oplen, opcnt = 0, pushcnt = 0, movcnt = 0, brcnt = 0;
1377 if (r_anal_is_prelude (anal, buf, bufsz)) {
1378 return true;
1379 }
1380 for (i = 0; i < bufsz && opcnt < 10; i += oplen, opcnt++) {
1381 r_anal_op_fini (&op);
1382 if ((oplen = r_anal_op (anal, &op, addr + i, buf + i, bufsz - i, R_ANAL_OP_MASK_BASIC | R_ANAL_OP_MASK_HINT)) < 1) {
1383 return false;
1384 }
1385 switch (op.type) {
1386 case R_ANAL_OP_TYPE_PUSH:
1387 case R_ANAL_OP_TYPE_UPUSH:
1388 case R_ANAL_OP_TYPE_RPUSH:
1389 pushcnt++;
1390 break;
1391 case R_ANAL_OP_TYPE_MOV:
1392 case R_ANAL_OP_TYPE_CMOV:
1393 movcnt++;
1394 break;
1395 case R_ANAL_OP_TYPE_JMP:
1396 case R_ANAL_OP_TYPE_CJMP:
1397 case R_ANAL_OP_TYPE_CALL:
1398 if (op.jump < low || op.jump >= high) {
1399 return false;
1400 }
1401 brcnt++;
1402 break;
1403 case R_ANAL_OP_TYPE_UNK:
1404 return false;
1405 default:
1406 break;
1407 }
1408 }
1409 return (pushcnt + movcnt + brcnt > 5);
1410 }
1411
r_anal_trim_jmprefs(RAnal * anal,RAnalFunction * fcn)1412 R_API void r_anal_trim_jmprefs(RAnal *anal, RAnalFunction *fcn) {
1413 RAnalRef *ref;
1414 RList *refs = r_anal_function_get_refs (fcn);
1415 RListIter *iter;
1416 const bool is_x86 = anal->cur->arch && !strcmp (anal->cur->arch, "x86"); // HACK
1417
1418 r_list_foreach (refs, iter, ref) {
1419 if (ref->type == R_ANAL_REF_TYPE_CODE && r_anal_function_contains (fcn, ref->addr)
1420 && (!is_x86 || !r_anal_function_contains (fcn, ref->at))) {
1421 r_anal_xrefs_deln (anal, ref->at, ref->addr, ref->type);
1422 }
1423 }
1424 r_list_free (refs);
1425 }
1426
r_anal_del_jmprefs(RAnal * anal,RAnalFunction * fcn)1427 R_API void r_anal_del_jmprefs(RAnal *anal, RAnalFunction *fcn) {
1428 RAnalRef *ref;
1429 RList *refs = r_anal_function_get_refs (fcn);
1430 RListIter *iter;
1431
1432 r_list_foreach (refs, iter, ref) {
1433 if (ref->type == R_ANAL_REF_TYPE_CODE) {
1434 r_anal_xrefs_deln (anal, ref->at, ref->addr, ref->type);
1435 }
1436 }
1437 r_list_free (refs);
1438 }
1439
1440 /* Does NOT invalidate read-ahead cache. */
r_anal_fcn(RAnal * anal,RAnalFunction * fcn,ut64 addr,ut64 len,int reftype)1441 R_API int r_anal_fcn(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut64 len, int reftype) {
1442 RPVector *metas = r_meta_get_all_in(anal, addr, R_META_TYPE_ANY);
1443 void **it;
1444 r_pvector_foreach (metas, it) {
1445 RAnalMetaItem *meta = ((RIntervalNode *)*it)->data;
1446 switch (meta->type) {
1447 case R_META_TYPE_DATA:
1448 case R_META_TYPE_STRING:
1449 case R_META_TYPE_FORMAT:
1450 r_pvector_free (metas);
1451 return 0;
1452 default:
1453 break;
1454 }
1455 }
1456 r_pvector_free (metas);
1457 if (anal->opt.norevisit) {
1458 if (!anal->visited) {
1459 anal->visited = set_u_new ();
1460 }
1461 if (set_u_contains (anal->visited, addr)) {
1462 eprintf ("r_anal_fcn: anal.norevisit at 0x%08"PFMT64x" %c\n", addr, reftype);
1463 return R_ANAL_RET_END;
1464 }
1465 set_u_add (anal->visited, addr);
1466 } else {
1467 if (anal->visited) {
1468 set_u_free (anal->visited);
1469 anal->visited = NULL;
1470 }
1471 }
1472 /* defines fcn. or loc. prefix */
1473 fcn->type = (reftype == R_ANAL_REF_TYPE_CODE) ? R_ANAL_FCN_TYPE_LOC : R_ANAL_FCN_TYPE_FCN;
1474 if (fcn->addr == UT64_MAX) {
1475 fcn->addr = addr;
1476 }
1477 fcn->maxstack = 0;
1478 if (fcn->cc && !strcmp (fcn->cc, "ms")) {
1479 // Probably should put this on the cc sdb
1480 const int shadow_store = 0x28; // First 4 args + retaddr
1481 fcn->stack = fcn->maxstack = fcn->reg_save_area = shadow_store;
1482 }
1483 // XXX -1 here results in lots of errors
1484 int ret = r_anal_fcn_bb (anal, fcn, addr, anal->opt.depth);
1485 if (ret < 0) {
1486 if (anal->verbose) {
1487 eprintf ("Failed to analyze basic block at 0x%"PFMT64x"\n", addr);
1488 }
1489 }
1490 if (anal->opt.endsize && ret == R_ANAL_RET_END && r_anal_function_realsize (fcn)) { // cfg analysis completed
1491 RListIter *iter;
1492 RAnalBlock *bb;
1493 ut64 endaddr = fcn->addr;
1494 const bool is_x86 = anal->cur->arch && !strcmp (anal->cur->arch, "x86");
1495
1496 // set function size as length of continuous sequence of bbs
1497 r_list_sort (fcn->bbs, &cmpaddr);
1498 r_list_foreach (fcn->bbs, iter, bb) {
1499 if (endaddr == bb->addr) {
1500 endaddr += bb->size;
1501 } else if ((endaddr < bb->addr && bb->addr - endaddr < BB_ALIGN)
1502 || (anal->opt.jmpmid && is_x86 && endaddr > bb->addr
1503 && bb->addr + bb->size > endaddr)) {
1504 endaddr = bb->addr + bb->size;
1505 } else {
1506 break;
1507 }
1508 }
1509 #if JAYRO_04
1510 // fcn is not yet in anal => pass NULL
1511 r_anal_function_resize (fcn, endaddr - fcn->addr);
1512 #endif
1513 r_anal_trim_jmprefs (anal, fcn);
1514 }
1515 return ret;
1516 }
1517
1518 // XXX deprecate
r_anal_fcn_del_locs(RAnal * anal,ut64 addr)1519 R_API int r_anal_fcn_del_locs(RAnal *anal, ut64 addr) {
1520 RListIter *iter, *iter2;
1521 RAnalFunction *fcn, *f = r_anal_get_fcn_in (anal, addr, R_ANAL_FCN_TYPE_ROOT);
1522 if (!f) {
1523 return false;
1524 }
1525 r_list_foreach_safe (anal->fcns, iter, iter2, fcn) {
1526 if (fcn->type != R_ANAL_FCN_TYPE_LOC) {
1527 continue;
1528 }
1529 if (r_anal_function_contains (fcn, addr)) {
1530 r_anal_function_delete (fcn);
1531 }
1532 }
1533 r_anal_fcn_del (anal, addr);
1534 return true;
1535 }
1536
r_anal_fcn_del(RAnal * a,ut64 addr)1537 R_API int r_anal_fcn_del(RAnal *a, ut64 addr) {
1538 RAnalFunction *fcn;
1539 RListIter *iter, *iter_tmp;
1540 r_list_foreach_safe (a->fcns, iter, iter_tmp, fcn) {
1541 D eprintf ("fcn at %llx %llx\n", fcn->addr, addr);
1542 if (fcn->addr == addr) {
1543 r_anal_function_delete (fcn);
1544 }
1545 }
1546 return true;
1547 }
1548
r_anal_get_fcn_in(RAnal * anal,ut64 addr,int type)1549 R_API RAnalFunction *r_anal_get_fcn_in(RAnal *anal, ut64 addr, int type) {
1550 RList *list = r_anal_get_functions_in (anal, addr);
1551 RAnalFunction *ret = NULL;
1552 if (list && !r_list_empty (list)) {
1553 if (type == R_ANAL_FCN_TYPE_ROOT) {
1554 RAnalFunction *fcn;
1555 RListIter *iter;
1556 r_list_foreach (list, iter, fcn) {
1557 if (fcn->addr == addr) {
1558 ret = fcn;
1559 break;
1560 }
1561 }
1562 } else {
1563 ret = r_list_first (list);
1564 }
1565 }
1566 r_list_free (list);
1567 return ret;
1568 }
1569
r_anal_get_fcn_in_bounds(RAnal * anal,ut64 addr,int type)1570 R_API RAnalFunction *r_anal_get_fcn_in_bounds(RAnal *anal, ut64 addr, int type) {
1571 RAnalFunction *fcn, *ret = NULL;
1572 RListIter *iter;
1573 if (type == R_ANAL_FCN_TYPE_ROOT) {
1574 r_list_foreach (anal->fcns, iter, fcn) {
1575 if (addr == fcn->addr) {
1576 return fcn;
1577 }
1578 }
1579 return NULL;
1580 }
1581 r_list_foreach (anal->fcns, iter, fcn) {
1582 if (!type || (fcn && fcn->type & type)) {
1583 if (r_anal_function_contains (fcn, addr)) {
1584 return fcn;
1585 }
1586 }
1587 }
1588 return ret;
1589 }
1590
r_anal_get_function_byname(RAnal * a,const char * name)1591 R_API RAnalFunction *r_anal_get_function_byname(RAnal *a, const char *name) {
1592 bool found = false;
1593 RAnalFunction *f = ht_pp_find (a->ht_name_fun, name, &found);
1594 if (f && found) {
1595 return f;
1596 }
1597 return NULL;
1598 }
1599
1600 /* rename RAnalFunctionBB.add() */
r_anal_fcn_add_bb(RAnal * a,RAnalFunction * fcn,ut64 addr,ut64 size,ut64 jump,ut64 fail,R_BORROW RAnalDiff * diff)1601 R_API bool r_anal_fcn_add_bb(RAnal *a, RAnalFunction *fcn, ut64 addr, ut64 size, ut64 jump, ut64 fail, R_BORROW RAnalDiff *diff) {
1602 D eprintf ("Add bb\n");
1603 if (size == 0) { // empty basic blocks allowed?
1604 eprintf ("Warning: empty basic block at 0x%08"PFMT64x" is not allowed. pending discussion.\n", addr);
1605 r_warn_if_reached ();
1606 return false;
1607 }
1608 if (size > a->opt.bb_max_size) {
1609 eprintf ("Warning: can't allocate such big bb of %"PFMT64d" bytes at 0x%08"PFMT64x"\n", (st64)size, addr);
1610 r_warn_if_reached ();
1611 return false;
1612 }
1613
1614 RAnalBlock *block = r_anal_get_block_at (a, addr);
1615 if (block) {
1616 r_anal_delete_block (block);
1617 block = NULL;
1618 }
1619
1620 const bool is_x86 = a->cur->arch && !strcmp (a->cur->arch, "x86");
1621 // TODO fix this x86-ism
1622 if (is_x86) {
1623 r_anal_fcn_invalidate_read_ahead_cache ();
1624 fcn_recurse (a, fcn, addr, size, 1);
1625 block = r_anal_get_block_at (a, addr);
1626 if (block) {
1627 r_anal_block_set_size (block, size);
1628 }
1629 } else {
1630 block = r_anal_create_block (a, addr, size);
1631 }
1632
1633 if (!block) {
1634 D eprintf ("Warning: r_anal_fcn_add_bb failed in fcn 0x%08"PFMT64x" at 0x%08"PFMT64x"\n", fcn->addr, addr);
1635 return false;
1636 }
1637
1638 r_anal_function_add_block (fcn, block);
1639
1640 block->jump = jump;
1641 block->fail = fail;
1642 block->fail = fail;
1643 if (diff) {
1644 if (!block->diff) {
1645 block->diff = r_anal_diff_new ();
1646 }
1647 if (block->diff) {
1648 block->diff->type = diff->type;
1649 block->diff->addr = diff->addr;
1650 if (diff->name) {
1651 R_FREE (block->diff->name);
1652 block->diff->name = strdup (diff->name);
1653 }
1654 }
1655 }
1656 return true;
1657 }
1658
r_anal_function_loops(RAnalFunction * fcn)1659 R_API int r_anal_function_loops(RAnalFunction *fcn) {
1660 RListIter *iter;
1661 RAnalBlock *bb;
1662 ut32 loops = 0;
1663 r_list_foreach (fcn->bbs, iter, bb) {
1664 if (bb->jump != UT64_MAX && bb->jump < bb->addr) {
1665 loops ++;
1666 }
1667 if (bb->fail != UT64_MAX && bb->fail < bb->addr) {
1668 loops ++;
1669 }
1670 }
1671 return loops;
1672 }
1673
r_anal_function_complexity(RAnalFunction * fcn)1674 R_API int r_anal_function_complexity(RAnalFunction *fcn) {
1675 /*
1676 CC = E - N + 2P
1677 E = the number of edges of the graph.
1678 N = the number of nodes of the graph.
1679 P = the number of connected components (exit nodes).
1680 */
1681 RAnal *anal = fcn->anal;
1682 int E = 0, N = 0, P = 0;
1683 RListIter *iter;
1684 RAnalBlock *bb;
1685
1686 r_list_foreach (fcn->bbs, iter, bb) {
1687 N++; // nodes
1688 if ((!anal || anal->verbose) && bb->jump == UT64_MAX && bb->fail != UT64_MAX) {
1689 eprintf ("Warning: invalid bb jump/fail pair at 0x%08"PFMT64x" (fcn 0x%08"PFMT64x"\n", bb->addr, fcn->addr);
1690 }
1691 if (bb->jump == UT64_MAX && bb->fail == UT64_MAX) {
1692 P++; // exit nodes
1693 } else {
1694 E++; // edges
1695 if (bb->fail != UT64_MAX) {
1696 E++;
1697 }
1698 }
1699 if (bb->switch_op && bb->switch_op->cases) {
1700 E += r_list_length (bb->switch_op->cases);
1701 }
1702 }
1703
1704 int result = E - N + (2 * P);
1705 if (result < 1 && (!anal || anal->verbose)) {
1706 eprintf ("Warning: CC = E(%d) - N(%d) + (2 * P(%d)) < 1 at 0x%08"PFMT64x"\n", E, N, P, fcn->addr);
1707 }
1708 // r_return_val_if_fail (result > 0, 0);
1709 return result;
1710 }
1711
1712 // tfj and afsj call this function
r_anal_function_get_json(RAnalFunction * function)1713 R_API char *r_anal_function_get_json(RAnalFunction *function) {
1714 RAnal *a = function->anal;
1715 PJ *pj = a->coreb.pjWithEncoding (a->coreb.core);
1716
1717 char *args = strdup ("");
1718 char *sdb_ret = r_str_newf ("func.%s.ret", function->name);
1719 char *sdb_args = r_str_newf ("func.%s.args", function->name);
1720 // RList *args_list = r_list_newf ((RListFree) free);
1721 unsigned int i;
1722 const char *ret_type = sdb_const_get (a->sdb_types, sdb_ret, 0);
1723 const char *argc_str = sdb_const_get (a->sdb_types, sdb_args, 0);
1724
1725 int argc = argc_str? atoi (argc_str): 0;
1726
1727 pj_o (pj);
1728 pj_ks (pj, "name", function->name);
1729 const bool no_return = r_anal_noreturn_at_addr (a, function->addr);
1730 pj_kb (pj, "noreturn", no_return);
1731 pj_ks (pj, "ret", r_str_get_fail (ret_type, "void"));
1732 if (function->cc) {
1733 pj_ks (pj, "cc", function->cc);
1734 }
1735 pj_k (pj, "args");
1736 pj_a (pj);
1737 for (i = 0; i < argc; i++) {
1738 pj_o (pj);
1739 char *sdb_arg_i = r_str_newf ("func.%s.arg.%d", function->name, i);
1740 char *arg_i = sdb_get (a->sdb_types, sdb_arg_i, 0);
1741 char *comma = strchr (arg_i, ',');
1742 if (comma) {
1743 *comma = 0;
1744 pj_ks (pj, "name", comma + 1);
1745 pj_ks (pj, "type", arg_i);
1746 const char *cc_arg = r_reg_get_name (a->reg, r_reg_get_name_idx (sdb_fmt ("A%d", i)));
1747 if (cc_arg) {
1748 pj_ks (pj, "cc", cc_arg);
1749 }
1750 }
1751 free (arg_i);
1752 free (sdb_arg_i);
1753 pj_end (pj);
1754 }
1755 pj_end (pj);
1756 free (sdb_args);
1757 free (sdb_ret);
1758 free (args);
1759 pj_end (pj);
1760 return pj_drain (pj);
1761 }
1762
r_anal_function_get_signature(RAnalFunction * function)1763 R_API char *r_anal_function_get_signature(RAnalFunction *function) {
1764 RAnal *a = function->anal;
1765 const char *realname = NULL, *import_substring = NULL;
1766
1767 RFlagItem *flag = a->flag_get (a->flb.f, function->addr);
1768 // Can't access R_FLAGS_FS_IMPORTS, since it is defined in r_core.h
1769 if (flag && flag->space && !strcmp (flag->space->name, "imports")) {
1770 // Get substring after last dot
1771 import_substring = r_str_rchr (function->name, NULL, '.');
1772 if (import_substring) {
1773 realname = import_substring + 1;
1774 }
1775 } else {
1776 realname = function->name;
1777 }
1778
1779 char *ret = NULL, *args = strdup ("");
1780 char *sdb_ret = r_str_newf ("func.%s.ret", realname);
1781 char *sdb_args = r_str_newf ("func.%s.args", realname);
1782 // RList *args_list = r_list_newf ((RListFree) free);
1783 unsigned int i, j;
1784 const char *ret_type = sdb_const_get (a->sdb_types, sdb_ret, 0);
1785 const char *argc_str = sdb_const_get (a->sdb_types, sdb_args, 0);
1786
1787 int argc = argc_str? atoi (argc_str): 0;
1788
1789 for (i = 0; i < argc; i++) {
1790 char *sdb_arg_i = r_str_newf ("func.%s.arg.%d", realname, i);
1791 char *arg_i = sdb_get (a->sdb_types, sdb_arg_i, 0);
1792 // parse commas
1793 int arg_i_len = strlen (arg_i);
1794 for (j = 0; j < arg_i_len; j++) {
1795 if (j > 0 && arg_i[j] == ',') {
1796 if (arg_i[j - 1] == '*') {
1797 // remove whitespace
1798 memmove (arg_i + j, arg_i + j + 1, strlen (arg_i) - j);
1799 } else {
1800 arg_i[j] = ' ';
1801 }
1802 }
1803 }
1804 char *new_args = (i + 1 == argc)
1805 ? r_str_newf ("%s%s", args, arg_i)
1806 : r_str_newf ("%s%s, ", args, arg_i);
1807 free (args);
1808 args = new_args;
1809
1810 free (arg_i);
1811 free (sdb_arg_i);
1812 }
1813 ret = r_str_newf ("%s %s (%s);", r_str_get_fail (ret_type, "void"), realname, args);
1814
1815 free (sdb_args);
1816 free (sdb_ret);
1817 free (args);
1818 return ret;
1819 }
1820
1821 /* set function signature from string */
r_anal_str_to_fcn(RAnal * a,RAnalFunction * f,const char * sig)1822 R_API int r_anal_str_to_fcn(RAnal *a, RAnalFunction *f, const char *sig) {
1823 r_return_val_if_fail (a || f || sig, false);
1824 char *error_msg = NULL;
1825 const char *out = r_parse_c_string (a, sig, &error_msg);
1826 if (out) {
1827 r_anal_save_parsed_type (a, out);
1828 }
1829 if (error_msg) {
1830 eprintf ("%s", error_msg);
1831 free (error_msg);
1832 }
1833
1834 return true;
1835 }
1836
r_anal_fcn_next(RAnal * anal,ut64 addr)1837 R_API RAnalFunction *r_anal_fcn_next(RAnal *anal, ut64 addr) {
1838 RAnalFunction *fcni;
1839 RListIter *iter;
1840 RAnalFunction *closer = NULL;
1841 r_list_foreach (anal->fcns, iter, fcni) {
1842 // if (fcni->addr == addr)
1843 if (fcni->addr > addr && (!closer || fcni->addr < closer->addr)) {
1844 closer = fcni;
1845 }
1846 }
1847 return closer;
1848 }
1849
r_anal_fcn_count(RAnal * anal,ut64 from,ut64 to)1850 R_API int r_anal_fcn_count(RAnal *anal, ut64 from, ut64 to) {
1851 int n = 0;
1852 RAnalFunction *fcni;
1853 RListIter *iter;
1854 r_list_foreach (anal->fcns, iter, fcni) {
1855 if (fcni->addr >= from && fcni->addr < to) {
1856 n++;
1857 }
1858 }
1859 return n;
1860 }
1861
1862 /* return the basic block in fcn found at the given address.
1863 * NULL is returned if such basic block doesn't exist. */
r_anal_fcn_bbget_in(const RAnal * anal,RAnalFunction * fcn,ut64 addr)1864 R_API RAnalBlock *r_anal_fcn_bbget_in(const RAnal *anal, RAnalFunction *fcn, ut64 addr) {
1865 r_return_val_if_fail (anal && fcn, NULL);
1866 if (addr == UT64_MAX) {
1867 return NULL;
1868 }
1869 const bool is_x86 = anal->cur->arch && !strcmp (anal->cur->arch, "x86");
1870 RListIter *iter;
1871 RAnalBlock *bb;
1872 r_list_foreach (fcn->bbs, iter, bb) {
1873 if (addr >= bb->addr && addr < (bb->addr + bb->size)
1874 && (!anal->opt.jmpmid || !is_x86 || r_anal_block_op_starts_at (bb, addr))) {
1875 return bb;
1876 }
1877 }
1878 return NULL;
1879 }
1880
r_anal_fcn_bbget_at(RAnal * anal,RAnalFunction * fcn,ut64 addr)1881 R_API RAnalBlock *r_anal_fcn_bbget_at(RAnal *anal, RAnalFunction *fcn, ut64 addr) {
1882 r_return_val_if_fail (fcn && addr != UT64_MAX, NULL);
1883 RAnalBlock *b = r_anal_get_block_at (anal, addr);
1884 if (b) {
1885 return b;
1886 }
1887 RListIter *iter;
1888 RAnalBlock *bb;
1889 r_list_foreach (fcn->bbs, iter, bb) {
1890 if (addr == bb->addr) {
1891 return bb;
1892 }
1893 }
1894 return NULL;
1895 }
1896
1897 // compute the cyclomatic cost
r_anal_function_cost(RAnalFunction * fcn)1898 R_API ut32 r_anal_function_cost(RAnalFunction *fcn) {
1899 RListIter *iter;
1900 RAnalBlock *bb;
1901 ut32 totalCycles = 0;
1902 if (!fcn) {
1903 return 0;
1904 }
1905 RAnal *anal = fcn->anal;
1906 r_list_foreach (fcn->bbs, iter, bb) {
1907 RAnalOp op;
1908 ut64 at, end = bb->addr + bb->size;
1909 ut8 *buf = malloc (bb->size);
1910 if (!buf) {
1911 continue;
1912 }
1913 (void)anal->iob.read_at (anal->iob.io, bb->addr, (ut8 *) buf, bb->size);
1914 int idx = 0;
1915 for (at = bb->addr; at < end;) {
1916 memset (&op, 0, sizeof (op));
1917 (void) r_anal_op (anal, &op, at, buf + idx, bb->size - idx, R_ANAL_OP_MASK_BASIC);
1918 if (op.size < 1) {
1919 op.size = 1;
1920 }
1921 idx += op.size;
1922 at += op.size;
1923 totalCycles += op.cycles;
1924 r_anal_op_fini (&op);
1925 }
1926 free (buf);
1927 }
1928 return totalCycles;
1929 }
1930
r_anal_function_count_edges(const RAnalFunction * fcn,R_NULLABLE int * ebbs)1931 R_API int r_anal_function_count_edges(const RAnalFunction *fcn, R_NULLABLE int *ebbs) {
1932 r_return_val_if_fail (fcn, 0);
1933 RListIter *iter;
1934 RAnalBlock *bb;
1935 int edges = 0;
1936 if (ebbs) {
1937 *ebbs = 0;
1938 }
1939 r_list_foreach (fcn->bbs, iter, bb) {
1940 if (ebbs && bb->jump == UT64_MAX && bb->fail == UT64_MAX) {
1941 *ebbs = *ebbs + 1;
1942 } else {
1943 if (bb->jump != UT64_MAX) {
1944 edges ++;
1945 }
1946 if (bb->fail != UT64_MAX) {
1947 edges ++;
1948 }
1949 }
1950 }
1951 return edges;
1952 }
1953
r_anal_function_purity(RAnalFunction * fcn)1954 R_API bool r_anal_function_purity(RAnalFunction *fcn) {
1955 if (fcn->has_changed) {
1956 HtUP *ht = ht_up_new (NULL, NULL, NULL);
1957 if (ht) {
1958 check_purity (ht, fcn);
1959 ht_up_free (ht);
1960 }
1961 }
1962 return fcn->is_pure;
1963 }
1964
can_affect_bp(RAnal * anal,RAnalOp * op)1965 static bool can_affect_bp(RAnal *anal, RAnalOp* op) {
1966 RAnalValue *dst = op->dst;
1967 RAnalValue *src = op->src[0];
1968 const char *opdreg = (dst && dst->reg) ? dst->reg->name : NULL;
1969 const char *opsreg = (src && src->reg) ? src->reg->name : NULL;
1970 const char *bp_name = anal->reg->name[R_REG_NAME_BP];
1971 bool is_bp_dst = opdreg && !dst->memref && !strcmp (opdreg, bp_name);
1972 bool is_bp_src = opsreg && !src->memref && !strcmp (opsreg, bp_name);
1973 if (op->type == R_ANAL_OP_TYPE_XCHG) {
1974 return is_bp_src || is_bp_dst;
1975 }
1976 return is_bp_dst;
1977 }
1978
1979 /*
1980 * This function checks whether any operation in a given function may change bp (excluding "mov bp, sp"
1981 * and "pop bp" at the end).
1982 */
__anal_fcn_check_bp_use(RAnal * anal,RAnalFunction * fcn)1983 static void __anal_fcn_check_bp_use(RAnal *anal, RAnalFunction *fcn) {
1984 RListIter *iter;
1985 RAnalBlock *bb;
1986 char *pos;
1987 char str_to_find[40];
1988 snprintf (str_to_find, sizeof (str_to_find),
1989 "\"type\":\"reg\",\"value\":\"%s", anal->reg->name[R_REG_NAME_BP]);
1990 if (!fcn) {
1991 return;
1992 }
1993 r_list_foreach (fcn->bbs, iter, bb) {
1994 RAnalOp op;
1995 ut64 at, end = bb->addr + bb->size;
1996 ut8 *buf = malloc (bb->size);
1997 if (!buf) {
1998 continue;
1999 }
2000 (void)anal->iob.read_at (anal->iob.io, bb->addr, (ut8 *) buf, bb->size);
2001 int idx = 0;
2002 for (at = bb->addr; at < end;) {
2003 r_anal_op (anal, &op, at, buf + idx, bb->size - idx, R_ANAL_OP_MASK_VAL | R_ANAL_OP_MASK_OPEX);
2004 if (op.size < 1) {
2005 op.size = 1;
2006 }
2007 switch (op.type) {
2008 case R_ANAL_OP_TYPE_MOV:
2009 case R_ANAL_OP_TYPE_LEA:
2010 if (can_affect_bp (anal, &op) && op.src[0] && op.src[0]->reg && op.src[0]->reg->name
2011 && strcmp (op.src[0]->reg->name, anal->reg->name[R_REG_NAME_SP])) {
2012 fcn->bp_frame = false;
2013 r_anal_op_fini (&op);
2014 free (buf);
2015 return;
2016 }
2017 break;
2018 case R_ANAL_OP_TYPE_ADD:
2019 case R_ANAL_OP_TYPE_AND:
2020 case R_ANAL_OP_TYPE_CMOV:
2021 case R_ANAL_OP_TYPE_NOT:
2022 case R_ANAL_OP_TYPE_OR:
2023 case R_ANAL_OP_TYPE_ROL:
2024 case R_ANAL_OP_TYPE_ROR:
2025 case R_ANAL_OP_TYPE_SAL:
2026 case R_ANAL_OP_TYPE_SAR:
2027 case R_ANAL_OP_TYPE_SHR:
2028 case R_ANAL_OP_TYPE_SUB:
2029 case R_ANAL_OP_TYPE_XOR:
2030 case R_ANAL_OP_TYPE_SHL:
2031 // op.dst is not filled for these operations, so for now, check for bp as dst looks like this; in the future it may be just replaced with call to can_affect_bp
2032 pos = op.opex.ptr ? strstr (op.opex.ptr, str_to_find) : NULL;
2033 if (pos && pos - op.opex.ptr < 60) {
2034 fcn->bp_frame = false;
2035 r_anal_op_fini (&op);
2036 free (buf);
2037 return;
2038 }
2039 break;
2040 case R_ANAL_OP_TYPE_XCHG:
2041 if (op.opex.ptr && strstr (op.opex.ptr, str_to_find)) {
2042 fcn->bp_frame = false;
2043 r_anal_op_fini (&op);
2044 free (buf);
2045 return;
2046 }
2047 break;
2048 case R_ANAL_OP_TYPE_POP:
2049 break;
2050 default:
2051 break;
2052 }
2053 idx += op.size;
2054 at += op.size;
2055 r_anal_op_fini (&op);
2056 }
2057 free (buf);
2058 }
2059 }
2060
r_anal_function_check_bp_use(RAnalFunction * fcn)2061 R_API void r_anal_function_check_bp_use(RAnalFunction *fcn) {
2062 r_return_if_fail (fcn);
2063 __anal_fcn_check_bp_use (fcn->anal, fcn);
2064 }
2065
2066 typedef struct {
2067 RAnalFunction *fcn;
2068 HtUP *visited;
2069 } BlockRecurseCtx;
2070
mark_as_visited(RAnalBlock * bb,void * user)2071 static bool mark_as_visited(RAnalBlock *bb, void *user) {
2072 BlockRecurseCtx *ctx = user;
2073 ht_up_insert (ctx->visited, bb->addr, NULL);
2074 return true;
2075 }
2076
analize_addr_cb(ut64 addr,void * user)2077 static bool analize_addr_cb(ut64 addr, void *user) {
2078 BlockRecurseCtx *ctx = user;
2079 RAnal *anal = ctx->fcn->anal;
2080 RAnalBlock *existing_bb = r_anal_get_block_at (anal, addr);
2081 if (!existing_bb || !r_list_contains (ctx->fcn->bbs, existing_bb)) {
2082 int old_len = r_list_length (ctx->fcn->bbs);
2083 r_anal_fcn_bb (ctx->fcn->anal, ctx->fcn, addr, anal->opt.depth);
2084 if (old_len != r_list_length (ctx->fcn->bbs)) {
2085 r_anal_block_recurse (r_anal_get_block_at (anal, addr), mark_as_visited, user);
2086 }
2087 }
2088 ht_up_insert (ctx->visited, addr, NULL);
2089 return true;
2090 }
2091
analize_descendents(RAnalBlock * bb,void * user)2092 static bool analize_descendents(RAnalBlock *bb, void *user) {
2093 return r_anal_block_successor_addrs_foreach (bb, analize_addr_cb, user);
2094 }
2095
free_ht_up(HtUPKv * kv)2096 static void free_ht_up(HtUPKv *kv) {
2097 ht_up_free ((HtUP *)kv->value);
2098 }
2099
update_var_analysis(RAnalFunction * fcn,int align,ut64 from,ut64 to)2100 static void update_var_analysis(RAnalFunction *fcn, int align, ut64 from, ut64 to) {
2101 RAnal *anal = fcn->anal;
2102 ut64 cur_addr;
2103 int opsz;
2104 from = align ? from - (from % align) : from;
2105 to = align ? R_ROUND (to, align) : to;
2106 if (UT64_SUB_OVFCHK (to, from)) {
2107 return;
2108 }
2109 ut64 len = to - from;
2110 ut8 *buf = malloc (len);
2111 if (!buf) {
2112 return;
2113 }
2114 if (anal->iob.read_at (anal->iob.io, from, buf, len) < len) {
2115 return;
2116 }
2117 for (cur_addr = from; cur_addr < to; cur_addr += opsz, len -= opsz) {
2118 RAnalOp op;
2119 int ret = r_anal_op (anal->coreb.core, &op, cur_addr, buf, len, R_ANAL_OP_MASK_ESIL | R_ANAL_OP_MASK_VAL);
2120 if (ret < 1 || op.size < 1) {
2121 r_anal_op_fini (&op);
2122 break;
2123 }
2124 opsz = op.size;
2125 r_anal_extract_vars (anal, fcn, &op);
2126 r_anal_op_fini (&op);
2127 }
2128 free (buf);
2129 }
2130
2131 // Clear function variable acesses inside in a block
clear_bb_vars(RAnalFunction * fcn,RAnalBlock * bb,ut64 from,ut64 to)2132 static void clear_bb_vars(RAnalFunction *fcn, RAnalBlock *bb, ut64 from, ut64 to) {
2133 int i;
2134 if (r_pvector_empty (&fcn->vars)) {
2135 return;
2136 }
2137 for (i = 0; i < bb->ninstr; i++) {
2138 const ut64 addr = r_anal_bb_opaddr_i (bb, i);
2139 if (addr < from) {
2140 continue;
2141 }
2142 if (addr >= to || addr == UT64_MAX) {
2143 break;
2144 }
2145 RPVector *vars = r_anal_function_get_vars_used_at (fcn, addr);
2146 if (vars) {
2147 RPVector *vars_clone = (RPVector *)r_vector_clone ((RVector *)vars);
2148 void **v;
2149 r_pvector_foreach (vars_clone, v) {
2150 r_anal_var_remove_access_at ((RAnalVar *)*v, addr);
2151 }
2152 r_pvector_clear (vars_clone);
2153 }
2154 }
2155 }
2156
update_analysis(RAnal * anal,RList * fcns,HtUP * reachable)2157 static void update_analysis(RAnal *anal, RList *fcns, HtUP *reachable) {
2158 RListIter *it, *it2, *tmp;
2159 RAnalFunction *fcn;
2160 bool old_jmpmid = anal->opt.jmpmid;
2161 anal->opt.jmpmid = true;
2162 r_anal_fcn_invalidate_read_ahead_cache ();
2163 r_list_foreach (fcns, it, fcn) {
2164 // Recurse through blocks of function, mark reachable,
2165 // analyze edges that don't have a block
2166 RAnalBlock *bb = r_anal_get_block_at (anal, fcn->addr);
2167 if (!bb) {
2168 r_anal_fcn_bb (anal, fcn, fcn->addr, anal->opt.depth);
2169 bb = r_anal_get_block_at (anal, fcn->addr);
2170 if (!bb) {
2171 continue;
2172 }
2173 }
2174 HtUP *ht = ht_up_new0 ();
2175 ht_up_insert (ht, bb->addr, NULL);
2176 BlockRecurseCtx ctx = { fcn, ht };
2177 r_anal_block_recurse (bb, analize_descendents, &ctx);
2178
2179 // Remove non-reachable blocks
2180 r_list_foreach_safe (fcn->bbs, it2, tmp, bb) {
2181 if (ht_up_find_kv (ht, bb->addr, NULL)) {
2182 continue;
2183 }
2184 HtUP *o_visited = ht_up_find (reachable, fcn->addr, NULL);
2185 if (!ht_up_find_kv (o_visited, bb->addr, NULL)) {
2186 // Avoid removing blocks that were already not reachable
2187 continue;
2188 }
2189 fcn->ninstr -= bb->ninstr;
2190 r_anal_function_remove_block (fcn, bb);
2191 }
2192
2193 RList *bbs = r_list_clone (fcn->bbs);
2194 r_anal_block_automerge (bbs);
2195 r_anal_function_delete_unused_vars (fcn);
2196 r_list_free (bbs);
2197 }
2198 anal->opt.jmpmid = old_jmpmid;
2199 }
2200
calc_reachable_and_remove_block(RList * fcns,RAnalFunction * fcn,RAnalBlock * bb,HtUP * reachable)2201 static void calc_reachable_and_remove_block(RList *fcns, RAnalFunction *fcn, RAnalBlock *bb, HtUP *reachable) {
2202 clear_bb_vars (fcn, bb, bb->addr, bb->addr + bb->size);
2203 if (!r_list_contains (fcns, fcn)) {
2204 r_list_append (fcns, fcn);
2205
2206 // Calculate reachable blocks from the start of function
2207 HtUP *ht = ht_up_new0 ();
2208 BlockRecurseCtx ctx = { fcn, ht };
2209 r_anal_block_recurse (r_anal_get_block_at (fcn->anal, fcn->addr), mark_as_visited, &ctx);
2210 ht_up_insert (reachable, fcn->addr, ht);
2211 }
2212 fcn->ninstr -= bb->ninstr;
2213 r_anal_function_remove_block (fcn, bb);
2214 }
2215
r_anal_update_analysis_range(RAnal * anal,ut64 addr,int size)2216 R_API void r_anal_update_analysis_range(RAnal *anal, ut64 addr, int size) {
2217 r_return_if_fail (anal);
2218 RListIter *it, *it2, *tmp;
2219 RAnalBlock *bb;
2220 RAnalFunction *fcn;
2221 RList *blocks = r_anal_get_blocks_intersect (anal, addr, size);
2222 if (r_list_empty (blocks)) {
2223 r_list_free (blocks);
2224 return;
2225 }
2226 RList *fcns = r_list_new ();
2227 HtUP *reachable = ht_up_new (NULL, free_ht_up, NULL);
2228 const int align = r_anal_archinfo (anal, R_ANAL_ARCHINFO_ALIGN);
2229 const ut64 end_write = addr + size;
2230
2231 r_list_foreach (blocks, it, bb) {
2232 if (!r_anal_block_was_modified (bb)) {
2233 continue;
2234 }
2235 r_list_foreach_safe (bb->fcns, it2, tmp, fcn) {
2236 if (align > 1) {
2237 if ((end_write < r_anal_bb_opaddr_i (bb, bb->ninstr - 1))
2238 && (!bb->switch_op || end_write < bb->switch_op->addr)) {
2239 // Special case when instructions are aligned and we don't
2240 // need to worry about a write messing with the jump instructions
2241 clear_bb_vars (fcn, bb, addr > bb->addr ? addr : bb->addr, end_write);
2242 update_var_analysis (fcn, align, addr > bb->addr ? addr : bb->addr, end_write);
2243 r_anal_function_delete_unused_vars (fcn);
2244 continue;
2245 }
2246 }
2247 calc_reachable_and_remove_block (fcns, fcn, bb, reachable);
2248 }
2249 }
2250 r_list_free (blocks); // This will call r_anal_block_unref to actually remove blocks from RAnal
2251 update_analysis (anal, fcns, reachable);
2252 ht_up_free (reachable);
2253 r_list_free (fcns);
2254 }
2255
r_anal_function_update_analysis(RAnalFunction * fcn)2256 R_API void r_anal_function_update_analysis(RAnalFunction *fcn) {
2257 r_return_if_fail (fcn);
2258 RListIter *it, *it2, *tmp, *tmp2;
2259 RAnalBlock *bb;
2260 RAnalFunction *f;
2261 RList *fcns = r_list_new ();
2262 HtUP *reachable = ht_up_new (NULL, free_ht_up, NULL);
2263 r_list_foreach_safe (fcn->bbs, it, tmp, bb) {
2264 if (r_anal_block_was_modified (bb)) {
2265 r_list_foreach_safe (bb->fcns, it2, tmp2, f) {
2266 calc_reachable_and_remove_block (fcns, f, bb, reachable);
2267 }
2268 }
2269 }
2270 update_analysis (fcn->anal, fcns, reachable);
2271 ht_up_free (reachable);
2272 r_list_free (fcns);
2273 }
2274