Alexandre Julliard : ntdll: Add debug registers to the context of all
exceptions.
Alexandre Julliard
julliard at wine.codeweavers.com
Fri Jan 13 07:31:20 CST 2006
Module: wine
Branch: refs/heads/master
Commit: 2878d9921669aaceb840ce460be4026f039076ec
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=2878d9921669aaceb840ce460be4026f039076ec
Author: Alexandre Julliard <julliard at winehq.org>
Date: Fri Jan 13 13:58:14 2006 +0100
ntdll: Add debug registers to the context of all exceptions.
Maintain a local cache of the debug registers to avoid server calls
where possible.
---
dlls/ntdll/ntdll_misc.h | 17 ++++++++++++++
dlls/ntdll/signal_i386.c | 47 ++++++++++++++++++++++++----------------
dlls/ntdll/thread.c | 33 ++++++++++++++++++++++++++--
include/wine/server_protocol.h | 3 ++-
include/winternl.h | 2 +-
server/protocol.def | 1 +
server/thread.c | 1 +
server/trace.c | 1 +
8 files changed, 81 insertions(+), 24 deletions(-)
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index ac9acae..c63b700 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -134,4 +134,21 @@ static inline struct ntdll_thread_data *
return (struct ntdll_thread_data *)NtCurrentTeb()->SystemReserved2;
}
+/* thread registers, stored in NtCurrentTeb()->SpareBytes1 */
+struct ntdll_thread_regs
+{
+ DWORD dr0; /* debug registers */
+ DWORD dr1;
+ DWORD dr2;
+ DWORD dr3;
+ DWORD dr6;
+ DWORD dr7;
+ DWORD spare[4]; /* change this if you add fields! */
+};
+
+static inline struct ntdll_thread_regs *ntdll_get_thread_regs(void)
+{
+ return (struct ntdll_thread_regs *)NtCurrentTeb()->SpareBytes1;
+}
+
#endif
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index be33458..1b2e8f0 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -740,7 +740,9 @@ inline static void restore_fpu( const CO
*/
inline static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext, WORD fs, WORD gs )
{
- context->ContextFlags = CONTEXT_FULL;
+ struct ntdll_thread_regs * const regs = ntdll_get_thread_regs();
+
+ context->ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
context->Eax = EAX_sig(sigcontext);
context->Ebx = EBX_sig(sigcontext);
context->Ecx = ECX_sig(sigcontext);
@@ -757,6 +759,12 @@ inline static void save_context( CONTEXT
context->SegFs = fs;
context->SegGs = gs;
context->SegSs = LOWORD(SS_sig(sigcontext));
+ context->Dr0 = regs->dr0;
+ context->Dr1 = regs->dr1;
+ context->Dr2 = regs->dr2;
+ context->Dr3 = regs->dr3;
+ context->Dr6 = regs->dr6;
+ context->Dr7 = regs->dr7;
}
@@ -767,6 +775,14 @@ inline static void save_context( CONTEXT
*/
inline static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
{
+ struct ntdll_thread_regs * const regs = ntdll_get_thread_regs();
+
+ regs->dr0 = context->Dr0;
+ regs->dr1 = context->Dr1;
+ regs->dr2 = context->Dr2;
+ regs->dr3 = context->Dr3;
+ regs->dr6 = context->Dr6;
+ regs->dr7 = context->Dr7;
EAX_sig(sigcontext) = context->Eax;
EBX_sig(sigcontext) = context->Ebx;
ECX_sig(sigcontext) = context->Ecx;
@@ -797,7 +813,7 @@ inline static void restore_context( cons
/***********************************************************************
* set_cpu_context
*
- * Set the new CPU context.
+ * Set the new CPU context. Used by NtSetContextThread.
*/
void set_cpu_context( const CONTEXT *context )
{
@@ -805,6 +821,16 @@ void set_cpu_context( const CONTEXT *con
if (flags & CONTEXT_FLOATING_POINT) restore_fpu( context );
+ if (flags & CONTEXT_DEBUG_REGISTERS)
+ {
+ struct ntdll_thread_regs * const regs = ntdll_get_thread_regs();
+ regs->dr0 = context->Dr0;
+ regs->dr1 = context->Dr1;
+ regs->dr2 = context->Dr2;
+ regs->dr3 = context->Dr3;
+ regs->dr6 = context->Dr6;
+ regs->dr7 = context->Dr7;
+ }
if (flags & CONTEXT_FULL)
{
if ((flags & CONTEXT_FULL) != (CONTEXT_FULL & ~CONTEXT_i386))
@@ -1027,8 +1053,6 @@ done:
*/
static void WINAPI raise_trap_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
{
- DWORD dr0, dr1, dr2, dr3, dr6, dr7;
-
if (rec->ExceptionCode == EXCEPTION_SINGLE_STEP)
{
if (context->EFlags & 0x100)
@@ -1048,22 +1072,7 @@ static void WINAPI raise_trap_exception(
}
}
- dr0 = context->Dr0;
- dr1 = context->Dr1;
- dr2 = context->Dr2;
- dr3 = context->Dr3;
- dr6 = context->Dr6;
- dr7 = context->Dr7;
-
__regs_RtlRaiseException( rec, context );
-
- context->ContextFlags = CONTEXT_FULL;
- if (dr0 != context->Dr0 || dr1 != context->Dr1 || dr2 != context->Dr2 ||
- dr3 != context->Dr3 || dr6 != context->Dr6 || dr7 != context->Dr7)
- {
- /* the debug registers have changed, set the new values */
- context->ContextFlags |= CONTEXT_DEBUG_REGISTERS;
- }
NtSetContextThread( GetCurrentThread(), context );
}
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index 9a2e2bd..d189bf7 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -294,6 +294,9 @@ NTSTATUS WINAPI RtlCreateUserThread( HAN
teb->ClientId.UniqueProcess = (HANDLE)GetCurrentProcessId();
teb->ClientId.UniqueThread = (HANDLE)tid;
+ /* inherit registers from parent thread */
+ memcpy( teb->SpareBytes1, ntdll_get_thread_regs(), sizeof(teb->SpareBytes1) );
+
thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
thread_data->request_fd = request_pipe[1];
@@ -495,8 +498,14 @@ NTSTATUS WINAPI NtSetContextThread( HAND
#ifdef __i386__
/* on i386 debug registers always require a server call */
- self = ((handle == GetCurrentThread()) &&
- !(context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386)));
+ self = (handle == GetCurrentThread());
+ if (self && (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386)))
+ {
+ struct ntdll_thread_regs * const regs = ntdll_get_thread_regs();
+ self = (regs->dr0 == context->Dr0 && regs->dr1 == context->Dr1 &&
+ regs->dr2 == context->Dr2 && regs->dr3 == context->Dr3 &&
+ regs->dr6 == context->Dr6 && regs->dr7 == context->Dr7);
+ }
#endif
if (!self)
@@ -781,6 +790,7 @@ NTSTATUS WINAPI NtGetContextThread( HAND
NTSTATUS ret;
CONTEXT ctx;
DWORD dummy, i;
+ BOOL self = FALSE;
SERVER_START_REQ( get_thread_context )
{
@@ -789,6 +799,7 @@ NTSTATUS WINAPI NtGetContextThread( HAND
req->suspend = 0;
wine_server_set_reply( req, &ctx, sizeof(ctx) );
ret = wine_server_call( req );
+ self = reply->self;
}
SERVER_END_REQ;
@@ -814,7 +825,23 @@ NTSTATUS WINAPI NtGetContextThread( HAND
}
}
- if (ret == STATUS_SUCCESS) copy_context( context, &ctx, context->ContextFlags );
+ if (ret == STATUS_SUCCESS)
+ {
+ copy_context( context, &ctx, context->ContextFlags );
+#ifdef __i386__
+ /* update the cached version of the debug registers */
+ if (self && (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386)))
+ {
+ struct ntdll_thread_regs * const regs = ntdll_get_thread_regs();
+ regs->dr0 = context->Dr0;
+ regs->dr1 = context->Dr1;
+ regs->dr2 = context->Dr2;
+ regs->dr3 = context->Dr3;
+ regs->dr6 = context->Dr6;
+ regs->dr7 = context->Dr7;
+ }
+#endif
+ }
else if (ret == STATUS_PENDING) ret = STATUS_ACCESS_DENIED;
return ret;
}
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 5f2ad9e..4ab1467 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -1990,6 +1990,7 @@ struct get_thread_context_request
struct get_thread_context_reply
{
struct reply_header __header;
+ int self;
/* VARARG(context,context); */
};
@@ -4348,6 +4349,6 @@ union generic_reply
struct query_symlink_reply query_symlink_reply;
};
-#define SERVER_PROTOCOL_VERSION 219
+#define SERVER_PROTOCOL_VERSION 220
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/include/winternl.h b/include/winternl.h
index 67403bb..a5a2e83 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -282,7 +282,7 @@ typedef struct _TEB
PVOID SystemReserved1[54]; /* 0cc used for kernel32 private data in Wine */
PVOID Spare1; /* 1a4 */
LONG ExceptionCode; /* 1a8 */
- BYTE SpareBytes1[40]; /* 1ac */
+ BYTE SpareBytes1[40]; /* 1ac used for ntdll private data in Wine */
PVOID SystemReserved2[10]; /* 1d4 used for ntdll private data in Wine */
GDI_TEB_BATCH GdiTebBatch; /* 1fc */
ULONG gdiRgn; /* 6dc */
diff --git a/server/protocol.def b/server/protocol.def
index 55aef19..d3878cb 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1432,6 +1432,7 @@ enum char_info_mode
unsigned int flags; /* context flags */
int suspend; /* if getting context during suspend */
@REPLY
+ int self; /* was it a handle to the current thread? */
VARARG(context,context); /* thread context */
@END
diff --git a/server/thread.c b/server/thread.c
index 3ffbf85..1c00ce7 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -1094,6 +1094,7 @@ DECL_HANDLER(get_thread_context)
memset( data, 0, sizeof(CONTEXT) );
get_thread_context( thread, data, req->flags );
}
+ reply->self = (thread == current);
release_object( thread );
}
diff --git a/server/trace.c b/server/trace.c
index 49ff25e..1aa964e 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1895,6 +1895,7 @@ static void dump_get_thread_context_requ
static void dump_get_thread_context_reply( const struct get_thread_context_reply *req )
{
+ fprintf( stderr, " self=%d,", req->self );
fprintf( stderr, " context=" );
dump_varargs_context( cur_size );
}
More information about the wine-cvs
mailing list