[Wine-patches] eterbug_1990 Ловля программных исключений
Anton Rudnev
=?iso-8859-1?q?mibori_=CE=C1_etersoft=2Eru?=
Сб Окт 11 14:08:35 MSD 2008
http://bugs.etersoft.ru/show_bug.cgi?id=1990#c11
----------- следующая часть -----------
From 0014db107ff300014f33f0ba0691e542a8d1abb9 Mon Sep 17 00:00:00 2001
From: Anton Rudnev <mibori на etersoft.ru>
Date: Fri, 19 Sep 2008 16:21:11 +0400
Subject: [PATCH] eterbug-1990
---
dlls/kernel32/except.c | 38 ++++-
dlls/ntdll/exception.c | 472 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 508 insertions(+), 2 deletions(-)
diff --git a/dlls/kernel32/except.c b/dlls/kernel32/except.c
index 21d3584..a753cd5 100644
--- a/dlls/kernel32/except.c
+++ b/dlls/kernel32/except.c
@@ -366,7 +366,7 @@ static int start_debugger_atomic(PEXCEPTION_POINTERS epointers)
/* ask for manual reset, so that once the debugger is started,
* every thread will know it */
NtCreateEvent( &hEvent, EVENT_ALL_ACCESS, &attr, TRUE, FALSE );
- if (InterlockedCompareExchangePointer( (PVOID)&hRunOnce, hEvent, 0 ) == 0)
+ if (InterlockedCompareExchangePointer( (PVOID)&hRunOnce, hEvent, 0 ) == 0)
{
/* ok, our event has been set... we're the winning thread */
BOOL ret = start_debugger( epointers, hRunOnce );
@@ -466,7 +466,41 @@ LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilter(
LPTOP_LEVEL_EXCEPTION_FILTER filter )
{
LPTOP_LEVEL_EXCEPTION_FILTER old = top_filter;
- top_filter = filter;
+
+
+
+ /*MIB: check WINESEHBLOCK */
+ if(!getenv("WINESEHBLOCK")){
+ top_filter = filter; // normal behaviour
+ } else {
+ char c;
+ printf(
+ "Call SetUnhandledExceptionFilter."
+ " Current filter - %x, new filter - %x.\n"
+ "[A]llow, [i]gnore(default)?:",
+ (DWORD)top_filter,
+ (DWORD)filter
+ );
+ while(1){
+ switch(c = fgetc(stdin)){
+ case 'A': c = 'a';
+ case 'a':
+ top_filter = filter;
+ printf("Allowed.\n");
+ break;
+ case '\n': c = 'i';
+ case 'I': c = 'i';
+ case 'i':
+ printf("Ignored.\n");
+ break;
+ default:
+ continue;
+ }
+ fgetc(stdin);
+ break;
+ }
+ }
+
return old;
}
diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c
index 8aa906e..e91079e 100644
--- a/dlls/ntdll/exception.c
+++ b/dlls/ntdll/exception.c
@@ -26,6 +26,8 @@
#include <errno.h>
#include <signal.h>
#include <stdarg.h>
+/* MIB: for WINESEHBLOCK */
+#include <stdio.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
@@ -296,6 +298,188 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
return STATUS_UNHANDLED_EXCEPTION;
}
+/*
+ table of filters, pointer to memory block:
+ item \n
+ item \n
+ ... ...
+ item \n
+ item \0
+*/
+
+/* filters table */
+char *filters = NULL;
+ //example "code=345 addr=434534\nparameters[0]=223f4\ncode=456";
+
+char /* command */
+ *sCode = "code",
+ *sFlag = "flags",
+ *sParameters = "parameters",
+ *sAddr = "addr";
+
+
+void show_filters(){
+ char *pos = filters;
+ if(!pos)
+ printf("NULL");
+
+ for(;*pos; pos++)
+ switch(*pos){
+ case '\n': printf("\\n"); break;
+ default: printf("%c", *pos);
+ }
+ printf("\\0\n");
+}
+
+
+
+#define MAXTOKEN 32
+
+char *check_arg(EXCEPTION_RECORD *rec, CONTEXT *context, char *pos){
+ char *cur;
+ char key[MAXTOKEN], value[MAXTOKEN], ind[MAXTOKEN];
+ int i;
+ DWORD v;
+
+ /* key */
+ cur = pos;
+ for(i = 0; i < MAXTOKEN; i++, cur++){
+ if(!*cur){
+ printf("Invalid `sym-name'.\n");
+ return NULL;
+ }
+ if((*cur == '=') || (*cur == '[')) break;
+ if(isalpha(*cur)) key[i] = *cur;
+ else{
+ printf("Invalid `sym-name'.\n");
+ return NULL;
+ }
+ }
+ if(i == MAXTOKEN){
+ printf("Out of range in `sym-name'.\n");
+ return NULL;
+ }
+ key[i] = (char)0;
+
+
+ /* ind */
+ if(*cur == '['){
+ cur++;
+ for(i = 0; i < 32; cur++, i++){
+ if(!*cur){
+ printf("Invalid `index'.\n");
+ return NULL;
+ }
+ if(*cur == ']') {
+ cur++;
+ break;
+ }
+ if(isdigit(*cur)) ind[i] = *cur;
+ else {
+ printf("Invalid `index'.\n");
+ return NULL;
+ }
+ }
+ if(i == MAXTOKEN){
+ printf("Out of range in `index'.\n");
+ return NULL;
+ }
+ ind[i] = 0;
+ }
+
+
+ /* value */
+ if(*cur = '='){
+ cur++;
+ for(i = 0; i < MAXTOKEN; i++, cur++){
+ if((!*cur) && (i == 0)){
+ printf("Invalid `value'.\n");
+ return NULL;
+ }
+ if((!*cur) || (*cur == '\n') || (*cur == ' ')) break;
+ if(isxdigit(*cur)) value[i] = *cur;
+ else {
+ printf("Invalid `value'.\n");
+ return NULL;
+ }
+ }
+ if(i == MAXTOKEN){
+ printf("Out of range in `value'.\n");
+ return NULL;
+ }
+ value[i] = 0;
+ }
+
+ v = strtoul(value, (char**)NULL, 16);
+
+ if(!strcmp(key, sCode))
+ if(rec->ExceptionCode == v) return cur;
+ else return NULL;
+
+ if(!strcmp(key, sFlag))
+ if(rec->ExceptionFlags == v) return cur;
+ else return NULL;
+
+
+ if(!strcmp(key, sParameters)){
+ int idx;
+ idx = atoi(ind);
+
+ if(idx < rec->NumberParameters)
+ if(v == (rec-> ExceptionInformation)[idx]) return cur;
+ else return NULL;
+ else return NULL;
+ }
+
+ if(!strcmp(key, sAddr))
+ if(((DWORD)(rec->ExceptionAddress)) == v) return cur;
+ else return NULL;
+
+ printf("Invalid `key' name.\n");
+
+ return NULL;
+}
+
+
+char *check_string(EXCEPTION_RECORD *rec, CONTEXT *context, char *pos){
+ char *cur;
+
+ for(cur = pos; (*cur != '\n') && (*cur != '\0');){
+ char *arg;
+
+ if(*cur == ' '){
+ cur++;
+ continue;
+ }
+ arg = check_arg(rec, context, cur);
+
+ if(!arg){
+ while(!((*cur == 0) || (*cur == '\n'))) cur++;
+ return cur;
+ } else
+ cur = arg;
+ }
+
+ return NULL;
+}
+
+BOOL auto_continue(EXCEPTION_RECORD *rec, CONTEXT *context){
+ char *pos;
+
+ if(!filters) return FALSE;
+
+ for(pos = filters; *pos;){
+ if(*pos == '\n'){
+ pos++;
+ continue;
+ }
+ pos = check_string(rec, context, pos);
+ if(!pos) return TRUE;
+ }
+
+ return FALSE;
+}
+
/*******************************************************************
* raise_exception
@@ -348,6 +532,294 @@ static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL f
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
return STATUS_SUCCESS;
+ { /* check $WINESEHBLOCK: */
+ char *sehBlock, command[2048];
+ int iteratorExceptionInformation;
+
+ if(sehBlock = getenv("WINESEHBLOCK"))
+ if(!strcmp(sehBlock, "all")){
+ //char c;
+ int loop;
+
+ //Exception information output
+ printf("Handled exception code=%x, flags=%x, addr=%p, parameters[%i]={",
+ rec->ExceptionCode,
+ rec->ExceptionFlags,
+ rec->ExceptionAddress,
+ rec->NumberParameters
+ );
+
+
+
+ for ( iteratorExceptionInformation = 0
+ ; iteratorExceptionInformation < rec->NumberParameters
+ ; iteratorExceptionInformation ++ )
+ printf("%x%s",
+ (rec->ExceptionInformation)[iteratorExceptionInformation],
+ (iteratorExceptionInformation != rec->NumberParameters - 1)?", ": ""
+ );
+ printf("}\n");
+
+ loop = !auto_continue(rec, context);
+ if(!loop) printf("Skip.\n");
+
+
+ while(loop){
+ int i;
+
+ printf("[d]ebugger, [c]ontinue, [e]xit, [h]elp:");
+ fgets(command, 256, stdin);
+ for(i = 0; i < 256; i++)
+ if(command[i] == '\n')
+ command[i] = '\x00';
+
+ if(!strcmp("h", command)){
+ printf(
+ "d Debugger\n"
+ "c Continue\n"
+ "e Exit\n"
+ "s List of skippers\n"
+ "s+ SkipperString Add new skipper\n"
+ "s- Number Delete skipper by number\n"
+ "s. Add new skipper for current handled exception\n"
+ "s= Add new skipper for current handled exception with parameters\n"
+ );
+ continue;
+ }
+
+
+ if(!strcmp("c", command)){
+ break;
+ }
+ if(!strcmp("e", command)){
+ exit(1);
+ }
+ /* Filters */
+ if(!strcmp("s", command)){
+ int i;
+ char *current, *begin;
+ if(!filters){
+ printf("Empty list.\n");
+ continue;
+ }
+ printf("Actual skippers:\n");
+ for(i = 0, current = begin = filters; *current; current++ ){
+ if(current == begin){
+ printf(" (%i)", i++);
+ }
+ if((*current) == '\n'){
+ begin = current;
+ begin++;
+ printf("\n");
+ continue;
+ }
+ printf("%c", *current);
+ }
+ MESSAGE("\n");
+ continue;
+ }
+
+ /* add new filter */
+ if((command[0] == 's') && (command[1] == '+')){
+ char *pos, *begin;
+ int l = 0;
+ pos = &(command[2]);
+
+
+ while(*pos == ' ')pos ++; /* skip spaces from begin */
+ begin = pos;
+
+ while(*pos) pos ++; /* to end */
+ for(; *pos == ' '; pos --)
+ *pos = (char)0; /* delete spaces from end */
+ l = strlen(begin);
+
+ if(filters){
+ int lf = strlen(filters);
+ char *p;
+
+ filters = (char *) realloc((void *)filters, lf + l + 2);
+
+ p = filters + lf;
+ *p = '\n';
+ strcpy(++p, begin);
+ } else {
+ filters = (char *) malloc(l + 1);
+ strcpy(filters, begin);
+ }
+ continue;
+ }
+
+ if((command[0] == 's') && (command[1] == '=')){
+ char f[2048];
+
+ sprintf(f, "code=%x flags=%x addr=%x",
+ rec->ExceptionCode,
+ rec->ExceptionFlags,
+ rec->ExceptionAddress
+ );
+
+ if(rec->NumberParameters){
+ int i;
+
+ for(i = 0; i < rec->NumberParameters; i++){
+ char arg[32];
+ sprintf(arg, " parameters[%i]=%x", i, (rec->ExceptionInformation)[i]);
+ strcat(f, arg);
+ }
+ }
+
+ if(filters){
+ int lf = strlen(filters);
+ char *p;
+
+ filters = (char*) realloc((void *)filters, lf + strlen(f) + 2);
+ p = filters + lf;
+ *p = '\n';
+ strcpy(++p, f);
+ } else {
+ filters = (char *) malloc (strlen(f) + 1);
+ strcpy(filters, f);
+ }
+ continue;
+ }
+
+
+
+ if((command[0] == 's') && (command[1] == '.')){
+ char f[128];
+
+ sprintf(f, "code=%x flags=%x addr=%x",
+ rec->ExceptionCode,
+ rec->ExceptionFlags,
+ rec->ExceptionAddress
+ );
+
+ if(filters){
+ int lf = strlen(filters);
+ char *p;
+
+ filters = (char*) realloc((void *)filters, lf + strlen(f) + 2);
+ p = filters + lf;
+ *p = '\n';
+ strcpy(++p, f);
+ } else {
+ filters = (char *) malloc (strlen(f) + 1);
+ strcpy(filters, f);
+ }
+ continue;
+ }
+
+
+
+ /* delete skipper from table */
+ if((command[0] == 's') && (command[1]=='-')){
+ int filtN = -1;
+
+ /* if filter list is empty */
+ if(!filters) continue;
+
+ /* parse argument */
+ { char *pos = command + 2, *begin;
+
+ while(*pos == ' ') pos ++; /* skip spaces from begin */
+ begin = pos;
+ while(*pos == ' ') pos ++; /* to end */
+ for(; *pos == ' '; pos --)
+ *pos = (char)0; /* delete spaces from end */
+
+ filtN = atoi(begin); /* convert string to number */
+ if(filtN < 0){
+ printf("Invalid argument.\n");
+ continue;
+ }
+ }
+ /* delete skipper */
+ { char *pos;
+ int count = 0;
+
+ for(pos = filters; *pos; pos ++)
+ if(*pos == '\n')
+ count ++;
+ count ++;
+
+ if (filtN >= count){
+ printf("Filter not found.\n");
+ continue;
+ }
+
+ if ((filtN == 0) && (count == 1)){ /* delete all memory block */
+ free((void *)filters);
+ filters = NULL;
+
+ continue;
+ } /* delete all memory block */
+
+ if ((filtN == 0) && (count != 1)){ /* delete first skipper */
+ char *new_filters, *begin;
+
+ pos = filters;
+ while(*pos != '\n') pos ++; /* to first `/n` */
+ begin = pos ++;
+ while(*pos)pos ++; /* to end */
+
+ new_filters = (char *) malloc((size_t)pos - (size_t)begin + 1);
+ memcpy((void *) new_filters, (void *) (begin + 1), (size_t)pos - (size_t)begin);
+ free(filters);
+ filters = new_filters;
+ continue;
+ } /* delete first skipper */
+
+ if(filtN == count - 1){ /* delete last skipper */
+ int i;
+ for(i = 0, pos = filters; i < filtN; pos ++)
+ if(*pos == '\n') i++;
+ /* *pos = '\n' */
+ pos--;
+ *pos = (char)0;
+ filters = (char *) realloc((void *)filters, (size_t)(pos + 1) - (size_t) filters);
+ continue;
+ } /* delete last skipper */
+
+ /* delete skipper by number */
+ { int i;
+ char *second, *new_filters;
+
+ for(i = 0, pos = filters; i < filtN; pos ++)
+ if(*pos == '\n') i++;
+ pos --;
+ /* *pos == '\n' */
+
+ second = pos + 1;
+ while(*second != '\n') second ++;
+ /* *second == '\n' */
+ new_filters = (char *) malloc((size_t)pos - (size_t)filters + strlen(second) + 1);
+ memcpy((void *)new_filters, (void *)filters, (size_t)pos - (size_t)filters + 1);
+ strcpy(new_filters + ((size_t)pos - (size_t)filters)+1, second + 1);
+
+ free(filters);
+ filters = new_filters;
+ continue;
+ } /*delete skipper by number */
+ } /* delete skipper */
+ }
+
+ if(!strcmp("d", command)){ /* call debugger */
+ EXCEPTION_POINTERS pointers;
+
+ pointers.ExceptionRecord = rec;
+ pointers.ContextRecord = context;
+
+ (*unhandled_exception_filter) (&pointers);
+
+ return STATUS_UNHANDLED_EXCEPTION;
+ } /* call debugger */
+
+ printf("Parse command error. Try again...\n");
+ }
+ }
+ } /* check $WINESEHBLOCK */
+
if ((status = call_stack_handlers( rec, context )) != STATUS_UNHANDLED_EXCEPTION)
return status;
}
--
1.5.6.GIT
Подробная информация о списке рассылки Wine-patches