Generate stub functions directly in assembly.
This commit is contained in:
parent
867ae269d4
commit
3fa5678ea9
|
@ -177,6 +177,7 @@ extern void dump_bytes( FILE *outfile, const unsigned char *data, int len,
|
|||
extern int remove_stdcall_decoration( char *name );
|
||||
extern DLLSPEC *alloc_dll_spec(void);
|
||||
extern void free_dll_spec( DLLSPEC *spec );
|
||||
extern int has_stubs( const DLLSPEC *spec );
|
||||
extern const char *make_c_identifier( const char *str );
|
||||
extern unsigned int get_alignment(unsigned int align);
|
||||
extern unsigned int get_page_size(void);
|
||||
|
|
|
@ -454,18 +454,6 @@ static void add_import_func( struct import *imp, ORDDEF *func )
|
|||
if (imp->delay) total_delayed++;
|
||||
}
|
||||
|
||||
/* check if the spec file exports any stubs */
|
||||
static int has_stubs( const DLLSPEC *spec )
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < spec->nb_entry_points; i++)
|
||||
{
|
||||
ORDDEF *odp = &spec->entry_points[i];
|
||||
if (odp->type == TYPE_STUB) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get the default entry point for a given spec file */
|
||||
static const char *get_default_entry_point( const DLLSPEC *spec )
|
||||
{
|
||||
|
|
|
@ -368,6 +368,7 @@ static int parse_spec_stub( ORDDEF *odp, DLLSPEC *spec )
|
|||
{
|
||||
odp->u.func.arg_types[0] = '\0';
|
||||
odp->link_name = xstrdup("");
|
||||
odp->flags |= FLAG_I386; /* don't bother generating stubs for Winelib */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -270,38 +270,62 @@ static void output_exports( FILE *outfile, DLLSPEC *spec )
|
|||
|
||||
|
||||
/*******************************************************************
|
||||
* output_stub_funcs
|
||||
* output_stubs
|
||||
*
|
||||
* Output the functions for stub entry points
|
||||
*/
|
||||
static void output_stub_funcs( FILE *outfile, DLLSPEC *spec )
|
||||
static void output_stubs( FILE *outfile, DLLSPEC *spec )
|
||||
{
|
||||
int i;
|
||||
const char *name, *exp_name;
|
||||
int i, pos;
|
||||
|
||||
for (i = 0; i < spec->nb_entry_points; i++)
|
||||
if (!has_stubs( spec )) return;
|
||||
|
||||
fprintf( outfile, "asm(\".text\\n\"\n" );
|
||||
|
||||
for (i = pos = 0; i < spec->nb_entry_points; i++)
|
||||
{
|
||||
ORDDEF *odp = &spec->entry_points[i];
|
||||
if (odp->type != TYPE_STUB) continue;
|
||||
fprintf( outfile, "#ifdef __GNUC__\n" );
|
||||
fprintf( outfile, "extern void __wine_spec_unimplemented_stub( const char *module, const char *func ) __attribute__((noreturn));\n" );
|
||||
fprintf( outfile, "#else\n" );
|
||||
fprintf( outfile, "extern void __wine_spec_unimplemented_stub( const char *module, const char *func );\n" );
|
||||
fprintf( outfile, "#endif\n\n" );
|
||||
break;
|
||||
|
||||
name = make_internal_name( odp, spec, "stub" );
|
||||
exp_name = odp->name ? odp->name : odp->export_name;
|
||||
fprintf( outfile, " \"\\t.align %d\\n\"\n", get_alignment(4) );
|
||||
fprintf( outfile, " \"\\t%s\\n\"\n", func_declaration(name) );
|
||||
fprintf( outfile, " \"%s:\\n\"\n", asm_name(name) );
|
||||
fprintf( outfile, " \"\\tcall .L__wine_stub_getpc_%d\\n\"\n", i );
|
||||
fprintf( outfile, " \".L__wine_stub_getpc_%d:\\n\"\n", i );
|
||||
fprintf( outfile, " \"\\tpopl %%eax\\n\"\n" );
|
||||
if (exp_name)
|
||||
{
|
||||
fprintf( outfile, " \"\\tleal .L__wine_stub_strings+%d-.L__wine_stub_getpc_%d(%%eax),%%ecx\\n\"\n",
|
||||
pos, i );
|
||||
fprintf( outfile, " \"\\tpushl %%ecx\\n\"\n" );
|
||||
pos += strlen(exp_name) + 1;
|
||||
}
|
||||
else
|
||||
fprintf( outfile, " \"\\tpushl $%d\\n\"\n", odp->ordinal );
|
||||
fprintf( outfile, " \"\\tleal %s-.L__wine_stub_getpc_%d(%%eax),%%ecx\\n\"\n",
|
||||
asm_name("__wine_spec_file_name"), i );
|
||||
fprintf( outfile, " \"\\tpushl %%ecx\\n\"\n" );
|
||||
fprintf( outfile, " \"\\tcall %s\\n\"\n", asm_name("__wine_spec_unimplemented_stub") );
|
||||
fprintf( outfile, " \"\\t%s\\n\"\n", func_size(name) );
|
||||
}
|
||||
|
||||
for (i = 0; i < spec->nb_entry_points; i++)
|
||||
if (pos)
|
||||
{
|
||||
const ORDDEF *odp = &spec->entry_points[i];
|
||||
if (odp->type != TYPE_STUB) continue;
|
||||
fprintf( outfile, "void %s(void) ", make_internal_name( odp, spec, "stub" ) );
|
||||
if (odp->name)
|
||||
fprintf( outfile, "{ __wine_spec_unimplemented_stub(__wine_spec_file_name, \"%s\"); }\n", odp->name );
|
||||
else if (odp->export_name)
|
||||
fprintf( outfile, "{ __wine_spec_unimplemented_stub(__wine_spec_file_name, \"%s\"); }\n", odp->export_name );
|
||||
else
|
||||
fprintf( outfile, "{ __wine_spec_unimplemented_stub(__wine_spec_file_name, \"%d\"); }\n", odp->ordinal );
|
||||
fprintf( outfile, " \".L__wine_stub_strings:\\n\"\n" );
|
||||
for (i = 0; i < spec->nb_entry_points; i++)
|
||||
{
|
||||
ORDDEF *odp = &spec->entry_points[i];
|
||||
if (odp->type != TYPE_STUB) continue;
|
||||
exp_name = odp->name ? odp->name : odp->export_name;
|
||||
if (exp_name)
|
||||
fprintf( outfile, " \"\\t%s \\\"%s\\\"\\n\"\n", get_asm_string_keyword(), exp_name );
|
||||
}
|
||||
}
|
||||
|
||||
fprintf( outfile, ");\n" );
|
||||
}
|
||||
|
||||
|
||||
|
@ -434,8 +458,6 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
|
|||
|
||||
fprintf( outfile, "const char __wine_spec_file_name[] = \"%s\";\n", spec->file_name );
|
||||
|
||||
output_stub_funcs( outfile, spec );
|
||||
|
||||
/* Output the resources */
|
||||
|
||||
resources_size = output_resources( outfile, spec );
|
||||
|
@ -542,6 +564,7 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
|
|||
fprintf( outfile, " \"\\t.long 0,0\\n\"\n" ); /* DataDirectory[15] */
|
||||
fprintf( outfile, ");\n" );
|
||||
|
||||
output_stubs( outfile, spec );
|
||||
output_exports( outfile, spec );
|
||||
output_imports( outfile, spec );
|
||||
output_dll_init( outfile, "__wine_spec_init_ctor", NULL );
|
||||
|
|
|
@ -296,6 +296,23 @@ void free_dll_spec( DLLSPEC *spec )
|
|||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* has_stubs
|
||||
*
|
||||
* Check if the spec file exports any stubs
|
||||
*/
|
||||
int has_stubs( const DLLSPEC *spec )
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < spec->nb_entry_points; i++)
|
||||
{
|
||||
ORDDEF *odp = &spec->entry_points[i];
|
||||
if (odp->type == TYPE_STUB) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* make_c_identifier
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue