Module: wine Branch: master Commit: c9f0bea910eb7d2a9ec9b395ef19c89e493e63cf URL: http://source.winehq.org/git/wine.git/?a=commit;h=c9f0bea910eb7d2a9ec9b395ef...
Author: Alexandre Julliard julliard@winehq.org Date: Wed Mar 26 15:38:00 2008 +0100
libwine: Added a wine_call_on_stack function.
---
include/wine/library.h | 1 + libs/wine/port.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ libs/wine/wine.def | 3 +- libs/wine/wine.map | 1 + 4 files changed, 68 insertions(+), 1 deletions(-)
diff --git a/include/wine/library.h b/include/wine/library.h index f00919e..2c3b7bb 100644 --- a/include/wine/library.h +++ b/include/wine/library.h @@ -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);
diff --git a/libs/wine/port.c b/libs/wine/port.c index 838c3ff..e2f7b0c 100644 --- a/libs/wine/port.c +++ b/libs/wine/port.c @@ -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 diff --git a/libs/wine/wine.def b/libs/wine/wine.def index 462a619..6304113 100644 --- a/libs/wine/wine.def +++ b/libs/wine/wine.def @@ -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 diff --git a/libs/wine/wine.map b/libs/wine/wine.map index 47e58ce..ef8d823 100644 --- a/libs/wine/wine.map +++ b/libs/wine/wine.map @@ -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;