diff --git a/reactos/tools/winebuild/Makefile.in b/reactos/tools/winebuild/Makefile.in index 77f36917113..c4ae029efe8 100644 --- a/reactos/tools/winebuild/Makefile.in +++ b/reactos/tools/winebuild/Makefile.in @@ -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) diff --git a/reactos/tools/winebuild/build.h b/reactos/tools/winebuild/build.h index efabe5f00fe..39e04b2a477 100644 --- a/reactos/tools/winebuild/build.h +++ b/reactos/tools/winebuild/build.h @@ -31,6 +31,15 @@ #include #include +#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; diff --git a/reactos/tools/winebuild/import.c b/reactos/tools/winebuild/import.c index cea90918953..d41a754ac41 100644 --- a/reactos/tools/winebuild/import.c +++ b/reactos/tools/winebuild/import.c @@ -35,7 +35,6 @@ # include #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); diff --git a/reactos/tools/winebuild/main.c b/reactos/tools/winebuild/main.c index 58011a0adc6..24807032fcc 100644 --- a/reactos/tools/winebuild/main.c +++ b/reactos/tools/winebuild/main.c @@ -36,7 +36,6 @@ # include #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; diff --git a/reactos/tools/winebuild/parser.c b/reactos/tools/winebuild/parser.c index a323bd452c0..ba813a4d30d 100644 --- a/reactos/tools/winebuild/parser.c +++ b/reactos/tools/winebuild/parser.c @@ -32,7 +32,6 @@ #include #include -#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; diff --git a/reactos/tools/winebuild/relay.c b/reactos/tools/winebuild/relay.c index 8b08cde8bea..3f955451562 100644 --- a/reactos/tools/winebuild/relay.c +++ b/reactos/tools/winebuild/relay.c @@ -28,29 +28,16 @@ #include #include -#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" ); } diff --git a/reactos/tools/winebuild/res16.c b/reactos/tools/winebuild/res16.c index 858ea321f02..4a6dddd24db 100644 --- a/reactos/tools/winebuild/res16.c +++ b/reactos/tools/winebuild/res16.c @@ -31,21 +31,14 @@ # include #endif #include -#ifdef HAVE_SYS_STAT_H -# include -#endif -#ifdef HAVE_SYS_MMAN_H -#include -#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 ); +} diff --git a/reactos/tools/winebuild/res32.c b/reactos/tools/winebuild/res32.c index 82e938c7332..ecda0b874ea 100644 --- a/reactos/tools/winebuild/res32.c +++ b/reactos/tools/winebuild/res32.c @@ -21,6 +21,7 @@ #include "config.h" #include "wine/port.h" +#include #include #include #include @@ -30,16 +31,13 @@ # include #endif #include -#ifdef HAVE_SYS_STAT_H -# include -#endif -#ifdef HAVE_SYS_MMAN_H -#include -#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 */ +} diff --git a/reactos/tools/winebuild/ros_diff.patch b/reactos/tools/winebuild/ros_diff.patch new file mode 100644 index 00000000000..07d9b13d156 --- /dev/null +++ b/reactos/tools/winebuild/ros_diff.patch @@ -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 \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 ); ++} diff --git a/reactos/tools/winebuild/spec16.c b/reactos/tools/winebuild/spec16.c index 8fda97806a9..a0a962f7251 100644 --- a/reactos/tools/winebuild/spec16.c +++ b/reactos/tools/winebuild/spec16.c @@ -28,10 +28,24 @@ #include #include -#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(); } diff --git a/reactos/tools/winebuild/spec32.c b/reactos/tools/winebuild/spec32.c index 4cafbae333b..4c8c2554df5 100644 --- a/reactos/tools/winebuild/spec32.c +++ b/reactos/tools/winebuild/spec32.c @@ -30,10 +30,21 @@ #include #include -#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 * diff --git a/reactos/tools/winebuild/utils.c b/reactos/tools/winebuild/utils.c index 8e50bb40ef9..c0b93710e6c 100644 --- a/reactos/tools/winebuild/utils.c +++ b/reactos/tools/winebuild/utils.c @@ -30,8 +30,13 @@ #ifdef HAVE_UNISTD_H # include #endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef HAVE_SYS_MMAN_H +#include +#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; } } diff --git a/reactos/tools/winebuild/winebuild.man.in b/reactos/tools/winebuild/winebuild.man.in index d13596812fc..d41fae7a8c9 100644 --- a/reactos/tools/winebuild/winebuild.man.in +++ b/reactos/tools/winebuild/winebuild.man.in @@ -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 diff --git a/reactos/tools/winebuild/winebuild.rbuild b/reactos/tools/winebuild/winebuild.rbuild index 4e26e551d8d..a8862149e29 100644 --- a/reactos/tools/winebuild/winebuild.rbuild +++ b/reactos/tools/winebuild/winebuild.rbuild @@ -4,8 +4,10 @@ import.c main.c parser.c + relay.c res16.c res32.c + spec16.c spec32.c utils.c mkstemps.c diff --git a/reactos/tools/winebuild/winglue.h b/reactos/tools/winebuild/winglue.h deleted file mode 100644 index 5d73e436a4f..00000000000 --- a/reactos/tools/winebuild/winglue.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef _WINGLUE_H -#define _WINGLUE_H - -#include - -#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 */