VirtualBox

source: vbox/trunk/src/VBox/Disassembler/DisasmInternal.h@ 106378

Last change on this file since 106378 was 106061, checked in by vboxsync, 3 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.5 KB
Line 
1/* $Id: DisasmInternal.h 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * VBox disassembler - Internal header.
4 */
5
6/*
7 * Copyright (C) 2006-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#ifndef VBOX_INCLUDED_SRC_DisasmInternal_h
29#define VBOX_INCLUDED_SRC_DisasmInternal_h
30#ifndef RT_WITHOUT_PRAGMA_ONCE
31# pragma once
32#endif
33
34#include <VBox/types.h>
35#include <VBox/err.h>
36#include <VBox/dis.h>
37#include <VBox/log.h>
38
39#include <iprt/param.h>
40
41
42/** @defgroup grp_dis_int Internals.
43 * @ingroup grp_dis
44 * @{
45 */
46
47/** This must be less or equal to DISSTATE::Instr.ab.
48 * See Vol3A/Table 6-2 and Vol3B/Section22.25 for instance. */
49#define DIS_MAX_INSTR_LENGTH 15
50
51/** Whether we can do unaligned access. */
52#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
53# define DIS_HOST_UNALIGNED_ACCESS_OK
54#endif
55
56
57/** @def OP
58 * Wrapper which initializes an DISOPCODE.
59 * We must use this so that we can exclude unused fields in order
60 * to save precious bytes in the GC version.
61 *
62 * @internal
63 */
64#if DISOPCODE_FORMAT == 0
65# define OP(pszOpcode, idxParse1, idxParse2, idxParse3, opcode, param1, param2, param3, optype) \
66 { pszOpcode, idxParse1, idxParse2, idxParse3, 0, opcode, param1, param2, param3, 0, 0, optype }
67# define OPVEX(pszOpcode, idxParse1, idxParse2, idxParse3, idxParse4, opcode, param1, param2, param3, param4, optype) \
68 { pszOpcode, idxParse1, idxParse2, idxParse3, idxParse4, opcode, param1, param2, param3, param4, 0, optype | DISOPTYPE_X86_SSE }
69
70#elif DISOPCODE_FORMAT == 16
71# define OP(pszOpcode, idxParse1, idxParse2, idxParse3, opcode, param1, param2, param3, optype) \
72 { optype, opcode, idxParse1, idxParse2, param1, param2, idxParse3, param3, 0, 0 }
73# define OPVEX(pszOpcode, idxParse1, idxParse2, idxParse3, idxParse4, opcode, param1, param2, param3, param4, optype) \
74 { optype | DISOPTYPE_X86_SSE, opcode, idxParse1, idxParse2, param1, param2, idxParse3, param3, param4, idxParse4 }
75
76#elif DISOPCODE_FORMAT == 15
77# define OP(pszOpcode, idxParse1, idxParse2, idxParse3, opcode, param1, param2, param3, optype) \
78 { opcode, idxParse1, idxParse2, idxParse3, param1, param2, param3, optype, 0, 0 }
79# define OPVEX(pszOpcode, idxParse1, idxParse2, idxParse3, idxParse4, opcode, param1, param2, param3, param4, optype) \
80 { opcode, idxParse1, idxParse2, idxParse3, param1, param2, param3, optype | DISOPTYPE_X86_SSE, param4, idxParse4 }
81#else
82# error Unsupported DISOPCODE_FORMAT value
83#endif
84
85
86/* Common */
87DECLHIDDEN(void) disReadMore(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMin);
88DECLHIDDEN(uint8_t) disReadByteSlow(PDISSTATE pDis, size_t offInstr);
89DECLHIDDEN(uint16_t) disReadWordSlow(PDISSTATE pDis, size_t offInstr);
90DECLHIDDEN(uint32_t) disReadDWordSlow(PDISSTATE pDis, size_t offInstr);
91DECLHIDDEN(uint64_t) disReadQWordSlow(PDISSTATE pDis, size_t offInstr);
92
93
94/**
95 * Read a byte (8-bit) instruction.
96 *
97 * @returns The requested byte.
98 * @param pDis The disassembler state.
99 * @param uAddress The address.
100 */
101DECL_FORCE_INLINE(uint8_t) disReadByte(PDISSTATE pDis, size_t offInstr)
102{
103 if (offInstr >= pDis->cbCachedInstr)
104 return disReadByteSlow(pDis, offInstr);
105 return pDis->Instr.ab[offInstr];
106}
107
108
109/**
110 * Read a word (16-bit) instruction.
111 *
112 * @returns The requested word.
113 * @param pDis The disassembler state.
114 * @param offInstr The offset of the qword relative to the
115 * instruction.
116 */
117DECL_FORCE_INLINE(uint16_t) disReadWord(PDISSTATE pDis, size_t offInstr)
118{
119 if (offInstr + 2 > pDis->cbCachedInstr)
120 return disReadWordSlow(pDis, offInstr);
121
122#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
123 return *(uint16_t const *)&pDis->Instr.ab[offInstr];
124#else
125 return RT_MAKE_U16(pDis->Instr.ab[offInstr], pDis->Instr.ab[offInstr + 1]);
126#endif
127}
128
129
130/**
131 * Read a dword (32-bit) instruction.
132 *
133 * @returns The requested dword.
134 * @param pDis The disassembler state.
135 * @param offInstr The offset of the qword relative to the
136 * instruction.
137 */
138DECL_FORCE_INLINE(uint32_t) disReadDWord(PDISSTATE pDis, size_t offInstr)
139{
140 if (offInstr + 4 > pDis->cbCachedInstr)
141 return disReadDWordSlow(pDis, offInstr);
142
143#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
144 return *(uint32_t const *)&pDis->Instr.ab[offInstr];
145#else
146 return RT_MAKE_U32_FROM_U8(pDis->Instr.ab[offInstr ], pDis->Instr.ab[offInstr + 1],
147 pDis->Instr.ab[offInstr + 2], pDis->Instr.ab[offInstr + 3]);
148#endif
149}
150
151
152/**
153 * Read a qword (64-bit) instruction.
154 *
155 * @returns The requested qword.
156 * @param pDis The disassembler state.
157 * @param uAddress The address.
158 */
159DECL_FORCE_INLINE(uint64_t) disReadQWord(PDISSTATE pDis, size_t offInstr)
160{
161 if (offInstr + 8 > pDis->cbCachedInstr)
162 return disReadQWordSlow(pDis, offInstr);
163
164#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
165 return *(uint64_t const *)&pDis->Instr.ab[offInstr];
166#else
167 return RT_MAKE_U64_FROM_U8(pDis->Instr.ab[offInstr ], pDis->Instr.ab[offInstr + 1],
168 pDis->Instr.ab[offInstr + 2], pDis->Instr.ab[offInstr + 3],
169 pDis->Instr.ab[offInstr + 4], pDis->Instr.ab[offInstr + 5],
170 pDis->Instr.ab[offInstr + 6], pDis->Instr.ab[offInstr + 7]);
171#endif
172}
173
174
175/**
176 * Reads some bytes into the cache.
177 *
178 * While this will set DISSTATE::rc on failure, the caller should disregard
179 * this since that is what would happen if we didn't prefetch bytes prior to the
180 * instruction parsing.
181 *
182 * @param pDis The disassembler state.
183 */
184DECL_FORCE_INLINE(void) disPrefetchBytes(PDISSTATE pDis)
185{
186 /*
187 * Read some bytes into the cache. (If this fail we continue as nothing
188 * has gone wrong since this is what would happen if we didn't precharge
189 * the cache here.)
190 */
191 int rc = pDis->pfnReadBytes(pDis, 0, 1, sizeof(pDis->Instr.ab));
192 if (RT_SUCCESS(rc))
193 {
194 Assert(pDis->cbCachedInstr >= 1);
195 Assert(pDis->cbCachedInstr <= sizeof(pDis->Instr.ab));
196 }
197 else
198 {
199 Log(("Initial read failed with rc=%Rrc!!\n", rc));
200 pDis->rc = rc;
201 }
202}
203
204
205#if defined(VBOX_DIS_WITH_X86_AMD64)
206DECLHIDDEN(PCDISOPCODE) disInitializeStateX86(PDISSTATE pDis, DISCPUMODE enmCpuMode, uint32_t fFilter);
207DECLHIDDEN(int) disInstrWorkerX86(PDISSTATE pDis, PCDISOPCODE paOneByteMap, uint32_t *pcbInstr);
208#endif
209#if defined(VBOX_DIS_WITH_ARMV8)
210DECLHIDDEN(PCDISOPCODE) disInitializeStateArmV8(PDISSTATE pDis, DISCPUMODE enmCpuMode, uint32_t fFilter);
211DECLHIDDEN(int) disInstrWorkerArmV8(PDISSTATE pDis, PCDISOPCODE paOneByteMap, uint32_t *pcbInstr);
212#endif
213
214size_t disFormatBytes(PCDISSTATE pDis, char *pszDst, size_t cchDst, uint32_t fFlags);
215
216/** @} */
217#endif /* !VBOX_INCLUDED_SRC_DisasmInternal_h */
218
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