Proposed fix to printing function disassembly with rewrite of the function handling reflines.

This commit is contained in:
Adam Pridgen 2014-01-22 22:55:48 -06:00 committed by pancake
parent 666ab166d1
commit 2e20adb68d
8 changed files with 290 additions and 10 deletions

View File

@ -321,8 +321,8 @@ R_API void r_anal_ex_op_to_bb(RAnal *anal, RAnalState *state, RAnalBlock *bb, RA
r_anal_ex_clone_op_switch_to_bb (bb, op);
}
R_API ut32 r_anal_ex_map_anal_ex_to_anal_bb_type (ut64 ranal2_op_type) {
ut32 bb_type = 0;
R_API ut64 r_anal_ex_map_anal_ex_to_anal_bb_type (ut64 ranal2_op_type) {
ut64 bb_type = 0;
ut64 conditional = R_ANAL_EX_COND_OP & ranal2_op_type ? R_ANAL_OP_TYPE_COND : 0;
ut64 code_op_val = ranal2_op_type & (R_ANAL_EX_CODE_OP | 0x1FF);

View File

@ -172,7 +172,7 @@ static int handle_bb_cf_recursive_descent (RAnal *anal, RAnalState *state) {
state->current_depth++;
addr = bb->addr;
IFDBG eprintf ("Handling a control flow change @ 0x%04"PFMT64x".\n", addr);
ut32 control_type = r_anal_ex_map_anal_ex_to_anal_op_type (bb->type2);
ut64 control_type = r_anal_ex_map_anal_ex_to_anal_op_type (bb->type2);
// XXX - transition to type2 control flow condtions
switch (control_type) {

View File

@ -87,6 +87,79 @@ R_API struct r_anal_refline_t *r_anal_reflines_get(struct r_anal_t *anal,
return list;
}
R_API struct r_anal_refline_t *r_anal_reflines_fcn_get( struct r_anal_t *anal, RAnalFunction *fcn,
int nlines, int linesout, int linescall) {
RAnalRefline *list2, *list = R_NEW (RAnalRefline);
RAnalBlock *bb;
RListIter *bb_iter;
int index = 0;
ut64 opc = fcn->addr, addr = 0;
ut32 len;
INIT_LIST_HEAD (&(list->list));
/* analyze code block */
r_list_foreach (fcn->bbs, bb_iter, bb) {
if (!bb || bb->size == 0) continue;
if (nlines != -1 && --nlines == 0) break;
len = bb->size;
addr = bb->addr;
/* store data */
ut64 control_type = bb->type;
control_type &= R_ANAL_BB_TYPE_SWITCH | R_ANAL_BB_TYPE_JMP | R_ANAL_BB_TYPE_COND | R_ANAL_BB_TYPE_CALL;
// handle call
if ( (control_type & R_ANAL_BB_TYPE_CALL) == R_ANAL_BB_TYPE_CALL && !linescall) {
continue;
}
// Handles conditonal + unconditional jump
if ( (control_type & R_ANAL_BB_TYPE_CJMP) == R_ANAL_BB_TYPE_CJMP) {
// dont need to continue here is opc+len exceed function scope
if (linesout && bb->fail > 0LL && bb->fail != bb->addr + len) {
list2 = R_NEW (RAnalRefline);
list2->from = bb->addr;
list2->to = bb->fail;
list2->index = index++;
list_add_tail (&(list2->list), &(list->list));
}
}
if ( (control_type & R_ANAL_BB_TYPE_JMP) == R_ANAL_BB_TYPE_JMP) {
if (!linesout || bb->jump == 0LL || bb->jump == bb->addr + len)
continue;
list2 = R_NEW (RAnalRefline);
list2->from = bb->addr;
list2->to = bb->jump;
list2->index = index++;
list_add_tail (&(list2->list), &(list->list));
continue;
}
// XXX - Todo test handle swith op
if ( control_type & R_ANAL_BB_TYPE_SWITCH) {
if (bb->switch_op) {
RAnalCaseOp *caseop;
RListIter *iter;
r_list_foreach (bb->switch_op->cases, iter, caseop) {
if (caseop) {
if (!linesout)// && (op.jump > opc+len || op.jump < pc))
continue;
list2 = R_NEW (RAnalRefline);
list2->from = bb->switch_op->addr;
list2->to = caseop->jump;
list2->index = index++;
list_add_tail (&(list2->list), &(list->list));
}
}
}
}
}
return list;
}
R_API int r_anal_reflines_middle(RAnal *a, RAnalRefline *list, ut64 addr, int len) {
struct list_head *pos;
if (list)

View File

@ -1,5 +1,5 @@
/* radare - LGPL - Copyright 2009-2013 - pancake */
//#include <r_anal_ex.h>
static int is_valid_input_num_value(RCore *core, char *input_value){
ut64 value = input_value ? r_num_math (core->num, input_value) : 0;
@ -839,7 +839,7 @@ static int cmd_print(void *data, const char *input) {
}
switch (input[1]) {
case 'i':
case 'i':
processed_cmd = R_TRUE;
pdi (core, l, len, (*input=='D')? len: core->blocksize);
pd_result = 0;
@ -973,8 +973,18 @@ static int cmd_print(void *data, const char *input) {
if (b->size > f->size) b->size = f->size;
}
// TODO: sort by addr
//r_list_sort (f->bbs, &r_anal_ex_bb_address_comparator);
r_list_foreach (f->bbs, iter, b) {
r_core_cmdf (core, "pD %"PFMT64d" @0x%"PFMT64x, b->size, b->addr);
/*switch (control_type) {
case R_ANAL_OP_TYPE_CALL:
break;
case R_ANAL_OP_TYPE_JMP:
break;
case R_ANAL_OP_TYPE_CJMP:
break;
case R_ANAL_OP_TYPE_SWITCH:
}*/
if (b->jump != UT64_MAX)
r_cons_printf ("-[true]-> 0x%08"PFMT64x"\n", b->jump);
if (b->fail != UT64_MAX)
@ -1008,6 +1018,9 @@ static int cmd_print(void *data, const char *input) {
RAnalFunction *f = r_anal_fcn_find (core->anal, core->offset,
R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM);
if (f) {
//RPrint *p, RCore *core, ut64 addr, int l, int invbreak, int cbytes
core->num->value = r_core_print_fcn_disasm (core->print, core, f->addr, 9999, 0, 2);
/*
ut8 *block = malloc (f->size+1);
if (block) {
r_core_read_at (core, f->addr, block, f->size);
@ -1016,7 +1029,7 @@ static int cmd_print(void *data, const char *input) {
f->size, 9999, 0, 2);
free (block);
pd_result = 0;
}
}*/
} else eprintf ("Cannot find function at 0x%08"PFMT64x"\n", core->offset);
}
l = 0;

View File

@ -170,6 +170,10 @@ static void handle_print_ptr (RCore *core, RDisasmState *ds, int len, int idx);
static int cmpaddr (void *_a, void *_b) {
RAnalBlock *a = _a, *b = _b;
return (a->addr > b->addr);
}
static void handle_add_show_color ( RCore *core, RDisasmState *ds) {
if (ds->show_color) {
@ -348,6 +352,18 @@ void handle_reflines_init (RCore *core, RDisasmState *ds) {
ds->addr, ds->buf, ds->len, -1,
ds->linesout, 1);
} else core->reflines = core->reflines2 = NULL;
}
void handle_reflines_fcn_init (RCore *core, RDisasmState *ds, RAnalFunction *fcn, ut8* buf) {
if (ds->show_lines) {
// TODO: make anal->reflines implicit
free (core->reflines); // TODO: leak
free (core->reflines2); // TODO: leak
core->reflines = r_anal_reflines_fcn_get (core->anal,
fcn, -1, ds->linesout, ds->show_linescall);
core->reflines2 = r_anal_reflines_fcn_get (core->anal,
fcn, -1, ds->linesout, 1);
} else core->reflines = core->reflines2 = NULL;
}
@ -1849,3 +1865,178 @@ R_API int r_core_print_disasm_json(RCore *core, ut64 addr, ut8 *buf, int len) {
r_cons_printf ("]");
return R_TRUE;
}
R_API int r_core_print_fcn_disasm(RPrint *p, RCore *core, ut64 addr, int l, int invbreak, int cbytes) {
/* other */
//void *old_user = core->anal->user;
RAnalFunction *fcn = r_anal_fcn_find (core->anal, addr, R_ANAL_FCN_TYPE_NULL),
*f = fcn;
ut32 cur_buf_sz = fcn->size+1;
ut8 *buf = malloc (cur_buf_sz);
ut32 len = fcn->size;
int ret, idx = 0, i;
int continueoninvbreak = (fcn->size == l) && invbreak;
RListIter *bb_iter;
RAnalBlock *bb = NULL;
RDisasmState *ds;
RList *bb_list = r_list_new();
//r_cons_printf ("len =%d l=%d ib=%d limit=%d\n", len, l, invbreak, p->limit);
// TODO: import values from debugger is possible
// TODO: allow to get those register snapshots from traces
// TODO: per-function register state trace
idx = 0;
memset (buf, 0, cur_buf_sz);
// TODO: All those ds must be print flags
ds = handle_init_ds (core);
ds->cbytes = cbytes;
ds->p = p;
ds->l = l;
ds->buf = buf;
ds->len = fcn->size;
ds->addr = fcn->addr;
r_list_foreach (fcn->bbs, bb_iter, bb) {
r_list_add_sorted (bb_list, bb, cmpaddr);
}
// Premptively read the bb data locs for ref lines
r_list_foreach (bb_list, bb_iter, bb) {
if (idx >= cur_buf_sz) break;
r_core_read_at (core, bb->addr, buf+idx, bb->size);
//ret = r_asm_disassemble (core->assembler, &ds->asmop, buf+idx, bb->size);
//if (ret > 0) eprintf ("%s\n",ds->asmop.buf_asm);
idx += bb->size;
}
handle_reflines_fcn_init (core, ds, fcn, buf);
core->inc = 0;
core->cons->vline = r_config_get_i (core->config, "scr.utf8")?
r_vline_u: r_vline_a;
r_cons_break (NULL, NULL);
i = 0;
idx = 0;
r_list_foreach (bb_list, bb_iter, bb) {
ut32 bb_size_consumed = 0;
// internal loop to consume bb that contain case-like operations
ds->at = bb->addr;
ds->addr = bb->addr;
len = bb->size;
if (len > cur_buf_sz) {
free(buf);
cur_buf_sz = len;
buf = malloc (cur_buf_sz);
ds->buf = buf;
}
do {
// XXX - why is it necessary to set this everytime?
r_asm_set_pc (core->assembler, ds->at);
if (ds->lines >= ds->l) break;
if (r_cons_singleton ()->breaked) break;
handle_update_ref_lines (core, ds);
/* show type links */
r_core_cmdf (core, "tf 0x%08"PFMT64x, ds->at);
handle_show_xrefs (core, ds);
handle_show_comments_right (core, ds);
ret = perform_disassembly (core, ds, buf+idx, len - bb_size_consumed);
handle_atabs_option (core, ds);
handle_colorize_opcode (core, ds);
// TODO: store previous oplen in core->dec
if (core->inc == 0) core->inc = ds->oplen;
r_anal_op_fini (&ds->analop);
if (!ds->lastfail)
r_anal_op (core->anal, &ds->analop, ds->at+bb_size_consumed, buf+idx, len-bb_size_consumed);
if (ret<1) {
r_strbuf_init (&ds->analop.esil);
ds->analop.type = R_ANAL_OP_TYPE_ILL;
}
handle_instruction_mov_lea (core, ds, idx);
handle_control_flow_comments (core, ds);
handle_adistrick_comments (core, ds);
/* XXX: This is really cpu consuming.. need to be fixed */
handle_show_functions (core, ds);
handle_show_flags_option (core, ds);
handle_print_lines_left (core, ds);
handle_print_offset (core, ds);
handle_print_op_size (core, ds);
handle_print_trace (core, ds);
handle_print_stackptr (core, ds);
ret = handle_print_meta_infos (core, ds, buf,len, idx);
if (ds->mi_found) {
ds->mi_found = 0;
continue;
}
/* show cursor */
handle_print_show_cursor (core, ds);
handle_print_show_bytes (core, ds);
handle_print_lines_right (core, ds);
handle_add_show_color (core, ds);
handle_build_op_str (core, ds);
handle_print_opstr (core, ds);
handle_print_fcn_name (core, ds);
handle_print_color_reset( core, ds);
handle_print_dwarf (core, ds);
ret = handle_print_middle (core, ds, ret );
handle_print_asmop_payload (core, ds);
if (core->assembler->syntax != R_ASM_SYNTAX_INTEL) {
RAsmOp ao; /* disassemble for the vm .. */
int os = core->assembler->syntax;
r_asm_set_syntax (core->assembler, R_ASM_SYNTAX_INTEL);
r_asm_disassemble (core->assembler, &ao, buf+idx, len-bb_size_consumed);
r_asm_set_syntax (core->assembler, os);
}
handle_print_core_vmode (core, ds);
handle_print_cc_update (core, ds);
handle_print_op_push_info (core, ds);
/*if (ds->analop.refptr) {
handle_print_refptr (core, ds);
} else {
handle_print_ptr (core, ds, len, idx);
}*/
handle_print_comments_right (core, ds);
if ( !(ds->show_comments &&
ds->show_comment_right &&
ds->show_comment_right &&
ds->comment))
r_cons_newline ();
if (ds->line) {
free (ds->line);
free (ds->refline);
free (ds->refline2);
ds->line = ds->refline = ds->refline2 = NULL;
}
bb_size_consumed += ds->oplen;
ds->index += ds->oplen;
idx += ds->oplen;
ds->at += ds->oplen;
ds->addr += ds->oplen;
ds->lines++;
free (ds->opstr);
ds->opstr = NULL;
} while (bb_size_consumed < len);
i++;
}
free (buf);
r_cons_break_end ();
if (ds->oldbits) {
r_config_set_i (core->config, "asm.bits", ds->oldbits);
ds->oldbits = 0;
}
r_anal_op_fini (&ds->analop);
handle_deinit_ds (core, ds);
r_list_free (bb_list);
return idx; //-ds->lastfail;
}

View File

@ -474,6 +474,7 @@ typedef enum {
R_ANAL_BB_TYPE_RET = 0x0020, /* return bb */
R_ANAL_BB_TYPE_JMP = 0x0040, /* jmp bb */
R_ANAL_BB_TYPE_COND = 0x0100, /* conditional bb */
R_ANAL_BB_TYPE_CJMP = R_ANAL_BB_TYPE_COND | R_ANAL_BB_TYPE_JMP,
R_ANAL_BB_TYPE_CALL = 0x0200,
R_ANAL_BB_TYPE_CMP = 0x0400,
R_ANAL_BB_TYPE_LD = 0x0800,
@ -583,7 +584,7 @@ typedef struct r_anal_op_t {
char *mnemonic; /* mnemonic */
ut64 addr; /* address */
ut64 type; /* type of opcode */
ut64 type2;
ut64 type2;
int stackop; /* operation on stack? */
int cond; /* condition type */
int size; /* size in bytes of opcode */
@ -997,7 +998,8 @@ R_API RAnalRefline *r_anal_reflines_get(RAnal *anal,
ut64 addr, const ut8 *buf, ut64 len, int nlines, int linesout, int linescall);
R_API int r_anal_reflines_middle(RAnal *anal, RAnalRefline *list, ut64 addr, int len);
R_API char* r_anal_reflines_str(void *core, ut64 addr, int opts);
R_API struct r_anal_refline_t *r_anal_reflines_fcn_get( struct r_anal_t *anal, RAnalFunction *fcn,
int nlines, int linesout, int linescall);
/* TODO move to r_core */
R_API void r_anal_var_list_show(RAnal *anal, RAnalFunction *fcn, ut64 addr);
R_API void r_anal_var_list(RAnal *anal, RAnalFunction *fcn, ut64 addr, int delta);

View File

@ -18,7 +18,7 @@ typedef struct r_anal_ex_op_to_str_t {
enum {
R_ANAL_EX_ILL_OP =-1, /* illegal instruction // trap */
R_ANAL_EX_NULL_OP = 0,
R_ANAL_EX_NOP = 1, /* does nothing */
R_ANAL_EX_NOP = 1, /* does nothing */
R_ANAL_EX_STORE_OP = 1 << 20, // Load or Store memory operation
R_ANAL_EX_LOAD_OP = 1 << 21, // Load or Store memory operation
R_ANAL_EX_REG_OP = 1 << 22, // register operation
@ -294,7 +294,7 @@ R_API ut64 r_anal_ex_map_anal_ex_to_anal_op_type(ut64 ranal2_op_type);
R_API void r_anal_ex_op_to_bb(RAnal *anal, RAnalState *state, RAnalBlock *bb, RAnalOp *op);
R_API int r_anal_ex_is_op_type_eop(ut64 x);
R_API ut32 r_anal_ex_map_anal_ex_to_anal_bb_type (ut64 ranal2_op_type);
R_API ut64 r_anal_ex_map_anal_ex_to_anal_bb_type (ut64 ranal2_op_type);
/* by default performs recursive descent, but is anal->analysis_algorithm
* is present, then that will be the algorithm used for analyzing the code

View File

@ -278,6 +278,7 @@ R_API RList *r_core_asm_back_disassemble_byte (RCore *core, ut64 addr, int len,
R_API int r_core_print_disasm(RPrint *p, RCore *core, ut64 addr, ut8 *buf, int len, int lines, int invbreak, int nbytes);
R_API int r_core_print_disasm_json(RCore *core, ut64 addr, ut8 *buf, int len);
R_API int r_core_print_disasm_instructions (RCore *core, int len, int l);
R_API int r_core_print_fcn_disasm(RPrint *p, RCore *core, ut64 addr, int l, int invbreak, int cbytes);
R_API void r_core_bin_bind(RCore *core);
R_API void r_core_bin_set_by_fd (RCore *core, ut64 bin_fd);