[WINEBUILD]

Sync winebuild to Wine_1_1_34
Lots of reactos hacks are gone now. ARM is natively supported now. Windows headers are no longer included, winglue.h is gone, the code that was previously removed is back again, there is no point in removing unused features. still there: the fastcall and pedll modifications. Added a ros-diff.

svn path=/trunk/; revision=44490
This commit is contained in:
Timo Kreuzer 2009-12-09 17:01:35 +00:00
parent 0cbf682dc2
commit 6d466854ff
15 changed files with 2181 additions and 744 deletions

View file

@ -3,6 +3,7 @@ TOPOBJDIR = ../..
SRCDIR = @srcdir@
VPATH = @srcdir@
EXEEXT = @EXEEXT@
DEFS = -D__WINESRC__ $(EXTRADEFS)
PROGRAMS = winebuild$(EXEEXT)
MANPAGES = winebuild.man
@ -28,7 +29,7 @@ all: $(PROGRAMS) $(MANPAGES)
winebuild$(EXEEXT): $(OBJS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBPORT) $(LDFLAGS)
install:: $(PROGRAMS) $(MANPAGES) $(INSTALLDIRS)
install install-dev:: $(PROGRAMS) $(MANPAGES) $(INSTALLDIRS)
$(INSTALL_PROGRAM) winebuild$(EXEEXT) $(DESTDIR)$(bindir)/winebuild$(EXEEXT)
$(INSTALL_DATA) winebuild.man $(DESTDIR)$(mandir)/man$(prog_manext)/winebuild.$(prog_manext)

View file

@ -31,6 +31,15 @@
#include <stdlib.h>
#include <string.h>
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#define EXEEXT ".exe"
typedef enum
{
TYPE_VARIABLE, /* variable */
@ -90,6 +99,7 @@ typedef struct
char *file_name; /* file name of the dll */
char *dll_name; /* internal name of the dll */
char *init_func; /* initialization routine */
char *main_module; /* main Win32 module for Win16 specs */
SPEC_TYPE type; /* type of dll (Win16/Win32) */
int base; /* ordinal base */
int limit; /* ordinal limit */
@ -112,14 +122,19 @@ typedef struct
enum target_cpu
{
CPU_x86, CPU_x86_64, CPU_SPARC, CPU_ALPHA, CPU_POWERPC, CPU_ARM
CPU_x86, CPU_x86_64, CPU_SPARC, CPU_ALPHA, CPU_POWERPC, CPU_ARM, CPU_LAST = CPU_ARM
};
enum target_platform
{
PLATFORM_UNSPECIFIED, PLATFORM_APPLE, PLATFORM_SOLARIS, PLATFORM_WINDOWS
PLATFORM_UNSPECIFIED,
PLATFORM_APPLE,
PLATFORM_FREEBSD,
PLATFORM_SOLARIS,
PLATFORM_WINDOWS
};
extern char *target_alias;
extern enum target_cpu target_cpu;
extern enum target_platform target_platform;
@ -136,10 +151,37 @@ extern enum target_platform target_platform;
#define FLAG_EXT_LINK 0x200 /* function links to an external symbol */
#define FLAG_CPU(cpu) (0x01000 << (cpu))
#define FLAG_CPU_MASK 0x1f000
#define FLAG_CPU_MASK (FLAG_CPU(CPU_LAST + 1) - FLAG_CPU(0))
#define FLAG_CPU_WIN64 (FLAG_CPU(CPU_x86_64))
#define FLAG_CPU_WIN32 (FLAG_CPU_MASK & ~FLAG_CPU_WIN64)
#define MAX_ORDINALS 65535
/* some Windows constants */
#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 /* No relocation info */
#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002
#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008
#define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010
#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020
#define IMAGE_FILE_16BIT_MACHINE 0x0040
#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080
#define IMAGE_FILE_32BIT_MACHINE 0x0100
#define IMAGE_FILE_DEBUG_STRIPPED 0x0200
#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400
#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800
#define IMAGE_FILE_SYSTEM 0x1000
#define IMAGE_FILE_DLL 0x2000
#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000
#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000
#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT 0x0100
#define IMAGE_SUBSYSTEM_NATIVE 1
#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2
#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3
/* global functions */
#ifndef __GNUC__
@ -169,6 +211,10 @@ extern void warning( const char *msg, ... )
__attribute__ ((__format__ (__printf__, 1, 2)));
extern int output( const char *format, ... )
__attribute__ ((__format__ (__printf__, 1, 2)));
extern const char *get_as_command(void);
extern const char *get_ld_command(void);
extern const char *get_nm_command(void);
extern const char *get_windres_command(void);
extern char *get_temp_file_name( const char *prefix, const char *suffix );
extern void output_standard_file_header(void);
extern FILE *open_input_file( const char *srcdir, const char *name );
@ -204,13 +250,22 @@ extern int resolve_imports( DLLSPEC *spec );
extern int has_imports(void);
extern int has_relays( DLLSPEC *spec );
extern void output_get_pc_thunk(void);
extern void output_module( DLLSPEC *spec );
extern void output_stubs( DLLSPEC *spec );
extern void output_imports( DLLSPEC *spec );
extern void output_exports( DLLSPEC *spec );
extern int load_res32_file( const char *name, DLLSPEC *spec );
extern void output_resources( DLLSPEC *spec );
extern void output_bin_resources( DLLSPEC *spec, unsigned int start_rva );
extern void output_fake_module( DLLSPEC *spec );
extern void load_res16_file( const char *name, DLLSPEC *spec );
extern void output_res16_data( DLLSPEC *spec );
extern void output_res16_directory( DLLSPEC *spec, const char *header_name );
extern void output_bin_res16_data( DLLSPEC *spec );
extern void output_res16_directory( DLLSPEC *spec );
extern void output_bin_res16_directory( DLLSPEC *spec, unsigned int data_offset );
extern void output_spec16_file( DLLSPEC *spec );
extern void output_fake_module16( DLLSPEC *spec16 );
extern void output_res_o_file( DLLSPEC *spec );
extern void BuildRelays16(void);
extern void BuildRelays32(void);
@ -219,9 +274,35 @@ extern void BuildSpec32File( DLLSPEC *spec );
extern void BuildDef32File( DLLSPEC *spec );
extern void BuildPedllFile( DLLSPEC *spec );
extern void add_16bit_exports( DLLSPEC *spec32, DLLSPEC *spec16 );
extern int parse_spec_file( FILE *file, DLLSPEC *spec );
extern int parse_def_file( FILE *file, DLLSPEC *spec );
/* buffer management */
extern int byte_swapped;
extern const char *input_buffer_filename;
extern const unsigned char *input_buffer;
extern size_t input_buffer_pos;
extern size_t input_buffer_size;
extern unsigned char *output_buffer;
extern size_t output_buffer_pos;
extern size_t output_buffer_size;
extern void init_input_buffer( const char *file );
extern void init_output_buffer(void);
extern void flush_output_buffer(void);
extern unsigned char get_byte(void);
extern unsigned short get_word(void);
extern unsigned int get_dword(void);
extern void put_data( const void *data, size_t size );
extern void put_byte( unsigned char val );
extern void put_word( unsigned short val );
extern void put_dword( unsigned int val );
extern void put_qword( unsigned int val );
extern void put_pword( unsigned int val );
extern void align_output( unsigned int align );
/* global variables */
extern int current_line;

View file

@ -35,7 +35,6 @@
# include <unistd.h>
#endif
#include "winglue.h"
#include "build.h"
struct import
@ -378,6 +377,7 @@ static const char *get_default_entry_point( const DLLSPEC *spec )
{
if (spec->characteristics & IMAGE_FILE_DLL) return "__wine_spec_dll_entry";
if (spec->subsystem == IMAGE_SUBSYSTEM_NATIVE) return "__wine_spec_drv_entry";
if (spec->type == SPEC_WIN16) return "__wine_spec_exe16_entry";
return "__wine_spec_exe_entry";
}
@ -466,7 +466,7 @@ static void check_undefined_exports( DLLSPEC *spec )
for (i = 0; i < spec->nb_entry_points; i++)
{
ORDDEF *odp = &spec->entry_points[i];
if (odp->type == TYPE_STUB) continue;
if (odp->type == TYPE_STUB || odp->type == TYPE_ABS) continue;
if (odp->flags & FLAG_FORWARD) continue;
if (find_name( odp->link_name, &undef_symbols ))
{
@ -508,7 +508,7 @@ static char *create_undef_symbols_file( DLLSPEC *spec )
for (i = 0; i < spec->nb_entry_points; i++)
{
ORDDEF *odp = &spec->entry_points[i];
if (odp->type == TYPE_STUB) continue;
if (odp->type == TYPE_STUB || odp->type == TYPE_ABS) continue;
if (odp->flags & FLAG_FORWARD) continue;
fprintf( f, "\t%s %s\n", get_asm_ptr_keyword(), asm_name(odp->link_name) );
}
@ -526,21 +526,21 @@ static char *create_undef_symbols_file( DLLSPEC *spec )
static const char *ldcombine_files( DLLSPEC *spec, char **argv )
{
unsigned int i, len = 0;
const char *prog = get_ld_command();
char *cmd, *p, *ld_tmp_file, *undef_file;
int err;
undef_file = create_undef_symbols_file( spec );
len += strlen(undef_file) + 1;
ld_tmp_file = get_temp_file_name( output_file_name, ".o" );
if (!ld_command) ld_command = xstrdup("ld");
for (i = 0; argv[i]; i++) len += strlen(argv[i]) + 1;
cmd = p = xmalloc( len + strlen(ld_tmp_file) + 8 + strlen(ld_command) );
p += sprintf( cmd, "%s -r -o %s %s", ld_command, ld_tmp_file, undef_file );
cmd = p = xmalloc( len + strlen(ld_tmp_file) + 8 + strlen(prog) );
p += sprintf( cmd, "%s -r -o %s %s", prog, ld_tmp_file, undef_file );
for (i = 0; argv[i]; i++)
p += sprintf( p, " %s", argv[i] );
if (verbose) fprintf( stderr, "%s\n", cmd );
err = system( cmd );
if (err) fatal_error( "%s -r failed with status %d\n", ld_command, err );
if (err) fatal_error( "%s -r failed with status %d\n", prog, err );
free( cmd );
return ld_tmp_file;
}
@ -550,6 +550,7 @@ void read_undef_symbols( DLLSPEC *spec, char **argv )
{
size_t prefix_len;
FILE *f;
const char *prog = get_nm_command();
char *cmd, buffer[1024], name_prefix[16];
int err;
const char *name;
@ -563,9 +564,8 @@ void read_undef_symbols( DLLSPEC *spec, char **argv )
name = ldcombine_files( spec, argv );
if (!nm_command) nm_command = xstrdup("nm");
cmd = xmalloc( strlen(nm_command) + strlen(name) + 5 );
sprintf( cmd, "%s -u %s", nm_command, name );
cmd = xmalloc( strlen(prog) + strlen(name) + 5 );
sprintf( cmd, "%s -u %s", prog, name );
if (!(f = popen( cmd, "r" )))
fatal_error( "Cannot execute '%s'\n", cmd );
@ -668,7 +668,9 @@ static void output_import_thunk( const char *name, const char *table, int pos )
}
break;
case CPU_x86_64:
output( "\t.cfi_startproc\n" );
output( "\tjmpq *%s+%d(%%rip)\n", table, pos );
output( "\t.cfi_endproc\n" );
break;
case CPU_SPARC:
if ( !UsePIC )
@ -697,6 +699,10 @@ static void output_import_thunk( const char *name, const char *table, int pos )
output( "\tlda $0,%d($0)\n", pos );
output( "\tjmp $31,($0)\n" );
break;
case CPU_ARM:
output( "\tmov r4, #%s\n", table );
output( "\tldr r15, [r4, #%d]\n", pos );
break;
case CPU_POWERPC:
output( "\tmr %s, %s\n", ppc_reg(0), ppc_reg(31) );
if (target_platform == PLATFORM_APPLE)
@ -970,23 +976,27 @@ static void output_delayed_import_thunks( const DLLSPEC *spec )
output( "\tjmp *%%eax\n" );
break;
case CPU_x86_64:
output( "\tpushq %%rdx\n" );
output( "\tpushq %%rcx\n" );
output( "\tpushq %%r8\n" );
output( "\tpushq %%r9\n" );
output( "\tpushq %%r10\n" );
output( "\tpushq %%r11\n" );
output( "\tsubq $40,%%rsp\n" );
output( "\t.cfi_startproc\n" );
output( "\tsubq $88,%%rsp\n" );
output( "\t.cfi_adjust_cfa_offset 88\n" );
output( "\tmovq %%rdx,80(%%rsp)\n" );
output( "\tmovq %%rcx,72(%%rsp)\n" );
output( "\tmovq %%r8,64(%%rsp)\n" );
output( "\tmovq %%r9,56(%%rsp)\n" );
output( "\tmovq %%r10,48(%%rsp)\n" );
output( "\tmovq %%r11,40(%%rsp)\n" );
output( "\tmovq %%rax,%%rcx\n" );
output( "\tcall %s\n", asm_name("__wine_spec_delay_load") );
output( "\taddq $40,%%rsp\n" );
output( "\tpopq %%r11\n" );
output( "\tpopq %%r10\n" );
output( "\tpopq %%r9\n" );
output( "\tpopq %%r8\n" );
output( "\tpopq %%rcx\n" );
output( "\tpopq %%rdx\n" );
output( "\tmovq 40(%%rsp),%%r11\n" );
output( "\tmovq 48(%%rsp),%%r10\n" );
output( "\tmovq 56(%%rsp),%%r9\n" );
output( "\tmovq 64(%%rsp),%%r8\n" );
output( "\tmovq 72(%%rsp),%%rcx\n" );
output( "\tmovq 80(%%rsp),%%rdx\n" );
output( "\taddq $88,%%rsp\n" );
output( "\t.cfi_adjust_cfa_offset -88\n" );
output( "\tjmp *%%rax\n" );
output( "\t.cfi_endproc\n" );
break;
case CPU_SPARC:
output( "\tsave %%sp, -96, %%sp\n" );
@ -999,6 +1009,11 @@ static void output_delayed_import_thunks( const DLLSPEC *spec )
output( "\tjsr $26,%s\n", asm_name("__wine_spec_delay_load") );
output( "\tjmp $31,($0)\n" );
break;
case CPU_ARM:
output( "\tstmfd sp!, {r4, r5, r6, r7, r8, r9, r10, lr}\n" );
output( "\tblx %s\n", asm_name("__wine_spec_delay_load") );
output( "\tldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, pc}\n" );
break;
case CPU_POWERPC:
if (target_platform == PLATFORM_APPLE) extra_stack_storage = 56;
@ -1068,8 +1083,10 @@ static void output_delayed_import_thunks( const DLLSPEC *spec )
output( "\tjmp %s\n", asm_name("__wine_delay_load_asm") );
break;
case CPU_x86_64:
output( "\t.cfi_startproc\n" );
output( "\tmovq $%d,%%rax\n", (idx << 16) | j );
output( "\tjmp %s\n", asm_name("__wine_delay_load_asm") );
output( "\t.cfi_endproc\n" );
break;
case CPU_SPARC:
output( "\tset %d, %%g1\n", (idx << 16) | j );
@ -1080,6 +1097,9 @@ static void output_delayed_import_thunks( const DLLSPEC *spec )
output( "\tldah $0,%d($0)\n", idx);
output( "\tjmp $31,%s\n", asm_name("__wine_delay_load_asm") );
break;
case CPU_ARM:
output( "\tb %s\n", asm_name("__wine_delay_load_asm") );
break;
case CPU_POWERPC:
switch(target_platform)
{
@ -1235,6 +1255,9 @@ void output_stubs( DLLSPEC *spec )
output( "\tcall %s\n", asm_name("__wine_spec_unimplemented_stub") );
break;
case CPU_x86_64:
output( "\t.cfi_startproc\n" );
output( "\tsubq $8,%%rsp\n" );
output( "\t.cfi_adjust_cfa_offset 8\n" );
output( "\tleaq .L__wine_spec_file_name(%%rip),%%rdi\n" );
if (exp_name)
{
@ -1243,8 +1266,8 @@ void output_stubs( DLLSPEC *spec )
}
else
output( "\tmovq $%d,%%rsi\n", odp->ordinal );
output( "\tsubq $8,%%rsp\n" );
output( "\tcall %s\n", asm_name("__wine_spec_unimplemented_stub") );
output( "\t.cfi_endproc\n" );
break;
default:
assert(0);

View file

@ -36,7 +36,6 @@
# include <getopt.h>
#endif
#include "winglue.h"
#include "build.h"
int UsePIC = 0;
@ -53,7 +52,13 @@ int force_pointer_size = 0;
enum target_cpu target_cpu = CPU_x86;
#elif defined(TARGET_amd64)
enum target_cpu target_cpu = CPU_x86_64;
#elif defined (TARGET_arm)
#elif defined(__sparc__)
enum target_cpu target_cpu = CPU_SPARC;
#elif defined(__ALPHA__)
enum target_cpu target_cpu = CPU_ALPHA;
#elif defined(__powerpc__)
enum target_cpu target_cpu = CPU_POWERPC;
#elif defined(TARGET_arm)
enum target_cpu target_cpu = CPU_ARM;
#else
#error Unsupported CPU
@ -61,14 +66,17 @@ enum target_cpu target_cpu = CPU_ARM;
#ifdef __APPLE__
enum target_platform target_platform = PLATFORM_APPLE;
#elif defined(__FreeBSD__)
enum target_platform target_platform = PLATFORM_FREEBSD;
#elif defined(__sun)
enum target_platform target_platform = PLATFORM_SOLARIS;
#elif defined(_WINDOWS)
#elif defined(_WIN32)
enum target_platform target_platform = PLATFORM_WINDOWS;
#else
enum target_platform target_platform = PLATFORM_UNSPECIFIED;
#endif
char *target_alias = NULL;
char **lib_path = NULL;
char *input_file_name = NULL;
@ -76,6 +84,7 @@ char *spec_file_name = NULL;
FILE *output_file = NULL;
const char *output_file_name = NULL;
static const char *output_file_source_name;
static int fake_module;
char *as_command = NULL;
char *ld_command = NULL;
@ -93,6 +102,7 @@ enum exec_mode_values
MODE_DEF,
MODE_RELAY16,
MODE_RELAY32,
MODE_RESOURCES,
MODE_PEDLL
};
@ -106,6 +116,7 @@ static const struct
{
{ "macos", PLATFORM_APPLE },
{ "darwin", PLATFORM_APPLE },
{ "freebsd", PLATFORM_FREEBSD },
{ "solaris", PLATFORM_SOLARIS },
{ "windows", PLATFORM_WINDOWS },
{ "winnt", PLATFORM_WINDOWS }
@ -137,6 +148,7 @@ static void set_subsystem( const char *subsystem, DLLSPEC *spec )
if (!strcmp( str, "native" )) spec->subsystem = IMAGE_SUBSYSTEM_NATIVE;
else if (!strcmp( str, "windows" )) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
else if (!strcmp( str, "console" )) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
else if (!strcmp( str, "win16" )) spec->type = SPEC_WIN16;
else fatal_error( "Invalid subsystem name '%s'\n", subsystem );
if (major)
{
@ -158,6 +170,8 @@ static void set_target( const char *target )
/* target specification is in the form CPU-MANUFACTURER-OS or CPU-MANUFACTURER-KERNEL-OS */
target_alias = xstrdup( target );
/* get the CPU part */
if (!(p = strchr( spec, '-' ))) fatal_error( "Invalid target specification '%s'\n", target );
@ -180,25 +194,6 @@ static void set_target( const char *target )
}
free( spec );
if (!as_command)
{
as_command = xmalloc( strlen(target) + sizeof("-as") );
strcpy( as_command, target );
strcat( as_command, "-as" );
}
if (!ld_command)
{
ld_command = xmalloc( strlen(target) + sizeof("-ld") );
strcpy( ld_command, target );
strcat( ld_command, "-ld" );
}
if (!nm_command)
{
nm_command = xmalloc( strlen(target) + sizeof("-nm") );
strcpy( nm_command, target );
strcat( nm_command, "-nm" );
}
}
/* cleanup on program exit */
@ -219,43 +214,46 @@ static void exit_on_signal( int sig )
static const char usage_str[] =
"Usage: winebuild [OPTIONS] [FILES]\n\n"
"Options:\n"
" --as-cmd=AS Command to use for assembling (default: as)\n"
" -b, --target=TARGET Specify target CPU and platform for cross-compiling\n"
" -d, --delay-lib=LIB Import the specified library in delayed mode\n"
" -D SYM Ignored for C flags compatibility\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, --filename=DLLFILE Set the DLL filename (default: from input file name)\n"
" -h, --help Display this help message\n"
" -H, --heap=SIZE Set the heap size for a Win16 dll\n"
" -i, --ignore=SYM[,SYM] Ignore specified symbols when resolving imports\n"
" -I DIR Ignored for C flags compatibility\n"
" -k, --kill-at Kill stdcall decorations in generated .def files\n"
" -K, FLAGS Compiler flags (only -KPIC is supported)\n"
" --ld-cmd=LD Command to use for linking (default: ld)\n"
" -l, --library=LIB Import the specified library\n"
" -L, --library-path=DIR Look for imports libraries in DIR\n"
" -m32, -m64 Force building 32-bit resp. 64-bit code\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"
" --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"
" -o, --output=NAME Set the output file name (default: stdout)\n"
" -r, --res=RSRC.RES Load resources from RSRC.RES\n"
" --save-temps Do not delete the generated intermediate files\n"
" --subsystem=SUBSYS Set the subsystem (one of native, windows, console)\n"
" -u, --undefined=SYMBOL Add an undefined reference to SYMBOL when linking\n"
" -v, --verbose Display the programs invoked\n"
" --version Print the version and exit\n"
" -w, --warnings Turn on warnings\n"
" --as-cmd=AS Command to use for assembling (default: as)\n"
" -b, --target=TARGET Specify target CPU and platform for cross-compiling\n"
" -d, --delay-lib=LIB Import the specified library in delayed mode\n"
" -D SYM Ignored for C flags compatibility\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, --filename=DLLFILE Set the DLL filename (default: from input file name)\n"
" --fake-module Create a fake binary module\n"
" -h, --help Display this help message\n"
" -H, --heap=SIZE Set the heap size for a Win16 dll\n"
" -i, --ignore=SYM[,SYM] Ignore specified symbols when resolving imports\n"
" -I DIR Ignored for C flags compatibility\n"
" -k, --kill-at Kill stdcall decorations in generated .def files\n"
" -K, FLAGS Compiler flags (only -KPIC is supported)\n"
" --large-address-aware Support an address space larger than 2Gb\n"
" --ld-cmd=LD Command to use for linking (default: ld)\n"
" -l, --library=LIB Import the specified library\n"
" -L, --library-path=DIR Look for imports libraries in DIR\n"
" -m32, -m64 Force building 32-bit resp. 64-bit code\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"
" --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"
" -o, --output=NAME Set the output file name (default: stdout)\n"
" -r, --res=RSRC.RES Load resources from RSRC.RES\n"
" --save-temps Do not delete the generated intermediate files\n"
" --subsystem=SUBSYS Set the subsystem (one of native, windows, console)\n"
" -u, --undefined=SYMBOL Add an undefined reference to SYMBOL when linking\n"
" -v, --verbose Display the programs invoked\n"
" --version Print the version and exit\n"
" -w, --warnings Turn on warnings\n"
"\nMode options:\n"
" --dll Build a .c file from a .spec or .def file\n"
" --def Build a .def file from a .spec file\n"
" --exe Build a .c file for an executable\n"
" --relay16 Build the 16-bit relay assembly routines\n"
" --relay32 Build the 32-bit relay assembly routines\n\n"
" --dll Build a .c file from a .spec or .def file\n"
" --def Build a .def file from a .spec file\n"
" --exe Build a .c file for an executable\n"
" --relay16 Build the 16-bit relay assembly routines\n"
" --relay32 Build the 32-bit relay assembly routines\n"
" --resources Build a .o file for the resource files\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";
@ -266,11 +264,14 @@ enum long_options_values
LONG_OPT_EXE,
LONG_OPT_ASCMD,
LONG_OPT_EXTERNAL_SYMS,
LONG_OPT_FAKE_MODULE,
LONG_OPT_LARGE_ADDRESS_AWARE,
LONG_OPT_LDCMD,
LONG_OPT_NMCMD,
LONG_OPT_NXCOMPAT,
LONG_OPT_RELAY16,
LONG_OPT_RELAY32,
LONG_OPT_RESOURCES,
LONG_OPT_SAVE_TEMPS,
LONG_OPT_SUBSYSTEM,
LONG_OPT_VERSION,
@ -286,11 +287,14 @@ static const struct option long_options[] =
{ "exe", 0, 0, LONG_OPT_EXE },
{ "as-cmd", 1, 0, LONG_OPT_ASCMD },
{ "external-symbols", 0, 0, LONG_OPT_EXTERNAL_SYMS },
{ "fake-module", 0, 0, LONG_OPT_FAKE_MODULE },
{ "large-address-aware", 0, 0, LONG_OPT_LARGE_ADDRESS_AWARE },
{ "ld-cmd", 1, 0, LONG_OPT_LDCMD },
{ "nm-cmd", 1, 0, LONG_OPT_NMCMD },
{ "nxcompat", 1, 0, LONG_OPT_NXCOMPAT },
{ "relay16", 0, 0, LONG_OPT_RELAY16 },
{ "relay32", 0, 0, LONG_OPT_RELAY32 },
{ "resources", 0, 0, LONG_OPT_RESOURCES },
{ "save-temps", 0, 0, LONG_OPT_SAVE_TEMPS },
{ "subsystem", 1, 0, LONG_OPT_SUBSYSTEM },
{ "version", 0, 0, LONG_OPT_VERSION },
@ -373,7 +377,7 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec )
else force_pointer_size = 8;
break;
case 'M':
spec->type = SPEC_WIN16;
spec->main_module = xstrdup( optarg );
break;
case 'N':
spec->dll_name = xstrdup( optarg );
@ -460,9 +464,15 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec )
case LONG_OPT_ASCMD:
as_command = xstrdup( optarg );
break;
case LONG_OPT_FAKE_MODULE:
fake_module = 1;
break;
case LONG_OPT_EXTERNAL_SYMS:
link_ext_symbols = 1;
break;
case LONG_OPT_LARGE_ADDRESS_AWARE:
spec->characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
break;
case LONG_OPT_LDCMD:
ld_command = xstrdup( optarg );
break;
@ -479,6 +489,9 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec )
case LONG_OPT_RELAY32:
set_exec_mode( MODE_RELAY32 );
break;
case LONG_OPT_RESOURCES:
set_exec_mode( MODE_RESOURCES );
break;
case LONG_OPT_SAVE_TEMPS:
save_temps = 1;
break;
@ -603,18 +616,31 @@ int main(int argc, char **argv)
if (spec->subsystem != IMAGE_SUBSYSTEM_NATIVE)
spec->characteristics |= IMAGE_FILE_DLL;
if (!spec_file_name) fatal_error( "missing .spec file\n" );
if (spec->type == SPEC_WIN32 && spec->main_module) /* embedded 16-bit module */
{
spec->type = SPEC_WIN16;
load_resources( argv, spec );
if (parse_input_file( spec )) BuildSpec16File( spec );
break;
}
/* fall through */
case MODE_EXE:
load_resources( argv, spec );
load_import_libs( argv );
if (spec_file_name && !parse_input_file( spec )) break;
if (fake_module)
{
if (spec->type == SPEC_WIN16) output_fake_module16( spec );
else output_fake_module( spec );
break;
}
read_undef_symbols( spec, argv );
switch (spec->type)
{
case SPEC_WIN16:
fatal_error( "Win16 specs are not supported in ReactOS version of winebuild\n" );
output_spec16_file( spec );
break;
case SPEC_WIN32:
read_undef_symbols( spec, argv );
BuildSpec32File( spec );
break;
default: assert(0);
@ -628,16 +654,22 @@ int main(int argc, char **argv)
BuildDef32File( spec );
break;
case MODE_RELAY16:
fatal_error( "Win16 relays are not supported in ReactOS version of winebuild\n" );
if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
BuildRelays16();
break;
case MODE_RELAY32:
fatal_error( "Win32 relays are not supported in ReactOS version of winebuild\n" );
if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
BuildRelays32();
break;
case MODE_PEDLL:
if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
if (!parse_input_file( spec )) break;
BuildPedllFile( spec );
break;
case MODE_RESOURCES:
load_resources( argv, spec );
output_res_o_file( spec );
break;
default:
usage(1);
break;

View file

@ -32,7 +32,6 @@
#include <stdlib.h>
#include <string.h>
#include "winglue.h"
#include "build.h"
int current_line = 0;
@ -146,13 +145,17 @@ static const char * GetToken( int allow_eol )
static ORDDEF *add_entry_point( DLLSPEC *spec )
{
ORDDEF *ret;
if (spec->nb_entry_points == spec->alloc_entry_points)
{
spec->alloc_entry_points += 128;
spec->entry_points = xrealloc( spec->entry_points,
spec->alloc_entry_points * sizeof(*spec->entry_points) );
}
return &spec->entry_points[spec->nb_entry_points++];
ret = &spec->entry_points[spec->nb_entry_points++];
memset( ret, 0, sizeof(*ret) );
return ret;
}
/*******************************************************************
@ -433,13 +436,20 @@ static const char *parse_spec_flags( ORDDEF *odp )
char *cpu_name = strtok( args, "," );
while (cpu_name)
{
enum target_cpu cpu = get_cpu_from_name( cpu_name );
if (cpu == -1)
if (!strcmp( cpu_name, "win32" ))
odp->flags |= FLAG_CPU_WIN32;
else if (!strcmp( cpu_name, "win64" ))
odp->flags |= FLAG_CPU_WIN64;
else
{
error( "Unknown architecture '%s'\n", cpu_name );
return NULL;
enum target_cpu cpu = get_cpu_from_name( cpu_name );
if (cpu == -1)
{
error( "Unknown architecture '%s'\n", cpu_name );
return NULL;
}
odp->flags |= FLAG_CPU( cpu );
}
odp->flags |= FLAG_CPU( cpu );
cpu_name = strtok( NULL, "," );
}
free( args );
@ -475,9 +485,7 @@ static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
{
const char *token;
size_t len;
ORDDEF *odp = add_entry_point( spec );
memset( odp, 0, sizeof(*odp) );
if (!(token = GetToken(0))) goto error;
@ -724,6 +732,39 @@ static void assign_ordinals( DLLSPEC *spec )
}
/*******************************************************************
* add_16bit_exports
*
* Add the necessary exports to the 32-bit counterpart of a 16-bit module.
*/
void add_16bit_exports( DLLSPEC *spec32, DLLSPEC *spec16 )
{
ORDDEF *odp;
/* add an export for the NE module */
odp = add_entry_point( spec32 );
odp->type = TYPE_EXTERN;
odp->name = xstrdup( "__wine_spec_dos_header" );
odp->lineno = 0;
odp->ordinal = 1;
odp->link_name = xstrdup( ".L__wine_spec_dos_header" );
if (spec16->main_module)
{
odp = add_entry_point( spec32 );
odp->type = TYPE_EXTERN;
odp->name = xstrdup( "__wine_spec_main_module" );
odp->lineno = 0;
odp->ordinal = 2;
odp->link_name = xstrdup( ".L__wine_spec_main_module" );
}
assign_names( spec32 );
assign_ordinals( spec32 );
}
/*******************************************************************
* parse_spec_file
*
@ -845,9 +886,7 @@ static int parse_def_export( char *name, DLLSPEC *spec )
{
int i, args;
const char *token = GetToken(1);
ORDDEF *odp = add_entry_point( spec );
memset( odp, 0, sizeof(*odp) );
odp->lineno = current_line;
odp->ordinal = -1;

View file

@ -28,29 +28,16 @@
#include <ctype.h>
#include <stdarg.h>
#define __WINESRC__ /* FIXME: for WINE_VM86_TEB_INFO */
#include "winternl.h"
#include "wine/winbase16.h"
#include "build.h"
/* offset of a structure field relative to the start of the struct */
#define STRUCTOFFSET(type,field) ((int)FIELD_OFFSET(type,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 0xc0 /* STRUCTOFFSET(TEB,WOW32Reserved) */
#define STACKOFFSET 0xc0 /* FIELD_OFFSET(TEB,WOW32Reserved) */
/* fix this if the ntdll_thread_regs structure is changed */
#define GS_OFFSET 0x1d8 /* STRUCTOFFSET(TEB,SystemReserved2) + STRUCTOFFSET(ntdll_thread_data,gs) */
#define GS_OFFSET 0x1d8 /* FIELD_OFFSET(TEB,SystemReserved2) + FIELD_OFFSET(ntdll_thread_data,gs) */
#define DPMI_VIF_OFFSET (0x1fc + 0) /* FIELD_OFFSET(TEB,GdiTebBatch) + FIELD_OFFSET(WINE_VM86_TEB_INFO,dpmi_vif) */
#define VM86_PENDING_OFFSET (0x1fc + 4) /* FIELD_OFFSET(TEB,GdiTebBatch) + FIELD_OFFSET(WINE_VM86_TEB_INFO,vm86_pending) */
static void function_header( const char *name )
{
@ -193,7 +180,7 @@ static void BuildCallFrom16Core( int reg_func, int thunk )
output( "\tpushl %%ds\n" );
output( "\tpopl %%ss\n" );
output( "\tmovl %%ebp, %%esp\n" );
output( "\taddl $%d, %%ebp\n", STACK32OFFSET(ebp) );
output( "\taddl $0x20,%%ebp\n"); /* FIELD_OFFSET(STACK32FRAME,ebp) */
/* At this point:
@ -210,10 +197,10 @@ static void BuildCallFrom16Core( int reg_func, int thunk )
if ( thunk )
{
/* Set up registers as expected and call thunk */
output( "\tleal %d(%%edx), %%ebx\n", (int)sizeof(STACK16FRAME)-22 );
output( "\tleal 0x1a(%%edx),%%ebx\n" ); /* sizeof(STACK16FRAME)-22 */
output( "\tleal -4(%%esp), %%ebp\n" );
output( "\tcall *%d(%%edx)\n", STACK16OFFSET(entry_point) );
output( "\tcall *0x26(%%edx)\n"); /* FIELD_OFFSET(STACK16FRAME,entry_point) */
/* Switch stack back */
output( "\t.byte 0x64\n\tmovw (%d), %%ss\n", STACKOFFSET+2 );
@ -244,43 +231,43 @@ static void BuildCallFrom16Core( int reg_func, int thunk )
/* Build register CONTEXT */
if ( reg_func )
{
output( "\tsubl $%d, %%esp\n", (int)sizeof(CONTEXT86) );
output( "\tsubl $0x2cc,%%esp\n" ); /* sizeof(CONTEXT86) */
output( "\tmovl %%ecx, %d(%%esp)\n", CONTEXTOFFSET(EFlags) );
output( "\tmovl %%ecx,0xc0(%%esp)\n" ); /* EFlags */
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Eax) );
output( "\tmovl %%ebx, %d(%%esp)\n", CONTEXTOFFSET(Ebx) );
output( "\tmovl %%esi, %d(%%esp)\n", CONTEXTOFFSET(Esi) );
output( "\tmovl %%edi, %d(%%esp)\n", CONTEXTOFFSET(Edi) );
output( "\tmovl %%eax,0xb0(%%esp)\n" ); /* Eax */
output( "\tmovl %%ebx,0xa4(%%esp)\n" ); /* Ebx */
output( "\tmovl %%esi,0xa0(%%esp)\n" ); /* Esi */
output( "\tmovl %%edi,0x9c(%%esp)\n" ); /* Edi */
output( "\tmovl %d(%%edx), %%eax\n", STACK16OFFSET(ebp) );
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Ebp) );
output( "\tmovl %d(%%edx), %%eax\n", STACK16OFFSET(ecx) );
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Ecx) );
output( "\tmovl %d(%%edx), %%eax\n", STACK16OFFSET(edx) );
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Edx) );
output( "\tmovl 0x0c(%%edx),%%eax\n"); /* FIELD_OFFSET(STACK16FRAME,ebp) */
output( "\tmovl %%eax,0xb4(%%esp)\n" ); /* Ebp */
output( "\tmovl 0x08(%%edx),%%eax\n"); /* FIELD_OFFSET(STACK16FRAME,ecx) */
output( "\tmovl %%eax,0xac(%%esp)\n" ); /* Ecx */
output( "\tmovl 0x04(%%edx),%%eax\n"); /* FIELD_OFFSET(STACK16FRAME,edx) */
output( "\tmovl %%eax,0xa8(%%esp)\n" ); /* Edx */
output( "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(ds) );
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegDs) );
output( "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(es) );
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegEs) );
output( "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(fs) );
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegFs) );
output( "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(gs) );
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegGs) );
output( "\tmovzwl 0x10(%%edx),%%eax\n"); /* FIELD_OFFSET(STACK16FRAME,ds) */
output( "\tmovl %%eax,0x98(%%esp)\n" ); /* SegDs */
output( "\tmovzwl 0x12(%%edx),%%eax\n"); /* FIELD_OFFSET(STACK16FRAME,es) */
output( "\tmovl %%eax,0x94(%%esp)\n" ); /* SegEs */
output( "\tmovzwl 0x14(%%edx),%%eax\n"); /* FIELD_OFFSET(STACK16FRAME,fs) */
output( "\tmovl %%eax,0x90(%%esp)\n" ); /* SegFs */
output( "\tmovzwl 0x16(%%edx),%%eax\n"); /* FIELD_OFFSET(STACK16FRAME,gs) */
output( "\tmovl %%eax,0x8c(%%esp)\n" ); /* SegGs */
output( "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(cs) );
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegCs) );
output( "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(ip) );
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Eip) );
output( "\tmovzwl 0x2e(%%edx),%%eax\n"); /* FIELD_OFFSET(STACK16FRAME,cs) */
output( "\tmovl %%eax,0xbc(%%esp)\n" ); /* SegCs */
output( "\tmovzwl 0x2c(%%edx),%%eax\n"); /* FIELD_OFFSET(STACK16FRAME,ip) */
output( "\tmovl %%eax,0xb8(%%esp)\n" ); /* Eip */
output( "\t.byte 0x64\n\tmovzwl (%d), %%eax\n", STACKOFFSET+2 );
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegSs) );
output( "\tmovl %%eax,0xc8(%%esp)\n" ); /* SegSs */
output( "\t.byte 0x64\n\tmovzwl (%d), %%eax\n", STACKOFFSET );
output( "\taddl $%d, %%eax\n", STACK16OFFSET(ip) );
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Esp) );
output( "\taddl $0x2c,%%eax\n"); /* FIELD_OFFSET(STACK16FRAME,ip) */
output( "\tmovl %%eax,0xc4(%%esp)\n" ); /* Esp */
#if 0
output( "\tfsave %d(%%esp)\n", CONTEXTOFFSET(FloatSave) );
output( "\tfsave 0x1c(%%esp)\n" ); /* FloatSave */
#endif
/* Push address of CONTEXT86 structure -- popped by the relay routine */
@ -297,14 +284,14 @@ static void BuildCallFrom16Core( int reg_func, int thunk )
}
/* Call relay routine (which will call the API entry point) */
output( "\tleal %d(%%edx), %%eax\n", (int)sizeof(STACK16FRAME) );
output( "\tleal 0x30(%%edx),%%eax\n" ); /* sizeof(STACK16FRAME) */
output( "\tpushl %%eax\n" );
output( "\tpushl %d(%%edx)\n", STACK16OFFSET(entry_point) );
output( "\tcall *%d(%%edx)\n", STACK16OFFSET(relay) );
output( "\tpushl 0x26(%%edx)\n"); /* FIELD_OFFSET(STACK16FRAME,entry_point) */
output( "\tcall *0x20(%%edx)\n"); /* FIELD_OFFSET(STACK16FRAME,relay) */
if ( reg_func )
{
output( "\tleal -%d(%%ebp), %%ebx\n", (int)sizeof(CONTEXT) + STACK32OFFSET(ebp) );
output( "\tleal -748(%%ebp),%%ebx\n" ); /* sizeof(CONTEXT) + FIELD_OFFSET(STACK32FRAME,ebp) */
/* Switch stack back */
output( "\t.byte 0x64\n\tmovw (%d), %%ss\n", STACKOFFSET+2 );
@ -312,36 +299,36 @@ static void BuildCallFrom16Core( int reg_func, int thunk )
output( "\t.byte 0x64\n\tpopl (%d)\n", STACKOFFSET );
/* Get return address to CallFrom16 stub */
output( "\taddw $%d, %%sp\n", STACK16OFFSET(callfrom_ip)-4 );
output( "\taddw $0x14,%%sp\n" ); /* FIELD_OFFSET(STACK16FRAME,callfrom_ip)-4 */
output( "\tpopl %%eax\n" );
output( "\tpopl %%edx\n" );
/* Restore all registers from CONTEXT */
output( "\tmovw %d(%%ebx), %%ss\n", CONTEXTOFFSET(SegSs) );
output( "\tmovl %d(%%ebx), %%esp\n", CONTEXTOFFSET(Esp) );
output( "\tmovw 0xc8(%%ebx),%%ss\n"); /* SegSs */
output( "\tmovl 0xc4(%%ebx),%%esp\n"); /* Esp */
output( "\taddl $4, %%esp\n" ); /* room for final return address */
output( "\tpushw %d(%%ebx)\n", CONTEXTOFFSET(SegCs) );
output( "\tpushw %d(%%ebx)\n", CONTEXTOFFSET(Eip) );
output( "\tpushw 0xbc(%%ebx)\n"); /* SegCs */
output( "\tpushw 0xb8(%%ebx)\n"); /* Eip */
output( "\tpushl %%edx\n" );
output( "\tpushl %%eax\n" );
output( "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(EFlags) );
output( "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(SegDs) );
output( "\tpushl 0xc0(%%ebx)\n"); /* EFlags */
output( "\tpushl 0x98(%%ebx)\n"); /* SegDs */
output( "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(SegEs) );
output( "\tpushl 0x94(%%ebx)\n"); /* SegEs */
output( "\tpopl %%es\n" );
output( "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(SegFs) );
output( "\tpushl 0x90(%%ebx)\n"); /* SegFs */
output( "\tpopl %%fs\n" );
output( "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(SegGs) );
output( "\tpushl 0x8c(%%ebx)\n"); /* SegGs */
output( "\tpopl %%gs\n" );
output( "\tmovl %d(%%ebx), %%ebp\n", CONTEXTOFFSET(Ebp) );
output( "\tmovl %d(%%ebx), %%esi\n", CONTEXTOFFSET(Esi) );
output( "\tmovl %d(%%ebx), %%edi\n", CONTEXTOFFSET(Edi) );
output( "\tmovl %d(%%ebx), %%eax\n", CONTEXTOFFSET(Eax) );
output( "\tmovl %d(%%ebx), %%edx\n", CONTEXTOFFSET(Edx) );
output( "\tmovl %d(%%ebx), %%ecx\n", CONTEXTOFFSET(Ecx) );
output( "\tmovl %d(%%ebx), %%ebx\n", CONTEXTOFFSET(Ebx) );
output( "\tmovl 0xb4(%%ebx),%%ebp\n"); /* Ebp */
output( "\tmovl 0xa0(%%ebx),%%esi\n"); /* Esi */
output( "\tmovl 0x9c(%%ebx),%%edi\n"); /* Edi */
output( "\tmovl 0xb0(%%ebx),%%eax\n"); /* Eax */
output( "\tmovl 0xa8(%%ebx),%%edx\n"); /* Edx */
output( "\tmovl 0xac(%%ebx),%%ecx\n"); /* Ecx */
output( "\tmovl 0xa4(%%ebx),%%ebx\n"); /* Ebx */
output( "\tpopl %%ds\n" );
output( "\tpopfl\n" );
@ -442,15 +429,15 @@ static void BuildCallTo16Core( int reg_func )
* at the cost of a somewhat less efficient return path.]
*/
output( "\tmovl %d(%%esp), %%edi\n", STACK32OFFSET(target) - STACK32OFFSET(edi));
output( "\tmovl 0x14(%%esp),%%edi\n" ); /* FIELD_OFFSET(STACK32FRAME,target) - FIELD_OFFSET(STACK32FRAME,edi) */
/* everything above edi has been popped already */
output( "\tmovl %%eax, %d(%%edi)\n", CONTEXTOFFSET(Eax) );
output( "\tmovl %%ebx, %d(%%edi)\n", CONTEXTOFFSET(Ebx) );
output( "\tmovl %%ecx, %d(%%edi)\n", CONTEXTOFFSET(Ecx) );
output( "\tmovl %%edx, %d(%%edi)\n", CONTEXTOFFSET(Edx) );
output( "\tmovl %%ebp, %d(%%edi)\n", CONTEXTOFFSET(Ebp) );
output( "\tmovl %%esi, %d(%%edi)\n", CONTEXTOFFSET(Esp) );
output( "\tmovl %%eax,0xb0(%%edi)\n"); /* Eax */
output( "\tmovl %%ebx,0xa4(%%edi)\n"); /* Ebx */
output( "\tmovl %%ecx,0xac(%%edi)\n"); /* Ecx */
output( "\tmovl %%edx,0xa8(%%edi)\n"); /* Edx */
output( "\tmovl %%ebp,0xb4(%%edi)\n"); /* Ebp */
output( "\tmovl %%esi,0xc4(%%edi)\n"); /* Esp */
/* The return glue code saved %esp into %esi */
}
@ -476,33 +463,33 @@ static void BuildCallTo16Core( int reg_func )
/* Make %bp point to the previous stackframe (built by CallFrom16) */
output( "\tmovzwl %%sp,%%ebp\n" );
output( "\tleal %d(%%ebp),%%ebp\n", STACK16OFFSET(bp) );
output( "\tleal 0x2a(%%ebp),%%ebp\n"); /* FIELD_OFFSET(STACK16FRAME,bp) */
/* Add the specified offset to the new sp */
output( "\tsubw %d(%%edx), %%sp\n", STACK32OFFSET(nb_args) );
output( "\tsubw 0x2c(%%edx), %%sp\n"); /* FIELD_OFFSET(STACK32FRAME,nb_args) */
if (reg_func)
{
/* Push the called routine address */
output( "\tmovl %d(%%edx),%%edx\n", STACK32OFFSET(target) );
output( "\tpushw %d(%%edx)\n", CONTEXTOFFSET(SegCs) );
output( "\tpushw %d(%%edx)\n", CONTEXTOFFSET(Eip) );
output( "\tmovl 0x28(%%edx),%%edx\n"); /* FIELD_OFFSET(STACK32FRAME,target) */
output( "\tpushw 0xbc(%%edx)\n"); /* SegCs */
output( "\tpushw 0xb8(%%edx)\n"); /* Eip */
/* Get the registers */
output( "\tpushw %d(%%edx)\n", CONTEXTOFFSET(SegDs) );
output( "\tpushl %d(%%edx)\n", CONTEXTOFFSET(SegEs) );
output( "\tpushw 0x98(%%edx)\n"); /* SegDs */
output( "\tpushl 0x94(%%edx)\n"); /* SegEs */
output( "\tpopl %%es\n" );
output( "\tpushl %d(%%edx)\n", CONTEXTOFFSET(SegFs) );
output( "\tpushl 0x90(%%edx)\n"); /* SegFs */
output( "\tpopl %%fs\n" );
output( "\tpushl %d(%%edx)\n", CONTEXTOFFSET(SegGs) );
output( "\tpushl 0x8c(%%edx)\n"); /* SegGs */
output( "\tpopl %%gs\n" );
output( "\tmovl %d(%%edx),%%ebp\n", CONTEXTOFFSET(Ebp) );
output( "\tmovl %d(%%edx),%%esi\n", CONTEXTOFFSET(Esi) );
output( "\tmovl %d(%%edx),%%edi\n", CONTEXTOFFSET(Edi) );
output( "\tmovl %d(%%edx),%%eax\n", CONTEXTOFFSET(Eax) );
output( "\tmovl %d(%%edx),%%ebx\n", CONTEXTOFFSET(Ebx) );
output( "\tmovl %d(%%edx),%%ecx\n", CONTEXTOFFSET(Ecx) );
output( "\tmovl %d(%%edx),%%edx\n", CONTEXTOFFSET(Edx) );
output( "\tmovl 0xb4(%%edx),%%ebp\n"); /* Ebp */
output( "\tmovl 0xa0(%%edx),%%esi\n"); /* Esi */
output( "\tmovl 0x9c(%%edx),%%edi\n"); /* Edi */
output( "\tmovl 0xb0(%%edx),%%eax\n"); /* Eax */
output( "\tmovl 0xa4(%%edx),%%ebx\n"); /* Ebx */
output( "\tmovl 0xac(%%edx),%%ecx\n"); /* Ecx */
output( "\tmovl 0xa8(%%edx),%%edx\n"); /* Edx */
/* Get the 16-bit ds */
output( "\tpopw %%ds\n" );
@ -510,12 +497,12 @@ static void BuildCallTo16Core( int reg_func )
else /* not a register function */
{
/* Push the called routine address */
output( "\tpushl %d(%%edx)\n", STACK32OFFSET(target) );
output( "\tpushl 0x28(%%edx)\n"); /* FIELD_OFFSET(STACK32FRAME,target) */
/* Set %fs and %gs to the value saved by the last CallFrom16 */
output( "\tpushw %d(%%ebp)\n", STACK16OFFSET(fs)-STACK16OFFSET(bp) );
output( "\tpushw -22(%%ebp)\n" ); /* FIELD_OFFSET(STACK16FRAME,fs)-FIELD_OFFSET(STACK16FRAME,bp) */
output( "\tpopw %%fs\n" );
output( "\tpushw %d(%%ebp)\n", STACK16OFFSET(gs)-STACK16OFFSET(bp) );
output( "\tpushw -20(%%ebp)\n" ); /* FIELD_OFFSET(STACK16FRAME,gs)-FIELD_OFFSET(STACK16FRAME,bp) */
output( "\tpopw %%gs\n" );
/* Set %ds and %es (and %ax just in case) equal to %ss */
@ -659,7 +646,7 @@ static void BuildRet16Func(void)
* (ebp+4) ret addr
* (ebp) ebp
*/
static void BuildCallTo32CBClient( BOOL isEx )
static void BuildCallTo32CBClient( int isEx )
{
function_header( isEx ? "CALL32_CBClientEx" : "CALL32_CBClient" );
@ -761,7 +748,7 @@ static void BuildCallTo32CBClient( BOOL isEx )
*/
static void BuildCallFrom32Regs(void)
{
static const int STACK_SPACE = 128 + sizeof(CONTEXT86);
static const int STACK_SPACE = 128 + 0x2cc /* sizeof(CONTEXT86) */;
/* Function header */
@ -775,38 +762,37 @@ static void BuildCallFrom32Regs(void)
/* Build the context structure */
output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(Eax) - STACK_SPACE );
output( "\tmovl %%eax,0xb0(%%esp)\n" ); /* Eax */
output( "\tpushfl\n" );
output( "\tpopl %%eax\n" );
output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(EFlags) - STACK_SPACE );
output( "\tmovl %%eax,0xc0(%%esp)\n"); /* EFlags */
output( "\tmovl 0(%%ebp),%%eax\n" );
output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(Ebp) - STACK_SPACE );
output( "\tmovl %%ebx,%d(%%ebp)\n", CONTEXTOFFSET(Ebx) - STACK_SPACE );
output( "\tmovl %%ecx,%d(%%ebp)\n", CONTEXTOFFSET(Ecx) - STACK_SPACE );
output( "\tmovl %%edx,%d(%%ebp)\n", CONTEXTOFFSET(Edx) - STACK_SPACE );
output( "\tmovl %%esi,%d(%%ebp)\n", CONTEXTOFFSET(Esi) - STACK_SPACE );
output( "\tmovl %%edi,%d(%%ebp)\n", CONTEXTOFFSET(Edi) - STACK_SPACE );
output( "\tmovl %%eax,0xb4(%%esp)\n"); /* Ebp */
output( "\tmovl %%ebx,0xa4(%%esp)\n"); /* Ebx */
output( "\tmovl %%ecx,0xac(%%esp)\n"); /* Ecx */
output( "\tmovl %%edx,0xa8(%%esp)\n"); /* Edx */
output( "\tmovl %%esi,0xa0(%%esp)\n"); /* Esi */
output( "\tmovl %%edi,0x9c(%%esp)\n"); /* Edi */
output( "\txorl %%eax,%%eax\n" );
output( "\tmovw %%cs,%%ax\n" );
output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(SegCs) - STACK_SPACE );
output( "\tmovl %%eax,0xbc(%%esp)\n"); /* SegCs */
output( "\tmovw %%es,%%ax\n" );
output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(SegEs) - STACK_SPACE );
output( "\tmovl %%eax,0x94(%%esp)\n"); /* SegEs */
output( "\tmovw %%fs,%%ax\n" );
output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(SegFs) - STACK_SPACE );
output( "\tmovl %%eax,0x90(%%esp)\n"); /* SegFs */
output( "\tmovw %%gs,%%ax\n" );
output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(SegGs) - STACK_SPACE );
output( "\tmovl %%eax,0x8c(%%esp)\n"); /* SegGs */
output( "\tmovw %%ss,%%ax\n" );
output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(SegSs) - STACK_SPACE );
output( "\tmovl %%eax,0xc8(%%esp)\n"); /* SegSs */
output( "\tmovw %%ds,%%ax\n" );
output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(SegDs) - STACK_SPACE );
output( "\tmovl %%eax,0x98(%%esp)\n"); /* SegDs */
output( "\tmovw %%ax,%%es\n" ); /* set %es equal to %ds just in case */
output( "\tmovl $0x%x,%%eax\n", CONTEXT86_FULL );
output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(ContextFlags) - STACK_SPACE );
output( "\tmovl $0x10007,0(%%esp)\n"); /* ContextFlags */
output( "\tmovl 16(%%ebp),%%eax\n" ); /* Get %eip at time of call */
output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(Eip) - STACK_SPACE );
output( "\tmovl %%eax,0xb8(%%esp)\n"); /* Eip */
/* Transfer the arguments */
@ -822,7 +808,7 @@ static void BuildCallFrom32Regs(void)
output( "\trep\n\tmovsl\n" ); /* copy args */
output( "1:\tleal %d(%%ebp),%%eax\n", -STACK_SPACE ); /* get addr of context struct */
output( "\tmovl %%eax,(%%edi)\n" ); /* and pass it as extra arg */
output( "\tmovl %%esi,%d(%%ebp)\n", CONTEXTOFFSET(Esp) - STACK_SPACE );
output( "\tmovl %%esi,%d(%%ebp)\n", 0xc4 /* Esp */ - STACK_SPACE );
/* Call the entry point */
@ -833,29 +819,29 @@ static void BuildCallFrom32Regs(void)
/* Restore the context structure */
output( "2:\tpushl %d(%%ecx)\n", CONTEXTOFFSET(SegEs) );
output( "2:\tpushl 0x94(%%ecx)\n"); /* SegEs */
output( "\tpopl %%es\n" );
output( "\tpushl %d(%%ecx)\n", CONTEXTOFFSET(SegFs) );
output( "\tpushl 0x90(%%ecx)\n"); /* SegFs */
output( "\tpopl %%fs\n" );
output( "\tpushl %d(%%ecx)\n", CONTEXTOFFSET(SegGs) );
output( "\tpushl 0x8c(%%ecx)\n"); /* SegGs */
output( "\tpopl %%gs\n" );
output( "\tmovl %d(%%ecx),%%edi\n", CONTEXTOFFSET(Edi) );
output( "\tmovl %d(%%ecx),%%esi\n", CONTEXTOFFSET(Esi) );
output( "\tmovl %d(%%ecx),%%edx\n", CONTEXTOFFSET(Edx) );
output( "\tmovl %d(%%ecx),%%ebx\n", CONTEXTOFFSET(Ebx) );
output( "\tmovl %d(%%ecx),%%eax\n", CONTEXTOFFSET(Eax) );
output( "\tmovl %d(%%ecx),%%ebp\n", CONTEXTOFFSET(Ebp) );
output( "\tmovl 0x9c(%%ecx),%%edi\n"); /* Edi */
output( "\tmovl 0xa0(%%ecx),%%esi\n"); /* Esi */
output( "\tmovl 0xa8(%%ecx),%%edx\n"); /* Edx */
output( "\tmovl 0xa4(%%ecx),%%ebx\n"); /* Ebx */
output( "\tmovl 0xb0(%%ecx),%%eax\n"); /* Eax */
output( "\tmovl 0xb4(%%ecx),%%ebp\n"); /* Ebp */
output( "\tpushl %d(%%ecx)\n", CONTEXTOFFSET(SegSs) );
output( "\tpushl 0xc8(%%ecx)\n"); /* SegSs */
output( "\tpopl %%ss\n" );
output( "\tmovl %d(%%ecx),%%esp\n", CONTEXTOFFSET(Esp) );
output( "\tmovl 0xc4(%%ecx),%%esp\n"); /* Esp */
output( "\tpushl %d(%%ecx)\n", CONTEXTOFFSET(EFlags) );
output( "\tpushl %d(%%ecx)\n", CONTEXTOFFSET(SegCs) );
output( "\tpushl %d(%%ecx)\n", CONTEXTOFFSET(Eip) );
output( "\tpushl %d(%%ecx)\n", CONTEXTOFFSET(SegDs) );
output( "\tmovl %d(%%ecx),%%ecx\n", CONTEXTOFFSET(Ecx) );
output( "\tpushl 0xc0(%%ecx)\n"); /* EFlags */
output( "\tpushl 0xbc(%%ecx)\n"); /* SegCs */
output( "\tpushl 0xb8(%%ecx)\n"); /* Eip */
output( "\tpushl 0x98(%%ecx)\n"); /* SegDs */
output( "\tmovl 0xac(%%ecx),%%ecx\n"); /* Ecx */
output( "\tpopl %%ds\n" );
output( "\tiret\n" );
@ -892,11 +878,9 @@ static void BuildPendingEventCheck(void)
/* Check for pending events. */
output( "\t.byte 0x64\n\ttestl $0xffffffff,(%d)\n",
STRUCTOFFSET(TEB,GdiTebBatch) + STRUCTOFFSET(WINE_VM86_TEB_INFO,vm86_pending) );
output( "\t.byte 0x64\n\ttestl $0xffffffff,(%d)\n", VM86_PENDING_OFFSET );
output( "\tje %s\n", asm_name("DPMI_PendingEventCheck_Cleanup") );
output( "\t.byte 0x64\n\ttestl $0xffffffff,(%d)\n",
STRUCTOFFSET(TEB,GdiTebBatch) + STRUCTOFFSET(WINE_VM86_TEB_INFO,dpmi_vif) );
output( "\t.byte 0x64\n\ttestl $0xffffffff,(%d)\n", DPMI_VIF_OFFSET );
output( "\tje %s\n", asm_name("DPMI_PendingEventCheck_Cleanup") );
/* Process pending events. */
@ -940,13 +924,13 @@ void BuildRelays16(void)
output( "%s\n", asm_globl("__wine_call16_start") );
/* Standard CallFrom16 routine */
BuildCallFrom16Core( FALSE, FALSE );
BuildCallFrom16Core( 0, 0 );
/* Register CallFrom16 routine */
BuildCallFrom16Core( TRUE, FALSE );
BuildCallFrom16Core( 1, 0 );
/* C16ThkSL CallFrom16 routine */
BuildCallFrom16Core( FALSE, TRUE );
BuildCallFrom16Core( 0, 1 );
/* Standard CallTo16 routine */
BuildCallTo16Core( 0 );
@ -958,10 +942,10 @@ void BuildRelays16(void)
BuildRet16Func();
/* CBClientThunkSL routine */
BuildCallTo32CBClient( FALSE );
BuildCallTo32CBClient( 0 );
/* CBClientThunkSLEx routine */
BuildCallTo32CBClient( TRUE );
BuildCallTo32CBClient( 1 );
/* Pending DPMI events check stub */
BuildPendingEventCheck();
@ -1003,55 +987,62 @@ void BuildRelays16(void)
static void build_call_from_regs_x86_64(void)
{
static const int STACK_SPACE = 128 + 0x4d0; /* size of x86_64 context */
int i;
/* Function header */
function_header( "__wine_call_from_regs" );
output( "\t.cfi_startproc\n" );
output( "\tsubq $%u,%%rsp\n", STACK_SPACE );
output( "\t.cfi_adjust_cfa_offset %u\n", STACK_SPACE );
/* save registers into the context */
output( "\tmovq %%rax,0x78(%%rsp)\n" );
output( "\t.cfi_rel_offset %%rax,0x78\n" );
output( "\tmovq %u(%%rsp),%%rax\n", STACK_SPACE + 16 ); /* saved %rcx on stack */
output( "\tmovq %%rax,0x80(%%rsp)\n" );
output( "\t.cfi_rel_offset %%rcx,0x80\n" );
output( "\tmovq %u(%%rsp),%%rax\n", STACK_SPACE + 24 ); /* saved %rdx on stack */
output( "\t.cfi_rel_offset %%rdx,0x88\n" );
output( "\tmovq %%rax,0x88(%%rsp)\n" );
output( "\tmovq %%rbx,0x90(%%rsp)\n" );
output( "\t.cfi_rel_offset %%rbx,0x90\n" );
output( "\tleaq %u(%%rsp),%%rax\n", STACK_SPACE + 16 );
output( "\tmovq %%rax,0x98(%%rsp)\n" );
output( "\tmovq %%rbp,0xa0(%%rsp)\n" );
output( "\t.cfi_rel_offset %%rbp,0xa0\n" );
output( "\tmovq %%rsi,0xa8(%%rsp)\n" );
output( "\t.cfi_rel_offset %%rsi,0xa8\n" );
output( "\tmovq %%rdi,0xb0(%%rsp)\n" );
output( "\t.cfi_rel_offset %%rdi,0xb0\n" );
output( "\tmovq %%r8,0xb8(%%rsp)\n" );
output( "\t.cfi_rel_offset %%r8,0xb8\n" );
output( "\tmovq %%r9,0xc0(%%rsp)\n" );
output( "\t.cfi_rel_offset %%r9,0xc0\n" );
output( "\tmovq %%r10,0xc8(%%rsp)\n" );
output( "\t.cfi_rel_offset %%r10,0xc8\n" );
output( "\tmovq %%r11,0xd0(%%rsp)\n" );
output( "\t.cfi_rel_offset %%r11,0xd0\n" );
output( "\tmovq %%r12,0xd8(%%rsp)\n" );
output( "\t.cfi_rel_offset %%r12,0xd8\n" );
output( "\tmovq %%r13,0xe0(%%rsp)\n" );
output( "\t.cfi_rel_offset %%r13,0xe0\n" );
output( "\tmovq %%r14,0xe8(%%rsp)\n" );
output( "\t.cfi_rel_offset %%r14,0xe8\n" );
output( "\tmovq %%r15,0xf0(%%rsp)\n" );
output( "\t.cfi_rel_offset %%r15,0xf0\n" );
output( "\tmovq %u(%%rsp),%%rax\n", STACK_SPACE + 8 );
output( "\tmovq %%rax,0xf8(%%rsp)\n" );
output( "\tstmxcsr 0x34(%%rsp)\n" );
output( "\tfxsave 0x100(%%rsp)\n" );
output( "\tmovdqa %%xmm0,0x1a0(%%rsp)\n" );
output( "\tmovdqa %%xmm1,0x1b0(%%rsp)\n" );
output( "\tmovdqa %%xmm2,0x1c0(%%rsp)\n" );
output( "\tmovdqa %%xmm3,0x1d0(%%rsp)\n" );
output( "\tmovdqa %%xmm4,0x1e0(%%rsp)\n" );
output( "\tmovdqa %%xmm5,0x1f0(%%rsp)\n" );
output( "\tmovdqa %%xmm6,0x200(%%rsp)\n" );
output( "\tmovdqa %%xmm7,0x210(%%rsp)\n" );
output( "\tmovdqa %%xmm8,0x220(%%rsp)\n" );
output( "\tmovdqa %%xmm9,0x230(%%rsp)\n" );
output( "\tmovdqa %%xmm10,0x240(%%rsp)\n" );
output( "\tmovdqa %%xmm11,0x250(%%rsp)\n" );
output( "\tmovdqa %%xmm12,0x260(%%rsp)\n" );
output( "\tmovdqa %%xmm13,0x270(%%rsp)\n" );
output( "\tmovdqa %%xmm14,0x280(%%rsp)\n" );
output( "\tmovdqa %%xmm15,0x290(%%rsp)\n" );
for (i = 0; i < 16; i++)
{
output( "\tmovdqa %%xmm%u,0x%x(%%rsp)\n", i, 0x1a0 + 16 * i );
output( "\t.cfi_rel_offset %%xmm%u,0x%x\n", i, 0x1a0 + 16 * i );
}
output( "\tmovw %%cs,0x38(%%rsp)\n" );
output( "\tmovw %%ds,0x3a(%%rsp)\n" );
@ -1074,6 +1065,7 @@ static void build_call_from_regs_x86_64(void)
output( "\tcmpq %%rax,%%rcx\n" );
output( "\tcmovgq %%rcx,%%rax\n" );
output( "\tmovq %%rsp,%%rbx\n" );
output( "\t.cfi_def_cfa_register %%rbx\n" );
output( "\tleaq 16(,%%rax,8),%%rax\n" ); /* add 8 for context arg and 8 for rounding */
output( "\tandq $~15,%%rax\n" );
output( "\tsubq %%rax,%%rsp\n" );
@ -1095,57 +1087,62 @@ static void build_call_from_regs_x86_64(void)
/* restore the context structure */
output( "1:\tmovq 0x80(%%rbx),%%rcx\n" );
output( "\t.cfi_same_value %%rcx\n" );
output( "\tmovq 0x88(%%rbx),%%rdx\n" );
output( "\t.cfi_same_value %%rdx\n" );
output( "\tmovq 0xa0(%%rbx),%%rbp\n" );
output( "\t.cfi_same_value %%rbp\n" );
output( "\tmovq 0xa8(%%rbx),%%rsi\n" );
output( "\t.cfi_same_value %%rsi\n" );
output( "\tmovq 0xb0(%%rbx),%%rdi\n" );
output( "\t.cfi_same_value %%rdi\n" );
output( "\tmovq 0xb8(%%rbx),%%r8\n" );
output( "\t.cfi_same_value %%r8\n" );
output( "\tmovq 0xc0(%%rbx),%%r9\n" );
output( "\t.cfi_same_value %%r9\n" );
output( "\tmovq 0xc8(%%rbx),%%r10\n" );
output( "\t.cfi_same_value %%r10\n" );
output( "\tmovq 0xd0(%%rbx),%%r11\n" );
output( "\t.cfi_same_value %%r11\n" );
output( "\tmovq 0xd8(%%rbx),%%r12\n" );
output( "\t.cfi_same_value %%r12\n" );
output( "\tmovq 0xe0(%%rbx),%%r13\n" );
output( "\t.cfi_same_value %%r13\n" );
output( "\tmovq 0xe8(%%rbx),%%r14\n" );
output( "\t.cfi_same_value %%r14\n" );
output( "\tmovq 0xf0(%%rbx),%%r15\n" );
output( "\t.cfi_same_value %%r15\n" );
output( "\tmovdqa 0x1a0(%%rbx),%%xmm0\n" );
output( "\tmovdqa 0x1b0(%%rbx),%%xmm1\n" );
output( "\tmovdqa 0x1c0(%%rbx),%%xmm2\n" );
output( "\tmovdqa 0x1d0(%%rbx),%%xmm3\n" );
output( "\tmovdqa 0x1e0(%%rbx),%%xmm4\n" );
output( "\tmovdqa 0x1f0(%%rbx),%%xmm5\n" );
output( "\tmovdqa 0x200(%%rbx),%%xmm6\n" );
output( "\tmovdqa 0x210(%%rbx),%%xmm7\n" );
output( "\tmovdqa 0x220(%%rbx),%%xmm8\n" );
output( "\tmovdqa 0x230(%%rbx),%%xmm9\n" );
output( "\tmovdqa 0x240(%%rbx),%%xmm10\n" );
output( "\tmovdqa 0x250(%%rbx),%%xmm11\n" );
output( "\tmovdqa 0x260(%%rbx),%%xmm12\n" );
output( "\tmovdqa 0x270(%%rbx),%%xmm13\n" );
output( "\tmovdqa 0x280(%%rbx),%%xmm14\n" );
output( "\tmovdqa 0x290(%%rbx),%%xmm15\n" );
for (i = 0; i < 16; i++)
{
output( "\tmovdqa 0x%x(%%rbx),%%xmm%u\n", 0x1a0 + 16 * i, i );
output( "\t.cfi_same_value %%xmm%u\n", i );
}
output( "\tfxrstor 0x100(%%rbx)\n" );
output( "\tldmxcsr 0x34(%%rbx)\n" );
output( "\tmovl 0x44(%%rbx),%%eax\n" );
output( "\tpushq %%rax\n" );
output( "\tpopfq\n" );
output( "\tmovq 0x98(%%rbx),%%rax\n" ); /* stack pointer */
output( "\tpushq 0xf8(%%rbx)\n" ); /* return address */
output( "\tpopq -8(%%rax)\n" );
output( "\tpushq 0x78(%%rbx)\n" ); /* rax */
output( "\tpopq -16(%%rax)\n" );
output( "\tmovq 0xf8(%%rbx),%%rax\n" ); /* rip */
output( "\tmovq %%rax,0(%%rsp)\n" );
output( "\tmovw 0x38(%%rbx),%%ax\n" ); /* cs */
output( "\tmovq %%rax,0x8(%%rsp)\n" );
output( "\tmovl 0x44(%%rbx),%%eax\n" ); /* flags */
output( "\tmovq %%rax,0x10(%%rsp)\n" );
output( "\tmovq 0x98(%%rbx),%%rax\n" ); /* rsp */
output( "\tmovq %%rax,0x18(%%rsp)\n" );
output( "\tmovw 0x42(%%rbx),%%ax\n" ); /* ss */
output( "\tmovq %%rax,0x20(%%rsp)\n" );
output( "\tmovq 0x78(%%rbx),%%rax\n" );
output( "\tmovq 0x90(%%rbx),%%rbx\n" );
output( "\tleaq -16(%%rax),%%rsp\n" );
output( "\tpopq %%rax\n" );
output( "\tret\n" );
output( "\tiretq\n" );
output( "\t.cfi_endproc\n" );
output_function_size( "__wine_call_from_regs" );
function_header( "__wine_restore_regs" );
output( "\t.cfi_startproc\n" );
output( "\tmovq %%rcx,%%rbx\n" );
output( "\tjmp 1b\n" );
output( "\t.cfi_endproc\n" );
output_function_size( "__wine_restore_regs" );
}

View file

@ -31,21 +31,14 @@
# include <sys/types.h>
#endif
#include <fcntl.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#include "winglue.h"
#include "build.h"
/* Unicode string or integer id */
struct string_id
{
char *str; /* ptr to string */
WORD id; /* integer id if str is NULL */
unsigned short id; /* integer id if str is NULL */
};
/* descriptor for a resource */
@ -54,15 +47,17 @@ struct resource
struct string_id type;
struct string_id name;
const void *data;
unsigned int name_offset;
unsigned int data_size;
WORD memopt;
unsigned int memopt;
};
/* type level of the resource tree */
struct res_type
{
const struct string_id *type; /* type name */
const struct resource *res; /* first resource of this type */
struct resource *res; /* first resource of this type */
unsigned int name_offset; /* name offset if string */
unsigned int nb_names; /* total number of names */
};
@ -73,10 +68,6 @@ struct res_tree
unsigned int nb_types; /* total number of types */
};
static const unsigned char *file_pos; /* current position in resource file */
static const unsigned char *file_end; /* end of resource file */
static const char *file_name; /* current resource file name */
static inline struct resource *add_resource( DLLSPEC *spec )
{
@ -84,7 +75,7 @@ static inline struct resource *add_resource( DLLSPEC *spec )
return &spec->resources[spec->nb_resources++];
}
static struct res_type *add_type( struct res_tree *tree, const struct resource *res )
static struct res_type *add_type( struct res_tree *tree, struct resource *res )
{
struct res_type *type;
tree->types = xrealloc( tree->types, (tree->nb_types + 1) * sizeof(*tree->types) );
@ -95,56 +86,21 @@ static struct res_type *add_type( struct res_tree *tree, const struct resource *
return type;
}
/* get the next byte from the current resource file */
static unsigned char get_byte(void)
{
unsigned char ret = *file_pos++;
if (file_pos > file_end) fatal_error( "%s is a truncated/corrupted file\n", file_name );
return ret;
}
/* get the next word from the current resource file */
static WORD get_word(void)
{
/* might not be aligned */
#ifdef WORDS_BIGENDIAN
unsigned char high = get_byte();
unsigned char low = get_byte();
#else
unsigned char low = get_byte();
unsigned char high = get_byte();
#endif
return low | (high << 8);
}
/* get the next dword from the current resource file */
static DWORD get_dword(void)
{
#ifdef WORDS_BIGENDIAN
WORD high = get_word();
WORD low = get_word();
#else
WORD low = get_word();
WORD high = get_word();
#endif
return low | (high << 16);
}
/* get a string from the current resource file */
static void get_string( struct string_id *str )
{
if (*file_pos == 0xff)
unsigned char c = get_byte();
if (c == 0xff)
{
get_byte(); /* skip the 0xff */
str->str = NULL;
str->id = get_word();
}
else
{
char *p = xmalloc(strlen((const char *)file_pos) + 1);
str->str = p;
str->str = (char *)input_buffer + input_buffer_pos - 1;
str->id = 0;
while ((*p++ = get_byte()));
while (get_byte()) /* nothing */;
}
}
@ -157,34 +113,17 @@ static void load_next_resource( DLLSPEC *spec )
get_string( &res->name );
res->memopt = get_word();
res->data_size = get_dword();
res->data = file_pos;
file_pos += res->data_size;
if (file_pos > file_end) fatal_error( "%s is a truncated/corrupted file\n", file_name );
res->data = input_buffer + input_buffer_pos;
input_buffer_pos += res->data_size;
if (input_buffer_pos > input_buffer_size)
fatal_error( "%s is a truncated/corrupted file\n", input_buffer_filename );
}
/* load a Win16 .res file */
void load_res16_file( const char *name, DLLSPEC *spec )
{
int fd;
void *base;
struct stat st;
if ((fd = open( name, O_RDONLY )) == -1) fatal_perror( "Cannot open %s", name );
if ((fstat( fd, &st ) == -1)) fatal_perror( "Cannot stat %s", name );
if (!st.st_size) fatal_error( "%s is an empty file\n", name );
#ifdef HAVE_MMAP
if ((base = mmap( NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0 )) == (void*)-1)
#endif /* HAVE_MMAP */
{
base = xmalloc( st.st_size );
if (read( fd, base, st.st_size ) != st.st_size)
fatal_error( "Cannot read %s\n", name );
}
file_name = name;
file_pos = base;
file_end = file_pos + st.st_size;
while (file_pos < file_end) load_next_resource( spec );
init_input_buffer( name );
while (input_buffer_pos < input_buffer_size) load_next_resource( spec );
}
/* compare two strings/ids */
@ -214,12 +153,14 @@ static int cmp_res( const void *ptr1, const void *ptr2 )
/* build the 2-level (type,name) resource tree */
static struct res_tree *build_resource_tree( DLLSPEC *spec )
{
unsigned int i;
unsigned int i, j, offset;
struct res_tree *tree;
struct res_type *type = NULL;
struct resource *res;
qsort( spec->resources, spec->nb_resources, sizeof(*spec->resources), cmp_res );
offset = 2; /* alignment */
tree = xmalloc( sizeof(*tree) );
tree->types = NULL;
tree->nb_types = 0;
@ -227,8 +168,33 @@ static struct res_tree *build_resource_tree( DLLSPEC *spec )
for (i = 0; i < spec->nb_resources; i++)
{
if (!i || cmp_string( &spec->resources[i].type, &spec->resources[i-1].type )) /* new type */
{
type = add_type( tree, &spec->resources[i] );
offset += 8;
}
type->nb_names++;
offset += 12;
}
offset += 2; /* terminator */
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
if (type->type->str)
{
type->name_offset = offset;
offset += strlen(type->type->str) + 1;
}
else type->name_offset = type->type->id | 0x8000;
for (j = 0, res = type->res; j < type->nb_names; j++, res++)
{
if (res->name.str)
{
res->name_offset = offset;
offset += strlen(res->name.str) + 1;
}
else res->name_offset = res->name.id | 0x8000;
}
}
return tree;
}
@ -249,24 +215,28 @@ static void output_string( const char *str )
output( " /* %s */\n", str );
}
/* output a string preceded by its length in binary format*/
static void output_bin_string( const char *str )
{
put_byte( strlen(str) );
while (*str) put_byte( *str++ );
}
/* output the resource data */
void output_res16_data( DLLSPEC *spec )
{
const struct resource *res;
unsigned int i;
if (!spec->nb_resources) return;
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
{
output( ".L__wine_spec_resource_%u:\n", i );
dump_bytes( res->data, res->data_size );
output( ".L__wine_spec_resource_%u_end:\n", i );
}
}
/* output the resource definitions */
void output_res16_directory( DLLSPEC *spec, const char *header_name )
void output_res16_directory( DLLSPEC *spec )
{
unsigned int i, j;
struct res_tree *tree;
@ -282,29 +252,13 @@ void output_res16_directory( DLLSPEC *spec, const char *header_name )
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
if (type->type->str)
output( "\t%s .L__wine_spec_restype_%u-.L__wine_spec_ne_rsrctab\n",
get_asm_short_keyword(), i );
else
output( "\t%s 0x%04x\n", get_asm_short_keyword(), type->type->id | 0x8000 );
output( "\t%s %u,0,0\n", get_asm_short_keyword(), type->nb_names );
output( "\t%s 0x%04x,%u,0,0\n", get_asm_short_keyword(), type->name_offset, type->nb_names );
for (j = 0, res = type->res; j < type->nb_names; j++, res++)
{
output( "\t%s .L__wine_spec_resource_%lu-%s\n",
get_asm_short_keyword(), (unsigned long)(res - spec->resources), header_name );
output( "\t%s .L__wine_spec_resource_%lu_end-.L__wine_spec_resource_%lu\n",
get_asm_short_keyword(), (unsigned long)(res - spec->resources),
(unsigned long)(res - spec->resources) );
output( "\t%s 0x%04x\n", get_asm_short_keyword(), res->memopt );
if (res->name.str)
output( "\t%s .L__wine_spec_resname_%u_%u-.L__wine_spec_ne_rsrctab\n",
get_asm_short_keyword(), i, j );
else
output( "\t%s 0x%04x\n", get_asm_short_keyword(), res->name.id | 0x8000 );
output( "\t%s 0,0\n", get_asm_short_keyword() );
output( "\t%s .L__wine_spec_resource_%lu-.L__wine_spec_dos_header,%u\n",
get_asm_short_keyword(), (unsigned long)(res - spec->resources), res->data_size );
output( "\t%s 0x%04x,0x%04x,0,0\n", get_asm_short_keyword(), res->memopt, res->name_offset );
}
}
output( "\t%s 0\n", get_asm_short_keyword() ); /* terminator */
@ -313,21 +267,68 @@ void output_res16_directory( DLLSPEC *spec, const char *header_name )
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
if (type->type->str)
{
output( ".L__wine_spec_restype_%u:\n", i );
output_string( type->type->str );
}
if (type->type->str) output_string( type->type->str );
for (j = 0, res = type->res; j < type->nb_names; j++, res++)
{
if (res->name.str)
{
output( ".L__wine_spec_resname_%u_%u:\n", i, j );
output_string( res->name.str );
}
}
if (res->name.str) output_string( res->name.str );
}
output( "\t.byte 0\n" ); /* names terminator */
free_resource_tree( tree );
}
/* output the resource data in binary format */
void output_bin_res16_data( DLLSPEC *spec )
{
const struct resource *res;
unsigned int i;
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
put_data( res->data, res->data_size );
}
/* output the resource definitions in binary format */
void output_bin_res16_directory( DLLSPEC *spec, unsigned int data_offset )
{
unsigned int i, j;
struct res_tree *tree;
const struct res_type *type;
const struct resource *res;
tree = build_resource_tree( spec );
put_word( 0 ); /* alignment */
/* type and name structures */
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
put_word( type->name_offset );
put_word( type->nb_names );
put_word( 0 );
put_word( 0 );
for (j = 0, res = type->res; j < type->nb_names; j++, res++)
{
put_word( data_offset );
put_word( res->data_size );
put_word( res->memopt );
put_word( res->name_offset );
put_word( 0 );
put_word( 0 );
data_offset += res->data_size;
}
}
put_word( 0 ); /* terminator */
/* name strings */
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
if (type->type->str) output_bin_string( type->type->str );
for (j = 0, res = type->res; j < type->nb_names; j++, res++)
if (res->name.str) output_bin_string( res->name.str );
}
put_byte( 0 ); /* names terminator */
free_resource_tree( tree );
}

