- Recommit the fixed winebuild. The fix was to:

* remove Colin's 31297.
 * spec32.c:625, substitute odp->name check with (odp->name || odp->export_name) check.

svn path=/trunk/; revision=31300
This commit is contained in:
Aleksey Bragin 2007-12-18 11:00:37 +00:00
parent 0bb029564f
commit a03416ebf8
13 changed files with 1440 additions and 1345 deletions

View file

@ -19,6 +19,8 @@ C_SRCS = \
spec32.c \ spec32.c \
utils.c utils.c
INSTALLDIRS = $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man$(prog_manext)
all: $(PROGRAMS) $(MANPAGES) all: $(PROGRAMS) $(MANPAGES)
@MAKE_RULES@ @MAKE_RULES@
@ -26,12 +28,11 @@ all: $(PROGRAMS) $(MANPAGES)
winebuild$(EXEEXT): $(OBJS) winebuild$(EXEEXT): $(OBJS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBPORT) $(LDFLAGS) $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBPORT) $(LDFLAGS)
install:: $(PROGRAMS) $(MANPAGES) install:: $(PROGRAMS) $(MANPAGES) $(INSTALLDIRS)
$(MKINSTALLDIRS) $(bindir) $(mandir)/man$(prog_manext) $(INSTALL_PROGRAM) winebuild$(EXEEXT) $(DESTDIR)$(bindir)/winebuild$(EXEEXT)
$(INSTALL_PROGRAM) winebuild$(EXEEXT) $(bindir)/winebuild$(EXEEXT) $(INSTALL_DATA) winebuild.man $(DESTDIR)$(mandir)/man$(prog_manext)/winebuild.$(prog_manext)
$(INSTALL_DATA) winebuild.man $(mandir)/man$(prog_manext)/winebuild.$(prog_manext)
uninstall:: uninstall::
$(RM) $(bindir)/winebuild$(EXEEXT) $(mandir)/man$(prog_manext)/winebuild.$(prog_manext) $(RM) $(DESTDIR)$(bindir)/winebuild$(EXEEXT) $(DESTDIR)$(mandir)/man$(prog_manext)/winebuild.$(prog_manext)
### Dependencies: @DEPENDENCIES@ # everything below this line is overwritten by make depend

View file

@ -17,7 +17,7 @@
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#ifndef __WINE_BUILD_H #ifndef __WINE_BUILD_H
@ -85,6 +85,7 @@ typedef struct
typedef struct typedef struct
{ {
char *src_name; /* file name of the source spec file */
char *file_name; /* file name of the dll */ char *file_name; /* file name of the dll */
char *dll_name; /* internal name of the dll */ char *dll_name; /* internal name of the dll */
char *init_func; /* initialization routine */ char *init_func; /* initialization routine */
@ -98,6 +99,7 @@ typedef struct
int nb_names; /* number of entry points with names */ int nb_names; /* number of entry points with names */
unsigned int nb_resources; /* number of resources */ unsigned int nb_resources; /* number of resources */
int characteristics; /* characteristics for the PE header */ int characteristics; /* characteristics for the PE header */
int dll_characteristics;/* DLL characteristics for the PE header */
int subsystem; /* subsystem id */ int subsystem; /* subsystem id */
int subsystem_major; /* subsystem version major number */ int subsystem_major; /* subsystem version major number */
int subsystem_minor; /* subsystem version minor number */ int subsystem_minor; /* subsystem version minor number */
@ -114,7 +116,7 @@ enum target_cpu
enum target_platform enum target_platform
{ {
PLATFORM_UNSPECIFIED, PLATFORM_APPLE, PLATFORM_SVR4, PLATFORM_WINDOWS PLATFORM_UNSPECIFIED, PLATFORM_APPLE, PLATFORM_WINDOWS
}; };
extern enum target_cpu target_cpu; extern enum target_cpu target_cpu;
@ -122,31 +124,16 @@ extern enum target_platform target_platform;
/* entry point flags */ /* entry point flags */
#define FLAG_NORELAY 0x01 /* don't use relay debugging for this function */ #define FLAG_NORELAY 0x01 /* don't use relay debugging for this function */
#define FLAG_NONAME 0x02 /* don't import function by name */ #define FLAG_NONAME 0x02 /* don't export function by name */
#define FLAG_RET16 0x04 /* function returns a 16-bit value */ #define FLAG_RET16 0x04 /* function returns a 16-bit value */
#define FLAG_RET64 0x08 /* function returns a 64-bit value */ #define FLAG_RET64 0x08 /* function returns a 64-bit value */
#define FLAG_I386 0x10 /* function is i386 only */ #define FLAG_I386 0x10 /* function is i386 only */
#define FLAG_REGISTER 0x20 /* use register calling convention */ #define FLAG_REGISTER 0x20 /* use register calling convention */
#define FLAG_PRIVATE 0x40 /* function is private (cannot be imported) */ #define FLAG_PRIVATE 0x40 /* function is private (cannot be imported) */
#define FLAG_ORDINAL 0x80 /* function should be imported by ordinal */
#define FLAG_FORWARD 0x80 /* function is a forwarded name */ #define FLAG_FORWARD 0x100 /* function is a forwarded name */
#define FLAG_EXT_LINK 0x100 /* function links to an external symbol */ #define FLAG_EXT_LINK 0x200 /* function links to an external symbol */
/* Offset of a structure field relative to the start of the struct */
#define STRUCTOFFSET(type,field) ((int)&((type *)0)->field)
/* Offset of register relative to the start of the CONTEXT struct */
#define CONTEXTOFFSET(reg) STRUCTOFFSET(CONTEXT86,reg)
/* Offset of register relative to the start of the STACK16FRAME struct */
#define STACK16OFFSET(reg) STRUCTOFFSET(STACK16FRAME,reg)
/* Offset of register relative to the start of the STACK32FRAME struct */
#define STACK32OFFSET(reg) STRUCTOFFSET(STACK32FRAME,reg)
/* Offset of the stack pointer relative to %fs:(0) */
#define STACKOFFSET (STRUCTOFFSET(TEB,WOW32Reserved))
#define MAX_ORDINALS 65535 #define MAX_ORDINALS 65535
@ -169,11 +156,13 @@ extern void error( const char *msg, ... )
__attribute__ ((__format__ (__printf__, 1, 2))); __attribute__ ((__format__ (__printf__, 1, 2)));
extern void warning( const char *msg, ... ) extern void warning( const char *msg, ... )
__attribute__ ((__format__ (__printf__, 1, 2))); __attribute__ ((__format__ (__printf__, 1, 2)));
extern int output( const char *format, ... )
__attribute__ ((__format__ (__printf__, 1, 2)));
extern char *get_temp_file_name( const char *prefix, const char *suffix ); extern char *get_temp_file_name( const char *prefix, const char *suffix );
extern void output_standard_file_header( FILE *outfile ); extern void output_standard_file_header(void);
extern FILE *open_input_file( const char *srcdir, const char *name ); extern FILE *open_input_file( const char *srcdir, const char *name );
extern void close_input_file( FILE *file ); extern void close_input_file( FILE *file );
extern void dump_bytes( FILE *outfile, const void *buffer, unsigned int size ); extern void dump_bytes( const void *buffer, unsigned int size );
extern int remove_stdcall_decoration( char *name ); extern int remove_stdcall_decoration( char *name );
extern void assemble_file( const char *src_file, const char *obj_file ); extern void assemble_file( const char *src_file, const char *obj_file );
extern DLLSPEC *alloc_dll_spec(void); extern DLLSPEC *alloc_dll_spec(void);
@ -191,7 +180,8 @@ extern const char *get_asm_string_keyword(void);
extern const char *get_asm_short_keyword(void); extern const char *get_asm_short_keyword(void);
extern const char *get_asm_rodata_section(void); extern const char *get_asm_rodata_section(void);
extern const char *get_asm_string_section(void); extern const char *get_asm_string_section(void);
extern void output_function_size( FILE *outfile, const char *name ); extern void output_function_size( const char *name );
extern void output_gnu_stack_note(void);
extern void add_import_dll( const char *name, const char *filename ); extern void add_import_dll( const char *name, const char *filename );
extern void add_delayed_import( const char *name ); extern void add_delayed_import( const char *name );
@ -201,27 +191,25 @@ extern void read_undef_symbols( DLLSPEC *spec, char **argv );
extern int resolve_imports( DLLSPEC *spec ); extern int resolve_imports( DLLSPEC *spec );
extern int has_imports(void); extern int has_imports(void);
extern int has_relays( DLLSPEC *spec ); extern int has_relays( DLLSPEC *spec );
extern void output_get_pc_thunk( FILE *outfile ); extern void output_get_pc_thunk(void);
extern void output_stubs( FILE *outfile, DLLSPEC *spec ); extern void output_stubs( DLLSPEC *spec );
extern void output_imports( FILE *outfile, DLLSPEC *spec ); extern void output_imports( DLLSPEC *spec );
extern int load_res32_file( const char *name, DLLSPEC *spec ); extern int load_res32_file( const char *name, DLLSPEC *spec );
extern void output_resources( FILE *outfile, DLLSPEC *spec ); extern void output_resources( DLLSPEC *spec );
extern void load_res16_file( const char *name, DLLSPEC *spec ); extern void load_res16_file( const char *name, DLLSPEC *spec );
extern void output_res16_data( FILE *outfile, DLLSPEC *spec ); extern void output_res16_data( DLLSPEC *spec );
extern void output_res16_directory( FILE *outfile, DLLSPEC *spec, const char *header_name ); extern void output_res16_directory( DLLSPEC *spec, const char *header_name );
extern void BuildRelays16( FILE *outfile ); extern void BuildRelays16(void);
extern void BuildRelays32( FILE *outfile ); extern void BuildRelays32(void);
extern void BuildSpec16File( FILE *outfile, DLLSPEC *spec ); extern void BuildSpec16File( DLLSPEC *spec );
extern void BuildSpec32File( FILE *outfile, DLLSPEC *spec ); extern void BuildSpec32File( DLLSPEC *spec );
extern void BuildDef32File( FILE *outfile, DLLSPEC *spec ); extern void BuildDef32File( DLLSPEC *spec );
extern void BuildPedllFile( FILE *outfile, DLLSPEC *spec ); extern void BuildPedllFile( DLLSPEC *spec );
extern int parse_spec_file( FILE *file, DLLSPEC *spec ); extern int parse_spec_file( FILE *file, DLLSPEC *spec );
extern int parse_def_file( FILE *file, DLLSPEC *spec ); extern int parse_def_file( FILE *file, DLLSPEC *spec );
extern int mkstemps(char *template, int suffix_len);
/* global variables */ /* global variables */
extern int current_line; extern int current_line;
@ -232,9 +220,11 @@ extern int display_warnings;
extern int kill_at; extern int kill_at;
extern int verbose; extern int verbose;
extern int save_temps; extern int save_temps;
extern int link_ext_symbols;
extern char *input_file_name; extern char *input_file_name;
extern char *spec_file_name; extern char *spec_file_name;
extern FILE *output_file;
extern const char *output_file_name; extern const char *output_file_name;
extern char **lib_path; extern char **lib_path;

File diff suppressed because it is too large Load diff

View file

@ -19,16 +19,14 @@
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include "config.h" #include "config.h"
#include "wine/port.h"
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#ifdef WIN32
#include <io.h> /* unlink() */
#endif//WIN32
#include <signal.h> #include <signal.h>
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
@ -48,6 +46,7 @@ int display_warnings = 0;
int kill_at = 0; int kill_at = 0;
int verbose = 0; int verbose = 0;
int save_temps = 0; int save_temps = 0;
int link_ext_symbols = 0;
#if defined(__i386__) || defined(__x86_64__) #if defined(__i386__) || defined(__x86_64__)
enum target_cpu target_cpu = CPU_x86; enum target_cpu target_cpu = CPU_x86;
@ -65,8 +64,6 @@ enum target_cpu target_cpu = CPU_POWERPC;
#ifdef __APPLE__ #ifdef __APPLE__
enum target_platform target_platform = PLATFORM_APPLE; enum target_platform target_platform = PLATFORM_APPLE;
#elif defined(__svr4__)
enum target_platform target_platform = PLATFORM_SVR4;
#elif defined(_WINDOWS) #elif defined(_WINDOWS)
enum target_platform target_platform = PLATFORM_WINDOWS; enum target_platform target_platform = PLATFORM_WINDOWS;
#else #else
@ -77,6 +74,7 @@ char **lib_path = NULL;
char *input_file_name = NULL; char *input_file_name = NULL;
char *spec_file_name = NULL; char *spec_file_name = NULL;
FILE *output_file = NULL;
const char *output_file_name = NULL; const char *output_file_name = NULL;
static const char *output_file_source_name; static const char *output_file_source_name;
@ -84,7 +82,6 @@ char *as_command = NULL;
char *ld_command = NULL; char *ld_command = NULL;
char *nm_command = NULL; char *nm_command = NULL;
static FILE *output_file;
static int nb_res_files; static int nb_res_files;
static char **res_files; static char **res_files;
@ -127,7 +124,6 @@ static const struct
{ {
{ "macos", PLATFORM_APPLE }, { "macos", PLATFORM_APPLE },
{ "darwin", PLATFORM_APPLE }, { "darwin", PLATFORM_APPLE },
{ "sunos", PLATFORM_SVR4 },
{ "windows", PLATFORM_WINDOWS }, { "windows", PLATFORM_WINDOWS },
{ "winnt", PLATFORM_WINDOWS } { "winnt", PLATFORM_WINDOWS }
}; };
@ -248,8 +244,9 @@ static const char usage_str[] =
" --as-cmd=AS Command to use for assembling (default: as)\n" " --as-cmd=AS Command to use for assembling (default: as)\n"
" -d, --delay-lib=LIB Import the specified library in delayed mode\n" " -d, --delay-lib=LIB Import the specified library in delayed mode\n"
" -D SYM Ignored for C flags compatibility\n" " -D SYM Ignored for C flags compatibility\n"
" -E, --export=FILE Export the symbols defined in the .spec or .def file\n"
" -e, --entry=FUNC Set the DLL entry point function (default: DllMain)\n" " -e, --entry=FUNC Set the DLL entry point function (default: DllMain)\n"
" -E, --export=FILE Export the symbols defined in the .spec or .def file\n"
" --external-symbols Allow linking to external symbols\n"
" -f FLAGS Compiler flags (only -fPIC is supported)\n" " -f FLAGS Compiler flags (only -fPIC is supported)\n"
" -F, --filename=DLLFILE Set the DLL filename (default: from input file name)\n" " -F, --filename=DLLFILE Set the DLL filename (default: from input file name)\n"
" -h, --help Display this help message\n" " -h, --help Display this help message\n"
@ -263,6 +260,7 @@ static const char usage_str[] =
" -L, --library-path=DIR Look for imports libraries in DIR\n" " -L, --library-path=DIR Look for imports libraries in DIR\n"
" -M, --main-module=MODULE Set the name of the main module for a Win16 dll\n" " -M, --main-module=MODULE Set the name of the main module for a Win16 dll\n"
" --nm-cmd=NM Command to use to get undefined symbols (default: nm)\n" " --nm-cmd=NM Command to use to get undefined symbols (default: nm)\n"
" --nxcompat=y|n Set the NX compatibility flag (default: yes)\n"
" -N, --dll-name=DLLNAME Set the DLL name (default: from input file name)\n" " -N, --dll-name=DLLNAME Set the DLL name (default: from input file name)\n"
" -o, --output=NAME Set the output file name (default: stdout)\n" " -o, --output=NAME Set the output file name (default: stdout)\n"
" -r, --res=RSRC.RES Load resources from RSRC.RES\n" " -r, --res=RSRC.RES Load resources from RSRC.RES\n"
@ -278,7 +276,7 @@ static const char usage_str[] =
" --def Build a .def file from a .spec file\n" " --def Build a .def file from a .spec file\n"
" --exe Build a .c file for an executable\n" " --exe Build a .c file for an executable\n"
" --relay16 Build the 16-bit relay assembly routines\n" " --relay16 Build the 16-bit relay assembly routines\n"
" --relay32 Build the 32-bit relay assembly routines\n" " --relay32 Build the 32-bit relay assembly routines\n\n"
" --pedll Build a .c file for PE dll\n\n" " --pedll Build a .c file for PE dll\n\n"
"The mode options are mutually exclusive; you must specify one and only one.\n\n"; "The mode options are mutually exclusive; you must specify one and only one.\n\n";
@ -288,14 +286,16 @@ enum long_options_values
LONG_OPT_DEF, LONG_OPT_DEF,
LONG_OPT_EXE, LONG_OPT_EXE,
LONG_OPT_ASCMD, LONG_OPT_ASCMD,
LONG_OPT_EXTERNAL_SYMS,
LONG_OPT_LDCMD, LONG_OPT_LDCMD,
LONG_OPT_NMCMD, LONG_OPT_NMCMD,
LONG_OPT_NXCOMPAT,
LONG_OPT_RELAY16, LONG_OPT_RELAY16,
LONG_OPT_RELAY32, LONG_OPT_RELAY32,
LONG_OPT_SAVE_TEMPS, LONG_OPT_SAVE_TEMPS,
LONG_OPT_SUBSYSTEM, LONG_OPT_SUBSYSTEM,
LONG_OPT_VERSION,
LONG_OPT_TARGET, LONG_OPT_TARGET,
LONG_OPT_VERSION,
LONG_OPT_PEDLL LONG_OPT_PEDLL
}; };
@ -303,19 +303,21 @@ static const char short_options[] = "C:D:E:F:H:I:K:L:M:N:d:e:f:hi:kl:m:o:r:u:vw"
static const struct option long_options[] = static const struct option long_options[] =
{ {
{ "dll", 0, 0, LONG_OPT_DLL }, { "dll", 0, 0, LONG_OPT_DLL },
{ "def", 0, 0, LONG_OPT_DEF }, { "def", 0, 0, LONG_OPT_DEF },
{ "exe", 0, 0, LONG_OPT_EXE }, { "exe", 0, 0, LONG_OPT_EXE },
{ "as-cmd", 1, 0, LONG_OPT_ASCMD }, { "as-cmd", 1, 0, LONG_OPT_ASCMD },
{ "ld-cmd", 1, 0, LONG_OPT_LDCMD }, { "external-symbols", 0, 0, LONG_OPT_EXTERNAL_SYMS },
{ "nm-cmd", 1, 0, LONG_OPT_NMCMD }, { "ld-cmd", 1, 0, LONG_OPT_LDCMD },
{ "relay16", 0, 0, LONG_OPT_RELAY16 }, { "nm-cmd", 1, 0, LONG_OPT_NMCMD },
{ "relay32", 0, 0, LONG_OPT_RELAY32 }, { "nxcompat", 1, 0, LONG_OPT_NXCOMPAT },
{ "save-temps",0, 0, LONG_OPT_SAVE_TEMPS }, { "relay16", 0, 0, LONG_OPT_RELAY16 },
{ "subsystem",1, 0, LONG_OPT_SUBSYSTEM }, { "relay32", 0, 0, LONG_OPT_RELAY32 },
{ "target", 1, 0, LONG_OPT_TARGET }, { "save-temps", 0, 0, LONG_OPT_SAVE_TEMPS },
{ "version", 0, 0, LONG_OPT_VERSION }, { "subsystem", 1, 0, LONG_OPT_SUBSYSTEM },
{ "pedll", 1, 0, LONG_OPT_PEDLL }, { "target", 1, 0, LONG_OPT_TARGET },
{ "version", 0, 0, LONG_OPT_VERSION },
{ "pedll", 1, 0, LONG_OPT_PEDLL },
/* aliases for short options */ /* aliases for short options */
{ "delay-lib", 1, 0, 'd' }, { "delay-lib", 1, 0, 'd' },
{ "export", 1, 0, 'E' }, { "export", 1, 0, 'E' },
@ -471,12 +473,19 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec )
case LONG_OPT_ASCMD: case LONG_OPT_ASCMD:
as_command = xstrdup( optarg ); as_command = xstrdup( optarg );
break; break;
case LONG_OPT_EXTERNAL_SYMS:
link_ext_symbols = 1;
break;
case LONG_OPT_LDCMD: case LONG_OPT_LDCMD:
ld_command = xstrdup( optarg ); ld_command = xstrdup( optarg );
break; break;
case LONG_OPT_NMCMD: case LONG_OPT_NMCMD:
nm_command = xstrdup( optarg ); nm_command = xstrdup( optarg );
break; break;
case LONG_OPT_NXCOMPAT:
if (optarg[0] == 'n' || optarg[0] == 'N')
spec->dll_characteristics &= ~IMAGE_DLLCHARACTERISTICS_NX_COMPAT;
break;
case LONG_OPT_RELAY16: case LONG_OPT_RELAY16:
set_exec_mode( MODE_RELAY16 ); set_exec_mode( MODE_RELAY16 );
break; break;
@ -564,6 +573,7 @@ static int parse_input_file( DLLSPEC *spec )
char *extension = strrchr( spec_file_name, '.' ); char *extension = strrchr( spec_file_name, '.' );
int result; int result;
spec->src_name = xstrdup( input_file_name );
if (extension && !strcmp( extension, ".def" )) if (extension && !strcmp( extension, ".def" ))
result = parse_def_file( input_file, spec ); result = parse_def_file( input_file, spec );
else else
@ -592,7 +602,8 @@ int main(int argc, char **argv)
switch(exec_mode) switch(exec_mode)
{ {
case MODE_DLL: case MODE_DLL:
spec->characteristics |= IMAGE_FILE_DLL; if (spec->subsystem != IMAGE_SUBSYSTEM_NATIVE)
spec->characteristics |= IMAGE_FILE_DLL;
load_resources( argv, spec ); load_resources( argv, spec );
load_import_libs( argv ); load_import_libs( argv );
if (!spec_file_name) fatal_error( "missing .spec file\n" ); if (!spec_file_name) fatal_error( "missing .spec file\n" );
@ -604,7 +615,7 @@ int main(int argc, char **argv)
break; break;
case SPEC_WIN32: case SPEC_WIN32:
read_undef_symbols( spec, argv ); read_undef_symbols( spec, argv );
BuildSpec32File( output_file, spec ); BuildSpec32File( spec );
break; break;
default: assert(0); default: assert(0);
} }
@ -616,14 +627,14 @@ int main(int argc, char **argv)
load_import_libs( argv ); load_import_libs( argv );
if (spec_file_name && !parse_input_file( spec )) break; if (spec_file_name && !parse_input_file( spec )) break;
read_undef_symbols( spec, argv ); read_undef_symbols( spec, argv );
BuildSpec32File( output_file, spec ); BuildSpec32File( spec );
break; break;
case MODE_DEF: case MODE_DEF:
if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] ); if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
if (spec->type == SPEC_WIN16) fatal_error( "Cannot yet build .def file for 16-bit dlls\n" ); if (spec->type == SPEC_WIN16) fatal_error( "Cannot yet build .def file for 16-bit dlls\n" );
if (!spec_file_name) fatal_error( "missing .spec file\n" ); if (!spec_file_name) fatal_error( "missing .spec file\n" );
if (!parse_input_file( spec )) break; if (!parse_input_file( spec )) break;
BuildDef32File( output_file, spec ); BuildDef32File( spec );
break; break;
case MODE_RELAY16: case MODE_RELAY16:
fatal_error( "Win16 relays are not supported in ReactOS version of winebuild\n" ); fatal_error( "Win16 relays are not supported in ReactOS version of winebuild\n" );
@ -634,7 +645,7 @@ int main(int argc, char **argv)
case MODE_PEDLL: case MODE_PEDLL:
if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] ); if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
if (!parse_input_file( spec )) break; if (!parse_input_file( spec )) break;
BuildPedllFile( output_file, spec ); BuildPedllFile( spec );
break; break;
default: default:
usage(1); usage(1);
@ -643,7 +654,7 @@ int main(int argc, char **argv)
if (nb_errors) exit(1); if (nb_errors) exit(1);
if (output_file_name) if (output_file_name)
{ {
fclose( output_file ); if (fclose( output_file ) < 0) fatal_perror( "fclose" );
if (output_file_source_name) assemble_file( output_file_source_name, output_file_name ); if (output_file_source_name) assemble_file( output_file_source_name, output_file_name );
output_file_name = NULL; output_file_name = NULL;
} }

