summaryrefslogtreecommitdiffstats
path: root/private/mvdm/bde
diff options
context:
space:
mode:
Diffstat (limited to 'private/mvdm/bde')
-rw-r--r--private/mvdm/bde/bde.def19
-rw-r--r--private/mvdm/bde/bde.h382
-rw-r--r--private/mvdm/bde/bdecmds.c569
-rw-r--r--private/mvdm/bde/bdeheap.c311
-rw-r--r--private/mvdm/bde/bdemisc.c372
-rw-r--r--private/mvdm/bde/bdestack.c653
-rw-r--r--private/mvdm/bde/bdesym.c887
-rw-r--r--private/mvdm/bde/bdeutil.c614
-rw-r--r--private/mvdm/bde/data.c43
-rw-r--r--private/mvdm/bde/disasm.c2380
-rw-r--r--private/mvdm/bde/makefile6
-rw-r--r--private/mvdm/bde/precomp.h17
-rw-r--r--private/mvdm/bde/sources116
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