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
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
232 additions
and
71 deletions
+232
-71
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
+116
-49
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
...
...
@@ -766,42 +766,59 @@ static ARM64_RUNTIME_FUNCTION *find_function_info_arm64( ULONG_PTR pc, ULONG_PTR
#ifdef __arm64ec__
#define RtlVirtualUnwind RtlVirtualUnwind_arm64
#define RtlVirtualUnwind2 RtlVirtualUnwind2_arm64
#define RtlLookupFunctionEntry RtlLookupFunctionEntry_arm64
#endif
/**********************************************************************
* RtlVirtualUnwind (NTDLL.@)
* RtlVirtualUnwind
2
(NTDLL.@)
*/
PEXCEPTION_ROUTINE
WINAPI
RtlVirtualUnwind
(
ULONG
type
,
ULONG_PTR
base
,
ULONG_PTR
pc
,
ARM64_RUNTIME_FUNCTION
*
func
,
ARM64_NT_CONTEXT
*
context
,
PVOID
*
handler_data
,
ULONG_PTR
*
frame_ret
,
KNONVOLATILE_CONTEXT_POINTERS_ARM64
*
ctx_ptr
)
NTSTATUS
WINAPI
RtlVirtualUnwind2
(
ULONG
type
,
ULONG_PTR
base
,
ULONG_PTR
pc
,
ARM64_RUNTIME_FUNCTION
*
func
,
ARM64_NT_CONTEXT
*
context
,
BOOLEAN
*
mach_frame_unwound
,
void
**
handler_data
,
ULONG_PTR
*
frame_ret
,
KNONVOLATILE_CONTEXT_POINTERS_ARM64
*
ctx_ptr
,
ULONG_PTR
*
limit_low
,
ULONG_PTR
*
limit_high
,
PEXCEPTION_ROUTINE
*
handler_ret
,
ULONG
flags
)
{
PEXCEPTION_ROUTINE
handler
;
TRACE
(
"type %lx base %I64x pc %I64x rva %I64x sp %I64x
\n
"
,
type
,
base
,
pc
,
pc
-
base
,
context
->
Sp
);
if
(
limit_low
||
limit_high
)
FIXME
(
"limits not supported
\n
"
);
TRACE
(
"type %lx pc %I64x sp %I64x
\n
"
,
type
,
pc
,
context
->
Sp
);
if
(
!
func
&&
pc
==
context
->
Lr
)
/* invalid leaf function */
{
context
->
Pc
=
0
;
return
NULL
;
}
if
(
!
func
&&
pc
==
context
->
Lr
)
return
STATUS_BAD_FUNCTION_TABLE
;
/* invalid leaf function */
*
handler_data
=
NULL
;
context
->
ContextFlags
|=
CONTEXT_UNWOUND_TO_CALL
;
if
(
!
func
)
/* leaf function */
handler
=
NULL
;
*
handler_ret
=
NULL
;
else
if
(
func
->
Flag
)
handler
=
unwind_packed_data
(
base
,
pc
,
func
,
context
,
ctx_ptr
);
*
handler_ret
=
unwind_packed_data
(
base
,
pc
,
func
,
context
,
ctx_ptr
);
else
handler
=
unwind_full_data
(
base
,
pc
,
func
,
context
,
handler_data
,
ctx_ptr
);
*
handler_ret
=
unwind_full_data
(
base
,
pc
,
func
,
context
,
handler_data
,
ctx_ptr
);
if
(
context
->
ContextFlags
&
CONTEXT_UNWOUND_TO_CALL
)
context
->
Pc
=
context
->
Lr
;
TRACE
(
"ret: pc=%I64x lr=%I64x sp=%I64x handler=%p
\n
"
,
context
->
Pc
,
context
->
Lr
,
context
->
Sp
,
handler
);
TRACE
(
"ret: pc=%I64x lr=%I64x sp=%I64x handler=%p
\n
"
,
context
->
Pc
,
context
->
Lr
,
context
->
Sp
,
*
handler_ret
);
*
frame_ret
=
context
->
Sp
;
return
handler
;
return
STATUS_SUCCESS
;
}
/**********************************************************************
* RtlVirtualUnwind (NTDLL.@)
*/
PEXCEPTION_ROUTINE
WINAPI
RtlVirtualUnwind
(
ULONG
type
,
ULONG_PTR
base
,
ULONG_PTR
pc
,
ARM64_RUNTIME_FUNCTION
*
func
,
ARM64_NT_CONTEXT
*
context
,
PVOID
*
handler_data
,
ULONG_PTR
*
frame_ret
,
KNONVOLATILE_CONTEXT_POINTERS_ARM64
*
ctx_ptr
)
{
PEXCEPTION_ROUTINE
handler
;
if
(
!
RtlVirtualUnwind2
(
type
,
base
,
pc
,
func
,
context
,
NULL
,
handler_data
,
frame_ret
,
ctx_ptr
,
NULL
,
NULL
,
&
handler
,
0
))
return
handler
;
context
->
Pc
=
0
;
return
NULL
;
}
...
...
@@ -850,6 +867,7 @@ BOOLEAN CDECL RtlAddFunctionTable( RUNTIME_FUNCTION *table, DWORD count, ULONG_P
}
#else
#undef RtlVirtualUnwind
#undef RtlVirtualUnwind2
#undef RtlLookupFunctionEntry
#endif
...
...
@@ -1367,39 +1385,60 @@ static RUNTIME_FUNCTION *find_function_info( ULONG_PTR pc, ULONG_PTR base,
return
NULL
;
}
/***********************************************************************
* RtlVirtualUnwind (NTDLL.@)
/**********************************************************************
* RtlVirtualUnwind2 (NTDLL.@)
*/
PEXCEPTION_ROUTINE
WINAPI
RtlVirtualUnwind
(
ULONG
type
,
ULONG_PTR
base
,
ULONG_PTR
pc
,
RUNTIME_FUNCTION
*
func
,
CONTEXT
*
context
,
PVOID
*
handler_data
,
ULONG_PTR
*
frame_ret
,
KNONVOLATILE_CONTEXT_POINTERS
*
ctx_ptr
)
NTSTATUS
WINAPI
RtlVirtualUnwind2
(
ULONG
type
,
ULONG_PTR
base
,
ULONG_PTR
pc
,
RUNTIME_FUNCTION
*
func
,
CONTEXT
*
context
,
BOOLEAN
*
mach_frame_unwound
,
void
**
handler_data
,
ULONG_PTR
*
frame_ret
,
KNONVOLATILE_CONTEXT_POINTERS
*
ctx_ptr
,
ULONG_PTR
*
limit_low
,
ULONG_PTR
*
limit_high
,
PEXCEPTION_ROUTINE
*
handler_ret
,
ULONG
flags
)
{
PEXCEPTION_ROUTINE
handler
;
TRACE
(
"type %lx pc %Ix sp %lx
\n
"
,
type
,
pc
,
context
->
Sp
);
TRACE
(
"type %lx base %Ix pc %Ix rva %Ix sp %lx
\n
"
,
type
,
base
,
pc
,
pc
-
base
,
context
->
Sp
);
if
(
limit_low
||
limit_high
)
FIXME
(
"limits not supported
\n
"
);
context
->
Pc
=
0
;
if
(
!
func
&&
pc
==
context
->
Lr
)
return
NULL
;
/* invalid leaf function */
if
(
!
func
&&
pc
==
context
->
Lr
)
return
STATUS_BAD_FUNCTION_TABLE
;
/* invalid leaf function */
*
handler_data
=
NULL
;
if
(
!
func
)
/* leaf function */
handler
=
NULL
;
*
handler_ret
=
NULL
;
else
if
(
func
->
Flag
)
handler
=
unwind_packed_data
(
base
,
pc
,
func
,
context
,
ctx_ptr
);
*
handler_ret
=
unwind_packed_data
(
base
,
pc
,
func
,
context
,
ctx_ptr
);
else
handler
=
unwind_full_data
(
base
,
pc
,
func
,
context
,
handler_data
,
ctx_ptr
);
*
handler_ret
=
unwind_full_data
(
base
,
pc
,
func
,
context
,
handler_data
,
ctx_ptr
);
TRACE
(
"ret: pc=%lx lr=%lx sp=%lx handler=%p
\n
"
,
context
->
Pc
,
context
->
Lr
,
context
->
Sp
,
handler
);
TRACE
(
"ret: pc=%lx lr=%lx sp=%lx handler=%p
\n
"
,
context
->
Pc
,
context
->
Lr
,
context
->
Sp
,
*
handler_ret
);
if
(
!
context
->
Pc
)
{
context
->
Pc
=
context
->
Lr
;
context
->
ContextFlags
|=
CONTEXT_UNWOUND_TO_CALL
;
}
*
frame_ret
=
context
->
Sp
;
return
handler
;
return
STATUS_SUCCESS
;
}
/***********************************************************************
* RtlVirtualUnwind (NTDLL.@)
*/
PEXCEPTION_ROUTINE
WINAPI
RtlVirtualUnwind
(
ULONG
type
,
ULONG_PTR
base
,
ULONG_PTR
pc
,
RUNTIME_FUNCTION
*
func
,
CONTEXT
*
context
,
PVOID
*
handler_data
,
ULONG_PTR
*
frame_ret
,
KNONVOLATILE_CONTEXT_POINTERS
*
ctx_ptr
)
{
PEXCEPTION_ROUTINE
handler
;
if
(
!
RtlVirtualUnwind2
(
type
,
base
,
pc
,
func
,
context
,
NULL
,
handler_data
,
frame_ret
,
ctx_ptr
,
NULL
,
NULL
,
&
handler
,
0
))
return
handler
;
context
->
Pc
=
0
;
return
NULL
;
}
...
...
@@ -1808,12 +1847,14 @@ static RUNTIME_FUNCTION *find_function_info( ULONG_PTR pc, ULONG_PTR base,
/**********************************************************************
* RtlVirtualUnwind (NTDLL.@)
* RtlVirtualUnwind
2
(NTDLL.@)
*/
PEXCEPTION_ROUTINE
WINAPI
RtlVirtualUnwind
(
ULONG
type
,
ULONG64
base
,
ULONG64
pc
,
RUNTIME_FUNCTION
*
function
,
CONTEXT
*
context
,
PVOID
*
data
,
ULONG64
*
frame_ret
,
KNONVOLATILE_CONTEXT_POINTERS
*
ctx_ptr
)
NTSTATUS
WINAPI
RtlVirtualUnwind2
(
ULONG
type
,
ULONG_PTR
base
,
ULONG_PTR
pc
,
RUNTIME_FUNCTION
*
function
,
CONTEXT
*
context
,
BOOLEAN
*
mach_frame_unwound
,
void
**
data
,
ULONG_PTR
*
frame_ret
,
KNONVOLATILE_CONTEXT_POINTERS
*
ctx_ptr
,
ULONG_PTR
*
limit_low
,
ULONG_PTR
*
limit_high
,
PEXCEPTION_ROUTINE
*
handler_ret
,
ULONG
flags
)
{
union
handler_data
*
handler_data
;
ULONG64
frame
,
off
;
...
...
@@ -1826,18 +1867,20 @@ PEXCEPTION_ROUTINE WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc
{
DWORD
flags
=
context
->
ContextFlags
&
~
CONTEXT_UNWOUND_TO_CALL
;
ARM64_NT_CONTEXT
arm_context
;
PEXCEPTION_ROUTINE
ret
;
NTSTATUS
status
;
context_x64_to_arm
(
&
arm_context
,
(
ARM64EC_NT_CONTEXT
*
)
context
);
ret
=
RtlVirtualUnwind_arm64
(
type
,
base
,
pc
,
(
ARM64_RUNTIME_FUNCTION
*
)
function
,
&
arm_context
,
data
,
frame_ret
,
NULL
);
status
=
RtlVirtualUnwind2_arm64
(
type
,
base
,
pc
,
(
ARM64_RUNTIME_FUNCTION
*
)
function
,
&
arm_context
,
NULL
,
data
,
frame_ret
,
NULL
,
limit_low
,
limit_high
,
handler_ret
,
flags
);
context_arm_to_x64
(
(
ARM64EC_NT_CONTEXT
*
)
context
,
&
arm_context
);
context
->
ContextFlags
=
flags
|
(
arm_context
.
ContextFlags
&
CONTEXT_UNWOUND_TO_CALL
);
return
ret
;
return
status
;
}
#endif
TRACE
(
"type %lx rip %I64x rsp %I64x
\n
"
,
type
,
pc
,
context
->
Rsp
);
TRACE
(
"type %lx base %I64x rip %I64x rva %I64x rsp %I64x
\n
"
,
type
,
base
,
pc
,
pc
-
base
,
context
->
Rsp
);
if
(
limit_low
||
limit_high
)
FIXME
(
"limits not supported
\n
"
);
frame
=
*
frame_ret
=
context
->
Rsp
;
...
...
@@ -1846,7 +1889,8 @@ PEXCEPTION_ROUTINE WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc
context
->
Rip
=
*
(
ULONG64
*
)
context
->
Rsp
;
context
->
Rsp
+=
sizeof
(
ULONG64
);
*
data
=
NULL
;
return
NULL
;
*
handler_ret
=
NULL
;
return
STATUS_SUCCESS
;
}
if
(
TRACE_ON
(
unwind
))
dump_unwind_info
(
base
,
function
);
...
...
@@ -1859,7 +1903,7 @@ PEXCEPTION_ROUTINE WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc
if
(
info
->
version
!=
1
&&
info
->
version
!=
2
)
{
FIXME
(
"unknown unwind info version %u at %p
\n
"
,
info
->
version
,
info
);
return
NULL
;
return
STATUS_BAD_FUNCTION_TABLE
;
}
if
(
info
->
frame_reg
)
...
...
@@ -1880,7 +1924,8 @@ PEXCEPTION_ROUTINE WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc
TRACE
(
"inside epilog.
\n
"
);
interpret_epilog
(
(
BYTE
*
)
pc
,
context
,
ctx_ptr
);
*
frame_ret
=
frame
;
return
NULL
;
*
handler_ret
=
NULL
;
return
STATUS_SUCCESS
;
}
}
...
...
@@ -1959,11 +2004,33 @@ PEXCEPTION_ROUTINE WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc
context
->
Rsp
+=
sizeof
(
ULONG64
);
}
if
(
!
(
info
->
flags
&
type
))
return
NULL
;
/* no matching handler */
if
(
prolog_offset
!=
~
0
)
return
NULL
;
/* inside prolog */
*
handler_ret
=
NULL
;
if
(
!
(
info
->
flags
&
type
))
return
STATUS_SUCCESS
;
/* no matching handler */
if
(
prolog_offset
!=
~
0
)
return
STATUS_SUCCESS
;
/* inside prolog */
*
handler_ret
=
(
PEXCEPTION_ROUTINE
)((
char
*
)
base
+
handler_data
->
handler
);
*
data
=
&
handler_data
->
handler
+
1
;
return
(
PEXCEPTION_ROUTINE
)((
char
*
)
base
+
handler_data
->
handler
);
return
STATUS_SUCCESS
;
}
/**********************************************************************
* RtlVirtualUnwind (NTDLL.@)
*/
PEXCEPTION_ROUTINE
WINAPI
RtlVirtualUnwind
(
ULONG
type
,
ULONG64
base
,
ULONG64
pc
,
RUNTIME_FUNCTION
*
func
,
CONTEXT
*
context
,
PVOID
*
handler_data
,
ULONG64
*
frame_ret
,
KNONVOLATILE_CONTEXT_POINTERS
*
ctx_ptr
)
{
PEXCEPTION_ROUTINE
handler
;
if
(
!
RtlVirtualUnwind2
(
type
,
base
,
pc
,
func
,
context
,
NULL
,
handler_data
,
frame_ret
,
ctx_ptr
,
NULL
,
NULL
,
&
handler
,
0
))
return
handler
;
context
->
Rip
=
0
;
return
NULL
;
}
...
...
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