From: Pierre Muller <muller@cerbere.u-strasbg.fr>
To: gdb-patches@sources.redhat.com
Subject: [RFC] handle signal passing to debuggee for win32 native target.
Date: Tue, 05 Feb 2002 04:59:00 -0000 [thread overview]
Message-ID: <4.2.0.58.20020205135825.01c36b00@ics.u-strasbg.fr> (raw)
[-- 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
next reply other threads:[~2002-02-05 12:59 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-02-05 4:59 Pierre Muller [this message]
2002-02-05 11:13 ` Christopher Faylor
2002-02-06 1:28 Pierre Muller
2002-02-06 9:57 ` Christopher Faylor
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4.2.0.58.20020205135825.01c36b00@ics.u-strasbg.fr \
--to=muller@cerbere.u-strasbg.fr \
--cc=gdb-patches@sources.redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox