static int disassemble_file( const char * name, opdis_off_t offset ) { int rv; FILE * f; opdis_t o; opdis_buf_t buf; opdis_insn_tree_t tree; f = fopen( name, "r" ); if (! f ) { printf( "Unable to open file %s: %s\n", name, strerror(errno) ); return -1; } buf = opdis_buf_read( f, 0, 0 ); fclose( f ); o = opdis_init(); tree = opdis_insn_tree_init( 1 ); opdis_set_display( o, store_insn, tree ); rv = opdis_disasm_cflow( o, buf, (opdis_vma_t) offset ); opdis_insn_tree_foreach( tree, print_insn, (void *) name ); opdis_insn_tree_free( tree ); opdis_term( o ); return (rv > 0) ? 0 : -2; }
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; }