Generate stub entries on the fly for missing entry points instead of
returning a deadbeef pointer.
This commit is contained in:
parent
c7471d11ef
commit
d5088668de
|
@ -135,8 +135,12 @@ static int format_exception_msg( const EXCEPTION_POINTERS *ptr, char *buffer, in
|
|||
rec->ExceptionInformation[0]);
|
||||
break;
|
||||
case EXCEPTION_WINE_STUB:
|
||||
if (HIWORD(rec->ExceptionInformation[1]))
|
||||
len = snprintf( buffer, size, "Unimplemented function %s.%s called",
|
||||
(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;
|
||||
case EXCEPTION_WINE_ASSERTION:
|
||||
len = snprintf( buffer, size, "Assertion failed" );
|
||||
|
|
|
@ -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 );
|
||||
for (c=0; c<rec->NumberParameters; c++) TRACE(" info[%ld]=%08lx\n", c, rec->ExceptionInformation[c]);
|
||||
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] );
|
||||
else
|
||||
FIXME( "call (from %p) to unimplemented function %s.%ld\n",
|
||||
rec->ExceptionAddress,
|
||||
(char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
|
||||
}
|
||||
#ifdef __i386__
|
||||
else
|
||||
{
|
||||
|
|
|
@ -158,6 +158,83 @@ static inline BOOL call_dll_entry_point( DLLENTRYPROC proc, void *module,
|
|||
#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
|
||||
*
|
||||
|
@ -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))
|
||||
{
|
||||
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
|
||||
{
|
||||
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",
|
||||
debugstr_w(current_modref->ldr.FullDllName.Buffer) );
|
||||
thunk_list->u1.Function = (PDWORD)0xdeadbeef;
|
||||
|
||||
WARN(" imported from %s, allocating stub %p\n",
|
||||
debugstr_w(current_modref->ldr.FullDllName.Buffer),
|
||||
thunk_list->u1.Function );
|
||||
import_list++;
|
||||
thunk_list++;
|
||||
}
|
||||
|
@ -453,9 +532,10 @@ static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *d
|
|||
ordinal - exports->Base );
|
||||
if (!thunk_list->u1.Function)
|
||||
{
|
||||
ERR("No implementation for %s.%d imported from %s, setting to 0xdeadbeef\n",
|
||||
name, ordinal, debugstr_w(current_modref->ldr.FullDllName.Buffer) );
|
||||
thunk_list->u1.Function = (PDWORD)0xdeadbeef;
|
||||
thunk_list->u1.Function = allocate_stub( name, (const char *)ordinal );
|
||||
WARN("No implementation for %s.%d imported from %s, setting to %p\n",
|
||||
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 );
|
||||
}
|
||||
|
@ -467,9 +547,10 @@ static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *d
|
|||
pe_name->Name, pe_name->Hint );
|
||||
if (!thunk_list->u1.Function)
|
||||
{
|
||||
ERR("No implementation for %s.%s imported from %s, setting to 0xdeadbeef\n",
|
||||
name, pe_name->Name, debugstr_w(current_modref->ldr.FullDllName.Buffer) );
|
||||
thunk_list->u1.Function = (PDWORD)0xdeadbeef;
|
||||
thunk_list->u1.Function = allocate_stub( name, pe_name->Name );
|
||||
WARN("No implementation for %s.%s imported from %s, setting to %p\n",
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -640,9 +640,12 @@ static DWORD dbg_handle_exception(EXCEPTION_RECORD* rec, BOOL first_chance)
|
|||
memory_get_string(dbg_curr_process->handle,
|
||||
(void*)rec->ExceptionInformation[0], TRUE, FALSE,
|
||||
dll, sizeof(dll));
|
||||
if (HIWORD(rec->ExceptionInformation[1]))
|
||||
memory_get_string(dbg_curr_process->handle,
|
||||
(void*)rec->ExceptionInformation[1], TRUE, FALSE,
|
||||
name, sizeof(name));
|
||||
else
|
||||
sprintf( name, "%ld", rec->ExceptionInformation[1] );
|
||||
dbg_printf("unimplemented function %s.%s called", dll, name);
|
||||
}
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue