/thirdparty/breakpad/third_party/libdisasm/ia32_invariant.c

http://github.com/tomahawk-player/tomahawk · C · 313 lines · 257 code · 37 blank · 19 comment · 47 complexity · d899b301b8e23a1efd73b83d43eaada7 MD5 · raw file

  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include "ia32_invariant.h"
  4. #include "ia32_insn.h"
  5. #include "ia32_settings.h"
  6. extern ia32_table_desc_t *ia32_tables;
  7. extern ia32_settings_t ia32_settings;
  8. extern size_t ia32_table_lookup( unsigned char *buf, size_t buf_len,
  9. unsigned int table, ia32_insn_t **raw_insn,
  10. unsigned int *prefixes );
  11. /* -------------------------------- ModR/M, SIB */
  12. /* Convenience flags */
  13. #define MODRM_EA 1 /* ModR/M is an effective addr */
  14. #define MODRM_reg 2 /* ModR/M is a register */
  15. /* ModR/M flags */
  16. #define MODRM_RM_SIB 0x04 /* R/M == 100 */
  17. #define MODRM_RM_NOREG 0x05 /* R/B == 101 */
  18. /* if (MODRM.MOD_NODISP && MODRM.RM_NOREG) then just disp32 */
  19. #define MODRM_MOD_NODISP 0x00 /* mod == 00 */
  20. #define MODRM_MOD_DISP8 0x01 /* mod == 01 */
  21. #define MODRM_MOD_DISP32 0x02 /* mod == 10 */
  22. #define MODRM_MOD_NOEA 0x03 /* mod == 11 */
  23. /* 16-bit modrm flags */
  24. #define MOD16_MOD_NODISP 0
  25. #define MOD16_MOD_DISP8 1
  26. #define MOD16_MOD_DISP16 2
  27. #define MOD16_MOD_REG 3
  28. #define MOD16_RM_BXSI 0
  29. #define MOD16_RM_BXDI 1
  30. #define MOD16_RM_BPSI 2
  31. #define MOD16_RM_BPDI 3
  32. #define MOD16_RM_SI 4
  33. #define MOD16_RM_DI 5
  34. #define MOD16_RM_BP 6
  35. #define MOD16_RM_BX 7
  36. /* SIB flags */
  37. #define SIB_INDEX_NONE 0x04
  38. #define SIB_BASE_EBP 0x05
  39. #define SIB_SCALE_NOBASE 0x00
  40. /* Convenience struct for modR/M bitfield */
  41. struct modRM_byte {
  42. unsigned int mod : 2;
  43. unsigned int reg : 3;
  44. unsigned int rm : 3;
  45. };
  46. /* Convenience struct for SIB bitfield */
  47. struct SIB_byte {
  48. unsigned int scale : 2;
  49. unsigned int index : 3;
  50. unsigned int base : 3;
  51. };
  52. #ifdef WIN32
  53. static void byte_decode(unsigned char b, struct modRM_byte *modrm) {
  54. #else
  55. static inline void byte_decode(unsigned char b, struct modRM_byte *modrm) {
  56. #endif
  57. /* generic bitfield-packing routine */
  58. modrm->mod = b >> 6; /* top 2 bits */
  59. modrm->reg = (b & 56) >> 3; /* middle 3 bits */
  60. modrm->rm = b & 7; /* bottom 3 bits */
  61. }
  62. static int ia32_invariant_modrm( unsigned char *in, unsigned char *out,
  63. unsigned int mode_16, x86_invariant_op_t *op) {
  64. struct modRM_byte modrm;
  65. struct SIB_byte sib;
  66. unsigned char *c, *cin;
  67. unsigned short *s;
  68. unsigned int *i;
  69. int size = 0; /* modrm byte is already counted */
  70. byte_decode(*in, &modrm); /* get bitfields */
  71. out[0] = in[0]; /* save modrm byte */
  72. cin = &in[1];
  73. c = &out[1];
  74. s = (unsigned short *)&out[1];
  75. i = (unsigned int *)&out[1];
  76. op->type = op_expression;
  77. op->flags |= op_pointer;
  78. if ( ! mode_16 && modrm.rm == MODRM_RM_SIB &&
  79. modrm.mod != MODRM_MOD_NOEA ) {
  80. size ++;
  81. byte_decode(*cin, (struct modRM_byte *)(void*)&sib);
  82. out[1] = in[1]; /* save sib byte */
  83. cin = &in[2];
  84. c = &out[2];
  85. s = (unsigned short *)&out[2];
  86. i = (unsigned int *)&out[2];
  87. if ( sib.base == SIB_BASE_EBP && ! modrm.mod ) {
  88. /* disp 32 is variant! */
  89. memset( i, X86_WILDCARD_BYTE, 4 );
  90. size += 4;
  91. }
  92. }
  93. if (! modrm.mod && modrm.rm == 101) {
  94. if ( mode_16 ) { /* straight RVA in disp */
  95. memset( s, X86_WILDCARD_BYTE, 2 );
  96. size += 2;
  97. } else {
  98. memset( i, X86_WILDCARD_BYTE, 2 );
  99. size += 4;
  100. }
  101. } else if (modrm.mod && modrm.mod < 3) {
  102. if (modrm.mod == MODRM_MOD_DISP8) { /* offset in disp */
  103. *c = *cin;
  104. size += 1;
  105. } else if ( mode_16 ) {
  106. *s = (* ((unsigned short *) cin));
  107. size += 2;
  108. } else {
  109. *i = (*((unsigned int *) cin));
  110. size += 4;
  111. }
  112. } else if ( modrm.mod == 3 ) {
  113. op->type = op_register;
  114. op->flags &= ~op_pointer;
  115. }
  116. return (size);
  117. }
  118. static int ia32_decode_invariant( unsigned char *buf, size_t buf_len,
  119. ia32_insn_t *t, unsigned char *out,
  120. unsigned int prefixes, x86_invariant_t *inv) {
  121. unsigned int addr_size, op_size, mode_16;
  122. unsigned int op_flags[3] = { t->dest_flag, t->src_flag, t->aux_flag };
  123. int x, type, bytes = 0, size = 0, modrm = 0;
  124. /* set addressing mode */
  125. if (ia32_settings.options & opt_16_bit) {
  126. op_size = ( prefixes & PREFIX_OP_SIZE ) ? 4 : 2;
  127. addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 4 : 2;
  128. mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 0 : 1;
  129. } else {
  130. op_size = ( prefixes & PREFIX_OP_SIZE ) ? 2 : 4;
  131. addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 2 : 4;
  132. mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 1 : 0;
  133. }
  134. for (x = 0; x < 3; x++) {
  135. inv->operands[x].access = (enum x86_op_access)
  136. OP_PERM(op_flags[x]);
  137. inv->operands[x].flags = (enum x86_op_flags)
  138. (OP_FLAGS(op_flags[x]) >> 12);
  139. switch (op_flags[x] & OPTYPE_MASK) {
  140. case OPTYPE_c:
  141. size = (op_size == 4) ? 2 : 1;
  142. break;
  143. case OPTYPE_a: case OPTYPE_v:
  144. size = (op_size == 4) ? 4 : 2;
  145. break;
  146. case OPTYPE_p:
  147. size = (op_size == 4) ? 6 : 4;
  148. break;
  149. case OPTYPE_b:
  150. size = 1;
  151. break;
  152. case OPTYPE_w:
  153. size = 2;
  154. break;
  155. case OPTYPE_d: case OPTYPE_fs: case OPTYPE_fd:
  156. case OPTYPE_fe: case OPTYPE_fb: case OPTYPE_fv:
  157. case OPTYPE_si: case OPTYPE_fx:
  158. size = 4;
  159. break;
  160. case OPTYPE_s:
  161. size = 6;
  162. break;
  163. case OPTYPE_q: case OPTYPE_pi:
  164. size = 8;
  165. break;
  166. case OPTYPE_dq: case OPTYPE_ps: case OPTYPE_ss:
  167. case OPTYPE_pd: case OPTYPE_sd:
  168. size = 16;
  169. break;
  170. case OPTYPE_m:
  171. size = (addr_size == 4) ? 4 : 2;
  172. break;
  173. default:
  174. break;
  175. }
  176. type = op_flags[x] & ADDRMETH_MASK;
  177. switch (type) {
  178. case ADDRMETH_E: case ADDRMETH_M: case ADDRMETH_Q:
  179. case ADDRMETH_R: case ADDRMETH_W:
  180. modrm = 1;
  181. bytes += ia32_invariant_modrm( buf, out,
  182. mode_16, &inv->operands[x]);
  183. break;
  184. case ADDRMETH_C: case ADDRMETH_D: case ADDRMETH_G:
  185. case ADDRMETH_P: case ADDRMETH_S: case ADDRMETH_T:
  186. case ADDRMETH_V:
  187. inv->operands[x].type = op_register;
  188. modrm = 1;
  189. break;
  190. case ADDRMETH_A: case ADDRMETH_O:
  191. /* pad with xF4's */
  192. memset( &out[bytes + modrm], X86_WILDCARD_BYTE,
  193. size );
  194. bytes += size;
  195. inv->operands[x].type = op_offset;
  196. if ( type == ADDRMETH_O ) {
  197. inv->operands[x].flags |= op_signed |
  198. op_pointer;
  199. }
  200. break;
  201. case ADDRMETH_I: case ADDRMETH_J:
  202. /* grab imm value */
  203. if ((op_flags[x] & OPTYPE_MASK) == OPTYPE_v) {
  204. /* assume this is an address */
  205. memset( &out[bytes + modrm],
  206. X86_WILDCARD_BYTE, size );
  207. } else {
  208. memcpy( &out[bytes + modrm],
  209. &buf[bytes + modrm], size );
  210. }
  211. bytes += size;
  212. if ( type == ADDRMETH_J ) {
  213. if ( size == 1 ) {
  214. inv->operands[x].type =
  215. op_relative_near;
  216. } else {
  217. inv->operands[x].type =
  218. op_relative_far;
  219. }
  220. inv->operands[x].flags |= op_signed;
  221. } else {
  222. inv->operands[x].type = op_immediate;
  223. }
  224. break;
  225. case ADDRMETH_F:
  226. inv->operands[x].type = op_register;
  227. break;
  228. case ADDRMETH_X:
  229. inv->operands[x].flags |= op_signed |
  230. op_pointer | op_ds_seg | op_string;
  231. break;
  232. case ADDRMETH_Y:
  233. inv->operands[x].flags |= op_signed |
  234. op_pointer | op_es_seg | op_string;
  235. break;
  236. case ADDRMETH_RR:
  237. inv->operands[x].type = op_register;
  238. break;
  239. case ADDRMETH_II:
  240. inv->operands[x].type = op_immediate;
  241. break;
  242. default:
  243. inv->operands[x].type = op_unused;
  244. break;
  245. }
  246. }
  247. return (bytes + modrm);
  248. }
  249. size_t ia32_disasm_invariant( unsigned char * buf, size_t buf_len,
  250. x86_invariant_t *inv ) {
  251. ia32_insn_t *raw_insn = NULL;
  252. unsigned int prefixes;
  253. unsigned int type;
  254. size_t size;
  255. /* Perform recursive table lookup starting with main table (0) */
  256. size = ia32_table_lookup( buf, buf_len, 0, &raw_insn, &prefixes );
  257. if ( size == INVALID_INSN || size > buf_len ) {
  258. /* TODO: set errno */
  259. return 0;
  260. }
  261. /* copy opcode bytes to buffer */
  262. memcpy( inv->bytes, buf, size );
  263. /* set mnemonic type and group */
  264. type = raw_insn->mnem_flag & ~INS_FLAG_MASK;
  265. inv->group = (enum x86_insn_group) (INS_GROUP(type)) >> 12;
  266. inv->type = (enum x86_insn_type) INS_TYPE(type);
  267. /* handle operands */
  268. size += ia32_decode_invariant( buf + size, buf_len - size, raw_insn,
  269. &buf[size - 1], prefixes, inv );
  270. inv->size = size;
  271. return size; /* return size of instruction in bytes */
  272. }
  273. size_t ia32_disasm_size( unsigned char *buf, size_t buf_len ) {
  274. x86_invariant_t inv = { {0} };
  275. return( ia32_disasm_invariant( buf, buf_len, &inv ) );
  276. }