|
|
/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
heap.c
Abstract:
This function contains the default ntsd debugger extensions
Author:
Bob Day (bobday) 29-Feb-1992 Grabbed standard header
Revision History:
Neil Sandlin (NeilSa) 15-Jan-1996 Merged with vdmexts
--*/
#include <precomp.h>
#pragma hdrstop
#define MYOF_FLAGS (OF_READ | OF_SHARE_DENY_NONE)
#define MAX_MODULE_LIST 200
char ModuleList[MAX_MODULE_LIST][9]; int ModuleListCount = 0;
BOOL GetVdmDbgEntry( LPSTR szEntryPoint, PVOID *pProc ) { HANDLE hModVDM; hModVDM = GetModuleHandle("VDMDBG.DLL"); if (hModVDM == (HANDLE)NULL) { PRINTF("VDMEXTS: Can't find vdmdbg.dll\n"); return FALSE; }
*pProc = GetProcAddress(hModVDM, szEntryPoint);
if (!*pProc) { PRINTF("VDMEXTS: Can't find VDMDBG.DLL entry point %s\n", szEntryPoint); return FALSE; } return TRUE; }
PSEGENTRY GetSegtablePointer( VOID ) { static PSEGENTRY (WINAPI *pfnVDMGetSegtablePointer)(VOID) = NULL;
if (!pfnVDMGetSegtablePointer && !GetVdmDbgEntry("VDMGetSegtablePointer", (PVOID)&pfnVDMGetSegtablePointer)) { return NULL; }
return((*pfnVDMGetSegtablePointer)()); }
VOID ParseModuleName( LPSTR szName, LPSTR szPath ) /*++
Routine Description:
This routine strips off the 8 character file name from a path
Arguments:
szName - pointer to buffer of 8 characters (plus null) szPath - full path of file
Return Value
None.
--*/
{ LPSTR lPtr = szPath; LPSTR lDest = szName; int BufferSize = 9;
while(*lPtr) lPtr++; // scan to end
while( ((DWORD)lPtr > (DWORD)szPath) && ((*lPtr != '\\') && (*lPtr != '/'))) lPtr--;
if (*lPtr) lPtr++;
while((*lPtr) && (*lPtr!='.')) { if (!--BufferSize) break; *lDest++ = *lPtr++; }
*lDest = 0; }
BOOL FindModuleNameList( LPSTR filename ) { int i;
for (i=0; i<ModuleListCount; i++) {
if (!_stricmp(filename, ModuleList[i])) { return TRUE; } } return FALSE; }
BOOL AddModuleNameList( LPSTR filename ) { if (!strlen(filename)) { return FALSE; }
if (!FindModuleNameList(filename)) { if (ModuleListCount>=(MAX_MODULE_LIST-1)) { return FALSE; } strcpy (ModuleList[ModuleListCount++], filename); } return TRUE; }
VOID FreeModuleNameList( VOID ) { ModuleListCount = 0; return; }
VOID BuildModuleNameList( VOID ) { HEAPENTRY he = {0}; SEGENTRY *se; char filename[9]; WORD sel; BOOL b; NEHEADER owner; ULONG base; CHAR ModuleName[9]; UCHAR len;
//
// Search WOW Module list
//
if (!ReadMemExpression("ntvdmd!DbgWowhExeHead", &sel, sizeof(sel))) { return; }
while(sel) {
base = GetInfoFromSelector(sel, PROT_MODE, NULL) + GetIntelBase();
b = READMEM((LPVOID)base, &owner, sizeof(owner));
if (!b || (owner.ne_magic != 0x454e)) { PRINTF("Invalid module list! (started with hExeHead)\n"); return; }
len = ReadByteSafe(base+owner.ne_restab); if (len>8) { len=8; } READMEM((LPVOID)(base+owner.ne_restab+1), ModuleName, 8);
ModuleName[len] = 0; AddModuleNameList(ModuleName);
// This is mapped to ne_pnextexe in kernel
sel = owner.ne_cbenttab; }
//
// Search debugger segment array
//
se = GetSegtablePointer(); while ( se ) { ParseModuleName(filename, se->szExePath); AddModuleNameList(filename);
se = se->Next; } }
BOOL GetOwnerSegmentFromSelector( WORD selector, int mode, LPSTR szModule, WORD *psegment ) /*++
Routine Description:
This routine returns the "segment number" and owner name of the given selector or v86mode segment. The returned number represents the position of the segment in the binary, and is 1-based.
Arguments:
selector - either PMODE selector or V86 mode segment mode - PROT_MODE or V86_MODE filename - pointer to buffer to receive module name psegment - pointer to WORD to receive segment number
Return Value
TRUE if found
--*/
{ HEAPENTRY he = {0}; SEGENTRY *se;
he.Selector = selector; if (FindHeapEntry(&he, FHE_FIND_SEL_ONLY, FHE_FIND_QUIET)) { strcpy(szModule, he.FileName); *psegment = he.SegmentNumber+1; return TRUE; }
se = GetSegtablePointer(); while ( se ) { if (se->selector == selector) { ParseModuleName(szModule, se->szExePath); *psegment = se->segment; return TRUE; } se = se->Next; }
return FALSE; }
BOOL GetSelectorFromOwnerSegment( LPSTR szModule, WORD segment, WORD *pselector, int *pmode ) { HEAPENTRY he = {0}; char tempModule[9]; SEGENTRY *se;
while (FindHeapEntry(&he, FHE_FIND_SEL_ONLY, FHE_FIND_QUIET)) {
if (!_stricmp(szModule, he.FileName) && (segment == he.SegmentNumber+1)) {
*pselector = he.gnode.pga_handle|1; *pmode = PROT_MODE; return TRUE; } }
se = GetSegtablePointer(); while ( se ) {
ParseModuleName(tempModule, se->szExePath);
if (!_stricmp(szModule, tempModule) && (segment == se->segment+1)) {
*pselector = se->selector; if (se->type == SEGTYPE_V86) { *pmode = V86_MODE; } else { *pmode = PROT_MODE; } return TRUE;
} se = se->Next; } return FALSE; }
BOOL FindSymbol( WORD selector, LONG offset, LPSTR sym_text, LONG *dist, int direction, int mode ) { char filename[9]; WORD segment; static VDMGETSYMBOLPROC pfnGetSymbol = NULL;
if (!pfnGetSymbol && !GetVdmDbgEntry("VDMGetSymbol", (PVOID)&pfnGetSymbol)) { return FALSE; }
if (GetOwnerSegmentFromSelector(selector, mode, filename, &segment)) { return(pfnGetSymbol(filename, segment, offset, (mode == PROT_MODE), (direction == AFTER), sym_text, dist)); } return FALSE; }
BOOL FindAddress( LPSTR sym_text, LPSTR filename, WORD *psegment, WORD *pselector, LONG *poffset, int *pmode, BOOL bDumpAll ) { int i; BOOL bResult; static VDMGETADDREXPRESSIONPROC pfnGetAddrExpression = NULL; WORD type; char module[9];
if (!pfnGetAddrExpression && !GetVdmDbgEntry("VDMGetAddrExpression", (PVOID)&pfnGetAddrExpression)) { return FALSE; }
BuildModuleNameList(); for (i=0; i<ModuleListCount; i++) { bResult = pfnGetAddrExpression(ModuleList[i], sym_text, pselector, poffset, &type); if (bResult) { strcpy(filename, ModuleList[i]);
if (type == VDMADDR_V86) { *pmode = V86_MODE; } else { *pmode = PROT_MODE; }
if (!GetOwnerSegmentFromSelector(*pselector, *pmode, module, psegment)) { *pmode = NOT_LOADED; } return TRUE; } } return FALSE; }
VOID ln( CMD_ARGLIST ) { VDMCONTEXT ThreadContext; WORD selector; LONG offset; CHAR sym_text[1000]; DWORD dist; BOOL b; int mode;
CMD_INIT();
mode = GetContext( &ThreadContext );
if (!GetNextToken()) { selector = (WORD) ThreadContext.SegCs; offset = ThreadContext.Eip; } else if (!ParseIntelAddress(&mode, &selector, &offset)) { return; }
if ( mode == PROT_MODE ) { PRINTF( "#%04X:%04lX", selector, offset ); } if ( mode == V86_MODE ) { PRINTF( "&%04X:%04lX", selector, offset ); }
b = FindSymbol( selector, offset, sym_text, &dist, BEFORE, mode ); if ( !b ) { PRINTF(" = Could not find symbol before"); } else { if ( dist == 0 ) { PRINTF(" = %s", sym_text ); } else { PRINTF(" = %s+0x%lx", sym_text, dist ); } } b = FindSymbol( selector, offset, sym_text, &dist, AFTER, mode ); if ( !b ) { PRINTF(" | Could not find symbol after"); } else { if ( dist == 0 ) { PRINTF(" | %s", sym_text ); } else { PRINTF(" | %s-0x%lx", sym_text, dist ); } } PRINTF("\n"); }
VOID x( CMD_ARGLIST ) { VDMCONTEXT ThreadContext; BOOL result; WORD selector; WORD segment; LONG offset; int mode; char filename[9];
CMD_INIT();
try {
mode = GetContext( &ThreadContext );
result = FindAddress( lpArgumentString, filename, &segment, &selector, &offset, &mode, TRUE);
if ( result ) { if ( mode == PROT_MODE ) { PRINTF("#"); } else if ( mode == V86_MODE ) { PRINTF("&"); } else if ( mode == NOT_LOADED ) { selector = 0; PRINTF("?"); }
PRINTF("%04X:%04X = %s(%04X)!%s\n", selector, offset, filename, segment, lpArgumentString ); return; }
PRINTF("Could not find symbol '%s'\n", lpArgumentString );
} except (1) {
PRINTF("Exception 0x%08x in vdmexts!\n", GetExceptionCode());
} }
/****************************************************************************
****************************************************************************
extension debugging routines
The following functions were added to help debug the debugger extension. They are not intended to be used in normal operation.
**************************************************************************** ****************************************************************************/
VOID DumpModuleNameList( VOID ) { int i;
for (i=0; i<ModuleListCount; i++) { PRINTF("%d %s\n", i, ModuleList[i]); } }
VOID moddump( CMD_ARGLIST ) { CMD_INIT(); BuildModuleNameList(); DumpModuleNameList(); }
VOID segdef( CMD_ARGLIST ) { int cnt; int UpdateCnt; SEGENTRY *se; WORD selector; WORD segment; DWORD length; int type;
CMD_INIT();
se = GetSegtablePointer();
if (!GetNextToken()) { PRINTF("Missing index\n"); return; } UpdateCnt = (int) EvaluateToken();
if (!GetNextToken()) { PRINTF("Missing selector\n"); return; } selector = (WORD) EvaluateToken();
if (!GetNextToken()) { PRINTF("Missing segment\n"); return; } segment = (WORD) EvaluateToken();
if (!GetNextToken()) { PRINTF("Missing limit\n"); return; } length = EvaluateToken();
if (!GetNextToken()) { PRINTF("Missing type\n"); return; } type = (int) EvaluateToken();
if (!GetNextToken()) { PRINTF("Missing path\n"); return; }
cnt = 0; while ( se ) { if (cnt == UpdateCnt) { se->selector = selector; se->segment = segment; se->length = length; se->type = type; strcpy(se->szExePath, lpArgumentString); break; } cnt++; se = se->Next; }
}
VOID segdump( CMD_ARGLIST ) { int cnt; int DumpCnt; SEGENTRY *se;
CMD_INIT();
PRINTF("Index Sel Seg Length Type Module Path\n"); se = GetSegtablePointer();
if (GetNextToken()) { DumpCnt = (int) EvaluateToken();
cnt = 0; while ( se ) { if (DumpCnt == cnt) { PRINTF("%03x %04x %04x %08x %s %s %s\n", cnt, se->selector, se->segment, se->length, ((se->type==SEGTYPE_V86) ? "v86 " : "prot"), se->szModule, se->szExePath); break; } cnt++; se = se->Next; } return; }
cnt = 0; while ( se ) { PRINTF("%03x %04x %04x %08x %s %s %s\n", cnt, se->selector, se->segment, se->length, ((se->type==SEGTYPE_V86) ? "v86 " : "prot"), se->szModule, se->szExePath); cnt++; se = se->Next; } }
|