windows-nt/Source/XPSP1/NT/base/tools/kdexts2/util.c
2020-09-26 16:20:57 +08:00

631 lines
13 KiB
C

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
util.c
Abstract:
WinDbg Extension Api
Author:
Wesley Witt (wesw) 15-Aug-1993
Environment:
User Mode.
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
ULONG
GetBitFieldOffset (
IN LPSTR Type,
IN LPSTR Field,
OUT PULONG pOffset,
OUT PULONG pSize
)
{
FIELD_INFO flds = {
Field, "", 0,
DBG_DUMP_FIELD_FULL_NAME | DBG_DUMP_FIELD_RETURN_ADDRESS | DBG_DUMP_FIELD_SIZE_IN_BITS,
0, NULL};
SYM_DUMP_PARAM Sym = {
sizeof (SYM_DUMP_PARAM), Type, DBG_DUMP_NO_PRINT, 0,
NULL, NULL, NULL, 1, &flds
};
ULONG Err, i=0;
LPSTR dot, last=Field;
Sym.nFields = 1;
Err = Ioctl( IG_DUMP_SYMBOL_INFO, &Sym, Sym.size );
*pOffset = (ULONG) (flds.address - Sym.addr);
*pSize = flds.size;
return Err;
}
ULONG
GetFieldOffsetEx (
IN LPSTR Type,
IN LPSTR Field,
OUT PULONG pOffset,
OUT PULONG pSize
)
{
FIELD_INFO flds = {
Field, "", 0,
DBG_DUMP_FIELD_FULL_NAME | DBG_DUMP_FIELD_RETURN_ADDRESS,
0, NULL};
SYM_DUMP_PARAM Sym = {
sizeof (SYM_DUMP_PARAM), Type, DBG_DUMP_NO_PRINT, 0,
NULL, NULL, NULL, 1, &flds
};
ULONG Err, i=0;
LPSTR dot, last=Field;
Sym.nFields = 1;
Err = Ioctl( IG_DUMP_SYMBOL_INFO, &Sym, Sym.size );
*pOffset = (ULONG) (flds.address - Sym.addr);
*pSize = flds.size;
return Err;
} // GetFieldOffsetEx()
ULONG
GetUlongFromAddress (
ULONG64 Location
)
{
ULONG Value;
ULONG result;
if ((!ReadMemory(Location,&Value,sizeof(ULONG),&result)) ||
(result < sizeof(ULONG))) {
dprintf("GetUlongFromAddress: unable to read from %p\n", Location);
return 0;
}
return Value;
}
ULONG64
GetPointerFromAddress (
ULONG64 Location
)
{
ULONG64 Value;
ULONG result;
if (!ReadPointer( Location, &Value )) {
dprintf( "GetPointerFromAddress: unable to read from %p\n", Location );
return 0;
}
return Value;
}
ULONG
GetUlongValue (
PCHAR String
)
{
ULONG64 Location;
ULONG Value;
ULONG result;
Location = GetExpression( String );
if (!Location) {
dprintf("unable to get %s\n",String);
return 0;
}
return GetUlongFromAddress( Location );
}
ULONG64
GetPointerValue (
PCHAR String
)
{
ULONG64 Location, Val=0;
Location = GetExpression( String );
if (!Location) {
dprintf("unable to get %s\n",String);
return 0;
}
ReadPointer(Location, &Val);
return Val;
}
ULONG64
GetGlobalFromAddress (
ULONG64 Location,
ULONG Size
)
{
ULONG64 value;
ULONG result;
value = 0;
if ((!ReadMemory(Location,&value,Size,&result)) || (result < Size)) {
dprintf("GetGlobalFromAddress: unable to read from %p\n", Location);
return 0;
}
return value;
} // GetGlobalFromAddress()
ULONG64
GetGlobalValue (
PCHAR String
)
{
ULONG64 location;
ULONG size;
location = GetExpression( String );
if (!location) {
dprintf("GetGlobalValue: unable to get %s\n",String);
return 0;
}
size = GetTypeSize( String );
if (!size) {
dprintf("GetGlobalValue: unable to get %s type size\n",String);
return 0;
}
return GetGlobalFromAddress( location, size );
} // GetGlobalValue()
HRESULT
GetGlobalEx(
PCHAR String,
PVOID OutValue,
ULONG OutSize
)
{
ULONG64 location;
ULONG size;
ULONG result;
ZeroMemory( OutValue, OutSize );
location = GetExpression( String );
if (!location) {
return E_INVALIDARG;
}
size = GetTypeSize( String );
if (!size) {
return E_INVALIDARG;
}
if ( size > OutSize ) {
return E_OUTOFMEMORY;
}
if ((!ReadMemory(location,OutValue,size,&result)) || (result < size)) {
return E_FAIL;
}
return S_OK;
} // GetGlobalEx()
#if 0
VOID
DumpImageName(
IN ULONG64 Process
)
{
ULONG64 ImageFileName;
STRING String;
ULONG Result;
IN WCHAR Buf[512];
if ( !GetFieldValue(Process, "EPROCESS", "ImageFileName.Buffer", ImageFileName ) ){
wcscpy(Buf,L"*** image name unavailable ***");
if ( ReadMemory( ImageFileName,
&String,
sizeof(STRING),
&Result) ) {
if ( ReadMemory( (DWORD)String.Buffer,
&Buf[0],
String.Length,
&Result) ) {
Buf[String.Length/sizeof(WCHAR)] = UNICODE_NULL;
}
}
} else {
wcscpy(Buf,L"System Process");
}
dprintf("%ws",Buf);
}
#endif
BOOLEAN
DbgRtlIsRightChild(
ULONG64 pLinks,
ULONG64 Parent
)
{
ULONG64 RightChild;
if (Parent == pLinks) {
return FALSE;
}
if (GetFieldValue(Parent, "RTL_SPLAY_LINKS", "RightChild", RightChild)) {
return FALSE;
}
if (RightChild == pLinks) {
return TRUE;
}
return FALSE;
}
BOOLEAN
DbgRtlIsLeftChild(
ULONG64 pLinks,
ULONG64 Parent
)
{
ULONG64 LeftChild;
if (Parent == pLinks) {
return FALSE;
}
if (GetFieldValue(Parent, "RTL_SPLAY_LINKS", "LeftChild", LeftChild)) {
return FALSE;
}
if (LeftChild == pLinks) {
return TRUE;
}
return FALSE;
}
ULONG
DumpSplayTree(
IN ULONG64 pSplayLinks,
IN PDUMP_SPLAY_NODE_FN DumpNodeFn
)
/*++
Purpose:
Perform an in-order iteration across a splay tree, calling a
user supplied function with a pointer to each RTL_SPLAY_LINKS
structure encountered in the tree, and the level in the tree
at which it was encountered (zero based).
Arguments:
pSplayLinks - pointer to root of a splay tree
DumpNodeFn - user supplied dumping function
Returns:
Count of nodes encountered in the tree.
Notes:
Errors reading memory do not terminate the iteration if more
work is possible.
Consumes the Control-C flag to terminate possible loops in
corrupt structures.
--*/
{
ULONG Level = 0;
ULONG NodeCount = 0;
if (pSplayLinks) {
ULONG64 LeftChild, RightChild, Parent, Current;
//
// Retrieve the root links, find the leftmost node in the tree
//
if (GetFieldValue(Current = pSplayLinks,
"RTL_SPLAY_LINKS",
"LeftChild",
LeftChild)) {
return NodeCount;
}
while (LeftChild != 0) {
if ( CheckControlC() ) {
return NodeCount;
}
if (GetFieldValue(Current = LeftChild,
"RTL_SPLAY_LINKS",
"LeftChild",
LeftChild)) {
//
// We can try to continue from this
//
break;
}
Level++;
}
while (TRUE) {
if ( CheckControlC() ) {
return NodeCount;
}
NodeCount++;
pSplayLinks = Current;
(*DumpNodeFn)(pSplayLinks, Level);
/*
first check to see if there is a right subtree to the input link
if there is then the real successor is the left most node in
the right subtree. That is find and return P in the following diagram
Links
\
.
.
.
/
P
\
*/
GetFieldValue(Current, "RTL_SPLAY_LINKS", "RightChild", RightChild);
if (RightChild != 0) {
if (GetFieldValue(Current = RightChild,
"RTL_SPLAY_LINKS",
"RightChild",
RightChild)) {
//
// We've failed to step through to a successor, so
// there is no more to do
//
return NodeCount;
}
Level++;
GetFieldValue(Current,"RTL_SPLAY_LINKS","LeftChild",LeftChild);
while (LeftChild != 0) {
if ( CheckControlC() ) {
return NodeCount;
}
if (GetFieldValue(Current = LeftChild,
"RTL_SPLAY_LINKS",
"LeftChild",
LeftChild)) {
//
// We can continue from this
//
break;
}
Level++;
}
} else {
/*
we do not have a right child so check to see if have a parent and if
so find the first ancestor that we are a left decendent of. That
is find and return P in the following diagram
P
/
.
.
.
Links
*/
//
// If the IsLeft or IsRight functions fail to read through a parent
// pointer, then we will quickly exit through the break below
//
GetFieldValue(Current, "RTL_SPLAY_LINKS", "Parent", Parent);
while (DbgRtlIsRightChild(Current, Parent)) {
if ( CheckControlC() ) {
return NodeCount;
}
Level--;
pSplayLinks = (Current = Parent);
}
GetFieldValue(Current, "RTL_SPLAY_LINKS", "Parent", Parent);
if (!DbgRtlIsLeftChild(Current, Parent)) {
//
// we do not have a real successor so we break out
//
break;
} else {
Level--;
pSplayLinks = (Current = Parent);
}
}
}
}
return NodeCount;
}
VOID
DumpUnicode64(
UNICODE_STRING64 u
)
{
UNICODE_STRING v;
DWORD BytesRead;
// dprintf("L %x, M %x, B %p ", u.Length, u.MaximumLength, u.Buffer);
if ((u.Length <= u.MaximumLength) &&
(u.Buffer) &&
(u.Length > 0)) {
v.Buffer = LocalAlloc(LPTR, u.MaximumLength);
if (v.Buffer != NULL) {
v.MaximumLength = u.MaximumLength;
v.Length = u.Length;
if (ReadMemory(u.Buffer,
v.Buffer,
u.Length,
(PULONG) &u.Buffer)) {
dprintf("%wZ", &v);
} else {
dprintf("<???>");
}
LocalFree(v.Buffer);
return;
}
}
}
BOOLEAN
IsHexNumber(
const char *szExpression
)
{
if (!szExpression[0]) {
return FALSE ;
}
for(;*szExpression; szExpression++) {
if ((*szExpression)< '0') { return FALSE ; }
else if ((*szExpression)> 'f') { return FALSE ; }
else if ((*szExpression)>='a') { continue ; }
else if ((*szExpression)> 'F') { return FALSE ; }
else if ((*szExpression)<='9') { continue ; }
else if ((*szExpression)>='A') { continue ; }
else { return FALSE ; }
}
return TRUE ;
}
BOOLEAN
IsDecNumber(
const char *szExpression
)
{
if (!szExpression[0]) {
return FALSE ;
}
while(*szExpression) {
if ((*szExpression)<'0') { return FALSE ; }
else if ((*szExpression)>'9') { return FALSE ; }
szExpression ++ ;
}
return TRUE ;
}
ULONG64
UtilStringToUlong64 (
UCHAR *String
)
{
UCHAR LowDword[9], HighDword[9];
ZeroMemory (&HighDword, sizeof (HighDword));
ZeroMemory (&LowDword, sizeof (LowDword));
if (strlen (String) > 8) {
memcpy (&LowDword, (void *) &String[strlen (String) - 8], 8);
memcpy (&HighDword, (void *) &String[0], strlen (String) - 8);
} else {
return strtoul (String, 0, 16);
}
return ((ULONG64) strtoul (HighDword, 0, 16) << 32) + strtoul (LowDword, 0, 16);
}
const char *
getEnumName(
ULONG EnumVal,
PENUM_NAME EnumTable
)
/*++
Routine Description:
Gets the supplied enum value's name in string format
Arguments:
EnumVal - Enum to be retrieved
EnumTable - Table in which the enum is looked up to find
the string to be retrieved (since we can't rely on the debugger)
Return Value:
None
--*/
{
ULONG i;
for (i=0; EnumTable[i].Name != NULL; i++) {
if (EnumTable[i].EnumVal == EnumVal) {
break;
}
}
if (EnumTable[i].Name != NULL) {
return EnumTable[i].Name;
} else {
return "Unknown ";
}
}