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:
Alexandre Julliard 2001-12-21 19:23:30 +00:00
parent 6add87e608
commit 1849f1eb15
4 changed files with 162 additions and 12 deletions

View File

@ -15,6 +15,9 @@
#include "thread.h"
#include "msvcrt.h"
#include "msvcrt/setjmp.h"
DEFAULT_DEBUG_CHANNEL(msvcrt);
typedef void (*MSVCRT_sig_handler_func)(void);
@ -227,32 +230,120 @@ int _abnormal_termination(void)
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.@)
*/
int MSVCRT__setjmp(LPDWORD* jmpbuf)
void _MSVCRT__setjmp(_JUMP_BUFFER *jmp, CONTEXT86* context)
{
FIXME(":(%p): stub\n",jmpbuf);
return 0;
TRACE("(%p)\n",jmp);
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.@)
*/
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);
return 0;
TRACE("(%p,%d)\n",jmp,nb_args);
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.@)
*/
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");
longjmp(env, val);
unsigned long cur_frame = 0;
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.@)

View File

@ -432,8 +432,8 @@ debug_channels (msvcrt)
@ stub _set_error_mode #(long)
@ stub _set_sbh_threshold #(long)
@ stub _seterrormode #(long)
@ cdecl _setjmp(ptr) MSVCRT__setjmp
@ cdecl _setjmp3(ptr long) MSVCRT__setjmp3
@ cdecl -register -noimport -i386 _setjmp(ptr) _MSVCRT__setjmp
@ cdecl -register -noimport -i386 _setjmp3(ptr long) _MSVCRT__setjmp3
@ stub _setmaxstdio #(long)
@ cdecl _setmbcp(long) _setmbcp
@ cdecl _setmode(long long) _setmode
@ -665,7 +665,7 @@ debug_channels (msvcrt)
@ cdecl localtime(ptr) localtime
@ forward -noimport log ntdll.log
@ 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 mblen(ptr long) MSVCRT_mblen
@ forward -noimport mbstowcs ntdll.mbstowcs

View File

@ -65,6 +65,7 @@ INSTALLED_INCLUDES = \
msvcrt/mbstring.h \
msvcrt/process.h \
msvcrt/search.h \
msvcrt/setjmp.h \
msvcrt/share.h \
msvcrt/stddef.h \
msvcrt/stdio.h \

58
include/msvcrt/setjmp.h Normal file
View File

@ -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 */