Sync to Wine-20050830:

Alexandre Julliard <julliard@winehq.org>
- Beginnings of a crt0 library.
- Added a warning for DllGetVersion and DllInstall not being declared
  private. Also warn when one of the Dll* functions is using a different
  internal name.
- Added a --undefined option to allow forcing some symbols to be
  resolved by the linker.
- Byteswap the resources if we detect that the header is in the wrong
  endianness.
- Moved more of the spec initialization code to the winecrt0 library,
  and get rid of implicit kernel32 imports.
- Use __wine_unimplemented_stub from crt0 for 16-bit spec files too.
- Moved the delay loading support code to the winecrt0 library.
- Avoid using common symbols, they are broken on Mac OS.
- Moved the implementation of spec file stubs to the winecrt0 library.
- The exported name strings should be inside the export directory (found
  by Vitaliy Margolen).
- Added some general purpose routines for managing list of symbol
  names.
- Print a warning when a generated import library doesn't export
  anything useful.
- Implemented DelayLoadFailureHook and use it in the winebuild-generated
  delay load code.
- Compute the ordinal base and limit in assign_ordinals instead of doing
  it while parsing.
- Get rid of the unused owner_name field.
Ge van Geldorp <gvg@reactos.org>
- Adapt changes to ReactOS

svn path=/trunk/; revision=17659
This commit is contained in:
Gé van Geldorp 2005-09-05 17:35:31 +00:00
parent 89c566ad64
commit 94a3a9e377
9 changed files with 244 additions and 492 deletions

View file

@ -88,7 +88,6 @@ typedef struct
{ {
char *file_name; /* file name of the dll */ char *file_name; /* file name of the dll */
char *dll_name; /* internal name of the dll */ char *dll_name; /* internal name of the dll */
char *owner_name; /* name of the 32-bit dll owning this one */
char *init_func; /* initialization routine */ char *init_func; /* initialization routine */
SPEC_TYPE type; /* type of dll (Win16/Win32) */ SPEC_TYPE type; /* type of dll (Win16/Win32) */
int base; /* ordinal base */ int base; /* ordinal base */
@ -190,7 +189,8 @@ extern const char *get_asm_short_keyword(void);
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 );
extern void add_ignore_symbol( const char *name ); extern void add_ignore_symbol( const char *name );
extern void read_undef_symbols( char **argv ); extern void add_extra_ld_symbol( const char *name );
extern void read_undef_symbols( DLLSPEC *spec, 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 void output_import_thunks( FILE *outfile, DLLSPEC *spec );

View file

@ -21,6 +21,7 @@
#include "config.h" #include "config.h"
#include <assert.h>
#include <ctype.h> #include <ctype.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h> #include <stdio.h>
@ -34,7 +35,6 @@
#endif #endif
#include "winglue.h" #include "winglue.h"
//#include "wine/exception.h"
#include "build.h" #include "build.h"
#ifndef EXCEPTION_NONCONTINUABLE #ifndef EXCEPTION_NONCONTINUABLE
@ -56,13 +56,16 @@ struct import
int nb_imports; /* number of imported functions */ int nb_imports; /* number of imported functions */
}; };
static char **undef_symbols; /* list of undefined symbols */ struct name_table
static int nb_undef_symbols = -1; {
static int undef_size; char **names;
unsigned int count, size;
};
static char **ignore_symbols; /* list of symbols to ignore */ static struct name_table undef_symbols; /* list of undefined symbols */
static int nb_ignore_symbols; static struct name_table ignore_symbols; /* list of symbols to ignore */
static int ignore_size; static struct name_table extra_ld_symbols; /* list of extra symbols that ld should resolve */
static struct name_table delayed_imports; /* list of delayed import dlls */
static char *ld_tmp_file; /* ld temp file name */ static char *ld_tmp_file; /* ld temp file name */
@ -71,8 +74,6 @@ static int nb_imports = 0; /* number of imported dlls (delayed or not) */
static int nb_delayed = 0; /* number of delayed dlls */ static int nb_delayed = 0; /* number of delayed dlls */
static int total_imports = 0; /* total number of imported functions */ static int total_imports = 0; /* total number of imported functions */
static int total_delayed = 0; /* total number of imported functions in delayed DLLs */ static int total_delayed = 0; /* total number of imported functions in delayed DLLs */
static char **delayed_imports; /* names of delayed import dlls */
static int nb_delayed_imports; /* size of the delayed_imports array */
/* list of symbols that are ignored by default */ /* list of symbols that are ignored by default */
static const char * const default_ignored_symbols[] = static const char * const default_ignored_symbols[] =
@ -151,18 +152,52 @@ static int func_cmp( const void *func1, const void *func2 )
odp2->name ? odp2->name : odp2->export_name ); odp2->name ? odp2->name : odp2->export_name );
} }
/* locate a symbol in a (sorted) list */ /* add a name to a name table */
inline static const char *find_symbol( const char *name, char **table, int size ) inline static void add_name( struct name_table *table, const char *name )
{
if (table->count == table->size)
{
table->size += (table->size / 2);
if (table->size < 32) table->size = 32;
table->names = xrealloc( table->names, table->size * sizeof(*table->names) );
}
table->names[table->count++] = xstrdup( name );
}
/* remove a name from a name table */
inline static void remove_name( struct name_table *table, unsigned int idx )
{
assert( idx < table->count );
free( table->names[idx] );
memmove( table->names + idx, table->names + idx + 1,
(table->count - idx - 1) * sizeof(*table->names) );
table->count--;
}
/* make a name table empty */
inline static void empty_name_table( struct name_table *table )
{
unsigned int i;
for (i = 0; i < table->count; i++) free( table->names[i] );
table->count = 0;
}
/* locate a name in a (sorted) list */
inline static const char *find_name( const char *name, const struct name_table *table )
{ {
char **res = NULL; char **res = NULL;
if (table) { if (table->count) res = bsearch( &name, table->names, table->count, sizeof(*table->names), name_cmp );
res = bsearch( &name, table, size, sizeof(*table), name_cmp );
}
return res ? *res : NULL; return res ? *res : NULL;
} }
/* sort a name table */
inline static void sort_names( struct name_table *table )
{
if (table->count) qsort( table->names, table->count, sizeof(*table->names), name_cmp );
}
/* locate an export in a (sorted) export list */ /* locate an export in a (sorted) export list */
inline static ORDDEF *find_export( const char *name, ORDDEF **table, int size ) inline static ORDDEF *find_export( const char *name, ORDDEF **table, int size )
{ {
@ -175,13 +210,6 @@ inline static ORDDEF *find_export( const char *name, ORDDEF **table, int size )
return res ? *res : NULL; return res ? *res : NULL;
} }
/* sort a symbol table */
inline static void sort_symbols( char **table, int size )
{
if (table )
qsort( table, size, sizeof(*table), name_cmp );
}
inline static void output_function_size( FILE *outfile, const char *name ) inline static void output_function_size( FILE *outfile, const char *name )
{ {
const char *size = func_size( name ); const char *size = func_size( name );
@ -209,9 +237,9 @@ static int is_delayed_import( const char *name )
{ {
int i; int i;
for (i = 0; i < nb_delayed_imports; i++) for (i = 0; i < delayed_imports.count; i++)
{ {
if (!strcmp( delayed_imports[i], name )) return 1; if (!strcmp( delayed_imports.names[i], name )) return 1;
} }
return 0; return 0;
} }
@ -367,13 +395,13 @@ void add_delayed_import( const char *name )
struct import *imp; struct import *imp;
char *fullname = get_dll_name( name, NULL ); char *fullname = get_dll_name( name, NULL );
delayed_imports = xrealloc( delayed_imports, (nb_delayed_imports+1) * sizeof(*delayed_imports) ); add_name( &delayed_imports, fullname );
delayed_imports[nb_delayed_imports++] = fullname;
if ((imp = is_already_imported( fullname )) && !imp->delay) if ((imp = is_already_imported( fullname )) && !imp->delay)
{ {
imp->delay = 1; imp->delay = 1;
nb_delayed++; nb_delayed++;
} }
free( fullname );
} }
/* remove an imported dll, based on its index in the dll_imports array */ /* remove an imported dll, based on its index in the dll_imports array */
@ -390,52 +418,35 @@ static void remove_import_dll( int index )
/* initialize the list of ignored symbols */ /* initialize the list of ignored symbols */
static void init_ignored_symbols(void) static void init_ignored_symbols(void)
{ {
int i; unsigned int i;
nb_ignore_symbols = sizeof(default_ignored_symbols)/sizeof(default_ignored_symbols[0]); for (i = 0; i < sizeof(default_ignored_symbols)/sizeof(default_ignored_symbols[0]); i++)
ignore_size = nb_ignore_symbols + 32; add_name( &ignore_symbols, default_ignored_symbols[i] );
ignore_symbols = xmalloc( ignore_size * sizeof(*ignore_symbols) );
for (i = 0; i < nb_ignore_symbols; i++)
ignore_symbols[i] = xstrdup( default_ignored_symbols[i] );
} }
/* add a symbol to the ignored symbol list */ /* add a symbol to the ignored symbol list */
/* if the name starts with '-' the symbol is removed instead */ /* if the name starts with '-' the symbol is removed instead */
void add_ignore_symbol( const char *name ) void add_ignore_symbol( const char *name )
{ {
int i; unsigned int i;
if (!ignore_symbols) init_ignored_symbols(); /* first time around, fill list with defaults */ if (!ignore_symbols.size) init_ignored_symbols(); /* first time around, fill list with defaults */
if (name[0] == '-') /* remove it */ if (name[0] == '-') /* remove it */
{ {
if (!name[1]) /* remove everything */ if (!name[1]) empty_name_table( &ignore_symbols ); /* remove everything */
else for (i = 0; i < ignore_symbols.count; i++)
{ {
for (i = 0; i < nb_ignore_symbols; i++) free( ignore_symbols[i] ); if (!strcmp( ignore_symbols.names[i], name+1 )) remove_name( &ignore_symbols, i-- );
nb_ignore_symbols = 0;
}
else
{
for (i = 0; i < nb_ignore_symbols; i++)
{
if (!strcmp( ignore_symbols[i], name+1 ))
{
free( ignore_symbols[i] );
memmove( &ignore_symbols[i], &ignore_symbols[i+1], nb_ignore_symbols - i - 1 );
nb_ignore_symbols--;
}
}
} }
} }
else else add_name( &ignore_symbols, name );
{ }
if (nb_ignore_symbols == ignore_size)
{ /* add a symbol to the list of extra symbols that ld must resolve */
ignore_size += 32; void add_extra_ld_symbol( const char *name )
ignore_symbols = xrealloc( ignore_symbols, ignore_size * sizeof(*ignore_symbols) ); {
} add_name( &extra_ld_symbols, name );
ignore_symbols[nb_ignore_symbols++] = xstrdup( name );
}
} }
/* add a function to the list of imports from a given dll */ /* add a function to the list of imports from a given dll */
@ -447,103 +458,33 @@ static void add_import_func( struct import *imp, ORDDEF *func )
if (imp->delay) total_delayed++; if (imp->delay) total_delayed++;
} }
/* add a symbol to the undef list */ /* check if the spec file exports any stubs */
inline static void add_undef_symbol( const char *name ) static int has_stubs( const DLLSPEC *spec )
{
if (nb_undef_symbols == undef_size)
{
undef_size += 128;
undef_symbols = xrealloc( undef_symbols, undef_size * sizeof(*undef_symbols) );
}
undef_symbols[nb_undef_symbols++] = xstrdup( name );
}
/* remove all the holes in the undefined symbol list; return the number of removed symbols */
static int remove_symbol_holes(void)
{
int i, off;
for (i = off = 0; i < nb_undef_symbols; i++)
{
if (!undef_symbols[i]) off++;
else undef_symbols[i - off] = undef_symbols[i];
}
nb_undef_symbols -= off;
return off;
}
/* add a symbol to the extra list, but only if needed */
static int add_extra_symbol( const char **extras, int *count, const char *name, const DLLSPEC *spec )
{ {
int i; int i;
if (!find_symbol( name, undef_symbols, nb_undef_symbols ))
{
/* check if the symbol is being exported by this dll */
for (i = 0; i < spec->nb_entry_points; i++)
{
ORDDEF *odp = &spec->entry_points[i];
if (odp->type == TYPE_STDCALL ||
odp->type == TYPE_CDECL ||
odp->type == TYPE_VARARGS ||
odp->type == TYPE_EXTERN)
{
if (odp->name && !strcmp( odp->name, name )) return 0;
}
}
extras[*count] = name;
(*count)++;
}
return 1;
}
/* add the extra undefined symbols that will be contained in the generated spec file itself */
static void add_extra_undef_symbols( const DLLSPEC *spec )
{
const char *extras[10];
int i, count = 0, nb_stubs = 0;
int kernel_imports = 0, ntdll_imports = 0;
sort_symbols( undef_symbols, nb_undef_symbols );
for (i = 0; i < spec->nb_entry_points; i++) for (i = 0; i < spec->nb_entry_points; i++)
{ {
ORDDEF *odp = &spec->entry_points[i]; ORDDEF *odp = &spec->entry_points[i];
if (odp->type == TYPE_STUB) nb_stubs++; if (odp->type == TYPE_STUB) return 1;
} }
return 0;
}
/* add symbols that will be contained in the spec file itself */ /* get the default entry point for a given spec file */
if (!(spec->characteristics & IMAGE_FILE_DLL)) static const char *get_default_entry_point( const DLLSPEC *spec )
{ {
switch (spec->subsystem) if (spec->characteristics & IMAGE_FILE_DLL) return "__wine_spec_dll_entry";
{ if (spec->subsystem == IMAGE_SUBSYSTEM_NATIVE) return "DriverEntry";
case IMAGE_SUBSYSTEM_WINDOWS_GUI: return "__wine_spec_exe_entry";
case IMAGE_SUBSYSTEM_WINDOWS_CUI: }
kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA", spec );
kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA", spec );
kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA", spec );
kernel_imports += add_extra_symbol( extras, &count, "ExitProcess", spec );
break;
}
}
if (nb_delayed)
{
kernel_imports += add_extra_symbol( extras, &count, "LoadLibraryA", spec );
kernel_imports += add_extra_symbol( extras, &count, "FreeLibrary", spec );
kernel_imports += add_extra_symbol( extras, &count, "GetProcAddress", spec );
kernel_imports += add_extra_symbol( extras, &count, "RaiseException", spec );
}
if (nb_stubs)
ntdll_imports += add_extra_symbol( extras, &count, "RtlRaiseException", spec );
/* make sure we import the dlls that contain these functions */ /* add the extra undefined symbols that will be contained in the generated spec file itself */
if (kernel_imports) add_import_dll( "kernel32", NULL ); static void add_extra_undef_symbols( DLLSPEC *spec )
if (ntdll_imports) add_import_dll( "ntdll", NULL ); {
if (!spec->init_func) spec->init_func = xstrdup( get_default_entry_point(spec) );
if (count) add_extra_ld_symbol( spec->init_func );
{ if (has_stubs( spec )) add_extra_ld_symbol( "__wine_spec_unimplemented_stub" );
for (i = 0; i < count; i++) add_undef_symbol( extras[i] ); if (nb_delayed) add_extra_ld_symbol( "__wine_spec_delay_load" );
sort_symbols( undef_symbols, nb_undef_symbols );
}
} }
/* check if a given imported dll is not needed, taking forwards into account */ /* check if a given imported dll is not needed, taking forwards into account */
@ -570,8 +511,8 @@ static int check_unused( const struct import* imp, const DLLSPEC *spec )
/* returns the name of the combined file */ /* returns the name of the combined file */
static const char *ldcombine_files( char **argv ) static const char *ldcombine_files( char **argv )
{ {
int i, len = 0; unsigned int i, len = 0;
char *cmd; char *cmd, *p;
int fd, err; int fd, err;
if (output_file_name && output_file_name[0]) if (output_file_name && output_file_name[0])
@ -587,10 +528,14 @@ static const char *ldcombine_files( char **argv )
atexit( remove_ld_tmp_file ); atexit( remove_ld_tmp_file );
if (!ld_command) ld_command = xstrdup("ld"); if (!ld_command) ld_command = xstrdup("ld");
for (i = 0; i < extra_ld_symbols.count; i++) len += strlen(extra_ld_symbols.names[i]) + 5;
for (i = 0; argv[i]; i++) len += strlen(argv[i]) + 1; for (i = 0; argv[i]; i++) len += strlen(argv[i]) + 1;
cmd = xmalloc( len + strlen(ld_tmp_file) + 8 + strlen(ld_command) ); cmd = p = xmalloc( len + strlen(ld_tmp_file) + 8 + strlen(ld_command) );
sprintf( cmd, "%s -r -o %s", ld_command, ld_tmp_file ); p += sprintf( cmd, "%s -r -o %s", ld_command, ld_tmp_file );
for (i = 0; argv[i]; i++) sprintf( cmd + strlen(cmd), " %s", argv[i] ); for (i = 0; i < extra_ld_symbols.count; i++)
p += sprintf( p, " -u %s", asm_name(extra_ld_symbols.names[i]) );
for (i = 0; argv[i]; i++)
p += sprintf( p, " %s", argv[i] );
err = system( cmd ); err = system( cmd );
if (err) fatal_error( "%s -r failed with status %d\n", ld_command, err ); if (err) fatal_error( "%s -r failed with status %d\n", ld_command, err );
free( cmd ); free( cmd );
@ -598,7 +543,7 @@ 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( DLLSPEC *spec, char **argv )
{ {
size_t prefix_len; size_t prefix_len;
FILE *f; FILE *f;
@ -608,14 +553,12 @@ void read_undef_symbols( char **argv )
if (!argv[0]) return; if (!argv[0]) return;
add_extra_undef_symbols( spec );
strcpy( name_prefix, asm_name("") ); strcpy( name_prefix, asm_name("") );
prefix_len = strlen( name_prefix ); prefix_len = strlen( name_prefix );
undef_size = nb_undef_symbols = 0; name = ldcombine_files( argv );
/* if we have multiple object files, link them together */
if (argv[1]) name = ldcombine_files( argv );
else name = argv[0];
if (!nm_command) nm_command = xstrdup("nm"); if (!nm_command) nm_command = xstrdup("nm");
cmd = xmalloc( strlen(nm_command) + strlen(name) + 5 ); cmd = xmalloc( strlen(nm_command) + strlen(name) + 5 );
@ -632,7 +575,7 @@ void read_undef_symbols( char **argv )
while (*p == ' ') p++; while (*p == ' ') p++;
if (p[0] == 'U' && p[1] == ' ' && p[2]) p += 2; if (p[0] == 'U' && p[1] == ' ' && p[2]) p += 2;
if (prefix_len && !strncmp( p, name_prefix, prefix_len )) p += prefix_len; if (prefix_len && !strncmp( p, name_prefix, prefix_len )) p += prefix_len;
add_undef_symbol( p ); add_name( &undef_symbols, p );
} }
if ((err = pclose( f ))) warning( "%s failed with status %d\n", cmd, err ); if ((err = pclose( f ))) warning( "%s failed with status %d\n", cmd, err );
free( cmd ); free( cmd );
@ -640,47 +583,39 @@ void read_undef_symbols( char **argv )
static void remove_ignored_symbols(void) static void remove_ignored_symbols(void)
{ {
int i; unsigned int i;
if (!ignore_symbols) init_ignored_symbols(); if (!ignore_symbols.size) init_ignored_symbols();
sort_symbols( ignore_symbols, nb_ignore_symbols ); sort_names( &ignore_symbols );
for (i = 0; i < nb_undef_symbols; i++) for (i = 0; i < undef_symbols.count; i++)
{ {
if (find_symbol( undef_symbols[i], ignore_symbols, nb_ignore_symbols )) if (find_name( undef_symbols.names[i], &ignore_symbols ))
{ remove_name( &undef_symbols, i-- );
free( undef_symbols[i] );
undef_symbols[i] = NULL;
}
} }
remove_symbol_holes();
} }
/* resolve the imports for a Win32 module */ /* resolve the imports for a Win32 module */
int resolve_imports( DLLSPEC *spec ) int resolve_imports( DLLSPEC *spec )
{ {
int i, j; unsigned int i, j, removed;
if (nb_undef_symbols == -1) return 0; /* no symbol file specified */
add_extra_undef_symbols( spec );
remove_ignored_symbols(); remove_ignored_symbols();
for (i = 0; i < nb_imports; i++) for (i = 0; i < nb_imports; i++)
{ {
struct import *imp = dll_imports[i]; struct import *imp = dll_imports[i];
for (j = 0; j < nb_undef_symbols; j++) for (j = removed = 0; j < undef_symbols.count; j++)
{ {
ORDDEF *odp = find_export( undef_symbols[j], imp->exports, imp->nb_exports ); ORDDEF *odp = find_export( undef_symbols.names[j], imp->exports, imp->nb_exports );
if (odp) if (odp)
{ {
add_import_func( imp, odp ); add_import_func( imp, odp );
free( undef_symbols[j] ); remove_name( &undef_symbols, j-- );
undef_symbols[j] = NULL; removed++;
} }
} }
/* remove all the holes in the undef symbols list */ if (!removed && check_unused( imp, spec ))
if (!remove_symbol_holes() && check_unused( imp, spec ))
{ {
/* the dll is not used, get rid of it */ /* the dll is not used, get rid of it */
warning( "%s imported but no symbols used\n", imp->spec->file_name ); warning( "%s imported but no symbols used\n", imp->spec->file_name );
@ -919,7 +854,7 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
} }
} }
fprintf( outfile, "\n" ); fprintf( outfile, "\n" );
fprintf( outfile, "static struct {\n" ); fprintf( outfile, "struct {\n" );
fprintf( outfile, " struct ImgDelayDescr {\n" ); fprintf( outfile, " struct ImgDelayDescr {\n" );
fprintf( outfile, " unsigned int grAttrs;\n" ); fprintf( outfile, " unsigned int grAttrs;\n" );
fprintf( outfile, " const char *szName;\n" ); fprintf( outfile, " const char *szName;\n" );
@ -929,15 +864,15 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
fprintf( outfile, " void* pBoundIAT;\n" ); fprintf( outfile, " void* pBoundIAT;\n" );
fprintf( outfile, " void* pUnloadIAT;\n" ); fprintf( outfile, " void* pUnloadIAT;\n" );
fprintf( outfile, " unsigned long dwTimeStamp;\n" ); fprintf( outfile, " unsigned long dwTimeStamp;\n" );
fprintf( outfile, " } imp[%d];\n", nb_delayed ); fprintf( outfile, " } imp[%d];\n", nb_delayed + 1 );
fprintf( outfile, " void *IAT[%d];\n", total_delayed ); fprintf( outfile, " void *IAT[%d];\n", total_delayed );
fprintf( outfile, " const char *INT[%d];\n", total_delayed ); fprintf( outfile, " const char *INT[%d];\n", total_delayed );
fprintf( outfile, "} delay_imports = {\n" ); fprintf( outfile, "} __wine_spec_delay_imports = {\n" );
fprintf( outfile, " {\n" ); fprintf( outfile, " {\n" );
for (i = j = 0; i < nb_imports; i++) for (i = j = 0; i < nb_imports; i++)
{ {
if (!dll_imports[i]->delay) continue; if (!dll_imports[i]->delay) continue;
fprintf( outfile, " { 0, \"%s\", &__wine_delay_imp_hmod[%d], &delay_imports.IAT[%d], &delay_imports.INT[%d], 0, 0, 0 },\n", fprintf( outfile, " { 0, \"%s\", &__wine_delay_imp_hmod[%d], &__wine_spec_delay_imports.IAT[%d], &__wine_spec_delay_imports.INT[%d], 0, 0, 0 },\n",
dll_imports[i]->spec->file_name, i, j, j ); dll_imports[i]->spec->file_name, i, j, j );
j += dll_imports[i]->nb_imports; j += dll_imports[i]->nb_imports;
} }
@ -969,32 +904,6 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
} }
fprintf( outfile, " }\n};\n\n" ); fprintf( outfile, " }\n};\n\n" );
fprintf( outfile, "extern void __stdcall RaiseException(unsigned int, unsigned int, unsigned int, const void *args[]);\n" );
fprintf( outfile, "extern void * __stdcall LoadLibraryA(const char*);\n");
fprintf( outfile, "extern void * __stdcall GetProcAddress(void *, const char*);\n");
fprintf( outfile, "\n" );
fprintf( outfile, "void *__stdcall __wine_delay_load( int idx_nr )\n" );
fprintf( outfile, "{\n" );
fprintf( outfile, " int idx = idx_nr >> 16, nr = idx_nr & 0xffff;\n" );
fprintf( outfile, " struct ImgDelayDescr *imd = delay_imports.imp + idx;\n" );
fprintf( outfile, " void **pIAT = imd->pIAT + nr;\n" );
fprintf( outfile, " const char** pINT = imd->pINT + nr;\n" );
fprintf( outfile, " void *fn;\n\n" );
fprintf( outfile, " if (!*imd->phmod) *imd->phmod = LoadLibraryA(imd->szName);\n" );
fprintf( outfile, " if (*imd->phmod && (fn = GetProcAddress(*imd->phmod, *pINT)))\n");
fprintf( outfile, " /* patch IAT with final value */\n" );
fprintf( outfile, " return *pIAT = fn;\n" );
fprintf( outfile, " else {\n");
fprintf( outfile, " const void *args[2];\n" );
fprintf( outfile, " args[0] = imd->szName;\n" );
fprintf( outfile, " args[1] = *pINT;\n" );
fprintf( outfile, " RaiseException( 0x%08x, %d, 2, args );\n",
EXCEPTION_WINE_STUB, EXCEPTION_NONCONTINUABLE );
fprintf( outfile, " return 0;\n" );
fprintf( outfile, " }\n}\n" );
return nb_delayed; return nb_delayed;
} }
@ -1017,17 +926,17 @@ static void output_delayed_import_thunks( FILE *outfile, const DLLSPEC *spec )
{ {
case CPU_x86: case CPU_x86:
fprintf( outfile, " \"\\tpushl %%ecx\\n\\tpushl %%edx\\n\\tpushl %%eax\\n\"\n" ); 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, " \"\\tcall %s\\n\"\n", asm_name("__wine_spec_delay_load") );
fprintf( outfile, " \"\\tpopl %%edx\\n\\tpopl %%ecx\\n\\tjmp *%%eax\\n\"\n" ); fprintf( outfile, " \"\\tpopl %%edx\\n\\tpopl %%ecx\\n\\tjmp *%%eax\\n\"\n" );
break; break;
case CPU_SPARC: case CPU_SPARC:
fprintf( outfile, " \"\\tsave %%sp, -96, %%sp\\n\"\n" ); fprintf( outfile, " \"\\tsave %%sp, -96, %%sp\\n\"\n" );
fprintf( outfile, " \"\\tcall %s\\n\"\n", asm_name("__wine_delay_load") ); fprintf( outfile, " \"\\tcall %s\\n\"\n", asm_name("__wine_spec_delay_load") );
fprintf( outfile, " \"\\tmov %%g1, %%o0\\n\"\n" ); fprintf( outfile, " \"\\tmov %%g1, %%o0\\n\"\n" );
fprintf( outfile, " \"\\tjmp %%o0\\n\\trestore\\n\"\n" ); fprintf( outfile, " \"\\tjmp %%o0\\n\\trestore\\n\"\n" );
break; break;
case CPU_ALPHA: case CPU_ALPHA:
fprintf( outfile, " \"\\tjsr $26,%s\\n\"\n", asm_name("__wine_delay_load") ); fprintf( outfile, " \"\\tjsr $26,%s\\n\"\n", asm_name("__wine_spec_delay_load") );
fprintf( outfile, " \"\\tjmp $31,($0)\\n\"\n" ); fprintf( outfile, " \"\\tjmp $31,($0)\\n\"\n" );
break; break;
case CPU_POWERPC: case CPU_POWERPC:
@ -1054,7 +963,7 @@ static void output_delayed_import_thunks( FILE *outfile, const DLLSPEC *spec )
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg(0), 44+extra_stack_storage, ppc_reg(1)); fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg(0), 44+extra_stack_storage, ppc_reg(1));
/* Call the __wine_delay_load function, arg1 is arg1. */ /* Call the __wine_delay_load function, arg1 is arg1. */
fprintf( outfile, " \"\\tbl %s\\n\"\n", asm_name("__wine_delay_load") ); fprintf( outfile, " \"\\tbl %s\\n\"\n", asm_name("__wine_spec_delay_load") );
/* Load return value from call into ctr register */ /* Load return value from call into ctr register */
fprintf( outfile, " \"\\tmtctr %s\\n\"\n", ppc_reg(3)); fprintf( outfile, " \"\\tmtctr %s\\n\"\n", ppc_reg(3));
@ -1145,7 +1054,7 @@ static void output_delayed_import_thunks( FILE *outfile, const DLLSPEC *spec )
fprintf( outfile, "\n \".align %d\\n\"\n", get_alignment(8) ); fprintf( outfile, "\n \".align %d\\n\"\n", get_alignment(8) );
fprintf( outfile, " \"%s:\\n\"\n", asm_name(delayed_import_thunks)); fprintf( outfile, " \"%s:\\n\"\n", asm_name(delayed_import_thunks));
pos = nb_delayed * 32; pos = (nb_delayed + 1) * 32;
for (i = 0; i < nb_imports; i++) for (i = 0; i < nb_imports; i++)
{ {
if (!dll_imports[i]->delay) continue; if (!dll_imports[i]->delay) continue;
@ -1153,7 +1062,7 @@ static void output_delayed_import_thunks( FILE *outfile, const DLLSPEC *spec )
{ {
ORDDEF *odp = dll_imports[i]->imports[j]; ORDDEF *odp = dll_imports[i]->imports[j];
output_import_thunk( outfile, odp->name ? odp->name : odp->export_name, output_import_thunk( outfile, odp->name ? odp->name : odp->export_name,
"delay_imports", pos ); "__wine_spec_delay_imports", pos );
} }
} }
output_function_size( outfile, delayed_import_thunks ); output_function_size( outfile, delayed_import_thunks );

