- Timestamp:
- Aug 2, 2018 10:53:28 AM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/DBGFStack.cpp
r73399 r73444 40 40 * Structures and Typedefs * 41 41 *********************************************************************************************************************************/ 42 /** Magic value for DBGFUNWINDSTATE::u32Magic (James Moody). */ 43 #define DBGFUNWINDSTATE_MAGIC UINT32_C(0x19250326) 44 /** Magic value for DBGFUNWINDSTATE::u32Magic after use. */ 45 #define DBGFUNWINDSTATE_MAGIC_DEAD UINT32_C(0x20101209) 46 47 /** 48 * Register state. 49 */ 50 typedef struct DBGFUNWINDSTATE 51 { 52 /** Structure magic (DBGFUNWINDSTATE_MAGIC) */ 53 uint32_t u32Magic; 54 /** The state architecture. */ 55 RTLDRARCH enmArch; 56 57 /** The program counter register. 58 * amd64/x86: RIP/EIP/IP 59 * sparc: PC 60 * arm32: PC / R15 61 */ 62 uint64_t uPc; 63 64 /** Return type. */ 65 DBGFRETRUNTYPE enmRetType; 66 67 /** Register state (see enmArch). */ 68 union 69 { 70 /** RTLDRARCH_AMD64, RTLDRARCH_X86_32 and RTLDRARCH_X86_16. */ 71 struct 72 { 73 /** General purpose registers indexed by X86_GREG_XXX. */ 74 uint64_t auRegs[16]; 75 /** The frame address. */ 76 RTFAR64 FrameAddr; 77 /** Set if we're in real or virtual 8086 mode. */ 78 bool fRealOrV86; 79 /** The flags register. */ 80 uint64_t uRFlags; 81 /** Trap error code. */ 82 uint64_t uErrCd; 83 /** Segment registers (indexed by X86_SREG_XXX). */ 84 uint16_t auSegs[6]; 85 86 /** Bitmap tracking register we've loaded and which content can possibly be trusted. */ 87 union 88 { 89 /** For effective clearing of the bits. */ 90 uint32_t fAll; 91 /** Detailed view. */ 92 struct 93 { 94 /** Bitmap indicating whether a GPR was loaded (parallel to auRegs). */ 95 uint16_t fRegs; 96 /** Bitmap indicating whether a segment register was loaded (parallel to auSegs). */ 97 uint8_t fSegs; 98 /** Set if uPc was loaded. */ 99 uint8_t fPc : 1; 100 /** Set if FrameAddr was loaded. */ 101 uint8_t fFrameAddr : 1; 102 /** Set if uRFlags was loaded. */ 103 uint8_t fRFlags : 1; 104 /** Set if uErrCd was loaded. */ 105 uint8_t fErrCd : 1; 106 } s; 107 } Loaded; 108 } x86; 109 110 /** @todo add ARM and others as needed. */ 111 } u; 112 113 /** 114 * Stack read callback. 115 * 116 * @returns IPRT status code. 117 * @param pThis Pointer to this structure. 118 * @param uSp The stack pointer address. 119 * @param cbToRead The number of bytes to read. 120 * @param pvDst Where to put the bytes we read. 121 */ 122 DECLCALLBACKMEMBER(int, pfnReadStack)(struct DBGFUNWINDSTATE *pThis, RTUINTPTR uSp, size_t cbToRead, void *pvDst); 123 /** User argument (usefule for pfnReadStack). */ 124 void *pvUser; 125 126 } DBGFUNWINDSTATE; 127 typedef struct DBGFUNWINDSTATE *PDBGFUNWINDSTATE; 128 typedef struct DBGFUNWINDSTATE const *PCDBGFUNWINDSTATE; 129 130 static DECLCALLBACK(int) dbgfR3StackReadCallback(PDBGFUNWINDSTATE pThis, RTUINTPTR uSp, size_t cbToRead, void *pvDst); 131 132 42 133 /** 43 134 * Unwind context. … … 53 144 RTDBGAS m_hAs; 54 145 55 uint64_t m_auRegs[16]; 56 uint64_t m_uPc; 57 uint64_t m_uRFlags; 58 uint16_t m_uCs; 59 uint16_t m_uSs; 146 DBGFUNWINDSTATE m_State; 60 147 61 148 RTDBGMOD m_hCached; … … 72 159 DBGFUNWINDCTX(PUVM pUVM, VMCPUID idCpu, PCCPUMCTX pInitialCtx, RTDBGAS hAs) 73 160 { 161 m_State.u32Magic = DBGFUNWINDSTATE_MAGIC; 162 m_State.enmArch = RTLDRARCH_AMD64; 163 m_State.pfnReadStack = dbgfR3StackReadCallback; 164 m_State.pvUser = this; 165 RT_ZERO(m_State.u); 74 166 if (pInitialCtx) 75 167 { 76 m_auRegs[X86_GREG_xAX] = pInitialCtx->rax; 77 m_auRegs[X86_GREG_xCX] = pInitialCtx->rcx; 78 m_auRegs[X86_GREG_xDX] = pInitialCtx->rdx; 79 m_auRegs[X86_GREG_xBX] = pInitialCtx->rbx; 80 m_auRegs[X86_GREG_xSP] = pInitialCtx->rsp; 81 m_auRegs[X86_GREG_xBP] = pInitialCtx->rbp; 82 m_auRegs[X86_GREG_xSI] = pInitialCtx->rsi; 83 m_auRegs[X86_GREG_xDI] = pInitialCtx->rdi; 84 m_auRegs[X86_GREG_x8 ] = pInitialCtx->r8; 85 m_auRegs[X86_GREG_x9 ] = pInitialCtx->r9; 86 m_auRegs[X86_GREG_x10] = pInitialCtx->r10; 87 m_auRegs[X86_GREG_x11] = pInitialCtx->r11; 88 m_auRegs[X86_GREG_x12] = pInitialCtx->r12; 89 m_auRegs[X86_GREG_x13] = pInitialCtx->r13; 90 m_auRegs[X86_GREG_x14] = pInitialCtx->r14; 91 m_auRegs[X86_GREG_x15] = pInitialCtx->r15; 92 m_uPc = pInitialCtx->rip; 93 m_uCs = pInitialCtx->cs.Sel; 94 m_uSs = pInitialCtx->ss.Sel; 95 m_uRFlags = pInitialCtx->rflags.u; 96 } 97 else 98 { 99 RT_BZERO(m_auRegs, sizeof(m_auRegs)); 100 m_uPc = 0; 101 m_uCs = 0; 102 m_uSs = 0; 103 m_uRFlags = 0; 168 m_State.u.x86.auRegs[X86_GREG_xAX] = pInitialCtx->rax; 169 m_State.u.x86.auRegs[X86_GREG_xCX] = pInitialCtx->rcx; 170 m_State.u.x86.auRegs[X86_GREG_xDX] = pInitialCtx->rdx; 171 m_State.u.x86.auRegs[X86_GREG_xBX] = pInitialCtx->rbx; 172 m_State.u.x86.auRegs[X86_GREG_xSP] = pInitialCtx->rsp; 173 m_State.u.x86.auRegs[X86_GREG_xBP] = pInitialCtx->rbp; 174 m_State.u.x86.auRegs[X86_GREG_xSI] = pInitialCtx->rsi; 175 m_State.u.x86.auRegs[X86_GREG_xDI] = pInitialCtx->rdi; 176 m_State.u.x86.auRegs[X86_GREG_x8 ] = pInitialCtx->r8; 177 m_State.u.x86.auRegs[X86_GREG_x9 ] = pInitialCtx->r9; 178 m_State.u.x86.auRegs[X86_GREG_x10] = pInitialCtx->r10; 179 m_State.u.x86.auRegs[X86_GREG_x11] = pInitialCtx->r11; 180 m_State.u.x86.auRegs[X86_GREG_x12] = pInitialCtx->r12; 181 m_State.u.x86.auRegs[X86_GREG_x13] = pInitialCtx->r13; 182 m_State.u.x86.auRegs[X86_GREG_x14] = pInitialCtx->r14; 183 m_State.u.x86.auRegs[X86_GREG_x15] = pInitialCtx->r15; 184 m_State.uPc = pInitialCtx->rip; 185 m_State.u.x86.uRFlags = pInitialCtx->rflags.u; 186 m_State.u.x86.auSegs[X86_SREG_ES] = pInitialCtx->es.Sel; 187 m_State.u.x86.auSegs[X86_SREG_CS] = pInitialCtx->cs.Sel; 188 m_State.u.x86.auSegs[X86_SREG_SS] = pInitialCtx->ss.Sel; 189 m_State.u.x86.auSegs[X86_SREG_DS] = pInitialCtx->ds.Sel; 190 m_State.u.x86.auSegs[X86_SREG_GS] = pInitialCtx->gs.Sel; 191 m_State.u.x86.auSegs[X86_SREG_FS] = pInitialCtx->fs.Sel; 192 m_State.u.x86.fRealOrV86 = CPUMIsGuestInRealOrV86ModeEx(pInitialCtx); 104 193 } 105 194 … … 154 243 155 244 /** 245 * @interface_method_impl{DBGFUNWINDSTATE,pfnReadStack} 246 */ 247 static DECLCALLBACK(int) dbgfR3StackReadCallback(PDBGFUNWINDSTATE pThis, RTUINTPTR uSp, size_t cbToRead, void *pvDst) 248 { 249 Assert( pThis->enmArch == RTLDRARCH_AMD64 250 || pThis->enmArch == RTLDRARCH_X86_32); 251 252 PDBGFUNWINDCTX pUnwindCtx = (PDBGFUNWINDCTX)pThis->pvUser; 253 DBGFADDRESS SrcAddr; 254 int rc = VINF_SUCCESS; 255 if ( pThis->enmArch == RTLDRARCH_X86_32 256 || pThis->enmArch == RTLDRARCH_X86_16) 257 { 258 if (!pThis->u.x86.fRealOrV86) 259 rc = DBGFR3AddrFromSelOff(pUnwindCtx->m_pUVM, pUnwindCtx->m_idCpu, &SrcAddr, pThis->u.x86.auSegs[X86_SREG_SS], uSp); 260 else 261 DBGFR3AddrFromFlat(pUnwindCtx->m_pUVM, &SrcAddr, uSp + ((uint32_t)pThis->u.x86.auSegs[X86_SREG_SS] << 4)); 262 } 263 else 264 DBGFR3AddrFromFlat(pUnwindCtx->m_pUVM, &SrcAddr, uSp); 265 if (RT_SUCCESS(rc)) 266 rc = DBGFR3MemRead(pUnwindCtx->m_pUVM, pUnwindCtx->m_idCpu, &SrcAddr, pvDst, cbToRead); 267 return rc; 268 } 269 270 271 /** 156 272 * Sets PC and SP. 157 273 * … … 163 279 static bool dbgfR3UnwindCtxSetPcAndSp(PDBGFUNWINDCTX pUnwindCtx, PCDBGFADDRESS pAddrPC, PCDBGFADDRESS pAddrStack) 164 280 { 281 Assert( pUnwindCtx->m_State.enmArch == RTLDRARCH_AMD64 282 || pUnwindCtx->m_State.enmArch == RTLDRARCH_X86_32); 283 165 284 if (!DBGFADDRESS_IS_FAR(pAddrPC)) 166 pUnwindCtx->m_ uPc = pAddrPC->FlatPtr;285 pUnwindCtx->m_State.uPc = pAddrPC->FlatPtr; 167 286 else 168 287 { 169 pUnwindCtx->m_ uPc= pAddrPC->off;170 pUnwindCtx->m_ uCs= pAddrPC->Sel;288 pUnwindCtx->m_State.uPc = pAddrPC->off; 289 pUnwindCtx->m_State.u.x86.auSegs[X86_SREG_CS] = pAddrPC->Sel; 171 290 } 172 291 if (!DBGFADDRESS_IS_FAR(pAddrStack)) 173 pUnwindCtx->m_ auRegs[X86_GREG_xSP] = pAddrStack->FlatPtr;292 pUnwindCtx->m_State.u.x86.auRegs[X86_GREG_xSP] = pAddrStack->FlatPtr; 174 293 else 175 294 { 176 pUnwindCtx->m_ auRegs[X86_GREG_xSP] = pAddrStack->off;177 pUnwindCtx->m_ uSs= pAddrStack->Sel;295 pUnwindCtx->m_State.u.x86.auRegs[X86_GREG_xSP] = pAddrStack->off; 296 pUnwindCtx->m_State.u.x86.auSegs[X86_SREG_SS] = pAddrStack->Sel; 178 297 } 179 298 return true; … … 184 303 * Try read a 16-bit value off the stack. 185 304 * 305 * @returns pfnReadStack result. 186 306 * @param pUnwindCtx The unwind context. 187 307 * @param uSrcAddr The stack address. 188 308 * @param puDst The read destination. 189 309 */ 190 static void dbgfR3UnwindCtxLoadU16(PDBGFUNWINDCTX pUnwindCtx, uint64_t uSrcAddr, uint16_t *puDst) 191 { 192 DBGFADDRESS SrcAddr; 193 DBGFR3MemRead(pUnwindCtx->m_pUVM, pUnwindCtx->m_idCpu, 194 DBGFR3AddrFromFlat(pUnwindCtx->m_pUVM, &SrcAddr, uSrcAddr), 195 puDst, sizeof(*puDst)); 310 DECLINLINE(int) dbgUnwindLoadStackU16(PDBGFUNWINDSTATE pThis, uint64_t uSrcAddr, uint16_t *puDst) 311 { 312 return pThis->pfnReadStack(pThis, uSrcAddr, sizeof(*puDst), puDst); 196 313 } 197 314 … … 200 317 * Try read a 64-bit value off the stack. 201 318 * 319 * @returns pfnReadStack result. 202 320 * @param pUnwindCtx The unwind context. 203 321 * @param uSrcAddr The stack address. 204 322 * @param puDst The read destination. 205 323 */ 206 static void dbgfR3UnwindCtxLoadU64(PDBGFUNWINDCTX pUnwindCtx, uint64_t uSrcAddr, uint64_t *puDst) 207 { 208 DBGFADDRESS SrcAddr; 209 DBGFR3MemRead(pUnwindCtx->m_pUVM, pUnwindCtx->m_idCpu, 210 DBGFR3AddrFromFlat(pUnwindCtx->m_pUVM, &SrcAddr, uSrcAddr), 211 puDst, sizeof(*puDst)); 324 DECLINLINE(int) dbgUnwindLoadStackU64(PDBGFUNWINDSTATE pThis, uint64_t uSrcAddr, uint64_t *puDst) 325 { 326 return pThis->pfnReadStack(pThis, uSrcAddr, sizeof(*puDst), puDst); 212 327 } 213 328 … … 217 332 * 218 333 * @returns RVA of unwind info on success, UINT32_MAX on failure. 219 * @param paFunctions The table to lookup @a offFunctionRva in.334 * @param paFunctions The table to lookup @a uRva in. 220 335 * @param iEnd Size of the table. 221 336 * @param uRva The RVA of the function we want. … … 244 359 * 245 360 * @returns true. 246 * @param p UnwindCtx The unwind context.361 * @param pThis The unwind state being worked. 247 362 * @param fErrCd Non-zero if there is an error code on the stack. 248 * @param pAddrFrame Where to return the frame pointer. 249 * @param penmRetType Where to return the return type. 250 */ 251 static bool dbgfR3UnwindCtxDoOneIRet(PDBGFUNWINDCTX pUnwindCtx, uint8_t fErrCd, 252 PDBGFADDRESS pAddrFrame, DBGFRETURNTYPE *penmRetType) 363 */ 364 static bool dbgUnwindPeAmd64DoOneIRet(PDBGFUNWINDSTATE pThis, uint8_t fErrCd) 253 365 { 254 366 Assert(fErrCd <= 1); 255 if (fErrCd) 256 pUnwindCtx->m_auRegs[X86_GREG_xSP] += 8; /* error code */ 257 258 *penmRetType = DBGFRETURNTYPE_IRET64; 259 DBGFR3AddrFromFlat(pUnwindCtx->m_pUVM, pAddrFrame, 260 pUnwindCtx->m_auRegs[X86_GREG_xSP] - /* pretend rbp is pushed on the stack */ 8); 261 262 dbgfR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_auRegs[X86_GREG_xSP], &pUnwindCtx->m_uPc); 263 pUnwindCtx->m_auRegs[X86_GREG_xSP] += 8; /* RIP */ 264 265 dbgfR3UnwindCtxLoadU16(pUnwindCtx, pUnwindCtx->m_auRegs[X86_GREG_xSP], &pUnwindCtx->m_uCs); 266 pUnwindCtx->m_auRegs[X86_GREG_xSP] += 8; /* CS */ 267 268 dbgfR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_auRegs[X86_GREG_xSP], &pUnwindCtx->m_uRFlags); 269 pUnwindCtx->m_auRegs[X86_GREG_xSP] += 8; /* EFLAGS */ 270 271 uint64_t uNewRsp = (pUnwindCtx->m_auRegs[X86_GREG_xSP] - 8) & ~(uint64_t)15; 272 dbgfR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_auRegs[X86_GREG_xSP], &uNewRsp); 273 pUnwindCtx->m_auRegs[X86_GREG_xSP] += 8; /* RSP */ 274 275 dbgfR3UnwindCtxLoadU16(pUnwindCtx, pUnwindCtx->m_auRegs[X86_GREG_xSP], &pUnwindCtx->m_uSs); 276 pUnwindCtx->m_auRegs[X86_GREG_xSP] += 8; /* SS */ 277 278 pUnwindCtx->m_auRegs[X86_GREG_xSP] = uNewRsp; 367 if (!fErrCd) 368 pThis->u.x86.Loaded.s.fErrCd = 0; 369 else 370 { 371 pThis->u.x86.uErrCd = 0; 372 pThis->u.x86.Loaded.s.fErrCd = 1; 373 dbgUnwindLoadStackU64(pThis, pThis->u.x86.auRegs[X86_GREG_xSP], &pThis->u.x86.uErrCd); 374 pThis->u.x86.auRegs[X86_GREG_xSP] += 8; 375 } 376 377 pThis->enmRetType = DBGFRETURNTYPE_IRET64; 378 pThis->u.x86.FrameAddr.off = pThis->u.x86.auRegs[X86_GREG_xSP] - /* pretend rbp is pushed on the stack */ 8; 379 pThis->u.x86.FrameAddr.sel = pThis->u.x86.auSegs[X86_SREG_SS]; 380 381 dbgUnwindLoadStackU64(pThis, pThis->u.x86.auRegs[X86_GREG_xSP], &pThis->uPc); 382 pThis->u.x86.auRegs[X86_GREG_xSP] += 8; /* RIP */ 383 384 dbgUnwindLoadStackU16(pThis, pThis->u.x86.auRegs[X86_GREG_xSP], &pThis->u.x86.auSegs[X86_SREG_CS]); 385 pThis->u.x86.auRegs[X86_GREG_xSP] += 8; /* CS */ 386 387 dbgUnwindLoadStackU64(pThis, pThis->u.x86.auRegs[X86_GREG_xSP], &pThis->u.x86.uRFlags); 388 pThis->u.x86.auRegs[X86_GREG_xSP] += 8; /* EFLAGS */ 389 390 uint64_t uNewRsp = (pThis->u.x86.auRegs[X86_GREG_xSP] - 8) & ~(uint64_t)15; 391 dbgUnwindLoadStackU64(pThis, pThis->u.x86.auRegs[X86_GREG_xSP], &uNewRsp); 392 pThis->u.x86.auRegs[X86_GREG_xSP] += 8; /* RSP */ 393 394 dbgUnwindLoadStackU16(pThis, pThis->u.x86.auRegs[X86_GREG_xSP], &pThis->u.x86.auSegs[X86_SREG_SS]); 395 pThis->u.x86.auRegs[X86_GREG_xSP] += 8; /* SS */ 396 397 pThis->u.x86.auRegs[X86_GREG_xSP] = uNewRsp; 398 399 pThis->u.x86.Loaded.s.fRegs |= RT_BIT(X86_GREG_xSP); 400 pThis->u.x86.Loaded.s.fSegs |= RT_BIT(X86_SREG_CS) | RT_BIT(X86_SREG_SS); 401 pThis->u.x86.Loaded.s.fPc = 1; 402 pThis->u.x86.Loaded.s.fFrameAddr = 1; 403 pThis->u.x86.Loaded.s.fRFlags = 1; 279 404 return true; 280 405 } … … 285 410 * 286 411 * @returns true on success, false on failure. 287 * @param pUnwindCtx The unwind context. 412 * @param hMod The debug module to retrieve unwind info from. 413 * @param paFunctions The table to lookup @a uRvaRip in. 414 * @param cFunctions Size of the lookup table. 288 415 * @param uRvaRip The RVA of the RIP. 289 * @param pAddrFrame Where to return the frame pointer.290 * @ param penmRetType Where to return the return type.291 */ 292 static bool dbg fR3UnwindCtxDoOneFrameCached(PDBGFUNWINDCTX pUnwindCtx, uint32_t uRvaRip,293 PDBGFADDRESS pAddrFrame, DBGFRETURNTYPE *penmRetType)416 * 417 * @todo Move this down to IPRT in the ldrPE.cpp / dbgmodcodeview.cpp area. 418 */ 419 static bool dbgUnwindPeAmd64DoOne(RTDBGMOD hMod, PCIMAGE_RUNTIME_FUNCTION_ENTRY paFunctions, size_t cFunctions, 420 PDBGFUNWINDSTATE pThis, uint32_t uRvaRip) 294 421 { 295 422 /* 296 423 * Lookup the unwind info RVA and try read it. 297 424 */ 298 PCIMAGE_RUNTIME_FUNCTION_ENTRY pEntry = dbgfR3UnwindCtxLookupUnwindInfoRva(pUnwindCtx->m_paFunctions, 299 pUnwindCtx->m_cFunctions, uRvaRip); 425 PCIMAGE_RUNTIME_FUNCTION_ENTRY pEntry = dbgfR3UnwindCtxLookupUnwindInfoRva(paFunctions, cFunctions, uRvaRip); 300 426 if (pEntry) 301 427 { … … 322 448 uBuf.uRva = pEntry->UnwindInfoAddress; 323 449 size_t cbBuf = sizeof(uBuf); 324 int rc = RTDbgModImageQueryProp( pUnwindCtx->m_hCached, RTLDRPROP_UNWIND_INFO, &uBuf, cbBuf, &cbBuf);450 int rc = RTDbgModImageQueryProp(hMod, RTLDRPROP_UNWIND_INFO, &uBuf, cbBuf, &cbBuf); 325 451 if (RT_FAILURE(rc)) 326 452 return false; … … 402 528 { 403 529 Assert(pInfo->aOpcodes[iOpcode].u.CodeOffset <= offPc); 404 switch (pInfo->aOpcodes[iOpcode].u.UnwindOp) 530 uint8_t const uOpInfo = pInfo->aOpcodes[iOpcode].u.OpInfo; 531 uint8_t const uUnwindOp = pInfo->aOpcodes[iOpcode].u.UnwindOp; 532 switch (uUnwindOp) 405 533 { 406 534 case IMAGE_AMD64_UWOP_PUSH_NONVOL: 407 p UnwindCtx->m_auRegs[X86_GREG_xSP] += 8;408 dbg fR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_auRegs[X86_GREG_xSP],409 &pUnwindCtx->m_auRegs[pInfo->aOpcodes[iOpcode].u.OpInfo]);535 pThis->u.x86.auRegs[X86_GREG_xSP] += 8; 536 dbgUnwindLoadStackU64(pThis, pThis->u.x86.auRegs[X86_GREG_xSP], &pThis->u.x86.auRegs[uOpInfo]); 537 pThis->u.x86.Loaded.s.fRegs |= RT_BIT(uOpInfo); 410 538 iOpcode++; 411 539 break; 412 540 413 541 case IMAGE_AMD64_UWOP_ALLOC_LARGE: 414 if ( pInfo->aOpcodes[iOpcode].u.OpInfo == 0)542 if (uOpInfo == 0) 415 543 { 416 544 iOpcode += 2; 417 545 AssertBreak(iOpcode <= cOpcodes); 418 p UnwindCtx->m_auRegs[X86_GREG_xSP] += pInfo->aOpcodes[iOpcode - 1].FrameOffset * 8;546 pThis->u.x86.auRegs[X86_GREG_xSP] += pInfo->aOpcodes[iOpcode - 1].FrameOffset * 8; 419 547 } 420 548 else … … 422 550 iOpcode += 3; 423 551 AssertBreak(iOpcode <= cOpcodes); 424 p UnwindCtx->m_auRegs[X86_GREG_xSP] += RT_MAKE_U32(pInfo->aOpcodes[iOpcode - 2].FrameOffset,552 pThis->u.x86.auRegs[X86_GREG_xSP] += RT_MAKE_U32(pInfo->aOpcodes[iOpcode - 2].FrameOffset, 425 553 pInfo->aOpcodes[iOpcode - 1].FrameOffset); 426 554 } … … 429 557 case IMAGE_AMD64_UWOP_ALLOC_SMALL: 430 558 AssertBreak(iOpcode <= cOpcodes); 431 p UnwindCtx->m_auRegs[X86_GREG_xSP] += pInfo->aOpcodes[iOpcode].u.OpInfo * 8 + 8;559 pThis->u.x86.auRegs[X86_GREG_xSP] += uOpInfo * 8 + 8; 432 560 iOpcode++; 433 561 break; 434 562 435 563 case IMAGE_AMD64_UWOP_SET_FPREG: 436 iFrameReg = pInfo->aOpcodes[iOpcode].u.OpInfo;564 iFrameReg = uOpInfo; 437 565 offFrameReg = pInfo->FrameOffset * 16; 438 566 iOpcode++; … … 442 570 case IMAGE_AMD64_UWOP_SAVE_NONVOL_FAR: 443 571 { 444 bool const fFar = pInfo->aOpcodes[iOpcode].u.UnwindOp == IMAGE_AMD64_UWOP_SAVE_NONVOL_FAR; 445 unsigned const iGreg = pInfo->aOpcodes[iOpcode].u.OpInfo; 446 uint32_t off = 0; 572 uint32_t off = 0; 447 573 iOpcode++; 448 574 if (iOpcode < cOpcodes) … … 450 576 off = pInfo->aOpcodes[iOpcode].FrameOffset; 451 577 iOpcode++; 452 if ( fFar&& iOpcode < cOpcodes)578 if (uUnwindOp == IMAGE_AMD64_UWOP_SAVE_NONVOL_FAR && iOpcode < cOpcodes) 453 579 { 454 580 off |= (uint32_t)pInfo->aOpcodes[iOpcode].FrameOffset << 16; … … 457 583 } 458 584 off *= 8; 459 dbgfR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_auRegs[X86_GREG_xSP] + off, &pUnwindCtx->m_auRegs[iGreg]); 585 dbgUnwindLoadStackU64(pThis, pThis->u.x86.auRegs[X86_GREG_xSP] + off, &pThis->u.x86.auRegs[uOpInfo]); 586 pThis->u.x86.Loaded.s.fRegs |= RT_BIT(uOpInfo); 460 587 break; 461 588 } … … 470 597 471 598 case IMAGE_AMD64_UWOP_PUSH_MACHFRAME: 472 return dbg fR3UnwindCtxDoOneIRet(pUnwindCtx, pInfo->aOpcodes[iOpcode].u.OpInfo, pAddrFrame, penmRetType);599 return dbgUnwindPeAmd64DoOneIRet(pThis, uOpInfo); 473 600 474 601 case IMAGE_AMD64_UWOP_EPILOG: … … 480 607 481 608 default: 482 AssertMsgFailedReturn(("%u\n", pInfo->aOpcodes[iOpcode].u.UnwindOp), false);609 AssertMsgFailedReturn(("%u\n", uUnwindOp), false); 483 610 } 484 611 } … … 495 622 while (iOpcode < cOpcodes) 496 623 { 497 switch (pInfo->aOpcodes[iOpcode].u.UnwindOp) 624 uint8_t const uOpInfo = pInfo->aOpcodes[iOpcode].u.OpInfo; 625 uint8_t const uUnwindOp = pInfo->aOpcodes[iOpcode].u.UnwindOp; 626 switch (uUnwindOp) 498 627 { 499 628 case IMAGE_AMD64_UWOP_PUSH_NONVOL: 500 p UnwindCtx->m_auRegs[X86_GREG_xSP] += 8;629 pThis->u.x86.auRegs[X86_GREG_xSP] += 8; 501 630 if (offEpilog == 0) 502 dbgfR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_auRegs[X86_GREG_xSP], 503 &pUnwindCtx->m_auRegs[pInfo->aOpcodes[iOpcode].u.OpInfo]); 631 { 632 dbgUnwindLoadStackU64(pThis, pThis->u.x86.auRegs[X86_GREG_xSP], &pThis->u.x86.auRegs[uOpInfo]); 633 pThis->u.x86.Loaded.s.fRegs |= RT_BIT(uOpInfo); 634 } 504 635 else 505 636 { 506 637 /* Decrement offEpilog by estimated POP instruction length. */ 507 638 offEpilog -= 1; 508 if (offEpilog > 0 && pInfo->aOpcodes[iOpcode].u.OpInfo >= 8)639 if (offEpilog > 0 && uOpInfo >= 8) 509 640 offEpilog -= 1; 510 641 } … … 513 644 514 645 case IMAGE_AMD64_UWOP_PUSH_MACHFRAME: /* Must terminate an epilog, so always execute this. */ 515 return dbg fR3UnwindCtxDoOneIRet(pUnwindCtx, pInfo->aOpcodes[iOpcode].u.OpInfo, pAddrFrame, penmRetType);646 return dbgUnwindPeAmd64DoOneIRet(pThis, uOpInfo); 516 647 517 648 case IMAGE_AMD64_UWOP_ALLOC_SMALL: … … 531 662 532 663 default: 533 AssertMsgFailedReturn(("%u\n", pInfo->aOpcodes[iOpcode].u.UnwindOp), false);664 AssertMsgFailedReturn(("%u\n", uUnwindOp), false); 534 665 } 535 666 } … … 549 680 * RSP should now give us the return address, so perform a RET. 550 681 */ 551 *penmRetType = DBGFRETURNTYPE_NEAR64; 552 DBGFR3AddrFromFlat(pUnwindCtx->m_pUVM, pAddrFrame, 553 pUnwindCtx->m_auRegs[X86_GREG_xSP] - /* pretend rbp is pushed on the stack */ 8); 554 555 dbgfR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_auRegs[X86_GREG_xSP], &pUnwindCtx->m_uPc); 556 pUnwindCtx->m_auRegs[X86_GREG_xSP] += 8; 682 pThis->enmRetType = DBGFRETURNTYPE_NEAR64; 683 684 pThis->u.x86.FrameAddr.off = pThis->u.x86.auRegs[X86_GREG_xSP] - /* pretend rbp is pushed on the stack */ 8; 685 pThis->u.x86.FrameAddr.sel = pThis->u.x86.auSegs[X86_SREG_SS]; 686 pThis->u.x86.Loaded.s.fFrameAddr = 1; 687 688 dbgUnwindLoadStackU64(pThis, pThis->u.x86.auRegs[X86_GREG_xSP], &pThis->uPc); 689 pThis->u.x86.auRegs[X86_GREG_xSP] += 8; 690 pThis->u.x86.Loaded.s.fPc = 1; 557 691 return true; 558 692 } 559 693 560 RT_NOREF_PV(pAddrFrame);561 694 return false; 562 695 } … … 568 701 * @returns true on success, false on failure. 569 702 * @param pUnwindCtx The unwind context. 570 * @param pAddrFrame Where to return the frame pointer. 571 * @param penmRetType Where to return the return type. 572 */ 573 static bool dbgfR3UnwindCtxDoOneFrame(PDBGFUNWINDCTX pUnwindCtx, PDBGFADDRESS pAddrFrame, DBGFRETURNTYPE *penmRetType) 703 */ 704 static bool dbgfR3UnwindCtxDoOneFrame(PDBGFUNWINDCTX pUnwindCtx) 574 705 { 575 706 /* 576 707 * Hope for the same module as last time around. 577 708 */ 578 RTUINTPTR offCache = pUnwindCtx->m_ uPc - pUnwindCtx->m_uCachedMapping;709 RTUINTPTR offCache = pUnwindCtx->m_State.uPc - pUnwindCtx->m_uCachedMapping; 579 710 if (offCache < pUnwindCtx->m_cbCachedMapping) 580 return dbgfR3UnwindCtxDoOneFrameCached(pUnwindCtx, offCache, pAddrFrame, penmRetType); 711 return dbgUnwindPeAmd64DoOne(pUnwindCtx->m_hCached, pUnwindCtx->m_paFunctions, pUnwindCtx->m_cFunctions, 712 &pUnwindCtx->m_State, offCache); 581 713 582 714 /* … … 586 718 RTUINTPTR uBase = 0; 587 719 RTDBGSEGIDX idxSeg = NIL_RTDBGSEGIDX; 588 int rc = RTDbgAsModuleByAddr(pUnwindCtx->m_hAs, pUnwindCtx->m_ uPc, &hDbgMod, &uBase, &idxSeg);720 int rc = RTDbgAsModuleByAddr(pUnwindCtx->m_hAs, pUnwindCtx->m_State.uPc, &hDbgMod, &uBase, &idxSeg); 589 721 if (RT_SUCCESS(rc)) 590 722 { … … 622 754 pUnwindCtx->m_cFunctions = cbNeeded / sizeof(*pUnwindCtx->m_paFunctions); 623 755 624 return dbg fR3UnwindCtxDoOneFrameCached(pUnwindCtx, pUnwindCtx->m_uPc - pUnwindCtx->m_uCachedMapping,625 pAddrFrame, penmRetType);756 return dbgUnwindPeAmd64DoOne(pUnwindCtx->m_hCached, pUnwindCtx->m_paFunctions, pUnwindCtx->m_cFunctions, 757 &pUnwindCtx->m_State, pUnwindCtx->m_State.uPc - pUnwindCtx->m_uCachedMapping); 626 758 } 627 759 RTMemFree(pvBuf); … … 659 791 *pcbRead = cb; 660 792 return rc; 793 } 794 795 static int dbgfR3StackWalkCollectRegisterChanges(PUVM pUVM, PDBGFSTACKFRAME pFrame, PDBGFUNWINDSTATE pState) 796 { 797 pFrame->cSureRegs = 0; 798 pFrame->paSureRegs = NULL; 799 800 if ( pState->enmArch == RTLDRARCH_AMD64 801 || pState->enmArch == RTLDRARCH_X86_32 802 || pState->enmArch == RTLDRARCH_X86_16) 803 { 804 if (pState->u.x86.Loaded.fAll) 805 { 806 /* 807 * Count relevant registers. 808 */ 809 uint32_t cRegs = 0; 810 if (pState->u.x86.Loaded.s.fRegs) 811 for (uint32_t f = 1; f < RT_BIT_32(RT_ELEMENTS(pState->u.x86.auRegs)); f <<= 1) 812 if (pState->u.x86.Loaded.s.fRegs & f) 813 cRegs++; 814 if (pState->u.x86.Loaded.s.fSegs) 815 for (uint32_t f = 1; f < RT_BIT_32(RT_ELEMENTS(pState->u.x86.auSegs)); f <<= 1) 816 if (pState->u.x86.Loaded.s.fSegs & f) 817 cRegs++; 818 if (pState->u.x86.Loaded.s.fRFlags) 819 cRegs++; 820 if (pState->u.x86.Loaded.s.fErrCd) 821 cRegs++; 822 if (cRegs > 0) 823 { 824 /* 825 * Allocate the arrays. 826 */ 827 PDBGFREGVALEX paSureRegs = (PDBGFREGVALEX)MMR3HeapAllocZU(pUVM, MM_TAG_DBGF_STACK, sizeof(DBGFREGVALEX) * cRegs); 828 AssertReturn(paSureRegs, VERR_NO_MEMORY); 829 pFrame->paSureRegs = paSureRegs; 830 pFrame->cSureRegs = cRegs; 831 832 /* 833 * Popuplate the arrays. 834 */ 835 uint32_t iReg = 0; 836 if (pState->u.x86.Loaded.s.fRegs) 837 for (uint32_t i = 1; i < RT_ELEMENTS(pState->u.x86.auRegs); i++) 838 if (pState->u.x86.Loaded.s.fRegs & RT_BIT(i)) 839 { 840 paSureRegs[iReg].Value.u64 = pState->u.x86.auRegs[i]; 841 paSureRegs[iReg].enmType = DBGFREGVALTYPE_U64; 842 paSureRegs[iReg].enmReg = (DBGFREG)(DBGFREG_RAX + i); 843 iReg++; 844 } 845 846 if (pState->u.x86.Loaded.s.fSegs) 847 for (uint32_t i = 1; i < RT_ELEMENTS(pState->u.x86.auSegs); i++) 848 if (pState->u.x86.Loaded.s.fSegs & RT_BIT(i)) 849 { 850 paSureRegs[iReg].Value.u16 = pState->u.x86.auSegs[i]; 851 paSureRegs[iReg].enmType = DBGFREGVALTYPE_U16; 852 switch (i) 853 { 854 case X86_SREG_ES: paSureRegs[iReg].enmReg = DBGFREG_ES; break; 855 case X86_SREG_CS: paSureRegs[iReg].enmReg = DBGFREG_CS; break; 856 case X86_SREG_SS: paSureRegs[iReg].enmReg = DBGFREG_SS; break; 857 case X86_SREG_DS: paSureRegs[iReg].enmReg = DBGFREG_DS; break; 858 case X86_SREG_FS: paSureRegs[iReg].enmReg = DBGFREG_FS; break; 859 case X86_SREG_GS: paSureRegs[iReg].enmReg = DBGFREG_GS; break; 860 default: AssertFailedBreak(); 861 } 862 iReg++; 863 } 864 865 if (iReg < cRegs) 866 { 867 if (pState->u.x86.Loaded.s.fRFlags) 868 { 869 paSureRegs[iReg].Value.u64 = pState->u.x86.uRFlags; 870 paSureRegs[iReg].enmType = DBGFREGVALTYPE_U64; 871 paSureRegs[iReg].enmReg = DBGFREG_RFLAGS; 872 iReg++; 873 } 874 if (pState->u.x86.Loaded.s.fErrCd) 875 { 876 paSureRegs[iReg].Value.u64 = pState->u.x86.uErrCd; 877 paSureRegs[iReg].enmType = DBGFREGVALTYPE_U64; 878 paSureRegs[iReg].enmReg = DBGFREG_END; 879 paSureRegs[iReg].pszName = "trap-errcd"; 880 iReg++; 881 } 882 } 883 Assert(iReg == cRegs); 884 } 885 } 886 } 887 888 return VINF_SUCCESS; 661 889 } 662 890 … … 707 935 pFrame->enmReturnFrameReturnType = DBGFRETURNTYPE_INVALID; 708 936 } 937 } 938 } 939 940 /* 941 * Enagage the OS layer and collect register changes. 942 */ 943 if (pFrame->fFlags & DBGFSTACKFRAME_FLAGS_USED_UNWIND_INFO) 944 { 945 /** @todo engage the OS buggers to identify trap frames and update unwindctx accordingly. */ 946 if (!fFirst) 947 { 948 int rc = dbgfR3StackWalkCollectRegisterChanges(pUnwindCtx->m_pUVM, pFrame, &pUnwindCtx->m_State); 949 if (RT_FAILURE(rc)) 950 return rc; 709 951 } 710 952 } … … 784 1026 || pFrame->enmReturnType == DBGFRETURNTYPE_IRET64) 785 1027 DBGFR3AddrFromSelOff(pUnwindCtx->m_pUVM, pUnwindCtx->m_idCpu, &pFrame->AddrReturnFrame, 786 pUnwindCtx->m_ uSs, pUnwindCtx->m_auRegs[X86_GREG_xBP]);1028 pUnwindCtx->m_State.u.x86.auSegs[X86_SREG_SS], pUnwindCtx->m_State.u.x86.auRegs[X86_GREG_xBP]); 787 1029 else if (pFrame->enmReturnType == DBGFRETURNTYPE_IRET32_V86) 788 1030 DBGFR3AddrFromFlat(pUnwindCtx->m_pUVM, &pFrame->AddrReturnFrame, 789 ((uint32_t)pUnwindCtx->m_uSs << 4) + pUnwindCtx->m_auRegs[X86_GREG_xBP]); 1031 ((uint32_t)pUnwindCtx->m_State.u.x86.auSegs[X86_SREG_SS] << 4) 1032 + pUnwindCtx->m_State.u.x86.auRegs[X86_GREG_xBP]); 790 1033 else 791 1034 { 792 pFrame->AddrReturnFrame.off = pUnwindCtx->m_ auRegs[X86_GREG_xBP];1035 pFrame->AddrReturnFrame.off = pUnwindCtx->m_State.u.x86.auRegs[X86_GREG_xBP]; 793 1036 pFrame->AddrReturnFrame.FlatPtr += pFrame->AddrReturnFrame.off - pFrame->AddrFrame.off; 794 1037 } … … 853 1096 || pFrame->enmReturnType == DBGFRETURNTYPE_IRET64) 854 1097 DBGFR3AddrFromSelOff(pUnwindCtx->m_pUVM, pUnwindCtx->m_idCpu, &pFrame->AddrReturnStack, 855 pUnwindCtx->m_ uSs, pUnwindCtx->m_auRegs[X86_GREG_xSP]);1098 pUnwindCtx->m_State.u.x86.auSegs[X86_SREG_SS], pUnwindCtx->m_State.u.x86.auRegs[X86_GREG_xSP]); 856 1099 else if (pFrame->enmReturnType == DBGFRETURNTYPE_IRET32_V86) 857 1100 DBGFR3AddrFromFlat(pUnwindCtx->m_pUVM, &pFrame->AddrReturnStack, 858 ((uint32_t)pUnwindCtx->m_uSs << 4) + pUnwindCtx->m_auRegs[X86_GREG_xSP]); 1101 ((uint32_t)pUnwindCtx->m_State.u.x86.auSegs[X86_SREG_SS] << 4) 1102 + pUnwindCtx->m_State.u.x86.auRegs[X86_GREG_xSP]); 859 1103 else 860 1104 { 861 pFrame->AddrReturnStack.off = pUnwindCtx->m_ auRegs[X86_GREG_xSP];1105 pFrame->AddrReturnStack.off = pUnwindCtx->m_State.u.x86.auRegs[X86_GREG_xSP]; 862 1106 pFrame->AddrReturnStack.FlatPtr += pFrame->AddrReturnStack.off - pFrame->AddrStack.off; 863 1107 } … … 877 1121 if (DBGFReturnTypeIsNear(pFrame->enmReturnType)) 878 1122 { 879 pFrame->AddrReturnPC.off = pUnwindCtx->m_ uPc;1123 pFrame->AddrReturnPC.off = pUnwindCtx->m_State.uPc; 880 1124 pFrame->AddrReturnPC.FlatPtr += pFrame->AddrReturnPC.off - pFrame->AddrPC.off; 881 1125 } 882 1126 else 883 1127 DBGFR3AddrFromSelOff(pUnwindCtx->m_pUVM, pUnwindCtx->m_idCpu, &pFrame->AddrReturnPC, 884 pUnwindCtx->m_ uCs, pUnwindCtx->m_uPc);1128 pUnwindCtx->m_State.u.x86.auSegs[X86_SREG_CS], pUnwindCtx->m_State.uPc); 885 1129 } 886 1130 else … … 983 1227 } 984 1228 /** @todo Reevaluate CS if the previous frame return type isn't near. */ 985 986 DBGFADDRESS AddrReturnFrame = pFrame->AddrReturnFrame; 987 DBGFRETURNTYPE enmReturnType = pFrame->enmReturnType; 988 if (dbgfR3UnwindCtxDoOneFrame(pUnwindCtx, &AddrReturnFrame, &enmReturnType)) 989 { 1229 if ( pUnwindCtx->m_State.enmArch == RTLDRARCH_AMD64 1230 || pUnwindCtx->m_State.enmArch == RTLDRARCH_X86_32 1231 || pUnwindCtx->m_State.enmArch == RTLDRARCH_X86_16) 1232 pUnwindCtx->m_State.u.x86.Loaded.fAll = 0; 1233 else 1234 AssertFailed(); 1235 if (dbgfR3UnwindCtxDoOneFrame(pUnwindCtx)) 1236 { 1237 DBGFADDRESS AddrReturnFrame = pFrame->AddrReturnFrame; 1238 int rc = DBGFR3AddrFromSelOff(pUnwindCtx->m_pUVM, pUnwindCtx->m_idCpu, &AddrReturnFrame, 1239 pUnwindCtx->m_State.u.x86.FrameAddr.sel, pUnwindCtx->m_State.u.x86.FrameAddr.off); 1240 if (RT_SUCCESS(rc)) 1241 pFrame->AddrReturnFrame = AddrReturnFrame; 1242 pFrame->enmReturnFrameReturnType = pUnwindCtx->m_State.enmRetType; 990 1243 pFrame->fFlags |= DBGFSTACKFRAME_FLAGS_UNWIND_INFO_RET; 991 pFrame->AddrReturnFrame = AddrReturnFrame;992 pFrame->enmReturnFrameReturnType = enmReturnType;993 1244 } 994 1245 } … … 1094 1345 else if ( RT_SUCCESS(rc) 1095 1346 && dbgfR3UnwindCtxSetPcAndSp(&UnwindCtx, &pCur->AddrPC, &pCur->AddrStack) 1096 && dbgfR3UnwindCtxDoOneFrame(&UnwindCtx, &pCur->AddrFrame, &pCur->enmReturnType)) 1097 { 1347 && dbgfR3UnwindCtxDoOneFrame(&UnwindCtx)) 1348 { 1349 pCur->enmReturnType = UnwindCtx.m_State.enmRetType; 1098 1350 pCur->fFlags |= DBGFSTACKFRAME_FLAGS_USED_UNWIND_INFO; 1351 rc = DBGFR3AddrFromSelOff(UnwindCtx.m_pUVM, UnwindCtx.m_idCpu, &pCur->AddrFrame, 1352 UnwindCtx.m_State.u.x86.FrameAddr.sel, UnwindCtx.m_State.u.x86.FrameAddr.off); 1099 1353 } 1100 1354 else if (enmCodeType != DBGFCODETYPE_GUEST) … … 1133 1387 while (!(pCur->fFlags & (DBGFSTACKFRAME_FLAGS_LAST | DBGFSTACKFRAME_FLAGS_MAX_DEPTH | DBGFSTACKFRAME_FLAGS_LOOP))) 1134 1388 { 1389 Next.cSureRegs = 0; 1390 Next.paSureRegs = NULL; 1391 1135 1392 /* try walk. */ 1136 1393 rc = dbgfR3StackWalk(&UnwindCtx, &Next, false /*fFirst*/); … … 1343 1600 RTDbgLineFree(pCur->pLineReturnPC); 1344 1601 1602 if (pCur->paSureRegs) 1603 { 1604 MMR3HeapFree(pCur->paSureRegs); 1605 pCur->paSureRegs = NULL; 1606 pCur->cSureRegs = 0; 1607 } 1608 1345 1609 pCur->pNextInternal = NULL; 1346 1610 pCur->pFirstInternal = NULL;
Note:
See TracChangeset
for help on using the changeset viewer.