rizin/test/integration/test_analysis_il.c
Rot127 67c633e8ca
Dist leaks & RISCV CI build (#6432)
* Fix leaks

* Fix linking issue on RISCV CI job

* Fix leak of all configs if they are reset.
2026-05-30 12:07:55 +00:00

168 lines
6.6 KiB
C

// SPDX-FileCopyrightText: 2022 Florian Märkl <info@florianmaerkl.de>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_core.h>
#include "../unit/minunit.h"
/**
* Test running an IL vm with Analysis connection independently of the global user-faced vm
*/
static bool test_analysis_il_vm_step() {
RzCore *core = rz_core_new();
mu_assert_notnull(core, "init core");
RzCoreFile *cf = rz_core_file_open(core, "hex://a9754937", RZ_PERM_RWX, 0);
mu_assert_notnull(cf, "open hex file");
rz_core_bin_load(core, NULL, 0);
rz_config_set(core->config, "asm.arch", "6502");
RzReg *reg = rz_reg_new();
mu_assert_notnull(reg, "create reg");
char *reg_profile = rz_analysis_get_reg_profile(core->analysis);
mu_assert_notnull(reg_profile, "reg profile");
bool succ = rz_reg_set_profile_string(reg, reg_profile);
rz_mem_free(reg_profile);
mu_assert_true(succ, "apply reg profile");
RzAnalysisILVM *vm = rz_analysis_il_vm_new(core->analysis, reg);
mu_assert_notnull(vm, "create analysis vm");
rz_analysis_il_vm_sync_to_reg(vm, reg); // initial sync to get any plugin-specified initialization
// a9 75 lda #0x75
RzReg *analysis_reg = rz_analysis_get_reg(core->analysis);
RzAnalysisILStepResult sr = rz_analysis_il_vm_step(core->analysis, vm, reg);
mu_assert_eq(sr, RZ_ANALYSIS_IL_STEP_RESULT_SUCCESS, "il step");
mu_assert_eq(rz_reg_getv(reg, "a"), 0x75, "result in local reg");
mu_assert_eq(rz_reg_get_value_by_role(reg, RZ_REG_NAME_PC), 2, "pc in local reg");
mu_assert_eq(rz_reg_getv(analysis_reg, "a"), 0x0, "global reg untouched");
mu_assert_eq(rz_reg_get_value_by_role(analysis_reg, RZ_REG_NAME_PC), 0, "global reg untouched");
// 49 37 eor #0x37
// ==> 0x75 ^ 0x37 = 0x42
sr = rz_analysis_il_vm_step(core->analysis, vm, reg);
mu_assert_eq(sr, RZ_ANALYSIS_IL_STEP_RESULT_SUCCESS, "il step");
mu_assert_eq(rz_reg_getv(reg, "a"), 0x42, "result in local reg");
mu_assert_eq(rz_reg_get_value_by_role(reg, RZ_REG_NAME_PC), 4, "pc in local reg");
mu_assert_eq(rz_reg_getv(analysis_reg, "a"), 0x0, "global reg untouched");
mu_assert_eq(rz_reg_get_value_by_role(analysis_reg, RZ_REG_NAME_PC), 0, "global reg untouched");
rz_reg_free(reg);
rz_analysis_il_vm_free(vm);
rz_core_free(core);
mu_end;
}
static bool test_analysis_il() {
RzCore *core = rz_core_new();
mu_assert_notnull(core, "init core");
RzCoreFile *cf = rz_core_file_open(core, "bins/elf/emulateme.arm64", RZ_PERM_RWX, 0);
mu_assert_notnull(cf, "open file");
mu_assert("load file", rz_core_bin_load(core, NULL, 0));
mu_assert("il vm setup", rz_analysis_il_vm_setup(core->analysis));
rz_core_perform_auto_analysis(core, RZ_CORE_ANALYSIS_DEEP);
RzStrBuf sb = { 0 };
RzAnalysisOp op = { 0 };
// extract and evaluate a single instruction
rz_core_analysis_il_reinit(core);
rz_analysis_op_init(&op);
rz_analysis_op(core->analysis, &op, core->offset, core->block, core->blocksize, RZ_ANALYSIS_OP_MASK_IL);
rz_il_op_effect_stringify(op.il_op, &sb, false);
mu_assert_streq(rz_strbuf_get(&sb), "(seq "
"(storew 0 (- (var sp) (bv 64 0x20)) (var x29)) "
"(storew 0 (+ (- (var sp) (bv 64 0x20)) (bv 64 0x8)) (var x30)) "
"(set sp (- (var sp) (bv 64 0x20))))",
"stringify il op");
mu_assert("eval rzil", rz_core_il_step(core, 1));
RzAnalysisILVM *il_vm = rz_analysis_get_il_vm(core->analysis);
RzILVal *v = rz_il_vm_get_var_value(il_vm->vm, RZ_IL_VAR_KIND_GLOBAL, "sp");
mu_assert_notnull(v, "RzIL vm var value");
mu_assert_eq(v->type, RZ_IL_TYPE_PURE_BITVECTOR, "var type");
mu_assert_eq(rz_bv_to_ut64(v->data.bv), -0x20, "var value");
// extract and evaluate a whole function
RzAnalysisFunction *f = rz_analysis_get_function_byname(core->analysis, "sym.decrypt");
mu_assert_notnull(v, "get function");
rz_core_seek(core, f->addr, true);
rz_config_set_b(core->config, "io.cache", true);
rz_core_file_open_load(core, "malloc://0x1000", 0x40000, RZ_PERM_R, false);
rz_core_file_open_load(core, "malloc://0x10", 0x50000, RZ_PERM_R, false);
ut64 obj_seckrit = rz_num_get(core->num, "obj.seckrit");
// New file mapping from 0x0-0xf
rz_core_file_malloc_copy_chunk(core, 0x10, obj_seckrit);
RzIOMap *map = rz_io_map_get(core->io, 0);
rz_io_map_remap(core->io, map->id, obj_seckrit);
RzReg *analysis_reg = rz_analysis_get_reg(core->analysis);
rz_core_reg_assign_sync(core, analysis_reg, NULL, "sp", 0x41000);
rz_core_reg_assign_sync(core, analysis_reg, NULL, "x0", 0x50000);
rz_core_write_string_at(core, 0x50000, "AnyColourYouLike");
rz_core_analysis_il_reinit(core);
mu_assert("eval rzil", rz_core_il_step_until(core, 0x914));
char buf[0x20];
obj_seckrit = rz_num_get(core->num, "obj.seckrit");
rz_io_read_at_mapped(core->io, obj_seckrit, (ut8 *)buf, RZ_ARRAY_SIZE(buf));
mu_assert_streq(buf, "Hello from RzIL!", "eval rzil in function");
RzIterator *iter = rz_core_analysis_op_function_iter(core, f, RZ_ANALYSIS_OP_MASK_IL);
mu_assert_notnull(iter, "function rzil");
ut64 count = 0;
RzAnalysisOp *pop = NULL;
rz_iterator_foreach(iter, pop) {
if (op.addr == 0x804) {
rz_strbuf_fini(&sb);
rz_il_op_effect_stringify(pop->il_op, &sb, false);
mu_assert_streq(rz_strbuf_get(&sb), "(set sp (- (var sp) (bv 64 0x30)))",
"stringify il op");
} else if (op.addr == 0x888) {
rz_strbuf_fini(&sb);
rz_il_op_effect_stringify(pop->il_op, &sb, false);
mu_assert_streq(rz_strbuf_get(&sb), "(set x0 (loadw 0 64 (+ (var sp) (bv 64 0x20))))",
"stringify il op");
}
++count;
}
mu_assert_eq(count, 69, "il op count of function");
rz_iterator_free(iter);
// extract and evaluate a chunk of instructions
count = 0;
iter = rz_core_analysis_op_chunk_iter(core, 0x918, 0, 30, RZ_ANALYSIS_OP_MASK_IL);
mu_assert_notnull(iter, "chunk rzil");
rz_iterator_foreach(iter, pop) {
if (op.addr == 0x918) {
rz_strbuf_fini(&sb);
rz_il_op_effect_stringify(pop->il_op, &sb, false);
mu_assert_streq(rz_strbuf_get(&sb), "(seq (storew 0 (- (var sp) (bv 64 0x30)) (var x29)) (storew 0 (+ (- (var sp) (bv 64 0x30)) (bv 64 0x8)) (var x30)) (set sp (- (var sp) (bv 64 0x30))))",
"stringify il op");
} else if (op.addr == 0x954) {
rz_strbuf_fini(&sb);
rz_il_op_effect_stringify(pop->il_op, &sb, false);
mu_assert_streq(rz_strbuf_get(&sb), "(set x0 (loadw 0 64 (+ (var sp) (bv 64 0x10))))",
"stringify il op");
}
++count;
}
mu_assert_eq(count, 30, "il op count of function");
rz_iterator_free(iter);
rz_strbuf_fini(&sb);
rz_analysis_op_fini(&op);
rz_core_seek(core, 0x918, true);
rz_core_analysis_il_reinit(core);
mu_assert("eval rzil", rz_core_il_step(core, 3));
rz_core_free(core);
mu_end;
}
bool all_tests() {
mu_run_test(test_analysis_il_vm_step);
mu_run_test(test_analysis_il);
return tests_passed != tests_run;
}
mu_main(all_tests)