* 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.
This commit is contained in:
parent
42e344a77c
commit
ccd213ac7e
8 changed files with 201 additions and 10 deletions
|
@ -1,4 +1,14 @@
|
||||||
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
|
* source.c (directory_command): Modify the determination of
|
||||||
condition of terminal "from_tty".
|
condition of terminal "from_tty".
|
||||||
|
|
|
@ -2110,7 +2110,7 @@ f-lang.o: f-lang.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
|
||||||
$(valprint_h) $(value_h)
|
$(valprint_h) $(value_h)
|
||||||
fork-child.o: fork-child.c $(defs_h) $(gdb_string_h) $(frame_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) \
|
$(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) \
|
frame-base.o: frame-base.c $(defs_h) $(frame_base_h) $(frame_h) \
|
||||||
$(gdb_obstack_h)
|
$(gdb_obstack_h)
|
||||||
frame.o: frame.c $(defs_h) $(frame_h) $(target_h) $(value_h) $(inferior_h) \
|
frame.o: frame.c $(defs_h) $(frame_h) $(target_h) $(value_h) $(inferior_h) \
|
||||||
|
|
14
gdb/NEWS
14
gdb/NEWS
|
@ -3,14 +3,24 @@
|
||||||
|
|
||||||
*** Changes since GDB 6.8
|
*** 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
|
* New commands
|
||||||
|
|
||||||
set debug timetstamp
|
set debug timetstamp
|
||||||
show debug timestamp
|
show debug timestamp
|
||||||
Display timestamps with GDB debugging output.
|
Display timestamps with GDB debugging output.
|
||||||
|
|
||||||
* Watchpoints can now be set on unreadable memory locations, e.g. addresses
|
set exec-wrapper
|
||||||
which will be allocated using malloc later in program execution.
|
show exec-wrapper
|
||||||
|
unset exec-wrapper
|
||||||
|
Use a wrapper program to launch programs for debugging.
|
||||||
|
|
||||||
*** Changes in GDB 6.8
|
*** Changes in GDB 6.8
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,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>
|
2008-03-03 Daniel Jacobowitz <dan@codesourcery.com>
|
||||||
|
|
||||||
* gdb.texinfo (Set Watchpoints): Mention watchpoints on
|
* gdb.texinfo (Set Watchpoints): Mention watchpoints on
|
||||||
|
|
|
@ -1921,6 +1921,36 @@ these cases, using the @code{start} command would stop the execution of
|
||||||
your program too late, as the program would have already completed the
|
your program too late, as the program would have already completed the
|
||||||
elaboration phase. Under these circumstances, insert breakpoints in your
|
elaboration phase. Under these circumstances, insert breakpoints in your
|
||||||
elaboration code before running your program.
|
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
|
@end table
|
||||||
|
|
||||||
@node Arguments
|
@node Arguments
|
||||||
|
@ -13083,6 +13113,29 @@ You can include @option{--debug} on the @code{gdbserver} command line.
|
||||||
process. This option is intended for @code{gdbserver} development and
|
process. This option is intended for @code{gdbserver} development and
|
||||||
for bug reports to the developers.
|
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}
|
@subsection Connecting to @code{gdbserver}
|
||||||
|
|
||||||
Run @value{GDBN} on the host system.
|
Run @value{GDBN} on the host system.
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
#include "gdbthread.h"
|
#include "gdbthread.h"
|
||||||
#include "command.h" /* for dont_repeat () */
|
#include "command.h" /* for dont_repeat () */
|
||||||
|
#include "gdbcmd.h"
|
||||||
#include "solib.h"
|
#include "solib.h"
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
@ -40,6 +41,8 @@
|
||||||
|
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
|
|
||||||
|
static char *exec_wrapper;
|
||||||
|
|
||||||
/* Break up SCRATCH into an argument vector suitable for passing to
|
/* 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
|
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
|
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 *allargs, char **env,
|
||||||
fact that it may expand when quoted; it is a worst-case number
|
fact that it may expand when quoted; it is a worst-case number
|
||||||
based on every character being '. */
|
based on every character being '. */
|
||||||
len = 5 + 4 * strlen (exec_file) + 1 + strlen (allargs) + 1 + /*slop */ 12;
|
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 = (char *) alloca (len);
|
||||||
shell_command[0] = '\0';
|
shell_command[0] = '\0';
|
||||||
|
|
||||||
|
@ -178,14 +184,22 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
|
||||||
{
|
{
|
||||||
/* We're going to call a shell. */
|
/* We're going to call a shell. */
|
||||||
|
|
||||||
/* Now add exec_file, quoting as necessary. */
|
|
||||||
|
|
||||||
char *p;
|
char *p;
|
||||||
int need_to_quote;
|
int need_to_quote;
|
||||||
const int escape_bang = escape_bang_in_quoted_argument (shell_file);
|
const int escape_bang = escape_bang_in_quoted_argument (shell_file);
|
||||||
|
|
||||||
strcat (shell_command, "exec ");
|
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
|
/* 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
|
csh on IRIX 4.0.1 can't deal with it. So we only quote it if
|
||||||
we need to. */
|
we need to. */
|
||||||
|
@ -399,6 +413,9 @@ startup_inferior (int ntraps)
|
||||||
have stopped one instruction after execing the shell. Here we
|
have stopped one instruction after execing the shell. Here we
|
||||||
must get it up to actual execution of the real program. */
|
must get it up to actual execution of the real program. */
|
||||||
|
|
||||||
|
if (exec_wrapper)
|
||||||
|
pending_execs++;
|
||||||
|
|
||||||
clear_proceed_status ();
|
clear_proceed_status ();
|
||||||
|
|
||||||
init_wait_for_inferior ();
|
init_wait_for_inferior ();
|
||||||
|
@ -446,3 +463,28 @@ startup_inferior (int ntraps)
|
||||||
}
|
}
|
||||||
stop_soon = NO_STOP_QUIETLY;
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
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>
|
2008-02-28 Ulrich Weigand <uweigand@de.ibm.com>
|
||||||
|
|
||||||
* configure.srv [powerpc64-*-linux*]: Add all files mentioned for
|
* configure.srv [powerpc64-*-linux*]: Add all files mentioned for
|
||||||
|
|
|
@ -41,7 +41,7 @@ static int attached;
|
||||||
static int response_needed;
|
static int response_needed;
|
||||||
static int exit_requested;
|
static int exit_requested;
|
||||||
|
|
||||||
static char **program_argv;
|
static char **program_argv, **wrapper_argv;
|
||||||
|
|
||||||
/* Enable miscellaneous debugging output. The name is historical - it
|
/* Enable miscellaneous debugging output. The name is historical - it
|
||||||
was originally used to debug LinuxThreads support. */
|
was originally used to debug LinuxThreads support. */
|
||||||
|
@ -83,16 +83,34 @@ target_running (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
start_inferior (char *argv[], char *statusptr)
|
start_inferior (char **argv, char *statusptr)
|
||||||
{
|
{
|
||||||
|
char **new_argv = argv;
|
||||||
attached = 0;
|
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
|
#ifdef SIGTTOU
|
||||||
signal (SIGTTOU, SIG_DFL);
|
signal (SIGTTOU, SIG_DFL);
|
||||||
signal (SIGTTIN, SIG_DFL);
|
signal (SIGTTIN, SIG_DFL);
|
||||||
#endif
|
#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
|
/* FIXME: we don't actually know at this point that the create
|
||||||
actually succeeded. We won't know that until we wait. */
|
actually succeeded. We won't know that until we wait. */
|
||||||
|
@ -109,6 +127,33 @@ start_inferior (char *argv[], char *statusptr)
|
||||||
atexit (restore_old_foreground_pgrp);
|
atexit (restore_old_foreground_pgrp);
|
||||||
#endif
|
#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
|
/* Wait till we are at 1st instruction in program, return signal
|
||||||
number (assuming success). */
|
number (assuming success). */
|
||||||
return mywait (statusptr, 0);
|
return mywait (statusptr, 0);
|
||||||
|
@ -1002,7 +1047,8 @@ gdbserver_usage (void)
|
||||||
"HOST:PORT to listen for a TCP connection.\n"
|
"HOST:PORT to listen for a TCP connection.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Options:\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
|
#undef require_running
|
||||||
|
@ -1046,6 +1092,23 @@ main (int argc, char *argv[])
|
||||||
attach = 1;
|
attach = 1;
|
||||||
else if (strcmp (*next_arg, "--multi") == 0)
|
else if (strcmp (*next_arg, "--multi") == 0)
|
||||||
multi_mode = 1;
|
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)
|
else if (strcmp (*next_arg, "--debug") == 0)
|
||||||
debug_threads = 1;
|
debug_threads = 1;
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in a new issue