-2008-03-06 Hidetaka Takano <hidetaka.takano@glb.toshiba.co.jp>
+2008-03-10 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.
+
+2008-03-10 Hidetaka Takano <hidetaka.takano@glb.toshiba.co.jp>
* source.c (directory_command): Modify the determination of
condition of terminal "from_tty".
$(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) \
*** Changes since GDB 6.8
+* Watchpoints can now be set on unreadable memory locations, e.g. addresses
+which will be allocated using malloc later in program execution.
+
+* New features in the GDB remote stub, gdbserver
+
+ - The "--wrapper" command-line argument tells gdbserver to use a
+ wrapper program to launch programs for debugging.
+
* New commands
set debug timetstamp
show debug timestamp
Display timestamps with GDB debugging output.
-* Watchpoints can now be set on unreadable memory locations, e.g. addresses
-which will be allocated using malloc later in program execution.
+set exec-wrapper
+show exec-wrapper
+unset exec-wrapper
+ Use a wrapper program to launch programs for debugging.
*** Changes in GDB 6.8
+2008-03-10 Daniel Jacobowitz <dan@codesourcery.com>
+
+ * gdb.texinfo (Starting): Document "set exec-wrapper".
+ (Server): Document gdbserver --wrapper.
+
2008-03-03 Daniel Jacobowitz <dan@codesourcery.com>
* gdb.texinfo (Set Watchpoints): Mention watchpoints on
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 that eventually calls @code{execve} with
+its arguments as a wrapper. Several standard Unix utilities do
+this, e.g.@: @code{env} and @code{nohup}. Any Unix 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
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 that eventually calls @code{execve} with
+its arguments as a wrapper. Several standard Unix utilities do
+this, e.g.@: @code{env} and @code{nohup}. Any Unix 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.
#include "terminal.h"
#include "gdbthread.h"
#include "command.h" /* for dont_repeat () */
+#include "gdbcmd.h"
#include "solib.h"
#include <signal.h>
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
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';
{
/* 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. */
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 ();
}
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);
+}
+2008-03-10 Daniel Jacobowitz <dan@codesourcery.com>
+
+ * server.c (wrapper_argv): New.
+ (start_inferior): Handle wrapper_argv. If set, expect an extra
+ trap.
+ (gdbserver_usage): Document --wrapper.
+ (main): Parse --wrapper.
+
2008-02-28 Ulrich Weigand <uweigand@de.ibm.com>
* configure.srv [powerpc64-*-linux*]: Add all files mentioned for
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. */
}
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. */
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);
"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
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