fix disassembling 'backwards'

(e.g. pd -5) producing wrong output

fixes #5105
This commit is contained in:
Jeffrey Crowell 2016-06-11 02:12:41 +00:00 committed by pancake
parent 20bd6003ae
commit 7c3fb53a5e
3 changed files with 42 additions and 2 deletions

View File

@ -1017,11 +1017,19 @@ static int pdi(RCore *core, int nb_opcodes, int nb_bytes, int fmt) {
}
} else if (!nb_bytes) {
if (nb_opcodes < 0) {
ut64 start;
/* Backward disassembly of `ilen` opcodes
* - We compute the new starting offset
* - Read at the new offset */
nb_opcodes = -nb_opcodes;
r_core_asm_bwdis_len (core, &nb_bytes, &core->offset, nb_opcodes);
if (r_core_prevop_addr (core, core->offset, nb_opcodes, &start)) {
// We have some anal_info.
nb_bytes = core->offset - start;
} else {
// anal ignorance.
r_core_asm_bwdis_len (core, &nb_bytes, &core->offset,
nb_opcodes);
}
r_core_read_at (core, core->offset, core->block, nb_bytes);
} else {
// workaround for the `for` loop below
@ -2755,6 +2763,7 @@ static int cmd_print(void *data, const char *input) {
if (!processed_cmd) {
ut64 addr = core->offset;
ut8 *block = NULL;
ut64 start;
if (bw_disassemble) {
block = malloc (core->blocksize);
@ -2769,7 +2778,13 @@ static int cmd_print(void *data, const char *input) {
} else { //pd
const int bs = core->blocksize;
int instr_len;
r_core_asm_bwdis_len (core, &instr_len, &addr, l);
if (r_core_prevop_addr (core, core->offset, l, &start)) {
// We have some anal_info.
instr_len = core->offset - start;
} else {
// anal ignorance.
r_core_asm_bwdis_len (core, &instr_len, &addr, l);
}
ut64 prevaddr = core->offset;
r_core_seek(core, prevaddr - instr_len, true);
block = realloc (block, R_MAX(instr_len, bs));

View File

@ -631,6 +631,30 @@ static ut64 prevop_addr (RCore *core, ut64 addr) {
return target - 4;
}
// Returns true if we can use analysis to find the previous operation address,
// sets prev_addr to the value of the instruction numinstrs back.
// If we can't use the anal, then set prev_addr to UT64_MAX and return false;
R_API bool r_core_prevop_addr (RCore* core, ut64 start_addr, int numinstrs,
ut64* prev_addr) {
RAnalBlock* bb;
int i;
// Check that we're in a bb, otherwise this prevop stuff won't work.
bb = r_anal_bb_from_offset (core->anal, start_addr);
if (bb) {
if (r_anal_bb_opaddr_at (bb, start_addr) != UT64_MAX) {
// Do some anal looping.
for (i = 0; i < numinstrs; ++i) {
*prev_addr = prevop_addr (core, start_addr);
start_addr = *prev_addr;
}
return true;
}
}
// Dang! not in a bb, return false and fallback to other methods.
*prev_addr = UT64_MAX;
return false;
}
static void reset_print_cur(RPrint *p) {
p->cur = 0;
p->ocur = -1;

View File

@ -227,6 +227,7 @@ R_API int r_core_read_at(RCore *core, ut64 addr, ut8 *buf, int size);
R_API int r_core_is_valid_offset (RCore *core, ut64 offset);
R_API int r_core_shift_block(RCore *core, ut64 addr, ut64 b_size, st64 dist);
R_API void r_core_visual_prompt_input (RCore *core);
R_API bool r_core_prevop_addr (RCore* core, ut64 start_addr, int numinstrs, ut64* prev_addr);
R_API bool r_core_visual_hudstuff(RCore *core);
R_API int r_core_visual_classes(RCore *core);
R_API int r_core_visual_types(RCore *core);