Rizin
unix-like reverse engineering framework and cli tools
il_validate.c File Reference
#include <rz_il/rz_il_validate.h>
#include <ht_uu.h>

Go to the source code of this file.

Classes

struct  rz_il_validate_global_context_t
 
struct  LocalContext
 
struct  LocalContextMeet
 
struct  local_pure_var_t
 

Functions

static void var_kv_free (HtPPKv *kv)
 
static void var_kv_unown_free (HtPPKv *kv)
 
RZ_API RzILValidateGlobalContextrz_il_validate_global_context_new_empty (ut32 pc_len)
 
RZ_API void rz_il_validate_global_context_add_var (RzILValidateGlobalContext *ctx, RZ_NONNULL const char *name, RzILSortPure sort)
 
RZ_API void rz_il_validate_global_context_add_mem (RzILValidateGlobalContext *ctx, RzILMemIndex idx, ut32 key_len, ut32 val_len)
 
RZ_API RzILValidateGlobalContextrz_il_validate_global_context_new_from_vm (RZ_NONNULL RzILVM *vm)
 
RZ_API void rz_il_validate_global_context_free (RzILValidateGlobalContext *ctx)
 
static bool local_context_init (LocalContext *ctx, const RzILValidateGlobalContext *global_ctx)
 
static void local_context_fini (LocalContext *ctx)
 
static bool local_var_copy_known_cb (RZ_NONNULL void *user, const void *k, const void *v)
 
static bool local_var_copy_avail_cb (RZ_NONNULL void *user, const void *k, const void *v)
 
static bool local_context_copy (LocalContext *dst, LocalContext *src)
 
static bool local_var_meet_known_cb (RZ_NONNULL void *user, const void *k, const void *v)
 
static bool local_var_meet_avail_cb (RZ_NONNULL void *user, const void *k, const void *v)
 
static bool local_context_meet (RZ_INOUT LocalContext *a, RZ_IN LocalContext *b, RzStrBuf *report_builder, const char *op_name)
 

Pure

#define VALIDATOR_PURE_ARGS
 
#define VALIDATOR_PURE_NAME(op)   validate_pure_##op
 
#define VALIDATOR_PURE(op)   static bool VALIDATOR_PURE_NAME(op)(VALIDATOR_PURE_ARGS)
 
#define VALIDATOR_ASSERT(condition, ...)
 
#define VALIDATOR_DESCEND(op, sort)
 
typedef struct local_pure_var_t LocalPureVar
 
typedef bool(* ValidatePureFn) (VALIDATOR_PURE_ARGS)
 
static ValidatePureFn validate_pure_table [RZ_IL_OP_PURE_MAX]
 
static bool validate_pure (VALIDATOR_PURE_ARGS)
 
 VALIDATOR_PURE (var)
 
 VALIDATOR_PURE (bool_const)
 
 VALIDATOR_PURE (bitv)
 
 VALIDATOR_PURE (bitv_binop)
 
 VALIDATOR_PURE (ite)
 
 VALIDATOR_PURE (let)
 
 VALIDATOR_PURE (inv)
 
 VALIDATOR_PURE (bool_binop)
 
 VALIDATOR_PURE (bitv_bool_unop)
 
 VALIDATOR_PURE (bitv_unop)
 
 VALIDATOR_PURE (shift)
 
 VALIDATOR_PURE (cmp)
 
 VALIDATOR_PURE (cast)
 
 VALIDATOR_PURE (append)
 
 VALIDATOR_PURE (load)
 
 VALIDATOR_PURE (loadw)
 
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)
 

Effect

#define VALIDATOR_EFFECT_ARGS
 
#define VALIDATOR_EFFECT_NAME(op)   validate_effect_##op
 
#define VALIDATOR_EFFECT(op)   static bool VALIDATOR_EFFECT_NAME(op)(VALIDATOR_EFFECT_ARGS)
 
#define VALIDATOR_DESCEND_PURE(op, sort)
 
#define VALIDATOR_DESCEND_EFFECT(op, etype, ectx, cleanup)
 
typedef bool(* ValidateEffectFn) (VALIDATOR_EFFECT_ARGS)
 
static ValidateEffectFn validate_effect_table [RZ_IL_OP_EFFECT_MAX]
 
static bool validate_effect (VALIDATOR_EFFECT_ARGS)
 
 VALIDATOR_EFFECT (empty)
 
 VALIDATOR_EFFECT (nop)
 
 VALIDATOR_EFFECT (store)
 
 VALIDATOR_EFFECT (storew)
 
 VALIDATOR_EFFECT (set)
 
 VALIDATOR_EFFECT (jmp)
 
 VALIDATOR_EFFECT (goto)
 
 VALIDATOR_EFFECT (seq)
 
 VALIDATOR_EFFECT (blk)
 
 VALIDATOR_EFFECT (repeat)
 
 VALIDATOR_EFFECT (branch)
 
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)
 

Macro Definition Documentation

◆ VALIDATOR_ASSERT

#define VALIDATOR_ASSERT (   condition,
  ... 
)
Value:
do { \
if (!(condition)) { \
rz_strbuf_appendf(report_builder, __VA_ARGS__); \
return false; \
} \
} while (0)

Definition at line 276 of file il_validate.c.

◆ VALIDATOR_DESCEND

#define VALIDATOR_DESCEND (   op,
  sort 
)
Value:
do { \
if (!validate_pure(op, sort, report_builder, ctx, local_pure_var_stack)) { \
return false; \
} \
} while (0)
static bool validate_pure(VALIDATOR_PURE_ARGS)
Definition: il_validate.c:569
Definition: dis.c:32

Definition at line 283 of file il_validate.c.

◆ VALIDATOR_DESCEND_EFFECT

#define VALIDATOR_DESCEND_EFFECT (   op,
  etype,
  ectx,
  cleanup 
)
Value:
do { \
if (!validate_effect(op, etype, report_builder, ectx)) { \
cleanup return false; \
} \
} while (0)
static bool validate_effect(VALIDATOR_EFFECT_ARGS)
Definition: il_validate.c:830

Definition at line 640 of file il_validate.c.

◆ VALIDATOR_DESCEND_PURE

#define VALIDATOR_DESCEND_PURE (   op,
  sort 
)
Value:
do { \
if (!validate_pure(op, sort, report_builder, ctx, NULL)) { \
return false; \
} \
} while (0)
#define NULL
Definition: cris-opc.c:27

Definition at line 634 of file il_validate.c.

◆ VALIDATOR_EFFECT

#define VALIDATOR_EFFECT (   op)    static bool VALIDATOR_EFFECT_NAME(op)(VALIDATOR_EFFECT_ARGS)

Definition at line 633 of file il_validate.c.

◆ VALIDATOR_EFFECT_ARGS

#define VALIDATOR_EFFECT_ARGS
Value:
RZ_NONNULL RzILTypeEffect *type_out, \
RZ_NONNULL RzStrBuf *report_builder, \
RZ_NONNULL LocalContext *ctx
ut8 op
Definition: 6502dis.c:13
#define RZ_NULLABLE
Definition: rz_types.h:65
RzILTypeEffect
Definition: sort.h:66

Definition at line 622 of file il_validate.c.

◆ VALIDATOR_EFFECT_NAME

#define VALIDATOR_EFFECT_NAME (   op)    validate_effect_##op

Definition at line 632 of file il_validate.c.

◆ VALIDATOR_PURE

#define VALIDATOR_PURE (   op)    static bool VALIDATOR_PURE_NAME(op)(VALIDATOR_PURE_ARGS)

Definition at line 275 of file il_validate.c.

◆ VALIDATOR_PURE_ARGS

#define VALIDATOR_PURE_ARGS
Value:
RZ_NONNULL RzILSortPure *sort_out, \
RZ_NONNULL RzStrBuf *report_builder, \
RZ_NONNULL const LocalContext *ctx, \
RZ_NULLABLE LocalPureVar *local_pure_var_stack
An IL op performing a pure computation, 'a pure.

Definition at line 263 of file il_validate.c.

◆ VALIDATOR_PURE_NAME

#define VALIDATOR_PURE_NAME (   op)    validate_pure_##op

Definition at line 274 of file il_validate.c.

Typedef Documentation