View file

@ -21,6 +21,7 @@
#include "config.h"
#include "wine/port.h"
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
@ -30,16 +31,13 @@
# include <sys/types.h>
#endif
#include <fcntl.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#include "winglue.h"
#include "build.h"
typedef unsigned short WCHAR;
typedef unsigned short WORD;
typedef unsigned int DWORD;
/* Unicode string or integer id */
struct string_id
{
@ -54,15 +52,18 @@ struct resource
struct string_id name;
const void *data;
unsigned int data_size;
WORD lang;
unsigned int data_offset;
unsigned short mem_options;
unsigned short lang;
};
/* name level of the resource tree */
struct res_name
{
const struct string_id *name; /* name */
const struct resource *res; /* resource */
struct resource *res; /* resource */
int nb_languages; /* number of languages */
unsigned int dir_offset; /* offset of directory in resource dir */
unsigned int name_offset; /* offset of name in resource dir */
};
@ -73,6 +74,7 @@ struct res_type
struct res_name *names; /* names array */
unsigned int nb_names; /* total number of names */
unsigned int nb_id_names; /* number of names that have a numeric id */
unsigned int dir_offset; /* offset of directory in resource dir */
unsigned int name_offset; /* offset of type name in resource dir */
};
@ -83,13 +85,11 @@ struct res_tree
unsigned int nb_types; /* total number of types */
};
static int byte_swapped; /* whether the current resource file is byte-swapped */
static const unsigned char *file_pos; /* current position in resource file */
static const unsigned char *file_end; /* end of resource file */
static const char *file_name; /* current resource file name */
/* size of a resource directory with n entries */
#define RESDIR_SIZE(n) (sizeof(IMAGE_RESOURCE_DIRECTORY) + (n) * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY))
#define RESOURCE_DIR_SIZE (4 * sizeof(unsigned int))
#define RESOURCE_DIR_ENTRY_SIZE (2 * sizeof(unsigned int))
#define RESOURCE_DATA_ENTRY_SIZE (4 * sizeof(unsigned int))
#define RESDIR_SIZE(n) (RESOURCE_DIR_SIZE + (n) * RESOURCE_DIR_ENTRY_SIZE)
static inline struct resource *add_resource( DLLSPEC *spec )
@ -111,7 +111,7 @@ static inline int strcmpW( const WCHAR *str1, const WCHAR *str2 )
return *str1 - *str2;
}
static struct res_name *add_name( struct res_type *type, const struct resource *res )
static struct res_name *add_name( struct res_type *type, struct resource *res )
{
struct res_name *name;
type->names = xrealloc( type->names, (type->nb_names + 1) * sizeof(*type->names) );
@ -123,7 +123,7 @@ static struct res_name *add_name( struct res_type *type, const struct resource *
return name;
}
static struct res_type *add_type( struct res_tree *tree, const struct resource *res )
static struct res_type *add_type( struct res_tree *tree, struct resource *res )
{
struct res_type *type;
tree->types = xrealloc( tree->types, (tree->nb_types + 1) * sizeof(*tree->types) );
@ -135,45 +135,64 @@ static struct res_type *add_type( struct res_tree *tree, const struct resource *
return type;
}
/* get the next word from the current resource file */
static WORD get_word(void)
{
WORD ret = *(const WORD *)file_pos;
if (byte_swapped) ret = (ret << 8) | (ret >> 8);
file_pos += sizeof(WORD);
if (file_pos > file_end) fatal_error( "%s is a truncated file\n", file_name );
return ret;
}
/* get the next dword from the current resource file */
static DWORD get_dword(void)
{
DWORD ret = *(const DWORD *)file_pos;
if (byte_swapped)
ret = ((ret << 24) | ((ret << 8) & 0x00ff0000) | ((ret >> 8) & 0x0000ff00) | (ret >> 24));
file_pos += sizeof(DWORD);
if (file_pos > file_end) fatal_error( "%s is a truncated file\n", file_name );
return ret;
}
/* get a string from the current resource file */
static void get_string( struct string_id *str )
{
if (*(const WCHAR *)file_pos == 0xffff)
WCHAR wc = get_word();
if (wc == 0xffff)
{
get_word(); /* skip the 0xffff */
str->str = NULL;
str->id = get_word();
}
else
{
WCHAR *p = xmalloc( (strlenW((const WCHAR*)file_pos) + 1) * sizeof(WCHAR) );
WCHAR *p = xmalloc( (strlenW( (const WCHAR *)(input_buffer + input_buffer_pos) - 1) + 1) * sizeof(WCHAR) );
str->str = p;
str->id = 0;
while ((*p++ = get_word()));
if ((*p++ = wc)) while ((*p++ = get_word()));
}
}
/* put a string into the resource file */
static void put_string( const struct string_id *str )
{
if (str->str)
{
const WCHAR *p = str->str;
while (*p) put_word( *p++ );
put_word( 0 );
}
else
{
put_word( 0xffff );
put_word( str->id );
}
}
static void dump_res_data( const struct resource *res )
{
unsigned int i = 0;
unsigned int size = (res->data_size + 3) & ~3;
if (!size) return;
input_buffer = res->data;
input_buffer_pos = 0;
input_buffer_size = size;
output( "\t.long " );
while (size > 4)
{
if ((i++ % 16) == 15) output( "0x%08x\n\t.long ", get_dword() );
else output( "0x%08x,", get_dword() );
size -= 4;
}
output( "0x%08x\n", get_dword() );
size -= 4;
assert( input_buffer_pos == input_buffer_size );
}
/* check the file header */
/* all values must be zero except header size */
static int check_header(void)
@ -200,52 +219,37 @@ static void load_next_resource( DLLSPEC *spec )
DWORD hdr_size;
struct resource *res = add_resource( spec );
res->data_size = (get_dword() + 3) & ~3;
res->data_size = get_dword();
hdr_size = get_dword();
if (hdr_size & 3) fatal_error( "%s header size not aligned\n", file_name );
if (hdr_size & 3) fatal_error( "%s header size not aligned\n", input_buffer_filename );
res->data = file_pos - 2*sizeof(DWORD) + hdr_size;
res->data = input_buffer + input_buffer_pos - 2*sizeof(DWORD) + hdr_size;
get_string( &res->type );
get_string( &res->name );
if ((UINT_PTR)file_pos & 2) get_word(); /* align to dword boundary */
if (input_buffer_pos & 2) get_word(); /* align to dword boundary */
get_dword(); /* skip data version */
get_word(); /* skip mem options */
res->mem_options = get_word();
res->lang = get_word();
get_dword(); /* skip version */
get_dword(); /* skip characteristics */
file_pos = (const unsigned char *)res->data + res->data_size;
if (file_pos > file_end) fatal_error( "%s is a truncated file\n", file_name );
input_buffer_pos = ((const unsigned char *)res->data - input_buffer) + ((res->data_size + 3) & ~3);
input_buffer_pos = (input_buffer_pos + 3) & ~3;
if (input_buffer_pos > input_buffer_size)
fatal_error( "%s is a truncated file\n", input_buffer_filename );
}
/* load a Win32 .res file */
int load_res32_file( const char *name, DLLSPEC *spec )
{
int fd, ret;
void *base;
struct stat st;
int ret;
if ((fd = open( name, O_RDONLY )) == -1) fatal_perror( "Cannot open %s", name );
if ((fstat( fd, &st ) == -1)) fatal_perror( "Cannot stat %s", name );
if (!st.st_size) fatal_error( "%s is an empty file\n", name );
#ifdef HAVE_MMAP
if ((base = mmap( NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0 )) == (void*)-1)
#endif /* HAVE_MMAP */
{
base = xmalloc( st.st_size );
if (read( fd, base, st.st_size ) != st.st_size)
fatal_error( "Cannot read %s\n", name );
}
init_input_buffer( name );
byte_swapped = 0;
file_name = name;
file_pos = base;
file_end = file_pos + st.st_size;
if ((ret = check_header()))
{
while (file_pos < file_end) load_next_resource( spec );
while (input_buffer_pos < input_buffer_size) load_next_resource( spec );
}
close( fd );
return ret;
}
@ -274,13 +278,24 @@ static int cmp_res( const void *ptr1, const void *ptr2 )
return res1->lang - res2->lang;
}
/* build the 3-level (type,name,language) resource tree */
static struct res_tree *build_resource_tree( DLLSPEC *spec )
static char *format_res_string( const struct string_id *str )
{
unsigned int i;
int i, len = str->str ? strlenW(str->str) + 1 : 5;
char *ret = xmalloc( len );
if (!str->str) sprintf( ret, "%04x", str->id );
else for (i = 0; i < len; i++) ret[i] = str->str[i]; /* dumb W->A conversion */
return ret;
}
/* build the 3-level (type,name,language) resource tree */
static struct res_tree *build_resource_tree( DLLSPEC *spec, unsigned int *dir_size )
{
unsigned int i, k, n, offset, data_offset;
struct res_tree *tree;
struct res_type *type = NULL;
struct res_name *name = NULL;
struct resource *res;
qsort( spec->resources, spec->nb_resources, sizeof(*spec->resources), cmp_res );
@ -299,8 +314,57 @@ static struct res_tree *build_resource_tree( DLLSPEC *spec )
{
name = add_name( type, &spec->resources[i] );
}
else if (spec->resources[i].lang == spec->resources[i-1].lang)
{
char *type_str = format_res_string( &spec->resources[i].type );
char *name_str = format_res_string( &spec->resources[i].name );
error( "winebuild: duplicate resource type %s name %s language %04x\n",
type_str, name_str, spec->resources[i].lang );
}
else name->nb_languages++;
}
/* compute the offsets */
offset = RESDIR_SIZE( tree->nb_types );
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
type->dir_offset = offset;
offset += RESDIR_SIZE( type->nb_names );
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
{
name->dir_offset = offset;
offset += RESDIR_SIZE( name->nb_languages );
}
}
data_offset = offset;
offset += spec->nb_resources * RESOURCE_DATA_ENTRY_SIZE;
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
if (type->type->str)
{
type->name_offset = offset | 0x80000000;
offset += (strlenW(type->type->str)+1) * sizeof(WCHAR);
}
else type->name_offset = type->type->id;
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
{
if (name->name->str)
{
name->name_offset = offset | 0x80000000;
offset += (strlenW(name->name->str)+1) * sizeof(WCHAR);
}
else name->name_offset = name->name->id;
for (k = 0, res = name->res; k < name->nb_languages; k++, res++)
{
unsigned int entry_offset = (res - spec->resources) * RESOURCE_DATA_ENTRY_SIZE;
res->data_offset = data_offset + entry_offset;
}
}
}
if (dir_size) *dir_size = (offset + 3) & ~3;
return tree;
}
@ -340,7 +404,7 @@ static inline void output_res_dir( unsigned int nb_names, unsigned int nb_ids )
void output_resources( DLLSPEC *spec )
{
int k, nb_id_types;
unsigned int i, n, offset, data_offset;
unsigned int i, n;
struct res_tree *tree;
struct res_type *type;
struct res_name *name;
@ -348,42 +412,7 @@ void output_resources( DLLSPEC *spec )
if (!spec->nb_resources) return;
tree = build_resource_tree( spec );
/* compute the offsets */
offset = RESDIR_SIZE( tree->nb_types );
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
offset += RESDIR_SIZE( type->nb_names );
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
offset += RESDIR_SIZE( name->nb_languages );
}
offset += spec->nb_resources * sizeof(IMAGE_RESOURCE_DATA_ENTRY);
for (i = nb_id_types = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
if (type->type->str)
{
type->name_offset = offset | 0x80000000;
offset += (strlenW(type->type->str)+1) * sizeof(WCHAR);
}
else
{
type->name_offset = type->type->id;
nb_id_types++;
}
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
{
if (name->name->str)
{
name->name_offset = offset | 0x80000000;
offset += (strlenW(name->name->str)+1) * sizeof(WCHAR);
}
else name->name_offset = name->name->id;
}
}
tree = build_resource_tree( spec, NULL );
/* output the resource directories */
@ -392,44 +421,31 @@ void output_resources( DLLSPEC *spec )
output( "\t.align %d\n", get_alignment(get_ptr_size()) );
output( ".L__wine_spec_resources:\n" );
for (i = nb_id_types = 0, type = tree->types; i < tree->nb_types; i++, type++)
if (!type->type->str) nb_id_types++;
output_res_dir( tree->nb_types - nb_id_types, nb_id_types );
/* dump the type directory */
offset = RESDIR_SIZE( tree->nb_types );
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
output( "\t.long 0x%08x,0x%08x\n",
type->name_offset, offset | 0x80000000 );
offset += RESDIR_SIZE( type->nb_names );
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
offset += RESDIR_SIZE( name->nb_languages );
}
data_offset = offset;
offset = RESDIR_SIZE( tree->nb_types );
type->name_offset, type->dir_offset | 0x80000000 );
/* dump the names and languages directories */
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
output_res_dir( type->nb_names - type->nb_id_names, type->nb_id_names );
offset += RESDIR_SIZE( type->nb_names );
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
{
output( "\t.long 0x%08x,0x%08x\n",
name->name_offset, offset | 0x80000000 );
offset += RESDIR_SIZE( name->nb_languages );
}
name->name_offset, name->dir_offset | 0x80000000 );
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
{
output_res_dir( 0, name->nb_languages );
for (k = 0, res = name->res; k < name->nb_languages; k++, res++)
{
unsigned int entry_offset = (res - spec->resources) * sizeof(IMAGE_RESOURCE_DATA_ENTRY);
output( "\t.long 0x%08x,0x%08x\n", res->lang, data_offset + entry_offset );
}
output( "\t.long 0x%08x,0x%08x\n", res->lang, res->data_offset );
}
}
@ -437,7 +453,7 @@ void output_resources( DLLSPEC *spec )
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
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 + 3) & ~3 );
/* dump the name strings */
@ -454,10 +470,197 @@ void output_resources( DLLSPEC *spec )
{
output( "\n\t.align %d\n", get_alignment(get_ptr_size()) );
output( ".L__wine_spec_res_%d:\n", i );
dump_bytes( res->data, res->data_size );
dump_res_data( res );
}
output( ".L__wine_spec_resources_end:\n" );
output( "\t.byte 0\n" );
free_resource_tree( tree );
}
/* output a Unicode string in binary format */
static void output_bin_string( const WCHAR *name )
{
int i, len = strlenW(name);
put_word( len );
for (i = 0; i < len; i++) put_word( name[i] );
}
/* output a resource directory in binary format */
static inline void output_bin_res_dir( unsigned int nb_names, unsigned int nb_ids )
{
put_dword( 0 ); /* Characteristics */
put_dword( 0 ); /* TimeDateStamp */
put_word( 0 ); /* MajorVersion */
put_word( 0 ); /* MinorVersion */
put_word( nb_names ); /* NumberOfNamedEntries */
put_word( nb_ids ); /* NumberOfIdEntries */
}
/* output the resource definitions in binary format */
void output_bin_resources( DLLSPEC *spec, unsigned int start_rva )
{
int k, nb_id_types;
unsigned int i, n, data_offset;
struct res_tree *tree;
struct res_type *type;
struct res_name *name;
const struct resource *res;
if (!spec->nb_resources) return;
tree = build_resource_tree( spec, &data_offset );
init_output_buffer();
/* output the resource directories */
for (i = nb_id_types = 0, type = tree->types; i < tree->nb_types; i++, type++)
if (!type->type->str) nb_id_types++;
output_bin_res_dir( tree->nb_types - nb_id_types, nb_id_types );
/* dump the type directory */
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
put_dword( type->name_offset );
put_dword( type->dir_offset | 0x80000000 );
}
/* dump the names and languages directories */
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
output_bin_res_dir( type->nb_names - type->nb_id_names, type->nb_id_names );
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
{
put_dword( name->name_offset );
put_dword( name->dir_offset | 0x80000000 );
}
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
{
output_bin_res_dir( 0, name->nb_languages );
for (k = 0, res = name->res; k < name->nb_languages; k++, res++)
{
put_dword( res->lang );
put_dword( res->data_offset );
}
}
}
/* dump the resource data entries */
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
{
put_dword( data_offset + start_rva );
put_dword( (res->data_size + 3) & ~3 );
put_dword( 0 );
put_dword( 0 );
data_offset += (res->data_size + 3) & ~3;
}
/* dump the name strings */
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
if (type->type->str) output_bin_string( type->type->str );
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
if (name->name->str) output_bin_string( name->name->str );
}
/* resource data */
align_output( 4 );
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
{
put_data( res->data, res->data_size );
align_output( 4 );
}
free_resource_tree( tree );
}
static unsigned int get_resource_header_size( const struct resource *res )
{
unsigned int size = 5 * sizeof(unsigned int) + 2 * sizeof(unsigned short);
if (!res->type.str) size += 2 * sizeof(unsigned short);
else size += (strlenW(res->type.str) + 1) * sizeof(WCHAR);
if (!res->name.str) size += 2 * sizeof(unsigned short);
else size += (strlenW(res->name.str) + 1) * sizeof(WCHAR);
return size;
}
/* output the resources into a .o file */
void output_res_o_file( DLLSPEC *spec )
{
unsigned int i;
char *res_file = NULL;
int fd, err;
if (!spec->nb_resources) fatal_error( "--resources mode needs at least one resource file as input\n" );
if (!output_file_name) fatal_error( "No output file name specified\n" );
byte_swapped = 0;
init_output_buffer();
put_dword( 0 ); /* ResSize */
put_dword( 32 ); /* HeaderSize */
put_word( 0xffff ); /* ResType */
put_word( 0x0000 );
put_word( 0xffff ); /* ResName */
put_word( 0x0000 );
put_dword( 0 ); /* DataVersion */
put_word( 0 ); /* Memory options */
put_word( 0 ); /* Language */
put_dword( 0 ); /* Version */
put_dword( 0 ); /* Characteristics */
for (i = 0; i < spec->nb_resources; i++)
{
unsigned int header_size = get_resource_header_size( &spec->resources[i] );
put_dword( spec->resources[i].data_size );
put_dword( (header_size + 3) & ~3 );
put_string( &spec->resources[i].type );
put_string( &spec->resources[i].name );
align_output( 4 );
put_dword( 0 );
put_word( spec->resources[i].mem_options );
put_word( spec->resources[i].lang );
put_dword( 0 );
put_dword( 0 );
put_data( spec->resources[i].data, spec->resources[i].data_size );
align_output( 4 );
}
/* if the output file name is a .res too, don't run the results through windres */
if (strendswith( output_file_name, ".res"))
{
flush_output_buffer();
return;
}
res_file = get_temp_file_name( output_file_name, ".res" );
if ((fd = open( res_file, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0600 )) == -1)
fatal_error( "Cannot create %s\n", res_file );
if (write( fd, output_buffer, output_buffer_pos ) != output_buffer_pos)
fatal_error( "Error writing to %s\n", res_file );
close( fd );
free( output_buffer );
if (res_file)
{
const char *prog = get_windres_command();
char *cmd = xmalloc( strlen(prog) + strlen(res_file) + strlen(output_file_name) + 9 );
sprintf( cmd, "%s -i %s -o %s", prog, res_file, output_file_name );
if (verbose) fprintf( stderr, "%s\n", cmd );
err = system( cmd );
if (err) fatal_error( "%s failed with status %d\n", prog, err );
free( cmd );
}
output_file_name = NULL; /* so we don't try to assemble it */
}

