From: Stefan Ginsberg Date: Fri, 23 Oct 2009 22:51:39 +0000 (+0000) Subject: - Replace RtlpGetExceptionAddress by the _ReturnAddress intrinsic and add it to ARM... X-Git-Tag: ReactOS-0.3.11~331 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=10bbe664b7e449d9d641e5ce51e664ffa2f3ac34 - Replace RtlpGetExceptionAddress by the _ReturnAddress intrinsic and add it to ARM intrin.h as it was missing. - 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 --- diff --git a/reactos/dll/ntdll/dispatch/arm/stubs_asm.s b/reactos/dll/ntdll/dispatch/arm/stubs_asm.s index f11c598b951..d78a4749820 100644 --- a/reactos/dll/ntdll/dispatch/arm/stubs_asm.s +++ b/reactos/dll/ntdll/dispatch/arm/stubs_asm.s @@ -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 - diff --git a/reactos/dll/ntdll/rtl/libsupp.c b/reactos/dll/ntdll/rtl/libsupp.c index 1ef8c26c3ae..3c4e01bba64 100644 --- a/reactos/dll/ntdll/rtl/libsupp.c +++ b/reactos/dll/ntdll/rtl/libsupp.c @@ -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 diff --git a/reactos/include/crt/mingw32/intrin_arm.h b/reactos/include/crt/mingw32/intrin_arm.h index 3e788926cbb..066c641254f 100644 --- a/reactos/include/crt/mingw32/intrin_arm.h +++ b/reactos/include/crt/mingw32/intrin_arm.h @@ -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) diff --git a/reactos/include/ddk/winddk.h b/reactos/include/ddk/winddk.h index 928d4fa60d0..491d2ba8fea 100644 --- a/reactos/include/ddk/winddk.h +++ b/reactos/include/ddk/winddk.h @@ -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 */ diff --git a/reactos/include/ndk/i386/asm.h b/reactos/include/ndk/i386/asm.h index 597010889f6..18908cca4fe 100644 --- a/reactos/include/ndk/i386/asm.h +++ b/reactos/include/ndk/i386/asm.h @@ -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 index 00000000000..faa65ba1724 --- /dev/null +++ b/reactos/lib/rtl/assert.c @@ -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 +#define NDEBUG +#include + +/* 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 +} diff --git a/reactos/lib/rtl/debug.c b/reactos/lib/rtl/debug.c index 7c42ebca8f4..1ba40c70af9 100644 --- a/reactos/lib/rtl/debug.c +++ b/reactos/lib/rtl/debug.c @@ -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; diff --git a/reactos/lib/rtl/error.c b/reactos/lib/rtl/error.c index f81254e3af3..ce35919d6be 100644 --- a/reactos/lib/rtl/error.c +++ b/reactos/lib/rtl/error.c @@ -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 */ diff --git a/reactos/lib/rtl/exception.c b/reactos/lib/rtl/exception.c index 15c1fe8d306..d4462e32111 100644 --- a/reactos/lib/rtl/exception.c +++ b/reactos/lib/rtl/exception.c @@ -17,12 +17,14 @@ /* 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 */ diff --git a/reactos/lib/rtl/i386/except.c b/reactos/lib/rtl/i386/except.c index 0b5d151929e..66a9d810e80 100644 --- a/reactos/lib/rtl/i386/except.c +++ b/reactos/lib/rtl/i386/except.c @@ -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; } diff --git a/reactos/lib/rtl/i386/except_asm.s b/reactos/lib/rtl/i386/except_asm.s index ed20db17cc3..9b2f856c724 100644 --- a/reactos/lib/rtl/i386/except_asm.s +++ b/reactos/lib/rtl/i386/except_asm.s @@ -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 diff --git a/reactos/lib/rtl/powerpc/except.c b/reactos/lib/rtl/powerpc/except.c index 5b6bce3397d..817ba3086f4 100644 --- a/reactos/lib/rtl/powerpc/except.c +++ b/reactos/lib/rtl/powerpc/except.c @@ -34,14 +34,6 @@ RtlDispatchException return TRUE; } -NTSYSAPI -PVOID -RtlpGetExceptionAddress() -{ - // XXX arty fixme - return NULL; -} - VOID NTAPI RtlUnwind(IN PVOID TargetFrame OPTIONAL, diff --git a/reactos/lib/rtl/rtl.rbuild b/reactos/lib/rtl/rtl.rbuild index e4aed9b73f8..64682037507 100644 --- a/reactos/lib/rtl/rtl.rbuild +++ b/reactos/lib/rtl/rtl.rbuild @@ -43,6 +43,7 @@ access.c acl.c actctx.c + assert.c atom.c bitmap.c bootdata.c diff --git a/reactos/lib/rtl/rtlp.h b/reactos/lib/rtl/rtlp.h index ea0114d056a..e0f2436e8b6 100644 --- a/reactos/lib/rtl/rtlp.h +++ b/reactos/lib/rtl/rtlp.h @@ -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); diff --git a/reactos/ntoskrnl/include/internal/kd.h b/reactos/ntoskrnl/include/internal/kd.h index d42ffb359e4..256d66c7e75 100644 --- a/reactos/ntoskrnl/include/internal/kd.h +++ b/reactos/ntoskrnl/include/internal/kd.h @@ -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); diff --git a/reactos/ntoskrnl/include/internal/kd64.h b/reactos/ntoskrnl/include/internal/kd64.h index 5961bd42d1a..fb193a4b60e 100644 --- a/reactos/ntoskrnl/include/internal/kd64.h +++ b/reactos/ntoskrnl/include/internal/kd64.h @@ -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 diff --git a/reactos/ntoskrnl/kd/kdmain.c b/reactos/ntoskrnl/kd/kdmain.c index 5c22935d4b7..791be4e8326 100644 --- a/reactos/ntoskrnl/kd/kdmain.c +++ b/reactos/ntoskrnl/kd/kdmain.c @@ -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; diff --git a/reactos/ntoskrnl/kd64/i386/kdsup.c b/reactos/ntoskrnl/kd64/i386/kdsup.c index 5777388a43c..b232a023f9a 100644 --- a/reactos/ntoskrnl/kd64/i386/kdsup.c +++ b/reactos/ntoskrnl/kd64/i386/kdsup.c @@ -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 *****************************************************************/ diff --git a/reactos/ntoskrnl/kd64/kdapi.c b/reactos/ntoskrnl/kd64/kdapi.c index a68e43b7c91..329fec5de54 100644 --- a/reactos/ntoskrnl/kd64/kdapi.c +++ b/reactos/ntoskrnl/kd64/kdapi.c @@ -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 ******************************************************************/ diff --git a/reactos/ntoskrnl/kd64/kdbreak.c b/reactos/ntoskrnl/kd64/kdbreak.c index 2583623bf18..48c2ccad9aa 100644 --- a/reactos/ntoskrnl/kd64/kdbreak.c +++ b/reactos/ntoskrnl/kd64/kdbreak.c @@ -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 ******************************************************************/ diff --git a/reactos/ntoskrnl/kd64/kdinit.c b/reactos/ntoskrnl/kd64/kdinit.c index e5c487c8a3b..81395643710 100644 --- a/reactos/ntoskrnl/kd64/kdinit.c +++ b/reactos/ntoskrnl/kd64/kdinit.c @@ -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 ******************************************************************/ diff --git a/reactos/ntoskrnl/kd64/kdprint.c b/reactos/ntoskrnl/kd64/kdprint.c index 8892358ed5d..3523efdee2f 100644 --- a/reactos/ntoskrnl/kd64/kdprint.c +++ b/reactos/ntoskrnl/kd64/kdprint.c @@ -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 diff --git a/reactos/ntoskrnl/kd64/kdtrap.c b/reactos/ntoskrnl/kd64/kdtrap.c index 409b2e9a5bb..aed14beba55 100644 --- a/reactos/ntoskrnl/kd64/kdtrap.c +++ b/reactos/ntoskrnl/kd64/kdtrap.c @@ -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)) diff --git a/reactos/ntoskrnl/kdbg/kdb_cli.c b/reactos/ntoskrnl/kdbg/kdb_cli.c index a517f96de2a..8c817f889f5 100644 --- a/reactos/ntoskrnl/kdbg/kdb_cli.c +++ b/reactos/ntoskrnl/kdbg/kdb_cli.c @@ -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; +} diff --git a/reactos/ntoskrnl/ke/arm/stubs_asm.s b/reactos/ntoskrnl/ke/arm/stubs_asm.s index 214b3976085..11b8f3a9bc4 100644 --- a/reactos/ntoskrnl/ke/arm/stubs_asm.s +++ b/reactos/ntoskrnl/ke/arm/stubs_asm.s @@ -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 diff --git a/reactos/ntoskrnl/ke/i386/trap.s b/reactos/ntoskrnl/ke/i386/trap.s index 190855fe6c8..15a146e1012 100644 --- a/reactos/ntoskrnl/ke/i386/trap.s +++ b/reactos/ntoskrnl/ke/i386/trap.s @@ -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: diff --git a/reactos/ntoskrnl/rtl/libsupp.c b/reactos/ntoskrnl/rtl/libsupp.c index ced25c1bade..7e4ee49dcf4 100644 --- a/reactos/ntoskrnl/rtl/libsupp.c +++ b/reactos/ntoskrnl/rtl/libsupp.c @@ -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