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
89b2dd08
Commit
89b2dd08
authored
Mar 13, 2012
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
msvcrt: Move more i386-specific exception code to except_i386.c.
parent
aba6423b
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
542 additions
and
544 deletions
+542
-544
cppexcept.h
dlls/msvcrt/cppexcept.h
+5
-56
except.c
dlls/msvcrt/except.c
+1
-488
except_i386.c
dlls/msvcrt/except_i386.c
+536
-0
No files found.
dlls/msvcrt/cppexcept.h
View file @
89b2dd08
...
...
@@ -44,59 +44,6 @@ typedef struct __exception
int
do_free
;
/* Whether to free 'name' in our dtor */
}
exception
;
/* the exception frame used by CxxFrameHandler */
typedef
struct
__cxx_exception_frame
{
EXCEPTION_REGISTRATION_RECORD
frame
;
/* the standard exception frame */
int
trylevel
;
DWORD
ebp
;
}
cxx_exception_frame
;
/* info about a single catch {} block */
typedef
struct
__catchblock_info
{
UINT
flags
;
/* flags (see below) */
const
type_info
*
type_info
;
/* C++ type caught by this block */
int
offset
;
/* stack offset to copy exception object to */
void
(
*
handler
)(
void
);
/* catch block handler code */
}
catchblock_info
;
#define TYPE_FLAG_CONST 1
#define TYPE_FLAG_VOLATILE 2
#define TYPE_FLAG_REFERENCE 8
/* info about a single try {} block */
typedef
struct
__tryblock_info
{
int
start_level
;
/* start trylevel of that block */
int
end_level
;
/* end trylevel of that block */
int
catch_level
;
/* initial trylevel of the catch block */
int
catchblock_count
;
/* count of catch blocks in array */
const
catchblock_info
*
catchblock
;
/* array of catch blocks */
}
tryblock_info
;
/* info about the unwind handler for a given trylevel */
typedef
struct
__unwind_info
{
int
prev
;
/* prev trylevel unwind handler, to run after this one */
void
(
*
handler
)(
void
);
/* unwind handler */
}
unwind_info
;
/* descriptor of all try blocks of a given function */
typedef
struct
__cxx_function_descr
{
UINT
magic
;
/* must be CXX_FRAME_MAGIC */
UINT
unwind_count
;
/* number of unwind handlers */
const
unwind_info
*
unwind_table
;
/* array of unwind handlers */
UINT
tryblock_count
;
/* number of try blocks */
const
tryblock_info
*
tryblock
;
/* array of try blocks */
UINT
ipmap_count
;
const
void
*
ipmap
;
const
void
*
expect_list
;
/* expected exceptions list when magic >= VC7 */
UINT
flags
;
/* flags when magic >= VC8 */
}
cxx_function_descr
;
#define FUNC_DESCR_SYNCHRONOUS 1
/* synchronous exceptions only (built with /EHs) */
typedef
void
(
*
cxx_copy_ctor
)(
void
);
/* offsets for computing the this pointer */
...
...
@@ -126,9 +73,12 @@ typedef struct __cxx_type_info_table
const
cxx_type_info
*
info
[
3
];
/* variable length, we declare it large enough for static RTTI */
}
cxx_type_info_table
;
typedef
DWORD
(
*
cxx_exc_custom_handler
)(
PEXCEPTION_RECORD
,
cxx_exception_frame
*
,
struct
__cxx_exception_frame
;
struct
__cxx_function_descr
;
typedef
DWORD
(
*
cxx_exc_custom_handler
)(
PEXCEPTION_RECORD
,
struct
__cxx_exception_frame
*
,
PCONTEXT
,
EXCEPTION_REGISTRATION_RECORD
**
,
const
cxx_function_descr
*
,
int
nested_trylevel
,
const
struct
__
cxx_function_descr
*
,
int
nested_trylevel
,
EXCEPTION_REGISTRATION_RECORD
*
nested_frame
,
DWORD
unknown3
);
/* type information for an exception object */
...
...
@@ -142,7 +92,6 @@ typedef struct __cxx_exception_type
void
WINAPI
_CxxThrowException
(
exception
*
,
const
cxx_exception_type
*
);
int
CDECL
_XcptFilter
(
NTSTATUS
,
PEXCEPTION_POINTERS
);
int
CDECL
__CppXcptFilter
(
NTSTATUS
,
PEXCEPTION_POINTERS
);
static
inline
const
char
*
dbgstr_type_info
(
const
type_info
*
info
)
{
...
...
dlls/msvcrt/except.c
View file @
89b2dd08
...
...
@@ -41,494 +41,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(seh);
static
MSVCRT_security_error_handler
security_error_handler
;
/* VC++ extensions to Win32 SEH */
typedef
struct
_SCOPETABLE
{
int
previousTryLevel
;
int
(
*
lpfnFilter
)(
PEXCEPTION_POINTERS
);
int
(
*
lpfnHandler
)(
void
);
}
SCOPETABLE
,
*
PSCOPETABLE
;
typedef
struct
_MSVCRT_EXCEPTION_FRAME
{
EXCEPTION_REGISTRATION_RECORD
*
prev
;
void
(
*
handler
)(
PEXCEPTION_RECORD
,
EXCEPTION_REGISTRATION_RECORD
*
,
PCONTEXT
,
PEXCEPTION_RECORD
);
PSCOPETABLE
scopetable
;
int
trylevel
;
int
_ebp
;
PEXCEPTION_POINTERS
xpointers
;
}
MSVCRT_EXCEPTION_FRAME
;
typedef
struct
{
int
gs_cookie_offset
;
ULONG
gs_cookie_xor
;
int
eh_cookie_offset
;
ULONG
eh_cookie_xor
;
SCOPETABLE
entries
[
1
];
}
SCOPETABLE_V4
;
#define TRYLEVEL_END (-1)
/* End of trylevel list */
#if defined(__GNUC__) && defined(__i386__)
static
inline
void
call_finally_block
(
void
*
code_block
,
void
*
base_ptr
)
{
__asm__
__volatile__
(
"movl %1,%%ebp; call *%%eax"
:
:
"a"
(
code_block
),
"g"
(
base_ptr
));
}
static
inline
int
call_filter
(
int
(
*
func
)(
PEXCEPTION_POINTERS
),
void
*
arg
,
void
*
ebp
)
{
int
ret
;
__asm__
__volatile__
(
"pushl %%ebp; pushl %3; movl %2,%%ebp; call *%%eax; popl %%ebp; popl %%ebp"
:
"=a"
(
ret
)
:
"0"
(
func
),
"r"
(
ebp
),
"r"
(
arg
)
:
"ecx"
,
"edx"
,
"memory"
);
return
ret
;
}
static
inline
int
call_unwind_func
(
int
(
*
func
)(
void
),
void
*
ebp
)
{
int
ret
;
__asm__
__volatile__
(
"pushl %%ebp
\n\t
"
"pushl %%ebx
\n\t
"
"pushl %%esi
\n\t
"
"pushl %%edi
\n\t
"
"movl %2,%%ebp
\n\t
"
"call *%0
\n\t
"
"popl %%edi
\n\t
"
"popl %%esi
\n\t
"
"popl %%ebx
\n\t
"
"popl %%ebp"
:
"=a"
(
ret
)
:
"0"
(
func
),
"r"
(
ebp
)
:
"ecx"
,
"edx"
,
"memory"
);
return
ret
;
}
#endif
#ifdef __i386__
static
const
SCOPETABLE_V4
*
get_scopetable_v4
(
MSVCRT_EXCEPTION_FRAME
*
frame
,
ULONG_PTR
cookie
)
{
return
(
const
SCOPETABLE_V4
*
)((
ULONG_PTR
)
frame
->
scopetable
^
cookie
);
}
static
DWORD
MSVCRT_nested_handler
(
PEXCEPTION_RECORD
rec
,
EXCEPTION_REGISTRATION_RECORD
*
frame
,
PCONTEXT
context
,
EXCEPTION_REGISTRATION_RECORD
**
dispatch
)
{
if
(
!
(
rec
->
ExceptionFlags
&
(
EH_UNWINDING
|
EH_EXIT_UNWIND
)))
return
ExceptionContinueSearch
;
*
dispatch
=
frame
;
return
ExceptionCollidedUnwind
;
}
/*********************************************************************
* _EH_prolog (MSVCRT.@)
*/
/* Provided for VC++ binary compatibility only */
__ASM_GLOBAL_FUNC
(
_EH_prolog
,
__ASM_CFI
(
".cfi_adjust_cfa_offset 4
\n\t
"
)
/* skip ret addr */
"pushl $-1
\n\t
"
__ASM_CFI
(
".cfi_adjust_cfa_offset 4
\n\t
"
)
"pushl %eax
\n\t
"
__ASM_CFI
(
".cfi_adjust_cfa_offset 4
\n\t
"
)
"pushl %fs:0
\n\t
"
__ASM_CFI
(
".cfi_adjust_cfa_offset 4
\n\t
"
)
"movl %esp, %fs:0
\n\t
"
"movl 12(%esp), %eax
\n\t
"
"movl %ebp, 12(%esp)
\n\t
"
"leal 12(%esp), %ebp
\n\t
"
"pushl %eax
\n\t
"
__ASM_CFI
(
".cfi_adjust_cfa_offset 4
\n\t
"
)
"ret"
)
static
void
msvcrt_local_unwind2
(
MSVCRT_EXCEPTION_FRAME
*
frame
,
int
trylevel
,
void
*
ebp
)
{
EXCEPTION_REGISTRATION_RECORD
reg
;
TRACE
(
"(%p,%d,%d)
\n
"
,
frame
,
frame
->
trylevel
,
trylevel
);
/* Register a handler in case of a nested exception */
reg
.
Handler
=
MSVCRT_nested_handler
;
reg
.
Prev
=
NtCurrentTeb
()
->
Tib
.
ExceptionList
;
__wine_push_frame
(
&
reg
);
while
(
frame
->
trylevel
!=
TRYLEVEL_END
&&
frame
->
trylevel
!=
trylevel
)
{
int
level
=
frame
->
trylevel
;
frame
->
trylevel
=
frame
->
scopetable
[
level
].
previousTryLevel
;
if
(
!
frame
->
scopetable
[
level
].
lpfnFilter
)
{
TRACE
(
"__try block cleanup level %d handler %p ebp %p
\n
"
,
level
,
frame
->
scopetable
[
level
].
lpfnHandler
,
ebp
);
call_unwind_func
(
frame
->
scopetable
[
level
].
lpfnHandler
,
ebp
);
}
}
__wine_pop_frame
(
&
reg
);
TRACE
(
"unwound OK
\n
"
);
}
static
void
msvcrt_local_unwind4
(
ULONG
*
cookie
,
MSVCRT_EXCEPTION_FRAME
*
frame
,
int
trylevel
,
void
*
ebp
)
{
EXCEPTION_REGISTRATION_RECORD
reg
;
const
SCOPETABLE_V4
*
scopetable
=
get_scopetable_v4
(
frame
,
*
cookie
);
TRACE
(
"(%p,%d,%d)
\n
"
,
frame
,
frame
->
trylevel
,
trylevel
);
/* Register a handler in case of a nested exception */
reg
.
Handler
=
MSVCRT_nested_handler
;
reg
.
Prev
=
NtCurrentTeb
()
->
Tib
.
ExceptionList
;
__wine_push_frame
(
&
reg
);
while
(
frame
->
trylevel
!=
-
2
&&
frame
->
trylevel
!=
trylevel
)
{
int
level
=
frame
->
trylevel
;
frame
->
trylevel
=
scopetable
->
entries
[
level
].
previousTryLevel
;
if
(
!
scopetable
->
entries
[
level
].
lpfnFilter
)
{
TRACE
(
"__try block cleanup level %d handler %p ebp %p
\n
"
,
level
,
scopetable
->
entries
[
level
].
lpfnHandler
,
ebp
);
call_unwind_func
(
scopetable
->
entries
[
level
].
lpfnHandler
,
ebp
);
}
}
__wine_pop_frame
(
&
reg
);
TRACE
(
"unwound OK
\n
"
);
}
/*******************************************************************
* _local_unwind2 (MSVCRT.@)
*/
void
CDECL
_local_unwind2
(
MSVCRT_EXCEPTION_FRAME
*
frame
,
int
trylevel
)
{
msvcrt_local_unwind2
(
frame
,
trylevel
,
&
frame
->
_ebp
);
}
/*******************************************************************
* _local_unwind4 (MSVCRT.@)
*/
void
CDECL
_local_unwind4
(
ULONG
*
cookie
,
MSVCRT_EXCEPTION_FRAME
*
frame
,
int
trylevel
)
{
msvcrt_local_unwind4
(
cookie
,
frame
,
trylevel
,
&
frame
->
_ebp
);
}
/*******************************************************************
* _global_unwind2 (MSVCRT.@)
*/
void
CDECL
_global_unwind2
(
EXCEPTION_REGISTRATION_RECORD
*
frame
)
{
TRACE
(
"(%p)
\n
"
,
frame
);
RtlUnwind
(
frame
,
0
,
0
,
0
);
}
/*********************************************************************
* _except_handler2 (MSVCRT.@)
*/
int
CDECL
_except_handler2
(
PEXCEPTION_RECORD
rec
,
EXCEPTION_REGISTRATION_RECORD
*
frame
,
PCONTEXT
context
,
EXCEPTION_REGISTRATION_RECORD
**
dispatcher
)
{
FIXME
(
"exception %x flags=%x at %p handler=%p %p %p stub
\n
"
,
rec
->
ExceptionCode
,
rec
->
ExceptionFlags
,
rec
->
ExceptionAddress
,
frame
->
Handler
,
context
,
dispatcher
);
return
ExceptionContinueSearch
;
}
/*********************************************************************
* _except_handler3 (MSVCRT.@)
*/
int
CDECL
_except_handler3
(
PEXCEPTION_RECORD
rec
,
MSVCRT_EXCEPTION_FRAME
*
frame
,
PCONTEXT
context
,
void
*
dispatcher
)
{
int
retval
,
trylevel
;
EXCEPTION_POINTERS
exceptPtrs
;
PSCOPETABLE
pScopeTable
;
TRACE
(
"exception %x flags=%x at %p handler=%p %p %p semi-stub
\n
"
,
rec
->
ExceptionCode
,
rec
->
ExceptionFlags
,
rec
->
ExceptionAddress
,
frame
->
handler
,
context
,
dispatcher
);
__asm__
__volatile__
(
"cld"
);
if
(
rec
->
ExceptionFlags
&
(
EH_UNWINDING
|
EH_EXIT_UNWIND
))
{
/* Unwinding the current frame */
msvcrt_local_unwind2
(
frame
,
TRYLEVEL_END
,
&
frame
->
_ebp
);
TRACE
(
"unwound current frame, returning ExceptionContinueSearch
\n
"
);
return
ExceptionContinueSearch
;
}
else
{
/* Hunting for handler */
exceptPtrs
.
ExceptionRecord
=
rec
;
exceptPtrs
.
ContextRecord
=
context
;
*
((
DWORD
*
)
frame
-
1
)
=
(
DWORD
)
&
exceptPtrs
;
trylevel
=
frame
->
trylevel
;
pScopeTable
=
frame
->
scopetable
;
while
(
trylevel
!=
TRYLEVEL_END
)
{
TRACE
(
"level %d prev %d filter %p
\n
"
,
trylevel
,
pScopeTable
[
trylevel
].
previousTryLevel
,
pScopeTable
[
trylevel
].
lpfnFilter
);
if
(
pScopeTable
[
trylevel
].
lpfnFilter
)
{
retval
=
call_filter
(
pScopeTable
[
trylevel
].
lpfnFilter
,
&
exceptPtrs
,
&
frame
->
_ebp
);
TRACE
(
"filter returned %s
\n
"
,
retval
==
EXCEPTION_CONTINUE_EXECUTION
?
"CONTINUE_EXECUTION"
:
retval
==
EXCEPTION_EXECUTE_HANDLER
?
"EXECUTE_HANDLER"
:
"CONTINUE_SEARCH"
);
if
(
retval
==
EXCEPTION_CONTINUE_EXECUTION
)
return
ExceptionContinueExecution
;
if
(
retval
==
EXCEPTION_EXECUTE_HANDLER
)
{
/* Unwind all higher frames, this one will handle the exception */
_global_unwind2
((
EXCEPTION_REGISTRATION_RECORD
*
)
frame
);
msvcrt_local_unwind2
(
frame
,
trylevel
,
&
frame
->
_ebp
);
/* Set our trylevel to the enclosing block, and call the __finally
* code, which won't return
*/
frame
->
trylevel
=
pScopeTable
[
trylevel
].
previousTryLevel
;
TRACE
(
"__finally block %p
\n
"
,
pScopeTable
[
trylevel
].
lpfnHandler
);
call_finally_block
(
pScopeTable
[
trylevel
].
lpfnHandler
,
&
frame
->
_ebp
);
ERR
(
"Returned from __finally block - expect crash!
\n
"
);
}
}
trylevel
=
pScopeTable
[
trylevel
].
previousTryLevel
;
}
}
TRACE
(
"reached TRYLEVEL_END, returning ExceptionContinueSearch
\n
"
);
return
ExceptionContinueSearch
;
}
/*********************************************************************
* _except_handler4_common (MSVCRT.@)
*/
int
CDECL
_except_handler4_common
(
ULONG
*
cookie
,
void
(
*
check_cookie
)(
void
),
EXCEPTION_RECORD
*
rec
,
MSVCRT_EXCEPTION_FRAME
*
frame
,
CONTEXT
*
context
,
EXCEPTION_REGISTRATION_RECORD
**
dispatcher
)
{
int
retval
,
trylevel
;
EXCEPTION_POINTERS
exceptPtrs
;
const
SCOPETABLE_V4
*
scope_table
=
get_scopetable_v4
(
frame
,
*
cookie
);
TRACE
(
"exception %x flags=%x at %p handler=%p %p %p cookie=%x scope table=%p cookies=%d/%x,%d/%x
\n
"
,
rec
->
ExceptionCode
,
rec
->
ExceptionFlags
,
rec
->
ExceptionAddress
,
frame
->
handler
,
context
,
dispatcher
,
*
cookie
,
scope_table
,
scope_table
->
gs_cookie_offset
,
scope_table
->
gs_cookie_xor
,
scope_table
->
eh_cookie_offset
,
scope_table
->
eh_cookie_xor
);
/* FIXME: no cookie validation yet */
if
(
rec
->
ExceptionFlags
&
(
EH_UNWINDING
|
EH_EXIT_UNWIND
))
{
/* Unwinding the current frame */
msvcrt_local_unwind4
(
cookie
,
frame
,
-
2
,
&
frame
->
_ebp
);
TRACE
(
"unwound current frame, returning ExceptionContinueSearch
\n
"
);
return
ExceptionContinueSearch
;
}
else
{
/* Hunting for handler */
exceptPtrs
.
ExceptionRecord
=
rec
;
exceptPtrs
.
ContextRecord
=
context
;
*
((
DWORD
*
)
frame
-
1
)
=
(
DWORD
)
&
exceptPtrs
;
trylevel
=
frame
->
trylevel
;
while
(
trylevel
!=
-
2
)
{
TRACE
(
"level %d prev %d filter %p
\n
"
,
trylevel
,
scope_table
->
entries
[
trylevel
].
previousTryLevel
,
scope_table
->
entries
[
trylevel
].
lpfnFilter
);
if
(
scope_table
->
entries
[
trylevel
].
lpfnFilter
)
{
retval
=
call_filter
(
scope_table
->
entries
[
trylevel
].
lpfnFilter
,
&
exceptPtrs
,
&
frame
->
_ebp
);
TRACE
(
"filter returned %s
\n
"
,
retval
==
EXCEPTION_CONTINUE_EXECUTION
?
"CONTINUE_EXECUTION"
:
retval
==
EXCEPTION_EXECUTE_HANDLER
?
"EXECUTE_HANDLER"
:
"CONTINUE_SEARCH"
);
if
(
retval
==
EXCEPTION_CONTINUE_EXECUTION
)
return
ExceptionContinueExecution
;
if
(
retval
==
EXCEPTION_EXECUTE_HANDLER
)
{
/* Unwind all higher frames, this one will handle the exception */
_global_unwind2
((
EXCEPTION_REGISTRATION_RECORD
*
)
frame
);
msvcrt_local_unwind4
(
cookie
,
frame
,
trylevel
,
&
frame
->
_ebp
);
/* Set our trylevel to the enclosing block, and call the __finally
* code, which won't return
*/
frame
->
trylevel
=
scope_table
->
entries
[
trylevel
].
previousTryLevel
;
TRACE
(
"__finally block %p
\n
"
,
scope_table
->
entries
[
trylevel
].
lpfnHandler
);
call_finally_block
(
scope_table
->
entries
[
trylevel
].
lpfnHandler
,
&
frame
->
_ebp
);
ERR
(
"Returned from __finally block - expect crash!
\n
"
);
}
}
trylevel
=
scope_table
->
entries
[
trylevel
].
previousTryLevel
;
}
}
TRACE
(
"reached -2, returning ExceptionContinueSearch
\n
"
);
return
ExceptionContinueSearch
;
}
/*
* setjmp/longjmp implementation
*/
#define MSVCRT_JMP_MAGIC 0x56433230
/* ID value for new jump structure */
typedef
void
(
__stdcall
*
MSVCRT_unwind_function
)(
const
struct
MSVCRT___JUMP_BUFFER
*
);
/* define an entrypoint for setjmp/setjmp3 that stores the registers in the jmp buf */
/* and then jumps to the C backend function */
#define DEFINE_SETJMP_ENTRYPOINT(name) \
__ASM_GLOBAL_FUNC( name, \
"movl 4(%esp),%ecx\n\t"
/* jmp_buf */
\
"movl %ebp,0(%ecx)\n\t"
/* jmp_buf.Ebp */
\
"movl %ebx,4(%ecx)\n\t"
/* jmp_buf.Ebx */
\
"movl %edi,8(%ecx)\n\t"
/* jmp_buf.Edi */
\
"movl %esi,12(%ecx)\n\t"
/* jmp_buf.Esi */
\
"movl %esp,16(%ecx)\n\t"
/* jmp_buf.Esp */
\
"movl 0(%esp),%eax\n\t" \
"movl %eax,20(%ecx)\n\t"
/* jmp_buf.Eip */
\
"jmp " __ASM_NAME("__regs_") # name )
/* restore the registers from the jmp buf upon longjmp */
extern
void
DECLSPEC_NORETURN
longjmp_set_regs
(
struct
MSVCRT___JUMP_BUFFER
*
jmp
,
int
retval
);
__ASM_GLOBAL_FUNC
(
longjmp_set_regs
,
"movl 4(%esp),%ecx
\n\t
"
/* jmp_buf */
"movl 8(%esp),%eax
\n\t
"
/* retval */
"movl 0(%ecx),%ebp
\n\t
"
/* jmp_buf.Ebp */
"movl 4(%ecx),%ebx
\n\t
"
/* jmp_buf.Ebx */
"movl 8(%ecx),%edi
\n\t
"
/* jmp_buf.Edi */
"movl 12(%ecx),%esi
\n\t
"
/* jmp_buf.Esi */
"movl 16(%ecx),%esp
\n\t
"
/* jmp_buf.Esp */
"addl $4,%esp
\n\t
"
/* get rid of return address */
"jmp *20(%ecx)
\n\t
"
/* jmp_buf.Eip */
)
/*
* The signatures of the setjmp/longjmp functions do not match that
* declared in the setjmp header so they don't follow the regular naming
* convention to avoid conflicts.
*/
/*******************************************************************
* _setjmp (MSVCRT.@)
*/
DEFINE_SETJMP_ENTRYPOINT
(
MSVCRT__setjmp
)
int
CDECL
__regs_MSVCRT__setjmp
(
struct
MSVCRT___JUMP_BUFFER
*
jmp
)
{
jmp
->
Registration
=
(
unsigned
long
)
NtCurrentTeb
()
->
Tib
.
ExceptionList
;
if
(
jmp
->
Registration
==
~
0UL
)
jmp
->
TryLevel
=
TRYLEVEL_END
;
else
jmp
->
TryLevel
=
((
MSVCRT_EXCEPTION_FRAME
*
)
jmp
->
Registration
)
->
trylevel
;
TRACE
(
"buf=%p ebx=%08lx esi=%08lx edi=%08lx ebp=%08lx esp=%08lx eip=%08lx frame=%08lx
\n
"
,
jmp
,
jmp
->
Ebx
,
jmp
->
Esi
,
jmp
->
Edi
,
jmp
->
Ebp
,
jmp
->
Esp
,
jmp
->
Eip
,
jmp
->
Registration
);
return
0
;
}
/*******************************************************************
* _setjmp3 (MSVCRT.@)
*/
DEFINE_SETJMP_ENTRYPOINT
(
MSVCRT__setjmp3
)
int
CDECL
__regs_MSVCRT__setjmp3
(
struct
MSVCRT___JUMP_BUFFER
*
jmp
,
int
nb_args
,
...)
{
jmp
->
Cookie
=
MSVCRT_JMP_MAGIC
;
jmp
->
UnwindFunc
=
0
;
jmp
->
Registration
=
(
unsigned
long
)
NtCurrentTeb
()
->
Tib
.
ExceptionList
;
if
(
jmp
->
Registration
==
~
0UL
)
{
jmp
->
TryLevel
=
TRYLEVEL_END
;
}
else
{
int
i
;
va_list
args
;
va_start
(
args
,
nb_args
);
if
(
nb_args
>
0
)
jmp
->
UnwindFunc
=
va_arg
(
args
,
unsigned
long
);
if
(
nb_args
>
1
)
jmp
->
TryLevel
=
va_arg
(
args
,
unsigned
long
);
else
jmp
->
TryLevel
=
((
MSVCRT_EXCEPTION_FRAME
*
)
jmp
->
Registration
)
->
trylevel
;
for
(
i
=
0
;
i
<
6
&&
i
<
nb_args
-
2
;
i
++
)
jmp
->
UnwindData
[
i
]
=
va_arg
(
args
,
unsigned
long
);
va_end
(
args
);
}
TRACE
(
"buf=%p ebx=%08lx esi=%08lx edi=%08lx ebp=%08lx esp=%08lx eip=%08lx frame=%08lx
\n
"
,
jmp
,
jmp
->
Ebx
,
jmp
->
Esi
,
jmp
->
Edi
,
jmp
->
Ebp
,
jmp
->
Esp
,
jmp
->
Eip
,
jmp
->
Registration
);
return
0
;
}
/*********************************************************************
* longjmp (MSVCRT.@)
*/
void
CDECL
MSVCRT_longjmp
(
struct
MSVCRT___JUMP_BUFFER
*
jmp
,
int
retval
)
{
unsigned
long
cur_frame
=
0
;
TRACE
(
"buf=%p ebx=%08lx esi=%08lx edi=%08lx ebp=%08lx esp=%08lx eip=%08lx frame=%08lx retval=%08x
\n
"
,
jmp
,
jmp
->
Ebx
,
jmp
->
Esi
,
jmp
->
Edi
,
jmp
->
Ebp
,
jmp
->
Esp
,
jmp
->
Eip
,
jmp
->
Registration
,
retval
);
cur_frame
=
(
unsigned
long
)
NtCurrentTeb
()
->
Tib
.
ExceptionList
;
TRACE
(
"cur_frame=%lx
\n
"
,
cur_frame
);
if
(
cur_frame
!=
jmp
->
Registration
)
_global_unwind2
((
EXCEPTION_REGISTRATION_RECORD
*
)
jmp
->
Registration
);
if
(
jmp
->
Registration
)
{
if
(
!
IsBadReadPtr
(
&
jmp
->
Cookie
,
sizeof
(
long
))
&&
jmp
->
Cookie
==
MSVCRT_JMP_MAGIC
&&
jmp
->
UnwindFunc
)
{
MSVCRT_unwind_function
unwind_func
;
unwind_func
=
(
MSVCRT_unwind_function
)
jmp
->
UnwindFunc
;
unwind_func
(
jmp
);
}
else
msvcrt_local_unwind2
((
MSVCRT_EXCEPTION_FRAME
*
)
jmp
->
Registration
,
jmp
->
TryLevel
,
(
void
*
)
jmp
->
Ebp
);
}
if
(
!
retval
)
retval
=
1
;
longjmp_set_regs
(
jmp
,
retval
);
}
/*********************************************************************
* _seh_longjmp_unwind (MSVCRT.@)
*/
void
__stdcall
_seh_longjmp_unwind
(
struct
MSVCRT___JUMP_BUFFER
*
jmp
)
{
msvcrt_local_unwind2
(
(
MSVCRT_EXCEPTION_FRAME
*
)
jmp
->
Registration
,
jmp
->
TryLevel
,
(
void
*
)
jmp
->
Ebp
);
}
/*********************************************************************
* _seh_longjmp_unwind4 (MSVCRT.@)
*/
void
__stdcall
_seh_longjmp_unwind4
(
struct
MSVCRT___JUMP_BUFFER
*
jmp
)
{
msvcrt_local_unwind4
(
(
void
*
)
jmp
->
Cookie
,
(
MSVCRT_EXCEPTION_FRAME
*
)
jmp
->
Registration
,
jmp
->
TryLevel
,
(
void
*
)
jmp
->
Ebp
);
}
#elif defined(__x86_64__)
#ifdef __x86_64__
/*******************************************************************
* _setjmp (MSVCRT.@)
...
...
dlls/msvcrt/except_i386.c
View file @
89b2dd08
/*
* msvcrt C++ exception handling
*
* Copyright 2000 Jon Griffiths
* Copyright 2002 Alexandre Julliard
* Copyright 2005 Juan Lang
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
...
...
@@ -42,6 +44,89 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
seh
);
/* the exception frame used by CxxFrameHandler */
typedef
struct
__cxx_exception_frame
{
EXCEPTION_REGISTRATION_RECORD
frame
;
/* the standard exception frame */
int
trylevel
;
DWORD
ebp
;
}
cxx_exception_frame
;
/* info about a single catch {} block */
typedef
struct
__catchblock_info
{
UINT
flags
;
/* flags (see below) */
const
type_info
*
type_info
;
/* C++ type caught by this block */
int
offset
;
/* stack offset to copy exception object to */
void
(
*
handler
)(
void
);
/* catch block handler code */
}
catchblock_info
;
#define TYPE_FLAG_CONST 1
#define TYPE_FLAG_VOLATILE 2
#define TYPE_FLAG_REFERENCE 8
/* info about a single try {} block */
typedef
struct
__tryblock_info
{
int
start_level
;
/* start trylevel of that block */
int
end_level
;
/* end trylevel of that block */
int
catch_level
;
/* initial trylevel of the catch block */
int
catchblock_count
;
/* count of catch blocks in array */
const
catchblock_info
*
catchblock
;
/* array of catch blocks */
}
tryblock_info
;
/* info about the unwind handler for a given trylevel */
typedef
struct
__unwind_info
{
int
prev
;
/* prev trylevel unwind handler, to run after this one */
void
(
*
handler
)(
void
);
/* unwind handler */
}
unwind_info
;
/* descriptor of all try blocks of a given function */
typedef
struct
__cxx_function_descr
{
UINT
magic
;
/* must be CXX_FRAME_MAGIC */
UINT
unwind_count
;
/* number of unwind handlers */
const
unwind_info
*
unwind_table
;
/* array of unwind handlers */
UINT
tryblock_count
;
/* number of try blocks */
const
tryblock_info
*
tryblock
;
/* array of try blocks */
UINT
ipmap_count
;
const
void
*
ipmap
;
const
void
*
expect_list
;
/* expected exceptions list when magic >= VC7 */
UINT
flags
;
/* flags when magic >= VC8 */
}
cxx_function_descr
;
#define FUNC_DESCR_SYNCHRONOUS 1
/* synchronous exceptions only (built with /EHs) */
typedef
struct
_SCOPETABLE
{
int
previousTryLevel
;
int
(
*
lpfnFilter
)(
PEXCEPTION_POINTERS
);
int
(
*
lpfnHandler
)(
void
);
}
SCOPETABLE
,
*
PSCOPETABLE
;
typedef
struct
_MSVCRT_EXCEPTION_FRAME
{
EXCEPTION_REGISTRATION_RECORD
*
prev
;
void
(
*
handler
)(
PEXCEPTION_RECORD
,
EXCEPTION_REGISTRATION_RECORD
*
,
PCONTEXT
,
PEXCEPTION_RECORD
);
PSCOPETABLE
scopetable
;
int
trylevel
;
int
_ebp
;
PEXCEPTION_POINTERS
xpointers
;
}
MSVCRT_EXCEPTION_FRAME
;
typedef
struct
{
int
gs_cookie_offset
;
ULONG
gs_cookie_xor
;
int
eh_cookie_offset
;
ULONG
eh_cookie_xor
;
SCOPETABLE
entries
[
1
];
}
SCOPETABLE_V4
;
#define TRYLEVEL_END (-1)
/* End of trylevel list */
DWORD
CDECL
cxx_frame_handler
(
PEXCEPTION_RECORD
rec
,
cxx_exception_frame
*
frame
,
PCONTEXT
context
,
EXCEPTION_REGISTRATION_RECORD
**
dispatch
,
const
cxx_function_descr
*
descr
,
...
...
@@ -90,6 +175,41 @@ static inline void DECLSPEC_NORETURN continue_after_catch( cxx_exception_frame*
for
(;;)
;
/* unreached */
}
static
inline
void
call_finally_block
(
void
*
code_block
,
void
*
base_ptr
)
{
__asm__
__volatile__
(
"movl %1,%%ebp; call *%%eax"
:
:
"a"
(
code_block
),
"g"
(
base_ptr
));
}
static
inline
int
call_filter
(
int
(
*
func
)(
PEXCEPTION_POINTERS
),
void
*
arg
,
void
*
ebp
)
{
int
ret
;
__asm__
__volatile__
(
"pushl %%ebp; pushl %3; movl %2,%%ebp; call *%%eax; popl %%ebp; popl %%ebp"
:
"=a"
(
ret
)
:
"0"
(
func
),
"r"
(
ebp
),
"r"
(
arg
)
:
"ecx"
,
"edx"
,
"memory"
);
return
ret
;
}
static
inline
int
call_unwind_func
(
int
(
*
func
)(
void
),
void
*
ebp
)
{
int
ret
;
__asm__
__volatile__
(
"pushl %%ebp
\n\t
"
"pushl %%ebx
\n\t
"
"pushl %%esi
\n\t
"
"pushl %%edi
\n\t
"
"movl %2,%%ebp
\n\t
"
"call *%0
\n\t
"
"popl %%edi
\n\t
"
"popl %%esi
\n\t
"
"popl %%ebx
\n\t
"
"popl %%ebp"
:
"=a"
(
ret
)
:
"0"
(
func
),
"r"
(
ebp
)
:
"ecx"
,
"edx"
,
"memory"
);
return
ret
;
}
static
inline
void
dump_type
(
const
cxx_type_info
*
type
)
{
TRACE
(
"flags %x type %p %s offsets %d,%d,%d size %d copy ctor %p
\n
"
,
...
...
@@ -496,4 +616,420 @@ unsigned int CDECL __CxxQueryExceptionSize(void)
return
sizeof
(
cxx_exception_type
);
}
/*********************************************************************
* _EH_prolog (MSVCRT.@)
*/
/* Provided for VC++ binary compatibility only */
__ASM_GLOBAL_FUNC
(
_EH_prolog
,
__ASM_CFI
(
".cfi_adjust_cfa_offset 4
\n\t
"
)
/* skip ret addr */
"pushl $-1
\n\t
"
__ASM_CFI
(
".cfi_adjust_cfa_offset 4
\n\t
"
)
"pushl %eax
\n\t
"
__ASM_CFI
(
".cfi_adjust_cfa_offset 4
\n\t
"
)
"pushl %fs:0
\n\t
"
__ASM_CFI
(
".cfi_adjust_cfa_offset 4
\n\t
"
)
"movl %esp, %fs:0
\n\t
"
"movl 12(%esp), %eax
\n\t
"
"movl %ebp, 12(%esp)
\n\t
"
"leal 12(%esp), %ebp
\n\t
"
"pushl %eax
\n\t
"
__ASM_CFI
(
".cfi_adjust_cfa_offset 4
\n\t
"
)
"ret"
)
static
const
SCOPETABLE_V4
*
get_scopetable_v4
(
MSVCRT_EXCEPTION_FRAME
*
frame
,
ULONG_PTR
cookie
)
{
return
(
const
SCOPETABLE_V4
*
)((
ULONG_PTR
)
frame
->
scopetable
^
cookie
);
}
static
DWORD
MSVCRT_nested_handler
(
PEXCEPTION_RECORD
rec
,
EXCEPTION_REGISTRATION_RECORD
*
frame
,
PCONTEXT
context
,
EXCEPTION_REGISTRATION_RECORD
**
dispatch
)
{
if
(
!
(
rec
->
ExceptionFlags
&
(
EH_UNWINDING
|
EH_EXIT_UNWIND
)))
return
ExceptionContinueSearch
;
*
dispatch
=
frame
;
return
ExceptionCollidedUnwind
;
}
static
void
msvcrt_local_unwind2
(
MSVCRT_EXCEPTION_FRAME
*
frame
,
int
trylevel
,
void
*
ebp
)
{
EXCEPTION_REGISTRATION_RECORD
reg
;
TRACE
(
"(%p,%d,%d)
\n
"
,
frame
,
frame
->
trylevel
,
trylevel
);
/* Register a handler in case of a nested exception */
reg
.
Handler
=
MSVCRT_nested_handler
;
reg
.
Prev
=
NtCurrentTeb
()
->
Tib
.
ExceptionList
;
__wine_push_frame
(
&
reg
);
while
(
frame
->
trylevel
!=
TRYLEVEL_END
&&
frame
->
trylevel
!=
trylevel
)
{
int
level
=
frame
->
trylevel
;
frame
->
trylevel
=
frame
->
scopetable
[
level
].
previousTryLevel
;
if
(
!
frame
->
scopetable
[
level
].
lpfnFilter
)
{
TRACE
(
"__try block cleanup level %d handler %p ebp %p
\n
"
,
level
,
frame
->
scopetable
[
level
].
lpfnHandler
,
ebp
);
call_unwind_func
(
frame
->
scopetable
[
level
].
lpfnHandler
,
ebp
);
}
}
__wine_pop_frame
(
&
reg
);
TRACE
(
"unwound OK
\n
"
);
}
static
void
msvcrt_local_unwind4
(
ULONG
*
cookie
,
MSVCRT_EXCEPTION_FRAME
*
frame
,
int
trylevel
,
void
*
ebp
)
{
EXCEPTION_REGISTRATION_RECORD
reg
;
const
SCOPETABLE_V4
*
scopetable
=
get_scopetable_v4
(
frame
,
*
cookie
);
TRACE
(
"(%p,%d,%d)
\n
"
,
frame
,
frame
->
trylevel
,
trylevel
);
/* Register a handler in case of a nested exception */
reg
.
Handler
=
MSVCRT_nested_handler
;
reg
.
Prev
=
NtCurrentTeb
()
->
Tib
.
ExceptionList
;
__wine_push_frame
(
&
reg
);
while
(
frame
->
trylevel
!=
-
2
&&
frame
->
trylevel
!=
trylevel
)
{
int
level
=
frame
->
trylevel
;
frame
->
trylevel
=
scopetable
->
entries
[
level
].
previousTryLevel
;
if
(
!
scopetable
->
entries
[
level
].
lpfnFilter
)
{
TRACE
(
"__try block cleanup level %d handler %p ebp %p
\n
"
,
level
,
scopetable
->
entries
[
level
].
lpfnHandler
,
ebp
);
call_unwind_func
(
scopetable
->
entries
[
level
].
lpfnHandler
,
ebp
);
}
}
__wine_pop_frame
(
&
reg
);
TRACE
(
"unwound OK
\n
"
);
}
/*******************************************************************
* _local_unwind2 (MSVCRT.@)
*/
void
CDECL
_local_unwind2
(
MSVCRT_EXCEPTION_FRAME
*
frame
,
int
trylevel
)
{
msvcrt_local_unwind2
(
frame
,
trylevel
,
&
frame
->
_ebp
);
}
/*******************************************************************
* _local_unwind4 (MSVCRT.@)
*/
void
CDECL
_local_unwind4
(
ULONG
*
cookie
,
MSVCRT_EXCEPTION_FRAME
*
frame
,
int
trylevel
)
{
msvcrt_local_unwind4
(
cookie
,
frame
,
trylevel
,
&
frame
->
_ebp
);
}
/*******************************************************************
* _global_unwind2 (MSVCRT.@)
*/
void
CDECL
_global_unwind2
(
EXCEPTION_REGISTRATION_RECORD
*
frame
)
{
TRACE
(
"(%p)
\n
"
,
frame
);
RtlUnwind
(
frame
,
0
,
0
,
0
);
}
/*********************************************************************
* _except_handler2 (MSVCRT.@)
*/
int
CDECL
_except_handler2
(
PEXCEPTION_RECORD
rec
,
EXCEPTION_REGISTRATION_RECORD
*
frame
,
PCONTEXT
context
,
EXCEPTION_REGISTRATION_RECORD
**
dispatcher
)
{
FIXME
(
"exception %x flags=%x at %p handler=%p %p %p stub
\n
"
,
rec
->
ExceptionCode
,
rec
->
ExceptionFlags
,
rec
->
ExceptionAddress
,
frame
->
Handler
,
context
,
dispatcher
);
return
ExceptionContinueSearch
;
}
/*********************************************************************
* _except_handler3 (MSVCRT.@)
*/
int
CDECL
_except_handler3
(
PEXCEPTION_RECORD
rec
,
MSVCRT_EXCEPTION_FRAME
*
frame
,
PCONTEXT
context
,
void
*
dispatcher
)
{
int
retval
,
trylevel
;
EXCEPTION_POINTERS
exceptPtrs
;
PSCOPETABLE
pScopeTable
;
TRACE
(
"exception %x flags=%x at %p handler=%p %p %p semi-stub
\n
"
,
rec
->
ExceptionCode
,
rec
->
ExceptionFlags
,
rec
->
ExceptionAddress
,
frame
->
handler
,
context
,
dispatcher
);
__asm__
__volatile__
(
"cld"
);
if
(
rec
->
ExceptionFlags
&
(
EH_UNWINDING
|
EH_EXIT_UNWIND
))
{
/* Unwinding the current frame */
msvcrt_local_unwind2
(
frame
,
TRYLEVEL_END
,
&
frame
->
_ebp
);
TRACE
(
"unwound current frame, returning ExceptionContinueSearch
\n
"
);
return
ExceptionContinueSearch
;
}
else
{
/* Hunting for handler */
exceptPtrs
.
ExceptionRecord
=
rec
;
exceptPtrs
.
ContextRecord
=
context
;
*
((
DWORD
*
)
frame
-
1
)
=
(
DWORD
)
&
exceptPtrs
;
trylevel
=
frame
->
trylevel
;
pScopeTable
=
frame
->
scopetable
;
while
(
trylevel
!=
TRYLEVEL_END
)
{
TRACE
(
"level %d prev %d filter %p
\n
"
,
trylevel
,
pScopeTable
[
trylevel
].
previousTryLevel
,
pScopeTable
[
trylevel
].
lpfnFilter
);
if
(
pScopeTable
[
trylevel
].
lpfnFilter
)
{
retval
=
call_filter
(
pScopeTable
[
trylevel
].
lpfnFilter
,
&
exceptPtrs
,
&
frame
->
_ebp
);
TRACE
(
"filter returned %s
\n
"
,
retval
==
EXCEPTION_CONTINUE_EXECUTION
?
"CONTINUE_EXECUTION"
:
retval
==
EXCEPTION_EXECUTE_HANDLER
?
"EXECUTE_HANDLER"
:
"CONTINUE_SEARCH"
);
if
(
retval
==
EXCEPTION_CONTINUE_EXECUTION
)
return
ExceptionContinueExecution
;
if
(
retval
==
EXCEPTION_EXECUTE_HANDLER
)
{
/* Unwind all higher frames, this one will handle the exception */
_global_unwind2
((
EXCEPTION_REGISTRATION_RECORD
*
)
frame
);
msvcrt_local_unwind2
(
frame
,
trylevel
,
&
frame
->
_ebp
);
/* Set our trylevel to the enclosing block, and call the __finally
* code, which won't return
*/
frame
->
trylevel
=
pScopeTable
[
trylevel
].
previousTryLevel
;
TRACE
(
"__finally block %p
\n
"
,
pScopeTable
[
trylevel
].
lpfnHandler
);
call_finally_block
(
pScopeTable
[
trylevel
].
lpfnHandler
,
&
frame
->
_ebp
);
ERR
(
"Returned from __finally block - expect crash!
\n
"
);
}
}
trylevel
=
pScopeTable
[
trylevel
].
previousTryLevel
;
}
}
TRACE
(
"reached TRYLEVEL_END, returning ExceptionContinueSearch
\n
"
);
return
ExceptionContinueSearch
;
}
/*********************************************************************
* _except_handler4_common (MSVCRT.@)
*/
int
CDECL
_except_handler4_common
(
ULONG
*
cookie
,
void
(
*
check_cookie
)(
void
),
EXCEPTION_RECORD
*
rec
,
MSVCRT_EXCEPTION_FRAME
*
frame
,
CONTEXT
*
context
,
EXCEPTION_REGISTRATION_RECORD
**
dispatcher
)
{
int
retval
,
trylevel
;
EXCEPTION_POINTERS
exceptPtrs
;
const
SCOPETABLE_V4
*
scope_table
=
get_scopetable_v4
(
frame
,
*
cookie
);
TRACE
(
"exception %x flags=%x at %p handler=%p %p %p cookie=%x scope table=%p cookies=%d/%x,%d/%x
\n
"
,
rec
->
ExceptionCode
,
rec
->
ExceptionFlags
,
rec
->
ExceptionAddress
,
frame
->
handler
,
context
,
dispatcher
,
*
cookie
,
scope_table
,
scope_table
->
gs_cookie_offset
,
scope_table
->
gs_cookie_xor
,
scope_table
->
eh_cookie_offset
,
scope_table
->
eh_cookie_xor
);
/* FIXME: no cookie validation yet */
if
(
rec
->
ExceptionFlags
&
(
EH_UNWINDING
|
EH_EXIT_UNWIND
))
{
/* Unwinding the current frame */
msvcrt_local_unwind4
(
cookie
,
frame
,
-
2
,
&
frame
->
_ebp
);
TRACE
(
"unwound current frame, returning ExceptionContinueSearch
\n
"
);
return
ExceptionContinueSearch
;
}
else
{
/* Hunting for handler */
exceptPtrs
.
ExceptionRecord
=
rec
;
exceptPtrs
.
ContextRecord
=
context
;
*
((
DWORD
*
)
frame
-
1
)
=
(
DWORD
)
&
exceptPtrs
;
trylevel
=
frame
->
trylevel
;
while
(
trylevel
!=
-
2
)
{
TRACE
(
"level %d prev %d filter %p
\n
"
,
trylevel
,
scope_table
->
entries
[
trylevel
].
previousTryLevel
,
scope_table
->
entries
[
trylevel
].
lpfnFilter
);
if
(
scope_table
->
entries
[
trylevel
].
lpfnFilter
)
{
retval
=
call_filter
(
scope_table
->
entries
[
trylevel
].
lpfnFilter
,
&
exceptPtrs
,
&
frame
->
_ebp
);
TRACE
(
"filter returned %s
\n
"
,
retval
==
EXCEPTION_CONTINUE_EXECUTION
?
"CONTINUE_EXECUTION"
:
retval
==
EXCEPTION_EXECUTE_HANDLER
?
"EXECUTE_HANDLER"
:
"CONTINUE_SEARCH"
);
if
(
retval
==
EXCEPTION_CONTINUE_EXECUTION
)
return
ExceptionContinueExecution
;
if
(
retval
==
EXCEPTION_EXECUTE_HANDLER
)
{
/* Unwind all higher frames, this one will handle the exception */
_global_unwind2
((
EXCEPTION_REGISTRATION_RECORD
*
)
frame
);
msvcrt_local_unwind4
(
cookie
,
frame
,
trylevel
,
&
frame
->
_ebp
);
/* Set our trylevel to the enclosing block, and call the __finally
* code, which won't return
*/
frame
->
trylevel
=
scope_table
->
entries
[
trylevel
].
previousTryLevel
;
TRACE
(
"__finally block %p
\n
"
,
scope_table
->
entries
[
trylevel
].
lpfnHandler
);
call_finally_block
(
scope_table
->
entries
[
trylevel
].
lpfnHandler
,
&
frame
->
_ebp
);
ERR
(
"Returned from __finally block - expect crash!
\n
"
);
}
}
trylevel
=
scope_table
->
entries
[
trylevel
].
previousTryLevel
;
}
}
TRACE
(
"reached -2, returning ExceptionContinueSearch
\n
"
);
return
ExceptionContinueSearch
;
}
/*
* setjmp/longjmp implementation
*/
#define MSVCRT_JMP_MAGIC 0x56433230
/* ID value for new jump structure */
typedef
void
(
__stdcall
*
MSVCRT_unwind_function
)(
const
struct
MSVCRT___JUMP_BUFFER
*
);
/* define an entrypoint for setjmp/setjmp3 that stores the registers in the jmp buf */
/* and then jumps to the C backend function */
#define DEFINE_SETJMP_ENTRYPOINT(name) \
__ASM_GLOBAL_FUNC( name, \
"movl 4(%esp),%ecx\n\t"
/* jmp_buf */
\
"movl %ebp,0(%ecx)\n\t"
/* jmp_buf.Ebp */
\
"movl %ebx,4(%ecx)\n\t"
/* jmp_buf.Ebx */
\
"movl %edi,8(%ecx)\n\t"
/* jmp_buf.Edi */
\
"movl %esi,12(%ecx)\n\t"
/* jmp_buf.Esi */
\
"movl %esp,16(%ecx)\n\t"
/* jmp_buf.Esp */
\
"movl 0(%esp),%eax\n\t" \
"movl %eax,20(%ecx)\n\t"
/* jmp_buf.Eip */
\
"jmp " __ASM_NAME("__regs_") # name )
/* restore the registers from the jmp buf upon longjmp */
extern
void
DECLSPEC_NORETURN
longjmp_set_regs
(
struct
MSVCRT___JUMP_BUFFER
*
jmp
,
int
retval
);
__ASM_GLOBAL_FUNC
(
longjmp_set_regs
,
"movl 4(%esp),%ecx
\n\t
"
/* jmp_buf */
"movl 8(%esp),%eax
\n\t
"
/* retval */
"movl 0(%ecx),%ebp
\n\t
"
/* jmp_buf.Ebp */
"movl 4(%ecx),%ebx
\n\t
"
/* jmp_buf.Ebx */
"movl 8(%ecx),%edi
\n\t
"
/* jmp_buf.Edi */
"movl 12(%ecx),%esi
\n\t
"
/* jmp_buf.Esi */
"movl 16(%ecx),%esp
\n\t
"
/* jmp_buf.Esp */
"addl $4,%esp
\n\t
"
/* get rid of return address */
"jmp *20(%ecx)
\n\t
"
/* jmp_buf.Eip */
)
/*
* The signatures of the setjmp/longjmp functions do not match that
* declared in the setjmp header so they don't follow the regular naming
* convention to avoid conflicts.
*/
/*******************************************************************
* _setjmp (MSVCRT.@)
*/
DEFINE_SETJMP_ENTRYPOINT
(
MSVCRT__setjmp
)
int
CDECL
__regs_MSVCRT__setjmp
(
struct
MSVCRT___JUMP_BUFFER
*
jmp
)
{
jmp
->
Registration
=
(
unsigned
long
)
NtCurrentTeb
()
->
Tib
.
ExceptionList
;
if
(
jmp
->
Registration
==
~
0UL
)
jmp
->
TryLevel
=
TRYLEVEL_END
;
else
jmp
->
TryLevel
=
((
MSVCRT_EXCEPTION_FRAME
*
)
jmp
->
Registration
)
->
trylevel
;
TRACE
(
"buf=%p ebx=%08lx esi=%08lx edi=%08lx ebp=%08lx esp=%08lx eip=%08lx frame=%08lx
\n
"
,
jmp
,
jmp
->
Ebx
,
jmp
->
Esi
,
jmp
->
Edi
,
jmp
->
Ebp
,
jmp
->
Esp
,
jmp
->
Eip
,
jmp
->
Registration
);
return
0
;
}
/*******************************************************************
* _setjmp3 (MSVCRT.@)
*/
DEFINE_SETJMP_ENTRYPOINT
(
MSVCRT__setjmp3
)
int
CDECL
__regs_MSVCRT__setjmp3
(
struct
MSVCRT___JUMP_BUFFER
*
jmp
,
int
nb_args
,
...)
{
jmp
->
Cookie
=
MSVCRT_JMP_MAGIC
;
jmp
->
UnwindFunc
=
0
;
jmp
->
Registration
=
(
unsigned
long
)
NtCurrentTeb
()
->
Tib
.
ExceptionList
;
if
(
jmp
->
Registration
==
~
0UL
)
{
jmp
->
TryLevel
=
TRYLEVEL_END
;
}
else
{
int
i
;
va_list
args
;
va_start
(
args
,
nb_args
);
if
(
nb_args
>
0
)
jmp
->
UnwindFunc
=
va_arg
(
args
,
unsigned
long
);
if
(
nb_args
>
1
)
jmp
->
TryLevel
=
va_arg
(
args
,
unsigned
long
);
else
jmp
->
TryLevel
=
((
MSVCRT_EXCEPTION_FRAME
*
)
jmp
->
Registration
)
->
trylevel
;
for
(
i
=
0
;
i
<
6
&&
i
<
nb_args
-
2
;
i
++
)
jmp
->
UnwindData
[
i
]
=
va_arg
(
args
,
unsigned
long
);
va_end
(
args
);
}
TRACE
(
"buf=%p ebx=%08lx esi=%08lx edi=%08lx ebp=%08lx esp=%08lx eip=%08lx frame=%08lx
\n
"
,
jmp
,
jmp
->
Ebx
,
jmp
->
Esi
,
jmp
->
Edi
,
jmp
->
Ebp
,
jmp
->
Esp
,
jmp
->
Eip
,
jmp
->
Registration
);
return
0
;
}
/*********************************************************************
* longjmp (MSVCRT.@)
*/
void
CDECL
MSVCRT_longjmp
(
struct
MSVCRT___JUMP_BUFFER
*
jmp
,
int
retval
)
{
unsigned
long
cur_frame
=
0
;
TRACE
(
"buf=%p ebx=%08lx esi=%08lx edi=%08lx ebp=%08lx esp=%08lx eip=%08lx frame=%08lx retval=%08x
\n
"
,
jmp
,
jmp
->
Ebx
,
jmp
->
Esi
,
jmp
->
Edi
,
jmp
->
Ebp
,
jmp
->
Esp
,
jmp
->
Eip
,
jmp
->
Registration
,
retval
);
cur_frame
=
(
unsigned
long
)
NtCurrentTeb
()
->
Tib
.
ExceptionList
;
TRACE
(
"cur_frame=%lx
\n
"
,
cur_frame
);
if
(
cur_frame
!=
jmp
->
Registration
)
_global_unwind2
((
EXCEPTION_REGISTRATION_RECORD
*
)
jmp
->
Registration
);
if
(
jmp
->
Registration
)
{
if
(
!
IsBadReadPtr
(
&
jmp
->
Cookie
,
sizeof
(
long
))
&&
jmp
->
Cookie
==
MSVCRT_JMP_MAGIC
&&
jmp
->
UnwindFunc
)
{
MSVCRT_unwind_function
unwind_func
;
unwind_func
=
(
MSVCRT_unwind_function
)
jmp
->
UnwindFunc
;
unwind_func
(
jmp
);
}
else
msvcrt_local_unwind2
((
MSVCRT_EXCEPTION_FRAME
*
)
jmp
->
Registration
,
jmp
->
TryLevel
,
(
void
*
)
jmp
->
Ebp
);
}
if
(
!
retval
)
retval
=
1
;
longjmp_set_regs
(
jmp
,
retval
);
}
/*********************************************************************
* _seh_longjmp_unwind (MSVCRT.@)
*/
void
__stdcall
_seh_longjmp_unwind
(
struct
MSVCRT___JUMP_BUFFER
*
jmp
)
{
msvcrt_local_unwind2
(
(
MSVCRT_EXCEPTION_FRAME
*
)
jmp
->
Registration
,
jmp
->
TryLevel
,
(
void
*
)
jmp
->
Ebp
);
}
/*********************************************************************
* _seh_longjmp_unwind4 (MSVCRT.@)
*/
void
__stdcall
_seh_longjmp_unwind4
(
struct
MSVCRT___JUMP_BUFFER
*
jmp
)
{
msvcrt_local_unwind4
(
(
void
*
)
jmp
->
Cookie
,
(
MSVCRT_EXCEPTION_FRAME
*
)
jmp
->
Registration
,
jmp
->
TryLevel
,
(
void
*
)
jmp
->
Ebp
);
}
#endif
/* __i386__ */
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