VirtualBox

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

最後變更 在這個檔案從39678是 39678,由 vboxsync 提交於 13 年 前

guru: todo

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id
檔案大小: 27.4 KB
 
1/* $Id: VMMGuruMeditation.cpp 39678 2011-12-26 21:46:15Z vboxsync $ */
2/** @file
3 * VMM - The Virtual Machine Monitor, Guru Meditation Code.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.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/hwaccm.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 memset(pHlp, 0, 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#ifndef LOG_ENABLED
159 if (!pHlp->pRelLogger)
160#endif
161 pHlp->pLogger = RTLogDefaultInstance();
162
163 if (pHlp->pRelLogger)
164 {
165 pHlp->fRelLoggerFlags = pHlp->pRelLogger->fFlags;
166 pHlp->pRelLogger->fFlags &= ~(RTLOGFLAGS_BUFFERED | RTLOGFLAGS_DISABLED);
167 }
168
169 /** @todo don't create a debug logger in release builds if we already
170 * have a release logger! */
171 if (pHlp->pLogger)
172 {
173 pHlp->fLoggerFlags = pHlp->pLogger->fFlags;
174 pHlp->fLoggerDestFlags = pHlp->pLogger->fDestFlags;
175 pHlp->pLogger->fFlags &= ~(RTLOGFLAGS_BUFFERED | RTLOGFLAGS_DISABLED);
176#ifndef DEBUG_sandervl
177 pHlp->pLogger->fDestFlags |= RTLOGDEST_DEBUGGER;
178#endif
179 }
180
181 /*
182 * Check if we need write to stderr.
183 */
184 pHlp->fStdErr = (!pHlp->pRelLogger || !(pHlp->pRelLogger->fDestFlags & (RTLOGDEST_STDOUT | RTLOGDEST_STDERR)))
185 && (!pHlp->pLogger || !(pHlp->pLogger->fDestFlags & (RTLOGDEST_STDOUT | RTLOGDEST_STDERR)));
186#ifdef DEBUG_sandervl
187 pHlp->fStdErr = false; /* takes too long to display here */
188#endif
189
190 /*
191 * Init the summary recording.
192 */
193 pHlp->fRecSummary = true;
194 pHlp->offSummary = 0;
195 pHlp->szSummary[0] = '\0';
196}
197
198
199/**
200 * Deletes the fatal dump output helper.
201 *
202 * @param pHlp The structure to delete.
203 */
204static void vmmR3FatalDumpInfoHlpDelete(PVMMR3FATALDUMPINFOHLP pHlp)
205{
206 if (pHlp->pRelLogger)
207 {
208 RTLogFlush(pHlp->pRelLogger);
209 pHlp->pRelLogger->fFlags = pHlp->fRelLoggerFlags;
210 }
211
212 if (pHlp->pLogger)
213 {
214 RTLogFlush(pHlp->pLogger);
215 pHlp->pLogger->fFlags = pHlp->fLoggerFlags;
216 pHlp->pLogger->fDestFlags = pHlp->fLoggerDestFlags;
217 }
218}
219
220
221/**
222 * Dumps the VM state on a fatal error.
223 *
224 * @param pVM VM Handle.
225 * @param pVCpu VMCPU Handle.
226 * @param rcErr VBox status code.
227 */
228VMMR3DECL(void) VMMR3FatalDump(PVM pVM, PVMCPU pVCpu, int rcErr)
229{
230 /*
231 * Create our output helper and sync it with the log settings.
232 * This helper will be used for all the output.
233 */
234 VMMR3FATALDUMPINFOHLP Hlp;
235 PCDBGFINFOHLP pHlp = &Hlp.Core;
236 vmmR3FatalDumpInfoHlpInit(&Hlp);
237
238 /* Release owned locks to make sure other VCPUs can continue in case they were waiting for one. */
239 PDMR3CritSectLeaveAll(pVM);
240
241 /*
242 * Header.
243 */
244 pHlp->pfnPrintf(pHlp,
245 "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
246 "!!\n"
247 "!! Guru Meditation %d (%Rrc)\n"
248 "!!\n",
249 rcErr, rcErr);
250
251 /*
252 * Continue according to context.
253 */
254 bool fDoneHyper = false;
255 switch (rcErr)
256 {
257 /*
258 * Hypervisor errors.
259 */
260 case VERR_VMM_RING0_ASSERTION:
261 case VINF_EM_DBG_HYPER_ASSERTION:
262 case VERR_VMM_RING3_CALL_DISABLED:
263 {
264 const char *pszMsg1 = VMMR3GetRZAssertMsg1(pVM);
265 while (pszMsg1 && *pszMsg1 == '\n')
266 pszMsg1++;
267 const char *pszMsg2 = VMMR3GetRZAssertMsg2(pVM);
268 while (pszMsg2 && *pszMsg2 == '\n')
269 pszMsg2++;
270 pHlp->pfnPrintf(pHlp,
271 "%s"
272 "%s",
273 pszMsg1,
274 pszMsg2);
275 if ( !pszMsg2
276 || !*pszMsg2
277 || strchr(pszMsg2, '\0')[-1] != '\n')
278 pHlp->pfnPrintf(pHlp, "\n");
279 /* fall thru */
280 }
281 case VERR_TRPM_DONT_PANIC:
282 case VERR_TRPM_PANIC:
283 case VINF_EM_RAW_STALE_SELECTOR:
284 case VINF_EM_RAW_IRET_TRAP:
285 case VINF_EM_DBG_HYPER_BREAKPOINT:
286 case VINF_EM_DBG_HYPER_STEPPED:
287 case VERR_VMM_HYPER_CR3_MISMATCH:
288 {
289 /*
290 * Active trap? This is only of partial interest when in hardware
291 * assisted virtualization mode, thus the different messages.
292 */
293 uint32_t uEIP = CPUMGetHyperEIP(pVCpu);
294 TRPMEVENT enmType;
295 uint8_t u8TrapNo = 0xce;
296 RTGCUINT uErrorCode = 0xdeadface;
297 RTGCUINTPTR uCR2 = 0xdeadface;
298 int rc2 = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrorCode, &uCR2);
299 if (!HWACCMIsEnabled(pVM))
300 {
301 if (RT_SUCCESS(rc2))
302 pHlp->pfnPrintf(pHlp,
303 "!! TRAP=%02x ERRCD=%RGv CR2=%RGv EIP=%RX32 Type=%d\n",
304 u8TrapNo, uErrorCode, uCR2, uEIP, enmType);
305 else
306 pHlp->pfnPrintf(pHlp,
307 "!! EIP=%RX32 NOTRAP\n",
308 uEIP);
309 }
310 else if (RT_SUCCESS(rc2))
311 pHlp->pfnPrintf(pHlp,
312 "!! ACTIVE TRAP=%02x ERRCD=%RGv CR2=%RGv PC=%RGr Type=%d (Guest!)\n",
313 u8TrapNo, uErrorCode, uCR2, CPUMGetGuestRIP(pVCpu), enmType);
314
315 /*
316 * Dump the relevant hypervisor registers and stack.
317 */
318 if (HWACCMIsEnabled(pVM))
319 {
320 if ( rcErr == VERR_VMM_RING0_ASSERTION /* fInRing3Call has already been cleared here. */
321 || pVCpu->vmm.s.CallRing3JmpBufR0.fInRing3Call)
322 {
323 /* Dump the jmpbuf. */
324 pHlp->pfnPrintf(pHlp,
325 "!!\n"
326 "!! CallRing3JmpBuf:\n"
327 "!!\n");
328 pHlp->pfnPrintf(pHlp,
329 "SavedEsp=%RHv SavedEbp=%RHv SpResume=%RHv SpCheck=%RHv\n",
330 pVCpu->vmm.s.CallRing3JmpBufR0.SavedEsp,
331 pVCpu->vmm.s.CallRing3JmpBufR0.SavedEbp,
332 pVCpu->vmm.s.CallRing3JmpBufR0.SpResume,
333 pVCpu->vmm.s.CallRing3JmpBufR0.SpCheck);
334 pHlp->pfnPrintf(pHlp,
335 "pvSavedStack=%RHv cbSavedStack=%#x fInRing3Call=%RTbool\n",
336 pVCpu->vmm.s.CallRing3JmpBufR0.pvSavedStack,
337 pVCpu->vmm.s.CallRing3JmpBufR0.cbSavedStack,
338 pVCpu->vmm.s.CallRing3JmpBufR0.fInRing3Call);
339 pHlp->pfnPrintf(pHlp,
340 "cbUsedMax=%#x cbUsedAvg=%#x cbUsedTotal=%#llx cUsedTotal=%#llx\n",
341 pVCpu->vmm.s.CallRing3JmpBufR0.cbUsedMax,
342 pVCpu->vmm.s.CallRing3JmpBufR0.cbUsedAvg,
343 pVCpu->vmm.s.CallRing3JmpBufR0.cbUsedTotal,
344 pVCpu->vmm.s.CallRing3JmpBufR0.cUsedTotal);
345
346 /* Dump the resume register frame on the stack. */
347 PRTHCUINTPTR pBP;
348#ifdef VMM_R0_SWITCH_STACK
349 pBP = (PRTHCUINTPTR)&pVCpu->vmm.s.pbEMTStackR3[ pVCpu->vmm.s.CallRing3JmpBufR0.SavedEbp
350 - MMHyperCCToR0(pVM, pVCpu->vmm.s.pbEMTStackR3)];
351#else
352 pBP = (PRTHCUINTPTR)&pVCpu->vmm.s.pbEMTStackR3[ pVCpu->vmm.s.CallRing3JmpBufR0.cbSavedStack
353 - pVCpu->vmm.s.CallRing3JmpBufR0.SpCheck
354 + pVCpu->vmm.s.CallRing3JmpBufR0.SavedEbp];
355#endif
356#if HC_ARCH_BITS == 32
357 pHlp->pfnPrintf(pHlp,
358 "eax=volatile ebx=%08x ecx=volatile edx=volatile esi=%08x edi=%08x\n"
359 "eip=%08x esp=%08x ebp=%08x efl=%08x\n"
360 ,
361 pBP[-3], pBP[-2], pBP[-1],
362 pBP[1], pVCpu->vmm.s.CallRing3JmpBufR0.SavedEbp - 8, pBP[0], pBP[-4]);
363#else
364# ifdef RT_OS_WINDOWS
365 pHlp->pfnPrintf(pHlp,
366 "rax=volatile rbx=%016RX64 rcx=volatile rdx=volatile\n"
367 "rsi=%016RX64 rdi=%016RX64 r8=volatile r9=volatile \n"
368 "r10=volatile r11=volatile r12=%016RX64 r13=%016RX64\n"
369 "r14=%016RX64 r15=%016RX64\n"
370 "rip=%016RX64 rsp=%016RX64 rbp=%016RX64 rfl=%08RX64\n"
371 ,
372 pBP[-7],
373 pBP[-6], pBP[-5],
374 pBP[-4], pBP[-3],
375 pBP[-2], pBP[-1],
376 pBP[1], pVCpu->vmm.s.CallRing3JmpBufR0.SavedEbp - 16, pBP[0], pBP[-8]);
377# else
378 pHlp->pfnPrintf(pHlp,
379 "rax=volatile rbx=%016RX64 rcx=volatile rdx=volatile\n"
380 "rsi=volatile rdi=volatile r8=volatile r9=volatile \n"
381 "r10=volatile r11=volatile r12=%016RX64 r13=%016RX64\n"
382 "r14=%016RX64 r15=%016RX64\n"
383 "rip=%016RX64 rsp=%016RX64 rbp=%016RX64 rflags=%08RX64\n"
384 ,
385 pBP[-5],
386 pBP[-4], pBP[-3],
387 pBP[-2], pBP[-1],
388 pBP[1], pVCpu->vmm.s.CallRing3JmpBufR0.SavedEbp - 16, pBP[0], pBP[-6]);
389# endif
390#endif
391
392 /* Callstack. */
393 DBGFADDRESS pc;
394 pc.fFlags = DBGFADDRESS_FLAGS_RING0 | DBGFADDRESS_FLAGS_VALID;
395#if HC_ARCH_BITS == 64
396 pc.FlatPtr = pc.off = pVCpu->vmm.s.CallRing3JmpBufR0.rip;
397#else
398 pc.FlatPtr = pc.off = pVCpu->vmm.s.CallRing3JmpBufR0.eip;
399#endif
400 pc.Sel = DBGF_SEL_FLAT;
401
402 DBGFADDRESS ebp;
403 ebp.fFlags = DBGFADDRESS_FLAGS_RING0 | DBGFADDRESS_FLAGS_VALID;
404 ebp.FlatPtr = ebp.off = pVCpu->vmm.s.CallRing3JmpBufR0.SavedEbp;
405 ebp.Sel = DBGF_SEL_FLAT;
406
407 DBGFADDRESS esp;
408 esp.fFlags = DBGFADDRESS_FLAGS_RING0 | DBGFADDRESS_FLAGS_VALID;
409 esp.Sel = DBGF_SEL_FLAT;
410 esp.FlatPtr = esp.off = pVCpu->vmm.s.CallRing3JmpBufR0.SavedEsp;
411
412 PCDBGFSTACKFRAME pFirstFrame;
413 rc2 = DBGFR3StackWalkBeginEx(pVM, pVCpu->idCpu, DBGFCODETYPE_RING0, &ebp, &esp, &pc,
414 DBGFRETURNTYPE_INVALID, &pFirstFrame);
415 if (RT_SUCCESS(rc2))
416 {
417 pHlp->pfnPrintf(pHlp,
418 "!!\n"
419 "!! Call Stack:\n"
420 "!!\n");
421#if HC_ARCH_BITS == 32
422 pHlp->pfnPrintf(pHlp, "EBP Ret EBP Ret CS:EIP Arg0 Arg1 Arg2 Arg3 CS:EIP Symbol [line]\n");
423#else
424 pHlp->pfnPrintf(pHlp, "RBP Ret RBP Ret RIP RIP Symbol [line]\n");
425#endif
426 for (PCDBGFSTACKFRAME pFrame = pFirstFrame;
427 pFrame;
428 pFrame = DBGFR3StackWalkNext(pFrame))
429 {
430#if HC_ARCH_BITS == 32
431 pHlp->pfnPrintf(pHlp,
432 "%RHv %RHv %04RX32:%RHv %RHv %RHv %RHv %RHv",
433 (RTHCUINTPTR)pFrame->AddrFrame.off,
434 (RTHCUINTPTR)pFrame->AddrReturnFrame.off,
435 (RTHCUINTPTR)pFrame->AddrReturnPC.Sel,
436 (RTHCUINTPTR)pFrame->AddrReturnPC.off,
437 pFrame->Args.au32[0],
438 pFrame->Args.au32[1],
439 pFrame->Args.au32[2],
440 pFrame->Args.au32[3]);
441 pHlp->pfnPrintf(pHlp, " %RTsel:%08RHv", pFrame->AddrPC.Sel, pFrame->AddrPC.off);
442#else
443 pHlp->pfnPrintf(pHlp,
444 "%RHv %RHv %RHv %RHv",
445 (RTHCUINTPTR)pFrame->AddrFrame.off,
446 (RTHCUINTPTR)pFrame->AddrReturnFrame.off,
447 (RTHCUINTPTR)pFrame->AddrReturnPC.off,
448 (RTHCUINTPTR)pFrame->AddrPC.off);
449#endif
450 if (pFrame->pSymPC)
451 {
452 RTGCINTPTR offDisp = pFrame->AddrPC.FlatPtr - pFrame->pSymPC->Value;
453 if (offDisp > 0)
454 pHlp->pfnPrintf(pHlp, " %s+%llx", pFrame->pSymPC->szName, (int64_t)offDisp);
455 else if (offDisp < 0)
456 pHlp->pfnPrintf(pHlp, " %s-%llx", pFrame->pSymPC->szName, -(int64_t)offDisp);
457 else
458 pHlp->pfnPrintf(pHlp, " %s", pFrame->pSymPC->szName);
459 }
460 if (pFrame->pLinePC)
461 pHlp->pfnPrintf(pHlp, " [%s @ 0i%d]", pFrame->pLinePC->szFilename, pFrame->pLinePC->uLineNo);
462 pHlp->pfnPrintf(pHlp, "\n");
463 }
464 DBGFR3StackWalkEnd(pFirstFrame);
465 }
466
467 /* raw stack */
468 Hlp.fRecSummary = false;
469 pHlp->pfnPrintf(pHlp,
470 "!!\n"
471 "!! Raw stack (mind the direction). \n"
472 "!! pbEMTStackR0=%RHv pbEMTStackBottomR0=%RHv VMM_STACK_SIZE=%#x\n"
473 "!! pbEmtStackR3=%p\n"
474 "!!\n"
475 "%.*Rhxd\n",
476 MMHyperCCToR0(pVM, pVCpu->vmm.s.pbEMTStackR3),
477 MMHyperCCToR0(pVM, pVCpu->vmm.s.pbEMTStackR3) + VMM_STACK_SIZE,
478 VMM_STACK_SIZE,
479 pVCpu->vmm.s.pbEMTStackR3,
480 VMM_STACK_SIZE, pVCpu->vmm.s.pbEMTStackR3);
481 }
482 else
483 {
484 pHlp->pfnPrintf(pHlp,
485 "!! Skipping ring-0 registers and stack, rcErr=%Rrc\n", rcErr);
486 }
487 }
488 else
489 {
490 /*
491 * Try figure out where eip is.
492 */
493 /* core code? */
494 if (uEIP - (RTGCUINTPTR)pVM->vmm.s.pvCoreCodeRC < pVM->vmm.s.cbCoreCode)
495 pHlp->pfnPrintf(pHlp,
496 "!! EIP is in CoreCode, offset %#x\n",
497 uEIP - (RTGCUINTPTR)pVM->vmm.s.pvCoreCodeRC);
498 else
499 { /* ask PDM */ /** @todo ask DBGFR3Sym later? */
500 char szModName[64];
501 RTRCPTR RCPtrMod;
502 char szNearSym1[260];
503 RTRCPTR RCPtrNearSym1;
504 char szNearSym2[260];
505 RTRCPTR RCPtrNearSym2;
506 int rc = PDMR3LdrQueryRCModFromPC(pVM, uEIP,
507 &szModName[0], sizeof(szModName), &RCPtrMod,
508 &szNearSym1[0], sizeof(szNearSym1), &RCPtrNearSym1,
509 &szNearSym2[0], sizeof(szNearSym2), &RCPtrNearSym2);
510 if (RT_SUCCESS(rc))
511 pHlp->pfnPrintf(pHlp,
512 "!! EIP in %s (%RRv) at rva %x near symbols:\n"
513 "!! %RRv rva %RRv off %08x %s\n"
514 "!! %RRv rva %RRv off -%08x %s\n",
515 szModName, RCPtrMod, (unsigned)(uEIP - RCPtrMod),
516 RCPtrNearSym1, RCPtrNearSym1 - RCPtrMod, (unsigned)(uEIP - RCPtrNearSym1), szNearSym1,
517 RCPtrNearSym2, RCPtrNearSym2 - RCPtrMod, (unsigned)(RCPtrNearSym2 - uEIP), szNearSym2);
518 else
519 pHlp->pfnPrintf(pHlp,
520 "!! EIP is not in any code known to VMM!\n");
521 }
522
523 /* Disassemble the instruction. */
524 char szInstr[256];
525 rc2 = DBGFR3DisasInstrEx(pVM, pVCpu->idCpu, 0, 0, DBGF_DISAS_FLAGS_CURRENT_HYPER | DBGF_DISAS_FLAGS_DEFAULT_MODE,
526 &szInstr[0], sizeof(szInstr), NULL);
527 if (RT_SUCCESS(rc2))
528 pHlp->pfnPrintf(pHlp,
529 "!! %s\n", szInstr);
530
531 /* Dump the hypervisor cpu state. */
532 pHlp->pfnPrintf(pHlp,
533 "!!\n"
534 "!!\n"
535 "!!\n");
536 rc2 = DBGFR3Info(pVM, "cpumhyper", "verbose", pHlp);
537 fDoneHyper = true;
538
539 /* Callstack. */
540 PCDBGFSTACKFRAME pFirstFrame;
541 rc2 = DBGFR3StackWalkBegin(pVM, pVCpu->idCpu, DBGFCODETYPE_HYPER, &pFirstFrame);
542 if (RT_SUCCESS(rc2))
543 {
544 pHlp->pfnPrintf(pHlp,
545 "!!\n"
546 "!! Call Stack:\n"
547 "!!\n"
548 "EBP Ret EBP Ret CS:EIP Arg0 Arg1 Arg2 Arg3 CS:EIP Symbol [line]\n");
549 for (PCDBGFSTACKFRAME pFrame = pFirstFrame;
550 pFrame;
551 pFrame = DBGFR3StackWalkNext(pFrame))
552 {
553 pHlp->pfnPrintf(pHlp,
554 "%08RX32 %08RX32 %04RX32:%08RX32 %08RX32 %08RX32 %08RX32 %08RX32",
555 (uint32_t)pFrame->AddrFrame.off,
556 (uint32_t)pFrame->AddrReturnFrame.off,
557 (uint32_t)pFrame->AddrReturnPC.Sel,
558 (uint32_t)pFrame->AddrReturnPC.off,
559 pFrame->Args.au32[0],
560 pFrame->Args.au32[1],
561 pFrame->Args.au32[2],
562 pFrame->Args.au32[3]);
563 pHlp->pfnPrintf(pHlp, " %RTsel:%08RGv", pFrame->AddrPC.Sel, pFrame->AddrPC.off);
564 if (pFrame->pSymPC)
565 {
566 RTGCINTPTR offDisp = pFrame->AddrPC.FlatPtr - pFrame->pSymPC->Value;
567 if (offDisp > 0)
568 pHlp->pfnPrintf(pHlp, " %s+%llx", pFrame->pSymPC->szName, (int64_t)offDisp);
569 else if (offDisp < 0)
570 pHlp->pfnPrintf(pHlp, " %s-%llx", pFrame->pSymPC->szName, -(int64_t)offDisp);
571 else
572 pHlp->pfnPrintf(pHlp, " %s", pFrame->pSymPC->szName);
573 }
574 if (pFrame->pLinePC)
575 pHlp->pfnPrintf(pHlp, " [%s @ 0i%d]", pFrame->pLinePC->szFilename, pFrame->pLinePC->uLineNo);
576 pHlp->pfnPrintf(pHlp, "\n");
577 }
578 DBGFR3StackWalkEnd(pFirstFrame);
579 }
580
581 /* raw stack */
582 Hlp.fRecSummary = false;
583 pHlp->pfnPrintf(pHlp,
584 "!!\n"
585 "!! Raw stack (mind the direction). pbEMTStackRC=%RRv pbEMTStackBottomRC=%RRv\n"
586 "!!\n"
587 "%.*Rhxd\n",
588 pVCpu->vmm.s.pbEMTStackRC, pVCpu->vmm.s.pbEMTStackBottomRC,
589 VMM_STACK_SIZE, pVCpu->vmm.s.pbEMTStackR3);
590 } /* !HWACCMIsEnabled */
591 break;
592 }
593
594 default:
595 {
596 break;
597 }
598
599 } /* switch (rcErr) */
600 Hlp.fRecSummary = false;
601
602
603 /*
604 * Generic info dumper loop.
605 */
606 static struct
607 {
608 const char *pszInfo;
609 const char *pszArgs;
610 } const aInfo[] =
611 {
612 { "mappings", NULL },
613 { "hma", NULL },
614 { "cpumguest", "verbose" },
615 { "cpumguestinstr", "verbose" },
616 { "cpumhyper", "verbose" },
617 { "cpumhost", "verbose" },
618 { "mode", "all" },
619 { "cpuid", "verbose" },
620 { "handlers", "phys virt hyper stats" },
621 { "timers", NULL },
622 { "activetimers", NULL },
623 };
624 for (unsigned i = 0; i < RT_ELEMENTS(aInfo); i++)
625 {
626 if (fDoneHyper && !strcmp(aInfo[i].pszInfo, "cpumhyper"))
627 continue;
628 pHlp->pfnPrintf(pHlp,
629 "!!\n"
630 "!! {%s, %s}\n"
631 "!!\n",
632 aInfo[i].pszInfo, aInfo[i].pszArgs);
633 DBGFR3Info(pVM, aInfo[i].pszInfo, aInfo[i].pszArgs, pHlp);
634 }
635
636 /* All other info items */
637 DBGFR3InfoMulti(pVM,
638 "*",
639 "mappings|hma|cpum|cpumguest|cpumguestinstr|cpumhyper|cpumhost|mode|cpuid"
640 "|pgmpd|pgmcr3|timers|activetimers|handlers|help",
641 "!!\n"
642 "!! {%s}\n"
643 "!!\n",
644 pHlp);
645
646
647 /* done */
648 pHlp->pfnPrintf(pHlp,
649 "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
650
651
652 /*
653 * Repeat the summary to stderr so we don't have to scroll half a mile up.
654 */
655 if (Hlp.szSummary[0])
656 RTStrmPrintf(g_pStdErr,
657 "%s"
658 "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",
659 Hlp.szSummary);
660
661 /*
662 * Delete the output instance (flushing and restoring of flags).
663 */
664 vmmR3FatalDumpInfoHlpDelete(&Hlp);
665}
666
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette