From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/mvdm/vdmexts/util.c | 811 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 811 insertions(+) create mode 100644 private/mvdm/vdmexts/util.c (limited to 'private/mvdm/vdmexts/util.c') diff --git a/private/mvdm/vdmexts/util.c b/private/mvdm/vdmexts/util.c new file mode 100644 index 000000000..a86ba2528 --- /dev/null +++ b/private/mvdm/vdmexts/util.c @@ -0,0 +1,811 @@ +/*++ + +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 + Added command line parsing + +--*/ + +#include +#pragma hdrstop + +VDMCONTEXT ThreadContext; + +BOOL +WINAPI +ReadProcessMem( + LPVOID lpBaseAddress, + LPVOID lpBuffer, + DWORD nSize + ) +{ + if ( fWinDbg ) { + return (*ReadMem)( (DWORD)lpBaseAddress, lpBuffer, nSize, NULL ); + } else { + return ReadProcessMemory( hCurrentProcess, lpBaseAddress, lpBuffer, nSize, NULL ); + } +} + +BOOL +WINAPI +WriteProcessMem( + LPVOID lpBaseAddress, + LPVOID lpBuffer, + DWORD nSize + ) +{ + if ( fWinDbg ) { + return (*WriteMem)( (DWORD)lpBaseAddress, lpBuffer, nSize, NULL ); + } else { + return WriteProcessMemory( hCurrentProcess, lpBaseAddress, lpBuffer, nSize, NULL ); + } + +} + +#ifndef i386 + +// +// The following two routines implement the very funky way that we +// have to get register values on the 486 emulator. +// + +ULONG +GetRegValue( + NT_CPU_REG reg, + BOOL bInNano, + ULONG UMask + ) + +{ + if (bInNano) { + + return(ReadDwordSafe(reg.nano_reg)); + + } else if (UMask & reg.universe_8bit_mask) { + + return (ReadDwordSafe(reg.saved_reg) & 0xFFFFFF00 | + ReadDwordSafe(reg.reg) & 0xFF); + + } else if (UMask & reg.universe_16bit_mask) { + + return (ReadDwordSafe(reg.saved_reg) & 0xFFFF0000 | + ReadDwordSafe(reg.reg) & 0xFFFF); + + } else { + + return (ReadDwordSafe(reg.reg)); + + } +} + +ULONG +GetEspValue( + NT_CPU_INFO nt_cpu_info, + BOOL bInNano + ) + +{ + if (bInNano) { + + return (ReadDwordSafe(nt_cpu_info.nano_esp)); + + } else { + + if (ReadDwordSafe(nt_cpu_info.stack_is_big)) { + + return (ReadDwordSafe(nt_cpu_info.host_sp) - + ReadDwordSafe(nt_cpu_info.ss_base)); + + } else { + + return (ReadDwordSafe(nt_cpu_info.esp_sanctuary) & 0xFFFF0000 | + (ReadDwordSafe(nt_cpu_info.host_sp) - + ReadDwordSafe(nt_cpu_info.ss_base) & 0xFFFF)); + + } + + } + +} + +#endif + +int +GetContext( + VDMCONTEXT* lpContext +) { +#ifndef i386 // + int mode; + ULONG pTmp; + NT_CPU_INFO nt_cpu_info; + BOOL b; + BOOL bInNano; + ULONG UMask; + + pTmp = (ULONG)EXPRESSION("ntvdm!nt_cpu_info"); + + if ( pTmp ) { + + b = READMEM((LPVOID) pTmp, &nt_cpu_info, sizeof(NT_CPU_INFO)); + + if ( !b ) { + PRINTF("Could not read IntelRegisters context out of process\n"); + return( -1 ); + } + + bInNano = ReadDwordSafe((ULONG) nt_cpu_info.in_nano_cpu); + UMask = ReadDwordSafe((ULONG) nt_cpu_info.universe); + + lpContext->Eax = GetRegValue(nt_cpu_info.eax, bInNano, UMask); + lpContext->Ecx = GetRegValue(nt_cpu_info.ecx, bInNano, UMask); + lpContext->Edx = GetRegValue(nt_cpu_info.edx, bInNano, UMask); + lpContext->Ebx = GetRegValue(nt_cpu_info.ebx, bInNano, UMask); + lpContext->Ebp = GetRegValue(nt_cpu_info.ebp, bInNano, UMask); + lpContext->Esi = GetRegValue(nt_cpu_info.esi, bInNano, UMask); + lpContext->Edi = GetRegValue(nt_cpu_info.edi, bInNano, UMask); + + lpContext->Esp = GetEspValue(nt_cpu_info, bInNano); + lpContext->EFlags = ReadDwordSafe(nt_cpu_info.flags); + lpContext->Eip = ReadDwordSafe(nt_cpu_info.eip); + + lpContext->SegEs = ReadWordSafe(nt_cpu_info.es); + lpContext->SegCs = ReadWordSafe(nt_cpu_info.cs); + lpContext->SegSs = ReadWordSafe(nt_cpu_info.ss); + lpContext->SegDs = ReadWordSafe(nt_cpu_info.ds); + lpContext->SegFs = ReadWordSafe(nt_cpu_info.fs); + lpContext->SegGs = ReadWordSafe(nt_cpu_info.gs); + + + } else { + + PRINTF("Could not find the symbol 'ntvdm!nt_cpu_info'\n"); + return( -1 ); + } + + if ( !(ReadDwordSafe(nt_cpu_info.cr0) & 1) ) { + mode = V86_MODE; + } else { + mode = PROT_MODE; + } + return( mode ); + +#else // + + NTSTATUS rc; + BOOL b; + ULONG EFlags; + WORD cs; + int mode; + ULONG lpVdmTib; + + lpContext->ContextFlags = CONTEXT_FULL; + rc = NtGetContextThread( hCurrentThread, + lpContext ); + if ( NT_ERROR(rc) ) { + PRINTF( "bde.k: Could not get current threads context - status = %08lX\n", rc ); + return( -1 ); + } + /* + ** Get the 16-bit registers from the context + */ + cs = (WORD)lpContext->SegCs; + EFlags = lpContext->EFlags; + + // BUGBUG We don't seem to be setting v86 mode correctly on x86. + // + + if ( EFlags & V86_BITS ) { + /* + ** V86 Mode + */ + mode = V86_MODE; + } else { + if ( (cs & RPL_MASK) != KGDT_R3_CODE ) { + mode = PROT_MODE; + } else { + /* + ** We are in flat 32-bit address space! + */ + lpVdmTib = (ULONG)EXPRESSION("ntvdm!VdmTib"); + if ( !lpVdmTib ) { + PRINTF("Could not find the symbol 'VdmTib'\n"); + return( -1 ); + } + + b = READMEM((LPVOID)(lpVdmTib+FIELD_OFFSET(VDM_TIB,VdmContext)), + lpContext, sizeof(VDMCONTEXT)); + + if ( !b ) { + PRINTF("Could not read IntelRegisters context out of process\n"); + return( -1 ); + } + EFlags = lpContext->EFlags; + if ( EFlags & V86_BITS ) { + mode = V86_MODE; + } else { + mode = PROT_MODE; + } + } + } + + return( mode ); +#endif +} + +ULONG +GetIntelBase( + VOID + ) +{ +#ifndef i386 + ULONG IntelBase; + BOOL b; + + IntelBase = (ULONG)EXPRESSION("ntvdm!Start_of_M_area"); + if ( IntelBase ) { + + b = READMEM((LPVOID) IntelBase, &IntelBase, sizeof(ULONG)); + + if ( !b ) { + PRINTF("Could not read symbol 'ntvdm!Start_of_M_area\n"); + return(0); + } + + } else { + PRINTF("Could not find the symbol 'ntvdm!Start_of_M_area'\n"); + } + + return(IntelBase); +#else + return(0); +#endif +} + +DWORD read_dword( + ULONG lpAddress, + BOOL bSafe +) { + BOOL b; + DWORD dword; + + b = READMEM((LPVOID)lpAddress, &dword, sizeof(dword)); + + if ( !b ) { + if ( !bSafe ) { + PRINTF("Failure reading dword at memory location %08lX\n", lpAddress ); + } + return( 0 ); + } + return( dword ); +} + +WORD read_word( + ULONG lpAddress, + BOOL bSafe +) { + BOOL b; + WORD word; + + b = READMEM((LPVOID)lpAddress, &word, sizeof(word)); + + if ( !b ) { + if ( !bSafe ) { + PRINTF("Failure reading word at memory location %08lX\n", lpAddress ); + } + return( 0 ); + } + return( word ); +} + +BYTE read_byte( + ULONG lpAddress, + BOOL bSafe +) { + BOOL b; + BYTE byte; + + b = READMEM((LPVOID)lpAddress, &byte, sizeof(byte)); + + if ( !b ) { + if ( !bSafe ) { + PRINTF("Failure reading byte at memory location %08lX\n", lpAddress ); + } + return( 0 ); + } + return( byte ); +} + +BOOL read_gnode32( + ULONG lpAddress, + PGNODE32 p, + BOOL bSafe +) { + BOOL b; + + b = READMEM((LPVOID)lpAddress, p, sizeof(*p)); + + if ( !b ) { + if ( !bSafe ) { + PRINTF("Failure reading word at memory location %08lX\n", lpAddress ); + } + return( 0 ); + } + return( TRUE ); +} + + +BOOL GetDescriptorData( + WORD selector, + LPVDMLDT_ENTRY pdte + ) +{ +#ifdef i386 + + LDT_ENTRY dte; + if (!GetThreadSelectorEntry( hCurrentThread, + selector, + &dte)) { + return( FALSE ); + } + pdte->HighWord = dte.HighWord; + pdte->BaseLow = dte.BaseLow; + pdte->LimitLow = dte.LimitLow; + return (TRUE); + +#else + PVOID LdtAddress; + NTSTATUS Status; + selector &= ~(SELECTOR_LDT | SELECTOR_RPL); + + // + // Get address of Ldt + // + + LdtAddress = (PVOID)EXPRESSION("ntvdm!Ldt"); + + Status = READMEM(LdtAddress, &LdtAddress, sizeof(ULONG)); + + if (!Status) { + return FALSE; + } + + (PUCHAR)LdtAddress += selector; + + Status = READMEM(LdtAddress, pdte, sizeof(VDMLDT_ENTRY)); + + return Status; +#endif +} + +ULONG GetInfoFromSelector( + WORD selector, + int mode, + SELECTORINFO *si +) { + + ULONG base; + ULONG type; +#ifdef i386 + BYTE byte; + BOOL b; +#endif + VDMLDT_ENTRY dte; + + switch( mode ) { + case V86_MODE: + base = (ULONG)selector << 4; + if ( si ) { + si->Limit = 0xFFFFL; + si->Base = (ULONG)selector << 4; + si->bCode = FALSE; + si->bBig = FALSE; + si->bWrite = TRUE; + si->bPresent = TRUE; + } + break; + case PROT_MODE: + +#ifdef i386 + if ( (selector & 0xFFF8) < KGDT_LDT ) { + return( (ULONG)-1 ); + } +#endif + + if ( !GetDescriptorData(selector, &dte) ) { + return( (ULONG)-1 ); + } + + base = ((ULONG)dte.HighWord.Bytes.BaseHi << 24) + + ((ULONG)dte.HighWord.Bytes.BaseMid << 16) + + ((ULONG)dte.BaseLow); + + if ( si ) { + si->Limit = (ULONG)dte.LimitLow + + ((ULONG)dte.HighWord.Bits.LimitHi << 16); + + if ( dte.HighWord.Bits.Granularity ) { + si->Limit <<= 12; + si->Limit += 0xFFF; + } + si->Base = base; + + type = dte.HighWord.Bits.Type; + + si->bSystem = !(BOOL) (type & 0x10); + + if (!si->bSystem) { + si->bCode = (BOOL) (type & 8); + } + si->bAccessed = (BOOL) (type & 1); + si->bWrite = (BOOL) (type & 2); + if (si->bCode) { + si->bWrite = !si->bWrite; + + } + si->bPresent = (BOOL) dte.HighWord.Bits.Pres; + si->bBig = (BOOL) dte.HighWord.Bits.Default_Big; + + } + + if ( base == 0 ) { + return( (ULONG)-1 ); + } + +#ifdef i386 + + b = READMEM((LPVOID)base, &byte, sizeof(byte)); + + if ( !b ) { + return( (ULONG)-1 ); + } +#endif + break; + + case FLAT_MODE: + PRINTF("Unsupported determination of base address in flat mode\n"); + base = 0; + break; + } + + return( base ); +} + + +//**************************************************************************** +// +// Command line parsing routines +// +//**************************************************************************** +BOOL +SkipToNextWhiteSpace( + VOID + ) +{ + char ch; + while ( (ch = *lpArgumentString) != '\0' ) { + if ( ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' ) { + return TRUE; + } + lpArgumentString++; + } + return FALSE; +} + + +BOOL +GetNextToken( + VOID + ) +{ + char ch; + + while ( (ch = *lpArgumentString) != '\0' ) { + if ( ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n' ) { + return TRUE; + } + lpArgumentString++; + } + return FALSE; +} + +ULONG +EvaluateToken( + VOID + ) +{ + char ch; + LPSTR pTemp; + ULONG value = 0; + + if (GetNextToken()) { + pTemp = lpArgumentString; + SkipToNextWhiteSpace(); + ch = *lpArgumentString; + *lpArgumentString = 0; + value = (ULONG) EXPRESSION( pTemp ); + *lpArgumentString = ch; + } + return (value); +} + +BOOL +IsTokenHex( + VOID + ) +{ + + UCHAR ch; + LPSTR pTemp; + BOOL result = TRUE; + + if (GetNextToken()) { + pTemp = lpArgumentString; + SkipToNextWhiteSpace(); + lpArgumentString--; + + while(lpArgumentString >= pTemp) { + + ch = *lpArgumentString--; + + if (ch < '0') { + result = FALSE; + break; + } + + if ((ch > '9') && (ch < 'A')) { + result = FALSE; + break; + } + + if ((ch > 'F') && (ch < 'a')) { + result = FALSE; + break; + } + + if (ch > 'f') { + result = FALSE; + break; + } + + } + + lpArgumentString = pTemp; + + } + return (result); + +} + + +BOOL +RegisterToAsciiValue( + LPSTR *pszValue, + LPSTR *pszReg + ) +{ + LPSTR szReg = *pszReg; + LPSTR szValue = *pszValue; + + if (!_strnicmp(szReg, "ax", 2) && !isalpha(szReg[2])) { + _ultoa((ULONG)LOWORD(ThreadContext.Eax), szValue, 16); + *pszReg += 2; + } else if (!_strnicmp(szReg, "bx", 2) && !isalpha(szReg[2])) { + _ultoa((ULONG)LOWORD(ThreadContext.Ebx), szValue, 16); + *pszReg += 2; + } else if (!_strnicmp(szReg, "cx", 2) && !isalpha(szReg[2])) { + _ultoa((ULONG)LOWORD(ThreadContext.Ecx), szValue, 16); + *pszReg += 2; + } else if (!_strnicmp(szReg, "dx", 2) && !isalpha(szReg[2])) { + _ultoa((ULONG)LOWORD(ThreadContext.Edx), szValue, 16); + *pszReg += 2; + } else if (!_strnicmp(szReg, "si", 2) && !isalpha(szReg[2])) { + _ultoa((ULONG)LOWORD(ThreadContext.Esi), szValue, 16); + *pszReg += 2; + } else if (!_strnicmp(szReg, "di", 2) && !isalpha(szReg[2])) { + _ultoa((ULONG)LOWORD(ThreadContext.Edi), szValue, 16); + *pszReg += 2; + } else if (!_strnicmp(szReg, "sp", 2) && !isalpha(szReg[2])) { + _ultoa((ULONG)LOWORD(ThreadContext.Esp), szValue, 16); + *pszReg += 2; + } else if (!_strnicmp(szReg, "bp", 2) && !isalpha(szReg[2])) { + _ultoa((ULONG)LOWORD(ThreadContext.Ebp), szValue, 16); + *pszReg += 2; + } else if (!_strnicmp(szReg, "ip", 2) && !isalpha(szReg[2])) { + _ultoa((ULONG)LOWORD(ThreadContext.Eip), szValue, 16); + *pszReg += 2; + + } else if (!_strnicmp(szReg, "eax", 3) && !isalpha(szReg[3])) { + _ultoa(ThreadContext.Eax, szValue, 16); + *pszReg += 3; + } else if (!_strnicmp(szReg, "ebx", 3) && !isalpha(szReg[3])) { + _ultoa(ThreadContext.Ebx, szValue, 16); + *pszReg += 3; + } else if (!_strnicmp(szReg, "ecx", 3) && !isalpha(szReg[3])) { + _ultoa(ThreadContext.Ecx, szValue, 16); + *pszReg += 3; + } else if (!_strnicmp(szReg, "edx", 3) && !isalpha(szReg[3])) { + _ultoa(ThreadContext.Edx, szValue, 16); + *pszReg += 3; + } else if (!_strnicmp(szReg, "esi", 3) && !isalpha(szReg[3])) { + _ultoa(ThreadContext.Esi, szValue, 16); + *pszReg += 3; + } else if (!_strnicmp(szReg, "edi", 3) && !isalpha(szReg[3])) { + _ultoa(ThreadContext.Edi, szValue, 16); + *pszReg += 3; + } else if (!_strnicmp(szReg, "esp", 3) && !isalpha(szReg[3])) { + _ultoa(ThreadContext.Esp, szValue, 16); + *pszReg += 3; + } else if (!_strnicmp(szReg, "ebp", 3) && !isalpha(szReg[3])) { + _ultoa(ThreadContext.Ebp, szValue, 16); + *pszReg += 3; + } else if (!_strnicmp(szReg, "eip", 3) && !isalpha(szReg[3])) { + _ultoa(ThreadContext.Eip, szValue, 16); + *pszReg += 3; + + } else if (!_strnicmp(szReg, "cs", 2) && !isalpha(szReg[2])) { + _ultoa((ULONG)ThreadContext.SegCs, szValue, 16); + *pszReg += 2; + } else if (!_strnicmp(szReg, "ds", 2) && !isalpha(szReg[2])) { + _ultoa((ULONG)ThreadContext.SegDs, szValue, 16); + *pszReg += 2; + } else if (!_strnicmp(szReg, "es", 2) && !isalpha(szReg[2])) { + _ultoa((ULONG)ThreadContext.SegEs, szValue, 16); + *pszReg += 2; + } else if (!_strnicmp(szReg, "fs", 2) && !isalpha(szReg[2])) { + _ultoa((ULONG)ThreadContext.SegFs, szValue, 16); + *pszReg += 2; + } else if (!_strnicmp(szReg, "gs", 2) && !isalpha(szReg[2])) { + _ultoa((ULONG)ThreadContext.SegGs, szValue, 16); + *pszReg += 2; + } else if (!_strnicmp(szReg, "ss", 2) && !isalpha(szReg[2])) { + _ultoa((ULONG)ThreadContext.SegSs, szValue, 16); + *pszReg += 2; + } else { + return FALSE; + } + +// PRINTF("value = %s\n", szValue); + while (*szValue) { + szValue++; + } + *pszValue = szValue; + return TRUE; +} + +VOID +ParseForIntelRegisters( + LPSTR szTarg, + LPSTR szSrc + ) +{ + + while (*szSrc) { + if (!isalpha(*szSrc)) { + if (!isdigit(*szSrc)) { + *szTarg++ = *szSrc++; + continue; + } + + while (isalpha(*szSrc) || isdigit(*szSrc)) { + *szTarg++ = *szSrc++; + } + continue; + } + + if (!RegisterToAsciiValue(&szTarg, &szSrc)) { + while (isalpha(*szSrc) || isdigit(*szSrc)) { + *szTarg++ = *szSrc++; + } + } + + } + *szTarg = 0; +} + +BOOL +ParseIntelAddress( + int *pMode, + WORD *pSelector, + PULONG pOffset + ) + +{ + char sel_text[128], off_text[128]; + char expr_text[256]; + char *colon; + char *mode_prefix; + WORD segment; + char filename[9]; + + colon = strchr( lpArgumentString, ':' ); + if ( colon == NULL ) { + LPSTR pSymbol = lpArgumentString; + BOOL bResult; + char chTemp; + + SkipToNextWhiteSpace(); + chTemp = *lpArgumentString; + *lpArgumentString = 0; + + bResult = FindAddress( pSymbol, + filename, + &segment, + pSelector, + pOffset, + pMode, + FALSE); + + *lpArgumentString = chTemp; + + if (bResult) { + if (*pMode == NOT_LOADED) { + PRINTF("Could not determine base of '%s'\n", pSymbol); + return FALSE; + } else { + return TRUE; + } + + } else { + + PRINTF("Could not find symbol: %s\n", pSymbol); + return FALSE; + } + } + + *pMode = GetContext( &ThreadContext ); + + mode_prefix = strchr( lpArgumentString, '&' ); + if ( mode_prefix == NULL ) { + + mode_prefix = strchr( lpArgumentString, '#' ); + if ( mode_prefix != NULL ) { + + if ( mode_prefix != lpArgumentString ) { + PRINTF("Address must have '&' symbol as the first character\n"); + return FALSE; + } + + *pMode = PROT_MODE; + lpArgumentString = mode_prefix+1; + } + + } else { + + if ( mode_prefix != lpArgumentString ) { + PRINTF("Address must have '#' symbol as the first character\n"); + return FALSE; + } + *pMode = V86_MODE; + lpArgumentString = mode_prefix+1; + + } + + *colon = '\0'; + strcpy( sel_text, lpArgumentString ); + *colon = ':'; + strcpy( off_text, colon+1 ); + + ParseForIntelRegisters(expr_text, sel_text); + *pSelector = (WORD) EXPRESSION( expr_text ); + ParseForIntelRegisters(expr_text, off_text); + *pOffset = (ULONG) EXPRESSION( expr_text ); + + SkipToNextWhiteSpace(); + + return TRUE; +} -- cgit v1.2.3