Authors: Jon Griffiths <jon_p_griffiths@yahoo.com>, François Gouget <fgouget@codeweavers.com>, Alexandre Julliard <julliard@codeweavers.com>
Implement setjmp/setjmp3 and longjmp.
This commit is contained in:
parent
6add87e608
commit
1849f1eb15
|
@ -15,6 +15,9 @@
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "msvcrt.h"
|
#include "msvcrt.h"
|
||||||
|
|
||||||
|
#include "msvcrt/setjmp.h"
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_DEBUG_CHANNEL(msvcrt);
|
DEFAULT_DEBUG_CHANNEL(msvcrt);
|
||||||
|
|
||||||
typedef void (*MSVCRT_sig_handler_func)(void);
|
typedef void (*MSVCRT_sig_handler_func)(void);
|
||||||
|
@ -227,32 +230,120 @@ int _abnormal_termination(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* setjmp/longjmp implementation
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __i386__
|
||||||
|
#define MSVCRT_JMP_MAGIC 0x56433230 /* ID value for new jump structure */
|
||||||
|
typedef void (*MSVCRT_unwind_function)(const void*);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.@)
|
* _setjmp (MSVCRT.@)
|
||||||
*/
|
*/
|
||||||
int MSVCRT__setjmp(LPDWORD* jmpbuf)
|
void _MSVCRT__setjmp(_JUMP_BUFFER *jmp, CONTEXT86* context)
|
||||||
{
|
{
|
||||||
FIXME(":(%p): stub\n",jmpbuf);
|
TRACE("(%p)\n",jmp);
|
||||||
return 0;
|
jmp->Ebp = context->Ebp;
|
||||||
|
jmp->Ebx = context->Ebx;
|
||||||
|
jmp->Edi = context->Edi;
|
||||||
|
jmp->Esi = context->Esi;
|
||||||
|
jmp->Esp = context->Esp;
|
||||||
|
jmp->Eip = context->Eip;
|
||||||
|
jmp->Registration = (unsigned long)NtCurrentTeb()->except;
|
||||||
|
if (jmp->Registration == TRYLEVEL_END)
|
||||||
|
jmp->TryLevel = TRYLEVEL_END;
|
||||||
|
else
|
||||||
|
jmp->TryLevel = ((MSVCRT_EXCEPTION_FRAME*)jmp->Registration)->trylevel;
|
||||||
|
TRACE("returning 0\n");
|
||||||
|
context->Eax=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
* _setjmp3 (MSVCRT.@)
|
* _setjmp3 (MSVCRT.@)
|
||||||
*/
|
*/
|
||||||
int __cdecl MSVCRT__setjmp3(LPDWORD *jmpbuf, int x)
|
void _MSVCRT__setjmp3(_JUMP_BUFFER *jmp, int nb_args, CONTEXT86* context)
|
||||||
{
|
{
|
||||||
FIXME(":(%p %x): stub\n",jmpbuf,x);
|
TRACE("(%p,%d)\n",jmp,nb_args);
|
||||||
return 0;
|
jmp->Ebp = context->Ebp;
|
||||||
|
jmp->Ebx = context->Ebx;
|
||||||
|
jmp->Edi = context->Edi;
|
||||||
|
jmp->Esi = context->Esi;
|
||||||
|
jmp->Esp = context->Esp;
|
||||||
|
jmp->Eip = context->Eip;
|
||||||
|
jmp->Cookie = MSVCRT_JMP_MAGIC;
|
||||||
|
jmp->UnwindFunc = 0;
|
||||||
|
jmp->Registration = (unsigned long)NtCurrentTeb()->except;
|
||||||
|
if (jmp->Registration == TRYLEVEL_END)
|
||||||
|
{
|
||||||
|
jmp->TryLevel = TRYLEVEL_END;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
void **args = ((void**)context->Esp)+2;
|
||||||
|
|
||||||
|
if (nb_args > 0) jmp->UnwindFunc = (unsigned long)*args++;
|
||||||
|
if (nb_args > 1) jmp->TryLevel = (unsigned long)*args++;
|
||||||
|
else jmp->TryLevel = ((MSVCRT_EXCEPTION_FRAME*)jmp->Registration)->trylevel;
|
||||||
|
if (nb_args > 2)
|
||||||
|
{
|
||||||
|
size_t size = (nb_args - 2) * sizeof(DWORD);
|
||||||
|
memcpy( jmp->UnwindData, args, min( size, sizeof(jmp->UnwindData) ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TRACE("returning 0\n");
|
||||||
|
context->Eax = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* longjmp (MSVCRT.@)
|
* longjmp (MSVCRT.@)
|
||||||
*/
|
*/
|
||||||
void MSVCRT_longjmp(jmp_buf env, int val)
|
void _MSVCRT_longjmp(_JUMP_BUFFER *jmp, int retval, CONTEXT86* context)
|
||||||
{
|
{
|
||||||
FIXME("MSVCRT_longjmp semistub, expect crash\n");
|
unsigned long cur_frame = 0;
|
||||||
longjmp(env, val);
|
|
||||||
|
TRACE("(%p,%d)\n", jmp, retval);
|
||||||
|
|
||||||
|
cur_frame=(unsigned long)NtCurrentTeb()->except;
|
||||||
|
TRACE("cur_frame=%lx\n",cur_frame);
|
||||||
|
|
||||||
|
if (cur_frame != jmp->Registration)
|
||||||
|
_global_unwind2((PEXCEPTION_FRAME)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
|
||||||
|
_local_unwind2((MSVCRT_EXCEPTION_FRAME*)jmp->Registration,
|
||||||
|
jmp->TryLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!retval)
|
||||||
|
retval = 1;
|
||||||
|
|
||||||
|
TRACE("Jump to %lx returning %d\n",jmp->Eip,retval);
|
||||||
|
context->Ebp = jmp->Ebp;
|
||||||
|
context->Ebx = jmp->Ebx;
|
||||||
|
context->Edi = jmp->Edi;
|
||||||
|
context->Esi = jmp->Esi;
|
||||||
|
context->Esp = jmp->Esp;
|
||||||
|
context->Eip = jmp->Eip;
|
||||||
|
context->Eax = retval;
|
||||||
}
|
}
|
||||||
|
#endif /* i386 */
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* signal (MSVCRT.@)
|
* signal (MSVCRT.@)
|
||||||
|
|
|
@ -432,8 +432,8 @@ debug_channels (msvcrt)
|
||||||
@ stub _set_error_mode #(long)
|
@ stub _set_error_mode #(long)
|
||||||
@ stub _set_sbh_threshold #(long)
|
@ stub _set_sbh_threshold #(long)
|
||||||
@ stub _seterrormode #(long)
|
@ stub _seterrormode #(long)
|
||||||
@ cdecl _setjmp(ptr) MSVCRT__setjmp
|
@ cdecl -register -noimport -i386 _setjmp(ptr) _MSVCRT__setjmp
|
||||||
@ cdecl _setjmp3(ptr long) MSVCRT__setjmp3
|
@ cdecl -register -noimport -i386 _setjmp3(ptr long) _MSVCRT__setjmp3
|
||||||
@ stub _setmaxstdio #(long)
|
@ stub _setmaxstdio #(long)
|
||||||
@ cdecl _setmbcp(long) _setmbcp
|
@ cdecl _setmbcp(long) _setmbcp
|
||||||
@ cdecl _setmode(long long) _setmode
|
@ cdecl _setmode(long long) _setmode
|
||||||
|
@ -665,7 +665,7 @@ debug_channels (msvcrt)
|
||||||
@ cdecl localtime(ptr) localtime
|
@ cdecl localtime(ptr) localtime
|
||||||
@ forward -noimport log ntdll.log
|
@ forward -noimport log ntdll.log
|
||||||
@ cdecl log10(double) log10
|
@ cdecl log10(double) log10
|
||||||
@ cdecl longjmp(long long) MSVCRT_longjmp
|
@ cdecl -register -noimport -i386 longjmp(ptr long) _MSVCRT_longjmp
|
||||||
@ cdecl malloc(long) MSVCRT_malloc
|
@ cdecl malloc(long) MSVCRT_malloc
|
||||||
@ cdecl mblen(ptr long) MSVCRT_mblen
|
@ cdecl mblen(ptr long) MSVCRT_mblen
|
||||||
@ forward -noimport mbstowcs ntdll.mbstowcs
|
@ forward -noimport mbstowcs ntdll.mbstowcs
|
||||||
|
|
|
@ -65,6 +65,7 @@ INSTALLED_INCLUDES = \
|
||||||
msvcrt/mbstring.h \
|
msvcrt/mbstring.h \
|
||||||
msvcrt/process.h \
|
msvcrt/process.h \
|
||||||
msvcrt/search.h \
|
msvcrt/search.h \
|
||||||
|
msvcrt/setjmp.h \
|
||||||
msvcrt/share.h \
|
msvcrt/share.h \
|
||||||
msvcrt/stddef.h \
|
msvcrt/stddef.h \
|
||||||
msvcrt/stdio.h \
|
msvcrt/stdio.h \
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Setjmp/Longjmp definitions
|
||||||
|
*
|
||||||
|
* Copyright 2001 Francois Gouget.
|
||||||
|
*/
|
||||||
|
#ifndef __WINE_SETJMP_H
|
||||||
|
#define __WINE_SETJMP_H
|
||||||
|
#define __WINE_USE_MSVCRT
|
||||||
|
|
||||||
|
#ifdef USE_MSVCRT_PREFIX
|
||||||
|
#define MSVCRT(x) MSVCRT_##x
|
||||||
|
#else
|
||||||
|
#define MSVCRT(x) x
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __i386__
|
||||||
|
|
||||||
|
#define _JBLEN 16
|
||||||
|
#define _JBTYPE int
|
||||||
|
|
||||||
|
typedef struct __JUMP_BUFFER
|
||||||
|
{
|
||||||
|
unsigned long Ebp;
|
||||||
|
unsigned long Ebx;
|
||||||
|
unsigned long Edi;
|
||||||
|
unsigned long Esi;
|
||||||
|
unsigned long Esp;
|
||||||
|
unsigned long Eip;
|
||||||
|
unsigned long Registration;
|
||||||
|
unsigned long TryLevel;
|
||||||
|
/* Start of new struct members */
|
||||||
|
unsigned long Cookie;
|
||||||
|
unsigned long UnwindFunc;
|
||||||
|
unsigned long UnwindData[6];
|
||||||
|
} _JUMP_BUFFER;
|
||||||
|
|
||||||
|
#endif /* __i386__ */
|
||||||
|
|
||||||
|
typedef _JBTYPE MSVCRT(jmp_buf)[_JBLEN];
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int MSVCRT(_setjmp)( MSVCRT(jmp_buf));
|
||||||
|
int MSVCRT(longjmp)( MSVCRT(jmp_buf),int);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef USE_MSVCRT_PREFIX
|
||||||
|
#define setjmp _setjmp
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __WINE_SETJMP_H */
|
Loading…
Reference in New Issue