VirtualBox

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

Last change on this file since 62478 was 62478, checked in by vboxsync, 8 years ago

(C) 2016

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