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
cf08bbaa
Commit
cf08bbaa
authored
Mar 25, 2024
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Use a common wrapper to call unwind handlers on x86-64.
parent
24e9fcac
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
49 additions
and
84 deletions
+49
-84
signal_x86_64.c
dlls/ntdll/signal_x86_64.c
+49
-84
No files found.
dlls/ntdll/signal_x86_64.c
View file @
cf08bbaa
...
...
@@ -391,6 +391,9 @@ struct unwind_exception_frame
* save space when .seh handler is used. */
DISPATCHER_CONTEXT
*
dispatch
;
};
C_ASSERT
(
sizeof
(
struct
unwind_exception_frame
)
==
0x28
);
C_ASSERT
(
offsetof
(
struct
unwind_exception_frame
,
dispatch
)
==
0x20
);
/**********************************************************************
* unwind_exception_handler
...
...
@@ -418,30 +421,26 @@ DWORD __cdecl unwind_exception_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTR
return
ExceptionCollidedUnwind
;
}
/***********************************************************************
* unwind_handler_call_wrapper
/**********************************************************************
* call_unwind_handler
*/
#ifdef __WINE_PE_BUILD
DWORD
WINAPI
unwind_handler_call_wrapper
(
EXCEPTION_RECORD
*
rec
,
void
*
frame
,
CONTEXT
*
context
,
DISPATCHER_CONTEXT
*
dispatch
);
C_ASSERT
(
sizeof
(
struct
unwind_exception_frame
)
==
0x28
);
C_ASSERT
(
offsetof
(
struct
unwind_exception_frame
,
dispatch
)
==
0x20
);
C_ASSERT
(
offsetof
(
DISPATCHER_CONTEXT
,
LanguageHandler
)
==
0x30
);
__ASM_GLOBAL_FUNC
(
unwind_handler_call_wrapper
,
DWORD
WINAPI
call_unwind_handler
(
EXCEPTION_RECORD
*
rec
,
ULONG_PTR
frame
,
CONTEXT
*
context
,
void
*
dispatch
,
PEXCEPTION_ROUTINE
handler
);
__ASM_GLOBAL_FUNC
(
call_unwind_handler
,
"subq $0x28,%rsp
\n\t
"
".seh_stackalloc 0x28
\n\t
"
".seh_endprologue
\n\t
"
".seh_handler unwind_exception_handler, @except, @unwind
\n\t
"
"movq %r9,0x20(%rsp)
\n\t
"
/* unwind_exception_frame->dispatch */
"callq *0x
30(%r9)
\n\t
"
/* dispatch->LanguageH
andler */
"callq *0x
50(%rsp)
\n\t
"
/* h
andler */
"nop
\n\t
"
/* avoid epilogue so handler is called */
"addq $0x28, %rsp
\n\t
"
"ret
\n\t
"
".seh_handler "
__ASM_NAME
(
"unwind_exception_handler"
)
", @except, @unwind
\n\t
"
)
"ret"
)
#else
static
DWORD
unwind_handler_call_wrapper
(
EXCEPTION_RECORD
*
rec
,
void
*
frame
,
CONTEXT
*
context
,
DISPATCHER_CONTEXT
*
dispatch
)
static
DWORD
call_unwind_handler
(
EXCEPTION_RECORD
*
rec
,
ULONG_PTR
frame
,
CONTEXT
*
context
,
void
*
dispatch
,
PEXCEPTION_ROUTINE
handler
)
{
struct
unwind_exception_frame
wrapper_frame
;
DWORD
res
;
...
...
@@ -449,68 +448,12 @@ static DWORD unwind_handler_call_wrapper( EXCEPTION_RECORD *rec, void *frame,
wrapper_frame
.
frame
.
Handler
=
unwind_exception_handler
;
wrapper_frame
.
dispatch
=
dispatch
;
__wine_push_frame
(
&
wrapper_frame
.
frame
);
res
=
dispatch
->
LanguageHandler
(
rec
,
(
void
*
)
dispatch
->
EstablisherFrame
,
dispatch
->
ContextRecord
,
dispatch
);
res
=
handler
(
rec
,
(
void
*
)
frame
,
context
,
dispatch
);
__wine_pop_frame
(
&
wrapper_frame
.
frame
);
return
res
;
}
#endif
/**********************************************************************
* call_unwind_handler
*
* Call a single unwind handler.
*/
DWORD
call_unwind_handler
(
EXCEPTION_RECORD
*
rec
,
DISPATCHER_CONTEXT
*
dispatch
)
{
DWORD
res
;
TRACE
(
"calling handler %p (rec=%p, frame=%p context=%p, dispatch=%p)
\n
"
,
dispatch
->
LanguageHandler
,
rec
,
(
void
*
)
dispatch
->
EstablisherFrame
,
dispatch
->
ContextRecord
,
dispatch
);
res
=
unwind_handler_call_wrapper
(
rec
,
(
void
*
)
dispatch
->
EstablisherFrame
,
dispatch
->
ContextRecord
,
dispatch
);
TRACE
(
"handler %p returned %lx
\n
"
,
dispatch
->
LanguageHandler
,
res
);
switch
(
res
)
{
case
ExceptionContinueSearch
:
case
ExceptionCollidedUnwind
:
break
;
default
:
raise_status
(
STATUS_INVALID_DISPOSITION
,
rec
);
break
;
}
return
res
;
}
/**********************************************************************
* call_teb_unwind_handler
*
* Call a single unwind handler from the TEB chain.
*/
static
DWORD
call_teb_unwind_handler
(
EXCEPTION_RECORD
*
rec
,
DISPATCHER_CONTEXT
*
dispatch
,
EXCEPTION_REGISTRATION_RECORD
*
teb_frame
)
{
DWORD
res
;
TRACE
(
"calling TEB handler %p (rec=%p, frame=%p context=%p, dispatch=%p)
\n
"
,
teb_frame
->
Handler
,
rec
,
teb_frame
,
dispatch
->
ContextRecord
,
dispatch
);
res
=
teb_frame
->
Handler
(
rec
,
teb_frame
,
dispatch
->
ContextRecord
,
(
EXCEPTION_REGISTRATION_RECORD
**
)
dispatch
);
TRACE
(
"handler at %p returned %lu
\n
"
,
teb_frame
->
Handler
,
res
);
switch
(
res
)
{
case
ExceptionContinueSearch
:
case
ExceptionCollidedUnwind
:
break
;
default
:
raise_status
(
STATUS_INVALID_DISPOSITION
,
rec
);
break
;
}
return
res
;
}
/**********************************************************************
* call_consolidate_callback
...
...
@@ -691,7 +634,7 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec
CONTEXT
new_context
;
NTSTATUS
status
;
ULONG_PTR
frame
;
DWORD
i
;
DWORD
i
,
res
;
RtlCaptureContext
(
context
);
new_context
=
*
context
;
...
...
@@ -744,40 +687,62 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec
raise_status
(
STATUS_INVALID_UNWIND_TARGET
,
rec
);
}
if
(
dispatch
.
EstablisherFrame
==
(
ULONG64
)
end_frame
)
rec
->
ExceptionFlags
|=
EXCEPTION_TARGET_UNWIND
;
if
(
call_unwind_handler
(
rec
,
&
dispatch
)
==
ExceptionCollidedUnwind
)
TRACE
(
"calling handler %p (rec=%p, frame=%I64x context=%p, dispatch=%p)
\n
"
,
dispatch
.
LanguageHandler
,
rec
,
dispatch
.
EstablisherFrame
,
dispatch
.
ContextRecord
,
&
dispatch
);
res
=
call_unwind_handler
(
rec
,
dispatch
.
EstablisherFrame
,
dispatch
.
ContextRecord
,
&
dispatch
,
dispatch
.
LanguageHandler
);
TRACE
(
"handler %p returned %lx
\n
"
,
dispatch
.
LanguageHandler
,
res
);
switch
(
res
)
{
case
ExceptionContinueSearch
:
rec
->
ExceptionFlags
&=
~
EXCEPTION_COLLIDED_UNWIND
;
break
;
case
ExceptionCollidedUnwind
:
new_context
=
*
context
;
RtlVirtualUnwind
(
UNW_FLAG_NHANDLER
,
dispatch
.
ImageBase
,
dispatch
.
ControlPc
,
dispatch
.
FunctionEntry
,
&
new_context
,
NULL
,
&
frame
,
NULL
);
rec
->
ExceptionFlags
|=
EXCEPTION_COLLIDED_UNWIND
;
goto
unwind_done
;
default
:
raise_status
(
STATUS_INVALID_DISPOSITION
,
rec
);
break
;
}
rec
->
ExceptionFlags
&=
~
EXCEPTION_COLLIDED_UNWIND
;
}
else
/* hack: call builtin handlers registered in the tib list */
{
DWORD64
backup_frame
=
dispatch
.
EstablisherFrame
;
while
(
is_valid_frame
(
(
ULONG_PTR
)
teb_frame
)
&&
(
ULONG64
)
teb_frame
<
new_context
.
Rsp
&&
(
ULONG64
)
teb_frame
<
(
ULONG64
)
end_frame
)
{
TRACE
(
"found builtin frame %p handler %p
\n
"
,
teb_frame
,
teb_frame
->
Handler
);
dispatch
.
EstablisherFrame
=
(
ULONG64
)
teb_frame
;
if
(
call_teb_unwind_handler
(
rec
,
&
dispatch
,
teb_frame
)
==
ExceptionCollidedUnwind
)
TRACE
(
"calling TEB handler %p (rec=%p, frame=%p context=%p, dispatch=%p)
\n
"
,
teb_frame
->
Handler
,
rec
,
teb_frame
,
dispatch
.
ContextRecord
,
&
dispatch
);
res
=
call_unwind_handler
(
rec
,
(
ULONG_PTR
)
teb_frame
,
dispatch
.
ContextRecord
,
&
dispatch
,
(
PEXCEPTION_ROUTINE
)
teb_frame
->
Handler
);
TRACE
(
"handler at %p returned %lu
\n
"
,
teb_frame
->
Handler
,
res
);
teb_frame
=
__wine_pop_frame
(
teb_frame
);
switch
(
res
)
{
teb_frame
=
__wine_pop_frame
(
teb_frame
);
case
ExceptionContinueSearch
:
rec
->
ExceptionFlags
&=
~
EXCEPTION_COLLIDED_UNWIND
;
break
;
case
ExceptionCollidedUnwind
:
new_context
=
*
context
;
RtlVirtualUnwind
(
UNW_FLAG_NHANDLER
,
dispatch
.
ImageBase
,
dispatch
.
ControlPc
,
dispatch
.
FunctionEntry
,
&
new_context
,
NULL
,
&
frame
,
NULL
);
dispatch
.
ControlPc
,
dispatch
.
FunctionEntry
,
&
new_context
,
&
dispatch
.
HandlerData
,
&
frame
,
NULL
);
rec
->
ExceptionFlags
|=
EXCEPTION_COLLIDED_UNWIND
;
goto
unwind_done
;
default
:
raise_status
(
STATUS_INVALID_DISPOSITION
,
rec
);
break
;
}
teb_frame
=
__wine_pop_frame
(
teb_frame
);
}
if
((
ULONG64
)
teb_frame
==
(
ULONG64
)
end_frame
&&
(
ULONG64
)
end_frame
<
new_context
.
Rsp
)
break
;
dispatch
.
EstablisherFrame
=
backup_frame
;
}
if
(
dispatch
.
EstablisherFrame
==
(
ULONG64
)
end_frame
)
break
;
...
...
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