◆ LocalPureVar

Linked list (stack) of let-bound vars

While descending, new var definitions are pushed, thus shadowing other vars of the same name when searching from the head.

◆ ValidateEffectFn

typedef bool(* ValidateEffectFn) (VALIDATOR_EFFECT_ARGS)

Definition at line 630 of file il_validate.c.

◆ ValidatePureFn

typedef bool(* ValidatePureFn) (VALIDATOR_PURE_ARGS)

Definition at line 272 of file il_validate.c.

Function Documentation

◆ local_context_copy()

static bool local_context_copy ( LocalContext dst,
LocalContext src 
)
static

Definition at line 161 of file il_validate.c.

161  {
162  if (!local_context_init(dst, src->global_ctx)) {
163  return false;
164  }
165  ht_pp_foreach(src->local_vars_known, local_var_copy_known_cb, dst);
166  ht_pp_foreach(src->local_vars_available, local_var_copy_avail_cb, dst);
167  return true;
168 }
lzma_index * src
Definition: index.h:567
static bool local_var_copy_avail_cb(RZ_NONNULL void *user, const void *k, const void *v)
Definition: il_validate.c:152
static bool local_context_init(LocalContext *ctx, const RzILValidateGlobalContext *global_ctx)
Definition: il_validate.c:122
static bool local_var_copy_known_cb(RZ_NONNULL void *user, const void *k, const void *v)
Definition: il_validate.c:141
char * dst
Definition: lz4.h:724

References dst, local_context_init(), local_var_copy_avail_cb(), local_var_copy_known_cb(), and src.

Referenced by VALIDATOR_EFFECT().

◆ local_context_fini()

static void local_context_fini ( LocalContext ctx)
static

Definition at line 136 of file il_validate.c.

136  {
137  ht_pp_free(ctx->local_vars_known);
138  ht_pp_free(ctx->local_vars_available);
139 }

Referenced by rz_il_validate_effect(), rz_il_validate_pure(), and VALIDATOR_EFFECT().

◆ local_context_init()

static bool local_context_init ( LocalContext ctx,
const RzILValidateGlobalContext global_ctx 
)
static

Definition at line 122 of file il_validate.c.

122  {
123  ctx->global_ctx = global_ctx;
124  ctx->local_vars_known = ht_pp_new(NULL, var_kv_free, NULL);
125  if (!ctx->local_vars_known) {
126  return false;
127  }
128  ctx->local_vars_available = ht_pp_new(NULL, var_kv_unown_free, NULL);
129  if (!ctx->local_vars_available) {
130  ht_pp_free(ctx->local_vars_known);
131  return false;
132  }
133  return true;
134 }
static void var_kv_free(HtPPKv *kv)
Definition: il_validate.c:19
static void var_kv_unown_free(HtPPKv *kv)
Definition: il_validate.c:24

References NULL, var_kv_free(), and var_kv_unown_free().

Referenced by local_context_copy(), rz_il_validate_effect(), and rz_il_validate_pure().

◆ local_context_meet()

static bool local_context_meet ( RZ_INOUT LocalContext a,
RZ_IN LocalContext b,
RzStrBuf report_builder,
const char *  op_name 
)
static

Meet (intersection) of two contexts, usually when two control flow paths meet. Known types for local vars are always kept from both, to ensure they always have the same type in the entire expression. Available local vars are intersected. This fails when a and b both know about a local var, but don't agree about its type.

a First input operand, this will also be modified in-place to contain the result. b Second input operand, will not be modified. report_builder On failure, will be appended with an error message op_name Name of the op in which the meet is being performed, for the error message

Returns
whether the meet succeeded

Definition at line 228 of file il_validate.c.

228  {
229  LocalContextMeet meet = {
230  .failed = false,
231  .report_builder = report_builder,
232  .op_name = op_name,
233  .dst = a,
234  .src = b
235  };
236  ht_pp_foreach(b->local_vars_known, local_var_meet_known_cb, &meet);
237  if (meet.failed) {
238  return false;
239  }
240  ht_pp_foreach(a->local_vars_available, local_var_meet_avail_cb, &meet);
241  return true;
242 }
static bool local_var_meet_known_cb(RZ_NONNULL void *user, const void *k, const void *v)
Definition: il_validate.c:179
static bool local_var_meet_avail_cb(RZ_NONNULL void *user, const void *k, const void *v)
Definition: il_validate.c:206
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41

References a, b, LocalContextMeet::failed, local_var_meet_avail_cb(), and local_var_meet_known_cb().

Referenced by VALIDATOR_EFFECT().

◆ local_var_copy_avail_cb()

static bool local_var_copy_avail_cb ( RZ_NONNULL void *  user,
const void *  k,
const void *  v 
)
static

Definition at line 152 of file il_validate.c.

152  {
153  LocalContext *dst = user;
154  RzILSortPure *sort = ht_pp_find(dst->local_vars_known, k, NULL);
155  // known is superset of avail, so we can assert this:
156  rz_return_val_if_fail(sort && rz_il_sort_pure_eq(*sort, *(RzILSortPure *)v), false);
157  ht_pp_update(dst->local_vars_available, k, sort);
158  return true;
159 }
const char * k
Definition: dsignal.c:11
const char * v
Definition: dsignal.c:12
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
static bool rz_il_sort_pure_eq(RzILSortPure a, RzILSortPure b)
Definition: sort.h:37

References dst, k, NULL, rz_il_sort_pure_eq(), rz_return_val_if_fail, and v.

Referenced by local_context_copy().

◆ local_var_copy_known_cb()

static bool local_var_copy_known_cb ( RZ_NONNULL void *  user,
const void *  k,
const void *  v 
)
static

Definition at line 141 of file il_validate.c.

141  {
142  LocalContext *dst = user;
144  if (!sort) {
145  return false;
146  }
147  *sort = *(RzILSortPure *)v;
148  ht_pp_update(dst->local_vars_known, k, sort);
149  return true;
150 }
#define RZ_NEW(x)
Definition: rz_types.h:285

References dst, k, RZ_NEW, and v.

Referenced by local_context_copy().

◆ local_var_meet_avail_cb()

static bool local_var_meet_avail_cb ( RZ_NONNULL void *  user,
const void *  k,
const void *  v 
)
static

Definition at line 206 of file il_validate.c.

206  {
207  LocalContextMeet *meet = user;
208  RzILSortPure *src_sort = ht_pp_find(meet->src->local_vars_available, k, NULL);
209  if (!src_sort) {
210  ht_pp_delete(meet->dst->local_vars_available, k);
211  }
212  return true;
213 }
LocalContext * dst
Definition: il_validate.c:174
LocalContext * src
Definition: il_validate.c:175
HtPP * local_vars_available
vars that can be accessed right now
Definition: il_validate.c:119

References LocalContextMeet::dst, k, LocalContext::local_vars_available, NULL, and LocalContextMeet::src.

Referenced by local_context_meet().

◆ local_var_meet_known_cb()

static bool local_var_meet_known_cb ( RZ_NONNULL void *  user,
const void *  k,
const void *  v 
)
static

Definition at line 179 of file il_validate.c.

179  {
180  LocalContextMeet *meet = user;
181  RzILSortPure src_sort = *(RzILSortPure *)v;
182  RzILSortPure *dst_sort = ht_pp_find(meet->dst->local_vars_known, k, NULL);
183  if (dst_sort && !rz_il_sort_pure_eq(src_sort, *dst_sort)) {
184  char *src_sort_s = rz_il_sort_pure_stringify(src_sort);
185  char *dst_sort_s = rz_il_sort_pure_stringify(*dst_sort);
186  rz_strbuf_appendf(meet->report_builder, "Control flow paths from %s op do not agree on the type of local variable \"%s\": %s vs. %s.\n",
187  meet->op_name, (const char *)k, src_sort_s, dst_sort_s);
188  free(src_sort_s);
189  free(dst_sort_s);
190  meet->failed = true;
191  return false;
192  }
193  if (!dst_sort) {
194  dst_sort = RZ_NEW(RzILSortPure);
195  if (!dst_sort) {
196  meet->failed = true;
197  return false;
198  }
199  *dst_sort = src_sort;
200  ht_pp_update(meet->dst->local_vars_known, k, dst_sort);
201  }
202  return true;
203 }
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
RZ_API RZ_OWN char * rz_il_sort_pure_stringify(RzILSortPure sort)
Definition: il_export.c:952
RZ_API bool rz_strbuf_appendf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
const char * op_name
Definition: il_validate.c:173
RzStrBuf * report_builder
Definition: il_validate.c:172
HtPP * local_vars_known
Definition: il_validate.c:117

