Reuse R_PERM in RAnalVarAccess.type instead of custom enum ##analysis

This commit is contained in:
pancake 2024-07-09 13:36:24 +02:00 committed by GitHub
parent c9b159c265
commit 668984c309
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 45 additions and 44 deletions

View File

@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2010-2023 - pancake, oddcoder */
/* radare - LGPL - Copyright 2010-2024 - pancake, oddcoder */
#define R_LOG_ORIGIN "anal.var"
@ -632,7 +632,7 @@ R_API RAnalVar *r_anal_var_get_dst_var(RAnalVar *var) {
r_return_val_if_fail (var, NULL);
RAnalVarAccess *acc;
r_vector_foreach (&var->accesses, acc) {
if (!(acc->type & R_ANAL_VAR_ACCESS_TYPE_READ)) {
if (!(acc->type & R_PERM_R)) {
continue;
}
ut64 addr = var->fcn->addr + acc->offset;
@ -644,7 +644,7 @@ R_API RAnalVar *r_anal_var_get_dst_var(RAnalVar *var) {
continue;
}
RAnalVarAccess *other_acc = r_anal_var_get_access_at (used_var, addr);
if (other_acc && other_acc->type & R_ANAL_VAR_ACCESS_TYPE_WRITE) {
if (other_acc && other_acc->type & R_PERM_W) {
return used_var;
}
}
@ -1003,7 +1003,7 @@ static void extract_arg(RAnal *anal, RAnalFunction *fcn, RAnalOp *op, const char
}
const int maxarg = 32; // TODO: use maxarg ?
int rw = (op->direction == R_ANAL_OP_DIR_WRITE) ? R_ANAL_VAR_ACCESS_TYPE_WRITE : R_ANAL_VAR_ACCESS_TYPE_READ;
int rw = (op->direction == R_ANAL_OP_DIR_WRITE) ? R_PERM_W : R_PERM_R;
if (*sign == '+') {
const bool isarg = type == R_ANAL_VAR_KIND_SPV ? ptr >= fcn->stack : ptr >= fcn->bp_off;
const char *pfx = isarg ? ARGPREFIX : VARPREFIX;
@ -1348,7 +1348,7 @@ R_API void r_anal_extract_rarg(RAnal *anal, RAnalOp *op, RAnalFunction *fcn, int
reg_set[i] = 1;
}
if (var) {
r_anal_var_set_access (var, var->regname, op->addr, R_ANAL_VAR_ACCESS_TYPE_READ, 0);
r_anal_var_set_access (var, var->regname, op->addr, R_PERM_R, 0);
r_meta_set_string (anal, R_META_TYPE_VARTYPE, op->addr, var->name);
}
}
@ -1367,7 +1367,7 @@ R_API void r_anal_extract_rarg(RAnal *anal, RAnalOp *op, RAnalFunction *fcn, int
}
RAnalVar *newvar = r_anal_function_set_var (fcn, delta, R_ANAL_VAR_KIND_REG, 0, size, true, vname);
if (newvar) {
r_anal_var_set_access (newvar, newvar->regname, op->addr, R_ANAL_VAR_ACCESS_TYPE_READ, 0);
r_anal_var_set_access (newvar, newvar->regname, op->addr, R_PERM_R, 0);
}
r_meta_set_string (anal, R_META_TYPE_VARTYPE, op->addr, vname);
free (vname);
@ -1392,7 +1392,7 @@ R_API void r_anal_extract_rarg(RAnal *anal, RAnalOp *op, RAnalFunction *fcn, int
}
RAnalVar *newvar = r_anal_function_set_var (fcn, delta, R_ANAL_VAR_KIND_REG, 0, size, true, vname);
if (newvar) {
r_anal_var_set_access (newvar, newvar->regname, op->addr, R_ANAL_VAR_ACCESS_TYPE_READ, 0);
r_anal_var_set_access (newvar, newvar->regname, op->addr, R_PERM_R, 0);
}
r_meta_set_string (anal, R_META_TYPE_VARTYPE, op->addr, vname);
free (vname);

View File

@ -5228,10 +5228,12 @@ typedef struct {
ut64 initial_sp;
} EsilBreakCtx;
static const char *reg_name_for_access(RAnalOp* op, RAnalVarAccessType type) {
typedef int RPerm;
static const char *reg_name_for_access(RAnalOp* op, RPerm type) {
RAnalValue *dst = r_vector_at (&op->dsts, 0);
RAnalValue *src = r_vector_at (&op->srcs, 0);
if (type == R_ANAL_VAR_ACCESS_TYPE_WRITE) {
if (type == R_PERM_W) {
if (dst) {
return dst->reg;
}
@ -5241,11 +5243,11 @@ static const char *reg_name_for_access(RAnalOp* op, RAnalVarAccessType type) {
return NULL;
}
static ut64 delta_for_access(RAnalOp *op, RAnalVarAccessType type) {
static ut64 delta_for_access(RAnalOp *op, RPerm type) {
RAnalValue *dst = r_vector_at (&op->dsts, 0);
RAnalValue *src0 = r_vector_at (&op->srcs, 0);
RAnalValue *src1 = r_vector_at (&op->srcs, 1);
if (type == R_ANAL_VAR_ACCESS_TYPE_WRITE) {
if (type == R_PERM_W) {
if (dst) {
return dst->imm + dst->delta;
}
@ -5260,10 +5262,8 @@ static ut64 delta_for_access(RAnalOp *op, RAnalVarAccessType type) {
return 0;
}
static void handle_var_stack_access(REsil *esil, ut64 addr, RAnalVarAccessType type, int len) {
if (!esil || !esil->user) {
return;
}
static void handle_var_stack_access(REsil *esil, ut64 addr, RPerm type, int len) {
R_RETURN_IF_FAIL (esil && esil->user);
EsilBreakCtx *ctx = esil->user;
const char *regname = reg_name_for_access (ctx->op, type);
if (ctx->fcn && regname) {
@ -5303,7 +5303,7 @@ static bool is_stack(RIO *io, ut64 addr) {
static bool esilbreak_mem_write(REsil *esil, ut64 addr, const ut8 *buf, int len) {
RCore *core = esil->anal->coreb.core;
handle_var_stack_access (esil, addr, R_ANAL_VAR_ACCESS_TYPE_WRITE, len);
handle_var_stack_access (esil, addr, R_PERM_W, len);
// ignore writes in stack
if (myvalid (core->io, addr) && r_io_read_at (core->io, addr, (ut8*)buf, len)) {
if (!is_stack (core->io, addr)) {
@ -5329,7 +5329,7 @@ static bool esilbreak_mem_read(REsil *esil, ut64 addr, ut8 *buf, int len) {
if (addr != UT64_MAX) {
esilbreak_last_read = addr;
}
handle_var_stack_access (esil, addr, R_ANAL_VAR_ACCESS_TYPE_READ, len);
handle_var_stack_access (esil, addr, R_PERM_R, len);
if (myvalid (core->io, addr) && r_io_read_at (core->io, addr, (ut8*)buf, len)) {
ut64 refptr = UT64_MAX;
bool trace = true;
@ -5376,14 +5376,12 @@ static bool esilbreak_mem_read(REsil *esil, ut64 addr, ut8 *buf, int len) {
}
static bool esilbreak_reg_write(REsil *esil, const char *name, ut64 *val) {
if (!esil || !esil->anal || !esil->user) {
return false;
}
R_RETURN_VAL_IF_FAIL (esil && esil->anal && esil->user, false);
RAnal *anal = esil->anal;
EsilBreakCtx *ctx = esil->user;
RAnalOp *op = ctx->op;
RCore *core = anal->coreb.core;
handle_var_stack_access (esil, *val, R_ANAL_VAR_ACCESS_TYPE_PTR, esil->anal->config->bits / 8);
handle_var_stack_access (esil, *val, R_PERM_NONE, esil->anal->config->bits / 8);
const bool is_arm = !strcmp (core->anal->config->arch, "arm");
//specific case to handle blx/bx cases in arm through emulation
// XXX this thing creates a lot of false positives

View File

@ -1517,7 +1517,7 @@ static void list_vars(RCore *core, RAnalFunction *fcn, PJ *pj, int type, const c
r_cons_printf ("* %s\n", var->name);
RAnalVarAccess *acc;
r_vector_foreach (&var->accesses, acc) {
if (!(acc->type & R_ANAL_VAR_ACCESS_TYPE_READ)) {
if (!(acc->type & R_PERM_R)) {
continue;
}
r_cons_printf ("R 0x%"PFMT64x" ", fcn->addr + acc->offset);
@ -1525,7 +1525,7 @@ static void list_vars(RCore *core, RAnalFunction *fcn, PJ *pj, int type, const c
r_core_print_disasm_instructions (core, 0, 1);
}
r_vector_foreach (&var->accesses, acc) {
if (!(acc->type & R_ANAL_VAR_ACCESS_TYPE_WRITE)) {
if (!(acc->type & R_PERM_W)) {
continue;
}
r_cons_printf ("W 0x%"PFMT64x" ", fcn->addr + acc->offset);
@ -1551,7 +1551,7 @@ static void list_vars(RCore *core, RAnalFunction *fcn, PJ *pj, int type, const c
r_list_free (list);
return;
}
int access_type = type == 'R' ? R_ANAL_VAR_ACCESS_TYPE_READ : R_ANAL_VAR_ACCESS_TYPE_WRITE;
int access_type = type == 'R' ? R_PERM_R : R_PERM_W;
if (pj) {
pj_a (pj);
}
@ -2049,7 +2049,7 @@ static int var_cmd(RCore *core, const char *str) {
res = false;
break;
}
int rw = (str[1] == 'g') ? R_ANAL_VAR_ACCESS_TYPE_READ : R_ANAL_VAR_ACCESS_TYPE_WRITE;
int rw = (str[1] == 'g') ? R_PERM_R : R_PERM_W;
int ptr = *var->type == 's' ? idx - fcn->maxstack : idx;
RAnalOp *op = r_core_anal_op (core, addr, 0);
const char *ireg = op ? op->ireg : NULL;

View File

@ -7,6 +7,7 @@
// still required by core in lot of places
#define USE_VARSUBS 0
#include <r_cons.h>
#include <r_types.h>
#include <r_io.h>
#include <r_esil.h>
@ -503,17 +504,19 @@ typedef enum {
#define VARPREFIX "var"
#define ARGPREFIX "arg"
#if 0
typedef enum {
R_ANAL_VAR_ACCESS_TYPE_PTR = 0,
R_ANAL_VAR_ACCESS_TYPE_READ = (1 << 0),
R_ANAL_VAR_ACCESS_TYPE_WRITE = (1 << 1)
} RAnalVarAccessType;
#endif
typedef struct r_anal_var_access_t {
const char *reg; // register used for access
st64 offset; // relative to the function's entrypoint
st64 stackptr; // delta added to register to get the var, e.g. [rbp - 0x10]
ut8 type; // RAnalVarAccessType bits
ut8 type; // R_PERM_{R/W/NONE} // TODO: R2_600 what about using rwx instead of custom enum?
} RAnalVarAccess;
typedef struct r_anal_var_constraint_t {
@ -608,7 +611,8 @@ typedef struct r_anal_bb_t {
ut8 *op_bytes;
ut8 *parent_reg_arena;
int parent_reg_arena_size;
#if R2_590
#if R2_600
// for the oppos
USE RVec
#else
ut16 *op_pos; // offsets of instructions in this block, count is ninstr - 1 (first is always 0)
@ -620,7 +624,6 @@ typedef struct r_anal_bb_t {
ut64 cmpval;
const char *cmpreg;
ut32 bbhash; // calculated with xxhash
RList *fcns;
RAnal *anal;
char *esil;
@ -721,17 +724,17 @@ enum {
R_ANAL_ESIL_DFG_TAG_MEM = 64,
R_ANAL_ESIL_DFG_TAG_MERGE = 128,
R_ANAL_ESIL_DFG_TAG_SIBLING = 256,
}; //RAnalEsilDFGTagType
}; // RAnalEsilDFGTagType
typedef struct r_anal_esil_dfg_t {
ut32 idx;
int fd;
RIOBind iob;
RReg *reg;
Sdb *regs; //resolves regnames to intervals
RRBTree *vars; //vars represented in regs and mem
RQueue *todo; //todo-queue allocated in this struct for perf
void *insert; //needed for setting regs in dfg
Sdb *regs; // resolves regnames to intervals
RRBTree *vars; // vars represented in regs and mem
RQueue *todo; // todo-queue allocated in this struct for perf
void *insert; // needed for setting regs in dfg
RGraph *flow;
RGraphNode *cur;
RGraphNode *old;
@ -787,7 +790,7 @@ typedef struct r_anal_plugin_t {
} RAnalPlugin;
/*----------------------------------------------------------------------------------------------*/
int * (r_anal_compare) (RAnalFunction , RAnalFunction );
int * (r_anal_compare) (RAnalFunction , RAnalFunction);
/*----------------------------------------------------------------------------------------------*/
#ifdef R_API
@ -1021,7 +1024,6 @@ R_API int r_anal_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int le
R_API int r_anal_opasm(RAnal *anal, ut64 pc, const char *s, ut8 *outbuf, int outlen);
R_API char *r_anal_op_tostring(RAnal *anal, RAnalOp *op);
/* pin */
R_API void r_anal_pin_init(RAnal *a);
R_API void r_anal_pin_fini(RAnal *a);
@ -1249,7 +1251,6 @@ R_API int r_anal_data_type(RAnal *a, ut64 da);
R_API RAnalData *r_anal_data_new_string(ut64 addr, const char *p, int size, int wide);
R_API RAnalData *r_anal_data_new(ut64 addr, int type, ut64 n, const ut8 *buf, int len);
R_API void r_anal_data_free(RAnalData *d);
#include <r_cons.h>
R_API char *r_anal_data_tostring(RAnalData *d, RConsPrintablePalette *pal);
/* meta

View File

@ -79,6 +79,7 @@
#define R_PERM_R 4
#define R_PERM_W 2
#define R_PERM_X 1
#define R_PERM_NONE 0
#define R_PERM_RW (R_PERM_R|R_PERM_W)
#define R_PERM_RX (R_PERM_R|R_PERM_X)
#define R_PERM_RWX (R_PERM_R|R_PERM_W|R_PERM_X)
@ -88,6 +89,7 @@
#define R_PERM_PRIV 16
#define R_PERM_ACCESS 32
#define R_PERM_CREAT 64
// R2_600 typedef int RPerm;
// HACK to fix capstone-android-mips build

View File

@ -95,10 +95,10 @@ bool test_r_anal_var(void) {
// accesses
r_anal_var_set_access (a, "rsp", 0x120, R_ANAL_VAR_ACCESS_TYPE_READ, 42);
r_anal_var_set_access (a, "rbp", 0x130, R_ANAL_VAR_ACCESS_TYPE_WRITE, 13);
r_anal_var_set_access (b, "rsp", 0x120, R_ANAL_VAR_ACCESS_TYPE_WRITE, 123);
r_anal_var_set_access (b, "rbp", 0x10, R_ANAL_VAR_ACCESS_TYPE_WRITE, -100);
r_anal_var_set_access (a, "rsp", 0x120, R_PERM_R, 42);
r_anal_var_set_access (a, "rbp", 0x130, R_PERM_W, 13);
r_anal_var_set_access (b, "rsp", 0x120, R_PERM_W, 123);
r_anal_var_set_access (b, "rbp", 0x10, R_PERM_W, -100);
st64 stackptr = r_anal_function_get_var_stackptr_at (fcn, -0x10, 0x12345);
mu_assert_eq (stackptr, ST64_MAX, "unset stackptr");
@ -135,14 +135,14 @@ bool test_r_anal_var(void) {
used_vars = r_anal_function_get_vars_used_at (fcn, 0xffffffffffff0130UL); // addresses should stay the same
mu_assert ("no used vars", !used_vars || r_pvector_length (used_vars));
r_anal_var_set_access (a, "rbp", 0xffffffffffff0130UL, R_ANAL_VAR_ACCESS_TYPE_READ, 42);
r_anal_var_set_access (a, "rbp", 0xffffffffffff0130UL, R_PERM_R, 42);
used_vars = r_anal_function_get_vars_used_at (fcn, 0xffffffffffff0130UL);
mu_assert_eq (r_pvector_length (used_vars), 1, "used vars count");
mu_assert ("used vars", r_pvector_contains (used_vars, a));
used_vars = r_anal_function_get_vars_used_at (fcn, 0x123);
mu_assert ("no used vars", !used_vars || r_pvector_length (used_vars));
r_anal_var_set_access (a, "rbp" , 0x123, R_ANAL_VAR_ACCESS_TYPE_READ, 42);
r_anal_var_set_access (a, "rbp" , 0x123, R_PERM_R, 42);
used_vars = r_anal_function_get_vars_used_at (fcn, 0x123);
mu_assert_eq (r_pvector_length (used_vars), 1, "used vars count");
mu_assert ("used vars", r_pvector_contains (used_vars, a));
@ -167,7 +167,7 @@ bool test_r_anal_var(void) {
used_vars = r_anal_function_get_vars_used_at (fcn, 0x8000000000000100);
mu_assert ("no used vars", !used_vars || r_pvector_length (used_vars));
r_anal_var_set_access (a, "rbp", 0x8000000000000100, R_ANAL_VAR_ACCESS_TYPE_READ, 987321);
r_anal_var_set_access (a, "rbp", 0x8000000000000100, R_PERM_R, 987321);
used_vars = r_anal_function_get_vars_used_at (fcn, 0x8000000000000100);
mu_assert_eq (r_pvector_length (used_vars), 1, "used vars count");
mu_assert ("used vars", r_pvector_contains (used_vars, a));
@ -176,7 +176,7 @@ bool test_r_anal_var(void) {
used_vars = r_anal_function_get_vars_used_at (fcn, 0x7ffffffffffffe00);
mu_assert ("no used vars", !used_vars || r_pvector_length (used_vars));
r_anal_var_set_access (a, "rbp", 0x7ffffffffffffe00, R_ANAL_VAR_ACCESS_TYPE_READ, 777);
r_anal_var_set_access (a, "rbp", 0x7ffffffffffffe00, R_PERM_R, 777);
used_vars = r_anal_function_get_vars_used_at (fcn, 0x7ffffffffffffe00);
mu_assert_eq (r_pvector_length (used_vars), 1, "used vars count");
mu_assert ("used vars", r_pvector_contains (used_vars, a));