VirtualBox

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

Last change on this file was 105858, checked in by vboxsync, 12 days ago

Disassembler/ARMv8: Implement decoding of the ldr/str (pre-/post-indexed) variant instructions and add testcases, bugref:10394

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.8 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/** MSR on x86, system register on ARMv8. */
206#define DISUSE_REG_SYSTEM RT_BIT_64(37)
207/** Pre-indexed parameter. */
208#define DISUSE_PRE_INDEXED RT_BIT_64(38)
209/** Post-indexed parameter. */
210#define DISUSE_POST_INDEXED RT_BIT_64(39)
211
212/** Mask of immediate use flags. */
213#define DISUSE_IMMEDIATE ( DISUSE_IMMEDIATE8 \
214 | DISUSE_IMMEDIATE16 \
215 | DISUSE_IMMEDIATE32 \
216 | DISUSE_IMMEDIATE64 \
217 | DISUSE_IMMEDIATE8_REL \
218 | DISUSE_IMMEDIATE16_REL \
219 | DISUSE_IMMEDIATE32_REL \
220 | DISUSE_IMMEDIATE64_REL \
221 | DISUSE_IMMEDIATE_ADDR_0_32 \
222 | DISUSE_IMMEDIATE_ADDR_16_32 \
223 | DISUSE_IMMEDIATE_ADDR_0_16 \
224 | DISUSE_IMMEDIATE_ADDR_16_16 \
225 | DISUSE_IMMEDIATE16_SX8 \
226 | DISUSE_IMMEDIATE32_SX8 \
227 | DISUSE_IMMEDIATE64_SX8)
228/** Check if the use flags indicates an effective address. */
229#define DISUSE_IS_EFFECTIVE_ADDR(a_fUseFlags) (!!( (a_fUseFlags) \
230 & ( DISUSE_BASE \
231 | DISUSE_INDEX \
232 | DISUSE_DISPLACEMENT32 \
233 | DISUSE_DISPLACEMENT64 \
234 | DISUSE_DISPLACEMENT16 \
235 | DISUSE_DISPLACEMENT8 \
236 | DISUSE_RIPDISPLACEMENT32) ))
237/** @} */
238
239
240/**
241 * Opcode parameter (operand) details.
242 */
243typedef struct DISOPPARAM
244{
245 /** A combination of DISUSE_XXX. */
246 uint64_t fUse;
247 /** Immediate value or address, applicable if any of the flags included in
248 * DISUSE_IMMEDIATE are set in fUse. */
249 uint64_t uValue;
250
251 /** Architecture specific parameter state. */
252 RT_GCC_EXTENSION union
253 {
254 /** x86/AMD64 specific state. */
255 DIS_OP_PARAM_X86_T x86;
256#if defined(VBOX_DIS_WITH_ARMV8)
257 /** ARMv8 specific state. */
258 DIS_OP_PARAM_ARMV8_T armv8;
259#endif
260 };
261} DISOPPARAM;
262AssertCompileSize(DISOPPARAM, 32);
263/** Pointer to opcode parameter. */
264typedef const DISOPPARAM *PCDISOPPARAM;
265
266
267/**
268 * Callback for reading instruction bytes.
269 *
270 * @returns VBox status code, bytes in DISSTATE::Instr::ab and byte count in
271 * DISSTATE::cbCachedInstr.
272 * @param pDis Pointer to the disassembler state. The user
273 * argument can be found in DISSTATE::pvUser if needed.
274 * @param offInstr The offset relative to the start of the instruction.
275 *
276 * To get the source address, add this to
277 * DISSTATE::uInstrAddr.
278 *
279 * To calculate the destination buffer address, use it
280 * as an index into DISSTATE::Instr::ab.
281 *
282 * @param cbMinRead The minimum number of bytes to read.
283 * @param cbMaxRead The maximum number of bytes that may be read.
284 */
285typedef DECLCALLBACKTYPE(int, FNDISREADBYTES,(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead));
286/** Pointer to a opcode byte reader. */
287typedef FNDISREADBYTES *PFNDISREADBYTES;
288
289
290/**
291 * The diassembler state and result.
292 */
293typedef struct DISSTATE
294{
295 /** The different instruction views.
296 * @sa cbCachedInstr, FNDISREADBYTES */
297 union
298 {
299 /** Byte (8-bit) view.
300 * This is the one referred to by FNDISREADBYTES and cbCached. */
301 uint8_t ab[16];
302 /** Single 16-bit view. */
303 uint16_t u16;
304 /** Single 32-bit view. */
305 uint32_t u32;
306 /** 16-bit view. */
307 uint16_t au16[8];
308 /** 32-bit view. */
309 uint32_t au32[4];
310 /** 64-bit view. */
311 uint64_t au64[2];
312 } Instr;
313
314 /** Pointer to the current instruction. */
315 PCDISOPCODE pCurInstr;
316#if ARCH_BITS == 32
317 uint32_t uPtrPadding2;
318#endif
319
320 /** Array of opcode parameters. */
321 DISOPPARAM aParams[4];
322
323 /** The number of valid bytes in DISSTATE::Instr. */
324 uint8_t cbCachedInstr;
325 /** The CPU mode (DISCPUMODE). */
326 uint8_t uCpuMode;
327 /** The instruction size. */
328 uint8_t cbInstr;
329 /** Unused bytes. */
330 uint8_t abUnused[1];
331
332 /** Return code set by a worker function like the opcode bytes readers. */
333 int32_t rc;
334 /** The address of the instruction. */
335 RTUINTPTR uInstrAddr;
336 /** Optional read function */
337 PFNDISREADBYTES pfnReadBytes;
338#if ARCH_BITS == 32
339 uint32_t uPadding3;
340#endif
341 /** User data supplied as an argument to the APIs. */
342 void *pvUser;
343#if ARCH_BITS == 32
344 uint32_t uPadding4;
345#endif
346
347 /** Architecture specific state. */
348 RT_GCC_EXTENSION union
349 {
350 /** x86/AMD64 specific state. */
351 DIS_STATE_X86_T x86;
352#if defined(VBOX_DIS_WITH_ARMV8)
353 /** ARMv8 specific state. */
354 DIS_STATE_ARMV8_T armv8;
355#endif
356 };
357} DISSTATE;
358AssertCompileMemberAlignment(DISSTATE, x86, 8);
359AssertCompileSize(DISSTATE, 0xd8);
360
361
362
363DISDECL(int) DISInstrToStr(void const *pvInstr, DISCPUMODE enmCpuMode,
364 PDISSTATE pDis, uint32_t *pcbInstr, char *pszOutput, size_t cbOutput);
365DISDECL(int) DISInstrToStrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
366 PDISSTATE pDis, uint32_t *pcbInstr, char *pszOutput, size_t cbOutput);
367DISDECL(int) DISInstrToStrEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode,
368 PFNDISREADBYTES pfnReadBytes, void *pvUser, uint32_t uFilter,
369 PDISSTATE pDis, uint32_t *pcbInstr, char *pszOutput, size_t cbOutput);
370
371DISDECL(int) DISInstr(void const *pvInstr, DISCPUMODE enmCpuMode, PDISSTATE pDis, uint32_t *pcbInstr);
372DISDECL(int) DISInstrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
373 PDISSTATE pDis, uint32_t *pcbInstr);
374DISDECL(int) DISInstrEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t uFilter,
375 PFNDISREADBYTES pfnReadBytes, void *pvUser,
376 PDISSTATE pDis, uint32_t *pcbInstr);
377DISDECL(int) DISInstrWithPrefetchedBytes(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
378 void const *pvPrefetched, size_t cbPretched,
379 PFNDISREADBYTES pfnReadBytes, void *pvUser,
380 PDISSTATE pDis, uint32_t *pcbInstr);
381
382DISDECL(uint8_t) DISGetParamSize(PCDISSTATE pDis, PCDISOPPARAM pParam);
383#if 0 /* unused */
384DISDECL(DISSELREG) DISDetectSegReg(PCDISSTATE pDis, PCDISOPPARAM pParam);
385DISDECL(uint8_t) DISQuerySegPrefixByte(PCDISSTATE pDis);
386#endif
387
388#if 0 /* Needs refactoring if we want to use this again, CPUMCTXCORE is history. */
389/** @name Flags returned by DISQueryParamVal (DISQPVPARAMVAL::flags).
390 * @{
391 */
392#define DISQPV_FLAG_8 UINT8_C(0x01)
393#define DISQPV_FLAG_16 UINT8_C(0x02)
394#define DISQPV_FLAG_32 UINT8_C(0x04)
395#define DISQPV_FLAG_64 UINT8_C(0x08)
396#define DISQPV_FLAG_FARPTR16 UINT8_C(0x10)
397#define DISQPV_FLAG_FARPTR32 UINT8_C(0x20)
398/** @} */
399
400/** @name Types returned by DISQueryParamVal (DISQPVPARAMVAL::flags).
401 * @{ */
402#define DISQPV_TYPE_REGISTER UINT8_C(1)
403#define DISQPV_TYPE_ADDRESS UINT8_C(2)
404#define DISQPV_TYPE_IMMEDIATE UINT8_C(3)
405/** @} */
406
407typedef struct
408{
409 union
410 {
411 uint8_t val8;
412 uint16_t val16;
413 uint32_t val32;
414 uint64_t val64;
415
416 int8_t i8;
417 int16_t i16;
418 int32_t i32;
419 int64_t i64;
420
421 struct
422 {
423 uint16_t sel;
424 uint32_t offset;
425 } farptr;
426 } val;
427
428 uint8_t type;
429 uint8_t size;
430 uint8_t flags;
431} DISQPVPARAMVAL;
432/** Pointer to opcode parameter value. */
433typedef DISQPVPARAMVAL *PDISQPVPARAMVAL;
434
435/** Indicates which parameter DISQueryParamVal should operate on. */
436typedef enum DISQPVWHICH
437{
438 DISQPVWHICH_DST = 1,
439 DISQPVWHICH_SRC,
440 DISQPVWHAT_32_BIT_HACK = 0x7fffffff
441} DISQPVWHICH;
442DISDECL(int) DISQueryParamVal(PCPUMCTXCORE pCtx, PCDISSTATE pDis, PCDISOPPARAM pParam, PDISQPVPARAMVAL pParamVal, DISQPVWHICH parmtype);
443DISDECL(int) DISQueryParamRegPtr(PCPUMCTXCORE pCtx, PCDISSTATE pDis, PCDISOPPARAM pParam, void **ppReg, size_t *pcbSize);
444
445DISDECL(int) DISFetchReg8(PCCPUMCTXCORE pCtx, unsigned reg8, uint8_t *pVal);
446DISDECL(int) DISFetchReg16(PCCPUMCTXCORE pCtx, unsigned reg16, uint16_t *pVal);
447DISDECL(int) DISFetchReg32(PCCPUMCTXCORE pCtx, unsigned reg32, uint32_t *pVal);
448DISDECL(int) DISFetchReg64(PCCPUMCTXCORE pCtx, unsigned reg64, uint64_t *pVal);
449DISDECL(int) DISFetchRegSeg(PCCPUMCTXCORE pCtx, DISSELREG sel, RTSEL *pVal);
450DISDECL(int) DISWriteReg8(PCPUMCTXCORE pRegFrame, unsigned reg8, uint8_t val8);
451DISDECL(int) DISWriteReg16(PCPUMCTXCORE pRegFrame, unsigned reg32, uint16_t val16);
452DISDECL(int) DISWriteReg32(PCPUMCTXCORE pRegFrame, unsigned reg32, uint32_t val32);
453DISDECL(int) DISWriteReg64(PCPUMCTXCORE pRegFrame, unsigned reg64, uint64_t val64);
454DISDECL(int) DISWriteRegSeg(PCPUMCTXCORE pCtx, DISSELREG sel, RTSEL val);
455DISDECL(int) DISPtrReg8(PCPUMCTXCORE pCtx, unsigned reg8, uint8_t **ppReg);
456DISDECL(int) DISPtrReg16(PCPUMCTXCORE pCtx, unsigned reg16, uint16_t **ppReg);
457DISDECL(int) DISPtrReg32(PCPUMCTXCORE pCtx, unsigned reg32, uint32_t **ppReg);
458DISDECL(int) DISPtrReg64(PCPUMCTXCORE pCtx, unsigned reg64, uint64_t **ppReg);
459#endif /* obsolete */
460
461
462/**
463 * Try resolve an address into a symbol name.
464 *
465 * For use with DISFormatYasmEx(), DISFormatMasmEx() and DISFormatGasEx().
466 *
467 * @returns VBox status code.
468 * @retval VINF_SUCCESS on success, pszBuf contains the full symbol name.
469 * @retval VINF_BUFFER_OVERFLOW if pszBuf is too small the symbol name. The
470 * content of pszBuf is truncated and zero terminated.
471 * @retval VERR_SYMBOL_NOT_FOUND if no matching symbol was found for the address.
472 *
473 * @param pDis Pointer to the disassembler CPU state.
474 * @param u32Sel The selector value. Use DIS_FMT_SEL_IS_REG, DIS_FMT_SEL_GET_VALUE,
475 * DIS_FMT_SEL_GET_REG to access this.
476 * @param uAddress The segment address.
477 * @param pszBuf Where to store the symbol name
478 * @param cchBuf The size of the buffer.
479 * @param poff If not a perfect match, then this is where the offset from the return
480 * symbol to the specified address is returned.
481 * @param pvUser The user argument.
482 */
483typedef DECLCALLBACKTYPE(int, FNDISGETSYMBOL,(PCDISSTATE pDis, uint32_t u32Sel, RTUINTPTR uAddress, char *pszBuf, size_t cchBuf,
484 RTINTPTR *poff, void *pvUser));
485/** Pointer to a FNDISGETSYMBOL(). */
486typedef FNDISGETSYMBOL *PFNDISGETSYMBOL;
487
488/**
489 * Checks if the FNDISGETSYMBOL argument u32Sel is a register or not.
490 */
491#define DIS_FMT_SEL_IS_REG(u32Sel) ( !!((u32Sel) & RT_BIT(31)) )
492
493/**
494 * Extracts the selector value from the FNDISGETSYMBOL argument u32Sel.
495 * @returns Selector value.
496 */
497#define DIS_FMT_SEL_GET_VALUE(u32Sel) ( (RTSEL)(u32Sel) )
498
499/**
500 * Extracts the register number from the FNDISGETSYMBOL argument u32Sel.
501 * @returns USE_REG_CS, USE_REG_SS, USE_REG_DS, USE_REG_ES, USE_REG_FS or USE_REG_FS.
502 */
503#define DIS_FMT_SEL_GET_REG(u32Sel) ( ((u32Sel) >> 16) & 0xf )
504
505/** @internal */
506#define DIS_FMT_SEL_FROM_REG(uReg) ( ((uReg) << 16) | RT_BIT(31) | 0xffff )
507/** @internal */
508#define DIS_FMT_SEL_FROM_VALUE(Sel) ( (Sel) & 0xffff )
509
510
511/** @name Flags for use with DISFormatYasmEx(), DISFormatMasmEx(),
512 * DISFormatGasEx() and DISFormatArmV8Ex().
513 * @{
514 */
515/** Put the address to the right. */
516#define DIS_FMT_FLAGS_ADDR_RIGHT RT_BIT_32(0)
517/** Put the address to the left. */
518#define DIS_FMT_FLAGS_ADDR_LEFT RT_BIT_32(1)
519/** Put the address in comments.
520 * For some assemblers this implies placing it to the right. */
521#define DIS_FMT_FLAGS_ADDR_COMMENT RT_BIT_32(2)
522/** Put the instruction bytes to the right of the disassembly. */
523#define DIS_FMT_FLAGS_BYTES_RIGHT RT_BIT_32(3)
524/** Put the instruction bytes to the left of the disassembly. */
525#define DIS_FMT_FLAGS_BYTES_LEFT RT_BIT_32(4)
526/** Put the instruction bytes in comments.
527 * For some assemblers this implies placing the bytes to the right. */
528#define DIS_FMT_FLAGS_BYTES_COMMENT RT_BIT_32(5)
529/** Put the bytes in square brackets. */
530#define DIS_FMT_FLAGS_BYTES_BRACKETS RT_BIT_32(6)
531/** Put spaces between the bytes. */
532#define DIS_FMT_FLAGS_BYTES_SPACED RT_BIT_32(7)
533/** Gives the width (in opcode bytes) of the opcode bytes area if on the left
534 * side. If zero, then a default of 7 will be used. */
535#define DIS_FMT_FLAGS_BYTES_WIDTH_MASK UINT32_C(0x00001f00)
536/** Shift count of the bytes width field. */
537#define DIS_FMT_FLAGS_BYTES_WIDTH_SHIFT 8
538/** Helper that makes shift the width count. */
539#define DIS_FMT_FLAGS_BYTES_WIDTH_MAKE(a_cb) ((uint32_t)(a_cb) << DIS_FMT_FLAGS_BYTES_WIDTH_SHIFT)
540/** Display the relative +/- offset of branch instructions that uses relative addresses,
541 * and put the target address in parenthesis. */
542#define DIS_FMT_FLAGS_RELATIVE_BRANCH RT_BIT_32(13)
543/** Strict assembly. The assembly should, when ever possible, make the
544 * assembler reproduce the exact same binary. (Refers to the yasm
545 * strict keyword.) */
546#define DIS_FMT_FLAGS_STRICT RT_BIT_32(14)
547/** C-style hex formatting (0x01), rather than assembly style (001h). */
548#define DIS_FMT_FLAGS_C_HEX RT_BIT_32(15)
549
550/** Checks if the given flags are a valid combination. */
551#define DIS_FMT_FLAGS_IS_VALID(fFlags) \
552 ( !((fFlags) & ~UINT32_C(0x0000ffff)) \
553 && ((fFlags) & (DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT)) != (DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT) \
554 && ( !((fFlags) & DIS_FMT_FLAGS_ADDR_COMMENT) \
555 || (fFlags & (DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT)) ) \
556 && ((fFlags) & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT)) != (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT) \
557 && ( !((fFlags) & (DIS_FMT_FLAGS_BYTES_COMMENT | DIS_FMT_FLAGS_BYTES_BRACKETS)) \
558 || (fFlags & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT)) ) \
559 )
560/** @} */
561
562DISDECL(size_t) DISFormatYasm( PCDISSTATE pDis, char *pszBuf, size_t cchBuf);
563DISDECL(size_t) DISFormatYasmEx(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
564DISDECL(size_t) DISFormatMasm( PCDISSTATE pDis, char *pszBuf, size_t cchBuf);
565DISDECL(size_t) DISFormatMasmEx(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
566DISDECL(size_t) DISFormatGas( PCDISSTATE pDis, char *pszBuf, size_t cchBuf);
567DISDECL(size_t) DISFormatGasEx( PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
568
569DISDECL(size_t) DISFormatArmV8( PCDISSTATE pDis, char *pszBuf, size_t cchBuf);
570DISDECL(size_t) DISFormatArmV8Ex(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
571
572/** @todo DISAnnotate(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, register
573 * reader, memory reader); */
574
575/** @} */
576
577RT_C_DECLS_END
578
579#endif /* !VBOX_INCLUDED_dis_h */
580
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle
ContactPrivacy/Do Not Sell My InfoTerms of Use