mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 08:55:19 +00:00
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:
parent
89c566ad64
commit
94a3a9e377
9 changed files with 244 additions and 492 deletions
|
@ -88,7 +88,6 @@ typedef struct
|
|||
{
|
||||
char *file_name; /* file 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 */
|
||||
SPEC_TYPE type; /* type of dll (Win16/Win32) */
|
||||
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_delayed_import( 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 output_imports( FILE *outfile, DLLSPEC *spec, int *nb_delayed );
|
||||
extern void output_import_thunks( FILE *outfile, DLLSPEC *spec );
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
|
@ -34,7 +35,6 @@
|
|||
#endif
|
||||
|
||||
#include "winglue.h"
|
||||
//#include "wine/exception.h"
|
||||
#include "build.h"
|
||||
|
||||
#ifndef EXCEPTION_NONCONTINUABLE
|
||||
|
@ -56,13 +56,16 @@ struct import
|
|||
int nb_imports; /* number of imported functions */
|
||||
};
|
||||
|
||||
static char **undef_symbols; /* list of undefined symbols */
|
||||
static int nb_undef_symbols = -1;
|
||||
static int undef_size;
|
||||
struct name_table
|
||||
{
|
||||
char **names;
|
||||
unsigned int count, size;
|
||||
};
|
||||
|
||||
static char **ignore_symbols; /* list of symbols to ignore */
|
||||
static int nb_ignore_symbols;
|
||||
static int ignore_size;
|
||||
static struct name_table undef_symbols; /* list of undefined symbols */
|
||||
static struct name_table ignore_symbols; /* list of symbols to ignore */
|
||||
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 */
|
||||
|
||||
|
@ -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 total_imports = 0; /* total number of imported functions */
|
||||
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 */
|
||||
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 );
|
||||
}
|
||||
|
||||
/* locate a symbol in a (sorted) list */
|
||||
inline static const char *find_symbol( const char *name, char **table, int size )
|
||||
/* add a name to a name table */
|
||||
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;
|
||||
|
||||
if (table) {
|
||||
res = bsearch( &name, table, size, sizeof(*table), name_cmp );
|
||||
}
|
||||
|
||||
if (table->count) res = bsearch( &name, table->names, table->count, sizeof(*table->names), name_cmp );
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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 )
|
||||
{
|
||||
const char *size = func_size( name );
|
||||
|
@ -209,9 +237,9 @@ static int is_delayed_import( const char *name )
|
|||
{
|
||||
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;
|
||||
}
|
||||
|
@ -367,13 +395,13 @@ void add_delayed_import( const char *name )
|
|||
struct import *imp;
|
||||
char *fullname = get_dll_name( name, NULL );
|
||||
|
||||
delayed_imports = xrealloc( delayed_imports, (nb_delayed_imports+1) * sizeof(*delayed_imports) );
|
||||
delayed_imports[nb_delayed_imports++] = fullname;
|
||||
add_name( &delayed_imports, fullname );
|
||||
if ((imp = is_already_imported( fullname )) && !imp->delay)
|
||||
{
|
||||
imp->delay = 1;
|
||||
nb_delayed++;
|
||||
}
|
||||
free( fullname );
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
static void init_ignored_symbols(void)
|
||||
{
|
||||
int i;
|
||||
unsigned int i;
|
||||
|
||||
nb_ignore_symbols = sizeof(default_ignored_symbols)/sizeof(default_ignored_symbols[0]);
|
||||
ignore_size = nb_ignore_symbols + 32;
|
||||
ignore_symbols = xmalloc( ignore_size * sizeof(*ignore_symbols) );
|
||||
for (i = 0; i < nb_ignore_symbols; i++)
|
||||
ignore_symbols[i] = xstrdup( default_ignored_symbols[i] );
|
||||
for (i = 0; i < sizeof(default_ignored_symbols)/sizeof(default_ignored_symbols[0]); i++)
|
||||
add_name( &ignore_symbols, default_ignored_symbols[i] );
|
||||
}
|
||||
|
||||
/* add a symbol to the ignored symbol list */
|
||||
/* if the name starts with '-' the symbol is removed instead */
|
||||
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[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] );
|
||||
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--;
|
||||
}
|
||||
}
|
||||
if (!strcmp( ignore_symbols.names[i], name+1 )) remove_name( &ignore_symbols, i-- );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nb_ignore_symbols == ignore_size)
|
||||
{
|
||||
ignore_size += 32;
|
||||
ignore_symbols = xrealloc( ignore_symbols, ignore_size * sizeof(*ignore_symbols) );
|
||||
}
|
||||
ignore_symbols[nb_ignore_symbols++] = xstrdup( name );
|
||||
}
|
||||
else add_name( &ignore_symbols, name );
|
||||
}
|
||||
|
||||
/* add a symbol to the list of extra symbols that ld must resolve */
|
||||
void add_extra_ld_symbol( const char *name )
|
||||
{
|
||||
add_name( &extra_ld_symbols, name );
|
||||
}
|
||||
|
||||
/* 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++;
|
||||
}
|
||||
|
||||
/* add a symbol to the undef list */
|
||||
inline static void add_undef_symbol( const char *name )
|
||||
{
|
||||
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 )
|
||||
/* check if the spec file exports any stubs */
|
||||
static int has_stubs( const DLLSPEC *spec )
|
||||
{
|
||||
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++)
|
||||
{
|
||||
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 */
|
||||
if (!(spec->characteristics & IMAGE_FILE_DLL))
|
||||
{
|
||||
switch (spec->subsystem)
|
||||
{
|
||||
case IMAGE_SUBSYSTEM_WINDOWS_GUI:
|
||||
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 );
|
||||
/* get the default entry point for a given spec file */
|
||||
static const char *get_default_entry_point( const DLLSPEC *spec )
|
||||
{
|
||||
if (spec->characteristics & IMAGE_FILE_DLL) return "__wine_spec_dll_entry";
|
||||
if (spec->subsystem == IMAGE_SUBSYSTEM_NATIVE) return "DriverEntry";
|
||||
return "__wine_spec_exe_entry";
|
||||
}
|
||||
|
||||
/* make sure we import the dlls that contain these functions */
|
||||
if (kernel_imports) add_import_dll( "kernel32", NULL );
|
||||
if (ntdll_imports) add_import_dll( "ntdll", NULL );
|
||||
|
||||
if (count)
|
||||
{
|
||||
for (i = 0; i < count; i++) add_undef_symbol( extras[i] );
|
||||
sort_symbols( undef_symbols, nb_undef_symbols );
|
||||
}
|
||||
/* add the extra undefined symbols that will be contained in the generated spec file itself */
|
||||
static void add_extra_undef_symbols( DLLSPEC *spec )
|
||||
{
|
||||
if (!spec->init_func) spec->init_func = xstrdup( get_default_entry_point(spec) );
|
||||
add_extra_ld_symbol( spec->init_func );
|
||||
if (has_stubs( spec )) add_extra_ld_symbol( "__wine_spec_unimplemented_stub" );
|
||||
if (nb_delayed) add_extra_ld_symbol( "__wine_spec_delay_load" );
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
static const char *ldcombine_files( char **argv )
|
||||
{
|
||||
int i, len = 0;
|
||||
char *cmd;
|
||||
unsigned int i, len = 0;
|
||||
char *cmd, *p;
|
||||
int fd, err;
|
||||
|
||||
if (output_file_name && output_file_name[0])
|
||||
|
@ -587,10 +528,14 @@ static const char *ldcombine_files( char **argv )
|
|||
atexit( remove_ld_tmp_file );
|
||||
|
||||
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;
|
||||
cmd = xmalloc( len + strlen(ld_tmp_file) + 8 + strlen(ld_command) );
|
||||
sprintf( cmd, "%s -r -o %s", ld_command, ld_tmp_file );
|
||||
for (i = 0; argv[i]; i++) sprintf( cmd + strlen(cmd), " %s", argv[i] );
|
||||
cmd = p = xmalloc( len + strlen(ld_tmp_file) + 8 + strlen(ld_command) );
|
||||
p += sprintf( cmd, "%s -r -o %s", ld_command, ld_tmp_file );
|
||||
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 );
|
||||
if (err) fatal_error( "%s -r failed with status %d\n", ld_command, err );
|
||||
free( cmd );
|
||||
|
@ -598,7 +543,7 @@ static const char *ldcombine_files( char **argv )
|
|||
}
|
||||
|
||||
/* 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;
|
||||
FILE *f;
|
||||
|
@ -608,14 +553,12 @@ void read_undef_symbols( char **argv )
|
|||
|
||||
if (!argv[0]) return;
|
||||
|
||||
add_extra_undef_symbols( spec );
|
||||
|
||||
strcpy( name_prefix, asm_name("") );
|
||||
prefix_len = strlen( name_prefix );
|
||||
|
||||
undef_size = nb_undef_symbols = 0;
|
||||
|
||||
/* if we have multiple object files, link them together */
|
||||
if (argv[1]) name = ldcombine_files( argv );
|
||||
else name = argv[0];
|
||||
name = ldcombine_files( argv );
|
||||
|
||||
if (!nm_command) nm_command = xstrdup("nm");
|
||||
cmd = xmalloc( strlen(nm_command) + strlen(name) + 5 );
|
||||
|
@ -632,7 +575,7 @@ void read_undef_symbols( char **argv )
|
|||
while (*p == ' ') p++;
|
||||
if (p[0] == 'U' && p[1] == ' ' && p[2]) p += 2;
|
||||
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 );
|
||||
free( cmd );
|
||||
|
@ -640,47 +583,39 @@ void read_undef_symbols( char **argv )
|
|||
|
||||
static void remove_ignored_symbols(void)
|
||||
{
|
||||
int i;
|
||||
unsigned int i;
|
||||
|
||||
if (!ignore_symbols) init_ignored_symbols();
|
||||
sort_symbols( ignore_symbols, nb_ignore_symbols );
|
||||
for (i = 0; i < nb_undef_symbols; i++)
|
||||
if (!ignore_symbols.size) init_ignored_symbols();
|
||||
sort_names( &ignore_symbols );
|
||||
for (i = 0; i < undef_symbols.count; i++)
|
||||
{
|
||||
if (find_symbol( undef_symbols[i], ignore_symbols, nb_ignore_symbols ))
|
||||
{
|
||||
free( undef_symbols[i] );
|
||||
undef_symbols[i] = NULL;
|
||||
}
|
||||
if (find_name( undef_symbols.names[i], &ignore_symbols ))
|
||||
remove_name( &undef_symbols, i-- );
|
||||
}
|
||||
remove_symbol_holes();
|
||||
}
|
||||
|
||||
/* resolve the imports for a Win32 module */
|
||||
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();
|
||||
|
||||
for (i = 0; i < nb_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)
|
||||
{
|
||||
add_import_func( imp, odp );
|
||||
free( undef_symbols[j] );
|
||||
undef_symbols[j] = NULL;
|
||||
remove_name( &undef_symbols, j-- );
|
||||
removed++;
|
||||
}
|
||||
}
|
||||
/* remove all the holes in the undef symbols list */
|
||||
if (!remove_symbol_holes() && check_unused( imp, spec ))
|
||||
if (!removed && check_unused( imp, spec ))
|
||||
{
|
||||
/* the dll is not used, get rid of it */
|
||||
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, "static struct {\n" );
|
||||
fprintf( outfile, "struct {\n" );
|
||||
fprintf( outfile, " struct ImgDelayDescr {\n" );
|
||||
fprintf( outfile, " unsigned int grAttrs;\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* pUnloadIAT;\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, " const char *INT[%d];\n", total_delayed );
|
||||
fprintf( outfile, "} delay_imports = {\n" );
|
||||
fprintf( outfile, "} __wine_spec_delay_imports = {\n" );
|
||||
fprintf( outfile, " {\n" );
|
||||
for (i = j = 0; i < nb_imports; i++)
|
||||
{
|
||||
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 );
|
||||
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, "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;
|
||||
}
|
||||
|
||||
|
@ -1017,17 +926,17 @@ static void output_delayed_import_thunks( FILE *outfile, const DLLSPEC *spec )
|
|||
{
|
||||
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, " \"\\tcall %s\\n\"\n", asm_name("__wine_spec_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, " \"\\tcall %s\\n\"\n", asm_name("__wine_spec_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, " \"\\tjsr $26,%s\\n\"\n", asm_name("__wine_spec_delay_load") );
|
||||
fprintf( outfile, " \"\\tjmp $31,($0)\\n\"\n" );
|
||||
break;
|
||||
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));
|
||||
|
||||
/* 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 */
|
||||
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, " \"%s:\\n\"\n", asm_name(delayed_import_thunks));
|
||||
pos = nb_delayed * 32;
|
||||
pos = (nb_delayed + 1) * 32;
|
||||
for (i = 0; i < nb_imports; i++)
|
||||
{
|
||||
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];
|
||||
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 );
|
||||
|
|
|
@ -233,31 +233,32 @@ static void exit_on_signal( int sig )
|
|||
static const char usage_str[] =
|
||||
"Usage: winebuild [OPTIONS] [FILES]\n\n"
|
||||
"Options:\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 SYM Ignored for C flags compatibility\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"
|
||||
" -f FLAGS Compiler flags (only -fPIC is supported)\n"
|
||||
" -F --filename=DLLFILE Set the DLL filename (default: from input file name)\n"
|
||||
" -h --help Display this help message\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 DIR Ignored for C flags compatibility\n"
|
||||
" -k --kill-at Kill stdcall decorations in generated .def files\n"
|
||||
" -K FLAGS Compiler flags (only -KPIC is supported)\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 SYM Ignored for C flags compatibility\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"
|
||||
" -f FLAGS Compiler flags (only -fPIC is supported)\n"
|
||||
" -F, --filename=DLLFILE Set the DLL filename (default: from input file name)\n"
|
||||
" -h, --help Display this help message\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 DIR Ignored for C flags compatibility\n"
|
||||
" -k, --kill-at Kill stdcall decorations in generated .def files\n"
|
||||
" -K, FLAGS Compiler flags (only -KPIC is supported)\n"
|
||||
" --ld-cmd=LD Command to use for linking (default: ld)\n"
|
||||
" -l --library=LIB Import the specified library\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"
|
||||
" -l, --library=LIB Import the specified library\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"
|
||||
" --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"
|
||||
" -o --output=NAME Set the output file name (default: stdout)\n"
|
||||
" -r --res=RSRC.RES Load resources from RSRC.RES\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"
|
||||
" -r, --res=RSRC.RES Load resources from RSRC.RES\n"
|
||||
" --subsystem=SUBSYS Set the subsystem (one of native, windows, console)\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"
|
||||
" -w --warnings Turn on warnings\n"
|
||||
" -w, --warnings Turn on warnings\n"
|
||||
"\nMode options:\n"
|
||||
" --dll Build a .c file from a .spec or .def file\n"
|
||||
" --def Build a .def file from a .spec file\n"
|
||||
|
@ -284,7 +285,7 @@ enum long_options_values
|
|||
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[] =
|
||||
{
|
||||
|
@ -316,6 +317,7 @@ static const struct option long_options[] =
|
|||
{ "dll-name", 1, 0, 'N' },
|
||||
{ "output", 1, 0, 'o' },
|
||||
{ "res", 1, 0, 'r' },
|
||||
{ "undefined", 1, 0, 'u' },
|
||||
{ "warnings", 0, 0, 'w' },
|
||||
{ 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 );
|
||||
break;
|
||||
case 'M':
|
||||
spec->owner_name = xstrdup( optarg );
|
||||
spec->type = SPEC_WIN16;
|
||||
break;
|
||||
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[nb_res_files++] = xstrdup( optarg );
|
||||
break;
|
||||
case 'u':
|
||||
add_extra_ld_symbol( optarg );
|
||||
break;
|
||||
case 'w':
|
||||
display_warnings = 1;
|
||||
break;
|
||||
|
@ -568,7 +572,7 @@ int main(int argc, char **argv)
|
|||
fatal_error( "Win16 specs are not supported in ReactOS version of winebuild\n" );
|
||||
break;
|
||||
case SPEC_WIN32:
|
||||
read_undef_symbols( argv );
|
||||
read_undef_symbols( spec, argv );
|
||||
BuildSpec32File( output_file, spec );
|
||||
break;
|
||||
default: assert(0);
|
||||
|
@ -580,7 +584,7 @@ int main(int argc, char **argv)
|
|||
load_resources( argv, spec );
|
||||
load_import_libs( argv );
|
||||
if (spec_file_name && !parse_input_file( spec )) break;
|
||||
read_undef_symbols( argv );
|
||||
read_undef_symbols( spec, argv );
|
||||
BuildSpec32File( output_file, spec );
|
||||
break;
|
||||
case MODE_DEF:
|
||||
|
|
|
@ -520,9 +520,14 @@ static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
|
|||
if (!strcmp( odp->name, "DllRegisterServer" ) ||
|
||||
!strcmp( odp->name, "DllUnregisterServer" ) ||
|
||||
!strcmp( odp->name, "DllGetClassObject" ) ||
|
||||
!strcmp( odp->name, "DllGetVersion" ) ||
|
||||
!strcmp( odp->name, "DllInstall" ) ||
|
||||
!strcmp( odp->name, "DllCanUnloadNow" ))
|
||||
{
|
||||
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;
|
||||
|
||||
/* 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->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 );
|
||||
goto error;
|
||||
}
|
||||
if (ordinal > spec->limit) spec->limit = ordinal;
|
||||
if (ordinal < spec->base) spec->base = ordinal;
|
||||
odp->ordinal = ordinal;
|
||||
token = GetToken(1);
|
||||
}
|
||||
|
|
|
@ -82,6 +82,7 @@ struct res_tree
|
|||
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_end; /* end of resource file */
|
||||
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)
|
||||
{
|
||||
WORD ret = *(const WORD *)file_pos;
|
||||
if (byte_swapped) ret = (ret << 8) | (ret >> 8);
|
||||
file_pos += sizeof(WORD);
|
||||
if (file_pos > file_end) fatal_error( "%s is a truncated file\n", file_name );
|
||||
return ret;
|
||||
|
@ -146,6 +148,8 @@ static WORD get_word(void)
|
|||
static DWORD get_dword(void)
|
||||
{
|
||||
DWORD ret = *(const DWORD *)file_pos;
|
||||
if (byte_swapped)
|
||||
ret = ((ret << 24) | ((ret << 8) & 0x00ff0000) | ((ret >> 8) & 0x0000ff00) | (ret >> 24));
|
||||
file_pos += sizeof(DWORD);
|
||||
if (file_pos > file_end) fatal_error( "%s is a truncated file\n", file_name );
|
||||
return ret;
|
||||
|
@ -173,8 +177,12 @@ static void get_string( struct string_id *str )
|
|||
/* all values must be zero except header size */
|
||||
static int check_header(void)
|
||||
{
|
||||
DWORD 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; /* name, must be id 0 */
|
||||
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 );
|
||||
}
|
||||
|
||||
byte_swapped = 0;
|
||||
file_name = name;
|
||||
file_pos = base;
|
||||
file_end = file_pos + st.st_size;
|
||||
|
|
|
@ -362,15 +362,10 @@ static void output_stub_funcs( FILE *outfile, const DLLSPEC *spec )
|
|||
ORDDEF *odp = spec->ordinals[i];
|
||||
if (!odp || odp->type != TYPE_STUB) continue;
|
||||
fprintf( outfile, "#ifdef __GNUC__\n" );
|
||||
fprintf( outfile, "static void __wine_unimplemented( const char *func ) __attribute__((noreturn));\n" );
|
||||
fprintf( outfile, "#endif\n" );
|
||||
fprintf( outfile, "static void __wine_unimplemented( const char *func )\n{\n" );
|
||||
fprintf( outfile, " extern void __stdcall RaiseException( unsigned int, unsigned int, unsigned int, const void ** );\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 );
|
||||
fprintf( outfile, "extern void __wine_spec_unimplemented_stub( const char *module, const char *func ) __attribute__((noreturn));\n" );
|
||||
fprintf( outfile, "#else\n" );
|
||||
fprintf( outfile, "extern void __wine_spec_unimplemented_stub( const char *module, const char *func );\n" );
|
||||
fprintf( outfile, "#endif\n\n" );
|
||||
break;
|
||||
}
|
||||
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_" );
|
||||
strcat( odp->link_name, odp->name );
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
@ -413,6 +408,7 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
|
|||
/* File header */
|
||||
|
||||
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 int __wine_call_from_16_long();\n" );
|
||||
fprintf( outfile, "extern void __wine_call_from_16_regs();\n" );
|
||||
|
|
|
@ -66,30 +66,6 @@ static const char *make_internal_name( const ORDDEF *odp, DLLSPEC *spec, const c
|
|||
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
|
||||
|
@ -128,7 +104,7 @@ static int output_debug( FILE *outfile )
|
|||
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;
|
||||
int i, strings_size, total_size;
|
||||
|
||||
if (!nr_exports) return 0;
|
||||
|
||||
|
@ -145,37 +121,23 @@ static int get_exports_size( DLLSPEC *spec )
|
|||
total_size += spec->nb_names * 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 */
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* 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
|
||||
*
|
||||
|
@ -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" ); /* TimeDateStamp */
|
||||
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", nr_exports ); /* NumberOfFunctions */
|
||||
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" );
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (spec->nb_names)
|
||||
{
|
||||
/* output the function ordinals */
|
||||
|
||||
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 */
|
||||
|
||||
if (fwd_size)
|
||||
|
@ -287,8 +254,8 @@ static void output_exports( FILE *outfile, DLLSPEC *spec )
|
|||
if (odp && (odp->flags & FLAG_FORWARD))
|
||||
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 */
|
||||
|
||||
|
@ -356,29 +323,10 @@ static void output_stub_funcs( FILE *outfile, DLLSPEC *spec )
|
|||
ORDDEF *odp = &spec->entry_points[i];
|
||||
if (odp->type != TYPE_STUB) continue;
|
||||
fprintf( outfile, "#ifdef __GNUC__\n" );
|
||||
fprintf( outfile, "static void __wine_unimplemented( 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, "extern void __wine_spec_unimplemented_stub( const char *module, const char *func ) __attribute__((noreturn));\n" );
|
||||
fprintf( outfile, "#else\n" );
|
||||
fprintf( outfile, " rec.addr = 0;\n" );
|
||||
fprintf( outfile, "#endif\n" );
|
||||
fprintf( outfile, " for (;;) RtlRaiseException( &rec );\n}\n\n" );
|
||||
fprintf( outfile, "extern void __wine_spec_unimplemented_stub( const char *module, const char *func );\n" );
|
||||
fprintf( outfile, "#endif\n\n" );
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -388,11 +336,11 @@ static void output_stub_funcs( FILE *outfile, DLLSPEC *spec )
|
|||
if (odp->type != TYPE_STUB) continue;
|
||||
fprintf( outfile, "void %s(void) ", make_internal_name( odp, spec, "stub" ) );
|
||||
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)
|
||||
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
|
||||
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 nr_exports, nr_imports, nr_delayed;
|
||||
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;
|
||||
resolve_imports( spec );
|
||||
|
@ -528,15 +475,10 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
|
|||
else
|
||||
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" );
|
||||
|
||||
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_export_names( outfile, spec );
|
||||
|
||||
/* Output the DLL imports */
|
||||
|
||||
|
@ -548,152 +490,8 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
|
|||
|
||||
/* Output the entry point function */
|
||||
|
||||
fprintf( outfile, "static int __wine_spec_init_state;\n" );
|
||||
fprintf( outfile, "extern int __wine_main_argc;\n" );
|
||||
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;
|
||||
}
|
||||
fprintf( outfile, "int __wine_spec_init_state = 0;\n" );
|
||||
fprintf( outfile, "extern void %s();\n\n", spec->init_func );
|
||||
|
||||
/* 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, " 0, 0,\n" ); /* Major/MinorLinkerVersion */
|
||||
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, " __wine_spec_pe_header,\n" ); /* ImageBase */
|
||||
fprintf( outfile, " %u,\n", page_size ); /* SectionAlignment */
|
||||
|
@ -804,9 +602,8 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
|
|||
"{\n"
|
||||
" extern void __wine_dll_register( const struct image_nt_headers *, const char * );\n"
|
||||
" __wine_spec_init_state = 1;\n"
|
||||
" __wine_dll_register( &nt_header, \"%s\" );\n"
|
||||
"}\n\n",
|
||||
spec->file_name );
|
||||
" __wine_dll_register( &nt_header, __wine_spec_file_name );\n"
|
||||
"}\n\n" );
|
||||
|
||||
fprintf( outfile,
|
||||
"void __wine_spec_init_ctor(void)\n"
|
||||
|
@ -838,7 +635,7 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
|
|||
void BuildDef32File( FILE *outfile, DLLSPEC *spec )
|
||||
{
|
||||
const char *name;
|
||||
int i;
|
||||
int i, total;
|
||||
|
||||
if (spec_file_name)
|
||||
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 */
|
||||
|
||||
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];
|
||||
int is_data = 0;
|
||||
|
||||
if (!odp) continue;
|
||||
|
||||
if (odp->name) name = odp->name;
|
||||
else if (odp->type == TYPE_STUB) name = make_internal_name( odp, spec, "stub" );
|
||||
else if (odp->export_name) name = odp->export_name;
|
||||
else name = make_internal_name( odp, spec, "noname_export" );
|
||||
|
||||
if (!(odp->flags & FLAG_PRIVATE)) total++;
|
||||
|
||||
fprintf(outfile, " %s", name);
|
||||
|
||||
switch(odp->type)
|
||||
|
@ -929,6 +729,7 @@ void BuildDef32File( FILE *outfile, DLLSPEC *spec )
|
|||
#endif
|
||||
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;
|
||||
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)
|
||||
{
|
||||
/* Output the stub functions */
|
||||
|
|
|
@ -250,7 +250,6 @@ DLLSPEC *alloc_dll_spec(void)
|
|||
spec = xmalloc( sizeof(*spec) );
|
||||
spec->file_name = NULL;
|
||||
spec->dll_name = NULL;
|
||||
spec->owner_name = NULL;
|
||||
spec->init_func = NULL;
|
||||
spec->type = SPEC_WIN32;
|
||||
spec->base = MAX_ORDINALS;
|
||||
|
@ -291,7 +290,6 @@ void free_dll_spec( DLLSPEC *spec )
|
|||
}
|
||||
free( spec->file_name );
|
||||
free( spec->dll_name );
|
||||
free( spec->owner_name );
|
||||
free( spec->init_func );
|
||||
free( spec->entry_points );
|
||||
free( spec->names );
|
||||
|
|
|
@ -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
|
||||
as returned by config.sub.
|
||||
.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
|
||||
Display the program version and exit.
|
||||
.TP
|
||||
|
|
Loading…
Reference in a new issue