View file

@ -0,0 +1,389 @@
Index: build.h
===================================================================
--- build.h (Revision 4)
+++ build.h (Arbeitskopie)
@@ -38,6 +38,8 @@
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
+#define EXEEXT ".exe"
+
typedef enum
{
TYPE_VARIABLE, /* variable */
@@ -47,6 +49,7 @@
TYPE_STDCALL, /* stdcall function (Win32) */
TYPE_CDECL, /* cdecl function (Win32) */
TYPE_VARARGS, /* varargs function (Win32) */
+ TYPE_FASTCALL, /* fastcall function (Win32) */
TYPE_EXTERN, /* external symbol (Win32) */
TYPE_NBTYPES
} ORD_TYPE;
@@ -269,6 +272,7 @@
extern void BuildSpec16File( DLLSPEC *spec );
extern void BuildSpec32File( DLLSPEC *spec );
extern void BuildDef32File( DLLSPEC *spec );
+extern void BuildPedllFile( DLLSPEC *spec );
extern void add_16bit_exports( DLLSPEC *spec32, DLLSPEC *spec16 );
extern int parse_spec_file( FILE *file, DLLSPEC *spec );
Index: main.c
===================================================================
--- main.c (Revision 4)
+++ main.c (Arbeitskopie)
@@ -48,9 +48,9 @@
int link_ext_symbols = 0;
int force_pointer_size = 0;
-#ifdef __i386__
+#if defined(TARGET_i386)
enum target_cpu target_cpu = CPU_x86;
-#elif defined(__x86_64__)
+#elif defined(TARGET_amd64)
enum target_cpu target_cpu = CPU_x86_64;
#elif defined(__sparc__)
enum target_cpu target_cpu = CPU_SPARC;
@@ -58,7 +58,7 @@
enum target_cpu target_cpu = CPU_ALPHA;
#elif defined(__powerpc__)
enum target_cpu target_cpu = CPU_POWERPC;
-#elif defined(__arm__)
+#elif defined(TARGET_arm)
enum target_cpu target_cpu = CPU_ARM;
#else
#error Unsupported CPU
@@ -102,7 +102,8 @@
MODE_DEF,
MODE_RELAY16,
MODE_RELAY32,
- MODE_RESOURCES
+ MODE_RESOURCES,
+ MODE_PEDLL
};
static enum exec_mode_values exec_mode = MODE_NONE;
@@ -253,6 +254,7 @@
" --relay16 Build the 16-bit relay assembly routines\n"
" --relay32 Build the 32-bit relay assembly routines\n"
" --resources Build a .o file for the resource files\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";
enum long_options_values
@@ -272,7 +274,8 @@
LONG_OPT_RESOURCES,
LONG_OPT_SAVE_TEMPS,
LONG_OPT_SUBSYSTEM,
- LONG_OPT_VERSION
+ LONG_OPT_VERSION,
+ LONG_OPT_PEDLL
};
static const char short_options[] = "C:D:E:F:H:I:K:L:M:N:b:d:e:f:hi:kl:m:o:r:u:vw";
@@ -295,6 +298,7 @@
{ "save-temps", 0, 0, LONG_OPT_SAVE_TEMPS },
{ "subsystem", 1, 0, LONG_OPT_SUBSYSTEM },
{ "version", 0, 0, LONG_OPT_VERSION },
+ { "pedll", 1, 0, LONG_OPT_PEDLL },
/* aliases for short options */
{ "target", 1, 0, 'b' },
{ "delay-lib", 1, 0, 'd' },
@@ -497,6 +501,11 @@
case LONG_OPT_VERSION:
printf( "winebuild version " PACKAGE_VERSION "\n" );
exit(0);
+ case LONG_OPT_PEDLL:
+ set_exec_mode( MODE_PEDLL );
+ spec_file_name = xstrdup( optarg );
+ set_dll_file_name( optarg, spec );
+ break;
case '?':
usage(1);
break;
@@ -652,6 +661,11 @@
if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
BuildRelays32();
break;
+ case MODE_PEDLL:
+ if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
+ if (!parse_input_file( spec )) break;
+ BuildPedllFile( spec );
+ break;
case MODE_RESOURCES:
load_resources( argv, spec );
output_res_o_file( spec );
Index: parser.c
===================================================================
--- parser.c (Revision 4)
+++ parser.c (Arbeitskopie)
@@ -56,6 +56,7 @@
"stdcall", /* TYPE_STDCALL */
"cdecl", /* TYPE_CDECL */
"varargs", /* TYPE_VARARGS */
+ "fastcall", /* TYPE_FASTCALL */
"extern" /* TYPE_EXTERN */
};
@@ -521,6 +522,7 @@
case TYPE_STDCALL:
case TYPE_VARARGS:
case TYPE_CDECL:
+ case TYPE_FASTCALL:
if (!parse_spec_export( odp, spec )) goto error;
break;
case TYPE_ABS:
Index: res32.c
===================================================================
--- res32.c (Revision 4)
+++ res32.c (Arbeitskopie)
@@ -35,12 +35,14 @@
#include "build.h"
typedef unsigned short WCHAR;
+typedef unsigned short WORD;
+typedef unsigned int DWORD;
/* Unicode string or integer id */
struct string_id
{
WCHAR *str; /* ptr to Unicode string */
- unsigned short id; /* integer id if str is NULL */
+ WORD id; /* integer id if str is NULL */
};
/* descriptor for a resource */
@@ -195,7 +197,7 @@
/* all values must be zero except header size */
static int check_header(void)
{
- unsigned int size;
+ DWORD size;
if (get_dword()) return 0; /* data size */
size = get_dword(); /* header size */
@@ -214,14 +216,14 @@
/* load the next resource from the current file */
static void load_next_resource( DLLSPEC *spec )
{
- unsigned int hdr_size;
+ DWORD hdr_size;
struct resource *res = add_resource( spec );
res->data_size = get_dword();
hdr_size = get_dword();
if (hdr_size & 3) fatal_error( "%s header size not aligned\n", input_buffer_filename );
- res->data = input_buffer + input_buffer_pos - 2*sizeof(unsigned int) + hdr_size;
+ res->data = input_buffer + input_buffer_pos - 2*sizeof(DWORD) + hdr_size;
get_string( &res->type );
get_string( &res->name );
if (input_buffer_pos & 2) get_word(); /* align to dword boundary */
Index: spec32.c
===================================================================
--- spec32.c (Revision 4)
+++ spec32.c (Arbeitskopie)
@@ -74,6 +74,28 @@
}
/*******************************************************************
+ * make_internal_name
+ *
+ * Generate an internal name for an entry point. Used for stubs etc.
+ */
+static const char *make_internal_name( const ORDDEF *odp, DLLSPEC *spec, const char *prefix )
+{
+ static char buffer[256];
+ if (odp->name || odp->export_name)
+ {
+ char *p;
+ sprintf( buffer, "__wine_%s_%s_%s", prefix, spec->file_name,
+ odp->name ? odp->name : odp->export_name );
+ /* make sure name is a legal C identifier */
+ for (p = buffer; *p; p++) if (!isalnum(*p) && *p != '_') break;
+ if (!*p) return buffer;
+ }
+ sprintf( buffer, "__wine_%s_%s_%d", prefix, make_c_identifier(spec->file_name), odp->ordinal );
+ return buffer;
+}
+
+
+/*******************************************************************
* output_relay_debug
*
* Output entry points for relay debugging
@@ -341,6 +363,44 @@
/*******************************************************************
+ * output_stub_funcs
+ *
+ * Output the functions for stub entry points
+ */
+static void output_stub_funcs( DLLSPEC *spec )
+{
+ int i;
+
+#if 0
+ for (i = 0; i < spec->nb_entry_points; i++)
+ {
+ ORDDEF *odp = &spec->entry_points[i];
+ if (odp->type != TYPE_STUB) continue;
+ fprintf( outfile, "#ifdef __GNUC__\n" );
+ fprintf( outfile, "extern void __wine_spec_unimplemented_stub( const char *module, const char *func ) __attribute__((noreturn));\n" );
+ fprintf( outfile, "#else\n" );
+ fprintf( outfile, "extern void __wine_spec_unimplemented_stub( const char *module, const char *func );\n" );
+ fprintf( outfile, "#endif\n\n" );
+ break;
+ }
+#endif
+
+ for (i = 0; i < spec->nb_entry_points; i++)
+ {
+ const ORDDEF *odp = &spec->entry_points[i];
+ if (odp->type != TYPE_STUB) continue;
+ output( "void %s(void) ", make_internal_name( odp, spec, "stub" ) );
+ if (odp->name)
+ output( "{ __wine_spec_unimplemented_stub(__wine_spec_file_name, \"%s\"); }\n", odp->name );
+ else if (odp->export_name)
+ output( "{ __wine_spec_unimplemented_stub(__wine_spec_file_name, \"%s\"); }\n", odp->export_name );
+ else
+ output( "{ __wine_spec_unimplemented_stub(__wine_spec_file_name, \"%d\"); }\n", odp->ordinal );
+ }
+}
+
+
+/*******************************************************************
* output_asm_constructor
*
* Output code for calling a dll constructor.
@@ -795,10 +855,6 @@
if (!(odp->flags & FLAG_PRIVATE)) total++;
- if (odp->type == TYPE_STUB) continue;
-
- output( " %s", name );
-
switch(odp->type)
{
case TYPE_EXTERN:
@@ -807,12 +863,14 @@
case TYPE_VARARGS:
case TYPE_CDECL:
/* try to reduce output */
+ output( " %s", name );
if(strcmp(name, odp->link_name) || (odp->flags & FLAG_FORWARD))
output( "=%s", odp->link_name );
break;
case TYPE_STDCALL:
{
int at_param = strlen(odp->u.func.arg_types) * get_ptr_size();
+ output( " %s", name );
if (!kill_at && target_cpu == CPU_x86) output( "@%d", at_param );
if (odp->flags & FLAG_FORWARD)
{
@@ -825,6 +883,51 @@
}
break;
}
+ case TYPE_FASTCALL:
+ {
+ int at_param = strlen(odp->u.func.arg_types) * get_ptr_size();
+ output( " " );
+ if (!kill_at) output( "@" );
+ output( "%s", name );
+ if (!kill_at) output( "@%d", at_param );
+ if (odp->flags & FLAG_FORWARD)
+ {
+ output( "=" );
+ if (!kill_at) output( "@" );
+ output( "%s", odp->link_name );
+ }
+ else if (strcmp(name, odp->link_name)) /* try to reduce output */
+ {
+ output( "=" );
+ if (!kill_at) output( "@" );
+ output( "%s", odp->link_name );
+ if (!kill_at) output( "@%d", at_param );
+ }
+ break;
+ }
+ case TYPE_STUB:
+ {
+ output( " %s", name );
+ if (!kill_at)
+ {
+ const char *check = name + strlen(name);
+ while (name != check &&
+ '0' <= check[-1] && check[-1] <= '9')
+ {
+ check--;
+ }
+ if (name != check && check != name + strlen(name) &&
+ '@' == check[-1])
+ {
+ output("%s", check - 1);
+ }
+ }
+ if (odp->name || odp->export_name)
+ {
+ output("=%s", make_internal_name( odp, spec, "stub" ));
+ }
+ break;
+ }
default:
assert(0);
}
@@ -836,3 +939,52 @@
}
if (!total) warning( "%s: Import library doesn't export anything\n", spec->file_name );
}
+
+
+/*******************************************************************
+ * BuildPedllFile
+ *
+ * Build a PE DLL C file from a spec file.
+ */
+void BuildPedllFile( DLLSPEC *spec )
+{
+ int i, has_stubs = 0;
+
+ output_standard_file_header();
+
+ for (i = 0; i < spec->nb_entry_points; i++)
+ {
+ const ORDDEF *odp = &spec->entry_points[i];
+ if (odp->type == TYPE_STUB)
+ {
+ has_stubs = 1;
+ break;
+ }
+ }
+
+ if (!has_stubs)
+ {
+ output( "/* This file is intentionally left blank */\n");
+ return;
+ }
+
+ output( "#include <stdarg.h>\n");
+ output( "#include \"windef.h\"\n");
+ output( "#include \"winbase.h\"\n");
+ output( "#include \"wine/config.h\"\n");
+ output( "#include \"wine/exception.h\"\n\n");
+
+ output( "void __wine_spec_unimplemented_stub( const char *module, const char *function )\n");
+ output( "{\n");
+ output( " ULONG_PTR args[2];\n");
+ output( "\n");
+ output( " args[0] = (ULONG_PTR)module;\n");
+ output( " args[1] = (ULONG_PTR)function;\n");
+ output( " RaiseException( EXCEPTION_WINE_STUB, EH_NONCONTINUABLE, 2, args );\n");
+ output( "}\n\n");
+
+ output( "static const char __wine_spec_file_name[] = \"%s\";\n\n", spec->file_name );
+
+ /* Output the stub functions */
+ output_stub_funcs( spec );
+}

View file

@ -28,10 +28,24 @@
#include <assert.h>
#include <ctype.h>
#include "wine/winbase16.h"
#include "build.h"
#define NE_FFLAGS_SINGLEDATA 0x0001
#define NE_FFLAGS_LIBMODULE 0x8000
/* argument type flags for relay debugging */
enum arg_types
{
ARG_NONE = 0, /* indicates end of arg list */
ARG_WORD, /* unsigned word */
ARG_SWORD, /* signed word */
ARG_LONG, /* long or segmented pointer */
ARG_PTR, /* linear pointer */
ARG_STR, /* linear pointer to null-terminated string */
ARG_SEGSTR, /* segmented pointer to null-terminated string */
ARG_VARARG /* start of varargs */
};
/* sequences of nops to fill a certain number of words */
static const char * const nop_sequence[4] =
{
@ -49,6 +63,22 @@ static inline int is_function( const ORDDEF *odp )
odp->type == TYPE_STUB);
}
static void init_dll_name( DLLSPEC *spec )
{
if (!spec->file_name)
{
char *p;
spec->file_name = xstrdup( output_file_name );
if ((p = strrchr( spec->file_name, '.' ))) *p = 0;
}
if (!spec->dll_name) /* set default name from file name */
{
char *p;
spec->dll_name = xstrdup( spec->file_name );
if ((p = strrchr( spec->dll_name, '.' ))) *p = 0;
}
}
/*******************************************************************
* output_entries
*
@ -451,7 +481,7 @@ static int sort_func_list( ORDDEF **list, int count,
*
* Output the dll initialization code.
*/
static void output_init_code( const DLLSPEC *spec, const char *header_name )
static void output_init_code( const DLLSPEC *spec )
{
char name[80];
@ -468,13 +498,13 @@ static void output_init_code( const DLLSPEC *spec, const char *header_name )
output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
output( "1:\tleal .L__wine_spec_file_name-1b(%%eax),%%ecx\n" );
output( "\tpushl %%ecx\n" );
output( "\tleal %s-1b(%%eax),%%ecx\n", header_name );
output( "\tleal .L__wine_spec_dos_header-1b(%%eax),%%ecx\n" );
output( "\tpushl %%ecx\n" );
}
else
{
output( "\tpushl $.L__wine_spec_file_name\n" );
output( "\tpushl $%s\n", header_name );
output( "\tpushl $.L__wine_spec_dos_header\n" );
}
output( "\tcall %s\n", asm_name("__wine_dll_register_16") );
output( "\taddl $12,%%esp\n" );
@ -490,12 +520,12 @@ static void output_init_code( const DLLSPEC *spec, const char *header_name )
if (UsePIC)
{
output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
output( "1:\tleal %s-1b(%%eax),%%ecx\n", header_name );
output( "1:\tleal .L__wine_spec_dos_header-1b(%%eax),%%ecx\n" );
output( "\tpushl %%ecx\n" );
}
else
{
output( "\tpushl $%s\n", header_name );
output( "\tpushl $.L__wine_spec_dos_header\n" );
}
output( "\tcall %s\n", asm_name("__wine_dll_unregister_16") );
output( "\taddl $12,%%esp\n" );
@ -522,38 +552,21 @@ static void output_init_code( const DLLSPEC *spec, const char *header_name )
/*******************************************************************
* BuildSpec16File
* output_module16
*
* Build a Win16 assembly file from a spec file.
* Output code for a 16-bit module.
*/
void BuildSpec16File( DLLSPEC *spec )
static void output_module16( DLLSPEC *spec )
{
ORDDEF **typelist;
ORDDEF *entry_point = NULL;
int i, j, nb_funcs;
char header_name[256];
/* File header */
output_standard_file_header();
if (!spec->file_name)
{
char *p;
spec->file_name = xstrdup( output_file_name );
if ((p = strrchr( spec->file_name, '.' ))) *p = 0;
}
if (!spec->dll_name) /* set default name from file name */
{
char *p;
spec->dll_name = xstrdup( spec->file_name );
if ((p = strrchr( spec->dll_name, '.' ))) *p = 0;
}
/* store the main entry point as ordinal 0 */
if (!spec->ordinals)
{
assert(spec->limit == 0);
spec->ordinals = xmalloc( sizeof(spec->ordinals[0]) );
spec->ordinals[0] = NULL;
}
@ -587,13 +600,11 @@ void BuildSpec16File( DLLSPEC *spec )
/* Output the module structure */
sprintf( header_name, "__wine_spec_%s_dos_header", make_c_identifier(spec->dll_name) );
output( "\n/* module data */\n\n" );
output( "\t.data\n" );
output( "\t.align %d\n", get_alignment(4) );
output( "%s:\n", header_name );
output( "\t%s 0x%04x\n", get_asm_short_keyword(), /* e_magic */
IMAGE_DOS_SIGNATURE );
output( ".L__wine_spec_dos_header:\n" );
output( "\t%s 0x5a4d\n", get_asm_short_keyword() ); /* e_magic */
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_cblp */
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_cp */
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_crlc */
@ -611,11 +622,10 @@ void BuildSpec16File( DLLSPEC *spec )
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_oemid */
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_oeminfo */
output( "\t%s 0,0,0,0,0,0,0,0,0,0\n", get_asm_short_keyword() ); /* e_res2 */
output( "\t.long .L__wine_spec_ne_header-%s\n", header_name ); /* e_lfanew */
output( "\t.long .L__wine_spec_ne_header-.L__wine_spec_dos_header\n" );/* e_lfanew */
output( ".L__wine_spec_ne_header:\n" );
output( "\t%s 0x%04x\n", get_asm_short_keyword(), /* ne_magic */
IMAGE_OS2_SIGNATURE );
output( "\t%s 0x454e\n", get_asm_short_keyword() ); /* ne_magic */
output( "\t.byte 0\n" ); /* ne_ver */
output( "\t.byte 0\n" ); /* ne_rev */
output( "\t%s .L__wine_spec_ne_enttab-.L__wine_spec_ne_header\n", /* ne_enttab */
@ -650,8 +660,8 @@ void BuildSpec16File( DLLSPEC *spec )
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_cmovent */
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_align */
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_cres */
output( "\t.byte 0x%02x\n", NE_OSFLAGS_WINDOWS ); /* ne_exetyp */
output( "\t.byte 0x%02x\n", NE_AFLAGS_FASTLOAD ); /* ne_flagsothers */
output( "\t.byte 0x02\n" ); /* ne_exetyp = NE_OSFLAGS_WINDOWS */
output( "\t.byte 0x08\n" ); /* ne_flagsothers = NE_AFLAGS_FASTLOAD */
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_pretthunks */
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_psegrefbytes */
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_swaparea */
@ -663,27 +673,27 @@ void BuildSpec16File( DLLSPEC *spec )
/* code segment entry */
output( "\t%s .L__wine_spec_code_segment-%s\n", /* filepos */
get_asm_short_keyword(), header_name );
output( "\t%s .L__wine_spec_code_segment-.L__wine_spec_dos_header\n", /* filepos */
get_asm_short_keyword() );
output( "\t%s .L__wine_spec_code_segment_end-.L__wine_spec_code_segment\n", /* size */
get_asm_short_keyword() );
output( "\t%s 0x%04x\n", get_asm_short_keyword(), NE_SEGFLAGS_32BIT ); /* flags */
output( "\t%s 0x2000\n", get_asm_short_keyword() ); /* flags = NE_SEGFLAGS_32BIT */
output( "\t%s .L__wine_spec_code_segment_end-.L__wine_spec_code_segment\n", /* minsize */
get_asm_short_keyword() );
/* data segment entry */
output( "\t%s .L__wine_spec_data_segment-%s\n", /* filepos */
get_asm_short_keyword(), header_name );
output( "\t%s .L__wine_spec_data_segment-.L__wine_spec_dos_header\n", /* filepos */
get_asm_short_keyword() );
output( "\t%s .L__wine_spec_data_segment_end-.L__wine_spec_data_segment\n", /* size */
get_asm_short_keyword() );
output( "\t%s 0x%04x\n", get_asm_short_keyword(), NE_SEGFLAGS_DATA ); /* flags */
output( "\t%s 0x0001\n", get_asm_short_keyword() ); /* flags = NE_SEGFLAGS_DATA */
output( "\t%s .L__wine_spec_data_segment_end-.L__wine_spec_data_segment\n", /* minsize */
get_asm_short_keyword() );
/* resource directory */
output_res16_directory( spec, header_name );
output_res16_directory( spec );
/* resident names table */
@ -829,14 +839,209 @@ void BuildSpec16File( DLLSPEC *spec )
output( "\t.long %s\n", asm_name("wine_ldt_copy") );
}
free( typelist );
}
/*******************************************************************
* BuildSpec16File
*
* Build a Win16 assembly file from a spec file.
*/
void BuildSpec16File( DLLSPEC *spec )
{
init_dll_name( spec );
output_standard_file_header();
output_module16( spec );
output_init_code( spec );
output( "\n\t%s\n", get_asm_string_section() );
output( ".L__wine_spec_file_name:\n" );
output( "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name );
output_stubs( spec );
output_get_pc_thunk();
output_init_code( spec, header_name );
output_gnu_stack_note();
free( typelist );
}
/*******************************************************************
* output_spec16_file
*
* Output the complete data for a spec 16-bit file.
*/
void output_spec16_file( DLLSPEC *spec16 )
{
DLLSPEC *spec32 = alloc_dll_spec();
init_dll_name( spec16 );
spec32->file_name = xstrdup( spec16->file_name );
if (spec16->characteristics & IMAGE_FILE_DLL)
{
spec32->characteristics = IMAGE_FILE_DLL;
spec32->init_func = xstrdup( "__wine_spec_dll_entry" );
}
resolve_imports( spec16 );
add_16bit_exports( spec32, spec16 );
output_standard_file_header();
output_module( spec32 );
output_module16( spec16 );
output_stubs( spec16 );
output_exports( spec32 );
output_imports( spec16 );
if (spec16->main_module)
{
output( "\n\t%s\n", get_asm_string_section() );
output( ".L__wine_spec_main_module:\n" );
output( "\t%s \"%s\"\n", get_asm_string_keyword(), spec16->main_module );
}
output_gnu_stack_note();
free_dll_spec( spec32 );
}
/*******************************************************************
* output_fake_module16
*
* Create a fake 16-bit binary module.
*/
void output_fake_module16( DLLSPEC *spec )
{
static const unsigned char code_segment[] = { 0x90, 0xc3 };
static const unsigned char data_segment[16] = { 0 };
static const char fakedll_signature[] = "Wine placeholder DLL";
const unsigned int cseg = 2;
const unsigned int lfanew = (0x40 + sizeof(fakedll_signature) + 15) & ~15;
const unsigned int segtab = lfanew + 0x40;
unsigned int i, rsrctab, restab, namelen, modtab, imptab, enttab, cbenttab, codeseg, dataseg, rsrcdata;
init_dll_name( spec );
init_output_buffer();
rsrctab = lfanew;
restab = segtab + 8 * cseg;
if (spec->nb_resources)
{
output_bin_res16_directory( spec, 0 );
align_output( 2 );
rsrctab = restab;
restab += output_buffer_pos;
free( output_buffer );
init_output_buffer();
}
namelen = strlen( spec->dll_name );
modtab = restab + ((namelen + 3) & ~1);
imptab = modtab;
enttab = modtab + 2;
cbenttab = 1;
codeseg = (enttab + cbenttab + 1) & ~1;
dataseg = codeseg + sizeof(code_segment);
rsrcdata = dataseg + sizeof(data_segment);
init_output_buffer();
put_word( 0x5a4d ); /* e_magic */
put_word( 0x40 ); /* e_cblp */
put_word( 0x01 ); /* e_cp */
put_word( 0 ); /* e_crlc */
put_word( lfanew / 16 ); /* e_cparhdr */
put_word( 0x0000 ); /* e_minalloc */
put_word( 0xffff ); /* e_maxalloc */
put_word( 0x0000 ); /* e_ss */
put_word( 0x00b8 ); /* e_sp */
put_word( 0 ); /* e_csum */
put_word( 0 ); /* e_ip */
put_word( 0 ); /* e_cs */
put_word( lfanew ); /* e_lfarlc */
put_word( 0 ); /* e_ovno */
put_dword( 0 ); /* e_res */
put_dword( 0 );
put_word( 0 ); /* e_oemid */
put_word( 0 ); /* e_oeminfo */
put_dword( 0 ); /* e_res2 */
put_dword( 0 );
put_dword( 0 );
put_dword( 0 );
put_dword( 0 );
put_dword( lfanew );
put_data( fakedll_signature, sizeof(fakedll_signature) );
align_output( 16 );
put_word( 0x454e ); /* ne_magic */
put_byte( 0 ); /* ne_ver */
put_byte( 0 ); /* ne_rev */
put_word( enttab - lfanew ); /* ne_enttab */
put_word( cbenttab ); /* ne_cbenttab */
put_dword( 0 ); /* ne_crc */
put_word( NE_FFLAGS_SINGLEDATA | /* ne_flags */
((spec->characteristics & IMAGE_FILE_DLL) ? NE_FFLAGS_LIBMODULE : 0) );
put_word( 2 ); /* ne_autodata */
put_word( spec->heap_size ); /* ne_heap */
put_word( 0 ); /* ne_stack */
put_word( 0 ); put_word( 0 ); /* ne_csip */
put_word( 0 ); put_word( 2 ); /* ne_sssp */
put_word( cseg ); /* ne_cseg */
put_word( 0 ); /* ne_cmod */
put_word( 0 ); /* ne_cbnrestab */
put_word( segtab - lfanew ); /* ne_segtab */
put_word( rsrctab - lfanew ); /* ne_rsrctab */
put_word( restab - lfanew ); /* ne_restab */
put_word( modtab - lfanew ); /* ne_modtab */
put_word( imptab - lfanew ); /* ne_imptab */
put_dword( 0 ); /* ne_nrestab */
put_word( 0 ); /* ne_cmovent */
put_word( 0 ); /* ne_align */
put_word( 0 ); /* ne_cres */
put_byte( 2 /*NE_OSFLAGS_WINDOWS*/ ); /* ne_exetyp */
put_byte( 8 /*NE_AFLAGS_FASTLOAD*/ ); /* ne_flagsothers */
put_word( 0 ); /* ne_pretthunks */
put_word( 0 ); /* ne_psegrefbytes */
put_word( 0 ); /* ne_swaparea */
put_word( 0 ); /* ne_expver */
/* segment table */
put_word( codeseg );
put_word( sizeof(code_segment) );
put_word( 0x2000 /* NE_SEGFLAGS_32BIT */ );
put_word( sizeof(code_segment) );
put_word( dataseg );
put_word( sizeof(data_segment) );
put_word( 0x0001 /* NE_SEGFLAGS_DATA */ );
put_word( sizeof(data_segment) );
/* resource directory */
if (spec->nb_resources)
{
output_bin_res16_directory( spec, rsrcdata );
align_output( 2 );
}
/* resident names table */
put_byte( namelen );
for (i = 0; i < namelen; i++) put_byte( toupper(spec->dll_name[i]) );
put_byte( 0 );
align_output( 2 );
/* imported names table */
put_word( 0 );
/* entry table */
put_byte( 0 );
align_output( 2 );
/* code segment */
put_data( code_segment, sizeof(code_segment) );
/* data segment */
put_data( data_segment, sizeof(data_segment) );
/* resource data */
output_bin_res16_data( spec );
flush_output_buffer();
}

View file

@ -30,10 +30,21 @@
#include <stdarg.h>
#include <string.h>
#include "winglue.h"
//#include "wine/exception.h"
#include "build.h"
#define IMAGE_FILE_MACHINE_UNKNOWN 0
#define IMAGE_FILE_MACHINE_I386 0x014c
#define IMAGE_FILE_MACHINE_ALPHA 0x0184
#define IMAGE_FILE_MACHINE_POWERPC 0x01f0
#define IMAGE_FILE_MACHINE_AMD64 0x8664
#define IMAGE_FILE_MACHINE_ARM 0x01C0
#define IMAGE_SIZEOF_NT_OPTIONAL32_HEADER 224
#define IMAGE_SIZEOF_NT_OPTIONAL64_HEADER 240
#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107
/* check if entry point needs a relay thunk */
static inline int needs_relay( const ORDDEF *odp )
@ -183,17 +194,21 @@ static void output_relay_debug( DLLSPEC *spec )
break;
case CPU_x86_64:
output( "\tmovq %%rcx,8(%%rsp)\n" );
output( "\tmovq %%rdx,16(%%rsp)\n" );
output( "\tmovq %%r8,24(%%rsp)\n" );
output( "\tmovq %%r9,32(%%rsp)\n" );
output( "\tmovq %%rsp,%%r8\n" );
output( "\t.cfi_startproc\n" );
output( "\tsubq $40,%%rsp\n" );
output( "\t.cfi_adjust_cfa_offset 40\n" );
output( "\tmovq %%rcx,48(%%rsp)\n" );
output( "\tmovq %%rdx,56(%%rsp)\n" );
output( "\tmovq %%r8,64(%%rsp)\n" );
output( "\tmovq %%r9,72(%%rsp)\n" );
output( "\tleaq 40(%%rsp),%%r8\n" );
output( "\tmovq $%u,%%rdx\n", (flags << 24) | (args << 16) | (i - spec->base) );
output( "\tleaq .L__wine_spec_relay_descr(%%rip),%%rcx\n" );
output( "\tsubq $40,%%rsp\n" );
output( "\tcallq *%u(%%rcx)\n", (odp->flags & FLAG_REGISTER) ? 16 : 8 );
output( "\taddq $40,%%rsp\n" );
output( "\t.cfi_adjust_cfa_offset -40\n" );
output( "\tret\n" );
output( "\t.cfi_endproc\n" );
break;
default:
@ -207,7 +222,7 @@ static void output_relay_debug( DLLSPEC *spec )
*
* Output the export table for a Win32 module.
*/
static void output_exports( DLLSPEC *spec )
void output_exports( DLLSPEC *spec )
{
int i, fwd_size = 0;
int nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
@ -329,8 +344,7 @@ static void output_exports( DLLSPEC *spec )
/* output relays */
/* we only support relay debugging on i386 and x86_64 */
if (target_cpu != CPU_x86 && target_cpu != CPU_x86_64)
if (!has_relays( spec ))
{
output( "\t%s 0\n", get_asm_ptr_keyword() );
return;
@ -416,6 +430,9 @@ static void output_asm_constructor( const char *constructor )
case CPU_ALPHA:
output( "\tjsr $26,%s\n", asm_name(constructor) );
break;
case CPU_ARM:
output( "\tblx %s\n", asm_name(constructor) );
break;
case CPU_POWERPC:
output( "\tbl %s\n", asm_name(constructor) );
break;
@ -425,18 +442,15 @@ static void output_asm_constructor( const char *constructor )
/*******************************************************************
* BuildSpec32File
* output_module
*
* Build a Win32 C file from a spec file.
* Output the module data.
*/
void BuildSpec32File( DLLSPEC *spec )
void output_module( DLLSPEC *spec )
{
int machine = 0;
unsigned int page_size = get_page_size();
resolve_imports( spec );
output_standard_file_header();
/* Reserve some space for the PE header */
switch (target_platform)
@ -462,6 +476,7 @@ void BuildSpec32File( DLLSPEC *spec )
case CPU_SPARC:
output( "\tjmp 1f\n" );
break;
case CPU_ARM:
case CPU_POWERPC:
output( "\tb 1f\n" );
break;
@ -479,11 +494,12 @@ void BuildSpec32File( DLLSPEC *spec )
output( "%s\n", asm_globl("__wine_spec_nt_header") );
output( ".L__wine_spec_rva_base:\n" );
output( "\t.long 0x%04x\n", IMAGE_NT_SIGNATURE ); /* Signature */
output( "\t.long 0x4550\n" ); /* Signature */
switch(target_cpu)
{
case CPU_x86: machine = IMAGE_FILE_MACHINE_I386; break;
case CPU_x86_64: machine = IMAGE_FILE_MACHINE_AMD64; break;
case CPU_ARM: machine = IMAGE_FILE_MACHINE_ARM; break;
case CPU_POWERPC: machine = IMAGE_FILE_MACHINE_POWERPC; break;
case CPU_ALPHA: machine = IMAGE_FILE_MACHINE_ALPHA; break;
case CPU_SPARC: machine = IMAGE_FILE_MACHINE_UNKNOWN; break;
@ -510,7 +526,7 @@ void BuildSpec32File( DLLSPEC *spec )
output( "\t.long 0\n" ); /* SizeOfUninitializedData */
/* note: we expand the AddressOfEntryPoint field on 64-bit by overwriting the BaseOfCode field */
output( "\t%s %s\n", /* AddressOfEntryPoint */
get_asm_ptr_keyword(), asm_name(spec->init_func) );
get_asm_ptr_keyword(), spec->init_func ? asm_name(spec->init_func) : "0" );
if (get_ptr_size() == 4)
{
output( "\t.long 0\n" ); /* BaseOfCode */
@ -581,15 +597,230 @@ void BuildSpec32File( DLLSPEC *spec )
if (target_platform == PLATFORM_APPLE)
output( "\t.lcomm %s,4\n", asm_name("_end") );
output_asm_constructor( "__wine_spec_init_ctor" );
}
/*******************************************************************
* BuildSpec32File
*
* Build a Win32 C file from a spec file.
*/
void BuildSpec32File( DLLSPEC *spec )
{
resolve_imports( spec );
output_standard_file_header();
output_module( spec );
output_stubs( spec );
output_exports( spec );
output_imports( spec );
output_resources( spec );
output_asm_constructor( "__wine_spec_init_ctor" );
output_gnu_stack_note();
}
/*******************************************************************
* output_fake_module
*
* Build a fake binary module from a spec file.
*/
void output_fake_module( DLLSPEC *spec )
{
static const unsigned char dll_code_section[] = { 0x31, 0xc0, /* xor %eax,%eax */
0xc2, 0x0c, 0x00 }; /* ret $12 */
static const unsigned char exe_code_section[] = { 0xb8, 0x01, 0x00, 0x00, 0x00, /* movl $1,%eax */
0xc2, 0x04, 0x00 }; /* ret $4 */
static const char fakedll_signature[] = "Wine placeholder DLL";
const unsigned int page_size = get_page_size();
const unsigned int section_align = page_size;
const unsigned int file_align = 0x200;
const unsigned int reloc_size = 8;
const unsigned int lfanew = (0x40 + sizeof(fakedll_signature) + 15) & ~15;
const unsigned int nb_sections = 2 + (spec->nb_resources != 0);
const unsigned int text_size = (spec->characteristics & IMAGE_FILE_DLL) ?
sizeof(dll_code_section) : sizeof(exe_code_section);
unsigned char *resources;
unsigned int resources_size;
unsigned int image_size = 3 * section_align;
resolve_imports( spec );
output_bin_resources( spec, 3 * section_align );
resources = output_buffer;
resources_size = output_buffer_pos;
if (resources_size) image_size += (resources_size + section_align - 1) & ~(section_align - 1);
init_output_buffer();
put_word( 0x5a4d ); /* e_magic */
put_word( 0x40 ); /* e_cblp */
put_word( 0x01 ); /* e_cp */
put_word( 0 ); /* e_crlc */
put_word( lfanew / 16 ); /* e_cparhdr */
put_word( 0x0000 ); /* e_minalloc */
put_word( 0xffff ); /* e_maxalloc */
put_word( 0x0000 ); /* e_ss */
put_word( 0x00b8 ); /* e_sp */
put_word( 0 ); /* e_csum */
put_word( 0 ); /* e_ip */
put_word( 0 ); /* e_cs */
put_word( lfanew ); /* e_lfarlc */
put_word( 0 ); /* e_ovno */
put_dword( 0 ); /* e_res */
put_dword( 0 );
put_word( 0 ); /* e_oemid */
put_word( 0 ); /* e_oeminfo */
put_dword( 0 ); /* e_res2 */
put_dword( 0 );
put_dword( 0 );
put_dword( 0 );
put_dword( 0 );
put_dword( lfanew );
put_data( fakedll_signature, sizeof(fakedll_signature) );
align_output( 16 );
put_dword( 0x4550 ); /* Signature */
switch(target_cpu)
{
case CPU_x86: put_word( IMAGE_FILE_MACHINE_I386 ); break;
case CPU_x86_64: put_word( IMAGE_FILE_MACHINE_AMD64 ); break;
case CPU_POWERPC: put_word( IMAGE_FILE_MACHINE_POWERPC ); break;
case CPU_ALPHA: put_word( IMAGE_FILE_MACHINE_ALPHA ); break;
case CPU_SPARC: put_word( IMAGE_FILE_MACHINE_UNKNOWN ); break;
case CPU_ARM: put_word( IMAGE_FILE_MACHINE_ARM ); break;
}
put_word( nb_sections ); /* NumberOfSections */
put_dword( 0 ); /* TimeDateStamp */
put_dword( 0 ); /* PointerToSymbolTable */
put_dword( 0 ); /* NumberOfSymbols */
put_word( get_ptr_size() == 8 ?
IMAGE_SIZEOF_NT_OPTIONAL64_HEADER :
IMAGE_SIZEOF_NT_OPTIONAL32_HEADER ); /* SizeOfOptionalHeader */
put_word( spec->characteristics ); /* Characteristics */
put_word( get_ptr_size() == 8 ?
IMAGE_NT_OPTIONAL_HDR64_MAGIC :
IMAGE_NT_OPTIONAL_HDR32_MAGIC ); /* Magic */
put_byte( 0 ); /* MajorLinkerVersion */
put_byte( 0 ); /* MinorLinkerVersion */
put_dword( text_size ); /* SizeOfCode */
put_dword( 0 ); /* SizeOfInitializedData */
put_dword( 0 ); /* SizeOfUninitializedData */
put_dword( section_align ); /* AddressOfEntryPoint */
put_dword( section_align ); /* BaseOfCode */
if (get_ptr_size() == 4) put_dword( 0 ); /* BaseOfData */
put_pword( 0x10000000 ); /* ImageBase */
put_dword( section_align ); /* SectionAlignment */
put_dword( file_align ); /* FileAlignment */
put_word( 1 ); /* MajorOperatingSystemVersion */
put_word( 0 ); /* MinorOperatingSystemVersion */
put_word( 0 ); /* MajorImageVersion */
put_word( 0 ); /* MinorImageVersion */
put_word( spec->subsystem_major ); /* MajorSubsystemVersion */
put_word( spec->subsystem_minor ); /* MinorSubsystemVersion */
put_dword( 0 ); /* Win32VersionValue */
put_dword( image_size ); /* SizeOfImage */
put_dword( file_align ); /* SizeOfHeaders */
put_dword( 0 ); /* CheckSum */
put_word( spec->subsystem ); /* Subsystem */
put_word( spec->dll_characteristics ); /* DllCharacteristics */
put_pword( (spec->stack_size ? spec->stack_size : 1024) * 1024 ); /* SizeOfStackReserve */
put_pword( page_size ); /* SizeOfStackCommit */
put_pword( (spec->heap_size ? spec->heap_size : 1024) * 1024 ); /* SizeOfHeapReserve */
put_pword( page_size ); /* SizeOfHeapCommit */
put_dword( 0 ); /* LoaderFlags */
put_dword( 16 ); /* NumberOfRvaAndSizes */
put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] */
put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] */
if (resources_size) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] */
{
put_dword( 3 * section_align );
put_dword( resources_size );
}
else
{
put_dword( 0 );
put_dword( 0 );
}
put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION] */
put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY] */
put_dword( 2 * section_align ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC] */
put_dword( reloc_size );
put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG] */
put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_COPYRIGHT] */
put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR] */
put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS] */
put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG] */
put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT] */
put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT] */
put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT] */
put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR] */
put_dword( 0 ); put_dword( 0 ); /* DataDirectory[15] */
/* .text section */
put_data( ".text\0\0", 8 ); /* Name */
put_dword( section_align ); /* VirtualSize */
put_dword( section_align ); /* VirtualAddress */
put_dword( text_size ); /* SizeOfRawData */
put_dword( file_align ); /* PointerToRawData */
put_dword( 0 ); /* PointerToRelocations */
put_dword( 0 ); /* PointerToLinenumbers */
put_word( 0 ); /* NumberOfRelocations */
put_word( 0 ); /* NumberOfLinenumbers */
put_dword( 0x60000020 /* CNT_CODE|MEM_EXECUTE|MEM_READ */ ); /* Characteristics */
/* .reloc section */
put_data( ".reloc\0", 8 ); /* Name */
put_dword( section_align ); /* VirtualSize */
put_dword( 2 * section_align );/* VirtualAddress */
put_dword( reloc_size ); /* SizeOfRawData */
put_dword( 2 * file_align ); /* PointerToRawData */
put_dword( 0 ); /* PointerToRelocations */
put_dword( 0 ); /* PointerToLinenumbers */
put_word( 0 ); /* NumberOfRelocations */
put_word( 0 ); /* NumberOfLinenumbers */
put_dword( 0x42000040 /* CNT_INITIALIZED_DATA|MEM_DISCARDABLE|MEM_READ */ ); /* Characteristics */
/* .rsrc section */
if (resources_size)
{
put_data( ".rsrc\0\0", 8 ); /* Name */
put_dword( (resources_size + section_align - 1) & ~(section_align - 1) ); /* VirtualSize */
put_dword( 3 * section_align );/* VirtualAddress */
put_dword( resources_size ); /* SizeOfRawData */
put_dword( 3 * file_align ); /* PointerToRawData */
put_dword( 0 ); /* PointerToRelocations */
put_dword( 0 ); /* PointerToLinenumbers */
put_word( 0 ); /* NumberOfRelocations */
put_word( 0 ); /* NumberOfLinenumbers */
put_dword( 0x40000040 /* CNT_INITIALIZED_DATA|MEM_READ */ ); /* Characteristics */
}
/* .text contents */
align_output( file_align );
if (spec->characteristics & IMAGE_FILE_DLL)
put_data( dll_code_section, sizeof(dll_code_section) );
else
put_data( exe_code_section, sizeof(exe_code_section) );
/* .reloc contents */
align_output( file_align );
put_dword( 0 ); /* VirtualAddress */
put_dword( 0 ); /* SizeOfBlock */
/* .rsrc contents */
if (resources_size)
{
align_output( file_align );
put_data( resources, resources_size );
}
flush_output_buffer();
}
/*******************************************************************
* BuildDef32File
*

View file

@ -30,8 +30,13 @@
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#include "winglue.h"
#include "build.h"
#define MAX_TMP_FILES 8
@ -52,7 +57,8 @@ static const struct
{ "x86_64", CPU_x86_64 },
{ "sparc", CPU_SPARC },
{ "alpha", CPU_ALPHA },
{ "powerpc", CPU_POWERPC }
{ "powerpc", CPU_POWERPC },
{ "arm", CPU_ARM }
};
/* atexit handler to clean tmp files */
@ -192,6 +198,167 @@ int output( const char *format, ... )
return ret;
}
/* find a build tool in the path, trying the various names */
static char *find_tool( const char * const *names )
{
static char **dirs;
static unsigned int count, maxlen;
char *p, *file;
unsigned int i, len;
struct stat st;
if (!dirs)
{
char *path;
/* split the path in directories */
if (!getenv( "PATH" )) return NULL;
path = xstrdup( getenv( "PATH" ));
for (p = path, count = 2; *p; p++) if (*p == ':') count++;
dirs = xmalloc( count * sizeof(*dirs) );
count = 0;
dirs[count++] = p = path;
while (*p)
{
while (*p && *p != ':') p++;
if (!*p) break;
*p++ = 0;
dirs[count++] = p;
}
for (i = 0; i < count; i++) maxlen = max( maxlen, strlen(dirs[i])+2 );
}
while (*names)
{
len = strlen(*names) + sizeof(EXEEXT) + 1;
file = xmalloc( maxlen + len );
for (i = 0; i < count; i++)
{
strcpy( file, dirs[i] );
p = file + strlen(file);
if (p == file) *p++ = '.';
if (p[-1] != '/') *p++ = '/';
strcpy( p, *names );
strcat( p, EXEEXT );
if (!stat( file, &st ) && S_ISREG(st.st_mode) && (st.st_mode & 0111)) return file;
}
free( file );
names++;
}
return NULL;
}
const char *get_as_command(void)
{
if (!as_command)
{
if (target_alias)
{
as_command = xmalloc( strlen(target_alias) + sizeof("-as") );
strcpy( as_command, target_alias );
strcat( as_command, "-as" );
}
else
{
static const char * const commands[] = { "gas", "as", NULL };
if (!(as_command = find_tool( commands ))) as_command = xstrdup("as");
}
if (force_pointer_size)
{
const char *args = (target_platform == PLATFORM_APPLE) ?
((force_pointer_size == 8) ? " -arch x86_64" : " -arch i386") :
((force_pointer_size == 8) ? " --64" : " --32");
as_command = xrealloc( as_command, strlen(as_command) + strlen(args) + 1 );
strcat( as_command, args );
}
}
return as_command;
}
const char *get_ld_command(void)
{
if (!ld_command)
{
if (target_alias)
{
ld_command = xmalloc( strlen(target_alias) + sizeof("-ld") );
strcpy( ld_command, target_alias );
strcat( ld_command, "-ld" );
}
else
{
static const char * const commands[] = { "ld", "gld", NULL };
if (!(ld_command = find_tool( commands ))) ld_command = xstrdup("ld");
}
if (force_pointer_size)
{
const char *args;
switch (target_platform)
{
case PLATFORM_APPLE:
args = (force_pointer_size == 8) ? " -arch x86_64" : " -arch i386";
break;
case PLATFORM_FREEBSD:
args = (force_pointer_size == 8) ? " -m elf_x86_64" : " -m elf_i386_fbsd";
break;
default:
args = (force_pointer_size == 8) ? " -m elf_x86_64" : " -m elf_i386";
break;
}
ld_command = xrealloc( ld_command, strlen(ld_command) + strlen(args) + 1 );
strcat( ld_command, args );
}
}
return ld_command;
}
const char *get_nm_command(void)
{
if (!nm_command)
{
if (target_alias)
{
nm_command = xmalloc( strlen(target_alias) + sizeof("-nm") );
strcpy( nm_command, target_alias );
strcat( nm_command, "-nm" );
}
else
{
static const char * const commands[] = { "nm", "gnm", NULL };
if (!(nm_command = find_tool( commands ))) nm_command = xstrdup("nm");
}
}
return nm_command;
}
const char *get_windres_command(void)
{
static char *windres_command;
if (!windres_command)
{
if (target_alias)
{
windres_command = xmalloc( strlen(target_alias) + sizeof("-windres") );
strcpy( windres_command, target_alias );
strcat( windres_command, "-windres" );
}
else
{
static const char * const commands[] = { "windres", NULL };
if (!(windres_command = find_tool( commands ))) windres_command = xstrdup("windres");
}
}
return windres_command;
}
/* get a name for a temp file, automatically cleaned up on exit */
char *get_temp_file_name( const char *prefix, const char *suffix )
{
@ -222,6 +389,156 @@ char *get_temp_file_name( const char *prefix, const char *suffix )
return name;
}
/*******************************************************************
* buffer management
*
* Function for reading from/writing to a memory buffer.
*/
int byte_swapped = 0;
const char *input_buffer_filename;
const unsigned char *input_buffer;
size_t input_buffer_pos;
size_t input_buffer_size;
unsigned char *output_buffer;
size_t output_buffer_pos;
size_t output_buffer_size;
static void check_output_buffer_space( size_t size )
{
if (output_buffer_pos + size >= output_buffer_size)
{
output_buffer_size = max( output_buffer_size * 2, output_buffer_pos + size );
output_buffer = xrealloc( output_buffer, output_buffer_size );
}
}
void init_input_buffer( const char *file )
{
int fd;
struct stat st;
if ((fd = open( file, O_RDONLY | O_BINARY )) == -1) fatal_perror( "Cannot open %s", file );
if ((fstat( fd, &st ) == -1)) fatal_perror( "Cannot stat %s", file );
if (!st.st_size) fatal_error( "%s is an empty file\n", file );
#ifdef HAVE_MMAP
if ((input_buffer = mmap( NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0 )) == (void*)-1)
#endif
{
unsigned char *buffer = xmalloc( st.st_size );
if (read( fd, buffer, st.st_size ) != st.st_size) fatal_error( "Cannot read %s\n", file );
input_buffer = buffer;
}
close( fd );
input_buffer_filename = xstrdup( file );
input_buffer_size = st.st_size;
input_buffer_pos = 0;
byte_swapped = 0;
}
void init_output_buffer(void)
{
output_buffer_size = 1024;
output_buffer_pos = 0;
output_buffer = xmalloc( output_buffer_size );
}
void flush_output_buffer(void)
{
if (fwrite( output_buffer, 1, output_buffer_pos, output_file ) != output_buffer_pos)
fatal_error( "Error writing to %s\n", output_file_name );
free( output_buffer );
}
unsigned char get_byte(void)
{
if (input_buffer_pos >= input_buffer_size)
fatal_error( "%s is a truncated file\n", input_buffer_filename );
return input_buffer[input_buffer_pos++];
}
unsigned short get_word(void)
{
unsigned short ret;
if (input_buffer_pos + sizeof(ret) > input_buffer_size)
fatal_error( "%s is a truncated file\n", input_buffer_filename );
memcpy( &ret, input_buffer + input_buffer_pos, sizeof(ret) );
if (byte_swapped) ret = (ret << 8) | (ret >> 8);
input_buffer_pos += sizeof(ret);
return ret;
}
unsigned int get_dword(void)
{
unsigned int ret;
if (input_buffer_pos + sizeof(ret) > input_buffer_size)
fatal_error( "%s is a truncated file\n", input_buffer_filename );
memcpy( &ret, input_buffer + input_buffer_pos, sizeof(ret) );
if (byte_swapped)
ret = ((ret << 24) | ((ret << 8) & 0x00ff0000) | ((ret >> 8) & 0x0000ff00) | (ret >> 24));
input_buffer_pos += sizeof(ret);
return ret;
}
void put_data( const void *data, size_t size )
{
check_output_buffer_space( size );
memcpy( output_buffer + output_buffer_pos, data, size );
output_buffer_pos += size;
}
void put_byte( unsigned char val )
{
check_output_buffer_space( 1 );
output_buffer[output_buffer_pos++] = val;
}
void put_word( unsigned short val )
{
if (byte_swapped) val = (val << 8) | (val >> 8);
put_data( &val, sizeof(val) );
}
void put_dword( unsigned int val )
{
if (byte_swapped)
val = ((val << 24) | ((val << 8) & 0x00ff0000) | ((val >> 8) & 0x0000ff00) | (val >> 24));
put_data( &val, sizeof(val) );
}
void put_qword( unsigned int val )
{
if (byte_swapped)
{
put_dword( 0 );
put_dword( val );
}
else
{
put_dword( val );
put_dword( 0 );
}
}
/* pointer-sized word */
void put_pword( unsigned int val )
{
if (get_ptr_size() == 8) put_qword( val );
else put_dword( val );
}
void align_output( unsigned int align )
{
size_t size = align - (output_buffer_pos % align);
if (size == align) return;
check_output_buffer_space( size );
memset( output_buffer + output_buffer_pos, 0, size );
output_buffer_pos += size;
}
/* output a standard header for generated files */
void output_standard_file_header(void)
{
@ -314,15 +631,15 @@ int remove_stdcall_decoration( char *name )
*/
void assemble_file( const char *src_file, const char *obj_file )
{
const char *prog = get_as_command();
char *cmd;
int err;
if (!as_command) as_command = xstrdup("as");
cmd = xmalloc( strlen(as_command) + strlen(obj_file) + strlen(src_file) + 6 );
sprintf( cmd, "%s -o %s %s", as_command, obj_file, src_file );
cmd = xmalloc( strlen(prog) + strlen(obj_file) + strlen(src_file) + 6 );
sprintf( cmd, "%s -o %s %s", prog, obj_file, src_file );
if (verbose) fprintf( stderr, "%s\n", cmd );
err = system( cmd );
if (err) fatal_error( "%s failed with status %d\n", as_command, err );
if (err) fatal_error( "%s failed with status %d\n", prog, err );
free( cmd );
}
@ -340,6 +657,7 @@ DLLSPEC *alloc_dll_spec(void)
spec->file_name = NULL;
spec->dll_name = NULL;
spec->init_func = NULL;
spec->main_module = NULL;
spec->type = SPEC_WIN32;
spec->base = MAX_ORDINALS;
spec->limit = 0;
@ -478,6 +796,7 @@ unsigned int get_alignment(unsigned int align)
case CPU_x86:
case CPU_x86_64:
case CPU_SPARC:
case CPU_ARM:
if (target_platform != PLATFORM_APPLE) return align;
/* fall through */
case CPU_POWERPC:
@ -499,6 +818,7 @@ unsigned int get_page_size(void)
case CPU_x86: return 4096;
case CPU_x86_64: return 4096;
case CPU_POWERPC: return 4096;
case CPU_ARM: return 4096;
case CPU_SPARC: return 8192;
case CPU_ALPHA: return 8192;
}
@ -535,6 +855,7 @@ const char *asm_name( const char *sym )
{
case PLATFORM_APPLE:
case PLATFORM_WINDOWS:
if (sym[0] == '.' && sym[1] == 'L') return sym;
buffer[0] = '_';
strcpy( buffer + 1, sym );
return buffer;
@ -556,7 +877,15 @@ const char *func_declaration( const char *func )
sprintf( buffer, ".def _%s; .scl 2; .type 32; .endef", func );
break;
default:
sprintf( buffer, ".type %s,@function", func );
switch(target_cpu)
{
case CPU_ARM:
sprintf( buffer, ".type %s,%%function", func );
break;
default:
sprintf( buffer, ".type %s,@function", func );
break;
}
break;
}
return buffer;
@ -585,7 +914,15 @@ void output_gnu_stack_note(void)
case PLATFORM_APPLE:
break;
default:
output( "\t.section .note.GNU-stack,\"\",@progbits\n" );
switch(target_cpu)
{
case CPU_ARM:
output( "\t.section .note.GNU-stack,\"\",%%progbits\n" );
break;
default:
output( "\t.section .note.GNU-stack,\"\",@progbits\n" );
break;
}
break;
}
}

View file

@ -53,12 +53,24 @@ Wine internal usage only, you should never need to use this option.
.B \--relay32
Generate the assembly code for the 32-bit relay routines. This is for
Wine internal usage only, you should never need to use this option.
.TP
.B \--resources
Generate a .o file containing all the input resources. This is useful
when building with a PE compiler, since the PE binutils cannot handle
multiple resource files as input. For a standard Unix build, the
resource files are automatically included when building the spec file,
so there's no need for an intermediate .o file.
.SH OPTIONS
.TP
.BI \--as-cmd= as-command
Specify the command to use to compile assembly files; the default is
\fBas\fR.
.TP
.BI \-b,\ --target= cpu-manufacturer[-kernel]-os
Specify the target CPU and platform on which the generated code will
be built. The target specification is in the standard autoconf format
as returned by config.sub.
.TP
.BI \-d,\ --delay-lib= name
Set the delayed import mode for the specified library, which must be
one of the libraries imported with the \fB-l\fR option. Delayed mode
@ -96,6 +108,11 @@ specification must be used instead).
.BI \-f\ flags
Ignored for compatibility with the C compiler.
.TP
.B \--fake-module
Create a fake PE module for a dll or exe, instead of the normal
assembly or object file. The PE module contains the resources for the
module, but no executable code.
.TP
.BI \-F,\ --filename= filename
Set the file name of the module. The default is to use the base name
of the spec file (without any extension).
@ -125,6 +142,10 @@ generated .def file. Only meaningful in \fB--def\fR mode.
.BI \-K\ flags
Ignored for compatibility with the C compiler.
.TP
.BI \--large-address-aware
Set a flag in the executable to notify the loader that this
application supports address spaces larger than 2 gigabytes.
.TP
.BI \--ld-cmd= ld-command
Specify the command to use to link the object files; the default is
\fBld\fR.
@ -138,6 +159,9 @@ Import the specified library, looking for a corresponding
\fIlibname.def\fR file in the directories specified with the \fB-L\fR
option.
.TP
.B \-m32, -m64
Generate 32-bit, respectively 64-bit code.
.TP
.BI \-M,\ --main-module= module
Specify that we are building a 16-bit dll, that will ultimately be
linked together with the 32-bit dll specified in \fImodule\fR. Only
@ -189,7 +213,10 @@ for a command line executable,
for a graphical executable,
.br
.B native
for a native-mode dll.
for a native-mode dll,
.br
.B win16
for a 16-bit module.
.br
The entry point of a command line executable is a normal C \fBmain\fR
function. A \fBwmain\fR function can be used instead if you need the
@ -199,11 +226,6 @@ argument array to use Unicode strings. A graphical executable has a
Optionally a major and minor subsystem version can also be specified;
the default subsystem version is 4.0.
.TP
.BI --target= cpu-manufacturer[-kernel]-os
Specify the target CPU and platform on which the generated code will
be built. The target specification is in the standard autoconf format
as returned by config.sub.
.TP
.BI \-u,\ --undefined= symbol
Add \fIsymbol\fR to the list of undefined symbols when invoking the
linker. This makes it possible to force a specific module of a static
@ -269,9 +291,6 @@ The function returns a 16-bit value (Win16 only).
.B -ret64
The function returns a 64-bit value (Win32 only).
.TP
.B -i386
The entry point is only available on i386 platforms.
.TP
.B -register
The function uses CPU register to pass arguments.
.TP
@ -282,6 +301,9 @@ accessed through GetProcAddress.
.B -ordinal
The entry point will be imported by ordinal instead of by name. The
name is still exported.
.TP
.BI -arch= cpu[,cpu]
The entry point is only available on the specified CPU architecture(s).
.SS "Function ordinals"
Syntax:
.br

