VirtualBox

Changeset 73494 in vbox


Ignore:
Timestamp:
Aug 4, 2018 7:41:30 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
124121
Message:

IPRT: Added single stack frame unwind function to RTDbgMod and RTLdr, copying over the PoC from DBGFRStack.cpp. bugref:3897

Location:
trunk
Files:
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/dbg.h

    r73482 r73494  
    3434RT_C_DECLS_BEGIN
    3535
    36 # ifdef IN_RING3
    3736
    3837/** @defgroup grp_rt_dbg    RTDbg - Debugging Routines
     
    275274} RTDBGUNWINDSTATE;
    276275
     276/**
     277 * Try read a 16-bit value off the stack.
     278 *
     279 * @returns pfnReadStack result.
     280 * @param   pThis           The unwind state.
     281 * @param   uSrcAddr        The stack address.
     282 * @param   puDst           The read destination.
     283 */
     284DECLINLINE(int) RTDbgUnwindLoadStackU16(PRTDBGUNWINDSTATE pThis, RTUINTPTR uSrcAddr, uint16_t *puDst)
     285{
     286    return pThis->pfnReadStack(pThis, uSrcAddr, sizeof(*puDst), puDst);
     287}
     288
     289/**
     290 * Try read a 32-bit value off the stack.
     291 *
     292 * @returns pfnReadStack result.
     293 * @param   pThis           The unwind state.
     294 * @param   uSrcAddr        The stack address.
     295 * @param   puDst           The read destination.
     296 */
     297DECLINLINE(int) RTDbgUnwindLoadStackU32(PRTDBGUNWINDSTATE pThis, RTUINTPTR uSrcAddr, uint32_t *puDst)
     298{
     299    return pThis->pfnReadStack(pThis, uSrcAddr, sizeof(*puDst), puDst);
     300}
     301
     302/**
     303 * Try read a 64-bit value off the stack.
     304 *
     305 * @returns pfnReadStack result.
     306 * @param   pThis           The unwind state.
     307 * @param   uSrcAddr        The stack address.
     308 * @param   puDst           The read destination.
     309 */
     310DECLINLINE(int) RTDbgUnwindLoadStackU64(PRTDBGUNWINDSTATE pThis, RTUINTPTR uSrcAddr, uint64_t *puDst)
     311{
     312    return pThis->pfnReadStack(pThis, uSrcAddr, sizeof(*puDst), puDst);
     313}
     314
    277315
    278316
     
    308346typedef const RTDBGSYMBOL *PCRTDBGSYMBOL;
    309347
     348
    310349/**
    311350 * Allocate a new symbol structure.
     
    385424RTDECL(void)            RTDbgLineFree(PRTDBGLINE pLine);
    386425
     426
     427# ifdef IN_RING3
    387428
    388429/** @defgroup grp_rt_dbgcfg     RTDbgCfg - Debugging Configuration
     
    659700/** @} */
    660701
     702# endif /* IN_RING3 */
    661703
    662704/** @} */
     
    11051147
    11061148
     1149# ifdef IN_RING3
    11071150/** @defgroup grp_rt_dbgmod     RTDbgMod - Debug Module Interpreter
    11081151 * @{
     
    17501793 */
    17511794RTDECL(int)         RTDbgModLineByAddrA(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGLINE *ppLineInfo);
     1795
     1796/**
     1797 * Try use unwind information to unwind one frame.
     1798 *
     1799 * @returns IPRT status code.  Last informational status from stack reader callback.
     1800 * @retval  VERR_DBG_NO_UNWIND_INFO if the module contains no unwind information.
     1801 * @retval  VERR_DBG_UNWIND_INFO_NOT_FOUND if no unwind information was found
     1802 *          for the location given by iSeg:off.
     1803 *
     1804 * @param   hDbgMod             The module handle.
     1805 * @param   iSeg                The segment number of the program counter.
     1806 * @param   off                 The offset into @a iSeg.  Together with @a iSeg
     1807 *                              this corresponds to the RTDBGUNWINDSTATE::uPc
     1808 *                              value pointed to by @a pState.
     1809 * @param   pState              The unwind state to work.
     1810 *
     1811 * @sa      RTLdrUnwindFrame
     1812 */
     1813RTDECL(int)         RTDbgModUnwindFrame(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState);
     1814
    17521815/** @} */
    1753 
    17541816# endif /* IN_RING3 */
     1817
    17551818
    17561819
  • trunk/include/iprt/err.h

    r72367 r73494  
    17291729/** Internal processing error the CodeView debug information reader. */
    17301730#define VERR_CV_IPE                             (-693)
     1731/** No unwind information was found. */
     1732#define VERR_DBG_NO_UNWIND_INFO                 (-694)
     1733/** No unwind information for the specified location. */
     1734#define VERR_DBG_UNWIND_INFO_NOT_FOUND          (-695)
     1735/** Malformed unwind information. */
     1736#define VERR_DBG_MALFORMED_UNWIND_INFO          (-696)
    17311737/** @} */
    17321738
  • trunk/include/iprt/ldr.h

    r73442 r73494  
    12281228RTDECL(int) RTLdrHashImage(RTLDRMOD hLdrMod, RTDIGESTTYPE enmDigest, char *pszDigest, size_t cbDigest);
    12291229
     1230/**
     1231 * Try use unwind information to unwind one frame.
     1232 *
     1233 * @returns IPRT status code.  Last informational status from stack reader callback.
     1234 * @retval  VERR_DBG_NO_UNWIND_INFO if the module contains no unwind information.
     1235 * @retval  VERR_DBG_UNWIND_INFO_NOT_FOUND if no unwind information was found
     1236 *          for the location given by iSeg:off.
     1237 *
     1238 * @param   hDbgMod             The module handle.
     1239 * @param   pvBits              Optional pointer to bits returned by
     1240 *                              RTLdrGetBits().  This can be utilized by some module
     1241 *                              interpreters to reduce memory consumption and file
     1242 *                              access.
     1243 * @param   iSeg                The segment number of the program counter.  UINT32_MAX if RVA.
     1244 * @param   off                 The offset into @a iSeg.  Together with @a iSeg
     1245 *                              this corresponds to the RTDBGUNWINDSTATE::uPc
     1246 *                              value pointed to by @a pState.
     1247 * @param   pState              The unwind state to work.
     1248 *
     1249 * @sa      RTDbgModUnwindFrame
     1250 */
     1251RTDECL(int) RTLdrUnwindFrame(RTLDRMOD hLdrMod, void const *pvBits, uint32_t iSeg, RTLDRADDR off, PRTDBGUNWINDSTATE pState);
     1252
    12301253RT_C_DECLS_END
    12311254
  • trunk/include/iprt/mangling.h

    r73375 r73494  
    755755# define RTDbgModSymbolByOrdinalA                       RT_MANGLER(RTDbgModSymbolByOrdinalA)
    756756# define RTDbgModSymbolCount                            RT_MANGLER(RTDbgModSymbolCount)
     757# define RTDbgModUnwindFrame                            RT_MANGLER(RTDbgModUnwindFrame)
    757758# define RTDbgSymbolAlloc                               RT_MANGLER(RTDbgSymbolAlloc)
    758759# define RTDbgSymbolDup                                 RT_MANGLER(RTDbgSymbolDup)
     
    11721173# define RTLdrSegOffsetToRva                            RT_MANGLER(RTLdrSegOffsetToRva)
    11731174# define RTLdrSize                                      RT_MANGLER(RTLdrSize)
     1175# define RTLdrUnwindFrame                               RT_MANGLER(RTLdrUnwindFrame)
    11741176# define RTLinuxCheckDevicePath                         RT_MANGLER(RTLinuxCheckDevicePath)
    11751177# define RTLinuxCheckDevicePathV                        RT_MANGLER(RTLinuxCheckDevicePathV)
  • trunk/src/VBox/Runtime/common/dbg/dbgmod.cpp

    r73375 r73494  
    22002200RT_EXPORT_SYMBOL(RTDbgModLineByAddrA);
    22012201
     2202
     2203RTDECL(int) RTDbgModUnwindFrame(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState)
     2204{
     2205    /*
     2206     * Validate input.
     2207     */
     2208    PRTDBGMODINT pDbgMod = hDbgMod;
     2209    RTDBGMOD_VALID_RETURN_RC(pDbgMod, VERR_INVALID_HANDLE);
     2210    AssertPtr(pState);
     2211    AssertReturn(pState->u32Magic == RTDBGUNWINDSTATE_MAGIC, VERR_INVALID_MAGIC);
     2212
     2213    RTDBGMOD_LOCK(pDbgMod);
     2214
     2215    /*
     2216     * Convert RVAs.
     2217     */
     2218    if (iSeg == RTDBGSEGIDX_RVA)
     2219    {
     2220        iSeg = pDbgMod->pDbgVt->pfnRvaToSegOff(pDbgMod, off, &off);
     2221        if (iSeg == NIL_RTDBGSEGIDX)
     2222        {
     2223            RTDBGMOD_UNLOCK(pDbgMod);
     2224            return VERR_DBG_INVALID_RVA;
     2225        }
     2226    }
     2227
     2228    /*
     2229     * Try the debug module first, then the image.
     2230     */
     2231    int rc = pDbgMod->pDbgVt->pfnUnwindFrame(pDbgMod, iSeg, off, pState);
     2232    if (rc == VERR_DBG_NO_UNWIND_INFO)
     2233        rc = pDbgMod->pImgVt->pfnUnwindFrame(pDbgMod, iSeg, off, pState);
     2234    else if (rc == VERR_DBG_UNWIND_INFO_NOT_FOUND)
     2235    {
     2236        rc = pDbgMod->pImgVt->pfnUnwindFrame(pDbgMod, iSeg, off, pState);
     2237        if (rc == VERR_DBG_NO_UNWIND_INFO)
     2238            rc = VERR_DBG_UNWIND_INFO_NOT_FOUND;
     2239    }
     2240
     2241    RTDBGMOD_UNLOCK(pDbgMod);
     2242    return rc;
     2243
     2244}
     2245RT_EXPORT_SYMBOL(RTDbgModUnwindFrame);
     2246
  • trunk/src/VBox/Runtime/common/dbg/dbgmodcodeview.cpp

    r73097 r73494  
    24072407
    24082408
     2409/** @interface_method_impl{RTDBGMODVTDBG,pfnUnwindFrame} */
     2410static DECLCALLBACK(int) rtDbgModCv_UnwindFrame(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState)
     2411{
     2412    RT_NOREF(pMod, iSeg, off, pState);
     2413    return VERR_DBG_NO_UNWIND_INFO;
     2414}
     2415
     2416
    24092417/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByAddr} */
    24102418static DECLCALLBACK(int) rtDbgModCv_LineByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off,
     
    31653173    /*.pfnLineByAddr = */       rtDbgModCv_LineByAddr,
    31663174
     3175    /*.pfnUnwindFrame = */      rtDbgModCv_UnwindFrame,
     3176
    31673177    /*.u32EndMagic = */         RTDBGMODVTDBG_MAGIC
    31683178};
  • trunk/src/VBox/Runtime/common/dbg/dbgmodcontainer.cpp

    r69111 r73494  
    150150
    151151
     152
     153/** @interface_method_impl{RTDBGMODVTDBG,pfnUnwindFrame} */
     154static DECLCALLBACK(int)
     155rtDbgModContainer_UnwindFrame(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState)
     156{
     157    RT_NOREF(pMod, iSeg, off, pState);
     158    return VERR_DBG_NO_UNWIND_INFO;
     159}
     160
     161
    152162/**
    153163 * Fills in a RTDBGSYMBOL structure.
     
    742752    /*.pfnLineByAddr = */       rtDbgModContainer_LineByAddr,
    743753
     754    /*.pfnUnwindFrame = */      rtDbgModContainer_UnwindFrame,
     755
    744756    /*.u32EndMagic = */         RTDBGMODVTDBG_MAGIC
    745757};
  • trunk/src/VBox/Runtime/common/dbg/dbgmoddbghelp.cpp

    r69111 r73494  
    6565    size_t          cbPrevUtf16Alloc;
    6666} RTDBGMODBGHELPARGS;
     67
     68
     69/** @interface_method_impl{RTDBGMODVTDBG,pfnUnwindFrame} */
     70static DECLCALLBACK(int) rtDbgModDbgHelp_UnwindFrame(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState)
     71{
     72    RT_NOREF(pMod, iSeg, off, pState);
     73    return VERR_DBG_NO_UNWIND_INFO;
     74}
    6775
    6876
     
    499507    /*.pfnLineByAddr = */       rtDbgModDbgHelp_LineByAddr,
    500508
     509    /*.pfnUnwindFrame = */      rtDbgModDbgHelp_UnwindFrame,
     510
    501511    /*.u32EndMagic = */         RTDBGMODVTDBG_MAGIC
    502512};
  • trunk/src/VBox/Runtime/common/dbg/dbgmoddeferred.cpp

    r73412 r73494  
    150150 *
    151151 */
     152
     153/** @interface_method_impl{RTDBGMODVTDBG,pfnUnwindFrame} */
     154static DECLCALLBACK(int)
     155rtDbgModDeferredDbg_UnwindFrame(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState)
     156{
     157    Assert(((PRTDBGMODDEFERRED)pMod->pvDbgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
     158    int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
     159    if (RT_SUCCESS(rc))
     160        rc = pMod->pDbgVt->pfnUnwindFrame(pMod, iSeg, off, pState);
     161    return rc;
     162}
    152163
    153164
     
    446457    /*.pfnLineByAddr = */       rtDbgModDeferredDbg_LineByAddr,
    447458
     459    /*.pfnUnwindFrame = */      rtDbgModDeferredDbg_UnwindFrame,
     460
    448461    /*.u32EndMagic = */         RTDBGMODVTDBG_MAGIC
    449462};
     
    459472 *
    460473 */
     474
     475/** @interface_method_impl{RTDBGMODVTIMG,pfnUnwindFrame} */
     476static DECLCALLBACK(int)
     477rtDbgModDeferredImg_UnwindFrame(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState)
     478{
     479    Assert(((PRTDBGMODDEFERRED)pMod->pvImgPriv)->u32Magic == RTDBGMODDEFERRED_MAGIC);
     480    int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
     481    if (RT_SUCCESS(rc))
     482        rc = pMod->pImgVt->pfnUnwindFrame(pMod, iSeg, off, pState);
     483    return rc;
     484}
     485
    461486
    462487/** @interface_method_impl{RTDBGMODVTIMG,pfnQueryProp} */
     
    638663    /*.pfnGetArch = */                  rtDbgModDeferredImg_GetArch,
    639664    /*.pfnQueryProp = */                rtDbgModDeferredImg_QueryProp,
     665    /*.pfnUnwindFrame = */              rtDbgModDeferredImg_UnwindFrame,
    640666
    641667    /*.u32EndMagic = */                 RTDBGMODVTIMG_MAGIC
  • trunk/src/VBox/Runtime/common/dbg/dbgmoddwarf.cpp

    r69111 r73494  
    45254525
    45264526
     4527/** @interface_method_impl{RTDBGMODVTDBG,pfnUnwindFrame} */
     4528static DECLCALLBACK(int) rtDbgModDwarf_UnwindFrame(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState)
     4529{
     4530    RT_NOREF(pMod, iSeg, off, pState);
     4531    return VERR_DBG_NO_UNWIND_INFO;
     4532}
     4533
     4534
    45274535/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByAddr} */
    45284536static DECLCALLBACK(int) rtDbgModDwarf_LineByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off,
     
    49684976    /*.pfnLineByAddr = */       rtDbgModDwarf_LineByAddr,
    49694977
     4978    /*.pfnUnwindFrame = */      rtDbgModDwarf_UnwindFrame,
     4979
    49704980    /*.u32EndMagic = */         RTDBGMODVTDBG_MAGIC
    49714981};
  • trunk/src/VBox/Runtime/common/dbg/dbgmodldr.cpp

    r73412 r73494  
    6161typedef RTDBGMODLDR *PRTDBGMODLDR;
    6262
     63
     64
     65/** @interface_method_impl{RTDBGMODVTDBG,pfnUnwindFrame} */
     66static DECLCALLBACK(int) rtDbgModLdr_UnwindFrame(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState)
     67{
     68    PRTDBGMODLDR pThis = (PRTDBGMODLDR)pMod->pvImgPriv;
     69    Assert(pThis->u32Magic == RTDBGMODLDR_MAGIC);
     70    return RTLdrUnwindFrame(pThis->hLdrMod, NULL, iSeg, off, pState);
     71}
    6372
    6473
     
    241250    /*.pfnGetArch = */                  rtDbgModLdr_GetArch,
    242251    /*.pfnQueryProp = */                rtDbgModLdr_QueryProp,
     252    /*.pfnUnwindFrame = */              rtDbgModLdr_UnwindFrame,
    243253
    244254    /*.u32EndMagic = */                 RTDBGMODVTIMG_MAGIC
  • trunk/src/VBox/Runtime/common/dbg/dbgmodnm.cpp

    r69111 r73494  
    5454typedef RTDBGMODNM *PRTDBGMODNM;
    5555
     56
     57
     58/** @interface_method_impl{RTDBGMODVTDBG,pfnUnwindFrame} */
     59static DECLCALLBACK(int) rtDbgModNm_UnwindFrame(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState)
     60{
     61    RT_NOREF(pMod, iSeg, off, pState);
     62    return VERR_DBG_NO_UNWIND_INFO;
     63}
    5664
    5765
     
    556564    /*.pfnLineByAddr = */       rtDbgModNm_LineByAddr,
    557565
     566    /*.pfnUnwindFrame = */      rtDbgModNm_UnwindFrame,
     567
    558568    /*.u32EndMagic = */         RTDBGMODVTDBG_MAGIC
    559569};
  • trunk/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h

    r73099 r73494  
    14311431    NULL /*pfnVerifySignature*/,
    14321432    NULL /*pfnHashImage*/,
     1433    NULL /*pfnUnwindFrame*/,
    14331434    42
    14341435};
  • trunk/src/VBox/Runtime/common/ldr/ldrEx.cpp

    r73442 r73494  
    3434
    3535#include <iprt/assert.h>
     36#include <iprt/dbg.h>
    3637#include <iprt/err.h>
    3738#include <iprt/log.h>
     
    708709
    709710
     711RTDECL(int) RTLdrUnwindFrame(RTLDRMOD hLdrMod, void const *pvBits, uint32_t iSeg, RTLDRADDR off, PRTDBGUNWINDSTATE pState)
     712{
     713    /*
     714     * Validate.
     715     */
     716    AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), VERR_INVALID_HANDLE);
     717    PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
     718    AssertPtr(pState);
     719    AssertReturn(pState->u32Magic == RTDBGUNWINDSTATE_MAGIC, VERR_INVALID_MAGIC);
     720
     721    /*
     722     * Pass on the work.
     723     */
     724    if (pMod->pOps->pfnUnwindFrame)
     725        return pMod->pOps->pfnUnwindFrame(pMod, pvBits, iSeg, off, pState);
     726    return VERR_DBG_NO_UNWIND_INFO;
     727}
     728RT_EXPORT_SYMBOL(RTLdrUnwindFrame);
     729
     730
    710731/**
    711732 * Internal method used by the IPRT debug bits.
  • trunk/src/VBox/Runtime/common/ldr/ldrNative.cpp

    r69111 r73494  
    8686    NULL,
    8787    NULL,
     88    NULL /*pfnUnwindFrame*/,
    8889    42
    8990};
  • trunk/src/VBox/Runtime/common/ldr/ldrPE.cpp

    r73387 r73494  
    3535#include <iprt/assert.h>
    3636#include <iprt/asm.h>
     37#include <iprt/dbg.h>
    3738#include <iprt/err.h>
    3839#include <iprt/log.h>
     
    4243#include <iprt/sha.h>
    4344#include <iprt/string.h>
     45#include <iprt/x86.h>
    4446#ifndef IPRT_WITHOUT_LDR_VERIFY
    4547#include <iprt/zero.h>
     
    29082910
    29092911
    2910 /**  @interface_method_impl{RTLDROPS,pfnHashImage}  */
     2912/**
     2913 * @interface_method_impl{RTLDROPS,pfnHashImage}
     2914 */
    29112915static DECLCALLBACK(int) rtldrPE_HashImage(PRTLDRMODINTERNAL pMod, RTDIGESTTYPE enmDigest, char *pszDigest, size_t cbDigest)
    29122916{
     
    29462950        }
    29472951    }
     2952    return rc;
     2953}
     2954
     2955
     2956/**
     2957 * Binary searches the lookup table.
     2958 *
     2959 * @returns RVA of unwind info on success, UINT32_MAX on failure.
     2960 * @param   paFunctions     The table to lookup @a uRva in.
     2961 * @param   iEnd            Size of the table.
     2962 * @param   uRva            The RVA of the function we want.
     2963 */
     2964DECLINLINE(PCIMAGE_RUNTIME_FUNCTION_ENTRY)
     2965rtldrPE_LookupRuntimeFunctionEntry(PCIMAGE_RUNTIME_FUNCTION_ENTRY paFunctions, size_t iEnd, uint32_t uRva)
     2966{
     2967    size_t iBegin = 0;
     2968    while (iBegin < iEnd)
     2969    {
     2970        size_t const i = iBegin  + (iEnd - iBegin) / 2;
     2971        PCIMAGE_RUNTIME_FUNCTION_ENTRY pEntry = &paFunctions[i];
     2972        if (uRva < pEntry->BeginAddress)
     2973            iEnd = i;
     2974        else if (uRva > pEntry->EndAddress)
     2975            iBegin = i + 1;
     2976        else
     2977            return pEntry;
     2978    }
     2979    return NULL;
     2980}
     2981
     2982
     2983/**
     2984 * Processes an IRET frame.
     2985 *
     2986 * @returns IPRT status code.
     2987 * @param   pState          The unwind state being worked.
     2988 * @param   fErrCd          Non-zero if there is an error code on the stack.
     2989 */
     2990static int rtldrPE_UnwindFrame_Amd64_IRet(PRTDBGUNWINDSTATE pState, uint8_t fErrCd)
     2991{
     2992    /* POP ErrCd (optional): */
     2993    Assert(fErrCd <= 1);
     2994    int rcRet;
     2995    if (fErrCd)
     2996    {
     2997        pState->u.x86.uErrCd = 0;
     2998        pState->u.x86.Loaded.s.fErrCd = 1;
     2999        rcRet = RTDbgUnwindLoadStackU64(pState, pState->u.x86.auRegs[X86_GREG_xSP], &pState->u.x86.uErrCd);
     3000        pState->u.x86.auRegs[X86_GREG_xSP] += 8;
     3001    }
     3002    else
     3003    {
     3004        pState->u.x86.Loaded.s.fErrCd = 0;
     3005        rcRet = VINF_SUCCESS;
     3006    }
     3007
     3008    /* Set return type and frame pointer. */
     3009    pState->enmRetType          = RTDBGRETURNTYPE_IRET64;
     3010    pState->u.x86.FrameAddr.off = pState->u.x86.auRegs[X86_GREG_xSP] - /* pretend rbp is pushed on the stack */ 8;
     3011    pState->u.x86.FrameAddr.sel = pState->u.x86.auSegs[X86_SREG_SS];
     3012
     3013    /* POP RIP: */
     3014    int rc = RTDbgUnwindLoadStackU64(pState, pState->u.x86.auRegs[X86_GREG_xSP], &pState->uPc);
     3015    if (RT_FAILURE(rc))
     3016        rcRet = rc;
     3017    pState->u.x86.auRegs[X86_GREG_xSP] += 8;
     3018
     3019    /* POP CS: */
     3020    rc = RTDbgUnwindLoadStackU16(pState, pState->u.x86.auRegs[X86_GREG_xSP], &pState->u.x86.auSegs[X86_SREG_CS]);
     3021    if (RT_FAILURE(rc))
     3022        rcRet = rc;
     3023    pState->u.x86.auRegs[X86_GREG_xSP] += 8;
     3024
     3025    /* POP RFLAGS: */
     3026    rc = RTDbgUnwindLoadStackU64(pState, pState->u.x86.auRegs[X86_GREG_xSP], &pState->u.x86.uRFlags);
     3027    if (RT_FAILURE(rc))
     3028        rcRet = rc;
     3029    pState->u.x86.auRegs[X86_GREG_xSP] += 8;
     3030
     3031    /* POP RSP, part 1: */
     3032    uint64_t uNewRsp = (pState->u.x86.auRegs[X86_GREG_xSP] - 8) & ~(uint64_t)15;
     3033    rc = RTDbgUnwindLoadStackU64(pState, pState->u.x86.auRegs[X86_GREG_xSP], &uNewRsp);
     3034    if (RT_FAILURE(rc))
     3035        rcRet = rc;
     3036    pState->u.x86.auRegs[X86_GREG_xSP] += 8;
     3037
     3038    /* POP SS: */
     3039    rc = RTDbgUnwindLoadStackU16(pState, pState->u.x86.auRegs[X86_GREG_xSP], &pState->u.x86.auSegs[X86_SREG_SS]);
     3040    if (RT_FAILURE(rc))
     3041        rcRet = rc;
     3042    pState->u.x86.auRegs[X86_GREG_xSP] += 8;
     3043
     3044    /* POP RSP, part 2: */
     3045    pState->u.x86.auRegs[X86_GREG_xSP] = uNewRsp;
     3046
     3047    /* Set loaded indicators: */
     3048    pState->u.x86.Loaded.s.fRegs        |= RT_BIT(X86_GREG_xSP);
     3049    pState->u.x86.Loaded.s.fSegs        |= RT_BIT(X86_SREG_CS) | RT_BIT(X86_SREG_SS);
     3050    pState->u.x86.Loaded.s.fPc           = 1;
     3051    pState->u.x86.Loaded.s.fFrameAddr    = 1;
     3052    pState->u.x86.Loaded.s.fRFlags       = 1;
     3053    return VINF_SUCCESS;
     3054}
     3055
     3056
     3057static int rtldrPE_UnwindFrame_Amd64(PRTLDRMODPE pThis, void const *pvBits, PRTDBGUNWINDSTATE pState, uint32_t uRvaPc,
     3058                                     PCIMAGE_RUNTIME_FUNCTION_ENTRY pEntry)
     3059{
     3060    /* Did we find any unwind information? */
     3061    if (!pEntry)
     3062        return VERR_DBG_UNWIND_INFO_NOT_FOUND;
     3063
     3064    /*
     3065     * Do the unwinding.
     3066     */
     3067    IMAGE_RUNTIME_FUNCTION_ENTRY ChainedEntry;
     3068    unsigned iFrameReg   = ~0U;
     3069    unsigned offFrameReg = 0;
     3070
     3071    int      fInEpilog = -1; /* -1: not-determined-assume-false;  0: false;  1: true. */
     3072    uint8_t  cbEpilog  = 0;
     3073    uint8_t  offEpilog = UINT8_MAX;
     3074    int      rcRet = VINF_SUCCESS;
     3075    int      rc;
     3076    for (unsigned cChainLoops = 0; ; cChainLoops++)
     3077    {
     3078        /*
     3079         * Get the info.
     3080         */
     3081        union
     3082        {
     3083            uint32_t uRva;
     3084            uint8_t  ab[  RT_OFFSETOF(IMAGE_UNWIND_INFO, aOpcodes)
     3085                        + sizeof(IMAGE_UNWIND_CODE) * 256
     3086                        + sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY)];
     3087        } uBuf;
     3088        rc = rtldrPEReadPartByRvaInfoBuf(pThis, pvBits, pEntry->UnwindInfoAddress, sizeof(uBuf), &uBuf);
     3089        if (RT_FAILURE(rc))
     3090            return rc;
     3091
     3092        /*
     3093         * Check the info.
     3094         */
     3095        ASMCompilerBarrier(); /* we're aliasing */
     3096        PCIMAGE_UNWIND_INFO pInfo = (PCIMAGE_UNWIND_INFO)&uBuf;
     3097
     3098        if (pInfo->Version != 1 && pInfo->Version != 2)
     3099            return VERR_DBG_MALFORMED_UNWIND_INFO;
     3100
     3101        /*
     3102         * Execute the opcodes.
     3103         */
     3104        unsigned const cOpcodes = pInfo->CountOfCodes;
     3105        unsigned       iOpcode  = 0;
     3106
     3107        /*
     3108         * Check for epilog opcodes at the start and see if we're in an epilog.
     3109         */
     3110        if (   pInfo->Version >= 2
     3111            && iOpcode < cOpcodes
     3112            && pInfo->aOpcodes[iOpcode].u.UnwindOp == IMAGE_AMD64_UWOP_EPILOG)
     3113        {
     3114            if (fInEpilog == -1)
     3115            {
     3116                cbEpilog = pInfo->aOpcodes[iOpcode].u.CodeOffset;
     3117                Assert(cbEpilog > 0);
     3118
     3119                uint32_t uRvaEpilog = pEntry->EndAddress - cbEpilog;
     3120                iOpcode++;
     3121                if (   (pInfo->aOpcodes[iOpcode - 1].u.OpInfo & 1)
     3122                    && uRvaPc >= uRvaEpilog)
     3123                {
     3124                    offEpilog = uRvaPc - uRvaEpilog;
     3125                    fInEpilog = 1;
     3126                }
     3127                else
     3128                {
     3129                    fInEpilog = 0;
     3130                    while (iOpcode < cOpcodes && pInfo->aOpcodes[iOpcode].u.UnwindOp == IMAGE_AMD64_UWOP_EPILOG)
     3131                    {
     3132                        uRvaEpilog = pEntry->EndAddress
     3133                                   - (pInfo->aOpcodes[iOpcode].u.CodeOffset + (pInfo->aOpcodes[iOpcode].u.OpInfo << 8));
     3134                        iOpcode++;
     3135                        if (uRvaPc - uRvaEpilog < cbEpilog)
     3136                        {
     3137                            offEpilog = uRvaPc - uRvaEpilog;
     3138                            fInEpilog = 1;
     3139                            break;
     3140                        }
     3141                    }
     3142                }
     3143            }
     3144            while (iOpcode < cOpcodes && pInfo->aOpcodes[iOpcode].u.UnwindOp == IMAGE_AMD64_UWOP_EPILOG)
     3145                iOpcode++;
     3146        }
     3147        if (fInEpilog != 1)
     3148        {
     3149            /*
     3150             * Skip opcodes that doesn't apply to us if we're in the prolog.
     3151             */
     3152            uint32_t offPc = uRvaPc - pEntry->BeginAddress;
     3153            if (offPc < pInfo->SizeOfProlog)
     3154                while (iOpcode < cOpcodes && pInfo->aOpcodes[iOpcode].u.CodeOffset > offPc)
     3155                    iOpcode++;
     3156
     3157            /*
     3158             * Execute the opcodes.
     3159             */
     3160            if (pInfo->FrameRegister != 0)
     3161            {
     3162                iFrameReg   = pInfo->FrameRegister;
     3163                offFrameReg = pInfo->FrameOffset * 16;
     3164            }
     3165            while (iOpcode < cOpcodes)
     3166            {
     3167                Assert(pInfo->aOpcodes[iOpcode].u.CodeOffset <= offPc);
     3168                uint8_t const uOpInfo   = pInfo->aOpcodes[iOpcode].u.OpInfo;
     3169                uint8_t const uUnwindOp = pInfo->aOpcodes[iOpcode].u.UnwindOp;
     3170                switch (uUnwindOp)
     3171                {
     3172                    case IMAGE_AMD64_UWOP_PUSH_NONVOL:
     3173                        rc = RTDbgUnwindLoadStackU64(pState, pState->u.x86.auRegs[X86_GREG_xSP], &pState->u.x86.auRegs[uOpInfo]);
     3174                        if (RT_FAILURE(rc))
     3175                            rcRet = rc;
     3176                        pState->u.x86.Loaded.s.fRegs |= RT_BIT(uOpInfo);
     3177                        pState->u.x86.auRegs[X86_GREG_xSP] += 8;
     3178                        iOpcode++;
     3179                        break;
     3180
     3181                    case IMAGE_AMD64_UWOP_ALLOC_LARGE:
     3182                        if (uOpInfo == 0)
     3183                        {
     3184                            iOpcode += 2;
     3185                            AssertBreak(iOpcode <= cOpcodes);
     3186                            pState->u.x86.auRegs[X86_GREG_xSP] += pInfo->aOpcodes[iOpcode - 1].FrameOffset * 8;
     3187                        }
     3188                        else
     3189                        {
     3190                            iOpcode += 3;
     3191                            AssertBreak(iOpcode <= cOpcodes);
     3192                            pState->u.x86.auRegs[X86_GREG_xSP] += RT_MAKE_U32(pInfo->aOpcodes[iOpcode - 2].FrameOffset,
     3193                                                                              pInfo->aOpcodes[iOpcode - 1].FrameOffset);
     3194                        }
     3195                        break;
     3196
     3197                    case IMAGE_AMD64_UWOP_ALLOC_SMALL:
     3198                        AssertBreak(iOpcode <= cOpcodes);
     3199                        pState->u.x86.auRegs[X86_GREG_xSP] += uOpInfo * 8 + 8;
     3200                        iOpcode++;
     3201                        break;
     3202
     3203                    case IMAGE_AMD64_UWOP_SET_FPREG:
     3204                        iFrameReg = uOpInfo;
     3205                        offFrameReg = pInfo->FrameOffset * 16;
     3206                        pState->u.x86.auRegs[X86_GREG_xSP] = pState->u.x86.auRegs[iFrameReg] - offFrameReg;
     3207                        iOpcode++;
     3208                        break;
     3209
     3210                    case IMAGE_AMD64_UWOP_SAVE_NONVOL:
     3211                    case IMAGE_AMD64_UWOP_SAVE_NONVOL_FAR:
     3212                    {
     3213                        uint32_t off = 0;
     3214                        iOpcode++;
     3215                        if (iOpcode < cOpcodes)
     3216                        {
     3217                            off = pInfo->aOpcodes[iOpcode].FrameOffset;
     3218                            iOpcode++;
     3219                            if (uUnwindOp == IMAGE_AMD64_UWOP_SAVE_NONVOL_FAR && iOpcode < cOpcodes)
     3220                            {
     3221                                off |= (uint32_t)pInfo->aOpcodes[iOpcode].FrameOffset << 16;
     3222                                iOpcode++;
     3223                            }
     3224                        }
     3225                        off *= 8;
     3226                        rc = RTDbgUnwindLoadStackU64(pState, pState->u.x86.auRegs[X86_GREG_xSP] + off,
     3227                                                     &pState->u.x86.auRegs[uOpInfo]);
     3228                        if (RT_FAILURE(rc))
     3229                            rcRet = rc;
     3230                        pState->u.x86.Loaded.s.fRegs |= RT_BIT(uOpInfo);
     3231                        break;
     3232                    }
     3233
     3234                    case IMAGE_AMD64_UWOP_SAVE_XMM128:
     3235                        iOpcode += 2;
     3236                        break;
     3237
     3238                    case IMAGE_AMD64_UWOP_SAVE_XMM128_FAR:
     3239                        iOpcode += 3;
     3240                        break;
     3241
     3242                    case IMAGE_AMD64_UWOP_PUSH_MACHFRAME:
     3243                        return rtldrPE_UnwindFrame_Amd64_IRet(pState, uOpInfo);
     3244
     3245                    case IMAGE_AMD64_UWOP_EPILOG:
     3246                        iOpcode += 1;
     3247                        break;
     3248
     3249                    case IMAGE_AMD64_UWOP_RESERVED_7:
     3250                        AssertFailedReturn(VERR_DBG_MALFORMED_UNWIND_INFO);
     3251
     3252                    default:
     3253                        AssertMsgFailedReturn(("%u\n", uUnwindOp), VERR_DBG_MALFORMED_UNWIND_INFO);
     3254                }
     3255            }
     3256        }
     3257        else
     3258        {
     3259            /*
     3260             * We're in the POP sequence of an epilog.  The POP sequence should
     3261             * mirror the PUSH sequence exactly.
     3262             *
     3263             * Note! We should only end up here for the initial frame (just consider
     3264             *       RSP, stack allocations, non-volatile register restores, ++).
     3265             */
     3266            while (iOpcode < cOpcodes)
     3267            {
     3268                uint8_t const uOpInfo   = pInfo->aOpcodes[iOpcode].u.OpInfo;
     3269                uint8_t const uUnwindOp = pInfo->aOpcodes[iOpcode].u.UnwindOp;
     3270                switch (uUnwindOp)
     3271                {
     3272                    case IMAGE_AMD64_UWOP_PUSH_NONVOL:
     3273                        pState->u.x86.auRegs[X86_GREG_xSP] += 8;
     3274                        if (offEpilog == 0)
     3275                        {
     3276                            rc = RTDbgUnwindLoadStackU64(pState, pState->u.x86.auRegs[X86_GREG_xSP],
     3277                                                         &pState->u.x86.auRegs[uOpInfo]);
     3278                            if (RT_FAILURE(rc))
     3279                                rcRet = rc;
     3280                            pState->u.x86.Loaded.s.fRegs |= RT_BIT(uOpInfo);
     3281                        }
     3282                        else
     3283                        {
     3284                            /* Decrement offEpilog by estimated POP instruction length. */
     3285                            offEpilog -= 1;
     3286                            if (offEpilog > 0 && uOpInfo >= 8)
     3287                                offEpilog -= 1;
     3288                        }
     3289                        iOpcode++;
     3290                        break;
     3291
     3292                    case IMAGE_AMD64_UWOP_PUSH_MACHFRAME: /* Must terminate an epilog, so always execute this. */
     3293                        return rtldrPE_UnwindFrame_Amd64_IRet(pState, uOpInfo);
     3294
     3295                    case IMAGE_AMD64_UWOP_ALLOC_SMALL:
     3296                    case IMAGE_AMD64_UWOP_SET_FPREG:
     3297                    case IMAGE_AMD64_UWOP_EPILOG:
     3298                        iOpcode++;
     3299                        break;
     3300                    case IMAGE_AMD64_UWOP_SAVE_NONVOL:
     3301                    case IMAGE_AMD64_UWOP_SAVE_XMM128:
     3302                        iOpcode += 2;
     3303                        break;
     3304                    case IMAGE_AMD64_UWOP_ALLOC_LARGE:
     3305                    case IMAGE_AMD64_UWOP_SAVE_NONVOL_FAR:
     3306                    case IMAGE_AMD64_UWOP_SAVE_XMM128_FAR:
     3307                        iOpcode += 3;
     3308                        break;
     3309
     3310                    default:
     3311                        AssertMsgFailedReturn(("%u\n", uUnwindOp), VERR_DBG_MALFORMED_UNWIND_INFO);
     3312                }
     3313            }
     3314        }
     3315
     3316        /*
     3317         * Chained stuff?
     3318         */
     3319        if (!(pInfo->Flags & IMAGE_UNW_FLAGS_CHAININFO))
     3320            break;
     3321        ChainedEntry = *(PCIMAGE_RUNTIME_FUNCTION_ENTRY)&pInfo->aOpcodes[(cOpcodes + 1) & ~1];
     3322        pEntry = &ChainedEntry;
     3323        AssertReturn(cChainLoops < 32, VERR_DBG_MALFORMED_UNWIND_INFO);
     3324    }
     3325
     3326    /*
     3327     * RSP should now give us the return address, so perform a RET.
     3328     */
     3329    pState->enmRetType = RTDBGRETURNTYPE_NEAR64;
     3330
     3331    pState->u.x86.FrameAddr.off = pState->u.x86.auRegs[X86_GREG_xSP] - /* pretend rbp is pushed on the stack */ 8;
     3332    pState->u.x86.FrameAddr.sel = pState->u.x86.auSegs[X86_SREG_SS];
     3333    pState->u.x86.Loaded.s.fFrameAddr = 1;
     3334
     3335    rc = RTDbgUnwindLoadStackU64(pState, pState->u.x86.auRegs[X86_GREG_xSP], &pState->uPc);
     3336    if (RT_FAILURE(rc))
     3337        rcRet = rc;
     3338    pState->u.x86.auRegs[X86_GREG_xSP] += 8;
     3339    pState->u.x86.Loaded.s.fPc = 1;
     3340    return rcRet;
     3341}
     3342
     3343
     3344/**
     3345 * @interface_method_impl{RTLDROPS,pfnUnwindFrame}
     3346 */
     3347static DECLCALLBACK(int) rtldrPE_UnwindFrame(PRTLDRMODINTERNAL pMod, void const *pvBits,
     3348                                             uint32_t iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState)
     3349{
     3350    PRTLDRMODPE pThis = (PRTLDRMODPE)pMod;
     3351
     3352    /*
     3353     * Translate the segment + offset into an RVA.
     3354     */
     3355    RTLDRADDR uRvaPc = off;
     3356    if (iSeg != UINT32_MAX)
     3357    {
     3358        int rc = rtldrPE_SegOffsetToRva(pMod, iSeg, off, &uRvaPc);
     3359        if (RT_FAILURE(rc))
     3360            return rc;
     3361    }
     3362
     3363    /*
     3364     * Check for unwind info and match the architecture.
     3365     */
     3366    if (   pThis->ExceptionDir.Size == 0
     3367        || pThis->ExceptionDir.VirtualAddress < pThis->cbHeaders)
     3368        return VERR_DBG_NO_UNWIND_INFO;
     3369    if (pThis->Core.enmArch != pState->enmArch)
     3370        return VERR_DBG_UNWIND_INFO_NOT_FOUND;
     3371
     3372    /* Currently only AMD64 unwinding is implemented, so head it off right away. */
     3373    if (pThis->Core.enmArch != RTLDRARCH_AMD64)
     3374        return VERR_DBG_UNWIND_INFO_NOT_FOUND;
     3375
     3376    /*
     3377     * Make the lookup table available to us.
     3378     */
     3379    void const    *pvTable = NULL;
     3380    uint32_t const cbTable = pThis->ExceptionDir.Size;
     3381    AssertReturn(   cbTable < pThis->cbImage
     3382                 && pThis->ExceptionDir.VirtualAddress < pThis->cbImage
     3383                 && pThis->ExceptionDir.VirtualAddress + cbTable <= pThis->cbImage, VERR_INTERNAL_ERROR_3);
     3384    int rc = rtldrPEReadPartByRva(pThis, pvBits, pThis->ExceptionDir.VirtualAddress, pThis->ExceptionDir.Size, &pvTable);
     3385    if (RT_FAILURE(rc))
     3386        return rc;
     3387
     3388    /*
     3389     * The rest is architecture dependent.
     3390     *
     3391     * Note! On windows we try catch access violations so we can safely use
     3392     *       this code on mapped images during assertions.
     3393     */
     3394#ifdef _MSC_VER
     3395    __try
     3396    {
     3397#endif
     3398        switch (pThis->Core.enmArch)
     3399        {
     3400            case RTLDRARCH_AMD64:
     3401                rc = rtldrPE_UnwindFrame_Amd64(pThis, pvBits, pState, uRvaPc,
     3402                                               rtldrPE_LookupRuntimeFunctionEntry((PCIMAGE_RUNTIME_FUNCTION_ENTRY)pvTable,
     3403                                                                                  cbTable / sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY),
     3404                                                                                  (uint32_t)uRvaPc));
     3405                break;
     3406
     3407            default:
     3408                rc = VERR_DBG_UNWIND_INFO_NOT_FOUND;
     3409                break;
     3410        }
     3411#ifdef _MSC_VER
     3412    }
     3413    __except (1 /*EXCEPTION_EXECUTE_HANDLER*/)
     3414    {
     3415        rc = VERR_DBG_UNWIND_INFO_NOT_FOUND;
     3416    }
     3417#endif
     3418    rtldrPEFreePart(pThis, pvBits, pvTable);
    29483419    return rc;
    29493420}
     
    30083479        rtldrPE_VerifySignature,
    30093480        rtldrPE_HashImage,
     3481        NULL /*pfnUnwindFrame*/,
    30103482        42
    30113483    },
     
    30423514        rtldrPE_VerifySignature,
    30433515        rtldrPE_HashImage,
     3516        rtldrPE_UnwindFrame,
    30443517        42
    30453518    },
  • trunk/src/VBox/Runtime/common/ldr/ldrkStuff.cpp

    r73442 r73494  
    906906    NULL,
    907907    NULL,
     908    NULL /*pfnUnwindFrame*/,
    908909    42
    909910};
  • trunk/src/VBox/Runtime/include/internal/dbgmod.h

    r73412 r73494  
    243243    DECLCALLBACKMEMBER(int, pfnQueryProp)(PRTDBGMODINT pMod, RTLDRPROP enmProp, void *pvBuf, size_t cbBuf, size_t *pcbRet);
    244244
     245    /**
     246     * Try use unwind information to unwind one frame.
     247     *
     248     * @returns IPRT status code.  Last informational status from stack reader callback.
     249     * @retval  VERR_DBG_NO_UNWIND_INFO if the module contains no unwind information.
     250     * @retval  VERR_DBG_UNWIND_INFO_NOT_FOUND if no unwind information was found
     251     *          for the location given by iSeg:off.
     252     *
     253     * @param   pMod        Pointer to the module structure.
     254     * @param   iSeg        The segment number of the program counter.
     255     * @param   off         The offset into @a iSeg.  Together with @a iSeg
     256     *                      this corresponds to the RTDBGUNWINDSTATE::uPc
     257     *                      value pointed to by @a pState.
     258     * @param   pState      The unwind state to work.
     259     *
     260     * @sa      RTLdrUnwindFrame, RTDbgModUnwindFrame
     261     */
     262    DECLCALLBACKMEMBER(int, pfnUnwindFrame)(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState);
     263
    245264    /** For catching initialization errors (RTDBGMODVTIMG_MAGIC). */
    246265    uint32_t    u32EndMagic;
     
    512531     *                      number.
    513532     */
    514     DECLCALLBACKMEMBER(int, pfnLineByAddr)(PRTDBGMODINT pMod, uint32_t iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGLINE pLineInfo);
    515 
     533    DECLCALLBACKMEMBER(int, pfnLineByAddr)(PRTDBGMODINT pMod, uint32_t iSeg, RTUINTPTR off,
     534                                           PRTINTPTR poffDisp, PRTDBGLINE pLineInfo);
     535
     536    /**
     537     * Try use unwind information to unwind one frame.
     538     *
     539     * @returns IPRT status code.  Last informational status from stack reader callback.
     540     * @retval  VERR_DBG_NO_UNWIND_INFO if the module contains no unwind information.
     541     * @retval  VERR_DBG_UNWIND_INFO_NOT_FOUND if no unwind information was found
     542     *          for the location given by iSeg:off.
     543     *
     544     * @param   pMod        Pointer to the module structure.
     545     * @param   iSeg        The segment number of the program counter.
     546     * @param   off         The offset into @a iSeg.  Together with @a iSeg
     547     *                      this corresponds to the RTDBGUNWINDSTATE::uPc
     548     *                      value pointed to by @a pState.
     549     * @param   pState      The unwind state to work.
     550     *
     551     * @sa      RTDbgModUnwindFrame
     552     */
     553    DECLCALLBACKMEMBER(int, pfnUnwindFrame)(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState);
    516554
    517555    /** For catching initialization errors (RTDBGMODVTDBG_MAGIC). */
  • trunk/src/VBox/Runtime/include/internal/ldr.h

    r73150 r73494  
    402402    DECLCALLBACKMEMBER(int, pfnHashImage)(PRTLDRMODINTERNAL pMod, RTDIGESTTYPE enmDigest, char *pszDigest, size_t cbDigest);
    403403
     404        /**
     405     * Try use unwind information to unwind one frame.
     406     *
     407     * @returns IPRT status code.  Last informational status from stack reader callback.
     408     * @retval  VERR_DBG_NO_UNWIND_INFO if the module contains no unwind information.
     409     * @retval  VERR_DBG_UNWIND_INFO_NOT_FOUND if no unwind information was found
     410     *          for the location given by iSeg:off.
     411     *
     412     * @param   pMod        Pointer to the module structure.
     413     * @param   pvBits      Pointer to the bits returned by
     414     *                      RTLDROPS::pfnGetBits(), optional.
     415     * @param   iSeg        The segment number of the program counter.  UINT32_MAX for RVA.
     416     * @param   off         The offset into @a iSeg.  Together with @a iSeg
     417     *                      this corresponds to the RTDBGUNWINDSTATE::uPc
     418     *                      value pointed to by @a pState.
     419     * @param   pState      The unwind state to work.
     420     *
     421     * @sa      RTLdrUnwindFrame, RTDbgModUnwindFrame
     422     */
     423    DECLCALLBACKMEMBER(int, pfnUnwindFrame)(PRTLDRMODINTERNAL pMod, void const *pvBits, uint32_t iSeg, RTUINTPTR off,
     424                                            PRTDBGUNWINDSTATE pState);
     425
    404426    /** Dummy entry to make sure we've initialized it all. */
    405427    RTUINT uDummy;
Note: See TracChangeset for help on using the changeset viewer.

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