- Replace RtlpGetExceptionAddress by the _ReturnAddress intrinsic and add it to ARM...
authorStefan Ginsberg <stefanginsberg@gmail.com>
Fri, 23 Oct 2009 22:51:39 +0000 (22:51 +0000)
committerStefan Ginsberg <stefanginsberg@gmail.com>
Fri, 23 Oct 2009 22:51:39 +0000 (22:51 +0000)
- Simplify RtlpCheckForActiveDebugger: Remove the BOOLEAN parameter as we would always pass it FALSE. Always return FALSE false from kernel mode for simplicity.
- Fix a critical flaw in our exception support: RtlRaiseException and RtlRaiseStatus were implemented in C on x86. This lead to unpredictable register corruption because the compiler could not know that it had to preserve non-volatile registers before calling RtlCaptureContext as the saved context is later used to restore the caller in case the exception is handled and execution is continued. This made the functions unsafe to return from as any non-volatile register could be corrupted. Implement them in assembly for x86 to safely capture the context using only EBP and ESP. The C versions of those routines are still used and shared for the other architectures we support -- needs to be determined if this is safe and correct for those architectures.
- The ntdll exception Wine exposed this issue, and all tests now pass. The remaining failures on the build server are caused by missing or incomplete debug register support in KVM/QEMU. Run the test in another VM or on real hardware and all the tests will pass.
- Implement Debug Prompt (DbgPrompt) support for KD and KDBG. The KDBG implementation reads the prompt from keyboard or serial depending on the mode so that sysreg and rosdbg can support it too.
- Properly implement RtlAssert using DbgPrompt to prompt for the action to take instead of always doing a breakpoint. The new implementation is disabled until sysreg can support this. Also move RtlAssert to its own file as it has nothing to do with the error routines (nor does it belong in exception.c).
- Note that DbgPrompt was already used in PspCatchCriticalBreak, and this would have resulted in a silent hang as BREAKPOINT_PROMPT wasn't handled at all by KDBG.
- Implement KiRaiseAssertion (10 lines of code with the trap macros) and thus support NT_ASSERT. Add partial support for it to KDBG to print out a warning and the address of the failure, but don't do anything else. Also add NT_ASSERT to the DDK headers so that we can use it, but don't use it yet as the ARM method of performing this has not been decided nor implemented.
- KiTrap3 doesn't set STATUS_SUCCESS but BREAKPOINT_BREAK. They have the same numerical value but very different meaning -- BREAKPOINT_BREAK means that the exception is a software breakpoint and not a debug service call. Fix some comments to document that this is what is checked for.
- Fix inverted and broken logic in KdpReport. It would never pass second chance exceptions to the debugger, didn't respect the stop-on-exception flag properly and would always fail to handle some special exceptions in both first and second chance instead of just failing to handle it in first chance. Clean up, reformat and document what is going on.
- The DebugPrint and DebugPrompt support routines only perform a 2D interrupt on x86; use more portable comments.
- Add Alex to the programmer section of x86's kdsup.c -- he wrote KdpGetStateChange, KdpSetContextState and the code that was previously in KdpRead/WriteControlSpace.
- Add my name to the parts of KD where I have made significant work on getting KD/WinDbg support up and running.
- KD debugging is now quite functional and stable. Some bugs and stubs remain to be flushed out, but overall KD is now much better and easier to use than KDBG.

svn path=/trunk/; revision=43705

27 files changed:
reactos/dll/ntdll/dispatch/arm/stubs_asm.s
reactos/dll/ntdll/rtl/libsupp.c
reactos/include/crt/mingw32/intrin_arm.h
reactos/include/ddk/winddk.h
reactos/include/ndk/i386/asm.h
reactos/lib/rtl/assert.c [new file with mode: 0644]
reactos/lib/rtl/debug.c
reactos/lib/rtl/error.c
reactos/lib/rtl/exception.c
reactos/lib/rtl/i386/except.c
reactos/lib/rtl/i386/except_asm.s
reactos/lib/rtl/powerpc/except.c
reactos/lib/rtl/rtl.rbuild
reactos/lib/rtl/rtlp.h
reactos/ntoskrnl/include/internal/kd.h
reactos/ntoskrnl/include/internal/kd64.h
reactos/ntoskrnl/kd/kdmain.c
reactos/ntoskrnl/kd64/i386/kdsup.c
reactos/ntoskrnl/kd64/kdapi.c
reactos/ntoskrnl/kd64/kdbreak.c
reactos/ntoskrnl/kd64/kdinit.c
reactos/ntoskrnl/kd64/kdprint.c
reactos/ntoskrnl/kd64/kdtrap.c
reactos/ntoskrnl/kdbg/kdb_cli.c
reactos/ntoskrnl/ke/arm/stubs_asm.s
reactos/ntoskrnl/ke/i386/trap.s
reactos/ntoskrnl/rtl/libsupp.c

index f11c598..d78a474 100644 (file)
@@ -6,7 +6,6 @@
 GENERATE_ARM_STUB LdrInitializeThunk
 GENERATE_ARM_STUB RtlGetCallersAddress
 GENERATE_ARM_STUB RtlUnwind
-GENERATE_ARM_STUB RtlpGetExceptionAddress
 GENERATE_ARM_STUB RtlDispatchException
 GENERATE_ARM_STUB RtlpGetStackLimits
 GENERATE_ARM_STUB DbgUserBreakPoint
@@ -15,4 +14,3 @@ GENERATE_ARM_STUB KiFastSystemCallRet
 GENERATE_ARM_STUB KiIntSystemCall
 GENERATE_ARM_STUB KiUserApcDispatcher
 GENERATE_ARM_STUB RtlInitializeContext
