Commit d5088668 authored by Alexandre Julliard's avatar Alexandre Julliard

Generate stub entries on the fly for missing entry points instead of

returning a deadbeef pointer.
parent c7471d11
...@@ -135,8 +135,12 @@ static int format_exception_msg( const EXCEPTION_POINTERS *ptr, char *buffer, in ...@@ -135,8 +135,12 @@ static int format_exception_msg( const EXCEPTION_POINTERS *ptr, char *buffer, in
rec->ExceptionInformation[0]); rec->ExceptionInformation[0]);
break; break;
case EXCEPTION_WINE_STUB: case EXCEPTION_WINE_STUB:
if (HIWORD(rec->ExceptionInformation[1]))
len = snprintf( buffer, size, "Unimplemented function %s.%s called", len = snprintf( buffer, size, "Unimplemented function %s.%s called",
(char *)rec->ExceptionInformation[0], (char *)rec->ExceptionInformation[1] ); (char *)rec->ExceptionInformation[0], (char *)rec->ExceptionInformation[1] );
else
len = snprintf( buffer, size, "Unimplemented function %s.%ld called",
(char *)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
break; break;
case EXCEPTION_WINE_ASSERTION: case EXCEPTION_WINE_ASSERTION:
len = snprintf( buffer, size, "Assertion failed" ); len = snprintf( buffer, size, "Assertion failed" );
......
...@@ -233,8 +233,16 @@ void WINAPI EXC_RtlRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context ) ...@@ -233,8 +233,16 @@ void WINAPI EXC_RtlRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context )
TRACE( "code=%lx flags=%lx addr=%p\n", rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress ); TRACE( "code=%lx flags=%lx addr=%p\n", rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
for (c=0; c<rec->NumberParameters; c++) TRACE(" info[%ld]=%08lx\n", c, rec->ExceptionInformation[c]); for (c=0; c<rec->NumberParameters; c++) TRACE(" info[%ld]=%08lx\n", c, rec->ExceptionInformation[c]);
if (rec->ExceptionCode == EXCEPTION_WINE_STUB) if (rec->ExceptionCode == EXCEPTION_WINE_STUB)
FIXME( "call to unimplemented function %s.%s\n", {
if (HIWORD(rec->ExceptionInformation[1]))
FIXME( "call (from %p) to unimplemented function %s.%s\n",
rec->ExceptionAddress,
(char*)rec->ExceptionInformation[0], (char*)rec->ExceptionInformation[1] ); (char*)rec->ExceptionInformation[0], (char*)rec->ExceptionInformation[1] );
else
FIXME( "call (from %p) to unimplemented function %s.%ld\n",
rec->ExceptionAddress,
(char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
}
#ifdef __i386__ #ifdef __i386__
else else
{ {
......
...@@ -158,6 +158,83 @@ static inline BOOL call_dll_entry_point( DLLENTRYPROC proc, void *module, ...@@ -158,6 +158,83 @@ static inline BOOL call_dll_entry_point( DLLENTRYPROC proc, void *module,
#endif /* __i386__ */ #endif /* __i386__ */
#ifdef __i386__
/*************************************************************************
* stub_entry_point
*
* Entry point for stub functions.
*/
static void stub_entry_point( const char *dll, const char *name, ... )
{
EXCEPTION_RECORD rec;
rec.ExceptionCode = EXCEPTION_WINE_STUB;
rec.ExceptionFlags = EH_NONCONTINUABLE;
rec.ExceptionRecord = NULL;
#ifdef __GNUC__
rec.ExceptionAddress = __builtin_return_address(0);
#else
rec.ExceptionAddress = *((void **)&dll - 1);
#endif
rec.NumberParameters = 2;
rec.ExceptionInformation[0] = (DWORD)dll;
rec.ExceptionInformation[1] = (DWORD)name;
for (;;) RtlRaiseException( &rec );
}
#include <pshpack1.h>
struct stub
{
BYTE popl_eax; /* popl %eax */
BYTE pushl1; /* pushl $name */
const char *name;
BYTE pushl2; /* pushl $dll */
const char *dll;
BYTE pushl_eax; /* pushl %eax */
BYTE jmp; /* jmp stub_entry_point */
DWORD entry;
};
#include <poppack.h>
/*************************************************************************
* allocate_stub
*
* Allocate a stub entry point.
*/
static void *allocate_stub( const char *dll, const char *name )
{
#define MAX_SIZE 65536
static struct stub *stubs;
static unsigned int nb_stubs;
struct stub *stub;
if (nb_stubs >= MAX_SIZE / sizeof(*stub)) return (void *)0xdeadbeef;
if (!stubs)
{
ULONG size = MAX_SIZE;
if (NtAllocateVirtualMemory( GetCurrentProcess(), (void **)&stubs, 0, &size,
MEM_COMMIT, PAGE_EXECUTE_WRITECOPY ) != STATUS_SUCCESS)
return (void *)0xdeadbeef;
}
stub = &stubs[nb_stubs++];
stub->popl_eax = 0x58; /* popl %eax */
stub->pushl1 = 0x68; /* pushl $name */
stub->name = name;
stub->pushl2 = 0x68; /* pushl $dll */
stub->dll = dll;
stub->pushl_eax = 0x50; /* pushl %eax */
stub->jmp = 0xe9; /* jmp stub_entry_point */
stub->entry = (BYTE *)stub_entry_point - (BYTE *)(&stub->entry + 1);
return stub;
}
#else /* __i386__ */
static inline void *allocate_stub( const char *dll, const char *name ) { return (void *)0xdeadbeef; }
#endif /* __i386__ */
/************************************************************************* /*************************************************************************
* get_modref * get_modref
* *
...@@ -426,17 +503,19 @@ static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *d ...@@ -426,17 +503,19 @@ static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *d
{ {
if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal)) if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal))
{ {
ERR("No implementation for %s.%ld", name, IMAGE_ORDINAL(import_list->u1.Ordinal)); int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal);
WARN("No implementation for %s.%d", name, ordinal );
thunk_list->u1.Function = allocate_stub( name, (const char *)ordinal );
} }
else else
{ {
IMAGE_IMPORT_BY_NAME *pe_name = get_rva( module, (DWORD)import_list->u1.AddressOfData ); IMAGE_IMPORT_BY_NAME *pe_name = get_rva( module, (DWORD)import_list->u1.AddressOfData );
ERR("No implementation for %s.%s", name, pe_name->Name ); WARN("No implementation for %s.%s", name, pe_name->Name );
thunk_list->u1.Function = allocate_stub( name, pe_name->Name );
} }
ERR(" imported from %s, setting to 0xdeadbeef\n", WARN(" imported from %s, allocating stub %p\n",
debugstr_w(current_modref->ldr.FullDllName.Buffer) ); debugstr_w(current_modref->ldr.FullDllName.Buffer),
thunk_list->u1.Function = (PDWORD)0xdeadbeef; thunk_list->u1.Function );
import_list++; import_list++;
thunk_list++; thunk_list++;
} }
...@@ -453,9 +532,10 @@ static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *d ...@@ -453,9 +532,10 @@ static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *d
ordinal - exports->Base ); ordinal - exports->Base );
if (!thunk_list->u1.Function) if (!thunk_list->u1.Function)
{ {
ERR("No implementation for %s.%d imported from %s, setting to 0xdeadbeef\n", thunk_list->u1.Function = allocate_stub( name, (const char *)ordinal );
name, ordinal, debugstr_w(current_modref->ldr.FullDllName.Buffer) ); WARN("No implementation for %s.%d imported from %s, setting to %p\n",
thunk_list->u1.Function = (PDWORD)0xdeadbeef; name, ordinal, debugstr_w(current_modref->ldr.FullDllName.Buffer),
thunk_list->u1.Function );
} }
TRACE("--- Ordinal %s.%d = %p\n", name, ordinal, thunk_list->u1.Function ); TRACE("--- Ordinal %s.%d = %p\n", name, ordinal, thunk_list->u1.Function );
} }
...@@ -467,9 +547,10 @@ static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *d ...@@ -467,9 +547,10 @@ static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *d
pe_name->Name, pe_name->Hint ); pe_name->Name, pe_name->Hint );
if (!thunk_list->u1.Function) if (!thunk_list->u1.Function)
{ {
ERR("No implementation for %s.%s imported from %s, setting to 0xdeadbeef\n", thunk_list->u1.Function = allocate_stub( name, pe_name->Name );
name, pe_name->Name, debugstr_w(current_modref->ldr.FullDllName.Buffer) ); WARN("No implementation for %s.%s imported from %s, setting to %p\n",
thunk_list->u1.Function = (PDWORD)0xdeadbeef; name, pe_name->Name, debugstr_w(current_modref->ldr.FullDllName.Buffer),
thunk_list->u1.Function );
} }
TRACE("--- %s %s.%d = %p\n", pe_name->Name, name, pe_name->Hint, thunk_list->u1.Function); TRACE("--- %s %s.%d = %p\n", pe_name->Name, name, pe_name->Hint, thunk_list->u1.Function);
} }
......
...@@ -640,9 +640,12 @@ static DWORD dbg_handle_exception(EXCEPTION_RECORD* rec, BOOL first_chance) ...@@ -640,9 +640,12 @@ static DWORD dbg_handle_exception(EXCEPTION_RECORD* rec, BOOL first_chance)
memory_get_string(dbg_curr_process->handle, memory_get_string(dbg_curr_process->handle,
(void*)rec->ExceptionInformation[0], TRUE, FALSE, (void*)rec->ExceptionInformation[0], TRUE, FALSE,
dll, sizeof(dll)); dll, sizeof(dll));
if (HIWORD(rec->ExceptionInformation[1]))
memory_get_string(dbg_curr_process->handle, memory_get_string(dbg_curr_process->handle,
(void*)rec->ExceptionInformation[1], TRUE, FALSE, (void*)rec->ExceptionInformation[1], TRUE, FALSE,
name, sizeof(name)); name, sizeof(name));
else
sprintf( name, "%ld", rec->ExceptionInformation[1] );
dbg_printf("unimplemented function %s.%s called", dll, name); dbg_printf("unimplemented function %s.%s called", dll, name);
} }
break; break;
......
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