static void configure_opdis( struct opdis_options * opts ) { opdis_t o = opts->opdis; const bfd_arch_info_type * arch_info = bfd_scan_arch( opts->arch_str ); opdis_set_arch( o, arch_info->arch, opts->arch, NULL ); if ( opts->disasm_opts && opts->disasm_opts[0] ) { opdis_set_disassembler_options( o, opts->disasm_opts ); } opdis_set_x86_syntax( o, opts->syntax ); opdis_set_display( o, opdis_display_cb, opts->insn_tree ); opdis_set_resolver( o, opdis_resolver_cb, opts->map ); }
static opdis_insn_t *get_opdis_insn(unsigned char *ins, unsigned char *end) { // unsigned char opdis_buf[OPDIS_BUF_LEN]; uintptr_t len = (uintptr_t) end - (uintptr_t) ins; opdis_buffer_t buf = { .len = (len > MAX_INSN_LENGTH) ? MAX_INSN_LENGTH : len, .data = ins, .vma = (bfd_vma) ins }; assert(buf.len <= MAX_INSN_LENGTH); if (!o) { o = opdis_init(); /* Unbelievably, opdis_insn_t won't tell us the encoded length of the instruction. * So we have to snarf it via a custom decoder. */ opdis_set_arch(o, bfd_arch_i386, bfd_mach_x86_64, NULL); opdis_set_display(o, display_cb, NULL); opdis_set_decoder(o, decode_cb, &cur_insn_len); assert(o->buf); assert(o->buf->string); } if (!cur_insn) { cur_insn = opdis_insn_alloc_fixed(OPDIS_ASCII_SZ, OPDIS_MNEMONIC_SZ, OPDIS_MAX_OPERANDS, OPDIS_OP_ASCII_SZ); } opdis_insn_clear(cur_insn); /* Don't let opdis see ud2 -- seems not to like it? */ if (is_ud2(ins)) { cur_insn_len = 2; return NULL; } /* Now do the one-instruction decode. */ unsigned int ret = opdis_disasm_insn(o, &buf, (opdis_vma_t) ins, cur_insn); if (!ret) return NULL; if (cur_insn->status == opdis_decode_invalid) return NULL; if (cur_insn_len == 0) { /* ud2 shows up with a "length" of 0 in the callback. * but its size == 2. FIXME: why wasn't "size" good enough * earlier, but is now? */ cur_insn_len = cur_insn->size; } return cur_insn; }
void disassemble_mem(void * src, size_t length) { opdis_t o; opdis_buf_t buf = opdis_buf_alloc(length, (opdis_vma_t)src); opdis_buf_fill(buf, 0, src, length); o = opdis_init(); //opdis_set_arch(o, bfd_arch_k1om, bfd_mach_k1om, NULL); //const bfd_arch_info_type *arch_info = bfd_scan_arch("i386:x86-64"); opdis_set_arch(o, bfd_arch_i386, bfd_mach_x86_64, print_insn_i386_att); opdis_disasm_linear(o, buf, (opdis_vma_t)src, length); opdis_buf_free(buf); opdis_term(o); }