View file

@ -233,31 +233,32 @@ static void exit_on_signal( int sig )
static const char usage_str[] = static const char usage_str[] =
"Usage: winebuild [OPTIONS] [FILES]\n\n" "Usage: winebuild [OPTIONS] [FILES]\n\n"
"Options:\n" "Options:\n"
" -C --source-dir=DIR Look for source files in DIR\n" " -C, --source-dir=DIR Look for source files in DIR\n"
" -d --delay-lib=LIB Import the specified library in delayed mode\n" " -d, --delay-lib=LIB Import the specified library in delayed mode\n"
" -D SYM Ignored for C flags compatibility\n" " -D SYM Ignored for C flags compatibility\n"
" -E --export=FILE Export the symbols defined in the .spec or .def file\n" " -E, --export=FILE Export the symbols defined in the .spec or .def file\n"
" -e --entry=FUNC Set the DLL entry point function (default: DllMain)\n" " -e, --entry=FUNC Set the DLL entry point function (default: DllMain)\n"
" -f FLAGS Compiler flags (only -fPIC is supported)\n" " -f FLAGS Compiler flags (only -fPIC is supported)\n"
" -F --filename=DLLFILE Set the DLL filename (default: from input file name)\n" " -F, --filename=DLLFILE Set the DLL filename (default: from input file name)\n"
" -h --help Display this help message\n" " -h, --help Display this help message\n"
" -H --heap=SIZE Set the heap size for a Win16 dll\n" " -H, --heap=SIZE Set the heap size for a Win16 dll\n"
" -i --ignore=SYM[,SYM] Ignore specified symbols when resolving imports\n" " -i, --ignore=SYM[,SYM] Ignore specified symbols when resolving imports\n"
" -I DIR Ignored for C flags compatibility\n" " -I DIR Ignored for C flags compatibility\n"
" -k --kill-at Kill stdcall decorations in generated .def files\n" " -k, --kill-at Kill stdcall decorations in generated .def files\n"
" -K FLAGS Compiler flags (only -KPIC is supported)\n" " -K, FLAGS Compiler flags (only -KPIC is supported)\n"
" --ld-cmd=LD Command to use for linking (default: ld)\n" " --ld-cmd=LD Command to use for linking (default: ld)\n"
" -l --library=LIB Import the specified library\n" " -l, --library=LIB Import the specified library\n"
" -L --library-path=DIR Look for imports libraries in DIR\n" " -L, --library-path=DIR Look for imports libraries in DIR\n"
" -M --main-module=MODULE Set the name of the main module for a Win16 dll\n" " -M, --main-module=MODULE Set the name of the main module for a Win16 dll\n"
" --nm-cmd=NM Command to use to get undefined symbols (default: nm)\n" " --nm-cmd=NM Command to use to get undefined symbols (default: nm)\n"
" -N --dll-name=DLLNAME Set the DLL name (default: from input file name)\n" " -N, --dll-name=DLLNAME Set the DLL name (default: from input file name)\n"
" -o --output=NAME Set the output file name (default: stdout)\n" " -o, --output=NAME Set the output file name (default: stdout)\n"
" -r --res=RSRC.RES Load resources from RSRC.RES\n" " -r, --res=RSRC.RES Load resources from RSRC.RES\n"
" --subsystem=SUBSYS Set the subsystem (one of native, windows, console)\n" " --subsystem=SUBSYS Set the subsystem (one of native, windows, console)\n"
" --target=TARGET Specify target CPU and platform for cross-compiling\n" " --target=TARGET Specify target CPU and platform for cross-compiling\n"
" -u, --undefined=SYMBOL Add an undefined reference to SYMBOL when linking\n"
" --version Print the version and exit\n" " --version Print the version and exit\n"
" -w --warnings Turn on warnings\n" " -w, --warnings Turn on warnings\n"
"\nMode options:\n" "\nMode options:\n"
" --dll Build a .c file from a .spec or .def file\n" " --dll Build a .c file from a .spec or .def file\n"
" --def Build a .def file from a .spec file\n" " --def Build a .def file from a .spec file\n"
@ -284,7 +285,7 @@ enum long_options_values
LONG_OPT_PEDLL LONG_OPT_PEDLL
}; };
static const char short_options[] = "C:D:E:F:H:I:K:L:M:N:d:e:f:hi:kl:m:o:r:w"; static const char short_options[] = "C:D:E:F:H:I:K:L:M:N:d:e:f:hi:kl:m:o:r:u:w";
static const struct option long_options[] = static const struct option long_options[] =
{ {
@ -316,6 +317,7 @@ static const struct option long_options[] =
{ "dll-name", 1, 0, 'N' }, { "dll-name", 1, 0, 'N' },
{ "output", 1, 0, 'o' }, { "output", 1, 0, 'o' },
{ "res", 1, 0, 'r' }, { "res", 1, 0, 'r' },
{ "undefined", 1, 0, 'u' },
{ "warnings", 0, 0, 'w' }, { "warnings", 0, 0, 'w' },
{ NULL, 0, 0, 0 } { NULL, 0, 0, 0 }
}; };
@ -373,7 +375,6 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec )
lib_path[nb_lib_paths++] = xstrdup( optarg ); lib_path[nb_lib_paths++] = xstrdup( optarg );
break; break;
case 'M': case 'M':
spec->owner_name = xstrdup( optarg );
spec->type = SPEC_WIN16; spec->type = SPEC_WIN16;
break; break;
case 'N': case 'N':
@ -423,6 +424,9 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec )
res_files = xrealloc( res_files, (nb_res_files+1) * sizeof(*res_files) ); res_files = xrealloc( res_files, (nb_res_files+1) * sizeof(*res_files) );
res_files[nb_res_files++] = xstrdup( optarg ); res_files[nb_res_files++] = xstrdup( optarg );
break; break;
case 'u':
add_extra_ld_symbol( optarg );
break;
case 'w': case 'w':
display_warnings = 1; display_warnings = 1;
break; break;
@ -568,7 +572,7 @@ int main(int argc, char **argv)
fatal_error( "Win16 specs are not supported in ReactOS version of winebuild\n" ); fatal_error( "Win16 specs are not supported in ReactOS version of winebuild\n" );
break; break;
case SPEC_WIN32: case SPEC_WIN32:
read_undef_symbols( argv ); read_undef_symbols( spec, argv );
BuildSpec32File( output_file, spec ); BuildSpec32File( output_file, spec );
break; break;
default: assert(0); default: assert(0);
@ -580,7 +584,7 @@ int main(int argc, char **argv)
load_resources( argv, spec ); load_resources( argv, spec );
load_import_libs( argv ); load_import_libs( argv );
if (spec_file_name && !parse_input_file( spec )) break; if (spec_file_name && !parse_input_file( spec )) break;
read_undef_symbols( argv ); read_undef_symbols( spec, argv );
BuildSpec32File( output_file, spec ); BuildSpec32File( output_file, spec );
break; break;
case MODE_DEF: case MODE_DEF:

