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
654c03d1
Commit
654c03d1
authored
Feb 22, 2024
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Handle leaf functions in RtlVirtualUnwind on x86-64.
parent
18b0473f
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
53 additions
and
31 deletions
+53
-31
signal_x86_64.c
dlls/ntdll/signal_x86_64.c
+10
-22
unwind.c
dlls/ntdll/tests/unwind.c
+32
-8
unwind.c
dlls/ntdll/unwind.c
+11
-1
No files found.
dlls/ntdll/signal_x86_64.c
View file @
654c03d1
...
...
@@ -100,22 +100,12 @@ static NTSTATUS virtual_unwind( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEX
dispatch
->
ImageBase
=
0
;
dispatch
->
ScopeIndex
=
0
;
dispatch
->
ControlPc
=
context
->
Rip
;
dispatch
->
FunctionEntry
=
RtlLookupFunctionEntry
(
context
->
Rip
,
&
dispatch
->
ImageBase
,
dispatch
->
HistoryTable
);
/* first look for PE exception information */
if
((
dispatch
->
FunctionEntry
=
RtlLookupFunctionEntry
(
context
->
Rip
,
&
dispatch
->
ImageBase
,
dispatch
->
HistoryTable
)))
{
dispatch
->
LanguageHandler
=
RtlVirtualUnwind
(
type
,
dispatch
->
ImageBase
,
context
->
Rip
,
dispatch
->
FunctionEntry
,
context
,
&
dispatch
->
HandlerData
,
&
dispatch
->
EstablisherFrame
,
NULL
);
return
STATUS_SUCCESS
;
}
/* then look for host system exception information */
if
(
LdrFindEntryForAddress
(
(
void
*
)
context
->
Rip
,
&
module
)
||
(
module
->
Flags
&
LDR_WINE_INTERNAL
))
/* look for host system exception information */
if
(
!
dispatch
->
FunctionEntry
&&
(
LdrFindEntryForAddress
(
(
void
*
)
context
->
Rip
,
&
module
)
||
(
module
->
Flags
&
LDR_WINE_INTERNAL
)))
{
struct
unwind_builtin_dll_params
params
=
{
type
,
dispatch
,
context
};
...
...
@@ -127,14 +117,12 @@ static NTSTATUS virtual_unwind( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEX
}
if
(
status
!=
STATUS_UNSUCCESSFUL
)
return
status
;
}
else
WARN
(
"exception data not found for pc %p
\n
"
,
(
void
*
)
context
->
Rip
);
/* no exception information, treat as a leaf function */
WARN
(
"exception data not found for pc %p
\n
"
,
(
void
*
)
context
->
Rip
);
dispatch
->
EstablisherFrame
=
context
->
Rsp
;
dispatch
->
LanguageHandler
=
NULL
;
context
->
Rip
=
*
(
ULONG64
*
)
context
->
Rsp
;
context
->
Rsp
=
context
->
Rsp
+
sizeof
(
ULONG64
);
dispatch
->
LanguageHandler
=
RtlVirtualUnwind
(
type
,
dispatch
->
ImageBase
,
context
->
Rip
,
dispatch
->
FunctionEntry
,
context
,
&
dispatch
->
HandlerData
,
&
dispatch
->
EstablisherFrame
,
NULL
);
return
STATUS_SUCCESS
;
}
...
...
dlls/ntdll/tests/unwind.c
View file @
654c03d1
...
...
@@ -2632,15 +2632,17 @@ static void call_virtual_unwind_x86( int testnum, const struct unwind_test_x86 *
UINT
i
,
j
,
k
,
broken_k
;
ULONG64
fake_stack
[
256
];
ULONG64
frame
,
orig_rip
,
orig_rbp
,
unset_reg
;
UINT
unwind_size
=
4
+
2
*
test
->
unwind_info
[
2
]
+
8
;
void
*
expected_handler
,
*
broken_handler
;
memcpy
(
(
char
*
)
code_mem
+
code_offset
,
test
->
function
,
test
->
function_size
);
memcpy
(
(
char
*
)
code_mem
+
unwind_offset
,
test
->
unwind_info
,
unwind_size
);
runtime_func
.
BeginAddress
=
code_offset
;
runtime_func
.
EndAddress
=
code_offset
+
test
->
function_size
;
runtime_func
.
UnwindData
=
unwind_offset
;
if
(
test
->
unwind_info
)
{
UINT
unwind_size
=
4
+
2
*
test
->
unwind_info
[
2
]
+
8
;
memcpy
(
(
char
*
)
code_mem
+
unwind_offset
,
test
->
unwind_info
,
unwind_size
);
runtime_func
.
BeginAddress
=
code_offset
;
runtime_func
.
EndAddress
=
code_offset
+
test
->
function_size
;
runtime_func
.
UnwindData
=
unwind_offset
;
}
trace
(
"code: %p stack: %p
\n
"
,
code_mem
,
fake_stack
);
...
...
@@ -2660,8 +2662,10 @@ static void call_virtual_unwind_x86( int testnum, const struct unwind_test_x86 *
(
void
*
)
orig_rip
,
*
(
BYTE
*
)
orig_rip
,
(
void
*
)
orig_rbp
,
(
void
*
)
context
.
Rsp
);
data
=
(
void
*
)
0xdeadbeef
;
if
(
!
test
->
unwind_info
)
fake_stack
[
0
]
=
0x1234
;
handler
=
RtlVirtualUnwind
(
UNW_FLAG_EHANDLER
,
(
ULONG64
)
code_mem
,
orig_rip
,
&
runtime_func
,
&
context
,
&
data
,
&
frame
,
&
ctx_ptr
);
test
->
unwind_info
?
&
runtime_func
:
NULL
,
&
context
,
&
data
,
&
frame
,
&
ctx_ptr
);
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
;
...
...
@@ -2671,7 +2675,8 @@ static void call_virtual_unwind_x86( int testnum, const struct unwind_test_x86 *
if
(
handler
)
ok
(
*
(
DWORD
*
)
data
==
0x08070605
,
"%u/%u: wrong handler data %lx
\n
"
,
testnum
,
i
,
*
(
DWORD
*
)
data
);
else
ok
(
data
==
(
void
*
)
0xdeadbeef
,
"%u/%u: handler data set to %p
\n
"
,
testnum
,
i
,
data
);
ok
(
data
==
(
test
->
unwind_info
?
(
void
*
)
0xdeadbeef
:
NULL
),
"%u/%u: handler data set to %p
\n
"
,
testnum
,
i
,
data
);
ok
(
context
.
Rip
==
test
->
results
[
i
].
rip
||
broken
(
test
->
broken_results
&&
context
.
Rip
==
test
->
broken_results
[
i
].
rip
),
...
...
@@ -2960,6 +2965,22 @@ static void test_virtual_unwind_x86(void)
{
0x01
,
0x50
,
FALSE
,
0x008
,
0x000
,
{
{
rsp
,
0x010
},
{
rbp
,
0x000
},
{
-
1
,
-
1
}
}},
};
#if 0
static const BYTE function_5[] =
{
0x90, /* 00: nop */
0x90, /* 01: nop */
0xc3 /* 02: ret */
};
static const struct results_x86 results_5[] =
{
/* offset rbp handler rip frame registers */
{ 0x01, 0x00, FALSE, 0x1234, 0x000, { {rsp,0x08}, {-1,-1} }},
{ 0x02, 0x00, FALSE, 0x1234, 0x000, { {rsp,0x08}, {-1,-1} }},
};
#endif
static
const
struct
unwind_test_x86
tests
[]
=
{
{
function_0
,
sizeof
(
function_0
),
unwind_info_0
,
results_0
,
ARRAY_SIZE
(
results_0
),
broken_results_0
},
...
...
@@ -2969,6 +2990,9 @@ static void test_virtual_unwind_x86(void)
/* Broken before Win10 1809. */
{
function_4
,
sizeof
(
function_4
),
unwind_info_4
,
results_4
,
ARRAY_SIZE
(
results_4
),
broken_results_4
},
#if 0 /* crashes before Win10 21H2 */
{ function_5, sizeof(function_5), NULL, results_5, ARRAY_SIZE(results_5) },
#endif
};
unsigned
int
i
;
...
...
dlls/ntdll/unwind.c
View file @
654c03d1
...
...
@@ -1838,9 +1838,19 @@ PVOID WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc,
#endif
TRACE
(
"type %lx rip %I64x rsp %I64x
\n
"
,
type
,
pc
,
context
->
Rsp
);
if
(
TRACE_ON
(
unwind
))
dump_unwind_info
(
base
,
function
);
frame
=
*
frame_ret
=
context
->
Rsp
;
if
(
!
function
)
/* leaf function */
{
context
->
Rip
=
*
(
ULONG64
*
)
context
->
Rsp
;
context
->
Rsp
+=
sizeof
(
ULONG64
);
*
data
=
NULL
;
return
NULL
;
}
if
(
TRACE_ON
(
unwind
))
dump_unwind_info
(
base
,
function
);
for
(;;)
{
info
=
(
struct
UNWIND_INFO
*
)((
char
*
)
base
+
function
->
UnwindData
);
...
...
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