Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
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-winehq
Commits
334f54c2
Commit
334f54c2
authored
Nov 30, 2023
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Call Wow64PrepareForException directly from KiUserExceptionDispatcher.
This requires moving the stack switch to Wow64PrepareForException. Based on a patch by Paul Gofman.
parent
ae32b2f4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
95 additions
and
25 deletions
+95
-25
signal_x86_64.c
dlls/ntdll/signal_x86_64.c
+7
-23
wow64.c
dlls/ntdll/tests/wow64.c
+53
-0
syscall.c
dlls/wow64/syscall.c
+34
-1
wow64.spec
dlls/wow64/wow64.spec
+1
-1
No files found.
dlls/ntdll/signal_x86_64.c
View file @
334f54c2
...
...
@@ -546,8 +546,6 @@ NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
NTSTATUS
status
;
DWORD
c
;
if
(
pWow64PrepareForException
)
pWow64PrepareForException
(
rec
,
context
);
TRACE_
(
seh
)(
"code=%lx flags=%lx addr=%p ip=%Ix
\n
"
,
rec
->
ExceptionCode
,
rec
->
ExceptionFlags
,
rec
->
ExceptionAddress
,
context
->
Rip
);
for
(
c
=
0
;
c
<
min
(
EXCEPTION_MAXIMUM_PARAMETERS
,
rec
->
NumberParameters
);
c
++
)
...
...
@@ -610,34 +608,20 @@ NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
}
NTSTATUS
WINAPI
dispatch_wow_exception
(
EXCEPTION_RECORD
*
rec_ptr
,
CONTEXT
*
context_ptr
)
{
char
buffer
[
sizeof
(
CONTEXT
)
+
sizeof
(
CONTEXT_EX
)
+
sizeof
(
XSTATE
)
+
128
];
CONTEXT
*
context
;
CONTEXT_EX
*
context_ex
;
EXCEPTION_RECORD
rec
=
*
rec_ptr
;
RtlInitializeExtendedContext
(
buffer
,
context_ptr
->
ContextFlags
,
&
context_ex
);
context
=
RtlLocateLegacyContext
(
context_ex
,
NULL
);
RtlCopyContext
(
context
,
context_ptr
->
ContextFlags
,
context_ptr
);
return
dispatch_exception
(
&
rec
,
context
);
}
/*******************************************************************
* KiUserExceptionDispatcher (NTDLL.@)
*/
__ASM_GLOBAL_FUNC
(
KiUserExceptionDispatcher
,
"mov 0x98(%rsp),%rcx
\n\t
"
/* context->Rsp */
"movw %cs,%ax
\n\t
"
"cmpw %ax,0x38(%rsp)
\n\t
"
/* context->SegCs */
"je 1f
\n\t
"
"cld
\n\t
"
/* some anticheats need this exact instruction here */
"mov "
__ASM_NAME
(
"pWow64PrepareForException"
)
"(%rip),%rax
\n\t
"
"test %rax,%rax
\n\t
"
"jz 1f
\n\t
"
"mov %rsp,%rdx
\n\t
"
/* context */
"lea 0x4f0(%rsp),%rcx
\n\t
"
/* rec */
"movq %r14,%rsp
\n\t
"
/* switch to 64-bit stack */
"call "
__ASM_NAME
(
"dispatch_wow_exception"
)
"
\n\t
"
"int3
\n
"
"call *%rax
\n
"
"1:
\t
mov 0xf8(%rsp),%rdx
\n\t
"
/* context->Rip */
"mov 0x98(%rsp),%rcx
\n\t
"
/* context->Rsp */
"mov %rdx,-0x8(%rcx)
\n\t
"
"mov %rbp,-0x10(%rcx)
\n\t
"
"mov %rdi,-0x18(%rcx)
\n\t
"
...
...
dlls/ntdll/tests/wow64.c
View file @
334f54c2
...
...
@@ -35,6 +35,7 @@ static NTSTATUS (WINAPI *pRtlWow64GetThreadContext)(HANDLE,WOW64_CONTEXT*);
static
NTSTATUS
(
WINAPI
*
pRtlWow64IsWowGuestMachineSupported
)(
USHORT
,
BOOLEAN
*
);
static
NTSTATUS
(
WINAPI
*
pNtMapViewOfSectionEx
)(
HANDLE
,
HANDLE
,
PVOID
*
,
const
LARGE_INTEGER
*
,
SIZE_T
*
,
ULONG
,
ULONG
,
MEM_EXTENDED_PARAMETER
*
,
ULONG
);
#ifdef _WIN64
static
NTSTATUS
(
WINAPI
*
pKiUserExceptionDispatcher
)(
EXCEPTION_RECORD
*
,
CONTEXT
*
);
static
NTSTATUS
(
WINAPI
*
pRtlWow64GetCpuAreaInfo
)(
WOW64_CPURESERVED
*
,
ULONG
,
WOW64_CPU_AREA_INFO
*
);
static
NTSTATUS
(
WINAPI
*
pRtlWow64GetThreadSelectorEntry
)(
HANDLE
,
THREAD_DESCRIPTOR_INFORMATION
*
,
ULONG
,
ULONG
*
);
static
CROSS_PROCESS_WORK_ENTRY
*
(
WINAPI
*
pRtlWow64PopAllCrossProcessWorkFromWorkList
)(
CROSS_PROCESS_WORK_HDR
*
,
BOOLEAN
*
);
...
...
@@ -100,6 +101,7 @@ static void init(void)
GET_PROC
(
RtlWow64GetThreadContext
);
GET_PROC
(
RtlWow64IsWowGuestMachineSupported
);
#ifdef _WIN64
GET_PROC
(
KiUserExceptionDispatcher
);
GET_PROC
(
RtlWow64GetCpuAreaInfo
);
GET_PROC
(
RtlWow64GetThreadSelectorEntry
);
GET_PROC
(
RtlWow64PopAllCrossProcessWorkFromWorkList
);
...
...
@@ -909,6 +911,7 @@ static void test_peb_teb(void)
static
void
test_selectors
(
void
)
{
#ifndef __arm__
THREAD_DESCRIPTOR_INFORMATION
info
;
NTSTATUS
status
;
ULONG
base
,
limit
,
sel
,
retlen
;
...
...
@@ -1043,6 +1046,7 @@ static void test_selectors(void)
}
}
#undef GET_ENTRY
#endif
/* __arm__ */
}
static
void
test_image_mappings
(
void
)
...
...
@@ -1384,6 +1388,20 @@ static void test_cpu_area(void)
else
win_skip
(
"RtlWow64GetCpuAreaInfo not supported
\n
"
);
}
static
void
test_exception_dispatcher
(
void
)
{
#ifdef __x86_64__
BYTE
*
code
=
(
BYTE
*
)
pKiUserExceptionDispatcher
;
void
**
hook
;
/* cld; mov xxx(%rip),%rax */
ok
(
code
[
0
]
==
0xfc
&&
code
[
1
]
==
0x48
&&
code
[
2
]
==
0x8b
&&
code
[
3
]
==
0x05
,
"wrong opcodes %02x %02x %02x %02x
\n
"
,
code
[
0
],
code
[
1
],
code
[
2
],
code
[
3
]
);
hook
=
(
void
**
)(
code
+
8
+
*
(
int
*
)(
code
+
4
));
ok
(
!*
hook
,
"hook %p set to %p
\n
"
,
hook
,
*
hook
);
#endif
}
#else
/* _WIN64 */
static
const
BYTE
call_func64_code
[]
=
...
...
@@ -2122,6 +2140,40 @@ static void test_cpu_area(void)
}
static
void
test_exception_dispatcher
(
void
)
{
ULONG64
ptr
,
hook_ptr
,
hook
,
expect
,
res
;
NTSTATUS
status
;
BYTE
code
[
8
];
if
(
!
is_wow64
)
return
;
if
(
!
code_mem
)
return
;
if
(
!
ntdll_module
)
return
;
ptr
=
get_proc_address64
(
ntdll_module
,
"KiUserExceptionDispatcher"
);
ok
(
ptr
,
"KiUserExceptionDispatcher not found
\n
"
);
if
(
pNtWow64ReadVirtualMemory64
)
{
HANDLE
process
=
OpenProcess
(
PROCESS_ALL_ACCESS
,
FALSE
,
GetCurrentProcessId
()
);
ok
(
process
!=
0
,
"failed to open current process %lu
\n
"
,
GetLastError
()
);
status
=
pNtWow64ReadVirtualMemory64
(
process
,
ptr
,
&
code
,
sizeof
(
code
),
&
res
);
ok
(
!
status
,
"NtWow64ReadVirtualMemory64 failed %lx
\n
"
,
status
);
/* cld; mov xxx(%rip),%rax */
ok
(
code
[
0
]
==
0xfc
&&
code
[
1
]
==
0x48
&&
code
[
2
]
==
0x8b
&&
code
[
3
]
==
0x05
,
"wrong opcodes %02x %02x %02x %02x
\n
"
,
code
[
0
],
code
[
1
],
code
[
2
],
code
[
3
]
);
hook_ptr
=
ptr
+
8
+
*
(
int
*
)(
code
+
4
);
status
=
pNtWow64ReadVirtualMemory64
(
process
,
hook_ptr
,
&
hook
,
sizeof
(
hook
),
&
res
);
ok
(
!
status
,
"NtWow64ReadVirtualMemory64 failed %lx
\n
"
,
status
);
expect
=
get_proc_address64
(
wow64_module
,
"Wow64PrepareForException"
);
ok
(
hook
==
expect
,
"hook %I64x set to %I64x / %I64x
\n
"
,
hook_ptr
,
hook
,
expect
);
NtClose
(
process
);
}
}
#endif
/* _WIN64 */
...
...
@@ -2142,4 +2194,5 @@ START_TEST(wow64)
test_syscalls
();
#endif
test_cpu_area
();
test_exception_dispatcher
();
}
dlls/wow64/syscall.c
View file @
334f54c2
...
...
@@ -101,7 +101,6 @@ static void (WINAPI *pBTCpuProcessInit)(void);
static
NTSTATUS
(
WINAPI
*
pBTCpuSetContext
)(
HANDLE
,
HANDLE
,
void
*
,
void
*
);
static
void
(
WINAPI
*
pBTCpuThreadInit
)(
void
);
static
void
(
WINAPI
*
pBTCpuSimulate
)(
void
);
static
NTSTATUS
(
WINAPI
*
pBTCpuResetToConsistentState
)(
EXCEPTION_POINTERS
*
);
static
void
*
(
WINAPI
*
p__wine_get_unix_opcode
)(
void
);
static
void
*
(
WINAPI
*
pKiRaiseUserExceptionDispatcher
)(
void
);
void
(
WINAPI
*
pBTCpuNotifyFlushInstructionCache2
)(
const
void
*
,
SIZE_T
)
=
NULL
;
...
...
@@ -111,6 +110,7 @@ void (WINAPI *pBTCpuNotifyMemoryDirty)( void *, SIZE_T ) = NULL;
void
(
WINAPI
*
pBTCpuNotifyMemoryFree
)(
void
*
,
SIZE_T
,
ULONG
)
=
NULL
;
void
(
WINAPI
*
pBTCpuNotifyMemoryProtect
)(
void
*
,
SIZE_T
,
ULONG
)
=
NULL
;
void
(
WINAPI
*
pBTCpuNotifyUnmapViewOfSection
)(
void
*
)
=
NULL
;
NTSTATUS
(
WINAPI
*
pBTCpuResetToConsistentState
)(
EXCEPTION_POINTERS
*
)
=
NULL
;
void
(
WINAPI
*
pBTCpuUpdateProcessorInformation
)(
SYSTEM_CPU_INFORMATION
*
)
=
NULL
;
void
(
WINAPI
*
pBTCpuThreadTerm
)(
HANDLE
)
=
NULL
;
...
...
@@ -1154,12 +1154,45 @@ void WINAPI Wow64LdrpInitialize( CONTEXT *context )
/**********************************************************************
* Wow64PrepareForException (wow64.@)
*/
#ifdef __x86_64__
__ASM_GLOBAL_FUNC
(
Wow64PrepareForException
,
"sub $0x38,%rsp
\n\t
"
"mov %rcx,%r10
\n\t
"
/* rec */
"movw %cs,%ax
\n\t
"
"cmpw %ax,0x38(%rdx)
\n\t
"
/* context->SegCs */
"je 1f
\n\t
"
/* already in 64-bit mode? */
/* copy arguments to 64-bit stack */
"mov %rsp,%rsi
\n\t
"
"mov 0x98(%rdx),%rcx
\n\t
"
/* context->Rsp */
"sub %rsi,%rcx
\n\t
"
/* stack size */
"sub %rcx,%r14
\n\t
"
/* reserve same size on 64-bit stack */
"and $~0x0f,%r14
\n\t
"
"mov %r14,%rdi
\n\t
"
"shr $3,%rcx
\n\t
"
"rep; movsq
\n\t
"
/* update arguments to point to the new stack */
"mov %r14,%rax
\n\t
"
"sub %rsp,%rax
\n\t
"
"add %rax,%r10
\n\t
"
/* rec */
"add %rax,%rdx
\n\t
"
/* context */
/* switch to 64-bit stack */
"mov %r14,%rsp
\n
"
/* build EXCEPTION_POINTERS structure and call BTCpuResetToConsistentState */
"1:
\t
lea 0x20(%rsp),%rcx
\n\t
"
/* pointers */
"mov %r10,(%rcx)
\n\t
"
/* rec */
"mov %rdx,8(%rcx)
\n\t
"
/* context */
"mov "
__ASM_NAME
(
"pBTCpuResetToConsistentState"
)
"(%rip),%rax
\n\t
"
"call *%rax
\n\t
"
"add $0x38,%rsp
\n\t
"
"ret"
)
#else
void
WINAPI
Wow64PrepareForException
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
)
{
EXCEPTION_POINTERS
ptrs
=
{
rec
,
context
};
pBTCpuResetToConsistentState
(
&
ptrs
);
}
#endif
/**********************************************************************
...
...
dlls/wow64/wow64.spec
View file @
334f54c2
...
...
@@ -15,7 +15,7 @@
@ stub Wow64NotifyUnsimulateComplete
@ stdcall Wow64PassExceptionToGuest(ptr)
@ stub Wow64PrepareForDebuggerAttach
@ stdcall Wow64PrepareForException(ptr ptr)
@ stdcall
-norelay
Wow64PrepareForException(ptr ptr)
@ stdcall Wow64ProcessPendingCrossProcessItems()
@ stdcall Wow64RaiseException(long ptr)
@ stub Wow64ShallowThunkAllocObjectAttributes32TO64_FNC
...
...
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