Sync to Wine:

Alexandre Julliard <[email protected]>
- Store all information about the current dll in a structure instead of
  using global variables to make it easier to reuse the parsing
  routines.
- Added native mode dll support (based on a patch by Marcus Meissner).
- Added support for building a dll from a .def file for cases where we
  don't want to write a full .spec.
- Renamed --spec option to --dll for consistency.
- Removed the Unicode exe modes, and instead detect automatically which
  mode to use based on the existence of main or wmain.
- Automatically detect whether the entry point is main or WinMain
  instead of depending on the subsystem type.
- Do not strip stdcall decoration in spec files.
- Print a warning when DllRegisterServer and similar functions are not
  marked private.
- Fill in the proper offsets in the resource directory instead of
  relying on the compiler to do it.
Jukka Heinonen <[email protected]>
- Remove support for generating interrupt handlers.
- DPMI programs now handle pending events.
Robert Shearman <[email protected]>
- Fix proc name reported in delay load failure.
Richard Cohen <[email protected]>
- Remove . from default library search path.
Eric Pouech <[email protected]>
- added size information about most of the generated thunks (import,
  16/32 relay...)
- marked the wine thunks by inserting specific symbols (to be managed
  by wine's dbghelp)
- removed the stabs generation:
  + mostly used by winedbg, and the previous item will replace it for
    dbghelp
  + still broken for gdb anyway
- enhanced const correctness
Pierre d'Herbemont <[email protected]>
- Detection of .size instruction.
- Detection of the assembler name prefix.
- Delayed import fix for Darwin and PowerPC Host.
- Be more accurate on Darwin stack size.
- Delay import fix on PowerPC hosts.
Marcus Meissner <[email protected]>
- Use "LD" instead of "ld" in winebuild to be able to use a different ld
  or ld options.
Dmitry Timoshkov <[email protected]>
- Add a few missing __ASM_NAME macros.

svn path=/trunk/; revision=11014
This commit is contained in:
Gé van Geldorp
2004-09-23 20:27:30 +00:00
parent 219e1cea20
commit 0a185bdb18
14 changed files with 1452 additions and 1018 deletions
+1 -1
View File
@@ -20,7 +20,7 @@ OBJECTS = \
CLEAN_FILES = *.o $(TARGET)
HOST_CFLAGS = -D__USE_W32API -D__REACTOS__ -I$(PATH_TO_TOP)/include -I$(PATH_TO_TOP)/include/wine -I$(W32API_PATH)/include
HOST_CFLAGS = -D__USE_W32API -I$(PATH_TO_TOP)/include -I$(PATH_TO_TOP)/include/wine -I$(W32API_PATH)/include
%.o: %.c
$(HOST_CC) $(HOST_CFLAGS) -c $< -o $@
+44 -41
View File
@@ -50,15 +50,6 @@ typedef enum
SPEC_WIN32
} SPEC_TYPE;
typedef enum
{
SPEC_MODE_DLL,
SPEC_MODE_GUIEXE,
SPEC_MODE_CUIEXE,
SPEC_MODE_GUIEXE_UNICODE,
SPEC_MODE_CUIEXE_UNICODE
} SPEC_MODE;
typedef struct
{
int n_values;
@@ -67,7 +58,6 @@ typedef struct
typedef struct
{
int n_args;
char arg_types[21];
} ORD_FUNCTION;
@@ -94,6 +84,31 @@ typedef struct
} u;
} ORDDEF;
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 */
int limit; /* ordinal limit */
int stack_size; /* exe stack size */
int heap_size; /* exe heap size */
int nb_entry_points; /* number of used entry points */
int alloc_entry_points; /* number of allocated entry points */
int nb_names; /* number of entry points with names */
int nb_resources; /* number of resources */
int characteristics; /* characteristics for the PE header */
int subsystem; /* subsystem id */
int subsystem_major; /* subsystem version major number */
int subsystem_minor; /* subsystem version minor number */
ORDDEF *entry_points; /* dll entry points */
ORDDEF **names; /* array of entry point names (points into entry_points) */
ORDDEF **ordinals; /* array of dll ordinals (points into entry_points) */
struct resource *resources; /* array of dll resources (format differs between Win16/Win32) */
} DLLSPEC;
/* entry point flags */
#define FLAG_NORELAY 0x01 /* don't use relay debugging for this function */
#define FLAG_NONAME 0x02 /* don't import function by name */
@@ -101,10 +116,9 @@ typedef struct
#define FLAG_RET64 0x08 /* function returns a 64-bit value */
#define FLAG_I386 0x10 /* function is i386 only */
#define FLAG_REGISTER 0x20 /* use register calling convention */
#define FLAG_INTERRUPT 0x40 /* function is an interrupt handler */
#define FLAG_PRIVATE 0x80 /* function is private (cannot be imported) */
#define FLAG_PRIVATE 0x40 /* function is private (cannot be imported) */
#define FLAG_FORWARD 0x100 /* function is a forwarded name */
#define FLAG_FORWARD 0x80 /* function is a forwarded name */
/* Offset of a structure field relative to the start of the struct */
#define STRUCTOFFSET(type,field) ((int)&((type *)0)->field)
@@ -147,60 +161,49 @@ extern FILE *open_input_file( const char *srcdir, const char *name );
extern void close_input_file( FILE *file );
extern void dump_bytes( FILE *outfile, const unsigned char *data, int len,
const char *label, int constant );
extern int remove_stdcall_decoration( char *name );
extern DLLSPEC *alloc_dll_spec(void);
extern void free_dll_spec( DLLSPEC *spec );
extern const char *make_c_identifier( const char *str );
extern int get_alignment(int alignBoundary);
extern void add_import_dll( const char *name, int delay );
extern void add_ignore_symbol( const char *name );
extern void read_undef_symbols( char **argv );
extern int resolve_imports( void );
extern int output_imports( FILE *outfile );
extern int load_res32_file( const char *name );
extern int output_resources( FILE *outfile );
extern void load_res16_file( const char *name );
extern int output_res16_data( FILE *outfile );
extern int output_res16_directory( unsigned char *buffer );
extern int resolve_imports( DLLSPEC *spec );
extern int output_imports( FILE *outfile, DLLSPEC *spec );
extern int load_res32_file( const char *name, DLLSPEC *spec );
extern void output_resources( FILE *outfile, DLLSPEC *spec );
extern void load_res16_file( const char *name, DLLSPEC *spec );
extern int output_res16_data( FILE *outfile, DLLSPEC *spec );
extern int output_res16_directory( unsigned char *buffer, DLLSPEC *spec );
extern void output_dll_init( FILE *outfile, const char *constructor, const char *destructor );
extern int parse_debug_channels( const char *srcdir, const char *filename );
extern void BuildRelays16( FILE *outfile );
extern void BuildRelays32( FILE *outfile );
extern void BuildSpec16File( FILE *outfile );
extern void BuildSpec32File( FILE *outfile );
extern void BuildDef32File( FILE *outfile );
extern void BuildSpec16File( FILE *outfile, DLLSPEC *spec );
extern void BuildSpec32File( FILE *outfile, DLLSPEC *spec );
extern void BuildDef32File( FILE *outfile, DLLSPEC *spec );
extern void BuildDebugFile( FILE *outfile, const char *srcdir, char **argv );
extern int ParseTopLevel( FILE *file );
extern int parse_spec_file( FILE *file, DLLSPEC *spec );
extern int parse_def_file( FILE *file, DLLSPEC *spec );
extern int parse_debug_channels( const char *srcdir, const char *filename );
/* global variables */
extern int current_line;
extern int nb_entry_points;
extern int nb_names;
extern int Base;
extern int Limit;
extern int DLLHeapSize;
extern int UsePIC;
extern int debugging;
extern int stack_size;
extern int nb_debug_channels;
extern int nb_lib_paths;
extern int nb_errors;
extern int display_warnings;
extern int kill_at;
extern char *owner_name;
extern char *dll_name;
extern char *dll_file_name;
extern const char *init_func;
extern char *input_file_name;
extern const char *output_file_name;
extern char **debug_channels;
extern char **lib_path;
extern ORDDEF *EntryPoints[MAX_ORDINALS];
extern ORDDEF *Ordinals[MAX_ORDINALS];
extern ORDDEF *Names[MAX_ORDINALS];
extern SPEC_MODE SpecMode;
extern SPEC_TYPE SpecType;
#endif /* __WINE_BUILD_H */
+215 -301
View File
@@ -1,8 +1,8 @@
/*
* DLL imports support
*
* Copyright 2000 Alexandre Julliard
* 2000 Eric Pouech
* Copyright 2000, 2004 Alexandre Julliard
* Copyright 2000 Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -26,32 +26,22 @@
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#if defined(WIN32)
#include <windows.h>
#else
#include <limits.h>
#endif
#include "windef.h"
#include "winbase.h"
#include "build.h"
struct func
{
char *name; /* function name */
int ordinal; /* function ordinal */
int ord_only; /* non-zero if function is imported by ordinal */
};
struct import
{
char *dll; /* dll name */
DLLSPEC *spec; /* description of the imported dll */
int delay; /* delay or not dll loading ? */
struct func *exports; /* functions exported from this dll */
ORDDEF **exports; /* functions exported from this dll */
int nb_exports; /* number of exported functions */
struct func *imports; /* functions we want to import from this dll */
ORDDEF **imports; /* functions we want to import from this dll */
int nb_imports; /* number of imported functions */
};
@@ -143,13 +133,16 @@ static const char * const ppc_reg[32] = { "0", "1", "2", "3", "4", "5", "6", "7"
/* compare function names; helper for resolve_imports */
static int name_cmp( const void *name, const void *entry )
{
return strcmp( *(char **)name, *(char **)entry );
return strcmp( *(const char* const *)name, *(const char* const *)entry );
}
/* compare function names; helper for resolve_imports */
static int func_cmp( const void *func1, const void *func2 )
{
return strcmp( ((struct func *)func1)->name, ((struct func *)func2)->name );
const ORDDEF *odp1 = *(const ORDDEF * const *)func1;
const ORDDEF *odp2 = *(const ORDDEF * const *)func2;
return strcmp( odp1->name ? odp1->name : odp1->export_name,
odp2->name ? odp2->name : odp2->export_name );
}
/* locate a symbol in a (sorted) list */
@@ -165,14 +158,15 @@ inline static const char *find_symbol( const char *name, char **table, int size
}
/* locate an export in a (sorted) export list */
inline static struct func *find_export( const char *name, struct func *table, int size )
inline static ORDDEF *find_export( const char *name, ORDDEF **table, int size )
{
struct func func, *res = NULL;
ORDDEF func, *odp, **res = NULL;
func.name = (char *)name;
func.ordinal = -1;
if (table) res = bsearch( &func, table, size, sizeof(*table), func_cmp );
return res;
odp = &func;
if (table) res = bsearch( &odp, table, size, sizeof(*table), func_cmp );
return res ? *res : NULL;
}
/* sort a symbol table */
@@ -182,16 +176,19 @@ inline static void sort_symbols( char **table, int size )
qsort( table, size, sizeof(*table), name_cmp );
}
inline static void output_function_size( FILE *outfile, const char *name )
{
#ifdef HAVE_ASM_DOT_SIZE
fprintf( outfile, " \"\\t.size " __ASM_NAME("%s") ", . - " __ASM_NAME("%s") "\\n\"\n", name, name);
#endif
}
/* free an import structure */
static void free_imports( struct import *imp )
{
int i;
for (i = 0; i < imp->nb_exports; i++) free( imp->exports[i].name );
for (i = 0; i < imp->nb_imports; i++) free( imp->imports[i].name );
free( imp->exports );
free( imp->imports );
free( imp->dll );
free_dll_spec( imp->spec );
free( imp );
}
@@ -208,7 +205,7 @@ static int is_already_imported( const char *name )
for (i = 0; i < nb_imports; i++)
{
if (!strcmp( dll_imports[i]->dll, name )) return 1;
if (!strcmp( dll_imports[i]->spec->file_name, name )) return 1;
}
return 0;
}
@@ -242,157 +239,44 @@ static char *open_library( const char *name )
{
if ((fullname = try_library_path( lib_path[i], name ))) return fullname;
}
if (!(fullname = try_library_path( ".", name )))
fatal_error( "could not open .def file for %s\n", name );
return fullname;
}
/* skip whitespace until the next token */
static char *skip_whitespace( char *p )
{
while (*p && isspace(*p)) p++;
if (!*p || *p == ';') p = NULL;
return p;
}
/* skip to the start of the next token, null terminating the current one */
static char *next_token( char *p )
{
while (*p && !isspace(*p)) p++;
if (*p) *p++ = 0;
return skip_whitespace( p );
}
/* remove the @nn suffix from stdcall names */
static char *remove_stdcall_decoration( char *buffer )
{
char *p = buffer + strlen(buffer) - 1;
while (p > buffer && isdigit(*p)) p--;
if (p > buffer && *p == '@') *p = 0;
return buffer;
fatal_error( "could not open .def file for %s\n", name );
return NULL;
}
/* read in the list of exported symbols of an import library */
static int read_import_lib( const char *name, struct import *imp )
{
FILE *f;
char buffer[1024];
char *fullname;
int size;
int i, ret;
DLLSPEC *spec = imp->spec;
imp->exports = NULL;
imp->nb_exports = size = 0;
imp->nb_exports = 0;
fullname = open_library( name );
f = open_input_file( NULL, fullname );
free( fullname );
while (fgets( buffer, sizeof(buffer), f ))
{
char *name, *flags;
int ordinal = 0, ord_only = 0;
char *p = buffer + strlen(buffer) - 1;
if (p < buffer) goto next;
if (*p == '\n') *p-- = 0;
p = buffer;
if (!(p = skip_whitespace(p))) goto next;
name = p;
p = next_token( name );
if (!strcmp( name, "LIBRARY" ))
{
if (!p)
{
error( "Expected name after LIBRARY\n" );
goto next;
}
name = p;
p = next_token( name );
if (p)
{
error( "Garbage after LIBRARY statement\n" );
goto next;
}
if (is_already_imported( name ))
{
close_input_file( f );
return 0; /* ignore this dll */
}
free( imp->dll );
imp->dll = xstrdup( name );
goto next;
}
if (!strcmp( name, "EXPORTS" )) goto next;
/* check for ordinal */
if (!p)
{
error( "Expected ordinal after function name\n" );
goto next;
}
if (*p != '@' || !isdigit(p[1]))
{
error( "Expected ordinal after function name '%s'\n", name );
goto next;
}
ordinal = strtol( p+1, &p, 10 );
if (ordinal >= MAX_ORDINALS)
{
error( "Invalid ordinal number %d\n", ordinal );
goto next;
}
/* check for optional flags */
while (p && (p = skip_whitespace(p)))
{
flags = p;
p = next_token( flags );
if (!strcmp( flags, "NONAME" ))
{
ord_only = 1;
if (!ordinal)
{
error( "Invalid ordinal number %d\n", ordinal );
goto next;
}
}
else if (!strcmp( flags, "CONSTANT" ) || !strcmp( flags, "DATA" ))
{
/* we don't support importing non-function entry points */
goto next;
}
else if (!strcmp( flags, "PRIVATE" ))
{
/* function must not be imported */
goto next;
}
else
{
error( "Garbage after ordinal declaration\n" );
goto next;
}
}
if (imp->nb_exports == size)
{
size += 128;
imp->exports = xrealloc( imp->exports, size * sizeof(*imp->exports) );
}
if ((p = strchr( name, '=' ))) *p = 0;
remove_stdcall_decoration( name );
imp->exports[imp->nb_exports].name = xstrdup( name );
imp->exports[imp->nb_exports].ordinal = ordinal;
imp->exports[imp->nb_exports].ord_only = ord_only;
imp->nb_exports++;
next:
current_line++;
}
ret = parse_def_file( f, spec );
close_input_file( f );
if (!ret) return 0;
if (is_already_imported( spec->file_name )) return 0;
imp->exports = xmalloc( spec->nb_entry_points * sizeof(*imp->exports) );
for (i = 0; i < spec->nb_entry_points; i++)
{
ORDDEF *odp = &spec->entry_points[i];
if (odp->type != TYPE_STDCALL && odp->type != TYPE_CDECL) continue;
if (odp->flags & FLAG_PRIVATE) continue;
imp->exports[imp->nb_exports++] = odp;
}
imp->exports = xrealloc( imp->exports, imp->nb_exports * sizeof(*imp->exports) );
if (imp->nb_exports)
qsort( imp->exports, imp->nb_exports, sizeof(*imp->exports), func_cmp );
return !nb_errors;
return 1;
}
/* add a dll to the list of imports */
@@ -413,11 +297,11 @@ void add_import_dll( const char *name, int delay )
}
imp = xmalloc( sizeof(*imp) );
imp->dll = fullname;
imp->delay = delay;
imp->imports = NULL;
imp->nb_imports = 0;
imp->spec = alloc_dll_spec();
imp->spec->file_name = fullname;
imp->delay = delay;
imp->imports = NULL;
imp->nb_imports = 0;
if (delay) nb_delayed++;
if (read_import_lib( name, imp ))
@@ -495,13 +379,10 @@ void add_ignore_symbol( const char *name )
}
/* add a function to the list of imports from a given dll */
static void add_import_func( struct import *imp, const struct func *func )
static void add_import_func( struct import *imp, ORDDEF *func )
{
imp->imports = xrealloc( imp->imports, (imp->nb_imports+1) * sizeof(*imp->imports) );
imp->imports[imp->nb_imports].name = xstrdup( func->name );
imp->imports[imp->nb_imports].ordinal = func->ordinal;
imp->imports[imp->nb_imports].ord_only = func->ord_only;
imp->nb_imports++;
imp->imports[imp->nb_imports++] = func;
total_imports++;
if (imp->delay) total_delayed++;
}
@@ -531,16 +412,16 @@ static int remove_symbol_holes(void)
}
/* add a symbol to the extra list, but only if needed */
static int add_extra_symbol( const char **extras, int *count, const char *name )
static int add_extra_symbol( const char **extras, int *count, const char *name, 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 < nb_entry_points; i++)
for (i = 0; i < spec->nb_entry_points; i++)
{
ORDDEF *odp = EntryPoints[i];
ORDDEF *odp = &spec->entry_points[i];
if (odp->type == TYPE_STDCALL ||
odp->type == TYPE_CDECL ||
odp->type == TYPE_VARARGS ||
@@ -556,7 +437,7 @@ static int add_extra_symbol( const char **extras, int *count, const char *name )
}
/* add the extra undefined symbols that will be contained in the generated spec file itself */
static void add_extra_undef_symbols(void)
static void add_extra_undef_symbols( const DLLSPEC *spec )
{
const char *extras[10];
int i, count = 0, nb_stubs = 0, nb_regs = 0;
@@ -564,44 +445,36 @@ static void add_extra_undef_symbols(void)
sort_symbols( undef_symbols, nb_undef_symbols );
for (i = 0; i < nb_entry_points; i++)
for (i = 0; i < spec->nb_entry_points; i++)
{
ORDDEF *odp = EntryPoints[i];
ORDDEF *odp = &spec->entry_points[i];
if (odp->type == TYPE_STUB) nb_stubs++;
if (odp->flags & FLAG_REGISTER) nb_regs++;
}
/* add symbols that will be contained in the spec file itself */
switch (SpecMode)
if (!(spec->characteristics & IMAGE_FILE_DLL))
{
case SPEC_MODE_DLL:
break;
case SPEC_MODE_GUIEXE:
kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA" );
kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA" );
kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA" );
/* fall through */
case SPEC_MODE_CUIEXE:
kernel_imports += add_extra_symbol( extras, &count, "ExitProcess" );
break;
case SPEC_MODE_GUIEXE_UNICODE:
kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA" );
kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA" );
kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA" );
/* fall through */
case SPEC_MODE_CUIEXE_UNICODE:
kernel_imports += add_extra_symbol( extras, &count, "ExitProcess" );
break;
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" );
kernel_imports += add_extra_symbol( extras, &count, "GetProcAddress" );
kernel_imports += add_extra_symbol( extras, &count, "LoadLibraryA", spec );
kernel_imports += add_extra_symbol( extras, &count, "GetProcAddress", spec );
}
if (nb_regs)
ntdll_imports += add_extra_symbol( extras, &count, "__wine_call_from_32_regs" );
ntdll_imports += add_extra_symbol( extras, &count, "__wine_call_from_32_regs", spec );
if (nb_delayed || nb_stubs)
ntdll_imports += add_extra_symbol( extras, &count, "RtlRaiseException" );
ntdll_imports += add_extra_symbol( extras, &count, "RtlRaiseException", spec );
/* make sure we import the dlls that contain these functions */
if (kernel_imports) add_import_dll( "kernel32", 0 );
@@ -615,18 +488,19 @@ static void add_extra_undef_symbols(void)
}
/* check if a given imported dll is not needed, taking forwards into account */
static int check_unused( const struct import* imp )
static int check_unused( const struct import* imp, const DLLSPEC *spec )
{
int i;
size_t len = strlen(imp->dll);
const char *p = strchr( imp->dll, '.' );
if (p && !strcasecmp( p, ".dll" )) len = p - imp->dll;
const char *file_name = imp->spec->file_name;
size_t len = strlen( file_name );
const char *p = strchr( file_name, '.' );
if (p && !strcasecmp( p, ".dll" )) len = p - file_name;
for (i = Base; i <= Limit; i++)
for (i = spec->base; i <= spec->limit; i++)
{
ORDDEF *odp = Ordinals[i];
ORDDEF *odp = spec->ordinals[i];
if (!odp || !(odp->flags & FLAG_FORWARD)) continue;
if (!strncasecmp( odp->link_name, imp->dll, len ) &&
if (!strncasecmp( odp->link_name, file_name, len ) &&
odp->link_name[len] == '.')
return 0; /* found a forward, it is used */
}
@@ -638,35 +512,26 @@ static int check_unused( const struct import* imp )
static const char *ldcombine_files( char **argv )
{
int i, len = 0;
char *cmd;
char *cmd, *ldcmd;
int fd, err;
#if defined(WIN32)
char tmppath[MAX_PATH];
char tmpfile[MAX_PATH];
#endif
#if defined(WIN32)
if (GetTempPathA(MAX_PATH, tmppath) == 0) return NULL;
if (GetTempFileNameA(tmppath, "WNB", 0, tmpfile) == 0) fatal_error( "could not generate a temp file\n" );
ld_tmp_file = xstrdup( tmpfile );
if ((fd = open( ld_tmp_file, O_RDONLY )) == -1)
#else
if (output_file_name && output_file_name[0])
if (output_file_name && output_file_name[0])
{
ld_tmp_file = xmalloc( PATH_MAX );
ld_tmp_file = xmalloc( strlen(output_file_name) + 10 );
strcpy( ld_tmp_file, output_file_name );
strcat( ld_tmp_file, ".XXXXXX.o" );
}
else ld_tmp_file = xstrdup( "/tmp/winebuild.tmp.XXXXXX.o" );
if ((fd = mkstemps( ld_tmp_file, 2 ) == -1)) fatal_error( "could not generate a temp file\n" );
#endif
else ld_tmp_file = xstrdup( "/tmp/winebuild.tmp.XXXXXX.o" );
if ((fd = mkstemps( ld_tmp_file, 2 ) == -1)) fatal_error( "could not generate a temp file\n" );
close( fd );
atexit( remove_ld_tmp_file );
ldcmd = getenv("LD");
if (!ldcmd) ldcmd = "ld";
for (i = 0; argv[i]; i++) len += strlen(argv[i]) + 1;
cmd = xmalloc( len + strlen(ld_tmp_file) + 10 );
sprintf( cmd, "ld -r -o %s", ld_tmp_file );
cmd = xmalloc( len + strlen(ld_tmp_file) + 8 + strlen(ldcmd) );
sprintf( cmd, "%s -r -o %s", ldcmd, ld_tmp_file );
for (i = 0; argv[i]; i++) sprintf( cmd + strlen(cmd), " %s", argv[i] );
err = system( cmd );
if (err) fatal_error( "ld -r failed with status %d\n", err );
@@ -677,6 +542,8 @@ static const char *ldcombine_files( char **argv )
/* read in the list of undefined symbols */
void read_undef_symbols( char **argv )
{
static const char name_prefix[] = __ASM_NAME("");
static const int prefix_len = sizeof(name_prefix) - 1;
FILE *f;
char buffer[1024];
int err;
@@ -702,6 +569,7 @@ void read_undef_symbols( char **argv )
p = buffer;
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 );
}
if ((err = pclose( f ))) warning( "nm -u %s error %d\n", name, err );
@@ -725,13 +593,13 @@ static void remove_ignored_symbols(void)
}
/* resolve the imports for a Win32 module */
int resolve_imports( void )
int resolve_imports( DLLSPEC *spec )
{
int i, j;
if (nb_undef_symbols == -1) return 0; /* no symbol file specified */
add_extra_undef_symbols();
add_extra_undef_symbols( spec );
remove_ignored_symbols();
for (i = 0; i < nb_imports; i++)
@@ -740,19 +608,19 @@ int resolve_imports( void )
for (j = 0; j < nb_undef_symbols; j++)
{
struct func *func = find_export( undef_symbols[j], imp->exports, imp->nb_exports );
if (func)
ORDDEF *odp = find_export( undef_symbols[j], imp->exports, imp->nb_exports );
if (odp)
{
add_import_func( imp, func );
add_import_func( imp, odp );
free( undef_symbols[j] );
undef_symbols[j] = NULL;
}
}
/* remove all the holes in the undef symbols list */
if (!remove_symbol_holes() && check_unused( imp ))
if (!remove_symbol_holes() && check_unused( imp, spec ))
{
/* the dll is not used, get rid of it */
warning( "%s imported but no symbols used\n", imp->dll );
warning( "%s imported but no symbols used\n", imp->spec->file_name );
remove_import_dll( i );
i--;
}
@@ -765,6 +633,7 @@ static int output_immediate_imports( FILE *outfile )
{
int i, j, pos;
int nb_imm = nb_imports - nb_delayed;
static const char import_thunks[] = "__wine_spec_import_thunks";
if (!nb_imm) goto done;
@@ -788,7 +657,7 @@ static int output_immediate_imports( FILE *outfile )
{
if (dll_imports[i]->delay) continue;
fprintf( outfile, " { 0, 0, 0, \"%s\", &imports.data[%d] },\n",
dll_imports[i]->dll, j );
dll_imports[i]->spec->file_name, j );
j += dll_imports[i]->nb_imports + 1;
}
@@ -800,18 +669,18 @@ static int output_immediate_imports( FILE *outfile )
for (i = 0; i < nb_imports; i++)
{
if (dll_imports[i]->delay) continue;
fprintf( outfile, " /* %s */\n", dll_imports[i]->dll );
fprintf( outfile, " /* %s */\n", dll_imports[i]->spec->file_name );
for (j = 0; j < dll_imports[i]->nb_imports; j++)
{
struct func *import = &dll_imports[i]->imports[j];
if (!import->ord_only)
ORDDEF *odp = dll_imports[i]->imports[j];
if (!(odp->flags & FLAG_NONAME))
{
unsigned short ord = import->ordinal;
unsigned short ord = odp->ordinal;
fprintf( outfile, " \"\\%03o\\%03o%s\",\n",
*(unsigned char *)&ord, *((unsigned char *)&ord + 1), import->name );
*(unsigned char *)&ord, *((unsigned char *)&ord + 1), odp->name );
}
else
fprintf( outfile, " (char *)%d,\n", import->ordinal );
fprintf( outfile, " (char *)%d,\n", odp->ordinal );
}
fprintf( outfile, " 0,\n" );
}
@@ -822,18 +691,21 @@ static int output_immediate_imports( FILE *outfile )
fprintf( outfile, "#ifndef __GNUC__\nstatic void __asm__dummy_import(void) {\n#endif\n\n" );
pos = 20 * (nb_imm + 1); /* offset of imports.data from start of imports */
fprintf( outfile, "asm(\".data\\n\\t.align %d\\n\"\n", get_alignment(8) );
fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\"\n", import_thunks);
for (i = 0; i < nb_imports; i++)
{
if (dll_imports[i]->delay) continue;
for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4)
{
struct func *import = &dll_imports[i]->imports[j];
fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", import->name );
fprintf( outfile, " \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", import->name );
fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\\t", import->name);
ORDDEF *odp = dll_imports[i]->imports[j];
const char *name = odp->name ? odp->name : odp->export_name;
fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", name );
fprintf( outfile, " \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", name );
fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\\t", name);
#if defined(__i386__)
if (strstr( import->name, "__wine_call_from_16" ))
if (strstr( name, "__wine_call_from_16" ))
fprintf( outfile, ".byte 0x2e\\n\\tjmp *(imports+%d)\\n\\tnop\\n", pos );
else
fprintf( outfile, "jmp *(imports+%d)\\n\\tmovl %%esi,%%esi\\n", pos );
@@ -880,19 +752,23 @@ static int output_immediate_imports( FILE *outfile )
#error You need to define import thunks for your architecture!
#endif
fprintf( outfile, "\"\n" );
output_function_size( outfile, name );
}
pos += 4;
}
fprintf( outfile, "\".text\");\n#ifndef __GNUC__\n}\n#endif\n\n" );
output_function_size( outfile, import_thunks );
fprintf( outfile, " \".text\");\n#ifndef __GNUC__\n}\n#endif\n\n" );
done:
return nb_imm;
}
/* output the delayed import table of a Win32 module */
static int output_delayed_imports( FILE *outfile )
static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
{
int i, idx, j, pos;
static const char delayed_import_loaders[] = "__wine_spec_delayed_import_loaders";
static const char delayed_import_thunks[] = "__wine_spec_delayed_import_thunks";
if (!nb_delayed) goto done;
@@ -902,8 +778,9 @@ static int output_delayed_imports( FILE *outfile )
fprintf( outfile, "static void *__wine_delay_imp_%d_hmod;\n", i);
for (j = 0; j < dll_imports[i]->nb_imports; j++)
{
fprintf( outfile, "void __wine_delay_imp_%d_%s();\n",
i, dll_imports[i]->imports[j].name );
ORDDEF *odp = dll_imports[i]->imports[j];
const char *name = odp->name ? odp->name : odp->export_name;
fprintf( outfile, "void __wine_delay_imp_%d_%s();\n", i, name );
}
}
fprintf( outfile, "\n" );
@@ -926,31 +803,33 @@ static int output_delayed_imports( FILE *outfile )
{
if (!dll_imports[i]->delay) continue;
fprintf( outfile, " { 0, \"%s\", &__wine_delay_imp_%d_hmod, &delay_imports.IAT[%d], &delay_imports.INT[%d], 0, 0, 0 },\n",
dll_imports[i]->dll, i, j, j );
dll_imports[i]->spec->file_name, i, j, j );
j += dll_imports[i]->nb_imports;
}
fprintf( outfile, " },\n {\n" );
for (i = 0; i < nb_imports; i++)
{
if (!dll_imports[i]->delay) continue;
fprintf( outfile, " /* %s */\n", dll_imports[i]->dll );
fprintf( outfile, " /* %s */\n", dll_imports[i]->spec->file_name );
for (j = 0; j < dll_imports[i]->nb_imports; j++)
{
fprintf( outfile, " &__wine_delay_imp_%d_%s,\n", i, dll_imports[i]->imports[j].name);
ORDDEF *odp = dll_imports[i]->imports[j];
const char *name = odp->name ? odp->name : odp->export_name;
fprintf( outfile, " &__wine_delay_imp_%d_%s,\n", i, name );
}
}
fprintf( outfile, " },\n {\n" );
for (i = 0; i < nb_imports; i++)
{
if (!dll_imports[i]->delay) continue;
fprintf( outfile, " /* %s */\n", dll_imports[i]->dll );
fprintf( outfile, " /* %s */\n", dll_imports[i]->spec->file_name );
for (j = 0; j < dll_imports[i]->nb_imports; j++)
{
struct func *import = &dll_imports[i]->imports[j];
if (import->ord_only)
fprintf( outfile, " (char *)%d,\n", import->ordinal );
ORDDEF *odp = dll_imports[i]->imports[j];
if (!odp->name)
fprintf( outfile, " (char *)%d,\n", odp->ordinal );
else
fprintf( outfile, " \"%s\",\n", import->name );
fprintf( outfile, " \"%s\",\n", odp->name );
}
}
fprintf( outfile, " }\n};\n\n" );
@@ -958,9 +837,9 @@ static int output_delayed_imports( FILE *outfile )
/* check if there's some stub defined. if so, exception struct
* is already defined, so don't emit it twice
*/
for (i = 0; i < nb_entry_points; i++) if (EntryPoints[i]->type == TYPE_STUB) break;
for (i = 0; i < spec->nb_entry_points; i++) if (spec->entry_points[i].type == TYPE_STUB) break;
if (i == nb_entry_points) {
if (i == spec->nb_entry_points) {
fprintf( outfile, "struct exc_record {\n" );
fprintf( outfile, " unsigned int code, flags;\n" );
fprintf( outfile, " void *rec, *addr;\n" );
@@ -993,7 +872,7 @@ static int output_delayed_imports( FILE *outfile )
fprintf( outfile, " rec.rec = 0;\n" );
fprintf( outfile, " rec.params = 2;\n" );
fprintf( outfile, " rec.info[0] = imd->szName;\n" );
fprintf( outfile, " rec.info[1] = *pINT + 2;\n" );
fprintf( outfile, " rec.info[1] = *pINT;\n" );
fprintf( outfile, "#ifdef __GNUC__\n" );
fprintf( outfile, " rec.addr = __builtin_return_address(1);\n" );
fprintf( outfile, "#else\n" );
@@ -1008,6 +887,7 @@ static int output_delayed_imports( FILE *outfile )
fprintf( outfile, "#endif\n" );
fprintf( outfile, "asm(\".align %d\\n\"\n", get_alignment(8) );
fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\"\n", delayed_import_loaders);
fprintf( outfile, " \"\\t" __ASM_FUNC("__wine_delay_load_asm") "\\n\"\n" );
fprintf( outfile, " \"" __ASM_NAME("__wine_delay_load_asm") ":\\n\"\n" );
#if defined(__i386__)
@@ -1020,25 +900,31 @@ static int output_delayed_imports( FILE *outfile )
fprintf( outfile, " \"\\tmov %%g1, %%o0\\n\"\n" );
fprintf( outfile, " \"\\tjmp %%o0\\n\\trestore\\n\"\n" );
#elif defined(__powerpc__)
# if defined(__APPLE__)
/* On darwin an extra 56 bytes must be allowed for the linkage area+param area */
# define extra_stack_storage 56
# else
# define extra_stack_storage 0
# endif
/* Save all callee saved registers into a stackframe. */
fprintf( outfile, " \"\\tstwu %s, -48(%s)\\n\"\n", ppc_reg[1], ppc_reg[1]);
fprintf( outfile, " \"\\tstw %s, 4(%s)\\n\"\n", ppc_reg[3], ppc_reg[1]);
fprintf( outfile, " \"\\tstw %s, 8(%s)\\n\"\n", ppc_reg[4], ppc_reg[1]);
fprintf( outfile, " \"\\tstw %s, 12(%s)\\n\"\n", ppc_reg[5], ppc_reg[1]);
fprintf( outfile, " \"\\tstw %s, 16(%s)\\n\"\n", ppc_reg[6], ppc_reg[1]);
fprintf( outfile, " \"\\tstw %s, 20(%s)\\n\"\n", ppc_reg[7], ppc_reg[1]);
fprintf( outfile, " \"\\tstw %s, 24(%s)\\n\"\n", ppc_reg[8], ppc_reg[1]);
fprintf( outfile, " \"\\tstw %s, 28(%s)\\n\"\n", ppc_reg[9], ppc_reg[1]);
fprintf( outfile, " \"\\tstw %s, 32(%s)\\n\"\n", ppc_reg[10], ppc_reg[1]);
fprintf( outfile, " \"\\tstw %s, 36(%s)\\n\"\n", ppc_reg[11], ppc_reg[1]);
fprintf( outfile, " \"\\tstw %s, 40(%s)\\n\"\n", ppc_reg[12], ppc_reg[1]);
fprintf( outfile, " \"\\tstwu %s, -%d(%s)\\n\"\n",ppc_reg[1], 48+extra_stack_storage, ppc_reg[1]);
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[3], 4+extra_stack_storage, ppc_reg[1]);
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[4], 8+extra_stack_storage, ppc_reg[1]);
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[5], 12+extra_stack_storage, ppc_reg[1]);
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[6], 16+extra_stack_storage, ppc_reg[1]);
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[7], 20+extra_stack_storage, ppc_reg[1]);
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[8], 24+extra_stack_storage, ppc_reg[1]);
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[9], 28+extra_stack_storage, ppc_reg[1]);
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[10],32+extra_stack_storage, ppc_reg[1]);
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[11],36+extra_stack_storage, ppc_reg[1]);
fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[12],40+extra_stack_storage, ppc_reg[1]);
/* r0 -> r3 (arg1) */
fprintf( outfile, " \"\\tmr %s, %s\\n\"\n", ppc_reg[3], ppc_reg[0]);
/* save return address */
fprintf( outfile, " \"\\tmflr %s\\n\"\n", ppc_reg[0]);
fprintf( outfile, " \"\\tstw %s, 44(%s)\\n\"\n", ppc_reg[0], 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. */
fprintf( outfile, " \"\\tbl " __ASM_NAME("__wine_delay_load") "\\n\"\n");
@@ -1047,27 +933,28 @@ static int output_delayed_imports( FILE *outfile )
fprintf( outfile, " \"\\tmtctr %s\\n\"\n", ppc_reg[3]);
/* restore all saved registers and drop stackframe. */
fprintf( outfile, " \"\\tlwz %s, 4(%s)\\n\"\n", ppc_reg[3], ppc_reg[1]);
fprintf( outfile, " \"\\tlwz %s, 8(%s)\\n\"\n", ppc_reg[4], ppc_reg[1]);
fprintf( outfile, " \"\\tlwz %s, 12(%s)\\n\"\n", ppc_reg[5], ppc_reg[1]);
fprintf( outfile, " \"\\tlwz %s, 16(%s)\\n\"\n", ppc_reg[6], ppc_reg[1]);
fprintf( outfile, " \"\\tlwz %s, 20(%s)\\n\"\n", ppc_reg[7], ppc_reg[1]);
fprintf( outfile, " \"\\tlwz %s, 24(%s)\\n\"\n", ppc_reg[8], ppc_reg[1]);
fprintf( outfile, " \"\\tlwz %s, 28(%s)\\n\"\n", ppc_reg[9], ppc_reg[1]);
fprintf( outfile, " \"\\tlwz %s, 32(%s)\\n\"\n", ppc_reg[10], ppc_reg[1]);
fprintf( outfile, " \"\\tlwz %s, 36(%s)\\n\"\n", ppc_reg[11], ppc_reg[1]);
fprintf( outfile, " \"\\tlwz %s, 40(%s)\\n\"\n", ppc_reg[12], ppc_reg[1]);
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[3], 4+extra_stack_storage, ppc_reg[1]);
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[4], 8+extra_stack_storage, ppc_reg[1]);
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[5], 12+extra_stack_storage, ppc_reg[1]);
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[6], 16+extra_stack_storage, ppc_reg[1]);
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[7], 20+extra_stack_storage, ppc_reg[1]);
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[8], 24+extra_stack_storage, ppc_reg[1]);
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[9], 28+extra_stack_storage, ppc_reg[1]);
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[10],32+extra_stack_storage, ppc_reg[1]);
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[11],36+extra_stack_storage, ppc_reg[1]);
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[12],40+extra_stack_storage, ppc_reg[1]);
/* Load return value from call into return register */
fprintf( outfile, " \"\\tlwz %s, 44(%s)\\n\"\n", ppc_reg[0], ppc_reg[1]);
fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[0], 44+extra_stack_storage, ppc_reg[1]);
fprintf( outfile, " \"\\tmtlr %s\\n\"\n", ppc_reg[0]);
fprintf( outfile, " \"\\taddi %s, %s, 48\\n\"\n", ppc_reg[1], ppc_reg[1]);
fprintf( outfile, " \"\\taddi %s, %s, %d\\n\"\n", ppc_reg[1], ppc_reg[1], 48+extra_stack_storage);
/* branch to ctr register. */
fprintf( outfile, "\"bctr\\n\"\n");
fprintf( outfile, " \"bctr\\n\"\n");
#else
#error You need to defined delayed import thunks for your architecture!
#endif
output_function_size( outfile, "__wine_delay_load_asm" );
for (i = idx = 0; i < nb_imports; i++)
{
@@ -1075,7 +962,10 @@ static int output_delayed_imports( FILE *outfile )
for (j = 0; j < dll_imports[i]->nb_imports; j++)
{
char buffer[128];
sprintf( buffer, "__wine_delay_imp_%d_%s", i, dll_imports[i]->imports[j].name );
ORDDEF *odp = dll_imports[i]->imports[j];
const char *name = odp->name ? odp->name : odp->export_name;
sprintf( buffer, "__wine_delay_imp_%d_%s", i, name );
fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", buffer );
fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\"\n", buffer );
#if defined(__i386__)
@@ -1085,31 +975,52 @@ static int output_delayed_imports( FILE *outfile )
fprintf( outfile, " \"\\tset %d, %%g1\\n\"\n", (idx << 16) | j );
fprintf( outfile, " \"\\tb,a __wine_delay_load_asm\\n\"\n" );
#elif defined(__powerpc__)
/* g0 is a function scratch register or so I understand. */
/* First load the upper half-word, and then the lower part */
fprintf( outfile, " \"\\tlis %s, %d\\n\"\n", ppc_reg[0], idx);
fprintf( outfile, " \"\\tli %s, %d\\n\"\n", ppc_reg[0], j);
#ifdef __APPLE__
/* On Darwin we can use r0 and r2 */
/* Upper part in r2 */
fprintf( outfile, " \"\\tlis %s, %d\\n\"\n", ppc_reg[2], idx);
/* Lower part + r2 -> r0, Note we can't use r0 directly */
fprintf( outfile, " \"\\taddi %s, %s, %d\\n\"\n", ppc_reg[0], ppc_reg[2], j);
fprintf( outfile, " \"\\tb " __ASM_NAME("__wine_delay_load_asm") "\\n\"\n");
#else /* __APPLE__ */
/* On linux we can't use r2 since r2 is not a scratch register (hold the TOC) */
/* Save r13 on the stack */
fprintf( outfile, " \"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
fprintf( outfile, " \"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[13], ppc_reg[1]);
/* Upper part in r13 */
fprintf( outfile, " \"\\tlis %s, %d\\n\"\n", ppc_reg[13], idx);
/* Lower part + r13 -> r0, Note we can't use r0 directly */
fprintf( outfile, " \"\\taddi %s, %s, %d\\n\"\n", ppc_reg[0], ppc_reg[13], j);
/* Restore r13 */
fprintf( outfile, " \"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[13], ppc_reg[1]);
fprintf( outfile, " \"\\taddic %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
fprintf( outfile, " \"\\tb " __ASM_NAME("__wine_delay_load_asm") "\\n\"\n");
#endif /* __APPLE__ */
#else
#error You need to defined delayed import thunks for your architecture!
#endif
output_function_size( outfile, name );
}
idx++;
}
output_function_size( outfile, delayed_import_loaders );
fprintf( outfile, "\n \".data\\n\\t.align %d\\n\"\n", get_alignment(8) );
fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\"\n", delayed_import_thunks);
pos = nb_delayed * 32;
for (i = 0; i < nb_imports; i++)
{
if (!dll_imports[i]->delay) continue;
for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4)
{
struct func *import = &dll_imports[i]->imports[j];
fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", import->name );
fprintf( outfile, " \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", import->name );
fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\\t\"", import->name);
ORDDEF *odp = dll_imports[i]->imports[j];
const char *name = odp->name ? odp->name : odp->export_name;
fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", name );
fprintf( outfile, " \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", name );
fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\\t\"", name );
#if defined(__i386__)
if (strstr( import->name, "__wine_call_from_16" ))
if (strstr( name, "__wine_call_from_16" ))
fprintf( outfile, "\".byte 0x2e\\n\\tjmp *(delay_imports+%d)\\n\\tnop\\n\"", pos );
else
fprintf( outfile, "\"jmp *(delay_imports+%d)\\n\\tmovl %%esi,%%esi\\n\"", pos );
@@ -1139,8 +1050,9 @@ static int output_delayed_imports( FILE *outfile )
fprintf( outfile, "\t\"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[8], ppc_reg[1]);
fprintf( outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
fprintf( outfile, "\t\"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[1]);
fprintf( outfile, "\t\"\\tlis %s, " ppc_high(__ASM_NAME("imports") "+ %d") "\\n\"\n", ppc_reg[9], pos);
fprintf( outfile, "\t\"\\tla %s, " ppc_low (__ASM_NAME("imports") "+ %d") "(%s)\\n\"\n", ppc_reg[8], pos, ppc_reg[9]);
fprintf( outfile, "\t\"\\tlis %s, " ppc_high(__ASM_NAME("delay_imports") "+ %d") "\\n\"\n", ppc_reg[9], pos);
fprintf( outfile, "\t\"\\tla %s, " ppc_low (__ASM_NAME("delay_imports") "+ %d") "(%s)\\n\"\n", ppc_reg[8], pos, ppc_reg[9]);
fprintf( outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[8]);
fprintf( outfile, "\t\"\\tmtctr %s\\n\"\n", ppc_reg[7]);
@@ -1155,8 +1067,10 @@ static int output_delayed_imports( FILE *outfile )
#error You need to define delayed import thunks for your architecture!
#endif
fprintf( outfile, "\n" );
output_function_size( outfile, name );
}
}
output_function_size( outfile, delayed_import_thunks );
fprintf( outfile, "\".text\");\n" );
fprintf( outfile, "#ifndef __GNUC__\n" );
fprintf( outfile, "}\n" );
@@ -1170,8 +1084,8 @@ static int output_delayed_imports( FILE *outfile )
/* output the import and delayed import tables of a Win32 module
* returns number of DLLs exported in 'immediate' mode
*/
int output_imports( FILE *outfile )
int output_imports( FILE *outfile, DLLSPEC *spec )
{
output_delayed_imports( outfile );
output_delayed_imports( outfile, spec );
return output_immediate_imports( outfile );
}
+98 -90
View File
@@ -29,27 +29,17 @@
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#ifdef HAVE_GETOPT_H
# include <getopt.h>
#endif
#include "windef.h"
#include "winbase.h"
#include "build.h"
ORDDEF *EntryPoints[MAX_ORDINALS];
ORDDEF *Ordinals[MAX_ORDINALS];
ORDDEF *Names[MAX_ORDINALS];
SPEC_MODE SpecMode = SPEC_MODE_DLL;
SPEC_TYPE SpecType = SPEC_WIN32;
int Base = MAX_ORDINALS;
int Limit = 0;
int DLLHeapSize = 0;
int UsePIC = 0;
int stack_size = 0;
int nb_entry_points = 0;
int nb_names = 0;
int nb_debug_channels = 0;
int nb_lib_paths = 0;
int nb_errors = 0;
@@ -63,27 +53,23 @@ int debugging = 1;
int debugging = 0;
#endif
char *owner_name = NULL;
char *dll_name = NULL;
char *dll_file_name = NULL;
const char *init_func = NULL;
char **debug_channels = NULL;
char **lib_path = NULL;
char *input_file_name = NULL;
const char *output_file_name = NULL;
static FILE *input_file;
static FILE *output_file;
static const char *current_src_dir;
static int nb_res_files;
static char **res_files;
static char *spec_file_name;
/* execution mode */
enum exec_mode_values
{
MODE_NONE,
MODE_SPEC,
MODE_DLL,
MODE_EXE,
MODE_DEF,
MODE_DEBUG,
@@ -94,18 +80,43 @@ enum exec_mode_values
static enum exec_mode_values exec_mode = MODE_NONE;
/* set the dll file name from the input file name */
static void set_dll_file_name( const char *name )
static void set_dll_file_name( const char *name, DLLSPEC *spec )
{
char *p;
if (dll_file_name) return;
if (spec->file_name) return;
if ((p = strrchr( name, '\\' ))) name = p + 1;
if ((p = strrchr( name, '/' ))) name = p + 1;
dll_file_name = xmalloc( strlen(name) + 5 );
strcpy( dll_file_name, name );
if ((p = strrchr( dll_file_name, '.' )) && !strcmp( p, ".spec" )) *p = 0;
if (!strchr( dll_file_name, '.' )) strcat( dll_file_name, ".dll" );
spec->file_name = xmalloc( strlen(name) + 5 );
strcpy( spec->file_name, name );
if ((p = strrchr( spec->file_name, '.' )))
{
if (!strcmp( p, ".spec" ) || !strcmp( p, ".def" )) *p = 0;
}
if (!strchr( spec->file_name, '.' )) strcat( spec->file_name, ".dll" );
}
/* set the dll subsystem */
static void set_subsystem( const char *subsystem, DLLSPEC *spec )
{
char *major, *minor, *str = xstrdup( subsystem );
if ((major = strchr( str, ':' ))) *major++ = 0;
if (!strcmp( str, "native" )) spec->subsystem = IMAGE_SUBSYSTEM_NATIVE;
else if (!strcmp( str, "windows" )) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
else if (!strcmp( str, "console" )) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
else fatal_error( "Invalid subsystem name '%s'\n", subsystem );
if (major)
{
if ((minor = strchr( major, '.' )))
{
*minor++ = 0;
spec->subsystem_minor = atoi( minor );
}
spec->subsystem_major = atoi( major );
}
free( str );
}
/* cleanup on program exit */
@@ -135,15 +146,15 @@ static const char usage_str[] =
" -K FLAGS Compiler flags (only -KPIC is supported)\n"
" -l --library=LIB Import the specified library\n"
" -L --library-path=DIR Look for imports libraries in DIR\n"
" -m --exe-mode=MODE Set the executable mode (cui|gui|cuiw|guiw)\n"
" -M --main-module=MODULE Set the name of the main module for a Win16 dll\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"
" --version Print the version and exit\n"
" -w --warnings Turn on warnings\n"
"\nMode options:\n"
" --spec=FILE.SPEC Build a .c file from a spec file\n"
" --dll=FILE Build a .c file from a .spec or .def file\n"
" --def=FILE.SPEC Build a .def file from a spec file\n"
" --exe=NAME Build a .c file for the named executable\n"
" --debug [FILES] Build a .c file with the debug channels declarations\n"
@@ -153,12 +164,13 @@ static const char usage_str[] =
enum long_options_values
{
LONG_OPT_SPEC = 1,
LONG_OPT_DLL = 1,
LONG_OPT_DEF,
LONG_OPT_EXE,
LONG_OPT_DEBUG,
LONG_OPT_RELAY16,
LONG_OPT_RELAY32,
LONG_OPT_SUBSYSTEM,
LONG_OPT_VERSION
};
@@ -166,12 +178,13 @@ static const char short_options[] = "C:D:F:H:I:K:L:M:N:d:e:f:hi:kl:m:o:r:w";
static const struct option long_options[] =
{
{ "spec", 1, 0, LONG_OPT_SPEC },
{ "dll", 1, 0, LONG_OPT_DLL },
{ "def", 1, 0, LONG_OPT_DEF },
{ "exe", 1, 0, LONG_OPT_EXE },
{ "debug", 0, 0, LONG_OPT_DEBUG },
{ "relay16", 0, 0, LONG_OPT_RELAY16 },
{ "relay32", 0, 0, LONG_OPT_RELAY32 },
{ "subsystem",1, 0, LONG_OPT_SUBSYSTEM },
{ "version", 0, 0, LONG_OPT_VERSION },
/* aliases for short options */
{ "source-dir", 1, 0, 'C' },
@@ -184,7 +197,6 @@ static const struct option long_options[] =
{ "kill-at", 0, 0, 'k' },
{ "library", 1, 0, 'l' },
{ "library-path", 1, 0, 'L' },
{ "exe-mode", 1, 0, 'm' },
{ "main-module", 1, 0, 'M' },
{ "dll-name", 1, 0, 'N' },
{ "output", 1, 0, 'o' },
@@ -206,7 +218,7 @@ static void set_exec_mode( enum exec_mode_values mode )
}
/* parse options from the argv array and remove all the recognized ones */
static char **parse_options( int argc, char **argv )
static char **parse_options( int argc, char **argv, DLLSPEC *spec )
{
char *p;
int optc;
@@ -222,14 +234,14 @@ static char **parse_options( int argc, char **argv )
/* ignored */
break;
case 'F':
dll_file_name = xstrdup( optarg );
spec->file_name = xstrdup( optarg );
break;
case 'H':
if (!isdigit(optarg[0]))
fatal_error( "Expected number argument with -H option instead of '%s'\n", optarg );
DLLHeapSize = atoi(optarg);
if (DLLHeapSize > 65535)
fatal_error( "Invalid heap size %d, maximum is 65535\n", DLLHeapSize );
spec->heap_size = atoi(optarg);
if (spec->heap_size > 65535)
fatal_error( "Invalid heap size %d, maximum is 65535\n", spec->heap_size );
break;
case 'I':
/* ignored */
@@ -242,18 +254,18 @@ static char **parse_options( int argc, char **argv )
lib_path[nb_lib_paths++] = xstrdup( optarg );
break;
case 'M':
owner_name = xstrdup( optarg );
SpecType = SPEC_WIN16;
spec->owner_name = xstrdup( optarg );
spec->type = SPEC_WIN16;
break;
case 'N':
dll_name = xstrdup( optarg );
spec->dll_name = xstrdup( optarg );
break;
case 'd':
add_import_dll( optarg, 1 );
break;
case 'e':
init_func = xstrdup( optarg );
if ((p = strchr( init_func, '@' ))) *p = 0; /* kill stdcall decoration */
spec->init_func = xstrdup( optarg );
if ((p = strchr( spec->init_func, '@' ))) *p = 0; /* kill stdcall decoration */
break;
case 'f':
if (!strcmp( optarg, "PIC") || !strcmp( optarg, "pic")) UsePIC = 1;
@@ -280,13 +292,6 @@ static char **parse_options( int argc, char **argv )
case 'l':
add_import_dll( optarg, 0 );
break;
case 'm':
if (!strcmp( optarg, "gui" )) SpecMode = SPEC_MODE_GUIEXE;
else if (!strcmp( optarg, "cui" )) SpecMode = SPEC_MODE_CUIEXE;
else if (!strcmp( optarg, "guiw" )) SpecMode = SPEC_MODE_GUIEXE_UNICODE;
else if (!strcmp( optarg, "cuiw" )) SpecMode = SPEC_MODE_CUIEXE_UNICODE;
else usage(1);
break;
case 'o':
if (unlink( optarg ) == -1 && errno != ENOENT)
fatal_error( "Unable to create output file '%s'\n", optarg );
@@ -302,24 +307,24 @@ static char **parse_options( int argc, char **argv )
case 'w':
display_warnings = 1;
break;
case LONG_OPT_SPEC:
set_exec_mode( MODE_SPEC );
input_file = open_input_file( NULL, optarg );
set_dll_file_name( optarg );
case LONG_OPT_DLL:
set_exec_mode( MODE_DLL );
spec_file_name = xstrdup( optarg );
set_dll_file_name( optarg, spec );
break;
case LONG_OPT_DEF:
set_exec_mode( MODE_DEF );
input_file = open_input_file( NULL, optarg );
set_dll_file_name( optarg );
spec_file_name = xstrdup( optarg );
set_dll_file_name( optarg, spec );
break;
case LONG_OPT_EXE:
set_exec_mode( MODE_EXE );
if ((p = strrchr( optarg, '/' ))) p++;
else p = optarg;
dll_file_name = xmalloc( strlen(p) + 5 );
strcpy( dll_file_name, p );
if (!strchr( dll_file_name, '.' )) strcat( dll_file_name, ".exe" );
if (SpecMode == SPEC_MODE_DLL) SpecMode = SPEC_MODE_GUIEXE;
spec->file_name = xmalloc( strlen(p) + 5 );
strcpy( spec->file_name, p );
if (!strchr( spec->file_name, '.' )) strcat( spec->file_name, ".exe" );
if (!spec->subsystem) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
break;
case LONG_OPT_DEBUG:
set_exec_mode( MODE_DEBUG );
@@ -330,6 +335,9 @@ static char **parse_options( int argc, char **argv )
case LONG_OPT_RELAY32:
set_exec_mode( MODE_RELAY32 );
break;
case LONG_OPT_SUBSYSTEM:
set_subsystem( optarg, spec );
break;
case LONG_OPT_VERSION:
printf( "winebuild version " PACKAGE_VERSION "\n" );
exit(0);
@@ -343,28 +351,28 @@ static char **parse_options( int argc, char **argv )
/* load all specified resource files */
static void load_resources( char *argv[] )
static void load_resources( char *argv[], DLLSPEC *spec )
{
int i;
char **ptr, **last;
switch (SpecType)
switch (spec->type)
{
case SPEC_WIN16:
for (i = 0; i < nb_res_files; i++) load_res16_file( res_files[i] );
for (i = 0; i < nb_res_files; i++) load_res16_file( res_files[i], spec );
break;
case SPEC_WIN32:
for (i = 0; i < nb_res_files; i++)
{
if (!load_res32_file( res_files[i] ))
if (!load_res32_file( res_files[i], spec ))
fatal_error( "%s is not a valid Win32 resource file\n", res_files[i] );
}
/* load any resource file found in the remaining arguments */
for (ptr = last = argv; *ptr; ptr++)
{
if (!load_res32_file( *ptr ))
if (!load_res32_file( *ptr, spec ))
*last++ = *ptr; /* not a resource file, keep it in the list */
}
*last = NULL;
@@ -372,67 +380,67 @@ static void load_resources( char *argv[] )
}
}
static int parse_input_file( DLLSPEC *spec )
{
FILE *input_file = open_input_file( NULL, spec_file_name );
char *extension = strrchr( spec_file_name, '.' );
if (extension && !strcmp( extension, ".def" ))
return parse_def_file( input_file, spec );
else
return parse_spec_file( input_file, spec );
close_input_file( input_file );
}
/*******************************************************************
* main
*/
int main(int argc, char **argv)
{
DLLSPEC *spec = alloc_dll_spec();
output_file = stdout;
argv = parse_options( argc, argv );
argv = parse_options( argc, argv, spec );
switch(exec_mode)
{
case MODE_SPEC:
load_resources( argv );
if (!ParseTopLevel( input_file )) break;
switch (SpecType)
case MODE_DLL:
spec->characteristics |= IMAGE_FILE_DLL;
load_resources( argv, spec );
if (!parse_input_file( spec )) break;
switch (spec->type)
{
case SPEC_WIN16:
#if defined(__REACTOS__)
fatal_error( "Win16 specs are not supported in ReactOS version of winebuild\n" );
#else
if (argv[0])
fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
BuildSpec16File( output_file );
#endif
break;
case SPEC_WIN32:
read_undef_symbols( argv );
BuildSpec32File( output_file );
BuildSpec32File( output_file, spec );
break;
default: assert(0);
}
break;
case MODE_EXE:
if (SpecType == SPEC_WIN16) fatal_error( "Cannot build 16-bit exe files\n" );
load_resources( argv );
if (spec->type == SPEC_WIN16) fatal_error( "Cannot build 16-bit exe files\n" );
load_resources( argv, spec );
read_undef_symbols( argv );
BuildSpec32File( output_file );
BuildSpec32File( output_file, spec );
break;
case MODE_DEF:
if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
if (SpecType == SPEC_WIN16) fatal_error( "Cannot yet build .def file for 16-bit dlls\n" );
if (!ParseTopLevel( input_file )) break;
BuildDef32File( output_file );
if (spec->type == SPEC_WIN16) fatal_error( "Cannot yet build .def file for 16-bit dlls\n" );
if (!parse_input_file( spec )) break;
BuildDef32File( output_file, spec );
break;
case MODE_DEBUG:
BuildDebugFile( output_file, current_src_dir, argv );
break;
case MODE_RELAY16:
#if defined(__REACTOS__)
fatal_error( "Win16 relays are not supported in ReactOS version of winebuild\n" );
#else
if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
BuildRelays16( output_file );
#endif
break;
case MODE_RELAY32:
#if defined(__REACTOS__)
fatal_error( "Win32 relays are not supported in ReactOS version of winebuild\n" );
#else
if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
BuildRelays32( output_file );
#endif
break;
default:
usage(1);
+386 -94
View File
@@ -3,7 +3,7 @@
*
* Copyright 1993 Robert J. Amstadt
* Copyright 1995 Martin von Loewis
* Copyright 1995, 1996, 1997 Alexandre Julliard
* Copyright 1995, 1996, 1997, 2004 Alexandre Julliard
* Copyright 1997 Eric Youngdale
* Copyright 1999 Ulrich Weigand
*
@@ -32,12 +32,8 @@
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
#include "windef.h"
#include "winbase.h"
#else
#include "winglue.h"
#endif
#include "build.h"
int current_line = 0;
@@ -47,6 +43,9 @@ static char TokenBuffer[512];
static char *ParseNext = ParseBuffer;
static FILE *input_file;
static const char *separator_chars;
static const char *comment_chars;
static const char * const TypeNames[TYPE_NBTYPES] =
{
"variable", /* TYPE_VARIABLE */
@@ -67,7 +66,6 @@ static const char * const FlagNames[] =
"ret64", /* FLAG_RET64 */
"i386", /* FLAG_I386 */
"register", /* FLAG_REGISTER */
"interrupt", /* FLAG_INTERRUPT */
"private", /* FLAG_PRIVATE */
NULL
};
@@ -80,7 +78,12 @@ static int IsNumberString(const char *s)
inline static int is_token_separator( char ch )
{
return (ch == '(' || ch == ')' || ch == '-');
return strchr( separator_chars, ch ) != NULL;
}
inline static int is_token_comment( char ch )
{
return strchr( comment_chars, ch ) != NULL;
}
/* get the next line from the input file, or return 0 if at eof */
@@ -113,7 +116,7 @@ static const char * GetToken( int allow_eol )
else break;
}
if ((*p == '\0') || (*p == '#'))
if ((*p == '\0') || is_token_comment(*p))
{
if (!allow_eol) error( "Declaration not terminated properly\n" );
return NULL;
@@ -138,12 +141,23 @@ static const char * GetToken( int allow_eol )
}
static ORDDEF *add_entry_point( DLLSPEC *spec )
{
if (spec->nb_entry_points == spec->alloc_entry_points)
{
spec->alloc_entry_points += 128;
spec->entry_points = xrealloc( spec->entry_points,
spec->alloc_entry_points * sizeof(*spec->entry_points) );
}
return &spec->entry_points[spec->nb_entry_points++];
}
/*******************************************************************
* ParseVariable
* parse_spec_variable
*
* Parse a variable definition.
* Parse a variable definition in a .spec file.
*/
static int ParseVariable( ORDDEF *odp )
static int parse_spec_variable( ORDDEF *odp, DLLSPEC *spec )
{
char *endptr;
int *value_array;
@@ -151,7 +165,7 @@ static int ParseVariable( ORDDEF *odp )
int value_array_size;
const char *token;
if (SpecType == SPEC_WIN32)
if (spec->type == SPEC_WIN32)
{
error( "'variable' not supported in Win32, use 'extern' instead\n" );
return 0;
@@ -201,16 +215,16 @@ static int ParseVariable( ORDDEF *odp )
/*******************************************************************
* ParseExportFunction
* parse_spec_export
*
* Parse a function definition.
* Parse an exported function definition in a .spec file.
*/
static int ParseExportFunction( ORDDEF *odp )
static int parse_spec_export( ORDDEF *odp, DLLSPEC *spec )
{
const char *token;
unsigned int i;
switch(SpecType)
switch(spec->type)
{
case SPEC_WIN16:
if (odp->type == TYPE_STDCALL)
@@ -225,11 +239,6 @@ static int ParseExportFunction( ORDDEF *odp )
error( "'pascal' not supported for Win32\n" );
return 0;
}
if (odp->flags & FLAG_INTERRUPT)
{
error( "'interrupt' not supported for Win32\n" );
return 0;
}
break;
default:
break;
@@ -273,7 +282,7 @@ static int ParseExportFunction( ORDDEF *odp )
return 0;
}
if (SpecType == SPEC_WIN32)
if (spec->type == SPEC_WIN32)
{
if (strcmp(token, "long") &&
strcmp(token, "ptr") &&
@@ -310,7 +319,7 @@ static int ParseExportFunction( ORDDEF *odp )
odp->link_name = xstrdup( token );
if (strchr( odp->link_name, '.' ))
{
if (SpecType == SPEC_WIN16)
if (spec->type == SPEC_WIN16)
{
error( "Forwarded functions not supported for Win16\n" );
return 0;
@@ -323,17 +332,17 @@ static int ParseExportFunction( ORDDEF *odp )
/*******************************************************************
* ParseEquate
* parse_spec_equate
*
* Parse an 'equate' definition.
* Parse an 'equate' definition in a .spec file.
*/
static int ParseEquate( ORDDEF *odp )
static int parse_spec_equate( ORDDEF *odp, DLLSPEC *spec )
{
char *endptr;
int value;
const char *token;
if (SpecType == SPEC_WIN32)
if (spec->type == SPEC_WIN32)
{
error( "'equate' not supported for Win32\n" );
return 0;
@@ -351,11 +360,11 @@ static int ParseEquate( ORDDEF *odp )
/*******************************************************************
* ParseStub
* parse_spec_stub
*
* Parse a 'stub' definition.
* Parse a 'stub' definition in a .spec file
*/
static int ParseStub( ORDDEF *odp )
static int parse_spec_stub( ORDDEF *odp, DLLSPEC *spec )
{
odp->u.func.arg_types[0] = '\0';
odp->link_name = xstrdup("");
@@ -364,15 +373,15 @@ static int ParseStub( ORDDEF *odp )
/*******************************************************************
* ParseExtern
* parse_spec_extern
*
* Parse an 'extern' definition.
* Parse an 'extern' definition in a .spec file.
*/
static int ParseExtern( ORDDEF *odp )
static int parse_spec_extern( ORDDEF *odp, DLLSPEC *spec )
{
const char *token;
if (SpecType == SPEC_WIN16)
if (spec->type == SPEC_WIN16)
{
error( "'extern' not supported for Win16, use 'variable' instead\n" );
return 0;
@@ -396,11 +405,11 @@ static int ParseExtern( ORDDEF *odp )
/*******************************************************************
* ParseFlags
* parse_spec_flags
*
* Parse the optional flags for an entry point
* Parse the optional flags for an entry point in a .spec file.
*/
static const char *ParseFlags( ORDDEF *odp )
static const char *parse_spec_flags( ORDDEF *odp )
{
unsigned int i;
const char *token;
@@ -422,32 +431,18 @@ static const char *ParseFlags( ORDDEF *odp )
return token;
}
/*******************************************************************
* fix_export_name
*
* Fix an exported function name by removing a possible @xx suffix
*/
static void fix_export_name( char *name )
{
char *p, *end = strrchr( name, '@' );
if (!end || !end[1] || end == name) return;
/* make sure all the rest is digits */
for (p = end + 1; *p; p++) if (!isdigit(*p)) return;
*end = 0;
}
/*******************************************************************
* ParseOrdinal
* parse_spec_ordinal
*
* Parse an ordinal definition.
* Parse an ordinal definition in a .spec file.
*/
static int ParseOrdinal(int ordinal)
static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
{
const char *token;
ORDDEF *odp = xmalloc( sizeof(*odp) );
ORDDEF *odp = add_entry_point( spec );
memset( odp, 0, sizeof(*odp) );
EntryPoints[nb_entry_points++] = odp;
if (!(token = GetToken(0))) goto error;
@@ -462,32 +457,31 @@ static int ParseOrdinal(int ordinal)
}
if (!(token = GetToken(0))) goto error;
if (*token == '-' && !(token = ParseFlags( odp ))) goto error;
if (*token == '-' && !(token = parse_spec_flags( odp ))) goto error;
odp->name = xstrdup( token );
fix_export_name( odp->name );
odp->lineno = current_line;
odp->ordinal = ordinal;
switch(odp->type)
{
case TYPE_VARIABLE:
if (!ParseVariable( odp )) goto error;
if (!parse_spec_variable( odp, spec )) goto error;
break;
case TYPE_PASCAL:
case TYPE_STDCALL:
case TYPE_VARARGS:
case TYPE_CDECL:
if (!ParseExportFunction( odp )) goto error;
if (!parse_spec_export( odp, spec )) goto error;
break;
case TYPE_ABS:
if (!ParseEquate( odp )) goto error;
if (!parse_spec_equate( odp, spec )) goto error;
break;
case TYPE_STUB:
if (!ParseStub( odp )) goto error;
if (!parse_spec_stub( odp, spec )) goto error;
break;
case TYPE_EXTERN:
if (!ParseExtern( odp )) goto error;
if (!parse_spec_extern( odp, spec )) goto error;
break;
default:
assert( 0 );
@@ -497,8 +491,7 @@ static int ParseOrdinal(int ordinal)
if (odp->flags & FLAG_I386)
{
/* ignore this entry point on non-Intel archs */
EntryPoints[--nb_entry_points] = NULL;
free( odp );
spec->nb_entry_points--;
return 1;
}
#endif
@@ -515,15 +508,20 @@ static int ParseOrdinal(int ordinal)
error( "Ordinal number %d too large\n", ordinal );
goto error;
}
if (ordinal > Limit) Limit = ordinal;
if (ordinal < Base) Base = ordinal;
if (ordinal > spec->limit) spec->limit = ordinal;
if (ordinal < spec->base) spec->base = ordinal;
odp->ordinal = ordinal;
if (Ordinals[ordinal])
}
if (odp->type == TYPE_STDCALL && !(odp->flags & FLAG_PRIVATE))
{
if (!strcmp( odp->name, "DllRegisterServer" ) ||
!strcmp( odp->name, "DllUnregisterServer" ) ||
!strcmp( odp->name, "DllGetClassObject" ) ||
!strcmp( odp->name, "DllCanUnloadNow" ))
{
error( "Duplicate ordinal %d\n", ordinal );
goto error;
warning( "Function %s should be marked private\n", odp->name );
}
Ordinals[ordinal] = odp;
}
if (!strcmp( odp->name, "@" ) || odp->flags & FLAG_NONAME)
@@ -533,7 +531,7 @@ static int ParseOrdinal(int ordinal)
error( "Nameless function needs an explicit ordinal number\n" );
goto error;
}
if (SpecType != SPEC_WIN32)
if (spec->type != SPEC_WIN32)
{
error( "Nameless functions not supported for Win16\n" );
goto error;
@@ -542,79 +540,135 @@ static int ParseOrdinal(int ordinal)
else odp->export_name = odp->name;
odp->name = NULL;
}
else Names[nb_names++] = odp;
return 1;
error:
EntryPoints[--nb_entry_points] = NULL;
spec->nb_entry_points--;
free( odp->name );
free( odp );
return 0;
}
static int name_compare( const void *name1, const void *name2 )
{
ORDDEF *odp1 = *(ORDDEF **)name1;
ORDDEF *odp2 = *(ORDDEF **)name2;
const ORDDEF *odp1 = *(const ORDDEF * const *)name1;
const ORDDEF *odp2 = *(const ORDDEF * const *)name2;
return strcmp( odp1->name, odp2->name );
}
/*******************************************************************
* sort_names
* assign_names
*
* Sort the name array and catch duplicates.
* Build the name array and catch duplicates.
*/
static void sort_names(void)
static void assign_names( DLLSPEC *spec )
{
int i;
int i, j;
if (!nb_names) return;
spec->nb_names = 0;
for (i = 0; i < spec->nb_entry_points; i++)
if (spec->entry_points[i].name) spec->nb_names++;
if (!spec->nb_names) return;
spec->names = xmalloc( spec->nb_names * sizeof(spec->names[0]) );
for (i = j = 0; i < spec->nb_entry_points; i++)
if (spec->entry_points[i].name) spec->names[j++] = &spec->entry_points[i];
/* sort the list of names */
qsort( Names, nb_names, sizeof(Names[0]), name_compare );
qsort( spec->names, spec->nb_names, sizeof(spec->names[0]), name_compare );
/* check for duplicate names */
for (i = 0; i < nb_names - 1; i++)
for (i = 0; i < spec->nb_names - 1; i++)
{
if (!strcmp( Names[i]->name, Names[i+1]->name ))
if (!strcmp( spec->names[i]->name, spec->names[i+1]->name ))
{
current_line = max( Names[i]->lineno, Names[i+1]->lineno );
current_line = max( spec->names[i]->lineno, spec->names[i+1]->lineno );
error( "'%s' redefined\n%s:%d: First defined here\n",
Names[i]->name, input_file_name,
min( Names[i]->lineno, Names[i+1]->lineno ) );
spec->names[i]->name, input_file_name,
min( spec->names[i]->lineno, spec->names[i+1]->lineno ) );
}
}
}
/*******************************************************************
* assign_ordinals
*
* Build the ordinal array.
*/
static void assign_ordinals( DLLSPEC *spec )
{
int i, count, ordinal;
/* start assigning from base, or from 1 if no ordinal defined yet */
if (spec->base == MAX_ORDINALS) spec->base = 1;
if (spec->limit < spec->base) spec->limit = spec->base;
count = max( spec->limit + 1, spec->base + spec->nb_entry_points );
spec->ordinals = xmalloc( count * sizeof(spec->ordinals[0]) );
memset( spec->ordinals, 0, count * sizeof(spec->ordinals[0]) );
/* fill in all explicitly specified ordinals */
for (i = 0; i < spec->nb_entry_points; i++)
{
ordinal = spec->entry_points[i].ordinal;
if (ordinal == -1) continue;
if (spec->ordinals[ordinal])
{
current_line = max( spec->entry_points[i].lineno, spec->ordinals[ordinal]->lineno );
error( "ordinal %d redefined\n%s:%d: First defined here\n",
ordinal, input_file_name,
min( spec->entry_points[i].lineno, spec->ordinals[ordinal]->lineno ) );
}
else spec->ordinals[ordinal] = &spec->entry_points[i];
}
/* now assign ordinals to the rest */
for (i = 0, ordinal = spec->base; i < spec->nb_names; i++)
{
if (spec->names[i]->ordinal != -1) continue; /* already has an ordinal */
while (spec->ordinals[ordinal]) ordinal++;
if (ordinal >= MAX_ORDINALS)
{
current_line = spec->names[i]->lineno;
fatal_error( "Too many functions defined (max %d)\n", MAX_ORDINALS );
}
spec->names[i]->ordinal = ordinal;
spec->ordinals[ordinal] = spec->names[i];
}
if (ordinal > spec->limit) spec->limit = ordinal;
}
/*******************************************************************
* ParseTopLevel
* parse_spec_file
*
* Parse a spec file.
* Parse a .spec file.
*/
int ParseTopLevel( FILE *file )
int parse_spec_file( FILE *file, DLLSPEC *spec )
{
const char *token;
input_file = file;
current_line = 0;
comment_chars = "#;";
separator_chars = "()-";
while (get_next_line())
{
if (!(token = GetToken(1))) continue;
if (strcmp(token, "@") == 0)
{
if (SpecType != SPEC_WIN32)
if (spec->type != SPEC_WIN32)
{
error( "'@' ordinals not supported for Win16\n" );
continue;
}
if (!ParseOrdinal( -1 )) continue;
if (!parse_spec_ordinal( -1, spec )) continue;
}
else if (IsNumberString(token))
{
if (!ParseOrdinal( atoi(token) )) continue;
if (!parse_spec_ordinal( atoi(token), spec )) continue;
}
else
{
@@ -625,7 +679,245 @@ int ParseTopLevel( FILE *file )
}
current_line = 0; /* no longer parsing the input file */
sort_names();
assign_names( spec );
assign_ordinals( spec );
return !nb_errors;
}
/*******************************************************************
* parse_def_library
*
* Parse a LIBRARY declaration in a .def file.
*/
static int parse_def_library( DLLSPEC *spec )
{
const char *token = GetToken(1);
if (!token) return 1;
if (strcmp( token, "BASE" ))
{
free( spec->file_name );
spec->file_name = xstrdup( token );
if (!(token = GetToken(1))) return 1;
}
if (strcmp( token, "BASE" ))
{
error( "Expected library name or BASE= declaration, got '%s'\n", token );
return 0;
}
if (!(token = GetToken(0))) return 0;
if (strcmp( token, "=" ))
{
error( "Expected '=' after BASE, got '%s'\n", token );
return 0;
}
if (!(token = GetToken(0))) return 0;
/* FIXME: do something with base address */
return 1;
}
/*******************************************************************
* parse_def_stack_heap_size
*
* Parse a STACKSIZE or HEAPSIZE declaration in a .def file.
*/
static int parse_def_stack_heap_size( int is_stack, DLLSPEC *spec )
{
const char *token = GetToken(0);
char *end;
unsigned long size;
if (!token) return 0;
size = strtoul( token, &end, 0 );
if (*end)
{
error( "Invalid number '%s'\n", token );
return 0;
}
if (is_stack) spec->stack_size = size / 1024;
else spec->heap_size = size / 1024;
if (!(token = GetToken(1))) return 1;
if (strcmp( token, "," ))
{
error( "Expected ',' after size, got '%s'\n", token );
return 0;
}
if (!(token = GetToken(0))) return 0;
/* FIXME: do something with reserve size */
return 1;
}
/*******************************************************************
* parse_def_export
*
* Parse an export declaration in a .def file.
*/
static int parse_def_export( char *name, DLLSPEC *spec )
{
int i, args;
const char *token = GetToken(1);
ORDDEF *odp = add_entry_point( spec );
memset( odp, 0, sizeof(*odp) );
odp->lineno = current_line;
odp->ordinal = -1;
odp->name = name;
args = remove_stdcall_decoration( odp->name );
if (args == -1) odp->type = TYPE_CDECL;
else
{
odp->type = TYPE_STDCALL;
args /= sizeof(int);
if (args >= sizeof(odp->u.func.arg_types))
{
error( "Too many arguments in stdcall function '%s'\n", odp->name );
return 0;
}
for (i = 0; i < args; i++) odp->u.func.arg_types[i] = 'l';
}
/* check for optional internal name */
if (token && !strcmp( token, "=" ))
{
if (!(token = GetToken(0))) goto error;
odp->link_name = xstrdup( token );
remove_stdcall_decoration( odp->link_name );
token = GetToken(1);
}
/* check for optional ordinal */
if (token && token[0] == '@')
{
int ordinal;
if (!IsNumberString( token+1 ))
{
error( "Expected number after '@', got '%s'\n", token+1 );
goto error;
}
ordinal = atoi( token+1 );
if (!ordinal)
{
error( "Ordinal 0 is not valid\n" );
goto error;
}
if (ordinal >= MAX_ORDINALS)
{
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);
}
/* check for other optional keywords */
if (token && !strcmp( token, "NONAME" ))
{
if (odp->ordinal == -1)
{
error( "NONAME requires an ordinal\n" );
goto error;
}
odp->export_name = odp->name;
odp->name = NULL;
odp->flags |= FLAG_NONAME;
token = GetToken(1);
}
if (token && !strcmp( token, "PRIVATE" ))
{
odp->flags |= FLAG_PRIVATE;
token = GetToken(1);
}
if (token && !strcmp( token, "DATA" ))
{
odp->type = TYPE_EXTERN;
token = GetToken(1);
}
if (token)
{
error( "Garbage text '%s' found at end of export declaration\n", token );
goto error;
}
return 1;
error:
spec->nb_entry_points--;
free( odp->name );
return 0;
}
/*******************************************************************
* parse_def_file
*
* Parse a .def file.
*/
int parse_def_file( FILE *file, DLLSPEC *spec )
{
const char *token;
int in_exports = 0;
input_file = file;
current_line = 0;
comment_chars = ";";
separator_chars = ",=";
while (get_next_line())
{
if (!(token = GetToken(1))) continue;
if (!strcmp( token, "LIBRARY" ) || !strcmp( token, "NAME" ))
{
if (!parse_def_library( spec )) continue;
goto end_of_line;
}
else if (!strcmp( token, "STACKSIZE" ))
{
if (!parse_def_stack_heap_size( 1, spec )) continue;
goto end_of_line;
}
else if (!strcmp( token, "HEAPSIZE" ))
{
if (!parse_def_stack_heap_size( 0, spec )) continue;
goto end_of_line;
}
else if (!strcmp( token, "EXPORTS" ))
{
in_exports = 1;
if (!(token = GetToken(1))) continue;
}
else if (!strcmp( token, "IMPORTS" ))
{
in_exports = 0;
if (!(token = GetToken(1))) continue;
}
else if (!strcmp( token, "SECTIONS" ))
{
in_exports = 0;
if (!(token = GetToken(1))) continue;
}
if (!in_exports) continue; /* ignore this line */
if (!parse_def_export( xstrdup(token), spec )) continue;
end_of_line:
if ((token = GetToken(1))) error( "Syntax error near '%s'\n", token );
}
current_line = 0; /* no longer parsing the input file */
assign_names( spec );
assign_ordinals( spec );
return !nb_errors;
}
+82 -61
View File
@@ -32,25 +32,22 @@
#include "build.h"
#if defined(__GNUC__) && !defined(__svr4__)
static const int use_stabs = 1;
#else
static const int use_stabs = 0;
#endif
#ifdef __i386__
static void function_header( FILE *outfile, const char *name )
{
fprintf( outfile, "\n\t.align %d\n", get_alignment(4) );
if (use_stabs)
fprintf( outfile, "\t.stabs \"%s:F1\",36,0,0," __ASM_NAME("%s") "\n", name, name);
fprintf( outfile, "\t" __ASM_FUNC("%s") "\n", name );
fprintf( outfile, "\t.globl " __ASM_NAME("%s") "\n", name );
fprintf( outfile, __ASM_NAME("%s") ":\n", name );
}
static void function_footer( FILE *outfile, const char *name )
{
fprintf( outfile, ".size " __ASM_NAME("%s") ", . - " __ASM_NAME("%s") "\n", name, name );
}
/*******************************************************************
* BuildCallFrom16Core
*
@@ -444,6 +441,10 @@ static void BuildCallFrom16Core( FILE *outfile, int reg_func, int thunk, int sho
/* Return to return stub which will return to caller */
fprintf( outfile, "\tlret $12\n" );
}
if (thunk) function_footer( outfile, "__wine_call_from_16_thunk" );
else if (reg_func) function_footer( outfile, "__wine_call_from_16_regs" );
else if (short_ret) function_footer( outfile, "__wine_call_from_16_word" );
else function_footer( outfile, "__wine_call_from_16_long" );
}
@@ -605,6 +606,9 @@ static void BuildCallTo16Core( FILE *outfile, int reg_func )
/* Jump to the called routine */
fprintf( outfile, "\t.byte 0x66\n" );
fprintf( outfile, "\tlret\n" );
/* Function footer */
function_footer( outfile, name );
}
@@ -648,6 +652,9 @@ static void BuildRet16Func( FILE *outfile )
fprintf( outfile, "\tlret\n" );
/* Function footer */
function_footer( outfile, "CallTo16_Ret" );
/* Declare the return address and data selector variables */
fprintf( outfile, "\n\t.align %d\n", get_alignment(4) );
@@ -756,9 +763,6 @@ static void BuildCallTo32CBClient( FILE *outfile, BOOL isEx )
/* Function header */
fprintf( outfile, "\n\t.align %d\n", get_alignment(4) );
if (use_stabs)
fprintf( outfile, ".stabs \"CALL32_%s:F1\",36,0,0," __ASM_NAME("CALL32_%s") "\n",
name, name );
fprintf( outfile, "\t.globl " __ASM_NAME("CALL32_%s") "\n", name );
fprintf( outfile, __ASM_NAME("CALL32_%s") ":\n", name );
@@ -882,6 +886,7 @@ static void BuildCallTo32CBClient( FILE *outfile, BOOL isEx )
fprintf( outfile, "\tpopl %%edi\n" );
fprintf( outfile, "\tpopl %%ebp\n" );
fprintf( outfile, "\tret\n" );
fprintf( outfile, ".size " __ASM_NAME("CALL32_%s") ", . - " __ASM_NAME("CALL32_%s") "\n", name, name );
}
static void BuildCallTo32CBClientRet( FILE *outfile, BOOL isEx )
@@ -907,6 +912,8 @@ static void BuildCallTo32CBClientRet( FILE *outfile, BOOL isEx )
}
fprintf( outfile, "\tlret\n" );
fprintf( outfile, ".size " __ASM_NAME("CALL32_%s_Ret") ", . - " __ASM_NAME("CALL32_%s_Ret") "\n", name, name );
/* Declare the return address variable */
fprintf( outfile, "\n\t.globl " __ASM_NAME("CALL32_%s_RetAddr") "\n", name );
@@ -1036,10 +1043,65 @@ static void BuildCallFrom32Regs( FILE *outfile )
fprintf( outfile, "\tpopl %%ds\n" );
fprintf( outfile, "\tiret\n" );
function_footer( outfile, "__wine_call_from_32_regs" );
function_header( outfile, "__wine_call_from_32_restore_regs" );
fprintf( outfile, "\tleal 4(%%esp),%%ecx\n" );
fprintf( outfile, "\tjmp 2b\n" );
function_footer( outfile, "__wine_call_from_32_restore_regs" );
}
/*******************************************************************
* BuildPendingEventCheck
*
* Build a function that checks whether there are any
* pending DPMI events.
*
* Stack layout:
*
* (sp+12) long eflags
* (sp+6) long cs
* (sp+2) long ip
* (sp) word fs
*
* On entry to function, fs register points to a valid TEB.
* On exit from function, stack will be popped.
*/
static void BuildPendingEventCheck( FILE *outfile )
{
/* Function header */
function_header( outfile, "DPMI_PendingEventCheck" );
/* Check for pending events. */
fprintf( outfile, "\t.byte 0x64\n\ttestl $0xffffffff,(%d)\n",
STRUCTOFFSET(TEB,vm86_pending) );
fprintf( outfile, "\tje " __ASM_NAME("DPMI_PendingEventCheck_Cleanup") "\n" );
fprintf( outfile, "\t.byte 0x64\n\ttestl $0xffffffff,(%d)\n",
STRUCTOFFSET(TEB,dpmi_vif) );
fprintf( outfile, "\tje " __ASM_NAME("DPMI_PendingEventCheck_Cleanup") "\n" );
/* Process pending events. */
fprintf( outfile, "\tsti\n" );
/* Start cleanup. Restore fs register. */
fprintf( outfile, ".globl " __ASM_NAME("DPMI_PendingEventCheck_Cleanup") "\n" );
fprintf( outfile, __ASM_NAME("DPMI_PendingEventCheck_Cleanup") ":\n" );
fprintf( outfile, "\tpopw %%fs\n" );
/* Return from function. */
fprintf( outfile, ".globl " __ASM_NAME("DPMI_PendingEventCheck_Return") "\n" );
fprintf( outfile, __ASM_NAME("DPMI_PendingEventCheck_Return") ":\n" );
fprintf( outfile, "\tiret\n" );
function_footer( outfile, "DPMI_PendingEventCheck" );
}
@@ -1050,26 +1112,12 @@ static void BuildCallFrom32Regs( FILE *outfile )
*/
void BuildRelays16( FILE *outfile )
{
char buffer[1024];
/* File header */
fprintf( outfile, "/* File generated automatically. Do not edit! */\n\n" );
fprintf( outfile, "\t.text\n" );
if (output_file_name && use_stabs)
{
getcwd(buffer, sizeof(buffer));
fprintf( outfile, "\t.file\t\"%s\"\n", output_file_name );
/*
* The stabs help the internal debugger as they are an indication that it
* is sensible to step into a thunk/trampoline.
*/
fprintf( outfile, ".stabs \"%s/\",100,0,0,Code_Start\n", buffer);
fprintf( outfile, ".stabs \"%s\",100,0,0,Code_Start\n", output_file_name );
fprintf( outfile, "Code_Start:\n\n" );
}
fprintf( outfile, __ASM_NAME("__wine_spec_thunk_text_16") ":\n\n" );
fprintf( outfile, __ASM_NAME("Call16_Start") ":\n" );
fprintf( outfile, "\t.globl " __ASM_NAME("Call16_Start") "\n" );
@@ -1101,24 +1149,11 @@ void BuildRelays16( FILE *outfile )
fprintf( outfile, __ASM_NAME("Call16_End") ":\n" );
fprintf( outfile, "\t.globl " __ASM_NAME("Call16_End") "\n" );
if (use_stabs)
{
fprintf( outfile, "\t.stabs \"\",100,0,0,.Letext\n");
fprintf( outfile, ".Letext:\n");
/* Some versions of gdb need to have the filename data for
each section, so output it again for the data section. */
if (output_file_name)
{
fprintf( outfile, ".stabs \"%s/\",100,0,0,Data_Start\n", buffer);
fprintf( outfile, ".stabs \"%s\",100,0,0,Data_Start\n", output_file_name );
fprintf( outfile, "Data_Start:\n\n" );
}
}
fprintf( outfile, "\t.size " __ASM_NAME("__wine_spec_thunk_text_16") ",. - " __ASM_NAME("__wine_spec_thunk_text_16") "\n" );
/* The whole Call16_Ret segment must lie within the .data section */
fprintf( outfile, "\n\t.data\n" );
fprintf( outfile, __ASM_NAME("__wine_spec_thunk_data_16") ":\n\n" );
fprintf( outfile, "\t.globl " __ASM_NAME("Call16_Ret_Start") "\n" );
fprintf( outfile, __ASM_NAME("Call16_Ret_Start") ":\n" );
@@ -1131,9 +1166,13 @@ void BuildRelays16( FILE *outfile )
/* CBClientThunkSLEx return stub */
BuildCallTo32CBClientRet( outfile, TRUE );
/* Pending DPMI events check stub */
BuildPendingEventCheck( outfile );
/* End of Call16_Ret segment */
fprintf( outfile, "\n\t.globl " __ASM_NAME("Call16_Ret_End") "\n" );
fprintf( outfile, __ASM_NAME("Call16_Ret_End") ":\n" );
fprintf( outfile, "\t.size " __ASM_NAME("__wine_spec_thunk_data_16") ",. - " __ASM_NAME("__wine_spec_thunk_data_16") "\n" );
}
/*******************************************************************
@@ -1147,30 +1186,12 @@ void BuildRelays32( FILE *outfile )
fprintf( outfile, "/* File generated automatically. Do not edit! */\n\n" );
fprintf( outfile, "\t.text\n" );
if (output_file_name && use_stabs)
{
char buffer[1024];
getcwd(buffer, sizeof(buffer));
fprintf( outfile, "\t.file\t\"%s\"\n", output_file_name );
/*
* The stabs help the internal debugger as they are an indication that it
* is sensible to step into a thunk/trampoline.
*/
fprintf( outfile, ".stabs \"%s/\",100,0,0,Code_Start\n", buffer);
fprintf( outfile, ".stabs \"%s\",100,0,0,Code_Start\n", output_file_name );
fprintf( outfile, "Code_Start:\n\n" );
}
fprintf( outfile, __ASM_NAME("__wine_spec_thunk_text_32") ":\n\n" );
/* 32-bit register entry point */
BuildCallFrom32Regs( outfile );
if (use_stabs)
{
fprintf( outfile, "\t.stabs \"\",100,0,0,.Letext\n");
fprintf( outfile, ".Letext:\n");
}
fprintf( outfile, "\t.size " __ASM_NAME("__wine_spec_thunk_text_32") ",. - " __ASM_NAME("__wine_spec_thunk_text_32") "\n" );
}
#else /* __i386__ */
+46 -34
View File
@@ -37,12 +37,8 @@
#include <sys/mman.h>
#endif
#ifdef WIN32
#include "windef.h"
#include "winbase.h"
#else
#include "winglue.h"
#endif
#include "build.h"
#define ALIGNMENT 2 /* alignment for resource data */
@@ -73,28 +69,29 @@ struct res_type
unsigned int nb_names; /* total number of names */
};
static struct resource *resources;
static int nb_resources;
static struct res_type *res_types;
static int nb_types; /* total number of types */
/* top level of the resource tree */
struct res_tree
{
struct res_type *types; /* types array */
unsigned int nb_types; /* total number of types */
};
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 */
inline static struct resource *add_resource(void)
inline static struct resource *add_resource( DLLSPEC *spec )
{
resources = xrealloc( resources, (nb_resources + 1) * sizeof(*resources) );
return &resources[nb_resources++];
spec->resources = xrealloc( spec->resources, (spec->nb_resources + 1) * sizeof(*spec->resources) );
return &spec->resources[spec->nb_resources++];
}
static struct res_type *add_type( const struct resource *res )
static struct res_type *add_type( struct res_tree *tree, const struct resource *res )
{
struct res_type *type;
res_types = xrealloc( res_types, (nb_types + 1) * sizeof(*res_types) );
type = &res_types[nb_types++];
tree->types = xrealloc( tree->types, (tree->nb_types + 1) * sizeof(*tree->types) );
type = &tree->types[tree->nb_types++];
type->type = &res->type;
type->res = res;
type->nb_names = 0;
@@ -155,9 +152,9 @@ static void get_string( struct string_id *str )
}
/* load the next resource from the current file */
static void load_next_resource(void)
static void load_next_resource( DLLSPEC *spec )
{
struct resource *res = add_resource();
struct resource *res = add_resource( spec );
get_string( &res->type );
get_string( &res->name );
@@ -169,7 +166,7 @@ static void load_next_resource(void)
}
/* load a Win16 .res file */
void load_res16_file( const char *name )
void load_res16_file( const char *name, DLLSPEC *spec )
{
int fd;
void *base;
@@ -190,7 +187,7 @@ void load_res16_file( const char *name )
file_name = name;
file_pos = base;
file_end = file_pos + st.st_size;
while (file_pos < file_end) load_next_resource();
while (file_pos < file_end) load_next_resource( spec );
}
/* compare two strings/ids */
@@ -218,19 +215,32 @@ static int cmp_res( const void *ptr1, const void *ptr2 )
}
/* build the 2-level (type,name) resource tree */
static void build_resource_tree(void)
static struct res_tree *build_resource_tree( DLLSPEC *spec )
{
int i;
struct res_tree *tree;
struct res_type *type = NULL;
qsort( resources, nb_resources, sizeof(*resources), cmp_res );
qsort( spec->resources, spec->nb_resources, sizeof(*spec->resources), cmp_res );
for (i = 0; i < nb_resources; i++)
tree = xmalloc( sizeof(*tree) );
tree->types = NULL;
tree->nb_types = 0;
for (i = 0; i < spec->nb_resources; i++)
{
if (!i || cmp_string( &resources[i].type, &resources[i-1].type )) /* new type */
type = add_type( &resources[i] );
if (!i || cmp_string( &spec->resources[i].type, &spec->resources[i-1].type )) /* new type */
type = add_type( tree, &spec->resources[i] );
type->nb_names++;
}
return tree;
}
/* free the resource tree */
static void free_resource_tree( struct res_tree *tree )
{
free( tree->types );
free( tree );
}
inline static void put_byte( unsigned char **buffer, unsigned char val )
@@ -258,19 +268,19 @@ static void output_string( unsigned char **buffer, const char *str )
}
/* output the resource data */
int output_res16_data( FILE *outfile )
int output_res16_data( FILE *outfile, DLLSPEC *spec )
{
const struct resource *res;
unsigned char *buffer, *p;
int i, total;
if (!nb_resources) return 0;
if (!spec->nb_resources) return 0;
for (i = total = 0, res = resources; i < nb_resources; i++, res++)
for (i = total = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
total += (res->data_size + ALIGN_MASK) & ~ALIGN_MASK;
buffer = p = xmalloc( total );
for (i = 0, res = resources; i < nb_resources; i++, res++)
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
{
memcpy( p, res->data, res->data_size );
p += res->data_size;
@@ -282,25 +292,26 @@ int output_res16_data( FILE *outfile )
}
/* output the resource definitions */
int output_res16_directory( unsigned char *buffer )
int output_res16_directory( unsigned char *buffer, DLLSPEC *spec )
{
int i, offset, res_offset = 0;
unsigned int j;
struct res_tree *tree;
const struct res_type *type;
const struct resource *res;
unsigned char *start = buffer;
build_resource_tree();
tree = build_resource_tree( spec );
offset = 4; /* alignment + terminator */
offset += nb_types * 8; /* typeinfo structures */
offset += nb_resources * 12; /* nameinfo structures */
offset += tree->nb_types * 8; /* typeinfo structures */
offset += spec->nb_resources * 12; /* nameinfo structures */
put_word( &buffer, ALIGNMENT );
/* type and name structures */
for (i = 0, type = res_types; i < nb_types; i++, type++)
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
if (type->type->str)
{
@@ -335,7 +346,7 @@ int output_res16_directory( unsigned char *buffer )
/* name strings */
for (i = 0, type = res_types; i < nb_types; i++, type++)
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
if (type->type->str) output_string( &buffer, type->type->str );
for (j = 0, res = type->res; j < type->nb_names; j++, res++)
@@ -346,5 +357,6 @@ int output_res16_directory( unsigned char *buffer )
put_byte( &buffer, 0 ); /* names terminator */
if ((buffer - start) & 1) put_byte( &buffer, 0 ); /* align on word boundary */
free_resource_tree( tree );
return buffer - start;
}
+104 -69
View File
@@ -37,12 +37,8 @@
#include <sys/mman.h>
#endif
#ifdef WIN32
#include "windef.h"
#include "winbase.h"
#else
#include "winglue.h"
#endif
#include "build.h"
/* Unicode string or integer id */
@@ -68,6 +64,7 @@ struct res_name
const struct string_id *name; /* name */
const struct resource *res; /* resource */
int nb_languages; /* number of languages */
unsigned int name_offset; /* offset of name in resource dir */
};
/* type level of the resource tree */
@@ -77,24 +74,28 @@ struct res_type
struct res_name *names; /* names array */
unsigned int nb_names; /* total number of names */
unsigned int nb_id_names; /* number of names that have a numeric id */
unsigned int name_offset; /* offset of type name in resource dir */
};
static struct resource *resources;
static int nb_resources;
static struct res_type *res_types;
static int nb_types; /* total number of types */
static int nb_id_types; /* number of types that have a numeric id */
/* top level of the resource tree */
struct res_tree
{
struct res_type *types; /* types array */
unsigned int nb_types; /* total number of types */
};
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 */
/* size of a resource directory with n entries */
#define RESDIR_SIZE(n) ((4 + 2 * (n)) * sizeof(int))
inline static struct resource *add_resource(void)
inline static struct resource *add_resource( DLLSPEC *spec )
{
resources = xrealloc( resources, (nb_resources + 1) * sizeof(*resources) );
return &resources[nb_resources++];
spec->resources = xrealloc( spec->resources, (spec->nb_resources + 1) * sizeof(spec->resources[0]) );
return &spec->resources[spec->nb_resources++];
}
static inline unsigned int strlenW( const WCHAR *str )
@@ -122,23 +123,22 @@ static struct res_name *add_name( struct res_type *type, const struct resource *
return name;
}
static struct res_type *add_type( const struct resource *res )
static struct res_type *add_type( struct res_tree *tree, const struct resource *res )
{
struct res_type *type;
res_types = xrealloc( res_types, (nb_types + 1) * sizeof(*res_types) );
type = &res_types[nb_types++];
tree->types = xrealloc( tree->types, (tree->nb_types + 1) * sizeof(*tree->types) );
type = &tree->types[tree->nb_types++];
type->type = &res->type;
type->names = NULL;
type->nb_names = 0;
type->nb_id_names = 0;
if (!type->type->str) nb_id_types++;
return type;
}
/* get the next word from the current resource file */
static WORD get_word(void)
{
WORD ret = *(WORD *)file_pos;
WORD ret = *(const WORD *)file_pos;
file_pos += sizeof(WORD);
if (file_pos > file_end) fatal_error( "%s is a truncated file\n", file_name );
return ret;
@@ -147,7 +147,7 @@ static WORD get_word(void)
/* get the next dword from the current resource file */
static DWORD get_dword(void)
{
DWORD ret = *(DWORD *)file_pos;
DWORD ret = *(const DWORD *)file_pos;
file_pos += sizeof(DWORD);
if (file_pos > file_end) fatal_error( "%s is a truncated file\n", file_name );
return ret;
@@ -156,7 +156,7 @@ static DWORD get_dword(void)
/* get a string from the current resource file */
static void get_string( struct string_id *str )
{
if (*(WCHAR *)file_pos == 0xffff)
if (*(const WCHAR *)file_pos == 0xffff)
{
get_word(); /* skip the 0xffff */
str->str = NULL;
@@ -164,7 +164,7 @@ static void get_string( struct string_id *str )
}
else
{
WCHAR *p = xmalloc( (strlenW((WCHAR*)file_pos) + 1) * sizeof(WCHAR) );
WCHAR *p = xmalloc( (strlenW((const WCHAR*)file_pos) + 1) * sizeof(WCHAR) );
str->str = p;
str->id = 0;
while ((*p++ = get_word()));
@@ -188,10 +188,10 @@ static int check_header(void)
}
/* load the next resource from the current file */
static void load_next_resource(void)
static void load_next_resource( DLLSPEC *spec )
{
DWORD hdr_size;
struct resource *res = add_resource();
struct resource *res = add_resource( spec );
res->data_size = (get_dword() + 3) & ~3;
hdr_size = get_dword();
@@ -207,12 +207,12 @@ static void load_next_resource(void)
get_dword(); /* skip version */
get_dword(); /* skip characteristics */
file_pos = (char *)res->data + res->data_size;
file_pos = (const char *)res->data + res->data_size;
if (file_pos > file_end) fatal_error( "%s is a truncated file\n", file_name );
}
/* load a Win32 .res file */
int load_res32_file( const char *name )
int load_res32_file( const char *name, DLLSPEC *spec )
{
int fd, ret;
void *base;
@@ -235,7 +235,7 @@ int load_res32_file( const char *name )
file_end = file_pos + st.st_size;
if ((ret = check_header()))
{
while (file_pos < file_end) load_next_resource();
while (file_pos < file_end) load_next_resource( spec );
}
close( fd );
return ret;
@@ -267,27 +267,43 @@ static int cmp_res( const void *ptr1, const void *ptr2 )
}
/* build the 3-level (type,name,language) resource tree */
static void build_resource_tree(void)
static struct res_tree *build_resource_tree( DLLSPEC *spec )
{
int i;
struct res_tree *tree;
struct res_type *type = NULL;
struct res_name *name = NULL;
qsort( resources, nb_resources, sizeof(*resources), cmp_res );
qsort( spec->resources, spec->nb_resources, sizeof(*spec->resources), cmp_res );
for (i = 0; i < nb_resources; i++)
tree = xmalloc( sizeof(*tree) );
tree->types = NULL;
tree->nb_types = 0;
for (i = 0; i < spec->nb_resources; i++)
{
if (!i || cmp_string( &resources[i].type, &resources[i-1].type )) /* new type */
if (!i || cmp_string( &spec->resources[i].type, &spec->resources[i-1].type )) /* new type */
{
type = add_type( &resources[i] );
name = add_name( type, &resources[i] );
type = add_type( tree, &spec->resources[i] );
name = add_name( type, &spec->resources[i] );
}
else if (cmp_string( &resources[i].name, &resources[i-1].name )) /* new name */
else if (cmp_string( &spec->resources[i].name, &spec->resources[i-1].name )) /* new name */
{
name = add_name( type, &resources[i] );
name = add_name( type, &spec->resources[i] );
}
else name->nb_languages++;
}
return tree;
}
/* free the resource tree */
static void free_resource_tree( struct res_tree *tree )
{
int i;
for (i = 0; i < tree->nb_types; i++) free( tree->types[i].names );
free( tree->types );
free( tree );
}
/* output a Unicode string */
@@ -302,21 +318,22 @@ static void output_string( FILE *outfile, const WCHAR *name )
}
/* output the resource definitions */
int output_resources( FILE *outfile )
void output_resources( FILE *outfile, DLLSPEC *spec )
{
int i, j, k;
unsigned int n;
const struct res_type *type;
const struct res_name *name;
int i, j, k, nb_id_types;
unsigned int n, offset, data_offset;
struct res_tree *tree;
struct res_type *type;
struct res_name *name;
const struct resource *res;
if (!nb_resources) return 0;
if (!spec->nb_resources) return;
build_resource_tree();
tree = build_resource_tree( spec );
/* resource data */
for (i = 0, res = resources; i < nb_resources; i++, res++)
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
{
const unsigned int *p = res->data;
int size = res->data_size / 4;
@@ -348,69 +365,86 @@ int output_resources( FILE *outfile )
/* resource directory definition */
fprintf( outfile, "#define OFFSETOF(field) ((char*)&((struct res_struct *)0)->field - (char*)((struct res_struct *) 0))\n" );
fprintf( outfile, "static struct res_struct{\n" );
fprintf( outfile, " struct res_dir type_dir;\n" );
fprintf( outfile, " struct res_dir_entry type_entries[%d];\n", nb_types );
fprintf( outfile, " struct res_dir_entry type_entries[%d];\n", tree->nb_types );
offset = RESDIR_SIZE( tree->nb_types );
for (i = 0, type = res_types; i < nb_types; i++, type++)
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
offset += RESDIR_SIZE( type->nb_names );
fprintf( outfile, " struct res_dir name_%d_dir;\n", i );
fprintf( outfile, " struct res_dir_entry name_%d_entries[%d];\n", i, type->nb_names );
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
{
offset += RESDIR_SIZE( name->nb_languages );
fprintf( outfile, " struct res_dir lang_%d_%d_dir;\n", i, n );
fprintf( outfile, " struct res_dir_entry lang_%d_%d_entries[%d];\n",
i, n, name->nb_languages );
}
}
fprintf( outfile, " struct res_data_entry data_entries[%d];\n", nb_resources );
fprintf( outfile, " struct res_data_entry data_entries[%d];\n", spec->nb_resources );
offset += spec->nb_resources * 4 * sizeof(int);
for (i = 0, type = res_types; i < nb_types; i++, type++)
for (i = nb_id_types = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
if (type->type->str)
{
type->name_offset = offset | 0x80000000;
offset += (strlenW(type->type->str)+1) * sizeof(unsigned short);
fprintf( outfile, " unsigned short type_%d_name[%d];\n",
i, strlenW(type->type->str)+1 );
}
else
{
type->name_offset = type->type->id;
nb_id_types++;
}
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
{
if (name->name->str)
{
name->name_offset = offset | 0x80000000;
offset += (strlenW(name->name->str)+1) * sizeof(unsigned short);
fprintf( outfile, " unsigned short name_%d_%d_name[%d];\n",
i, n, strlenW(name->name->str)+1 );
}
else name->name_offset = name->name->id;
}
}
/* resource directory contents */
fprintf( outfile, "} resources = {\n" );
fprintf( outfile, " { 0, 0, 0, 0, %d, %d },\n", nb_types - nb_id_types, nb_id_types );
fprintf( outfile, " { 0, 0, 0, 0, %d, %d },\n", tree->nb_types - nb_id_types, nb_id_types );
/* dump the type directory */
offset = RESDIR_SIZE( tree->nb_types );
fprintf( outfile, " {\n" );
for (i = 0, type = res_types; i < nb_types; i++, type++)
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
if (!type->type->str)
fprintf( outfile, " { 0x%04x, OFFSETOF(name_%d_dir) | 0x80000000 },\n",
type->type->id, i );
else
fprintf( outfile, " { OFFSETOF(type_%d_name) | 0x80000000, OFFSETOF(name_%d_dir) | 0x80000000 },\n",
i, i );
fprintf( outfile, " { 0x%08x, 0x%08x },\n", type->name_offset, offset | 0x80000000 );
offset += RESDIR_SIZE( type->nb_names );
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
offset += RESDIR_SIZE( name->nb_languages );
}
fprintf( outfile, " },\n" );
data_offset = offset;
offset = RESDIR_SIZE( tree->nb_types );
/* dump the names and languages directories */
for (i = 0, type = res_types; i < nb_types; i++, type++)
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
fprintf( outfile, " { 0, 0, 0, 0, %d, %d }, /* name_%d_dir */\n {\n",
type->nb_names - type->nb_id_names, type->nb_id_names, i );
offset += RESDIR_SIZE( type->nb_names );
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
{
if (!name->name->str)
fprintf( outfile, " { 0x%04x, OFFSETOF(lang_%d_%d_dir) | 0x80000000 },\n",
name->name->id, i, n );
else
fprintf( outfile, " { OFFSETOF(name_%d_%d_name) | 0x80000000, OFFSETOF(lang_%d_%d_dir) | 0x80000000 },\n",
i, n, i, n );
fprintf( outfile, " { 0x%08x, 0x%08x },\n", name->name_offset, offset | 0x80000000 );
offset += RESDIR_SIZE( name->nb_languages );
}
fprintf( outfile, " },\n" );
@@ -420,8 +454,8 @@ int output_resources( FILE *outfile )
name->nb_languages, i, n );
for (k = 0, res = name->res; k < name->nb_languages; k++, res++)
{
fprintf( outfile, " { 0x%04x, OFFSETOF(data_entries[%d]) },\n",
res->lang, res - resources );
fprintf( outfile, " { 0x%04x, 0x%08x },\n",
res->lang, data_offset + (res - spec->resources) * 4 * sizeof(int) );
}
fprintf( outfile, " },\n" );
}
@@ -429,13 +463,14 @@ int output_resources( FILE *outfile )
/* dump the resource data entries */
fprintf( outfile, " {\n" );
for (i = 0, res = resources; i < nb_resources; i++, res++)
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
{
fprintf( outfile, " { res_%d, sizeof(res_%d), 0, 0 },\n", i, i );
fprintf( outfile, " { res_%d, sizeof(res_%d), 0, 0 }, /* %08x */\n", i, i,
data_offset + i * 4 * sizeof(int) );
}
/* dump the name strings */
for (i = 0, type = res_types; i < nb_types; i++, type++)
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
if (type->type->str)
{
@@ -451,6 +486,6 @@ int output_resources( FILE *outfile )
}
}
}
fprintf( outfile, " }\n};\n#undef OFFSETOF\n\n" );
return nb_resources;
fprintf( outfile, " }\n};\n\n" );
free_resource_tree( tree );
}
+43 -53
View File
@@ -111,7 +111,7 @@ static int StoreVariableCode( unsigned char *buffer, int size, ORDDEF *odp )
* as a byte stream into the assembly code.
*/
static int BuildModule16( FILE *outfile, int max_code_offset,
int max_data_offset )
int max_data_offset, DLLSPEC *spec )
{
int i;
char *buffer;
@@ -142,7 +142,7 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
pModule->next = 0;
pModule->flags = NE_FFLAGS_SINGLEDATA | NE_FFLAGS_BUILTIN | NE_FFLAGS_LIBMODULE;
pModule->dgroup = 2;
pModule->heap_size = DLLHeapSize;
pModule->heap_size = spec->heap_size;
pModule->stack_size = 0;
pModule->ip = 0;
pModule->cs = 0;
@@ -172,8 +172,8 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
pModule->fileinfo = (int)pFileInfo - (int)pModule;
memset( pFileInfo, 0, sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName) );
pFileInfo->cBytes = sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName)
+ strlen(dll_file_name);
strcpy( pFileInfo->szPathName, dll_file_name );
+ strlen(spec->file_name);
strcpy( pFileInfo->szPathName, spec->file_name );
pstr = (char *)pFileInfo + pFileInfo->cBytes + 1;
/* Segment table */
@@ -201,7 +201,7 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
pstr = (char *)pSegment;
pstr = (char *)(((long)pstr + 3) & ~3);
pModule->res_table = (int)pstr - (int)pModule;
pstr += output_res16_directory( pstr );
pstr += output_res16_directory( pstr, spec );
/* Imported names table */
@@ -215,16 +215,16 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
pstr = (char *)(((long)pstr + 3) & ~3);
pModule->name_table = (int)pstr - (int)pModule;
/* First entry is module name */
*pstr = strlen( dll_name );
strcpy( pstr + 1, dll_name );
*pstr = strlen( spec->dll_name );
strcpy( pstr + 1, spec->dll_name );
strupper( pstr + 1 );
pstr += *pstr + 1;
*pstr++ = 0;
*pstr++ = 0;
/* Store all ordinals */
for (i = 1; i <= Limit; i++)
for (i = 1; i <= spec->limit; i++)
{
ORDDEF *odp = Ordinals[i];
ORDDEF *odp = spec->ordinals[i];
WORD ord = i;
if (!odp || !odp->name[0]) continue;
*pstr = strlen( odp->name );
@@ -240,10 +240,10 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
pstr = (char *)(((long)pstr + 3) & ~3);
pModule->entry_table = (int)pstr - (int)pModule;
for (i = 1; i <= Limit; i++)
for (i = 1; i <= spec->limit; i++)
{
int selector = 0;
ORDDEF *odp = Ordinals[i];
ORDDEF *odp = spec->ordinals[i];
if (!odp) continue;
switch (odp->type)
@@ -317,8 +317,6 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
* extern LONG WINAPI PREFIX_CallFrom16_C_long_xxx( FARPROC func, LPBYTE args );
* extern void WINAPI PREFIX_CallFrom16_C_regs_xxx( FARPROC func, LPBYTE args,
* CONTEXT86 *context );
* extern void WINAPI PREFIX_CallFrom16_C_intr_xxx( FARPROC func, LPBYTE args,
* CONTEXT86 *context );
*
* where 'C' is the calling convention ('p' for pascal or 'c' for cdecl),
* and each 'x' is an argument ('w'=word, 's'=signed word, 'l'=long,
@@ -333,10 +331,6 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
* For register functions, the arguments (if present) are converted just
* the same as for normal functions, but in addition the CONTEXT86 pointer
* filled with the current register values is passed to the 32-bit routine.
* (An 'intr' interrupt handler routine is treated exactly like a register
* routine, except that upon return, the flags word pushed onto the stack
* by the interrupt is removed by the 16-bit call stub.)
*
*/
static void BuildCallFrom16Func( FILE *outfile, const char *profile, const char *prefix )
{
@@ -360,7 +354,6 @@ static void BuildCallFrom16Func( FILE *outfile, const char *profile, const char
if (!strncmp( "word_", profile + 2, 5 )) short_ret = 1;
else if (!strncmp( "regs_", profile + 2, 5 )) reg_func = 1;
else if (!strncmp( "intr_", profile + 2, 5 )) reg_func = 2;
else if (strncmp( "long_", profile + 2, 5 ))
{
fprintf( stderr, "Invalid function name '%s', ignored\n", profile );
@@ -467,7 +460,6 @@ static const char *get_function_name( const ORDDEF *odp )
(odp->type == TYPE_PASCAL) ? "p" :
(odp->type == TYPE_VARARGS) ? "v" : "c",
(odp->flags & FLAG_REGISTER) ? "regs" :
(odp->flags & FLAG_INTERRUPT) ? "intr" :
(odp->flags & FLAG_RET16) ? "word" : "long",
odp->u.func.arg_types );
return buffer;
@@ -479,8 +471,8 @@ static const char *get_function_name( const ORDDEF *odp )
*/
static int Spec16TypeCompare( const void *e1, const void *e2 )
{
const ORDDEF *odp1 = *(const ORDDEF **)e1;
const ORDDEF *odp2 = *(const ORDDEF **)e2;
const ORDDEF *odp1 = *(const ORDDEF * const *)e1;
const ORDDEF *odp2 = *(const ORDDEF * const *)e2;
int retval;
int type1 = odp1->type;
int type2 = odp2->type;
@@ -490,8 +482,8 @@ static int Spec16TypeCompare( const void *e1, const void *e2 )
if ((retval = type1 - type2) != 0) return retval;
type1 = odp1->flags & (FLAG_RET16|FLAG_REGISTER|FLAG_INTERRUPT);
type2 = odp2->flags & (FLAG_RET16|FLAG_REGISTER|FLAG_INTERRUPT);
type1 = odp1->flags & (FLAG_RET16|FLAG_REGISTER);
type2 = odp2->flags & (FLAG_RET16|FLAG_REGISTER);
if ((retval = type1 - type2) != 0) return retval;
@@ -504,14 +496,14 @@ static int Spec16TypeCompare( const void *e1, const void *e2 )
*
* Output the functions for stub entry points
*/
static void output_stub_funcs( FILE *outfile )
static void output_stub_funcs( FILE *outfile, const DLLSPEC *spec )
{
int i;
char *p;
for (i = 0; i <= Limit; i++)
for (i = 0; i <= spec->limit; i++)
{
ORDDEF *odp = Ordinals[i];
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" );
@@ -528,7 +520,7 @@ static void output_stub_funcs( FILE *outfile )
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", dll_file_name );
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" );
@@ -538,9 +530,9 @@ static void output_stub_funcs( FILE *outfile )
fprintf( outfile, " for (;;) RtlRaiseException( &rec );\n}\n\n" );
break;
}
for (i = 0; i <= Limit; i++)
for (i = 0; i <= spec->limit; i++)
{
ORDDEF *odp = Ordinals[i];
ORDDEF *odp = spec->ordinals[i];
if (!odp || odp->type != TYPE_STUB) continue;
odp->link_name = xrealloc( odp->link_name, strlen(odp->name) + 13 );
strcpy( odp->link_name, "__wine_stub_" );
@@ -557,7 +549,7 @@ static void output_stub_funcs( FILE *outfile )
*
* Build a Win16 assembly file from a spec file.
*/
void BuildSpec16File( FILE *outfile )
void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
{
ORDDEF **type, **typelist;
int i, nFuncs, nTypes;
@@ -580,22 +572,22 @@ void BuildSpec16File( FILE *outfile )
memset( data, 0, 16 );
data_offset = 16;
if (!dll_name) /* set default name from file name */
if (!spec->dll_name) /* set default name from file name */
{
char *p;
dll_name = xstrdup( dll_file_name );
if ((p = strrchr( dll_name, '.' ))) *p = 0;
spec->dll_name = xstrdup( spec->file_name );
if ((p = strrchr( spec->dll_name, '.' ))) *p = 0;
}
output_stub_funcs( outfile );
output_stub_funcs( outfile, spec );
/* Build sorted list of all argument types, without duplicates */
typelist = (ORDDEF **)calloc( Limit+1, sizeof(ORDDEF *) );
typelist = (ORDDEF **)calloc( spec->limit+1, sizeof(ORDDEF *) );
for (i = nFuncs = 0; i <= Limit; i++)
for (i = nFuncs = 0; i <= spec->limit; i++)
{
ORDDEF *odp = Ordinals[i];
ORDDEF *odp = spec->ordinals[i];
if (!odp) continue;
switch (odp->type)
{
@@ -627,15 +619,15 @@ void BuildSpec16File( FILE *outfile )
char profile[101];
strcpy( profile, get_function_name( typelist[i] ));
BuildCallFrom16Func( outfile, profile, dll_file_name );
BuildCallFrom16Func( outfile, profile, spec->file_name );
}
#endif
/* Output the DLL functions prototypes */
for (i = 0; i <= Limit; i++)
for (i = 0; i <= spec->limit; i++)
{
ORDDEF *odp = Ordinals[i];
ORDDEF *odp = spec->ordinals[i];
if (!odp) continue;
switch(odp->type)
{
@@ -701,8 +693,6 @@ void BuildSpec16File( FILE *outfile )
break;
}
if (typelist[i]->flags & FLAG_INTERRUPT) argsize += 2;
/* build the arg types bit fields */
arg_types[0] = arg_types[1] = 0;
for (j = 0; typelist[i]->u.func.arg_types[j]; j++)
@@ -719,13 +709,13 @@ void BuildSpec16File( FILE *outfile )
}
arg_types[j / 10] |= type << (3 * (j % 10));
}
if (typelist[i]->flags & (FLAG_REGISTER|FLAG_INTERRUPT)) arg_types[0] |= ARG_REGISTER;
if (typelist[i]->flags & FLAG_REGISTER) arg_types[0] |= ARG_REGISTER;
if (typelist[i]->flags & FLAG_RET16) arg_types[0] |= ARG_RET16;
#ifdef __i386__
fprintf( outfile, " { 0x68, __wine_%s_CallFrom16_%s, 0x9a, __wine_call_from_16_%s,\n",
make_c_identifier(dll_file_name), profile,
(typelist[i]->flags & (FLAG_REGISTER|FLAG_INTERRUPT)) ? "regs":
make_c_identifier(spec->file_name), profile,
(typelist[i]->flags & FLAG_REGISTER) ? "regs":
(typelist[i]->flags & FLAG_RET16) ? "word" : "long" );
if (argsize)
fprintf( outfile, " 0x%04x, 0xca66, %d, { 0x%08x, 0x%08x } },\n",
@@ -745,9 +735,9 @@ void BuildSpec16File( FILE *outfile )
}
fprintf( outfile, " },\n {\n" );
for (i = 0; i <= Limit; i++)
for (i = 0; i <= spec->limit; i++)
{
ORDDEF *odp = Ordinals[i];
ORDDEF *odp = spec->ordinals[i];
if (!odp) continue;
switch (odp->type)
{
@@ -767,7 +757,7 @@ void BuildSpec16File( FILE *outfile )
type = bsearch( &odp, typelist, nTypes, sizeof(ORDDEF *), Spec16TypeCompare );
assert( type );
fprintf( outfile, " /* %s.%d */ ", dll_name, i );
fprintf( outfile, " /* %s.%d */ ", spec->dll_name, i );
#ifdef __i386__
fprintf( outfile, "{ 0x5566, 0x68, %s, 0xe866, %d /* %s */ },\n",
#else
@@ -797,8 +787,8 @@ void BuildSpec16File( FILE *outfile )
/* Build the module */
module_size = BuildModule16( outfile, code_offset, data_offset );
res_size = output_res16_data( outfile );
module_size = BuildModule16( outfile, code_offset, data_offset, spec );
res_size = output_res16_data( outfile, spec );
/* Output the DLL descriptor */
@@ -816,14 +806,14 @@ void BuildSpec16File( FILE *outfile )
fprintf( outfile, " sizeof(Module),\n" );
fprintf( outfile, " &code_segment,\n" );
fprintf( outfile, " Data_Segment,\n" );
fprintf( outfile, " \"%s\",\n", owner_name );
fprintf( outfile, " \"%s\",\n", spec->owner_name );
fprintf( outfile, " %s\n", res_size ? "resource_data" : "0" );
fprintf( outfile, "};\n" );
/* Output the DLL constructor */
sprintf( constructor, "__wine_spec_%s_init", make_c_identifier(dll_file_name) );
sprintf( destructor, "__wine_spec_%s_fini", make_c_identifier(dll_file_name) );
sprintf( constructor, "__wine_spec_%s_init", make_c_identifier(spec->file_name) );
sprintf( destructor, "__wine_spec_%s_fini", make_c_identifier(spec->file_name) );
output_dll_init( outfile, constructor, destructor );
fprintf( outfile,
+228 -237
View File
@@ -61,48 +61,42 @@ static int string_compare( const void *ptr1, const void *ptr2 )
*
* Generate an internal name for an entry point. Used for stubs etc.
*/
static const char *make_internal_name( const ORDDEF *odp, const char *prefix )
static const char *make_internal_name( const ORDDEF *odp, DLLSPEC *spec, const char *prefix )
{
static char buffer[256];
if (odp->name || odp->export_name)
{
char *p;
sprintf( buffer, "__wine_%s_%s_%s", prefix, dll_file_name,
sprintf( buffer, "__wine_%s_%s_%s", prefix, spec->file_name,
odp->name ? odp->name : odp->export_name );
/* make sure name is a legal C identifier */
for (p = buffer; *p; p++) if (!isalnum(*p) && *p != '_') break;
if (!*p) return buffer;
}
sprintf( buffer, "__wine_%s_%s_%d", prefix, make_c_identifier(dll_file_name), odp->ordinal );
sprintf( buffer, "__wine_%s_%s_%d", prefix, make_c_identifier(spec->file_name), odp->ordinal );
return buffer;
}
/*******************************************************************
* AssignOrdinals
* declare_weak_function
*
* Assign ordinals to all entry points.
* Output a prototype for a weak function.
*/
static void AssignOrdinals(void)
static void declare_weak_function( FILE *outfile, const char *ret_type, const char *name, const char *params)
{
int i, ordinal;
if ( !nb_names ) return;
/* start assigning from Base, or from 1 if no ordinal defined yet */
if (Base == MAX_ORDINALS) Base = 1;
for (i = 0, ordinal = Base; i < nb_names; i++)
{
if (Names[i]->ordinal != -1) continue; /* already has an ordinal */
while (Ordinals[ordinal]) ordinal++;
if (ordinal >= MAX_ORDINALS)
{
current_line = Names[i]->lineno;
fatal_error( "Too many functions defined (max %d)\n", MAX_ORDINALS );
}
Names[i]->ordinal = ordinal;
Ordinals[ordinal] = Names[i];
}
if (ordinal > Limit) Limit = ordinal;
fprintf( outfile, "#ifdef __GNUC__\n" );
fprintf( outfile, "# ifdef __APPLE__\n" );
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, "# else\n" );
fprintf( outfile, "extern %s %s(%s) __attribute__((weak));\n", ret_type, name, params );
fprintf( outfile, "# endif\n" );
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 " __ASM_NAME("%s") "\"); }\n", name );
fprintf( outfile, "#endif\n\n" );
}
@@ -140,7 +134,7 @@ static int output_debug( FILE *outfile )
*
* Output the export table for a Win32 module.
*/
static int output_exports( FILE *outfile, int nr_exports )
static int output_exports( FILE *outfile, int nr_exports, DLLSPEC *spec )
{
int i, fwd_size = 0, total_size = 0;
@@ -156,11 +150,11 @@ static int output_exports( FILE *outfile, int nr_exports )
fprintf( outfile, " \"\\t.long 0\\n\"\n" ); /* TimeDateStamp */
fprintf( outfile, " \"\\t.long 0\\n\"\n" ); /* MajorVersion/MinorVersion */
fprintf( outfile, " \"\\t.long __wine_spec_exp_names\\n\"\n" ); /* Name */
fprintf( outfile, " \"\\t.long %d\\n\"\n", Base ); /* Base */
fprintf( outfile, " \"\\t.long %d\\n\"\n", nr_exports ); /* NumberOfFunctions */
fprintf( outfile, " \"\\t.long %d\\n\"\n", nb_names ); /* NumberOfNames */
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 */
fprintf( outfile, " \"\\t.long __wine_spec_exports_funcs\\n\"\n" ); /* AddressOfFunctions */
if (nb_names)
if (spec->nb_names)
{
fprintf( outfile, " \"\\t.long __wine_spec_exp_name_ptrs\\n\"\n" ); /* AddressOfNames */
fprintf( outfile, " \"\\t.long __wine_spec_exp_ordinals\\n\"\n" ); /* AddressOfNameOrdinals */
@@ -175,9 +169,9 @@ static int output_exports( FILE *outfile, int nr_exports )
/* output the function pointers */
fprintf( outfile, " \"__wine_spec_exports_funcs:\\n\"\n" );
for (i = Base; i <= Limit; i++)
for (i = spec->base; i <= spec->limit; i++)
{
ORDDEF *odp = Ordinals[i];
ORDDEF *odp = spec->ordinals[i];
if (!odp) fprintf( outfile, " \"\\t.long 0\\n\"\n" );
else switch(odp->type)
{
@@ -188,7 +182,8 @@ static int output_exports( FILE *outfile, int nr_exports )
if (!(odp->flags & FLAG_FORWARD))
{
fprintf( outfile, " \"\\t.long " __ASM_NAME("%s") "\\n\"\n",
(odp->flags & FLAG_REGISTER) ? make_internal_name(odp,"regs") : odp->link_name );
(odp->flags & FLAG_REGISTER) ? make_internal_name( odp, spec, "regs" )
: odp->link_name );
}
else
{
@@ -197,49 +192,51 @@ static int output_exports( FILE *outfile, int nr_exports )
}
break;
case TYPE_STUB:
fprintf( outfile, " \"\\t.long " __ASM_NAME("%s") "\\n\"\n", make_internal_name( odp, "stub" ) );
fprintf( outfile, " \"\\t.long " __ASM_NAME("%s") "\\n\"\n",
make_internal_name( odp, spec, "stub" ) );
break;
default:
assert(0);
}
}
total_size += (Limit - Base + 1) * sizeof(int);
total_size += (spec->limit - spec->base + 1) * sizeof(int);
if (nb_names)
if (spec->nb_names)
{
/* output the function name pointers */
int namepos = strlen(dll_file_name) + 1;
int namepos = strlen(spec->file_name) + 1;
fprintf( outfile, " \"__wine_spec_exp_name_ptrs:\\n\"\n" );
for (i = 0; i < nb_names; i++)
for (i = 0; i < spec->nb_names; i++)
{
fprintf( outfile, " \"\\t.long __wine_spec_exp_names+%d\\n\"\n", namepos );
namepos += strlen(Names[i]->name) + 1;
namepos += strlen(spec->names[i]->name) + 1;
}
total_size += nb_names * sizeof(int);
total_size += spec->nb_names * sizeof(int);
}
/* output the function names */
fprintf( outfile, " \"\\t.text\\n\"\n" );
fprintf( outfile, " \"__wine_spec_exp_names:\\n\"\n" );
fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", dll_file_name );
for (i = 0; i < nb_names; i++)
fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", Names[i]->name );
fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", spec->file_name );
for (i = 0; i < spec->nb_names; i++)
fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", spec->names[i]->name );
fprintf( outfile, " \"\\t.data\\n\"\n" );
if (nb_names)
if (spec->nb_names)
{
/* output the function ordinals */
fprintf( outfile, " \"__wine_spec_exp_ordinals:\\n\"\n" );
for (i = 0; i < nb_names; i++)
for (i = 0; i < spec->nb_names; i++)
{
fprintf( outfile, " \"\\t" __ASM_SHORT " %d\\n\"\n", Names[i]->ordinal - Base );
fprintf( outfile, " \"\\t" __ASM_SHORT " %d\\n\"\n",
spec->names[i]->ordinal - spec->base );
}
total_size += nb_names * sizeof(short);
if (nb_names % 2)
total_size += spec->nb_names * sizeof(short);
if (spec->nb_names % 2)
{
fprintf( outfile, " \"\\t" __ASM_SHORT " 0\\n\"\n" );
total_size += sizeof(short);
@@ -251,9 +248,9 @@ static int output_exports( FILE *outfile, int nr_exports )
if (fwd_size)
{
fprintf( outfile, " \"__wine_spec_forwards:\\n\"\n" );
for (i = Base; i <= Limit; i++)
for (i = spec->base; i <= spec->limit; i++)
{
ORDDEF *odp = Ordinals[i];
ORDDEF *odp = spec->ordinals[i];
if (odp && (odp->flags & FLAG_FORWARD))
fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", odp->link_name );
}
@@ -265,9 +262,9 @@ static int output_exports( FILE *outfile, int nr_exports )
if (debugging)
{
for (i = Base; i <= Limit; i++)
for (i = spec->base; i <= spec->limit; i++)
{
ORDDEF *odp = Ordinals[i];
ORDDEF *odp = spec->ordinals[i];
unsigned int j, args, mask = 0;
const char *name;
@@ -287,7 +284,7 @@ static int output_exports( FILE *outfile, int nr_exports )
name = odp->link_name;
args = strlen(odp->u.func.arg_types) * sizeof(int);
if (odp->flags & FLAG_REGISTER) name = make_internal_name( odp, "regs" );
if (odp->flags & FLAG_REGISTER) name = make_internal_name( odp, spec, "regs" );
switch(odp->type)
{
@@ -325,13 +322,13 @@ static int output_exports( FILE *outfile, int nr_exports )
*
* Output the functions for stub entry points
*/
static void output_stub_funcs( FILE *outfile )
static void output_stub_funcs( FILE *outfile, DLLSPEC *spec )
{
int i;
for (i = 0; i < nb_entry_points; i++)
for (i = 0; i < spec->nb_entry_points; i++)
{
ORDDEF *odp = EntryPoints[i];
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" );
@@ -349,7 +346,7 @@ static void output_stub_funcs( FILE *outfile )
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", dll_file_name );
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" );
@@ -360,11 +357,11 @@ static void output_stub_funcs( FILE *outfile )
break;
}
for (i = 0; i < nb_entry_points; i++)
for (i = 0; i < spec->nb_entry_points; i++)
{
ORDDEF *odp = EntryPoints[i];
const ORDDEF *odp = &spec->entry_points[i];
if (odp->type != TYPE_STUB) continue;
fprintf( outfile, "void %s(void) ", make_internal_name( odp, "stub" ) );
fprintf( outfile, "void %s(void) ", make_internal_name( odp, spec, "stub" ) );
if (odp->name)
fprintf( outfile, "{ __wine_unimplemented(\"%s\"); }\n", odp->name );
else if (odp->export_name)
@@ -380,18 +377,18 @@ static void output_stub_funcs( FILE *outfile )
*
* Output the functions for register entry points
*/
static void output_register_funcs( FILE *outfile )
static void output_register_funcs( FILE *outfile, DLLSPEC *spec )
{
const char *name;
int i;
for (i = 0; i < nb_entry_points; i++)
for (i = 0; i < spec->nb_entry_points; i++)
{
ORDDEF *odp = EntryPoints[i];
const ORDDEF *odp = &spec->entry_points[i];
if (odp->type != TYPE_STDCALL && odp->type != TYPE_CDECL) continue;
if (!(odp->flags & FLAG_REGISTER)) continue;
if (odp->flags & FLAG_FORWARD) continue;
name = make_internal_name( odp, "regs" );
name = make_internal_name( odp, spec, "regs" );
fprintf( outfile,
"asm(\".align %d\\n\\t\"\n"
" \"" __ASM_FUNC("%s") "\\n\\t\"\n"
@@ -491,13 +488,12 @@ void output_dll_init( FILE *outfile, const char *constructor, const char *destru
*
* Build a Win32 C file from a spec file.
*/
void BuildSpec32File( FILE *outfile )
void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
{
int exports_size = 0;
int nr_exports, nr_imports, nr_resources;
int characteristics, subsystem;
int nr_exports, nr_imports;
DWORD page_size;
char constructor[100];
const char *init_func = spec->init_func;
#ifdef HAVE_GETPAGESIZE
page_size = getpagesize();
@@ -513,10 +509,8 @@ void BuildSpec32File( FILE *outfile )
# error Cannot get the page size on this platform
#endif
AssignOrdinals();
nr_exports = Base <= Limit ? Limit - Base + 1 : 0;
resolve_imports();
nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
resolve_imports( spec );
output_standard_file_header( outfile );
/* Reserve some space for the PE header */
@@ -535,7 +529,12 @@ void BuildSpec32File( FILE *outfile )
fprintf( outfile, "}\n" );
fprintf( outfile, "#endif\n" );
#ifdef __APPLE__
fprintf( outfile, "static char _end[4];\n" );
#else
fprintf( outfile, "extern char _end[];\n" );
#endif
fprintf( outfile, "extern int __wine_spec_data_start[], __wine_spec_exports[];\n\n" );
#ifdef __i386__
@@ -548,7 +547,7 @@ void BuildSpec32File( FILE *outfile )
{
/* Output the stub functions */
output_stub_funcs( outfile );
output_stub_funcs( outfile, spec );
fprintf( outfile, "#ifndef __GNUC__\n" );
fprintf( outfile, "static void __asm__dummy(void) {\n" );
@@ -556,11 +555,11 @@ void BuildSpec32File( FILE *outfile )
/* Output code for all register functions */
output_register_funcs( outfile );
output_register_funcs( outfile, spec );
/* Output the exports and relay entry points */
exports_size = output_exports( outfile, nr_exports );
exports_size = output_exports( outfile, nr_exports, spec );
fprintf( outfile, "#ifndef __GNUC__\n" );
fprintf( outfile, "}\n" );
@@ -569,37 +568,95 @@ void BuildSpec32File( FILE *outfile )
/* Output the DLL imports */
nr_imports = output_imports( outfile );
nr_imports = output_imports( outfile, spec );
/* Output the resources */
nr_resources = output_resources( outfile );
output_resources( outfile, spec );
/* Output LibMain function */
/* Output the entry point function */
characteristics = subsystem = 0;
switch(SpecMode)
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" );
#ifdef __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" );
#endif
if (spec->characteristics & IMAGE_FILE_DLL)
{
case SPEC_MODE_DLL:
if (init_func) fprintf( outfile, "extern void %s();\n", init_func );
if (init_func)
fprintf( outfile, "extern int __stdcall %s( void*, unsigned int, void* );\n\n", init_func );
else
{
fprintf( outfile, "#ifdef __GNUC__\n" );
fprintf( outfile, "# ifdef __APPLE__\n" );
fprintf( outfile, "extern void DllMain() __attribute__((weak_import));\n" );
fprintf( outfile, "# else\n" );
fprintf( outfile, "extern void DllMain() __attribute__((weak));\n" );
fprintf( outfile, "# endif\n" );
fprintf( outfile, "#else\n" );
fprintf( outfile, "extern void DllMain();\n" );
fprintf( outfile, "static void __asm__dummy_dllmain(void)" );
fprintf( outfile, " { asm(\".weak " __ASM_NAME("DllMain") "\"); }\n" );
fprintf( outfile, "#endif\n" );
declare_weak_function( outfile, "int __stdcall", "DllMain", "void*, unsigned int, void*" );
init_func = "DllMain";
}
characteristics = IMAGE_FILE_DLL;
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) _fini();\n"
" return ret;\n"
"}\n",
DLL_PROCESS_ATTACH, init_func, init_func, DLL_PROCESS_DETACH );
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 SPEC_MODE_GUIEXE:
if (!init_func) init_func = "WinMain";
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"
@@ -610,123 +667,46 @@ void BuildSpec32File( FILE *outfile )
" char *lpReserved2;\n"
" void *hStdInput, *hStdOutput, *hStdError;\n"
"} STARTUPINFOA;\n"
"int _ARGC;\n"
"char **_ARGV;\n"
"extern int __stdcall %s(void *,void *,char *,int);\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"
" extern int __wine_main_argc;\n"
" extern char **__wine_main_argv;\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"
" _ARGC = __wine_main_argc;\n"
" _ARGV = __wine_main_argv;\n"
" ExitProcess( %s( GetModuleHandleA(0), 0, cmdline, info.wShowWindow ) );\n"
"}\n\n", init_func, init_func );
init_func = "__wine_exe_main";
subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
break;
case SPEC_MODE_GUIEXE_UNICODE:
if (!init_func) init_func = "WinMain";
" 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,
"\ntypedef unsigned short WCHAR;\n"
"typedef 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"
"int _ARGC;\n"
"WCHAR **_ARGV;\n"
"extern int __stdcall %s(void *,void *,char *,int);\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"
" extern int __wine_main_argc;\n"
" extern WCHAR **__wine_main_wargv;\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"
" _ARGC = __wine_main_argc;\n"
" _ARGV = __wine_main_wargv;\n"
" ExitProcess( %s( GetModuleHandleA(0), 0, cmdline, info.wShowWindow ) );\n"
"}\n\n", init_func, init_func );
" if (__wine_spec_init_state == 1) _fini();\n"
" ExitProcess( ret );\n"
"}\n\n" );
init_func = "__wine_exe_main";
subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
break;
case SPEC_MODE_CUIEXE:
if (!init_func) init_func = "main";
fprintf( outfile,
"\nint _ARGC;\n"
"char **_ARGV;\n"
"extern void __stdcall ExitProcess(int);\n"
"static void __wine_exe_main(void)\n"
"{\n"
" extern int %s( int argc, char *argv[] );\n"
" extern int __wine_main_argc;\n"
" extern char **__wine_main_argv;\n"
" _ARGC = __wine_main_argc;\n"
" _ARGV = __wine_main_argv;\n"
" ExitProcess( %s( _ARGC, _ARGV ) );\n"
"}\n\n", init_func, init_func );
init_func = "__wine_exe_main";
subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
break;
case SPEC_MODE_CUIEXE_UNICODE:
if (!init_func) init_func = "wmain";
fprintf( outfile,
"\ntypedef unsigned short WCHAR;\n"
"int _ARGC;\n"
"WCHAR **_ARGV;\n"
"extern void __stdcall ExitProcess(int);\n"
"static void __wine_exe_main(void)\n"
"{\n"
" extern int %s( int argc, WCHAR *argv[] );\n"
" extern int __wine_main_argc;\n"
" extern WCHAR **__wine_main_wargv;\n"
" _ARGC = __wine_main_argc;\n"
" _ARGV = __wine_main_wargv;\n"
" ExitProcess( %s( _ARGC, _ARGV ) );\n"
"}\n\n", init_func, init_func );
init_func = "__wine_exe_main";
subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
break;
}
@@ -788,29 +768,30 @@ void BuildSpec32File( FILE *outfile )
#endif
fprintf( outfile, " 0, 0, 0, 0,\n" );
fprintf( outfile, " sizeof(nt_header.OptionalHeader),\n" ); /* SizeOfOptionalHeader */
fprintf( outfile, " 0x%04x },\n", characteristics ); /* Characteristics */
fprintf( outfile, " 0x%04x },\n", spec->characteristics ); /* Characteristics */
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 ? init_func : "DllMain" ); /* AddressOfEntryPoint */
fprintf( outfile, " %s,\n", init_func ); /* AddressOfEntryPoint */
fprintf( outfile, " 0, __wine_spec_data_start,\n" ); /* BaseOfCode/Data */
fprintf( outfile, " __wine_spec_pe_header,\n" ); /* ImageBase */
fprintf( outfile, " %ld,\n", page_size ); /* SectionAlignment */
fprintf( outfile, " %ld,\n", page_size ); /* FileAlignment */
fprintf( outfile, " 1, 0,\n" ); /* Major/MinorOperatingSystemVersion */
fprintf( outfile, " 0, 0,\n" ); /* Major/MinorImageVersion */
fprintf( outfile, " 4, 0,\n" ); /* Major/MinorSubsystemVersion */
fprintf( outfile, " %d,\n", spec->subsystem_major ); /* MajorSubsystemVersion */
fprintf( outfile, " %d,\n", spec->subsystem_minor ); /* MinorSubsystemVersion */
fprintf( outfile, " 0,\n" ); /* Win32VersionValue */
fprintf( outfile, " _end,\n" ); /* SizeOfImage */
fprintf( outfile, " %ld,\n", page_size ); /* SizeOfHeaders */
fprintf( outfile, " 0,\n" ); /* CheckSum */
fprintf( outfile, " 0x%04x,\n", subsystem ); /* Subsystem */
fprintf( outfile, " 0x%04x,\n", spec->subsystem );/* Subsystem */
fprintf( outfile, " 0,\n" ); /* DllCharacteristics */
fprintf( outfile, " %d, %ld,\n", /* SizeOfStackReserve/Commit */
(stack_size ? stack_size : 1024) * 1024, page_size );
(spec->stack_size ? spec->stack_size : 1024) * 1024, page_size );
fprintf( outfile, " %d, %ld,\n", /* SizeOfHeapReserve/Commit */
(DLLHeapSize ? DLLHeapSize : 1024) * 1024, page_size );
(spec->heap_size ? spec->heap_size : 1024) * 1024, page_size );
fprintf( outfile, " 0,\n" ); /* LoaderFlags */
fprintf( outfile, " %d,\n", IMAGE_NUMBEROF_DIRECTORY_ENTRIES ); /* NumberOfRvaAndSizes */
fprintf( outfile, " {\n" );
@@ -819,22 +800,29 @@ void BuildSpec32File( FILE *outfile )
fprintf( outfile, " { %s, %s },\n", /* IMAGE_DIRECTORY_ENTRY_IMPORT */
nr_imports ? "&imports" : "0", nr_imports ? "sizeof(imports)" : "0" );
fprintf( outfile, " { %s, %s },\n", /* IMAGE_DIRECTORY_ENTRY_RESOURCE */
nr_resources ? "&resources" : "0", nr_resources ? "sizeof(resources)" : "0" );
spec->nb_resources ? "&resources" : "0",
spec->nb_resources ? "sizeof(resources)" : "0" );
fprintf( outfile, " }\n }\n};\n\n" );
/* Output the DLL constructor */
sprintf( constructor, "__wine_spec_%s_init", make_c_identifier(dll_file_name) );
output_dll_init( outfile, constructor, NULL );
fprintf( outfile,
"void %s(void)\n"
"void __wine_spec_init(void)\n"
"{\n"
" extern void __wine_dll_register( const struct image_nt_headers *, const char * );\n"
" extern void *__wine_dbg_register( char * const *, int );\n"
" __wine_spec_init_state = 1;\n"
" __wine_dll_register( &nt_header, \"%s\" );\n"
"}\n",
constructor, dll_file_name );
"}\n\n",
spec->file_name );
output_dll_init( outfile, "__wine_spec_init_ctor", NULL );
fprintf( outfile,
"void __wine_spec_init_ctor(void)\n"
"{\n"
" if (__wine_spec_init_state) return;\n"
" __wine_spec_init();\n"
" __wine_spec_init_state = 2;\n"
"}\n" );
}
@@ -843,25 +831,23 @@ void BuildSpec32File( FILE *outfile )
*
* Build a Win32 def file from a spec file.
*/
void BuildDef32File(FILE *outfile)
void BuildDef32File( FILE *outfile, DLLSPEC *spec )
{
const char *name;
int i;
AssignOrdinals();
fprintf(outfile, "; File generated automatically from %s; do not edit!\n\n",
input_file_name );
fprintf(outfile, "LIBRARY %s\n\n", dll_file_name);
fprintf(outfile, "LIBRARY %s\n\n", spec->file_name);
fprintf(outfile, "EXPORTS\n");
/* Output the exports and relay entry points */
for(i = 0; i < nb_entry_points; i++)
for(i = 0; i < spec->nb_entry_points; i++)
{
ORDDEF *odp = EntryPoints[i];
const ORDDEF *odp = &spec->entry_points[i];
int is_data = 0;
if (!odp) continue;
@@ -906,7 +892,7 @@ void BuildDef32File(FILE *outfile)
fprintf( outfile, " @%d", odp->ordinal );
if (!odp->name) fprintf( outfile, " NONAME" );
if (is_data) fprintf( outfile, " DATA" );
#if !defined(__REACTOS__)
#if 0
/* MinGW binutils cannot handle this correctly */
if (odp->flags & FLAG_PRIVATE) fprintf( outfile, " PRIVATE" );
#endif
@@ -951,8 +937,8 @@ void BuildDebugFile( FILE *outfile, const char *srcdir, char **argv )
fprintf( outfile,
"#ifdef __GNUC__\n"
"static void __wine_dbg_%s_init(void) __attribute__((constructor));\n"
"static void __wine_dbg_%s_fini(void) __attribute__((destructor));\n"
"void __wine_dbg_%s_init(void) __attribute__((constructor));\n"
"void __wine_dbg_%s_fini(void) __attribute__((destructor));\n"
"#else\n"
"static void __asm__dummy_dll_init(void) {\n",
prefix, prefix );
@@ -972,29 +958,34 @@ void BuildDebugFile( FILE *outfile, const char *srcdir, char **argv )
fprintf( outfile, " \"\\tnop\\n\"\n" );
fprintf( outfile, " \"\\t.section\t\\\".text\\\"\\n\");\n" );
#elif defined(__powerpc__)
# ifdef __APPLE__
fprintf( outfile, "asm(\"\\t.mod_init_func\\n\"\n" );
fprintf( outfile, " \"\\t.align 2\\n\"\n" );
fprintf( outfile, " \"\\t.long " __ASM_NAME("__wine_dbg_%s_init") "\\n\"\n", prefix );
fprintf( outfile, " \"\\t.text\\n\");\n" );
fprintf( outfile, "asm(\"\\t.mod_term_func\\n\"\n" );
fprintf( outfile, " \"\\t.align 2\\n\"\n" );
fprintf( outfile, " \"\\t.long " __ASM_NAME("__wine_dbg_%s_fini") "\\n\"\n", prefix );
fprintf( outfile, " \"\\t.text\\n\");\n" );
# else
fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
fprintf( outfile, " \"\\tbl " __ASM_NAME("__wine_dbg_%s_init") "\\n\"\n", prefix );
fprintf( outfile, " \"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
fprintf( outfile, " \"\\tbl " __ASM_NAME("__wine_dbg_%s_fini") "\\n\"\n", prefix );
fprintf( outfile, " \"\\t.text\\n\");\n" );
# endif
#else
#error You need to define the DLL constructor for your architecture
#endif
fprintf( outfile, "}\n#endif /* defined(__GNUC__) */\n" );
fprintf( outfile, "}\n#endif /* defined(__GNUC__) */\n\n" );
fprintf( outfile,
"\n#ifdef __GNUC__\n"
"static\n"
"#endif\n"
"void __wine_dbg_%s_init(void)\n"
"{\n"
" extern void *__wine_dbg_register( char * const *, int );\n"
" debug_registration = __wine_dbg_register( debug_channels, %d );\n"
"}\n", prefix, nr_debug );
" if (!debug_registration) debug_registration = __wine_dbg_register( debug_channels, %d );\n"
"}\n\n", prefix, nr_debug );
fprintf( outfile,
"\n#ifdef __GNUC__\n"
"static\n"
"#endif\n"
"void __wine_dbg_%s_fini(void)\n"
"{\n"
" extern void __wine_dbg_unregister( void* );\n"
+81
View File
@@ -86,6 +86,7 @@ void fatal_error( const char *msg, ... )
fprintf( stderr, "%d:", current_line );
fputc( ' ', stderr );
}
else fprintf( stderr, "winebuild: " );
vfprintf( stderr, msg, valist );
va_end( valist );
exit(1);
@@ -213,6 +214,86 @@ void close_input_file( FILE *file )
}
/*******************************************************************
* remove_stdcall_decoration
*
* Remove a possible @xx suffix from a function name.
* Return the numerical value of the suffix, or -1 if none.
*/
int remove_stdcall_decoration( char *name )
{
char *p, *end = strrchr( name, '@' );
if (!end || !end[1] || end == name) return -1;
/* make sure all the rest is digits */
for (p = end + 1; *p; p++) if (!isdigit(*p)) return -1;
*end = 0;
return atoi( end + 1 );
}
/*******************************************************************
* alloc_dll_spec
*
* Create a new dll spec file descriptor
*/
DLLSPEC *alloc_dll_spec(void)
{
DLLSPEC *spec;
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;
spec->limit = 0;
spec->stack_size = 0;
spec->heap_size = 0;
spec->nb_entry_points = 0;
spec->alloc_entry_points = 0;
spec->nb_names = 0;
spec->nb_resources = 0;
spec->characteristics = 0;
spec->subsystem = 0;
spec->subsystem_major = 4;
spec->subsystem_minor = 0;
spec->entry_points = NULL;
spec->names = NULL;
spec->ordinals = NULL;
spec->resources = NULL;
return spec;
}
/*******************************************************************
* free_dll_spec
*
* Free dll spec file descriptor
*/
void free_dll_spec( DLLSPEC *spec )
{
int i;
for (i = 0; i < spec->nb_entry_points; i++)
{
ORDDEF *odp = &spec->entry_points[i];
free( odp->name );
free( odp->export_name );
free( odp->link_name );
}
free( spec->file_name );
free( spec->dll_name );
free( spec->owner_name );
free( spec->init_func );
free( spec->entry_points );
free( spec->names );
free( spec->ordinals );
free( spec->resources );
free( spec );
}
/*******************************************************************
* make_c_identifier
*
+34 -37
View File
@@ -19,10 +19,11 @@ option can be specified, as described in the \fBOPTIONS\fR section.
You have to specify exactly one of the following options, depending on
what you want winebuild to generate.
.TP
.BI \--spec=\ file.spec
Build a C file from a spec file (see \fBSPEC FILE SYNTAX\fR for
details). The resulting C file must be compiled and linked to the
other object files to build a working Wine dll.
.BI \--dll= filename
Build a C file from a .spec file (see \fBSPEC FILE SYNTAX\fR for
details), or from a standard Windows .def file. The resulting C file
must be compiled and linked to the other object files to build a
working Wine dll.
.br
In that mode, the
.I input files
@@ -32,16 +33,16 @@ final dll, to allow
to get the list of all undefined symbols that need to be imported from
other dlls.
.TP
.BI \--exe=\ name
.BI \--exe= name
Build a C file for the named executable. This is basically the same as
the --spec mode except that it doesn't require a .spec file as input,
the --dll mode except that it doesn't require a .spec file as input,
since an executable doesn't export functions. The resulting C file
must be compiled and linked to the other object files to build a
working Wine executable, and all the other object files must be listed
as
.I input files.
.TP
.BI \--def=\ file.spec
.BI \--def= file.spec
Build a .def file from a spec file. This is used when building dlls
with a PE (Win32) compiler.
.TP
@@ -75,11 +76,12 @@ Specify the module entry point function; if not specified, the default
is
.B DllMain
for dlls, and
.B main
or
.B WinMain
for CUI or GUI executables respectively. This is only valid for Win32
modules.
for executables (if
.B WinMain
is not defined, the standard C
.B main
is used instead). This is only valid for Win32 modules.
.TP
.BI \-f\ flags
Ignored for compatibility with the C compiler.
@@ -130,29 +132,7 @@ imported from it is actually called).
.BI \-M,\ --main-module= module
Specify that we are building a 16-bit dll, that will ultimately be
linked together with the 32-bit dll specified in \fImodule\fR. Only
meaningful in \fB--spec\fR mode.
.TP
.BI \-m,\ --exe-mode= mode
Set the executable mode, which can be one of the following:
.br
.B cui
for a command line ASCII executable,
.br
.B gui
for a graphical ASCII executable,
.br
.B cuiw
for a command line Unicode executable,
.br
.B guiw
for a graphical Unicode executable.
.br
A command line executable entry point is a normal C \fBmain\fR
function. A graphical executable has a \fBWinMain\fR entry point
instead. The ASCII/Unicode distinction applies to the strings that are
passed to the entry point.
.br
This option is only meaningful in \fB--exe\fR mode.
meaningful in \fB--dll\fR mode.
.TP
.BI \-N,\ --dll-name= dllname
Set the internal name of the module. It is only used in Win16
@@ -176,6 +156,26 @@ and will automatically be handled correctly (though the
.B \-r
option will also work for Win32 files).
.TP
.BI --subsystem= subsystem[:major[.minor]]
Set the subsystem of the executable, which can be one of the following:
.br
.B console
for a command line executable,
.br
.B windows
for a graphical executable,
.br
.B native
for a native-mode dll.
.br
The entry point of a command line executable is a normal C \fBmain\fR
function. A \fBwmain\fR function can be used instead if you need the
argument array to use Unicode strings. A graphical executable has a
\fBWinMain\fR entry point.
.br
Optionally a major and minor subsystem version can also be specified;
the default subsystem version is 4.0.
.TP
.B \--version
Display the program version and exit.
.TP
@@ -237,9 +237,6 @@ The entry point is only available on i386 platforms.
.B -register
The function uses CPU register to pass arguments.
.TP
.B -interrupt
The function is an interrupt handler routine.
.TP
.B -private
The function cannot be imported from other dlls, it can only be
accessed through GetProcAddress.
+86
View File
@@ -0,0 +1,86 @@
Index: main.c
===================================================================
RCS file: /home/wine/wine/tools/winebuild/main.c,v
retrieving revision 1.55
diff -u -r1.55 main.c
--- main.c 25 Mar 2004 00:40:52 -0000 1.55
+++ main.c 23 Sep 2004 20:38:14 -0000
@@ -412,9 +412,7 @@
switch (spec->type)
{
case SPEC_WIN16:
- if (argv[0])
- fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
- BuildSpec16File( output_file, spec );
+ fatal_error( "Win16 specs are not supported in ReactOS version of winebuild\n" );
break;
case SPEC_WIN32:
read_undef_symbols( argv );
@@ -439,12 +437,10 @@
BuildDebugFile( output_file, current_src_dir, argv );
break;
case MODE_RELAY16:
- if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
- BuildRelays16( output_file );
+ fatal_error( "Win16 relays are not supported in ReactOS version of winebuild\n" );
break;
case MODE_RELAY32:
- if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
- BuildRelays32( output_file );
+ fatal_error( "Win32 relays are not supported in ReactOS version of winebuild\n" );
break;
default:
usage(1);
Index: spec32.c
===================================================================
RCS file: /home/wine/wine/tools/winebuild/spec32.c,v
retrieving revision 1.83
diff -u -r1.83 spec32.c
--- spec32.c 15 Jul 2004 18:58:42 -0000 1.83
+++ spec32.c 23 Sep 2004 20:38:15 -0000
@@ -30,9 +30,15 @@
#include <stdarg.h>
#include <string.h>
+#ifdef WIN32
#include "windef.h"
#include "winbase.h"
-#include "wine/exception.h"
+#else
+#include "winglue.h"
+#endif
+#define EXCEPTION_WINE_STUB 0x80000100 /* stub entry point called */
+#define EH_NONCONTINUABLE 0x01
+
#include "build.h"
@@ -886,7 +892,10 @@
fprintf( outfile, " @%d", odp->ordinal );
if (!odp->name) fprintf( outfile, " NONAME" );
if (is_data) fprintf( outfile, " DATA" );
+#if 0
+ /* MinGW binutils cannot handle this correctly */
if (odp->flags & FLAG_PRIVATE) fprintf( outfile, " PRIVATE" );
+#endif
fprintf( outfile, "\n" );
}
}
Index: utils.c
===================================================================
RCS file: /home/wine/wine/tools/winebuild/utils.c,v
retrieving revision 1.20
diff -u -r1.20 utils.c
--- utils.c 25 Mar 2004 00:40:52 -0000 1.20
+++ utils.c 23 Sep 2004 20:38:15 -0000
@@ -21,6 +21,10 @@
#include "config.h"
#include "wine/port.h"
+#if !defined(WIN32)
+#undef strdup
+#endif
+
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
+4
View File
@@ -9,7 +9,11 @@ typedef unsigned short WCHAR;
#define LOBYTE(w) ((BYTE)(w))
#define HIBYTE(w) ((BYTE)(((WORD)(w)>>8)&0xFF))
#define DLL_PROCESS_ATTACH 1
#define DLL_PROCESS_DETACH 0
#define IMAGE_FILE_DLL 8192
#define IMAGE_SUBSYSTEM_NATIVE 1
#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2
#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16