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.
406 lines
11 KiB
406 lines
11 KiB
//+----------------------------------------------------------------------------
|
|
//
|
|
// File: slist.c
|
|
//
|
|
// Module: Debugger extension DLL
|
|
//
|
|
// Synopsis: !slist debugger extension for ntsd and kd. Dumps the SLIST
|
|
// header and then walks the SLIST displaying the address of
|
|
// each node on the list.
|
|
//
|
|
// Copyright (C) 2001 Microsoft Corporation
|
|
//
|
|
// Created: 14 Nov 2001 Scott Gasch (sgasch)
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
|
|
#include "precomp.h"
|
|
#include "ntrtl.h"
|
|
#include <string.h>
|
|
#pragma hdrstop
|
|
|
|
#define ARRAY_COUNT(x) (sizeof(x) / sizeof((x)[0]))
|
|
|
|
CHAR *g_szNodeType = NULL;
|
|
ULONG64 g_uOffset = 0;
|
|
ULONG64 g_uSlistHead = 0;
|
|
ULONG g_uPtrSize = 0;
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DisplaySlistHelp
|
|
//
|
|
// Synopsis: Display a simple usage message
|
|
//
|
|
// Arguments: void
|
|
//
|
|
// Returns: void
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
void
|
|
DisplaySlistHelp(void)
|
|
{
|
|
dprintf("!slist <address> [symbol [offset]]\n\n"
|
|
"Dump the slist with header at address. If symbol and offset are\n"
|
|
"present, assume each node on the SLIST is of type symbol and that\n"
|
|
"the SLIST pointer is at offset in the struct.\n\n"
|
|
"Examples:\n"
|
|
" !slist 80543ea8\n"
|
|
" !slist myprog!SlistHeader myprog!NODE 0\n");
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DumpSlistHeader
|
|
//
|
|
// Synopsis: Given the address of the SLIST header, dump it.
|
|
//
|
|
// Arguments: ULONG64 u64AddrSlistHeader -- addr of SLIST_HEADER in debugee mem
|
|
//
|
|
// Returns: void
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
void
|
|
DumpSlistHeader(void)
|
|
{
|
|
ULONG uOffset; // field offset within the struct
|
|
|
|
dprintf("SLIST HEADER:\n");
|
|
|
|
if (InitTypeRead(g_uSlistHead,
|
|
nt!_SLIST_HEADER))
|
|
{
|
|
dprintf("Unable to read type nt!_SLIST_HEADER at %p\n",
|
|
g_uSlistHead);
|
|
dprintf("Please check your symbols and sympath.\n");
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Depending on the type of machine we are debugging, dump the proper
|
|
// SLIST_HEADER structure. Note this must change is the definition of
|
|
// SLIST_HEADER changes in ntrtl.h.
|
|
//
|
|
if ((TargetMachine == IMAGE_FILE_MACHINE_IA64) ||
|
|
(TargetMachine == IMAGE_FILE_MACHINE_AMD64))
|
|
{
|
|
GetFieldOffset ("nt!_SLIST_HEADER", "Alignment", &uOffset);
|
|
dprintf(" +0x%03x Alignment : %I64x\n",
|
|
uOffset, ReadField(Alignment));
|
|
dprintf(" +0x%03x (Depth) : %x\n",
|
|
uOffset, ReadField(Alignment) & 0xFFFF);
|
|
GetFieldOffset ("nt!_SLIST_HEADER", "Region", &uOffset);
|
|
dprintf(" +0x%03x Region : %I64x\n",
|
|
uOffset, ReadField(Region));
|
|
}
|
|
else
|
|
{
|
|
GetFieldOffset ("nt!_SLIST_HEADER", "Alignment", &uOffset);
|
|
dprintf(" +0x%03x Alignment : %I64x\n",
|
|
uOffset, ReadField(Alignment));
|
|
GetFieldOffset ("nt!_SLIST_HEADER", "Next", &uOffset);
|
|
dprintf(" +0x%03x Next : %I64x\n",
|
|
uOffset, ReadField(Next));
|
|
GetFieldOffset ("nt!_SLIST_HEADER", "Depth", &uOffset);
|
|
dprintf(" +0x%03x Depth : %I64x\n",
|
|
uOffset, ReadField(Depth));
|
|
GetFieldOffset ("nt!_SLIST_HEADER", "Sequence", &uOffset);
|
|
dprintf(" +0x%03x Sequence : %I64x\n",
|
|
uOffset, ReadField(Sequence));
|
|
}
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DumpSlist
|
|
//
|
|
// Synopsis: Walk and display the SLIST.
|
|
//
|
|
// Arguments: ULONG64 pHeader -- addr of SLIST_HEADER in debugee mem
|
|
//
|
|
// Returns: void
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
void
|
|
DumpSlist(void)
|
|
{
|
|
ULONG uError; // result of ReadPointer operations
|
|
ULONG64 pCurrent; // ptr to current item
|
|
ULONG64 pNext; // ptr to next item
|
|
ULONG64 u64Head; // first item scratch var
|
|
ULONG64 u64Region; // region info for ia64 headers
|
|
SYM_DUMP_PARAM SymDump;
|
|
ULONG x;
|
|
|
|
//
|
|
// Determine the address of the first node on the list.
|
|
//
|
|
if ((TargetMachine == IMAGE_FILE_MACHINE_IA64) ||
|
|
(TargetMachine == IMAGE_FILE_MACHINE_AMD64))
|
|
{
|
|
//
|
|
// For ia64, getting the first node involves some work. It's
|
|
// made up of some bits from the Alignment part of the header
|
|
// and a few bits from the Region part of the header.
|
|
//
|
|
// First read the Alignment part in.
|
|
//
|
|
uError = ReadPointer(g_uSlistHead, &u64Head);
|
|
if (!uError)
|
|
{
|
|
dprintf("Can't read memory at %p, error %x\n",
|
|
g_uSlistHead, uError);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Now read the Region part in, 8 bytes later.
|
|
//
|
|
uError = ReadPointer(g_uSlistHead + 8, &u64Region);
|
|
if (!uError)
|
|
{
|
|
dprintf("Can't read memory at %p, error %x\n",
|
|
(g_uSlistHead + 8), uError);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Note to self:
|
|
//
|
|
// 25 == SLIST_ADR_BITS_START
|
|
// 4 == SLIST_ADR_ALIGMENT
|
|
//
|
|
// See base\ntos\rtl\ia64\slist.s
|
|
//
|
|
pCurrent = ((u64Head >> 25) << 4);
|
|
pCurrent += u64Region;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// For x86 this is easy, the pointer is sitting in the first 4
|
|
// bytes of the Header.
|
|
//
|
|
uError = ReadPointer(g_uSlistHead, &u64Head);
|
|
if (!uError)
|
|
{
|
|
dprintf("Can't read memory at %p, error %x\n",
|
|
g_uSlistHead, uError);
|
|
return;
|
|
}
|
|
pCurrent = u64Head;
|
|
}
|
|
dprintf("\nSLIST CONTENTS:\n");
|
|
|
|
//
|
|
// Walk until NULL termination
|
|
//
|
|
while((ULONG64)0 != pCurrent)
|
|
{
|
|
//
|
|
// Be responsive to ^C, allow dump of SLIST to be aborted
|
|
//
|
|
if (TRUE == CheckControlC())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Dump this one
|
|
//
|
|
if (NULL == g_szNodeType)
|
|
{
|
|
dprintf("%p ", pCurrent);
|
|
|
|
for (x = 0;
|
|
x < 4;
|
|
x++)
|
|
{
|
|
uError = ReadPointer(pCurrent + (x * g_uPtrSize), &pNext);
|
|
if (!uError)
|
|
{
|
|
dprintf("Can't read memory at address %p, error %x\n",
|
|
pCurrent + (x * g_uPtrSize), uError);
|
|
pNext = 0;
|
|
} else
|
|
{
|
|
if (g_uPtrSize == 4)
|
|
{
|
|
dprintf("%08x ", pNext);
|
|
}
|
|
else
|
|
{
|
|
dprintf("%08x%08x ",
|
|
(pNext & 0xFFFFFFFF00000000) >> 32,
|
|
pNext & 0x00000000FFFFFFFF);
|
|
if (x == 1) dprintf("\n ");
|
|
}
|
|
}
|
|
|
|
}
|
|
dprintf("\n");
|
|
}
|
|
else
|
|
{
|
|
dprintf("%p\n",
|
|
(pCurrent - g_uOffset));
|
|
|
|
SymDump.size = sizeof(SYM_DUMP_PARAM);
|
|
SymDump.sName = (PUCHAR)g_szNodeType;
|
|
SymDump.Options = 0;
|
|
SymDump.addr = pCurrent - g_uOffset;
|
|
SymDump.listLink = NULL;
|
|
SymDump.Context = NULL;
|
|
SymDump.CallbackRoutine = NULL;
|
|
SymDump.nFields = 0;
|
|
SymDump.Fields = NULL;
|
|
|
|
Ioctl(IG_DUMP_SYMBOL_INFO, &SymDump, SymDump.size);
|
|
}
|
|
|
|
//
|
|
// Get the next one
|
|
//
|
|
uError = ReadPointer(pCurrent, &pNext);
|
|
if (!uError)
|
|
{
|
|
dprintf("Can't read memory at %p, error %x\n",
|
|
pCurrent, uError);
|
|
return;
|
|
}
|
|
pCurrent = pNext;
|
|
}
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: slist
|
|
//
|
|
// Synopsis: Entry point for !slist
|
|
//
|
|
// Arguments: Arguments to command in char *args
|
|
//
|
|
// Returns: S_OK
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
|
|
DECLARE_API(slist)
|
|
{
|
|
SLIST_HEADER sSlistHeader;
|
|
ULONG64 u64AddrSlistHeader = 0;
|
|
BOOL fSuccess;
|
|
CHAR *pArgs = NULL;
|
|
CHAR *pDelims = " \t";
|
|
CHAR *pToken;
|
|
DWORD dwNumTokens = 0;
|
|
|
|
INIT_API();
|
|
|
|
//
|
|
// Reset params from last time we ran.
|
|
//
|
|
g_uSlistHead = 0;
|
|
if (NULL != g_szNodeType)
|
|
{
|
|
free(g_szNodeType);
|
|
g_szNodeType = NULL;
|
|
}
|
|
g_uOffset = 0;
|
|
|
|
if ((TargetMachine == IMAGE_FILE_MACHINE_IA64) ||
|
|
(TargetMachine == IMAGE_FILE_MACHINE_AMD64))
|
|
{
|
|
g_uPtrSize = 8;
|
|
}
|
|
else
|
|
{
|
|
g_uPtrSize = 4;
|
|
}
|
|
|
|
//
|
|
// Parse our arguments
|
|
//
|
|
pArgs = _strdup(args);
|
|
if (NULL == pArgs)
|
|
{
|
|
dprintf("Debugger machine out of memory!\n");
|
|
goto Done;
|
|
}
|
|
|
|
pToken = strtok(pArgs, pDelims);
|
|
while (NULL != pToken)
|
|
{
|
|
dwNumTokens++;
|
|
|
|
if ((!strncmp(pToken, "-help", 5)) ||
|
|
(!strncmp(pToken, "-?", 2)) ||
|
|
(!strncmp(pToken, "/help", 5)) ||
|
|
(!strncmp(pToken, "/?", 2)))
|
|
{
|
|
DisplaySlistHelp();
|
|
goto Done;
|
|
}
|
|
else
|
|
{
|
|
if (0 == g_uSlistHead)
|
|
{
|
|
g_uSlistHead = GetExpression(pToken);
|
|
}
|
|
else if (NULL == g_szNodeType)
|
|
{
|
|
g_szNodeType = _strdup(pToken);
|
|
if (NULL == g_szNodeType)
|
|
{
|
|
dprintf("Debugger machine out of memory!\n");
|
|
goto Done;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
g_uOffset = GetExpression(pToken);
|
|
}
|
|
}
|
|
pToken = strtok(NULL, pDelims);
|
|
}
|
|
|
|
//
|
|
// If they called with no commandline, give them the help.
|
|
//
|
|
if (0 == dwNumTokens)
|
|
{
|
|
DisplaySlistHelp();
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Dump the slist header
|
|
//
|
|
DumpSlistHeader();
|
|
|
|
//
|
|
// Walk the slist
|
|
//
|
|
DumpSlist();
|
|
|
|
Done:
|
|
g_uSlistHead = 0;
|
|
if (NULL != g_szNodeType)
|
|
{
|
|
free(g_szNodeType);
|
|
g_szNodeType = NULL;
|
|
}
|
|
g_uOffset = 0;
|
|
g_uPtrSize = 0;
|
|
|
|
if (NULL != pArgs)
|
|
{
|
|
free(pArgs);
|
|
}
|
|
|
|
EXIT_API();
|
|
return(S_OK);
|
|
}
|
|
|