Rizin
unix-like reverse engineering framework and cli tools
jmptbl.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2010-2019 nibble <nibble.ds@gmail.com>
2 // SPDX-FileCopyrightText: 2010-2019 alvaro <alvaro.felipe91@gmail.com>
3 // SPDX-FileCopyrightText: 2010-2019 pancake <pancake@nopcode.org>
4 // SPDX-License-Identifier: LGPL-3.0-only
5 
6 #include <rz_analysis.h>
7 #include <rz_parse.h>
8 #include <rz_util.h>
9 #include <rz_list.h>
10 #include <rz_types_overflow.h>
11 
12 #define aprintf(format, ...) \
13  RZ_LOG_DEBUG(format, __VA_ARGS__)
14 
15 static void apply_case(RzAnalysis *analysis, RzAnalysisBlock *block, ut64 switch_addr, ut64 offset_sz, ut64 case_addr, ut64 id, ut64 case_addr_loc) {
16  // eprintf ("** apply_case: 0x%"PFMT64x " from 0x%"PFMT64x "\n", case_addr, case_addr_loc);
17  rz_meta_set_data_at(analysis, case_addr_loc, offset_sz);
18  rz_analysis_hint_set_immbase(analysis, case_addr_loc, 10);
19  rz_analysis_xrefs_set(analysis, switch_addr, case_addr, RZ_ANALYSIS_XREF_TYPE_CODE);
20  if (block) {
21  rz_analysis_block_add_switch_case(block, switch_addr, id, case_addr);
22  }
23  if (analysis->flb.set) {
24  char flagname[0x30];
25  snprintf(flagname, sizeof(flagname), "case.0x%" PFMT64x ".%d", (ut64)switch_addr, (int)id);
26  analysis->flb.set(analysis->flb.f, flagname, case_addr, 1);
27  }
28 }
29 
30 static void apply_switch(RzAnalysis *analysis, ut64 switch_addr, ut64 jmptbl_addr, ut64 cases_count, ut64 default_case_addr) {
31  char tmp[0x30];
32  snprintf(tmp, sizeof(tmp), "switch table (%" PFMT64u " cases) at 0x%" PFMT64x, cases_count, jmptbl_addr);
33  rz_meta_set_string(analysis, RZ_META_TYPE_COMMENT, switch_addr, tmp);
34  if (analysis->flb.set) {
35  snprintf(tmp, sizeof(tmp), "switch.0x%08" PFMT64x, switch_addr);
36  analysis->flb.set(analysis->flb.f, tmp, switch_addr, 1);
37  if (default_case_addr != UT64_MAX) {
38  rz_analysis_xrefs_set(analysis, switch_addr, default_case_addr, RZ_ANALYSIS_XREF_TYPE_CODE);
39  snprintf(tmp, sizeof(tmp), "case.default.0x%" PFMT64x, switch_addr);
40  analysis->flb.set(analysis->flb.f, tmp, default_case_addr, 1);
41  }
42  }
43 }
44 
45 // analyze a jmptablle inside a function // maybe rename to rz_analysis_fcn_jmptbl() ?
46 RZ_API bool rz_analysis_jmptbl(RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisBlock *block, ut64 jmpaddr, ut64 table, ut64 tablesize, ut64 default_addr) {
47  RzAnalysisJmpTableParams params = {
48  .jmp_address = jmpaddr,
49  .case_shift = 0,
50  .jmptbl_loc = table,
51  .casetbl_loc = UT64_MAX,
52  .jmptbl_off = table,
53  .entry_size = tablesize,
54  .table_count = tablesize,
55  .default_case = default_addr,
56  };
57  return rz_analysis_walkthrough_jmptbl(analysis, fcn, block, &params);
58 }
59 
60 static inline bool jmptable_size_is_invalid(RzAnalysisJmpTableParams *params) {
61  return UT64_MUL_OVFCHK(params->table_count, params->entry_size) ||
62  params->table_count * params->entry_size > ST32_MAX;
63 }
64 
77  rz_return_val_if_fail(analysis && fcn && block && params, false);
78  bool ret = true;
79  if (params->table_count == 0) {
80  params->table_count = analysis->opt.jmptbl_maxcount;
81  }
82  if (params->jmptbl_loc == UT64_MAX) {
83  aprintf("Invalid jump table location 0x%08" PFMT64x "\n", params->jmptbl_loc);
84  return false;
85  }
86  if (params->casetbl_loc == UT64_MAX) {
87  aprintf("Invalid case table location 0x%08" PFMT64x "\n", params->jmptbl_loc);
88  return false;
89  }
90  if (jmptable_size_is_invalid(params)) {
91  aprintf("Invalid jump table size at 0x%08" PFMT64x "\n", params->jmp_address);
92  return false;
93  }
94  ut64 jmpptr, case_idx, jmpptr_idx;
95  ut8 *jmptbl = calloc(params->table_count, params->entry_size);
96  if (!jmptbl || !analysis->iob.read_at(analysis->iob.io, params->jmptbl_loc, jmptbl, params->table_count * params->entry_size)) {
97  free(jmptbl);
98  return false;
99  }
100  ut8 *casetbl = calloc(params->table_count, sizeof(ut8));
101  if (!casetbl || !analysis->iob.read_at(analysis->iob.io, params->casetbl_loc, casetbl, params->table_count)) {
102  free(jmptbl);
103  free(casetbl);
104  return false;
105  }
106  for (case_idx = 0; case_idx < params->table_count; case_idx++) {
107  jmpptr_idx = casetbl[case_idx];
108 
109  if (jmpptr_idx >= params->table_count) {
110  ret = false;
111  break;
112  }
113 
114  switch (params->entry_size) {
115  case 1:
116  jmpptr = rz_read_le8(jmptbl + jmpptr_idx);
117  break;
118  case 2:
119  jmpptr = rz_read_le16(jmptbl + jmpptr_idx * 2);
120  break;
121  case 4:
122  jmpptr = rz_read_le32(jmptbl + jmpptr_idx * 4);
123  break;
124  default:
125  jmpptr = rz_read_le64(jmptbl + jmpptr_idx * 8);
126  break;
127  }
128  if (jmpptr == 0 || jmpptr == UT32_MAX || jmpptr == UT64_MAX) {
129  break;
130  }
131  if (!analysis->iob.is_valid_offset(analysis->iob.io, jmpptr, 0)) {
132  st32 jmpdelta = (st32)jmpptr;
133  // jump tables where sign extended movs are used
134  jmpptr = params->jmptbl_off + jmpdelta;
135  if (!analysis->iob.is_valid_offset(analysis->iob.io, jmpptr, 0)) {
136  break;
137  }
138  }
139  if (analysis->limit) {
140  if (jmpptr < analysis->limit->from || jmpptr > analysis->limit->to) {
141  break;
142  }
143  }
144 
145  const ut64 jmpptr_idx_off = params->casetbl_loc + case_idx;
146  rz_meta_set_data_at(analysis, jmpptr_idx_off, 1);
147  rz_analysis_hint_set_immbase(analysis, jmpptr_idx_off, 10);
148 
149  apply_case(analysis, block, params->jmp_address, params->entry_size, jmpptr, case_idx + params->case_shift, params->jmptbl_loc + jmpptr_idx * params->entry_size);
150  rz_analysis_task_item_new(analysis, params->tasks, fcn, NULL, jmpptr);
151  }
152 
153  if (case_idx > 0) {
154  if (params->default_case == 0) {
155  params->default_case = UT64_MAX;
156  }
157  apply_switch(analysis, params->jmp_address, params->jmptbl_loc, case_idx, params->default_case);
158  }
159 
160  free(jmptbl);
161  free(casetbl);
162  return ret;
163 }
164 
177  rz_return_val_if_fail(analysis && fcn && block && params, false);
178  // table_count can not always be determined
179  if (params->table_count == 0) {
180  params->table_count = analysis->opt.jmptbl_maxcount;
181  }
182  if (params->jmptbl_loc == UT64_MAX) {
183  aprintf("Invalid jump table location 0x%08" PFMT64x "\n", params->jmptbl_loc);
184  return false;
185  }
186  if (jmptable_size_is_invalid(params)) {
187  aprintf("Invalid jump table size at 0x%08" PFMT64x "\n", params->jmp_address);
188  return false;
189  }
190  ut64 jmpptr, offs;
191  ut8 *jmptbl = calloc(params->table_count, params->entry_size);
192  if (!jmptbl) {
193  return false;
194  }
195  bool is_arm = analysis->cur->arch && !strncmp(analysis->cur->arch, "arm", 3);
196  // eprintf ("JMPTBL AT 0x%"PFMT64x"\n", jmptbl_loc);
197  analysis->iob.read_at(analysis->iob.io, params->jmptbl_loc, jmptbl, params->table_count * params->entry_size);
198  for (offs = 0; offs + params->entry_size - 1 < params->table_count * params->entry_size; offs += params->entry_size) {
199  switch (params->entry_size) {
200  case 1:
201  jmpptr = (ut64)(ut8)rz_read_le8(jmptbl + offs);
202  break;
203  case 2:
204  jmpptr = (ut64)rz_read_le16(jmptbl + offs);
205  break;
206  case 4:
207  jmpptr = rz_read_le32(jmptbl + offs);
208  break;
209  case 8:
210  jmpptr = rz_read_le64(jmptbl + offs);
211  break; // XXX
212  default:
213  jmpptr = rz_read_le64(jmptbl + offs);
214  break;
215  }
216  // eprintf ("WALKING %llx\n", jmpptr);
217  // if we don't check for 0 here, the next check with ptr+jmpptr
218  // will obviously be a good offset since it will be the start
219  // of the table, which is not what we want
220  if (jmpptr == 0 || jmpptr == UT32_MAX || jmpptr == UT64_MAX) {
221  break;
222  }
223  if (params->entry_size == 2 && is_arm) {
224  jmpptr = params->jmp_address + 4 + (jmpptr * 2); // tbh [pc, r2, lsl 1] // assume lsl 1
225  } else if (params->entry_size == 1 && is_arm) {
226  jmpptr = params->jmp_address + 4 + (jmpptr * 2); // lbb [pc, r2] // assume lsl 1
227  } else if (!analysis->iob.is_valid_offset(analysis->iob.io, jmpptr, 0)) {
228  st32 jmpdelta = (st32)jmpptr;
229  // jump tables where sign extended movs are used
230  jmpptr = params->jmptbl_off + jmpdelta;
231  if (!analysis->iob.is_valid_offset(analysis->iob.io, jmpptr, 0)) {
232  break;
233  }
234  }
235  if (analysis->limit) {
236  if (jmpptr < analysis->limit->from || jmpptr > analysis->limit->to) {
237  break;
238  }
239  }
240  apply_case(analysis, block, params->jmp_address, params->entry_size, jmpptr, (offs / params->entry_size) + params->case_shift, params->jmptbl_loc + offs);
241  rz_analysis_task_item_new(analysis, params->tasks, fcn, NULL, jmpptr);
242  }
243 
244  if (offs > 0) {
245  if (params->default_case == 0) {
246  params->default_case = UT64_MAX;
247  }
248  apply_switch(analysis, params->jmp_address, params->jmptbl_loc, offs / params->entry_size, params->default_case);
249  }
250 
251  free(jmptbl);
252  return true;
253 }
254 
255 static bool detect_casenum_shift(RzAnalysisOp *op, RzRegItem **cmp_reg, st64 *start_casenum_shift) {
256  if (!*cmp_reg) {
257  return true;
258  }
259  if (op->dst && op->dst->reg && op->dst->reg->offset == (*cmp_reg)->offset) {
260  if (op->type == RZ_ANALYSIS_OP_TYPE_LEA && op->ptr == UT64_MAX) {
261  *start_casenum_shift = -(st64)op->disp;
262  } else if (op->val != UT64_MAX) {
263  if (op->type == RZ_ANALYSIS_OP_TYPE_ADD) {
264  *start_casenum_shift = -(st64)op->val;
265  } else if (op->type == RZ_ANALYSIS_OP_TYPE_SUB) {
266  *start_casenum_shift = op->val;
267  }
268  } else if (op->type == RZ_ANALYSIS_OP_TYPE_MOV) {
269  *cmp_reg = op->src[0]->reg;
270  return false;
271  }
272  return true;
273  }
274  return false;
275 }
276 
288 RZ_API bool rz_analysis_get_delta_jmptbl_info(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn, ut64 jmp_address, ut64 lea_address, RZ_NONNULL RzAnalysisJmpTableParams *params) {
289  rz_return_val_if_fail(analysis && fcn && params, false);
290  bool isValid = false;
291  bool foundCmp = false;
292  ut64 i;
293 
294  RzAnalysisOp tmp_aop = { 0 };
295  if (lea_address > jmp_address) {
296  return false;
297  }
298 
299  params->jmp_address = jmp_address;
300 
301  int search_sz = jmp_address - lea_address;
302  ut8 *buf = malloc(search_sz);
303  if (!buf) {
304  return false;
305  }
306  // search for a cmp register with a reasonable size
307  analysis->iob.read_at(analysis->iob.io, lea_address, (ut8 *)buf, search_sz);
308  RzVector v;
309  rz_vector_init(&v, sizeof(ut64), NULL, NULL);
310  int len = 0;
311  RzRegItem *cmp_reg = NULL;
312  for (i = 0; i + 8 < search_sz; i += len) {
313  len = rz_analysis_op(analysis, &tmp_aop, lea_address + i, buf + i, search_sz - i, RZ_ANALYSIS_OP_MASK_BASIC);
314  if (len < 1) {
315  len = 1;
316  }
317 
318  if (foundCmp) {
319  if (tmp_aop.type != RZ_ANALYSIS_OP_TYPE_CJMP) {
320  continue;
321  }
322 
323  params->default_case = tmp_aop.jump == tmp_aop.jump + len ? tmp_aop.fail : tmp_aop.jump;
324  break;
325  }
326 
328  if (type != RZ_ANALYSIS_OP_TYPE_CMP) {
329  continue;
330  }
331  // get the value of the cmp
332  // for operands in op, check if type is immediate and val is sane
333  // TODO: How? opex?
334 
335  // for the time being, this seems to work
336  // might not actually have a value, let the next step figure out the size then
337  if (tmp_aop.val == UT64_MAX && tmp_aop.refptr == 0) {
338  isValid = true;
339  params->table_count = 0;
340  } else if (tmp_aop.refptr == 0) {
341  isValid = tmp_aop.val < 0x200;
342  params->table_count = tmp_aop.val + 1;
343  } else {
344  isValid = tmp_aop.refptr < 0x200;
345  params->table_count = tmp_aop.refptr + 1;
346  }
347  rz_vector_push(&v, &i);
348  rz_analysis_op(analysis, &tmp_aop, lea_address + i, buf + i, search_sz - i, RZ_ANALYSIS_OP_MASK_VAL);
349  if (tmp_aop.dst && tmp_aop.dst->reg) {
350  cmp_reg = tmp_aop.dst->reg;
351  } else if (tmp_aop.reg) {
352  cmp_reg = rz_reg_get(analysis->reg, tmp_aop.reg, RZ_REG_TYPE_ANY);
353  } else if (tmp_aop.src[0] && tmp_aop.src[0]->reg) {
354  cmp_reg = tmp_aop.src[0]->reg;
355  }
356  rz_analysis_op_fini(&tmp_aop);
357  // TODO: check the jmp for whether val is included in valid range or not (ja vs jae)
358  foundCmp = true;
359  }
360  if (isValid) {
361  params->case_shift = 0;
362  void **it;
363  rz_vector_foreach_prev(&v, it) {
364  const ut64 op_off = *(ut64 *)it;
365  ut64 op_addr = lea_address + op_off;
366  rz_analysis_op(analysis, &tmp_aop, op_addr,
367  buf + op_off, search_sz - op_off,
369  if (detect_casenum_shift(&tmp_aop, &cmp_reg, &params->case_shift)) {
370  rz_analysis_op_fini(&tmp_aop);
371  break;
372  }
373  rz_analysis_op_fini(&tmp_aop);
374  }
375  }
376  rz_vector_fini(&v);
377  free(buf);
378  return isValid;
379 }
380 
392  /*
393  * Example about arm jump table
394  *
395  * 0x000105b4 060050e3 cmp r0, 3
396  * 0x000105b8 00f18f90 addls pc, pc, r0, lsl 2
397  * 0x000105bc 0d0000ea b loc.000105f8
398  * 0x000105c0 050000ea b 0x105dc
399  * 0x000105c4 050000ea b 0x105e0
400  * 0x000105c8 060000ea b 0x105e8
401  * ; CODE XREF from loc._a_7 (+0x10)
402  * 0x000105dc b6ffffea b sym.input_1
403  * ; CODE XREF from loc._a_7 (+0x14)
404  * 0x000105e0 b9ffffea b sym.input_2
405  * ; CODE XREF from loc._a_7 (+0x28)
406  * 0x000105e4 ccffffea b sym.input_7
407  * ; CODE XREF from loc._a_7 (+0x18)
408  * 0x000105e8 bbffffea b sym.input_3
409  */
410  rz_return_val_if_fail(analysis && fcn && block && params, false);
411  ut64 offs, jmpptr;
412 
413  if (params->table_count == 0) {
414  params->table_count = analysis->opt.jmptbl_maxcount;
415  }
416 
417  for (offs = 0; offs + params->entry_size - 1 < params->table_count * params->entry_size; offs += params->entry_size) {
418  jmpptr = params->jmptbl_loc + offs;
419  apply_case(analysis, block, params->jmp_address, params->entry_size, jmpptr, offs / params->entry_size, params->jmptbl_loc + offs);
420  rz_analysis_task_item_new(analysis, params->tasks, fcn, NULL, jmpptr);
421  }
422 
423  if (offs > 0) {
424  if (params->default_case == 0 || params->default_case == UT32_MAX) {
425  params->default_case = UT64_MAX;
426  }
427  apply_switch(analysis, params->jmp_address, params->jmptbl_loc, offs / params->entry_size, params->default_case);
428  }
429  return true;
430 }
431 
443 RZ_API bool rz_analysis_get_jmptbl_info(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn, RZ_NONNULL RzAnalysisBlock *block, ut64 jmp_address, RZ_NONNULL RzAnalysisJmpTableParams *params) {
444  rz_return_val_if_fail(analysis && fcn && params && block, false);
445  bool isValid = false;
446  int i;
447  RzListIter *iter;
448  RzAnalysisBlock *tmp_bb, *prev_bb;
449  prev_bb = 0;
450  if (!fcn->bbs) {
451  return false;
452  }
453 
454  params->jmp_address = jmp_address;
455 
456  /* if UJMP is in .plt section just skip it */
457  RzBinSection *s = analysis->binb.get_vsect_at(analysis->binb.bin, jmp_address);
458  if (s && s->name[0]) {
459  bool in_plt = strstr(s->name, ".plt") != NULL;
460  if (!in_plt && strstr(s->name, "_stubs") != NULL) {
461  /* for mach0 */
462  in_plt = true;
463  }
464  if (in_plt) {
465  return false;
466  }
467  }
468 
469  // search for the predecessor bb
470  rz_list_foreach (fcn->bbs, iter, tmp_bb) {
471  if (tmp_bb->jump == block->addr || tmp_bb->fail == block->addr) {
472  prev_bb = tmp_bb;
473  break;
474  }
475  }
476  // predecessor must be a conditional jump
477  if (!prev_bb || !prev_bb->jump || !prev_bb->fail) {
478  aprintf("Missing predecesessor on basic block conditional jump at 0x%08" PFMT64x ", required by jump table\n", jmp_address);
479  return false;
480  }
481 
482  // default case is the jump target of the unconditional jump
483  params->default_case = prev_bb->jump == block->addr ? prev_bb->fail : prev_bb->jump;
484 
485  RzAnalysisOp tmp_aop = { 0 };
486  ut8 *bb_buf = calloc(1, prev_bb->size);
487  if (!bb_buf) {
488  return false;
489  }
490  // search for a cmp register with a reasonable size
491  analysis->iob.read_at(analysis->iob.io, prev_bb->addr, (ut8 *)bb_buf, prev_bb->size);
492  isValid = false;
493 
494  RzAnalysisHint *hint = rz_analysis_hint_get(analysis, jmp_address);
495  if (hint) {
496  ut64 val = hint->val;
497  rz_analysis_hint_free(hint);
498  if (val != UT64_MAX) {
499  params->table_count = val;
500  return true;
501  }
502  }
503 
504  RzRegItem *cmp_reg = NULL;
505  for (i = prev_bb->ninstr - 1; i >= 0; i--) {
506  const ut64 prev_pos = rz_analysis_block_get_op_offset(prev_bb, i);
507  const ut64 op_addr = rz_analysis_block_get_op_addr(prev_bb, i);
508  if (prev_pos >= prev_bb->size) {
509  continue;
510  }
511  int buflen = prev_bb->size - prev_pos;
512  int len = rz_analysis_op(analysis, &tmp_aop, op_addr,
513  bb_buf + prev_pos, buflen,
516  if (len < 1 || type != RZ_ANALYSIS_OP_TYPE_CMP) {
517  rz_analysis_op_fini(&tmp_aop);
518  continue;
519  }
520  // get the value of the cmp
521  // for operands in op, check if type is immediate and val is sane
522  // TODO: How? opex?
523 
524  // for the time being, this seems to work
525  // might not actually have a value, let the next step figure out the size then
526  if (tmp_aop.val == UT64_MAX && tmp_aop.refptr == 0) {
527  isValid = true;
528  params->table_count = 0;
529  } else if (tmp_aop.refptr == 0 || tmp_aop.val != UT64_MAX) {
530  isValid = tmp_aop.val < 0x200;
531  params->table_count = tmp_aop.val + 1;
532  } else {
533  isValid = tmp_aop.refptr < 0x200;
534  params->table_count = tmp_aop.refptr + 1;
535  }
536  if (isValid) {
537  rz_analysis_op_fini(&tmp_aop);
538  rz_analysis_op(analysis, &tmp_aop, op_addr,
539  bb_buf + prev_pos, buflen,
541  if (tmp_aop.dst && tmp_aop.dst->reg) {
542  cmp_reg = tmp_aop.dst->reg;
543  } else if (tmp_aop.reg) {
544  cmp_reg = rz_reg_get(analysis->reg, tmp_aop.reg, RZ_REG_TYPE_ANY);
545  } else if (tmp_aop.src[0] && tmp_aop.src[0]->reg) {
546  cmp_reg = tmp_aop.src[0]->reg;
547  }
548  }
549  rz_analysis_op_fini(&tmp_aop);
550  // TODO: check the jmp for whether val is included in valid range or not (ja vs jae)
551  break;
552  }
553  if (isValid) {
554  params->case_shift = 0;
555  for (i--; i >= 0; i--) {
556  const ut64 prev_pos = rz_analysis_block_get_op_offset(prev_bb, i);
557  const ut64 op_addr = rz_analysis_block_get_op_addr(prev_bb, i);
558  if (prev_pos >= prev_bb->size) {
559  continue;
560  }
561  int buflen = prev_bb->size - prev_pos;
562  rz_analysis_op(analysis, &tmp_aop, op_addr,
563  bb_buf + prev_pos, buflen,
565  if (detect_casenum_shift(&tmp_aop, &cmp_reg, &params->case_shift)) {
566  rz_analysis_op_fini(&tmp_aop);
567  break;
568  }
569 
570  rz_analysis_op_fini(&tmp_aop);
571  }
572  }
573  free(bb_buf);
574  return isValid;
575 }
size_t len
Definition: 6502dis.c:15
static bool isValid(ut64 addr)
Definition: analysis_objc.c:51
lzma_index ** i
Definition: index.h:629
ut16 val
Definition: armass64_const.h:6
RZ_API ut64 rz_analysis_block_get_op_addr(RzAnalysisBlock *block, size_t i)
Definition: block.c:1016
RZ_API void rz_analysis_block_add_switch_case(RzAnalysisBlock *block, ut64 switch_addr, ut64 case_value, ut64 case_addr)
Definition: block.c:575
RZ_API ut16 rz_analysis_block_get_op_offset(RzAnalysisBlock *block, size_t i)
Definition: block.c:1006
#define RZ_API
#define NULL
Definition: cris-opc.c:27
uint32_t ut32
const char * v
Definition: dsignal.c:12
RZ_API bool rz_analysis_task_item_new(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzVector *tasks, RZ_NONNULL RzAnalysisFunction *fcn, RZ_NULLABLE RzAnalysisBlock *block, ut64 address)
Adds a new task item to the tasks parameter.
Definition: fcn.c:1488
RZ_API RzAnalysisHint * rz_analysis_hint_get(RzAnalysis *a, ut64 addr)
Definition: hint.c:506
RZ_API void rz_analysis_hint_free(RzAnalysisHint *h)
Definition: hint.c:371
RZ_API void rz_analysis_hint_set_immbase(RzAnalysis *a, ut64 addr, int base)
Definition: hint.c:229
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void * buf
Definition: ioapi.h:138
static bool jmptable_size_is_invalid(RzAnalysisJmpTableParams *params)
Definition: jmptbl.c:60
#define aprintf(format,...)
Definition: jmptbl.c:12
RZ_API bool rz_analysis_walkthrough_arm_jmptbl_style(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn, RZ_NONNULL RzAnalysisBlock *block, RZ_NONNULL RzAnalysisJmpTableParams *params)
Marks for analysis ARM specific jump table cases.
Definition: jmptbl.c:391
RZ_API bool rz_analysis_get_jmptbl_info(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn, RZ_NONNULL RzAnalysisBlock *block, ut64 jmp_address, RZ_NONNULL RzAnalysisJmpTableParams *params)
Gets some necessary information about a jump table to perform analysis on.
Definition: jmptbl.c:443
static void apply_switch(RzAnalysis *analysis, ut64 switch_addr, ut64 jmptbl_addr, ut64 cases_count, ut64 default_case_addr)
Definition: jmptbl.c:30
RZ_API bool rz_analysis_walkthrough_jmptbl(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn, RZ_NONNULL RzAnalysisBlock *block, RZ_NONNULL RzAnalysisJmpTableParams *params)
Marks the jump table cases for analysis.
Definition: jmptbl.c:176
static bool detect_casenum_shift(RzAnalysisOp *op, RzRegItem **cmp_reg, st64 *start_casenum_shift)
Definition: jmptbl.c:255
RZ_API bool rz_analysis_get_delta_jmptbl_info(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn, ut64 jmp_address, ut64 lea_address, RZ_NONNULL RzAnalysisJmpTableParams *params)
Gets some necessary information about a jump table to perform analysis on.
Definition: jmptbl.c:288
static void apply_case(RzAnalysis *analysis, RzAnalysisBlock *block, ut64 switch_addr, ut64 offset_sz, ut64 case_addr, ut64 id, ut64 case_addr_loc)
Definition: jmptbl.c:15
RZ_API bool rz_analysis_jmptbl(RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisBlock *block, ut64 jmpaddr, ut64 table, ut64 tablesize, ut64 default_addr)
Definition: jmptbl.c:46
RZ_API bool rz_analysis_walkthrough_casetbl(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn, RZ_NONNULL RzAnalysisBlock *block, RZ_NONNULL RzAnalysisJmpTableParams *params)
Marks for analysis jump table cases with a space optimization for multiple cases corresponding to the...
Definition: jmptbl.c:76
snprintf
Definition: kernel.h:364
uint8_t ut8
Definition: lh5801.h:11
void * malloc(size_t size)
Definition: malloc.c:123
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
static uint32_t const uint8_t uint32_t uint32_t limit
Definition: memcmplen.h:45
RZ_API void rz_meta_set_data_at(RzAnalysis *a, ut64 addr, ut64 wordsz)
Definition: meta.c:307
RZ_API bool rz_meta_set_string(RzAnalysis *a, RzAnalysisMetaType type, ut64 addr, const char *s)
Definition: meta.c:141
int type
Definition: mipsasm.c:17
RZ_API bool rz_analysis_op_fini(RzAnalysisOp *op)
Definition: op.c:37
RZ_API int rz_analysis_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask)
Definition: op.c:96
static int is_arm(RzBinPEObj *bin)
Definition: pe_info.c:12
RZ_API RzRegItem * rz_reg_get(RzReg *reg, const char *name, int type)
Definition: reg.c:344
static RzSocket * s
Definition: rtr.c:28
@ RZ_ANALYSIS_XREF_TYPE_CODE
Definition: rz_analysis.h:900
@ RZ_META_TYPE_COMMENT
Definition: rz_analysis.h:295
@ RZ_ANALYSIS_OP_MASK_BASIC
Definition: rz_analysis.h:440
@ RZ_ANALYSIS_OP_MASK_VAL
Definition: rz_analysis.h:442
@ RZ_ANALYSIS_OP_MASK_HINT
Definition: rz_analysis.h:443
#define RZ_ANALYSIS_OP_TYPE_MASK
Definition: rz_analysis.h:358
@ RZ_ANALYSIS_OP_TYPE_CMP
Definition: rz_analysis.h:399
@ RZ_ANALYSIS_OP_TYPE_SUB
Definition: rz_analysis.h:402
@ RZ_ANALYSIS_OP_TYPE_ADD
Definition: rz_analysis.h:401
@ RZ_ANALYSIS_OP_TYPE_CJMP
Definition: rz_analysis.h:373
@ RZ_ANALYSIS_OP_TYPE_MOV
Definition: rz_analysis.h:390
@ RZ_ANALYSIS_OP_TYPE_LEA
Definition: rz_analysis.h:417
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
static ut16 rz_read_le16(const void *src)
Definition: rz_endian.h:206
static ut32 rz_read_le32(const void *src)
Definition: rz_endian.h:239
static ut8 rz_read_le8(const void *src)
Definition: rz_endian.h:187
static ut64 rz_read_le64(const void *src)
Definition: rz_endian.h:266
@ RZ_REG_TYPE_ANY
Definition: rz_reg.h:35
#define RZ_NONNULL
Definition: rz_types.h:64
#define PFMT64u
Definition: rz_types.h:395
#define PFMT64x
Definition: rz_types.h:393
#define st64
Definition: rz_types_base.h:10
#define UT32_MAX
Definition: rz_types_base.h:99
#define ST32_MAX
Definition: rz_types_base.h:97
#define UT64_MAX
Definition: rz_types_base.h:86
#define st32
Definition: rz_types_base.h:12
RZ_API void * rz_vector_push(RzVector *vec, void *x)
Definition: vector.c:197
RZ_API void rz_vector_fini(RzVector *vec)
Definition: vector.c:61
#define rz_vector_foreach_prev(vec, it)
Definition: rz_vector.h:173
RZ_API void rz_vector_init(RzVector *vec, size_t elem_size, RzVectorFree free, void *free_user)
Definition: vector.c:33
RzAnalysisValue * dst
Definition: rz_analysis.h:840
RzAnalysisValue * src[3]
Definition: rz_analysis.h:839
const char * reg
Definition: rz_analysis.h:845
RzFlagBind flb
Definition: rz_analysis.h:575
RzFlagSet set
Definition: rz_flag.h:84
RzFlag * f
Definition: rz_flag.h:78
ut64 buflen
Definition: core.c:76
Definition: dis.c:32
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
RZ_API bool rz_analysis_xrefs_set(RzAnalysis *analysis, ut64 from, ut64 to, RzAnalysisXRefType type)
Definition: xrefs.c:117