windows-nt/Source/XPSP1/NT/ds/adsi/dbgexts/dbgarg.c
2020-09-26 16:20:57 +08:00

261 lines
5.5 KiB
C

/*++
Copyright (c) 1990 - 1994 Microsoft Corporation
All rights reserved
Module Name:
dbgspl.c
Abstract:
Debugging tools for Argus
Author:
Krishna Ganugapati (KrishnaG) 28-December-1994
Revision History:
KrishnaG: Created: 28-December-1994
To do:
--*/
#define NOMINMAX
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <stdlib.h>
#include <math.h>
#include <ntsdexts.h>
#include "dbglocal.h"
typedef void (*PNTSD_OUTPUT_ROUTINE)(char *, ...);
//+---------------------------------------------------------------------------
//
// Function: DumpVtbl
//
// Synopsis: Dumps a vtbl to the debugger
//
// Effects: Given a pointer to a vtbl, output the name of the vtbl, and
// its contents to the debugger.
//
// Arguments: [pvtbl] -- Address of vtbl
// [pszCommand] -- Symbolic expression for pvtbl
//
// History: 8-07-94 kevinro Created
// 12-28-94 krishnaG swiped from the Ole project
//
//----------------------------------------------------------------------------
BOOL
DumpVtbl(
HANDLE hCurrentProcess,
HANDLE hCurrentThread,
DWORD dwCurrentPc,
PNTSD_EXTENSION_APIS lpExtensionApis,
LPSTR lpArgumentString,
PVOID pvtbl
)
{
DWORD dwVtblOffset;
char achNextSymbol[256];
DWORD dwIndex;
DWORD dwVtblEntry;
if (pvtbl == 0)
{
// Can't handle objects at zero
// ntsdPrintf("%s has a vtbl pointer of NULL\n", pszCommand);
return 0;
}
if ((DWORD)pvtbl == 0xdededede)
{
// Can't handle objects at zero
// ntsdPrintf("%s may be deleted memory. pvtbl==0xdededede\n",pszCommand);
return 0;
}
//
// This value points at the VTBL. Find a symbol for the VTBL
//
ntsdGetSymbol((LPVOID)pvtbl,(UCHAR *)achNextSymbol,(LPDWORD)&dwVtblOffset);
//
// If the dwVtblOffset is not zero, then we are pointing into the table.
// This could mean multiple inheritance. We could be tricky, and try to
// determine the vtbl by backing up here. Maybe later
//
if (dwVtblOffset != 0){
ntsdPrintf("Closest Previous symbol is %s at 0x%x (offset -0x%x)\n",
achNextSymbol,
(DWORD)pvtbl - dwVtblOffset,
dwVtblOffset);
return 0;
}
ntsdPrintf("0x%08x -->\t %s\n",pvtbl,achNextSymbol);
//
// vtbl entries should always point at functions. Therefore, we should
// always have a displacement of zero. To check for the end of the table
// we will reevaluate the vtbl pointer. If the offset isn't what we
// expected, then we are done.
//
for (dwIndex = 0 ; dwIndex < 4096 ; dwIndex += 4)
{
ntsdGetSymbol((LPVOID)((DWORD)pvtbl+dwIndex),
(UCHAR *)achNextSymbol,
(LPDWORD)&dwVtblOffset);
if (dwVtblOffset != dwIndex){
//
// May have moved on to another vtable
//
#if DBG
ntsdPrintf("?? %s + %x\n",achNextSymbol,dwVtblOffset);
ntsdPrintf("Moved to another table?\n");
#endif
return 0;
}
movemem(
(LPVOID)((DWORD)(pvtbl)+dwIndex),
(PVOID)&dwVtblEntry,
sizeof(dwVtblEntry)
);
//
// If the function is at zero, then must be at end of table
//
if (dwVtblEntry == 0) {
#if DBG
ntsdPrintf("dwVtblEntry is zero. Must be end of table\n");
return 0;
#endif
}
// Now, determine the symbol for the entry in the vtbl
ntsdGetSymbol((LPVOID)dwVtblEntry,
(UCHAR *)achNextSymbol,
(LPDWORD)&dwVtblOffset);
// If it doesn't point to the start of a routine, then it
// probably isn't part of the vtbl
if (dwVtblOffset != 0)
{
#if DBG
ntsdPrintf("?? %s + %x\n",achNextSymbol,dwVtblOffset);
ntsdPrintf("Doesn't point to function?\n");
#endif
return 0;
}
ntsdPrintf(" 0x%08x\t %s\n",dwVtblEntry,achNextSymbol);
}
ntsdPrintf("Wow, there were at least 1024 entries in the table!\n");
return(TRUE);
}
void
vtbl(
HANDLE hCurrentProcess,
HANDLE hCurrentThread,
DWORD dwCurrentPc,
PNTSD_EXTENSION_APIS lpExtensionApis,
LPSTR lpArgumentString
)
{
PVOID pvtbl;
//
// Evalute the first pointer. This is a pointer to the table
//
pvtbl = (PVOID) ntsdGetExpr(lpArgumentString);
DumpVtbl(
hCurrentProcess,
hCurrentThread,
dwCurrentPc,
lpExtensionApis,
lpArgumentString,
pvtbl
);
}
BOOL dp(
HANDLE hCurrentProcess,
HANDLE hCurrentThread,
DWORD dwCurrentPc,
PNTSD_EXTENSION_APIS lpExtensionApis,
LPSTR lpArgumentString)
{
PNTSD_OUTPUT_ROUTINE Print;
PNTSD_GET_EXPRESSION EvalExpression;
PNTSD_GET_SYMBOL GetSymbol;
DWORD dwAddress = 0;
BOOL bThereAreOptions = TRUE;
Print = lpExtensionApis->lpOutputRoutine;
EvalExpression = lpExtensionApis->lpGetExpressionRoutine;
GetSymbol = lpExtensionApis->lpGetSymbolRoutine;
while (bThereAreOptions) {
while (isspace(*lpArgumentString)) {
lpArgumentString++;
}
switch (*lpArgumentString) {
default: // go get the address because there's nothing else
bThereAreOptions = FALSE;
break;
}
}
if (*lpArgumentString != 0) {
dwAddress = EvalValue(&lpArgumentString, EvalExpression, Print);
}else {
Print("Usage: !argexts.dp <addr of object>\n");
return(TRUE);
}
//
// Now dump out the object
//
return TRUE;
}