VirtualBox

source: vbox/trunk/src/VBox/Disassembler/DisasmReg.cpp

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
  • Property svn:sync_process set to export
File size: 25.6 KB
Line 
1/* $Id: DisasmReg.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBox disassembler- Register Info Helpers.
4 */
5
6/*
7 * Copyright (C) 2006-2023 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
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_DIS
33#include <VBox/dis.h>
34#include <VBox/disopcode.h>
35#include <iprt/errcore.h>
36#include <VBox/log.h>
37#include <VBox/vmm/cpum.h>
38#include <iprt/assert.h>
39#include <iprt/string.h>
40#include <iprt/stdarg.h>
41#include "DisasmInternal.h"
42
43
44/*********************************************************************************************************************************
45* Global Variables *
46*********************************************************************************************************************************/
47/**
48 * Array for accessing 64-bit general registers in VMMREGFRAME structure
49 * by register's index from disasm.
50 */
51static const unsigned g_aReg64Index[] =
52{
53 RT_OFFSETOF(CPUMCTXCORE, rax), /* DISGREG_RAX */
54 RT_OFFSETOF(CPUMCTXCORE, rcx), /* DISGREG_RCX */
55 RT_OFFSETOF(CPUMCTXCORE, rdx), /* DISGREG_RDX */
56 RT_OFFSETOF(CPUMCTXCORE, rbx), /* DISGREG_RBX */
57 RT_OFFSETOF(CPUMCTXCORE, rsp), /* DISGREG_RSP */
58 RT_OFFSETOF(CPUMCTXCORE, rbp), /* DISGREG_RBP */
59 RT_OFFSETOF(CPUMCTXCORE, rsi), /* DISGREG_RSI */
60 RT_OFFSETOF(CPUMCTXCORE, rdi), /* DISGREG_RDI */
61 RT_OFFSETOF(CPUMCTXCORE, r8), /* DISGREG_R8 */
62 RT_OFFSETOF(CPUMCTXCORE, r9), /* DISGREG_R9 */
63 RT_OFFSETOF(CPUMCTXCORE, r10), /* DISGREG_R10 */
64 RT_OFFSETOF(CPUMCTXCORE, r11), /* DISGREG_R11 */
65 RT_OFFSETOF(CPUMCTXCORE, r12), /* DISGREG_R12 */
66 RT_OFFSETOF(CPUMCTXCORE, r13), /* DISGREG_R13 */
67 RT_OFFSETOF(CPUMCTXCORE, r14), /* DISGREG_R14 */
68 RT_OFFSETOF(CPUMCTXCORE, r15) /* DISGREG_R15 */
69};
70
71/**
72 * Macro for accessing 64-bit general purpose registers in CPUMCTXCORE structure.
73 */
74#define DIS_READ_REG64(p, idx) (*(uint64_t *)((char *)(p) + g_aReg64Index[idx]))
75#define DIS_WRITE_REG64(p, idx, val) (*(uint64_t *)((char *)(p) + g_aReg64Index[idx]) = val)
76#define DIS_PTR_REG64(p, idx) ( (uint64_t *)((char *)(p) + g_aReg64Index[idx]))
77
78/**
79 * Array for accessing 32-bit general registers in VMMREGFRAME structure
80 * by register's index from disasm.
81 */
82static const unsigned g_aReg32Index[] =
83{
84 RT_OFFSETOF(CPUMCTXCORE, eax), /* DISGREG_EAX */
85 RT_OFFSETOF(CPUMCTXCORE, ecx), /* DISGREG_ECX */
86 RT_OFFSETOF(CPUMCTXCORE, edx), /* DISGREG_EDX */
87 RT_OFFSETOF(CPUMCTXCORE, ebx), /* DISGREG_EBX */
88 RT_OFFSETOF(CPUMCTXCORE, esp), /* DISGREG_ESP */
89 RT_OFFSETOF(CPUMCTXCORE, ebp), /* DISGREG_EBP */
90 RT_OFFSETOF(CPUMCTXCORE, esi), /* DISGREG_ESI */
91 RT_OFFSETOF(CPUMCTXCORE, edi), /* DISGREG_EDI */
92 RT_OFFSETOF(CPUMCTXCORE, r8), /* DISGREG_R8D */
93 RT_OFFSETOF(CPUMCTXCORE, r9), /* DISGREG_R9D */
94 RT_OFFSETOF(CPUMCTXCORE, r10), /* DISGREG_R1D */
95 RT_OFFSETOF(CPUMCTXCORE, r11), /* DISGREG_R11D */
96 RT_OFFSETOF(CPUMCTXCORE, r12), /* DISGREG_R12D */
97 RT_OFFSETOF(CPUMCTXCORE, r13), /* DISGREG_R13D */
98 RT_OFFSETOF(CPUMCTXCORE, r14), /* DISGREG_R14D */
99 RT_OFFSETOF(CPUMCTXCORE, r15) /* DISGREG_R15D */
100};
101
102/**
103 * Macro for accessing 32-bit general purpose registers in CPUMCTXCORE structure.
104 */
105#define DIS_READ_REG32(p, idx) (*(uint32_t *)((char *)(p) + g_aReg32Index[idx]))
106/* From http://www.cs.cmu.edu/~fp/courses/15213-s06/misc/asm64-handout.pdf:
107 * ``Perhaps unexpectedly, instructions that move or generate 32-bit register
108 * values also set the upper 32 bits of the register to zero. Consequently
109 * there is no need for an instruction movzlq.''
110 */
111#define DIS_WRITE_REG32(p, idx, val) (*(uint64_t *)((char *)(p) + g_aReg32Index[idx]) = (uint32_t)val)
112#define DIS_PTR_REG32(p, idx) ( (uint32_t *)((char *)(p) + g_aReg32Index[idx]))
113
114/**
115 * Array for accessing 16-bit general registers in CPUMCTXCORE structure
116 * by register's index from disasm.
117 */
118static const unsigned g_aReg16Index[] =
119{
120 RT_OFFSETOF(CPUMCTXCORE, eax), /* DISGREG_AX */
121 RT_OFFSETOF(CPUMCTXCORE, ecx), /* DISGREG_CX */
122 RT_OFFSETOF(CPUMCTXCORE, edx), /* DISGREG_DX */
123 RT_OFFSETOF(CPUMCTXCORE, ebx), /* DISGREG_BX */
124 RT_OFFSETOF(CPUMCTXCORE, esp), /* DISGREG_SP */
125 RT_OFFSETOF(CPUMCTXCORE, ebp), /* DISGREG_BP */
126 RT_OFFSETOF(CPUMCTXCORE, esi), /* DISGREG_SI */
127 RT_OFFSETOF(CPUMCTXCORE, edi), /* DISGREG_DI */
128 RT_OFFSETOF(CPUMCTXCORE, r8), /* DISGREG_R8W */
129 RT_OFFSETOF(CPUMCTXCORE, r9), /* DISGREG_R9W */
130 RT_OFFSETOF(CPUMCTXCORE, r10), /* DISGREG_R10W */
131 RT_OFFSETOF(CPUMCTXCORE, r11), /* DISGREG_R11W */
132 RT_OFFSETOF(CPUMCTXCORE, r12), /* DISGREG_R12W */
133 RT_OFFSETOF(CPUMCTXCORE, r13), /* DISGREG_R13W */
134 RT_OFFSETOF(CPUMCTXCORE, r14), /* DISGREG_R14W */
135 RT_OFFSETOF(CPUMCTXCORE, r15) /* DISGREG_R15W */
136};
137
138/**
139 * Macro for accessing 16-bit general purpose registers in CPUMCTXCORE structure.
140 */
141#define DIS_READ_REG16(p, idx) (*(uint16_t *)((char *)(p) + g_aReg16Index[idx]))
142#define DIS_WRITE_REG16(p, idx, val) (*(uint16_t *)((char *)(p) + g_aReg16Index[idx]) = val)
143#define DIS_PTR_REG16(p, idx) ( (uint16_t *)((char *)(p) + g_aReg16Index[idx]))
144
145/**
146 * Array for accessing 8-bit general registers in CPUMCTXCORE structure
147 * by register's index from disasm.
148 */
149static const unsigned g_aReg8Index[] =
150{
151 RT_OFFSETOF(CPUMCTXCORE, eax), /* DISGREG_AL */
152 RT_OFFSETOF(CPUMCTXCORE, ecx), /* DISGREG_CL */
153 RT_OFFSETOF(CPUMCTXCORE, edx), /* DISGREG_DL */
154 RT_OFFSETOF(CPUMCTXCORE, ebx), /* DISGREG_BL */
155 RT_OFFSETOF_ADD(CPUMCTXCORE, eax, 1), /* DISGREG_AH */
156 RT_OFFSETOF_ADD(CPUMCTXCORE, ecx, 1), /* DISGREG_CH */
157 RT_OFFSETOF_ADD(CPUMCTXCORE, edx, 1), /* DISGREG_DH */
158 RT_OFFSETOF_ADD(CPUMCTXCORE, ebx, 1), /* DISGREG_BH */
159 RT_OFFSETOF(CPUMCTXCORE, r8), /* DISGREG_R8B */
160 RT_OFFSETOF(CPUMCTXCORE, r9), /* DISGREG_R9B */
161 RT_OFFSETOF(CPUMCTXCORE, r10), /* DISGREG_R10B*/
162 RT_OFFSETOF(CPUMCTXCORE, r11), /* DISGREG_R11B */
163 RT_OFFSETOF(CPUMCTXCORE, r12), /* DISGREG_R12B */
164 RT_OFFSETOF(CPUMCTXCORE, r13), /* DISGREG_R13B */
165 RT_OFFSETOF(CPUMCTXCORE, r14), /* DISGREG_R14B */
166 RT_OFFSETOF(CPUMCTXCORE, r15), /* DISGREG_R15B */
167 RT_OFFSETOF(CPUMCTXCORE, esp), /* DISGREG_SPL; with REX prefix only */
168 RT_OFFSETOF(CPUMCTXCORE, ebp), /* DISGREG_BPL; with REX prefix only */
169 RT_OFFSETOF(CPUMCTXCORE, esi), /* DISGREG_SIL; with REX prefix only */
170 RT_OFFSETOF(CPUMCTXCORE, edi) /* DISGREG_DIL; with REX prefix only */
171};
172
173/**
174 * Macro for accessing 8-bit general purpose registers in CPUMCTXCORE structure.
175 */
176#define DIS_READ_REG8(p, idx) (*(uint8_t *)((char *)(p) + g_aReg8Index[idx]))
177#define DIS_WRITE_REG8(p, idx, val) (*(uint8_t *)((char *)(p) + g_aReg8Index[idx]) = val)
178#define DIS_PTR_REG8(p, idx) ( (uint8_t *)((char *)(p) + g_aReg8Index[idx]))
179
180/**
181 * Array for accessing segment registers in CPUMCTXCORE structure
182 * by register's index from disasm.
183 */
184static const unsigned g_aRegSegIndex[] =
185{
186 RT_OFFSETOF(CPUMCTXCORE, es), /* DISSELREG_ES */
187 RT_OFFSETOF(CPUMCTXCORE, cs), /* DISSELREG_CS */
188 RT_OFFSETOF(CPUMCTXCORE, ss), /* DISSELREG_SS */
189 RT_OFFSETOF(CPUMCTXCORE, ds), /* DISSELREG_DS */
190 RT_OFFSETOF(CPUMCTXCORE, fs), /* DISSELREG_FS */
191 RT_OFFSETOF(CPUMCTXCORE, gs) /* DISSELREG_GS */
192};
193
194/**
195 * Macro for accessing segment registers in CPUMCTXCORE structure.
196 */
197#define DIS_READ_REGSEG(p, idx) (*((uint16_t *)((char *)(p) + g_aRegSegIndex[idx])))
198#define DIS_WRITE_REGSEG(p, idx, val) (*((uint16_t *)((char *)(p) + g_aRegSegIndex[idx])) = val)
199
200
201
202/**
203 * Returns the value of the specified 8 bits general purpose register
204 *
205 */
206DISDECL(int) DISFetchReg8(PCCPUMCTXCORE pCtx, unsigned reg8, uint8_t *pVal)
207{
208 AssertReturnStmt(reg8 < RT_ELEMENTS(g_aReg8Index), *pVal = 0, VERR_INVALID_PARAMETER);
209
210 *pVal = DIS_READ_REG8(pCtx, reg8);
211 return VINF_SUCCESS;
212}
213
214/**
215 * Returns the value of the specified 16 bits general purpose register
216 *
217 */
218DISDECL(int) DISFetchReg16(PCCPUMCTXCORE pCtx, unsigned reg16, uint16_t *pVal)
219{
220 AssertReturnStmt(reg16 < RT_ELEMENTS(g_aReg16Index), *pVal = 0, VERR_INVALID_PARAMETER);
221
222 *pVal = DIS_READ_REG16(pCtx, reg16);
223 return VINF_SUCCESS;
224}
225
226/**
227 * Returns the value of the specified 32 bits general purpose register
228 *
229 */
230DISDECL(int) DISFetchReg32(PCCPUMCTXCORE pCtx, unsigned reg32, uint32_t *pVal)
231{
232 AssertReturnStmt(reg32 < RT_ELEMENTS(g_aReg32Index), *pVal = 0, VERR_INVALID_PARAMETER);
233
234 *pVal = DIS_READ_REG32(pCtx, reg32);
235 return VINF_SUCCESS;
236}
237
238/**
239 * Returns the value of the specified 64 bits general purpose register
240 *
241 */
242DISDECL(int) DISFetchReg64(PCCPUMCTXCORE pCtx, unsigned reg64, uint64_t *pVal)
243{
244 AssertReturnStmt(reg64 < RT_ELEMENTS(g_aReg64Index), *pVal = 0, VERR_INVALID_PARAMETER);
245
246 *pVal = DIS_READ_REG64(pCtx, reg64);
247 return VINF_SUCCESS;
248}
249
250/**
251 * Returns the pointer to the specified 8 bits general purpose register
252 *
253 */
254DISDECL(int) DISPtrReg8(PCPUMCTXCORE pCtx, unsigned reg8, uint8_t **ppReg)
255{
256 AssertReturnStmt(reg8 < RT_ELEMENTS(g_aReg8Index), *ppReg = NULL, VERR_INVALID_PARAMETER);
257
258 *ppReg = DIS_PTR_REG8(pCtx, reg8);
259 return VINF_SUCCESS;
260}
261
262/**
263 * Returns the pointer to the specified 16 bits general purpose register
264 *
265 */
266DISDECL(int) DISPtrReg16(PCPUMCTXCORE pCtx, unsigned reg16, uint16_t **ppReg)
267{
268 AssertReturnStmt(reg16 < RT_ELEMENTS(g_aReg16Index), *ppReg = NULL, VERR_INVALID_PARAMETER);
269
270 *ppReg = DIS_PTR_REG16(pCtx, reg16);
271 return VINF_SUCCESS;
272}
273
274/**
275 * Returns the pointer to the specified 32 bits general purpose register
276 */
277DISDECL(int) DISPtrReg32(PCPUMCTXCORE pCtx, unsigned reg32, uint32_t **ppReg)
278{
279 AssertReturnStmt(reg32 < RT_ELEMENTS(g_aReg32Index), *ppReg = NULL, VERR_INVALID_PARAMETER);
280
281 *ppReg = DIS_PTR_REG32(pCtx, reg32);
282 return VINF_SUCCESS;
283}
284
285/**
286 * Returns the pointer to the specified 64 bits general purpose register
287 */
288DISDECL(int) DISPtrReg64(PCPUMCTXCORE pCtx, unsigned reg64, uint64_t **ppReg)
289{
290 AssertReturnStmt(reg64 < RT_ELEMENTS(g_aReg64Index), *ppReg = NULL, VERR_INVALID_PARAMETER);
291
292 *ppReg = DIS_PTR_REG64(pCtx, reg64);
293 return VINF_SUCCESS;
294}
295
296/**
297 * Returns the value of the specified segment register
298 */
299DISDECL(int) DISFetchRegSeg(PCCPUMCTXCORE pCtx, DISSELREG sel, RTSEL *pVal)
300{
301 AssertReturn((unsigned)sel < RT_ELEMENTS(g_aRegSegIndex), VERR_INVALID_PARAMETER);
302
303 AssertCompile(sizeof(uint16_t) == sizeof(RTSEL));
304 *pVal = DIS_READ_REGSEG(pCtx, sel);
305 return VINF_SUCCESS;
306}
307
308/**
309 * Updates the value of the specified 64 bits general purpose register
310 *
311 */
312DISDECL(int) DISWriteReg64(PCPUMCTXCORE pRegFrame, unsigned reg64, uint64_t val64)
313{
314 AssertReturn(reg64 < RT_ELEMENTS(g_aReg64Index), VERR_INVALID_PARAMETER);
315
316 DIS_WRITE_REG64(pRegFrame, reg64, val64);
317 return VINF_SUCCESS;
318}
319
320/**
321 * Updates the value of the specified 32 bits general purpose register
322 *
323 */
324DISDECL(int) DISWriteReg32(PCPUMCTXCORE pRegFrame, unsigned reg32, uint32_t val32)
325{
326 AssertReturn(reg32 < RT_ELEMENTS(g_aReg32Index), VERR_INVALID_PARAMETER);
327
328 DIS_WRITE_REG32(pRegFrame, reg32, val32);
329 return VINF_SUCCESS;
330}
331
332/**
333 * Updates the value of the specified 16 bits general purpose register
334 *
335 */
336DISDECL(int) DISWriteReg16(PCPUMCTXCORE pRegFrame, unsigned reg16, uint16_t val16)
337{
338 AssertReturn(reg16 < RT_ELEMENTS(g_aReg16Index), VERR_INVALID_PARAMETER);
339
340 DIS_WRITE_REG16(pRegFrame, reg16, val16);
341 return VINF_SUCCESS;
342}
343
344/**
345 * Updates the specified 8 bits general purpose register
346 *
347 */
348DISDECL(int) DISWriteReg8(PCPUMCTXCORE pRegFrame, unsigned reg8, uint8_t val8)
349{
350 AssertReturn(reg8 < RT_ELEMENTS(g_aReg8Index), VERR_INVALID_PARAMETER);
351
352 DIS_WRITE_REG8(pRegFrame, reg8, val8);
353 return VINF_SUCCESS;
354}
355
356/**
357 * Updates the specified segment register
358 *
359 */
360DISDECL(int) DISWriteRegSeg(PCPUMCTXCORE pCtx, DISSELREG sel, RTSEL val)
361{
362 AssertReturn((unsigned)sel < RT_ELEMENTS(g_aRegSegIndex), VERR_INVALID_PARAMETER);
363
364 AssertCompile(sizeof(uint16_t) == sizeof(RTSEL));
365 DIS_WRITE_REGSEG(pCtx, sel, val);
366 return VINF_SUCCESS;
367}
368
369/**
370 * Returns the value of the parameter in pParam
371 *
372 * @returns VBox error code
373 * @param pCtx CPU context structure pointer
374 * @param pDis Pointer to the disassembler state.
375 * @param pParam Pointer to the parameter to parse
376 * @param pParamVal Pointer to parameter value (OUT)
377 * @param parmtype Parameter type
378 *
379 * @note Currently doesn't handle FPU/XMM/MMX/3DNow! parameters correctly!!
380 *
381 */
382DISDECL(int) DISQueryParamVal(PCPUMCTXCORE pCtx, PCDISSTATE pDis, PCDISOPPARAM pParam, PDISQPVPARAMVAL pParamVal, DISQPVWHICH parmtype)
383{
384 memset(pParamVal, 0, sizeof(*pParamVal));
385
386 if (DISUSE_IS_EFFECTIVE_ADDR(pParam->fUse))
387 {
388 // Effective address
389 pParamVal->type = DISQPV_TYPE_ADDRESS;
390 pParamVal->size = pParam->cb;
391
392 if (pParam->fUse & DISUSE_BASE)
393 {
394 if (pParam->fUse & DISUSE_REG_GEN8)
395 {
396 pParamVal->flags |= DISQPV_FLAG_8;
397 if (RT_FAILURE(DISFetchReg8(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val8))) return VERR_INVALID_PARAMETER;
398 }
399 else
400 if (pParam->fUse & DISUSE_REG_GEN16)
401 {
402 pParamVal->flags |= DISQPV_FLAG_16;
403 if (RT_FAILURE(DISFetchReg16(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val16))) return VERR_INVALID_PARAMETER;
404 }
405 else
406 if (pParam->fUse & DISUSE_REG_GEN32)
407 {
408 pParamVal->flags |= DISQPV_FLAG_32;
409 if (RT_FAILURE(DISFetchReg32(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val32))) return VERR_INVALID_PARAMETER;
410 }
411 else
412 if (pParam->fUse & DISUSE_REG_GEN64)
413 {
414 pParamVal->flags |= DISQPV_FLAG_64;
415 if (RT_FAILURE(DISFetchReg64(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val64))) return VERR_INVALID_PARAMETER;
416 }
417 else
418 {
419 AssertFailed();
420 return VERR_INVALID_PARAMETER;
421 }
422 }
423 // Note that scale implies index (SIB byte)
424 if (pParam->fUse & DISUSE_INDEX)
425 {
426 if (pParam->fUse & DISUSE_REG_GEN16)
427 {
428 uint16_t val16;
429
430 pParamVal->flags |= DISQPV_FLAG_16;
431 if (RT_FAILURE(DISFetchReg16(pCtx, pParam->Index.idxGenReg, &val16))) return VERR_INVALID_PARAMETER;
432
433 Assert(!(pParam->fUse & DISUSE_SCALE)); /* shouldn't be possible in 16 bits mode */
434
435 pParamVal->val.val16 += val16;
436 }
437 else
438 if (pParam->fUse & DISUSE_REG_GEN32)
439 {
440 uint32_t val32;
441
442 pParamVal->flags |= DISQPV_FLAG_32;
443 if (RT_FAILURE(DISFetchReg32(pCtx, pParam->Index.idxGenReg, &val32))) return VERR_INVALID_PARAMETER;
444
445 if (pParam->fUse & DISUSE_SCALE)
446 val32 *= pParam->uScale;
447
448 pParamVal->val.val32 += val32;
449 }
450 else
451 if (pParam->fUse & DISUSE_REG_GEN64)
452 {
453 uint64_t val64;
454
455 pParamVal->flags |= DISQPV_FLAG_64;
456 if (RT_FAILURE(DISFetchReg64(pCtx, pParam->Index.idxGenReg, &val64))) return VERR_INVALID_PARAMETER;
457
458 if (pParam->fUse & DISUSE_SCALE)
459 val64 *= pParam->uScale;
460
461 pParamVal->val.val64 += val64;
462 }
463 else
464 AssertFailed();
465 }
466
467 if (pParam->fUse & DISUSE_DISPLACEMENT8)
468 {
469 if (pDis->uCpuMode == DISCPUMODE_32BIT)
470 pParamVal->val.i32 += (int32_t)pParam->uDisp.i8;
471 else if (pDis->uCpuMode == DISCPUMODE_64BIT)
472 pParamVal->val.i64 += (int64_t)pParam->uDisp.i8;
473 else
474 pParamVal->val.i16 += (int16_t)pParam->uDisp.i8;
475 }
476 else if (pParam->fUse & DISUSE_DISPLACEMENT16)
477 {
478 if (pDis->uCpuMode == DISCPUMODE_32BIT)
479 pParamVal->val.i32 += (int32_t)pParam->uDisp.i16;
480 else if (pDis->uCpuMode == DISCPUMODE_64BIT)
481 pParamVal->val.i64 += (int64_t)pParam->uDisp.i16;
482 else
483 pParamVal->val.i16 += pParam->uDisp.i16;
484 }
485 else if (pParam->fUse & DISUSE_DISPLACEMENT32)
486 {
487 if (pDis->uCpuMode == DISCPUMODE_32BIT)
488 pParamVal->val.i32 += pParam->uDisp.i32;
489 else
490 pParamVal->val.i64 += pParam->uDisp.i32;
491 }
492 else if (pParam->fUse & DISUSE_DISPLACEMENT64)
493 {
494 Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
495 pParamVal->val.i64 += pParam->uDisp.i64;
496 }
497 else if (pParam->fUse & DISUSE_RIPDISPLACEMENT32)
498 {
499 Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
500 /* Relative to the RIP of the next instruction. */
501 pParamVal->val.i64 += pParam->uDisp.i32 + pCtx->rip + pDis->cbInstr;
502 }
503 return VINF_SUCCESS;
504 }
505
506 if (pParam->fUse & (DISUSE_REG_GEN8|DISUSE_REG_GEN16|DISUSE_REG_GEN32|DISUSE_REG_GEN64|DISUSE_REG_FP|DISUSE_REG_MMX|DISUSE_REG_XMM|DISUSE_REG_CR|DISUSE_REG_DBG|DISUSE_REG_SEG|DISUSE_REG_TEST))
507 {
508 if (parmtype == DISQPVWHICH_DST)
509 {
510 // Caller needs to interpret the register according to the instruction (source/target, special value etc)
511 pParamVal->type = DISQPV_TYPE_REGISTER;
512 pParamVal->size = pParam->cb;
513 return VINF_SUCCESS;
514 }
515 //else DISQPVWHICH_SRC
516
517 pParamVal->type = DISQPV_TYPE_IMMEDIATE;
518
519 if (pParam->fUse & DISUSE_REG_GEN8)
520 {
521 pParamVal->flags |= DISQPV_FLAG_8;
522 pParamVal->size = sizeof(uint8_t);
523 if (RT_FAILURE(DISFetchReg8(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val8))) return VERR_INVALID_PARAMETER;
524 }
525 else
526 if (pParam->fUse & DISUSE_REG_GEN16)
527 {
528 pParamVal->flags |= DISQPV_FLAG_16;
529 pParamVal->size = sizeof(uint16_t);
530 if (RT_FAILURE(DISFetchReg16(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val16))) return VERR_INVALID_PARAMETER;
531 }
532 else
533 if (pParam->fUse & DISUSE_REG_GEN32)
534 {
535 pParamVal->flags |= DISQPV_FLAG_32;
536 pParamVal->size = sizeof(uint32_t);
537 if (RT_FAILURE(DISFetchReg32(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val32))) return VERR_INVALID_PARAMETER;
538 }
539 else
540 if (pParam->fUse & DISUSE_REG_GEN64)
541 {
542 pParamVal->flags |= DISQPV_FLAG_64;
543 pParamVal->size = sizeof(uint64_t);
544 if (RT_FAILURE(DISFetchReg64(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val64))) return VERR_INVALID_PARAMETER;
545 }
546 else
547 {
548 // Caller needs to interpret the register according to the instruction (source/target, special value etc)
549 pParamVal->type = DISQPV_TYPE_REGISTER;
550 }
551 Assert(!(pParam->fUse & DISUSE_IMMEDIATE));
552 return VINF_SUCCESS;
553 }
554
555 if (pParam->fUse & DISUSE_IMMEDIATE)
556 {
557 pParamVal->type = DISQPV_TYPE_IMMEDIATE;
558 if (pParam->fUse & (DISUSE_IMMEDIATE8|DISUSE_IMMEDIATE8_REL))
559 {
560 pParamVal->flags |= DISQPV_FLAG_8;
561 if (pParam->cb == 2)
562 {
563 pParamVal->size = sizeof(uint16_t);
564 pParamVal->val.val16 = (uint8_t)pParam->uValue;
565 }
566 else
567 {
568 pParamVal->size = sizeof(uint8_t);
569 pParamVal->val.val8 = (uint8_t)pParam->uValue;
570 }
571 }
572 else
573 if (pParam->fUse & (DISUSE_IMMEDIATE16|DISUSE_IMMEDIATE16_REL|DISUSE_IMMEDIATE_ADDR_0_16|DISUSE_IMMEDIATE16_SX8))
574 {
575 pParamVal->flags |= DISQPV_FLAG_16;
576 pParamVal->size = sizeof(uint16_t);
577 pParamVal->val.val16 = (uint16_t)pParam->uValue;
578 AssertMsg(pParamVal->size == pParam->cb || ((pParam->cb == 1) && (pParam->fUse & DISUSE_IMMEDIATE16_SX8)), ("pParamVal->size %d vs %d EIP=%RX32\n", pParamVal->size, pParam->cb, pCtx->eip) );
579 }
580 else
581 if (pParam->fUse & (DISUSE_IMMEDIATE32|DISUSE_IMMEDIATE32_REL|DISUSE_IMMEDIATE_ADDR_0_32|DISUSE_IMMEDIATE32_SX8))
582 {
583 pParamVal->flags |= DISQPV_FLAG_32;
584 pParamVal->size = sizeof(uint32_t);
585 pParamVal->val.val32 = (uint32_t)pParam->uValue;
586 Assert(pParamVal->size == pParam->cb || ((pParam->cb == 1) && (pParam->fUse & DISUSE_IMMEDIATE32_SX8)) );
587 }
588 else
589 if (pParam->fUse & (DISUSE_IMMEDIATE64 | DISUSE_IMMEDIATE64_REL | DISUSE_IMMEDIATE64_SX8))
590 {
591 pParamVal->flags |= DISQPV_FLAG_64;
592 pParamVal->size = sizeof(uint64_t);
593 pParamVal->val.val64 = pParam->uValue;
594 Assert(pParamVal->size == pParam->cb || ((pParam->cb == 1) && (pParam->fUse & DISUSE_IMMEDIATE64_SX8)) );
595 }
596 else
597 if (pParam->fUse & (DISUSE_IMMEDIATE_ADDR_16_16))
598 {
599 pParamVal->flags |= DISQPV_FLAG_FARPTR16;
600 pParamVal->size = sizeof(uint16_t)*2;
601 pParamVal->val.farptr.sel = (uint16_t)RT_LOWORD(pParam->uValue >> 16);
602 pParamVal->val.farptr.offset = (uint32_t)RT_LOWORD(pParam->uValue);
603 Assert(pParamVal->size == pParam->cb);
604 }
605 else
606 if (pParam->fUse & (DISUSE_IMMEDIATE_ADDR_16_32))
607 {
608 pParamVal->flags |= DISQPV_FLAG_FARPTR32;
609 pParamVal->size = sizeof(uint16_t) + sizeof(uint32_t);
610 pParamVal->val.farptr.sel = (uint16_t)RT_LOWORD(pParam->uValue >> 32);
611 pParamVal->val.farptr.offset = (uint32_t)(pParam->uValue & 0xFFFFFFFF);
612 Assert(pParam->cb == 8);
613 }
614 }
615 return VINF_SUCCESS;
616}
617
618/**
619 * Returns the pointer to a register of the parameter in pParam. We need this
620 * pointer when an interpreted instruction updates a register as a side effect.
621 * In CMPXCHG we know that only [r/e]ax is updated, but with XADD this could
622 * be every register.
623 *
624 * @returns VBox error code
625 * @param pCtx CPU context structure pointer
626 * @param pDis Pointer to the disassembler state.
627 * @param pParam Pointer to the parameter to parse
628 * @param pReg Pointer to parameter value (OUT)
629 * @param cbsize Parameter size (OUT)
630 *
631 * @note Currently doesn't handle FPU/XMM/MMX/3DNow! parameters correctly!!
632 *
633 */
634DISDECL(int) DISQueryParamRegPtr(PCPUMCTXCORE pCtx, PCDISSTATE pDis, PCDISOPPARAM pParam, void **ppReg, size_t *pcbSize)
635{
636 NOREF(pDis);
637 if (pParam->fUse & (DISUSE_REG_GEN8|DISUSE_REG_GEN16|DISUSE_REG_GEN32|DISUSE_REG_FP|DISUSE_REG_MMX|DISUSE_REG_XMM|DISUSE_REG_CR|DISUSE_REG_DBG|DISUSE_REG_SEG|DISUSE_REG_TEST))
638 {
639 if (pParam->fUse & DISUSE_REG_GEN8)
640 {
641 uint8_t *pu8Reg;
642 if (RT_SUCCESS(DISPtrReg8(pCtx, pParam->Base.idxGenReg, &pu8Reg)))
643 {
644 *pcbSize = sizeof(uint8_t);
645 *ppReg = (void *)pu8Reg;
646 return VINF_SUCCESS;
647 }
648 }
649 else
650 if (pParam->fUse & DISUSE_REG_GEN16)
651 {
652 uint16_t *pu16Reg;
653 if (RT_SUCCESS(DISPtrReg16(pCtx, pParam->Base.idxGenReg, &pu16Reg)))
654 {
655 *pcbSize = sizeof(uint16_t);
656 *ppReg = (void *)pu16Reg;
657 return VINF_SUCCESS;
658 }
659 }
660 else
661 if (pParam->fUse & DISUSE_REG_GEN32)
662 {
663 uint32_t *pu32Reg;
664 if (RT_SUCCESS(DISPtrReg32(pCtx, pParam->Base.idxGenReg, &pu32Reg)))
665 {
666 *pcbSize = sizeof(uint32_t);
667 *ppReg = (void *)pu32Reg;
668 return VINF_SUCCESS;
669 }
670 }
671 else
672 if (pParam->fUse & DISUSE_REG_GEN64)
673 {
674 uint64_t *pu64Reg;
675 if (RT_SUCCESS(DISPtrReg64(pCtx, pParam->Base.idxGenReg, &pu64Reg)))
676 {
677 *pcbSize = sizeof(uint64_t);
678 *ppReg = (void *)pu64Reg;
679 return VINF_SUCCESS;
680 }
681 }
682 }
683 return VERR_INVALID_PARAMETER;
684}
685
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use