[RzIL] Rework Variable Handling (#2174)
There are now three kinds of vars: global, local and local pure. Global and local pure are exactly like in BAP, local ones are defined by their initial set op and have the scope of a single lifted instruction. The set op now handles both global and local vars, let is now pure and binds only inside its body. Vars have static types, global and local are always mutable, local pure naturally immutable. The var op specifies the kind of variable to take from, and the individual variable sets are separate. This corresponds to BAP's behavior where the kind of variable is part of the identifier. Variable content storage has also been rewritten and RzILBag removed.
This commit is contained in:
parent
2e065789a7
commit
54318a2268
28 changed files with 968 additions and 1104 deletions
|
|
@ -32,20 +32,28 @@ typedef struct bf_context_t {
|
|||
ut64 op_count;
|
||||
} BfContext;
|
||||
|
||||
#define bf_il_ptr() rz_il_op_new_var("ptr")
|
||||
#define bf_il_set_ptr(x) rz_il_op_new_set("ptr", x)
|
||||
#define bf_il_ptr() rz_il_op_new_var("ptr", RZ_IL_VAR_KIND_GLOBAL)
|
||||
#define bf_il_set_ptr(x) rz_il_op_new_set("ptr", false, x)
|
||||
#define bf_il_one(l) rz_il_op_new_bitv_from_ut64(l, 1)
|
||||
|
||||
static void bf_syscall_read(RzILVM *vm, RzILOpEffect *op) {
|
||||
ut8 c = getc(stdin);
|
||||
RzBitVector *bv = rz_bv_new_from_ut64(BF_BYTE_SIZE, c);
|
||||
RzILVal *ptr_val = rz_il_hash_find_val_by_name(vm, "ptr");
|
||||
rz_il_vm_mem_store(vm, 0, ptr_val->data.bv, bv);
|
||||
RzILVal *ptr_val = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, "ptr");
|
||||
if (ptr_val->type == RZ_IL_TYPE_PURE_BITVECTOR) {
|
||||
rz_il_vm_mem_store(vm, 0, ptr_val->data.bv, bv);
|
||||
} else {
|
||||
rz_warn_if_reached();
|
||||
}
|
||||
rz_bv_free(bv);
|
||||
}
|
||||
|
||||
static void bf_syscall_write(RzILVM *vm, RzILOpEffect *op) {
|
||||
RzILVal *ptr_val = rz_il_hash_find_val_by_name(vm, "ptr");
|
||||
RzILVal *ptr_val = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, "ptr");
|
||||
if (ptr_val->type != RZ_IL_TYPE_PURE_BITVECTOR) {
|
||||
rz_warn_if_reached();
|
||||
return;
|
||||
}
|
||||
RzBitVector *bv = rz_il_vm_mem_load(vm, 0, ptr_val->data.bv);
|
||||
ut32 c = rz_bv_to_ut32(bv);
|
||||
putchar(c);
|
||||
|
|
@ -148,7 +156,7 @@ RzILOpEffect *bf_llimit(RzILVM *vm, BfContext *ctx, ut64 id, ut64 addr) {
|
|||
free(dst_lbl_name);
|
||||
free(to_free);
|
||||
|
||||
RzILOpBitVector *var = rz_il_op_new_var("ptr");
|
||||
RzILOpBitVector *var = rz_il_op_new_var("ptr", RZ_IL_VAR_KIND_GLOBAL);
|
||||
RzILOpBool *cond = rz_il_op_new_non_zero(rz_il_op_new_load(0, var));
|
||||
|
||||
// goto ]
|
||||
|
|
@ -185,7 +193,7 @@ RzILOpEffect *bf_rlimit(RzILVM *vm, BfContext *ctx, ut64 id, ut64 addr) {
|
|||
rz_return_val_if_fail(dst_lbl_name, NULL);
|
||||
dst_label = rz_il_vm_find_label_by_name(vm, dst_lbl_name);
|
||||
|
||||
RzILOpBitVector *var = rz_il_op_new_var("ptr");
|
||||
RzILOpBitVector *var = rz_il_op_new_var("ptr", RZ_IL_VAR_KIND_GLOBAL);
|
||||
RzILOpBool *cond = rz_il_op_new_non_zero(rz_il_op_new_load(0, var));
|
||||
|
||||
// goto [
|
||||
|
|
|
|||
135
librz/core/cil.c
135
librz/core/cil.c
|
|
@ -437,48 +437,30 @@ RZ_IPI bool rz_core_analysis_rzil_vm_set(RzCore *core, const char *var_name, ut6
|
|||
return false;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
RzBitVector *bv = NULL;
|
||||
|
||||
if (!strcmp(var_name, "PC")) {
|
||||
found = true;
|
||||
bv = rz_bv_new_from_ut64(rzil->vm->pc->len, value);
|
||||
RzBitVector *bv = rz_bv_new_from_ut64(rzil->vm->pc->len, value);
|
||||
rz_bv_free(rzil->vm->pc);
|
||||
rzil->vm->pc = bv;
|
||||
} else {
|
||||
RzILVal *oldval = NULL;
|
||||
RzILVal *newval = NULL;
|
||||
RzILVar *var = NULL;
|
||||
void **it = NULL;
|
||||
rz_pvector_foreach (&rzil->vm->vm_global_variable_list, it) {
|
||||
var = *it;
|
||||
if (var_name && strcmp(var_name, var->var_name)) {
|
||||
continue;
|
||||
}
|
||||
found = true;
|
||||
oldval = rz_il_hash_find_val_by_var(rzil->vm, var);
|
||||
switch (oldval->type) {
|
||||
case RZ_IL_VAR_TYPE_BV:
|
||||
bv = rz_bv_new_from_ut64(oldval->data.bv->len, value);
|
||||
newval = rz_il_vm_create_value_bitv(rzil->vm, bv);
|
||||
break;
|
||||
case RZ_IL_VAR_TYPE_BOOL:
|
||||
newval = rz_il_vm_create_value_bool(rzil->vm, value);
|
||||
break;
|
||||
case RZ_IL_VAR_TYPE_UNK:
|
||||
RZ_LOG_ERROR("RzIL: cannot set an Unknown type via command line\n");
|
||||
break;
|
||||
default:
|
||||
rz_warn_if_reached();
|
||||
break;
|
||||
}
|
||||
|
||||
rz_il_hash_cancel_binding(rzil->vm, var);
|
||||
rz_il_hash_bind(rzil->vm, var, newval);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return found;
|
||||
|
||||
RzILVar *var = rz_il_vm_get_var(rzil->vm, RZ_IL_VAR_KIND_GLOBAL, var_name);
|
||||
if (!var) {
|
||||
return false;
|
||||
}
|
||||
RzILVal *val = NULL;
|
||||
switch (var->sort.type) {
|
||||
case RZ_IL_TYPE_PURE_BITVECTOR:
|
||||
val = rz_il_value_new_bitv(rz_bv_new_from_ut64(var->sort.props.bv.length, value));
|
||||
break;
|
||||
case RZ_IL_TYPE_PURE_BOOL:
|
||||
val = rz_il_value_new_bool(rz_il_bool_new(value != 0));
|
||||
break;
|
||||
}
|
||||
if (val) {
|
||||
rz_il_vm_set_global_var(rzil->vm, var_name, val);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef struct il_print_t {
|
||||
|
|
@ -526,23 +508,6 @@ static void rzil_print_register_bitv(RzBitVector *number, ILPrint *p) {
|
|||
free(hex);
|
||||
}
|
||||
|
||||
static void rzil_print_register_unk(ILPrint *p) {
|
||||
switch (p->mode) {
|
||||
case RZ_OUTPUT_MODE_STANDARD:
|
||||
rz_strbuf_appendf(p_sb(p->ptr), " %s: unk", p->name);
|
||||
break;
|
||||
case RZ_OUTPUT_MODE_TABLE:
|
||||
rz_table_add_rowf(p_tbl(p->ptr), "sss", p->name, "unkn", "");
|
||||
break;
|
||||
case RZ_OUTPUT_MODE_JSON:
|
||||
pj_knull(p_pj(p->ptr), p->name);
|
||||
break;
|
||||
default:
|
||||
rz_cons_printf("unknown\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RZ_IPI void rz_core_analysis_rzil_vm_status(RzCore *core, const char *var_name, RzOutputMode mode) {
|
||||
RzAnalysisRzil *rzil = core->analysis->rzil;
|
||||
if (!rzil || !rzil->vm) {
|
||||
|
|
@ -574,35 +539,39 @@ RZ_IPI void rz_core_analysis_rzil_vm_status(RzCore *core, const char *var_name,
|
|||
rzil_print_register_bitv(rzil->vm->pc, &p);
|
||||
}
|
||||
|
||||
void **it;
|
||||
rz_pvector_foreach (&rzil->vm->vm_global_variable_list, it) {
|
||||
RzILVar *var = *it;
|
||||
if (var_name && strcmp(var_name, var->var_name)) {
|
||||
continue;
|
||||
}
|
||||
p.name = var->var_name;
|
||||
RzILVal *val = rz_il_hash_find_val_by_var(rzil->vm, var);
|
||||
switch (val->type) {
|
||||
case RZ_IL_VAR_TYPE_BV:
|
||||
rzil_print_register_bitv(val->data.bv, &p);
|
||||
break;
|
||||
case RZ_IL_VAR_TYPE_BOOL:
|
||||
rzil_print_register_bool(val->data.b->b, &p);
|
||||
break;
|
||||
case RZ_IL_VAR_TYPE_UNK:
|
||||
rzil_print_register_unk(&p);
|
||||
break;
|
||||
default:
|
||||
rz_warn_if_reached();
|
||||
break;
|
||||
}
|
||||
if (var_name) {
|
||||
break;
|
||||
}
|
||||
if (rz_strbuf_length(p_sb(p.ptr)) > 95) {
|
||||
rz_cons_printf("%s\n", rz_strbuf_get(p_sb(p.ptr)));
|
||||
rz_strbuf_fini(p_sb(p.ptr));
|
||||
RzPVector *global_vars = rz_il_vm_get_all_vars(rzil->vm, RZ_IL_VAR_KIND_GLOBAL);
|
||||
if (global_vars) {
|
||||
void **it;
|
||||
rz_pvector_foreach (global_vars, it) {
|
||||
RzILVar *var = *it;
|
||||
if (var_name && strcmp(var_name, var->name)) {
|
||||
continue;
|
||||
}
|
||||
p.name = var->name;
|
||||
RzILVal *val = rz_il_vm_get_var_value(rzil->vm, RZ_IL_VAR_KIND_GLOBAL, var->name);
|
||||
if (!val) {
|
||||
continue;
|
||||
}
|
||||
switch (val->type) {
|
||||
case RZ_IL_TYPE_PURE_BITVECTOR:
|
||||
rzil_print_register_bitv(val->data.bv, &p);
|
||||
break;
|
||||
case RZ_IL_TYPE_PURE_BOOL:
|
||||
rzil_print_register_bool(val->data.b->b, &p);
|
||||
break;
|
||||
default:
|
||||
rz_warn_if_reached();
|
||||
break;
|
||||
}
|
||||
if (var_name) {
|
||||
break;
|
||||
}
|
||||
if (rz_strbuf_length(p_sb(p.ptr)) > 95) {
|
||||
rz_cons_printf("%s\n", rz_strbuf_get(p_sb(p.ptr)));
|
||||
rz_strbuf_fini(p_sb(p.ptr));
|
||||
}
|
||||
}
|
||||
rz_pvector_free(global_vars);
|
||||
}
|
||||
|
||||
char *out = NULL;
|
||||
|
|
|
|||
|
|
@ -1,136 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2021 heersin <teablearcher@gmail.com>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <rz_il/definitions/bag.h>
|
||||
|
||||
/**
|
||||
* Create a bag to store all RzILValue instances
|
||||
* Only used in VM to clean garbage values (unused RzILVal)
|
||||
* \param capacity max size of bag
|
||||
* \param func function pointer to free element
|
||||
* \return RzILBag pointer
|
||||
*/
|
||||
RZ_API RzILBag *rz_il_new_bag(int capacity, RzILBagFreeFunc func) {
|
||||
RzILBag *bag = RZ_NEW0(RzILBag);
|
||||
if (!bag) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bag->capacity = capacity;
|
||||
bag->data_list = RZ_NEWS0(void *, capacity);
|
||||
bag->item_count = 0;
|
||||
bag->next_pos = 0;
|
||||
bag->next_pos_stack = RZ_NEWS0(int, capacity);
|
||||
bag->sp = 0; // sp point to first empty
|
||||
bag->free_func = func;
|
||||
|
||||
// init stack
|
||||
for (int i = 0; i < capacity; ++i) {
|
||||
bag->next_pos_stack[i] = i; // empty 1 2 3 4 ......
|
||||
}
|
||||
|
||||
return bag;
|
||||
}
|
||||
|
||||
int rz_il_find_in_bag(RzILBag *bag, void *item) {
|
||||
void *cur_item;
|
||||
for (int i = 0; i < bag->capacity; ++i) {
|
||||
cur_item = bag->data_list[i];
|
||||
if (cur_item == item) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
// not found
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an element from bag
|
||||
* \param bag RzILBag instance
|
||||
* \param item pointer pointed to the item you want to remove from current bag
|
||||
* \return true if successfully removed
|
||||
*/
|
||||
RZ_API bool rz_il_rm_from_bag(RZ_NONNULL RzILBag *bag, RZ_NONNULL void *item) {
|
||||
rz_return_val_if_fail(bag && item, false);
|
||||
int pos = rz_il_find_in_bag(bag, item);
|
||||
if (pos == -1) {
|
||||
// not in bag
|
||||
return false;
|
||||
}
|
||||
|
||||
// in bag, remove it
|
||||
if (bag->free_func) {
|
||||
bag->free_func(bag->data_list[pos]);
|
||||
}
|
||||
bag->data_list[pos] = NULL;
|
||||
|
||||
// there is a new spare space
|
||||
// record it (push this position to stack)
|
||||
bag->next_pos_stack[bag->sp] = pos;
|
||||
bag->sp -= 1;
|
||||
|
||||
// item count
|
||||
bag->item_count -= 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store an item into bag
|
||||
* \param bag RzILBag, point to the bag
|
||||
* \param item A pointer to an element you want to store
|
||||
* \return true if store successfully
|
||||
*/
|
||||
RZ_API bool rz_il_add_to_bag(RZ_NONNULL RzILBag *bag, RZ_NONNULL void *item) {
|
||||
rz_return_val_if_fail(bag && item, false);
|
||||
if (bag->item_count >= bag->capacity) {
|
||||
RZ_LOG_ERROR("[Cannot Carry More Values]\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rz_il_find_in_bag(bag, item) != -1) {
|
||||
// already in bag
|
||||
return false;
|
||||
}
|
||||
|
||||
// not in bag, add it
|
||||
bag->data_list[bag->next_pos] = item;
|
||||
|
||||
// pop next_pos
|
||||
bag->sp += 1;
|
||||
bag->next_pos = bag->next_pos_stack[bag->sp];
|
||||
|
||||
// item count
|
||||
bag->item_count += 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the bag
|
||||
* \param bag RzILBag, point to the bag
|
||||
*/
|
||||
RZ_API void rz_il_free_bag(RzILBag *bag) {
|
||||
if (!bag) {
|
||||
return;
|
||||
}
|
||||
|
||||
// free data
|
||||
for (int i = 0; i < bag->capacity; ++i) {
|
||||
void *cur_item = bag->data_list[i];
|
||||
if (cur_item) {
|
||||
if (bag->free_func) {
|
||||
bag->free_func(cur_item);
|
||||
}
|
||||
bag->data_list[i] = NULL;
|
||||
}
|
||||
}
|
||||
free(bag->data_list);
|
||||
|
||||
// free stack
|
||||
free(bag->next_pos_stack);
|
||||
|
||||
// free bag
|
||||
free(bag);
|
||||
}
|
||||
|
|
@ -5,6 +5,21 @@
|
|||
|
||||
#include <rz_il/definitions/value.h>
|
||||
|
||||
/**
|
||||
* Returns a new RzILVal (Any type)
|
||||
* \param type RzILVarType to set of the value
|
||||
* \return val RzILVal, pointer to this value
|
||||
*/
|
||||
RZ_API RZ_OWN RzILVal *rz_il_value_new(RzILTypePure type) {
|
||||
RzILVal *ret;
|
||||
ret = RZ_NEW0(RzILVal);
|
||||
if (!ret) {
|
||||
return NULL;
|
||||
}
|
||||
ret->type = type;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new RzILVal (Bitvector type)
|
||||
* \param bv RzBitVector to set
|
||||
|
|
@ -12,7 +27,7 @@
|
|||
*/
|
||||
RZ_API RZ_OWN RzILVal *rz_il_value_new_bitv(RZ_NONNULL RzBitVector *bv) {
|
||||
rz_return_val_if_fail(bv, NULL);
|
||||
RzILVal *ret = rz_il_value_new(RZ_IL_VAR_TYPE_BV);
|
||||
RzILVal *ret = rz_il_value_new(RZ_IL_TYPE_PURE_BITVECTOR);
|
||||
if (!ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -27,7 +42,7 @@ RZ_API RZ_OWN RzILVal *rz_il_value_new_bitv(RZ_NONNULL RzBitVector *bv) {
|
|||
*/
|
||||
RZ_API RZ_OWN RzILVal *rz_il_value_new_bool(RZ_NONNULL RzILBool *b) {
|
||||
rz_return_val_if_fail(b, NULL);
|
||||
RzILVal *ret = rz_il_value_new(RZ_IL_VAR_TYPE_BOOL);
|
||||
RzILVal *ret = rz_il_value_new(RZ_IL_TYPE_PURE_BOOL);
|
||||
if (!ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -36,17 +51,29 @@ RZ_API RZ_OWN RzILVal *rz_il_value_new_bool(RZ_NONNULL RzILBool *b) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a new RzILVal (Any type)
|
||||
* \param type RzILVarType to set of the value
|
||||
* \return val RzILVal, pointer to this value
|
||||
* Create a value of the given sort filled with all zeroes or false
|
||||
*/
|
||||
RZ_API RZ_OWN RzILVal *rz_il_value_new(RzILVarType type) {
|
||||
RzILVal *ret;
|
||||
ret = RZ_NEW0(RzILVal);
|
||||
RZ_API RZ_OWN RzILVal *rz_il_value_new_zero_of(RzILSortPure sort) {
|
||||
RzILVal *ret = rz_il_value_new(sort.type);
|
||||
if (!ret) {
|
||||
return NULL;
|
||||
}
|
||||
ret->type = type;
|
||||
switch (sort.type) {
|
||||
case RZ_IL_TYPE_PURE_BOOL:
|
||||
ret->data.b = rz_il_bool_new(false);
|
||||
if (!ret->data.b) {
|
||||
rz_il_value_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case RZ_IL_TYPE_PURE_BITVECTOR:
|
||||
ret->data.bv = rz_bv_new_zero(sort.props.bv.length);
|
||||
if (!ret->data.bv) {
|
||||
rz_il_value_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -61,14 +88,12 @@ RZ_API RZ_OWN RzILVal *rz_il_value_dup(RZ_NONNULL RzILVal *val) {
|
|||
RzBitVector *bv = NULL;
|
||||
|
||||
switch (val->type) {
|
||||
case RZ_IL_VAR_TYPE_BOOL:
|
||||
case RZ_IL_TYPE_PURE_BOOL:
|
||||
b = rz_il_bool_new(val->data.b->b);
|
||||
return b ? rz_il_value_new_bool(b) : NULL;
|
||||
case RZ_IL_VAR_TYPE_BV:
|
||||
case RZ_IL_TYPE_PURE_BITVECTOR:
|
||||
bv = rz_bv_dup(val->data.bv);
|
||||
return bv ? rz_il_value_new_bitv(bv) : NULL;
|
||||
case RZ_IL_VAR_TYPE_UNK:
|
||||
return rz_il_value_new_unk();
|
||||
default:
|
||||
rz_warn_if_reached();
|
||||
return NULL;
|
||||
|
|
@ -83,18 +108,27 @@ RZ_API void rz_il_value_free(RZ_NULLABLE RzILVal *val) {
|
|||
if (!val) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (val->type) {
|
||||
case RZ_IL_VAR_TYPE_BOOL:
|
||||
case RZ_IL_TYPE_PURE_BOOL:
|
||||
rz_il_bool_free(val->data.b);
|
||||
break;
|
||||
case RZ_IL_VAR_TYPE_BV:
|
||||
case RZ_IL_TYPE_PURE_BITVECTOR:
|
||||
rz_bv_free(val->data.bv);
|
||||
break;
|
||||
case RZ_IL_VAR_TYPE_UNK:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
free(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sort that \p val belongs to
|
||||
*/
|
||||
RZ_API RzILSortPure rz_il_value_get_sort(RZ_NONNULL RzILVal *val) {
|
||||
RzILSortPure r = { 0 };
|
||||
r.type = val->type;
|
||||
if (val->type == RZ_IL_TYPE_PURE_BITVECTOR) {
|
||||
r.props.bv.length = rz_bv_len(val->data.bv);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,23 +8,20 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* New a variable with RzILVarType
|
||||
* \param name string, name of variable
|
||||
* \return var RzILVar, pointer to this variable
|
||||
* Create a new variable description
|
||||
*/
|
||||
RZ_API RZ_OWN RzILVar *rz_il_variable_new(RZ_NONNULL const char *name, RzILVarType type, bool is_mutable) {
|
||||
RZ_API RZ_OWN RzILVar *rz_il_variable_new(RZ_NONNULL const char *name, RzILSortPure sort) {
|
||||
rz_return_val_if_fail(name, NULL);
|
||||
RzILVar *ret = RZ_NEW0(RzILVar);
|
||||
if (!ret) {
|
||||
return NULL;
|
||||
}
|
||||
ret->var_name = strdup(name);
|
||||
if (!ret->var_name) {
|
||||
ret->name = strdup(name);
|
||||
if (!ret->name) {
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
ret->is_mutable = is_mutable;
|
||||
ret->type = type;
|
||||
ret->sort = sort;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -36,6 +33,144 @@ RZ_API void rz_il_variable_free(RZ_NULLABLE RzILVar *var) {
|
|||
if (!var) {
|
||||
return;
|
||||
}
|
||||
free(var->var_name);
|
||||
free(var->name);
|
||||
free(var);
|
||||
}
|
||||
}
|
||||
|
||||
// Variable Set
|
||||
|
||||
static void var_ht_free(HtPPKv *kv) {
|
||||
free(kv->key);
|
||||
rz_il_variable_free(kv->value);
|
||||
}
|
||||
|
||||
static void val_ht_free(HtPPKv *kv) {
|
||||
free(kv->key);
|
||||
rz_il_value_free(kv->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize \p vs as an empty variable set
|
||||
*
|
||||
* This makes sure that if a failure occurs, the contents are still zeroed out,
|
||||
* so it is safe (but not required) to call rz_il_var_set_fini(), even if the init failed.
|
||||
*
|
||||
* \return whether the initialization succeeded
|
||||
*/
|
||||
RZ_API bool rz_il_var_set_init(RzILVarSet *vs) {
|
||||
rz_return_val_if_fail(vs, false);
|
||||
memset(vs, 0, sizeof(*vs));
|
||||
vs->vars = ht_pp_new(NULL, var_ht_free, NULL);
|
||||
if (!vs->vars) {
|
||||
return false;
|
||||
}
|
||||
vs->contents = ht_pp_new(NULL, val_ht_free, NULL);
|
||||
if (!vs->contents) {
|
||||
ht_pp_free(vs->vars);
|
||||
vs->vars = NULL;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
RZ_API void rz_il_var_set_fini(RzILVarSet *vs) {
|
||||
ht_pp_free(vs->vars);
|
||||
ht_pp_free(vs->contents);
|
||||
}
|
||||
|
||||
RZ_API void rz_il_var_set_reset(RzILVarSet *vs) {
|
||||
rz_il_var_set_fini(vs);
|
||||
rz_il_var_set_init(vs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new variable of the given name and sort.
|
||||
* If a variable of this name already exists, nothing happens.
|
||||
*/
|
||||
RZ_API RZ_BORROW RzILVar *rz_il_var_set_create_var(RzILVarSet *vs, const char *name, RzILSortPure sort) {
|
||||
rz_return_val_if_fail(vs && name, NULL);
|
||||
if (ht_pp_find(vs->vars, name, NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
RzILVar *var = rz_il_variable_new(name, sort);
|
||||
if (!var) {
|
||||
return NULL;
|
||||
}
|
||||
ht_pp_insert(vs->vars, name, var);
|
||||
return var;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a variable, if it exists
|
||||
* \return the variable's variable, to be freed by the caller
|
||||
*/
|
||||
RZ_API RZ_OWN RZ_NULLABLE RzILVal *rz_il_var_set_remove_var(RzILVarSet *vs, const char *name) {
|
||||
rz_return_val_if_fail(vs && name, NULL);
|
||||
ht_pp_delete(vs->vars, name);
|
||||
HtPPKv *kv = ht_pp_find_kv(vs->contents, name, NULL);
|
||||
if (!kv) {
|
||||
return NULL;
|
||||
}
|
||||
RzILVal *r = kv->value;
|
||||
kv->value = NULL;
|
||||
ht_pp_delete(vs->contents, name);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the contents of the variable called \p name to \p val
|
||||
*
|
||||
* In order for this to succeed, a variable called \p name must already exist
|
||||
* and the sort of \p val must match the variable's sort. Checking this is done
|
||||
* inside this function, so calling it with invalid args in that sense is fine.
|
||||
*
|
||||
* \return whether the value was successfully bound
|
||||
*/
|
||||
RZ_API bool rz_il_var_set_bind(RzILVarSet *vs, const char *name, RZ_OWN RzILVal *val) {
|
||||
rz_return_val_if_fail(vs && name && val, NULL);
|
||||
RzILVar *var = ht_pp_find(vs->vars, name, NULL);
|
||||
if (!var || !rz_il_sort_pure_eq(var->sort, rz_il_value_get_sort(val))) {
|
||||
if (!var) {
|
||||
RZ_LOG_ERROR("Attempted to bind value to non-existent variable \"%s\"\n", name);
|
||||
} else {
|
||||
RZ_LOG_ERROR("Attempted to bind mis-sorted value to variable \"%s\"\n", name);
|
||||
}
|
||||
rz_il_value_free(val);
|
||||
return false;
|
||||
}
|
||||
ht_pp_update(vs->contents, name, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the definition of the variable called \p name
|
||||
*/
|
||||
RZ_API RZ_BORROW RzILVar *rz_il_var_set_get(RzILVarSet *vs, const char *name) {
|
||||
return ht_pp_find(vs->vars, name, NULL);
|
||||
}
|
||||
|
||||
static bool vars_collect_cb(void *user, const void *k, const void *v) {
|
||||
rz_pvector_push(user, (void *)v);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all variable definitions in the given set
|
||||
*/
|
||||
RZ_API RZ_OWN RzPVector /* <RzILVar> */ *rz_il_var_set_get_all(RzILVarSet *vs) {
|
||||
rz_return_val_if_fail(vs, NULL);
|
||||
RzPVector *r = rz_pvector_new(NULL);
|
||||
if (!r) {
|
||||
return NULL;
|
||||
}
|
||||
ht_pp_foreach(vs->vars, vars_collect_cb, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current value of the variable called \p name
|
||||
*/
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_var_set_get_value(RzILVarSet *vs, const char *name) {
|
||||
rz_return_val_if_fail(vs && name, NULL);
|
||||
return ht_pp_find(vs->contents, name, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -177,6 +177,26 @@ static void il_opdmp_ite(RzILOpPure *op, RzStrBuf *sb, PJ *pj) {
|
|||
il_op_param_3("ite", op->op.ite, pure, condition, pure, x, pure, y);
|
||||
}
|
||||
|
||||
static void il_opdmp_let(RzILOpPure *op, RzStrBuf *sb, PJ *pj) {
|
||||
RzILOpArgsLet *opx = &op->op.let;
|
||||
if (sb) {
|
||||
rz_strbuf_appendf(sb, "let(v:%s, exp:", opx->name);
|
||||
il_op_pure_resolve(opx->exp, sb, pj);
|
||||
rz_strbuf_append(sb, ", body:");
|
||||
il_op_pure_resolve(opx->body, sb, pj);
|
||||
rz_strbuf_append(sb, ")");
|
||||
} else {
|
||||
pj_o(pj);
|
||||
pj_ks(pj, "opcode", "let");
|
||||
pj_ks(pj, "dst", opx->name);
|
||||
pj_k(pj, "exp");
|
||||
il_op_pure_resolve(opx->exp, sb, pj);
|
||||
pj_k(pj, "body");
|
||||
il_op_pure_resolve(opx->body, sb, pj);
|
||||
pj_end(pj);
|
||||
}
|
||||
}
|
||||
|
||||
static void il_opdmp_bool_false(RzILOpPure *op, RzStrBuf *sb, PJ *pj) {
|
||||
if (sb) {
|
||||
rz_strbuf_append(sb, "bool(false)");
|
||||
|
|
@ -433,23 +453,6 @@ static void il_opdmp_set(RzILOpEffect *op, RzStrBuf *sb, PJ *pj) {
|
|||
}
|
||||
}
|
||||
|
||||
static void il_opdmp_let(RzILOpEffect *op, RzStrBuf *sb, PJ *pj) {
|
||||
RzILOpArgsLet *opx = &op->op.let;
|
||||
if (sb) {
|
||||
rz_strbuf_appendf(sb, "let(v:%s, x:", opx->v);
|
||||
il_op_pure_resolve(opx->x, sb, pj);
|
||||
rz_strbuf_append(sb, opx->mut ? ")" : ", const)");
|
||||
} else {
|
||||
pj_o(pj);
|
||||
pj_ks(pj, "opcode", "let");
|
||||
pj_ks(pj, "dst", opx->v);
|
||||
pj_kb(pj, "const", !opx->mut);
|
||||
pj_k(pj, "src");
|
||||
il_op_pure_resolve(opx->x, sb, pj);
|
||||
pj_end(pj);
|
||||
}
|
||||
}
|
||||
|
||||
static void il_opdmp_jmp(RzILOpEffect *op, RzStrBuf *sb, PJ *pj) {
|
||||
il_op_param_1("jmp", op->op.jmp, dst);
|
||||
}
|
||||
|
|
@ -517,6 +520,9 @@ static void il_op_pure_resolve(RzILOpPure *op, RzStrBuf *sb, PJ *pj) {
|
|||
case RZ_IL_OP_ITE:
|
||||
il_opdmp_ite(op, sb, pj);
|
||||
return;
|
||||
case RZ_IL_OP_LET:
|
||||
il_opdmp_let(op, sb, pj);
|
||||
return;
|
||||
case RZ_IL_OP_B0:
|
||||
il_opdmp_bool_false(op, sb, pj);
|
||||
return;
|
||||
|
|
@ -651,9 +657,6 @@ static void il_op_effect_resolve(RzILOpEffect *op, RzStrBuf *sb, PJ *pj) {
|
|||
case RZ_IL_OP_SET:
|
||||
il_opdmp_set(op, sb, pj);
|
||||
return;
|
||||
case RZ_IL_OP_LET:
|
||||
il_opdmp_let(op, sb, pj);
|
||||
return;
|
||||
case RZ_IL_OP_JMP:
|
||||
il_opdmp_jmp(op, sb, pj);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -71,10 +71,20 @@ RZ_API RZ_OWN RzILOpPure *rz_il_op_new_unk() {
|
|||
*
|
||||
* var v is the value of the variable v.
|
||||
*/
|
||||
RZ_API RZ_OWN RzILOpPure *rz_il_op_new_var(RZ_NONNULL const char *v) {
|
||||
RZ_API RZ_OWN RzILOpPure *rz_il_op_new_var(RZ_NONNULL const char *v, RzILVarKind kind) {
|
||||
rz_return_val_if_fail(v, NULL);
|
||||
RzILOpPure *ret;
|
||||
rz_il_op_new_1(Pure, RZ_IL_OP_VAR, RzILOpArgsVar, var, v);
|
||||
rz_il_op_new_2(Pure, RZ_IL_OP_VAR, RzILOpArgsVar, var, v, kind);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* `let_ v exp body` binds the value of exp to v body.
|
||||
*/
|
||||
RZ_API RZ_OWN RzILOpPure *rz_il_op_new_let(RZ_NONNULL const char *name, RZ_NONNULL RzILOpPure *exp, RZ_NONNULL RzILOpPure *body) {
|
||||
rz_return_val_if_fail(name && exp && body, NULL);
|
||||
RzILOpPure *ret;
|
||||
rz_il_op_new_3(Pure, RZ_IL_OP_LET, RzILOpArgsLet, let, name, exp, body);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -497,23 +507,10 @@ RZ_API RZ_OWN RzILOpEffect *rz_il_op_new_nop() {
|
|||
*
|
||||
* set v x changes the value stored in v to the value of x.
|
||||
*/
|
||||
RZ_API RZ_OWN RzILOpEffect *rz_il_op_new_set(RZ_NONNULL const char *v, RZ_NONNULL RzILOpPure *x) {
|
||||
RZ_API RZ_OWN RzILOpEffect *rz_il_op_new_set(RZ_NONNULL const char *v, bool is_local, RZ_NONNULL RzILOpPure *x) {
|
||||
rz_return_val_if_fail(v && x, NULL);
|
||||
RzILOpEffect *ret;
|
||||
rz_il_op_new_2(Effect, RZ_IL_OP_SET, RzILOpArgsSet, set, v, x);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief op structure for `let` ('a var -> 'a pure -> 'b pure -> 'b pure -> data eff)
|
||||
*
|
||||
* let v exp body bind the value of exp to v body.
|
||||
* essentially allows you to create a local variable
|
||||
*/
|
||||
RZ_API RZ_OWN RzILOpEffect *rz_il_op_new_let(RZ_NONNULL const char *v, RZ_NONNULL RzILOpPure *x, bool mut) {
|
||||
rz_return_val_if_fail(v && x, NULL);
|
||||
RzILOpEffect *ret;
|
||||
rz_il_op_new_3(Effect, RZ_IL_OP_LET, RzILOpArgsLet, let, v, x, mut);
|
||||
rz_il_op_new_3(Effect, RZ_IL_OP_SET, RzILOpArgsSet, set, v, is_local, x);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -741,6 +738,10 @@ RZ_API RzILOpPure *rz_il_op_pure_dup(RZ_NONNULL RzILOpPure *op) {
|
|||
case RZ_IL_OP_ITE:
|
||||
DUP_OP3(ite, condition, x, y);
|
||||
break;
|
||||
case RZ_IL_OP_LET:
|
||||
r->op.let.name = op->op.let.name;
|
||||
DUP_OP2(let, exp, body);
|
||||
break;
|
||||
case RZ_IL_OP_B0:
|
||||
break;
|
||||
case RZ_IL_OP_B1:
|
||||
|
|
@ -873,6 +874,9 @@ RZ_API void rz_il_op_pure_free(RZ_NULLABLE RzILOpPure *op) {
|
|||
case RZ_IL_OP_ITE:
|
||||
rz_il_op_free_3(pure, ite, condition, x, y);
|
||||
break;
|
||||
case RZ_IL_OP_LET:
|
||||
rz_il_op_free_2(pure, let, exp, body);
|
||||
break;
|
||||
case RZ_IL_OP_B0:
|
||||
case RZ_IL_OP_B1:
|
||||
break;
|
||||
|
|
@ -949,7 +953,7 @@ RZ_API void rz_il_op_pure_free(RZ_NULLABLE RzILOpPure *op) {
|
|||
rz_il_op_free_2(pure, ule, x, y);
|
||||
break;
|
||||
case RZ_IL_OP_CAST:
|
||||
rz_il_op_free_1(pure, cast, val);
|
||||
rz_il_op_free_2(pure, cast, fill, val);
|
||||
break;
|
||||
case RZ_IL_OP_CONCAT:
|
||||
rz_warn_if_reached();
|
||||
|
|
@ -987,9 +991,6 @@ RZ_API void rz_il_op_effect_free(RZ_NULLABLE RzILOpEffect *op) {
|
|||
case RZ_IL_OP_SET:
|
||||
rz_il_op_free_1(pure, set, x);
|
||||
break;
|
||||
case RZ_IL_OP_LET:
|
||||
rz_il_op_free_1(pure, let, x);
|
||||
break;
|
||||
case RZ_IL_OP_JMP:
|
||||
rz_il_op_free_1(pure, jmp, dst);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -203,11 +203,8 @@ RZ_API void rz_il_vm_setup_reg_binding(RZ_NONNULL RzILVM *vm, RZ_NONNULL RZ_OWN
|
|||
rz_return_if_fail(vm && rb && !vm->reg_binding);
|
||||
vm->reg_binding = rb;
|
||||
for (size_t i = 0; i < rb->regs_count; i++) {
|
||||
if (rb->regs[i].size == 1) {
|
||||
rz_il_vm_add_bit_reg(vm, rb->regs[i].name, false);
|
||||
} else {
|
||||
rz_il_vm_add_reg(vm, rb->regs[i].name, rb->regs[i].size);
|
||||
}
|
||||
rz_il_vm_create_global_var(vm, rb->regs[i].name,
|
||||
rb->regs[i].size == 1 ? rz_il_sort_pure_bool() : rz_il_sort_pure_bv(rb->regs[i].size));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -255,8 +252,8 @@ RZ_API bool rz_il_vm_sync_to_reg(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzReg *reg) {
|
|||
perfect = false;
|
||||
continue;
|
||||
}
|
||||
RzILVal *val = rz_il_hash_find_val_by_name(vm, item->name);
|
||||
if (!val || (val->type != RZ_IL_VAR_TYPE_BV && val->type != RZ_IL_VAR_TYPE_BOOL)) {
|
||||
RzILVal *val = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, item->name);
|
||||
if (!val) {
|
||||
perfect = false;
|
||||
RzBitVector *bv = rz_bv_new_zero(ri->size);
|
||||
if (!bv) {
|
||||
|
|
@ -270,7 +267,7 @@ RZ_API bool rz_il_vm_sync_to_reg(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzReg *reg) {
|
|||
}
|
||||
RzBitVector *dupped = NULL;
|
||||
const RzBitVector *bv;
|
||||
if (val->type == RZ_IL_VAR_TYPE_BV) {
|
||||
if (val->type == RZ_IL_TYPE_PURE_BITVECTOR) {
|
||||
bv = val->data.bv;
|
||||
if (rz_bv_len(bv) != ri->size) {
|
||||
perfect = false;
|
||||
|
|
@ -278,7 +275,11 @@ RZ_API bool rz_il_vm_sync_to_reg(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzReg *reg) {
|
|||
if (!dupped) {
|
||||
break;
|
||||
}
|
||||
rz_bv_copy_nbits(bv, 0, dupped, 0, RZ_MIN(rz_bv_len(bv), ri->size));
|
||||
if (ri->size > 1) {
|
||||
rz_bv_copy_nbits(bv, 0, dupped, 0, RZ_MIN(rz_bv_len(bv), ri->size));
|
||||
} else {
|
||||
rz_bv_set_from_ut64(dupped, rz_bv_is_zero_vector(bv) ? 0 : 1);
|
||||
}
|
||||
bv = dupped;
|
||||
}
|
||||
} else { // RZ_IL_VAR_TYPE_BOOL
|
||||
|
|
@ -317,7 +318,7 @@ RZ_API void rz_il_vm_sync_from_reg(RzILVM *vm, RZ_NONNULL RzReg *reg) {
|
|||
}
|
||||
for (size_t i = 0; i < rb->regs_count; i++) {
|
||||
RzILRegBindingItem *item = &rb->regs[i];
|
||||
RzILVar *var = rz_il_find_var_by_name(vm, item->name);
|
||||
RzILVar *var = rz_il_vm_get_var(vm, RZ_IL_VAR_KIND_GLOBAL, item->name);
|
||||
if (!var) {
|
||||
RZ_LOG_ERROR("IL Variable \"%s\" does not exist for bound register of the same name.\n", item->name);
|
||||
continue;
|
||||
|
|
@ -325,7 +326,7 @@ RZ_API void rz_il_vm_sync_from_reg(RzILVM *vm, RZ_NONNULL RzReg *reg) {
|
|||
RzRegItem *ri = rz_reg_get(reg, item->name, RZ_REG_TYPE_ANY);
|
||||
if (item->size == 1) {
|
||||
bool b = ri ? rz_reg_get_value(reg, ri) != 0 : false;
|
||||
rz_il_hash_bind(vm, var, rz_il_vm_fortify_bool(vm, b));
|
||||
rz_il_vm_set_global_var(vm, var->name, rz_il_value_new_bool(rz_il_bool_new(b)));
|
||||
} else {
|
||||
RzBitVector *bv = ri ? rz_reg_get_bv(reg, ri) : rz_bv_new_zero(item->size);
|
||||
if (!bv) {
|
||||
|
|
@ -333,14 +334,16 @@ RZ_API void rz_il_vm_sync_from_reg(RzILVM *vm, RZ_NONNULL RzReg *reg) {
|
|||
}
|
||||
RzBitVector *dupped = NULL;
|
||||
if (rz_bv_len(bv) != item->size) {
|
||||
dupped = rz_bv_new_zero(item->size);
|
||||
if (!dupped) {
|
||||
RzBitVector *nbv = rz_bv_new_zero(item->size);
|
||||
if (!nbv) {
|
||||
rz_bv_free(bv);
|
||||
break;
|
||||
}
|
||||
rz_bv_copy_nbits(bv, 0, dupped, 0, RZ_MIN(rz_bv_len(bv), item->size));
|
||||
bv = dupped;
|
||||
rz_bv_copy_nbits(bv, 0, nbv, 0, RZ_MIN(rz_bv_len(bv), item->size));
|
||||
dupped = bv;
|
||||
bv = nbv;
|
||||
}
|
||||
rz_il_hash_bind(vm, var, rz_il_vm_fortify_bitv(vm, bv));
|
||||
rz_il_vm_set_global_var(vm, var->name, rz_il_value_new_bitv(bv));
|
||||
rz_bv_free(dupped);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
400
librz/il/il_vm.c
400
librz/il/il_vm.c
|
|
@ -25,15 +25,6 @@ static void free_label_kv(HtPPKv *kv) {
|
|||
free(lbl);
|
||||
}
|
||||
|
||||
static void free_bind_var(HtPPKv *kv) {
|
||||
free(kv->key);
|
||||
}
|
||||
|
||||
static void free_bind_var_val(HtPPKv *kv) {
|
||||
free(kv->key);
|
||||
rz_il_value_free(kv->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* initiate an empty VM
|
||||
* \param vm RzILVM, pointer to an empty VM
|
||||
|
|
@ -43,16 +34,19 @@ static void free_bind_var_val(HtPPKv *kv) {
|
|||
RZ_API bool rz_il_vm_init(RzILVM *vm, ut64 start_addr, ut32 addr_size, bool big_endian) {
|
||||
rz_return_val_if_fail(vm, false);
|
||||
|
||||
rz_pvector_init(&vm->vm_global_variable_list, (RzPVectorFree)rz_il_variable_free);
|
||||
rz_pvector_init(&vm->vm_local_variable_list, (RzPVectorFree)rz_il_variable_free);
|
||||
rz_pvector_init(&vm->vm_memory, (RzPVectorFree)rz_il_mem_free);
|
||||
|
||||
vm->vm_global_value_set = rz_il_new_bag(RZ_IL_VM_MAX_VAL, (RzILBagFreeFunc)rz_il_value_free);
|
||||
if (!vm->vm_global_value_set) {
|
||||
RZ_LOG_ERROR("RzIL: cannot allocate VM value bag\n");
|
||||
if (!rz_il_var_set_init(&vm->global_vars)) {
|
||||
rz_il_vm_fini(vm);
|
||||
return false;
|
||||
}
|
||||
if (!rz_il_var_set_init(&vm->local_vars)) {
|
||||
rz_il_vm_fini(vm);
|
||||
return false;
|
||||
}
|
||||
if (!rz_il_var_set_init(&vm->local_pure_vars)) {
|
||||
rz_il_vm_fini(vm);
|
||||
return false;
|
||||
}
|
||||
rz_pvector_init(&vm->vm_memory, (RzPVectorFree)rz_il_mem_free);
|
||||
|
||||
// Key : string
|
||||
// Val : RzILEffectLabel
|
||||
|
|
@ -72,30 +66,6 @@ RZ_API bool rz_il_vm_init(RzILVM *vm, ut64 start_addr, ut32 addr_size, bool big_
|
|||
return false;
|
||||
}
|
||||
|
||||
// Binding Table for Variable and Value
|
||||
HtPPOptions bind_options = { 0 };
|
||||
bind_options.cmp = (HtPPListComparator)strcmp;
|
||||
bind_options.hashfn = (HtPPHashFunction)sdb_hash;
|
||||
bind_options.dupkey = (HtPPDupKey)strdup;
|
||||
bind_options.dupvalue = NULL;
|
||||
bind_options.freefn = (HtPPKvFreeFunc)free_bind_var;
|
||||
bind_options.elem_size = sizeof(HtPPKv);
|
||||
bind_options.calcsizeK = (HtPPCalcSizeK)strlen;
|
||||
vm->vm_global_bind_table = ht_pp_new_opt(&bind_options);
|
||||
if (!vm->vm_global_bind_table) {
|
||||
RZ_LOG_ERROR("RzIL: cannot allocate VM global hashmap\n");
|
||||
rz_il_vm_fini(vm);
|
||||
return false;
|
||||
}
|
||||
|
||||
bind_options.freefn = (HtPPKvFreeFunc)free_bind_var_val;
|
||||
vm->vm_local_bind_table = ht_pp_new_opt(&bind_options);
|
||||
if (!vm->vm_local_bind_table) {
|
||||
RZ_LOG_ERROR("RzIL: cannot allocate VM local hashmap\n");
|
||||
rz_il_vm_fini(vm);
|
||||
return false;
|
||||
}
|
||||
|
||||
vm->pc = rz_bv_new_from_ut64(addr_size, start_addr);
|
||||
if (!vm->pc) {
|
||||
RZ_LOG_ERROR("RzIL: cannot allocate VM program counter\n");
|
||||
|
|
@ -128,21 +98,13 @@ RZ_API bool rz_il_vm_init(RzILVM *vm, ut64 start_addr, ut32 addr_size, bool big_
|
|||
* \param vm RzILVM* pointer to VM
|
||||
*/
|
||||
RZ_API void rz_il_vm_fini(RzILVM *vm) {
|
||||
if (vm->vm_global_value_set) {
|
||||
rz_il_free_bag(vm->vm_global_value_set);
|
||||
vm->vm_global_value_set = NULL;
|
||||
}
|
||||
rz_pvector_fini(&vm->vm_global_variable_list);
|
||||
rz_il_var_set_fini(&vm->global_vars);
|
||||
rz_il_var_set_fini(&vm->local_vars);
|
||||
rz_il_var_set_fini(&vm->local_pure_vars);
|
||||
|
||||
rz_il_reg_binding_free(vm->reg_binding);
|
||||
rz_pvector_fini(&vm->vm_local_variable_list);
|
||||
rz_pvector_fini(&vm->vm_memory);
|
||||
|
||||
ht_pp_free(vm->vm_global_bind_table);
|
||||
vm->vm_global_bind_table = NULL;
|
||||
|
||||
ht_pp_free(vm->vm_local_bind_table);
|
||||
vm->vm_local_bind_table = NULL;
|
||||
|
||||
ht_pp_free(vm->vm_global_label_table);
|
||||
vm->vm_global_label_table = NULL;
|
||||
|
||||
|
|
@ -209,306 +171,100 @@ RZ_API RzILMem *rz_il_vm_get_mem(RzILVM *vm, RzILMemIndex index) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create A new global variable in VM
|
||||
* \param vm RzILVM, pointer to VM
|
||||
* \param name string, name of this variable
|
||||
* \param is_mutable bool, sets if variable is const or not
|
||||
* \return var RzILVar, pointer to the new variable in VM
|
||||
* Create a new global variable of the given sort and assign it to all-zero/false
|
||||
*/
|
||||
RZ_API RZ_BORROW RzILVar *rz_il_vm_create_global_variable(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, RzILVarType type, bool is_mutable) {
|
||||
RZ_API RZ_BORROW RzILVar *rz_il_vm_create_global_var(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, RzILSortPure sort) {
|
||||
rz_return_val_if_fail(vm && name, NULL);
|
||||
if (rz_pvector_len(&vm->vm_global_variable_list) >= RZ_IL_VM_MAX_VAR) {
|
||||
RZ_LOG_ERROR("RzIL: reached max number of variables that the VM can handle.\n");
|
||||
RzILVar *var = rz_il_var_set_create_var(&vm->global_vars, name, sort);
|
||||
if (!var) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// create , store, update count
|
||||
RzILVar *var = rz_il_variable_new(name, type, is_mutable);
|
||||
rz_pvector_push(&vm->vm_global_variable_list, var);
|
||||
RzILVal *val = rz_il_value_new_zero_of(sort);
|
||||
if (!val) {
|
||||
return NULL;
|
||||
}
|
||||
rz_il_var_set_bind(&vm->global_vars, name, val);
|
||||
return var;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create A new local variable in VM
|
||||
* \param vm RzILVM, pointer to VM
|
||||
* \param name string, name of this variable
|
||||
* \param is_mutable bool, sets if variable is const or not
|
||||
* \return var RzILVar, pointer to the new variable in VM
|
||||
* Set the value of a global variable to the given value.
|
||||
* The variable must already exist.
|
||||
*/
|
||||
RZ_API RZ_BORROW RzILVar *rz_il_vm_create_local_variable(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, RzILVarType type, bool is_mutable) {
|
||||
rz_return_val_if_fail(vm && name, NULL);
|
||||
if (rz_pvector_len(&vm->vm_global_variable_list) >= RZ_IL_VM_MAX_VAR) {
|
||||
RZ_LOG_ERROR("RzIL: reached max number of variables that the VM can handle.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// create , store, update count
|
||||
RzILVar *var = rz_il_variable_new(name, type, is_mutable);
|
||||
rz_pvector_push(&vm->vm_local_variable_list, var);
|
||||
return var;
|
||||
RZ_API void rz_il_vm_set_global_var(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, RZ_OWN RzILVal *val) {
|
||||
rz_return_if_fail(vm && name && val);
|
||||
rz_il_var_set_bind(&vm->global_vars, name, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new value in VM (BitVector type)
|
||||
* \param vm RzILVM, pointer to VM
|
||||
* \param bitv RzBitVector, enum to specify the type of this value
|
||||
* \return val RzILVal, pointer to the new value in VM
|
||||
* Set the value of a local variable to the given value.
|
||||
* The variable is created with the sort of \p val if it does not already exist.
|
||||
*/
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_vm_create_value_bitv(RZ_NONNULL RzILVM *vm, RZ_NULLABLE RzBitVector *bitv) {
|
||||
rz_return_val_if_fail(vm && bitv, NULL);
|
||||
if (vm->val_count >= RZ_IL_VM_MAX_VAL) {
|
||||
RZ_LOG_ERROR("No More Values\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RzILVal *val = rz_il_value_new_bitv(bitv);
|
||||
rz_il_add_to_bag(vm->vm_global_value_set, val);
|
||||
return val;
|
||||
RZ_API void rz_il_vm_set_local_var(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, RZ_OWN RzILVal *val) {
|
||||
rz_return_if_fail(vm && name && val);
|
||||
rz_il_var_set_create_var(&vm->local_vars, name, rz_il_value_get_sort(val));
|
||||
rz_il_var_set_bind(&vm->local_vars, name, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new value in VM (Boolean type)
|
||||
* \param vm RzILVM, pointer to VM
|
||||
* \param type RzILVarType, enum to specify the type of this value
|
||||
* \return val RzILVal, pointer to the new value in VM
|
||||
* \brief Create and assign a new local let binding.
|
||||
*
|
||||
* This is meant to be called right before evaluating the body of a let expression. Inside the body, \p name will then be bound to \p val.
|
||||
* Because there might already exist an outer binding of the same name shadowing this one, the previous value is returned.
|
||||
* After evaluating the body, call rz_il_vm_pop_local_pure_var(), passing this value.
|
||||
*/
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_vm_create_value_bool(RZ_NONNULL RzILVM *vm, bool value) {
|
||||
rz_return_val_if_fail(vm, NULL);
|
||||
if (vm->val_count >= RZ_IL_VM_MAX_VAL) {
|
||||
RZ_LOG_ERROR("No More Values\n");
|
||||
return NULL;
|
||||
}
|
||||
RzILBool *b = rz_il_bool_new(value);
|
||||
if (!b) {
|
||||
rz_warn_if_reached();
|
||||
return NULL;
|
||||
}
|
||||
RzILVal *val = rz_il_value_new_bool(b);
|
||||
rz_il_add_to_bag(vm->vm_global_value_set, val);
|
||||
return val;
|
||||
RZ_API RzILLocalPurePrev rz_il_vm_push_local_pure_var(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, RzILVal *val) {
|
||||
rz_return_val_if_fail(vm && name && val, NULL);
|
||||
RzILVal *r = rz_il_var_set_remove_var(&vm->local_pure_vars, name);
|
||||
rz_il_var_set_create_var(&vm->local_pure_vars, name, rz_il_value_get_sort(val));
|
||||
rz_il_var_set_bind(&vm->local_pure_vars, name, val);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new value in VM with (Unknown type)
|
||||
* \param vm RzILVM, pointer to VM
|
||||
* \param type RzILVarType, enum to specify the type of this value
|
||||
* \return val RzILVal, pointer to the new value in VM
|
||||
* \brief Remove a local let binding and restore the state for the outer context.
|
||||
* \param prev pass here the return value of rz_il_vm_push_local_pure_var()
|
||||
*/
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_vm_create_value_unk(RZ_NONNULL RzILVM *vm) {
|
||||
rz_return_val_if_fail(vm, NULL);
|
||||
if (vm->val_count >= RZ_IL_VM_MAX_VAL) {
|
||||
RZ_LOG_ERROR("No More Values\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RzILVal *val = rz_il_value_new_unk();
|
||||
rz_il_add_to_bag(vm->vm_global_value_set, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a register in VM (create a variable and value, and then bind value to variable)
|
||||
* \param vm RzILVM, pointer to this vm
|
||||
* \param name string, the name of register
|
||||
* \param length ut32, width of register
|
||||
*/
|
||||
RZ_API void rz_il_vm_add_reg(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, ut32 length) {
|
||||
rz_return_if_fail(vm && name && length > 0);
|
||||
RzBitVector *bv = rz_bv_new_zero(length);
|
||||
if (!bv) {
|
||||
return;
|
||||
}
|
||||
RzILVar *var = rz_il_vm_create_global_variable(vm, name, RZ_IL_VAR_TYPE_BV, true);
|
||||
RzILVal *val = rz_il_vm_create_value_bitv(vm, bv);
|
||||
rz_il_hash_bind(vm, var, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a register in VM (create a variable and value, and then bind value to variable)
|
||||
* \param vm RzILVM, pointer to this vm
|
||||
* \param name string, the name of register
|
||||
* \param value bool, value of the bit register
|
||||
*/
|
||||
RZ_API void rz_il_vm_add_bit_reg(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, bool value) {
|
||||
RZ_API void rz_il_vm_pop_local_pure_var(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, RzILLocalPurePrev prev) {
|
||||
rz_return_if_fail(vm && name);
|
||||
RzILVar *var = rz_il_vm_create_global_variable(vm, name, RZ_IL_VAR_TYPE_BOOL, true);
|
||||
RzILVal *val = rz_il_vm_create_value_bool(vm, value);
|
||||
rz_il_hash_bind(vm, var, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a temporary value (type `RzILVal`) inside vm become a value store in VM
|
||||
* \param vm RzILVM, pointer to VM
|
||||
* \param temp_val_index int, the index of temporary value you attempt to fortify
|
||||
* \return val RzILVal, pointer to the fortified value
|
||||
*/
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_vm_fortify_val(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILVal *val) {
|
||||
rz_return_val_if_fail(vm && val, NULL);
|
||||
rz_il_add_to_bag(vm->vm_global_value_set, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a temporary value (type `RzBitVector`) inside vm become a value store in VM
|
||||
* \param vm RzILVM, pointer to VM
|
||||
* \param temp_val_index int, the index of temporary value you attempt to fortify
|
||||
* \return val RzILVal, pointer to the fortified value
|
||||
*/
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_vm_fortify_bitv(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzBitVector *bitv) {
|
||||
rz_return_val_if_fail(vm && bitv, NULL);
|
||||
RzILVal *val = rz_il_value_new_bitv(bitv);
|
||||
if (!val) {
|
||||
return NULL;
|
||||
RzILVal *r = rz_il_var_set_remove_var(&vm->local_pure_vars, name);
|
||||
rz_warn_if_fail(r); // the var should always be bound when calling this function
|
||||
rz_il_value_free(r);
|
||||
if (prev) {
|
||||
rz_il_var_set_create_var(&vm->local_pure_vars, name, rz_il_value_get_sort(prev));
|
||||
rz_il_var_set_bind(&vm->local_pure_vars, name, prev);
|
||||
}
|
||||
rz_il_add_to_bag(vm->vm_global_value_set, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a temporary value (type `RzILBool`) inside vm become a value store in VM
|
||||
* \param vm RzILVM, pointer to VM
|
||||
* \param temp_val_index int, the index of temporary value you attempt to fortify
|
||||
* \return val RzILVal, pointer to the fortified value
|
||||
*/
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_vm_fortify_bool(RZ_NONNULL RzILVM *vm, bool value) {
|
||||
static RzILVarSet *var_set_of_kind(RzILVM *vm, RzILVarKind kind) {
|
||||
switch (kind) {
|
||||
case RZ_IL_VAR_KIND_GLOBAL:
|
||||
return &vm->global_vars;
|
||||
case RZ_IL_VAR_KIND_LOCAL:
|
||||
return &vm->local_vars;
|
||||
case RZ_IL_VAR_KIND_LOCAL_PURE:
|
||||
return &vm->local_pure_vars;
|
||||
}
|
||||
rz_warn_if_reached();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RZ_API RZ_BORROW RzILVar *rz_il_vm_get_var(RZ_NONNULL RzILVM *vm, RzILVarKind kind, const char *name) {
|
||||
rz_return_val_if_fail(vm && name, NULL);
|
||||
return rz_il_var_set_get(var_set_of_kind(vm, kind), name);
|
||||
}
|
||||
|
||||
RZ_API RZ_OWN RzPVector /* <RzILVar> */ *rz_il_vm_get_all_vars(RZ_NONNULL RzILVM *vm, RzILVarKind kind) {
|
||||
rz_return_val_if_fail(vm, NULL);
|
||||
RzILBool *b = rz_il_bool_new(value);
|
||||
if (!b) {
|
||||
rz_warn_if_reached();
|
||||
return NULL;
|
||||
}
|
||||
RzILVal *val = rz_il_value_new_bool(b);
|
||||
if (!val) {
|
||||
return NULL;
|
||||
}
|
||||
rz_il_add_to_bag(vm->vm_global_value_set, val);
|
||||
return val;
|
||||
return rz_il_var_set_get_all(var_set_of_kind(vm, kind));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the global value bind to the given variable
|
||||
* \param vm RzILVM, pointer to VM
|
||||
* \param var RzILVar, pointer to a variable
|
||||
* \return val RzILVal, pointer to the value of variable
|
||||
* Get the current value of the variable identified by its \p name and \p kind.
|
||||
*/
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_hash_find_val_by_var(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILVar *var) {
|
||||
rz_return_val_if_fail(vm && var, NULL);
|
||||
return rz_il_hash_find_val_by_name(vm, var->var_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the global value by variable name
|
||||
* \param vm RzILVM, pointer to VM
|
||||
* \param var_name string, the name of variable
|
||||
* \return val RzILVal, pointer to the value of variable with name `var_name`
|
||||
*/
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_hash_find_val_by_name(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *var_name) {
|
||||
rz_return_val_if_fail(vm && var_name, NULL);
|
||||
return ht_pp_find(vm->vm_global_bind_table, var_name, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the local value bind to the given variable
|
||||
* \param vm RzILVM, pointer to VM
|
||||
* \param var RzILVar, pointer to a variable
|
||||
* \return val RzILVal, pointer to the value of variable
|
||||
*/
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_hash_find_local_val_by_var(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILVar *var) {
|
||||
rz_return_val_if_fail(vm && var, NULL);
|
||||
return rz_il_hash_find_local_val_by_name(vm, var->var_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the local value by variable name
|
||||
* \param vm RzILVM, pointer to VM
|
||||
* \param var_name string, the name of variable
|
||||
* \return val RzILVal, pointer to the value of variable with name `var_name`
|
||||
*/
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_hash_find_local_val_by_name(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *var_name) {
|
||||
rz_return_val_if_fail(vm && var_name, NULL);
|
||||
return ht_pp_find(vm->vm_local_bind_table, var_name, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the global variable by variable name
|
||||
* \param vm RzILVM, pointer to VM
|
||||
* \param var_name string, the name of variable
|
||||
* \return var RzILVar, pointer to the variable
|
||||
*/
|
||||
RZ_API RZ_BORROW RzILVar *rz_il_find_var_by_name(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *var_name) {
|
||||
rz_return_val_if_fail(vm && var_name, NULL);
|
||||
RzILVar *var;
|
||||
void **it;
|
||||
rz_pvector_foreach (&vm->vm_global_variable_list, it) {
|
||||
var = (RzILVar *)*it;
|
||||
if (!strcmp(var_name, var->var_name)) {
|
||||
return var;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the local variable by variable name
|
||||
* \param vm RzILVM, pointer to VM
|
||||
* \param var_name string, the name of variable
|
||||
* \return var RzILVar, pointer to the variable
|
||||
*/
|
||||
RZ_API RZ_BORROW RzILVar *rz_il_find_local_var_by_name(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *var_name) {
|
||||
rz_return_val_if_fail(vm && var_name, NULL);
|
||||
RzILVar *var;
|
||||
void **it;
|
||||
rz_pvector_foreach (&vm->vm_local_variable_list, it) {
|
||||
var = (RzILVar *)*it;
|
||||
if (!strcmp(var_name, var->var_name)) {
|
||||
return var;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the binding between global var and its val, make it available to bind another value
|
||||
* \param vm pointer to VM
|
||||
* \param var RzILVar, variable you want to cancel its original binding
|
||||
*/
|
||||
RZ_API void rz_il_hash_cancel_binding(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILVar *var) {
|
||||
rz_return_if_fail(vm && var);
|
||||
RzILVal *val = rz_il_hash_find_val_by_name(vm, var->var_name);
|
||||
rz_il_rm_from_bag(vm->vm_global_value_set, val);
|
||||
ht_pp_delete(vm->vm_global_bind_table, var->var_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind global variable and value
|
||||
* \param vm pointer to VM
|
||||
* \param var RzILVar, variable
|
||||
* \param val RzILVal, value
|
||||
*/
|
||||
RZ_API void rz_il_hash_bind(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILVar *var, RZ_NONNULL RzILVal *val) {
|
||||
rz_return_if_fail(vm && var && val);
|
||||
ht_pp_update(vm->vm_global_bind_table, var->var_name, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the binding between local var and its val, make it available to bind another value
|
||||
* \param vm pointer to VM
|
||||
* \param var RzILVar, variable you want to cancel its original binding
|
||||
*/
|
||||
RZ_API void rz_il_hash_cancel_local_binding(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILVar *var) {
|
||||
rz_return_if_fail(vm && var);
|
||||
ht_pp_delete(vm->vm_local_bind_table, var->var_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind local variable and value
|
||||
* \param vm pointer to VM
|
||||
* \param var RzILVar, variable
|
||||
* \param val RzILVal, value
|
||||
*/
|
||||
RZ_API void rz_il_hash_local_bind(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILVar *var, RZ_NONNULL RzILVal *val) {
|
||||
rz_return_if_fail(vm && var && val);
|
||||
ht_pp_update(vm->vm_local_bind_table, var->var_name, val);
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_vm_get_var_value(RZ_NONNULL RzILVM *vm, RzILVarKind kind, const char *name) {
|
||||
rz_return_val_if_fail(vm && name, NULL);
|
||||
return rz_il_var_set_get_value(var_set_of_kind(vm, kind), name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -9,45 +9,45 @@
|
|||
#include <rz_il/rz_il_vm.h>
|
||||
|
||||
// Handler for core theory opcodes
|
||||
void *rz_il_handler_ite(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_var(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_unk(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_ite(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_var(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_let(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_unk(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
|
||||
void *rz_il_handler_bitv(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_msb(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_lsb(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_is_zero(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_eq(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_ule(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_sle(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_neg(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_logical_not(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_add(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_sub(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_mul(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_div(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_sdiv(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_mod(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_smod(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_shiftl(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_shiftr(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_logical_and(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_logical_or(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_logical_xor(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_bitv(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_msb(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_lsb(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_is_zero(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_eq(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_ule(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_sle(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_neg(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_logical_not(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_add(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_sub(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_mul(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_div(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_sdiv(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_mod(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_smod(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_shiftl(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_shiftr(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_logical_and(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_logical_or(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_logical_xor(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
|
||||
void *rz_il_handler_bool_false(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_bool_true(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_bool_and(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_bool_or(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_bool_xor(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_bool_inv(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_bool_false(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_bool_true(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_bool_and(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_bool_or(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_bool_xor(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_bool_inv(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
|
||||
void *rz_il_handler_cast(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_append(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_cast(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
void *rz_il_handler_append(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
|
||||
bool rz_il_handler_nop(RzILVM *vm, RzILOpEffect *op);
|
||||
bool rz_il_handler_set(RzILVM *vm, RzILOpEffect *op);
|
||||
bool rz_il_handler_let(RzILVM *vm, RzILOpEffect *op);
|
||||
bool rz_il_handler_jmp(RzILVM *vm, RzILOpEffect *op);
|
||||
bool rz_il_handler_goto(RzILVM *vm, RzILOpEffect *op);
|
||||
bool rz_il_handler_seq(RzILVM *vm, RzILOpEffect *op);
|
||||
|
|
@ -55,19 +55,20 @@ bool rz_il_handler_blk(RzILVM *vm, RzILOpEffect *op);
|
|||
bool rz_il_handler_repeat(RzILVM *vm, RzILOpEffect *op);
|
||||
bool rz_il_handler_branch(RzILVM *vm, RzILOpEffect *op);
|
||||
|
||||
void *rz_il_handler_load(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_load(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
bool rz_il_handler_store(RzILVM *vm, RzILOpEffect *op);
|
||||
void *rz_il_handler_loadw(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_loadw(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
bool rz_il_handler_storew(RzILVM *vm, RzILOpEffect *op);
|
||||
|
||||
// TODO: remove me when all the handlers are implemented
|
||||
void *rz_il_handler_pure_unimplemented(RzILVM *vm, RzILOpPure *op, RzILPureType *type);
|
||||
void *rz_il_handler_pure_unimplemented(RzILVM *vm, RzILOpPure *op, RzILTypePure *type);
|
||||
bool rz_il_handler_effect_unimplemented(RzILVM *vm, RzILOpEffect *op);
|
||||
|
||||
RZ_IPI RzILOpPureHandler rz_il_op_handler_pure_table_default[RZ_IL_OP_PURE_MAX] = {
|
||||
[RZ_IL_OP_VAR] = rz_il_handler_var,
|
||||
[RZ_IL_OP_UNK] = rz_il_handler_unk,
|
||||
[RZ_IL_OP_ITE] = rz_il_handler_ite,
|
||||
[RZ_IL_OP_LET] = rz_il_handler_let,
|
||||
[RZ_IL_OP_B0] = rz_il_handler_bool_false,
|
||||
[RZ_IL_OP_B1] = rz_il_handler_bool_true,
|
||||
[RZ_IL_OP_INV] = rz_il_handler_bool_inv,
|
||||
|
|
@ -107,7 +108,6 @@ RZ_IPI RzILOpEffectHandler rz_il_op_handler_effect_table_default[RZ_IL_OP_EFFECT
|
|||
[RZ_IL_OP_STOREW] = rz_il_handler_storew,
|
||||
[RZ_IL_OP_NOP] = rz_il_handler_nop,
|
||||
[RZ_IL_OP_SET] = rz_il_handler_set,
|
||||
[RZ_IL_OP_LET] = rz_il_handler_let,
|
||||
[RZ_IL_OP_JMP] = rz_il_handler_jmp,
|
||||
[RZ_IL_OP_GOTO] = rz_il_handler_goto,
|
||||
[RZ_IL_OP_SEQ] = rz_il_handler_seq,
|
||||
|
|
@ -227,17 +227,12 @@ RZ_API bool rz_il_vm_step(RzILVM *vm, RzILOpEffect *op, ut32 op_size) {
|
|||
rz_bv_free(step);
|
||||
vm->pc = next_pc;
|
||||
|
||||
// remove any local defined variable
|
||||
void **it;
|
||||
rz_pvector_foreach (&vm->vm_local_variable_list, it) {
|
||||
RzILVar *var = *it;
|
||||
rz_il_hash_cancel_local_binding(vm, var);
|
||||
}
|
||||
rz_pvector_clear(&vm->vm_local_variable_list);
|
||||
// remove any local defined variable (local pure vars are unbound automatically)
|
||||
rz_il_var_set_reset(&vm->local_vars);
|
||||
return succ;
|
||||
}
|
||||
|
||||
static void *eval_pure(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILOpPure *op, RZ_NONNULL RzILPureType *type) {
|
||||
static void *eval_pure(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILOpPure *op, RZ_NONNULL RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
RzILOpPureHandler handler = vm->op_handler_pure_table[op->code];
|
||||
rz_return_val_if_fail(handler, NULL);
|
||||
|
|
@ -251,11 +246,11 @@ static bool eval_effect(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILOpEffect *op) {
|
|||
return handler(vm, op);
|
||||
}
|
||||
|
||||
static const char *pure_type_name(RzILPureType type) {
|
||||
static const char *pure_type_name(RzILTypePure type) {
|
||||
switch (type) {
|
||||
case RZ_IL_PURE_TYPE_BITV:
|
||||
case RZ_IL_TYPE_PURE_BITVECTOR:
|
||||
return "bitvector";
|
||||
case RZ_IL_PURE_TYPE_BOOL:
|
||||
case RZ_IL_TYPE_PURE_BOOL:
|
||||
return "bool";
|
||||
default:
|
||||
return "unknown";
|
||||
|
|
@ -269,13 +264,13 @@ static const char *pure_type_name(RzILPureType type) {
|
|||
RZ_API RZ_NULLABLE RZ_OWN RzBitVector *rz_il_evaluate_bitv(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILOpBitVector *op) {
|
||||
rz_return_val_if_fail(vm && op, NULL);
|
||||
// check type and auto convertion between bitv/bool/val
|
||||
RzILPureType type = -1;
|
||||
RzILTypePure type = -1;
|
||||
void *res = eval_pure(vm, op, &type);
|
||||
if (!res) {
|
||||
// propagate error
|
||||
return NULL;
|
||||
}
|
||||
if (type != RZ_IL_PURE_TYPE_BITV) {
|
||||
if (type != RZ_IL_TYPE_PURE_BITVECTOR) {
|
||||
RZ_LOG_ERROR("RzIL: type error: expected bitvector, got %s\n", pure_type_name(type));
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -289,13 +284,13 @@ RZ_API RZ_NULLABLE RZ_OWN RzBitVector *rz_il_evaluate_bitv(RZ_NONNULL RzILVM *vm
|
|||
RZ_API RZ_NULLABLE RZ_OWN RzILBool *rz_il_evaluate_bool(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILOpBool *op) {
|
||||
rz_return_val_if_fail(vm && op, NULL);
|
||||
// check type and auto convertion between bitv/bool/val
|
||||
RzILPureType type = -1;
|
||||
RzILTypePure type = -1;
|
||||
void *res = eval_pure(vm, op, &type);
|
||||
if (!res) {
|
||||
// propagate error
|
||||
return NULL;
|
||||
}
|
||||
if (type != RZ_IL_PURE_TYPE_BOOL) {
|
||||
if (type != RZ_IL_TYPE_PURE_BOOL) {
|
||||
RZ_LOG_ERROR("RzIL: type error: expected bool, got %s\n", pure_type_name(type));
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -309,16 +304,16 @@ RZ_API RZ_NULLABLE RZ_OWN RzILBool *rz_il_evaluate_bool(RZ_NONNULL RzILVM *vm, R
|
|||
RZ_API RZ_NULLABLE RZ_OWN RzILVal *rz_il_evaluate_val(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILOpPure *op) {
|
||||
rz_return_val_if_fail(vm && op, NULL);
|
||||
// check type and auto convertion between bitv/bool/val
|
||||
RzILPureType type = -1;
|
||||
RzILTypePure type = -1;
|
||||
void *res = eval_pure(vm, op, &type);
|
||||
if (!res) {
|
||||
// propagate error
|
||||
return NULL;
|
||||
}
|
||||
switch (type) {
|
||||
case RZ_IL_PURE_TYPE_BOOL:
|
||||
case RZ_IL_TYPE_PURE_BOOL:
|
||||
return rz_il_value_new_bool(res);
|
||||
case RZ_IL_PURE_TYPE_BITV:
|
||||
case RZ_IL_TYPE_PURE_BITVECTOR:
|
||||
return rz_il_value_new_bitv(res);
|
||||
default:
|
||||
RZ_LOG_ERROR("RzIL: type error: expected bitvector, got %s\n", pure_type_name(type));
|
||||
|
|
@ -329,7 +324,7 @@ RZ_API RZ_NULLABLE RZ_OWN RzILVal *rz_il_evaluate_val(RZ_NONNULL RzILVM *vm, RZ_
|
|||
/**
|
||||
* Evaluate the given pure op, returning the resulting value and its type.
|
||||
*/
|
||||
RZ_API RZ_NULLABLE RZ_OWN RzILVal *rz_il_evaluate_pure(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILOpPure *op, RZ_NONNULL RzILPureType *type) {
|
||||
RZ_API RZ_NULLABLE RZ_OWN void *rz_il_evaluate_pure(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILOpPure *op, RZ_NONNULL RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op, NULL);
|
||||
return eval_pure(vm, op, type);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ rz_il_sources = [
|
|||
'definitions/value.c',
|
||||
'definitions/bool.c',
|
||||
'definitions/mem.c',
|
||||
'definitions/bag.c',
|
||||
'theory_bitv.c',
|
||||
'theory_effect.c',
|
||||
'theory_init.c',
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include <rz_il/rz_il_opcodes.h>
|
||||
#include <rz_il/rz_il_vm.h>
|
||||
|
||||
void *rz_il_handler_msb(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_msb(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsMsb *op_msb = &op->op.msb;
|
||||
|
|
@ -12,11 +12,11 @@ void *rz_il_handler_msb(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
|||
RzILBool *result = bv ? rz_il_bool_new(rz_bv_msb(bv)) : NULL;
|
||||
rz_bv_free(bv);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BOOL;
|
||||
*type = RZ_IL_TYPE_PURE_BOOL;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *rz_il_handler_lsb(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_lsb(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsLsb *op_lsb = &op->op.lsb;
|
||||
|
|
@ -24,11 +24,11 @@ void *rz_il_handler_lsb(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
|||
RzILBool *result = bv ? rz_il_bool_new(rz_bv_lsb(bv)) : NULL;
|
||||
rz_bv_free(bv);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BOOL;
|
||||
*type = RZ_IL_TYPE_PURE_BOOL;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *rz_il_handler_is_zero(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_is_zero(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsLsb *op_lsb = &op->op.lsb;
|
||||
|
|
@ -36,11 +36,11 @@ void *rz_il_handler_is_zero(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type)
|
|||
RzILBool *result = bv ? rz_il_bool_new(rz_bv_is_zero_vector(bv)) : NULL;
|
||||
rz_bv_free(bv);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BOOL;
|
||||
*type = RZ_IL_TYPE_PURE_BOOL;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *rz_il_handler_neg(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_neg(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsNeg *neg = &op->op.neg;
|
||||
|
|
@ -49,11 +49,11 @@ void *rz_il_handler_neg(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
|||
RzBitVector *bv_result = bv_arg ? rz_bv_neg(bv_arg) : NULL;
|
||||
rz_bv_free(bv_arg);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BITV;
|
||||
*type = RZ_IL_TYPE_PURE_BITVECTOR;
|
||||
return bv_result;
|
||||
}
|
||||
|
||||
void *rz_il_handler_logical_not(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_logical_not(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsLogNot *op_not = &op->op.lognot;
|
||||
|
|
@ -62,11 +62,11 @@ void *rz_il_handler_logical_not(RzILVM *vm, RzILOpBitVector *op, RzILPureType *t
|
|||
RzBitVector *result = bv ? rz_bv_not(bv) : NULL;
|
||||
rz_bv_free(bv);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BITV;
|
||||
*type = RZ_IL_TYPE_PURE_BITVECTOR;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *rz_il_handler_eq(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_eq(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsSle *op_sle = &op->op.sle;
|
||||
|
|
@ -77,11 +77,11 @@ void *rz_il_handler_eq(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
|||
rz_bv_free(x);
|
||||
rz_bv_free(y);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BOOL;
|
||||
*type = RZ_IL_TYPE_PURE_BOOL;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *rz_il_handler_sle(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_sle(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsSle *op_sle = &op->op.sle;
|
||||
|
|
@ -92,11 +92,11 @@ void *rz_il_handler_sle(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
|||
rz_bv_free(x);
|
||||
rz_bv_free(y);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BOOL;
|
||||
*type = RZ_IL_TYPE_PURE_BOOL;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *rz_il_handler_ule(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_ule(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsUle *op_ule = &op->op.ule;
|
||||
|
|
@ -107,11 +107,11 @@ void *rz_il_handler_ule(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
|||
rz_bv_free(x);
|
||||
rz_bv_free(y);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BOOL;
|
||||
*type = RZ_IL_TYPE_PURE_BOOL;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *rz_il_handler_add(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_add(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsAdd *op_add = &op->op.add;
|
||||
|
|
@ -123,11 +123,11 @@ void *rz_il_handler_add(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
|||
rz_bv_free(x);
|
||||
rz_bv_free(y);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BITV;
|
||||
*type = RZ_IL_TYPE_PURE_BITVECTOR;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *rz_il_handler_append(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_append(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsAppend *op_append = &op->op.append;
|
||||
|
|
@ -138,11 +138,11 @@ void *rz_il_handler_append(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type)
|
|||
rz_bv_free(low);
|
||||
rz_bv_free(high);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BITV;
|
||||
*type = RZ_IL_TYPE_PURE_BITVECTOR;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *rz_il_handler_logical_and(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_logical_and(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsAdd *op_add = &op->op.add;
|
||||
|
|
@ -153,11 +153,11 @@ void *rz_il_handler_logical_and(RzILVM *vm, RzILOpBitVector *op, RzILPureType *t
|
|||
rz_bv_free(x);
|
||||
rz_bv_free(y);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BITV;
|
||||
*type = RZ_IL_TYPE_PURE_BITVECTOR;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *rz_il_handler_logical_or(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_logical_or(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsAdd *op_add = &op->op.add;
|
||||
|
|
@ -168,11 +168,11 @@ void *rz_il_handler_logical_or(RzILVM *vm, RzILOpBitVector *op, RzILPureType *ty
|
|||
rz_bv_free(x);
|
||||
rz_bv_free(y);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BITV;
|
||||
*type = RZ_IL_TYPE_PURE_BITVECTOR;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *rz_il_handler_logical_xor(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_logical_xor(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsAdd *op_add = &op->op.add;
|
||||
|
|
@ -183,11 +183,11 @@ void *rz_il_handler_logical_xor(RzILVM *vm, RzILOpBitVector *op, RzILPureType *t
|
|||
rz_bv_free(x);
|
||||
rz_bv_free(y);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BITV;
|
||||
*type = RZ_IL_TYPE_PURE_BITVECTOR;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *rz_il_handler_sub(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_sub(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsSub *op_sub = &op->op.sub;
|
||||
|
|
@ -198,11 +198,11 @@ void *rz_il_handler_sub(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
|||
rz_bv_free(x);
|
||||
rz_bv_free(y);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BITV;
|
||||
*type = RZ_IL_TYPE_PURE_BITVECTOR;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *rz_il_handler_mul(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_mul(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsMul *op_mul = &op->op.mul;
|
||||
|
|
@ -214,11 +214,11 @@ void *rz_il_handler_mul(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
|||
rz_bv_free(x);
|
||||
rz_bv_free(y);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BITV;
|
||||
*type = RZ_IL_TYPE_PURE_BITVECTOR;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *rz_il_handler_div(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_div(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsDiv *op_div = &op->op.div;
|
||||
|
|
@ -239,11 +239,11 @@ void *rz_il_handler_div(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
|||
rz_bv_free(x);
|
||||
rz_bv_free(y);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BITV;
|
||||
*type = RZ_IL_TYPE_PURE_BITVECTOR;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *rz_il_handler_sdiv(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_sdiv(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsSdiv *op_sdiv = &op->op.sdiv;
|
||||
|
|
@ -254,11 +254,11 @@ void *rz_il_handler_sdiv(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
|||
rz_bv_free(x);
|
||||
rz_bv_free(y);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BITV;
|
||||
*type = RZ_IL_TYPE_PURE_BITVECTOR;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *rz_il_handler_mod(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_mod(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsMod *op_mod = &op->op.mod;
|
||||
|
|
@ -269,11 +269,11 @@ void *rz_il_handler_mod(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
|||
rz_bv_free(x);
|
||||
rz_bv_free(y);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BITV;
|
||||
*type = RZ_IL_TYPE_PURE_BITVECTOR;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *rz_il_handler_smod(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_smod(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsSmod *op_smod = &op->op.smod;
|
||||
|
|
@ -284,11 +284,11 @@ void *rz_il_handler_smod(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
|||
rz_bv_free(x);
|
||||
rz_bv_free(y);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BITV;
|
||||
*type = RZ_IL_TYPE_PURE_BITVECTOR;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *rz_il_handler_shiftl(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_shiftl(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsShiftLeft *op_shiftl = &op->op.shiftl;
|
||||
|
|
@ -306,11 +306,11 @@ void *rz_il_handler_shiftl(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type)
|
|||
rz_bv_free(bv);
|
||||
rz_il_bool_free(fill_bit);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BITV;
|
||||
*type = RZ_IL_TYPE_PURE_BITVECTOR;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *rz_il_handler_shiftr(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_shiftr(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsShiftRight *op_shr = &op->op.shiftr;
|
||||
|
|
@ -329,21 +329,21 @@ void *rz_il_handler_shiftr(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type)
|
|||
rz_bv_free(bv);
|
||||
rz_il_bool_free(fill_bit);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BITV;
|
||||
*type = RZ_IL_TYPE_PURE_BITVECTOR;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *rz_il_handler_bitv(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_bitv(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
RzILOpArgsBv *op_bitv = &op->op.bitv;
|
||||
|
||||
RzBitVector *bv = rz_bv_dup(op_bitv->value);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BITV;
|
||||
*type = RZ_IL_TYPE_PURE_BITVECTOR;
|
||||
return bv;
|
||||
}
|
||||
|
||||
void *rz_il_handler_cast(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_cast(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsCast *op_cast = &op->op.cast;
|
||||
|
|
@ -363,6 +363,6 @@ void *rz_il_handler_cast(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
|||
rz_il_bool_free(fill);
|
||||
rz_bv_free(bv);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BITV;
|
||||
*type = RZ_IL_TYPE_PURE_BITVECTOR;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,26 +7,26 @@
|
|||
/**
|
||||
* \brief also known as b0
|
||||
*/
|
||||
void *rz_il_handler_bool_false(RzILVM *vm, RzILOpBool *op, RzILPureType *type) {
|
||||
void *rz_il_handler_bool_false(RzILVM *vm, RzILOpBool *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILBool *ret = rz_il_bool_new(false);
|
||||
*type = RZ_IL_PURE_TYPE_BOOL;
|
||||
*type = RZ_IL_TYPE_PURE_BOOL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief also known as b1
|
||||
*/
|
||||
void *rz_il_handler_bool_true(RzILVM *vm, RzILOpBool *op, RzILPureType *type) {
|
||||
void *rz_il_handler_bool_true(RzILVM *vm, RzILOpBool *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILBool *ret = rz_il_bool_new(true);
|
||||
*type = RZ_IL_PURE_TYPE_BOOL;
|
||||
*type = RZ_IL_TYPE_PURE_BOOL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *rz_il_handler_bool_and(RzILVM *vm, RzILOpBool *op, RzILPureType *type) {
|
||||
void *rz_il_handler_bool_and(RzILVM *vm, RzILOpBool *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsBoolAnd *op_and = &op->op.booland;
|
||||
|
|
@ -37,11 +37,11 @@ void *rz_il_handler_bool_and(RzILVM *vm, RzILOpBool *op, RzILPureType *type) {
|
|||
rz_il_bool_free(x);
|
||||
rz_il_bool_free(y);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BOOL;
|
||||
*type = RZ_IL_TYPE_PURE_BOOL;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *rz_il_handler_bool_or(RzILVM *vm, RzILOpBool *op, RzILPureType *type) {
|
||||
void *rz_il_handler_bool_or(RzILVM *vm, RzILOpBool *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsBoolOr *op_or = &op->op.boolor;
|
||||
|
|
@ -52,11 +52,11 @@ void *rz_il_handler_bool_or(RzILVM *vm, RzILOpBool *op, RzILPureType *type) {
|
|||
rz_il_bool_free(x);
|
||||
rz_il_bool_free(y);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BOOL;
|
||||
*type = RZ_IL_TYPE_PURE_BOOL;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *rz_il_handler_bool_xor(RzILVM *vm, RzILOpBool *op, RzILPureType *type) {
|
||||
void *rz_il_handler_bool_xor(RzILVM *vm, RzILOpBool *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsBoolXor *op_xor = &op->op.boolxor;
|
||||
|
|
@ -67,14 +67,14 @@ void *rz_il_handler_bool_xor(RzILVM *vm, RzILOpBool *op, RzILPureType *type) {
|
|||
rz_il_bool_free(x);
|
||||
rz_il_bool_free(y);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BOOL;
|
||||
*type = RZ_IL_TYPE_PURE_BOOL;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief also known as boolean not
|
||||
*/
|
||||
void *rz_il_handler_bool_inv(RzILVM *vm, RzILOpBool *op, RzILPureType *type) {
|
||||
void *rz_il_handler_bool_inv(RzILVM *vm, RzILOpBool *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsBoolInv *op_inv = &op->op.boolinv;
|
||||
|
|
@ -82,6 +82,6 @@ void *rz_il_handler_bool_inv(RzILVM *vm, RzILOpBool *op, RzILPureType *type) {
|
|||
RzILBool *result = x ? rz_il_bool_not(x) : NULL;
|
||||
rz_il_bool_free(x);
|
||||
|
||||
*type = RZ_IL_PURE_TYPE_BOOL;
|
||||
*type = RZ_IL_TYPE_PURE_BOOL;
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,88 +12,39 @@ static RzILEvent *il_event_new_write_from_var(RzILVM *vm, RzILVar *var, RzILVal
|
|||
RzBitVector *oldnum = NULL;
|
||||
RzBitVector *newnum = NULL;
|
||||
|
||||
if (new_val->type == RZ_IL_VAR_TYPE_BOOL) {
|
||||
if (new_val->type == RZ_IL_TYPE_PURE_BOOL) {
|
||||
newnum = rz_bv_new_from_ut64(1, new_val->data.b->b);
|
||||
} else {
|
||||
newnum = new_val->data.bv;
|
||||
}
|
||||
|
||||
old_val = rz_il_hash_find_val_by_var(vm, var);
|
||||
old_val = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, var->name);
|
||||
if (old_val) {
|
||||
if (old_val->type == RZ_IL_VAR_TYPE_BOOL) {
|
||||
if (old_val->type == RZ_IL_TYPE_PURE_BOOL) {
|
||||
oldnum = rz_bv_new_from_ut64(1, old_val->data.b->b);
|
||||
} else {
|
||||
oldnum = old_val->data.bv;
|
||||
}
|
||||
}
|
||||
|
||||
evt = rz_il_event_var_write_new(var->var_name, oldnum, newnum);
|
||||
if (old_val && old_val->type == RZ_IL_VAR_TYPE_BOOL) {
|
||||
evt = rz_il_event_var_write_new(var->name, oldnum, newnum);
|
||||
if (old_val && old_val->type == RZ_IL_TYPE_PURE_BOOL) {
|
||||
rz_bv_free(oldnum);
|
||||
}
|
||||
if (new_val->type == RZ_IL_VAR_TYPE_BOOL) {
|
||||
if (new_val->type == RZ_IL_TYPE_PURE_BOOL) {
|
||||
rz_bv_free(newnum);
|
||||
}
|
||||
return evt;
|
||||
}
|
||||
|
||||
static void rz_il_set(RzILVM *vm, const char *var_name, bool is_local, bool is_mutable, RZ_OWN RzILVal *val) {
|
||||
RzILVar *var = NULL;
|
||||
RzILEvent *evt = NULL;
|
||||
static void rz_il_set(RzILVM *vm, const char *var_name, bool is_local, RZ_OWN RzILVal *val) {
|
||||
if (is_local) {
|
||||
var = rz_il_find_local_var_by_name(vm, var_name);
|
||||
rz_il_vm_set_local_var(vm, var_name, val);
|
||||
} else {
|
||||
var = rz_il_find_var_by_name(vm, var_name);
|
||||
}
|
||||
if (!var && !is_local) {
|
||||
// it's a set to a global variable which has not been defined.
|
||||
char *message = rz_str_newf("unknown global variable '%s'.", var_name);
|
||||
evt = rz_il_event_exception_new(message);
|
||||
free(message);
|
||||
rz_il_value_free(val);
|
||||
rz_il_vm_event_add(vm, evt);
|
||||
return;
|
||||
} else if (var && !var->is_mutable) {
|
||||
// forbid changing an immutable type
|
||||
char *message = rz_str_newf("cannot change %s variable '%s' because is not mutable.", is_local ? "local" : "global", var_name);
|
||||
evt = rz_il_event_exception_new(message);
|
||||
free(message);
|
||||
rz_il_value_free(val);
|
||||
rz_il_vm_event_add(vm, evt);
|
||||
return;
|
||||
}
|
||||
|
||||
// enforce var type to val except if var is unk, because unk type can be set to any type.
|
||||
if (var && var->type == RZ_IL_VAR_TYPE_BV && val->type == RZ_IL_VAR_TYPE_BOOL) {
|
||||
RzBitVector *bv = rz_bv_new_from_ut64(1, val->data.b->b);
|
||||
RzILVal *cast = rz_il_value_new_bitv(bv);
|
||||
rz_il_value_free(val);
|
||||
val = cast;
|
||||
} else if (var && var->type == RZ_IL_VAR_TYPE_BOOL && val->type == RZ_IL_VAR_TYPE_BV) {
|
||||
RzILBool *b = rz_il_bool_new(!rz_bv_is_zero_vector(val->data.bv));
|
||||
RzILVal *cast = rz_il_value_new_bool(b);
|
||||
rz_il_value_free(val);
|
||||
val = cast;
|
||||
}
|
||||
|
||||
if (is_local) {
|
||||
// add/update local variable
|
||||
if (var) {
|
||||
// update mutable local variable
|
||||
rz_il_hash_cancel_local_binding(vm, var);
|
||||
} else {
|
||||
// first set of an mutable/immutable local variable
|
||||
var = rz_il_vm_create_local_variable(vm, var_name, val->type, is_mutable);
|
||||
}
|
||||
rz_il_hash_local_bind(vm, var, val);
|
||||
} else {
|
||||
// update global variable
|
||||
evt = il_event_new_write_from_var(vm, var, val);
|
||||
rz_il_hash_cancel_binding(vm, var);
|
||||
rz_il_hash_bind(vm, var, val);
|
||||
|
||||
rz_il_vm_fortify_val(vm, val);
|
||||
RzILVar *var = rz_il_vm_get_var(vm, RZ_IL_VAR_KIND_GLOBAL, var_name);
|
||||
RzILEvent *evt = il_event_new_write_from_var(vm, var, val);
|
||||
rz_il_vm_event_add(vm, evt);
|
||||
rz_il_vm_set_global_var(vm, var_name, val);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -109,18 +60,7 @@ bool rz_il_handler_set(RzILVM *vm, RzILOpEffect *op) {
|
|||
if (!val) {
|
||||
return false;
|
||||
}
|
||||
rz_il_set(vm, set_op->v, false, true, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool rz_il_handler_let(RzILVM *vm, RzILOpEffect *op) {
|
||||
rz_return_val_if_fail(vm && op, false);
|
||||
RzILOpArgsLet *let_op = &op->op.let;
|
||||
RzILVal *val = rz_il_evaluate_val(vm, let_op->x);
|
||||
if (!val) {
|
||||
return false;
|
||||
}
|
||||
rz_il_set(vm, let_op->v, true, let_op->mut, val);
|
||||
rz_il_set(vm, set_op->v, set_op->is_local, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,20 +7,20 @@
|
|||
static RzILEvent *il_event_new_read_from_name(RzILVM *vm, const char *name, RzILVal *value) {
|
||||
rz_return_val_if_fail(vm && name, NULL);
|
||||
RzBitVector *num = NULL;
|
||||
if (value->type == RZ_IL_VAR_TYPE_BOOL) {
|
||||
if (value->type == RZ_IL_TYPE_PURE_BOOL) {
|
||||
num = rz_bv_new_from_ut64(1, value->data.b->b);
|
||||
} else {
|
||||
num = value->data.bv;
|
||||
}
|
||||
|
||||
RzILEvent *evt = rz_il_event_var_read_new(name, num);
|
||||
if (value->type == RZ_IL_VAR_TYPE_BOOL) {
|
||||
if (value->type == RZ_IL_TYPE_PURE_BOOL) {
|
||||
rz_bv_free(num);
|
||||
}
|
||||
return evt;
|
||||
}
|
||||
|
||||
void *rz_il_handler_ite(RzILVM *vm, RzILOpPure *op, RzILPureType *type) {
|
||||
void *rz_il_handler_ite(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpArgsIte *op_ite = &op->op.ite;
|
||||
|
|
@ -39,33 +39,27 @@ void *rz_il_handler_ite(RzILVM *vm, RzILOpPure *op, RzILPureType *type) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
void *rz_il_handler_var(RzILVM *vm, RzILOpPure *op, RzILPureType *type) {
|
||||
void *rz_il_handler_var(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
bool is_local = false;
|
||||
|
||||
RzILOpArgsVar *var_op = &op->op.var;
|
||||
RzILVal *val = rz_il_hash_find_val_by_name(vm, var_op->v);
|
||||
if (!val) {
|
||||
val = rz_il_hash_find_local_val_by_name(vm, var_op->v);
|
||||
is_local = true;
|
||||
}
|
||||
|
||||
RzILVal *val = rz_il_vm_get_var_value(vm, var_op->kind, var_op->v);
|
||||
if (!val) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!is_local) {
|
||||
if (var_op->kind == RZ_IL_VAR_KIND_GLOBAL) {
|
||||
rz_il_vm_event_add(vm, il_event_new_read_from_name(vm, var_op->v, val));
|
||||
}
|
||||
|
||||
void *ret = NULL;
|
||||
switch (val->type) {
|
||||
case RZ_IL_VAR_TYPE_BOOL:
|
||||
*type = RZ_IL_PURE_TYPE_BOOL;
|
||||
case RZ_IL_TYPE_PURE_BOOL:
|
||||
*type = RZ_IL_TYPE_PURE_BOOL;
|
||||
ret = rz_il_bool_new(val->data.b->b);
|
||||
break;
|
||||
case RZ_IL_VAR_TYPE_BV:
|
||||
*type = RZ_IL_PURE_TYPE_BITV;
|
||||
case RZ_IL_TYPE_PURE_BITVECTOR:
|
||||
*type = RZ_IL_TYPE_PURE_BITVECTOR;
|
||||
ret = rz_bv_dup(val->data.bv);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -74,12 +68,25 @@ void *rz_il_handler_var(RzILVM *vm, RzILOpPure *op, RzILPureType *type) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
void *rz_il_handler_unk(RzILVM *vm, RzILOpPure *op, RzILPureType *type) {
|
||||
void *rz_il_handler_let(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
RzILOpArgsLet *args = &op->op.let;
|
||||
RzILVal *v = rz_il_evaluate_val(vm, args->exp);
|
||||
if (!v) {
|
||||
return NULL;
|
||||
}
|
||||
RzILLocalPurePrev prev = rz_il_vm_push_local_pure_var(vm, args->name, v);
|
||||
void *r = rz_il_evaluate_pure(vm, args->body, type);
|
||||
rz_il_vm_pop_local_pure_var(vm, args->name, prev);
|
||||
return r;
|
||||
}
|
||||
|
||||
void *rz_il_handler_unk(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *rz_il_handler_pure_unimplemented(RzILVM *vm, RzILOpPure *op, RzILPureType *type) {
|
||||
void *rz_il_handler_pure_unimplemented(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
RZ_LOG_ERROR("RzIL: unimplemented op handler (%d).\n", (int)op->code);
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#include <rz_il/rz_il_vm.h>
|
||||
#include <rz_il/rz_il_opcodes.h>
|
||||
|
||||
void *rz_il_handler_load(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_load(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
RzILOpArgsLoad *op_load = &op->op.load;
|
||||
|
||||
|
|
@ -15,7 +15,7 @@ void *rz_il_handler_load(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
|||
}
|
||||
RzBitVector *ret = rz_il_vm_mem_load(vm, op_load->mem, addr);
|
||||
rz_bv_free(addr);
|
||||
*type = RZ_IL_PURE_TYPE_BITV;
|
||||
*type = RZ_IL_TYPE_PURE_BITVECTOR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ bool rz_il_handler_store(RzILVM *vm, RzILOpEffect *op) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
void *rz_il_handler_loadw(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
||||
void *rz_il_handler_loadw(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
RzILOpArgsLoadW *op_loadw = &op->op.loadw;
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ void *rz_il_handler_loadw(RzILVM *vm, RzILOpBitVector *op, RzILPureType *type) {
|
|||
}
|
||||
RzBitVector *ret = rz_il_vm_mem_loadw(vm, op_loadw->mem, addr, op_loadw->n_bits);
|
||||
rz_bv_free(addr);
|
||||
*type = RZ_IL_PURE_TYPE_BITV;
|
||||
*type = RZ_IL_TYPE_PURE_BITVECTOR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -116,7 +116,6 @@ rz_util_files = [
|
|||
install_headers(rz_util_files, install_dir: join_paths(rizin_incdir, 'rz_util'))
|
||||
|
||||
rz_il_definitions_files = [
|
||||
'rz_il/definitions/bag.h',
|
||||
'rz_il/definitions/bool.h',
|
||||
'rz_il/definitions/definitions.h',
|
||||
'rz_il/definitions/label.h',
|
||||
|
|
|
|||
|
|
@ -1,40 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2021 heersin <teablearcher@gmail.com>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#ifndef RZ_IL_BAG_H
|
||||
#define RZ_IL_BAG_H
|
||||
|
||||
#include <rz_util.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*RzILBagFreeFunc)(void *);
|
||||
/**
|
||||
* \struct rz_il_bag_t
|
||||
* \brief structure of RzILBag, used to store RzILVal instances and manage them
|
||||
*
|
||||
* The main purpose of introducing RzILBag is to prevent excessive growth in the number of RzILVal
|
||||
* It's mainly used to clean up unused values during VM execution, and clean up values at the end
|
||||
*/
|
||||
typedef struct rz_il_bag_t {
|
||||
void **data_list; ///< Space to carry pointers
|
||||
int item_count; ///< count current items
|
||||
int capacity; ///< maximum size
|
||||
int *next_pos_stack; ///< internal variable, used for managing space
|
||||
int next_pos; ///< internal variable, used for managing space
|
||||
int sp; ///< internal variable, used for managing space
|
||||
RzILBagFreeFunc free_func; ///< Function pointer to free RzILVal
|
||||
} RzILBag;
|
||||
|
||||
RZ_API RzILBag *rz_il_new_bag(int capacity, RzILBagFreeFunc func);
|
||||
RZ_API bool rz_il_rm_from_bag(RzILBag *bag, void *item);
|
||||
RZ_API bool rz_il_add_to_bag(RzILBag *bag, void *item);
|
||||
RZ_API void rz_il_free_bag(RzILBag *bag);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // RZ_IL_BAG_H
|
||||
|
|
@ -9,7 +9,6 @@
|
|||
#include <rz_il/definitions/bool.h>
|
||||
#include <rz_il/definitions/value.h>
|
||||
#include <rz_il/definitions/variable.h>
|
||||
#include <rz_il/definitions/bag.h>
|
||||
#include <rz_il/definitions/mem.h>
|
||||
|
||||
#endif // RZ_IL_DEFINITIONS_H
|
||||
|
|
|
|||
66
librz/include/rz_il/definitions/sort.h
Normal file
66
librz/include/rz_il/definitions/sort.h
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
// SPDX-FileCopyrightText: 2022 Florian Märkl <info@florianmaerkl.de>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#ifndef RZ_IL_SORT_H
|
||||
#define RZ_IL_SORT_H
|
||||
|
||||
#include <rz_types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \brief Type and Sort identifiers for values in the IL
|
||||
*
|
||||
* Our notion:
|
||||
* * Types only tell which kind of value something is. E.g. whether it is a bitvector or boolean, but no other info.
|
||||
* They can generally be expressed sufficiently as an enum.
|
||||
* * Sorts carry any additional info that makes up the structure of a value, in particular bitvector sorts specify a concrete bit count.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
RZ_IL_TYPE_PURE_BOOL,
|
||||
RZ_IL_TYPE_PURE_BITVECTOR
|
||||
} RzILTypePure;
|
||||
|
||||
typedef struct rz_il_sort_pure_t {
|
||||
RzILTypePure type;
|
||||
union {
|
||||
struct {
|
||||
ut32 length;
|
||||
} bv;
|
||||
} props;
|
||||
} RzILSortPure;
|
||||
|
||||
static inline bool rz_il_sort_pure_eq(RzILSortPure a, RzILSortPure b) {
|
||||
if (a.type != b.type) {
|
||||
return false;
|
||||
}
|
||||
if (a.type == RZ_IL_TYPE_PURE_BITVECTOR && a.props.bv.length != b.props.bv.length) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline RzILSortPure rz_il_sort_pure_bool() {
|
||||
RzILSortPure r = {
|
||||
.type = RZ_IL_TYPE_PURE_BOOL
|
||||
};
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline RzILSortPure rz_il_sort_pure_bv(ut32 length) {
|
||||
RzILSortPure r = {
|
||||
.type = RZ_IL_TYPE_PURE_BITVECTOR
|
||||
};
|
||||
r.props.bv.length = length;
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -6,7 +6,8 @@
|
|||
#ifndef RZ_IL_VALUE_H
|
||||
#define RZ_IL_VALUE_H
|
||||
|
||||
#include <rz_il/definitions/variable.h>
|
||||
#include <rz_il/definitions/bool.h>
|
||||
#include <rz_il/definitions/sort.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
@ -21,16 +22,16 @@ typedef union {
|
|||
* A concrete value of `'a pure`. Either a bitvector or boolean.
|
||||
*/
|
||||
typedef struct rz_il_val_t {
|
||||
RzILVarType type; ///< type of value
|
||||
RzILTypePure type; ///< type of value
|
||||
RzValUnion data; ///< data pointer
|
||||
} RzILVal;
|
||||
|
||||
RZ_API RZ_OWN RzILVal *rz_il_value_new_bitv(RZ_NONNULL RzBitVector *bv);
|
||||
RZ_API RZ_OWN RzILVal *rz_il_value_new_bool(RZ_NONNULL RzILBool *b);
|
||||
#define rz_il_value_new_unk() rz_il_value_new(RZ_IL_VAR_TYPE_UNK)
|
||||
RZ_API RZ_OWN RzILVal *rz_il_value_new(RzILVarType type);
|
||||
RZ_API RZ_OWN RzILVal *rz_il_value_new_zero_of(RzILSortPure sort);
|
||||
RZ_API RZ_OWN RzILVal *rz_il_value_dup(RZ_NONNULL RzILVal *val);
|
||||
RZ_API void rz_il_value_free(RZ_NULLABLE RzILVal *val);
|
||||
RZ_API RzILSortPure rz_il_value_get_sort(RZ_NONNULL RzILVal *val);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,31 +7,48 @@
|
|||
#define RZ_IL_VARIABLE_H
|
||||
|
||||
#include <rz_util/rz_bitvector.h>
|
||||
#include <rz_il/definitions/bool.h>
|
||||
#include <rz_il/definitions/value.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
RZ_IL_VAR_TYPE_BV,
|
||||
RZ_IL_VAR_TYPE_BOOL,
|
||||
RZ_IL_VAR_TYPE_UNK, // Unkown value
|
||||
} RzILVarType;
|
||||
|
||||
/**
|
||||
* \struct rz_il_var_t
|
||||
* \brief structure of RzILVar
|
||||
* \brief Definition of a variable inside the vm
|
||||
*/
|
||||
typedef struct rz_il_var_t {
|
||||
char *var_name; ///< name of variable
|
||||
bool is_mutable;
|
||||
RzILVarType type; ///< data type of variable
|
||||
char *name;
|
||||
RzILSortPure sort; ///< "type" of the variable
|
||||
} RzILVar;
|
||||
|
||||
RZ_API RZ_OWN RzILVar *rz_il_variable_new(RZ_NONNULL const char *name, RzILVarType type, bool is_mutable);
|
||||
RZ_API RZ_OWN RzILVar *rz_il_variable_new(RZ_NONNULL const char *name, RzILSortPure sort);
|
||||
RZ_API void rz_il_variable_free(RZ_NULLABLE RzILVar *var);
|
||||
|
||||
/**
|
||||
* \brief Holds a set of variable definitions and their current contents
|
||||
* This is meant only as a low-level container to be used in RzILVM.
|
||||
*/
|
||||
typedef struct rz_il_var_set_t {
|
||||
HtPP /* <char *, RzILVar *> */ *vars;
|
||||
HtPP /* <char *, RzILVal *> */ *contents;
|
||||
} RzILVarSet;
|
||||
|
||||
RZ_API bool rz_il_var_set_init(RzILVarSet *vs);
|
||||
RZ_API void rz_il_var_set_fini(RzILVarSet *vs);
|
||||
RZ_API void rz_il_var_set_reset(RzILVarSet *vs);
|
||||
RZ_API RZ_BORROW RzILVar *rz_il_var_set_create_var(RzILVarSet *vs, const char *name, RzILSortPure sort);
|
||||
RZ_API RZ_OWN RZ_NULLABLE RzILVal *rz_il_var_set_remove_var(RzILVarSet *vs, const char *name);
|
||||
RZ_API bool rz_il_var_set_bind(RzILVarSet *vs, const char *name, RZ_OWN RzILVal *val);
|
||||
RZ_API RZ_BORROW RzILVar *rz_il_var_set_get(RzILVarSet *vs, const char *name);
|
||||
RZ_API RZ_OWN RzPVector /* <RzILVar> */ *rz_il_var_set_get_all(RzILVarSet *vs);
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_var_set_get_value(RzILVarSet *vs, const char *name);
|
||||
|
||||
typedef enum {
|
||||
RZ_IL_VAR_KIND_GLOBAL, ///< global var, usually bound to a physical representation like a register.
|
||||
RZ_IL_VAR_KIND_LOCAL, ///< local var, defined and assigned by set ops, mutable and useable across effects.
|
||||
RZ_IL_VAR_KIND_LOCAL_PURE ///< local pure var, bound only by let expressions, scope is limited to the let's pure body, thus it's immutable.
|
||||
} RzILVarKind;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -164,24 +164,25 @@ typedef struct rz_il_op_args_shift_t RzILOpArgsShiftLeft;
|
|||
typedef struct rz_il_op_args_shift_t RzILOpArgsShiftRight;
|
||||
|
||||
/**
|
||||
* \brief op structure for `set` ('a var -> 'a pure -> data eff)
|
||||
* \brief op structure for `set` ('a var -> 'a pure -> data eff)
|
||||
*
|
||||
* set v x changes the value stored in v to the value of x.
|
||||
* set v x changes the value stored in v to the value of x.
|
||||
*/
|
||||
typedef struct rz_il_op_args_set_t {
|
||||
const char *v; ///< name of variable, const one
|
||||
bool is_local; ///< whether a global variable should be set or a local optionally created and set
|
||||
RzILOpPure *x; ///< value to set the variable to
|
||||
} RzILOpArgsSet;
|
||||
|
||||
/**
|
||||
* \brief op structure for `set` ('a var -> 'a pure -> data eff)
|
||||
* \brief op structure for `let_ : 'a var -> 'a pure -> 'b pure -> 'b pure`
|
||||
*
|
||||
* set v x changes the value stored in v to the value of x.
|
||||
* `let_ v exp body` binds the value of exp to v body.
|
||||
*/
|
||||
typedef struct rz_il_op_args_let_t {
|
||||
const char *v; ///< name of variable, const one
|
||||
bool mut; ///< define is local variable is const or not
|
||||
RzILOpPure *x; ///< value to set the variable to
|
||||
const char *name; ///< name of variable
|
||||
RzILOpPure *exp; ///< value/expression to bind the variable to
|
||||
RzILOpPure *body; ///< body in which the variable will be bound and that produces the result
|
||||
} RzILOpArgsLet;
|
||||
|
||||
/**
|
||||
|
|
@ -262,6 +263,7 @@ typedef struct rz_il_op_args_ite_t {
|
|||
*/
|
||||
typedef struct rz_il_op_args_var_t {
|
||||
const char *v; ///< name of variable, const one
|
||||
RzILVarKind kind; ///< set of variables to pick from
|
||||
} RzILOpArgsVar;
|
||||
|
||||
/**
|
||||
|
|
@ -347,6 +349,7 @@ typedef enum {
|
|||
RZ_IL_OP_VAR,
|
||||
RZ_IL_OP_UNK,
|
||||
RZ_IL_OP_ITE,
|
||||
RZ_IL_OP_LET,
|
||||
|
||||
// RzILBool
|
||||
RZ_IL_OP_B0,
|
||||
|
|
@ -404,6 +407,7 @@ struct rz_il_op_pure_t {
|
|||
union {
|
||||
RzILOpArgsIte ite;
|
||||
RzILOpArgsVar var;
|
||||
RzILOpArgsLet let;
|
||||
|
||||
RzILOpArgsBoolAnd booland;
|
||||
RzILOpArgsBoolOr boolor;
|
||||
|
|
@ -444,7 +448,8 @@ RZ_API RzILOpPure *rz_il_op_pure_dup(RZ_NONNULL RzILOpPure *op);
|
|||
|
||||
RZ_API RZ_OWN RzILOpPure *rz_il_op_new_ite(RZ_NONNULL RzILOpPure *condition, RZ_NULLABLE RzILOpPure *x, RZ_NULLABLE RzILOpPure *y);
|
||||
RZ_API RZ_OWN RzILOpPure *rz_il_op_new_unk();
|
||||
RZ_API RZ_OWN RzILOpPure *rz_il_op_new_var(RZ_NONNULL const char *var);
|
||||
RZ_API RZ_OWN RzILOpPure *rz_il_op_new_var(RZ_NONNULL const char *var, RzILVarKind kind);
|
||||
RZ_API RZ_OWN RzILOpPure *rz_il_op_new_let(RZ_NONNULL const char *name, RZ_NONNULL RzILOpPure *exp, RZ_NONNULL RzILOpPure *body);
|
||||
RZ_API RZ_OWN RzILOpBool *rz_il_op_new_b0();
|
||||
RZ_API RZ_OWN RzILOpBool *rz_il_op_new_b1();
|
||||
RZ_API RZ_OWN RzILOpBool *rz_il_op_new_bool_and(RZ_NONNULL RzILOpBool *x, RZ_NONNULL RzILOpBool *y);
|
||||
|
|
@ -492,7 +497,6 @@ typedef enum {
|
|||
|
||||
RZ_IL_OP_NOP,
|
||||
RZ_IL_OP_SET,
|
||||
RZ_IL_OP_LET,
|
||||
RZ_IL_OP_JMP,
|
||||
RZ_IL_OP_GOTO,
|
||||
RZ_IL_OP_SEQ,
|
||||
|
|
@ -507,7 +511,6 @@ struct rz_il_op_effect_t {
|
|||
RzILOpEffectCode code;
|
||||
union {
|
||||
RzILOpArgsSet set;
|
||||
RzILOpArgsLet let;
|
||||
RzILOpArgsJmp jmp;
|
||||
RzILOpArgsGoto goto_;
|
||||
RzILOpArgsSeq seq;
|
||||
|
|
@ -523,8 +526,7 @@ struct rz_il_op_effect_t {
|
|||
RZ_API void rz_il_op_effect_free(RZ_NULLABLE RzILOpEffect *op);
|
||||
|
||||
RZ_API RZ_OWN RzILOpEffect *rz_il_op_new_nop();
|
||||
RZ_API RZ_OWN RzILOpEffect *rz_il_op_new_set(RZ_NONNULL const char *var, RZ_NONNULL RzILOpPure *x);
|
||||
RZ_API RZ_OWN RzILOpEffect *rz_il_op_new_let(RZ_NONNULL const char *var, RZ_NONNULL RzILOpPure *x, bool is_mutable);
|
||||
RZ_API RZ_OWN RzILOpEffect *rz_il_op_new_set(RZ_NONNULL const char *v, bool is_local, RZ_NONNULL RzILOpPure *x);
|
||||
RZ_API RZ_OWN RzILOpEffect *rz_il_op_new_jmp(RZ_NONNULL RzILOpBitVector *dst);
|
||||
RZ_API RZ_OWN RzILOpEffect *rz_il_op_new_goto(RZ_NONNULL const char *label);
|
||||
RZ_API RZ_OWN RzILOpEffect *rz_il_op_new_seq(RZ_NONNULL RzILOpEffect *x, RZ_NONNULL RzILOpEffect *y);
|
||||
|
|
|
|||
|
|
@ -14,14 +14,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define RZ_IL_VM_MAX_VAR 2048
|
||||
#define RZ_IL_VM_MAX_VAL 1024
|
||||
|
||||
typedef enum {
|
||||
RZ_IL_PURE_TYPE_BOOL, ///< RzILBool
|
||||
RZ_IL_PURE_TYPE_BITV ///< RzBitVector
|
||||
} RzILPureType;
|
||||
|
||||
typedef struct rz_il_vm_t RzILVM;
|
||||
|
||||
/**
|
||||
|
|
@ -29,7 +21,7 @@ typedef struct rz_il_vm_t RzILVM;
|
|||
* \param type when returning a non-null value, this must be set to the respective type.
|
||||
* \return The evaluated value of the type indicated by *type, or NULL if an error occured and the execution should be aborted
|
||||
*/
|
||||
typedef void *(*RzILOpPureHandler)(RzILVM *vm, RzILOpPure *op, RZ_NONNULL RZ_OUT RzILPureType *type);
|
||||
typedef void *(*RzILOpPureHandler)(RzILVM *vm, RzILOpPure *op, RZ_NONNULL RZ_OUT RzILTypePure *type);
|
||||
|
||||
/**
|
||||
* \brief Evaluation (execution) callback for a single effect opcode
|
||||
|
|
@ -44,15 +36,13 @@ typedef void (*RzILVmHook)(RzILVM *vm, RzILOpEffect *op);
|
|||
* \brief core theory VM structure
|
||||
*/
|
||||
struct rz_il_vm_t {
|
||||
RzILBag *vm_global_value_set; ///< Store all RzILVal instance
|
||||
RzPVector /*<RzILVar*>*/ vm_global_variable_list; ///< Store all the global RzILVar instance
|
||||
RZ_NULLABLE RzILRegBinding *reg_binding; ///< Optional, specifies which (global) variables are bound to registers
|
||||
RzPVector /*<RzILVar*>*/ vm_local_variable_list; ///< Store all the local RzILVar instance
|
||||
RzPVector /*<RzILMem*>*/ vm_memory; ///< Memories available in the VM, by their inded. May be sparse (contain NULLs).
|
||||
RzILVarSet global_vars; ///< All global variables (usually bound to registers)
|
||||
RzILVarSet local_vars; ///< All local variables, created by local set ops
|
||||
RzILVarSet local_pure_vars; ///< All local variables, during execution temporarily bound by let, only usable in pure expressions and immutable
|
||||
RzPVector /*<RzILMem>*/ vm_memory; ///< Memories available in the VM, by their index. May be sparse (contain NULLs).
|
||||
ut32 val_count, lab_count; ///< count for VM predefined things
|
||||
ut32 addr_size; ///< size of address space
|
||||
HtPP *vm_global_bind_table; ///< Hashtable to record relationships between global var and val
|
||||
HtPP *vm_local_bind_table; ///< Hashtable to record relationships between local var and val
|
||||
HtPP *vm_global_label_table; ///< Hashtable to maintain the label and address
|
||||
HtPP *vm_local_label_table; ///< Hashtable to maintain the label and address
|
||||
RzBitVector *pc; ///< Program Counter of VM
|
||||
|
|
@ -67,53 +57,38 @@ RZ_API RzILVM *rz_il_vm_new(ut64 start_addr, ut32 addr_size, bool big_endian);
|
|||
RZ_API void rz_il_vm_free(RzILVM *vm);
|
||||
RZ_API bool rz_il_vm_init(RzILVM *vm, ut64 start_addr, ut32 addr_size, bool big_endian);
|
||||
RZ_API void rz_il_vm_fini(RzILVM *vm);
|
||||
RZ_API void rz_il_vm_add_mem(RzILVM *vm, RzILMemIndex index, RZ_OWN RzILMem *mem);
|
||||
RZ_API RzILMem *rz_il_vm_get_mem(RzILVM *vm, RzILMemIndex index);
|
||||
RZ_API bool rz_il_vm_step(RzILVM *vm, RzILOpEffect *op, ut32 op_size);
|
||||
|
||||
// VM Event operations
|
||||
RZ_API void rz_il_vm_event_add(RzILVM *vm, RzILEvent *evt);
|
||||
|
||||
// Memory operations
|
||||
RZ_API void rz_il_vm_add_mem(RzILVM *vm, RzILMemIndex index, RZ_OWN RzILMem *mem);
|
||||
RZ_API RzILMem *rz_il_vm_get_mem(RzILVM *vm, RzILMemIndex index);
|
||||
|
||||
RZ_API RzBitVector *rz_il_vm_mem_load(RzILVM *vm, RzILMemIndex index, RzBitVector *key);
|
||||
RZ_API void rz_il_vm_mem_store(RzILVM *vm, RzILMemIndex index, RzBitVector *key, RzBitVector *value);
|
||||
RZ_API RzBitVector *rz_il_vm_mem_loadw(RzILVM *vm, RzILMemIndex index, RzBitVector *key, ut32 n_bits);
|
||||
RZ_API void rz_il_vm_mem_storew(RzILVM *vm, RzILMemIndex index, RzBitVector *key, RzBitVector *value);
|
||||
|
||||
// VM operations about Variable and Value
|
||||
// Labels
|
||||
RZ_API RZ_BORROW RzBitVector *rz_il_hash_find_addr_by_lblname(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *lbl_name);
|
||||
RZ_API RZ_BORROW RzILEffectLabel *rz_il_vm_find_label_by_name(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *lbl_name);
|
||||
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);
|
||||
RZ_API RZ_BORROW RzILEffectLabel *rz_il_vm_create_label_lazy(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name);
|
||||
RZ_API RZ_BORROW RzILEffectLabel *rz_il_vm_update_label(RZ_NONNULL RzILVM *vm, RZ_NONNULL char *name, RZ_NONNULL RZ_BORROW RzBitVector *addr);
|
||||
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_hash_find_val_by_var(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILVar *var);
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_hash_find_val_by_name(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *var_name);
|
||||
RZ_API RZ_BORROW RzILVar *rz_il_find_var_by_name(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *var_name);
|
||||
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_hash_find_local_val_by_var(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILVar *var);
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_hash_find_local_val_by_name(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *var_name);
|
||||
RZ_API RZ_BORROW RzILVar *rz_il_find_local_var_by_name(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *var_name);
|
||||
|
||||
RZ_API RZ_BORROW RzILVar *rz_il_vm_create_global_variable(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, RzILVarType type, bool is_mutable);
|
||||
RZ_API RZ_BORROW RzILVar *rz_il_vm_create_local_variable(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, RzILVarType type, bool is_mutable);
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_vm_create_value_bitv(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzBitVector *bitv);
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_vm_create_value_bool(RZ_NONNULL RzILVM *vm, bool value);
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_vm_create_value_unk(RZ_NONNULL RzILVM *vm);
|
||||
|
||||
RZ_API void rz_il_hash_bind(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILVar *var, RZ_NONNULL RzILVal *val);
|
||||
RZ_API void rz_il_hash_cancel_binding(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILVar *var);
|
||||
|
||||
RZ_API void rz_il_hash_local_bind(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILVar *var, RZ_NONNULL RzILVal *val);
|
||||
RZ_API void rz_il_hash_cancel_local_binding(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILVar *var);
|
||||
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_vm_fortify_val(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILVal *val);
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_vm_fortify_bitv(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzBitVector *val);
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_vm_fortify_bool(RZ_NONNULL RzILVM *vm, bool val);
|
||||
|
||||
RZ_API void rz_il_vm_add_reg(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, ut32 length);
|
||||
RZ_API void rz_il_vm_add_bit_reg(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, bool value);
|
||||
// Variables
|
||||
RZ_API RZ_BORROW RzILVar *rz_il_vm_create_global_var(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, RzILSortPure sort);
|
||||
RZ_API void rz_il_vm_set_global_var(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, RZ_OWN RzILVal *val);
|
||||
RZ_API void rz_il_vm_set_local_var(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, RZ_OWN RzILVal *val);
|
||||
typedef RZ_NULLABLE RzILVal *RzILLocalPurePrev;
|
||||
RZ_API RzILLocalPurePrev rz_il_vm_push_local_pure_var(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, RzILVal *val);
|
||||
RZ_API void rz_il_vm_pop_local_pure_var(RZ_NONNULL RzILVM *vm, RZ_NONNULL const char *name, RzILLocalPurePrev prev);
|
||||
RZ_API RZ_BORROW RzILVar *rz_il_vm_get_var(RZ_NONNULL RzILVM *vm, RzILVarKind kind, const char *name);
|
||||
RZ_API RZ_OWN RzPVector /* <RzILVar> */ *rz_il_vm_get_all_vars(RZ_NONNULL RzILVM *vm, RzILVarKind kind);
|
||||
RZ_API RZ_BORROW RzILVal *rz_il_vm_get_var_value(RZ_NONNULL RzILVM *vm, RzILVarKind kind, const char *name);
|
||||
|
||||
// Printing/Export
|
||||
RZ_API void rz_il_op_pure_stringify(RZ_NONNULL RzILOpPure *op, RZ_NONNULL RzStrBuf *sb);
|
||||
RZ_API void rz_il_op_effect_stringify(RZ_NONNULL RzILOpEffect *op, RZ_NONNULL RzStrBuf *sb);
|
||||
|
||||
|
|
@ -123,15 +98,14 @@ RZ_API void rz_il_op_effect_json(RZ_NONNULL RzILOpEffect *op, RZ_NONNULL PJ *pj)
|
|||
RZ_API void rz_il_event_stringify(RZ_NONNULL RzILEvent *evt, RZ_NONNULL RzStrBuf *sb);
|
||||
RZ_API void rz_il_event_json(RZ_NONNULL RzILEvent *evt, RZ_NONNULL PJ *pj);
|
||||
|
||||
// VM auto convert functions
|
||||
// Evaluation (Emulation)
|
||||
RZ_API RZ_NULLABLE RZ_OWN RzBitVector *rz_il_evaluate_bitv(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILOpBitVector *op);
|
||||
RZ_API RZ_NULLABLE RZ_OWN RzILBool *rz_il_evaluate_bool(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILOpBool *op);
|
||||
RZ_API RZ_NULLABLE RZ_OWN RzILVal *rz_il_evaluate_val(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILOpPure *op);
|
||||
RZ_API RZ_NULLABLE RZ_OWN RzILVal *rz_il_evaluate_pure(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILOpPure *op, RZ_NONNULL RzILPureType *type);
|
||||
RZ_API RZ_NULLABLE RZ_OWN void *rz_il_evaluate_pure(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILOpPure *op, RZ_NONNULL RzILTypePure *type);
|
||||
RZ_API bool rz_il_evaluate_effect(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILOpEffect *op);
|
||||
|
||||
// recursively parse and evaluate
|
||||
RZ_API RZ_OWN void *rz_il_parse_op_root(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILOpEffect *op);
|
||||
RZ_API bool rz_il_vm_step(RzILVM *vm, RzILOpEffect *op, ut32 op_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ RZ_API ut16 rz_bv_to_ut16(RZ_NONNULL const RzBitVector *x);
|
|||
RZ_API ut32 rz_bv_to_ut32(RZ_NONNULL const RzBitVector *x);
|
||||
RZ_API ut64 rz_bv_to_ut64(RZ_NONNULL const RzBitVector *x);
|
||||
// misc
|
||||
RZ_API bool rz_bv_is_zero_vector(RZ_NONNULL RzBitVector *x);
|
||||
RZ_API bool rz_bv_is_zero_vector(RZ_NONNULL const RzBitVector *x);
|
||||
RZ_API RZ_OWN RzBitVector *rz_bv_new_from_ut64(ut32 length, ut64 value);
|
||||
RZ_API RZ_OWN RzBitVector *rz_bv_new_from_st64(ut32 length, st64 value);
|
||||
RZ_API RZ_OWN RzBitVector *rz_bv_new_from_bytes_le(RZ_IN RZ_NONNULL const ut8 *buf, ut32 bit_offset, ut32 size);
|
||||
|
|
|
|||
|
|
@ -1010,7 +1010,7 @@ RZ_API bool rz_bv_lsb(RZ_NONNULL RzBitVector *bv) {
|
|||
* \param x RzBitVector, pointer to bv
|
||||
* \return ret bool, return true if bv is a zero bitvector, false if not
|
||||
*/
|
||||
RZ_API bool rz_bv_is_zero_vector(RZ_NONNULL RzBitVector *x) {
|
||||
RZ_API bool rz_bv_is_zero_vector(RZ_NONNULL const RzBitVector *x) {
|
||||
rz_return_val_if_fail(x, false);
|
||||
|
||||
if (x->len <= 64) {
|
||||
|
|
|
|||
|
|
@ -166,18 +166,10 @@ static bool test_il_vm_sync_to_reg() {
|
|||
RzILRegBinding *rb = rz_il_reg_binding_exactly(reg, RZ_ARRAY_SIZE(bind), bind);
|
||||
rz_il_vm_setup_reg_binding(vm, rb);
|
||||
|
||||
RzILVar *var = rz_il_find_var_by_name(vm, "r0");
|
||||
mu_assert_notnull(var, "var");
|
||||
rz_il_hash_bind(vm, var, rz_il_vm_fortify_bitv(vm, rz_bv_new_from_ut64(64, 0x8247abc)));
|
||||
var = rz_il_find_var_by_name(vm, "r1");
|
||||
mu_assert_notnull(var, "var");
|
||||
rz_il_hash_bind(vm, var, rz_il_vm_fortify_bitv(vm, rz_bv_new_from_ut64(32, 0xfed134)));
|
||||
var = rz_il_find_var_by_name(vm, "af");
|
||||
mu_assert_notnull(var, "var");
|
||||
rz_il_hash_bind(vm, var, rz_il_vm_fortify_bool(vm, false));
|
||||
var = rz_il_find_var_by_name(vm, "bf");
|
||||
mu_assert_notnull(var, "var");
|
||||
rz_il_hash_bind(vm, var, rz_il_vm_fortify_bool(vm, true));
|
||||
rz_il_vm_set_global_var(vm, "r0", rz_il_value_new_bitv(rz_bv_new_from_ut64(64, 0x8247abc)));
|
||||
rz_il_vm_set_global_var(vm, "r1", rz_il_value_new_bitv(rz_bv_new_from_ut64(32, 0xfed134)));
|
||||
rz_il_vm_set_global_var(vm, "af", rz_il_value_new_bool(rz_il_bool_new(false)));
|
||||
rz_il_vm_set_global_var(vm, "bf", rz_il_value_new_bool(rz_il_bool_new(true)));
|
||||
|
||||
rz_bv_set_from_ut64(vm->pc, 0x10001);
|
||||
|
||||
|
|
@ -189,6 +181,39 @@ static bool test_il_vm_sync_to_reg() {
|
|||
mu_assert_eq(rz_reg_getv(reg, "bf"), 1, "reg from vm");
|
||||
|
||||
rz_reg_free(reg);
|
||||
|
||||
// adjustments after profile change
|
||||
const char *profile2 =
|
||||
"=PC pc\n"
|
||||
"gpr r1 .64 8 0\n"
|
||||
"gpr r0 .32 0 0\n"
|
||||
"gpr r3 .64 24 0\n"
|
||||
"gpr pc .64 32 0\n"
|
||||
"gpr af .8 40 0\n"
|
||||
"gpr bf .1 41.0 0\n";
|
||||
reg = rz_reg_new();
|
||||
rz_reg_set_profile_string(reg, profile2);
|
||||
rz_il_vm_sync_to_reg(vm, reg);
|
||||
mu_assert_eq(rz_reg_getv(reg, "r0"), 0x8247abc, "reg from vm");
|
||||
mu_assert_eq(rz_reg_getv(reg, "r1"), 0xfed134, "reg from vm");
|
||||
mu_assert_eq(rz_reg_getv(reg, "pc"), 0x10001, "reg from vm");
|
||||
mu_assert_eq(rz_reg_getv(reg, "af"), 0, "reg from vm");
|
||||
mu_assert_eq(rz_reg_getv(reg, "bf"), 1, "reg from vm");
|
||||
rz_reg_free(reg);
|
||||
|
||||
// even harder adjustments
|
||||
const char *profile3 =
|
||||
"=PC pc\n"
|
||||
"gpr r1 .1 8 0\n"
|
||||
"gpr r42 .64 24 0\n"
|
||||
"gpr pc .64 32 0\n";
|
||||
reg = rz_reg_new();
|
||||
rz_reg_set_profile_string(reg, profile3);
|
||||
rz_il_vm_sync_to_reg(vm, reg);
|
||||
mu_assert_eq(rz_reg_getv(reg, "r1"), 1, "reg from vm");
|
||||
mu_assert_eq(rz_reg_getv(reg, "pc"), 0x10001, "reg from vm");
|
||||
rz_reg_free(reg);
|
||||
|
||||
rz_il_vm_free(vm);
|
||||
mu_end;
|
||||
}
|
||||
|
|
@ -218,30 +243,116 @@ static bool test_il_vm_sync_from_reg() {
|
|||
rz_il_vm_setup_reg_binding(vm, rb);
|
||||
|
||||
rz_il_vm_sync_from_reg(vm, reg);
|
||||
RzILVal *val = rz_il_hash_find_val_by_name(vm, "r0");
|
||||
RzILVal *val = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, "r0");
|
||||
mu_assert_notnull(val, "val");
|
||||
mu_assert_eq(val->type, RZ_IL_VAR_TYPE_BV, "val type");
|
||||
mu_assert_eq(val->type, RZ_IL_TYPE_PURE_BITVECTOR, "val type");
|
||||
mu_assert_eq(rz_bv_len(val->data.bv), 64, "val len");
|
||||
mu_assert_eq(rz_bv_to_ut64(val->data.bv), 0x1234, "val val");
|
||||
val = rz_il_hash_find_val_by_name(vm, "r1");
|
||||
val = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, "r1");
|
||||
mu_assert_notnull(val, "val");
|
||||
mu_assert_eq(val->type, RZ_IL_VAR_TYPE_BV, "val type");
|
||||
mu_assert_eq(val->type, RZ_IL_TYPE_PURE_BITVECTOR, "val type");
|
||||
mu_assert_eq(rz_bv_len(val->data.bv), 32, "val len");
|
||||
mu_assert_eq(rz_bv_to_ut64(val->data.bv), 0x5678, "val val");
|
||||
RzILVar *var = rz_il_find_var_by_name(vm, "r3");
|
||||
RzILVar *var = rz_il_vm_get_var(vm, RZ_IL_VAR_KIND_GLOBAL, "r3");
|
||||
mu_assert_null(var, "unbound");
|
||||
val = rz_il_hash_find_val_by_name(vm, "af");
|
||||
val = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, "af");
|
||||
mu_assert_notnull(val, "val");
|
||||
mu_assert_eq(val->type, RZ_IL_VAR_TYPE_BOOL, "val type");
|
||||
mu_assert_eq(val->type, RZ_IL_TYPE_PURE_BOOL, "val type");
|
||||
mu_assert_false(val->data.b->b, "val val");
|
||||
val = rz_il_hash_find_val_by_name(vm, "bf");
|
||||
val = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, "bf");
|
||||
mu_assert_notnull(val, "val");
|
||||
mu_assert_eq(val->type, RZ_IL_VAR_TYPE_BOOL, "val type");
|
||||
mu_assert_eq(val->type, RZ_IL_TYPE_PURE_BOOL, "val type");
|
||||
mu_assert_true(val->data.b->b, "val val");
|
||||
|
||||
mu_assert_eq(rz_bv_len(vm->pc), 64, "pc len");
|
||||
mu_assert_eq(rz_bv_to_ut64(vm->pc), 0x10001, "pc");
|
||||
|
||||
rz_reg_free(reg);
|
||||
|
||||
// adjustments after profile change
|
||||
const char *profile2 =
|
||||
"=PC pc\n"
|
||||
"gpr r1 .64 8 0\n"
|
||||
"gpr r0 .32 0 0\n"
|
||||
"gpr r3 .64 24 0\n"
|
||||
"gpr pc .64 32 0\n"
|
||||
"gpr af .8 40 0\n"
|
||||
"gpr bf .1 41.0 0\n";
|
||||
reg = rz_reg_new();
|
||||
rz_reg_set_profile_string(reg, profile2);
|
||||
rz_reg_setv(reg, "r0", 0x5678);
|
||||
rz_reg_setv(reg, "r1", 0x0123456789abcdef);
|
||||
rz_reg_setv(reg, "r3", 1);
|
||||
rz_reg_setv(reg, "pc", 0x10001);
|
||||
rz_reg_setv(reg, "af", 42);
|
||||
rz_reg_setv(reg, "bf", 0);
|
||||
|
||||
rz_il_vm_sync_from_reg(vm, reg);
|
||||
val = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, "r0");
|
||||
mu_assert_notnull(val, "val");
|
||||
mu_assert_eq(val->type, RZ_IL_TYPE_PURE_BITVECTOR, "val type");
|
||||
mu_assert_eq(rz_bv_len(val->data.bv), 64, "val len");
|
||||
mu_assert_eq(rz_bv_to_ut64(val->data.bv), 0x5678, "val val");
|
||||
val = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, "r1");
|
||||
mu_assert_notnull(val, "val");
|
||||
mu_assert_eq(val->type, RZ_IL_TYPE_PURE_BITVECTOR, "val type");
|
||||
mu_assert_eq(rz_bv_len(val->data.bv), 32, "val len");
|
||||
mu_assert_eq(rz_bv_to_ut64(val->data.bv), 0x89abcdef, "val val");
|
||||
var = rz_il_vm_get_var(vm, RZ_IL_VAR_KIND_GLOBAL, "r3");
|
||||
mu_assert_null(var, "unbound");
|
||||
val = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, "af");
|
||||
mu_assert_notnull(val, "val");
|
||||
mu_assert_eq(val->type, RZ_IL_TYPE_PURE_BOOL, "val type");
|
||||
mu_assert_true(val->data.b->b, "val val");
|
||||
val = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, "bf");
|
||||
mu_assert_notnull(val, "val");
|
||||
mu_assert_eq(val->type, RZ_IL_TYPE_PURE_BOOL, "val type");
|
||||
mu_assert_false(val->data.b->b, "val val");
|
||||
|
||||
mu_assert_eq(rz_bv_len(vm->pc), 64, "pc len");
|
||||
mu_assert_eq(rz_bv_to_ut64(vm->pc), 0x10001, "pc");
|
||||
|
||||
rz_reg_free(reg);
|
||||
|
||||
// even harder adjustments
|
||||
const char *profile3 =
|
||||
"=PC pc\n"
|
||||
"gpr r1 .1 8 0\n"
|
||||
"gpr r42 .64 24 0\n"
|
||||
"gpr pc .64 32 0\n";
|
||||
reg = rz_reg_new();
|
||||
rz_reg_set_profile_string(reg, profile3);
|
||||
rz_reg_setv(reg, "r1", 1);
|
||||
rz_reg_setv(reg, "r32", 0x0123456789abcdef);
|
||||
rz_reg_setv(reg, "pc", 0x10002);
|
||||
|
||||
rz_il_vm_sync_from_reg(vm, reg);
|
||||
val = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, "r0");
|
||||
mu_assert_notnull(val, "val");
|
||||
mu_assert_eq(val->type, RZ_IL_TYPE_PURE_BITVECTOR, "val type");
|
||||
mu_assert_eq(rz_bv_len(val->data.bv), 64, "val len");
|
||||
mu_assert_eq(rz_bv_to_ut64(val->data.bv), 0, "val val");
|
||||
val = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, "r1");
|
||||
mu_assert_notnull(val, "val");
|
||||
mu_assert_eq(val->type, RZ_IL_TYPE_PURE_BITVECTOR, "val type");
|
||||
mu_assert_eq(rz_bv_len(val->data.bv), 32, "val len");
|
||||
mu_assert_eq(rz_bv_to_ut64(val->data.bv), 1, "val val");
|
||||
var = rz_il_vm_get_var(vm, RZ_IL_VAR_KIND_GLOBAL, "r3");
|
||||
mu_assert_null(var, "unbound");
|
||||
val = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, "af");
|
||||
mu_assert_notnull(val, "val");
|
||||
mu_assert_eq(val->type, RZ_IL_TYPE_PURE_BOOL, "val type");
|
||||
mu_assert_false(val->data.b->b, "val val");
|
||||
val = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, "bf");
|
||||
mu_assert_notnull(val, "val");
|
||||
mu_assert_eq(val->type, RZ_IL_TYPE_PURE_BOOL, "val type");
|
||||
mu_assert_false(val->data.b->b, "val val");
|
||||
|
||||
mu_assert_eq(rz_bv_len(vm->pc), 64, "pc len");
|
||||
mu_assert_eq(rz_bv_to_ut64(vm->pc), 0x10002, "pc");
|
||||
|
||||
rz_reg_free(reg);
|
||||
|
||||
rz_il_vm_free(vm);
|
||||
mu_end;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,63 +12,56 @@ static bool test_rzil_vm_init() {
|
|||
mu_end;
|
||||
}
|
||||
|
||||
static bool test_rzil_vm_basic_operation() {
|
||||
static bool test_rzil_vm_global_vars() {
|
||||
RzILVM *vm = rz_il_vm_new(0, 8, true);
|
||||
|
||||
// 1. create variables
|
||||
RzILVar *var_r1 = rz_il_vm_create_global_variable(vm, "r1", RZ_IL_VAR_TYPE_UNK, true);
|
||||
RzILVar *var_r2 = rz_il_vm_create_global_variable(vm, "r2", RZ_IL_VAR_TYPE_UNK, false);
|
||||
RzILVar *var_r1 = rz_il_vm_create_global_var(vm, "r1", rz_il_sort_pure_bool());
|
||||
RzILVar *var_r2 = rz_il_vm_create_global_var(vm, "r2", rz_il_sort_pure_bv(32));
|
||||
mu_assert_notnull(var_r1, "Create var 1");
|
||||
mu_assert_notnull(var_r2, "Create var 2");
|
||||
|
||||
// check name
|
||||
mu_assert_streq(var_r1->var_name, "r1", "var r1 name");
|
||||
mu_assert_streq(var_r2->var_name, "r2", "var r2 name");
|
||||
mu_assert_streq(var_r1->name, "r1", "var r1 name");
|
||||
mu_assert_streq(var_r2->name, "r2", "var r2 name");
|
||||
|
||||
// check type
|
||||
mu_assert_eq(var_r1->type, RZ_IL_VAR_TYPE_UNK, "var r1 type unk");
|
||||
mu_assert_eq(var_r2->type, RZ_IL_VAR_TYPE_UNK, "var r2 type unk");
|
||||
mu_assert_true(rz_il_sort_pure_eq(var_r1->sort, rz_il_sort_pure_bool()), "var r1 sort");
|
||||
mu_assert_true(rz_il_sort_pure_eq(var_r2->sort, rz_il_sort_pure_bv(32)), "var r2 sort");
|
||||
|
||||
// check mutablity
|
||||
mu_assert_eq(var_r1->is_mutable, true, "var r1 is mutable");
|
||||
mu_assert_eq(var_r2->is_mutable, false, "var r2 is not mutable");
|
||||
|
||||
// 2. find vars from vm
|
||||
RzILVar *find_var_r1 = rz_il_find_var_by_name(vm, "r1");
|
||||
RzILVar *find_var_r2 = rz_il_find_var_by_name(vm, "r2");
|
||||
// find vars from vm
|
||||
RzILVar *find_var_r1 = rz_il_vm_get_var(vm, RZ_IL_VAR_KIND_GLOBAL, "r1");
|
||||
RzILVar *find_var_r2 = rz_il_vm_get_var(vm, RZ_IL_VAR_KIND_GLOBAL, "r2");
|
||||
mu_assert_eq(var_r1, find_var_r1, "Store and find r1");
|
||||
mu_assert_eq(var_r2, find_var_r2, "Store and find r2");
|
||||
|
||||
// 3. create value
|
||||
RzILVal *val_r1 = rz_il_vm_create_value_bitv(vm, rz_bv_new_zero(32));
|
||||
RzILVal *val_r2 = rz_il_vm_create_value_bool(vm, false);
|
||||
mu_assert_notnull(val_r1, "Create val 1");
|
||||
mu_assert_notnull(val_r2, "Create val 2");
|
||||
// initial contents
|
||||
RzILVal *val_r1 = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, "r1");
|
||||
mu_assert_eq(val_r1->type, RZ_IL_TYPE_PURE_BOOL, "val type");
|
||||
mu_assert_false(val_r1->data.b->b, "val content");
|
||||
RzILVal *val_r2 = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, "r2");
|
||||
mu_assert_eq(val_r2->type, RZ_IL_TYPE_PURE_BITVECTOR, "val type");
|
||||
mu_assert_eq(rz_bv_len(val_r2->data.bv), 32, "val bv len");
|
||||
mu_assert_eq(rz_bv_to_ut64(val_r2->data.bv), 0, "val bv content");
|
||||
|
||||
// check type
|
||||
mu_assert_eq(val_r1->type, RZ_IL_VAR_TYPE_BV, "val 1 has type bitv");
|
||||
mu_assert_eq(val_r2->type, RZ_IL_VAR_TYPE_BOOL, "val 2 has type bool");
|
||||
// bind value to var
|
||||
rz_il_vm_set_global_var(vm, "r1", rz_il_value_new_bool(rz_il_bool_new(true)));
|
||||
rz_il_vm_set_global_var(vm, "r2", rz_il_value_new_bitv(rz_bv_new_from_ut64(32, 123)));
|
||||
val_r1 = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, "r1");
|
||||
mu_assert_eq(val_r1->type, RZ_IL_TYPE_PURE_BOOL, "val type");
|
||||
mu_assert_true(val_r1->data.b->b, "val content");
|
||||
val_r2 = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, "r2");
|
||||
mu_assert_eq(val_r2->type, RZ_IL_TYPE_PURE_BITVECTOR, "val type");
|
||||
mu_assert_eq(rz_bv_len(val_r2->data.bv), 32, "val bv len");
|
||||
mu_assert_eq(rz_bv_to_ut64(val_r2->data.bv), 123, "val bv content");
|
||||
|
||||
// 4. bind value to var
|
||||
rz_il_hash_bind(vm, var_r1, val_r1);
|
||||
rz_il_hash_bind(vm, var_r2, val_r2);
|
||||
RzILVal *find_val_r1 = rz_il_hash_find_val_by_name(vm, "r1");
|
||||
RzILVal *find_val_r2 = rz_il_hash_find_val_by_name(vm, "r2");
|
||||
mu_assert_eq(val_r1, find_val_r1, "Bind and find");
|
||||
mu_assert_eq(val_r2, find_val_r2, "Bind and find");
|
||||
rz_il_vm_free(vm);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
// 5. cancel binding
|
||||
rz_il_hash_cancel_binding(vm, var_r1);
|
||||
RzILVal *null_val = rz_il_hash_find_val_by_name(vm, "r1");
|
||||
mu_assert_null(null_val, "Cancel binding");
|
||||
|
||||
// 6. bind to another one
|
||||
rz_il_hash_bind(vm, var_r1, val_r2);
|
||||
RzILVal *cur_var_r1_value = rz_il_hash_find_val_by_name(vm, "r1");
|
||||
RzILVal *cur_var_r2_value = rz_il_hash_find_val_by_name(vm, "r2");
|
||||
mu_assert_eq(cur_var_r1_value, cur_var_r2_value, "Bind to the same value");
|
||||
|
||||
// 7. create label
|
||||
static bool test_rzil_vm_labels() {
|
||||
RzILVM *vm = rz_il_vm_new(0, 8, true);
|
||||
// create label
|
||||
RzBitVector *addr = rz_bv_new_from_ut64(16, 233);
|
||||
RzILEffectLabel *blackhole = rz_il_vm_create_label(vm, "blackhole", addr);
|
||||
|
||||
|
|
@ -87,7 +80,7 @@ static bool test_rzil_vm_basic_operation() {
|
|||
is_equal_bv = rz_bv_cmp(find_addr, addr) == 0 ? true : false;
|
||||
mu_assert("Find address equal", is_equal_bv);
|
||||
|
||||
// 8. create label lazy (without giving an address)
|
||||
// create label lazy (without giving an address)
|
||||
RzILEffectLabel *lazy = rz_il_vm_create_label_lazy(vm, "lazy");
|
||||
RzILEffectLabel *find_lazy = rz_il_vm_find_label_by_name(vm, "lazy");
|
||||
mu_assert_eq(lazy, find_lazy, "Find lazy label");
|
||||
|
|
@ -95,7 +88,7 @@ static bool test_rzil_vm_basic_operation() {
|
|||
RzBitVector *lazy_addr = rz_il_hash_find_addr_by_lblname(vm, "lazy");
|
||||
mu_assert_null(lazy_addr, "Lazy label have NULL address");
|
||||
|
||||
// 9. update the address of lazy label
|
||||
// update the address of lazy label
|
||||
rz_il_vm_update_label(vm, "lazy", addr);
|
||||
lazy_addr = rz_il_hash_find_addr_by_lblname(vm, "lazy");
|
||||
is_equal_bv = rz_bv_cmp(lazy_addr, addr) == 0 ? true : false;
|
||||
|
|
@ -106,36 +99,6 @@ static bool test_rzil_vm_basic_operation() {
|
|||
mu_end;
|
||||
}
|
||||
|
||||
static bool test_rzil_vm_operation() {
|
||||
RzILVM *vm = rz_il_vm_new(0, 8, false);
|
||||
|
||||
// 1. create register r0 and r1
|
||||
rz_il_vm_add_reg(vm, "r0", 8);
|
||||
rz_il_vm_add_reg(vm, "r1", 8);
|
||||
|
||||
RzILVar *reg_r0 = rz_il_find_var_by_name(vm, "r0");
|
||||
RzILVar *reg_r1 = rz_il_find_var_by_name(vm, "r1");
|
||||
mu_assert_streq(reg_r0->var_name, "r0", "register name r0");
|
||||
mu_assert_streq(reg_r1->var_name, "r1", "register name r1");
|
||||
|
||||
RzILVal *val_r0 = rz_il_hash_find_val_by_name(vm, "r0");
|
||||
RzILVal *val_r1 = rz_il_hash_find_val_by_name(vm, "r1");
|
||||
mu_assert_eq(val_r0->type, RZ_IL_VAR_TYPE_BV, "r0 is bitvector");
|
||||
mu_assert_eq(val_r1->type, RZ_IL_VAR_TYPE_BV, "r1 is bitvector");
|
||||
|
||||
RzILVal *r0 = rz_il_hash_find_val_by_name(vm, "r0");
|
||||
RzILVal *r1 = rz_il_hash_find_val_by_name(vm, "r1");
|
||||
|
||||
bool is_zero = rz_bv_is_zero_vector(r0->data.bv);
|
||||
mu_assert("Init r0 as all zero bitvector", is_zero);
|
||||
|
||||
is_zero = rz_bv_is_zero_vector(r1->data.bv);
|
||||
mu_assert("Init r1 as all zero bitvector", is_zero);
|
||||
|
||||
rz_il_vm_free(vm);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
static bool test_rzil_vm_root_evaluation() {
|
||||
RzILVM *vm = rz_il_vm_new(0, 8, false);
|
||||
|
||||
|
|
@ -159,7 +122,7 @@ static bool test_rzil_vm_root_evaluation() {
|
|||
|
||||
// Evaluate the whole ite expression
|
||||
RzILVal *ite_val = rz_il_evaluate_val(vm, ite_root);
|
||||
mu_assert_eq(ite_val->type, RZ_IL_VAR_TYPE_BOOL, "Return a Bool Val");
|
||||
mu_assert_eq(ite_val->type, RZ_IL_TYPE_PURE_BOOL, "Return a Bool Val");
|
||||
mu_assert_eq(ite_val->data.b->b, true, "Return a True");
|
||||
rz_il_value_free(ite_val);
|
||||
|
||||
|
|
@ -168,6 +131,52 @@ static bool test_rzil_vm_root_evaluation() {
|
|||
mu_end;
|
||||
}
|
||||
|
||||
static bool test_rzil_vm_op_let() {
|
||||
RzILVM *vm = rz_il_vm_new(0, 8, false);
|
||||
|
||||
// simple case:
|
||||
// let preanswer = 41 in preanswer + 1
|
||||
RzILOpBitVector *op = rz_il_op_new_let("preanswer",
|
||||
rz_il_op_new_bitv_from_ut64(16, 41),
|
||||
rz_il_op_new_add(rz_il_op_new_var("preanswer", RZ_IL_VAR_KIND_LOCAL_PURE), rz_il_op_new_bitv_from_ut64(16, 1)));
|
||||
RzBitVector *r = rz_il_evaluate_bitv(vm, op);
|
||||
rz_il_op_pure_free(op);
|
||||
mu_assert_notnull(r, "eval");
|
||||
mu_assert_eq(rz_bv_len(r), 16, "eval len");
|
||||
mu_assert_eq(rz_bv_to_ut64(r), 42, "eval val");
|
||||
rz_bv_free(r);
|
||||
RzPVector *vars = rz_il_var_set_get_all(&vm->local_pure_vars);
|
||||
mu_assert_notnull(vars, "vars vector");
|
||||
mu_assert_eq(rz_pvector_len(vars), 0, "cleanup");
|
||||
rz_pvector_free(vars);
|
||||
|
||||
// complex case with shadowing
|
||||
// let y = 0x23 in
|
||||
// let x = 0xaaaa in
|
||||
// y + cast 8 (let y = x + 0x2212 in y - x)
|
||||
op = rz_il_op_new_let("y", rz_il_op_new_bitv_from_ut64(8, 0x23),
|
||||
rz_il_op_new_let("x", rz_il_op_new_bitv_from_ut64(16, 0xaaaa),
|
||||
rz_il_op_new_add(
|
||||
rz_il_op_new_var("y", RZ_IL_VAR_KIND_LOCAL_PURE),
|
||||
rz_il_op_new_cast(8, rz_il_op_new_b0(),
|
||||
rz_il_op_new_let("y",
|
||||
rz_il_op_new_add(rz_il_op_new_var("x", RZ_IL_VAR_KIND_LOCAL_PURE), rz_il_op_new_bitv_from_ut64(16, 0x2212)),
|
||||
rz_il_op_new_sub(rz_il_op_new_var("y", RZ_IL_VAR_KIND_LOCAL_PURE), rz_il_op_new_var("x", RZ_IL_VAR_KIND_LOCAL_PURE)))))));
|
||||
r = rz_il_evaluate_bitv(vm, op);
|
||||
rz_il_op_pure_free(op);
|
||||
mu_assert_notnull(r, "eval");
|
||||
mu_assert_eq(rz_bv_len(r), 8, "eval len");
|
||||
mu_assert_eq(rz_bv_to_ut64(r), 0x35, "eval val");
|
||||
rz_bv_free(r);
|
||||
vars = rz_il_var_set_get_all(&vm->local_pure_vars);
|
||||
mu_assert_notnull(vars, "vars vector");
|
||||
mu_assert_eq(rz_pvector_len(vars), 0, "cleanup");
|
||||
rz_pvector_free(vars);
|
||||
|
||||
rz_il_vm_free(vm);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
static bool test_rzil_vm_op_cast() {
|
||||
RzILVM *vm = rz_il_vm_new(0, 8, false);
|
||||
|
||||
|
|
@ -264,32 +273,41 @@ static bool test_rzil_vm_op_signed() {
|
|||
static bool test_rzil_vm_op_set() {
|
||||
RzILVM *vm = rz_il_vm_new(0, 8, false);
|
||||
|
||||
RzILVar *var_r1 = rz_il_vm_create_global_variable(vm, "r1", RZ_IL_VAR_TYPE_UNK, true);
|
||||
RzILVar *var_r2 = rz_il_vm_create_global_variable(vm, "r2", RZ_IL_VAR_TYPE_UNK, false);
|
||||
rz_il_hash_bind(vm, var_r1, rz_il_vm_create_value_bitv(vm, rz_bv_new_zero(32)));
|
||||
rz_il_hash_bind(vm, var_r2, rz_il_vm_create_value_bitv(vm, rz_bv_new_zero(32)));
|
||||
RzILVar *var_r1 = rz_il_vm_create_global_var(vm, "r1", rz_il_sort_pure_bv(32));
|
||||
rz_il_vm_create_global_var(vm, "r2", rz_il_sort_pure_bv(32));
|
||||
|
||||
// try to set immutable and fail
|
||||
RzILOpEffect *op = rz_il_op_new_set("r2", rz_il_op_new_bitv_from_ut64(24, 42));
|
||||
// set global
|
||||
RzILOpEffect *op = rz_il_op_new_set("r1", false, rz_il_op_new_bitv_from_ut64(32, 42));
|
||||
bool succ = rz_il_evaluate_effect(vm, op);
|
||||
rz_il_op_effect_free(op);
|
||||
RzILVal *val = rz_il_hash_find_val_by_name(vm, var_r2->var_name);
|
||||
RzILVal *val = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, var_r1->name);
|
||||
mu_assert_true(succ, "success");
|
||||
mu_assert_notnull(val, "get val");
|
||||
mu_assert_eq(val->type, RZ_IL_VAR_TYPE_BV, "unchanged bv");
|
||||
mu_assert_eq(rz_bv_len(val->data.bv), 32, "unchanged bv len");
|
||||
mu_assert_eq(rz_bv_to_ut64(val->data.bv), 0, "unchanged bv val");
|
||||
|
||||
// set mutable
|
||||
op = rz_il_op_new_set("r1", rz_il_op_new_bitv_from_ut64(24, 42));
|
||||
succ = rz_il_evaluate_effect(vm, op);
|
||||
rz_il_op_effect_free(op);
|
||||
val = rz_il_hash_find_val_by_name(vm, var_r1->var_name);
|
||||
mu_assert_true(succ, "success");
|
||||
mu_assert_notnull(val, "get val");
|
||||
mu_assert_eq(val->type, RZ_IL_VAR_TYPE_BV, "set bv");
|
||||
mu_assert_eq(rz_bv_len(val->data.bv), 24, "set bv len");
|
||||
mu_assert_eq(val->type, RZ_IL_TYPE_PURE_BITVECTOR, "set bv");
|
||||
mu_assert_eq(rz_bv_len(val->data.bv), 32, "set bv len");
|
||||
mu_assert_eq(rz_bv_to_ut64(val->data.bv), 42, "set bv val");
|
||||
RzPVector *vars = rz_il_var_set_get_all(&vm->local_vars);
|
||||
mu_assert_notnull(vars, "vars vector");
|
||||
mu_assert_eq(rz_pvector_len(vars), 0, "cleanup");
|
||||
rz_pvector_free(vars);
|
||||
|
||||
// set local temporarily
|
||||
op = rz_il_op_new_seq(
|
||||
rz_il_op_new_set("r1", true, rz_il_op_new_bitv_from_ut64(32, 2)),
|
||||
rz_il_op_new_set("r1", false,
|
||||
rz_il_op_new_div(rz_il_op_new_var("r1", RZ_IL_VAR_KIND_GLOBAL), rz_il_op_new_var("r1", RZ_IL_VAR_KIND_LOCAL))));
|
||||
succ = rz_il_vm_step(vm, op, 1);
|
||||
rz_il_op_effect_free(op);
|
||||
val = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, var_r1->name);
|
||||
mu_assert_true(succ, "success");
|
||||
mu_assert_notnull(val, "get val");
|
||||
mu_assert_eq(val->type, RZ_IL_TYPE_PURE_BITVECTOR, "set bv");
|
||||
mu_assert_eq(rz_bv_len(val->data.bv), 32, "set bv len");
|
||||
mu_assert_eq(rz_bv_to_ut64(val->data.bv), 21, "set bv val");
|
||||
vars = rz_il_var_set_get_all(&vm->local_vars);
|
||||
mu_assert_notnull(vars, "vars vector");
|
||||
mu_assert_eq(rz_pvector_len(vars), 0, "cleanup");
|
||||
rz_pvector_free(vars);
|
||||
|
||||
rz_il_vm_free(vm);
|
||||
mu_end;
|
||||
|
|
@ -328,9 +346,9 @@ static bool test_rzil_vm_op_goto_addr() {
|
|||
static bool test_rzil_vm_op_blk() {
|
||||
RzILVM *vm = rz_il_vm_new(0, 8, false);
|
||||
|
||||
RzILVar *var = rz_il_vm_create_global_variable(vm, "leetbap", RZ_IL_VAR_TYPE_UNK, true);
|
||||
rz_il_hash_bind(vm, var, rz_il_vm_create_value_bitv(vm, rz_bv_new_from_ut64(8, 0x42)));
|
||||
RzILOpEffect *data_eff = rz_il_op_new_set("leetbap", rz_il_op_new_bitv_from_ut64(8, 0x13));
|
||||
RzILVar *var = rz_il_vm_create_global_var(vm, "leetbap", rz_il_sort_pure_bv(8));
|
||||
rz_il_vm_set_global_var(vm, var->name, rz_il_value_new_bitv(rz_bv_new_from_ut64(8, 0x42)));
|
||||
RzILOpEffect *data_eff = rz_il_op_new_set("leetbap", false, rz_il_op_new_bitv_from_ut64(8, 0x13));
|
||||
|
||||
RzBitVector *dst = rz_bv_new_from_ut64(8, 0x07);
|
||||
rz_il_vm_create_label(vm, "beach", dst);
|
||||
|
|
@ -342,9 +360,9 @@ static bool test_rzil_vm_op_blk() {
|
|||
rz_il_op_effect_free(op);
|
||||
|
||||
mu_assert_true(succ, "op failed");
|
||||
RzILVal *val = rz_il_hash_find_val_by_name(vm, var->var_name);
|
||||
RzILVal *val = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, var->name);
|
||||
mu_assert_notnull(val, "val null");
|
||||
mu_assert_eq(val->type, RZ_IL_VAR_TYPE_BV, "type not bv");
|
||||
mu_assert_eq(val->type, RZ_IL_TYPE_PURE_BITVECTOR, "type not bv");
|
||||
mu_assert_eq(rz_bv_len(val->data.bv), 8, "len not correct");
|
||||
mu_assert_eq(rz_bv_to_ut64(val->data.bv), 0x13, "bitv not correct");
|
||||
mu_assert_eq(rz_bv_to_ut64(vm->pc), 0x07, "wrong pc");
|
||||
|
|
@ -372,16 +390,16 @@ static bool test_rzil_vm_op_blk() {
|
|||
static bool test_rzil_vm_op_repeat() {
|
||||
RzILVM *vm = rz_il_vm_new(0, 8, false);
|
||||
|
||||
RzILVar *var = rz_il_vm_create_global_variable(vm, "leetbap", RZ_IL_VAR_TYPE_UNK, true);
|
||||
rz_il_hash_bind(vm, var, rz_il_vm_create_value_bitv(vm, rz_bv_new_from_ut64(16, 42)));
|
||||
RzILVar *count = rz_il_vm_create_global_variable(vm, "i", RZ_IL_VAR_TYPE_UNK, true);
|
||||
rz_il_hash_bind(vm, count, rz_il_vm_create_value_bitv(vm, rz_bv_new_from_ut64(8, 7)));
|
||||
RzILVar *var = rz_il_vm_create_global_var(vm, "leetbap", rz_il_sort_pure_bv(16));
|
||||
rz_il_vm_set_global_var(vm, var->name, rz_il_value_new_bitv(rz_bv_new_from_ut64(16, 42)));
|
||||
RzILVar *count = rz_il_vm_create_global_var(vm, "i", rz_il_sort_pure_bv(8));
|
||||
rz_il_vm_set_global_var(vm, count->name, rz_il_value_new_bitv(rz_bv_new_from_ut64(8, 7)));
|
||||
|
||||
RzILOpBitVector *sub = rz_il_op_new_sub(rz_il_op_new_var("i"), rz_il_op_new_bitv_from_ut64(8, 1));
|
||||
RzILOpBitVector *mul = rz_il_op_new_mul(rz_il_op_new_var("leetbap"), rz_il_op_new_bitv_from_ut64(16, 3));
|
||||
RzILOpBitVector *sub = rz_il_op_new_sub(rz_il_op_new_var("i", RZ_IL_VAR_KIND_GLOBAL), rz_il_op_new_bitv_from_ut64(8, 1));
|
||||
RzILOpBitVector *mul = rz_il_op_new_mul(rz_il_op_new_var("leetbap", RZ_IL_VAR_KIND_GLOBAL), rz_il_op_new_bitv_from_ut64(16, 3));
|
||||
|
||||
RzILOpEffect *mul_eff = rz_il_op_new_set("leetbap", rz_il_op_pure_dup(mul));
|
||||
RzILOpEffect *sub_eff = rz_il_op_new_set("i", rz_il_op_pure_dup(sub));
|
||||
RzILOpEffect *mul_eff = rz_il_op_new_set("leetbap", false, mul);
|
||||
RzILOpEffect *sub_eff = rz_il_op_new_set("i", false, rz_il_op_pure_dup(sub));
|
||||
RzILOpEffect *data_seq = rz_il_op_new_seq(mul_eff, sub_eff);
|
||||
RzILOpBool *c = rz_il_op_new_non_zero(sub);
|
||||
|
||||
|
|
@ -390,14 +408,14 @@ static bool test_rzil_vm_op_repeat() {
|
|||
rz_il_op_effect_free(op);
|
||||
|
||||
mu_assert_true(succ, "op failed");
|
||||
RzILVal *val = rz_il_hash_find_val_by_name(vm, var->var_name);
|
||||
RzILVal *val = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, var->name);
|
||||
mu_assert_notnull(val, "leetbap null");
|
||||
mu_assert_eq(val->type, RZ_IL_VAR_TYPE_BV, "leetbap type not bv");
|
||||
mu_assert_eq(val->type, RZ_IL_TYPE_PURE_BITVECTOR, "leetbap type not bv");
|
||||
mu_assert_eq(rz_bv_len(val->data.bv), 16, "leetbap len not correct");
|
||||
mu_assert_eq(rz_bv_to_ut64(val->data.bv), 30618, "leetbap bitv not correct");
|
||||
RzILVal *val2 = rz_il_hash_find_val_by_name(vm, count->var_name);
|
||||
RzILVal *val2 = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, count->name);
|
||||
mu_assert_notnull(val2, "i null");
|
||||
mu_assert_eq(val2->type, RZ_IL_VAR_TYPE_BV, "i type not bv");
|
||||
mu_assert_eq(val2->type, RZ_IL_TYPE_PURE_BITVECTOR, "i type not bv");
|
||||
mu_assert_eq(rz_bv_len(val2->data.bv), 8, "i len not correct");
|
||||
mu_assert_eq(rz_bv_to_ut64(val2->data.bv), 1, "i bitv not correct");
|
||||
|
||||
|
|
@ -406,15 +424,13 @@ static bool test_rzil_vm_op_repeat() {
|
|||
}
|
||||
|
||||
static void hook_test(RzILVM *vm, RzILOpEffect *op) {
|
||||
RzILVar *var = rz_il_find_var_by_name(vm, "myvar");
|
||||
rz_il_hash_bind(vm, var, rz_il_vm_create_value_bitv(vm, rz_bv_new_from_ut64(32, 0xc0ffee)));
|
||||
rz_il_vm_set_global_var(vm, "myvar", rz_il_value_new_bitv(rz_bv_new_from_ut64(32, 0xc0ffee)));
|
||||
}
|
||||
|
||||
static bool test_rzil_vm_op_goto_hook() {
|
||||
RzILVM *vm = rz_il_vm_new(0, 8, false);
|
||||
|
||||
RzILVar *var = rz_il_vm_create_global_variable(vm, "myvar", RZ_IL_VAR_TYPE_UNK, true);
|
||||
rz_il_hash_bind(vm, var, rz_il_vm_create_value_bitv(vm, rz_bv_new_zero(32)));
|
||||
rz_il_vm_create_global_var(vm, "myvar", rz_il_sort_pure_bv(32));
|
||||
|
||||
RzBitVector *dst = rz_bv_new_from_ut64(8, 0x42);
|
||||
RzILEffectLabel *label = rz_il_vm_create_label_lazy(vm, "beach");
|
||||
|
|
@ -428,8 +444,8 @@ static bool test_rzil_vm_op_goto_hook() {
|
|||
mu_assert_true(succ, "success");
|
||||
|
||||
// check the effect we implemented in hook_test
|
||||
RzILVal *val = rz_il_hash_find_val_by_name(vm, "myvar");
|
||||
mu_assert_eq(val->type, RZ_IL_VAR_TYPE_BV, "val type");
|
||||
RzILVal *val = rz_il_vm_get_var_value(vm, RZ_IL_VAR_KIND_GLOBAL, "myvar");
|
||||
mu_assert_eq(val->type, RZ_IL_TYPE_PURE_BITVECTOR, "val type");
|
||||
mu_assert_eq(rz_bv_to_ut64(val->data.bv), 0xc0ffee, "val contents");
|
||||
|
||||
rz_il_vm_free(vm);
|
||||
|
|
@ -450,6 +466,7 @@ static bool test_rzil_vm_op_load() {
|
|||
mu_assert_notnull(res, "eval res");
|
||||
mu_assert_eq(rz_bv_len(res), 8, "res byte size");
|
||||
mu_assert_eq(rz_bv_to_ut64(res), 0x42, "res value");
|
||||
rz_bv_free(res);
|
||||
|
||||
op = rz_il_op_new_load(0, rz_il_op_new_bitv_from_ut64(16, 100));
|
||||
res = rz_il_evaluate_bitv(vm, op);
|
||||
|
|
@ -457,6 +474,7 @@ static bool test_rzil_vm_op_load() {
|
|||
mu_assert_notnull(res, "eval res");
|
||||
mu_assert_eq(rz_bv_len(res), 8, "res byte size");
|
||||
mu_assert_eq(rz_bv_to_ut64(res), 0xaa, "res value (overflow)");
|
||||
rz_bv_free(res);
|
||||
|
||||
rz_il_vm_free(vm);
|
||||
mu_end;
|
||||
|
|
@ -494,6 +512,7 @@ static bool test_rzil_vm_op_loadw_le() {
|
|||
mu_assert_notnull(res, "eval res");
|
||||
mu_assert_eq(rz_bv_len(res), 16, "res byte size");
|
||||
mu_assert_eq(rz_bv_to_ut64(res), 0x442, "res value");
|
||||
rz_bv_free(res);
|
||||
|
||||
rz_il_vm_free(vm);
|
||||
mu_end;
|
||||
|
|
@ -531,6 +550,7 @@ static bool test_rzil_vm_op_loadw_be() {
|
|||
mu_assert_notnull(res, "eval res");
|
||||
mu_assert_eq(rz_bv_len(res), 16, "res byte size");
|
||||
mu_assert_eq(rz_bv_to_ut64(res), 0x4204, "res value");
|
||||
rz_bv_free(res);
|
||||
|
||||
rz_il_vm_free(vm);
|
||||
mu_end;
|
||||
|
|
@ -571,9 +591,10 @@ static bool test_rzil_vm_op_append() {
|
|||
|
||||
bool all_tests() {
|
||||
mu_run_test(test_rzil_vm_init);
|
||||
mu_run_test(test_rzil_vm_basic_operation);
|
||||
mu_run_test(test_rzil_vm_operation);
|
||||
mu_run_test(test_rzil_vm_global_vars);
|
||||
mu_run_test(test_rzil_vm_labels);
|
||||
mu_run_test(test_rzil_vm_root_evaluation);
|
||||
mu_run_test(test_rzil_vm_op_let);
|
||||
mu_run_test(test_rzil_vm_op_cast);
|
||||
mu_run_test(test_rzil_vm_op_unsigned);
|
||||
mu_run_test(test_rzil_vm_op_signed);
|
||||
|
|
|
|||
Loading…
Reference in a new issue