View file

@ -520,9 +520,14 @@ static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
if (!strcmp( odp->name, "DllRegisterServer" ) || if (!strcmp( odp->name, "DllRegisterServer" ) ||
!strcmp( odp->name, "DllUnregisterServer" ) || !strcmp( odp->name, "DllUnregisterServer" ) ||
!strcmp( odp->name, "DllGetClassObject" ) || !strcmp( odp->name, "DllGetClassObject" ) ||
!strcmp( odp->name, "DllGetVersion" ) ||
!strcmp( odp->name, "DllInstall" ) ||
!strcmp( odp->name, "DllCanUnloadNow" )) !strcmp( odp->name, "DllCanUnloadNow" ))
{ {
warning( "Function %s should be marked private\n", odp->name ); warning( "Function %s should be marked private\n", odp->name );
if (strcmp( odp->name, odp->link_name ))
warning( "Function %s should not use a different internal name (%s)\n",
odp->name, odp->link_name );
} }
} }
@ -602,6 +607,16 @@ static void assign_ordinals( DLLSPEC *spec )
int i, count, ordinal; int i, count, ordinal;
/* start assigning from base, or from 1 if no ordinal defined yet */ /* start assigning from base, or from 1 if no ordinal defined yet */
spec->base = MAX_ORDINALS;
spec->limit = 0;
for (i = 0; i < spec->nb_entry_points; i++)
{
ordinal = spec->entry_points[i].ordinal;
if (ordinal == -1) continue;
if (ordinal > spec->limit) spec->limit = ordinal;
if (ordinal < spec->base) spec->base = ordinal;
}
if (spec->base == MAX_ORDINALS) spec->base = 1; if (spec->base == MAX_ORDINALS) spec->base = 1;
if (spec->limit < spec->base) spec->limit = spec->base; if (spec->limit < spec->base) spec->limit = spec->base;
@ -819,8 +834,6 @@ static int parse_def_export( char *name, DLLSPEC *spec )
error( "Ordinal number %d too large\n", ordinal ); error( "Ordinal number %d too large\n", ordinal );
goto error; goto error;
} }
if (ordinal > spec->limit) spec->limit = ordinal;
if (ordinal < spec->base) spec->base = ordinal;
odp->ordinal = ordinal; odp->ordinal = ordinal;
token = GetToken(1); token = GetToken(1);
} }

