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 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); }
static void set_defaults( struct opdis_options * opts ) { opts->jobs = job_list_alloc(); opts->map = mem_map_alloc(); opts->targets = tgt_list_alloc(); opts->opdis = opdis_init(); opts->insn_tree = opdis_insn_tree_init( 1 ); opts->output_file = stdout; // TODO get first available arch // TODO: use 64-bit detection? opts->arch_str = "i386"; opts->arch = bfd_mach_i386_i386; opts->syntax_str = "att"; opts->syntax = opdis_x86_syntax_att; opts->fmt_str = "dump"; opts->fmt = asmfmt_dump; opts->disasm_opts = ""; }