/*++ 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 #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=(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; iselector = 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; } }