windows-nt/Source/XPSP1/NT/base/mvdm/vdmexts/sym.c
2020-09-26 16:20:57 +08:00

650 lines
13 KiB
C

/*++
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;
}
}