VirtualBox

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

Last change on this file since 41743 was 41743, checked in by vboxsync, 13 years ago

DISOPPARAM: s/index.reg_gen/Index.idxGenReg/ + doc

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

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