[RzIL] Fix concept of Effects and Effect ops (#2109)
This brings our concept of effects in line with BAP and fixes issues like values being evaluated prematurely in seq. The main point is that ops themselves are the effects, rather than returning them to be evaluated later.
This commit is contained in:
parent
c65509c1cd
commit
544905631c
19 changed files with 239 additions and 534 deletions
|
|
@ -89,15 +89,13 @@ ut64 parse_label_id(char *lbl_name) {
|
|||
RzPVector *bf_right_arrow(RzILVM *vm, ut64 id) {
|
||||
// (set ptr (+ (val ptr) (int 1)))
|
||||
RzILOp *add = rz_il_op_new_add(bf_il_ptr(), bf_il_one(BF_ADDR_SIZE));
|
||||
RzILOp *perform = rz_il_op_new_perform(bf_il_set_ptr(add));
|
||||
return rz_il_make_oplist(1, perform);
|
||||
return rz_il_make_oplist(1, bf_il_set_ptr(add));
|
||||
}
|
||||
|
||||
RzPVector *bf_left_arrow(RzILVM *vm, ut64 id) {
|
||||
// (set ptr (- (val ptr) (int 1)))
|
||||
RzILOp *sub = rz_il_op_new_sub(bf_il_ptr(), bf_il_one(BF_ADDR_SIZE));
|
||||
RzILOp *perform = rz_il_op_new_perform(bf_il_set_ptr(sub));
|
||||
return rz_il_make_oplist(1, perform);
|
||||
return rz_il_make_oplist(1, bf_il_set_ptr(sub));
|
||||
}
|
||||
|
||||
RzPVector *bf_inc(RzILVM *vm, ut64 id) {
|
||||
|
|
@ -121,15 +119,13 @@ RzPVector *bf_dec(RzILVM *vm, ut64 id) {
|
|||
RzPVector *bf_out(RzILVM *vm, ut64 id) {
|
||||
// (goto write)
|
||||
RzILOp *goto_ = rz_il_op_new_goto("write");
|
||||
RzILOp *perform = rz_il_op_new_perform(goto_);
|
||||
return rz_il_make_oplist(1, perform);
|
||||
return rz_il_make_oplist(1, goto_);
|
||||
}
|
||||
|
||||
RzPVector *bf_in(RzILVM *vm, ut64 id) {
|
||||
// (goto hook_read)
|
||||
RzILOp *goto_ = rz_il_op_new_goto("read");
|
||||
RzILOp *perform = rz_il_op_new_perform(goto_);
|
||||
return rz_il_make_oplist(1, perform);
|
||||
return rz_il_make_oplist(1, goto_);
|
||||
}
|
||||
|
||||
RzPVector *bf_llimit(RzILVM *vm, BfContext *ctx, ut64 id, ut64 addr) {
|
||||
|
|
@ -175,8 +171,7 @@ RzPVector *bf_llimit(RzILVM *vm, BfContext *ctx, ut64 id, ut64 addr) {
|
|||
RzILOp *branch = rz_il_op_new_branch(load, NULL, goto_);
|
||||
|
||||
// perform
|
||||
RzILOp *perform = rz_il_op_new_perform(branch);
|
||||
return rz_il_make_oplist(1, perform);
|
||||
return rz_il_make_oplist(1, branch);
|
||||
}
|
||||
|
||||
RzPVector *bf_rlimit(RzILVM *vm, BfContext *ctx, ut64 id, ut64 addr) {
|
||||
|
|
@ -215,11 +210,8 @@ RzPVector *bf_rlimit(RzILVM *vm, BfContext *ctx, ut64 id, ut64 addr) {
|
|||
// branch if (load mem (var ptr)) is true then goto ]
|
||||
RzILOp *branch = rz_il_op_new_branch(load, goto_, NULL);
|
||||
|
||||
// perform
|
||||
RzILOp *perform = rz_il_op_new_perform(branch);
|
||||
|
||||
free(to_free);
|
||||
return rz_il_make_oplist(1, perform);
|
||||
return rz_il_make_oplist(1, branch);
|
||||
}
|
||||
|
||||
static bool bf_specific_init(RzAnalysisRzil *rzil) {
|
||||
|
|
|
|||
|
|
@ -1,210 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2021 heersin <teablearcher@gmail.com>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <rz_il/definitions/effect.h>
|
||||
|
||||
/**
|
||||
* Create a data effect
|
||||
* \return Data effect instance
|
||||
*/
|
||||
RZ_API RzILDataEffect *rz_il_effect_data_new(void) {
|
||||
RzILDataEffect *ret;
|
||||
ret = RZ_NEW0(RzILDataEffect);
|
||||
if (!ret) {
|
||||
return NULL;
|
||||
}
|
||||
ret->operation = 0;
|
||||
ret->var_name = NULL;
|
||||
ret->val = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a control effect
|
||||
* \return Control effect
|
||||
*/
|
||||
RZ_API RzILCtrlEffect *rz_il_effect_ctrl_new(void) {
|
||||
RzILCtrlEffect *ret;
|
||||
ret = RZ_NEW0(RzILCtrlEffect);
|
||||
if (!ret) {
|
||||
return NULL;
|
||||
}
|
||||
ret->pc = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack a control effect to a general effect
|
||||
* \param eff control effect
|
||||
* \return general effect
|
||||
*/
|
||||
RZ_API RzILEffect *rz_il_wrap_ctrl_effect(RzILCtrlEffect *eff) {
|
||||
RzILEffect *ret;
|
||||
ret = RZ_NEW0(RzILEffect);
|
||||
if (!ret) {
|
||||
return NULL;
|
||||
}
|
||||
ret->effect_type = EFFECT_TYPE_CTRL;
|
||||
ret->ctrl_eff = eff;
|
||||
ret->notation = 0;
|
||||
ret->next_eff = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack a data effect to a general effect
|
||||
* \param eff data effect
|
||||
* \return general effect
|
||||
*/
|
||||
RZ_API RzILEffect *rz_il_wrap_data_effect(RzILDataEffect *eff) {
|
||||
RzILEffect *ret;
|
||||
ret = RZ_NEW0(RzILEffect);
|
||||
if (!ret) {
|
||||
return NULL;
|
||||
}
|
||||
ret->effect_type = EFFECT_TYPE_DATA;
|
||||
ret->data_eff = eff;
|
||||
ret->notation = 0;
|
||||
ret->next_eff = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free a control effect
|
||||
* \param eff control effect to be free
|
||||
*/
|
||||
RZ_API void rz_il_effect_ctrl_free(RzILCtrlEffect *eff) {
|
||||
if (!eff) {
|
||||
return;
|
||||
}
|
||||
free(eff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free a data effect
|
||||
* \param eff data effect to be free
|
||||
*/
|
||||
RZ_API void rz_il_effect_data_free(RzILDataEffect *eff) {
|
||||
if (!eff) {
|
||||
return;
|
||||
}
|
||||
free(eff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a general effect with effect type
|
||||
* \param type effect type, can be CONTROL or DATA, see EFFECT_TYPE_* enums
|
||||
* \return General effect
|
||||
*/
|
||||
RZ_API RzILEffect *rz_il_effect_new(RzEffectType type) {
|
||||
RzILEffect *ret;
|
||||
|
||||
// can only be data or ctrl
|
||||
switch (type) {
|
||||
case EFFECT_TYPE_CTRL:
|
||||
ret = rz_il_wrap_ctrl_effect(rz_il_effect_ctrl_new());
|
||||
break;
|
||||
case EFFECT_TYPE_DATA:
|
||||
ret = rz_il_wrap_data_effect(rz_il_effect_data_new());
|
||||
break;
|
||||
case EFFECT_TYPE_NON:
|
||||
ret = RZ_NEW0(RzILEffect);
|
||||
ret->effect_type = EFFECT_TYPE_NON;
|
||||
ret->notation = EFFECT_NOTATION_NON;
|
||||
ret->data_eff = NULL;
|
||||
ret->ctrl_eff = NULL;
|
||||
ret->next_eff = NULL;
|
||||
break;
|
||||
default:
|
||||
// not handled in init
|
||||
RZ_LOG_ERROR("error: Unknown type");
|
||||
ret = NULL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free a general effect
|
||||
* \param effect a general effect to be free
|
||||
*/
|
||||
RZ_API void rz_il_effect_free(RzILEffect *effect) {
|
||||
if (!effect) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (effect->effect_type) {
|
||||
case EFFECT_TYPE_CTRL:
|
||||
rz_il_effect_ctrl_free(effect->ctrl_eff);
|
||||
effect->ctrl_eff = NULL;
|
||||
break;
|
||||
case EFFECT_TYPE_DATA:
|
||||
rz_il_effect_data_free(effect->data_eff);
|
||||
effect->data_eff = NULL;
|
||||
break;
|
||||
case EFFECT_TYPE_NON:
|
||||
break;
|
||||
default:
|
||||
// not handled
|
||||
RZ_LOG_ERROR("error: Unknown type");
|
||||
break;
|
||||
}
|
||||
free(effect);
|
||||
}
|
||||
|
||||
static char *ctrl_effect_as_string(RzILCtrlEffect *eff) {
|
||||
if (!eff) {
|
||||
return NULL;
|
||||
}
|
||||
return rz_str_newf("[Ctrl Eff] pc -> %" PFMT64u "\n", rz_bv_to_ut64(eff->pc));
|
||||
}
|
||||
|
||||
static char *data_effect_as_string(RzILDataEffect *eff) {
|
||||
if (!eff) {
|
||||
return NULL;
|
||||
}
|
||||
return rz_str_newf("[Data Eff] varname A: %s\n", eff->var_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make effect info as a string for print
|
||||
* \param effect RzILEffect
|
||||
* \return char *, effect info string
|
||||
*/
|
||||
RZ_API RZ_OWN char *rz_il_effect_as_string(RzILEffect *effect) {
|
||||
if (!effect) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (effect->effect_type) {
|
||||
case EFFECT_TYPE_CTRL:
|
||||
return ctrl_effect_as_string(effect->ctrl_eff);
|
||||
break;
|
||||
case EFFECT_TYPE_DATA:
|
||||
return data_effect_as_string(effect->data_eff);
|
||||
break;
|
||||
case EFFECT_TYPE_NON:
|
||||
return rz_str_new("[Non Effect]\n");
|
||||
break;
|
||||
default:
|
||||
// not handled
|
||||
RZ_LOG_ERROR("RzIL: effect: Unknown type when print");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an effect label
|
||||
* \param name label name
|
||||
* \param type Label type
|
||||
* \return Pointer to label
|
||||
*/
|
||||
RZ_API RzILEffectLabel *rz_il_effect_label_new(RZ_NONNULL const char *name, RzILEffectLabelType type) {
|
||||
RzILEffectLabel *lbl = RZ_NEW0(RzILEffectLabel);
|
||||
if (!lbl) {
|
||||
return NULL;
|
||||
}
|
||||
lbl->label_id = strdup(name);
|
||||
lbl->type = type;
|
||||
return lbl;
|
||||
}
|
||||
20
librz/il/definitions/label.c
Normal file
20
librz/il/definitions/label.c
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// SPDX-FileCopyrightText: 2021 heersin <teablearcher@gmail.com>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <rz_il/definitions/label.h>
|
||||
|
||||
/**
|
||||
* Create an effect label
|
||||
* \param name label name
|
||||
* \param type Label type
|
||||
* \return Pointer to label
|
||||
*/
|
||||
RZ_API RzILEffectLabel *rz_il_effect_label_new(RZ_NONNULL const char *name, RzILEffectLabelType type) {
|
||||
RzILEffectLabel *lbl = RZ_NEW0(RzILEffectLabel);
|
||||
if (!lbl) {
|
||||
return NULL;
|
||||
}
|
||||
lbl->label_id = strdup(name);
|
||||
lbl->type = type;
|
||||
return lbl;
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
rz_il_sources = [
|
||||
'definitions/effect.c',
|
||||
'definitions/label.c',
|
||||
'definitions/variable.c',
|
||||
'definitions/value.c',
|
||||
'definitions/bool.c',
|
||||
|
|
|
|||
|
|
@ -82,6 +82,17 @@ static void il_op_resolve(RzILOp *op, RzStrBuf *sb, PJ *pj);
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
#define il_op_param_0(name) \
|
||||
do { \
|
||||
if (sb) { \
|
||||
rz_strbuf_append(sb, name "()"); \
|
||||
} else { \
|
||||
pj_o(pj); \
|
||||
pj_ks(pj, "opcode", name); \
|
||||
pj_end(pj); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define il_op_param_1(name, opx, v0) \
|
||||
do { \
|
||||
if (sb) { \
|
||||
|
|
@ -352,8 +363,8 @@ static void il_opdmp_store(RzILOp *op, RzStrBuf *sb, PJ *pj) {
|
|||
}
|
||||
}
|
||||
|
||||
static void il_opdmp_perform(RzILOp *op, RzStrBuf *sb, PJ *pj) {
|
||||
il_op_param_1("perform", op->op.perform, eff);
|
||||
static void il_opdmp_nop(RzILOp *op, RzStrBuf *sb, PJ *pj) {
|
||||
il_op_param_0("nop");
|
||||
}
|
||||
|
||||
static void il_opdmp_set(RzILOp *op, RzStrBuf *sb, PJ *pj) {
|
||||
|
|
@ -541,8 +552,8 @@ static void il_op_resolve(RzILOp *op, RzStrBuf *sb, PJ *pj) {
|
|||
case RZIL_OP_STORE:
|
||||
il_opdmp_store(op, sb, pj);
|
||||
return;
|
||||
case RZIL_OP_PERFORM:
|
||||
il_opdmp_perform(op, sb, pj);
|
||||
case RZIL_OP_NOP:
|
||||
il_opdmp_nop(op, sb, pj);
|
||||
return;
|
||||
case RZIL_OP_SET:
|
||||
il_opdmp_set(op, sb, pj);
|
||||
|
|
|
|||
|
|
@ -465,15 +465,10 @@ RZ_API RZ_OWN RzILOp *rz_il_op_new_append(RZ_NONNULL RzILOp *x, RZ_NONNULL RzILO
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief op structure for `perform` ('a Effect.sort -> 'a eff)
|
||||
*
|
||||
* perform s performs a generic effect of sort s.
|
||||
*/
|
||||
RZ_API RZ_OWN RzILOp *rz_il_op_new_perform(RZ_NONNULL RzILOp *eff) {
|
||||
RZ_API RZ_OWN RzILOp *rz_il_op_new_nop(RZ_NONNULL RzILOp *eff) {
|
||||
rz_return_val_if_fail(eff, NULL);
|
||||
RzILOp *ret;
|
||||
rz_il_op_new_1(RZIL_OP_PERFORM, RzILOpPerform, perform, eff);
|
||||
rz_il_op_new_0(RZIL_OP_NOP);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -728,8 +723,8 @@ RZ_API void rz_il_op_free(RZ_NULLABLE RzILOp *op) {
|
|||
case RZIL_OP_STORE:
|
||||
rz_il_op_free_2(store, key, value);
|
||||
break;
|
||||
case RZIL_OP_PERFORM:
|
||||
rz_il_op_free_1(perform, eff);
|
||||
case RZIL_OP_NOP:
|
||||
// nothing to free
|
||||
break;
|
||||
case RZIL_OP_SET:
|
||||
rz_il_op_free_1(set, x);
|
||||
|
|
|
|||
|
|
@ -576,8 +576,8 @@ RZ_API RZ_OWN RzILVal *rz_il_evaluate_val(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzIL
|
|||
* \param type, RzILOpArgType*, a pointer to store type info for error-checking
|
||||
* \return effect, RzILEffect*, expression value
|
||||
*/
|
||||
RZ_API RZ_OWN RzILEffect *rz_il_evaluate_effect(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILOp *op, RZ_NONNULL RzILOpArgType *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
RZ_API RZ_OWN void rz_il_evaluate_effect(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILOp *op, RZ_NONNULL RzILOpArgType *type) {
|
||||
rz_return_if_fail(vm && op && type);
|
||||
void *result = rz_il_parse_op_root(vm, op, type);
|
||||
RzILOpArgType t = *type;
|
||||
|
||||
|
|
@ -585,8 +585,6 @@ RZ_API RZ_OWN RzILEffect *rz_il_evaluate_effect(RZ_NONNULL RzILVM *vm, RZ_NONNUL
|
|||
// else, convert to bitv if possible
|
||||
// else report error
|
||||
switch (t) {
|
||||
case RZIL_OP_ARG_EFF:
|
||||
return result;
|
||||
case RZIL_OP_ARG_BITV:
|
||||
rz_bv_free(result);
|
||||
break;
|
||||
|
|
@ -603,8 +601,6 @@ RZ_API RZ_OWN RzILEffect *rz_il_evaluate_effect(RZ_NONNULL RzILVM *vm, RZ_NONNUL
|
|||
RZ_LOG_ERROR("RzIL: unknown RzILEffect type\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ static RzILEvent *il_event_new_write_from_var(RzILVM *vm, RzILVar *var, RzILVal
|
|||
}
|
||||
|
||||
evt = rz_il_event_var_write_new(var->var_name, oldnum, newnum);
|
||||
if (old_val->type == RZIL_VAR_TYPE_BOOL) {
|
||||
if (old_val && old_val->type == RZIL_VAR_TYPE_BOOL) {
|
||||
rz_bv_free(oldnum);
|
||||
}
|
||||
if (new_val->type == RZIL_VAR_TYPE_BOOL) {
|
||||
|
|
@ -37,19 +37,9 @@ static RzILEvent *il_event_new_write_from_var(RzILVM *vm, RzILVar *var, RzILVal
|
|||
return evt;
|
||||
}
|
||||
|
||||
static void rz_il_perform_data(RzILVM *vm, RzILEffect *eff) {
|
||||
static void rz_il_set(RzILVM *vm, const char *var_name, bool is_local, bool is_mutable, RZ_OWN RzILVal *val) {
|
||||
RzILVar *var = NULL;
|
||||
RzILVal *val = NULL;
|
||||
RzILEvent *evt = NULL;
|
||||
const char *var_name = NULL;
|
||||
bool is_local = false, is_mutable = false;
|
||||
|
||||
val = eff->data_eff->val;
|
||||
eff->data_eff->val = NULL;
|
||||
var_name = eff->data_eff->var_name;
|
||||
is_local = eff->data_eff->is_local;
|
||||
is_mutable = eff->data_eff->is_mutable;
|
||||
|
||||
if (is_local) {
|
||||
var = rz_il_find_local_var_by_name(vm, var_name);
|
||||
} else {
|
||||
|
|
@ -107,131 +97,63 @@ static void rz_il_perform_data(RzILVM *vm, RzILEffect *eff) {
|
|||
}
|
||||
}
|
||||
|
||||
static void rz_il_perform_ctrl(RzILVM *vm, RzILEffect *eff) {
|
||||
if (eff->notation & (EFFECT_NOTATION_GOTO_HOOK | EFFECT_NOTATION_GOTO_SYS)) {
|
||||
RzILOp *goto_op = (RzILOp *)eff->ctrl_eff;
|
||||
eff->ctrl_eff = NULL;
|
||||
|
||||
RzILEffectLabel *label = rz_il_vm_find_label_by_name(vm, goto_op->op.goto_->lbl);
|
||||
RzILVmHook internal_hook = (RzILVmHook)label->hook;
|
||||
|
||||
internal_hook(vm, goto_op);
|
||||
return;
|
||||
}
|
||||
|
||||
// Normal
|
||||
RzBitVector *new_addr = eff->ctrl_eff->pc;
|
||||
rz_il_vm_event_add(vm, rz_il_event_pc_write_new(vm->pc, new_addr));
|
||||
rz_bv_free(vm->pc);
|
||||
vm->pc = new_addr;
|
||||
}
|
||||
|
||||
void *rz_il_handler_perform(RzILVM *vm, RzILOp *op, RzILOpArgType *type) {
|
||||
void *rz_il_handler_nop(RzILVM *vm, RzILOp *op, RzILOpArgType *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpPerform *perform_op = op->op.perform;
|
||||
|
||||
RzILEffect *eff = rz_il_evaluate_effect(vm, perform_op->eff, type);
|
||||
do {
|
||||
if (eff->effect_type == EFFECT_TYPE_DATA) {
|
||||
rz_il_perform_data(vm, eff);
|
||||
} else if (eff->effect_type == EFFECT_TYPE_CTRL) {
|
||||
rz_il_perform_ctrl(vm, eff);
|
||||
}
|
||||
RzILEffect *tmp = eff->next_eff;
|
||||
rz_il_effect_free(eff);
|
||||
eff = tmp;
|
||||
} while (eff != NULL);
|
||||
|
||||
*type = RZIL_OP_ARG_EFF;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *rz_il_handler_set(RzILVM *vm, RzILOp *op, RzILOpArgType *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpSet *set_op = op->op.set;
|
||||
|
||||
RzILEffect *eff = rz_il_effect_new(EFFECT_TYPE_DATA);
|
||||
eff->data_eff->var_name = set_op->v;
|
||||
eff->data_eff->is_local = false;
|
||||
eff->data_eff->is_mutable = true;
|
||||
eff->data_eff->val = rz_il_evaluate_val(vm, set_op->x, type);
|
||||
|
||||
// store effect in the temporay list
|
||||
rz_il_set(vm, set_op->v, false, true, rz_il_evaluate_val(vm, set_op->x, type));
|
||||
*type = RZIL_OP_ARG_EFF;
|
||||
return eff;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *rz_il_handler_let(RzILVM *vm, RzILOp *op, RzILOpArgType *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpLet *let_op = op->op.let;
|
||||
|
||||
RzILEffect *eff = rz_il_effect_new(EFFECT_TYPE_DATA);
|
||||
eff->data_eff->var_name = let_op->v;
|
||||
eff->data_eff->is_local = true;
|
||||
eff->data_eff->is_mutable = let_op->mut;
|
||||
eff->data_eff->val = rz_il_evaluate_val(vm, let_op->x, type);
|
||||
|
||||
// store effect in the temporay list
|
||||
rz_il_set(vm, let_op->v, true, let_op->mut, rz_il_evaluate_val(vm, let_op->x, type));
|
||||
*type = RZIL_OP_ARG_EFF;
|
||||
return eff;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void perform_jump(RzILVM *vm, RZ_OWN RzBitVector *dst) {
|
||||
rz_il_vm_event_add(vm, rz_il_event_pc_write_new(vm->pc, dst));
|
||||
rz_bv_free(vm->pc);
|
||||
vm->pc = dst;
|
||||
}
|
||||
|
||||
void *rz_il_handler_jmp(RzILVM *vm, RzILOp *op, RzILOpArgType *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpJmp *op_jmp = op->op.jmp;
|
||||
RzBitVector *addr = rz_il_evaluate_bitv(vm, op_jmp->dst, type);
|
||||
RzILEffect *eff = rz_il_effect_new(EFFECT_TYPE_CTRL);
|
||||
|
||||
eff->ctrl_eff->pc = addr;
|
||||
|
||||
perform_jump(vm, rz_il_evaluate_bitv(vm, op->op.jmp->dst, type));
|
||||
*type = RZIL_OP_ARG_EFF;
|
||||
return eff;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *rz_il_handler_goto(RzILVM *vm, RzILOp *op, RzILOpArgType *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpGoto *op_goto = op->op.goto_;
|
||||
const char *lname = op_goto->lbl;
|
||||
RzILEffect *eff = rz_il_effect_new(EFFECT_TYPE_CTRL);
|
||||
|
||||
RzILEffectLabel *label = rz_il_vm_find_label_by_name(vm, lname);
|
||||
if (label->type == EFFECT_LABEL_SYSCALL) {
|
||||
rz_il_effect_ctrl_free(eff->ctrl_eff);
|
||||
eff->notation = EFFECT_NOTATION_GOTO_SYS;
|
||||
// WARN : HACK to call hook
|
||||
eff->ctrl_eff = (void *)op;
|
||||
} else if (label->type == EFFECT_LABEL_HOOK) {
|
||||
rz_il_effect_ctrl_free(eff->ctrl_eff);
|
||||
eff->notation = EFFECT_NOTATION_GOTO_HOOK;
|
||||
// WARN : HACK to call
|
||||
eff->ctrl_eff = (void *)op;
|
||||
if (label->type == EFFECT_LABEL_SYSCALL || label->type == EFFECT_LABEL_HOOK) {
|
||||
RzILVmHook internal_hook = (RzILVmHook)label->hook;
|
||||
internal_hook(vm, op);
|
||||
} else {
|
||||
// Normal
|
||||
const RzBitVector *addr = rz_il_hash_find_addr_by_lblname(vm, lname);
|
||||
eff->ctrl_eff->pc = rz_bv_dup(addr);
|
||||
perform_jump(vm, rz_bv_dup(label->addr));
|
||||
}
|
||||
|
||||
*type = RZIL_OP_ARG_EFF;
|
||||
return eff;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *rz_il_handler_seq(RzILVM *vm, RzILOp *op, RzILOpArgType *type) {
|
||||
rz_return_val_if_fail(vm && op && type, NULL);
|
||||
|
||||
RzILOpSeq *op_seq = op->op.seq;
|
||||
|
||||
RzILEffect *eff_x = rz_il_evaluate_effect(vm, op_seq->x, type);
|
||||
RzILEffect *eff_y = rz_il_evaluate_effect(vm, op_seq->y, type);
|
||||
|
||||
// add eff_y to the next eff of eff_x
|
||||
RzILEffect *eff_uni = eff_x;
|
||||
eff_uni->next_eff = eff_y;
|
||||
|
||||
return eff_uni;
|
||||
rz_il_evaluate_effect(vm, op_seq->x, type);
|
||||
rz_il_evaluate_effect(vm, op_seq->y, type);
|
||||
*type = RZIL_OP_ARG_EFF;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *rz_il_handler_branch(RzILVM *vm, RzILOp *op, RzILOpArgType *type) {
|
||||
|
|
@ -240,18 +162,19 @@ void *rz_il_handler_branch(RzILVM *vm, RzILOp *op, RzILOpArgType *type) {
|
|||
RzILOpBranch *op_branch = op->op.branch;
|
||||
|
||||
RzILBool *condition = rz_il_evaluate_bool(vm, op_branch->condition, type);
|
||||
RzILEffect *ret;
|
||||
if (condition->b) {
|
||||
// true branch
|
||||
ret = (op_branch->true_eff == NULL) ? rz_il_effect_new(EFFECT_TYPE_NON) : rz_il_evaluate_effect(vm, op_branch->true_eff, type);
|
||||
if (op_branch->true_eff) {
|
||||
rz_il_evaluate_effect(vm, op_branch->true_eff, type);
|
||||
}
|
||||
} else {
|
||||
// false branch
|
||||
ret = (op_branch->false_eff == NULL) ? rz_il_effect_new(EFFECT_TYPE_NON) : rz_il_evaluate_effect(vm, op_branch->false_eff, type);
|
||||
if (op_branch->false_eff) {
|
||||
rz_il_evaluate_effect(vm, op_branch->false_eff, type);
|
||||
}
|
||||
}
|
||||
rz_il_bool_free(condition);
|
||||
|
||||
if (ret) {
|
||||
*type = RZIL_OP_ARG_EFF;
|
||||
}
|
||||
return ret;
|
||||
*type = RZIL_OP_ARG_EFF;
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ void *rz_il_handler_bool_inv(RzILVM *vm, RzILOp *op, RzILOpArgType *type);
|
|||
void *rz_il_handler_cast(RzILVM *vm, RzILOp *op, RzILOpArgType *type);
|
||||
void *rz_il_handler_append(RzILVM *vm, RzILOp *op, RzILOpArgType *type);
|
||||
|
||||
void *rz_il_handler_perform(RzILVM *vm, RzILOp *op, RzILOpArgType *type);
|
||||
void *rz_il_handler_nop(RzILVM *vm, RzILOp *op, RzILOpArgType *type);
|
||||
void *rz_il_handler_set(RzILVM *vm, RzILOp *op, RzILOpArgType *type);
|
||||
void *rz_il_handler_let(RzILVM *vm, RzILOp *op, RzILOpArgType *type);
|
||||
void *rz_il_handler_jmp(RzILVM *vm, RzILOp *op, RzILOpArgType *type);
|
||||
|
|
@ -86,7 +86,7 @@ static RzILOpHandler op_handler_table_default[RZIL_OP_MAX] = {
|
|||
rz_il_handler_append, /* RZIL_OP_APPEND */
|
||||
rz_il_handler_load, /* RZIL_OP_LOAD */
|
||||
rz_il_handler_store, /* RZIL_OP_STORE */
|
||||
rz_il_handler_perform, /* RZIL_OP_PERFORM */
|
||||
rz_il_handler_nop, /* RZIL_OP_NOP */
|
||||
rz_il_handler_set, /* RZIL_OP_SET */
|
||||
rz_il_handler_let, /* RZIL_OP_LET */
|
||||
rz_il_handler_jmp, /* RZIL_OP_JMP */
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#define RZ_IL_DEFINITIONS_H
|
||||
|
||||
#include <rz_util/rz_bitvector.h>
|
||||
#include <rz_il/definitions/effect.h>
|
||||
#include <rz_il/definitions/label.h>
|
||||
#include <rz_il/definitions/bool.h>
|
||||
#include <rz_il/definitions/value.h>
|
||||
#include <rz_il/definitions/variable.h>
|
||||
|
|
|
|||
|
|
@ -1,100 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2021 heersin <teablearcher@gmail.com>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#ifndef RZ_IL_EFFECT_H
|
||||
#define RZ_IL_EFFECT_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <rz_util.h>
|
||||
#include <rz_type.h>
|
||||
#include <rz_il/definitions/value.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
EFFECT_TYPE_NON, // perform none effect will not affect data / control, used for passing info
|
||||
EFFECT_TYPE_DATA,
|
||||
EFFECT_TYPE_CTRL,
|
||||
} RzEffectType;
|
||||
|
||||
typedef enum {
|
||||
EFFECT_NOTATION_NON = 0x0,
|
||||
EFFECT_NOTATION_GOTO_SYS = 0x1,
|
||||
EFFECT_NOTATION_GOTO_HOOK = 0x2
|
||||
} RzEffectNotation;
|
||||
|
||||
typedef enum {
|
||||
EFFECT_LABEL_ADDR,
|
||||
EFFECT_LABEL_SYSCALL,
|
||||
EFFECT_LABEL_HOOK
|
||||
// more
|
||||
} RzILEffectLabelType;
|
||||
|
||||
typedef enum {
|
||||
DATA_EFF_NON,
|
||||
DATA_EFF_ASSIGN,
|
||||
DATA_EFF_INC
|
||||
// maybe more
|
||||
} RzILDataEffOperation;
|
||||
|
||||
struct rzil_effect_label_t {
|
||||
char *label_id; ///< Label name
|
||||
union {
|
||||
RzBitVector *addr; ///< RzBitVector address if EFFECT_LABEL_ADDR
|
||||
void *hook; ///< Function pointer if EFFECT_LABEL_SYSCALL / EFFECT_LABEL_HOOK
|
||||
};
|
||||
RzILEffectLabelType type; ///< type of label
|
||||
};
|
||||
|
||||
struct rzil_control_effect_t {
|
||||
RzBitVector *pc; ///< New Program Counter
|
||||
};
|
||||
|
||||
struct rzil_data_effect_t {
|
||||
const char *var_name; ///< Name of variable, const one
|
||||
bool is_mutable;
|
||||
bool is_local;
|
||||
RzILVal *val;
|
||||
RzILDataEffOperation operation; ///< operation to value and variable
|
||||
};
|
||||
|
||||
typedef struct rzil_control_effect_t RzILCtrlEffect;
|
||||
typedef struct rzil_data_effect_t RzILDataEffect;
|
||||
typedef struct rzil_effect_label_t RzILEffectLabel;
|
||||
|
||||
typedef struct rzil_effect_union_t RzILEffect;
|
||||
/**
|
||||
* \struct rzil_effect_union_t
|
||||
* \brief structure of data/control effect
|
||||
*/
|
||||
struct rzil_effect_union_t {
|
||||
ut8 effect_type; ///< effect type
|
||||
RzEffectNotation notation; ///< Marks for carring additional info
|
||||
RzILEffect *next_eff; ///< pointer to next effect, used in packed effect
|
||||
union {
|
||||
RzILCtrlEffect *ctrl_eff; ///< pointer to ctrl effect
|
||||
RzILDataEffect *data_eff; ///< pointer to data effect
|
||||
};
|
||||
};
|
||||
|
||||
// a chain of effects
|
||||
// should use something like rz_vector / rz_list
|
||||
RZ_API RzILEffect *rz_il_effect_new(RzEffectType type);
|
||||
RZ_API RzILDataEffect *rz_il_effect_data_new(void);
|
||||
RZ_API RzILCtrlEffect *rz_il_effect_ctrl_new(void);
|
||||
RZ_API RzILEffect *rz_il_wrap_ctrl_effect(RzILCtrlEffect *eff);
|
||||
RZ_API RzILEffect *rz_il_wrap_data_effect(RzILDataEffect *eff);
|
||||
RZ_API RzILEffectLabel *rz_il_effect_label_new(const char *name, RzILEffectLabelType type);
|
||||
RZ_API void rz_il_effect_free(RzILEffect *effect);
|
||||
RZ_API void rz_il_effect_ctrl_free(RzILCtrlEffect *eff);
|
||||
RZ_API void rz_il_effect_data_free(RzILDataEffect *eff);
|
||||
RZ_API char *rz_il_effect_as_string(RzILEffect *effect);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // RZ_IL_EFFECT_H
|
||||
41
librz/include/rz_il/definitions/label.h
Normal file
41
librz/include/rz_il/definitions/label.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
// SPDX-FileCopyrightText: 2021 heersin <teablearcher@gmail.com>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#ifndef RZ_IL_EFFECT_H
|
||||
#define RZ_IL_EFFECT_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <rz_util.h>
|
||||
#include <rz_type.h>
|
||||
#include <rz_il/definitions/value.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
EFFECT_LABEL_ADDR,
|
||||
EFFECT_LABEL_SYSCALL,
|
||||
EFFECT_LABEL_HOOK
|
||||
// more
|
||||
} RzILEffectLabelType;
|
||||
|
||||
struct rzil_effect_label_t {
|
||||
char *label_id; ///< Label name
|
||||
union {
|
||||
RzBitVector *addr; ///< RzBitVector address if EFFECT_LABEL_ADDR
|
||||
void *hook; ///< Function pointer if EFFECT_LABEL_SYSCALL / EFFECT_LABEL_HOOK
|
||||
};
|
||||
RzILEffectLabelType type; ///< type of label
|
||||
};
|
||||
|
||||
typedef struct rzil_effect_label_t RzILEffectLabel;
|
||||
|
||||
RZ_API RzILEffectLabel *rz_il_effect_label_new(const char *name, RzILEffectLabelType type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // RZ_IL_EFFECT_H
|
||||
|
|
@ -18,8 +18,7 @@ typedef union {
|
|||
} RzValUnion;
|
||||
|
||||
/**
|
||||
* \struct rz_il_val_t
|
||||
* \brief structure of RzILVal
|
||||
* A concrete value of `'a pure`. Either a bitvector or boolean.
|
||||
*/
|
||||
typedef struct rz_il_val_t {
|
||||
RzILVarType type; ///< type of value
|
||||
|
|
|
|||
|
|
@ -140,17 +140,6 @@ struct rzil_op_shift_t {
|
|||
RzILOp *y; ///< index of operand 2
|
||||
};
|
||||
|
||||
/**
|
||||
* \struct rzil_op_perform_t
|
||||
* \brief op structure for `perform` ('a Effect.sort -> 'a eff)
|
||||
*
|
||||
* perform s performs a generic effect of sort s.
|
||||
* normally we set ret to -1 to show that no more effect after perform this one
|
||||
*/
|
||||
struct rzil_op_perform_t {
|
||||
RzILOp *eff; ///< index of effect to perform
|
||||
};
|
||||
|
||||
/**
|
||||
* \struct rzil_op_set_t
|
||||
* \brief op structure for `set` ('a var -> 'a pure -> data eff)
|
||||
|
|
@ -356,7 +345,7 @@ typedef enum {
|
|||
RZIL_OP_STORE,
|
||||
|
||||
// Effects (opcode with side effects)
|
||||
RZIL_OP_PERFORM,
|
||||
RZIL_OP_NOP,
|
||||
RZIL_OP_SET,
|
||||
RZIL_OP_LET,
|
||||
RZIL_OP_JMP,
|
||||
|
|
@ -406,7 +395,6 @@ typedef struct rzil_op_bool_operation_t RzILOpBoolOr;
|
|||
typedef struct rzil_op_bool_operation_t RzILOpBoolXor;
|
||||
typedef struct rzil_op_bool_inv_t RzILOpBoolInv;
|
||||
|
||||
typedef struct rzil_op_perform_t RzILOpPerform;
|
||||
typedef struct rzil_op_set_t RzILOpSet;
|
||||
typedef struct rzil_op_let_t RzILOpLet;
|
||||
typedef struct rzil_op_jmp_t RzILOpJmp;
|
||||
|
|
@ -451,7 +439,6 @@ typedef union {
|
|||
RzILOpShiftRight *shiftr;
|
||||
RzILOpAppend *append;
|
||||
|
||||
RzILOpPerform *perform;
|
||||
RzILOpSet *set;
|
||||
RzILOpLet *let;
|
||||
RzILOpJmp *jmp;
|
||||
|
|
@ -505,7 +492,7 @@ RZ_API RZ_OWN RzILOp *rz_il_op_new_log_xor(RZ_NONNULL RzILOp *x, RZ_NONNULL RzIL
|
|||
RZ_API RZ_OWN RzILOp *rz_il_op_new_shiftl(RZ_NONNULL RzILOp *fill_bit, RZ_NONNULL RzILOp *x, RZ_NONNULL RzILOp *y);
|
||||
RZ_API RZ_OWN RzILOp *rz_il_op_new_shiftr(RZ_NONNULL RzILOp *fill_bit, RZ_NONNULL RzILOp *x, RZ_NONNULL RzILOp *y);
|
||||
RZ_API RZ_OWN RzILOp *rz_il_op_new_append(RZ_NONNULL RzILOp *high, RZ_NONNULL RzILOp *low);
|
||||
RZ_API RZ_OWN RzILOp *rz_il_op_new_perform(RZ_NONNULL RzILOp *effect);
|
||||
RZ_API RZ_OWN RzILOp *rz_il_op_new_nop();
|
||||
RZ_API RZ_OWN RzILOp *rz_il_op_new_set(RZ_NONNULL const char *var, RZ_NONNULL RzILOp *x);
|
||||
RZ_API RZ_OWN RzILOp *rz_il_op_new_let(RZ_NONNULL const char *var, RZ_NONNULL RzILOp *x, bool is_mutable);
|
||||
RZ_API RZ_OWN RzILOp *rz_il_op_new_jmp(RZ_NONNULL RzILOp *dst);
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ RZ_API void rz_il_event_json(RZ_NONNULL RzILEvent *evt, RZ_NONNULL PJ *pj);
|
|||
RZ_API RZ_OWN RzBitVector *rz_il_evaluate_bitv(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILOp *op, RZ_NONNULL RzILOpArgType *type);
|
||||
RZ_API RZ_OWN RzILBool *rz_il_evaluate_bool(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILOp *op, RZ_NONNULL RzILOpArgType *type);
|
||||
RZ_API RZ_OWN RzILVal *rz_il_evaluate_val(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILOp *op, RZ_NONNULL RzILOpArgType *type);
|
||||
RZ_API RZ_OWN RzILEffect *rz_il_evaluate_effect(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILOp *op, RZ_NONNULL RzILOpArgType *type);
|
||||
RZ_API RZ_OWN void rz_il_evaluate_effect(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILOp *op, RZ_NONNULL RzILOpArgType *type);
|
||||
|
||||
// recursively parse and evaluate
|
||||
RZ_API RZ_OWN void *rz_il_parse_op_root(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILOp *op, RZ_NONNULL RzILOpArgType *type);
|
||||
|
|
|
|||
|
|
@ -457,7 +457,7 @@ rz_il_definitions_files = [
|
|||
'include/rz_il/definitions/bag.h',
|
||||
'include/rz_il/definitions/bool.h',
|
||||
'include/rz_il/definitions/definitions.h',
|
||||
'include/rz_il/definitions/effect.h',
|
||||
'include/rz_il/definitions/label.h',
|
||||
'include/rz_il/definitions/mem.h',
|
||||
'include/rz_il/definitions/value.h',
|
||||
'include/rz_il/definitions/variable.h',
|
||||
|
|
|
|||
|
|
@ -81,23 +81,23 @@ opcode: inc [ptr]
|
|||
rzil: [store(key:var(v:ptr), value:add(x:load(key:var(v:ptr), mem:0), y:bitv(bits:0x01, len:8)), mem:0)]
|
||||
[{"opcode":"store","key":{"opcode":"var","value":"ptr"},"value":{"opcode":"add","x":{"opcode":"load","key":{"opcode":"var","value":"ptr"},"mem":0},"y":{"opcode":"bitv","bits":"0x01","len":8}},"mem":0}]
|
||||
opcode: while [ptr]
|
||||
rzil: [perform(eff:branch(condition:load(key:var(v:ptr), mem:0), true_eff:nop, false_eff:goto(lbl:]8)))]
|
||||
[{"opcode":"perform","eff":{"opcode":"branch","condition":{"opcode":"load","key":{"opcode":"var","value":"ptr"},"mem":0},"true_eff":{"opcode":"nop"},"false_eff":{"opcode":"goto","label":"]8"}}}]
|
||||
rzil: [branch(condition:load(key:var(v:ptr), mem:0), true_eff:nop, false_eff:goto(lbl:]8))]
|
||||
[{"opcode":"branch","condition":{"opcode":"load","key":{"opcode":"var","value":"ptr"},"mem":0},"true_eff":{"opcode":"nop"},"false_eff":{"opcode":"goto","label":"]8"}}]
|
||||
opcode: inc ptr
|
||||
rzil: [perform(eff:set(v:ptr, x:add(x:var(v:ptr), y:bitv(bits:0x0000000000000001, len:64))))]
|
||||
[{"opcode":"perform","eff":{"opcode":"set","dst":"ptr","src":{"opcode":"add","x":{"opcode":"var","value":"ptr"},"y":{"opcode":"bitv","bits":"0x0000000000000001","len":64}}}}]
|
||||
rzil: [set(v:ptr, x:add(x:var(v:ptr), y:bitv(bits:0x0000000000000001, len:64)))]
|
||||
[{"opcode":"set","dst":"ptr","src":{"opcode":"add","x":{"opcode":"var","value":"ptr"},"y":{"opcode":"bitv","bits":"0x0000000000000001","len":64}}}]
|
||||
opcode: dec ptr
|
||||
rzil: [perform(eff:set(v:ptr, x:sub(x:var(v:ptr), y:bitv(bits:0x0000000000000001, len:64))))]
|
||||
[{"opcode":"perform","eff":{"opcode":"set","dst":"ptr","src":{"opcode":"sub","x":{"opcode":"var","value":"ptr"},"y":{"opcode":"bitv","bits":"0x0000000000000001","len":64}}}}]
|
||||
rzil: [set(v:ptr, x:sub(x:var(v:ptr), y:bitv(bits:0x0000000000000001, len:64)))]
|
||||
[{"opcode":"set","dst":"ptr","src":{"opcode":"sub","x":{"opcode":"var","value":"ptr"},"y":{"opcode":"bitv","bits":"0x0000000000000001","len":64}}}]
|
||||
opcode: dec [ptr]
|
||||
rzil: [store(key:var(v:ptr), value:sub(x:load(key:var(v:ptr), mem:0), y:bitv(bits:0x01, len:8)), mem:0)]
|
||||
[{"opcode":"store","key":{"opcode":"var","value":"ptr"},"value":{"opcode":"sub","x":{"opcode":"load","key":{"opcode":"var","value":"ptr"},"mem":0},"y":{"opcode":"bitv","bits":"0x01","len":8}},"mem":0}]
|
||||
opcode: loop
|
||||
rzil: [perform(eff:branch(condition:load(key:var(v:ptr), mem:0), true_eff:goto(lbl:[14), false_eff:nop))]
|
||||
[{"opcode":"perform","eff":{"opcode":"branch","condition":{"opcode":"load","key":{"opcode":"var","value":"ptr"},"mem":0},"true_eff":{"opcode":"goto","label":"[14"},"false_eff":{"opcode":"nop"}}}]
|
||||
rzil: [branch(condition:load(key:var(v:ptr), mem:0), true_eff:goto(lbl:[14), false_eff:nop)]
|
||||
[{"opcode":"branch","condition":{"opcode":"load","key":{"opcode":"var","value":"ptr"},"mem":0},"true_eff":{"opcode":"goto","label":"[14"},"false_eff":{"opcode":"nop"}}]
|
||||
opcode: out [ptr]
|
||||
rzil: [perform(eff:goto(lbl:write))]
|
||||
[{"opcode":"perform","eff":{"opcode":"goto","label":"write"}}]
|
||||
rzil: [goto(lbl:write)]
|
||||
[{"opcode":"goto","label":"write"}]
|
||||
opcode: nop
|
||||
rzil: []
|
||||
null
|
||||
|
|
|
|||
|
|
@ -116,45 +116,11 @@ static bool test_rzil_mem() {
|
|||
mu_end;
|
||||
}
|
||||
|
||||
static bool test_rzil_effect() {
|
||||
RzILEffect *general_effect = rz_il_effect_new(EFFECT_TYPE_NON);
|
||||
mu_assert_notnull(general_effect, "Create Empty General Effect");
|
||||
|
||||
mu_assert_eq(general_effect->effect_type, EFFECT_TYPE_NON, "Empty effect has correct type");
|
||||
mu_assert_null(general_effect->next_eff, "Empty doesn't have next effect");
|
||||
mu_assert_null(general_effect->ctrl_eff, "Empty doesn't include control effect");
|
||||
mu_assert_null(general_effect->data_eff, "Empty doesn't include data effect");
|
||||
rz_il_effect_free(general_effect);
|
||||
|
||||
RzILCtrlEffect *c_eff = rz_il_effect_ctrl_new();
|
||||
mu_assert_notnull(c_eff, "Create empty control effect");
|
||||
mu_assert_null(c_eff->pc, "Empty control effect have no next pc info");
|
||||
|
||||
RzILDataEffect *d_eff = rz_il_effect_data_new();
|
||||
mu_assert_notnull(d_eff, "Create empty data effect");
|
||||
mu_assert_null(d_eff->var_name, "Empty data effect doesn't have variable name");
|
||||
|
||||
RzILEffect *data_effect, *contrl_effect;
|
||||
// wrap data effect
|
||||
data_effect = rz_il_wrap_data_effect(d_eff);
|
||||
mu_assert_eq(data_effect->effect_type, EFFECT_TYPE_DATA, "Wrap data effect");
|
||||
mu_assert_eq(data_effect->data_eff, d_eff, "Get data effect from general one");
|
||||
rz_il_effect_free(data_effect);
|
||||
|
||||
contrl_effect = rz_il_wrap_ctrl_effect(c_eff);
|
||||
mu_assert_eq(contrl_effect->effect_type, EFFECT_TYPE_CTRL, "Wrap control effect");
|
||||
mu_assert_eq(contrl_effect->ctrl_eff, c_eff, "Get control effect from general one");
|
||||
rz_il_effect_free(contrl_effect);
|
||||
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool all_tests() {
|
||||
mu_run_test(test_rzil_bool_init);
|
||||
mu_run_test(test_rzil_bool_logic);
|
||||
|
||||
mu_run_test(test_rzil_mem);
|
||||
mu_run_test(test_rzil_effect);
|
||||
return tests_passed != tests_run;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -164,21 +164,102 @@ static bool test_rzil_vm_root_evaluation() {
|
|||
mu_assert_eq(ite_val->data.b->b, true, "Return a True");
|
||||
rz_il_value_free(ite_val);
|
||||
|
||||
// Catch error
|
||||
|
||||
RzILOp *branch_cond = rz_il_op_new_b1();
|
||||
RzILOp *branch_true = rz_il_op_new_b1();
|
||||
RzILOp *branch_false = NULL; // empty effect
|
||||
RzILOp *branch_root = rz_il_op_new_branch(branch_cond, branch_true, branch_false);
|
||||
|
||||
type_checker = RZIL_OP_ARG_INIT;
|
||||
RzILEffect *eff = rz_il_evaluate_effect(vm, branch_root, &type_checker);
|
||||
mu_assert_null(eff, "Error happens");
|
||||
mu_assert_eq(type_checker, RZIL_OP_ARG_BOOL, "you cannot convert bool type to effect, such an error will be detected");
|
||||
rz_il_effect_free(eff);
|
||||
|
||||
rz_il_op_free(ite_root);
|
||||
rz_il_op_free(branch_root);
|
||||
rz_il_vm_free(vm);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
static bool test_rzil_vm_op_set() {
|
||||
RzILVM *vm = rz_il_vm_new(0, 8, 16);
|
||||
|
||||
RzILVar *var_r1 = rz_il_vm_create_global_variable(vm, "r1", RZIL_VAR_TYPE_UNK, true);
|
||||
RzILVar *var_r2 = rz_il_vm_create_global_variable(vm, "r2", RZIL_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)));
|
||||
|
||||
// try to set immutable and fail
|
||||
RzILOp *op = rz_il_op_new_set("r2", rz_il_op_new_bitv_from_ut64(24, 42));
|
||||
RzILOpArgType tret = RZIL_OP_ARG_INIT;
|
||||
rz_il_evaluate_effect(vm, op, &tret);
|
||||
rz_il_op_free(op);
|
||||
RzILVal *val = rz_il_hash_find_val_by_name(vm, var_r2->var_name);
|
||||
mu_assert_notnull(val, "get val");
|
||||
mu_assert_eq(val->type, RZIL_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));
|
||||
tret = RZIL_OP_ARG_INIT;
|
||||
rz_il_evaluate_effect(vm, op, &tret);
|
||||
rz_il_op_free(op);
|
||||
val = rz_il_hash_find_val_by_name(vm, var_r1->var_name);
|
||||
mu_assert_notnull(val, "get val");
|
||||
mu_assert_eq(val->type, RZIL_VAR_TYPE_BV, "set bv");
|
||||
mu_assert_eq(rz_bv_len(val->data.bv), 24, "set bv len");
|
||||
mu_assert_eq(rz_bv_to_ut64(val->data.bv), 42, "set bv val");
|
||||
|
||||
rz_il_vm_free(vm);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
static bool test_rzil_vm_op_jmp() {
|
||||
RzILVM *vm = rz_il_vm_new(0, 8, 16);
|
||||
|
||||
RzILOp *op = rz_il_op_new_jmp(rz_il_op_new_bitv_from_ut64(8, 0x42));
|
||||
RzILOpArgType tret = RZIL_OP_ARG_INIT;
|
||||
rz_il_evaluate_effect(vm, op, &tret);
|
||||
rz_il_op_free(op);
|
||||
mu_assert_eq(rz_bv_to_ut64(vm->pc), 0x42, "jumped");
|
||||
|
||||
rz_il_vm_free(vm);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
static bool test_rzil_vm_op_goto_addr() {
|
||||
RzILVM *vm = rz_il_vm_new(0, 8, 16);
|
||||
|
||||
RzBitVector *dst = rz_bv_new_from_ut64(8, 0x42);
|
||||
rz_il_vm_create_label(vm, "beach", dst);
|
||||
rz_bv_free(dst);
|
||||
|
||||
RzILOp *op = rz_il_op_new_goto("beach");
|
||||
RzILOpArgType tret = RZIL_OP_ARG_INIT;
|
||||
rz_il_evaluate_effect(vm, op, &tret);
|
||||
rz_il_op_free(op);
|
||||
mu_assert_eq(rz_bv_to_ut64(vm->pc), 0x42, "wentto");
|
||||
|
||||
rz_il_vm_free(vm);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
static void hook_test(RzILVM *vm, RzILOp *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)));
|
||||
}
|
||||
|
||||
static bool test_rzil_vm_op_goto_hook() {
|
||||
RzILVM *vm = rz_il_vm_new(0, 8, 16);
|
||||
|
||||
RzILVar *var = rz_il_vm_create_global_variable(vm, "myvar", RZIL_VAR_TYPE_UNK, true);
|
||||
rz_il_hash_bind(vm, var, rz_il_vm_create_value_bitv(vm, rz_bv_new_zero(32)));
|
||||
|
||||
RzBitVector *dst = rz_bv_new_from_ut64(8, 0x42);
|
||||
RzILEffectLabel *label = rz_il_vm_create_label_lazy(vm, "beach");
|
||||
label->type = EFFECT_LABEL_HOOK;
|
||||
label->hook = hook_test;
|
||||
rz_bv_free(dst);
|
||||
|
||||
RzILOp *op = rz_il_op_new_goto("beach");
|
||||
RzILOpArgType tret = RZIL_OP_ARG_INIT;
|
||||
rz_il_evaluate_effect(vm, op, &tret);
|
||||
rz_il_op_free(op);
|
||||
|
||||
// check the effect we implemented in hook_test
|
||||
RzILVal *val = rz_il_hash_find_val_by_name(vm, "myvar");
|
||||
mu_assert_eq(val->type, RZIL_VAR_TYPE_BV, "val type");
|
||||
mu_assert_eq(rz_bv_to_ut64(val->data.bv), 0xc0ffee, "val contents");
|
||||
|
||||
rz_il_vm_free(vm);
|
||||
mu_end;
|
||||
}
|
||||
|
|
@ -188,6 +269,10 @@ bool all_tests() {
|
|||
mu_run_test(test_rzil_vm_basic_operation);
|
||||
mu_run_test(test_rzil_vm_operation);
|
||||
mu_run_test(test_rzil_vm_root_evaluation);
|
||||
mu_run_test(test_rzil_vm_op_set);
|
||||
mu_run_test(test_rzil_vm_op_jmp);
|
||||
mu_run_test(test_rzil_vm_op_goto_addr);
|
||||
mu_run_test(test_rzil_vm_op_goto_hook);
|
||||
return tests_passed != tests_run;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue