Re: [Bug win32/14529] Make gdb capable of JIT-debugging on W32

LRN
2012-09-10T02:22:51Z

[-- Attachment #1: Type: text/plain, Size: 2599 bytes --]

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 31.08.2012 19:37, LRN wrote:
> On 31.08.2012 18:52, Eli Zaretskii wrote:
>> This needs a documentation patch to explain how this option
>> should be used.
> I can do that.
Patch is attached.
>>> +void +signal_event_command (char *args, int from_tty) +{ +
>>> int async_exec = 0; + uintmax_t event_id = 0; + char *endargs
>>> = NULL; + struct cleanup *back_to = make_cleanup
>>> (null_cleanup, NULL); + + dont_repeat (); /* Not for the
>>> faint of heart */ + + event_id = strtoumax (args, &endargs,
>>> 10); + + if ((event_id == UINTMAX_MAX && errno == ERANGE) ||
>>> event_id == 0) + error (_("Failed to convert event id `%s'
>>> to integer"), args); + +#ifdef __MINGW32__ + SetEvent
>>> ((HANDLE) event_id); + CloseHandle ((HANDLE) event_id); +#else
>>> + /* Does nothing on other platforms */ +#endif +
>>> discard_cleanups (back_to); +}
>
>> I wonder whether it would be cleaner to have the entire function
>> to be conditionally compiled on MinGW only.
>
>>> @@ -1055,6 +1065,7 @@ Options:\n\n\ --dbx DBX
>>> compatibility mode.\n\ --directory=DIR Search for source
>>> files in DIR.\n\ --epoch Output information used by
>>> epoch emacs-GDB interface.\n\ + --event=EVENT Signal the
>>> EVENT when attached to a process. W32 only.\n\
>
>> And also this part.
>
> They were, initially. However, gdb contribution documentation said
> that gdb devs frown upon extra #ifdefs in files that are not
> platform-specific. The code is mostly platform independent, it's
> the two W32API functions that only work on W32 (and you can write
> non-W32 equivalent, if you figure out how to make it work). Thus, i
> removed extra #ifdefs in main.c and other files.
Revised patch is attached.
I've made a configure option to enable this "feature", and enabled it by
default on MinGW and Cygwin. Since now it's a feature, appropriate
ifdefs were placed into the code.

Also, i reviewed the argument converting code and tweaked it a bit.
Hopefully it's correct.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (MingW32)
Comment: Using GnuPG with Mozilla - http://www.enigmail.net/

iQEcBAEBAgAGBQJQTU7aAAoJEOs4Jb6SI2CwEXkIANUy6En26IfobaExOtLtI6wT
IR0MVeCTTPhBODb6cXSl6uw9fti8MmBD2vxT/SDoR4I5jszP8n7rmdwFVVL7nvvq
cBuNnLpvTq12Mz0PrdZp7H/dMTwah5zbUz9rYqULNiEAYnkRPyBbUpPOAZpsRJPa
JvvpzZwqpC2Wt83zBjF403RuoEGuBT65452iBg7MDggaadj8ettjNO9/4sebsN1B
jIp6TWisvDHARk6cs8EC12IEJX/iMdbyzkBiW/n2ltaKOc6E9kZ0DnQ8LOTAxb4M
6XQMeqDLCp9sokV4hBdIRaaTdLmmiZeQ2RTahlQjFsCbhB5k9yPOjyeiHMdVxfk=
=Ndq4
-----END PGP SIGNATURE-----

[-- Attachment #2: 0003-Add-W32-JIT-to-docs.all.patch --]
[-- Type: text/plain, Size: 1327 bytes --]

--- gdb-7.5/gdb/doc/gdb.texinfo.orig 2012-07-20 21:59:05 +0400
+++ gdb-7.5/gdb/doc/gdb.texinfo 2012-09-10 06:18:28 +0400
@@ -977,6 +977,11 @@
@cindex @code{-p}
Connect to process ID @var{number}, as with the @code{attach} command.

+@item -event @var{number}
+@cindex @code{--event}
+Signal event ID @var{number} after attaching to a process. Used on W32 to
+make crashing process unblock.
+
@item -command @var{file}
@itemx -x @var{file}
@cindex @code{--command}
@@ -2390,6 +2395,16 @@
process continue running, you may use the @code{continue} command after
attaching @value{GDBN} to the process.

+On W32 when system detects unhandled exception in a process, it runs default
+exception handler, which starts a debugger, and then proceeds to wait
+indefinitely on an event object. System might ask user to choose a debugger,
+or, if HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug registry key
+is defined, it will run the debugger program with the command specified in
+that key. First "%ld" token in that key will be replaced with the process ID,
+second "%ld" token will be replaced with ID of the event the process is
+waiting upon. Once GDB attaches to the process, it will signal that event,
+allowing execution to continue, and will catch the exception.
+
@table @code
@kindex detach
@item detach

[-- Attachment #3: 0001-Make-gdb-JIT-capable-W32-v1.mingw32.patch --]
[-- Type: text/plain, Size: 7033 bytes --]

From 58d3018c84b96507ae13d39d7d59c3bf5364b01b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=A0=D1=83=D1=81=D0=BB=D0=B0=D0=BD=20=D0=98=D0=B6=D0=B1=D1?=
=?UTF-8?q?=83=D0=BB=D0=B0=D1=82=D0=BE=D0=B2?= <lrn1986@gmail.com>
Date: Wed, 29 Aug 2012 17:00:47 +0400
Subject: [PATCH] Make gdb JIT-capable (W32)

Adds the --event=EVENT commandline arugment. After attaching to a process,
gdb will signal that event.
Intended to be used in conjunction with AeDebug on W32.
Can be (and is) used to attach a debugger manually.
Adds configure option to enable this feature. By default it is enabled for
MinGW and Cygwin.

PR gdb/14529
---
gdb/configure.ac | 33 +++++++++++++++++++++++++++++++--
gdb/infcmd.c | 27 +++++++++++++++++++++++++++
gdb/inferior.h | 4 ++++
gdb/main.c | 25 ++++++++++++++++++++++++-
4 files changed, 86 insertions(+), 3 deletions(-)

diff --git a/gdb/configure.ac b/gdb/configure.ac
index 0c62b46..19dec6d 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -599,6 +599,9 @@ if test x"$enable_tui" != xno; then
fi
fi

+# Default value for w32_jitdbg (see below)
+default_w32_jitdbg=0
+
# Since GDB uses Readline, we need termcap functionality. In many
# cases this will be provided by the curses library, but some systems
# have a seperate termcap library, or no curses library at all.
@@ -608,16 +611,42 @@ case $host_os in
if test -d $srcdir/libtermcap; then
LIBS="../libtermcap/libtermcap.a $LIBS"
ac_cv_search_tgetent="../libtermcap/libtermcap.a"
- fi ;;
+ fi
+ default_w32_jitdbg=1
+ ;;
go32* | *djgpp*)
ac_cv_search_tgetent="none required"
;;
*mingw32*)
ac_cv_search_tgetent="none required"
CONFIG_OBS="$CONFIG_OBS windows-termcap.o"
+ default_w32_jitdbg=1
;;
esac

+# This feature requires 3 things:
+# 1) windows.h with SetEvent() and CloseHandle() prototypes
+# 2) inttypes.h with uintptr_t type defined
+# 3) libkernel32 that exports SetEvent() and CloseHandle()
+# Because functions in (1) use stdcall on W32, it's impossible to
+# check them with AC_SEARCH_LIBS.
+# Until a more elaborate check is written (compile_ifelse or something),
+# users will have to enable this feature explicitly.
+# However, this feature is enabled by default for platforms where it should
+# normally work (MinGW and Cygwin).
+
+AC_ARG_ENABLE(w32-jitdbg,
+AS_HELP_STRING([--enable-w32-jitdbg], [enable W32 JIT debugging]),
+ [case $enableval in
+ yes) w32_jitdbg=1 ;;
+ no) w32_jitdbg=0 ;;
+ *)
+ AC_MSG_ERROR([bad value $enableval for --enable-w32-jitdbg]) ;;
+ esac],
+ [w32_jitdbg=$default_w32_jitdbg])
+AC_DEFINE_UNQUOTED(W32_JITDBG, $w32_jitdbg,
+ [Define to 1 if W32 JIT debugging support is enabled, to 0 otherwise])
+
# These are the libraries checked by Readline.
AC_SEARCH_LIBS(tgetent, [termcap tinfo curses ncurses])

