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
ca598405
Commit
ca598405
authored
Feb 29, 2024
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Implement RtlVirtualUnwind2.
parent
9ac8d63e
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
116 additions
and
22 deletions
+116
-22
signal_arm.c
dlls/ntdll/signal_arm.c
+3
-4
signal_arm64.c
dlls/ntdll/signal_arm64.c
+4
-4
signal_x86_64.c
dlls/ntdll/signal_x86_64.c
+3
-5
unwind.c
dlls/ntdll/tests/unwind.c
+106
-9
unwind.c
dlls/ntdll/unwind.c
+0
-0
No files found.
dlls/ntdll/signal_arm.c
View file @
ca598405
...
...
@@ -125,10 +125,9 @@ static NTSTATUS virtual_unwind( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEX
dispatch
->
FunctionEntry
=
RtlLookupFunctionEntry
(
pc
,
(
DWORD_PTR
*
)
&
dispatch
->
ImageBase
,
dispatch
->
HistoryTable
);
dispatch
->
LanguageHandler
=
RtlVirtualUnwind
(
type
,
dispatch
->
ImageBase
,
pc
,
dispatch
->
FunctionEntry
,
context
,
&
dispatch
->
HandlerData
,
(
ULONG_PTR
*
)
&
dispatch
->
EstablisherFrame
,
NULL
);
if
(
!
context
->
Pc
)
if
(
RtlVirtualUnwind2
(
type
,
dispatch
->
ImageBase
,
pc
,
dispatch
->
FunctionEntry
,
context
,
NULL
,
&
dispatch
->
HandlerData
,
(
ULONG_PTR
*
)
&
dispatch
->
EstablisherFrame
,
NULL
,
NULL
,
NULL
,
&
dispatch
->
LanguageHandler
,
0
))
{
WARN
(
"exception data not found for pc %p, lr %p
\n
"
,
(
void
*
)
pc
,
(
void
*
)
context
->
Lr
);
return
STATUS_INVALID_DISPOSITION
;
...
...
dlls/ntdll/signal_arm64.c
View file @
ca598405
...
...
@@ -155,10 +155,10 @@ static NTSTATUS virtual_unwind( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEX
if
(
dispatch
->
ControlPcIsUnwound
)
pc
-=
4
;
dispatch
->
FunctionEntry
=
RtlLookupFunctionEntry
(
pc
,
&
dispatch
->
ImageBase
,
dispatch
->
HistoryTable
);
dispatch
->
LanguageHandler
=
RtlVirtualUnwind
(
type
,
dispatch
->
ImageBase
,
pc
,
dispatch
->
FunctionEntry
,
context
,
&
dispatch
->
HandlerData
,
&
dispatch
->
EstablisherFrame
,
NULL
);
if
(
!
context
->
Pc
)
if
(
RtlVirtualUnwind2
(
type
,
dispatch
->
ImageBase
,
pc
,
dispatch
->
FunctionEntry
,
context
,
NULL
,
&
dispatch
->
HandlerData
,
&
dispatch
->
EstablisherFrame
,
NULL
,
NULL
,
NULL
,
&
dispatch
->
LanguageHandler
,
0
)
)
{
WARN
(
"exception data not found for pc %p, lr %p
\n
"
,
(
void
*
)
pc
,
(
void
*
)
context
->
Lr
);
return
STATUS_INVALID_DISPOSITION
;
...
...
dlls/ntdll/signal_x86_64.c
View file @
ca598405
...
...
@@ -119,11 +119,9 @@ static NTSTATUS virtual_unwind( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEX
}
else
WARN
(
"exception data not found for pc %p
\n
"
,
(
void
*
)
context
->
Rip
);
dispatch
->
LanguageHandler
=
RtlVirtualUnwind
(
type
,
dispatch
->
ImageBase
,
context
->
Rip
,
dispatch
->
FunctionEntry
,
context
,
&
dispatch
->
HandlerData
,
&
dispatch
->
EstablisherFrame
,
NULL
);
return
STATUS_SUCCESS
;
return
RtlVirtualUnwind2
(
type
,
dispatch
->
ImageBase
,
context
->
Rip
,
dispatch
->
FunctionEntry
,
context
,
NULL
,
&
dispatch
->
HandlerData
,
&
dispatch
->
EstablisherFrame
,
NULL
,
NULL
,
NULL
,
&
dispatch
->
LanguageHandler
,
0
);
}
...
...
dlls/ntdll/tests/unwind.c
View file @
ca598405
...
...
@@ -46,6 +46,7 @@ static BOOLEAN (CDECL *pRtlDeleteFunctionTable)(RUNTIME_FUNCTION*);
static
DWORD
(
WINAPI
*
pRtlAddGrowableFunctionTable
)(
void
**
,
RUNTIME_FUNCTION
*
,
DWORD
,
DWORD
,
ULONG_PTR
,
ULONG_PTR
);
static
void
(
WINAPI
*
pRtlGrowFunctionTable
)(
void
*
,
DWORD
);
static
void
(
WINAPI
*
pRtlDeleteGrowableFunctionTable
)(
void
*
);
static
NTSTATUS
(
WINAPI
*
pRtlVirtualUnwind2
)(
ULONG
,
ULONG_PTR
,
ULONG_PTR
,
RUNTIME_FUNCTION
*
,
CONTEXT
*
,
BOOLEAN
*
,
void
**
,
ULONG_PTR
*
,
KNONVOLATILE_CONTEXT_POINTERS
*
,
ULONG_PTR
*
,
ULONG_PTR
*
,
PEXCEPTION_ROUTINE
*
,
ULONG
);
static
NTSTATUS
(
WINAPI
*
pNtAllocateVirtualMemoryEx
)(
HANDLE
,
PVOID
*
,
SIZE_T
*
,
ULONG
,
ULONG
,
MEM_EXTENDED_PARAMETER
*
,
ULONG
);
#ifdef __arm__
...
...
@@ -125,8 +126,10 @@ static void call_virtual_unwind_arm( int testnum, const struct unwind_test_arm *
{
static
const
int
code_offset
=
1024
;
static
const
int
unwind_offset
=
2048
;
void
*
handler
,
*
data
;
void
*
data
;
CONTEXT
context
;
NTSTATUS
status
;
PEXCEPTION_ROUTINE
handler
;
RUNTIME_FUNCTION
runtime_func
;
KNONVOLATILE_CONTEXT_POINTERS
ctx_ptr
;
UINT
i
,
j
,
k
;
...
...
@@ -163,11 +166,44 @@ static void call_virtual_unwind_arm( int testnum, const struct unwind_test_arm *
trace
(
"%u/%u: pc=%p (%02x) fp=%p sp=%p
\n
"
,
testnum
,
i
,
(
void
*
)
orig_pc
,
*
(
UINT
*
)
orig_pc
,
(
void
*
)
orig_fp
,
(
void
*
)
context
.
Sp
);
if
(
test
->
results
[
i
].
handler
==
-
2
)
orig_pc
=
context
.
Lr
;
if
(
pRtlVirtualUnwind2
)
{
CONTEXT
new_context
=
context
;
handler
=
(
void
*
)
0xdeadbeef
;
data
=
(
void
*
)
0xdeadbeef
;
frame
=
0xdeadbeef
;
status
=
pRtlVirtualUnwind2
(
UNW_FLAG_EHANDLER
,
(
ULONG
)
code_mem
,
orig_pc
,
test
->
unwind_info
?
&
runtime_func
:
NULL
,
&
new_context
,
NULL
,
&
data
,
&
frame
,
&
ctx_ptr
,
NULL
,
NULL
,
&
handler
,
0
);
if
(
test
->
results
[
i
].
handler
>
0
)
{
ok
(
!
status
,
"RtlVirtualUnwind2 failed %lx
\n
"
,
status
);
ok
(
(
char
*
)
handler
==
(
char
*
)
code_mem
+
0x200
,
"%u/%u: wrong handler %p/%p
\n
"
,
testnum
,
i
,
handler
,
(
char
*
)
code_mem
+
0x200
);
if
(
handler
)
ok
(
*
(
DWORD
*
)
data
==
0x08070605
,
"%u/%u: wrong handler data %lx
\n
"
,
testnum
,
i
,
*
(
DWORD
*
)
data
);
}
else
if
(
test
->
results
[
i
].
handler
<
-
1
)
{
ok
(
status
==
STATUS_BAD_FUNCTION_TABLE
,
"RtlVirtualUnwind2 failed %lx
\n
"
,
status
);
ok
(
handler
==
(
void
*
)
0xdeadbeef
,
"handler set to %p
\n
"
,
handler
);
ok
(
data
==
(
void
*
)
0xdeadbeef
,
"handler data set to %p
\n
"
,
data
);
}
else
{
ok
(
!
status
,
"RtlVirtualUnwind2 failed %lx
\n
"
,
status
);
ok
(
handler
==
NULL
,
"handler %p instead of NULL
\n
"
,
handler
);
ok
(
data
==
NULL
,
"handler data set to %p
\n
"
,
data
);
}
}
data
=
(
void
*
)
0xdeadbeef
;
frame
=
0xdeadbeef
;
if
(
test
->
results
[
i
].
handler
==
-
2
)
orig_pc
=
context
.
Lr
;
handler
=
RtlVirtualUnwind
(
UNW_FLAG_EHANDLER
,
(
ULONG
)
code_mem
,
orig_pc
,
test
->
unwind_info
?
(
RUNTIME_FUNCTION
*
)
&
runtime_func
:
NULL
,
test
->
unwind_info
?
&
runtime_func
:
NULL
,
&
context
,
&
data
,
&
frame
,
&
ctx_ptr
);
if
(
test
->
results
[
i
].
handler
>
0
)
{
...
...
@@ -1558,15 +1594,17 @@ static void call_virtual_unwind_arm64( void *code_mem, int testnum, const struct
{
static
const
int
code_offset
=
1024
;
static
const
int
unwind_offset
=
2048
;
void
*
handler
,
*
data
;
void
*
data
;
#ifdef __x86_64__
ARM64EC_NT_CONTEXT
context
;
ARM64EC_NT_CONTEXT
context
,
new_context
;
#else
ARM64_NT_CONTEXT
context
;
ARM64_NT_CONTEXT
context
,
new_context
;
#endif
PEXCEPTION_ROUTINE
handler
;
ARM64_RUNTIME_FUNCTION
runtime_func
;
KNONVOLATILE_CONTEXT_POINTERS
ctx_ptr
;
UINT
i
,
j
,
k
;
NTSTATUS
status
;
ULONG64
fake_stack
[
256
];
ULONG64
frame
,
orig_pc
,
orig_fp
,
unset_reg
,
sp_offset
=
0
,
regval
,
*
regptr
;
static
const
UINT
nb_regs
=
ARRAY_SIZE
(
test
->
results
[
i
].
regs
);
...
...
@@ -1604,9 +1642,42 @@ static void call_virtual_unwind_arm64( void *code_mem, int testnum, const struct
trace
(
"pc=%p (%02x) fp=%p sp=%p
\n
"
,
(
void
*
)
orig_pc
,
*
(
UINT
*
)
orig_pc
,
(
void
*
)
orig_fp
,
(
void
*
)
context
.
Sp
);
if
(
test
->
results
[
i
].
handler
==
-
2
)
orig_pc
=
context
.
Lr
;
if
(
pRtlVirtualUnwind2
)
{
new_context
=
context
;
handler
=
(
void
*
)
0xdeadbeef
;
data
=
(
void
*
)
0xdeadbeef
;
frame
=
0xdeadbeef
;
status
=
pRtlVirtualUnwind2
(
UNW_FLAG_EHANDLER
,
(
ULONG_PTR
)
code_mem
,
orig_pc
,
test
->
unwind_info
?
(
RUNTIME_FUNCTION
*
)
&
runtime_func
:
NULL
,
(
CONTEXT
*
)
&
new_context
,
NULL
,
&
data
,
&
frame
,
&
ctx_ptr
,
NULL
,
NULL
,
&
handler
,
0
);
if
(
test
->
results
[
i
].
handler
>
0
)
{
ok
(
!
status
,
"RtlVirtualUnwind2 failed %lx
\n
"
,
status
);
ok
(
(
char
*
)
handler
==
(
char
*
)
code_mem
+
0x200
,
"wrong handler %p/%p
\n
"
,
handler
,
(
char
*
)
code_mem
+
0x200
);
if
(
handler
)
ok
(
*
(
DWORD
*
)
data
==
0x08070605
,
"wrong handler data %lx
\n
"
,
*
(
DWORD
*
)
data
);
}
else
if
(
test
->
results
[
i
].
handler
<
-
1
)
{
ok
(
status
==
STATUS_BAD_FUNCTION_TABLE
,
"RtlVirtualUnwind2 failed %lx
\n
"
,
status
);
ok
(
handler
==
(
void
*
)
0xdeadbeef
,
"handler set to %p
\n
"
,
handler
);
ok
(
data
==
(
void
*
)
0xdeadbeef
,
"handler data set to %p
\n
"
,
data
);
}
else
{
ok
(
!
status
,
"RtlVirtualUnwind2 failed %lx
\n
"
,
status
);
ok
(
handler
==
NULL
,
"handler %p instead of NULL
\n
"
,
handler
);
ok
(
data
==
NULL
,
"handler data set to %p
\n
"
,
data
);
}
}
data
=
(
void
*
)
0xdeadbeef
;
frame
=
0xdeadbeef
;
if
(
test
->
results
[
i
].
handler
==
-
2
)
orig_pc
=
context
.
Lr
;
handler
=
RtlVirtualUnwind
(
UNW_FLAG_EHANDLER
,
(
ULONG64
)
code_mem
,
orig_pc
,
test
->
unwind_info
?
(
RUNTIME_FUNCTION
*
)
&
runtime_func
:
NULL
,
(
CONTEXT
*
)
&
context
,
&
data
,
&
frame
,
&
ctx_ptr
);
...
...
@@ -2625,8 +2696,10 @@ static void call_virtual_unwind_x86( int testnum, const struct unwind_test_x86 *
{
static
const
int
code_offset
=
1024
;
static
const
int
unwind_offset
=
2048
;
void
*
handler
,
*
data
;
void
*
data
;
NTSTATUS
status
;
CONTEXT
context
;
PEXCEPTION_ROUTINE
handler
;
RUNTIME_FUNCTION
runtime_func
;
KNONVOLATILE_CONTEXT_POINTERS
ctx_ptr
;
UINT
i
,
j
,
k
,
broken_k
;
...
...
@@ -2661,8 +2734,31 @@ static void call_virtual_unwind_x86( int testnum, const struct unwind_test_x86 *
trace
(
"%u/%u: rip=%p (%02x) rbp=%p rsp=%p
\n
"
,
testnum
,
i
,
(
void
*
)
orig_rip
,
*
(
BYTE
*
)
orig_rip
,
(
void
*
)
orig_rbp
,
(
void
*
)
context
.
Rsp
);
data
=
(
void
*
)
0xdeadbeef
;
if
(
!
test
->
unwind_info
)
fake_stack
[
0
]
=
0x1234
;
expected_handler
=
test
->
results
[
i
].
handler
?
(
char
*
)
code_mem
+
0x200
:
NULL
;
broken_handler
=
test
->
broken_results
&&
test
->
broken_results
[
i
].
handler
?
(
char
*
)
code_mem
+
0x200
:
NULL
;
if
(
pRtlVirtualUnwind2
)
{
CONTEXT
new_context
=
context
;
handler
=
(
void
*
)
0xdeadbeef
;
data
=
(
void
*
)
0xdeadbeef
;
status
=
pRtlVirtualUnwind2
(
UNW_FLAG_EHANDLER
,
(
ULONG_PTR
)
code_mem
,
orig_rip
,
test
->
unwind_info
?
&
runtime_func
:
NULL
,
&
new_context
,
NULL
,
&
data
,
&
frame
,
&
ctx_ptr
,
NULL
,
NULL
,
&
handler
,
0
);
ok
(
!
status
,
"RtlVirtualUnwind2 failed %lx
\n
"
,
status
);
ok
(
handler
==
expected_handler
||
broken
(
test
->
broken_results
&&
handler
==
broken_handler
),
"%u/%u: wrong handler %p/%p
\n
"
,
testnum
,
i
,
handler
,
expected_handler
);
if
(
handler
)
ok
(
*
(
DWORD
*
)
data
==
0x08070605
,
"%u/%u: wrong handler data %lx
\n
"
,
testnum
,
i
,
*
(
DWORD
*
)
data
);
else
ok
(
data
==
(
test
->
unwind_info
?
(
void
*
)
0xdeadbeef
:
NULL
),
"%u/%u: handler data set to %p
\n
"
,
testnum
,
i
,
data
);
}
data
=
(
void
*
)
0xdeadbeef
;
handler
=
RtlVirtualUnwind
(
UNW_FLAG_EHANDLER
,
(
ULONG64
)
code_mem
,
orig_rip
,
test
->
unwind_info
?
&
runtime_func
:
NULL
,
&
context
,
&
data
,
&
frame
,
&
ctx_ptr
);
...
...
@@ -3329,6 +3425,7 @@ START_TEST(unwind)
X
(
RtlInstallFunctionTableCallback
);
X
(
RtlLookupFunctionEntry
);
X
(
RtlLookupFunctionTable
);
X
(
RtlVirtualUnwind2
);
#undef X
#ifdef __arm__
...
...
dlls/ntdll/unwind.c
View file @
ca598405
This diff is collapsed.
Click to expand it.
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