View file

@ -19,10 +19,11 @@
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include "config.h" #include "config.h"
#include "wine/port.h"
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
@ -44,6 +45,9 @@ static FILE *input_file;
static const char *separator_chars; static const char *separator_chars;
static const char *comment_chars; static const char *comment_chars;
/* valid characters in ordinal names */
static const char valid_ordname_chars[] = "/$:-_@?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
static const char * const TypeNames[TYPE_NBTYPES] = static const char * const TypeNames[TYPE_NBTYPES] =
{ {
"variable", /* TYPE_VARIABLE */ "variable", /* TYPE_VARIABLE */
@ -65,6 +69,7 @@ static const char * const FlagNames[] =
"i386", /* FLAG_I386 */ "i386", /* FLAG_I386 */
"register", /* FLAG_REGISTER */ "register", /* FLAG_REGISTER */
"private", /* FLAG_PRIVATE */ "private", /* FLAG_PRIVATE */
"ordinal", /* FLAG_ORDINAL */
NULL NULL
}; };
@ -74,12 +79,12 @@ static int IsNumberString(const char *s)
return 1; return 1;
} }
inline static int is_token_separator( char ch ) static inline int is_token_separator( char ch )
{ {
return strchr( separator_chars, ch ) != NULL; return strchr( separator_chars, ch ) != NULL;
} }
inline static int is_token_comment( char ch ) static inline int is_token_comment( char ch )
{ {
return strchr( comment_chars, ch ) != NULL; return strchr( comment_chars, ch ) != NULL;
} }
@ -445,6 +450,7 @@ static const char *parse_spec_flags( ORDDEF *odp )
static int parse_spec_ordinal( int ordinal, DLLSPEC *spec ) static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
{ {
const char *token; const char *token;
size_t len;
ORDDEF *odp = add_entry_point( spec ); ORDDEF *odp = add_entry_point( spec );
memset( odp, 0, sizeof(*odp) ); memset( odp, 0, sizeof(*odp) );
@ -468,6 +474,13 @@ static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
odp->lineno = current_line; odp->lineno = current_line;
odp->ordinal = ordinal; odp->ordinal = ordinal;
len = strspn( odp->name, valid_ordname_chars );
if (len < strlen( odp->name ))
{
error( "Character '%c' is not allowed in exported name '%s'\n", odp->name[len], odp->name );
goto error;
}
switch(odp->type) switch(odp->type)
{ {
case TYPE_VARIABLE: case TYPE_VARIABLE:
@ -532,11 +545,14 @@ static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
} }
} }
if (!strcmp( odp->name, "@" ) || odp->flags & FLAG_NONAME) if (!strcmp( odp->name, "@" ) || odp->flags & (FLAG_NONAME | FLAG_ORDINAL))
{ {
if (ordinal == -1) if (ordinal == -1)
{ {
error( "Nameless function needs an explicit ordinal number\n" ); if (!strcmp( odp->name, "@" ))
error( "Nameless function needs an explicit ordinal number\n" );
else
error( "Function imported by ordinal needs an explicit ordinal number\n" );
goto error; goto error;
} }
if (spec->type != SPEC_WIN32) if (spec->type != SPEC_WIN32)
@ -544,9 +560,16 @@ static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
error( "Nameless functions not supported for Win16\n" ); error( "Nameless functions not supported for Win16\n" );
goto error; goto error;
} }
if (!strcmp( odp->name, "@" )) free( odp->name ); if (!strcmp( odp->name, "@" ))
else odp->export_name = odp->name; {
odp->name = NULL; free( odp->name );
odp->name = NULL;
}
else if (!(odp->flags & FLAG_ORDINAL)) /* -ordinal only affects the import library */
{
odp->export_name = odp->name;
odp->name = NULL;
}
} }
return 1; return 1;

File diff suppressed because it is too large Load diff

View file

@ -15,10 +15,11 @@
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include "config.h" #include "config.h"
#include "wine/port.h"
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
@ -77,7 +78,7 @@ static const unsigned char *file_end; /* end of resource file */
static const char *file_name; /* current resource file name */ static const char *file_name; /* current resource file name */
inline static struct resource *add_resource( DLLSPEC *spec ) static inline struct resource *add_resource( DLLSPEC *spec )
{ {
spec->resources = xrealloc( spec->resources, (spec->nb_resources + 1) * sizeof(*spec->resources) ); spec->resources = xrealloc( spec->resources, (spec->nb_resources + 1) * sizeof(*spec->resources) );
return &spec->resources[spec->nb_resources++]; return &spec->resources[spec->nb_resources++];
@ -140,7 +141,7 @@ static void get_string( struct string_id *str )
} }
else else
{ {
char *p = xmalloc( (strlen((char*)file_pos) + 1) ); char *p = xmalloc(strlen((const char *)file_pos) + 1);
str->str = p; str->str = p;
str->id = 0; str->id = 0;
while ((*p++ = get_byte())); while ((*p++ = get_byte()));
@ -240,16 +241,16 @@ static void free_resource_tree( struct res_tree *tree )
} }
/* output a string preceded by its length */ /* output a string preceded by its length */
static void output_string( FILE *outfile, const char *str ) static void output_string( const char *str )
{ {
unsigned int i, len = strlen(str); unsigned int i, len = strlen(str);
fprintf( outfile, "\t.byte 0x%02x", len ); output( "\t.byte 0x%02x", len );
for (i = 0; i < len; i++) fprintf( outfile, ",0x%02x", (unsigned char)str[i] ); for (i = 0; i < len; i++) output( ",0x%02x", (unsigned char)str[i] );
fprintf( outfile, " /* %s */\n", str ); output( " /* %s */\n", str );
} }
/* output the resource data */ /* output the resource data */
void output_res16_data( FILE *outfile, DLLSPEC *spec ) void output_res16_data( DLLSPEC *spec )
{ {
const struct resource *res; const struct resource *res;
unsigned int i; unsigned int i;
@ -258,14 +259,14 @@ void output_res16_data( FILE *outfile, DLLSPEC *spec )
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++) for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
{ {
fprintf( outfile, ".L__wine_spec_resource_%u:\n", i ); output( ".L__wine_spec_resource_%u:\n", i );
dump_bytes( outfile, res->data, res->data_size ); dump_bytes( res->data, res->data_size );
fprintf( outfile, ".L__wine_spec_resource_%u_end:\n", i ); output( ".L__wine_spec_resource_%u_end:\n", i );
} }
} }
/* output the resource definitions */ /* output the resource definitions */
void output_res16_directory( FILE *outfile, DLLSPEC *spec, const char *header_name ) void output_res16_directory( DLLSPEC *spec, const char *header_name )
{ {
unsigned int i, j; unsigned int i, j;
struct res_tree *tree; struct res_tree *tree;
@ -274,38 +275,39 @@ void output_res16_directory( FILE *outfile, DLLSPEC *spec, const char *header_na
tree = build_resource_tree( spec ); tree = build_resource_tree( spec );
fprintf( outfile, "\n.L__wine_spec_ne_rsrctab:\n" ); output( "\n.L__wine_spec_ne_rsrctab:\n" );
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* alignment */ output( "\t%s 0\n", get_asm_short_keyword() ); /* alignment */
/* type and name structures */ /* type and name structures */
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++) for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{ {
if (type->type->str) if (type->type->str)
fprintf( outfile, "\t%s .L__wine_spec_restype_%u-.L__wine_spec_ne_rsrctab\n", output( "\t%s .L__wine_spec_restype_%u-.L__wine_spec_ne_rsrctab\n",
get_asm_short_keyword(), i ); get_asm_short_keyword(), i );
else else
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), type->type->id | 0x8000 ); output( "\t%s 0x%04x\n", get_asm_short_keyword(), type->type->id | 0x8000 );
fprintf( outfile, "\t%s %u,0,0\n", get_asm_short_keyword(), type->nb_names ); output( "\t%s %u,0,0\n", get_asm_short_keyword(), type->nb_names );
for (j = 0, res = type->res; j < type->nb_names; j++, res++) for (j = 0, res = type->res; j < type->nb_names; j++, res++)
{ {
fprintf( outfile, "\t%s .L__wine_spec_resource_%u-%s\n", output( "\t%s .L__wine_spec_resource_%lu-%s\n",
get_asm_short_keyword(), res - spec->resources, header_name ); get_asm_short_keyword(), (unsigned long)(res - spec->resources), header_name );
fprintf( outfile, "\t%s .L__wine_spec_resource_%u_end-.L__wine_spec_resource_%u\n", output( "\t%s .L__wine_spec_resource_%lu_end-.L__wine_spec_resource_%lu\n",
get_asm_short_keyword(), res - spec->resources, res - spec->resources ); get_asm_short_keyword(), (unsigned long)(res - spec->resources),
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), res->memopt ); (unsigned long)(res - spec->resources) );
output( "\t%s 0x%04x\n", get_asm_short_keyword(), res->memopt );
if (res->name.str) if (res->name.str)
fprintf( outfile, "\t%s .L__wine_spec_resname_%u_%u-.L__wine_spec_ne_rsrctab\n", output( "\t%s .L__wine_spec_resname_%u_%u-.L__wine_spec_ne_rsrctab\n",
get_asm_short_keyword(), i, j ); get_asm_short_keyword(), i, j );
else else
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), res->name.id | 0x8000 ); output( "\t%s 0x%04x\n", get_asm_short_keyword(), res->name.id | 0x8000 );
fprintf( outfile, "\t%s 0,0\n", get_asm_short_keyword() ); output( "\t%s 0,0\n", get_asm_short_keyword() );
} }
} }
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* terminator */ output( "\t%s 0\n", get_asm_short_keyword() ); /* terminator */
/* name strings */ /* name strings */
@ -313,19 +315,19 @@ void output_res16_directory( FILE *outfile, DLLSPEC *spec, const char *header_na
{ {
if (type->type->str) if (type->type->str)
{ {
fprintf( outfile, ".L__wine_spec_restype_%u:\n", i ); output( ".L__wine_spec_restype_%u:\n", i );
output_string( outfile, type->type->str ); output_string( type->type->str );
} }
for (j = 0, res = type->res; j < type->nb_names; j++, res++) for (j = 0, res = type->res; j < type->nb_names; j++, res++)
{ {
if (res->name.str) if (res->name.str)
{ {
fprintf( outfile, ".L__wine_spec_resname_%u_%u:\n", i, j ); output( ".L__wine_spec_resname_%u_%u:\n", i, j );
output_string( outfile, res->name.str ); output_string( res->name.str );
} }
} }
} }
fprintf( outfile, "\t.byte 0\n" ); /* names terminator */ output( "\t.byte 0\n" ); /* names terminator */
free_resource_tree( tree ); free_resource_tree( tree );
} }

View file

@ -15,10 +15,11 @@
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include "config.h" #include "config.h"
#include "wine/port.h"
#include <ctype.h> #include <ctype.h>
#include <stdlib.h> #include <stdlib.h>
@ -91,7 +92,7 @@ static const char *file_name; /* current resource file name */
#define RESDIR_SIZE(n) (sizeof(IMAGE_RESOURCE_DIRECTORY) + (n) * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY)) #define RESDIR_SIZE(n) (sizeof(IMAGE_RESOURCE_DIRECTORY) + (n) * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY))
inline static struct resource *add_resource( DLLSPEC *spec ) static inline struct resource *add_resource( DLLSPEC *spec )
{ {
spec->resources = xrealloc( spec->resources, (spec->nb_resources + 1) * sizeof(spec->resources[0]) ); spec->resources = xrealloc( spec->resources, (spec->nb_resources + 1) * sizeof(spec->resources[0]) );
return &spec->resources[spec->nb_resources++]; return &spec->resources[spec->nb_resources++];
@ -314,29 +315,29 @@ static void free_resource_tree( struct res_tree *tree )
} }
/* output a Unicode string */ /* output a Unicode string */
static void output_string( FILE *outfile, const WCHAR *name ) static void output_string( const WCHAR *name )
{ {
int i, len = strlenW(name); int i, len = strlenW(name);
fprintf( outfile, "\t%s 0x%04x", get_asm_short_keyword(), len ); output( "\t%s 0x%04x", get_asm_short_keyword(), len );
for (i = 0; i < len; i++) fprintf( outfile, ",0x%04x", name[i] ); for (i = 0; i < len; i++) output( ",0x%04x", name[i] );
fprintf( outfile, " /* " ); output( " /* " );
for (i = 0; i < len; i++) fprintf( outfile, "%c", isprint((char)name[i]) ? (char)name[i] : '?' ); for (i = 0; i < len; i++) output( "%c", isprint((char)name[i]) ? (char)name[i] : '?' );
fprintf( outfile, " */\n" ); output( " */\n" );
} }
/* output a resource directory */ /* output a resource directory */
static inline void output_res_dir( FILE *outfile, unsigned int nb_names, unsigned int nb_ids ) static inline void output_res_dir( unsigned int nb_names, unsigned int nb_ids )
{ {
fprintf( outfile, "\t.long 0\n" ); /* Characteristics */ output( "\t.long 0\n" ); /* Characteristics */
fprintf( outfile, "\t.long 0\n" ); /* TimeDateStamp */ output( "\t.long 0\n" ); /* TimeDateStamp */
fprintf( outfile, "\t%s 0,0\n", /* Major/MinorVersion */ output( "\t%s 0,0\n", /* Major/MinorVersion */
get_asm_short_keyword() ); get_asm_short_keyword() );
fprintf( outfile, "\t%s %u,%u\n", /* NumberOfNamed/IdEntries */ output( "\t%s %u,%u\n", /* NumberOfNamed/IdEntries */
get_asm_short_keyword(), nb_names, nb_ids ); get_asm_short_keyword(), nb_names, nb_ids );
} }
/* output the resource definitions */ /* output the resource definitions */
void output_resources( FILE *outfile, DLLSPEC *spec ) void output_resources( DLLSPEC *spec )
{ {
int k, nb_id_types; int k, nb_id_types;
unsigned int i, n, offset, data_offset; unsigned int i, n, offset, data_offset;
@ -386,19 +387,19 @@ void output_resources( FILE *outfile, DLLSPEC *spec )
/* output the resource directories */ /* output the resource directories */
fprintf( outfile, "\n/* resources */\n\n" ); output( "\n/* resources */\n\n" );
fprintf( outfile, "\t.data\n" ); output( "\t.data\n" );
fprintf( outfile, "\t.align %d\n", get_alignment(get_ptr_size()) ); output( "\t.align %d\n", get_alignment(get_ptr_size()) );
fprintf( outfile, ".L__wine_spec_resources:\n" ); output( ".L__wine_spec_resources:\n" );
output_res_dir( outfile, tree->nb_types - nb_id_types, nb_id_types ); output_res_dir( tree->nb_types - nb_id_types, nb_id_types );
/* dump the type directory */ /* dump the type directory */
offset = RESDIR_SIZE( tree->nb_types ); offset = RESDIR_SIZE( tree->nb_types );
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++) for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{ {
fprintf( outfile, "\t.long 0x%08x,0x%08x\n", output( "\t.long 0x%08x,0x%08x\n",
type->name_offset, offset | 0x80000000 ); type->name_offset, offset | 0x80000000 );
offset += RESDIR_SIZE( type->nb_names ); offset += RESDIR_SIZE( type->nb_names );
for (n = 0, name = type->names; n < type->nb_names; n++, name++) for (n = 0, name = type->names; n < type->nb_names; n++, name++)
@ -412,22 +413,22 @@ void output_resources( FILE *outfile, DLLSPEC *spec )
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++) for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{ {
output_res_dir( outfile, type->nb_names - type->nb_id_names, type->nb_id_names ); output_res_dir( type->nb_names - type->nb_id_names, type->nb_id_names );
offset += RESDIR_SIZE( type->nb_names ); offset += RESDIR_SIZE( type->nb_names );
for (n = 0, name = type->names; n < type->nb_names; n++, name++) for (n = 0, name = type->names; n < type->nb_names; n++, name++)
{ {
fprintf( outfile, "\t.long 0x%08x,0x%08x\n", output( "\t.long 0x%08x,0x%08x\n",
name->name_offset, offset | 0x80000000 ); name->name_offset, offset | 0x80000000 );
offset += RESDIR_SIZE( name->nb_languages ); offset += RESDIR_SIZE( name->nb_languages );
} }
for (n = 0, name = type->names; n < type->nb_names; n++, name++) for (n = 0, name = type->names; n < type->nb_names; n++, name++)
{ {
output_res_dir( outfile, 0, name->nb_languages ); output_res_dir( 0, name->nb_languages );
for (k = 0, res = name->res; k < name->nb_languages; k++, res++) for (k = 0, res = name->res; k < name->nb_languages; k++, res++)
{ {
fprintf( outfile, "\t.long 0x%08x,0x%08x\n", res->lang, unsigned int entry_offset = (res - spec->resources) * sizeof(IMAGE_RESOURCE_DATA_ENTRY);
data_offset + (res - spec->resources) * sizeof(IMAGE_RESOURCE_DATA_ENTRY) ); output( "\t.long 0x%08x,0x%08x\n", res->lang, data_offset + entry_offset );
} }
} }
} }
@ -435,28 +436,28 @@ void output_resources( FILE *outfile, DLLSPEC *spec )
/* dump the resource data entries */ /* dump the resource data entries */
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++) for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
fprintf( outfile, "\t.long .L__wine_spec_res_%d-.L__wine_spec_rva_base,%u,0,0\n", output( "\t.long .L__wine_spec_res_%d-.L__wine_spec_rva_base,%u,0,0\n",
i, res->data_size ); i, res->data_size );
/* dump the name strings */ /* dump the name strings */
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++) for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{ {
if (type->type->str) output_string( outfile, type->type->str ); if (type->type->str) output_string( type->type->str );
for (n = 0, name = type->names; n < type->nb_names; n++, name++) for (n = 0, name = type->names; n < type->nb_names; n++, name++)
if (name->name->str) output_string( outfile, name->name->str ); if (name->name->str) output_string( name->name->str );
} }
/* resource data */ /* resource data */
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++) for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
{ {
fprintf( outfile, "\n\t.align %d\n", get_alignment(get_ptr_size()) ); output( "\n\t.align %d\n", get_alignment(get_ptr_size()) );
fprintf( outfile, ".L__wine_spec_res_%d:\n", i ); output( ".L__wine_spec_res_%d:\n", i );
dump_bytes( outfile, res->data, res->data_size ); dump_bytes( res->data, res->data_size );
} }
fprintf( outfile, ".L__wine_spec_resources_end:\n" ); output( ".L__wine_spec_resources_end:\n" );
fprintf( outfile, "\t.byte 0\n" ); output( "\t.byte 0\n" );
free_resource_tree( tree ); free_resource_tree( tree );
} }

View file

@ -19,10 +19,11 @@
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include "config.h" #include "config.h"
#include "wine/port.h"
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
@ -53,31 +54,31 @@ static inline int is_function( const ORDDEF *odp )
* *
* Output entries for individual symbols in the entry table. * Output entries for individual symbols in the entry table.
*/ */
static void output_entries( FILE *outfile, DLLSPEC *spec, int first, int count ) static void output_entries( DLLSPEC *spec, int first, int count )
{ {
int i; int i;
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
ORDDEF *odp = spec->ordinals[first + i]; ORDDEF *odp = spec->ordinals[first + i];
fprintf( outfile, "\t.byte 0x03\n" ); /* flags: exported & public data */ output( "\t.byte 0x03\n" ); /* flags: exported & public data */
switch (odp->type) switch (odp->type)
{ {
case TYPE_CDECL: case TYPE_CDECL:
case TYPE_PASCAL: case TYPE_PASCAL:
case TYPE_VARARGS: case TYPE_VARARGS:
case TYPE_STUB: case TYPE_STUB:
fprintf( outfile, "\t%s .L__wine_%s_%u-.L__wine_spec_code_segment\n", output( "\t%s .L__wine_%s_%u-.L__wine_spec_code_segment\n",
get_asm_short_keyword(), get_asm_short_keyword(),
make_c_identifier(spec->dll_name), first + i ); make_c_identifier(spec->dll_name), first + i );
break; break;
case TYPE_VARIABLE: case TYPE_VARIABLE:
fprintf( outfile, "\t%s .L__wine_%s_%u-.L__wine_spec_data_segment\n", output( "\t%s .L__wine_%s_%u-.L__wine_spec_data_segment\n",
get_asm_short_keyword(), get_asm_short_keyword(),
make_c_identifier(spec->dll_name), first + i ); make_c_identifier(spec->dll_name), first + i );
break; break;
case TYPE_ABS: case TYPE_ABS:
fprintf( outfile, "\t%s 0x%04x /* %s */\n", output( "\t%s 0x%04x /* %s */\n",
get_asm_short_keyword(), odp->u.abs.value, odp->name ); get_asm_short_keyword(), odp->u.abs.value, odp->name );
break; break;
default: default:
@ -90,7 +91,7 @@ static void output_entries( FILE *outfile, DLLSPEC *spec, int first, int count )
/******************************************************************* /*******************************************************************
* output_entry_table * output_entry_table
*/ */
static void output_entry_table( FILE *outfile, DLLSPEC *spec ) static void output_entry_table( DLLSPEC *spec )
{ {
int i, prev = 0, prev_sel = -1, bundle_count = 0; int i, prev = 0, prev_sel = -1, bundle_count = 0;
@ -125,10 +126,10 @@ static void output_entry_table( FILE *outfile, DLLSPEC *spec )
/* flush previous bundle */ /* flush previous bundle */
if (bundle_count) if (bundle_count)
{ {
fprintf( outfile, "\t/* %s.%d - %s.%d */\n", output( "\t/* %s.%d - %s.%d */\n",
spec->dll_name, prev - bundle_count + 1, spec->dll_name, prev ); spec->dll_name, prev - bundle_count + 1, spec->dll_name, prev );
fprintf( outfile, "\t.byte 0x%02x,0x%02x\n", bundle_count, prev_sel ); output( "\t.byte 0x%02x,0x%02x\n", bundle_count, prev_sel );
output_entries( outfile, spec, prev - bundle_count + 1, bundle_count ); output_entries( spec, prev - bundle_count + 1, bundle_count );
} }
if (prev + 1 != i) if (prev + 1 != i)
@ -136,10 +137,10 @@ static void output_entry_table( FILE *outfile, DLLSPEC *spec )
int skip = i - (prev + 1); int skip = i - (prev + 1);
while (skip > 255) while (skip > 255)
{ {
fprintf( outfile, "\t.byte 0xff,0x00\n" ); output( "\t.byte 0xff,0x00\n" );
skip -= 255; skip -= 255;
} }
fprintf( outfile, "\t.byte 0x%02x,0x00\n", skip ); output( "\t.byte 0x%02x,0x00\n", skip );
} }
bundle_count = 0; bundle_count = 0;
@ -152,24 +153,24 @@ static void output_entry_table( FILE *outfile, DLLSPEC *spec )
/* flush last bundle */ /* flush last bundle */
if (bundle_count) if (bundle_count)
{ {
fprintf( outfile, "\t.byte 0x%02x,0x%02x\n", bundle_count, prev_sel ); output( "\t.byte 0x%02x,0x%02x\n", bundle_count, prev_sel );
output_entries( outfile, spec, prev - bundle_count + 1, bundle_count ); output_entries( spec, prev - bundle_count + 1, bundle_count );
} }
fprintf( outfile, "\t.byte 0x00\n" ); output( "\t.byte 0x00\n" );
} }
/******************************************************************* /*******************************************************************
* output_resident_name * output_resident_name
*/ */
static void output_resident_name( FILE *outfile, const char *string, int ordinal ) static void output_resident_name( const char *string, int ordinal )
{ {
unsigned int i, len = strlen(string); unsigned int i, len = strlen(string);
fprintf( outfile, "\t.byte 0x%02x", len ); output( "\t.byte 0x%02x", len );
for (i = 0; i < len; i++) fprintf( outfile, ",0x%02x", (unsigned char)toupper(string[i]) ); for (i = 0; i < len; i++) output( ",0x%02x", (unsigned char)toupper(string[i]) );
fprintf( outfile, " /* %s */\n", string ); output( " /* %s */\n", string );
fprintf( outfile, "\t%s %u\n", get_asm_short_keyword(), ordinal ); output( "\t%s %u\n", get_asm_short_keyword(), ordinal );
} }
@ -282,7 +283,7 @@ static int get_function_argsize( const ORDDEF *odp )
* the same as for normal functions, but in addition the CONTEXT86 pointer * 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. * filled with the current register values is passed to the 32-bit routine.
*/ */
static void output_call16_function( FILE *outfile, ORDDEF *odp ) static void output_call16_function( ORDDEF *odp )
{ {
char name[256]; char name[256];
int i, pos, stack_words; int i, pos, stack_words;
@ -292,41 +293,41 @@ static void output_call16_function( FILE *outfile, ORDDEF *odp )
sprintf( name, ".L__wine_spec_call16_%s", get_relay_name(odp) ); sprintf( name, ".L__wine_spec_call16_%s", get_relay_name(odp) );
fprintf( outfile, "\t.align %d\n", get_alignment(4) ); output( "\t.align %d\n", get_alignment(4) );
fprintf( outfile, "\t%s\n", func_declaration(name) ); output( "\t%s\n", func_declaration(name) );
fprintf( outfile, "%s:\n", name ); output( "%s:\n", name );
fprintf( outfile, "\tpushl %%ebp\n" ); output( "\tpushl %%ebp\n" );
fprintf( outfile, "\tmovl %%esp,%%ebp\n" ); output( "\tmovl %%esp,%%ebp\n" );
stack_words = 2; stack_words = 2;
if (needs_ldt) if (needs_ldt)
{ {
fprintf( outfile, "\tpushl %%esi\n" ); output( "\tpushl %%esi\n" );
stack_words++; stack_words++;
if (UsePIC) if (UsePIC)
{ {
fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") ); output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
fprintf( outfile, "1:\tmovl wine_ldt_copy_ptr-1b(%%eax),%%esi\n" ); output( "1:\tmovl wine_ldt_copy_ptr-1b(%%eax),%%esi\n" );
} }
else else
fprintf( outfile, "\tmovl $%s,%%esi\n", asm_name("wine_ldt_copy") ); output( "\tmovl $%s,%%esi\n", asm_name("wine_ldt_copy") );
} }
/* preserve 16-byte stack alignment */ /* preserve 16-byte stack alignment */
stack_words += strlen(args); stack_words += strlen(args);
if ((odp->flags & FLAG_REGISTER) || (odp->type == TYPE_VARARGS)) stack_words++; if ((odp->flags & FLAG_REGISTER) || (odp->type == TYPE_VARARGS)) stack_words++;
if (stack_words % 4) fprintf( outfile, "\tsubl $%d,%%esp\n", 16 - 4 * (stack_words % 4) ); if (stack_words % 4) output( "\tsubl $%d,%%esp\n", 16 - 4 * (stack_words % 4) );
if (args[0] || odp->type == TYPE_VARARGS) if (args[0] || odp->type == TYPE_VARARGS)
fprintf( outfile, "\tmovl 12(%%ebp),%%ecx\n" ); /* args */ output( "\tmovl 12(%%ebp),%%ecx\n" ); /* args */
if (odp->flags & FLAG_REGISTER) if (odp->flags & FLAG_REGISTER)
{ {
fprintf( outfile, "\tpushl 16(%%ebp)\n" ); /* context */ output( "\tpushl 16(%%ebp)\n" ); /* context */
} }
else if (odp->type == TYPE_VARARGS) else if (odp->type == TYPE_VARARGS)
{ {
fprintf( outfile, "\tleal %d(%%ecx),%%eax\n", argsize ); output( "\tleal %d(%%ecx),%%eax\n", argsize );
fprintf( outfile, "\tpushl %%eax\n" ); /* va_list16 */ output( "\tpushl %%eax\n" ); /* va_list16 */
} }
pos = (odp->type == TYPE_PASCAL) ? 0 : argsize; pos = (odp->type == TYPE_PASCAL) ? 0 : argsize;
@ -336,33 +337,33 @@ static void output_call16_function( FILE *outfile, ORDDEF *odp )
{ {
case 'w': /* word */ case 'w': /* word */
if (odp->type != TYPE_PASCAL) pos -= 2; if (odp->type != TYPE_PASCAL) pos -= 2;
fprintf( outfile, "\tmovzwl %d(%%ecx),%%eax\n", pos ); output( "\tmovzwl %d(%%ecx),%%eax\n", pos );
fprintf( outfile, "\tpushl %%eax\n" ); output( "\tpushl %%eax\n" );
if (odp->type == TYPE_PASCAL) pos += 2; if (odp->type == TYPE_PASCAL) pos += 2;
break; break;
case 's': /* s_word */ case 's': /* s_word */
if (odp->type != TYPE_PASCAL) pos -= 2; if (odp->type != TYPE_PASCAL) pos -= 2;
fprintf( outfile, "\tmovswl %d(%%ecx),%%eax\n", pos ); output( "\tmovswl %d(%%ecx),%%eax\n", pos );
fprintf( outfile, "\tpushl %%eax\n" ); output( "\tpushl %%eax\n" );
if (odp->type == TYPE_PASCAL) pos += 2; if (odp->type == TYPE_PASCAL) pos += 2;
break; break;
case 'l': /* long or segmented pointer */ case 'l': /* long or segmented pointer */
case 'T': /* segmented pointer to null-terminated string */ case 'T': /* segmented pointer to null-terminated string */
if (odp->type != TYPE_PASCAL) pos -= 4; if (odp->type != TYPE_PASCAL) pos -= 4;
fprintf( outfile, "\tpushl %d(%%ecx)\n", pos ); output( "\tpushl %d(%%ecx)\n", pos );
if (odp->type == TYPE_PASCAL) pos += 4; if (odp->type == TYPE_PASCAL) pos += 4;
break; break;
case 'p': /* linear pointer */ case 'p': /* linear pointer */
case 't': /* linear pointer to null-terminated string */ case 't': /* linear pointer to null-terminated string */
if (odp->type != TYPE_PASCAL) pos -= 4; if (odp->type != TYPE_PASCAL) pos -= 4;
fprintf( outfile, "\tmovzwl %d(%%ecx),%%edx\n", pos + 2 ); /* sel */ output( "\tmovzwl %d(%%ecx),%%edx\n", pos + 2 ); /* sel */
fprintf( outfile, "\tshr $3,%%edx\n" ); output( "\tshr $3,%%edx\n" );
fprintf( outfile, "\tmovzwl %d(%%ecx),%%eax\n", pos ); /* offset */ output( "\tmovzwl %d(%%ecx),%%eax\n", pos ); /* offset */
fprintf( outfile, "\taddl (%%esi,%%edx,4),%%eax\n" ); output( "\taddl (%%esi,%%edx,4),%%eax\n" );
fprintf( outfile, "\tpushl %%eax\n" ); output( "\tpushl %%eax\n" );
if (odp->type == TYPE_PASCAL) pos += 4; if (odp->type == TYPE_PASCAL) pos += 4;
break; break;
@ -371,14 +372,13 @@ static void output_call16_function( FILE *outfile, ORDDEF *odp )
} }
} }
fprintf( outfile, "\tcall *8(%%ebp)\n" ); output( "\tcall *8(%%ebp)\n" );
if (needs_ldt) fprintf( outfile, "\tmovl -4(%%ebp),%%esi\n" ); if (needs_ldt) output( "\tmovl -4(%%ebp),%%esi\n" );
if (odp->flags & FLAG_RET16) fprintf( outfile, "\tmovzwl %%ax,%%eax\n" );
fprintf( outfile, "\tleave\n" ); output( "\tleave\n" );
fprintf( outfile, "\tret\n" ); output( "\tret\n" );
output_function_size( outfile, name ); output_function_size( name );
} }
@ -450,72 +450,72 @@ static int sort_func_list( ORDDEF **list, int count,
* *
* Output the dll initialization code. * Output the dll initialization code.
*/ */
static void output_init_code( FILE *outfile, const DLLSPEC *spec, const char *header_name ) static void output_init_code( const DLLSPEC *spec, const char *header_name )
{ {
char name[80]; char name[80];
sprintf( name, ".L__wine_spec_%s_init", make_c_identifier(spec->dll_name) ); sprintf( name, ".L__wine_spec_%s_init", make_c_identifier(spec->dll_name) );
fprintf( outfile, "\n/* dll initialization code */\n\n" ); output( "\n/* dll initialization code */\n\n" );
fprintf( outfile, "\t.text\n" ); output( "\t.text\n" );
fprintf( outfile, "\t.align 4\n" ); output( "\t.align 4\n" );
fprintf( outfile, "\t%s\n", func_declaration(name) ); output( "\t%s\n", func_declaration(name) );
fprintf( outfile, "%s:\n", name ); output( "%s:\n", name );
fprintf( outfile, "subl $4,%%esp\n" ); output( "subl $4,%%esp\n" );
if (UsePIC) if (UsePIC)
{ {
fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") ); output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
fprintf( outfile, "1:\tleal .L__wine_spec_file_name-1b(%%eax),%%ecx\n" ); output( "1:\tleal .L__wine_spec_file_name-1b(%%eax),%%ecx\n" );
fprintf( outfile, "\tpushl %%ecx\n" ); output( "\tpushl %%ecx\n" );
fprintf( outfile, "\tleal %s-1b(%%eax),%%ecx\n", header_name ); output( "\tleal %s-1b(%%eax),%%ecx\n", header_name );
fprintf( outfile, "\tpushl %%ecx\n" ); output( "\tpushl %%ecx\n" );
} }
else else
{ {
fprintf( outfile, "\tpushl $.L__wine_spec_file_name\n" ); output( "\tpushl $.L__wine_spec_file_name\n" );
fprintf( outfile, "\tpushl $%s\n", header_name ); output( "\tpushl $%s\n", header_name );
} }
fprintf( outfile, "\tcall %s\n", asm_name("__wine_dll_register_16") ); output( "\tcall %s\n", asm_name("__wine_dll_register_16") );
fprintf( outfile, "\taddl $12,%%esp\n" ); output( "\taddl $12,%%esp\n" );
fprintf( outfile, "\tret\n" ); output( "\tret\n" );
output_function_size( outfile, name ); output_function_size( name );
sprintf( name, ".L__wine_spec_%s_fini", make_c_identifier(spec->dll_name) ); sprintf( name, ".L__wine_spec_%s_fini", make_c_identifier(spec->dll_name) );
fprintf( outfile, "\t.align 4\n" ); output( "\t.align 4\n" );
fprintf( outfile, "\t%s\n", func_declaration(name) ); output( "\t%s\n", func_declaration(name) );
fprintf( outfile, "%s:\n", name ); output( "%s:\n", name );
fprintf( outfile, "subl $8,%%esp\n" ); output( "subl $8,%%esp\n" );
if (UsePIC) if (UsePIC)
{ {
fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") ); output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
fprintf( outfile, "1:\tleal %s-1b(%%eax),%%ecx\n", header_name ); output( "1:\tleal %s-1b(%%eax),%%ecx\n", header_name );
fprintf( outfile, "\tpushl %%ecx\n" ); output( "\tpushl %%ecx\n" );
} }
else else
{ {
fprintf( outfile, "\tpushl $%s\n", header_name ); output( "\tpushl $%s\n", header_name );
} }
fprintf( outfile, "\tcall %s\n", asm_name("__wine_dll_unregister_16") ); output( "\tcall %s\n", asm_name("__wine_dll_unregister_16") );
fprintf( outfile, "\taddl $12,%%esp\n" ); output( "\taddl $12,%%esp\n" );
fprintf( outfile, "\tret\n" ); output( "\tret\n" );
output_function_size( outfile, name ); output_function_size( name );
if (target_platform == PLATFORM_APPLE) if (target_platform == PLATFORM_APPLE)
{ {
fprintf( outfile, "\t.mod_init_func\n" ); output( "\t.mod_init_func\n" );
fprintf( outfile, "\t.align %d\n", get_alignment(4) ); output( "\t.align %d\n", get_alignment(4) );
fprintf( outfile, "\t.long .L__wine_spec_%s_init\n", make_c_identifier(spec->dll_name) ); output( "\t.long .L__wine_spec_%s_init\n", make_c_identifier(spec->dll_name) );
fprintf( outfile, "\t.mod_term_func\n" ); output( "\t.mod_term_func\n" );
fprintf( outfile, "\t.align %d\n", get_alignment(4) ); output( "\t.align %d\n", get_alignment(4) );
fprintf( outfile, "\t.long .L__wine_spec_%s_fini\n", make_c_identifier(spec->dll_name) ); output( "\t.long .L__wine_spec_%s_fini\n", make_c_identifier(spec->dll_name) );
} }
else else
{ {
fprintf( outfile, "\t.section \".init\",\"ax\"\n" ); output( "\t.section \".init\",\"ax\"\n" );
fprintf( outfile, "\tcall .L__wine_spec_%s_init\n", make_c_identifier(spec->dll_name) ); output( "\tcall .L__wine_spec_%s_init\n", make_c_identifier(spec->dll_name) );
fprintf( outfile, "\t.section \".fini\",\"ax\"\n" ); output( "\t.section \".fini\",\"ax\"\n" );
fprintf( outfile, "\tcall .L__wine_spec_%s_fini\n", make_c_identifier(spec->dll_name) ); output( "\tcall .L__wine_spec_%s_fini\n", make_c_identifier(spec->dll_name) );
} }
} }
@ -525,7 +525,7 @@ static void output_init_code( FILE *outfile, const DLLSPEC *spec, const char *he
* *
* Build a Win16 assembly file from a spec file. * Build a Win16 assembly file from a spec file.
*/ */
void BuildSpec16File( FILE *outfile, DLLSPEC *spec ) void BuildSpec16File( DLLSPEC *spec )
{ {
ORDDEF **typelist; ORDDEF **typelist;
int i, j, nb_funcs; int i, j, nb_funcs;
@ -533,7 +533,7 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
/* File header */ /* File header */
output_standard_file_header( outfile ); output_standard_file_header();
if (!spec->dll_name) /* set default name from file name */ if (!spec->dll_name) /* set default name from file name */
{ {
@ -558,135 +558,135 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
/* Output the module structure */ /* Output the module structure */
sprintf( header_name, "__wine_spec_%s_dos_header", make_c_identifier(spec->dll_name) ); sprintf( header_name, "__wine_spec_%s_dos_header", make_c_identifier(spec->dll_name) );
fprintf( outfile, "\n/* module data */\n\n" ); output( "\n/* module data */\n\n" );
fprintf( outfile, "\t.data\n" ); output( "\t.data\n" );
fprintf( outfile, "\t.align %d\n", get_alignment(4) ); output( "\t.align %d\n", get_alignment(4) );
fprintf( outfile, "%s:\n", header_name ); output( "%s:\n", header_name );
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), /* e_magic */ output( "\t%s 0x%04x\n", get_asm_short_keyword(), /* e_magic */
IMAGE_DOS_SIGNATURE ); IMAGE_DOS_SIGNATURE );
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_cblp */ output( "\t%s 0\n", get_asm_short_keyword() ); /* e_cblp */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_cp */ output( "\t%s 0\n", get_asm_short_keyword() ); /* e_cp */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_crlc */ output( "\t%s 0\n", get_asm_short_keyword() ); /* e_crlc */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_cparhdr */ output( "\t%s 0\n", get_asm_short_keyword() ); /* e_cparhdr */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_minalloc */ output( "\t%s 0\n", get_asm_short_keyword() ); /* e_minalloc */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_maxalloc */ output( "\t%s 0\n", get_asm_short_keyword() ); /* e_maxalloc */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_ss */ output( "\t%s 0\n", get_asm_short_keyword() ); /* e_ss */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_sp */ output( "\t%s 0\n", get_asm_short_keyword() ); /* e_sp */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_csum */ output( "\t%s 0\n", get_asm_short_keyword() ); /* e_csum */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_ip */ output( "\t%s 0\n", get_asm_short_keyword() ); /* e_ip */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_cs */ output( "\t%s 0\n", get_asm_short_keyword() ); /* e_cs */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_lfarlc */ output( "\t%s 0\n", get_asm_short_keyword() ); /* e_lfarlc */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_ovno */ output( "\t%s 0\n", get_asm_short_keyword() ); /* e_ovno */
fprintf( outfile, "\t%s 0,0,0,0\n", get_asm_short_keyword() ); /* e_res */ output( "\t%s 0,0,0,0\n", get_asm_short_keyword() ); /* e_res */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_oemid */ output( "\t%s 0\n", get_asm_short_keyword() ); /* e_oemid */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_oeminfo */ output( "\t%s 0\n", get_asm_short_keyword() ); /* e_oeminfo */
fprintf( outfile, "\t%s 0,0,0,0,0,0,0,0,0,0\n", get_asm_short_keyword() ); /* e_res2 */ output( "\t%s 0,0,0,0,0,0,0,0,0,0\n", get_asm_short_keyword() ); /* e_res2 */
fprintf( outfile, "\t.long .L__wine_spec_ne_header-%s\n", header_name ); /* e_lfanew */ output( "\t.long .L__wine_spec_ne_header-%s\n", header_name ); /* e_lfanew */
fprintf( outfile, ".L__wine_spec_ne_header:\n" ); output( ".L__wine_spec_ne_header:\n" );
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), /* ne_magic */ output( "\t%s 0x%04x\n", get_asm_short_keyword(), /* ne_magic */
IMAGE_OS2_SIGNATURE ); IMAGE_OS2_SIGNATURE );
fprintf( outfile, "\t.byte 0\n" ); /* ne_ver */ output( "\t.byte 0\n" ); /* ne_ver */
fprintf( outfile, "\t.byte 0\n" ); /* ne_rev */ output( "\t.byte 0\n" ); /* ne_rev */
fprintf( outfile, "\t%s .L__wine_spec_ne_enttab-.L__wine_spec_ne_header\n", /* ne_enttab */ output( "\t%s .L__wine_spec_ne_enttab-.L__wine_spec_ne_header\n", /* ne_enttab */
get_asm_short_keyword() ); get_asm_short_keyword() );
fprintf( outfile, "\t%s .L__wine_spec_ne_enttab_end-.L__wine_spec_ne_enttab\n", /* ne_cbenttab */ output( "\t%s .L__wine_spec_ne_enttab_end-.L__wine_spec_ne_enttab\n", /* ne_cbenttab */
get_asm_short_keyword() ); get_asm_short_keyword() );
fprintf( outfile, "\t.long 0\n" ); /* ne_crc */ output( "\t.long 0\n" ); /* ne_crc */
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), /* ne_flags */ output( "\t%s 0x%04x\n", get_asm_short_keyword(), /* ne_flags */
NE_FFLAGS_SINGLEDATA | NE_FFLAGS_LIBMODULE ); NE_FFLAGS_SINGLEDATA | NE_FFLAGS_LIBMODULE );
fprintf( outfile, "\t%s 2\n", get_asm_short_keyword() ); /* ne_autodata */ output( "\t%s 2\n", get_asm_short_keyword() ); /* ne_autodata */
fprintf( outfile, "\t%s %u\n", get_asm_short_keyword(), spec->heap_size ); /* ne_heap */ output( "\t%s %u\n", get_asm_short_keyword(), spec->heap_size ); /* ne_heap */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_stack */ output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_stack */
fprintf( outfile, "\t.long 0\n" ); /* ne_csip */ output( "\t.long 0\n" ); /* ne_csip */
fprintf( outfile, "\t.long 0\n" ); /* ne_sssp */ output( "\t.long 0\n" ); /* ne_sssp */
fprintf( outfile, "\t%s 2\n", get_asm_short_keyword() ); /* ne_cseg */ output( "\t%s 2\n", get_asm_short_keyword() ); /* ne_cseg */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_cmod */ output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_cmod */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_cbnrestab */ output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_cbnrestab */
fprintf( outfile, "\t%s .L__wine_spec_ne_segtab-.L__wine_spec_ne_header\n", /* ne_segtab */ output( "\t%s .L__wine_spec_ne_segtab-.L__wine_spec_ne_header\n", /* ne_segtab */
get_asm_short_keyword() ); get_asm_short_keyword() );
fprintf( outfile, "\t%s .L__wine_spec_ne_rsrctab-.L__wine_spec_ne_header\n", /* ne_rsrctab */ output( "\t%s .L__wine_spec_ne_rsrctab-.L__wine_spec_ne_header\n", /* ne_rsrctab */
get_asm_short_keyword() ); get_asm_short_keyword() );
fprintf( outfile, "\t%s .L__wine_spec_ne_restab-.L__wine_spec_ne_header\n", /* ne_restab */ output( "\t%s .L__wine_spec_ne_restab-.L__wine_spec_ne_header\n", /* ne_restab */
get_asm_short_keyword() ); get_asm_short_keyword() );
fprintf( outfile, "\t%s .L__wine_spec_ne_modtab-.L__wine_spec_ne_header\n", /* ne_modtab */ output( "\t%s .L__wine_spec_ne_modtab-.L__wine_spec_ne_header\n", /* ne_modtab */
get_asm_short_keyword() ); get_asm_short_keyword() );
fprintf( outfile, "\t%s .L__wine_spec_ne_imptab-.L__wine_spec_ne_header\n", /* ne_imptab */ output( "\t%s .L__wine_spec_ne_imptab-.L__wine_spec_ne_header\n", /* ne_imptab */
get_asm_short_keyword() ); get_asm_short_keyword() );
fprintf( outfile, "\t.long 0\n" ); /* ne_nrestab */ output( "\t.long 0\n" ); /* ne_nrestab */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_cmovent */ output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_cmovent */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_align */ output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_align */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_cres */ output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_cres */
fprintf( outfile, "\t.byte 0x%02x\n", NE_OSFLAGS_WINDOWS ); /* ne_exetyp */ output( "\t.byte 0x%02x\n", NE_OSFLAGS_WINDOWS ); /* ne_exetyp */
fprintf( outfile, "\t.byte 0x%02x\n", NE_AFLAGS_FASTLOAD ); /* ne_flagsothers */ output( "\t.byte 0x%02x\n", NE_AFLAGS_FASTLOAD ); /* ne_flagsothers */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_pretthunks */ output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_pretthunks */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_psegrefbytes */ output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_psegrefbytes */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_swaparea */ output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_swaparea */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_expver */ output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_expver */
/* segment table */ /* segment table */
fprintf( outfile, "\n.L__wine_spec_ne_segtab:\n" ); output( "\n.L__wine_spec_ne_segtab:\n" );
/* code segment entry */ /* code segment entry */
fprintf( outfile, "\t%s .L__wine_spec_code_segment-%s\n", /* filepos */ output( "\t%s .L__wine_spec_code_segment-%s\n", /* filepos */
get_asm_short_keyword(), header_name ); get_asm_short_keyword(), header_name );
fprintf( outfile, "\t%s .L__wine_spec_code_segment_end-.L__wine_spec_code_segment\n", /* size */ output( "\t%s .L__wine_spec_code_segment_end-.L__wine_spec_code_segment\n", /* size */
get_asm_short_keyword() ); get_asm_short_keyword() );
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), NE_SEGFLAGS_32BIT ); /* flags */ output( "\t%s 0x%04x\n", get_asm_short_keyword(), NE_SEGFLAGS_32BIT ); /* flags */
fprintf( outfile, "\t%s .L__wine_spec_code_segment_end-.L__wine_spec_code_segment\n", /* minsize */ output( "\t%s .L__wine_spec_code_segment_end-.L__wine_spec_code_segment\n", /* minsize */
get_asm_short_keyword() ); get_asm_short_keyword() );
/* data segment entry */ /* data segment entry */
fprintf( outfile, "\t%s .L__wine_spec_data_segment-%s\n", /* filepos */ output( "\t%s .L__wine_spec_data_segment-%s\n", /* filepos */
get_asm_short_keyword(), header_name ); get_asm_short_keyword(), header_name );
fprintf( outfile, "\t%s .L__wine_spec_data_segment_end-.L__wine_spec_data_segment\n", /* size */ output( "\t%s .L__wine_spec_data_segment_end-.L__wine_spec_data_segment\n", /* size */
get_asm_short_keyword() ); get_asm_short_keyword() );
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), NE_SEGFLAGS_DATA ); /* flags */ output( "\t%s 0x%04x\n", get_asm_short_keyword(), NE_SEGFLAGS_DATA ); /* flags */
fprintf( outfile, "\t%s .L__wine_spec_data_segment_end-.L__wine_spec_data_segment\n", /* minsize */ output( "\t%s .L__wine_spec_data_segment_end-.L__wine_spec_data_segment\n", /* minsize */
get_asm_short_keyword() ); get_asm_short_keyword() );
/* resource directory */ /* resource directory */
output_res16_directory( outfile, spec, header_name ); output_res16_directory( spec, header_name );
/* resident names table */ /* resident names table */
fprintf( outfile, "\n\t.align %d\n", get_alignment(2) ); output( "\n\t.align %d\n", get_alignment(2) );
fprintf( outfile, ".L__wine_spec_ne_restab:\n" ); output( ".L__wine_spec_ne_restab:\n" );
output_resident_name( outfile, spec->dll_name, 0 ); output_resident_name( spec->dll_name, 0 );
for (i = 1; i <= spec->limit; i++) for (i = 1; i <= spec->limit; i++)
{ {
ORDDEF *odp = spec->ordinals[i]; ORDDEF *odp = spec->ordinals[i];
if (!odp || !odp->name[0]) continue; if (!odp || !odp->name[0]) continue;
output_resident_name( outfile, odp->name, i ); output_resident_name( odp->name, i );
} }
fprintf( outfile, "\t.byte 0\n" ); output( "\t.byte 0\n" );
/* imported names table */ /* imported names table */
fprintf( outfile, "\n\t.align %d\n", get_alignment(2) ); output( "\n\t.align %d\n", get_alignment(2) );
fprintf( outfile, ".L__wine_spec_ne_modtab:\n" ); output( ".L__wine_spec_ne_modtab:\n" );
fprintf( outfile, ".L__wine_spec_ne_imptab:\n" ); output( ".L__wine_spec_ne_imptab:\n" );
fprintf( outfile, "\t.byte 0,0\n" ); output( "\t.byte 0,0\n" );
/* entry table */ /* entry table */
fprintf( outfile, "\n.L__wine_spec_ne_enttab:\n" ); output( "\n.L__wine_spec_ne_enttab:\n" );
output_entry_table( outfile, spec ); output_entry_table( spec );
fprintf( outfile, ".L__wine_spec_ne_enttab_end:\n" ); output( ".L__wine_spec_ne_enttab_end:\n" );
/* code segment */ /* code segment */
fprintf( outfile, "\n\t.align %d\n", get_alignment(2) ); output( "\n\t.align %d\n", get_alignment(2) );
fprintf( outfile, ".L__wine_spec_code_segment:\n" ); output( ".L__wine_spec_code_segment:\n" );
for ( i = 0; i < nb_funcs; i++ ) for ( i = 0; i < nb_funcs; i++ )
{ {
unsigned int arg_types[2]; unsigned int arg_types[2];
int j, nop_words, argsize = 0; int nop_words, argsize = 0;
if ( typelist[i]->type == TYPE_PASCAL ) if ( typelist[i]->type == TYPE_PASCAL )
argsize = get_function_argsize( typelist[i] ); argsize = get_function_argsize( typelist[i] );
@ -709,9 +709,9 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
} }
if (typelist[i]->type == TYPE_VARARGS) arg_types[j / 10] |= ARG_VARARG << (3 * (j % 10)); if (typelist[i]->type == TYPE_VARARGS) arg_types[j / 10] |= ARG_VARARG << (3 * (j % 10));
fprintf( outfile, ".L__wine_spec_callfrom16_%s:\n", get_callfrom16_name(typelist[i]) ); output( ".L__wine_spec_callfrom16_%s:\n", get_callfrom16_name(typelist[i]) );
fprintf( outfile, "\tpushl $.L__wine_spec_call16_%s\n", get_relay_name(typelist[i]) ); output( "\tpushl $.L__wine_spec_call16_%s\n", get_relay_name(typelist[i]) );
fprintf( outfile, "\tlcall $0,$0\n" ); output( "\tlcall $0,$0\n" );
if (typelist[i]->flags & FLAG_REGISTER) if (typelist[i]->flags & FLAG_REGISTER)
{ {
@ -719,90 +719,91 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
} }
else if (typelist[i]->flags & FLAG_RET16) else if (typelist[i]->flags & FLAG_RET16)
{ {
fprintf( outfile, "\torw %%ax,%%ax\n" ); output( "\torw %%ax,%%ax\n" );
fprintf( outfile, "\tnop\n" ); /* so that the lretw is aligned */ output( "\tnop\n" ); /* so that the lretw is aligned */
nop_words = 2; nop_words = 2;
} }
else else
{ {
fprintf( outfile, "shld $16,%%eax,%%edx\n" ); output( "\tshld $16,%%eax,%%edx\n" );
fprintf( outfile, "orl %%eax,%%eax\n" ); output( "\torl %%eax,%%eax\n" );
nop_words = 1; nop_words = 1;
} }
if (argsize) if (argsize)
{ {
fprintf( outfile, "lretw $%u\n", argsize ); output( "\tlretw $%u\n", argsize );
nop_words--; nop_words--;
} }
else fprintf( outfile, "lretw\n" ); else output( "\tlretw\n" );
if (nop_words) fprintf( outfile, "\t%s\n", nop_sequence[nop_words-1] ); if (nop_words) output( "\t%s\n", nop_sequence[nop_words-1] );
/* the movl is here so that the code contains only valid instructions, */ /* the movl is here so that the code contains only valid instructions, */
/* it's never actually executed, we only care about the arg_types[] values */ /* it's never actually executed, we only care about the arg_types[] values */
fprintf( outfile, "\t%s 0x86c7\n", get_asm_short_keyword() ); output( "\t%s 0x86c7\n", get_asm_short_keyword() );
fprintf( outfile, "\t.long 0x%08x,0x%08x\n", arg_types[0], arg_types[1] ); output( "\t.long 0x%08x,0x%08x\n", arg_types[0], arg_types[1] );
} }
for (i = 0; i <= spec->limit; i++) for (i = 0; i <= spec->limit; i++)
{ {
ORDDEF *odp = spec->ordinals[i]; ORDDEF *odp = spec->ordinals[i];
if (!odp || !is_function( odp )) continue; if (!odp || !is_function( odp )) continue;
fprintf( outfile, ".L__wine_%s_%u:\n", make_c_identifier(spec->dll_name), i ); output( ".L__wine_%s_%u:\n", make_c_identifier(spec->dll_name), i );
fprintf( outfile, "\tpushw %%bp\n" ); output( "\tpushw %%bp\n" );
fprintf( outfile, "\tpushl $%s\n", output( "\tpushl $%s\n",
asm_name( odp->type == TYPE_STUB ? get_stub_name( odp, spec ) : odp->link_name )); asm_name( odp->type == TYPE_STUB ? get_stub_name( odp, spec ) : odp->link_name ));
fprintf( outfile, "\tcallw .L__wine_spec_callfrom16_%s\n", get_callfrom16_name( odp ) ); output( "\tcallw .L__wine_spec_callfrom16_%s\n", get_callfrom16_name( odp ) );
} }
fprintf( outfile, ".L__wine_spec_code_segment_end:\n" ); output( ".L__wine_spec_code_segment_end:\n" );
/* data segment */ /* data segment */
fprintf( outfile, "\n.L__wine_spec_data_segment:\n" ); output( "\n.L__wine_spec_data_segment:\n" );
fprintf( outfile, "\t.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n" ); /* instance data */ output( "\t.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n" ); /* instance data */
for (i = 0; i <= spec->limit; i++) for (i = 0; i <= spec->limit; i++)
{ {
ORDDEF *odp = spec->ordinals[i]; ORDDEF *odp = spec->ordinals[i];
if (!odp || odp->type != TYPE_VARIABLE) continue; if (!odp || odp->type != TYPE_VARIABLE) continue;
fprintf( outfile, ".L__wine_%s_%u:\n", make_c_identifier(spec->dll_name), i ); output( ".L__wine_%s_%u:\n", make_c_identifier(spec->dll_name), i );
fprintf( outfile, "\t.long " ); output( "\t.long " );
for (j = 0; j < odp->u.var.n_values-1; j++) for (j = 0; j < odp->u.var.n_values-1; j++)
fprintf( outfile, "0x%08x,", odp->u.var.values[j] ); output( "0x%08x,", odp->u.var.values[j] );
fprintf( outfile, "0x%08x\n", odp->u.var.values[j] ); output( "0x%08x\n", odp->u.var.values[j] );
} }
fprintf( outfile, ".L__wine_spec_data_segment_end:\n" ); output( ".L__wine_spec_data_segment_end:\n" );
/* resource data */ /* resource data */
if (spec->nb_resources) if (spec->nb_resources)
{ {
fprintf( outfile, "\n.L__wine_spec_resource_data:\n" ); output( "\n.L__wine_spec_resource_data:\n" );
output_res16_data( outfile, spec ); output_res16_data( spec );
} }
fprintf( outfile, "\t.byte 0\n" ); /* make sure the last symbol points to something */ output( "\t.byte 0\n" ); /* make sure the last symbol points to something */
/* relay functions */ /* relay functions */
nb_funcs = sort_func_list( typelist, nb_funcs, relay_type_compare ); nb_funcs = sort_func_list( typelist, nb_funcs, relay_type_compare );
if (nb_funcs) if (nb_funcs)
{ {
fprintf( outfile, "\n/* relay functions */\n\n" ); output( "\n/* relay functions */\n\n" );
fprintf( outfile, "\t.text\n" ); output( "\t.text\n" );
for ( i = 0; i < nb_funcs; i++ ) output_call16_function( outfile, typelist[i] ); for ( i = 0; i < nb_funcs; i++ ) output_call16_function( typelist[i] );
fprintf( outfile, "\t.data\n" ); output( "\t.data\n" );
fprintf( outfile, "wine_ldt_copy_ptr:\n" ); output( "wine_ldt_copy_ptr:\n" );
fprintf( outfile, "\t.long %s\n", asm_name("wine_ldt_copy") ); output( "\t.long %s\n", asm_name("wine_ldt_copy") );
} }
fprintf( outfile, "\n\t%s\n", get_asm_string_section() ); output( "\n\t%s\n", get_asm_string_section() );
fprintf( outfile, ".L__wine_spec_file_name:\n" ); output( ".L__wine_spec_file_name:\n" );
fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name ); output( "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name );
output_stubs( outfile, spec ); output_stubs( spec );
output_get_pc_thunk( outfile ); output_get_pc_thunk();
output_init_code( outfile, spec, header_name ); output_init_code( spec, header_name );
output_gnu_stack_note();
free( typelist ); free( typelist );
} }