@@ -1071,7 +1100,7 @@ AC_CHECK_HEADERS([nlist.h machine/reg.h poll.h sys/poll.h proc_service.h \
sys/reg.h sys/debugreg.h sys/select.h sys/syscall.h \
sys/types.h sys/wait.h wait.h termios.h termio.h \
sgtty.h unistd.h elf_hp.h ctype.h time.h locale.h \
- dlfcn.h sys/socket.h sys/un.h])
+ dlfcn.h sys/socket.h sys/un.h windows.h inttypes.h])
AC_CHECK_HEADERS(link.h, [], [],
[#if HAVE_SYS_TYPES_H
# include <sys/types.h>
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 8e2f74e..7d304a3 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -57,6 +57,11 @@
#include "continuations.h"
#include "linespec.h"

+#if W32_JITDBG
+#include <windows.h>
+#include <inttypes.h>
+#endif
+
/* Functions exported for general use, in inferior.h: */

void all_registers_info (char *, int);
@@ -2636,6 +2641,29 @@ attach_command (char *args, int from_tty)
discard_cleanups (back_to);
}

+#if W32_JITDBG
+void
+signal_event_command (char *args, int from_tty)
+{
+ int async_exec = 0;
+ uintptr_t event_id = 0;
+ char *endargs = NULL;
+ struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
+
+ dont_repeat (); /* Not for the faint of heart */
+
+ event_id = strtoumax (args, &endargs, 10);
+
+ if ((errno == ERANGE) || (event_id == 0) || (event_id > UINTPTR_MAX) ||
+ ((HANDLE) event_id == INVALID_HANDLE_VALUE))
+ error (_("Failed to convert event id `%s' to event id"), args);
+
+ SetEvent ((HANDLE) event_id);
+ CloseHandle ((HANDLE) event_id);
+ discard_cleanups (back_to);
+}
+#endif
+
/* We had just found out that the target was already attached to an
inferior. PTID points at a thread of this new inferior, that is
the most likely to be stopped right now, but not necessarily so.
diff --git a/gdb/inferior.h b/gdb/inferior.h
index b2607c3..c733032 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -241,6 +241,10 @@ extern void post_create_inferior (struct target_ops *, int);

extern void attach_command (char *, int);

+#if W32_JITDBG
+extern void signal_event_command (char *, int);
+#endif
+
extern char *get_inferior_args (void);

extern void set_inferior_args (char *);
diff --git a/gdb/main.c b/gdb/main.c
index 155b609..76ac3c1 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -278,6 +278,9 @@ captured_main (void *data)
char *symarg = NULL;
char *execarg = NULL;
char *pidarg = NULL;
+#if W32_JITDBG
+ char *eventarg = NULL;
+#endif
char *corearg = NULL;
char *pid_or_core_arg = NULL;
char *cdarg = NULL;
@@ -402,6 +405,9 @@ captured_main (void *data)
OPT_TUI,
OPT_NOWINDOWS,
OPT_WINDOWS,
+#if W32_JITDBG
+ OPT_EVENT,
+#endif
OPT_IX,
OPT_IEX
};
@@ -438,6 +444,9 @@ captured_main (void *data)
{"c", required_argument, 0, 'c'},
{"pid", required_argument, 0, 'p'},
{"p", required_argument, 0, 'p'},
+#if W32_JITDBG
+ {"event", required_argument, 0, OPT_EVENT},
+#endif
{"command", required_argument, 0, 'x'},
{"eval-command", required_argument, 0, 'X'},
{"version", no_argument, &print_version, 1},
@@ -582,6 +591,11 @@ captured_main (void *data)
VEC_safe_push (cmdarg_s, cmdarg_vec, &cmdarg);
}
break;
+#if W32_JITDBG
+ case OPT_EVENT:
+ eventarg = optarg;
+ break;
+#endif
case 'B':
batch_flag = batch_silent = 1;
gdb_stdout = ui_file_new();
@@ -927,7 +941,11 @@ captured_main (void *data)
catch_command_errors (core_file_command, pid_or_core_arg,
!batch_flag, RETURN_MASK_ALL);
}
-
+#if W32_JITDBG
+ if (eventarg != NULL)
+ catch_command_errors (signal_event_command, eventarg,
+ !batch_flag, RETURN_MASK_ALL);
+#endif
if (ttyarg != NULL)
set_inferior_io_terminal (ttyarg);

@@ -1059,6 +1077,11 @@ Options:\n\n\
--fullname Output information used by emacs-GDB interface.\n\
--help Print this message.\n\
"), stream);
+#if W32_JITDBG
+ fputs_unfiltered (_("\
+ --event=EVENT Signal the EVENT when attached to a process.\n\
+"), stream);
+#endif
fputs_unfiltered (_("\
--interpreter=INTERP\n\
Select a specific interpreter / user interface\n\
--
1.7.4