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

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial