Hack to detect register functions automatically so that relay debug

also works for functions using the DEFINE_REGS_ENTRY_POINT macros.
This commit is contained in:
Alexandre Julliard 2002-11-04 22:50:24 +00:00
parent d427f731f0
commit 07f736bc3d
2 changed files with 25 additions and 9 deletions

View File

@ -463,7 +463,7 @@ void WINAPI RELAY_DoCallFrom32Regs( CONTEXT86 *context )
BYTE *relay_addr = *((BYTE **)context->Esp - 1); BYTE *relay_addr = *((BYTE **)context->Esp - 1);
DEBUG_ENTRY_POINT *relay = (DEBUG_ENTRY_POINT *)(relay_addr - 5); 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 */ /* remove extra stuff from the stack */
context->Eip = stack32_pop(context); context->Eip = stack32_pop(context);
@ -523,6 +523,26 @@ __ASM_GLOBAL_FUNC( RELAY_CallFrom32Regs,
"call " __ASM_NAME("__wine_call_from_32_regs") "\n\t" "call " __ASM_NAME("__wine_call_from_32_regs") "\n\t"
".long " __ASM_NAME("RELAY_DoCallFrom32Regs") ",0" ); ".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 * RELAY_SetupDLL
* *
@ -560,7 +580,7 @@ void RELAY_SetupDLL( const char *module )
if (on) if (on)
{ {
debug->call = 0xe8; /* call relative */ 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; debug->callfrom32 = (char *)RELAY_CallFrom32Regs - (char *)&debug->ret;
else else
debug->callfrom32 = (char *)RELAY_CallFrom32 - (char *)&debug->ret; debug->callfrom32 = (char *)RELAY_CallFrom32 - (char *)&debug->ret;

View File

@ -271,23 +271,19 @@ static int output_exports( FILE *outfile, int nr_exports )
name = odp->link_name; name = odp->link_name;
args = strlen(odp->u.func.arg_types) * sizeof(int); args = strlen(odp->u.func.arg_types) * sizeof(int);
if (odp->flags & FLAG_REGISTER) if (odp->flags & FLAG_REGISTER) name = make_internal_name( odp, "regs" );
{
name = make_internal_name( odp, "regs" );
args |= 0x8000;
}
switch(odp->type) switch(odp->type)
{ {
case TYPE_STDCALL: case TYPE_STDCALL:
fprintf( outfile, " \"\\tjmp " __ASM_NAME("%s") "\\n\"\n", name ); 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 ); fprintf( outfile, " \"\\t.long " __ASM_NAME("%s") ",0x%08x\\n\"\n", name, mask );
break; break;
case TYPE_CDECL: case TYPE_CDECL:
fprintf( outfile, " \"\\tjmp " __ASM_NAME("%s") "\\n\"\n", name ); fprintf( outfile, " \"\\tjmp " __ASM_NAME("%s") "\\n\"\n", name );
fprintf( outfile, " \"\\tret\\n\"\n" ); 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 ); fprintf( outfile, " \"\\t.long " __ASM_NAME("%s") ",0x%08x\\n\"\n", name, mask );
break; break;
default: default: