Commit 246c3606 authored by Alexandre Julliard's avatar Alexandre Julliard

Reserve space for the PE header at the start of the .so file.

Store the export table inside the data section so that sections can be properly aligned. Build the relay function table directly in the .spec.c file. Moved relay debugging functions to relay386.c.
parent a1b2fc2a
......@@ -7,33 +7,21 @@
#ifndef __WINE_BUILTIN32_H
#define __WINE_BUILTIN32_H
typedef void (*ENTRYPOINT32)();
typedef struct
{
const char *name; /* DLL name */
const char* filename; /* DLL file name */
int base; /* Ordinal base */
int nb_funcs; /* Number of functions */
int nb_names; /* Number of function names */
int nb_imports; /* Number of imported DLLs */
int fwd_size; /* Total size of forward names */
const ENTRYPOINT32 *functions; /* Pointer to function table */
const char * const *names; /* Pointer to names table */
const unsigned short *ordinals; /* Pointer to ordinals table */
const unsigned char *args; /* Pointer to argument lengths */
const unsigned int *argtypes; /* Pointer to argument types bitmask */
void *pe_header; /* Buffer for PE header */
void *exports; /* Pointer to export directory */
unsigned int exports_size; /* Total size of export directory */
const char * const *imports; /* Pointer to imports */
const ENTRYPOINT32 dllentrypoint;/* Pointer to LibMain function */
void (*dllentrypoint)(); /* Pointer to entry point function */
int characteristics;
const void *rsrc; /* Resource descriptor */
void *rsrc; /* Resource descriptor */
} BUILTIN32_DESCRIPTOR;
extern ENTRYPOINT32 BUILTIN32_GetEntryPoint( char *buffer, void *relay,
unsigned int *typemask );
extern void BUILTIN32_RegisterDLL( const BUILTIN32_DESCRIPTOR *descr );
extern void BUILTIN32_Unimplemented( const BUILTIN32_DESCRIPTOR *descr,
int ordinal );
extern void BUILTIN32_SwitchRelayDebug(int onoff);
extern void BUILTIN32_Unimplemented( const char *dllname, const char *funcname );
extern void RELAY_SetupDLL( const char *module );
#endif /* __WINE_BUILTIN32_H */
......@@ -708,14 +708,19 @@ typedef HANDLE *PHANDLE;
".long " __ASM_NAME(#fn) "\n\t" \
".byte " #args ", " #args )
#define DEFINE_REGS_ENTRYPOINT_0( name, fn ) \
extern void WINAPI name(void); \
_DEFINE_REGS_ENTRYPOINT( name, fn, 0 )
#define DEFINE_REGS_ENTRYPOINT_1( name, fn, t1 ) \
extern void WINAPI name( t1 a1 ); \
_DEFINE_REGS_ENTRYPOINT( name, fn, 4 )
#define DEFINE_REGS_ENTRYPOINT_2( name, fn, t1, t2 ) \
extern void WINAPI name( t1 a1, t2 a2 ); \
_DEFINE_REGS_ENTRYPOINT( name, fn, 8 )
#define DEFINE_REGS_ENTRYPOINT_3( name, fn, t1, t2, t3 ) \
extern void WINAPI name( t1 a1, t2 a2, t3 a3 ); \
_DEFINE_REGS_ENTRYPOINT( name, fn, 12 )
#define DEFINE_REGS_ENTRYPOINT_4( name, fn, t1, t2, t3, t4 ) \
extern void WINAPI name( t1 a1, t2 a2, t3 a3, t4 a4 ); \
_DEFINE_REGS_ENTRYPOINT( name, fn, 16 )
#endif /* __i386__ */
......@@ -1619,9 +1624,9 @@ typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD Base;
DWORD NumberOfFunctions;
DWORD NumberOfNames;
LPDWORD *AddressOfFunctions;
LPDWORD *AddressOfNames;
LPWORD *AddressOfNameOrdinals;
DWORD AddressOfFunctions;
DWORD AddressOfNames;
DWORD AddressOfNameOrdinals;
} IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY;
/* Import name entry */
......
......@@ -22,7 +22,6 @@
#include "msdos.h"
#include "color.h"
#include "options.h"
#include "builtin32.h"
#include "debugtools.h"
#include "debugdefs.h"
#include "module.h"
......@@ -111,7 +110,7 @@ void MAIN_ParseDebugOptions( const char *arg )
extern char **debug_snoop_excludelist;
int i;
int l, cls, dotracerelay = TRACE_ON(relay);
int l, cls;
char *options = strdup(arg);
......@@ -214,10 +213,6 @@ void MAIN_ParseDebugOptions( const char *arg )
}
while((*options==',')&&(*(++options)));
/* special handling for relay debugging */
if (dotracerelay != TRACE_ON(relay))
BUILTIN32_SwitchRelayDebug( TRACE_ON(relay) );
if (!*options) return;
error:
......
......@@ -7,12 +7,15 @@
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include "winnt.h"
#include "builtin32.h"
#include "selectors.h"
#include "stackframe.h"
#include "syslevel.h"
#include "main.h"
#include "module.h"
#include "process.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(relay);
......@@ -62,6 +65,77 @@ int RELAY_ShowDebugmsgRelay(const char *func) {
#ifdef __i386__
typedef struct
{
BYTE call; /* 0xe8 call callfrom32 (relative) */
DWORD callfrom32 WINE_PACKED; /* RELAY_CallFrom32 relative addr */
BYTE ret; /* 0xc2 ret $n or 0xc3 ret */
WORD args; /* nb of args to remove from the stack */
FARPROC orig; /* original entry point */
DWORD argtypes; /* argument types */
} DEBUG_ENTRY_POINT;
/***********************************************************************
* find_exported_name
*
* Find the name of an exported function.
*/
static const char *find_exported_name( const char *module,
IMAGE_EXPORT_DIRECTORY *exp, int ordinal )
{
int i;
const char *ret = NULL;
WORD *ordptr = (WORD *)(module + exp->AddressOfNameOrdinals);
for (i = 0; i < exp->NumberOfNames; i++, ordptr++)
if (*ordptr + exp->Base == ordinal) break;
if (i < exp->NumberOfNames)
ret = module + ((DWORD*)(module + exp->AddressOfNames))[i];
return ret;
}
/***********************************************************************
* get_entry_point
*
* Get the name of the DLL entry point corresponding to a relay address.
*/
static void get_entry_point( char *buffer, DEBUG_ENTRY_POINT *relay )
{
IMAGE_DATA_DIRECTORY *dir;
IMAGE_EXPORT_DIRECTORY *exp = NULL;
DEBUG_ENTRY_POINT *debug;
char *base = NULL;
const char *name;
int ordinal = 0;
WINE_MODREF *wm;
/* First find the module */
for (wm = PROCESS_Current()->modref_list; wm; wm = wm->next)
{
if (wm->type != MODULE32_PE) continue;
if (!(wm->flags & WINE_MODREF_INTERNAL)) continue;
base = (char *)wm->module;
dir = &PE_HEADER(base)->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY];
if (!dir->Size) continue;
exp = (IMAGE_EXPORT_DIRECTORY *)(base + dir->VirtualAddress);
debug = (DEBUG_ENTRY_POINT *)((char *)exp + dir->Size);
if (debug <= relay && relay < debug + exp->NumberOfFunctions)
{
ordinal = relay - debug;
break;
}
}
/* Now find the function */
name = find_exported_name( base, exp, ordinal + exp->Base );
sprintf( buffer, "%s.%ld: %s", base + exp->Name, ordinal + exp->Base, name ? name : "@" );
}
/***********************************************************************
* RELAY_PrintArgs
*/
......@@ -94,29 +168,28 @@ static inline void RELAY_PrintArgs( int *args, int nb_args, unsigned int typemas
* (esp+4) ret_addr
* (esp) return addr to relay code
*/
int RELAY_CallFrom32( int ret_addr, ... )
static int RELAY_CallFrom32( int ret_addr, ... )
{
int ret;
char buffer[80];
unsigned int typemask;
FARPROC func;
int *args = &ret_addr + 1;
/* Relay addr is the return address for this function */
BYTE *relay_addr = (BYTE *)__builtin_return_address(0);
WORD nb_args = *(WORD *)(relay_addr + 1) / sizeof(int);
DEBUG_ENTRY_POINT *relay = (DEBUG_ENTRY_POINT *)(relay_addr - 5);
WORD nb_args = relay->args / sizeof(int);
get_entry_point( buffer, relay );
assert(TRACE_ON(relay));
func = (FARPROC)BUILTIN32_GetEntryPoint( buffer, relay_addr - 5, &typemask );
DPRINTF( "Call %s(", buffer );
RELAY_PrintArgs( args, nb_args, typemask );
RELAY_PrintArgs( args, nb_args, relay->argtypes );
DPRINTF( ") ret=%08x fs=%04x\n", ret_addr, __get_fs() );
SYSLEVEL_CheckNotLevel( 2 );
if (*relay_addr == 0xc3) /* cdecl */
if (relay->ret == 0xc3) /* cdecl */
{
LRESULT (*cfunc)() = (LRESULT(*)())func;
LRESULT (*cfunc)() = (LRESULT(*)())relay->orig;
switch(nb_args)
{
case 0: ret = cfunc(); break;
......@@ -159,6 +232,7 @@ int RELAY_CallFrom32( int ret_addr, ... )
}
else /* stdcall */
{
FARPROC func = relay->orig;
switch(nb_args)
{
case 0: ret = func(); break;
......@@ -225,14 +299,14 @@ void WINAPI RELAY_DoCallFrom32Regs( CONTEXT86 *context );
DEFINE_REGS_ENTRYPOINT_0( RELAY_CallFrom32Regs, RELAY_DoCallFrom32Regs )
void WINAPI RELAY_DoCallFrom32Regs( CONTEXT86 *context )
{
unsigned int typemask;
char buffer[80];
int* args;
FARPROC func;
BYTE *entry_point;
BYTE *relay_addr = *((BYTE **)ESP_reg(context) - 1);
WORD nb_args = *(WORD *)(relay_addr + 1) / sizeof(int);
DEBUG_ENTRY_POINT *relay = (DEBUG_ENTRY_POINT *)(relay_addr - 5);
WORD nb_args = (relay->args & ~0x8000) / sizeof(int);
/* remove extra stuff from the stack */
EIP_reg(context) = stack32_pop(context);
......@@ -241,12 +315,14 @@ void WINAPI RELAY_DoCallFrom32Regs( CONTEXT86 *context )
assert(TRACE_ON(relay));
entry_point = (BYTE *)BUILTIN32_GetEntryPoint( buffer, relay_addr - 5, &typemask );
entry_point = (BYTE *)relay->orig;
assert( *entry_point == 0xe8 /* lcall */ );
func = *(FARPROC *)(entry_point + 5);
get_entry_point( buffer, relay );
DPRINTF( "Call %s(", buffer );
RELAY_PrintArgs( args, nb_args, typemask );
RELAY_PrintArgs( args, nb_args, relay->argtypes );
DPRINTF( ") ret=%08lx fs=%04lx\n", EIP_reg(context), FS_reg(context) );
DPRINTF(" eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx esi=%08lx edi=%08lx\n",
......@@ -302,5 +378,65 @@ void WINAPI RELAY_DoCallFrom32Regs( CONTEXT86 *context )
SYSLEVEL_CheckNotLevel( 2 );
}
#endif /* __i386__ */
/***********************************************************************
* RELAY_SetupDLL
*
* Setup relay debugging for a built-in dll.
*/
void RELAY_SetupDLL( const char *module )
{
IMAGE_DATA_DIRECTORY *dir;
IMAGE_EXPORT_DIRECTORY *exports;
DEBUG_ENTRY_POINT *debug;
DWORD *funcs;
int i;
const char *name, *dllname;
dir = &PE_HEADER(module)->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY];
if (!dir->Size) return;
exports = (IMAGE_EXPORT_DIRECTORY *)(module + dir->VirtualAddress);
debug = (DEBUG_ENTRY_POINT *)((char *)exports + dir->Size);
funcs = (DWORD *)(module + exports->AddressOfFunctions);
dllname = module + exports->Name;
for (i = 0; i < exports->NumberOfFunctions; i++, funcs++, debug++)
{
int on = 1;
if (!debug->call) continue; /* not a normal function */
if ((name = find_exported_name( module, exports, i + exports->Base )))
{
char buffer[200];
sprintf( buffer, "%s.%d: %s", dllname, i, name );
on = RELAY_ShowDebugmsgRelay(buffer);
}
if (on)
{
debug->call = 0xe8; /* call relative */
if (debug->args & 0x8000) /* register func */
debug->callfrom32 = (char *)RELAY_CallFrom32Regs - (char *)&debug->ret;
else
debug->callfrom32 = (char *)RELAY_CallFrom32 - (char *)&debug->ret;
}
else
{
debug->call = 0xe9; /* jmp relative */
debug->callfrom32 = (char *)debug->orig - (char *)&debug->ret;
}
debug->orig = (FARPROC)(module + (DWORD)*funcs);
*funcs = (char *)debug - module;
}
}
#else /* __i386__ */
void RELAY_SetupDLL( const char *module )
{
}
#endif /* __i386__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment