1 |
dpavlin |
1 |
/* |
2 |
|
|
* HT Editor |
3 |
|
|
* x86dis.cc |
4 |
|
|
* |
5 |
|
|
* Copyright (C) 1999-2002 Stefan Weyergraf |
6 |
|
|
* |
7 |
|
|
* This program is free software; you can redistribute it and/or modify |
8 |
|
|
* it under the terms of the GNU General Public License version 2 as |
9 |
|
|
* published by the Free Software Foundation. |
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, write to the Free Software |
18 |
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
19 |
|
|
*/ |
20 |
|
|
|
21 |
|
|
#include <cstdio> |
22 |
|
|
#include <cstring> |
23 |
|
|
#include <cstdlib> |
24 |
|
|
|
25 |
|
|
#include "x86dis.h" |
26 |
|
|
|
27 |
|
|
#define mkmod(modrm) (((modrm)>>6)&3) |
28 |
|
|
#define mkreg(modrm) (((modrm)>>3)&7) |
29 |
|
|
#define mkrm(modrm) ((modrm)&7) |
30 |
|
|
|
31 |
|
|
#define mkscale(modrm) (((modrm)>>6)&3) |
32 |
|
|
#define mkindex(modrm) (((modrm)>>3)&7) |
33 |
|
|
#define mkbase(modrm) ((modrm)&7) |
34 |
|
|
|
35 |
|
|
int modrm16_1[8] = { X86_REG_BX, X86_REG_BX, X86_REG_BP, X86_REG_BP, |
36 |
|
|
X86_REG_SI, X86_REG_DI, X86_REG_BP, X86_REG_BX}; |
37 |
|
|
int modrm16_2[8] = { X86_REG_SI, X86_REG_DI, X86_REG_SI, X86_REG_DI, |
38 |
|
|
X86_REG_NO, X86_REG_NO, X86_REG_NO, X86_REG_NO}; |
39 |
|
|
|
40 |
|
|
int sibbase[8] = { X86_REG_AX, X86_REG_CX, X86_REG_DX, X86_REG_BX, |
41 |
|
|
X86_REG_SP, X86_REG_BP, X86_REG_SI, X86_REG_DI }; |
42 |
|
|
|
43 |
|
|
int sibindex[8] = { X86_REG_AX, X86_REG_CX, X86_REG_DX, X86_REG_BX, |
44 |
|
|
X86_REG_NO, X86_REG_BP, X86_REG_SI, X86_REG_DI }; |
45 |
|
|
|
46 |
|
|
int sibscale[4] = {1, 2, 4, 8}; |
47 |
|
|
|
48 |
|
|
/* |
49 |
|
|
* CLASS X86Disassembler |
50 |
|
|
*/ |
51 |
|
|
|
52 |
|
|
X86Disassembler::X86Disassembler() |
53 |
|
|
{ |
54 |
|
|
} |
55 |
|
|
|
56 |
|
|
X86Disassembler::X86Disassembler(int _opsize, int _addrsize) |
57 |
|
|
{ |
58 |
|
|
opsize=_opsize; |
59 |
|
|
addrsize=_addrsize; |
60 |
|
|
} |
61 |
|
|
|
62 |
|
|
X86Disassembler::~X86Disassembler() |
63 |
|
|
{ |
64 |
|
|
} |
65 |
|
|
|
66 |
|
|
dis_insn *X86Disassembler::decode(const byte *code, int Maxlen, CPU_ADDR Addr) |
67 |
|
|
{ |
68 |
|
|
ocodep=code; |
69 |
|
|
/* initialize */ |
70 |
|
|
codep=ocodep; |
71 |
|
|
maxlen=Maxlen; |
72 |
|
|
seg=Addr.addr32.seg; |
73 |
|
|
addr=Addr.addr32.offset; |
74 |
|
|
modrm=-1; |
75 |
|
|
sib=-1; |
76 |
|
|
memset(&insn, 0, sizeof(insn)); |
77 |
|
|
insn.invalid=false; |
78 |
|
|
insn.eopsize=opsize; |
79 |
|
|
insn.eaddrsize=opsize; |
80 |
|
|
|
81 |
|
|
prefixes(); |
82 |
|
|
|
83 |
|
|
insn.opcode=c; |
84 |
|
|
decode_insn(&x86_insns[insn.opcode]); |
85 |
|
|
|
86 |
|
|
if (insn.invalid) { |
87 |
|
|
insn.name="db"; |
88 |
|
|
insn.size=1; |
89 |
|
|
insn.op[0].type=X86_OPTYPE_IMM; |
90 |
|
|
insn.op[0].size=1; |
91 |
|
|
insn.op[0].imm=*code; |
92 |
|
|
insn.lockprefix=X86_PREFIX_NO; |
93 |
|
|
insn.repprefix=X86_PREFIX_NO; |
94 |
|
|
insn.segprefix=X86_PREFIX_NO; |
95 |
|
|
for (int i=1; i<3; i++) insn.op[i].type=X86_OPTYPE_EMPTY; |
96 |
|
|
} else { |
97 |
|
|
insn.size=codep-ocodep; |
98 |
|
|
} |
99 |
|
|
return &insn; |
100 |
|
|
} |
101 |
|
|
|
102 |
|
|
void X86Disassembler::decode_modrm(x86_insn_op *op, char size, int allow_reg, int allow_mem, int mmx) |
103 |
|
|
{ |
104 |
|
|
int modrm=getmodrm(); |
105 |
|
|
int mod=mkmod(modrm); |
106 |
|
|
int rm=mkrm(modrm); |
107 |
|
|
if (mod==3) { |
108 |
|
|
/* reg */ |
109 |
|
|
if (!allow_reg) { |
110 |
|
|
invalidate(); |
111 |
|
|
return; |
112 |
|
|
} |
113 |
|
|
if (mmx) { |
114 |
|
|
op->type=X86_OPTYPE_MMX; |
115 |
|
|
op->size=8; |
116 |
|
|
op->mmx=rm; |
117 |
|
|
} else { |
118 |
|
|
op->type=X86_OPTYPE_REG; |
119 |
|
|
op->size=esizeop(size); |
120 |
|
|
op->reg=rm; |
121 |
|
|
} |
122 |
|
|
} else { |
123 |
|
|
/* mem */ |
124 |
|
|
if (!allow_mem) { |
125 |
|
|
invalidate(); |
126 |
|
|
return; |
127 |
|
|
} |
128 |
|
|
op->mem.addrsize=insn.eaddrsize; |
129 |
|
|
if (insn.eaddrsize==X86_ADDRSIZE16) { |
130 |
|
|
op->type=X86_OPTYPE_MEM; |
131 |
|
|
op->size=esizeop(size); |
132 |
|
|
op->mem.floatptr=isfloat(size); |
133 |
|
|
if ((mod==0) && (rm==6)) { |
134 |
|
|
op->mem.hasdisp=1; |
135 |
|
|
op->mem.disp=getword(); |
136 |
|
|
op->mem.base=X86_REG_NO; |
137 |
|
|
op->mem.index=X86_REG_NO; |
138 |
|
|
op->mem.scale=0; |
139 |
|
|
} else { |
140 |
|
|
op->mem.base=modrm16_1[rm]; |
141 |
|
|
op->mem.index=modrm16_2[rm]; |
142 |
|
|
op->mem.scale=1; |
143 |
|
|
switch (mod) { |
144 |
|
|
case 0: |
145 |
|
|
op->mem.hasdisp=0; |
146 |
|
|
op->mem.disp=0; |
147 |
|
|
break; |
148 |
|
|
case 1: |
149 |
|
|
op->mem.hasdisp=1; |
150 |
|
|
op->mem.disp=(char)getbyte(); |
151 |
|
|
break; |
152 |
|
|
case 2: |
153 |
|
|
op->mem.hasdisp=1; |
154 |
|
|
op->mem.disp=(short)getword(); |
155 |
|
|
break; |
156 |
|
|
} |
157 |
|
|
} |
158 |
|
|
} else { |
159 |
|
|
op->type=X86_OPTYPE_MEM; |
160 |
|
|
op->size=esizeop(size); |
161 |
|
|
op->mem.floatptr=isfloat(size); |
162 |
|
|
if ((mod==0) && (rm==5)) { |
163 |
|
|
op->mem.hasdisp=1; |
164 |
|
|
op->mem.disp=getdword(); |
165 |
|
|
op->mem.base=X86_REG_NO; |
166 |
|
|
op->mem.index=X86_REG_NO; |
167 |
|
|
op->mem.scale=0; |
168 |
|
|
} else if (rm==4) { |
169 |
|
|
decode_sib(op, mod); |
170 |
|
|
} else { |
171 |
|
|
op->mem.base=rm; |
172 |
|
|
op->mem.index=X86_REG_NO; |
173 |
|
|
op->mem.scale=1; |
174 |
|
|
switch (mod) { |
175 |
|
|
case 0: |
176 |
|
|
op->mem.hasdisp=0; |
177 |
|
|
op->mem.disp=0; |
178 |
|
|
break; |
179 |
|
|
case 1: |
180 |
|
|
op->mem.hasdisp=1; |
181 |
|
|
op->mem.disp=(char)getbyte(); |
182 |
|
|
break; |
183 |
|
|
case 2: |
184 |
|
|
op->mem.hasdisp=1; |
185 |
|
|
op->mem.disp=getdword(); |
186 |
|
|
break; |
187 |
|
|
} |
188 |
|
|
} |
189 |
|
|
} |
190 |
|
|
} |
191 |
|
|
} |
192 |
|
|
|
193 |
|
|
void X86Disassembler::decode_insn(x86opc_insn *xinsn) |
194 |
|
|
{ |
195 |
|
|
if (!xinsn->name) { |
196 |
|
|
x86opc_insn_op_special special=*((x86opc_insn_op_special*)(&xinsn->op[0])); |
197 |
|
|
switch (special.type) { |
198 |
|
|
case SPECIAL_TYPE_INVALID: |
199 |
|
|
invalidate(); |
200 |
|
|
break; |
201 |
|
|
case SPECIAL_TYPE_PREFIX: |
202 |
|
|
switch (c) { |
203 |
|
|
case 0x0f: |
204 |
|
|
if (insn.opcodeclass == X86DIS_OPCODE_CLASS_STD) { |
205 |
|
|
insn.opcode = getbyte(); |
206 |
|
|
insn.opcodeclass = X86DIS_OPCODE_CLASS_EXT; |
207 |
|
|
decode_insn(&x86_insns_ext[insn.opcode]); |
208 |
|
|
break; |
209 |
|
|
} |
210 |
|
|
default: |
211 |
|
|
invalidate(); |
212 |
|
|
break; |
213 |
|
|
} |
214 |
|
|
break; |
215 |
|
|
case SPECIAL_TYPE_GROUP: { |
216 |
|
|
int m = mkreg(getmodrm()); |
217 |
|
|
insn.opcode |= m<<8; |
218 |
|
|
decode_insn(&x86_group_insns[(int)special.data][m]); |
219 |
|
|
break; |
220 |
|
|
} |
221 |
|
|
case SPECIAL_TYPE_FGROUP: { |
222 |
|
|
int m = getmodrm(); |
223 |
|
|
if (mkmod(m) == 3) { |
224 |
|
|
x86opc_finsn f = x86_float_group_insns[(int)special.data][mkreg(m)]; |
225 |
|
|
/* fprintf(stderr, "special.data=%d, m=%d, mkreg(m)=%d, mkrm(m)=%d\n", special.data, m, mkreg(m), mkrm(m));*/ |
226 |
|
|
if (f.group) { |
227 |
|
|
decode_insn(&f.group[mkrm(m)]); |
228 |
|
|
} else if (f.insn.name) { |
229 |
|
|
decode_insn(&f.insn); |
230 |
|
|
} else invalidate(); |
231 |
|
|
} else { |
232 |
|
|
decode_insn(&x86_modfloat_group_insns[(int)special.data][mkreg(m)]); |
233 |
|
|
} |
234 |
|
|
break; |
235 |
|
|
} |
236 |
|
|
} |
237 |
|
|
} else { |
238 |
|
|
insn.name=xinsn->name; |
239 |
|
|
for (int i=0; i<3; i++) { |
240 |
|
|
decode_op(&insn.op[i], &xinsn->op[i]); |
241 |
|
|
} |
242 |
|
|
} |
243 |
|
|
} |
244 |
|
|
|
245 |
|
|
void X86Disassembler::decode_op(x86_insn_op *op, x86opc_insn_op *xop) |
246 |
|
|
{ |
247 |
|
|
switch (xop->type) { |
248 |
|
|
case TYPE_0: |
249 |
|
|
return; |
250 |
|
|
case TYPE_A: { |
251 |
|
|
/* direct address without ModR/M */ |
252 |
|
|
op->type=X86_OPTYPE_FARPTR; |
253 |
|
|
op->size=esizeop(xop->size); |
254 |
|
|
switch (op->size) { |
255 |
|
|
case 4: |
256 |
|
|
op->farptr.offset=getword(); |
257 |
|
|
op->farptr.seg=getword(); |
258 |
|
|
break; |
259 |
|
|
case 6: |
260 |
|
|
op->farptr.offset=getdword(); |
261 |
|
|
op->farptr.seg=getword(); |
262 |
|
|
break; |
263 |
|
|
} |
264 |
|
|
break; |
265 |
|
|
} |
266 |
|
|
case TYPE_C: { |
267 |
|
|
/* reg of ModR/M picks control register */ |
268 |
|
|
op->type=X86_OPTYPE_CRX; |
269 |
|
|
op->size=esizeop(xop->size); |
270 |
|
|
op->crx=mkreg(getmodrm()); |
271 |
|
|
break; |
272 |
|
|
} |
273 |
|
|
case TYPE_D: { |
274 |
|
|
/* reg of ModR/M picks debug register */ |
275 |
|
|
op->type=X86_OPTYPE_DRX; |
276 |
|
|
op->size=esizeop(xop->size); |
277 |
|
|
op->drx=mkreg(getmodrm()); |
278 |
|
|
break; |
279 |
|
|
} |
280 |
|
|
case TYPE_E: { |
281 |
|
|
/* ModR/M (general reg or memory) */ |
282 |
|
|
decode_modrm(op, xop->size, (xop->size!=SIZE_P), 1, 0); |
283 |
|
|
break; |
284 |
|
|
} |
285 |
|
|
case TYPE_F: { |
286 |
|
|
/* r/m of ModR/M picks a fpu register */ |
287 |
|
|
op->type=X86_OPTYPE_STX; |
288 |
|
|
op->size=10; |
289 |
|
|
op->stx=mkrm(getmodrm()); |
290 |
|
|
break; |
291 |
|
|
} |
292 |
|
|
case TYPE_Fx: { |
293 |
|
|
/* extra picks a fpu register */ |
294 |
|
|
op->type=X86_OPTYPE_STX; |
295 |
|
|
op->size=10; |
296 |
|
|
op->stx=xop->extra; |
297 |
|
|
break; |
298 |
|
|
} |
299 |
|
|
case TYPE_G: { |
300 |
|
|
/* reg of ModR/M picks general register */ |
301 |
|
|
op->type=X86_OPTYPE_REG; |
302 |
|
|
op->size=esizeop(xop->size); |
303 |
|
|
op->reg=mkreg(getmodrm()); |
304 |
|
|
break; |
305 |
|
|
} |
306 |
|
|
case TYPE_Is: { |
307 |
|
|
/* signed immediate */ |
308 |
|
|
op->type=X86_OPTYPE_IMM; |
309 |
|
|
op->size=esizeop(xop->extendedsize); |
310 |
|
|
int s=esizeop(xop->size); |
311 |
|
|
switch (s) { |
312 |
|
|
case 1: |
313 |
|
|
op->imm=(char)getbyte(); |
314 |
|
|
break; |
315 |
|
|
case 2: |
316 |
|
|
op->imm=(short)getword(); |
317 |
|
|
break; |
318 |
|
|
case 4: |
319 |
|
|
op->imm=getdword(); |
320 |
|
|
break; |
321 |
|
|
} |
322 |
|
|
switch (op->size) { |
323 |
|
|
case 1: |
324 |
|
|
op->imm&=0xff; |
325 |
|
|
break; |
326 |
|
|
case 2: |
327 |
|
|
op->imm&=0xffff; |
328 |
|
|
break; |
329 |
|
|
} |
330 |
|
|
break; |
331 |
|
|
} |
332 |
|
|
case TYPE_I: { |
333 |
|
|
/* unsigned immediate */ |
334 |
|
|
op->type=X86_OPTYPE_IMM; |
335 |
|
|
op->size=esizeop(xop->extendedsize); |
336 |
|
|
int s=esizeop(xop->size); |
337 |
|
|
switch (s) { |
338 |
|
|
case 1: |
339 |
|
|
op->imm=getbyte(); |
340 |
|
|
break; |
341 |
|
|
case 2: |
342 |
|
|
op->imm=getword(); |
343 |
|
|
break; |
344 |
|
|
case 4: |
345 |
|
|
op->imm=getdword(); |
346 |
|
|
break; |
347 |
|
|
} |
348 |
|
|
break; |
349 |
|
|
} |
350 |
|
|
case TYPE_Ix: { |
351 |
|
|
/* fixed immediate */ |
352 |
|
|
op->type=X86_OPTYPE_IMM; |
353 |
|
|
op->size=esizeop(xop->extendedsize); |
354 |
|
|
op->imm=xop->extra; |
355 |
|
|
break; |
356 |
|
|
} |
357 |
|
|
case TYPE_J: { |
358 |
|
|
/* relative branch offset */ |
359 |
|
|
op->type=X86_OPTYPE_IMM; |
360 |
|
|
// op->size=esizeaddr(xop->extendedsize); |
361 |
|
|
op->size=(addrsize==X86_ADDRSIZE32) ? 4 : 2; |
362 |
|
|
int s=esizeop(xop->size); |
363 |
|
|
switch (s) { |
364 |
|
|
case 1: |
365 |
|
|
op->imm=(char)getbyte()+addr; |
366 |
|
|
break; |
367 |
|
|
case 2: |
368 |
|
|
op->imm=(short)getword()+addr; |
369 |
|
|
break; |
370 |
|
|
case 4: |
371 |
|
|
op->imm=getdword()+addr; |
372 |
|
|
break; |
373 |
|
|
} |
374 |
|
|
break; |
375 |
|
|
} |
376 |
|
|
case TYPE_M: { |
377 |
|
|
/* ModR/M (memory only) */ |
378 |
|
|
decode_modrm(op, xop->size, 0, 1, 0); |
379 |
|
|
break; |
380 |
|
|
} |
381 |
|
|
case TYPE_O: { |
382 |
|
|
/* direct memory without ModR/M */ |
383 |
|
|
op->type=X86_OPTYPE_MEM; |
384 |
|
|
op->size=esizeop(xop->size); |
385 |
|
|
op->mem.floatptr=isfloat(xop->size); |
386 |
|
|
op->mem.addrsize=insn.eaddrsize; |
387 |
|
|
switch (insn.eaddrsize) { |
388 |
|
|
case X86_ADDRSIZE16: |
389 |
|
|
op->mem.hasdisp=1; |
390 |
|
|
op->mem.disp=getword(); |
391 |
|
|
break; |
392 |
|
|
case X86_ADDRSIZE32: |
393 |
|
|
op->mem.hasdisp=1; |
394 |
|
|
op->mem.disp=getdword(); |
395 |
|
|
break; |
396 |
|
|
} |
397 |
|
|
op->mem.base=X86_REG_NO; |
398 |
|
|
op->mem.index=X86_REG_NO; |
399 |
|
|
op->mem.scale=1; |
400 |
|
|
break; |
401 |
|
|
} |
402 |
|
|
case TYPE_P: { |
403 |
|
|
/* reg of ModR/M picks MMX register */ |
404 |
|
|
op->type=X86_OPTYPE_MMX; |
405 |
|
|
op->size=8; |
406 |
|
|
op->mmx=mkreg(getmodrm()); |
407 |
|
|
break; |
408 |
|
|
} |
409 |
|
|
case TYPE_Q: { |
410 |
|
|
/* ModR/M (MMX reg or memory) */ |
411 |
|
|
decode_modrm(op, xop->size, 1, 1, 1); |
412 |
|
|
break; |
413 |
|
|
} |
414 |
|
|
case TYPE_R: { |
415 |
|
|
/* rm of ModR/M picks general register */ |
416 |
|
|
op->type=X86_OPTYPE_REG; |
417 |
|
|
op->size=esizeop(xop->size); |
418 |
|
|
op->reg=mkrm(getmodrm()); |
419 |
|
|
break; |
420 |
|
|
} |
421 |
|
|
case TYPE_Rx: { |
422 |
|
|
/* extra picks register */ |
423 |
|
|
op->type=X86_OPTYPE_REG; |
424 |
|
|
op->size=esizeop(xop->size); |
425 |
|
|
op->reg=xop->extra; |
426 |
|
|
break; |
427 |
|
|
} |
428 |
|
|
case TYPE_S: { |
429 |
|
|
/* reg of ModR/M picks segment register */ |
430 |
|
|
op->type=X86_OPTYPE_SEG; |
431 |
|
|
op->size=esizeop(xop->size); |
432 |
|
|
op->seg=mkreg(getmodrm()); |
433 |
|
|
if (op->seg>5) invalidate(); |
434 |
|
|
break; |
435 |
|
|
} |
436 |
|
|
case TYPE_Sx: { |
437 |
|
|
/* extra picks segment register */ |
438 |
|
|
op->type=X86_OPTYPE_SEG; |
439 |
|
|
op->size=esizeop(xop->size); |
440 |
|
|
op->seg=xop->extra; |
441 |
|
|
if (op->seg>5) invalidate(); |
442 |
|
|
break; |
443 |
|
|
} |
444 |
|
|
case TYPE_T: { |
445 |
|
|
/* reg of ModR/M picks test register */ |
446 |
|
|
op->type=X86_OPTYPE_TRX; |
447 |
|
|
op->size=esizeop(xop->size); |
448 |
|
|
op->trx=mkreg(getmodrm()); |
449 |
|
|
break; |
450 |
|
|
} |
451 |
|
|
} |
452 |
|
|
} |
453 |
|
|
|
454 |
|
|
void X86Disassembler::decode_sib(x86_insn_op *op, int mod) |
455 |
|
|
{ |
456 |
|
|
int sib=getsib(); |
457 |
|
|
int scale=mkscale(sib); |
458 |
|
|
int index=mkindex(sib); |
459 |
|
|
int base=mkbase(sib); |
460 |
|
|
int disp=mod; |
461 |
|
|
if (base==5) { |
462 |
|
|
if (mod==0) { |
463 |
|
|
op->mem.base=X86_REG_NO; |
464 |
|
|
disp=2; |
465 |
|
|
} else { |
466 |
|
|
op->mem.base=X86_REG_BP; |
467 |
|
|
} |
468 |
|
|
op->mem.index=sibindex[index]; |
469 |
|
|
op->mem.scale=sibscale[scale]; |
470 |
|
|
} else { |
471 |
|
|
op->mem.base=sibbase[base]; |
472 |
|
|
op->mem.index=sibindex[index]; |
473 |
|
|
op->mem.scale=sibscale[scale]; |
474 |
|
|
} |
475 |
|
|
switch (disp) { |
476 |
|
|
case 0: |
477 |
|
|
op->mem.hasdisp=0; |
478 |
|
|
op->mem.disp=0; |
479 |
|
|
break; |
480 |
|
|
case 1: |
481 |
|
|
op->mem.hasdisp=1; |
482 |
|
|
op->mem.disp=(char)getbyte(); |
483 |
|
|
break; |
484 |
|
|
case 2: |
485 |
|
|
op->mem.hasdisp=1; |
486 |
|
|
op->mem.disp=getdword(); |
487 |
|
|
break; |
488 |
|
|
} |
489 |
|
|
} |
490 |
|
|
|
491 |
|
|
dis_insn *X86Disassembler::duplicateInsn(dis_insn *disasm_insn) |
492 |
|
|
{ |
493 |
|
|
x86dis_insn *insn = (x86dis_insn *)malloc(sizeof (x86dis_insn)); |
494 |
|
|
*insn = *(x86dis_insn *)disasm_insn; |
495 |
|
|
return insn; |
496 |
|
|
} |
497 |
|
|
|
498 |
|
|
int X86Disassembler::esizeaddr(char c) |
499 |
|
|
{ |
500 |
|
|
switch (c) { |
501 |
|
|
case SIZE_B: |
502 |
|
|
return 1; |
503 |
|
|
case SIZE_W: |
504 |
|
|
return 2; |
505 |
|
|
case SIZE_D: |
506 |
|
|
return 4; |
507 |
|
|
case SIZE_Q: |
508 |
|
|
return 8; |
509 |
|
|
case SIZE_S: |
510 |
|
|
return 4; |
511 |
|
|
case SIZE_L: |
512 |
|
|
return 8; |
513 |
|
|
case SIZE_T: |
514 |
|
|
return 10; |
515 |
|
|
case SIZE_C: |
516 |
|
|
if (insn.eaddrsize==X86_ADDRSIZE16) return 1; else return 2; |
517 |
|
|
case SIZE_V: |
518 |
|
|
if (insn.eaddrsize==X86_ADDRSIZE16) return 2; else return 4; |
519 |
|
|
case SIZE_P: |
520 |
|
|
if (insn.eaddrsize==X86_ADDRSIZE16) return 4; else return 6; |
521 |
|
|
} |
522 |
|
|
return 0; |
523 |
|
|
} |
524 |
|
|
|
525 |
|
|
int X86Disassembler::esizeop(char c) |
526 |
|
|
{ |
527 |
|
|
switch (c) { |
528 |
|
|
case SIZE_B: |
529 |
|
|
return 1; |
530 |
|
|
case SIZE_W: |
531 |
|
|
return 2; |
532 |
|
|
case SIZE_D: |
533 |
|
|
return 4; |
534 |
|
|
case SIZE_Q: |
535 |
|
|
return 8; |
536 |
|
|
case SIZE_S: |
537 |
|
|
return 4; |
538 |
|
|
case SIZE_L: |
539 |
|
|
return 8; |
540 |
|
|
case SIZE_T: |
541 |
|
|
return 10; |
542 |
|
|
case SIZE_C: |
543 |
|
|
if (insn.eopsize==X86_OPSIZE16) return 1; else return 2; |
544 |
|
|
case SIZE_V: |
545 |
|
|
if (insn.eopsize==X86_OPSIZE16) return 2; else return 4; |
546 |
|
|
case SIZE_P: |
547 |
|
|
if (insn.eopsize==X86_OPSIZE16) return 4; else return 6; |
548 |
|
|
} |
549 |
|
|
return 0; |
550 |
|
|
} |
551 |
|
|
|
552 |
|
|
byte X86Disassembler::getbyte() |
553 |
|
|
{ |
554 |
|
|
if (codep-ocodep+1<=maxlen) { |
555 |
|
|
addr+=1; |
556 |
|
|
return *(codep++); |
557 |
|
|
} else { |
558 |
|
|
invalidate(); |
559 |
|
|
return 0; |
560 |
|
|
} |
561 |
|
|
} |
562 |
|
|
|
563 |
|
|
word X86Disassembler::getword() |
564 |
|
|
{ |
565 |
|
|
if (codep-ocodep+2<=maxlen) { |
566 |
|
|
word w; |
567 |
|
|
addr += 2; |
568 |
|
|
w = codep[0] | (codep[1]<<8); |
569 |
|
|
codep += 2; |
570 |
|
|
return w; |
571 |
|
|
} else { |
572 |
|
|
invalidate(); |
573 |
|
|
return 0; |
574 |
|
|
} |
575 |
|
|
} |
576 |
|
|
|
577 |
|
|
dword X86Disassembler::getdword() |
578 |
|
|
{ |
579 |
|
|
if (codep-ocodep+4<=maxlen) { |
580 |
|
|
dword w; |
581 |
|
|
addr += 4; |
582 |
|
|
w = codep[0] | (codep[1]<<8) | (codep[2]<<16) | (codep[3]<<24); |
583 |
|
|
codep += 4; |
584 |
|
|
return w; |
585 |
|
|
} else { |
586 |
|
|
invalidate(); |
587 |
|
|
return 0; |
588 |
|
|
} |
589 |
|
|
} |
590 |
|
|
|
591 |
|
|
void X86Disassembler::getOpcodeMetrics(int &min_length, int &max_length, int &min_look_ahead, int &avg_look_ahead, int &addr_align) |
592 |
|
|
{ |
593 |
|
|
min_length = 1; |
594 |
|
|
max_length = 15; |
595 |
|
|
min_look_ahead = 120; // 1/2/3/4/5/6/8/10/12/15 |
596 |
|
|
avg_look_ahead = 24; // 1/2/3/4/6/8/12/24 |
597 |
|
|
addr_align = 1; |
598 |
|
|
} |
599 |
|
|
|
600 |
|
|
int X86Disassembler::getmodrm() |
601 |
|
|
{ |
602 |
|
|
if (modrm==-1) modrm=getbyte(); |
603 |
|
|
return modrm; |
604 |
|
|
} |
605 |
|
|
|
606 |
|
|
char *X86Disassembler::getName() |
607 |
|
|
{ |
608 |
|
|
return "x86/Disassembler"; |
609 |
|
|
} |
610 |
|
|
|
611 |
|
|
int X86Disassembler::getsib() |
612 |
|
|
{ |
613 |
|
|
if (sib==-1) sib=getbyte(); |
614 |
|
|
return sib; |
615 |
|
|
} |
616 |
|
|
|
617 |
|
|
byte X86Disassembler::getSize(dis_insn *disasm_insn) |
618 |
|
|
{ |
619 |
|
|
return ((x86dis_insn*)disasm_insn)->size; |
620 |
|
|
} |
621 |
|
|
|
622 |
|
|
void X86Disassembler::invalidate() |
623 |
|
|
{ |
624 |
|
|
insn.invalid=1; |
625 |
|
|
} |
626 |
|
|
|
627 |
|
|
int X86Disassembler::isfloat(char c) |
628 |
|
|
{ |
629 |
|
|
switch (c) { |
630 |
|
|
case SIZE_S: |
631 |
|
|
case SIZE_L: |
632 |
|
|
case SIZE_T: |
633 |
|
|
return 1; |
634 |
|
|
} |
635 |
|
|
return 0; |
636 |
|
|
} |
637 |
|
|
|
638 |
|
|
void X86Disassembler::prefixes() |
639 |
|
|
{ |
640 |
|
|
bool notprefix=0; |
641 |
|
|
insn.lockprefix=X86_PREFIX_NO; |
642 |
|
|
insn.repprefix=X86_PREFIX_NO; |
643 |
|
|
insn.segprefix=X86_PREFIX_NO; |
644 |
|
|
while ((codep-ocodep<15) && (!notprefix)) { |
645 |
|
|
c=getbyte(); |
646 |
|
|
switch (c) { |
647 |
|
|
case 0x26: |
648 |
|
|
insn.segprefix=X86_PREFIX_ES; |
649 |
|
|
break; |
650 |
|
|
case 0x2e: |
651 |
|
|
insn.segprefix=X86_PREFIX_CS; |
652 |
|
|
break; |
653 |
|
|
case 0x36: |
654 |
|
|
insn.segprefix=X86_PREFIX_SS; |
655 |
|
|
break; |
656 |
|
|
case 0x3e: |
657 |
|
|
insn.segprefix=X86_PREFIX_DS; |
658 |
|
|
break; |
659 |
|
|
case 0x64: |
660 |
|
|
insn.segprefix=X86_PREFIX_FS; |
661 |
|
|
break; |
662 |
|
|
case 0x65: |
663 |
|
|
insn.segprefix=X86_PREFIX_GS; |
664 |
|
|
break; |
665 |
|
|
case 0x66: |
666 |
|
|
insn.eopsize=(opsize==X86_OPSIZE16) ? X86_OPSIZE32 : X86_OPSIZE16; |
667 |
|
|
break; |
668 |
|
|
case 0x67: |
669 |
|
|
insn.eaddrsize=(addrsize==X86_ADDRSIZE16) ? X86_ADDRSIZE32 : X86_ADDRSIZE16; |
670 |
|
|
break; |
671 |
|
|
case 0xf0: |
672 |
|
|
insn.lockprefix=X86_PREFIX_LOCK; |
673 |
|
|
break; |
674 |
|
|
case 0xf2: |
675 |
|
|
insn.repprefix=X86_PREFIX_REPNZ; |
676 |
|
|
break; |
677 |
|
|
case 0xf3: |
678 |
|
|
insn.repprefix=X86_PREFIX_REPZ; |
679 |
|
|
break; |
680 |
|
|
default: |
681 |
|
|
notprefix=1; |
682 |
|
|
} |
683 |
|
|
} |
684 |
|
|
} |
685 |
|
|
|
686 |
|
|
int X86Disassembler::special_param_ambiguity(x86dis_insn *disasm_insn) |
687 |
|
|
{ |
688 |
|
|
int regc=0, memc=0, segc=0; |
689 |
|
|
for (int i=0; i<3; i++) { |
690 |
|
|
switch (disasm_insn->op[i].type) { |
691 |
|
|
case X86_OPTYPE_SEG: |
692 |
|
|
segc++; |
693 |
|
|
case X86_OPTYPE_REG: |
694 |
|
|
case X86_OPTYPE_CRX: |
695 |
|
|
case X86_OPTYPE_DRX: |
696 |
|
|
case X86_OPTYPE_TRX: |
697 |
|
|
case X86_OPTYPE_STX: |
698 |
|
|
case X86_OPTYPE_MMX: |
699 |
|
|
regc++; |
700 |
|
|
break; |
701 |
|
|
case X86_OPTYPE_MEM: |
702 |
|
|
memc++; |
703 |
|
|
break; |
704 |
|
|
} |
705 |
|
|
} |
706 |
|
|
return (memc && !regc) |
707 |
|
|
|| (memc && segc) |
708 |
|
|
|| (strcmp(disasm_insn->name, "movzx") == 0) |
709 |
|
|
|| (strcmp(disasm_insn->name, "movsx") == 0); |
710 |
|
|
} |
711 |
|
|
|
712 |
|
|
void X86Disassembler::str_op(char *opstr, int *opstrlen, x86dis_insn *insn, x86_insn_op *op, bool explicit_params) |
713 |
|
|
{ |
714 |
|
|
const char *cs_default = get_cs(e_cs_default); |
715 |
|
|
const char *cs_number = get_cs(e_cs_number); |
716 |
|
|
const char *cs_symbol = get_cs(e_cs_symbol); |
717 |
|
|
|
718 |
|
|
*opstrlen=0; |
719 |
|
|
switch (op->type) { |
720 |
|
|
case X86_OPTYPE_IMM: { |
721 |
|
|
CPU_ADDR a; |
722 |
|
|
// FIXME: hack |
723 |
|
|
if ((insn->name[0]=='j') || strcmp(insn->name, "call")==0) { |
724 |
|
|
a.addr32.seg = seg; |
725 |
|
|
} else { |
726 |
|
|
a.addr32.seg = 0; |
727 |
|
|
} |
728 |
|
|
a.addr32.offset = op->imm; |
729 |
|
|
int slen; |
730 |
|
|
char *s=(addr_sym_func) ? addr_sym_func(a, &slen, addr_sym_func_context) : NULL; |
731 |
|
|
if (s) { |
732 |
|
|
memmove(opstr, s, slen); |
733 |
|
|
opstr[slen]=0; |
734 |
|
|
*opstrlen=slen; |
735 |
|
|
} else { |
736 |
|
|
char *g=opstr; |
737 |
|
|
strcpy(g, cs_number); g += strlen(cs_number); |
738 |
|
|
switch (op->size) { |
739 |
|
|
case 1: |
740 |
|
|
hexd(&g, 2, options, op->imm); |
741 |
|
|
break; |
742 |
|
|
case 2: |
743 |
|
|
hexd(&g, 4, options, op->imm); |
744 |
|
|
break; |
745 |
|
|
case 4: |
746 |
|
|
hexd(&g, 8, options, op->imm); |
747 |
|
|
break; |
748 |
|
|
} |
749 |
|
|
strcpy(g, cs_default); g += strlen(cs_default); |
750 |
|
|
} |
751 |
|
|
break; |
752 |
|
|
} |
753 |
|
|
case X86_OPTYPE_REG: { |
754 |
|
|
int j; |
755 |
|
|
switch (op->size) { |
756 |
|
|
case 1: j=0; break; |
757 |
|
|
case 2: j=1; break; |
758 |
|
|
case 4: j=2; break; |
759 |
|
|
default: |
760 |
|
|
j=-1; |
761 |
|
|
} |
762 |
|
|
if (j!=-1) sprintf(opstr, x86_regs[j][op->reg]); |
763 |
|
|
break; |
764 |
|
|
} |
765 |
|
|
case X86_OPTYPE_SEG: |
766 |
|
|
if (x86_segs[op->seg]) { |
767 |
|
|
sprintf(opstr, x86_segs[op->seg]); |
768 |
|
|
} |
769 |
|
|
break; |
770 |
|
|
case X86_OPTYPE_CRX: |
771 |
|
|
sprintf(opstr, "cr%d", op->crx); |
772 |
|
|
break; |
773 |
|
|
case X86_OPTYPE_DRX: |
774 |
|
|
sprintf(opstr, "dr%d", op->drx); |
775 |
|
|
break; |
776 |
|
|
case X86_OPTYPE_TRX: |
777 |
|
|
sprintf(opstr, "tr%d", op->trx); |
778 |
|
|
break; |
779 |
|
|
case X86_OPTYPE_STX: |
780 |
|
|
if (op->stx) { |
781 |
|
|
sprintf(opstr, "st(%d)", op->stx); |
782 |
|
|
} else { |
783 |
|
|
strcpy(opstr, "st"); |
784 |
|
|
} |
785 |
|
|
break; |
786 |
|
|
case X86_OPTYPE_MMX: |
787 |
|
|
sprintf(opstr, "mm%d", op->mmx); |
788 |
|
|
break; |
789 |
|
|
case X86_OPTYPE_MEM: { |
790 |
|
|
char *d=opstr; |
791 |
|
|
int reg; |
792 |
|
|
if (explicit_params) { |
793 |
|
|
if (op->mem.floatptr) { |
794 |
|
|
switch (op->size) { |
795 |
|
|
case 4: |
796 |
|
|
d+=sprintf(d, "single ptr "); |
797 |
|
|
break; |
798 |
|
|
case 8: |
799 |
|
|
d+=sprintf(d, "double ptr "); |
800 |
|
|
break; |
801 |
|
|
case 10: |
802 |
|
|
d+=sprintf(d, "extended ptr "); |
803 |
|
|
break; |
804 |
|
|
} |
805 |
|
|
} else { |
806 |
|
|
switch (op->size) { |
807 |
|
|
case 1: |
808 |
|
|
d+=sprintf(d, "byte ptr "); |
809 |
|
|
break; |
810 |
|
|
case 2: |
811 |
|
|
d+=sprintf(d, "word ptr "); |
812 |
|
|
break; |
813 |
|
|
case 4: |
814 |
|
|
d+=sprintf(d, "dword ptr "); |
815 |
|
|
break; |
816 |
|
|
case 6: |
817 |
|
|
d+=sprintf(d, "pword ptr "); |
818 |
|
|
break; |
819 |
|
|
case 8: |
820 |
|
|
d+=sprintf(d, "qword ptr "); |
821 |
|
|
break; |
822 |
|
|
} |
823 |
|
|
} |
824 |
|
|
} |
825 |
|
|
if (insn->eaddrsize==X86_ADDRSIZE16) reg=1; else reg=2; |
826 |
|
|
if (insn->segprefix!=X86_PREFIX_NO) d+=sprintf(d, "%s%s:%s", x86_segs[insn->segprefix], cs_symbol, cs_default); |
827 |
|
|
strcpy(d, cs_symbol); d += strlen(cs_symbol); |
828 |
|
|
*(d++)='['; |
829 |
|
|
strcpy(d, cs_default); d += strlen(cs_default); |
830 |
|
|
|
831 |
|
|
int optimize_addr=options & X86DIS_STYLE_OPTIMIZE_ADDR; |
832 |
|
|
int first=1; |
833 |
|
|
if (optimize_addr && (op->mem.base!=X86_REG_NO) && (op->mem.base==op->mem.index)) { |
834 |
|
|
d+=sprintf(d, "%s%s*%s%d%s", x86_regs[reg][op->mem.index], cs_symbol, cs_number, op->mem.scale+1, cs_default); |
835 |
|
|
first=0; |
836 |
|
|
} else { |
837 |
|
|
if (op->mem.base!=X86_REG_NO) { |
838 |
|
|
d+=sprintf(d, "%s", x86_regs[reg][op->mem.base]); |
839 |
|
|
first=0; |
840 |
|
|
} |
841 |
|
|
if (op->mem.index!=X86_REG_NO) { |
842 |
|
|
if (!first) *(d++)='+'; |
843 |
|
|
if ((op->mem.scale==1)) { |
844 |
|
|
d+=sprintf(d, "%s", x86_regs[reg][op->mem.index]); |
845 |
|
|
} else { |
846 |
|
|
d+=sprintf(d, "%s%s*%s%d%s", x86_regs[reg][op->mem.index], cs_symbol, cs_number, op->mem.scale, cs_default); |
847 |
|
|
} |
848 |
|
|
first=0; |
849 |
|
|
} |
850 |
|
|
} |
851 |
|
|
if ((!optimize_addr && op->mem.hasdisp) || (optimize_addr && op->mem.disp) || first) { |
852 |
|
|
CPU_ADDR a; |
853 |
|
|
a.addr32.seg = 0; // FIXME: not ok |
854 |
|
|
a.addr32.offset=op->mem.disp; |
855 |
|
|
int slen; |
856 |
|
|
char *s=(addr_sym_func) ? addr_sym_func(a, &slen, addr_sym_func_context) : 0; |
857 |
|
|
if (s) { |
858 |
|
|
if (!first) { |
859 |
|
|
strcpy(d, cs_symbol); d += strlen(cs_symbol); |
860 |
|
|
*(d++)='+'; |
861 |
|
|
strcpy(d, cs_default); d += strlen(cs_default); |
862 |
|
|
} |
863 |
|
|
memmove(d, s, slen); |
864 |
|
|
d+=slen; |
865 |
|
|
*opstrlen=d-opstr; |
866 |
|
|
} else { |
867 |
|
|
dword q; |
868 |
|
|
switch (op->mem.addrsize) { |
869 |
|
|
case X86_ADDRSIZE16: |
870 |
|
|
q=op->mem.disp; |
871 |
|
|
if (!first) { |
872 |
|
|
strcpy(d, cs_symbol); d += strlen(cs_symbol); |
873 |
|
|
if (op->mem.disp&0x80000000) { |
874 |
|
|
*(d++)='-'; |
875 |
|
|
q=-q; |
876 |
|
|
} else *(d++)='+'; |
877 |
|
|
} |
878 |
|
|
strcpy(d, cs_number); d += strlen(cs_number); |
879 |
|
|
hexd(&d, 4, options, q); |
880 |
|
|
strcpy(d, cs_default); d += strlen(cs_default); |
881 |
|
|
break; |
882 |
|
|
case X86_ADDRSIZE32: |
883 |
|
|
q=op->mem.disp; |
884 |
|
|
if (!first) { |
885 |
|
|
strcpy(d, cs_symbol); d += strlen(cs_symbol); |
886 |
|
|
if (op->mem.disp&0x80000000) { |
887 |
|
|
*(d++)='-'; |
888 |
|
|
q=-q; |
889 |
|
|
} else *(d++)='+'; |
890 |
|
|
} |
891 |
|
|
strcpy(d, cs_number); d += strlen(cs_number); |
892 |
|
|
hexd(&d, 8, options, q); |
893 |
|
|
strcpy(d, cs_default); d += strlen(cs_default); |
894 |
|
|
break; |
895 |
|
|
} |
896 |
|
|
} |
897 |
|
|
} |
898 |
|
|
strcpy(d, cs_symbol); d += strlen(cs_symbol); |
899 |
|
|
*(d++)=']'; |
900 |
|
|
strcpy(d, cs_default); d += strlen(cs_default); |
901 |
|
|
if (*opstrlen) |
902 |
|
|
*opstrlen += strlen(cs_symbol) + 1 + strlen(cs_default); |
903 |
|
|
*d=0; |
904 |
|
|
break; |
905 |
|
|
} |
906 |
|
|
case X86_OPTYPE_FARPTR: { |
907 |
|
|
CPU_ADDR a; |
908 |
|
|
/* a.addr32.seg = op->farptr.seg; |
909 |
|
|
a.addr32.offset = op->farptr.offset; |
910 |
|
|
*/ |
911 |
|
|
a.addr32.seg = op->farptr.seg; |
912 |
|
|
a.addr32.offset = op->farptr.offset; |
913 |
|
|
int slen; |
914 |
|
|
char *s=(addr_sym_func) ? addr_sym_func(a, &slen, addr_sym_func_context) : 0; |
915 |
|
|
if (s) { |
916 |
|
|
memmove(opstr, s, slen); |
917 |
|
|
opstr[slen]=0; |
918 |
|
|
*opstrlen=slen; |
919 |
|
|
} else { |
920 |
|
|
char *g=opstr; |
921 |
|
|
hexd(&g, 4, options, op->farptr.seg); |
922 |
|
|
strcpy(g, cs_symbol); g += strlen(cs_symbol); |
923 |
|
|
*(g++)=':'; |
924 |
|
|
strcpy(g, cs_default); g += strlen(cs_default); |
925 |
|
|
switch (op->size) { |
926 |
|
|
case 4: |
927 |
|
|
hexd(&g, 4, options, op->farptr.offset); |
928 |
|
|
break; |
929 |
|
|
case 6: |
930 |
|
|
hexd(&g, 8, options, op->farptr.offset); |
931 |
|
|
break; |
932 |
|
|
} |
933 |
|
|
} |
934 |
|
|
break; |
935 |
|
|
} |
936 |
|
|
default: |
937 |
|
|
opstr[0]=0; |
938 |
|
|
} |
939 |
|
|
} |
940 |
|
|
|
941 |
|
|
void X86Disassembler::str_format(char **str, char **format, char *p, char *n, char *op[3], int oplen[3], char stopchar, int print) |
942 |
|
|
{ |
943 |
|
|
const char *cs_default = get_cs(e_cs_default); |
944 |
|
|
const char *cs_symbol = get_cs(e_cs_symbol); |
945 |
|
|
|
946 |
|
|
char *f=*format; |
947 |
|
|
char *s=*str; |
948 |
|
|
while (*f) { |
949 |
|
|
if (*f==stopchar) break; |
950 |
|
|
switch (*f) { |
951 |
|
|
case '\t': |
952 |
|
|
if (print) do *(s++)=' '; while ((s-insnstr) % DIS_STYLE_TABSIZE); |
953 |
|
|
break; |
954 |
|
|
case DISASM_STRF_VAR: |
955 |
|
|
f++; |
956 |
|
|
if (print) { |
957 |
|
|
char *t=0; |
958 |
|
|
int tl=0; |
959 |
|
|
switch (*f) { |
960 |
|
|
case DISASM_STRF_PREFIX: |
961 |
|
|
t=p; |
962 |
|
|
break; |
963 |
|
|
case DISASM_STRF_NAME: |
964 |
|
|
t=n; |
965 |
|
|
break; |
966 |
|
|
case DISASM_STRF_FIRST: |
967 |
|
|
t=op[0]; |
968 |
|
|
tl=oplen[0]; |
969 |
|
|
break; |
970 |
|
|
case DISASM_STRF_SECOND: |
971 |
|
|
t=op[1]; |
972 |
|
|
tl=oplen[1]; |
973 |
|
|
break; |
974 |
|
|
case DISASM_STRF_THIRD: |
975 |
|
|
t=op[2]; |
976 |
|
|
tl=oplen[2]; |
977 |
|
|
break; |
978 |
|
|
} |
979 |
|
|
if (tl) { |
980 |
|
|
memmove(s, t, tl); |
981 |
|
|
s+=tl; |
982 |
|
|
*s=0; |
983 |
|
|
} else { |
984 |
|
|
strcpy(s, t); |
985 |
|
|
s += strlen(s); |
986 |
|
|
} |
987 |
|
|
} |
988 |
|
|
break; |
989 |
|
|
case DISASM_STRF_COND: { |
990 |
|
|
char *t=0; |
991 |
|
|
f++; |
992 |
|
|
switch (*f) { |
993 |
|
|
case DISASM_STRF_PREFIX: |
994 |
|
|
t=p; |
995 |
|
|
break; |
996 |
|
|
case DISASM_STRF_NAME: |
997 |
|
|
t=n; |
998 |
|
|
break; |
999 |
|
|
case DISASM_STRF_FIRST: |
1000 |
|
|
t=op[0]; |
1001 |
|
|
break; |
1002 |
|
|
case DISASM_STRF_SECOND: |
1003 |
|
|
t=op[1]; |
1004 |
|
|
break; |
1005 |
|
|
case DISASM_STRF_THIRD: |
1006 |
|
|
t=op[2]; |
1007 |
|
|
break; |
1008 |
|
|
} |
1009 |
|
|
f+=2; |
1010 |
|
|
if ((t) && (t[0])) { |
1011 |
|
|
str_format(&s, &f, p, n, op, oplen, *(f-1), 1); |
1012 |
|
|
} else { |
1013 |
|
|
str_format(&s, &f, p, n, op, oplen, *(f-1), 0); |
1014 |
|
|
} |
1015 |
|
|
break; |
1016 |
|
|
} |
1017 |
|
|
default: |
1018 |
|
|
if (print) { |
1019 |
|
|
bool x = (strchr(",.-=+-*/[]()", *f) != NULL) && *f; |
1020 |
|
|
if (x) { strcpy(s, cs_symbol); s += strlen(cs_symbol); } |
1021 |
|
|
*(s++) = *f; |
1022 |
|
|
if (x) { strcpy(s, cs_default); s += strlen(cs_default); } |
1023 |
|
|
} |
1024 |
|
|
} |
1025 |
|
|
f++; |
1026 |
|
|
} |
1027 |
|
|
*s=0; |
1028 |
|
|
*format=f; |
1029 |
|
|
*str=s; |
1030 |
|
|
} |
1031 |
|
|
|
1032 |
|
|
char *X86Disassembler::str(dis_insn *disasm_insn, int options) |
1033 |
|
|
{ |
1034 |
|
|
return strf(disasm_insn, options, DISASM_STRF_DEFAULT_FORMAT); |
1035 |
|
|
} |
1036 |
|
|
|
1037 |
|
|
char *X86Disassembler::strf(dis_insn *disasm_insn, int opt, char *format) |
1038 |
|
|
{ |
1039 |
|
|
x86dis_insn *insn = (x86dis_insn*)disasm_insn; |
1040 |
|
|
char prefix[64]; |
1041 |
|
|
char *p = prefix; |
1042 |
|
|
options = opt; |
1043 |
|
|
*p = 0; |
1044 |
|
|
if (insn->lockprefix == X86_PREFIX_LOCK) p+=sprintf(p, "lock "); |
1045 |
|
|
if (insn->repprefix == X86_PREFIX_REPZ) { |
1046 |
|
|
p += sprintf(p, "repz "); |
1047 |
|
|
} else if (insn->repprefix == X86_PREFIX_REPNZ) { |
1048 |
|
|
p += sprintf(p, "repnz "); |
1049 |
|
|
} |
1050 |
|
|
if ((p != prefix) && (*(p-1) == ' ')) { |
1051 |
|
|
p--; |
1052 |
|
|
*p = 0; |
1053 |
|
|
} |
1054 |
|
|
|
1055 |
|
|
bool explicit_params = ((options & X86DIS_STYLE_EXPLICIT_MEMSIZE) || |
1056 |
|
|
special_param_ambiguity(insn)); |
1057 |
|
|
|
1058 |
|
|
char ops[3][512]; /* FIXME: possible buffer overflow ! */ |
1059 |
|
|
char *op[3]; |
1060 |
|
|
int oplen[3]; |
1061 |
|
|
|
1062 |
|
|
if (options & DIS_STYLE_HIGHLIGHT) enable_highlighting(); |
1063 |
|
|
for (int i=0; i<3; i++) { |
1064 |
|
|
op[i]=(char*)&ops[i]; |
1065 |
|
|
str_op(op[i], &oplen[i], insn, &insn->op[i], explicit_params); |
1066 |
|
|
} |
1067 |
|
|
char *s=insnstr; |
1068 |
|
|
char n[32]; |
1069 |
|
|
switch (insn->eopsize) { |
1070 |
|
|
case X86_OPSIZE16: |
1071 |
|
|
sprintf(n, insn->name, 'w'); |
1072 |
|
|
break; |
1073 |
|
|
case X86_OPSIZE32: |
1074 |
|
|
sprintf(n, insn->name, 'd'); |
1075 |
|
|
break; |
1076 |
|
|
default: |
1077 |
|
|
strcpy(n, insn->name); |
1078 |
|
|
break; |
1079 |
|
|
} |
1080 |
|
|
str_format(&s, &format, prefix, n, op, oplen, 0, 1); |
1081 |
|
|
disable_highlighting(); |
1082 |
|
|
return insnstr; |
1083 |
|
|
} |
1084 |
|
|
|
1085 |
|
|
bool X86Disassembler::validInsn(dis_insn *disasm_insn) |
1086 |
|
|
{ |
1087 |
|
|
return !((x86dis_insn *)disasm_insn)->invalid; |
1088 |
|
|
} |
1089 |
|
|
|