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

LRN
2012-08-31T15:37:59Z

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

On 31.08.2012 18:52, Eli Zaretskii wrote:
>> Date: Wed, 29 Aug 2012 21:54:37 +0400 From: LRN
>> <lrn1986@gmail.com>
>>
>> To be a JIT-debugger [1] on Windows, gdb has to be able to signal
>> an event, which is passed to it by command line. If that is not
>> done, the process being debugged will not come out of a waiting
>> loop after gdb attaches to it. If the event is signaled, Windows
>> will break the loop, and let the exception fall into gdb's lap
>> (well, stack will be a bit borked, but that's another issue for
>> another day, and there are ways of working around it), after gdb
>> user does 'continue'.
>>
>> The attached patch [2] does exactly that by adding extra
>> "--event=EVENT" argument, thus AeDebug command line will look
>> like this: c:\mingw32\bin\gdb.exe --pid=%ld --event=%ld
>
> What is AeDebug? do you mean the Registry entry of that name? And
> what value should be used in --event= option?
Well, i think the official name is "JIT-debugging", but "JIT" has
other meanings, while AeDebug can only refer to this practice. Yes, it
comes from the registry key name. It's all documented in the link i gave.

The value of event option is an integer, which is a Windows Handle
(which is, in a nutshell, a void*; actually, good point - i should
make it 64-bit-capable, although i have never seen a handle THAT long;
OTOH, i haven't done a lot of 64-bit programming either).
This is a handle to an event object.

>
> This needs a documentation patch to explain how this option should
> be used.
I can do that. Here's the explanation (if it needs clarification or
rewording in some places, let me know) that would go to the docs:

A process crashes.
OS looks up AeDebug registry entry, gets a debugger command line.
OS then creates an event object in the crashing process, and orders
the process to wait on it.
Then OS runs the debugger [1], substituting "%ld"s in AeDebug command
line for pid and event handle, in that order.
OS duplicates the event object handle to the debugger process, so
debugger process has access to it.
Debugger initializes, attaches to the crashing process, and sets the
event.
Crashing process wakes up from waiting, once it is allowed to continue
execution by the debugger.

User makes use of this by specifying the right command line in AeDebug
registry entry, so the OS will run the debugger of user's choice
(which, obviously, would be gdb in our case).

I think it's also worth mentioning that it is possible to use this
mechanism manually: a W32 process can install an exception handler,
and in that handler create an event, spawn a suspended debugger
process, duplicate the event to debugger process, resume debugger
process, and wait for the event to be set. I.e. do the same thing OS does.
After waking up from the wait, the process returns from the exception
handler with appropriate value, which will make the OS return
execution to the point of the crash, and try to run again, but this
time it will be caught by the debugger.
In this case, obviously, process might use other ways of obtaining the
debugger command line. In GNUnet i use an environment variable for that.

Which files should the explanation go to? Should it refer to MSDN
and/or be entirely self-sufficient?

>> +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.

[1] I'm not actually sure it happens in that order. As my manual use
example later on shows you, you need to create debugger process with
suspended main thread, otherwise it's a race between debugger process
initialization and your attempts to duplicate event handle to it.
Windows might have special stuff for that though. Also, the code
probably runs as a default exception handler within the crashing
process, so while it's OS code that does the stuff, it does so from
within that process, not from outside, and probably uses process'
access token. And it means that the process waits on the event only
after spawning the debugger, just as in my manual use example.

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

iQEcBAEBAgAGBQJQQNo2AAoJEOs4Jb6SI2CwyuUIANi7eAVFBywpWPoAA5eH1JDk
jZG1/jnp4WBqEDHrkdTw1d5/ylFAL0sPfVZr9/Y/Q+QMJXZRV3K4sqYPL6/Anccx
4k5OdIgbfURWhaZYLCIJHjRMHW8nGKmwap/jsbvPDV+gyGfuvMZZsGzi/7RFIvwW
OWOGTWSowTvvN4/hrx6b7XY5NE1o15WzmDBogM771NaydjHSH/6L/KgDPmlpawKj
dCii5xOuzBsYyhhXa5GdN4jSPajZlF2QFi9yoaXXGndUPGUv++t9V0hO4xFWIvDD
Uff4dVGWBfmxvr6P45zCJdIESslywkvFFjjK9xECl+MzXPnWwE+QeKlH98SWNjE=
=Brjg
-----END PGP SIGNATURE-----