View file

@ -4,8 +4,10 @@
<file>import.c</file>
<file>main.c</file>
<file>parser.c</file>
<file>relay.c</file>
<file>res16.c</file>
<file>res32.c</file>
<file>spec16.c</file>
<file>spec32.c</file>
<file>utils.c</file>
<file>mkstemps.c</file>

View file

@ -1,126 +0,0 @@
#ifndef _WINGLUE_H
#define _WINGLUE_H
#include <host/typedefs.h>
#define DLL_PROCESS_ATTACH 1
#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_SUBSYSTEM_NATIVE 1
#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2
#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
#define IMAGE_FILE_MACHINE_UNKNOWN 0
#define IMAGE_FILE_MACHINE_I386 0x014c
#define IMAGE_FILE_MACHINE_ALPHA 0x0184
#define IMAGE_FILE_MACHINE_POWERPC 0x01f0
#define IMAGE_FILE_MACHINE_AMD64 0x8664
#define IMAGE_NT_SIGNATURE 0x00004550
#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT 0x0100
#define IMAGE_SIZEOF_NT_OPTIONAL32_HEADER 224
#define IMAGE_SIZEOF_NT_OPTIONAL64_HEADER 240
#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
#if defined(_WIN64)
#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER IMAGE_SIZEOF_NT_OPTIONAL64_HEADER
#define IMAGE_NT_OPTIONAL_HDR_MAGIC IMAGE_NT_OPTIONAL_HDR64_MAGIC
#else
#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER IMAGE_SIZEOF_NT_OPTIONAL32_HEADER
#define IMAGE_NT_OPTIONAL_HDR_MAGIC IMAGE_NT_OPTIONAL_HDR32_MAGIC
#endif
#ifndef NONAMELESSUNION
#ifdef __GNUC__
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
#define _ANONYMOUS_UNION __extension__
#define _ANONYMOUS_STRUCT __extension__
#else
#if defined(__cplusplus)
#define _ANONYMOUS_UNION __extension__
#endif /* __cplusplus */
#endif /* __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) */
#elif defined(__WATCOMC__) || defined(_MSC_VER)
#define _ANONYMOUS_UNION
#define _ANONYMOUS_STRUCT
#endif /* __GNUC__/__WATCOMC__ */
#endif /* NONAMELESSUNION */
#ifndef _ANONYMOUS_UNION
#define _ANONYMOUS_UNION
#define _UNION_NAME(x) x
#define DUMMYUNIONNAME u
#define DUMMYUNIONNAME2 u2
#define DUMMYUNIONNAME3 u3
#define DUMMYUNIONNAME4 u4
#define DUMMYUNIONNAME5 u5
#define DUMMYUNIONNAME6 u6
#define DUMMYUNIONNAME7 u7
#define DUMMYUNIONNAME8 u8
#else
#define _UNION_NAME(x)
#define DUMMYUNIONNAME
#define DUMMYUNIONNAME2
#define DUMMYUNIONNAME3
#define DUMMYUNIONNAME4
#define DUMMYUNIONNAME5
#define DUMMYUNIONNAME6
#define DUMMYUNIONNAME7
#define DUMMYUNIONNAME8
#endif
#ifndef _ANONYMOUS_STRUCT
#define _ANONYMOUS_STRUCT
#define _STRUCT_NAME(x) x
#define DUMMYSTRUCTNAME s
#define DUMMYSTRUCTNAME2 s2
#define DUMMYSTRUCTNAME3 s3
#else
#define _STRUCT_NAME(x)
#define DUMMYSTRUCTNAME
#define DUMMYSTRUCTNAME2
#define DUMMYSTRUCTNAME3
#endif
typedef struct _IMAGE_RESOURCE_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
WORD NumberOfNamedEntries;
WORD NumberOfIdEntries;
} IMAGE_RESOURCE_DIRECTORY,*PIMAGE_RESOURCE_DIRECTORY;
_ANONYMOUS_STRUCT typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
_ANONYMOUS_UNION union {
_ANONYMOUS_STRUCT struct {
DWORD NameOffset:31;
DWORD NameIsString:1;
}DUMMYSTRUCTNAME;
DWORD Name;
WORD Id;
} DUMMYUNIONNAME;
_ANONYMOUS_UNION union {
DWORD OffsetToData;
_ANONYMOUS_STRUCT struct {
DWORD OffsetToDirectory:31;
DWORD DataIsDirectory:1;
} DUMMYSTRUCTNAME2;
} DUMMYUNIONNAME2;
} IMAGE_RESOURCE_DIRECTORY_ENTRY,*PIMAGE_RESOURCE_DIRECTORY_ENTRY;
typedef struct _IMAGE_RESOURCE_DATA_ENTRY {
DWORD OffsetToData;
DWORD Size;
DWORD CodePage;
DWORD Reserved;
} IMAGE_RESOURCE_DATA_ENTRY,*PIMAGE_RESOURCE_DATA_ENTRY;
#ifndef max
#define max(a,b) ((a)>(b)?(a):(b))
#endif
#ifndef min
#define min(a,b) ((a)<(b)?(a):(b))
#endif
#endif /* _WINGLUE_H */