libwine: Added a wine_call_on_stack function.

This commit is contained in:
Alexandre Julliard 2008-03-26 15:38:00 +01:00
parent f6d871eecf
commit c9f0bea910
4 changed files with 68 additions and 1 deletions

View File

@ -66,6 +66,7 @@ extern void wine_init( int argc, char *argv[], char *error, int error_size );
/* portability */
extern void DECLSPEC_NORETURN wine_switch_to_stack( void (*func)(void *), void *arg, void *stack );
extern int wine_call_on_stack( int (*func)(void *), void *arg, void *stack );
extern void wine_set_pe_load_area( void *base, size_t size );
extern void wine_free_pe_load_area(void);

View File

@ -116,5 +116,69 @@ __ASM_GLOBAL_FUNC( wine_switch_to_stack,
"callq *%rax\n\t" /* call func */
"int $3")
#else
void DECLSPEC_NORETURN wine_switch_to_stack( void (*func)(void *), void *arg, void *stack )
{
wine_call_on_stack( (int (*)(void *))func, arg, stack );
abort();
}
#endif
/***********************************************************************
* wine_call_on_stack
*
* Switch to the specified stack to call the function and return.
*/
int wine_call_on_stack( int (*func)(void *), void *arg, void *stack );
#if defined(__i386__) && defined(__GNUC__)
__ASM_GLOBAL_FUNC( wine_call_on_stack,
"pushl %ebp\n\t"
"pushl %esi\n\t"
"movl 12(%esp),%ecx\n\t" /* func */
"movl 16(%esp),%edx\n\t" /* arg */
"movl 20(%esp),%esi\n\t" /* stack */
"andl $~15,%esi\n\t"
"subl $12,%esi\n\t"
"xchgl %esi,%esp\n\t"
"pushl %edx\n\t"
"xorl %ebp,%ebp\n\t"
"call *%ecx\n\t"
"movl %esi,%esp\n\t"
"popl %esi\n\t"
"popl %ebp\n\t"
"ret" )
#elif defined(__i386__) && defined(_MSC_VER)
__declspec(naked) int wine_call_on_stack( int (*func)(void *), void *arg, void *stack )
{
__asm push ebp;
__asm push esi;
__asm mov ecx, 12[esp];
__asm mov edx, 16[esp];
__asm mov esi, 20[esp];
__asm xchg esp, esi;
__asm push edx;
__asm xor ebp, ebp;
__asm call [ecx];
__asm mov esp, esi;
__asm pop esi;
__asm pop ebp
__asm ret;
}
#elif defined(__x86_64__) && defined(__GNUC__)
__ASM_GLOBAL_FUNC( wine_call_on_stack,
"pushq %rbp\n\t"
"pushq %rbx\n\t"
"movq %rsp,%rbx\n\t"
"movq %rdi,%rax\n\t" /* func */
"movq %rsi,%rdi\n\t" /* arg */
"andq $~15,%rdx\n\t" /* stack */
"movq %rdx,%rsp\n\t"
"xorq %rbp,%rbp\n\t"
"callq *%rax\n\t" /* call func */
"movq %rbx,%rsp\n\t"
"popq %rbx\n\t"
"popq %rbp\n\t"
"ret")
#else
#error You must implement wine_switch_to_stack for your platform
#endif

View File

@ -50,6 +50,7 @@ EXPORTS
vsnprintfW
vsprintfW
wine_anon_mmap
wine_call_on_stack
wine_casemap_lower
wine_casemap_upper
wine_compare_string
@ -65,7 +66,7 @@ EXPORTS
wine_dbgstr_an
wine_dbgstr_wn
wine_dlclose
wine_dll_enum_load_path;
wine_dll_enum_load_path
wine_dll_get_owner
wine_dll_load
wine_dll_load_main_exe

View File

@ -50,6 +50,7 @@ WINE_1.0
vsnprintfW;
vsprintfW;
wine_anon_mmap;
wine_call_on_stack;
wine_casemap_lower;
wine_casemap_upper;
wine_compare_string;