* Re: [RFC] handle signal passing to debuggee for win32 native target.
@ 2002-02-06 1:28 Pierre Muller
2002-02-06 9:57 ` Christopher Faylor
0 siblings, 1 reply; 4+ messages in thread
From: Pierre Muller @ 2002-02-06 1:28 UTC (permalink / raw)
To: gdb-patches
At 20:13 05/02/2002 , vous avez écrit:
>On Tue, Feb 05, 2002 at 01:58:53PM +0100, Pierre Muller wrote:
> >But I don't really know if Cygwin library uses SetUnhandledExceptionFilter
> >(I suspect it does as my patch does not work as intended...).
>
>It does, in effect, yes.
I didn't find out where this is used...
>Please check this in, Pierre. It looks good.
Done, thanks.
(I first sent this to Christopher only...
sorry for this error).
Pierre Muller
Institut Charles Sadron
6,rue Boussingault
F 67083 STRASBOURG CEDEX (France)
mailto:muller@ics.u-strasbg.fr
Phone : (33)-3-88-41-40-07 Fax : (33)-3-88-41-40-99
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC] handle signal passing to debuggee for win32 native target.
2002-02-06 1:28 [RFC] handle signal passing to debuggee for win32 native target Pierre Muller
@ 2002-02-06 9:57 ` Christopher Faylor
0 siblings, 0 replies; 4+ messages in thread
From: Christopher Faylor @ 2002-02-06 9:57 UTC (permalink / raw)
To: gdb-patches
On Wed, Feb 06, 2002 at 10:28:32AM +0100, Pierre Muller wrote:
>At 20:13 05/02/2002 , vous avez ?crit:
>>On Tue, Feb 05, 2002 at 01:58:53PM +0100, Pierre Muller wrote:
>> >But I don't really know if Cygwin library uses SetUnhandledExceptionFilter
>> >(I suspect it does as my patch does not work as intended...).
>>
>>It does, in effect, yes.
>
>I didn't find out where this is used...
Do you really want to understand cygwin internals? :-)
It's handled, in a raw fashion, by 'init_exception_handler' in the file
'exceptions.cc' in the cygwin source.
cgf
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC] handle signal passing to debuggee for win32 native target.
2002-02-05 4:59 Pierre Muller
@ 2002-02-05 11:13 ` Christopher Faylor
0 siblings, 0 replies; 4+ messages in thread
From: Christopher Faylor @ 2002-02-05 11:13 UTC (permalink / raw)
To: gdb-patches
On Tue, Feb 05, 2002 at 01:58:53PM +0100, Pierre Muller wrote:
>But I don't really know if Cygwin library uses SetUnhandledExceptionFilter
>(I suspect it does as my patch does not work as intended...).
It does, in effect, yes.
Please check this in, Pierre. It looks good.
cgf
^ permalink raw reply [flat|nested] 4+ messages in thread
* [RFC] handle signal passing to debuggee for win32 native target.
@ 2002-02-05 4:59 Pierre Muller
2002-02-05 11:13 ` Christopher Faylor
0 siblings, 1 reply; 4+ messages in thread
From: Pierre Muller @ 2002-02-05 4:59 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 2821 bytes --]
The following patch handles (to the best of what
I discovered can be done) the passing of signals
to the inferior for native win32 targets.
Known limitation:
--
The main problem is that this will only partially work because of a known bug
in the win32 API:
Extracted from
http://www.microsoft.com/msj/defaultframe.asp?page=/msj/0898/bugslayer0898.htm&nav=/msj/0898/newnav.htm
There are a couple of issues to remember when using SetUnhandledExceptionFilter.
The first is that any exception filter that you set cannot be debugged. This is a known bug.
Knowledge Base article Q173652 says that under a debugger the process wide filter is not called.
This can be a bit of a pain, but in a C++ program you can just use your function in a regular SEH exception
filter to debug it. If you look at the CH_TEST.CPP test program, which is part of this month's source code
(Aug98Bugslayer.exe ), this is exactly what I did to debug it.
An alternative is to use a kernel debugger like WinDBG to get around this limitation.
But I don't really know if Cygwin library uses SetUnhandledExceptionFilter
(I suspect it does as my patch does not work as intended...).
The other problem seems to be that changes to the ExceptionRecord structure in the current_event
do not seem to be reflected when the exception is passed to the debuggee.
(See the disabled code in the patch for child_resume). Passing another signal value
then the one generated does not seem possible.
Simple test program to check the changes:
>>>>test.c begin
int x;
int * y;
int
main ()
{
(int) y = 0xfffffff0;
x = 56;
*y = x;
return 0;
}
>>>>test.c end
gcc -g -o test.exe test.c
Use the newly build gdb (with the patch below applied)
./gdb ./test
(gdb)run
(gdb)cont
> You should get a stackdump due to an SIGSEGV signal.
(gdb)run
(gdb)handle SIGSEGV nopass
(gdb)cont
> You should get a second SIGSEGV report
but if you check the assembler instruction
(gdb) x /i $eip
it should give you something like
(gdb) mov %edx,(%eax)
with $eax containing 0xfffffff0
if you change the value of $eax to &x
you should be able to finish the program without any error.
2002-02-05 Pierre Muller <muller@ics.u-strasbg.fr>
win32-nat.c (last_sig): Changed type of variable to target_signal,
to allow easier handling of pass state.
(DEBUG_EXCEPTION_SIMPLE): New macro, used in handle_exception,
that gives exception name and address.
(handle_exception): Use DEBUG_EXCEPTION_SIMPLE macro
and set last_sig value to ourstatus->value.sig. Some missing
exceptions added.
(child_continue): Correctly report continue_status.
(get_child_debug_event,do_initial_child_stuff): Set last_sig to
TARGET_SIGNAL_0 (new default value).
(child_resume): consider sig argument passed to decide if
the exception should be passed to debuggee or not.
[-- Attachment #2: win32-nat.diffs --]
[-- Type: text/plain, Size: 8756 bytes --]
Index: win32-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/win32-nat.c,v
retrieving revision 1.45
diff -u -p -b -r1.45 win32-nat.c
--- win32-nat.c 2002/02/05 08:04:22 1.45
+++ win32-nat.c 2002/02/05 12:55:12
@@ -98,8 +98,9 @@ static void child_stop (void);
static int win32_child_thread_alive (ptid_t);
void child_kill_inferior (void);
-static int last_sig = 0; /* Set if a signal was received from the
- debugged process */
+static enum target_signal last_sig = TARGET_SIGNAL_0;
+/* Set if a signal was received from the debugged process */
+
/* Thread information structure used to track information that is
not available in gdb's thread structure. */
typedef struct thread_info_struct
@@ -218,6 +219,7 @@ static const struct xlate_exception
{EXCEPTION_BREAKPOINT, TARGET_SIGNAL_TRAP},
{DBG_CONTROL_C, TARGET_SIGNAL_INT},
{EXCEPTION_SINGLE_STEP, TARGET_SIGNAL_TRAP},
+ {STATUS_FLOAT_DIVIDE_BY_ZERO, TARGET_SIGNAL_FPE},
{-1, -1}};
static void
@@ -823,6 +825,10 @@ handle_output_debug_string (struct targe
return gotasig;
}
+#define DEBUG_EXCEPTION_SIMPLE(x) if (debug_exceptions) \
+ printf ("gdb: Target exception %s at 0x%08lx\n", x, \
+ (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress)
+
static int
handle_exception (struct target_waitstatus *ourstatus)
{
@@ -837,52 +843,80 @@ handle_exception (struct target_waitstat
switch (code)
{
case EXCEPTION_ACCESS_VIOLATION:
- DEBUG_EXCEPT (("gdb: Target exception ACCESS_VIOLATION at 0x%08lx\n",
- (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
+ DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION");
+ ourstatus->value.sig = TARGET_SIGNAL_SEGV;
+ break;
+ case STATUS_STACK_OVERFLOW:
+ DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW");
ourstatus->value.sig = TARGET_SIGNAL_SEGV;
- last_sig = SIGSEGV;
+ break;
+ case STATUS_FLOAT_DENORMAL_OPERAND:
+ DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND");
+ ourstatus->value.sig = TARGET_SIGNAL_FPE;
+ break;
+ case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
+ DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
+ ourstatus->value.sig = TARGET_SIGNAL_FPE;
+ break;
+ case STATUS_FLOAT_INEXACT_RESULT:
+ DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INEXACT_RESULT");
+ ourstatus->value.sig = TARGET_SIGNAL_FPE;
+ break;
+ case STATUS_FLOAT_INVALID_OPERATION:
+ DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INVALID_OPERATION");
+ ourstatus->value.sig = TARGET_SIGNAL_FPE;
+ break;
+ case STATUS_FLOAT_OVERFLOW:
+ DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_OVERFLOW");
+ ourstatus->value.sig = TARGET_SIGNAL_FPE;
+ break;
+ case STATUS_FLOAT_STACK_CHECK:
+ DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_STACK_CHECK");
+ ourstatus->value.sig = TARGET_SIGNAL_FPE;
break;
case STATUS_FLOAT_UNDERFLOW:
+ DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_UNDERFLOW");
+ ourstatus->value.sig = TARGET_SIGNAL_FPE;
+ break;
case STATUS_FLOAT_DIVIDE_BY_ZERO:
- case STATUS_FLOAT_OVERFLOW:
+ DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DIVIDE_BY_ZERO");
+ ourstatus->value.sig = TARGET_SIGNAL_FPE;
+ break;
case STATUS_INTEGER_DIVIDE_BY_ZERO:
- DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08lx\n",
- (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
+ DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_DIVIDE_BY_ZERO");
ourstatus->value.sig = TARGET_SIGNAL_FPE;
- last_sig = SIGFPE;
break;
- case STATUS_STACK_OVERFLOW:
- DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08lx\n",
- (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
- ourstatus->value.sig = TARGET_SIGNAL_SEGV;
+ case STATUS_INTEGER_OVERFLOW:
+ DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_OVERFLOW");
+ ourstatus->value.sig = TARGET_SIGNAL_FPE;
break;
case EXCEPTION_BREAKPOINT:
- DEBUG_EXCEPT (("gdb: Target exception BREAKPOINT at 0x%08lx\n",
- (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
+ DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
ourstatus->value.sig = TARGET_SIGNAL_TRAP;
break;
case DBG_CONTROL_C:
- DEBUG_EXCEPT (("gdb: Target exception CONTROL_C at 0x%08lx\n",
- (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
+ DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C");
ourstatus->value.sig = TARGET_SIGNAL_INT;
- last_sig = SIGINT; /* FIXME - should check pass state */
break;
case DBG_CONTROL_BREAK:
- DEBUG_EXCEPT (("gdb: Target exception CONTROL_BREAK at 0x%08lx\n",
- (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
+ DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_BREAK");
ourstatus->value.sig = TARGET_SIGNAL_INT;
- last_sig = SIGINT; /* FIXME - should check pass state */
break;
case EXCEPTION_SINGLE_STEP:
- DEBUG_EXCEPT (("gdb: Target exception SINGLE_STEP at 0x%08lx\n",
- (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
+ DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP");
ourstatus->value.sig = TARGET_SIGNAL_TRAP;
break;
case EXCEPTION_ILLEGAL_INSTRUCTION:
- DEBUG_EXCEPT (("gdb: Target exception SINGLE_ILL at 0x%08lx\n",
- (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
+ DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ILLEGAL_INSTRUCTION");
+ ourstatus->value.sig = TARGET_SIGNAL_ILL;
+ break;
+ case EXCEPTION_PRIV_INSTRUCTION:
+ DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_PRIV_INSTRUCTION");
+ ourstatus->value.sig = TARGET_SIGNAL_ILL;
+ break;
+ case EXCEPTION_NONCONTINUABLE_EXCEPTION:
+ DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_NONCONTINUABLE_EXCEPTION");
ourstatus->value.sig = TARGET_SIGNAL_ILL;
- last_sig = SIGILL;
break;
default:
if (current_event.u.Exception.dwFirstChance)
@@ -894,6 +928,7 @@ handle_exception (struct target_waitstat
break;
}
exception_count++;
+ last_sig = ourstatus->value.sig;
return 1;
}
@@ -906,8 +941,10 @@ child_continue (DWORD continue_status, i
thread_info *th;
BOOL res;
- DEBUG_EVENTS (("ContinueDebugEvent (cpid=%ld, ctid=%ld, DBG_CONTINUE);\n",
- current_event.dwProcessId, current_event.dwThreadId));
+ DEBUG_EVENTS (("ContinueDebugEvent (cpid=%ld, ctid=%ld, %s);\n",
+ current_event.dwProcessId, current_event.dwThreadId,
+ continue_status == DBG_CONTINUE ?
+ "DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED"));
res = ContinueDebugEvent (current_event.dwProcessId,
current_event.dwThreadId,
continue_status);
@@ -952,7 +989,7 @@ get_child_debug_event (int pid, struct t
static thread_info dummy_thread_info;
int retval = 0;
- last_sig = 0;
+ last_sig = TARGET_SIGNAL_0;
if (!(debug_event = WaitForDebugEvent (¤t_event, 1000)))
goto out;
@@ -1118,7 +1155,7 @@ do_initial_child_stuff (DWORD pid)
extern int stop_after_trap;
int i;
- last_sig = 0;
+ last_sig = TARGET_SIGNAL_0;
event_count = 0;
exception_count = 0;
debug_registers_changed = 0;
@@ -1470,11 +1507,45 @@ void
child_resume (ptid_t ptid, int step, enum target_signal sig)
{
thread_info *th;
- DWORD continue_status = last_sig > 0 && last_sig < NSIG ?
- DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE;
+ DWORD continue_status = DBG_CONTINUE;
+
int pid = PIDGET (ptid);
+
+ if (sig != TARGET_SIGNAL_0)
+ {
+ if (current_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
+ {
+ DEBUG_EXCEPT(("Cannot continue with signal %d here.\n",sig));
+ }
+ else if (sig == last_sig)
+ continue_status = DBG_EXCEPTION_NOT_HANDLED;
+ else
+#if 0
+/* This code does not seem to work, because
+ the kernel does probably not consider changes in the ExceptionRecord
+ structure when passing the exception to the inferior.
+ Note that this seems possible in the exception handler itself. */
+ {
+ int i;
+ for (i = 0; xlate[i].them != -1; i++)
+ if (xlate[i].us == sig)
+ {
+ current_event.u.Exception.ExceptionRecord.ExceptionCode =
+ xlate[i].them;
+ continue_status = DBG_EXCEPTION_NOT_HANDLED;
+ break;
+ }
+ if (continue_status == DBG_CONTINUE)
+ {
+ DEBUG_EXCEPT(("Cannot continue with signal %d.\n",sig));
+ }
+ }
+#endif
+ DEBUG_EXCEPT(("Can only continue with recieved signal %d.\n",
+ last_sig));
+ }
- last_sig = 0;
+ last_sig = TARGET_SIGNAL_0;
DEBUG_EXEC (("gdb: child_resume (pid=%d, step=%d, sig=%d);\n",
pid, step, sig));
[-- Attachment #3: Type: text/plain, Size: 176 bytes --]
Pierre Muller
Institut Charles Sadron
6,rue Boussingault
F 67083 STRASBOURG CEDEX (France)
mailto:muller@ics.u-strasbg.fr
Phone : (33)-3-88-41-40-07 Fax : (33)-3-88-41-40-99
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2002-02-06 17:57 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-02-06 1:28 [RFC] handle signal passing to debuggee for win32 native target Pierre Muller
2002-02-06 9:57 ` Christopher Faylor
-- strict thread matches above, loose matches on Subject: below --
2002-02-05 4:59 Pierre Muller
2002-02-05 11:13 ` Christopher Faylor
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox