/* Top level stuff for GDB, the GNU debugger.
- Copyright (C) 1986-2014 Free Software Foundation, Inc.
+ Copyright (C) 1986-2017 Free Software Foundation, Inc.
This file is part of GDB.
#include "inferior.h"
#include "symfile.h"
#include "gdbcore.h"
-
-#include "exceptions.h"
#include "getopt.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
-
-#include <string.h>
#include "event-loop.h"
#include "ui-out.h"
#include "filestuff.h"
#include <signal.h>
#include "event-top.h"
+#include "infrun.h"
+#include "signals-state-save-restore.h"
+#include <vector>
/* The selected interpreter. This will be used as a set command
variable, so it should always be malloc'ed - since
do_setshow_command will free it. */
char *interpreter_p;
-/* Whether xdb commands will be handled. */
-int xdb_commands = 0;
-
/* Whether dbx commands will be handled. */
int dbx_commands = 0;
the possibly relocated path to python's lib directory. */
char *python_libdir = 0;
-struct ui_file *gdb_stdout;
-struct ui_file *gdb_stderr;
-struct ui_file *gdb_stdlog;
-struct ui_file *gdb_stdin;
/* Target IO streams. */
struct ui_file *gdb_stdtargin;
struct ui_file *gdb_stdtarg;
for (p = tmp_sys_gdbinit; IS_DIR_SEPARATOR (*p); ++p)
continue;
relocated_sysgdbinit = concat (gdb_datadir, SLASH_STRING, p,
- NULL);
+ (char *) NULL);
xfree (tmp_sys_gdbinit);
}
else
#ifdef HAVE_SIGALTSTACK
stack_t ss;
- ss.ss_sp = xmalloc (SIGSTKSZ);
+ /* FreeBSD versions older than 11.0 use char * for ss_sp instead of
+ void *. This cast works with both types. */
+ ss.ss_sp = (char *) xmalloc (SIGSTKSZ);
ss.ss_size = SIGSTKSZ;
ss.ss_flags = 0;
static int
captured_command_loop (void *data)
{
+ struct ui *ui = current_ui;
+
/* Top-level execution commands can be run in the background from
here on. */
- interpreter_async = 1;
+ current_ui->async = 1;
+
+ /* Give the interpreter a chance to print a prompt, if necessary */
+ if (ui->prompt_state != PROMPT_BLOCKED)
+ interp_pre_command_loop (top_level_interpreter ());
+
+ /* Now it's time to start the event loop. */
+ start_event_loop ();
- current_interp_command_loop ();
/* FIXME: cagney/1999-11-05: A correct command_loop() implementaton
would clean things up (restoring the cleanup chain) to the state
they were just prior to the call. Technically, this means that
error) we try to quit. If the quit is aborted, catch_errors()
which called this catch the signal and restart the command
loop. */
- quit_command (NULL, instream == stdin);
+ quit_command (NULL, ui->instream == ui->stdin_stream);
return 1;
}
catch_command_errors/catch_command_errors_const. */
static int
-handle_command_errors (volatile struct gdb_exception e)
+handle_command_errors (struct gdb_exception e)
{
if (e.reason < 0)
{
static int
catch_command_errors (catch_command_errors_ftype *command,
- char *arg, int from_tty, return_mask mask)
+ char *arg, int from_tty)
{
- volatile struct gdb_exception e;
-
- TRY_CATCH (e, mask)
+ TRY
{
+ int was_sync = current_ui->prompt_state == PROMPT_BLOCKED;
+
command (arg, from_tty);
+
+ maybe_wait_sync_command_done (was_sync);
}
- return handle_command_errors (e);
+ CATCH (e, RETURN_MASK_ALL)
+ {
+ return handle_command_errors (e);
+ }
+ END_CATCH
+
+ return 1;
}
/* Type of the command callback passed to catch_command_errors_const. */
static int
catch_command_errors_const (catch_command_errors_const_ftype *command,
- const char *arg, int from_tty, return_mask mask)
+ const char *arg, int from_tty)
{
- volatile struct gdb_exception e;
-
- TRY_CATCH (e, mask)
+ TRY
{
+ int was_sync = current_ui->prompt_state == PROMPT_BLOCKED;
+
command (arg, from_tty);
+
+ maybe_wait_sync_command_done (was_sync);
+ }
+ CATCH (e, RETURN_MASK_ALL)
+ {
+ return handle_command_errors (e);
}
- return handle_command_errors (e);
+ END_CATCH
+
+ return 1;
}
-/* Arguments of --command option and its counterpart. */
-typedef struct cmdarg {
- /* Type of this option. */
- enum {
- /* Option type -x. */
- CMDARG_FILE,
+/* Adapter for symbol_file_add_main that translates 'from_tty' to a
+ symfile_add_flags. */
- /* Option type -ex. */
- CMDARG_COMMAND,
+static void
+symbol_file_add_main_adapter (const char *arg, int from_tty)
+{
+ symfile_add_flags add_flags = 0;
- /* Option type -ix. */
- CMDARG_INIT_FILE,
+ if (from_tty)
+ add_flags |= SYMFILE_VERBOSE;
+
+ symbol_file_add_main (arg, add_flags);
+}
+
+/* Type of this option. */
+enum cmdarg_kind
+{
+ /* Option type -x. */
+ CMDARG_FILE,
+
+ /* Option type -ex. */
+ CMDARG_COMMAND,
+
+ /* Option type -ix. */
+ CMDARG_INIT_FILE,
- /* Option type -iex. */
- CMDARG_INIT_COMMAND
- } type;
+ /* Option type -iex. */
+ CMDARG_INIT_COMMAND
+};
+
+/* Arguments of --command option and its counterpart. */
+struct cmdarg
+{
+ cmdarg (cmdarg_kind type_, char *string_)
+ : type (type_), string (string_)
+ {}
+
+ /* Type of this option. */
+ enum cmdarg_kind type;
/* Value of this option - filename or the GDB command itself. String memory
is not owned by this structure despite it is 'const'. */
char *string;
-} cmdarg_s;
-
-/* Define type VEC (cmdarg_s). */
-DEF_VEC_O (cmdarg_s);
+};
-static int
-captured_main (void *data)
+static void
+captured_main_1 (struct captured_main_args *context)
{
- struct captured_main_args *context = data;
int argc = context->argc;
char **argv = context->argv;
+
static int quiet = 0;
static int set_args = 0;
static int inhibit_home_gdbinit = 0;
static int print_configuration;
/* Pointers to all arguments of --command option. */
- VEC (cmdarg_s) *cmdarg_vec = NULL;
- struct cmdarg *cmdarg_p;
+ std::vector<struct cmdarg> cmdarg_vec;
- /* Indices of all arguments of --directory option. */
- char **dirarg;
- /* Allocated size. */
- int dirsize;
- /* Number of elements used. */
- int ndir;
+ /* All arguments of --directory option. */
+ std::vector<char *> dirarg;
/* gdb init files. */
const char *system_gdbinit;
int save_auto_load;
struct objfile *objfile;
- struct cleanup *pre_stat_chain;
+ struct cleanup *chain;
#ifdef HAVE_SBRK
- /* Set this before calling make_command_stats_cleanup. */
+ /* Set this before constructing scoped_command_stats. */
lim_at_start = (char *) sbrk (0);
#endif
- pre_stat_chain = make_command_stats_cleanup (0);
+ scoped_command_stats stat_reporter (false);
#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
setlocale (LC_MESSAGES, "");
#if defined (HAVE_SETLOCALE)
setlocale (LC_CTYPE, "");
#endif
+#ifdef ENABLE_NLS
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
+#endif
bfd_init ();
notice_open_fds ();
+ save_original_signals_state ();
- make_cleanup (VEC_cleanup (cmdarg_s), &cmdarg_vec);
- dirsize = 1;
- dirarg = (char **) xmalloc (dirsize * sizeof (*dirarg));
- ndir = 0;
-
- clear_quit_flag ();
- saved_command_line = (char *) xmalloc (saved_command_line_size);
- saved_command_line[0] = '\0';
- instream = stdin;
+ saved_command_line = (char *) xstrdup ("");
#ifdef __MINGW32__
/* Ensure stderr is unbuffered. A Cygwin pty or pipe is implemented
setvbuf (stderr, NULL, _IONBF, BUFSIZ);
#endif
- gdb_stdout = stdio_fileopen (stdout);
- gdb_stderr = stderr_fileopen ();
+ main_ui = new_ui (stdin, stdout, stderr);
+ current_ui = main_ui;
- gdb_stdlog = gdb_stderr; /* for moment */
- gdb_stdtarg = gdb_stderr; /* for moment */
- gdb_stdin = stdio_fileopen (stdin);
gdb_stdtargerr = gdb_stderr; /* for moment */
gdb_stdtargin = gdb_stdin; /* for moment */
gdb_program_name = xstrdup (argv[0]);
#endif
+ /* Prefix warning messages with the command name. */
+ warning_pre_print = xstrprintf ("%s: warning: ", gdb_program_name);
+
if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)))
- /* Don't use *_filtered or warning() (which relies on
- current_target) until after initialize_all_files(). */
- fprintf_unfiltered (gdb_stderr,
- _("%s: warning: error finding "
- "working directory: %s\n"),
- argv[0], safe_strerror (errno));
-
+ perror_warning_with_name (_("error finding working directory"));
+
current_directory = gdb_dirbuf;
/* Set the sysroot path. */
gdb_sysroot = relocate_gdb_directory (TARGET_SYSTEM_ROOT,
TARGET_SYSTEM_ROOT_RELOCATABLE);
+ if (gdb_sysroot == NULL || *gdb_sysroot == '\0')
+ {
+ xfree (gdb_sysroot);
+ gdb_sysroot = xstrdup (TARGET_SYSROOT_PREFIX);
+ }
+
debug_file_directory = relocate_gdb_directory (DEBUGDIR,
DEBUGDIR_RELOCATABLE);
#ifdef WITH_PYTHON_PATH
{
/* For later use in helping Python find itself. */
- char *tmp = concat (WITH_PYTHON_PATH, SLASH_STRING, "lib", NULL);
+ char *tmp = concat (WITH_PYTHON_PATH, SLASH_STRING, "lib", (char *) NULL);
python_libdir = relocate_gdb_directory (tmp, PYTHON_PATH_RELOCATABLE);
xfree (tmp);
static struct option long_options[] =
{
{"tui", no_argument, 0, OPT_TUI},
- {"xdb", no_argument, &xdb_commands, 1},
{"dbx", no_argument, &dbx_commands, 1},
{"readnow", no_argument, &readnow_symbol_files, 1},
{"r", no_argument, &readnow_symbol_files, 1},
xfree (interpreter_p);
interpreter_p = xstrdup (INTERP_TUI);
#else
- fprintf_unfiltered (gdb_stderr,
- _("%s: TUI mode is not supported\n"),
- argv[0]);
- exit (1);
+ error (_("%s: TUI mode is not supported"), gdb_program_name);
#endif
break;
case OPT_WINDOWS:
pidarg = optarg;
break;
case 'x':
- {
- struct cmdarg cmdarg = { CMDARG_FILE, optarg };
-
- VEC_safe_push (cmdarg_s, cmdarg_vec, &cmdarg);
- }
+ cmdarg_vec.emplace_back (CMDARG_FILE, optarg);
break;
case 'X':
- {
- struct cmdarg cmdarg = { CMDARG_COMMAND, optarg };
-
- VEC_safe_push (cmdarg_s, cmdarg_vec, &cmdarg);
- }
+ cmdarg_vec.emplace_back (CMDARG_COMMAND, optarg);
break;
case OPT_IX:
- {
- struct cmdarg cmdarg = { CMDARG_INIT_FILE, optarg };
-
- VEC_safe_push (cmdarg_s, cmdarg_vec, &cmdarg);
- }
+ cmdarg_vec.emplace_back (CMDARG_INIT_FILE, optarg);
break;
case OPT_IEX:
- {
- struct cmdarg cmdarg = { CMDARG_INIT_COMMAND, optarg };
-
- VEC_safe_push (cmdarg_s, cmdarg_vec, &cmdarg);
- }
+ cmdarg_vec.emplace_back (CMDARG_INIT_COMMAND, optarg);
break;
case 'B':
batch_flag = batch_silent = 1;
- gdb_stdout = ui_file_new();
+ gdb_stdout = new null_file ();
break;
case 'D':
if (optarg[0] == '\0')
- {
- fprintf_unfiltered (gdb_stderr,
- _("%s: empty path for"
- " `--data-directory'\n"),
- argv[0]);
- exit (1);
- }
+ error (_("%s: empty path for `--data-directory'"),
+ gdb_program_name);
set_gdb_data_directory (optarg);
gdb_datadir_provided = 1;
break;
extern int gdbtk_test (char *);
if (!gdbtk_test (optarg))
- {
- fprintf_unfiltered (gdb_stderr,
- _("%s: unable to load "
- "tclcommand file \"%s\""),
- argv[0], optarg);
- exit (1);
- }
+ error (_("%s: unable to load tclcommand file \"%s\""),
+ gdb_program_name, optarg);
break;
}
case 'y':
interpreter_p = xstrdup (optarg);
break;
case 'd':
- dirarg[ndir++] = optarg;
- if (ndir >= dirsize)
- {
- dirsize *= 2;
- dirarg = (char **) xrealloc ((char *) dirarg,
- dirsize * sizeof (*dirarg));
- }
+ dirarg.push_back (optarg);
break;
case 't':
ttyarg = optarg;
i = strtol (optarg, &p, 0);
if (i == 0 && p == optarg)
-
- /* Don't use *_filtered or warning() (which relies on
- current_target) until after initialize_all_files(). */
-
- fprintf_unfiltered
- (gdb_stderr,
- _("warning: could not set baud rate to `%s'.\n"), optarg);
+ warning (_("could not set baud rate to `%s'."),
+ optarg);
else
baud_rate = i;
}
i = strtol (optarg, &p, 0);
if (i == 0 && p == optarg)
-
- /* Don't use *_filtered or warning() (which relies on
- current_target) until after initialize_all_files(). */
-
- fprintf_unfiltered (gdb_stderr,
- _("warning: could not set "
- "timeout limit to `%s'.\n"), optarg);
+ warning (_("could not set timeout limit to `%s'."),
+ optarg);
else
remote_timeout = i;
}
break;
case '?':
- fprintf_unfiltered (gdb_stderr,
- _("Use `%s --help' for a "
- "complete list of options.\n"),
- argv[0]);
- exit (1);
+ error (_("Use `%s --help' for a complete list of options."),
+ gdb_program_name);
}
}
/* Try to set up an alternate signal stack for SIGSEGV handlers. */
setup_alternate_signal_stack ();
- /* Initialize all files. Give the interpreter a chance to take
- control of the console via the deprecated_init_ui_hook (). */
+ /* Initialize all files. */
gdb_init (gdb_program_name);
/* Now that gdb_init has created the initial inferior, we're in
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);
- }
+ error (_("%s: `--args' specified but no program specified"),
+ gdb_program_name);
+
symarg = argv[optind];
execarg = argv[optind];
++optind;
/* Install the default UI. All the interpreters should have had a
look at things by now. Initialize the default interpreter. */
-
- {
- /* Find it. */
- struct interp *interp = interp_lookup (interpreter_p);
-
- if (interp == NULL)
- error (_("Interpreter `%s' unrecognized"), interpreter_p);
- /* Install it. */
- if (!interp_set (interp, 1))
- {
- fprintf_unfiltered (gdb_stderr,
- "Interpreter `%s' failed to initialize.\n",
- interpreter_p);
- exit (1);
- }
- }
+ set_top_level_interpreter (interpreter_p);
/* FIXME: cagney/2003-02-03: The big hack (part 2 of 2) that lets
GDB retain the old MI1 interpreter startup behavior. Output the
}
/* Set off error and warning messages with a blank line. */
+ xfree (warning_pre_print);
warning_pre_print = _("\nwarning: ");
/* Read and execute the system-wide gdbinit file, if it exists.
processed; it sets global parameters, which are independent of
what file you are debugging or what directory you are in. */
if (system_gdbinit && !inhibit_gdbinit)
- catch_command_errors_const (source_script, system_gdbinit,
- 0, RETURN_MASK_ALL);
+ catch_command_errors_const (source_script, system_gdbinit, 0);
/* Read and execute $HOME/.gdbinit file, if it exists. This is done
*before* all the command line arguments are processed; it sets
debugging or what directory you are in. */
if (home_gdbinit && !inhibit_gdbinit && !inhibit_home_gdbinit)
- catch_command_errors_const (source_script,
- home_gdbinit, 0, RETURN_MASK_ALL);
+ catch_command_errors_const (source_script, home_gdbinit, 0);
/* Process '-ix' and '-iex' options early. */
- for (i = 0; VEC_iterate (cmdarg_s, cmdarg_vec, i, cmdarg_p); i++)
- switch (cmdarg_p->type)
+ for (i = 0; i < cmdarg_vec.size (); i++)
{
- case CMDARG_INIT_FILE:
- catch_command_errors_const (source_script, cmdarg_p->string,
- !batch_flag, RETURN_MASK_ALL);
- break;
- case CMDARG_INIT_COMMAND:
- catch_command_errors (execute_command, cmdarg_p->string,
- !batch_flag, RETURN_MASK_ALL);
- break;
+ const struct cmdarg &cmdarg_p = cmdarg_vec[i];
+
+ switch (cmdarg_p.type)
+ {
+ case CMDARG_INIT_FILE:
+ catch_command_errors_const (source_script, cmdarg_p.string,
+ !batch_flag);
+ break;
+ case CMDARG_INIT_COMMAND:
+ catch_command_errors (execute_command, cmdarg_p.string,
+ !batch_flag);
+ break;
+ }
}
/* Now perform all the actions indicated by the arguments. */
if (cdarg != NULL)
{
- catch_command_errors (cd_command, cdarg, 0, RETURN_MASK_ALL);
+ catch_command_errors (cd_command, cdarg, 0);
}
- for (i = 0; i < ndir; i++)
- catch_command_errors (directory_switch, dirarg[i], 0, RETURN_MASK_ALL);
- xfree (dirarg);
+ for (i = 0; i < dirarg.size (); i++)
+ catch_command_errors (directory_switch, dirarg[i], 0);
/* Skip auto-loading section-specified scripts until we've sourced
local_gdbinit (which is often used to augment the source search
open it, better only print one error message.
catch_command_errors returns non-zero on success! */
if (catch_command_errors_const (exec_file_attach, execarg,
- !batch_flag, RETURN_MASK_ALL))
- catch_command_errors_const (symbol_file_add_main, symarg,
- !batch_flag, RETURN_MASK_ALL);
+ !batch_flag))
+ catch_command_errors_const (symbol_file_add_main_adapter, symarg,
+ !batch_flag);
}
else
{
if (execarg != NULL)
catch_command_errors_const (exec_file_attach, execarg,
- !batch_flag, RETURN_MASK_ALL);
+ !batch_flag);
if (symarg != NULL)
- catch_command_errors_const (symbol_file_add_main, symarg,
- !batch_flag, RETURN_MASK_ALL);
+ catch_command_errors_const (symbol_file_add_main_adapter, symarg,
+ !batch_flag);
}
if (corearg && pidarg)
"a core file at the same time."));
if (corearg != NULL)
- catch_command_errors (core_file_command, corearg,
- !batch_flag, RETURN_MASK_ALL);
+ catch_command_errors (core_file_command, corearg, !batch_flag);
else if (pidarg != NULL)
- catch_command_errors (attach_command, pidarg,
- !batch_flag, RETURN_MASK_ALL);
+ catch_command_errors (attach_command, pidarg, !batch_flag);
else if (pid_or_core_arg)
{
/* The user specified 'gdb program pid' or gdb program core'.
if (isdigit (pid_or_core_arg[0]))
{
if (catch_command_errors (attach_command, pid_or_core_arg,
- !batch_flag, RETURN_MASK_ALL) == 0)
+ !batch_flag) == 0)
catch_command_errors (core_file_command, pid_or_core_arg,
- !batch_flag, RETURN_MASK_ALL);
+ !batch_flag);
}
else /* Can't be a pid, better be a corefile. */
catch_command_errors (core_file_command, pid_or_core_arg,
- !batch_flag, RETURN_MASK_ALL);
+ !batch_flag);
}
if (ttyarg != NULL)
{
auto_load_local_gdbinit_loaded = 1;
- catch_command_errors_const (source_script, local_gdbinit, 0,
- RETURN_MASK_ALL);
+ catch_command_errors_const (source_script, local_gdbinit, 0);
}
}
load_auto_scripts_for_objfile (objfile);
/* Process '-x' and '-ex' options. */
- for (i = 0; VEC_iterate (cmdarg_s, cmdarg_vec, i, cmdarg_p); i++)
- switch (cmdarg_p->type)
+ for (i = 0; i < cmdarg_vec.size (); i++)
{
- case CMDARG_FILE:
- catch_command_errors_const (source_script, cmdarg_p->string,
- !batch_flag, RETURN_MASK_ALL);
- break;
- case CMDARG_COMMAND:
- catch_command_errors (execute_command, cmdarg_p->string,
- !batch_flag, RETURN_MASK_ALL);
- break;
+ const struct cmdarg &cmdarg_p = cmdarg_vec[i];
+
+ switch (cmdarg_p.type)
+ {
+ case CMDARG_FILE:
+ catch_command_errors_const (source_script, cmdarg_p.string,
+ !batch_flag);
+ break;
+ case CMDARG_COMMAND:
+ catch_command_errors (execute_command, cmdarg_p.string,
+ !batch_flag);
+ break;
+ }
}
/* Read in the old history after all the command files have been
/* We have hit the end of the batch file. */
quit_force (NULL, 0);
}
+}
+
+static void
+captured_main (void *data)
+{
+ struct captured_main_args *context = (struct captured_main_args *) data;
- /* Show time and/or space usage. */
- do_cleanups (pre_stat_chain);
+ captured_main_1 (context);
/* NOTE: cagney/1999-11-07: There is probably no reason for not
moving this loop and the code found in captured_command_loop()
int
gdb_main (struct captured_main_args *args)
{
- catch_errors (captured_main, args, "", RETURN_MASK_ALL);
+ TRY
+ {
+ captured_main (args);
+ }
+ CATCH (ex, RETURN_MASK_ALL)
+ {
+ exception_print (gdb_stderr, ex);
+ }
+ END_CATCH
+
/* The only way to end up here is by an error (normal exit is
handled by quit_force()), hence always return an error status. */
return 1;
#endif
fputs_unfiltered (_("\
--dbx DBX compatibility mode.\n\
- --xdb XDB compatibility mode.\n\
-q, --quiet, --silent\n\
Do not print version number on startup.\n\n\
"), stream);