Changeset 73377 in vbox
- Timestamp:
- Jul 27, 2018 8:01:56 AM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/DBGFStack.cpp
r73360 r73377 31 31 #include <iprt/param.h> 32 32 #include <iprt/assert.h> 33 #include <iprt/alloca.h> 34 #include <iprt/mem.h> 33 35 #include <iprt/string.h> 34 #include <iprt/alloca.h> 35 36 37 36 37 38 /********************************************************************************************************************************* 39 * Structures and Typedefs * 40 *********************************************************************************************************************************/ 38 41 /** 39 * Read stack memory. 40 */ 41 DECLINLINE(int) dbgfR3Read(PUVM pUVM, VMCPUID idCpu, void *pvBuf, PCDBGFADDRESS pSrcAddr, size_t cb, size_t *pcbRead) 42 * Unwind context. 43 * 44 * @note Using a constructor and destructor here for simple+safe cleanup. 45 * 46 * @todo Generalize and move to IPRT or some such place. 47 */ 48 typedef struct DBGFUNWINDCTX 49 { 50 PUVM m_pUVM; 51 VMCPUID m_idCpu; 52 RTDBGAS m_hAs; 53 uint64_t m_uPc; 54 uint64_t m_aGprs[16]; 55 56 RTDBGMOD m_hCached; 57 RTUINTPTR m_uCachedMapping; 58 RTUINTPTR m_cbCachedMapping; 59 uint8_t *m_pbCachedInfo; 60 size_t m_cbCachedInfo; 61 62 DBGFUNWINDCTX(PUVM pUVM, VMCPUID idCpu, PCCPUMCTX pInitialCtx, RTDBGAS hAs) 63 { 64 if (pInitialCtx) 65 { 66 m_aGprs[X86_GREG_xAX] = pInitialCtx->rax; 67 m_aGprs[X86_GREG_xCX] = pInitialCtx->rcx; 68 m_aGprs[X86_GREG_xDX] = pInitialCtx->rdx; 69 m_aGprs[X86_GREG_xBX] = pInitialCtx->rbx; 70 m_aGprs[X86_GREG_xSP] = pInitialCtx->rsp; 71 m_aGprs[X86_GREG_xBP] = pInitialCtx->rbp; 72 m_aGprs[X86_GREG_xSI] = pInitialCtx->rsi; 73 m_aGprs[X86_GREG_xDI] = pInitialCtx->rdi; 74 m_aGprs[X86_GREG_x8 ] = pInitialCtx->r8; 75 m_aGprs[X86_GREG_x9 ] = pInitialCtx->r9; 76 m_aGprs[X86_GREG_x10] = pInitialCtx->r10; 77 m_aGprs[X86_GREG_x11] = pInitialCtx->r11; 78 m_aGprs[X86_GREG_x12] = pInitialCtx->r12; 79 m_aGprs[X86_GREG_x13] = pInitialCtx->r13; 80 m_aGprs[X86_GREG_x14] = pInitialCtx->r14; 81 m_aGprs[X86_GREG_x15] = pInitialCtx->r15; 82 m_uPc = pInitialCtx->rip; 83 } 84 else 85 { 86 RT_BZERO(m_aGprs, sizeof(m_aGprs)); 87 m_uPc = 0; 88 } 89 m_pUVM = pUVM; 90 m_idCpu = idCpu; 91 m_hAs = hAs; 92 93 m_hCached = NIL_RTDBGMOD; 94 m_uCachedMapping = 0; 95 m_cbCachedMapping = 0; 96 m_pbCachedInfo = NULL; 97 m_cbCachedInfo = 0; 98 } 99 100 ~DBGFUNWINDCTX(); 101 102 } DBGFUNWINDCTX; 103 /** Pointer to unwind context. */ 104 typedef DBGFUNWINDCTX *PDBGFUNWINDCTX; 105 106 107 static void dbgfR3UnwindCtxFlushCache(PDBGFUNWINDCTX pUnwindCtx) 108 { 109 if (pUnwindCtx->m_hCached != NIL_RTDBGMOD) 110 { 111 RTDbgModRelease(pUnwindCtx->m_hCached); 112 pUnwindCtx->m_hCached = NIL_RTDBGMOD; 113 } 114 if (pUnwindCtx->m_pbCachedInfo) 115 { 116 RTMemFree(pUnwindCtx->m_pbCachedInfo); 117 pUnwindCtx->m_pbCachedInfo = NULL; 118 } 119 pUnwindCtx->m_cbCachedInfo = 0; 120 } 121 122 123 DBGFUNWINDCTX::~DBGFUNWINDCTX() 124 { 125 dbgfR3UnwindCtxFlushCache(this); 126 } 127 128 129 static bool dbgfR3UnwindCtxSetPcAndSp(PDBGFUNWINDCTX pUnwindCtx, PCDBGFADDRESS pAddrPC, PCDBGFADDRESS pAddrStack) 130 { 131 pUnwindCtx->m_uPc = pAddrPC->FlatPtr; 132 pUnwindCtx->m_aGprs[X86_GREG_xSP] = pAddrStack->FlatPtr; 133 return true; 134 } 135 136 137 static bool dbgfR3UnwindCtxDoOneFrameCached(PDBGFUNWINDCTX pUnwindCtx, PDBGFADDRESS pAddrFrame) 138 { 139 if (!pUnwindCtx->m_cbCachedInfo) 140 return false; 141 142 //PCIMAGE_RUNTIME_FUNCTION_ENTRY; 143 //UNWIND_HISTORY_TABLE 144 145 RT_NOREF_PV(pAddrFrame); 146 return false; 147 } 148 149 150 static bool dbgfR3UnwindCtxDoOneFrame(PDBGFUNWINDCTX pUnwindCtx, PDBGFADDRESS pAddrFrame) 151 { 152 /* 153 * Hope for the same module as last time around. 154 */ 155 RTUINTPTR offCache = pUnwindCtx->m_uPc - pUnwindCtx->m_uCachedMapping; 156 if (offCache < pUnwindCtx->m_cbCachedMapping) 157 return dbgfR3UnwindCtxDoOneFrameCached(pUnwindCtx, pAddrFrame); 158 159 /* 160 * Try locate the module. 161 */ 162 RTDBGMOD hDbgMod = NIL_RTDBGMOD; 163 RTUINTPTR uBase = 0; 164 RTDBGSEGIDX idxSeg = NIL_RTDBGSEGIDX; 165 int rc = RTDbgAsModuleByAddr(pUnwindCtx->m_hAs, pUnwindCtx->m_uPc, &hDbgMod, &uBase, &idxSeg); 166 if (RT_SUCCESS(rc)) 167 { 168 /* We cache the module regardless of unwind info. */ 169 dbgfR3UnwindCtxFlushCache(pUnwindCtx); 170 pUnwindCtx->m_hCached = hDbgMod; 171 pUnwindCtx->m_uCachedMapping = uBase; 172 pUnwindCtx->m_cbCachedMapping = RTDbgModSegmentSize(hDbgMod, idxSeg); 173 174 /* Play simple for now. */ 175 if ( idxSeg == NIL_RTDBGSEGIDX 176 && RTDbgModImageGetFormat(hDbgMod) == RTLDRFMT_PE 177 && RTDbgModImageGetArch(hDbgMod) == RTLDRARCH_AMD64) 178 { 179 /* 180 * Try query the unwind data. 181 */ 182 size_t cbNeeded = 0; 183 rc = RTDbgModImageQueryProp(hDbgMod, RTLDRPROP_UNWIND_INFO, NULL, 0, &cbNeeded); 184 if ( rc == VERR_BUFFER_OVERFLOW 185 && cbNeeded > 12 186 && cbNeeded < _64M) 187 { 188 void *pvBuf = RTMemAllocZ(cbNeeded + 32); 189 if (pvBuf) 190 { 191 rc = RTDbgModImageQueryProp(hDbgMod, RTLDRPROP_UNWIND_INFO, pUnwindCtx->m_pbCachedInfo, cbNeeded, &cbNeeded); 192 if (RT_SUCCESS(rc)) 193 { 194 pUnwindCtx->m_pbCachedInfo = (uint8_t *)pvBuf; 195 pUnwindCtx->m_cbCachedInfo = cbNeeded; 196 return dbgfR3UnwindCtxDoOneFrameCached(pUnwindCtx, pAddrFrame); 197 } 198 RTMemFree(pvBuf); 199 } 200 } 201 } 202 } 203 return false; 204 } 205 206 207 208 /** 209 * Read stack memory, will init entire buffer. 210 */ 211 DECLINLINE(int) dbgfR3StackRead(PUVM pUVM, VMCPUID idCpu, void *pvBuf, PCDBGFADDRESS pSrcAddr, size_t cb, size_t *pcbRead) 42 212 { 43 213 int rc = DBGFR3MemRead(pUVM, idCpu, pSrcAddr, pvBuf, cb); … … 78 248 * unwind tables). 79 249 */ 80 static intdbgfR3StackWalk(PUVM pUVM, VMCPUID idCpu, RTDBGAS hAs, PDBGFSTACKFRAME pFrame)250 DECL_NO_INLINE(static, int) dbgfR3StackWalk(PUVM pUVM, VMCPUID idCpu, RTDBGAS hAs, PDBGFSTACKFRAME pFrame) 81 251 { 82 252 /* … … 138 308 139 309 Assert(DBGFADDRESS_IS_VALID(&pFrame->AddrFrame)); 140 int rc = dbgfR3 Read(pUVM, idCpu, u.pv,141 pFrame->fFlags & DBGFSTACKFRAME_FLAGS_ALL_VALID142 ? &pFrame->AddrReturnFrame143 : &pFrame->AddrFrame,144 cbRead, &cbRead);310 int rc = dbgfR3StackRead(pUVM, idCpu, u.pv, 311 pFrame->fFlags & DBGFSTACKFRAME_FLAGS_ALL_VALID 312 ? &pFrame->AddrReturnFrame 313 : &pFrame->AddrFrame, 314 cbRead, &cbRead); 145 315 if ( RT_FAILURE(rc) 146 316 || cbRead < cbRetAddr + cbStackItem) … … 321 491 * Walks the entire stack allocating memory as we walk. 322 492 */ 323 static DECLCALLBACK(int) dbgfR3StackWalkCtxFull(PUVM pUVM, VMCPUID idCpu, PCCPUMCTX CORE pCtxCore, RTDBGAS hAs,493 static DECLCALLBACK(int) dbgfR3StackWalkCtxFull(PUVM pUVM, VMCPUID idCpu, PCCPUMCTX pCtx, RTDBGAS hAs, 324 494 DBGFCODETYPE enmCodeType, 325 495 PCDBGFADDRESS pAddrFrame, … … 329 499 PCDBGFSTACKFRAME *ppFirstFrame) 330 500 { 501 DBGFUNWINDCTX UnwindCtx(pUVM, idCpu, pCtx, hAs); 502 331 503 /* alloc first frame. */ 332 504 PDBGFSTACKFRAME pCur = (PDBGFSTACKFRAME)MMR3HeapAllocZU(pUVM, MM_TAG_DBGF_STACK, sizeof(*pCur)); … … 344 516 pCur->AddrPC = *pAddrPC; 345 517 else if (enmCodeType != DBGFCODETYPE_GUEST) 346 DBGFR3AddrFromFlat(pUVM, &pCur->AddrPC, pCtx Core->rip);518 DBGFR3AddrFromFlat(pUVM, &pCur->AddrPC, pCtx->rip); 347 519 else 348 rc = DBGFR3AddrFromSelOff(pUVM, idCpu, &pCur->AddrPC, pCtx Core->cs.Sel, pCtxCore->rip);520 rc = DBGFR3AddrFromSelOff(pUVM, idCpu, &pCur->AddrPC, pCtx->cs.Sel, pCtx->rip); 349 521 if (RT_SUCCESS(rc)) 350 522 { 351 if (enmReturnType == DBGFRETURNTYPE_INVALID)352 switch (pCur->AddrPC.fFlags & DBGFADDRESS_FLAGS_TYPE_MASK)353 {354 case DBGFADDRESS_FLAGS_FAR16: pCur->enmReturnType = DBGFRETURNTYPE_NEAR16; break;355 case DBGFADDRESS_FLAGS_FAR32: pCur->enmReturnType = DBGFRETURNTYPE_NEAR32; break;356 case DBGFADDRESS_FLAGS_FAR64: pCur->enmReturnType = DBGFRETURNTYPE_NEAR64; break;357 case DBGFADDRESS_FLAGS_RING0:358 pCur->enmReturnType = HC_ARCH_BITS == 64 ? DBGFRETURNTYPE_NEAR64 : DBGFRETURNTYPE_NEAR32;359 break;360 default:361 pCur->enmReturnType = DBGFRETURNTYPE_NEAR32;362 break; /// @todo 64-bit guests363 }364 365 523 uint64_t fAddrMask; 366 524 if (enmCodeType == DBGFCODETYPE_RING0) … … 377 535 { 378 536 PVMCPU pVCpu = VMMGetCpuById(pUVM->pVM, idCpu); 379 CPUMMODE CpuMode = CPUMGetGuestMode(pVCpu); 380 if (CpuMode == CPUMMODE_REAL) 537 CPUMMODE enmCpuMode = CPUMGetGuestMode(pVCpu); 538 if (enmCpuMode == CPUMMODE_REAL) 539 { 381 540 fAddrMask = UINT16_MAX; 382 else if ( CpuMode == CPUMMODE_PROTECTED 541 if (enmReturnType == DBGFRETURNTYPE_INVALID) 542 pCur->enmReturnType = DBGFRETURNTYPE_NEAR16; 543 } 544 else if ( enmCpuMode == CPUMMODE_PROTECTED 383 545 || !CPUMIsGuestIn64BitCode(pVCpu)) 546 { 384 547 fAddrMask = UINT32_MAX; 548 if (enmReturnType == DBGFRETURNTYPE_INVALID) 549 pCur->enmReturnType = DBGFRETURNTYPE_NEAR32; 550 } 385 551 else 552 { 386 553 fAddrMask = UINT64_MAX; 387 } 554 if (enmReturnType == DBGFRETURNTYPE_INVALID) 555 pCur->enmReturnType = DBGFRETURNTYPE_NEAR64; 556 } 557 } 558 559 if (enmReturnType == DBGFRETURNTYPE_INVALID) 560 switch (pCur->AddrPC.fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) 561 { 562 case DBGFADDRESS_FLAGS_FAR16: pCur->enmReturnType = DBGFRETURNTYPE_NEAR16; break; 563 case DBGFADDRESS_FLAGS_FAR32: pCur->enmReturnType = DBGFRETURNTYPE_NEAR32; break; 564 case DBGFADDRESS_FLAGS_FAR64: pCur->enmReturnType = DBGFRETURNTYPE_NEAR64; break; 565 case DBGFADDRESS_FLAGS_RING0: 566 pCur->enmReturnType = HC_ARCH_BITS == 64 ? DBGFRETURNTYPE_NEAR64 : DBGFRETURNTYPE_NEAR32; 567 break; 568 default: 569 pCur->enmReturnType = DBGFRETURNTYPE_NEAR32; 570 break; 571 } 572 388 573 389 574 if (pAddrStack) 390 575 pCur->AddrStack = *pAddrStack; 391 576 else if (enmCodeType != DBGFCODETYPE_GUEST) 392 DBGFR3AddrFromFlat(pUVM, &pCur->AddrStack, pCtx Core->rsp & fAddrMask);577 DBGFR3AddrFromFlat(pUVM, &pCur->AddrStack, pCtx->rsp & fAddrMask); 393 578 else 394 rc = DBGFR3AddrFromSelOff(pUVM, idCpu, &pCur->AddrStack, pCtx Core->ss.Sel, pCtxCore->rsp & fAddrMask);579 rc = DBGFR3AddrFromSelOff(pUVM, idCpu, &pCur->AddrStack, pCtx->ss.Sel, pCtx->rsp & fAddrMask); 395 580 396 581 if (pAddrFrame) 397 582 pCur->AddrFrame = *pAddrFrame; 398 else if (enmCodeType != DBGFCODETYPE_GUEST) 399 DBGFR3AddrFromFlat(pUVM, &pCur->AddrFrame, pCtxCore->rbp & fAddrMask); 400 else if (RT_SUCCESS(rc)) 401 rc = DBGFR3AddrFromSelOff(pUVM, idCpu, &pCur->AddrFrame, pCtxCore->ss.Sel, pCtxCore->rbp & fAddrMask); 583 else 584 { 585 if ( RT_SUCCESS(rc) 586 && dbgfR3UnwindCtxSetPcAndSp(&UnwindCtx, &pCur->AddrPC, &pCur->AddrStack) 587 && dbgfR3UnwindCtxDoOneFrame(&UnwindCtx, &pCur->AddrFrame)) 588 { } 589 else if (enmCodeType != DBGFCODETYPE_GUEST) 590 DBGFR3AddrFromFlat(pUVM, &pCur->AddrFrame, pCtx->rbp & fAddrMask); 591 else if (RT_SUCCESS(rc)) 592 rc = DBGFR3AddrFromSelOff(pUVM, idCpu, &pCur->AddrFrame, pCtx->ss.Sel, pCtx->rbp & fAddrMask); 593 } 402 594 } 403 595 else … … 490 682 * Get the CPUM context pointer and pass it on the specified EMT. 491 683 */ 492 RTDBGAS 493 PCCPUMCTX CORE pCtxCore;684 RTDBGAS hAs; 685 PCCPUMCTX pCtx; 494 686 switch (enmCodeType) 495 687 { 496 688 case DBGFCODETYPE_GUEST: 497 pCtx Core = CPUMGetGuestCtxCore(VMMGetCpuById(pVM, idCpu));498 hAs = DBGF_AS_GLOBAL;689 pCtx = CPUMQueryGuestCtxPtr(VMMGetCpuById(pVM, idCpu)); 690 hAs = DBGF_AS_GLOBAL; 499 691 break; 500 692 case DBGFCODETYPE_HYPER: 501 pCtx Core = CPUMGetHyperCtxCore(VMMGetCpuById(pVM, idCpu));502 hAs = DBGF_AS_RC_AND_GC_GLOBAL;693 pCtx = CPUMQueryGuestCtxPtr(VMMGetCpuById(pVM, idCpu)); 694 hAs = DBGF_AS_RC_AND_GC_GLOBAL; 503 695 break; 504 696 case DBGFCODETYPE_RING0: 505 pCtx Core= NULL; /* No valid context present. */506 hAs = DBGF_AS_R0;697 pCtx = NULL; /* No valid context present. */ 698 hAs = DBGF_AS_R0; 507 699 break; 508 700 default: … … 510 702 } 511 703 return VMR3ReqPriorityCallWaitU(pUVM, idCpu, (PFNRT)dbgfR3StackWalkCtxFull, 10, 512 pUVM, idCpu, pCtx Core, hAs, enmCodeType,704 pUVM, idCpu, pCtx, hAs, enmCodeType, 513 705 pAddrFrame, pAddrStack, pAddrPC, enmReturnType, ppFirstFrame); 514 706 }
Note:
See TracChangeset
for help on using the changeset viewer.