* removal of `omo` command
* use of `oml`, `oml.` and `oml=` to list maps instead of `om`
* removal of RIZIN output from `oml`
* removal of `omn.` and just assume `omn` uses core->offset
Before:
store(key:var(v:ptr), value:add(x:load(key:var(v:ptr), mem:0),
y:int(value:1, length:8)), mem:0)
After:
(store 0 (var ptr) (+ (load 0 (var ptr)) (bv 8 0x1)))
S-Expressions like this are more concise and will be trivial to parse,
in case we want a parser for this later. It is also very similar to what
BAP uses, so it will be easier to compare.
This adds the IL validator, which performs static type-checking of both
pure and effect ops among other checks. In particular, assuming the
validator is correctly implemented, if it considers an op to be valid
under some context, evaluating the op in the vm will never yield a
runtime error, that is, an error where the vm itself errors, not an
expected error state of the code being executed. In our case, this
includes for example:
* Any kind of type error: Conditions not being bool, bitvector sizes not
matching, ...
* Variables not being available when they are accessed Using local
* variables with multiple different types in a single effect etc.
Any code that we lift must obey these rules. Thus, any analysis can rely
on it. The plan for this is to use the validator primarily in testing,
development of lifters and for IL code coming from the outside. If our
lifting code is covered well enough by tests using the validator, we can
omit the validation at runtime.
The only ops that do not have well-defined validation yet are blk and
goto since their semantics, in particular regarding label handling are
still a bit vague. This also removes the concat and unk ops since they
are unimplemented and not needed.
There are now three kinds of vars: global, local and local pure. Global
and local pure are exactly like in BAP, local ones are defined by their
initial set op and have the scope of a single lifted instruction.
The set op now handles both global and local vars, let is now pure and
binds only inside its body. Vars have static types, global and local are
always mutable, local pure naturally immutable.
The var op specifies the kind of variable to take from, and the
individual variable sets are separate. This corresponds to BAP's
behavior where the kind of variable is part of the identifier.
Variable content storage has also been rewritten and RzILBag removed.
* Add documentation for 'rz_core_analysis_search_xrefs'
* Search RzAnalysisOp.analysis_vals for references as well.
* Add test case for string search in RzAnalysisOp.analysis_vals.
* Replace int with RzOutputMode to indicate the output mode of the commands.
* Let `rz_core_analysis_refs()` use the `RzOutputMode` enum.
* Split `found_xref()` to `is_valid_xref()` and `print_xref()`.
Plugins do not create register-based variables themselves anymore, but
they are derived from the register profile. However not all registers
may be bound and not all variables may be actual registers. The concrete
relations between an RzILVM and registers is described by an
RzILRegBinding object. It is simply a list of register names and
variables are created of the same names. When stepping with aezs, the
registers are synchronized automatically. From now on, aezv is primarily
useful for debugging, but interacting with emulation from the user side
should be done with ar.
rzil should be either rz_il when prefixed for Rizin API, or just il
whenever it's used in some local identifier/name.
In addition, the unclear notion of "vm_layer" has been removed. The VM
source files are split into management and evaluation instead.
This dups a pure opcode, in particular to be able to reuse a single
expression multiple times in lifting. For effects, we do not neet this
so far since those usually only appear a single time.
This adds an RzBuffer implementation that binds against RzIO's
rz_io_read_at/rz_io_write_at in order to access the mapped memory. This
is in contrast to the previous io RzBuffer, which has been renamed to
..._io_fd and which reads directly from a single file descriptor without
mapping.
To keep bf working, bin_bf now maps an area of zeroes because
otherwise the initial memory contents in RzIL would read as 0xff.
The root type of a lifted op is now simply a single RzILOpEffect, which
can be for example a chain of seq ops. This is in line with what BAP
uses.
For convenient creation of sequences, `rz_il_op_new_seqn(ut32 n, ...)`
is a drop-in replacement for `rz_il_make_oplist(ut32 n, ...)`.