winebuild: Support relay debugging for PE builtin dlls.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
stable
Alexandre Julliard 2019-05-16 21:33:47 +02:00
parent d38ec9e226
commit 6c41cc6152
3 changed files with 70 additions and 16 deletions

View File

@ -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 );

View File

@ -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__ */

View File

@ -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" );