Changeset 73388 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Jul 27, 2018 3:20:29 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/DBGFStack.cpp
r73377 r73388 34 34 #include <iprt/mem.h> 35 35 #include <iprt/string.h> 36 #include <iprt/formats/pecoff.h> 36 37 37 38 … … 59 60 uint8_t *m_pbCachedInfo; 60 61 size_t m_cbCachedInfo; 62 63 /** Function table for PE/AMD64 (entire m_pbCachedInfo) . */ 64 PCIMAGE_RUNTIME_FUNCTION_ENTRY m_paFunctions; 65 /** Number functions in m_paFunctions. */ 66 size_t m_cFunctions; 61 67 62 68 DBGFUNWINDCTX(PUVM pUVM, VMCPUID idCpu, PCCPUMCTX pInitialCtx, RTDBGAS hAs) … … 96 102 m_pbCachedInfo = NULL; 97 103 m_cbCachedInfo = 0; 104 m_paFunctions = NULL; 105 m_cFunctions = 0; 98 106 } 99 107 … … 118 126 } 119 127 pUnwindCtx->m_cbCachedInfo = 0; 128 pUnwindCtx->m_paFunctions = NULL; 129 pUnwindCtx->m_cFunctions = 0; 120 130 } 121 131 … … 135 145 136 146 137 static bool dbgfR3UnwindCtxDoOneFrameCached(PDBGFUNWINDCTX pUnwindCtx, PDBGFADDRESS pAddrFrame) 138 { 139 if (!pUnwindCtx->m_cbCachedInfo) 140 return false; 141 142 //PCIMAGE_RUNTIME_FUNCTION_ENTRY; 143 //UNWIND_HISTORY_TABLE 147 /** 148 * Try read a 64-bit value off the stack. 149 * 150 * @param pUnwindCtx The unwind context. 151 * @param uSrcAddr The stack address. 152 * @param puDst The read destination. 153 */ 154 static void dbgfR3UnwindCtxLoadU64(PDBGFUNWINDCTX pUnwindCtx, uint64_t uSrcAddr, uint64_t *puDst) 155 { 156 DBGFADDRESS SrcAddr; 157 DBGFR3MemRead(pUnwindCtx->m_pUVM, pUnwindCtx->m_idCpu, 158 DBGFR3AddrFromFlat(pUnwindCtx->m_pUVM, &SrcAddr, uSrcAddr), 159 puDst, sizeof(*puDst)); 160 } 161 162 163 /** 164 * Binary searches the lookup table. 165 * 166 * @returns RVA of unwind info on success, UINT32_MAX on failure. 167 * @param paFunctions The table to lookup @a offFunctionRva in. 168 * @param iEnd Size of the table. 169 * @param uRva The RVA of the function we want. 170 */ 171 DECLINLINE(PCIMAGE_RUNTIME_FUNCTION_ENTRY) 172 dbgfR3UnwindCtxLookupUnwindInfoRva(PCIMAGE_RUNTIME_FUNCTION_ENTRY paFunctions, size_t iEnd, uint32_t uRva) 173 { 174 size_t iBegin = 0; 175 while (iBegin < iEnd) 176 { 177 size_t const i = iBegin + (iEnd - iBegin) / 2; 178 PCIMAGE_RUNTIME_FUNCTION_ENTRY pEntry = &paFunctions[i]; 179 if (uRva < pEntry->BeginAddress) 180 iEnd = i; 181 else if (uRva > pEntry->EndAddress) 182 iBegin = i + 1; 183 else 184 return pEntry; 185 } 186 return NULL; 187 } 188 189 190 static bool dbgfR3UnwindCtxDoOneFrameCached(PDBGFUNWINDCTX pUnwindCtx, uint32_t uRvaRip, PDBGFADDRESS pAddrFrame) 191 { 192 /* 193 * Lookup the unwind info RVA and try read it. 194 */ 195 PCIMAGE_RUNTIME_FUNCTION_ENTRY pEntry = dbgfR3UnwindCtxLookupUnwindInfoRva(pUnwindCtx->m_paFunctions, 196 pUnwindCtx->m_cFunctions, uRvaRip); 197 if (pEntry) 198 { 199 unsigned iFrameReg = ~0U; 200 unsigned offFrameReg = 0; 201 202 for (;;) 203 { 204 /* 205 * Get the info. 206 */ 207 union 208 { 209 uint32_t uRva; 210 uint8_t ab[ RT_OFFSETOF(IMAGE_UNWIND_INFO, aOpcodes) 211 + sizeof(IMAGE_UNWIND_CODE) * 256 212 + sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY)]; 213 } uBuf; 214 215 uBuf.uRva = pEntry->UnwindInfoAddress; 216 size_t cbBuf = sizeof(uBuf); 217 int rc = RTDbgModImageQueryProp(pUnwindCtx->m_hCached, RTLDRPROP_UNWIND_INFO, &uBuf, cbBuf, &cbBuf); 218 if (RT_FAILURE(rc)) 219 return false; 220 221 /* 222 * Check the info. 223 */ 224 ASMCompilerBarrier(); /* we're aliasing */ 225 PCIMAGE_UNWIND_INFO pInfo = (PCIMAGE_UNWIND_INFO)&uBuf; 226 227 if (pInfo->Version != 1) 228 return false; 229 230 /* 231 * Execute the opcodes. 232 */ 233 unsigned const cOpcodes = pInfo->CountOfCodes; 234 unsigned iOpcode = 0; 235 236 /* First, skip opcodes that doesn't apply to us if we're the prolog. */ 237 uint32_t offPc = uRvaRip - pEntry->BeginAddress; 238 if (offPc < pInfo->SizeOfProlog) 239 while (iOpcode < cOpcodes && pInfo->aOpcodes[iOpcode].u.CodeOffset > offPc) 240 iOpcode++; 241 242 /* Execute. */ 243 if (pInfo->FrameRegister != 0) 244 { 245 iFrameReg = pInfo->FrameRegister; 246 offFrameReg = pInfo->FrameOffset * 16; 247 } 248 while (iOpcode < cOpcodes) 249 { 250 Assert(pInfo->aOpcodes[iOpcode].u.CodeOffset <= offPc); 251 switch (pInfo->aOpcodes[iOpcode].u.UnwindOp) 252 { 253 case IMAGE_AMD64_UWOP_PUSH_NONVOL: 254 pUnwindCtx->m_aGprs[X86_GREG_xSP] -= 8; 255 dbgfR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_aGprs[X86_GREG_xSP], 256 &pUnwindCtx->m_aGprs[pInfo->aOpcodes[iOpcode].u.OpInfo]); 257 iOpcode++; 258 break; 259 260 case IMAGE_AMD64_UWOP_ALLOC_LARGE: 261 iOpcode += 3; 262 AssertBreak(iOpcode <= cOpcodes); 263 pUnwindCtx->m_aGprs[X86_GREG_xSP] -= *(uint32_t const *)&pInfo->aOpcodes[iOpcode - 2]; 264 break; 265 266 case IMAGE_AMD64_UWOP_ALLOC_SMALL: 267 AssertBreak(iOpcode <= cOpcodes); 268 pUnwindCtx->m_aGprs[X86_GREG_xSP] -= pInfo->aOpcodes[iOpcode].u.OpInfo * 8 + 8; 269 iOpcode++; 270 break; 271 272 case IMAGE_AMD64_UWOP_SET_FPREG: 273 iFrameReg = pInfo->aOpcodes[iOpcode].u.OpInfo; 274 offFrameReg = pInfo->FrameOffset * 16; 275 break; 276 277 case IMAGE_AMD64_UWOP_SAVE_NONVOL: 278 case IMAGE_AMD64_UWOP_SAVE_NONVOL_FAR: 279 { 280 bool const fFar = pInfo->aOpcodes[iOpcode].u.UnwindOp == IMAGE_AMD64_UWOP_SAVE_NONVOL_FAR; 281 unsigned const iGreg = pInfo->aOpcodes[iOpcode].u.OpInfo; 282 uint32_t off = 0; 283 iOpcode++; 284 if (iOpcode < cOpcodes) 285 { 286 off = pInfo->aOpcodes[iOpcode].FrameOffset; 287 iOpcode++; 288 if (fFar && iOpcode < cOpcodes) 289 { 290 off |= (uint32_t)pInfo->aOpcodes[iOpcode].FrameOffset << 16; 291 iOpcode++; 292 } 293 } 294 off *= 8; 295 dbgfR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_aGprs[X86_GREG_xSP] + off, &pUnwindCtx->m_aGprs[iGreg]); 296 break; 297 } 298 299 case IMAGE_AMD64_UWOP_SAVE_XMM128: 300 iOpcode += 2; 301 break; 302 303 case IMAGE_AMD64_UWOP_SAVE_XMM128_FAR: 304 iOpcode += 3; 305 break; 306 307 case IMAGE_AMD64_UWOP_PUSH_MACHFRAME: 308 { 309 Assert(pInfo->aOpcodes[iOpcode].u.OpInfo <= 1); 310 if (pInfo->aOpcodes[iOpcode].u.OpInfo) 311 pUnwindCtx->m_aGprs[X86_GREG_xSP] -= 8; /* error code */ 312 313 pUnwindCtx->m_aGprs[X86_GREG_xSP] -= 8; /* RIP */ 314 dbgfR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_aGprs[X86_GREG_xSP], &pUnwindCtx->m_uPc); 315 316 pUnwindCtx->m_aGprs[X86_GREG_xSP] -= 8; /* CS */ 317 //dbgfR3UnwindCtxLoadU16(pUnwindCtx, pUnwindCtx->m_aGprs[X86_GREG_xSP], &pUnwindCtx->m_uCs); 318 319 pUnwindCtx->m_aGprs[X86_GREG_xSP] -= 8; /* EFLAGS */ 320 //dbgfR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_aGprs[X86_GREG_xSP], &pUnwindCtx->m_uRFlags); 321 322 pUnwindCtx->m_aGprs[X86_GREG_xSP] -= 8; /* RSP */ 323 uint64_t uNewRsp = (pUnwindCtx->m_aGprs[X86_GREG_xSP] - 8) & ~(uint64_t)15; 324 dbgfR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_aGprs[X86_GREG_xSP], &uNewRsp); 325 326 pUnwindCtx->m_aGprs[X86_GREG_xSP] -= 8; /* SS */ 327 //dbgfR3UnwindCtxLoadU16(pUnwindCtx, pUnwindCtx->m_aGprs[X86_GREG_xSP], &pUnwindCtx->m_uSs); 328 329 pUnwindCtx->m_aGprs[X86_GREG_xSP] = uNewRsp; 330 return true; 331 } 332 333 case IMAGE_AMD64_UWOP_RESERVED_6: 334 AssertFailedReturn(false); 335 336 case IMAGE_AMD64_UWOP_RESERVED_7: 337 AssertFailedReturn(false); 338 339 default: 340 AssertMsgFailedReturn(("%u\n", pInfo->aOpcodes[iOpcode].u.UnwindOp), false); 341 } 342 } 343 344 /* 345 * Chained stuff? 346 */ 347 if (!(pInfo->Flags & IMAGE_UNW_FLAGS_CHAININFO)) 348 break; 349 /** @todo impl chains. */ 350 break; 351 } 352 353 /** @todo do post processing. */ 354 } 144 355 145 356 RT_NOREF_PV(pAddrFrame); … … 155 366 RTUINTPTR offCache = pUnwindCtx->m_uPc - pUnwindCtx->m_uCachedMapping; 156 367 if (offCache < pUnwindCtx->m_cbCachedMapping) 157 return dbgfR3UnwindCtxDoOneFrameCached(pUnwindCtx, pAddrFrame);368 return dbgfR3UnwindCtxDoOneFrameCached(pUnwindCtx, offCache, pAddrFrame); 158 369 159 370 /* … … 174 385 /* Play simple for now. */ 175 386 if ( idxSeg == NIL_RTDBGSEGIDX 176 && RTDbgModImageGetFormat(hDbgMod) == RTLDRFMT_ PE387 && RTDbgModImageGetFormat(hDbgMod) == RTLDRFMT_32BIT_HACK /// @todo RTLDRFMT_PE (disabled code) 177 388 && RTDbgModImageGetArch(hDbgMod) == RTLDRARCH_AMD64) 178 389 { … … 181 392 */ 182 393 size_t cbNeeded = 0; 183 rc = RTDbgModImageQueryProp(hDbgMod, RTLDRPROP_UNWIND_ INFO, NULL, 0, &cbNeeded);394 rc = RTDbgModImageQueryProp(hDbgMod, RTLDRPROP_UNWIND_TABLE, NULL, 0, &cbNeeded); 184 395 if ( rc == VERR_BUFFER_OVERFLOW 185 && cbNeeded > 12396 && cbNeeded >= sizeof(*pUnwindCtx->m_paFunctions) 186 397 && cbNeeded < _64M) 187 398 { … … 189 400 if (pvBuf) 190 401 { 191 rc = RTDbgModImageQueryProp(hDbgMod, RTLDRPROP_UNWIND_ INFO, pUnwindCtx->m_pbCachedInfo, cbNeeded, &cbNeeded);402 rc = RTDbgModImageQueryProp(hDbgMod, RTLDRPROP_UNWIND_TABLE, pUnwindCtx->m_pbCachedInfo, cbNeeded, &cbNeeded); 192 403 if (RT_SUCCESS(rc)) 193 404 { 194 405 pUnwindCtx->m_pbCachedInfo = (uint8_t *)pvBuf; 195 406 pUnwindCtx->m_cbCachedInfo = cbNeeded; 196 return dbgfR3UnwindCtxDoOneFrameCached(pUnwindCtx, pAddrFrame); 407 pUnwindCtx->m_paFunctions = (PCIMAGE_RUNTIME_FUNCTION_ENTRY)pvBuf; 408 pUnwindCtx->m_cFunctions = cbNeeded / sizeof(*pUnwindCtx->m_paFunctions); 409 410 return dbgfR3UnwindCtxDoOneFrameCached(pUnwindCtx, pUnwindCtx->m_uPc - pUnwindCtx->m_uCachedMapping, 411 pAddrFrame); 197 412 } 198 413 RTMemFree(pvBuf); … … 203 418 return false; 204 419 } 205 206 420 207 421
Note:
See TracChangeset
for help on using the changeset viewer.