View file

@ -19,10 +19,11 @@
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include "config.h" #include "config.h"
#include "wine/port.h"
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
@ -30,10 +31,7 @@
#include <string.h> #include <string.h>
#include "winglue.h" #include "winglue.h"
//#include "wine/exception.h"
#define EXCEPTION_WINE_STUB 0x80000100 /* stub entry point called */
#define EH_NONCONTINUABLE 0x01
#include "build.h" #include "build.h"
@ -52,7 +50,7 @@ static inline int needs_relay( const ORDDEF *odp )
/* check if dll will output relay thunks */ /* check if dll will output relay thunks */
int has_relays( DLLSPEC *spec ) int has_relays( DLLSPEC *spec )
{ {
unsigned int i; int i;
if (target_cpu != CPU_x86) return 0; if (target_cpu != CPU_x86) return 0;
@ -91,30 +89,31 @@ static const char *make_internal_name( const ORDDEF *odp, DLLSPEC *spec, const c
* *
* Output entry points for relay debugging * Output entry points for relay debugging
*/ */
static void output_relay_debug( FILE *outfile, DLLSPEC *spec ) static void output_relay_debug( DLLSPEC *spec )
{ {
unsigned int i, j, args, flags; int i;
unsigned int j, args, flags;
/* first the table of entry point offsets */ /* first the table of entry point offsets */
fprintf( outfile, "\t%s\n", get_asm_rodata_section() ); output( "\t%s\n", get_asm_rodata_section() );
fprintf( outfile, "\t.align %d\n", get_alignment(4) ); output( "\t.align %d\n", get_alignment(4) );
fprintf( outfile, ".L__wine_spec_relay_entry_point_offsets:\n" ); output( ".L__wine_spec_relay_entry_point_offsets:\n" );
for (i = spec->base; i <= spec->limit; i++) for (i = spec->base; i <= spec->limit; i++)
{ {
ORDDEF *odp = spec->ordinals[i]; ORDDEF *odp = spec->ordinals[i];
if (needs_relay( odp )) if (needs_relay( odp ))
fprintf( outfile, "\t.long .L__wine_spec_relay_entry_point_%d-__wine_spec_relay_entry_points\n", i ); output( "\t.long .L__wine_spec_relay_entry_point_%d-__wine_spec_relay_entry_points\n", i );
else else
fprintf( outfile, "\t.long 0\n" ); output( "\t.long 0\n" );
} }
/* then the table of argument types */ /* then the table of argument types */
fprintf( outfile, "\t.align %d\n", get_alignment(4) ); output( "\t.align %d\n", get_alignment(4) );
fprintf( outfile, ".L__wine_spec_relay_arg_types:\n" ); output( ".L__wine_spec_relay_arg_types:\n" );
for (i = spec->base; i <= spec->limit; i++) for (i = spec->base; i <= spec->limit; i++)
{ {
@ -129,14 +128,14 @@ static void output_relay_debug( FILE *outfile, DLLSPEC *spec )
if (odp->u.func.arg_types[j] == 'W') mask |= 2<< (j*2); if (odp->u.func.arg_types[j] == 'W') mask |= 2<< (j*2);
} }
} }
fprintf( outfile, "\t.long 0x%08x\n", mask ); output( "\t.long 0x%08x\n", mask );
} }
/* then the relay thunks */ /* then the relay thunks */
fprintf( outfile, "\t.text\n" ); output( "\t.text\n" );
fprintf( outfile, "__wine_spec_relay_entry_points:\n" ); output( "__wine_spec_relay_entry_points:\n" );
fprintf( outfile, "\tnop\n" ); /* to avoid 0 offset */ output( "\tnop\n" ); /* to avoid 0 offset */
for (i = spec->base; i <= spec->limit; i++) for (i = spec->base; i <= spec->limit; i++)
{ {
@ -144,39 +143,39 @@ static void output_relay_debug( FILE *outfile, DLLSPEC *spec )
if (!needs_relay( odp )) continue; if (!needs_relay( odp )) continue;
fprintf( outfile, "\t.align %d\n", get_alignment(4) ); output( "\t.align %d\n", get_alignment(4) );
fprintf( outfile, ".L__wine_spec_relay_entry_point_%d:\n", i ); output( ".L__wine_spec_relay_entry_point_%d:\n", i );
if (odp->flags & FLAG_REGISTER) if (odp->flags & FLAG_REGISTER)
fprintf( outfile, "\tpushl %%eax\n" ); output( "\tpushl %%eax\n" );
else else
fprintf( outfile, "\tpushl %%esp\n" ); output( "\tpushl %%esp\n" );
args = strlen(odp->u.func.arg_types); args = strlen(odp->u.func.arg_types);
flags = 0; flags = 0;
if (odp->flags & FLAG_RET64) flags |= 1; if (odp->flags & FLAG_RET64) flags |= 1;
if (odp->type == TYPE_STDCALL) flags |= 2; if (odp->type == TYPE_STDCALL) flags |= 2;
fprintf( outfile, "\tpushl $%u\n", (flags << 24) | (args << 16) | (i - spec->base) ); output( "\tpushl $%u\n", (flags << 24) | (args << 16) | (i - spec->base) );
if (UsePIC) if (UsePIC)
{ {
fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") ); output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
fprintf( outfile, "1:\tleal .L__wine_spec_relay_descr-1b(%%eax),%%eax\n" ); output( "1:\tleal .L__wine_spec_relay_descr-1b(%%eax),%%eax\n" );
} }
else fprintf( outfile, "\tmovl $.L__wine_spec_relay_descr,%%eax\n" ); else output( "\tmovl $.L__wine_spec_relay_descr,%%eax\n" );
fprintf( outfile, "\tpushl %%eax\n" ); output( "\tpushl %%eax\n" );
if (odp->flags & FLAG_REGISTER) if (odp->flags & FLAG_REGISTER)
{ {
fprintf( outfile, "\tcall *8(%%eax)\n" ); output( "\tcall *8(%%eax)\n" );
} }
else else
{ {
fprintf( outfile, "\tcall *4(%%eax)\n" ); output( "\tcall *4(%%eax)\n" );
if (odp->type == TYPE_STDCALL) if (odp->type == TYPE_STDCALL)
fprintf( outfile, "\tret $%u\n", args * get_ptr_size() ); output( "\tret $%u\n", args * get_ptr_size() );
else else
fprintf( outfile, "\tret\n" ); output( "\tret\n" );
} }
} }
} }
@ -186,46 +185,46 @@ static void output_relay_debug( FILE *outfile, DLLSPEC *spec )
* *
* Output the export table for a Win32 module. * Output the export table for a Win32 module.
*/ */
static void output_exports( FILE *outfile, DLLSPEC *spec ) static void output_exports( DLLSPEC *spec )
{ {
int i, fwd_size = 0; int i, fwd_size = 0;
int nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0; int nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
if (!nr_exports) return; if (!nr_exports) return;
fprintf( outfile, "\n/* export table */\n\n" ); output( "\n/* export table */\n\n" );
fprintf( outfile, "\t.data\n" ); output( "\t.data\n" );
fprintf( outfile, "\t.align %d\n", get_alignment(4) ); output( "\t.align %d\n", get_alignment(4) );
fprintf( outfile, ".L__wine_spec_exports:\n" ); output( ".L__wine_spec_exports:\n" );
/* export directory header */ /* export directory header */
fprintf( outfile, "\t.long 0\n" ); /* Characteristics */ output( "\t.long 0\n" ); /* Characteristics */
fprintf( outfile, "\t.long 0\n" ); /* TimeDateStamp */ output( "\t.long 0\n" ); /* TimeDateStamp */
fprintf( outfile, "\t.long 0\n" ); /* MajorVersion/MinorVersion */ output( "\t.long 0\n" ); /* MajorVersion/MinorVersion */
fprintf( outfile, "\t.long .L__wine_spec_exp_names-.L__wine_spec_rva_base\n" ); /* Name */ output( "\t.long .L__wine_spec_exp_names-.L__wine_spec_rva_base\n" ); /* Name */
fprintf( outfile, "\t.long %u\n", spec->base ); /* Base */ output( "\t.long %u\n", spec->base ); /* Base */
fprintf( outfile, "\t.long %u\n", nr_exports ); /* NumberOfFunctions */ output( "\t.long %u\n", nr_exports ); /* NumberOfFunctions */
fprintf( outfile, "\t.long %u\n", spec->nb_names ); /* NumberOfNames */ output( "\t.long %u\n", spec->nb_names ); /* NumberOfNames */
fprintf( outfile, "\t.long .L__wine_spec_exports_funcs-.L__wine_spec_rva_base\n" ); /* AddressOfFunctions */ output( "\t.long .L__wine_spec_exports_funcs-.L__wine_spec_rva_base\n" ); /* AddressOfFunctions */
if (spec->nb_names) if (spec->nb_names)
{ {
fprintf( outfile, "\t.long .L__wine_spec_exp_name_ptrs-.L__wine_spec_rva_base\n" ); /* AddressOfNames */ output( "\t.long .L__wine_spec_exp_name_ptrs-.L__wine_spec_rva_base\n" ); /* AddressOfNames */
fprintf( outfile, "\t.long .L__wine_spec_exp_ordinals-.L__wine_spec_rva_base\n" ); /* AddressOfNameOrdinals */ output( "\t.long .L__wine_spec_exp_ordinals-.L__wine_spec_rva_base\n" ); /* AddressOfNameOrdinals */
} }
else else
{ {
fprintf( outfile, "\t.long 0\n" ); /* AddressOfNames */ output( "\t.long 0\n" ); /* AddressOfNames */
fprintf( outfile, "\t.long 0\n" ); /* AddressOfNameOrdinals */ output( "\t.long 0\n" ); /* AddressOfNameOrdinals */
} }
/* output the function pointers */ /* output the function pointers */
fprintf( outfile, "\n.L__wine_spec_exports_funcs:\n" ); output( "\n.L__wine_spec_exports_funcs:\n" );
for (i = spec->base; i <= spec->limit; i++) for (i = spec->base; i <= spec->limit; i++)
{ {
ORDDEF *odp = spec->ordinals[i]; ORDDEF *odp = spec->ordinals[i];
if (!odp) fprintf( outfile, "\t.long 0\n" ); if (!odp) output( "\t%s 0\n", get_asm_ptr_keyword() );
else switch(odp->type) else switch(odp->type)
{ {
case TYPE_EXTERN: case TYPE_EXTERN:
@ -234,21 +233,21 @@ static void output_exports( FILE *outfile, DLLSPEC *spec )
case TYPE_CDECL: case TYPE_CDECL:
if (odp->flags & FLAG_FORWARD) if (odp->flags & FLAG_FORWARD)
{ {
fprintf( outfile, "\t%s .L__wine_spec_forwards+%u\n", get_asm_ptr_keyword(), fwd_size ); output( "\t%s .L__wine_spec_forwards+%u\n", get_asm_ptr_keyword(), fwd_size );
fwd_size += strlen(odp->link_name) + 1; fwd_size += strlen(odp->link_name) + 1;
} }
else if (odp->flags & FLAG_EXT_LINK) else if (odp->flags & FLAG_EXT_LINK)
{ {
fprintf( outfile, "\t%s %s_%s\n", output( "\t%s %s_%s\n",
get_asm_ptr_keyword(), asm_name("__wine_spec_ext_link"), odp->link_name ); get_asm_ptr_keyword(), asm_name("__wine_spec_ext_link"), odp->link_name );
} }
else else
{ {
fprintf( outfile, "\t%s %s\n", get_asm_ptr_keyword(), asm_name(odp->link_name) ); output( "\t%s %s\n", get_asm_ptr_keyword(), asm_name(odp->link_name) );
} }
break; break;
case TYPE_STUB: case TYPE_STUB:
fprintf( outfile, "\t%s %s\n", get_asm_ptr_keyword(), output( "\t%s %s\n", get_asm_ptr_keyword(),
asm_name( get_stub_name( odp, spec )) ); asm_name( get_stub_name( odp, spec )) );
break; break;
default: default:
@ -262,68 +261,68 @@ static void output_exports( FILE *outfile, DLLSPEC *spec )
int namepos = strlen(spec->file_name) + 1; int namepos = strlen(spec->file_name) + 1;
fprintf( outfile, "\n.L__wine_spec_exp_name_ptrs:\n" ); output( "\n.L__wine_spec_exp_name_ptrs:\n" );
for (i = 0; i < spec->nb_names; i++) for (i = 0; i < spec->nb_names; i++)
{ {
fprintf( outfile, "\t.long .L__wine_spec_exp_names+%u-.L__wine_spec_rva_base\n", namepos ); output( "\t.long .L__wine_spec_exp_names+%u-.L__wine_spec_rva_base\n", namepos );
namepos += strlen(spec->names[i]->name) + 1; namepos += strlen(spec->names[i]->name) + 1;
} }
/* output the function ordinals */ /* output the function ordinals */
fprintf( outfile, "\n.L__wine_spec_exp_ordinals:\n" ); output( "\n.L__wine_spec_exp_ordinals:\n" );
for (i = 0; i < spec->nb_names; i++) for (i = 0; i < spec->nb_names; i++)
{ {
fprintf( outfile, "\t%s %d\n", output( "\t%s %d\n",
get_asm_short_keyword(), spec->names[i]->ordinal - spec->base ); get_asm_short_keyword(), spec->names[i]->ordinal - spec->base );
} }
if (spec->nb_names % 2) if (spec->nb_names % 2)
{ {
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); output( "\t%s 0\n", get_asm_short_keyword() );
} }
} }
/* output the export name strings */ /* output the export name strings */
fprintf( outfile, "\n.L__wine_spec_exp_names:\n" ); output( "\n.L__wine_spec_exp_names:\n" );
fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name ); output( "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name );
for (i = 0; i < spec->nb_names; i++) for (i = 0; i < spec->nb_names; i++)
fprintf( outfile, "\t%s \"%s\"\n", output( "\t%s \"%s\"\n",
get_asm_string_keyword(), spec->names[i]->name ); get_asm_string_keyword(), spec->names[i]->name );
/* output forward strings */ /* output forward strings */
if (fwd_size) if (fwd_size)
{ {
fprintf( outfile, "\n.L__wine_spec_forwards:\n" ); output( "\n.L__wine_spec_forwards:\n" );
for (i = spec->base; i <= spec->limit; i++) for (i = spec->base; i <= spec->limit; i++)
{ {
ORDDEF *odp = spec->ordinals[i]; ORDDEF *odp = spec->ordinals[i];
if (odp && (odp->flags & FLAG_FORWARD)) if (odp && (odp->flags & FLAG_FORWARD))
fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), odp->link_name ); output( "\t%s \"%s\"\n", get_asm_string_keyword(), odp->link_name );
} }
} }
fprintf( outfile, "\t.align %d\n", get_alignment(get_ptr_size()) ); output( "\t.align %d\n", get_alignment(get_ptr_size()) );
fprintf( outfile, ".L__wine_spec_exports_end:\n" ); output( ".L__wine_spec_exports_end:\n" );
/* output relays */ /* output relays */
/* we only support relay debugging on i386 */ /* we only support relay debugging on i386 */
if (target_cpu != CPU_x86) if (target_cpu != CPU_x86)
{ {
fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() ); output( "\t%s 0\n", get_asm_ptr_keyword() );
return; return;
} }
fprintf( outfile, ".L__wine_spec_relay_descr:\n" ); output( ".L__wine_spec_relay_descr:\n" );
fprintf( outfile, "\t%s 0xdeb90001\n", get_asm_ptr_keyword() ); /* magic */ output( "\t%s 0xdeb90001\n", get_asm_ptr_keyword() ); /* magic */
fprintf( outfile, "\t%s 0,0\n", get_asm_ptr_keyword() ); /* relay funcs */ output( "\t%s 0,0\n", get_asm_ptr_keyword() ); /* relay funcs */
fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() ); /* private data */ output( "\t%s 0\n", get_asm_ptr_keyword() ); /* private data */
fprintf( outfile, "\t%s __wine_spec_relay_entry_points\n", get_asm_ptr_keyword() ); output( "\t%s __wine_spec_relay_entry_points\n", get_asm_ptr_keyword() );
fprintf( outfile, "\t%s .L__wine_spec_relay_entry_point_offsets\n", get_asm_ptr_keyword() ); output( "\t%s .L__wine_spec_relay_entry_point_offsets\n", get_asm_ptr_keyword() );
fprintf( outfile, "\t%s .L__wine_spec_relay_arg_types\n", get_asm_ptr_keyword() ); output( "\t%s .L__wine_spec_relay_arg_types\n", get_asm_ptr_keyword() );
output_relay_debug( outfile, spec ); output_relay_debug( spec );
} }
@ -332,7 +331,7 @@ static void output_exports( FILE *outfile, DLLSPEC *spec )
* *
* Output the functions for stub entry points * Output the functions for stub entry points
*/ */
static void output_stub_funcs( FILE *outfile, DLLSPEC *spec ) static void output_stub_funcs( DLLSPEC *spec )
{ {
int i; int i;
@ -354,13 +353,13 @@ static void output_stub_funcs( FILE *outfile, DLLSPEC *spec )
{ {
const ORDDEF *odp = &spec->entry_points[i]; const ORDDEF *odp = &spec->entry_points[i];
if (odp->type != TYPE_STUB) continue; if (odp->type != TYPE_STUB) continue;
fprintf( outfile, "void %s(void) ", make_internal_name( odp, spec, "stub" ) ); output( "void %s(void) ", make_internal_name( odp, spec, "stub" ) );
if (odp->name) if (odp->name)
fprintf( outfile, "{ __wine_spec_unimplemented_stub(__wine_spec_file_name, \"%s\"); }\n", odp->name ); output( "{ __wine_spec_unimplemented_stub(__wine_spec_file_name, \"%s\"); }\n", odp->name );
else if (odp->export_name) else if (odp->export_name)
fprintf( outfile, "{ __wine_spec_unimplemented_stub(__wine_spec_file_name, \"%s\"); }\n", odp->export_name ); output( "{ __wine_spec_unimplemented_stub(__wine_spec_file_name, \"%s\"); }\n", odp->export_name );
else else
fprintf( outfile, "{ __wine_spec_unimplemented_stub(__wine_spec_file_name, \"%d\"); }\n", odp->ordinal ); output( "{ __wine_spec_unimplemented_stub(__wine_spec_file_name, \"%d\"); }\n", odp->ordinal );
} }
} }
@ -370,33 +369,33 @@ static void output_stub_funcs( FILE *outfile, DLLSPEC *spec )
* *
* Output code for calling a dll constructor. * Output code for calling a dll constructor.
*/ */
static void output_asm_constructor( FILE *outfile, const char *constructor ) static void output_asm_constructor( const char *constructor )
{ {
if (target_platform == PLATFORM_APPLE) if (target_platform == PLATFORM_APPLE)
{ {
/* Mach-O doesn't have an init section */ /* Mach-O doesn't have an init section */
fprintf( outfile, "\n\t.mod_init_func\n" ); output( "\n\t.mod_init_func\n" );
fprintf( outfile, "\t.align %d\n", get_alignment(4) ); output( "\t.align %d\n", get_alignment(4) );
fprintf( outfile, "\t.long %s\n", asm_name(constructor) ); output( "\t.long %s\n", asm_name(constructor) );
} }
else else
{ {
fprintf( outfile, "\n\t.section \".init\",\"ax\"\n" ); output( "\n\t.section \".init\",\"ax\"\n" );
switch(target_cpu) switch(target_cpu)
{ {
case CPU_x86: case CPU_x86:
case CPU_x86_64: case CPU_x86_64:
fprintf( outfile, "\tcall %s\n", asm_name(constructor) ); output( "\tcall %s\n", asm_name(constructor) );
break; break;
case CPU_SPARC: case CPU_SPARC:
fprintf( outfile, "\tcall %s\n", asm_name(constructor) ); output( "\tcall %s\n", asm_name(constructor) );
fprintf( outfile, "\tnop\n" ); output( "\tnop\n" );
break; break;
case CPU_ALPHA: case CPU_ALPHA:
fprintf( outfile, "\tjsr $26,%s\n", asm_name(constructor) ); output( "\tjsr $26,%s\n", asm_name(constructor) );
break; break;
case CPU_POWERPC: case CPU_POWERPC:
fprintf( outfile, "\tbl %s\n", asm_name(constructor) ); output( "\tbl %s\n", asm_name(constructor) );
break; break;
} }
} }
@ -408,32 +407,32 @@ static void output_asm_constructor( FILE *outfile, const char *constructor )
* *
* Build a Win32 C file from a spec file. * Build a Win32 C file from a spec file.
*/ */
void BuildSpec32File( FILE *outfile, DLLSPEC *spec ) void BuildSpec32File( DLLSPEC *spec )
{ {
int machine = 0; int machine = 0;
unsigned int page_size = get_page_size(); unsigned int page_size = get_page_size();
resolve_imports( spec ); resolve_imports( spec );
output_standard_file_header( outfile ); output_standard_file_header();
/* Reserve some space for the PE header */ /* Reserve some space for the PE header */
fprintf( outfile, "\t.text\n" ); output( "\t.text\n" );
fprintf( outfile, "\t.align %d\n", get_alignment(page_size) ); output( "\t.align %d\n", get_alignment(page_size) );
fprintf( outfile, "__wine_spec_pe_header:\n" ); output( "__wine_spec_pe_header:\n" );
if (target_platform == PLATFORM_APPLE) if (target_platform == PLATFORM_APPLE)
fprintf( outfile, "\t.space 65536\n" ); output( "\t.space 65536\n" );
else else
fprintf( outfile, "\t.skip 65536\n" ); output( "\t.skip 65536\n" );
/* Output the NT header */ /* Output the NT header */
fprintf( outfile, "\n\t.data\n" ); output( "\n\t.data\n" );
fprintf( outfile, "\t.align %d\n", get_alignment(get_ptr_size()) ); output( "\t.align %d\n", get_alignment(get_ptr_size()) );
fprintf( outfile, "%s\n", asm_globl("__wine_spec_nt_header") ); output( "%s\n", asm_globl("__wine_spec_nt_header") );
fprintf( outfile, ".L__wine_spec_rva_base:\n" ); output( ".L__wine_spec_rva_base:\n" );
fprintf( outfile, "\t.long 0x%04x\n", IMAGE_NT_SIGNATURE ); /* Signature */ output( "\t.long 0x%04x\n", IMAGE_NT_SIGNATURE ); /* Signature */
switch(target_cpu) switch(target_cpu)
{ {
case CPU_x86: machine = IMAGE_FILE_MACHINE_I386; break; case CPU_x86: machine = IMAGE_FILE_MACHINE_I386; break;
@ -442,104 +441,105 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
case CPU_ALPHA: machine = IMAGE_FILE_MACHINE_ALPHA; break; case CPU_ALPHA: machine = IMAGE_FILE_MACHINE_ALPHA; break;
case CPU_SPARC: machine = IMAGE_FILE_MACHINE_UNKNOWN; break; case CPU_SPARC: machine = IMAGE_FILE_MACHINE_UNKNOWN; break;
} }
fprintf( outfile, "\t%s 0x%04x\n", /* Machine */ output( "\t%s 0x%04x\n", /* Machine */
get_asm_short_keyword(), machine ); get_asm_short_keyword(), machine );
fprintf( outfile, "\t%s 0\n", /* NumberOfSections */ output( "\t%s 0\n", /* NumberOfSections */
get_asm_short_keyword() ); get_asm_short_keyword() );
fprintf( outfile, "\t.long 0\n" ); /* TimeDateStamp */ output( "\t.long 0\n" ); /* TimeDateStamp */
fprintf( outfile, "\t.long 0\n" ); /* PointerToSymbolTable */ output( "\t.long 0\n" ); /* PointerToSymbolTable */
fprintf( outfile, "\t.long 0\n" ); /* NumberOfSymbols */ output( "\t.long 0\n" ); /* NumberOfSymbols */
fprintf( outfile, "\t%s %d\n", /* SizeOfOptionalHeader */ output( "\t%s %d\n", /* SizeOfOptionalHeader */
get_asm_short_keyword(), get_asm_short_keyword(),
get_ptr_size() == 8 ? IMAGE_SIZEOF_NT_OPTIONAL64_HEADER : IMAGE_SIZEOF_NT_OPTIONAL32_HEADER ); get_ptr_size() == 8 ? IMAGE_SIZEOF_NT_OPTIONAL64_HEADER : IMAGE_SIZEOF_NT_OPTIONAL32_HEADER );
fprintf( outfile, "\t%s 0x%04x\n", /* Characteristics */ output( "\t%s 0x%04x\n", /* Characteristics */
get_asm_short_keyword(), spec->characteristics ); get_asm_short_keyword(), spec->characteristics );
fprintf( outfile, "\t%s 0x%04x\n", /* Magic */ output( "\t%s 0x%04x\n", /* Magic */
get_asm_short_keyword(), get_asm_short_keyword(),
get_ptr_size() == 8 ? IMAGE_NT_OPTIONAL_HDR64_MAGIC : IMAGE_NT_OPTIONAL_HDR32_MAGIC ); get_ptr_size() == 8 ? IMAGE_NT_OPTIONAL_HDR64_MAGIC : IMAGE_NT_OPTIONAL_HDR32_MAGIC );
fprintf( outfile, "\t.byte 0\n" ); /* MajorLinkerVersion */ output( "\t.byte 0\n" ); /* MajorLinkerVersion */
fprintf( outfile, "\t.byte 0\n" ); /* MinorLinkerVersion */ output( "\t.byte 0\n" ); /* MinorLinkerVersion */
fprintf( outfile, "\t.long 0\n" ); /* SizeOfCode */ output( "\t.long 0\n" ); /* SizeOfCode */
fprintf( outfile, "\t.long 0\n" ); /* SizeOfInitializedData */ output( "\t.long 0\n" ); /* SizeOfInitializedData */
fprintf( outfile, "\t.long 0\n" ); /* SizeOfUninitializedData */ output( "\t.long 0\n" ); /* SizeOfUninitializedData */
/* note: we expand the AddressOfEntryPoint field on 64-bit by overwriting the BaseOfCode field */ /* note: we expand the AddressOfEntryPoint field on 64-bit by overwriting the BaseOfCode field */
fprintf( outfile, "\t%s %s\n", /* AddressOfEntryPoint */ output( "\t%s %s\n", /* AddressOfEntryPoint */
get_asm_ptr_keyword(), asm_name(spec->init_func) ); get_asm_ptr_keyword(), asm_name(spec->init_func) );
if (get_ptr_size() == 4) if (get_ptr_size() == 4)
{ {
fprintf( outfile, "\t.long 0\n" ); /* BaseOfCode */ output( "\t.long 0\n" ); /* BaseOfCode */
fprintf( outfile, "\t.long 0\n" ); /* BaseOfData */ output( "\t.long 0\n" ); /* BaseOfData */
} }
fprintf( outfile, "\t%s __wine_spec_pe_header\n", /* ImageBase */ output( "\t%s __wine_spec_pe_header\n", /* ImageBase */
get_asm_ptr_keyword() ); get_asm_ptr_keyword() );
fprintf( outfile, "\t.long %u\n", page_size ); /* SectionAlignment */ output( "\t.long %u\n", page_size ); /* SectionAlignment */
fprintf( outfile, "\t.long %u\n", page_size ); /* FileAlignment */ output( "\t.long %u\n", page_size ); /* FileAlignment */
fprintf( outfile, "\t%s 1,0\n", /* Major/MinorOperatingSystemVersion */ output( "\t%s 1,0\n", /* Major/MinorOperatingSystemVersion */
get_asm_short_keyword() ); get_asm_short_keyword() );
fprintf( outfile, "\t%s 0,0\n", /* Major/MinorImageVersion */ output( "\t%s 0,0\n", /* Major/MinorImageVersion */
get_asm_short_keyword() ); get_asm_short_keyword() );
fprintf( outfile, "\t%s %u,%u\n", /* Major/MinorSubsystemVersion */ output( "\t%s %u,%u\n", /* Major/MinorSubsystemVersion */
get_asm_short_keyword(), spec->subsystem_major, spec->subsystem_minor ); get_asm_short_keyword(), spec->subsystem_major, spec->subsystem_minor );
fprintf( outfile, "\t.long 0\n" ); /* Win32VersionValue */ output( "\t.long 0\n" ); /* Win32VersionValue */
fprintf( outfile, "\t.long %s-.L__wine_spec_rva_base\n", /* SizeOfImage */ output( "\t.long %s-.L__wine_spec_rva_base\n", /* SizeOfImage */
asm_name("_end") ); asm_name("_end") );
fprintf( outfile, "\t.long %u\n", page_size ); /* SizeOfHeaders */ output( "\t.long %u\n", page_size ); /* SizeOfHeaders */
fprintf( outfile, "\t.long 0\n" ); /* CheckSum */ output( "\t.long 0\n" ); /* CheckSum */
fprintf( outfile, "\t%s 0x%04x\n", /* Subsystem */ output( "\t%s 0x%04x\n", /* Subsystem */
get_asm_short_keyword(), spec->subsystem ); get_asm_short_keyword(), spec->subsystem );
fprintf( outfile, "\t%s 0\n", /* DllCharacteristics */ output( "\t%s 0x%04x\n", /* DllCharacteristics */
get_asm_short_keyword() ); get_asm_short_keyword(), spec->dll_characteristics );
fprintf( outfile, "\t%s %u,%u\n", /* SizeOfStackReserve/Commit */ output( "\t%s %u,%u\n", /* SizeOfStackReserve/Commit */
get_asm_ptr_keyword(), (spec->stack_size ? spec->stack_size : 1024) * 1024, page_size ); get_asm_ptr_keyword(), (spec->stack_size ? spec->stack_size : 1024) * 1024, page_size );
fprintf( outfile, "\t%s %u,%u\n", /* SizeOfHeapReserve/Commit */ output( "\t%s %u,%u\n", /* SizeOfHeapReserve/Commit */
get_asm_ptr_keyword(), (spec->heap_size ? spec->heap_size : 1024) * 1024, page_size ); get_asm_ptr_keyword(), (spec->heap_size ? spec->heap_size : 1024) * 1024, page_size );
fprintf( outfile, "\t.long 0\n" ); /* LoaderFlags */ output( "\t.long 0\n" ); /* LoaderFlags */
fprintf( outfile, "\t.long 16\n" ); /* NumberOfRvaAndSizes */ output( "\t.long 16\n" ); /* NumberOfRvaAndSizes */
if (spec->base <= spec->limit) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] */ if (spec->base <= spec->limit) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] */
fprintf( outfile, "\t.long .L__wine_spec_exports-.L__wine_spec_rva_base," output( "\t.long .L__wine_spec_exports-.L__wine_spec_rva_base,"
".L__wine_spec_exports_end-.L__wine_spec_exports\n" ); ".L__wine_spec_exports_end-.L__wine_spec_exports\n" );
else else
fprintf( outfile, "\t.long 0,0\n" ); output( "\t.long 0,0\n" );
if (has_imports()) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] */ if (has_imports()) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] */
fprintf( outfile, "\t.long .L__wine_spec_imports-.L__wine_spec_rva_base," output( "\t.long .L__wine_spec_imports-.L__wine_spec_rva_base,"
".L__wine_spec_imports_end-.L__wine_spec_imports\n" ); ".L__wine_spec_imports_end-.L__wine_spec_imports\n" );
else else
fprintf( outfile, "\t.long 0,0\n" ); output( "\t.long 0,0\n" );
if (spec->nb_resources) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] */ if (spec->nb_resources) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] */
fprintf( outfile, "\t.long .L__wine_spec_resources-.L__wine_spec_rva_base," output( "\t.long .L__wine_spec_resources-.L__wine_spec_rva_base,"
".L__wine_spec_resources_end-.L__wine_spec_resources\n" ); ".L__wine_spec_resources_end-.L__wine_spec_resources\n" );
else else
fprintf( outfile, "\t.long 0,0\n" ); output( "\t.long 0,0\n" );
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[3] */ output( "\t.long 0,0\n" ); /* DataDirectory[3] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[4] */ output( "\t.long 0,0\n" ); /* DataDirectory[4] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[5] */ output( "\t.long 0,0\n" ); /* DataDirectory[5] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[6] */ output( "\t.long 0,0\n" ); /* DataDirectory[6] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[7] */ output( "\t.long 0,0\n" ); /* DataDirectory[7] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[8] */ output( "\t.long 0,0\n" ); /* DataDirectory[8] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[9] */ output( "\t.long 0,0\n" ); /* DataDirectory[9] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[10] */ output( "\t.long 0,0\n" ); /* DataDirectory[10] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[11] */ output( "\t.long 0,0\n" ); /* DataDirectory[11] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[12] */ output( "\t.long 0,0\n" ); /* DataDirectory[12] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[13] */ output( "\t.long 0,0\n" ); /* DataDirectory[13] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[14] */ output( "\t.long 0,0\n" ); /* DataDirectory[14] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[15] */ output( "\t.long 0,0\n" ); /* DataDirectory[15] */
fprintf( outfile, "\n\t%s\n", get_asm_string_section() ); output( "\n\t%s\n", get_asm_string_section() );
fprintf( outfile, "%s\n", asm_globl("__wine_spec_file_name") ); output( "%s\n", asm_globl("__wine_spec_file_name") );
fprintf( outfile, ".L__wine_spec_file_name:\n" ); output( ".L__wine_spec_file_name:\n" );
fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name ); output( "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name );
if (target_platform == PLATFORM_APPLE) if (target_platform == PLATFORM_APPLE)
fprintf( outfile, "\t.lcomm %s,4\n", asm_name("_end") ); output( "\t.lcomm %s,4\n", asm_name("_end") );
output_stubs( outfile, spec ); output_stubs( spec );
output_exports( outfile, spec ); output_exports( spec );
output_imports( outfile, spec ); output_imports( spec );
output_resources( outfile, spec ); output_resources( spec );
output_asm_constructor( outfile, "__wine_spec_init_ctor" ); output_asm_constructor( "__wine_spec_init_ctor" );
output_gnu_stack_note();
} }
@ -548,20 +548,19 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
* *
* Build a Win32 def file from a spec file. * Build a Win32 def file from a spec file.
*/ */
void BuildDef32File( FILE *outfile, DLLSPEC *spec ) void BuildDef32File( DLLSPEC *spec )
{ {
const char *name; const char *name;
int i, total; int i, total;
if (spec_file_name) if (spec_file_name)
fprintf( outfile, "; File generated automatically from %s; do not edit!\n\n", output( "; File generated automatically from %s; do not edit!\n\n",
spec_file_name ); spec_file_name );
else else
fprintf( outfile, "; File generated automatically; do not edit!\n\n" ); output( "; File generated automatically; do not edit!\n\n" );
fprintf(outfile, "LIBRARY %s\n\n", spec->file_name); output( "LIBRARY %s\n\n", spec->file_name);
output( "EXPORTS\n");
fprintf(outfile, "EXPORTS\n");
/* Output the exports and relay entry points */ /* Output the exports and relay entry points */
@ -573,13 +572,13 @@ void BuildDef32File( FILE *outfile, DLLSPEC *spec )
if (!odp) continue; if (!odp) continue;
if (odp->name) name = odp->name; if (odp->name) name = odp->name;
else if (odp->type == TYPE_STUB) name = make_internal_name( odp, spec, "stub" );
else if (odp->export_name) name = odp->export_name; else if (odp->export_name) name = odp->export_name;
else name = make_internal_name( odp, spec, "noname_export" ); else continue;
if (!(odp->flags & FLAG_PRIVATE)) total++; if (!(odp->flags & FLAG_PRIVATE)) total++;
fprintf(outfile, " %s", name);
output( " %s", name );
switch(odp->type) switch(odp->type)
{ {
@ -590,20 +589,20 @@ void BuildDef32File( FILE *outfile, DLLSPEC *spec )
case TYPE_CDECL: case TYPE_CDECL:
/* try to reduce output */ /* try to reduce output */
if(strcmp(name, odp->link_name) || (odp->flags & FLAG_FORWARD)) if(strcmp(name, odp->link_name) || (odp->flags & FLAG_FORWARD))
fprintf(outfile, "=%s", odp->link_name); output( "=%s", odp->link_name );
break; break;
case TYPE_STDCALL: case TYPE_STDCALL:
{ {
int at_param = strlen(odp->u.func.arg_types) * get_ptr_size(); int at_param = strlen(odp->u.func.arg_types) * get_ptr_size();
if (!kill_at) fprintf(outfile, "@%d", at_param); if (!kill_at) output( "@%d", at_param );
if (odp->flags & FLAG_FORWARD) if (odp->flags & FLAG_FORWARD)
{ {
fprintf(outfile, "=%s", odp->link_name); output( "=%s", odp->link_name );
} }
else if (strcmp(name, odp->link_name)) /* try to reduce output */ else if (strcmp(name, odp->link_name)) /* try to reduce output */
{ {
fprintf(outfile, "=%s", odp->link_name); output( "=%s", odp->link_name );
if (!kill_at) fprintf(outfile, "@%d", at_param); if (!kill_at) output( "@%d", at_param );
} }
break; break;
} }
@ -620,30 +619,23 @@ void BuildDef32File( FILE *outfile, DLLSPEC *spec )
if (name != check && check != name + strlen(name) && if (name != check && check != name + strlen(name) &&
'@' == check[-1]) '@' == check[-1])
{ {
fprintf(outfile, "%s", check - 1); output("%s", check - 1);
} }
} }
if (NULL != odp->name) if (odp->name || odp->export_name)
{ {
fprintf(outfile, "=%s", make_internal_name( odp, spec, "stub" )); output("=%s", make_internal_name( odp, spec, "stub" ));
} }
break; break;
} }
default: default:
assert(0); assert(0);
} }
fprintf( outfile, " @%d", odp->ordinal ); output( " @%d", odp->ordinal );
#if 0 /* MinGW binutils cannot handle this correctly */ if (!odp->name || (odp->flags & FLAG_ORDINAL)) output( " NONAME" );
if (!odp->name) fprintf( outfile, " NONAME" ); if (is_data) output( " DATA" );
#else if (odp->flags & FLAG_PRIVATE) output( " PRIVATE" );
if (!odp->name && (odp->type == TYPE_STUB || odp->export_name)) fprintf( outfile, " NONAME" ); output( "\n" );
#endif
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" );
} }
if (!total) warning( "%s: Import library doesn't export anything\n", spec->file_name ); if (!total) warning( "%s: Import library doesn't export anything\n", spec->file_name );
} }
@ -654,34 +646,34 @@ void BuildDef32File( FILE *outfile, DLLSPEC *spec )
* *
* Build a PE DLL C file from a spec file. * Build a PE DLL C file from a spec file.
*/ */
void BuildPedllFile( FILE *outfile, DLLSPEC *spec ) void BuildPedllFile( DLLSPEC *spec )
{ {
int nr_exports; int nr_exports;
nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0; nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
output_standard_file_header( outfile ); output_standard_file_header();
fprintf( outfile, "#include <stdarg.h>\n"); output( "#include <stdarg.h>\n");
fprintf( outfile, "#include \"windef.h\"\n"); output( "#include \"windef.h\"\n");
fprintf( outfile, "#include \"winbase.h\"\n"); output( "#include \"winbase.h\"\n");
fprintf( outfile, "#include \"wine/config.h\"\n"); output( "#include \"wine/config.h\"\n");
fprintf( outfile, "#include \"wine/exception.h\"\n\n"); output( "#include \"wine/exception.h\"\n\n");
fprintf( outfile, "void __wine_spec_unimplemented_stub( const char *module, const char *function )\n"); output( "void __wine_spec_unimplemented_stub( const char *module, const char *function )\n");
fprintf( outfile, "{\n"); output( "{\n");
fprintf( outfile, " ULONG_PTR args[2];\n"); output( " ULONG_PTR args[2];\n");
fprintf( outfile, "\n"); output( "\n");
fprintf( outfile, " args[0] = (ULONG_PTR)module;\n"); output( " args[0] = (ULONG_PTR)module;\n");
fprintf( outfile, " args[1] = (ULONG_PTR)function;\n"); output( " args[1] = (ULONG_PTR)function;\n");
fprintf( outfile, " RaiseException( EXCEPTION_WINE_STUB, EH_NONCONTINUABLE, 2, args );\n"); output( " RaiseException( EXCEPTION_WINE_STUB, EH_NONCONTINUABLE, 2, args );\n");
fprintf( outfile, "}\n\n"); output( "}\n\n");
fprintf( outfile, "static const char __wine_spec_file_name[] = \"%s\";\n\n", spec->file_name ); output( "static const char __wine_spec_file_name[] = \"%s\";\n\n", spec->file_name );
if (nr_exports) if (nr_exports)
{ {
/* Output the stub functions */ /* Output the stub functions */
output_stub_funcs( outfile, spec ); output_stub_funcs( spec );
} }
} }

View file

@ -15,14 +15,11 @@
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include "config.h" #include "config.h"
#include "wine/port.h"
#if !defined(WIN32)
#undef strdup
#endif
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
@ -34,6 +31,7 @@
# include <unistd.h> # include <unistd.h>
#endif #endif
#include "winglue.h"
#include "build.h" #include "build.h"
#define MAX_TMP_FILES 8 #define MAX_TMP_FILES 8
@ -165,6 +163,18 @@ void warning( const char *msg, ... )
va_end( valist ); va_end( valist );
} }
int output( const char *format, ... )
{
int ret;
va_list valist;
va_start( valist, format );
ret = vfprintf( output_file, format, valist );
va_end( valist );
if (ret < 0) fatal_perror( "Output error" );
return ret;
}
/* get a name for a temp file, automatically cleaned up on exit */ /* get a name for a temp file, automatically cleaned up on exit */
char *get_temp_file_name( const char *prefix, const char *suffix ) char *get_temp_file_name( const char *prefix, const char *suffix )
{ {
@ -196,31 +206,29 @@ char *get_temp_file_name( const char *prefix, const char *suffix )
} }
/* output a standard header for generated files */ /* output a standard header for generated files */
void output_standard_file_header( FILE *outfile ) void output_standard_file_header(void)
{ {
if (spec_file_name) if (spec_file_name)
fprintf( outfile, "/* File generated automatically from %s; do not edit! */\n", output( "/* File generated automatically from %s; do not edit! */\n", spec_file_name );
spec_file_name );
else else
fprintf( outfile, "/* File generated automatically; do not edit! */\n" ); output( "/* File generated automatically; do not edit! */\n" );
fprintf( outfile, output( "/* This file can be copied, modified and distributed without restriction. */\n\n" );
"/* This file can be copied, modified and distributed without restriction. */\n\n" );
} }
/* dump a byte stream into the assembly code */ /* dump a byte stream into the assembly code */
void dump_bytes( FILE *outfile, const void *buffer, unsigned int size ) void dump_bytes( const void *buffer, unsigned int size )
{ {
unsigned int i; unsigned int i;
const unsigned char *ptr = buffer; const unsigned char *ptr = buffer;
if (!size) return; if (!size) return;
fprintf( outfile, "\t.byte " ); output( "\t.byte " );
for (i = 0; i < size - 1; i++, ptr++) for (i = 0; i < size - 1; i++, ptr++)
{ {
if ((i % 16) == 15) fprintf( outfile, "0x%02x\n\t.byte ", *ptr ); if ((i % 16) == 15) output( "0x%02x\n\t.byte ", *ptr );
else fprintf( outfile, "0x%02x,", *ptr ); else output( "0x%02x,", *ptr );
} }
fprintf( outfile, "0x%02x\n", *ptr ); output( "0x%02x\n", *ptr );
} }
@ -324,7 +332,12 @@ DLLSPEC *alloc_dll_spec(void)
spec->alloc_entry_points = 0; spec->alloc_entry_points = 0;
spec->nb_names = 0; spec->nb_names = 0;
spec->nb_resources = 0; spec->nb_resources = 0;
spec->characteristics = 0; spec->characteristics = IMAGE_FILE_EXECUTABLE_IMAGE;
if (get_ptr_size() > 4)
spec->characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
else
spec->characteristics |= IMAGE_FILE_32BIT_MACHINE;
spec->dll_characteristics = IMAGE_DLLCHARACTERISTICS_NX_COMPAT;
spec->subsystem = 0; spec->subsystem = 0;
spec->subsystem_major = 4; spec->subsystem_major = 4;
spec->subsystem_minor = 0; spec->subsystem_minor = 0;
@ -444,7 +457,7 @@ unsigned int get_alignment(unsigned int align)
case CPU_POWERPC: case CPU_POWERPC:
case CPU_ALPHA: case CPU_ALPHA:
n = 0; n = 0;
while ((1 << n) != align) n++; while ((1u << n) != align) n++;
return n; return n;
} }
/* unreached */ /* unreached */
@ -523,7 +536,7 @@ const char *func_declaration( const char *func )
} }
/* output a size declaration for an assembly function */ /* output a size declaration for an assembly function */
void output_function_size( FILE *outfile, const char *name ) void output_function_size( const char *name )
{ {
switch (target_platform) switch (target_platform)
{ {
@ -531,7 +544,21 @@ void output_function_size( FILE *outfile, const char *name )
case PLATFORM_WINDOWS: case PLATFORM_WINDOWS:
break; break;
default: default:
fprintf( outfile, "\t.size %s, .-%s\n", name, name ); output( "\t.size %s, .-%s\n", name, name );
break;
}
}
/* output the GNU note for non-exec stack */
void output_gnu_stack_note(void)
{
switch (target_platform)
{
case PLATFORM_WINDOWS:
case PLATFORM_APPLE:
break;
default:
output( "\t.section .note.GNU-stack,\"\",@progbits\n" );
break; break;
} }
} }

