diff options
Diffstat (limited to 'private/mvdm/bde')
-rw-r--r-- | private/mvdm/bde/bde.def | 19 | ||||
-rw-r--r-- | private/mvdm/bde/bde.h | 382 | ||||
-rw-r--r-- | private/mvdm/bde/bdecmds.c | 569 | ||||
-rw-r--r-- | private/mvdm/bde/bdeheap.c | 311 | ||||
-rw-r--r-- | private/mvdm/bde/bdemisc.c | 372 | ||||
-rw-r--r-- | private/mvdm/bde/bdestack.c | 653 | ||||
-rw-r--r-- | private/mvdm/bde/bdesym.c | 887 | ||||
-rw-r--r-- | private/mvdm/bde/bdeutil.c | 614 | ||||
-rw-r--r-- | private/mvdm/bde/data.c | 43 | ||||
-rw-r--r-- | private/mvdm/bde/disasm.c | 2380 | ||||
-rw-r--r-- | private/mvdm/bde/makefile | 6 | ||||
-rw-r--r-- | private/mvdm/bde/precomp.h | 17 | ||||
-rw-r--r-- | private/mvdm/bde/sources | 116 |
13 files changed, 6369 insertions, 0 deletions
diff --git a/private/mvdm/bde/bde.def b/private/mvdm/bde/bde.def new file mode 100644 index 000000000..ab01e94fd --- /dev/null +++ b/private/mvdm/bde/bde.def @@ -0,0 +1,19 @@ +NAME BDE + +DESCRIPTION 'Bob's Debugger Extensions' + +EXPORTS + k + kb + r + ln + lm + es + dg + dgh + ti + help + u + db + dw + dd diff --git a/private/mvdm/bde/bde.h b/private/mvdm/bde/bde.h new file mode 100644 index 000000000..be48c745e --- /dev/null +++ b/private/mvdm/bde/bde.h @@ -0,0 +1,382 @@ + +// +// Pointers to WINDBG api +// + +extern PNTSD_OUTPUT_ROUTINE Print; +extern PNTSD_GET_EXPRESSION GetExpression; +extern PNTSD_GET_SYMBOL GetSymbol; +//extern PNTSD_DISASM Disassemble; +extern PNTSD_CHECK_CONTROL_C CheckCtrlC; + +extern PWINDBG_READ_PROCESS_MEMORY_ROUTINE ReadProcessMemWinDbg; +extern PWINDBG_WRITE_PROCESS_MEMORY_ROUTINE WriteProcessMemWinDbg; +extern PWINDBG_GET_THREAD_CONTEXT_ROUTINE GetThreadContextWinDbg; +extern PWINDBG_SET_THREAD_CONTEXT_ROUTINE SetThreadContextWinDbg; + +extern fWinDbg; +extern HANDLE hCurrentProcess; +extern HANDLE hCurrentThread; +extern LPSTR lpArgumentString; + +#define PRINTF (* Print) +#define EXPRESSION (* GetExpression) + +#define ReadDword(x) read_dword((ULONG)x, FALSE) +#define ReadWord(x) read_word ((ULONG)x, FALSE) +#define ReadByte(x) read_byte ((ULONG)x, FALSE) +#define ReadDwordSafe(x) read_dword((ULONG)x, TRUE) +#define ReadWordSafe(x) read_word ((ULONG)x, TRUE) +#define ReadByteSafe(x) read_byte ((ULONG)x, TRUE) +#define ReadGNode(x,p) read_gnode((ULONG)x,p,FALSE) +#define ReadGNode32(x,p) read_gnode32((ULONG)x,p,FALSE) + +#define BEFORE 0 +#define AFTER 1 + +#define RPL_MASK 0x78 +#define V86_BITS 0x20000 + +#define SELECTOR_LDT 0x04 +#define SELECTOR_RPL 0x03 + +#define V86_MODE 0 +#define PROT_MODE 1 +#define FLAT_MODE 2 + +#define CALL_NEAR_RELATIVE 0xE8 +#define CALL_NEAR_INDIRECT 0xFF +#define INDIRECT_NEAR_TYPE 0x02 +#define CALL_FAR_ABSOLUTE 0x9A +#define CALL_FAR_INDIRECT 0xFF +#define INDIRECT_FAR_TYPE 0x03 +#define PUSH_CS 0x0E +#define ADD_SP 0xC483 + +#define TYPE_BITS 0x38 +#define TYPE0 0x00 +#define TYPE1 0x08 +#define TYPE2 0x10 +#define TYPE3 0x18 +#define TYPE4 0x20 +#define TYPE5 0x28 +#define TYPE6 0x30 +#define TYPE7 0x38 + +#define MOD_BITS 0xC0 +#define MOD0 0x00 +#define MOD1 0x40 +#define MOD2 0x80 +#define MOD3 0xC0 + +#define RM_BITS 0x07 +#define RM0 0x00 +#define RM1 0x01 +#define RM2 0x02 +#define RM3 0x03 +#define RM4 0x04 +#define RM5 0x05 +#define RM6 0x06 +#define RM7 0x07 + +#define FLAG_OVERFLOW 0x0800 +#define FLAG_DIRECTION 0x0400 +#define FLAG_INTERRUPT 0x0200 +#define FLAG_SIGN 0x0080 +#define FLAG_ZERO 0x0040 +#define FLAG_AUXILLIARY 0x0010 +#define FLAG_PARITY 0x0004 +#define FLAG_CARRY 0x0001 + +#define SEGTYPE_AVAILABLE 0 +#define SEGTYPE_V86 1 +#define SEGTYPE_PROT 2 + +#define MAXSEGENTRY 1024 + +#define WOW16 0 + +#define GA_ENDSIG ((BYTE)0x5a) + +typedef struct _SELECTORINFO { + DWORD Base; + DWORD Limit; + BOOL bCode; + BOOL bSystem; + BOOL bPresent; + BOOL bWrite; + BOOL bAccessed; + BOOL bBig; +} SELECTORINFO; + +typedef struct _segentry { + int type; + LPSTR path_name; + WORD selector; + WORD segment; + DWORD ImgLen; +} SEGENTRY; + +#pragma pack(1) + +typedef struct _GNODE { // GlobalArena + BYTE ga_count ; // lock count for movable segments + WORD ga_owner ; // DOS 2.x 3.x owner field (current task) + WORD ga_size ; // DOS 2.x 3.x size, in paragraphs, not incl. header + BYTE ga_flags ; // 1 byte available for flags + WORD ga_prev ; // previous arena entry (first points to self) + WORD ga_next ; // next arena entry (last points to self) + WORD ga_handle ; // back link to handle table entry + WORD ga_lruprev ; // Previous handle in lru chain + WORD ga_lrunext ; // Next handle in lru chain +} GNODE; +typedef GNODE UNALIGNED *PGNODE; + +typedef struct _GNODE32 { // GlobalArena + DWORD pga_next ; // next arena entry (last points to self) + DWORD pga_prev ; // previous arena entry (first points to self) + DWORD pga_address ; // 32 bit linear address of memory + DWORD pga_size ; // 32 bit size in bytes + WORD pga_handle ; // back link to handle table entry + WORD pga_owner ; // Owner field (current task) + BYTE pga_count ; // lock count for movable segments + BYTE pga_pglock ; // # times page locked + BYTE pga_flags ; // 1 word available for flags + BYTE pga_selcount ; // Number of selectors allocated + DWORD pga_lruprev ; // Previous entry in lru chain + DWORD pga_lrunext ; // Next entry in lru chain +} GNODE32; +typedef GNODE32 UNALIGNED *PGNODE32; + +typedef struct _GHI { + WORD hi_check ; // arena check word (non-zero enables heap checking) + WORD hi_freeze ; // arena frozen word (non-zero prevents compaction) + WORD hi_count ; // #entries in arena + WORD hi_first ; // first arena entry (sentinel, always busy) + WORD hi_last ; // last arena entry (sentinel, always busy) + BYTE hi_ncompact ; // #compactions done so far (max of 3) + BYTE ghi_dislevel; // current discard level + WORD hi_distotal ; // total amount discarded so far + WORD hi_htable ; // head of handle table list + WORD hi_hfree ; // head of free handle table list + WORD hi_hdelta ; // #handles to allocate each time + WORD hi_hexpand ; // address of near procedure to expand handles for + // this arena +} GHI; +typedef GHI UNALIGNED *PGHI; + +typedef struct _GHI32 { + WORD hi_check ; // arena check word (non-zero enables heap checking) + WORD hi_freeze ; // arena frozen word (non-zero prevents compaction) + WORD hi_count ; // #entries in arena + WORD hi_first ; // first arena entry (sentinel, always busy) + WORD hi_res1 ; // reserved + WORD hi_last ; // last arena entry (sentinel, always busy) + WORD hi_res2 ; // reserved + BYTE hi_ncompact ; // #compactions done so far (max of 3) + BYTE hi_dislevel ; // current discard level + DWORD hi_distotal ; // total amount discarded so far + WORD hi_htable ; // head of handle table list + WORD hi_hfree ; // head of free handle table list + WORD hi_hdelta ; // #handles to allocate each time + WORD hi_hexpand ; // address of near procedure to expand handles for this arena + WORD hi_pstats ; // address of statistics table or zero +} GHI32; +typedef GHI32 UNALIGNED *PGHI32; + +typedef struct _HEAPENTRY { + GNODE32 gnode; + DWORD CurrentEntry; + DWORD NextEntry; + WORD Selector; + int SegmentNumber; + char OwnerName[9]; + char FileName[9]; +} HEAPENTRY; + +typedef struct _NEHEADER { + WORD ne_magic ; + BYTE ne_ver ; + BYTE ne_rev ; + WORD ne_enttab ; + WORD ne_cbenttab ; + DWORD ne_crc ; + WORD ne_flags ; + WORD ne_autodata ; + WORD ne_heap ; + WORD ne_stack ; + DWORD ne_csip ; + DWORD ne_sssp ; + WORD ne_cseg ; + WORD ne_cmod ; + WORD ne_cbnrestab ; + WORD ne_segtab ; + WORD ne_rsrctab ; + WORD ne_restab ; + WORD ne_modtab ; + WORD ne_imptab ; + DWORD ne_nrestab ; + WORD ne_cmovent ; + WORD ne_align ; + WORD ne_cres ; + BYTE ne_exetyp ; + BYTE ne_flagsothers ; + WORD ne_pretthunks ; + WORD ne_psegrefbytes; + WORD ne_swaparea ; + WORD ne_expver ; +} NEHEADER; +typedef NEHEADER UNALIGNED *PNEHEADER; + +#pragma pack() + + +#ifndef i386 + +// +// Structures in 486 cpu for obtaining registers (FROM NT_CPU.C) +// + +typedef struct NT_CPU_REG { + ULONG *nano_reg; /* where the nano CPU keeps the register */ + ULONG *reg; /* where the light compiler keeps the reg */ + ULONG *saved_reg; /* where currently unused bits are kept */ + ULONG universe_8bit_mask;/* is register in 8-bit form? */ + ULONG universe_16bit_mask;/* is register in 16-bit form? */ +} NT_CPU_REG; + +typedef struct NT_CPU_INFO { + /* Variables for deciding what mode we're in */ + BOOL *in_nano_cpu; /* is the Nano CPU executing? */ + ULONG *universe; /* the mode that the CPU is in */ + + /* General purpose register pointers */ + NT_CPU_REG eax, ebx, ecx, edx, esi, edi, ebp; + + /* Variables for getting SP or ESP. */ + BOOL *stack_is_big; /* is the stack 32-bit? */ + ULONG *nano_esp; /* where the Nano CPU keeps ESP */ + UCHAR **host_sp; /* ptr to variable holding stack pointer as a + host address */ + UCHAR **ss_base; /* ptr to variables holding base of SS as a + host address */ + ULONG *esp_sanctuary; /* top 16 bits of ESP if we're now using SP */ + + ULONG *eip; + + /* Segment registers. */ + USHORT *cs, *ds, *es, *fs, *gs, *ss; + + ULONG *flags; + + /* CR0, mainly to let us figure out if we're in real or protect mode */ + ULONG *cr0; +} NT_CPU_INFO; + + +#endif // i386 + + + +BOOL +WINAPI +ReadProcessMem( + HANDLE hProcess, + LPVOID lpBaseAddress, + LPVOID lpBuffer, + DWORD nSize, + LPDWORD lpNumberOfBytesRead + ); + +BOOL +WINAPI +WriteProcessMem( + HANDLE hProcess, + LPVOID lpBaseAddress, + LPVOID lpBuffer, + DWORD nSize, + LPDWORD lpNumberOfBytesWritten + ); + +BOOL +CheckGlobalHeap( + VOID + ); + +int GetContext( + VDMCONTEXT* lpContext +); + +ULONG GetInfoFromSelector( + WORD selector, + int mode, + SELECTORINFO *si +); + +BOOL +FindHeapEntry( + HEAPENTRY *he, + BOOL bFindAny + ); + +BOOL FindSymbol( + WORD selector, + LONG offset, + LPSTR sym_text, + LONG *dist, + int direction, + int mode +); + +ULONG GetIntelBase( + VOID +); + +DWORD read_dword( + ULONG lpAddress, + BOOL bSafe +); + +WORD read_word( + ULONG lpAddress, + BOOL bSafe +); + +BYTE read_byte( + ULONG lpAddress, + BOOL bSafe +); + +BOOL read_gnode( + ULONG lpAddress, + PGNODE p, + BOOL bSafe +); + +BOOL read_gnode32( + ULONG lpAddress, + PGNODE32 p, + BOOL bSafe +); + +BOOL GetNextToken( + VOID + ); + +BOOL ParseIntelAddress( + int *pMode, + WORD *pSelector, + PULONG pOffset + ); + +VOID DumpRegs (VOID); +VOID DumpMemory (UINT); +VOID DumpGHeap (VOID); +VOID DumpDescriptor (VOID); +VOID EvaluateSymbol (VOID); +VOID ListModules (VOID); +VOID ListNear (VOID); +VOID TaskInfo (VOID); +VOID WalkStack (VOID); +VOID WalkStackVerbose (VOID); +VOID Unassemble (VOID); diff --git a/private/mvdm/bde/bdecmds.c b/private/mvdm/bde/bdecmds.c new file mode 100644 index 000000000..97b20a18b --- /dev/null +++ b/private/mvdm/bde/bdecmds.c @@ -0,0 +1,569 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + +Abstract: + + +Author: + + +Notes: + + +Revision History: + +--*/ + +#include <precomp.h> +#pragma hdrstop + +// +// Macro for setting up pointers to WinDbg routines +// +// This line currently causes a build warning, which I don't understand +// Disassemble = p->lpDisasmRoutine; + +#define SETUP_WINDBG_POINTERS( p ) { \ + Print = p->lpOutputRoutine; \ + GetExpression = p->lpGetExpressionRoutine; \ + GetSymbol = p->lpGetSymbolRoutine; \ + CheckCtrlC = p->lpCheckControlCRoutine; \ + \ + if ( p->nSize >= sizeof(WINDBG_EXTENSION_APIS) ) { \ + fWinDbg = TRUE; \ + ReadProcessMemWinDbg = p->lpReadProcessMemoryRoutine; \ + WriteProcessMemWinDbg = p->lpWriteProcessMemoryRoutine; \ + GetThreadContextWinDbg = p->lpGetThreadContextRoutine; \ + SetThreadContextWinDbg = p->lpSetThreadContextRoutine; \ + } else { \ + fWinDbg = FALSE; \ + } \ +} + + +VOID +db( + HANDLE CurrentProcess, + HANDLE CurrentThread, + DWORD CurrentPc, + PWINDBG_EXTENSION_APIS ExtensionApis, + LPSTR ArgumentString + ) +/*++ + +Routine Description: + + +Arguments: + + CurrentProcess -- Supplies a handle to the current process + CurrentThread -- Supplies a handle to the current thread + CurrentPc -- Supplies the current program counter. (may be meaningless) + ExtensionApis -- Supplies pointers to ntsd support routines + ArgumentString -- Supplies the arguments passed to the command + +Return Value: + + None. + +--*/ +{ + UNREFERENCED_PARAMETER(CurrentPc); + + hCurrentProcess = CurrentProcess; + hCurrentThread = CurrentThread; + lpArgumentString = ArgumentString; + SETUP_WINDBG_POINTERS(ExtensionApis); + DumpMemory(1); + +} + +VOID +dw( + HANDLE CurrentProcess, + HANDLE CurrentThread, + DWORD CurrentPc, + PWINDBG_EXTENSION_APIS ExtensionApis, + LPSTR ArgumentString + ) +/*++ + +Routine Description: + + +Arguments: + + CurrentProcess -- Supplies a handle to the current process + CurrentThread -- Supplies a handle to the current thread + CurrentPc -- Supplies the current program counter. (may be meaningless) + ExtensionApis -- Supplies pointers to ntsd support routines + ArgumentString -- Supplies the arguments passed to the command + +Return Value: + + None. + +--*/ +{ + UNREFERENCED_PARAMETER(CurrentPc); + + hCurrentProcess = CurrentProcess; + hCurrentThread = CurrentThread; + lpArgumentString = ArgumentString; + SETUP_WINDBG_POINTERS(ExtensionApis); + DumpMemory(2); + +} + +VOID +dd( + HANDLE CurrentProcess, + HANDLE CurrentThread, + DWORD CurrentPc, + PWINDBG_EXTENSION_APIS ExtensionApis, + LPSTR ArgumentString + ) +/*++ + +Routine Description: + + +Arguments: + + CurrentProcess -- Supplies a handle to the current process + CurrentThread -- Supplies a handle to the current thread + CurrentPc -- Supplies the current program counter. (may be meaningless) + ExtensionApis -- Supplies pointers to ntsd support routines + ArgumentString -- Supplies the arguments passed to the command + +Return Value: + + None. + +--*/ +{ + UNREFERENCED_PARAMETER(CurrentPc); + + hCurrentProcess = CurrentProcess; + hCurrentThread = CurrentThread; + lpArgumentString = ArgumentString; + SETUP_WINDBG_POINTERS(ExtensionApis); + DumpMemory(4); + +} + +VOID +dg( + HANDLE CurrentProcess, + HANDLE CurrentThread, + DWORD CurrentPc, + PWINDBG_EXTENSION_APIS ExtensionApis, + LPSTR ArgumentString + ) +/*++ + +Routine Description: + + +Arguments: + + CurrentProcess -- Supplies a handle to the current process + CurrentThread -- Supplies a handle to the current thread + CurrentPc -- Supplies the current program counter. (may be meaningless) + ExtensionApis -- Supplies pointers to ntsd support routines + ArgumentString -- Supplies the arguments passed to the command + +Return Value: + + None. + +--*/ +{ + UNREFERENCED_PARAMETER(CurrentPc); + + hCurrentProcess = CurrentProcess; + hCurrentThread = CurrentThread; + lpArgumentString = ArgumentString; + SETUP_WINDBG_POINTERS(ExtensionApis); + DumpDescriptor(); + +} + +VOID +dgh( + HANDLE CurrentProcess, + HANDLE CurrentThread, + DWORD CurrentPc, + PWINDBG_EXTENSION_APIS ExtensionApis, + LPSTR ArgumentString + ) +/*++ + +Routine Description: + + +Arguments: + + CurrentProcess -- Supplies a handle to the current process + CurrentThread -- Supplies a handle to the current thread + CurrentPc -- Supplies the current program counter. (may be meaningless) + ExtensionApis -- Supplies pointers to ntsd support routines + ArgumentString -- Supplies the arguments passed to the command + +Return Value: + + None. + +--*/ +{ + UNREFERENCED_PARAMETER(CurrentPc); + + hCurrentProcess = CurrentProcess; + hCurrentThread = CurrentThread; + lpArgumentString = ArgumentString; + SETUP_WINDBG_POINTERS(ExtensionApis); + DumpGHeap(); + +} + + +VOID +es( + HANDLE CurrentProcess, + HANDLE CurrentThread, + DWORD CurrentPc, + PWINDBG_EXTENSION_APIS ExtensionApis, + LPSTR ArgumentString + ) +/*++ + +Routine Description: + + +Arguments: + + CurrentProcess -- Supplies a handle to the current process + CurrentThread -- Supplies a handle to the current thread + CurrentPc -- Supplies the current program counter. (may be meaningless) + ExtensionApis -- Supplies pointers to ntsd support routines + ArgumentString -- Supplies the arguments passed to the command + +Return Value: + + None. + +--*/ +{ + UNREFERENCED_PARAMETER(CurrentPc); + + hCurrentProcess = CurrentProcess; + hCurrentThread = CurrentThread; + lpArgumentString = ArgumentString; + SETUP_WINDBG_POINTERS(ExtensionApis); + if (!CheckGlobalHeap()) { + return; + } + EvaluateSymbol(); + +} + +VOID +help( + HANDLE CurrentProcess, + HANDLE CurrentThread, + DWORD CurrentPc, + PWINDBG_EXTENSION_APIS ExtensionApis, + LPSTR ArgumentString +) { + SETUP_WINDBG_POINTERS(ExtensionApis); + + PRINTF("[db|dw|dd] addr - Dump 16-bit memory\n"); + PRINTF("dg <sel> - Dump info on a selector\n"); + PRINTF("dgh <sel> - Dump global heap\n"); + PRINTF("es <symbol> - Get symbol's value\n"); + PRINTF("k - Stack trace\n"); + PRINTF("kb - Stack trace with symbols\n"); + PRINTF("lm - List loaded modules\n"); + PRINTF("ln <addr> - Determine near symbols\n"); + PRINTF("r - Dump registers\n"); + PRINTF("ti <thrdid> - Dump WOW Task Info\n"); + PRINTF("u <addr> - Unassemble 16-bit code with symbols\n"); + PRINTF("\n"); +} + +VOID +k( + HANDLE CurrentProcess, + HANDLE CurrentThread, + DWORD CurrentPc, + PWINDBG_EXTENSION_APIS ExtensionApis, + LPSTR ArgumentString + ) +/*++ + +Routine Description: + + +Arguments: + + CurrentProcess -- Supplies a handle to the current process + CurrentThread -- Supplies a handle to the current thread + CurrentPc -- Supplies the current program counter. (may be meaningless) + ExtensionApis -- Supplies pointers to ntsd support routines + ArgumentString -- Supplies the arguments passed to the command + +Return Value: + + None. + +--*/ +{ + UNREFERENCED_PARAMETER(CurrentPc); + + hCurrentProcess = CurrentProcess; + hCurrentThread = CurrentThread; + lpArgumentString = ArgumentString; + SETUP_WINDBG_POINTERS(ExtensionApis); + if (!CheckGlobalHeap()) { + return; + } + WalkStack(); + +} + + +VOID +kb( + HANDLE CurrentProcess, + HANDLE CurrentThread, + DWORD CurrentPc, + PWINDBG_EXTENSION_APIS ExtensionApis, + LPSTR ArgumentString + ) +/*++ + +Routine Description: + + +Arguments: + + CurrentProcess -- Supplies a handle to the current process + CurrentThread -- Supplies a handle to the current thread + CurrentPc -- Supplies the current program counter. (may be meaningless) + ExtensionApis -- Supplies pointers to ntsd support routines + ArgumentString -- Supplies the arguments passed to the command + +Return Value: + + None. + +--*/ +{ + UNREFERENCED_PARAMETER(CurrentPc); + + hCurrentProcess = CurrentProcess; + hCurrentThread = CurrentThread; + lpArgumentString = ArgumentString; + SETUP_WINDBG_POINTERS(ExtensionApis); + if (!CheckGlobalHeap()) { + return; + } + WalkStackVerbose(); + +} + + +VOID +lm( + HANDLE CurrentProcess, + HANDLE CurrentThread, + DWORD CurrentPc, + PWINDBG_EXTENSION_APIS ExtensionApis, + LPSTR ArgumentString + ) +/*++ + +Routine Description: + + +Arguments: + + CurrentProcess -- Supplies a handle to the current process + CurrentThread -- Supplies a handle to the current thread + CurrentPc -- Supplies the current program counter. (may be meaningless) + ExtensionApis -- Supplies pointers to ntsd support routines + ArgumentString -- Supplies the arguments passed to the command + +Return Value: + + None. + +--*/ +{ + UNREFERENCED_PARAMETER(CurrentPc); + + hCurrentProcess = CurrentProcess; + hCurrentThread = CurrentThread; + lpArgumentString = ArgumentString; + SETUP_WINDBG_POINTERS(ExtensionApis); + if (!CheckGlobalHeap()) { + return; + } + ListModules(); + +} + + +VOID +ln( + HANDLE CurrentProcess, + HANDLE CurrentThread, + DWORD CurrentPc, + PWINDBG_EXTENSION_APIS ExtensionApis, + LPSTR ArgumentString + ) +/*++ + +Routine Description: + + +Arguments: + + CurrentProcess -- Supplies a handle to the current process + CurrentThread -- Supplies a handle to the current thread + CurrentPc -- Supplies the current program counter. (may be meaningless) + ExtensionApis -- Supplies pointers to ntsd support routines + ArgumentString -- Supplies the arguments passed to the command + +Return Value: + + None. + +--*/ +{ + UNREFERENCED_PARAMETER(CurrentPc); + + hCurrentProcess = CurrentProcess; + hCurrentThread = CurrentThread; + lpArgumentString = ArgumentString; + SETUP_WINDBG_POINTERS(ExtensionApis); + ListNear(); + +} + + +VOID +r( + IN HANDLE CurrentProcess, + IN HANDLE CurrentThread, + IN DWORD CurrentPc, + IN PWINDBG_EXTENSION_APIS ExtensionApis, + IN LPSTR ArgumentString + ) +/*++ + +Routine Description: + + +Arguments: + + CurrentProcess -- Supplies a handle to the current process + CurrentThread -- Supplies a handle to the current thread + CurrentPc -- Supplies the current program counter. (may be meaningless) + ExtensionApis -- Supplies pointers to ntsd support routines + ArgumentString -- Supplies the arguments passed to the command + +Return Value: + + None. + +--*/ +{ + UNREFERENCED_PARAMETER(CurrentPc); + + hCurrentProcess = CurrentProcess; + hCurrentThread = CurrentThread; + lpArgumentString = ArgumentString; + SETUP_WINDBG_POINTERS(ExtensionApis); + DumpRegs(); + +} + + +VOID +ti( + IN HANDLE CurrentProcess, + IN HANDLE CurrentThread, + IN DWORD CurrentPc, + IN PWINDBG_EXTENSION_APIS ExtensionApis, + IN LPSTR ArgumentString + ) +/*++ + +Routine Description: + + +Arguments: + + CurrentProcess -- Supplies a handle to the current process + CurrentThread -- Supplies a handle to the current thread + CurrentPc -- Supplies the current program counter. (may be meaningless) + ExtensionApis -- Supplies pointers to ntsd support routines + ArgumentString -- Supplies the arguments passed to the command + +Return Value: + + None. + +--*/ +{ + UNREFERENCED_PARAMETER(CurrentPc); + + hCurrentProcess = CurrentProcess; + hCurrentThread = CurrentThread; + lpArgumentString = ArgumentString; + SETUP_WINDBG_POINTERS(ExtensionApis); + TaskInfo(); + +} + +VOID +u( + IN HANDLE CurrentProcess, + IN HANDLE CurrentThread, + IN DWORD CurrentPc, + IN PWINDBG_EXTENSION_APIS ExtensionApis, + IN LPSTR ArgumentString + ) +/*++ + +Routine Description: + + +Arguments: + + CurrentProcess -- Supplies a handle to the current process + CurrentThread -- Supplies a handle to the current thread + CurrentPc -- Supplies the current program counter. (may be meaningless) + ExtensionApis -- Supplies pointers to ntsd support routines + ArgumentString -- Supplies the arguments passed to the command + +Return Value: + + None. + +--*/ +{ + UNREFERENCED_PARAMETER(CurrentPc); + + hCurrentProcess = CurrentProcess; + hCurrentThread = CurrentThread; + lpArgumentString = ArgumentString; + SETUP_WINDBG_POINTERS(ExtensionApis); + Unassemble(); + +} diff --git a/private/mvdm/bde/bdeheap.c b/private/mvdm/bde/bdeheap.c new file mode 100644 index 000000000..f9deed96d --- /dev/null +++ b/private/mvdm/bde/bdeheap.c @@ -0,0 +1,311 @@ +#include <precomp.h> +#pragma hdrstop + + +BOOL bWalkOnly = FALSE; + +ULONG +GetHeapBase( + VOID + ) +{ + WORD selector; + SELECTORINFO si; + + //BUGBUG SLIMY SLIMY! Look around for a selector that appears to be + // the kernel heap + + for (selector=0x1bf; selector<0x1ff; selector+=8) { + + GetInfoFromSelector(selector, PROT_MODE, &si); + if ((!si.bSystem) && (!si.bCode) && (si.Limit>0xffff)) { + break; + } + si.Base = 0; + } + + return(si.Base + GetIntelBase()); + +} + + + +void +GetFileNameFromOwner( + LPSTR filename, + LPSTR OwnerName + ) +{ +} + + +VOID +GetSegmentOwnerInfo( + HEAPENTRY *he + ) +{ + BOOL b; + NEHEADER owner; + ULONG base; + UCHAR len; + int i; + ULONG offset; + WORD wTemp; + + he->SegmentNumber = -1; + he->OwnerName[0] = 0; + if (he->gnode.pga_owner == 0) { + strcpy(he->OwnerName, "free"); + return; + } else if (he->gnode.pga_owner>=0xFFF8) { + strcpy(he->OwnerName, "sentinel"); + return; + } + + + base = GetInfoFromSelector(he->gnode.pga_owner, PROT_MODE, NULL) + + GetIntelBase(); + + b = ReadProcessMem( + hCurrentProcess, + (LPVOID)base, + &owner, + sizeof(owner), + NULL + ); + + if (b) { + if (owner.ne_magic == 0x454e) { + + len = ReadByteSafe(base+owner.ne_restab); + if (len>8) { + len=8; + } + ReadProcessMem(hCurrentProcess, + (LPVOID) (base+owner.ne_restab+1), + he->OwnerName, + 8, + NULL + ); + + he->OwnerName[len] = 0; + if (!_stricmp(he->OwnerName, "kernel")) { + strcpy(he->FileName, "krnl386"); + } else { + strcpy(he->FileName, he->OwnerName); + } + + offset = owner.ne_segtab; + + for (i=0; i<owner.ne_cseg; i++) { + wTemp = ReadWordSafe(base+offset+8); //get handle + if (wTemp == he->gnode.pga_handle) { + he->SegmentNumber = i; + break; + } + offset += 10; + } + + } + } + +} + +BOOL +CheckGlobalHeap( + ) +{ + PGHI32 pghi; + DWORD offset; + DWORD count; + DWORD p; + GNODE32 gnode; + PBYTE pFault = NULL; + BOOL bError = FALSE; + + pghi = (PGHI32)GetHeapBase(); + offset = (DWORD) ReadWord(&pghi->hi_first); + + // + // If we get here, the caller wants us to scan the heap + // + + count = ReadWord(&pghi->hi_count); + + while ((offset != 0) && (count)) { + + p = (DWORD)pghi + offset; + + if (!ReadGNode32(p, &gnode)) { + + PRINTF("Error reading global heap!\n"); + return FALSE; + + } + + count--; + if (offset == gnode.pga_next) { + return TRUE; + } + offset = gnode.pga_next; + } + + PRINTF("Error: Kernel heap is corrupt!\n"); + return FALSE; +} + + +BOOL +FindHeapEntry( + HEAPENTRY *he, + BOOL bFindAny + ) +{ + PGHI32 pghi; + DWORD offset; + DWORD MaxEntries, count; + DWORD p; + PBYTE pFault = NULL; + BOOL bError = FALSE; + + pghi = (PGHI32)GetHeapBase(); + + // + // The caller has requested that we return the next heap + // entry since the last invocation, or the first entry. + // + + if (he->CurrentEntry == 0) { + + // get first entry + offset = (DWORD) ReadWord(&pghi->hi_first); + + } else { + if (he->CurrentEntry == he->NextEntry) { + return FALSE; + } + + // get next entry + offset = he->NextEntry; + + } + + he->CurrentEntry = offset; + + if (he->Selector == 0) { + + p = (DWORD)pghi + offset; + if (!ReadGNode32(p, &he->gnode)) { + + PRINTF("Error reading global heap!\n"); + return FALSE; + + } + + he->NextEntry = he->gnode.pga_next; + GetSegmentOwnerInfo(he); + return TRUE; + } + + // + // If we get here, the caller wants us to scan the heap + // + + MaxEntries = ReadWord(&pghi->hi_count); + count = 0; + + while ((offset != 0) && (count <= MaxEntries)) { + + p = (DWORD)pghi + offset; + + if (!ReadGNode32(p, &he->gnode)) { + + PRINTF("Error reading global heap!\n"); + return FALSE; + + } else { + + if (bFindAny) { + WORD sel = he->Selector; + + if (((sel|1)==((WORD)he->gnode.pga_handle|1)) || + ((sel|1)==((WORD)he->gnode.pga_owner|1))) { + he->NextEntry = he->gnode.pga_next; + GetSegmentOwnerInfo(he); + return TRUE; + } + + } else { + if ((he->Selector|1)==((WORD)he->gnode.pga_handle|1)) { + he->NextEntry = he->gnode.pga_next; + GetSegmentOwnerInfo(he); + return TRUE; + } + } + } + + count++; + if (offset == he->gnode.pga_next) { + break; + } + offset = he->gnode.pga_next; + he->CurrentEntry = offset; + } + + return FALSE; +} + + + +//************************************************************* +// dumpgheap xxx +// where xxx is the 16-bit protect mode selector of the +// Kernel global heap info. +// +//************************************************************* + + +VOID +DumpGHeap( + VOID + ) +{ + VDMCONTEXT ThreadContext; + int mode; + HEAPENTRY he = {0}; + SELECTORINFO si; + + mode = GetContext( &ThreadContext ); + + if (GetNextToken()) { + he.Selector = (WORD) EXPRESSION( lpArgumentString ); + } + + PRINTF("Arena Base Limit Hnd Own Fl Module Type Resid"); + PRINTF("\n"); + + PRINTF("===== ======== ======== ==== ==== == ======== ==== ====="); + PRINTF("\n"); + + while (FindHeapEntry(&he, TRUE)) { + + PRINTF("%.5x", he.CurrentEntry); + PRINTF(" %.8x", he.gnode.pga_address); + PRINTF(" %.8X", he.gnode.pga_size); + PRINTF(" %.4X", he.gnode.pga_handle); + PRINTF(" %.4X", he.gnode.pga_owner); + PRINTF(" %.2X", he.gnode.pga_flags); + PRINTF(" %8s", he.OwnerName); + + GetInfoFromSelector((WORD)(he.gnode.pga_handle | 1), PROT_MODE, &si); + + PRINTF(" %s", si.bCode ? "Code" : "Data"); + + if (he.SegmentNumber != -1) { + PRINTF(" %d", he.SegmentNumber); + } + PRINTF("\n"); + + } + +} diff --git a/private/mvdm/bde/bdemisc.c b/private/mvdm/bde/bdemisc.c new file mode 100644 index 000000000..65f646e63 --- /dev/null +++ b/private/mvdm/bde/bdemisc.c @@ -0,0 +1,372 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + ntsdexts.c + +Abstract: + + This function contains the default ntsd debugger extensions + +Author: + + Bob Day (bobday) 29-Feb-1992 Grabbed standard header + +Revision History: + +--*/ + +#include <precomp.h> +#pragma hdrstop +#include <ctype.h> + +VOID +DumpMemory( + UINT DumpType + ) +{ + VDMCONTEXT ThreadContext; + int mode; + int i, j, lines = 8; + WORD selector; + ULONG offset; + ULONG base; + char ch; + + if (!DumpType) { + return; + } + + mode = GetContext( &ThreadContext ); + + if (!GetNextToken()) { + PRINTF("Please specify an address\n"); + return; + } + + if (!ParseIntelAddress(&mode, &selector, &offset)) { + return; + } + + if (GetNextToken()) { + if ((*lpArgumentString == 'l') || (*lpArgumentString == 'L')) { + lpArgumentString++; + } + lines = (EXPRESSION(lpArgumentString)*DumpType+15)/16; + } + + base = GetInfoFromSelector(selector, mode, NULL) + GetIntelBase(); + + for (i=0; i<lines; i++) { + if (offset & 0xFFFF0000) { + PRINTF("%04x:%08lx ", selector, offset); + } else { + PRINTF("%04x:%04x ", selector, LOWORD(offset)); + } + + switch(DumpType) { + + case 1: + for (j=0; j<16; j++) { + if (j==8) { + PRINTF("-"); + } else { + PRINTF(" "); + } + PRINTF("%02x", ReadByteSafe(base+offset+j)); + } + PRINTF(" "); + + for (j=0; j<16; j++) { + ch = ReadByteSafe(base+offset+j); + if (isprint(ch)) { + PRINTF("%c", ch); + } else { + PRINTF("."); + } + } + + break; + case 2: + for (j=0; j<16; j+=2) { + PRINTF(" %04x", ReadWordSafe(base+offset+j)); + } + break; + case 4: + for (j=0; j<16; j+=4) { + PRINTF(" %08lx", ReadDwordSafe(base+offset+j)); + } + break; + } + PRINTF("\n"); + offset += 16; + + } + +} + + + +VOID +DumpRegs( +) { + VDMCONTEXT ThreadContext; + int mode; + + mode = GetContext( &ThreadContext ); + + PRINTF("eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx esi=%08lx edi=%08lx\n", + ThreadContext.Eax, + ThreadContext.Ebx, + ThreadContext.Ecx, + ThreadContext.Edx, + ThreadContext.Esi, + ThreadContext.Edi ); + PRINTF("eip=%08lx esp=%08lx ebp=%08lx ", + ThreadContext.Eip, + ThreadContext.Esp, + ThreadContext.Ebp ); + if ( ThreadContext.EFlags & FLAG_OVERFLOW ) { + PRINTF("ov "); + } else { + PRINTF("nv "); + } + if ( ThreadContext.EFlags & FLAG_DIRECTION ) { + PRINTF("dn "); + } else { + PRINTF("up "); + } + if ( ThreadContext.EFlags & FLAG_INTERRUPT ) { + PRINTF("ei "); + } else { + PRINTF("di "); + } + if ( ThreadContext.EFlags & FLAG_SIGN ) { + PRINTF("ng "); + } else { + PRINTF("pl "); + } + if ( ThreadContext.EFlags & FLAG_ZERO ) { + PRINTF("zr "); + } else { + PRINTF("nz "); + } + if ( ThreadContext.EFlags & FLAG_AUXILLIARY ) { + PRINTF("ac "); + } else { + PRINTF("na "); + } + if ( ThreadContext.EFlags & FLAG_PARITY ) { + PRINTF("po "); + } else { + PRINTF("pe "); + } + if ( ThreadContext.EFlags & FLAG_CARRY ) { + PRINTF("cy "); + } else { + PRINTF("nc "); + } + PRINTF("\n"); + PRINTF("cs=%04x ss=%04x ds=%04x es=%04x fs=%04x gs=%04x efl=%08lx\n", + ThreadContext.SegCs, + ThreadContext.SegSs, + ThreadContext.SegDs, + ThreadContext.SegEs, + ThreadContext.SegFs, + ThreadContext.SegGs, + ThreadContext.EFlags ); +} + + +VOID +ListModules( +) { + VDMCONTEXT ThreadContext; + int mode; + HEAPENTRY he = {0}; + SELECTORINFO si; + + mode = GetContext( &ThreadContext ); + + if (GetNextToken()) { + he.Selector = (WORD) EXPRESSION( lpArgumentString ); + } + + PRINTF("Sel Base Limit Type Seg Module\n"); + PRINTF("==== ======== ======== ==== ==== ========\n"); + + + while (FindHeapEntry(&he, FALSE)) { + if (he.SegmentNumber != -1) { + GetInfoFromSelector((WORD)(he.gnode.pga_handle | 1), PROT_MODE, &si); + PRINTF("%04X %08lX %08lX", + he.gnode.pga_handle | 1, + he.gnode.pga_address, + he.gnode.pga_size - 1); + + PRINTF(" %s", si.bCode ? "Code" : "Data"); + + PRINTF(" %04X %s\n", + he.SegmentNumber, + he.OwnerName); + } + + } + +} + +VOID +DumpDescriptor( +) { + VDMCONTEXT ThreadContext; + WORD selector; + ULONG Base; + int mode; + SELECTORINFO si; + int i, count = 16; + + mode = GetContext( &ThreadContext ); + + if (GetNextToken()) { + selector = (WORD) EXPRESSION( lpArgumentString ); + } else { + PRINTF("Please enter a selector\n"); + return; + } + + for (i=0; i<count; i++) { + + Base = GetInfoFromSelector( selector, mode, &si ); + + PRINTF("%04X => Base: %08lX", selector, Base); + +#ifndef i386 + PRINTF(" (%08X)", Base+GetIntelBase()); +#endif + + PRINTF(" Limit: %08lX %s %s %s %s\n", + si.Limit, + si.bPresent ? " P" : "NP", + si.bSystem ? "System" : si.bCode ? "Code " : "Data ", + si.bSystem ? "" : si.bWrite ? "W" : "R", + si.bSystem ? "" : si.bAccessed ? "A" : "" + ); + + selector+=8; + } + +} + + +// +// Dump Taskinfo; +// +// If no argument, dump all wow tasks. +// If 0, dump current WOW task +// Else dump the specifies task {which is thread-id as shown by +// ~ command under ntsd like 37.6b so thread-id is 6b) +// + +void DumpTaskInfo (ptd,mode) +PTD ptd; +int mode; +{ + + ULONG Base; + TDB tdb; + BOOL b; + + Base = GetInfoFromSelector( ptd->htask16, mode, NULL ); + b = ReadProcessMem( hCurrentProcess, + (LPVOID) (Base+GetIntelBase()), + &tdb, + sizeof(tdb), + NULL ); + + if ( !b ) { + PRINTF("Failure reading TDB at %X\n", Base ); + return; + } + + PRINTF("\nDump for ThreadId = %x\n",ptd->dwThreadID); + PRINTF(" Stack = %x:%x\n",HIWORD(ptd->vpStack),LOWORD(ptd->vpStack)); + PRINTF(" HTask (TDB) = %x\n", ptd->htask16); + PRINTF(" HInst = %x\n", ptd->hInst16); + PRINTF(" HMod16 = %x\n", ptd->hMod16); + PRINTF(" CompatFlags = %x\n",ptd->dwWOWCompatFlags); + PRINTF(" HThread = %x\n",ptd->hThread); + PRINTF(" TDBFlags = %x\n",tdb.TDB_flags); + PRINTF(" ExpWinVer = %x\n",tdb.TDB_ExpWinVer); + PRINTF(" DTA = %x:%x\n",HIWORD(tdb.TDB_DTA),LOWORD(tdb.TDB_DTA)); + PRINTF(" CurDir = %.64s\n",tdb.TDB_Directory); + PRINTF(" ModName = %.8s\n",tdb.TDB_ModName); +} + +void TaskInfo ( +) { + VDMCONTEXT ThreadContext; + DWORD ThreadId; + PTD ptd,ptdHead; + TD td; + int mode; + BOOL b,fFound=FALSE; + + + mode = GetContext( &ThreadContext ); + + ThreadId = (DWORD)-1; // Assume Dump All Tasks + if (GetNextToken()) { + ThreadId = (DWORD) EXPRESSION( lpArgumentString ); + } + + ptdHead = (PTD)EXPRESSION("wow32!gptdTaskHead"); + + // get the pointer to first TD + b = ReadProcessMem( hCurrentProcess, + (LPVOID) (ptdHead), + &ptd, + sizeof(DWORD), + NULL ); + + if ( !b ) { + PRINTF("Failure reading gptdTaskHead at %08lX\n", ptdHead ); + return; + } + + // enumerate td list to find the match(es) + while (ptd) { + b = ReadProcessMem( hCurrentProcess, + (LPVOID) (ptd), + &td, + sizeof(TD), + NULL ); + if ( !b ) { + PRINTF("Failure reading TD At %08lX\n", ptd ); + return; + } + + if (ThreadId == -1) { + DumpTaskInfo (&td,mode); + fFound = TRUE; + } + else { + if (ThreadId == td.dwThreadID) { + DumpTaskInfo (&td,mode); + fFound = TRUE; + break; + } + } + ptd = td.ptdNext; + } + + if (!fFound) { + if (ThreadId == -1) { + PRINTF("No WOW Task Found.\n"); + } + else + PRINTF("WOW Task With Thread Id = %02x Not Found.\n",ThreadId); + } + return; +} diff --git a/private/mvdm/bde/bdestack.c b/private/mvdm/bde/bdestack.c new file mode 100644 index 000000000..b25b9b618 --- /dev/null +++ b/private/mvdm/bde/bdestack.c @@ -0,0 +1,653 @@ +#include <precomp.h> +#pragma hdrstop + +ULONG IntelBase; + +void dump_params( + ULONG params, + char convention, + int param_words +) { + WORD word; + int cnt; + + if ( param_words == 0 ) { + param_words = 10; + } + PRINTF("("); + cnt = 0; + while ( cnt != param_words ) { + if ( convention == 'c' ) { + word = ReadWord(params+cnt); + } else { + word = ReadWord(params+(param_words-cnt)); + } + if ( cnt == param_words - 1 ) { + PRINTF("%04x",word); + } else { + PRINTF("%04x,",word); + } + cnt+=2; + } + PRINTF(")"); +} + +int look_for_near( + ULONG pbp, + WORD cs, + WORD ss, + WORD bp, + int framed, + ULONG csBase, + int mode, + BOOL fUseSymbols, + BOOL fParams +) { + WORD ip; + ULONG ra; + char call_type; + char frame_type; + char convention; + int param_words; + signed short dest; + unsigned char opcode; + unsigned char mod; + unsigned char type; + unsigned char rm; + WORD dest_ip; + char symbol[1000]; + BOOL fOk; + BOOL fInst; + BOOL b; + LONG dist; + BOOL fDest; + + fOk = TRUE; + fInst = FALSE; + fDest = FALSE; + + param_words = 0; + if ( framed ) { + frame_type = 'B'; + } else { + frame_type = 'C'; + } + ip = ReadWord(pbp+2); + ra = csBase + (ULONG)ip; + + do { + opcode = ReadByteSafe(ra - 2); + if ( opcode == CALL_NEAR_INDIRECT ) { + if ( ReadByteSafe(ra - 3) == PUSH_CS ) { + call_type = 'f'; + } else { + call_type = 'N'; + } + opcode = ReadByteSafe(ra - 1); + mod = opcode & MOD_BITS; + type = opcode & TYPE_BITS; + rm = opcode & RM_BITS; + if ( type == INDIRECT_NEAR_TYPE ) { + if ( mod == MOD0 && rm != RM6 ) { + fInst = TRUE; + break; + } + if ( mod == MOD3 ) { + fInst = TRUE; + break; + } + } + } + opcode = ReadByteSafe(ra - 3); + if ( opcode == CALL_NEAR_RELATIVE ) { + if ( ReadByteSafe(ra - 4) == PUSH_CS ) { + call_type = 'f'; + } else { + call_type = 'N'; + } + dest = ReadWordSafe( ra - 2 ); + dest_ip = ip+dest; + fInst = TRUE; + fDest = TRUE; + break; + } + if ( opcode == CALL_NEAR_INDIRECT ) { + if ( ReadByteSafe(ra - 4) == PUSH_CS ) { + call_type = 'f'; + } else { + call_type = 'N'; + } + opcode = ReadByteSafe(ra - 2); + mod = opcode & MOD_BITS; + type = opcode & TYPE_BITS; + rm = opcode & RM_BITS; + if ( type == INDIRECT_NEAR_TYPE + && mod == MOD1 ) { + fInst = TRUE; + break; + } + } + opcode = ReadByteSafe(ra - 4); + if ( opcode == CALL_NEAR_INDIRECT ) { + if ( ReadByteSafe(ra - 5) == PUSH_CS ) { + call_type = 'f'; + } else { + call_type = 'N'; + } + opcode = ReadByteSafe(ra - 3); + mod = opcode & MOD_BITS; + type = opcode & TYPE_BITS; + rm = opcode & RM_BITS; + if ( type == INDIRECT_NEAR_TYPE ) { + if ( mod == MOD0 && rm == RM6 ) { + fInst = TRUE; + break; + } + if ( mod == MOD2 ) { + fInst = TRUE; + break; + } + } + } + fOk = FALSE; + } while ( FALSE ); + + if ( fOk ) { + if ( fUseSymbols ) { + b = FindSymbol( cs, (LONG)ip, symbol, &dist, BEFORE, mode ); + } else { + b = FALSE; + } + b = FALSE; + + if ( b ) { + if ( dist == 0 ) { + PRINTF("%04X:%04X %s %c%c", ss, bp, symbol, call_type, frame_type ); + } else { + PRINTF("%04X:%04X %s+0x%lx %c%c", ss, bp, symbol, dist, call_type, frame_type ); + } + } else { + PRINTF("%04X:%04X %04X:%04X %c%c", ss, bp, cs, ip, call_type, frame_type ); + } + if ( fInst ) { + if ( ReadWordSafe(ra) == ADD_SP ) { + convention = 'c'; + param_words = ReadByteSafe( ra+2 ); + } else { + convention = 'p'; + } + if ( fUseSymbols && fDest ) { + b = FindSymbol( cs, (LONG)dest_ip, symbol, &dist, BEFORE, mode ); + } else { + b = FALSE; + } + if ( b ) { + if ( dist == 0 ) { + PRINTF(" %ccall near %s", convention, symbol ); + } else { + PRINTF(" %ccall near %s+0x%lx", convention, symbol, dist ); + } + } else { + if ( fDest ) { + PRINTF(" %ccall near %04X", convention, dest_ip ); + } else { + PRINTF(" %ccall near [Indirect]", convention ); + } + } + if ( fParams ) { + dump_params( pbp+4, convention, param_words ); + } + } + PRINTF("\n"); + return( 1 ); + } + + return( 0 ); +} + +int look_for_far( + ULONG pbp, + WORD *cs, + WORD ss, + WORD bp, + int framed, + ULONG *csBase, + int mode, + BOOL fUseSymbols, + BOOL fParams +) { + WORD ip; + WORD new_cs; + ULONG new_csBase; + ULONG ra; + char frame_type; + char convention; + int param_words; + WORD dest_cs; + WORD dest_ip; + unsigned char opcode; + unsigned char mod; + unsigned char type; + unsigned char rm; + char symbol[1000]; + BOOL fOk; + BOOL fInst; + BOOL b; + LONG dist; + BOOL fDest; + int iMeth; + WORD low_this; + WORD high_this; + + fOk = TRUE; + fInst = FALSE; + fDest = FALSE; + iMeth = -1; + + param_words = 0; + if ( framed ) { + frame_type = 'B'; + } else { + frame_type = 'C'; + } + ip = ReadWord(pbp+2); + new_cs = ReadWord(pbp+4); + new_csBase = GetInfoFromSelector( new_cs, mode, NULL ) + IntelBase; + if ( new_csBase == -1 ) { + return( 0 ); + } + ra = new_csBase + (ULONG)ip; + + do { + opcode = ReadByteSafe(ra - 2); + if ( opcode == CALL_FAR_INDIRECT ) { + opcode = ReadByte(ra - 1); + mod = opcode & MOD_BITS; + type = opcode & TYPE_BITS; + rm = opcode & RM_BITS; + if ( type == INDIRECT_FAR_TYPE ) { + if ( mod == MOD0 && rm != RM6 ) { + fInst = TRUE; + iMeth = 0; + break; + } + if ( mod == MOD3 ) { + fInst = TRUE; + break; + } + } + } + opcode = ReadByteSafe(ra - 3); + if ( opcode == CALL_FAR_INDIRECT ) { + opcode = ReadByteSafe(ra - 2); + mod = opcode & MOD_BITS; + type = opcode & TYPE_BITS; + rm = opcode & RM_BITS; + if ( type == INDIRECT_FAR_TYPE + && mod == MOD1 ) { + fInst = TRUE; + iMeth = ReadByteSafe(ra - 1); + break; + } + } + opcode = ReadByteSafe(ra - 4); + if ( opcode == CALL_FAR_INDIRECT ) { + opcode = ReadByteSafe(ra - 3); + mod = opcode & MOD_BITS; + type = opcode & TYPE_BITS; + rm = opcode & RM_BITS; + if ( type == INDIRECT_FAR_TYPE ) { + if ( mod == MOD0 && rm == RM6 ) { + fInst = TRUE; + break; + } + if ( mod == MOD2 ) { + fInst = TRUE; + break; + } + } + } + opcode = ReadByteSafe(ra - 5); + if ( opcode == CALL_FAR_ABSOLUTE ) { + dest_ip = ReadWordSafe( ra - 4 ); + dest_cs = ReadWordSafe( ra - 2 ); + fInst = TRUE; + fDest = TRUE; + break; + } + fOk = FALSE; + } while ( FALSE ); + + if ( fOk ) { + if ( fUseSymbols ) { + b = FindSymbol( new_cs, (LONG)ip, symbol, &dist, BEFORE, mode ); + } else { + b = FALSE; + } + b = FALSE; + + if ( b ) { + if ( dist == 0 ) { + PRINTF("%04X:%04X %s F%c", ss, bp, symbol, frame_type ); + } else { + PRINTF("%04X:%04X %s+0x%lx F%c", ss, bp, symbol, dist, frame_type ); + } + } else { + PRINTF("%04X:%04X %04X:%04X F%c", ss, bp, new_cs, ip, frame_type ); + } + if ( fInst ) { + if ( ReadWordSafe(ra) == ADD_SP ) { + convention = 'c'; + param_words = ReadByteSafe( ra+2 ); + } else { + convention = 'p'; + } + if ( fUseSymbols && fDest ) { + b = FindSymbol( dest_cs, (LONG)dest_ip, symbol, &dist, BEFORE, mode ); + } else { + b = FALSE; + } + if ( b ) { + if ( dist == 0 ) { + PRINTF(" %ccall far %s", convention, symbol ); + } else { + PRINTF(" %ccall far %s + 0x%lx", convention, symbol, dist ); + } + } else { + if ( fDest ) { + PRINTF(" %ccall far %04X:%04X", convention, dest_cs, dest_ip ); + } else { + ULONG thisBase; + ULONG pvtbl; + ULONG vtblBase; + ULONG pfn; + WORD low_vtbl; + WORD high_vtbl; + WORD low_fn; + WORD high_fn; + + if ( iMeth != -1 ) { + low_this = ReadWord(pbp+6); + high_this = ReadWord(pbp+8); + + if ( low_this == 0 && high_this == 0 ) { + low_fn = 0; + high_fn = 0; + strcpy(symbol,""); + } else { + thisBase = GetInfoFromSelector( high_this, mode, NULL ) + IntelBase; + pvtbl = thisBase + (ULONG)low_this; + + low_vtbl = ReadWord(pvtbl); + high_vtbl = ReadWord(pvtbl+2); + + vtblBase = GetInfoFromSelector( high_vtbl, mode, NULL ) + IntelBase; + pfn = vtblBase + (ULONG)low_vtbl + iMeth; + + low_fn = ReadWord(pfn); + high_fn = ReadWord(pfn+2); + + b = FindSymbol( high_fn, (LONG)low_fn, symbol, &dist, BEFORE, mode ); + if ( !b ) { + wsprintf(symbol,"%04X:%04X", high_fn, low_fn ); + } + } + } + switch( iMeth ) { + default: + case -1: + if ( iMeth != -1 && (iMeth & 0x3) == 0 ) { + PRINTF(" %ccall far [Ind-%04X:%04x Method %d] %s", convention, high_this, low_this, iMeth/4, symbol ); + } else { + PRINTF(" %ccall far [Indirect]", convention ); + } + break; + case 0: + PRINTF(" %ccall far [Ind-%04X:%04X Method 0 - QI?] %s", convention, high_this, low_this, symbol); + break; + case 4: + PRINTF(" %ccall far [Ind-%04X:%04X Method 1 - AddRef?] %s", convention, high_this, low_this, symbol); + break; + case 8: + PRINTF(" %ccall far [Ind-%04X:%04X Method 2 - Release?] %s", convention, high_this, low_this, symbol); + break; + } + } + } + if ( fParams ) { + dump_params( pbp+6, convention, param_words ); + } + } + PRINTF("\n"); + *cs = new_cs; + *csBase = new_csBase; + return( 1 ); + } + return( 0 ); +} + +int scan_for_frameless( + WORD ss, + WORD sp, + WORD next_bp, + WORD *cs, + ULONG ssBase, + ULONG *csBase, + int limit, + int mode, + BOOL fUseSymbols, + BOOL fParams +) { + ULONG pbp; + int result; + int cnt; + + cnt = 1000; + sp -= 2; + while ( limit ) { + sp += 2; + --cnt; + if ( sp == next_bp || cnt == 0 ) { + break; + } + + pbp = ssBase + (ULONG)sp; + + result = look_for_near( pbp, *cs, ss, sp, 0, *csBase, + mode, fUseSymbols, fParams ); + if ( result ) { + --limit; + continue; + } + /* + ** Check for far calls + */ + result = look_for_far( pbp, cs, ss, sp, 0, csBase, + mode, fUseSymbols, fParams ); + if ( result ) { + --limit; + continue; + } + } + + return( 0 ); +} + +void stack_trace( + WORD ss, + ULONG ssBase, + WORD sp, + WORD bp, + WORD cs, + ULONG csBase, + int limit, + int mode, + BOOL fUseSymbols, + BOOL fGuessFrameless, + BOOL fParams +) { + WORD next_bp; + ULONG pbp; + int far_only; + int result; + WORD save_sp; + WORD save_bp; + WORD save_cs; + ULONG save_csBase; + int save_limit; + + save_sp = sp; + save_bp = bp; + save_cs = cs; + save_csBase = csBase; + save_limit = limit; + + PRINTF("[-Stack-] [-Retrn-] XY (X=Near/Far/far,Y=Call chain/BP Chain)\n"); + + next_bp = bp; + + while ( limit ) { + bp = next_bp; + if ( bp == 0 ) { + break; + } + if ( bp & 0x01 ) { + far_only = 1; + bp &= 0xFFFE; + } else { + far_only = 0; + } + pbp = ssBase + (ULONG)bp; + next_bp = ReadWord(pbp); + + if ( fGuessFrameless ) { + limit -= scan_for_frameless( ss, sp, bp, &cs, + ssBase, &csBase, limit, mode, fUseSymbols, + fParams ); + } + + if ( limit ) { + /* + ** Check for near calls + */ + if ( far_only == 0 ) { + result = look_for_near( pbp, cs, ss, bp, 1, csBase, + mode, fUseSymbols, fParams ); + if ( result ) { + sp = bp + 4; + --limit; + continue; + } + } + /* + ** Check for far calls + */ + result = look_for_far( pbp, &cs, ss, bp, 1, &csBase, + mode, fUseSymbols, fParams ); + if ( result ) { + sp = bp + 6; + --limit; + continue; + } + PRINTF("Could not find call\n"); + break; + } + } + if ( fGuessFrameless ) { + if ( limit ) { + limit -= scan_for_frameless( + ss, sp, 0, &cs, ssBase, &csBase, limit, mode, + fUseSymbols, fParams ); + } + } +} + +VOID +WalkStack( +) { + VDMCONTEXT ThreadContext; + WORD bp; + WORD sp; + WORD ss; + WORD cs; + WORD ip; + + ULONG csBase; + ULONG ssBase; + int mode; + int lines; + + mode = GetContext( &ThreadContext ); + IntelBase = GetIntelBase(); + + sp = (WORD)ThreadContext.Esp; + bp = (WORD)ThreadContext.Ebp; + ss = (WORD)ThreadContext.SegSs; + ip = (WORD)ThreadContext.Eip; + cs = (WORD)ThreadContext.SegCs; + + csBase = GetInfoFromSelector( cs, mode, NULL ) + IntelBase; + ssBase = GetInfoFromSelector( ss, mode, NULL ) + IntelBase; + + lines = 10; + if (GetNextToken()) { + lines = EXPRESSION( lpArgumentString ); + } + + stack_trace( ss, + ssBase, + sp, + bp, + cs, + csBase, + lines, + mode, + FALSE, + FALSE, + FALSE ); +} + +VOID +WalkStackVerbose( +) { + VDMCONTEXT ThreadContext; + WORD bp; + WORD sp; + WORD ss; + WORD cs; + WORD ip; + + ULONG csBase; + ULONG ssBase; + int mode; + int lines; + + mode = GetContext( &ThreadContext ); + IntelBase = GetIntelBase(); + + sp = (WORD)ThreadContext.Esp; + bp = (WORD)ThreadContext.Ebp; + ss = (WORD)ThreadContext.SegSs; + ip = (WORD)ThreadContext.Eip; + cs = (WORD)ThreadContext.SegCs; + + csBase = GetInfoFromSelector( cs, mode, NULL ) + IntelBase; + ssBase = GetInfoFromSelector( ss, mode, NULL ) + IntelBase; + + lines = 10; + if (GetNextToken()) { + lines = EXPRESSION( lpArgumentString ); + } + + stack_trace( ss, + ssBase, + sp, + bp, + cs, + csBase, + lines, + mode, + TRUE, + FALSE, + FALSE ); +} diff --git a/private/mvdm/bde/bdesym.c b/private/mvdm/bde/bdesym.c new file mode 100644 index 000000000..a0b76e132 --- /dev/null +++ b/private/mvdm/bde/bdesym.c @@ -0,0 +1,887 @@ +#include <precomp.h> +#pragma hdrstop + +#define MYOF_FLAGS (OF_READ | OF_SHARE_DENY_NONE) + +int read_name( + int ifile, + LPSTR pch +) { + char length; + int rc; + + rc = _lread( ifile, &length, sizeof(length) ); + if ( rc != sizeof(length) ) { + PRINTF("Could not read name length\n"); + *pch = '\0'; + return( -1 ); + } + rc = _lread( ifile, pch, length ); + if ( rc != length ) { + PRINTF("Could not read name\n"); + *pch = '\0'; + return( -1 ); + } + *(pch + length) = '\0'; + return( (int)length ); +} + +BOOL FindExport( + LPSTR filename, + WORD segment, + WORD offset, + LPSTR sym_text, + int direction, + LONG *dist +) { + int iFile; + OFSTRUCT ofs; + int rc; + IMAGE_DOS_HEADER doshdr; + IMAGE_OS2_HEADER winhdr; + BYTE Table[65536]; + BYTE bBundles; + BYTE bFlags; + BYTE *ptr; + WORD wIndex = 1; + int i; + int this_dist; + int wIndexBest = -1; + char myfilename[256]; +#pragma pack(1) + typedef struct + { + BYTE bFlags; + UNALIGNED WORD wSegOffset; + } FENTRY, *PFENTRY; + + typedef struct + { + BYTE bFlags; + UNALIGNED WORD wINT3F; + BYTE bSegNumber; + UNALIGNED WORD wSegOffset; + } MENTRY, *PMENTRY; +#pragma pack() + + strcpy(myfilename, filename); + if (-1 == (iFile=OpenFile(myfilename, &ofs, MYOF_FLAGS))) { + + PRINTF("Error reading file %s\n", filename); + strcpy(myfilename, filename); + strcat(myfilename, ".exe"); + + if (-1 == (iFile=OpenFile(myfilename, &ofs, MYOF_FLAGS))) { + + PRINTF("Error reading file %s\n", myfilename); + strcpy(myfilename, filename); + strcat(myfilename, ".dll"); + + if (-1 == (iFile=OpenFile(myfilename, &ofs, MYOF_FLAGS))) { + PRINTF("Error reading file %s\n", myfilename); + return FALSE; + } + } + } + + rc = _lread(iFile, &doshdr, sizeof(doshdr)); + if (rc != sizeof(doshdr)) { + //PRINTF("Error reading DOS header\n"); + goto Error; + } + if (doshdr.e_magic != IMAGE_DOS_SIGNATURE) { + //PRINTF("Error - no DOS EXE signature"); + goto Error; + } + rc = _llseek(iFile, doshdr.e_lfanew, FILE_BEGIN); + if (rc == -1) { + //PRINTF("Error - could not seek - probably not Win3.1 exe\n"); + goto Error; + } + rc = _lread(iFile, &winhdr, sizeof(winhdr)); + if (rc != sizeof(winhdr)) { + //PRINTF("Error - could not read WIN header - probably not Win3.1 exe\n"); + goto Error; + } + if (winhdr.ne_magic != IMAGE_OS2_SIGNATURE) { + //PRINTF("Error - not WIN EXE signature\n"); + goto Error; + } + rc = _llseek(iFile, doshdr.e_lfanew+winhdr.ne_enttab, FILE_BEGIN); + if (rc == -1) { + //PRINTF("Error - could not seek to entry table\n"); + goto Error; + } + rc = _lread(iFile, Table, winhdr.ne_cbenttab); + if (rc != winhdr.ne_cbenttab) { + //PRINTF("Error - could not read entry table\n"); + goto Error; + } + ptr = Table; + while (TRUE) { + bBundles = *ptr++; + if (bBundles == 0) + break; + + bFlags = *ptr++; + switch (bFlags) { + case 0: // Placeholders + wIndex += bBundles; + break; + + case 0xff: // movable segments + for (i=0; i<(int)bBundles; ++i) { + PMENTRY pe = (PMENTRY )ptr; + if (pe->bSegNumber == segment) { + this_dist = (direction == BEFORE) ? offset - pe->wSegOffset + : pe->wSegOffset - offset; + if ( this_dist >= 0 && (this_dist < *dist || *dist == -1) ) { + // mark this as the best match so far + *dist = this_dist; + wIndexBest = wIndex; + } + } + ptr += sizeof(MENTRY); + wIndex++; + } + break; + + default: // fixed segments + if ((int)bFlags != segment) { + ptr += (int)bBundles * sizeof(FENTRY); + wIndex += (int)bBundles; + } else { + for (i=0; i<(int)bBundles; ++i) { + PFENTRY pe = (PFENTRY)ptr; + this_dist = (direction == BEFORE) ? offset - pe->wSegOffset + : pe->wSegOffset - offset; + if ( this_dist >= 0 && (this_dist < *dist || *dist == -1) ) { + // mark this as the best match so far + *dist = this_dist; + wIndexBest = wIndex; + } + ptr += sizeof(FENTRY); + wIndex++; + } + } + break; + } + } + if (wIndexBest == -1) { + // no match found - error out +Error: + _lclose(iFile); + return FALSE; + } + + // Success: match found + // wIndexBest = ordinal of the function + // segment:offset = address to look up + // *dist = distance from segment:offset to the symbol + // filename = name of .exe/.dll + + // Look for the ordinal in the resident name table + rc = _llseek(iFile, doshdr.e_lfanew+winhdr.ne_restab, FILE_BEGIN); + if (rc == -1) { + //PRINTF("Error - unable to seek to residentname table\n"); + goto Error; + } + rc = _lread(iFile, Table, winhdr.ne_modtab-winhdr.ne_restab); + if (rc != winhdr.ne_modtab-winhdr.ne_restab) { + //PRINTF("Error - unable to read entire resident name table\n"); + goto Error; + } + ptr = Table; + while (*ptr) { + if ( *(UNALIGNED USHORT *)(ptr+1+*ptr) == (USHORT)wIndexBest) { + // found the matching name + *(ptr+1+*ptr) = '\0'; // null-terminate the function name + wsprintf(sym_text, "%s", ptr+1); + goto Finished; + } + ptr += *ptr + 3; + } + + // Look for the ordinal in the non-resident name table + rc = _llseek(iFile, doshdr.e_lfanew+winhdr.ne_nrestab, FILE_BEGIN); + if (rc == -1) { + //PRINTF("Error - unable to seek to non-residentname table\n"); + goto Error; + } + rc = _lread(iFile, Table, winhdr.ne_cbnrestab); + if (rc != winhdr.ne_cbnrestab) { + //PRINTF("Error - unable to read entire non-resident name table\n"); + goto Error; + } + ptr = Table; + while (*ptr) { + if ( *(UNALIGNED USHORT *)(ptr+1+*ptr) == (USHORT)wIndexBest) { + // found the matching name + *(ptr+1+*ptr) = '\0'; // null-terminate the function name + wsprintf(sym_text, "%s", ptr+1); + goto Finished; + } + ptr += *ptr + 3; + } + // fall into error path - no match found + goto Error; + +Finished: + _lclose(iFile); + return TRUE; +} + + +int read_symbol( + int ifile, + LPSTR pch, + LONG *offset +) { + int rc; + WORD word; + + rc = _lread( ifile, (LPSTR)&word, sizeof(WORD) ); + if ( rc != sizeof(WORD) ) { + PRINTF("Could not read symbol offset\n"); + *pch = '\0'; + *offset = 0L; + return(-1); + } + *offset = (LONG)word; + rc = read_name( ifile, pch ); + return( rc ); +} + +BOOL FindSymbol( + WORD selector, + LONG offset, + LPSTR sym_text, + LONG *dist, + int direction, + int mode +) { + BOOL result; + int length; + int iFile; + char filename[256]; + OFSTRUCT ofs; + LONG filesize; + LONG start_position; + LONG position; + WORD w1; + WORD num_syms; + WORD w3; + WORD w4; + WORD next_off; +#ifdef NEED_INDICES + WORD index; + char c2; + int nSubEtry; +#endif + char c1; + int rc; + int cnt; + LONG this_offset; + WORD r2; + WORD seg_num; + char b[12]; + char name_buff[128]; + LONG this_dist; + HEAPENTRY he = {0}; + + *dist = -1; + strcpy( sym_text, "[Unknown]" ); + result = FALSE; + + if ( mode == V86_MODE ) { + return FALSE; +// v86_addr = ((ULONG)selector << 4) + (ULONG)offset; + } + + /* + ** Search for selector in kernel heap + */ + he.Selector = selector; + while (FindHeapEntry(&he, FALSE)) { + { + strcpy(filename, he.FileName); + strcat(filename,".sym"); + + iFile = OpenFile( filename, &ofs, MYOF_FLAGS ); + + if ( iFile == -1 ) { + PRINTF("Could not open symbol file \"%s\"\n", filename ); + + // Open the .EXE/.DLL file and see if the address corresponds + // to an exported function. + result = FindExport(he.FileName,(WORD)(he.SegmentNumber+1),(WORD)offset,sym_text,direction,dist); + if (!result) { + // not found in any .dll/.exe's export table, so just print file name, + // segment number, and offset + wsprintf(sym_text,"%s(%X):%04X",he.OwnerName, he.SegmentNumber,offset); + *dist = 0; + result = TRUE; + } + continue; + } + + rc = _lread( iFile, (LPSTR)&filesize, sizeof(filesize) ); + if ( rc != sizeof(filesize) ) { + PRINTF("Could not read file size\n"); + _lclose( iFile ); + return( FALSE ); + } + filesize <<= 4; + + rc = _lread( iFile, (LPSTR)&w1, sizeof(w1) ); + if ( rc != sizeof(w1) ) { + PRINTF("Could not read w1\n"); + _lclose( iFile ); + return( FALSE ); + } + + rc = _lread( iFile, (LPSTR)&num_syms, sizeof(num_syms) ); + if ( rc != sizeof(num_syms) ) { + PRINTF("Could not read num_syms\n"); + _lclose( iFile ); + return( FALSE ); + } + rc = _lread( iFile, (LPSTR)&w3, sizeof(w3) ); + if ( rc != sizeof(w3) ) { + PRINTF("Could not read w3\n"); + _lclose( iFile ); + return( FALSE ); + } + rc = _lread( iFile, (LPSTR)&w4, sizeof(w4) ); + if ( rc != sizeof(w4) ) { + PRINTF("Could not read w4\n"); + _lclose( iFile ); + return( FALSE ); + } + rc = _lread( iFile, (LPSTR)&next_off, sizeof(next_off) ); + if ( rc != sizeof(next_off) ) { + PRINTF("Could not read next_off\n"); + _lclose( iFile ); + return( FALSE ); + } + start_position = ((LONG)next_off) << 4; + + rc = _lread( iFile, (LPSTR)&c1, sizeof(c1) ); + if ( rc != sizeof(c1) ) { + PRINTF("Could not read c1\n"); + _lclose( iFile ); + return( FALSE ); + } + + read_name( iFile, name_buff ); + +#ifdef NEED_ABSOLUTES +#ifdef NEED_SYM4 + rc = _lread( iFile, (LPSTR)&c2, sizeof(c2) ); + if ( rc != sizeof(c2) ) { + PRINTF("Could not read c2\n"); + _lclose( iFile ); + return( FALSE ); + } +#endif + + cnt = num_syms; + while ( cnt ) { + length = read_symbol( lpOutputRoutine, iFile, name_buff, & + this_offset ); + if ( length == 0 ) { + PRINTF("Error access symbols in file %s\n", filename ); + break; + } + --cnt; + } +#ifdef NEED_INDICES + cnt = num_syms; + while ( cnt ) { + rc = _lread( iFile, (LPSTR)&index, sizeof(index) ); + if ( rc != sizeof(index) ) { + PRINTF("Could not read index table entry\n"); + _lclose( iFile ); + return( FALSE ); + } + PRINTF("Index: %04X\n", index ); + --cnt; + } +#endif +#endif + + position = start_position; + do { + rc = _llseek( iFile, position, FILE_BEGIN ); + if ( rc == -1 ) { + PRINTF("Failed to seek to next record\n"); + _lclose( iFile ); + return( FALSE ); + } + rc = _lread( iFile, (LPSTR)&next_off, sizeof(next_off) ); + if ( rc != sizeof(next_off) ) { + PRINTF("Could not read next_off\n"); + _lclose( iFile ); + return( FALSE ); + } + position = ((LONG)next_off) << 4; + + rc = _lread( iFile, (LPSTR)&num_syms, sizeof(num_syms) ); + if ( rc != sizeof(num_syms) ) { + PRINTF("Could not read num_syms\n"); + _lclose( iFile ); + return( FALSE ); + } + + rc = _lread( iFile, (LPSTR)&r2, sizeof(r2) ); + if ( rc != sizeof(r2) ) { + PRINTF("Could not read r2\n"); + _lclose( iFile ); + return( FALSE ); + } + + rc = _lread( iFile, (LPSTR)&seg_num, sizeof(seg_num) ); + if ( rc != sizeof(seg_num) ) { + PRINTF("Could not read seg_num\n"); + _lclose( iFile ); + return( FALSE ); + } + + if ( mode == PROT_MODE && seg_num != (WORD)(he.SegmentNumber+1) ) { + /* + ** Skip reading of symbols for segments with the wrong seg_num + */ + continue; + } + + cnt = 0; + while ( cnt < 12 ) { + rc = _lread( iFile, (LPSTR)&b[cnt], sizeof(b[0]) ); + if ( rc != sizeof(b[0]) ) { + PRINTF("Could not read 12 byte b array\n"); + _lclose( iFile ); + return( FALSE ); + } + cnt++; + } + read_name( iFile, name_buff ); + + cnt = num_syms; + while ( cnt ) { + length = read_symbol( iFile, name_buff, + &this_offset ); + if ( length == 0 ) { + PRINTF("Error access symbols in file %s\n", filename ); + break; + } + switch( mode ) { + case PROT_MODE: + switch( direction ) { + case BEFORE: + this_dist = offset - this_offset; + break; + case AFTER: + this_dist = this_offset - offset; + break; + } + break; + case V86_MODE: +#if 0 + mod_addr = mod_offset + (ULONG)(seg_num << 4) + this_offset; + switch( direction ) { + case BEFORE: + this_dist = v86_addr - mod_addr; + break; + case AFTER: + this_dist = mod_addr - v86_addr; + break; + } +#endif + break; + } + if ( this_dist >= 0 && (this_dist < *dist || *dist == -1) ) { + *dist = this_dist; + strcpy( sym_text, name_buff ); + result = TRUE; + } + --cnt; + } +#ifdef NEED_INDICES + cnt = num_syms; + while ( cnt ) { + rc = _lread( iFile, (LPSTR)&index, sizeof(index) ); + if ( rc != sizeof(index) ) { + PRINTF("Could not read index table entry\n"); + _lclose( iFile ); + return( FALSE ); + } + --cnt; + } +#endif + } while ( position != start_position && position != 0 ); + + _lclose( iFile ); + } + } + return( result ); +} + +BOOL FindAddress( + WORD *selector, + LONG *offset, + LPSTR sym_text, + int mode +) { + int length; + int iFile; + char filename[256]; + OFSTRUCT ofs; + LONG filesize; + LONG start_position; + LONG position; + WORD w1; + WORD num_syms; + WORD w3; + WORD w4; + WORD next_off; +#ifdef NEED_INDICES + WORD index; +#endif + char c1; + char c2; + int rc; + int cnt; + LONG this_offset; + WORD r2; + WORD seg_num; + char b[12]; + char name_buff[128]; + char name1[200]; + HEAPENTRY he = {0}; + + strcpy(name1,sym_text); + _strupr(name1); + + if (mode == V86_MODE) { //BUGBUG + return FALSE; + } + + /* + ** Search for selector in kernel heap + */ + while (FindHeapEntry(&he, FALSE)) { + { + strcpy(filename, he.FileName); + strcat(filename,".sym"); + + iFile = OpenFile( filename, &ofs, MYOF_FLAGS ); + + if ( iFile == -1 ) { + // PRINTF("Could not open symbol file \"%s\"\n", filename ); + continue; + } + + rc = _lread( iFile, (LPSTR)&filesize, sizeof(filesize) ); + if ( rc != sizeof(filesize) ) { + PRINTF("Could not read file size\n"); + _lclose( iFile ); + return( FALSE ); + } + filesize <<= 4; + + rc = _lread( iFile, (LPSTR)&w1, sizeof(w1) ); + if ( rc != sizeof(w1) ) { + PRINTF("Could not read w1\n"); + _lclose( iFile ); + return( FALSE ); + } + + rc = _lread( iFile, (LPSTR)&num_syms, sizeof(num_syms) ); + if ( rc != sizeof(num_syms) ) { + PRINTF("Could not read num_syms\n"); + _lclose( iFile ); + return( FALSE ); + } + rc = _lread( iFile, (LPSTR)&w3, sizeof(w3) ); + if ( rc != sizeof(w3) ) { + PRINTF("Could not read w3\n"); + _lclose( iFile ); + return( FALSE ); + } + rc = _lread( iFile, (LPSTR)&w4, sizeof(w4) ); + if ( rc != sizeof(w4) ) { + PRINTF("Could not read w4\n"); + _lclose( iFile ); + return( FALSE ); + } + rc = _lread( iFile, (LPSTR)&next_off, sizeof(next_off) ); + if ( rc != sizeof(next_off) ) { + PRINTF("Could not read next_off\n"); + _lclose( iFile ); + return( FALSE ); + } + start_position = ((LONG)next_off) << 4; + + rc = _lread( iFile, (LPSTR)&c1, sizeof(c1) ); + if ( rc != sizeof(c1) ) { + PRINTF("Could not read c1\n"); + _lclose( iFile ); + return( FALSE ); + } + + read_name( iFile, name_buff ); + + rc = _lread( iFile, (LPSTR)&c2, sizeof(c2) ); + if ( rc != sizeof(c2) ) { + PRINTF("Could not read c2\n"); + _lclose( iFile ); + return( FALSE ); + } + + cnt = num_syms; + while ( cnt ) { + length = read_symbol( iFile, name_buff, + &this_offset ); + if ( length == 0 ) { + PRINTF("Error access symbols in file %s\n", filename ); + break; + } + + --cnt; + } +#ifdef NEED_INDICES + cnt = num_syms; + while ( cnt ) { + rc = _lread( iFile, (LPSTR)&index, sizeof(index) ); + if ( rc != sizeof(index) ) { + PRINTF("Could not read index table entry\n"); + _lclose( iFile ); + return( FALSE ); + } + PRINTF("Index: %04X\n", index ); + --cnt; + } +#endif + + position = start_position; + do { + rc = _llseek( iFile, position, FILE_BEGIN ); + if ( rc == -1 ) { + PRINTF("Failed to seek to next record\n"); + _lclose( iFile ); + return( FALSE ); + } + rc = _lread( iFile, (LPSTR)&next_off, sizeof(next_off) ); + if ( rc != sizeof(next_off) ) { + PRINTF("Could not read next_off\n"); + _lclose( iFile ); + return( FALSE ); + } + position = ((LONG)next_off) << 4; + + rc = _lread( iFile, (LPSTR)&num_syms, sizeof(num_syms) ); + if ( rc != sizeof(num_syms) ) { + PRINTF("Could not read num_syms\n"); + _lclose( iFile ); + return( FALSE ); + } + + rc = _lread( iFile, (LPSTR)&r2, sizeof(r2) ); + if ( rc != sizeof(r2) ) { + PRINTF("Could not read r2\n"); + _lclose( iFile ); + return( FALSE ); + } + + rc = _lread( iFile, (LPSTR)&seg_num, sizeof(seg_num) ); + if ( rc != sizeof(seg_num) ) { + PRINTF("Could not read seg_num\n"); + _lclose( iFile ); + return( FALSE ); + } + + if ( mode == PROT_MODE && + seg_num != (WORD)(he.SegmentNumber+1) ) { + /* + ** Skip reading of symbols for segments with the wrong seg_num + */ + continue; + } + + cnt = 0; + while ( cnt < 12 ) { + rc = _lread( iFile, (LPSTR)&b[cnt], sizeof(b[0]) ); + if ( rc != sizeof(b[0]) ) { + PRINTF("Could not read 12 byte b array\n"); + _lclose( iFile ); + return( FALSE ); + } + cnt++; + } + read_name( iFile, name_buff ); + + cnt = num_syms; + while ( cnt ) { + length = read_symbol( iFile, name_buff, &this_offset ); + if ( length == 0 ) { + PRINTF("Error access symbols in file %s\n", filename ); + break; + } + if ( _stricmp(name_buff,sym_text) == 0 ) { + switch( mode ) { + case PROT_MODE: + *selector = (WORD)(he.gnode.pga_handle | 1); + *offset = this_offset; + _lclose( iFile ); + return( TRUE ); +#if 0 + case V86_MODE: + *selector = se[nEntry].selector + seg_num; + *offset = this_offset; + _lclose( iFile ); + return( TRUE ); +#endif + } + } + { + char name2[200]; + + strcpy(name2,name_buff); + _strupr(name2); + + if ( strstr(name2,name1) != 0 ) { + switch( mode ) { + case PROT_MODE: + *selector = (WORD)(he.gnode.pga_handle | 1); + *offset = this_offset; + PRINTF("%04X:%04X = %s\n", *selector, *offset, name_buff ); + break; +#if 0 + case V86_MODE: + *selector = se[nEntry].selector + seg_num; + *offset = this_offset; + PRINTF("%04X:%04X = %s\n", *selector, *offset, name_buff ); + break; +#endif + } + } + } + + --cnt; + } + } while ( position != start_position && position != 0 ); + + _lclose( iFile ); + } + } + return( FALSE ); +} + +VOID +ListNear( +) { + VDMCONTEXT ThreadContext; + WORD selector; + LONG offset; + CHAR sym_text[1000]; + DWORD dist; + BOOL b; + int mode; + + 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 +EvaluateSymbol( +) { + VDMCONTEXT ThreadContext; + BOOL result; + WORD selector; + LONG offset; + int mode; + + try { + + mode = GetContext( &ThreadContext ); + + result = FindAddress( &selector, &offset, lpArgumentString, mode ); + + if ( result ) { + if ( mode == PROT_MODE ) { + PRINTF("Symbol %s = #%04X:%04X PROT_MODE\n", lpArgumentString, selector, offset ); + } + if ( mode == V86_MODE ) { + PRINTF("Symbol %s = &%04X:%04X V86_MODE\n", lpArgumentString, selector, offset ); + } + return; + } + + if ( mode == PROT_MODE ) { + mode = V86_MODE; + } else { + if ( mode == V86_MODE ) { + mode = PROT_MODE; + } + } + + result = FindAddress( &selector, &offset, lpArgumentString, mode ); + if ( result ) { + if ( mode == PROT_MODE ) { + PRINTF("Symbol %s = #%04X:%04X PROT_MODE\n", lpArgumentString, selector, offset ); + } + if ( mode == V86_MODE ) { + PRINTF("Symbol %s = &%04X:%04X V86_MODE\n", lpArgumentString, selector, offset ); + } + return; + } + + PRINTF("Could not find symbol %s\n", lpArgumentString ); + + } except (1) { + + PRINTF("Exception 0x%08x in !bde.es, don't forget to thank Dave Hart for saving\n" + "your debugging bacon by adding a try/except block!\n" + "And while you're at it remind him to take out this caffeine-induced spew.\n", + GetExceptionCode()); + + } +} + diff --git a/private/mvdm/bde/bdeutil.c b/private/mvdm/bde/bdeutil.c new file mode 100644 index 000000000..141358b37 --- /dev/null +++ b/private/mvdm/bde/bdeutil.c @@ -0,0 +1,614 @@ +#include <precomp.h> +#pragma hdrstop + +BOOL +WINAPI +ReadProcessMem( + HANDLE hProcess, + LPVOID lpBaseAddress, + LPVOID lpBuffer, + DWORD nSize, + LPDWORD lpNumberOfBytesRead + ) +{ + if ( fWinDbg ) { + return (*ReadProcessMemWinDbg)( (DWORD)lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead ); + } else { + return ReadProcessMemory( hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead ); + } +} + +BOOL +WINAPI +WriteProcessMem( + HANDLE hProcess, + LPVOID lpBaseAddress, + LPVOID lpBuffer, + DWORD nSize, + LPDWORD lpNumberOfBytesWritten + ) +{ + if ( fWinDbg ) { + return (*WriteProcessMemWinDbg)( (DWORD)lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesWritten ); + } else { + return WriteProcessMemory( hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesWritten ); + } + +} + +#ifndef i386 + +ULONG +GetRegValue( + NT_CPU_REG reg, + BOOL bInNano, + ULONG UMask + ) + +{ + if (bInNano) { + + return(ReadDword(reg.nano_reg)); + + } else if (UMask & reg.universe_8bit_mask) { + + return (ReadDword(reg.saved_reg) & 0xFFFFFF00 | + ReadDword(reg.reg) & 0xFF); + + } else if (UMask & reg.universe_16bit_mask) { + + return (ReadDword(reg.saved_reg) & 0xFFFF0000 | + ReadDword(reg.reg) & 0xFFFF); + + } else { + + return (ReadDword(reg.reg)); + + } +} + +ULONG +GetEspValue( + NT_CPU_INFO nt_cpu_info, + BOOL bInNano + ) + +{ + if (bInNano) { + + return (ReadDword(nt_cpu_info.nano_esp)); + + } else { + + if (ReadDword(nt_cpu_info.stack_is_big)) { + + return (ReadDword(nt_cpu_info.host_sp) - + ReadDword(nt_cpu_info.ss_base)); + + } else { + + return (ReadDword(nt_cpu_info.esp_sanctuary) & 0xFFFF0000 | + (ReadDword(nt_cpu_info.host_sp) - + ReadDword(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 = ReadProcessMem( hCurrentProcess, + (LPVOID) pTmp, + (LPVOID) &nt_cpu_info, + sizeof(NT_CPU_INFO), + NULL ); + if ( !b ) { + PRINTF("Could not read IntelRegisters context out of process\n"); + return( -1 ); + } + + bInNano = ReadDword((ULONG) nt_cpu_info.in_nano_cpu); + UMask = ReadDword((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 = ReadDword(nt_cpu_info.flags); + lpContext->Eip = ReadDword(nt_cpu_info.eip); + + lpContext->SegEs = ReadWord(nt_cpu_info.es); + lpContext->SegCs = ReadWord(nt_cpu_info.cs); + lpContext->SegSs = ReadWord(nt_cpu_info.ss); + lpContext->SegDs = ReadWord(nt_cpu_info.ds); + lpContext->SegFs = ReadWord(nt_cpu_info.fs); + lpContext->SegGs = ReadWord(nt_cpu_info.gs); + + + } else { + + PRINTF("Could not find the symbol 'ntvdm!nt_cpu_info'\n"); + return( -1 ); + } + + if ( !(ReadDword(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; + + 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 = ReadProcessMem( hCurrentProcess, + (LPVOID) (lpVdmTib + + FIELD_OFFSET(VDM_TIB,VdmContext)), + lpContext, + sizeof(VDMCONTEXT), + NULL ); + 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 = ReadProcessMem( hCurrentProcess, + (LPVOID) IntelBase, &IntelBase, + sizeof(ULONG), NULL ); + 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 = ReadProcessMem( + hCurrentProcess, + (LPVOID)lpAddress, + &dword, + sizeof(dword), + NULL + ); + 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 = ReadProcessMem( + hCurrentProcess, + (LPVOID)lpAddress, + &word, + sizeof(word), + NULL + ); + 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 = ReadProcessMem( + hCurrentProcess, + (LPVOID)lpAddress, + &byte, + sizeof(byte), + NULL + ); + if ( !b ) { + if ( !bSafe ) { + PRINTF("Failure reading byte at memory location %08lX\n", lpAddress ); + } + return( 0 ); + } + return( byte ); +} + +BOOL read_gnode( + ULONG lpAddress, + PGNODE p, + BOOL bSafe +) { + BOOL b; + + b = ReadProcessMem( + hCurrentProcess, + (LPVOID)lpAddress, + p, + sizeof(*p), + NULL + ); + if ( !b ) { + if ( !bSafe ) { + PRINTF("Failure reading word at memory location %08lX\n", lpAddress ); + } + return( 0 ); + } + return( TRUE ); +} + +BOOL read_gnode32( + ULONG lpAddress, + PGNODE32 p, + BOOL bSafe +) { + BOOL b; + + b = ReadProcessMem( + hCurrentProcess, + (LPVOID)lpAddress, + p, + sizeof(*p), + NULL + ); + 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 + NTSTATUS rc; + DESCRIPTOR_TABLE_ENTRY dte; + dte.Selector = selector; + rc = NtQueryInformationThread( hCurrentThread, + ThreadDescriptorTableEntry, + &dte, + sizeof(DESCRIPTOR_TABLE_ENTRY), + NULL ); + if ( NT_ERROR(rc) ) { + return( FALSE ); + } + pdte->HighWord = dte.Descriptor.HighWord; + pdte->BaseLow = dte.Descriptor.BaseLow; + pdte->LimitLow = dte.Descriptor.LimitLow; + return (TRUE); +#else + PVOID LdtAddress; + NTSTATUS Status; + ULONG BytesRead; + selector &= ~(SELECTOR_LDT | SELECTOR_RPL); + + // + // Get address of Ldt + // + + LdtAddress = (PVOID)EXPRESSION("ntvdm!Ldt"); + + Status = ReadProcessMem( + hCurrentProcess, + LdtAddress, + &LdtAddress, + sizeof(ULONG), + &BytesRead + ); + + if ((!Status) || (BytesRead != sizeof(ULONG))) { + return FALSE; + } + + (PUCHAR)LdtAddress += selector; + + Status = ReadProcessMem( + hCurrentProcess, + LdtAddress, + pdte, + sizeof(VDMLDT_ENTRY), + &BytesRead + ); + return TRUE; +#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->bCode = FALSE; + } + break; + case PROT_MODE: + +#ifdef i386 + if ( (selector & 0xFF78) < 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 = ReadProcessMem( + hCurrentProcess, + (LPVOID)base, + &byte, + sizeof(byte), + NULL + ); + 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; +} + + +BOOL +ParseIntelAddress( + int *pMode, + WORD *pSelector, + PULONG pOffset + ) + +{ + char sel_text[128], off_text[128]; + char *colon; + char *mode_prefix; + + colon = strchr( lpArgumentString, ':' ); + if ( colon == NULL ) { + PRINTF("Please specify an address in the form 'seg:offset'\n"); + return FALSE; + } + + 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 ); + *pSelector = (WORD) EXPRESSION( sel_text ); + *pOffset = (ULONG) EXPRESSION( off_text ); + + SkipToNextWhiteSpace(); + + return TRUE; +} diff --git a/private/mvdm/bde/data.c b/private/mvdm/bde/data.c new file mode 100644 index 000000000..fea75b02a --- /dev/null +++ b/private/mvdm/bde/data.c @@ -0,0 +1,43 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + Data.c + +Abstract: + + This module contains definitions for global data for the IEU and + VDD debugging extensions + +Author: + + Dave Hastings (daveh) 2-Apr-1992 + +Revision History: + +--*/ + +#include <precomp.h> +#pragma hdrstop +// +// Pointers to NTSD api +// + +PNTSD_OUTPUT_ROUTINE Print; +PNTSD_GET_EXPRESSION GetExpression; +PNTSD_GET_SYMBOL GetSymbol; +//PNTSD_DISASM Disassemble; +PNTSD_CHECK_CONTROL_C CheckCtrlC; + +PWINDBG_READ_PROCESS_MEMORY_ROUTINE ReadProcessMemWinDbg; +PWINDBG_WRITE_PROCESS_MEMORY_ROUTINE WriteProcessMemWinDbg; +PWINDBG_GET_THREAD_CONTEXT_ROUTINE GetThreadContextWinDbg; +PWINDBG_SET_THREAD_CONTEXT_ROUTINE SetThreadContextWinDbg; + +BOOL fWinDbg; + +HANDLE hCurrentProcess; +HANDLE hCurrentThread; +LPSTR lpArgumentString; diff --git a/private/mvdm/bde/disasm.c b/private/mvdm/bde/disasm.c new file mode 100644 index 000000000..4b1fb7e1b --- /dev/null +++ b/private/mvdm/bde/disasm.c @@ -0,0 +1,2380 @@ +/*++ + +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + disasm.c + +Abstract: + + This file contains the x86 disassmbler invoked by "!bde.u <16:16 address>" + +Author: + + Barry Bond (BarryBo) + +Revision History: + + 09-May-1995 Barry Bond (BarryBo) Created + +--*/ + +#include <precomp.h> +#pragma hdrstop + +int unassemble_one(BYTE *pInstrStart, BOOL bDefaultBig, WORD wInstrSeg, DWORD dwInstrOff, char *pchOutput, char *pchExtra); + +// global variables which must be set by the caller of unassemble_one() +static VDMCONTEXT *g_pThreadContext; +static int g_mode; + + +VOID +Unassemble( + VOID +) { + VDMCONTEXT ThreadContext; + WORD selector; + ULONG offset; + int mode; + char rgchOutput[128]; + char rgchExtra[128]; + BYTE rgbInstruction[64]; + int cb; + int i; + int j; + int count=10; + ULONG Base; + SELECTORINFO si; + + mode = GetContext( &ThreadContext ); + + if (!GetNextToken()) { + selector = (WORD) ThreadContext.SegCs; + offset = ThreadContext.Eip; + } else if (!ParseIntelAddress(&mode, &selector, &offset)) { + return; + } + + if (GetNextToken()) { + count = (int) EXPRESSION(lpArgumentString); + } + + if ( mode != PROT_MODE && mode != V86_MODE) { + PRINTF(" Disassembly of flat mode code not allowed.\n"); + return; + } + + g_pThreadContext = &ThreadContext; + g_mode = mode; + + Base = GetInfoFromSelector( selector, mode, &si ) + GetIntelBase(); + + for (i=0; i<count; ++i) { + + cb = sizeof(rgbInstruction); + if ((DWORD)(offset+cb) >= si.Limit) + cb -= offset+cb-si.Limit; + if (!ReadProcessMem( hCurrentProcess, + (LPVOID)(Base+offset), + rgbInstruction, + cb, + NULL)) { + PRINTF("<Error Reading Memory>\n"); + return; + } + + cb = unassemble_one(rgbInstruction, + si.bBig, + selector, offset, + rgchOutput, + rgchExtra); + + if (offset > 0xffff) { + PRINTF("%04x:%08x ", selector, offset); + } else { + PRINTF("%04x:%04x ", selector, offset); + } + + for (j=0; j<cb; ++j) + PRINTF("%02x", rgbInstruction[j]); + for (; j<8; ++j) + PRINTF(" "); + PRINTF("%s\t%s\n", rgchOutput, rgchExtra); + + offset+=cb; + } +} + + +typedef struct _ADDR { + ULONG sOff; + USHORT sSeg; +} ADDR; + + +LPBYTE checkprefixes(LPBYTE); +void AppendPrefixes(void); +void DisplayAddress(int mod, int rm, int sOff, int size); + +#define modrmB 1 +#define modrmW 2 +#define reg1B 3 +#define reg1W 4 +#define reg2B 5 +#define reg2W 6 +#define eeeControl 7 +#define eeeDebug 8 +#define eeeTest 9 +#define regSeg 10 +#define ALreg 11 +#define AHreg 12 +#define BLreg 13 +#define BHreg 14 +#define CLreg 15 +#define CHreg 16 +#define DLreg 17 +#define DHreg 18 +#define AXreg 19 +#define BXreg 20 +#define CXreg 21 +#define DXreg 22 +#define SIreg 23 +#define DIreg 24 +#define SPreg 25 +#define BPreg 26 +#define CSreg 27 +#define SSreg 28 +#define DSreg 29 +#define ESreg 30 +#define FSreg 31 +#define GSreg 32 +#define ImmB 33 +#define ImmBEnter 34 +#define ImmBS 35 +#define ImmW 36 +#define ImmW1 37 +#define jmpB 38 +#define jmpW 39 +#define memB 40 +#define memW 41 +#define memD 42 +#define indirmodrmW 43 +#define indirFARmodrmW 44 +#define memB1 45 + + +int DmodrmB(LPBYTE); +int DmodrmW(LPBYTE); +int Dreg1B(LPBYTE); +int Dreg1W(LPBYTE); +int Dreg2B(LPBYTE); +int Dreg2W(LPBYTE); +int DeeeControl(LPBYTE); +int DeeeDebug(LPBYTE); +int DeeeTest(LPBYTE); +int DregSeg(LPBYTE); +int DALreg(LPBYTE); +int DAHreg(LPBYTE); +int DBLreg(LPBYTE); +int DBHreg(LPBYTE); +int DCLreg(LPBYTE); +int DCHreg(LPBYTE); +int DDLreg(LPBYTE); +int DDHreg(LPBYTE); +int DAXreg(LPBYTE); +int DBXreg(LPBYTE); +int DCXreg(LPBYTE); +int DDXreg(LPBYTE); +int DSIreg(LPBYTE); +int DDIreg(LPBYTE); +int DSPreg(LPBYTE); +int DBPreg(LPBYTE); +int DCSreg(LPBYTE); +int DSSreg(LPBYTE); +int DDSreg(LPBYTE); +int DESreg(LPBYTE); +int DFSreg(LPBYTE); +int DGSreg(LPBYTE); +int DImmB(LPBYTE); +int DImmBEnter(LPBYTE); +int DImmBS(LPBYTE); +int DImmW(LPBYTE); +int DImmW1(LPBYTE); // immediate-16 for 1-byte instructions +int DjmpB(LPBYTE); +int DjmpW(LPBYTE); +int DmemB(LPBYTE); +int DmemB1(LPBYTE); +int DmemW(LPBYTE); +int DmemD(LPBYTE); +int DindirmodrmW(LPBYTE); +int DindirFARmodrmW(LPBYTE); + +struct { + int (*pfn)(LPBYTE); +} rgpfn[] = { + + 0, // 0th entry is reserved + DmodrmB, + DmodrmW, + Dreg1B, + Dreg1W, + Dreg2B, + Dreg2W, + DeeeControl, + DeeeDebug, + DeeeTest, + DregSeg, + DALreg, + DAHreg, + DBLreg, + DBHreg, + DCLreg, + DCHreg, + DDLreg, + DDHreg, + DAXreg, + DBXreg, + DCXreg, + DDXreg, + DSIreg, + DDIreg, + DSPreg, + DBPreg, + DCSreg, + DSSreg, + DDSreg, + DESreg, + DFSreg, + DGSreg, + DImmB, + DImmBEnter, + DImmBS, + DImmW, + DImmW1, // immediate-16 for 1-byte instructions + DjmpB, + DjmpW, + DmemB, + DmemW, + DmemD, + DindirmodrmW, + DindirFARmodrmW, + DmemB1 +}; + +char *g_pchOutput; // the disassembled instruction +char *g_pchExtra; // contents of memory (if any) modified by this instr. +int prefixes; + +//NOTE: if first byte = 0x0f, then the instruction is two bytes long + +char *szRegsB[] = {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"}; +char *szRegsW[] = {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"}; +char *szRegsD[] = {"eax","ecx","edx","ebx","esp","ebp","esi","edi"}; +char *szRegsSeg[] = {"es", "cs", "ss", "ds", "fs", "gs", "(bad)", "(bad)"}; +char *szMod[] = {"[bx+si", "[bx+di", "[bp+si", "[bp+di", "[si", "[di", "[bp", "[bx"}; + +#define PREFIX_REPZ 1 +#define PREFIX_REPNZ 2 +#define PREFIX_LOCK 4 +#define PREFIX_CS 8 +#define PREFIX_SS 0x10 +#define PREFIX_DS 0x20 +#define PREFIX_ES 0x40 +#define PREFIX_FS 0x80 +#define PREFIX_GS 0x100 +#define PREFIX_DATA 0x200 +#define PREFIX_ADR 0x400 +#define PREFIX_FWAIT 0x800 + +#define GROUP_1B -1 +#define GROUP_1WS -2 +#define GROUP_1W -3 +#define GROUP_2B -4 +#define GROUP_2W -5 +#define GROUP_2B_1 -6 +#define GROUP_2W_1 -7 +#define GROUP_2B_CL -8 +#define GROUP_2W_CL -9 +#define GROUP_3B -10 +#define GROUP_3W -11 +#define GROUP_4 -12 +#define GROUP_5 -13 +#define GROUP_6 -14 +#define GROUP_7 -15 +#define GROUP_8 -16 + +#define FLOATCODE -51 +#define FLOAT FLOATCODE + +// WARNING: This list must remain in sync with the szInstructions[] array +#define szAdc 1 +#define szAdd 2 +#define szAnd 3 +#define szBad 4 +#define szCmp 5 +#define szDec 6 +#define szIn 7 +#define szInc 8 +#define szJmp 9 +#define szMov 10 +#define szOr 11 +#define szOut 12 +#define szRcl 13 +#define szRcr 14 +#define szRol 15 +#define szRor 16 +#define szSar 17 +#define szSbb 18 +#define szShl 19 +#define szShr 20 +#define szSub 21 +#define szTest 22 +#define szPop 23 +#define szPush 24 +#define szXchg 25 +#define szXor 26 +#define szDaa 27 +#define szDas 28 +#define szPusha 29 +#define szPopa 30 +#define szBound 31 +#define szArpl 32 +#define szAaa 33 +#define szAas 34 +#define szImul 35 +#define szIdiv 36 +#define szJo 37 +#define szJno 38 +#define szJb 39 +#define szJae 40 +#define szJe 41 +#define szJne 42 +#define szJbe 43 +#define szJa 44 +#define szJs 45 +#define szJns 46 +#define szJp 47 +#define szJnp 48 +#define szJl 49 +#define szJnl 50 +#define szJle 51 +#define szJg 52 +#define szNop 53 +#define szLea 54 +#define szCbw 55 +#define szCwd 56 +#define szCall 57 +#define szPushf 58 +#define szPopf 59 +#define szSahf 60 +#define szLahf 61 +#define szMovsb 62 +#define szMovsw 63 +#define szCmpsb 64 +#define szCmpsw 65 +#define szStosb 66 +#define szStosw 67 +#define szLodsb 68 +#define szLodsw 69 +#define szScasb 70 +#define szScasw 71 +#define szRetn 72 +#define szLes 73 +#define szLds 74 +#define szEnter 75 +#define szLeave 76 +#define szRetf 77 +#define szInt3 78 +#define szInt 79 +#define szInto 80 +#define szIret 81 +#define szAam 82 +#define szAad 83 +#define szXlat 84 +#define szLoopne 85 +#define szLoope 86 +#define szLoop 87 +#define szJcxz 88 +#define szHalt 89 +#define szCmc 90 +#define szClc 91 +#define szStc 92 +#define szCli 93 +#define szSti 94 +#define szCld 95 +#define szStd 96 +#define szLar 97 +#define szLsl 98 +#define szClts 99 +#define szSeto 100 +#define szSetno 101 +#define szSetb 102 +#define szSetae 103 +#define szSete 104 +#define szSetne 105 +#define szSetbe 106 +#define szSeta 107 +#define szSets 108 +#define szSetns 109 +#define szSetp 110 +#define szSetnp 111 +#define szSetl 112 +#define szSetge 113 +#define szSetle 114 +#define szSetg 115 +#define szBt 116 +#define szShld 117 +#define szBts 118 +#define szShrd 119 +#define szShdr 120 +#define szLss 121 +#define szBtr 122 +#define szLfs 123 +#define szLgs 124 +#define szMovzx 125 +#define szBtc 126 +#define szBsf 127 +#define szBsr 128 +#define szMovsx 129 +#define szNot 130 +#define szNeg 131 +#define szMul 132 +#define szDiv 133 +#define szSldt 134 +#define szStr 135 +#define szLldt 136 +#define szLtr 137 +#define szVerr 138 +#define szVerw 139 +#define szSgdt 140 +#define szSidt 141 +#define szLgdt 142 +#define szLidt 143 +#define szSmsw 144 +#define szLmsw 145 + +// WARNING: This must stay in sync with the #define list above +char *szInstructions[] = { + "", //used to indicate groups + "adc", + "add", + "and", + "(bad)", + "cmp", + "dec", + "in", + "inc", + "jmp", + // 10 + "mov", + "or", + "out", + "rcl", + "rcr", + "rol", + "ror", + "sar", + "sbb", + "shl", + // 20 + "shr", + "sub", + "test", + "pop", + "push", + "xchg", + "xor", + "daa", + "das", + "pusha", + // 30 + "popa", + "bound", + "arpl", + "aaa", + "aas", + "imul", + "idiv", + "jo", + "jno", + "jb", + // 40 + "jae", + "je", + "jne", + "jbe", + "ja", + "js", + "jns", + "jp", + "jnp", + "jl", + // 50 + "jnl", + "jle", + "jg", + "nop", + "lea", + "cbw", + "cwd", + "call", + "pushf", + "popf", + // 60 + "sahf", + "lahf", + "movsb", + "movsw", + "cmpsb", + "cmpsw", + "stosb", + "stosw", + "lodsb", + "lodsw", + // 70 + "scasb", + "scasw", + "retn", + "les", + "lds", + "enter", + "leave", + "retf", + "int3", + "int", + // 80 + "into", + "iret", + "aam", + "aad", + "xlat", + "loopne", + "loope", + "loop", + "jcxz", + "halt", + // 90 + "cmc", + "clc", + "stc", + "cli", + "sti", + "cld", + "std", + "lar", + "lsl", + "clts", + // 100 + "seto", + "setno", + "setb", + "setae", + "sete", + "setne", + "setbe", + "seta", + "sets", + "setns", + // 110 + "setp", + "setnp", + "setl", + "setge", + "setle", + "setg", + "bt", + "shld", + "bts", + "shrd", + // 120 + "shdr", + "lss", + "btr", + "lfs", + "lgs", + "movzx", + "btc", + "bsf", + "bsr", + "movsx", + // 130 + "not", + "neg", + "mul", + "div", + "sldt", + "str", + "lldt", + "ltr", + "verr", + "verw", + // 140 + "sgdt", + "sidt", + "lgdt", + "lidt", + "smsw", + "lmsw" +}; + +struct dis { + int szName; + char iPart1; + char iPart2; + char iPart3; +}; + +struct dis dis386[] = { + // 0 + { szAdd, modrmB, reg1B }, + { szAdd, modrmW, reg1W }, + { szAdd, reg1B, modrmB }, + { szAdd, reg1W, modrmW }, + { szAdd, ALreg, ImmB }, + { szAdd, AXreg, ImmW }, + { szPush, ESreg }, + { szPop, ESreg}, + // 8 + { szOr, modrmB, reg1B }, + { szOr, modrmW, reg1W }, + { szOr, reg1B, modrmB }, + { szOr, reg1W, modrmW }, + { szOr, ALreg, ImmB }, + { szOr, AXreg, ImmW }, + { szPush, CSreg }, + { szBad }, // 0x0f is the 2-byte instr prefix + // 10 + { szAdc, modrmB, reg1B }, + { szAdc, modrmW, reg1W }, + { szAdc, reg1B, modrmB }, + { szAdc, reg1W, modrmW }, + { szAdc, ALreg, ImmB }, + { szAdc, AXreg, ImmW }, + { szPush, SSreg }, + { szPop, SSreg }, + // 18 + { szSbb, modrmB, reg1B }, + { szSbb, modrmW, reg1W }, + { szSbb, reg1B, modrmB }, + { szSbb, reg1W, modrmW }, + { szSbb, ALreg, ImmB }, + { szSbb, AXreg, ImmW }, + { szPush, DSreg }, + { szPop, DSreg }, + // 20 + { szAnd, modrmB, reg1B }, + { szAnd, modrmW, reg1W }, + { szAnd, reg1B, modrmB }, + { szAnd, reg1W, modrmW }, + { szAnd, ALreg, ImmB }, + { szAnd, AXreg, ImmW }, + { szBad }, // ES override prefix + { szDaa }, + // 28 + { szSub, modrmB, reg1B }, + { szSub, modrmW, reg1W }, + { szSub, reg1B, modrmB }, + { szSub, reg1W, modrmW }, + { szSub, ALreg, ImmB }, + { szSub, AXreg, ImmW }, + { szBad }, // CS override prefix + { szDas }, + // 30 + { szXor, modrmB, reg1B }, + { szXor, modrmW, reg1W }, + { szXor, reg1B, modrmB }, + { szXor, reg1W, modrmW }, + { szXor, ALreg, ImmB }, + { szXor, AXreg, ImmW }, + { szBad}, // SS override prefix + { szAaa }, + // 38 + { szCmp, modrmB, reg1B }, + { szCmp, modrmW, reg1W }, + { szCmp, reg1B, modrmB }, + { szCmp, reg1W, modrmW }, + { szCmp, ALreg, ImmB }, + { szCmp, AXreg, ImmW }, + { szBad }, + { szAas }, + // 40 + { szInc, AXreg }, + { szInc, CXreg }, + { szInc, DXreg }, + { szInc, BXreg }, + { szInc, SPreg }, + { szInc, BPreg }, + { szInc, SIreg }, + { szInc, DIreg }, + // 48 + { szDec, AXreg }, + { szDec, CXreg }, + { szDec, DXreg }, + { szDec, BXreg }, + { szDec, SPreg }, + { szDec, BPreg }, + { szDec, SIreg }, + { szDec, DIreg }, + // 50 + { szPush, AXreg }, + { szPush, CXreg }, + { szPush, DXreg }, + { szPush, BXreg }, + { szPush, SPreg }, + { szPush, BPreg }, + { szPush, SIreg }, + { szPush, DIreg }, + // 58 + { szPop, AXreg }, + { szPop, CXreg }, + { szPop, DXreg }, + { szPop, BXreg }, + { szPop, SPreg }, + { szPop, BPreg }, + { szPop, SIreg }, + { szPop, DIreg }, + // 60 + { szPusha }, + { szPopa }, + { szBound, reg1W, modrmW }, + { szArpl, reg1W, reg2W }, + { szBad }, // FS segment override + { szBad }, // GS segment override + { szBad }, // op size prefix + { szBad }, // addr size prefix + // 68 + { szPush, ImmW}, + { szImul, reg1W, modrmW }, + { szPush, ImmBS}, + { szImul, reg1B, modrmB }, + { szIn, ImmB, DXreg }, + { szIn, ImmW, DXreg }, + { szOut, ImmB, DXreg }, + { szOut, ImmW, DXreg }, + // 70 + { szJo, jmpB }, + { szJno, jmpB }, + { szJb, jmpB }, + { szJae, jmpB }, + { szJe, jmpB }, + { szJne, jmpB }, + { szJbe, jmpB }, + { szJa, jmpB }, + // 78 + { szJs, jmpB }, + { szJns, jmpB }, + { szJp, jmpB }, + { szJnp, jmpB }, + { szJl, jmpB }, + { szJnl, jmpB }, + { szJle, jmpB }, + { szJg, jmpB }, + // 80 + { GROUP_1B }, + { GROUP_1W }, + { szBad }, + { GROUP_1WS }, + { szTest, reg1B, modrmB }, + { szTest, reg1W, modrmW }, + { szXchg, reg1B, modrmB }, + { szXchg, reg1W, modrmW }, + // 88 + { szMov, modrmB, reg1B }, + { szMov, modrmW, reg1W }, + { szMov, reg1B, modrmB }, + { szMov, reg1W, modrmW }, + { szMov, modrmW, regSeg }, + { szLea, reg1W, modrmW }, + { szMov, regSeg, modrmW }, + { szPop, modrmW }, + // 90 + { szNop }, + { szXchg, AXreg, CXreg }, + { szXchg, AXreg, DXreg }, + { szXchg, AXreg, BXreg }, + { szXchg, AXreg, SPreg }, + { szXchg, AXreg, BPreg }, + { szXchg, AXreg, SIreg }, + { szXchg, AXreg, DIreg }, + // 98 + { szCbw }, + { szCwd }, + { szCall, memD }, + { szBad }, + { szPushf }, + { szPopf }, + { szSahf }, + { szLahf }, + // a0 + { szMov, ALreg, memB }, + { szMov, AXreg, memW }, + { szMov, memB, ALreg }, + { szMov, memW, AXreg }, + { szMovsb }, + { szMovsw }, + { szCmpsb }, + { szCmpsw }, + // a8 + { szTest, ALreg, memB }, + { szTest, AXreg, memW }, + { szStosb }, + { szStosw }, + { szLodsb }, + { szLodsw }, + { szScasb }, + { szScasw }, + // b0 + { szMov, ALreg, ImmB }, + { szMov, CLreg, ImmB }, + { szMov, DLreg, ImmB }, + { szMov, BLreg, ImmB }, + { szMov, AHreg, ImmB }, + { szMov, CHreg, ImmB }, + { szMov, DHreg, ImmB }, + { szMov, BHreg, ImmB }, + // b8 + { szMov, AXreg, ImmW }, + { szMov, CXreg, ImmW }, + { szMov, DXreg, ImmW }, + { szMov, BXreg, ImmW }, + { szMov, SPreg, ImmW }, + { szMov, BPreg, ImmW }, + { szMov, SIreg, ImmW }, + { szMov, DIreg, ImmW }, + // c0 + { GROUP_2B }, + { GROUP_2W }, + { szRetn, ImmW }, + { szRetn }, + { szLes, reg1W, modrmW }, + { szLds, reg1W, modrmW }, + { szMov, modrmB, ImmB }, + { szMov, modrmW, ImmW }, + // c8 + { szEnter, ImmW, ImmBEnter }, + { szLeave }, + { szRetf, ImmW1 }, + { szRetf }, + { szInt3 }, + { szInt, ImmB }, + { szInto }, + { szIret }, + // d0 + { GROUP_2B_1 }, + { GROUP_2W_1 }, + { GROUP_2B_CL }, + { GROUP_2W_CL }, + { szAam, ImmB }, + { szAad, ImmB }, + { szBad }, + { szXlat }, + // d8 + { FLOAT }, + { FLOAT }, + { FLOAT }, + { FLOAT }, + { FLOAT }, + { FLOAT }, + { FLOAT }, + { FLOAT }, + // e0 + { szLoopne, jmpB }, + { szLoope, jmpB }, + { szLoop, jmpB }, + { szJcxz, jmpB }, + { szIn, ALreg, memB1 }, + { szIn, AXreg, memB1 }, + { szOut, memB1, ALreg }, + { szOut, memB1, AXreg }, + // e8 + { szCall, jmpW }, + { szJmp, jmpW }, + { szJmp, memD }, + { szJmp, jmpB }, + { szIn, ALreg, DXreg }, + { szIn, AXreg, DXreg }, + { szOut, DXreg, ALreg }, + { szOut, DXreg, AXreg }, + // f0 + { szBad }, // lock prefix + { szBad }, + { szBad }, // repne prefix + { szBad }, // repz prefix + { szHalt }, + { szCmc }, + { GROUP_3B }, + { GROUP_3W }, + // f8 + { szClc }, + { szStc }, + { szCli }, + { szSti }, + { szCld }, + { szStd }, + { GROUP_4 }, + { GROUP_5 }, +}; + + +struct dis dis386_2[] = { + // 00 + { GROUP_6 }, + { GROUP_7 }, + { szLar, reg1W, modrmW }, + { szLsl, reg1W, modrmW }, + { szBad }, + { szBad }, + { szClts }, + { szBad }, + // 08 + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + // 10 + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + // 18 + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + // 20 + { szMov, reg2W, eeeControl }, + { szMov, reg2W, eeeDebug }, + { szMov, eeeControl, reg2W }, + { szMov, eeeDebug, reg2W }, + { szMov, reg2W, eeeTest }, + { szBad }, + { szMov, eeeTest, reg2W }, + { szBad }, + // 28 + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + // 30 + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + // 38 + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + // 40 + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + // 48 + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + // 50 + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + // 58 + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + // 60 + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + // 68 + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + // 70 + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + // 78 + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + // 80 + { szJo, jmpW }, + { szJno, jmpW }, + { szJb, jmpW }, + { szJae, jmpW }, + { szJe, jmpW }, + { szJne, jmpW }, + { szJbe, jmpW }, + { szJa, jmpW }, + // 88 + { szJs, jmpW }, + { szJns, jmpW }, + { szJp, jmpW }, + { szJnp, jmpW }, + { szJl, jmpW }, + { szJnl, jmpW }, + { szJle, jmpW }, + { szJg, jmpW }, + // 90 + { szSeto, modrmB }, + { szSetno, modrmB }, + { szSetb, modrmB }, + { szSetae, modrmB }, + { szSete, modrmB }, + { szSetne, modrmB }, + { szSetbe, modrmB }, + { szSeta, modrmB }, + // 98 + { szSets, modrmB }, + { szSetns, modrmB }, + { szSetp, modrmB }, + { szSetnp, modrmB }, + { szSetl, modrmB }, + { szSetge, modrmB }, + { szSetle, modrmB }, + { szSetg, modrmB }, + // a0 + { szPush, FSreg }, + { szPop, FSreg }, + { szBad }, + { szBt, modrmW, reg1W }, + { szShld, reg1W, modrmW, ImmB }, + { szShld, reg1W, modrmW, CLreg }, + { szBad }, + { szBad }, + // a8 + { szPush, GSreg }, + { szPop, GSreg }, + { szBad }, + { szBts, modrmW, reg1W }, + { szShrd, reg1W, modrmW, ImmB }, + { szShdr, reg1W, modrmW, CLreg }, + { szBad }, + { szImul, reg1W, modrmW }, + // b0 + { szBad }, + { szBad }, + { szLss, reg1W, modrmW }, + { szBtr, modrmW, reg1W }, + { szLfs, reg1W, modrmW }, + { szLgs, reg1W, modrmW }, + { szMovzx, reg1B, modrmB }, + { szMovzx, reg1W, modrmW }, + // b8 + { szBad }, + { szBad }, + { GROUP_8 }, + { szBtc, modrmW, reg1W }, + { szBsf, reg1W, modrmW }, + { szBsr, reg1W, modrmW }, + { szMovsx, reg1B, modrmB }, + { szMovsx, reg1W, modrmW }, + // c0 + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + // c8 + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + // d0 + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + // d8 + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + // e0 + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + // e8 + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + // f0 + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + // f8 + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, +}; + +struct dis dis386_groups[][8] = { + // GROUP_1B + { + { szAdd, modrmB, ImmB }, + { szOr, modrmB, ImmB }, + { szAdc, modrmB, ImmB }, + { szSbb, modrmB, ImmB }, + { szAnd, modrmB, ImmB }, + { szSub, modrmB, ImmB }, + { szXor, modrmB, ImmB }, + { szCmp, modrmB, ImmB } + }, + // GROUP_1WS + { + { szAdd, modrmW, ImmBS }, + { szOr, modrmW, ImmBS }, + { szAdc, modrmW, ImmBS }, + { szSbb, modrmW, ImmBS }, + { szAnd, modrmW, ImmBS }, + { szSub, modrmW, ImmBS }, + { szXor, modrmW, ImmBS }, + { szCmp, modrmW, ImmBS } + }, + // GROUP_1W + { + { szAdd, modrmW, ImmW }, + { szOr, modrmW, ImmW }, + { szAdc, modrmW, ImmW }, + { szSbb, modrmW, ImmW }, + { szAnd, modrmW, ImmW }, + { szSub, modrmW, ImmW }, + { szXor, modrmW, ImmW }, + { szCmp, modrmW, ImmW } + }, + // GROUP_2B + { + { szRol, modrmB, ImmB }, + { szRor, modrmB, ImmB }, + { szRcl, modrmB, ImmB }, + { szRcr, modrmB, ImmB }, + { szShl, modrmB, ImmB }, + { szShr, modrmB, ImmB }, + { szBad }, + { szSar, modrmB, ImmB } + }, + // GROUP_2W + { + { szRol, modrmW, ImmB }, + { szRor, modrmW, ImmB }, + { szRcl, modrmW, ImmB }, + { szRcr, modrmW, ImmB }, + { szShl, modrmW, ImmB }, + { szShr, modrmW, ImmB }, + { szBad }, + { szSar, modrmW, ImmB } + }, + // GROUP_2B_1 + { + { szRol, modrmB }, + { szRor, modrmB }, + { szRcl, modrmB }, + { szRcr, modrmB }, + { szShl, modrmB }, + { szShr, modrmB }, + { szBad }, + { szSar, modrmB } + }, + // GROUP_2W_1 + { + { szRol, modrmW }, + { szRor, modrmW }, + { szRcl, modrmW }, + { szRcr, modrmW }, + { szShl, modrmW }, + { szShr, modrmW }, + { szBad }, + { szSar, modrmW } + }, + // GROUP_2B_CL + { + { szRol, modrmB, CLreg }, + { szRor, modrmB, CLreg }, + { szRcl, modrmB, CLreg }, + { szRcr, modrmB, CLreg }, + { szShl, modrmB, CLreg }, + { szShr, modrmB, CLreg }, + { szBad }, + { szSar, modrmB, CLreg } + }, + // GROUP_2W_CL + { + { szRol, modrmW, CLreg }, + { szRor, modrmW, CLreg }, + { szRcl, modrmW, CLreg }, + { szRcr, modrmW, CLreg }, + { szShl, modrmW, CLreg }, + { szShr, modrmW, CLreg }, + { szBad }, + { szSar, modrmW, CLreg } + }, + // GROUP_3B + { + { szTest, modrmB, ImmB }, + { szBad }, + { szNot, modrmB }, + { szNeg, modrmB }, + { szMul, ALreg, modrmB }, + { szImul, ALreg, modrmB }, + { szDiv, ALreg, modrmB }, + { szIdiv, ALreg, modrmB } + }, + // GROUP_3W + { + { szTest, modrmW, ImmW }, + { szBad }, + { szNot, modrmW }, + { szNeg, modrmW }, + { szMul, AXreg, modrmW }, + { szImul, AXreg, modrmW }, + { szDiv, AXreg, modrmW }, + { szIdiv, AXreg, modrmW } + }, + // GROUP_4 + { + { szInc, modrmB }, + { szDec, modrmB }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBad } + }, + // GROUP_5 + { + { szInc, modrmW }, + { szDec, modrmW }, + { szCall, indirmodrmW }, + { szCall, indirFARmodrmW }, + { szJmp, indirmodrmW }, + { szJmp, indirFARmodrmW }, + { szPush, modrmW }, + { szBad } + }, + // GROUP_6 + { + { szSldt, modrmW }, + { szStr, modrmW }, + { szLldt, modrmW }, + { szLtr, modrmW }, + { szVerr, modrmW }, + { szVerw, modrmW }, + { szBad }, + { szBad } + }, + // GROUP_7 + { + { szSgdt, modrmW }, + { szSidt, modrmW }, + { szLgdt, modrmW }, + { szLidt, modrmW }, + { szSmsw, modrmW }, + { szBad }, + { szLmsw, modrmW }, + { szBad } + }, + // GROUP_8 + { + { szBad }, + { szBad }, + { szBad }, + { szBad }, + { szBt, modrmW, ImmB }, + { szBts, modrmW, ImmB }, + { szBtr, modrmW, ImmB }, + { szBtc, modrmW, ImmB } + } +}; + +UCHAR OpcodeSize; +BYTE *pData; +ADDR g_InstrAddr; +BOOL bBig; + +void AppendString(char *str) +{ + strcpy(g_pchOutput, (str)); + g_pchOutput+=strlen(g_pchOutput); +} + +void ExtraString(char *str) +{ + strcpy(g_pchExtra, (str)); + g_pchExtra+=strlen(g_pchExtra); +} + +#define AppendChar(c) {*g_pchOutput++ = (c);} +#define AppendNumber(d) {_ultoa((ULONG)d,g_pchOutput, 16); g_pchOutput+=strlen(g_pchOutput);} + +#define ExtraChar(c) {*g_pchExtra++ = (c);} +#define ExtraNumber(d) {_ultoa((ULONG)d,g_pchExtra, 16); g_pchExtra+=strlen(g_pchExtra);} + +int unassemble_one( + BYTE *pInstrStart, // instruction to decode (can be local buffer) + BOOL bDefaultBig, + WORD wInstrSeg, // selector of instruction + DWORD dwInstrOff, // offset of instruction + char *pchOutput, // [out] disassembled instruction + char *pchExtra // [out] extra info (ie. "es:[53]=1234") + // (can be NULL) +) { + int i; + BYTE *pInstr = pInstrStart; + struct dis *pszDecode; + + g_pchOutput = pchOutput; + g_InstrAddr.sSeg = wInstrSeg; + g_InstrAddr.sOff = dwInstrOff; + bBig = bDefaultBig; + + if (pchExtra) + *pchExtra = '\0'; + + g_pchExtra = pchExtra; + + pInstr = checkprefixes(pInstr); + + OpcodeSize = 1; + + if (*pInstr == 0x0f) { + OpcodeSize++; + pInstr++; + pszDecode = &dis386_2[*pInstr]; + } else { + pszDecode = &dis386[*pInstr]; + } + + if (prefixes & PREFIX_REPZ) + AppendString("repz "); + if (prefixes & PREFIX_REPNZ) + AppendString("repnz "); + if (prefixes & PREFIX_LOCK) + AppendString("lock "); + if ((prefixes & PREFIX_FWAIT) && ((*pInstr < 0xd8) || (*pInstr > 0xdf))) { + /* fwait not followed by floating point instruction */ + AppendString("fwait"); + return (1); + } + + pInstr++; + pData = pInstr; + if (pszDecode->szName < 0) { // found a GROUP_ or FLOAT entry... + i = (-pszDecode->szName)-1; + if (i == FLOATCODE) { + //Later: mputs("Floating point instructions NYI\n"); + return 1; + } else { + pszDecode = &dis386_groups[i][(*pInstr>>3)&7]; + } + } + + AppendString(szInstructions[pszDecode->szName]); + + if (pszDecode->iPart1) { + + AppendChar('\t'); + + i = (*(rgpfn[pszDecode->iPart1].pfn))(pInstr); + + if (pszDecode->iPart2) { + AppendString(", "); + i+=(*(rgpfn[pszDecode->iPart2].pfn))(pInstr); + if (pszDecode->iPart3) { + AppendString(", "); + i+=(*(rgpfn[pszDecode->iPart3].pfn))(pInstr); + } + } + + pInstr+=i; + } + + AppendChar('\0'); + return pInstr - pInstrStart; // return length of instruction +} + +BOOL safe_read_byte( + ADDR addr, + BYTE *pb +) { + ULONG Base; + + *pb = 0xbb; + Base = GetInfoFromSelector( addr.sSeg, g_mode, NULL ); + if (Base == (ULONG)-1 || Base == 0) { + return FALSE; + } + + Base += GetIntelBase(); + + return ReadProcessMem( hCurrentProcess, + (LPVOID)(Base+(ULONG)addr.sOff), + pb, + 1, + NULL); +} + +BOOL safe_read_short( + ADDR addr, + SHORT *ps +) { + ULONG Base; + + Base = GetInfoFromSelector( addr.sSeg, g_mode, NULL ); + if (Base == (ULONG)-1 || Base == 0) { + return FALSE; + } + + Base += GetIntelBase(); + + return ReadProcessMem( hCurrentProcess, + (LPVOID)(Base+(ULONG)addr.sOff), + ps, + 2, + NULL); +} + +BOOL safe_read_long( + ADDR addr, + LONG *pl +) { + ULONG Base; + + Base = GetInfoFromSelector( addr.sSeg, g_mode, NULL ); + if (Base == (ULONG)-1 || Base == 0) { + return FALSE; + } + + Base += GetIntelBase(); + + return ReadProcessMem( hCurrentProcess, + (LPVOID)(Base+(ULONG)addr.sOff), + pl, + 4, + NULL); +} + + +int Dreg1B(LPBYTE lpB) +{ + BYTE b = (*lpB >> 3) & 7; + + AppendString(szRegsB[b]); + + return 0; +} + +int Dreg1W(LPBYTE lpB) +{ + BYTE b = (*lpB >> 3) & 7; + + if (prefixes & PREFIX_DATA) + AppendString(szRegsD[b]); + else + AppendString(szRegsW[b]); + + return 0; +} + +int Dreg2B(LPBYTE lpB) +{ + BYTE b = *lpB & 7; + + AppendString(szRegsB[b]); + + return 0; +} + +int Dreg2W(LPBYTE lpB) +{ + BYTE b = *lpB & 7; + + if (prefixes & PREFIX_DATA) + AppendString(szRegsD[b]); + else + AppendString(szRegsW[b]); + + return 0; +} + +int DmodrmB(LPBYTE lpB) +{ + BYTE rm = *lpB & 0x07; + BYTE mod = *lpB >> 6; + unsigned short num; + int iRet; + + if (mod == 3) { + AppendPrefixes(); + AppendString(szRegsB[rm]); + return 1; + } + + iRet = 0; + AppendString("byte ptr "); + AppendPrefixes(); + AppendString(szMod[rm]); + AppendChar('+'); + + pData++; + switch (mod) { + case 0: + if (rm == 6) { + g_pchOutput-=3; // back up over the 'BP+' + num = *((UNALIGNED USHORT*)pData); + AppendNumber(num); + pData++; + iRet = 3; + } else { + num = 0; + g_pchOutput--; + iRet = 1; + } + break; + + case 1: + num = *pData; + AppendNumber(num); + pData++; + iRet = 2; + break; + + case 2: + num = *((UNALIGNED USHORT*)pData); + AppendNumber(num); + pData += 2; + iRet = 3; + break; + } + + AppendChar(']'); + + DisplayAddress(mod, rm, num, 1); + + return iRet; +} + +int DmodrmW(LPBYTE lpB) +{ + BYTE rm = *lpB & 0x07; + BYTE mod = *lpB >> 6; + unsigned short num; + int iRet; + + if (mod == 3) { + AppendPrefixes(); + if (prefixes & PREFIX_DATA) + AppendString(szRegsD[rm]); + else + AppendString(szRegsW[rm]); + return 1; + } + + if (prefixes & PREFIX_DATA) { + AppendString("dword ptr "); + AppendPrefixes(); + AppendChar('['); + AppendString(szRegsD[rm]); + } else { + AppendString("word ptr "); + AppendPrefixes(); + AppendString(szMod[rm]); + } + AppendChar('+'); + + pData++; + switch (mod) { + case 0: + if (rm == 6) { + g_pchOutput-=3; // back up over 'BP+' + num = *((UNALIGNED USHORT*)pData); + AppendNumber(num); + pData+=2; + iRet = 3; + } else { + g_pchOutput--; // else back up over '+' alone + num=0; + iRet = 1; + } + break; + + case 1: + num = *pData; + AppendNumber(num); + pData++; + iRet = 2; + break; + + case 2: + num = *((UNALIGNED USHORT *)pData); + AppendNumber(num); + pData+=2; + iRet = 3; + break; + } + + AppendChar(']'); + + if (prefixes & PREFIX_DATA) + DisplayAddress(mod, rm, num, 4); + else + DisplayAddress(mod, rm, num, 2); + + return iRet; +} + + +void DisplayAddress(int mod, int rm, int sOff, int size) +{ + ADDR addr; + + // if caller of unassemble_one() didn't want extra info, return now + if (g_pchExtra == NULL) + return; + + // no memory reference + if (mod == 3) + return; + + // display prefix + + if (prefixes & PREFIX_DS) { + ExtraChar('D'); + addr.sSeg = (USHORT)g_pThreadContext->SegDs; + } else if (prefixes & PREFIX_ES) { + ExtraChar('E'); + addr.sSeg = (USHORT)g_pThreadContext->SegEs; + } else if (prefixes & PREFIX_FS) { + ExtraChar('F'); + addr.sSeg = (USHORT)g_pThreadContext->SegFs; + } else if (prefixes & PREFIX_GS) { + ExtraChar('G'); + addr.sSeg = (USHORT)g_pThreadContext->SegGs; + } else if (prefixes & PREFIX_CS) { + ExtraChar('C'); + addr.sSeg = (USHORT)g_pThreadContext->SegCs; + } else if ( (prefixes & PREFIX_SS) || rm==2 || rm == 3) { + ExtraChar('S'); + addr.sSeg = (USHORT)g_pThreadContext->SegSs; + } else if (rm == 6 && mod != 0) { + ExtraChar('S'); + addr.sSeg = (USHORT)g_pThreadContext->SegSs; + } else { + ExtraChar('D'); + addr.sSeg = (USHORT)g_pThreadContext->SegDs; + } + + ExtraString("S:["); + + switch (rm) { + case 0: + addr.sOff = (USHORT)(g_pThreadContext->Ebx + g_pThreadContext->Esi); + break; + + case 1: + addr.sOff = (USHORT)(g_pThreadContext->Ebx + g_pThreadContext->Edi); + break; + + case 2: + addr.sOff = (USHORT)(g_pThreadContext->Ebp + g_pThreadContext->Esi); + break; + + case 3: + addr.sOff = (USHORT)(g_pThreadContext->Ebp + g_pThreadContext->Edi); + break; + + case 4: + addr.sOff = (USHORT)g_pThreadContext->Esi; + break; + + case 5: + addr.sOff = (USHORT)g_pThreadContext->Edi; + break; + + case 6: + if (mod == 0) + addr.sOff = 0; + else + addr.sOff = (USHORT)g_pThreadContext->Ebp; + break; + + default: + addr.sOff = (USHORT)g_pThreadContext->Ebx; + + } + + addr.sOff += sOff; + ExtraNumber(addr.sOff); + ExtraString("]="); + if (size == 2) { + SHORT s; + if (safe_read_short(addr, &s)) { + ExtraNumber( s ); + } else { + ExtraString("????"); + } + } else if (size == 1) { + BYTE b; + if (safe_read_byte(addr, &b)) { + ExtraNumber( b ); + } else { + ExtraString("??"); + } + } else if (size == 4) { + LONG l; + if (safe_read_long(addr, &l)) { + ExtraNumber( l ); + } else { + ExtraString("????????"); + } + } else { + ExtraString("Unknown size!"); + } +} + + +int DALreg(LPBYTE lpB) +{ + AppendString("al"); + + return 0; +} + +int DAHreg(LPBYTE lpB) +{ + AppendString("ah"); + + return 0; +} + +int DBLreg(LPBYTE lpB) +{ + AppendString("bl"); + + return 0; +} + +int DBHreg(LPBYTE lpB) +{ + AppendString("bh"); + + return 0; +} + +int DCLreg(LPBYTE lpB) +{ + AppendString("cl"); + + return 0; +} + +int DCHreg(LPBYTE lpB) +{ + AppendString("ch"); + + return 0; +} + +int DDLreg(LPBYTE lpB) +{ + AppendString("dl"); + + return 0; +} + +int DDHreg(LPBYTE lpB) +{ + AppendString("dh"); + + return 0; +} + +int DAXreg(LPBYTE lpB) +{ + if ((prefixes & PREFIX_DATA) ^ bBig) + AppendChar('e'); + + AppendString("ax"); + + return 0; +} + +int DBXreg(LPBYTE lpB) +{ + if ((prefixes & PREFIX_DATA) ^ bBig) + AppendChar('e'); + + AppendString("bx"); + + return 0; +} + +int DCXreg(LPBYTE lpB) +{ + if ((prefixes & PREFIX_DATA) ^ bBig) + AppendChar('e'); + + AppendString("cx"); + + return 0; +} + +int DDXreg(LPBYTE lpB) +{ + if ((prefixes & PREFIX_DATA) ^ bBig) + AppendChar('e'); + + AppendString("dx"); + + return 0; +} + +int DBPreg(LPBYTE lpB) +{ + if ((prefixes & PREFIX_DATA) ^ bBig) + AppendChar('e'); + + AppendString("bp"); + + return 0; +} + +int DSPreg(LPBYTE lpB) +{ + if ((prefixes & PREFIX_DATA) ^ bBig) + AppendChar('e'); + + AppendString("sp"); + + return 0; +} + +int DSIreg(LPBYTE lpB) +{ + if ((prefixes & PREFIX_DATA) ^ bBig) + AppendChar('e'); + + AppendString("si"); + + return 0; +} + +int DDIreg(LPBYTE lpB) +{ + if ((prefixes & PREFIX_DATA) ^ bBig) + AppendChar('e'); + + AppendString("di"); + + return 0; +} + +int DCSreg(LPBYTE lpB) +{ + AppendString("cs"); + + return 0; +} + +int DDSreg(LPBYTE lpB) +{ + AppendString("ds"); + + return 0; +} + +int DSSreg(LPBYTE lpB) +{ + AppendString("es"); + + return 0; +} + +int DESreg(LPBYTE lpB) +{ + AppendString("es"); + + return 0; +} + +int DFSreg(LPBYTE lpB) +{ + AppendString("fs"); + + return 0; +} + +int DGSreg(LPBYTE lpB) +{ + AppendString("gs"); + + return 0; +} + +int DImmB(LPBYTE lpB) +{ + AppendNumber(*pData); + pData++; + + return 1; +} + +int DImmBEnter(LPBYTE lpB) +{ + AppendNumber(*pData); + pData++; + + return 1; +} + +int DImmBS(LPBYTE lpB) // sign-extend 8-bit value to 16 bits +{ + int i = (signed char)*(pData); + + AppendNumber(i); + pData++; + + return 1; +} + +int DImmW(LPBYTE lpB) +{ + if ((prefixes & PREFIX_DATA) ^ bBig) { + + AppendNumber( *((UNALIGNED ULONG*)pData) ); + pData+=4; + return 4; + + } else { + + AppendNumber( *((UNALIGNED USHORT*)pData) ); + pData+=2; + return 2; + + } +} + +int DImmW1(LPBYTE lpB) +{ + AppendNumber( *((UNALIGNED SHORT*)(pData)) ); + pData++; + + return 2; +} + +int DjmpB(LPBYTE lpB) +{ + USHORT wDest = g_InstrAddr.sOff + (UNALIGNED USHORT)*lpB + OpcodeSize + 1; + + AppendNumber(wDest); + + return 1; +} + +int DjmpW(LPBYTE lpB) +{ + USHORT wDest = g_InstrAddr.sOff + (USHORT)*((UNALIGNED USHORT *)lpB) + OpcodeSize + 2; + + AppendNumber(wDest); + + return 2; +} + +int DregSeg(LPBYTE lpB) +{ + BYTE b = (*lpB >> 3) & 7; + + AppendString(szRegsSeg[b]); + + return 0; +} + + +int DmemB(LPBYTE lpB) +{ + ADDR addr; + + addr.sOff = *(lpB+1); + + AppendChar('['); + AppendNumber( addr.sOff ); + AppendChar(']'); + + if (g_pchExtra) { + BYTE b; + + if (prefixes & PREFIX_DS) { + ExtraChar('D'); + addr.sSeg = (USHORT)g_pThreadContext->SegDs; + } else if (prefixes & PREFIX_ES) { + ExtraChar('E'); + addr.sSeg = (USHORT)g_pThreadContext->SegEs; + } else if (prefixes & PREFIX_FS) { + ExtraChar('F'); + addr.sSeg = (USHORT)g_pThreadContext->SegFs; + } else if (prefixes & PREFIX_GS) { + ExtraChar('G'); + addr.sSeg = (USHORT)g_pThreadContext->SegGs; + } else if (prefixes & PREFIX_CS) { + ExtraChar('C'); + addr.sSeg = (USHORT)g_pThreadContext->SegCs; + } else if (prefixes & PREFIX_SS) { + ExtraChar('S'); + addr.sSeg = (USHORT)g_pThreadContext->SegSs; + } else { + ExtraChar('D'); + addr.sSeg = (USHORT)g_pThreadContext->SegDs; + } + + ExtraString("S:["); + ExtraNumber( addr.sOff ); + ExtraString("]="); + if (safe_read_byte(addr, &b)) { + ExtraNumber( b ); + } else { + ExtraString("??"); + } + + } + + return 1; +} + +int DmemB1(LPBYTE lpB) +{ + AppendNumber( *lpB ); + + return 1; +} + +int DmemW(LPBYTE lpB) +{ + int i; + ADDR addr; + + addr.sOff = *(lpB+1); + + AppendChar('['); + if (prefixes & PREFIX_DATA) { + AppendNumber( *((UNALIGNED long*)lpB) ); + i=4; + } else { + addr.sOff = *((UNALIGNED short *)lpB); + AppendNumber( addr.sOff ); + i=2; + } + AppendChar(']'); + + if (g_pchExtra) { + + if (prefixes & PREFIX_DS) { + ExtraChar('D'); + addr.sSeg = (USHORT)g_pThreadContext->SegDs; + } else if (prefixes & PREFIX_ES) { + ExtraChar('E'); + addr.sSeg = (USHORT)g_pThreadContext->SegEs; + } else if (prefixes & PREFIX_FS) { + ExtraChar('F'); + addr.sSeg = (USHORT)g_pThreadContext->SegFs; + } else if (prefixes & PREFIX_GS) { + ExtraChar('G'); + addr.sSeg = (USHORT)g_pThreadContext->SegGs; + } else if (prefixes & PREFIX_CS) { + ExtraChar('C'); + addr.sSeg = (USHORT)g_pThreadContext->SegCs; + } else if (prefixes & PREFIX_SS) { + ExtraChar('S'); + addr.sSeg = (USHORT)g_pThreadContext->SegSs; + } else { + ExtraChar('D'); + addr.sSeg = (USHORT)g_pThreadContext->SegDs; + } + + ExtraString("S:["); + ExtraNumber( addr.sOff ); + ExtraString("]="); + if (i == 2) { + SHORT s; + if (safe_read_short(addr, &s)) { + ExtraNumber( s ); + } else { + ExtraString( "????" ); + } + } else { + LONG l; + + if (safe_read_long(addr, &l)) { + ExtraNumber( l ); + } else { + ExtraString( "????????" ); + } + } + } + + return i; +} + + +int DmemD(LPBYTE lpB) +{ + int i; + + if (prefixes & PREFIX_DATA) { + AppendNumber( *(((UNALIGNED SHORT*)lpB)+2) ); + AppendChar(':'); + AppendNumber( *((UNALIGNED long*)lpB) ); + i=6; + } else { + USHORT sel, off; + + sel = *(((UNALIGNED SHORT*)lpB)+1); + off = *((UNALIGNED SHORT*)lpB); + AppendNumber( sel ); + AppendChar(':'); + AppendNumber( off ); + i=4; + + if (g_pchExtra) { + char sym_text[1000]; + LONG dist; + + // if the exact symbol name was found, print it + if (FindSymbol( sel, + off, + sym_text, + &dist, + BEFORE, + g_mode)) { + ExtraString("= "); + ExtraString(sym_text); + if (dist) { + ExtraString(" + "); + ExtraNumber( dist ); + } + } + } + + } + + return i; +} + +int DindirmodrmW(LPBYTE lpB) +{ + int i; + + AppendString("FAR PTR "); + i = DmodrmW(lpB); + AppendChar(']'); + + return i; +} + + +int DindirFARmodrmW(LPBYTE lpB) +{ + int i; + + AppendString("FAR PTR "); + i = DmodrmW(lpB); + AppendChar(']'); + + return i; +} + + +int DeeeControl(LPBYTE lpB) +{ + AppendChar('c'); + AppendChar('r'); + AppendChar('0'+ ((*lpB >> 3) & 7) ); + + return 1; +} + +int DeeeDebug(LPBYTE lpB) +{ + AppendChar('d'); + AppendChar('r'); + AppendChar('0'+ ((*lpB >> 3) & 7) ); + + return 1; +} + +int DeeeTest(LPBYTE lpB) +{ + AppendChar('t'); + AppendChar('r'); + AppendChar('0'+ ((*lpB >> 3) & 7) ); + + return 1; +} + + +LPBYTE checkprefixes(LPBYTE lpB) +{ + prefixes = 0; + + for (;;) { + + switch (*lpB) { + case 0xf3: + prefixes |= PREFIX_REPZ; + break; + case 0xf2: + prefixes |= PREFIX_REPNZ; + break; + case 0xf0: + prefixes |= PREFIX_LOCK; + break; + case 0x2e: + prefixes |= PREFIX_CS; + break; + case 0x36: + prefixes |= PREFIX_SS; + break; + case 0x3e: + prefixes |= PREFIX_DS; + break; + case 0x26: + prefixes |= PREFIX_ES; + break; + case 0x64: + prefixes |= PREFIX_FS; + break; + case 0x65: + prefixes |= PREFIX_GS; + break; + case 0x66: + prefixes |= PREFIX_DATA; + break; + case 0x67: + prefixes |= PREFIX_ADR; + break; + case 0x9b: + prefixes |= PREFIX_FWAIT; + break; + default: + return lpB; + } + lpB++; + } +} + + +void AppendPrefixes(void) +{ + if (prefixes & PREFIX_CS) + AppendString("cs:"); + if (prefixes & PREFIX_DS) + AppendString("ds:"); + if (prefixes & PREFIX_SS) + AppendString("ss:"); + if (prefixes & PREFIX_ES) + AppendString("es:"); + if (prefixes & PREFIX_FS) + AppendString("fs:"); + if (prefixes & PREFIX_GS) + AppendString("gs:"); +} diff --git a/private/mvdm/bde/makefile b/private/mvdm/bde/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/mvdm/bde/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/mvdm/bde/precomp.h b/private/mvdm/bde/precomp.h new file mode 100644 index 000000000..f6bb740f7 --- /dev/null +++ b/private/mvdm/bde/precomp.h @@ -0,0 +1,17 @@ +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> +#include <windows.h> +#define NOEXTAPI +#include <wdbgexts.h> +#include <ntsdexts.h> +#include <string.h> + +#if defined (i386) +#include <vdm.h> +#endif + +#include <vdmdbg.h> +#include <tdb16.h> +#include "..\wow32\wow32.h" +#include <bde.h> diff --git a/private/mvdm/bde/sources b/private/mvdm/bde/sources new file mode 100644 index 000000000..79a6dae0c --- /dev/null +++ b/private/mvdm/bde/sources @@ -0,0 +1,116 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1990 + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + + +# +# The MAJORCOMP and MINORCOMP variables are defined +# so that $(MAJORCOMP)$(MINORCOMP)filename can be used in +# cross compiling to provide unique filenames in a flat namespace. +# + +MAJORCOMP=ntsd +MINORCOMP=ntsdexts + +# +# The TARGETNAME variable is defined by the developer. It is the name of +# the target (component) that is being built by this makefile. It +# should NOT include any path or file extension information. +# + +TARGETNAME=bde + +DLLBASE=0x79000000 + +# +# The TARGETPATH and TARGETTYPE variables are defined by the developer. +# The first specifies where the target is to be build. The second specifies +# the type of target (either PROGRAM, DYNLINK, LIBRARY, UMAPPL_NOLIB or +# BOOTPGM). UMAPPL_NOLIB is used when you're only building user-mode +# apps and don't need to build a library. +# + +TARGETPATH=obj + +# Pick one of the following and delete the others +TARGETTYPE=DYNLINK + +# +# The TARGETLIBS specifies additional libraries to link with you target +# image. Each library path specification should contain an asterisk (*) +# where the machine specific subdirectory name should go. +# + +TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\kernel32.lib \ + $(BASEDIR)\public\sdk\lib\*\user32.lib + +# +# The INCLUDES variable specifies any include paths that are specific to +# this source directory. Separate multiple directory paths with single +# semicolons. Relative path specifications are okay. +# + +INCLUDES=..\inc;..\..\inc;..\..\windows\inc + + +# +# The SOURCES variable is defined by the developer. It is a list of all the +# source files for this component. Each source file should be on a separate +# line using the line continuation character. This will minimize merge +# conflicts if two developers adding source files to the same component. +# + +SOURCES=bdecmds.c \ + bdeheap.c \ + bdemisc.c \ + bdestack.c \ + bdesym.c \ + bdeutil.c \ + data.c \ + disasm.c + + +# +# Next specify options for the compiler. +# + +C_DEFINES=-DWIN32 -DNT + + +# +# Next specify a kernel mode test (valid only in NTOS tree) +# + +NTTEST= + +# +# Next specify one or more user mode test programs and their type +# UMTEST is used for optional test programs. UMAPPL is used for +# programs that always get built when the directory is built. +# + +# + +PRECOMPILED_INCLUDE=precomp.h +PRECOMPILED_PCH=precomp.pch +PRECOMPILED_OBJ=precomp.obj |