VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/DBGFReg.cpp@ 35346

Last change on this file since 35346 was 35346, checked in by vboxsync, 14 years ago

VMM reorg: Moving the public include files from include/VBox to include/VBox/vmm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 50.8 KB
Line 
1/* $Id: DBGFReg.cpp 35346 2010-12-27 16:13:13Z vboxsync $ */
2/** @file
3 * DBGF - Debugger Facility, Register Methods.
4 */
5
6/*
7 * Copyright (C) 2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_DBGF
23#include <VBox/vmm/dbgf.h>
24#include "DBGFInternal.h"
25#include <VBox/vmm/vm.h>
26#include <VBox/param.h>
27#include <VBox/err.h>
28#include <VBox/log.h>
29
30
31/*******************************************************************************
32* Defined Constants And Macros *
33*******************************************************************************/
34/** @name Register and value sizes used by dbgfR3RegQueryWorker and
35 * dbgfR3RegSetWorker.
36 * @{ */
37#define R_SZ_8 RT_BIT(0)
38#define R_SZ_16 RT_BIT(1)
39#define R_SZ_32 RT_BIT(2)
40#define R_SZ_64 RT_BIT(3)
41#define R_SZ_64_16 RT_BIT(4)
42#define R_SZ_80 RT_BIT(5)
43#define R_SZ_128 RT_BIT(6)
44#define R_SZ_8_TO_64 (R_SZ_8 | R_SZ_16 | R_SZ_32 | R_SZ_64)
45#define R_SZ_16_TO_64 (R_SZ_16 | R_SZ_32 | R_SZ_64)
46#define R_SZ_32_OR_64 (R_SZ_32 | R_SZ_64)
47/** @} */
48
49
50/*******************************************************************************
51* Structures and Typedefs *
52*******************************************************************************/
53/**
54 * Register sub-field descriptor.
55 */
56typedef struct DBGFREGSUBFIELD
57{
58 /** The name of the sub-field. NULL is used to terminate the array. */
59 const char *pszName;
60 /** The index of the first bit. */
61 uint8_t iFirstBit;
62 /** The number of bits. */
63 uint8_t cBits;
64 /** The shift count. */
65 int8_t cShift;
66 /** @todo getter/setter callbacks? */
67} DBGFREGSUBFIELD;
68/** Pointer to a const register sub-field descriptor. */
69typedef DBGFREGSUBFIELD const *PCDBGFREGSUBFIELD;
70
71/**
72 * Register alias descriptor.
73 */
74typedef struct DBGFREGALIAS
75{
76 /** The alias name. NULL is used to terminate the array. */
77 const char *pszName;
78 /** Set to a valid type if the alias has a different type. */
79 DBGFREGVALTYPE enmType;
80} DBGFREGALIAS;
81/** Pointer to a const register alias descriptor. */
82typedef DBGFREGALIAS const *PCDBGFREGALIAS;
83
84/**
85 * Register descriptor.
86 */
87typedef struct DBGFREGDESC
88{
89 /** The normal register name. */
90 const char *pszName;
91 /** The register identifier (same as the table index). */
92 DBGFREG enmReg;
93 /** The default register type. */
94 DBGFREGVALTYPE enmType;
95 /** The offset info the CPUMCTX structure. ~(size_t)0 if not applicable. */
96 size_t offCtx;
97 /** Getter (optional). */
98 DECLCALLBACKMEMBER(int, pfnGet)(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
99 /** Setter (optional). */
100 DECLCALLBACKMEMBER(int, pfnSet)(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
101 /** Aliases (optional). */
102 PCDBGFREGALIAS paAliases;
103 /** Sub fields (optional). */
104 PCDBGFREGSUBFIELD paSubFields;
105} DBGFREGDESC;
106/** Pointer to a const register descriptor. */
107typedef DBGFREGDESC const *PCDBGFREGDESC;
108
109
110/*******************************************************************************
111* Internal Functions *
112*******************************************************************************/
113static DECLCALLBACK(int) dbgfR3RegSet_seg(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
114static DECLCALLBACK(int) dbgfR3RegGet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
115static DECLCALLBACK(int) dbgfR3RegSet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
116static DECLCALLBACK(int) dbgfR3RegGet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
117static DECLCALLBACK(int) dbgfR3RegSet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
118static DECLCALLBACK(int) dbgfR3RegGet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
119static DECLCALLBACK(int) dbgfR3RegSet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
120static DECLCALLBACK(int) dbgfR3RegGet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
121static DECLCALLBACK(int) dbgfR3RegSet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
122static DECLCALLBACK(int) dbgfR3RegGet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
123static DECLCALLBACK(int) dbgfR3RegSet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
124static DECLCALLBACK(int) dbgfR3RegGet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
125static DECLCALLBACK(int) dbgfR3RegSet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
126static DECLCALLBACK(int) dbgfR3RegGet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue);
127static DECLCALLBACK(int) dbgfR3RegSet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask);
128
129
130/*******************************************************************************
131* Global Variables *
132*******************************************************************************/
133/*
134 * Set up aliases.
135 */
136#define DBGFREGALIAS_STD(Name, psz32, psz16, psz8) \
137 static DBGFREGALIAS const g_aDbgfRegAliases_##Name[] = \
138 { \
139 { psz32, DBGFREGVALTYPE_U32 }, \
140 { psz16, DBGFREGVALTYPE_U16 }, \
141 { psz8, DBGFREGVALTYPE_U8 }, \
142 { NULL, DBGFREGVALTYPE_INVALID } \
143 }
144DBGFREGALIAS_STD(rax, "eax", "ax", "al");
145DBGFREGALIAS_STD(rcx, "ecx", "cx", "cl");
146DBGFREGALIAS_STD(rdx, "edx", "dx", "dl");
147DBGFREGALIAS_STD(rbx, "ebx", "bx", "bl");
148DBGFREGALIAS_STD(rsp, "esp", "sp", NULL);
149DBGFREGALIAS_STD(rbp, "ebp", "bp", NULL);
150DBGFREGALIAS_STD(rsi, "esi", "si", "sil");
151DBGFREGALIAS_STD(rdi, "edi", "di", "dil");
152DBGFREGALIAS_STD(r8, "r8d", "r8w", "r8b");
153DBGFREGALIAS_STD(r9, "r9d", "r9w", "r9b");
154DBGFREGALIAS_STD(r10, "r10d", "r10w", "r10b");
155DBGFREGALIAS_STD(r11, "r11d", "r11w", "r11b");
156DBGFREGALIAS_STD(r12, "r12d", "r12w", "r12b");
157DBGFREGALIAS_STD(r13, "r13d", "r13w", "r13b");
158DBGFREGALIAS_STD(r14, "r14d", "r14w", "r14b");
159DBGFREGALIAS_STD(r15, "r15d", "r15w", "r15b");
160DBGFREGALIAS_STD(rip, "eip", "ip", NULL);
161DBGFREGALIAS_STD(rflags, "eflags", "flags", NULL);
162#undef DBGFREGALIAS_STD
163
164static DBGFREGALIAS const g_aDbgfRegAliases_fpuip[] =
165{
166 { "fpuip", DBGFREGVALTYPE_U16 },
167 { NULL, DBGFREGVALTYPE_INVALID }
168};
169
170static DBGFREGALIAS const g_aDbgfRegAliases_fpudp[] =
171{
172 { "fpudp", DBGFREGVALTYPE_U16 },
173 { NULL, DBGFREGVALTYPE_INVALID }
174};
175
176static DBGFREGALIAS const g_aDbgfRegAliases_cr0[] =
177{
178 { "msw", DBGFREGVALTYPE_U16 },
179 { NULL, DBGFREGVALTYPE_INVALID }
180};
181
182/*
183 * Sub fields.
184 */
185/** Sub-fields for the (hidden) segment attribute register. */
186static DBGFREGSUBFIELD const g_aDbgfRegFields_seg[] =
187{
188 { "type", 0, 4, 0 },
189 { "s", 4, 1, 0 },
190 { "dpl", 5, 2, 0 },
191 { "p", 7, 1, 0 },
192 { "avl", 12, 1, 0 },
193 { "l", 13, 1, 0 },
194 { "d", 14, 1, 0 },
195 { "g", 15, 1, 0 },
196 { NULL, 0, 0, 0 }
197};
198
199/** Sub-fields for the flags register. */
200static DBGFREGSUBFIELD const g_aDbgfRegFields_rflags[] =
201{
202 { "cf", 0, 1, 0 },
203 { "pf", 2, 1, 0 },
204 { "af", 4, 1, 0 },
205 { "zf", 6, 1, 0 },
206 { "sf", 7, 1, 0 },
207 { "tf", 8, 1, 0 },
208 { "if", 9, 1, 0 },
209 { "df", 10, 1, 0 },
210 { "of", 11, 1, 0 },
211 { "iopl", 12, 2, 0 },
212 { "nt", 14, 1, 0 },
213 { "rf", 16, 1, 0 },
214 { "vm", 17, 1, 0 },
215 { "ac", 18, 1, 0 },
216 { "vif", 19, 1, 0 },
217 { "vip", 20, 1, 0 },
218 { "id", 21, 1, 0 },
219 { NULL, 0, 0, 0 }
220};
221
222/** Sub-fields for the FPU control word register. */
223static DBGFREGSUBFIELD const g_aDbgfRegFields_fcw[] =
224{
225 { "im", 1, 1, 0 },
226 { "dm", 2, 1, 0 },
227 { "zm", 3, 1, 0 },
228 { "om", 4, 1, 0 },
229 { "um", 5, 1, 0 },
230 { "pm", 6, 1, 0 },
231 { "pc", 8, 2, 0 },
232 { "rc", 10, 2, 0 },
233 { "x", 12, 1, 0 },
234 { NULL, 0, 0, 0 }
235};
236
237/** Sub-fields for the FPU status word register. */
238static DBGFREGSUBFIELD const g_aDbgfRegFields_fsw[] =
239{
240 { "ie", 0, 1, 0 },
241 { "de", 1, 1, 0 },
242 { "ze", 2, 1, 0 },
243 { "oe", 3, 1, 0 },
244 { "ue", 4, 1, 0 },
245 { "pe", 5, 1, 0 },
246 { "se", 6, 1, 0 },
247 { "es", 7, 1, 0 },
248 { "c0", 8, 1, 0 },
249 { "c1", 9, 1, 0 },
250 { "c2", 10, 1, 0 },
251 { "top", 11, 3, 0 },
252 { "c3", 14, 1, 0 },
253 { "b", 15, 1, 0 },
254 { NULL, 0, 0, 0 }
255};
256
257/** Sub-fields for the FPU tag word register. */
258static DBGFREGSUBFIELD const g_aDbgfRegFields_ftw[] =
259{
260 { "tag0", 0, 2, 0 },
261 { "tag1", 2, 2, 0 },
262 { "tag2", 4, 2, 0 },
263 { "tag3", 6, 2, 0 },
264 { "tag4", 8, 2, 0 },
265 { "tag5", 10, 2, 0 },
266 { "tag6", 12, 2, 0 },
267 { "tag7", 14, 2, 0 },
268 { NULL, 0, 0, 0 }
269};
270
271/** Sub-fields for the Multimedia Extensions Control and Status Register. */
272static DBGFREGSUBFIELD const g_aDbgfRegFields_mxcsr[] =
273{
274 { "ie", 0, 1, 0 },
275 { "de", 1, 1, 0 },
276 { "ze", 2, 1, 0 },
277 { "oe", 3, 1, 0 },
278 { "ue", 4, 1, 0 },
279 { "pe", 5, 1, 0 },
280 { "daz", 6, 1, 0 },
281 { "im", 7, 1, 0 },
282 { "dm", 8, 1, 0 },
283 { "zm", 9, 1, 0 },
284 { "om", 10, 1, 0 },
285 { "um", 11, 1, 0 },
286 { "pm", 12, 1, 0 },
287 { "rc", 13, 2, 0 },
288 { "fz", 14, 1, 0 },
289 { NULL, 0, 0, 0 }
290};
291
292/** Sub-fields for the FPU tag word register. */
293static DBGFREGSUBFIELD const g_aDbgfRegFields_stN[] =
294{
295 { "man", 0, 64, 0 },
296 { "exp", 64, 15, 0 },
297 { "sig", 79, 1, 0 },
298 { NULL, 0, 0, 0 }
299};
300
301/** Sub-fields for the MMX registers. */
302static DBGFREGSUBFIELD const g_aDbgfRegFields_mmN[] =
303{
304 { "dw0", 0, 32, 0 },
305 { "dw1", 32, 32, 0 },
306 { "w0", 0, 16, 0 },
307 { "w1", 16, 16, 0 },
308 { "w2", 32, 16, 0 },
309 { "w3", 48, 16, 0 },
310 { "b0", 0, 8, 0 },
311 { "b1", 8, 8, 0 },
312 { "b2", 16, 8, 0 },
313 { "b3", 24, 8, 0 },
314 { "b4", 32, 8, 0 },
315 { "b5", 40, 8, 0 },
316 { "b6", 48, 8, 0 },
317 { "b7", 56, 8, 0 },
318 { NULL, 0, 0, 0 }
319};
320
321/** Sub-fields for the XMM registers. */
322static DBGFREGSUBFIELD const g_aDbgfRegFields_xmmN[] =
323{
324 { "r0", 0, 32, 0 },
325 { "r0.man", 0+ 0, 23, 0 },
326 { "r0.exp", 0+23, 8, 0 },
327 { "r0.sig", 0+31, 1, 0 },
328 { "r1", 32, 32, 0 },
329 { "r1.man", 32+ 0, 23, 0 },
330 { "r1.exp", 32+23, 8, 0 },
331 { "r1.sig", 32+31, 1, 0 },
332 { "r2", 64, 32, 0 },
333 { "r2.man", 64+ 0, 23, 0 },
334 { "r2.exp", 64+23, 8, 0 },
335 { "r2.sig", 64+31, 1, 0 },
336 { "r3", 96, 32, 0 },
337 { "r3.man", 96+ 0, 23, 0 },
338 { "r3.exp", 96+23, 8, 0 },
339 { "r3.sig", 96+31, 1, 0 },
340 { NULL, 0, 0, 0 }
341};
342
343/** Sub-fields for the CR0 register. */
344static DBGFREGSUBFIELD const g_aDbgfRegFields_cr0[] =
345{
346 /** @todo */
347 { NULL, 0, 0, 0 }
348};
349
350/** Sub-fields for the CR3 register. */
351static DBGFREGSUBFIELD const g_aDbgfRegFields_cr3[] =
352{
353 /** @todo */
354 { NULL, 0, 0, 0 }
355};
356
357/** Sub-fields for the CR4 register. */
358static DBGFREGSUBFIELD const g_aDbgfRegFields_cr4[] =
359{
360 /** @todo */
361 { NULL, 0, 0, 0 }
362};
363
364/** Sub-fields for the DR6 register. */
365static DBGFREGSUBFIELD const g_aDbgfRegFields_dr6[] =
366{
367 /** @todo */
368 { NULL, 0, 0, 0 }
369};
370
371/** Sub-fields for the DR7 register. */
372static DBGFREGSUBFIELD const g_aDbgfRegFields_dr7[] =
373{
374 /** @todo */
375 { NULL, 0, 0, 0 }
376};
377
378/** Sub-fields for the CR_PAT MSR. */
379static DBGFREGSUBFIELD const g_aDbgfRegFields_apic_base[] =
380{
381 { "bsp", 8, 1, 0 },
382 { "ge", 9, 1, 0 },
383 { "base", 12, 20, 12 },
384 { NULL, 0, 0, 0 }
385};
386
387/** Sub-fields for the CR_PAT MSR. */
388static DBGFREGSUBFIELD const g_aDbgfRegFields_cr_pat[] =
389{
390 /** @todo */
391 { NULL, 0, 0, 0 }
392};
393
394/** Sub-fields for the PERF_STATUS MSR. */
395static DBGFREGSUBFIELD const g_aDbgfRegFields_perf_status[] =
396{
397 /** @todo */
398 { NULL, 0, 0, 0 }
399};
400
401/** Sub-fields for the EFER MSR. */
402static DBGFREGSUBFIELD const g_aDbgfRegFields_efer[] =
403{
404 /** @todo */
405 { NULL, 0, 0, 0 }
406};
407
408/** Sub-fields for the STAR MSR. */
409static DBGFREGSUBFIELD const g_aDbgfRegFields_star[] =
410{
411 /** @todo */
412 { NULL, 0, 0, 0 }
413};
414
415/** Sub-fields for the CSTAR MSR. */
416static DBGFREGSUBFIELD const g_aDbgfRegFields_cstar[] =
417{
418 /** @todo */
419 { NULL, 0, 0, 0 }
420};
421
422/** Sub-fields for the LSTAR MSR. */
423static DBGFREGSUBFIELD const g_aDbgfRegFields_lstar[] =
424{
425 /** @todo */
426 { NULL, 0, 0, 0 }
427};
428
429/** Sub-fields for the SF_MASK MSR. */
430static DBGFREGSUBFIELD const g_aDbgfRegFields_sf_mask[] =
431{
432 /** @todo */
433 { NULL, 0, 0, 0 }
434};
435
436
437
438/**
439 * The register descriptors.
440 */
441static DBGFREGDESC const g_aDbgfRegDescs[] =
442{
443#define DBGFREGDESC_REG(UName, LName) \
444 { #LName, DBGFREG_##UName, DBGFREGVALTYPE_U64, RT_OFFSETOF(CPUMCTX, LName), NULL, NULL, g_aDbgfRegAliases_##LName, NULL }
445 DBGFREGDESC_REG(RAX, rax),
446 DBGFREGDESC_REG(RCX, rcx),
447 DBGFREGDESC_REG(RDX, rdx),
448 DBGFREGDESC_REG(RSP, rsp),
449 DBGFREGDESC_REG(RBP, rbp),
450 DBGFREGDESC_REG(RSI, rsi),
451 DBGFREGDESC_REG(RDI, rdi),
452 DBGFREGDESC_REG(R8, r8),
453 DBGFREGDESC_REG(R9, r9),
454 DBGFREGDESC_REG(R10, r10),
455 DBGFREGDESC_REG(R11, r11),
456 DBGFREGDESC_REG(R12, r12),
457 DBGFREGDESC_REG(R13, r13),
458 DBGFREGDESC_REG(R14, r14),
459 DBGFREGDESC_REG(R15, r15),
460#define DBGFREGDESC_SEG(UName, LName) \
461 { #LName, DBGFREG_##UName, DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, LName), NULL, dbgfR3RegSet_seg, NULL, NULL }, \
462 { #LName "_attr", DBGFREG_##UName##_ATTR, DBGFREGVALTYPE_U32, RT_OFFSETOF(CPUMCTX, LName##Hid.Attr.u), NULL, NULL, NULL, g_aDbgfRegFields_seg }, \
463 { #LName "_base", DBGFREG_##UName##_ATTR, DBGFREGVALTYPE_U64, RT_OFFSETOF(CPUMCTX, LName##Hid.u64Base), NULL, NULL, NULL, NULL }, \
464 { #LName "_lim", DBGFREG_##UName##_ATTR, DBGFREGVALTYPE_U32, RT_OFFSETOF(CPUMCTX, LName##Hid.u32Limit), NULL, NULL, NULL, NULL }
465 DBGFREGDESC_SEG(CS, cs),
466 DBGFREGDESC_SEG(DS, ds),
467 DBGFREGDESC_SEG(ES, es),
468 DBGFREGDESC_SEG(FS, fs),
469 DBGFREGDESC_SEG(GS, gs),
470 DBGFREGDESC_SEG(SS, ss),
471 DBGFREGDESC_REG(RIP, rip),
472 { "rflags", DBGFREG_RFLAGS, DBGFREGVALTYPE_U64, RT_OFFSETOF(CPUMCTX, rflags), NULL, NULL, g_aDbgfRegAliases_rflags, g_aDbgfRegFields_rflags },
473 { "fcw", DBGFREG_FCW, DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, fpu.FCW), NULL, NULL, NULL, g_aDbgfRegFields_fcw },
474 { "fsw", DBGFREG_FSW, DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, fpu.FSW), NULL, NULL, NULL, g_aDbgfRegFields_fsw },
475 { "ftw", DBGFREG_FTW, DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, fpu.FTW), dbgfR3RegGet_ftw, dbgfR3RegSet_ftw, NULL, g_aDbgfRegFields_ftw },
476 { "fop", DBGFREG_FOP, DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, fpu.FOP), NULL, NULL, NULL, NULL },
477 { "fpuip", DBGFREG_FPUIP, DBGFREGVALTYPE_U32, RT_OFFSETOF(CPUMCTX, fpu.FPUIP), NULL, NULL, g_aDbgfRegAliases_fpuip, NULL },
478 { "fpucs", DBGFREG_FPUCS, DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, fpu.CS), NULL, NULL, NULL, NULL },
479 { "fpudp", DBGFREG_FPUDP, DBGFREGVALTYPE_U32, RT_OFFSETOF(CPUMCTX, fpu.FPUDP), NULL, NULL, g_aDbgfRegAliases_fpudp, NULL },
480 { "fpuds", DBGFREG_FPUDS, DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, fpu.DS), NULL, NULL, NULL, NULL },
481 { "mxcsr", DBGFREG_MXCSR, DBGFREGVALTYPE_U32, RT_OFFSETOF(CPUMCTX, fpu.MXCSR), NULL, NULL, NULL, g_aDbgfRegFields_mxcsr },
482 { "mxcsr_mask", DBGFREG_MXCSR_MASK, DBGFREGVALTYPE_U32, RT_OFFSETOF(CPUMCTX, fpu.MXCSR_MASK), NULL, NULL, NULL, g_aDbgfRegFields_mxcsr },
483#define DBGFREGDESC_ST(n) \
484 { "st" #n, DBGFREG_ST##n, DBGFREGVALTYPE_80, ~(size_t)0, dbgfR3RegGet_stN, dbgfR3RegSet_stN, NULL, g_aDbgfRegFields_stN }
485 DBGFREGDESC_ST(0),
486 DBGFREGDESC_ST(1),
487 DBGFREGDESC_ST(2),
488 DBGFREGDESC_ST(3),
489 DBGFREGDESC_ST(4),
490 DBGFREGDESC_ST(5),
491 DBGFREGDESC_ST(6),
492 DBGFREGDESC_ST(7),
493#define DBGFREGDESC_MM(n) \
494 { "mm" #n, DBGFREG_MM##n, DBGFREGVALTYPE_U64, RT_OFFSETOF(CPUMCTX, fpu.aRegs[n].mmx), NULL, NULL, NULL, g_aDbgfRegFields_mmN }
495 DBGFREGDESC_MM(0),
496 DBGFREGDESC_MM(1),
497 DBGFREGDESC_MM(2),
498 DBGFREGDESC_MM(3),
499 DBGFREGDESC_MM(4),
500 DBGFREGDESC_MM(5),
501 DBGFREGDESC_MM(6),
502 DBGFREGDESC_MM(7),
503#define DBGFREGDESC_XMM(n) \
504 { "xmm" #n, DBGFREG_XMM##n, DBGFREGVALTYPE_U128, RT_OFFSETOF(CPUMCTX, fpu.aXMM[n].xmm), NULL, NULL, NULL, g_aDbgfRegFields_xmmN }
505 DBGFREGDESC_XMM(0),
506 DBGFREGDESC_XMM(1),
507 DBGFREGDESC_XMM(2),
508 DBGFREGDESC_XMM(3),
509 DBGFREGDESC_XMM(4),
510 DBGFREGDESC_XMM(5),
511 DBGFREGDESC_XMM(6),
512 DBGFREGDESC_XMM(7),
513 DBGFREGDESC_XMM(8),
514 DBGFREGDESC_XMM(9),
515 DBGFREGDESC_XMM(10),
516 DBGFREGDESC_XMM(11),
517 DBGFREGDESC_XMM(12),
518 DBGFREGDESC_XMM(13),
519 DBGFREGDESC_XMM(14),
520 DBGFREGDESC_XMM(15),
521 { "gdtr_base", DBGFREG_GDTR_BASE, DBGFREGVALTYPE_U64, RT_OFFSETOF(CPUMCTX, gdtr.pGdt), NULL, NULL, NULL, NULL },
522 { "gdtr_limit", DBGFREG_GDTR_LIMIT, DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, gdtr.cbGdt), NULL, NULL, NULL, NULL },
523 { "idtr_base", DBGFREG_IDTR_BASE, DBGFREGVALTYPE_U64, RT_OFFSETOF(CPUMCTX, idtr.pIdt), NULL, NULL, NULL, NULL },
524 { "idtr_limit", DBGFREG_IDTR_LIMIT, DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, idtr.cbIdt), NULL, NULL, NULL, NULL },
525 DBGFREGDESC_SEG(LDTR, ldtr),
526 DBGFREGDESC_SEG(TR, tr),
527 { "cr0", DBGFREG_CR0, DBGFREGVALTYPE_U32, 0, dbgfR3RegGet_crX, dbgfR3RegSet_crX, g_aDbgfRegAliases_cr0, g_aDbgfRegFields_cr0 },
528 { "cr2", DBGFREG_CR2, DBGFREGVALTYPE_U64, 2, dbgfR3RegGet_crX, dbgfR3RegSet_crX, NULL, NULL },
529 { "cr3", DBGFREG_CR3, DBGFREGVALTYPE_U64, 3, dbgfR3RegGet_crX, dbgfR3RegSet_crX, NULL, g_aDbgfRegFields_cr3 },
530 { "cr4", DBGFREG_CR4, DBGFREGVALTYPE_U32, 4, dbgfR3RegGet_crX, dbgfR3RegSet_crX, NULL, g_aDbgfRegFields_cr4 },
531 { "cr8", DBGFREG_CR8, DBGFREGVALTYPE_U32, 8, dbgfR3RegGet_crX, dbgfR3RegSet_crX, NULL, NULL },
532 { "dr0", DBGFREG_DR0, DBGFREGVALTYPE_U64, 0, dbgfR3RegGet_drX, dbgfR3RegSet_drX, NULL, NULL },
533 { "dr1", DBGFREG_DR1, DBGFREGVALTYPE_U64, 1, dbgfR3RegGet_drX, dbgfR3RegSet_drX, NULL, NULL },
534 { "dr2", DBGFREG_DR2, DBGFREGVALTYPE_U64, 2, dbgfR3RegGet_drX, dbgfR3RegSet_drX, NULL, NULL },
535 { "dr3", DBGFREG_DR3, DBGFREGVALTYPE_U64, 3, dbgfR3RegGet_drX, dbgfR3RegSet_drX, NULL, NULL },
536 { "dr6", DBGFREG_DR6, DBGFREGVALTYPE_U32, 6, dbgfR3RegGet_drX, dbgfR3RegSet_drX, NULL, g_aDbgfRegFields_dr6 },
537 { "dr7", DBGFREG_DR7, DBGFREGVALTYPE_U32, 7, dbgfR3RegGet_drX, dbgfR3RegSet_drX, NULL, g_aDbgfRegFields_dr7 },
538 { "apic_base", DBGFREG_MSR_IA32_APICBASE, DBGFREGVALTYPE_U32, MSR_IA32_APICBASE, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, g_aDbgfRegFields_apic_base },
539 { "pat", DBGFREG_MSR_IA32_CR_PAT, DBGFREGVALTYPE_U64, MSR_IA32_CR_PAT, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, g_aDbgfRegFields_cr_pat },
540 { "perf_status", DBGFREG_MSR_IA32_PERF_STATUS, DBGFREGVALTYPE_U64, MSR_IA32_PERF_STATUS, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, g_aDbgfRegFields_perf_status },
541 { "sysenter_cs", DBGFREG_MSR_IA32_SYSENTER_CS, DBGFREGVALTYPE_U16, MSR_IA32_SYSENTER_CS, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL },
542 { "sysenter_eip", DBGFREG_MSR_IA32_SYSENTER_EIP, DBGFREGVALTYPE_U32, MSR_IA32_SYSENTER_EIP, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL },
543 { "sysenter_esp", DBGFREG_MSR_IA32_SYSENTER_ESP, DBGFREGVALTYPE_U32, MSR_IA32_SYSENTER_ESP, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL },
544 { "tsc", DBGFREG_MSR_IA32_TSC, DBGFREGVALTYPE_U32, MSR_IA32_TSC, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL },
545 { "efer", DBGFREG_MSR_K6_EFER, DBGFREGVALTYPE_U32, MSR_K6_EFER, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, g_aDbgfRegFields_efer },
546 { "star", DBGFREG_MSR_K6_STAR, DBGFREGVALTYPE_U64, MSR_K6_STAR, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, g_aDbgfRegFields_star },
547 { "cstar", DBGFREG_MSR_K8_CSTAR, DBGFREGVALTYPE_U64, MSR_K8_CSTAR, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, g_aDbgfRegFields_cstar },
548 { "msr_fs_base", DBGFREG_MSR_K8_FS_BASE, DBGFREGVALTYPE_U64, MSR_K8_FS_BASE, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL },
549 { "msr_gs_base", DBGFREG_MSR_K8_GS_BASE, DBGFREGVALTYPE_U64, MSR_K8_GS_BASE, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL },
550 { "krnl_gs_base", DBGFREG_MSR_K8_KERNEL_GS_BASE, DBGFREGVALTYPE_U64, MSR_K8_KERNEL_GS_BASE, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL },
551 { "lstar", DBGFREG_MSR_K8_LSTAR, DBGFREGVALTYPE_U64, MSR_K8_LSTAR, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, g_aDbgfRegFields_lstar },
552 { "tsc_aux", DBGFREG_MSR_K8_TSC_AUX, DBGFREGVALTYPE_U64, MSR_K8_TSC_AUX, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL },
553 { "ah", DBGFREG_AH, DBGFREGVALTYPE_U8, RT_OFFSETOF(CPUMCTX, rax) + 1, NULL, NULL, NULL, NULL },
554 { "ch", DBGFREG_CH, DBGFREGVALTYPE_U8, RT_OFFSETOF(CPUMCTX, rcx) + 1, NULL, NULL, NULL, NULL },
555 { "dh", DBGFREG_DH, DBGFREGVALTYPE_U8, RT_OFFSETOF(CPUMCTX, rdx) + 1, NULL, NULL, NULL, NULL },
556 { "bh", DBGFREG_BH, DBGFREGVALTYPE_U8, RT_OFFSETOF(CPUMCTX, rbx) + 1, NULL, NULL, NULL, NULL },
557 { "gdtr", DBGFREG_GDTR, DBGFREGVALTYPE_DTR, ~(size_t)0, dbgfR3RegGet_gdtr, dbgfR3RegSet_gdtr, NULL, NULL },
558 { "idtr", DBGFREG_IDTR, DBGFREGVALTYPE_DTR, ~(size_t)0, dbgfR3RegGet_idtr, dbgfR3RegSet_idtr, NULL, NULL },
559#undef DBGFREGDESC_REG
560#undef DBGFREGDESC_SEG
561#undef DBGFREGDESC_ST
562#undef DBGFREGDESC_MM
563#undef DBGFREGDESC_XMM
564};
565
566
567static DECLCALLBACK(int) dbgfR3RegSet_seg(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
568{
569 return VERR_NOT_IMPLEMENTED;
570}
571
572static DECLCALLBACK(int) dbgfR3RegGet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
573{
574 return VERR_NOT_IMPLEMENTED;
575}
576
577static DECLCALLBACK(int) dbgfR3RegSet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
578{
579 return VERR_NOT_IMPLEMENTED;
580}
581
582static DECLCALLBACK(int) dbgfR3RegGet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
583{
584 return VERR_NOT_IMPLEMENTED;
585}
586
587static DECLCALLBACK(int) dbgfR3RegSet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
588{
589 return VERR_NOT_IMPLEMENTED;
590}
591
592static DECLCALLBACK(int) dbgfR3RegGet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
593{
594 return VERR_NOT_IMPLEMENTED;
595}
596
597static DECLCALLBACK(int) dbgfR3RegSet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
598{
599 return VERR_NOT_IMPLEMENTED;
600}
601
602static DECLCALLBACK(int) dbgfR3RegGet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
603{
604 return VERR_NOT_IMPLEMENTED;
605}
606
607static DECLCALLBACK(int) dbgfR3RegSet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
608{
609 return VERR_NOT_IMPLEMENTED;
610}
611
612static DECLCALLBACK(int) dbgfR3RegGet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
613{
614 return VERR_NOT_IMPLEMENTED;
615}
616
617static DECLCALLBACK(int) dbgfR3RegSet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
618{
619 return VERR_NOT_IMPLEMENTED;
620}
621
622static DECLCALLBACK(int) dbgfR3RegGet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
623{
624 return VERR_NOT_IMPLEMENTED;
625}
626
627static DECLCALLBACK(int) dbgfR3RegSet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
628{
629 return VERR_NOT_IMPLEMENTED;
630}
631
632static DECLCALLBACK(int) dbgfR3RegGet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)
633{
634 return VERR_NOT_IMPLEMENTED;
635}
636
637static DECLCALLBACK(int) dbgfR3RegSet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)
638{
639 return VERR_NOT_IMPLEMENTED;
640}
641
642
643
644/**
645 * Wrapper around CPUMQueryGuestMsr for dbgfR3RegQueryWorker.
646 *
647 * @retval VINF_SUCCESS
648 * @retval VERR_DBGF_INVALID_REGISTER
649 *
650 * @param pVCpu The current CPU.
651 * @param pu64 Where to store the register value.
652 * @param pfRegSizes Where to store the register sizes.
653 * @param idMsr The MSR to get.
654 */
655static uint64_t dbgfR3RegGetMsr(PVMCPU pVCpu, uint64_t *pu64, uint32_t *pfRegSizes, uint32_t idMsr)
656{
657 *pfRegSizes = R_SZ_64;
658 int rc = CPUMQueryGuestMsr(pVCpu, idMsr, pu64);
659 if (RT_FAILURE(rc))
660 {
661 AssertMsg(rc == VERR_CPUM_RAISE_GP_0, ("%Rrc\n", rc));
662 *pu64 = 0;
663 }
664 return VINF_SUCCESS;
665}
666
667/**
668 * Worker for DBGFR3RegQueryU8, DBGFR3RegQueryU16, DBGFR3RegQueryU32 and
669 * DBGFR3RegQueryU64.
670 *
671 * @param pVM The VM handle.
672 * @param idCpu The target CPU ID.
673 * @param enmReg The register that's being queried.
674 * @param pu64 Where to store the register value.
675 * @param pfRegSizes Where to store the register sizes.
676 */
677static DECLCALLBACK(int) dbgfR3RegQueryWorker(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t *pu64, uint32_t *pfRegSizes)
678{
679/** @todo rewrite this to use the register descriptors. */
680 PVMCPU pVCpu = &pVM->aCpus[idCpu];
681 PCCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
682 switch (enmReg)
683 {
684 case DBGFREG_RAX: *pu64 = pCtx->rax; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;
685 case DBGFREG_RCX: *pu64 = pCtx->rcx; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;
686 case DBGFREG_RDX: *pu64 = pCtx->rdx; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;
687 case DBGFREG_RBX: *pu64 = pCtx->rbx; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;
688 case DBGFREG_RSP: *pu64 = pCtx->rsp; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;
689 case DBGFREG_RBP: *pu64 = pCtx->rbp; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;
690 case DBGFREG_RSI: *pu64 = pCtx->rsi; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;
691 case DBGFREG_RDI: *pu64 = pCtx->rdi; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;
692 case DBGFREG_R8: *pu64 = pCtx->r8; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;
693 case DBGFREG_R9: *pu64 = pCtx->r9; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;
694 case DBGFREG_R10: *pu64 = pCtx->r10; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;
695 case DBGFREG_R11: *pu64 = pCtx->r11; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;
696 case DBGFREG_R12: *pu64 = pCtx->r12; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;
697 case DBGFREG_R13: *pu64 = pCtx->r13; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;
698 case DBGFREG_R14: *pu64 = pCtx->r14; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;
699 case DBGFREG_R15: *pu64 = pCtx->r15; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;
700
701 case DBGFREG_CS: *pu64 = pCtx->cs; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;
702 case DBGFREG_DS: *pu64 = pCtx->ds; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;
703 case DBGFREG_ES: *pu64 = pCtx->es; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;
704 case DBGFREG_FS: *pu64 = pCtx->fs; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;
705 case DBGFREG_GS: *pu64 = pCtx->gs; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;
706 case DBGFREG_SS: *pu64 = pCtx->ss; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;
707
708 case DBGFREG_CS_ATTR: *pu64 = pCtx->csHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;
709 case DBGFREG_DS_ATTR: *pu64 = pCtx->dsHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;
710 case DBGFREG_ES_ATTR: *pu64 = pCtx->esHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;
711 case DBGFREG_FS_ATTR: *pu64 = pCtx->fsHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;
712 case DBGFREG_GS_ATTR: *pu64 = pCtx->gsHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;
713 case DBGFREG_SS_ATTR: *pu64 = pCtx->ssHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;
714
715 case DBGFREG_CS_BASE: *pu64 = pCtx->csHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS;
716 case DBGFREG_DS_BASE: *pu64 = pCtx->dsHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS;
717 case DBGFREG_ES_BASE: *pu64 = pCtx->esHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS;
718 case DBGFREG_FS_BASE: *pu64 = pCtx->fsHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS;
719 case DBGFREG_GS_BASE: *pu64 = pCtx->gsHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS;
720 case DBGFREG_SS_BASE: *pu64 = pCtx->ssHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS;
721
722 case DBGFREG_CS_LIMIT: *pu64 = pCtx->csHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;
723 case DBGFREG_DS_LIMIT: *pu64 = pCtx->dsHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;
724 case DBGFREG_ES_LIMIT: *pu64 = pCtx->esHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;
725 case DBGFREG_FS_LIMIT: *pu64 = pCtx->fsHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;
726 case DBGFREG_GS_LIMIT: *pu64 = pCtx->gsHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;
727 case DBGFREG_SS_LIMIT: *pu64 = pCtx->ssHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;
728
729 case DBGFREG_RIP: *pu64 = pCtx->rip; *pfRegSizes = R_SZ_16_TO_64; return VINF_SUCCESS;
730 case DBGFREG_FLAGS: *pu64 = pCtx->rflags.u; *pfRegSizes = R_SZ_16_TO_64; return VINF_SUCCESS;
731
732 /** @todo check fxsave/fsave format? */
733 case DBGFREG_FCW: *pu64 = pCtx->fpu.FCW; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;
734 case DBGFREG_FSW: *pu64 = pCtx->fpu.FSW; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;
735 case DBGFREG_FTW: *pu64 = pCtx->fpu.FTW; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;
736 case DBGFREG_FOP: *pu64 = pCtx->fpu.FOP; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;
737 case DBGFREG_FPUIP: *pu64 = pCtx->fpu.FPUIP; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;
738 case DBGFREG_FPUCS: *pu64 = pCtx->fpu.CS; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;
739 case DBGFREG_FPUDP: *pu64 = pCtx->fpu.FPUDP; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;
740 case DBGFREG_FPUDS: *pu64 = pCtx->fpu.DS; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;
741 case DBGFREG_MXCSR: *pu64 = pCtx->fpu.MXCSR; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;
742 case DBGFREG_MXCSR_MASK:*pu64 = pCtx->fpu.MXCSR_MASK; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;
743
744 case DBGFREG_ST0:
745 case DBGFREG_ST1:
746 case DBGFREG_ST2:
747 case DBGFREG_ST3:
748 case DBGFREG_ST4:
749 case DBGFREG_ST5:
750 case DBGFREG_ST6:
751 case DBGFREG_ST7:
752 {
753 /** @todo check tags and fxsave/fsave format. */
754 unsigned iReg = (pCtx->fpu.FSW >> 11) & 7;
755 iReg += enmReg - DBGFREG_ST0;
756 iReg &= 7;
757
758 *pu64 = pCtx->fpu.aRegs[iReg].au64[0];
759 *pfRegSizes = R_SZ_80;
760 return VINF_SUCCESS;
761 }
762
763 case DBGFREG_MM0:
764 case DBGFREG_MM1:
765 case DBGFREG_MM2:
766 case DBGFREG_MM3:
767 case DBGFREG_MM4:
768 case DBGFREG_MM5:
769 case DBGFREG_MM6:
770 case DBGFREG_MM7:
771 *pu64 = pCtx->fpu.aRegs[enmReg - DBGFREG_MM0].mmx;
772 *pfRegSizes = R_SZ_64;
773 return VINF_SUCCESS;
774
775 case DBGFREG_XMM0:
776 case DBGFREG_XMM1:
777 case DBGFREG_XMM2:
778 case DBGFREG_XMM3:
779 case DBGFREG_XMM4:
780 case DBGFREG_XMM5:
781 case DBGFREG_XMM6:
782 case DBGFREG_XMM7:
783 case DBGFREG_XMM8:
784 case DBGFREG_XMM9:
785 case DBGFREG_XMM10:
786 case DBGFREG_XMM11:
787 case DBGFREG_XMM12:
788 case DBGFREG_XMM13:
789 case DBGFREG_XMM14:
790 case DBGFREG_XMM15:
791 *pu64 = pCtx->fpu.aRegs[enmReg - DBGFREG_XMM0].au64[0];
792 *pfRegSizes = R_SZ_128;
793 return VINF_SUCCESS;
794
795 case DBGFREG_GDTR_BASE: *pu64 = pCtx->gdtr.pGdt; *pfRegSizes = R_SZ_64; return VINF_SUCCESS;
796 case DBGFREG_GDTR_LIMIT: *pu64 = pCtx->gdtr.cbGdt; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;
797 case DBGFREG_IDTR_BASE: *pu64 = pCtx->idtr.pIdt; *pfRegSizes = R_SZ_64; return VINF_SUCCESS;
798 case DBGFREG_IDTR_LIMIT: *pu64 = pCtx->idtr.cbIdt; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;
799 case DBGFREG_LDTR: *pu64 = pCtx->ldtr; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;
800 case DBGFREG_LDTR_ATTR: *pu64 = pCtx->ldtrHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;
801 case DBGFREG_LDTR_BASE: *pu64 = pCtx->ldtrHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS;
802 case DBGFREG_LDTR_LIMIT: *pu64 = pCtx->ldtrHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;
803 case DBGFREG_TR: *pu64 = pCtx->tr; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;
804 case DBGFREG_TR_ATTR: *pu64 = pCtx->trHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;
805 case DBGFREG_TR_BASE: *pu64 = pCtx->trHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS;
806 case DBGFREG_TR_LIMIT: *pu64 = pCtx->trHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;
807
808 case DBGFREG_CR0: *pu64 = CPUMGetGuestCR0(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
809 case DBGFREG_CR2: *pu64 = CPUMGetGuestCR2(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
810 case DBGFREG_CR3: *pu64 = CPUMGetGuestCR3(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
811 case DBGFREG_CR4: *pu64 = CPUMGetGuestCR4(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
812 case DBGFREG_CR8: *pu64 = CPUMGetGuestCR8(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
813
814 case DBGFREG_DR0: *pu64 = CPUMGetGuestDR0(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
815 case DBGFREG_DR1: *pu64 = CPUMGetGuestDR1(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
816 case DBGFREG_DR2: *pu64 = CPUMGetGuestDR2(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
817 case DBGFREG_DR3: *pu64 = CPUMGetGuestDR3(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
818 case DBGFREG_DR6: *pu64 = CPUMGetGuestDR6(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
819 case DBGFREG_DR7: *pu64 = CPUMGetGuestDR7(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;
820
821 case DBGFREG_MSR_IA32_APICBASE: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_APICBASE);
822 case DBGFREG_MSR_IA32_CR_PAT: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_CR_PAT);
823 case DBGFREG_MSR_IA32_PERF_STATUS: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_PERF_STATUS);
824 case DBGFREG_MSR_IA32_SYSENTER_CS: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_SYSENTER_CS);
825 case DBGFREG_MSR_IA32_SYSENTER_EIP: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_SYSENTER_EIP);
826 case DBGFREG_MSR_IA32_SYSENTER_ESP: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_SYSENTER_ESP);
827 case DBGFREG_MSR_IA32_TSC: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_TSC);
828 case DBGFREG_MSR_K6_EFER: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K6_EFER);
829 case DBGFREG_MSR_K6_STAR: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K6_STAR);
830 case DBGFREG_MSR_K8_CSTAR: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_CSTAR);
831 case DBGFREG_MSR_K8_FS_BASE: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_FS_BASE);
832 case DBGFREG_MSR_K8_GS_BASE: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_GS_BASE);
833 case DBGFREG_MSR_K8_KERNEL_GS_BASE: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_KERNEL_GS_BASE);
834 case DBGFREG_MSR_K8_LSTAR: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_LSTAR);
835 case DBGFREG_MSR_K8_SF_MASK: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_SF_MASK);
836 case DBGFREG_MSR_K8_TSC_AUX: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_TSC_AUX);
837
838 case DBGFREG_AH: *pu64 = RT_BYTE2(pCtx->ax); *pfRegSizes = R_SZ_8; return VINF_SUCCESS;
839 case DBGFREG_CH: *pu64 = RT_BYTE2(pCtx->cx); *pfRegSizes = R_SZ_8; return VINF_SUCCESS;
840 case DBGFREG_DH: *pu64 = RT_BYTE2(pCtx->dx); *pfRegSizes = R_SZ_8; return VINF_SUCCESS;
841 case DBGFREG_BH: *pu64 = RT_BYTE2(pCtx->bx); *pfRegSizes = R_SZ_8; return VINF_SUCCESS;
842 case DBGFREG_GDTR: *pu64 = pCtx->gdtr.pGdt; *pfRegSizes = R_SZ_64_16; return VINF_SUCCESS;
843 case DBGFREG_IDTR: *pu64 = pCtx->idtr.pIdt; *pfRegSizes = R_SZ_64_16; return VINF_SUCCESS;
844
845 case DBGFREG_END:
846 case DBGFREG_32BIT_HACK:
847 /* no default! We want GCC warnings. */
848 break;
849 }
850
851 AssertMsgFailed(("%d (%#x)\n", enmReg, enmReg));
852 return VERR_DBGF_INVALID_REGISTER;
853}
854
855
856/**
857 * Queries a 8-bit register value.
858 *
859 * @retval VINF_SUCCESS
860 * @retval VERR_INVALID_VM_HANDLE
861 * @retval VERR_INVALID_CPU_ID
862 * @retval VERR_DBGF_INVALID_REGISTER
863 * @retval VINF_DBGF_TRUNCATED_REGISTER
864 *
865 * @param pVM The VM handle.
866 * @param idCpu The target CPU ID.
867 * @param enmReg The register that's being queried.
868 * @param pu8 Where to store the register value.
869 */
870VMMR3DECL(int) DBGFR3RegQueryU8(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint8_t *pu8)
871{
872 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
873 AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
874
875 uint64_t u64Value;
876 uint32_t fRegSizes;
877 int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes);
878 if (RT_SUCCESS(rc))
879 {
880 *pu8 = (uint8_t)u64Value;
881 if (R_SZ_8 & fRegSizes)
882 rc = VINF_SUCCESS;
883 else
884 rc = VINF_DBGF_TRUNCATED_REGISTER;
885 }
886 else
887 *pu8 = 0;
888 return rc;
889}
890
891
892/**
893 * Queries a 16-bit register value.
894 *
895 * @retval VINF_SUCCESS
896 * @retval VERR_INVALID_VM_HANDLE
897 * @retval VERR_INVALID_CPU_ID
898 * @retval VERR_DBGF_INVALID_REGISTER
899 * @retval VINF_DBGF_TRUNCATED_REGISTER
900 * @retval VINF_DBGF_ZERO_EXTENDED_REGISTER
901 *
902 * @param pVM The VM handle.
903 * @param idCpu The target CPU ID.
904 * @param enmReg The register that's being queried.
905 * @param pu16 Where to store the register value.
906 */
907VMMR3DECL(int) DBGFR3RegQueryU16(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint16_t *pu16)
908{
909 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
910 AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
911
912 uint64_t u64Value;
913 uint32_t fRegSizes;
914 int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes);
915 if (RT_SUCCESS(rc))
916 {
917 *pu16 = (uint16_t)u64Value;
918 if (R_SZ_16 & fRegSizes)
919 rc = VINF_SUCCESS;
920 else if (~(R_SZ_8 | R_SZ_16) & fRegSizes)
921 rc = VINF_DBGF_TRUNCATED_REGISTER;
922 else
923 rc = VINF_DBGF_ZERO_EXTENDED_REGISTER;
924 }
925 else
926 *pu16 = 0;
927 return rc;
928}
929
930
931/**
932 * Queries a 32-bit register value.
933 *
934 * @retval VINF_SUCCESS
935 * @retval VERR_INVALID_VM_HANDLE
936 * @retval VERR_INVALID_CPU_ID
937 * @retval VERR_DBGF_INVALID_REGISTER
938 * @retval VINF_DBGF_TRUNCATED_REGISTER
939 * @retval VINF_DBGF_ZERO_EXTENDED_REGISTER
940 *
941 * @param pVM The VM handle.
942 * @param idCpu The target CPU ID.
943 * @param enmReg The register that's being queried.
944 * @param pu32 Where to store the register value.
945 */
946VMMR3DECL(int) DBGFR3RegQueryU32(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint32_t *pu32)
947{
948 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
949 AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
950
951 uint64_t u64Value;
952 uint32_t fRegSizes;
953 int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes);
954 if (RT_SUCCESS(rc))
955 {
956 *pu32 = (uint32_t)u64Value;
957 if (R_SZ_32 & fRegSizes)
958 rc = VINF_SUCCESS;
959 else if (~(R_SZ_8 | R_SZ_16 | R_SZ_32) & fRegSizes)
960 rc = VINF_DBGF_TRUNCATED_REGISTER;
961 else
962 rc = VINF_DBGF_ZERO_EXTENDED_REGISTER;
963 }
964 else
965 *pu32 = 0;
966 return rc;
967}
968
969
970/**
971 * Queries a 64-bit register value.
972 *
973 * @retval VINF_SUCCESS
974 * @retval VERR_INVALID_VM_HANDLE
975 * @retval VERR_INVALID_CPU_ID
976 * @retval VERR_DBGF_INVALID_REGISTER
977 * @retval VINF_DBGF_TRUNCATED_REGISTER
978 * @retval VINF_DBGF_ZERO_EXTENDED_REGISTER
979 *
980 * @param pVM The VM handle.
981 * @param idCpu The target CPU ID.
982 * @param enmReg The register that's being queried.
983 * @param pu64 Where to store the register value.
984 */
985VMMR3DECL(int) DBGFR3RegQueryU64(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t *pu64)
986{
987 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
988 AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
989
990 uint64_t u64Value;
991 uint32_t fRegSizes;
992 int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes);
993 if (RT_SUCCESS(rc))
994 {
995 *pu64 = u64Value;
996 if (R_SZ_64 & fRegSizes)
997 rc = VINF_SUCCESS;
998 else if (~(R_SZ_8 | R_SZ_16 | R_SZ_32 | R_SZ_64) & fRegSizes)
999 rc = VINF_DBGF_TRUNCATED_REGISTER;
1000 else
1001 rc = VINF_DBGF_ZERO_EXTENDED_REGISTER;
1002 }
1003 else
1004 *pu64 = 0;
1005 return rc;
1006}
1007
1008
1009/**
1010 * Wrapper around CPUMQueryGuestMsr for dbgfR3RegQueryBatchWorker.
1011 *
1012 * @retval VINF_SUCCESS
1013 * @retval VERR_DBGF_INVALID_REGISTER
1014 *
1015 * @param pVCpu The current CPU.
1016 * @param pReg The where to store the register value and
1017 * size.
1018 * @param idMsr The MSR to get.
1019 */
1020static void dbgfR3RegGetMsrBatch(PVMCPU pVCpu, PDBGFREGENTRY pReg, uint32_t idMsr)
1021{
1022 pReg->enmType = DBGFREGVALTYPE_U64;
1023 int rc = CPUMQueryGuestMsr(pVCpu, idMsr, &pReg->Val.u64);
1024 if (RT_FAILURE(rc))
1025 {
1026 AssertMsg(rc == VERR_CPUM_RAISE_GP_0, ("%Rrc\n", rc));
1027 pReg->Val.u64 = 0;
1028 }
1029}
1030
1031
1032static DECLCALLBACK(int) dbgfR3RegQueryBatchWorker(PVM pVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs)
1033{
1034 PVMCPU pVCpu = &pVM->aCpus[idCpu];
1035 PCCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
1036
1037 PDBGFREGENTRY pReg = paRegs - 1;
1038 while (cRegs-- > 0)
1039 {
1040 pReg++;
1041 pReg->Val.au64[0] = 0;
1042 pReg->Val.au64[1] = 0;
1043
1044 DBGFREG const enmReg = pReg->enmReg;
1045 AssertMsgReturn(enmReg >= 0 && enmReg <= DBGFREG_END, ("%d (%#x)\n", enmReg, enmReg), VERR_DBGF_INVALID_REGISTER);
1046 if (enmReg != DBGFREG_END)
1047 {
1048 PCDBGFREGDESC pDesc = &g_aDbgfRegDescs[enmReg];
1049 if (!pDesc->pfnGet)
1050 {
1051 PCRTUINT128U pu = (PCRTUINT128U)((uintptr_t)pCtx + pDesc->offCtx);
1052 pReg->enmType = pDesc->enmType;
1053 switch (pDesc->enmType)
1054 {
1055 case DBGFREGVALTYPE_U8: pReg->Val.u8 = pu->au8[0]; break;
1056 case DBGFREGVALTYPE_U16: pReg->Val.u16 = pu->au16[0]; break;
1057 case DBGFREGVALTYPE_U32: pReg->Val.u32 = pu->au32[0]; break;
1058 case DBGFREGVALTYPE_U64: pReg->Val.u64 = pu->au64[0]; break;
1059 case DBGFREGVALTYPE_U128:
1060 pReg->Val.au64[0] = pu->au64[0];
1061 pReg->Val.au64[1] = pu->au64[1];
1062 break;
1063 case DBGFREGVALTYPE_LRD:
1064 pReg->Val.au64[0] = pu->au64[0];
1065 pReg->Val.au16[5] = pu->au16[5];
1066 break;
1067 default:
1068 AssertMsgFailedReturn(("%s %d\n", pDesc->pszName, pDesc->enmType), VERR_INTERNAL_ERROR_3);
1069 }
1070 }
1071 else
1072 {
1073 int rc = pDesc->pfnGet(pVCpu, pDesc, pCtx, &pReg->Val.u);
1074 if (RT_FAILURE(rc))
1075 return rc;
1076 }
1077 }
1078 }
1079
1080 return VINF_SUCCESS;
1081}
1082
1083
1084/**
1085 * Query a batch of registers.
1086 *
1087 * @retval VINF_SUCCESS
1088 * @retval VERR_INVALID_VM_HANDLE
1089 * @retval VERR_INVALID_CPU_ID
1090 * @retval VERR_DBGF_INVALID_REGISTER
1091 *
1092 * @param pVM The VM handle.
1093 * @param idCpu The target CPU ID.
1094 * @param paRegs Pointer to an array of @a cRegs elements. On
1095 * input the enmReg members indicates which
1096 * registers to query. On successful return the
1097 * other members are set. DBGFREG_END can be used
1098 * as a filler.
1099 * @param cRegs The number of entries in @a paRegs.
1100 */
1101VMMR3DECL(int) DBGFR3RegQueryBatch(PVM pVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs)
1102{
1103 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
1104 AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
1105 if (!cRegs)
1106 return VINF_SUCCESS;
1107 AssertReturn(cRegs < _1M, VERR_OUT_OF_RANGE);
1108 AssertPtrReturn(paRegs, VERR_INVALID_POINTER);
1109 size_t iReg = cRegs;
1110 while (iReg-- > 0)
1111 {
1112 DBGFREG enmReg = paRegs[iReg].enmReg;
1113 AssertMsgReturn(enmReg < DBGFREG_END && enmReg >= DBGFREG_AL, ("%d (%#x)", enmReg, enmReg), VERR_DBGF_INVALID_REGISTER);
1114 }
1115
1116 return VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryBatchWorker, 4, pVM, idCpu, paRegs, cRegs);
1117}
1118
1119
1120/**
1121 * Query a all registers for a Virtual CPU.
1122 *
1123 * @retval VINF_SUCCESS
1124 * @retval VERR_INVALID_VM_HANDLE
1125 * @retval VERR_INVALID_CPU_ID
1126 *
1127 * @param pVM The VM handle.
1128 * @param idCpu The target CPU ID.
1129 * @param paRegs Pointer to an array of @a cRegs elements.
1130 * These will be filled with the CPU register
1131 * values. Overflowing entries will be set to
1132 * DBGFREG_END. The returned registers can be
1133 * accessed by using the DBGFREG values as index.
1134 * @param cRegs The number of entries in @a paRegs. The
1135 * recommended value is DBGFREG_ALL_COUNT.
1136 */
1137VMMR3DECL(int) DBGFR3RegQueryAll(PVM pVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs)
1138{
1139 /*
1140 * Validate input.
1141 */
1142 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
1143 AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
1144 if (!cRegs)
1145 return VINF_SUCCESS;
1146 AssertReturn(cRegs < _1M, VERR_OUT_OF_RANGE);
1147 AssertPtrReturn(paRegs, VERR_INVALID_POINTER);
1148
1149 /*
1150 * Convert it into a batch query (lazy bird).
1151 */
1152 unsigned iReg = 0;
1153 while (iReg < cRegs && iReg < DBGFREG_ALL_COUNT)
1154 {
1155 paRegs[iReg].enmReg = (DBGFREG)iReg;
1156 iReg++;
1157 }
1158 while (iReg < cRegs)
1159 paRegs[iReg++].enmReg = DBGFREG_END;
1160
1161 return VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryBatchWorker, 4, pVM, idCpu, paRegs, cRegs);
1162}
1163
1164
1165
1166/**
1167 * Gets the name of a register.
1168 *
1169 * @returns Pointer to read-only register name (lower case). NULL if the
1170 * parameters are invalid.
1171 * @param enmReg The register identifier.
1172 * @param enmType The register type. This is for sort out
1173 * aliases. Pass DBGFREGVALTYPE_INVALID to get
1174 * the standard name.
1175 */
1176VMMR3DECL(const char *) DBGFR3RegName(DBGFREG enmReg, DBGFREGVALTYPE enmType)
1177{
1178 AssertReturn(enmReg >= DBGFREG_AL && enmReg < DBGFREG_END, NULL);
1179 AssertReturn(enmType >= DBGFREGVALTYPE_INVALID && enmType < DBGFREGVALTYPE_END, NULL);
1180
1181 PCDBGFREGDESC pDesc = &g_aDbgfRegDescs[enmReg];
1182 PCDBGFREGALIAS pAlias = pDesc->paAliases;
1183 if ( pAlias
1184 && pDesc->enmType != enmType
1185 && enmType != DBGFREGVALTYPE_INVALID)
1186 {
1187 while (pAlias->pszName)
1188 {
1189 if (pAlias->enmType == enmType)
1190 return pAlias->pszName;
1191 pAlias++;
1192 }
1193 }
1194
1195 return pDesc->pszName;
1196}
1197
1198
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