VirtualBox

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

Last change on this file since 105724 was 105724, checked in by vboxsync, 4 weeks ago

Disassembler,VMM,HostDrivers,Debugger,MakeAlternativeSource: Convert DISSTATE::Param1,...,DISSTATE::Param4 to DISSTATE::aParams[4] for easier indexing, bugref:10394

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.5 KB
Line 
1/** @file
2 * DIS - The VirtualBox Disassembler.
3 */
4
5/*
6 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
7 *
8 * This file is part of VirtualBox base platform packages, as
9 * available from https://www.virtualbox.org.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation, in version 3 of the
14 * License.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <https://www.gnu.org/licenses>.
23 *
24 * The contents of this file may alternatively be used under the terms
25 * of the Common Development and Distribution License Version 1.0
26 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
27 * in the VirtualBox distribution, in which case the provisions of the
28 * CDDL are applicable instead of those of the GPL.
29 *
30 * You may elect to license modified versions of this file under the
31 * terms and conditions of either the GPL or the CDDL or both.
32 *
33 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
34 */
35
36#ifndef VBOX_INCLUDED_dis_h
37#define VBOX_INCLUDED_dis_h
38#ifndef RT_WITHOUT_PRAGMA_ONCE
39# pragma once
40#endif
41
42#include <VBox/types.h>
43#include <VBox/dis-x86-amd64.h>
44#if defined(VBOX_DIS_WITH_ARMV8)
45# include <VBox/dis-armv8.h>
46#endif
47#include <iprt/assert.h>
48
49
50RT_C_DECLS_BEGIN
51
52/** @defgroup grp_dis VBox Disassembler
53 * @{ */
54
55/** @name Operand type (DISOPCODEX86::fOpType).
56 * @{
57 */
58#define DISOPTYPE_INVALID RT_BIT_32(0)
59#define DISOPTYPE_HARMLESS RT_BIT_32(1)
60#define DISOPTYPE_CONTROLFLOW RT_BIT_32(2)
61#define DISOPTYPE_POTENTIALLY_DANGEROUS RT_BIT_32(3)
62#define DISOPTYPE_DANGEROUS RT_BIT_32(4)
63#define DISOPTYPE_PORTIO RT_BIT_32(5)
64#define DISOPTYPE_PRIVILEGED RT_BIT_32(6)
65#define DISOPTYPE_PRIVILEGED_NOTRAP RT_BIT_32(7)
66#define DISOPTYPE_UNCOND_CONTROLFLOW RT_BIT_32(8)
67#define DISOPTYPE_RELATIVE_CONTROLFLOW RT_BIT_32(9)
68#define DISOPTYPE_COND_CONTROLFLOW RT_BIT_32(10)
69#define DISOPTYPE_INTERRUPT RT_BIT_32(11)
70#define DISOPTYPE_ILLEGAL RT_BIT_32(12)
71#define DISOPTYPE_RRM_DANGEROUS RT_BIT_32(14) /**< Some additional dangerous ones when recompiling raw r0. */
72#define DISOPTYPE_RRM_DANGEROUS_16 RT_BIT_32(15) /**< Some additional dangerous ones when recompiling 16-bit raw r0. */
73#define DISOPTYPE_RRM_MASK (DISOPTYPE_RRM_DANGEROUS | DISOPTYPE_RRM_DANGEROUS_16)
74#define DISOPTYPE_INHIBIT_IRQS RT_BIT_32(16) /**< Will or can inhibit irqs (sti, pop ss, mov ss) */
75
76#define DISOPTYPE_X86_PORTIO_READ RT_BIT_32(17)
77#define DISOPTYPE_X86_PORTIO_WRITE RT_BIT_32(18)
78#define DISOPTYPE_X86_INVALID_64 RT_BIT_32(19) /**< Invalid in 64 bits mode */
79#define DISOPTYPE_X86_ONLY_64 RT_BIT_32(20) /**< Only valid in 64 bits mode */
80#define DISOPTYPE_X86_DEFAULT_64_OP_SIZE RT_BIT_32(21) /**< Default 64 bits operand size */
81#define DISOPTYPE_X86_FORCED_64_OP_SIZE RT_BIT_32(22) /**< Forced 64 bits operand size; regardless of prefix bytes */
82#define DISOPTYPE_X86_REXB_EXTENDS_OPREG RT_BIT_32(23) /**< REX.B extends the register field in the opcode byte */
83#define DISOPTYPE_X86_MOD_FIXED_11 RT_BIT_32(24) /**< modrm.mod is always 11b */
84#define DISOPTYPE_X86_FORCED_32_OP_SIZE_X86 RT_BIT_32(25) /**< Forced 32 bits operand size; regardless of prefix bytes (only in 16 & 32 bits mode!) */
85#define DISOPTYPE_X86_AVX RT_BIT_32(28) /**< AVX,AVX2,++ instruction. Not implemented yet! */
86#define DISOPTYPE_X86_SSE RT_BIT_32(29) /**< SSE,SSE2,SSE3,SSE4,++ instruction. Not implemented yet! */
87#define DISOPTYPE_X86_MMX RT_BIT_32(30) /**< MMX,MMXExt,3DNow,++ instruction. Not implemented yet! */
88#define DISOPTYPE_X86_FPU RT_BIT_32(31) /**< FPU instruction. Not implemented yet! */
89#define DISOPTYPE_ALL UINT32_C(0xffffffff)
90/** @} */
91
92
93/**
94 * Opcode descriptor.
95 */
96#if !defined(DIS_CORE_ONLY) || defined(DOXYGEN_RUNNING)
97typedef struct DISOPCODE
98{
99# define DISOPCODE_FORMAT 0
100 /** Mnemonic and operand formatting. */
101 const char *pszOpcode;
102 /** Parameter \#1 parser index. */
103 uint8_t idxParse1;
104 /** Parameter \#2 parser index. */
105 uint8_t idxParse2;
106 /** Parameter \#3 parser index. */
107 uint8_t idxParse3;
108 /** Parameter \#4 parser index. */
109 uint8_t idxParse4;
110 /** The opcode identifier (enum OPCODESX86) - this is DIS specific.
111 * @see grp_dis_opcodes, VBox/disopcode-x86-amd64.h */
112 uint16_t uOpcode;
113 /** Parameter \#1 info, @see grp_dis_opparam. */
114 uint16_t fParam1;
115 /** Parameter \#2 info, @see grp_dis_opparam. */
116 uint16_t fParam2;
117 /** Parameter \#3 info, @see grp_dis_opparam. */
118 uint16_t fParam3;
119 /** Parameter \#4 info, @see grp_dis_opparam. */
120 uint16_t fParam4;
121 /** padding unused */
122 uint16_t uPadding;
123 /** Operand type flags, DISOPTYPE_XXX. */
124 uint32_t fOpType;
125} DISOPCODE;
126#else
127# pragma pack(1)
128typedef struct DISOPCODE
129{
130#if 1 /*!defined(RT_ARCH_X86) && !defined(RT_ARCH_AMD64) - probably not worth it for ~4K, costs 2-3% speed. */
131 /* 16 bytes (trick is to make sure the bitfields doesn't cross dwords): */
132# define DISOPCODE_FORMAT 16
133 uint32_t fOpType;
134 uint16_t uOpcode;
135 uint8_t idxParse1;
136 uint8_t idxParse2;
137 uint32_t fParam1 : 12; /* 1st dword: 12+12+8 = 0x20 (32) */
138 uint32_t fParam2 : 12;
139 uint32_t idxParse3 : 8;
140 uint32_t fParam3 : 12; /* 2nd dword: 12+12+8 = 0x20 (32) */
141 uint32_t fParam4 : 12;
142 uint32_t idxParse4 : 8;
143#else /* 15 bytes: */
144# define DISOPCODE_FORMAT 15
145 uint64_t uOpcode : 10; /* 1st qword: 10+12+12+12+6+6+6 = 0x40 (64) */
146 uint64_t idxParse1 : 6;
147 uint64_t idxParse2 : 6;
148 uint64_t idxParse3 : 6;
149 uint64_t fParam1 : 12;
150 uint64_t fParam2 : 12;
151 uint64_t fParam3 : 12;
152 uint32_t fOpType;
153 uint16_t fParam4;
154 uint8_t idxParse4;
155#endif
156} DISOPCODE;
157# pragma pack()
158AssertCompile(sizeof(DISOPCODE) == DISOPCODE_FORMAT);
159#endif
160AssertCompile(DISOPCODE_FORMAT != 15); /* Needs fixing before use as disopcode.h now has more than 1024 opcode values. */
161
162
163/** @name Parameter usage flags.
164 * @{
165 */
166#define DISUSE_BASE RT_BIT_64(0)
167#define DISUSE_INDEX RT_BIT_64(1)
168#define DISUSE_SCALE RT_BIT_64(2)
169#define DISUSE_REG_GEN8 RT_BIT_64(3)
170#define DISUSE_REG_GEN16 RT_BIT_64(4)
171#define DISUSE_REG_GEN32 RT_BIT_64(5)
172#define DISUSE_REG_GEN64 RT_BIT_64(6)
173#define DISUSE_REG_FP RT_BIT_64(7)
174#define DISUSE_REG_MMX RT_BIT_64(8)
175#define DISUSE_REG_XMM RT_BIT_64(9)
176#define DISUSE_REG_YMM RT_BIT_64(10)
177#define DISUSE_REG_CR RT_BIT_64(11)
178#define DISUSE_REG_DBG RT_BIT_64(12)
179#define DISUSE_REG_SEG RT_BIT_64(13)
180#define DISUSE_REG_TEST RT_BIT_64(14)
181#define DISUSE_DISPLACEMENT8 RT_BIT_64(15)
182#define DISUSE_DISPLACEMENT16 RT_BIT_64(16)
183#define DISUSE_DISPLACEMENT32 RT_BIT_64(17)
184#define DISUSE_DISPLACEMENT64 RT_BIT_64(18)
185#define DISUSE_RIPDISPLACEMENT32 RT_BIT_64(19)
186#define DISUSE_IMMEDIATE8 RT_BIT_64(20)
187#define DISUSE_IMMEDIATE8_REL RT_BIT_64(21)
188#define DISUSE_IMMEDIATE16 RT_BIT_64(22)
189#define DISUSE_IMMEDIATE16_REL RT_BIT_64(23)
190#define DISUSE_IMMEDIATE32 RT_BIT_64(24)
191#define DISUSE_IMMEDIATE32_REL RT_BIT_64(25)
192#define DISUSE_IMMEDIATE64 RT_BIT_64(26)
193#define DISUSE_IMMEDIATE64_REL RT_BIT_64(27)
194#define DISUSE_IMMEDIATE_ADDR_0_32 RT_BIT_64(28)
195#define DISUSE_IMMEDIATE_ADDR_16_32 RT_BIT_64(29)
196#define DISUSE_IMMEDIATE_ADDR_0_16 RT_BIT_64(30)
197#define DISUSE_IMMEDIATE_ADDR_16_16 RT_BIT_64(31)
198/** DS:ESI */
199#define DISUSE_POINTER_DS_BASED RT_BIT_64(32)
200/** ES:EDI */
201#define DISUSE_POINTER_ES_BASED RT_BIT_64(33)
202#define DISUSE_IMMEDIATE16_SX8 RT_BIT_64(34)
203#define DISUSE_IMMEDIATE32_SX8 RT_BIT_64(35)
204#define DISUSE_IMMEDIATE64_SX8 RT_BIT_64(36)
205
206/** Mask of immediate use flags. */
207#define DISUSE_IMMEDIATE ( DISUSE_IMMEDIATE8 \
208 | DISUSE_IMMEDIATE16 \
209 | DISUSE_IMMEDIATE32 \
210 | DISUSE_IMMEDIATE64 \
211 | DISUSE_IMMEDIATE8_REL \
212 | DISUSE_IMMEDIATE16_REL \
213 | DISUSE_IMMEDIATE32_REL \
214 | DISUSE_IMMEDIATE64_REL \
215 | DISUSE_IMMEDIATE_ADDR_0_32 \
216 | DISUSE_IMMEDIATE_ADDR_16_32 \
217 | DISUSE_IMMEDIATE_ADDR_0_16 \
218 | DISUSE_IMMEDIATE_ADDR_16_16 \
219 | DISUSE_IMMEDIATE16_SX8 \
220 | DISUSE_IMMEDIATE32_SX8 \
221 | DISUSE_IMMEDIATE64_SX8)
222/** Check if the use flags indicates an effective address. */
223#define DISUSE_IS_EFFECTIVE_ADDR(a_fUseFlags) (!!( (a_fUseFlags) \
224 & ( DISUSE_BASE \
225 | DISUSE_INDEX \
226 | DISUSE_DISPLACEMENT32 \
227 | DISUSE_DISPLACEMENT64 \
228 | DISUSE_DISPLACEMENT16 \
229 | DISUSE_DISPLACEMENT8 \
230 | DISUSE_RIPDISPLACEMENT32) ))
231/** @} */
232
233
234/**
235 * Opcode parameter (operand) details.
236 */
237typedef struct DISOPPARAM
238{
239 /** A combination of DISUSE_XXX. */
240 uint64_t fUse;
241 /** Immediate value or address, applicable if any of the flags included in
242 * DISUSE_IMMEDIATE are set in fUse. */
243 uint64_t uValue;
244
245 /** Architecture specific parameter state. */
246 RT_GCC_EXTENSION union
247 {
248 /** x86/AMD64 specific state. */
249 DIS_OP_PARAM_X86_T x86;
250#if defined(VBOX_DIS_WITH_ARMV8)
251 /** ARMv8 specific state. */
252 DIS_OP_PARAM_ARMV8_T armv8;
253#endif
254 };
255} DISOPPARAM;
256AssertCompileSize(DISOPPARAM, 32);
257/** Pointer to opcode parameter. */
258typedef const DISOPPARAM *PCDISOPPARAM;
259
260
261/**
262 * Callback for reading instruction bytes.
263 *
264 * @returns VBox status code, bytes in DISSTATE::Instr::ab and byte count in
265 * DISSTATE::cbCachedInstr.
266 * @param pDis Pointer to the disassembler state. The user
267 * argument can be found in DISSTATE::pvUser if needed.
268 * @param offInstr The offset relative to the start of the instruction.
269 *
270 * To get the source address, add this to
271 * DISSTATE::uInstrAddr.
272 *
273 * To calculate the destination buffer address, use it
274 * as an index into DISSTATE::Instr::ab.
275 *
276 * @param cbMinRead The minimum number of bytes to read.
277 * @param cbMaxRead The maximum number of bytes that may be read.
278 */
279typedef DECLCALLBACKTYPE(int, FNDISREADBYTES,(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead));
280/** Pointer to a opcode byte reader. */
281typedef FNDISREADBYTES *PFNDISREADBYTES;
282
283
284/**
285 * The diassembler state and result.
286 */
287typedef struct DISSTATE
288{
289 /** The different instruction views.
290 * @sa cbCachedInstr, FNDISREADBYTES */
291 union
292 {
293 /** Byte (8-bit) view.
294 * This is the one referred to by FNDISREADBYTES and cbCached. */
295 uint8_t ab[16];
296 /** Single 16-bit view. */
297 uint16_t u16;
298 /** Single 32-bit view. */
299 uint32_t u32;
300 /** 16-bit view. */
301 uint16_t au16[8];
302 /** 32-bit view. */
303 uint32_t au32[4];
304 /** 64-bit view. */
305 uint64_t au64[2];
306 } Instr;
307
308 /** Pointer to the current instruction. */
309 PCDISOPCODE pCurInstr;
310#if ARCH_BITS == 32
311 uint32_t uPtrPadding2;
312#endif
313
314 /** Array of opcode parameters. */
315 DISOPPARAM aParams[4];
316
317 /** The number of valid bytes in DISSTATE::Instr. */
318 uint8_t cbCachedInstr;
319 /** The CPU mode (DISCPUMODE). */
320 uint8_t uCpuMode;
321 /** The instruction size. */
322 uint8_t cbInstr;
323 /** Unused bytes. */
324 uint8_t abUnused[1];
325
326 /** Return code set by a worker function like the opcode bytes readers. */
327 int32_t rc;
328 /** The address of the instruction. */
329 RTUINTPTR uInstrAddr;
330 /** Optional read function */
331 PFNDISREADBYTES pfnReadBytes;
332#if ARCH_BITS == 32
333 uint32_t uPadding3;
334#endif
335 /** User data supplied as an argument to the APIs. */
336 void *pvUser;
337#if ARCH_BITS == 32
338 uint32_t uPadding4;
339#endif
340
341 /** Architecture specific state. */
342 RT_GCC_EXTENSION union
343 {
344 /** x86/AMD64 specific state. */
345 DIS_STATE_X86_T x86;
346#if defined(VBOX_DIS_WITH_ARMV8)
347 /** ARMv8 specific state. */
348 DIS_STATE_ARMV8_T armv8;
349#endif
350 };
351} DISSTATE;
352AssertCompileMemberAlignment(DISSTATE, x86, 8);
353AssertCompileSize(DISSTATE, 0xd8);
354
355
356
357DISDECL(int) DISInstrToStr(void const *pvInstr, DISCPUMODE enmCpuMode,
358 PDISSTATE pDis, uint32_t *pcbInstr, char *pszOutput, size_t cbOutput);
359DISDECL(int) DISInstrToStrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
360 PDISSTATE pDis, uint32_t *pcbInstr, char *pszOutput, size_t cbOutput);
361DISDECL(int) DISInstrToStrEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode,
362 PFNDISREADBYTES pfnReadBytes, void *pvUser, uint32_t uFilter,
363 PDISSTATE pDis, uint32_t *pcbInstr, char *pszOutput, size_t cbOutput);
364
365DISDECL(int) DISInstr(void const *pvInstr, DISCPUMODE enmCpuMode, PDISSTATE pDis, uint32_t *pcbInstr);
366DISDECL(int) DISInstrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
367 PDISSTATE pDis, uint32_t *pcbInstr);
368DISDECL(int) DISInstrEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t uFilter,
369 PFNDISREADBYTES pfnReadBytes, void *pvUser,
370 PDISSTATE pDis, uint32_t *pcbInstr);
371DISDECL(int) DISInstrWithPrefetchedBytes(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
372 void const *pvPrefetched, size_t cbPretched,
373 PFNDISREADBYTES pfnReadBytes, void *pvUser,
374 PDISSTATE pDis, uint32_t *pcbInstr);
375
376DISDECL(uint8_t) DISGetParamSize(PCDISSTATE pDis, PCDISOPPARAM pParam);
377#if 0 /* unused */
378DISDECL(DISSELREG) DISDetectSegReg(PCDISSTATE pDis, PCDISOPPARAM pParam);
379DISDECL(uint8_t) DISQuerySegPrefixByte(PCDISSTATE pDis);
380#endif
381
382#if 0 /* Needs refactoring if we want to use this again, CPUMCTXCORE is history. */
383/** @name Flags returned by DISQueryParamVal (DISQPVPARAMVAL::flags).
384 * @{
385 */
386#define DISQPV_FLAG_8 UINT8_C(0x01)
387#define DISQPV_FLAG_16 UINT8_C(0x02)
388#define DISQPV_FLAG_32 UINT8_C(0x04)
389#define DISQPV_FLAG_64 UINT8_C(0x08)
390#define DISQPV_FLAG_FARPTR16 UINT8_C(0x10)
391#define DISQPV_FLAG_FARPTR32 UINT8_C(0x20)
392/** @} */
393
394/** @name Types returned by DISQueryParamVal (DISQPVPARAMVAL::flags).
395 * @{ */
396#define DISQPV_TYPE_REGISTER UINT8_C(1)
397#define DISQPV_TYPE_ADDRESS UINT8_C(2)
398#define DISQPV_TYPE_IMMEDIATE UINT8_C(3)
399/** @} */
400
401typedef struct
402{
403 union
404 {
405 uint8_t val8;
406 uint16_t val16;
407 uint32_t val32;
408 uint64_t val64;
409
410 int8_t i8;
411 int16_t i16;
412 int32_t i32;
413 int64_t i64;
414
415 struct
416 {
417 uint16_t sel;
418 uint32_t offset;
419 } farptr;
420 } val;
421
422 uint8_t type;
423 uint8_t size;
424 uint8_t flags;
425} DISQPVPARAMVAL;
426/** Pointer to opcode parameter value. */
427typedef DISQPVPARAMVAL *PDISQPVPARAMVAL;
428
429/** Indicates which parameter DISQueryParamVal should operate on. */
430typedef enum DISQPVWHICH
431{
432 DISQPVWHICH_DST = 1,
433 DISQPVWHICH_SRC,
434 DISQPVWHAT_32_BIT_HACK = 0x7fffffff
435} DISQPVWHICH;
436DISDECL(int) DISQueryParamVal(PCPUMCTXCORE pCtx, PCDISSTATE pDis, PCDISOPPARAM pParam, PDISQPVPARAMVAL pParamVal, DISQPVWHICH parmtype);
437DISDECL(int) DISQueryParamRegPtr(PCPUMCTXCORE pCtx, PCDISSTATE pDis, PCDISOPPARAM pParam, void **ppReg, size_t *pcbSize);
438
439DISDECL(int) DISFetchReg8(PCCPUMCTXCORE pCtx, unsigned reg8, uint8_t *pVal);
440DISDECL(int) DISFetchReg16(PCCPUMCTXCORE pCtx, unsigned reg16, uint16_t *pVal);
441DISDECL(int) DISFetchReg32(PCCPUMCTXCORE pCtx, unsigned reg32, uint32_t *pVal);
442DISDECL(int) DISFetchReg64(PCCPUMCTXCORE pCtx, unsigned reg64, uint64_t *pVal);
443DISDECL(int) DISFetchRegSeg(PCCPUMCTXCORE pCtx, DISSELREG sel, RTSEL *pVal);
444DISDECL(int) DISWriteReg8(PCPUMCTXCORE pRegFrame, unsigned reg8, uint8_t val8);
445DISDECL(int) DISWriteReg16(PCPUMCTXCORE pRegFrame, unsigned reg32, uint16_t val16);
446DISDECL(int) DISWriteReg32(PCPUMCTXCORE pRegFrame, unsigned reg32, uint32_t val32);
447DISDECL(int) DISWriteReg64(PCPUMCTXCORE pRegFrame, unsigned reg64, uint64_t val64);
448DISDECL(int) DISWriteRegSeg(PCPUMCTXCORE pCtx, DISSELREG sel, RTSEL val);
449DISDECL(int) DISPtrReg8(PCPUMCTXCORE pCtx, unsigned reg8, uint8_t **ppReg);
450DISDECL(int) DISPtrReg16(PCPUMCTXCORE pCtx, unsigned reg16, uint16_t **ppReg);
451DISDECL(int) DISPtrReg32(PCPUMCTXCORE pCtx, unsigned reg32, uint32_t **ppReg);
452DISDECL(int) DISPtrReg64(PCPUMCTXCORE pCtx, unsigned reg64, uint64_t **ppReg);
453#endif /* obsolete */
454
455
456/**
457 * Try resolve an address into a symbol name.
458 *
459 * For use with DISFormatYasmEx(), DISFormatMasmEx() and DISFormatGasEx().
460 *
461 * @returns VBox status code.
462 * @retval VINF_SUCCESS on success, pszBuf contains the full symbol name.
463 * @retval VINF_BUFFER_OVERFLOW if pszBuf is too small the symbol name. The
464 * content of pszBuf is truncated and zero terminated.
465 * @retval VERR_SYMBOL_NOT_FOUND if no matching symbol was found for the address.
466 *
467 * @param pDis Pointer to the disassembler CPU state.
468 * @param u32Sel The selector value. Use DIS_FMT_SEL_IS_REG, DIS_FMT_SEL_GET_VALUE,
469 * DIS_FMT_SEL_GET_REG to access this.
470 * @param uAddress The segment address.
471 * @param pszBuf Where to store the symbol name
472 * @param cchBuf The size of the buffer.
473 * @param poff If not a perfect match, then this is where the offset from the return
474 * symbol to the specified address is returned.
475 * @param pvUser The user argument.
476 */
477typedef DECLCALLBACKTYPE(int, FNDISGETSYMBOL,(PCDISSTATE pDis, uint32_t u32Sel, RTUINTPTR uAddress, char *pszBuf, size_t cchBuf,
478 RTINTPTR *poff, void *pvUser));
479/** Pointer to a FNDISGETSYMBOL(). */
480typedef FNDISGETSYMBOL *PFNDISGETSYMBOL;
481
482/**
483 * Checks if the FNDISGETSYMBOL argument u32Sel is a register or not.
484 */
485#define DIS_FMT_SEL_IS_REG(u32Sel) ( !!((u32Sel) & RT_BIT(31)) )
486
487/**
488 * Extracts the selector value from the FNDISGETSYMBOL argument u32Sel.
489 * @returns Selector value.
490 */
491#define DIS_FMT_SEL_GET_VALUE(u32Sel) ( (RTSEL)(u32Sel) )
492
493/**
494 * Extracts the register number from the FNDISGETSYMBOL argument u32Sel.
495 * @returns USE_REG_CS, USE_REG_SS, USE_REG_DS, USE_REG_ES, USE_REG_FS or USE_REG_FS.
496 */
497#define DIS_FMT_SEL_GET_REG(u32Sel) ( ((u32Sel) >> 16) & 0xf )
498
499/** @internal */
500#define DIS_FMT_SEL_FROM_REG(uReg) ( ((uReg) << 16) | RT_BIT(31) | 0xffff )
501/** @internal */
502#define DIS_FMT_SEL_FROM_VALUE(Sel) ( (Sel) & 0xffff )
503
504
505/** @name Flags for use with DISFormatYasmEx(), DISFormatMasmEx(),
506 * DISFormatGasEx() and DISFormatArmV8Ex().
507 * @{
508 */
509/** Put the address to the right. */
510#define DIS_FMT_FLAGS_ADDR_RIGHT RT_BIT_32(0)
511/** Put the address to the left. */
512#define DIS_FMT_FLAGS_ADDR_LEFT RT_BIT_32(1)
513/** Put the address in comments.
514 * For some assemblers this implies placing it to the right. */
515#define DIS_FMT_FLAGS_ADDR_COMMENT RT_BIT_32(2)
516/** Put the instruction bytes to the right of the disassembly. */
517#define DIS_FMT_FLAGS_BYTES_RIGHT RT_BIT_32(3)
518/** Put the instruction bytes to the left of the disassembly. */
519#define DIS_FMT_FLAGS_BYTES_LEFT RT_BIT_32(4)
520/** Put the instruction bytes in comments.
521 * For some assemblers this implies placing the bytes to the right. */
522#define DIS_FMT_FLAGS_BYTES_COMMENT RT_BIT_32(5)
523/** Put the bytes in square brackets. */
524#define DIS_FMT_FLAGS_BYTES_BRACKETS RT_BIT_32(6)
525/** Put spaces between the bytes. */
526#define DIS_FMT_FLAGS_BYTES_SPACED RT_BIT_32(7)
527/** Gives the width (in opcode bytes) of the opcode bytes area if on the left
528 * side. If zero, then a default of 7 will be used. */
529#define DIS_FMT_FLAGS_BYTES_WIDTH_MASK UINT32_C(0x00001f00)
530/** Shift count of the bytes width field. */
531#define DIS_FMT_FLAGS_BYTES_WIDTH_SHIFT 8
532/** Helper that makes shift the width count. */
533#define DIS_FMT_FLAGS_BYTES_WIDTH_MAKE(a_cb) ((uint32_t)(a_cb) << DIS_FMT_FLAGS_BYTES_WIDTH_SHIFT)
534/** Display the relative +/- offset of branch instructions that uses relative addresses,
535 * and put the target address in parenthesis. */
536#define DIS_FMT_FLAGS_RELATIVE_BRANCH RT_BIT_32(13)
537/** Strict assembly. The assembly should, when ever possible, make the
538 * assembler reproduce the exact same binary. (Refers to the yasm
539 * strict keyword.) */
540#define DIS_FMT_FLAGS_STRICT RT_BIT_32(14)
541/** C-style hex formatting (0x01), rather than assembly style (001h). */
542#define DIS_FMT_FLAGS_C_HEX RT_BIT_32(15)
543
544/** Checks if the given flags are a valid combination. */
545#define DIS_FMT_FLAGS_IS_VALID(fFlags) \
546 ( !((fFlags) & ~UINT32_C(0x0000ffff)) \
547 && ((fFlags) & (DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT)) != (DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT) \
548 && ( !((fFlags) & DIS_FMT_FLAGS_ADDR_COMMENT) \
549 || (fFlags & (DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT)) ) \
550 && ((fFlags) & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT)) != (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT) \
551 && ( !((fFlags) & (DIS_FMT_FLAGS_BYTES_COMMENT | DIS_FMT_FLAGS_BYTES_BRACKETS)) \
552 || (fFlags & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT)) ) \
553 )
554/** @} */
555
556DISDECL(size_t) DISFormatYasm( PCDISSTATE pDis, char *pszBuf, size_t cchBuf);
557DISDECL(size_t) DISFormatYasmEx(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
558DISDECL(size_t) DISFormatMasm( PCDISSTATE pDis, char *pszBuf, size_t cchBuf);
559DISDECL(size_t) DISFormatMasmEx(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
560DISDECL(size_t) DISFormatGas( PCDISSTATE pDis, char *pszBuf, size_t cchBuf);
561DISDECL(size_t) DISFormatGasEx( PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
562
563DISDECL(size_t) DISFormatArmV8( PCDISSTATE pDis, char *pszBuf, size_t cchBuf);
564DISDECL(size_t) DISFormatArmV8Ex(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
565
566/** @todo DISAnnotate(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, register
567 * reader, memory reader); */
568
569/** @} */
570
571RT_C_DECLS_END
572
573#endif /* !VBOX_INCLUDED_dis_h */
574
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