-
index 1ef8c26..3c4e01b 100644 (file)
@@ -33,9 +33,10 @@ RtlWalkFrameChain(OUT PVOID *Callers,
 
 BOOLEAN
 NTAPI
-RtlpCheckForActiveDebugger(BOOLEAN Type)
+RtlpCheckForActiveDebugger(VOID)
 {
-    return (NtCurrentPeb()->BeingDebugged);
+    /* Return the flag in the PEB */
+    return NtCurrentPeb()->BeingDebugged;
 }
 
 BOOLEAN
index 3e78892..066c641 100644 (file)
@@ -32,6 +32,7 @@
 #error Unsupported compiler
 #endif
 
+#define _ReturnAddress() (__builtin_return_address(0))
 #define _ReadWriteBarrier() __sync_synchronize()
 
 __INTRIN_INLINE char _InterlockedCompareExchange8(volatile char * const Destination, const char Exchange, const char Comperand)
index 928d4fa..491d2ba 100644 (file)
@@ -5796,6 +5796,25 @@ KeAcquireSpinLockRaiseToDpc(
 #define ROUND_TO_PAGES(Size) \
   ((ULONG_PTR) (((ULONG_PTR) Size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
 
+
+
+#if defined(_X86_) || defined(_AMD64_)
+
+//
+// x86 and x64 performs a 0x2C interrupt
+//
+#define DbgRaiseAssertionFailure __int2c
+
+#elif defined(_ARM_)
+
+//
+// TODO
+//
+
+#else
+#error Unsupported Architecture
+#endif
+
 #if DBG
 
 #define ASSERT(exp) \
@@ -5807,7 +5826,7 @@ KeAcquireSpinLockRaiseToDpc(
     RtlAssert( #exp, __FILE__, __LINE__, msg ), FALSE : TRUE)
 
 #define RTL_SOFT_ASSERT(exp) \
-  (VOID)((!(_exp)) ? \
+  (VOID)((!(exp)) ? \
     DbgPrint("%s(%d): Soft assertion failed\n   Expression: %s\n", __FILE__, __LINE__, #exp), FALSE : TRUE)
 
 #define RTL_SOFT_ASSERTMSG(msg, exp) \
@@ -5820,6 +5839,36 @@ KeAcquireSpinLockRaiseToDpc(
 #define RTL_SOFT_VERIFY(exp) RTL_SOFT_ASSERT(exp)
 #define RTL_SOFT_VERIFYMSG(msg, exp) RTL_SOFT_ASSERTMSG(msg, exp)
 
+#if defined(_MSC_VER)
+
+#define NT_ASSERT(exp) \
+   ((!(exp)) ? \
+      (__annotation(L"Debug", L"AssertFail", L#exp), \
+       DbgRaiseAssertionFailure(), FALSE) : TRUE)
+
+#define NT_ASSERTMSG(msg, exp) \
+   ((!(exp)) ? \
+      (__annotation(L"Debug", L"AssertFail", L##msg), \
+      DbgRaiseAssertionFailure(), FALSE) : TRUE)
+
+#define NT_ASSERTMSGW(msg, exp) \
+    ((!(exp)) ? \
+        (__annotation(L"Debug", L"AssertFail", msg), \
+         DbgRaiseAssertionFailure(), FALSE) : TRUE)
+
+#else
+
+//
+// GCC doesn't support __annotation (nor PDB)
+//
+#define NT_ASSERT(exp) \
+   (VOID)((!(exp)) ? (DbgRaiseAssertionFailure(), FALSE) : TRUE)
+
+#define NT_ASSERTMSG NT_ASSERT
+#define NT_ASSERTMSGW NT_ASSERT
+
+#endif
+
 #else /* !DBG */
 
 #define ASSERT(exp) ((VOID) 0)
@@ -5834,6 +5883,10 @@ KeAcquireSpinLockRaiseToDpc(
 #define RTL_SOFT_VERIFY(exp) ((exp) ? TRUE : FALSE)
 #define RTL_SOFT_VERIFYMSG(msg, exp) ((exp) ? TRUE : FALSE)
 
+#define NT_ASSERT(exp)     ((VOID)0)
+#define NT_ASSERTMSG(exp)  ((VOID)0)
+#define NT_ASSERTMSGW(exp) ((VOID)0)
+
 #endif /* DBG */
 
 /* HACK HACK HACK - GCC (or perhaps LD) is messing this up */
index 5970108..18908cc 100644 (file)
@@ -376,6 +376,19 @@ Author:
 #define CONTEXT_FLOAT_SAVE_STATUS_WORD          CONTEXT_FLOAT_SAVE + FP_STATUS_WORD
 #define CONTEXT_FLOAT_SAVE_TAG_WORD             CONTEXT_FLOAT_SAVE + FP_TAG_WORD
 #define CONTEXT_ALIGNED_SIZE                    0x2CC
+#define CONTEXT_FRAME_LENGTH                    0x2D0
+
+//
+// CONTEXT Flags
+//
+#ifdef __ASM__
+#define CONTEXT_CONTROL                         0x10001
+#define CONTEXT_INTEGER                         0x10002
+#define CONTEXT_SEGMENTS                        0x10004
+#define CONTEXT_FLOATING_POINT                  0x10008
+#define CONTEXT_DEBUG_REGISTERS                 0x10010
+#define CONTEXT_FULL                            0x10007
+#endif
 
 //
 // EXCEPTION_RECORD Offsets
@@ -527,7 +540,6 @@ Author:
 // NTSTATUS, Bugcheck Codes and Debug Codes
 //
 #ifdef __ASM__
-#define STATUS_SUCCESS                          0x00000000
 #define STATUS_ACCESS_VIOLATION                 0xC0000005
 #define STATUS_IN_PAGE_ERROR                    0xC0000006
 #define STATUS_GUARD_PAGE_VIOLATION             0x80000001
@@ -553,6 +565,7 @@ Author:
 #define STATUS_FLOAT_UNDERFLOW                  0xC0000093
 #define STATUS_FLOAT_MULTIPLE_FAULTS            0xC00002B4
 #define STATUS_FLOAT_MULTIPLE_TRAPS             0xC00002B5
+#define STATUS_ASSERTION_FAILURE                0xC0000420
 #define APC_INDEX_MISMATCH                      0x01
 #define IRQL_NOT_GREATER_OR_EQUAL               0x09
 #define IRQL_NOT_LESS_OR_EQUAL                  0x0A
@@ -564,6 +577,11 @@ Author:
 #define HARDWARE_INTERRUPT_STORM                0xF2
 #define DBG_STATUS_CONTROL_C                    0x01
 
+//
+// DebugService Control Types
+//
+#define BREAKPOINT_BREAK                        0x0
+
 //
 // IRQL Levels
 //
diff --git a/reactos/lib/rtl/assert.c b/reactos/lib/rtl/assert.c
new file mode 100644 (file)
index 0000000..faa65ba
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * COPYRIGHT:         See COPYING in the top level directory
+ * PROJECT:           ReactOS Run-Time Library
+ * PURPOSE:           Implements RtlAssert used by the ASSERT
+ *                    and ASSERTMSG debugging macros
+ * FILE:              lib/rtl/assert.c
+ * PROGRAMERS:        Stefan Ginsberg (stefan.ginsberg@reactos.org)
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <rtl.h>
+#define NDEBUG
+#include <debug.h>
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+RtlAssert(IN PVOID FailedAssertion,
+          IN PVOID FileName,
+          IN ULONG LineNumber,
+          IN PCHAR Message OPTIONAL)
+{
+#if 0 // Disabled until sysreg can handle debug prompts
+    CHAR Action[2];
+    CONTEXT Context;
+
+    /* Capture caller's context for the debugger */
+    RtlCaptureContext(&Context);
+
+    /* Enter prompt loop */
+    for (;;)
+    {
+        /* Print the assertion */
+        DbgPrint("\n*** Assertion failed: %s%s\n"
+                 "***   Source File: %s, line %ld\n\n",
+                 Message != NULL ? Message : "",
+                 (PSTR)FailedAssertion,
+                 (PSTR)FileName,
+                 LineNumber);
+
+        /* Prompt for action */
+        DbgPrompt("Break repeatedly, break Once, Ignore,"
+                  " terminate Process or terminate Thread (boipt)? ",
+                  Action,
+                  sizeof(Action));
+        switch (Action[0])
+        {
+            /* Break repeatedly */
+            case 'B': case 'b':
+
+                /* Do a breakpoint, then prompt again */
+                DbgPrint("Execute '.cxr %p' to dump context\n", &Context);
+                DbgBreakPoint();
+                break;
+
+            /* Ignore */
+            case 'I': case 'i':
+
+                /* Return to caller */
+                return;
+
+            /* Break once */
+            case 'O': case 'o':
+
+                /* Do a breakpoint and return */
+                DbgPrint("Execute '.cxr %p' to dump context\n", &Context);
+                DbgBreakPoint();
+                return;
+
+            /* Terminate process*/
+            case 'P': case 'p':
+
+                /* Terminate us */
+                ZwTerminateProcess(ZwCurrentProcess(), STATUS_UNSUCCESSFUL);
+                break;
+
+            /* Terminate thread */
+            case 'T': case 't':
+
+                /* Terminate us */
+                ZwTerminateThread(ZwCurrentThread(), STATUS_UNSUCCESSFUL);
+                break;
+
+            /* Unrecognized */
+            default:
+
+                /* Prompt again */
+                break;
+        }
+    }
+
+    /* Shouldn't get here */
+    DbgBreakPoint();
+    ZwTerminateProcess(ZwCurrentProcess(), STATUS_UNSUCCESSFUL);
+#else
+   if (NULL != Message)
+   {
+      DbgPrint("Assertion \'%s\' failed at %s line %d: %s\n",
+               (PCHAR)FailedAssertion,
+               (PCHAR)FileName,
+               LineNumber,
+               Message);
+   }
+   else
+   {
+      DbgPrint("Assertion \'%s\' failed at %s line %d\n",
+               (PCHAR)FailedAssertion,
+               (PCHAR)FileName,
+               LineNumber);
+   }
+
+   DbgBreakPoint();
+#endif
+}
index 7c42ebc..1ba40c7 100644 (file)
@@ -22,7 +22,7 @@ DebugPrint(IN PANSI_STRING DebugString,
            IN ULONG ComponentId,
            IN ULONG Level)
 {
-    /* Call the INT2D Service */
+    /* Call the Debug Service */
     return DebugService(BREAKPOINT_PRINT,
                         DebugString->Buffer,
                         DebugString->Length,
@@ -35,7 +35,7 @@ NTAPI
 DebugPrompt(IN PCSTRING Output,
             IN PSTRING Input)
 {
-    /* Call the INT2D Service */
+    /* Call the Debug Service */
     return DebugService(BREAKPOINT_PROMPT,
                         Output->Buffer,
                         Output->Length,
@@ -115,7 +115,7 @@ vDbgPrintExWithPrefixInternal(IN LPCSTR Prefix,
     DebugString.Buffer = Buffer;
 
     /* First, let the debugger know as well */
-    if (RtlpCheckForActiveDebugger(FALSE))
+    if (RtlpCheckForActiveDebugger())
     {
         /* Fill out an exception record */
         ExceptionRecord.ExceptionCode = DBG_PRINTEXCEPTION_C;
index f81254e..ce35919 100644 (file)
@@ -809,35 +809,6 @@ static const ERROR_TABLE ErrorTable[] =
 
 /* FUNCTIONS ***************************************************************/
 
-/*
- * @implemented
- */
-VOID
-NTAPI
-RtlAssert(PVOID FailedAssertion,
-          PVOID FileName,
-          ULONG LineNumber,
-          PCHAR Message)
-{
-   if (NULL != Message)
-   {
-      DbgPrint("Assertion \'%s\' failed at %s line %d: %s\n",
-               (PCHAR)FailedAssertion,
-               (PCHAR)FileName,
-               LineNumber,
-               Message);
-   }
-   else
-   {
-      DbgPrint("Assertion \'%s\' failed at %s line %d\n",
-               (PCHAR)FailedAssertion,
-               (PCHAR)FileName,
-               LineNumber);
-   }
-
-   DbgBreakPoint();
-}
-
 /*
 * @unimplemented
 */
index 15c1fe8..d4462e3 100644 (file)
 
 /* FUNCTIONS ***************************************************************/
 
+#if !defined(_M_IX86)
+
 /*
  * @implemented
  */
 VOID
 NTAPI
-RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord)
+RtlRaiseException(IN PEXCEPTION_RECORD ExceptionRecord)
 {
     CONTEXT Context;
     NTSTATUS Status;
@@ -30,19 +32,14 @@ RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord)
     /* Capture the context */
     RtlCaptureContext(&Context);
 
-#ifdef _M_IX86
-    /* Fixup ESP */
-    Context.Esp += sizeof(ULONG);
-#endif
-
     /* Save the exception address */
-    ExceptionRecord->ExceptionAddress = RtlpGetExceptionAddress();
+    ExceptionRecord->ExceptionAddress = _ReturnAddress();
 
     /* Write the context flag */
     Context.ContextFlags = CONTEXT_FULL;
 
     /* Check if user mode debugger is active */
-    if (RtlpCheckForActiveDebugger(FALSE))
+    if (RtlpCheckForActiveDebugger())
     {
         /* Raise an exception immediately */
         Status = ZwRaiseException(ExceptionRecord, &Context, TRUE);
@@ -68,7 +65,7 @@ RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord)
 
 #ifdef _MSC_VER
 #pragma warning(push)
-#pragma warning(disable:4717)
+#pragma warning(disable:4717) // RtlRaiseStatus is recursive by design
 #endif
 
 /*
@@ -76,7 +73,7 @@ RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord)
  */
 VOID
 NTAPI
-RtlRaiseStatus(NTSTATUS Status)
+RtlRaiseStatus(IN NTSTATUS Status)
 {
     EXCEPTION_RECORD ExceptionRecord;
     CONTEXT Context;
@@ -84,13 +81,8 @@ RtlRaiseStatus(NTSTATUS Status)
      /* Capture the context */
     RtlCaptureContext(&Context);
 
-#ifdef _M_IX86
-    /* Add one argument to ESP */
-    Context.Esp += sizeof(PVOID);
-#endif
-
     /* Create an exception record */
-    ExceptionRecord.ExceptionAddress = RtlpGetExceptionAddress();
+    ExceptionRecord.ExceptionAddress = _ReturnAddress();
     ExceptionRecord.ExceptionCode  = Status;
     ExceptionRecord.ExceptionRecord = NULL;
     ExceptionRecord.NumberParameters = 0;
@@ -100,7 +92,7 @@ RtlRaiseStatus(NTSTATUS Status)
     Context.ContextFlags = CONTEXT_FULL;
 
     /* Check if user mode debugger is active */
-    if (RtlpCheckForActiveDebugger(FALSE))
+    if (RtlpCheckForActiveDebugger())
     {
         /* Raise an exception immediately */
         ZwRaiseException(&ExceptionRecord, &Context, TRUE);
@@ -122,6 +114,8 @@ RtlRaiseStatus(NTSTATUS Status)
 #pragma warning(pop)
 #endif
 
+#endif
+
 /*
  * @implemented
  */
index 0b5d151..66a9d81 100644 (file)
@@ -235,7 +235,7 @@ RtlUnwind(IN PVOID TargetFrame OPTIONAL,
         ExceptionRecord3.ExceptionFlags = 0;
         ExceptionRecord3.ExceptionCode = STATUS_UNWIND;
         ExceptionRecord3.ExceptionRecord = NULL;
-        ExceptionRecord3.ExceptionAddress = RtlpGetExceptionAddress();
+        ExceptionRecord3.ExceptionAddress = _ReturnAddress();
         ExceptionRecord3.NumberParameters = 0;
     }
 
index ed20db1..9b2f856 100644 (file)
@@ -4,6 +4,7 @@
  * FILE:            lib/rtl/i386/except_asm.S
  * PURPOSE:         User-mode exception support for IA-32
  * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
+ *                  Stefan Ginsberg (stefan.ginsberg@reactos.org)
  */
 
 /* INCLUDES ******************************************************************/
@@ -41,17 +42,6 @@ _RtlpSetExceptionList@4:
     ret 4
 .endfunc
 
-.func RtlpGetExceptionAddress@0
-.globl _RtlpGetExceptionAddress@0
-_RtlpGetExceptionAddress@0:
-
-    /* Return the address from the stack */
-    mov eax, [ebp+4]
-
-    /* Return */
-    ret
-.endfunc
-
 .func RtlCaptureContext@4
 .globl _RtlCaptureContext@4
 _RtlCaptureContext@4:
@@ -262,3 +252,150 @@ _RtlpUnwindProtector:
     ret 16
 .endfunc
 
+.func RtlRaiseException@4
+.globl _RtlRaiseException@4
+_RtlRaiseException@4:
+
+    /* Set up stack frame */
+    push ebp
+    mov ebp, esp
+
+    /*
+     * Save the context while preserving everything but ESP and EBP.
+     * This is vital because the caller will be restored with this context
+     * in case the execution is continued, which means we must not clobber
+     * the non-volatiles. We preserve the volatiles too because the context
+     * could get passed to a debugger.
+     */
+    lea esp, [esp-CONTEXT_FRAME_LENGTH]
+    push esp
+    call _RtlCaptureContext@4
+
+    /* Adjust ESP to account for the argument that was passed */
+    add dword ptr [esp+CONTEXT_ESP], 4
+
+    /* Save the exception address */
+    mov edx, [ebp+4]
+    mov eax, [ebp+8]
+    mov [eax+EXCEPTION_RECORD_EXCEPTION_ADDRESS], edx
+
+    /* Write the context flag */
+    mov dword ptr [esp+CONTEXT_FLAGS], CONTEXT_FULL
+
+    /* Check if user mode debugger is active */
+    call _RtlpCheckForActiveDebugger@0
+    test al, al
+    jnz DebuggerActive1
+
+    /* Dispatch the exception */
+    push esp
+    push [ebp+8]
+    call _RtlDispatchException@8
+    test al, al
+    jz RaiseException
+
+    /* Continue, go back to previous context */
+    mov ecx, esp
+    push 0
+    push ecx
+    call  _ZwContinue@8
+    jmp RaiseStatus1
+
+DebuggerActive1:
+
+    /* Raise an exception immediately */
+    mov ecx, esp
+    push 1
+    push ecx
+    push [ebp+8]
+    call _ZwRaiseException@12
+    jmp RaiseStatus1
+
+RaiseException:
+
+    /* Raise the exception */
+    mov ecx, esp
+    push 0
+    push ecx
+    push [ebp+8]
+    call _ZwRaiseException@12
+
+RaiseStatus1:
+
+    /* If we returned, raise a status */
+    push eax
+    call _RtlRaiseStatus@4
+.endfunc
+
+.func RtlRaiseStatus@4
+.globl _RtlRaiseStatus@4
+_RtlRaiseStatus@4:
+
+    /* Set up stack frame */
+    push ebp
+    mov ebp, esp
+
+    /*
+     * Save the context while preserving everything but ESP and EBP.
+     * This is vital because the caller will be restored with this context
+     * in case the execution is continued, which means we must not clobber
+     * the non-volatiles. We preserve the volatiles too because the context
+     * could get passed to a debugger.
+     */
+    lea esp, [esp-CONTEXT_FRAME_LENGTH-EXCEPTION_RECORD_LENGTH]
+    push esp
+    call _RtlCaptureContext@4
+
+    /* Adjust ESP to account for the argument that was passed */
+    add dword ptr [esp+CONTEXT_ESP], 4
+
+    /* Set up the exception record */
+    lea ecx, [esp+CONTEXT_FRAME_LENGTH]
+    mov eax, [ebp+8]
+    mov dword ptr [ecx+EXCEPTION_RECORD_EXCEPTION_CODE], eax
+    mov dword ptr [ecx+EXCEPTION_RECORD_EXCEPTION_FLAGS], EXCEPTION_NONCONTINUABLE
+    and dword ptr [ecx+EXCEPTION_RECORD_EXCEPTION_RECORD], 0
+    mov eax, [ebp+4]
+    mov dword ptr [ecx+EXCEPTION_RECORD_EXCEPTION_ADDRESS], eax
+    and dword ptr [ecx+EXCEPTION_RECORD_NUMBER_PARAMETERS], 0
+
+    /* Write the context flag */
+    mov dword ptr [esp+CONTEXT_FLAGS], CONTEXT_FULL
+
+    /* Check if user mode debugger is active */
+    call _RtlpCheckForActiveDebugger@0
+
+    /* Restore ECX and jump if debugger is active */
+    lea ecx, [esp+CONTEXT_FRAME_LENGTH]
+    test al, al
+    jnz DebuggerActive2
+
+    /* Dispatch the exception */
+    push esp
+    push ecx
+    call _RtlDispatchException@8
+
+    /* Raise exception if we got here */
+    lea ecx, [esp+CONTEXT_FRAME_LENGTH]
+    mov edx, esp
+    push 0
+    push edx
+    push ecx
+    call _ZwRaiseException@12
+    jmp RaiseStatus2
+
+DebuggerActive2:
+
+    /* Raise an exception immediately */
+    mov edx, esp
+    push 1
+    push edx
+    push ecx
+    call _ZwRaiseException@12
+
+RaiseStatus2:
+
+    /* If we returned, raise a status */
+    push eax
+    call _RtlRaiseStatus@4
+.endfunc
index 5b6bce3..817ba30 100644 (file)
@@ -34,14 +34,6 @@ RtlDispatchException
     return TRUE;
 }
 
-NTSYSAPI
-PVOID
-RtlpGetExceptionAddress()
-{
-    // XXX arty fixme
-    return NULL;
-}
-
 VOID
 NTAPI
 RtlUnwind(IN PVOID TargetFrame OPTIONAL,
index e4aed9b..6468203 100644 (file)
@@ -43,6 +43,7 @@
        <file>access.c</file>
        <file>acl.c</file>
        <file>actctx.c</file>
+       <file>assert.c</file>
        <file>atom.c</file>
        <file>bitmap.c</file>
        <file>bootdata.c</file>
index ea0114d..e0f2436 100644 (file)
@@ -100,7 +100,7 @@ RtlLeaveHeapLock(PRTL_CRITICAL_SECTION CriticalSection);
 
 BOOLEAN
 NTAPI
-RtlpCheckForActiveDebugger(BOOLEAN Type);
+RtlpCheckForActiveDebugger(VOID);
 
 BOOLEAN
 NTAPI
@@ -141,10 +141,6 @@ RtlpCheckLogException(IN PEXCEPTION_RECORD ExceptionRecord,
                       IN PVOID ContextData,
                       IN ULONG Size);
 
-PVOID
-NTAPI
-RtlpGetExceptionAddress(VOID);
-
 VOID
 NTAPI
 RtlpCaptureContext(OUT PCONTEXT ContextRecord);
index d42ffb3..256d66c 100644 (file)
@@ -208,6 +208,15 @@ KdpPrintString(
     LPSTR String,
     ULONG Length);
 
+ULONG
+NTAPI
+KdpPrompt(
+    IN LPSTR InString,
+    IN USHORT InStringLength,
+    OUT LPSTR OutString,
+    IN USHORT OutStringLength
+);
+
 BOOLEAN
 NTAPI
 KdpDetectConflicts(PCM_RESOURCE_LIST DriverList);
index 5961bd4..fb193a4 100644 (file)
@@ -201,13 +201,13 @@ KdpPrint(
     OUT PBOOLEAN Status
 );
 
-BOOLEAN
+USHORT
 NTAPI
 KdpPrompt(
-    IN LPSTR InString,
-    IN USHORT InStringLength,
-    OUT LPSTR OutString,
-    IN USHORT OutStringLength,
+    IN LPSTR PromptString,
+    IN USHORT PromptLength,
+    OUT LPSTR ResponseString,
+    IN USHORT MaximumResponseLength,
     IN KPROCESSOR_MODE PreviousMode,
     IN PKTRAP_FRAME TrapFrame,
     IN PKEXCEPTION_FRAME ExceptionFrame
index 5c22935..791be4e 100644 (file)
@@ -113,7 +113,8 @@ KdpEnterDebuggerException(IN PKTRAP_FRAME TrapFrame,
         ((ExceptionCommand == BREAKPOINT_LOAD_SYMBOLS) ||
          (ExceptionCommand == BREAKPOINT_UNLOAD_SYMBOLS) ||
          (ExceptionCommand == BREAKPOINT_COMMAND_STRING) ||
-         (ExceptionCommand == BREAKPOINT_PRINT)))
+         (ExceptionCommand == BREAKPOINT_PRINT) ||
+         (ExceptionCommand == BREAKPOINT_PROMPT)))
     {
         /* Check if this is a debug print */
         if (ExceptionCommand == BREAKPOINT_PRINT)
@@ -126,22 +127,57 @@ KdpEnterDebuggerException(IN PKTRAP_FRAME TrapFrame,
             /* Return success */
             KeSetContextReturnRegister(Context, STATUS_SUCCESS);
         }
+#ifdef KDBG
         else if (ExceptionCommand == BREAKPOINT_LOAD_SYMBOLS)
         {
-#ifdef KDBG
             PLDR_DATA_TABLE_ENTRY LdrEntry;
 
             /* Load symbols. Currently implemented only for KDBG! */
             if(KdbpSymFindModule(((PKD_SYMBOLS_INFO)ExceptionRecord->ExceptionInformation[2])->BaseOfDll, NULL, -1, &LdrEntry))
                 KdbSymProcessSymbols(LdrEntry);
-#endif
         }
+        else if (ExceptionCommand == BREAKPOINT_PROMPT)
+        {
+            ULONG ReturnValue;
+            LPSTR OutString;
+            USHORT OutStringLength;
+
+            /* Get the response string  and length */
+            OutString = (LPSTR)Context->Ebx;
+            OutStringLength = (USHORT)Context->Edi;
+
+            /* Call KDBG */
+            ReturnValue = KdpPrompt((LPSTR)ExceptionRecord->
+                                    ExceptionInformation[1],
+                                    (USHORT)ExceptionRecord->
+                                    ExceptionInformation[2],
+                                    OutString,
+                                    OutStringLength);
+
+            /* Return the number of characters that we received */
+            Context->Eax = ReturnValue;
+        }
+#endif
 
         /* This we can handle: simply bump the Program Counter */
         KeSetContextPc(Context, KeGetContextPc(Context) + KD_BREAKPOINT_SIZE);
         return TRUE;
     }
 
+#ifdef KDBG
+    /* Check if this is an assertion failure */
+    if (ExceptionRecord->ExceptionCode == STATUS_ASSERTION_FAILURE)
+    {
+        /* Warn about it */
+        DbgPrint("\n!!! Assertion Failure at Address 0x%p !!!\n\n",
+                 (PVOID)Context->Eip);
+
+        /* Bump EIP to the instruction following the int 2C and return */
+        Context->Eip += 2;
+        return TRUE;
+    }
+#endif
+
     /* Get out of here if the Debugger isn't connected */
     if (KdDebuggerNotPresent) return FALSE;
 
index 5777388..b232a02 100644 (file)
@@ -3,7 +3,8 @@
  * LICENSE:         GPL - See COPYING in the top level directory
  * FILE:            ntoskrnl/kd64/i386/kdsup.c
  * PURPOSE:         KD support routines for x86
- * PROGRAMMERS:     Stefan Ginsberg (stefan.ginsberg@reactos.org)
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+ *                  Stefan Ginsberg (stefan.ginsberg@reactos.org)
  */
 
 /* INCLUDES *****************************************************************/
index a68e43b..329fec5 100644 (file)
@@ -4,6 +4,7 @@
  * FILE:            ntoskrnl/kd64/kdapi.c
  * PURPOSE:         KD64 Public Routines and Internal Support
  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+ *                  Stefan Ginsberg (stefan.ginsberg@reactos.org)
  */
 
 /* INCLUDES ******************************************************************/
index 2583623..48c2cca 100644 (file)
@@ -4,6 +4,7 @@
  * FILE:            ntoskrnl/kd64/kdbreak.c
  * PURPOSE:         KD64 Breakpoint Support
  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+ *                  Stefan Ginsberg (stefan.ginsberg@reactos.org)
  */
 
 /* INCLUDES ******************************************************************/
index e5c487c..8139564 100644 (file)
@@ -4,6 +4,7 @@
  * FILE:            ntoskrnl/kd64/kdinit.c
  * PURPOSE:         KD64 Initialization Code
  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+ *                  Stefan Ginsberg (stefan.ginsberg@reactos.org)
  */
 
 /* INCLUDES ******************************************************************/
index 8892358..3523efd 100644 (file)
@@ -4,6 +4,7 @@
  * FILE:            ntoskrnl/kd64/kdprint.c
  * PURPOSE:         KD64 Trap Handler Routines
  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+ *                  Stefan Ginsberg (stefan.ginsberg@reactos.org)
  */
 
 /* INCLUDES ******************************************************************/
@@ -51,6 +52,75 @@ KdpPrintString(IN PSTRING Output)
     return KdpPollBreakInWithPortLock();
 }
 
+BOOLEAN
+NTAPI
+KdpPromptString(IN PSTRING PromptString,
+                IN PSTRING ResponseString)
+{
+    STRING Data, Header;
+    DBGKD_DEBUG_IO DebugIo;
+    ULONG Length = PromptString->Length;
+    KDSTATUS Status;
+
+    /* Copy the string to the message buffer */
+    RtlCopyMemory(KdpMessageBuffer,
+                  PromptString->Buffer,
+                  PromptString->Length);
+
+    /* Make sure we don't exceed the KD Packet size */
+    if ((sizeof(DBGKD_DEBUG_IO) + Length) > PACKET_MAX_SIZE)
+    {
+        /* Normalize length */
+        Length = PACKET_MAX_SIZE - sizeof(DBGKD_DEBUG_IO);
+    }
+
+    /* Build the packet header */
+    DebugIo.ApiNumber = DbgKdGetStringApi;
+    DebugIo.ProcessorLevel = KeProcessorLevel;
+    DebugIo.Processor = KeGetCurrentPrcb()->Number;
+    DebugIo.u.GetString.LengthOfPromptString = Length;
+    DebugIo.u.GetString.LengthOfStringRead = ResponseString->MaximumLength;
+    Header.Length = sizeof(DBGKD_DEBUG_IO);
+    Header.Buffer = (PCHAR)&DebugIo;
+
+    /* Build the data */
+    Data.Length = PromptString->Length;
+    Data.Buffer = KdpMessageBuffer;
+
+    /* Send the packet */
+    KdSendPacket(PACKET_TYPE_KD_DEBUG_IO, &Header, &Data, &KdpContext);
+
+    /* Set the maximum lengths for the receive */
+    Header.MaximumLength = sizeof(DBGKD_DEBUG_IO);
+    Data.MaximumLength = sizeof(KdpMessageBuffer);
+
+    /* Enter receive loop */
+    do
+    {
+        /* Get our reply */
+        Status = KdReceivePacket(PACKET_TYPE_KD_DEBUG_IO,
+                                 &Header,
+                                 &Data,
+                                 &Length,
+                                 &KdpContext);
+
+        /* Return TRUE if we need to resend */
+        if (Status == KdPacketNeedsResend) return TRUE;
+
+    /* Loop until we succeed */
+    } while (Status != KdPacketReceived);
+
+    /* Don't copy back a larger respone than there is room foor */
+    Length = min(Length, ResponseString->MaximumLength);
+
+    /* Copy back the string and return the length */
+    RtlCopyMemory(ResponseString->Buffer, KdpMessageBuffer, Length);
+    ResponseString->Length = Length;
+
+    /* Success; we don't need to resend */
+    return FALSE;
+}
+
 VOID
 NTAPI
 KdpCommandString(IN ULONG Length,
@@ -108,20 +178,56 @@ KdpSymbol(IN PSTRING DllPath,
     KdExitDebugger(Entered);
 }
 
-BOOLEAN
+USHORT
 NTAPI
-KdpPrompt(IN LPSTR InString,
-          IN USHORT InStringLength,
-          OUT LPSTR OutString,
-          IN USHORT OutStringLength,
+KdpPrompt(IN LPSTR PromptString,
+          IN USHORT PromptLength,
+          OUT LPSTR ResponseString,
+          IN USHORT MaximumResponseLength,
           IN KPROCESSOR_MODE PreviousMode,
           IN PKTRAP_FRAME TrapFrame,
           IN PKEXCEPTION_FRAME ExceptionFrame)
 {
-    /* FIXME */
-    KdpDprintf("KdpPrompt called\n");
-    while (TRUE);
-    return FALSE;
+    STRING PromptBuffer, ResponseBuffer;
+    BOOLEAN Entered, Resend;
+
+    /* Normalize the lengths */
+    PromptLength = min(PromptLength, 512);
+    MaximumResponseLength = min(MaximumResponseLength, 512);
+
+    /* Check if we need to verify the string */
+    if (PreviousMode != KernelMode)
+    {
+        /* FIXME: Handle user-mode */
+    }
+
+    /* Setup the prompt and response  buffers */
+    PromptBuffer.Buffer = PromptString;
+    PromptBuffer.Length = PromptLength;
+    ResponseBuffer.Buffer = ResponseString;
+    ResponseBuffer.Length = 0;
+    ResponseBuffer.MaximumLength = MaximumResponseLength;
+
+    /* Log the print */
+    //KdLogDbgPrint(&PromptBuffer);
+
+    /* Enter the debugger */
+    Entered = KdEnterDebugger(TrapFrame, ExceptionFrame);
+
+    /* Enter prompt loop */
+    do
+    {
+        /* Send the prompt and receive the response */
+        Resend = KdpPromptString(&PromptBuffer, &ResponseBuffer);
+
+    /* Loop while we need to resend */
+    } while (Resend);
+
+    /* Exit the debugger */
+    KdExitDebugger(Entered);
+
+    /* Return the number of characters received */
+    return ResponseBuffer.Length;
 }
 
 NTSTATUS
index 409b2e9..aed14be 100644 (file)
@@ -4,6 +4,7 @@
  * FILE:            ntoskrnl/kd64/kdtrap.c
  * PURPOSE:         KD64 Trap Handlers
  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+ *                  Stefan Ginsberg (stefan.ginsberg@reactos.org)
  */
 
 /* INCLUDES ******************************************************************/
@@ -55,24 +56,41 @@ KdpReport(IN PKTRAP_FRAME TrapFrame,
     PKPRCB Prcb;
     NTSTATUS ExceptionCode = ExceptionRecord->ExceptionCode;
 
-    /* Check if this is single step or a breakpoint, or if we're forced to handle it */
+    /*
+     * Determine whether to pass the exception to the debugger.
+     * First, check if this is a "debug exception", meaning breakpoint
+     * (including debug service), single step and assertion failure exceptions.
+     */
     if ((ExceptionCode == STATUS_BREAKPOINT) ||
         (ExceptionCode == STATUS_SINGLE_STEP) ||
-        (ExceptionCode == STATUS_ASSERTION_FAILURE) ||
-        (NtGlobalFlag & FLG_STOP_ON_EXCEPTION))
+        (ExceptionCode == STATUS_ASSERTION_FAILURE))
     {
-        /* Check if we can't really handle this */
-        if ((SecondChanceException) ||
-            (ExceptionCode == STATUS_PORT_DISCONNECTED) ||
-            (NT_SUCCESS(ExceptionCode)))
+        /* This is a debug exception; we always pass them to the debugger */
+    }
+    else if (NtGlobalFlag & FLG_STOP_ON_EXCEPTION)
+    {
+        /*
+         * Not a debug exception, but the stop-on-exception flag is set,
+         * meaning the debugger requests that we pass it first chance
+         * exceptions. However, some exceptions are always passed to the
+         * exception handler first, namely exceptions with a code that isn't
+         * an error or warning code, and also exceptions with the special
+         * STATUS_PORT_DISCONNECTED code (an error code).
+         */
+        if ((SecondChanceException == FALSE) &&
+            ((ExceptionCode == STATUS_PORT_DISCONNECTED) ||
+             (NT_SUCCESS(ExceptionCode))))
         {
-            /* Return false to have someone else take care of the exception */
+            /* Let the exception handler, if any, try to handle it */
             return FALSE;
         }
     }
-    else if (SecondChanceException)
+    else if (SecondChanceException == FALSE)
     {
-        /* We won't bother unless this is first chance */
+        /* 
+         * This isn't a debug exception and the stop-on-exception flag isn't
+         * set, so don't bother
+         */
         return FALSE;
     }
 
@@ -122,7 +140,8 @@ KdpTrap(IN PKTRAP_FRAME TrapFrame,
 
     /*
      * Check if we got a STATUS_BREAKPOINT with a SubID for Print, Prompt or
-     * Load/Unload symbols.
+     * Load/Unload symbols. Make sure it isn't a software breakpoints as those
+     * are handled by KdpReport.
      */
     if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
         (ExceptionRecord->ExceptionInformation[0] != BREAKPOINT_BREAK))
@@ -296,7 +315,10 @@ KdIsThisAKdTrap(IN PEXCEPTION_RECORD ExceptionRecord,
                 IN PCONTEXT Context,
                 IN KPROCESSOR_MODE PreviousMode)
 {
-    /* Check if this is a breakpoint or a valid debug service */
+    /*
+     * Determine if this is a valid debug service call and make sure that
+     * it isn't a software breakpoint
+     */
     if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
         (ExceptionRecord->NumberParameters > 0) &&
         (ExceptionRecord->ExceptionInformation[0] != BREAKPOINT_BREAK))
index a517f96..8c817f8 100644 (file)
@@ -2801,3 +2801,142 @@ KdbpCliInit()
 
     ExFreePool(FileBuffer);
 }
+
+VOID
+NTAPI
+KdpSerialDebugPrint(
+    LPSTR Message,
+    ULONG Length
+);
+
+STRING KdpPromptString = RTL_CONSTANT_STRING("kdb:> ");
+extern KSPIN_LOCK KdpSerialSpinLock;
+
+ULONG
+NTAPI
+KdpPrompt(IN LPSTR InString,
+          IN USHORT InStringLength,
+          OUT LPSTR OutString,
+          IN USHORT OutStringLength)
+{
+    USHORT i;
+    CHAR Response;
+    ULONG DummyScanCode;
+    KIRQL OldIrql;
+
+    /* Acquire the printing spinlock without waiting at raised IRQL */
+    while (TRUE)
+    {
+        /* Wait when the spinlock becomes available */
+        while (!KeTestSpinLock(&KdpSerialSpinLock));
+
+        /* Spinlock was free, raise IRQL */
+        KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+        /* Try to get the spinlock */
+        if (KeTryToAcquireSpinLockAtDpcLevel(&KdpSerialSpinLock))
+            break;
+
+        /* Someone else got the spinlock, lower IRQL back */
+        KeLowerIrql(OldIrql);
+    }
+
+    /* Loop the string to send */
+    for (i = 0; i < InStringLength; i++)
+    {
+        /* Print it to serial */
+        KdPortPutByteEx(&SerialPortInfo, *(PCHAR)(InString + i));
+    }
+
+    /* Print a new line for log neatness */
+    KdPortPutByteEx(&SerialPortInfo, '\r');
+    KdPortPutByteEx(&SerialPortInfo, '\n');
+
+    /* Print the kdb prompt */
+    for (i = 0; i < KdpPromptString.Length; i++)
+    {
+        /* Print it to serial */
+        KdPortPutByteEx(&SerialPortInfo,
+                        *(KdpPromptString.Buffer + i));
+    }
+
+    /* Loop the whole string */
+    for (i = 0; i < OutStringLength; i++)
+    {
+        /* Check if this is serial debugging mode */
+        if (KdbDebugState & KD_DEBUG_KDSERIAL)
+        {
+            /* Get the character from serial */
+            do
+            {
+                Response = KdbpTryGetCharSerial(MAXULONG);
+            } while (Response == -1);
+        }
+        else
+        {
+            /* Get the response from the keyboard */
+            do
+            {
+                Response = KdbpTryGetCharKeyboard(&DummyScanCode, MAXULONG);
+            } while (Response == -1);
+        }
+
+        /* Check for return */
+        if (Response == '\r')
+        {
+            /*
+             * We might need to discard the next '\n'.
+             * Wait a bit to make sure we receive it.
+             */
+            KeStallExecutionProcessor(100000);
+
+            /* Check the mode */
+            if (KdbDebugState & KD_DEBUG_KDSERIAL)
+            {
+                /* Read and discard the next character, if any */
+                KdbpTryGetCharSerial(5);
+            }
+            else
+            {
+                /* Read and discard the next character, if any */
+                KdbpTryGetCharKeyboard(&DummyScanCode, 5);
+            }
+
+            /* 
+             * Null terminate the output string -- documentation states that
+             * DbgPrompt does not null terminate, but it does
+             */
+            *(PCHAR)(OutString + i) = 0;
+
+            /* Print a new line */
+            KdPortPutByteEx(&SerialPortInfo, '\r');
+            KdPortPutByteEx(&SerialPortInfo, '\n');         
+
+            /* Release spinlock */
+            KiReleaseSpinLock(&KdpSerialSpinLock);
+
+            /* Lower IRQL back */
+            KeLowerIrql(OldIrql);
+
+            /* Return the length  */
+            return OutStringLength + 1;
+        }
+
+        /* Write it back and print it to the log */
+        *(PCHAR)(OutString + i) = Response;
+        KdPortPutByteEx(&SerialPortInfo, Response);
+    }
+
+    /* Print a new line */
+    KdPortPutByteEx(&SerialPortInfo, '\r');
+    KdPortPutByteEx(&SerialPortInfo, '\n');
+
+    /* Release spinlock */
+    KiReleaseSpinLock(&KdpSerialSpinLock);
+
+    /* Lower IRQL back */
+    KeLowerIrql(OldIrql);
+
+    /* Return the length  */
+    return OutStringLength;
+}
index 214b397..11b8f3a 100644 (file)
@@ -10,7 +10,6 @@ GENERATE_ARM_STUB _global_unwind2
 GENERATE_ARM_STUB _local_unwind2  
 GENERATE_ARM_STUB RtlGetCallersAddress 
 GENERATE_ARM_STUB RtlUnwind 
-GENERATE_ARM_STUB RtlpGetExceptionAddress
 GENERATE_ARM_STUB RtlDispatchException
 GENERATE_ARM_STUB RtlpGetStackLimits
 GENERATE_ARM_STUB DbgBreakPointWithStatus 
index 190855f..15a146e 100644 (file)
@@ -132,7 +132,6 @@ _KiTrapIoTable:
 
 _KiGetTickCount:
 _KiCallbackReturn:
-_KiRaiseAssertion:
     /* FIXME: TODO */
     UNHANDLED_PATH
 
@@ -461,6 +460,29 @@ AbiosExit:
     /* FIXME: TODO */
     UNHANDLED_PATH
 
+.func KiRaiseAssertion
+TRAP_FIXUPS kira_a, kira_t, DoFixupV86, DoFixupAbios
+_KiRaiseAssertion:
+
+    /* Push error code */
+    push 0
+
+    /* Enter trap */
+    TRAP_PROLOG kira_a, kira_t
+
+    /*
+     * Modify EIP so it points to the faulting instruction and set it as the
+     * exception address. Note that the 'int 2C' instruction used for this call
+     * is 2 bytes long as opposed to 1 byte 'int 3'.
+     */
+    sub dword ptr [ebp+KTRAP_FRAME_EIP], 2
+    mov ebx, [ebp+KTRAP_FRAME_EIP]
+
+    /* Raise an assertion failure */
+    mov eax, STATUS_ASSERTION_FAILURE
+    jmp _DispatchNoParam
+.endfunc
+
 .func KiDebugService
 TRAP_FIXUPS kids_a, kids_t, DoFixupV86, DoFixupAbios
 _KiDebugService:
@@ -780,8 +802,11 @@ _KiTrap3:
     /* Enter trap */
     TRAP_PROLOG kit3_a, kit3_t
 
-    /* Set status code */
-    mov eax, STATUS_SUCCESS
+    /*
+     * Set the special code to indicate that this is a software breakpoint
+     * and not a debug service call
+     */
+    mov eax, BREAKPOINT_BREAK
 
     /* Check for V86 */
 PrepareInt3:
index ced25c1..7e4ee49 100644 (file)
@@ -44,10 +44,10 @@ RtlInitializeRangeListPackage(VOID)
 
 BOOLEAN
 NTAPI
-RtlpCheckForActiveDebugger(BOOLEAN Type)
+RtlpCheckForActiveDebugger(VOID)
 {
     /* This check is meaningless in kernel-mode */
-    return Type;
+    return FALSE;
 }
 
 BOOLEAN