References LocalContextMeet::dst, LocalContextMeet::failed, free(), k, LocalContext::local_vars_known, NULL, LocalContextMeet::op_name, LocalContextMeet::report_builder, rz_il_sort_pure_eq(), rz_il_sort_pure_stringify(), RZ_NEW, rz_strbuf_appendf(), and v.

Referenced by local_context_meet().

◆ rz_il_validate_effect()

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 
)

Run validation (type-checking and other checks) on an effect. op the op to be checked. May be null, which will always be reported as invalid. ctx global context, defining available global vars and mems local_var_sorts_out optionally returns a map of local variable names defined in the effect to their sorts type_put optionally returns the type of effects that the ops perform, i.e. ctrl, data, both or none report_out optionally returns a readable report containing details about why the validation failed

Returns
whether the given op is valid under ctx

Definition at line 846 of file il_validate.c.

849  {
850  LocalContext local_ctx;
851  if (!local_context_init(&local_ctx, ctx)) {
852  if (report_out) {
853  *report_out = NULL;
854  }
855  return false;
856  }
858  RzStrBuf report_builder;
859  rz_strbuf_init(&report_builder);
860  bool valid = validate_effect(op, &type, &report_builder, &local_ctx);
861  if (valid && local_var_sorts_out) {
862  *local_var_sorts_out = local_ctx.local_vars_known;
863  local_ctx.local_vars_known = NULL;
864  }
865  local_context_fini(&local_ctx);
866  if (type_out) {
867  *type_out = type;
868  }
869  if (report_out) {
870  *report_out = rz_strbuf_is_empty(&report_builder) ? NULL : rz_str_trim_tail(rz_strbuf_drain_nofree(&report_builder));
871  }
872  rz_strbuf_fini(&report_builder);
873  return valid;
874 }
static void local_context_fini(LocalContext *ctx)
Definition: il_validate.c:136
int type
Definition: mipsasm.c:17
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...
Definition: str_trim.c:125
RZ_API RZ_OWN char * rz_strbuf_drain_nofree(RzStrBuf *sb)
Definition: strbuf.c:349
RZ_API void rz_strbuf_fini(RzStrBuf *sb)
Definition: strbuf.c:365
RZ_API void rz_strbuf_init(RzStrBuf *sb)
Definition: strbuf.c:33
RZ_API bool rz_strbuf_is_empty(RzStrBuf *sb)
Definition: strbuf.c:24
@ RZ_IL_TYPE_EFFECT_NONE
nop
Definition: sort.h:67
bool valid
Definition: core.c:77

References local_context_fini(), local_context_init(), LocalContext::local_vars_known, NULL, RZ_IL_TYPE_EFFECT_NONE, rz_str_trim_tail(), rz_strbuf_drain_nofree(), rz_strbuf_fini(), rz_strbuf_init(), rz_strbuf_is_empty(), type, valid, and validate_effect().

Referenced by print_and_check_il().

◆ rz_il_validate_global_context_add_mem()

RZ_API void rz_il_validate_global_context_add_mem ( RzILValidateGlobalContext ctx,
RzILMemIndex  idx,
ut32  key_len,
ut32  val_len 
)

Define a new memory in ctx

Definition at line 69 of file il_validate.c.

69  {
70  rz_return_if_fail(ctx && key_len && val_len);
71  ht_uu_update(ctx->mems, idx, ((ut64)key_len << 32) | (ut64)val_len);
72 }
int idx
Definition: setup.py:197
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References setup::idx, rz_return_if_fail, and ut64().

Referenced by rz_il_validate_global_context_new_from_vm().

◆ rz_il_validate_global_context_add_var()

RZ_API void rz_il_validate_global_context_add_var ( RzILValidateGlobalContext ctx,
RZ_NONNULL const char *  name,
RzILSortPure  sort 
)

Define a new global variable in ctx

Definition at line 56 of file il_validate.c.

56  {
59  if (!hts) {
60  return;
61  }
62  *hts = sort;
63  ht_pp_update(ctx->global_vars, name, hts);
64 }
Definition: z80asm.h:102

References RZ_NEW, and rz_return_if_fail.

Referenced by rz_il_validate_global_context_new_from_vm().

◆ rz_il_validate_global_context_free()

RZ_API void rz_il_validate_global_context_free ( RzILValidateGlobalContext ctx)

Definition at line 99 of file il_validate.c.

99  {
100  if (!ctx) {
101  return;
102  }
103  ht_pp_free(ctx->global_vars);
104  ht_uu_free(ctx->mems);
105  free(ctx);
106 }

References free().

Referenced by print_and_check_il().

◆ rz_il_validate_global_context_new_empty()

RZ_API RzILValidateGlobalContext* rz_il_validate_global_context_new_empty ( ut32  pc_len)

Create a new global context for validation Vars and mems can be added manually with rz_il_validate_global_context_add_* functions.

Definition at line 32 of file il_validate.c.

32  {
33  rz_return_val_if_fail(pc_len, NULL);
35  if (!ctx) {
36  return NULL;
37  }
38  ctx->pc_len = pc_len;
39  ctx->global_vars = ht_pp_new(NULL, var_kv_free, NULL);
40  if (!ctx->global_vars) {
41  free(ctx);
42  return NULL;
43  }
44  ctx->mems = ht_uu_new0();
45  if (!ctx->mems) {
46  ht_pp_free(ctx->global_vars);
47  free(ctx);
48  return NULL;
49  }
50  return ctx;
51 }
#define RZ_NEW0(x)
Definition: rz_types.h:284

References free(), NULL, RZ_NEW0, rz_return_val_if_fail, and var_kv_free().

Referenced by rz_il_validate_global_context_new_from_vm().

◆ rz_il_validate_global_context_new_from_vm()

RZ_API RzILValidateGlobalContext* rz_il_validate_global_context_new_from_vm ( RZ_NONNULL RzILVM vm)

Create a new context for IL validation based on the global vars and mems in vm

Definition at line 77 of file il_validate.c.

77  {
81  if (vars) {
82  void **it;
83  rz_pvector_foreach (vars, it) {
84  RzILVar *var = *it;
86  }
87  rz_pvector_free(vars);
88  }
89  for (size_t i = 0; i < rz_pvector_len(&vm->vm_memory); i++) {
90  RzILMem *mem = rz_pvector_at(&vm->vm_memory, i);
91  if (!mem) {
92  continue;
93  }
95  }
96  return ctx;
97 }
lzma_index ** i
Definition: index.h:629
RZ_API ut32 rz_il_mem_key_len(RzILMem *mem)
Get the bit-size of a key (address) into the memory.
Definition: mem.c:49
RZ_API ut32 rz_il_mem_value_len(RzILMem *mem)
Get the bit-size of a value in the memory.
Definition: mem.c:60
RZ_API void rz_il_validate_global_context_add_mem(RzILValidateGlobalContext *ctx, RzILMemIndex idx, ut32 key_len, ut32 val_len)
Definition: il_validate.c:69
RZ_API void rz_il_validate_global_context_add_var(RzILValidateGlobalContext *ctx, RZ_NONNULL const char *name, RzILSortPure sort)
Definition: il_validate.c:56
RZ_API RzILValidateGlobalContext * rz_il_validate_global_context_new_empty(ut32 pc_len)
Definition: il_validate.c:32
RZ_API RZ_OWN RzPVector * rz_il_vm_get_all_vars(RZ_NONNULL RzILVM *vm, RzILVarKind kind)
Definition: il_vm.c:256
RZ_API ut32 rz_il_vm_get_pc_len(RzILVM *vm)
Definition: il_vm.c:145
void * mem
Definition: libc.cpp:91
ut32 RzILMemIndex
Definition: mem.h:14
static size_t rz_pvector_len(const RzPVector *vec)
Definition: rz_vector.h:231
RZ_API void rz_pvector_free(RzPVector *vec)
Definition: vector.c:336
static void * rz_pvector_at(const RzPVector *vec, size_t index)
Definition: rz_vector.h:236
#define rz_pvector_foreach(vec, it)
Definition: rz_vector.h:334
A single memory as part of the RzIL VM.
Definition: mem.h:26
Definition of a variable inside the vm.
Definition: variable.h:19
RzILSortPure sort
"type" of the variable
Definition: variable.h:21
char * name
Definition: variable.h:20
@ RZ_IL_VAR_KIND_GLOBAL
global var, usually bound to a physical representation like a register.
Definition: variable.h:47

References i, mem, rz_il_var_t::name, NULL, rz_il_mem_key_len(), rz_il_mem_value_len(), rz_il_validate_global_context_add_mem(), rz_il_validate_global_context_add_var(), rz_il_validate_global_context_new_empty(), RZ_IL_VAR_KIND_GLOBAL, rz_il_vm_get_all_vars(), rz_il_vm_get_pc_len(), rz_pvector_at(), rz_pvector_foreach, rz_pvector_free(), rz_pvector_len(), rz_return_val_if_fail, and rz_il_var_t::sort.

Referenced by print_and_check_il().

◆ rz_il_validate_pure()

Run validation (type-checking and other checks) on a pure expression and determine its sort. op the op to be checked. May be null, which will always be reported as invalid. ctx global context, defining available global vars and mems sort_out optionally returns the sort of the expression, if it is valid report_out optionally returns a readable report containing details about why the validation failed

Returns
whether the given op is valid under ctx

Definition at line 584 of file il_validate.c.

585  {
586  LocalContext local_ctx;
587  if (!local_context_init(&local_ctx, ctx)) {
588  if (report_out) {
589  *report_out = NULL;
590  }
591  return false;
592  }
593  RzStrBuf report_builder;
594  rz_strbuf_init(&report_builder);
595  RzILSortPure sort = { 0 };
596  bool valid = validate_pure(op, &sort, &report_builder, &local_ctx, NULL);
597  local_context_fini(&local_ctx);
598  if (sort_out) {
599  *sort_out = sort;
600  }
601  if (report_out) {
602  *report_out = rz_strbuf_is_empty(&report_builder) ? NULL : rz_str_trim_tail(rz_strbuf_drain_nofree(&report_builder));
603  }
604  rz_strbuf_fini(&report_builder);
605  return valid;
606 }

References local_context_fini(), local_context_init(), NULL, rz_str_trim_tail(), rz_strbuf_drain_nofree(), rz_strbuf_fini(), rz_strbuf_init(), rz_strbuf_is_empty(), local_pure_var_t::sort, valid, and validate_pure().

◆ validate_effect()

static bool validate_effect ( VALIDATOR_EFFECT_ARGS  )
static

Definition at line 830 of file il_validate.c.

830  {
831  VALIDATOR_ASSERT(op, "Encountered NULL for effect op.\n");
833  rz_return_val_if_fail(validator, false);
834  return validator(op, type_out, report_builder, ctx);
835 }
#define VALIDATOR_ASSERT(condition,...)
Definition: il_validate.c:276
static ValidateEffectFn validate_effect_table[RZ_IL_OP_EFFECT_MAX]
Definition: il_validate.c:816
bool(* ValidateEffectFn)(VALIDATOR_EFFECT_ARGS)
Definition: il_validate.c:630
struct op_code code
Definition: dis.c:33

References op::code, rz_return_val_if_fail, validate_effect_table, and VALIDATOR_ASSERT.

Referenced by rz_il_validate_effect().

◆ validate_pure()

static bool validate_pure ( VALIDATOR_PURE_ARGS  )
static

Definition at line 569 of file il_validate.c.

569  {
570  VALIDATOR_ASSERT(op, "Encountered NULL for pure op.\n");
572  rz_return_val_if_fail(validator, false);
573  return validator(op, sort_out, report_builder, ctx, local_pure_var_stack);
574 }
static ValidatePureFn validate_pure_table[RZ_IL_OP_PURE_MAX]
Definition: il_validate.c:532
bool(* ValidatePureFn)(VALIDATOR_PURE_ARGS)
Definition: il_validate.c:272

References op::code, rz_return_val_if_fail, validate_pure_table, and VALIDATOR_ASSERT.

Referenced by rz_il_validate_pure(), and VALIDATOR_PURE().

◆ VALIDATOR_EFFECT() [1/11]

VALIDATOR_EFFECT ( blk  )

Definition at line 764 of file il_validate.c.

764  {
765  RzILOpArgsBlk *args = &op->op.blk;
766  // Semantics of blk are still somewhat undefined in RzIL
767  RzILTypeEffect td;
768  VALIDATOR_DESCEND_EFFECT(args->data_eff, &td, ctx, {});
769  VALIDATOR_ASSERT((td | RZ_IL_TYPE_EFFECT_DATA) == RZ_IL_TYPE_EFFECT_DATA, "Data effect operand of blk op does not only perform data effects.");
770  RzILTypeEffect tc;
771  VALIDATOR_DESCEND_EFFECT(args->ctrl_eff, &tc, ctx, {});
772  VALIDATOR_ASSERT((tc | RZ_IL_TYPE_EFFECT_CTRL) == RZ_IL_TYPE_EFFECT_CTRL, "Control effect operand of blk op does not only perform control effects.");
773  *type_out = td | tc;
774  return true;
775 }
#define VALIDATOR_DESCEND_EFFECT(op, etype, ectx, cleanup)
Definition: il_validate.c:640
int args
Definition: mipsasm.c:18
@ RZ_IL_TYPE_EFFECT_DATA
mutating mems, vars, etc.
Definition: sort.h:68
@ RZ_IL_TYPE_EFFECT_CTRL
jmp/goto
Definition: sort.h:69
op structure for blk (label -> data eff -> ctrl eff -> unit eff)

References args, RZ_IL_TYPE_EFFECT_CTRL, RZ_IL_TYPE_EFFECT_DATA, VALIDATOR_ASSERT, and VALIDATOR_DESCEND_EFFECT.

◆ VALIDATOR_EFFECT() [2/11]

VALIDATOR_EFFECT ( branch  )

Definition at line 797 of file il_validate.c.

797  {
798  RzILOpArgsBranch *args = &op->op.branch;
800  VALIDATOR_DESCEND_PURE(args->condition, &sc);
801  VALIDATOR_ASSERT(sc.type == RZ_IL_TYPE_PURE_BOOL, "Condition of branch op is not boolean.\n");
802  LocalContext false_ctx;
803  if (!local_context_copy(&false_ctx, ctx)) {
804  return false;
805  }
806  RzILTypeEffect tt;
807  VALIDATOR_DESCEND_EFFECT(args->true_eff, &tt, ctx, { local_context_fini(&false_ctx); });
808  RzILTypeEffect tf;
809  VALIDATOR_DESCEND_EFFECT(args->false_eff, &tf, &false_ctx, { local_context_fini(&false_ctx); });
810  bool val = local_context_meet(ctx, &false_ctx, report_builder, "branch");
811  local_context_fini(&false_ctx);
812  *type_out = tt | tf;
813  return val;
814 }
ut16 val
Definition: armass64_const.h:6
static char sc[]
Definition: egg_cb.c:6
static bool local_context_meet(RZ_INOUT LocalContext *a, RZ_IN LocalContext *b, RzStrBuf *report_builder, const char *op_name)
Definition: il_validate.c:228
static bool local_context_copy(LocalContext *dst, LocalContext *src)
Definition: il_validate.c:161
#define VALIDATOR_DESCEND_PURE(op, sort)
Definition: il_validate.c:634
@ RZ_IL_TYPE_PURE_BOOL
Definition: sort.h:24
op structure for branch (bool -> 'a eff -> 'a eff -> 'a eff)

References args, local_context_copy(), local_context_fini(), local_context_meet(), RZ_IL_TYPE_PURE_BOOL, sc, val, VALIDATOR_ASSERT, VALIDATOR_DESCEND_EFFECT, and VALIDATOR_DESCEND_PURE.

◆ VALIDATOR_EFFECT() [3/11]

VALIDATOR_EFFECT ( empty  )

Definition at line 647 of file il_validate.c.

647  {
648  *type_out = RZ_IL_TYPE_EFFECT_NONE;
649  return true;
650 }

References RZ_IL_TYPE_EFFECT_NONE.

◆ VALIDATOR_EFFECT() [4/11]

VALIDATOR_EFFECT ( goto  )

Definition at line 741 of file il_validate.c.

741  {
742  RzILOpArgsGoto *args = &op->op.goto_;
743  VALIDATOR_ASSERT(args->lbl, "Label of goto op is NULL.\n");
744  // So far, no restrictions on goto because labels are dynamically created. This might change in the future.
745  *type_out = RZ_IL_TYPE_EFFECT_CTRL;
746  return true;
747 }
op structure for goto (label -> ctrl eff)

References args, RZ_IL_TYPE_EFFECT_CTRL, and VALIDATOR_ASSERT.

◆ VALIDATOR_EFFECT() [5/11]

VALIDATOR_EFFECT ( jmp  )

Definition at line 729 of file il_validate.c.

729  {
730  RzILOpArgsJmp *args = &op->op.jmp;
731  RzILSortPure sd;
732  VALIDATOR_DESCEND_PURE(args->dst, &sd);
733  VALIDATOR_ASSERT(sd.type == RZ_IL_TYPE_PURE_BITVECTOR, "Dst operand of jmp op is not a bitvector.\n");
734  VALIDATOR_ASSERT(sd.props.bv.length == ctx->global_ctx->pc_len,
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);
737  *type_out = RZ_IL_TYPE_EFFECT_CTRL;
738  return true;
739 }
@ RZ_IL_TYPE_PURE_BITVECTOR
Definition: sort.h:25
op structure for jmp (_ bitv -> ctrl eff)
struct rz_il_sort_pure_t::@283::@284 bv
union rz_il_sort_pure_t::@283 props
RzILTypePure type
Definition: sort.h:29

References args, rz_il_sort_pure_t::bv, rz_il_sort_pure_t::props, RZ_IL_TYPE_EFFECT_CTRL, RZ_IL_TYPE_PURE_BITVECTOR, rz_il_sort_pure_t::type, VALIDATOR_ASSERT, and VALIDATOR_DESCEND_PURE.

◆ VALIDATOR_EFFECT() [6/11]

VALIDATOR_EFFECT ( nop  )

Definition at line 652 of file il_validate.c.

652  {
653  *type_out = RZ_IL_TYPE_EFFECT_NONE;
654  return true;
655 }

References RZ_IL_TYPE_EFFECT_NONE.

◆ VALIDATOR_EFFECT() [7/11]

VALIDATOR_EFFECT ( repeat  )

Definition at line 777 of file il_validate.c.

777  {
778  RzILOpArgsRepeat *args = &op->op.repeat;
780  VALIDATOR_DESCEND_PURE(args->condition, &sc);
781  VALIDATOR_ASSERT(sc.type == RZ_IL_TYPE_PURE_BOOL, "Condition of repeat op is not boolean.\n");
782  LocalContext loop_ctx;
783  if (!local_context_copy(&loop_ctx, ctx)) {
784  return false;
785  }
786  RzILTypeEffect t;
787  VALIDATOR_DESCEND_EFFECT(args->data_eff, &t, ctx, { local_context_fini(&loop_ctx); });
788  // Enforce (by overapproximation) that there are no effects after a ctrl effect, like in seq.
789  // In a loop, we just reject ctrl completely. This also matches BAP's `repeat : bool -> data eff -> data eff`.
790  VALIDATOR_ASSERT((t | RZ_IL_TYPE_EFFECT_DATA) == RZ_IL_TYPE_EFFECT_DATA, "Body operand of repeat op does not only perform data effects.");
791  bool val = local_context_meet(ctx, &loop_ctx, report_builder, "repeat");
792  local_context_fini(&loop_ctx);
793  *type_out = t;
794  return val;
795 }
op structure for repeat (bool -> data eff -> data eff)

References args, local_context_copy(), local_context_fini(), local_context_meet(), RZ_IL_TYPE_EFFECT_DATA, RZ_IL_TYPE_PURE_BOOL, sc, val, VALIDATOR_ASSERT, VALIDATOR_DESCEND_EFFECT, and VALIDATOR_DESCEND_PURE.

◆ VALIDATOR_EFFECT() [8/11]

VALIDATOR_EFFECT ( seq  )

Definition at line 749 of file il_validate.c.

749  {
750  RzILOpArgsSeq *args = &op->op.seq;
751  RzILTypeEffect tx;
752  VALIDATOR_DESCEND_EFFECT(args->x, &tx, ctx, {});
753  RzILTypeEffect ty;
754  VALIDATOR_DESCEND_EFFECT(args->y, &ty, ctx, {});
755  // Code after a jmp/goto makes no sense because the jmp naturally jumps somewhere else already.
756  // Intuitively, this could be considered just dead code and valid, but because it is not practically useful,
757  // we reject such code completely for now, which gives us more freedom if in the future we do want to define
758  // semantics for code after ctrl in some way.
759  VALIDATOR_ASSERT(!(tx & RZ_IL_TYPE_EFFECT_CTRL) || !ty, "Encountered further effects after a ctrl effect in seq op.");
760  *type_out = tx | ty;
761  return true;
762 }
op structure for Seq ('a eff -> 'a eff -> 'a eff)

References args, RZ_IL_TYPE_EFFECT_CTRL, VALIDATOR_ASSERT, and VALIDATOR_DESCEND_EFFECT.

◆ VALIDATOR_EFFECT() [9/11]

VALIDATOR_EFFECT ( set  )

Definition at line 696 of file il_validate.c.

696  {
697  RzILOpArgsSet *args = &op->op.set;
698  VALIDATOR_ASSERT(args->v, "Var name of set op is NULL.\n");
699  RzILSortPure sx;
700  VALIDATOR_DESCEND_PURE(args->x, &sx);
701  RzILSortPure *sort = ht_pp_find(
702  args->is_local ? ctx->local_vars_known : ctx->global_ctx->global_vars, args->v, NULL);
703  VALIDATOR_ASSERT(args->is_local || sort, "Global variable \"%s\" referenced by set op does not exist.\n", args->v);
704  if (sort && !rz_il_sort_pure_eq(*sort, sx)) {
705  char *svs = rz_il_sort_pure_stringify(*sort);
706  char *sxs = rz_il_sort_pure_stringify(sx);
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",
709  args->v, rz_str_get_null(svs), rz_str_get_null(sxs));
710  free(svs);
711  free(sxs);
712  return false;
713  }
714  if (args->is_local) {
715  if (!sort) {
716  sort = RZ_NEW(RzILSortPure);
717  if (!sort) {
718  return false;
719  }
720  *sort = sx;
721  ht_pp_update(ctx->local_vars_known, args->v, sort);
722  }
723  ht_pp_update(ctx->local_vars_available, args->v, sort);
724  }
725  *type_out = RZ_IL_TYPE_EFFECT_DATA;
726  return true;
727 }
static const char * rz_str_get_null(const char *str)
Definition: rz_str.h:190
op structure for set ('a var -> 'a pure -> data eff)

References args, free(), NULL, rz_il_sort_pure_eq(), rz_il_sort_pure_stringify(), RZ_IL_TYPE_EFFECT_DATA, RZ_NEW, rz_str_get_null(), rz_strbuf_appendf(), local_pure_var_t::sort, VALIDATOR_ASSERT, and VALIDATOR_DESCEND_PURE.

◆ VALIDATOR_EFFECT() [10/11]

VALIDATOR_EFFECT ( store  )

Definition at line 657 of file il_validate.c.

657  {
658  RzILOpArgsStore *args = &op->op.store;
659  bool found = false;
660  ut64 htm = ht_uu_find(ctx->global_ctx->mems, args->mem, &found);
661  VALIDATOR_ASSERT(found, "Mem %u referenced by store op does not exist.\n", (unsigned int)args->mem);
662  ut32 key_len = htm >> 32;
663  ut32 val_len = htm & UT32_MAX;
664  RzILSortPure sk;
665  VALIDATOR_DESCEND_PURE(args->key, &sk);
666  VALIDATOR_ASSERT(sk.type == RZ_IL_TYPE_PURE_BITVECTOR, "Key operand of store op is not a bitvector.\n");
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);
669  RzILSortPure sv;
670  VALIDATOR_DESCEND_PURE(args->value, &sv);
671  VALIDATOR_ASSERT(sv.type == RZ_IL_TYPE_PURE_BITVECTOR, "Value operand of store op is not a bitvector.\n");
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);
674  *type_out = RZ_IL_TYPE_EFFECT_DATA;
675  return true;
676 }
uint32_t ut32
RZ_API const KEY_TYPE bool * found
Definition: ht_inc.h:130
#define UT32_MAX
Definition: rz_types_base.h:99
op structure for store (('a, 'b) mem -> 'a bitv -> 'b bitv -> ('a, 'b) mem)

