Skip to content

Commit

Permalink
Move esil_cfg related typedefs back to anal
Browse files Browse the repository at this point in the history
  • Loading branch information
condret committed Nov 25, 2024
1 parent 34bc40f commit 0561115
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 57 deletions.
76 changes: 39 additions & 37 deletions libr/anal/esil_cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,22 +85,22 @@ static void esil_expr_atomize(RIDStorage *atoms, char *expr) {
}

static void _free_bb_cb(void *data) {
REsilBB *bb = (REsilBB *)data;
RAnalEsilBB *bb = (RAnalEsilBB *)data;
free (bb->expr);
free (bb);
}

// REMINDER: generating the block content needs to prepend setting the program counter
// r_anal_esil_cfg_op does this ^, use it whenever generating cfg from op

// this nasty function is an insert-compare for RGraphNodes that contain REsilBB
// this nasty function is an insert-compare for RGraphNodes that contain RAnalEsilBB
static int _graphnode_esilbb_insert_cmp(void *incoming, void *in, void *user) {
RGraphNode *incoming_gnode = (RGraphNode *)incoming;
RGraphNode *in_gnode = (RGraphNode *)in;
REsilBB *incoming_bb = (REsilBB *)incoming_gnode->data;
REsilBB *in_bb = (REsilBB *)in_gnode->data;
RAnalEsilBB *incoming_bb = (RAnalEsilBB *)incoming_gnode->data;
RAnalEsilBB *in_bb = (RAnalEsilBB *)in_gnode->data;

// REsilBBs have the nice property, that they cannot intersect,
// RAnalEsilBBs have the nice property, that they cannot intersect,
// so just comparing first and first should be fine for inserting
#if 0
return incoming_bb->first - in_bb->first;
Expand All @@ -118,9 +118,9 @@ static int _graphnode_esilbb_insert_cmp(void *incoming, void *in, void *user) {
}

static int _graphnode_esilbb_find_cmp(void *incoming, void *in, void *user) {
REsilEOffset *find_me = (REsilEOffset *)incoming;
RAnalEsilEOffset *find_me = (RAnalEsilEOffset *)incoming;
RGraphNode *in_gnode = (RGraphNode *)in;
REsilBB *in_bb = (REsilBB *)in_gnode->data;
RAnalEsilBB *in_bb = (RAnalEsilBB *)in_gnode->data;
// not sure if this is needed that way
if (find_me->off < in_bb->first.off) {
return -1;
Expand All @@ -140,7 +140,7 @@ static int _graphnode_esilbb_find_cmp(void *incoming, void *in, void *user) {
static int _graphnode_delete_always_0_cmp(void *incoming, void *in, void *user) {
EsilCfgGen *gen = (EsilCfgGen *)user;
RGraphNode *delete_me = (RGraphNode *)in;
REsilBB *delete_me_bb = (REsilBB *)delete_me->data;
RAnalEsilBB *delete_me_bb = (RAnalEsilBB *)delete_me->data;
r_graph_del_node (gen->cfg->g, delete_me);
ut32 id;
for (id = delete_me_bb->first.idx; id <= delete_me_bb->last.idx; id++) {
Expand All @@ -157,13 +157,13 @@ void _handle_if_enter (EsilCfgGen *gen, ut32 id, const bool has_next) {
EsilCfgScopeCookie *cookie = R_NEW0 (EsilCfgScopeCookie);

// get current bb
// REsilBB *bb = (REsilBB *)gen->cur->data;
// RAnalEsilBB *bb = (RAnalEsilBB *)gen->cur->data;

// create if-enter-bb
REsilBB *entered_bb = R_NEW0 (REsilBB);
RAnalEsilBB *entered_bb = R_NEW0 (RAnalEsilBB);
entered_bb->first.off = entered_bb->last.off = gen->off;
entered_bb->first.idx = entered_bb->last.idx = id + 1;
entered_bb->enter = R_ESIL_BLOCK_ENTER_TRUE;
entered_bb->enter = R_ANAL_ESIL_BLOCK_ENTER_TRUE;

// create if-entered-graph-node
RGraphNode *entered_node = r_graph_add_node (gen->cfg->g, entered_bb);
Expand All @@ -188,7 +188,7 @@ void _handle_else_enter (EsilCfgGen *gen, ut32 id, const bool has_next) {
EsilCfgScopeCookie *cookie = (EsilCfgScopeCookie *)r_stack_peek (gen->ifelse);

// create if-enter-bb
REsilBB *entered_bb = R_NEW0 (REsilBB);
RAnalEsilBB *entered_bb = R_NEW0 (RAnalEsilBB);
entered_bb->first.off = entered_bb->last.off = gen->off;
entered_bb->first.idx = entered_bb->last.idx = id + 1;

Expand All @@ -198,13 +198,13 @@ void _handle_else_enter (EsilCfgGen *gen, ut32 id, const bool has_next) {
r_crbtree_insert (gen->blocks, entered_node, _graphnode_esilbb_insert_cmp, NULL);

if (cookie->is_else) {
entered_bb->enter = R_ESIL_BLOCK_ENTER_TRUE;
entered_bb->enter = R_ANAL_ESIL_BLOCK_ENTER_TRUE;
r_graph_add_edge (gen->cfg->g, cookie->if_block, entered_node);
cookie->if_block = entered_node;
cookie->else_block = gen->cur;
cookie->is_else = false;
} else {
entered_bb->enter = R_ESIL_BLOCK_ENTER_FALSE;
entered_bb->enter = R_ANAL_ESIL_BLOCK_ENTER_FALSE;
r_graph_add_edge (gen->cfg->g, cookie->else_block, entered_node);
cookie->else_block = entered_node;
cookie->if_block = gen->cur;
Expand All @@ -220,12 +220,12 @@ void _handle_fi_leave(EsilCfgGen *gen, ut32 id, const bool has_next) {
return;
}

REsilBB *cur_bb = (REsilBB *)gen->cur->data;
RAnalEsilBB *cur_bb = (RAnalEsilBB *)gen->cur->data;
// this block is not executed when the if or else block is empty
if (memcmp (&cur_bb->first, &cur_bb->last, sizeof (REsilEOffset))) {
if (memcmp (&cur_bb->first, &cur_bb->last, sizeof (RAnalEsilEOffset))) {
// TODO: add some thoughts in comments here
cur_bb->last.idx--;
REsilBB *leaving_bb = R_NEW0 (REsilBB);
RAnalEsilBB *leaving_bb = R_NEW0 (RAnalEsilBB);
leaving_bb->first.off = leaving_bb->last.off = gen->off;
leaving_bb->first.idx = leaving_bb->last.idx = id;
RGraphNode *leaving_node = r_graph_add_node (gen->cfg->g, leaving_bb);
Expand Down Expand Up @@ -261,7 +261,7 @@ void _handle_control_flow_ifelsefi (EsilCfgGen *gen, char *atom, ut32 id) {
bool _round_0_cb (void *user, void *data, ut32 id) {
EsilCfgGen *gen = (EsilCfgGen *)user;
char *atom = (char *)data;
REsilBB *bb = (REsilBB *)gen->cur->data;
RAnalEsilBB *bb = (RAnalEsilBB *)gen->cur->data;
REsilOp *op = esil_get_op (gen->esil, atom);
bb->last.idx = (ut16)id;
if (op && op->type == R_ESIL_OP_TYPE_CONTROL_FLOW) {
Expand All @@ -271,11 +271,11 @@ bool _round_0_cb (void *user, void *data, ut32 id) {
}

RGraphNode *_common_break_goto (EsilCfgGen *gen, ut32 id) {
REsilEOffset off = { gen->off, (ut16)id };
RAnalEsilEOffset off = { gen->off, (ut16)id };
RGraphNode *gnode = r_crbtree_find (gen->blocks, &off, _graphnode_esilbb_find_cmp, NULL);
REsilBB *bb = (REsilBB *)gnode->data;
RAnalEsilBB *bb = (RAnalEsilBB *)gnode->data;
if (id != bb->last.idx) {
REsilBB *next_bb = R_NEW0 (REsilBB);
RAnalEsilBB *next_bb = R_NEW0 (RAnalEsilBB);
// split blocks
next_bb->first.off = gen->off;
next_bb->first.idx = id + 1;
Expand All @@ -302,7 +302,7 @@ void _handle_break (EsilCfgGen *gen, ut32 id) {

void _handle_goto (EsilCfgGen *gen, ut32 idx) {
RGraphNode *gnode = _common_break_goto (gen, idx);
REsilBB *bb = (REsilBB *)gnode->data;
RAnalEsilBB *bb = (RAnalEsilBB *)gnode->data;
// so what we're doing here is emulating this block with a certain degree of abstraction:
// no reg-access
// no io-access
Expand Down Expand Up @@ -348,16 +348,16 @@ void _handle_goto (EsilCfgGen *gen, ut32 idx) {
}

// get the node to the corresponding GOTO destination
REsilEOffset dst_off = { gen->off, (ut16)v->val };
RAnalEsilEOffset dst_off = { gen->off, (ut16)v->val };
RGraphNode *dst_node = r_crbtree_find (gen->blocks, &dst_off, _graphnode_esilbb_find_cmp, NULL);
if (!dst_node) {
// out-of-bounds
// check if this works
dst_node = gen->cfg->end;
} else {
REsilBB *dst_bb = (REsilBB *)dst_node->data;
RAnalEsilBB *dst_bb = (RAnalEsilBB *)dst_node->data;
if (dst_bb->first.idx != v->val) {
REsilBB *split_bb = R_NEW0 (REsilBB);
RAnalEsilBB *split_bb = R_NEW0 (RAnalEsilBB);
split_bb[0] = dst_bb[0];
dst_bb->last.idx = v->val - 1;
split_bb->first.idx = v->val;
Expand Down Expand Up @@ -390,7 +390,7 @@ bool _round_1_cb(void *user, void *data, ut32 id) {
}

void _round_2_cb (RGraphNode *n, RGraphVisitor *vi) {
REsilBB *bb = (REsilBB *)n->data;
RAnalEsilBB *bb = (RAnalEsilBB *)n->data;
EsilCfgGen *gen = (EsilCfgGen *)vi->data;
RStrBuf *buf = r_strbuf_new (n == gen->cfg->end ? NULL: (char *)r_id_storage_get (gen->atoms, bb->first.idx));
r_strbuf_append (buf, ",");
Expand All @@ -417,7 +417,7 @@ static RAnalEsilCFG *esil_cfg_gen(RAnalEsilCFG *cfg, RAnal *anal, RIDStorage *at
if (!_expr) {
return cfg; //NULL?
}
REsilBB *end_bb = R_NEW0 (REsilBB);
RAnalEsilBB *end_bb = R_NEW0 (RAnalEsilBB);
if (!end_bb) {
free (_expr);
return cfg;
Expand All @@ -441,7 +441,7 @@ static RAnalEsilCFG *esil_cfg_gen(RAnalEsilCFG *cfg, RAnal *anal, RIDStorage *at
//
// without information about the outside cfg, we CANNOT merge cpu-instructions

REsilBB *bb = (REsilBB *)cfg->end->data;
RAnalEsilBB *bb = (RAnalEsilBB *)cfg->end->data;

end_bb->expr = bb->expr;
// FIXME: use end_bb here
Expand Down Expand Up @@ -500,7 +500,7 @@ static RAnalEsilCFG *esil_cfg_gen(RAnalEsilCFG *cfg, RAnal *anal, RIDStorage *at
R_IPI RAnalEsilCFG *r_anal_esil_cfg_new(void) {
RAnalEsilCFG *cf = R_NEW0 (RAnalEsilCFG);
if (cf) {
REsilBB *p = R_NEW0 (REsilBB);
RAnalEsilBB *p = R_NEW0 (RAnalEsilBB);
if (!p) {
free (cf);
return NULL;
Expand Down Expand Up @@ -576,7 +576,7 @@ R_API RAnalEsilCFG *r_anal_esil_cfg_op(R_NULLABLE RAnalEsilCFG *cfg, RAnal *anal
if (!anal->reg || !anal->esil) {
return NULL;
}
REsilBB *glue_bb = R_NEW0 (REsilBB);
RAnalEsilBB *glue_bb = R_NEW0 (RAnalEsilBB);
if (!glue_bb) {
return NULL;
}
Expand All @@ -593,7 +593,7 @@ R_API RAnalEsilCFG *r_anal_esil_cfg_op(R_NULLABLE RAnalEsilCFG *cfg, RAnal *anal
free (glue_bb);
return NULL;
}
glue_bb->enter = R_ESIL_BLOCK_ENTER_GLUE;
glue_bb->enter = R_ANAL_ESIL_BLOCK_ENTER_GLUE;
glue_bb->first.off = glue_bb->last.off = op->addr;
glue_bb->first.idx = glue_bb->last.idx = 0;

Expand Down Expand Up @@ -630,12 +630,13 @@ static void merge_2_blocks(RAnalEsilCFG *cfg, RGraphNode *node, RGraphNode *bloc
r_list_foreach (block->in_nodes, iter, n) {
r_graph_add_edge (cfg->g, n, node);
}
REsilBB *block_bb, *node_bb = (REsilBB *)node->data;
block_bb = (REsilBB *)block->data;
if ((block_bb->enter == R_ESIL_BLOCK_ENTER_TRUE) || (block_bb->enter == R_ESIL_BLOCK_ENTER_FALSE)) {
RAnalEsilBB *block_bb, *node_bb = (RAnalEsilBB *)node->data;
block_bb = (RAnalEsilBB *)block->data;
if ((block_bb->enter == R_ANAL_ESIL_BLOCK_ENTER_TRUE) ||
(block_bb->enter == R_ANAL_ESIL_BLOCK_ENTER_FALSE)) {
node_bb->enter = block_bb->enter;
} else {
node_bb->enter = R_ESIL_BLOCK_ENTER_NORMAL;
node_bb->enter = R_ANAL_ESIL_BLOCK_ENTER_NORMAL;
}
RStrBuf *buf = r_strbuf_new (block_bb->expr);
node_bb->first = block_bb->first;
Expand All @@ -657,10 +658,11 @@ R_API void r_anal_esil_cfg_merge_blocks(RAnalEsilCFG *cfg) {
RGraphNode *node;
r_list_foreach_safe (cfg->g->nodes, iter, ator, node) {
if (r_list_length (node->in_nodes) == 1) {
REsilBB *bb = (REsilBB *)node->data;
RAnalEsilBB *bb = (RAnalEsilBB *)node->data;
RGraphNode *top = (RGraphNode *)r_list_last (node->out_nodes);
// segfaults here ?
if (!(top && bb->enter == R_ESIL_BLOCK_ENTER_GLUE && (r_list_length (top->in_nodes) > 1))) {
if (!(top && bb->enter == R_ANAL_ESIL_BLOCK_ENTER_GLUE &&
(r_list_length (top->in_nodes) > 1))) {
RGraphNode *block = (RGraphNode *)r_list_last (node->in_nodes);
if (r_list_length (block->out_nodes) == 1) {
merge_2_blocks (cfg, node, block);
Expand Down
20 changes: 20 additions & 0 deletions libr/include/r_anal.h
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,26 @@ typedef struct r_anal_esil_cfg_t {
RGraph *g;
} RAnalEsilCFG;

// this is 80-bit offsets so we can address every piece of esil in an instruction
typedef struct r_anal_esil_expr_offset_t {
ut64 off;
ut16 idx;
} RAnalEsilEOffset;

typedef enum {
R_ANAL_ESIL_BLOCK_ENTER_NORMAL = 0,
R_ANAL_ESIL_BLOCK_ENTER_TRUE,
R_ANAL_ESIL_BLOCK_ENTER_FALSE,
R_ANAL_ESIL_BLOCK_ENTER_GLUE,
} RAnalEsilBlockEnterType;

typedef struct r_anal_esil_basic_block_t {
RAnalEsilEOffset first;
RAnalEsilEOffset last;
char *expr; //synthesized esil-expression for this block
RAnalEsilBlockEnterType enter; //maybe more type is needed here
} RAnalEsilBB;

enum {
R_ANAL_ESIL_DFG_TAG_CONST = 1,
R_ANAL_ESIL_DFG_TAG_VAR = 2,
Expand Down
20 changes: 0 additions & 20 deletions libr/include/r_esil.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,26 +36,6 @@ enum {
R_ESIL_OP_TYPE_TRAP = 0x100 // syscall, interrupts, breakpoints, ...
};

// this is 80-bit offsets so we can address every piece of esil in an instruction
typedef struct r_esil_expr_offset_t {
ut64 off;
ut16 idx;
} REsilEOffset;

typedef enum {
R_ESIL_BLOCK_ENTER_NORMAL = 0,
R_ESIL_BLOCK_ENTER_TRUE,
R_ESIL_BLOCK_ENTER_FALSE,
R_ESIL_BLOCK_ENTER_GLUE,
} REsilBlockEnterType;

typedef struct r_esil_basic_block_t {
REsilEOffset first;
REsilEOffset last;
char *expr; //synthesized esil-expression for this block
REsilBlockEnterType enter; //maybe more type is needed here
} REsilBB;

typedef struct r_esil_t ESIL;

typedef bool (*REsilHandlerCB)(ESIL *esil, ut32 h, void *user);
Expand Down

0 comments on commit 0561115

Please sign in to comment.