Module: wine Branch: master Commit: e1d68b2e169580be8dc6f8927e01a19c60f79d65 URL: http://source.winehq.org/git/wine.git/?a=commit;h=e1d68b2e169580be8dc6f8927e...
Author: Sebastian Lackner sebastian@fds-team.de Date: Thu Feb 18 09:58:36 2016 +0100
ntdll: Implement handling of int $0x2d for x86_64.
Signed-off-by: Sebastian Lackner sebastian@fds-team.de Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ntdll/signal_x86_64.c | 53 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index 0c64541..be5a342 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -2170,6 +2170,17 @@ static EXCEPTION_RECORD *setup_exception( ucontext_t *sigcontext, raise_func fun }
+/*********************************************************************** + * get_exception_context + * + * Get a pointer to the context built by setup_exception. + */ +static inline CONTEXT *get_exception_context( EXCEPTION_RECORD *rec ) +{ + return (CONTEXT *)rec - 1; /* cf. stack_layout structure */ +} + + /********************************************************************** * find_function_info */ @@ -2513,9 +2524,20 @@ static void raise_segv_exception( EXCEPTION_RECORD *rec, CONTEXT *context ) set_cpu_context( context ); } break; + case EXCEPTION_BREAKPOINT: + switch (rec->ExceptionInformation[0]) + { + case 1: /* BREAKPOINT_PRINT */ + case 3: /* BREAKPOINT_LOAD_SYMBOLS */ + case 4: /* BREAKPOINT_UNLOAD_SYMBOLS */ + case 5: /* BREAKPOINT_COMMAND_STRING (>= Win2003) */ + goto done; + } + break; } status = raise_exception( rec, context, TRUE ); if (status) raise_status( status, rec ); +done: set_cpu_context( context ); }
@@ -2533,6 +2555,28 @@ static void raise_generic_exception( EXCEPTION_RECORD *rec, CONTEXT *context ) }
+/*********************************************************************** + * handle_interrupt + * + * Handle an interrupt. + */ +static inline BOOL handle_interrupt( unsigned int interrupt, EXCEPTION_RECORD *rec, CONTEXT *context ) +{ + switch(interrupt) + { + case 0x2d: + context->Rip += 3; + rec->ExceptionCode = EXCEPTION_BREAKPOINT; + rec->ExceptionAddress = (void *)context->Rip; + rec->NumberParameters = 1; + rec->ExceptionInformation[0] = context->Rax; + return TRUE; + default: + return FALSE; + } +} + + /********************************************************************** * segv_handler * @@ -2560,8 +2604,13 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext ) case TRAP_x86_SEGNPFLT: /* Segment not present exception */ case TRAP_x86_PROTFLT: /* General protection fault */ case TRAP_x86_UNKNOWN: /* Unknown fault code */ - rec->ExceptionCode = ERROR_sig(ucontext) ? EXCEPTION_ACCESS_VIOLATION : EXCEPTION_PRIV_INSTRUCTION; - rec->ExceptionCode = EXCEPTION_ACCESS_VIOLATION; + { + CONTEXT *win_context = get_exception_context( rec ); + WORD err = ERROR_sig(ucontext); + if ((err & 7) == 2 && handle_interrupt( err >> 3, rec, win_context )) break; + rec->ExceptionCode = err ? EXCEPTION_ACCESS_VIOLATION : EXCEPTION_PRIV_INSTRUCTION; + rec->ExceptionCode = EXCEPTION_ACCESS_VIOLATION; + } break; case TRAP_x86_PAGEFLT: /* Page fault */ rec->ExceptionCode = EXCEPTION_ACCESS_VIOLATION;