Added patch with various improvements for fake dlls.

This commit is contained in:
Sebastian Lackner 2017-05-15 21:07:42 +02:00
parent 5d38a0fed0
commit 6a14f80fdc
7 changed files with 1215 additions and 0 deletions

View File

@ -411,6 +411,7 @@ patch_enable_all ()
enable_wineboot_HKEY_DYN_DATA="$1"
enable_wineboot_ProxySettings="$1"
enable_wineboot_drivers_etc_Stubs="$1"
enable_winebuild_Fake_Dlls="$1"
enable_winecfg_Libraries="$1"
enable_winecfg_Staging="$1"
enable_winecfg_Unmounted_Devices="$1"
@ -1464,6 +1465,9 @@ patch_enable ()
wineboot-drivers_etc_Stubs)
enable_wineboot_drivers_etc_Stubs="$2"
;;
winebuild-Fake_Dlls)
enable_winebuild_Fake_Dlls="$2"
;;
winecfg-Libraries)
enable_winecfg_Libraries="$2"
;;
@ -2084,6 +2088,13 @@ if test "$enable_wined3d_CSMT_Helper" -eq 1; then
enable_wined3d_Silence_FIXMEs=1
fi
if test "$enable_winebuild_Fake_Dlls" -eq 1; then
if test "$enable_ntdll_Interrupt_0x2e" -gt 1; then
abort "Patchset ntdll-Interrupt-0x2e disabled, but winebuild-Fake_Dlls depends on that."
fi
enable_ntdll_Interrupt_0x2e=1
fi
if test "$enable_wineboot_ProxySettings" -eq 1; then
if test "$enable_wineboot_DriveSerial" -gt 1; then
abort "Patchset wineboot-DriveSerial disabled, but wineboot-ProxySettings depends on that."
@ -8540,6 +8551,33 @@ if test "$enable_wineboot_ProxySettings" -eq 1; then
) >> "$patchlist"
fi
# Patchset winebuild-Fake_Dlls
# |
# | This patchset has the following (direct or indirect) dependencies:
# | * ntdll-Interrupt-0x2e
# |
# | This patchset fixes the following Wine bugs:
# | * [#42741] Various improvements for fake dlls
# |
# | Modified files:
# | * dlls/ntdll/signal_i386.c, tools/winebuild/build.h, tools/winebuild/import.c, tools/winebuild/parser.c,
# | tools/winebuild/res32.c, tools/winebuild/spec16.c, tools/winebuild/spec32.c, tools/winebuild/utils.c
# |
if test "$enable_winebuild_Fake_Dlls" -eq 1; then
patch_apply winebuild-Fake_Dlls/0001-winebuild-Generate-syscall-thunks-for-ntdll-exports.patch
patch_apply winebuild-Fake_Dlls/0002-winebuild-Use-Windows-7-WOW64-signature-for-syscall-.patch
patch_apply winebuild-Fake_Dlls/0003-winebuild-Use-multipass-label-system-to-generate-fak.patch
patch_apply winebuild-Fake_Dlls/0004-winebuild-Add-stub-functions-in-fake-dlls.patch
patch_apply winebuild-Fake_Dlls/0005-winebuild-Add-syscall-thunks-in-fake-dlls.patch
(
printf '%s\n' '+ { "Michael Müller", "winebuild: Generate syscall thunks for ntdll exports.", 1 },';
printf '%s\n' '+ { "Michael Müller", "winebuild: Use Windows 7 WOW64 signature for syscall thunks.", 1 },';
printf '%s\n' '+ { "Michael Müller", "winebuild: Use multipass label system to generate fake dlls.", 1 },';
printf '%s\n' '+ { "Michael Müller", "winebuild: Add stub functions in fake dlls.", 1 },';
printf '%s\n' '+ { "Michael Müller", "winebuild: Add syscall thunks in fake dlls.", 1 },';
) >> "$patchlist"
fi
# Patchset winecfg-Libraries
# |
# | Modified files:

View File

