VirtualBox

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

Last change on this file since 47095 was 46993, checked in by vboxsync, 12 years ago

DISPREFIX_REX_FLAGS is 0, so don't use it.

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