From 634824be58d71a2ccba534fe49c151dd24ca34d2 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 26 Oct 2000 22:03:34 +0000 Subject: [PATCH] Raise an exception when a stub entry point is called. --- debugger/winedbg.c | 10 +++++ include/windef.h | 2 - include/wine/exception.h | 2 + relay32/builtin32.c | 18 --------- tools/winebuild/spec32.c | 45 ++++++++++++++++++---- win32/except.c | 83 +++++++++++++++++++++++++++++++++++++--- 6 files changed, 127 insertions(+), 33 deletions(-) diff --git a/debugger/winedbg.c b/debugger/winedbg.c index 45dde5c1272..ec649cf405c 100644 --- a/debugger/winedbg.c +++ b/debugger/winedbg.c @@ -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]); diff --git a/include/windef.h b/include/windef.h index 192eff93e9d..f1e851718a8 100644 --- a/include/windef.h +++ b/include/windef.h @@ -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 diff --git a/include/wine/exception.h b/include/wine/exception.h index c8d6bdd4afe..41d07576e40 100644 --- a/include/wine/exception.h +++ b/include/wine/exception.h @@ -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 diff --git a/relay32/builtin32.c b/relay32/builtin32.c index 1ff7a985880..cdb288c098f 100644 --- a/relay32/builtin32.c +++ b/relay32/builtin32.c @@ -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); -} diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c index a8b02d26616..79c75a00657 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c @@ -12,6 +12,7 @@ #include #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", diff --git a/win32/except.c b/win32/except.c index 6ff1219f8cb..ecfe9331f60 100644 --- a/win32/except.c +++ b/win32/except.c @@ -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;