References args, rz_il_sort_pure_t::bv, found, rz_il_sort_pure_t::props, RZ_IL_TYPE_EFFECT_DATA, RZ_IL_TYPE_PURE_BITVECTOR, rz_il_sort_pure_t::type, UT32_MAX, ut64(), VALIDATOR_ASSERT, and VALIDATOR_DESCEND_PURE.

◆ VALIDATOR_EFFECT() [11/11]

VALIDATOR_EFFECT ( storew  )

Definition at line 678 of file il_validate.c.

678  {
679  RzILOpArgsStoreW *args = &op->op.storew;
680  bool found = false;
681  ut64 htm = ht_uu_find(ctx->global_ctx->mems, args->mem, &found);
682  VALIDATOR_ASSERT(found, "Mem %u referenced by storew op does not exist.\n", (unsigned int)args->mem);
683  ut32 key_len = htm >> 32;
684  RzILSortPure sk;
685  VALIDATOR_DESCEND_PURE(args->key, &sk);
686  VALIDATOR_ASSERT(sk.type == RZ_IL_TYPE_PURE_BITVECTOR, "Key operand of storew op is not a bitvector.\n");
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);
689  RzILSortPure sv;
690  VALIDATOR_DESCEND_PURE(args->value, &sv);
691  VALIDATOR_ASSERT(sv.type == RZ_IL_TYPE_PURE_BITVECTOR, "Value operand of storew op is not a bitvector.\n");
692  *type_out = RZ_IL_TYPE_EFFECT_DATA;
693  return true;
694 }
Store an entire word of arbitrary bit size into a memory.

References args, rz_il_sort_pure_t::bv, found, rz_il_sort_pure_t::props, RZ_IL_TYPE_EFFECT_DATA, RZ_IL_TYPE_PURE_BITVECTOR, rz_il_sort_pure_t::type, ut64(), VALIDATOR_ASSERT, and VALIDATOR_DESCEND_PURE.

◆ VALIDATOR_PURE() [1/16]

VALIDATOR_PURE ( append  )

Definition at line 487 of file il_validate.c.

487  {
488  RzILOpPure *x = op->op.append.high;
489  RzILOpPure *y = op->op.append.low;
490  RzILSortPure sx;
491  VALIDATOR_DESCEND(x, &sx);
492  VALIDATOR_ASSERT(sx.type == RZ_IL_TYPE_PURE_BITVECTOR, "High operand of append op is not a bitvector.\n");
493  RzILSortPure sy;
494  VALIDATOR_DESCEND(y, &sy);
495  VALIDATOR_ASSERT(sy.type == RZ_IL_TYPE_PURE_BITVECTOR, "Low operand of append op is not a bitvector.\n");
496  *sort_out = rz_il_sort_pure_bv(sx.props.bv.length + sy.props.bv.length);
497  return true;
498 }
#define VALIDATOR_DESCEND(op, sort)
Definition: il_validate.c:283
int x
Definition: mipsasm.c:20
static RzILSortPure rz_il_sort_pure_bv(ut32 length)
Definition: sort.h:55

References rz_il_sort_pure_t::bv, rz_il_sort_pure_t::props, rz_il_sort_pure_bv(), RZ_IL_TYPE_PURE_BITVECTOR, rz_il_sort_pure_t::type, VALIDATOR_ASSERT, VALIDATOR_DESCEND, and x.

◆ VALIDATOR_PURE() [2/16]

VALIDATOR_PURE ( bitv  )

Definition at line 327 of file il_validate.c.

327  {
328  RzBitVector *bv = op->op.bitv.value;
329  if (!bv) {
330  rz_strbuf_appendf(report_builder, "Bitvector in constant bitvector op is NULL.\n");
331  return false;
332  }
333  *sort_out = rz_il_sort_pure_bv(rz_bv_len(bv));
334  return true;
335 }
RZ_API ut32 rz_bv_len(RZ_NONNULL const RzBitVector *bv)
Definition: bitvector.c:1140
structure for bitvector
Definition: rz_bitvector.h:19

References rz_bv_len(), rz_il_sort_pure_bv(), and rz_strbuf_appendf().

◆ VALIDATOR_PURE() [3/16]

VALIDATOR_PURE ( bitv_binop  )

'a bitv -> 'a bitv -> 'a bitv ops e.g. add, sub, mul, div, ...

Definition at line 341 of file il_validate.c.

341  {
342  RzILOpPure *x = op->op.add.x; // just add is fine, all ops in here use the same struct
343  RzILOpPure *y = op->op.add.y;
344  RzILSortPure sx;
345  VALIDATOR_DESCEND(x, &sx);
346  VALIDATOR_ASSERT(sx.type == RZ_IL_TYPE_PURE_BITVECTOR, "Left operand of %s op is not a bitvector.\n", rz_il_op_pure_code_stringify(op->code));
347  RzILSortPure sy;
348  VALIDATOR_DESCEND(y, &sy);
349  VALIDATOR_ASSERT(sy.type == RZ_IL_TYPE_PURE_BITVECTOR, "Right operand of %s op is not a bitvector.\n", rz_il_op_pure_code_stringify(op->code));
350  VALIDATOR_ASSERT(sx.props.bv.length == sy.props.bv.length, "Operand sizes of %s op do not agree: %u vs. %u.\n",
351  rz_il_op_pure_code_stringify(op->code), (unsigned int)sx.props.bv.length, (unsigned int)sy.props.bv.length);
352  *sort_out = sx;
353  return true;
354 }
RZ_API RZ_NONNULL const char * rz_il_op_pure_code_stringify(RzILOpPureCode code)
Definition: il_export.c:872

References rz_il_sort_pure_t::bv, op::code, rz_il_sort_pure_t::props, rz_il_op_pure_code_stringify(), RZ_IL_TYPE_PURE_BITVECTOR, rz_il_sort_pure_t::type, VALIDATOR_ASSERT, VALIDATOR_DESCEND, and x.

◆ VALIDATOR_PURE() [4/16]

VALIDATOR_PURE ( bitv_bool_unop  )

'a bitv -> bool ops e.g. msb, lsb

Definition at line 423 of file il_validate.c.

423  {
424  RzILOpPure *x = op->op.msb.bv; // just msb is fine, all ops in here use the same struct
425  RzILSortPure sx;
426  VALIDATOR_DESCEND(x, &sx);
427  VALIDATOR_ASSERT(sx.type == RZ_IL_TYPE_PURE_BITVECTOR, "Operand of %s op is not a bitvector.\n", rz_il_op_pure_code_stringify(op->code));
428  *sort_out = rz_il_sort_pure_bool();
429  return true;
430 }
static RzILSortPure rz_il_sort_pure_bool()
Definition: sort.h:47

References op::code, rz_il_op_pure_code_stringify(), rz_il_sort_pure_bool(), RZ_IL_TYPE_PURE_BITVECTOR, rz_il_sort_pure_t::type, VALIDATOR_ASSERT, VALIDATOR_DESCEND, and x.

◆ VALIDATOR_PURE() [5/16]

VALIDATOR_PURE ( bitv_unop  )

'a bitv -> 'a bitv ops e.g. bitwise negation

Definition at line 436 of file il_validate.c.

436  {
437  RzILOpPure *x = op->op.lognot.bv; // just lognot is fine, all ops in here use the same struct
438  RzILSortPure sx;
439  VALIDATOR_DESCEND(x, &sx);
440  VALIDATOR_ASSERT(sx.type == RZ_IL_TYPE_PURE_BITVECTOR, "Operand of %s op is not a bitvector.\n", rz_il_op_pure_code_stringify(op->code));
441  *sort_out = sx;
442  return true;
443 }