@ -0,0 +1,343 @@
From 8350a72d2ef7ff70d6e9a7769a3f61b25d687e16 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Thu, 11 May 2017 05:32:55 +0200
Subject: winebuild: Generate syscall thunks for ntdll exports.
Based on a patch by Erich E. Hoover.
---
tools/winebuild/build.h | 6 +++++
tools/winebuild/import.c | 10 ++++----
tools/winebuild/parser.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++
tools/winebuild/spec16.c | 22 +-----------------
tools/winebuild/spec32.c | 48 +++++++++++++++++++++++++++++++++++++++
tools/winebuild/utils.c | 21 +++++++++++++++++
6 files changed, 141 insertions(+), 25 deletions(-)
diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h
index 398d54200c7..e338c9c8024 100644
--- a/tools/winebuild/build.h
+++ b/tools/winebuild/build.h
@@ -102,6 +102,7 @@ typedef struct
int flags;
char *name; /* public name of this function */
char *link_name; /* name of the C symbol to link to */
+ char *impl_name; /* name of the C symbol of the real implementation (thunks only) */
char *export_name; /* name exported under for noname exports */
union
{
@@ -128,6 +129,7 @@ typedef struct
int alloc_entry_points; /* number of allocated entry points */
int nb_names; /* number of entry points with names */
unsigned int nb_resources; /* number of resources */
+ int nb_syscalls; /* number of syscalls */
int characteristics; /* characteristics for the PE header */
int dll_characteristics;/* DLL characteristics for the PE header */
int subsystem; /* subsystem id */
@@ -137,6 +139,7 @@ typedef struct
ORDDEF **names; /* array of entry point names (points into entry_points) */
ORDDEF **ordinals; /* array of dll ordinals (points into entry_points) */
struct resource *resources; /* array of dll resources (format differs between Win16/Win32) */
+ ORDDEF **syscalls; /* array of syscalls (points into entry_points) */
} DLLSPEC;
enum target_cpu
@@ -176,6 +179,7 @@ struct strarray
#define FLAG_FORWARD 0x100 /* function is a forwarded name */
#define FLAG_EXT_LINK 0x200 /* function links to an external symbol */
#define FLAG_EXPORT32 0x400 /* 32-bit export in 16-bit spec file */
+#define FLAG_SYSCALL 0x800 /* function should be called through a syscall thunk */
#define FLAG_CPU(cpu) (0x01000 << (cpu))
#define FLAG_CPU_MASK (FLAG_CPU(CPU_LAST + 1) - FLAG_CPU(0))
@@ -313,6 +317,8 @@ 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 );
+extern int sort_func_list( ORDDEF **list, int count, int (*compare)(const void *, const void *) );
+
/* buffer management */
extern int byte_swapped;
diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c
index e7bad72c37b..cc8c422a33c 100644
--- a/tools/winebuild/import.c
+++ b/tools/winebuild/import.c
@@ -451,6 +451,7 @@ static void check_undefined_forwards( DLLSPEC *spec )
/* flag the dll exports that link to an undefined symbol */
static void check_undefined_exports( DLLSPEC *spec )
{
+ const char *name;
int i;
for (i = 0; i < spec->nb_entry_points; i++)
@@ -458,7 +459,8 @@ static void check_undefined_exports( DLLSPEC *spec )
ORDDEF *odp = &spec->entry_points[i];
if (odp->type == TYPE_STUB || odp->type == TYPE_ABS || odp->type == TYPE_VARIABLE) continue;
if (odp->flags & FLAG_FORWARD) continue;
- if (find_name( odp->link_name, &undef_symbols ))
+ name = odp->impl_name ? odp->impl_name : odp->link_name;
+ if (find_name( name, &undef_symbols ))
{
switch(odp->type)
{
@@ -470,14 +472,14 @@ static void check_undefined_exports( DLLSPEC *spec )
if (link_ext_symbols)
{
odp->flags |= FLAG_EXT_LINK;
- strarray_add( &ext_link_imports, odp->link_name, NULL );
+ strarray_add( &ext_link_imports, name, NULL );
}
else error( "%s:%d: function '%s' not defined\n",
- spec->src_name, odp->lineno, odp->link_name );
+ spec->src_name, odp->lineno, name );
break;
default:
error( "%s:%d: external symbol '%s' is not a function\n",
- spec->src_name, odp->lineno, odp->link_name );
+ spec->src_name, odp->lineno, name );
break;
}
}
diff --git a/tools/winebuild/parser.c b/tools/winebuild/parser.c
index 2762a8cd10e..d8dceaead28 100644
--- a/tools/winebuild/parser.c
+++ b/tools/winebuild/parser.c
@@ -507,6 +507,24 @@ static const char *parse_spec_flags( DLLSPEC *spec, ORDDEF *odp )
}
+static int needs_syscall( ORDDEF *odp, DLLSPEC *spec )
+{
+ if (target_cpu != CPU_x86)
+ return 0;
+ if (odp->flags & (FLAG_FORWARD | FLAG_NORELAY | FLAG_REGISTER))
+ return 0;
+ if (odp->type != TYPE_STDCALL)
+ return 0;
+ if (!spec->dll_name || strcmp(spec->dll_name, "ntdll"))
+ return 0;
+ if (!odp->name)
+ return 0;
+ if (strncmp(odp->name, "Nt", 2) && strncmp(odp->name, "Zw", 2))
+ return 0;
+ return 1;
+}
+
+
/*******************************************************************
* parse_spec_ordinal
*
@@ -575,6 +593,14 @@ static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
assert( 0 );
}
+ if (needs_syscall( odp, spec ))
+ {
+ char *link_name = strmake( "__syscall_%s", odp->link_name );
+ odp->impl_name = odp->link_name;
+ odp->link_name = link_name;
+ odp->flags |= FLAG_SYSCALL;
+ }
+
if ((odp->flags & FLAG_CPU_MASK) && !(odp->flags & FLAG_CPU(target_cpu)))
{
/* ignore this entry point */
@@ -771,6 +797,37 @@ static void assign_ordinals( DLLSPEC *spec )
}
+static int link_name_compare( const void *e1, const void *e2 )
+{
+ const ORDDEF *odp1 = *(const ORDDEF * const *)e1;
+ const ORDDEF *odp2 = *(const ORDDEF * const *)e2;
+ return strcmp(odp1->link_name, odp2->link_name);
+}
+
+
+static void assign_syscalls( DLLSPEC *spec )
+{
+ int i;
+
+ spec->syscalls = xmalloc( (spec->limit - spec->base + 1) * sizeof(*spec->syscalls) );
+ spec->nb_syscalls = 0;
+
+ for (i = 0; i <= spec->limit; i++)
+ {
+ ORDDEF *odp = spec->ordinals[i];
+ if (!odp || !(odp->flags & FLAG_SYSCALL)) continue;
+ spec->syscalls[spec->nb_syscalls++] = odp;
+ }
+
+ spec->nb_syscalls = sort_func_list( spec->syscalls, spec->nb_syscalls, link_name_compare );
+ if (!spec->nb_syscalls)
+ {
+ free( spec->syscalls );
+ spec->syscalls = NULL;
+ }
+}
+
+
/*******************************************************************
* add_16bit_exports
*
@@ -872,6 +929,8 @@ int parse_spec_file( FILE *file, DLLSPEC *spec )
current_line = 0; /* no longer parsing the input file */
assign_names( spec );
assign_ordinals( spec );
+ assign_syscalls( spec );
+
return !nb_errors;
}
diff --git a/tools/winebuild/spec16.c b/tools/winebuild/spec16.c
index 85bcf099999..54aad5d95b4 100644
--- a/tools/winebuild/spec16.c
+++ b/tools/winebuild/spec16.c
@@ -494,27 +494,6 @@ static int relay_type_compare( const void *e1, const void *e2 )
/*******************************************************************
- * sort_func_list
- *
- * Sort a list of functions, removing duplicates.
- */
-static int sort_func_list( ORDDEF **list, int count,
- int (*compare)(const void *, const void *) )
-{
- int i, j;
-
- if (!count) return 0;
- qsort( list, count, sizeof(*list), compare );
-
- for (i = j = 0; i < count; i++)
- {
- if (compare( &list[j], &list[i] )) list[++j] = list[i];
- }
- return j + 1;
-}
-
-
-/*******************************************************************
* output_module16
*
* Output code for a 16-bit module.
@@ -542,6 +521,7 @@ static void output_module16( DLLSPEC *spec )
entry_point->flags = FLAG_REGISTER;
entry_point->name = NULL;
entry_point->link_name = xstrdup( spec->init_func );
+ entry_point->impl_name = NULL;
entry_point->export_name = NULL;
entry_point->u.func.nb_args = 0;
assert( !spec->ordinals[0] );
diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c
index f3feb0f3300..541c01f2006 100644
--- a/tools/winebuild/spec32.c
+++ b/tools/winebuild/spec32.c
@@ -274,6 +274,53 @@ static void output_relay_debug( DLLSPEC *spec )
}
/*******************************************************************
+ * output_syscall_thunks
+ *
+ * Output entry points for system call functions
+ */
+static void output_syscall_thunks( DLLSPEC *spec )
+{
+ char *name;
+ int i;
+
+ if (!spec->nb_syscalls)
+ return;
+
+ output( "\n/* syscall thunks */\n\n" );
+ output( "\t.text\n" );
+
+ for (i = 0; i < spec->nb_syscalls; i++)
+ {
+ ORDDEF *odp = spec->syscalls[i];
+ name = xstrdup(asm_name(odp->link_name));
+
+ output( "\t.align %d\n", get_alignment(16) );
+ output( "\t%s\n", func_declaration(name) );
+ output( "%s\n", asm_globl(name) );
+ output_cfi( ".cfi_startproc" );
+ output( "\tmovl $%s, %%eax\n", asm_name(odp->impl_name) );
+ output( "\tmovl $__wine_syscall_dispatcher, %%edx\n" );
+ output( "\tcall *%%edx\n" );
+ output( "\tret $%d\n", get_args_size(odp) );
+ output_cfi( ".cfi_endproc" );
+ output_function_size( name );
+
+ free( name );
+ }
+
+ output( "\t.align %d\n", get_alignment(16) );
+ output( "\t%s\n", func_declaration("__wine_syscall_dispatcher") );
+ output( "%s\n", asm_globl("__wine_syscall_dispatcher") );
+ output_cfi( ".cfi_startproc" );
+ output( "\tadd $4, %%esp\n" );
+ output( "\tjmp *%%eax\n" );
+ output( "\tret\n" );
+ output_cfi( ".cfi_endproc" );
+ output_function_size( "__wine_syscall_dispatcher" );
+ output( "\t.previous\n" );
+}
+
+/*******************************************************************
* output_exports
*
* Output the export table for a Win32 module.
@@ -624,6 +671,7 @@ void BuildSpec32File( DLLSPEC *spec )
output_standard_file_header();
output_module( spec );
output_stubs( spec );
+ output_syscall_thunks( spec );
output_exports( spec );
output_imports( spec );
if (is_undefined( "__wine_call_from_regs" )) output_asm_relays();
diff --git a/tools/winebuild/utils.c b/tools/winebuild/utils.c
index 6e01f1a5268..925054b8bb7 100644
--- a/tools/winebuild/utils.c
+++ b/tools/winebuild/utils.c
@@ -792,6 +792,7 @@ void free_dll_spec( DLLSPEC *spec )
free( odp->name );
free( odp->export_name );
free( odp->link_name );
+ free( odp->impl_name );
}
free( spec->file_name );
free( spec->dll_name );
@@ -801,6 +802,7 @@ void free_dll_spec( DLLSPEC *spec )
free( spec->names );
free( spec->ordinals );
free( spec->resources );
+ free( spec->syscalls );
free( spec );
}
@@ -1128,3 +1130,22 @@ const char *get_asm_string_section(void)
default: return ".section .rodata";
}
}
+
+/*******************************************************************
+ * sort_func_list
+ *
+ * Sort a list of functions, removing duplicates.
+ */
+int sort_func_list( ORDDEF **list, int count, int (*compare)(const void *, const void *) )
+{
+ int i, j;
+
+ if (!count) return 0;
+ qsort( list, count, sizeof(*list), compare );
+
+ for (i = j = 0; i < count; i++)
+ {
+ if (compare( &list[j], &list[i] )) list[++j] = list[i];
+ }
+ return j + 1;
+}
--
2.12.2