View file

@ -73,11 +73,11 @@ Specify the module entry point function; if not specified, the default
is is
.B DllMain .B DllMain
for dlls, and for dlls, and
.B WinMain
for executables (if
.B WinMain
is not defined, the standard C
.B main .B main
for executables (if the standard C
.B main
is not defined,
.B WinMain
is used instead). This is only valid for Win32 modules. is used instead). This is only valid for Win32 modules.
.TP .TP
.BI \-E,\ --export= filename .BI \-E,\ --export= filename
@ -85,6 +85,14 @@ Specify a .spec file (see \fBSPEC FILE SYNTAX\fR for details),
or a standard Windows .def file that defines the exports or a standard Windows .def file that defines the exports
of the DLL or executable that is being built. of the DLL or executable that is being built.
.TP .TP
.B \--external-symbols
Allow linking to external symbols directly from the spec
file. Normally symbols exported by a dll have to be defined in the dll
itself; this option makes it possible to use symbols defined in
another Unix library (for symbols defined in another dll, a
.I forward
specification must be used instead).
.TP
.BI \-f\ flags .BI \-f\ flags
Ignored for compatibility with the C compiler. Ignored for compatibility with the C compiler.
.TP .TP
@ -145,6 +153,10 @@ KRNL386.EXE. It shouldn't be needed otherwise.
Specify the command to use to get the list of undefined symbols; the Specify the command to use to get the list of undefined symbols; the
default is \fBnm\fR. default is \fBnm\fR.
.TP .TP
.BI --nxcompat= yes|no
Specify whether the module is compatible with no-exec support. The
default is yes.
.TP
.BI \-o,\ --output= file .BI \-o,\ --output= file
Set the name of the output file (default is standard output). If the Set the name of the output file (default is standard output). If the
output file name end in \fB.o\fR, the text output is sent to a output file name end in \fB.o\fR, the text output is sent to a
@ -248,7 +260,8 @@ The entry point is not displayed in relay debugging traces (Win32
only). only).
.TP .TP
.B -noname .B -noname
The entry point will be imported by ordinal instead of by name. The entry point will be exported by ordinal instead of by name. The
name is still available for importing.
.TP .TP
.B -ret16 .B -ret16
The function returns a 16-bit value (Win16 only). The function returns a 16-bit value (Win16 only).
@ -265,6 +278,10 @@ The function uses CPU register to pass arguments.
.B -private .B -private
The function cannot be imported from other dlls, it can only be The function cannot be imported from other dlls, it can only be
accessed through GetProcAddress. accessed through GetProcAddress.
.TP
.B -ordinal
The entry point will be imported by ordinal instead of by name. The
name is still exported.
.SS "Function ordinals" .SS "Function ordinals"
Syntax: Syntax:
.br .br

View file

@ -17,6 +17,9 @@ typedef unsigned int UINT_PTR;
#define DLL_PROCESS_ATTACH 1 #define DLL_PROCESS_ATTACH 1
#define DLL_PROCESS_DETACH 0 #define DLL_PROCESS_DETACH 0
#define IMAGE_FILE_EXECUTABLE_IMAGE 2
#define IMAGE_FILE_LARGE_ADDRESS_AWARE 32
#define IMAGE_FILE_32BIT_MACHINE 256
#define IMAGE_FILE_DLL 8192 #define IMAGE_FILE_DLL 8192
#define IMAGE_SUBSYSTEM_NATIVE 1 #define IMAGE_SUBSYSTEM_NATIVE 1
#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 #define IMAGE_SUBSYSTEM_WINDOWS_GUI 2
@ -28,6 +31,7 @@ typedef unsigned int UINT_PTR;
#define IMAGE_FILE_MACHINE_POWERPC 0x01f0 #define IMAGE_FILE_MACHINE_POWERPC 0x01f0
#define IMAGE_FILE_MACHINE_AMD64 0x8664 #define IMAGE_FILE_MACHINE_AMD64 0x8664
#define IMAGE_NT_SIGNATURE 0x00004550 #define IMAGE_NT_SIGNATURE 0x00004550
#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT 0x0100
#define IMAGE_SIZEOF_NT_OPTIONAL32_HEADER 224 #define IMAGE_SIZEOF_NT_OPTIONAL32_HEADER 224
#define IMAGE_SIZEOF_NT_OPTIONAL64_HEADER 240 #define IMAGE_SIZEOF_NT_OPTIONAL64_HEADER 240
#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b #define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b