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
060a8b4a
Commit
060a8b4a
authored
Nov 30, 2023
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Fix stack layout and unwind information for KiUserApcDispatcher on ARM64.
parent
9bbdf6c7
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
120 additions
and
16 deletions
+120
-16
signal_arm64.c
dlls/ntdll/signal_arm64.c
+13
-7
exception.c
dlls/ntdll/tests/exception.c
+85
-0
signal_arm64.c
dlls/ntdll/unix/signal_arm64.c
+22
-9
No files found.
dlls/ntdll/signal_arm64.c
View file @
060a8b4a
...
...
@@ -587,13 +587,19 @@ __ASM_GLOBAL_FUNC( KiUserExceptionDispatcher,
/*******************************************************************
* KiUserApcDispatcher (NTDLL.@)
*/
void
WINAPI
KiUserApcDispatcher
(
CONTEXT
*
context
,
ULONG_PTR
arg1
,
ULONG_PTR
arg2
,
ULONG_PTR
arg3
,
PNTAPCFUNC
apc
)
{
void
(
CALLBACK
*
func
)(
ULONG_PTR
,
ULONG_PTR
,
ULONG_PTR
,
CONTEXT
*
)
=
(
void
*
)
apc
;
func
(
arg1
,
arg2
,
arg3
,
context
);
NtContinue
(
context
,
TRUE
);
}
__ASM_GLOBAL_FUNC
(
KiUserApcDispatcher
,
__ASM_SEH
(
".seh_context
\n\t
"
)
"nop
\n\t
"
__ASM_SEH
(
".seh_stackalloc 0x30
\n\t
"
)
__ASM_SEH
(
".seh_endprologue
\n\t
"
)
"ldp x16, x0, [sp]
\n\t
"
/* func, arg1 */
"ldp x1, x2, [sp, #0x10]
\n\t
"
/* arg2, arg3 */
"add x3, sp, #0x30
\n\t
"
/* context (FIXME) */
"blr x16
\n\t
"
"add x0, sp, #0x30
\n\t
"
/* context */
"ldr w1, [sp, #0x20]
\n\t
"
/* alertable */
"bl "
__ASM_NAME
(
"NtContinue"
)
"
\n\t
"
"brk #1"
)
/*******************************************************************
...
...
dlls/ntdll/tests/exception.c
View file @
060a8b4a
...
...
@@ -8666,6 +8666,90 @@ static void test_KiUserExceptionDispatcher(void)
VirtualProtect
(
pKiUserExceptionDispatcher
,
sizeof
(
saved_code
),
old_protect
,
&
old_protect
);
}
static
UINT
apc_count
;
static
void
CALLBACK
apc_func
(
ULONG_PTR
arg1
,
ULONG_PTR
arg2
,
ULONG_PTR
arg3
)
{
ok
(
arg1
==
0x1234
+
apc_count
,
"wrong arg1 %Ix
\n
"
,
arg1
);
ok
(
arg2
==
0x5678
,
"wrong arg2 %Ix
\n
"
,
arg2
);
ok
(
arg3
==
0xdeadbeef
,
"wrong arg3 %Ix
\n
"
,
arg3
);
apc_count
++
;
}
static
void
*
WINAPI
hook_KiUserApcDispatcher
(
void
*
stack
)
{
struct
{
void
*
func
;
ULONG64
args
[
3
];
ULONG64
alertable
;
ULONG64
align
;
CONTEXT
context
;
}
*
args
=
stack
;
trace
(
"stack=%p func=%p args=%Ix,%Ix,%Ix alertable=%Ix context=%p pc=%Ix sp=%Ix (%Ix)
\n
"
,
args
,
args
->
func
,
args
->
args
[
0
],
args
->
args
[
1
],
args
->
args
[
2
],
args
->
alertable
,
&
args
->
context
,
args
->
context
.
Pc
,
args
->
context
.
Sp
,
args
->
context
.
Sp
-
(
ULONG_PTR
)
stack
);
ok
(
args
->
func
==
apc_func
,
"wrong func %p / %p
\n
"
,
args
->
func
,
apc_func
);
ok
(
args
->
args
[
0
]
==
0x1234
+
apc_count
,
"wrong arg1 %Ix
\n
"
,
args
->
args
[
0
]
);
ok
(
args
->
args
[
1
]
==
0x5678
,
"wrong arg2 %Ix
\n
"
,
args
->
args
[
1
]
);
ok
(
args
->
args
[
2
]
==
0xdeadbeef
,
"wrong arg3 %Ix
\n
"
,
args
->
args
[
2
]
);
if
(
apc_count
)
args
->
alertable
=
FALSE
;
pNtQueueApcThread
(
GetCurrentThread
(),
apc_func
,
0x1234
+
apc_count
+
1
,
0x5678
,
0xdeadbeef
);
hook_called
=
TRUE
;
memcpy
(
pKiUserApcDispatcher
,
saved_code
,
sizeof
(
saved_code
));
FlushInstructionCache
(
GetCurrentProcess
(),
pKiUserApcDispatcher
,
sizeof
(
saved_code
));
return
pKiUserApcDispatcher
;
}
static
void
test_KiUserApcDispatcher
(
void
)
{
ULONG
hook_trampoline
[]
=
{
0x910003e0
,
/* mov x0, sp */
0x5800006f
,
/* ldr x15, 1f */
0xd63f01e0
,
/* blr x15 */
0xd61f0000
,
/* br x0 */
0
,
0
,
/* 1: hook_KiUserApcDispatcher */
};
DWORD
old_protect
;
BOOL
ret
;
*
(
void
**
)
&
hook_trampoline
[
4
]
=
hook_KiUserApcDispatcher
;
memcpy
(
code_mem
,
hook_trampoline
,
sizeof
(
hook_trampoline
));
ret
=
VirtualProtect
(
pKiUserApcDispatcher
,
sizeof
(
saved_code
),
PAGE_EXECUTE_READWRITE
,
&
old_protect
);
ok
(
ret
,
"Got unexpected ret %#x, GetLastError() %lu.
\n
"
,
ret
,
GetLastError
()
);
memcpy
(
saved_code
,
pKiUserApcDispatcher
,
sizeof
(
saved_code
)
);
*
(
void
**
)
&
patched_code
[
3
]
=
code_mem
;
memcpy
(
pKiUserApcDispatcher
,
patched_code
,
sizeof
(
patched_code
)
);
FlushInstructionCache
(
GetCurrentProcess
(),
pKiUserApcDispatcher
,
sizeof
(
patched_code
));
hook_called
=
FALSE
;
apc_count
=
0
;
pNtQueueApcThread
(
GetCurrentThread
(),
apc_func
,
0x1234
,
0x5678
,
0xdeadbeef
);
SleepEx
(
0
,
TRUE
);
ok
(
apc_count
==
2
,
"APC count %u
\n
"
,
apc_count
);
ok
(
hook_called
,
"hook was not called
\n
"
);
memcpy
(
pKiUserApcDispatcher
,
patched_code
,
sizeof
(
patched_code
)
);
FlushInstructionCache
(
GetCurrentProcess
(),
pKiUserApcDispatcher
,
sizeof
(
patched_code
));
pNtQueueApcThread
(
GetCurrentThread
(),
apc_func
,
0x1234
+
apc_count
,
0x5678
,
0xdeadbeef
);
SleepEx
(
0
,
TRUE
);
ok
(
apc_count
==
3
,
"APC count %u
\n
"
,
apc_count
);
SleepEx
(
0
,
TRUE
);
ok
(
apc_count
==
4
,
"APC count %u
\n
"
,
apc_count
);
VirtualProtect
(
pKiUserApcDispatcher
,
sizeof
(
saved_code
),
old_protect
,
&
old_protect
);
}
#endif
/* __aarch64__ */
#if defined(__i386__) || defined(__x86_64__)
...
...
@@ -11929,6 +12013,7 @@ START_TEST(exception)
test_continue
();
test_virtual_unwind
();
test_KiUserExceptionDispatcher
();
test_KiUserApcDispatcher
();
#elif defined(__arm__)
...
...
dlls/ntdll/unix/signal_arm64.c
View file @
060a8b4a
...
...
@@ -138,6 +138,19 @@ struct exc_stack_layout
C_ASSERT
(
offsetof
(
struct
exc_stack_layout
,
rec
)
==
0x390
);
C_ASSERT
(
sizeof
(
struct
exc_stack_layout
)
==
0x440
);
/* stack layout when calling KiUserApcDispatcher */
struct
apc_stack_layout
{
void
*
func
;
/* 000 APC to call*/
ULONG64
args
[
3
];
/* 008 function arguments */
ULONG64
alertable
;
/* 020 */
ULONG64
align
;
/* 028 */
CONTEXT
context
;
/* 030 */
ULONG64
redzone
[
2
];
/* 3c0 */
};
C_ASSERT
(
offsetof
(
struct
apc_stack_layout
,
context
)
==
0x30
);
C_ASSERT
(
sizeof
(
struct
apc_stack_layout
)
==
0x3d0
);
struct
syscall_frame
{
ULONG64
x
[
29
];
/* 000 */
...
...
@@ -979,7 +992,7 @@ NTSTATUS call_user_apc_dispatcher( CONTEXT *context, ULONG_PTR arg1, ULONG_PTR a
{
struct
syscall_frame
*
frame
=
arm64_thread_data
()
->
syscall_frame
;
ULONG64
sp
=
context
?
context
->
Sp
:
frame
->
sp
;
struct
apc_stack_layout
{
CONTEXT
context
;
}
*
stack
;
struct
apc_stack_layout
*
stack
;
sp
&=
~
15
;
stack
=
(
struct
apc_stack_layout
*
)
sp
-
1
;
...
...
@@ -994,14 +1007,14 @@ NTSTATUS call_user_apc_dispatcher( CONTEXT *context, ULONG_PTR arg1, ULONG_PTR a
NtGetContextThread
(
GetCurrentThread
(),
&
stack
->
context
);
stack
->
context
.
X0
=
status
;
}
frame
->
sp
=
(
ULONG64
)
stack
;
frame
->
pc
=
(
ULONG64
)
pKiUserApcDispatcher
;
frame
->
x
[
0
]
=
(
ULONG64
)
&
stack
->
context
;
frame
->
x
[
1
]
=
arg1
;
frame
->
x
[
2
]
=
arg2
;
frame
->
x
[
3
]
=
arg3
;
frame
->
x
[
4
]
=
(
ULONG64
)
func
;
frame
->
restore_flags
|=
CONTEXT_CONTROL
|
CONTEXT_INTEGER
;
stack
->
func
=
func
;
stack
->
args
[
0
]
=
arg1
;
stack
->
args
[
1
]
=
arg2
;
stack
->
args
[
2
]
=
arg3
;
frame
->
sp
=
(
ULONG64
)
stack
;
frame
->
pc
=
(
ULONG64
)
pKiUserApcDispatcher
;
frame
->
restore_flags
|=
CONTEXT_CONTROL
;
syscall_frame_fixup_for_fastpath
(
frame
);
return
status
;
}
...
...
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