View File

@ -0,0 +1,90 @@
From a4aa8b13ef33ed01128652be1feaf6a98920372b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Fri, 12 May 2017 04:05:24 +0200
Subject: winebuild: Use Windows 7 WOW64 signature for syscall thunks.
---
dlls/ntdll/signal_i386.c | 2 ++
tools/winebuild/spec32.c | 32 ++++++++++++++++++++++++++------
2 files changed, 28 insertions(+), 6 deletions(-)
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index ac98ed0dba0..115f48d3dd1 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -481,6 +481,7 @@ static wine_signal_handler handlers[256];
static BOOL fpux_support; /* whether the CPU supports extended fpu context */
extern void DECLSPEC_NORETURN __wine_restore_regs( const CONTEXT *context );
+extern void DECLSPEC_NORETURN __wine_syscall_dispatcher( void );
enum i386_trap_code
{
@@ -2396,6 +2397,7 @@ NTSTATUS signal_alloc_thread( TEB **teb )
*teb = addr;
(*teb)->Tib.Self = &(*teb)->Tib;
(*teb)->Tib.ExceptionList = (void *)~0UL;
+ (*teb)->WOW32Reserved = __wine_syscall_dispatcher;
thread_data = (struct ntdll_thread_data *)(*teb)->SpareBytes1;
if (!(thread_data->fs = wine_ldt_alloc_fs()))
{
diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c
index 541c01f2006..7e08b756df4 100644
--- a/tools/winebuild/spec32.c
+++ b/tools/winebuild/spec32.c
@@ -298,26 +298,46 @@ static void output_syscall_thunks( DLLSPEC *spec )
output( "\t%s\n", func_declaration(name) );
output( "%s\n", asm_globl(name) );
output_cfi( ".cfi_startproc" );
- output( "\tmovl $%s, %%eax\n", asm_name(odp->impl_name) );
- output( "\tmovl $__wine_syscall_dispatcher, %%edx\n" );
- output( "\tcall *%%edx\n" );
- output( "\tret $%d\n", get_args_size(odp) );
+ output( "\t.byte 0xb8\n" ); /* mov eax, SYSCALL */
+ output( "\t.long %d\n", i );
+ output( "\t.byte 0x33,0xc9\n" ); /* xor ecx, ecx */
+ output( "\t.byte 0x8d,0x54,0x24,0x04\n" ); /* lea edx, [esp + 4] */
+ output( "\t.byte 0x64,0xff,0x15,0xc0,0x00,0x00,0x00\n" ); /* call dword ptr fs:[0C0h] */
+ output( "\t.byte 0x83,0xc4,0x04\n" ); /* add esp, 4 */
+ output( "\t.byte 0xc2\n" ); /* ret X */
+ output( "\t.short %d\n", get_args_size(odp) );
output_cfi( ".cfi_endproc" );
output_function_size( name );
free( name );
}
+ output( "\n/* syscall table */\n\n" );
+ output( "\t.data\n" );
+ output( "%s\n", asm_globl("__wine_syscall_table") );
+ for (i = 0; i < spec->nb_syscalls; i++)
+ {
+ ORDDEF *odp = spec->syscalls[i];
+ output ("\t%s %s\n", get_asm_ptr_keyword(), asm_name(odp->impl_name) );
+ }
+
+ output( "\n/* syscall dispatcher */\n\n" );
+ output( "\t.text\n" );
output( "\t.align %d\n", get_alignment(16) );
output( "\t%s\n", func_declaration("__wine_syscall_dispatcher") );
output( "%s\n", asm_globl("__wine_syscall_dispatcher") );
output_cfi( ".cfi_startproc" );
output( "\tadd $4, %%esp\n" );
- output( "\tjmp *%%eax\n" );
+ if (UsePIC)
+ {
+ output( "\tcall 1f\n" );
+ output( "1:\tpopl %%ecx\n" );
+ output( "\tjmpl *(%s-1b)(%%ecx,%%eax,%d)\n", asm_name("__wine_syscall_table"), get_ptr_size() );
+ }
+ else output( "\tjmpl *%s(,%%eax,4)\n", asm_name("__wine_syscall_table") );
output( "\tret\n" );
output_cfi( ".cfi_endproc" );
output_function_size( "__wine_syscall_dispatcher" );
- output( "\t.previous\n" );
}
/*******************************************************************
--
2.12.2

View File

@ -0,0 +1,430 @@
From dd66c26e64f14e3b72716449147a656a87232482 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Mon, 15 May 2017 02:05:49 +0200
Subject: winebuild: Use multipass label system to generate fake dlls.
---
tools/winebuild/build.h | 6 ++
tools/winebuild/res32.c | 1 -
tools/winebuild/spec32.c | 144 ++++++++++++++++++++++++++---------------------
tools/winebuild/utils.c | 92 ++++++++++++++++++++++++++++++
4 files changed, 179 insertions(+), 64 deletions(-)
diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h
index e338c9c8024..3434cfe9c90 100644
--- a/tools/winebuild/build.h
+++ b/tools/winebuild/build.h
@@ -328,6 +328,7 @@ 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_rva;
extern size_t output_buffer_size;
extern void init_input_buffer( const char *file );
@@ -343,6 +344,11 @@ 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 );
+extern void align_output_rva( unsigned int file_align, unsigned int rva_align );
+extern size_t label_pos( const char *name );
+extern size_t label_rva( const char *name );
+extern size_t label_rva_align( const char *name );
+extern void put_label( const char *name );
/* global variables */
diff --git a/tools/winebuild/res32.c b/tools/winebuild/res32.c
index 1686f567185..8db3213fbbd 100644
--- a/tools/winebuild/res32.c
+++ b/tools/winebuild/res32.c
@@ -534,7 +534,6 @@ void output_bin_resources( DLLSPEC *spec, unsigned int start_rva )
if (!spec->nb_resources) return;
tree = build_resource_tree( spec, &data_offset );
- init_output_buffer();
/* output the resource directories */
diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c
index 7e08b756df4..bc47cd7b32e 100644
--- a/tools/winebuild/spec32.c
+++ b/tools/winebuild/spec32.c
@@ -702,11 +702,11 @@ void BuildSpec32File( DLLSPEC *spec )
/*******************************************************************
- * output_fake_module
+ * output_fake_module_pass
*
- * Build a fake binary module from a spec file.
+ * Helper to create a fake binary module from a spec file.
*/
-void output_fake_module( DLLSPEC *spec )
+static void output_fake_module_pass( DLLSPEC *spec )
{
static const unsigned char dll_code_section[] = { 0x31, 0xc0, /* xor %eax,%eax */
0xc2, 0x0c, 0x00 }; /* ret $12 */
@@ -718,22 +718,8 @@ void output_fake_module( DLLSPEC *spec )
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 */
@@ -761,7 +747,7 @@ void output_fake_module( DLLSPEC *spec )
put_dword( lfanew );
put_data( fakedll_signature, sizeof(fakedll_signature) );
- align_output( 16 );
+ align_output_rva( 16, 16 );
put_dword( 0x4550 ); /* Signature */
switch(target_cpu)
@@ -785,11 +771,11 @@ void output_fake_module( DLLSPEC *spec )
IMAGE_NT_OPTIONAL_HDR32_MAGIC ); /* Magic */
put_byte( 7 ); /* MajorLinkerVersion */
put_byte( 10 ); /* MinorLinkerVersion */
- put_dword( text_size ); /* SizeOfCode */
+ put_dword( label_pos("text_end") - label_pos("text_start") ); /* SizeOfCode */
put_dword( 0 ); /* SizeOfInitializedData */
put_dword( 0 ); /* SizeOfUninitializedData */
- put_dword( section_align ); /* AddressOfEntryPoint */
- put_dword( section_align ); /* BaseOfCode */
+ put_dword( label_rva("text_start") ); /* AddressOfEntryPoint */
+ put_dword( label_rva("text_start") ); /* BaseOfCode */
if (get_ptr_size() == 4) put_dword( 0 ); /* BaseOfData */
put_pword( 0x10000000 ); /* ImageBase */
put_dword( section_align ); /* SectionAlignment */
@@ -801,8 +787,8 @@ void output_fake_module( DLLSPEC *spec )
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( label_rva_align("file_end") ); /* SizeOfImage */
+ put_dword( label_pos("header_end") ); /* SizeOfHeaders */
put_dword( 0 ); /* CheckSum */
put_word( spec->subsystem ); /* Subsystem */
put_word( spec->dll_characteristics ); /* DllCharacteristics */
@@ -815,10 +801,10 @@ void output_fake_module( DLLSPEC *spec )
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] */
+ if (spec->nb_resources) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] */
{
- put_dword( 3 * section_align );
- put_dword( resources_size );
+ put_dword( label_rva("res_start") );
+ put_dword( label_pos("res_end") - label_pos("res_start") );
}
else
{
@@ -828,8 +814,8 @@ void output_fake_module( DLLSPEC *spec )
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( label_rva("reloc_start") ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC] */
+ put_dword( label_pos("reloc_end") - label_pos("reloc_start") );
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] */
@@ -842,62 +828,94 @@ void output_fake_module( DLLSPEC *spec )
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 */
+ put_data( ".text\0\0", 8 ); /* Name */
+ put_dword( label_rva_align("text_end") - label_rva("text_start") ); /* VirtualSize */
+ put_dword( label_rva("text_start") ); /* VirtualAddress */
+ put_dword( label_pos("text_end") - label_pos("text_start") ); /* SizeOfRawData */
+ put_dword( label_pos("text_start") ); /* 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_data( ".reloc\0", 8 ); /* Name */
+ put_dword( label_rva_align("reloc_end") - label_rva("reloc_start") ); /* VirtualSize */
+ put_dword( label_rva("reloc_start") ); /* VirtualAddress */
+ put_dword( label_pos("reloc_end") - label_pos("reloc_start") ); /* SizeOfRawData */
+ put_dword( label_pos("reloc_start") ); /* 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)
+ if (spec->nb_resources)
{
- 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 */
+ put_data( ".rsrc\0\0", 8 ); /* Name */
+ put_dword( label_rva_align("res_end") - label_rva("res_start") ); /* VirtualSize */
+ put_dword( label_rva("res_start") ); /* VirtualAddress */
+ put_dword( label_pos("res_end") - label_pos("res_start") ); /* SizeOfRawData */
+ put_dword( label_pos("res_start") ); /* 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 */
}
+ align_output_rva( file_align, file_align );
+ put_label( "header_end" );
+
/* .text contents */
- align_output( file_align );
+ align_output_rva( file_align, section_align );
+ put_label( "text_start" );
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) );
+ put_label( "text_end" );
/* .reloc contents */
- align_output( file_align );
+ align_output_rva( file_align, section_align );
+ put_label( "reloc_start" );
put_dword( 0 ); /* VirtualAddress */
put_dword( 0 ); /* SizeOfBlock */
+ put_label( "reloc_end" );
/* .rsrc contents */
- if (resources_size)
+ if (spec->nb_resources)
{
- align_output( file_align );
- put_data( resources, resources_size );
+ align_output_rva( file_align, section_align );
+ put_label( "res_start" );
+ output_bin_resources( spec, label_rva("res_start") );
+ put_label( "res_end" );
}
+
+ put_label( "file_end" );
+}
+
+
+/*******************************************************************
+ * output_fake_module
+ *
+ * Build a fake binary module from a spec file.
+ */
+void output_fake_module( DLLSPEC *spec )
+{
+ resolve_imports( spec );
+
+ /* First pass */
+ init_output_buffer();
+ output_fake_module_pass( spec );
+
+ /* Second pass */
+ output_buffer_pos = 0;
+ output_buffer_rva = 0;
+ output_fake_module_pass( spec );
+
flush_output_buffer();
}
diff --git a/tools/winebuild/utils.c b/tools/winebuild/utils.c
index 925054b8bb7..eada46604ec 100644
--- a/tools/winebuild/utils.c
+++ b/tools/winebuild/utils.c
@@ -37,6 +37,7 @@
#include <sys/mman.h>
#endif
+#include "wine/list.h"
#include "build.h"
#if defined(_WIN32) && !defined(__CYGWIN__)
@@ -518,8 +519,86 @@ size_t input_buffer_pos;
size_t input_buffer_size;
unsigned char *output_buffer;
size_t output_buffer_pos;
+size_t output_buffer_rva;
size_t output_buffer_size;
+struct label
+{
+ struct list entry;
+ const char *name;
+ size_t pos;
+ size_t rva;
+};
+
+static struct list labels = LIST_INIT( labels );
+
+struct label *get_label( const char *name )
+{
+ struct label *label;
+
+ LIST_FOR_EACH_ENTRY( label, &labels, struct label, entry )
+ {
+ if (!strcmp(name, label->name))
+ return label;
+ }
+
+ label = xmalloc( sizeof(*label) );
+ label->name = name;
+ label->pos = 0;
+ label->rva = 0;
+
+ list_add_tail( &labels, &label->entry );
+
+ return label;
+}
+
+size_t label_pos( const char *name )
+{
+ struct label *label = get_label( name );
+ return label->pos;
+}
+
+size_t label_rva( const char *name )
+{
+ struct label *label = get_label( name );
+ return label->rva;
+}
+
+size_t label_rva_align( const char *name )
+{
+ const unsigned int page_size = get_page_size();
+ size_t rva = label_rva( name );
+ size_t size = page_size - (rva % page_size);
+
+ if (size != page_size) rva += size;
+ return rva;
+}
+
+void put_label( const char *name )
+{
+ struct label *label = get_label( name );
+
+ if (label->pos || label->rva)
+ {
+ assert( label->pos == output_buffer_pos );
+ assert( label->rva == output_buffer_rva );
+ }
+
+ label->pos = output_buffer_pos;
+ label->rva = output_buffer_rva;
+}
+
+void free_labels( void )
+{
+ struct label *label, *label2;
+
+ LIST_FOR_EACH_ENTRY_SAFE( label, label2, &labels, struct label, entry )
+ {
+ list_remove( &label->entry );
+ free( label );
+ }
+}
+
static void check_output_buffer_space( size_t size )
{
if (output_buffer_pos + size >= output_buffer_size)
@@ -556,7 +635,9 @@ void init_output_buffer(void)
{
output_buffer_size = 1024;
output_buffer_pos = 0;
+ output_buffer_rva = 0;
output_buffer = xmalloc( output_buffer_size );
+ free_labels();
}
void flush_output_buffer(void)
@@ -564,6 +645,7 @@ 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 );
+ free_labels();
}
unsigned char get_byte(void)
@@ -603,12 +685,14 @@ 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;
+ output_buffer_rva += size;
}
void put_byte( unsigned char val )
{
check_output_buffer_space( 1 );
output_buffer[output_buffer_pos++] = val;
+ output_buffer_rva++;
}
void put_word( unsigned short val )
@@ -655,6 +739,14 @@ void align_output( unsigned int align )
output_buffer_pos += size;
}
+void align_output_rva( unsigned int file_align, unsigned int rva_align )
+{
+ size_t size = rva_align - (output_buffer_rva % rva_align);
+
+ if (size != rva_align) output_buffer_rva += size;
+ align_output( file_align );
+}
+
/* output a standard header for generated files */
void output_standard_file_header(void)
{
--
2.12.2

View File

@ -0,0 +1,246 @@
From d9cb75b157dd6929d99c5a7b0b37639d87cfa0dd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Mon, 15 May 2017 16:27:56 +0200
Subject: winebuild: Add stub functions in fake dlls.
---
dlls/ntdll/signal_i386.c | 17 +++++++
tools/winebuild/build.h | 1 +
tools/winebuild/spec32.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++-
tools/winebuild/utils.c | 10 +++-
4 files changed, 141 insertions(+), 4 deletions(-)
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index 115f48d3dd1..3730afd38e0 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -1904,6 +1904,20 @@ static inline DWORD get_fpu_code( const CONTEXT *context )
return EXCEPTION_FLT_INVALID_OPERATION; /* generic error */
}
+static void fakedll_stub ( CONTEXT *context )
+{
+ EXCEPTION_RECORD record;
+
+ record.ExceptionCode = EXCEPTION_WINE_STUB;
+ record.ExceptionFlags = EH_NONCONTINUABLE;
+ record.ExceptionRecord = NULL;
+ record.ExceptionAddress = (void*)context->Eip;
+ record.NumberParameters = 2;
+ record.ExceptionInformation[0] = (ULONG_PTR)context->Ecx;
+ record.ExceptionInformation[1] = (ULONG_PTR)context->Edx;
+
+ for (;;) NtRaiseException( &record, context, TRUE );
+}
/**********************************************************************
* raise_segv_exception
@@ -1963,6 +1977,9 @@ static void WINAPI raise_segv_exception( EXCEPTION_RECORD *rec, CONTEXT *context
}
break;
case EXCEPTION_WINE_SYSCALL:
+ if (rec->ExceptionInformation[0] == 0xdeadc0de)
+ fakedll_stub( context );
+
FIXME("unimplemented syscall handler for 0x%lx, stack 0x%lx\n",
rec->ExceptionInformation[0], rec->ExceptionInformation[1]);
context->Eax = STATUS_INVALID_SYSTEM_SERVICE;
diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h
index 3434cfe9c90..e76800bb5da 100644
--- a/tools/winebuild/build.h
+++ b/tools/winebuild/build.h
@@ -343,6 +343,7 @@ 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 put_str( const char *str );
extern void align_output( unsigned int align );
extern void align_output_rva( unsigned int file_align, unsigned int rva_align );
extern size_t label_pos( const char *name );
diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c
index bc47cd7b32e..e2f7dcf43e0 100644
--- a/tools/winebuild/spec32.c
+++ b/tools/winebuild/spec32.c
@@ -701,6 +701,113 @@ void BuildSpec32File( DLLSPEC *spec )
}
+static void create_stub_exports_x86( DLLSPEC *spec )
+{
+ static const unsigned char dll_main[] = { 0xb8, 0x01, 0x00, 0x00, 0x00, /* mov eax, 0x1 */
+ 0xc2, 0x0c, 0x00 }; /* ret 12 */
+ int i, nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
+
+ /* entry function */
+ put_data( dll_main, sizeof(dll_main) );
+
+ if (!nr_exports) return;
+
+ /* pic thunk function */
+ align_output_rva( 16, 16 );
+ put_label( "_thunk_eax" );
+ put_byte( 0x8b ); put_byte( 0x04 ); put_byte( 0x24 ); /* mov eax, dword[esp] */
+ put_byte( 0xc3 ); /* ret */
+
+ /* output stub code for exports */
+ for (i = 0; i < spec->nb_entry_points; i++)
+ {
+ ORDDEF *odp = &spec->entry_points[i];
+ const char *name = get_stub_name( odp, spec );
+ size_t rva;
+
+ align_output_rva( 16, 16 );
+ put_label( name );
+
+ put_byte( 0x8b ); put_byte( 0xff ); /* mov edi, edi */
+ put_byte( 0x55 ); /* push ebp */
+ put_byte( 0x8b ); put_byte( 0xec ); /* mov ebp, esp */
+ rva = output_buffer_rva + 5;
+ put_byte( 0xe8 ); put_dword( label_rva("_thunk_eax") - rva ); /* call _thunk_eax */
+ put_byte( 0x8d ); put_byte( 0x88 ); /* lea ecx, [eax + dll_name] */
+ put_dword( label_rva("dll_fake_name") - rva );
+ if (!odp->name || (odp->flags & FLAG_NONAME))
+ {
+ put_byte( 0xba ); put_dword( odp->ordinal ); /* mov edx, ordinal */
+ }
+ else
+ {
+ put_byte( 0x8d ); put_byte( 0x90 ); /* lea edx, [eax + func_name] */
+ put_dword( label_rva(strmake("str_%s", name)) - rva );
+ }
+ put_byte( 0xb8 ); put_dword( 0xdeadc0de ); /* mov eax, 0xdeadc0de */
+ put_byte( 0xcd ); put_byte( 0x2e ); /* int 0x2e */
+ put_byte( 0x5d ); /* pop ebp */
+ put_byte( 0xc3 ); /* ret */
+ }
+
+ /* name to show in stub message */
+ align_output_rva( 16, 16 );
+ put_label( "dll_fake_name" );
+ put_str( strmake("(fake) %s", spec->file_name) );
+
+ /* export directory */
+ align_output_rva( 16, 16 );
+ put_label( "export_start" );
+ put_dword( 0 ); /* Characteristics */
+ put_dword( 0 ); /* TimeDateStamp */
+ put_dword( 0 ); /* MajorVersion/MinorVersion */
+ put_dword( label_rva("dll_name") ); /* Name */
+ put_dword( spec->base ); /* Base */
+ put_dword( nr_exports ); /* NumberOfFunctions */
+ put_dword( spec->nb_names ); /* NumberOfNames */
+ put_dword( label_rva("export_funcs") ); /* AddressOfFunctions */
+ put_dword( label_rva("export_names") ); /* AddressOfNames */
+ put_dword( label_rva("export_ordinals") ); /* AddressOfNameOrdinals */
+
+ put_label( "export_funcs" );
+ for (i = spec->base; i <= spec->limit; i++)
+ {
+ ORDDEF *odp = spec->ordinals[i];
+ if (odp)
+ {
+ const char *name = get_stub_name( odp, spec );
+ put_dword( label_rva( name ) );
+ }
+ else
+ put_dword( 0 );
+ }
+
+ if (spec->nb_names)
+ {
+ put_label( "export_names" );
+ for (i = 0; i < spec->nb_names; i++)
+ put_dword( label_rva(strmake("str_%s", get_stub_name(spec->names[i], spec))) );
+
+ put_label( "export_ordinals" );
+ for (i = 0; i < spec->nb_names; i++)
+ put_word( spec->names[i]->ordinal - spec->base );
+ if (spec->nb_names % 2)
+ put_word( 0 );
+ }
+
+ put_label( "dll_name" );
+ put_str( spec->file_name );
+
+ for (i = 0; i < spec->nb_names; i++)
+ {
+ put_label( strmake("str_%s", get_stub_name(spec->names[i], spec)) );
+ put_str( spec->names[i]->name );
+ }
+
+ put_label( "export_end" );
+}
+
+
/*******************************************************************
* output_fake_module_pass
*
@@ -799,7 +906,8 @@ static void output_fake_module_pass( DLLSPEC *spec )
put_dword( 0 ); /* LoaderFlags */
put_dword( 16 ); /* NumberOfRvaAndSizes */
- put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] */
+ put_dword( label_rva("export_start") ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] */
+ put_dword( label_pos("export_end") - label_pos("export_start") );
put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] */
if (spec->nb_resources) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] */
{
@@ -873,7 +981,12 @@ static void output_fake_module_pass( DLLSPEC *spec )
align_output_rva( file_align, section_align );
put_label( "text_start" );
if (spec->characteristics & IMAGE_FILE_DLL)
- put_data( dll_code_section, sizeof(dll_code_section) );
+ {
+ if (target_cpu == CPU_x86)
+ create_stub_exports_x86( spec );
+ else
+ put_data( dll_code_section, sizeof(dll_code_section) );
+ }
else
put_data( exe_code_section, sizeof(exe_code_section) );
put_label( "text_end" );
diff --git a/tools/winebuild/utils.c b/tools/winebuild/utils.c
index eada46604ec..b37ce9dc16f 100644
--- a/tools/winebuild/utils.c
+++ b/tools/winebuild/utils.c
@@ -525,7 +525,7 @@ size_t output_buffer_size;
struct label
{
struct list entry;
- const char *name;
+ char *name;
size_t pos;
size_t rva;
};
@@ -543,7 +543,7 @@ struct label *get_label( const char *name )
}
label = xmalloc( sizeof(*label) );
- label->name = name;
+ label->name = xstrdup( name );
label->pos = 0;
label->rva = 0;
@@ -595,6 +595,7 @@ void free_labels( void )
LIST_FOR_EACH_ENTRY_SAFE( label, label2, &labels, struct label, entry )
{
list_remove( &label->entry );
+ free( label->name );
free( label );
}
}
@@ -729,6 +730,11 @@ void put_pword( unsigned int val )
else put_dword( val );
}
+void put_str( const char *str )
+{
+ put_data( str, strlen(str)+1 );
+}
+
void align_output( unsigned int align )
{
size_t size = align - (output_buffer_pos % align);
--
2.12.2

View File

@ -0,0 +1,66 @@
From 614e3fe66a2c5f0c85a8bdddce5d6ba8244e765d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Mon, 15 May 2017 17:56:48 +0200
Subject: winebuild: Add syscall thunks in fake dlls.
---
tools/winebuild/spec32.c | 26 ++++++++++++++++++++++++--
1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c
index e2f7dcf43e0..bd200b44000 100644
--- a/tools/winebuild/spec32.c
+++ b/tools/winebuild/spec32.c
@@ -722,10 +722,14 @@ static void create_stub_exports_x86( DLLSPEC *spec )
for (i = 0; i < spec->nb_entry_points; i++)
{
ORDDEF *odp = &spec->entry_points[i];
- const char *name = get_stub_name( odp, spec );
+ const char *name;
size_t rva;
+ if (odp->flags & FLAG_SYSCALL)
+ continue;
+
align_output_rva( 16, 16 );
+ name = get_stub_name( odp, spec );
put_label( name );
put_byte( 0x8b ); put_byte( 0xff ); /* mov edi, edi */
@@ -750,6 +754,24 @@ static void create_stub_exports_x86( DLLSPEC *spec )
put_byte( 0xc3 ); /* ret */
}
+ /* output syscalls */
+ for (i = 0; i < spec->nb_syscalls; i++)
+ {
+ ORDDEF *odp = spec->syscalls[i];
+
+ align_output_rva( 16, 16 );
+ put_label( odp->link_name );
+
+ put_byte( 0xb8 ); put_dword( i ); /* mov eax, SYSCALL */
+ put_byte( 0x33 ); put_byte( 0xc9 ); /* xor ecx, ecx */
+ put_byte( 0x8d ); put_byte( 0x54 ); /* lea edx, [esp + 4] */
+ put_byte( 0x24 ); put_byte( 0x04 );
+ put_byte( 0x64 ); put_byte( 0xff ); /* call dword ptr fs:[0C0h] */
+ put_byte( 0x15 ); put_dword( 0xc0 );
+ put_byte( 0x83 ); put_byte( 0xc4 ); put_byte( 0x04 ); /* add esp, 4 */
+ put_byte( 0xc2 ); put_word( get_args_size(odp) ); /* ret X */
+ }
+
/* name to show in stub message */
align_output_rva( 16, 16 );
put_label( "dll_fake_name" );
@@ -775,7 +797,7 @@ static void create_stub_exports_x86( DLLSPEC *spec )
ORDDEF *odp = spec->ordinals[i];
if (odp)
{
- const char *name = get_stub_name( odp, spec );
+ const char *name = (odp->flags & FLAG_SYSCALL) ? odp->link_name : get_stub_name( odp, spec );
put_dword( label_rva( name ) );
}
else
--
2.12.2

View File

@ -0,0 +1,2 @@
Fixes: [42741] Various improvements for fake dlls
Depends: ntdll-Interrupt-0x2e