VirtualBox

root/trunk/include/VBox/dis.h

Revision 10273, 29.1 kB (checked in by vboxsync, 5 months ago)

USE_IMMEDIATE64_SX8 added

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /** @file
2  * DIS - The VirtualBox Disassembler.
3  */
4
5 /*
6  * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
26  * Clara, CA 95054 USA or visit http://www.sun.com if you need
27  * additional information or have any questions.
28  */
29
30 #ifndef ___VBox_disasm_h
31 #define ___VBox_disasm_h
32
33 #include <VBox/cdefs.h>
34 #include <VBox/types.h>
35 #include <VBox/disopcode.h>
36
37 #if defined(__L4ENV__)
38 #include <setjmp.h>
39 #endif
40
41 __BEGIN_DECLS
42
43
44 /** CPU mode flags (DISCPUSTATE::mode).
45  * @{
46  */
47 typedef enum
48 {
49     CPUMODE_16BIT = 1,
50     CPUMODE_32BIT = 2,
51     CPUMODE_64BIT = 3,
52     /** hack forcing the size of the enum to 32-bits. */
53     CPUMODE_MAKE_32BIT_HACK = 0x7fffffff
54 } DISCPUMODE;
55 /** @} */
56
57 /** Prefix byte flags
58  * @{
59  */
60 #define PREFIX_NONE                     0
61 /** non-default address size. */
62 #define PREFIX_ADDRSIZE                 RT_BIT(0)
63 /** non-default operand size. */
64 #define PREFIX_OPSIZE                   RT_BIT(1)
65 /** lock prefix. */
66 #define PREFIX_LOCK                     RT_BIT(2)
67 /** segment prefix. */
68 #define PREFIX_SEG                      RT_BIT(3)
69 /** rep(e) prefix (not a prefix, but we'll treat is as one). */
70 #define PREFIX_REP                      RT_BIT(4)
71 /** rep(e) prefix (not a prefix, but we'll treat is as one). */
72 #define PREFIX_REPNE                    RT_BIT(5)
73 /** REX prefix (64 bits) */
74 #define PREFIX_REX                      RT_BIT(6)
75 /** @} */
76
77 /** 64 bits prefix byte flags
78  * @{
79  */
80 #define PREFIX_REX_OP_2_FLAGS(a)        (a - OP_PARM_REX_START)
81 #define PREFIX_REX_FLAGS                PREFIX_REX_OP_2_FLAGS(OP_PARM_REX)
82 #define PREFIX_REX_FLAGS_B              PREFIX_REX_OP_2_FLAGS(OP_PARM_REX_B)
83 #define PREFIX_REX_FLAGS_X              PREFIX_REX_OP_2_FLAGS(OP_PARM_REX_X)
84 #define PREFIX_REX_FLAGS_XB             PREFIX_REX_OP_2_FLAGS(OP_PARM_REX_XB)
85 #define PREFIX_REX_FLAGS_R              PREFIX_REX_OP_2_FLAGS(OP_PARM_REX_R)
86 #define PREFIX_REX_FLAGS_RB             PREFIX_REX_OP_2_FLAGS(OP_PARM_REX_RB)
87 #define PREFIX_REX_FLAGS_RX             PREFIX_REX_OP_2_FLAGS(OP_PARM_REX_RX)
88 #define PREFIX_REX_FLAGS_RXB            PREFIX_REX_OP_2_FLAGS(OP_PARM_REX_RXB)
89 #define PREFIX_REX_FLAGS_W              PREFIX_REX_OP_2_FLAGS(OP_PARM_REX_W)
90 #define PREFIX_REX_FLAGS_WB             PREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WB)
91 #define PREFIX_REX_FLAGS_WX             PREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WX)
92 #define PREFIX_REX_FLAGS_WXB            PREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WXB)
93 #define PREFIX_REX_FLAGS_WR             PREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WR)
94 #define PREFIX_REX_FLAGS_WRB            PREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WRB)
95 #define PREFIX_REX_FLAGS_WRX            PREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WRX)
96 #define PREFIX_REX_FLAGS_WRXB           PREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WRXB)
97 /** @} */
98
99 /**
100  * Operand type.
101  */
102 #define OPTYPE_INVALID                  RT_BIT(0)
103 #define OPTYPE_HARMLESS                 RT_BIT(1)
104 #define OPTYPE_CONTROLFLOW              RT_BIT(2)
105 #define OPTYPE_POTENTIALLY_DANGEROUS    RT_BIT(3)
106 #define OPTYPE_DANGEROUS                RT_BIT(4)
107 #define OPTYPE_PORTIO                   RT_BIT(5)
108 #define OPTYPE_PRIVILEGED               RT_BIT(6)
109 #define OPTYPE_PRIVILEGED_NOTRAP        RT_BIT(7)
110 #define OPTYPE_UNCOND_CONTROLFLOW       RT_BIT(8)
111 #define OPTYPE_RELATIVE_CONTROLFLOW     RT_BIT(9)
112 #define OPTYPE_COND_CONTROLFLOW         RT_BIT(10)
113 #define OPTYPE_INTERRUPT                RT_BIT(11)
114 #define OPTYPE_ILLEGAL                  RT_BIT(12)
115 #define OPTYPE_RRM_DANGEROUS            RT_BIT(14)  /**< Some additional dangerouse ones when recompiling raw r0. */
116 #define OPTYPE_RRM_DANGEROUS_16         RT_BIT(15)  /**< Some additional dangerouse ones when recompiling 16-bit raw r0. */
117 #define OPTYPE_RRM_MASK                 (OPTYPE_RRM_DANGEROUS | OPTYPE_RRM_DANGEROUS_16)
118 #define OPTYPE_INHIBIT_IRQS             RT_BIT(16)  /**< Will or can inhibit irqs (sti, pop ss, mov ss) */
119 #define OPTYPE_PORTIO_READ              RT_BIT(17)
120 #define OPTYPE_PORTIO_WRITE             RT_BIT(18)
121 #define OPTYPE_INVALID_64               RT_BIT(19)  /**< Invalid in 64 bits mode */
122 #define OPTYPE_ONLY_64                  RT_BIT(20)  /**< Only valid in 64 bits mode */
123 #define OPTYPE_DEFAULT_64_OP_SIZE       RT_BIT(21)  /**< Default 64 bits operand size */
124 #define OPTYPE_FORCED_64_OP_SIZE        RT_BIT(22)  /**< Forced 64 bits operand size; regardless of prefix bytes */
125 #define OPTYPE_REXB_EXTENDS_OPREG       RT_BIT(23)  /**< REX.B extends the register field in the opcode byte */
126 #define OPTYPE_ALL                      (0xffffffff)
127
128 /** Parameter usage flags.
129  * @{
130  */
131 #define USE_BASE                        RT_BIT_64(0)
132 #define USE_INDEX                       RT_BIT_64(1)
133 #define USE_SCALE                       RT_BIT_64(2)
134 #define USE_REG_GEN8                    RT_BIT_64(3)
135 #define USE_REG_GEN16                   RT_BIT_64(4)
136 #define USE_REG_GEN32                   RT_BIT_64(5)
137 #define USE_REG_GEN64                   RT_BIT_64(6)
138 #define USE_REG_FP                      RT_BIT_64(7)
139 #define USE_REG_MMX                     RT_BIT_64(8)
140 #define USE_REG_XMM                     RT_BIT_64(9)
141 #define USE_REG_CR                      RT_BIT_64(10)
142 #define USE_REG_DBG                     RT_BIT_64(11)
143 #define USE_REG_SEG                     RT_BIT_64(12)
144 #define USE_REG_TEST                    RT_BIT_64(13)
145 #define USE_DISPLACEMENT8               RT_BIT_64(14)
146 #define USE_DISPLACEMENT16              RT_BIT_64(15)
147 #define USE_DISPLACEMENT32              RT_BIT_64(16)
148 #define USE_DISPLACEMENT64              RT_BIT_64(17)
149 #define USE_RIPDISPLACEMENT32           RT_BIT_64(18)
150 #define USE_IMMEDIATE8                  RT_BIT_64(19)
151 #define USE_IMMEDIATE8_REL              RT_BIT_64(20)
152 #define USE_IMMEDIATE16                 RT_BIT_64(21)
153 #define USE_IMMEDIATE16_REL             RT_BIT_64(22)
154 #define USE_IMMEDIATE32                 RT_BIT_64(23)
155 #define USE_IMMEDIATE32_REL             RT_BIT_64(24)
156 #define USE_IMMEDIATE64                 RT_BIT_64(25)
157 #define USE_IMMEDIATE64_REL             RT_BIT_64(26)
158 #define USE_IMMEDIATE_ADDR_0_32         RT_BIT_64(27)
159 #define USE_IMMEDIATE_ADDR_16_32        RT_BIT_64(28)
160 #define USE_IMMEDIATE_ADDR_0_16         RT_BIT_64(29)
161 #define USE_IMMEDIATE_ADDR_16_16        RT_BIT_64(30)
162 /** DS:ESI */
163 #define USE_POINTER_DS_BASED            RT_BIT_64(31)
164 /** ES:EDI */
165 #define USE_POINTER_ES_BASED            RT_BIT_64(32)
166 #define USE_IMMEDIATE16_SX8             RT_BIT_64(33)
167 #define USE_IMMEDIATE32_SX8             RT_BIT_64(34)
168 #define USE_IMMEDIATE64_SX8             RT_BIT_64(36)
169
170 #define USE_IMMEDIATE                   (USE_IMMEDIATE8|USE_IMMEDIATE16|USE_IMMEDIATE32|USE_IMMEDIATE64|USE_IMMEDIATE8_REL|USE_IMMEDIATE16_REL|USE_IMMEDIATE32_REL|USE_IMMEDIATE64_REL|USE_IMMEDIATE_ADDR_0_32|USE_IMMEDIATE_ADDR_16_32|USE_IMMEDIATE_ADDR_0_16|USE_IMMEDIATE_ADDR_16_16|USE_IMMEDIATE16_SX8|USE_IMMEDIATE32_SX8|USE_IMMEDIATE64_SX8)
171
172 #define DIS_IS_EFFECTIVE_ADDR(flags)    !!((flags) & (USE_BASE|USE_INDEX|USE_DISPLACEMENT32|USE_DISPLACEMENT64|USE_DISPLACEMENT16|USE_DISPLACEMENT8|USE_RIPDISPLACEMENT32))
173 /** @} */
174
175 /** index in {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"}
176  * @{
177  */
178 #define USE_REG_RAX                     0
179 #define USE_REG_RCX                     1
180 #define USE_REG_RDX                     2
181 #define USE_REG_RBX                     3
182 #define USE_REG_RSP                     4
183 #define USE_REG_RBP                     5
184 #define USE_REG_RSI                     6
185 #define USE_REG_RDI                     7
186 #define USE_REG_R8                      8
187 #define USE_REG_R9                      9
188 #define USE_REG_R10                     10
189 #define USE_REG_R11                     11
190 #define USE_REG_R12                     12
191 #define USE_REG_R13                     13
192 #define USE_REG_R14                     14
193 #define USE_REG_R15                     15
194 /** @} */
195
196 /** index in {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI", "R8D", "R9D", "R10D", "R11D", "R12D", "R13D", "R14D", "R15D"}
197  * @{
198  */
199 #define USE_REG_EAX                     0
200 #define USE_REG_ECX                     1
201 #define USE_REG_EDX                     2
202 #define USE_REG_EBX                     3
203 #define USE_REG_ESP                     4
204 #define USE_REG_EBP                     5
205 #define USE_REG_ESI                     6
206 #define USE_REG_EDI                     7
207 #define USE_REG_R8D                     8
208 #define USE_REG_R9D                     9
209 #define USE_REG_R10D                    10
210 #define USE_REG_R11D                    11
211 #define USE_REG_R12D                    12
212 #define USE_REG_R13D                    13
213 #define USE_REG_R14D                    14
214 #define USE_REG_R15D                    15
215
216 /** @} */
217 /** index in {"AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI", "R8W", "R9W", "R10W", "R11W", "R12W", "R13W", "R14W", "R15W"}
218  * @{
219  */
220 #define USE_REG_AX                      0
221 #define USE_REG_CX                      1
222 #define USE_REG_DX                      2
223 #define USE_REG_BX                      3
224 #define USE_REG_SP                      4
225 #define USE_REG_BP                      5
226 #define USE_REG_SI                      6
227 #define USE_REG_DI                      7
228 #define USE_REG_R8W                     8
229 #define USE_REG_R9W                     9
230 #define USE_REG_R10W                    10
231 #define USE_REG_R11W                    11
232 #define USE_REG_R12W                    12
233 #define USE_REG_R13W                    13
234 #define USE_REG_R14W                    14
235 #define USE_REG_R15W                    15
236 /** @} */
237
238 /** index in {"AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH", "R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B", "SPL", "BPL", "SIL", "DIL"}
239  * @{
240  */
241 #define USE_REG_AL                      0
242 #define USE_REG_CL                      1
243 #define USE_REG_DL                      2
244 #define USE_REG_BL                      3
245 #define USE_REG_AH                      4
246 #define USE_REG_CH                      5
247 #define USE_REG_DH                      6
248 #define USE_REG_BH                      7
249 #define USE_REG_R8B                     8
250 #define USE_REG_R9B                     9
251 #define USE_REG_R10B                    10
252 #define USE_REG_R11B                    11
253 #define USE_REG_R12B                    12
254 #define USE_REG_R13B                    13
255 #define USE_REG_R14B                    14
256 #define USE_REG_R15B                    15
257 #define USE_REG_SPL                     16
258 #define USE_REG_BPL                     17
259 #define USE_REG_SIL                     18
260 #define USE_REG_DIL                     19
261
262 /** @} */
263
264 /** index in {ES, CS, SS, DS, FS, GS}
265  * @{
266  */
267 typedef enum
268 {
269     DIS_SELREG_ES = 0,
270     DIS_SELREG_CS = 1,
271     DIS_SELREG_SS = 2,
272     DIS_SELREG_DS = 3,
273     DIS_SELREG_FS = 4,
274     DIS_SELREG_GS = 5,
275     /** The usual 32-bit paranoia. */
276     DIS_SEGREG_32BIT_HACK = 0x7fffffff
277 } DIS_SELREG;
278 /** @} */
279
280 #define USE_REG_FP0                     0
281 #define USE_REG_FP1                     1
282 #define USE_REG_FP2                     2
283 #define USE_REG_FP3                     3
284 #define USE_REG_FP4                     4
285 #define USE_REG_FP5                     5
286 #define USE_REG_FP6                     6
287 #define USE_REG_FP7                     7
288
289 #define USE_REG_CR0                     0
290 #define USE_REG_CR1                     1
291 #define USE_REG_CR2                     2
292 #define USE_REG_CR3                     3
293 #define USE_REG_CR4                     4
294 #define USE_REG_CR8                     8
295
296 #define USE_REG_DR0                     0
297 #define USE_REG_DR1                     1
298 #define USE_REG_DR2                     2
299 #define USE_REG_DR3                     3
300 #define USE_REG_DR4                     4
301 #define USE_REG_DR5                     5
302 #define USE_REG_DR6                     6
303 #define USE_REG_DR7                     7
304
305 #define USE_REG_MMX0                    0
306 #define USE_REG_MMX1                    1
307 #define USE_REG_MMX2                    2
308 #define USE_REG_MMX3                    3
309 #define USE_REG_MMX4                    4
310 #define USE_REG_MMX5                    5
311 #define USE_REG_MMX6                    6
312 #define USE_REG_MMX7                    7
313
314 #define USE_REG_XMM0                    0
315 #define USE_REG_XMM1                    1
316 #define USE_REG_XMM2                    2
317 #define USE_REG_XMM3                    3
318 #define USE_REG_XMM4                    4
319 #define USE_REG_XMM5                    5
320 #define USE_REG_XMM6                    6
321 #define USE_REG_XMM7                    7
322
323 /** Used by DISQueryParamVal & EMIQueryParamVal
324  * @{
325  */
326 #define PARAM_VAL8             RT_BIT(0)
327 #define PARAM_VAL16            RT_BIT(1)
328 #define PARAM_VAL32            RT_BIT(2)
329 #define PARAM_VAL64            RT_BIT(3)
330 #define PARAM_VALFARPTR16      RT_BIT(4)
331 #define PARAM_VALFARPTR32      RT_BIT(5)
332
333 #define PARMTYPE_REGISTER      1
334 #define PARMTYPE_ADDRESS       2
335 #define PARMTYPE_IMMEDIATE     3
336
337 typedef struct
338 {
339     uint32_t        type;
340     uint32_t        size;
341     uint64_t        flags;
342
343     union
344     {
345         uint8_t     val8;
346         uint16_t    val16;
347         uint32_t    val32;
348         uint64_t    val64;
349
350         struct
351         {
352             uint16_t sel;
353             uint32_t offset;
354         } farptr;
355     } val;
356
357 } OP_PARAMVAL;
358 /** Pointer to opcode parameter value. */
359 typedef OP_PARAMVAL *POP_PARAMVAL;
360
361 typedef enum
362 {
363     PARAM_DEST,
364     PARAM_SOURCE
365 } PARAM_TYPE;
366
367 /** @} */
368
369 /**
370  * Operand Parameter.
371  */
372 typedef struct _OP_PARAMETER
373 {
374     /** @todo switch param and parval and move disp64 and flags up here with the other 64-bit vars to get more natural alignment and save space. */
375     int             param;
376     uint64_t        parval;
377 #ifndef DIS_SEPARATE_FORMATTER
378     char            szParam[32];
379 #endif
380
381     int32_t         disp8, disp16, disp32;
382     uint32_t        size;
383
384     int64_t         disp64;
385     uint64_t        flags;
386
387     union
388     {
389         uint32_t    reg_gen;
390         /** ST(0) - ST(7) */
391         uint32_t    reg_fp;
392         /** MMX0 - MMX7 */
393         uint32_t    reg_mmx;
394         /** XMM0 - XMM7 */
395         uint32_t    reg_xmm;
396         /** {ES, CS, SS, DS, FS, GS} */
397         DIS_SELREG  reg_seg;
398         /** TR0-TR7 (?) */
399         uint32_t    reg_test;
400         /** CR0-CR4 */
401         uint32_t    reg_ctrl;
402         /** DR0-DR7 */
403         uint32_t    reg_dbg;
404     } base;
405     union
406     {
407         uint32_t    reg_gen;
408     } index;
409
410     /** 2, 4 or 8. */
411     uint32_t scale;
412
413 } OP_PARAMETER;
414 /** Pointer to opcode parameter. */
415 typedef OP_PARAMETER *POP_PARAMETER;
416 /** Pointer to opcode parameter. */
417 typedef const OP_PARAMETER *PCOP_PARAMETER;
418
419
420 struct _OPCODE;
421 /** Pointer to opcode. */
422 typedef struct _OPCODE *POPCODE;
423 /** Pointer to const opcode. */
424 typedef const struct _OPCODE *PCOPCODE;
425
426 typedef DECLCALLBACK(int) FN_DIS_READBYTES(RTUINTPTR pSrc, uint8_t *pDest, unsigned size, void *pvUserdata);
427 typedef FN_DIS_READBYTES *PFN_DIS_READBYTES;
428
429 /* forward decl */
430 struct _DISCPUSTATE;
431 /** Pointer to the disassembler CPU state. */
432 typedef struct _DISCPUSTATE *PDISCPUSTATE;
433
434 /** Parser callback.
435  * @remark no DECLCALLBACK() here because it's considered to be internal (really, I'm too lazy to update all the functions). */
436 typedef unsigned FNDISPARSE(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu);
437 typedef FNDISPARSE *PFNDISPARSE;
438
439 typedef struct _DISCPUSTATE
440 {
441     /* Global setting */
442     DISCPUMODE      mode;
443
444     /* Per instruction prefix settings */
445     uint32_t        prefix;
446     /** segment prefix value. */
447     DIS_SELREG      enmPrefixSeg;
448     /** rex prefix value (64 bits only */
449     uint32_t        prefix_rex;
450     /** addressing mode (16 or 32 bits). (CPUMODE_*) */
451     DISCPUMODE      addrmode;
452     /** operand mode (16 or 32 bits). (CPUMODE_*) */
453     DISCPUMODE      opmode;
454
455     OP_PARAMETER    param1;
456     OP_PARAMETER    param2;
457     OP_PARAMETER    param3;
458
459     /** ModRM fields. */
460     union
461     {
462         /* Bitfield view */
463         struct
464         {
465             unsigned        Rm  : 4;
466             unsigned        Reg : 4;
467             unsigned        Mod : 2;
468         } Bits;
469         /* unsigned view */
470         unsigned            u;
471     } ModRM;
472
473     /** SIB fields. */
474     union
475     {
476         /* Bitfield view */
477         struct
478         {
479             unsigned        Base  : 4;
480             unsigned        Index : 4;
481             unsigned        Scale : 2;
482         } Bits;
483         /* unsigned view */
484         unsigned            u;
485     } SIB;
486
487     int32_t         disp;
488
489     /** First opcode byte of instruction. */
490     uint8_t         opcode;
491     /** Last prefix byte (for SSE2 extension tables) */
492     uint8_t         lastprefix;
493     RTUINTPTR       opaddr;
494     uint32_t        opsize;
495 #ifndef DIS_CORE_ONLY
496     /** Opcode format string for current instruction. */
497     const char      *pszOpcode;
498 #endif
499
500     /** Internal: pointer to disassembly function table */
501     PFNDISPARSE    *pfnDisasmFnTable;
502     /** Internal: instruction filter */
503     uint32_t        uFilter;
504
505     /** Pointer to the current instruction. */
506     PCOPCODE        pCurInstr;
507
508     void           *apvUserData[3];
509
510     /** Optional read function */
511     PFN_DIS_READBYTES pfnReadBytes;
512 #ifdef __L4ENV__
513     jmp_buf *pJumpBuffer;
514 #endif /* __L4ENV__ */
515 } DISCPUSTATE;
516
517 /** Pointer to a const disassembler CPU state. */
518 typedef DISCPUSTATE const *PCDISCPUSTATE;
519
520 /** Opcode. */
521 #pragma pack(4)
522 typedef struct _OPCODE
523 {
524 #ifndef DIS_CORE_ONLY
525     const char  *pszOpcode;
526 #endif
527     uint8_t     idxParse1;
528     uint8_t     idxParse2;
529     uint8_t     idxParse3;
530     uint16_t    opcode;
531     uint16_t    param1;
532     uint16_t    param2;
533     uint16_t    param3;
534
535     unsigned    optype;
536 } OPCODE;
537 #pragma pack()
538
539
540 /**
541  * Disassembles a code block.
542  *
543  * @returns VBox error code
544  * @param   pCpu            Pointer to cpu structure which have DISCPUSTATE::mode
545  *                          set correctly.
546  * @param   pvCodeBlock     Pointer to the strunction to disassemble.
547  * @param   cbMax           Maximum number of bytes to disassemble.
548  * @param   pcbSize         Where to store the size of the instruction.
549  *                          NULL is allowed.
550  *
551  *
552  * @todo    Define output callback.
553  * @todo    Using signed integers as sizes is a bit odd. There are still
554  *          some GCC warnings about mixing signed and unsigend integers.
555  * @todo    Need to extend this interface to include a code address so we
556  *          can dissassemble GC code. Perhaps a new function is better...
557  * @remark  cbMax isn't respected as a boundry. DISInstr() will read beyond cbMax.
558  *          This means *pcbSize >= cbMax sometimes.
559  */
560 DISDECL(int) DISBlock(PDISCPUSTATE pCpu, RTUINTPTR pvCodeBlock, unsigned cbMax, unsigned *pSize);
561
562 /**
563  * Disassembles one instruction
564  *
565  * @returns VBox error code
566  * @param   pCpu            Pointer to cpu structure which have DISCPUSTATE::mode
567  *                          set correctly.
568  * @param   pu8Instruction  Pointer to the instrunction to disassemble.
569  * @param   u32EipOffset    Offset to add to instruction address to get the real virtual address
570  * @param   pcbSize         Where to store the size of the instruction.
571  *                          NULL is allowed.
572  * @param   pszOutput       Storage for disassembled instruction
573  *
574  * @todo    Define output callback.
575  */
576 DISDECL(int) DISInstr(PDISCPUSTATE pCpu, RTUINTPTR pu8Instruction, unsigned u32EipOffset, unsigned *pcbSize, char *pszOutput);
577
578 /**
579  * Disassembles one instruction
580  *
581  * @returns VBox error code
582  * @param   pCpu            Pointer to cpu structure which have DISCPUSTATE::mode
583  *                          set correctly.
584  * @param   pu8Instruction  Pointer to the strunction to disassemble.
585  * @param   u32EipOffset    Offset to add to instruction address to get the real virtual address
586  * @param   pcbSize         Where to store the size of the instruction.
587  *                          NULL is allowed.
588  * @param   pszOutput       Storage for disassembled instruction
589  * @param   uFilter         Instruction type filter
590  *
591  * @todo    Define output callback.
592  */
593 DISDECL(int) DISInstrEx(PDISCPUSTATE pCpu, RTUINTPTR pu8Instruction, uint32_t u32EipOffset, uint32_t *pcbSize,
594                          char *pszOutput, unsigned uFilter);
595
596 /**
597  * Parses one instruction.
598  * The result is found in pCpu.
599  *
600  * @returns VBox error code
601  * @param   pCpu            Pointer to cpu structure which has DISCPUSTATE::mode set correctly.
602  * @param   InstructionAddr Pointer to the instruction to parse.
603  * @param   pcbInstruction  Where to store the size of the instruction.
604  *                          NULL is allowed.
605  */
606 DISDECL(int) DISCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, unsigned *pcbInstruction);
607
608 /**
609  * Parses one guest instruction.
610  * The result is found in pCpu and pcbInstruction.
611  *
612  * @returns VBox status code.
613  * @param   InstructionAddr Address of the instruction to decode. What this means
614  *                          is left to the pfnReadBytes function.
615  * @param   enmCpuMode      The CPU mode. CPUMODE_32BIT, CPUMODE_16BIT, or CPUMODE_64BIT.
616  * @param   pfnReadBytes    Callback for reading instruction bytes.
617  * @param   pvUser          User argument for the instruction reader. (Ends up in apvUserData[0].)
618  * @param   pCpu            Pointer to cpu structure. Will be initialized.
619  * @param   pcbInstruction  Where to store the size of the instruction.
620  *                          NULL is allowed.
621  */
622 DISDECL(int) DISCoreOneEx(RTUINTPTR InstructionAddr, DISCPUMODE enmCpuMode, PFN_DIS_READBYTES pfnReadBytes, void *pvUser,
623                           PDISCPUSTATE pCpu, unsigned *pcbInstruction);
624
625 DISDECL(int)        DISGetParamSize(PDISCPUSTATE pCpu, POP_PARAMETER pParam);
626 DISDECL(DIS_SELREG) DISDetectSegReg(PDISCPUSTATE pCpu, POP_PARAMETER pParam);
627 DISDECL(uint8_t)    DISQuerySegPrefixByte(PDISCPUSTATE pCpu);
628
629 /**
630  * Returns the value of the parameter in pParam
631  *
632  * @returns VBox error code
633  * @param   pCtx            Exception structure pointer
634  * @param   pCpu            Pointer to cpu structure which have DISCPUSTATE::mode
635  *                          set correctly.
636  * @param   pParam          Pointer to the parameter to parse
637  * @param   pParamVal       Pointer to parameter value (OUT)
638  * @param   parmtype        Parameter type
639  *
640  * @note    Currently doesn't handle FPU/XMM/MMX/3DNow! parameters correctly!!
641  *
642  */
643 DISDECL(int) DISQueryParamVal(PCPUMCTXCORE pCtx, PDISCPUSTATE pCpu, POP_PARAMETER pParam, POP_PARAMVAL pParamVal, PARAM_TYPE parmtype);
644 DISDECL(int) DISQueryParamRegPtr(PCPUMCTXCORE pCtx, PDISCPUSTATE pCpu, POP_PARAMETER pParam, void **ppReg, size_t *pcbSize);
645
646 DISDECL(int) DISFetchReg8(PCCPUMCTXCORE pCtx, unsigned reg8, uint8_t *pVal);
647 DISDECL(int) DISFetchReg16(PCCPUMCTXCORE pCtx, unsigned reg16, uint16_t *pVal);
648 DISDECL(int) DISFetchReg32(PCCPUMCTXCORE pCtx, unsigned reg32, uint32_t *pVal);
649 DISDECL(int) DISFetchReg64(PCCPUMCTXCORE pCtx, unsigned reg64, uint64_t *pVal);
650 DISDECL(int) DISFetchRegSeg(PCCPUMCTXCORE pCtx, DIS_SELREG sel, RTSEL *pVal);
651 DISDECL(int) DISFetchRegSegEx(PCCPUMCTXCORE pCtx, DIS_SELREG sel, RTSEL *pVal, PCPUMSELREGHID *ppSelHidReg);
652 DISDECL(int) DISWriteReg8(PCPUMCTXCORE pRegFrame, unsigned reg8, uint8_t val8);
653 DISDECL(int) DISWriteReg16(PCPUMCTXCORE pRegFrame, unsigned reg32, uint16_t val16);
654 DISDECL(int) DISWriteReg32(PCPUMCTXCORE pRegFrame, unsigned reg32, uint32_t val32);
655 DISDECL(int) DISWriteReg64(PCPUMCTXCORE pRegFrame, unsigned reg64, uint64_t val64);
656 DISDECL(int) DISWriteRegSeg(PCPUMCTXCORE pCtx, DIS_SELREG sel, RTSEL val);
657 DISDECL(int) DISPtrReg8(PCPUMCTXCORE pCtx, unsigned reg8, uint8_t **ppReg);
658 DISDECL(int) DISPtrReg16(PCPUMCTXCORE pCtx, unsigned reg16, uint16_t **ppReg);
659 DISDECL(int) DISPtrReg32(PCPUMCTXCORE pCtx, unsigned reg32, uint32_t **ppReg);
660 DISDECL(int) DISPtrReg64(PCPUMCTXCORE pCtx, unsigned reg64, uint64_t **ppReg);
661
662
663 /**
664  * Try resolve an address into a symbol name.
665  *
666  * For use with DISFormatYasmEx(), DISFormatMasmEx() and DISFormatGasEx().
667  *
668  * @returns VBox status code.
669  * @retval  VINF_SUCCESS on success, pszBuf contains the full symbol name.
670  * @retval  VINF_BUFFER_OVERFLOW if pszBuf is too small the symbol name. The
671  *          content of pszBuf is truncated and zero terminated.
672  * @retval  VERR_SYMBOL_NOT_FOUND if no matching symbol was found for the address.
673  *
674  * @param   pCpu        Pointer to the disassembler CPU state.
675  * @param   u32Sel      The selector value. Use DIS_FMT_SEL_IS_REG, DIS_FMT_SEL_GET_VALUE,
676  *                      DIS_FMT_SEL_GET_REG to access this.
677  * @param   uAddress    The segment address.
678  * @param   pszBuf      Where to store the symbol name
679  * @param   cchBuf      The size of the buffer.
680  * @param   poff        If not a perfect match, then this is where the offset from the return
681  *                      symbol to the specified address is returned.
682  * @param   pvUser      The user argument.
683  */
684 typedef DECLCALLBACK(int) FNDISGETSYMBOL(PCDISCPUSTATE pCpu, uint32_t u32Sel, RTUINTPTR uAddress, char *pszBuf, size_t cchBuf, RTINTPTR *poff, void *pvUser);
685 /** Pointer to a FNDISGETSYMBOL(). */
686 typedef FNDISGETSYMBOL *PFNDISGETSYMBOL;
687
688 /**
689  * Checks if the FNDISGETSYMBOL argument u32Sel is a register or not.
690  */
691 #define DIS_FMT_SEL_IS_REG(u32Sel)          ( !!((u32Sel) & RT_BIT(31)) )
692
693 /**
694  * Extracts the selector value from the FNDISGETSYMBOL argument u32Sel.
695  * @returns Selector value.
696  */
697 #define DIS_FMT_SEL_GET_VALUE(u32Sel)       ( (RTSEL)(u32Sel) )
698
699 /**
700  * Extracts the register number from the FNDISGETSYMBOL argument u32Sel.
701  * @returns USE_REG_CS, USE_REG_SS, USE_REG_DS, USE_REG_ES, USE_REG_FS or USE_REG_FS.
702  */
703 #define DIS_FMT_SEL_GET_REG(u32Sel)         ( ((u32Sel) >> 16) & 0xf )
704
705 /** @internal */
706 #define DIS_FMT_SEL_FROM_REG(uReg)          ( ((uReg) << 16) | RT_BIT(31) | 0xffff )
707 /** @internal */
708 #define DIS_FMT_SEL_FROM_VALUE(Sel)         ( (Sel) & 0xffff )
709
710
711 /** @name Flags for use with DISFormatYasmEx(), DISFormatMasmEx() and DISFormatGasEx().
712  * @{
713  */
714 /** Put the address to the right. */
715 #define DIS_FMT_FLAGS_ADDR_RIGHT            RT_BIT_32(0)
716 /** Put the address to the left. */
717 #define DIS_FMT_FLAGS_ADDR_LEFT             RT_BIT_32(1)
718 /** Put the address in comments.
719  * For some assemblers this implies placing it to the right. */
720 #define DIS_FMT_FLAGS_ADDR_COMMENT          RT_BIT_32(2)
721 /** Put the instruction bytes to the right of the disassembly. */
722 #define DIS_FMT_FLAGS_BYTES_RIGHT           RT_BIT_32(3)
723 /** Put the instruction bytes to the left of the disassembly. */
724 #define DIS_FMT_FLAGS_BYTES_LEFT            RT_BIT_32(4)
725 /** Put the instruction bytes in comments.
726  * For some assemblers this implies placing the bytes to the right. */
727 #define DIS_FMT_FLAGS_BYTES_COMMENT         RT_BIT_32(5)
728 /** Put the bytes in square brackets. */
729 #define DIS_FMT_FLAGS_BYTES_BRACKETS        RT_BIT_32(6)
730 /** Put spaces between the bytes. */
731 #define DIS_FMT_FLAGS_BYTES_SPACED          RT_BIT_32(7)
732 /** Display the relative +/- offset of branch instructions that uses relative addresses,
733  * and put the target address in parenthesis. */
734 #define DIS_FMT_FLAGS_RELATIVE_BRANCH       RT_BIT_32(8)
735 /** Strict assembly. The assembly should, when ever possible, make the
736  * assembler reproduce the exact same binary. (Refers to the yasm
737  * strict keyword.) */
738 #define DIS_FMT_FLAGS_STRICT                RT_BIT_32(9)
739 /** Checks if the given flags are a valid combination. */
740 #define DIS_FMT_FLAGS_IS_VALID(fFlags) \
741     (   !((fFlags) & ~UINT32_C(0x000003ff)) \
742      && ((fFlags) & (DIS_FMT_FLAGS_ADDR_RIGHT  | DIS_FMT_FLAGS_ADDR_LEFT))  != (DIS_FMT_FLAGS_ADDR_RIGHT  | DIS_FMT_FLAGS_ADDR_LEFT) \
743      && (   !((fFlags) & DIS_FMT_FLAGS_ADDR_COMMENT) \
744          || (fFlags & (DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT)) ) \
745      && ((fFlags) & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT)) != (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT) \
746      && (   !((fFlags) & (DIS_FMT_FLAGS_BYTES_COMMENT | DIS_FMT_FLAGS_BYTES_BRACKETS)) \
747          || (fFlags & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT)) ) \
748     )
749 /** @} */
750
751 DISDECL(size_t) DISFormatYasm( PCDISCPUSTATE pCpu, char *pszBuf, size_t cchBuf);
752 DISDECL(size_t) DISFormatYasmEx(PCDISCPUSTATE pCpu, char