x86_disasm.cpp 7.5 KB

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