winebuild: Added output() function to properly deal with write errors.
This commit is contained in:
parent
05001b1ca8
commit
715804999e
|
@ -154,11 +154,13 @@ extern void error( const char *msg, ... )
|
|||
__attribute__ ((__format__ (__printf__, 1, 2)));
|
||||
extern void warning( const char *msg, ... )
|
||||
__attribute__ ((__format__ (__printf__, 1, 2)));
|
||||
extern int output( const char *format, ... )
|
||||
__attribute__ ((__format__ (__printf__, 1, 2)));
|
||||
extern char *get_temp_file_name( const char *prefix, const char *suffix );
|
||||
extern void output_standard_file_header( FILE *outfile );
|
||||
extern void output_standard_file_header(void);
|
||||
extern FILE *open_input_file( const char *srcdir, const char *name );
|
||||
extern void close_input_file( FILE *file );
|
||||
extern void dump_bytes( FILE *outfile, const void *buffer, unsigned int size );
|
||||
extern void dump_bytes( const void *buffer, unsigned int size );
|
||||
extern int remove_stdcall_decoration( char *name );
|
||||
extern void assemble_file( const char *src_file, const char *obj_file );
|
||||
extern DLLSPEC *alloc_dll_spec(void);
|
||||
|
@ -176,8 +178,8 @@ extern const char *get_asm_string_keyword(void);
|
|||
extern const char *get_asm_short_keyword(void);
|
||||
extern const char *get_asm_rodata_section(void);
|
||||
extern const char *get_asm_string_section(void);
|
||||
extern void output_function_size( FILE *outfile, const char *name );
|
||||
extern void output_gnu_stack_note( FILE *outfile );
|
||||
extern void output_function_size( const char *name );
|
||||
extern void output_gnu_stack_note(void);
|
||||
|
||||
extern void add_import_dll( const char *name, const char *filename );
|
||||
extern void add_delayed_import( const char *name );
|
||||
|
@ -187,20 +189,20 @@ extern void read_undef_symbols( DLLSPEC *spec, char **argv );
|
|||
extern int resolve_imports( DLLSPEC *spec );
|
||||
extern int has_imports(void);
|
||||
extern int has_relays( DLLSPEC *spec );
|
||||
extern void output_get_pc_thunk( FILE *outfile );
|
||||
extern void output_stubs( FILE *outfile, DLLSPEC *spec );
|
||||
extern void output_imports( FILE *outfile, DLLSPEC *spec );
|
||||
extern void output_get_pc_thunk(void);
|
||||
extern void output_stubs( DLLSPEC *spec );
|
||||
extern void output_imports( DLLSPEC *spec );
|
||||
extern int load_res32_file( const char *name, DLLSPEC *spec );
|
||||
extern void output_resources( FILE *outfile, DLLSPEC *spec );
|
||||
extern void output_resources( DLLSPEC *spec );
|
||||
extern void load_res16_file( const char *name, DLLSPEC *spec );
|
||||
extern void output_res16_data( FILE *outfile, DLLSPEC *spec );
|
||||
extern void output_res16_directory( FILE *outfile, DLLSPEC *spec, const char *header_name );
|
||||
extern void output_res16_data( DLLSPEC *spec );
|
||||
extern void output_res16_directory( DLLSPEC *spec, const char *header_name );
|
||||
|
||||
extern void BuildRelays16( FILE *outfile );
|
||||
extern void BuildRelays32( FILE *outfile );
|
||||
extern void BuildSpec16File( FILE *outfile, DLLSPEC *spec );
|
||||
extern void BuildSpec32File( FILE *outfile, DLLSPEC *spec );
|
||||
extern void BuildDef32File( FILE *outfile, DLLSPEC *spec );
|
||||
extern void BuildRelays16(void);
|
||||
extern void BuildRelays32(void);
|
||||
extern void BuildSpec16File( DLLSPEC *spec );
|
||||
extern void BuildSpec32File( DLLSPEC *spec );
|
||||
extern void BuildDef32File( DLLSPEC *spec );
|
||||
|
||||
extern int parse_spec_file( FILE *file, DLLSPEC *spec );
|
||||
extern int parse_def_file( FILE *file, DLLSPEC *spec );
|
||||
|
@ -219,6 +221,7 @@ extern int link_ext_symbols;
|
|||
|
||||
extern char *input_file_name;
|
||||
extern char *spec_file_name;
|
||||
extern FILE *output_file;
|
||||
extern const char *output_file_name;
|
||||
extern char **lib_path;
|
||||
|
||||
|
|
|
@ -592,99 +592,99 @@ int resolve_imports( DLLSPEC *spec )
|
|||
}
|
||||
|
||||
/* output the get_pc thunk if needed */
|
||||
void output_get_pc_thunk( FILE *outfile )
|
||||
void output_get_pc_thunk(void)
|
||||
{
|
||||
if (target_cpu != CPU_x86) return;
|
||||
if (!UsePIC) return;
|
||||
fprintf( outfile, "\n\t.text\n" );
|
||||
fprintf( outfile, "\t.align %d\n", get_alignment(4) );
|
||||
fprintf( outfile, "\t%s\n", func_declaration("__wine_spec_get_pc_thunk_eax") );
|
||||
fprintf( outfile, "%s:\n", asm_name("__wine_spec_get_pc_thunk_eax") );
|
||||
fprintf( outfile, "\tpopl %%eax\n" );
|
||||
fprintf( outfile, "\tpushl %%eax\n" );
|
||||
fprintf( outfile, "\tret\n" );
|
||||
output_function_size( outfile, "__wine_spec_get_pc_thunk_eax" );
|
||||
output( "\n\t.text\n" );
|
||||
output( "\t.align %d\n", get_alignment(4) );
|
||||
output( "\t%s\n", func_declaration("__wine_spec_get_pc_thunk_eax") );
|
||||
output( "%s:\n", asm_name("__wine_spec_get_pc_thunk_eax") );
|
||||
output( "\tpopl %%eax\n" );
|
||||
output( "\tpushl %%eax\n" );
|
||||
output( "\tret\n" );
|
||||
output_function_size( "__wine_spec_get_pc_thunk_eax" );
|
||||
}
|
||||
|
||||
/* output a single import thunk */
|
||||
static void output_import_thunk( FILE *outfile, const char *name, const char *table, int pos )
|
||||
static void output_import_thunk( const char *name, const char *table, int pos )
|
||||
{
|
||||
fprintf( outfile, "\n\t.align %d\n", get_alignment(4) );
|
||||
fprintf( outfile, "\t%s\n", func_declaration(name) );
|
||||
fprintf( outfile, "%s\n", asm_globl(name) );
|
||||
output( "\n\t.align %d\n", get_alignment(4) );
|
||||
output( "\t%s\n", func_declaration(name) );
|
||||
output( "%s\n", asm_globl(name) );
|
||||
|
||||
switch(target_cpu)
|
||||
{
|
||||
case CPU_x86:
|
||||
if (!UsePIC)
|
||||
{
|
||||
fprintf( outfile, "\tjmp *(%s+%d)\n", table, pos );
|
||||
output( "\tjmp *(%s+%d)\n", table, pos );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
|
||||
fprintf( outfile, "1:\tjmp *%s+%d-1b(%%eax)\n", table, pos );
|
||||
output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
|
||||
output( "1:\tjmp *%s+%d-1b(%%eax)\n", table, pos );
|
||||
}
|
||||
break;
|
||||
case CPU_x86_64:
|
||||
fprintf( outfile, "\tjmpq *%s+%d(%%rip)\n", table, pos );
|
||||
output( "\tjmpq *%s+%d(%%rip)\n", table, pos );
|
||||
break;
|
||||
case CPU_SPARC:
|
||||
if ( !UsePIC )
|
||||
{
|
||||
fprintf( outfile, "\tsethi %%hi(%s+%d), %%g1\n", table, pos );
|
||||
fprintf( outfile, "\tld [%%g1+%%lo(%s+%d)], %%g1\n", table, pos );
|
||||
fprintf( outfile, "\tjmp %%g1\n" );
|
||||
fprintf( outfile, "\tnop\n" );
|
||||
output( "\tsethi %%hi(%s+%d), %%g1\n", table, pos );
|
||||
output( "\tld [%%g1+%%lo(%s+%d)], %%g1\n", table, pos );
|
||||
output( "\tjmp %%g1\n" );
|
||||
output( "\tnop\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Hmpf. Stupid sparc assembler always interprets global variable
|
||||
names as GOT offsets, so we have to do it the long way ... */
|
||||
fprintf( outfile, "\tsave %%sp, -96, %%sp\n" );
|
||||
fprintf( outfile, "0:\tcall 1f\n" );
|
||||
fprintf( outfile, "\tnop\n" );
|
||||
fprintf( outfile, "1:\tsethi %%hi(%s+%d-0b), %%g1\n", table, pos );
|
||||
fprintf( outfile, "\tor %%g1, %%lo(%s+%d-0b), %%g1\n", table, pos );
|
||||
fprintf( outfile, "\tld [%%g1+%%o7], %%g1\n" );
|
||||
fprintf( outfile, "\tjmp %%g1\n" );
|
||||
fprintf( outfile, "\trestore\n" );
|
||||
output( "\tsave %%sp, -96, %%sp\n" );
|
||||
output( "0:\tcall 1f\n" );
|
||||
output( "\tnop\n" );
|
||||
output( "1:\tsethi %%hi(%s+%d-0b), %%g1\n", table, pos );
|
||||
output( "\tor %%g1, %%lo(%s+%d-0b), %%g1\n", table, pos );
|
||||
output( "\tld [%%g1+%%o7], %%g1\n" );
|
||||
output( "\tjmp %%g1\n" );
|
||||
output( "\trestore\n" );
|
||||
}
|
||||
break;
|
||||
case CPU_ALPHA:
|
||||
fprintf( outfile, "\tlda $0,%s\n", table );
|
||||
fprintf( outfile, "\tlda $0,%d($0)\n", pos );
|
||||
fprintf( outfile, "\tjmp $31,($0)\n" );
|
||||
output( "\tlda $0,%s\n", table );
|
||||
output( "\tlda $0,%d($0)\n", pos );
|
||||
output( "\tjmp $31,($0)\n" );
|
||||
break;
|
||||
case CPU_POWERPC:
|
||||
fprintf( outfile, "\taddi %s, %s, -0x4\n", ppc_reg(1), ppc_reg(1) );
|
||||
fprintf( outfile, "\tstw %s, 0(%s)\n", ppc_reg(9), ppc_reg(1) );
|
||||
fprintf( outfile, "\taddi %s, %s, -0x4\n", ppc_reg(1), ppc_reg(1) );
|
||||
fprintf( outfile, "\tstw %s, 0(%s)\n", ppc_reg(8), ppc_reg(1) );
|
||||
fprintf( outfile, "\taddi %s, %s, -0x4\n", ppc_reg(1), ppc_reg(1) );
|
||||
fprintf( outfile, "\tstw %s, 0(%s)\n", ppc_reg(7), ppc_reg(1) );
|
||||
output( "\taddi %s, %s, -0x4\n", ppc_reg(1), ppc_reg(1) );
|
||||
output( "\tstw %s, 0(%s)\n", ppc_reg(9), ppc_reg(1) );
|
||||
output( "\taddi %s, %s, -0x4\n", ppc_reg(1), ppc_reg(1) );
|
||||
output( "\tstw %s, 0(%s)\n", ppc_reg(8), ppc_reg(1) );
|
||||
output( "\taddi %s, %s, -0x4\n", ppc_reg(1), ppc_reg(1) );
|
||||
output( "\tstw %s, 0(%s)\n", ppc_reg(7), ppc_reg(1) );
|
||||
if (target_platform == PLATFORM_APPLE)
|
||||
{
|
||||
fprintf( outfile, "\tlis %s, ha16(%s+%d)\n", ppc_reg(9), table, pos );
|
||||
fprintf( outfile, "\tla %s, lo16(%s+%d)(%s)\n", ppc_reg(8), table, pos, ppc_reg(9) );
|
||||
output( "\tlis %s, ha16(%s+%d)\n", ppc_reg(9), table, pos );
|
||||
output( "\tla %s, lo16(%s+%d)(%s)\n", ppc_reg(8), table, pos, ppc_reg(9) );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( outfile, "\tlis %s, (%s+%d)@h\n", ppc_reg(9), table, pos );
|
||||
fprintf( outfile, "\tla %s, (%s+%d)@l(%s)\n", ppc_reg(8), table, pos, ppc_reg(9) );
|
||||
output( "\tlis %s, (%s+%d)@h\n", ppc_reg(9), table, pos );
|
||||
output( "\tla %s, (%s+%d)@l(%s)\n", ppc_reg(8), table, pos, ppc_reg(9) );
|
||||
}
|
||||
fprintf( outfile, "\tlwz %s, 0(%s)\n", ppc_reg(7), ppc_reg(8) );
|
||||
fprintf( outfile, "\tmtctr %s\n", ppc_reg(7) );
|
||||
fprintf( outfile, "\tlwz %s, 0(%s)\n", ppc_reg(7), ppc_reg(1) );
|
||||
fprintf( outfile, "\taddi %s, %s, 0x4\n", ppc_reg(1), ppc_reg(1) );
|
||||
fprintf( outfile, "\tlwz %s, 0(%s)\n", ppc_reg(8), ppc_reg(1) );
|
||||
fprintf( outfile, "\taddi %s, %s, 0x4\n", ppc_reg(1), ppc_reg(1) );
|
||||
fprintf( outfile, "\tlwz %s, 0(%s)\n", ppc_reg(9), ppc_reg(1) );
|
||||
fprintf( outfile, "\taddi %s, %s, 0x4\n", ppc_reg(1), ppc_reg(1) );
|
||||
fprintf( outfile, "\tbctr\n" );
|
||||
output( "\tlwz %s, 0(%s)\n", ppc_reg(7), ppc_reg(8) );
|
||||
output( "\tmtctr %s\n", ppc_reg(7) );
|
||||
output( "\tlwz %s, 0(%s)\n", ppc_reg(7), ppc_reg(1) );
|
||||
output( "\taddi %s, %s, 0x4\n", ppc_reg(1), ppc_reg(1) );
|
||||
output( "\tlwz %s, 0(%s)\n", ppc_reg(8), ppc_reg(1) );
|
||||
output( "\taddi %s, %s, 0x4\n", ppc_reg(1), ppc_reg(1) );
|
||||
output( "\tlwz %s, 0(%s)\n", ppc_reg(9), ppc_reg(1) );
|
||||
output( "\taddi %s, %s, 0x4\n", ppc_reg(1), ppc_reg(1) );
|
||||
output( "\tbctr\n" );
|
||||
break;
|
||||
}
|
||||
output_function_size( outfile, name );
|
||||
output_function_size( name );
|
||||
}
|
||||
|
||||
/* check if we need an import directory */
|
||||
|
@ -694,7 +694,7 @@ int has_imports(void)
|
|||
}
|
||||
|
||||
/* output the import table of a Win32 module */
|
||||
static void output_immediate_imports( FILE *outfile )
|
||||
static void output_immediate_imports(void)
|
||||
{
|
||||
int i, j;
|
||||
const char *dll_name;
|
||||
|
@ -703,10 +703,10 @@ static void output_immediate_imports( FILE *outfile )
|
|||
|
||||
/* main import header */
|
||||
|
||||
fprintf( outfile, "\n/* import table */\n" );
|
||||
fprintf( outfile, "\n\t.data\n" );
|
||||
fprintf( outfile, "\t.align %d\n", get_alignment(4) );
|
||||
fprintf( outfile, ".L__wine_spec_imports:\n" );
|
||||
output( "\n/* import table */\n" );
|
||||
output( "\n\t.data\n" );
|
||||
output( "\t.align %d\n", get_alignment(4) );
|
||||
output( ".L__wine_spec_imports:\n" );
|
||||
|
||||
/* list of dlls */
|
||||
|
||||
|
@ -714,23 +714,23 @@ static void output_immediate_imports( FILE *outfile )
|
|||
{
|
||||
if (dll_imports[i]->delay) continue;
|
||||
dll_name = make_c_identifier( dll_imports[i]->spec->file_name );
|
||||
fprintf( outfile, "\t.long 0\n" ); /* OriginalFirstThunk */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* TimeDateStamp */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* ForwarderChain */
|
||||
fprintf( outfile, "\t.long .L__wine_spec_import_name_%s-.L__wine_spec_rva_base\n", /* Name */
|
||||
output( "\t.long 0\n" ); /* OriginalFirstThunk */
|
||||
output( "\t.long 0\n" ); /* TimeDateStamp */
|
||||
output( "\t.long 0\n" ); /* ForwarderChain */
|
||||
output( "\t.long .L__wine_spec_import_name_%s-.L__wine_spec_rva_base\n", /* Name */
|
||||
dll_name );
|
||||
fprintf( outfile, "\t.long .L__wine_spec_import_data_ptrs+%d-.L__wine_spec_rva_base\n", /* FirstThunk */
|
||||
output( "\t.long .L__wine_spec_import_data_ptrs+%d-.L__wine_spec_rva_base\n", /* FirstThunk */
|
||||
j * get_ptr_size() );
|
||||
j += dll_imports[i]->nb_imports + 1;
|
||||
}
|
||||
fprintf( outfile, "\t.long 0\n" ); /* OriginalFirstThunk */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* TimeDateStamp */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* ForwarderChain */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* Name */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* FirstThunk */
|
||||
output( "\t.long 0\n" ); /* OriginalFirstThunk */
|
||||
output( "\t.long 0\n" ); /* TimeDateStamp */
|
||||
output( "\t.long 0\n" ); /* ForwarderChain */
|
||||
output( "\t.long 0\n" ); /* Name */
|
||||
output( "\t.long 0\n" ); /* FirstThunk */
|
||||
|
||||
fprintf( outfile, "\n\t.align %d\n", get_alignment(get_ptr_size()) );
|
||||
fprintf( outfile, ".L__wine_spec_import_data_ptrs:\n" );
|
||||
output( "\n\t.align %d\n", get_alignment(get_ptr_size()) );
|
||||
output( ".L__wine_spec_import_data_ptrs:\n" );
|
||||
for (i = 0; i < nb_imports; i++)
|
||||
{
|
||||
if (dll_imports[i]->delay) continue;
|
||||
|
@ -739,19 +739,19 @@ static void output_immediate_imports( FILE *outfile )
|
|||
{
|
||||
ORDDEF *odp = dll_imports[i]->imports[j];
|
||||
if (!(odp->flags & FLAG_NONAME))
|
||||
fprintf( outfile, "\t%s .L__wine_spec_import_data_%s_%s-.L__wine_spec_rva_base\n",
|
||||
output( "\t%s .L__wine_spec_import_data_%s_%s-.L__wine_spec_rva_base\n",
|
||||
get_asm_ptr_keyword(), dll_name, odp->name );
|
||||
else
|
||||
{
|
||||
if (get_ptr_size() == 8)
|
||||
fprintf( outfile, "\t.quad 0x800000000000%04x\n", odp->ordinal );
|
||||
output( "\t.quad 0x800000000000%04x\n", odp->ordinal );
|
||||
else
|
||||
fprintf( outfile, "\t.long 0x8000%04x\n", odp->ordinal );
|
||||
output( "\t.long 0x8000%04x\n", odp->ordinal );
|
||||
}
|
||||
}
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );
|
||||
output( "\t%s 0\n", get_asm_ptr_keyword() );
|
||||
}
|
||||
fprintf( outfile, ".L__wine_spec_imports_end:\n" );
|
||||
output( ".L__wine_spec_imports_end:\n" );
|
||||
|
||||
for (i = 0; i < nb_imports; i++)
|
||||
{
|
||||
|
@ -762,10 +762,10 @@ static void output_immediate_imports( FILE *outfile )
|
|||
ORDDEF *odp = dll_imports[i]->imports[j];
|
||||
if (!(odp->flags & FLAG_NONAME))
|
||||
{
|
||||
fprintf( outfile, "\t.align %d\n", get_alignment(2) );
|
||||
fprintf( outfile, ".L__wine_spec_import_data_%s_%s:\n", dll_name, odp->name );
|
||||
fprintf( outfile, "\t%s %d\n", get_asm_short_keyword(), odp->ordinal );
|
||||
fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), odp->name );
|
||||
output( "\t.align %d\n", get_alignment(2) );
|
||||
output( ".L__wine_spec_import_data_%s_%s:\n", dll_name, odp->name );
|
||||
output( "\t%s %d\n", get_asm_short_keyword(), odp->ordinal );
|
||||
output( "\t%s \"%s\"\n", get_asm_string_keyword(), odp->name );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -774,13 +774,13 @@ static void output_immediate_imports( FILE *outfile )
|
|||
{
|
||||
if (dll_imports[i]->delay) continue;
|
||||
dll_name = make_c_identifier( dll_imports[i]->spec->file_name );
|
||||
fprintf( outfile, ".L__wine_spec_import_name_%s:\n\t%s \"%s\"\n",
|
||||
output( ".L__wine_spec_import_name_%s:\n\t%s \"%s\"\n",
|
||||
dll_name, get_asm_string_keyword(), dll_imports[i]->spec->file_name );
|
||||
}
|
||||
}
|
||||
|
||||
/* output the import thunks of a Win32 module */
|
||||
static void output_immediate_import_thunks( FILE *outfile )
|
||||
static void output_immediate_import_thunks(void)
|
||||
{
|
||||
int i, j, pos;
|
||||
int nb_imm = nb_imports - nb_delayed;
|
||||
|
@ -788,10 +788,10 @@ static void output_immediate_import_thunks( FILE *outfile )
|
|||
|
||||
if (!nb_imm) return;
|
||||
|
||||
fprintf( outfile, "\n/* immediate import thunks */\n\n" );
|
||||
fprintf( outfile, "\t.text\n" );
|
||||
fprintf( outfile, "\t.align %d\n", get_alignment(8) );
|
||||
fprintf( outfile, "%s:\n", asm_name(import_thunks));
|
||||
output( "\n/* immediate import thunks */\n\n" );
|
||||
output( "\t.text\n" );
|
||||
output( "\t.align %d\n", get_alignment(8) );
|
||||
output( "%s:\n", asm_name(import_thunks));
|
||||
|
||||
for (i = pos = 0; i < nb_imports; i++)
|
||||
{
|
||||
|
@ -799,56 +799,56 @@ static void output_immediate_import_thunks( FILE *outfile )
|
|||
for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += get_ptr_size())
|
||||
{
|
||||
ORDDEF *odp = dll_imports[i]->imports[j];
|
||||
output_import_thunk( outfile, odp->name ? odp->name : odp->export_name,
|
||||
output_import_thunk( odp->name ? odp->name : odp->export_name,
|
||||
".L__wine_spec_import_data_ptrs", pos );
|
||||
}
|
||||
pos += get_ptr_size();
|
||||
}
|
||||
output_function_size( outfile, import_thunks );
|
||||
output_function_size( import_thunks );
|
||||
}
|
||||
|
||||
/* output the delayed import table of a Win32 module */
|
||||
static void output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
|
||||
static void output_delayed_imports( const DLLSPEC *spec )
|
||||
{
|
||||
int i, j, mod;
|
||||
|
||||
if (!nb_delayed) return;
|
||||
|
||||
fprintf( outfile, "\n/* delayed imports */\n\n" );
|
||||
fprintf( outfile, "\t.data\n" );
|
||||
fprintf( outfile, "\t.align %d\n", get_alignment(get_ptr_size()) );
|
||||
fprintf( outfile, "%s\n", asm_globl("__wine_spec_delay_imports") );
|
||||
output( "\n/* delayed imports */\n\n" );
|
||||
output( "\t.data\n" );
|
||||
output( "\t.align %d\n", get_alignment(get_ptr_size()) );
|
||||
output( "%s\n", asm_globl("__wine_spec_delay_imports") );
|
||||
|
||||
/* list of dlls */
|
||||
|
||||
for (i = j = mod = 0; i < nb_imports; i++)
|
||||
{
|
||||
if (!dll_imports[i]->delay) continue;
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() ); /* grAttrs */
|
||||
fprintf( outfile, "\t%s .L__wine_delay_name_%d\n", /* szName */
|
||||
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* grAttrs */
|
||||
output( "\t%s .L__wine_delay_name_%d\n", /* szName */
|
||||
get_asm_ptr_keyword(), i );
|
||||
fprintf( outfile, "\t%s .L__wine_delay_modules+%d\n", /* phmod */
|
||||
output( "\t%s .L__wine_delay_modules+%d\n", /* phmod */
|
||||
get_asm_ptr_keyword(), mod * get_ptr_size() );
|
||||
fprintf( outfile, "\t%s .L__wine_delay_IAT+%d\n", /* pIAT */
|
||||
output( "\t%s .L__wine_delay_IAT+%d\n", /* pIAT */
|
||||
get_asm_ptr_keyword(), j * get_ptr_size() );
|
||||
fprintf( outfile, "\t%s .L__wine_delay_INT+%d\n", /* pINT */
|
||||
output( "\t%s .L__wine_delay_INT+%d\n", /* pINT */
|
||||
get_asm_ptr_keyword(), j * get_ptr_size() );
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() ); /* pBoundIAT */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() ); /* pUnloadIAT */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() ); /* dwTimeStamp */
|
||||
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pBoundIAT */
|
||||
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pUnloadIAT */
|
||||
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* dwTimeStamp */
|
||||
j += dll_imports[i]->nb_imports;
|
||||
mod++;
|
||||
}
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() ); /* grAttrs */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() ); /* szName */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() ); /* phmod */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() ); /* pIAT */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() ); /* pINT */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() ); /* pBoundIAT */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() ); /* pUnloadIAT */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() ); /* dwTimeStamp */
|
||||
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* grAttrs */
|
||||
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* szName */
|
||||
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* phmod */
|
||||
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pIAT */
|
||||
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pINT */
|
||||
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pBoundIAT */
|
||||
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pUnloadIAT */
|
||||
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* dwTimeStamp */
|
||||
|
||||
fprintf( outfile, "\n.L__wine_delay_IAT:\n" );
|
||||
output( "\n.L__wine_delay_IAT:\n" );
|
||||
for (i = 0; i < nb_imports; i++)
|
||||
{
|
||||
if (!dll_imports[i]->delay) continue;
|
||||
|
@ -856,12 +856,12 @@ static void output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
|
|||
{
|
||||
ORDDEF *odp = dll_imports[i]->imports[j];
|
||||
const char *name = odp->name ? odp->name : odp->export_name;
|
||||
fprintf( outfile, "\t%s .L__wine_delay_imp_%d_%s\n",
|
||||
output( "\t%s .L__wine_delay_imp_%d_%s\n",
|
||||
get_asm_ptr_keyword(), i, name );
|
||||
}
|
||||
}
|
||||
|
||||
fprintf( outfile, "\n.L__wine_delay_INT:\n" );
|
||||
output( "\n.L__wine_delay_INT:\n" );
|
||||
for (i = 0; i < nb_imports; i++)
|
||||
{
|
||||
if (!dll_imports[i]->delay) continue;
|
||||
|
@ -869,24 +869,24 @@ static void output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
|
|||
{
|
||||
ORDDEF *odp = dll_imports[i]->imports[j];
|
||||
if (!odp->name)
|
||||
fprintf( outfile, "\t%s %d\n", get_asm_ptr_keyword(), odp->ordinal );
|
||||
output( "\t%s %d\n", get_asm_ptr_keyword(), odp->ordinal );
|
||||
else
|
||||
fprintf( outfile, "\t%s .L__wine_delay_data_%d_%s\n",
|
||||
output( "\t%s .L__wine_delay_data_%d_%s\n",
|
||||
get_asm_ptr_keyword(), i, odp->name );
|
||||
}
|
||||
}
|
||||
|
||||
fprintf( outfile, "\n.L__wine_delay_modules:\n" );
|
||||
output( "\n.L__wine_delay_modules:\n" );
|
||||
for (i = 0; i < nb_imports; i++)
|
||||
{
|
||||
if (dll_imports[i]->delay) fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );
|
||||
if (dll_imports[i]->delay) output( "\t%s 0\n", get_asm_ptr_keyword() );
|
||||
}
|
||||
|
||||
for (i = 0; i < nb_imports; i++)
|
||||
{
|
||||
if (!dll_imports[i]->delay) continue;
|
||||
fprintf( outfile, ".L__wine_delay_name_%d:\n", i );
|
||||
fprintf( outfile, "\t%s \"%s\"\n",
|
||||
output( ".L__wine_delay_name_%d:\n", i );
|
||||
output( "\t%s \"%s\"\n",
|
||||
get_asm_string_keyword(), dll_imports[i]->spec->file_name );
|
||||
}
|
||||
|
||||
|
@ -897,15 +897,15 @@ static void output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
|
|||
{
|
||||
ORDDEF *odp = dll_imports[i]->imports[j];
|
||||
if (!odp->name) continue;
|
||||
fprintf( outfile, ".L__wine_delay_data_%d_%s:\n", i, odp->name );
|
||||
fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), odp->name );
|
||||
output( ".L__wine_delay_data_%d_%s:\n", i, odp->name );
|
||||
output( "\t%s \"%s\"\n", get_asm_string_keyword(), odp->name );
|
||||
}
|
||||
}
|
||||
output_function_size( outfile, "__wine_spec_delay_imports" );
|
||||
output_function_size( "__wine_spec_delay_imports" );
|
||||
}
|
||||
|
||||
/* output the delayed import thunks of a Win32 module */
|
||||
static void output_delayed_import_thunks( FILE *outfile, const DLLSPEC *spec )
|
||||
static void output_delayed_import_thunks( const DLLSPEC *spec )
|
||||
{
|
||||
int i, idx, j, pos, extra_stack_storage = 0;
|
||||
static const char delayed_import_loaders[] = "__wine_spec_delayed_import_loaders";
|
||||
|
@ -913,105 +913,105 @@ static void output_delayed_import_thunks( FILE *outfile, const DLLSPEC *spec )
|
|||
|
||||
if (!nb_delayed) return;
|
||||
|
||||
fprintf( outfile, "\n/* delayed import thunks */\n\n" );
|
||||
fprintf( outfile, "\t.text\n" );
|
||||
fprintf( outfile, "\t.align %d\n", get_alignment(8) );
|
||||
fprintf( outfile, "%s:\n", asm_name(delayed_import_loaders));
|
||||
fprintf( outfile, "\t%s\n", func_declaration("__wine_delay_load_asm") );
|
||||
fprintf( outfile, "%s:\n", asm_name("__wine_delay_load_asm") );
|
||||
output( "\n/* delayed import thunks */\n\n" );
|
||||
output( "\t.text\n" );
|
||||
output( "\t.align %d\n", get_alignment(8) );
|
||||
output( "%s:\n", asm_name(delayed_import_loaders));
|
||||
output( "\t%s\n", func_declaration("__wine_delay_load_asm") );
|
||||
output( "%s:\n", asm_name("__wine_delay_load_asm") );
|
||||
switch(target_cpu)
|
||||
{
|
||||
case CPU_x86:
|
||||
fprintf( outfile, "\tpushl %%ecx\n" );
|
||||
fprintf( outfile, "\tpushl %%edx\n" );
|
||||
fprintf( outfile, "\tpushl %%eax\n" );
|
||||
fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_delay_load") );
|
||||
fprintf( outfile, "\tpopl %%edx\n" );
|
||||
fprintf( outfile, "\tpopl %%ecx\n" );
|
||||
fprintf( outfile, "\tjmp *%%eax\n" );
|
||||
output( "\tpushl %%ecx\n" );
|
||||
output( "\tpushl %%edx\n" );
|
||||
output( "\tpushl %%eax\n" );
|
||||
output( "\tcall %s\n", asm_name("__wine_spec_delay_load") );
|
||||
output( "\tpopl %%edx\n" );
|
||||
output( "\tpopl %%ecx\n" );
|
||||
output( "\tjmp *%%eax\n" );
|
||||
break;
|
||||
case CPU_x86_64:
|
||||
fprintf( outfile, "\tpushq %%rdi\n" );
|
||||
fprintf( outfile, "\tpushq %%rsi\n" );
|
||||
fprintf( outfile, "\tpushq %%rdx\n" );
|
||||
fprintf( outfile, "\tpushq %%rcx\n" );
|
||||
fprintf( outfile, "\tpushq %%r8\n" );
|
||||
fprintf( outfile, "\tpushq %%r9\n" );
|
||||
fprintf( outfile, "\tsubq $8,%%rsp\n" );
|
||||
fprintf( outfile, "\tmovq %%r11,%%rdi\n" );
|
||||
fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_delay_load") );
|
||||
fprintf( outfile, "\taddq $8,%%rsp\n" );
|
||||
fprintf( outfile, "\tpopq %%r9\n" );
|
||||
fprintf( outfile, "\tpopq %%r8\n" );
|
||||
fprintf( outfile, "\tpopq %%rcx\n" );
|
||||
fprintf( outfile, "\tpopq %%rdx\n" );
|
||||
fprintf( outfile, "\tpopq %%rsi\n" );
|
||||
fprintf( outfile, "\tpopq %%rdi\n" );
|
||||
fprintf( outfile, "\tjmp *%%rax\n" );
|
||||
output( "\tpushq %%rdi\n" );
|
||||
output( "\tpushq %%rsi\n" );
|
||||
output( "\tpushq %%rdx\n" );
|
||||
output( "\tpushq %%rcx\n" );
|
||||
output( "\tpushq %%r8\n" );
|
||||
output( "\tpushq %%r9\n" );
|
||||
output( "\tsubq $8,%%rsp\n" );
|
||||
output( "\tmovq %%r11,%%rdi\n" );
|
||||
output( "\tcall %s\n", asm_name("__wine_spec_delay_load") );
|
||||
output( "\taddq $8,%%rsp\n" );
|
||||
output( "\tpopq %%r9\n" );
|
||||
output( "\tpopq %%r8\n" );
|
||||
output( "\tpopq %%rcx\n" );
|
||||
output( "\tpopq %%rdx\n" );
|
||||
output( "\tpopq %%rsi\n" );
|
||||
output( "\tpopq %%rdi\n" );
|
||||
output( "\tjmp *%%rax\n" );
|
||||
break;
|
||||
case CPU_SPARC:
|
||||
fprintf( outfile, "\tsave %%sp, -96, %%sp\n" );
|
||||
fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_delay_load") );
|
||||
fprintf( outfile, "\tmov %%g1, %%o0\n" );
|
||||
fprintf( outfile, "\tjmp %%o0\n" );
|
||||
fprintf( outfile, "\trestore\n" );
|
||||
output( "\tsave %%sp, -96, %%sp\n" );
|
||||
output( "\tcall %s\n", asm_name("__wine_spec_delay_load") );
|
||||
output( "\tmov %%g1, %%o0\n" );
|
||||
output( "\tjmp %%o0\n" );
|
||||
output( "\trestore\n" );
|
||||
break;
|
||||
case CPU_ALPHA:
|
||||
fprintf( outfile, "\tjsr $26,%s\n", asm_name("__wine_spec_delay_load") );
|
||||
fprintf( outfile, "\tjmp $31,($0)\n" );
|
||||
output( "\tjsr $26,%s\n", asm_name("__wine_spec_delay_load") );
|
||||
output( "\tjmp $31,($0)\n" );
|
||||
break;
|
||||
case CPU_POWERPC:
|
||||
if (target_platform == PLATFORM_APPLE) extra_stack_storage = 56;
|
||||
|
||||
/* Save all callee saved registers into a stackframe. */
|
||||
fprintf( outfile, "\tstwu %s, -%d(%s)\n",ppc_reg(1), 48+extra_stack_storage, ppc_reg(1));
|
||||
fprintf( outfile, "\tstw %s, %d(%s)\n", ppc_reg(3), 4+extra_stack_storage, ppc_reg(1));
|
||||
fprintf( outfile, "\tstw %s, %d(%s)\n", ppc_reg(4), 8+extra_stack_storage, ppc_reg(1));
|
||||
fprintf( outfile, "\tstw %s, %d(%s)\n", ppc_reg(5), 12+extra_stack_storage, ppc_reg(1));
|
||||
fprintf( outfile, "\tstw %s, %d(%s)\n", ppc_reg(6), 16+extra_stack_storage, ppc_reg(1));
|
||||
fprintf( outfile, "\tstw %s, %d(%s)\n", ppc_reg(7), 20+extra_stack_storage, ppc_reg(1));
|
||||
fprintf( outfile, "\tstw %s, %d(%s)\n", ppc_reg(8), 24+extra_stack_storage, ppc_reg(1));
|
||||
fprintf( outfile, "\tstw %s, %d(%s)\n", ppc_reg(9), 28+extra_stack_storage, ppc_reg(1));
|
||||
fprintf( outfile, "\tstw %s, %d(%s)\n", ppc_reg(10),32+extra_stack_storage, ppc_reg(1));
|
||||
fprintf( outfile, "\tstw %s, %d(%s)\n", ppc_reg(11),36+extra_stack_storage, ppc_reg(1));
|
||||
fprintf( outfile, "\tstw %s, %d(%s)\n", ppc_reg(12),40+extra_stack_storage, ppc_reg(1));
|
||||
output( "\tstwu %s, -%d(%s)\n",ppc_reg(1), 48+extra_stack_storage, ppc_reg(1));
|
||||
output( "\tstw %s, %d(%s)\n", ppc_reg(3), 4+extra_stack_storage, ppc_reg(1));
|
||||
output( "\tstw %s, %d(%s)\n", ppc_reg(4), 8+extra_stack_storage, ppc_reg(1));
|
||||
output( "\tstw %s, %d(%s)\n", ppc_reg(5), 12+extra_stack_storage, ppc_reg(1));
|
||||
output( "\tstw %s, %d(%s)\n", ppc_reg(6), 16+extra_stack_storage, ppc_reg(1));
|
||||
output( "\tstw %s, %d(%s)\n", ppc_reg(7), 20+extra_stack_storage, ppc_reg(1));
|
||||
output( "\tstw %s, %d(%s)\n", ppc_reg(8), 24+extra_stack_storage, ppc_reg(1));
|
||||
output( "\tstw %s, %d(%s)\n", ppc_reg(9), 28+extra_stack_storage, ppc_reg(1));
|
||||
output( "\tstw %s, %d(%s)\n", ppc_reg(10),32+extra_stack_storage, ppc_reg(1));
|
||||
output( "\tstw %s, %d(%s)\n", ppc_reg(11),36+extra_stack_storage, ppc_reg(1));
|
||||
output( "\tstw %s, %d(%s)\n", ppc_reg(12),40+extra_stack_storage, ppc_reg(1));
|
||||
|
||||
/* r0 -> r3 (arg1) */
|
||||
fprintf( outfile, "\tmr %s, %s\n", ppc_reg(3), ppc_reg(0));
|
||||
output( "\tmr %s, %s\n", ppc_reg(3), ppc_reg(0));
|
||||
|
||||
/* save return address */
|
||||
fprintf( outfile, "\tmflr %s\n", ppc_reg(0));
|
||||
fprintf( outfile, "\tstw %s, %d(%s)\n", ppc_reg(0), 44+extra_stack_storage, ppc_reg(1));
|
||||
output( "\tmflr %s\n", ppc_reg(0));
|
||||
output( "\tstw %s, %d(%s)\n", ppc_reg(0), 44+extra_stack_storage, ppc_reg(1));
|
||||
|
||||
/* Call the __wine_delay_load function, arg1 is arg1. */
|
||||
fprintf( outfile, "\tbl %s\n", asm_name("__wine_spec_delay_load") );
|
||||
output( "\tbl %s\n", asm_name("__wine_spec_delay_load") );
|
||||
|
||||
/* Load return value from call into ctr register */
|
||||
fprintf( outfile, "\tmtctr %s\n", ppc_reg(3));
|
||||
output( "\tmtctr %s\n", ppc_reg(3));
|
||||
|
||||
/* restore all saved registers and drop stackframe. */
|
||||
fprintf( outfile, "\tlwz %s, %d(%s)\n", ppc_reg(3), 4+extra_stack_storage, ppc_reg(1));
|
||||
fprintf( outfile, "\tlwz %s, %d(%s)\n", ppc_reg(4), 8+extra_stack_storage, ppc_reg(1));
|
||||
fprintf( outfile, "\tlwz %s, %d(%s)\n", ppc_reg(5), 12+extra_stack_storage, ppc_reg(1));
|
||||
fprintf( outfile, "\tlwz %s, %d(%s)\n", ppc_reg(6), 16+extra_stack_storage, ppc_reg(1));
|
||||
fprintf( outfile, "\tlwz %s, %d(%s)\n", ppc_reg(7), 20+extra_stack_storage, ppc_reg(1));
|
||||
fprintf( outfile, "\tlwz %s, %d(%s)\n", ppc_reg(8), 24+extra_stack_storage, ppc_reg(1));
|
||||
fprintf( outfile, "\tlwz %s, %d(%s)\n", ppc_reg(9), 28+extra_stack_storage, ppc_reg(1));
|
||||
fprintf( outfile, "\tlwz %s, %d(%s)\n", ppc_reg(10),32+extra_stack_storage, ppc_reg(1));
|
||||
fprintf( outfile, "\tlwz %s, %d(%s)\n", ppc_reg(11),36+extra_stack_storage, ppc_reg(1));
|
||||
fprintf( outfile, "\tlwz %s, %d(%s)\n", ppc_reg(12),40+extra_stack_storage, ppc_reg(1));
|
||||
output( "\tlwz %s, %d(%s)\n", ppc_reg(3), 4+extra_stack_storage, ppc_reg(1));
|
||||
output( "\tlwz %s, %d(%s)\n", ppc_reg(4), 8+extra_stack_storage, ppc_reg(1));
|
||||
output( "\tlwz %s, %d(%s)\n", ppc_reg(5), 12+extra_stack_storage, ppc_reg(1));
|
||||
output( "\tlwz %s, %d(%s)\n", ppc_reg(6), 16+extra_stack_storage, ppc_reg(1));
|
||||
output( "\tlwz %s, %d(%s)\n", ppc_reg(7), 20+extra_stack_storage, ppc_reg(1));
|
||||
output( "\tlwz %s, %d(%s)\n", ppc_reg(8), 24+extra_stack_storage, ppc_reg(1));
|
||||
output( "\tlwz %s, %d(%s)\n", ppc_reg(9), 28+extra_stack_storage, ppc_reg(1));
|
||||
output( "\tlwz %s, %d(%s)\n", ppc_reg(10),32+extra_stack_storage, ppc_reg(1));
|
||||
output( "\tlwz %s, %d(%s)\n", ppc_reg(11),36+extra_stack_storage, ppc_reg(1));
|
||||
output( "\tlwz %s, %d(%s)\n", ppc_reg(12),40+extra_stack_storage, ppc_reg(1));
|
||||
|
||||
/* Load return value from call into return register */
|
||||
fprintf( outfile, "\tlwz %s, %d(%s)\n", ppc_reg(0), 44+extra_stack_storage, ppc_reg(1));
|
||||
fprintf( outfile, "\tmtlr %s\n", ppc_reg(0));
|
||||
fprintf( outfile, "\taddi %s, %s, %d\n", ppc_reg(1), ppc_reg(1), 48+extra_stack_storage);
|
||||
output( "\tlwz %s, %d(%s)\n", ppc_reg(0), 44+extra_stack_storage, ppc_reg(1));
|
||||
output( "\tmtlr %s\n", ppc_reg(0));
|
||||
output( "\taddi %s, %s, %d\n", ppc_reg(1), ppc_reg(1), 48+extra_stack_storage);
|
||||
|
||||
/* branch to ctr register. */
|
||||
fprintf( outfile, "\tbctr\n");
|
||||
output( "\tbctr\n");
|
||||
break;
|
||||
}
|
||||
output_function_size( outfile, "__wine_delay_load_asm" );
|
||||
fprintf( outfile, "\n" );
|
||||
output_function_size( "__wine_delay_load_asm" );
|
||||
output( "\n" );
|
||||
|
||||
for (i = idx = 0; i < nb_imports; i++)
|
||||
{
|
||||
|
@ -1021,25 +1021,25 @@ static void output_delayed_import_thunks( FILE *outfile, const DLLSPEC *spec )
|
|||
ORDDEF *odp = dll_imports[i]->imports[j];
|
||||
const char *name = odp->name ? odp->name : odp->export_name;
|
||||
|
||||
fprintf( outfile, ".L__wine_delay_imp_%d_%s:\n", i, name );
|
||||
output( ".L__wine_delay_imp_%d_%s:\n", i, name );
|
||||
switch(target_cpu)
|
||||
{
|
||||
case CPU_x86:
|
||||
fprintf( outfile, "\tmovl $%d, %%eax\n", (idx << 16) | j );
|
||||
fprintf( outfile, "\tjmp %s\n", asm_name("__wine_delay_load_asm") );
|
||||
output( "\tmovl $%d, %%eax\n", (idx << 16) | j );
|
||||
output( "\tjmp %s\n", asm_name("__wine_delay_load_asm") );
|
||||
break;
|
||||
case CPU_x86_64:
|
||||
fprintf( outfile, "\tmovq $%d,%%r11\n", (idx << 16) | j );
|
||||
fprintf( outfile, "\tjmp %s\n", asm_name("__wine_delay_load_asm") );
|
||||
output( "\tmovq $%d,%%r11\n", (idx << 16) | j );
|
||||
output( "\tjmp %s\n", asm_name("__wine_delay_load_asm") );
|
||||
break;
|
||||
case CPU_SPARC:
|
||||
fprintf( outfile, "\tset %d, %%g1\n", (idx << 16) | j );
|
||||
fprintf( outfile, "\tb,a %s\n", asm_name("__wine_delay_load_asm") );
|
||||
output( "\tset %d, %%g1\n", (idx << 16) | j );
|
||||
output( "\tb,a %s\n", asm_name("__wine_delay_load_asm") );
|
||||
break;
|
||||
case CPU_ALPHA:
|
||||
fprintf( outfile, "\tlda $0,%d($31)\n", j);
|
||||
fprintf( outfile, "\tldah $0,%d($0)\n", idx);
|
||||
fprintf( outfile, "\tjmp $31,%s\n", asm_name("__wine_delay_load_asm") );
|
||||
output( "\tlda $0,%d($31)\n", j);
|
||||
output( "\tldah $0,%d($0)\n", idx);
|
||||
output( "\tjmp $31,%s\n", asm_name("__wine_delay_load_asm") );
|
||||
break;
|
||||
case CPU_POWERPC:
|
||||
switch(target_platform)
|
||||
|
@ -1047,24 +1047,24 @@ static void output_delayed_import_thunks( FILE *outfile, const DLLSPEC *spec )
|
|||
case PLATFORM_APPLE:
|
||||
/* On Darwin we can use r0 and r2 */
|
||||
/* Upper part in r2 */
|
||||
fprintf( outfile, "\tlis %s, %d\n", ppc_reg(2), idx);
|
||||
output( "\tlis %s, %d\n", ppc_reg(2), idx);
|
||||
/* Lower part + r2 -> r0, Note we can't use r0 directly */
|
||||
fprintf( outfile, "\taddi %s, %s, %d\n", ppc_reg(0), ppc_reg(2), j);
|
||||
fprintf( outfile, "\tb %s\n", asm_name("__wine_delay_load_asm") );
|
||||
output( "\taddi %s, %s, %d\n", ppc_reg(0), ppc_reg(2), j);
|
||||
output( "\tb %s\n", asm_name("__wine_delay_load_asm") );
|
||||
break;
|
||||
default:
|
||||
/* On linux we can't use r2 since r2 is not a scratch register (hold the TOC) */
|
||||
/* Save r13 on the stack */
|
||||
fprintf( outfile, "\taddi %s, %s, -0x4\n", ppc_reg(1), ppc_reg(1));
|
||||
fprintf( outfile, "\tstw %s, 0(%s)\n", ppc_reg(13), ppc_reg(1));
|
||||
output( "\taddi %s, %s, -0x4\n", ppc_reg(1), ppc_reg(1));
|
||||
output( "\tstw %s, 0(%s)\n", ppc_reg(13), ppc_reg(1));
|
||||
/* Upper part in r13 */
|
||||
fprintf( outfile, "\tlis %s, %d\n", ppc_reg(13), idx);
|
||||
output( "\tlis %s, %d\n", ppc_reg(13), idx);
|
||||
/* Lower part + r13 -> r0, Note we can't use r0 directly */
|
||||
fprintf( outfile, "\taddi %s, %s, %d\n", ppc_reg(0), ppc_reg(13), j);
|
||||
output( "\taddi %s, %s, %d\n", ppc_reg(0), ppc_reg(13), j);
|
||||
/* Restore r13 */
|
||||
fprintf( outfile, "\tstw %s, 0(%s)\n", ppc_reg(13), ppc_reg(1));
|
||||
fprintf( outfile, "\taddic %s, %s, 0x4\n", ppc_reg(1), ppc_reg(1));
|
||||
fprintf( outfile, "\tb %s\n", asm_name("__wine_delay_load_asm") );
|
||||
output( "\tstw %s, 0(%s)\n", ppc_reg(13), ppc_reg(1));
|
||||
output( "\taddic %s, %s, 0x4\n", ppc_reg(1), ppc_reg(1));
|
||||
output( "\tb %s\n", asm_name("__wine_delay_load_asm") );
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -1072,25 +1072,25 @@ static void output_delayed_import_thunks( FILE *outfile, const DLLSPEC *spec )
|
|||
}
|
||||
idx++;
|
||||
}
|
||||
output_function_size( outfile, delayed_import_loaders );
|
||||
output_function_size( delayed_import_loaders );
|
||||
|
||||
fprintf( outfile, "\n\t.align %d\n", get_alignment(get_ptr_size()) );
|
||||
fprintf( outfile, "%s:\n", asm_name(delayed_import_thunks));
|
||||
output( "\n\t.align %d\n", get_alignment(get_ptr_size()) );
|
||||
output( "%s:\n", asm_name(delayed_import_thunks));
|
||||
for (i = pos = 0; i < nb_imports; i++)
|
||||
{
|
||||
if (!dll_imports[i]->delay) continue;
|
||||
for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += get_ptr_size())
|
||||
{
|
||||
ORDDEF *odp = dll_imports[i]->imports[j];
|
||||
output_import_thunk( outfile, odp->name ? odp->name : odp->export_name,
|
||||
output_import_thunk( odp->name ? odp->name : odp->export_name,
|
||||
".L__wine_delay_IAT", pos );
|
||||
}
|
||||
}
|
||||
output_function_size( outfile, delayed_import_thunks );
|
||||
output_function_size( delayed_import_thunks );
|
||||
}
|
||||
|
||||
/* output import stubs for exported entry points that link to external symbols */
|
||||
static void output_external_link_imports( FILE *outfile, DLLSPEC *spec )
|
||||
static void output_external_link_imports( DLLSPEC *spec )
|
||||
{
|
||||
unsigned int i, pos;
|
||||
|
||||
|
@ -1105,25 +1105,25 @@ static void output_external_link_imports( FILE *outfile, DLLSPEC *spec )
|
|||
remove_name( &ext_link_imports, i-- );
|
||||
}
|
||||
|
||||
fprintf( outfile, "\n/* external link thunks */\n\n" );
|
||||
fprintf( outfile, "\t.data\n" );
|
||||
fprintf( outfile, "\t.align %d\n", get_alignment(get_ptr_size()) );
|
||||
fprintf( outfile, ".L__wine_spec_external_links:\n" );
|
||||
output( "\n/* external link thunks */\n\n" );
|
||||
output( "\t.data\n" );
|
||||
output( "\t.align %d\n", get_alignment(get_ptr_size()) );
|
||||
output( ".L__wine_spec_external_links:\n" );
|
||||
for (i = 0; i < ext_link_imports.count; i++)
|
||||
fprintf( outfile, "\t%s %s\n", get_asm_ptr_keyword(), asm_name(ext_link_imports.names[i]) );
|
||||
output( "\t%s %s\n", get_asm_ptr_keyword(), asm_name(ext_link_imports.names[i]) );
|
||||
|
||||
fprintf( outfile, "\n\t.text\n" );
|
||||
fprintf( outfile, "\t.align %d\n", get_alignment(get_ptr_size()) );
|
||||
fprintf( outfile, "%s:\n", asm_name("__wine_spec_external_link_thunks") );
|
||||
output( "\n\t.text\n" );
|
||||
output( "\t.align %d\n", get_alignment(get_ptr_size()) );
|
||||
output( "%s:\n", asm_name("__wine_spec_external_link_thunks") );
|
||||
|
||||
for (i = pos = 0; i < ext_link_imports.count; i++)
|
||||
{
|
||||
char buffer[256];
|
||||
sprintf( buffer, "__wine_spec_ext_link_%s", ext_link_imports.names[i] );
|
||||
output_import_thunk( outfile, buffer, ".L__wine_spec_external_links", pos );
|
||||
output_import_thunk( buffer, ".L__wine_spec_external_links", pos );
|
||||
pos += get_ptr_size();
|
||||
}
|
||||
output_function_size( outfile, "__wine_spec_external_link_thunks" );
|
||||
output_function_size( "__wine_spec_external_link_thunks" );
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
|
@ -1131,15 +1131,15 @@ static void output_external_link_imports( FILE *outfile, DLLSPEC *spec )
|
|||
*
|
||||
* Output the functions for stub entry points
|
||||
*/
|
||||
void output_stubs( FILE *outfile, DLLSPEC *spec )
|
||||
void output_stubs( DLLSPEC *spec )
|
||||
{
|
||||
const char *name, *exp_name;
|
||||
int i, pos;
|
||||
|
||||
if (!has_stubs( spec )) return;
|
||||
|
||||
fprintf( outfile, "\n/* stub functions */\n\n" );
|
||||
fprintf( outfile, "\t.text\n" );
|
||||
output( "\n/* stub functions */\n\n" );
|
||||
output( "\t.text\n" );
|
||||
|
||||
for (i = pos = 0; i < spec->nb_entry_points; i++)
|
||||
{
|
||||
|
@ -1148,64 +1148,64 @@ void output_stubs( FILE *outfile, DLLSPEC *spec )
|
|||
|
||||
name = get_stub_name( odp, spec );
|
||||
exp_name = odp->name ? odp->name : odp->export_name;
|
||||
fprintf( outfile, "\t.align %d\n", get_alignment(4) );
|
||||
fprintf( outfile, "\t%s\n", func_declaration(name) );
|
||||
fprintf( outfile, "%s:\n", asm_name(name) );
|
||||
fprintf( outfile, "\tsubl $4,%%esp\n" );
|
||||
output( "\t.align %d\n", get_alignment(4) );
|
||||
output( "\t%s\n", func_declaration(name) );
|
||||
output( "%s:\n", asm_name(name) );
|
||||
output( "\tsubl $4,%%esp\n" );
|
||||
|
||||
if (UsePIC)
|
||||
{
|
||||
fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
|
||||
fprintf( outfile, "1:" );
|
||||
output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
|
||||
output( "1:" );
|
||||
if (exp_name)
|
||||
{
|
||||
fprintf( outfile, "\tleal .L__wine_stub_strings+%d-1b(%%eax),%%ecx\n", pos );
|
||||
fprintf( outfile, "\tpushl %%ecx\n" );
|
||||
output( "\tleal .L__wine_stub_strings+%d-1b(%%eax),%%ecx\n", pos );
|
||||
output( "\tpushl %%ecx\n" );
|
||||
pos += strlen(exp_name) + 1;
|
||||
}
|
||||
else
|
||||
fprintf( outfile, "\tpushl $%d\n", odp->ordinal );
|
||||
fprintf( outfile, "\tleal .L__wine_spec_file_name-1b(%%eax),%%ecx\n" );
|
||||
fprintf( outfile, "\tpushl %%ecx\n" );
|
||||
output( "\tpushl $%d\n", odp->ordinal );
|
||||
output( "\tleal .L__wine_spec_file_name-1b(%%eax),%%ecx\n" );
|
||||
output( "\tpushl %%ecx\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (exp_name)
|
||||
{
|
||||
fprintf( outfile, "\tpushl $.L__wine_stub_strings+%d\n", pos );
|
||||
output( "\tpushl $.L__wine_stub_strings+%d\n", pos );
|
||||
pos += strlen(exp_name) + 1;
|
||||
}
|
||||
else
|
||||
fprintf( outfile, "\tpushl $%d\n", odp->ordinal );
|
||||
fprintf( outfile, "\tpushl $.L__wine_spec_file_name\n" );
|
||||
output( "\tpushl $%d\n", odp->ordinal );
|
||||
output( "\tpushl $.L__wine_spec_file_name\n" );
|
||||
}
|
||||
fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_unimplemented_stub") );
|
||||
output_function_size( outfile, name );
|
||||
output( "\tcall %s\n", asm_name("__wine_spec_unimplemented_stub") );
|
||||
output_function_size( name );
|
||||
}
|
||||
|
||||
if (pos)
|
||||
{
|
||||
fprintf( outfile, "\t%s\n", get_asm_string_section() );
|
||||
fprintf( outfile, ".L__wine_stub_strings:\n" );
|
||||
output( "\t%s\n", get_asm_string_section() );
|
||||
output( ".L__wine_stub_strings:\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", get_asm_string_keyword(), exp_name );
|
||||
output( "\t%s \"%s\"\n", get_asm_string_keyword(), exp_name );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* output the import and delayed import tables of a Win32 module */
|
||||
void output_imports( FILE *outfile, DLLSPEC *spec )
|
||||
void output_imports( DLLSPEC *spec )
|
||||
{
|
||||
output_immediate_imports( outfile );
|
||||
output_delayed_imports( outfile, spec );
|
||||
output_immediate_import_thunks( outfile );
|
||||
output_delayed_import_thunks( outfile, spec );
|
||||
output_external_link_imports( outfile, spec );
|
||||
output_immediate_imports();
|
||||
output_delayed_imports( spec );
|
||||
output_immediate_import_thunks();
|
||||
output_delayed_import_thunks( spec );
|
||||
output_external_link_imports( spec );
|
||||
if (nb_imports || ext_link_imports.count || has_stubs(spec) || has_relays(spec))
|
||||
output_get_pc_thunk( outfile );
|
||||
output_get_pc_thunk();
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ char **lib_path = NULL;
|
|||
|
||||
char *input_file_name = NULL;
|
||||
char *spec_file_name = NULL;
|
||||
FILE *output_file = NULL;
|
||||
const char *output_file_name = NULL;
|
||||
static const char *output_file_source_name;
|
||||
|
||||
|
@ -82,7 +83,6 @@ char *as_command = NULL;
|
|||
char *ld_command = NULL;
|
||||
char *nm_command = NULL;
|
||||
|
||||
static FILE *output_file;
|
||||
static int nb_res_files;
|
||||
static char **res_files;
|
||||
|
||||
|
@ -597,11 +597,11 @@ int main(int argc, char **argv)
|
|||
case SPEC_WIN16:
|
||||
if (argv[0])
|
||||
fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
|
||||
BuildSpec16File( output_file, spec );
|
||||
BuildSpec16File( spec );
|
||||
break;
|
||||
case SPEC_WIN32:
|
||||
read_undef_symbols( spec, argv );
|
||||
BuildSpec32File( output_file, spec );
|
||||
BuildSpec32File( spec );
|
||||
break;
|
||||
default: assert(0);
|
||||
}
|
||||
|
@ -613,22 +613,22 @@ int main(int argc, char **argv)
|
|||
load_import_libs( argv );
|
||||
if (spec_file_name && !parse_input_file( spec )) break;
|
||||
read_undef_symbols( spec, argv );
|
||||
BuildSpec32File( output_file, spec );
|
||||
BuildSpec32File( spec );
|
||||
break;
|
||||
case MODE_DEF:
|
||||
if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
|
||||
if (spec->type == SPEC_WIN16) fatal_error( "Cannot yet build .def file for 16-bit dlls\n" );
|
||||
if (!spec_file_name) fatal_error( "missing .spec file\n" );
|
||||
if (!parse_input_file( spec )) break;
|
||||
BuildDef32File( output_file, spec );
|
||||
BuildDef32File( spec );
|
||||
break;
|
||||
case MODE_RELAY16:
|
||||
if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
|
||||
BuildRelays16( output_file );
|
||||
BuildRelays16();
|
||||
break;
|
||||
case MODE_RELAY32:
|
||||
if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
|
||||
BuildRelays32( output_file );
|
||||
BuildRelays32();
|
||||
break;
|
||||
default:
|
||||
usage(1);
|
||||
|
@ -637,7 +637,7 @@ int main(int argc, char **argv)
|
|||
if (nb_errors) exit(1);
|
||||
if (output_file_name)
|
||||
{
|
||||
fclose( output_file );
|
||||
if (fclose( output_file ) < 0) fatal_perror( "fclose" );
|
||||
if (output_file_source_name) assemble_file( output_file_source_name, output_file_name );
|
||||
output_file_name = NULL;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -242,16 +242,16 @@ static void free_resource_tree( struct res_tree *tree )
|
|||
}
|
||||
|
||||
/* output a string preceded by its length */
|
||||
static void output_string( FILE *outfile, const char *str )
|
||||
static void output_string( const char *str )
|
||||
{
|
||||
unsigned int i, len = strlen(str);
|
||||
fprintf( outfile, "\t.byte 0x%02x", len );
|
||||
for (i = 0; i < len; i++) fprintf( outfile, ",0x%02x", (unsigned char)str[i] );
|
||||
fprintf( outfile, " /* %s */\n", str );
|
||||
output( "\t.byte 0x%02x", len );
|
||||
for (i = 0; i < len; i++) output( ",0x%02x", (unsigned char)str[i] );
|
||||
output( " /* %s */\n", str );
|
||||
}
|
||||
|
||||
/* output the resource data */
|
||||
void output_res16_data( FILE *outfile, DLLSPEC *spec )
|
||||
void output_res16_data( DLLSPEC *spec )
|
||||
{
|
||||
const struct resource *res;
|
||||
unsigned int i;
|
||||
|
@ -260,14 +260,14 @@ void output_res16_data( FILE *outfile, DLLSPEC *spec )
|
|||
|
||||
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
|
||||
{
|
||||
fprintf( outfile, ".L__wine_spec_resource_%u:\n", i );
|
||||
dump_bytes( outfile, res->data, res->data_size );
|
||||
fprintf( outfile, ".L__wine_spec_resource_%u_end:\n", i );
|
||||
output( ".L__wine_spec_resource_%u:\n", i );
|
||||
dump_bytes( res->data, res->data_size );
|
||||
output( ".L__wine_spec_resource_%u_end:\n", i );
|
||||
}
|
||||
}
|
||||
|
||||
/* output the resource definitions */
|
||||
void output_res16_directory( FILE *outfile, DLLSPEC *spec, const char *header_name )
|
||||
void output_res16_directory( DLLSPEC *spec, const char *header_name )
|
||||
{
|
||||
unsigned int i, j;
|
||||
struct res_tree *tree;
|
||||
|
@ -276,38 +276,38 @@ void output_res16_directory( FILE *outfile, DLLSPEC *spec, const char *header_na
|
|||
|
||||
tree = build_resource_tree( spec );
|
||||
|
||||
fprintf( outfile, "\n.L__wine_spec_ne_rsrctab:\n" );
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* alignment */
|
||||
output( "\n.L__wine_spec_ne_rsrctab:\n" );
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* alignment */
|
||||
|
||||
/* type and name structures */
|
||||
|
||||
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
|
||||
{
|
||||
if (type->type->str)
|
||||
fprintf( outfile, "\t%s .L__wine_spec_restype_%u-.L__wine_spec_ne_rsrctab\n",
|
||||
output( "\t%s .L__wine_spec_restype_%u-.L__wine_spec_ne_rsrctab\n",
|
||||
get_asm_short_keyword(), i );
|
||||
else
|
||||
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), type->type->id | 0x8000 );
|
||||
output( "\t%s 0x%04x\n", get_asm_short_keyword(), type->type->id | 0x8000 );
|
||||
|
||||
fprintf( outfile, "\t%s %u,0,0\n", get_asm_short_keyword(), type->nb_names );
|
||||
output( "\t%s %u,0,0\n", get_asm_short_keyword(), type->nb_names );
|
||||
|
||||
for (j = 0, res = type->res; j < type->nb_names; j++, res++)
|
||||
{
|
||||
fprintf( outfile, "\t%s .L__wine_spec_resource_%u-%s\n",
|
||||
output( "\t%s .L__wine_spec_resource_%u-%s\n",
|
||||
get_asm_short_keyword(), res - spec->resources, header_name );
|
||||
fprintf( outfile, "\t%s .L__wine_spec_resource_%u_end-.L__wine_spec_resource_%u\n",
|
||||
output( "\t%s .L__wine_spec_resource_%u_end-.L__wine_spec_resource_%u\n",
|
||||
get_asm_short_keyword(), res - spec->resources, res - spec->resources );
|
||||
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), res->memopt );
|
||||
output( "\t%s 0x%04x\n", get_asm_short_keyword(), res->memopt );
|
||||
if (res->name.str)
|
||||
fprintf( outfile, "\t%s .L__wine_spec_resname_%u_%u-.L__wine_spec_ne_rsrctab\n",
|
||||
output( "\t%s .L__wine_spec_resname_%u_%u-.L__wine_spec_ne_rsrctab\n",
|
||||
get_asm_short_keyword(), i, j );
|
||||
else
|
||||
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), res->name.id | 0x8000 );
|
||||
output( "\t%s 0x%04x\n", get_asm_short_keyword(), res->name.id | 0x8000 );
|
||||
|
||||
fprintf( outfile, "\t%s 0,0\n", get_asm_short_keyword() );
|
||||
output( "\t%s 0,0\n", get_asm_short_keyword() );
|
||||
}
|
||||
}
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* terminator */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* terminator */
|
||||
|
||||
/* name strings */
|
||||
|
||||
|
@ -315,19 +315,19 @@ void output_res16_directory( FILE *outfile, DLLSPEC *spec, const char *header_na
|
|||
{
|
||||
if (type->type->str)
|
||||
{
|
||||
fprintf( outfile, ".L__wine_spec_restype_%u:\n", i );
|
||||
output_string( outfile, type->type->str );
|
||||
output( ".L__wine_spec_restype_%u:\n", i );
|
||||
output_string( type->type->str );
|
||||
}
|
||||
for (j = 0, res = type->res; j < type->nb_names; j++, res++)
|
||||
{
|
||||
if (res->name.str)
|
||||
{
|
||||
fprintf( outfile, ".L__wine_spec_resname_%u_%u:\n", i, j );
|
||||
output_string( outfile, res->name.str );
|
||||
output( ".L__wine_spec_resname_%u_%u:\n", i, j );
|
||||
output_string( res->name.str );
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf( outfile, "\t.byte 0\n" ); /* names terminator */
|
||||
output( "\t.byte 0\n" ); /* names terminator */
|
||||
|
||||
free_resource_tree( tree );
|
||||
}
|
||||
|
|
|
@ -316,29 +316,29 @@ static void free_resource_tree( struct res_tree *tree )
|
|||
}
|
||||
|
||||
/* output a Unicode string */
|
||||
static void output_string( FILE *outfile, const WCHAR *name )
|
||||
static void output_string( const WCHAR *name )
|
||||
{
|
||||
int i, len = strlenW(name);
|
||||
fprintf( outfile, "\t%s 0x%04x", get_asm_short_keyword(), len );
|
||||
for (i = 0; i < len; i++) fprintf( outfile, ",0x%04x", name[i] );
|
||||
fprintf( outfile, " /* " );
|
||||
for (i = 0; i < len; i++) fprintf( outfile, "%c", isprint((char)name[i]) ? (char)name[i] : '?' );
|
||||
fprintf( outfile, " */\n" );
|
||||
output( "\t%s 0x%04x", get_asm_short_keyword(), len );
|
||||
for (i = 0; i < len; i++) output( ",0x%04x", name[i] );
|
||||
output( " /* " );
|
||||
for (i = 0; i < len; i++) output( "%c", isprint((char)name[i]) ? (char)name[i] : '?' );
|
||||
output( " */\n" );
|
||||
}
|
||||
|
||||
/* output a resource directory */
|
||||
static inline void output_res_dir( FILE *outfile, unsigned int nb_names, unsigned int nb_ids )
|
||||
static inline void output_res_dir( unsigned int nb_names, unsigned int nb_ids )
|
||||
{
|
||||
fprintf( outfile, "\t.long 0\n" ); /* Characteristics */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* TimeDateStamp */
|
||||
fprintf( outfile, "\t%s 0,0\n", /* Major/MinorVersion */
|
||||
output( "\t.long 0\n" ); /* Characteristics */
|
||||
output( "\t.long 0\n" ); /* TimeDateStamp */
|
||||
output( "\t%s 0,0\n", /* Major/MinorVersion */
|
||||
get_asm_short_keyword() );
|
||||
fprintf( outfile, "\t%s %u,%u\n", /* NumberOfNamed/IdEntries */
|
||||
output( "\t%s %u,%u\n", /* NumberOfNamed/IdEntries */
|
||||
get_asm_short_keyword(), nb_names, nb_ids );
|
||||
}
|
||||
|
||||
/* output the resource definitions */
|
||||
void output_resources( FILE *outfile, DLLSPEC *spec )
|
||||
void output_resources( DLLSPEC *spec )
|
||||
{
|
||||
int k, nb_id_types;
|
||||
unsigned int i, n, offset, data_offset;
|
||||
|
@ -388,19 +388,19 @@ void output_resources( FILE *outfile, DLLSPEC *spec )
|
|||
|
||||
/* output the resource directories */
|
||||
|
||||
fprintf( outfile, "\n/* resources */\n\n" );
|
||||
fprintf( outfile, "\t.data\n" );
|
||||
fprintf( outfile, "\t.align %d\n", get_alignment(get_ptr_size()) );
|
||||
fprintf( outfile, ".L__wine_spec_resources:\n" );
|
||||
output( "\n/* resources */\n\n" );
|
||||
output( "\t.data\n" );
|
||||
output( "\t.align %d\n", get_alignment(get_ptr_size()) );
|
||||
output( ".L__wine_spec_resources:\n" );
|
||||
|
||||
output_res_dir( outfile, tree->nb_types - nb_id_types, nb_id_types );
|
||||
output_res_dir( tree->nb_types - nb_id_types, nb_id_types );
|
||||
|
||||
/* dump the type directory */
|
||||
|
||||
offset = RESDIR_SIZE( tree->nb_types );
|
||||
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
|
||||
{
|
||||
fprintf( outfile, "\t.long 0x%08x,0x%08x\n",
|
||||
output( "\t.long 0x%08x,0x%08x\n",
|
||||
type->name_offset, offset | 0x80000000 );
|
||||
offset += RESDIR_SIZE( type->nb_names );
|
||||
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
|
||||
|
@ -414,22 +414,22 @@ void output_resources( FILE *outfile, DLLSPEC *spec )
|
|||
|
||||
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
|
||||
{
|
||||
output_res_dir( outfile, type->nb_names - type->nb_id_names, type->nb_id_names );
|
||||
output_res_dir( type->nb_names - type->nb_id_names, type->nb_id_names );
|
||||
offset += RESDIR_SIZE( type->nb_names );
|
||||
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
|
||||
{
|
||||
fprintf( outfile, "\t.long 0x%08x,0x%08x\n",
|
||||
output( "\t.long 0x%08x,0x%08x\n",
|
||||
name->name_offset, offset | 0x80000000 );
|
||||
offset += RESDIR_SIZE( name->nb_languages );
|
||||
}
|
||||
|
||||
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
|
||||
{
|
||||
output_res_dir( outfile, 0, name->nb_languages );
|
||||
output_res_dir( 0, name->nb_languages );
|
||||
for (k = 0, res = name->res; k < name->nb_languages; k++, res++)
|
||||
{
|
||||
unsigned int entry_offset = (res - spec->resources) * sizeof(IMAGE_RESOURCE_DATA_ENTRY);
|
||||
fprintf( outfile, "\t.long 0x%08x,0x%08x\n", res->lang, data_offset + entry_offset );
|
||||
output( "\t.long 0x%08x,0x%08x\n", res->lang, data_offset + entry_offset );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -437,28 +437,28 @@ void output_resources( FILE *outfile, DLLSPEC *spec )
|
|||
/* dump the resource data entries */
|
||||
|
||||
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
|
||||
fprintf( outfile, "\t.long .L__wine_spec_res_%d-.L__wine_spec_rva_base,%u,0,0\n",
|
||||
output( "\t.long .L__wine_spec_res_%d-.L__wine_spec_rva_base,%u,0,0\n",
|
||||
i, res->data_size );
|
||||
|
||||
/* dump the name strings */
|
||||
|
||||
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
|
||||
{
|
||||
if (type->type->str) output_string( outfile, type->type->str );
|
||||
if (type->type->str) output_string( type->type->str );
|
||||
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
|
||||
if (name->name->str) output_string( outfile, name->name->str );
|
||||
if (name->name->str) output_string( name->name->str );
|
||||
}
|
||||
|
||||
/* resource data */
|
||||
|
||||
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
|
||||
{
|
||||
fprintf( outfile, "\n\t.align %d\n", get_alignment(get_ptr_size()) );
|
||||
fprintf( outfile, ".L__wine_spec_res_%d:\n", i );
|
||||
dump_bytes( outfile, res->data, res->data_size );
|
||||
output( "\n\t.align %d\n", get_alignment(get_ptr_size()) );
|
||||
output( ".L__wine_spec_res_%d:\n", i );
|
||||
dump_bytes( res->data, res->data_size );
|
||||
}
|
||||
fprintf( outfile, ".L__wine_spec_resources_end:\n" );
|
||||
fprintf( outfile, "\t.byte 0\n" );
|
||||
output( ".L__wine_spec_resources_end:\n" );
|
||||
output( "\t.byte 0\n" );
|
||||
|
||||
free_resource_tree( tree );
|
||||
}
|
||||
|
|
|
@ -54,31 +54,31 @@ static inline int is_function( const ORDDEF *odp )
|
|||
*
|
||||
* Output entries for individual symbols in the entry table.
|
||||
*/
|
||||
static void output_entries( FILE *outfile, DLLSPEC *spec, int first, int count )
|
||||
static void output_entries( DLLSPEC *spec, int first, int count )
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
ORDDEF *odp = spec->ordinals[first + i];
|
||||
fprintf( outfile, "\t.byte 0x03\n" ); /* flags: exported & public data */
|
||||
output( "\t.byte 0x03\n" ); /* flags: exported & public data */
|
||||
switch (odp->type)
|
||||
{
|
||||
case TYPE_CDECL:
|
||||
case TYPE_PASCAL:
|
||||
case TYPE_VARARGS:
|
||||
case TYPE_STUB:
|
||||
fprintf( outfile, "\t%s .L__wine_%s_%u-.L__wine_spec_code_segment\n",
|
||||
output( "\t%s .L__wine_%s_%u-.L__wine_spec_code_segment\n",
|
||||
get_asm_short_keyword(),
|
||||
make_c_identifier(spec->dll_name), first + i );
|
||||
break;
|
||||
case TYPE_VARIABLE:
|
||||
fprintf( outfile, "\t%s .L__wine_%s_%u-.L__wine_spec_data_segment\n",
|
||||
output( "\t%s .L__wine_%s_%u-.L__wine_spec_data_segment\n",
|
||||
get_asm_short_keyword(),
|
||||
make_c_identifier(spec->dll_name), first + i );
|
||||
break;
|
||||
case TYPE_ABS:
|
||||
fprintf( outfile, "\t%s 0x%04x /* %s */\n",
|
||||
output( "\t%s 0x%04x /* %s */\n",
|
||||
get_asm_short_keyword(), odp->u.abs.value, odp->name );
|
||||
break;
|
||||
default:
|
||||
|
@ -91,7 +91,7 @@ static void output_entries( FILE *outfile, DLLSPEC *spec, int first, int count )
|
|||
/*******************************************************************
|
||||
* output_entry_table
|
||||
*/
|
||||
static void output_entry_table( FILE *outfile, DLLSPEC *spec )
|
||||
static void output_entry_table( DLLSPEC *spec )
|
||||
{
|
||||
int i, prev = 0, prev_sel = -1, bundle_count = 0;
|
||||
|
||||
|
@ -126,10 +126,10 @@ static void output_entry_table( FILE *outfile, DLLSPEC *spec )
|
|||
/* flush previous bundle */
|
||||
if (bundle_count)
|
||||
{
|
||||
fprintf( outfile, "\t/* %s.%d - %s.%d */\n",
|
||||
output( "\t/* %s.%d - %s.%d */\n",
|
||||
spec->dll_name, prev - bundle_count + 1, spec->dll_name, prev );
|
||||
fprintf( outfile, "\t.byte 0x%02x,0x%02x\n", bundle_count, prev_sel );
|
||||
output_entries( outfile, spec, prev - bundle_count + 1, bundle_count );
|
||||
output( "\t.byte 0x%02x,0x%02x\n", bundle_count, prev_sel );
|
||||
output_entries( spec, prev - bundle_count + 1, bundle_count );
|
||||
}
|
||||
|
||||
if (prev + 1 != i)
|
||||
|
@ -137,10 +137,10 @@ static void output_entry_table( FILE *outfile, DLLSPEC *spec )
|
|||
int skip = i - (prev + 1);
|
||||
while (skip > 255)
|
||||
{
|
||||
fprintf( outfile, "\t.byte 0xff,0x00\n" );
|
||||
output( "\t.byte 0xff,0x00\n" );
|
||||
skip -= 255;
|
||||
}
|
||||
fprintf( outfile, "\t.byte 0x%02x,0x00\n", skip );
|
||||
output( "\t.byte 0x%02x,0x00\n", skip );
|
||||
}
|
||||
|
||||
bundle_count = 0;
|
||||
|
@ -153,24 +153,24 @@ static void output_entry_table( FILE *outfile, DLLSPEC *spec )
|
|||
/* flush last bundle */
|
||||
if (bundle_count)
|
||||
{
|
||||
fprintf( outfile, "\t.byte 0x%02x,0x%02x\n", bundle_count, prev_sel );
|
||||
output_entries( outfile, spec, prev - bundle_count + 1, bundle_count );
|
||||
output( "\t.byte 0x%02x,0x%02x\n", bundle_count, prev_sel );
|
||||
output_entries( spec, prev - bundle_count + 1, bundle_count );
|
||||
}
|
||||
fprintf( outfile, "\t.byte 0x00\n" );
|
||||
output( "\t.byte 0x00\n" );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* output_resident_name
|
||||
*/
|
||||
static void output_resident_name( FILE *outfile, const char *string, int ordinal )
|
||||
static void output_resident_name( const char *string, int ordinal )
|
||||
{
|
||||
unsigned int i, len = strlen(string);
|
||||
|
||||
fprintf( outfile, "\t.byte 0x%02x", len );
|
||||
for (i = 0; i < len; i++) fprintf( outfile, ",0x%02x", (unsigned char)toupper(string[i]) );
|
||||
fprintf( outfile, " /* %s */\n", string );
|
||||
fprintf( outfile, "\t%s %u\n", get_asm_short_keyword(), ordinal );
|
||||
output( "\t.byte 0x%02x", len );
|
||||
for (i = 0; i < len; i++) output( ",0x%02x", (unsigned char)toupper(string[i]) );
|
||||
output( " /* %s */\n", string );
|
||||
output( "\t%s %u\n", get_asm_short_keyword(), ordinal );
|
||||
}
|
||||
|
||||
|
||||
|
@ -283,7 +283,7 @@ static int get_function_argsize( const ORDDEF *odp )
|
|||
* the same as for normal functions, but in addition the CONTEXT86 pointer
|
||||
* filled with the current register values is passed to the 32-bit routine.
|
||||
*/
|
||||
static void output_call16_function( FILE *outfile, ORDDEF *odp )
|
||||
static void output_call16_function( ORDDEF *odp )
|
||||
{
|
||||
char name[256];
|
||||
int i, pos, stack_words;
|
||||
|
@ -293,41 +293,41 @@ static void output_call16_function( FILE *outfile, ORDDEF *odp )
|
|||
|
||||
sprintf( name, ".L__wine_spec_call16_%s", get_relay_name(odp) );
|
||||
|
||||
fprintf( outfile, "\t.align %d\n", get_alignment(4) );
|
||||
fprintf( outfile, "\t%s\n", func_declaration(name) );
|
||||
fprintf( outfile, "%s:\n", name );
|
||||
fprintf( outfile, "\tpushl %%ebp\n" );
|
||||
fprintf( outfile, "\tmovl %%esp,%%ebp\n" );
|
||||
output( "\t.align %d\n", get_alignment(4) );
|
||||
output( "\t%s\n", func_declaration(name) );
|
||||
output( "%s:\n", name );
|
||||
output( "\tpushl %%ebp\n" );
|
||||
output( "\tmovl %%esp,%%ebp\n" );
|
||||
stack_words = 2;
|
||||
if (needs_ldt)
|
||||
{
|
||||
fprintf( outfile, "\tpushl %%esi\n" );
|
||||
output( "\tpushl %%esi\n" );
|
||||
stack_words++;
|
||||
if (UsePIC)
|
||||
{
|
||||
fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
|
||||
fprintf( outfile, "1:\tmovl wine_ldt_copy_ptr-1b(%%eax),%%esi\n" );
|
||||
output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
|
||||
output( "1:\tmovl wine_ldt_copy_ptr-1b(%%eax),%%esi\n" );
|
||||
}
|
||||
else
|
||||
fprintf( outfile, "\tmovl $%s,%%esi\n", asm_name("wine_ldt_copy") );
|
||||
output( "\tmovl $%s,%%esi\n", asm_name("wine_ldt_copy") );
|
||||
}
|
||||
|
||||
/* preserve 16-byte stack alignment */
|
||||
stack_words += strlen(args);
|
||||
if ((odp->flags & FLAG_REGISTER) || (odp->type == TYPE_VARARGS)) stack_words++;
|
||||
if (stack_words % 4) fprintf( outfile, "\tsubl $%d,%%esp\n", 16 - 4 * (stack_words % 4) );
|
||||
if (stack_words % 4) output( "\tsubl $%d,%%esp\n", 16 - 4 * (stack_words % 4) );
|
||||
|
||||
if (args[0] || odp->type == TYPE_VARARGS)
|
||||
fprintf( outfile, "\tmovl 12(%%ebp),%%ecx\n" ); /* args */
|
||||
output( "\tmovl 12(%%ebp),%%ecx\n" ); /* args */
|
||||
|
||||
if (odp->flags & FLAG_REGISTER)
|
||||
{
|
||||
fprintf( outfile, "\tpushl 16(%%ebp)\n" ); /* context */
|
||||
output( "\tpushl 16(%%ebp)\n" ); /* context */
|
||||
}
|
||||
else if (odp->type == TYPE_VARARGS)
|
||||
{
|
||||
fprintf( outfile, "\tleal %d(%%ecx),%%eax\n", argsize );
|
||||
fprintf( outfile, "\tpushl %%eax\n" ); /* va_list16 */
|
||||
output( "\tleal %d(%%ecx),%%eax\n", argsize );
|
||||
output( "\tpushl %%eax\n" ); /* va_list16 */
|
||||
}
|
||||
|
||||
pos = (odp->type == TYPE_PASCAL) ? 0 : argsize;
|
||||
|
@ -337,33 +337,33 @@ static void output_call16_function( FILE *outfile, ORDDEF *odp )
|
|||
{
|
||||
case 'w': /* word */
|
||||
if (odp->type != TYPE_PASCAL) pos -= 2;
|
||||
fprintf( outfile, "\tmovzwl %d(%%ecx),%%eax\n", pos );
|
||||
fprintf( outfile, "\tpushl %%eax\n" );
|
||||
output( "\tmovzwl %d(%%ecx),%%eax\n", pos );
|
||||
output( "\tpushl %%eax\n" );
|
||||
if (odp->type == TYPE_PASCAL) pos += 2;
|
||||
break;
|
||||
|
||||
case 's': /* s_word */
|
||||
if (odp->type != TYPE_PASCAL) pos -= 2;
|
||||
fprintf( outfile, "\tmovswl %d(%%ecx),%%eax\n", pos );
|
||||
fprintf( outfile, "\tpushl %%eax\n" );
|
||||
output( "\tmovswl %d(%%ecx),%%eax\n", pos );
|
||||
output( "\tpushl %%eax\n" );
|
||||
if (odp->type == TYPE_PASCAL) pos += 2;
|
||||
break;
|
||||
|
||||
case 'l': /* long or segmented pointer */
|
||||
case 'T': /* segmented pointer to null-terminated string */
|
||||
if (odp->type != TYPE_PASCAL) pos -= 4;
|
||||
fprintf( outfile, "\tpushl %d(%%ecx)\n", pos );
|
||||
output( "\tpushl %d(%%ecx)\n", pos );
|
||||
if (odp->type == TYPE_PASCAL) pos += 4;
|
||||
break;
|
||||
|
||||
case 'p': /* linear pointer */
|
||||
case 't': /* linear pointer to null-terminated string */
|
||||
if (odp->type != TYPE_PASCAL) pos -= 4;
|
||||
fprintf( outfile, "\tmovzwl %d(%%ecx),%%edx\n", pos + 2 ); /* sel */
|
||||
fprintf( outfile, "\tshr $3,%%edx\n" );
|
||||
fprintf( outfile, "\tmovzwl %d(%%ecx),%%eax\n", pos ); /* offset */
|
||||
fprintf( outfile, "\taddl (%%esi,%%edx,4),%%eax\n" );
|
||||
fprintf( outfile, "\tpushl %%eax\n" );
|
||||
output( "\tmovzwl %d(%%ecx),%%edx\n", pos + 2 ); /* sel */
|
||||
output( "\tshr $3,%%edx\n" );
|
||||
output( "\tmovzwl %d(%%ecx),%%eax\n", pos ); /* offset */
|
||||
output( "\taddl (%%esi,%%edx,4),%%eax\n" );
|
||||
output( "\tpushl %%eax\n" );
|
||||
if (odp->type == TYPE_PASCAL) pos += 4;
|
||||
break;
|
||||
|
||||
|
@ -372,13 +372,13 @@ static void output_call16_function( FILE *outfile, ORDDEF *odp )
|
|||
}
|
||||
}
|
||||
|
||||
fprintf( outfile, "\tcall *8(%%ebp)\n" );
|
||||
output( "\tcall *8(%%ebp)\n" );
|
||||
|
||||
if (needs_ldt) fprintf( outfile, "\tmovl -4(%%ebp),%%esi\n" );
|
||||
if (needs_ldt) output( "\tmovl -4(%%ebp),%%esi\n" );
|
||||
|
||||
fprintf( outfile, "\tleave\n" );
|
||||
fprintf( outfile, "\tret\n" );
|
||||
output_function_size( outfile, name );
|
||||
output( "\tleave\n" );
|
||||
output( "\tret\n" );
|
||||
output_function_size( name );
|
||||
}
|
||||
|
||||
|
||||
|
@ -450,72 +450,72 @@ static int sort_func_list( ORDDEF **list, int count,
|
|||
*
|
||||
* Output the dll initialization code.
|
||||
*/
|
||||
static void output_init_code( FILE *outfile, const DLLSPEC *spec, const char *header_name )
|
||||
static void output_init_code( const DLLSPEC *spec, const char *header_name )
|
||||
{
|
||||
char name[80];
|
||||
|
||||
sprintf( name, ".L__wine_spec_%s_init", make_c_identifier(spec->dll_name) );
|
||||
|
||||
fprintf( outfile, "\n/* dll initialization code */\n\n" );
|
||||
fprintf( outfile, "\t.text\n" );
|
||||
fprintf( outfile, "\t.align 4\n" );
|
||||
fprintf( outfile, "\t%s\n", func_declaration(name) );
|
||||
fprintf( outfile, "%s:\n", name );
|
||||
fprintf( outfile, "subl $4,%%esp\n" );
|
||||
output( "\n/* dll initialization code */\n\n" );
|
||||
output( "\t.text\n" );
|
||||
output( "\t.align 4\n" );
|
||||
output( "\t%s\n", func_declaration(name) );
|
||||
output( "%s:\n", name );
|
||||
output( "subl $4,%%esp\n" );
|
||||
if (UsePIC)
|
||||
{
|
||||
fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
|
||||
fprintf( outfile, "1:\tleal .L__wine_spec_file_name-1b(%%eax),%%ecx\n" );
|
||||
fprintf( outfile, "\tpushl %%ecx\n" );
|
||||
fprintf( outfile, "\tleal %s-1b(%%eax),%%ecx\n", header_name );
|
||||
fprintf( outfile, "\tpushl %%ecx\n" );
|
||||
output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
|
||||
output( "1:\tleal .L__wine_spec_file_name-1b(%%eax),%%ecx\n" );
|
||||
output( "\tpushl %%ecx\n" );
|
||||
output( "\tleal %s-1b(%%eax),%%ecx\n", header_name );
|
||||
output( "\tpushl %%ecx\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( outfile, "\tpushl $.L__wine_spec_file_name\n" );
|
||||
fprintf( outfile, "\tpushl $%s\n", header_name );
|
||||
output( "\tpushl $.L__wine_spec_file_name\n" );
|
||||
output( "\tpushl $%s\n", header_name );
|
||||
}
|
||||
fprintf( outfile, "\tcall %s\n", asm_name("__wine_dll_register_16") );
|
||||
fprintf( outfile, "\taddl $12,%%esp\n" );
|
||||
fprintf( outfile, "\tret\n" );
|
||||
output_function_size( outfile, name );
|
||||
output( "\tcall %s\n", asm_name("__wine_dll_register_16") );
|
||||
output( "\taddl $12,%%esp\n" );
|
||||
output( "\tret\n" );
|
||||
output_function_size( name );
|
||||
|
||||
sprintf( name, ".L__wine_spec_%s_fini", make_c_identifier(spec->dll_name) );
|
||||
|
||||
fprintf( outfile, "\t.align 4\n" );
|
||||
fprintf( outfile, "\t%s\n", func_declaration(name) );
|
||||
fprintf( outfile, "%s:\n", name );
|
||||
fprintf( outfile, "subl $8,%%esp\n" );
|
||||
output( "\t.align 4\n" );
|
||||
output( "\t%s\n", func_declaration(name) );
|
||||
output( "%s:\n", name );
|
||||
output( "subl $8,%%esp\n" );
|
||||
if (UsePIC)
|
||||
{
|
||||
fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
|
||||
fprintf( outfile, "1:\tleal %s-1b(%%eax),%%ecx\n", header_name );
|
||||
fprintf( outfile, "\tpushl %%ecx\n" );
|
||||
output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
|
||||
output( "1:\tleal %s-1b(%%eax),%%ecx\n", header_name );
|
||||
output( "\tpushl %%ecx\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( outfile, "\tpushl $%s\n", header_name );
|
||||
output( "\tpushl $%s\n", header_name );
|
||||
}
|
||||
fprintf( outfile, "\tcall %s\n", asm_name("__wine_dll_unregister_16") );
|
||||
fprintf( outfile, "\taddl $12,%%esp\n" );
|
||||
fprintf( outfile, "\tret\n" );
|
||||
output_function_size( outfile, name );
|
||||
output( "\tcall %s\n", asm_name("__wine_dll_unregister_16") );
|
||||
output( "\taddl $12,%%esp\n" );
|
||||
output( "\tret\n" );
|
||||
output_function_size( name );
|
||||
|
||||
if (target_platform == PLATFORM_APPLE)
|
||||
{
|
||||
fprintf( outfile, "\t.mod_init_func\n" );
|
||||
fprintf( outfile, "\t.align %d\n", get_alignment(4) );
|
||||
fprintf( outfile, "\t.long .L__wine_spec_%s_init\n", make_c_identifier(spec->dll_name) );
|
||||
fprintf( outfile, "\t.mod_term_func\n" );
|
||||
fprintf( outfile, "\t.align %d\n", get_alignment(4) );
|
||||
fprintf( outfile, "\t.long .L__wine_spec_%s_fini\n", make_c_identifier(spec->dll_name) );
|
||||
output( "\t.mod_init_func\n" );
|
||||
output( "\t.align %d\n", get_alignment(4) );
|
||||
output( "\t.long .L__wine_spec_%s_init\n", make_c_identifier(spec->dll_name) );
|
||||
output( "\t.mod_term_func\n" );
|
||||
output( "\t.align %d\n", get_alignment(4) );
|
||||
output( "\t.long .L__wine_spec_%s_fini\n", make_c_identifier(spec->dll_name) );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( outfile, "\t.section \".init\",\"ax\"\n" );
|
||||
fprintf( outfile, "\tcall .L__wine_spec_%s_init\n", make_c_identifier(spec->dll_name) );
|
||||
fprintf( outfile, "\t.section \".fini\",\"ax\"\n" );
|
||||
fprintf( outfile, "\tcall .L__wine_spec_%s_fini\n", make_c_identifier(spec->dll_name) );
|
||||
output( "\t.section \".init\",\"ax\"\n" );
|
||||
output( "\tcall .L__wine_spec_%s_init\n", make_c_identifier(spec->dll_name) );
|
||||
output( "\t.section \".fini\",\"ax\"\n" );
|
||||
output( "\tcall .L__wine_spec_%s_fini\n", make_c_identifier(spec->dll_name) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -525,7 +525,7 @@ static void output_init_code( FILE *outfile, const DLLSPEC *spec, const char *he
|
|||
*
|
||||
* Build a Win16 assembly file from a spec file.
|
||||
*/
|
||||
void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
|
||||
void BuildSpec16File( DLLSPEC *spec )
|
||||
{
|
||||
ORDDEF **typelist;
|
||||
int i, j, nb_funcs;
|
||||
|
@ -533,7 +533,7 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
|
|||
|
||||
/* File header */
|
||||
|
||||
output_standard_file_header( outfile );
|
||||
output_standard_file_header();
|
||||
|
||||
if (!spec->dll_name) /* set default name from file name */
|
||||
{
|
||||
|
@ -558,130 +558,130 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
|
|||
/* Output the module structure */
|
||||
|
||||
sprintf( header_name, "__wine_spec_%s_dos_header", make_c_identifier(spec->dll_name) );
|
||||
fprintf( outfile, "\n/* module data */\n\n" );
|
||||
fprintf( outfile, "\t.data\n" );
|
||||
fprintf( outfile, "\t.align %d\n", get_alignment(4) );
|
||||
fprintf( outfile, "%s:\n", header_name );
|
||||
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), /* e_magic */
|
||||
output( "\n/* module data */\n\n" );
|
||||
output( "\t.data\n" );
|
||||
output( "\t.align %d\n", get_alignment(4) );
|
||||
output( "%s:\n", header_name );
|
||||
output( "\t%s 0x%04x\n", get_asm_short_keyword(), /* e_magic */
|
||||
IMAGE_DOS_SIGNATURE );
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_cblp */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_cp */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_crlc */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_cparhdr */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_minalloc */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_maxalloc */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_ss */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_sp */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_csum */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_ip */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_cs */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_lfarlc */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_ovno */
|
||||
fprintf( outfile, "\t%s 0,0,0,0\n", get_asm_short_keyword() ); /* e_res */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_oemid */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_oeminfo */
|
||||
fprintf( outfile, "\t%s 0,0,0,0,0,0,0,0,0,0\n", get_asm_short_keyword() ); /* e_res2 */
|
||||
fprintf( outfile, "\t.long .L__wine_spec_ne_header-%s\n", header_name ); /* e_lfanew */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_cblp */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_cp */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_crlc */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_cparhdr */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_minalloc */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_maxalloc */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_ss */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_sp */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_csum */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_ip */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_cs */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_lfarlc */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_ovno */
|
||||
output( "\t%s 0,0,0,0\n", get_asm_short_keyword() ); /* e_res */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_oemid */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_oeminfo */
|
||||
output( "\t%s 0,0,0,0,0,0,0,0,0,0\n", get_asm_short_keyword() ); /* e_res2 */
|
||||
output( "\t.long .L__wine_spec_ne_header-%s\n", header_name ); /* e_lfanew */
|
||||
|
||||
fprintf( outfile, ".L__wine_spec_ne_header:\n" );
|
||||
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), /* ne_magic */
|
||||
output( ".L__wine_spec_ne_header:\n" );
|
||||
output( "\t%s 0x%04x\n", get_asm_short_keyword(), /* ne_magic */
|
||||
IMAGE_OS2_SIGNATURE );
|
||||
fprintf( outfile, "\t.byte 0\n" ); /* ne_ver */
|
||||
fprintf( outfile, "\t.byte 0\n" ); /* ne_rev */
|
||||
fprintf( outfile, "\t%s .L__wine_spec_ne_enttab-.L__wine_spec_ne_header\n", /* ne_enttab */
|
||||
output( "\t.byte 0\n" ); /* ne_ver */
|
||||
output( "\t.byte 0\n" ); /* ne_rev */
|
||||
output( "\t%s .L__wine_spec_ne_enttab-.L__wine_spec_ne_header\n", /* ne_enttab */
|
||||
get_asm_short_keyword() );
|
||||
fprintf( outfile, "\t%s .L__wine_spec_ne_enttab_end-.L__wine_spec_ne_enttab\n", /* ne_cbenttab */
|
||||
output( "\t%s .L__wine_spec_ne_enttab_end-.L__wine_spec_ne_enttab\n", /* ne_cbenttab */
|
||||
get_asm_short_keyword() );
|
||||
fprintf( outfile, "\t.long 0\n" ); /* ne_crc */
|
||||
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), /* ne_flags */
|
||||
output( "\t.long 0\n" ); /* ne_crc */
|
||||
output( "\t%s 0x%04x\n", get_asm_short_keyword(), /* ne_flags */
|
||||
NE_FFLAGS_SINGLEDATA | NE_FFLAGS_LIBMODULE );
|
||||
fprintf( outfile, "\t%s 2\n", get_asm_short_keyword() ); /* ne_autodata */
|
||||
fprintf( outfile, "\t%s %u\n", get_asm_short_keyword(), spec->heap_size ); /* ne_heap */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_stack */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* ne_csip */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* ne_sssp */
|
||||
fprintf( outfile, "\t%s 2\n", get_asm_short_keyword() ); /* ne_cseg */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_cmod */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_cbnrestab */
|
||||
fprintf( outfile, "\t%s .L__wine_spec_ne_segtab-.L__wine_spec_ne_header\n", /* ne_segtab */
|
||||
output( "\t%s 2\n", get_asm_short_keyword() ); /* ne_autodata */
|
||||
output( "\t%s %u\n", get_asm_short_keyword(), spec->heap_size ); /* ne_heap */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_stack */
|
||||
output( "\t.long 0\n" ); /* ne_csip */
|
||||
output( "\t.long 0\n" ); /* ne_sssp */
|
||||
output( "\t%s 2\n", get_asm_short_keyword() ); /* ne_cseg */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_cmod */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_cbnrestab */
|
||||
output( "\t%s .L__wine_spec_ne_segtab-.L__wine_spec_ne_header\n", /* ne_segtab */
|
||||
get_asm_short_keyword() );
|
||||
fprintf( outfile, "\t%s .L__wine_spec_ne_rsrctab-.L__wine_spec_ne_header\n", /* ne_rsrctab */
|
||||
output( "\t%s .L__wine_spec_ne_rsrctab-.L__wine_spec_ne_header\n", /* ne_rsrctab */
|
||||
get_asm_short_keyword() );
|
||||
fprintf( outfile, "\t%s .L__wine_spec_ne_restab-.L__wine_spec_ne_header\n", /* ne_restab */
|
||||
output( "\t%s .L__wine_spec_ne_restab-.L__wine_spec_ne_header\n", /* ne_restab */
|
||||
get_asm_short_keyword() );
|
||||
fprintf( outfile, "\t%s .L__wine_spec_ne_modtab-.L__wine_spec_ne_header\n", /* ne_modtab */
|
||||
output( "\t%s .L__wine_spec_ne_modtab-.L__wine_spec_ne_header\n", /* ne_modtab */
|
||||
get_asm_short_keyword() );
|
||||
fprintf( outfile, "\t%s .L__wine_spec_ne_imptab-.L__wine_spec_ne_header\n", /* ne_imptab */
|
||||
output( "\t%s .L__wine_spec_ne_imptab-.L__wine_spec_ne_header\n", /* ne_imptab */
|
||||
get_asm_short_keyword() );
|
||||
fprintf( outfile, "\t.long 0\n" ); /* ne_nrestab */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_cmovent */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_align */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_cres */
|
||||
fprintf( outfile, "\t.byte 0x%02x\n", NE_OSFLAGS_WINDOWS ); /* ne_exetyp */
|
||||
fprintf( outfile, "\t.byte 0x%02x\n", NE_AFLAGS_FASTLOAD ); /* ne_flagsothers */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_pretthunks */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_psegrefbytes */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_swaparea */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_expver */
|
||||
output( "\t.long 0\n" ); /* ne_nrestab */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_cmovent */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_align */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_cres */
|
||||
output( "\t.byte 0x%02x\n", NE_OSFLAGS_WINDOWS ); /* ne_exetyp */
|
||||
output( "\t.byte 0x%02x\n", NE_AFLAGS_FASTLOAD ); /* ne_flagsothers */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_pretthunks */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_psegrefbytes */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_swaparea */
|
||||
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_expver */
|
||||
|
||||
/* segment table */
|
||||
|
||||
fprintf( outfile, "\n.L__wine_spec_ne_segtab:\n" );
|
||||
output( "\n.L__wine_spec_ne_segtab:\n" );
|
||||
|
||||
/* code segment entry */
|
||||
|
||||
fprintf( outfile, "\t%s .L__wine_spec_code_segment-%s\n", /* filepos */
|
||||
output( "\t%s .L__wine_spec_code_segment-%s\n", /* filepos */
|
||||
get_asm_short_keyword(), header_name );
|
||||
fprintf( outfile, "\t%s .L__wine_spec_code_segment_end-.L__wine_spec_code_segment\n", /* size */
|
||||
output( "\t%s .L__wine_spec_code_segment_end-.L__wine_spec_code_segment\n", /* size */
|
||||
get_asm_short_keyword() );
|
||||
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), NE_SEGFLAGS_32BIT ); /* flags */
|
||||
fprintf( outfile, "\t%s .L__wine_spec_code_segment_end-.L__wine_spec_code_segment\n", /* minsize */
|
||||
output( "\t%s 0x%04x\n", get_asm_short_keyword(), NE_SEGFLAGS_32BIT ); /* flags */
|
||||
output( "\t%s .L__wine_spec_code_segment_end-.L__wine_spec_code_segment\n", /* minsize */
|
||||
get_asm_short_keyword() );
|
||||
|
||||
/* data segment entry */
|
||||
|
||||
fprintf( outfile, "\t%s .L__wine_spec_data_segment-%s\n", /* filepos */
|
||||
output( "\t%s .L__wine_spec_data_segment-%s\n", /* filepos */
|
||||
get_asm_short_keyword(), header_name );
|
||||
fprintf( outfile, "\t%s .L__wine_spec_data_segment_end-.L__wine_spec_data_segment\n", /* size */
|
||||
output( "\t%s .L__wine_spec_data_segment_end-.L__wine_spec_data_segment\n", /* size */
|
||||
get_asm_short_keyword() );
|
||||
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), NE_SEGFLAGS_DATA ); /* flags */
|
||||
fprintf( outfile, "\t%s .L__wine_spec_data_segment_end-.L__wine_spec_data_segment\n", /* minsize */
|
||||
output( "\t%s 0x%04x\n", get_asm_short_keyword(), NE_SEGFLAGS_DATA ); /* flags */
|
||||
output( "\t%s .L__wine_spec_data_segment_end-.L__wine_spec_data_segment\n", /* minsize */
|
||||
get_asm_short_keyword() );
|
||||
|
||||
/* resource directory */
|
||||
|
||||
output_res16_directory( outfile, spec, header_name );
|
||||
output_res16_directory( spec, header_name );
|
||||
|
||||
/* resident names table */
|
||||
|
||||
fprintf( outfile, "\n\t.align %d\n", get_alignment(2) );
|
||||
fprintf( outfile, ".L__wine_spec_ne_restab:\n" );
|
||||
output_resident_name( outfile, spec->dll_name, 0 );
|
||||
output( "\n\t.align %d\n", get_alignment(2) );
|
||||
output( ".L__wine_spec_ne_restab:\n" );
|
||||
output_resident_name( spec->dll_name, 0 );
|
||||
for (i = 1; i <= spec->limit; i++)
|
||||
{
|
||||
ORDDEF *odp = spec->ordinals[i];
|
||||
if (!odp || !odp->name[0]) continue;
|
||||
output_resident_name( outfile, odp->name, i );
|
||||
output_resident_name( odp->name, i );
|
||||
}
|
||||
fprintf( outfile, "\t.byte 0\n" );
|
||||
output( "\t.byte 0\n" );
|
||||
|
||||
/* imported names table */
|
||||
|
||||
fprintf( outfile, "\n\t.align %d\n", get_alignment(2) );
|
||||
fprintf( outfile, ".L__wine_spec_ne_modtab:\n" );
|
||||
fprintf( outfile, ".L__wine_spec_ne_imptab:\n" );
|
||||
fprintf( outfile, "\t.byte 0,0\n" );
|
||||
output( "\n\t.align %d\n", get_alignment(2) );
|
||||
output( ".L__wine_spec_ne_modtab:\n" );
|
||||
output( ".L__wine_spec_ne_imptab:\n" );
|
||||
output( "\t.byte 0,0\n" );
|
||||
|
||||
/* entry table */
|
||||
|
||||
fprintf( outfile, "\n.L__wine_spec_ne_enttab:\n" );
|
||||
output_entry_table( outfile, spec );
|
||||
fprintf( outfile, ".L__wine_spec_ne_enttab_end:\n" );
|
||||
output( "\n.L__wine_spec_ne_enttab:\n" );
|
||||
output_entry_table( spec );
|
||||
output( ".L__wine_spec_ne_enttab_end:\n" );
|
||||
|
||||
/* code segment */
|
||||
|
||||
fprintf( outfile, "\n\t.align %d\n", get_alignment(2) );
|
||||
fprintf( outfile, ".L__wine_spec_code_segment:\n" );
|
||||
output( "\n\t.align %d\n", get_alignment(2) );
|
||||
output( ".L__wine_spec_code_segment:\n" );
|
||||
|
||||
for ( i = 0; i < nb_funcs; i++ )
|
||||
{
|
||||
|
@ -709,9 +709,9 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
|
|||
}
|
||||
if (typelist[i]->type == TYPE_VARARGS) arg_types[j / 10] |= ARG_VARARG << (3 * (j % 10));
|
||||
|
||||
fprintf( outfile, ".L__wine_spec_callfrom16_%s:\n", get_callfrom16_name(typelist[i]) );
|
||||
fprintf( outfile, "\tpushl $.L__wine_spec_call16_%s\n", get_relay_name(typelist[i]) );
|
||||
fprintf( outfile, "\tlcall $0,$0\n" );
|
||||
output( ".L__wine_spec_callfrom16_%s:\n", get_callfrom16_name(typelist[i]) );
|
||||
output( "\tpushl $.L__wine_spec_call16_%s\n", get_relay_name(typelist[i]) );
|
||||
output( "\tlcall $0,$0\n" );
|
||||
|
||||
if (typelist[i]->flags & FLAG_REGISTER)
|
||||
{
|
||||
|
@ -719,91 +719,91 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
|
|||
}
|
||||
else if (typelist[i]->flags & FLAG_RET16)
|
||||
{
|
||||
fprintf( outfile, "\torw %%ax,%%ax\n" );
|
||||
fprintf( outfile, "\tnop\n" ); /* so that the lretw is aligned */
|
||||
output( "\torw %%ax,%%ax\n" );
|
||||
output( "\tnop\n" ); /* so that the lretw is aligned */
|
||||
nop_words = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( outfile, "\tshld $16,%%eax,%%edx\n" );
|
||||
fprintf( outfile, "\torl %%eax,%%eax\n" );
|
||||
output( "\tshld $16,%%eax,%%edx\n" );
|
||||
output( "\torl %%eax,%%eax\n" );
|
||||
nop_words = 1;
|
||||
}
|
||||
|
||||
if (argsize)
|
||||
{
|
||||
fprintf( outfile, "\tlretw $%u\n", argsize );
|
||||
output( "\tlretw $%u\n", argsize );
|
||||
nop_words--;
|
||||
}
|
||||
else fprintf( outfile, "\tlretw\n" );
|
||||
else output( "\tlretw\n" );
|
||||
|
||||
if (nop_words) fprintf( outfile, "\t%s\n", nop_sequence[nop_words-1] );
|
||||
if (nop_words) output( "\t%s\n", nop_sequence[nop_words-1] );
|
||||
|
||||
/* the movl is here so that the code contains only valid instructions, */
|
||||
/* it's never actually executed, we only care about the arg_types[] values */
|
||||
fprintf( outfile, "\t%s 0x86c7\n", get_asm_short_keyword() );
|
||||
fprintf( outfile, "\t.long 0x%08x,0x%08x\n", arg_types[0], arg_types[1] );
|
||||
output( "\t%s 0x86c7\n", get_asm_short_keyword() );
|
||||
output( "\t.long 0x%08x,0x%08x\n", arg_types[0], arg_types[1] );
|
||||
}
|
||||
|
||||
for (i = 0; i <= spec->limit; i++)
|
||||
{
|
||||
ORDDEF *odp = spec->ordinals[i];
|
||||
if (!odp || !is_function( odp )) continue;
|
||||
fprintf( outfile, ".L__wine_%s_%u:\n", make_c_identifier(spec->dll_name), i );
|
||||
fprintf( outfile, "\tpushw %%bp\n" );
|
||||
fprintf( outfile, "\tpushl $%s\n",
|
||||
output( ".L__wine_%s_%u:\n", make_c_identifier(spec->dll_name), i );
|
||||
output( "\tpushw %%bp\n" );
|
||||
output( "\tpushl $%s\n",
|
||||
asm_name( odp->type == TYPE_STUB ? get_stub_name( odp, spec ) : odp->link_name ));
|
||||
fprintf( outfile, "\tcallw .L__wine_spec_callfrom16_%s\n", get_callfrom16_name( odp ) );
|
||||
output( "\tcallw .L__wine_spec_callfrom16_%s\n", get_callfrom16_name( odp ) );
|
||||
}
|
||||
fprintf( outfile, ".L__wine_spec_code_segment_end:\n" );
|
||||
output( ".L__wine_spec_code_segment_end:\n" );
|
||||
|
||||
/* data segment */
|
||||
|
||||
fprintf( outfile, "\n.L__wine_spec_data_segment:\n" );
|
||||
fprintf( outfile, "\t.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n" ); /* instance data */
|
||||
output( "\n.L__wine_spec_data_segment:\n" );
|
||||
output( "\t.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n" ); /* instance data */
|
||||
for (i = 0; i <= spec->limit; i++)
|
||||
{
|
||||
ORDDEF *odp = spec->ordinals[i];
|
||||
if (!odp || odp->type != TYPE_VARIABLE) continue;
|
||||
fprintf( outfile, ".L__wine_%s_%u:\n", make_c_identifier(spec->dll_name), i );
|
||||
fprintf( outfile, "\t.long " );
|
||||
output( ".L__wine_%s_%u:\n", make_c_identifier(spec->dll_name), i );
|
||||
output( "\t.long " );
|
||||
for (j = 0; j < odp->u.var.n_values-1; j++)
|
||||
fprintf( outfile, "0x%08x,", odp->u.var.values[j] );
|
||||
fprintf( outfile, "0x%08x\n", odp->u.var.values[j] );
|
||||
output( "0x%08x,", odp->u.var.values[j] );
|
||||
output( "0x%08x\n", odp->u.var.values[j] );
|
||||
}
|
||||
fprintf( outfile, ".L__wine_spec_data_segment_end:\n" );
|
||||
output( ".L__wine_spec_data_segment_end:\n" );
|
||||
|
||||
/* resource data */
|
||||
|
||||
if (spec->nb_resources)
|
||||
{
|
||||
fprintf( outfile, "\n.L__wine_spec_resource_data:\n" );
|
||||
output_res16_data( outfile, spec );
|
||||
output( "\n.L__wine_spec_resource_data:\n" );
|
||||
output_res16_data( spec );
|
||||
}
|
||||
|
||||
fprintf( outfile, "\t.byte 0\n" ); /* make sure the last symbol points to something */
|
||||
output( "\t.byte 0\n" ); /* make sure the last symbol points to something */
|
||||
|
||||
/* relay functions */
|
||||
|
||||
nb_funcs = sort_func_list( typelist, nb_funcs, relay_type_compare );
|
||||
if (nb_funcs)
|
||||
{
|
||||
fprintf( outfile, "\n/* relay functions */\n\n" );
|
||||
fprintf( outfile, "\t.text\n" );
|
||||
for ( i = 0; i < nb_funcs; i++ ) output_call16_function( outfile, typelist[i] );
|
||||
fprintf( outfile, "\t.data\n" );
|
||||
fprintf( outfile, "wine_ldt_copy_ptr:\n" );
|
||||
fprintf( outfile, "\t.long %s\n", asm_name("wine_ldt_copy") );
|
||||
output( "\n/* relay functions */\n\n" );
|
||||
output( "\t.text\n" );
|
||||
for ( i = 0; i < nb_funcs; i++ ) output_call16_function( typelist[i] );
|
||||
output( "\t.data\n" );
|
||||
output( "wine_ldt_copy_ptr:\n" );
|
||||
output( "\t.long %s\n", asm_name("wine_ldt_copy") );
|
||||
}
|
||||
|
||||
fprintf( outfile, "\n\t%s\n", get_asm_string_section() );
|
||||
fprintf( outfile, ".L__wine_spec_file_name:\n" );
|
||||
fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name );
|
||||
output( "\n\t%s\n", get_asm_string_section() );
|
||||
output( ".L__wine_spec_file_name:\n" );
|
||||
output( "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name );
|
||||
|
||||
output_stubs( outfile, spec );
|
||||
output_get_pc_thunk( outfile );
|
||||
output_init_code( outfile, spec, header_name );
|
||||
output_gnu_stack_note( outfile );
|
||||
output_stubs( spec );
|
||||
output_get_pc_thunk();
|
||||
output_init_code( spec, header_name );
|
||||
output_gnu_stack_note();
|
||||
|
||||
free( typelist );
|
||||
}
|
||||
|
|
|
@ -68,30 +68,30 @@ int has_relays( DLLSPEC *spec )
|
|||
*
|
||||
* Output entry points for relay debugging
|
||||
*/
|
||||
static void output_relay_debug( FILE *outfile, DLLSPEC *spec )
|
||||
static void output_relay_debug( DLLSPEC *spec )
|
||||
{
|
||||
unsigned int i, j, args, flags;
|
||||
|
||||
/* first the table of entry point offsets */
|
||||
|
||||
fprintf( outfile, "\t%s\n", get_asm_rodata_section() );
|
||||
fprintf( outfile, "\t.align %d\n", get_alignment(4) );
|
||||
fprintf( outfile, ".L__wine_spec_relay_entry_point_offsets:\n" );
|
||||
output( "\t%s\n", get_asm_rodata_section() );
|
||||
output( "\t.align %d\n", get_alignment(4) );
|
||||
output( ".L__wine_spec_relay_entry_point_offsets:\n" );
|
||||
|
||||
for (i = spec->base; i <= spec->limit; i++)
|
||||
{
|
||||
ORDDEF *odp = spec->ordinals[i];
|
||||
|
||||
if (needs_relay( odp ))
|
||||
fprintf( outfile, "\t.long .L__wine_spec_relay_entry_point_%d-__wine_spec_relay_entry_points\n", i );
|
||||
output( "\t.long .L__wine_spec_relay_entry_point_%d-__wine_spec_relay_entry_points\n", i );
|
||||
else
|
||||
fprintf( outfile, "\t.long 0\n" );
|
||||
output( "\t.long 0\n" );
|
||||
}
|
||||
|
||||
/* then the table of argument types */
|
||||
|
||||
fprintf( outfile, "\t.align %d\n", get_alignment(4) );
|
||||
fprintf( outfile, ".L__wine_spec_relay_arg_types:\n" );
|
||||
output( "\t.align %d\n", get_alignment(4) );
|
||||
output( ".L__wine_spec_relay_arg_types:\n" );
|
||||
|
||||
for (i = spec->base; i <= spec->limit; i++)
|
||||
{
|
||||
|
@ -106,14 +106,14 @@ static void output_relay_debug( FILE *outfile, DLLSPEC *spec )
|
|||
if (odp->u.func.arg_types[j] == 'W') mask |= 2<< (j*2);
|
||||
}
|
||||
}
|
||||
fprintf( outfile, "\t.long 0x%08x\n", mask );
|
||||
output( "\t.long 0x%08x\n", mask );
|
||||
}
|
||||
|
||||
/* then the relay thunks */
|
||||
|
||||
fprintf( outfile, "\t.text\n" );
|
||||
fprintf( outfile, "__wine_spec_relay_entry_points:\n" );
|
||||
fprintf( outfile, "\tnop\n" ); /* to avoid 0 offset */
|
||||
output( "\t.text\n" );
|
||||
output( "__wine_spec_relay_entry_points:\n" );
|
||||
output( "\tnop\n" ); /* to avoid 0 offset */
|
||||
|
||||
for (i = spec->base; i <= spec->limit; i++)
|
||||
{
|
||||
|
@ -121,39 +121,39 @@ static void output_relay_debug( FILE *outfile, DLLSPEC *spec )
|
|||
|
||||
if (!needs_relay( odp )) continue;
|
||||
|
||||
fprintf( outfile, "\t.align %d\n", get_alignment(4) );
|
||||
fprintf( outfile, ".L__wine_spec_relay_entry_point_%d:\n", i );
|
||||
output( "\t.align %d\n", get_alignment(4) );
|
||||
output( ".L__wine_spec_relay_entry_point_%d:\n", i );
|
||||
|
||||
if (odp->flags & FLAG_REGISTER)
|
||||
fprintf( outfile, "\tpushl %%eax\n" );
|
||||
output( "\tpushl %%eax\n" );
|
||||
else
|
||||
fprintf( outfile, "\tpushl %%esp\n" );
|
||||
output( "\tpushl %%esp\n" );
|
||||
|
||||
args = strlen(odp->u.func.arg_types);
|
||||
flags = 0;
|
||||
if (odp->flags & FLAG_RET64) flags |= 1;
|
||||
if (odp->type == TYPE_STDCALL) flags |= 2;
|
||||
fprintf( outfile, "\tpushl $%u\n", (flags << 24) | (args << 16) | (i - spec->base) );
|
||||
output( "\tpushl $%u\n", (flags << 24) | (args << 16) | (i - spec->base) );
|
||||
|
||||
if (UsePIC)
|
||||
{
|
||||
fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
|
||||
fprintf( outfile, "1:\tleal .L__wine_spec_relay_descr-1b(%%eax),%%eax\n" );
|
||||
output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
|
||||
output( "1:\tleal .L__wine_spec_relay_descr-1b(%%eax),%%eax\n" );
|
||||
}
|
||||
else fprintf( outfile, "\tmovl $.L__wine_spec_relay_descr,%%eax\n" );
|
||||
fprintf( outfile, "\tpushl %%eax\n" );
|
||||
else output( "\tmovl $.L__wine_spec_relay_descr,%%eax\n" );
|
||||
output( "\tpushl %%eax\n" );
|
||||
|
||||
if (odp->flags & FLAG_REGISTER)
|
||||
{
|
||||
fprintf( outfile, "\tcall *8(%%eax)\n" );
|
||||
output( "\tcall *8(%%eax)\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( outfile, "\tcall *4(%%eax)\n" );
|
||||
output( "\tcall *4(%%eax)\n" );
|
||||
if (odp->type == TYPE_STDCALL)
|
||||
fprintf( outfile, "\tret $%u\n", args * get_ptr_size() );
|
||||
output( "\tret $%u\n", args * get_ptr_size() );
|
||||
else
|
||||
fprintf( outfile, "\tret\n" );
|
||||
output( "\tret\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -163,46 +163,46 @@ static void output_relay_debug( FILE *outfile, DLLSPEC *spec )
|
|||
*
|
||||
* Output the export table for a Win32 module.
|
||||
*/
|
||||
static void output_exports( FILE *outfile, DLLSPEC *spec )
|
||||
static void output_exports( DLLSPEC *spec )
|
||||
{
|
||||
int i, fwd_size = 0;
|
||||
int nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
|
||||
|
||||
if (!nr_exports) return;
|
||||
|
||||
fprintf( outfile, "\n/* export table */\n\n" );
|
||||
fprintf( outfile, "\t.data\n" );
|
||||
fprintf( outfile, "\t.align %d\n", get_alignment(4) );
|
||||
fprintf( outfile, ".L__wine_spec_exports:\n" );
|
||||
output( "\n/* export table */\n\n" );
|
||||
output( "\t.data\n" );
|
||||
output( "\t.align %d\n", get_alignment(4) );
|
||||
output( ".L__wine_spec_exports:\n" );
|
||||
|
||||
/* export directory header */
|
||||
|
||||
fprintf( outfile, "\t.long 0\n" ); /* Characteristics */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* TimeDateStamp */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* MajorVersion/MinorVersion */
|
||||
fprintf( outfile, "\t.long .L__wine_spec_exp_names-.L__wine_spec_rva_base\n" ); /* Name */
|
||||
fprintf( outfile, "\t.long %u\n", spec->base ); /* Base */
|
||||
fprintf( outfile, "\t.long %u\n", nr_exports ); /* NumberOfFunctions */
|
||||
fprintf( outfile, "\t.long %u\n", spec->nb_names ); /* NumberOfNames */
|
||||
fprintf( outfile, "\t.long .L__wine_spec_exports_funcs-.L__wine_spec_rva_base\n" ); /* AddressOfFunctions */
|
||||
output( "\t.long 0\n" ); /* Characteristics */
|
||||
output( "\t.long 0\n" ); /* TimeDateStamp */
|
||||
output( "\t.long 0\n" ); /* MajorVersion/MinorVersion */
|
||||
output( "\t.long .L__wine_spec_exp_names-.L__wine_spec_rva_base\n" ); /* Name */
|
||||
output( "\t.long %u\n", spec->base ); /* Base */
|
||||
output( "\t.long %u\n", nr_exports ); /* NumberOfFunctions */
|
||||
output( "\t.long %u\n", spec->nb_names ); /* NumberOfNames */
|
||||
output( "\t.long .L__wine_spec_exports_funcs-.L__wine_spec_rva_base\n" ); /* AddressOfFunctions */
|
||||
if (spec->nb_names)
|
||||
{
|
||||
fprintf( outfile, "\t.long .L__wine_spec_exp_name_ptrs-.L__wine_spec_rva_base\n" ); /* AddressOfNames */
|
||||
fprintf( outfile, "\t.long .L__wine_spec_exp_ordinals-.L__wine_spec_rva_base\n" ); /* AddressOfNameOrdinals */
|
||||
output( "\t.long .L__wine_spec_exp_name_ptrs-.L__wine_spec_rva_base\n" ); /* AddressOfNames */
|
||||
output( "\t.long .L__wine_spec_exp_ordinals-.L__wine_spec_rva_base\n" ); /* AddressOfNameOrdinals */
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( outfile, "\t.long 0\n" ); /* AddressOfNames */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* AddressOfNameOrdinals */
|
||||
output( "\t.long 0\n" ); /* AddressOfNames */
|
||||
output( "\t.long 0\n" ); /* AddressOfNameOrdinals */
|
||||
}
|
||||
|
||||
/* output the function pointers */
|
||||
|
||||
fprintf( outfile, "\n.L__wine_spec_exports_funcs:\n" );
|
||||
output( "\n.L__wine_spec_exports_funcs:\n" );
|
||||
for (i = spec->base; i <= spec->limit; i++)
|
||||
{
|
||||
ORDDEF *odp = spec->ordinals[i];
|
||||
if (!odp) fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );
|
||||
if (!odp) output( "\t%s 0\n", get_asm_ptr_keyword() );
|
||||
else switch(odp->type)
|
||||
{
|
||||
case TYPE_EXTERN:
|
||||
|
@ -211,21 +211,21 @@ static void output_exports( FILE *outfile, DLLSPEC *spec )
|
|||
case TYPE_CDECL:
|
||||
if (odp->flags & FLAG_FORWARD)
|
||||
{
|
||||
fprintf( outfile, "\t%s .L__wine_spec_forwards+%u\n", get_asm_ptr_keyword(), fwd_size );
|
||||
output( "\t%s .L__wine_spec_forwards+%u\n", get_asm_ptr_keyword(), fwd_size );
|
||||
fwd_size += strlen(odp->link_name) + 1;
|
||||
}
|
||||
else if (odp->flags & FLAG_EXT_LINK)
|
||||
{
|
||||
fprintf( outfile, "\t%s %s_%s\n",
|
||||
output( "\t%s %s_%s\n",
|
||||
get_asm_ptr_keyword(), asm_name("__wine_spec_ext_link"), odp->link_name );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( outfile, "\t%s %s\n", get_asm_ptr_keyword(), asm_name(odp->link_name) );
|
||||
output( "\t%s %s\n", get_asm_ptr_keyword(), asm_name(odp->link_name) );
|
||||
}
|
||||
break;
|
||||
case TYPE_STUB:
|
||||
fprintf( outfile, "\t%s %s\n", get_asm_ptr_keyword(),
|
||||
output( "\t%s %s\n", get_asm_ptr_keyword(),
|
||||
asm_name( get_stub_name( odp, spec )) );
|
||||
break;
|
||||
default:
|
||||
|
@ -239,68 +239,68 @@ static void output_exports( FILE *outfile, DLLSPEC *spec )
|
|||
|
||||
int namepos = strlen(spec->file_name) + 1;
|
||||
|
||||
fprintf( outfile, "\n.L__wine_spec_exp_name_ptrs:\n" );
|
||||
output( "\n.L__wine_spec_exp_name_ptrs:\n" );
|
||||
for (i = 0; i < spec->nb_names; i++)
|
||||
{
|
||||
fprintf( outfile, "\t.long .L__wine_spec_exp_names+%u-.L__wine_spec_rva_base\n", namepos );
|
||||
output( "\t.long .L__wine_spec_exp_names+%u-.L__wine_spec_rva_base\n", namepos );
|
||||
namepos += strlen(spec->names[i]->name) + 1;
|
||||
}
|
||||
|
||||
/* output the function ordinals */
|
||||
|
||||
fprintf( outfile, "\n.L__wine_spec_exp_ordinals:\n" );
|
||||
output( "\n.L__wine_spec_exp_ordinals:\n" );
|
||||
for (i = 0; i < spec->nb_names; i++)
|
||||
{
|
||||
fprintf( outfile, "\t%s %d\n",
|
||||
output( "\t%s %d\n",
|
||||
get_asm_short_keyword(), spec->names[i]->ordinal - spec->base );
|
||||
}
|
||||
if (spec->nb_names % 2)
|
||||
{
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() );
|
||||
output( "\t%s 0\n", get_asm_short_keyword() );
|
||||
}
|
||||
}
|
||||
|
||||
/* output the export name strings */
|
||||
|
||||
fprintf( outfile, "\n.L__wine_spec_exp_names:\n" );
|
||||
fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name );
|
||||
output( "\n.L__wine_spec_exp_names:\n" );
|
||||
output( "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name );
|
||||
for (i = 0; i < spec->nb_names; i++)
|
||||
fprintf( outfile, "\t%s \"%s\"\n",
|
||||
output( "\t%s \"%s\"\n",
|
||||
get_asm_string_keyword(), spec->names[i]->name );
|
||||
|
||||
/* output forward strings */
|
||||
|
||||
if (fwd_size)
|
||||
{
|
||||
fprintf( outfile, "\n.L__wine_spec_forwards:\n" );
|
||||
output( "\n.L__wine_spec_forwards:\n" );
|
||||
for (i = spec->base; i <= spec->limit; i++)
|
||||
{
|
||||
ORDDEF *odp = spec->ordinals[i];
|
||||
if (odp && (odp->flags & FLAG_FORWARD))
|
||||
fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), odp->link_name );
|
||||
output( "\t%s \"%s\"\n", get_asm_string_keyword(), odp->link_name );
|
||||
}
|
||||
}
|
||||
fprintf( outfile, "\t.align %d\n", get_alignment(get_ptr_size()) );
|
||||
fprintf( outfile, ".L__wine_spec_exports_end:\n" );
|
||||
output( "\t.align %d\n", get_alignment(get_ptr_size()) );
|
||||
output( ".L__wine_spec_exports_end:\n" );
|
||||
|
||||
/* output relays */
|
||||
|
||||
/* we only support relay debugging on i386 */
|
||||
if (target_cpu != CPU_x86)
|
||||
{
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );
|
||||
output( "\t%s 0\n", get_asm_ptr_keyword() );
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf( outfile, ".L__wine_spec_relay_descr:\n" );
|
||||
fprintf( outfile, "\t%s 0xdeb90001\n", get_asm_ptr_keyword() ); /* magic */
|
||||
fprintf( outfile, "\t%s 0,0\n", get_asm_ptr_keyword() ); /* relay funcs */
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() ); /* private data */
|
||||
fprintf( outfile, "\t%s __wine_spec_relay_entry_points\n", get_asm_ptr_keyword() );
|
||||
fprintf( outfile, "\t%s .L__wine_spec_relay_entry_point_offsets\n", get_asm_ptr_keyword() );
|
||||
fprintf( outfile, "\t%s .L__wine_spec_relay_arg_types\n", get_asm_ptr_keyword() );
|
||||
output( ".L__wine_spec_relay_descr:\n" );
|
||||
output( "\t%s 0xdeb90001\n", get_asm_ptr_keyword() ); /* magic */
|
||||
output( "\t%s 0,0\n", get_asm_ptr_keyword() ); /* relay funcs */
|
||||
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* private data */
|
||||
output( "\t%s __wine_spec_relay_entry_points\n", get_asm_ptr_keyword() );
|
||||
output( "\t%s .L__wine_spec_relay_entry_point_offsets\n", get_asm_ptr_keyword() );
|
||||
output( "\t%s .L__wine_spec_relay_arg_types\n", get_asm_ptr_keyword() );
|
||||
|
||||
output_relay_debug( outfile, spec );
|
||||
output_relay_debug( spec );
|
||||
}
|
||||
|
||||
|
||||
|
@ -309,33 +309,33 @@ static void output_exports( FILE *outfile, DLLSPEC *spec )
|
|||
*
|
||||
* Output code for calling a dll constructor.
|
||||
*/
|
||||
static void output_asm_constructor( FILE *outfile, const char *constructor )
|
||||
static void output_asm_constructor( const char *constructor )
|
||||
{
|
||||
if (target_platform == PLATFORM_APPLE)
|
||||
{
|
||||
/* Mach-O doesn't have an init section */
|
||||
fprintf( outfile, "\n\t.mod_init_func\n" );
|
||||
fprintf( outfile, "\t.align %d\n", get_alignment(4) );
|
||||
fprintf( outfile, "\t.long %s\n", asm_name(constructor) );
|
||||
output( "\n\t.mod_init_func\n" );
|
||||
output( "\t.align %d\n", get_alignment(4) );
|
||||
output( "\t.long %s\n", asm_name(constructor) );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( outfile, "\n\t.section \".init\",\"ax\"\n" );
|
||||
output( "\n\t.section \".init\",\"ax\"\n" );
|
||||
switch(target_cpu)
|
||||
{
|
||||
case CPU_x86:
|
||||
case CPU_x86_64:
|
||||
fprintf( outfile, "\tcall %s\n", asm_name(constructor) );
|
||||
output( "\tcall %s\n", asm_name(constructor) );
|
||||
break;
|
||||
case CPU_SPARC:
|
||||
fprintf( outfile, "\tcall %s\n", asm_name(constructor) );
|
||||
fprintf( outfile, "\tnop\n" );
|
||||
output( "\tcall %s\n", asm_name(constructor) );
|
||||
output( "\tnop\n" );
|
||||
break;
|
||||
case CPU_ALPHA:
|
||||
fprintf( outfile, "\tjsr $26,%s\n", asm_name(constructor) );
|
||||
output( "\tjsr $26,%s\n", asm_name(constructor) );
|
||||
break;
|
||||
case CPU_POWERPC:
|
||||
fprintf( outfile, "\tbl %s\n", asm_name(constructor) );
|
||||
output( "\tbl %s\n", asm_name(constructor) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -347,32 +347,32 @@ static void output_asm_constructor( FILE *outfile, const char *constructor )
|
|||
*
|
||||
* Build a Win32 C file from a spec file.
|
||||
*/
|
||||
void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
|
||||
void BuildSpec32File( DLLSPEC *spec )
|
||||
{
|
||||
int machine = 0;
|
||||
unsigned int page_size = get_page_size();
|
||||
|
||||
resolve_imports( spec );
|
||||
output_standard_file_header( outfile );
|
||||
output_standard_file_header();
|
||||
|
||||
/* Reserve some space for the PE header */
|
||||
|
||||
fprintf( outfile, "\t.text\n" );
|
||||
fprintf( outfile, "\t.align %d\n", get_alignment(page_size) );
|
||||
fprintf( outfile, "__wine_spec_pe_header:\n" );
|
||||
output( "\t.text\n" );
|
||||
output( "\t.align %d\n", get_alignment(page_size) );
|
||||
output( "__wine_spec_pe_header:\n" );
|
||||
if (target_platform == PLATFORM_APPLE)
|
||||
fprintf( outfile, "\t.space 65536\n" );
|
||||
output( "\t.space 65536\n" );
|
||||
else
|
||||
fprintf( outfile, "\t.skip 65536\n" );
|
||||
output( "\t.skip 65536\n" );
|
||||
|
||||
/* Output the NT header */
|
||||
|
||||
fprintf( outfile, "\n\t.data\n" );
|
||||
fprintf( outfile, "\t.align %d\n", get_alignment(get_ptr_size()) );
|
||||
fprintf( outfile, "%s\n", asm_globl("__wine_spec_nt_header") );
|
||||
fprintf( outfile, ".L__wine_spec_rva_base:\n" );
|
||||
output( "\n\t.data\n" );
|
||||
output( "\t.align %d\n", get_alignment(get_ptr_size()) );
|
||||
output( "%s\n", asm_globl("__wine_spec_nt_header") );
|
||||
output( ".L__wine_spec_rva_base:\n" );
|
||||
|
||||
fprintf( outfile, "\t.long 0x%04x\n", IMAGE_NT_SIGNATURE ); /* Signature */
|
||||
output( "\t.long 0x%04x\n", IMAGE_NT_SIGNATURE ); /* Signature */
|
||||
switch(target_cpu)
|
||||
{
|
||||
case CPU_x86: machine = IMAGE_FILE_MACHINE_I386; break;
|
||||
|
@ -381,105 +381,105 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
|
|||
case CPU_ALPHA: machine = IMAGE_FILE_MACHINE_ALPHA; break;
|
||||
case CPU_SPARC: machine = IMAGE_FILE_MACHINE_UNKNOWN; break;
|
||||
}
|
||||
fprintf( outfile, "\t%s 0x%04x\n", /* Machine */
|
||||
output( "\t%s 0x%04x\n", /* Machine */
|
||||
get_asm_short_keyword(), machine );
|
||||
fprintf( outfile, "\t%s 0\n", /* NumberOfSections */
|
||||
output( "\t%s 0\n", /* NumberOfSections */
|
||||
get_asm_short_keyword() );
|
||||
fprintf( outfile, "\t.long 0\n" ); /* TimeDateStamp */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* PointerToSymbolTable */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* NumberOfSymbols */
|
||||
fprintf( outfile, "\t%s %d\n", /* SizeOfOptionalHeader */
|
||||
output( "\t.long 0\n" ); /* TimeDateStamp */
|
||||
output( "\t.long 0\n" ); /* PointerToSymbolTable */
|
||||
output( "\t.long 0\n" ); /* NumberOfSymbols */
|
||||
output( "\t%s %d\n", /* SizeOfOptionalHeader */
|
||||
get_asm_short_keyword(),
|
||||
get_ptr_size() == 8 ? IMAGE_SIZEOF_NT_OPTIONAL64_HEADER : IMAGE_SIZEOF_NT_OPTIONAL32_HEADER );
|
||||
fprintf( outfile, "\t%s 0x%04x\n", /* Characteristics */
|
||||
output( "\t%s 0x%04x\n", /* Characteristics */
|
||||
get_asm_short_keyword(), spec->characteristics );
|
||||
fprintf( outfile, "\t%s 0x%04x\n", /* Magic */
|
||||
output( "\t%s 0x%04x\n", /* Magic */
|
||||
get_asm_short_keyword(),
|
||||
get_ptr_size() == 8 ? IMAGE_NT_OPTIONAL_HDR64_MAGIC : IMAGE_NT_OPTIONAL_HDR32_MAGIC );
|
||||
fprintf( outfile, "\t.byte 0\n" ); /* MajorLinkerVersion */
|
||||
fprintf( outfile, "\t.byte 0\n" ); /* MinorLinkerVersion */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* SizeOfCode */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* SizeOfInitializedData */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* SizeOfUninitializedData */
|
||||
output( "\t.byte 0\n" ); /* MajorLinkerVersion */
|
||||
output( "\t.byte 0\n" ); /* MinorLinkerVersion */
|
||||
output( "\t.long 0\n" ); /* SizeOfCode */
|
||||
output( "\t.long 0\n" ); /* SizeOfInitializedData */
|
||||
output( "\t.long 0\n" ); /* SizeOfUninitializedData */
|
||||
/* note: we expand the AddressOfEntryPoint field on 64-bit by overwriting the BaseOfCode field */
|
||||
fprintf( outfile, "\t%s %s\n", /* AddressOfEntryPoint */
|
||||
output( "\t%s %s\n", /* AddressOfEntryPoint */
|
||||
get_asm_ptr_keyword(), asm_name(spec->init_func) );
|
||||
if (get_ptr_size() == 4)
|
||||
{
|
||||
fprintf( outfile, "\t.long 0\n" ); /* BaseOfCode */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* BaseOfData */
|
||||
output( "\t.long 0\n" ); /* BaseOfCode */
|
||||
output( "\t.long 0\n" ); /* BaseOfData */
|
||||
}
|
||||
fprintf( outfile, "\t%s __wine_spec_pe_header\n", /* ImageBase */
|
||||
output( "\t%s __wine_spec_pe_header\n", /* ImageBase */
|
||||
get_asm_ptr_keyword() );
|
||||
fprintf( outfile, "\t.long %u\n", page_size ); /* SectionAlignment */
|
||||
fprintf( outfile, "\t.long %u\n", page_size ); /* FileAlignment */
|
||||
fprintf( outfile, "\t%s 1,0\n", /* Major/MinorOperatingSystemVersion */
|
||||
output( "\t.long %u\n", page_size ); /* SectionAlignment */
|
||||
output( "\t.long %u\n", page_size ); /* FileAlignment */
|
||||
output( "\t%s 1,0\n", /* Major/MinorOperatingSystemVersion */
|
||||
get_asm_short_keyword() );
|
||||
fprintf( outfile, "\t%s 0,0\n", /* Major/MinorImageVersion */
|
||||
output( "\t%s 0,0\n", /* Major/MinorImageVersion */
|
||||
get_asm_short_keyword() );
|
||||
fprintf( outfile, "\t%s %u,%u\n", /* Major/MinorSubsystemVersion */
|
||||
output( "\t%s %u,%u\n", /* Major/MinorSubsystemVersion */
|
||||
get_asm_short_keyword(), spec->subsystem_major, spec->subsystem_minor );
|
||||
fprintf( outfile, "\t.long 0\n" ); /* Win32VersionValue */
|
||||
fprintf( outfile, "\t.long %s-.L__wine_spec_rva_base\n", /* SizeOfImage */
|
||||
output( "\t.long 0\n" ); /* Win32VersionValue */
|
||||
output( "\t.long %s-.L__wine_spec_rva_base\n", /* SizeOfImage */
|
||||
asm_name("_end") );
|
||||
fprintf( outfile, "\t.long %u\n", page_size ); /* SizeOfHeaders */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* CheckSum */
|
||||
fprintf( outfile, "\t%s 0x%04x\n", /* Subsystem */
|
||||
output( "\t.long %u\n", page_size ); /* SizeOfHeaders */
|
||||
output( "\t.long 0\n" ); /* CheckSum */
|
||||
output( "\t%s 0x%04x\n", /* Subsystem */
|
||||
get_asm_short_keyword(), spec->subsystem );
|
||||
fprintf( outfile, "\t%s 0\n", /* DllCharacteristics */
|
||||
output( "\t%s 0\n", /* DllCharacteristics */
|
||||
get_asm_short_keyword() );
|
||||
fprintf( outfile, "\t%s %u,%u\n", /* SizeOfStackReserve/Commit */
|
||||
output( "\t%s %u,%u\n", /* SizeOfStackReserve/Commit */
|
||||
get_asm_ptr_keyword(), (spec->stack_size ? spec->stack_size : 1024) * 1024, page_size );
|
||||
fprintf( outfile, "\t%s %u,%u\n", /* SizeOfHeapReserve/Commit */
|
||||
output( "\t%s %u,%u\n", /* SizeOfHeapReserve/Commit */
|
||||
get_asm_ptr_keyword(), (spec->heap_size ? spec->heap_size : 1024) * 1024, page_size );
|
||||
fprintf( outfile, "\t.long 0\n" ); /* LoaderFlags */
|
||||
fprintf( outfile, "\t.long 16\n" ); /* NumberOfRvaAndSizes */
|
||||
output( "\t.long 0\n" ); /* LoaderFlags */
|
||||
output( "\t.long 16\n" ); /* NumberOfRvaAndSizes */
|
||||
|
||||
if (spec->base <= spec->limit) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] */
|
||||
fprintf( outfile, "\t.long .L__wine_spec_exports-.L__wine_spec_rva_base,"
|
||||
output( "\t.long .L__wine_spec_exports-.L__wine_spec_rva_base,"
|
||||
".L__wine_spec_exports_end-.L__wine_spec_exports\n" );
|
||||
else
|
||||
fprintf( outfile, "\t.long 0,0\n" );
|
||||
output( "\t.long 0,0\n" );
|
||||
|
||||
if (has_imports()) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] */
|
||||
fprintf( outfile, "\t.long .L__wine_spec_imports-.L__wine_spec_rva_base,"
|
||||
output( "\t.long .L__wine_spec_imports-.L__wine_spec_rva_base,"
|
||||
".L__wine_spec_imports_end-.L__wine_spec_imports\n" );
|
||||
else
|
||||
fprintf( outfile, "\t.long 0,0\n" );
|
||||
output( "\t.long 0,0\n" );
|
||||
|
||||
if (spec->nb_resources) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] */
|
||||
fprintf( outfile, "\t.long .L__wine_spec_resources-.L__wine_spec_rva_base,"
|
||||
output( "\t.long .L__wine_spec_resources-.L__wine_spec_rva_base,"
|
||||
".L__wine_spec_resources_end-.L__wine_spec_resources\n" );
|
||||
else
|
||||
fprintf( outfile, "\t.long 0,0\n" );
|
||||
output( "\t.long 0,0\n" );
|
||||
|
||||
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[3] */
|
||||
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[4] */
|
||||
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[5] */
|
||||
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[6] */
|
||||
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[7] */
|
||||
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[8] */
|
||||
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[9] */
|
||||
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[10] */
|
||||
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[11] */
|
||||
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[12] */
|
||||
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[13] */
|
||||
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[14] */
|
||||
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[15] */
|
||||
output( "\t.long 0,0\n" ); /* DataDirectory[3] */
|
||||
output( "\t.long 0,0\n" ); /* DataDirectory[4] */
|
||||
output( "\t.long 0,0\n" ); /* DataDirectory[5] */
|
||||
output( "\t.long 0,0\n" ); /* DataDirectory[6] */
|
||||
output( "\t.long 0,0\n" ); /* DataDirectory[7] */
|
||||
output( "\t.long 0,0\n" ); /* DataDirectory[8] */
|
||||
output( "\t.long 0,0\n" ); /* DataDirectory[9] */
|
||||
output( "\t.long 0,0\n" ); /* DataDirectory[10] */
|
||||
output( "\t.long 0,0\n" ); /* DataDirectory[11] */
|
||||
output( "\t.long 0,0\n" ); /* DataDirectory[12] */
|
||||
output( "\t.long 0,0\n" ); /* DataDirectory[13] */
|
||||
output( "\t.long 0,0\n" ); /* DataDirectory[14] */
|
||||
output( "\t.long 0,0\n" ); /* DataDirectory[15] */
|
||||
|
||||
fprintf( outfile, "\n\t%s\n", get_asm_string_section() );
|
||||
fprintf( outfile, "%s\n", asm_globl("__wine_spec_file_name") );
|
||||
fprintf( outfile, ".L__wine_spec_file_name:\n" );
|
||||
fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name );
|
||||
output( "\n\t%s\n", get_asm_string_section() );
|
||||
output( "%s\n", asm_globl("__wine_spec_file_name") );
|
||||
output( ".L__wine_spec_file_name:\n" );
|
||||
output( "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name );
|
||||
if (target_platform == PLATFORM_APPLE)
|
||||
fprintf( outfile, "\t.lcomm %s,4\n", asm_name("_end") );
|
||||
output( "\t.lcomm %s,4\n", asm_name("_end") );
|
||||
|
||||
output_stubs( outfile, spec );
|
||||
output_exports( outfile, spec );
|
||||
output_imports( outfile, spec );
|
||||
output_resources( outfile, spec );
|
||||
output_asm_constructor( outfile, "__wine_spec_init_ctor" );
|
||||
output_gnu_stack_note( outfile );
|
||||
output_stubs( spec );
|
||||
output_exports( spec );
|
||||
output_imports( spec );
|
||||
output_resources( spec );
|
||||
output_asm_constructor( "__wine_spec_init_ctor" );
|
||||
output_gnu_stack_note();
|
||||
}
|
||||
|
||||
|
||||
|
@ -488,20 +488,19 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
|
|||
*
|
||||
* Build a Win32 def file from a spec file.
|
||||
*/
|
||||
void BuildDef32File( FILE *outfile, DLLSPEC *spec )
|
||||
void BuildDef32File( DLLSPEC *spec )
|
||||
{
|
||||
const char *name;
|
||||
int i, total;
|
||||
|
||||
if (spec_file_name)
|
||||
fprintf( outfile, "; File generated automatically from %s; do not edit!\n\n",
|
||||
output( "; File generated automatically from %s; do not edit!\n\n",
|
||||
spec_file_name );
|
||||
else
|
||||
fprintf( outfile, "; File generated automatically; do not edit!\n\n" );
|
||||
output( "; File generated automatically; do not edit!\n\n" );
|
||||
|
||||
fprintf(outfile, "LIBRARY %s\n\n", spec->file_name);
|
||||
|
||||
fprintf(outfile, "EXPORTS\n");
|
||||
output( "LIBRARY %s\n\n", spec->file_name);
|
||||
output( "EXPORTS\n");
|
||||
|
||||
/* Output the exports and relay entry points */
|
||||
|
||||
|
@ -520,7 +519,7 @@ void BuildDef32File( FILE *outfile, DLLSPEC *spec )
|
|||
|
||||
if (odp->type == TYPE_STUB) continue;
|
||||
|
||||
fprintf(outfile, " %s", name);
|
||||
output( " %s", name );
|
||||
|
||||
switch(odp->type)
|
||||
{
|
||||
|
@ -531,31 +530,31 @@ void BuildDef32File( FILE *outfile, DLLSPEC *spec )
|
|||
case TYPE_CDECL:
|
||||
/* try to reduce output */
|
||||
if(strcmp(name, odp->link_name) || (odp->flags & FLAG_FORWARD))
|
||||
fprintf(outfile, "=%s", odp->link_name);
|
||||
output( "=%s", odp->link_name );
|
||||
break;
|
||||
case TYPE_STDCALL:
|
||||
{
|
||||
int at_param = strlen(odp->u.func.arg_types) * get_ptr_size();
|
||||
if (!kill_at) fprintf(outfile, "@%d", at_param);
|
||||
if (!kill_at) output( "@%d", at_param );
|
||||
if (odp->flags & FLAG_FORWARD)
|
||||
{
|
||||
fprintf(outfile, "=%s", odp->link_name);
|
||||
output( "=%s", odp->link_name );
|
||||
}
|
||||
else if (strcmp(name, odp->link_name)) /* try to reduce output */
|
||||
{
|
||||
fprintf(outfile, "=%s", odp->link_name);
|
||||
if (!kill_at) fprintf(outfile, "@%d", at_param);
|
||||
output( "=%s", odp->link_name );
|
||||
if (!kill_at) output( "@%d", at_param );
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
fprintf( outfile, " @%d", odp->ordinal );
|
||||
if (!odp->name) fprintf( outfile, " NONAME" );
|
||||
if (is_data) fprintf( outfile, " DATA" );
|
||||
if (odp->flags & FLAG_PRIVATE) fprintf( outfile, " PRIVATE" );
|
||||
fprintf( outfile, "\n" );
|
||||
output( " @%d", odp->ordinal );
|
||||
if (!odp->name) output( " NONAME" );
|
||||
if (is_data) output( " DATA" );
|
||||
if (odp->flags & FLAG_PRIVATE) output( " PRIVATE" );
|
||||
output( "\n" );
|
||||
}
|
||||
if (!total) warning( "%s: Import library doesn't export anything\n", spec->file_name );
|
||||
}
|
||||
|
|
|
@ -162,6 +162,18 @@ void warning( const char *msg, ... )
|
|||
va_end( valist );
|
||||
}
|
||||
|
||||
int output( const char *format, ... )
|
||||
{
|
||||
int ret;
|
||||
va_list valist;
|
||||
|
||||
va_start( valist, format );
|
||||
ret = vfprintf( output_file, format, valist );
|
||||
va_end( valist );
|
||||
if (ret < 0) fatal_perror( "Output error" );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* get a name for a temp file, automatically cleaned up on exit */
|
||||
char *get_temp_file_name( const char *prefix, const char *suffix )
|
||||
{
|
||||
|
@ -193,31 +205,29 @@ char *get_temp_file_name( const char *prefix, const char *suffix )
|
|||
}
|
||||
|
||||
/* output a standard header for generated files */
|
||||
void output_standard_file_header( FILE *outfile )
|
||||
void output_standard_file_header(void)
|
||||
{
|
||||
if (spec_file_name)
|
||||
fprintf( outfile, "/* File generated automatically from %s; do not edit! */\n",
|
||||
spec_file_name );
|
||||
output( "/* File generated automatically from %s; do not edit! */\n", spec_file_name );
|
||||
else
|
||||
fprintf( outfile, "/* File generated automatically; do not edit! */\n" );
|
||||
fprintf( outfile,
|
||||
"/* This file can be copied, modified and distributed without restriction. */\n\n" );
|
||||
output( "/* File generated automatically; do not edit! */\n" );
|
||||
output( "/* This file can be copied, modified and distributed without restriction. */\n\n" );
|
||||
}
|
||||
|
||||
/* dump a byte stream into the assembly code */
|
||||
void dump_bytes( FILE *outfile, const void *buffer, unsigned int size )
|
||||
void dump_bytes( const void *buffer, unsigned int size )
|
||||
{
|
||||
unsigned int i;
|
||||
const unsigned char *ptr = buffer;
|
||||
|
||||
if (!size) return;
|
||||
fprintf( outfile, "\t.byte " );
|
||||
output( "\t.byte " );
|
||||
for (i = 0; i < size - 1; i++, ptr++)
|
||||
{
|
||||
if ((i % 16) == 15) fprintf( outfile, "0x%02x\n\t.byte ", *ptr );
|
||||
else fprintf( outfile, "0x%02x,", *ptr );
|
||||
if ((i % 16) == 15) output( "0x%02x\n\t.byte ", *ptr );
|
||||
else output( "0x%02x,", *ptr );
|
||||
}
|
||||
fprintf( outfile, "0x%02x\n", *ptr );
|
||||
output( "0x%02x\n", *ptr );
|
||||
}
|
||||
|
||||
|
||||
|
@ -520,7 +530,7 @@ const char *func_declaration( const char *func )
|
|||
}
|
||||
|
||||
/* output a size declaration for an assembly function */
|
||||
void output_function_size( FILE *outfile, const char *name )
|
||||
void output_function_size( const char *name )
|
||||
{
|
||||
switch (target_platform)
|
||||
{
|
||||
|
@ -528,13 +538,13 @@ void output_function_size( FILE *outfile, const char *name )
|
|||
case PLATFORM_WINDOWS:
|
||||
break;
|
||||
default:
|
||||
fprintf( outfile, "\t.size %s, .-%s\n", name, name );
|
||||
output( "\t.size %s, .-%s\n", name, name );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* output the GNU note for non-exec stack */
|
||||
void output_gnu_stack_note( FILE *outfile )
|
||||
void output_gnu_stack_note(void)
|
||||
{
|
||||
switch (target_platform)
|
||||
{
|
||||
|
@ -542,7 +552,7 @@ void output_gnu_stack_note( FILE *outfile )
|
|||
case PLATFORM_APPLE:
|
||||
break;
|
||||
default:
|
||||
fprintf( outfile, "\t.section .note.GNU-stack,\"\",@progbits\n" );
|
||||
output( "\t.section .note.GNU-stack,\"\",@progbits\n" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue