📄 dbg.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*++
Module Name:
dbg.c
Abstract:
Environment:
WinCE
--*/
#include "kdp.h"
///#define V_ADDR(addr) VerifyAccess((addr), VERIFY_KERNEL_OK, (ACCESSKEY)-1)
#define V_ADDR(addr) (addr)
extern LPVOID ThreadStopFunc;
const DWORD dwKStart=(DWORD)-1, dwNewKStart=(DWORD)-1; //KPage start and new start addresses
const DWORD dwKEnd=(DWORD)-1, dwNewKEnd=(DWORD)-1; //KPage end and new end addresses
int g_cFrameInCallStack = 0;
static const CHAR lpszUnk[]="UNKNOWN";
static const CHAR lpszKernName[]="NK.EXE";
// Handle Explorer help
const char g_szHandleExHelp[] =
"Handle Explorer (Target Side Command):\n" \
"\thl ? - Request help on Handle Explorer commands\n" \
"\thl query [P:pid] [T:type] - Display information about handles in process and/or of a specific typeid\n" \
"\thl info hid - Display information about a single handle\n" \
"\thl delete P:pid H:hid - Delete a handle from a process (DANGEROUS)\n\n" \
"PID and Type ID should be decimal values. Handle ID should be hexadecimal.\n" \
"T00: Win32 T01: Thread T02: Process T03: [Unused]\n" \
"T04: Event T05: Mutex T06: API Set T07: File\n" \
"T08: Find T09: DB File T10: DB Find T11: Socket\n" \
"T12: Interface T13: Semaphore T14: FS Map T15: WNet Enum\n";
// Map Handle Explorer IDs -> names
const LPCSTR g_apszHandleFields[] =
{"Handle", // KD_HDATA_HANDLE
"Access Key", // KD_HDATA_AKY
"Ref Count", // KD_HDATA_REFCNT
"Type", // KD_HDATA_TYPE
"Name", // KD_HDATA_NAME
"Suspend Cnt", // KD_HDATA_THREAD_SUSPEND
"Owner Proc", // KD_HDATA_THREAD_PROC
"Base Prio", // KD_HDATA_THREAD_BPRIO
"Cur Prio", // KD_HDATA_THREAD_CPRIO
"Kernel Time", // KD_HDATA_THREAD_KTIME
"User Time", // KD_HDATA_THREAD_UTIME
"PID", // KD_HDATA_PROC_PID
"Trust Level", // KD_HDATA_PROC_TRUST
"VMBase", // KD_HDATA_PROC_VMBASE
"Base Ptr", // KD_HDATA_PROC_BASEPTR
"Commandline", // KD_HDATA_PROC_CMDLINE
"State", // KD_HDATA_EVENT_STATE
"Man. Reset", // KD_HDATA_EVENT_RESET
"Lock Count", // KD_HDATA_MUTEX_LOCKCNT
"Owner", // KD_HDATA_MUTEX_OWNER
"Count", // KD_HDATA_SEM_COUNT
"Max Count", // KD_HDATA_SEM_MAXCOUNT
};
// Stackwalk state globals
PCALLSTACK pStk = NULL;
PPROCESS pLastProc = NULL;
PTHREAD pWalkThread = NULL;
BOOL g_fTopFrame = TRUE;
static WCHAR rgchBuf[256];
void kdbgWtoA(LPWSTR pWstr, LPCHAR pAstr) {
while (*pAstr++ = (CHAR)*pWstr++)
;
}
void kdbgWtoAmax(LPWSTR pWstr, LPCHAR pAstr, int max) {
while ((max--) && (*pAstr++ = (CHAR)*pWstr++))
;
}
DWORD kdbgwcslen(LPWSTR pWstr) {
const wchar_t *eos = pWstr;
while( *eos++ )
;
return( (size_t)(eos - pWstr - 1) );
}
static BOOL sprintf_temp(
PCHAR pOutBuf,
PUSHORT pOutBufIndex,
PUSHORT pMaxBytes,
LPWSTR lpszFmt,
...
)
{
WCHAR szTempString[256];
WORD wLen;
//
// Write to a temporary string
//
NKwvsprintfW(szTempString, lpszFmt,
(LPVOID) ( ((DWORD)&lpszFmt) + sizeof(lpszFmt) ),
sizeof(szTempString) / sizeof(WCHAR));
wLen = (WORD) kdbgwcslen(szTempString);
if ((*pMaxBytes) < wLen) {
// Not enough space
return FALSE;
}
//
// Convert to ASCII and write it to the output buffer
//
kdbgWtoA( szTempString, (CHAR*) &(pOutBuf[*pOutBufIndex]) );
//
// Don't include the NULL. Instead manually update index to include null at
// the very end.
//
(*pOutBufIndex) += wLen;
(*pMaxBytes) -= wLen;
return TRUE;
}
// Like library function, returns number of chars copied or -1 on overflow
int snprintf(LPSTR pszBuf, UINT cBufLen, LPCWSTR pszFmt, ...)
{
WCHAR szTempString[256];
UINT cOutLen, cStrLen;
// Do nothing if no buffer
if (cBufLen == 0)
return -1;
NKwvsprintfW(szTempString, pszFmt, (&pszFmt) + 1, lengthof(szTempString));
cStrLen = kdbgwcslen(szTempString);
cOutLen = min(cBufLen - 1, cStrLen);
szTempString[cOutLen] = L'\0';
kdbgWtoA(szTempString, pszBuf);
return (cBufLen > cStrLen ? cOutLen : -1);
}
// Like library function
unsigned long strtoul(const char *nptr, char **endptr, int base)
{
unsigned long oflow_mul = (unsigned long)(ULONG_MAX / (unsigned long) base);
unsigned long oflow_add = (unsigned long)(ULONG_MAX % (unsigned long) base);
unsigned long i = 0;
unsigned long n;
// Defensive programming
if (base < 2 || base > 36)
{
DEBUGGERMSG(KDZONE_DBG, (L"Invalid base (%u) passed to strtoul!\r\n", base));
return ULONG_MAX;
}
while((*nptr >= '0' && *nptr <= '9') || // numeric
(*nptr >= 'a' && *nptr <= 'z') || // lower-case alpha
(*nptr >= 'A' && *nptr <= 'Z')) // upper-case alpha
{
if (*nptr >= '0' && *nptr <= '9')
n = (*nptr - '0');
else if (*nptr >= 'a' && *nptr <= 'z')
n = (10 + *nptr - 'a');
else // if (*nptr >= 'A' && *nptr <= 'Z')
n = (10 + *nptr - 'A');
// Validate input
if (n >= (unsigned long) base)
break;
// Check for overflow
if (i > oflow_mul || (i == oflow_mul && n > oflow_add))
{
i = ULONG_MAX;
break;
}
i = (i * base) + n;
nptr++;
}
if (endptr != NULL)
*endptr = (char *) nptr;
return i;
}
// We get isspace in headers but not imports, so we need to roll our own
int Kdp_isspace(char ch)
{
return (ch == ' ' || (ch > 9 && ch < 13) ? 1 : 0);
}
/*++
Routine Name:
ParseParamString
Routine Description:
Part of the FlexPTI parser. This routine parses a parameter string into
individual parameters.
Arguments:
pszParamString - [in/out] Pointer to parameter string
Return Value:
Number of parameters parsed. On return, pszParamString will contain the
address of the first parameter.
--*/
static UINT ParseParamString(LPSTR *ppszParamString)
{
LPSTR pszCurPos = *ppszParamString;
UINT nParams = 0;
LPSTR pszCopyPos;
// Skip leading whitespace
while(Kdp_isspace(*pszCurPos))
pszCurPos++;
// Store start of parameter string
*ppszParamString = pszCurPos;
while(*pszCurPos != '\0')
{
pszCopyPos = pszCurPos;
// Find first whitespace outside of quotes. As an added bonus, we copy
// over quotes here so """f""o"o becomes foo.
while ((pszCopyPos <= pszCurPos) &&
(*pszCurPos != '\0') && // not end of string and
((!Kdp_isspace(*pszCurPos)) || // haven't found a space or
((pszCurPos - pszCopyPos) % 2 != 0))) // in the middle of quotes
{
// If we have a quote, this desyncs pszCopyPos and pszCurPos so we
// start copying characters backward. The loop test prevents us
// from exiting between quotes unless we hit the end of the string.
if (*pszCurPos != '"')
{
*pszCopyPos = *pszCurPos;
pszCopyPos++;
}
pszCurPos++;
}
// Null-terminate the end of the parameter
while(pszCopyPos < pszCurPos)
*pszCopyPos++ = '\0';
// Skip trailing whitespace
while(Kdp_isspace(*pszCurPos))
*pszCurPos++ = '\0';
nParams++;
}
return nParams;
}
/*++
Routine Name:
GetNextParam
Routine Description:
Part of the FlexPTI parser. This routine finds the offset of the next
parameter in the parameter string. The parser splits the parameter string
into individual parameters (like argc/argv). To avoid memory allocation, it
leaves the parameters in-place and nulls out characters in the middle.
It is imperative that the caller verify that there is another parameter in
the string or this function may crash.
Arguments:
pszCurParam - [in] Pointer to current parameter
Return Value:
A pointer to the next parameter string is returned.
--*/
static LPCSTR GetNextParam(LPCSTR pszCurParam)
{
// Find end of current string
while(*pszCurParam != '\0')
pszCurParam++;
// Find start of next string
while(*pszCurParam == '\0')
pszCurParam++;
return pszCurParam;
}
CHAR lpszModuleName[MAX_PATH];
LPCHAR GetWin32ExeName(PPROCESS pProc)
{
if (pProc->lpszProcName) {
kdbgWtoA(pProc->lpszProcName,lpszModuleName);
return lpszModuleName;
}
return (LPCHAR)lpszUnk;
}
BOOL GetModuleInfo (PROCESS *pProc, DWORD dwStructAddr, KD_MODULE_INFO *pkmodi, BOOL fRedundant, BOOL fUnloadSymbols)
{
LPMODULE lpMod;
static BOOL PhysUpd;
DEBUGGERMSG(KDZONE_DBG, (TEXT("\r\nGetting name and base for module %8.8lx \r\n"), dwStructAddr));
// set default to not ROM DLL
pkmodi->dwDllRwEnd = 0;
pkmodi->dwDllRwStart = 0xFFFFFFFF;
// set default to no TimeStamp data
pkmodi->dwTimeStamp = 0;
// set defaults for v15 protocol data
pkmodi->hDll = NULL;
pkmodi->dwInUse = 0;
pkmodi->wFlags = 0;
pkmodi->bTrustLevel = 0;
// Check for the kernel first
if (&(kdProcArray [0]) == (PROCESS *) dwStructAddr)
{
if (PhysUpd && fRedundant)
{
DEBUGGERMSG(KDZONE_DBG, (TEXT("\r\nReturning redundant\r\n")));
return FALSE;
}
pkmodi->szName = (LPCHAR) lpszKernName;
pkmodi->ImageBase = (ULONG) kdProcArray[0].BasePtr;
pkmodi->ImageSize = kdProcArray[0].e32.e32_vsize;
pkmodi->dwDllRwStart = ((COPYentry *)(pTOC->ulCopyOffset))->ulDest;
pkmodi->dwDllRwEnd = pkmodi->dwDllRwStart + ((COPYentry *)(pTOC->ulCopyOffset))->ulDestLen - 1;
pkmodi->dwTimeStamp = kdProcArray[0].e32.e32_timestamp;
pkmodi->hDll = NULL;
pkmodi->dwInUse = (1 << kdProcArray[0].procnum);
pkmodi->wFlags = 0;
pkmodi->bTrustLevel = kdProcArray[0].bTrustLevel;
PhysUpd=TRUE;
DEBUGGERMSG(KDZONE_DBG, (L"Returning kernel %8.8lx-%8.8lx %a (TimeStamp: %8.8lx)\r\n", pkmodi->ImageBase, pkmodi->ImageBase+pkmodi->ImageSize, pkmodi->szName, pkmodi->dwTimeStamp));
return TRUE;
}
DEBUGGERMSG(KDZONE_DBG,
(TEXT("\r\nMy address %8.8lx, adjusted %8.8lx, Base: %8.8lx, Base+Size: %8.8lx\r\n"),
dwStructAddr, (ULONG)MapPtrInProc(dwStructAddr, pProc), (long)pProc->BasePtr,
MapPtrInProc((long)pProc->BasePtr+pProc->e32.e32_vsize, pProc)));
if ((PROCESS *) dwStructAddr == pProc)
{ // Process
pkmodi->szName = GetWin32ExeName (pProc);
pkmodi->ImageBase = (UINT) MapPtrInProc (pProc->BasePtr, pProc);
pkmodi->ImageSize = pProc->e32.e32_vsize;
pkmodi->dwTimeStamp = pProc->e32.e32_timestamp;
pkmodi->hDll = NULL;
pkmodi->dwInUse = (1 << pProc->procnum);
pkmodi->wFlags = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -