The ROme OpTimistic Simulator  2.0.0
A General-Purpose Multithreaded Parallel/Distributed Simulation Platform
ld.c
1 /*
2 x86 Length Disassembler.
3 Copyright (C) 2016 Alessandro Pellegrini
4 Copyright (C) 2013 Byron Platt
5 
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 #include <stdbool.h>
20 
21 #include "lend.h"
22 #include "ld.h"
23 
24 //__thread bool _rip_relative;
25 bool _rip_relative;
26 
27 /* length_disasm */
28 unsigned int length_disasm(void *opcode0, char mode) {
29  unsigned char *opcode = opcode0;
30 
31  unsigned int flag = 0;
32  unsigned int ddef = 4, mdef = 4;
33  unsigned int msize = 0, dsize = 0;
34 
35  unsigned char first_op, op, modrm, mod, rm, rex = 0;
36  unsigned char multibyte = 0;
37 
38  _rip_relative = false;
39 
40 prefix:
41  op = *opcode++;
42 
43  /* prefix */
44  if (CHECK_PREFIX(op)) {
45  if (CHECK_PREFIX_66(op)) ddef = 2;
46  else if (CHECK_PREFIX_67(op)) mdef = 2;
47  goto prefix;
48  }
49 
50  /* Possible REX prefixes, which come after legacy prefixes.
51  * Moreover, multiple REX prefixes could be present. Although the behaviour should
52  * be undefined, most CPUs consider only the last one. */
53  if (mode == MODE_X64 && CHECK_REX(op)) {
54  rex = op;
55  goto prefix;
56  }
57 
58  first_op = op;
59 
60  /* two and three byte opcode */
61  if (CHECK_0F(op)) {
62  op = *opcode++;
63  multibyte = 1;
64 
65  /* Three-byte 38 table */
66  if(CHECK_38(op)) {
67  op = *opcode++;
68  if(CHECK_MODRM38(op)) flag++;
69  } else
70 
71  /* Three-byte 3A table */
72  if(CHECK_3A(op)) {
73  op = *opcode++;
74  if(CHECK_MODRM3A(op)) flag++;
75  }
76 
77  /* Two-byte table */
78  else {
79  if (CHECK_MODRM2(op)) flag++;
80  if (CHECK_DATA12(op)) dsize++;
81  if (CHECK_DATA662(op)) dsize += ddef;
82  }
83  }
84 
85  /* one byte opcode */
86  else {
87  if (CHECK_MODRM(op)) flag++;
88  if (CHECK_TEST(op) && !(*opcode & 0x38)) dsize += (op & 1) ? ddef : 1;
89  if (CHECK_DATA1(op)) dsize++;
90  if (CHECK_DATA2(op)) dsize += 2;
91  if (CHECK_DATA66(op)) dsize += ddef;
92  if (CHECK_MEM67(op)) msize += mdef;
93  }
94 
95  /* modrm */
96  if (flag) {
97  modrm = *opcode++;
98  mod = modrm & 0xc0;
99  rm = modrm & 0x07;
100 
101  if (mod != 0xc0) {
102  if (mod == 0x40) msize++;
103  if (mod == 0x80) msize += mdef;
104  if (mdef == 2 && mode == MODE_X32) {
105  if ((mod == 0x00) && (rm == 0x06)) msize += 2;
106  } else {
107  if (rm == 0x04) {
108  rm = *opcode++ & 0x07; /* rm is the sib */
109  }
110  if (rm == 0x05 && mod == 0x00) {
111  if(mdef == 2) msize += 2;
112  else msize += 4;
113  }
114  }
115  if(mode == MODE_X64 && first_op != 0xff && mod == 0x00 && rm == 0x05) {
116  _rip_relative = true;
117  }
118 
119  } else {
120  if(op == 0x70) { /* TODO: need another table here! */
121  /* Three operands instruction (SSE extension) */
122  dsize = 1;
123  }
124  }
125  }
126 
127  /* REX.W causes 66h to be ignored */
128  if (CHECK_REXW(rex) && !multibyte) {
129  if(CHECK_IMM64(op)) dsize = 8;
130  if(CHECK_OFF64(op)) msize = 8;
131  }
132 
133  opcode += msize + dsize;
134 
135  return opcode - (unsigned char *)opcode0;
136 }