From 5a6adb4f13abeafcc842e880384a16b05b797ffb Mon Sep 17 00:00:00 2001 From: Casper Hornstrup Date: Wed, 23 Jan 2002 23:39:26 +0000 Subject: [PATCH] Added GNU Debugger stub for remote debugging. Fixed bugs in NtQueryDirectoryObject. Added static library target. svn path=/trunk/; revision=2546 --- reactos/.gdbinit | 11 +- reactos/config | 7 + reactos/gdb.ini | 4 + reactos/hal/hal/hal.c | 18 +- reactos/hal/hal/hal.def | 2 + reactos/hal/hal/hal.edf | 2 + reactos/hal/halx86/kdbg.c | 55 +- reactos/include/ddk/kdfuncs.h | 14 +- reactos/include/ddk/ketypes.h | 2 +- reactos/include/ntos/except.h | 2 +- reactos/include/ntos/types.h | 25 +- reactos/ntoskrnl/Makefile | 5 +- reactos/ntoskrnl/cm/regfile.c | 3 +- reactos/ntoskrnl/include/internal/kd.h | 34 +- reactos/ntoskrnl/include/internal/ldr.h | 2 + reactos/ntoskrnl/kd/gdbstub.c | 1325 +++++++++++++++++++++++ reactos/ntoskrnl/kd/kdebug.c | 115 +- reactos/ntoskrnl/ke/catch.c | 36 +- reactos/ntoskrnl/ke/i386/exp.c | 62 +- reactos/ntoskrnl/ke/i386/irq.c | 44 +- reactos/ntoskrnl/ke/main.c | 26 +- reactos/ntoskrnl/ldr/loader.c | 20 +- reactos/ntoskrnl/mm/mm.c | 3 +- reactos/ntoskrnl/ob/dirobj.c | 40 +- reactos/tools/helper.mk | 24 +- 25 files changed, 1734 insertions(+), 147 deletions(-) create mode 100644 reactos/gdb.ini create mode 100644 reactos/ntoskrnl/kd/gdbstub.c diff --git a/reactos/.gdbinit b/reactos/.gdbinit index ab852f9298b..8a322d4a376 100644 --- a/reactos/.gdbinit +++ b/reactos/.gdbinit @@ -1,7 +1,4 @@ -file ntoskrnl/ntoskrnl.nostrip.exe -#add-symbol-file lib/ntdll/ntdll.dll 0x77f61000 -#add-symbol-file lib/kernel32/kernel32.dll 0x77f01000 -#add-symbol-file apps/exp/exp.exe 0x401000 -#add-symbol-file subsys/csrss/csrss.exe 0x401000 -#add-symbol-file subsys/smss/smss.exe 0x401000 -break exp.c:254 +directory /mnt/windows/CvsHome/reactos/ntoskrnl +symbol-file ntoskrnl/ntoskrnl.nostrip.exe -mapped +set remotebaud 115200 +target remote com2 diff --git a/reactos/config b/reactos/config index 1b36a169c19..09501359fc3 100644 --- a/reactos/config +++ b/reactos/config @@ -10,6 +10,13 @@ ARCH := i386 # KDBG := 0 +# +# Whether to dump debug prints to the serial port +# If this is disabled and KDBG is enabled the GDB +# stub is used +# +SERDUMP := 0 + # # Whether to compile for debugging # diff --git a/reactos/gdb.ini b/reactos/gdb.ini new file mode 100644 index 00000000000..8a322d4a376 --- /dev/null +++ b/reactos/gdb.ini @@ -0,0 +1,4 @@ +directory /mnt/windows/CvsHome/reactos/ntoskrnl +symbol-file ntoskrnl/ntoskrnl.nostrip.exe -mapped +set remotebaud 115200 +target remote com2 diff --git a/reactos/hal/hal/hal.c b/reactos/hal/hal/hal.c index d1d107cf8b2..eb487bbe460 100644 --- a/reactos/hal/hal/hal.c +++ b/reactos/hal/hal/hal.c @@ -1,4 +1,4 @@ -/* $Id: hal.c,v 1.1 2001/08/21 20:18:26 chorns Exp $ +/* $Id: hal.c,v 1.2 2002/01/23 23:39:24 chorns Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -645,6 +645,22 @@ KdPortSave(VOID) } +BOOLEAN +STDCALL +KdPortDisableInterrupts() +{ + UNIMPLEMENTED; +} + + +BOOLEAN +STDCALL +KdPortEnableInterrupts() +{ + UNIMPLEMENTED; +} + + VOID STDCALL KeAcquireSpinLock( diff --git a/reactos/hal/hal/hal.def b/reactos/hal/hal/hal.def index 4a2109327c3..6b2b3a8feca 100644 --- a/reactos/hal/hal/hal.def +++ b/reactos/hal/hal/hal.def @@ -65,6 +65,8 @@ KdPortPollByte@4 KdPortPutByte@4 KdPortRestore@0 KdPortSave@0 +KdPortDisableInterrupts@0 +KdPortEnableInterrupts@0 KeAcquireSpinLock@8 @KeAcquireSpinLockRaiseToSynch@4 KeFlushWriteBuffer@0 diff --git a/reactos/hal/hal/hal.edf b/reactos/hal/hal/hal.edf index 1a7a19de470..9257549588d 100644 --- a/reactos/hal/hal/hal.edf +++ b/reactos/hal/hal/hal.edf @@ -65,6 +65,8 @@ KdPortPollByte=KdPortPollByte@4 KdPortPutByte=KdPortPutByte@4 KdPortRestore=KdPortRestore@0 KdPortSave=KdPortSave@0 +KdPortDisableInterrupts=KdPortDisableInterrupts@0 +KdPortEnableInterrupts=KdPortEnableInterrupts@0 KeAcquireSpinLock=KeAcquireSpinLock@8 KeAcquireSpinLockRaiseToSynch=@KeAcquireSpinLockRaiseToSynch@4 KeFlushWriteBuffer=KeFlushWriteBuffer@0 diff --git a/reactos/hal/halx86/kdbg.c b/reactos/hal/halx86/kdbg.c index 1f3ea8b67bd..ba0b552234a 100644 --- a/reactos/hal/halx86/kdbg.c +++ b/reactos/hal/halx86/kdbg.c @@ -1,4 +1,4 @@ -/* $Id: kdbg.c,v 1.2 2001/08/27 01:23:50 ekohl Exp $ +/* $Id: kdbg.c,v 1.3 2002/01/23 23:39:24 chorns Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -27,6 +27,11 @@ #define SER_THR(x) ((x)+0) #define SER_DLL(x) ((x)+0) #define SER_IER(x) ((x)+1) +#define SR_IER_ERDA 0x01 +#define SR_IER_ETHRE 0x02 +#define SR_IER_ERLSI 0x04 +#define SR_IER_EMS 0x08 +#define SR_IER_ALL 0x0F #define SER_DLM(x) ((x)+1) #define SER_IIR(x) ((x)+2) #define SER_LCR(x) ((x)+3) @@ -46,6 +51,9 @@ #define SER_MCR(x) ((x)+4) #define SR_MCR_DTR 0x01 #define SR_MCR_RTS 0x02 +#define SR_MCR_OUT1 0x04 +#define SR_MCR_OUT2 0x08 +#define SR_MCR_LOOP 0x10 #define SER_LSR(x) ((x)+5) #define SR_LSR_DR 0x01 #define SR_LSR_TBE 0x20 @@ -331,4 +339,49 @@ KdPortSave ( } +/* HAL.KdPortDisableInterrupts */ +BOOLEAN +STDCALL +KdPortDisableInterrupts() +{ + UCHAR ch; + + if (PortInitialized == FALSE) + return FALSE; + + ch = READ_PORT_UCHAR (SER_MCR (PortBase)); + ch &= (~(SR_MCR_OUT1 | SR_MCR_OUT2)); + WRITE_PORT_UCHAR (SER_MCR (PortBase), ch); + + ch = READ_PORT_UCHAR (SER_IER (PortBase)); + ch &= (~SR_IER_ALL); + WRITE_PORT_UCHAR (SER_IER (PortBase), ch); + + return TRUE; +} + + +/* HAL.KdPortEnableInterrupts */ +BOOLEAN +STDCALL +KdPortEnableInterrupts() +{ + UCHAR ch; + + if (PortInitialized == FALSE) + return FALSE; + + ch = READ_PORT_UCHAR (SER_IER (PortBase)); + ch &= (~SR_IER_ALL); + ch |= SR_IER_ERDA; + WRITE_PORT_UCHAR (SER_IER (PortBase), ch); + + ch = READ_PORT_UCHAR (SER_MCR (PortBase)); + ch &= (~SR_MCR_LOOP); + ch |= (SR_MCR_OUT1 | SR_MCR_OUT2); + WRITE_PORT_UCHAR (SER_MCR (PortBase), ch); + + return TRUE; +} + /* EOF */ diff --git a/reactos/include/ddk/kdfuncs.h b/reactos/include/ddk/kdfuncs.h index 6af0db74b72..057ba4df47a 100644 --- a/reactos/include/ddk/kdfuncs.h +++ b/reactos/include/ddk/kdfuncs.h @@ -1,6 +1,6 @@ #ifndef __INCLUDE_DDK_KDFUNCS_H #define __INCLUDE_DDK_KDFUNCS_H -/* $Id: kdfuncs.h,v 1.4 2001/08/21 20:13:05 chorns Exp $ */ +/* $Id: kdfuncs.h,v 1.5 2002/01/23 23:39:24 chorns Exp $ */ /* --- NTOSKRNL.EXE --- */ #if defined(__NTOSKRNL__) @@ -50,4 +50,16 @@ KdPortSave ( VOID ); +BOOLEAN +STDCALL +KdPortDisableInterrupts( + VOID + ); + +BOOLEAN +STDCALL +KdPortEnableInterrupts( + VOID + ); + #endif /* __INCLUDE_DDK_KDFUNCS_H */ diff --git a/reactos/include/ddk/ketypes.h b/reactos/include/ddk/ketypes.h index 32ab700b17a..3fc07fa42d0 100644 --- a/reactos/include/ddk/ketypes.h +++ b/reactos/include/ddk/ketypes.h @@ -111,7 +111,7 @@ typedef struct _DISPATCHER_HEADER UCHAR Inserted; LONG SignalState; LIST_ENTRY WaitListHead; -} __attribute__((packed)) DISPATCHER_HEADER; +} __attribute__((packed)) DISPATCHER_HEADER, *PDISPATCHER_HEADER; typedef struct _KQUEUE diff --git a/reactos/include/ntos/except.h b/reactos/include/ntos/except.h index c7d24b7a633..c34b62df11f 100644 --- a/reactos/include/ntos/except.h +++ b/reactos/include/ntos/except.h @@ -28,7 +28,7 @@ struct _EXCEPTION_REGISTRATION; typedef EXCEPTION_DISPOSITION CDECL (*PEXCEPTION_HANDLER)( struct _EXCEPTION_RECORD* ExceptionRecord, struct _EXCEPTION_REGISTRATION* ExceptionRegistration, - struct _CONTEXT* Context, + PCONTEXT Context, PVOID DispatcherContext); diff --git a/reactos/include/ntos/types.h b/reactos/include/ntos/types.h index b0411ab4b4e..ebdf60f97ba 100644 --- a/reactos/include/ntos/types.h +++ b/reactos/include/ntos/types.h @@ -226,8 +226,6 @@ typedef unsigned short *PWCHAR; #endif -#ifdef __i386__ - typedef struct _FLOATING_SAVE_AREA { DWORD ControlWord; DWORD StatusWord; @@ -240,7 +238,7 @@ typedef struct _FLOATING_SAVE_AREA { DWORD Cr0NpxState; } FLOATING_SAVE_AREA; -typedef struct _CONTEXT { +typedef struct _CONTEXT_X86 { DWORD ContextFlags; DWORD Dr0; @@ -270,11 +268,9 @@ typedef struct _CONTEXT { DWORD EFlags; DWORD Esp; DWORD SegSs; -} CONTEXT, *PCONTEXT, *LPCONTEXT; +} CONTEXT_X86, *PCONTEXT_X86, *LPCONTEXT_X86; -#else /* __ppc__ */ - -typedef struct +typedef struct _CONTEXT_PPC { /* Floating point registers returned when CONTEXT_FLOATING_POINT is set */ double Fpr0; @@ -367,7 +363,20 @@ typedef struct DWORD Dr5; /* Breakpoint Register 6 */ DWORD Dr6; /* Debug Status Register */ DWORD Dr7; /* Debug Control Register */ -} CONTEXT, *PCONTEXT, *LPCONTEXT; +} CONTEXT_PPC, *PCONTEXT_PPC, *LPCONTEXT_PPC; + +#ifdef __i386__ + +typedef CONTEXT_X86 CONTEXT; +typedef PCONTEXT_X86 PCONTEXT; +typedef LPCONTEXT_X86 LPCONTEXT; + +#else /* __ppc__ */ + +typedef CONTEXT_PPC CONTEXT; +typedef PCONTEXT_PPC PCONTEXT; +typedef LPCONTEXT_PPC LPCONTEXT; + #endif typedef HANDLE *PHANDLE; diff --git a/reactos/ntoskrnl/Makefile b/reactos/ntoskrnl/Makefile index 583d45fa2a7..a5f7e57ebfe 100644 --- a/reactos/ntoskrnl/Makefile +++ b/reactos/ntoskrnl/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.64 2002/01/21 22:34:36 hbirr Exp $ +# $Id: Makefile,v 1.65 2002/01/23 23:39:24 chorns Exp $ # # ReactOS Operating System # @@ -321,7 +321,8 @@ OBJECTS_CC = \ OBJECTS_KD = \ kd/kdebug.o \ kd/service.o \ - kd/dlog.o + kd/dlog.o \ + kd/gdbstub.o DEP_OBJECTS := $(OBJECTS_NT) $(OBJECTS_MM) $(OBJECTS_ARCH) \ $(OBJECTS_IO) $(OBJECTS_KE) $(OBJECTS_OB) \ diff --git a/reactos/ntoskrnl/cm/regfile.c b/reactos/ntoskrnl/cm/regfile.c index ad4bebff490..02be4bc45da 100644 --- a/reactos/ntoskrnl/cm/regfile.c +++ b/reactos/ntoskrnl/cm/regfile.c @@ -739,7 +739,6 @@ CmiAddValueToKey(IN PREGISTRY_FILE RegistryFile, >= ((LONG)(ValueListBlock->SubBlockSize-4))/(LONG)sizeof(BLOCK_OFFSET)) // >= -(ValueListBlock->SubBlockSize-4)/sizeof(BLOCK_OFFSET)) { - DPRINT1("\n"); Status = CmiAllocateBlock(RegistryFile, (PVOID) &NewValueListBlock, sizeof(BLOCK_OFFSET) * @@ -760,7 +759,7 @@ CmiAddValueToKey(IN PREGISTRY_FILE RegistryFile, KeyBlock->ValuesOffset = VLBOffset; ValueListBlock = NewValueListBlock; } - DPRINT1("KeyBlock->NumberOfValues %d, ValueListBlock->SubBlockSize %d (%d %x)\n", + DPRINT("KeyBlock->NumberOfValues %d, ValueListBlock->SubBlockSize %d (%d %x)\n", KeyBlock->NumberOfValues, ValueListBlock->SubBlockSize, -(ValueListBlock->SubBlockSize-4)/sizeof(BLOCK_OFFSET), -(ValueListBlock->SubBlockSize-4)/sizeof(BLOCK_OFFSET)); diff --git a/reactos/ntoskrnl/include/internal/kd.h b/reactos/ntoskrnl/include/internal/kd.h index d27c240f89a..54b0ea1d31f 100644 --- a/reactos/ntoskrnl/include/internal/kd.h +++ b/reactos/ntoskrnl/include/internal/kd.h @@ -1,4 +1,4 @@ -/* $Id: kd.h,v 1.3 2001/02/10 22:51:08 dwelch Exp $ +/* $Id: kd.h,v 1.4 2002/01/23 23:39:25 chorns Exp $ * * kernel debugger prototypes */ @@ -6,6 +6,15 @@ #ifndef __INCLUDE_INTERNAL_KERNEL_DEBUGGER_H #define __INCLUDE_INTERNAL_KERNEL_DEBUGGER_H +#include + +typedef enum _KD_CONTINUE_TYPE +{ + kdContinue = 0, + kdDoNotHandleException, + kdHandleException +} KD_CONTINUE_TYPE; + ULONG KdpPrintString (PANSI_STRING String); @@ -16,4 +25,27 @@ DebugLogInit(VOID); VOID DebugLogInit2(VOID); +VOID +KdInit1(); + +VOID +KdInit2(); + +VOID +KdPutChar(UCHAR Value); + +UCHAR +KdGetChar(); + +VOID +KdGdbStubInit(); + +VOID +KdDebugPrint (LPSTR Message); + +KD_CONTINUE_TYPE +KdEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord, + PCONTEXT Context, + PKTRAP_FRAME TrapFrame); + #endif /* __INCLUDE_INTERNAL_KERNEL_DEBUGGER_H */ diff --git a/reactos/ntoskrnl/include/internal/ldr.h b/reactos/ntoskrnl/include/internal/ldr.h index 8dec2b69318..4396f629c33 100644 --- a/reactos/ntoskrnl/include/internal/ldr.h +++ b/reactos/ntoskrnl/include/internal/ldr.h @@ -100,6 +100,8 @@ NTSTATUS LdrFindModuleObject( PUNICODE_STRING ModuleName, PMODULE_OBJECT *ModuleObject); +NTSTATUS LdrpOpenModuleDirectory(PHANDLE Handle); + extern ULONG_PTR LdrHalBase; #endif /* __INCLUDE_INTERNAL_LDR_H */ diff --git a/reactos/ntoskrnl/kd/gdbstub.c b/reactos/ntoskrnl/kd/gdbstub.c new file mode 100644 index 00000000000..34ada3a20f3 --- /dev/null +++ b/reactos/ntoskrnl/kd/gdbstub.c @@ -0,0 +1,1325 @@ +/**************************************************************************** + + THIS SOFTWARE IS NOT COPYRIGHTED + + HP offers the following for use in the public domain. HP makes no + warranty with regard to the software or it's performance and the + user accepts the software "AS IS" with all faults. + + HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD + TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +****************************************************************************/ + +/**************************************************************************** + * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $ + * + * Module name: remcom.c $ + * Revision: 1.34 $ + * Date: 91/03/09 12:29:49 $ + * Contributor: Lake Stevens Instrument Division$ + * + * Description: low level support for gdb debugger. $ + * + * Considerations: only works on target hardware $ + * + * Written by: Glenn Engel $ + * ModuleState: Experimental $ + * + * NOTES: See Below $ + * + * Modified for 386 by Jim Kingdon, Cygnus Support. + * Modified for ReactOS by Casper S. Hornstrup + * + * To enable debugger support, two things need to happen. One, setting + * up a routine so that it is in the exception path, is necessary in order + * to allow any breakpoints or error conditions to be properly intercepted + * and reported to gdb. + * Two, a breakpoint needs to be generated to begin communication. + * + * Because gdb will sometimes write to the stack area to execute function + * calls, this program cannot rely on using the supervisor stack so it + * uses it's own stack area. + * + ************* + * + * The following gdb commands are supported: + * + * command function Return value + * + * g return the value of the CPU Registers hex data or ENN + * G set the value of the CPU Registers OK or ENN + * + * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN + * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN + * + * c Resume at current address SNN ( signal NN) + * cAA..AA Continue at address AA..AA SNN + * + * s Step one instruction SNN + * sAA..AA Step one instruction from AA..AA SNN + * + * k kill + * + * ? What was the last sigval ? SNN (signal NN) + * + * All commands and responses are sent with a packet which includes a + * Checksum. A packet consists of + * + * $#. + * + * where + * :: + * :: < two hex digits computed as modulo 256 sum of > + * + * When a packet is received, it is first acknowledged with either '+' or '-'. + * '+' indicates a successful transfer. '-' indicates a failed transfer. + * + * Example: + * + * Host: Reply: + * $m0,10#2a +$00010203040506070809101112131415#42 + * + ****************************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +extern LIST_ENTRY PiThreadListHead; + + +/************************************************************************/ +/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ +/* at least NUMREGBYTES*2 are needed for register packets */ +#define BUFMAX 1000 + +static BOOLEAN GspInitialized; /* boolean flag. TRUE means we've been initialized */ +static PKINTERRUPT GspInterrupt; + +static BOOLEAN GspRemoteDebug; + +static CONST CHAR HexChars[]="0123456789abcdef"; + +static PETHREAD GspRunThread; /* NULL means run all threads */ +static PETHREAD GspDbgThread; +static PETHREAD GspEnumThread; + +/* Number of Registers. */ +#define NUMREGS 16 + +enum REGISTER_NAMES +{ + EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, + PC /* also known as eip */, + PS /* also known as eflags */, + CS, SS, DS, ES, FS, GS +}; + +typedef struct _CPU_REGISTER +{ + DWORD Size; + DWORD OffsetInTF; +} CPU_REGISTER, *PCPU_REGISTER; + +#define KTRAP_FRAME_X86 KTRAP_FRAME + +#define EIP_REGNO 8 + +static CPU_REGISTER GspRegisters[NUMREGS] = +{ + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Eax) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Ecx) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Edx) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Ebx) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Esp) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Ebp) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Esi) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Edi) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Eip) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Eflags) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Cs) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Ss) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Ds) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Es) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Fs) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Gs) } +}; + +static CHAR GspThreadStates[THREAD_STATE_MAX] = +{ + "Invalid", /* THREAD_STATE_INVALID */ + "Runnable", /* THREAD_STATE_RUNNABLE */ + "Running", /* THREAD_STATE_RUNNING */ + "Suspended", /* THREAD_STATE_SUSPENDED */ + "Frozen", /* THREAD_STATE_FROZEN */ + "Terminated 1", /* THREAD_STATE_TERMINATED_1 */ + "Terminated 2", /* THREAD_STATE_TERMINATED_2 */ + "Blocked" /* THREAD_STATE_BLOCKED */ +}; + +char * +strtok(char *s, const char *delim) +{ + const char *spanp; + int c, sc; + char *tok; + static char *last; + + + if (s == NULL && (s = last) == NULL) + return (NULL); + + /* + * Skip (span) leading delimiters (s += strspn(s, delim), sort of). + */ + cont: + c = *s++; + for (spanp = delim; (sc = *spanp++) != 0;) { + if (c == sc) + goto cont; + } + + if (c == 0) { /* no non-delimiter characters */ + last = NULL; + return (NULL); + } + tok = s - 1; + + /* + * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). + * Note that delim must have one NUL; we stop if we see that, too. + */ + for (;;) { + c = *s++; + spanp = delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + last = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} + + +LONG +HexValue (CHAR ch) +{ + if ((ch >= '0') && (ch <= '9')) return (ch - '0'); + if ((ch >= 'a') && (ch <= 'f')) return (ch - 'a' + 10); + if ((ch >= 'A') && (ch <= 'F')) return (ch - 'A' + 10); + return (-1); +} + +static CHAR GspInBuffer[BUFMAX]; +static CHAR GspOutBuffer[BUFMAX]; + +/* scan for the sequence $# */ + +PCHAR +GspGetPacket() +{ + PCHAR Buffer = &GspInBuffer[0]; + CHAR Checksum; + CHAR XmitChecksum; + ULONG Count; + CHAR ch; + + while (TRUE) + { + /* wait around for the start character, ignore all other characters */ + while ((ch = KdGetChar ()) != '$'); + + retry: + Checksum = 0; + XmitChecksum = -1; + Count = 0; + + /* now, read until a # or end of Buffer is found */ + while (Count < BUFMAX) + { + ch = KdGetChar (); + if (ch == '$') + goto retry; + if (ch == '#') + break; + Checksum = Checksum + ch; + Buffer[Count] = ch; + Count = Count + 1; + } + Buffer[Count] = 0; + + if (ch == '#') + { + ch = KdGetChar (); + XmitChecksum = HexValue (ch) << 4; + ch = KdGetChar (); + XmitChecksum += HexValue (ch); + + if (Checksum != XmitChecksum) + { + KdPutChar ('-'); /* failed checksum */ + } + else + { + KdPutChar ('+'); /* successful transfer */ + + /* if a sequence char is present, reply the sequence ID */ + if (Buffer[2] == ':') + { + KdPutChar (Buffer[0]); + KdPutChar (Buffer[1]); + + return &Buffer[3]; + } + + return &Buffer[0]; + } + } + } +} + +/* send the packet in Buffer. */ + +VOID +GspPutPacket (PCHAR Buffer) +{ + CHAR Checksum; + LONG Count; + CHAR ch; + + /* $#. */ + do + { + KdPutChar ('$'); + Checksum = 0; + Count = 0; + + while ((ch = Buffer[Count])) + { + KdPutChar (ch); + Checksum += ch; + Count += 1; + } + + KdPutChar ('#'); + KdPutChar (HexChars[(Checksum >> 4) & 0xf]); + KdPutChar (HexChars[Checksum & 0xf]); + } + while (KdGetChar () != '+'); +} + + +VOID +GspPutPacketNoWait (PCHAR Buffer) +{ + CHAR Checksum; + LONG Count; + CHAR ch; + + /* $#. */ + KdPutChar ('$'); + Checksum = 0; + Count = 0; + + while ((ch = Buffer[Count])) + { + KdPutChar (ch); + Checksum += ch; + Count += 1; + } + + KdPutChar ('#'); + KdPutChar (HexChars[(Checksum >> 4) & 0xf]); + KdPutChar (HexChars[Checksum & 0xf]); +} + + +VOID +GspDebugError(LPSTR Message) +{ + DbgPrint ("%s\n", Message); +} + +/* Address of a routine to RTE to if we get a memory fault. */ +static VOID (*volatile MemoryFaultRoutine) () = NULL; + +/* Indicate to caller of GspMem2Hex or GspHex2Mem that there has been an + error. */ +static volatile BOOLEAN GspMemoryError = FALSE; + + +/* Currently not used */ +VOID +GspSetMemoryError() +{ + GspMemoryError = TRUE; +} + + +/* These are separate functions so that they are so short and sweet + that the compiler won't save any Registers (if there is a fault + to MemoryFaultRoutine, they won't get restored, so there better + not be any saved). */ +CHAR +GspGetChar (PCHAR Address) +{ + return *Address; +} + + +VOID +GspSetChar (PCHAR Address, + CHAR Value) +{ + *Address = Value; +} + + +/* Convert the memory pointed to by Address into hex, placing result in Buffer */ +/* Return a pointer to the last char put in Buffer (null) */ +/* If MayFault is TRUE, then we should set GspMemoryError in response to + a fault; if FALSE treat a fault like any other fault in the stub. */ +PCHAR +GspMem2Hex (PCHAR Address, + PCHAR Buffer, + LONG Count, + BOOLEAN MayFault) +{ + ULONG i; + CHAR ch; + + if (MayFault) + MemoryFaultRoutine = GspSetMemoryError; + for (i = 0; i < Count; i++) + { + ch = GspGetChar (Address++); + if (MayFault && GspMemoryError) + return (Buffer); + *Buffer++ = HexChars[(ch >> 4) & 0xf]; + *Buffer++ = HexChars[ch & 0xf]; + } + *Buffer = 0; + if (MayFault) + MemoryFaultRoutine = NULL; + return (Buffer); +} + + +/* Convert the hex array pointed to by Buffer into binary to be placed at Address */ +/* Return a pointer to the character AFTER the last byte read from Buffer */ +PCHAR +GspHex2Mem (PCHAR Buffer, + PCHAR Address, + ULONG Count, + BOOLEAN MayFault) +{ + ULONG i; + CHAR ch; + + if (MayFault) + MemoryFaultRoutine = GspSetMemoryError; + for (i = 0; i < Count; i++) + { + ch = HexValue (*Buffer++) << 4; + ch = ch + HexValue (*Buffer++); + GspSetChar (Address++, ch); + if (MayFault && GspMemoryError) + return (Buffer); + } + if (MayFault) + MemoryFaultRoutine = NULL; + return (Buffer); +} + + +/* This function takes the 386 exception vector and attempts to + translate this number into a unix compatible signal value */ +ULONG +GspComputeSignal (NTSTATUS ExceptionCode) +{ + ULONG SigVal; + + switch (ExceptionCode) + { + case STATUS_INTEGER_DIVIDE_BY_ZERO: + SigVal = 8; + break; /* divide by zero */ + case STATUS_SINGLE_STEP: + SigVal = 5; + break; /* debug exception */ + case STATUS_BREAKPOINT: + SigVal = 5; + break; /* breakpoint */ + case STATUS_INTEGER_OVERFLOW: + SigVal = 16; + break; /* into instruction (overflow) */ + case STATUS_ARRAY_BOUNDS_EXCEEDED: + SigVal = 16; + break; /* bound instruction */ + case STATUS_ILLEGAL_INSTRUCTION: + SigVal = 4; + break; /* Invalid opcode */ +#if 0 + case STATUS_FLT_INVALID_OPERATION: + SigVal = 8; + break; /* coprocessor not available */ +#endif + case STATUS_STACK_OVERFLOW: + SigVal = 11; + break; /* stack exception */ + case STATUS_DATATYPE_MISALIGNMENT: + SigVal = 11; + break; /* page fault */ + default: + SigVal = 7; /* "software generated" */ + } + return (SigVal); +} + + +/**********************************************/ +/* WHILE WE FIND NICE HEX CHARS, BUILD A LONG */ +/* RETURN NUMBER OF CHARS PROCESSED */ +/**********************************************/ +LONG +GspHex2Long (PCHAR *Address, + PLONG Value) +{ + LONG NumChars = 0; + LONG Hex; + + *Value = 0; + + while (**Address) + { + Hex = HexValue (**Address); + if (Hex >= 0) + { + *Value = (*Value << 4) | Hex; + NumChars++; + } + else + break; + + (*Address)++; + } + + return (NumChars); +} + + +VOID +GspLong2Hex (PCHAR *Address, + LONG Value) +{ + LONG Save; + + Save = (((Value >> 0) & 0xf) << 24) | + (((Value >> 8) & 0xf) << 16) | + (((Value >> 16) & 0xf) << 8) | + (((Value >> 24) & 0xf) << 0); + *Address = GspMem2Hex ((PCHAR) &Save, *Address, 4, FALSE); +} + + +VOID +GspGetRegistersFromTrapFrame(PCHAR Address, + PKTRAP_FRAME TrapFrame) +{ + PCPU_REGISTER Regs; + ULONG Value; + PCHAR Buffer; + PULONG p; + DWORD i; + + Buffer = Address; + Regs = &GspRegisters[0]; + for (i = 0; i < NUMREGS; i++) + { + if (TrapFrame) + { + p = (PULONG) ((ULONG_PTR) TrapFrame + Regs[i].OffsetInTF); + Value = *p; + } + else if (i == EIP_REGNO) + { + /* + * This thread has not been sheduled yet so assume it + * is still in PsBeginThreadWithContextInternal(). + */ + Value = (ULONG) PsBeginThreadWithContextInternal; + } + else + { + Value = 0; + } + Buffer = GspMem2Hex ((PCHAR) &Value, Buffer, Regs[i].Size, FALSE); + } +} + + +VOID +GspSetRegistersInTrapFrame(PCHAR Address, + PKTRAP_FRAME TrapFrame) +{ + PCPU_REGISTER Regs; + ULONG Value; + PCHAR Buffer; + PULONG p; + DWORD i; + + if (!TrapFrame) + return; + + Buffer = Address; + Regs = &GspRegisters[0]; + for (i = 0; i < NUMREGS; i++) + { + p = (PULONG) ((ULONG_PTR) TrapFrame + Regs[i].OffsetInTF); + Value = 0; + Buffer = GspHex2Mem (Buffer, (PCHAR) &Value, Regs[i].Size, FALSE); + *p = Value; + } +} + + +VOID +GspSetSingleRegisterInTrapFrame(PCHAR Address, + LONG Number, + PKTRAP_FRAME TrapFrame) +{ + ULONG Value; + PULONG p; + + if (!TrapFrame) + return; + + p = (PULONG) ((ULONG_PTR) TrapFrame + GspRegisters[Number].OffsetInTF); + Value = 0; + GspHex2Mem (Address, (PCHAR) &Value, GspRegisters[Number].Size, FALSE); + *p = Value; +} + + +BOOLEAN +GspFindThread(PCHAR Data, + PETHREAD *Thread) +{ + PETHREAD ThreadInfo = NULL; + + if (strcmp (Data, "-1") == 0) + { + /* All threads */ + ThreadInfo = NULL; + } + else if (strcmp (Data, "0") == 0) + { + /* Pick any thread, pick the first thread, + * which is what most people are interested in + */ + ThreadInfo = CONTAINING_RECORD (PiThreadListHead.Flink, + ETHREAD, Tcb.ThreadListEntry); + } + else + { + ULONG ThreadId; + PCHAR ptr = &Data[0]; + + GspHex2Long (&ptr, (PLONG) &ThreadId); + + if (!NT_SUCCESS (PsLookupThreadByThreadId ((PVOID) ThreadId, &ThreadInfo))) + { + *Thread = NULL; + return FALSE; + } + } + *Thread = ThreadInfo; + return TRUE; +} + + +VOID +GspSetThread(PCHAR Request) +{ + PETHREAD ThreadInfo; + PCHAR ptr = &Request[1]; + + switch (Request[0]) + { + case 'c': /* Run thread */ + if (GspFindThread (ptr, &ThreadInfo)) + { + GspOutBuffer[0] = 'O'; + GspOutBuffer[1] = 'K'; + GspRunThread = ThreadInfo; + } + else + { + GspOutBuffer[0] = 'E'; + } + break; + case 'g': /* Debug thread */ + if (GspFindThread (ptr, &ThreadInfo)) + { + GspOutBuffer[0] = 'O'; + GspOutBuffer[1] = 'K'; + GspDbgThread = ThreadInfo; + } + else + { + GspOutBuffer[0] = 'E'; + } + break; + default: + break; + } +} + + +VOID +GspQuery(PCHAR Request) +{ + PCHAR Command; + ULONG Value; + + Command = strtok (Request, ","); + if (strncmp (Command, "C", 1) == 0) + { + PCHAR ptr = &GspOutBuffer[2]; + + /* Get current thread id */ + GspOutBuffer[0] = 'Q'; + GspOutBuffer[1] = 'C'; + Value = (ULONG) GspDbgThread->Cid.UniqueThread; + GspLong2Hex (&ptr, Value); + } + else if (strncmp (Command, "fThreadInfo", 11) == 0) + { + PCHAR ptr = &GspOutBuffer[1]; + + /* Get first thread id */ + GspOutBuffer[0] = 'm'; + GspEnumThread = CONTAINING_RECORD (PiThreadListHead.Flink, + ETHREAD, Tcb.ThreadListEntry); + Value = (ULONG) GspEnumThread->Cid.UniqueThread; + GspLong2Hex (&ptr, Value); + } + else if (strncmp (Command, "sThreadInfo", 11) == 0) + { + PCHAR ptr = &GspOutBuffer[1]; + + /* Get next thread id */ + if ((GspEnumThread) && (GspEnumThread->Tcb.ThreadListEntry.Flink != PiThreadListHead.Flink)) + { + GspEnumThread = CONTAINING_RECORD (GspEnumThread->Tcb.ThreadListEntry.Flink, + ETHREAD, Tcb.ThreadListEntry); + GspOutBuffer[0] = 'm'; + Value = (ULONG) GspEnumThread->Cid.UniqueThread; + GspLong2Hex (&ptr, Value); + } + else + { + GspOutBuffer[0] = '1'; + } + } + else if (strncmp (Command, "ThreadExtraInfo", 15) == 0) + { + PETHREAD ThreadInfo; + PCHAR ptr = &Command[15]; + + /* Get thread information */ + if (GspFindThread (ptr, &ThreadInfo)) + { + PCHAR String = &GspThreadStates[ThreadInfo->Tcb.State]; + GspMem2Hex (String, &GspOutBuffer[0], strlen (String), FALSE); + } + } +#if 0 + else if (strncmp (Command, "L", 1) == 0) + { + PLIST_ENTRY CurrentEntry; + PETHREAD Current; + ULONG MaxThreads = 0; + ULONG ThreadId = 0; + ULONG ThreadCount = 0; + + /* List threads */ + GspHex2Mem (&Request[1], (PCHAR) &MaxThreads, 2, TRUE); + GspHex2Mem (&Request[3], (PCHAR) &Value, 4, TRUE); + GspHex2Mem (&Request[11], (PCHAR) &ThreadId, 4, TRUE); + + GspOutBuffer[0] = 'q'; + GspOutBuffer[1] = 'M'; + Value = 0; + GspMem2Hex ((PCHAR) &Value, &GspOutBuffer[5], 4, TRUE); + GspMem2Hex ((PCHAR) &ThreadId, &GspOutBuffer[13], 4, TRUE); + + CurrentEntry = PiThreadListHead.Flink; + while ((CurrentEntry != &PiThreadListHead) && (ThreadCount < MaxThreads)) + { + Current = CONTAINING_RECORD (CurrentEntry, ETHREAD, Tcb.ThreadListEntry); + Value = 0; + GspMem2Hex ((PCHAR) &Value, &GspOutBuffer[21+ThreadCount*16], 4, TRUE); + Value = (ULONG) Current->Cid.UniqueThread; + GspMem2Hex ((PCHAR) &Value, &GspOutBuffer[21+ThreadCount*16+8], 4, TRUE); + CurrentEntry = CurrentEntry->Flink; + ThreadCount++; + } + + if (CurrentEntry != &PiThreadListHead) + { + GspOutBuffer[4] = '0'; + } + else + { + GspOutBuffer[4] = '1'; + } + + GspMem2Hex ((PCHAR) &ThreadCount, &GspOutBuffer[2], 1, TRUE); + } +#endif + else if (strncmp (Command, "Offsets", 7) == 0) + { + strcpy (GspOutBuffer, "Text=0;Data=0;Bss=0"); + } +} + +VOID +GspQueryThreadStatus(PCHAR Request) +{ + PETHREAD ThreadInfo; + PCHAR ptr = &Request[0]; + + if (GspFindThread (ptr, &ThreadInfo)) + { + GspOutBuffer[0] = 'O'; + GspOutBuffer[1] = 'K'; + GspOutBuffer[2] = '\0'; + } + else + { + GspOutBuffer[0] = 'E'; + GspOutBuffer[1] = '\0'; + } +} + + +typedef struct _GsHwBreakPoint +{ + BOOLEAN Enabled; + ULONG Type; + ULONG Length; + ULONG Address; +} GsHwBreakPoint; + +GsHwBreakPoint GspBreakpoints[4] = +{ + { Enabled : FALSE }, + { Enabled : FALSE }, + { Enabled : FALSE }, + { Enabled : FALSE } +}; + +VOID +GspCorrectHwBreakpoint() +{ + ULONG BreakpointNumber; + BOOLEAN CorrectIt; + BOOLEAN Bit; + ULONG dr7; + + asm volatile ( + "movl %%db7, %0\n" : "=r" (dr7) : ); + do + { + ULONG addr0, addr1, addr2, addr3; + + asm volatile ( + "movl %%db0, %0\n" + "movl %%db1, %1\n" + "movl %%db2, %2\n" + "movl %%db3, %3\n" + : "=r" (addr0), "=r" (addr1), + "=r" (addr2), "=r" (addr3) : ); + } while (FALSE); + CorrectIt = FALSE; + for (BreakpointNumber = 0; BreakpointNumber < 3; BreakpointNumber++) + { + Bit = 2 << (BreakpointNumber << 1); + if (!(dr7 & Bit) && GspBreakpoints[BreakpointNumber].Enabled) { + CorrectIt = TRUE; + dr7 |= Bit; + dr7 &= ~(0xf0000 << (BreakpointNumber << 2)); + dr7 |= (((GspBreakpoints[BreakpointNumber].Length << 2) | + GspBreakpoints[BreakpointNumber].Type) << 16) << (BreakpointNumber << 2); + switch (BreakpointNumber) { + case 0: + asm volatile ("movl %0, %%dr0\n" + : : "r" (GspBreakpoints[BreakpointNumber].Address) ); + break; + + case 1: + asm volatile ("movl %0, %%dr1\n" + : : "r" (GspBreakpoints[BreakpointNumber].Address) ); + break; + + case 2: + asm volatile ("movl %0, %%dr2\n" + : : "r" (GspBreakpoints[BreakpointNumber].Address) ); + break; + + case 3: + asm volatile ("movl %0, %%dr3\n" + : : "r" (GspBreakpoints[BreakpointNumber].Address) ); + break; + } + } + else if ((dr7 & Bit) && !GspBreakpoints[BreakpointNumber].Enabled) + { + CorrectIt = TRUE; + dr7 &= ~Bit; + dr7 &= ~(0xf0000 << (BreakpointNumber << 2)); + } + } + if (CorrectIt) + { + asm volatile ( "movl %0, %%db7\n" : : "r" (dr7)); + } +} + +ULONG +GspRemoveHwBreakpoint(ULONG BreakpointNumber) +{ + if (!GspBreakpoints[BreakpointNumber].Enabled) + { + return -1; + } + GspBreakpoints[BreakpointNumber].Enabled = 0; + return 0; +} + + +ULONG +GspSetHwBreakpoint(ULONG BreakpointNumber, + ULONG Type, + ULONG Length, + ULONG Address) +{ + if (GspBreakpoints[BreakpointNumber].Enabled) + { + return -1; + } + GspBreakpoints[BreakpointNumber].Enabled = TRUE; + GspBreakpoints[BreakpointNumber].Type = Type; + GspBreakpoints[BreakpointNumber].Length = Length; + GspBreakpoints[BreakpointNumber].Address = Address; + return 0; +} + + +/* + * This function does all command procesing for interfacing to gdb. + */ +KD_CONTINUE_TYPE +KdEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord, + PCONTEXT Context, + PKTRAP_FRAME TrapFrame) +{ + BOOLEAN Stepping; + LONG Address; + LONG Length; + LONG SigVal; + LONG NewPC; + PCHAR ptr; + + /* FIXME: Stop on other CPUs too */ + /* Disable hardware debugging while we are inside the stub */ + __asm__("movl %0,%%db7" : /* no output */ : "r" (0)); + + /* reply to host that an exception has occurred */ + SigVal = GspComputeSignal (ExceptionRecord->ExceptionCode); + + ptr = &GspOutBuffer[0]; + + *ptr++ = 'T'; /* notify gdb with signo, PC, FP and SP */ + *ptr++ = HexChars[(SigVal >> 4) & 0xf]; + *ptr++ = HexChars[SigVal & 0xf]; + + *ptr++ = HexChars[ESP]; + *ptr++ = ':'; + ptr = GspMem2Hex ((PCHAR) &TrapFrame->Esp, ptr, 4, 0); /* SP */ + *ptr++ = ';'; + + *ptr++ = HexChars[EBP]; + *ptr++ = ':'; + ptr = GspMem2Hex ((PCHAR) &TrapFrame->Ebp, ptr, 4, 0); /* FP */ + *ptr++ = ';'; + + *ptr++ = HexChars[PC]; + *ptr++ = ':'; + ptr = GspMem2Hex((PCHAR) &TrapFrame->Eip, ptr, 4, 0); /* PC */ + *ptr++ = ';'; + + *ptr = '\0'; + + GspPutPacket (&GspOutBuffer[0]); + + Stepping = FALSE; + + while (TRUE) + { + /* Zero the buffer now so we don't have to worry about the terminating zero character */ + memset (GspOutBuffer, 0, sizeof (GspInBuffer)); + ptr = GspGetPacket (); + + switch (*ptr++) + { + case '?': + GspOutBuffer[0] = 'S'; + GspOutBuffer[1] = HexChars[SigVal >> 4]; + GspOutBuffer[2] = HexChars[SigVal % 16]; + GspOutBuffer[3] = 0; + break; + case 'd': + GspRemoteDebug = !GspRemoteDebug; /* toggle debug flag */ + break; + case 'g': /* return the value of the CPU Registers */ + if (GspDbgThread) + GspGetRegistersFromTrapFrame (&GspOutBuffer[0], GspDbgThread->Tcb.TrapFrame); + else + GspGetRegistersFromTrapFrame (&GspOutBuffer[0], TrapFrame); + break; + case 'G': /* set the value of the CPU Registers - return OK */ + if (GspDbgThread) + GspSetRegistersInTrapFrame (ptr, GspDbgThread->Tcb.TrapFrame); + else + GspSetRegistersInTrapFrame (ptr, TrapFrame); + strcpy (GspOutBuffer, "OK"); + break; + case 'P': /* set the value of a single CPU register - return OK */ + { + LONG Register; + + if ((GspHex2Long (&ptr, &Register)) && (*ptr++ == '=')) + if ((Register >= 0) && (Register < NUMREGS)) + { + if (GspDbgThread) + GspSetSingleRegisterInTrapFrame (ptr, Register, + GspDbgThread->Tcb.TrapFrame); + else + GspSetSingleRegisterInTrapFrame (ptr, Register, TrapFrame); + strcpy (GspOutBuffer, "OK"); + break; + } + + strcpy (GspOutBuffer, "E01"); + break; + } + + /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ + case 'm': + /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */ + if (GspHex2Long (&ptr, &Address)) + if (*(ptr++) == ',') + if (GspHex2Long (&ptr, &Length)) + { + ptr = 0; + GspMemoryError = FALSE; + GspMem2Hex ((PCHAR) Address, GspOutBuffer, Length, 1); + if (GspMemoryError) + { + strcpy (GspOutBuffer, "E03"); + GspDebugError ("memory fault"); + } + } + + if (ptr) + { + strcpy (GspOutBuffer, "E01"); + } + break; + + /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ + case 'M': + /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */ + if (GspHex2Long (&ptr, &Address)) + if (*(ptr++) == ',') + if (GspHex2Long (&ptr, &Length)) + if (*(ptr++) == ':') + { + GspMemoryError = FALSE; + GspHex2Mem (ptr, (PCHAR) Address, Length, TRUE); + + if (GspMemoryError) + { + strcpy (GspOutBuffer, "E03"); + GspDebugError ("memory fault"); + } + else + { + strcpy (GspOutBuffer, "OK"); + } + + ptr = NULL; + } + if (ptr) + { + strcpy (GspOutBuffer, "E02"); + } + break; + + /* cAA..AA Continue at address AA..AA(optional) */ + /* sAA..AA Step one instruction from AA..AA(optional) */ + case 's': + Stepping = TRUE; + case 'c': + { + ULONG BreakpointNumber; + ULONG dr6; + + /* try to read optional parameter, pc unchanged if no parm */ + if (GspHex2Long (&ptr, &Address)) + Context->Eip = Address; + + NewPC = Context->Eip; + + /* clear the trace bit */ + Context->EFlags &= 0xfffffeff; + + /* set the trace bit if we're Stepping */ + if (Stepping) + Context->EFlags |= 0x100; + + asm volatile ("movl %%db6, %0\n" : "=r" (dr6) : ); + if (!(dr6 & 0x4000)) + { + for (BreakpointNumber = 0; BreakpointNumber < 4; ++BreakpointNumber) + { + if (dr6 & (1 << BreakpointNumber)) + { + if (GspBreakpoints[BreakpointNumber].Type == 0) + { + /* Set restore flag */ + Context->EFlags |= 0x10000; + break; + } + } + } + } + GspCorrectHwBreakpoint(); + asm volatile ("movl %0, %%db6\n" : : "r" (0)); + + return kdHandleException; + break; + } + case 'k': /* kill the program */ + strcpy (GspOutBuffer, "OK"); + break; + /* kill the program */ + case 'H': /* Set thread */ + GspSetThread (ptr); + break; + case 'q': /* Query */ + GspQuery (ptr); + break; + case 'T': /* Query thread status */ + GspQueryThreadStatus (ptr); + break; + case 'Y': + { + ULONG Number; + ULONG Length; + ULONG Type; + ULONG Address; + + ptr = &GspOutBuffer[1]; + GspHex2Long (&ptr, &Number); + ptr++; + GspHex2Long (&ptr, &Type); + ptr++; + GspHex2Long (&ptr, &Length); + ptr++; + GspHex2Long (&ptr, &Address); + if (GspSetHwBreakpoint (Number & 0x3, Type & 0x3 , Length & 0x3, Address) == 0) + { + strcpy (GspOutBuffer, "OK"); + } + else + { + strcpy (GspOutBuffer, "E"); + } + break; + /* Remove hardware breakpoint */ + } + case 'y': + { + ULONG Number; + + ptr = &GspOutBuffer[1]; + GspHex2Long(&ptr, &Number); + if (GspRemoveHwBreakpoint (Number & 0x3) == 0) + { + strcpy (GspOutBuffer, "OK"); + } + else + { + strcpy (GspOutBuffer, "E"); + } + break; + } + default: + break; + } /* switch */ + + /* reply to the request */ + GspPutPacket (&GspOutBuffer[0]); + } + + return kdDoNotHandleException; +} + + +BOOLEAN +STDCALL +GspBreakIn(PKINTERRUPT Interrupt, + PVOID ServiceContext) +{ + PKTRAP_FRAME TrapFrame; + BOOLEAN DoBreakIn; + CONTEXT Context; + KIRQL OldIrql; + CHAR Value; + + DPRINT ("Break In\n"); + + DoBreakIn = FALSE; + while (KdPortGetByte (&Value)) + { + if (Value == 0x03) + DoBreakIn = TRUE; + } + + if (!DoBreakIn) + return TRUE; + + KeRaiseIrql (HIGH_LEVEL, &OldIrql); + + TrapFrame = PsGetCurrentThread()->Tcb.TrapFrame; + + KeTrapFrameToContext (TrapFrame, &Context); + + KdEnterDebuggerException (NULL, &Context, TrapFrame); + + KeContextToTrapFrame (&Context, TrapFrame); + + KeLowerIrql (OldIrql); + + return TRUE; +} + + +extern ULONG KdpPortIrq; + +/* Initialize the GDB stub */ +VOID +KdGdbStubInit(ULONG Phase) +{ + KAFFINITY Affinity; + NTSTATUS Status; + ULONG MappedIrq; + KIRQL Dirql; + + if (Phase == 0) + { + GspInitialized = TRUE; + GspRunThread = PsGetCurrentThread(); + GspDbgThread = PsGetCurrentThread(); + GspEnumThread = NULL; + } + else if (Phase == 1) + { + /* Hook an interrupt handler to allow the debugger to break into + the system */ + MappedIrq = HalGetInterruptVector (Internal, + 0, + 0, + KdpPortIrq, + &Dirql, + &Affinity); + + Status = IoConnectInterrupt(&GspInterrupt, + GspBreakIn, + NULL, + NULL, + MappedIrq, + Dirql, + Dirql, + 0, + FALSE, + Affinity, + FALSE); + if (!NT_SUCCESS (Status)) + { + DPRINT1("Could not connect to IRQ line %d (0x%x)\n", + KdpPortIrq, Status); + return; + } + + KdPortEnableInterrupts(); + } +} + +/* This function will generate a breakpoint exception. It is used at the + beginning of a program to sync up with a debugger and can be used + otherwise as a quick means to stop program execution and "break" into + the debugger. */ + +VOID +KdDebugPrint (LPSTR Message) +{ +#ifdef SERDUMP + + PCHAR pch = (PCHAR) Message; + + while (*pch != 0) + { + if (*pch == '\n') + { + KdPortPutByte ('\r'); + } + KdPortPutByte (*pch); + pch++; + } + +#else /* !SERDUMP */ + +/* This can be quite annoying! */ +#if 0 + if (GspInitialized) + { + ULONG Length; + + GspOutBuffer[0] = 'O'; + GspOutBuffer[1] = '\0'; + strcat (&GspOutBuffer[0], Message); + Length = strlen (Message); + GspOutBuffer[2 + Length] = '\n'; + GspOutBuffer[3 + Length] = '\0'; + GspPutPacketNoWait (&GspOutBuffer[0]); + } +#endif + +#endif /* SERDUMP */ +} diff --git a/reactos/ntoskrnl/kd/kdebug.c b/reactos/ntoskrnl/kd/kdebug.c index 2a3fc63f2cc..5dda80d7343 100644 --- a/reactos/ntoskrnl/kd/kdebug.c +++ b/reactos/ntoskrnl/kd/kdebug.c @@ -1,4 +1,4 @@ -/* $Id: kdebug.c,v 1.30 2001/12/31 19:06:47 dwelch Exp $ +/* $Id: kdebug.c,v 1.31 2002/01/23 23:39:25 chorns Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -18,7 +18,9 @@ /* serial debug connection */ #define DEFAULT_DEBUG_PORT 2 /* COM2 */ -#define DEFAULT_DEBUG_BAUD_RATE 19200 /* 19200 Baud */ +#define DEFAULT_DEBUG_COM1_IRQ 4 /* COM1 IRQ */ +#define DEFAULT_DEBUG_COM2_IRQ 3 /* COM2 IRQ */ +#define DEFAULT_DEBUG_BAUD_RATE 115200 /* 115200 Baud */ /* bochs debug output */ #define BOCHS_LOGGER_PORT (0xe9) @@ -43,8 +45,8 @@ KdDebuggerNotPresent = TRUE; /* EXPORTED */ static BOOLEAN KdpBreakPending = FALSE; -static BOOLEAN KdpBreakRecieved = FALSE; static ULONG KdpDebugType = ScreenDebug | BochsDebug; +ULONG KdpPortIrq = 0; /* PRIVATE FUNCTIONS ********************************************************/ @@ -75,12 +77,12 @@ KdInitSystem ( #ifdef KDBG /* Initialize runtime debugging if available */ DbgRDebugInit(); - #endif /* set debug port default values */ PortInfo.ComPort = DEFAULT_DEBUG_PORT; PortInfo.BaudRate = DEFAULT_DEBUG_BAUD_RATE; + KdpPortIrq = DEFAULT_DEBUG_COM2_IRQ; /* * parse kernel command line @@ -157,6 +159,21 @@ KdInitSystem ( PortInfo.BaudRate = Value; } } + else if (!_strnicmp (p2, "IRQ", 3)) + { + p2 += 3; + if (*p2 != '=') + { + p2++; + Value = (ULONG)atol (p2); + if (Value > 0) + { + KdDebuggerEnabled = TRUE; + KdpDebugType = KdpDebugType | SerialDebug; + KdpPortIrq = Value; + } + } + } } p1 = p2; } @@ -200,6 +217,31 @@ KdInitSystem ( } } +VOID KdInit1() +{ +#ifndef SERDUMP + + /* Initialize kernel debugger */ + if (KdDebuggerEnabled && (KdpDebugType & SerialDebug)) + { + KdGdbStubInit(0); + } + +#endif /* !SERDUMP */ +} + +VOID KdInit2() +{ +#ifndef SERDUMP + + /* Initialize kernel debugger */ + if (KdDebuggerEnabled && (KdpDebugType & SerialDebug)) + { + KdGdbStubInit(1); + } + +#endif /* !SERDUMP */ +} ULONG KdpPrintString (PANSI_STRING String) { @@ -210,17 +252,7 @@ ULONG KdpPrintString (PANSI_STRING String) HalDisplayString (String->Buffer); } if (KdpDebugType & SerialDebug) - { - while (*pch != 0) - { - if (*pch == '\n') - { - KdPortPutByte ('\r'); - } - KdPortPutByte (*pch); - pch++; - } - } + KdDebugPrint (pch); if (KdpDebugType & BochsDebug) { pch = String->Buffer; @@ -253,37 +285,18 @@ KdPollBreakIn ( VOID ) { - BOOLEAN Result = FALSE; - UCHAR ByteRead; +#ifndef SERDUMP - if (KdDebuggerEnabled == FALSE || KdpDebugType != SerialDebug) - return Result; + if (!KdDebuggerEnabled || !(KdpDebugType & SerialDebug)) + return FALSE; -// Flags = KiDisableInterrupts(); + return TRUE; - HalDisplayString ("Waiting for kernel debugger connection...\n"); +#else /* SERDUMP */ - if (KdPortPollByte (&ByteRead)) - { - if (ByteRead == 0x62) - { - if (KdpBreakPending == TRUE) - { - KdpBreakPending = FALSE; - KdpBreakRecieved = TRUE; - Result = TRUE; - } - HalDisplayString (" Kernel debugger connected\n"); - } - else - { - HalDisplayString (" Kernel debugger connection failed\n"); - } - } + return FALSE; -// KiRestoreInterrupts (Flags); - - return Result; +#endif /* !SERDUMP */ } VOID STDCALL @@ -368,4 +381,24 @@ KdSystemDebugControl(ULONG Code) } } + +/* Support routines for the GDB stubs */ + +VOID +KdPutChar(UCHAR Value) +{ + KdPortPutByte (Value); +} + + +UCHAR +KdGetChar() +{ + UCHAR Value; + + while (!KdPortGetByte (&Value)); + + return Value; +} + /* EOF */ diff --git a/reactos/ntoskrnl/ke/catch.c b/reactos/ntoskrnl/ke/catch.c index f06d420b5f4..2a8d0f2e52b 100644 --- a/reactos/ntoskrnl/ke/catch.c +++ b/reactos/ntoskrnl/ke/catch.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: catch.c,v 1.16 2001/09/24 00:51:16 chorns Exp $ +/* $Id: catch.c,v 1.17 2002/01/23 23:39:25 chorns Exp $ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/catch.c @@ -27,9 +27,11 @@ /* INCLUDES *****************************************************************/ #include +#include #include #include #include +#include #define NDEBUG #include @@ -197,7 +199,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord, EXCEPTION_DISPOSITION Value; CONTEXT TContext; - DPRINT("KiDispatchException() called \n"); + DPRINT("KiDispatchException() called\n"); /* PCR->KeExceptionDispatchCount++; */ if (Context == NULL) @@ -212,12 +214,12 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord, Context = &TContext; } - +#if 0 if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) { Context->Eip--; } - +#endif if (PreviousMode == UserMode) { if (SearchFrames) @@ -265,15 +267,31 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord, } else { + KD_CONTINUE_TYPE Action; + /* PreviousMode == KernelMode */ - Value = RtlpDispatchException(ExceptionRecord, Context); - DPRINT("RtlpDispatchException() returned with 0x%X\n", Value); +#ifndef KDBG - /* If RtlpDispatchException() does not handle the exception then bugcheck */ - if (Value != ExceptionContinueExecution) + KeBugCheck (KMODE_EXCEPTION_NOT_HANDLED); + +#endif /* KDBG */ + + Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf); + if (Action != kdHandleException) + { + Value = RtlpDispatchException (ExceptionRecord, Context); + + DPRINT("RtlpDispatchException() returned with 0x%X\n", Value); + /* If RtlpDispatchException() does not handle the exception then bugcheck */ + if (Value != ExceptionContinueExecution) + { + KeBugCheck (KMODE_EXCEPTION_NOT_HANDLED); + } + } + else { - KeBugCheck(KMODE_EXCEPTION_NOT_HANDLED); + KeContextToTrapFrame (Context, KeGetCurrentThread()->TrapFrame); } } } diff --git a/reactos/ntoskrnl/ke/i386/exp.c b/reactos/ntoskrnl/ke/i386/exp.c index 02d9c77e375..7790c0d6b2f 100644 --- a/reactos/ntoskrnl/ke/i386/exp.c +++ b/reactos/ntoskrnl/ke/i386/exp.c @@ -95,6 +95,29 @@ static char *ExceptionTypeStrings[] = "Machine Check" }; +static NTSTATUS ExceptionToNtStatus[] = + { + STATUS_INTEGER_DIVIDE_BY_ZERO, + STATUS_SINGLE_STEP, + STATUS_ACCESS_VIOLATION, + STATUS_BREAKPOINT, + STATUS_INTEGER_OVERFLOW, + STATUS_ARRAY_BOUNDS_EXCEEDED, + STATUS_ILLEGAL_INSTRUCTION, + STATUS_ACCESS_VIOLATION, /* STATUS_FLT_INVALID_OPERATION */ + STATUS_ACCESS_VIOLATION, + STATUS_ACCESS_VIOLATION, + STATUS_ACCESS_VIOLATION, + STATUS_ACCESS_VIOLATION, + STATUS_STACK_OVERFLOW, + STATUS_ACCESS_VIOLATION, + STATUS_ACCESS_VIOLATION, + STATUS_ACCESS_VIOLATION, /* STATUS_FLT_INVALID_OPERATION */ + STATUS_DATATYPE_MISALIGNMENT, + STATUS_ACCESS_VIOLATION + }; + + /* FUNCTIONS ****************************************************************/ extern unsigned int _text_start__, _text_end__; @@ -168,37 +191,10 @@ KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2) { EXCEPTION_RECORD Er; - if (ExceptionNr == 0) - { - Er.ExceptionCode = STATUS_INTEGER_DIVIDE_BY_ZERO; - } - else if (ExceptionNr == 1) - { - Er.ExceptionCode = STATUS_SINGLE_STEP; - } - else if (ExceptionNr == 3) - { - Er.ExceptionCode = STATUS_BREAKPOINT; - } - else if (ExceptionNr == 4) - { - Er.ExceptionCode = STATUS_INTEGER_OVERFLOW; - } - else if (ExceptionNr == 5) - { - Er.ExceptionCode = STATUS_ARRAY_BOUNDS_EXCEEDED; - } - else if (ExceptionNr == 6) - { - Er.ExceptionCode = STATUS_ILLEGAL_INSTRUCTION; - } - else - { - Er.ExceptionCode = STATUS_ACCESS_VIOLATION; - } Er.ExceptionFlags = 0; Er.ExceptionRecord = NULL; Er.ExceptionAddress = (PVOID)Tf->Eip; + if (ExceptionNr == 14) { Er.NumberParameters = 2; @@ -207,6 +203,14 @@ KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2) } else { + if (ExceptionNr < 16) + { + Er.ExceptionCode = ExceptionToNtStatus[ExceptionNr]; + } + else + { + Er.ExceptionCode = STATUS_ACCESS_VIOLATION; + } Er.NumberParameters = 0; } @@ -406,7 +410,7 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr) * Complete CPU context */ { -//#define SEH +#define SEH unsigned int cr2; #ifndef SEH unsigned int cr3; diff --git a/reactos/ntoskrnl/ke/i386/irq.c b/reactos/ntoskrnl/ke/i386/irq.c index 3e37fdbfdfb..72b5cc53684 100644 --- a/reactos/ntoskrnl/ke/i386/irq.c +++ b/reactos/ntoskrnl/ke/i386/irq.c @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.15 2001/08/30 20:38:19 dwelch Exp $ +/* $Id: irq.c,v 1.16 2002/01/23 23:39:25 chorns Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -240,6 +240,30 @@ typedef struct _KIRQ_TRAPFRAME ULONG Eflags; } KIRQ_TRAPFRAME, *PKIRQ_TRAPFRAME; +#ifdef DBG + +VOID +KeIRQTrapFrameToTrapFrame(PKIRQ_TRAPFRAME IrqTrapFrame, + PKTRAP_FRAME TrapFrame) +{ + TrapFrame->Fs = IrqTrapFrame->Fs; + TrapFrame->Fs = IrqTrapFrame->Es; + TrapFrame->Ds = IrqTrapFrame->Ds; + TrapFrame->Eax = IrqTrapFrame->Eax; + TrapFrame->Ecx = IrqTrapFrame->Ecx; + TrapFrame->Edx = IrqTrapFrame->Edx; + TrapFrame->Ebx = IrqTrapFrame->Ebx; + TrapFrame->Esp = IrqTrapFrame->Esp; + TrapFrame->Ebp = IrqTrapFrame->Ebp; + TrapFrame->Esi = IrqTrapFrame->Esi; + TrapFrame->Edi = IrqTrapFrame->Edi; + TrapFrame->Eip = IrqTrapFrame->Eip; + TrapFrame->Cs = IrqTrapFrame->Cs; + TrapFrame->Eflags = IrqTrapFrame->Eflags; +} + +#endif + #ifdef MP VOID @@ -256,6 +280,15 @@ KiInterruptDispatch (ULONG Vector, PKIRQ_TRAPFRAME Trapframe) PLIST_ENTRY current; ULONG irq; +#ifdef DBG + + KTRAP_FRAME KernelTrapFrame; + + KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame); + KeGetCurrentThread()->TrapFrame = &KernelTrapFrame; + +#endif /* DBG */ + DPRINT("I(%d) ", Vector); /* @@ -348,6 +381,15 @@ KiInterruptDispatch (ULONG irq, PKIRQ_TRAPFRAME Trapframe) PKINTERRUPT isr; PLIST_ENTRY current; +#ifdef DBG + + KTRAP_FRAME KernelTrapFrame; + + KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame); + KeGetCurrentThread()->TrapFrame = &KernelTrapFrame; + +#endif /* DBG */ + /* * Notify the rest of the kernel of the raised irq level */ diff --git a/reactos/ntoskrnl/ke/main.c b/reactos/ntoskrnl/ke/main.c index 169e7c94bec..de47b47f157 100644 --- a/reactos/ntoskrnl/ke/main.c +++ b/reactos/ntoskrnl/ke/main.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: main.c,v 1.111 2002/01/15 02:51:32 dwelch Exp $ +/* $Id: main.c,v 1.112 2002/01/23 23:39:25 chorns Exp $ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/main.c @@ -88,7 +88,7 @@ SERVICE Services[] = { {L"pci", L"PCI Bus Driver", L"Boot Bus Extender", 0, 1}, {L"keyboard", L"Standard Keyboard Driver", L"Base", 0, 1}, {L"blue", L"Bluescreen Driver", L"Base", 0, 1}, -/* {L"vidport", L"Video Port Driver", L"Base", 0, 1}, + {L"vidport", L"Video Port Driver", L"Base", 0, 1}, {L"vgamp", L"VGA Miniport", L"Base", 0, 1}, {L"minixfs", L"Minix File System", L"File system", 0, 1}, {L"msfs", L"Mail Slot File System", L"File system", 0, 1}, @@ -97,13 +97,13 @@ SERVICE Services[] = { {L"mouclass", L"Mouse Class Driver", L"Pointer Class", 0, 1}, {L"ndis", L"NDIS System Driver", L"NDIS Wrapper", 0, 1}, {L"ne2000", L"Novell Eagle 2000 Driver", L"NDIS", 0, 1}, - {L"afd", L"AFD Networking Support Environment", L"TDI", 0, 1},*/ + {L"afd", L"AFD Networking Support Environment", L"TDI", 0, 1}, {NULL,} }; /* FUNCTIONS ****************************************************************/ -//#define FULLREG +#define FULLREG VOID CreateDefaultRegistryForLegacyDriver( PSERVICE Service) @@ -312,7 +312,7 @@ VOID CreateDefaultRegistryForLegacyDriver( NtClose(KeyHandle); return; } -#if FULLREG +#ifdef FULLREG DwordData = Service->Start; Length = sizeof(DWORD); Status = RtlWriteRegistryValue( @@ -953,11 +953,7 @@ ExpInitializeExecutive(VOID) * Initialize the kernel debugger */ KdInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock); - if (KdPollBreakIn ()) - { - DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C); - } - + MmInit2(); KeInit2(); @@ -965,7 +961,14 @@ ExpInitializeExecutive(VOID) ObInit(); PiInitProcessManager(); - + + KdInit1(); + + if (KdPollBreakIn ()) + { + DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C); + } + /* * Display version number and copyright/warranty message */ @@ -1029,6 +1032,7 @@ ExpInitializeExecutive(VOID) NtInit(); MmInit3(); CcInit(); + KdInit2(); /* Report all resources used by hal */ HalReportResourceUsage(); diff --git a/reactos/ntoskrnl/ldr/loader.c b/reactos/ntoskrnl/ldr/loader.c index 94cd231348f..1383997dd28 100644 --- a/reactos/ntoskrnl/ldr/loader.c +++ b/reactos/ntoskrnl/ldr/loader.c @@ -1,4 +1,4 @@ -/* $Id: loader.c,v 1.94 2002/01/02 21:00:55 chorns Exp $ +/* $Id: loader.c,v 1.95 2002/01/23 23:39:25 chorns Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -322,6 +322,24 @@ VOID LdrInitModuleManagement(VOID) ModuleObject->TextSection = &LdrHalTextSection; } + +NTSTATUS +LdrpOpenModuleDirectory(PHANDLE Handle) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING ModuleDirectory; + + RtlInitUnicodeString (&ModuleDirectory, MODULE_ROOT_NAME); + InitializeObjectAttributes(&ObjectAttributes, + &ModuleDirectory, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + return NtOpenDirectoryObject(Handle, GENERIC_ALL, &ObjectAttributes); +} + + /* * load the auto config drivers. */ diff --git a/reactos/ntoskrnl/mm/mm.c b/reactos/ntoskrnl/mm/mm.c index 13185d8fc5d..a7dacf28900 100644 --- a/reactos/ntoskrnl/mm/mm.c +++ b/reactos/ntoskrnl/mm/mm.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: mm.c,v 1.53 2002/01/01 00:21:56 dwelch Exp $ +/* $Id: mm.c,v 1.54 2002/01/23 23:39:26 chorns Exp $ * * COPYRIGHT: See COPYING in the top directory * PROJECT: ReactOS kernel @@ -328,7 +328,6 @@ NTSTATUS MmNotPresentFault(KPROCESSOR_MODE Mode, MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, (PVOID)Address); if (MemoryArea == NULL) { - DbgPrint("%s:%d\n",__FILE__,__LINE__); if (!FromMdl) { MmUnlockAddressSpace(AddressSpace); diff --git a/reactos/ntoskrnl/ob/dirobj.c b/reactos/ntoskrnl/ob/dirobj.c index d20355a50b8..06e54bcb747 100644 --- a/reactos/ntoskrnl/ob/dirobj.c +++ b/reactos/ntoskrnl/ob/dirobj.c @@ -1,4 +1,4 @@ -/* $Id: dirobj.c,v 1.12 2001/06/16 14:10:55 ekohl Exp $ +/* $Id: dirobj.c,v 1.13 2002/01/23 23:39:26 chorns Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -183,10 +183,10 @@ NTSTATUS STDCALL NtQueryDirectoryObject (IN HANDLE DirObjHandle, } else { - DirectorySize = 1; + DirectoryCount = 1; } - DirectorySize = (DirectoryCount + 1) * sizeof (OBJDIR_INFORMATION); - if (DirectorySize >= SpaceLeft) + DirectorySize = DirectoryCount * sizeof (OBJDIR_INFORMATION); + if (DirectorySize > SpaceLeft) { return (STATUS_BUFFER_TOO_SMALL); } @@ -208,7 +208,7 @@ NTSTATUS STDCALL NtQueryDirectoryObject (IN HANDLE DirObjHandle, ); if ((EntriesToSkip) && (current_entry == & dir->head)) { - return (STATUS_INVALID_PARAMETER); + return (STATUS_NO_MORE_ENTRIES); } } /* @@ -225,44 +225,44 @@ NTSTATUS STDCALL NtQueryDirectoryObject (IN HANDLE DirObjHandle, */ SpaceLeft -= DirectorySize; /* Scan the directory */ - do { + do + { /* * Check if we reached the end of the directory. */ if (current_entry == & dir->head) { - /* Any data? */ + /* Any data? */ if (i) break; /* DONE */ /* FIXME: better error handling here! */ return (STATUS_NO_MORE_ENTRIES); } - /* + /* * Compute the current OBJECT_HEADER memory * object's address. */ - current = CONTAINING_RECORD(current_entry, OBJECT_HEADER, Entry); - /* - * Compute the space required in the user buffer to copy - * the data from the current object: + current = CONTAINING_RECORD(current_entry, OBJECT_HEADER, Entry); + /* + * Compute the space required in the user buffer to copy + * the data from the current object: * * Name (WCHAR) 0 TypeName (WCHAR) 0 - */ + */ NameLength = (wcslen (current->Name.Buffer) * sizeof (WCHAR)); TypeNameLength = (wcslen (current->ObjectType->TypeName.Buffer) * sizeof (WCHAR)); - SpaceRequired = - (NameLength + sizeof (WCHAR)) - + (TypeNameLength + sizeof (WCHAR)); + SpaceRequired = (NameLength + 1) * sizeof (WCHAR) + + (TypeNameLength + 1) * sizeof (WCHAR); /* * Check for free space in the user buffer. */ - if (SpaceRequired >= SpaceLeft) + if (SpaceRequired > SpaceLeft) { return (STATUS_BUFFER_TOO_SMALL); } - /* - * Copy the current directory entry's data into the buffer + /* + * Copy the current directory entry's data into the buffer * and update the OBJDIR_INFORMATION entry in the array. - */ + */ /* --- Object's name --- */ current_odi->ObjectName.Length = NameLength; current_odi->ObjectName.MaximumLength = (NameLength + sizeof (WCHAR)); diff --git a/reactos/tools/helper.mk b/reactos/tools/helper.mk index 33979c6732c..6ce01010bab 100644 --- a/reactos/tools/helper.mk +++ b/reactos/tools/helper.mk @@ -1,4 +1,4 @@ -# $Id: helper.mk,v 1.10 2002/01/08 00:49:02 dwelch Exp $ +# $Id: helper.mk,v 1.11 2002/01/23 23:39:26 chorns Exp $ # # Helper makefile for ReactOS modules # Variables this makefile accepts: @@ -6,7 +6,7 @@ # program = User mode program # proglib = Executable program that have exported functions # dynlink = Dynamic Link Library (DLL) -# library = Import library that will be linked with other code +# library = Library that will be linked with other code # driver_library = Import library for a driver # driver = Kernel mode driver # export_driver = Kernel mode driver that have exported functions @@ -125,8 +125,8 @@ endif endif ifeq ($(TARGET_TYPE),library) - MK_MODE := user - MK_EXETYPE := dll + MK_MODE := static + MK_EXETYPE := MK_DEFEXT := .a MK_DEFENTRY := MK_DDKLIBS := @@ -135,12 +135,12 @@ ifeq ($(TARGET_TYPE),library) MK_CPPFLAGS := -I./ -I$(SDK_PATH_INC) MK_RCFLAGS := --include-dir $(SDK_PATH_INC) MK_IMPLIB := no - MK_IMPLIBONLY := yes - MK_IMPLIBDEFPATH := $(SDK_PATH_LIB) - MK_IMPLIB_EXT := .a + MK_IMPLIBONLY := no + MK_IMPLIBDEFPATH := + MK_IMPLIB_EXT := MK_INSTALLDIR := $(SDK_PATH_INC) MK_DISTDIR := # FIXME - MK_RES_BASE := + MK_RES_BASE := endif ifeq ($(TARGET_TYPE),driver_library) @@ -523,6 +523,14 @@ $(MK_FULLNAME): $(MK_FULLRES) $(TARGET_OBJECTS) $(MK_LIBS) endif # MK_MODE +# Static library target +ifeq ($(MK_MODE),static) + +$(MK_FULLNAME): $(TARGET_OBJECTS) + $(AR) -r $(MK_FULLNAME) $(TARGET_OBJECTS) + +endif # MK_MODE + endif # MK_IMPLIBONLY