"Peter Oberndorfer" kumbayo84@arcor.de wrote:
I'm not fully sure if the fixup also happens for other architectures (i guess not) so this patch is more a RFC
@@ -336,6 +336,10 @@ static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL f if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED) return STATUS_SUCCESS;
/* fix up instruction pointer in context for EXCEPTION_BREAKPOINT */
if (rec->ExceptionCode == EXCEPTION_BREAKPOINT)
GET_IP(context) = (DWORD_PTR)GET_IP(context) - 1;
Gary Nebbett's book "Windows Nt/2000 Native API Reference" in the section C "Exceptions and Debugging" provides a pseudocode for KiDispatchException (page 439, Example C.1), and it does exactly the same thing as the patch above. *But* it does it as a very first thing after getting the context and before sending the debugger event.
On Monday 19 February 2007 09:37, Dmitry Timoshkov wrote:
"Peter Oberndorfer" kumbayo84@arcor.de wrote:
I'm not fully sure if the fixup also happens for other architectures (i guess not) so this patch is more a RFC
@@ -336,6 +336,10 @@ static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL f if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED) return STATUS_SUCCESS;
/* fix up instruction pointer in context for EXCEPTION_BREAKPOINT */
if (rec->ExceptionCode == EXCEPTION_BREAKPOINT)
GET_IP(context) = (DWORD_PTR)GET_IP(context) - 1;
Gary Nebbett's book "Windows Nt/2000 Native API Reference" in the section C "Exceptions and Debugging" provides a pseudocode for KiDispatchException (page 439, Example C.1), and it does exactly the same thing as the patch above. *But* it does it as a very first thing after getting the context and before sending the debugger event.
The strange thing is my testcase [patch 2/3] shows/(should show) that the debugger gets a unmodified eip for a first chance exception + if (de.u.Exception.dwFirstChance) + { + /* debugger gets first chance exception with unmodified ctx.Eip */ + ok((DWORD)ctx.Eip == (DWORD)code_mem_address + 0xb, "Eip at %x instead of 0x%x\n", + ctx.Eip, (DWORD)code_mem_address + 0xb);
and the modified one when the application did not handle the exception
+ else + { + /* debugger gets context after exception handler has played with it */ + /* ctx.Eip is the same value the exception handler got */ + if (de.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) + { + todo_wine{ + ok((DWORD)ctx.Eip == (DWORD)code_mem_address + 0xa, "Eip at %x instead of 0x%x\n", + ctx.Eip, (DWORD)code_mem_address + 0xa); + }
i tested this testcase on XP and 2K
Unfortunetely i don't own that book :-( Could you please verify in the pseudocode that the modified context gets sent to the debugger, and not some unmodified copy? Or maybe they unfix the context again in the send_to_debugger function ;-) Or the pseudo code is not fully correct.
Thanks, Greetings Peter
"Peter Oberndorfer" kumbayo84@arcor.de wrote:
The strange thing is my testcase [patch 2/3] shows/(should show) that the debugger gets a unmodified eip for a first chance exception
- if (de.u.Exception.dwFirstChance)
- {
- /* debugger gets first chance exception with unmodified ctx.Eip */
- ok((DWORD)ctx.Eip == (DWORD)code_mem_address + 0xb, "Eip at %x instead of 0x%x\n",
- ctx.Eip, (DWORD)code_mem_address + 0xb);
and the modified one when the application did not handle the exception
Could that be due to an error in your test?
Unfortunetely i don't own that book :-( Could you please verify in the pseudocode that the modified context gets sent to the debugger, and not some unmodified copy?
The pseudocode of KiDispatchException as the very first thing calls KeContextFromKframes and then unconditionally decrements context.Eip in the case of STATUS_BREAKPOINT.
Or maybe they unfix the context again in the send_to_debugger function ;-) Or the pseudo code is not fully correct.
That's a possibility, yes.