Module: wine Branch: master Commit: 6c41cc61529f238fd7a7dc7eb4162d0fe8427e8d URL: https://source.winehq.org/git/wine.git/?a=commit;h=6c41cc61529f238fd7a7dc7eb...
Author: Alexandre Julliard julliard@winehq.org Date: Thu May 16 21:33:47 2019 +0200
winebuild: Support relay debugging for PE builtin dlls.
Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ntdll/loader.c | 9 ++++++++- dlls/ntdll/relay.c | 47 ++++++++++++++++++++++++++++++++++++++++------- tools/winebuild/spec32.c | 30 ++++++++++++++++++++++-------- 3 files changed, 70 insertions(+), 16 deletions(-)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 8dae813..c77f329 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -2190,7 +2190,14 @@ static NTSTATUS load_native_dll( LPCWSTR load_path, const UNICODE_STRING *nt_nam } SERVER_END_REQ;
- if ((wm->ldr.Flags & LDR_IMAGE_IS_DLL) && TRACE_ON(snoop)) SNOOP_SetupDLL( module ); + if (image_info->image_flags & IMAGE_FLAGS_WineBuiltin) + { + if (TRACE_ON(relay)) RELAY_SetupDLL( module ); + } + else + { + if ((wm->ldr.Flags & LDR_IMAGE_IS_DLL) && TRACE_ON(snoop)) SNOOP_SetupDLL( module ); + }
TRACE_(loaddll)( "Loaded %s at %p: %s\n", debugstr_w(wm->ldr.FullDllName.Buffer), module, dll_type );
diff --git a/dlls/ntdll/relay.c b/dlls/ntdll/relay.c index 255d0e1..1deb2b7 100644 --- a/dlls/ntdll/relay.c +++ b/dlls/ntdll/relay.c @@ -42,7 +42,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(relay);
struct relay_descr /* descriptor for a module */ { - void *magic; /* signature */ + ULONG_PTR magic; /* signature */ void *relay_call; /* functions to call from relay thunks */ void *private; /* reserved for the relay code private data */ const char *entry_point_base; /* base address of entry point thunks */ @@ -50,7 +50,13 @@ struct relay_descr /* descriptor for a module */ const char *args_string; /* string describing the arguments */ };
-#define RELAY_DESCR_MAGIC ((void *)0xdeb90002) +struct relay_descr_rva /* RVA to the descriptor for PE dlls */ +{ + DWORD magic; + DWORD descr; +}; + +#define RELAY_DESCR_MAGIC 0xdeb90002 #define IS_INTARG(x) (((ULONG_PTR)(x) >> 16) == 0)
/* private data built at dll load time */ @@ -837,6 +843,26 @@ __ASM_GLOBAL_FUNC( relay_call, #endif
+static struct relay_descr *get_relay_descr( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports, + DWORD exp_size ) +{ + struct relay_descr *descr; + struct relay_descr_rva *rva; + ULONG_PTR ptr = (ULONG_PTR)module + exports->Name; + + /* sanity checks */ + if (ptr <= (ULONG_PTR)(exports + 1)) return NULL; + if (ptr > (ULONG_PTR)exports + exp_size) return NULL; + if (ptr % sizeof(DWORD)) return NULL; + + rva = (struct relay_descr_rva *)ptr - 1; + if (rva->magic != RELAY_DESCR_MAGIC) return NULL; + if (rva->descr) descr = (struct relay_descr *)((char *)module + rva->descr); + else descr = (struct relay_descr *)((const char *)exports + exp_size); + if (descr->magic != RELAY_DESCR_MAGIC) return NULL; + return descr; +} + /*********************************************************************** * RELAY_GetProcAddress * @@ -846,9 +872,9 @@ FARPROC RELAY_GetProcAddress( HMODULE module, const IMAGE_EXPORT_DIRECTORY *expo DWORD exp_size, FARPROC proc, DWORD ordinal, const WCHAR *user ) { struct relay_private_data *data; - const struct relay_descr *descr = (const struct relay_descr *)((const char *)exports + exp_size); + const struct relay_descr *descr = get_relay_descr( module, exports, exp_size );
- if (descr->magic != RELAY_DESCR_MAGIC || !(data = descr->private)) return proc; /* no relay data */ + if (!descr || !(data = descr->private)) return proc; /* no relay data */ if (!data->entry_points[ordinal].orig_func) return proc; /* not a relayed function */ if (check_from_module( debug_from_relay_includelist, debug_from_relay_excludelist, user )) return proc; /* we want to relay it */ @@ -866,18 +892,19 @@ void RELAY_SetupDLL( HMODULE module ) IMAGE_EXPORT_DIRECTORY *exports; DWORD *funcs; unsigned int i, len; - DWORD size, entry_point_rva; + DWORD size, entry_point_rva, old_prot; struct relay_descr *descr; struct relay_private_data *data; const WORD *ordptr; + void *func_base; + SIZE_T func_size;
RtlRunOnceExecuteOnce( &init_once, init_debug_lists, NULL, NULL );
exports = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size ); if (!exports) return;
- descr = (struct relay_descr *)((char *)exports + size); - if (descr->magic != RELAY_DESCR_MAGIC) return; + if (!(descr = get_relay_descr( module, exports, size ))) return;
if (!(data = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) + (exports->NumberOfFunctions-1) * sizeof(data->entry_points) ))) @@ -907,6 +934,10 @@ void RELAY_SetupDLL( HMODULE module )
funcs = (DWORD *)((char *)module + exports->AddressOfFunctions); entry_point_rva = descr->entry_point_base - (const char *)module; + + func_base = funcs; + func_size = exports->NumberOfFunctions * sizeof(*funcs); + NtProtectVirtualMemory( NtCurrentProcess(), &func_base, &func_size, PAGE_READWRITE, &old_prot ); for (i = 0; i < exports->NumberOfFunctions; i++, funcs++) { if (!descr->entry_point_offsets[i]) continue; /* not a normal function */ @@ -916,6 +947,8 @@ void RELAY_SetupDLL( HMODULE module ) data->entry_points[i].orig_func = (char *)module + *funcs; *funcs = entry_point_rva + descr->entry_point_offsets[i]; } + if (old_prot != PAGE_READWRITE) + NtProtectVirtualMemory( NtCurrentProcess(), &func_base, &func_size, old_prot, &old_prot ); }
#else /* __i386__ || __x86_64__ || __arm__ || __aarch64__ */ diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c index 68b50f9..a0aa017 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c @@ -379,6 +379,7 @@ static void output_relay_debug( DLLSPEC *spec ) void output_exports( DLLSPEC *spec ) { int i, fwd_size = 0; + int needs_relay = has_relays( spec ); int nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0; const char *func_ptr = (target_platform == PLATFORM_WINDOWS) ? ".rva" : get_asm_ptr_keyword();
@@ -472,6 +473,13 @@ void output_exports( DLLSPEC *spec ) } }
+ if (needs_relay) + { + output( "\t.long 0xdeb90002\n" ); /* magic */ + if (target_platform == PLATFORM_WINDOWS) output_rva( ".L__wine_spec_relay_descr" ); + else output( "\t.long 0\n" ); + } + /* output the export name strings */
output( "\n.L__wine_spec_exp_names:\n" ); @@ -493,17 +501,23 @@ void output_exports( DLLSPEC *spec ) } }
- if (target_platform == PLATFORM_WINDOWS) return; - - output( "\t.align %d\n", get_alignment(get_ptr_size()) ); - output( ".L__wine_spec_exports_end:\n" ); - /* output relays */
- if (!has_relays( spec )) + if (target_platform == PLATFORM_WINDOWS) { - output( "\t%s 0\n", get_asm_ptr_keyword() ); - return; + if (!needs_relay) return; + output( "\t.data\n" ); + output( "\t.align %d\n", get_alignment(get_ptr_size()) ); + } + else + { + output( "\t.align %d\n", get_alignment(get_ptr_size()) ); + output( ".L__wine_spec_exports_end:\n" ); + if (!needs_relay) + { + output( "\t%s 0\n", get_asm_ptr_keyword() ); + return; + } }
output( ".L__wine_spec_relay_descr:\n" );