Move ESIL into its own namespace (#6199)

* Move ESIL into its own namespace
* Remove RzAnalysisEsilInterState from RzAnalysis
* More cleanup to split cil.c from ESIL code
* Rename RzAnalysisRzilTrace to RzAnalysisILTrace
* Fix various null-derefs.
* Remove rz_analysis_get/set_esil_inter_state
* Fix use after free and leaks
This commit is contained in:
Giovanni 2026-04-11 16:26:01 +08:00 committed by GitHub
parent 1fe7507c0f
commit 1a57d18cc4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 1824 additions and 1904 deletions

View file

@ -113,12 +113,6 @@ RZ_API RzAnalysis *rz_analysis_new(RZ_NULLABLE const char *sdb_types_path) {
free(analysis);
return NULL;
}
analysis->esilinterstate = RZ_NEW0(RzAnalysisEsilInterState);
if (!analysis->esilinterstate) {
free(analysis->sdb_types_path);
free(analysis);
return NULL;
}
analysis->bb_tree = NULL;
analysis->ht_addr_fun = ht_up_new(NULL, NULL);
analysis->ht_name_fun = ht_sp_new(HT_STR_DUP, NULL, NULL);
@ -222,7 +216,6 @@ RZ_API void rz_analysis_free(RZ_NULLABLE RzAnalysis *a) {
rz_type_db_free(a->typedb);
sdb_free(a->sdb);
rz_analysis_esil_free(a->esil);
free(a->esilinterstate);
free(a->last_disasm_reg);
rz_list_free(a->imports);
rz_str_constpool_fini(&a->constpool);
@ -645,16 +638,6 @@ RZ_API RZ_BORROW bool rz_analysis_get_recursive_noreturn(RZ_NONNULL RzAnalysis *
return analysis->recursive_noreturn;
}
RZ_DEPRECATE RZ_API RZ_BORROW RzAnalysisEsilInterState *rz_analysis_get_esil_inter_state(RZ_NONNULL RzAnalysis *analysis) {
rz_return_val_if_fail(analysis, NULL);
return analysis->esilinterstate;
}
RZ_DEPRECATE RZ_API void rz_analysis_set_esil_inter_state(RZ_NONNULL RzAnalysis *analysis, RZ_NULLABLE RzAnalysisEsilInterState *esilinterstate) {
rz_return_if_fail(analysis);
analysis->esilinterstate = esilinterstate;
}
RZ_DEPRECATE RZ_API void rz_analysis_set_core(RZ_NONNULL RzAnalysis *analysis, RZ_NULLABLE void *core) {
rz_return_if_fail(analysis);
analysis->core = core;
@ -665,16 +648,6 @@ RZ_DEPRECATE RZ_API void rz_analysis_set_event(RZ_NONNULL RzAnalysis *analysis,
analysis->ev = ev;
}
RZ_DEPRECATE RZ_API RZ_BORROW RzAnalysisEsil *rz_analysis_get_esil(RZ_NONNULL RzAnalysis *analysis) {
rz_return_val_if_fail(analysis, NULL);
return analysis->esil;
}
RZ_DEPRECATE RZ_API void rz_analysis_set_esil(RZ_NONNULL RzAnalysis *analysis, RZ_NULLABLE RzAnalysisEsil *esil) {
rz_return_if_fail(analysis);
analysis->esil = esil;
}
RZ_DEPRECATE RZ_API const char *rz_analysis_get_arch(RZ_NONNULL const RzAnalysis *analysis) {
rz_return_val_if_fail(analysis, RZ_SYS_ARCH);
return analysis->cur ? analysis->cur->name : RZ_SYS_ARCH;
@ -1272,3 +1245,13 @@ RZ_API void rz_analysis_remove_import(RzAnalysis *analysis, const char *imp) {
RZ_API void rz_analysis_purge_imports(RzAnalysis *analysis) {
rz_list_purge(analysis->imports);
}
RZ_DEPRECATE RZ_API RZ_BORROW RzAnalysisEsil *rz_analysis_get_esil(RZ_NONNULL RzAnalysis *analysis) {
rz_return_val_if_fail(analysis, NULL);
return analysis->esil;
}
RZ_DEPRECATE RZ_API void rz_analysis_set_esil(RZ_NONNULL RzAnalysis *analysis, RZ_NULLABLE RzAnalysisEsil *esil) {
rz_return_if_fail(analysis);
analysis->esil = esil;
}

View file

@ -52,7 +52,6 @@ struct rz_analysis_t {
int maxreflines; // asm.lines.maxref
ut32 pcalign; // asm.pcalign
RzAnalysisEsil *esil;
RzAnalysisEsilInterState *esilinterstate;
RzAnalysisILVM *il_vm; ///< user-faced VM, NEVER use this for any analysis passes!
RzAnalysisPlugin *cur;
RzInterval limit; // analysis.from, analysis.to

View file

@ -2,10 +2,9 @@
// SPDX-FileCopyrightText: 2014-2021 condret <condr3t@protonmail.com>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_esil/rz_esil.h>
#include "analysis_private.h"
#include <rz_types.h>
#include <rz_util.h>
#include <rz_bind.h>
#define EANALYSIS(e) ((RzAnalysis *)(esil->panalysis))
#define FLG(x) RZ_ANALYSIS_ESIL_FLAG_##x
#define cpuflag(x, y) \
@ -51,7 +50,7 @@ static bool isnum(RzAnalysisEsil *esil, const char *str, ut64 *num) {
}
static bool ispackedreg(RzAnalysisEsil *esil, const char *str) {
RzRegItem *ri = rz_reg_get(esil->analysis->reg, str, -1);
RzRegItem *ri = rz_reg_get(EANALYSIS(esil)->reg, str, -1);
return ri ? ri->packed_size > 0 : false;
}
@ -100,6 +99,7 @@ RZ_API RzAnalysisEsil *rz_analysis_esil_new(int stacksize, int iotrap, unsigned
rz_analysis_esil_interrupts_init(esil);
esil->addrmask = genmask(addrsize - 1);
rz_strbuf_init(&esil->current_opstr);
esil->esilinterstate = RZ_NEW0(RzAnalysisEsilInterState);
return esil;
}
@ -132,14 +132,6 @@ static bool rz_analysis_esil_fire_trap(RzAnalysisEsil *esil, int trap_type, int
return true;
}
}
if (esil->analysis) {
RzAnalysisPlugin *ap = esil->analysis->cur;
if (ap && ap->esil_trap) {
if (ap->esil_trap(esil, trap_type, trap_code)) {
return true;
}
}
}
return false;
}
@ -155,8 +147,8 @@ RZ_API void rz_analysis_esil_free(RzAnalysisEsil *esil) {
if (!esil) {
return;
}
if (esil->analysis && esil == esil->analysis->esil) {
esil->analysis->esil = NULL;
if (EANALYSIS(esil) && esil == EANALYSIS(esil)->esil) {
EANALYSIS(esil)->esil = NULL;
}
ht_sp_free(esil->ops);
esil->ops = NULL;
@ -166,8 +158,8 @@ RZ_API void rz_analysis_esil_free(RzAnalysisEsil *esil) {
esil->stats = NULL;
rz_analysis_esil_stack_free(esil);
free(esil->stack);
if (esil->analysis && esil->analysis->cur && esil->analysis->cur->esil_fini) {
esil->analysis->cur->esil_fini(esil);
if (EANALYSIS(esil) && EANALYSIS(esil)->cur && EANALYSIS(esil)->cur->esil_fini) {
EANALYSIS(esil)->cur->esil_fini(esil);
}
rz_strbuf_fini(&esil->current_opstr);
rz_analysis_esil_trace_free(esil->trace);
@ -179,17 +171,18 @@ RZ_API void rz_analysis_esil_free(RzAnalysisEsil *esil) {
free(esil->cmd_step);
free(esil->cmd_step_out);
free(esil->cmd_ioer);
free(esil->esilinterstate);
free(esil);
}
static ut8 esil_internal_sizeof_reg(RzAnalysisEsil *esil, const char *r) {
rz_return_val_if_fail(esil && esil->analysis && esil->analysis->reg && r, 0);
RzRegItem *ri = rz_reg_get(esil->analysis->reg, r, -1);
rz_return_val_if_fail(esil && EANALYSIS(esil) && EANALYSIS(esil)->reg && r, 0);
RzRegItem *ri = rz_reg_get(EANALYSIS(esil)->reg, r, -1);
return ri ? ri->size : 0;
}
static int internal_esil_mem_read(RzAnalysisEsil *esil, ut64 addr, ut8 *buf, int len) {
rz_return_val_if_fail(esil && esil->analysis && esil->analysis->iob.io, 0);
rz_return_val_if_fail(esil && EANALYSIS(esil) && EANALYSIS(esil)->iob.io, 0);
addr &= esil->addrmask;
if (esil->cmd_mdev && esil->mdev_range) {
@ -200,10 +193,10 @@ static int internal_esil_mem_read(RzAnalysisEsil *esil, ut64 addr, ut8 *buf, int
}
}
// TODO: Check if error return from read_at.(on previous version of r2 this call always return len)
(void)esil->analysis->iob.read_at(esil->analysis->iob.io, addr, buf, len);
(void)EANALYSIS(esil)->iob.read_at(EANALYSIS(esil)->iob.io, addr, buf, len);
// check if request address is mapped , if don't fire trap and esil ioer callback
// now with siol, read_at return true/false can't be used to check error vs len
if (!esil->analysis->iob.is_valid_offset(esil->analysis->iob.io, addr, false)) {
if (!EANALYSIS(esil)->iob.is_valid_offset(EANALYSIS(esil)->iob.io, addr, false)) {
if (esil->iotrap) {
esil->trap = RZ_ANALYSIS_TRAP_READ_ERR;
esil->trap_code = addr;
@ -216,14 +209,14 @@ static int internal_esil_mem_read(RzAnalysisEsil *esil, ut64 addr, ut8 *buf, int
}
static int internal_esil_mem_read_no_null(RzAnalysisEsil *esil, ut64 addr, ut8 *buf, int len) {
rz_return_val_if_fail(esil && esil->analysis && esil->analysis->iob.io, 0);
rz_return_val_if_fail(esil && EANALYSIS(esil) && EANALYSIS(esil)->iob.io, 0);
addr &= esil->addrmask;
// TODO: Check if error return from read_at.(on previous version of r2 this call always return len)
(void)esil->analysis->iob.read_at(esil->analysis->iob.io, addr, buf, len);
(void)EANALYSIS(esil)->iob.read_at(EANALYSIS(esil)->iob.io, addr, buf, len);
// check if request address is mapped , if don't fire trap and esil ioer callback
// now with siol, read_at return true/false can't be used to check error vs len
if (!esil->analysis->iob.is_valid_offset(esil->analysis->iob.io, addr, false)) {
if (!EANALYSIS(esil)->iob.is_valid_offset(EANALYSIS(esil)->iob.io, addr, false)) {
if (esil->iotrap) {
esil->trap = RZ_ANALYSIS_TRAP_READ_ERR;
esil->trap_code = addr;
@ -253,7 +246,7 @@ RZ_API int rz_analysis_esil_mem_read(RzAnalysisEsil *esil, ut64 addr, ut8 *buf,
static int internal_esil_mem_write(RzAnalysisEsil *esil, ut64 addr, const ut8 *buf, int len) {
int ret = 0;
if (!esil || !esil->analysis || !esil->analysis->iob.io || esil->nowrite) {
if (!esil || !EANALYSIS(esil) || !EANALYSIS(esil)->iob.io || esil->nowrite) {
return 0;
}
addr &= esil->addrmask;
@ -264,12 +257,12 @@ static int internal_esil_mem_write(RzAnalysisEsil *esil, ut64 addr, const ut8 *b
}
}
}
if (esil->analysis->iob.write_at(esil->analysis->iob.io, addr, buf, len)) {
if (EANALYSIS(esil)->iob.write_at(EANALYSIS(esil)->iob.io, addr, buf, len)) {
ret = len;
}
// check if request address is mapped , if don't fire trap and esil ioer callback
// now with siol, write_at return true/false can't be used to check error vs len
if (!esil->analysis->iob.is_valid_offset(esil->analysis->iob.io, addr, false)) {
if (!EANALYSIS(esil)->iob.is_valid_offset(EANALYSIS(esil)->iob.io, addr, false)) {
if (esil->iotrap) {
esil->trap = RZ_ANALYSIS_TRAP_WRITE_ERR;
esil->trap_code = addr;
@ -283,19 +276,19 @@ static int internal_esil_mem_write(RzAnalysisEsil *esil, ut64 addr, const ut8 *b
static int internal_esil_mem_write_no_null(RzAnalysisEsil *esil, ut64 addr, const ut8 *buf, int len) {
int ret = 0;
if (!esil || !esil->analysis || !esil->analysis->iob.io || !addr) {
if (!esil || !EANALYSIS(esil) || !EANALYSIS(esil)->iob.io || !addr) {
return 0;
}
if (esil->nowrite) {
return 0;
}
addr &= esil->addrmask;
if (esil->analysis->iob.write_at(esil->analysis->iob.io, addr, buf, len)) {
if (EANALYSIS(esil)->iob.write_at(EANALYSIS(esil)->iob.io, addr, buf, len)) {
ret = len;
}
// check if request address is mapped , if don't fire trap and esil ioer callback
// now with siol, write_at return true/false can't be used to check error vs len
if (!esil->analysis->iob.is_valid_offset(esil->analysis->iob.io, addr, false)) {
if (!EANALYSIS(esil)->iob.is_valid_offset(EANALYSIS(esil)->iob.io, addr, false)) {
if (esil->iotrap) {
esil->trap = RZ_ANALYSIS_TRAP_WRITE_ERR;
esil->trap_code = addr;
@ -318,13 +311,13 @@ RZ_API int rz_analysis_esil_mem_write(RzAnalysisEsil *esil, ut64 addr, const ut8
}
static int internal_esil_reg_read(RzAnalysisEsil *esil, const char *regname, ut64 *num, int *size) {
RzRegItem *reg = rz_reg_get(esil->analysis->reg, regname, -1);
RzRegItem *reg = rz_reg_get(EANALYSIS(esil)->reg, regname, -1);
if (reg) {
if (size) {
*size = reg->size;
}
if (num) {
*num = rz_reg_get_value(esil->analysis->reg, reg);
*num = rz_reg_get_value(EANALYSIS(esil)->reg, reg);
}
return true;
}
@ -332,10 +325,10 @@ static int internal_esil_reg_read(RzAnalysisEsil *esil, const char *regname, ut6
}
static int internal_esil_reg_write(RzAnalysisEsil *esil, const char *regname, ut64 num) {
if (esil && esil->analysis) {
RzRegItem *reg = rz_reg_get(esil->analysis->reg, regname, -1);
if (esil && EANALYSIS(esil)) {
RzRegItem *reg = rz_reg_get(EANALYSIS(esil)->reg, regname, -1);
if (reg) {
rz_reg_set_value(esil->analysis->reg, reg, num);
rz_reg_set_value(EANALYSIS(esil)->reg, reg, num);
return true;
}
}
@ -343,12 +336,12 @@ static int internal_esil_reg_write(RzAnalysisEsil *esil, const char *regname, ut
}
static int internal_esil_reg_write_no_null(RzAnalysisEsil *esil, const char *regname, ut64 num) {
rz_return_val_if_fail(esil && esil->analysis && esil->analysis->reg, false);
rz_return_val_if_fail(esil && EANALYSIS(esil) && EANALYSIS(esil)->reg, false);
RzRegItem *reg = rz_reg_get(esil->analysis->reg, regname, -1);
const char *pc = rz_reg_get_name(esil->analysis->reg, RZ_REG_NAME_PC);
const char *sp = rz_reg_get_name(esil->analysis->reg, RZ_REG_NAME_SP);
const char *bp = rz_reg_get_name(esil->analysis->reg, RZ_REG_NAME_BP);
RzRegItem *reg = rz_reg_get(EANALYSIS(esil)->reg, regname, -1);
const char *pc = rz_reg_get_name(EANALYSIS(esil)->reg, RZ_REG_NAME_PC);
const char *sp = rz_reg_get_name(EANALYSIS(esil)->reg, RZ_REG_NAME_SP);
const char *bp = rz_reg_get_name(EANALYSIS(esil)->reg, RZ_REG_NAME_BP);
if (!pc) {
RZ_LOG_WARN("RzReg profile does not contain PC register\n");
@ -363,7 +356,7 @@ static int internal_esil_reg_write_no_null(RzAnalysisEsil *esil, const char *reg
return false;
}
if (reg && reg->name && ((strcmp(reg->name, pc) && strcmp(reg->name, sp) && strcmp(reg->name, bp)) || num)) { // I trust k-maps
rz_reg_set_value(esil->analysis->reg, reg, num);
rz_reg_set_value(EANALYSIS(esil)->reg, reg, num);
return true;
}
return false;
@ -410,7 +403,7 @@ RZ_API int rz_analysis_esil_get_parm_type(RzAnalysisEsil *esil, const char *str)
}
return RZ_ANALYSIS_ESIL_PARM_NUM;
not_a_number:
if (rz_reg_get(esil->analysis->reg, str, -1)) {
if (rz_reg_get(EANALYSIS(esil)->reg, str, -1)) {
return RZ_ANALYSIS_ESIL_PARM_REG;
}
return RZ_ANALYSIS_ESIL_PARM_INVALID;
@ -428,7 +421,7 @@ RZ_API int rz_analysis_esil_get_parm_size(RzAnalysisEsil *esil, const char *str,
case RZ_ANALYSIS_ESIL_PARM_NUM:
*num = rz_num_get(NULL, str);
if (size) {
*size = esil->analysis->bits;
*size = EANALYSIS(esil)->bits;
}
return true;
case RZ_ANALYSIS_ESIL_PARM_REG:
@ -479,7 +472,7 @@ RZ_API int rz_analysis_esil_reg_read(RzAnalysisEsil *esil, const char *regname,
}
*num = 0LL;
if (size) {
*size = esil->analysis->bits;
*size = EANALYSIS(esil)->bits;
}
if (esil->cb.hook_reg_read) {
ret = esil->cb.hook_reg_read(esil, regname, num, size);
@ -688,8 +681,8 @@ static bool esil_js(RzAnalysisEsil *esil) {
// TODO: this should be deprecated because it is not accurate
static bool esil_rs(RzAnalysisEsil *esil) {
rz_return_val_if_fail(esil && esil->analysis, false);
return rz_analysis_esil_pushnum(esil, esil->analysis->bits >> 3);
rz_return_val_if_fail(esil && EANALYSIS(esil), false);
return rz_analysis_esil_pushnum(esil, EANALYSIS(esil)->bits >> 3);
}
// TODO: this should be deprecated because plugins should know their current address
@ -699,7 +692,7 @@ static bool esil_address(RzAnalysisEsil *esil) {
}
static bool esil_weak_eq(RzAnalysisEsil *esil) {
rz_return_val_if_fail(esil && esil->analysis, false);
rz_return_val_if_fail(esil && EANALYSIS(esil), false);
char *dst = rz_analysis_esil_pop(esil);
char *src = rz_analysis_esil_pop(esil);
@ -881,8 +874,8 @@ static bool esil_trap(RzAnalysisEsil *esil) {
static bool esil_bits(RzAnalysisEsil *esil) {
ut64 s;
if (popRN(esil, &s)) {
if (esil->analysis && esil->analysis->coreb.setab) {
esil->analysis->coreb.setab(esil->analysis->coreb.core, NULL, s);
if (EANALYSIS(esil) && EANALYSIS(esil)->coreb.setab) {
EANALYSIS(esil)->coreb.setab(EANALYSIS(esil)->coreb.core, NULL, s);
}
return true;
}
@ -909,9 +902,9 @@ static bool esil_cmp(RzAnalysisEsil *esil) {
esil->old = num;
esil->cur = num - num2;
ret = true;
if (rz_reg_get(esil->analysis->reg, dst, -1)) {
if (rz_reg_get(EANALYSIS(esil)->reg, dst, -1)) {
esil->lastsz = esil_internal_sizeof_reg(esil, dst);
} else if (rz_reg_get(esil->analysis->reg, src, -1)) {
} else if (rz_reg_get(EANALYSIS(esil)->reg, src, -1)) {
esil->lastsz = esil_internal_sizeof_reg(esil, src);
} else {
// default size is set to 64 as internally operands are ut64
@ -1702,9 +1695,9 @@ static bool esil_poke_n(RzAnalysisEsil *esil, int bits) {
if (bits == 128) {
src2 = rz_analysis_esil_pop(esil);
if (src2 && rz_analysis_esil_get_parm(esil, src2, &num2)) {
rz_write_ble(b, num, esil->analysis->big_endian, 64);
rz_write_ble(b, num, EANALYSIS(esil)->big_endian, 64);
rz_analysis_esil_mem_write(esil, addr, b, bytes);
rz_write_ble(b, num2, esil->analysis->big_endian, 64);
rz_write_ble(b, num2, EANALYSIS(esil)->big_endian, 64);
rz_analysis_esil_mem_write(esil, addr + 8, b, bytes);
ret = true;
goto out;
@ -1718,12 +1711,12 @@ static bool esil_poke_n(RzAnalysisEsil *esil, int bits) {
esil->cb.hook_mem_read = NULL;
rz_analysis_esil_mem_read(esil, addr, b, bytes);
esil->cb.hook_mem_read = oldhook;
n = rz_read_ble64(b, esil->analysis->big_endian);
n = rz_read_ble64(b, EANALYSIS(esil)->big_endian);
esil->old = n;
esil->cur = num;
esil->lastsz = bits;
num = num & bitmask;
rz_write_ble(b, num, esil->analysis->big_endian, bits);
rz_write_ble(b, num, EANALYSIS(esil)->big_endian, bits);
rz_analysis_esil_mem_write(esil, addr, b, bytes);
ret = true;
}
@ -1760,7 +1753,7 @@ static bool esil_poke16(RzAnalysisEsil *esil) {
}
static bool esil_poke(RzAnalysisEsil *esil) {
return esil_poke_n(esil, esil->analysis->bits);
return esil_poke_n(esil, EANALYSIS(esil)->bits);
}
static bool esil_poke_some(RzAnalysisEsil *esil) {
@ -1788,7 +1781,7 @@ static bool esil_poke_some(RzAnalysisEsil *esil) {
}
rz_analysis_esil_get_parm_size(esil, foo, &tmp, &regsize);
isregornum(esil, foo, &num64);
rz_write_ble(b, num64, esil->analysis->big_endian, regsize);
rz_write_ble(b, num64, EANALYSIS(esil)->big_endian, regsize);
const int size_bytes = regsize / 8;
const ut32 written = rz_analysis_esil_mem_write(esil, ptr, b, size_bytes);
if (written != size_bytes) {
@ -1826,8 +1819,8 @@ static bool esil_peek_n(RzAnalysisEsil *esil, int bits) {
if (bits == 128) {
ut8 a[sizeof(ut64) * 2] = { 0 };
rz_analysis_esil_mem_read(esil, addr, a, bytes);
ut64 b = rz_read_ble(a, esil->analysis->big_endian, bits);
ut64 c = rz_read_ble(a + 8, esil->analysis->big_endian, bits);
ut64 b = rz_read_ble(a, EANALYSIS(esil)->big_endian, bits);
ut64 c = rz_read_ble(a + 8, EANALYSIS(esil)->big_endian, bits);
rz_strf(res, "0x%" PFMT64x, b);
rz_analysis_esil_push(esil, res);
rz_strf(res, "0x%" PFMT64x, c);
@ -1838,7 +1831,7 @@ static bool esil_peek_n(RzAnalysisEsil *esil, int bits) {
ut64 bitmask = genmask(bits - 1);
ut8 a[sizeof(ut64)] = { 0 };
rz_analysis_esil_mem_read(esil, addr, a, bytes);
ut64 b = rz_read_ble(a, esil->analysis->big_endian, bits);
ut64 b = rz_read_ble(a, EANALYSIS(esil)->big_endian, bits);
rz_strf(res, "0x%" PFMT64x, b & bitmask);
rz_analysis_esil_push(esil, res);
esil->lastsz = bits;
@ -1878,7 +1871,7 @@ static bool esil_stack(RzAnalysisEsil *esil) {
}
static bool esil_peek(RzAnalysisEsil *esil) {
return esil_peek_n(esil, esil->analysis->bits);
return esil_peek_n(esil, EANALYSIS(esil)->bits);
};
static bool esil_peek_some(RzAnalysisEsil *esil) {
@ -1905,7 +1898,7 @@ static bool esil_peek_some(RzAnalysisEsil *esil) {
}
const ut32 read = rz_analysis_esil_mem_read(esil, ptr, a, 4);
if (read == 4) { // this is highly questionabla
num32 = rz_read_ble32(a, esil->analysis->big_endian);
num32 = rz_read_ble32(a, EANALYSIS(esil)->big_endian);
rz_analysis_esil_reg_write(esil, foo, num32);
} else {
ESIL_LOG("Cannot peek from 0x%08" PFMT64x "\n", ptr);
@ -1966,7 +1959,7 @@ static bool esil_mem_oreq8(RzAnalysisEsil *esil) {
return esil_mem_oreq_n(esil, 64);
}
static bool esil_mem_oreq(RzAnalysisEsil *esil) {
return esil_mem_oreq_n(esil, esil->analysis->bits);
return esil_mem_oreq_n(esil, EANALYSIS(esil)->bits);
}
/* XOREQ */
@ -2012,7 +2005,7 @@ static bool esil_mem_xoreq8(RzAnalysisEsil *esil) {
return esil_mem_xoreq_n(esil, 64);
}
static bool esil_mem_xoreq(RzAnalysisEsil *esil) {
return esil_mem_xoreq_n(esil, esil->analysis->bits);
return esil_mem_xoreq_n(esil, EANALYSIS(esil)->bits);
}
/* ANDEQ */
@ -2058,7 +2051,7 @@ static bool esil_mem_andeq8(RzAnalysisEsil *esil) {
return esil_mem_andeq_n(esil, 64);
}
static bool esil_mem_andeq(RzAnalysisEsil *esil) {
return esil_mem_andeq_n(esil, esil->analysis->bits);
return esil_mem_andeq_n(esil, EANALYSIS(esil)->bits);
}
/* ADDEQ */
@ -2104,7 +2097,7 @@ static bool esil_mem_addeq8(RzAnalysisEsil *esil) {
return esil_mem_addeq_n(esil, 64);
}
static bool esil_mem_addeq(RzAnalysisEsil *esil) {
return esil_mem_addeq_n(esil, esil->analysis->bits);
return esil_mem_addeq_n(esil, EANALYSIS(esil)->bits);
}
/* SUBEQ */
@ -2150,7 +2143,7 @@ static bool esil_mem_subeq8(RzAnalysisEsil *esil) {
return esil_mem_subeq_n(esil, 64);
}
static bool esil_mem_subeq(RzAnalysisEsil *esil) {
return esil_mem_subeq_n(esil, esil->analysis->bits);
return esil_mem_subeq_n(esil, EANALYSIS(esil)->bits);
}
/* MODEQ */
@ -2203,7 +2196,7 @@ static bool esil_mem_modeq8(RzAnalysisEsil *esil) {
return esil_mem_modeq_n(esil, 64);
}
static bool esil_mem_modeq(RzAnalysisEsil *esil) {
return esil_mem_modeq_n(esil, esil->analysis->bits);
return esil_mem_modeq_n(esil, EANALYSIS(esil)->bits);
}
/* DIVEQ */
@ -2255,7 +2248,7 @@ static bool esil_mem_diveq8(RzAnalysisEsil *esil) {
return esil_mem_diveq_n(esil, 64);
}
static bool esil_mem_diveq(RzAnalysisEsil *esil) {
return esil_mem_diveq_n(esil, esil->analysis->bits);
return esil_mem_diveq_n(esil, EANALYSIS(esil)->bits);
}
/* MULEQ */
@ -2302,7 +2295,7 @@ static bool esil_mem_muleq8(RzAnalysisEsil *esil) {
}
static bool esil_mem_muleq(RzAnalysisEsil *esil) {
switch (esil->analysis->bits) {
switch (EANALYSIS(esil)->bits) {
case 64: return esil_mem_muleq8(esil);
case 32: return esil_mem_muleq4(esil);
case 16: return esil_mem_muleq2(esil);
@ -2355,7 +2348,7 @@ static bool esil_mem_inceq8(RzAnalysisEsil *esil) {
return esil_mem_inceq_n(esil, 64);
}
static bool esil_mem_inceq(RzAnalysisEsil *esil) {
return esil_mem_inceq_n(esil, esil->analysis->bits);
return esil_mem_inceq_n(esil, EANALYSIS(esil)->bits);
}
/* DECEQ */
@ -2399,7 +2392,7 @@ static bool esil_mem_deceq8(RzAnalysisEsil *esil) {
return esil_mem_deceq_n(esil, 64);
}
static bool esil_mem_deceq(RzAnalysisEsil *esil) {
return esil_mem_deceq_n(esil, esil->analysis->bits);
return esil_mem_deceq_n(esil, EANALYSIS(esil)->bits);
}
/* LSLEQ */
@ -2453,7 +2446,7 @@ static bool esil_mem_lsleq8(RzAnalysisEsil *esil) {
return esil_mem_lsleq_n(esil, 64);
}
static bool esil_mem_lsleq(RzAnalysisEsil *esil) {
return esil_mem_lsleq_n(esil, esil->analysis->bits);
return esil_mem_lsleq_n(esil, EANALYSIS(esil)->bits);
}
/* LSREQ */
@ -2499,7 +2492,7 @@ static bool esil_mem_lsreq8(RzAnalysisEsil *esil) {
return esil_mem_lsreq_n(esil, 64);
}
static bool esil_mem_lsreq(RzAnalysisEsil *esil) {
return esil_mem_lsreq_n(esil, esil->analysis->bits);
return esil_mem_lsreq_n(esil, EANALYSIS(esil)->bits);
}
/* get value of register or memory reference and push the value */
@ -2582,9 +2575,9 @@ static bool esil_smaller(RzAnalysisEsil *esil) { // 'dst < src' => 'src,dst,<'
esil->old = num;
esil->cur = num - num2;
ret = true;
if (rz_reg_get(esil->analysis->reg, dst, -1)) {
if (rz_reg_get(EANALYSIS(esil)->reg, dst, -1)) {
esil->lastsz = esil_internal_sizeof_reg(esil, dst);
} else if (rz_reg_get(esil->analysis->reg, src, -1)) {
} else if (rz_reg_get(EANALYSIS(esil)->reg, src, -1)) {
esil->lastsz = esil_internal_sizeof_reg(esil, src);
} else {
// default size is set to 64 as internally operands are ut64
@ -2608,9 +2601,9 @@ static bool esil_bigger(RzAnalysisEsil *esil) { // 'dst > src' => 'src,dst,>'
esil->old = num;
esil->cur = num - num2;
ret = true;
if (rz_reg_get(esil->analysis->reg, dst, -1)) {
if (rz_reg_get(EANALYSIS(esil)->reg, dst, -1)) {
esil->lastsz = esil_internal_sizeof_reg(esil, dst);
} else if (rz_reg_get(esil->analysis->reg, src, -1)) {
} else if (rz_reg_get(EANALYSIS(esil)->reg, src, -1)) {
esil->lastsz = esil_internal_sizeof_reg(esil, src);
} else {
// default size is set to 64 as internally operands are ut64
@ -2634,9 +2627,9 @@ static bool esil_smaller_equal(RzAnalysisEsil *esil) { // 'dst <= src' => 'src,d
esil->old = num;
esil->cur = num - num2;
ret = true;
if (rz_reg_get(esil->analysis->reg, dst, -1)) {
if (rz_reg_get(EANALYSIS(esil)->reg, dst, -1)) {
esil->lastsz = esil_internal_sizeof_reg(esil, dst);
} else if (rz_reg_get(esil->analysis->reg, src, -1)) {
} else if (rz_reg_get(EANALYSIS(esil)->reg, src, -1)) {
esil->lastsz = esil_internal_sizeof_reg(esil, src);
} else {
// default size is set to 64 as internally operands are ut64
@ -2660,9 +2653,9 @@ static bool esil_bigger_equal(RzAnalysisEsil *esil) { // 'dst >= src' => 'src,ds
esil->old = num;
esil->cur = num - num2;
ret = true;
if (rz_reg_get(esil->analysis->reg, dst, -1)) {
if (rz_reg_get(EANALYSIS(esil)->reg, dst, -1)) {
esil->lastsz = esil_internal_sizeof_reg(esil, dst);
} else if (rz_reg_get(esil->analysis->reg, src, -1)) {
} else if (rz_reg_get(EANALYSIS(esil)->reg, src, -1)) {
esil->lastsz = esil_internal_sizeof_reg(esil, src);
} else {
// default size is set to 64 as internally operands are ut64
@ -2889,8 +2882,8 @@ repeat:
wordi = 0;
while (*str) {
if (str == hashbang) {
if (esil->analysis && esil->analysis->coreb.setab) {
esil->analysis->coreb.cmd(esil->analysis->coreb.core, str + 2);
if (EANALYSIS(esil) && EANALYSIS(esil)->coreb.setab) {
EANALYSIS(esil)->coreb.cmd(EANALYSIS(esil)->coreb.core, str + 2);
}
break;
}
@ -3158,11 +3151,11 @@ static void rz_analysis_esil_setup_ops(RzAnalysisEsil *esil) {
}
/* register callbacks using this analysis module. */
RZ_API bool rz_analysis_esil_setup(RzAnalysisEsil *esil, RzAnalysis *analysis, int romem, int stats, int nonull, RzCore *core) {
RZ_API bool rz_analysis_esil_setup(RzAnalysisEsil *esil, void /*RzAnalysis*/ *panalysis, int romem, int stats, int nonull, void /*RzCore*/ *pcore) {
rz_return_val_if_fail(esil, false);
// esil->debug = 0;
esil->core = core;
esil->analysis = analysis;
esil->pcore = pcore;
esil->panalysis = panalysis;
esil->parse_goto_count = RZ_ANALYSIS_ESIL_GOTO_LIMIT;
esil->trap = 0;
esil->trap_code = 0;
@ -3187,7 +3180,9 @@ RZ_API bool rz_analysis_esil_setup(RzAnalysisEsil *esil, RzAnalysis *analysis, i
rz_analysis_esil_stats(esil, stats);
rz_analysis_esil_setup_ops(esil);
return (analysis->cur && analysis->cur->esil_init)
? analysis->cur->esil_init(esil)
: true;
RzAnalysis *analysis = panalysis;
if (analysis->cur && analysis->cur->esil_init) {
return analysis->cur->esil_init(esil);
}
return true;
}

View file

@ -1,9 +1,8 @@
// SPDX-FileCopyrightText: 2018 condret <condr3t@protonmail.com>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_esil/rz_esil.h>
#include "analysis_private.h"
#include <rz_util.h>
#include <rz_lib.h>
static void interrupt_free(RzAnalysisEsilInterrupt *i) {
rz_analysis_esil_interrupt_free(i->esil, i);

View file

@ -1,9 +1,8 @@
// SPDX-FileCopyrightText: 2018 condret <condr3t@protonmail.com>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_esil/rz_esil.h>
#include "analysis_private.h"
#include <rz_util.h>
#include <rz_lib.h>
RZ_API void rz_analysis_esil_sources_init(RzAnalysisEsil *esil) {
if (esil && !esil->sources) {

View file

@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: 2014 pancake <pancake@nopcode.org>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_esil/rz_esil.h>
#include "analysis_private.h"
static int hook_flag_read(RzAnalysisEsil *esil, const char *flag, ut64 *num) {

View file

@ -2,13 +2,12 @@
// SPDX-FileCopyrightText: 2015-2020 rkx1209 <rkx1209dev@gmail.com>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_esil/rz_esil.h>
#include "analysis_private.h"
#define CMP_REG_CHANGE(x, y) ((x) - ((RzAnalysisEsilRegChange *)(y))->idx)
#define CMP_MEM_CHANGE(x, y) ((x) - ((RzAnalysisEsilMemChange *)(y))->idx)
#define ESILISTATE esil->analysis->esilinterstate
// IL trace wrapper of esil
static inline bool esil_add_mem_trace(RzAnalysisEsilTrace *etrace, RzILTraceMemOp *mem) {
RzILTraceInstruction *instr_trace = rz_analysis_esil_get_instruction_trace(etrace, etrace->idx);
@ -22,6 +21,7 @@ static inline bool esil_add_reg_trace(RzAnalysisEsilTrace *etrace, RzILTraceRegO
RZ_API RzAnalysisEsilTrace *rz_analysis_esil_trace_new(RzAnalysisEsil *esil) {
rz_return_val_if_fail(esil && esil->stack_addr && esil->stack_size, NULL);
RzAnalysis *analysis = esil->panalysis;
size_t i;
RzAnalysisEsilTrace *trace = RZ_NEW0(RzAnalysisEsilTrace);
if (!trace) {
@ -50,11 +50,10 @@ RZ_API RzAnalysisEsilTrace *rz_analysis_esil_trace_new(RzAnalysisEsil *esil) {
RZ_LOG_ERROR("esil: Cannot allocate stack for trace\n");
goto error;
}
esil->analysis->iob.read_at(esil->analysis->iob.io, trace->stack_addr,
trace->stack_data, trace->stack_size);
analysis->iob.read_at(analysis->iob.io, trace->stack_addr, trace->stack_data, trace->stack_size);
// Save initial registers arenas
for (i = 0; i < RZ_REG_TYPE_LAST; i++) {
RzRegArena *a = esil->analysis->reg->regset[i].arena;
RzRegArena *a = analysis->reg->regset[i].arena;
RzRegArena *b = rz_reg_arena_new(a->size);
if (!b) {
RZ_LOG_ERROR("esil: Cannot allocate register arena for trace\n");
@ -122,23 +121,24 @@ static int trace_hook_reg_read(RzAnalysisEsil *esil, const char *name, ut64 *res
// RZ_LOG_WARN("Register not found in profile\n");
return 0;
}
if (ESILISTATE->callbacks.hook_reg_read) {
if (esil->esilinterstate->callbacks.hook_reg_read) {
RzAnalysisEsilCallbacks cbs = esil->cb;
esil->cb = ESILISTATE->callbacks;
ret = ESILISTATE->callbacks.hook_reg_read(esil, name, res, size);
esil->cb = esil->esilinterstate->callbacks;
ret = esil->esilinterstate->callbacks.hook_reg_read(esil, name, res, size);
esil->cb = cbs;
}
if (!ret && esil->cb.reg_read) {
ret = esil->cb.reg_read(esil, name, res, size);
}
if (ret) {
RzAnalysis *analysis = esil->panalysis;
// Trace reg read behavior
RzILTraceRegOp *reg_read = RZ_NEW0(RzILTraceRegOp);
if (!reg_read) {
RZ_LOG_ERROR("failed to init reg read trace\n");
return 0;
}
reg_read->reg_name = rz_str_constpool_get(&esil->analysis->constpool, name);
reg_read->reg_name = rz_str_constpool_get(&analysis->constpool, name);
reg_read->behavior = RZ_IL_TRACE_OP_READ;
reg_read->value = *res;
if (!esil_add_reg_trace(esil->trace, reg_read)) {
@ -150,6 +150,7 @@ static int trace_hook_reg_read(RzAnalysisEsil *esil, const char *name, ut64 *res
static int trace_hook_reg_write(RzAnalysisEsil *esil, const char *name, ut64 *val) {
int ret = 0;
RzAnalysis *analysis = esil->panalysis;
// add reg write to trace
RzILTraceRegOp *reg_write = RZ_NEW0(RzILTraceRegOp);
@ -157,19 +158,19 @@ static int trace_hook_reg_write(RzAnalysisEsil *esil, const char *name, ut64 *va
RZ_LOG_ERROR("failed to init reg write\n");
return ret;
}
reg_write->reg_name = rz_str_constpool_get(&esil->analysis->constpool, name);
reg_write->reg_name = rz_str_constpool_get(&analysis->constpool, name);
reg_write->behavior = RZ_IL_TRACE_OP_WRITE;
reg_write->value = *val;
if (!esil_add_reg_trace(esil->trace, reg_write)) {
RZ_FREE(reg_write);
}
RzRegItem *ri = rz_reg_get(esil->analysis->reg, name, -1);
RzRegItem *ri = rz_reg_get(analysis->reg, name, -1);
add_reg_change(esil->trace, esil->trace->idx + 1, ri, *val);
if (ESILISTATE->callbacks.hook_reg_write) {
if (esil->esilinterstate->callbacks.hook_reg_write) {
RzAnalysisEsilCallbacks cbs = esil->cb;
esil->cb = ESILISTATE->callbacks;
ret = ESILISTATE->callbacks.hook_reg_write(esil, name, val);
esil->cb = esil->esilinterstate->callbacks;
ret = esil->esilinterstate->callbacks.hook_reg_write(esil, name, val);
esil->cb = cbs;
}
return ret;
@ -202,10 +203,10 @@ static int trace_hook_mem_read(RzAnalysisEsil *esil, ut64 addr, ut8 *buf, int le
RZ_FREE(mem_read);
}
if (ESILISTATE->callbacks.hook_mem_read) {
if (esil->esilinterstate->callbacks.hook_mem_read) {
RzAnalysisEsilCallbacks cbs = esil->cb;
esil->cb = ESILISTATE->callbacks;
ret = ESILISTATE->callbacks.hook_mem_read(esil, addr, buf, len);
esil->cb = esil->esilinterstate->callbacks;
ret = esil->esilinterstate->callbacks.hook_mem_read(esil, addr, buf, len);
esil->cb = cbs;
}
return ret;
@ -240,10 +241,10 @@ static int trace_hook_mem_write(RzAnalysisEsil *esil, ut64 addr, const ut8 *buf,
add_mem_change(esil->trace, esil->trace->idx + 1, addr + i, buf[i]);
}
if (ESILISTATE->callbacks.hook_mem_write) {
if (esil->esilinterstate->callbacks.hook_mem_write) {
RzAnalysisEsilCallbacks cbs = esil->cb;
esil->cb = ESILISTATE->callbacks;
ret = ESILISTATE->callbacks.hook_mem_write(esil, addr, buf, len);
esil->cb = esil->esilinterstate->callbacks;
ret = esil->esilinterstate->callbacks.hook_mem_write(esil, addr, buf, len);
esil->cb = cbs;
}
return ret;
@ -255,7 +256,7 @@ static int trace_hook_mem_write(RzAnalysisEsil *esil, ut64 addr, const ut8 *buf,
* \param idx int, index of instruction
* \return RzILTraceInstruction *, instruction trace at index
*/
RZ_API RZ_BORROW RzILTraceInstruction *rz_analysis_esil_get_instruction_trace(RZ_NONNULL RzAnalysisEsilTrace *etrace, int idx) {
RZ_API RZ_BORROW void /*RzILTraceInstruction*/ *rz_analysis_esil_get_instruction_trace(RZ_NONNULL RzAnalysisEsilTrace *etrace, int idx) {
rz_return_val_if_fail(etrace, NULL);
if (idx < 0 || idx >= rz_pvector_len(etrace->instructions)) {
return NULL;
@ -263,10 +264,9 @@ RZ_API RZ_BORROW RzILTraceInstruction *rz_analysis_esil_get_instruction_trace(RZ
return rz_pvector_at(etrace->instructions, idx);
}
RZ_API void rz_analysis_esil_trace_op(RzAnalysisEsil *esil, RZ_NONNULL RzAnalysisOp *op) {
rz_return_if_fail(esil && op);
const char *expr = rz_strbuf_get(&op->esil);
if (RZ_STR_ISEMPTY(expr)) {
RZ_API void rz_analysis_esil_trace_op(RzAnalysisEsil *esil, ut64 pc, RZ_NULLABLE const char *esil_expr) {
rz_return_if_fail(esil);
if (RZ_STR_ISEMPTY(esil_expr)) {
// do nothing
return;
}
@ -283,17 +283,18 @@ RZ_API void rz_analysis_esil_trace_op(RzAnalysisEsil *esil, RZ_NONNULL RzAnalysi
}
/* save old callbacks */
int esil_verbose = esil->verbose;
if (ESILISTATE->callbacks_set) {
if (esil->esilinterstate->callbacks_set) {
RZ_LOG_ERROR("esil: Cannot call recursively\n");
}
ESILISTATE->callbacks = esil->cb;
ESILISTATE->callbacks_set = true;
esil->esilinterstate->callbacks = esil->cb;
esil->esilinterstate->callbacks_set = true;
RzILTraceInstruction *instruction = rz_analysis_il_trace_instruction_new(op->addr);
RzILTraceInstruction *instruction = rz_analysis_il_trace_instruction_new(pc);
rz_pvector_push(esil->trace->instructions, instruction);
RzRegItem *pc_ri = rz_reg_get(esil->analysis->reg, "PC", -1);
add_reg_change(esil->trace, esil->trace->idx, pc_ri, op->addr);
RzAnalysis *analysis = esil->panalysis;
RzRegItem *pc_ri = rz_reg_get(analysis->reg, "PC", -1);
add_reg_change(esil->trace, esil->trace->idx, pc_ri, pc);
/* set hooks */
esil->verbose = 0;
esil->cb.hook_reg_read = trace_hook_reg_read;
@ -302,11 +303,11 @@ RZ_API void rz_analysis_esil_trace_op(RzAnalysisEsil *esil, RZ_NONNULL RzAnalysi
esil->cb.hook_mem_write = trace_hook_mem_write;
/* evaluate esil expression */
rz_analysis_esil_parse(esil, expr);
rz_analysis_esil_parse(esil, esil_expr);
rz_analysis_esil_stack_free(esil);
/* restore hooks */
esil->cb = ESILISTATE->callbacks;
ESILISTATE->callbacks_set = false;
esil->cb = esil->esilinterstate->callbacks;
esil->esilinterstate->callbacks_set = false;
esil->verbose = esil_verbose;
/* increment idx */
esil->trace->idx++;
@ -320,8 +321,9 @@ static bool restore_memory_cb(void *user, const ut64 key, const void *value) {
rz_vector_upper_bound(vmem, esil->trace->idx, index, CMP_MEM_CHANGE);
if (index > 0 && index <= vmem->len) {
RzAnalysis *analysis = esil->panalysis;
RzAnalysisEsilMemChange *c = rz_vector_index_ptr(vmem, index - 1);
esil->analysis->iob.write_at(esil->analysis->iob.io, key, &c->data, 1);
analysis->iob.write_at(analysis->iob.io, key, &c->data, 1);
}
return true;
}
@ -332,8 +334,9 @@ static bool restore_register(RzAnalysisEsil *esil, RzRegItem *ri, int idx) {
if (vreg) {
rz_vector_upper_bound(vreg, idx, index, CMP_REG_CHANGE);
if (index > 0 && index <= vreg->len) {
RzAnalysis *analysis = esil->panalysis;
RzAnalysisEsilRegChange *c = rz_vector_index_ptr(vreg, index - 1);
rz_reg_set_value(esil->analysis->reg, ri, c->data);
rz_reg_set_value(analysis->reg, ri, c->data);
}
}
return true;
@ -342,26 +345,27 @@ static bool restore_register(RzAnalysisEsil *esil, RzRegItem *ri, int idx) {
RZ_API void rz_analysis_esil_trace_restore(RzAnalysisEsil *esil, int idx) {
rz_return_if_fail(esil);
size_t i;
RzAnalysis *analysis = esil->panalysis;
RzAnalysisEsilTrace *trace = esil->trace;
// Restore initial state when going backward
if (idx < esil->trace->idx) {
// Restore initial registers value
for (i = 0; i < RZ_REG_TYPE_LAST; i++) {
RzRegArena *a = esil->analysis->reg->regset[i].arena;
RzRegArena *a = analysis->reg->regset[i].arena;
RzRegArena *b = trace->arena[i];
if (a && b) {
memcpy(a->bytes, b->bytes, a->size);
}
}
// Restore initial stack memory
esil->analysis->iob.write_at(esil->analysis->iob.io, trace->stack_addr,
analysis->iob.write_at(analysis->iob.io, trace->stack_addr,
trace->stack_data, trace->stack_size);
}
// Apply latest changes to registers and memory
esil->trace->idx = idx;
RzListIter *iter;
RzRegItem *ri;
rz_list_foreach (esil->analysis->reg->allregs, iter, ri) {
rz_list_foreach (analysis->reg->allregs, iter, ri) {
restore_register(esil, ri, idx);
}
ht_up_foreach(trace->memory, restore_memory_cb, esil);

View file

@ -17,10 +17,10 @@
* \param rzil RZ_IL instance
* \return pointer to RzilTrace
*/
RZ_API RzAnalysisRzilTrace *rz_analysis_rzil_trace_new(RzAnalysis *analysis, RZ_NONNULL RzAnalysisILVM *rzil) {
RZ_API RzAnalysisILTrace *rz_analysis_il_trace_new(RzAnalysis *analysis, RZ_NONNULL RzAnalysisILVM *rzil) {
rz_return_val_if_fail(rzil, NULL);
size_t i;
RzAnalysisEsilTrace *trace = RZ_NEW0(RzAnalysisEsilTrace);
RzAnalysisILTrace *trace = RZ_NEW0(RzAnalysisILTrace);
if (!trace) {
return NULL;
}
@ -59,7 +59,7 @@ RZ_API RzAnalysisRzilTrace *rz_analysis_rzil_trace_new(RzAnalysis *analysis, RZ_
}
return trace;
error:
rz_analysis_esil_trace_free(trace);
rz_analysis_il_trace_free(trace);
return NULL;
}
@ -67,7 +67,7 @@ error:
* Free an IL trace
* \param trace trace to be free
*/
RZ_API void rz_analysis_rzil_trace_free(RzAnalysisEsilTrace *trace) {
RZ_API void rz_analysis_il_trace_free(RzAnalysisILTrace *trace) {
size_t i;
if (!trace) {
return;
@ -90,6 +90,6 @@ RZ_API void rz_analysis_rzil_trace_free(RzAnalysisEsilTrace *trace) {
* \param rzil IL instance
* \param op RzAnalysisRzilOp, a general IL op structure (Designed for switching between different implementations of IL op struct)
*/
RZ_API void rz_analysis_rzil_trace_op(RzAnalysis *analysis, RZ_NONNULL RzAnalysisILVM *rzil, RZ_NONNULL RzAnalysisLiftedILOp op) {
RZ_API void rz_analysis_il_trace_op(RzAnalysis *analysis, RZ_NONNULL RzAnalysisILVM *rzil, RZ_NONNULL RzAnalysisLiftedILOp op) {
// TODO : rewrite this file when migrate to new op structure
}

View file

@ -1405,9 +1405,10 @@ static OPCODE_DESC *avr_op_analyze(RzAnalysis *analysis, RzAnalysisOp *op, ut64
}
static bool avr_custom_des(RzAnalysisEsil *esil) {
if (!esil || !esil->analysis || !esil->analysis->reg) {
if (!esil) {
return false;
}
ut64 arg;
if (!__esil_pop_argument(esil, &arg)) {
return false;
@ -1487,9 +1488,10 @@ static bool avr_custom_spm_page_erase(RzAnalysisEsil *esil) {
ut64 addr, page_size_bits, i;
// sanity check
if (!esil || !esil->analysis || !esil->analysis->reg) {
if (!esil || !esil->panalysis) {
return false;
}
RzAnalysis *analysis = esil->panalysis;
// get target address
if (!__esil_pop_argument(esil, &addr)) {
@ -1497,7 +1499,7 @@ static bool avr_custom_spm_page_erase(RzAnalysisEsil *esil) {
}
// get details about current MCU and fix input address
cpu = get_cpu_model(esil->analysis->cpu);
cpu = get_cpu_model(analysis->cpu);
page_size_bits = const_get_value(const_by_name(cpu, CPU_CONST_PARAM, "page_size"));
// align base address to page_size_bits
@ -1521,9 +1523,10 @@ static bool avr_custom_spm_page_fill(RzAnalysisEsil *esil) {
ut8 r0, r1;
// sanity check
if (!esil || !esil->analysis || !esil->analysis->reg) {
if (!esil || !esil->panalysis) {
return false;
}
RzAnalysis *analysis = esil->panalysis;
// get target address, r0, r1
if (!__esil_pop_argument(esil, &addr)) {
@ -1541,7 +1544,7 @@ static bool avr_custom_spm_page_fill(RzAnalysisEsil *esil) {
r1 = i;
// get details about current MCU and fix input address
cpu = get_cpu_model(esil->analysis->cpu);
cpu = get_cpu_model(analysis->cpu);
page_size_bits = const_get_value(const_by_name(cpu, CPU_CONST_PARAM, "page_size"));
// align and crop base address
@ -1562,9 +1565,10 @@ static bool avr_custom_spm_page_write(RzAnalysisEsil *esil) {
ut64 addr, page_size_bits, tmp_page;
// sanity check
if (!esil || !esil->analysis || !esil->analysis->reg) {
if (!esil || !esil->panalysis) {
return false;
}
RzAnalysis *analysis = esil->panalysis;
// get target address
if (!__esil_pop_argument(esil, &addr)) {
@ -1573,7 +1577,7 @@ static bool avr_custom_spm_page_write(RzAnalysisEsil *esil) {
// get details about current MCU and fix input address and base address
// of the internal temporary page
cpu = get_cpu_model(esil->analysis->cpu);
cpu = get_cpu_model(analysis->cpu);
page_size_bits = const_get_value(const_by_name(cpu, CPU_CONST_PARAM, "page_size"));
rz_analysis_esil_reg_read(esil, "_page", &tmp_page, NULL);
@ -1595,12 +1599,13 @@ static bool avr_custom_spm_page_write(RzAnalysisEsil *esil) {
static int esil_avr_hook_reg_write(RzAnalysisEsil *esil, const char *name, ut64 *val) {
CPU_MODEL *cpu;
if (!esil || !esil->analysis) {
if (!esil || !esil->panalysis) {
return 0;
}
RzAnalysis *analysis = esil->panalysis;
// select cpu info
cpu = get_cpu_model(esil->analysis->cpu);
cpu = get_cpu_model(analysis->cpu);
// crop registers and force certain values
if (!strcmp(name, "pc")) {
@ -1618,7 +1623,8 @@ static int esil_avr_hook_reg_write(RzAnalysisEsil *esil, const char *name, ut64
return 0;
}
RZ_IPI int rz_avr_esil_init(RzAnalysisEsil *esil) {
RZ_IPI bool rz_avr_esil_init(void *pesil) {
RzAnalysisEsil *esil = pesil;
if (!esil) {
return false;
}
@ -1631,10 +1637,6 @@ RZ_IPI int rz_avr_esil_init(RzAnalysisEsil *esil) {
return true;
}
RZ_IPI int rz_avr_esil_fini(RzAnalysisEsil *esil) {
return true;
}
RZ_IPI void rz_avr_esil_opcode(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len) {
// select cpu info
CPU_MODEL *cpu = get_cpu_model(analysis->cpu);

View file

@ -5,8 +5,7 @@
#define RZ_AVR_ESIL_H
#include "analysis_private.h"
RZ_IPI int rz_avr_esil_init(RzAnalysisEsil *esil);
RZ_IPI int rz_avr_esil_fini(RzAnalysisEsil *esil);
RZ_IPI bool rz_avr_esil_init(void *pesil);
RZ_IPI void rz_avr_esil_opcode(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len);
#endif /* RZ_AVR_ESIL_H */

View file

@ -1844,22 +1844,20 @@ static char *_6502_get_reg_profile(RzAnalysis *analysis) {
return rz_str_dup(p);
}
static int _6502_esil_init(RzAnalysisEsil *esil) {
if (esil->analysis && esil->analysis->reg) { // initial values
rz_reg_set_value(esil->analysis->reg, rz_reg_get(esil->analysis->reg, "pc", -1), 0x0000);
rz_reg_set_value(esil->analysis->reg, rz_reg_get(esil->analysis->reg, "sp", -1), 0xff);
rz_reg_set_value(esil->analysis->reg, rz_reg_get(esil->analysis->reg, "a", -1), 0x00);
rz_reg_set_value(esil->analysis->reg, rz_reg_get(esil->analysis->reg, "x", -1), 0x00);
rz_reg_set_value(esil->analysis->reg, rz_reg_get(esil->analysis->reg, "y", -1), 0x00);
rz_reg_set_value(esil->analysis->reg, rz_reg_get(esil->analysis->reg, "flags", -1), 0x00);
static bool _6502_esil_init(void *pesil) {
RzAnalysisEsil *esil = pesil;
RzAnalysis *analysis = esil->panalysis;
if (analysis && analysis->reg) { // initial values
rz_reg_set_value(analysis->reg, rz_reg_get(analysis->reg, "pc", -1), 0x0000);
rz_reg_set_value(analysis->reg, rz_reg_get(analysis->reg, "sp", -1), 0xff);
rz_reg_set_value(analysis->reg, rz_reg_get(analysis->reg, "a", -1), 0x00);
rz_reg_set_value(analysis->reg, rz_reg_get(analysis->reg, "x", -1), 0x00);
rz_reg_set_value(analysis->reg, rz_reg_get(analysis->reg, "y", -1), 0x00);
rz_reg_set_value(analysis->reg, rz_reg_get(analysis->reg, "flags", -1), 0x00);
}
return true;
}
static int _6502_esil_fini(RzAnalysisEsil *esil) {
return true;
}
static int _6502_address_bits(RzAnalysis *analysis, int bits) {
return 16;
}
@ -1904,7 +1902,6 @@ RzAnalysisPlugin rz_analysis_plugin_6502 = {
.get_reg_profile = &_6502_get_reg_profile,
.esil = true,
.esil_init = _6502_esil_init,
.esil_fini = _6502_esil_fini,
.il_config = _6502_il_config,
.archinfo = _6502_archinfo,
};

View file

@ -912,80 +912,11 @@ static void analyze_op_esil(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut
break;
}
}
#if 0
// custom reg read/write temporarily disabled - see r2 issue #9242
static int i8051_hook_reg_read(RzAnalysisEsil *, const char *, ut64 *, int *);
static int i8051_reg_compare(const void *name, const void *reg) {
return strcmp ((const char*)name, ((RI8051Reg*)reg)->name);
}
static RI8051Reg *i8051_reg_find(const char *name) {
return (RI8051Reg *) bsearch (
name, registers,
sizeof (registers) / sizeof (registers[0]),
sizeof (registers[0]),
i8051_reg_compare);
}
static int i8051_reg_get_offset(RzAnalysisEsil *esil, RI8051Reg *ri) {
ut8 offset = ri->offset;
if (ri->banked) {
ut64 psw = 0LL;
i8051_hook_reg_read (esil, "psw", &psw, NULL);
offset += psw & 0x18;
}
return offset;
}
// dkreuter: It would be nice if we could attach hooks to RzRegItems directly.
// That way we could avoid doing a string lookup on register names
// as rz_reg_get already does this. Also, the analysis esil callbacks
// approach interferes with rz_reg_arena_swap.
static int i8051_hook_reg_read(RzAnalysisEsil *esil, const char *name, ut64 *res, int *size) {
int ret = 0;
ut64 val = 0LL;
RI8051Reg *ri;
RzAnalysisEsilCallbacks cbs = esil->cb;
if ((ri = i8051_reg_find (name))) {
ut8 offset = i8051_reg_get_offset(esil, ri);
ret = rz_analysis_esil_mem_read (esil, IRAM_BASE + offset, (ut8*)res, ri->num_bytes);
}
esil->cb = ocbs;
if (!ret && ocbs.hook_reg_read) {
ret = ocbs.hook_reg_read (esil, name, res, NULL);
}
if (!ret && ocbs.reg_read) {
ret = ocbs.reg_read (esil, name, &val, NULL);
}
esil->cb = cbs;
return ret;
}
static int i8051_hook_reg_write(RzAnalysisEsil *esil, const char *name, ut64 *val) {
int ret = 0;
RI8051Reg *ri;
RzAnalysisEsilCallbacks cbs = esil->cb;
if ((ri = i8051_reg_find (name))) {
ut8 offset = i8051_reg_get_offset(esil, ri);
ret = rz_analysis_esil_mem_write (esil, IRAM_BASE + offset, (ut8*)val, ri->num_bytes);
}
esil->cb = ocbs;
if (!ret && ocbs.hook_reg_write) {
ret = ocbs.hook_reg_write (esil, name, val);
}
esil->cb = cbs;
return ret;
}
#endif
static int esil_i8051_init(RzAnalysisEsil *esil) {
static bool esil_i8051_init(void *pesil) {
RzAnalysisEsil *esil = pesil;
RzAnalysis *analysis = esil->panalysis;
// reset emulation control registers based on cpu
set_cpu_model(esil->analysis, true);
set_cpu_model(analysis, true);
if (esil->cb.user) {
return true;
@ -1005,7 +936,8 @@ static int esil_i8051_init(RzAnalysisEsil *esil) {
return true;
}
static int esil_i8051_fini(RzAnalysisEsil *esil) {
static bool esil_i8051_fini(void *pesil) {
RzAnalysisEsil *esil = pesil;
RZ_FREE(esil->cb.user);
return true;
}

View file

@ -490,7 +490,6 @@ RzAnalysisPlugin rz_analysis_plugin_avr = {
.op = &avr_op,
.get_reg_profile = &get_reg_profile,
.esil_init = rz_avr_esil_init,
.esil_fini = rz_avr_esil_fini,
.il_config = rz_avr_il_config,
.analysis_mask = analysis_mask_avr,
};

View file

@ -1131,7 +1131,7 @@ static inline void gb_analysis_cb_srl(RzAnalysisOpMask mask, RzReg *reg, RzAnaly
}
static bool gb_custom_daa(RzAnalysisEsil *esil) {
if (!esil || !esil->analysis || !esil->analysis->reg) {
if (!esil) {
return false;
}
char *v = rz_analysis_esil_pop(esil);
@ -2005,22 +2005,25 @@ static char *gb_get_reg_profile(RzAnalysis *analysis) {
return rz_str_dup(p);
}
static int gb_esil_init(RzAnalysisEsil *esil) {
static bool gb_esil_init(void *pesil) {
RzAnalysisEsil *esil = pesil;
RzAnalysis *analysis = esil->panalysis;
GBUser *user = RZ_NEW0(GBUser);
rz_analysis_esil_set_op(esil, "daa", gb_custom_daa, 1, 1, RZ_ANALYSIS_ESIL_OP_TYPE_MATH | RZ_ANALYSIS_ESIL_OP_TYPE_CUSTOM);
if (user) {
if (esil->analysis) {
esil->analysis->iob.read_at(esil->analysis->iob.io, 0x147, &user->mbc_id, 1);
esil->analysis->iob.read_at(esil->analysis->iob.io, 0x148, &user->romsz_id, 1);
esil->analysis->iob.read_at(esil->analysis->iob.io, 0x149, &user->ramsz_id, 1);
if (esil->analysis->reg) { // initial values
rz_reg_set_value(esil->analysis->reg, rz_reg_get(esil->analysis->reg, "mpc", -1), 0x100);
rz_reg_set_value(esil->analysis->reg, rz_reg_get(esil->analysis->reg, "sp", -1), 0xfffe);
rz_reg_set_value(esil->analysis->reg, rz_reg_get(esil->analysis->reg, "af", -1), 0x01b0);
rz_reg_set_value(esil->analysis->reg, rz_reg_get(esil->analysis->reg, "bc", -1), 0x0013);
rz_reg_set_value(esil->analysis->reg, rz_reg_get(esil->analysis->reg, "de", -1), 0x00d8);
rz_reg_set_value(esil->analysis->reg, rz_reg_get(esil->analysis->reg, "hl", -1), 0x014d);
rz_reg_set_value(esil->analysis->reg, rz_reg_get(esil->analysis->reg, "ime", -1), true);
if (analysis) {
analysis->iob.read_at(analysis->iob.io, 0x147, &user->mbc_id, 1);
analysis->iob.read_at(analysis->iob.io, 0x148, &user->romsz_id, 1);
analysis->iob.read_at(analysis->iob.io, 0x149, &user->ramsz_id, 1);
if (analysis->reg) { // initial values
rz_reg_set_value(analysis->reg, rz_reg_get(analysis->reg, "mpc", -1), 0x100);
rz_reg_set_value(analysis->reg, rz_reg_get(analysis->reg, "sp", -1), 0xfffe);
rz_reg_set_value(analysis->reg, rz_reg_get(analysis->reg, "af", -1), 0x01b0);
rz_reg_set_value(analysis->reg, rz_reg_get(analysis->reg, "bc", -1), 0x0013);
rz_reg_set_value(analysis->reg, rz_reg_get(analysis->reg, "de", -1), 0x00d8);
rz_reg_set_value(analysis->reg, rz_reg_get(analysis->reg, "hl", -1), 0x014d);
rz_reg_set_value(analysis->reg, rz_reg_get(analysis->reg, "ime", -1), true);
}
}
esil->cb.user = user;
@ -2028,7 +2031,8 @@ static int gb_esil_init(RzAnalysisEsil *esil) {
return true;
}
static int gb_esil_fini(RzAnalysisEsil *esil) {
static bool gb_esil_fini(void *pesil) {
RzAnalysisEsil *esil = pesil;
RZ_FREE(esil->cb.user);
return true;
}

View file

@ -3797,21 +3797,6 @@ static RzList /*<RzSearchKeyword *>*/ *analysis_preludes(RzAnalysis *analysis) {
return l;
}
static int esil_x86_zydis_init(RzAnalysisEsil *esil) {
if (!esil) {
return false;
}
// XXX. this depends on kernel
// rz_analysis_esil_set_interrupt (esil, 0x80, x86_int_0x80);
/* disable by default */
// rz_analysis_esil_set_interrupt (esil, 0x80, NULL,addr); // this is stupid, don't do this
return true;
}
static int esil_x86_zydis_fini(RzAnalysisEsil *esil) {
return true;
}
RzAnalysisPlugin rz_analysis_plugin_x86_zydis = {
.name = "x86",
.desc = "Zydis X86 analysis",
@ -3825,8 +3810,6 @@ RzAnalysisPlugin rz_analysis_plugin_x86_zydis = {
.get_reg_profile = &get_reg_profile,
.init = x86_init,
.fini = x86_fini,
.esil_init = esil_x86_zydis_init,
.esil_fini = esil_x86_zydis_fini,
.il_config = rz_x86_il_config
};

View file

@ -9,7 +9,7 @@
#include <rz_core.h>
#define LOOP_MAX 10
static bool analysis_emul_init(RzCore *core, RzConfigHold *hc, RzDebugTrace **dt, RzAnalysisEsilTrace **et, RzAnalysisRzilTrace **rt) {
static bool analysis_emul_init(RzCore *core, RzConfigHold *hc, RzDebugTrace **dt, RzAnalysisEsilTrace **et, RzAnalysisILTrace **rt) {
RzReg *rreg = rz_analysis_get_reg(core->analysis);
RzAnalysisEsil *esil = rz_analysis_get_esil(core->analysis);
if (!esil) {
@ -37,7 +37,7 @@ static bool analysis_emul_init(RzCore *core, RzConfigHold *hc, RzDebugTrace **dt
return (core->dbg->trace && esil->trace);
}
static void analysis_emul_restore(RzCore *core, RzConfigHold *hc, RzDebugTrace *dt, RzAnalysisEsilTrace *et, RzAnalysisRzilTrace *rt) {
static void analysis_emul_restore(RzCore *core, RzConfigHold *hc, RzDebugTrace *dt, RzAnalysisEsilTrace *et, RzAnalysisILTrace *rt) {
RzAnalysisEsil *esil = rz_analysis_get_esil(core->analysis);
rz_config_hold_restore(hc);
rz_config_hold_free(hc);
@ -847,7 +847,7 @@ RZ_API void rz_core_analysis_type_match(RzCore *core, RzAnalysisFunction *fcn, H
}
RzDebugTrace *dt = NULL;
RzAnalysisEsilTrace *et = NULL;
RzAnalysisRzilTrace *rt = NULL;
RzAnalysisILTrace *rt = NULL;
if (!analysis_emul_init(core, hc, &dt, &et, &rt) || !fcn) {
analysis_emul_restore(core, hc, dt, et, rt);
return;

View file

@ -1549,7 +1549,7 @@ static bool cb_iopcachewrite(void *user, void *data) {
RZ_API bool rz_core_esil_cmd(RzAnalysisEsil *esil, const char *cmd, ut64 a1, ut64 a2) {
if (cmd && *cmd) {
RzCore *core = esil->core;
RzCore *core = (RzCore *)esil->pcore;
rz_core_cmdf(core, "%s %" PFMT64d " %" PFMT64d, cmd, a1, a2);
return core->num->value;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -699,10 +699,11 @@ static void aea_stats_init(AeaStats *stats) {
}
static void aea_stats_fini(AeaStats *stats) {
RZ_FREE(stats->regs);
RZ_FREE(stats->regread);
RZ_FREE(stats->regwrite);
RZ_FREE(stats->inputregs);
RZ_FREE_CUSTOM(stats->regs, rz_list_free);
RZ_FREE_CUSTOM(stats->regread, rz_list_free);
RZ_FREE_CUSTOM(stats->regwrite, rz_list_free);
RZ_FREE_CUSTOM(stats->regvalues, rz_list_free);
RZ_FREE_CUSTOM(stats->inputregs, rz_list_free);
}
static bool contains(RzList /*<char *>*/ *list, const char *name) {
@ -718,14 +719,15 @@ static bool contains(RzList /*<char *>*/ *list, const char *name) {
static int mymemwrite(RzAnalysisEsil *esil, ut64 addr, const ut8 *buf, int len) {
RzListIter *iter;
RzAnalysisEsilMemoryRegion *n;
RzAnalysisEsilInterState *estate = rz_analysis_get_esil_inter_state(esil->analysis);
RzAnalysisEsilInterState *estate = esil->esilinterstate;
RzCore *core = esil->pcore;
RzList *memwrites = estate->memwrites;
rz_list_foreach (memwrites, iter, n) {
if (addr == n->addr) {
return len;
}
}
if (!rz_io_is_valid_offset(esil->core->io, addr, 0)) {
if (!rz_io_is_valid_offset(core->io, addr, 0)) {
return false;
}
n = RZ_NEW(RzAnalysisEsilMemoryRegion);
@ -740,14 +742,15 @@ static int mymemwrite(RzAnalysisEsil *esil, ut64 addr, const ut8 *buf, int len)
static int mymemread(RzAnalysisEsil *esil, ut64 addr, ut8 *buf, int len) {
RzListIter *iter;
RzAnalysisEsilMemoryRegion *n;
RzAnalysisEsilInterState *estate = rz_analysis_get_esil_inter_state(esil->analysis);
RzAnalysisEsilInterState *estate = esil->esilinterstate;
RzCore *core = esil->pcore;
RzList *memreads = estate->memreads;
rz_list_foreach (memreads, iter, n) {
if (addr == n->addr) {
return len;
}
}
if (!rz_io_is_valid_offset(esil->core->io, addr, 0)) {
if (!rz_io_is_valid_offset(core->io, addr, 0)) {
return false;
}
n = RZ_NEW(RzAnalysisEsilMemoryRegion);
@ -847,15 +850,16 @@ static void showmem_json(RzList /*<RzAnalysisEsilMemoryRegion *>*/ *list, PJ *pj
}
static bool cmd_aea(RzCore *core, int mode, ut64 addr, int length) {
RzAnalysisEsil *esil;
RzAnalysisEsil *esil = NULL;
bool ret = false;
RzReg *rreg = rz_analysis_get_reg(core->analysis);
int ptr, ops, ops_end = 0, len, buf_sz, maxopsize;
ut64 addr_end;
AeaStats stats;
const char *esilstr;
int ptr = 0, ops = 0, ops_end = 0, len = 0, buf_sz = 0, maxopsize = 0;
ut64 addr_end = 0;
AeaStats stats = { 0 };
const char *esilstr = NULL;
RzAnalysisOp aop = RZ_EMPTY;
ut8 *buf;
RzList *regnow;
ut8 *buf = NULL;
RzList *regnow = NULL;
PJ *pj = NULL;
if (!core) {
return false;
@ -887,7 +891,6 @@ static bool cmd_aea(RzCore *core, int mode, ut64 addr, int length) {
aea_stats_init(&stats);
rz_reg_arena_push(rreg);
RzAnalysisEsilInterState *estate = rz_analysis_get_esil_inter_state(core->analysis);
int stacksize = rz_config_get_i(core->config, "esil.stack.depth");
bool iotrap = rz_config_get_i(core->config, "esil.iotrap");
int romem = rz_config_get_i(core->config, "esil.romem");
@ -898,6 +901,7 @@ static bool cmd_aea(RzCore *core, int mode, ut64 addr, int length) {
rz_analysis_esil_setup(esil, core->analysis, romem, stats1, noNULL, core); // setup io
#define hasNext(x) (x & 1) ? (addr < addr_end) : (ops < ops_end)
RzAnalysisEsilInterState *estate = esil->esilinterstate;
estate->memreads = rz_list_new();
estate->memwrites = rz_list_new();
esil->user = &stats;
@ -925,7 +929,6 @@ static bool cmd_aea(RzCore *core, int mode, ut64 addr, int length) {
esil->cb.hook_reg_write = NULL;
esil->cb.hook_reg_read = NULL;
// esil_fini (core);
rz_analysis_esil_free(esil);
rz_reg_arena_pop(rreg);
regnow = rz_list_newf(free);
{
@ -961,7 +964,7 @@ static bool cmd_aea(RzCore *core, int mode, ut64 addr, int length) {
} else if ((mode >> 4) & 1) {
pj = pj_new();
if (!pj) {
return false;
goto fail;
}
pj_o(pj);
pj_k(pj, "A");
@ -1028,15 +1031,16 @@ static bool cmd_aea(RzCore *core, int mode, ut64 addr, int length) {
showmem(estate->memwrites);
}
}
ret = true;
fail:
rz_list_free(estate->memreads);
rz_list_free(estate->memwrites);
estate->memreads = NULL;
estate->memwrites = NULL;
aea_stats_fini(&stats);
free(buf);
RZ_FREE(regnow);
return true;
rz_list_free(regnow);
rz_analysis_esil_free(esil);
return ret;
}
// aeC
@ -6355,6 +6359,7 @@ RZ_IPI RzCmdStatus rz_analyze_esil_insn_access_handler(RzCore *core, int argc, c
}
ut64 newPC = core->offset + op->size;
rz_reg_setv(reg, "PC", newPC);
rz_analysis_op_free(op);
}
const char cmd_type = argv[2][0];

View file

@ -1921,7 +1921,8 @@ RZ_IPI RzCmdStatus rz_cmd_debug_traces_esil_i_handler(RzCore *core, int argc, co
return RZ_CMD_STATUS_ERROR;
}
RzAnalysisEsil *esil = rz_analysis_get_esil(core->analysis);
rz_analysis_esil_trace_op(esil, op);
const char *eexpr = rz_strbuf_get(&op->esil);
rz_analysis_esil_trace_op(esil, op->addr, eexpr);
rz_analysis_op_free(op);
return RZ_CMD_STATUS_OK;
}

View file

@ -561,6 +561,7 @@ static void RzBinSourceLineCacheItem_free(RzBinSourceLineCacheItem *x) {
}
static RzDisasmState *ds_init(RzCore *core) {
RzAnalysisEsil *esil = rz_analysis_get_esil(core->analysis);
RzDisasmState *ds = RZ_NEW0(RzDisasmState);
if (!ds) {
return NULL;
@ -669,15 +670,14 @@ static RzDisasmState *ds_init(RzCore *core) {
ds->show_emu_ssa = rz_config_get_b(core->config, "emu.ssa");
ds->show_emu_stack = rz_config_get_b(core->config, "emu.stack");
ds->stackFd = -1;
if (ds->show_emu_stack) {
if (ds->show_emu_stack && esil) {
// TODO: initialize fake stack in here
const char *uri = "malloc://32K";
ut64 size = rz_num_get(core->num, "32K");
RzReg *rreg = rz_analysis_get_reg(core->analysis);
RzAnalysisEsilInterState *estate = rz_analysis_get_esil_inter_state(core->analysis);
ut64 addr = rz_reg_getv(rreg, "SP") - (size / 2);
estate->emustack_min = addr;
estate->emustack_max = addr + size;
esil->esilinterstate->emustack_min = addr;
esil->esilinterstate->emustack_max = addr + size;
ds->stackFd = rz_io_fd_open(core->io, uri, RZ_PERM_RW, 0);
RzIOMap *map = rz_io_map_add(core->io, ds->stackFd, RZ_PERM_RW, 0LL, addr, size);
if (!map) {
@ -4296,7 +4296,7 @@ static int mymemwrite1(RzAnalysisEsil *esil, ut64 addr, const ut8 *buf, int len)
}
static int mymemwrite2(RzAnalysisEsil *esil, ut64 addr, const ut8 *buf, int len) {
RzAnalysisEsilInterState *estate = rz_analysis_get_esil_inter_state(esil->analysis);
RzAnalysisEsilInterState *estate = esil->esilinterstate;
return (addr >= estate->emustack_min && addr < estate->emustack_max);
}
@ -4332,7 +4332,7 @@ static int myregread(RzAnalysisEsil *esil, const char *name, ut64 *res, int *siz
static int myregwrite(RzAnalysisEsil *esil, const char *name, ut64 *val) {
char str[64], *msg = NULL;
RzCore *core = esil->core;
RzCore *core = esil->pcore;
bool big_endian = core ? rz_asm_is_big_endian_set(core->rasm) : false;
RzDisasmState *ds = esil->user;
if (!ds) {

View file

@ -49,8 +49,8 @@ RZ_IPI bool rz_core_visual_esil(RzCore *core) {
}
memcpy(buf, core->block, sizeof(ut64));
RzAnalysisEsil *esil = rz_analysis_esil_new(20, 0, addrsize);
esil->core = core;
esil->analysis = core->analysis;
esil->pcore = core;
esil->panalysis = core->analysis;
rz_analysis_esil_set_pc(esil, core->offset);
for (;;) {
rz_cons_clear00();

View file

@ -192,7 +192,8 @@ RZ_API void rz_debug_trace_op(RzDebug *dbg, RzAnalysisOp *op) {
if (dbg->trace->enabled) {
RzAnalysisEsil *esil = rz_analysis_get_esil(dbg->analysis);
if (esil) {
rz_analysis_esil_trace_op(esil, op);
const char *eexpr = rz_strbuf_get(&op->esil);
rz_analysis_esil_trace_op(esil, op->addr, eexpr);
} else {
if (dbg->verbose) {
RZ_LOG_WARN("debug: Run aeim to get esil initialized\n");

View file

@ -164,6 +164,11 @@ rz_il_files = [
]
install_headers(rz_il_files, install_dir: join_paths(rizin_incdir, 'rz_il'))
rz_esil_files = [
'rz_esil/rz_esil.h',
]
install_headers(rz_esil_files, install_dir: join_paths(rizin_incdir, 'rz_esil'))
rz_crypto_files = [
'rz_crypto/rz_des.h',
'rz_crypto/rz_aes.h',

View file

@ -24,8 +24,7 @@
#include <rz_il.h>
#include <rz_platform.h>
#include <rz_cmd.h>
#define esilprintf(op, fmt, ...) rz_strbuf_setf(&op->esil, fmt, ##__VA_ARGS__)
#include <rz_esil/rz_esil.h>
#ifdef __cplusplus
extern "C" {
@ -396,7 +395,17 @@ typedef struct rz_analysis_callbacks_t {
bool (*read_at)(RzAnalysis *analysis, ut64 addr, ut8 *buf, int len);
} RzAnalysisCallbacks;
#define RZ_ANALYSIS_ESIL_GOTO_LIMIT 4096
typedef struct rz_analysis_il_trace_t {
int idx;
int end_idx;
HtUP *registers;
HtUP *memory;
RzRegArena *arena[RZ_REG_TYPE_LAST];
ut64 stack_addr;
ut64 stack_size;
ut8 *stack_data;
RzPVector /*<RzILTraceInstruction *>*/ *instructions;
} RzAnalysisILTrace;
typedef struct rz_analysis_options_t {
int depth;
@ -960,21 +969,6 @@ typedef struct rz_analysis_cycle_hook_t { // rename ?
int cycles;
} RzAnalysisCycleHook;
typedef struct rz_analysis_esil_word_t {
int type;
const char *str;
} RzAnalysisEsilWord;
// only flags that affect control flow
enum {
RZ_ANALYSIS_ESIL_FLAG_ZERO = 1,
RZ_ANALYSIS_ESIL_FLAG_CARRY = 2,
RZ_ANALYSIS_ESIL_FLAG_OVERFLOW = 4,
RZ_ANALYSIS_ESIL_FLAG_PARITY = 8,
RZ_ANALYSIS_ESIL_FLAG_SIGN = 16,
// ...
};
enum {
RZ_ANALYSIS_TRAP_NONE = 0,
RZ_ANALYSIS_TRAP_UNHANDLED = 1,
@ -989,161 +983,11 @@ enum {
RZ_ANALYSIS_TRAP_HALT = 10,
};
enum {
RZ_ANALYSIS_ESIL_PARM_INVALID = 0,
RZ_ANALYSIS_ESIL_PARM_REG,
RZ_ANALYSIS_ESIL_PARM_NUM,
};
typedef struct rz_analysis_ref_char {
char *str;
char *cols;
} RzAnalysisRefStr;
// must be a char
#define ESIL_INTERNAL_PREFIX '$'
#define ESIL_STACK_NAME "esil.ram"
typedef struct rz_analysis_esil_source_t {
ut32 id;
ut32 claimed;
void *content;
} RzAnalysisEsilSource;
typedef struct rz_analysis_esil_t RzAnalysisEsil;
RZ_API void rz_analysis_esil_sources_init(RzAnalysisEsil *esil);
RZ_API ut32 rz_analysis_esil_load_source(RzAnalysisEsil *esil, const char *path);
RZ_API void *rz_analysis_esil_get_source(RzAnalysisEsil *esil, ut32 src_id);
RZ_API bool rz_analysis_esil_claim_source(RzAnalysisEsil *esil, ut32 src_id);
RZ_API void rz_analysis_esil_release_source(RzAnalysisEsil *esil, ut32 src_id);
RZ_API void rz_analysis_esil_sources_fini(RzAnalysisEsil *esil);
typedef bool (*RzAnalysisEsilInterruptCB)(RzAnalysisEsil *esil, ut32 interrupt, void *user);
typedef struct rz_analysis_esil_interrupt_handler_t {
const ut32 num;
const char *name;
void *(*init)(RzAnalysisEsil *esil);
RzAnalysisEsilInterruptCB cb;
void (*fini)(void *user);
} RzAnalysisEsilInterruptHandler;
typedef struct rz_analysis_esil_change_reg_t {
int idx;
ut64 data;
} RzAnalysisEsilRegChange;
typedef struct rz_analysis_esil_change_mem_t {
int idx;
ut8 data;
} RzAnalysisEsilMemChange;
typedef struct rz_analysis_esil_trace_t {
int idx;
int end_idx;
HtUP *registers;
HtUP *memory;
RzRegArena *arena[RZ_REG_TYPE_LAST];
ut64 stack_addr;
ut64 stack_size;
ut8 *stack_data;
RzPVector /*<RzILTraceInstruction *>*/ *instructions;
} RzAnalysisEsilTrace;
typedef int (*RzAnalysisEsilHookRegWriteCB)(RzAnalysisEsil *esil, const char *name, ut64 *val);
typedef struct rz_analysis_esil_callbacks_t {
void *user;
/* callbacks */
int (*hook_flag_read)(RzAnalysisEsil *esil, const char *flag, ut64 *num);
int (*hook_command)(RzAnalysisEsil *esil, const char *op);
int (*hook_mem_read)(RzAnalysisEsil *esil, ut64 addr, ut8 *buf, int len);
int (*mem_read)(RzAnalysisEsil *esil, ut64 addr, ut8 *buf, int len);
int (*hook_mem_write)(RzAnalysisEsil *esil, ut64 addr, const ut8 *buf, int len);
int (*mem_write)(RzAnalysisEsil *esil, ut64 addr, const ut8 *buf, int len);
int (*hook_reg_read)(RzAnalysisEsil *esil, const char *name, ut64 *res, int *size);
int (*reg_read)(RzAnalysisEsil *esil, const char *name, ut64 *res, int *size);
RzAnalysisEsilHookRegWriteCB hook_reg_write;
int (*reg_write)(RzAnalysisEsil *esil, const char *name, ut64 val);
} RzAnalysisEsilCallbacks;
struct rz_analysis_esil_t {
RzCore *core;
RzAnalysis *analysis;
char **stack;
ut64 addrmask;
int stacksize;
int stackptr;
ut32 skip;
int nowrite;
int iotrap;
int exectrap;
int repeat;
int parse_stop;
int parse_goto;
int parse_goto_count;
int verbose;
ut64 flags;
ut64 address;
ut64 stack_addr;
ut32 stack_size;
int delay; // mapped to $ds in ESIL
ut64 jump_target; // mapped to $jt in ESIL
int jump_target_set; // mapped to $js in ESIL
int trap;
ut32 trap_code; // extend into a struct to store more exception info?
// parity flag? done with cur
ut64 old; // used for carry-flagging and borrow-flagging
ut64 cur; // used for carry-flagging and borrow-flagging
ut8 lastsz; // in bits //used for signature-flag
/* native ops and custom ops */
HtSP *ops;
RzStrBuf current_opstr;
RzIDStorage *sources;
HtUP *interrupts;
/* deep esil parsing fills this */
Sdb *stats;
RzAnalysisEsilTrace *trace;
RzAnalysisEsilCallbacks cb;
// this is so cursed, can we please remove external commands from esil internals.
// Function pointers are fine, but not commands
char *cmd_step; // rizin (external) command to run before a step is performed
char *cmd_step_out; // rizin (external) command to run after a step is performed
char *cmd_intr; // rizin (external) command to run when an interrupt occurs
char *cmd_trap; // rizin (external) command to run when a trap occurs
char *cmd_mdev; // rizin (external) command to run when an memory mapped device address is used
char *cmd_todo; // rizin (external) command to run when esil expr contains TODO
char *cmd_ioer; // rizin (external) command to run when esil fails to IO
char *mdev_range; // string containing the rz_str_range to match for read/write accesses
bool (*cmd)(RzAnalysisEsil *esil, const char *name, ut64 a0, ut64 a1);
void *user;
int stack_fd; // ahem, let's not do this
bool in_cmd_step;
};
/* During the analysis RzAnalysisEsil could be reset multiple times,
* thus there is a need to preserve some values between those runs.
*/
typedef struct rz_analysis_esil_inter_state_t {
bool analysis_stop;
ut64 last_read;
ut64 last_data;
ut64 emustack_min;
ut64 emustack_max;
RzList /*<RzAnalysisEsilMemoryRegion *>*/ *memreads;
RzList /*<RzAnalysisEsilMemoryRegion *>*/ *memwrites;
RzAnalysisEsilCallbacks callbacks;
bool callbacks_set;
} RzAnalysisEsilInterState;
/* Alias RegChange and MemChange */
typedef RzAnalysisEsilRegChange RzAnalysisRzilRegChange;
typedef RzAnalysisEsilMemChange RzAnalysisRzilMemChange;
/* Alias esil strace */
typedef RzAnalysisEsilTrace RzAnalysisRzilTrace;
/**
* \brief Description of the contents of a single IL variable
*/
@ -1215,68 +1059,10 @@ typedef enum {
RZ_ANALYSIS_IL_STEP_INVALID_OP
} RzAnalysisILStepResult;
#undef ESIL
typedef struct rz_analysis_esil_interrupt_t {
RzAnalysisEsilInterruptHandler *handler;
void *user;
ut32 src_id;
RzAnalysisEsil *esil;
} RzAnalysisEsilInterrupt;
enum {
RZ_ANALYSIS_ESIL_OP_TYPE_UNKNOWN = 0x1,
RZ_ANALYSIS_ESIL_OP_TYPE_CONTROL_FLOW,
RZ_ANALYSIS_ESIL_OP_TYPE_MEM_READ = 0x4,
RZ_ANALYSIS_ESIL_OP_TYPE_MEM_WRITE = 0x8,
RZ_ANALYSIS_ESIL_OP_TYPE_REG_WRITE = 0x10,
RZ_ANALYSIS_ESIL_OP_TYPE_MATH = 0x20,
RZ_ANALYSIS_ESIL_OP_TYPE_CUSTOM = 0x40
};
typedef bool (*RzAnalysisEsilOpCb)(RzAnalysisEsil *esil);
typedef struct rz_analysis_esil_operation_t {
RzAnalysisEsilOpCb code;
ut32 push; // amount of operands pushed
ut32 pop; // amount of operands popped
ut32 type;
} RzAnalysisEsilOp;
// this is 80-bit offsets so we can address every piece of esil in an instruction
typedef struct rz_analysis_esil_expr_offset_t {
ut64 off;
ut16 idx;
} RzAnalysisEsilEOffset;
typedef enum {
RZ_ANALYSIS_ESIL_BLOCK_ENTER_NORMAL = 0,
RZ_ANALYSIS_ESIL_BLOCK_ENTER_TRUE,
RZ_ANALYSIS_ESIL_BLOCK_ENTER_FALSE,
RZ_ANALYSIS_ESIL_BLOCK_ENTER_GLUE,
} RzAnalysisEsilBlockEnterType;
typedef struct rz_analysis_esil_basic_block_t {
RzAnalysisEsilEOffset first;
RzAnalysisEsilEOffset last;
char *expr; // synthesized esil-expression for this block
RzAnalysisEsilBlockEnterType enter; // maybe more type is needed here
} RzAnalysisEsilBB;
// Structure to represent memory reads and writes during ESIL tracing
typedef struct rz_analysis_esil_memory_region_t {
ut64 addr; ///< memory address
size_t size; ///< size of the region
} RzAnalysisEsilMemoryRegion;
// TODO: rm data + len
typedef int (*RzAnalysisOpCallback)(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask);
typedef char *(*RzAnalysisRegProfGetCallback)(RzAnalysis *a);
typedef int (*RzAnalysisEsilCB)(RzAnalysisEsil *esil);
typedef int (*RzAnalysisEsilLoopCB)(RzAnalysisEsil *esil, RzAnalysisOp *op);
typedef int (*RzAnalysisEsilTrapCB)(RzAnalysisEsil *esil, int trap_type, int trap_code);
typedef RZ_OWN RzAnalysisILConfig *(*RzAnalysisILConfigCB)(RzAnalysis *analysis);
typedef struct rz_analysis_plugin_t {
@ -1305,15 +1091,49 @@ typedef struct rz_analysis_plugin_t {
RzAnalysisOpCallback op;
RzAnalysisRegProfGetCallback get_reg_profile;
RzAnalysisEsilCB esil_init; // initialize esil-related stuff
RzAnalysisEsilLoopCB esil_post_loop; // cycle-counting, firing interrupts, ...
RzAnalysisEsilTrapCB esil_trap; // traps / exceptions
RzAnalysisEsilCB esil_fini; // deinitialize
RzAnalysisILConfigCB il_config; ///< return an IL config to execute lifted code of the given analysis' arch/cpu/bits
// Deprecated.
bool (*esil_init)(void *esil);
bool (*esil_fini)(void *esil);
} RzAnalysisPlugin;
typedef enum {
RZ_IL_TRACE_OP_READ, ///< read
RZ_IL_TRACE_OP_WRITE ///< write
} RzILTraceOpType;
typedef struct {
ut64 addr; ///< memory address
RzILTraceOpType behavior; ///< read or write, see RzILTraceOpType enums
ut8 data_buf[32]; ///< data either written to or read from
int data_len; ///< data length
} RzILTraceMemOp;
typedef struct {
const char *reg_name; ///< name of register
RzILTraceOpType behavior; ///< READ or WRITE, see RzILTraceOpType enums
ut64 value; ///< data either written to or read from
} RzILTraceRegOp;
typedef enum {
RZ_IL_TRACE_INS_HAS_MEM_R = 0x1U, ///< instruction include memory read
RZ_IL_TRACE_INS_HAS_MEM_W = 0x2U, ///< instruction include memory write
RZ_IL_TRACE_INS_HAS_REG_R = 0x4U, ///< instruction include register read
RZ_IL_TRACE_INS_HAS_REG_W = 0x8U ///< instruction include register write
} RzILTraceInsOp;
typedef struct rz_il_trace_instruction_t {
ut64 addr; ///< Address of instruction
ut32 stats; ///< Has write/read to reg/mem ? see RZ_IL_TRACE_INS_HAS_* enums
RzPVector /*<RzILTraceMemOp *>*/ *write_mem_ops; ///< Vector<RzILTraceMemOp>
RzPVector /*<RzILTraceMemOp *>*/ *read_mem_ops; ///< Vector<RzILTraceMemOp>
RzPVector /*<RzILTraceRegOp *>*/ *write_reg_ops; ///< Vector<RzILTraceRegOp>
RzPVector /*<RzILTraceRegOp *>*/ *read_reg_ops; ///< Vector<RzILTraceRegOp>
} RzILTraceInstruction;
/*----------------------------------------------------------------------------------------------*/
#ifdef RZ_API
@ -1568,8 +1388,6 @@ RZ_DEPRECATE RZ_API void rz_analysis_set_core(RZ_NONNULL RzAnalysis *analysis, R
RZ_DEPRECATE RZ_API void rz_analysis_set_event(RZ_NONNULL RzAnalysis *analysis, RZ_NULLABLE RzEvent *ev);
RZ_DEPRECATE RZ_API RZ_BORROW RzAnalysisEsil *rz_analysis_get_esil(RZ_NONNULL RzAnalysis *analysis);
RZ_DEPRECATE RZ_API void rz_analysis_set_esil(RZ_NONNULL RzAnalysis *analysis, RZ_NULLABLE RzAnalysisEsil *esil);
RZ_DEPRECATE RZ_API RZ_BORROW RzAnalysisEsilInterState *rz_analysis_get_esil_inter_state(RZ_NONNULL RzAnalysis *analysis);
RZ_DEPRECATE RZ_API void rz_analysis_set_esil_inter_state(RZ_NONNULL RzAnalysis *analysis, RZ_NULLABLE RzAnalysisEsilInterState *esilinterstate);
RZ_DEPRECATE RZ_API const char *rz_analysis_get_arch(RZ_NONNULL const RzAnalysis *analysis);
RZ_DEPRECATE RZ_API int rz_analysis_get_bits(RZ_NONNULL const RzAnalysis *analysis);
RZ_DEPRECATE RZ_API bool rz_analysis_is_big_endian_set(RZ_NONNULL const RzAnalysis *analysis);
@ -1623,76 +1441,6 @@ RZ_API int rz_analysis_op(RZ_NONNULL RzAnalysis *analysis, RZ_OUT RzAnalysisOp *
RZ_API RzAnalysisOp *rz_analysis_op_hexstr(RzAnalysis *analysis, ut64 addr, const char *hexstr);
RZ_API char *rz_analysis_op_to_string(RzAnalysis *analysis, RzAnalysisOp *op);
RZ_API RzAnalysisEsil *rz_analysis_esil_new(int stacksize, int iotrap, unsigned int addrsize);
RZ_API bool rz_analysis_esil_set_pc(RzAnalysisEsil *esil, ut64 addr);
RZ_API bool rz_analysis_esil_setup(RzAnalysisEsil *esil, RzAnalysis *analysis, int romem, int stats, int nonull, RzCore *core);
RZ_API void rz_analysis_esil_free(RzAnalysisEsil *esil);
RZ_API bool rz_analysis_esil_runword(RzAnalysisEsil *esil, const char *word);
RZ_API bool rz_analysis_esil_parse(RzAnalysisEsil *esil, const char *str);
RZ_API int rz_analysis_esil_mem_read(RzAnalysisEsil *esil, ut64 addr, ut8 *buf, int len);
RZ_API int rz_analysis_esil_mem_write(RzAnalysisEsil *esil, ut64 addr, const ut8 *buf, int len);
RZ_API int rz_analysis_esil_reg_read(RzAnalysisEsil *esil, const char *regname, ut64 *num, int *size);
RZ_API int rz_analysis_esil_reg_write(RzAnalysisEsil *esil, const char *dst, ut64 num);
RZ_API bool rz_analysis_esil_pushnum(RzAnalysisEsil *esil, ut64 num);
RZ_API bool rz_analysis_esil_push(RzAnalysisEsil *esil, const char *str);
RZ_API char *rz_analysis_esil_pop(RzAnalysisEsil *esil);
RZ_API const char *rz_analysis_esil_trapstr(int type);
RZ_API bool rz_analysis_esil_set_op(RzAnalysisEsil *esil, const char *op, RzAnalysisEsilOpCb code, ut32 push, ut32 pop, ut32 type);
RZ_API void rz_analysis_esil_stack_free(RzAnalysisEsil *esil);
RZ_API int rz_analysis_esil_get_parm_type(RzAnalysisEsil *esil, const char *str);
RZ_API int rz_analysis_esil_get_parm(RzAnalysisEsil *esil, const char *str, ut64 *num);
RZ_API int rz_analysis_esil_condition(RzAnalysisEsil *esil, const char *str);
// esil_interrupt.c
RZ_API void rz_analysis_esil_interrupts_init(RzAnalysisEsil *esil);
RZ_API RzAnalysisEsilInterrupt *rz_analysis_esil_interrupt_new(RzAnalysisEsil *esil, ut32 src_id, RzAnalysisEsilInterruptHandler *ih);
RZ_API void rz_analysis_esil_interrupt_free(RzAnalysisEsil *esil, RzAnalysisEsilInterrupt *intr);
RZ_API bool rz_analysis_esil_set_interrupt(RzAnalysisEsil *esil, RzAnalysisEsilInterrupt *intr);
RZ_API int rz_analysis_esil_fire_interrupt(RzAnalysisEsil *esil, ut32 intr_num);
RZ_API bool rz_analysis_esil_load_interrupts(RzAnalysisEsil *esil, RzAnalysisEsilInterruptHandler **handlers, ut32 src_id);
RZ_API bool rz_analysis_esil_load_interrupts_from_lib(RzAnalysisEsil *esil, const char *path);
RZ_API void rz_analysis_esil_interrupts_fini(RzAnalysisEsil *esil);
RZ_API void rz_analysis_esil_mem_ro(RzAnalysisEsil *esil, int mem_readonly);
RZ_API void rz_analysis_esil_stats(RzAnalysisEsil *esil, int enable);
/* new trace implementation */
typedef enum {
RZ_IL_TRACE_OP_READ, ///< read
RZ_IL_TRACE_OP_WRITE ///< write
} RzILTraceOpType;
typedef struct {
ut64 addr; ///< memory address
RzILTraceOpType behavior; ///< read or write, see RzILTraceOpType enums
ut8 data_buf[32]; ///< data either written to or read from
int data_len; ///< data length
} RzILTraceMemOp;
typedef struct {
const char *reg_name; ///< name of register
RzILTraceOpType behavior; ///< READ or WRITE, see RzILTraceOpType enums
ut64 value; ///< data either written to or read from
} RzILTraceRegOp;
typedef enum {
RZ_IL_TRACE_INS_HAS_MEM_R = 0x1U, ///< instruction include memory read
RZ_IL_TRACE_INS_HAS_MEM_W = 0x2U, ///< instruction include memory write
RZ_IL_TRACE_INS_HAS_REG_R = 0x4U, ///< instruction include register read
RZ_IL_TRACE_INS_HAS_REG_W = 0x8U ///< instruction include register write
} RzILTraceInsOp;
typedef struct {
ut64 addr; ///< Address of instruction
ut32 stats; ///< Has write/read to reg/mem ? see RZ_IL_TRACE_INS_HAS_* enums
RzPVector /*<RzILTraceMemOp *>*/ *write_mem_ops; ///< Vector<RzILTraceMemOp>
RzPVector /*<RzILTraceMemOp *>*/ *read_mem_ops; ///< Vector<RzILTraceMemOp>
RzPVector /*<RzILTraceRegOp *>*/ *write_reg_ops; ///< Vector<RzILTraceRegOp>
RzPVector /*<RzILTraceRegOp *>*/ *read_reg_ops; ///< Vector<RzILTraceRegOp>
} RzILTraceInstruction;
/* Independent Trace Functions */
RZ_API RzILTraceInstruction *rz_analysis_il_trace_instruction_new(ut64 addr);
RZ_API void rz_analysis_il_trace_instruction_free(RzILTraceInstruction *instruction);
@ -1703,15 +1451,6 @@ RZ_API RzILTraceRegOp *rz_analysis_il_get_reg_op_trace(RzILTraceInstruction *tra
RZ_API bool rz_analysis_il_mem_trace_contains(RzILTraceInstruction *trace, ut64 addr, RzILTraceOpType op_type);
RZ_API bool rz_analysis_il_reg_trace_contains(RzILTraceInstruction *trace, const char *regname, RzILTraceOpType op_type);
/* ESIL trace */
RZ_API RZ_BORROW RzILTraceInstruction *rz_analysis_esil_get_instruction_trace(RZ_NONNULL RzAnalysisEsilTrace *etrace, int idx);
RZ_API RzAnalysisEsilTrace *rz_analysis_esil_trace_new(RzAnalysisEsil *esil);
RZ_API void rz_analysis_esil_trace_free(RzAnalysisEsilTrace *trace);
RZ_API void rz_analysis_esil_trace_op(RzAnalysisEsil *esil, RZ_NONNULL RzAnalysisOp *op);
RZ_API void rz_analysis_esil_trace_list(RzAnalysisEsil *esil);
RZ_API void rz_analysis_esil_trace_show(RzAnalysisEsil *esil, int idx);
RZ_API void rz_analysis_esil_trace_restore(RzAnalysisEsil *esil, int idx);
/* RzIL */
RZ_API RzAnalysisILInitState *rz_analysis_il_init_state_new();
RZ_API void rz_analysis_il_init_state_free(RzAnalysisILInitState *state);
@ -1742,9 +1481,9 @@ RZ_API bool rz_analysis_il_vm_set_bool(RZ_NONNULL RzAnalysis *analysis, RZ_NULLA
RZ_API bool rz_analysis_il_vm_set_float(RZ_NONNULL RzAnalysis *analysis, RZ_NULLABLE const char *var_name, long double value);
/* trace */
RZ_API RzAnalysisRzilTrace *rz_analysis_rzil_trace_new(RzAnalysis *analysis, RZ_NONNULL RzAnalysisILVM *rzil);
RZ_API void rz_analysis_rzil_trace_free(RzAnalysisRzilTrace *trace);
RZ_API void rz_analysis_rzil_trace_op(RzAnalysis *analysis, RZ_NONNULL RzAnalysisILVM *rzil, RZ_NONNULL RzAnalysisLiftedILOp op);
RZ_API RzAnalysisILTrace *rz_analysis_il_trace_new(RzAnalysis *analysis, RZ_NONNULL RzAnalysisILVM *rzil);
RZ_API void rz_analysis_il_trace_free(RzAnalysisILTrace *trace);
RZ_API void rz_analysis_il_trace_op(RzAnalysis *analysis, RZ_NONNULL RzAnalysisILVM *rzil, RZ_NONNULL RzAnalysisLiftedILOp op);
RZ_API bool rz_analysis_add_device_peripheral_map(RzBinObject *o, RzAnalysis *analysis);

View file

@ -0,0 +1,281 @@
// SPDX-FileCopyrightText: 2014-2021 pancake <pancake@nopcode.org>
// SPDX-FileCopyrightText: 2014-2021 condret <condr3t@protonmail.com>
// SPDX-License-Identifier: LGPL-3.0-only
#ifndef RZ_ANALYSIS_ESIL_H
#define RZ_ANALYSIS_ESIL_H
#include <rz_util.h>
#include <rz_reg.h>
#ifdef __cplusplus
extern "C" {
#endif
#define RZ_ANALYSIS_ESIL_GOTO_LIMIT 4096
#define esilprintf(op, fmt, ...) rz_strbuf_setf(&op->esil, fmt, ##__VA_ARGS__)
typedef struct rz_analysis_esil_word_t {
int type;
const char *str;
} RzAnalysisEsilWord;
// only flags that affect control flow
enum {
RZ_ANALYSIS_ESIL_FLAG_ZERO = 1,
RZ_ANALYSIS_ESIL_FLAG_CARRY = 2,
RZ_ANALYSIS_ESIL_FLAG_OVERFLOW = 4,
RZ_ANALYSIS_ESIL_FLAG_PARITY = 8,
RZ_ANALYSIS_ESIL_FLAG_SIGN = 16,
// ...
};
enum {
RZ_ANALYSIS_ESIL_PARM_INVALID = 0,
RZ_ANALYSIS_ESIL_PARM_REG,
RZ_ANALYSIS_ESIL_PARM_NUM,
};
// must be a char
#define ESIL_INTERNAL_PREFIX '$'
#define ESIL_STACK_NAME "esil.ram"
typedef struct rz_analysis_esil_source_t {
ut32 id;
ut32 claimed;
void *content;
} RzAnalysisEsilSource;
typedef struct rz_analysis_esil_t RzAnalysisEsil;
RZ_API void rz_analysis_esil_sources_init(RzAnalysisEsil *esil);
RZ_API ut32 rz_analysis_esil_load_source(RzAnalysisEsil *esil, const char *path);
RZ_API void *rz_analysis_esil_get_source(RzAnalysisEsil *esil, ut32 src_id);
RZ_API bool rz_analysis_esil_claim_source(RzAnalysisEsil *esil, ut32 src_id);
RZ_API void rz_analysis_esil_release_source(RzAnalysisEsil *esil, ut32 src_id);
RZ_API void rz_analysis_esil_sources_fini(RzAnalysisEsil *esil);
typedef bool (*RzAnalysisEsilInterruptCB)(RzAnalysisEsil *esil, ut32 interrupt, void *user);
typedef struct rz_analysis_esil_interrupt_handler_t {
const ut32 num;
const char *name;
void *(*init)(RzAnalysisEsil *esil);
RzAnalysisEsilInterruptCB cb;
void (*fini)(void *user);
} RzAnalysisEsilInterruptHandler;
typedef struct rz_analysis_esil_change_reg_t {
int idx;
ut64 data;
} RzAnalysisEsilRegChange;
typedef struct rz_analysis_esil_change_mem_t {
int idx;
ut8 data;
} RzAnalysisEsilMemChange;
typedef struct rz_analysis_esil_trace_t {
int idx;
int end_idx;
HtUP *registers;
HtUP *memory;
RzRegArena *arena[RZ_REG_TYPE_LAST];
ut64 stack_addr;
ut64 stack_size;
ut8 *stack_data;
RzPVector /*<RzILTraceInstruction *>*/ *instructions;
} RzAnalysisEsilTrace;
typedef int (*RzAnalysisEsilHookRegWriteCB)(RzAnalysisEsil *esil, const char *name, ut64 *val);
typedef struct rz_analysis_esil_callbacks_t {
void *user;
/* callbacks */
int (*hook_flag_read)(RzAnalysisEsil *esil, const char *flag, ut64 *num);
int (*hook_command)(RzAnalysisEsil *esil, const char *op);
int (*hook_mem_read)(RzAnalysisEsil *esil, ut64 addr, ut8 *buf, int len);
int (*mem_read)(RzAnalysisEsil *esil, ut64 addr, ut8 *buf, int len);
int (*hook_mem_write)(RzAnalysisEsil *esil, ut64 addr, const ut8 *buf, int len);
int (*mem_write)(RzAnalysisEsil *esil, ut64 addr, const ut8 *buf, int len);
int (*hook_reg_read)(RzAnalysisEsil *esil, const char *name, ut64 *res, int *size);
int (*reg_read)(RzAnalysisEsil *esil, const char *name, ut64 *res, int *size);
RzAnalysisEsilHookRegWriteCB hook_reg_write;
int (*reg_write)(RzAnalysisEsil *esil, const char *name, ut64 val);
} RzAnalysisEsilCallbacks;
/* During the analysis RzAnalysisEsil could be reset multiple times,
* thus there is a need to preserve some values between those runs.
*/
typedef struct rz_analysis_esil_inter_state_t {
bool analysis_stop;
ut64 last_read;
ut64 last_data;
ut64 emustack_min;
ut64 emustack_max;
RzList /*<RzAnalysisEsilMemoryRegion *>*/ *memreads;
RzList /*<RzAnalysisEsilMemoryRegion *>*/ *memwrites;
RzAnalysisEsilCallbacks callbacks;
bool callbacks_set;
} RzAnalysisEsilInterState;
struct rz_analysis_esil_t {
void *pcore;
void *panalysis;
char **stack;
ut64 addrmask;
int stacksize;
int stackptr;
ut32 skip;
int nowrite;
int iotrap;
int exectrap;
int repeat;
int parse_stop;
int parse_goto;
int parse_goto_count;
int verbose;
ut64 flags;
ut64 address;
ut64 stack_addr;
ut32 stack_size;
int delay; // mapped to $ds in ESIL
ut64 jump_target; // mapped to $jt in ESIL
int jump_target_set; // mapped to $js in ESIL
int trap;
ut32 trap_code; // extend into a struct to store more exception info?
// parity flag? done with cur
ut64 old; // used for carry-flagging and borrow-flagging
ut64 cur; // used for carry-flagging and borrow-flagging
ut8 lastsz; // in bits //used for signature-flag
/* native ops and custom ops */
HtSP *ops;
RzStrBuf current_opstr;
RzIDStorage *sources;
HtUP *interrupts;
/* deep esil parsing fills this */
Sdb *stats;
RzAnalysisEsilTrace *trace;
RzAnalysisEsilCallbacks cb;
// this is so cursed, can we please remove external commands from esil internals.
// Function pointers are fine, but not commands
char *cmd_step; // rizin (external) command to run before a step is performed
char *cmd_step_out; // rizin (external) command to run after a step is performed
char *cmd_intr; // rizin (external) command to run when an interrupt occurs
char *cmd_trap; // rizin (external) command to run when a trap occurs
char *cmd_mdev; // rizin (external) command to run when an memory mapped device address is used
char *cmd_todo; // rizin (external) command to run when esil expr contains TODO
char *cmd_ioer; // rizin (external) command to run when esil fails to IO
char *mdev_range; // string containing the rz_str_range to match for read/write accesses
bool (*cmd)(RzAnalysisEsil *esil, const char *name, ut64 a0, ut64 a1);
void *user;
int stack_fd; // ahem, let's not do this
bool in_cmd_step;
RzAnalysisEsilInterState *esilinterstate;
};
/* Alias RegChange and MemChange */
typedef RzAnalysisEsilRegChange RzAnalysisRzilRegChange;
typedef RzAnalysisEsilMemChange RzAnalysisRzilMemChange;
/* Alias esil strace */
typedef struct rz_analysis_esil_interrupt_t {
RzAnalysisEsilInterruptHandler *handler;
void *user;
ut32 src_id;
RzAnalysisEsil *esil;
} RzAnalysisEsilInterrupt;
enum {
RZ_ANALYSIS_ESIL_OP_TYPE_UNKNOWN = 0x1,
RZ_ANALYSIS_ESIL_OP_TYPE_CONTROL_FLOW,
RZ_ANALYSIS_ESIL_OP_TYPE_MEM_READ = 0x4,
RZ_ANALYSIS_ESIL_OP_TYPE_MEM_WRITE = 0x8,
RZ_ANALYSIS_ESIL_OP_TYPE_REG_WRITE = 0x10,
RZ_ANALYSIS_ESIL_OP_TYPE_MATH = 0x20,
RZ_ANALYSIS_ESIL_OP_TYPE_CUSTOM = 0x40
};
typedef bool (*RzAnalysisEsilOpCb)(RzAnalysisEsil *esil);
typedef struct rz_analysis_esil_operation_t {
RzAnalysisEsilOpCb code;
ut32 push; // amount of operands pushed
ut32 pop; // amount of operands popped
ut32 type;
} RzAnalysisEsilOp;
// this is 80-bit offsets so we can address every piece of esil in an instruction
typedef struct rz_analysis_esil_expr_offset_t {
ut64 off;
ut16 idx;
} RzAnalysisEsilEOffset;
typedef enum {
RZ_ANALYSIS_ESIL_BLOCK_ENTER_NORMAL = 0,
RZ_ANALYSIS_ESIL_BLOCK_ENTER_TRUE,
RZ_ANALYSIS_ESIL_BLOCK_ENTER_FALSE,
RZ_ANALYSIS_ESIL_BLOCK_ENTER_GLUE,
} RzAnalysisEsilBlockEnterType;
typedef struct rz_analysis_esil_basic_block_t {
RzAnalysisEsilEOffset first;
RzAnalysisEsilEOffset last;
char *expr; // synthesized esil-expression for this block
RzAnalysisEsilBlockEnterType enter; // maybe more type is needed here
} RzAnalysisEsilBB;
// Structure to represent memory reads and writes during ESIL tracing
typedef struct rz_analysis_esil_memory_region_t {
ut64 addr; ///< memory address
size_t size; ///< size of the region
} RzAnalysisEsilMemoryRegion;
RZ_API RzAnalysisEsil *rz_analysis_esil_new(int stacksize, int iotrap, unsigned int addrsize);
RZ_API bool rz_analysis_esil_set_pc(RzAnalysisEsil *esil, ut64 addr);
RZ_API bool rz_analysis_esil_setup(RzAnalysisEsil *esil, void /*RzAnalysis*/ *analysis, int romem, int stats, int nonull, void /*RzCore*/ *core);
RZ_API void rz_analysis_esil_free(RzAnalysisEsil *esil);
RZ_API bool rz_analysis_esil_runword(RzAnalysisEsil *esil, const char *word);
RZ_API bool rz_analysis_esil_parse(RzAnalysisEsil *esil, const char *str);
RZ_API int rz_analysis_esil_mem_read(RzAnalysisEsil *esil, ut64 addr, ut8 *buf, int len);
RZ_API int rz_analysis_esil_mem_write(RzAnalysisEsil *esil, ut64 addr, const ut8 *buf, int len);
RZ_API int rz_analysis_esil_reg_read(RzAnalysisEsil *esil, const char *regname, ut64 *num, int *size);
RZ_API int rz_analysis_esil_reg_write(RzAnalysisEsil *esil, const char *dst, ut64 num);
RZ_API bool rz_analysis_esil_pushnum(RzAnalysisEsil *esil, ut64 num);
RZ_API bool rz_analysis_esil_push(RzAnalysisEsil *esil, const char *str);
RZ_API char *rz_analysis_esil_pop(RzAnalysisEsil *esil);
RZ_API const char *rz_analysis_esil_trapstr(int type);
RZ_API bool rz_analysis_esil_set_op(RzAnalysisEsil *esil, const char *op, RzAnalysisEsilOpCb code, ut32 push, ut32 pop, ut32 type);
RZ_API void rz_analysis_esil_stack_free(RzAnalysisEsil *esil);
RZ_API int rz_analysis_esil_get_parm_type(RzAnalysisEsil *esil, const char *str);
RZ_API int rz_analysis_esil_get_parm(RzAnalysisEsil *esil, const char *str, ut64 *num);
RZ_API int rz_analysis_esil_condition(RzAnalysisEsil *esil, const char *str);
// esil_interrupt.c
RZ_API void rz_analysis_esil_interrupts_init(RzAnalysisEsil *esil);
RZ_API RzAnalysisEsilInterrupt *rz_analysis_esil_interrupt_new(RzAnalysisEsil *esil, ut32 src_id, RzAnalysisEsilInterruptHandler *ih);
RZ_API void rz_analysis_esil_interrupt_free(RzAnalysisEsil *esil, RzAnalysisEsilInterrupt *intr);
RZ_API bool rz_analysis_esil_set_interrupt(RzAnalysisEsil *esil, RzAnalysisEsilInterrupt *intr);
RZ_API int rz_analysis_esil_fire_interrupt(RzAnalysisEsil *esil, ut32 intr_num);
RZ_API bool rz_analysis_esil_load_interrupts(RzAnalysisEsil *esil, RzAnalysisEsilInterruptHandler **handlers, ut32 src_id);
RZ_API bool rz_analysis_esil_load_interrupts_from_lib(RzAnalysisEsil *esil, const char *path);
RZ_API void rz_analysis_esil_interrupts_fini(RzAnalysisEsil *esil);
RZ_API void rz_analysis_esil_mem_ro(RzAnalysisEsil *esil, int mem_readonly);
RZ_API void rz_analysis_esil_stats(RzAnalysisEsil *esil, int enable);
/* ESIL trace */
RZ_API RZ_BORROW void /*RzILTraceInstruction*/ *rz_analysis_esil_get_instruction_trace(RZ_NONNULL RzAnalysisEsilTrace *etrace, int idx);
RZ_API RzAnalysisEsilTrace *rz_analysis_esil_trace_new(RzAnalysisEsil *esil);
RZ_API void rz_analysis_esil_trace_free(RzAnalysisEsilTrace *trace);
RZ_API void rz_analysis_esil_trace_op(RzAnalysisEsil *esil, ut64 pc, RZ_NULLABLE const char *esil_expr);
RZ_API void rz_analysis_esil_trace_list(RzAnalysisEsil *esil);
RZ_API void rz_analysis_esil_trace_show(RzAnalysisEsil *esil, int idx);
RZ_API void rz_analysis_esil_trace_restore(RzAnalysisEsil *esil, int idx);
#ifdef __cplusplus
}
#endif
#endif /* RZ_ANALYSIS_ESIL_H */

View file

@ -2,7 +2,6 @@
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_util/rz_annotated_code.h>
#include <rz_core.h>
#include <rz_util.h>
RZ_API RzAnnotatedCode *rz_annotated_code_new(char *code) {

View file

@ -3,7 +3,7 @@
#include <string.h>
#include <rz_types.h>
#include <rz_core.h>
#include <rz_util.h>
#include "axml_resources.h"

View file

@ -2,7 +2,7 @@
// SPDX-FileCopyrightText: 2020 karliss <karlis3p70l1ij@gmail.com>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_core.h>
#include <rz_util.h>
#include <rz_util/rz_graph_drawable.h>
#include "graph_priv.h"

View file

@ -11,7 +11,9 @@
#include <rz_util/rz_strbuf.h>
#include <rz_vector.h>
#include <rz_util/rz_print.h>
#define RZ_NO_ESIL 1
#include <rz_analysis.h>
#undef RZ_NO_ESIL
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

View file

@ -1,10 +1,10 @@
// SPDX-FileCopyrightText: 2013-2020 pancake <pancake@nopcode.org>
// SPDX-License-Identifier: LGPL-3.0-only
#include "rz_types.h"
#include "rz_util/rz_sys.h"
#include <rz_types.h>
#include <rz_util/rz_sys.h>
#include <rz_util/rz_str.h>
#include <rz_core.h>
#include <rz_util.h>
#include <errno.h>
#include <string.h>