mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-01-28 22:04:43 -08:00
Added patch with various improvements for fake dlls.
This commit is contained in:
parent
5d38a0fed0
commit
6a14f80fdc
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
2
patches/winebuild-Fake_Dlls/definition
Normal file
2
patches/winebuild-Fake_Dlls/definition
Normal file
@ -0,0 +1,2 @@
|
||||
Fixes: [42741] Various improvements for fake dlls
|
||||
Depends: ntdll-Interrupt-0x2e
|
Loading…
x
Reference in New Issue
Block a user