- Timestamp:
- Aug 4, 2018 7:42:07 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/DBGFStack.cpp
r73490 r73495 46 46 * 47 47 * @note Using a constructor and destructor here for simple+safe cleanup. 48 *49 * @todo Generalize and move to IPRT or some such place.50 48 */ 51 49 typedef struct DBGFUNWINDCTX … … 58 56 uint64_t m_uOsScratch; /**< For passing to DBGFOSREG::pfnStackUnwindAssist. */ 59 57 60 RTDBGUNWINDSTATE m_State;61 62 58 RTDBGMOD m_hCached; 63 59 RTUINTPTR m_uCachedMapping; 64 60 RTUINTPTR m_cbCachedMapping; 65 uint8_t *m_pbCachedInfo; 66 size_t m_cbCachedInfo; 67 68 /** Function table for PE/AMD64 (entire m_pbCachedInfo) . */ 69 PCIMAGE_RUNTIME_FUNCTION_ENTRY m_paFunctions; 70 /** Number functions in m_paFunctions. */ 71 size_t m_cFunctions; 61 RTDBGSEGIDX m_idxCachedSegMapping; 62 63 RTDBGUNWINDSTATE m_State; 72 64 73 65 DBGFUNWINDCTX(PUVM pUVM, VMCPUID idCpu, PCCPUMCTX pInitialCtx, RTDBGAS hAs) … … 119 111 m_uCachedMapping = 0; 120 112 m_cbCachedMapping = 0; 121 m_pbCachedInfo = NULL; 122 m_cbCachedInfo = 0; 123 m_paFunctions = NULL; 124 m_cFunctions = 0; 113 m_idxCachedSegMapping = NIL_RTDBGSEGIDX; 125 114 } 126 115 … … 139 128 pUnwindCtx->m_hCached = NIL_RTDBGMOD; 140 129 } 141 if (pUnwindCtx->m_pbCachedInfo) 142 { 143 RTMemFree(pUnwindCtx->m_pbCachedInfo); 144 pUnwindCtx->m_pbCachedInfo = NULL; 145 } 146 pUnwindCtx->m_cbCachedInfo = 0; 147 pUnwindCtx->m_paFunctions = NULL; 148 pUnwindCtx->m_cFunctions = 0; 130 pUnwindCtx->m_cbCachedMapping = 0; 131 pUnwindCtx->m_idxCachedSegMapping = NIL_RTDBGSEGIDX; 149 132 } 150 133 … … 189 172 if (RT_SUCCESS(rc)) 190 173 rc = DBGFR3MemRead(pUnwindCtx->m_pUVM, pUnwindCtx->m_idCpu, &SrcAddr, pvDst, cbToRead); 191 return rc; 174 if (RT_SUCCESS(rc)) 175 return rc; 176 return -rc; /* Ignore read errors. */ 192 177 } 193 178 … … 225 210 226 211 /** 227 * Try read a 16-bit value off the stack.228 *229 * @returns pfnReadStack result.230 * @param pThis The unwind state.231 * @param uSrcAddr The stack address.232 * @param puDst The read destination.233 */234 DECLINLINE(int) dbgUnwindLoadStackU16(PRTDBGUNWINDSTATE pThis, uint64_t uSrcAddr, uint16_t *puDst)235 {236 return pThis->pfnReadStack(pThis, uSrcAddr, sizeof(*puDst), puDst);237 }238 239 240 /**241 * Try read a 64-bit value off the stack.242 *243 * @returns pfnReadStack result.244 * @param pThis The unwind state.245 * @param uSrcAddr The stack address.246 * @param puDst The read destination.247 */248 DECLINLINE(int) dbgUnwindLoadStackU64(PRTDBGUNWINDSTATE pThis, uint64_t uSrcAddr, uint64_t *puDst)249 {250 return pThis->pfnReadStack(pThis, uSrcAddr, sizeof(*puDst), puDst);251 }252 253 254 /**255 * Binary searches the lookup table.256 *257 * @returns RVA of unwind info on success, UINT32_MAX on failure.258 * @param paFunctions The table to lookup @a uRva in.259 * @param iEnd Size of the table.260 * @param uRva The RVA of the function we want.261 */262 DECLINLINE(PCIMAGE_RUNTIME_FUNCTION_ENTRY)263 dbgfR3UnwindCtxLookupUnwindInfoRva(PCIMAGE_RUNTIME_FUNCTION_ENTRY paFunctions, size_t iEnd, uint32_t uRva)264 {265 size_t iBegin = 0;266 while (iBegin < iEnd)267 {268 size_t const i = iBegin + (iEnd - iBegin) / 2;269 PCIMAGE_RUNTIME_FUNCTION_ENTRY pEntry = &paFunctions[i];270 if (uRva < pEntry->BeginAddress)271 iEnd = i;272 else if (uRva > pEntry->EndAddress)273 iBegin = i + 1;274 else275 return pEntry;276 }277 return NULL;278 }279 280 281 /**282 * Processes an IRET frame.283 *284 * @returns true.285 * @param pThis The unwind state being worked.286 * @param fErrCd Non-zero if there is an error code on the stack.287 */288 static bool dbgUnwindPeAmd64DoOneIRet(PRTDBGUNWINDSTATE pThis, uint8_t fErrCd)289 {290 Assert(fErrCd <= 1);291 if (!fErrCd)292 pThis->u.x86.Loaded.s.fErrCd = 0;293 else294 {295 pThis->u.x86.uErrCd = 0;296 pThis->u.x86.Loaded.s.fErrCd = 1;297 dbgUnwindLoadStackU64(pThis, pThis->u.x86.auRegs[X86_GREG_xSP], &pThis->u.x86.uErrCd);298 pThis->u.x86.auRegs[X86_GREG_xSP] += 8;299 }300 301 pThis->enmRetType = RTDBGRETURNTYPE_IRET64;302 pThis->u.x86.FrameAddr.off = pThis->u.x86.auRegs[X86_GREG_xSP] - /* pretend rbp is pushed on the stack */ 8;303 pThis->u.x86.FrameAddr.sel = pThis->u.x86.auSegs[X86_SREG_SS];304 305 dbgUnwindLoadStackU64(pThis, pThis->u.x86.auRegs[X86_GREG_xSP], &pThis->uPc);306 pThis->u.x86.auRegs[X86_GREG_xSP] += 8; /* RIP */307 308 dbgUnwindLoadStackU16(pThis, pThis->u.x86.auRegs[X86_GREG_xSP], &pThis->u.x86.auSegs[X86_SREG_CS]);309 pThis->u.x86.auRegs[X86_GREG_xSP] += 8; /* CS */310 311 dbgUnwindLoadStackU64(pThis, pThis->u.x86.auRegs[X86_GREG_xSP], &pThis->u.x86.uRFlags);312 pThis->u.x86.auRegs[X86_GREG_xSP] += 8; /* EFLAGS */313 314 uint64_t uNewRsp = (pThis->u.x86.auRegs[X86_GREG_xSP] - 8) & ~(uint64_t)15;315 dbgUnwindLoadStackU64(pThis, pThis->u.x86.auRegs[X86_GREG_xSP], &uNewRsp);316 pThis->u.x86.auRegs[X86_GREG_xSP] += 8; /* RSP */317 318 dbgUnwindLoadStackU16(pThis, pThis->u.x86.auRegs[X86_GREG_xSP], &pThis->u.x86.auSegs[X86_SREG_SS]);319 pThis->u.x86.auRegs[X86_GREG_xSP] += 8; /* SS */320 321 pThis->u.x86.auRegs[X86_GREG_xSP] = uNewRsp;322 323 pThis->u.x86.Loaded.s.fRegs |= RT_BIT(X86_GREG_xSP);324 pThis->u.x86.Loaded.s.fSegs |= RT_BIT(X86_SREG_CS) | RT_BIT(X86_SREG_SS);325 pThis->u.x86.Loaded.s.fPc = 1;326 pThis->u.x86.Loaded.s.fFrameAddr = 1;327 pThis->u.x86.Loaded.s.fRFlags = 1;328 return true;329 }330 331 332 /**333 * Unwinds one frame using cached module info.334 *335 * @returns true on success, false on failure.336 * @param hMod The debug module to retrieve unwind info from.337 * @param paFunctions The table to lookup @a uRvaRip in.338 * @param cFunctions Size of the lookup table.339 * @param pThis The unwind state.340 * @param uRvaRip The RVA of the RIP.341 *342 * @todo Move this down to IPRT in the ldrPE.cpp / dbgmodcodeview.cpp area.343 */344 static bool dbgUnwindPeAmd64DoOne(RTDBGMOD hMod, PCIMAGE_RUNTIME_FUNCTION_ENTRY paFunctions, size_t cFunctions,345 PRTDBGUNWINDSTATE pThis, uint32_t uRvaRip)346 {347 /*348 * Lookup the unwind info RVA and try read it.349 */350 PCIMAGE_RUNTIME_FUNCTION_ENTRY pEntry = dbgfR3UnwindCtxLookupUnwindInfoRva(paFunctions, cFunctions, uRvaRip);351 if (pEntry)352 {353 IMAGE_RUNTIME_FUNCTION_ENTRY ChainedEntry;354 unsigned iFrameReg = ~0U;355 unsigned offFrameReg = 0;356 357 int fInEpilog = -1; /* -1: not-determined-assume-false; 0: false; 1: true. */358 uint8_t cbEpilog = 0;359 uint8_t offEpilog = UINT8_MAX;360 for (unsigned cChainLoops = 0; ; cChainLoops++)361 {362 /*363 * Get the info.364 */365 union366 {367 uint32_t uRva;368 uint8_t ab[ RT_OFFSETOF(IMAGE_UNWIND_INFO, aOpcodes)369 + sizeof(IMAGE_UNWIND_CODE) * 256370 + sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY)];371 } uBuf;372 373 uBuf.uRva = pEntry->UnwindInfoAddress;374 size_t cbBuf = sizeof(uBuf);375 int rc = RTDbgModImageQueryProp(hMod, RTLDRPROP_UNWIND_INFO, &uBuf, cbBuf, &cbBuf);376 if (RT_FAILURE(rc))377 return false;378 379 /*380 * Check the info.381 */382 ASMCompilerBarrier(); /* we're aliasing */383 PCIMAGE_UNWIND_INFO pInfo = (PCIMAGE_UNWIND_INFO)&uBuf;384 385 if (pInfo->Version != 1 && pInfo->Version != 2)386 return false;387 388 /*389 * Execute the opcodes.390 */391 unsigned const cOpcodes = pInfo->CountOfCodes;392 unsigned iOpcode = 0;393 394 /*395 * Check for epilog opcodes at the start and see if we're in an epilog.396 */397 if ( pInfo->Version >= 2398 && iOpcode < cOpcodes399 && pInfo->aOpcodes[iOpcode].u.UnwindOp == IMAGE_AMD64_UWOP_EPILOG)400 {401 if (fInEpilog == -1)402 {403 cbEpilog = pInfo->aOpcodes[iOpcode].u.CodeOffset;404 Assert(cbEpilog > 0);405 406 uint32_t uRvaEpilog = pEntry->EndAddress - cbEpilog;407 iOpcode++;408 if ( (pInfo->aOpcodes[iOpcode - 1].u.OpInfo & 1)409 && uRvaRip >= uRvaEpilog)410 {411 offEpilog = uRvaRip - uRvaEpilog;412 fInEpilog = 1;413 }414 else415 {416 fInEpilog = 0;417 while (iOpcode < cOpcodes && pInfo->aOpcodes[iOpcode].u.UnwindOp == IMAGE_AMD64_UWOP_EPILOG)418 {419 uRvaEpilog = pEntry->EndAddress420 - (pInfo->aOpcodes[iOpcode].u.CodeOffset + (pInfo->aOpcodes[iOpcode].u.OpInfo << 8));421 iOpcode++;422 if (uRvaRip - uRvaEpilog < cbEpilog)423 {424 offEpilog = uRvaRip - uRvaEpilog;425 fInEpilog = 1;426 break;427 }428 }429 }430 }431 while (iOpcode < cOpcodes && pInfo->aOpcodes[iOpcode].u.UnwindOp == IMAGE_AMD64_UWOP_EPILOG)432 iOpcode++;433 }434 if (fInEpilog != 1)435 {436 /*437 * Skip opcodes that doesn't apply to us if we're in the prolog.438 */439 uint32_t offPc = uRvaRip - pEntry->BeginAddress;440 if (offPc < pInfo->SizeOfProlog)441 while (iOpcode < cOpcodes && pInfo->aOpcodes[iOpcode].u.CodeOffset > offPc)442 iOpcode++;443 444 /*445 * Execute the opcodes.446 */447 if (pInfo->FrameRegister != 0)448 {449 iFrameReg = pInfo->FrameRegister;450 offFrameReg = pInfo->FrameOffset * 16;451 }452 while (iOpcode < cOpcodes)453 {454 Assert(pInfo->aOpcodes[iOpcode].u.CodeOffset <= offPc);455 uint8_t const uOpInfo = pInfo->aOpcodes[iOpcode].u.OpInfo;456 uint8_t const uUnwindOp = pInfo->aOpcodes[iOpcode].u.UnwindOp;457 switch (uUnwindOp)458 {459 case IMAGE_AMD64_UWOP_PUSH_NONVOL:460 dbgUnwindLoadStackU64(pThis, pThis->u.x86.auRegs[X86_GREG_xSP], &pThis->u.x86.auRegs[uOpInfo]);461 pThis->u.x86.Loaded.s.fRegs |= RT_BIT(uOpInfo);462 pThis->u.x86.auRegs[X86_GREG_xSP] += 8;463 iOpcode++;464 break;465 466 case IMAGE_AMD64_UWOP_ALLOC_LARGE:467 if (uOpInfo == 0)468 {469 iOpcode += 2;470 AssertBreak(iOpcode <= cOpcodes);471 pThis->u.x86.auRegs[X86_GREG_xSP] += pInfo->aOpcodes[iOpcode - 1].FrameOffset * 8;472 }473 else474 {475 iOpcode += 3;476 AssertBreak(iOpcode <= cOpcodes);477 pThis->u.x86.auRegs[X86_GREG_xSP] += RT_MAKE_U32(pInfo->aOpcodes[iOpcode - 2].FrameOffset,478 pInfo->aOpcodes[iOpcode - 1].FrameOffset);479 }480 break;481 482 case IMAGE_AMD64_UWOP_ALLOC_SMALL:483 AssertBreak(iOpcode <= cOpcodes);484 pThis->u.x86.auRegs[X86_GREG_xSP] += uOpInfo * 8 + 8;485 iOpcode++;486 break;487 488 case IMAGE_AMD64_UWOP_SET_FPREG:489 iFrameReg = uOpInfo;490 offFrameReg = pInfo->FrameOffset * 16;491 pThis->u.x86.auRegs[X86_GREG_xSP] = pThis->u.x86.auRegs[iFrameReg] - offFrameReg;492 iOpcode++;493 break;494 495 case IMAGE_AMD64_UWOP_SAVE_NONVOL:496 case IMAGE_AMD64_UWOP_SAVE_NONVOL_FAR:497 {498 uint32_t off = 0;499 iOpcode++;500 if (iOpcode < cOpcodes)501 {502 off = pInfo->aOpcodes[iOpcode].FrameOffset;503 iOpcode++;504 if (uUnwindOp == IMAGE_AMD64_UWOP_SAVE_NONVOL_FAR && iOpcode < cOpcodes)505 {506 off |= (uint32_t)pInfo->aOpcodes[iOpcode].FrameOffset << 16;507 iOpcode++;508 }509 }510 off *= 8;511 dbgUnwindLoadStackU64(pThis, pThis->u.x86.auRegs[X86_GREG_xSP] + off, &pThis->u.x86.auRegs[uOpInfo]);512 pThis->u.x86.Loaded.s.fRegs |= RT_BIT(uOpInfo);513 break;514 }515 516 case IMAGE_AMD64_UWOP_SAVE_XMM128:517 iOpcode += 2;518 break;519 520 case IMAGE_AMD64_UWOP_SAVE_XMM128_FAR:521 iOpcode += 3;522 break;523 524 case IMAGE_AMD64_UWOP_PUSH_MACHFRAME:525 return dbgUnwindPeAmd64DoOneIRet(pThis, uOpInfo);526 527 case IMAGE_AMD64_UWOP_EPILOG:528 iOpcode += 1;529 break;530 531 case IMAGE_AMD64_UWOP_RESERVED_7:532 AssertFailedReturn(false);533 534 default:535 AssertMsgFailedReturn(("%u\n", uUnwindOp), false);536 }537 }538 }539 else540 {541 /*542 * We're in the POP sequence of an epilog. The POP sequence should543 * mirror the PUSH sequence exactly.544 *545 * Note! We should only end up here for the initial frame (just consider546 * RSP, stack allocations, non-volatile register restores, ++).547 */548 while (iOpcode < cOpcodes)549 {550 uint8_t const uOpInfo = pInfo->aOpcodes[iOpcode].u.OpInfo;551 uint8_t const uUnwindOp = pInfo->aOpcodes[iOpcode].u.UnwindOp;552 switch (uUnwindOp)553 {554 case IMAGE_AMD64_UWOP_PUSH_NONVOL:555 pThis->u.x86.auRegs[X86_GREG_xSP] += 8;556 if (offEpilog == 0)557 {558 dbgUnwindLoadStackU64(pThis, pThis->u.x86.auRegs[X86_GREG_xSP], &pThis->u.x86.auRegs[uOpInfo]);559 pThis->u.x86.Loaded.s.fRegs |= RT_BIT(uOpInfo);560 }561 else562 {563 /* Decrement offEpilog by estimated POP instruction length. */564 offEpilog -= 1;565 if (offEpilog > 0 && uOpInfo >= 8)566 offEpilog -= 1;567 }568 iOpcode++;569 break;570 571 case IMAGE_AMD64_UWOP_PUSH_MACHFRAME: /* Must terminate an epilog, so always execute this. */572 return dbgUnwindPeAmd64DoOneIRet(pThis, uOpInfo);573 574 case IMAGE_AMD64_UWOP_ALLOC_SMALL:575 case IMAGE_AMD64_UWOP_SET_FPREG:576 case IMAGE_AMD64_UWOP_EPILOG:577 iOpcode++;578 break;579 case IMAGE_AMD64_UWOP_SAVE_NONVOL:580 case IMAGE_AMD64_UWOP_SAVE_XMM128:581 iOpcode += 2;582 break;583 case IMAGE_AMD64_UWOP_ALLOC_LARGE:584 case IMAGE_AMD64_UWOP_SAVE_NONVOL_FAR:585 case IMAGE_AMD64_UWOP_SAVE_XMM128_FAR:586 iOpcode += 3;587 break;588 589 default:590 AssertMsgFailedReturn(("%u\n", uUnwindOp), false);591 }592 }593 }594 595 /*596 * Chained stuff?597 */598 if (!(pInfo->Flags & IMAGE_UNW_FLAGS_CHAININFO))599 break;600 ChainedEntry = *(PCIMAGE_RUNTIME_FUNCTION_ENTRY)&pInfo->aOpcodes[(cOpcodes + 1) & ~1];601 pEntry = &ChainedEntry;602 AssertReturn(cChainLoops < 32, false);603 }604 605 /*606 * RSP should now give us the return address, so perform a RET.607 */608 pThis->enmRetType = RTDBGRETURNTYPE_NEAR64;609 610 pThis->u.x86.FrameAddr.off = pThis->u.x86.auRegs[X86_GREG_xSP] - /* pretend rbp is pushed on the stack */ 8;611 pThis->u.x86.FrameAddr.sel = pThis->u.x86.auSegs[X86_SREG_SS];612 pThis->u.x86.Loaded.s.fFrameAddr = 1;613 614 dbgUnwindLoadStackU64(pThis, pThis->u.x86.auRegs[X86_GREG_xSP], &pThis->uPc);615 pThis->u.x86.auRegs[X86_GREG_xSP] += 8;616 pThis->u.x86.Loaded.s.fPc = 1;617 return true;618 }619 620 return false;621 }622 623 624 /**625 212 * Tries to unwind one frame using unwind info. 626 213 * … … 631 218 { 632 219 /* 633 * Hope for the same module as last time around.220 * Need to load it into the cache? 634 221 */ 635 222 RTUINTPTR offCache = pUnwindCtx->m_State.uPc - pUnwindCtx->m_uCachedMapping; 636 if (offCache < pUnwindCtx->m_cbCachedMapping) 637 return dbgUnwindPeAmd64DoOne(pUnwindCtx->m_hCached, pUnwindCtx->m_paFunctions, pUnwindCtx->m_cFunctions, 638 &pUnwindCtx->m_State, offCache); 639 640 /* 641 * Try locate the module. 642 */ 643 RTDBGMOD hDbgMod = NIL_RTDBGMOD; 644 RTUINTPTR uBase = 0; 645 RTDBGSEGIDX idxSeg = NIL_RTDBGSEGIDX; 646 int rc = RTDbgAsModuleByAddr(pUnwindCtx->m_hAs, pUnwindCtx->m_State.uPc, &hDbgMod, &uBase, &idxSeg); 223 if (offCache >= pUnwindCtx->m_cbCachedMapping) 224 { 225 RTDBGMOD hDbgMod = NIL_RTDBGMOD; 226 RTUINTPTR uBase = 0; 227 RTDBGSEGIDX idxSeg = NIL_RTDBGSEGIDX; 228 int rc = RTDbgAsModuleByAddr(pUnwindCtx->m_hAs, pUnwindCtx->m_State.uPc, &hDbgMod, &uBase, &idxSeg); 229 if (RT_SUCCESS(rc)) 230 { 231 dbgfR3UnwindCtxFlushCache(pUnwindCtx); 232 pUnwindCtx->m_hCached = hDbgMod; 233 pUnwindCtx->m_uCachedMapping = uBase; 234 pUnwindCtx->m_idxCachedSegMapping = idxSeg; 235 pUnwindCtx->m_cbCachedMapping = idxSeg == NIL_RTDBGSEGIDX ? RTDbgModImageSize(hDbgMod) 236 : RTDbgModSegmentSize(hDbgMod, idxSeg); 237 offCache = pUnwindCtx->m_State.uPc - uBase; 238 } 239 else 240 return false; 241 } 242 243 /* 244 * Do the lookup. 245 */ 246 AssertCompile(UINT32_MAX == NIL_RTDBGSEGIDX); 247 int rc = RTDbgModUnwindFrame(pUnwindCtx->m_hCached, pUnwindCtx->m_idxCachedSegMapping, offCache, &pUnwindCtx->m_State); 647 248 if (RT_SUCCESS(rc)) 648 { 649 /* We cache the module regardless of unwind info. */ 650 dbgfR3UnwindCtxFlushCache(pUnwindCtx); 651 pUnwindCtx->m_hCached = hDbgMod; 652 pUnwindCtx->m_uCachedMapping = uBase; 653 pUnwindCtx->m_cbCachedMapping = idxSeg == NIL_RTDBGSEGIDX ? RTDbgModImageSize(hDbgMod) 654 : RTDbgModSegmentSize(hDbgMod, idxSeg); 655 656 /* Play simple for now. */ 657 if ( idxSeg == NIL_RTDBGSEGIDX 658 && RTDbgModImageGetFormat(hDbgMod) == RTLDRFMT_PE 659 && RTDbgModImageGetArch(hDbgMod) == RTLDRARCH_AMD64) 660 { 661 /* 662 * Try query the unwind data. 663 */ 664 uint32_t uDummy; 665 size_t cbNeeded = 0; 666 rc = RTDbgModImageQueryProp(hDbgMod, RTLDRPROP_UNWIND_TABLE, &uDummy, 0, &cbNeeded); 667 if ( rc == VERR_BUFFER_OVERFLOW 668 && cbNeeded >= sizeof(*pUnwindCtx->m_paFunctions) 669 && cbNeeded < _64M) 670 { 671 void *pvBuf = RTMemAllocZ(cbNeeded + 32); 672 if (pvBuf) 673 { 674 rc = RTDbgModImageQueryProp(hDbgMod, RTLDRPROP_UNWIND_TABLE, pvBuf, cbNeeded + 32, &cbNeeded); 675 if (RT_SUCCESS(rc)) 676 { 677 pUnwindCtx->m_pbCachedInfo = (uint8_t *)pvBuf; 678 pUnwindCtx->m_cbCachedInfo = cbNeeded; 679 pUnwindCtx->m_paFunctions = (PCIMAGE_RUNTIME_FUNCTION_ENTRY)pvBuf; 680 pUnwindCtx->m_cFunctions = cbNeeded / sizeof(*pUnwindCtx->m_paFunctions); 681 682 return dbgUnwindPeAmd64DoOne(pUnwindCtx->m_hCached, pUnwindCtx->m_paFunctions, pUnwindCtx->m_cFunctions, 683 &pUnwindCtx->m_State, pUnwindCtx->m_State.uPc - pUnwindCtx->m_uCachedMapping); 684 } 685 RTMemFree(pvBuf); 686 } 687 } 688 } 689 } 249 return true; 690 250 return false; 691 251 }
Note:
See TracChangeset
for help on using the changeset viewer.