View file

@ -82,6 +82,7 @@ struct res_tree
unsigned int nb_types; /* total number of types */ unsigned int nb_types; /* total number of types */
}; };
static int byte_swapped; /* whether the current resource file is byte-swapped */
static const unsigned char *file_pos; /* current position in resource file */ static const unsigned char *file_pos; /* current position in resource file */
static const unsigned char *file_end; /* end of resource file */ static const unsigned char *file_end; /* end of resource file */
static const char *file_name; /* current resource file name */ static const char *file_name; /* current resource file name */
@ -137,6 +138,7 @@ static struct res_type *add_type( struct res_tree *tree, const struct resource *
static WORD get_word(void) static WORD get_word(void)
{ {
WORD ret = *(const WORD *)file_pos; WORD ret = *(const WORD *)file_pos;
if (byte_swapped) ret = (ret << 8) | (ret >> 8);
file_pos += sizeof(WORD); file_pos += sizeof(WORD);
if (file_pos > file_end) fatal_error( "%s is a truncated file\n", file_name ); if (file_pos > file_end) fatal_error( "%s is a truncated file\n", file_name );
return ret; return ret;
@ -146,6 +148,8 @@ static WORD get_word(void)
static DWORD get_dword(void) static DWORD get_dword(void)
{ {
DWORD ret = *(const DWORD *)file_pos; DWORD ret = *(const DWORD *)file_pos;
if (byte_swapped)
ret = ((ret << 24) | ((ret << 8) & 0x00ff0000) | ((ret >> 8) & 0x0000ff00) | (ret >> 24));
file_pos += sizeof(DWORD); file_pos += sizeof(DWORD);
if (file_pos > file_end) fatal_error( "%s is a truncated file\n", file_name ); if (file_pos > file_end) fatal_error( "%s is a truncated file\n", file_name );
return ret; return ret;
@ -173,8 +177,12 @@ static void get_string( struct string_id *str )
/* all values must be zero except header size */ /* all values must be zero except header size */
static int check_header(void) static int check_header(void)
{ {
DWORD size;
if (get_dword()) return 0; /* data size */ if (get_dword()) return 0; /* data size */
if (get_dword() != 32) return 0; /* header size */ size = get_dword(); /* header size */
if (size == 0x20000000) byte_swapped = 1;
else if (size != 0x20) return 0;
if (get_word() != 0xffff || get_word()) return 0; /* type, must be id 0 */ if (get_word() != 0xffff || get_word()) return 0; /* type, must be id 0 */
if (get_word() != 0xffff || get_word()) return 0; /* name, must be id 0 */ if (get_word() != 0xffff || get_word()) return 0; /* name, must be id 0 */
if (get_dword()) return 0; /* data version */ if (get_dword()) return 0; /* data version */
@ -228,6 +236,7 @@ int load_res32_file( const char *name, DLLSPEC *spec )
fatal_error( "Cannot read %s\n", name ); fatal_error( "Cannot read %s\n", name );
} }
byte_swapped = 0;
file_name = name; file_name = name;
file_pos = base; file_pos = base;
file_end = file_pos + st.st_size; file_end = file_pos + st.st_size;

View file

@ -362,15 +362,10 @@ static void output_stub_funcs( FILE *outfile, const DLLSPEC *spec )
ORDDEF *odp = spec->ordinals[i]; ORDDEF *odp = spec->ordinals[i];
if (!odp || odp->type != TYPE_STUB) continue; if (!odp || odp->type != TYPE_STUB) continue;
fprintf( outfile, "#ifdef __GNUC__\n" ); fprintf( outfile, "#ifdef __GNUC__\n" );
fprintf( outfile, "static void __wine_unimplemented( const char *func ) __attribute__((noreturn));\n" ); fprintf( outfile, "extern void __wine_spec_unimplemented_stub( const char *module, const char *func ) __attribute__((noreturn));\n" );
fprintf( outfile, "#endif\n" ); fprintf( outfile, "#else\n" );
fprintf( outfile, "static void __wine_unimplemented( const char *func )\n{\n" ); fprintf( outfile, "extern void __wine_spec_unimplemented_stub( const char *module, const char *func );\n" );
fprintf( outfile, " extern void __stdcall RaiseException( unsigned int, unsigned int, unsigned int, const void ** );\n" ); fprintf( outfile, "#endif\n\n" );
fprintf( outfile, " const void *args[2];\n" );
fprintf( outfile, " args[0] = \"%s\";\n", spec->file_name );
fprintf( outfile, " args[1] = func;\n" );
fprintf( outfile, " for (;;) RaiseException( 0x%08x, %d, 2, args );\n}\n\n",
EXCEPTION_WINE_STUB, EH_NONCONTINUABLE );
break; break;
} }
for (i = 0; i <= spec->limit; i++) for (i = 0; i <= spec->limit; i++)
@ -381,7 +376,7 @@ static void output_stub_funcs( FILE *outfile, const DLLSPEC *spec )
strcpy( odp->link_name, "__wine_stub_" ); strcpy( odp->link_name, "__wine_stub_" );
strcat( odp->link_name, odp->name ); strcat( odp->link_name, odp->name );
for (p = odp->link_name; *p; p++) if (!isalnum(*p)) *p = '_'; for (p = odp->link_name; *p; p++) if (!isalnum(*p)) *p = '_';
fprintf( outfile, "static void %s(void) { __wine_unimplemented(\"%s\"); }\n", fprintf( outfile, "static void %s(void) { __wine_spec_unimplemented_stub(__wine_spec16_file_name, \"%s\"); }\n",
odp->link_name, odp->name ); odp->link_name, odp->name );
} }
} }
@ -413,6 +408,7 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
/* File header */ /* File header */
output_file_header( outfile ); output_file_header( outfile );
fprintf( outfile, "static const char __wine_spec16_file_name[] = \"%s\";\n", spec->file_name );
fprintf( outfile, "extern unsigned short __wine_call_from_16_word();\n" ); fprintf( outfile, "extern unsigned short __wine_call_from_16_word();\n" );
fprintf( outfile, "extern unsigned int __wine_call_from_16_long();\n" ); fprintf( outfile, "extern unsigned int __wine_call_from_16_long();\n" );
fprintf( outfile, "extern void __wine_call_from_16_regs();\n" ); fprintf( outfile, "extern void __wine_call_from_16_regs();\n" );

View file

@ -66,30 +66,6 @@ static const char *make_internal_name( const ORDDEF *odp, DLLSPEC *spec, const c
return buffer; return buffer;
} }
/*******************************************************************
* declare_weak_function
*
* Output a prototype for a weak function.
*/
static void declare_weak_function( FILE *outfile, const char *ret_type, const char *name, const char *params)
{
fprintf( outfile, "#ifdef __GNUC__\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, "#define %s __wine_spec_weak_%s\n", name, name );
fprintf( outfile, "asm(\".weak_reference %s\");\n", asm_name(name) );
}
else fprintf( outfile, "extern %s %s(%s) __attribute__((weak));\n", ret_type, name, params );
fprintf( outfile, "#else\n" );
fprintf( outfile, "extern %s %s(%s);\n", ret_type, name, params );
fprintf( outfile, "static void __asm__dummy_%s(void)", name );
fprintf( outfile, " { asm(\".weak %s\"); }\n", asm_name(name) );
fprintf( outfile, "#endif\n\n" );
}
/******************************************************************* /*******************************************************************
* output_debug * output_debug
@ -128,7 +104,7 @@ static int output_debug( FILE *outfile )
static int get_exports_size( DLLSPEC *spec ) static int get_exports_size( DLLSPEC *spec )
{ {
int nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0; int nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
int i, fwd_size = 0, total_size; int i, strings_size, total_size;
if (!nr_exports) return 0; if (!nr_exports) return 0;
@ -145,37 +121,23 @@ static int get_exports_size( DLLSPEC *spec )
total_size += spec->nb_names * sizeof(short); total_size += spec->nb_names * sizeof(short);
if (spec->nb_names % 2) total_size += sizeof(short); if (spec->nb_names % 2) total_size += sizeof(short);
/* export name strings */
strings_size = strlen(spec->file_name) + 1;
for (i = 0; i < spec->nb_names; i++)
strings_size += strlen(spec->names[i]->name) + 1;
/* forward strings */ /* forward strings */
for (i = spec->base; i <= spec->limit; i++) for (i = spec->base; i <= spec->limit; i++)
{ {
ORDDEF *odp = spec->ordinals[i]; ORDDEF *odp = spec->ordinals[i];
if (odp && odp->flags & FLAG_FORWARD) fwd_size += strlen(odp->link_name) + 1; if (odp && odp->flags & FLAG_FORWARD) strings_size += strlen(odp->link_name) + 1;
} }
total_size += (fwd_size + 3) & ~3; total_size += (strings_size + 3) & ~3;
return total_size; 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
* *
@ -198,7 +160,7 @@ static void output_exports( FILE *outfile, DLLSPEC *spec )
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 %s\\n\"\n", asm_name("__wine_spec_exp_names") ); /* Name */ fprintf( outfile, " \"\\t.long __wine_spec_exp_names\\n\"\n" ); /* 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 */
@ -255,13 +217,10 @@ static void output_exports( FILE *outfile, 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 %s+%d\\n\"\n", asm_name("__wine_spec_exp_names"), namepos ); fprintf( outfile, " \"\\t.long __wine_spec_exp_names+%d\\n\"\n", namepos );
namepos += strlen(spec->names[i]->name) + 1; namepos += strlen(spec->names[i]->name) + 1;
} }
}
if (spec->nb_names)
{
/* output the function ordinals */ /* output the function ordinals */
fprintf( outfile, " \"__wine_spec_exp_ordinals:\\n\"\n" ); fprintf( outfile, " \"__wine_spec_exp_ordinals:\\n\"\n" );
@ -276,6 +235,14 @@ static void output_exports( FILE *outfile, DLLSPEC *spec )
} }
} }
/* output the export name strings */
fprintf( outfile, " \"__wine_spec_exp_names:\\n\"\n" );
fprintf( outfile, " \"\\t%s \\\"%s\\\"\\n\"\n", get_asm_string_keyword(), spec->file_name );
for (i = 0; i < spec->nb_names; i++)
fprintf( outfile, " \"\\t%s \\\"%s\\\"\\n\"\n",
get_asm_string_keyword(), spec->names[i]->name );
/* output forward strings */ /* output forward strings */
if (fwd_size) if (fwd_size)
@ -287,8 +254,8 @@ static void output_exports( FILE *outfile, DLLSPEC *spec )
if (odp && (odp->flags & FLAG_FORWARD)) if (odp && (odp->flags & FLAG_FORWARD))
fprintf( outfile, " \"\\t%s \\\"%s\\\"\\n\"\n", get_asm_string_keyword(), odp->link_name ); fprintf( outfile, " \"\\t%s \\\"%s\\\"\\n\"\n", get_asm_string_keyword(), odp->link_name );
} }
fprintf( outfile, " \"\\t.align %d\\n\"\n", get_alignment(4) );
} }
fprintf( outfile, " \"\\t.align %d\\n\"\n", get_alignment(4) );
/* output relays */ /* output relays */
@ -356,29 +323,10 @@ static void output_stub_funcs( FILE *outfile, DLLSPEC *spec )
ORDDEF *odp = &spec->entry_points[i]; ORDDEF *odp = &spec->entry_points[i];
if (odp->type != TYPE_STUB) continue; if (odp->type != TYPE_STUB) continue;
fprintf( outfile, "#ifdef __GNUC__\n" ); fprintf( outfile, "#ifdef __GNUC__\n" );
fprintf( outfile, "static void __wine_unimplemented( const char *func ) __attribute__((noreturn));\n" ); fprintf( outfile, "extern void __wine_spec_unimplemented_stub( const char *module, const char *func ) __attribute__((noreturn));\n" );
fprintf( outfile, "#endif\n\n" );
fprintf( outfile, "struct exc_record {\n" );
fprintf( outfile, " unsigned int code, flags;\n" );
fprintf( outfile, " void *rec, *addr;\n" );
fprintf( outfile, " unsigned int params;\n" );
fprintf( outfile, " const void *info[15];\n" );
fprintf( outfile, "};\n\n" );
fprintf( outfile, "extern void __stdcall RtlRaiseException( struct exc_record * );\n\n" );
fprintf( outfile, "static void __wine_unimplemented( const char *func )\n{\n" );
fprintf( outfile, " struct exc_record rec;\n" );
fprintf( outfile, " rec.code = 0x%08x;\n", EXCEPTION_WINE_STUB );
fprintf( outfile, " rec.flags = %d;\n", EH_NONCONTINUABLE );
fprintf( outfile, " rec.rec = 0;\n" );
fprintf( outfile, " rec.params = 2;\n" );
fprintf( outfile, " rec.info[0] = \"%s\";\n", spec->file_name );
fprintf( outfile, " rec.info[1] = func;\n" );
fprintf( outfile, "#ifdef __GNUC__\n" );
fprintf( outfile, " rec.addr = __builtin_return_address(1);\n" );
fprintf( outfile, "#else\n" ); fprintf( outfile, "#else\n" );
fprintf( outfile, " rec.addr = 0;\n" ); fprintf( outfile, "extern void __wine_spec_unimplemented_stub( const char *module, const char *func );\n" );
fprintf( outfile, "#endif\n" ); fprintf( outfile, "#endif\n\n" );
fprintf( outfile, " for (;;) RtlRaiseException( &rec );\n}\n\n" );
break; break;
} }
@ -388,11 +336,11 @@ static void output_stub_funcs( FILE *outfile, DLLSPEC *spec )
if (odp->type != TYPE_STUB) continue; if (odp->type != TYPE_STUB) continue;
fprintf( outfile, "void %s(void) ", make_internal_name( odp, spec, "stub" ) ); fprintf( outfile, "void %s(void) ", make_internal_name( odp, spec, "stub" ) );
if (odp->name) if (odp->name)
fprintf( outfile, "{ __wine_unimplemented(\"%s\"); }\n", odp->name ); fprintf( outfile, "{ __wine_spec_unimplemented_stub(__wine_spec_file_name, \"%s\"); }\n", odp->name );
else if (odp->export_name) else if (odp->export_name)
fprintf( outfile, "{ __wine_unimplemented(\"%s\"); }\n", odp->export_name ); fprintf( outfile, "{ __wine_spec_unimplemented_stub(__wine_spec_file_name, \"%s\"); }\n", odp->export_name );
else else
fprintf( outfile, "{ __wine_unimplemented(\"%d\"); }\n", odp->ordinal ); fprintf( outfile, "{ __wine_spec_unimplemented_stub(__wine_spec_file_name, \"%d\"); }\n", odp->ordinal );
} }
} }
@ -496,7 +444,6 @@ 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;
unsigned int page_size = get_page_size(); unsigned int page_size = get_page_size();
const char *init_func = spec->init_func;
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 );
@ -528,15 +475,10 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
else else
fprintf( outfile, "extern char _end[];\n" ); fprintf( outfile, "extern char _end[];\n" );
fprintf( outfile, "static const char __wine_spec_file_name[] = \"%s\";\n", spec->file_name );
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" );
if (target_cpu == CPU_x86)
fprintf( outfile, "#define __stdcall __attribute__((__stdcall__))\n\n" );
else
fprintf( outfile, "#define __stdcall\n\n" );
output_stub_funcs( outfile, spec ); output_stub_funcs( outfile, spec );
output_export_names( outfile, spec );
/* Output the DLL imports */ /* Output the DLL imports */
@ -548,152 +490,8 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
/* Output the entry point function */ /* Output the entry point function */
fprintf( outfile, "static int __wine_spec_init_state;\n" ); fprintf( outfile, "int __wine_spec_init_state = 0;\n" );
fprintf( outfile, "extern int __wine_main_argc;\n" ); fprintf( outfile, "extern void %s();\n\n", spec->init_func );
fprintf( outfile, "extern char **__wine_main_argv;\n" );
fprintf( outfile, "extern char **__wine_main_environ;\n" );
fprintf( outfile, "extern unsigned short **__wine_main_wargv;\n" );
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, "{\n" );
fprintf( outfile, " void (*init)(void);\n" );
fprintf( outfile, " _dyld_func_lookup(\"__dyld_make_delayed_module_initializer_calls\", (unsigned long *)&init);\n" );
fprintf( outfile, " init();\n" );
fprintf( outfile, "}\n" );
fprintf( outfile, "static void __wine_spec_hidden_fini()\n" );
fprintf( outfile, "{\n" );
fprintf( outfile, " void (*fini)(void);\n" );
fprintf( outfile, " _dyld_func_lookup(\"__dyld_mod_term_funcs\", (unsigned long *)&fini);\n" );
fprintf( outfile, " fini();\n" );
fprintf( outfile, "}\n" );
fprintf( outfile, "#define _init __wine_spec_hidden_init\n" );
fprintf( outfile, "#define _fini __wine_spec_hidden_fini\n" );
}
else
{
fprintf( outfile, "extern void _init(int, char**, char**);\n" );
fprintf( outfile, "extern void _fini();\n" );
}
if (spec->characteristics & IMAGE_FILE_DLL)
{
if (init_func)
fprintf( outfile, "extern int __stdcall %s( void*, unsigned int, void* );\n\n", init_func );
else
{
declare_weak_function( outfile, "int __stdcall", "DllMain", "void*, unsigned int, void*" );
init_func = "DllMain";
}
fprintf( outfile,
"static int __stdcall __wine_dll_main( void *inst, unsigned int reason, void *reserved )\n"
"{\n"
" int ret;\n"
" if (reason == %d && __wine_spec_init_state == 1)\n"
" _init( __wine_main_argc, __wine_main_argv, __wine_main_environ );\n"
" ret = %s ? %s( inst, reason, reserved ) : 1;\n"
" if (reason == %d && __wine_spec_init_state == 1)\n",
DLL_PROCESS_ATTACH, init_func, init_func, DLL_PROCESS_DETACH );
if (!nr_delayed)
fprintf( outfile, " _fini();\n" );
else
fprintf( outfile,
" {\n"
" extern int __stdcall FreeLibrary(void *);\n"
" unsigned int i;\n"
" _fini();\n"
" for (i = 0; i < sizeof(__wine_delay_imp_hmod)/sizeof(__wine_delay_imp_hmod[0]); i++)\n"
" if (__wine_delay_imp_hmod[i]) FreeLibrary( __wine_delay_imp_hmod[i] );\n"
" }\n" );
fprintf( outfile, " return ret;\n}\n" );
init_func = "__wine_dll_main";
}
else switch(spec->subsystem)
{
case IMAGE_SUBSYSTEM_NATIVE:
if (init_func)
fprintf( outfile, "extern int __stdcall %s( void*, void* );\n\n", init_func );
else
{
declare_weak_function( outfile, "int __stdcall", "DriverEntry", "void*, void*");
init_func = "DriverEntry";
}
fprintf( outfile,
"static int __stdcall __wine_driver_entry( void *obj, void *path )\n"
"{\n"
" int ret;\n"
" if (__wine_spec_init_state == 1)\n"
" _init( __wine_main_argc, __wine_main_argv, __wine_main_environ );\n"
" ret = %s ? %s( obj, path ) : 0;\n"
" if (__wine_spec_init_state == 1) _fini();\n"
" return ret;\n"
"}\n",
init_func, init_func );
init_func = "__wine_driver_entry";
break;
case IMAGE_SUBSYSTEM_WINDOWS_GUI:
case IMAGE_SUBSYSTEM_WINDOWS_CUI:
if (init_func)
fprintf( outfile, "extern int %s( int argc, char *argv[] );\n", init_func );
else
{
declare_weak_function( outfile, "int", "main", "int argc, char *argv[]" );
declare_weak_function( outfile, "int", "wmain", "int argc, unsigned short *argv[]" );
declare_weak_function( outfile, "int __stdcall", "WinMain", "void *,void *,char *,int" );
}
fprintf( outfile,
"\ntypedef struct {\n"
" unsigned int cb;\n"
" char *lpReserved, *lpDesktop, *lpTitle;\n"
" unsigned int dwX, dwY, dwXSize, dwYSize;\n"
" unsigned int dwXCountChars, dwYCountChars, dwFillAttribute, dwFlags;\n"
" unsigned short wShowWindow, cbReserved2;\n"
" char *lpReserved2;\n"
" void *hStdInput, *hStdOutput, *hStdError;\n"
"} STARTUPINFOA;\n"
"extern char * __stdcall GetCommandLineA(void);\n"
"extern void * __stdcall GetModuleHandleA(char *);\n"
"extern void __stdcall GetStartupInfoA(STARTUPINFOA *);\n"
"extern void __stdcall ExitProcess(unsigned int);\n"
"static void __wine_exe_main(void)\n"
"{\n"
" int ret;\n"
" if (__wine_spec_init_state == 1)\n"
" _init( __wine_main_argc, __wine_main_argv, __wine_main_environ );\n" );
if (init_func)
fprintf( outfile,
" ret = %s( __wine_main_argc, __wine_main_argv );\n", init_func );
else
fprintf( outfile,
" if (WinMain) {\n"
" STARTUPINFOA info;\n"
" char *cmdline = GetCommandLineA();\n"
" int bcount=0, in_quotes=0;\n"
" while (*cmdline) {\n"
" if ((*cmdline=='\\t' || *cmdline==' ') && !in_quotes) break;\n"
" else if (*cmdline=='\\\\') bcount++;\n"
" else if (*cmdline=='\\\"') {\n"
" if ((bcount & 1)==0) in_quotes=!in_quotes;\n"
" bcount=0;\n"
" }\n"
" else bcount=0;\n"
" cmdline++;\n"
" }\n"
" while (*cmdline=='\\t' || *cmdline==' ') cmdline++;\n"
" GetStartupInfoA( &info );\n"
" if (!(info.dwFlags & 1)) info.wShowWindow = 1;\n"
" ret = WinMain( GetModuleHandleA(0), 0, cmdline, info.wShowWindow );\n"
" }\n"
" else if (wmain) ret = wmain( __wine_main_argc, __wine_main_wargv );\n"
" else ret = main( __wine_main_argc, __wine_main_argv );\n" );
fprintf( outfile,
" if (__wine_spec_init_state == 1) _fini();\n"
" ExitProcess( ret );\n"
"}\n\n" );
init_func = "__wine_exe_main";
break;
}
/* Output the NT header */ /* Output the NT header */
@ -766,7 +564,7 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
fprintf( outfile, " { 0x%04x,\n", IMAGE_NT_OPTIONAL_HDR_MAGIC ); /* Magic */ fprintf( outfile, " { 0x%04x,\n", IMAGE_NT_OPTIONAL_HDR_MAGIC ); /* Magic */
fprintf( outfile, " 0, 0,\n" ); /* Major/MinorLinkerVersion */ fprintf( outfile, " 0, 0,\n" ); /* Major/MinorLinkerVersion */
fprintf( outfile, " 0, 0, 0,\n" ); /* SizeOfCode/Data */ fprintf( outfile, " 0, 0, 0,\n" ); /* SizeOfCode/Data */
fprintf( outfile, " %s,\n", init_func ); /* AddressOfEntryPoint */ fprintf( outfile, " %s,\n", spec->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, " %u,\n", page_size ); /* SectionAlignment */ fprintf( outfile, " %u,\n", page_size ); /* SectionAlignment */
@ -804,9 +602,8 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
"{\n" "{\n"
" extern void __wine_dll_register( const struct image_nt_headers *, const char * );\n" " extern void __wine_dll_register( const struct image_nt_headers *, const char * );\n"
" __wine_spec_init_state = 1;\n" " __wine_spec_init_state = 1;\n"
" __wine_dll_register( &nt_header, \"%s\" );\n" " __wine_dll_register( &nt_header, __wine_spec_file_name );\n"
"}\n\n", "}\n\n" );
spec->file_name );
fprintf( outfile, fprintf( outfile,
"void __wine_spec_init_ctor(void)\n" "void __wine_spec_init_ctor(void)\n"
@ -838,7 +635,7 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
void BuildDef32File( FILE *outfile, DLLSPEC *spec ) void BuildDef32File( FILE *outfile, DLLSPEC *spec )
{ {
const char *name; const char *name;
int i; int i, total;
if (spec_file_name) if (spec_file_name)
fprintf( outfile, "; File generated automatically from %s; do not edit!\n\n", fprintf( outfile, "; File generated automatically from %s; do not edit!\n\n",
@ -852,17 +649,20 @@ void BuildDef32File( FILE *outfile, DLLSPEC *spec )
/* Output the exports and relay entry points */ /* Output the exports and relay entry points */
for(i = 0; i < spec->nb_entry_points; i++) for (i = total = 0; i < spec->nb_entry_points; i++)
{ {
const ORDDEF *odp = &spec->entry_points[i]; const ORDDEF *odp = &spec->entry_points[i];
int is_data = 0; int is_data = 0;
if (!odp) continue; if (!odp) continue;
if (odp->name) name = odp->name; if (odp->name) name = odp->name;
else if (odp->type == TYPE_STUB) name = make_internal_name( odp, spec, "stub" ); else if (odp->type == TYPE_STUB) name = make_internal_name( odp, spec, "stub" );
else if (odp->export_name) name = odp->export_name; else if (odp->export_name) name = odp->export_name;
else name = make_internal_name( odp, spec, "noname_export" ); else name = make_internal_name( odp, spec, "noname_export" );
if (!(odp->flags & FLAG_PRIVATE)) total++;
fprintf(outfile, " %s", name); fprintf(outfile, " %s", name);
switch(odp->type) switch(odp->type)
@ -929,6 +729,7 @@ void BuildDef32File( FILE *outfile, DLLSPEC *spec )
#endif #endif
fprintf( outfile, "\n" ); fprintf( outfile, "\n" );
} }
if (!total) warning( "%s: Import library doesn't export anything\n", spec->file_name );
} }
@ -1011,6 +812,23 @@ void BuildPedllFile( FILE *outfile, DLLSPEC *spec )
nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0; nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
output_standard_file_header( outfile ); output_standard_file_header( outfile );
fprintf( outfile, "#include <stdarg.h>\n");
fprintf( outfile, "#include \"windef.h\"\n");
fprintf( outfile, "#include \"winbase.h\"\n");
fprintf( outfile, "#include \"wine/config.h\"\n");
fprintf( outfile, "#include \"wine/exception.h\"\n\n");
fprintf( outfile, "void __wine_spec_unimplemented_stub( const char *module, const char *function )\n");
fprintf( outfile, "{\n");
fprintf( outfile, " ULONG_PTR args[2];\n");
fprintf( outfile, "\n");
fprintf( outfile, " args[0] = (ULONG_PTR)module;\n");
fprintf( outfile, " args[1] = (ULONG_PTR)function;\n");
fprintf( outfile, " RaiseException( EXCEPTION_WINE_STUB, EH_NONCONTINUABLE, 2, args );\n");
fprintf( outfile, "}\n\n");
fprintf( outfile, "static const char __wine_spec_file_name[] = \"%s\";\n\n", spec->file_name );
if (nr_exports) if (nr_exports)
{ {
/* Output the stub functions */ /* Output the stub functions */

View file

@ -250,7 +250,6 @@ DLLSPEC *alloc_dll_spec(void)
spec = xmalloc( sizeof(*spec) ); spec = xmalloc( sizeof(*spec) );
spec->file_name = NULL; spec->file_name = NULL;
spec->dll_name = NULL; spec->dll_name = NULL;
spec->owner_name = NULL;
spec->init_func = NULL; spec->init_func = NULL;
spec->type = SPEC_WIN32; spec->type = SPEC_WIN32;
spec->base = MAX_ORDINALS; spec->base = MAX_ORDINALS;
@ -291,7 +290,6 @@ void free_dll_spec( DLLSPEC *spec )
} }
free( spec->file_name ); free( spec->file_name );
free( spec->dll_name ); free( spec->dll_name );
free( spec->owner_name );
free( spec->init_func ); free( spec->init_func );
free( spec->entry_points ); free( spec->entry_points );
free( spec->names ); free( spec->names );

View file

@ -196,6 +196,11 @@ Specify the target CPU and platform on which the generated code will
be built. The target specification is in the standard autoconf format be built. The target specification is in the standard autoconf format
as returned by config.sub. as returned by config.sub.
.TP .TP
.BI \-u,\ --undefined= symbol
Add \fIsymbol\fR to the list of undefined symbols when invoking the
linker. This makes it possible to force a specific module of a static
library to be included when resolving imports.
.TP
.B \--version .B \--version
Display the program version and exit. Display the program version and exit.
.TP .TP