Commit 04a2917f authored by Paul Gofman's avatar Paul Gofman Committed by Alexandre Julliard

ntdll: Store exception reporting flags in server context.

parent 547d3a77
......@@ -247,7 +247,7 @@ static void check_context_exception_request_( DWORD flags, BOOL hardware_excepti
if (!(flags & CONTEXT_EXCEPTION_REPORTING)) return;
expected_flags |= hardware_exception ? CONTEXT_EXCEPTION_ACTIVE : CONTEXT_SERVICE_ACTIVE;
ok_(__FILE__, line)( (flags & exception_reporting_flags) == expected_flags, "got %#lx, expected %#lx.\n",
todo_wine ok_(__FILE__, line)( (flags & exception_reporting_flags) == expected_flags, "got %#lx, expected %#lx.\n",
flags, expected_flags );
}
#endif
......@@ -1120,7 +1120,7 @@ static void test_debugger(DWORD cont_status, BOOL with_WaitForDebugEventEx)
ctx.ContextFlags = CONTEXT_FULL | CONTEXT_EXTENDED_REGISTERS | CONTEXT_EXCEPTION_REQUEST;
status = pNtGetContextThread(pi.hThread, &ctx);
ok(!status, "NtGetContextThread failed with 0x%lx\n", status);
todo_wine ok(ctx.ContextFlags & CONTEXT_EXCEPTION_REPORTING
ok(ctx.ContextFlags & CONTEXT_EXCEPTION_REPORTING
|| broken( !(ctx.ContextFlags & CONTEXT_EXCEPTION_REPORTING) ) /* Win7 WoW64 */,
"got %#lx.\n", ctx.ContextFlags);
......@@ -3593,7 +3593,7 @@ static void test_debugger(DWORD cont_status, BOOL with_WaitForDebugEventEx)
ctx.ContextFlags = CONTEXT_FULL | CONTEXT_SEGMENTS | CONTEXT_EXCEPTION_REQUEST;
status = pNtGetContextThread(pi.hThread, &ctx);
ok(!status, "NtGetContextThread failed with 0x%lx\n", status);
todo_wine ok(ctx.ContextFlags & CONTEXT_EXCEPTION_REPORTING, "got %#lx.\n", ctx.ContextFlags);
ok(ctx.ContextFlags & CONTEXT_EXCEPTION_REPORTING, "got %#lx.\n", ctx.ContextFlags);
trace("exception 0x%lx at %p firstchance=%ld Rip=%p, Rax=%p\n",
de.u.Exception.ExceptionRecord.ExceptionCode,
......@@ -4356,7 +4356,7 @@ static void test_wow64_context(void)
ctx.ContextFlags = WOW64_CONTEXT_ALL | CONTEXT_EXCEPTION_REQUEST;
ret = pRtlWow64GetThreadContext( pi.hThread, &ctx );
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
todo_wine ok( (ctx.ContextFlags & CONTEXT_EXCEPTION_REPORTING) || broken( ctx.ContextFlags == WOW64_CONTEXT_ALL ) /*Win 7*/,
ok( (ctx.ContextFlags & CONTEXT_EXCEPTION_REPORTING) || broken( ctx.ContextFlags == WOW64_CONTEXT_ALL ) /*Win 7*/,
"got context flags %#lx\n", ctx.ContextFlags );
if (context.SegCs == cs32)
......@@ -4444,7 +4444,7 @@ static void test_wow64_context(void)
{
trace( "in 64-bit mode %04x\n", context.SegCs );
if (ctx.ContextFlags & CONTEXT_EXCEPTION_REPORTING)
ok( ctx.ContextFlags == (WOW64_CONTEXT_ALL | CONTEXT_EXCEPTION_REQUEST
todo_wine ok( ctx.ContextFlags == (WOW64_CONTEXT_ALL | CONTEXT_EXCEPTION_REQUEST
| CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE)
|| ctx.ContextFlags == (WOW64_CONTEXT_ALL | CONTEXT_EXCEPTION_REQUEST
| CONTEXT_EXCEPTION_REPORTING | CONTEXT_EXCEPTION_ACTIVE),
......@@ -11204,13 +11204,13 @@ static void test_context_exception_request(void)
c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST;
ret = GetThreadContext( thread, &c );
ok( ret, "got error %lu.\n", GetLastError() );
todo_wine ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags );
ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags );
c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE
| CONTEXT_EXCEPTION_ACTIVE;
ret = GetThreadContext( thread, &c );
ok( ret, "got error %lu.\n", GetLastError() );
todo_wine ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags );
ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags );
ResumeThread(thread);
WriteRelease( &p.sync, 2 );
......@@ -11260,13 +11260,13 @@ static void test_context_exception_request(void)
c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST;
ret = GetThreadContext( thread, &c );
ok( ret, "got error %lu.\n", GetLastError() );
todo_wine ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags );
ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags );
c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE
| CONTEXT_EXCEPTION_ACTIVE;
ret = GetThreadContext( thread, &c );
ok( ret, "got error %lu.\n", GetLastError() );
todo_wine ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags );
ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags );
WriteRelease( &p.sync, 6 );
......
......@@ -751,7 +751,11 @@ unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT
if (ret == STATUS_USER_APC) *user_apc = reply_data.call.user;
if (reply_size > sizeof(reply_data.call))
{
memcpy( context, reply_data.context, reply_size - sizeof(reply_data.call) );
context[0].flags &= ~SERVER_CTX_EXEC_SPACE;
context[1].flags &= ~SERVER_CTX_EXEC_SPACE;
}
return ret;
}
......
......@@ -166,7 +166,7 @@ void fpu_to_fpux( XMM_SAVE_AREA32 *fpux, const I386_FLOATING_SAVE_AREA *fpu )
*/
static unsigned int get_server_context_flags( const void *context, USHORT machine )
{
unsigned int flags, ret = 0;
unsigned int flags = 0, ret = 0;
switch (machine)
{
......@@ -204,6 +204,7 @@ static unsigned int get_server_context_flags( const void *context, USHORT machin
if (flags & CONTEXT_ARM64_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS;
break;
}
if (flags & CONTEXT_EXCEPTION_REQUEST) ret |= SERVER_CTX_EXEC_SPACE;
return ret;
}
......@@ -218,11 +219,11 @@ static unsigned int get_native_context_flags( USHORT native_machine, USHORT wow_
switch (MAKELONG( native_machine, wow_machine ))
{
case MAKELONG( IMAGE_FILE_MACHINE_AMD64, IMAGE_FILE_MACHINE_I386 ):
return SERVER_CTX_DEBUG_REGISTERS | SERVER_CTX_FLOATING_POINT | SERVER_CTX_YMM_REGISTERS;
return SERVER_CTX_DEBUG_REGISTERS | SERVER_CTX_FLOATING_POINT | SERVER_CTX_YMM_REGISTERS | SERVER_CTX_EXEC_SPACE;
case MAKELONG( IMAGE_FILE_MACHINE_ARM64, IMAGE_FILE_MACHINE_ARMNT ):
return SERVER_CTX_DEBUG_REGISTERS | SERVER_CTX_FLOATING_POINT;
return SERVER_CTX_DEBUG_REGISTERS | SERVER_CTX_FLOATING_POINT | SERVER_CTX_EXEC_SPACE;
default:
return 0;
return SERVER_CTX_EXEC_SPACE;
}
}
......@@ -243,6 +244,21 @@ static void xstate_to_server( context_t *to, const CONTEXT_EX *xctx )
/***********************************************************************
* exception_request_flags_to_server
*
* Copy exception reporting flags to the server format.
*/
static void exception_request_flags_to_server( context_t *to, DWORD context_flags )
{
if (!(context_flags & CONTEXT_EXCEPTION_REPORTING)) return;
to->flags |= SERVER_CTX_EXEC_SPACE;
if (context_flags & CONTEXT_SERVICE_ACTIVE) to->exec_space.space.space = EXEC_SPACE_SYSCALL;
else if (context_flags & CONTEXT_EXCEPTION_ACTIVE) to->exec_space.space.space = EXEC_SPACE_EXCEPTION;
else to->exec_space.space.space = EXEC_SPACE_USERMODE;
}
/***********************************************************************
* context_to_server
*
* Convert a register context to the server format.
......@@ -319,6 +335,7 @@ static NTSTATUS context_to_server( context_t *to, USHORT to_machine, const void
}
if (flags & CONTEXT_I386_XSTATE)
xstate_to_server( to, (const CONTEXT_EX *)(from + 1) );
exception_request_flags_to_server( to, flags );
return STATUS_SUCCESS;
}
......@@ -377,6 +394,7 @@ static NTSTATUS context_to_server( context_t *to, USHORT to_machine, const void
}
if (flags & CONTEXT_I386_XSTATE)
xstate_to_server( to, (const CONTEXT_EX *)(from + 1) );
exception_request_flags_to_server( to, flags );
return STATUS_SUCCESS;
}
......@@ -438,6 +456,7 @@ static NTSTATUS context_to_server( context_t *to, USHORT to_machine, const void
}
if (flags & CONTEXT_AMD64_XSTATE)
xstate_to_server( to, (const CONTEXT_EX *)(from + 1) );
exception_request_flags_to_server( to, flags );
return STATUS_SUCCESS;
}
......@@ -503,6 +522,7 @@ static NTSTATUS context_to_server( context_t *to, USHORT to_machine, const void
}
if (flags & CONTEXT_AMD64_XSTATE)
xstate_to_server( to, (const CONTEXT_EX *)(from + 1) );
exception_request_flags_to_server( to, flags );
return STATUS_SUCCESS;
}
......@@ -550,6 +570,7 @@ static NTSTATUS context_to_server( context_t *to, USHORT to_machine, const void
for (i = 0; i < ARM_MAX_WATCHPOINTS; i++) to->debug.arm_regs.wvr[i] = from->Wvr[i];
for (i = 0; i < ARM_MAX_WATCHPOINTS; i++) to->debug.arm_regs.wcr[i] = from->Wcr[i];
}
exception_request_flags_to_server( to, flags );
return STATUS_SUCCESS;
}
......@@ -591,6 +612,7 @@ static NTSTATUS context_to_server( context_t *to, USHORT to_machine, const void
for (i = 0; i < ARM64_MAX_WATCHPOINTS; i++) to->debug.arm64_regs.wcr[i] = from->Wcr[i];
for (i = 0; i < ARM64_MAX_WATCHPOINTS; i++) to->debug.arm64_regs.wvr[i] = from->Wvr[i];
}
exception_request_flags_to_server( to, flags );
return STATUS_SUCCESS;
}
......@@ -633,6 +655,20 @@ static void xstate_from_server( CONTEXT_EX *xctx, const context_t *from )
/***********************************************************************
* exception_request_flags_from_server
*
* Copy exception reporting flags from the server format.
*/
static void exception_request_flags_from_server( DWORD *context_flags, const context_t *from )
{
if (!(*context_flags & CONTEXT_EXCEPTION_REQUEST) || !(from->flags & SERVER_CTX_EXEC_SPACE)) return;
*context_flags = (*context_flags & ~(CONTEXT_SERVICE_ACTIVE | CONTEXT_EXCEPTION_ACTIVE)) | CONTEXT_EXCEPTION_REPORTING;
if (from->exec_space.space.space == EXEC_SPACE_SYSCALL) *context_flags |= CONTEXT_SERVICE_ACTIVE;
else if (from->exec_space.space.space == EXEC_SPACE_EXCEPTION) *context_flags |= CONTEXT_EXCEPTION_ACTIVE;
}
/***********************************************************************
* context_from_server
*
* Convert a register context from the server format.
......@@ -706,6 +742,7 @@ static NTSTATUS context_from_server( void *dst, const context_t *from, USHORT ma
}
if ((from->flags & SERVER_CTX_YMM_REGISTERS) && (to_flags & CONTEXT_I386_XSTATE))
xstate_from_server( (CONTEXT_EX *)(to + 1), from );
exception_request_flags_from_server( &to->ContextFlags, from );
return STATUS_SUCCESS;
}
......@@ -767,6 +804,7 @@ static NTSTATUS context_from_server( void *dst, const context_t *from, USHORT ma
}
if ((from->flags & SERVER_CTX_YMM_REGISTERS) && (to_flags & CONTEXT_I386_XSTATE))
xstate_from_server( (CONTEXT_EX *)(to + 1), from );
exception_request_flags_from_server( &to->ContextFlags, from );
return STATUS_SUCCESS;
}
......@@ -829,6 +867,7 @@ static NTSTATUS context_from_server( void *dst, const context_t *from, USHORT ma
}
if ((from->flags & SERVER_CTX_YMM_REGISTERS) && (to_flags & CONTEXT_AMD64_XSTATE))
xstate_from_server( (CONTEXT_EX *)(to + 1), from );
exception_request_flags_from_server( &to->ContextFlags, from );
return STATUS_SUCCESS;
}
......@@ -898,6 +937,7 @@ static NTSTATUS context_from_server( void *dst, const context_t *from, USHORT ma
}
if ((from->flags & SERVER_CTX_YMM_REGISTERS) && (to_flags & CONTEXT_AMD64_XSTATE))
xstate_from_server( (CONTEXT_EX *)(to + 1), from );
exception_request_flags_from_server( &to->ContextFlags, from );
return STATUS_SUCCESS;
}
......@@ -945,6 +985,7 @@ static NTSTATUS context_from_server( void *dst, const context_t *from, USHORT ma
for (i = 0; i < ARM_MAX_WATCHPOINTS; i++) to->Wvr[i] = from->debug.arm_regs.wvr[i];
for (i = 0; i < ARM_MAX_WATCHPOINTS; i++) to->Wcr[i] = from->debug.arm_regs.wcr[i];
}
exception_request_flags_from_server( &to->ContextFlags, from );
return STATUS_SUCCESS;
}
......@@ -986,6 +1027,7 @@ static NTSTATUS context_from_server( void *dst, const context_t *from, USHORT ma
for (i = 0; i < ARM64_MAX_WATCHPOINTS; i++) to->Wcr[i] = from->debug.arm64_regs.wcr[i];
for (i = 0; i < ARM64_MAX_WATCHPOINTS; i++) to->Wvr[i] = from->debug.arm64_regs.wvr[i];
}
exception_request_flags_from_server( &to->ContextFlags, from );
return STATUS_SUCCESS;
}
......
......@@ -111,6 +111,14 @@ typedef union
} debug_event_t;
enum context_exec_space
{
EXEC_SPACE_USERMODE,
EXEC_SPACE_SYSCALL,
EXEC_SPACE_EXCEPTION,
};
typedef struct
{
unsigned int machine;
......@@ -157,6 +165,10 @@ typedef struct
} ext;
union
{
struct { enum context_exec_space space; int __pad; } space;
} exec_space;
union
{
struct { struct { unsigned __int64 low, high; } ymm_high[16]; } regs;
} ymm;
} context_t;
......@@ -168,6 +180,7 @@ typedef struct
#define SERVER_CTX_DEBUG_REGISTERS 0x10
#define SERVER_CTX_EXTENDED_REGISTERS 0x20
#define SERVER_CTX_YMM_REGISTERS 0x40
#define SERVER_CTX_EXEC_SPACE 0x80
struct send_fd
......@@ -6509,7 +6522,7 @@ union generic_reply
/* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 798
#define SERVER_PROTOCOL_VERSION 799
/* ### protocol_version end ### */
......
......@@ -126,6 +126,14 @@ typedef union
} unload_dll;
} debug_event_t;
enum context_exec_space
{
EXEC_SPACE_USERMODE,
EXEC_SPACE_SYSCALL,
EXEC_SPACE_EXCEPTION,
};
/* context data */
typedef struct
{
......@@ -173,6 +181,10 @@ typedef struct
} ext; /* selected by SERVER_CTX_EXTENDED_REGISTERS */
union
{
struct { enum context_exec_space space; int __pad; } space;
} exec_space; /* selected by SERVER_CTX_EXEC_SPACE */
union
{
struct { struct { unsigned __int64 low, high; } ymm_high[16]; } regs;
} ymm; /* selected by SERVER_CTX_YMM_REGISTERS */
} context_t;
......@@ -184,6 +196,7 @@ typedef struct
#define SERVER_CTX_DEBUG_REGISTERS 0x10
#define SERVER_CTX_EXTENDED_REGISTERS 0x20
#define SERVER_CTX_YMM_REGISTERS 0x40
#define SERVER_CTX_EXEC_SPACE 0x80
/* structure used in sending an fd from client to server */
struct send_fd
......
......@@ -706,7 +706,7 @@ C_ASSERT( sizeof(async_data_t) == 40 );
C_ASSERT( sizeof(atom_t) == 4 );
C_ASSERT( sizeof(char) == 1 );
C_ASSERT( sizeof(client_ptr_t) == 8 );
C_ASSERT( sizeof(context_t) == 1720 );
C_ASSERT( sizeof(context_t) == 1728 );
C_ASSERT( sizeof(cursor_pos_t) == 24 );
C_ASSERT( sizeof(data_size_t) == 4 );
C_ASSERT( sizeof(debug_event_t) == 160 );
......
......@@ -1303,6 +1303,7 @@ static void copy_context( context_t *to, const context_t *from, unsigned int fla
if (flags & SERVER_CTX_DEBUG_REGISTERS) to->debug = from->debug;
if (flags & SERVER_CTX_EXTENDED_REGISTERS) to->ext = from->ext;
if (flags & SERVER_CTX_YMM_REGISTERS) to->ymm = from->ymm;
if (flags & SERVER_CTX_EXEC_SPACE) to->exec_space = from->exec_space;
}
/* gets the current impersonation token */
......@@ -1941,14 +1942,14 @@ DECL_HANDLER(set_thread_context)
/* If context is in a pending state, we don't know if we will use WoW or native
* context, so store both and discard irrevelant one in select request. */
const int is_pending = thread->context->status == STATUS_PENDING;
unsigned int native_flags = contexts[CTX_NATIVE].flags;
unsigned int native_flags = contexts[CTX_NATIVE].flags & ~SERVER_CTX_EXEC_SPACE;
if (ctx_count == 2 && (is_pending || thread->context->regs[CTX_WOW].machine))
{
context_t *ctx = &thread->context->regs[CTX_WOW];
/* some regs are always set from the native context */
flags = contexts[CTX_WOW].flags & ~req->native_flags;
flags = contexts[CTX_WOW].flags & ~(req->native_flags | SERVER_CTX_EXEC_SPACE);
if (is_pending) ctx->machine = contexts[CTX_WOW].machine;
else native_flags &= req->native_flags;
......
......@@ -822,6 +822,19 @@ static void dump_varargs_context( const char *prefix, data_size_t size )
fprintf( stderr, "%s{machine=%04x", prefix, ctx.machine );
break;
}
if (ctx.flags & SERVER_CTX_EXEC_SPACE)
{
const char *space;
switch (ctx.exec_space.space.space)
{
case EXEC_SPACE_USERMODE: space = "user"; break;
case EXEC_SPACE_SYSCALL: space = "syscall"; break;
case EXEC_SPACE_EXCEPTION: space = "exception"; break;
default: space = "invalid"; break;
}
fprintf( stderr, ",exec_space=%s", space );
}
fputc( '}', stderr );
remove_data( size );
}
......
......@@ -54,7 +54,7 @@ my %formats =
"hw_input_t" => [ 40, 8, "&dump_hw_input" ],
# varargs-only structures
"apc_call_t" => [ 64, 8 ],
"context_t" => [ 1720, 8 ],
"context_t" => [ 1728, 8 ],
"cursor_pos_t" => [ 24, 8 ],
"debug_event_t" => [ 160, 8 ],
"message_data_t" => [ 48, 8 ],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment