Alexandre Julliard : winebuild: Support relay debugging for PE builtin dlls.

Alexandre Julliard julliard at winehq.org
Fri May 17 16:10:14 CDT 2019


Module: wine
Branch: master
Commit: 6c41cc61529f238fd7a7dc7eb4162d0fe8427e8d
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=6c41cc61529f238fd7a7dc7eb4162d0fe8427e8d

Author: Alexandre Julliard <julliard at 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 at 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" );




More information about the wine-cvs mailing list