From 5dafbf7e67877960edba9d007b5242997cc8d1d4 Mon Sep 17 00:00:00 2001 From: wargio Date: Mon, 13 Dec 2021 23:44:00 +0100 Subject: [PATCH] [core] aezv - modify variables in RzIL VM --- librz/core/cil.c | 63 +++++++++++++++++++++++++- librz/core/cmd/cmd_analysis.c | 10 +++- librz/core/cmd_descs/cmd_analysis.yaml | 5 +- librz/core/cmd_descs/cmd_descs.c | 10 +++- librz/core/core_private.h | 1 + test/db/cmd/cmd_aez | 24 ++++++++++ 6 files changed, 108 insertions(+), 5 deletions(-) diff --git a/librz/core/cil.c b/librz/core/cil.c index 5eff5187fe..4b8b14e1be 100644 --- a/librz/core/cil.c +++ b/librz/core/cil.c @@ -420,6 +420,67 @@ RZ_IPI void rz_core_analysis_rzil_reinit(RzCore *core) { } } +/** + * \brief Set a vm variable from user input + * \return whether the set succeeded + * + * Sets the given var, or "PC" to the given value. + * The type of the variable is handled dynamically. + * This is intended for setting from user input only. + */ +RZ_IPI bool rz_core_analysis_rzil_vm_set(RzCore *core, const char *var_name, ut64 value) { + rz_return_val_if_fail(core && core->analysis && var_name, false); + + RzAnalysisRzil *rzil = core->analysis->rzil; + if (!rzil || !rzil->vm) { + RZ_LOG_ERROR("RzIL: Run 'aezi' first to initialize the VM\n"); + 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); + 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 RZIL_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 RZIL_VAR_TYPE_BOOL: + newval = rz_il_vm_create_value_bool(rzil->vm, value); + break; + case RZIL_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 found; +} + typedef struct il_print_t { RzOutputMode mode; const char *name; @@ -485,7 +546,7 @@ static void rzil_print_register_unk(ILPrint *p) { 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) { - RZ_LOG_ERROR("RzIL: the VM is not initialized.\n"); + RZ_LOG_ERROR("RzIL: Run 'aezi' first to initialize the VM\n"); return; } diff --git a/librz/core/cmd/cmd_analysis.c b/librz/core/cmd/cmd_analysis.c index b4c0cc1de6..c921daf2de 100644 --- a/librz/core/cmd/cmd_analysis.c +++ b/librz/core/cmd/cmd_analysis.c @@ -8932,6 +8932,14 @@ RZ_IPI RzCmdStatus rz_rzil_vm_step_until_addr_handler(RzCore *core, int argc, co } RZ_IPI RzCmdStatus rz_rzil_vm_status_handler(RzCore *core, int argc, const char **argv, RzOutputMode mode) { - rz_core_analysis_rzil_vm_status(core, argc > 1 ? argv[1] : NULL, mode); + if (argc == 3) { + ut64 value = rz_num_math(core->num, argv[2]); + if (rz_core_analysis_rzil_vm_set(core, argv[1], value)) { + rz_cons_printf("%s = 0x%" PFMT64x "\n", argv[1], value); + } + } else { + // print variable or all variables + rz_core_analysis_rzil_vm_status(core, argc == 2 ? argv[1] : NULL, mode); + } return RZ_CMD_STATUS_OK; } diff --git a/librz/core/cmd_descs/cmd_analysis.yaml b/librz/core/cmd_descs/cmd_analysis.yaml index adf8278d85..f8219c8433 100644 --- a/librz/core/cmd_descs/cmd_analysis.yaml +++ b/librz/core/cmd_descs/cmd_analysis.yaml @@ -519,7 +519,7 @@ commands: - name: address type: RZ_CMD_ARG_TYPE_RZNUM - name: aezv - summary: Print the current status of the RzIL Virtual Machine + summary: Print or modify the current status of the RzIL Virtual Machine cname: rzil_vm_status type: RZ_CMD_DESC_TYPE_ARGV_MODES modes: @@ -531,6 +531,9 @@ commands: - name: var_name type: RZ_CMD_ARG_TYPE_STRING optional: true + - name: number + type: RZ_CMD_ARG_TYPE_RZNUM + optional: true ##################################################### # Keep this in sync with dr in cmd_debug.yaml from here... - name: ar diff --git a/librz/core/cmd_descs/cmd_descs.c b/librz/core/cmd_descs/cmd_descs.c index eca2a2a759..9386875575 100644 --- a/librz/core/cmd_descs/cmd_descs.c +++ b/librz/core/cmd_descs/cmd_descs.c @@ -104,7 +104,7 @@ static const RzCmdDescArg analysis_function_all_opcode_stat_args[2]; static const RzCmdDescArg rzil_vm_step_args[2]; static const RzCmdDescArg rzil_vm_step_with_events_args[2]; static const RzCmdDescArg rzil_vm_step_until_addr_args[2]; -static const RzCmdDescArg rzil_vm_status_args[2]; +static const RzCmdDescArg rzil_vm_status_args[3]; static const RzCmdDescArg analysis_regs_args[2]; static const RzCmdDescArg analysis_regs_columns_args[2]; static const RzCmdDescArg analysis_regs_references_args[2]; @@ -1860,6 +1860,12 @@ static const RzCmdDescArg rzil_vm_status_args[] = { { .name = "var_name", .type = RZ_CMD_ARG_TYPE_STRING, + .optional = true, + + }, + { + .name = "number", + .type = RZ_CMD_ARG_TYPE_RZNUM, .flags = RZ_CMD_ARG_FLAG_LAST, .optional = true, @@ -1867,7 +1873,7 @@ static const RzCmdDescArg rzil_vm_status_args[] = { { 0 }, }; static const RzCmdDescHelp rzil_vm_status_help = { - .summary = "Print the current status of the RzIL Virtual Machine", + .summary = "Print or modify the current status of the RzIL Virtual Machine", .args = rzil_vm_status_args, }; diff --git a/librz/core/core_private.h b/librz/core/core_private.h index 8a15d1a652..bda190d271 100644 --- a/librz/core/core_private.h +++ b/librz/core/core_private.h @@ -30,6 +30,7 @@ RZ_IPI void rz_core_analysis_esil_emulate_bb(RzCore *core); RZ_IPI void rz_core_analysis_esil_default(RzCore *core); RZ_IPI void rz_core_analysis_rzil_reinit(RzCore *core); +RZ_IPI bool rz_core_analysis_rzil_vm_set(RzCore *core, const char *var_name, ut64 value); RZ_IPI void rz_core_analysis_rzil_vm_status(RzCore *core, const char *varname, RzOutputMode mode); RZ_IPI void rz_core_rzil_step(RzCore *core); RZ_IPI void rz_core_analysis_rzil_step_with_events(RzCore *core, PJ *pj); diff --git a/test/db/cmd/cmd_aez b/test/db/cmd/cmd_aez index 54e4ac1a45..d930b65b5e 100644 --- a/test/db/cmd/cmd_aez +++ b/test/db/cmd/cmd_aez @@ -10,3 +10,27 @@ EXPECT=<