VirtualBox

Changeset 73495 in vbox for trunk/src


Ignore:
Timestamp:
Aug 4, 2018 7:42:07 PM (6 years ago)
Author:
vboxsync
Message:

DBGF: Use the new IPRT unwind functionality. bugref:3897

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/DBGFStack.cpp

    r73490 r73495  
    4646 *
    4747 * @note Using a constructor and destructor here for simple+safe cleanup.
    48  *
    49  * @todo Generalize and move to IPRT or some such place.
    5048 */
    5149typedef struct DBGFUNWINDCTX
     
    5856    uint64_t    m_uOsScratch; /**< For passing to DBGFOSREG::pfnStackUnwindAssist. */
    5957
    60     RTDBGUNWINDSTATE m_State;
    61 
    6258    RTDBGMOD    m_hCached;
    6359    RTUINTPTR   m_uCachedMapping;
    6460    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;
    7264
    7365    DBGFUNWINDCTX(PUVM pUVM, VMCPUID idCpu, PCCPUMCTX pInitialCtx, RTDBGAS hAs)
     
    119111        m_uCachedMapping  = 0;
    120112        m_cbCachedMapping = 0;
    121         m_pbCachedInfo    = NULL;
    122         m_cbCachedInfo    = 0;
    123         m_paFunctions     = NULL;
    124         m_cFunctions      = 0;
     113        m_idxCachedSegMapping = NIL_RTDBGSEGIDX;
    125114    }
    126115
     
    139128        pUnwindCtx->m_hCached = NIL_RTDBGMOD;
    140129    }
    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;
    149132}
    150133
     
    189172    if (RT_SUCCESS(rc))
    190173        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. */
    192177}
    193178
     
    225210
    226211/**
    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         else
    275             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     else
    294     {
    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             union
    366             {
    367                 uint32_t uRva;
    368                 uint8_t  ab[  RT_OFFSETOF(IMAGE_UNWIND_INFO, aOpcodes)
    369                             + sizeof(IMAGE_UNWIND_CODE) * 256
    370                             + 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 >= 2
    398                 && iOpcode < cOpcodes
    399                 && 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                     else
    415                     {
    416                         fInEpilog = 0;
    417                         while (iOpcode < cOpcodes && pInfo->aOpcodes[iOpcode].u.UnwindOp == IMAGE_AMD64_UWOP_EPILOG)
    418                         {
    419                             uRvaEpilog = pEntry->EndAddress
    420                                        - (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                             else
    474                             {
    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             else
    540             {
    541                 /*
    542                  * We're in the POP sequence of an epilog.  The POP sequence should
    543                  * mirror the PUSH sequence exactly.
    544                  *
    545                  * Note! We should only end up here for the initial frame (just consider
    546                  *       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                             else
    562                             {
    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 /**
    625212 * Tries to unwind one frame using unwind info.
    626213 *
     
    631218{
    632219    /*
    633      * Hope for the same module as last time around.
     220     * Need to load it into the cache?
    634221     */
    635222    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);
    647248    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;
    690250    return false;
    691251}
Note: See TracChangeset for help on using the changeset viewer.

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