Changeset 73494 in vbox
- Timestamp:
- Aug 4, 2018 7:41:30 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 124121
- Location:
- trunk
- Files:
-
- 19 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/dbg.h
r73482 r73494 34 34 RT_C_DECLS_BEGIN 35 35 36 # ifdef IN_RING337 36 38 37 /** @defgroup grp_rt_dbg RTDbg - Debugging Routines … … 275 274 } RTDBGUNWINDSTATE; 276 275 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 */ 284 DECLINLINE(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 */ 297 DECLINLINE(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 */ 310 DECLINLINE(int) RTDbgUnwindLoadStackU64(PRTDBGUNWINDSTATE pThis, RTUINTPTR uSrcAddr, uint64_t *puDst) 311 { 312 return pThis->pfnReadStack(pThis, uSrcAddr, sizeof(*puDst), puDst); 313 } 314 277 315 278 316 … … 308 346 typedef const RTDBGSYMBOL *PCRTDBGSYMBOL; 309 347 348 310 349 /** 311 350 * Allocate a new symbol structure. … … 385 424 RTDECL(void) RTDbgLineFree(PRTDBGLINE pLine); 386 425 426 427 # ifdef IN_RING3 387 428 388 429 /** @defgroup grp_rt_dbgcfg RTDbgCfg - Debugging Configuration … … 659 700 /** @} */ 660 701 702 # endif /* IN_RING3 */ 661 703 662 704 /** @} */ … … 1105 1147 1106 1148 1149 # ifdef IN_RING3 1107 1150 /** @defgroup grp_rt_dbgmod RTDbgMod - Debug Module Interpreter 1108 1151 * @{ … … 1750 1793 */ 1751 1794 RTDECL(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 */ 1813 RTDECL(int) RTDbgModUnwindFrame(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState); 1814 1752 1815 /** @} */ 1753 1754 1816 # endif /* IN_RING3 */ 1817 1755 1818 1756 1819 -
trunk/include/iprt/err.h
r72367 r73494 1729 1729 /** Internal processing error the CodeView debug information reader. */ 1730 1730 #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) 1731 1737 /** @} */ 1732 1738 -
trunk/include/iprt/ldr.h
r73442 r73494 1228 1228 RTDECL(int) RTLdrHashImage(RTLDRMOD hLdrMod, RTDIGESTTYPE enmDigest, char *pszDigest, size_t cbDigest); 1229 1229 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 */ 1251 RTDECL(int) RTLdrUnwindFrame(RTLDRMOD hLdrMod, void const *pvBits, uint32_t iSeg, RTLDRADDR off, PRTDBGUNWINDSTATE pState); 1252 1230 1253 RT_C_DECLS_END 1231 1254 -
trunk/include/iprt/mangling.h
r73375 r73494 755 755 # define RTDbgModSymbolByOrdinalA RT_MANGLER(RTDbgModSymbolByOrdinalA) 756 756 # define RTDbgModSymbolCount RT_MANGLER(RTDbgModSymbolCount) 757 # define RTDbgModUnwindFrame RT_MANGLER(RTDbgModUnwindFrame) 757 758 # define RTDbgSymbolAlloc RT_MANGLER(RTDbgSymbolAlloc) 758 759 # define RTDbgSymbolDup RT_MANGLER(RTDbgSymbolDup) … … 1172 1173 # define RTLdrSegOffsetToRva RT_MANGLER(RTLdrSegOffsetToRva) 1173 1174 # define RTLdrSize RT_MANGLER(RTLdrSize) 1175 # define RTLdrUnwindFrame RT_MANGLER(RTLdrUnwindFrame) 1174 1176 # define RTLinuxCheckDevicePath RT_MANGLER(RTLinuxCheckDevicePath) 1175 1177 # define RTLinuxCheckDevicePathV RT_MANGLER(RTLinuxCheckDevicePathV) -
trunk/src/VBox/Runtime/common/dbg/dbgmod.cpp
r73375 r73494 2200 2200 RT_EXPORT_SYMBOL(RTDbgModLineByAddrA); 2201 2201 2202 2203 RTDECL(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 } 2245 RT_EXPORT_SYMBOL(RTDbgModUnwindFrame); 2246 -
trunk/src/VBox/Runtime/common/dbg/dbgmodcodeview.cpp
r73097 r73494 2407 2407 2408 2408 2409 /** @interface_method_impl{RTDBGMODVTDBG,pfnUnwindFrame} */ 2410 static 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 2409 2417 /** @interface_method_impl{RTDBGMODVTDBG,pfnLineByAddr} */ 2410 2418 static DECLCALLBACK(int) rtDbgModCv_LineByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, … … 3165 3173 /*.pfnLineByAddr = */ rtDbgModCv_LineByAddr, 3166 3174 3175 /*.pfnUnwindFrame = */ rtDbgModCv_UnwindFrame, 3176 3167 3177 /*.u32EndMagic = */ RTDBGMODVTDBG_MAGIC 3168 3178 }; -
trunk/src/VBox/Runtime/common/dbg/dbgmodcontainer.cpp
r69111 r73494 150 150 151 151 152 153 /** @interface_method_impl{RTDBGMODVTDBG,pfnUnwindFrame} */ 154 static DECLCALLBACK(int) 155 rtDbgModContainer_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 152 162 /** 153 163 * Fills in a RTDBGSYMBOL structure. … … 742 752 /*.pfnLineByAddr = */ rtDbgModContainer_LineByAddr, 743 753 754 /*.pfnUnwindFrame = */ rtDbgModContainer_UnwindFrame, 755 744 756 /*.u32EndMagic = */ RTDBGMODVTDBG_MAGIC 745 757 }; -
trunk/src/VBox/Runtime/common/dbg/dbgmoddbghelp.cpp
r69111 r73494 65 65 size_t cbPrevUtf16Alloc; 66 66 } RTDBGMODBGHELPARGS; 67 68 69 /** @interface_method_impl{RTDBGMODVTDBG,pfnUnwindFrame} */ 70 static 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 } 67 75 68 76 … … 499 507 /*.pfnLineByAddr = */ rtDbgModDbgHelp_LineByAddr, 500 508 509 /*.pfnUnwindFrame = */ rtDbgModDbgHelp_UnwindFrame, 510 501 511 /*.u32EndMagic = */ RTDBGMODVTDBG_MAGIC 502 512 }; -
trunk/src/VBox/Runtime/common/dbg/dbgmoddeferred.cpp
r73412 r73494 150 150 * 151 151 */ 152 153 /** @interface_method_impl{RTDBGMODVTDBG,pfnUnwindFrame} */ 154 static DECLCALLBACK(int) 155 rtDbgModDeferredDbg_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 } 152 163 153 164 … … 446 457 /*.pfnLineByAddr = */ rtDbgModDeferredDbg_LineByAddr, 447 458 459 /*.pfnUnwindFrame = */ rtDbgModDeferredDbg_UnwindFrame, 460 448 461 /*.u32EndMagic = */ RTDBGMODVTDBG_MAGIC 449 462 }; … … 459 472 * 460 473 */ 474 475 /** @interface_method_impl{RTDBGMODVTIMG,pfnUnwindFrame} */ 476 static DECLCALLBACK(int) 477 rtDbgModDeferredImg_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 461 486 462 487 /** @interface_method_impl{RTDBGMODVTIMG,pfnQueryProp} */ … … 638 663 /*.pfnGetArch = */ rtDbgModDeferredImg_GetArch, 639 664 /*.pfnQueryProp = */ rtDbgModDeferredImg_QueryProp, 665 /*.pfnUnwindFrame = */ rtDbgModDeferredImg_UnwindFrame, 640 666 641 667 /*.u32EndMagic = */ RTDBGMODVTIMG_MAGIC -
trunk/src/VBox/Runtime/common/dbg/dbgmoddwarf.cpp
r69111 r73494 4525 4525 4526 4526 4527 /** @interface_method_impl{RTDBGMODVTDBG,pfnUnwindFrame} */ 4528 static 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 4527 4535 /** @interface_method_impl{RTDBGMODVTDBG,pfnLineByAddr} */ 4528 4536 static DECLCALLBACK(int) rtDbgModDwarf_LineByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, … … 4968 4976 /*.pfnLineByAddr = */ rtDbgModDwarf_LineByAddr, 4969 4977 4978 /*.pfnUnwindFrame = */ rtDbgModDwarf_UnwindFrame, 4979 4970 4980 /*.u32EndMagic = */ RTDBGMODVTDBG_MAGIC 4971 4981 }; -
trunk/src/VBox/Runtime/common/dbg/dbgmodldr.cpp
r73412 r73494 61 61 typedef RTDBGMODLDR *PRTDBGMODLDR; 62 62 63 64 65 /** @interface_method_impl{RTDBGMODVTDBG,pfnUnwindFrame} */ 66 static 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 } 63 72 64 73 … … 241 250 /*.pfnGetArch = */ rtDbgModLdr_GetArch, 242 251 /*.pfnQueryProp = */ rtDbgModLdr_QueryProp, 252 /*.pfnUnwindFrame = */ rtDbgModLdr_UnwindFrame, 243 253 244 254 /*.u32EndMagic = */ RTDBGMODVTIMG_MAGIC -
trunk/src/VBox/Runtime/common/dbg/dbgmodnm.cpp
r69111 r73494 54 54 typedef RTDBGMODNM *PRTDBGMODNM; 55 55 56 57 58 /** @interface_method_impl{RTDBGMODVTDBG,pfnUnwindFrame} */ 59 static 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 } 56 64 57 65 … … 556 564 /*.pfnLineByAddr = */ rtDbgModNm_LineByAddr, 557 565 566 /*.pfnUnwindFrame = */ rtDbgModNm_UnwindFrame, 567 558 568 /*.u32EndMagic = */ RTDBGMODVTDBG_MAGIC 559 569 }; -
trunk/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h
r73099 r73494 1431 1431 NULL /*pfnVerifySignature*/, 1432 1432 NULL /*pfnHashImage*/, 1433 NULL /*pfnUnwindFrame*/, 1433 1434 42 1434 1435 }; -
trunk/src/VBox/Runtime/common/ldr/ldrEx.cpp
r73442 r73494 34 34 35 35 #include <iprt/assert.h> 36 #include <iprt/dbg.h> 36 37 #include <iprt/err.h> 37 38 #include <iprt/log.h> … … 708 709 709 710 711 RTDECL(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 } 728 RT_EXPORT_SYMBOL(RTLdrUnwindFrame); 729 730 710 731 /** 711 732 * Internal method used by the IPRT debug bits. -
trunk/src/VBox/Runtime/common/ldr/ldrNative.cpp
r69111 r73494 86 86 NULL, 87 87 NULL, 88 NULL /*pfnUnwindFrame*/, 88 89 42 89 90 }; -
trunk/src/VBox/Runtime/common/ldr/ldrPE.cpp
r73387 r73494 35 35 #include <iprt/assert.h> 36 36 #include <iprt/asm.h> 37 #include <iprt/dbg.h> 37 38 #include <iprt/err.h> 38 39 #include <iprt/log.h> … … 42 43 #include <iprt/sha.h> 43 44 #include <iprt/string.h> 45 #include <iprt/x86.h> 44 46 #ifndef IPRT_WITHOUT_LDR_VERIFY 45 47 #include <iprt/zero.h> … … 2908 2910 2909 2911 2910 /** @interface_method_impl{RTLDROPS,pfnHashImage} */ 2912 /** 2913 * @interface_method_impl{RTLDROPS,pfnHashImage} 2914 */ 2911 2915 static DECLCALLBACK(int) rtldrPE_HashImage(PRTLDRMODINTERNAL pMod, RTDIGESTTYPE enmDigest, char *pszDigest, size_t cbDigest) 2912 2916 { … … 2946 2950 } 2947 2951 } 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 */ 2964 DECLINLINE(PCIMAGE_RUNTIME_FUNCTION_ENTRY) 2965 rtldrPE_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 */ 2990 static 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 3057 static 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 */ 3347 static 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); 2948 3419 return rc; 2949 3420 } … … 3008 3479 rtldrPE_VerifySignature, 3009 3480 rtldrPE_HashImage, 3481 NULL /*pfnUnwindFrame*/, 3010 3482 42 3011 3483 }, … … 3042 3514 rtldrPE_VerifySignature, 3043 3515 rtldrPE_HashImage, 3516 rtldrPE_UnwindFrame, 3044 3517 42 3045 3518 }, -
trunk/src/VBox/Runtime/common/ldr/ldrkStuff.cpp
r73442 r73494 906 906 NULL, 907 907 NULL, 908 NULL /*pfnUnwindFrame*/, 908 909 42 909 910 }; -
trunk/src/VBox/Runtime/include/internal/dbgmod.h
r73412 r73494 243 243 DECLCALLBACKMEMBER(int, pfnQueryProp)(PRTDBGMODINT pMod, RTLDRPROP enmProp, void *pvBuf, size_t cbBuf, size_t *pcbRet); 244 244 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 245 264 /** For catching initialization errors (RTDBGMODVTIMG_MAGIC). */ 246 265 uint32_t u32EndMagic; … … 512 531 * number. 513 532 */ 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); 516 554 517 555 /** For catching initialization errors (RTDBGMODVTDBG_MAGIC). */ -
trunk/src/VBox/Runtime/include/internal/ldr.h
r73150 r73494 402 402 DECLCALLBACKMEMBER(int, pfnHashImage)(PRTLDRMODINTERNAL pMod, RTDIGESTTYPE enmDigest, char *pszDigest, size_t cbDigest); 403 403 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 404 426 /** Dummy entry to make sure we've initialized it all. */ 405 427 RTUINT uDummy;
Note:
See TracChangeset
for help on using the changeset viewer.