40 if (!
ctx->global_vars) {
44 ctx->mems = ht_uu_new0();
46 ht_pp_free(
ctx->global_vars);
63 ht_pp_update(
ctx->global_vars,
name, hts);
71 ht_uu_update(
ctx->mems,
idx, ((
ut64)key_len << 32) | (
ut64)val_len);
103 ht_pp_free(
ctx->global_vars);
104 ht_uu_free(
ctx->mems);
123 ctx->global_ctx = global_ctx;
125 if (!
ctx->local_vars_known) {
129 if (!
ctx->local_vars_available) {
130 ht_pp_free(
ctx->local_vars_known);
137 ht_pp_free(
ctx->local_vars_known);
138 ht_pp_free(
ctx->local_vars_available);
148 ht_pp_update(
dst->local_vars_known,
k, sort);
157 ht_pp_update(
dst->local_vars_available,
k, sort);
187 meet->
op_name, (
const char *)
k, src_sort_s, dst_sort_s);
199 *dst_sort = src_sort;
231 .report_builder = report_builder,
263 #define VALIDATOR_PURE_ARGS \
264 RZ_NULLABLE RzILOpPure *op, \
265 RZ_NONNULL RzILSortPure *sort_out, \
266 RZ_NONNULL RzStrBuf *report_builder, \
267 RZ_NONNULL const LocalContext *ctx, \
268 RZ_NULLABLE LocalPureVar *local_pure_var_stack
274 #define VALIDATOR_PURE_NAME(op) validate_pure_##op
275 #define VALIDATOR_PURE(op) static bool VALIDATOR_PURE_NAME(op)(VALIDATOR_PURE_ARGS)
276 #define VALIDATOR_ASSERT(condition, ...) \
278 if (!(condition)) { \
279 rz_strbuf_appendf(report_builder, __VA_ARGS__); \
283 #define VALIDATOR_DESCEND(op, sort) \
285 if (!validate_pure(op, sort, report_builder, ctx, local_pure_var_stack)) { \
293 switch (
args->kind) {
308 if (!strcmp(loc->name,
args->v)) {
309 *sort_out = loc->sort;
330 rz_strbuf_appendf(report_builder,
"Bitvector in constant bitvector op is NULL.\n");
368 rz_strbuf_appendf(report_builder,
"Types of ite branches do not agree: %s vs. %s.\n",
388 .next = local_pure_var_stack
505 ut32 key_len = htm >> 32;
510 VALIDATOR_ASSERT(sk.
props.
bv.length == key_len,
"Length of key operand (%u) of load op is not equal to key length %u of mem %u.\n",
511 (
unsigned int)sk.
props.
bv.length, (
unsigned int)key_len, (
unsigned int)
args->mem);
522 ut32 key_len = htm >> 32;
526 VALIDATOR_ASSERT(sk.
props.
bv.length == key_len,
"Length of key operand (%u) of loadw op is not equal to key length %u of mem %u.\n",
527 (
unsigned int)sk.
props.
bv.length, (
unsigned int)key_len, (
unsigned int)
args->mem);
573 return validator(
op, sort_out, report_builder,
ctx, local_pure_var_stack);
616 #undef VALIDATOR_PURE_ARGS
617 #undef VALIDATOR_PURE_NAME
618 #undef VALIDATOR_PURE
619 #undef VALIDATOR_DESCEND
622 #define VALIDATOR_EFFECT_ARGS \
623 RZ_NULLABLE RzILOpEffect *op, \
624 RZ_NONNULL RzILTypeEffect *type_out, \
625 RZ_NONNULL RzStrBuf *report_builder, \
626 RZ_NONNULL LocalContext *ctx
632 #define VALIDATOR_EFFECT_NAME(op) validate_effect_##op
633 #define VALIDATOR_EFFECT(op) static bool VALIDATOR_EFFECT_NAME(op)(VALIDATOR_EFFECT_ARGS)
634 #define VALIDATOR_DESCEND_PURE(op, sort) \
636 if (!validate_pure(op, sort, report_builder, ctx, NULL)) { \
640 #define VALIDATOR_DESCEND_EFFECT(op, etype, ectx, cleanup) \
642 if (!validate_effect(op, etype, report_builder, ectx)) { \
643 cleanup return false; \
662 ut32 key_len = htm >> 32;
667 VALIDATOR_ASSERT(sk.
props.
bv.length == key_len,
"Length of key operand (%u) of store op is not equal to key length %u of mem %u.\n",
668 (
unsigned int)sk.
props.
bv.length, (
unsigned int)key_len, (
unsigned int)
args->mem);
672 VALIDATOR_ASSERT(sv.
props.
bv.length == val_len,
"Length of value operand (%u) of store op is not equal to value length %u of mem %u.\n",
673 (
unsigned int)sv.
props.
bv.length, (
unsigned int)val_len, (
unsigned int)
args->mem);
683 ut32 key_len = htm >> 32;
687 VALIDATOR_ASSERT(sk.
props.
bv.length == key_len,
"Length of key operand (%u) of storew op is not equal to key length %u of mem %u.\n",
688 (
unsigned int)sk.
props.
bv.length, (
unsigned int)key_len, (
unsigned int)
args->mem);
702 args->is_local ?
ctx->local_vars_known :
ctx->global_ctx->global_vars,
args->v,
NULL);
707 rz_strbuf_appendf(report_builder,
"Types of %sal variable \"%s\" and set op do not agree: %s vs. %s.\n",
708 args->is_local ?
"loc" :
"glob",
714 if (
args->is_local) {
721 ht_pp_update(
ctx->local_vars_known,
args->v,
sort);
723 ht_pp_update(
ctx->local_vars_available,
args->v,
sort);
735 "Length of dst operand (%u) of jmp op is not equal to pc length %u.\n",
736 (
unsigned int)sd.
props.
bv.length, (
unsigned int)
ctx->global_ctx->pc_len);
834 return validator(
op, type_out, report_builder,
ctx);
861 if (
valid && local_var_sorts_out) {
static RzILOpEffect * cmp(cs_insn *insn, bool is_thumb)
static RZ_NULLABLE RzILOpBitVector * shift(RzILOpBitVector *val, RZ_NULLABLE RzILOpBool **carry_out, arm_shifter type, RZ_OWN RzILOpBitVector *dist)
RZ_API void Ht_() free(HtName_(Ht) *ht)
RZ_API const KEY_TYPE bool * found
RZ_API ut32 rz_il_mem_key_len(RzILMem *mem)
Get the bit-size of a key (address) into the memory.
RZ_API ut32 rz_il_mem_value_len(RzILMem *mem)
Get the bit-size of a value in the memory.
RZ_API RZ_NONNULL const char * rz_il_op_pure_code_stringify(RzILOpPureCode code)
RZ_API RZ_OWN char * rz_il_sort_pure_stringify(RzILSortPure sort)
#define VALIDATOR_EFFECT_NAME(op)
#define VALIDATOR_PURE_ARGS
RZ_API void rz_il_validate_global_context_free(RzILValidateGlobalContext *ctx)
#define VALIDATOR_ASSERT(condition,...)
static void local_context_fini(LocalContext *ctx)
static bool local_context_meet(RZ_INOUT LocalContext *a, RZ_IN LocalContext *b, RzStrBuf *report_builder, const char *op_name)
static bool local_var_meet_known_cb(RZ_NONNULL void *user, const void *k, const void *v)
RZ_API bool rz_il_validate_pure(RZ_NULLABLE RzILOpPure *op, RZ_NONNULL RzILValidateGlobalContext *ctx, RZ_NULLABLE RZ_OUT RzILSortPure *sort_out, RZ_NULLABLE RZ_OUT RzILValidateReport *report_out)
#define VALIDATOR_PURE(op)
RZ_API void rz_il_validate_global_context_add_mem(RzILValidateGlobalContext *ctx, RzILMemIndex idx, ut32 key_len, ut32 val_len)
RZ_API void rz_il_validate_global_context_add_var(RzILValidateGlobalContext *ctx, RZ_NONNULL const char *name, RzILSortPure sort)
#define VALIDATOR_EFFECT_ARGS
static void var_kv_free(HtPPKv *kv)
static bool local_context_copy(LocalContext *dst, LocalContext *src)
#define VALIDATOR_DESCEND_EFFECT(op, etype, ectx, cleanup)
#define VALIDATOR_DESCEND_PURE(op, sort)
static bool local_var_meet_avail_cb(RZ_NONNULL void *user, const void *k, const void *v)
static ValidatePureFn validate_pure_table[RZ_IL_OP_PURE_MAX]
#define VALIDATOR_PURE_NAME(op)
static bool local_var_copy_avail_cb(RZ_NONNULL void *user, const void *k, const void *v)
static bool validate_effect(VALIDATOR_EFFECT_ARGS)
bool(* ValidatePureFn)(VALIDATOR_PURE_ARGS)
static bool local_context_init(LocalContext *ctx, const RzILValidateGlobalContext *global_ctx)
RZ_API RzILValidateGlobalContext * rz_il_validate_global_context_new_from_vm(RZ_NONNULL RzILVM *vm)
#define VALIDATOR_EFFECT(op)
static bool local_var_copy_known_cb(RZ_NONNULL void *user, const void *k, const void *v)
RZ_API RzILValidateGlobalContext * rz_il_validate_global_context_new_empty(ut32 pc_len)
RZ_API bool rz_il_validate_effect(RZ_NULLABLE RzILOpEffect *op, RZ_NONNULL RzILValidateGlobalContext *ctx, RZ_NULLABLE RZ_OUT HtPP **local_var_sorts_out, RZ_NULLABLE RZ_OUT RzILTypeEffect *type_out, RZ_NULLABLE RZ_OUT RzILValidateReport *report_out)
struct local_pure_var_t LocalPureVar
static ValidateEffectFn validate_effect_table[RZ_IL_OP_EFFECT_MAX]
static bool validate_pure(VALIDATOR_PURE_ARGS)
#define VALIDATOR_DESCEND(op, sort)
bool(* ValidateEffectFn)(VALIDATOR_EFFECT_ARGS)
static void var_kv_unown_free(HtPPKv *kv)
RZ_API RZ_OWN RzPVector * rz_il_vm_get_all_vars(RZ_NONNULL RzILVM *vm, RzILVarKind kind)
RZ_API ut32 rz_il_vm_get_pc_len(RzILVM *vm)
void * load(const char *name, size_t *len)
static void repeat(struct parse *, sopno, int, int)
#define rz_return_if_fail(expr)
#define rz_return_val_if_fail(expr, val)
RZ_API ut32 rz_bv_len(RZ_NONNULL const RzBitVector *bv)
Validation/Type Checking of RzIL Code.
char * RzILValidateReport
RZ_API RZ_BORROW char * rz_str_trim_tail(RZ_NONNULL char *str)
Removes whitespace characters (space, tab, newline etc.) from the end of a string and replaces them w...
static const char * rz_str_get_null(const char *str)
RZ_API RZ_OWN char * rz_strbuf_drain_nofree(RzStrBuf *sb)
RZ_API void rz_strbuf_fini(RzStrBuf *sb)
RZ_API bool rz_strbuf_appendf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API void rz_strbuf_init(RzStrBuf *sb)
RZ_API bool rz_strbuf_is_empty(RzStrBuf *sb)
static size_t rz_pvector_len(const RzPVector *vec)
RZ_API void rz_pvector_free(RzPVector *vec)
static void * rz_pvector_at(const RzPVector *vec, size_t index)
#define rz_pvector_foreach(vec, it)
static bool rz_il_sort_pure_eq(RzILSortPure a, RzILSortPure b)
@ RZ_IL_TYPE_EFFECT_DATA
mutating mems, vars, etc.
@ RZ_IL_TYPE_EFFECT_CTRL
jmp/goto
@ RZ_IL_TYPE_EFFECT_NONE
nop
static RzILSortPure rz_il_sort_pure_bool()
@ RZ_IL_TYPE_PURE_BITVECTOR
static RzILSortPure rz_il_sort_pure_bv(ut32 length)
RzStrBuf * report_builder
HtPP * local_vars_available
vars that can be accessed right now
const RzILValidateGlobalContext * global_ctx
struct local_pure_var_t * next
A single memory as part of the RzIL VM.
op structure for inv (!bool -> bool)
op structure for branch (bool -> 'a eff -> 'a eff -> 'a eff)
op structure for casting bitv
op structure for binary comparison ops ('a bitv -> 'a bitv -> bool)
op structure for goto (label -> ctrl eff)
op structure for ite (bool -> 'a pure -> 'a pure -> 'a pure)
op structure for jmp (_ bitv -> ctrl eff)
op structure for let_ : 'a var -> 'a pure -> 'b pure -> 'b pure
op structure for load (('a, 'b) mem -> 'a bitv -> 'b bitv)
Load an entire word of arbitrary bit size from a memory.
op structure for Seq ('a eff -> 'a eff -> 'a eff)
op structure for set ('a var -> 'a pure -> data eff)
op structure for lshift and rshift (bool -> 's bitv -> 'b bitv -> 's bitv)
op structure for store (('a, 'b) mem -> 'a bitv -> 'b bitv -> ('a, 'b) mem)
Store an entire word of arbitrary bit size into a memory.
op structure for var ('a var -> 'a pure)
An IL op performing a pure computation, 'a pure.
struct rz_il_sort_pure_t::@283::@284 bv
union rz_il_sort_pure_t::@283 props
Definition of a variable inside the vm.
RzILSortPure sort
"type" of the variable
Low-level VM to execute raw IL code.
op structure for blk (label -> data eff -> ctrl eff -> unit eff)
op structure for repeat (bool -> data eff -> data eff)
@ 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,...
ut64(WINAPI *w32_GetEnabledXStateFeatures)()