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