VirtualBox

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

Last change on this file since 72064 was 70948, checked in by vboxsync, 7 years ago

VMM: Added a bMainExecutionEngine member to the VM structure for use instead of fHMEnabled and fNEMEnabled. Changed a lot of HMIsEnabled invocations to use the new macros VM_IS_RAW_MODE_ENABLED and VM_IS_HM_OR_NEM_ENABLED. Eliminated fHMEnabledFixed. Fixed inverted test for raw-mode debug register sanity checking. Some other minor cleanups.

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