Rizin
unix-like reverse engineering framework and cli tools
analysis_il.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2021 heersin <teablearcher@gmail.com>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_analysis.h>
5 
11 static void var_state_free(void *e, void *user) {
13  if (!s) {
14  return;
15  }
16  rz_il_value_free(s->val);
17 }
18 
21  if (!r) {
22  return NULL;
23  }
25  return r;
26 }
27 
29  if (!state) {
30  return;
31  }
32  rz_vector_fini(&state->vars);
33 }
34 
39  RZ_NONNULL const char *name, RZ_NONNULL RZ_OWN RzILVal *val) {
42  if (!v) {
44  return;
45  }
46  v->name = name;
47  v->val = val;
48 }
49 
53 RZ_API RZ_OWN RzAnalysisILConfig *rz_analysis_il_config_new(ut32 pc_size, bool big_endian, ut32 mem_key_size) {
54  rz_return_val_if_fail(pc_size && mem_key_size, NULL);
56  if (!r) {
57  return NULL;
58  }
59  r->pc_size = pc_size;
60  r->big_endian = big_endian;
61  r->mem_key_size = mem_key_size;
63  return r;
64 }
65 
67  if (!cfg) {
68  return;
69  }
70  rz_pvector_fini(&cfg->labels);
71  free(cfg);
72 }
73 
78  rz_return_if_fail(cfg && label);
79  rz_pvector_push(&cfg->labels, label);
80 }
81 
83 
85 
90 static void setup_vm_from_config(RzAnalysis *analysis, RzAnalysisILVM *vm, RzAnalysisILConfig *cfg);
92 
100  RzAnalysisILConfig *config = a->cur->il_config(a);
101  if (!config) {
102  return false;
103  }
105  if (!r) {
106  goto ruby_pool;
107  }
108  r->io_buf = rz_buf_new_with_io(&a->iob);
110  if (!r->vm) {
111  rz_buf_free(r->io_buf);
112  free(r);
113  r = NULL;
114  goto ruby_pool;
115  }
116  setup_vm_init_state(r, config->init_state, init_state_reg);
117 ruby_pool:
119  return r;
120 }
121 
126  if (!vm) {
127  return;
128  }
129  rz_il_vm_free(vm->vm);
130  rz_il_reg_binding_free(vm->reg_binding);
131  rz_buf_free(vm->io_buf);
132  free(vm);
133 }
134 
136  if (!a->cur->get_reg_profile) {
137  return false;
138  }
139  // Explicitly use a new reg here!
140  // The a->reg might be changed by the user, but plugins expect exactly
141  // the register profile they supplied. Syncing will later adjust the register
142  // contents if necessary.
143  RzReg *reg = rz_reg_new();
144  if (!reg) {
145  return false;
146  }
147  char *profile = a->cur->get_reg_profile(a);
148  bool succ;
149  if (!profile) {
150  succ = false;
151  goto new_real;
152  }
153  succ = rz_reg_set_profile_string(reg, profile);
154  free(profile);
155  if (!succ) {
156  goto new_real;
157  }
158  if (cfg->reg_bindings) {
159  size_t count = 0;
160  while (cfg->reg_bindings[count]) {
161  count++;
162  }
164  } else {
166  }
167  if (!vm->reg_binding) {
168  succ = false;
169  goto new_real;
170  }
172 new_real:
173  rz_reg_free(reg);
174  return succ;
175 }
176 
178  vm->vm = rz_il_vm_new(0, cfg->pc_size, cfg->big_endian);
179  if (!vm->vm) {
180  return;
181  }
182  if (!setup_regs(analysis, vm, cfg)) {
183  rz_il_vm_free(vm->vm);
184  vm->vm = NULL;
185  return;
186  }
188  void **it;
189  rz_pvector_foreach (&cfg->labels, it) {
190  RzILEffectLabel *lbl = *it;
192  }
193 }
194 
196  if (reg) {
198  }
199  if (is) {
201  rz_vector_foreach(&is->vars, v) {
202  rz_il_vm_set_global_var(vm->vm, v->name, rz_il_value_dup(v->val));
203  }
204  }
205 }
206 
214  rz_return_if_fail(vm && reg);
216 }
217 
227  rz_return_val_if_fail(vm && reg, false);
228  return rz_il_vm_sync_to_reg(vm->vm, vm->reg_binding, reg);
229 }
230 
241  rz_return_val_if_fail(analysis && vm, false);
242  RzAnalysisPlugin *cur = analysis->cur;
243  if (!cur || !analysis->read_at) {
245  }
246 
247  if (reg) {
249  }
250  ut64 addr = rz_bv_to_ut64(vm->vm->pc);
251 
252  ut8 code[32] = { 0 };
253  analysis->read_at(analysis, addr, code, sizeof(code));
254  RzAnalysisOp op = { 0 };
256  RzILOpEffect *ilop = r < 0 ? NULL : op.il_op;
257 
259  if (ilop) {
260  bool succ = rz_il_vm_step(vm->vm, ilop, addr + (op.size > 0 ? op.size : 1));
262  if (reg) {
264  }
265  } else {
267  }
268 
270  return res;
271 }
272 
274 
276 
286  rz_return_val_if_fail(analysis, false);
287  rz_analysis_il_vm_cleanup(analysis);
288  if (!analysis->cur || !analysis->cur->il_config) {
289  return false;
290  }
291  analysis->il_vm = rz_analysis_il_vm_new(analysis, analysis->reg);
292  if (analysis->il_vm) {
293  // rz_analysis_il_vm_new merges the contents of analysis->reg with the plugin's optional RzAnalysisILInitState
294  // Now sync the merged state back:
295  rz_il_vm_sync_to_reg(analysis->il_vm->vm, analysis->il_vm->reg_binding, analysis->reg);
296  }
297  return !!analysis->il_vm;
298 }
299 
304  rz_return_if_fail(analysis);
305  rz_analysis_il_vm_free(analysis->il_vm);
306  analysis->il_vm = NULL;
307 }
308 
#define e(frag)
RZ_API void rz_analysis_il_vm_cleanup(RzAnalysis *analysis)
Definition: analysis_il.c:303
RZ_API void rz_analysis_il_vm_sync_from_reg(RzAnalysisILVM *vm, RZ_NONNULL RzReg *reg)
Definition: analysis_il.c:213
static void setup_vm_init_state(RzAnalysisILVM *vm, RZ_NULLABLE RzAnalysisILInitState *is, RZ_NULLABLE RzReg *reg)
Definition: analysis_il.c:195
RZ_API void rz_analysis_il_config_add_label(RZ_NONNULL RzAnalysisILConfig *cfg, RZ_NONNULL RZ_OWN RzILEffectLabel *label)
Definition: analysis_il.c:77
RZ_API void rz_analysis_il_init_state_free(RzAnalysisILInitState *state)
Definition: analysis_il.c:28
RZ_API RZ_OWN RzAnalysisILConfig * rz_analysis_il_config_new(ut32 pc_size, bool big_endian, ut32 mem_key_size)
Definition: analysis_il.c:53
static bool setup_regs(RzAnalysis *a, RzAnalysisILVM *vm, RzAnalysisILConfig *cfg)
Definition: analysis_il.c:135
RZ_API bool rz_analysis_il_vm_sync_to_reg(RzAnalysisILVM *vm, RZ_NONNULL RzReg *reg)
Definition: analysis_il.c:226
RZ_API void rz_analysis_il_config_free(RzAnalysisILConfig *cfg)
Definition: analysis_il.c:66
RZ_API RZ_OWN RzAnalysisILVM * rz_analysis_il_vm_new(RzAnalysis *a, RZ_NULLABLE RzReg *init_state_reg)
Definition: analysis_il.c:98
static void var_state_free(void *e, void *user)
Definition: analysis_il.c:11
RZ_API bool rz_analysis_il_vm_setup(RzAnalysis *analysis)
Definition: analysis_il.c:285
RZ_API RzAnalysisILInitState * rz_analysis_il_init_state_new()
Definition: analysis_il.c:19
RZ_API RzAnalysisILStepResult rz_analysis_il_vm_step(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisILVM *vm, RZ_NULLABLE RzReg *reg)
Definition: analysis_il.c:240
RZ_API void rz_analysis_il_vm_free(RZ_NULLABLE RzAnalysisILVM *vm)
Definition: analysis_il.c:125
RZ_API void rz_analysis_il_init_state_set_var(RZ_NONNULL RzAnalysisILInitState *state, RZ_NONNULL const char *name, RZ_NONNULL RZ_OWN RzILVal *val)
Definition: analysis_il.c:38
static void setup_vm_from_config(RzAnalysis *analysis, RzAnalysisILVM *vm, RzAnalysisILConfig *cfg)
Definition: analysis_il.c:177
ut16 val
Definition: armass64_const.h:6
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
uint32_t ut32
const char * v
Definition: dsignal.c:12
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
RZ_API RzILMem * rz_il_mem_new(RzBuffer *buf, ut32 key_len)
Definition: mem.c:13
RZ_API RZ_OWN RzILVal * rz_il_value_dup(RZ_NONNULL const RzILVal *val)
Definition: value.c:85
RZ_API void rz_il_value_free(RZ_NULLABLE RzILVal *val)
Definition: value.c:107
RZ_API void rz_il_vm_sync_from_reg(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILRegBinding *rb, RZ_NONNULL RzReg *reg)
Definition: il_reg.c:316
RZ_API void rz_il_vm_setup_reg_binding(RZ_NONNULL RzILVM *vm, RZ_NONNULL RZ_BORROW RzILRegBinding *rb)
Definition: il_reg.c:222
RZ_API bool rz_il_vm_sync_to_reg(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILRegBinding *rb, RZ_NONNULL RzReg *reg)
Definition: il_reg.c:241
RZ_API RzILRegBinding * rz_il_reg_binding_exactly(RZ_NONNULL RzReg *reg, size_t regs_count, RZ_NONNULL RZ_BORROW const char **regs)
Definition: il_reg.c:154
RZ_API void rz_il_reg_binding_free(RzILRegBinding *rb)
Definition: il_reg.c:207
RZ_API RzILRegBinding * rz_il_reg_binding_derive(RZ_NONNULL RzReg *reg)
Calculate a new binding of IL variables against the profile of the given RzReg.
Definition: il_reg.c:35
RZ_API void rz_il_vm_set_global_var(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, RZ_OWN RzILVal *val)
Definition: il_vm.c:193
RZ_API void rz_il_vm_add_mem(RzILVM *vm, RzILMemIndex index, RZ_OWN RzILMem *mem)
Definition: il_vm.c:153
RZ_API RzILVM * rz_il_vm_new(ut64 start_addr, ut32 addr_size, bool big_endian)
Definition: il_vm.c:121
RZ_API void rz_il_vm_free(RzILVM *vm)
Definition: il_vm.c:134
RZ_API void rz_il_vm_add_label(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILEffectLabel *label)
Definition: il_vm.c:296
RZ_API bool rz_il_vm_step(RzILVM *vm, RzILOpEffect *op, ut64 fallthrough_addr)
Definition: il_vm_eval.c:222
RZ_API RzILEffectLabel * rz_il_effect_label_dup(RZ_NONNULL RzILEffectLabel *lbl)
Definition: label.c:28
RZ_API void rz_il_effect_label_free(RzILEffectLabel *lbl)
Definition: label.c:16
#define reg(n)
uint8_t ut8
Definition: lh5801.h:11
const char * name
Definition: op.c:541
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
RZ_API bool rz_reg_set_profile_string(RZ_NONNULL RzReg *reg, RZ_NONNULL const char *profile_str)
Parses a register profile string and sets up all registers accordingly in reg.
Definition: profile.c:431
RZ_API void rz_reg_free(RzReg *reg)
Definition: reg.c:279
RZ_API RzReg * rz_reg_new(void)
Definition: reg.c:286
static RzSocket * s
Definition: rtr.c:28
RzAnalysisILStepResult
Definition: rz_analysis.h:1161
@ RZ_ANALYSIS_IL_STEP_IL_RUNTIME_ERROR
Definition: rz_analysis.h:1164
@ RZ_ANALYSIS_IL_STEP_INVALID_OP
Definition: rz_analysis.h:1165
@ RZ_ANALYSIS_IL_STEP_RESULT_SUCCESS
Definition: rz_analysis.h:1162
@ RZ_ANALYSIS_IL_STEP_RESULT_NOT_SET_UP
Definition: rz_analysis.h:1163
@ RZ_ANALYSIS_OP_MASK_HINT
Definition: rz_analysis.h:443
@ RZ_ANALYSIS_OP_MASK_IL
Definition: rz_analysis.h:446
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_API ut64 rz_bv_to_ut64(RZ_NONNULL const RzBitVector *x)
Definition: bitvector.c:1454
RZ_API void rz_buf_free(RzBuffer *b)
Free all internal data hold by the buffer and the buffer.
Definition: buf.c:1253
RZ_API RZ_OWN RzBuffer * rz_buf_new_with_io(RZ_NONNULL void *iob)
Creates a new buffer wrapping the memory map exposed by RzIOBind.
Definition: buf.c:509
#define RZ_NULLABLE
Definition: rz_types.h:65
#define RZ_OWN
Definition: rz_types.h:62
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_NONNULL
Definition: rz_types.h:64
RZ_API void rz_pvector_init(RzPVector *vec, RzPVectorFree free)
Definition: vector.c:298
RZ_API void rz_pvector_fini(RzPVector *vec)
Definition: vector.c:331
RZ_API void * rz_vector_push(RzVector *vec, void *x)
Definition: vector.c:197
void(* RzPVectorFree)(void *e)
Definition: rz_vector.h:43
#define rz_vector_foreach(vec, it)
Definition: rz_vector.h:169
static void ** rz_pvector_push(RzPVector *vec, void *x)
Definition: rz_vector.h:300
RZ_API void rz_vector_fini(RzVector *vec)
Definition: vector.c:61
RZ_API void rz_vector_init(RzVector *vec, size_t elem_size, RzVectorFree free, void *free_user)
Definition: vector.c:33
#define rz_pvector_foreach(vec, it)
Definition: rz_vector.h:334
#define a(i)
Definition: sha256.c:41
Definition: inftree9.h:24
Definition: dis.h:35
Definition: z80asm.h:102
Description of the global context of an RzAnalysisILVM.
Definition: rz_analysis.h:1134
ut32 pc_size
size of the program counter in bits
Definition: rz_analysis.h:1135
RzPVector labels
global labels, primarily for syscall/hook callbacks
Definition: rz_analysis.h:1143
ut32 mem_key_size
address size for memory 0, bound against IO
Definition: rz_analysis.h:1142
RZ_NULLABLE const char ** reg_bindings
Definition: rz_analysis.h:1141
Description of an initial state of an RzAnalysisILVM.
Definition: rz_analysis.h:1117
Description of the contents of a single IL variable.
Definition: rz_analysis.h:1104
High-level RzIL vm to emulate disassembled code.
Definition: rz_analysis.h:1155
RZ_NONNULL RzILRegBinding * reg_binding
specifies which (global) variables are bound to registers
Definition: rz_analysis.h:1158
RZ_NONNULL RzILVM * vm
low-level vm to execute IL code
Definition: rz_analysis.h:1156
RZ_NONNULL RzBuffer * io_buf
buffer to use for memory 0 (io)
Definition: rz_analysis.h:1157
RzAnalysisILConfigCB il_config
return an IL config to execute lifted code of the given analysis' arch/cpu/bits
Definition: rz_analysis.h:1270
struct rz_analysis_plugin_t * cur
Definition: rz_analysis.h:586
RzAnalysisILVM * il_vm
user-faced VM, NEVER use this for any analysis passes!
Definition: rz_analysis.h:585
Definition: dis.h:43
Definition: dis.c:32
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58