mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 09:25:10 +00:00
Sync to Wine-20050628:
Alexandre Julliard <julliard@winehq.org> - Generate the resource data directly inside the resource directory. - Replaced all uses of the __ASM_NAME macro by the asm_name function to allow run-time determination of the correct format. - Beginnings of an infrastructure to allow specifying the target CPU and platform at run-time. - Output the exported names as a C string so that they end up in the correct section. - Reuse output_dll_init for the constructor of debug files. - Moved all assembly code to the end of the generated C files to avoid conflicting with the compiler over section changes. - Switch back to .data at the end of asm sections to work around an optimization in recent gcc versions. - Remove some i386 ifdefs for 16-bit entry points since they are no longer used by default on other platforms anyway. - Make import thunks position-independent to avoid text relocations. - Generate proper PIC code for CALL32_CBClient. - Store a relative pointer for registry entry points to avoid some text relocations. - Allocate ordinals in the order of the declarations in the spec file. Wolfgang Thaller <wolfgang.thaller@gmx.net> - Winebuild darwin/x86-specific fixes: - Assembler interprets .align as power-of-two - Add .weak_reference to output where gcc 3.3 swallows it - Use __ASM_NAME and HAVE_ASM_DOT_SIZE in a few places in winebuild where they have been missing (needed for Darwin/x86). Pierre d'Herbemont <stegefin@free.fr> - Use .mod_*_func sections on Mac OS X/i386 instead of the elf constructor/destructor. svn path=/trunk/; revision=16438
This commit is contained in:
parent
40dc1919bc
commit
d005fc9f1a
10 changed files with 788 additions and 772 deletions
|
@ -109,6 +109,19 @@ typedef struct
|
||||||
struct resource *resources; /* array of dll resources (format differs between Win16/Win32) */
|
struct resource *resources; /* array of dll resources (format differs between Win16/Win32) */
|
||||||
} DLLSPEC;
|
} DLLSPEC;
|
||||||
|
|
||||||
|
enum target_cpu
|
||||||
|
{
|
||||||
|
CPU_x86, CPU_SPARC, CPU_ALPHA, CPU_POWERPC
|
||||||
|
};
|
||||||
|
|
||||||
|
enum target_platform
|
||||||
|
{
|
||||||
|
PLATFORM_UNSPECIFIED, PLATFORM_APPLE, PLATFORM_SVR4, PLATFORM_WINDOWS
|
||||||
|
};
|
||||||
|
|
||||||
|
extern enum target_cpu target_cpu;
|
||||||
|
extern enum target_platform target_platform;
|
||||||
|
|
||||||
/* entry point flags */
|
/* entry point flags */
|
||||||
#define FLAG_NORELAY 0x01 /* don't use relay debugging for this function */
|
#define FLAG_NORELAY 0x01 /* don't use relay debugging for this function */
|
||||||
#define FLAG_NONAME 0x02 /* don't import function by name */
|
#define FLAG_NONAME 0x02 /* don't import function by name */
|
||||||
|
@ -166,7 +179,11 @@ extern int remove_stdcall_decoration( char *name );
|
||||||
extern DLLSPEC *alloc_dll_spec(void);
|
extern DLLSPEC *alloc_dll_spec(void);
|
||||||
extern void free_dll_spec( DLLSPEC *spec );
|
extern void free_dll_spec( DLLSPEC *spec );
|
||||||
extern const char *make_c_identifier( const char *str );
|
extern const char *make_c_identifier( const char *str );
|
||||||
extern int get_alignment(int alignBoundary);
|
extern unsigned int get_alignment(unsigned int align);
|
||||||
|
extern unsigned int get_page_size(void);
|
||||||
|
extern const char *asm_name( const char *func );
|
||||||
|
extern const char *func_declaration( const char *func );
|
||||||
|
extern const char *func_size( const char *func );
|
||||||
|
|
||||||
extern void add_import_dll( const char *name, const char *filename );
|
extern void add_import_dll( const char *name, const char *filename );
|
||||||
extern void add_delayed_import( const char *name );
|
extern void add_delayed_import( const char *name );
|
||||||
|
@ -174,6 +191,7 @@ extern void add_ignore_symbol( const char *name );
|
||||||
extern void read_undef_symbols( char **argv );
|
extern void read_undef_symbols( char **argv );
|
||||||
extern int resolve_imports( DLLSPEC *spec );
|
extern int resolve_imports( DLLSPEC *spec );
|
||||||
extern int output_imports( FILE *outfile, DLLSPEC *spec, int *nb_delayed );
|
extern int output_imports( FILE *outfile, DLLSPEC *spec, int *nb_delayed );
|
||||||
|
extern void output_import_thunks( FILE *outfile, DLLSPEC *spec );
|
||||||
extern int load_res32_file( const char *name, DLLSPEC *spec );
|
extern int load_res32_file( const char *name, DLLSPEC *spec );
|
||||||
extern void output_resources( FILE *outfile, DLLSPEC *spec );
|
extern void output_resources( FILE *outfile, DLLSPEC *spec );
|
||||||
extern void load_res16_file( const char *name, DLLSPEC *spec );
|
extern void load_res16_file( const char *name, DLLSPEC *spec );
|
||||||
|
|
|
@ -125,23 +125,16 @@ static const char * const default_ignored_symbols[] =
|
||||||
"tanh"
|
"tanh"
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __powerpc__
|
|
||||||
# ifdef __APPLE__
|
static inline const char *ppc_reg( int reg )
|
||||||
# define ppc_high(mem) "ha16(" mem ")"
|
{
|
||||||
# define ppc_low(mem) "lo16(" mem ")"
|
static const char * const ppc_regs[32] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
||||||
static const char * const ppc_reg[32] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
"r8", "r9", "r10","r11","r12","r13","r14","r15",
|
||||||
"r8", "r9", "r10","r11","r12","r13","r14","r15",
|
"r16","r17","r18","r19","r20","r21","r22","r23",
|
||||||
"r16","r17","r18","r19","r20","r21","r22","r23",
|
"r24","r25","r26","r27","r28","r29","r30","r31" };
|
||||||
"r24","r25","r26","r27","r28","r29","r30","r31" };
|
if (target_platform == PLATFORM_APPLE) return ppc_regs[reg];
|
||||||
# else /* __APPLE__ */
|
return ppc_regs[reg] + 1; /* skip the 'r' */
|
||||||
# define ppc_high(mem) "(" mem ")@hi"
|
}
|
||||||
# define ppc_low(mem) "(" mem ")@l"
|
|
||||||
static const char * const ppc_reg[32] = { "0", "1", "2", "3", "4", "5", "6", "7",
|
|
||||||
"8", "9", "10","11","12","13","14","15",
|
|
||||||
"16","17","18","19","20","21","22","23",
|
|
||||||
"24","25","26","27","28","29","30","31" };
|
|
||||||
# endif /* __APPLE__ */
|
|
||||||
#endif /* __powerpc__ */
|
|
||||||
|
|
||||||
/* compare function names; helper for resolve_imports */
|
/* compare function names; helper for resolve_imports */
|
||||||
static int name_cmp( const void *name, const void *entry )
|
static int name_cmp( const void *name, const void *entry )
|
||||||
|
@ -191,9 +184,8 @@ inline static void sort_symbols( char **table, int size )
|
||||||
|
|
||||||
inline static void output_function_size( FILE *outfile, const char *name )
|
inline static void output_function_size( FILE *outfile, const char *name )
|
||||||
{
|
{
|
||||||
#ifdef HAVE_ASM_DOT_SIZE
|
const char *size = func_size( name );
|
||||||
fprintf( outfile, " \"\\t.size " __ASM_NAME("%s") ", . - " __ASM_NAME("%s") "\\n\"\n", name, name);
|
if (size[0]) fprintf( outfile, " \"\\t%s\\n\"\n", size );
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free an import structure */
|
/* free an import structure */
|
||||||
|
@ -607,15 +599,17 @@ static const char *ldcombine_files( char **argv )
|
||||||
/* read in the list of undefined symbols */
|
/* read in the list of undefined symbols */
|
||||||
void read_undef_symbols( char **argv )
|
void read_undef_symbols( char **argv )
|
||||||
{
|
{
|
||||||
static const char name_prefix[] = __ASM_NAME("");
|
size_t prefix_len;
|
||||||
static const int prefix_len = sizeof(name_prefix) - 1;
|
|
||||||
FILE *f;
|
FILE *f;
|
||||||
char *cmd, buffer[1024];
|
char *cmd, buffer[1024], name_prefix[16];
|
||||||
int err;
|
int err;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
if (!argv[0]) return;
|
if (!argv[0]) return;
|
||||||
|
|
||||||
|
strcpy( name_prefix, asm_name("") );
|
||||||
|
prefix_len = strlen( name_prefix );
|
||||||
|
|
||||||
undef_size = nb_undef_symbols = 0;
|
undef_size = nb_undef_symbols = 0;
|
||||||
|
|
||||||
/* if we have multiple object files, link them together */
|
/* if we have multiple object files, link them together */
|
||||||
|
@ -695,14 +689,120 @@ int resolve_imports( DLLSPEC *spec )
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* output a single import thunk */
|
||||||
|
static void output_import_thunk( FILE *outfile, const char *name, const char *table, int pos )
|
||||||
|
{
|
||||||
|
fprintf( outfile, " \"\\t.align %d\\n\"\n", get_alignment(8) );
|
||||||
|
fprintf( outfile, " \"\\t%s\\n\"\n", func_declaration(name) );
|
||||||
|
fprintf( outfile, " \"\\t.globl %s\\n\"\n", asm_name(name) );
|
||||||
|
fprintf( outfile, " \"%s:\\n\"\n", asm_name(name) );
|
||||||
|
|
||||||
|
switch(target_cpu)
|
||||||
|
{
|
||||||
|
case CPU_x86:
|
||||||
|
if (!UsePIC)
|
||||||
|
{
|
||||||
|
if (strstr( name, "__wine_call_from_16" )) fprintf( outfile, " \"\\t.byte 0x2e\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\tjmp *(imports+%d)\\n\"\n", pos );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!strcmp( name, "__wine_call_from_32_regs" ) ||
|
||||||
|
!strcmp( name, "__wine_call_from_16_regs" ))
|
||||||
|
{
|
||||||
|
/* special case: need to preserve all registers */
|
||||||
|
fprintf( outfile, " \"\\tpushl %%eax\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\tpushfl\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\tcall .L__wine_spec_%s\\n\"\n", name );
|
||||||
|
fprintf( outfile, " \".L__wine_spec_%s:\\n\"\n", name );
|
||||||
|
fprintf( outfile, " \"\\tpopl %%eax\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\taddl $%d+%s-.L__wine_spec_%s,%%eax\\n\"\n",
|
||||||
|
pos, asm_name(table), name );
|
||||||
|
if (!strcmp( name, "__wine_call_from_16_regs" ))
|
||||||
|
fprintf( outfile, " \"\\t.byte 0x2e\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\tmovl 0(%%eax),%%eax\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\txchgl 4(%%esp),%%eax\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\tpopfl\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\tret\\n\"\n" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf( outfile, " \"\\tcall .L__wine_spec_%s\\n\"\n", name );
|
||||||
|
fprintf( outfile, " \".L__wine_spec_%s:\\n\"\n", name );
|
||||||
|
fprintf( outfile, " \"\\tpopl %%eax\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\taddl $%d+%s-.L__wine_spec_%s,%%eax\\n\"\n",
|
||||||
|
pos, asm_name(table), name );
|
||||||
|
if (strstr( name, "__wine_call_from_16" ))
|
||||||
|
fprintf( outfile, " \"\\t.byte 0x2e\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\tjmp *0(%%eax)\\n\"\n" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CPU_SPARC:
|
||||||
|
if ( !UsePIC )
|
||||||
|
{
|
||||||
|
fprintf( outfile, " \"\\tsethi %%hi(%s+%d), %%g1\\n\"\n", table, pos );
|
||||||
|
fprintf( outfile, " \"\\tld [%%g1+%%lo(%s+%d)], %%g1\\n\"\n", table, pos );
|
||||||
|
fprintf( outfile, " \"\\tjmp %%g1\\n\\tnop\\n\"\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\"\n" );
|
||||||
|
fprintf( outfile, " \"0:\\tcall 1f\\n\\tnop\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"1:\\tsethi %%hi(%s+%d-0b), %%g1\\n\"\n", table, pos );
|
||||||
|
fprintf( outfile, " \"\\tor %%g1, %%lo(%s+%d-0b), %%g1\\n\"\n", table, pos );
|
||||||
|
fprintf( outfile, " \"\\tld [%%g1+%%o7], %%g1\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\tjmp %%g1\\n\\trestore\\n\"\n" );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CPU_ALPHA:
|
||||||
|
fprintf( outfile, " \"\\tlda $0,%s\\n\"\n", table );
|
||||||
|
fprintf( outfile, " \"\\tlda $0,%d($0)\\n\"\n", pos);
|
||||||
|
fprintf( outfile, " \"\\tjmp $31,($0)\\n\"\n" );
|
||||||
|
break;
|
||||||
|
case CPU_POWERPC:
|
||||||
|
fprintf(outfile, " \"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg(1), ppc_reg(1));
|
||||||
|
fprintf(outfile, " \"\\tstw %s, 0(%s)\\n\"\n", ppc_reg(9), ppc_reg(1));
|
||||||
|
fprintf(outfile, " \"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg(1), ppc_reg(1));
|
||||||
|
fprintf(outfile, " \"\\tstw %s, 0(%s)\\n\"\n", ppc_reg(8), ppc_reg(1));
|
||||||
|
fprintf(outfile, " \"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg(1), ppc_reg(1));
|
||||||
|
fprintf(outfile, " \"\\tstw %s, 0(%s)\\n\"\n", ppc_reg(7), ppc_reg(1));
|
||||||
|
if (target_platform == PLATFORM_APPLE)
|
||||||
|
{
|
||||||
|
fprintf(outfile, " \"\\tlis %s, ha16(%s+%d)\\n\"\n",
|
||||||
|
ppc_reg(9), asm_name(table), pos);
|
||||||
|
fprintf(outfile, " \"\\tla %s, lo16(%s+%d)(%s)\\n\"\n",
|
||||||
|
ppc_reg(8), asm_name(table), pos, ppc_reg(9));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(outfile, " \"\\tlis %s, (%s+%d)@hi\\n\"\n",
|
||||||
|
ppc_reg(9), asm_name(table), pos);
|
||||||
|
fprintf(outfile, " \"\\tla %s, (%s+%d)@l(%s)\\n\"\n",
|
||||||
|
ppc_reg(8), asm_name(table), pos, ppc_reg(9));
|
||||||
|
}
|
||||||
|
fprintf(outfile, " \"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg(7), ppc_reg(8));
|
||||||
|
fprintf(outfile, " \"\\tmtctr %s\\n\"\n", ppc_reg(7));
|
||||||
|
fprintf(outfile, " \"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg(7), ppc_reg(1));
|
||||||
|
fprintf(outfile, " \"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg(1), ppc_reg(1));
|
||||||
|
fprintf(outfile, " \"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg(8), ppc_reg(1));
|
||||||
|
fprintf(outfile, " \"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg(1), ppc_reg(1));
|
||||||
|
fprintf(outfile, " \"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg(9), ppc_reg(1));
|
||||||
|
fprintf(outfile, " \"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg(1), ppc_reg(1));
|
||||||
|
fprintf(outfile, " \"\\tbctr\\n\"\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
output_function_size( outfile, name );
|
||||||
|
}
|
||||||
|
|
||||||
/* output the import table of a Win32 module */
|
/* output the import table of a Win32 module */
|
||||||
static int output_immediate_imports( FILE *outfile )
|
static int output_immediate_imports( FILE *outfile )
|
||||||
{
|
{
|
||||||
int i, j, pos;
|
int i, j, nb_imm = nb_imports - nb_delayed;
|
||||||
int nb_imm = nb_imports - nb_delayed;
|
|
||||||
static const char import_thunks[] = "__wine_spec_import_thunks";
|
|
||||||
|
|
||||||
if (!nb_imm) goto done;
|
if (!nb_imm) return 0;
|
||||||
|
|
||||||
/* main import header */
|
/* main import header */
|
||||||
|
|
||||||
|
@ -753,13 +853,23 @@ static int output_immediate_imports( FILE *outfile )
|
||||||
}
|
}
|
||||||
fprintf( outfile, " }\n};\n\n" );
|
fprintf( outfile, " }\n};\n\n" );
|
||||||
|
|
||||||
/* thunks for imported functions */
|
return nb_imm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* output the import thunks of a Win32 module */
|
||||||
|
static void output_immediate_import_thunks( FILE *outfile )
|
||||||
|
{
|
||||||
|
int i, j, pos;
|
||||||
|
int nb_imm = nb_imports - nb_delayed;
|
||||||
|
static const char import_thunks[] = "__wine_spec_import_thunks";
|
||||||
|
|
||||||
|
if (!nb_imm) return;
|
||||||
|
|
||||||
fprintf( outfile, "#ifndef __GNUC__\nstatic void __asm__dummy_import(void) {\n#endif\n\n" );
|
|
||||||
pos = (sizeof(void *) + 2*sizeof(unsigned int) + sizeof(const char *) + sizeof(void *)) *
|
pos = (sizeof(void *) + 2*sizeof(unsigned int) + sizeof(const char *) + sizeof(void *)) *
|
||||||
(nb_imm + 1); /* offset of imports.data from start of imports */
|
(nb_imm + 1); /* offset of imports.data from start of imports */
|
||||||
|
fprintf( outfile, "/* immediate import thunks */\n" );
|
||||||
fprintf( outfile, "asm(\".text\\n\\t.align %d\\n\"\n", get_alignment(8) );
|
fprintf( outfile, "asm(\".text\\n\\t.align %d\\n\"\n", get_alignment(8) );
|
||||||
fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\"\n", import_thunks);
|
fprintf( outfile, " \"%s:\\n\"\n", asm_name(import_thunks));
|
||||||
|
|
||||||
for (i = 0; i < nb_imports; i++)
|
for (i = 0; i < nb_imports; i++)
|
||||||
{
|
{
|
||||||
|
@ -767,84 +877,21 @@ static int output_immediate_imports( FILE *outfile )
|
||||||
for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += sizeof(const char *))
|
for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += sizeof(const char *))
|
||||||
{
|
{
|
||||||
ORDDEF *odp = dll_imports[i]->imports[j];
|
ORDDEF *odp = dll_imports[i]->imports[j];
|
||||||
const char *name = odp->name ? odp->name : odp->export_name;
|
output_import_thunk( outfile, odp->name ? odp->name : odp->export_name,
|
||||||
fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", name );
|
"imports", pos );
|
||||||
fprintf( outfile, " \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", name );
|
|
||||||
fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\\t", name);
|
|
||||||
|
|
||||||
#ifndef __REACTOS__
|
|
||||||
#if defined(__i386__)
|
|
||||||
if (strstr( name, "__wine_call_from_16" ))
|
|
||||||
fprintf( outfile, ".byte 0x2e\\n\\tjmp *(imports+%d)\\n\\tnop\\n", pos );
|
|
||||||
else
|
|
||||||
fprintf( outfile, "jmp *(imports+%d)\\n\\tmovl %%esi,%%esi\\n", pos );
|
|
||||||
#elif defined(__sparc__)
|
|
||||||
if ( !UsePIC )
|
|
||||||
{
|
|
||||||
fprintf( outfile, "sethi %%hi(imports+%d), %%g1\\n\\t", pos );
|
|
||||||
fprintf( outfile, "ld [%%g1+%%lo(imports+%d)], %%g1\\n\\t", pos );
|
|
||||||
fprintf( outfile, "jmp %%g1\\n\\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, "save %%sp, -96, %%sp\\n" );
|
|
||||||
fprintf( outfile, "0:\\tcall 1f\\n\\tnop\\n" );
|
|
||||||
fprintf( outfile, "1:\\tsethi %%hi(imports+%d-0b), %%g1\\n\\t", pos );
|
|
||||||
fprintf( outfile, "or %%g1, %%lo(imports+%d-0b), %%g1\\n\\t", pos );
|
|
||||||
fprintf( outfile, "ld [%%g1+%%o7], %%g1\\n\\t" );
|
|
||||||
fprintf( outfile, "jmp %%g1\\n\\trestore\\n" );
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(__powerpc__)
|
|
||||||
fprintf(outfile, "\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
|
|
||||||
fprintf(outfile, "\t\"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[9], ppc_reg[1]);
|
|
||||||
fprintf(outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
|
|
||||||
fprintf(outfile, "\t\"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[8], ppc_reg[1]);
|
|
||||||
fprintf(outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
|
|
||||||
fprintf(outfile, "\t\"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[1]);
|
|
||||||
|
|
||||||
fprintf(outfile, "\t\"\\tlis %s, " ppc_high(__ASM_NAME("imports") "+ %d") "\\n\"\n", ppc_reg[9], pos);
|
|
||||||
fprintf(outfile, "\t\"\\tla %s, " ppc_low (__ASM_NAME("imports") "+ %d") "(%s)\\n\"\n", ppc_reg[8], pos, ppc_reg[9]);
|
|
||||||
fprintf(outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[8]);
|
|
||||||
fprintf(outfile, "\t\"\\tmtctr %s\\n\"\n", ppc_reg[7]);
|
|
||||||
|
|
||||||
fprintf(outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[1]);
|
|
||||||
fprintf(outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
|
|
||||||
fprintf(outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[8], ppc_reg[1]);
|
|
||||||
fprintf(outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
|
|
||||||
fprintf(outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[9], ppc_reg[1]);
|
|
||||||
fprintf(outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
|
|
||||||
fprintf(outfile, "\t\"\\tbctr\\n");
|
|
||||||
#elif defined(__ALPHA__)
|
|
||||||
fprintf( outfile, "\tlda $0,imports\\n\"\n" );
|
|
||||||
fprintf( outfile, "\t\"\\tlda $0,%d($0)\\n\"\n", pos);
|
|
||||||
fprintf( outfile, "\t\"\\tjmp $31,($0)\\n" );
|
|
||||||
#else
|
|
||||||
#error You need to define import thunks for your architecture!
|
|
||||||
#endif
|
|
||||||
#endif /*__REACTOS__*/
|
|
||||||
fprintf( outfile, "\"\n" );
|
|
||||||
output_function_size( outfile, name );
|
|
||||||
}
|
}
|
||||||
pos += 4;
|
pos += 4;
|
||||||
}
|
}
|
||||||
output_function_size( outfile, import_thunks );
|
output_function_size( outfile, import_thunks );
|
||||||
fprintf( outfile, " \".text\");\n#ifndef __GNUC__\n}\n#endif\n\n" );
|
fprintf( outfile, ");\n" );
|
||||||
|
|
||||||
done:
|
|
||||||
return nb_imm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* output the delayed import table of a Win32 module */
|
/* output the delayed import table of a Win32 module */
|
||||||
static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
|
static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
|
||||||
{
|
{
|
||||||
int i, idx, j, pos;
|
int i, j;
|
||||||
static const char delayed_import_loaders[] = "__wine_spec_delayed_import_loaders";
|
|
||||||
static const char delayed_import_thunks[] = "__wine_spec_delayed_import_thunks";
|
|
||||||
|
|
||||||
if (!nb_delayed) goto done;
|
if (!nb_delayed) return 0;
|
||||||
|
|
||||||
fprintf( outfile, "static void *__wine_delay_imp_hmod[%d];\n", nb_delayed );
|
fprintf( outfile, "static void *__wine_delay_imp_hmod[%d];\n", nb_delayed );
|
||||||
for (i = 0; i < nb_imports; i++)
|
for (i = 0; i < nb_imports; i++)
|
||||||
|
@ -932,83 +979,93 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
|
||||||
fprintf( outfile, " RaiseException( 0x%08x, %d, 2, args );\n",
|
fprintf( outfile, " RaiseException( 0x%08x, %d, 2, args );\n",
|
||||||
EXCEPTION_WINE_STUB, EXCEPTION_NONCONTINUABLE );
|
EXCEPTION_WINE_STUB, EXCEPTION_NONCONTINUABLE );
|
||||||
fprintf( outfile, " return 0;\n" );
|
fprintf( outfile, " return 0;\n" );
|
||||||
fprintf( outfile, " }\n}\n\n" );
|
fprintf( outfile, " }\n}\n" );
|
||||||
|
|
||||||
fprintf( outfile, "#ifndef __GNUC__\n" );
|
return nb_delayed;
|
||||||
fprintf( outfile, "static void __asm__dummy_delay_import(void) {\n" );
|
}
|
||||||
fprintf( outfile, "#endif\n" );
|
|
||||||
|
|
||||||
fprintf( outfile, "asm(\".align %d\\n\"\n", get_alignment(8) );
|
/* output the delayed import thunks of a Win32 module */
|
||||||
fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\"\n", delayed_import_loaders);
|
static void output_delayed_import_thunks( FILE *outfile, const DLLSPEC *spec )
|
||||||
fprintf( outfile, " \"\\t" __ASM_FUNC("__wine_delay_load_asm") "\\n\"\n" );
|
{
|
||||||
fprintf( outfile, " \"" __ASM_NAME("__wine_delay_load_asm") ":\\n\"\n" );
|
int i, idx, j, pos, extra_stack_storage = 0;
|
||||||
#if defined(__i386__)
|
static const char delayed_import_loaders[] = "__wine_spec_delayed_import_loaders";
|
||||||
fprintf( outfile, " \"\\tpushl %%ecx\\n\\tpushl %%edx\\n\\tpushl %%eax\\n\"\n" );
|
static const char delayed_import_thunks[] = "__wine_spec_delayed_import_thunks";
|
||||||
fprintf( outfile, " \"\\tcall __wine_delay_load\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\tpopl %%edx\\n\\tpopl %%ecx\\n\\tjmp *%%eax\\n\"\n" );
|
|
||||||
#elif defined(__sparc__)
|
|
||||||
fprintf( outfile, " \"\\tsave %%sp, -96, %%sp\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\tcall __wine_delay_load\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\tmov %%g1, %%o0\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\tjmp %%o0\\n\\trestore\\n\"\n" );
|
|
||||||
#elif defined(__powerpc__)
|
|
||||||
# if defined(__APPLE__)
|
|
||||||
/* On darwin an extra 56 bytes must be allowed for the linkage area+param area */
|
|
||||||
# define extra_stack_storage 56
|
|
||||||
# else
|
|
||||||
# define extra_stack_storage 0
|
|
||||||
# endif
|
|
||||||
/* Save all callee saved registers into a stackframe. */
|
|
||||||
fprintf( outfile, " \"\\tstwu %s, -%d(%s)\\n\"\n",ppc_reg[1], 48+extra_stack_storage, ppc_reg[1]);
|
|
||||||
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[3], 4+extra_stack_storage, ppc_reg[1]);
|
|
||||||
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[4], 8+extra_stack_storage, ppc_reg[1]);
|
|
||||||
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[5], 12+extra_stack_storage, ppc_reg[1]);
|
|
||||||
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[6], 16+extra_stack_storage, ppc_reg[1]);
|
|
||||||
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[7], 20+extra_stack_storage, ppc_reg[1]);
|
|
||||||
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[8], 24+extra_stack_storage, ppc_reg[1]);
|
|
||||||
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[9], 28+extra_stack_storage, ppc_reg[1]);
|
|
||||||
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[10],32+extra_stack_storage, ppc_reg[1]);
|
|
||||||
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[11],36+extra_stack_storage, ppc_reg[1]);
|
|
||||||
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[12],40+extra_stack_storage, ppc_reg[1]);
|
|
||||||
|
|
||||||
/* r0 -> r3 (arg1) */
|
if (!nb_delayed) return;
|
||||||
fprintf( outfile, " \"\\tmr %s, %s\\n\"\n", ppc_reg[3], ppc_reg[0]);
|
|
||||||
|
|
||||||
/* save return address */
|
fprintf( outfile, "/* delayed import thunks */\n" );
|
||||||
fprintf( outfile, " \"\\tmflr %s\\n\"\n", ppc_reg[0]);
|
fprintf( outfile, "asm(\".text\\n\"\n" );
|
||||||
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[0], 44+extra_stack_storage, ppc_reg[1]);
|
fprintf( outfile, " \"\\t.align %d\\n\"\n", get_alignment(8) );
|
||||||
|
fprintf( outfile, " \"%s:\\n\"\n", asm_name(delayed_import_loaders));
|
||||||
|
fprintf( outfile, " \"\\t%s\\n\"\n", func_declaration("__wine_delay_load_asm") );
|
||||||
|
fprintf( outfile, " \"%s:\\n\"\n", asm_name("__wine_delay_load_asm") );
|
||||||
|
switch(target_cpu)
|
||||||
|
{
|
||||||
|
case CPU_x86:
|
||||||
|
fprintf( outfile, " \"\\tpushl %%ecx\\n\\tpushl %%edx\\n\\tpushl %%eax\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\tcall %s\\n\"\n", asm_name("__wine_delay_load") );
|
||||||
|
fprintf( outfile, " \"\\tpopl %%edx\\n\\tpopl %%ecx\\n\\tjmp *%%eax\\n\"\n" );
|
||||||
|
break;
|
||||||
|
case CPU_SPARC:
|
||||||
|
fprintf( outfile, " \"\\tsave %%sp, -96, %%sp\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\tcall %s\\n\"\n", asm_name("__wine_delay_load") );
|
||||||
|
fprintf( outfile, " \"\\tmov %%g1, %%o0\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\tjmp %%o0\\n\\trestore\\n\"\n" );
|
||||||
|
break;
|
||||||
|
case CPU_ALPHA:
|
||||||
|
fprintf( outfile, " \"\\tjsr $26,%s\\n\"\n", asm_name("__wine_delay_load") );
|
||||||
|
fprintf( outfile, " \"\\tjmp $31,($0)\\n\"\n" );
|
||||||
|
break;
|
||||||
|
case CPU_POWERPC:
|
||||||
|
if (target_platform == PLATFORM_APPLE) extra_stack_storage = 56;
|
||||||
|
|
||||||
/* Call the __wine_delay_load function, arg1 is arg1. */
|
/* Save all callee saved registers into a stackframe. */
|
||||||
fprintf( outfile, " \"\\tbl " __ASM_NAME("__wine_delay_load") "\\n\"\n");
|
fprintf( outfile, " \"\\tstwu %s, -%d(%s)\\n\"\n",ppc_reg(1), 48+extra_stack_storage, ppc_reg(1));
|
||||||
|
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg(3), 4+extra_stack_storage, ppc_reg(1));
|
||||||
|
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg(4), 8+extra_stack_storage, ppc_reg(1));
|
||||||
|
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg(5), 12+extra_stack_storage, ppc_reg(1));
|
||||||
|
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg(6), 16+extra_stack_storage, ppc_reg(1));
|
||||||
|
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg(7), 20+extra_stack_storage, ppc_reg(1));
|
||||||
|
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg(8), 24+extra_stack_storage, ppc_reg(1));
|
||||||
|
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg(9), 28+extra_stack_storage, ppc_reg(1));
|
||||||
|
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg(10),32+extra_stack_storage, ppc_reg(1));
|
||||||
|
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg(11),36+extra_stack_storage, ppc_reg(1));
|
||||||
|
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg(12),40+extra_stack_storage, ppc_reg(1));
|
||||||
|
|
||||||
/* Load return value from call into ctr register */
|
/* r0 -> r3 (arg1) */
|
||||||
fprintf( outfile, " \"\\tmtctr %s\\n\"\n", ppc_reg[3]);
|
fprintf( outfile, " \"\\tmr %s, %s\\n\"\n", ppc_reg(3), ppc_reg(0));
|
||||||
|
|
||||||
/* restore all saved registers and drop stackframe. */
|
/* save return address */
|
||||||
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[3], 4+extra_stack_storage, ppc_reg[1]);
|
fprintf( outfile, " \"\\tmflr %s\\n\"\n", ppc_reg(0));
|
||||||
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[4], 8+extra_stack_storage, ppc_reg[1]);
|
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg(0), 44+extra_stack_storage, ppc_reg(1));
|
||||||
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[5], 12+extra_stack_storage, ppc_reg[1]);
|
|
||||||
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[6], 16+extra_stack_storage, ppc_reg[1]);
|
|
||||||
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[7], 20+extra_stack_storage, ppc_reg[1]);
|
|
||||||
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[8], 24+extra_stack_storage, ppc_reg[1]);
|
|
||||||
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[9], 28+extra_stack_storage, ppc_reg[1]);
|
|
||||||
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[10],32+extra_stack_storage, ppc_reg[1]);
|
|
||||||
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[11],36+extra_stack_storage, ppc_reg[1]);
|
|
||||||
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[12],40+extra_stack_storage, ppc_reg[1]);
|
|
||||||
|
|
||||||
/* Load return value from call into return register */
|
/* Call the __wine_delay_load function, arg1 is arg1. */
|
||||||
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[0], 44+extra_stack_storage, ppc_reg[1]);
|
fprintf( outfile, " \"\\tbl %s\\n\"\n", asm_name("__wine_delay_load") );
|
||||||
fprintf( outfile, " \"\\tmtlr %s\\n\"\n", ppc_reg[0]);
|
|
||||||
fprintf( outfile, " \"\\taddi %s, %s, %d\\n\"\n", ppc_reg[1], ppc_reg[1], 48+extra_stack_storage);
|
|
||||||
|
|
||||||
/* branch to ctr register. */
|
/* Load return value from call into ctr register */
|
||||||
fprintf( outfile, " \"bctr\\n\"\n");
|
fprintf( outfile, " \"\\tmtctr %s\\n\"\n", ppc_reg(3));
|
||||||
#elif defined(__ALPHA__)
|
|
||||||
fprintf( outfile, " \"\\tjsr $26,__wine_delay_load\\n\"\n" );
|
/* restore all saved registers and drop stackframe. */
|
||||||
fprintf( outfile, " \"\\tjmp $31,($0)\\n\"\n" );
|
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg(3), 4+extra_stack_storage, ppc_reg(1));
|
||||||
#else
|
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg(4), 8+extra_stack_storage, ppc_reg(1));
|
||||||
#error You need to defined delayed import thunks for your architecture!
|
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg(5), 12+extra_stack_storage, ppc_reg(1));
|
||||||
#endif
|
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg(6), 16+extra_stack_storage, ppc_reg(1));
|
||||||
|
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg(7), 20+extra_stack_storage, ppc_reg(1));
|
||||||
|
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg(8), 24+extra_stack_storage, ppc_reg(1));
|
||||||
|
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg(9), 28+extra_stack_storage, ppc_reg(1));
|
||||||
|
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg(10),32+extra_stack_storage, ppc_reg(1));
|
||||||
|
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg(11),36+extra_stack_storage, ppc_reg(1));
|
||||||
|
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\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\"\n", ppc_reg(0), 44+extra_stack_storage, ppc_reg(1));
|
||||||
|
fprintf( outfile, " \"\\tmtlr %s\\n\"\n", ppc_reg(0));
|
||||||
|
fprintf( outfile, " \"\\taddi %s, %s, %d\\n\"\n", ppc_reg(1), ppc_reg(1), 48+extra_stack_storage);
|
||||||
|
|
||||||
|
/* branch to ctr register. */
|
||||||
|
fprintf( outfile, " \"bctr\\n\"\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
output_function_size( outfile, "__wine_delay_load_asm" );
|
output_function_size( outfile, "__wine_delay_load_asm" );
|
||||||
|
|
||||||
for (i = idx = 0; i < nb_imports; i++)
|
for (i = idx = 0; i < nb_imports; i++)
|
||||||
|
@ -1021,43 +1078,51 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
|
||||||
const char *name = odp->name ? odp->name : odp->export_name;
|
const char *name = odp->name ? odp->name : odp->export_name;
|
||||||
|
|
||||||
sprintf( buffer, "__wine_delay_imp_%d_%s", i, name );
|
sprintf( buffer, "__wine_delay_imp_%d_%s", i, name );
|
||||||
fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", buffer );
|
fprintf( outfile, " \"\\t%s\\n\"\n", func_declaration(buffer) );
|
||||||
fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\"\n", buffer );
|
fprintf( outfile, " \"%s:\\n\"\n", asm_name(buffer) );
|
||||||
#if defined(__i386__)
|
switch(target_cpu)
|
||||||
fprintf( outfile, " \"\\tmovl $%d, %%eax\\n\"\n", (idx << 16) | j );
|
{
|
||||||
fprintf( outfile, " \"\\tjmp __wine_delay_load_asm\\n\"\n" );
|
case CPU_x86:
|
||||||
#elif defined(__sparc__)
|
fprintf( outfile, " \"\\tmovl $%d, %%eax\\n\"\n", (idx << 16) | j );
|
||||||
fprintf( outfile, " \"\\tset %d, %%g1\\n\"\n", (idx << 16) | j );
|
fprintf( outfile, " \"\\tjmp %s\\n\"\n", asm_name("__wine_delay_load_asm") );
|
||||||
fprintf( outfile, " \"\\tb,a __wine_delay_load_asm\\n\"\n" );
|
break;
|
||||||
#elif defined(__powerpc__)
|
case CPU_SPARC:
|
||||||
#ifdef __APPLE__
|
fprintf( outfile, " \"\\tset %d, %%g1\\n\"\n", (idx << 16) | j );
|
||||||
/* On Darwin we can use r0 and r2 */
|
fprintf( outfile, " \"\\tb,a %s\\n\"\n", asm_name("__wine_delay_load_asm") );
|
||||||
/* Upper part in r2 */
|
break;
|
||||||
fprintf( outfile, " \"\\tlis %s, %d\\n\"\n", ppc_reg[2], idx);
|
case CPU_ALPHA:
|
||||||
/* Lower part + r2 -> r0, Note we can't use r0 directly */
|
fprintf( outfile, " \"\\tlda $0,%d($31)\\n\"\n", j);
|
||||||
fprintf( outfile, " \"\\taddi %s, %s, %d\\n\"\n", ppc_reg[0], ppc_reg[2], j);
|
fprintf( outfile, " \"\\tldah $0,%d($0)\\n\"\n", idx);
|
||||||
fprintf( outfile, " \"\\tb " __ASM_NAME("__wine_delay_load_asm") "\\n\"\n");
|
fprintf( outfile, " \"\\tjmp $31,%s\\n\"\n", asm_name("__wine_delay_load_asm") );
|
||||||
#else /* __APPLE__ */
|
break;
|
||||||
/* On linux we can't use r2 since r2 is not a scratch register (hold the TOC) */
|
case CPU_POWERPC:
|
||||||
/* Save r13 on the stack */
|
switch(target_platform)
|
||||||
fprintf( outfile, " \"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
|
{
|
||||||
fprintf( outfile, " \"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[13], ppc_reg[1]);
|
case PLATFORM_APPLE:
|
||||||
/* Upper part in r13 */
|
/* On Darwin we can use r0 and r2 */
|
||||||
fprintf( outfile, " \"\\tlis %s, %d\\n\"\n", ppc_reg[13], idx);
|
/* Upper part in r2 */
|
||||||
/* Lower part + r13 -> r0, Note we can't use r0 directly */
|
fprintf( outfile, " \"\\tlis %s, %d\\n\"\n", ppc_reg(2), idx);
|
||||||
fprintf( outfile, " \"\\taddi %s, %s, %d\\n\"\n", ppc_reg[0], ppc_reg[13], j);
|
/* Lower part + r2 -> r0, Note we can't use r0 directly */
|
||||||
/* Restore r13 */
|
fprintf( outfile, " \"\\taddi %s, %s, %d\\n\"\n", ppc_reg(0), ppc_reg(2), j);
|
||||||
fprintf( outfile, " \"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[13], ppc_reg[1]);
|
fprintf( outfile, " \"\\tb %s\\n\"\n", asm_name("__wine_delay_load_asm") );
|
||||||
fprintf( outfile, " \"\\taddic %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
|
break;
|
||||||
fprintf( outfile, " \"\\tb " __ASM_NAME("__wine_delay_load_asm") "\\n\"\n");
|
default:
|
||||||
#endif /* __APPLE__ */
|
/* On linux we can't use r2 since r2 is not a scratch register (hold the TOC) */
|
||||||
#elif defined(__ALPHA__)
|
/* Save r13 on the stack */
|
||||||
fprintf( outfile, " \"\\tlda $0,%d($31)\\n\"\n", j);
|
fprintf( outfile, " \"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg(1), ppc_reg(1));
|
||||||
fprintf( outfile, " \"\\tldah $0,%d($0)\\n\"\n", idx);
|
fprintf( outfile, " \"\\tstw %s, 0(%s)\\n\"\n", ppc_reg(13), ppc_reg(1));
|
||||||
fprintf( outfile, " \"\\tjmp $31,__wine_delay_load_asm\\n\"\n" );
|
/* Upper part in r13 */
|
||||||
#else
|
fprintf( outfile, " \"\\tlis %s, %d\\n\"\n", ppc_reg(13), idx);
|
||||||
#error You need to defined delayed import thunks for your architecture!
|
/* Lower part + r13 -> r0, Note we can't use r0 directly */
|
||||||
#endif
|
fprintf( outfile, " \"\\taddi %s, %s, %d\\n\"\n", ppc_reg(0), ppc_reg(13), j);
|
||||||
|
/* Restore r13 */
|
||||||
|
fprintf( outfile, " \"\\tstw %s, 0(%s)\\n\"\n", ppc_reg(13), ppc_reg(1));
|
||||||
|
fprintf( outfile, " \"\\taddic %s, %s, 0x4\\n\"\n", ppc_reg(1), ppc_reg(1));
|
||||||
|
fprintf( outfile, " \"\\tb %s\\n\"\n", asm_name("__wine_delay_load_asm") );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
output_function_size( outfile, name );
|
output_function_size( outfile, name );
|
||||||
}
|
}
|
||||||
idx++;
|
idx++;
|
||||||
|
@ -1065,7 +1130,7 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
|
||||||
output_function_size( outfile, delayed_import_loaders );
|
output_function_size( outfile, delayed_import_loaders );
|
||||||
|
|
||||||
fprintf( outfile, "\n \".align %d\\n\"\n", get_alignment(8) );
|
fprintf( outfile, "\n \".align %d\\n\"\n", get_alignment(8) );
|
||||||
fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\"\n", delayed_import_thunks);
|
fprintf( outfile, " \"%s:\\n\"\n", asm_name(delayed_import_thunks));
|
||||||
pos = nb_delayed * 32;
|
pos = nb_delayed * 32;
|
||||||
for (i = 0; i < nb_imports; i++)
|
for (i = 0; i < nb_imports; i++)
|
||||||
{
|
{
|
||||||
|
@ -1073,75 +1138,12 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
|
||||||
for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4)
|
for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4)
|
||||||
{
|
{
|
||||||
ORDDEF *odp = dll_imports[i]->imports[j];
|
ORDDEF *odp = dll_imports[i]->imports[j];
|
||||||
const char *name = odp->name ? odp->name : odp->export_name;
|
output_import_thunk( outfile, odp->name ? odp->name : odp->export_name,
|
||||||
|
"delay_imports", pos );
|
||||||
fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", name );
|
|
||||||
fprintf( outfile, " \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", name );
|
|
||||||
fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\\t\"", name );
|
|
||||||
#if defined(__i386__)
|
|
||||||
if (strstr( name, "__wine_call_from_16" ))
|
|
||||||
fprintf( outfile, "\".byte 0x2e\\n\\tjmp *(delay_imports+%d)\\n\\tnop\\n\"", pos );
|
|
||||||
else
|
|
||||||
fprintf( outfile, "\"jmp *(delay_imports+%d)\\n\\tmovl %%esi,%%esi\\n\"", pos );
|
|
||||||
#elif defined(__sparc__)
|
|
||||||
if ( !UsePIC )
|
|
||||||
{
|
|
||||||
fprintf( outfile, "\"sethi %%hi(delay_imports+%d), %%g1\\n\\t\"", pos );
|
|
||||||
fprintf( outfile, "\"ld [%%g1+%%lo(delay_imports+%d)], %%g1\\n\\t\"", pos );
|
|
||||||
fprintf( outfile, "\"jmp %%g1\\n\\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, "\"save %%sp, -96, %%sp\\n\"" );
|
|
||||||
fprintf( outfile, "\"0:\\tcall 1f\\n\\tnop\\n\"" );
|
|
||||||
fprintf( outfile, "\"1:\\tsethi %%hi(delay_imports+%d-0b), %%g1\\n\\t\"", pos );
|
|
||||||
fprintf( outfile, "\"or %%g1, %%lo(delay_imports+%d-0b), %%g1\\n\\t\"", pos );
|
|
||||||
fprintf( outfile, "\"ld [%%g1+%%o7], %%g1\\n\\t\"" );
|
|
||||||
fprintf( outfile, "\"jmp %%g1\\n\\trestore\\n\"" );
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(__powerpc__)
|
|
||||||
fprintf( outfile, "\t\"addi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
|
|
||||||
fprintf( outfile, "\t\"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[9], ppc_reg[1]);
|
|
||||||
fprintf( outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
|
|
||||||
fprintf( outfile, "\t\"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[8], ppc_reg[1]);
|
|
||||||
fprintf( outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
|
|
||||||
fprintf( outfile, "\t\"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[1]);
|
|
||||||
|
|
||||||
fprintf( outfile, "\t\"\\tlis %s, " ppc_high(__ASM_NAME("delay_imports") "+ %d") "\\n\"\n", ppc_reg[9], pos);
|
|
||||||
fprintf( outfile, "\t\"\\tla %s, " ppc_low (__ASM_NAME("delay_imports") "+ %d") "(%s)\\n\"\n", ppc_reg[8], pos, ppc_reg[9]);
|
|
||||||
fprintf( outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[8]);
|
|
||||||
fprintf( outfile, "\t\"\\tmtctr %s\\n\"\n", ppc_reg[7]);
|
|
||||||
|
|
||||||
fprintf( outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[1]);
|
|
||||||
fprintf( outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
|
|
||||||
fprintf( outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[8], ppc_reg[1]);
|
|
||||||
fprintf( outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
|
|
||||||
fprintf( outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[9], ppc_reg[1]);
|
|
||||||
fprintf( outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
|
|
||||||
fprintf( outfile, "\t\"\\tbctr\\n\"");
|
|
||||||
#elif defined(__ALPHA__)
|
|
||||||
fprintf( outfile, "\t\"lda $0,delay_imports\\n\"\n" );
|
|
||||||
fprintf( outfile, "\t\"\\tlda $0,%d($0)\\n\"\n", pos);
|
|
||||||
fprintf( outfile, "\t\"\\tjmp $31,($0)\\n\"" );
|
|
||||||
#else
|
|
||||||
#error You need to define delayed import thunks for your architecture!
|
|
||||||
#endif
|
|
||||||
fprintf( outfile, "\n" );
|
|
||||||
output_function_size( outfile, name );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output_function_size( outfile, delayed_import_thunks );
|
output_function_size( outfile, delayed_import_thunks );
|
||||||
fprintf( outfile, ");\n" );
|
fprintf( outfile, ");\n" );
|
||||||
fprintf( outfile, "#ifndef __GNUC__\n" );
|
|
||||||
fprintf( outfile, "}\n" );
|
|
||||||
fprintf( outfile, "#endif\n" );
|
|
||||||
fprintf( outfile, "\n" );
|
|
||||||
|
|
||||||
done:
|
|
||||||
return nb_delayed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* output the import and delayed import tables of a Win32 module
|
/* output the import and delayed import tables of a Win32 module
|
||||||
|
@ -1152,3 +1154,10 @@ int output_imports( FILE *outfile, DLLSPEC *spec, int *nb_delayed )
|
||||||
*nb_delayed = output_delayed_imports( outfile, spec );
|
*nb_delayed = output_delayed_imports( outfile, spec );
|
||||||
return output_immediate_imports( outfile );
|
return output_immediate_imports( outfile );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* output the import and delayed import thunks of a Win32 module */
|
||||||
|
void output_import_thunks( FILE *outfile, DLLSPEC *spec )
|
||||||
|
{
|
||||||
|
output_delayed_import_thunks( outfile, spec );
|
||||||
|
output_immediate_import_thunks( outfile );
|
||||||
|
}
|
||||||
|
|
|
@ -44,12 +44,28 @@ int nb_lib_paths = 0;
|
||||||
int nb_errors = 0;
|
int nb_errors = 0;
|
||||||
int display_warnings = 0;
|
int display_warnings = 0;
|
||||||
int kill_at = 0;
|
int kill_at = 0;
|
||||||
|
|
||||||
/* we only support relay debugging on i386 */
|
|
||||||
#ifdef __i386__
|
|
||||||
int debugging = 1;
|
|
||||||
#else
|
|
||||||
int debugging = 0;
|
int debugging = 0;
|
||||||
|
|
||||||
|
#ifdef __i386__
|
||||||
|
enum target_cpu target_cpu = CPU_x86;
|
||||||
|
#elif defined(__sparc__)
|
||||||
|
enum target_cpu target_cpu = CPU_SPARC;
|
||||||
|
#elif defined(__ALPHA__)
|
||||||
|
enum target_cpu target_cpu = CPU_ALPHA;
|
||||||
|
#elif defined(__powerpc__)
|
||||||
|
enum target_cpu target_cpu = CPU_POWERPC;
|
||||||
|
#else
|
||||||
|
#error Unsupported CPU
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
enum target_platform target_platform = PLATFORM_APPLE;
|
||||||
|
#elif defined(__svr4__)
|
||||||
|
enum target_platform target_platform = PLATFORM_SVR4;
|
||||||
|
#elif defined(_WINDOWS)
|
||||||
|
enum target_platform target_platform = PLATFORM_WINDOWS;
|
||||||
|
#else
|
||||||
|
enum target_platform target_platform = PLATFORM_UNSPECIFIED;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char **debug_channels = NULL;
|
char **debug_channels = NULL;
|
||||||
|
@ -454,6 +470,9 @@ int main(int argc, char **argv)
|
||||||
output_file = stdout;
|
output_file = stdout;
|
||||||
argv = parse_options( argc, argv, spec );
|
argv = parse_options( argc, argv, spec );
|
||||||
|
|
||||||
|
/* we only support relay debugging on i386 */
|
||||||
|
debugging = (target_cpu == CPU_x86);
|
||||||
|
|
||||||
switch(exec_mode)
|
switch(exec_mode)
|
||||||
{
|
{
|
||||||
case MODE_DLL:
|
case MODE_DLL:
|
||||||
|
|
|
@ -485,14 +485,12 @@ static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
|
||||||
assert( 0 );
|
assert( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __i386__
|
if ((target_cpu != CPU_x86) && (odp->flags & FLAG_I386))
|
||||||
if (odp->flags & FLAG_I386)
|
|
||||||
{
|
{
|
||||||
/* ignore this entry point on non-Intel archs */
|
/* ignore this entry point on non-Intel archs */
|
||||||
spec->nb_entry_points--;
|
spec->nb_entry_points--;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ordinal != -1)
|
if (ordinal != -1)
|
||||||
{
|
{
|
||||||
|
@ -627,17 +625,17 @@ static void assign_ordinals( DLLSPEC *spec )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now assign ordinals to the rest */
|
/* now assign ordinals to the rest */
|
||||||
for (i = 0, ordinal = spec->base; i < spec->nb_names; i++)
|
for (i = 0, ordinal = spec->base; i < spec->nb_entry_points; i++)
|
||||||
{
|
{
|
||||||
if (spec->names[i]->ordinal != -1) continue; /* already has an ordinal */
|
if (spec->entry_points[i].ordinal != -1) continue;
|
||||||
while (spec->ordinals[ordinal]) ordinal++;
|
while (spec->ordinals[ordinal]) ordinal++;
|
||||||
if (ordinal >= MAX_ORDINALS)
|
if (ordinal >= MAX_ORDINALS)
|
||||||
{
|
{
|
||||||
current_line = spec->names[i]->lineno;
|
current_line = spec->entry_points[i].lineno;
|
||||||
fatal_error( "Too many functions defined (max %d)\n", MAX_ORDINALS );
|
fatal_error( "Too many functions defined (max %d)\n", MAX_ORDINALS );
|
||||||
}
|
}
|
||||||
spec->names[i]->ordinal = ordinal;
|
spec->entry_points[i].ordinal = ordinal;
|
||||||
spec->ordinals[ordinal] = spec->names[i];
|
spec->ordinals[ordinal] = &spec->entry_points[i];
|
||||||
}
|
}
|
||||||
if (ordinal > spec->limit) spec->limit = ordinal;
|
if (ordinal > spec->limit) spec->limit = ordinal;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,20 +31,24 @@
|
||||||
|
|
||||||
#include "build.h"
|
#include "build.h"
|
||||||
|
|
||||||
#ifdef __i386__
|
|
||||||
|
|
||||||
static void function_header( FILE *outfile, const char *name )
|
static void function_header( FILE *outfile, const char *name )
|
||||||
{
|
{
|
||||||
fprintf( outfile, "\n\t.align %d\n", get_alignment(4) );
|
fprintf( outfile, "\n\t.align %d\n", get_alignment(4) );
|
||||||
fprintf( outfile, "\t" __ASM_FUNC("%s") "\n", name );
|
fprintf( outfile, "\t%s\n", func_declaration(name) );
|
||||||
fprintf( outfile, "\t.globl " __ASM_NAME("%s") "\n", name );
|
fprintf( outfile, "\t.globl %s\n", asm_name(name) );
|
||||||
fprintf( outfile, __ASM_NAME("%s") ":\n", name );
|
fprintf( outfile, "%s:\n", asm_name(name) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void function_footer( FILE *outfile, const char *name )
|
static void function_footer( FILE *outfile, const char *name )
|
||||||
{
|
{
|
||||||
fprintf( outfile, ".size " __ASM_NAME("%s") ", . - " __ASM_NAME("%s") "\n", name, name );
|
const char *size = func_size( name );
|
||||||
|
if (size[0]) fprintf( outfile, "\t%s\n", size );
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const char *data16_prefix(void)
|
||||||
|
{
|
||||||
|
return (target_platform == PLATFORM_SVR4) ? "\tdata16\n" : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
|
@ -147,37 +151,31 @@ static void BuildCallFrom16Core( FILE *outfile, int reg_func, int thunk, int sho
|
||||||
|
|
||||||
if (UsePIC)
|
if (UsePIC)
|
||||||
{
|
{
|
||||||
fprintf( outfile, "\t.byte 0x2e\n\tmovl " __ASM_NAME("CallTo16_DataSelector@GOT") "(%%ecx), %%edx\n" );
|
fprintf( outfile, "\t.byte 0x2e\n\tmovl %s(%%ecx), %%edx\n", asm_name("CallTo16_DataSelector@GOT") );
|
||||||
fprintf( outfile, "\t.byte 0x2e\n\tmovl (%%edx), %%edx\n" );
|
fprintf( outfile, "\t.byte 0x2e\n\tmovl (%%edx), %%edx\n" );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
fprintf( outfile, "\t.byte 0x2e\n\tmovl " __ASM_NAME("CallTo16_DataSelector") ",%%edx\n" );
|
fprintf( outfile, "\t.byte 0x2e\n\tmovl %s,%%edx\n", asm_name("CallTo16_DataSelector") );
|
||||||
|
|
||||||
/* Load 32-bit segment registers */
|
/* Load 32-bit segment registers */
|
||||||
#ifdef __svr4__
|
fprintf( outfile, "%s\tmovw %%dx, %%ds\n", data16_prefix() );
|
||||||
fprintf( outfile, "\tdata16\n");
|
fprintf( outfile, "%s\tmovw %%dx, %%es\n", data16_prefix() );
|
||||||
#endif
|
|
||||||
fprintf( outfile, "\tmovw %%dx, %%ds\n" );
|
|
||||||
#ifdef __svr4__
|
|
||||||
fprintf( outfile, "\tdata16\n");
|
|
||||||
#endif
|
|
||||||
fprintf( outfile, "\tmovw %%dx, %%es\n" );
|
|
||||||
|
|
||||||
if ( UsePIC )
|
if ( UsePIC )
|
||||||
{
|
{
|
||||||
fprintf( outfile, "\tmovl " __ASM_NAME("CallTo16_TebSelector@GOT") "(%%ecx), %%edx\n" );
|
fprintf( outfile, "\tmovl %s(%%ecx), %%edx\n", asm_name("CallTo16_TebSelector@GOT") );
|
||||||
fprintf( outfile, "\tmovw (%%edx), %%fs\n" );
|
fprintf( outfile, "\tmovw (%%edx), %%fs\n" );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
fprintf( outfile, "\tmovw " __ASM_NAME("CallTo16_TebSelector") ", %%fs\n" );
|
fprintf( outfile, "\tmovw %s, %%fs\n", asm_name("CallTo16_TebSelector") );
|
||||||
|
|
||||||
fprintf( outfile, "\t.byte 0x64\n\tmov (%d),%%gs\n", STRUCTOFFSET(TEB,gs_sel) );
|
fprintf( outfile, "\t.byte 0x64\n\tmov (%d),%%gs\n", STRUCTOFFSET(TEB,gs_sel) );
|
||||||
|
|
||||||
/* Get address of wine_ldt_copy array into %ecx */
|
/* Get address of wine_ldt_copy array into %ecx */
|
||||||
if ( UsePIC )
|
if ( UsePIC )
|
||||||
fprintf( outfile, "\tmovl " __ASM_NAME("wine_ldt_copy@GOT") "(%%ecx), %%ecx\n" );
|
fprintf( outfile, "\tmovl %s(%%ecx), %%ecx\n", asm_name("wine_ldt_copy@GOT") );
|
||||||
else
|
else
|
||||||
fprintf( outfile, "\tmovl $" __ASM_NAME("wine_ldt_copy") ", %%ecx\n" );
|
fprintf( outfile, "\tmovl $%s, %%ecx\n", asm_name("wine_ldt_copy") );
|
||||||
|
|
||||||
/* Translate STACK16FRAME base to flat offset in %edx */
|
/* Translate STACK16FRAME base to flat offset in %edx */
|
||||||
fprintf( outfile, "\tmovw %%ss, %%dx\n" );
|
fprintf( outfile, "\tmovw %%ss, %%dx\n" );
|
||||||
|
@ -195,10 +193,7 @@ static void BuildCallFrom16Core( FILE *outfile, int reg_func, int thunk, int sho
|
||||||
fprintf( outfile, "\tpushl %%ebp\n" );
|
fprintf( outfile, "\tpushl %%ebp\n" );
|
||||||
|
|
||||||
/* Switch stacks */
|
/* Switch stacks */
|
||||||
#ifdef __svr4__
|
fprintf( outfile, "%s\t.byte 0x64\n\tmovw %%ss, (%d)\n", data16_prefix(), STACKOFFSET + 2 );
|
||||||
fprintf( outfile,"\tdata16\n");
|
|
||||||
#endif
|
|
||||||
fprintf( outfile, "\t.byte 0x64\n\tmovw %%ss, (%d)\n", STACKOFFSET + 2 );
|
|
||||||
fprintf( outfile, "\t.byte 0x64\n\tmovw %%sp, (%d)\n", STACKOFFSET );
|
fprintf( outfile, "\t.byte 0x64\n\tmovw %%sp, (%d)\n", STACKOFFSET );
|
||||||
fprintf( outfile, "\tpushl %%ds\n" );
|
fprintf( outfile, "\tpushl %%ds\n" );
|
||||||
fprintf( outfile, "\tpopl %%ss\n" );
|
fprintf( outfile, "\tpopl %%ss\n" );
|
||||||
|
@ -320,9 +315,9 @@ static void BuildCallFrom16Core( FILE *outfile, int reg_func, int thunk, int sho
|
||||||
fprintf( outfile, "\tpushl $0\n" );
|
fprintf( outfile, "\tpushl $0\n" );
|
||||||
|
|
||||||
if ( UsePIC )
|
if ( UsePIC )
|
||||||
fprintf( outfile, "\tcall " __ASM_NAME("RELAY_DebugCallFrom16@PLT") "\n ");
|
fprintf( outfile, "\tcall %s\n ", asm_name("RELAY_DebugCallFrom16@PLT"));
|
||||||
else
|
else
|
||||||
fprintf( outfile, "\tcall " __ASM_NAME("RELAY_DebugCallFrom16") "\n ");
|
fprintf( outfile, "\tcall %s\n ", asm_name("RELAY_DebugCallFrom16"));
|
||||||
|
|
||||||
fprintf( outfile, "\tpopl %%edx\n" );
|
fprintf( outfile, "\tpopl %%edx\n" );
|
||||||
fprintf( outfile, "\tpopl %%edx\n" );
|
fprintf( outfile, "\tpopl %%edx\n" );
|
||||||
|
@ -359,9 +354,9 @@ static void BuildCallFrom16Core( FILE *outfile, int reg_func, int thunk, int sho
|
||||||
fprintf( outfile, "\tpushl $0\n" );
|
fprintf( outfile, "\tpushl $0\n" );
|
||||||
|
|
||||||
if ( UsePIC )
|
if ( UsePIC )
|
||||||
fprintf( outfile, "\tcall " __ASM_NAME("RELAY_DebugCallFrom16Ret@PLT") "\n ");
|
fprintf( outfile, "\tcall %s\n ", asm_name("RELAY_DebugCallFrom16Ret@PLT"));
|
||||||
else
|
else
|
||||||
fprintf( outfile, "\tcall " __ASM_NAME("RELAY_DebugCallFrom16Ret") "\n ");
|
fprintf( outfile, "\tcall %s\n ", asm_name("RELAY_DebugCallFrom16Ret"));
|
||||||
|
|
||||||
fprintf( outfile, "\tpopl %%eax\n" );
|
fprintf( outfile, "\tpopl %%eax\n" );
|
||||||
fprintf( outfile, "\tpopl %%eax\n" );
|
fprintf( outfile, "\tpopl %%eax\n" );
|
||||||
|
@ -545,10 +540,7 @@ static void BuildCallTo16Core( FILE *outfile, int reg_func )
|
||||||
|
|
||||||
/* Switch to the 16-bit stack */
|
/* Switch to the 16-bit stack */
|
||||||
fprintf( outfile, "\tmovl %%esp,%%edx\n" );
|
fprintf( outfile, "\tmovl %%esp,%%edx\n" );
|
||||||
#ifdef __svr4__
|
fprintf( outfile, "%s\t.byte 0x64\n\tmovw (%d),%%ss\n", data16_prefix(), STACKOFFSET + 2);
|
||||||
fprintf( outfile,"\tdata16\n");
|
|
||||||
#endif
|
|
||||||
fprintf( outfile, "\t.byte 0x64\n\tmovw (%d),%%ss\n", STACKOFFSET + 2);
|
|
||||||
fprintf( outfile, "\t.byte 0x64\n\tmovw (%d),%%sp\n", STACKOFFSET );
|
fprintf( outfile, "\t.byte 0x64\n\tmovw (%d),%%sp\n", STACKOFFSET );
|
||||||
fprintf( outfile, "\t.byte 0x64\n\tmovl %%edx,(%d)\n", STACKOFFSET );
|
fprintf( outfile, "\t.byte 0x64\n\tmovl %%edx,(%d)\n", STACKOFFSET );
|
||||||
|
|
||||||
|
@ -625,26 +617,19 @@ static void BuildRet16Func( FILE *outfile )
|
||||||
|
|
||||||
/* Restore 32-bit segment registers */
|
/* Restore 32-bit segment registers */
|
||||||
|
|
||||||
fprintf( outfile, "\t.byte 0x2e\n\tmovl " __ASM_NAME("CallTo16_DataSelector") "-" __ASM_NAME("Call16_Ret_Start") ",%%edi\n" );
|
fprintf( outfile, "\t.byte 0x2e\n\tmovl %s", asm_name("CallTo16_DataSelector") );
|
||||||
#ifdef __svr4__
|
fprintf( outfile, "-%s,%%edi\n", asm_name("Call16_Ret_Start") );
|
||||||
fprintf( outfile, "\tdata16\n");
|
fprintf( outfile, "%s\tmovw %%di,%%ds\n", data16_prefix() );
|
||||||
#endif
|
fprintf( outfile, "%s\tmovw %%di,%%es\n", data16_prefix() );
|
||||||
fprintf( outfile, "\tmovw %%di,%%ds\n" );
|
|
||||||
#ifdef __svr4__
|
|
||||||
fprintf( outfile, "\tdata16\n");
|
|
||||||
#endif
|
|
||||||
fprintf( outfile, "\tmovw %%di,%%es\n" );
|
|
||||||
|
|
||||||
fprintf( outfile, "\t.byte 0x2e\n\tmov " __ASM_NAME("CallTo16_TebSelector") "-" __ASM_NAME("Call16_Ret_Start") ",%%fs\n" );
|
fprintf( outfile, "\t.byte 0x2e\n\tmov %s", asm_name("CallTo16_TebSelector") );
|
||||||
|
fprintf( outfile, "-%s,%%fs\n", asm_name("Call16_Ret_Start") );
|
||||||
|
|
||||||
fprintf( outfile, "\t.byte 0x64\n\tmov (%d),%%gs\n", STRUCTOFFSET(TEB,gs_sel) );
|
fprintf( outfile, "\t.byte 0x64\n\tmov (%d),%%gs\n", STRUCTOFFSET(TEB,gs_sel) );
|
||||||
|
|
||||||
/* Restore the 32-bit stack */
|
/* Restore the 32-bit stack */
|
||||||
|
|
||||||
#ifdef __svr4__
|
fprintf( outfile, "%s\tmovw %%di,%%ss\n", data16_prefix() );
|
||||||
fprintf( outfile, "\tdata16\n");
|
|
||||||
#endif
|
|
||||||
fprintf( outfile, "\tmovw %%di,%%ss\n" );
|
|
||||||
fprintf( outfile, "\t.byte 0x64\n\tmovl (%d),%%esp\n", STACKOFFSET );
|
fprintf( outfile, "\t.byte 0x64\n\tmovl (%d),%%esp\n", STACKOFFSET );
|
||||||
|
|
||||||
/* Return to caller */
|
/* Return to caller */
|
||||||
|
@ -657,10 +642,10 @@ static void BuildRet16Func( FILE *outfile )
|
||||||
/* Declare the return address and data selector variables */
|
/* Declare the return address and data selector variables */
|
||||||
|
|
||||||
fprintf( outfile, "\n\t.align %d\n", get_alignment(4) );
|
fprintf( outfile, "\n\t.align %d\n", get_alignment(4) );
|
||||||
fprintf( outfile, "\t.globl " __ASM_NAME("CallTo16_DataSelector") "\n" );
|
fprintf( outfile, "\t.globl %s\n", asm_name("CallTo16_DataSelector") );
|
||||||
fprintf( outfile, __ASM_NAME("CallTo16_DataSelector") ":\t.long 0\n" );
|
fprintf( outfile, "%s:\t.long 0\n", asm_name("CallTo16_DataSelector") );
|
||||||
fprintf( outfile, "\t.globl " __ASM_NAME("CallTo16_TebSelector") "\n" );
|
fprintf( outfile, "\t.globl %s\n", asm_name("CallTo16_TebSelector") );
|
||||||
fprintf( outfile, __ASM_NAME("CallTo16_TebSelector") ":\t.long 0\n" );
|
fprintf( outfile, "%s:\t.long 0\n", asm_name("CallTo16_TebSelector") );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -756,14 +741,14 @@ static void BuildRet16Func( FILE *outfile )
|
||||||
*/
|
*/
|
||||||
static void BuildCallTo32CBClient( FILE *outfile, BOOL isEx )
|
static void BuildCallTo32CBClient( FILE *outfile, BOOL isEx )
|
||||||
{
|
{
|
||||||
const char *name = isEx? "CBClientEx" : "CBClient";
|
const char *name = isEx? "CALL32_CBClientEx" : "CALL32_CBClient";
|
||||||
int size = isEx? 24 : 12;
|
int size = isEx? 24 : 12;
|
||||||
|
|
||||||
/* Function header */
|
/* Function header */
|
||||||
|
|
||||||
fprintf( outfile, "\n\t.align %d\n", get_alignment(4) );
|
fprintf( outfile, "\n\t.align %d\n", get_alignment(4) );
|
||||||
fprintf( outfile, "\t.globl " __ASM_NAME("CALL32_%s") "\n", name );
|
fprintf( outfile, "\t.globl %s\n", asm_name(name) );
|
||||||
fprintf( outfile, __ASM_NAME("CALL32_%s") ":\n", name );
|
fprintf( outfile, "%s:\n", asm_name(name) );
|
||||||
|
|
||||||
/* Entry code */
|
/* Entry code */
|
||||||
|
|
||||||
|
@ -773,6 +758,15 @@ static void BuildCallTo32CBClient( FILE *outfile, BOOL isEx )
|
||||||
fprintf( outfile, "\tpushl %%esi\n" );
|
fprintf( outfile, "\tpushl %%esi\n" );
|
||||||
fprintf( outfile, "\tpushl %%ebx\n" );
|
fprintf( outfile, "\tpushl %%ebx\n" );
|
||||||
|
|
||||||
|
if (UsePIC)
|
||||||
|
{
|
||||||
|
/* Get Global Offset Table into %edx */
|
||||||
|
fprintf( outfile, "\tcall .L__wine_%s.getgot1\n", name );
|
||||||
|
fprintf( outfile, ".L__wine_%s.getgot1:\n", name );
|
||||||
|
fprintf( outfile, "\tpopl %%edx\n" );
|
||||||
|
fprintf( outfile, "\taddl $_GLOBAL_OFFSET_TABLE_+[.-.L__wine_%s.getgot1], %%edx\n", name );
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the 16-bit stack */
|
/* Get the 16-bit stack */
|
||||||
|
|
||||||
fprintf( outfile, "\t.byte 0x64\n\tmovl (%d),%%ebx\n", STACKOFFSET);
|
fprintf( outfile, "\t.byte 0x64\n\tmovl (%d),%%ebx\n", STACKOFFSET);
|
||||||
|
@ -782,7 +776,13 @@ static void BuildCallTo32CBClient( FILE *outfile, BOOL isEx )
|
||||||
fprintf( outfile, "\tshldl $16,%%ebx,%%eax\n" );
|
fprintf( outfile, "\tshldl $16,%%ebx,%%eax\n" );
|
||||||
fprintf( outfile, "\tandl $0xfff8,%%eax\n" );
|
fprintf( outfile, "\tandl $0xfff8,%%eax\n" );
|
||||||
fprintf( outfile, "\tshrl $1,%%eax\n" );
|
fprintf( outfile, "\tshrl $1,%%eax\n" );
|
||||||
fprintf( outfile, "\tmovl " __ASM_NAME("wine_ldt_copy") "(%%eax),%%esi\n" );
|
if (!UsePIC)
|
||||||
|
fprintf( outfile, "\tmovl %s(%%eax),%%esi\n", asm_name("wine_ldt_copy") );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf( outfile, "\tmovl %s(%%edx), %%esi\n", asm_name("wine_ldt_copy@GOT") );
|
||||||
|
fprintf( outfile, "\tmovl (%%esi,%%eax), %%esi\n" );
|
||||||
|
}
|
||||||
fprintf( outfile, "\tmovw %%bx,%%ax\n" );
|
fprintf( outfile, "\tmovw %%bx,%%ax\n" );
|
||||||
fprintf( outfile, "\taddl %%eax,%%esi\n" );
|
fprintf( outfile, "\taddl %%eax,%%esi\n" );
|
||||||
|
|
||||||
|
@ -815,7 +815,13 @@ static void BuildCallTo32CBClient( FILE *outfile, BOOL isEx )
|
||||||
fprintf( outfile, "\taddl $%d, %%ebx\n", sizeof(STACK16FRAME)-size+4 + 4 );
|
fprintf( outfile, "\taddl $%d, %%ebx\n", sizeof(STACK16FRAME)-size+4 + 4 );
|
||||||
fprintf( outfile, "\tmovl %%ebx, 0(%%edi)\n" ); /* 16-bit ss:sp */
|
fprintf( outfile, "\tmovl %%ebx, 0(%%edi)\n" ); /* 16-bit ss:sp */
|
||||||
|
|
||||||
fprintf( outfile, "\tmovl " __ASM_NAME("CALL32_%s_RetAddr") ", %%eax\n", name );
|
if (!UsePIC)
|
||||||
|
fprintf( outfile, "\tmovl %s_RetAddr, %%eax\n", asm_name(name) );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf( outfile, "\tmovl %s_RetAddr@GOT(%%edx), %%eax\n", asm_name(name) );
|
||||||
|
fprintf( outfile, "\tmovl (%%eax), %%eax\n" );
|
||||||
|
}
|
||||||
fprintf( outfile, "\tmovl %%eax, 4(%%edi)\n" ); /* overwrite return address */
|
fprintf( outfile, "\tmovl %%eax, 4(%%edi)\n" ); /* overwrite return address */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -836,7 +842,13 @@ static void BuildCallTo32CBClient( FILE *outfile, BOOL isEx )
|
||||||
fprintf( outfile, "\tandl $0x0000ffff, %%eax\n" );
|
fprintf( outfile, "\tandl $0x0000ffff, %%eax\n" );
|
||||||
fprintf( outfile, "\tmovl %%eax, 16(%%edi)\n" );
|
fprintf( outfile, "\tmovl %%eax, 16(%%edi)\n" );
|
||||||
|
|
||||||
fprintf( outfile, "\tmovl " __ASM_NAME("CALL32_%s_RetAddr") ", %%eax\n", name );
|
if (!UsePIC)
|
||||||
|
fprintf( outfile, "\tmovl %s_RetAddr, %%eax\n", asm_name(name) );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf( outfile, "\tmovl %s_RetAddr@GOT(%%edx), %%eax\n", asm_name(name) );
|
||||||
|
fprintf( outfile, "\tmovl (%%eax), %%eax\n" );
|
||||||
|
}
|
||||||
fprintf( outfile, "\tmovl %%eax, 20(%%edi)\n" );
|
fprintf( outfile, "\tmovl %%eax, 20(%%edi)\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -885,17 +897,17 @@ static void BuildCallTo32CBClient( FILE *outfile, BOOL isEx )
|
||||||
fprintf( outfile, "\tpopl %%edi\n" );
|
fprintf( outfile, "\tpopl %%edi\n" );
|
||||||
fprintf( outfile, "\tpopl %%ebp\n" );
|
fprintf( outfile, "\tpopl %%ebp\n" );
|
||||||
fprintf( outfile, "\tret\n" );
|
fprintf( outfile, "\tret\n" );
|
||||||
fprintf( outfile, ".size " __ASM_NAME("CALL32_%s") ", . - " __ASM_NAME("CALL32_%s") "\n", name, name );
|
function_footer( outfile, name );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BuildCallTo32CBClientRet( FILE *outfile, BOOL isEx )
|
static void BuildCallTo32CBClientRet( FILE *outfile, BOOL isEx )
|
||||||
{
|
{
|
||||||
const char *name = isEx? "CBClientEx" : "CBClient";
|
const char *name = isEx? "CALL32_CBClientEx_Ret" : "CALL32_CBClient_Ret";
|
||||||
|
|
||||||
/* '16-bit' return stub */
|
/* '16-bit' return stub */
|
||||||
|
|
||||||
fprintf( outfile, "\n\t.globl " __ASM_NAME("CALL32_%s_Ret") "\n", name );
|
fprintf( outfile, "\n\t.globl %s\n", asm_name(name) );
|
||||||
fprintf( outfile, __ASM_NAME("CALL32_%s_Ret") ":\n", name );
|
fprintf( outfile, "%s:\n", asm_name(name) );
|
||||||
|
|
||||||
if ( !isEx )
|
if ( !isEx )
|
||||||
{
|
{
|
||||||
|
@ -910,13 +922,12 @@ static void BuildCallTo32CBClientRet( FILE *outfile, BOOL isEx )
|
||||||
fprintf( outfile, "\tlssl %%ss:-12(%%ebx), %%esp\n" );
|
fprintf( outfile, "\tlssl %%ss:-12(%%ebx), %%esp\n" );
|
||||||
}
|
}
|
||||||
fprintf( outfile, "\tlret\n" );
|
fprintf( outfile, "\tlret\n" );
|
||||||
|
function_footer( outfile, name );
|
||||||
fprintf( outfile, ".size " __ASM_NAME("CALL32_%s_Ret") ", . - " __ASM_NAME("CALL32_%s_Ret") "\n", name, name );
|
|
||||||
|
|
||||||
/* Declare the return address variable */
|
/* Declare the return address variable */
|
||||||
|
|
||||||
fprintf( outfile, "\n\t.globl " __ASM_NAME("CALL32_%s_RetAddr") "\n", name );
|
fprintf( outfile, "\n\t.globl %sAddr\n", asm_name(name) );
|
||||||
fprintf( outfile, __ASM_NAME("CALL32_%s_RetAddr") ":\t.long 0\n", name );
|
fprintf( outfile, "%sAddr:\t.long 0\n", asm_name(name) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1011,7 +1022,8 @@ static void BuildCallFrom32Regs( FILE *outfile )
|
||||||
|
|
||||||
/* Call the entry point */
|
/* Call the entry point */
|
||||||
|
|
||||||
fprintf( outfile, "\tcall *0(%%ebx)\n" );
|
fprintf( outfile, "\taddl (%%ebx),%%ebx\n" );
|
||||||
|
fprintf( outfile, "\tcall *%%ebx\n" );
|
||||||
fprintf( outfile, "\tleal -%d(%%ebp),%%ecx\n", STACK_SPACE );
|
fprintf( outfile, "\tleal -%d(%%ebp),%%ecx\n", STACK_SPACE );
|
||||||
|
|
||||||
/* Restore the context structure */
|
/* Restore the context structure */
|
||||||
|
@ -1074,30 +1086,30 @@ static void BuildPendingEventCheck( FILE *outfile )
|
||||||
function_header( outfile, "DPMI_PendingEventCheck" );
|
function_header( outfile, "DPMI_PendingEventCheck" );
|
||||||
|
|
||||||
/* Check for pending events. */
|
/* Check for pending events. */
|
||||||
|
|
||||||
fprintf( outfile, "\t.byte 0x64\n\ttestl $0xffffffff,(%d)\n",
|
|
||||||
STRUCTOFFSET(TEB,vm86_pending) );
|
|
||||||
fprintf( outfile, "\tje " __ASM_NAME("DPMI_PendingEventCheck_Cleanup") "\n" );
|
|
||||||
|
|
||||||
fprintf( outfile, "\t.byte 0x64\n\ttestl $0xffffffff,(%d)\n",
|
fprintf( outfile, "\t.byte 0x64\n\ttestl $0xffffffff,(%d)\n",
|
||||||
|
STRUCTOFFSET(TEB,vm86_pending) );
|
||||||
|
fprintf( outfile, "\tje %s\n", asm_name("DPMI_PendingEventCheck_Cleanup") );
|
||||||
|
|
||||||
|
fprintf( outfile, "\t.byte 0x64\n\ttestl $0xffffffff,(%d)\n",
|
||||||
STRUCTOFFSET(TEB,dpmi_vif) );
|
STRUCTOFFSET(TEB,dpmi_vif) );
|
||||||
|
|
||||||
fprintf( outfile, "\tje " __ASM_NAME("DPMI_PendingEventCheck_Cleanup") "\n" );
|
fprintf( outfile, "\tje %s\n", asm_name("DPMI_PendingEventCheck_Cleanup") );
|
||||||
|
|
||||||
/* Process pending events. */
|
/* Process pending events. */
|
||||||
|
|
||||||
fprintf( outfile, "\tsti\n" );
|
fprintf( outfile, "\tsti\n" );
|
||||||
|
|
||||||
/* Start cleanup. Restore fs register. */
|
/* Start cleanup. Restore fs register. */
|
||||||
|
|
||||||
fprintf( outfile, ".globl " __ASM_NAME("DPMI_PendingEventCheck_Cleanup") "\n" );
|
fprintf( outfile, ".globl %s\n", asm_name("DPMI_PendingEventCheck_Cleanup") );
|
||||||
fprintf( outfile, __ASM_NAME("DPMI_PendingEventCheck_Cleanup") ":\n" );
|
fprintf( outfile, "%s:\n", asm_name("DPMI_PendingEventCheck_Cleanup") );
|
||||||
fprintf( outfile, "\tpopw %%fs\n" );
|
fprintf( outfile, "\tpopw %%fs\n" );
|
||||||
|
|
||||||
/* Return from function. */
|
/* Return from function. */
|
||||||
|
|
||||||
fprintf( outfile, ".globl " __ASM_NAME("DPMI_PendingEventCheck_Return") "\n" );
|
fprintf( outfile, ".globl %s\n", asm_name("DPMI_PendingEventCheck_Return") );
|
||||||
fprintf( outfile, __ASM_NAME("DPMI_PendingEventCheck_Return") ":\n" );
|
fprintf( outfile, "%s:\n", asm_name("DPMI_PendingEventCheck_Return") );
|
||||||
fprintf( outfile, "\tiret\n" );
|
fprintf( outfile, "\tiret\n" );
|
||||||
|
|
||||||
function_footer( outfile, "DPMI_PendingEventCheck" );
|
function_footer( outfile, "DPMI_PendingEventCheck" );
|
||||||
|
@ -1111,15 +1123,21 @@ static void BuildPendingEventCheck( FILE *outfile )
|
||||||
*/
|
*/
|
||||||
void BuildRelays16( FILE *outfile )
|
void BuildRelays16( FILE *outfile )
|
||||||
{
|
{
|
||||||
|
if (target_cpu != CPU_x86)
|
||||||
|
{
|
||||||
|
fprintf( outfile, "/* File not used with this architecture. Do not edit! */\n\n" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* File header */
|
/* File header */
|
||||||
|
|
||||||
fprintf( outfile, "/* File generated automatically. Do not edit! */\n\n" );
|
fprintf( outfile, "/* File generated automatically. Do not edit! */\n\n" );
|
||||||
fprintf( outfile, "\t.text\n" );
|
fprintf( outfile, "\t.text\n" );
|
||||||
|
|
||||||
fprintf( outfile, __ASM_NAME("__wine_spec_thunk_text_16") ":\n\n" );
|
fprintf( outfile, "%s:\n\n", asm_name("__wine_spec_thunk_text_16") );
|
||||||
|
|
||||||
fprintf( outfile, __ASM_NAME("Call16_Start") ":\n" );
|
fprintf( outfile, "\t.globl %s\n", asm_name("Call16_Start") );
|
||||||
fprintf( outfile, "\t.globl " __ASM_NAME("Call16_Start") "\n" );
|
fprintf( outfile, "%s:\n", asm_name("Call16_Start") );
|
||||||
fprintf( outfile, "\t.byte 0\n\n" );
|
fprintf( outfile, "\t.byte 0\n\n" );
|
||||||
|
|
||||||
/* Standard CallFrom16 routine (WORD return) */
|
/* Standard CallFrom16 routine (WORD return) */
|
||||||
|
@ -1146,15 +1164,15 @@ void BuildRelays16( FILE *outfile )
|
||||||
/* CBClientThunkSLEx routine */
|
/* CBClientThunkSLEx routine */
|
||||||
BuildCallTo32CBClient( outfile, TRUE );
|
BuildCallTo32CBClient( outfile, TRUE );
|
||||||
|
|
||||||
fprintf( outfile, __ASM_NAME("Call16_End") ":\n" );
|
fprintf( outfile, "\t.globl %s\n", asm_name("Call16_End") );
|
||||||
fprintf( outfile, "\t.globl " __ASM_NAME("Call16_End") "\n" );
|
fprintf( outfile, "%s:\n", asm_name("Call16_End") );
|
||||||
fprintf( outfile, "\t.size " __ASM_NAME("__wine_spec_thunk_text_16") ",. - " __ASM_NAME("__wine_spec_thunk_text_16") "\n" );
|
function_footer( outfile, "__wine_spec_thunk_text_16" );
|
||||||
|
|
||||||
/* The whole Call16_Ret segment must lie within the .data section */
|
/* The whole Call16_Ret segment must lie within the .data section */
|
||||||
fprintf( outfile, "\n\t.data\n" );
|
fprintf( outfile, "\n\t.data\n" );
|
||||||
fprintf( outfile, __ASM_NAME("__wine_spec_thunk_data_16") ":\n\n" );
|
fprintf( outfile, "%s:\n\n", asm_name("__wine_spec_thunk_data_16") );
|
||||||
fprintf( outfile, "\t.globl " __ASM_NAME("Call16_Ret_Start") "\n" );
|
fprintf( outfile, "\t.globl %s\n", asm_name("Call16_Ret_Start") );
|
||||||
fprintf( outfile, __ASM_NAME("Call16_Ret_Start") ":\n" );
|
fprintf( outfile, "%s:\n", asm_name("Call16_Ret_Start") );
|
||||||
|
|
||||||
/* Standard CallTo16 return stub */
|
/* Standard CallTo16 return stub */
|
||||||
BuildRet16Func( outfile );
|
BuildRet16Func( outfile );
|
||||||
|
@ -1169,9 +1187,9 @@ void BuildRelays16( FILE *outfile )
|
||||||
BuildPendingEventCheck( outfile );
|
BuildPendingEventCheck( outfile );
|
||||||
|
|
||||||
/* End of Call16_Ret segment */
|
/* End of Call16_Ret segment */
|
||||||
fprintf( outfile, "\n\t.globl " __ASM_NAME("Call16_Ret_End") "\n" );
|
fprintf( outfile, "\n\t.globl %s\n", asm_name("Call16_Ret_End") );
|
||||||
fprintf( outfile, __ASM_NAME("Call16_Ret_End") ":\n" );
|
fprintf( outfile, "%s:\n", asm_name("Call16_Ret_End") );
|
||||||
fprintf( outfile, "\t.size " __ASM_NAME("__wine_spec_thunk_data_16") ",. - " __ASM_NAME("__wine_spec_thunk_data_16") "\n" );
|
function_footer( outfile, "__wine_spec_thunk_data_16" );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
|
@ -1181,28 +1199,20 @@ void BuildRelays16( FILE *outfile )
|
||||||
*/
|
*/
|
||||||
void BuildRelays32( FILE *outfile )
|
void BuildRelays32( FILE *outfile )
|
||||||
{
|
{
|
||||||
|
if (target_cpu != CPU_x86)
|
||||||
|
{
|
||||||
|
fprintf( outfile, "/* File not used with this architecture. Do not edit! */\n\n" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* File header */
|
/* File header */
|
||||||
|
|
||||||
fprintf( outfile, "/* File generated automatically. Do not edit! */\n\n" );
|
fprintf( outfile, "/* File generated automatically. Do not edit! */\n\n" );
|
||||||
fprintf( outfile, "\t.text\n" );
|
fprintf( outfile, "\t.text\n" );
|
||||||
fprintf( outfile, __ASM_NAME("__wine_spec_thunk_text_32") ":\n\n" );
|
fprintf( outfile, "%s:\n\n", asm_name("__wine_spec_thunk_text_32") );
|
||||||
|
|
||||||
/* 32-bit register entry point */
|
/* 32-bit register entry point */
|
||||||
BuildCallFrom32Regs( outfile );
|
BuildCallFrom32Regs( outfile );
|
||||||
|
|
||||||
fprintf( outfile, "\t.size " __ASM_NAME("__wine_spec_thunk_text_32") ",. - " __ASM_NAME("__wine_spec_thunk_text_32") "\n" );
|
function_footer( outfile, "__wine_spec_thunk_text_32" );
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* __i386__ */
|
|
||||||
|
|
||||||
void BuildRelays16( FILE *outfile )
|
|
||||||
{
|
|
||||||
fprintf( outfile, "/* File not used with this architecture. Do not edit! */\n\n" );
|
|
||||||
}
|
|
||||||
|
|
||||||
void BuildRelays32( FILE *outfile )
|
|
||||||
{
|
|
||||||
fprintf( outfile, "/* File not used with this architecture. Do not edit! */\n\n" );
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* __i386__ */
|
|
||||||
|
|
|
@ -329,22 +329,6 @@ void output_resources( FILE *outfile, DLLSPEC *spec )
|
||||||
|
|
||||||
tree = build_resource_tree( spec );
|
tree = build_resource_tree( spec );
|
||||||
|
|
||||||
/* resource data */
|
|
||||||
|
|
||||||
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
|
|
||||||
{
|
|
||||||
const unsigned int *p = res->data;
|
|
||||||
int size = res->data_size / 4;
|
|
||||||
/* dump data as ints to ensure correct alignment */
|
|
||||||
fprintf( outfile, "static const unsigned int res_%d[%d] = {\n ", i, size );
|
|
||||||
for (j = 0; j < size - 1; j++, p++)
|
|
||||||
{
|
|
||||||
fprintf( outfile, "0x%08x,", *p );
|
|
||||||
if ((j % 8) == 7) fprintf( outfile, "\n " );
|
|
||||||
}
|
|
||||||
fprintf( outfile, "0x%08x\n};\n\n", *p );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* directory structures */
|
/* directory structures */
|
||||||
|
|
||||||
fprintf( outfile, "struct res_dir {\n" );
|
fprintf( outfile, "struct res_dir {\n" );
|
||||||
|
@ -412,10 +396,12 @@ void output_resources( FILE *outfile, DLLSPEC *spec )
|
||||||
else name->name_offset = name->name->id;
|
else name->name_offset = name->name->id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
|
||||||
|
fprintf( outfile, " unsigned int res_%d[%d];\n", i, res->data_size / 4 );
|
||||||
|
|
||||||
/* resource directory contents */
|
/* resource directory contents */
|
||||||
|
|
||||||
fprintf( outfile, "} resources = {\n" );
|
fprintf( outfile, "} __wine_spec_resources = {\n" );
|
||||||
fprintf( outfile, " { 0, 0, 0, 0, %d, %d },\n", tree->nb_types - nb_id_types, nb_id_types );
|
fprintf( outfile, " { 0, 0, 0, 0, %d, %d },\n", tree->nb_types - nb_id_types, nb_id_types );
|
||||||
|
|
||||||
/* dump the type directory */
|
/* dump the type directory */
|
||||||
|
@ -463,7 +449,7 @@ void output_resources( FILE *outfile, DLLSPEC *spec )
|
||||||
fprintf( outfile, " {\n" );
|
fprintf( outfile, " {\n" );
|
||||||
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
|
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
|
||||||
{
|
{
|
||||||
fprintf( outfile, " { res_%d, sizeof(res_%d), 0, 0 }, /* %08x */\n", i, i,
|
fprintf( outfile, " { __wine_spec_resources.res_%d, sizeof(__wine_spec_resources.res_%d), 0, 0 }, /* %08x */\n", i, i,
|
||||||
data_offset + i * 4 * sizeof(int) );
|
data_offset + i * 4 * sizeof(int) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -484,6 +470,24 @@ void output_resources( FILE *outfile, DLLSPEC *spec )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf( outfile, " }\n};\n\n" );
|
fprintf( outfile, " },\n" );
|
||||||
|
|
||||||
|
/* resource data */
|
||||||
|
|
||||||
|
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
|
||||||
|
{
|
||||||
|
const unsigned int *p = res->data;
|
||||||
|
int size = res->data_size / 4;
|
||||||
|
/* dump data as ints to ensure correct alignment */
|
||||||
|
fprintf( outfile, " { /* res_%d */\n ", i );
|
||||||
|
for (j = 0; j < size - 1; j++, p++)
|
||||||
|
{
|
||||||
|
fprintf( outfile, "0x%08x,", *p );
|
||||||
|
if ((j % 8) == 7) fprintf( outfile, "\n " );
|
||||||
|
}
|
||||||
|
fprintf( outfile, "0x%08x\n },\n", *p );
|
||||||
|
}
|
||||||
|
fprintf( outfile, "};\n\n" );
|
||||||
|
|
||||||
free_resource_tree( tree );
|
free_resource_tree( tree );
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,20 +36,18 @@
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
* get_cs
|
* get_cs
|
||||||
*/
|
*/
|
||||||
#ifdef __i386__
|
|
||||||
static inline unsigned short get_cs(void)
|
static inline unsigned short get_cs(void)
|
||||||
{
|
{
|
||||||
unsigned short res;
|
unsigned short res = 0;
|
||||||
#ifdef __GNUC__
|
#ifdef __i386__
|
||||||
|
# ifdef __GNUC__
|
||||||
__asm__("movw %%cs,%w0" : "=r"(res));
|
__asm__("movw %%cs,%w0" : "=r"(res));
|
||||||
#elif defined(_MSC_VER)
|
# elif defined(_MSC_VER)
|
||||||
__asm { mov res, cs }
|
__asm { mov res, cs }
|
||||||
#else
|
# endif
|
||||||
res = 0;
|
#endif /* __i386__ */
|
||||||
#endif
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
#endif /* __i386__ */
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
|
@ -65,11 +63,7 @@ static void output_file_header( FILE *outfile )
|
||||||
fprintf( outfile, " unsigned long limit[8192];\n" );
|
fprintf( outfile, " unsigned long limit[8192];\n" );
|
||||||
fprintf( outfile, " unsigned char flags[8192];\n" );
|
fprintf( outfile, " unsigned char flags[8192];\n" );
|
||||||
fprintf( outfile, "} wine_ldt_copy;\n\n" );
|
fprintf( outfile, "} wine_ldt_copy;\n\n" );
|
||||||
#ifdef __i386__
|
|
||||||
fprintf( outfile, "#define __stdcall __attribute__((__stdcall__))\n\n" );
|
fprintf( outfile, "#define __stdcall __attribute__((__stdcall__))\n\n" );
|
||||||
#else
|
|
||||||
fprintf( outfile, "#define __stdcall\n\n" );
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -166,7 +160,6 @@ static void output_bytes( FILE *outfile, const void *buffer, unsigned int size )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __i386__
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
* BuildCallFrom16Func
|
* BuildCallFrom16Func
|
||||||
*
|
*
|
||||||
|
@ -310,7 +303,6 @@ static void BuildCallFrom16Func( FILE *outfile, const char *profile, const char
|
||||||
fprintf( outfile, "%s args + %d", i? ",\n" : "", argsize );
|
fprintf( outfile, "%s args + %d", i? ",\n" : "", argsize );
|
||||||
fprintf( outfile, " );\n}\n\n" );
|
fprintf( outfile, " );\n}\n\n" );
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
|
@ -416,9 +408,7 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
|
||||||
unsigned int et_size, et_offset;
|
unsigned int et_size, et_offset;
|
||||||
|
|
||||||
char constructor[100], destructor[100];
|
char constructor[100], destructor[100];
|
||||||
#ifdef __i386__
|
|
||||||
unsigned short code_selector = get_cs();
|
unsigned short code_selector = get_cs();
|
||||||
#endif
|
|
||||||
|
|
||||||
/* File header */
|
/* File header */
|
||||||
|
|
||||||
|
@ -473,7 +463,6 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Output CallFrom16 routines needed by this .spec file */
|
/* Output CallFrom16 routines needed by this .spec file */
|
||||||
#ifdef __i386__
|
|
||||||
for ( i = 0; i < nTypes; i++ )
|
for ( i = 0; i < nTypes; i++ )
|
||||||
{
|
{
|
||||||
char profile[101];
|
char profile[101];
|
||||||
|
@ -481,17 +470,11 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
|
||||||
strcpy( profile, get_function_name( typelist[i] ));
|
strcpy( profile, get_function_name( typelist[i] ));
|
||||||
BuildCallFrom16Func( outfile, profile, spec->file_name );
|
BuildCallFrom16Func( outfile, profile, spec->file_name );
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* compute code and data sizes, set offsets, and output prototypes */
|
/* compute code and data sizes, set offsets, and output prototypes */
|
||||||
|
|
||||||
#ifdef __i386__
|
|
||||||
entrypoint_size = 2 + 5 + 4; /* pushw bp + pushl target + call */
|
entrypoint_size = 2 + 5 + 4; /* pushw bp + pushl target + call */
|
||||||
callfrom_size = 5 + 7 + 4 + 8; /* pushl relay + lcall cs:glue + lret n + args */
|
callfrom_size = 5 + 7 + 4 + 8; /* pushl relay + lcall cs:glue + lret n + args */
|
||||||
#else
|
|
||||||
entrypoint_size = 4 + 4; /* target + call */
|
|
||||||
callfrom_size = 4 + 8; /* lret n + args */
|
|
||||||
#endif
|
|
||||||
code_size = nTypes * callfrom_size;
|
code_size = nTypes * callfrom_size;
|
||||||
|
|
||||||
for (i = 0; i <= spec->limit; i++)
|
for (i = 0; i <= spec->limit; i++)
|
||||||
|
@ -638,22 +621,18 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
|
||||||
|
|
||||||
code_offset = et_offset + et_size;
|
code_offset = et_offset + et_size;
|
||||||
fprintf( outfile, " struct {\n" );
|
fprintf( outfile, " struct {\n" );
|
||||||
#ifdef __i386__
|
|
||||||
fprintf( outfile, " unsigned char pushl;\n" ); /* pushl $relay */
|
fprintf( outfile, " unsigned char pushl;\n" ); /* pushl $relay */
|
||||||
fprintf( outfile, " void *relay;\n" );
|
fprintf( outfile, " void *relay;\n" );
|
||||||
fprintf( outfile, " unsigned char lcall;\n" ); /* lcall __FLATCS__:glue */
|
fprintf( outfile, " unsigned char lcall;\n" ); /* lcall __FLATCS__:glue */
|
||||||
fprintf( outfile, " void *glue;\n" );
|
fprintf( outfile, " void *glue;\n" );
|
||||||
fprintf( outfile, " unsigned short flatcs;\n" );
|
fprintf( outfile, " unsigned short flatcs;\n" );
|
||||||
#endif
|
|
||||||
fprintf( outfile, " unsigned short lret;\n" ); /* lret $args */
|
fprintf( outfile, " unsigned short lret;\n" ); /* lret $args */
|
||||||
fprintf( outfile, " unsigned short args;\n" );
|
fprintf( outfile, " unsigned short args;\n" );
|
||||||
fprintf( outfile, " unsigned int arg_types[2];\n" );
|
fprintf( outfile, " unsigned int arg_types[2];\n" );
|
||||||
fprintf( outfile, " } call[%d];\n", nTypes );
|
fprintf( outfile, " } call[%d];\n", nTypes );
|
||||||
fprintf( outfile, " struct {\n" );
|
fprintf( outfile, " struct {\n" );
|
||||||
#ifdef __i386__
|
|
||||||
fprintf( outfile, " unsigned short pushw_bp;\n" ); /* pushw %bp */
|
fprintf( outfile, " unsigned short pushw_bp;\n" ); /* pushw %bp */
|
||||||
fprintf( outfile, " unsigned char pushl;\n" ); /* pushl $target */
|
fprintf( outfile, " unsigned char pushl;\n" ); /* pushl $target */
|
||||||
#endif
|
|
||||||
fprintf( outfile, " void (*target)();\n" );
|
fprintf( outfile, " void (*target)();\n" );
|
||||||
fprintf( outfile, " unsigned short call;\n" ); /* call CALLFROM16 */
|
fprintf( outfile, " unsigned short call;\n" ); /* call CALLFROM16 */
|
||||||
fprintf( outfile, " short callfrom16;\n" );
|
fprintf( outfile, " short callfrom16;\n" );
|
||||||
|
@ -804,7 +783,6 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
|
||||||
if (typelist[i]->flags & FLAG_REGISTER) arg_types[0] |= ARG_REGISTER;
|
if (typelist[i]->flags & FLAG_REGISTER) arg_types[0] |= ARG_REGISTER;
|
||||||
if (typelist[i]->flags & FLAG_RET16) arg_types[0] |= ARG_RET16;
|
if (typelist[i]->flags & FLAG_RET16) arg_types[0] |= ARG_RET16;
|
||||||
|
|
||||||
#ifdef __i386__
|
|
||||||
fprintf( outfile, " { 0x68, __wine_%s_CallFrom16_%s, 0x9a, __wine_call_from_16_%s,\n",
|
fprintf( outfile, " { 0x68, __wine_%s_CallFrom16_%s, 0x9a, __wine_call_from_16_%s,\n",
|
||||||
make_c_identifier(spec->file_name), profile,
|
make_c_identifier(spec->file_name), profile,
|
||||||
(typelist[i]->flags & FLAG_REGISTER) ? "regs":
|
(typelist[i]->flags & FLAG_REGISTER) ? "regs":
|
||||||
|
@ -815,14 +793,6 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
|
||||||
else
|
else
|
||||||
fprintf( outfile, " 0x%04x, 0xcb66, 0x9090, { 0x%08x, 0x%08x } },\n",
|
fprintf( outfile, " 0x%04x, 0xcb66, 0x9090, { 0x%08x, 0x%08x } },\n",
|
||||||
code_selector, arg_types[0], arg_types[1] );
|
code_selector, arg_types[0], arg_types[1] );
|
||||||
#else
|
|
||||||
if (argsize)
|
|
||||||
fprintf( outfile, " { 0xca66, %d, { 0x%08x, 0x%08x } },\n",
|
|
||||||
argsize, arg_types[0], arg_types[1] );
|
|
||||||
else
|
|
||||||
fprintf( outfile, " { 0xcb66, 0x9090, { 0x%08x, 0x%08x } },\n",
|
|
||||||
arg_types[0], arg_types[1] );
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
fprintf( outfile, " },\n {\n" );
|
fprintf( outfile, " },\n {\n" );
|
||||||
|
|
||||||
|
@ -841,11 +811,7 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
|
||||||
|
|
||||||
fprintf( outfile, " /* %s.%d */ ", spec->dll_name, i );
|
fprintf( outfile, " /* %s.%d */ ", spec->dll_name, i );
|
||||||
fprintf( outfile,
|
fprintf( outfile,
|
||||||
#ifdef __i386__
|
|
||||||
"{ 0x5566, 0x68, %s, 0xe866, %d /* %s */ },\n",
|
"{ 0x5566, 0x68, %s, 0xe866, %d /* %s */ },\n",
|
||||||
#else
|
|
||||||
"{ %s, 0xe866, %d, /* %s */ },\n",
|
|
||||||
#endif
|
|
||||||
odp->link_name,
|
odp->link_name,
|
||||||
(type - typelist) * callfrom_size - (odp->offset + entrypoint_size),
|
(type - typelist) * callfrom_size - (odp->offset + entrypoint_size),
|
||||||
get_function_name( odp ) );
|
get_function_name( odp ) );
|
||||||
|
@ -877,7 +843,6 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
|
||||||
|
|
||||||
sprintf( constructor, "__wine_spec_%s_init", make_c_identifier(spec->file_name) );
|
sprintf( constructor, "__wine_spec_%s_init", make_c_identifier(spec->file_name) );
|
||||||
sprintf( destructor, "__wine_spec_%s_fini", make_c_identifier(spec->file_name) );
|
sprintf( destructor, "__wine_spec_%s_fini", make_c_identifier(spec->file_name) );
|
||||||
output_dll_init( outfile, constructor, destructor );
|
|
||||||
|
|
||||||
fprintf( outfile,
|
fprintf( outfile,
|
||||||
"void %s(void)\n"
|
"void %s(void)\n"
|
||||||
|
@ -891,4 +856,14 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
|
||||||
" extern void __wine_dll_unregister_16( const struct module_data * );\n"
|
" extern void __wine_dll_unregister_16( const struct module_data * );\n"
|
||||||
" __wine_dll_unregister_16( &module );\n"
|
" __wine_dll_unregister_16( &module );\n"
|
||||||
"}\n", destructor );
|
"}\n", destructor );
|
||||||
|
|
||||||
|
fprintf( outfile, "#ifndef __GNUC__\n" );
|
||||||
|
fprintf( outfile, "static void __asm__dummy_dll_init(void) {\n" );
|
||||||
|
fprintf( outfile, "#endif\n" );
|
||||||
|
|
||||||
|
output_dll_init( outfile, constructor, destructor );
|
||||||
|
|
||||||
|
fprintf( outfile, "#ifndef __GNUC__\n" );
|
||||||
|
fprintf( outfile, "}\n" );
|
||||||
|
fprintf( outfile, "#endif\n" );
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,12 +37,6 @@
|
||||||
#include "build.h"
|
#include "build.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
# define __ASM_SKIP ".space"
|
|
||||||
#else
|
|
||||||
# define __ASM_SKIP ".skip"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int string_compare( const void *ptr1, const void *ptr2 )
|
static int string_compare( const void *ptr1, const void *ptr2 )
|
||||||
{
|
{
|
||||||
const char * const *str1 = ptr1;
|
const char * const *str1 = ptr1;
|
||||||
|
@ -80,17 +74,19 @@ static const char *make_internal_name( const ORDDEF *odp, DLLSPEC *spec, const c
|
||||||
static void declare_weak_function( FILE *outfile, const char *ret_type, const char *name, const char *params)
|
static void declare_weak_function( FILE *outfile, const char *ret_type, const char *name, const char *params)
|
||||||
{
|
{
|
||||||
fprintf( outfile, "#ifdef __GNUC__\n" );
|
fprintf( outfile, "#ifdef __GNUC__\n" );
|
||||||
fprintf( outfile, "# ifdef __APPLE__\n" );
|
if (target_platform == PLATFORM_APPLE)
|
||||||
fprintf( outfile, "extern %s %s(%s) __attribute__((weak_import));\n", ret_type, name, params );
|
{
|
||||||
fprintf( outfile, "static %s (*__wine_spec_weak_%s)(%s) = %s;\n", ret_type, name, params, name );
|
fprintf( outfile, "extern %s %s(%s) __attribute__((weak_import));\n", ret_type, name, params );
|
||||||
fprintf( outfile, "#define %s __wine_spec_weak_%s\n", name, name );
|
fprintf( outfile, "static %s (*__wine_spec_weak_%s)(%s) = %s;\n", ret_type, name, params, name );
|
||||||
fprintf( outfile, "# else\n" );
|
fprintf( outfile, "#define %s __wine_spec_weak_%s\n", name, name );
|
||||||
fprintf( outfile, "extern %s %s(%s) __attribute__((weak));\n", ret_type, name, params );
|
fprintf( outfile, "asm(\".weak_reference %s\");\n", asm_name(name) );
|
||||||
fprintf( outfile, "# endif\n" );
|
}
|
||||||
|
else fprintf( outfile, "extern %s %s(%s) __attribute__((weak));\n", ret_type, name, params );
|
||||||
|
|
||||||
fprintf( outfile, "#else\n" );
|
fprintf( outfile, "#else\n" );
|
||||||
fprintf( outfile, "extern %s %s(%s);\n", ret_type, name, params );
|
fprintf( outfile, "extern %s %s(%s);\n", ret_type, name, params );
|
||||||
fprintf( outfile, "static void __asm__dummy_%s(void)", name );
|
fprintf( outfile, "static void __asm__dummy_%s(void)", name );
|
||||||
fprintf( outfile, " { asm(\".weak " __ASM_NAME("%s") "\"); }\n", name );
|
fprintf( outfile, " { asm(\".weak %s\"); }\n", asm_name(name) );
|
||||||
fprintf( outfile, "#endif\n\n" );
|
fprintf( outfile, "#endif\n\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,27 +120,85 @@ static int output_debug( FILE *outfile )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
* get_exports_size
|
||||||
|
*
|
||||||
|
* Compute the size of the export table.
|
||||||
|
*/
|
||||||
|
static int get_exports_size( DLLSPEC *spec )
|
||||||
|
{
|
||||||
|
int nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
|
||||||
|
int i, fwd_size = 0, total_size;
|
||||||
|
|
||||||
|
if (!nr_exports) return 0;
|
||||||
|
|
||||||
|
/* export directory header */
|
||||||
|
total_size = 10 * sizeof(int);
|
||||||
|
|
||||||
|
/* function pointers */
|
||||||
|
total_size += nr_exports * sizeof(int);
|
||||||
|
|
||||||
|
/* function name pointers */
|
||||||
|
total_size += spec->nb_names * sizeof(int);
|
||||||
|
|
||||||
|
/* function ordinals */
|
||||||
|
total_size += spec->nb_names * sizeof(short);
|
||||||
|
if (spec->nb_names % 2) total_size += sizeof(short);
|
||||||
|
|
||||||
|
/* forward strings */
|
||||||
|
for (i = spec->base; i <= spec->limit; i++)
|
||||||
|
{
|
||||||
|
ORDDEF *odp = spec->ordinals[i];
|
||||||
|
if (odp && odp->flags & FLAG_FORWARD) fwd_size += strlen(odp->link_name) + 1;
|
||||||
|
}
|
||||||
|
total_size += (fwd_size + 3) & ~3;
|
||||||
|
|
||||||
|
return total_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
* output_export_names
|
||||||
|
*
|
||||||
|
* Output all the exported names for a Win32 module.
|
||||||
|
*/
|
||||||
|
static void output_export_names( FILE *outfile, DLLSPEC *spec )
|
||||||
|
{
|
||||||
|
int i, nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
|
||||||
|
|
||||||
|
if (!nr_exports) return;
|
||||||
|
|
||||||
|
fprintf( outfile, "\nconst char __wine_spec_exp_names[] =" );
|
||||||
|
fprintf( outfile, "\n \"%s\\0\"", spec->file_name );
|
||||||
|
for (i = 0; i < spec->nb_names; i++)
|
||||||
|
fprintf( outfile, "\n \"%s\\0\"", spec->names[i]->name );
|
||||||
|
fprintf( outfile, ";\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
* output_exports
|
* output_exports
|
||||||
*
|
*
|
||||||
* Output the export table for a Win32 module.
|
* Output the export table for a Win32 module.
|
||||||
*/
|
*/
|
||||||
static int output_exports( FILE *outfile, int nr_exports, DLLSPEC *spec )
|
static void output_exports( FILE *outfile, DLLSPEC *spec )
|
||||||
{
|
{
|
||||||
int i, fwd_size = 0, total_size = 0;
|
int i, fwd_size = 0;
|
||||||
|
int nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
|
||||||
|
|
||||||
if (!nr_exports) return 0;
|
if (!nr_exports) return;
|
||||||
|
|
||||||
|
fprintf( outfile, "/* export table */\n" );
|
||||||
fprintf( outfile, "asm(\".data\\n\"\n" );
|
fprintf( outfile, "asm(\".data\\n\"\n" );
|
||||||
fprintf( outfile, " \"\\t.align %d\\n\"\n", get_alignment(4) );
|
fprintf( outfile, " \"\\t.align %d\\n\"\n", get_alignment(4) );
|
||||||
fprintf( outfile, " \"" __ASM_NAME("__wine_spec_exports") ":\\n\"\n" );
|
fprintf( outfile, " \"%s:\\n\"\n", asm_name("__wine_spec_exports") );
|
||||||
|
|
||||||
/* export directory header */
|
/* export directory header */
|
||||||
|
|
||||||
fprintf( outfile, " \"\\t.long 0\\n\"\n" ); /* Characteristics */
|
fprintf( outfile, " \"\\t.long 0\\n\"\n" ); /* Characteristics */
|
||||||
fprintf( outfile, " \"\\t.long 0\\n\"\n" ); /* TimeDateStamp */
|
fprintf( outfile, " \"\\t.long 0\\n\"\n" ); /* TimeDateStamp */
|
||||||
fprintf( outfile, " \"\\t.long 0\\n\"\n" ); /* MajorVersion/MinorVersion */
|
fprintf( outfile, " \"\\t.long 0\\n\"\n" ); /* MajorVersion/MinorVersion */
|
||||||
fprintf( outfile, " \"\\t.long __wine_spec_exp_names\\n\"\n" ); /* Name */
|
fprintf( outfile, " \"\\t.long %s\\n\"\n", asm_name("__wine_spec_exp_names") ); /* Name */
|
||||||
fprintf( outfile, " \"\\t.long %d\\n\"\n", spec->base ); /* Base */
|
fprintf( outfile, " \"\\t.long %d\\n\"\n", spec->base ); /* Base */
|
||||||
fprintf( outfile, " \"\\t.long %d\\n\"\n", nr_exports ); /* NumberOfFunctions */
|
fprintf( outfile, " \"\\t.long %d\\n\"\n", nr_exports ); /* NumberOfFunctions */
|
||||||
fprintf( outfile, " \"\\t.long %d\\n\"\n", spec->nb_names ); /* NumberOfNames */
|
fprintf( outfile, " \"\\t.long %d\\n\"\n", spec->nb_names ); /* NumberOfNames */
|
||||||
|
@ -159,7 +213,6 @@ static int output_exports( FILE *outfile, int nr_exports, DLLSPEC *spec )
|
||||||
fprintf( outfile, " \"\\t.long 0\\n\"\n" ); /* AddressOfNames */
|
fprintf( outfile, " \"\\t.long 0\\n\"\n" ); /* AddressOfNames */
|
||||||
fprintf( outfile, " \"\\t.long 0\\n\"\n" ); /* AddressOfNameOrdinals */
|
fprintf( outfile, " \"\\t.long 0\\n\"\n" ); /* AddressOfNameOrdinals */
|
||||||
}
|
}
|
||||||
total_size += 10 * sizeof(int);
|
|
||||||
|
|
||||||
/* output the function pointers */
|
/* output the function pointers */
|
||||||
|
|
||||||
|
@ -176,7 +229,7 @@ static int output_exports( FILE *outfile, int nr_exports, DLLSPEC *spec )
|
||||||
case TYPE_CDECL:
|
case TYPE_CDECL:
|
||||||
if (!(odp->flags & FLAG_FORWARD))
|
if (!(odp->flags & FLAG_FORWARD))
|
||||||
{
|
{
|
||||||
fprintf( outfile, " \"\\t.long " __ASM_NAME("%s") "\\n\"\n", odp->link_name );
|
fprintf( outfile, " \"\\t.long %s\\n\"\n", asm_name(odp->link_name) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -185,14 +238,13 @@ static int output_exports( FILE *outfile, int nr_exports, DLLSPEC *spec )
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TYPE_STUB:
|
case TYPE_STUB:
|
||||||
fprintf( outfile, " \"\\t.long " __ASM_NAME("%s") "\\n\"\n",
|
fprintf( outfile, " \"\\t.long %s\\n\"\n",
|
||||||
make_internal_name( odp, spec, "stub" ) );
|
asm_name( make_internal_name( odp, spec, "stub" )) );
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
total_size += (spec->limit - spec->base + 1) * sizeof(int);
|
|
||||||
|
|
||||||
if (spec->nb_names)
|
if (spec->nb_names)
|
||||||
{
|
{
|
||||||
|
@ -203,21 +255,11 @@ static int output_exports( FILE *outfile, int nr_exports, DLLSPEC *spec )
|
||||||
fprintf( outfile, " \"__wine_spec_exp_name_ptrs:\\n\"\n" );
|
fprintf( outfile, " \"__wine_spec_exp_name_ptrs:\\n\"\n" );
|
||||||
for (i = 0; i < spec->nb_names; i++)
|
for (i = 0; i < spec->nb_names; i++)
|
||||||
{
|
{
|
||||||
fprintf( outfile, " \"\\t.long __wine_spec_exp_names+%d\\n\"\n", namepos );
|
fprintf( outfile, " \"\\t.long %s+%d\\n\"\n", asm_name("__wine_spec_exp_names"), namepos );
|
||||||
namepos += strlen(spec->names[i]->name) + 1;
|
namepos += strlen(spec->names[i]->name) + 1;
|
||||||
}
|
}
|
||||||
total_size += spec->nb_names * sizeof(int);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* output the function names */
|
|
||||||
|
|
||||||
fprintf( outfile, " \"\\t.text\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"__wine_spec_exp_names:\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", spec->file_name );
|
|
||||||
for (i = 0; i < spec->nb_names; i++)
|
|
||||||
fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", spec->names[i]->name );
|
|
||||||
fprintf( outfile, " \"\\t.data\\n\"\n" );
|
|
||||||
|
|
||||||
if (spec->nb_names)
|
if (spec->nb_names)
|
||||||
{
|
{
|
||||||
/* output the function ordinals */
|
/* output the function ordinals */
|
||||||
|
@ -228,11 +270,9 @@ static int output_exports( FILE *outfile, int nr_exports, DLLSPEC *spec )
|
||||||
fprintf( outfile, " \"\\t" __ASM_SHORT " %d\\n\"\n",
|
fprintf( outfile, " \"\\t" __ASM_SHORT " %d\\n\"\n",
|
||||||
spec->names[i]->ordinal - spec->base );
|
spec->names[i]->ordinal - spec->base );
|
||||||
}
|
}
|
||||||
total_size += spec->nb_names * sizeof(short);
|
|
||||||
if (spec->nb_names % 2)
|
if (spec->nb_names % 2)
|
||||||
{
|
{
|
||||||
fprintf( outfile, " \"\\t" __ASM_SHORT " 0\\n\"\n" );
|
fprintf( outfile, " \"\\t" __ASM_SHORT " 0\\n\"\n" );
|
||||||
total_size += sizeof(short);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +288,6 @@ static int output_exports( FILE *outfile, int nr_exports, DLLSPEC *spec )
|
||||||
fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", odp->link_name );
|
fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", odp->link_name );
|
||||||
}
|
}
|
||||||
fprintf( outfile, " \"\\t.align %d\\n\"\n", get_alignment(4) );
|
fprintf( outfile, " \"\\t.align %d\\n\"\n", get_alignment(4) );
|
||||||
total_size += (fwd_size + 3) & ~3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* output relays */
|
/* output relays */
|
||||||
|
@ -279,15 +318,15 @@ static int output_exports( FILE *outfile, int nr_exports, DLLSPEC *spec )
|
||||||
switch(odp->type)
|
switch(odp->type)
|
||||||
{
|
{
|
||||||
case TYPE_STDCALL:
|
case TYPE_STDCALL:
|
||||||
fprintf( outfile, " \"\\tjmp " __ASM_NAME("%s") "\\n\"\n", odp->link_name );
|
fprintf( outfile, " \"\\tjmp %s\\n\"\n", asm_name(odp->link_name) );
|
||||||
fprintf( outfile, " \"\\tret $%d\\n\"\n", args );
|
fprintf( outfile, " \"\\tret $%d\\n\"\n", args );
|
||||||
fprintf( outfile, " \"\\t.long " __ASM_NAME("%s") ",0x%08x\\n\"\n", odp->link_name, mask );
|
fprintf( outfile, " \"\\t.long %s,0x%08x\\n\"\n", asm_name(odp->link_name), mask );
|
||||||
break;
|
break;
|
||||||
case TYPE_CDECL:
|
case TYPE_CDECL:
|
||||||
fprintf( outfile, " \"\\tjmp " __ASM_NAME("%s") "\\n\"\n", odp->link_name );
|
fprintf( outfile, " \"\\tjmp %s\\n\"\n", asm_name(odp->link_name) );
|
||||||
fprintf( outfile, " \"\\tret\\n\"\n" );
|
fprintf( outfile, " \"\\tret\\n\"\n" );
|
||||||
fprintf( outfile, " \"\\t" __ASM_SHORT " %d\\n\"\n", args );
|
fprintf( outfile, " \"\\t" __ASM_SHORT " %d\\n\"\n", args );
|
||||||
fprintf( outfile, " \"\\t.long " __ASM_NAME("%s") ",0x%08x\\n\"\n", odp->link_name, mask );
|
fprintf( outfile, " \"\\t.long %s,0x%08x\\n\"\n", asm_name(odp->link_name), mask );
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
|
@ -298,12 +337,7 @@ static int output_exports( FILE *outfile, int nr_exports, DLLSPEC *spec )
|
||||||
fprintf( outfile, " \"\\t.long 0,0,0,0\\n\"\n" );
|
fprintf( outfile, " \"\\t.long 0,0,0,0\\n\"\n" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fprintf( outfile, ");\n" );
|
||||||
fprintf( outfile, " \"\\t.text\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\t.align %d\\n\"\n", get_alignment(4) );
|
|
||||||
fprintf( outfile, ");\n\n" );
|
|
||||||
|
|
||||||
return total_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -369,88 +403,85 @@ static void output_stub_funcs( FILE *outfile, DLLSPEC *spec )
|
||||||
*/
|
*/
|
||||||
void output_dll_init( FILE *outfile, const char *constructor, const char *destructor )
|
void output_dll_init( FILE *outfile, const char *constructor, const char *destructor )
|
||||||
{
|
{
|
||||||
fprintf( outfile, "#ifndef __GNUC__\n" );
|
if (target_platform == PLATFORM_APPLE)
|
||||||
fprintf( outfile, "static void __asm__dummy_dll_init(void) {\n" );
|
|
||||||
fprintf( outfile, "#endif\n" );
|
|
||||||
|
|
||||||
#if defined(__i386__)
|
|
||||||
if (constructor)
|
|
||||||
{
|
{
|
||||||
fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
|
/* Mach-O doesn't have an init section */
|
||||||
fprintf( outfile, " \"\\tcall " __ASM_NAME("%s") "\\n\"\n", constructor );
|
if (constructor)
|
||||||
fprintf( outfile, " \"\\t.section\\t\\\".text\\\"\\n\");\n" );
|
{
|
||||||
|
fprintf( outfile, "asm(\"\\t.mod_init_func\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\t.align 2\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\t.long %s\\n\"\n", asm_name(constructor) );
|
||||||
|
fprintf( outfile, " \"\\t.text\\n\");\n" );
|
||||||
|
}
|
||||||
|
if (destructor)
|
||||||
|
{
|
||||||
|
fprintf( outfile, "asm(\"\\t.mod_term_func\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\t.align 2\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\t.long %s\\n\"\n", asm_name(destructor) );
|
||||||
|
fprintf( outfile, " \"\\t.text\\n\");\n" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (destructor)
|
else switch(target_cpu)
|
||||||
{
|
{
|
||||||
fprintf( outfile, "asm(\"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
|
case CPU_x86:
|
||||||
fprintf( outfile, " \"\\tcall " __ASM_NAME("%s") "\\n\"\n", destructor );
|
if (constructor)
|
||||||
fprintf( outfile, " \"\\t.section\\t\\\".text\\\"\\n\");\n" );
|
{
|
||||||
|
fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\tcall %s\\n\"\n", asm_name(constructor) );
|
||||||
|
fprintf( outfile, " \"\\t.section\\t\\\".text\\\"\\n\");\n" );
|
||||||
|
}
|
||||||
|
if (destructor)
|
||||||
|
{
|
||||||
|
fprintf( outfile, "asm(\"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\tcall %s\\n\"\n", asm_name(destructor) );
|
||||||
|
fprintf( outfile, " \"\\t.section\\t\\\".text\\\"\\n\");\n" );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CPU_SPARC:
|
||||||
|
if (constructor)
|
||||||
|
{
|
||||||
|
fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\tcall %s\\n\"\n", asm_name(constructor) );
|
||||||
|
fprintf( outfile, " \"\\tnop\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\t.section\\t\\\".text\\\"\\n\");\n" );
|
||||||
|
}
|
||||||
|
if (destructor)
|
||||||
|
{
|
||||||
|
fprintf( outfile, "asm(\"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\tcall %s\\n\"\n", asm_name(destructor) );
|
||||||
|
fprintf( outfile, " \"\\tnop\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\t.section\\t\\\".text\\\"\\n\");\n" );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CPU_ALPHA:
|
||||||
|
if (constructor)
|
||||||
|
{
|
||||||
|
fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\tjsr $26,%s\\n\"\n", asm_name(constructor) );
|
||||||
|
fprintf( outfile, " \"\\t.section\\t\\\".text\\\"\\n\");\n" );
|
||||||
|
}
|
||||||
|
if (destructor)
|
||||||
|
{
|
||||||
|
fprintf( outfile, "asm(\"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\tjsr $26,%s\\n\"\n", asm_name(destructor) );
|
||||||
|
fprintf( outfile, " \"\\t.section\\t\\\".text\\\"\\n\");\n" );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CPU_POWERPC:
|
||||||
|
if (constructor)
|
||||||
|
{
|
||||||
|
fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\tbl %s\\n\"\n", asm_name(constructor) );
|
||||||
|
fprintf( outfile, " \"\\t.section\\t\\\".text\\\"\\n\");\n" );
|
||||||
|
}
|
||||||
|
if (destructor)
|
||||||
|
{
|
||||||
|
fprintf( outfile, "asm(\"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
|
||||||
|
fprintf( outfile, " \"\\tbl %s\\n\"\n", asm_name(destructor) );
|
||||||
|
fprintf( outfile, " \"\\t.section\\t\\\".text\\\"\\n\");\n" );
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
#elif defined(__sparc__)
|
|
||||||
if (constructor)
|
|
||||||
{
|
|
||||||
fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\tcall " __ASM_NAME("%s") "\\n\"\n", constructor );
|
|
||||||
fprintf( outfile, " \"\\tnop\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\t.section\\t\\\".text\\\"\\n\");\n" );
|
|
||||||
}
|
|
||||||
if (destructor)
|
|
||||||
{
|
|
||||||
fprintf( outfile, "asm(\"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\tcall " __ASM_NAME("%s") "\\n\"\n", destructor );
|
|
||||||
fprintf( outfile, " \"\\tnop\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\t.section\\t\\\".text\\\"\\n\");\n" );
|
|
||||||
}
|
|
||||||
#elif defined(__powerpc__)
|
|
||||||
# ifdef __APPLE__
|
|
||||||
/* Mach-O doesn't have an init section */
|
|
||||||
if (constructor)
|
|
||||||
{
|
|
||||||
fprintf( outfile, "asm(\"\\t.mod_init_func\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\t.align 2\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\t.long " __ASM_NAME("%s") "\\n\"\n", constructor );
|
|
||||||
fprintf( outfile, " \"\\t.text\\n\");\n" );
|
|
||||||
}
|
|
||||||
if (destructor)
|
|
||||||
{
|
|
||||||
fprintf( outfile, "asm(\"\\t.mod_term_func\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\t.align 2\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\t.long " __ASM_NAME("%s") "\\n\"\n", destructor );
|
|
||||||
fprintf( outfile, " \"\\t.text\\n\");\n" );
|
|
||||||
}
|
|
||||||
# else /* __APPLE__ */
|
|
||||||
if (constructor)
|
|
||||||
{
|
|
||||||
fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\tbl " __ASM_NAME("%s") "\\n\"\n", constructor );
|
|
||||||
fprintf( outfile, " \"\\t.section\\t\\\".text\\\"\\n\");\n" );
|
|
||||||
}
|
|
||||||
if (destructor)
|
|
||||||
{
|
|
||||||
fprintf( outfile, "asm(\"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\tbl " __ASM_NAME("%s") "\\n\"\n", destructor );
|
|
||||||
fprintf( outfile, " \"\\t.section\\t\\\".text\\\"\\n\");\n" );
|
|
||||||
}
|
|
||||||
# endif /* __APPLE__ */
|
|
||||||
#elif defined(__ALPHA__)
|
|
||||||
if (constructor)
|
|
||||||
{
|
|
||||||
fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\tjsr $26," __ASM_NAME("%s") "\\n\"\n", constructor );
|
|
||||||
fprintf( outfile, " \"\\t.section\\t\\\".text\\\"\\n\");\n" );
|
|
||||||
}
|
|
||||||
if (destructor)
|
|
||||||
{
|
|
||||||
fprintf( outfile, "asm(\"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\tjsr $26," __ASM_NAME("%s") "\\n\"\n", destructor );
|
|
||||||
fprintf( outfile, " \"\\t.section\\t\\\".text\\\"\\n\");\n" );
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#error You need to define the DLL constructor for your architecture
|
|
||||||
#endif
|
|
||||||
fprintf( outfile, "#ifndef __GNUC__\n" );
|
|
||||||
fprintf( outfile, "}\n" );
|
|
||||||
fprintf( outfile, "#endif\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -463,25 +494,12 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
|
||||||
{
|
{
|
||||||
int exports_size = 0;
|
int exports_size = 0;
|
||||||
int nr_exports, nr_imports, nr_delayed;
|
int nr_exports, nr_imports, nr_delayed;
|
||||||
DWORD page_size;
|
unsigned int page_size = get_page_size();
|
||||||
const char *init_func = spec->init_func;
|
const char *init_func = spec->init_func;
|
||||||
|
|
||||||
#ifdef HAVE_GETPAGESIZE
|
|
||||||
page_size = getpagesize();
|
|
||||||
#elif defined(__svr4__)
|
|
||||||
page_size = sysconf(_SC_PAGESIZE);
|
|
||||||
#elif defined(_WINDOWS)
|
|
||||||
{
|
|
||||||
SYSTEM_INFO si;
|
|
||||||
GetSystemInfo(&si);
|
|
||||||
page_size = si.dwPageSize;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
# error Cannot get the page size on this platform
|
|
||||||
#endif
|
|
||||||
|
|
||||||
nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
|
nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
|
||||||
resolve_imports( spec );
|
resolve_imports( spec );
|
||||||
|
exports_size = get_exports_size( spec );
|
||||||
output_standard_file_header( outfile );
|
output_standard_file_header( outfile );
|
||||||
|
|
||||||
/* Reserve some space for the PE header */
|
/* Reserve some space for the PE header */
|
||||||
|
@ -492,46 +510,32 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
|
||||||
fprintf( outfile, "#endif\n" );
|
fprintf( outfile, "#endif\n" );
|
||||||
fprintf( outfile, "asm(\".text\\n\\t\"\n" );
|
fprintf( outfile, "asm(\".text\\n\\t\"\n" );
|
||||||
fprintf( outfile, " \".align %d\\n\"\n", get_alignment(page_size) );
|
fprintf( outfile, " \".align %d\\n\"\n", get_alignment(page_size) );
|
||||||
fprintf( outfile, " \"" __ASM_NAME("__wine_spec_pe_header") ":\\t" __ASM_SKIP " 65536\\n\\t\"\n" );
|
fprintf( outfile, " \"%s:\\t\"\n", asm_name("__wine_spec_pe_header") );
|
||||||
|
if (target_platform == PLATFORM_APPLE)
|
||||||
|
fprintf( outfile, " \".space 65536\\n\\t\"\n" );
|
||||||
|
else
|
||||||
|
fprintf( outfile, " \".skip 65536\\n\\t\"\n" );
|
||||||
fprintf( outfile, " \".data\\n\\t\"\n" );
|
fprintf( outfile, " \".data\\n\\t\"\n" );
|
||||||
fprintf( outfile, " \".align %d\\n\"\n", get_alignment(4) );
|
fprintf( outfile, " \".align %d\\n\"\n", get_alignment(4) );
|
||||||
fprintf( outfile, " \"" __ASM_NAME("__wine_spec_data_start") ":\\t.long 1\");\n" );
|
fprintf( outfile, " \"%s:\\t.long 1\");\n", asm_name("__wine_spec_data_start") );
|
||||||
fprintf( outfile, "#ifndef __GNUC__\n" );
|
fprintf( outfile, "#ifndef __GNUC__\n" );
|
||||||
fprintf( outfile, "}\n" );
|
fprintf( outfile, "}\n" );
|
||||||
fprintf( outfile, "#endif\n" );
|
fprintf( outfile, "#endif\n" );
|
||||||
|
|
||||||
#ifdef __APPLE__
|
if (target_platform == PLATFORM_APPLE)
|
||||||
fprintf( outfile, "static char _end[4];\n" );
|
fprintf( outfile, "static char _end[4];\n" );
|
||||||
#else
|
else
|
||||||
fprintf( outfile, "extern char _end[];\n" );
|
fprintf( outfile, "extern char _end[];\n" );
|
||||||
#endif
|
|
||||||
|
|
||||||
fprintf( outfile, "extern int __wine_spec_data_start[], __wine_spec_exports[];\n\n" );
|
fprintf( outfile, "extern int __wine_spec_data_start[], __wine_spec_exports[];\n\n" );
|
||||||
|
|
||||||
#ifdef __i386__
|
if (target_cpu == CPU_x86)
|
||||||
fprintf( outfile, "#define __stdcall __attribute__((__stdcall__))\n\n" );
|
fprintf( outfile, "#define __stdcall __attribute__((__stdcall__))\n\n" );
|
||||||
#else
|
else
|
||||||
fprintf( outfile, "#define __stdcall\n\n" );
|
fprintf( outfile, "#define __stdcall\n\n" );
|
||||||
#endif
|
|
||||||
|
|
||||||
if (nr_exports)
|
output_stub_funcs( outfile, spec );
|
||||||
{
|
output_export_names( outfile, spec );
|
||||||
/* Output the stub functions */
|
|
||||||
|
|
||||||
output_stub_funcs( outfile, spec );
|
|
||||||
|
|
||||||
fprintf( outfile, "#ifndef __GNUC__\n" );
|
|
||||||
fprintf( outfile, "static void __asm__dummy(void) {\n" );
|
|
||||||
fprintf( outfile, "#endif /* !defined(__GNUC__) */\n" );
|
|
||||||
|
|
||||||
/* Output the exports and relay entry points */
|
|
||||||
|
|
||||||
exports_size = output_exports( outfile, nr_exports, spec );
|
|
||||||
|
|
||||||
fprintf( outfile, "#ifndef __GNUC__\n" );
|
|
||||||
fprintf( outfile, "}\n" );
|
|
||||||
fprintf( outfile, "#endif /* !defined(__GNUC__) */\n" );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Output the DLL imports */
|
/* Output the DLL imports */
|
||||||
|
|
||||||
|
@ -548,26 +552,29 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
|
||||||
fprintf( outfile, "extern char **__wine_main_argv;\n" );
|
fprintf( outfile, "extern char **__wine_main_argv;\n" );
|
||||||
fprintf( outfile, "extern char **__wine_main_environ;\n" );
|
fprintf( outfile, "extern char **__wine_main_environ;\n" );
|
||||||
fprintf( outfile, "extern unsigned short **__wine_main_wargv;\n" );
|
fprintf( outfile, "extern unsigned short **__wine_main_wargv;\n" );
|
||||||
#ifdef __APPLE__
|
if (target_platform == PLATFORM_APPLE)
|
||||||
fprintf( outfile, "extern _dyld_func_lookup(char *, void *);" );
|
{
|
||||||
fprintf( outfile, "static void __wine_spec_hidden_init(int argc, char** argv, char** envp)\n" );
|
fprintf( outfile, "extern _dyld_func_lookup(char *, void *);" );
|
||||||
fprintf( outfile, "{\n" );
|
fprintf( outfile, "static void __wine_spec_hidden_init(int argc, char** argv, char** envp)\n" );
|
||||||
fprintf( outfile, " void (*init)(void);\n" );
|
fprintf( outfile, "{\n" );
|
||||||
fprintf( outfile, " _dyld_func_lookup(\"__dyld_make_delayed_module_initializer_calls\", (unsigned long *)&init);\n" );
|
fprintf( outfile, " void (*init)(void);\n" );
|
||||||
fprintf( outfile, " init();\n" );
|
fprintf( outfile, " _dyld_func_lookup(\"__dyld_make_delayed_module_initializer_calls\", (unsigned long *)&init);\n" );
|
||||||
fprintf( outfile, "}\n" );
|
fprintf( outfile, " init();\n" );
|
||||||
fprintf( outfile, "static void __wine_spec_hidden_fini()\n" );
|
fprintf( outfile, "}\n" );
|
||||||
fprintf( outfile, "{\n" );
|
fprintf( outfile, "static void __wine_spec_hidden_fini()\n" );
|
||||||
fprintf( outfile, " void (*fini)(void);\n" );
|
fprintf( outfile, "{\n" );
|
||||||
fprintf( outfile, " _dyld_func_lookup(\"__dyld_mod_term_funcs\", (unsigned long *)&fini);\n" );
|
fprintf( outfile, " void (*fini)(void);\n" );
|
||||||
fprintf( outfile, " fini();\n" );
|
fprintf( outfile, " _dyld_func_lookup(\"__dyld_mod_term_funcs\", (unsigned long *)&fini);\n" );
|
||||||
fprintf( outfile, "}\n" );
|
fprintf( outfile, " fini();\n" );
|
||||||
fprintf( outfile, "#define _init __wine_spec_hidden_init\n" );
|
fprintf( outfile, "}\n" );
|
||||||
fprintf( outfile, "#define _fini __wine_spec_hidden_fini\n" );
|
fprintf( outfile, "#define _init __wine_spec_hidden_init\n" );
|
||||||
#else
|
fprintf( outfile, "#define _fini __wine_spec_hidden_fini\n" );
|
||||||
fprintf( outfile, "extern void _init(int, char**, char**);\n" );
|
}
|
||||||
fprintf( outfile, "extern void _fini();\n" );
|
else
|
||||||
#endif
|
{
|
||||||
|
fprintf( outfile, "extern void _init(int, char**, char**);\n" );
|
||||||
|
fprintf( outfile, "extern void _fini();\n" );
|
||||||
|
}
|
||||||
|
|
||||||
if (spec->characteristics & IMAGE_FILE_DLL)
|
if (spec->characteristics & IMAGE_FILE_DLL)
|
||||||
{
|
{
|
||||||
|
@ -736,15 +743,21 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
|
||||||
fprintf( outfile, " } OptionalHeader;\n" );
|
fprintf( outfile, " } OptionalHeader;\n" );
|
||||||
fprintf( outfile, "} nt_header = {\n" );
|
fprintf( outfile, "} nt_header = {\n" );
|
||||||
fprintf( outfile, " 0x%04x,\n", IMAGE_NT_SIGNATURE ); /* Signature */
|
fprintf( outfile, " 0x%04x,\n", IMAGE_NT_SIGNATURE ); /* Signature */
|
||||||
#ifdef __i386__
|
switch(target_cpu)
|
||||||
fprintf( outfile, " { 0x%04x,\n", IMAGE_FILE_MACHINE_I386 ); /* Machine */
|
{
|
||||||
#elif defined(__powerpc__)
|
case CPU_x86:
|
||||||
fprintf( outfile, " { 0x%04x,\n", IMAGE_FILE_MACHINE_POWERPC ); /* Machine */
|
fprintf( outfile, " { 0x%04x,\n", IMAGE_FILE_MACHINE_I386 ); /* Machine */
|
||||||
#elif defined(__ALPHA__)
|
break;
|
||||||
fprintf( outfile, " { 0x%04x,\n", IMAGE_FILE_MACHINE_ALPHA ); /* Machine */
|
case CPU_POWERPC:
|
||||||
#else
|
fprintf( outfile, " { 0x%04x,\n", IMAGE_FILE_MACHINE_POWERPC ); /* Machine */
|
||||||
fprintf( outfile, " { 0x%04x,\n", IMAGE_FILE_MACHINE_UNKNOWN ); /* Machine */
|
break;
|
||||||
#endif
|
case CPU_ALPHA:
|
||||||
|
fprintf( outfile, " { 0x%04x,\n", IMAGE_FILE_MACHINE_ALPHA ); /* Machine */
|
||||||
|
break;
|
||||||
|
case CPU_SPARC:
|
||||||
|
fprintf( outfile, " { 0x%04x,\n", IMAGE_FILE_MACHINE_UNKNOWN ); /* Machine */
|
||||||
|
break;
|
||||||
|
}
|
||||||
fprintf( outfile, " 0, 0, 0, 0,\n" );
|
fprintf( outfile, " 0, 0, 0, 0,\n" );
|
||||||
fprintf( outfile, " sizeof(nt_header.OptionalHeader),\n" ); /* SizeOfOptionalHeader */
|
fprintf( outfile, " sizeof(nt_header.OptionalHeader),\n" ); /* SizeOfOptionalHeader */
|
||||||
fprintf( outfile, " 0x%04x },\n", spec->characteristics ); /* Characteristics */
|
fprintf( outfile, " 0x%04x },\n", spec->characteristics ); /* Characteristics */
|
||||||
|
@ -755,21 +768,21 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
|
||||||
fprintf( outfile, " %s,\n", init_func ); /* AddressOfEntryPoint */
|
fprintf( outfile, " %s,\n", init_func ); /* AddressOfEntryPoint */
|
||||||
fprintf( outfile, " 0, __wine_spec_data_start,\n" ); /* BaseOfCode/Data */
|
fprintf( outfile, " 0, __wine_spec_data_start,\n" ); /* BaseOfCode/Data */
|
||||||
fprintf( outfile, " __wine_spec_pe_header,\n" ); /* ImageBase */
|
fprintf( outfile, " __wine_spec_pe_header,\n" ); /* ImageBase */
|
||||||
fprintf( outfile, " %ld,\n", page_size ); /* SectionAlignment */
|
fprintf( outfile, " %u,\n", page_size ); /* SectionAlignment */
|
||||||
fprintf( outfile, " %ld,\n", page_size ); /* FileAlignment */
|
fprintf( outfile, " %u,\n", page_size ); /* FileAlignment */
|
||||||
fprintf( outfile, " 1, 0,\n" ); /* Major/MinorOperatingSystemVersion */
|
fprintf( outfile, " 1, 0,\n" ); /* Major/MinorOperatingSystemVersion */
|
||||||
fprintf( outfile, " 0, 0,\n" ); /* Major/MinorImageVersion */
|
fprintf( outfile, " 0, 0,\n" ); /* Major/MinorImageVersion */
|
||||||
fprintf( outfile, " %d,\n", spec->subsystem_major ); /* MajorSubsystemVersion */
|
fprintf( outfile, " %d,\n", spec->subsystem_major ); /* MajorSubsystemVersion */
|
||||||
fprintf( outfile, " %d,\n", spec->subsystem_minor ); /* MinorSubsystemVersion */
|
fprintf( outfile, " %d,\n", spec->subsystem_minor ); /* MinorSubsystemVersion */
|
||||||
fprintf( outfile, " 0,\n" ); /* Win32VersionValue */
|
fprintf( outfile, " 0,\n" ); /* Win32VersionValue */
|
||||||
fprintf( outfile, " _end,\n" ); /* SizeOfImage */
|
fprintf( outfile, " _end,\n" ); /* SizeOfImage */
|
||||||
fprintf( outfile, " %ld,\n", page_size ); /* SizeOfHeaders */
|
fprintf( outfile, " %u,\n", page_size ); /* SizeOfHeaders */
|
||||||
fprintf( outfile, " 0,\n" ); /* CheckSum */
|
fprintf( outfile, " 0,\n" ); /* CheckSum */
|
||||||
fprintf( outfile, " 0x%04x,\n", spec->subsystem );/* Subsystem */
|
fprintf( outfile, " 0x%04x,\n", spec->subsystem );/* Subsystem */
|
||||||
fprintf( outfile, " 0,\n" ); /* DllCharacteristics */
|
fprintf( outfile, " 0,\n" ); /* DllCharacteristics */
|
||||||
fprintf( outfile, " %d, %ld,\n", /* SizeOfStackReserve/Commit */
|
fprintf( outfile, " %u, %u,\n", /* SizeOfStackReserve/Commit */
|
||||||
(spec->stack_size ? spec->stack_size : 1024) * 1024, page_size );
|
(spec->stack_size ? spec->stack_size : 1024) * 1024, page_size );
|
||||||
fprintf( outfile, " %d, %ld,\n", /* SizeOfHeapReserve/Commit */
|
fprintf( outfile, " %u, %u,\n", /* SizeOfHeapReserve/Commit */
|
||||||
(spec->heap_size ? spec->heap_size : 1024) * 1024, page_size );
|
(spec->heap_size ? spec->heap_size : 1024) * 1024, page_size );
|
||||||
fprintf( outfile, " 0,\n" ); /* LoaderFlags */
|
fprintf( outfile, " 0,\n" ); /* LoaderFlags */
|
||||||
fprintf( outfile, " %d,\n", IMAGE_NUMBEROF_DIRECTORY_ENTRIES ); /* NumberOfRvaAndSizes */
|
fprintf( outfile, " %d,\n", IMAGE_NUMBEROF_DIRECTORY_ENTRIES ); /* NumberOfRvaAndSizes */
|
||||||
|
@ -779,8 +792,8 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
|
||||||
fprintf( outfile, " { %s, %s },\n", /* IMAGE_DIRECTORY_ENTRY_IMPORT */
|
fprintf( outfile, " { %s, %s },\n", /* IMAGE_DIRECTORY_ENTRY_IMPORT */
|
||||||
nr_imports ? "&imports" : "0", nr_imports ? "sizeof(imports)" : "0" );
|
nr_imports ? "&imports" : "0", nr_imports ? "sizeof(imports)" : "0" );
|
||||||
fprintf( outfile, " { %s, %s },\n", /* IMAGE_DIRECTORY_ENTRY_RESOURCE */
|
fprintf( outfile, " { %s, %s },\n", /* IMAGE_DIRECTORY_ENTRY_RESOURCE */
|
||||||
spec->nb_resources ? "&resources" : "0",
|
spec->nb_resources ? "&__wine_spec_resources" : "0",
|
||||||
spec->nb_resources ? "sizeof(resources)" : "0" );
|
spec->nb_resources ? "sizeof(__wine_spec_resources)" : "0" );
|
||||||
fprintf( outfile, " }\n }\n};\n\n" );
|
fprintf( outfile, " }\n }\n};\n\n" );
|
||||||
|
|
||||||
/* Output the DLL constructor */
|
/* Output the DLL constructor */
|
||||||
|
@ -794,7 +807,6 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
|
||||||
"}\n\n",
|
"}\n\n",
|
||||||
spec->file_name );
|
spec->file_name );
|
||||||
|
|
||||||
output_dll_init( outfile, "__wine_spec_init_ctor", NULL );
|
|
||||||
fprintf( outfile,
|
fprintf( outfile,
|
||||||
"void __wine_spec_init_ctor(void)\n"
|
"void __wine_spec_init_ctor(void)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
@ -802,6 +814,18 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
|
||||||
" __wine_spec_init();\n"
|
" __wine_spec_init();\n"
|
||||||
" __wine_spec_init_state = 2;\n"
|
" __wine_spec_init_state = 2;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
|
|
||||||
|
fprintf( outfile, "#ifndef __GNUC__\n" );
|
||||||
|
fprintf( outfile, "static void __asm__dummy(void) {\n" );
|
||||||
|
fprintf( outfile, "#endif\n" );
|
||||||
|
|
||||||
|
output_exports( outfile, spec );
|
||||||
|
output_import_thunks( outfile, spec );
|
||||||
|
output_dll_init( outfile, "__wine_spec_init_ctor", NULL );
|
||||||
|
|
||||||
|
fprintf( outfile, "#ifndef __GNUC__\n" );
|
||||||
|
fprintf( outfile, "}\n" );
|
||||||
|
fprintf( outfile, "#endif\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -915,7 +939,7 @@ void BuildDef32File( FILE *outfile, DLLSPEC *spec )
|
||||||
void BuildDebugFile( FILE *outfile, const char *srcdir, char **argv )
|
void BuildDebugFile( FILE *outfile, const char *srcdir, char **argv )
|
||||||
{
|
{
|
||||||
int nr_debug;
|
int nr_debug;
|
||||||
char *prefix, *p;
|
char *prefix, *p, *constructor, *destructor;
|
||||||
|
|
||||||
while (*argv)
|
while (*argv)
|
||||||
{
|
{
|
||||||
|
@ -941,69 +965,35 @@ void BuildDebugFile( FILE *outfile, const char *srcdir, char **argv )
|
||||||
|
|
||||||
/* Output the DLL constructor */
|
/* Output the DLL constructor */
|
||||||
|
|
||||||
|
constructor = xmalloc( strlen(prefix) + 17 );
|
||||||
|
destructor = xmalloc( strlen(prefix) + 17 );
|
||||||
|
sprintf( constructor, "__wine_dbg_%s_init", prefix );
|
||||||
|
sprintf( destructor, "__wine_dbg_%s_fini", prefix );
|
||||||
fprintf( outfile,
|
fprintf( outfile,
|
||||||
"#ifdef __GNUC__\n"
|
"#ifdef __GNUC__\n"
|
||||||
"void __wine_dbg_%s_init(void) __attribute__((constructor));\n"
|
"void %s(void) __attribute__((constructor));\n"
|
||||||
"void __wine_dbg_%s_fini(void) __attribute__((destructor));\n"
|
"void %s(void) __attribute__((destructor));\n"
|
||||||
"#else\n"
|
"#else\n"
|
||||||
"static void __asm__dummy_dll_init(void) {\n",
|
"static void __asm__dummy_dll_init(void) {\n",
|
||||||
prefix, prefix );
|
constructor, destructor );
|
||||||
|
output_dll_init( outfile, constructor, destructor );
|
||||||
#if defined(__i386__)
|
|
||||||
fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\tcall " __ASM_NAME("__wine_dbg_%s_init") "\\n\"\n", prefix );
|
|
||||||
fprintf( outfile, " \"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\tcall " __ASM_NAME("__wine_dbg_%s_fini") "\\n\"\n", prefix );
|
|
||||||
fprintf( outfile, " \"\\t.section\\t\\\".text\\\"\\n\");\n" );
|
|
||||||
#elif defined(__sparc__)
|
|
||||||
fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\tcall " __ASM_NAME("__wine_dbg_%s_init") "\\n\"\n", prefix );
|
|
||||||
fprintf( outfile, " \"\\tnop\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\tcall " __ASM_NAME("__wine_dbg_%s_fini") "\\n\"\n", prefix );
|
|
||||||
fprintf( outfile, " \"\\tnop\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\t.section\t\\\".text\\\"\\n\");\n" );
|
|
||||||
#elif defined(__powerpc__)
|
|
||||||
# ifdef __APPLE__
|
|
||||||
fprintf( outfile, "asm(\"\\t.mod_init_func\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\t.align 2\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\t.long " __ASM_NAME("__wine_dbg_%s_init") "\\n\"\n", prefix );
|
|
||||||
fprintf( outfile, " \"\\t.text\\n\");\n" );
|
|
||||||
fprintf( outfile, "asm(\"\\t.mod_term_func\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\t.align 2\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\t.long " __ASM_NAME("__wine_dbg_%s_fini") "\\n\"\n", prefix );
|
|
||||||
fprintf( outfile, " \"\\t.text\\n\");\n" );
|
|
||||||
# else
|
|
||||||
fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\tbl " __ASM_NAME("__wine_dbg_%s_init") "\\n\"\n", prefix );
|
|
||||||
fprintf( outfile, " \"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\tbl " __ASM_NAME("__wine_dbg_%s_fini") "\\n\"\n", prefix );
|
|
||||||
fprintf( outfile, " \"\\t.text\\n\");\n" );
|
|
||||||
# endif
|
|
||||||
#elif defined(__ALPHA__)
|
|
||||||
fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\tjsr $26," __ASM_NAME("__wine_dbg_%s_init") "\\n\"\n", prefix );
|
|
||||||
fprintf( outfile, " \"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
|
|
||||||
fprintf( outfile, " \"\\tjsr $26," __ASM_NAME("__wine_dbg_%s_fini") "\\n\"\n", prefix );
|
|
||||||
fprintf( outfile, " \"\\t.section\\t\\\".text\\\"\\n\");\n" );
|
|
||||||
#else
|
|
||||||
#error You need to define the DLL constructor for your architecture
|
|
||||||
#endif
|
|
||||||
fprintf( outfile, "}\n#endif /* defined(__GNUC__) */\n\n" );
|
fprintf( outfile, "}\n#endif /* defined(__GNUC__) */\n\n" );
|
||||||
|
|
||||||
fprintf( outfile,
|
fprintf( outfile,
|
||||||
"void __wine_dbg_%s_init(void)\n"
|
"void %s(void)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" extern void *__wine_dbg_register( char * const *, int );\n"
|
" extern void *__wine_dbg_register( char * const *, int );\n"
|
||||||
" if (!debug_registration) debug_registration = __wine_dbg_register( debug_channels, %d );\n"
|
" if (!debug_registration) debug_registration = __wine_dbg_register( debug_channels, %d );\n"
|
||||||
"}\n\n", prefix, nr_debug );
|
"}\n\n", constructor, nr_debug );
|
||||||
fprintf( outfile,
|
fprintf( outfile,
|
||||||
"void __wine_dbg_%s_fini(void)\n"
|
"void %s(void)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" extern void __wine_dbg_unregister( void* );\n"
|
" extern void __wine_dbg_unregister( void* );\n"
|
||||||
" __wine_dbg_unregister( debug_registration );\n"
|
" __wine_dbg_unregister( debug_registration );\n"
|
||||||
"}\n", prefix );
|
"}\n", destructor );
|
||||||
|
|
||||||
|
free( constructor );
|
||||||
|
free( destructor );
|
||||||
free( prefix );
|
free( prefix );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#undef strdup
|
#undef strdup
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -342,81 +343,70 @@ const char *make_c_identifier( const char *str )
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* alignBoundary -- the number of bytes to align to.
|
* align -- the number of bytes to align to. Must be a power of 2.
|
||||||
* If we're on an architecture where
|
|
||||||
* the assembler requires a 'number
|
|
||||||
* of low-order zero bits' as a
|
|
||||||
* .align argument, then this number
|
|
||||||
* must be a power of 2.
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
int get_alignment(int alignBoundary)
|
unsigned int get_alignment(unsigned int align)
|
||||||
{
|
{
|
||||||
#if defined(__powerpc__) || defined(__ALPHA__)
|
unsigned int n;
|
||||||
|
|
||||||
int n = 0;
|
assert( !(align & (align - 1)) );
|
||||||
|
|
||||||
switch(alignBoundary)
|
switch(target_cpu)
|
||||||
{
|
{
|
||||||
case 2:
|
case CPU_x86:
|
||||||
n = 1;
|
case CPU_SPARC:
|
||||||
break;
|
if (target_platform != PLATFORM_APPLE) return align;
|
||||||
case 4:
|
/* fall through */
|
||||||
n = 2;
|
case CPU_POWERPC:
|
||||||
break;
|
case CPU_ALPHA:
|
||||||
case 8:
|
n = 0;
|
||||||
n = 3;
|
while ((1 << n) != align) n++;
|
||||||
break;
|
return n;
|
||||||
case 16:
|
|
||||||
n = 4;
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
n = 5;
|
|
||||||
break;
|
|
||||||
case 64:
|
|
||||||
n = 6;
|
|
||||||
break;
|
|
||||||
case 128:
|
|
||||||
n = 7;
|
|
||||||
break;
|
|
||||||
case 256:
|
|
||||||
n = 8;
|
|
||||||
break;
|
|
||||||
case 512:
|
|
||||||
n = 9;
|
|
||||||
break;
|
|
||||||
case 1024:
|
|
||||||
n = 10;
|
|
||||||
break;
|
|
||||||
case 2048:
|
|
||||||
n = 11;
|
|
||||||
break;
|
|
||||||
case 4096:
|
|
||||||
n = 12;
|
|
||||||
break;
|
|
||||||
case 8192:
|
|
||||||
n = 13;
|
|
||||||
break;
|
|
||||||
case 16384:
|
|
||||||
n = 14;
|
|
||||||
break;
|
|
||||||
case 32768:
|
|
||||||
n = 15;
|
|
||||||
break;
|
|
||||||
case 65536:
|
|
||||||
n = 16;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fatal_error("Alignment to %d-byte boundary not supported on this architecture.\n",
|
|
||||||
alignBoundary);
|
|
||||||
}
|
}
|
||||||
return n;
|
/* unreached */
|
||||||
|
assert(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#elif defined(__i386__) || defined(__sparc__)
|
/* return the page size for the target CPU */
|
||||||
|
unsigned int get_page_size(void)
|
||||||
|
{
|
||||||
|
switch(target_cpu)
|
||||||
|
{
|
||||||
|
case CPU_x86: return 4096;
|
||||||
|
case CPU_POWERPC: return 4096;
|
||||||
|
case CPU_SPARC: return 8192;
|
||||||
|
case CPU_ALPHA: return 8192;
|
||||||
|
}
|
||||||
|
/* unreached */
|
||||||
|
assert(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return alignBoundary;
|
/* return the assembly name for a C symbol */
|
||||||
|
const char *asm_name( const char *sym )
|
||||||
|
{
|
||||||
|
static char buffer[256];
|
||||||
|
sprintf( buffer, __ASM_NAME("%s"), sym );
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return an assembly function declaration for a C function name */
|
||||||
|
const char *func_declaration( const char *func )
|
||||||
|
{
|
||||||
|
static char buffer[256];
|
||||||
|
sprintf( buffer, __ASM_FUNC("%s"), func );
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return a size declaration for an assembly function */
|
||||||
|
const char *func_size( const char *func )
|
||||||
|
{
|
||||||
|
#ifdef HAVE_ASM_DOT_SIZE
|
||||||
|
static char buffer[256];
|
||||||
|
sprintf( buffer, ".size " __ASM_NAME("%s") ", .-" __ASM_NAME("%s"), func, func );
|
||||||
|
return buffer;
|
||||||
#else
|
#else
|
||||||
#error "How does the '.align' assembler directive work on your architecture?"
|
return "";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,10 @@ typedef unsigned short WCHAR;
|
||||||
#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2
|
#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2
|
||||||
#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3
|
#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3
|
||||||
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
|
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
|
||||||
#define IMAGE_FILE_MACHINE_I386 332
|
#define IMAGE_FILE_MACHINE_UNKNOWN 0
|
||||||
|
#define IMAGE_FILE_MACHINE_I386 0x014c
|
||||||
|
#define IMAGE_FILE_MACHINE_ALPHA 0x0184
|
||||||
|
#define IMAGE_FILE_MACHINE_POWERPC 0x01f0
|
||||||
#define IMAGE_NT_SIGNATURE 0x00004550
|
#define IMAGE_NT_SIGNATURE 0x00004550
|
||||||
#define IMAGE_NT_OPTIONAL_HDR_MAGIC 0x10b
|
#define IMAGE_NT_OPTIONAL_HDR_MAGIC 0x10b
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue