[Home]Binutils/Libopcodes

ec2-54-210-158-163.compute-1.amazonaws.com | ToothyWiki | Binutils | RecentChanges | Login | Webcomic

The libopcodes.so shared library provides functionality to disassemble executable binaries into machine and human readable formats.

Select disassembler for target architecture


The binary disassembler class is constructed using a bfd (Binary File Descriptor) class.  This is used to select the approprtiate instruction set disassembler.  If the requested disassembler is unavailable, this function will return NULL.

   disassembler_ftype disassemble = disassembler( bfd * bfdFile );

Customise output streams


Various callbacks to handle the disassembled code can be specified using the disassembler_info class.  The primary output is via the printf_ftype callback.  This has a similar signature to fprintf (which can be used directly) as below:

   struct disassembler_info info;
  init_disassemble_info ( &info, stdout, (fprintf_ftype)fprintf );

The most common callback override replaces the address display logic.  Objdump uses this to resolve hexadecimal addresses to human-readable symbols.

   void custom_print_address( bfd_vma address, struct disassemble_info * info ) {}
  info.print_address_func = custom_print_address;

Disassemble


The disassembler class can be used to disassemble a single instruction at the specified program location.  It returns the number of bytes to increment the program location to the next instruction (or negative if the program location is outside the supplied buffer).  A section of code than thus be disassembled in a while loop as follows:

   while ( pc < endPc )
  {
      int count = disassemble( pc, &info );
      if ( count < 0 ) break;
      pc += count;
  }

Static program analysis (or lack thereof)


For some architectures (but unfortunately not i386), the disassemble command will set various information about the command that has been disassembled in the disassembler_info structure.

   info.insn_info_valid - set to non-zero if information is available
  info.insn_type      - type of instruction (conditional branch/call/illegal)
  info.target          - address 1 [e.g. branch destination/data source]
  info.target2        - address 2 [e.g. destination address]

Example


The following code opens an executable file and disassembles the .text segment:

   #include "bfd.h"
  #include "dis-asm.h"

   void override_print_address(bfd_vma addr, struct disassemble_info *info)
  {
    printf( "0x%x", addr );
  }

   int main( int argc, char ** argv )
  {
    bfd                  * bfdFile;
    asection              * section;
    disassembler_ftype      disassemble;
    struct disassemble_info info;
    unsigned long count, pc;

     bfd_init();
    bfdFile = bfd_openr( "/bin/ls", "elf64-x86-64" );
    if ( bfdFile == NULL )
      {
        printf( "Error [%x]: %s\n", bfd_get_error(), bfd_errmsg(bfd_get_error()) );
        return -1;
      }
    if ( !bfd_check_format( bfdFile, bfd_object ))
      {
        printf( "Error [%x]: %s\n", bfd_get_error(), bfd_errmsg(bfd_get_error()) );
        return -1;
      }
    /* Retrieve the .text code section */
    section = bfd_get_section_by_name( bfdFile, ".text" );
    if (section == NULL )
    {
      printf( "Error accessing .text section\n" );
      return -1;
    }

     /* Construct disassembler_ftype class */
    disassemble = disassembler ( bfdFile );
    if ( disassemble == NULL )
    {
      printf( "Error creating disassembler\n" );
      return -1;
    }

     /* Construct and configure the disassembler_info class using stdout */ 
    init_disassemble_info ( &info, stdout, (fprintf_ftype)fprintf );
    info.print_address_func = override_print_address;
    info.arch          = bfd_get_arch( bfdFile );
    info.mach          = bfd_get_mach( bfdFile );
    info.buffer_vma    = section->vma;
    info.buffer_length = section->size;
    info.section      = section;
    bfd_malloc_and_get_section( bfdFile,
                                section,
                                &info.buffer );
    disassemble_init_for_target ( &info );

     /* Start diassembling at the file start_address */
    pc = bfd_get_start_address( bfdFile );
    do
    {
      printf( "0x%x  ", pc );
      count = disassemble( pc, &info );
      pc += count;
      printf( "\n" );
    } while ( count > 0 && pc < bfd_get_start_address( bfdFile ) + section->size );
    return 0;
  }

ec2-54-210-158-163.compute-1.amazonaws.com | ToothyWiki | Binutils | RecentChanges | Login | Webcomic
Edit this page | View other revisions | Recently used referrers
Last edited December 25, 2009 10:25 pm (viewing revision 2, which is the newest) (diff)
Search: