Raise an exception when a stub entry point is called.

This commit is contained in:
Alexandre Julliard 2000-10-26 22:03:34 +00:00
parent 07d0c31c6c
commit 634824be58
6 changed files with 127 additions and 33 deletions

View File

@ -444,6 +444,16 @@ static BOOL DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOOL
return TRUE; return TRUE;
} }
break; 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: case EXCEPTION_VM86_INTx:
DEBUG_Printf(DBG_CHN_MESG, "interrupt %02lx in vm86 mode", DEBUG_Printf(DBG_CHN_MESG, "interrupt %02lx in vm86 mode",
rec->ExceptionInformation[0]); rec->ExceptionInformation[0]);

View File

@ -117,14 +117,12 @@ extern "C" {
# if defined(__GNUC__) && ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 7))) # if defined(__GNUC__) && ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 7)))
# define __stdcall __attribute__((__stdcall__)) # define __stdcall __attribute__((__stdcall__))
# define __cdecl __attribute__((__cdecl__)) # define __cdecl __attribute__((__cdecl__))
# define __RESTORE_ES __asm__ __volatile__("pushl %ds\n\tpopl %es")
# else # else
# error You need gcc >= 2.7 to build Wine on a 386 # error You need gcc >= 2.7 to build Wine on a 386
# endif /* __GNUC__ */ # endif /* __GNUC__ */
#else /* __i386__ */ #else /* __i386__ */
# define __stdcall # define __stdcall
# define __cdecl # define __cdecl
# define __RESTORE_ES
#endif /* __i386__ */ #endif /* __i386__ */
#define CALLBACK __stdcall #define CALLBACK __stdcall

View File

@ -168,6 +168,8 @@ static inline EXCEPTION_FRAME * WINE_UNUSED __wine_pop_frame( EXCEPTION_FRAME *f
/* Wine-specific exceptions codes */ /* Wine-specific exceptions codes */
#define EXCEPTION_WINE_STUB 0x80000100 /* stub entry point called */
/* unhandled return status from vm86 mode */ /* unhandled return status from vm86 mode */
#define EXCEPTION_VM86_INTx 0x80000101 #define EXCEPTION_VM86_INTx 0x80000101
#define EXCEPTION_VM86_STI 0x80000102 #define EXCEPTION_VM86_STI 0x80000102

View File

@ -356,21 +356,3 @@ void BUILTIN32_RegisterDLL( const IMAGE_NT_HEADERS *header, const char *filename
builtin_dlls[nb_dlls].filename = filename; builtin_dlls[nb_dlls].filename = filename;
nb_dlls++; 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);
}

View File

@ -12,6 +12,7 @@
#include <unistd.h> #include <unistd.h>
#include "winbase.h" #include "winbase.h"
#include "wine/exception.h"
#include "build.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); fprintf( outfile, "%s", odp->u.func.link_name);
break; break;
case TYPE_STUB: 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; break;
case TYPE_REGISTER: case TYPE_REGISTER:
fprintf( outfile, "__regs_%d", i ); 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", fprintf( outfile, "/* File generated automatically from %s; do not edit! */\n\n",
input_file_name ); input_file_name );
fprintf( outfile, "extern void BUILTIN32_Unimplemented( const char *dllname, const char *funcname );\n\n" );
/* Reserve some space for the PE header */ /* 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, " \".align %ld\\n\"\n", page_size );
fprintf( outfile, " \"pe_header:\\t.fill %ld,1,0\\n\\t\");\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 */ /* Output the DLL functions prototypes */
@ -330,13 +362,12 @@ void BuildSpec32File( FILE *outfile )
case TYPE_STUB: case TYPE_STUB:
if (odp->name[0]) if (odp->name[0])
fprintf( outfile, fprintf( outfile,
"static void __stub_%d() { BUILTIN32_Unimplemented(dllname,\"%s\"); }\n", "static void __stub_%s() { __wine_unimplemented(\"%s\"); }\n",
odp->ordinal, odp->name ); odp->name, odp->name );
else else
fprintf( outfile, fprintf( outfile,
"static void __stub_%d() { BUILTIN32_Unimplemented(dllname,\"%d\"); }\n", "static void __stub_%d() { __wine_unimplemented(\"%d\"); }\n",
odp->ordinal, odp->ordinal ); odp->ordinal, odp->ordinal );
break; break;
default: default:
fprintf(stderr,"build: function type %d not available for Win32\n", fprintf(stderr,"build: function type %d not available for Win32\n",

View File

@ -27,7 +27,7 @@
#include "winerror.h" #include "winerror.h"
#include "ntddk.h" #include "ntddk.h"
#include "wine/exception.h" #include "wine/exception.h"
#include "ldt.h" #include "selectors.h"
#include "callback.h" #include "callback.h"
#include "process.h" #include "process.h"
#include "thread.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) * UnhandledExceptionFilter (KERNEL32.537)
*/ */
@ -133,11 +208,7 @@ DWORD WINAPI UnhandledExceptionFilter(PEXCEPTION_POINTERS epointers)
} }
if (!bAuto && Callout.MessageBoxA) { if (!bAuto && Callout.MessageBoxA) {
sprintf( buffer, "Unhandled exception 0x%08lx at address 0x%04lx:0x%08lx.\n" format_exception_msg( epointers, buffer );
"Do you wish to debug it ?",
epointers->ExceptionRecord->ExceptionCode,
epointers->ContextRecord->SegCs,
(DWORD)epointers->ExceptionRecord->ExceptionAddress );
if (Callout.MessageBoxA( 0, buffer, "Error", MB_YESNO | MB_ICONHAND ) == IDNO) { if (Callout.MessageBoxA( 0, buffer, "Error", MB_YESNO | MB_ICONHAND ) == IDNO) {
TRACE("Killing process\n"); TRACE("Killing process\n");
return EXCEPTION_EXECUTE_HANDLER; return EXCEPTION_EXECUTE_HANDLER;