Rizin
unix-like reverse engineering framework and cli tools
il_vm.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2021 Florian Märkl <info@florianmaerkl.de>
2 // SPDX-FileCopyrightText: 2021 heersin <teablearcher@gmail.com>
3 // SPDX-License-Identifier: LGPL-3.0-only
4 
11 #include <rz_il/rz_il_vm.h>
12 
15 
16 static void free_label_kv(HtPPKv *kv) {
17  free(kv->key);
18  rz_il_effect_label_free(kv->value);
19 }
20 
27 RZ_API bool rz_il_vm_init(RzILVM *vm, ut64 start_addr, ut32 addr_size, bool big_endian) {
28  rz_return_val_if_fail(vm, false);
29 
30  if (!rz_il_var_set_init(&vm->global_vars)) {
31  rz_il_vm_fini(vm);
32  return false;
33  }
34  if (!rz_il_var_set_init(&vm->local_vars)) {
35  rz_il_vm_fini(vm);
36  return false;
37  }
39  rz_il_vm_fini(vm);
40  return false;
41  }
43 
44  // Key : string
45  // Val : RzILEffectLabel
46  // Do not dump it since its single signed here, and will be free in `close`
47  HtPPOptions lbl_options = { 0 };
48  lbl_options.cmp = (HtPPListComparator)strcmp;
49  lbl_options.hashfn = (HtPPHashFunction)sdb_hash;
50  lbl_options.dupkey = (HtPPDupKey)strdup;
51  lbl_options.dupvalue = NULL;
52  lbl_options.freefn = (HtPPKvFreeFunc)free_label_kv;
53  lbl_options.elem_size = sizeof(HtPPKv);
54  lbl_options.calcsizeK = (HtPPCalcSizeK)strlen;
55  vm->vm_global_label_table = ht_pp_new_opt(&lbl_options);
56  if (!vm->vm_global_label_table) {
57  RZ_LOG_ERROR("RzIL: cannot allocate VM label hashmap\n");
58  rz_il_vm_fini(vm);
59  return false;
60  }
61 
62  vm->pc = rz_bv_new_from_ut64(addr_size, start_addr);
63  if (!vm->pc) {
64  RZ_LOG_ERROR("RzIL: cannot allocate VM program counter\n");
65  rz_il_vm_fini(vm);
66  return false;
67  }
68 
69  // init jump table of labels
74 
75  vm->lab_count = 0;
76  vm->val_count = 0;
77  vm->addr_size = addr_size;
78  vm->big_endian = big_endian;
79 
81  if (!vm->events) {
82  RZ_LOG_ERROR("RzIL: cannot allocate VM event list\n");
83  rz_il_vm_fini(vm);
84  return false;
85  }
86  return true;
87 }
88 
97 
99 
100  ht_pp_free(vm->vm_global_label_table);
102 
107 
108  rz_bv_free(vm->pc);
109  vm->pc = NULL;
110 
111  rz_list_free(vm->events);
112  vm->events = NULL;
113 }
114 
121 RZ_API RzILVM *rz_il_vm_new(ut64 start_addr, ut32 addr_size, bool big_endian) {
122  RzILVM *vm = RZ_NEW0(RzILVM);
123  if (!vm) {
124  return NULL;
125  }
126  rz_il_vm_init(vm, start_addr, addr_size, big_endian);
127  return vm;
128 }
129 
135  if (!vm) {
136  return;
137  }
138  rz_il_vm_fini(vm);
139  free(vm);
140 }
141 
146  return rz_bv_len(vm->pc);
147 }
148 
154  if (index < rz_pvector_len(&vm->vm_memory)) {
155  rz_mem_free(rz_pvector_at(&vm->vm_memory, index));
156  }
157  rz_pvector_reserve(&vm->vm_memory, index + 1);
158  // Fill up with NULLs until the given index
159  while (rz_pvector_len(&vm->vm_memory) < index + 1) {
161  }
162  rz_pvector_set(&vm->vm_memory, index, mem);
163 }
164 
166  if (index >= rz_pvector_len(&vm->vm_memory)) {
167  return NULL;
168  }
169  return rz_pvector_at(&vm->vm_memory, index);
170 }
171 
177  RzILVar *var = rz_il_var_set_create_var(&vm->global_vars, name, sort);
178  if (!var) {
179  return NULL;
180  }
182  if (!val) {
183  return NULL;
184  }
185  rz_il_var_set_bind(&vm->global_vars, name, val);
186  return var;
187 }
188 
194  rz_return_if_fail(vm && name && val);
195  rz_il_var_set_bind(&vm->global_vars, name, val);
196 }
197 
203  rz_return_if_fail(vm && name && val);
205  rz_il_var_set_bind(&vm->local_vars, name, val);
206 }
207 
216  rz_return_val_if_fail(vm && name && val, NULL);
217  RzILVal *r = rz_il_var_set_remove_var(&vm->local_pure_vars, name);
218  rz_il_var_set_create_var(&vm->local_pure_vars, name, rz_il_value_get_sort(val));
219  rz_il_var_set_bind(&vm->local_pure_vars, name, val);
220  return r;
221 }
222 
228  rz_return_if_fail(vm && name);
229  RzILVal *r = rz_il_var_set_remove_var(&vm->local_pure_vars, name);
230  rz_warn_if_fail(r); // the var should always be bound when calling this function
232  if (prev) {
233  rz_il_var_set_create_var(&vm->local_pure_vars, name, rz_il_value_get_sort(prev));
234  rz_il_var_set_bind(&vm->local_pure_vars, name, prev);
235  }
236 }
237 
239  switch (kind) {
241  return &vm->global_vars;
243  return &vm->local_vars;
245  return &vm->local_pure_vars;
246  }
248  return NULL;
249 }
250 
253  return rz_il_var_set_get(var_set_of_kind(vm, kind), name);
254 }
255 
258  return rz_il_var_set_get_all(var_set_of_kind(vm, kind));
259 }
260 
266  return rz_il_var_set_get_value(var_set_of_kind(vm, kind), name);
267 }
268 
276  rz_return_val_if_fail(vm && lbl_name, NULL);
277  bool found = false;
278  RzILEffectLabel *label = ht_pp_find(vm->vm_global_label_table, lbl_name, &found);
279  if (!found) {
280  return NULL;
281  }
282  return label->addr;
283 }
284 
292  rz_return_val_if_fail(vm && lbl_name, NULL);
293  return ht_pp_find(vm->vm_global_label_table, lbl_name, NULL);
294 }
295 
297  rz_return_if_fail(vm && label);
298  ht_pp_update(vm->vm_global_label_table, label->label_id, label);
299 }
300 
309  rz_return_val_if_fail(vm && name && addr, NULL);
311  lbl->addr = rz_bv_dup(addr);
312  rz_il_vm_add_label(vm, lbl);
313  return lbl;
314 }
315 
325  lbl->addr = NULL;
326  rz_il_vm_add_label(vm, lbl);
327  return lbl;
328 }
329 
337  rz_return_val_if_fail(vm && name && addr, NULL);
338  RzILEffectLabel *lbl = ht_pp_find(vm->vm_global_label_table, name, NULL);
339  if (lbl->addr) {
340  rz_bv_free(lbl->addr);
341  }
342  lbl->addr = rz_bv_dup(addr);
343  return lbl;
344 }
#define RZ_IPI
Definition: analysis_wasm.c:11
ut16 val
Definition: armass64_const.h:6
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
uint32_t ut32
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
RZ_API const KEY_TYPE bool * found
Definition: ht_inc.h:130
RZ_API void rz_il_mem_free(RzILMem *mem)
Definition: mem.c:34
RZ_API RzILSortPure rz_il_value_get_sort(RZ_NONNULL RzILVal *val)
Definition: value.c:127
RZ_API RZ_OWN RzILVal * rz_il_value_new_zero_of(RzILSortPure sort)
Definition: value.c:56
RZ_API void rz_il_value_free(RZ_NULLABLE RzILVal *val)
Definition: value.c:107
RZ_API void rz_il_event_free(RZ_NULLABLE RzILEvent *evt)
Definition: il_events.c:11
RZ_API RZ_BORROW RzILEffectLabel * rz_il_vm_create_label(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, RZ_NONNULL RZ_BORROW RzBitVector *addr)
Definition: il_vm.c:308
RZ_API void rz_il_vm_set_local_var(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, RZ_OWN RzILVal *val)
Definition: il_vm.c:202
RZ_API RZ_BORROW RzBitVector * rz_il_hash_find_addr_by_lblname(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *lbl_name)
Definition: il_vm.c:275
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 RzILLocalPurePrev rz_il_vm_push_local_pure_var(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, RzILVal *val)
Create and assign a new local let binding.
Definition: il_vm.c:215
RZ_IPI RzILOpEffectHandler rz_il_op_handler_effect_table_default[RZ_IL_OP_EFFECT_MAX]
Definition: il_vm_eval.c:104
RZ_API void rz_il_vm_fini(RzILVM *vm)
Definition: il_vm.c:93
static void free_label_kv(HtPPKv *kv)
Definition: il_vm.c:16
static RzILVarSet * var_set_of_kind(RzILVM *vm, RzILVarKind kind)
Definition: il_vm.c:238
RZ_API void rz_il_vm_pop_local_pure_var(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, RzILLocalPurePrev prev)
Remove a local let binding and restore the state for the outer context.
Definition: il_vm.c:227
RZ_API RZ_BORROW RzILEffectLabel * rz_il_vm_update_label(RZ_NONNULL RzILVM *vm, RZ_NONNULL char *name, RZ_NONNULL RZ_BORROW RzBitVector *addr)
Definition: il_vm.c:336
RZ_API RZ_BORROW RzILEffectLabel * rz_il_vm_create_label_lazy(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name)
Definition: il_vm.c:322
RZ_API RZ_BORROW RzILEffectLabel * rz_il_vm_find_label_by_name(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *lbl_name)
Definition: il_vm.c:291
RZ_API RZ_OWN RzPVector * rz_il_vm_get_all_vars(RZ_NONNULL RzILVM *vm, RzILVarKind kind)
Definition: il_vm.c:256
RZ_API RZ_BORROW RzILVal * rz_il_vm_get_var_value(RZ_NONNULL RzILVM *vm, RzILVarKind kind, const char *name)
Definition: il_vm.c:264
RZ_API RzILMem * rz_il_vm_get_mem(RzILVM *vm, RzILMemIndex index)
Definition: il_vm.c:165
RZ_API RZ_BORROW RzILVar * rz_il_vm_create_global_var(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, RzILSortPure sort)
Definition: il_vm.c:175
RZ_IPI RzILOpPureHandler rz_il_op_handler_pure_table_default[RZ_IL_OP_PURE_MAX]
Definition: il_vm_eval.c:67
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 bool rz_il_vm_init(RzILVM *vm, ut64 start_addr, ut32 addr_size, bool big_endian)
Definition: il_vm.c:27
RZ_API RZ_BORROW RzILVar * rz_il_vm_get_var(RZ_NONNULL RzILVM *vm, RzILVarKind kind, const char *name)
Definition: il_vm.c:251
RZ_API ut32 rz_il_vm_get_pc_len(RzILVM *vm)
Definition: il_vm.c:145
RZ_API void rz_il_vm_add_label(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILEffectLabel *label)
Definition: il_vm.c:296
RZ_API RzILEffectLabel * rz_il_effect_label_new(RZ_NONNULL const char *name, RzILEffectLabelType type)
Definition: label.c:6
RZ_API void rz_il_effect_label_free(RzILEffectLabel *lbl)
Definition: label.c:16
@ EFFECT_LABEL_ADDR
Definition: label.h:18
void * mem
Definition: libc.cpp:91
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
ut32 RzILMemIndex
Definition: mem.h:14
#define rz_warn_if_reached()
Definition: rz_assert.h:29
#define rz_warn_if_fail(expr)
Definition: rz_assert.h:35
#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 RZ_OWN RzBitVector * rz_bv_dup(const RZ_NONNULL RzBitVector *bv)
Definition: bitvector.c:167
RZ_API void rz_bv_free(RZ_NULLABLE RzBitVector *bv)
Definition: bitvector.c:85
RZ_API ut32 rz_bv_len(RZ_NONNULL const RzBitVector *bv)
Definition: bitvector.c:1140
RZ_API RZ_OWN RzBitVector * rz_bv_new_from_ut64(ut32 length, ut64 value)
Definition: bitvector.c:1161
@ RZ_IL_OP_PURE_MAX
@ RZ_IL_OP_EFFECT_MAX
void *(* RzILOpPureHandler)(RzILVM *vm, RzILOpPure *op, RZ_NONNULL RZ_OUT RzILTypePure *type)
Evaluation callback for a single pure opcode.
Definition: rz_il_vm.h:24
bool(* RzILOpEffectHandler)(RzILVM *vm, RzILOpEffect *op)
Evaluation (execution) callback for a single effect opcode.
Definition: rz_il_vm.h:30
RZ_NULLABLE RzILVal * RzILLocalPurePrev
Definition: rz_il_vm.h:86
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API void rz_mem_free(void *)
Definition: mem.c:361
#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
#define RZ_NEWS0(x, y)
Definition: rz_types.h:282
#define RZ_BORROW
Definition: rz_types.h:63
static void ** rz_pvector_reserve(RzPVector *vec, size_t capacity)
Definition: rz_vector.h:312
static void rz_pvector_set(RzPVector *vec, size_t index, void *e)
Definition: rz_vector.h:241
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
static size_t rz_pvector_len(const RzPVector *vec)
Definition: rz_vector.h:231
void(* RzPVectorFree)(void *e)
Definition: rz_vector.h:43
static void ** rz_pvector_push(RzPVector *vec, void *x)
Definition: rz_vector.h:300
static void * rz_pvector_at(const RzPVector *vec, size_t index)
Definition: rz_vector.h:236
RZ_API ut32 sdb_hash(const char *key)
Definition: util.c:22
structure for bitvector
Definition: rz_bitvector.h:19
Definition: dis.h:35
Definition: z80asm.h:102
RzBitVector * addr
RzBitVector address if EFFECT_LABEL_ADDR.
Definition: label.h:27
A single memory as part of the RzIL VM.
Definition: mem.h:26
Holds a set of variable definitions and their current contents This is meant only as a low-level cont...
Definition: variable.h:31
Definition of a variable inside the vm.
Definition: variable.h:19
Low-level VM to execute raw IL code.
Definition: rz_il_vm.h:37
RzILOpPureHandler * op_handler_pure_table
Array of Handler, handler can be indexed by opcode.
Definition: rz_il_vm.h:47
RzILVarSet local_vars
All local variables, created by local set ops.
Definition: rz_il_vm.h:39
ut32 lab_count
count for VM predefined things
Definition: rz_il_vm.h:42
RzList * events
List of events that has happened in the last step.
Definition: rz_il_vm.h:49
ut32 addr_size
size of address space
Definition: rz_il_vm.h:43
bool big_endian
Sets the endianness of the memory reads/writes operations.
Definition: rz_il_vm.h:50
ut32 val_count
Definition: rz_il_vm.h:42
RzILVarSet local_pure_vars
All local variables, during execution temporarily bound by let, only usable in pure expressions and i...
Definition: rz_il_vm.h:40
RzILVarSet global_vars
All global variables (usually bound to registers)
Definition: rz_il_vm.h:38
RzBitVector * pc
Program Counter of VM.
Definition: rz_il_vm.h:46
RzPVector vm_memory
Memories available in the VM, by their index. May be sparse (contain NULLs).
Definition: rz_il_vm.h:41
HtPP * vm_global_label_table
Hashtable to maintain the label and address.
Definition: rz_il_vm.h:44
RzILOpEffectHandler * op_handler_effect_table
Array of Handler, handler can be indexed by opcode.
Definition: rz_il_vm.h:48
RZ_API RZ_BORROW RzILVar * rz_il_var_set_create_var(RzILVarSet *vs, const char *name, RzILSortPure sort)
Definition: variable.c:90
RZ_API bool rz_il_var_set_bind(RzILVarSet *vs, const char *name, RZ_OWN RzILVal *val)
Definition: variable.c:129
RZ_API bool rz_il_var_set_init(RzILVarSet *vs)
Definition: variable.c:60
RZ_API RZ_OWN RzPVector * rz_il_var_set_get_all(RzILVarSet *vs)
Definition: variable.c:160
RZ_API RZ_BORROW RzILVar * rz_il_var_set_get(RzILVarSet *vs, const char *name)
Definition: variable.c:148
RZ_API RZ_BORROW RzILVal * rz_il_var_set_get_value(RzILVarSet *vs, const char *name)
Definition: variable.c:173
RZ_API void rz_il_var_set_fini(RzILVarSet *vs)
Definition: variable.c:76
RZ_API RZ_OWN RZ_NULLABLE RzILVal * rz_il_var_set_remove_var(RzILVarSet *vs, const char *name)
Definition: variable.c:107
RzILVarKind
Definition: variable.h:46
@ RZ_IL_VAR_KIND_GLOBAL
global var, usually bound to a physical representation like a register.
Definition: variable.h:47
@ RZ_IL_VAR_KIND_LOCAL
local var, defined and assigned by set ops, mutable and useable across effects.
Definition: variable.h:48
@ RZ_IL_VAR_KIND_LOCAL_PURE
local pure var, bound only by let expressions, scope is limited to the let's pure body,...
Definition: variable.h:49
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58