VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/VMMGuruMeditation.cpp@ 50653

Last change on this file since 50653 was 45693, checked in by vboxsync, 11 years ago

VMM: Introducing VINF_EM_TRIPLE_FAULT status code for triple-fault conditions in HM, to result in a guru meditation.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 27.9 KB
Line 
1/* $Id: VMMGuruMeditation.cpp 45693 2013-04-24 11:32:42Z vboxsync $ */
2/** @file
3 * VMM - The Virtual Machine Monitor, Guru Meditation Code.
4 */
5
6/*
7 * Copyright (C) 2006-2013 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* Header Files *
20*******************************************************************************/
21#define LOG_GROUP LOG_GROUP_VMM
22#include <VBox/vmm/vmm.h>
23#include <VBox/vmm/pdmapi.h>
24#include <VBox/vmm/pdmcritsect.h>
25#include <VBox/vmm/trpm.h>
26#include <VBox/vmm/dbgf.h>
27#include "VMMInternal.h"
28#include <VBox/vmm/vm.h>
29#include <VBox/vmm/mm.h>
30#include <VBox/vmm/iom.h>
31#include <VBox/vmm/em.h>
32
33#include <VBox/err.h>
34#include <VBox/param.h>
35#include <VBox/version.h>
36#include <VBox/vmm/hm.h>
37#include <iprt/assert.h>
38#include <iprt/time.h>
39#include <iprt/stream.h>
40#include <iprt/string.h>
41#include <iprt/stdarg.h>
42
43
44/*******************************************************************************
45* Structures and Typedefs *
46*******************************************************************************/
47/**
48 * Structure to pass to DBGFR3Info() and for doing all other
49 * output during fatal dump.
50 */
51typedef struct VMMR3FATALDUMPINFOHLP
52{
53 /** The helper core. */
54 DBGFINFOHLP Core;
55 /** The release logger instance. */
56 PRTLOGGER pRelLogger;
57 /** The saved release logger flags. */
58 uint32_t fRelLoggerFlags;
59 /** The logger instance. */
60 PRTLOGGER pLogger;
61 /** The saved logger flags. */
62 uint32_t fLoggerFlags;
63 /** The saved logger destination flags. */
64 uint32_t fLoggerDestFlags;
65 /** Whether to output to stderr or not. */
66 bool fStdErr;
67 /** Whether we're still recording the summary or not. */
68 bool fRecSummary;
69 /** Buffer for the summary. */
70 char szSummary[4096-2];
71 /** The current summary offset. */
72 size_t offSummary;
73} VMMR3FATALDUMPINFOHLP, *PVMMR3FATALDUMPINFOHLP;
74/** Pointer to a VMMR3FATALDUMPINFOHLP structure. */
75typedef const VMMR3FATALDUMPINFOHLP *PCVMMR3FATALDUMPINFOHLP;
76
77
78/**
79 * Print formatted string.
80 *
81 * @param pHlp Pointer to this structure.
82 * @param pszFormat The format string.
83 * @param ... Arguments.
84 */
85static DECLCALLBACK(void) vmmR3FatalDumpInfoHlp_pfnPrintf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...)
86{
87 va_list args;
88 va_start(args, pszFormat);
89 pHlp->pfnPrintfV(pHlp, pszFormat, args);
90 va_end(args);
91}
92
93
94/**
95 * Print formatted string.
96 *
97 * @param pHlp Pointer to this structure.
98 * @param pszFormat The format string.
99 * @param args Argument list.
100 */
101static DECLCALLBACK(void) vmmR3FatalDumpInfoHlp_pfnPrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args)
102{
103 PVMMR3FATALDUMPINFOHLP pMyHlp = (PVMMR3FATALDUMPINFOHLP)pHlp;
104
105 if (pMyHlp->pRelLogger)
106 {
107 va_list args2;
108 va_copy(args2, args);
109 RTLogLoggerV(pMyHlp->pRelLogger, pszFormat, args2);
110 va_end(args2);
111 }
112 if (pMyHlp->pLogger)
113 {
114 va_list args2;
115 va_copy(args2, args);
116 RTLogLoggerV(pMyHlp->pLogger, pszFormat, args);
117 va_end(args2);
118 }
119 if (pMyHlp->fStdErr)
120 {
121 va_list args2;
122 va_copy(args2, args);
123 RTStrmPrintfV(g_pStdErr, pszFormat, args);
124 va_end(args2);
125 }
126 if (pMyHlp->fRecSummary)
127 {
128 size_t cchLeft = sizeof(pMyHlp->szSummary) - pMyHlp->offSummary;
129 if (cchLeft > 1)
130 {
131 va_list args2;
132 va_copy(args2, args);
133 size_t cch = RTStrPrintfV(&pMyHlp->szSummary[pMyHlp->offSummary], cchLeft, pszFormat, args);
134 va_end(args2);
135 Assert(cch <= cchLeft);
136 pMyHlp->offSummary += cch;
137 }
138 }
139}
140
141
142/**
143 * Initializes the fatal dump output helper.
144 *
145 * @param pHlp The structure to initialize.
146 */
147static void vmmR3FatalDumpInfoHlpInit(PVMMR3FATALDUMPINFOHLP pHlp)
148{
149 RT_BZERO(pHlp, sizeof(*pHlp));
150
151 pHlp->Core.pfnPrintf = vmmR3FatalDumpInfoHlp_pfnPrintf;
152 pHlp->Core.pfnPrintfV = vmmR3FatalDumpInfoHlp_pfnPrintfV;
153
154 /*
155 * The loggers.
156 */
157 pHlp->pRelLogger = RTLogRelDefaultInstance();
158#ifdef LOG_ENABLED
159 pHlp->pLogger = RTLogDefaultInstance();
160#else
161 if (pHlp->pRelLogger)
162 pHlp->pLogger = RTLogGetDefaultInstance();
163 else
164 pHlp->pLogger = RTLogDefaultInstance();
165#endif
166
167 if (pHlp->pRelLogger)
168 {
169 pHlp->fRelLoggerFlags = pHlp->pRelLogger->fFlags;
170 pHlp->pRelLogger->fFlags &= ~RTLOGFLAGS_DISABLED;
171 pHlp->pRelLogger->fFlags |= RTLOGFLAGS_BUFFERED;
172 }
173
174 if (pHlp->pLogger)
175 {
176 pHlp->fLoggerFlags = pHlp->pLogger->fFlags;
177 pHlp->fLoggerDestFlags = pHlp->pLogger->fDestFlags;
178 pHlp->pLogger->fFlags &= ~RTLOGFLAGS_DISABLED;
179 pHlp->pLogger->fFlags |= RTLOGFLAGS_BUFFERED;
180#ifndef DEBUG_sandervl
181 pHlp->pLogger->fDestFlags |= RTLOGDEST_DEBUGGER;
182#endif
183 }
184
185 /*
186 * Check if we need write to stderr.
187 */
188 pHlp->fStdErr = (!pHlp->pRelLogger || !(pHlp->pRelLogger->fDestFlags & (RTLOGDEST_STDOUT | RTLOGDEST_STDERR)))
189 && (!pHlp->pLogger || !(pHlp->pLogger->fDestFlags & (RTLOGDEST_STDOUT | RTLOGDEST_STDERR)));
190#ifdef DEBUG_sandervl
191 pHlp->fStdErr = false; /* takes too long to display here */
192#endif
193
194 /*
195 * Init the summary recording.
196 */
197 pHlp->fRecSummary = true;
198 pHlp->offSummary = 0;
199 pHlp->szSummary[0] = '\0';
200}
201
202
203/**
204 * Deletes the fatal dump output helper.
205 *
206 * @param pHlp The structure to delete.
207 */
208static void vmmR3FatalDumpInfoHlpDelete(PVMMR3FATALDUMPINFOHLP pHlp)
209{
210 if (pHlp->pRelLogger)
211 {
212 RTLogFlush(pHlp->pRelLogger);
213 pHlp->pRelLogger->fFlags = pHlp->fRelLoggerFlags;
214 }
215
216 if (pHlp->pLogger)
217 {
218 RTLogFlush(pHlp->pLogger);
219 pHlp->pLogger->fFlags = pHlp->fLoggerFlags;
220 pHlp->pLogger->fDestFlags = pHlp->fLoggerDestFlags;
221 }
222}
223
224
225/**
226 * Dumps the VM state on a fatal error.
227 *
228 * @param pVM Pointer to the VM.
229 * @param pVCpu Pointer to the VMCPU.
230 * @param rcErr VBox status code.
231 */
232VMMR3DECL(void) VMMR3FatalDump(PVM pVM, PVMCPU pVCpu, int rcErr)
233{
234 /*
235 * Create our output helper and sync it with the log settings.
236 * This helper will be used for all the output.
237 */
238 VMMR3FATALDUMPINFOHLP Hlp;
239 PCDBGFINFOHLP pHlp = &Hlp.Core;
240 vmmR3FatalDumpInfoHlpInit(&Hlp);
241
242 /* Release owned locks to make sure other VCPUs can continue in case they were waiting for one. */
243 PDMR3CritSectLeaveAll(pVM);
244
245 /*
246 * Header.
247 */
248 pHlp->pfnPrintf(pHlp,
249 "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
250 "!!\n"
251 "!! Guru Meditation %d (%Rrc)\n"
252 "!!\n",
253 rcErr, rcErr);
254
255 /*
256 * Continue according to context.
257 */
258 bool fDoneHyper = false;
259 switch (rcErr)
260 {
261 /*
262 * Hypervisor errors.
263 */
264 case VERR_VMM_RING0_ASSERTION:
265 case VINF_EM_DBG_HYPER_ASSERTION:
266 case VERR_VMM_RING3_CALL_DISABLED:
267 {
268 const char *pszMsg1 = VMMR3GetRZAssertMsg1(pVM);
269 while (pszMsg1 && *pszMsg1 == '\n')
270 pszMsg1++;
271 const char *pszMsg2 = VMMR3GetRZAssertMsg2(pVM);
272 while (pszMsg2 && *pszMsg2 == '\n')
273 pszMsg2++;
274 pHlp->pfnPrintf(pHlp,
275 "%s"
276 "%s",
277 pszMsg1,
278 pszMsg2);
279 if ( !pszMsg2
280 || !*pszMsg2
281 || strchr(pszMsg2, '\0')[-1] != '\n')
282 pHlp->pfnPrintf(pHlp, "\n");
283 /* fall thru */
284 }
285 case VERR_TRPM_DONT_PANIC:
286 case VERR_TRPM_PANIC:
287 case VINF_EM_RAW_STALE_SELECTOR:
288 case VINF_EM_RAW_IRET_TRAP:
289 case VINF_EM_DBG_HYPER_BREAKPOINT:
290 case VINF_EM_DBG_HYPER_STEPPED:
291 case VINF_EM_TRIPLE_FAULT:
292 case VERR_VMM_HYPER_CR3_MISMATCH:
293 {
294 /*
295 * Active trap? This is only of partial interest when in hardware
296 * assisted virtualization mode, thus the different messages.
297 */
298 uint32_t uEIP = CPUMGetHyperEIP(pVCpu);
299 TRPMEVENT enmType;
300 uint8_t u8TrapNo = 0xce;
301 RTGCUINT uErrorCode = 0xdeadface;
302 RTGCUINTPTR uCR2 = 0xdeadface;
303 uint8_t cbInstr = UINT8_MAX;
304 int rc2 = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrorCode, &uCR2, &cbInstr);
305 if (!HMIsEnabled(pVM))
306 {
307 if (RT_SUCCESS(rc2))
308 pHlp->pfnPrintf(pHlp,
309 "!! TRAP=%02x ERRCD=%RGv CR2=%RGv EIP=%RX32 Type=%d cbInstr=%02x\n",
310 u8TrapNo, uErrorCode, uCR2, uEIP, enmType, cbInstr);
311 else
312 pHlp->pfnPrintf(pHlp,
313 "!! EIP=%RX32 NOTRAP\n",
314 uEIP);
315 }
316 else if (RT_SUCCESS(rc2))
317 pHlp->pfnPrintf(pHlp,
318 "!! ACTIVE TRAP=%02x ERRCD=%RGv CR2=%RGv PC=%RGr Type=%d cbInstr=%02x (Guest!)\n",
319 u8TrapNo, uErrorCode, uCR2, CPUMGetGuestRIP(pVCpu), enmType, cbInstr);
320
321 /*
322 * Dump the relevant hypervisor registers and stack.
323 */
324 if (HMIsEnabled(pVM))
325 {
326 if ( rcErr == VERR_VMM_RING0_ASSERTION /* fInRing3Call has already been cleared here. */
327 || pVCpu->vmm.s.CallRing3JmpBufR0.fInRing3Call)
328 {
329 /* Dump the jmpbuf. */
330 pHlp->pfnPrintf(pHlp,
331 "!!\n"
332 "!! CallRing3JmpBuf:\n"
333 "!!\n");
334 pHlp->pfnPrintf(pHlp,
335 "SavedEsp=%RHv SavedEbp=%RHv SpResume=%RHv SpCheck=%RHv\n",
336 pVCpu->vmm.s.CallRing3JmpBufR0.SavedEsp,
337 pVCpu->vmm.s.CallRing3JmpBufR0.SavedEbp,
338 pVCpu->vmm.s.CallRing3JmpBufR0.SpResume,
339 pVCpu->vmm.s.CallRing3JmpBufR0.SpCheck);
340 pHlp->pfnPrintf(pHlp,
341 "pvSavedStack=%RHv cbSavedStack=%#x fInRing3Call=%RTbool\n",
342 pVCpu->vmm.s.CallRing3JmpBufR0.pvSavedStack,
343 pVCpu->vmm.s.CallRing3JmpBufR0.cbSavedStack,
344 pVCpu->vmm.s.CallRing3JmpBufR0.fInRing3Call);
345 pHlp->pfnPrintf(pHlp,
346 "cbUsedMax=%#x cbUsedAvg=%#x cbUsedTotal=%#llx cUsedTotal=%#llx\n",
347 pVCpu->vmm.s.CallRing3JmpBufR0.cbUsedMax,
348 pVCpu->vmm.s.CallRing3JmpBufR0.cbUsedAvg,
349 pVCpu->vmm.s.CallRing3JmpBufR0.cbUsedTotal,
350 pVCpu->vmm.s.CallRing3JmpBufR0.cUsedTotal);
351
352 /* Dump the resume register frame on the stack. */
353 PRTHCUINTPTR pBP;
354#ifdef VMM_R0_SWITCH_STACK
355 pBP = (PRTHCUINTPTR)&pVCpu->vmm.s.pbEMTStackR3[ pVCpu->vmm.s.CallRing3JmpBufR0.SavedEbp
356 - MMHyperCCToR0(pVM, pVCpu->vmm.s.pbEMTStackR3)];
357#else
358 pBP = (PRTHCUINTPTR)&pVCpu->vmm.s.pbEMTStackR3[ pVCpu->vmm.s.CallRing3JmpBufR0.cbSavedStack
359 - pVCpu->vmm.s.CallRing3JmpBufR0.SpCheck
360 + pVCpu->vmm.s.CallRing3JmpBufR0.SavedEbp];
361#endif
362#if HC_ARCH_BITS == 32
363 pHlp->pfnPrintf(pHlp,
364 "eax=volatile ebx=%08x ecx=volatile edx=volatile esi=%08x edi=%08x\n"
365 "eip=%08x esp=%08x ebp=%08x efl=%08x\n"
366 ,
367 pBP[-3], pBP[-2], pBP[-1],
368 pBP[1], pVCpu->vmm.s.CallRing3JmpBufR0.SavedEbp - 8, pBP[0], pBP[-4]);
369#else
370# ifdef RT_OS_WINDOWS
371 pHlp->pfnPrintf(pHlp,
372 "rax=volatile rbx=%016RX64 rcx=volatile rdx=volatile\n"
373 "rsi=%016RX64 rdi=%016RX64 r8=volatile r9=volatile \n"
374 "r10=volatile r11=volatile r12=%016RX64 r13=%016RX64\n"
375 "r14=%016RX64 r15=%016RX64\n"
376 "rip=%016RX64 rsp=%016RX64 rbp=%016RX64 rfl=%08RX64\n"
377 ,
378 pBP[-7],
379 pBP[-6], pBP[-5],
380 pBP[-4], pBP[-3],
381 pBP[-2], pBP[-1],
382 pBP[1], pVCpu->vmm.s.CallRing3JmpBufR0.SavedEbp - 16, pBP[0], pBP[-8]);
383# else
384 pHlp->pfnPrintf(pHlp,
385 "rax=volatile rbx=%016RX64 rcx=volatile rdx=volatile\n"
386 "rsi=volatile rdi=volatile r8=volatile r9=volatile \n"
387 "r10=volatile r11=volatile r12=%016RX64 r13=%016RX64\n"
388 "r14=%016RX64 r15=%016RX64\n"
389 "rip=%016RX64 rsp=%016RX64 rbp=%016RX64 rflags=%08RX64\n"
390 ,
391 pBP[-5],
392 pBP[-4], pBP[-3],
393 pBP[-2], pBP[-1],
394 pBP[1], pVCpu->vmm.s.CallRing3JmpBufR0.SavedEbp - 16, pBP[0], pBP[-6]);
395# endif
396#endif
397
398 /* Callstack. */
399 DBGFADDRESS pc;
400 pc.fFlags = DBGFADDRESS_FLAGS_RING0 | DBGFADDRESS_FLAGS_VALID;
401#if HC_ARCH_BITS == 64
402 pc.FlatPtr = pc.off = pVCpu->vmm.s.CallRing3JmpBufR0.rip;
403#else
404 pc.FlatPtr = pc.off = pVCpu->vmm.s.CallRing3JmpBufR0.eip;
405#endif
406 pc.Sel = DBGF_SEL_FLAT;
407
408 DBGFADDRESS ebp;
409 ebp.fFlags = DBGFADDRESS_FLAGS_RING0 | DBGFADDRESS_FLAGS_VALID;
410 ebp.FlatPtr = ebp.off = pVCpu->vmm.s.CallRing3JmpBufR0.SavedEbp;
411 ebp.Sel = DBGF_SEL_FLAT;
412
413 DBGFADDRESS esp;
414 esp.fFlags = DBGFADDRESS_FLAGS_RING0 | DBGFADDRESS_FLAGS_VALID;
415 esp.Sel = DBGF_SEL_FLAT;
416 esp.FlatPtr = esp.off = pVCpu->vmm.s.CallRing3JmpBufR0.SavedEsp;
417
418 PCDBGFSTACKFRAME pFirstFrame;
419 rc2 = DBGFR3StackWalkBeginEx(pVM->pUVM, pVCpu->idCpu, DBGFCODETYPE_RING0, &ebp, &esp, &pc,
420 DBGFRETURNTYPE_INVALID, &pFirstFrame);
421 if (RT_SUCCESS(rc2))
422 {
423 pHlp->pfnPrintf(pHlp,
424 "!!\n"
425 "!! Call Stack:\n"
426 "!!\n");
427#if HC_ARCH_BITS == 32
428 pHlp->pfnPrintf(pHlp, "EBP Ret EBP Ret CS:EIP Arg0 Arg1 Arg2 Arg3 CS:EIP Symbol [line]\n");
429#else
430 pHlp->pfnPrintf(pHlp, "RBP Ret RBP Ret RIP RIP Symbol [line]\n");
431#endif
432 for (PCDBGFSTACKFRAME pFrame = pFirstFrame;
433 pFrame;
434 pFrame = DBGFR3StackWalkNext(pFrame))
435 {
436#if HC_ARCH_BITS == 32
437 pHlp->pfnPrintf(pHlp,
438 "%RHv %RHv %04RX32:%RHv %RHv %RHv %RHv %RHv",
439 (RTHCUINTPTR)pFrame->AddrFrame.off,
440 (RTHCUINTPTR)pFrame->AddrReturnFrame.off,
441 (RTHCUINTPTR)pFrame->AddrReturnPC.Sel,
442 (RTHCUINTPTR)pFrame->AddrReturnPC.off,
443 pFrame->Args.au32[0],
444 pFrame->Args.au32[1],
445 pFrame->Args.au32[2],
446 pFrame->Args.au32[3]);
447 pHlp->pfnPrintf(pHlp, " %RTsel:%08RHv", pFrame->AddrPC.Sel, pFrame->AddrPC.off);
448#else
449 pHlp->pfnPrintf(pHlp,
450 "%RHv %RHv %RHv %RHv",
451 (RTHCUINTPTR)pFrame->AddrFrame.off,
452 (RTHCUINTPTR)pFrame->AddrReturnFrame.off,
453 (RTHCUINTPTR)pFrame->AddrReturnPC.off,
454 (RTHCUINTPTR)pFrame->AddrPC.off);
455#endif
456 if (pFrame->pSymPC)
457 {
458 RTGCINTPTR offDisp = pFrame->AddrPC.FlatPtr - pFrame->pSymPC->Value;
459 if (offDisp > 0)
460 pHlp->pfnPrintf(pHlp, " %s+%llx", pFrame->pSymPC->szName, (int64_t)offDisp);
461 else if (offDisp < 0)
462 pHlp->pfnPrintf(pHlp, " %s-%llx", pFrame->pSymPC->szName, -(int64_t)offDisp);
463 else
464 pHlp->pfnPrintf(pHlp, " %s", pFrame->pSymPC->szName);
465 }
466 if (pFrame->pLinePC)
467 pHlp->pfnPrintf(pHlp, " [%s @ 0i%d]", pFrame->pLinePC->szFilename, pFrame->pLinePC->uLineNo);
468 pHlp->pfnPrintf(pHlp, "\n");
469 }
470 DBGFR3StackWalkEnd(pFirstFrame);
471 }
472
473 /* raw stack */
474 Hlp.fRecSummary = false;
475 pHlp->pfnPrintf(pHlp,
476 "!!\n"
477 "!! Raw stack (mind the direction). \n"
478 "!! pbEMTStackR0=%RHv pbEMTStackBottomR0=%RHv VMM_STACK_SIZE=%#x\n"
479 "!! pbEmtStackR3=%p\n"
480 "!!\n"
481 "%.*Rhxd\n",
482 MMHyperCCToR0(pVM, pVCpu->vmm.s.pbEMTStackR3),
483 MMHyperCCToR0(pVM, pVCpu->vmm.s.pbEMTStackR3) + VMM_STACK_SIZE,
484 VMM_STACK_SIZE,
485 pVCpu->vmm.s.pbEMTStackR3,
486 VMM_STACK_SIZE, pVCpu->vmm.s.pbEMTStackR3);
487 }
488 else
489 {
490 pHlp->pfnPrintf(pHlp,
491 "!! Skipping ring-0 registers and stack, rcErr=%Rrc\n", rcErr);
492 }
493 }
494 else
495 {
496 /*
497 * Try figure out where eip is.
498 */
499 /* core code? */
500 if (uEIP - (RTGCUINTPTR)pVM->vmm.s.pvCoreCodeRC < pVM->vmm.s.cbCoreCode)
501 pHlp->pfnPrintf(pHlp,
502 "!! EIP is in CoreCode, offset %#x\n",
503 uEIP - (RTGCUINTPTR)pVM->vmm.s.pvCoreCodeRC);
504 else
505 { /* ask PDM */ /** @todo ask DBGFR3Sym later? */
506 char szModName[64];
507 RTRCPTR RCPtrMod;
508 char szNearSym1[260];
509 RTRCPTR RCPtrNearSym1;
510 char szNearSym2[260];
511 RTRCPTR RCPtrNearSym2;
512 int rc = PDMR3LdrQueryRCModFromPC(pVM, uEIP,
513 &szModName[0], sizeof(szModName), &RCPtrMod,
514 &szNearSym1[0], sizeof(szNearSym1), &RCPtrNearSym1,
515 &szNearSym2[0], sizeof(szNearSym2), &RCPtrNearSym2);
516 if (RT_SUCCESS(rc))
517 pHlp->pfnPrintf(pHlp,
518 "!! EIP in %s (%RRv) at rva %x near symbols:\n"
519 "!! %RRv rva %RRv off %08x %s\n"
520 "!! %RRv rva %RRv off -%08x %s\n",
521 szModName, RCPtrMod, (unsigned)(uEIP - RCPtrMod),
522 RCPtrNearSym1, RCPtrNearSym1 - RCPtrMod, (unsigned)(uEIP - RCPtrNearSym1), szNearSym1,
523 RCPtrNearSym2, RCPtrNearSym2 - RCPtrMod, (unsigned)(RCPtrNearSym2 - uEIP), szNearSym2);
524 else
525 pHlp->pfnPrintf(pHlp,
526 "!! EIP is not in any code known to VMM!\n");
527 }
528
529 /* Disassemble the instruction. */
530 char szInstr[256];
531 rc2 = DBGFR3DisasInstrEx(pVM->pUVM, pVCpu->idCpu, 0, 0,
532 DBGF_DISAS_FLAGS_CURRENT_HYPER | DBGF_DISAS_FLAGS_DEFAULT_MODE,
533 &szInstr[0], sizeof(szInstr), NULL);
534 if (RT_SUCCESS(rc2))
535 pHlp->pfnPrintf(pHlp,
536 "!! %s\n", szInstr);
537
538 /* Dump the hypervisor cpu state. */
539 pHlp->pfnPrintf(pHlp,
540 "!!\n"
541 "!!\n"
542 "!!\n");
543 rc2 = DBGFR3Info(pVM->pUVM, "cpumhyper", "verbose", pHlp);
544 fDoneHyper = true;
545
546 /* Callstack. */
547 PCDBGFSTACKFRAME pFirstFrame;
548 rc2 = DBGFR3StackWalkBegin(pVM->pUVM, pVCpu->idCpu, DBGFCODETYPE_HYPER, &pFirstFrame);
549 if (RT_SUCCESS(rc2))
550 {
551 pHlp->pfnPrintf(pHlp,
552 "!!\n"
553 "!! Call Stack:\n"
554 "!!\n"
555 "EBP Ret EBP Ret CS:EIP Arg0 Arg1 Arg2 Arg3 CS:EIP Symbol [line]\n");
556 for (PCDBGFSTACKFRAME pFrame = pFirstFrame;
557 pFrame;
558 pFrame = DBGFR3StackWalkNext(pFrame))
559 {
560 pHlp->pfnPrintf(pHlp,
561 "%08RX32 %08RX32 %04RX32:%08RX32 %08RX32 %08RX32 %08RX32 %08RX32",
562 (uint32_t)pFrame->AddrFrame.off,
563 (uint32_t)pFrame->AddrReturnFrame.off,
564 (uint32_t)pFrame->AddrReturnPC.Sel,
565 (uint32_t)pFrame->AddrReturnPC.off,
566 pFrame->Args.au32[0],
567 pFrame->Args.au32[1],
568 pFrame->Args.au32[2],
569 pFrame->Args.au32[3]);
570 pHlp->pfnPrintf(pHlp, " %RTsel:%08RGv", pFrame->AddrPC.Sel, pFrame->AddrPC.off);
571 if (pFrame->pSymPC)
572 {
573 RTGCINTPTR offDisp = pFrame->AddrPC.FlatPtr - pFrame->pSymPC->Value;
574 if (offDisp > 0)
575 pHlp->pfnPrintf(pHlp, " %s+%llx", pFrame->pSymPC->szName, (int64_t)offDisp);
576 else if (offDisp < 0)
577 pHlp->pfnPrintf(pHlp, " %s-%llx", pFrame->pSymPC->szName, -(int64_t)offDisp);
578 else
579 pHlp->pfnPrintf(pHlp, " %s", pFrame->pSymPC->szName);
580 }
581 if (pFrame->pLinePC)
582 pHlp->pfnPrintf(pHlp, " [%s @ 0i%d]", pFrame->pLinePC->szFilename, pFrame->pLinePC->uLineNo);
583 pHlp->pfnPrintf(pHlp, "\n");
584 }
585 DBGFR3StackWalkEnd(pFirstFrame);
586 }
587
588 /* raw stack */
589 Hlp.fRecSummary = false;
590 pHlp->pfnPrintf(pHlp,
591 "!!\n"
592 "!! Raw stack (mind the direction). pbEMTStackRC=%RRv pbEMTStackBottomRC=%RRv\n"
593 "!!\n"
594 "%.*Rhxd\n",
595 pVCpu->vmm.s.pbEMTStackRC, pVCpu->vmm.s.pbEMTStackBottomRC,
596 VMM_STACK_SIZE, pVCpu->vmm.s.pbEMTStackR3);
597 } /* !HMIsEnabled */
598 break;
599 }
600
601 case VERR_IEM_INSTR_NOT_IMPLEMENTED:
602 case VERR_IEM_ASPECT_NOT_IMPLEMENTED:
603 {
604 DBGFR3Info(pVM->pUVM, "cpumguest", NULL, pHlp);
605 DBGFR3Info(pVM->pUVM, "cpumguestinstr", NULL, pHlp);
606 break;
607 }
608
609 default:
610 {
611 break;
612 }
613
614 } /* switch (rcErr) */
615 Hlp.fRecSummary = false;
616
617
618 /*
619 * Generic info dumper loop.
620 */
621 static struct
622 {
623 const char *pszInfo;
624 const char *pszArgs;
625 } const aInfo[] =
626 {
627 { "mappings", NULL },
628 { "hma", NULL },
629 { "cpumguest", "verbose" },
630 { "cpumguestinstr", "verbose" },
631 { "cpumhyper", "verbose" },
632 { "cpumhost", "verbose" },
633 { "mode", "all" },
634 { "cpuid", "verbose" },
635 { "handlers", "phys virt hyper stats" },
636 { "timers", NULL },
637 { "activetimers", NULL },
638 };
639 for (unsigned i = 0; i < RT_ELEMENTS(aInfo); i++)
640 {
641 if (fDoneHyper && !strcmp(aInfo[i].pszInfo, "cpumhyper"))
642 continue;
643 pHlp->pfnPrintf(pHlp,
644 "!!\n"
645 "!! {%s, %s}\n"
646 "!!\n",
647 aInfo[i].pszInfo, aInfo[i].pszArgs);
648 DBGFR3Info(pVM->pUVM, aInfo[i].pszInfo, aInfo[i].pszArgs, pHlp);
649 }
650
651 /* All other info items */
652 DBGFR3InfoMulti(pVM,
653 "*",
654 "mappings|hma|cpum|cpumguest|cpumguestinstr|cpumhyper|cpumhost|mode|cpuid"
655 "|pgmpd|pgmcr3|timers|activetimers|handlers|help",
656 "!!\n"
657 "!! {%s}\n"
658 "!!\n",
659 pHlp);
660
661
662 /* done */
663 pHlp->pfnPrintf(pHlp,
664 "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
665
666
667 /*
668 * Repeat the summary to stderr so we don't have to scroll half a mile up.
669 */
670 if (Hlp.szSummary[0])
671 RTStrmPrintf(g_pStdErr,
672 "%s"
673 "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",
674 Hlp.szSummary);
675
676 /*
677 * Delete the output instance (flushing and restoring of flags).
678 */
679 vmmR3FatalDumpInfoHlpDelete(&Hlp);
680}
681
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use