[RzIL] Add rz_il_op_new_(unsigned|signed)()

This commit is contained in:
Florian Märkl 2021-12-29 14:15:52 +01:00
parent 97aba39cf3
commit 7a8d5af180
3 changed files with 81 additions and 4 deletions

View file

@ -288,6 +288,26 @@ RZ_API RZ_OWN RzILOpBitVector *rz_il_op_new_cast(ut32 length, RZ_NONNULL RzILOpB
return ret;
}
/**
* \brief Extend val to length bits, filling up with zeroes
*
* For length > val->len, this fits the general notion of zero extension.
*/
RZ_API RZ_OWN RzILOpBitVector *rz_il_op_new_unsigned(ut32 length, RZ_NONNULL RzILOpBitVector *val) {
rz_return_val_if_fail(length && val, NULL);
return rz_il_op_new_cast(length, rz_il_op_new_b0(), val);
}
/**
* \brief Extend val to length bits, filling up with val's most significant bit
*
* For length > val->len, this fits the general notion of sign extension.
*/
RZ_API RZ_OWN RzILOpBitVector *rz_il_op_new_signed(ut32 length, RZ_NONNULL RzILOpBitVector *val) {
rz_return_val_if_fail(length && val, NULL);
return rz_il_op_new_cast(length, rz_il_op_new_msb(rz_il_op_pure_dup(val)), val);
}
/**
* \brief op structure for `neg` ('s bitv -> 's bitv)
*
@ -673,7 +693,10 @@ RZ_API RZ_OWN RzILOpEffect *rz_il_op_new_storew(RzILMemIndex mem, RZ_NONNULL RzI
#undef rz_il_op_new_2
#undef rz_il_op_new_3
RZ_API RzILOpPure *rz_il_op_pure_dup(RZ_NULLABLE RzILOpPure *op) {
/**
* Duplicate the given op recursively, for example to reuse it multiple times in another op.
*/
RZ_API RzILOpPure *rz_il_op_pure_dup(RZ_NONNULL RzILOpPure *op) {
rz_return_val_if_fail(op, NULL);
RzILOpPure *r = RZ_NEW0(RzILOpPure);
if (!r) {

View file

@ -439,7 +439,7 @@ struct rz_il_op_pure_t {
};
RZ_API void rz_il_op_pure_free(RZ_NULLABLE RzILOpPure *op);
RZ_API RzILOpPure *rz_il_op_pure_dup(RZ_NULLABLE RzILOpPure *op);
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();
@ -461,6 +461,8 @@ RZ_API RZ_OWN RzILOpBool *rz_il_op_new_eq(RZ_NONNULL RzILOpPure *x, RZ_NONNULL R
RZ_API RZ_OWN RzILOpBool *rz_il_op_new_ule(RZ_NONNULL RzILOpPure *x, RZ_NONNULL RzILOpPure *y);
RZ_API RZ_OWN RzILOpBool *rz_il_op_new_sle(RZ_NONNULL RzILOpPure *x, RZ_NONNULL RzILOpPure *y);
RZ_API RZ_OWN RzILOpBitVector *rz_il_op_new_cast(ut32 length, RZ_NONNULL RzILOpBool *fill, RZ_NONNULL RzILOpBitVector *val);
RZ_API RZ_OWN RzILOpBitVector *rz_il_op_new_unsigned(ut32 length, RZ_NONNULL RzILOpBitVector *val); // "zero extension"
RZ_API RZ_OWN RzILOpBitVector *rz_il_op_new_signed(ut32 length, RZ_NONNULL RzILOpBitVector *val); // "sign extension"
RZ_API RZ_OWN RzILOpBitVector *rz_il_op_new_neg(RZ_NONNULL RzILOpBitVector *value);
RZ_API RZ_OWN RzILOpBitVector *rz_il_op_new_log_not(RZ_NONNULL RzILOpBitVector *value);
RZ_API RZ_OWN RzILOpBitVector *rz_il_op_new_add(RZ_NONNULL RzILOpBitVector *x, RZ_NONNULL RzILOpBitVector *y);

View file

@ -189,7 +189,7 @@ static bool test_rzil_vm_op_cast() {
mu_assert_eq(rz_bv_to_ut64(r), 0x2, "eval val");
rz_bv_free(r);
// 8 -> 16 (false)
// 8 -> 13 (false)
op = rz_il_op_new_cast(13, rz_il_op_new_b0(), rz_il_op_new_bitv_from_ut64(8, 0x42));
r = rz_il_evaluate_bitv(vm, op);
rz_il_op_pure_free(op);
@ -198,7 +198,7 @@ static bool test_rzil_vm_op_cast() {
mu_assert_eq(rz_bv_to_ut64(r), 0x42, "eval val");
rz_bv_free(r);
// 8 -> 16 (true)
// 8 -> 13 (true)
op = rz_il_op_new_cast(13, rz_il_op_new_b1(), rz_il_op_new_bitv_from_ut64(8, 0x42));
r = rz_il_evaluate_bitv(vm, op);
rz_il_op_pure_free(op);
@ -211,6 +211,56 @@ static bool test_rzil_vm_op_cast() {
mu_end;
}
static bool test_rzil_vm_op_unsigned() {
RzILVM *vm = rz_il_vm_new(0, 8, false);
// msb not set, filled with 0
RzILOpPure *op = rz_il_op_new_unsigned(13, rz_il_op_new_bitv_from_ut64(8, 0x42));
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), 13, "eval length");
mu_assert_eq(rz_bv_to_ut64(r), 0x42, "eval val");
rz_bv_free(r);
// msb set, still filled with 0
op = rz_il_op_new_unsigned(13, rz_il_op_new_bitv_from_ut64(8, 0xf2));
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), 13, "eval length");
mu_assert_eq(rz_bv_to_ut64(r), 0xf2, "eval val");
rz_bv_free(r);
rz_il_vm_free(vm);
mu_end;
}
static bool test_rzil_vm_op_signed() {
RzILVM *vm = rz_il_vm_new(0, 8, false);
// msb not set, filled with 0
RzILOpPure *op = rz_il_op_new_signed(13, rz_il_op_new_bitv_from_ut64(8, 0x42));
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), 13, "eval length");
mu_assert_eq(rz_bv_to_ut64(r), 0x42, "eval val");
rz_bv_free(r);
// msb set, filled with 1
op = rz_il_op_new_signed(13, rz_il_op_new_bitv_from_ut64(8, 0xf2));
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), 13, "eval length");
mu_assert_eq(rz_bv_to_ut64(r), 0x1ff2, "eval val");
rz_bv_free(r);
rz_il_vm_free(vm);
mu_end;
}
static bool test_rzil_vm_op_set() {
RzILVM *vm = rz_il_vm_new(0, 8, false);
@ -430,6 +480,8 @@ bool all_tests() {
mu_run_test(test_rzil_vm_operation);
mu_run_test(test_rzil_vm_root_evaluation);
mu_run_test(test_rzil_vm_op_cast);
mu_run_test(test_rzil_vm_op_unsigned);
mu_run_test(test_rzil_vm_op_signed);
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);