static int analyze(RAnal *anal, RAnalOp *op, ut64 offset, ut8* buf, int len) { char *bytes, *optype = NULL, *stackop = NULL; int ret; ret = r_anal_op (anal, op, offset, buf, len); if (ret) { stackop = stackop2str (op->stackop); optype = optype2str (op->type); bytes = r_hex_bin2strdup (buf, ret); printf ("bytes: %s\n", bytes); printf ("type: %s\n", optype); if (op->jump != -1LL) printf ("jump: 0x%08"PFMT64x"\n", op->jump); if (op->fail != -1LL) printf ("fail: 0x%08"PFMT64x"\n", op->fail); //if (op->ref != -1LL) // printf ("ref: 0x%08"PFMT64x"\n", op->ref); if (op->val != -1LL) printf ("value: 0x%08"PFMT64x"\n", op->val); printf ("stackop: %s\n", stackop); printf ("esil: %s\n", r_strbuf_get (&op->esil)); printf ("stackptr: %"PFMT64d"\n", op->stackptr); printf ("decode str: %s\n", r_anal_op_to_string (anal, op)); printf ("--\n"); free (optype); free (stackop); free (bytes); } return ret; }
static RList *r_core_asm_back_disassemble (RCore *core, ut64 addr, int len, ut64 max_hit_count, ut8 disassmble_each_addr, ut32 extra_padding) { RList *hits;; RAsmOp op; ut8 *buf = NULL; ut8 max_invalid_b4_exit = 4, last_num_invalid = 0; int current_instr_len = 0; ut64 current_instr_addr = addr, current_buf_pos = 0, next_buf_pos = len; RCoreAsmHit dummy_value; ut32 hit_count = 0; if (disassmble_each_addr){ return r_core_asm_back_disassemble_all(core, addr, len, max_hit_count, extra_padding+1); } hits = r_core_asm_hit_list_new (); buf = malloc (len + extra_padding); if (!hits || !buf ){ if (hits) { r_list_purge (hits); free (hits); } free (buf); return NULL; } if (r_io_read_at (core->io, (addr + extra_padding)-len, buf, len+extra_padding) != len+extra_padding) { r_list_purge (hits); free (hits); free (buf); return NULL; } // // XXX - This is a heavy handed approach without a // an appropriate btree or hash table for storing // hits, because are using: // 1) Sorted RList with many inserts and searches // 2) Pruning hits to find the most optimal disassembly // greedy approach // 1) Consume previous bytes // 1a) Instruction is invalid (incr current_instr_addr) // 1b) Disasm is perfect // 1c) Disasm is underlap (disasm(current_instr_addr, next_instr_addr - current_instr_addr) short some bytes) // 1d) Disasm is overlap (disasm(current_instr_addr, next_instr_addr - current_instr_addr) over some bytes) memset (&dummy_value, 0, sizeof (RCoreAsmHit)); // disassemble instructions previous to current address, extra_padding can move the location of addr // so we need to account for that with current_buf_pos current_buf_pos = len - extra_padding - 1; next_buf_pos = len + extra_padding - 1; current_instr_addr = addr-1; do { if (r_cons_singleton ()->breaked) break; // reset assembler r_asm_set_pc (core->assembler, current_instr_addr); current_instr_len = next_buf_pos - current_buf_pos; current_instr_len = r_asm_disassemble (core->assembler, &op, buf+current_buf_pos, current_instr_len); IFDBG { ut32 byte_cnt = current_instr_len ? current_instr_len : 1; eprintf("current_instr_addr: 0x%"PFMT64x", current_buf_pos: 0x%"PFMT64x", current_instr_len: %d \n", current_instr_addr, current_buf_pos, current_instr_len); ut8 *hex_str = (ut8*)r_hex_bin2strdup(buf+current_buf_pos, byte_cnt); eprintf("==== current_instr_bytes: %s ",hex_str); if (current_instr_len > 0) eprintf("op.buf_asm: %s\n", op.buf_asm); else eprintf("op.buf_asm: <invalid>\n"); free(hex_str); } // disassembly invalid if (current_instr_len == 0 || strstr (op.buf_asm, "invalid")) { if (current_instr_len == 0) current_instr_len = 1; add_hit_to_sorted_hits(hits, current_instr_addr, current_instr_len, /* is_valid */ false); hit_count ++; last_num_invalid ++; // disassembly perfect } else if (current_buf_pos + current_instr_len == next_buf_pos) { // i think this may be the only case where an invalid instruction will be // added because handle_forward_disassemble and handle_disassembly_overlap // are only called in cases where a valid instruction has been found. // and they are lazy, since they purge the hit list ut32 purge_results = 0; ut8 is_valid = true; IFDBG eprintf(" handling underlap case: current_instr_addr: 0x%"PFMT64x".\n", current_instr_addr); purge_results = prune_hits_in_addr_range(hits, current_instr_addr, current_instr_len, /* is_valid */ true); if (purge_results) { handle_forward_disassemble(core, hits, buf, len, current_buf_pos+current_instr_len, current_instr_addr+current_instr_len, addr); hit_count = r_list_length(hits); } add_hit_to_sorted_hits(hits, current_instr_addr, current_instr_len, is_valid); //handle_forward_disassemble(core, hits, buf, len, current_buf_pos+current_instr_len, current_instr_addr+current_instr_len, addr/*end_addr*/); hit_count ++; next_buf_pos = current_buf_pos; last_num_invalid = 0; // disassembly underlap } else if (current_buf_pos + current_instr_len < next_buf_pos) { ut32 purge_results = 0; ut8 is_valid = true; purge_results = prune_hits_in_addr_range(hits, current_instr_addr, current_instr_len, /* is_valid */ true); add_hit_to_sorted_hits(hits, current_instr_addr, current_instr_len, is_valid); if (hit_count < purge_results ) hit_count = 0; // WTF?? else hit_count -= purge_results; next_buf_pos = current_buf_pos; handle_forward_disassemble(core, hits, buf, len - extra_padding, current_buf_pos+current_instr_len, current_instr_addr+current_instr_len, addr); hit_count = r_list_length(hits); last_num_invalid = 0; // disassembly overlap } else if (current_buf_pos + current_instr_len > next_buf_pos) { //ut64 value = handle_disassembly_overlap(core, hits, buf, len, current_buf_pos, current_instr_addr); next_buf_pos = current_buf_pos; hit_count = r_list_length (hits); last_num_invalid = 0; } // walk backwards by one instruction IFDBG eprintf(" current_instr_addr: 0x%"PFMT64x" current_instr_len: %d next_instr_addr: 0x%04"PFMT64x"\n", current_instr_addr, current_instr_len, next_buf_pos); IFDBG eprintf(" hit count: %d \n", hit_count ); current_instr_addr -= 1; current_buf_pos -= 1; if ( hit_count >= max_hit_count && (last_num_invalid >= max_invalid_b4_exit || last_num_invalid == 0)) break; } while (((int) current_buf_pos >= 0) && (int)(len - current_buf_pos) >= 0); r_asm_set_pc (core->assembler, addr); free (buf); return hits; }
static int r_print_format_uleb(const RPrint* p, int endian, int mode, const char* setval, ut64 seeki, ut8* buf, int i, int size) { int elem = -1; int s = 0, sum = 0; ut64 value = 0, offset = 0; if (size >= ARRAYINDEX_COEF) { elem = size / ARRAYINDEX_COEF - 1; size %= ARRAYINDEX_COEF; } // offset = seeki+((elem>=0)?16*elem:0); if (MUSTSET) { ut8 *tmp; char *nbr; do { offset += s; r_uleb128_decode (buf+offset, &s, &value); } while (elem--); tmp = (ut8*) r_uleb128_encode (r_num_math (NULL, setval), &s); nbr = r_hex_bin2strdup (tmp, s); p->cb_printf ("\"wx %s\" @ 0x%08"PFMT64x"\n", nbr, seeki+offset); free (tmp); free (nbr); // sum = size of the converted number } else if (MUSTSEE) { if (!SEEVALUE) p->cb_printf ("0x%08"PFMT64x" = ", seeki); if (size==-1) { r_uleb128_decode (buf+i, &s, &value); p->cb_printf ("%"PFMT64d, value); sum = s; } else { if (!SEEVALUE) p->cb_printf ("[ "); while (size--) { if (elem == -1 || elem == 0) { r_uleb128_decode (buf+i, &s, &value); sum += s; p->cb_printf ("%"PFMT64d, value); if (elem == 0) elem = -2; } if (size != 0 && elem == -1) p->cb_printf (", "); if (elem > -1) elem--; i+=s; } if (!SEEVALUE) p->cb_printf (" ]"); } } else if (MUSTSEEJSON) { if (size==-1) { r_uleb128_decode (buf+i, &s, &value); p->cb_printf ("\"%"PFMT64d"\"", value); sum = s; } else { p->cb_printf ("[ "); while (size--) { if (elem == -1 || elem == 0) { r_uleb128_decode (buf+i, &s, &value); sum += s; p->cb_printf ("\"%"PFMT64d"\"", value); if (elem == 0) elem = -2; } if (size != 0 && elem == -1) p->cb_printf (", "); if (elem > -1) elem--; i+=s; } p->cb_printf (" ]"); } p->cb_printf ("}"); } return sum; }