VirtualBox

source: vbox/trunk/include/VBox/dis.h@ 55306

Last change on this file since 55306 was 55033, checked in by vboxsync, 10 years ago

Disassembler: typo & nit.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 35.8 KB
Line 
1/** @file
2 * DIS - The VirtualBox Disassembler.
3 */
4
5/*
6 * Copyright (C) 2006-2012 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
24 */
25
26#ifndef ___VBox_dis_h
27#define ___VBox_dis_h
28
29#include <VBox/types.h>
30#include <VBox/disopcode.h>
31#include <iprt/assert.h>
32
33
34RT_C_DECLS_BEGIN
35
36
37/** @name Prefix byte flags (DISSTATE::fPrefix).
38 * @{
39 */
40#define DISPREFIX_NONE UINT8_C(0x00)
41/** non-default address size. */
42#define DISPREFIX_ADDRSIZE UINT8_C(0x01)
43/** non-default operand size. */
44#define DISPREFIX_OPSIZE UINT8_C(0x02)
45/** lock prefix. */
46#define DISPREFIX_LOCK UINT8_C(0x04)
47/** segment prefix. */
48#define DISPREFIX_SEG UINT8_C(0x08)
49/** rep(e) prefix (not a prefix, but we'll treat is as one). */
50#define DISPREFIX_REP UINT8_C(0x10)
51/** rep(e) prefix (not a prefix, but we'll treat is as one). */
52#define DISPREFIX_REPNE UINT8_C(0x20)
53/** REX prefix (64 bits) */
54#define DISPREFIX_REX UINT8_C(0x40)
55/** @} */
56
57/** @name VEX.Lvvvv prefix destination register flag.
58 * @{
59 */
60#define VEX_LEN256 UINT8_C(0x01)
61#define VEXREG_IS256B(x) ((x) & VEX_LEN256)
62/* Convert second byte of VEX prefix to internal format */
63#define VEX_2B2INT(x) ((((x) >> 2) & 0x1f))
64#define VEX_HAS_REX_R(x) (!((x) & 0x80))
65
66#define DISPREFIX_VEX_FLAG_W UINT8_C(0x01)
67 /** @} */
68
69/** @name 64 bits prefix byte flags (DISSTATE::fRexPrefix).
70 * Requires VBox/disopcode.h.
71 * @{
72 */
73#define DISPREFIX_REX_OP_2_FLAGS(a) (a - OP_PARM_REX_START)
74/*#define DISPREFIX_REX_FLAGS DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX) - 0, which is no flag */
75#define DISPREFIX_REX_FLAGS_B DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_B)
76#define DISPREFIX_REX_FLAGS_X DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_X)
77#define DISPREFIX_REX_FLAGS_XB DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_XB)
78#define DISPREFIX_REX_FLAGS_R DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_R)
79#define DISPREFIX_REX_FLAGS_RB DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_RB)
80#define DISPREFIX_REX_FLAGS_RX DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_RX)
81#define DISPREFIX_REX_FLAGS_RXB DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_RXB)
82#define DISPREFIX_REX_FLAGS_W DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_W)
83#define DISPREFIX_REX_FLAGS_WB DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WB)
84#define DISPREFIX_REX_FLAGS_WX DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WX)
85#define DISPREFIX_REX_FLAGS_WXB DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WXB)
86#define DISPREFIX_REX_FLAGS_WR DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WR)
87#define DISPREFIX_REX_FLAGS_WRB DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WRB)
88#define DISPREFIX_REX_FLAGS_WRX DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WRX)
89#define DISPREFIX_REX_FLAGS_WRXB DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WRXB)
90/** @} */
91AssertCompile(RT_IS_POWER_OF_TWO(DISPREFIX_REX_FLAGS_B));
92AssertCompile(RT_IS_POWER_OF_TWO(DISPREFIX_REX_FLAGS_X));
93AssertCompile(RT_IS_POWER_OF_TWO(DISPREFIX_REX_FLAGS_W));
94AssertCompile(RT_IS_POWER_OF_TWO(DISPREFIX_REX_FLAGS_R));
95
96/** @name Operand type (DISOPCODE::fOpType).
97 * @{
98 */
99#define DISOPTYPE_INVALID RT_BIT_32(0)
100#define DISOPTYPE_HARMLESS RT_BIT_32(1)
101#define DISOPTYPE_CONTROLFLOW RT_BIT_32(2)
102#define DISOPTYPE_POTENTIALLY_DANGEROUS RT_BIT_32(3)
103#define DISOPTYPE_DANGEROUS RT_BIT_32(4)
104#define DISOPTYPE_PORTIO RT_BIT_32(5)
105#define DISOPTYPE_PRIVILEGED RT_BIT_32(6)
106#define DISOPTYPE_PRIVILEGED_NOTRAP RT_BIT_32(7)
107#define DISOPTYPE_UNCOND_CONTROLFLOW RT_BIT_32(8)
108#define DISOPTYPE_RELATIVE_CONTROLFLOW RT_BIT_32(9)
109#define DISOPTYPE_COND_CONTROLFLOW RT_BIT_32(10)
110#define DISOPTYPE_INTERRUPT RT_BIT_32(11)
111#define DISOPTYPE_ILLEGAL RT_BIT_32(12)
112#define DISOPTYPE_RRM_DANGEROUS RT_BIT_32(14) /**< Some additional dangerous ones when recompiling raw r0. */
113#define DISOPTYPE_RRM_DANGEROUS_16 RT_BIT_32(15) /**< Some additional dangerous ones when recompiling 16-bit raw r0. */
114#define DISOPTYPE_RRM_MASK (DISOPTYPE_RRM_DANGEROUS | DISOPTYPE_RRM_DANGEROUS_16)
115#define DISOPTYPE_INHIBIT_IRQS RT_BIT_32(16) /**< Will or can inhibit irqs (sti, pop ss, mov ss) */
116#define DISOPTYPE_PORTIO_READ RT_BIT_32(17)
117#define DISOPTYPE_PORTIO_WRITE RT_BIT_32(18)
118#define DISOPTYPE_INVALID_64 RT_BIT_32(19) /**< Invalid in 64 bits mode */
119#define DISOPTYPE_ONLY_64 RT_BIT_32(20) /**< Only valid in 64 bits mode */
120#define DISOPTYPE_DEFAULT_64_OP_SIZE RT_BIT_32(21) /**< Default 64 bits operand size */
121#define DISOPTYPE_FORCED_64_OP_SIZE RT_BIT_32(22) /**< Forced 64 bits operand size; regardless of prefix bytes */
122#define DISOPTYPE_REXB_EXTENDS_OPREG RT_BIT_32(23) /**< REX.B extends the register field in the opcode byte */
123#define DISOPTYPE_MOD_FIXED_11 RT_BIT_32(24) /**< modrm.mod is always 11b */
124#define DISOPTYPE_FORCED_32_OP_SIZE_X86 RT_BIT_32(25) /**< Forced 32 bits operand size; regardless of prefix bytes (only in 16 & 32 bits mode!) */
125#define DISOPTYPE_SSE RT_BIT_32(29) /**< SSE,SSE2,SSE3,AVX,++ instruction. Not implemented yet! */
126#define DISOPTYPE_MMX RT_BIT_32(30) /**< MMX,MMXExt,3DNow,++ instruction. Not implemented yet! */
127#define DISOPTYPE_FPU RT_BIT_32(31) /**< FPU instruction. Not implemented yet! */
128#define DISOPTYPE_ALL UINT32_C(0xffffffff)
129/** @} */
130
131/** @name Parameter usage flags.
132 * @{
133 */
134#define DISUSE_BASE RT_BIT_64(0)
135#define DISUSE_INDEX RT_BIT_64(1)
136#define DISUSE_SCALE RT_BIT_64(2)
137#define DISUSE_REG_GEN8 RT_BIT_64(3)
138#define DISUSE_REG_GEN16 RT_BIT_64(4)
139#define DISUSE_REG_GEN32 RT_BIT_64(5)
140#define DISUSE_REG_GEN64 RT_BIT_64(6)
141#define DISUSE_REG_FP RT_BIT_64(7)
142#define DISUSE_REG_MMX RT_BIT_64(8)
143#define DISUSE_REG_XMM RT_BIT_64(9)
144#define DISUSE_REG_YMM RT_BIT_64(10)
145#define DISUSE_REG_CR RT_BIT_64(11)
146#define DISUSE_REG_DBG RT_BIT_64(12)
147#define DISUSE_REG_SEG RT_BIT_64(13)
148#define DISUSE_REG_TEST RT_BIT_64(14)
149#define DISUSE_DISPLACEMENT8 RT_BIT_64(15)
150#define DISUSE_DISPLACEMENT16 RT_BIT_64(16)
151#define DISUSE_DISPLACEMENT32 RT_BIT_64(17)
152#define DISUSE_DISPLACEMENT64 RT_BIT_64(18)
153#define DISUSE_RIPDISPLACEMENT32 RT_BIT_64(19)
154#define DISUSE_IMMEDIATE8 RT_BIT_64(20)
155#define DISUSE_IMMEDIATE8_REL RT_BIT_64(21)
156#define DISUSE_IMMEDIATE16 RT_BIT_64(22)
157#define DISUSE_IMMEDIATE16_REL RT_BIT_64(23)
158#define DISUSE_IMMEDIATE32 RT_BIT_64(24)
159#define DISUSE_IMMEDIATE32_REL RT_BIT_64(25)
160#define DISUSE_IMMEDIATE64 RT_BIT_64(26)
161#define DISUSE_IMMEDIATE64_REL RT_BIT_64(27)
162#define DISUSE_IMMEDIATE_ADDR_0_32 RT_BIT_64(28)
163#define DISUSE_IMMEDIATE_ADDR_16_32 RT_BIT_64(29)
164#define DISUSE_IMMEDIATE_ADDR_0_16 RT_BIT_64(30)
165#define DISUSE_IMMEDIATE_ADDR_16_16 RT_BIT_64(31)
166/** DS:ESI */
167#define DISUSE_POINTER_DS_BASED RT_BIT_64(32)
168/** ES:EDI */
169#define DISUSE_POINTER_ES_BASED RT_BIT_64(33)
170#define DISUSE_IMMEDIATE16_SX8 RT_BIT_64(34)
171#define DISUSE_IMMEDIATE32_SX8 RT_BIT_64(35)
172#define DISUSE_IMMEDIATE64_SX8 RT_BIT_64(36)
173
174/** Mask of immediate use flags. */
175#define DISUSE_IMMEDIATE ( DISUSE_IMMEDIATE8 \
176 | DISUSE_IMMEDIATE16 \
177 | DISUSE_IMMEDIATE32 \
178 | DISUSE_IMMEDIATE64 \
179 | DISUSE_IMMEDIATE8_REL \
180 | DISUSE_IMMEDIATE16_REL \
181 | DISUSE_IMMEDIATE32_REL \
182 | DISUSE_IMMEDIATE64_REL \
183 | DISUSE_IMMEDIATE_ADDR_0_32 \
184 | DISUSE_IMMEDIATE_ADDR_16_32 \
185 | DISUSE_IMMEDIATE_ADDR_0_16 \
186 | DISUSE_IMMEDIATE_ADDR_16_16 \
187 | DISUSE_IMMEDIATE16_SX8 \
188 | DISUSE_IMMEDIATE32_SX8 \
189 | DISUSE_IMMEDIATE64_SX8)
190/** Check if the use flags indicates an effective address. */
191#define DISUSE_IS_EFFECTIVE_ADDR(a_fUseFlags) (!!( (a_fUseFlags) \
192 & ( DISUSE_BASE \
193 | DISUSE_INDEX \
194 | DISUSE_DISPLACEMENT32 \
195 | DISUSE_DISPLACEMENT64 \
196 | DISUSE_DISPLACEMENT16 \
197 | DISUSE_DISPLACEMENT8 \
198 | DISUSE_RIPDISPLACEMENT32) ))
199/** @} */
200
201/** @name 64-bit general register indexes.
202 * This matches the AMD64 register encoding. It is found used in
203 * DISOPPARAM::Base.idxGenReg and DISOPPARAM::Index.idxGenReg.
204 * @note Safe to assume same values as the 16-bit and 32-bit general registers.
205 * @{
206 */
207#define DISGREG_RAX UINT8_C(0)
208#define DISGREG_RCX UINT8_C(1)
209#define DISGREG_RDX UINT8_C(2)
210#define DISGREG_RBX UINT8_C(3)
211#define DISGREG_RSP UINT8_C(4)
212#define DISGREG_RBP UINT8_C(5)
213#define DISGREG_RSI UINT8_C(6)
214#define DISGREG_RDI UINT8_C(7)
215#define DISGREG_R8 UINT8_C(8)
216#define DISGREG_R9 UINT8_C(9)
217#define DISGREG_R10 UINT8_C(10)
218#define DISGREG_R11 UINT8_C(11)
219#define DISGREG_R12 UINT8_C(12)
220#define DISGREG_R13 UINT8_C(13)
221#define DISGREG_R14 UINT8_C(14)
222#define DISGREG_R15 UINT8_C(15)
223/** @} */
224
225/** @name 32-bit general register indexes.
226 * This matches the AMD64 register encoding. It is found used in
227 * DISOPPARAM::Base.idxGenReg and DISOPPARAM::Index.idxGenReg.
228 * @note Safe to assume same values as the 16-bit and 64-bit general registers.
229 * @{
230 */
231#define DISGREG_EAX UINT8_C(0)
232#define DISGREG_ECX UINT8_C(1)
233#define DISGREG_EDX UINT8_C(2)
234#define DISGREG_EBX UINT8_C(3)
235#define DISGREG_ESP UINT8_C(4)
236#define DISGREG_EBP UINT8_C(5)
237#define DISGREG_ESI UINT8_C(6)
238#define DISGREG_EDI UINT8_C(7)
239#define DISGREG_R8D UINT8_C(8)
240#define DISGREG_R9D UINT8_C(9)
241#define DISGREG_R10D UINT8_C(10)
242#define DISGREG_R11D UINT8_C(11)
243#define DISGREG_R12D UINT8_C(12)
244#define DISGREG_R13D UINT8_C(13)
245#define DISGREG_R14D UINT8_C(14)
246#define DISGREG_R15D UINT8_C(15)
247/** @} */
248
249/** @name 16-bit general register indexes.
250 * This matches the AMD64 register encoding. It is found used in
251 * DISOPPARAM::Base.idxGenReg and DISOPPARAM::Index.idxGenReg.
252 * @note Safe to assume same values as the 32-bit and 64-bit general registers.
253 * @{
254 */
255#define DISGREG_AX UINT8_C(0)
256#define DISGREG_CX UINT8_C(1)
257#define DISGREG_DX UINT8_C(2)
258#define DISGREG_BX UINT8_C(3)
259#define DISGREG_SP UINT8_C(4)
260#define DISGREG_BP UINT8_C(5)
261#define DISGREG_SI UINT8_C(6)
262#define DISGREG_DI UINT8_C(7)
263#define DISGREG_R8W UINT8_C(8)
264#define DISGREG_R9W UINT8_C(9)
265#define DISGREG_R10W UINT8_C(10)
266#define DISGREG_R11W UINT8_C(11)
267#define DISGREG_R12W UINT8_C(12)
268#define DISGREG_R13W UINT8_C(13)
269#define DISGREG_R14W UINT8_C(14)
270#define DISGREG_R15W UINT8_C(15)
271/** @} */
272
273/** @name 8-bit general register indexes.
274 * This mostly (?) matches the AMD64 register encoding. It is found used in
275 * DISOPPARAM::Base.idxGenReg and DISOPPARAM::Index.idxGenReg.
276 * @{
277 */
278#define DISGREG_AL UINT8_C(0)
279#define DISGREG_CL UINT8_C(1)
280#define DISGREG_DL UINT8_C(2)
281#define DISGREG_BL UINT8_C(3)
282#define DISGREG_AH UINT8_C(4)
283#define DISGREG_CH UINT8_C(5)
284#define DISGREG_DH UINT8_C(6)
285#define DISGREG_BH UINT8_C(7)
286#define DISGREG_R8B UINT8_C(8)
287#define DISGREG_R9B UINT8_C(9)
288#define DISGREG_R10B UINT8_C(10)
289#define DISGREG_R11B UINT8_C(11)
290#define DISGREG_R12B UINT8_C(12)
291#define DISGREG_R13B UINT8_C(13)
292#define DISGREG_R14B UINT8_C(14)
293#define DISGREG_R15B UINT8_C(15)
294#define DISGREG_SPL UINT8_C(16)
295#define DISGREG_BPL UINT8_C(17)
296#define DISGREG_SIL UINT8_C(18)
297#define DISGREG_DIL UINT8_C(19)
298/** @} */
299
300/** @name Segment registerindexes.
301 * This matches the AMD64 register encoding. It is found used in
302 * DISOPPARAM::Base.idxSegReg.
303 * @{
304 */
305typedef enum
306{
307 DISSELREG_ES = 0,
308 DISSELREG_CS = 1,
309 DISSELREG_SS = 2,
310 DISSELREG_DS = 3,
311 DISSELREG_FS = 4,
312 DISSELREG_GS = 5,
313 /** End of the valid register index values. */
314 DISSELREG_END,
315 /** The usual 32-bit paranoia. */
316 DIS_SEGREG_32BIT_HACK = 0x7fffffff
317} DISSELREG;
318/** @} */
319
320/** @name FPU register indexes.
321 * This matches the AMD64 register encoding. It is found used in
322 * DISOPPARAM::Base.idxFpuReg.
323 * @{
324 */
325#define DISFPREG_ST0 UINT8_C(0)
326#define DISFPREG_ST1 UINT8_C(1)
327#define DISFPREG_ST2 UINT8_C(2)
328#define DISFPREG_ST3 UINT8_C(3)
329#define DISFPREG_ST4 UINT8_C(4)
330#define DISFPREG_ST5 UINT8_C(5)
331#define DISFPREG_ST6 UINT8_C(6)
332#define DISFPREG_ST7 UINT8_C(7)
333/** @} */
334
335/** @name Control register indexes.
336 * This matches the AMD64 register encoding. It is found used in
337 * DISOPPARAM::Base.idxCtrlReg.
338 * @{
339 */
340#define DISCREG_CR0 UINT8_C(0)
341#define DISCREG_CR1 UINT8_C(1)
342#define DISCREG_CR2 UINT8_C(2)
343#define DISCREG_CR3 UINT8_C(3)
344#define DISCREG_CR4 UINT8_C(4)
345#define DISCREG_CR8 UINT8_C(8)
346/** @} */
347
348/** @name Debug register indexes.
349 * This matches the AMD64 register encoding. It is found used in
350 * DISOPPARAM::Base.idxDbgReg.
351 * @{
352 */
353#define DISDREG_DR0 UINT8_C(0)
354#define DISDREG_DR1 UINT8_C(1)
355#define DISDREG_DR2 UINT8_C(2)
356#define DISDREG_DR3 UINT8_C(3)
357#define DISDREG_DR4 UINT8_C(4)
358#define DISDREG_DR5 UINT8_C(5)
359#define DISDREG_DR6 UINT8_C(6)
360#define DISDREG_DR7 UINT8_C(7)
361/** @} */
362
363/** @name MMX register indexes.
364 * This matches the AMD64 register encoding. It is found used in
365 * DISOPPARAM::Base.idxMmxReg.
366 * @{
367 */
368#define DISMREG_MMX0 UINT8_C(0)
369#define DISMREG_MMX1 UINT8_C(1)
370#define DISMREG_MMX2 UINT8_C(2)
371#define DISMREG_MMX3 UINT8_C(3)
372#define DISMREG_MMX4 UINT8_C(4)
373#define DISMREG_MMX5 UINT8_C(5)
374#define DISMREG_MMX6 UINT8_C(6)
375#define DISMREG_MMX7 UINT8_C(7)
376/** @} */
377
378/** @name SSE register indexes.
379 * This matches the AMD64 register encoding. It is found used in
380 * DISOPPARAM::Base.idxXmmReg.
381 * @{
382 */
383#define DISXREG_XMM0 UINT8_C(0)
384#define DISXREG_XMM1 UINT8_C(1)
385#define DISXREG_XMM2 UINT8_C(2)
386#define DISXREG_XMM3 UINT8_C(3)
387#define DISXREG_XMM4 UINT8_C(4)
388#define DISXREG_XMM5 UINT8_C(5)
389#define DISXREG_XMM6 UINT8_C(6)
390#define DISXREG_XMM7 UINT8_C(7)
391/** @} */
392
393
394/**
395 * Opcode parameter (operand) details.
396 */
397typedef struct DISOPPARAM
398{
399 /** A combination of DISUSE_XXX. */
400 uint64_t fUse;
401 /** Immediate value or address, applicable if any of the flags included in
402 * DISUSE_IMMEDIATE are set in fUse. */
403 uint64_t uValue;
404 /** Disposition. */
405 union
406 {
407 /** 64-bit displacement, applicable if DISUSE_DISPLACEMENT64 is set in fUse. */
408 int64_t i64;
409 uint64_t u64;
410 /** 32-bit displacement, applicable if DISUSE_DISPLACEMENT32 or
411 * DISUSE_RIPDISPLACEMENT32 is set in fUse. */
412 int32_t i32;
413 uint32_t u32;
414 /** 16-bit displacement, applicable if DISUSE_DISPLACEMENT16 is set in fUse. */
415 int32_t i16;
416 uint32_t u16;
417 /** 8-bit displacement, applicable if DISUSE_DISPLACEMENT8 is set in fUse. */
418 int32_t i8;
419 uint32_t u8;
420 } uDisp;
421 /** The base register from ModR/M or SIB, applicable if DISUSE_BASE is
422 * set in fUse. */
423 union
424 {
425 /** General register index (DISGREG_XXX), applicable if DISUSE_REG_GEN8,
426 * DISUSE_REG_GEN16, DISUSE_REG_GEN32 or DISUSE_REG_GEN64 is set in fUse. */
427 uint8_t idxGenReg;
428 /** FPU stack register index (DISFPREG_XXX), applicable if DISUSE_REG_FP is
429 * set in fUse. 1:1 indexes. */
430 uint8_t idxFpuReg;
431 /** MMX register index (DISMREG_XXX), applicable if DISUSE_REG_MMX is
432 * set in fUse. 1:1 indexes. */
433 uint8_t idxMmxReg;
434 /** SSE register index (DISXREG_XXX), applicable if DISUSE_REG_XMM is
435 * set in fUse. 1:1 indexes. */
436 uint8_t idxXmmReg;
437 /** SSE2 register index (DISYREG_XXX), applicable if DISUSE_REG_YMM is
438 * set in fUse. 1:1 indexes. */
439 uint8_t idxYmmReg;
440 /** Segment register index (DISSELREG_XXX), applicable if DISUSE_REG_SEG is
441 * set in fUse. */
442 uint8_t idxSegReg;
443 /** Test register, TR0-TR7, present on early IA32 CPUs, applicable if
444 * DISUSE_REG_TEST is set in fUse. No index defines for these. */
445 uint8_t idxTestReg;
446 /** Control register index (DISCREG_XXX), applicable if DISUSE_REG_CR is
447 * set in fUse. 1:1 indexes. */
448 uint8_t idxCtrlReg;
449 /** Debug register index (DISDREG_XXX), applicable if DISUSE_REG_DBG is
450 * set in fUse. 1:1 indexes. */
451 uint8_t idxDbgReg;
452 } Base;
453 /** The SIB index register meaning, applicable if DISUSE_INDEX is
454 * set in fUse. */
455 union
456 {
457 /** General register index (DISGREG_XXX), applicable if DISUSE_REG_GEN8,
458 * DISUSE_REG_GEN16, DISUSE_REG_GEN32 or DISUSE_REG_GEN64 is set in fUse. */
459 uint8_t idxGenReg;
460 /** XMM register index (DISXREG_XXX), applicable if DISUSE_REG_XMM
461 * is set in fUse. */
462 uint8_t idxXmmReg;
463 /** YMM register index (DISXREG_XXX), applicable if DISUSE_REG_YMM
464 * is set in fUse. */
465 uint8_t idxYmmReg;
466 } Index;
467 /** 2, 4 or 8, if DISUSE_SCALE is set in fUse. */
468 uint8_t uScale;
469 /** Parameter size. */
470 uint8_t cb;
471 /** Copy of the corresponding DISOPCODE::fParam1 / DISOPCODE::fParam2 /
472 * DISOPCODE::fParam3. */
473 uint32_t fParam;
474} DISOPPARAM;
475AssertCompileSize(DISOPPARAM, 32);
476/** Pointer to opcode parameter. */
477typedef DISOPPARAM *PDISOPPARAM;
478/** Pointer to opcode parameter. */
479typedef const DISOPPARAM *PCDISOPPARAM;
480
481
482/**
483 * Opcode descriptor.
484 */
485typedef struct DISOPCODE
486{
487#ifndef DIS_CORE_ONLY
488 const char *pszOpcode;
489#endif
490 /** Parameter \#1 parser index. */
491 uint8_t idxParse1;
492 /** Parameter \#2 parser index. */
493 uint8_t idxParse2;
494 /** Parameter \#3 parser index. */
495 uint8_t idxParse3;
496 /** Parameter \#4 parser index. */
497 uint8_t idxParse4;
498 /** The opcode identifier. This DIS specific, @see grp_dis_opcodes and
499 * VBox/disopcode.h. */
500 uint16_t uOpcode;
501 /** Parameter \#1 info, @see grp_dis_opparam. */
502 uint16_t fParam1;
503 /** Parameter \#2 info, @see grp_dis_opparam. */
504 uint16_t fParam2;
505 /** Parameter \#3 info, @see grp_dis_opparam. */
506 uint16_t fParam3;
507 /** Parameter \#4 info, @see grp_dis_opparam. */
508 uint16_t fParam4;
509 /** padding unused */
510 uint16_t uPadding;
511 /** Operand type flags, DISOPTYPE_XXX. */
512 uint32_t fOpType;
513} DISOPCODE;
514/** Pointer to const opcode. */
515typedef const struct DISOPCODE *PCDISOPCODE;
516
517
518/**
519 * Callback for reading instruction bytes.
520 *
521 * @returns VBox status code, bytes in DISSTATE::abInstr and byte count in
522 * DISSTATE::cbCachedInstr.
523 * @param pDis Pointer to the disassembler state. The user
524 * argument can be found in DISSTATE::pvUser if needed.
525 * @param offInstr The offset relative to the start of the instruction.
526 *
527 * To get the source address, add this to
528 * DISSTATE::uInstrAddr.
529 *
530 * To calculate the destination buffer address, use it
531 * as an index into DISSTATE::abInstr.
532 *
533 * @param cbMinRead The minimum number of bytes to read.
534 * @param cbMaxRead The maximum number of bytes that may be read.
535 */
536typedef DECLCALLBACK(int) FNDISREADBYTES(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead);
537/** Pointer to a opcode byte reader. */
538typedef FNDISREADBYTES *PFNDISREADBYTES;
539
540/** Parser callback.
541 * @remark no DECLCALLBACK() here because it's considered to be internal and
542 * there is no point in enforcing CDECL. */
543typedef size_t FNDISPARSE(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam);
544/** Pointer to a disassembler parser function. */
545typedef FNDISPARSE *PFNDISPARSE;
546/** Pointer to a const disassembler parser function pointer. */
547typedef PFNDISPARSE const *PCPFNDISPARSE;
548
549/**
550 * The diassembler state and result.
551 */
552typedef struct DISSTATE
553{
554 /** The number of valid bytes in abInstr. */
555 uint8_t cbCachedInstr;
556 /** SIB fields. */
557 union
558 {
559 /** Bitfield view */
560 struct
561 {
562 uint8_t Base;
563 uint8_t Index;
564 uint8_t Scale;
565 } Bits;
566 } SIB;
567 /** ModRM fields. */
568 union
569 {
570 /** Bitfield view */
571 struct
572 {
573 uint8_t Rm;
574 uint8_t Reg;
575 uint8_t Mod;
576 } Bits;
577 } ModRM;
578 /** The CPU mode (DISCPUMODE). */
579 uint8_t uCpuMode;
580 /** The addressing mode (DISCPUMODE). */
581 uint8_t uAddrMode;
582 /** The operand mode (DISCPUMODE). */
583 uint8_t uOpMode;
584 /** Per instruction prefix settings. */
585 uint8_t fPrefix;
586 /** REX prefix value (64 bits only). */
587 uint8_t fRexPrefix;
588 /** Segment prefix value (DISSELREG). */
589 uint8_t idxSegPrefix;
590 /** Last prefix byte (for SSE2 extension tables). */
591 uint8_t bLastPrefix;
592 /** Last significant opcode byte of instruction. */
593 uint8_t bOpCode;
594 /** The size of the prefix bytes. */
595 uint8_t cbPrefix;
596 /** The instruction size. */
597 uint8_t cbInstr;
598 /** VEX presence flag, destination register and size */
599 uint8_t bVexDestReg;
600 /** VEX.W flag */
601 uint8_t bVexWFlag;
602 /** Unused bytes. */
603 uint8_t abUnused[1];
604 /** Internal: instruction filter */
605 uint32_t fFilter;
606 /** Internal: pointer to disassembly function table */
607 PCPFNDISPARSE pfnDisasmFnTable;
608#if ARCH_BITS == 32
609 uint32_t uPtrPadding1;
610#endif
611 /** Pointer to the current instruction. */
612 PCDISOPCODE pCurInstr;
613#if ARCH_BITS == 32
614 uint32_t uPtrPadding2;
615#endif
616 /** The instruction bytes. */
617 uint8_t abInstr[16];
618 /** SIB displacment. */
619 int32_t i32SibDisp;
620
621 /** Return code set by a worker function like the opcode bytes readers. */
622 int32_t rc;
623 /** The address of the instruction. */
624 RTUINTPTR uInstrAddr;
625 /** Optional read function */
626 PFNDISREADBYTES pfnReadBytes;
627#if ARCH_BITS == 32
628 uint32_t uPadding3;
629#endif
630 /** User data supplied as an argument to the APIs. */
631 void *pvUser;
632#if ARCH_BITS == 32
633 uint32_t uPadding4;
634#endif
635 /** Parameters. */
636 DISOPPARAM Param1;
637 DISOPPARAM Param2;
638 DISOPPARAM Param3;
639 DISOPPARAM Param4;
640} DISSTATE;
641AssertCompileSize(DISSTATE, 0xd8);
642
643/** @deprecated Use DISSTATE and change Cpu and DisState to Dis. */
644typedef DISSTATE DISCPUSTATE;
645
646
647
648DISDECL(int) DISInstrToStr(void const *pvInstr, DISCPUMODE enmCpuMode,
649 PDISSTATE pDis, uint32_t *pcbInstr, char *pszOutput, size_t cbOutput);
650DISDECL(int) DISInstrToStrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
651 PDISSTATE pDis, uint32_t *pcbInstr, char *pszOutput, size_t cbOutput);
652DISDECL(int) DISInstrToStrEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode,
653 PFNDISREADBYTES pfnReadBytes, void *pvUser, uint32_t uFilter,
654 PDISSTATE pDis, uint32_t *pcbInstr, char *pszOutput, size_t cbOutput);
655
656DISDECL(int) DISInstr(void const *pvInstr, DISCPUMODE enmCpuMode, PDISSTATE pDis, uint32_t *pcbInstr);
657DISDECL(int) DISInstrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
658 PDISSTATE pDis, uint32_t *pcbInstr);
659DISDECL(int) DISInstrEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t uFilter,
660 PFNDISREADBYTES pfnReadBytes, void *pvUser,
661 PDISSTATE pDis, uint32_t *pcbInstr);
662DISDECL(int) DISInstrWithPrefetchedBytes(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
663 void const *pvPrefetched, size_t cbPretched,
664 PFNDISREADBYTES pfnReadBytes, void *pvUser,
665 PDISSTATE pDis, uint32_t *pcbInstr);
666
667DISDECL(int) DISGetParamSize(PCDISSTATE pDis, PCDISOPPARAM pParam);
668DISDECL(DISSELREG) DISDetectSegReg(PCDISSTATE pDis, PCDISOPPARAM pParam);
669DISDECL(uint8_t) DISQuerySegPrefixByte(PCDISSTATE pDis);
670
671
672
673/** @name Flags returned by DISQueryParamVal (DISQPVPARAMVAL::flags).
674 * @{
675 */
676#define DISQPV_FLAG_8 UINT8_C(0x01)
677#define DISQPV_FLAG_16 UINT8_C(0x02)
678#define DISQPV_FLAG_32 UINT8_C(0x04)
679#define DISQPV_FLAG_64 UINT8_C(0x08)
680#define DISQPV_FLAG_FARPTR16 UINT8_C(0x10)
681#define DISQPV_FLAG_FARPTR32 UINT8_C(0x20)
682/** @} */
683
684/** @name Types returned by DISQueryParamVal (DISQPVPARAMVAL::flags).
685 * @{ */
686#define DISQPV_TYPE_REGISTER UINT8_C(1)
687#define DISQPV_TYPE_ADDRESS UINT8_C(2)
688#define DISQPV_TYPE_IMMEDIATE UINT8_C(3)
689/** @} */
690
691typedef struct
692{
693 union
694 {
695 uint8_t val8;
696 uint16_t val16;
697 uint32_t val32;
698 uint64_t val64;
699
700 struct
701 {
702 uint16_t sel;
703 uint32_t offset;
704 } farptr;
705 } val;
706
707 uint8_t type;
708 uint8_t size;
709 uint8_t flags;
710} DISQPVPARAMVAL;
711/** Pointer to opcode parameter value. */
712typedef DISQPVPARAMVAL *PDISQPVPARAMVAL;
713
714/** Indicates which parameter DISQueryParamVal should operate on. */
715typedef enum DISQPVWHICH
716{
717 DISQPVWHICH_DST = 1,
718 DISQPVWHICH_SRC,
719 DISQPVWHAT_32_BIT_HACK = 0x7fffffff
720} DISQPVWHICH;
721DISDECL(int) DISQueryParamVal(PCPUMCTXCORE pCtx, PCDISSTATE pDis, PCDISOPPARAM pParam, PDISQPVPARAMVAL pParamVal, DISQPVWHICH parmtype);
722DISDECL(int) DISQueryParamRegPtr(PCPUMCTXCORE pCtx, PCDISSTATE pDis, PCDISOPPARAM pParam, void **ppReg, size_t *pcbSize);
723
724DISDECL(int) DISFetchReg8(PCCPUMCTXCORE pCtx, unsigned reg8, uint8_t *pVal);
725DISDECL(int) DISFetchReg16(PCCPUMCTXCORE pCtx, unsigned reg16, uint16_t *pVal);
726DISDECL(int) DISFetchReg32(PCCPUMCTXCORE pCtx, unsigned reg32, uint32_t *pVal);
727DISDECL(int) DISFetchReg64(PCCPUMCTXCORE pCtx, unsigned reg64, uint64_t *pVal);
728DISDECL(int) DISFetchRegSeg(PCCPUMCTXCORE pCtx, DISSELREG sel, RTSEL *pVal);
729DISDECL(int) DISFetchRegSegEx(PCPUMCTXCORE pCtx, DISSELREG sel, PCPUMSELREG *ppSelReg);
730DISDECL(int) DISWriteReg8(PCPUMCTXCORE pRegFrame, unsigned reg8, uint8_t val8);
731DISDECL(int) DISWriteReg16(PCPUMCTXCORE pRegFrame, unsigned reg32, uint16_t val16);
732DISDECL(int) DISWriteReg32(PCPUMCTXCORE pRegFrame, unsigned reg32, uint32_t val32);
733DISDECL(int) DISWriteReg64(PCPUMCTXCORE pRegFrame, unsigned reg64, uint64_t val64);
734DISDECL(int) DISWriteRegSeg(PCPUMCTXCORE pCtx, DISSELREG sel, RTSEL val);
735DISDECL(int) DISPtrReg8(PCPUMCTXCORE pCtx, unsigned reg8, uint8_t **ppReg);
736DISDECL(int) DISPtrReg16(PCPUMCTXCORE pCtx, unsigned reg16, uint16_t **ppReg);
737DISDECL(int) DISPtrReg32(PCPUMCTXCORE pCtx, unsigned reg32, uint32_t **ppReg);
738DISDECL(int) DISPtrReg64(PCPUMCTXCORE pCtx, unsigned reg64, uint64_t **ppReg);
739
740
741/**
742 * Try resolve an address into a symbol name.
743 *
744 * For use with DISFormatYasmEx(), DISFormatMasmEx() and DISFormatGasEx().
745 *
746 * @returns VBox status code.
747 * @retval VINF_SUCCESS on success, pszBuf contains the full symbol name.
748 * @retval VINF_BUFFER_OVERFLOW if pszBuf is too small the symbol name. The
749 * content of pszBuf is truncated and zero terminated.
750 * @retval VERR_SYMBOL_NOT_FOUND if no matching symbol was found for the address.
751 *
752 * @param pDis Pointer to the disassembler CPU state.
753 * @param u32Sel The selector value. Use DIS_FMT_SEL_IS_REG, DIS_FMT_SEL_GET_VALUE,
754 * DIS_FMT_SEL_GET_REG to access this.
755 * @param uAddress The segment address.
756 * @param pszBuf Where to store the symbol name
757 * @param cchBuf The size of the buffer.
758 * @param poff If not a perfect match, then this is where the offset from the return
759 * symbol to the specified address is returned.
760 * @param pvUser The user argument.
761 */
762typedef DECLCALLBACK(int) FNDISGETSYMBOL(PCDISSTATE pDis, uint32_t u32Sel, RTUINTPTR uAddress, char *pszBuf, size_t cchBuf, RTINTPTR *poff, void *pvUser);
763/** Pointer to a FNDISGETSYMBOL(). */
764typedef FNDISGETSYMBOL *PFNDISGETSYMBOL;
765
766/**
767 * Checks if the FNDISGETSYMBOL argument u32Sel is a register or not.
768 */
769#define DIS_FMT_SEL_IS_REG(u32Sel) ( !!((u32Sel) & RT_BIT(31)) )
770
771/**
772 * Extracts the selector value from the FNDISGETSYMBOL argument u32Sel.
773 * @returns Selector value.
774 */
775#define DIS_FMT_SEL_GET_VALUE(u32Sel) ( (RTSEL)(u32Sel) )
776
777/**
778 * Extracts the register number from the FNDISGETSYMBOL argument u32Sel.
779 * @returns USE_REG_CS, USE_REG_SS, USE_REG_DS, USE_REG_ES, USE_REG_FS or USE_REG_FS.
780 */
781#define DIS_FMT_SEL_GET_REG(u32Sel) ( ((u32Sel) >> 16) & 0xf )
782
783/** @internal */
784#define DIS_FMT_SEL_FROM_REG(uReg) ( ((uReg) << 16) | RT_BIT(31) | 0xffff )
785/** @internal */
786#define DIS_FMT_SEL_FROM_VALUE(Sel) ( (Sel) & 0xffff )
787
788
789/** @name Flags for use with DISFormatYasmEx(), DISFormatMasmEx() and DISFormatGasEx().
790 * @{
791 */
792/** Put the address to the right. */
793#define DIS_FMT_FLAGS_ADDR_RIGHT RT_BIT_32(0)
794/** Put the address to the left. */
795#define DIS_FMT_FLAGS_ADDR_LEFT RT_BIT_32(1)
796/** Put the address in comments.
797 * For some assemblers this implies placing it to the right. */
798#define DIS_FMT_FLAGS_ADDR_COMMENT RT_BIT_32(2)
799/** Put the instruction bytes to the right of the disassembly. */
800#define DIS_FMT_FLAGS_BYTES_RIGHT RT_BIT_32(3)
801/** Put the instruction bytes to the left of the disassembly. */
802#define DIS_FMT_FLAGS_BYTES_LEFT RT_BIT_32(4)
803/** Put the instruction bytes in comments.
804 * For some assemblers this implies placing the bytes to the right. */
805#define DIS_FMT_FLAGS_BYTES_COMMENT RT_BIT_32(5)
806/** Put the bytes in square brackets. */
807#define DIS_FMT_FLAGS_BYTES_BRACKETS RT_BIT_32(6)
808/** Put spaces between the bytes. */
809#define DIS_FMT_FLAGS_BYTES_SPACED RT_BIT_32(7)
810/** Display the relative +/- offset of branch instructions that uses relative addresses,
811 * and put the target address in parenthesis. */
812#define DIS_FMT_FLAGS_RELATIVE_BRANCH RT_BIT_32(8)
813/** Strict assembly. The assembly should, when ever possible, make the
814 * assembler reproduce the exact same binary. (Refers to the yasm
815 * strict keyword.) */
816#define DIS_FMT_FLAGS_STRICT RT_BIT_32(9)
817/** Checks if the given flags are a valid combination. */
818#define DIS_FMT_FLAGS_IS_VALID(fFlags) \
819 ( !((fFlags) & ~UINT32_C(0x000003ff)) \
820 && ((fFlags) & (DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT)) != (DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT) \
821 && ( !((fFlags) & DIS_FMT_FLAGS_ADDR_COMMENT) \
822 || (fFlags & (DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT)) ) \
823 && ((fFlags) & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT)) != (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT) \
824 && ( !((fFlags) & (DIS_FMT_FLAGS_BYTES_COMMENT | DIS_FMT_FLAGS_BYTES_BRACKETS)) \
825 || (fFlags & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT)) ) \
826 )
827/** @} */
828
829DISDECL(size_t) DISFormatYasm( PCDISSTATE pDis, char *pszBuf, size_t cchBuf);
830DISDECL(size_t) DISFormatYasmEx(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
831DISDECL(size_t) DISFormatMasm( PCDISSTATE pDis, char *pszBuf, size_t cchBuf);
832DISDECL(size_t) DISFormatMasmEx(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
833DISDECL(size_t) DISFormatGas( PCDISSTATE pDis, char *pszBuf, size_t cchBuf);
834DISDECL(size_t) DISFormatGasEx( PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
835
836/** @todo DISAnnotate(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, register
837 * reader, memory reader); */
838
839DISDECL(bool) DISFormatYasmIsOddEncoding(PDISSTATE pDis);
840
841
842RT_C_DECLS_END
843
844#endif
845
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette