toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_disasm.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     5 #include "libdis.h"
     6 #include "ia32_insn.h"
     7 #include "ia32_invariant.h"
     8 #include "x86_operand_list.h"
    11 #ifdef _MSC_VER
    12         #define snprintf        _snprintf
    13         #define inline          __inline
    14 #endif
    16 unsigned int x86_disasm( unsigned char *buf, unsigned int buf_len,
    17                 uint32_t buf_rva, unsigned int offset,
    18                 x86_insn_t *insn ){
    19         int len, size;
    20 	unsigned char bytes[MAX_INSTRUCTION_SIZE];
    22         if ( ! buf || ! insn || ! buf_len ) {
    23                 /* caller screwed up somehow */
    24                 return 0;
    25         }
    28 	/* ensure we are all NULLed up */
    29 	memset( insn, 0, sizeof(x86_insn_t) );
    30         insn->addr = buf_rva + offset;
    31         insn->offset = offset;
    32 	/* default to invalid insn */
    33 	insn->type = insn_invalid;
    34 	insn->group = insn_none;
    36         if ( offset >= buf_len ) {
    37                 /* another caller screwup ;) */
    38                 x86_report_error(report_disasm_bounds, (void*)(long)buf_rva+offset);
    39                 return 0;
    40         }
    42         len = buf_len - offset;
    44 	/* copy enough bytes for disassembly into buffer : this
    45 	 * helps prevent buffer overruns at the end of a file */
    46 	memset( bytes, 0, MAX_INSTRUCTION_SIZE );
    47 	memcpy( bytes, &buf[offset], (len < MAX_INSTRUCTION_SIZE) ? len : 
    48 		MAX_INSTRUCTION_SIZE );
    50         /* actually do the disassembly */
    51 	/* TODO: allow switching when more disassemblers are added */
    52         size = ia32_disasm_addr( bytes, len, insn);
    54         /* check and see if we had an invalid instruction */
    55         if (! size ) {
    56                 x86_report_error(report_invalid_insn, (void*)(long)buf_rva+offset );
    57                 return 0;
    58         }
    60         /* check if we overran the end of the buffer */
    61         if ( size > len ) {
    62                 x86_report_error( report_insn_bounds, (void*)(long)buf_rva + offset );
    63 		MAKE_INVALID( insn, bytes );
    64 		return 0;
    65 	}
    67         /* fill bytes field of insn */
    68         memcpy( insn->bytes, bytes, size );
    70         return size;
    71 }
    73 unsigned int x86_disasm_range( unsigned char *buf, uint32_t buf_rva,
    74                       unsigned int offset, unsigned int len,
    75                       DISASM_CALLBACK func, void *arg ) {
    76         x86_insn_t insn;
    77         unsigned int buf_len, size, count = 0, bytes = 0;
    79         /* buf_len is implied by the arguments */
    80         buf_len = len + offset;
    82         while ( bytes < len ) {
    83                 size = x86_disasm( buf, buf_len, buf_rva, offset + bytes,
    84                                    &insn );
    85                 if ( size ) {
    86                         /* invoke callback if it exists */
    87                         if ( func ) {
    88                                 (*func)( &insn, arg );
    89                         }
    90                         bytes += size;
    91                         count ++;
    92                 } else {
    93                         /* error */
    94                         bytes++;        /* try next byte */
    95                 }
    97 		x86_oplist_free( &insn );
    98         }
   100         return( count );
   101 }
   103 static inline int follow_insn_dest( x86_insn_t *insn ) {
   104         if ( insn->type == insn_jmp || insn->type == insn_jcc ||
   105              insn->type == insn_call || insn->type == insn_callcc ) {
   106                 return(1);
   107         }
   108         return(0);
   109 }
   111 static inline int insn_doesnt_return( x86_insn_t *insn ) {
   112         return( (insn->type == insn_jmp || insn->type == insn_return) ? 1: 0 );
   113 }
   115 static int32_t internal_resolver( x86_op_t *op, x86_insn_t *insn ){
   116         int32_t next_addr = -1;
   117         if ( x86_optype_is_address(op->type) ) {
   118                 next_addr = op->data.sdword;
   119         } else if ( op->type == op_relative_near ) {
   120 		next_addr = insn->addr + insn->size + op->data.relative_near;
   121         } else if ( op->type == op_relative_far ) {
   122 		next_addr = insn->addr + insn->size + op->data.relative_far;
   123         }
   124         return( next_addr );
   125 }
   127 unsigned int x86_disasm_forward( unsigned char *buf, unsigned int buf_len,
   128                         uint32_t buf_rva, unsigned int offset,
   129                         DISASM_CALLBACK func, void *arg,
   130                         DISASM_RESOLVER resolver, void *r_arg ){
   131         x86_insn_t insn;
   132         x86_op_t *op;
   133         int32_t next_addr;
   134         uint32_t next_offset;
   135         unsigned int size, count = 0, bytes = 0, cont = 1;
   137         while ( cont && bytes < buf_len ) {
   138                 size = x86_disasm( buf, buf_len, buf_rva, offset + bytes,
   139                            &insn );
   141                 if ( size ) {
   142                         /* invoke callback if it exists */
   143                         if ( func ) {
   144                                 (*func)( &insn, arg );
   145                         }
   146                         bytes += size;
   147                         count ++;
   148                 } else {
   149                         /* error */
   150                         bytes++;        /* try next byte */
   151                 }
   153                 if ( follow_insn_dest(&insn) ) {
   154                         op = x86_get_dest_operand( &insn );
   155                         next_addr = -1;
   157                         /* if caller supplied a resolver, use it to determine
   158                          * the address to disassemble */
   159                         if ( resolver ) {
   160                                 next_addr = resolver(op, &insn, r_arg);
   161                         } else {
   162                                 next_addr = internal_resolver(op, &insn);
   163                         }
   165                         if (next_addr != -1 ) {
   166                                 next_offset = next_addr - buf_rva;
   167                                 /* if offset is in this buffer... */
   168                                 if ( next_addr >= buf_rva &&
   169                                      next_offset < buf_len ) {
   170                                         /* go ahead and disassemble */
   171                                         count += x86_disasm_forward( buf,
   172                                                             buf_len,
   173                                                             buf_rva,
   174                                                             next_offset,
   175                                                             func, arg,
   176                                                             resolver, r_arg );
   177                                 } else  {
   178                                         /* report unresolved address */
   179                                         x86_report_error( report_disasm_bounds,
   180                                                      (void*)(long)next_addr );
   181                                 }
   182                         }
   183                 } /* end follow_insn */
   185                 if ( insn_doesnt_return(&insn) ) {
   186                         /* stop disassembling */
   187                         cont = 0;
   188                 }
   190 		x86_oplist_free( &insn );
   191         }
   192         return( count );
   193 }
   195 /* invariant instruction representation */
   196 size_t x86_invariant_disasm( unsigned char *buf, int buf_len, 
   197 		x86_invariant_t *inv ){
   198 	if (! buf || ! buf_len || ! inv  ) {
   199 		return(0);
   200 	}
   202 	return ia32_disasm_invariant(buf, buf_len, inv);
   203 }
   204 size_t x86_size_disasm( unsigned char *buf, unsigned int buf_len ) {
   205 	if (! buf || ! buf_len  ) {
   206 		return(0);
   207 	}
   209 	return ia32_disasm_size(buf, buf_len);
   210 }

mercurial