mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-21 01:12:32 +08:00
Fix for PR gdb/209, PR gdb/156:
* gdbarch.c, gdbarch.h: Rebuilt. * gdbarch.sh: Added `construct_inferior_arguments'. * cli/cli-decode.h (cmd_list_element): Added pre_show_hook. Typo fix. * cli/cli-setshow.c (do_setshow_command): Call the pre_show_hook. * infcmd.c (_initialize_infcmd): Set sfunc on `set args' command. (inferior_argc, inferior_argv): New globals. (notice_args_set): New function. (set_inferior_args): Clear inferior_argc and inferior_argv. (set_inferior_args_vector): New function. (get_inferior_args): Handle inferior argument vector. (run_command): Use get_inferior_args(). (notice_args_read): New function. (_initialize_infcmd): Don't call set_inferior_args. * command.h: Typo fix. (cmd_list_element): Added pre_show_hook. * main.c (captured_main): Added --args option. (print_gdb_help): Document --args. * inferior.h (construct_inferior_arguments): Declare. (set_inferior_args_vector): Likewise. * fork-child.c (construct_inferior_arguments): New function.
This commit is contained in:
parent
aa26fa3a7e
commit
552c04a742
@ -1,3 +1,28 @@
|
||||
2001-11-21 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
Fix for PR gdb/209, PR gdb/156:
|
||||
* gdbarch.c, gdbarch.h: Rebuilt.
|
||||
* gdbarch.sh: Added `construct_inferior_arguments'.
|
||||
* cli/cli-decode.h (cmd_list_element): Added pre_show_hook.
|
||||
Typo fix.
|
||||
* cli/cli-setshow.c (do_setshow_command): Call the pre_show_hook.
|
||||
* infcmd.c (_initialize_infcmd): Set sfunc on `set args' command.
|
||||
(inferior_argc, inferior_argv): New globals.
|
||||
(notice_args_set): New function.
|
||||
(set_inferior_args): Clear inferior_argc and inferior_argv.
|
||||
(set_inferior_args_vector): New function.
|
||||
(get_inferior_args): Handle inferior argument vector.
|
||||
(run_command): Use get_inferior_args().
|
||||
(notice_args_read): New function.
|
||||
(_initialize_infcmd): Don't call set_inferior_args.
|
||||
* command.h: Typo fix.
|
||||
(cmd_list_element): Added pre_show_hook.
|
||||
* main.c (captured_main): Added --args option.
|
||||
(print_gdb_help): Document --args.
|
||||
* inferior.h (construct_inferior_arguments): Declare.
|
||||
(set_inferior_args_vector): Likewise.
|
||||
* fork-child.c (construct_inferior_arguments): New function.
|
||||
|
||||
2001-11-21 Kevin Buettner <kevinb@redhat.com>
|
||||
|
||||
* lin-lwp.c (lin_lwp_attach_lwp): Make sure SIGCHLD is in set of
|
||||
|
@ -128,7 +128,7 @@ struct cmd_list_element
|
||||
/* If type is not_set_cmd, call it like this: */
|
||||
void (*cfunc) (char *args, int from_tty);
|
||||
|
||||
/* If type is cmd_set or show_cmd, first set the variables, and
|
||||
/* If type is set_cmd or show_cmd, first set the variables, and
|
||||
then call this. */
|
||||
void (*sfunc) (char *args, int from_tty, struct cmd_list_element * c);
|
||||
}
|
||||
@ -166,6 +166,10 @@ struct cmd_list_element
|
||||
/* if this command is deprecated, this is the replacement name */
|
||||
char *replacement;
|
||||
|
||||
/* If this command represents a show command, then this function
|
||||
is called before the variable's value is examined. */
|
||||
void (*pre_show_hook) (struct cmd_list_element *c);
|
||||
|
||||
/* Hook for another command to be executed before this command. */
|
||||
struct cmd_list_element *hook_pre;
|
||||
|
||||
|
@ -267,6 +267,10 @@ do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c)
|
||||
old_chain = make_cleanup_ui_out_stream_delete (stb);
|
||||
#endif /* UI_OUT */
|
||||
|
||||
/* Possibly call the pre hook. */
|
||||
if (c->pre_show_hook)
|
||||
(c->pre_show_hook) (c);
|
||||
|
||||
/* Print doc minus "show" at start. */
|
||||
print_doc_line (gdb_stdout, c->doc + 5);
|
||||
|
||||
|
@ -134,7 +134,7 @@ struct cmd_list_element
|
||||
/* If type is not_set_cmd, call it like this: */
|
||||
void (*cfunc) (char *args, int from_tty);
|
||||
|
||||
/* If type is cmd_set or show_cmd, first set the variables, and
|
||||
/* If type is set_cmd or show_cmd, first set the variables, and
|
||||
then call this. */
|
||||
void (*sfunc) (char *args, int from_tty, struct cmd_list_element * c);
|
||||
}
|
||||
@ -172,6 +172,10 @@ struct cmd_list_element
|
||||
/* if this command is deprecated, this is the replacement name */
|
||||
char *replacement;
|
||||
|
||||
/* If this command represents a show command, then this function
|
||||
is called before the variable's value is examined. */
|
||||
void (*pre_show_hook) (struct cmd_list_element *c);
|
||||
|
||||
/* Hook for another command to be executed before this command. */
|
||||
struct cmd_list_element *hook_pre;
|
||||
|
||||
|
@ -568,3 +568,74 @@ startup_inferior (int ntraps)
|
||||
#endif /* STARTUP_INFERIOR */
|
||||
stop_soon_quietly = 0;
|
||||
}
|
||||
|
||||
/* Compute command-line string given argument vector. This does the
|
||||
same shell processing as fork_inferior. */
|
||||
/* ARGSUSED */
|
||||
char *
|
||||
construct_inferior_arguments (struct gdbarch *gdbarch, int argc, char **argv)
|
||||
{
|
||||
char *result;
|
||||
|
||||
if (STARTUP_WITH_SHELL)
|
||||
{
|
||||
/* This holds all the characters considered special to the
|
||||
typical Unix shells. We include `^' because the SunOS
|
||||
/bin/sh treats it as a synonym for `|'. */
|
||||
char *special = "\"!#$&*()\\|[]{}<>?'\"`~^; \t\n";
|
||||
int i;
|
||||
int length = 0;
|
||||
char *out, *cp;
|
||||
|
||||
/* We over-compute the size. It shouldn't matter. */
|
||||
for (i = 0; i < argc; ++i)
|
||||
length += 2 * strlen (argv[i]) + 1;
|
||||
|
||||
result = (char *) xmalloc (length);
|
||||
out = result;
|
||||
|
||||
for (i = 0; i < argc; ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
*out++ = ' ';
|
||||
|
||||
for (cp = argv[i]; *cp; ++cp)
|
||||
{
|
||||
if (strchr (special, *cp) != NULL)
|
||||
*out++ = '\\';
|
||||
*out++ = *cp;
|
||||
}
|
||||
}
|
||||
*out = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
/* In this case we can't handle arguments that contain spaces,
|
||||
tabs, or newlines -- see breakup_args(). */
|
||||
int i;
|
||||
int length = 0;
|
||||
|
||||
for (i = 0; i < argc; ++i)
|
||||
{
|
||||
char *cp = strchr (argv[i], ' ');
|
||||
if (cp == NULL)
|
||||
cp = strchr (argv[i], '\t');
|
||||
if (cp == NULL)
|
||||
cp = strchr (argv[i], '\n');
|
||||
if (cp != NULL)
|
||||
error ("can't handle command-line argument containing whitespace");
|
||||
length += strlen (argv[i]) + 1;
|
||||
}
|
||||
|
||||
result = (char *) xmalloc (length);
|
||||
result[0] = '\0';
|
||||
for (i = 0; i < argc; ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
strcat (result, " ");
|
||||
strcat (result, argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -255,6 +255,7 @@ struct gdbarch
|
||||
gdbarch_skip_trampoline_code_ftype *skip_trampoline_code;
|
||||
gdbarch_in_solib_call_trampoline_ftype *in_solib_call_trampoline;
|
||||
gdbarch_in_function_epilogue_p_ftype *in_function_epilogue_p;
|
||||
gdbarch_construct_inferior_arguments_ftype *construct_inferior_arguments;
|
||||
};
|
||||
|
||||
|
||||
@ -394,6 +395,7 @@ struct gdbarch startup_gdbarch =
|
||||
0,
|
||||
0,
|
||||
generic_in_function_epilogue_p,
|
||||
construct_inferior_arguments,
|
||||
/* startup_gdbarch() */
|
||||
};
|
||||
|
||||
@ -504,6 +506,7 @@ gdbarch_alloc (const struct gdbarch_info *info,
|
||||
current_gdbarch->skip_trampoline_code = generic_skip_trampoline_code;
|
||||
current_gdbarch->in_solib_call_trampoline = generic_in_solib_call_trampoline;
|
||||
current_gdbarch->in_function_epilogue_p = generic_in_function_epilogue_p;
|
||||
current_gdbarch->construct_inferior_arguments = construct_inferior_arguments;
|
||||
/* gdbarch_alloc() */
|
||||
|
||||
return current_gdbarch;
|
||||
@ -755,6 +758,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
|
||||
/* Skip verify of skip_trampoline_code, invalid_p == 0 */
|
||||
/* Skip verify of in_solib_call_trampoline, invalid_p == 0 */
|
||||
/* Skip verify of in_function_epilogue_p, invalid_p == 0 */
|
||||
/* Skip verify of construct_inferior_arguments, invalid_p == 0 */
|
||||
buf = ui_file_xstrdup (log, &dummy);
|
||||
make_cleanup (xfree, buf);
|
||||
if (strlen (buf) > 0)
|
||||
@ -962,6 +966,10 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
|
||||
(long) current_gdbarch->coerce_float_to_double
|
||||
/*COERCE_FLOAT_TO_DOUBLE ()*/);
|
||||
#endif
|
||||
if (GDB_MULTI_ARCH)
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: construct_inferior_arguments = 0x%08lx\n",
|
||||
(long) current_gdbarch->construct_inferior_arguments);
|
||||
#ifdef CONVERT_FROM_FUNC_PTR_ADDR
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: %s # %s\n",
|
||||
@ -4270,6 +4278,24 @@ set_gdbarch_in_function_epilogue_p (struct gdbarch *gdbarch,
|
||||
gdbarch->in_function_epilogue_p = in_function_epilogue_p;
|
||||
}
|
||||
|
||||
char *
|
||||
gdbarch_construct_inferior_arguments (struct gdbarch *gdbarch, int argc, char **argv)
|
||||
{
|
||||
if (gdbarch->construct_inferior_arguments == 0)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"gdbarch: gdbarch_construct_inferior_arguments invalid");
|
||||
if (gdbarch_debug >= 2)
|
||||
fprintf_unfiltered (gdb_stdlog, "gdbarch_construct_inferior_arguments called\n");
|
||||
return gdbarch->construct_inferior_arguments (gdbarch, argc, argv);
|
||||
}
|
||||
|
||||
void
|
||||
set_gdbarch_construct_inferior_arguments (struct gdbarch *gdbarch,
|
||||
gdbarch_construct_inferior_arguments_ftype construct_inferior_arguments)
|
||||
{
|
||||
gdbarch->construct_inferior_arguments = construct_inferior_arguments;
|
||||
}
|
||||
|
||||
|
||||
/* Keep a registry of per-architecture data-pointers required by GDB
|
||||
modules. */
|
||||
|
@ -2113,6 +2113,19 @@ typedef int (gdbarch_in_function_epilogue_p_ftype) (struct gdbarch *gdbarch, COR
|
||||
extern int gdbarch_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR addr);
|
||||
extern void set_gdbarch_in_function_epilogue_p (struct gdbarch *gdbarch, gdbarch_in_function_epilogue_p_ftype *in_function_epilogue_p);
|
||||
|
||||
/* Given a vector of command-line arguments, return a newly allocated
|
||||
string which, when passed to the create_inferior function, will be
|
||||
parsed (on Unix systems, by the shell) to yield the same vector.
|
||||
This function should call error() if the argument vector is not
|
||||
representable for this target or if this target does not support
|
||||
command-line arguments.
|
||||
ARGC is the number of elements in the vector.
|
||||
ARGV is an array of strings, one per argument. */
|
||||
|
||||
typedef char * (gdbarch_construct_inferior_arguments_ftype) (struct gdbarch *gdbarch, int argc, char **argv);
|
||||
extern char * gdbarch_construct_inferior_arguments (struct gdbarch *gdbarch, int argc, char **argv);
|
||||
extern void set_gdbarch_construct_inferior_arguments (struct gdbarch *gdbarch, gdbarch_construct_inferior_arguments_ftype *construct_inferior_arguments);
|
||||
|
||||
extern struct gdbarch_tdep *gdbarch_tdep (struct gdbarch *gdbarch);
|
||||
|
||||
|
||||
|
@ -560,6 +560,15 @@ f:2:IN_SOLIB_CALL_TRAMPOLINE:int:in_solib_call_trampoline:CORE_ADDR pc, char *na
|
||||
# which don't suffer from that problem could just let this functionality
|
||||
# untouched.
|
||||
m:::int:in_function_epilogue_p:CORE_ADDR addr:addr::0:generic_in_function_epilogue_p::0
|
||||
# Given a vector of command-line arguments, return a newly allocated
|
||||
# string which, when passed to the create_inferior function, will be
|
||||
# parsed (on Unix systems, by the shell) to yield the same vector.
|
||||
# This function should call error() if the argument vector is not
|
||||
# representable for this target or if this target does not support
|
||||
# command-line arguments.
|
||||
# ARGC is the number of elements in the vector.
|
||||
# ARGV is an array of strings, one per argument.
|
||||
m::CONSTRUCT_INFERIOR_ARGUMENTS:char *:construct_inferior_arguments:int argc, char **argv:argc, argv:::construct_inferior_arguments::0
|
||||
EOF
|
||||
}
|
||||
|
||||
|
63
gdb/infcmd.c
63
gdb/infcmd.c
@ -123,6 +123,12 @@ static void breakpoint_auto_delete_contents (PTR);
|
||||
|
||||
static char *inferior_args;
|
||||
|
||||
/* The inferior arguments as a vector. If INFERIOR_ARGC is nonzero,
|
||||
then we must compute INFERIOR_ARGS from this (via the target). */
|
||||
|
||||
static int inferior_argc;
|
||||
static char **inferior_argv;
|
||||
|
||||
/* File name for default use for standard in/out in the inferior. */
|
||||
|
||||
char *inferior_io_terminal;
|
||||
@ -199,6 +205,19 @@ struct environ *inferior_environ;
|
||||
char *
|
||||
get_inferior_args (void)
|
||||
{
|
||||
if (inferior_argc != 0)
|
||||
{
|
||||
char *n, *old;
|
||||
|
||||
n = gdbarch_construct_inferior_arguments (current_gdbarch,
|
||||
inferior_argc, inferior_argv);
|
||||
old = set_inferior_args (n);
|
||||
xfree (old);
|
||||
}
|
||||
|
||||
if (inferior_args == NULL)
|
||||
inferior_args = xstrdup ("");
|
||||
|
||||
return inferior_args;
|
||||
}
|
||||
|
||||
@ -208,10 +227,37 @@ set_inferior_args (char *newargs)
|
||||
char *saved_args = inferior_args;
|
||||
|
||||
inferior_args = newargs;
|
||||
inferior_argc = 0;
|
||||
inferior_argv = 0;
|
||||
|
||||
return saved_args;
|
||||
}
|
||||
|
||||
void
|
||||
set_inferior_args_vector (int argc, char **argv)
|
||||
{
|
||||
inferior_argc = argc;
|
||||
inferior_argv = argv;
|
||||
}
|
||||
|
||||
/* Notice when `set args' is run. */
|
||||
static void
|
||||
notice_args_set (char *args, int from_tty, struct cmd_list_element *c)
|
||||
{
|
||||
inferior_argc = 0;
|
||||
inferior_argv = 0;
|
||||
}
|
||||
|
||||
/* Notice when `show args' is run. */
|
||||
static void
|
||||
notice_args_read (struct cmd_list_element *c)
|
||||
{
|
||||
/* Might compute the value. */
|
||||
get_inferior_args ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This function detects whether or not a '&' character (indicating
|
||||
background execution) has been added as *the last* of the arguments ARGS
|
||||
of a command. If it has, it removes it and returns 1. Otherwise it
|
||||
@ -331,7 +377,9 @@ Start it from the beginning? "))
|
||||
if (exec_file)
|
||||
ui_out_field_string (uiout, "execfile", exec_file);
|
||||
ui_out_spaces (uiout, 1);
|
||||
ui_out_field_string (uiout, "infargs", inferior_args);
|
||||
/* We call get_inferior_args() because we might need to compute
|
||||
the value now. */
|
||||
ui_out_field_string (uiout, "infargs", get_inferior_args ());
|
||||
ui_out_text (uiout, "\n");
|
||||
ui_out_flush (uiout);
|
||||
#else
|
||||
@ -339,13 +387,17 @@ Start it from the beginning? "))
|
||||
if (exec_file)
|
||||
puts_filtered (exec_file);
|
||||
puts_filtered (" ");
|
||||
puts_filtered (inferior_args);
|
||||
/* We call get_inferior_args() because we might need to compute
|
||||
the value now. */
|
||||
puts_filtered (get_inferior_args ());
|
||||
puts_filtered ("\n");
|
||||
gdb_flush (gdb_stdout);
|
||||
#endif
|
||||
}
|
||||
|
||||
target_create_inferior (exec_file, inferior_args,
|
||||
/* We call get_inferior_args() because we might need to compute
|
||||
the value now. */
|
||||
target_create_inferior (exec_file, get_inferior_args (),
|
||||
environ_vector (inferior_environ));
|
||||
}
|
||||
|
||||
@ -1785,8 +1837,10 @@ _initialize_infcmd (void)
|
||||
"Set argument list to give program being debugged when it is started.\n\
|
||||
Follow this command with any number of args, to be passed to the program.",
|
||||
&setlist);
|
||||
add_show_from_set (c, &showlist);
|
||||
c->completer = filename_completer;
|
||||
c->function.sfunc = notice_args_set;
|
||||
c = add_show_from_set (c, &showlist);
|
||||
c->pre_show_hook = notice_args_read;
|
||||
|
||||
c = add_cmd
|
||||
("environment", no_class, environment_info,
|
||||
@ -1952,7 +2006,6 @@ Register name as argument means describe only that register.");
|
||||
add_info ("float", float_info,
|
||||
"Print the status of the floating point unit\n");
|
||||
|
||||
set_inferior_args (xstrdup ("")); /* Initially no args */
|
||||
inferior_environ = make_environ ();
|
||||
init_environ (inferior_environ);
|
||||
}
|
||||
|
@ -270,6 +270,8 @@ extern void clone_and_follow_inferior (int, int *);
|
||||
|
||||
extern void startup_inferior (int);
|
||||
|
||||
extern char *construct_inferior_arguments (struct gdbarch *, int, char **);
|
||||
|
||||
/* From inflow.c */
|
||||
|
||||
extern void new_tty_prefork (char *);
|
||||
@ -307,6 +309,8 @@ extern char *get_inferior_args (void);
|
||||
|
||||
extern char *set_inferior_args (char *);
|
||||
|
||||
extern void set_inferior_args_vector (int, char **);
|
||||
|
||||
/* Last signal that the inferior received (why it stopped). */
|
||||
|
||||
extern enum target_signal stop_signal;
|
||||
|
69
gdb/main.c
69
gdb/main.c
@ -124,6 +124,7 @@ captured_main (void *data)
|
||||
int count;
|
||||
static int quiet = 0;
|
||||
static int batch = 0;
|
||||
static int set_args = 0;
|
||||
|
||||
/* Pointers to various arguments from command line. */
|
||||
char *symarg = NULL;
|
||||
@ -263,6 +264,7 @@ captured_main (void *data)
|
||||
{"windows", no_argument, &use_windows, 1},
|
||||
{"statistics", no_argument, 0, 13},
|
||||
{"write", no_argument, &write_files, 1},
|
||||
{"args", no_argument, &set_args, 1},
|
||||
/* Allow machine descriptions to add more options... */
|
||||
#ifdef ADDITIONAL_OPTIONS
|
||||
ADDITIONAL_OPTIONS
|
||||
@ -276,7 +278,7 @@ captured_main (void *data)
|
||||
|
||||
c = getopt_long_only (argc, argv, "",
|
||||
long_options, &option_index);
|
||||
if (c == EOF)
|
||||
if (c == EOF || set_args)
|
||||
break;
|
||||
|
||||
/* Long option that takes an argument. */
|
||||
@ -432,25 +434,46 @@ extern int gdbtk_test (char *);
|
||||
use_windows = 0;
|
||||
#endif
|
||||
|
||||
/* OK, that's all the options. The other arguments are filenames. */
|
||||
count = 0;
|
||||
for (; optind < argc; optind++)
|
||||
switch (++count)
|
||||
{
|
||||
case 1:
|
||||
symarg = argv[optind];
|
||||
execarg = argv[optind];
|
||||
break;
|
||||
case 2:
|
||||
/* FIXME: The documentation says this can be a "ProcID". as well. */
|
||||
corearg = argv[optind];
|
||||
break;
|
||||
case 3:
|
||||
fprintf_unfiltered (gdb_stderr,
|
||||
"Excess command line arguments ignored. (%s%s)\n",
|
||||
argv[optind], (optind == argc - 1) ? "" : " ...");
|
||||
break;
|
||||
}
|
||||
if (set_args)
|
||||
{
|
||||
/* The remaining options are the command-line options for the
|
||||
inferior. The first one is the sym/exec file, and the rest
|
||||
are arguments. */
|
||||
if (optind >= argc)
|
||||
{
|
||||
fprintf_unfiltered (gdb_stderr,
|
||||
"%s: `--args' specified but no program specified\n",
|
||||
argv[0]);
|
||||
exit (1);
|
||||
}
|
||||
symarg = argv[optind];
|
||||
execarg = argv[optind];
|
||||
++optind;
|
||||
set_inferior_args_vector (argc - optind, &argv[optind]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* OK, that's all the options. The other arguments are filenames. */
|
||||
count = 0;
|
||||
for (; optind < argc; optind++)
|
||||
switch (++count)
|
||||
{
|
||||
case 1:
|
||||
symarg = argv[optind];
|
||||
execarg = argv[optind];
|
||||
break;
|
||||
case 2:
|
||||
/* FIXME: The documentation says this can be a
|
||||
"ProcID". as well. */
|
||||
corearg = argv[optind];
|
||||
break;
|
||||
case 3:
|
||||
fprintf_unfiltered (gdb_stderr,
|
||||
"Excess command line arguments ignored. (%s%s)\n",
|
||||
argv[optind], (optind == argc - 1) ? "" : " ...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (batch)
|
||||
quiet = 1;
|
||||
}
|
||||
@ -713,8 +736,12 @@ print_gdb_help (struct ui_file *stream)
|
||||
{
|
||||
fputs_unfiltered ("\
|
||||
This is the GNU debugger. Usage:\n\n\
|
||||
gdb [options] [executable-file [core-file or process-id]]\n\n\
|
||||
gdb [options] [executable-file [core-file or process-id]]\n\
|
||||
gdb [options] --args executable-file [inferior-arguments ...]\n\n\
|
||||
Options:\n\n\
|
||||
", stream);
|
||||
fputs_unfiltered ("\
|
||||
--args Arguments after executable-file are passed to inferior\n\
|
||||
", stream);
|
||||
fputs_unfiltered ("\
|
||||
--[no]async Enable (disable) asynchronous version of CLI\n\
|
||||
|
Loading…
Reference in New Issue
Block a user