* RFC: Allow a wrapper when starting programs
@ 2008-02-08 18:57 Daniel Jacobowitz
2008-02-09 8:48 ` Eli Zaretskii
2008-02-12 19:46 ` Joel Brobecker
0 siblings, 2 replies; 12+ messages in thread
From: Daniel Jacobowitz @ 2008-02-08 18:57 UTC (permalink / raw)
To: gdb-patches; +Cc: Eli Zaretskii
This patch allows GDB and gdbserver to use wrapper programs when they
launch an inferior process.
One place this is useful is the example I used in the manual:
incompatible environment variables. If you use "set environment", the
changed variable is passed first to $SHELL and from there to the
program. Normally that's fine, but you might be setting an
LD_LIBRARY_PATH or LD_PRELOAD which will crash the shell.
So instead you do this:
(gdb) set exec-wrapper env 'LD_PRELOAD=libtest.so'
(gdb) run
And the variable is automatically passed to the right place.
There's other examples, too. For instance you could use "su" as a
wrapper to run the program as another user. That will only work if
you started as root, since otherwise GDB tracing "su" will remove
su's privileges.
Does this look OK?
--
Daniel Jacobowitz
CodeSourcery
2008-02-08 Daniel Jacobowitz <dan@codesourcery.com>
* Makefile.in (fork-child.o): Update.
* NEWS: Document "set exec-wrapper" and the gdbserver --wrapper
argument. Gather all gdbserver features together.
* fork-child.c (exec_wrapper): New variable.
(fork_inferior): Use it.
(startup_inferior): Skip an extra trap if using "set exec-wrapper".
(unset_exec_wrapper_command, _initialize_fork_child): New.
* gdb.texinfo (Starting): Document "set exec-wrapper".
(Server): Document gdbserver --wrapper.
* server.c (wrapper_argv): New.
(start_inferior): Handle wrapper_argv. If set, expect an extra
trap.
(gdbserver_usage): Document --wrapper.
(main): Parse --wrapper.
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.978
diff -u -p -r1.978 Makefile.in
--- Makefile.in 30 Jan 2008 07:17:31 -0000 1.978
+++ Makefile.in 8 Feb 2008 18:46:39 -0000
@@ -2109,7 +2109,7 @@ f-lang.o: f-lang.c $(defs_h) $(gdb_strin
$(valprint_h) $(value_h)
fork-child.o: fork-child.c $(defs_h) $(gdb_string_h) $(frame_h) \
$(inferior_h) $(target_h) $(gdb_wait_h) $(gdb_vfork_h) $(gdbcore_h) \
- $(terminal_h) $(gdbthread_h) $(command_h) $(solib_h)
+ $(terminal_h) $(gdbthread_h) $(command_h) $(gdbcmd_h) $(solib_h)
frame-base.o: frame-base.c $(defs_h) $(frame_base_h) $(frame_h) \
$(gdb_obstack_h)
frame.o: frame.c $(defs_h) $(frame_h) $(target_h) $(value_h) $(inferior_h) \
Index: NEWS
===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.256
diff -u -p -r1.256 NEWS
--- NEWS 7 Feb 2008 19:23:10 -0000 1.256
+++ NEWS 8 Feb 2008 18:46:39 -0000
@@ -34,18 +34,6 @@ more than one contiguous range of addres
* Target descriptions can now describe registers for PowerPC.
-* The GDB remote stub, gdbserver, now supports the AltiVec and SPE
-registers on PowerPC targets.
-
-* The GDB remote stub, gdbserver, now supports thread debugging on GNU/Linux
-targets even when the libthread_db library is not available.
-
-* The GDB remote stub, gdbserver, now supports the new file transfer
-commands (remote put, remote get, and remote delete).
-
-* The GDB remote stub, gdbserver, now supports run and attach in
-extended-remote mode.
-
* hppa*64*-*-hpux11* target broken
The debugger is unable to start a program and fails with the following
error: "Error trying to get information about dynamic linker".
@@ -60,6 +48,25 @@ Decimal Floating Point extension. In ad
now has a set of pseudo-registers to inspect decimal float values
stored in two consecutive float registers.
+* New features in the GDB remote stub, gdbserver
+
+ - AltiVec and SPE registers on PowerPC targets are now accessible.
+
+ - Thread debugging is now supported on GNU/Linux targets even when
+ the libthread_db library is missing.
+
+ - The new file transfer commands (remote put, remote get, and remote
+ delete) are supported with gdbserver.
+
+ - In extended-remote mode, "run" and "attach" can be used to debug new
+ processes.
+
+ - The "--multi" command-line argument lets gdbserver start without
+ a debuggee in extended-remote mode.
+
+ - The "--wrapper" command-line argument tells gdbserver to use a
+ wrapper program to launch programs for debugging.
+
* New commands
set print frame-arguments (all|scalars|none)
@@ -72,6 +79,11 @@ remote get
remote delete
Transfer files to and from a remote target, and delete remote files.
+set exec-wrapper
+show exec-wrapper
+unset exec-wrapper
+ Use a wrapper program to set launch programs for debugging.
+
* New MI commands
-target-file-put
Index: fork-child.c
===================================================================
RCS file: /cvs/src/src/gdb/fork-child.c,v
retrieving revision 1.38
diff -u -p -r1.38 fork-child.c
--- fork-child.c 29 Jan 2008 21:11:24 -0000 1.38
+++ fork-child.c 8 Feb 2008 18:46:39 -0000
@@ -31,6 +31,7 @@
#include "terminal.h"
#include "gdbthread.h"
#include "command.h" /* for dont_repeat () */
+#include "gdbcmd.h"
#include "solib.h"
#include <signal.h>
@@ -40,6 +41,8 @@
extern char **environ;
+static char *exec_wrapper;
+
/* Break up SCRATCH into an argument vector suitable for passing to
execvp and store it in ARGV. E.g., on "run a b c d" this routine
would get as input the string "a b c d", and as output it would
@@ -160,6 +163,9 @@ fork_inferior (char *exec_file_arg, char
fact that it may expand when quoted; it is a worst-case number
based on every character being '. */
len = 5 + 4 * strlen (exec_file) + 1 + strlen (allargs) + 1 + /*slop */ 12;
+ if (exec_wrapper)
+ len += strlen (exec_wrapper) + 1;
+
shell_command = (char *) alloca (len);
shell_command[0] = '\0';
@@ -178,14 +184,22 @@ fork_inferior (char *exec_file_arg, char
{
/* We're going to call a shell. */
- /* Now add exec_file, quoting as necessary. */
-
char *p;
int need_to_quote;
const int escape_bang = escape_bang_in_quoted_argument (shell_file);
strcat (shell_command, "exec ");
+ /* Add any exec wrapper. That may be a program name with arguments, so
+ the user must handle quoting. */
+ if (exec_wrapper)
+ {
+ strcat (shell_command, exec_wrapper);
+ strcat (shell_command, " ");
+ }
+
+ /* Now add exec_file, quoting as necessary. */
+
/* Quoting in this style is said to work with all shells. But
csh on IRIX 4.0.1 can't deal with it. So we only quote it if
we need to. */
@@ -399,6 +413,9 @@ startup_inferior (int ntraps)
have stopped one instruction after execing the shell. Here we
must get it up to actual execution of the real program. */
+ if (exec_wrapper)
+ pending_execs++;
+
clear_proceed_status ();
init_wait_for_inferior ();
@@ -446,3 +463,26 @@ startup_inferior (int ntraps)
}
stop_soon = NO_STOP_QUIETLY;
}
+
+/* Implement the "unset exec-wrapper" command. */
+
+static void
+unset_exec_wrapper_command (char *args, int from_tty)
+{
+ xfree (exec_wrapper);
+ exec_wrapper = NULL;
+}
+
+void
+_initialize_fork_child (void)
+{
+ add_setshow_filename_cmd ("exec-wrapper", class_run, &exec_wrapper, _("\
+Set a wrapper for running programs."), _("\
+Show the wrapper for running programs."), NULL,
+ NULL, NULL,
+ &setlist, &showlist);
+
+ add_cmd ("exec-wrapper", class_run, unset_exec_wrapper_command,
+ _("Disable use of an execution wrapper."),
+ &unsetlist);
+}
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.467
diff -u -p -r1.467 gdb.texinfo
--- doc/gdb.texinfo 3 Feb 2008 18:55:27 -0000 1.467
+++ doc/gdb.texinfo 8 Feb 2008 18:46:42 -0000
@@ -1910,6 +1910,31 @@ these cases, using the @code{start} comm
your program too late, as the program would have already completed the
elaboration phase. Under these circumstances, insert breakpoints in your
elaboration code before running your program.
+
+@kindex set exec-wrapper
+@item set exec-wrapper @var{wrapper}
+@itemx show exec-wrapper
+@itemx unset exec-wrapper
+If @samp{exec-wrapper} is set, the specified wrapper will be used to
+launch programs for debugging. @value{GDBN} will start your program
+with a shell command of the form @kbd{exec @var{wrapper}
+@var{program}}. Quoting will be added to @var{program} and its
+arguments, but not to @var{wrapper}, so you should add quotes if
+appropriate for your shell. The wrapper will run until its first
+debug trap before @value{GDBN} takes control.
+
+On Unix systems, a debug trap (@code{SIGTRAP}) is generated at the
+@code{execve} system call. This allows any program which uses
+@code{execve} to start another program to be used as a wrapper. For
+example, you can use @code{env} to pass an environment variable to the
+debugged program, without setting the variable to your shell's
+environment:
+
+@smallexample
+(@value{GDBP}) set exec-wrapper env 'LD_PRELOAD=libtest.so'
+(@value{GDBP}) run
+@end smallexample
+
@end table
@node Arguments
@@ -13074,6 +13099,27 @@ You can include @option{--debug} on the
process. This option is intended for @code{gdbserver} development and
for bug reports to the developers.
+The @option{--wrapper} option specifies a wrapper to launch programs
+for debugging. The option should be followed by the name of the
+wrapper, then any command-line arguments to pass to the wrapper, then
+@kbd{--} indicating the end of the wrapper arguments.
+
+@code{gdbserver} will run the specified wrapper program with a
+combined command line including the wrapper arguments, then the name
+of the program to debug, then any arguments to the program. The wrapper
+will run until its first debug trap before @value{GDBN} gains control.
+
+On Unix systems, a debug trap (@code{SIGTRAP}) is generated at the
+@code{execve} system call. This allows any program which uses
+@code{execve} to start another program to be used as a wrapper. For
+example, you can use @code{env} to pass an environment variable to the
+debugged program, without setting the variable in @code{gdbserver}'s
+environment:
+
+@smallexample
+$ gdbserver --wrapper env LD_PRELOAD=libtest.so -- :2222 ./testprog
+@end smallexample
+
@subsection Connecting to @code{gdbserver}
Run @value{GDBN} on the host system.
Index: gdbserver/server.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/server.c,v
retrieving revision 1.63
diff -u -p -r1.63 server.c
--- gdbserver/server.c 30 Jan 2008 00:51:50 -0000 1.63
+++ gdbserver/server.c 8 Feb 2008 18:46:42 -0000
@@ -41,7 +41,7 @@ static int attached;
static int response_needed;
static int exit_requested;
-static char **program_argv;
+static char **program_argv, **wrapper_argv;
/* Enable miscellaneous debugging output. The name is historical - it
was originally used to debug LinuxThreads support. */
@@ -81,16 +81,34 @@ target_running (void)
}
static int
-start_inferior (char *argv[], char *statusptr)
+start_inferior (char **argv, char *statusptr)
{
+ char **new_argv = argv;
attached = 0;
+ if (wrapper_argv != NULL)
+ {
+ int i, count = 1;
+
+ for (i = 0; wrapper_argv[i] != NULL; i++)
+ count++;
+ for (i = 0; argv[i] != NULL; i++)
+ count++;
+ new_argv = alloca (sizeof (char *) * count);
+ count = 0;
+ for (i = 0; wrapper_argv[i] != NULL; i++)
+ new_argv[count++] = wrapper_argv[i];
+ for (i = 0; argv[i] != NULL; i++)
+ new_argv[count++] = argv[i];
+ new_argv[count] = NULL;
+ }
+
#ifdef SIGTTOU
signal (SIGTTOU, SIG_DFL);
signal (SIGTTIN, SIG_DFL);
#endif
- signal_pid = create_inferior (argv[0], argv);
+ signal_pid = create_inferior (new_argv[0], new_argv);
/* FIXME: we don't actually know at this point that the create
actually succeeded. We won't know that until we wait. */
@@ -107,6 +125,33 @@ start_inferior (char *argv[], char *stat
atexit (restore_old_foreground_pgrp);
#endif
+ if (wrapper_argv != NULL)
+ {
+ struct thread_resume resume_info;
+ int sig;
+
+ resume_info.thread = -1;
+ resume_info.step = 0;
+ resume_info.sig = 0;
+ resume_info.leave_stopped = 0;
+
+ sig = mywait (statusptr, 0);
+ if (*statusptr != 'T')
+ return sig;
+
+ do
+ {
+ (*the_target->resume) (&resume_info);
+
+ sig = mywait (statusptr, 0);
+ if (*statusptr != 'T')
+ return sig;
+ }
+ while (sig != TARGET_SIGNAL_TRAP);
+
+ return sig;
+ }
+
/* Wait till we are at 1st instruction in program, return signal
number (assuming success). */
return mywait (statusptr, 0);
@@ -1001,7 +1046,8 @@ gdbserver_usage (void)
"HOST:PORT to listen for a TCP connection.\n"
"\n"
"Options:\n"
- " --debug\t\tEnable debugging output.\n");
+ " --debug\t\tEnable debugging output.\n"
+ " --wrapper WRAPPER --\tRun WRAPPER to start new programs.\n");
}
#undef require_running
@@ -1045,6 +1091,23 @@ main (int argc, char *argv[])
attach = 1;
else if (strcmp (*next_arg, "--multi") == 0)
multi_mode = 1;
+ else if (strcmp (*next_arg, "--wrapper") == 0)
+ {
+ next_arg++;
+
+ wrapper_argv = next_arg;
+ while (*next_arg != NULL && strcmp (*next_arg, "--") != 0)
+ next_arg++;
+
+ if (next_arg == wrapper_argv || *next_arg == NULL)
+ {
+ gdbserver_usage ();
+ exit (1);
+ }
+
+ /* Consume the "--". */
+ *next_arg = NULL;
+ }
else if (strcmp (*next_arg, "--debug") == 0)
debug_threads = 1;
else
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFC: Allow a wrapper when starting programs
2008-02-08 18:57 RFC: Allow a wrapper when starting programs Daniel Jacobowitz
@ 2008-02-09 8:48 ` Eli Zaretskii
2008-02-09 15:48 ` Daniel Jacobowitz
2008-02-12 19:46 ` Joel Brobecker
1 sibling, 1 reply; 12+ messages in thread
From: Eli Zaretskii @ 2008-02-09 8:48 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches
> Date: Fri, 8 Feb 2008 13:57:27 -0500
> From: Daniel Jacobowitz <drow@false.org>
> Cc: Eli Zaretskii <eliz@gnu.org>
>
> This patch allows GDB and gdbserver to use wrapper programs when they
> launch an inferior process.
Thanks!
A few comments on your patch:
> --- NEWS 7 Feb 2008 19:23:10 -0000 1.256
> +++ NEWS 8 Feb 2008 18:46:39 -0000
This part is okay, except:
> +* New features in the GDB remote stub, gdbserver
> +
> + - AltiVec and SPE registers on PowerPC targets are now accessible.
> +
> + - Thread debugging is now supported on GNU/Linux targets even when
> + the libthread_db library is missing.
> +
> + - The new file transfer commands (remote put, remote get, and remote
> + delete) are supported with gdbserver.
You are already describing gdbserver changes, so saying that again at
the end of the last sentence is redundant, I think.
> --- fork-child.c 29 Jan 2008 21:11:24 -0000 1.38
> +++ fork-child.c 8 Feb 2008 18:46:39 -0000
Do all supported platform use fork-child to run the inferior? If not,
those that don't will not have this feature, and this fact should be
reflected in the manual.
> + if (exec_wrapper)
> + pending_execs++;
You seem to be assuming that the wrapper is a simple command that
exec's only once. But in fact the wrapper could be an arbitrarily
complex script that exec's several times, right? If a single-exec
limitation is something we cannot easily overcome, we must document it
clearly in the manual.
> +void
> +_initialize_fork_child (void)
> +{
> + add_setshow_filename_cmd ("exec-wrapper", class_run, &exec_wrapper, _("\
> +Set a wrapper for running programs."), _("\
> +Show the wrapper for running programs."), NULL,
That is rather cryptic, IMO. How about adding a few more words about
what is a wrapper and how it is used?
> + The wrapper will run until its first
> +debug trap before @value{GDBN} takes control.
> +
> +On Unix systems, a debug trap (@code{SIGTRAP}) is generated at the
> +@code{execve} system call. This allows any program which uses
> +@code{execve} to start another program to be used as a wrapper.
This is not detailed enough to be useful to anyone but a GDB hacker
who also happened to read the respective portions of the code in
fork-child.c. In any case, it left me wondering what is this all
about, and why I, as a GDB user, should care about SIGTRAPs.
IOW, if this is important for the user to know, we should explain the
issue in terms understandable by a GDB user.
> + The wrapper
> +will run until its first debug trap before @value{GDBN} gains control.
> +
> +On Unix systems, a debug trap (@code{SIGTRAP}) is generated at the
> +@code{execve} system call. This allows any program which uses
> +@code{execve} to start another program to be used as a wrapper. For
> +example, you can use @code{env} to pass an environment variable to the
> +debugged program, without setting the variable in @code{gdbserver}'s
> +environment:
Same here.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFC: Allow a wrapper when starting programs
2008-02-09 8:48 ` Eli Zaretskii
@ 2008-02-09 15:48 ` Daniel Jacobowitz
2008-02-09 16:41 ` Eli Zaretskii
0 siblings, 1 reply; 12+ messages in thread
From: Daniel Jacobowitz @ 2008-02-09 15:48 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches
On Sat, Feb 09, 2008 at 10:47:15AM +0200, Eli Zaretskii wrote:
> > --- fork-child.c 29 Jan 2008 21:11:24 -0000 1.38
> > +++ fork-child.c 8 Feb 2008 18:46:39 -0000
>
> Do all supported platform use fork-child to run the inferior? If not,
> those that don't will not have this feature, and this fact should be
> reflected in the manual.
I was wondering about that. Will keeping the list up to date be a
problem?
Every native (non-remote) target uses fork-child, except for DJGPP,
Cygwin, mingw32, and QNX NTO.
> > + if (exec_wrapper)
> > + pending_execs++;
>
> You seem to be assuming that the wrapper is a simple command that
> exec's only once. But in fact the wrapper could be an arbitrarily
> complex script that exec's several times, right? If a single-exec
> limitation is something we cannot easily overcome, we must document it
> clearly in the manual.
For a typical script, this isn't an issue. Forks are not caught, nor
are execs after forking. So this would work:
#!/bin/sh
touch /tmp/logfile
exec "$@" 2> my-stderr.txt
Of course, you could chain wrappers: "set exec-wrapper env env". And
GDB could make the number of traps configurable for that case. But I
don't think it's useful, and it's hard to explain. So I would prefer
not to support it until someone finds a way to take advantage of
chaining.
> > +void
> > +_initialize_fork_child (void)
> > +{
> > + add_setshow_filename_cmd ("exec-wrapper", class_run, &exec_wrapper, _("\
> > +Set a wrapper for running programs."), _("\
> > +Show the wrapper for running programs."), NULL,
>
> That is rather cryptic, IMO. How about adding a few more words about
> what is a wrapper and how it is used?
>
> > + The wrapper will run until its first
> > +debug trap before @value{GDBN} takes control.
> > +
> > +On Unix systems, a debug trap (@code{SIGTRAP}) is generated at the
> > +@code{execve} system call. This allows any program which uses
> > +@code{execve} to start another program to be used as a wrapper.
>
> This is not detailed enough to be useful to anyone but a GDB hacker
> who also happened to read the respective portions of the code in
> fork-child.c. In any case, it left me wondering what is this all
> about, and why I, as a GDB user, should care about SIGTRAPs.
>
> IOW, if this is important for the user to know, we should explain the
> issue in terms understandable by a GDB user.
This is where I get stuck. I did the best I could, but the effect of
waiting for an extra trap is hard to describe except in terms of
signals or examples. I don't know what else to add.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFC: Allow a wrapper when starting programs
2008-02-09 15:48 ` Daniel Jacobowitz
@ 2008-02-09 16:41 ` Eli Zaretskii
2008-02-09 16:53 ` Daniel Jacobowitz
0 siblings, 1 reply; 12+ messages in thread
From: Eli Zaretskii @ 2008-02-09 16:41 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches
> Date: Sat, 9 Feb 2008 10:48:34 -0500
> From: Daniel Jacobowitz <drow@false.org>
> Cc: gdb-patches@sourceware.org
>
> On Sat, Feb 09, 2008 at 10:47:15AM +0200, Eli Zaretskii wrote:
> > > --- fork-child.c 29 Jan 2008 21:11:24 -0000 1.38
> > > +++ fork-child.c 8 Feb 2008 18:46:39 -0000
> >
> > Do all supported platform use fork-child to run the inferior? If not,
> > those that don't will not have this feature, and this fact should be
> > reflected in the manual.
>
> I was wondering about that. Will keeping the list up to date be a
> problem?
Maybe, but it's better not to create an impression that this is
supported universally. To make the burden easier, we could say
something like "this is supported by only some platforms".
> Every native (non-remote) target uses fork-child, except for DJGPP,
> Cygwin, mingw32, and QNX NTO.
DJGPP is not important enough to care, but Cygwin is, and so are (to a
lesser extent, I think) MinGW and NTO.
> Of course, you could chain wrappers: "set exec-wrapper env env". And
> GDB could make the number of traps configurable for that case. But I
> don't think it's useful, and it's hard to explain. So I would prefer
> not to support it until someone finds a way to take advantage of
> chaining.
I agree; documenting the restriction in the manual should be good
enough.
> > > + The wrapper will run until its first
> > > +debug trap before @value{GDBN} takes control.
> > > +
> > > +On Unix systems, a debug trap (@code{SIGTRAP}) is generated at the
> > > +@code{execve} system call. This allows any program which uses
> > > +@code{execve} to start another program to be used as a wrapper.
> >
> > This is not detailed enough to be useful to anyone but a GDB hacker
> > who also happened to read the respective portions of the code in
> > fork-child.c. In any case, it left me wondering what is this all
> > about, and why I, as a GDB user, should care about SIGTRAPs.
> >
> > IOW, if this is important for the user to know, we should explain the
> > issue in terms understandable by a GDB user.
>
> This is where I get stuck. I did the best I could, but the effect of
> waiting for an extra trap is hard to describe except in terms of
> signals or examples. I don't know what else to add.
Try me: if you explain why all this is needed, I might find a way to
describe that in the manual. For starters, why do we need to wait for
an extra trap?
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFC: Allow a wrapper when starting programs
2008-02-09 16:41 ` Eli Zaretskii
@ 2008-02-09 16:53 ` Daniel Jacobowitz
2008-02-09 19:20 ` Doug Evans
2008-02-11 16:14 ` Daniel Jacobowitz
0 siblings, 2 replies; 12+ messages in thread
From: Daniel Jacobowitz @ 2008-02-09 16:53 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches
On Sat, Feb 09, 2008 at 06:40:48PM +0200, Eli Zaretskii wrote:
> Maybe, but it's better not to create an impression that this is
> supported universally. To make the burden easier, we could say
> something like "this is supported by only some platforms".
>
> > Every native (non-remote) target uses fork-child, except for DJGPP,
> > Cygwin, mingw32, and QNX NTO.
>
> DJGPP is not important enough to care, but Cygwin is, and so are (to a
> lesser extent, I think) MinGW and NTO.
Yeah. Listing them is probably best.
> > > > + The wrapper will run until its first
> > > > +debug trap before @value{GDBN} takes control.
> > > > +
> > > > +On Unix systems, a debug trap (@code{SIGTRAP}) is generated at the
> > > > +@code{execve} system call. This allows any program which uses
> > > > +@code{execve} to start another program to be used as a wrapper.
> > >
> > > This is not detailed enough to be useful to anyone but a GDB hacker
> > > who also happened to read the respective portions of the code in
> > > fork-child.c. In any case, it left me wondering what is this all
> > > about, and why I, as a GDB user, should care about SIGTRAPs.
> > >
> > > IOW, if this is important for the user to know, we should explain the
> > > issue in terms understandable by a GDB user.
> >
> > This is where I get stuck. I did the best I could, but the effect of
> > waiting for an extra trap is hard to describe except in terms of
> > signals or examples. I don't know what else to add.
>
> Try me: if you explain why all this is needed, I might find a way to
> describe that in the manual. For starters, why do we need to wait for
> an extra trap?
Sure. We're waiting for an extra trap for the same reason we
currently wait for two (on most systems; sometimes varies). We
normally fork and then execute a command like this one:
sh -c 'exec your-program'
The first trap is generated when gdb execs sh. At this point we know
where the child is, but it's at the wrong place. The loaded binary is
sh, not your-program, so we can't set breakpoints in your-program.
With a wrapper, we run:
sh -c 'exec wrapper your-program'
So after two traps, the loaded program is wrapper. If we gave
control to the user or tried to insert breakpoints at your-program's
symbols, things would go wrong. We have to wait until the loaded
program is finally your-program.
There's no portable way to check what the loaded program is, and
even if there were it wouldn't help enough; wrapper and your-program
might be the same binary (a corner case, I admit).
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFC: Allow a wrapper when starting programs
2008-02-09 16:53 ` Daniel Jacobowitz
@ 2008-02-09 19:20 ` Doug Evans
2008-02-10 1:15 ` Daniel Jacobowitz
2008-02-11 16:14 ` Daniel Jacobowitz
1 sibling, 1 reply; 12+ messages in thread
From: Doug Evans @ 2008-02-09 19:20 UTC (permalink / raw)
To: gdb-patches
On Feb 9, 2008 8:53 AM, Daniel Jacobowitz <drow@false.org> wrote:
> Sure. We're waiting for an extra trap for the same reason we
> currently wait for two (on most systems; sometimes varies). We
> normally fork and then execute a command like this one:
>
> sh -c 'exec your-program'
>
> The first trap is generated when gdb execs sh. At this point we know
> where the child is, but it's at the wrong place. The loaded binary is
> sh, not your-program, so we can't set breakpoints in your-program.
>
> With a wrapper, we run:
>
> sh -c 'exec wrapper your-program'
>
> So after two traps, the loaded program is wrapper. If we gave
> control to the user or tried to insert breakpoints at your-program's
> symbols, things would go wrong. We have to wait until the loaded
> program is finally your-program.
>
> There's no portable way to check what the loaded program is, and
> even if there were it wouldn't help enough; wrapper and your-program
> might be the same binary (a corner case, I admit).
When explained this way one might think there are two wrappers: sh and
wrapper. Has anyone ever wanted a way to remove, replace, or
otherwise alter the use of the sh "wrapper"? I realize sh brings
certain functionality to the party, but it seems like one popular use
of the second wrapper is to work around the presence of the first
wrapper. It leaves me wondering if there's a better way. OTOH,
pragmatics may require the proposed implementation.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFC: Allow a wrapper when starting programs
2008-02-09 19:20 ` Doug Evans
@ 2008-02-10 1:15 ` Daniel Jacobowitz
0 siblings, 0 replies; 12+ messages in thread
From: Daniel Jacobowitz @ 2008-02-10 1:15 UTC (permalink / raw)
To: Doug Evans; +Cc: gdb-patches
On Sat, Feb 09, 2008 at 11:19:35AM -0800, Doug Evans wrote:
> When explained this way one might think there are two wrappers: sh and
> wrapper. Has anyone ever wanted a way to remove, replace, or
> otherwise alter the use of the sh "wrapper"?
Yes, I've been meaning to make it optional again.
(I actually need the second wrapper for a completely different
purpose. Env is just a convenient example of the second
wrapper.)
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFC: Allow a wrapper when starting programs
2008-02-09 16:53 ` Daniel Jacobowitz
2008-02-09 19:20 ` Doug Evans
@ 2008-02-11 16:14 ` Daniel Jacobowitz
2008-02-11 19:45 ` Daniel Jacobowitz
2008-02-11 20:30 ` Eli Zaretskii
1 sibling, 2 replies; 12+ messages in thread
From: Daniel Jacobowitz @ 2008-02-11 16:14 UTC (permalink / raw)
To: Eli Zaretskii, gdb-patches
On Sat, Feb 09, 2008 at 11:53:28AM -0500, Daniel Jacobowitz wrote:
> Sure. We're waiting for an extra trap for the same reason we
> currently wait for two (on most systems; sometimes varies). We
> normally fork and then execute a command like this one:
>
> sh -c 'exec your-program'
>
> The first trap is generated when gdb execs sh. At this point we know
> where the child is, but it's at the wrong place. The loaded binary is
> sh, not your-program, so we can't set breakpoints in your-program.
>
> With a wrapper, we run:
>
> sh -c 'exec wrapper your-program'
>
> So after two traps, the loaded program is wrapper. If we gave
> control to the user or tried to insert breakpoints at your-program's
> symbols, things would go wrong. We have to wait until the loaded
> program is finally your-program.
Hi Eli,
Could you take a look at this version? I've made the descriptions
more user-centric and I hope they're clearer now.
--
Daniel Jacobowitz
CodeSourcery
2008-02-11 Daniel Jacobowitz <dan@codesourcery.com>
* Makefile.in (fork-child.o): Update.
* NEWS: Document "set exec-wrapper" and the gdbserver --wrapper
argument. Gather all gdbserver features together.
* fork-child.c (exec_wrapper): New variable.
(fork_inferior): Use it.
(startup_inferior): Skip an extra trap if using "set exec-wrapper".
(unset_exec_wrapper_command, _initialize_fork_child): New.
* gdb.texinfo (Starting): Document "set exec-wrapper".
(Server): Document gdbserver --wrapper.
* server.c (wrapper_argv): New.
(start_inferior): Handle wrapper_argv. If set, expect an extra
trap.
(gdbserver_usage): Document --wrapper.
(main): Parse --wrapper.
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.981
diff -u -p -r1.981 Makefile.in
--- Makefile.in 9 Feb 2008 13:45:33 -0000 1.981
+++ Makefile.in 11 Feb 2008 16:13:06 -0000
@@ -2109,7 +2109,7 @@ f-lang.o: f-lang.c $(defs_h) $(gdb_strin
$(valprint_h) $(value_h)
fork-child.o: fork-child.c $(defs_h) $(gdb_string_h) $(frame_h) \
$(inferior_h) $(target_h) $(gdb_wait_h) $(gdb_vfork_h) $(gdbcore_h) \
- $(terminal_h) $(gdbthread_h) $(command_h) $(solib_h)
+ $(terminal_h) $(gdbthread_h) $(command_h) $(gdbcmd_h) $(solib_h)
frame-base.o: frame-base.c $(defs_h) $(frame_base_h) $(frame_h) \
$(gdb_obstack_h)
frame.o: frame.c $(defs_h) $(frame_h) $(target_h) $(value_h) $(inferior_h) \
Index: NEWS
===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.256
diff -u -p -r1.256 NEWS
--- NEWS 7 Feb 2008 19:23:10 -0000 1.256
+++ NEWS 11 Feb 2008 16:13:06 -0000
@@ -34,18 +34,6 @@ more than one contiguous range of addres
* Target descriptions can now describe registers for PowerPC.
-* The GDB remote stub, gdbserver, now supports the AltiVec and SPE
-registers on PowerPC targets.
-
-* The GDB remote stub, gdbserver, now supports thread debugging on GNU/Linux
-targets even when the libthread_db library is not available.
-
-* The GDB remote stub, gdbserver, now supports the new file transfer
-commands (remote put, remote get, and remote delete).
-
-* The GDB remote stub, gdbserver, now supports run and attach in
-extended-remote mode.
-
* hppa*64*-*-hpux11* target broken
The debugger is unable to start a program and fails with the following
error: "Error trying to get information about dynamic linker".
@@ -60,6 +48,25 @@ Decimal Floating Point extension. In ad
now has a set of pseudo-registers to inspect decimal float values
stored in two consecutive float registers.
+* New features in the GDB remote stub, gdbserver
+
+ - AltiVec and SPE registers on PowerPC targets are now accessible.
+
+ - Thread debugging is now supported on GNU/Linux targets even when
+ the libthread_db library is missing.
+
+ - The new file transfer commands (remote put, remote get, and remote
+ delete) are supported with gdbserver.
+
+ - In extended-remote mode, "run" and "attach" can be used to debug new
+ processes.
+
+ - The "--multi" command-line argument lets gdbserver start without
+ a debuggee in extended-remote mode.
+
+ - The "--wrapper" command-line argument tells gdbserver to use a
+ wrapper program to launch programs for debugging.
+
* New commands
set print frame-arguments (all|scalars|none)
@@ -72,6 +79,11 @@ remote get
remote delete
Transfer files to and from a remote target, and delete remote files.
+set exec-wrapper
+show exec-wrapper
+unset exec-wrapper
+ Use a wrapper program to set launch programs for debugging.
+
* New MI commands
-target-file-put
Index: fork-child.c
===================================================================
RCS file: /cvs/src/src/gdb/fork-child.c,v
retrieving revision 1.38
diff -u -p -r1.38 fork-child.c
--- fork-child.c 29 Jan 2008 21:11:24 -0000 1.38
+++ fork-child.c 11 Feb 2008 16:13:07 -0000
@@ -31,6 +31,7 @@
#include "terminal.h"
#include "gdbthread.h"
#include "command.h" /* for dont_repeat () */
+#include "gdbcmd.h"
#include "solib.h"
#include <signal.h>
@@ -40,6 +41,8 @@
extern char **environ;
+static char *exec_wrapper;
+
/* Break up SCRATCH into an argument vector suitable for passing to
execvp and store it in ARGV. E.g., on "run a b c d" this routine
would get as input the string "a b c d", and as output it would
@@ -160,6 +163,9 @@ fork_inferior (char *exec_file_arg, char
fact that it may expand when quoted; it is a worst-case number
based on every character being '. */
len = 5 + 4 * strlen (exec_file) + 1 + strlen (allargs) + 1 + /*slop */ 12;
+ if (exec_wrapper)
+ len += strlen (exec_wrapper) + 1;
+
shell_command = (char *) alloca (len);
shell_command[0] = '\0';
@@ -178,14 +184,22 @@ fork_inferior (char *exec_file_arg, char
{
/* We're going to call a shell. */
- /* Now add exec_file, quoting as necessary. */
-
char *p;
int need_to_quote;
const int escape_bang = escape_bang_in_quoted_argument (shell_file);
strcat (shell_command, "exec ");
+ /* Add any exec wrapper. That may be a program name with arguments, so
+ the user must handle quoting. */
+ if (exec_wrapper)
+ {
+ strcat (shell_command, exec_wrapper);
+ strcat (shell_command, " ");
+ }
+
+ /* Now add exec_file, quoting as necessary. */
+
/* Quoting in this style is said to work with all shells. But
csh on IRIX 4.0.1 can't deal with it. So we only quote it if
we need to. */
@@ -399,6 +413,9 @@ startup_inferior (int ntraps)
have stopped one instruction after execing the shell. Here we
must get it up to actual execution of the real program. */
+ if (exec_wrapper)
+ pending_execs++;
+
clear_proceed_status ();
init_wait_for_inferior ();
@@ -446,3 +463,28 @@ startup_inferior (int ntraps)
}
stop_soon = NO_STOP_QUIETLY;
}
+
+/* Implement the "unset exec-wrapper" command. */
+
+static void
+unset_exec_wrapper_command (char *args, int from_tty)
+{
+ xfree (exec_wrapper);
+ exec_wrapper = NULL;
+}
+
+void
+_initialize_fork_child (void)
+{
+ add_setshow_filename_cmd ("exec-wrapper", class_run, &exec_wrapper, _("\
+Set a wrapper for running programs.\n\
+The wrapper prepares the system and environment for the new program."),
+ _("\
+Show the wrapper for running programs."), NULL,
+ NULL, NULL,
+ &setlist, &showlist);
+
+ add_cmd ("exec-wrapper", class_run, unset_exec_wrapper_command,
+ _("Disable use of an execution wrapper."),
+ &unsetlist);
+}
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.467
diff -u -p -r1.467 gdb.texinfo
--- doc/gdb.texinfo 3 Feb 2008 18:55:27 -0000 1.467
+++ doc/gdb.texinfo 11 Feb 2008 16:13:09 -0000
@@ -1910,6 +1910,36 @@ these cases, using the @code{start} comm
your program too late, as the program would have already completed the
elaboration phase. Under these circumstances, insert breakpoints in your
elaboration code before running your program.
+
+@kindex set exec-wrapper
+@item set exec-wrapper @var{wrapper}
+@itemx show exec-wrapper
+@itemx unset exec-wrapper
+When @samp{exec-wrapper} is set, the specified wrapper is used to
+launch programs for debugging. @value{GDBN} starts your program
+with a shell command of the form @kbd{exec @var{wrapper}
+@var{program}}. Quoting is added to @var{program} and its
+arguments, but not to @var{wrapper}, so you should add quotes if
+appropriate for your shell. The wrapper runs until it executes
+your program, and then @value{GDBN} takes control.
+
+You can use any program which eventually calls @code{execve} with
+its arguments as a wrapper. Several standard Unix utilities do
+this, e.g.@: @code{env} and @code{nohup}. Any shell script ending
+with @code{exec "$@"} will also work.
+
+For example, you can use @code{env} to pass an environment variable to
+the debugged program, without setting the variable in your shell's
+environment:
+
+@smallexample
+(@value{GDBP}) set exec-wrapper env 'LD_PRELOAD=libtest.so'
+(@value{GDBP}) run
+@end smallexample
+
+This command is available when debugging locally on most targets, excluding
+@sc{djgpp}, Cygwin, MS Windows, and QNX Neutrino.
+
@end table
@node Arguments
@@ -13074,6 +13104,29 @@ You can include @option{--debug} on the
process. This option is intended for @code{gdbserver} development and
for bug reports to the developers.
+The @option{--wrapper} option specifies a wrapper to launch programs
+for debugging. The option should be followed by the name of the
+wrapper, then any command-line arguments to pass to the wrapper, then
+@kbd{--} indicating the end of the wrapper arguments.
+
+@code{gdbserver} runs the specified wrapper program with a combined
+command line including the wrapper arguments, then the name of the
+program to debug, then any arguments to the program. The wrapper
+runs until it executes your program, and then @value{GDBN} gains control.
+
+You can use any program which eventually calls @code{execve} with
+its arguments as a wrapper. Several standard Unix utilities do
+this, e.g.@: @code{env} and @code{nohup}. Any shell script ending
+with @code{exec "$@"} will also work.
+
+For example, you can use @code{env} to pass an environment variable to
+the debugged program, without setting the variable in @code{gdbserver}'s
+environment:
+
+@smallexample
+$ gdbserver --wrapper env LD_PRELOAD=libtest.so -- :2222 ./testprog
+@end smallexample
+
@subsection Connecting to @code{gdbserver}
Run @value{GDBN} on the host system.
Index: gdbserver/server.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/server.c,v
retrieving revision 1.63
diff -u -p -r1.63 server.c
--- gdbserver/server.c 30 Jan 2008 00:51:50 -0000 1.63
+++ gdbserver/server.c 11 Feb 2008 16:13:09 -0000
@@ -41,7 +41,7 @@ static int attached;
static int response_needed;
static int exit_requested;
-static char **program_argv;
+static char **program_argv, **wrapper_argv;
/* Enable miscellaneous debugging output. The name is historical - it
was originally used to debug LinuxThreads support. */
@@ -81,16 +81,34 @@ target_running (void)
}
static int
-start_inferior (char *argv[], char *statusptr)
+start_inferior (char **argv, char *statusptr)
{
+ char **new_argv = argv;
attached = 0;
+ if (wrapper_argv != NULL)
+ {
+ int i, count = 1;
+
+ for (i = 0; wrapper_argv[i] != NULL; i++)
+ count++;
+ for (i = 0; argv[i] != NULL; i++)
+ count++;
+ new_argv = alloca (sizeof (char *) * count);
+ count = 0;
+ for (i = 0; wrapper_argv[i] != NULL; i++)
+ new_argv[count++] = wrapper_argv[i];
+ for (i = 0; argv[i] != NULL; i++)
+ new_argv[count++] = argv[i];
+ new_argv[count] = NULL;
+ }
+
#ifdef SIGTTOU
signal (SIGTTOU, SIG_DFL);
signal (SIGTTIN, SIG_DFL);
#endif
- signal_pid = create_inferior (argv[0], argv);
+ signal_pid = create_inferior (new_argv[0], new_argv);
/* FIXME: we don't actually know at this point that the create
actually succeeded. We won't know that until we wait. */
@@ -107,6 +125,33 @@ start_inferior (char *argv[], char *stat
atexit (restore_old_foreground_pgrp);
#endif
+ if (wrapper_argv != NULL)
+ {
+ struct thread_resume resume_info;
+ int sig;
+
+ resume_info.thread = -1;
+ resume_info.step = 0;
+ resume_info.sig = 0;
+ resume_info.leave_stopped = 0;
+
+ sig = mywait (statusptr, 0);
+ if (*statusptr != 'T')
+ return sig;
+
+ do
+ {
+ (*the_target->resume) (&resume_info);
+
+ sig = mywait (statusptr, 0);
+ if (*statusptr != 'T')
+ return sig;
+ }
+ while (sig != TARGET_SIGNAL_TRAP);
+
+ return sig;
+ }
+
/* Wait till we are at 1st instruction in program, return signal
number (assuming success). */
return mywait (statusptr, 0);
@@ -1001,7 +1046,8 @@ gdbserver_usage (void)
"HOST:PORT to listen for a TCP connection.\n"
"\n"
"Options:\n"
- " --debug\t\tEnable debugging output.\n");
+ " --debug\t\tEnable debugging output.\n"
+ " --wrapper WRAPPER --\tRun WRAPPER to start new programs.\n");
}
#undef require_running
@@ -1045,6 +1091,23 @@ main (int argc, char *argv[])
attach = 1;
else if (strcmp (*next_arg, "--multi") == 0)
multi_mode = 1;
+ else if (strcmp (*next_arg, "--wrapper") == 0)
+ {
+ next_arg++;
+
+ wrapper_argv = next_arg;
+ while (*next_arg != NULL && strcmp (*next_arg, "--") != 0)
+ next_arg++;
+
+ if (next_arg == wrapper_argv || *next_arg == NULL)
+ {
+ gdbserver_usage ();
+ exit (1);
+ }
+
+ /* Consume the "--". */
+ *next_arg = NULL;
+ }
else if (strcmp (*next_arg, "--debug") == 0)
debug_threads = 1;
else
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFC: Allow a wrapper when starting programs
2008-02-11 16:14 ` Daniel Jacobowitz
@ 2008-02-11 19:45 ` Daniel Jacobowitz
2008-02-11 20:30 ` Eli Zaretskii
1 sibling, 0 replies; 12+ messages in thread
From: Daniel Jacobowitz @ 2008-02-11 19:45 UTC (permalink / raw)
To: gdb-patches; +Cc: Eli Zaretskii
On Mon, Feb 11, 2008 at 11:14:18AM -0500, Daniel Jacobowitz wrote:
> +set exec-wrapper
> +show exec-wrapper
> +unset exec-wrapper
> + Use a wrapper program to set launch programs for debugging.
Drop "set ". Whoops.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFC: Allow a wrapper when starting programs
2008-02-11 16:14 ` Daniel Jacobowitz
2008-02-11 19:45 ` Daniel Jacobowitz
@ 2008-02-11 20:30 ` Eli Zaretskii
2008-03-10 23:14 ` Daniel Jacobowitz
1 sibling, 1 reply; 12+ messages in thread
From: Eli Zaretskii @ 2008-02-11 20:30 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches
> Date: Mon, 11 Feb 2008 11:14:18 -0500
> From: Daniel Jacobowitz <drow@false.org>
>
> Could you take a look at this version? I've made the descriptions
> more user-centric and I hope they're clearer now.
Yes, this is much, much better; thanks.
> +You can use any program which eventually calls @code{execve} with
> +its arguments as a wrapper. Several standard Unix utilities do
> +this, e.g.@: @code{env} and @code{nohup}. Any shell script ending
> +with @code{exec "$@"} will also work.
I think "any Unix shell script" is more accurate.
Otherwise, I'm happy now.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFC: Allow a wrapper when starting programs
2008-02-08 18:57 RFC: Allow a wrapper when starting programs Daniel Jacobowitz
2008-02-09 8:48 ` Eli Zaretskii
@ 2008-02-12 19:46 ` Joel Brobecker
1 sibling, 0 replies; 12+ messages in thread
From: Joel Brobecker @ 2008-02-12 19:46 UTC (permalink / raw)
To: gdb-patches
> 2008-02-08 Daniel Jacobowitz <dan@codesourcery.com>
>
> * Makefile.in (fork-child.o): Update.
> * NEWS: Document "set exec-wrapper" and the gdbserver --wrapper
> argument. Gather all gdbserver features together.
> * fork-child.c (exec_wrapper): New variable.
> (fork_inferior): Use it.
> (startup_inferior): Skip an extra trap if using "set exec-wrapper".
> (unset_exec_wrapper_command, _initialize_fork_child): New.
>
> * gdb.texinfo (Starting): Document "set exec-wrapper".
> (Server): Document gdbserver --wrapper.
>
> * server.c (wrapper_argv): New.
> (start_inferior): Handle wrapper_argv. If set, expect an extra
> trap.
> (gdbserver_usage): Document --wrapper.
> (main): Parse --wrapper.
FWIW, I took a look a the GDB code side of it, and it looks good
(my knowledge of gdbserver is very very partial, though).
I think this is a very nice feature!
--
Joel
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFC: Allow a wrapper when starting programs
2008-02-11 20:30 ` Eli Zaretskii
@ 2008-03-10 23:14 ` Daniel Jacobowitz
0 siblings, 0 replies; 12+ messages in thread
From: Daniel Jacobowitz @ 2008-03-10 23:14 UTC (permalink / raw)
To: gdb-patches
On Mon, Feb 11, 2008 at 10:29:52PM +0200, Eli Zaretskii wrote:
> > Date: Mon, 11 Feb 2008 11:14:18 -0500
> > From: Daniel Jacobowitz <drow@false.org>
> >
> > Could you take a look at this version? I've made the descriptions
> > more user-centric and I hope they're clearer now.
>
> Yes, this is much, much better; thanks.
Thanks for your help. Belatedly, checked in.
> I think "any Unix shell script" is more accurate.
(with this change)
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2008-03-10 23:14 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-02-08 18:57 RFC: Allow a wrapper when starting programs Daniel Jacobowitz
2008-02-09 8:48 ` Eli Zaretskii
2008-02-09 15:48 ` Daniel Jacobowitz
2008-02-09 16:41 ` Eli Zaretskii
2008-02-09 16:53 ` Daniel Jacobowitz
2008-02-09 19:20 ` Doug Evans
2008-02-10 1:15 ` Daniel Jacobowitz
2008-02-11 16:14 ` Daniel Jacobowitz
2008-02-11 19:45 ` Daniel Jacobowitz
2008-02-11 20:30 ` Eli Zaretskii
2008-03-10 23:14 ` Daniel Jacobowitz
2008-02-12 19:46 ` Joel Brobecker
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox