You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
447 lines
12 KiB
447 lines
12 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
afds.c
|
|
|
|
Abstract:
|
|
|
|
Implements afds command
|
|
|
|
Author:
|
|
|
|
Vadim Eydelman, March 2000
|
|
|
|
Environment:
|
|
|
|
User Mode.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "afdkdp.h"
|
|
#pragma hdrstop
|
|
|
|
#define AFDKD_TOKEN "@$."
|
|
#define AFDKD_TOKSZ (sizeof (AFDKD_TOKEN)-1)
|
|
|
|
ULONG
|
|
ListCallback (
|
|
PFIELD_INFO pField,
|
|
PVOID UserContext
|
|
);
|
|
|
|
//
|
|
// Public functions.
|
|
//
|
|
|
|
ULONG LinkOffset;
|
|
|
|
DECLARE_API( afds )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps afd endpoints
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG64 address;
|
|
CHAR expr[MAX_ADDRESS_EXPRESSION];
|
|
PCHAR argp;
|
|
INT i;
|
|
ULONG result;
|
|
|
|
gClient = pClient;
|
|
|
|
argp = ProcessOptions ((PCHAR)args);
|
|
if (argp==NULL)
|
|
return E_INVALIDARG;
|
|
|
|
if ((Options & (AFDKD_LINK_FIELD|AFDKD_LIST_TYPE)) !=
|
|
(AFDKD_LINK_FIELD|AFDKD_LIST_TYPE)) {
|
|
dprintf ("\nafds: Missing link or list type specification");
|
|
dprintf ("\nUsage:\nafds -l link -t type [options] address\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (sscanf( argp, "%s%n", expr, &i )!=1) {
|
|
dprintf ("\nafds: Missing address specification");
|
|
dprintf ("\nUsage:\nafds -l link -t type [options] address\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
argp += i;
|
|
|
|
address = GetExpression (expr);
|
|
|
|
if (Options & AFDKD_LINK_SELF) {
|
|
result = GetFieldOffset (ListedType, LinkField, &LinkOffset);
|
|
if (result!=0) {
|
|
dprintf ("\nafds: Cannot get offset of %s in %s, err: %ld\n",
|
|
LinkField, ListedType, result);
|
|
return E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
ListType (
|
|
(Options & AFDKD_LINK_SELF)
|
|
? "LIST_ENTRY"
|
|
: ListedType, // Type
|
|
address, // Address
|
|
(Options & AFDKD_LINK_AOF)
|
|
? 1
|
|
: 0, // ListByFieldAddress
|
|
(Options & AFDKD_LINK_SELF)
|
|
? "Flink"
|
|
: LinkField, // NextPointer
|
|
ListedType, // Context
|
|
ListCallback);
|
|
dprintf ("\n");
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
ULONG
|
|
ListCallback (
|
|
PFIELD_INFO pField,
|
|
PVOID UserContext
|
|
)
|
|
{
|
|
ULONG64 address;
|
|
address = pField->address;
|
|
if (Options & AFDKD_LINK_SELF) {
|
|
address -= LinkOffset;
|
|
}
|
|
if (!(Options & AFDKD_CONDITIONAL) ||
|
|
CheckConditional (address, UserContext)) {
|
|
dprintf ("\n%s @ %p", UserContext, address);
|
|
ProcessFieldOutput (address, UserContext);
|
|
}
|
|
else {
|
|
dprintf (".");
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
{
|
|
ULONG64
|
|
GetExpressionFromType (
|
|
ULONG64 Address,
|
|
PCHAR Type,
|
|
PCHAR Expression
|
|
)
|
|
CHAR expr[MAX_CONDITIONAL_EXPRESSION];
|
|
PCHAR argp = Expression, pe = expr, pestop=pe+sizeof(expr)-1;
|
|
ULONG result;
|
|
ULONG64 value;
|
|
PCHAR type = Type;
|
|
ULONG64 address = Address;
|
|
|
|
while (*argp) {
|
|
if (*argp=='@' && strncmp (argp, AFDKD_TOKEN, AFDKD_TOKSZ)==0) {
|
|
PCHAR end = pe;
|
|
argp+= AFDKD_TOKSZ;
|
|
while (isalnum (*argp) ||
|
|
*argp=='[' ||
|
|
*argp==']' ||
|
|
*argp=='_' ||
|
|
*argp=='.' ||
|
|
*argp=='-') {
|
|
if (*argp=='-') {
|
|
if (*(argp+1)=='>') {
|
|
if (*(argp+2)=='(') {
|
|
*end = 0;
|
|
result = GetFieldValue (address, type, pe, value);
|
|
if (result!=0) {
|
|
dprintf ("\nCheckConditional: Can't get %s.%s at %p (err:%d)\n", type, pe, address, result);
|
|
return FALSE;
|
|
}
|
|
if (value==0)
|
|
return FALSE;
|
|
argp += 3;
|
|
type = argp;
|
|
while (*argp && *argp!=')') {
|
|
argp += 1;
|
|
}
|
|
*argp++ = 0;
|
|
address = value;
|
|
end = pe;
|
|
continue;
|
|
|
|
}
|
|
if (end>=pestop)
|
|
break;
|
|
*end++ = *argp++;
|
|
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
if (end>=pestop)
|
|
break;
|
|
*end++ = *argp++;
|
|
}
|
|
*end = 0;
|
|
result = GetFieldValue (address, type, pe, value);
|
|
if (result!=0) {
|
|
dprintf ("\nCheckConditional: Can't get %s.%s at %p (err:%d)\n", type, pe, address, result);
|
|
return FALSE;
|
|
}
|
|
pe += _snprintf (pe, pestop-pe, "0x%I64X", value);
|
|
address = Address;
|
|
type = Type;
|
|
}
|
|
else {
|
|
if (pe>=pestop)
|
|
break;
|
|
*pe++ = *argp++;
|
|
}
|
|
}
|
|
*pe = 0;
|
|
|
|
return GetExpression (expr);
|
|
}
|
|
*/
|
|
|
|
BOOLEAN
|
|
CheckConditional (
|
|
ULONG64 Address,
|
|
PCHAR Type
|
|
)
|
|
{
|
|
DEBUG_VALUE val;
|
|
|
|
if (GetExpressionFromType (Address, Type, Conditional, DEBUG_VALUE_INT64, &val)==S_OK)
|
|
return val.I64!=0;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
VOID
|
|
ProcessFieldOutput (
|
|
ULONG64 Address,
|
|
PCHAR Type
|
|
)
|
|
{
|
|
ULONG result;
|
|
|
|
FldParam.addr = Address;
|
|
FldParam.sName = Type;
|
|
if (Options & AFDKD_NO_DISPLAY) {
|
|
FldParam.Options |= DBG_DUMP_COMPACT_OUT;
|
|
}
|
|
|
|
dprintf ("\n");
|
|
if (FldParam.nFields>0 ||
|
|
(FldParam.nFields==0 && CppFieldEnd==0)) {
|
|
result = Ioctl (IG_DUMP_SYMBOL_INFO, &FldParam, FldParam.size );
|
|
if (result!=0) {
|
|
dprintf ("\nProcessFieldOutput: IG_DUMP_SYMBOL_INFO failed, err: %ld\n", result);
|
|
}
|
|
}
|
|
if (CppFieldEnd>FldParam.nFields) {
|
|
ULONG i;
|
|
for (i=FldParam.nFields; i<CppFieldEnd; i++) {
|
|
DEBUG_VALUE val;
|
|
if (GetExpressionFromType (Address, Type, FldParam.Fields[i].fName,
|
|
DEBUG_VALUE_INVALID,
|
|
&val)==S_OK) {
|
|
dprintf (" %s = 0x%I64x(%d)\n",
|
|
&FldParam.Fields[i].fName[AFDKD_CPP_PREFSZ],
|
|
val.I64,
|
|
val.Type
|
|
);
|
|
}
|
|
/*
|
|
SYM_DUMP_PARAM fldParam;
|
|
CHAR fieldStr[MAX_FIELD_CHARS], *p;
|
|
FIELD_INFO field = FldParam.Fields[i];
|
|
ULONG64 value;
|
|
ULONG skip = 0;
|
|
fldParam = FldParam;
|
|
fldParam.nFields = 1;
|
|
fldParam.Fields = &field;
|
|
//fldParam.Options |= DBG_DUMP_NO_PRINT;
|
|
strncpy (fieldStr, field.fName, sizeof (fieldStr));
|
|
field.fName = p = fieldStr;
|
|
field.fOptions |= DBG_DUMP_FIELD_COPY_FIELD_DATA;
|
|
field.fieldCallBack = &value;
|
|
while ((p=strstr (p, "->("))!=NULL) {
|
|
*p = 0;
|
|
result = Ioctl (IG_DUMP_SYMBOL_INFO, &fldParam, fldParam.size );
|
|
if (result!=0) {
|
|
dprintf ("\nProcessFieldOutput: GetFieldValue (%p,%s,%s) failed, err: %ld\n",
|
|
fldParam.addr,
|
|
fldParam.sName,
|
|
field.fName,
|
|
result);
|
|
goto DoneField;
|
|
}
|
|
fldParam.addr = value;
|
|
|
|
p += sizeof ("->(")-1;
|
|
fldParam.sName = p;
|
|
p = strchr (p, ')');
|
|
if (p==NULL) {
|
|
dprintf ("\nProcessFieldOutput: missing ')' in %s\n", fldParam.sName);
|
|
goto DoneField;
|
|
}
|
|
*p++ = 0;
|
|
|
|
skip += 3;
|
|
dprintf ("%*.80s%s : %I64x->(%s)\n", skip, " ",
|
|
field.fName,
|
|
DISP_PTR(value),
|
|
fldParam.sName);
|
|
|
|
field.fName = p;
|
|
if (value==0) {
|
|
goto DoneField;
|
|
}
|
|
}
|
|
//fldParam.Options &= (~DBG_DUMP_NO_PRINT);
|
|
field.fOptions &= ~(DBG_DUMP_FIELD_COPY_FIELD_DATA);
|
|
field.fieldCallBack = NULL;
|
|
result = Ioctl (IG_DUMP_SYMBOL_INFO, &fldParam, fldParam.size );
|
|
if (result!=0) {
|
|
dprintf ("\nProcessFieldOutput: IG_DUMP_SYMBOL_INFO %p %s %s failed, err: %ld\n",
|
|
fldParam.addr,
|
|
fldParam.sName,
|
|
field.fName,
|
|
result);
|
|
break;
|
|
}
|
|
|
|
DoneField:
|
|
;
|
|
*/
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
DECLARE_API( filefind )
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Searches non-paged pool for FILE_OBJECT given its FsContext field.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
|
|
ULONG64 FsContext;
|
|
ULONG64 PoolStart, PoolEnd, PoolPage;
|
|
ULONG64 PoolExpansionStart, PoolExpansionEnd;
|
|
ULONG result;
|
|
ULONG64 val;
|
|
BOOLEAN twoPools;
|
|
|
|
gClient = pClient;
|
|
|
|
if (!CheckKmGlobals ()) {
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
FsContext = GetExpression (args);
|
|
if (FsContext==0 || FsContext<UserProbeAddress) {
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if ( (result = ReadPtr (DebuggerData.MmNonPagedPoolStart, &PoolStart))!=0 ||
|
|
(result = ReadPtr (DebuggerData.MmNonPagedPoolEnd, &PoolEnd))!=0 ) {
|
|
dprintf ("\nfilefind - Cannot get non-paged pool limits, err: %ld\n",
|
|
result);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (PoolStart + DebuggerData.MmMaximumNonPagedPoolInBytes!=PoolEnd) {
|
|
if ( (result = GetFieldValue (0,
|
|
"NT!MmSizeOfNonPagedPoolInBytes",
|
|
NULL,
|
|
val))!=0 ||
|
|
(result = GetFieldValue (0,
|
|
"NT!MmNonPagedPoolExpansionStart",
|
|
NULL,
|
|
PoolExpansionStart))!=0 ) {
|
|
dprintf ("\nfilefind - Cannot get non-paged pool expansion limits, err: %ld\n",
|
|
result);
|
|
return E_INVALIDARG;
|
|
}
|
|
PoolExpansionEnd = PoolEnd;
|
|
PoolEnd = PoolStart + val;
|
|
twoPools = TRUE;
|
|
}
|
|
else {
|
|
twoPools = FALSE;
|
|
}
|
|
|
|
|
|
PoolPage = PoolStart;
|
|
dprintf ("Searching non-paged pool %p - %p...\n", PoolStart, PoolEnd);
|
|
while (PoolPage<PoolEnd) {
|
|
SEARCHMEMORY Search;
|
|
|
|
if (CheckControlC ()) {
|
|
break;
|
|
}
|
|
|
|
Search.SearchAddress = PoolPage;
|
|
Search.SearchLength = PoolEnd-PoolPage;
|
|
Search.Pattern = &FsContext;
|
|
Search.PatternLength = IsPtr64 () ? sizeof (ULONG64) : sizeof (ULONG);
|
|
Search.FoundAddress = 0;
|
|
|
|
if (Ioctl (IG_SEARCH_MEMORY, &Search, sizeof (Search)) &&
|
|
Search.FoundAddress!=0) {
|
|
ULONG64 fileAddr;
|
|
fileAddr = Search.FoundAddress-FsContextOffset;
|
|
result = (ULONG)InitTypeRead (fileAddr, NT!_FILE_OBJECT);
|
|
if (result==0 && (CSHORT)ReadField (Type)==IO_TYPE_FILE) {
|
|
dprintf ("File object at %p\n", fileAddr);
|
|
}
|
|
else {
|
|
dprintf (" pool search match at %p\n", Search.FoundAddress);
|
|
}
|
|
PoolPage = Search.FoundAddress +
|
|
(IsPtr64() ? sizeof (ULONG64) : sizeof (ULONG));
|
|
}
|
|
else {
|
|
if (!twoPools || PoolEnd==PoolExpansionEnd) {
|
|
break;
|
|
}
|
|
else {
|
|
dprintf ("Searching expansion non-paged pool %p - %p...\n",
|
|
PoolExpansionStart, PoolExpansionEnd);
|
|
PoolEnd = PoolExpansionEnd;
|
|
PoolPage = PoolExpansionStart;
|
|
}
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|