References op::code, rz_il_op_pure_code_stringify(), RZ_IL_TYPE_PURE_BITVECTOR, rz_il_sort_pure_t::type, VALIDATOR_ASSERT, VALIDATOR_DESCEND, and x.

◆ VALIDATOR_PURE() [6/16]

VALIDATOR_PURE ( bool_binop  )

bool -> bool -> bool ops e.g. and, or, ...

Definition at line 406 of file il_validate.c.

406  {
407  RzILOpPure *x = op->op.booland.x; // just booland is fine, all ops in here use the same struct
408  RzILOpPure *y = op->op.booland.y;
409  RzILSortPure sx;
410  VALIDATOR_DESCEND(x, &sx);
411  VALIDATOR_ASSERT(sx.type == RZ_IL_TYPE_PURE_BOOL, "Left operand of %s op is not bool.\n", rz_il_op_pure_code_stringify(op->code));
412  RzILSortPure sy;
413  VALIDATOR_DESCEND(y, &sy);
414  VALIDATOR_ASSERT(sy.type == RZ_IL_TYPE_PURE_BOOL, "Right operand of %s op is not bool.\n", rz_il_op_pure_code_stringify(op->code));
415  *sort_out = rz_il_sort_pure_bool();
416  return true;
417 }

References op::code, rz_il_op_pure_code_stringify(), rz_il_sort_pure_bool(), RZ_IL_TYPE_PURE_BOOL, rz_il_sort_pure_t::type, VALIDATOR_ASSERT, VALIDATOR_DESCEND, and x.

◆ VALIDATOR_PURE() [7/16]

VALIDATOR_PURE ( bool_const  )

Definition at line 322 of file il_validate.c.

322  {
323  *sort_out = rz_il_sort_pure_bool();
324  return true;
325 }

References rz_il_sort_pure_bool().

◆ VALIDATOR_PURE() [8/16]

VALIDATOR_PURE ( cast  )

Definition at line 474 of file il_validate.c.

474  {
475  RzILOpArgsCast *args = &op->op.cast;
476  VALIDATOR_ASSERT(args->length, "Length of cast op is 0.\n");
477  RzILSortPure sf;
478  VALIDATOR_DESCEND(args->fill, &sf);
479  VALIDATOR_ASSERT(sf.type == RZ_IL_TYPE_PURE_BOOL, "Fill operand of cast op is not bool.\n");
480  RzILSortPure sx;
481  VALIDATOR_DESCEND(args->val, &sx);
482  VALIDATOR_ASSERT(sx.type == RZ_IL_TYPE_PURE_BITVECTOR, "Value operand of %s op is not a bitvector.\n", rz_il_op_pure_code_stringify(op->code));
483  *sort_out = rz_il_sort_pure_bv(args->length);
484  return true;
485 }
op structure for casting bitv

References args, op::code, rz_il_op_pure_code_stringify(), rz_il_sort_pure_bv(), RZ_IL_TYPE_PURE_BITVECTOR, RZ_IL_TYPE_PURE_BOOL, rz_il_sort_pure_t::type, VALIDATOR_ASSERT, and VALIDATOR_DESCEND.

◆ VALIDATOR_PURE() [9/16]

VALIDATOR_PURE ( cmp  )

Definition at line 460 of file il_validate.c.

460  {
461  RzILOpArgsEq *args = &op->op.eq;
462  RzILSortPure sx;
463  VALIDATOR_DESCEND(args->x, &sx);
464  VALIDATOR_ASSERT(sx.type == RZ_IL_TYPE_PURE_BITVECTOR, "Left operand of %s op is not a bitvector.\n", rz_il_op_pure_code_stringify(op->code));
465  RzILSortPure sy;
466  VALIDATOR_DESCEND(args->y, &sy);
467  VALIDATOR_ASSERT(sy.type == RZ_IL_TYPE_PURE_BITVECTOR, "Right operand of %s op is not a bitvector.\n", rz_il_op_pure_code_stringify(op->code));
468  VALIDATOR_ASSERT(sx.props.bv.length == sy.props.bv.length, "Operand sizes of %s op do not agree: %u vs. %u.\n",
469  rz_il_op_pure_code_stringify(op->code), (unsigned int)sx.props.bv.length, (unsigned int)sy.props.bv.length);
470  *sort_out = rz_il_sort_pure_bool();
471  return true;
472 }
op structure for binary comparison ops ('a bitv -> 'a bitv -> bool)

References args, rz_il_sort_pure_t::bv, op::code, rz_il_sort_pure_t::props, rz_il_op_pure_code_stringify(), rz_il_sort_pure_bool(), RZ_IL_TYPE_PURE_BITVECTOR, rz_il_sort_pure_t::type, VALIDATOR_ASSERT, and VALIDATOR_DESCEND.

◆ VALIDATOR_PURE() [10/16]

VALIDATOR_PURE ( inv  )

Definition at line 393 of file il_validate.c.

393  {
394  RzILOpArgsBoolInv *args = &op->op.boolinv;
395  RzILSortPure sort;
396  VALIDATOR_DESCEND(args->x, &sort);
397  VALIDATOR_ASSERT(sort.type == RZ_IL_TYPE_PURE_BOOL, "Operand of boolean inv op is not boolean.\n");
398  *sort_out = rz_il_sort_pure_bool();
399  return true;
400 }
op structure for inv (!bool -> bool)

References args, rz_il_sort_pure_bool(), RZ_IL_TYPE_PURE_BOOL, local_pure_var_t::sort, rz_il_sort_pure_t::type, VALIDATOR_ASSERT, and VALIDATOR_DESCEND.

◆ VALIDATOR_PURE() [11/16]

VALIDATOR_PURE ( ite  )

Definition at line 356 of file il_validate.c.

356  {
357  RzILOpArgsIte *args = &op->op.ite;
359  VALIDATOR_DESCEND(args->condition, &sc);
360  VALIDATOR_ASSERT(sc.type == RZ_IL_TYPE_PURE_BOOL, "Condition of ite op is not boolean.\n");
361  RzILSortPure sx;
362  VALIDATOR_DESCEND(args->x, &sx);
363  RzILSortPure sy;
364  VALIDATOR_DESCEND(args->y, &sy);
365  if (!rz_il_sort_pure_eq(sx, sy)) {
366  char *sxs = rz_il_sort_pure_stringify(sx);
367  char *sys = rz_il_sort_pure_stringify(sy);
368  rz_strbuf_appendf(report_builder, "Types of ite branches do not agree: %s vs. %s.\n",
369  rz_str_get_null(sxs), rz_str_get_null(sys));
370  free(sxs);
371  free(sys);
372  return false;
373  }
374  *sort_out = sx;
375  return true;
376 }
op structure for ite (bool -> 'a pure -> 'a pure -> 'a pure)

References args, free(), rz_il_sort_pure_eq(), rz_il_sort_pure_stringify(), RZ_IL_TYPE_PURE_BOOL, rz_str_get_null(), rz_strbuf_appendf(), sc, VALIDATOR_ASSERT, and VALIDATOR_DESCEND.

◆ VALIDATOR_PURE() [12/16]

VALIDATOR_PURE ( let  )

Definition at line 378 of file il_validate.c.

378  {
379  RzILOpArgsLet *args = &op->op.let;
380  VALIDATOR_ASSERT(args->name, "Var name of let op is NULL.\n");
381  VALIDATOR_ASSERT(args->exp, "Expression of let op is NULL.\n");
382  VALIDATOR_ASSERT(args->body, "Body of let op is NULL.\n");
383  RzILSortPure sort;
384  VALIDATOR_DESCEND(args->exp, &sort);
385  LocalPureVar var = {
386  .name = args->name,
387  .sort = sort,
388  .next = local_pure_var_stack
389  };
390  return validate_pure(args->body, sort_out, report_builder, ctx, &var);
391 }
const char * name
Definition: il_validate.c:257
op structure for let_ : 'a var -> 'a pure -> 'b pure -> 'b pure

References args, local_pure_var_t::name, local_pure_var_t::sort, validate_pure(), VALIDATOR_ASSERT, and VALIDATOR_DESCEND.

◆ VALIDATOR_PURE() [13/16]

VALIDATOR_PURE ( load  )

Definition at line 500 of file il_validate.c.

500  {
501  RzILOpArgsLoad *args = &op->op.load;
502  bool found = false;
503  ut64 htm = ht_uu_find(ctx->global_ctx->mems, args->mem, &found);
504  VALIDATOR_ASSERT(found, "Mem %u referenced by load op does not exist.\n", (unsigned int)args->mem);
505  ut32 key_len = htm >> 32;
506  ut32 val_len = htm & UT32_MAX;
507  RzILSortPure sk;
508  VALIDATOR_DESCEND(args->key, &sk);
509  VALIDATOR_ASSERT(sk.type == RZ_IL_TYPE_PURE_BITVECTOR, "Key operand of load op is not a bitvector.\n");
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);
512  *sort_out = rz_il_sort_pure_bv(val_len);
513  return true;
514 }
op structure for load (('a, 'b) mem -> 'a bitv -> 'b bitv)

