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
89f3c597
Commit
89f3c597
authored
Dec 03, 2023
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Fix stack layout for KiUserExceptionDispatcher on ARM.
parent
42046a24
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
139 additions
and
39 deletions
+139
-39
signal_arm.c
dlls/ntdll/signal_arm.c
+17
-1
exception.c
dlls/ntdll/tests/exception.c
+103
-0
signal_arm.c
dlls/ntdll/unix/signal_arm.c
+19
-38
No files found.
dlls/ntdll/signal_arm.c
View file @
89f3c597
...
...
@@ -463,7 +463,7 @@ static NTSTATUS call_function_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_con
/*******************************************************************
* KiUserExceptionDispatcher (NTDLL.@)
*/
NTSTATUS
WINAPI
KiUserExceptionDispatcher
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
)
NTSTATUS
WINAPI
dispatch_exception
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
)
{
NTSTATUS
status
;
DWORD
c
;
...
...
@@ -526,6 +526,22 @@ NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *conte
if
(
status
!=
STATUS_UNHANDLED_EXCEPTION
)
RtlRaiseStatus
(
status
);
return
NtRaiseException
(
rec
,
context
,
FALSE
);
}
__ASM_GLOBAL_FUNC
(
KiUserExceptionDispatcher
,
__ASM_SEH
(
".seh_custom 0xee,0x02
\n\t
"
)
/* MSFT_OP_CONTEXT */
__ASM_SEH
(
".seh_endprologue
\n\t
"
)
__ASM_EHABI
(
".save {sp}
\n\t
"
)
/* Restore Sp last */
__ASM_EHABI
(
".pad #-(0x80 + 0x0c + 0x0c)
\n\t
"
)
/* Move back across D0-D15, Cpsr, Fpscr, Padding, Pc, Lr and Sp */
__ASM_EHABI
(
".vsave {d8-d15}
\n\t
"
)
__ASM_EHABI
(
".pad #0x40
\n\t
"
)
/* Skip past D0-D7 */
__ASM_EHABI
(
".pad #0x0c
\n\t
"
)
/* Skip past Cpsr, Fpscr and Padding */
__ASM_EHABI
(
".save {lr, pc}
\n\t
"
)
__ASM_EHABI
(
".pad #0x08
\n\t
"
)
/* Skip past R12 and Sp - Sp is restored last */
__ASM_EHABI
(
".save {r4-r11}
\n\t
"
)
__ASM_EHABI
(
".pad #0x14
\n\t
"
)
/* Skip past ContextFlags and R0-R3 */
"add r0, sp, #0x1a0
\n\t
"
/* rec (context + 1) */
"mov r1, sp
\n\t
"
/* context */
"bl "
__ASM_NAME
(
"dispatch_exception"
)
"
\n\t
"
"udf #1"
)
/*******************************************************************
...
...
dlls/ntdll/tests/exception.c
View file @
89f3c597
...
...
@@ -7343,6 +7343,108 @@ static void test_debug_service(DWORD numexc)
/* not supported */
}
static
BOOL
hook_called
;
static
BOOL
got_exception
;
static
void
*
code_ptr
;
static
WORD
patched_code
[]
=
{
0x4668
,
/* mov r0, sp */
0xf8df
,
0xc004
,
/* ldr.w ip, [pc, #0x4] */
0x4760
,
/* bx ip */
0
,
0
,
/* 1: hook_trampoline */
};
static
WORD
saved_code
[
ARRAY_SIZE
(
patched_code
)];
static
LONG
WINAPI
dbg_except_continue_vectored_handler
(
struct
_EXCEPTION_POINTERS
*
ptrs
)
{
EXCEPTION_RECORD
*
rec
=
ptrs
->
ExceptionRecord
;
CONTEXT
*
context
=
ptrs
->
ContextRecord
;
trace
(
"dbg_except_continue_vectored_handler, code %#lx, pc %#lx.
\n
"
,
rec
->
ExceptionCode
,
context
->
Pc
);
got_exception
=
TRUE
;
ok
(
rec
->
ExceptionCode
==
0x80000003
,
"Got unexpected exception code %#lx.
\n
"
,
rec
->
ExceptionCode
);
return
EXCEPTION_CONTINUE_EXECUTION
;
}
static
void
*
WINAPI
hook_KiUserExceptionDispatcher
(
void
*
stack
)
{
CONTEXT
*
context
=
stack
;
EXCEPTION_RECORD
*
rec
=
(
EXCEPTION_RECORD
*
)(
context
+
1
);
trace
(
"rec %p context %p pc %#lx sp %#lx flags %#lx
\n
"
,
rec
,
context
,
context
->
Pc
,
context
->
Sp
,
context
->
ContextFlags
);
ok
(
!
((
ULONG_PTR
)
stack
&
7
),
"unaligned stack %p
\n
"
,
stack
);
ok
(
rec
->
ExceptionCode
==
0x80000003
,
"Got unexpected ExceptionCode %#lx.
\n
"
,
rec
->
ExceptionCode
);
hook_called
=
TRUE
;
memcpy
(
code_ptr
,
saved_code
,
sizeof
(
saved_code
));
FlushInstructionCache
(
GetCurrentProcess
(),
code_ptr
,
sizeof
(
saved_code
));
return
pKiUserExceptionDispatcher
;
}
static
void
test_KiUserExceptionDispatcher
(
void
)
{
WORD
hook_trampoline
[]
=
{
0x4668
,
/* mov r0, sp */
0xf8df
,
0xc006
,
/* ldr.w r12, [pc, #0x6] */
0x47e0
,
/* blx r12 */
0x4700
,
/* bx r0 */
0
,
0
,
/* 1: hook_KiUserExceptionDispatcher */
};
EXCEPTION_RECORD
record
=
{
EXCEPTION_BREAKPOINT
};
void
*
trampoline_ptr
,
*
vectored_handler
;
DWORD
old_protect
;
BOOL
ret
;
code_ptr
=
(
void
*
)(((
ULONG_PTR
)
pKiUserExceptionDispatcher
)
&
~
1
);
/* mask thumb bit */
*
(
void
**
)
&
hook_trampoline
[
5
]
=
hook_KiUserExceptionDispatcher
;
trampoline_ptr
=
(
char
*
)
code_mem
+
1024
;
memcpy
(
trampoline_ptr
,
hook_trampoline
,
sizeof
(
hook_trampoline
));
ret
=
VirtualProtect
(
code_ptr
,
sizeof
(
saved_code
),
PAGE_EXECUTE_READWRITE
,
&
old_protect
);
ok
(
ret
,
"Got unexpected ret %#x, GetLastError() %lu.
\n
"
,
ret
,
GetLastError
()
);
memcpy
(
saved_code
,
code_ptr
,
sizeof
(
saved_code
)
);
*
(
void
**
)
&
patched_code
[
4
]
=
(
char
*
)
trampoline_ptr
+
1
;
/* thumb */
vectored_handler
=
AddVectoredExceptionHandler
(
TRUE
,
dbg_except_continue_vectored_handler
);
memcpy
(
code_ptr
,
patched_code
,
sizeof
(
patched_code
)
);
FlushInstructionCache
(
GetCurrentProcess
(),
code_ptr
,
sizeof
(
patched_code
));
got_exception
=
FALSE
;
hook_called
=
FALSE
;
pRtlRaiseException
(
&
record
);
ok
(
got_exception
,
"Handler was not called.
\n
"
);
todo_wine
ok
(
!
hook_called
,
"Hook was called.
\n
"
);
memcpy
(
code_ptr
,
patched_code
,
sizeof
(
patched_code
)
);
FlushInstructionCache
(
GetCurrentProcess
(),
code_ptr
,
sizeof
(
patched_code
));
got_exception
=
0
;
hook_called
=
FALSE
;
NtCurrentTeb
()
->
Peb
->
BeingDebugged
=
1
;
pRtlRaiseException
(
&
record
);
ok
(
got_exception
,
"Handler was not called.
\n
"
);
ok
(
hook_called
,
"Hook was not called.
\n
"
);
NtCurrentTeb
()
->
Peb
->
BeingDebugged
=
0
;
RemoveVectoredExceptionHandler
(
vectored_handler
);
VirtualProtect
(
code_ptr
,
sizeof
(
saved_code
),
old_protect
,
&
old_protect
);
}
#elif defined(__aarch64__)
#define UNW_FLAG_NHANDLER 0
...
...
@@ -12245,6 +12347,7 @@ START_TEST(exception)
#elif defined(__arm__)
test_virtual_unwind
();
test_KiUserExceptionDispatcher
();
#endif
...
...
dlls/ntdll/unix/signal_arm.c
View file @
89f3c597
...
...
@@ -174,6 +174,16 @@ enum arm_trap_code
TRAP_ARM_ALIGNFLT
=
17
,
/* Alignment check exception */
};
/* stack layout when calling KiUserExceptionDispatcher */
struct
exc_stack_layout
{
CONTEXT
context
;
/* 000 */
EXCEPTION_RECORD
rec
;
/* 1a0 */
ULONG
redzone
[
2
];
/* 1f0 */
};
C_ASSERT
(
offsetof
(
struct
exc_stack_layout
,
rec
)
==
0x1a0
);
C_ASSERT
(
sizeof
(
struct
exc_stack_layout
)
==
0x1f8
);
struct
syscall_frame
{
UINT
r0
;
/* 000 */
...
...
@@ -1019,25 +1029,6 @@ NTSTATUS get_thread_wow64_context( HANDLE handle, void *ctx, ULONG size )
}
__ASM_GLOBAL_FUNC
(
raise_func_trampoline
,
"push {r12,lr}
\n\t
"
/* (Padding +) Pc in the original frame */
"ldr r3, [r1, #0x38]
\n\t
"
/* context->Sp */
"push {r3}
\n\t
"
/* Original Sp */
__ASM_CFI_CFA_IS_AT1
(
sp
,
0x04
)
__ASM_CFI_REG_IS_AT1
(
lr
,
sp
,
0x0c
)
__ASM_EHABI
(
".save {sp}
\n\t
"
)
__ASM_EHABI
(
".pad #-12
\n\t
"
)
__ASM_EHABI
(
".save {pc}
\n\t
"
)
__ASM_EHABI
(
".pad #8
\n\t
"
)
__ASM_EHABI
(
".save {lr}
\n\t
"
)
/* We can't express restoring both Pc and Lr with CFI
* directives, but we manually load Lr from the stack
* in unwind_builtin_dll above. */
"ldr r3, [r1, #0x3c]
\n\t
"
/* context->Lr */
"push {r3}
\n\t
"
/* Original Lr */
"blx r2
\n\t
"
"udf #0"
)
/***********************************************************************
* setup_exception
*
...
...
@@ -1045,13 +1036,8 @@ __ASM_GLOBAL_FUNC( raise_func_trampoline,
*/
static
void
setup_exception
(
ucontext_t
*
sigcontext
,
EXCEPTION_RECORD
*
rec
)
{
struct
{
CONTEXT
context
;
EXCEPTION_RECORD
rec
;
}
*
stack
;
void
*
stack_ptr
=
(
void
*
)(
SP_sig
(
sigcontext
)
&
~
3
);
struct
exc_stack_layout
*
stack
;
void
*
stack_ptr
=
(
void
*
)(
SP_sig
(
sigcontext
)
&
~
7
);
CONTEXT
context
;
NTSTATUS
status
;
...
...
@@ -1071,13 +1057,9 @@ static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec )
/* now modify the sigcontext to return to the raise function */
SP_sig
(
sigcontext
)
=
(
DWORD
)
stack
;
LR_sig
(
sigcontext
)
=
context
.
Pc
;
PC_sig
(
sigcontext
)
=
(
DWORD
)
raise_func_trampoline
;
PC_sig
(
sigcontext
)
=
(
DWORD
)
pKiUserExceptionDispatcher
;
if
(
PC_sig
(
sigcontext
)
&
1
)
CPSR_sig
(
sigcontext
)
|=
0x20
;
else
CPSR_sig
(
sigcontext
)
&=
~
0x20
;
REGn_sig
(
0
,
sigcontext
)
=
(
DWORD
)
&
stack
->
rec
;
/* first arg for KiUserExceptionDispatcher */
REGn_sig
(
1
,
sigcontext
)
=
(
DWORD
)
&
stack
->
context
;
/* second arg for KiUserExceptionDispatcher */
REGn_sig
(
2
,
sigcontext
)
=
(
DWORD
)
pKiUserExceptionDispatcher
;
}
...
...
@@ -1135,18 +1117,17 @@ void call_raise_user_exception_dispatcher(void)
*/
NTSTATUS
call_user_exception_dispatcher
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
)
{
struct
exc_stack_layout
*
stack
;
struct
syscall_frame
*
frame
=
arm_thread_data
()
->
syscall_frame
;
DWORD
lr
=
frame
->
lr
;
DWORD
sp
=
frame
->
sp
;
NTSTATUS
status
=
NtSetContextThread
(
GetCurrentThread
(),
context
);
if
(
status
)
return
status
;
frame
->
r0
=
(
DWORD
)
rec
;
frame
->
r1
=
(
DWORD
)
context
;
stack
=
(
struct
exc_stack_layout
*
)(
context
->
Sp
&
~
7
)
-
1
;
memmove
(
&
stack
->
context
,
context
,
sizeof
(
*
context
)
);
memmove
(
&
stack
->
rec
,
rec
,
sizeof
(
*
rec
)
);
frame
->
pc
=
(
DWORD
)
pKiUserExceptionDispatcher
;
frame
->
lr
=
lr
;
frame
->
sp
=
sp
;
frame
->
restore_flags
|=
CONTEXT_INTEGER
|
CONTEXT_CONTROL
;
frame
->
sp
=
(
DWORD
)
stack
;
frame
->
restore_flags
|=
CONTEXT_CONTROL
;
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