Getting started with Opdis

This document provides some brief examples of how to use libopdis and the opdis command line utility.


Using opdis to disassemble an object file symbol

Use the -N option to disassemble a symbol in an object file using the control-flow algorithm.

opdis -N main a.out

Note: Only symbols recognized by libbfd can be disassembled. The --list-bfd-symbols option can be used to list all available symbols in a BFD target:

opdis --list-bfd-symbols -B a.out

Using opdis to disassemble a hex string

Enclose the hexadecimal bytes in quotes as an argument to the -b option.

opdis -b '90 90 90 90'
opdis -b 'CC'
opdis -b "`od -j 0x1C20 -t x1 -A x -N 16 -w16 a.out | head -1 | cut -f 1 -d ' ' --complement `"

Using opdis to disassemble an ELF binary

1. Use readelf to get the offset, size, and vma of the .text section.

readelf -S a.out | grep -A 1 text
  [14] .text             PROGBITS         0000000000401c20  00001c20
       0000000000004de8  0000000000000000  AX       0     0     16

This section can be mapped to the load address with the option -m :0x1C20@0x401C20+0x4DE8 (:offset+size). The section can be disassembled using the option -l @0x401C20+0x4DE8 (+length).

2. Use readelf to get the address of the main symbol.

readelf -s a.out | grep main
    17: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main\@GLIBC_2.2.5 (3)
   124: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main\@\@GLIBC_
   208: 00000000004026c0  1417 FUNC    GLOBAL DEFAULT   14 main

The symbol can be disassembled using -c @0x4026C0 ().

3. Run opdis to generate the disassembly.

Linear disassembly of text section:

opdis -m :0x1C20@0x401C20+0x4DE8 -l @0x401C20+0x4DE8

Control-flow disassembly of entry point:

opdis -m :0x1C20@0x401C20+0x4DE8 -c @0x4026C0

Using libopdis to disassemble a memory location

First, an opdis_buf_t must be allocated and filled with the contents of the memory location. The VMA of the memory location can be used as the VMA of the opdis_buf_t. Next, an opdis_t is created using the default values, and opdis_disasm_linear is used to disassemble the bytes.

#include <opdis/opdis.h>

void disassemble_mem( void * src, opdis_offset_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_disasm_linear( o, buf, (opdis_vma_t) src, length );
        opdis_term( o );
}

Note that the opdis_t is never configured, so the default values are used. This means that the architecture is i386, the syntax is Intel, and the instructions are written to STDOUT.

Using libopdis to disassemble a file

This is the same as disassembling a memory location except that the opdis_buf_t is read from a file.

#include <opdis/opdis.h>

void disassemble_file( FILE * f, opdis_vma_t vma, opdis_offset_t offset ) {
        opdis_t o;
        opdis_buf_t buf = opdis_buf_read( f, 0, 0 );

        o = opdis_init();
        opdis_disasm_linear( o, buf, offset, length );
        opdis_term( o );
}

Using libopdis and BFD to disassemble an object file section

Initializing an opdis_t from a valid bfd pointer will configure the target architecture automatically. A valid BFD section can then be disassembled using opdis_disasm_bfd_section.

#include <opdis/opdis.h>

int disassemble_bfd_section( const char * filename, const char * sec_name ) {
        opdis_t o;
        struct bfd_section * section;
        bfd *abfd = bfd_openr( filename, NULL );
        if (! abfd  ) {
                fprintf( stderr, "Unable to create BFD for %s\n", filename );
                return 0;
        }

        if ( bfd_get_flavour( abfd ) == bfd_target_unknown_flavour ) {
                fprintf( stderr, "Unknown BFD flavor: cannot continue\n" );
                return 0;
        }

        section = bfd_get_section_by_name( abfd, sec_name );
        if (! section ) {
                fprintf( stderr, "Cannot find BFD section %s\n", sec_name );
                return 0;
        }

        o = opdis_init_from_bfd( abfd );
        opdis_disasm_bfd_section( o, section )
        opdis_term( o );

        return 1;
}

Note: opdis_init_from_bfd only configures the architecture of the opdis_t. The other options will be set to their defaults, e.g. the instructions will be printed to STDOUT.

Using libopdis and BFD to disassemble an object file entry point

As with disassembling a BFD section, a valid bfd object can be used to configure an opdis_t. The opdis_disasm_bfd_entry function can be used to disassemble the entry point of the object file, if one exists.

#include <opdis/opdis.h>

int disassemble_bfd_entry( const char * filename ) {
        opdis_t o;
        bfd *abfd = bfd_openr( filename, NULL );
        if (! abfd  ) {
                fprintf( stderr, "Unable to create BFD for %s\n", filename );
                return 0;
        }

        if ( bfd_get_flavour( abfd ) == bfd_target_unknown_flavour ) {
                fprintf( stderr, "Unknown BFD flavor: cannot continue\n" );
                return 0;
        }

        o = opdis_init_from_bfd( abfd );
        opdis_disasm_bfd_entry( o, abfd )
        opdis_term( o );

        return 1;
}

Generated on Wed Mar 10 14:30:46 2010 for Opdis Disassembly Library by  doxygen 1.6.1