📄 dwdmpgen.cpp
字号:
}
resptr++;
}
DEBUGGERMSG(OXZONE_DWDMPGEN,(L"--DwDmpGen!FindTypeByNum: Leave, dwRva=0x%08X\r\n", dwRva));
return dwRva;
}
//------------------------------------------------------------------------------
// Find first entry (from curr pointer)
//------------------------------------------------------------------------------
DWORD FindFirst(LPBYTE curr)
{
DWORD dwRva = 0;
resroot_t *rootptr;
resent_t *resptr;
DEBUGGERMSG(OXZONE_DWDMPGEN,(L"++DwDmpGen!FindFirst: Enter\r\n"));
rootptr = (resroot_t *)curr;
resptr = (resent_t *)(curr + sizeof(resroot_t) +
rootptr->numnameents*sizeof(resent_t));
dwRva = resptr->rva;
DEBUGGERMSG(OXZONE_DWDMPGEN,(L"--DwDmpGen!FindFirst: Leave, dwRva=0x%08X\r\n", dwRva));
return dwRva;
}
//------------------------------------------------------------------------------
// Extract a resource
//------------------------------------------------------------------------------
LPVOID ExtractOneResource(
LPBYTE lpres,
LPCWSTR lpszName,
LPCWSTR lpszType,
DWORD o32rva,
LPDWORD pdwSize
)
{
DWORD trva;
LPVOID lpData = NULL;
DEBUGGERMSG(OXZONE_DWDMPGEN,(L"++DwDmpGen!ExtractOneResource: Enter\r\n"));
if (!(trva = FindTypeByNum(lpres, (DWORD)lpszType)) ||
!(trva = FindTypeByNum(lpres+(trva&0x7fffffff),(DWORD)lpszName)) ||
!(trva = FindFirst(lpres+(trva&0x7fffffff))) ||
(trva & 0x80000000))
{
lpData = NULL;
goto Exit;
}
trva = (ULONG)(lpres + trva);
if (pdwSize)
*pdwSize = ((resdata_t *)trva)->size;
lpData = (lpres+((resdata_t *)trva)->rva-o32rva);
Exit:
DEBUGGERMSG(OXZONE_DWDMPGEN,(L"--DwDmpGen!ExtractOneResource: Leave, lpData=0x%08X\r\n", lpData));
return lpData;
}
/*----------------------------------------------------------------------------
GetVersionInfo
Get version info for a process or module.
----------------------------------------------------------------------------*/
HRESULT GetVersionInfo(HANDLE hModule, VS_FIXEDFILEINFO **ppvsFixedInfo)
{
HRESULT hRes = E_FAIL;
int loop;
BOOL fVersionInfoFound = FALSE;
DWORD o32rva;
LPBYTE lpres = NULL;
VERHEAD *pVerHead = NULL;
LPWSTR lpStart;
DWORD dwTemp;
LPBYTE BasePtr;
e32_lite *pe32l = NULL;
o32_lite *po32_ptr;
PPROCESS pProc;
PMODULE pMod = NULL;
PPROCESS pProcArray;
DEBUGGERMSG(OXZONE_DWDMPGEN,(L"++DwDmpGen!GetVersionInfo: Enter\r\n"));
pProcArray = FetchProcArray();
if (NULL == pProcArray)
{
DEBUGGERMSG(OXZONE_ALERT,(L" DwDmpGen!GetVersionInfo: FetchProcArray returned NULL\r\n"));
hRes = E_FAIL;
goto Exit;
}
if (pProc = HandleToProc(hModule))
{ // a process
PMODULE pCoreDll = (PMODULE)hCoreDll;
DWORD dwInUse = (1 << pProc->procnum);
if (!pCoreDll || !(dwInUse & pCoreDll->inuse))
{
// When process is starting or dying we can not access the o32_ptr, since it may be pointing at invalid memory
DEBUGGERMSG(OXZONE_ALERT, (L" DwDmpGen!GetVersionInfo: Process ID 0x%08X (%s) not using CoreDll.dll, may be in startup or shutdown.\r\n", pProc->hProc, pProc->lpszProcName));
hRes = E_FAIL;
goto Exit;
}
BasePtr = (LPBYTE)MapPtrProc(pProc->BasePtr, pProc);
pe32l = &pProc->e32;
}
else if ((pMod = (LPMODULE)hModule)->lpSelf == pMod)
{ // a module
if (!pMod->inuse)
{
DEBUGGERMSG(OXZONE_ALERT, (L" DwDmpGen!GetVersionInfo: Inuse flag for module not set, returning ...\r\n"));
hRes = E_FAIL;
goto Exit;
}
BasePtr = (LPBYTE)MapPtrProc(pMod->BasePtr, &pProcArray[0]);
pe32l = &pMod->e32;
}
if (pe32l && pe32l->e32_unit[RES].rva)
{
if (pMod && pMod->rwHigh)
{
// need to find the right section if RO/RW section are split
po32_ptr = pMod->o32_ptr;
for (loop = 0; loop < pe32l->e32_objcnt; loop++)
{
if ((po32_ptr) && (po32_ptr[loop].o32_rva == pe32l->e32_unit[RES].rva) && (po32_ptr[loop].o32_psize))
{
if ((po32_ptr[loop].o32_flags & IMAGE_SCN_COMPRESSED))
{
// if compressed, fail
DEBUGGERMSG(OXZONE_ALERT,(L" DwDmpGen!GetVersionInfo: Version resource is compressed\r\n"));
hRes = E_FAIL;
goto Exit;
}
o32rva = po32_ptr[loop].o32_rva;
lpres = (LPBYTE) (po32_ptr[loop].o32_realaddr);
break;
}
}
}
else
{
o32rva = pe32l->e32_unit[RES].rva;
lpres = BasePtr + pe32l->e32_unit[RES].rva;
}
if (lpres)
{
pVerHead = (VERHEAD *)ExtractOneResource(lpres, MAKEINTRESOURCE(VS_VERSION_INFO), VS_FILE_INFO, o32rva, &dwTemp);
if (pVerHead)
{
if (((DWORD)pVerHead->wTotLen > dwTemp) || (pVerHead->vsf.dwSignature != VS_FFI_SIGNATURE))
{
DEBUGGERMSG(OXZONE_ALERT,(L" DwDmpGen!GetVersionInfo: Bad Version resource data\r\n"));
hRes = E_FAIL;
goto Exit;
}
else
{
DEBUGGERMSG(OXZONE_DWDMPGEN,(L" DwDmpGen!GetVersionInfo: Ver Len=%u, Ver Key=%s\r\n", pVerHead->wTotLen, pVerHead->szKey));
lpStart = (LPWSTR)((LPBYTE)pVerHead+DWORDUP((sizeof(VERBLOCK)-sizeof(WCHAR))+(kdbgwcslen(pVerHead->szKey)+1)*sizeof(WCHAR)));
*ppvsFixedInfo = (VS_FIXEDFILEINFO*)(lpStart < (LPWSTR)((LPBYTE)pVerHead+pVerHead->wTotLen) ? lpStart : (LPWSTR)(pVerHead->szKey+kdbgwcslen(pVerHead->szKey)));
fVersionInfoFound = TRUE;
}
}
}
}
if (!fVersionInfoFound)
{
DEBUGGERMSG(OXZONE_DWDMPGEN,(L" DwDmpGen!GetVersionInfo: No Version Info\r\n"));
hRes = E_FAIL;
goto Exit;
}
hRes = S_OK;
Exit:
DEBUGGERMSG(OXZONE_DWDMPGEN,(L"--DwDmpGen!GetVersionInfo: Leave, hRes=0x%08X\r\n", hRes));
return hRes;
}
/*----------------------------------------------------------------------------
GetBucketParameters
Get the bucket parameters from exception information.
----------------------------------------------------------------------------*/
HRESULT GetBucketParameters(PCEDUMP_BUCKET_PARAMETERS pceDmpBucketParameters)
{
HRESULT hRes = E_FAIL;
DWORD dwPC, dwExcAddr, dwPCSlot, dwPCOriginal;
DWORD dwImageBase, dwImageSize;
PPROCESS pProcess, pProcessOriginal;
PTHREAD pThread;
PMODULE pMod;
BOOL fFoundMod = FALSE;
VS_FIXEDFILEINFO * pvsFixedInfo = NULL;
KDataStruct *pKData;
PPROCESS pProcArray;
DWORD dwProcessNumber;
CallSnapshotEx csexFrames[STACK_FRAMES_BUFFERED] = {0};
DWORD dwFramesReturned, dwFrameCount;
BOOL fDifferentPCorProcess = FALSE;
DEBUGGERMSG(OXZONE_DWDMPGEN,(L"++DwDmpGen!GetBucketParameters: Enter\r\n"));
pProcArray = FetchProcArray();
if (NULL == pProcArray)
{
DEBUGGERMSG(OXZONE_ALERT,(L" DwDmpGen!GetBucketParameters: FetchProcArray returned NULL\r\n"));
hRes = E_FAIL;
goto Exit;
}
pKData = FetchKData ();
if (NULL == pKData)
{
DEBUGGERMSG(OXZONE_ALERT,(L" DwDmpGen!GetBucketParameters: FetchKData returned NULL\r\n"));
hRes = E_FAIL;
goto Exit;
}
pceDmpBucketParameters->SizeOfHeader = sizeof(CEDUMP_BUCKET_PARAMETERS);
if (g_fCaptureDumpFileOnDeviceCalled)
{
pceDmpBucketParameters->EventType = (DWORD)WATSON_SNAPSHOT_EVENT;
}
else
{
pceDmpBucketParameters->EventType = (DWORD)WATSON_EXCEPTION_EVENT;
}
DEBUGGERMSG(OXZONE_DWDMPGEN,(L" DwDmpGen!GetBucketParameters: hCurProc=0x%08X, hCurThread=0x%08X, hOwnerProc=0x%08X\r\n",
hCurProc, hCurThread, (DWORD)((PROCESS *)(pCurThread->pOwnerProc)->hProc)));
DEBUGGERMSG(OXZONE_DWDMPGEN,(L" DwDmpGen!GetBucketParameters: hDmpProc=0x%08X, hDmpThread=0x%08X, hOwnerProc=0x%08X\r\n",
g_pDmpProc->hProc, g_pDmpThread->hTh, (DWORD)((PROCESS *)(g_pDmpThread->pOwnerProc)->hProc)));
pProcessOriginal = pProcess = g_pDmpProc;
pThread = g_pDmpThread;
if (pThread == pCurThread)
{
// Default to the Exception PC
dwPCOriginal = dwPC = CONTEXT_TO_PROGRAM_COUNTER (g_pContextException);
dwExcAddr = (DWORD) g_pExceptionRecord->ExceptionAddress;
#ifdef DEBUG
if ((dwExcAddr < dwPC) || (dwExcAddr > (dwPC+4)))
{
DEBUGGERMSG (OXZONE_ALERT,(L" DwDmpGen!GetBucketParameters: WARNING: Exception frame PC (0x%08X) is different than Exception address (0x%08X).\r\n", dwPC, dwExcAddr));
}
#endif // DEBUG
// Check if CaptureDumpFileOnDevice API called for current thread
if (g_fCaptureDumpFileOnDeviceCalled)
{
// Unwind two frames from point of exception (CaptureDumpFileOnDevice API + Calling function)
dwFramesReturned = GetCallStack(pThread->hTh, 2, csexFrames, STACKSNAP_EXTENDED_INFO, 0);
if (dwFramesReturned != 2)
{
DEBUGGERMSG (OXZONE_ALERT,(L" DwDmpGen!GetBucketParameters: GetCallStack did not unwind 2 frames for CaptureDumpFileOnDevice API, dwFramesReturned=%u.\r\n", dwFramesReturned));
// Don't fail, just go with the exception PC
}
else
{
// Get the PC and process of the frame calling CaptureDumpFileOnDevice API
// this will provide bucketing data for the module that called the API
dwFrameCount = 1;
dwPC = csexFrames[dwFrameCount].dwReturnAddr;
pProcess = HandleToProc((HANDLE)csexFrames[dwFrameCount].dwCurProc);
++ dwFrameCount;
}
}
}
else
{
// We should only get here when CaptureDumpFileOnDevice API is called for another thread
KD_ASSERT(g_fCaptureDumpFileOnDeviceCalled);
dwPCOriginal = dwPC = GetThreadIP(pThread);
// Check if PC in Nk.exe (Process 0) & Nk.exe not owner of thread
// If PC is in Nk.exe then we try unwind out of NK.exe & Coredll.dll
// This should give us better bucket parameters, otherwise we always get Nk.EXE + KCall offset for buckets
dwImageBase = (DWORD) pProcArray[0].BasePtr;
if (dwImageBase < 0x01FFFFFF)
{
dwImageBase |= pProcArray[0].dwVMBase;
}
dwImageSize = pProcArray[0].e32.e32_vsize;
if ((dwImageBase <= dwPC) && (dwPC < (dwImageBase + dwImageSize)) && (pThread->pOwnerProc != &pProcArray[0]))
{
// Unwind frames from current PC
dwFramesReturned = GetCallStack(pThread->hTh, STACK_FRAMES_BUFFERED, csexFrames, STACKSNAP_EXTENDED_INFO, 0);
if (dwFramesReturned <= 0)
{
DEBUGGERMSG (OXZONE_ALERT,(L" DwDmpGen!GetBucketParameters: GetCallStack did not unwind frames from Nk.exe, dwFramesReturned=%u.\r\n", dwFramesReturned));
// Don't fail, just go with the NK.exe PC
}
else
{
BOOL fFramesLeft = TRUE;
// Walk down frames until we are out of nk.exe (Process 0)
// Start at top frame
dwFrameCount = 0;
while ((dwImageBase <= dwPC) && (dwPC < (dwImageBase + dwImageSize)) && (fFramesLeft))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -