VirtualBox

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

Last change on this file was 101546, checked in by vboxsync, 7 months ago

DIS: Added DIS_FMT_FLAGS_BYTES_WIDTH_MASK/SHIFT/MAKE and DIS_FMT_FLAGS_C_HEX flags. bugref:10371

  • 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 DISOPPARAM Param1;
315 DISOPPARAM Param2;
316 DISOPPARAM Param3;
317 DISOPPARAM Param4;
318
319 /** The number of valid bytes in DISSTATE::Instr. */
320 uint8_t cbCachedInstr;
321 /** The CPU mode (DISCPUMODE). */
322 uint8_t uCpuMode;
323 /** The instruction size. */
324 uint8_t cbInstr;
325 /** Unused bytes. */
326 uint8_t abUnused[1];
327
328 /** Return code set by a worker function like the opcode bytes readers. */
329 int32_t rc;
330 /** The address of the instruction. */
331 RTUINTPTR uInstrAddr;
332 /** Optional read function */
333 PFNDISREADBYTES pfnReadBytes;
334#if ARCH_BITS == 32
335 uint32_t uPadding3;
336#endif
337 /** User data supplied as an argument to the APIs. */
338 void *pvUser;
339#if ARCH_BITS == 32
340 uint32_t uPadding4;
341#endif
342
343 /** Architecture specific state. */
344 RT_GCC_EXTENSION union
345 {
346 /** x86/AMD64 specific state. */
347 DIS_STATE_X86_T x86;
348#if defined(VBOX_DIS_WITH_ARMV8)
349 /** ARMv8 specific state. */
350 DIS_STATE_ARMV8_T armv8;
351#endif
352 };
353} DISSTATE;
354AssertCompileMemberAlignment(DISSTATE, x86, 8);
355AssertCompileSize(DISSTATE, 0xd8);
356
357
358
359DISDECL(int) DISInstrToStr(void const *pvInstr, DISCPUMODE enmCpuMode,
360 PDISSTATE pDis, uint32_t *pcbInstr, char *pszOutput, size_t cbOutput);
361DISDECL(int) DISInstrToStrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
362 PDISSTATE pDis, uint32_t *pcbInstr, char *pszOutput, size_t cbOutput);
363DISDECL(int) DISInstrToStrEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode,
364 PFNDISREADBYTES pfnReadBytes, void *pvUser, uint32_t uFilter,
365 PDISSTATE pDis, uint32_t *pcbInstr, char *pszOutput, size_t cbOutput);
366
367DISDECL(int) DISInstr(void const *pvInstr, DISCPUMODE enmCpuMode, PDISSTATE pDis, uint32_t *pcbInstr);
368DISDECL(int) DISInstrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
369 PDISSTATE pDis, uint32_t *pcbInstr);
370DISDECL(int) DISInstrEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t uFilter,
371 PFNDISREADBYTES pfnReadBytes, void *pvUser,
372 PDISSTATE pDis, uint32_t *pcbInstr);
373DISDECL(int) DISInstrWithPrefetchedBytes(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
374 void const *pvPrefetched, size_t cbPretched,
375 PFNDISREADBYTES pfnReadBytes, void *pvUser,
376 PDISSTATE pDis, uint32_t *pcbInstr);
377
378DISDECL(uint8_t) DISGetParamSize(PCDISSTATE pDis, PCDISOPPARAM pParam);
379#if 0 /* unused */
380DISDECL(DISSELREG) DISDetectSegReg(PCDISSTATE pDis, PCDISOPPARAM pParam);
381DISDECL(uint8_t) DISQuerySegPrefixByte(PCDISSTATE pDis);
382#endif
383
384#if 0 /* Needs refactoring if we want to use this again, CPUMCTXCORE is history. */
385/** @name Flags returned by DISQueryParamVal (DISQPVPARAMVAL::flags).
386 * @{
387 */
388#define DISQPV_FLAG_8 UINT8_C(0x01)
389#define DISQPV_FLAG_16 UINT8_C(0x02)
390#define DISQPV_FLAG_32 UINT8_C(0x04)
391#define DISQPV_FLAG_64 UINT8_C(0x08)
392#define DISQPV_FLAG_FARPTR16 UINT8_C(0x10)
393#define DISQPV_FLAG_FARPTR32 UINT8_C(0x20)
394/** @} */
395
396/** @name Types returned by DISQueryParamVal (DISQPVPARAMVAL::flags).
397 * @{ */
398#define DISQPV_TYPE_REGISTER UINT8_C(1)
399#define DISQPV_TYPE_ADDRESS UINT8_C(2)
400#define DISQPV_TYPE_IMMEDIATE UINT8_C(3)
401/** @} */
402
403typedef struct
404{
405 union
406 {
407 uint8_t val8;
408 uint16_t val16;
409 uint32_t val32;
410 uint64_t val64;
411
412 int8_t i8;
413 int16_t i16;
414 int32_t i32;
415 int64_t i64;
416
417 struct
418 {
419 uint16_t sel;
420 uint32_t offset;
421 } farptr;
422 } val;
423
424 uint8_t type;
425 uint8_t size;
426 uint8_t flags;
427} DISQPVPARAMVAL;
428/** Pointer to opcode parameter value. */
429typedef DISQPVPARAMVAL *PDISQPVPARAMVAL;
430
431/** Indicates which parameter DISQueryParamVal should operate on. */
432typedef enum DISQPVWHICH
433{
434 DISQPVWHICH_DST = 1,
435 DISQPVWHICH_SRC,
436 DISQPVWHAT_32_BIT_HACK = 0x7fffffff
437} DISQPVWHICH;
438DISDECL(int) DISQueryParamVal(PCPUMCTXCORE pCtx, PCDISSTATE pDis, PCDISOPPARAM pParam, PDISQPVPARAMVAL pParamVal, DISQPVWHICH parmtype);
439DISDECL(int) DISQueryParamRegPtr(PCPUMCTXCORE pCtx, PCDISSTATE pDis, PCDISOPPARAM pParam, void **ppReg, size_t *pcbSize);
440
441DISDECL(int) DISFetchReg8(PCCPUMCTXCORE pCtx, unsigned reg8, uint8_t *pVal);
442DISDECL(int) DISFetchReg16(PCCPUMCTXCORE pCtx, unsigned reg16, uint16_t *pVal);
443DISDECL(int) DISFetchReg32(PCCPUMCTXCORE pCtx, unsigned reg32, uint32_t *pVal);
444DISDECL(int) DISFetchReg64(PCCPUMCTXCORE pCtx, unsigned reg64, uint64_t *pVal);
445DISDECL(int) DISFetchRegSeg(PCCPUMCTXCORE pCtx, DISSELREG sel, RTSEL *pVal);
446DISDECL(int) DISWriteReg8(PCPUMCTXCORE pRegFrame, unsigned reg8, uint8_t val8);
447DISDECL(int) DISWriteReg16(PCPUMCTXCORE pRegFrame, unsigned reg32, uint16_t val16);
448DISDECL(int) DISWriteReg32(PCPUMCTXCORE pRegFrame, unsigned reg32, uint32_t val32);
449DISDECL(int) DISWriteReg64(PCPUMCTXCORE pRegFrame, unsigned reg64, uint64_t val64);
450DISDECL(int) DISWriteRegSeg(PCPUMCTXCORE pCtx, DISSELREG sel, RTSEL val);
451DISDECL(int) DISPtrReg8(PCPUMCTXCORE pCtx, unsigned reg8, uint8_t **ppReg);
452DISDECL(int) DISPtrReg16(PCPUMCTXCORE pCtx, unsigned reg16, uint16_t **ppReg);
453DISDECL(int) DISPtrReg32(PCPUMCTXCORE pCtx, unsigned reg32, uint32_t **ppReg);
454DISDECL(int) DISPtrReg64(PCPUMCTXCORE pCtx, unsigned reg64, uint64_t **ppReg);
455#endif /* obsolete */
456
457
458/**
459 * Try resolve an address into a symbol name.
460 *
461 * For use with DISFormatYasmEx(), DISFormatMasmEx() and DISFormatGasEx().
462 *
463 * @returns VBox status code.
464 * @retval VINF_SUCCESS on success, pszBuf contains the full symbol name.
465 * @retval VINF_BUFFER_OVERFLOW if pszBuf is too small the symbol name. The
466 * content of pszBuf is truncated and zero terminated.
467 * @retval VERR_SYMBOL_NOT_FOUND if no matching symbol was found for the address.
468 *
469 * @param pDis Pointer to the disassembler CPU state.
470 * @param u32Sel The selector value. Use DIS_FMT_SEL_IS_REG, DIS_FMT_SEL_GET_VALUE,
471 * DIS_FMT_SEL_GET_REG to access this.
472 * @param uAddress The segment address.
473 * @param pszBuf Where to store the symbol name
474 * @param cchBuf The size of the buffer.
475 * @param poff If not a perfect match, then this is where the offset from the return
476 * symbol to the specified address is returned.
477 * @param pvUser The user argument.
478 */
479typedef DECLCALLBACKTYPE(int, FNDISGETSYMBOL,(PCDISSTATE pDis, uint32_t u32Sel, RTUINTPTR uAddress, char *pszBuf, size_t cchBuf,
480 RTINTPTR *poff, void *pvUser));
481/** Pointer to a FNDISGETSYMBOL(). */
482typedef FNDISGETSYMBOL *PFNDISGETSYMBOL;
483
484/**
485 * Checks if the FNDISGETSYMBOL argument u32Sel is a register or not.
486 */
487#define DIS_FMT_SEL_IS_REG(u32Sel) ( !!((u32Sel) & RT_BIT(31)) )
488
489/**
490 * Extracts the selector value from the FNDISGETSYMBOL argument u32Sel.
491 * @returns Selector value.
492 */
493#define DIS_FMT_SEL_GET_VALUE(u32Sel) ( (RTSEL)(u32Sel) )
494
495/**
496 * Extracts the register number from the FNDISGETSYMBOL argument u32Sel.
497 * @returns USE_REG_CS, USE_REG_SS, USE_REG_DS, USE_REG_ES, USE_REG_FS or USE_REG_FS.
498 */
499#define DIS_FMT_SEL_GET_REG(u32Sel) ( ((u32Sel) >> 16) & 0xf )
500
501/** @internal */
502#define DIS_FMT_SEL_FROM_REG(uReg) ( ((uReg) << 16) | RT_BIT(31) | 0xffff )
503/** @internal */
504#define DIS_FMT_SEL_FROM_VALUE(Sel) ( (Sel) & 0xffff )
505
506
507/** @name Flags for use with DISFormatYasmEx(), DISFormatMasmEx(),
508 * DISFormatGasEx() and DISFormatArmV8Ex().
509 * @{
510 */
511/** Put the address to the right. */
512#define DIS_FMT_FLAGS_ADDR_RIGHT RT_BIT_32(0)
513/** Put the address to the left. */
514#define DIS_FMT_FLAGS_ADDR_LEFT RT_BIT_32(1)
515/** Put the address in comments.
516 * For some assemblers this implies placing it to the right. */
517#define DIS_FMT_FLAGS_ADDR_COMMENT RT_BIT_32(2)
518/** Put the instruction bytes to the right of the disassembly. */
519#define DIS_FMT_FLAGS_BYTES_RIGHT RT_BIT_32(3)
520/** Put the instruction bytes to the left of the disassembly. */
521#define DIS_FMT_FLAGS_BYTES_LEFT RT_BIT_32(4)
522/** Put the instruction bytes in comments.
523 * For some assemblers this implies placing the bytes to the right. */
524#define DIS_FMT_FLAGS_BYTES_COMMENT RT_BIT_32(5)
525/** Put the bytes in square brackets. */
526#define DIS_FMT_FLAGS_BYTES_BRACKETS RT_BIT_32(6)
527/** Put spaces between the bytes. */
528#define DIS_FMT_FLAGS_BYTES_SPACED RT_BIT_32(7)
529/** Gives the width (in opcode bytes) of the opcode bytes area if on the left
530 * side. If zero, then a default of 7 will be used. */
531#define DIS_FMT_FLAGS_BYTES_WIDTH_MASK UINT32_C(0x00001f00)
532/** Shift count of the bytes width field. */
533#define DIS_FMT_FLAGS_BYTES_WIDTH_SHIFT 8
534/** Helper that makes shift the width count. */
535#define DIS_FMT_FLAGS_BYTES_WIDTH_MAKE(a_cb) ((uint32_t)(a_cb) << DIS_FMT_FLAGS_BYTES_WIDTH_SHIFT)
536/** Display the relative +/- offset of branch instructions that uses relative addresses,
537 * and put the target address in parenthesis. */
538#define DIS_FMT_FLAGS_RELATIVE_BRANCH RT_BIT_32(13)
539/** Strict assembly. The assembly should, when ever possible, make the
540 * assembler reproduce the exact same binary. (Refers to the yasm
541 * strict keyword.) */
542#define DIS_FMT_FLAGS_STRICT RT_BIT_32(14)
543/** C-style hex formatting (0x01), rather than assembly style (001h). */
544#define DIS_FMT_FLAGS_C_HEX RT_BIT_32(15)
545
546/** Checks if the given flags are a valid combination. */
547#define DIS_FMT_FLAGS_IS_VALID(fFlags) \
548 ( !((fFlags) & ~UINT32_C(0x0000ffff)) \
549 && ((fFlags) & (DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT)) != (DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT) \
550 && ( !((fFlags) & DIS_FMT_FLAGS_ADDR_COMMENT) \
551 || (fFlags & (DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT)) ) \
552 && ((fFlags) & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT)) != (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT) \
553 && ( !((fFlags) & (DIS_FMT_FLAGS_BYTES_COMMENT | DIS_FMT_FLAGS_BYTES_BRACKETS)) \
554 || (fFlags & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT)) ) \
555 )
556/** @} */
557
558DISDECL(size_t) DISFormatYasm( PCDISSTATE pDis, char *pszBuf, size_t cchBuf);
559DISDECL(size_t) DISFormatYasmEx(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
560DISDECL(size_t) DISFormatMasm( PCDISSTATE pDis, char *pszBuf, size_t cchBuf);
561DISDECL(size_t) DISFormatMasmEx(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
562DISDECL(size_t) DISFormatGas( PCDISSTATE pDis, char *pszBuf, size_t cchBuf);
563DISDECL(size_t) DISFormatGasEx( PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
564
565DISDECL(size_t) DISFormatArmV8( PCDISSTATE pDis, char *pszBuf, size_t cchBuf);
566DISDECL(size_t) DISFormatArmV8Ex(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
567
568/** @todo DISAnnotate(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, register
569 * reader, memory reader); */
570
571/** @} */
572
573RT_C_DECLS_END
574
575#endif /* !VBOX_INCLUDED_dis_h */
576
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use