From 07f736bc3db3ed83f989204065993e161aeea9fc Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 4 Nov 2002 22:50:24 +0000 Subject: [PATCH] Hack to detect register functions automatically so that relay debug also works for functions using the DEFINE_REGS_ENTRY_POINT macros. --- relay32/relay386.c | 24 ++++++++++++++++++++++-- tools/winebuild/spec32.c | 10 +++------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/relay32/relay386.c b/relay32/relay386.c index 92d4b5647f0..1024bedd2ea 100644 --- a/relay32/relay386.c +++ b/relay32/relay386.c @@ -463,7 +463,7 @@ void WINAPI RELAY_DoCallFrom32Regs( CONTEXT86 *context ) BYTE *relay_addr = *((BYTE **)context->Esp - 1); DEBUG_ENTRY_POINT *relay = (DEBUG_ENTRY_POINT *)(relay_addr - 5); - WORD nb_args = (relay->args & ~0x8000) / sizeof(int); + WORD nb_args = relay->args / sizeof(int); /* remove extra stuff from the stack */ context->Eip = stack32_pop(context); @@ -523,6 +523,26 @@ __ASM_GLOBAL_FUNC( RELAY_CallFrom32Regs, "call " __ASM_NAME("__wine_call_from_32_regs") "\n\t" ".long " __ASM_NAME("RELAY_DoCallFrom32Regs") ",0" ); + +/* check whether the function at addr starts with a call to __wine_call_from_32_regs */ +static BOOL is_register_entry_point( const BYTE *addr ) +{ + extern void __wine_call_from_32_regs(); + int *offset; + void *ptr; + + if (*addr != 0xe8) return FALSE; /* not a call */ + /* check if call target is __wine_call_from_32_regs */ + offset = (int *)(addr + 1); + if (*offset == (char *)__wine_call_from_32_regs - (char *)(offset + 1)) return TRUE; + /* now check if call target is an import table jump to __wine_call_from_32_regs */ + addr = (BYTE *)(offset + 1) + *offset; + if (addr[0] != 0xff || addr[1] != 0x25) return FALSE; /* not an indirect jmp */ + ptr = *(void **)(addr + 2); /* get indirect jmp target address */ + return (*(char **)ptr == (char *)__wine_call_from_32_regs); +} + + /*********************************************************************** * RELAY_SetupDLL * @@ -560,7 +580,7 @@ void RELAY_SetupDLL( const char *module ) if (on) { debug->call = 0xe8; /* call relative */ - if (debug->args & 0x8000) /* register func */ + if (is_register_entry_point( debug->orig )) debug->callfrom32 = (char *)RELAY_CallFrom32Regs - (char *)&debug->ret; else debug->callfrom32 = (char *)RELAY_CallFrom32 - (char *)&debug->ret; diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c index c6ac6330023..ae51b5dfd85 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c @@ -271,23 +271,19 @@ static int output_exports( FILE *outfile, int nr_exports ) name = odp->link_name; args = strlen(odp->u.func.arg_types) * sizeof(int); - if (odp->flags & FLAG_REGISTER) - { - name = make_internal_name( odp, "regs" ); - args |= 0x8000; - } + if (odp->flags & FLAG_REGISTER) name = make_internal_name( odp, "regs" ); switch(odp->type) { case TYPE_STDCALL: fprintf( outfile, " \"\\tjmp " __ASM_NAME("%s") "\\n\"\n", name ); - fprintf( outfile, " \"\\tret $0x%04x\\n\"\n", args ); + fprintf( outfile, " \"\\tret $%d\\n\"\n", args ); fprintf( outfile, " \"\\t.long " __ASM_NAME("%s") ",0x%08x\\n\"\n", name, mask ); break; case TYPE_CDECL: fprintf( outfile, " \"\\tjmp " __ASM_NAME("%s") "\\n\"\n", name ); fprintf( outfile, " \"\\tret\\n\"\n" ); - fprintf( outfile, " \"\\t.short 0x%04x\\n\"\n", args ); + fprintf( outfile, " \"\\t.short %d\\n\"\n", args ); fprintf( outfile, " \"\\t.long " __ASM_NAME("%s") ",0x%08x\\n\"\n", name, mask ); break; default: