Raise an exception when a stub entry point is called.
This commit is contained in:
parent
07d0c31c6c
commit
634824be58
|
@ -444,6 +444,16 @@ static BOOL DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOOL
|
|||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case EXCEPTION_WINE_STUB:
|
||||
{
|
||||
char dll[32], name[64];
|
||||
DEBUG_ProcessGetString( dll, sizeof(dll), DEBUG_CurrThread->process->handle,
|
||||
(char *)rec->ExceptionInformation[0] );
|
||||
DEBUG_ProcessGetString( name, sizeof(name), DEBUG_CurrThread->process->handle,
|
||||
(char *)rec->ExceptionInformation[1] );
|
||||
DEBUG_Printf(DBG_CHN_MESG, "unimplemented function %s.%s called", dll, name );
|
||||
}
|
||||
break;
|
||||
case EXCEPTION_VM86_INTx:
|
||||
DEBUG_Printf(DBG_CHN_MESG, "interrupt %02lx in vm86 mode",
|
||||
rec->ExceptionInformation[0]);
|
||||
|
|
|
@ -117,14 +117,12 @@ extern "C" {
|
|||
# if defined(__GNUC__) && ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 7)))
|
||||
# define __stdcall __attribute__((__stdcall__))
|
||||
# define __cdecl __attribute__((__cdecl__))
|
||||
# define __RESTORE_ES __asm__ __volatile__("pushl %ds\n\tpopl %es")
|
||||
# else
|
||||
# error You need gcc >= 2.7 to build Wine on a 386
|
||||
# endif /* __GNUC__ */
|
||||
#else /* __i386__ */
|
||||
# define __stdcall
|
||||
# define __cdecl
|
||||
# define __RESTORE_ES
|
||||
#endif /* __i386__ */
|
||||
|
||||
#define CALLBACK __stdcall
|
||||
|
|
|
@ -168,6 +168,8 @@ static inline EXCEPTION_FRAME * WINE_UNUSED __wine_pop_frame( EXCEPTION_FRAME *f
|
|||
|
||||
/* Wine-specific exceptions codes */
|
||||
|
||||
#define EXCEPTION_WINE_STUB 0x80000100 /* stub entry point called */
|
||||
|
||||
/* unhandled return status from vm86 mode */
|
||||
#define EXCEPTION_VM86_INTx 0x80000101
|
||||
#define EXCEPTION_VM86_STI 0x80000102
|
||||
|
|
|
@ -356,21 +356,3 @@ void BUILTIN32_RegisterDLL( const IMAGE_NT_HEADERS *header, const char *filename
|
|||
builtin_dlls[nb_dlls].filename = filename;
|
||||
nb_dlls++;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* BUILTIN32_Unimplemented
|
||||
*
|
||||
* This function is called for unimplemented 32-bit entry points (declared
|
||||
* as 'stub' in the spec file).
|
||||
*/
|
||||
void BUILTIN32_Unimplemented( const char *dllname, const char *funcname )
|
||||
{
|
||||
__RESTORE_ES; /* Just in case */
|
||||
|
||||
MESSAGE( "FATAL: No handler for Win32 routine %s.%s", dllname, funcname );
|
||||
#ifdef __GNUC__
|
||||
MESSAGE( " (called from %p)", __builtin_return_address(1) );
|
||||
#endif
|
||||
MESSAGE( "\n" );
|
||||
ExitProcess(1);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "winbase.h"
|
||||
#include "wine/exception.h"
|
||||
#include "build.h"
|
||||
|
||||
|
||||
|
@ -155,7 +156,8 @@ static void output_exports( FILE *outfile, int nr_exports, int nr_names, int fwd
|
|||
fprintf( outfile, "%s", odp->u.func.link_name);
|
||||
break;
|
||||
case TYPE_STUB:
|
||||
fprintf( outfile, "__stub_%d", i );
|
||||
if (odp->name[0]) fprintf( outfile, "__stub_%s", odp->name );
|
||||
else fprintf( outfile, "__stub_%d", i );
|
||||
break;
|
||||
case TYPE_REGISTER:
|
||||
fprintf( outfile, "__regs_%d", i );
|
||||
|
@ -294,7 +296,6 @@ void BuildSpec32File( FILE *outfile )
|
|||
|
||||
fprintf( outfile, "/* File generated automatically from %s; do not edit! */\n\n",
|
||||
input_file_name );
|
||||
fprintf( outfile, "extern void BUILTIN32_Unimplemented( const char *dllname, const char *funcname );\n\n" );
|
||||
|
||||
/* Reserve some space for the PE header */
|
||||
|
||||
|
@ -303,7 +304,38 @@ void BuildSpec32File( FILE *outfile )
|
|||
fprintf( outfile, " \".align %ld\\n\"\n", page_size );
|
||||
fprintf( outfile, " \"pe_header:\\t.fill %ld,1,0\\n\\t\");\n", page_size );
|
||||
|
||||
fprintf( outfile, "static const char dllname[] = \"%s\";\n", DLLName );
|
||||
fprintf( outfile, "static const char dllname[] = \"%s\";\n\n", DLLName );
|
||||
|
||||
/* Output the stub function if necessary */
|
||||
|
||||
for (i = 0, odp = EntryPoints; i < nb_entry_points; i++, odp++)
|
||||
{
|
||||
if (odp->type != TYPE_STUB) continue;
|
||||
fprintf( outfile, "#ifdef __GNUC__\n" );
|
||||
fprintf( outfile, "static void __wine_unimplemented( const char *func ) __attribute__((noreturn));\n" );
|
||||
fprintf( outfile, "#endif\n" );
|
||||
fprintf( outfile, "static void __wine_unimplemented( const char *func )\n{\n" );
|
||||
fprintf( outfile, " struct exc_record {\n" );
|
||||
fprintf( outfile, " unsigned int code, flags;\n" );
|
||||
fprintf( outfile, " void *rec, *addr;\n" );
|
||||
fprintf( outfile, " unsigned int params;\n" );
|
||||
fprintf( outfile, " const void *info[15];\n" );
|
||||
fprintf( outfile, " } rec;\n" );
|
||||
fprintf( outfile, " extern void RtlRaiseException( struct exc_record * );\n\n" );
|
||||
fprintf( outfile, " rec.code = 0x%08x;\n", EXCEPTION_WINE_STUB );
|
||||
fprintf( outfile, " rec.flags = %d;\n", EH_NONCONTINUABLE );
|
||||
fprintf( outfile, " rec.rec = 0;\n" );
|
||||
fprintf( outfile, " rec.params = 2;\n" );
|
||||
fprintf( outfile, " rec.info[0] = dllname;\n" );
|
||||
fprintf( outfile, " rec.info[1] = func;\n" );
|
||||
fprintf( outfile, "#ifdef __GNUC__\n" );
|
||||
fprintf( outfile, " rec.addr = __builtin_return_address(1);\n" );
|
||||
fprintf( outfile, "#else\n" );
|
||||
fprintf( outfile, " rec.addr = 0;\n" );
|
||||
fprintf( outfile, "#endif\n" );
|
||||
fprintf( outfile, " for (;;) RtlRaiseException( &rec );\n}\n\n" );
|
||||
break;
|
||||
}
|
||||
|
||||
/* Output the DLL functions prototypes */
|
||||
|
||||
|
@ -330,13 +362,12 @@ void BuildSpec32File( FILE *outfile )
|
|||
case TYPE_STUB:
|
||||
if (odp->name[0])
|
||||
fprintf( outfile,
|
||||
"static void __stub_%d() { BUILTIN32_Unimplemented(dllname,\"%s\"); }\n",
|
||||
odp->ordinal, odp->name );
|
||||
"static void __stub_%s() { __wine_unimplemented(\"%s\"); }\n",
|
||||
odp->name, odp->name );
|
||||
else
|
||||
fprintf( outfile,
|
||||
"static void __stub_%d() { BUILTIN32_Unimplemented(dllname,\"%d\"); }\n",
|
||||
"static void __stub_%d() { __wine_unimplemented(\"%d\"); }\n",
|
||||
odp->ordinal, odp->ordinal );
|
||||
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"build: function type %d not available for Win32\n",
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "winerror.h"
|
||||
#include "ntddk.h"
|
||||
#include "wine/exception.h"
|
||||
#include "ldt.h"
|
||||
#include "selectors.h"
|
||||
#include "callback.h"
|
||||
#include "process.h"
|
||||
#include "thread.h"
|
||||
|
@ -63,6 +63,81 @@ void WINAPI RaiseException( DWORD code, DWORD flags, DWORD nbargs, const LPDWORD
|
|||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* format_exception_msg
|
||||
*/
|
||||
static void format_exception_msg( const EXCEPTION_POINTERS *ptr, char *buffer )
|
||||
{
|
||||
const EXCEPTION_RECORD *rec = ptr->ExceptionRecord;
|
||||
|
||||
switch(rec->ExceptionCode)
|
||||
{
|
||||
case EXCEPTION_INT_DIVIDE_BY_ZERO:
|
||||
sprintf( buffer, "Unhandled division by zero" );
|
||||
break;
|
||||
case EXCEPTION_INT_OVERFLOW:
|
||||
sprintf( buffer, "Unhandled overflow" );
|
||||
break;
|
||||
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
|
||||
sprintf( buffer, "Unhandled array bounds" );
|
||||
break;
|
||||
case EXCEPTION_ILLEGAL_INSTRUCTION:
|
||||
sprintf( buffer, "Unhandled illegal instruction" );
|
||||
break;
|
||||
case EXCEPTION_STACK_OVERFLOW:
|
||||
sprintf( buffer, "Unhandled stack overflow" );
|
||||
break;
|
||||
case EXCEPTION_PRIV_INSTRUCTION:
|
||||
sprintf( buffer, "Unhandled priviledged instruction" );
|
||||
break;
|
||||
case EXCEPTION_ACCESS_VIOLATION:
|
||||
if (rec->NumberParameters == 2)
|
||||
sprintf( buffer, "Unhandled page fault on %s access to 0x%08lx",
|
||||
rec->ExceptionInformation[0] ? "write" : "read",
|
||||
rec->ExceptionInformation[1]);
|
||||
else
|
||||
sprintf( buffer, "Unhandled page fault");
|
||||
break;
|
||||
case EXCEPTION_DATATYPE_MISALIGNMENT:
|
||||
sprintf( buffer, "Unhandled alignment" );
|
||||
break;
|
||||
case CONTROL_C_EXIT:
|
||||
sprintf( buffer, "Unhandled ^C");
|
||||
break;
|
||||
case EXCEPTION_CRITICAL_SECTION_WAIT:
|
||||
sprintf( buffer, "Critical section %08lx wait failed",
|
||||
rec->ExceptionInformation[0]);
|
||||
break;
|
||||
case EXCEPTION_WINE_STUB:
|
||||
sprintf( buffer, "Unimplemented function %s.%s called",
|
||||
(char *)rec->ExceptionInformation[0], (char *)rec->ExceptionInformation[1] );
|
||||
break;
|
||||
case EXCEPTION_VM86_INTx:
|
||||
sprintf( buffer, "Unhandled interrupt %02lx in vm86 mode",
|
||||
rec->ExceptionInformation[0]);
|
||||
break;
|
||||
case EXCEPTION_VM86_STI:
|
||||
sprintf( buffer, "Unhandled sti in vm86 mode");
|
||||
break;
|
||||
case EXCEPTION_VM86_PICRETURN:
|
||||
sprintf( buffer, "Unhandled PIC return in vm86 mode");
|
||||
break;
|
||||
default:
|
||||
sprintf( buffer, "Unhandled exception 0x%08lx", rec->ExceptionCode);
|
||||
break;
|
||||
}
|
||||
#ifdef __i386__
|
||||
if (ptr->ContextRecord->SegCs != __get_cs())
|
||||
sprintf( buffer+strlen(buffer), " at address 0x%04lx:0x%08lx.\n",
|
||||
ptr->ContextRecord->SegCs, (DWORD)ptr->ExceptionRecord->ExceptionAddress );
|
||||
else
|
||||
#endif
|
||||
sprintf( buffer+strlen(buffer), " at address 0x%08lx.\n",
|
||||
(DWORD)ptr->ExceptionRecord->ExceptionAddress );
|
||||
strcat( buffer, "Do you wish to debug it ?" );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* UnhandledExceptionFilter (KERNEL32.537)
|
||||
*/
|
||||
|
@ -133,11 +208,7 @@ DWORD WINAPI UnhandledExceptionFilter(PEXCEPTION_POINTERS epointers)
|
|||
}
|
||||
|
||||
if (!bAuto && Callout.MessageBoxA) {
|
||||
sprintf( buffer, "Unhandled exception 0x%08lx at address 0x%04lx:0x%08lx.\n"
|
||||
"Do you wish to debug it ?",
|
||||
epointers->ExceptionRecord->ExceptionCode,
|
||||
epointers->ContextRecord->SegCs,
|
||||
(DWORD)epointers->ExceptionRecord->ExceptionAddress );
|
||||
format_exception_msg( epointers, buffer );
|
||||
if (Callout.MessageBoxA( 0, buffer, "Error", MB_YESNO | MB_ICONHAND ) == IDNO) {
|
||||
TRACE("Killing process\n");
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
|
|
Loading…
Reference in New Issue