References args, rz_il_sort_pure_t::bv, found, rz_il_sort_pure_t::props, rz_il_sort_pure_bv(), RZ_IL_TYPE_PURE_BITVECTOR, rz_il_sort_pure_t::type, UT32_MAX, ut64(), VALIDATOR_ASSERT, and VALIDATOR_DESCEND.

◆ VALIDATOR_PURE() [14/16]

VALIDATOR_PURE ( loadw  )

Definition at line 516 of file il_validate.c.

516  {
517  RzILOpArgsLoadW *args = &op->op.loadw;
518  VALIDATOR_ASSERT(args->n_bits, "Length of loadw op is 0.\n");
519  bool found = false;
520  ut64 htm = ht_uu_find(ctx->global_ctx->mems, args->mem, &found);
521  VALIDATOR_ASSERT(found, "Mem %u referenced by loadw op does not exist.\n", (unsigned int)args->mem);
522  ut32 key_len = htm >> 32;
523  RzILSortPure sk;
524  VALIDATOR_DESCEND(args->key, &sk);
525  VALIDATOR_ASSERT(sk.type == RZ_IL_TYPE_PURE_BITVECTOR, "Key operand of loadw op is not a bitvector.\n");
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);
528  *sort_out = rz_il_sort_pure_bv(args->n_bits);
529  return true;
530 }
Load an entire word of arbitrary bit size from a memory.

References args, rz_il_sort_pure_t::bv, found, rz_il_sort_pure_t::props, rz_il_sort_pure_bv(), RZ_IL_TYPE_PURE_BITVECTOR, rz_il_sort_pure_t::type, ut64(), VALIDATOR_ASSERT, and VALIDATOR_DESCEND.

◆ VALIDATOR_PURE() [15/16]

VALIDATOR_PURE ( shift  )

Definition at line 445 of file il_validate.c.

445  {
446  RzILOpArgsShiftLeft *args = &op->op.shiftl;
447  RzILSortPure sf;
448  VALIDATOR_DESCEND(args->fill_bit, &sf);
449  VALIDATOR_ASSERT(sf.type == RZ_IL_TYPE_PURE_BOOL, "Fill operand of %s op is not bool.\n", rz_il_op_pure_code_stringify(op->code));
450  RzILSortPure sx;
451  VALIDATOR_DESCEND(args->x, &sx);
452  VALIDATOR_ASSERT(sx.type == RZ_IL_TYPE_PURE_BITVECTOR, "Value operand of %s op is not a bitvector.\n", rz_il_op_pure_code_stringify(op->code));
453  RzILSortPure sy;
454  VALIDATOR_DESCEND(args->y, &sy);
455  VALIDATOR_ASSERT(sy.type == RZ_IL_TYPE_PURE_BITVECTOR, "Distance operand of %s op is not a bitvector.\n", rz_il_op_pure_code_stringify(op->code));
456  *sort_out = sx;
457  return true;
458 }
op structure for lshift and rshift (bool -> 's bitv -> 'b bitv -> 's bitv)

References args, op::code, rz_il_op_pure_code_stringify(), RZ_IL_TYPE_PURE_BITVECTOR, RZ_IL_TYPE_PURE_BOOL, rz_il_sort_pure_t::type, VALIDATOR_ASSERT, and VALIDATOR_DESCEND.

◆ VALIDATOR_PURE() [16/16]

VALIDATOR_PURE ( var  )

Definition at line 290 of file il_validate.c.

290  {
291  RzILOpArgsVar *args = &op->op.var;
292  VALIDATOR_ASSERT(args->v, "Var name of var op is NULL.\n");
293  switch (args->kind) {
294  case RZ_IL_VAR_KIND_GLOBAL: {
295  RzILSortPure *sort = ht_pp_find(ctx->global_ctx->global_vars, args->v, NULL);
296  VALIDATOR_ASSERT(sort, "Global variable \"%s\" referenced by var op does not exist.\n", args->v);
297  *sort_out = *sort;
298  return true;
299  }
300  case RZ_IL_VAR_KIND_LOCAL: {
301  RzILSortPure *sort = ht_pp_find(ctx->local_vars_available, args->v, NULL);
302  VALIDATOR_ASSERT(sort, "Local variable \"%s\" is not available at var op.\n", args->v);
303  *sort_out = *sort;
304  return true;
305  }
307  for (LocalPureVar *loc = local_pure_var_stack; loc; loc = loc->next) {
308  if (!strcmp(loc->name, args->v)) {
309  *sort_out = loc->sort;
310  return true;
311  }
312  }
313  VALIDATOR_ASSERT(false, "Local pure variable \"%s\" unbound at var op.\n", args->v);
314  return false;
315  }
316  default:
317  VALIDATOR_ASSERT(false, "Var op has invalid kind.\n");
318  }
319  return true;
320 }
struct local_pure_var_t * next
Definition: il_validate.c:259
op structure for var ('a var -> 'a pure)
@ RZ_IL_VAR_KIND_LOCAL
local var, defined and assigned by set ops, mutable and useable across effects.
Definition: variable.h:48
@ RZ_IL_VAR_KIND_LOCAL_PURE
local pure var, bound only by let expressions, scope is limited to the let's pure body,...
Definition: variable.h:49

References args, local_pure_var_t::next, NULL, RZ_IL_VAR_KIND_GLOBAL, RZ_IL_VAR_KIND_LOCAL, RZ_IL_VAR_KIND_LOCAL_PURE, local_pure_var_t::sort, and VALIDATOR_ASSERT.

◆ var_kv_free()

static void var_kv_free ( HtPPKv *  kv)
static

Definition at line 19 of file il_validate.c.

19  {
20  free(kv->key);
21  free(kv->value);
22 }

References free().

Referenced by local_context_init(), and rz_il_validate_global_context_new_empty().

◆ var_kv_unown_free()

static void var_kv_unown_free ( HtPPKv *  kv)
static

Definition at line 24 of file il_validate.c.

24  {
25  free(kv->key);
26 }

References free().

Referenced by local_context_init().

Variable Documentation

◆ validate_effect_table

ValidateEffectFn validate_effect_table[RZ_IL_OP_EFFECT_MAX]
static
Initial value:
= {
}
#define jmp
#define VALIDATOR_EFFECT_NAME(op)
Definition: il_validate.c:632
static void repeat(struct parse *, sopno, int, int)
Definition: regcomp.c:1155
@ RZ_IL_OP_BLK
@ RZ_IL_OP_GOTO
@ RZ_IL_OP_SEQ
@ RZ_IL_OP_NOP
@ RZ_IL_OP_JMP
@ RZ_IL_OP_EMPTY
@ RZ_IL_OP_STORE
@ RZ_IL_OP_STOREW
@ RZ_IL_OP_REPEAT
@ RZ_IL_OP_BRANCH
@ RZ_IL_OP_SET

Definition at line 816 of file il_validate.c.

Referenced by validate_effect().

◆ validate_pure_table

ValidatePureFn validate_pure_table[RZ_IL_OP_PURE_MAX]
static

Definition at line 532 of file il_validate.c.

Referenced by validate_pure().