VirtualBox

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

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

DIS: Reducing the DISCPUMODE even more (200 bytes now) and making it have the same layout in all contexts. This is useful since it's used several places in the VM structure. Also a bunch of other cleanups.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 29.4 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.215389.xyz. 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::prefix_rex).
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::prefix_rex).
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.
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/** index in {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"}
195 * @{
196 */
197#define USE_REG_RAX 0
198#define USE_REG_RCX 1
199#define USE_REG_RDX 2
200#define USE_REG_RBX 3
201#define USE_REG_RSP 4
202#define USE_REG_RBP 5
203#define USE_REG_RSI 6
204#define USE_REG_RDI 7
205#define USE_REG_R8 8
206#define USE_REG_R9 9
207#define USE_REG_R10 10
208#define USE_REG_R11 11
209#define USE_REG_R12 12
210#define USE_REG_R13 13
211#define USE_REG_R14 14
212#define USE_REG_R15 15
213/** @} */
214
215/** index in {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI", "R8D", "R9D", "R10D", "R11D", "R12D", "R13D", "R14D", "R15D"}
216 * @{
217 */
218#define USE_REG_EAX 0
219#define USE_REG_ECX 1
220#define USE_REG_EDX 2
221#define USE_REG_EBX 3
222#define USE_REG_ESP 4
223#define USE_REG_EBP 5
224#define USE_REG_ESI 6
225#define USE_REG_EDI 7
226#define USE_REG_R8D 8
227#define USE_REG_R9D 9
228#define USE_REG_R10D 10
229#define USE_REG_R11D 11
230#define USE_REG_R12D 12
231#define USE_REG_R13D 13
232#define USE_REG_R14D 14
233#define USE_REG_R15D 15
234/** @} */
235
236/** index in {"AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI", "R8W", "R9W", "R10W", "R11W", "R12W", "R13W", "R14W", "R15W"}
237 * @{
238 */
239#define USE_REG_AX 0
240#define USE_REG_CX 1
241#define USE_REG_DX 2
242#define USE_REG_BX 3
243#define USE_REG_SP 4
244#define USE_REG_BP 5
245#define USE_REG_SI 6
246#define USE_REG_DI 7
247#define USE_REG_R8W 8
248#define USE_REG_R9W 9
249#define USE_REG_R10W 10
250#define USE_REG_R11W 11
251#define USE_REG_R12W 12
252#define USE_REG_R13W 13
253#define USE_REG_R14W 14
254#define USE_REG_R15W 15
255/** @} */
256
257/** index in {"AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH", "R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B", "SPL", "BPL", "SIL", "DIL"}
258 * @{
259 */
260#define USE_REG_AL 0
261#define USE_REG_CL 1
262#define USE_REG_DL 2
263#define USE_REG_BL 3
264#define USE_REG_AH 4
265#define USE_REG_CH 5
266#define USE_REG_DH 6
267#define USE_REG_BH 7
268#define USE_REG_R8B 8
269#define USE_REG_R9B 9
270#define USE_REG_R10B 10
271#define USE_REG_R11B 11
272#define USE_REG_R12B 12
273#define USE_REG_R13B 13
274#define USE_REG_R14B 14
275#define USE_REG_R15B 15
276#define USE_REG_SPL 16
277#define USE_REG_BPL 17
278#define USE_REG_SIL 18
279#define USE_REG_DIL 19
280
281/** @} */
282
283/** index in {ES, CS, SS, DS, FS, GS}
284 * @{
285 */
286typedef enum
287{
288 DIS_SELREG_ES = 0,
289 DIS_SELREG_CS = 1,
290 DIS_SELREG_SS = 2,
291 DIS_SELREG_DS = 3,
292 DIS_SELREG_FS = 4,
293 DIS_SELREG_GS = 5,
294 /** The usual 32-bit paranoia. */
295 DIS_SEGREG_32BIT_HACK = 0x7fffffff
296} DIS_SELREG;
297/** @} */
298
299#define USE_REG_FP0 0
300#define USE_REG_FP1 1
301#define USE_REG_FP2 2
302#define USE_REG_FP3 3
303#define USE_REG_FP4 4
304#define USE_REG_FP5 5
305#define USE_REG_FP6 6
306#define USE_REG_FP7 7
307
308#define USE_REG_CR0 0
309#define USE_REG_CR1 1
310#define USE_REG_CR2 2
311#define USE_REG_CR3 3
312#define USE_REG_CR4 4
313#define USE_REG_CR8 8
314
315#define USE_REG_DR0 0
316#define USE_REG_DR1 1
317#define USE_REG_DR2 2
318#define USE_REG_DR3 3
319#define USE_REG_DR4 4
320#define USE_REG_DR5 5
321#define USE_REG_DR6 6
322#define USE_REG_DR7 7
323
324#define USE_REG_MMX0 0
325#define USE_REG_MMX1 1
326#define USE_REG_MMX2 2
327#define USE_REG_MMX3 3
328#define USE_REG_MMX4 4
329#define USE_REG_MMX5 5
330#define USE_REG_MMX6 6
331#define USE_REG_MMX7 7
332
333#define USE_REG_XMM0 0
334#define USE_REG_XMM1 1
335#define USE_REG_XMM2 2
336#define USE_REG_XMM3 3
337#define USE_REG_XMM4 4
338#define USE_REG_XMM5 5
339#define USE_REG_XMM6 6
340#define USE_REG_XMM7 7
341/** @todo missing XMM8-XMM15 */
342
343/** Used by DISQueryParamVal & EMIQueryParamVal
344 * @{
345 */
346#define PARAM_VAL8 RT_BIT(0)
347#define PARAM_VAL16 RT_BIT(1)
348#define PARAM_VAL32 RT_BIT(2)
349#define PARAM_VAL64 RT_BIT(3)
350#define PARAM_VALFARPTR16 RT_BIT(4)
351#define PARAM_VALFARPTR32 RT_BIT(5)
352
353#define PARMTYPE_REGISTER 1
354#define PARMTYPE_ADDRESS 2
355#define PARMTYPE_IMMEDIATE 3
356
357typedef struct
358{
359 uint32_t type;
360 uint32_t size;
361 uint64_t flags;
362
363 union
364 {
365 uint8_t val8;
366 uint16_t val16;
367 uint32_t val32;
368 uint64_t val64;
369
370 struct
371 {
372 uint16_t sel;
373 uint32_t offset;
374 } farptr;
375 } val;
376
377} OP_PARAMVAL;
378/** Pointer to opcode parameter value. */
379typedef OP_PARAMVAL *POP_PARAMVAL;
380
381typedef enum
382{
383 PARAM_DEST,
384 PARAM_SOURCE
385} PARAM_TYPE;
386
387/** @} */
388
389/**
390 * Operand Parameter.
391 */
392typedef struct DISOPPARAM
393{
394 uint64_t parval;
395 /** A combination of DISUSE_XXX. */
396 uint64_t fUse;
397 union
398 {
399 int64_t i64;
400 int32_t i32;
401 int32_t i16;
402 int32_t i8;
403 uint64_t u64;
404 uint32_t u32;
405 uint32_t u16;
406 uint32_t u8;
407 } uDisp;
408 int32_t param;
409
410 union
411 {
412 uint8_t reg_gen;
413 /** ST(0) - ST(7) */
414 uint8_t reg_fp;
415 /** MMX0 - MMX7 */
416 uint8_t reg_mmx;
417 /** XMM0 - XMM7 */
418 uint8_t reg_xmm;
419 /** {ES, CS, SS, DS, FS, GS} (DIS_SELREG). */
420 uint8_t reg_seg;
421 /** TR0-TR7 (?) */
422 uint8_t reg_test;
423 /** CR0-CR4 */
424 uint8_t reg_ctrl;
425 /** DR0-DR7 */
426 uint8_t reg_dbg;
427 } base;
428 union
429 {
430 uint8_t reg_gen;
431 } index;
432
433 /** 2, 4 or 8. */
434 uint8_t scale;
435 /** Parameter size. */
436 uint8_t cb;
437} DISOPPARAM;
438AssertCompileSize(DISOPPARAM, 32);
439/** Pointer to opcode parameter. */
440typedef DISOPPARAM *PDISOPPARAM;
441/** Pointer to opcode parameter. */
442typedef const DISOPPARAM *PCOP_PARAMETER;
443
444
445/** Pointer to const opcode. */
446typedef const struct DISOPCODE *PCDISOPCODE;
447
448/**
449 * Callback for reading opcode bytes.
450 *
451 * @param pDisState Pointer to the CPU state. The primary user argument
452 * can be retrived from DISCPUSTATE::apvUserData[0]. If
453 * more is required these can be passed in the
454 * subsequent slots.
455 * @param pbDst Pointer to output buffer.
456 * @param uSrcAddr The address to start reading at.
457 * @param cbToRead The number of bytes to read.
458 */
459typedef DECLCALLBACK(int) FNDISREADBYTES(PDISCPUSTATE pDisState, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead);
460/** Pointer to a opcode byte reader. */
461typedef FNDISREADBYTES *PFNDISREADBYTES;
462
463/** Parser callback.
464 * @remark no DECLCALLBACK() here because it's considered to be internal (really, I'm too lazy to update all the functions). */
465typedef unsigned FNDISPARSE(RTUINTPTR pu8CodeBlock, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu);
466typedef FNDISPARSE *PFNDISPARSE;
467typedef PFNDISPARSE const *PCPFNDISPARSE;
468
469typedef struct DISCPUSTATE
470{
471 /* Because of apvUserData[1] and apvUserData[2], put the less frequently
472 used bits at the top for now. (Might be better off in the middle?) */
473 DISOPPARAM param3;
474 DISOPPARAM param2;
475 DISOPPARAM param1;
476
477 /* off: 0x060 (96) */
478 /** ModRM fields. */
479 union
480 {
481 /** Bitfield view */
482 struct
483 {
484 unsigned Rm : 4;
485 unsigned Reg : 4;
486 unsigned Mod : 2;
487 } Bits;
488 /** unsigned view */
489 unsigned u;
490 } ModRM;
491 /** SIB fields. */
492 union
493 {
494 /** Bitfield view */
495 struct
496 {
497 unsigned Base : 4;
498 unsigned Index : 4;
499 unsigned Scale : 2;
500 } Bits;
501 /** unsigned view */
502 unsigned u;
503 } SIB;
504 int32_t i32SibDisp;
505
506 /* off: 0x06c (108) */
507 /** The CPU mode (DISCPUMODE). */
508 uint8_t mode;
509 /** The addressing mode (DISCPUMODE). */
510 uint8_t addrmode;
511 /** The operand mode (DISCPUMODE). */
512 uint8_t opmode;
513 /** Per instruction prefix settings. */
514 uint8_t prefix;
515 /* off: 0x070 (112) */
516 /** REX prefix value (64 bits only). */
517 uint8_t prefix_rex;
518 /** Segment prefix value (DIS_SELREG). */
519 uint8_t idxSegPrefix;
520 /** Last prefix byte (for SSE2 extension tables). */
521 uint8_t lastprefix;
522 /** First opcode byte of instruction. */
523 uint8_t opcode;
524 /* off: 0x074 (116) */
525 /** The size of the prefix bytes. */
526 uint8_t cbPrefix;
527 /** The instruction size. */
528 uint8_t opsize;
529 uint8_t abUnused[2];
530 /* off: 0x078 (120) */
531 /** Return code set by a worker function like the opcode bytes readers. */
532 int32_t rc;
533 /** Internal: instruction filter */
534 uint32_t fFilter;
535 /* off: 0x080 (128) */
536 /** Internal: pointer to disassembly function table */
537 PCPFNDISPARSE pfnDisasmFnTable;
538#if ARCH_BITS == 32
539 uint32_t uPtrPadding1;
540#endif
541 /** Pointer to the current instruction. */
542 PCDISOPCODE pCurInstr;
543#if ARCH_BITS == 32
544 uint32_t uPtrPadding2;
545#endif
546 /* off: 0x090 (144) */
547 /** The address of the instruction. */
548 RTUINTPTR uInstrAddr;
549 /* off: 0x098 (152) */
550 /** Optional read function */
551 PFNDISREADBYTES pfnReadBytes;
552#if ARCH_BITS == 32
553 uint32_t uPadding3;
554#endif
555 /* off: 0x0a0 (160) */
556 /** The instruction bytes. */
557 uint8_t abInstr[16];
558 /* off: 0x0b0 (176) */
559 /** User data slots for the read callback. The first entry is used for the
560 * pvUser argument, the rest are up for grabs.
561 * @remarks This must come last so that we can memset everything before this. */
562 void *apvUserData[3];
563#if ARCH_BITS == 32
564 uint32_t auPadding4[3];
565#endif
566} DISCPUSTATE;
567
568/** The storage padding sufficient to hold the largest DISCPUSTATE in all
569 * contexts (R3, R0 and RC). Used various places in the VMM internals. */
570#define DISCPUSTATE_PADDING_SIZE (HC_ARCH_BITS == 64 ? 0x1a0 : 0x180)
571
572/** Opcode. */
573#pragma pack(4)
574typedef struct DISOPCODE
575{
576#ifndef DIS_CORE_ONLY
577 const char *pszOpcode;
578#endif
579 uint8_t idxParse1;
580 uint8_t idxParse2;
581 uint8_t idxParse3;
582 uint16_t opcode;
583 uint16_t param1;
584 uint16_t param2;
585 uint16_t param3;
586 uint32_t optype;
587} DISOPCODE;
588#pragma pack()
589
590
591DISDECL(int) DISInstrToStr(void const *pvInstr, DISCPUMODE enmCpuMode,
592 PDISCPUSTATE pCpu, uint32_t *pcbInstr, char *pszOutput, size_t cbOutput);
593DISDECL(int) DISInstrToStrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
594 PDISCPUSTATE pCpu, uint32_t *pcbInstr, char *pszOutput, size_t cbOutput);
595DISDECL(int) DISInstrToStrEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode,
596 PFNDISREADBYTES pfnReadBytes, void *pvUser, uint32_t uFilter,
597 PDISCPUSTATE pCpu, uint32_t *pcbInstr, char *pszOutput, size_t cbOutput);
598
599DISDECL(int) DISInstr(void const *pvInstr, DISCPUMODE enmCpuMode, PDISCPUSTATE pCpu, uint32_t *pcbInstr);
600DISDECL(int) DISInstrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
601 PDISCPUSTATE pCpu, uint32_t *pcbInstr);
602DISDECL(int) DISInstEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t uFilter,
603 PFNDISREADBYTES pfnReadBytes, void *pvUser,
604 PDISCPUSTATE pCpu, uint32_t *pcbInstr);
605
606DISDECL(int) DISGetParamSize(PDISCPUSTATE pCpu, PDISOPPARAM pParam);
607DISDECL(DIS_SELREG) DISDetectSegReg(PDISCPUSTATE pCpu, PDISOPPARAM pParam);
608DISDECL(uint8_t) DISQuerySegPrefixByte(PDISCPUSTATE pCpu);
609
610DISDECL(int) DISQueryParamVal(PCPUMCTXCORE pCtx, PDISCPUSTATE pCpu, PDISOPPARAM pParam, POP_PARAMVAL pParamVal, PARAM_TYPE parmtype);
611DISDECL(int) DISQueryParamRegPtr(PCPUMCTXCORE pCtx, PDISCPUSTATE pCpu, PDISOPPARAM pParam, void **ppReg, size_t *pcbSize);
612
613DISDECL(int) DISFetchReg8(PCCPUMCTXCORE pCtx, unsigned reg8, uint8_t *pVal);
614DISDECL(int) DISFetchReg16(PCCPUMCTXCORE pCtx, unsigned reg16, uint16_t *pVal);
615DISDECL(int) DISFetchReg32(PCCPUMCTXCORE pCtx, unsigned reg32, uint32_t *pVal);
616DISDECL(int) DISFetchReg64(PCCPUMCTXCORE pCtx, unsigned reg64, uint64_t *pVal);
617DISDECL(int) DISFetchRegSeg(PCCPUMCTXCORE pCtx, DIS_SELREG sel, RTSEL *pVal);
618DISDECL(int) DISFetchRegSegEx(PCCPUMCTXCORE pCtx, DIS_SELREG sel, RTSEL *pVal, PCPUMSELREGHID *ppSelHidReg);
619DISDECL(int) DISWriteReg8(PCPUMCTXCORE pRegFrame, unsigned reg8, uint8_t val8);
620DISDECL(int) DISWriteReg16(PCPUMCTXCORE pRegFrame, unsigned reg32, uint16_t val16);
621DISDECL(int) DISWriteReg32(PCPUMCTXCORE pRegFrame, unsigned reg32, uint32_t val32);
622DISDECL(int) DISWriteReg64(PCPUMCTXCORE pRegFrame, unsigned reg64, uint64_t val64);
623DISDECL(int) DISWriteRegSeg(PCPUMCTXCORE pCtx, DIS_SELREG sel, RTSEL val);
624DISDECL(int) DISPtrReg8(PCPUMCTXCORE pCtx, unsigned reg8, uint8_t **ppReg);
625DISDECL(int) DISPtrReg16(PCPUMCTXCORE pCtx, unsigned reg16, uint16_t **ppReg);
626DISDECL(int) DISPtrReg32(PCPUMCTXCORE pCtx, unsigned reg32, uint32_t **ppReg);
627DISDECL(int) DISPtrReg64(PCPUMCTXCORE pCtx, unsigned reg64, uint64_t **ppReg);
628
629
630/**
631 * Try resolve an address into a symbol name.
632 *
633 * For use with DISFormatYasmEx(), DISFormatMasmEx() and DISFormatGasEx().
634 *
635 * @returns VBox status code.
636 * @retval VINF_SUCCESS on success, pszBuf contains the full symbol name.
637 * @retval VINF_BUFFER_OVERFLOW if pszBuf is too small the symbol name. The
638 * content of pszBuf is truncated and zero terminated.
639 * @retval VERR_SYMBOL_NOT_FOUND if no matching symbol was found for the address.
640 *
641 * @param pCpu Pointer to the disassembler CPU state.
642 * @param u32Sel The selector value. Use DIS_FMT_SEL_IS_REG, DIS_FMT_SEL_GET_VALUE,
643 * DIS_FMT_SEL_GET_REG to access this.
644 * @param uAddress The segment address.
645 * @param pszBuf Where to store the symbol name
646 * @param cchBuf The size of the buffer.
647 * @param poff If not a perfect match, then this is where the offset from the return
648 * symbol to the specified address is returned.
649 * @param pvUser The user argument.
650 */
651typedef DECLCALLBACK(int) FNDISGETSYMBOL(PCDISCPUSTATE pCpu, uint32_t u32Sel, RTUINTPTR uAddress, char *pszBuf, size_t cchBuf, RTINTPTR *poff, void *pvUser);
652/** Pointer to a FNDISGETSYMBOL(). */
653typedef FNDISGETSYMBOL *PFNDISGETSYMBOL;
654
655/**
656 * Checks if the FNDISGETSYMBOL argument u32Sel is a register or not.
657 */
658#define DIS_FMT_SEL_IS_REG(u32Sel) ( !!((u32Sel) & RT_BIT(31)) )
659
660/**
661 * Extracts the selector value from the FNDISGETSYMBOL argument u32Sel.
662 * @returns Selector value.
663 */
664#define DIS_FMT_SEL_GET_VALUE(u32Sel) ( (RTSEL)(u32Sel) )
665
666/**
667 * Extracts the register number from the FNDISGETSYMBOL argument u32Sel.
668 * @returns USE_REG_CS, USE_REG_SS, USE_REG_DS, USE_REG_ES, USE_REG_FS or USE_REG_FS.
669 */
670#define DIS_FMT_SEL_GET_REG(u32Sel) ( ((u32Sel) >> 16) & 0xf )
671
672/** @internal */
673#define DIS_FMT_SEL_FROM_REG(uReg) ( ((uReg) << 16) | RT_BIT(31) | 0xffff )
674/** @internal */
675#define DIS_FMT_SEL_FROM_VALUE(Sel) ( (Sel) & 0xffff )
676
677
678/** @name Flags for use with DISFormatYasmEx(), DISFormatMasmEx() and DISFormatGasEx().
679 * @{
680 */
681/** Put the address to the right. */
682#define DIS_FMT_FLAGS_ADDR_RIGHT RT_BIT_32(0)
683/** Put the address to the left. */
684#define DIS_FMT_FLAGS_ADDR_LEFT RT_BIT_32(1)
685/** Put the address in comments.
686 * For some assemblers this implies placing it to the right. */
687#define DIS_FMT_FLAGS_ADDR_COMMENT RT_BIT_32(2)
688/** Put the instruction bytes to the right of the disassembly. */
689#define DIS_FMT_FLAGS_BYTES_RIGHT RT_BIT_32(3)
690/** Put the instruction bytes to the left of the disassembly. */
691#define DIS_FMT_FLAGS_BYTES_LEFT RT_BIT_32(4)
692/** Put the instruction bytes in comments.
693 * For some assemblers this implies placing the bytes to the right. */
694#define DIS_FMT_FLAGS_BYTES_COMMENT RT_BIT_32(5)
695/** Put the bytes in square brackets. */
696#define DIS_FMT_FLAGS_BYTES_BRACKETS RT_BIT_32(6)
697/** Put spaces between the bytes. */
698#define DIS_FMT_FLAGS_BYTES_SPACED RT_BIT_32(7)
699/** Display the relative +/- offset of branch instructions that uses relative addresses,
700 * and put the target address in parenthesis. */
701#define DIS_FMT_FLAGS_RELATIVE_BRANCH RT_BIT_32(8)
702/** Strict assembly. The assembly should, when ever possible, make the
703 * assembler reproduce the exact same binary. (Refers to the yasm
704 * strict keyword.) */
705#define DIS_FMT_FLAGS_STRICT RT_BIT_32(9)
706/** Checks if the given flags are a valid combination. */
707#define DIS_FMT_FLAGS_IS_VALID(fFlags) \
708 ( !((fFlags) & ~UINT32_C(0x000003ff)) \
709 && ((fFlags) & (DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT)) != (DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT) \
710 && ( !((fFlags) & DIS_FMT_FLAGS_ADDR_COMMENT) \
711 || (fFlags & (DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT)) ) \
712 && ((fFlags) & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT)) != (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT) \
713 && ( !((fFlags) & (DIS_FMT_FLAGS_BYTES_COMMENT | DIS_FMT_FLAGS_BYTES_BRACKETS)) \
714 || (fFlags & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT)) ) \
715 )
716/** @} */
717
718DISDECL(size_t) DISFormatYasm( PCDISCPUSTATE pCpu, char *pszBuf, size_t cchBuf);
719DISDECL(size_t) DISFormatYasmEx(PCDISCPUSTATE pCpu, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
720DISDECL(size_t) DISFormatMasm( PCDISCPUSTATE pCpu, char *pszBuf, size_t cchBuf);
721DISDECL(size_t) DISFormatMasmEx(PCDISCPUSTATE pCpu, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
722DISDECL(size_t) DISFormatGas( PCDISCPUSTATE pCpu, char *pszBuf, size_t cchBuf);
723DISDECL(size_t) DISFormatGasEx( PCDISCPUSTATE pCpu, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
724
725/** @todo DISAnnotate(PCDISCPUSTATE pCpu, char *pszBuf, size_t cchBuf, register reader, memory reader); */
726
727DISDECL(bool) DISFormatYasmIsOddEncoding(PDISCPUSTATE pCpu);
728
729
730RT_C_DECLS_END
731
732#endif
733
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