Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
11d6c52f
Commit
11d6c52f
authored
Jul 01, 2021
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Use the CPU area to get/set the Wow64 context on x86-64.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
4acecd86
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
179 additions
and
5 deletions
+179
-5
signal_x86_64.c
dlls/ntdll/unix/signal_x86_64.c
+179
-5
No files found.
dlls/ntdll/unix/signal_x86_64.c
View file @
11d6c52f
...
@@ -1614,7 +1614,8 @@ void *get_native_context( CONTEXT *context )
...
@@ -1614,7 +1614,8 @@ void *get_native_context( CONTEXT *context )
*/
*/
void
*
get_wow_context
(
CONTEXT
*
context
)
void
*
get_wow_context
(
CONTEXT
*
context
)
{
{
return
NULL
;
if
(
context
->
SegCs
!=
cs64_sel
)
return
NULL
;
return
get_cpu_area
(
IMAGE_FILE_MACHINE_I386
);
}
}
...
@@ -1851,10 +1852,97 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
...
@@ -1851,10 +1852,97 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
*/
*/
NTSTATUS
set_thread_wow64_context
(
HANDLE
handle
,
const
void
*
ctx
,
ULONG
size
)
NTSTATUS
set_thread_wow64_context
(
HANDLE
handle
,
const
void
*
ctx
,
ULONG
size
)
{
{
BOOL
self
;
BOOL
self
=
(
handle
==
GetCurrentThread
());
struct
syscall_frame
*
frame
=
amd64_thread_data
()
->
syscall_frame
;
I386_CONTEXT
*
wow_frame
;
const
I386_CONTEXT
*
context
=
ctx
;
DWORD
flags
=
context
->
ContextFlags
&
~
CONTEXT_i386
;
if
(
size
!=
sizeof
(
I386_CONTEXT
))
return
STATUS_INFO_LENGTH_MISMATCH
;
if
(
size
!=
sizeof
(
I386_CONTEXT
))
return
STATUS_INFO_LENGTH_MISMATCH
;
return
set_thread_context
(
handle
,
ctx
,
&
self
,
IMAGE_FILE_MACHINE_I386
);
/* debug registers require a server call */
if
(
self
&&
(
flags
&
CONTEXT_I386_DEBUG_REGISTERS
))
self
=
(
amd64_thread_data
()
->
dr0
==
context
->
Dr0
&&
amd64_thread_data
()
->
dr1
==
context
->
Dr1
&&
amd64_thread_data
()
->
dr2
==
context
->
Dr2
&&
amd64_thread_data
()
->
dr3
==
context
->
Dr3
&&
amd64_thread_data
()
->
dr6
==
context
->
Dr6
&&
amd64_thread_data
()
->
dr7
==
context
->
Dr7
);
if
(
!
self
)
{
NTSTATUS
ret
=
set_thread_context
(
handle
,
context
,
&
self
,
IMAGE_FILE_MACHINE_I386
);
if
(
ret
||
!
self
)
return
ret
;
if
(
flags
&
CONTEXT_I386_DEBUG_REGISTERS
)
{
amd64_thread_data
()
->
dr0
=
context
->
Dr0
;
amd64_thread_data
()
->
dr1
=
context
->
Dr1
;
amd64_thread_data
()
->
dr2
=
context
->
Dr2
;
amd64_thread_data
()
->
dr3
=
context
->
Dr3
;
amd64_thread_data
()
->
dr6
=
context
->
Dr6
;
amd64_thread_data
()
->
dr7
=
context
->
Dr7
;
}
if
(
!
(
flags
&
~
CONTEXT_I386_DEBUG_REGISTERS
))
return
ret
;
}
if
(
!
(
wow_frame
=
get_cpu_area
(
IMAGE_FILE_MACHINE_I386
)))
return
STATUS_INVALID_PARAMETER
;
if
(
flags
&
CONTEXT_I386_INTEGER
)
{
wow_frame
->
Eax
=
context
->
Eax
;
wow_frame
->
Ebx
=
context
->
Ebx
;
wow_frame
->
Ecx
=
context
->
Ecx
;
wow_frame
->
Edx
=
context
->
Edx
;
wow_frame
->
Esi
=
context
->
Esi
;
wow_frame
->
Edi
=
context
->
Edi
;
}
if
(
flags
&
CONTEXT_I386_CONTROL
)
{
wow_frame
->
Esp
=
context
->
Esp
;
wow_frame
->
Ebp
=
context
->
Ebp
;
wow_frame
->
Eip
=
context
->
Eip
;
wow_frame
->
EFlags
=
context
->
EFlags
;
wow_frame
->
SegCs
=
cs32_sel
;
wow_frame
->
SegSs
=
ds64_sel
;
}
if
(
flags
&
CONTEXT_I386_SEGMENTS
)
{
wow_frame
->
SegDs
=
ds64_sel
;
wow_frame
->
SegEs
=
ds64_sel
;
wow_frame
->
SegFs
=
0
;
/* FIXME */
wow_frame
->
SegGs
=
ds64_sel
;
}
if
(
flags
&
CONTEXT_I386_DEBUG_REGISTERS
)
{
wow_frame
->
Dr0
=
context
->
Dr0
;
wow_frame
->
Dr1
=
context
->
Dr1
;
wow_frame
->
Dr2
=
context
->
Dr2
;
wow_frame
->
Dr3
=
context
->
Dr3
;
wow_frame
->
Dr6
=
context
->
Dr6
;
wow_frame
->
Dr7
=
context
->
Dr7
;
}
if
(
flags
&
CONTEXT_I386_EXTENDED_REGISTERS
)
{
memcpy
(
&
frame
->
xsave
,
context
->
ExtendedRegisters
,
sizeof
(
frame
->
xsave
)
);
}
else
if
(
flags
&
CONTEXT_I386_FLOATING_POINT
)
{
fpu_to_fpux
(
&
frame
->
xsave
,
&
context
->
FloatSave
);
}
if
(
flags
&
CONTEXT_I386_XSTATE
)
{
CONTEXT_EX
*
context_ex
=
(
CONTEXT_EX
*
)(
context
+
1
);
XSTATE
*
xs
=
(
XSTATE
*
)((
char
*
)
context_ex
+
context_ex
->
XState
.
Offset
);
if
(
xs
->
Mask
&
XSTATE_MASK_GSSE
)
{
frame
->
xstate
.
Mask
|=
XSTATE_MASK_GSSE
;
memcpy
(
&
frame
->
xstate
.
YmmContext
,
&
xs
->
YmmContext
,
sizeof
(
xs
->
YmmContext
)
);
}
else
frame
->
xstate
.
Mask
&=
~
XSTATE_MASK_GSSE
;
frame
->
restore_flags
|=
CONTEXT_I386_XSTATE
;
}
return
STATUS_SUCCESS
;
}
}
...
@@ -1863,10 +1951,96 @@ NTSTATUS set_thread_wow64_context( HANDLE handle, const void *ctx, ULONG size )
...
@@ -1863,10 +1951,96 @@ NTSTATUS set_thread_wow64_context( HANDLE handle, const void *ctx, ULONG size )
*/
*/
NTSTATUS
get_thread_wow64_context
(
HANDLE
handle
,
void
*
ctx
,
ULONG
size
)
NTSTATUS
get_thread_wow64_context
(
HANDLE
handle
,
void
*
ctx
,
ULONG
size
)
{
{
BOOL
self
;
DWORD
needed_flags
;
struct
syscall_frame
*
frame
=
amd64_thread_data
()
->
syscall_frame
;
I386_CONTEXT
*
wow_frame
,
*
context
=
ctx
;
BOOL
self
=
(
handle
==
GetCurrentThread
());
if
(
size
!=
sizeof
(
I386_CONTEXT
))
return
STATUS_INFO_LENGTH_MISMATCH
;
if
(
size
!=
sizeof
(
I386_CONTEXT
))
return
STATUS_INFO_LENGTH_MISMATCH
;
return
get_thread_context
(
handle
,
ctx
,
&
self
,
IMAGE_FILE_MACHINE_I386
);
needed_flags
=
context
->
ContextFlags
&
~
CONTEXT_i386
;
/* debug registers require a server call */
if
(
needed_flags
&
CONTEXT_I386_DEBUG_REGISTERS
)
self
=
FALSE
;
if
(
!
self
)
{
NTSTATUS
ret
=
get_thread_context
(
handle
,
context
,
&
self
,
IMAGE_FILE_MACHINE_I386
);
if
(
ret
||
!
self
)
return
ret
;
/* update the cached version of the debug registers */
if
(
needed_flags
&
CONTEXT_I386_DEBUG_REGISTERS
)
{
amd64_thread_data
()
->
dr0
=
context
->
Dr0
;
amd64_thread_data
()
->
dr1
=
context
->
Dr1
;
amd64_thread_data
()
->
dr2
=
context
->
Dr2
;
amd64_thread_data
()
->
dr3
=
context
->
Dr3
;
amd64_thread_data
()
->
dr6
=
context
->
Dr6
;
amd64_thread_data
()
->
dr7
=
context
->
Dr7
;
}
if
(
!
(
needed_flags
&
~
CONTEXT_I386_DEBUG_REGISTERS
))
return
ret
;
}
if
(
!
(
wow_frame
=
get_cpu_area
(
IMAGE_FILE_MACHINE_I386
)))
return
STATUS_INVALID_PARAMETER
;
if
(
needed_flags
&
CONTEXT_I386_INTEGER
)
{
context
->
Eax
=
wow_frame
->
Eax
;
context
->
Ebx
=
wow_frame
->
Ebx
;
context
->
Ecx
=
wow_frame
->
Ecx
;
context
->
Edx
=
wow_frame
->
Edx
;
context
->
Esi
=
wow_frame
->
Esi
;
context
->
Edi
=
wow_frame
->
Edi
;
context
->
ContextFlags
|=
CONTEXT_I386_INTEGER
;
}
if
(
needed_flags
&
CONTEXT_I386_CONTROL
)
{
context
->
Esp
=
wow_frame
->
Esp
;
context
->
Ebp
=
wow_frame
->
Ebp
;
context
->
Eip
=
wow_frame
->
Eip
;
context
->
EFlags
=
wow_frame
->
EFlags
;
context
->
SegCs
=
wow_frame
->
SegCs
;
context
->
SegSs
=
wow_frame
->
SegSs
;
context
->
ContextFlags
|=
CONTEXT_I386_CONTROL
;
}
if
(
needed_flags
&
CONTEXT_I386_SEGMENTS
)
{
context
->
SegDs
=
wow_frame
->
SegDs
;
context
->
SegEs
=
wow_frame
->
SegEs
;
context
->
SegFs
=
wow_frame
->
SegFs
;
context
->
SegGs
=
wow_frame
->
SegGs
;
context
->
ContextFlags
|=
CONTEXT_I386_SEGMENTS
;
}
if
(
needed_flags
&
CONTEXT_I386_EXTENDED_REGISTERS
)
{
memcpy
(
context
->
ExtendedRegisters
,
&
frame
->
xsave
,
sizeof
(
context
->
ExtendedRegisters
)
);
context
->
ContextFlags
|=
CONTEXT_I386_EXTENDED_REGISTERS
;
}
if
(
needed_flags
&
CONTEXT_I386_FLOATING_POINT
)
{
fpux_to_fpu
(
&
context
->
FloatSave
,
&
frame
->
xsave
);
context
->
ContextFlags
|=
CONTEXT_I386_FLOATING_POINT
;
}
if
((
needed_flags
&
CONTEXT_I386_XSTATE
)
&&
(
cpu_info
.
ProcessorFeatureBits
&
CPU_FEATURE_AVX
))
{
CONTEXT_EX
*
context_ex
=
(
CONTEXT_EX
*
)(
context
+
1
);
XSTATE
*
xstate
=
(
XSTATE
*
)((
char
*
)
context_ex
+
context_ex
->
XState
.
Offset
);
unsigned
int
mask
;
if
(
context_ex
->
XState
.
Length
<
offsetof
(
XSTATE
,
YmmContext
)
||
context_ex
->
XState
.
Length
>
sizeof
(
XSTATE
))
return
STATUS_INVALID_PARAMETER
;
mask
=
(
xstate_compaction_enabled
?
xstate
->
CompactionMask
:
xstate
->
Mask
)
&
XSTATE_MASK_GSSE
;
xstate
->
Mask
=
frame
->
xstate
.
Mask
&
mask
;
xstate
->
CompactionMask
=
xstate_compaction_enabled
?
(
0x8000000000000000
|
mask
)
:
0
;
memset
(
xstate
->
Reserved
,
0
,
sizeof
(
xstate
->
Reserved
)
);
if
(
xstate
->
Mask
)
{
if
(
context_ex
->
XState
.
Length
<
sizeof
(
XSTATE
))
return
STATUS_BUFFER_OVERFLOW
;
memcpy
(
&
xstate
->
YmmContext
,
&
frame
->
xstate
.
YmmContext
,
sizeof
(
xstate
->
YmmContext
)
);
}
}
return
STATUS_SUCCESS
;
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment