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
31e3c431
Commit
31e3c431
authored
Feb 28, 2024
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Implement RtlCaptureContext on ARM64EC.
parent
9591a36e
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
142 additions
and
71 deletions
+142
-71
signal_arm64ec.c
dlls/ntdll/signal_arm64ec.c
+65
-2
exception.c
dlls/ntdll/tests/exception.c
+76
-68
unwind.h
dlls/ntdll/unwind.h
+1
-1
No files found.
dlls/ntdll/signal_arm64ec.c
View file @
31e3c431
...
...
@@ -1559,12 +1559,75 @@ BOOLEAN WINAPI RtlIsEcCode( const void *ptr )
}
/* capture context information; helper for RtlCaptureContext */
static
void
__attribute__
((
used
))
capture_context
(
CONTEXT
*
context
,
UINT
cpsr
,
UINT
fpcr
,
UINT
fpsr
)
{
RUNTIME_FUNCTION
*
func
;
void
*
handler_data
;
ULONG_PTR
pc
,
base
,
frame
;
CONTEXT
unwind_context
;
context
->
ContextFlags
=
CONTEXT_AMD64_FULL
;
context
->
EFlags
=
cpsr_to_eflags
(
cpsr
);
context
->
MxCsr
=
fpcsr_to_mxcsr
(
fpcr
,
fpsr
);
context
->
FltSave
.
ControlWord
=
0x27f
;
context
->
FltSave
.
StatusWord
=
0
;
context
->
FltSave
.
MxCsr
=
context
->
MxCsr
;
/* unwind one level to get register values from caller function */
unwind_context
=
*
context
;
pc
=
context
->
Rip
-
4
;
func
=
RtlLookupFunctionEntry
(
pc
,
&
base
,
NULL
);
RtlVirtualUnwind
(
UNW_FLAG_NHANDLER
,
base
,
pc
,
func
,
&
unwind_context
,
&
handler_data
,
&
frame
,
NULL
);
memcpy
(
&
context
->
Rax
,
&
unwind_context
.
Rax
,
offsetof
(
CONTEXT
,
FltSave
)
-
offsetof
(
CONTEXT
,
Rax
)
);
}
/***********************************************************************
* RtlCaptureContext (NTDLL.@)
*/
void
WINAPI
RtlCaptureContext
(
CONTEXT
*
context
)
void
__attribute__
((
naked
))
RtlCaptureContext
(
CONTEXT
*
context
)
{
FIXME
(
"not implemented
\n
"
);
asm
(
".seh_proc RtlCaptureContext
\n\t
"
".seh_endprologue
\n\t
"
"stp x8, x0, [x0, #0x78]
\n\t
"
/* context->Rax,Rcx */
"stp x1, x27, [x0, #0x88]
\n\t
"
/* context->Rdx,Rbx */
"mov x1, sp
\n\t
"
"stp x1, x29, [x0, #0x98]
\n\t
"
/* context->Rsp,Rbp */
"stp x25, x26, [x0, #0xa8]
\n\t
"
/* context->Rsi,Rdi */
"stp x2, x3, [x0, #0xb8]
\n\t
"
/* context->R8,R9 */
"stp x4, x5, [x0, #0xc8]
\n\t
"
/* context->R10,R11 */
"stp x19, x20, [x0, #0xd8]
\n\t
"
/* context->R12,R13 */
"stp x21, x22, [x0, #0xe8]
\n\t
"
/* context->R14,R15 */
"str x30, [x0, #0xf8]
\n\t
"
/* context->Rip */
"ubfx x1, x16, #0, #16
\n\t
"
"stp x30, x1, [x0, #0x120]
\n\t
"
/* context->FloatRegisters[0] */
"ubfx x1, x16, #16, #16
\n\t
"
"stp x6, x1, [x0, #0x130]
\n\t
"
/* context->FloatRegisters[1] */
"ubfx x1, x16, #32, #16
\n\t
"
"stp x7, x1, [x0, #0x140]
\n\t
"
/* context->FloatRegisters[2] */
"ubfx x1, x16, #48, #16
\n\t
"
"stp x9, x1, [x0, #0x150]
\n\t
"
/* context->FloatRegisters[3] */
"ubfx x1, x17, #0, #16
\n\t
"
"stp x10, x1, [x0, #0x160]
\n\t
"
/* context->FloatRegisters[4] */
"ubfx x1, x17, #16, #16
\n\t
"
"stp x11, x1, [x0, #0x170]
\n\t
"
/* context->FloatRegisters[5] */
"ubfx x1, x17, #32, #16
\n\t
"
"stp x12, x1, [x0, #0x180]
\n\t
"
/* context->FloatRegisters[6] */
"ubfx x1, x17, #48, #16
\n\t
"
"stp x15, x1, [x0, #0x190]
\n\t
"
/* context->FloatRegisters[7] */
"stp q0, q1, [x0, #0x1a0]
\n\t
"
/* context->Xmm0,Xmm1 */
"stp q2, q3, [x0, #0x1c0]
\n\t
"
/* context->Xmm2,Xmm3 */
"stp q4, q5, [x0, #0x1e0]
\n\t
"
/* context->Xmm4,Xmm5 */
"stp q6, q7, [x0, #0x200]
\n\t
"
/* context->Xmm6,Xmm7 */
"stp q8, q9, [x0, #0x220]
\n\t
"
/* context->Xmm8,Xmm9 */
"stp q10, q11, [x0, #0x240]
\n\t
"
/* context->Xmm10,Xmm11 */
"stp q12, q13, [x0, #0x260]
\n\t
"
/* context->Xmm12,Xmm13 */
"stp q14, q15, [x0, #0x280]
\n\t
"
/* context->Xmm14,Xmm15 */
"mrs x1, nzcv
\n\t
"
"mrs x2, fpcr
\n\t
"
"mrs x3, fpsr
\n\t
"
"b capture_context
\n\t
"
".seh_endproc"
);
}
...
...
dlls/ntdll/tests/exception.c
View file @
31e3c431
...
...
@@ -20,6 +20,7 @@
#include <stdarg.h>
#include <stdio.h>
#include <setjmp.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
...
...
@@ -110,38 +111,6 @@ static void (WINAPI *pRtlGetUnloadEventTraceEx)(ULONG **element_size, ULONG **el
#endif
#if defined(__x86_64__)
typedef
struct
_SETJMP_FLOAT128
{
unsigned
__int64
DECLSPEC_ALIGN
(
16
)
Part
[
2
];
}
SETJMP_FLOAT128
;
typedef
struct
_JUMP_BUFFER
{
unsigned
__int64
Frame
;
unsigned
__int64
Rbx
;
unsigned
__int64
Rsp
;
unsigned
__int64
Rbp
;
unsigned
__int64
Rsi
;
unsigned
__int64
Rdi
;
unsigned
__int64
R12
;
unsigned
__int64
R13
;
unsigned
__int64
R14
;
unsigned
__int64
R15
;
unsigned
__int64
Rip
;
unsigned
long
MxCsr
;
unsigned
short
FpCsr
;
unsigned
short
Spare
;
SETJMP_FLOAT128
Xmm6
;
SETJMP_FLOAT128
Xmm7
;
SETJMP_FLOAT128
Xmm8
;
SETJMP_FLOAT128
Xmm9
;
SETJMP_FLOAT128
Xmm10
;
SETJMP_FLOAT128
Xmm11
;
SETJMP_FLOAT128
Xmm12
;
SETJMP_FLOAT128
Xmm13
;
SETJMP_FLOAT128
Xmm14
;
SETJMP_FLOAT128
Xmm15
;
}
_JUMP_BUFFER
;
typedef
union
_UNWIND_CODE
{
...
...
@@ -173,12 +142,14 @@ typedef struct _UNWIND_INFO
*/
}
UNWIND_INFO
;
static
BOOL
is_arm64ec
;
static
EXCEPTION_DISPOSITION
(
WINAPI
*
p__C_specific_handler
)(
EXCEPTION_RECORD
*
,
ULONG64
,
CONTEXT
*
,
DISPATCHER_CONTEXT
*
);
static
VOID
(
WINAPI
*
pRtlCaptureContext
)(
CONTEXT
*
);
static
VOID
(
CDECL
*
pRtlRestoreContext
)(
CONTEXT
*
,
EXCEPTION_RECORD
*
);
static
NTSTATUS
(
WINAPI
*
pRtlWow64GetThreadContext
)(
HANDLE
,
WOW64_CONTEXT
*
);
static
NTSTATUS
(
WINAPI
*
pRtlWow64SetThreadContext
)(
HANDLE
,
const
WOW64_CONTEXT
*
);
static
NTSTATUS
(
WINAPI
*
pRtlWow64GetCpuAreaInfo
)(
WOW64_CPURESERVED
*
,
ULONG
,
WOW64_CPU_AREA_INFO
*
);
static
NTSTATUS
(
WINAPI
*
pRtlGetNativeSystemInformation
)(
SYSTEM_INFORMATION_CLASS
,
void
*
,
ULONG
,
ULONG
*
);
static
int
(
CDECL
*
p_setjmp
)(
_JUMP_BUFFER
*
);
#endif
...
...
@@ -3745,34 +3716,53 @@ static void test_thread_context(void)
memset
(
&
expect
,
0xcc
,
sizeof
(
expect
)
);
func_ptr
(
&
context
,
0
,
&
expect
,
pRtlCaptureContext
);
ok
(
context
.
ContextFlags
==
(
CONTEXT_CONTROL
|
CONTEXT_INTEGER
|
CONTEXT_SEGMENTS
|
CONTEXT_FLOATING_POINT
),
"wrong flags %08lx
\n
"
,
context
.
ContextFlags
);
COMPARE
(
Rax
);
if
(
is_arm64ec
)
{
ok
(
context
.
ContextFlags
==
(
CONTEXT_CONTROL
|
CONTEXT_INTEGER
|
CONTEXT_FLOATING_POINT
),
"wrong flags %08lx
\n
"
,
context
.
ContextFlags
);
ok
(
(
context
.
EFlags
&
~
0xc5
)
==
(
expect
.
EFlags
&
~
0xc5
),
"wrong EFlags %lx / %I64x
\n
"
,
context
.
EFlags
,
expect
.
EFlags
);
ok
(
context
.
SegCs
==
0xcccc
,
"wrong SegCs %x
\n
"
,
context
.
SegCs
);
ok
(
context
.
SegDs
==
0xcccc
,
"wrong SegDs %x
\n
"
,
context
.
SegDs
);
ok
(
context
.
SegEs
==
0xcccc
,
"wrong SegEs %x
\n
"
,
context
.
SegEs
);
ok
(
context
.
SegFs
==
0xcccc
,
"wrong SegFs %x
\n
"
,
context
.
SegFs
);
ok
(
context
.
SegGs
==
0xcccc
,
"wrong SegGs %x
\n
"
,
context
.
SegGs
);
ok
(
context
.
SegSs
==
0xcccc
,
"wrong SegSs %x
\n
"
,
context
.
SegSs
);
}
else
{
ok
(
context
.
ContextFlags
==
(
CONTEXT_CONTROL
|
CONTEXT_INTEGER
|
CONTEXT_SEGMENTS
|
CONTEXT_FLOATING_POINT
),
"wrong flags %08lx
\n
"
,
context
.
ContextFlags
);
COMPARE
(
Rax
);
COMPARE
(
Rcx
);
COMPARE
(
Rdx
);
COMPARE
(
R8
);
COMPARE
(
R9
);
COMPARE
(
R10
);
COMPARE
(
R11
);
COMPARE
(
EFlags
);
COMPARE
(
SegCs
);
COMPARE
(
SegDs
);
COMPARE
(
SegEs
);
COMPARE
(
SegFs
);
COMPARE
(
SegGs
);
COMPARE
(
SegSs
);
ok
(
!
memcmp
(
&
context
.
FltSave
,
&
expect
.
FltSave
,
offsetof
(
XMM_SAVE_AREA32
,
XmmRegisters
)),
"wrong FltSave
\n
"
);
}
COMPARE
(
Rbx
);
COMPARE
(
Rcx
);
COMPARE
(
Rdx
);
COMPARE
(
Rsi
);
COMPARE
(
Rdi
);
COMPARE
(
R8
);
COMPARE
(
R9
);
COMPARE
(
R10
);
COMPARE
(
R11
);
COMPARE
(
R12
);
COMPARE
(
R13
);
COMPARE
(
R14
);
COMPARE
(
R15
);
COMPARE
(
Rbp
);
COMPARE
(
Rsp
);
COMPARE
(
EFlags
);
COMPARE
(
MxCsr
);
COMPARE
(
SegCs
);
COMPARE
(
SegDs
);
COMPARE
(
SegEs
);
COMPARE
(
SegFs
);
COMPARE
(
SegGs
);
COMPARE
(
SegSs
);
ok
(
!
memcmp
(
&
context
.
FltSave
,
&
expect
.
FltSave
,
offsetof
(
XMM_SAVE_AREA32
,
XmmRegisters
)),
"wrong FltSave
\n
"
);
COMPARE
(
FltSave
.
MxCsr
);
COMPARE
(
FltSave
.
ControlWord
);
COMPARE
(
FltSave
.
StatusWord
);
for
(
i
=
0
;
i
<
16
;
i
++
)
ok
(
!
memcmp
(
&
context
.
Xmm0
+
i
,
&
expect
.
FltSave
.
XmmRegisters
[
i
],
sizeof
(
context
.
Xmm0
)
),
"wrong xmm%u
\n
"
,
i
);
...
...
@@ -3786,15 +3776,32 @@ static void test_thread_context(void)
status
=
func_ptr
(
GetCurrentThread
(),
&
context
,
&
expect
,
pNtGetContextThread
);
ok
(
status
==
STATUS_SUCCESS
,
"NtGetContextThread failed %08lx
\n
"
,
status
);
/* other registers are not preserved */
COMPARE
(
Rbx
);
COMPARE
(
Rsi
);
COMPARE
(
Rdi
);
COMPARE
(
R12
);
COMPARE
(
R13
);
COMPARE
(
R14
);
COMPARE
(
R15
);
COMPARE
(
Rbp
);
if
(
is_arm64ec
)
{
/* Rsp is the stack upon entry to the ARM64 NtGetContextThread syscall */
ok
(
context
.
Rsp
<=
expect
.
Rsp
-
sizeof
(
ARM64_NT_CONTEXT
)
&&
context
.
Rsp
>=
expect
.
Rsp
-
0x1000
,
"wrong Rsp %p/%p
\n
"
,
(
void
*
)
context
.
Rsp
,
(
void
*
)
expect
.
Rsp
);
}
else
{
/* other registers are not preserved */
COMPARE
(
Rbx
);
COMPARE
(
Rsi
);
COMPARE
(
Rdi
);
COMPARE
(
R12
);
COMPARE
(
R13
);
COMPARE
(
R14
);
COMPARE
(
R15
);
COMPARE
(
Rbp
);
/* Rsp is the stack upon entry to NtGetContextThread */
ok
(
context
.
Rsp
==
expect
.
Rsp
-
8
,
"wrong Rsp %p/%p
\n
"
,
(
void
*
)
context
.
Rsp
,
(
void
*
)
expect
.
Rsp
);
/* Rip is somewhere close to the NtGetContextThread implementation */
ok
(
(
char
*
)
context
.
Rip
>=
(
char
*
)
pNtGetContextThread
-
0x40000
&&
(
char
*
)
context
.
Rip
<=
(
char
*
)
pNtGetContextThread
+
0x40000
,
"wrong Rip %p/%p
\n
"
,
(
void
*
)
context
.
Rip
,
(
void
*
)
pNtGetContextThread
);
}
COMPARE
(
MxCsr
);
COMPARE
(
SegCs
);
COMPARE
(
SegDs
);
...
...
@@ -3812,13 +3819,6 @@ static void test_thread_context(void)
for
(
i
=
6
;
i
<
16
;
i
++
)
ok
(
!
memcmp
(
&
context
.
Xmm0
+
i
,
&
expect
.
FltSave
.
XmmRegisters
[
i
],
sizeof
(
context
.
Xmm0
)
),
"wrong xmm%u
\n
"
,
i
);
/* Rsp is the stack upon entry to NtGetContextThread */
ok
(
context
.
Rsp
==
expect
.
Rsp
-
8
,
"wrong Rsp %p/%p
\n
"
,
(
void
*
)
context
.
Rsp
,
(
void
*
)
expect
.
Rsp
);
/* Rip is somewhere close to the NtGetContextThread implementation */
ok
(
(
char
*
)
context
.
Rip
>=
(
char
*
)
pNtGetContextThread
-
0x40000
&&
(
char
*
)
context
.
Rip
<=
(
char
*
)
pNtGetContextThread
+
0x40000
,
"wrong Rip %p/%p
\n
"
,
(
void
*
)
context
.
Rip
,
(
void
*
)
pNtGetContextThread
);
#undef COMPARE
}
...
...
@@ -10116,14 +10116,22 @@ START_TEST(exception)
#define X(f) p##f = (void*)GetProcAddress(hntdll, #f)
X
(
__C_specific_handler
);
X
(
RtlCaptureContext
);
X
(
RtlRestoreContext
);
X
(
RtlWow64GetThreadContext
);
X
(
RtlWow64SetThreadContext
);
X
(
RtlWow64GetCpuAreaInfo
);
X
(
RtlGetNativeSystemInformation
);
#undef X
p_setjmp
=
(
void
*
)
GetProcAddress
(
hmsvcrt
,
"_setjmp"
);
if
(
pRtlGetNativeSystemInformation
)
{
SYSTEM_CPU_INFORMATION
info
;
ULONG
len
;
if
(
!
pRtlGetNativeSystemInformation
(
SystemCpuInformation
,
&
info
,
sizeof
(
info
),
&
len
))
is_arm64ec
=
(
info
.
ProcessorArchitecture
==
PROCESSOR_ARCHITECTURE_ARM64
);
}
test_exceptions
();
test_rtlraiseexception
();
test_debug_registers
();
...
...
dlls/ntdll/unwind.h
View file @
31e3c431
...
...
@@ -63,7 +63,7 @@ static inline UINT eflags_to_cpsr( UINT eflags )
static
inline
UINT
cpsr_to_eflags
(
UINT
cpsr
)
{
UINT
ret
=
0
;
UINT
ret
=
0
x202
;
if
(
cpsr
&
0x10000000
)
ret
|=
0x0800
;
/* overflow */
if
(
cpsr
&
0x20000000
)
ret
|=
0x0001
;
/* carry */
...
...
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