X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fmain.c;h=3649e4a22018667380237c63fedf425dfe26f531;hb=d27c357a5b83773054e85ff3ea5dbfe18b9dd3c0;hp=9e2288959016930b71321630cf6ab66533003cf2;hpb=9224a01377868604ce4a7eb9c0d97736f7349dcd;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/main.c b/gdb/main.c index 9e22889590..3649e4a220 100644 --- a/gdb/main.c +++ b/gdb/main.c @@ -1,6 +1,6 @@ /* Top level stuff for GDB, the GNU debugger. - Copyright (C) 1986-2019 Free Software Foundation, Inc. + Copyright (C) 1986-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -28,7 +28,7 @@ #include #include #include -#include "event-loop.h" +#include "gdbsupport/event-loop.h" #include "ui-out.h" #include "interps.h" @@ -45,9 +45,15 @@ #include "event-top.h" #include "infrun.h" #include "gdbsupport/signals-state-save-restore.h" +#include #include #include "gdbsupport/pathstuff.h" #include "cli/cli-style.h" +#ifdef GDBTK +#include "gdbtk/generic/gdbtk.h" +#endif +#include "gdbsupport/alt-stack.h" +#include "observable.h" /* The selected interpreter. This will be used as a set command variable, so it should always be malloc'ed - since @@ -61,7 +67,7 @@ int dbx_commands = 0; char *gdb_sysroot = 0; /* GDB datadir, used to store data files. */ -char *gdb_datadir = 0; +std::string gdb_datadir; /* Non-zero if GDB_DATADIR was provided on the command line. This doesn't track whether data-directory is set later from the @@ -70,7 +76,7 @@ static int gdb_datadir_provided = 0; /* If gdb was configured with --with-python=/path, the possibly relocated path to python's lib directory. */ -char *python_libdir = 0; +std::string python_libdir; /* Target IO streams. */ struct ui_file *gdb_stdtargin; @@ -119,73 +125,73 @@ set_gdb_data_directory (const char *new_datadir) print_sys_errmsg (new_datadir, save_errno); } else if (!S_ISDIR (st.st_mode)) - warning (_("%s is not a directory."), new_datadir); + warning (_("%ps is not a directory."), + styled_string (file_name_style.style (), new_datadir)); - xfree (gdb_datadir); - gdb_datadir = gdb_realpath (new_datadir).release (); + gdb_datadir = gdb_realpath (new_datadir).get (); /* gdb_realpath won't return an absolute path if the path doesn't exist, but we still want to record an absolute path here. If the user entered "../foo" and "../foo" doesn't exist then we'll record $(pwd)/../foo which isn't canonical, but that's ok. */ - if (!IS_ABSOLUTE_PATH (gdb_datadir)) + if (!IS_ABSOLUTE_PATH (gdb_datadir.c_str ())) { - gdb::unique_xmalloc_ptr abs_datadir = gdb_abspath (gdb_datadir); + gdb::unique_xmalloc_ptr abs_datadir + = gdb_abspath (gdb_datadir.c_str ()); - xfree (gdb_datadir); - gdb_datadir = abs_datadir.release (); + gdb_datadir = abs_datadir.get (); } } /* Relocate a file or directory. PROGNAME is the name by which gdb was invoked (i.e., argv[0]). INITIAL is the default value for the file or directory. RELOCATABLE is true if the value is relocatable, - false otherwise. Returns a newly allocated string; this may return - NULL under the same conditions as make_relative_prefix. */ + false otherwise. This may return an empty string under the same + conditions as make_relative_prefix returning NULL. */ -static char * +static std::string relocate_path (const char *progname, const char *initial, bool relocatable) { if (relocatable) - return make_relative_prefix (progname, BINDIR, initial); - return xstrdup (initial); + { + gdb::unique_xmalloc_ptr str (make_relative_prefix (progname, + BINDIR, + initial)); + if (str != nullptr) + return str.get (); + return std::string (); + } + return initial; } /* Like relocate_path, but specifically checks for a directory. INITIAL is relocated according to the rules of relocate_path. If the result is a directory, it is used; otherwise, INITIAL is used. - The chosen directory is then canonicalized using lrealpath. This - function always returns a newly-allocated string. */ + The chosen directory is then canonicalized using lrealpath. */ -char * +std::string relocate_gdb_directory (const char *initial, bool relocatable) { - char *dir; - - dir = relocate_path (gdb_program_name, initial, relocatable); - if (dir) + std::string dir = relocate_path (gdb_program_name, initial, relocatable); + if (!dir.empty ()) { struct stat s; - if (*dir == '\0' || stat (dir, &s) != 0 || !S_ISDIR (s.st_mode)) + if (stat (dir.c_str (), &s) != 0 || !S_ISDIR (s.st_mode)) { - xfree (dir); - dir = NULL; + dir.clear (); } } - if (!dir) - dir = xstrdup (initial); + if (dir.empty ()) + dir = initial; /* Canonicalize the directory. */ - if (*dir) + if (!dir.empty ()) { - char *canon_sysroot = lrealpath (dir); + gdb::unique_xmalloc_ptr canon_sysroot (lrealpath (dir.c_str ())); if (canon_sysroot) - { - xfree (dir); - dir = canon_sysroot; - } + dir = canon_sysroot.get (); } return dir; @@ -196,7 +202,8 @@ relocate_gdb_directory (const char *initial, bool relocatable) otherwise. */ static std::string -relocate_gdbinit_path_maybe_in_datadir (const std::string& file) +relocate_gdbinit_path_maybe_in_datadir (const std::string &file, + bool relocatable) { size_t datadir_len = strlen (GDB_DATADIR); @@ -215,19 +222,12 @@ relocate_gdbinit_path_maybe_in_datadir (const std::string& file) size_t start = datadir_len; for (; IS_DIR_SEPARATOR (file[start]); ++start) ; - relocated_path = (std::string (gdb_datadir) + SLASH_STRING - + file.substr (start)); + relocated_path = gdb_datadir + SLASH_STRING + file.substr (start); } else { - char *relocated = relocate_path (gdb_program_name, - file.c_str (), - SYSTEM_GDBINIT_RELOCATABLE); - if (relocated != nullptr) - { - relocated_path = relocated; - xfree (relocated); - } + relocated_path = relocate_path (gdb_program_name, file.c_str (), + relocatable); } return relocated_path; } @@ -238,11 +238,11 @@ relocate_gdbinit_path_maybe_in_datadir (const std::string& file) to be loaded, then SYSTEM_GDBINIT (resp. HOME_GDBINIT and LOCAL_GDBINIT) is set to the empty string. */ static void -get_init_files (std::string *system_gdbinit, +get_init_files (std::vector *system_gdbinit, std::string *home_gdbinit, std::string *local_gdbinit) { - static std::string sysgdbinit; + static std::vector sysgdbinit; static std::string homeinit; static std::string localinit; static int initialized = 0; @@ -254,10 +254,51 @@ get_init_files (std::string *system_gdbinit, if (SYSTEM_GDBINIT[0]) { std::string relocated_sysgdbinit - = relocate_gdbinit_path_maybe_in_datadir (SYSTEM_GDBINIT); + = relocate_gdbinit_path_maybe_in_datadir + (SYSTEM_GDBINIT, SYSTEM_GDBINIT_RELOCATABLE); if (!relocated_sysgdbinit.empty () && stat (relocated_sysgdbinit.c_str (), &s) == 0) - sysgdbinit = relocated_sysgdbinit; + sysgdbinit.push_back (relocated_sysgdbinit); + } + if (SYSTEM_GDBINIT_DIR[0]) + { + std::string relocated_gdbinit_dir + = relocate_gdbinit_path_maybe_in_datadir + (SYSTEM_GDBINIT_DIR, SYSTEM_GDBINIT_DIR_RELOCATABLE); + if (!relocated_gdbinit_dir.empty ()) { + gdb_dir_up dir (opendir (relocated_gdbinit_dir.c_str ())); + if (dir != nullptr) + { + std::vector files; + for (;;) + { + struct dirent *ent = readdir (dir.get ()); + if (ent == nullptr) + break; + std::string name (ent->d_name); + if (name == "." || name == "..") + continue; + /* ent->d_type is not available on all systems (e.g. mingw, + Solaris), so we have to call stat(). */ + std::string filename + = relocated_gdbinit_dir + SLASH_STRING + name; + if (stat (filename.c_str (), &s) != 0 + || !S_ISREG (s.st_mode)) + continue; + const struct extension_language_defn *extlang + = get_ext_lang_of_file (filename.c_str ()); + /* We effectively don't support "set script-extension + off/soft", because we are loading system init files here, + so it does not really make sense to depend on a + setting. */ + if (extlang != nullptr && ext_lang_present_p (extlang)) + files.push_back (std::move (filename)); + } + std::sort (files.begin (), files.end ()); + sysgdbinit.insert (sysgdbinit.end (), + files.begin (), files.end ()); + } + } } const char *homedir = getenv ("HOME"); @@ -296,27 +337,59 @@ get_init_files (std::string *system_gdbinit, *local_gdbinit = localinit; } -/* Try to set up an alternate signal stack for SIGSEGV handlers. - This allows us to handle SIGSEGV signals generated when the - normal process stack is exhausted. If this stack is not set - up (sigaltstack is unavailable or fails) and a SIGSEGV is - generated when the normal stack is exhausted then the program - will behave as though no SIGSEGV handler was installed. */ +/* Start up the event loop. This is the entry point to the event loop + from the command loop. */ static void -setup_alternate_signal_stack (void) +start_event_loop () { -#ifdef HAVE_SIGALTSTACK - stack_t ss; + /* Loop until there is nothing to do. This is the entry point to + the event loop engine. gdb_do_one_event will process one event + for each invocation. It blocks waiting for an event and then + processes it. */ + while (1) + { + int result = 0; + + try + { + result = gdb_do_one_event (); + } + catch (const gdb_exception &ex) + { + exception_print (gdb_stderr, ex); + + /* If any exception escaped to here, we better enable + stdin. Otherwise, any command that calls async_disable_stdin, + and then throws, will leave stdin inoperable. */ + SWITCH_THRU_ALL_UIS () + { + async_enable_stdin (); + } + /* If we long-jumped out of do_one_event, we probably didn't + get around to resetting the prompt, which leaves readline + in a messed-up state. Reset it here. */ + current_ui->prompt_state = PROMPT_NEEDED; + gdb::observers::command_error.notify (); + /* This call looks bizarre, but it is required. If the user + entered a command that caused an error, + after_char_processing_hook won't be called from + rl_callback_read_char_wrapper. Using a cleanup there + won't work, since we want this function to be called + after a new prompt is printed. */ + if (after_char_processing_hook) + (*after_char_processing_hook) (); + /* Maybe better to set a flag to be checked somewhere as to + whether display the prompt or not. */ + } - /* 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; + if (result < 0) + break; + } - sigaltstack(&ss, NULL); -#endif + /* We are done with the event loop. There are no more event sources + to listen to. So we exit GDB. */ + return; } /* Call command_loop. */ @@ -541,29 +614,26 @@ captured_main_1 (struct captured_main_args *context) perror_warning_with_name (_("error finding working directory")); /* Set the sysroot path. */ - gdb_sysroot = relocate_gdb_directory (TARGET_SYSTEM_ROOT, - TARGET_SYSTEM_ROOT_RELOCATABLE); + gdb_sysroot + = xstrdup (relocate_gdb_directory (TARGET_SYSTEM_ROOT, + TARGET_SYSTEM_ROOT_RELOCATABLE).c_str ()); - if (gdb_sysroot == NULL || *gdb_sysroot == '\0') + if (*gdb_sysroot == '\0') { xfree (gdb_sysroot); gdb_sysroot = xstrdup (TARGET_SYSROOT_PREFIX); } - debug_file_directory = relocate_gdb_directory (DEBUGDIR, - DEBUGDIR_RELOCATABLE); + debug_file_directory + = xstrdup (relocate_gdb_directory (DEBUGDIR, + DEBUGDIR_RELOCATABLE).c_str ()); gdb_datadir = relocate_gdb_directory (GDB_DATADIR, GDB_DATADIR_RELOCATABLE); -#ifdef WITH_PYTHON_PATH - { - /* For later use in helping Python find itself. */ - char *tmp = concat (WITH_PYTHON_PATH, SLASH_STRING, "lib", (char *) NULL); - - python_libdir = relocate_gdb_directory (tmp, PYTHON_PATH_RELOCATABLE); - xfree (tmp); - } +#ifdef WITH_PYTHON_LIBDIR + python_libdir = relocate_gdb_directory (WITH_PYTHON_LIBDIR, + PYTHON_LIBDIR_RELOCATABLE); #endif #ifdef RELOC_SRCDIR @@ -597,6 +667,9 @@ captured_main_1 (struct captured_main_args *context) OPT_READNOW, OPT_READNEVER }; + /* This struct requires int* in the struct, but write_files is a bool. + So use this temporary int that we write back after argument parsing. */ + int write_files_1 = 0; static struct option long_options[] = { {"tui", no_argument, 0, OPT_TUI}, @@ -661,7 +734,7 @@ captured_main_1 (struct captured_main_args *context) {"w", no_argument, NULL, OPT_WINDOWS}, {"windows", no_argument, NULL, OPT_WINDOWS}, {"statistics", no_argument, 0, OPT_STATISTICS}, - {"write", no_argument, &write_files, 1}, + {"write", no_argument, &write_files_1, 1}, {"args", no_argument, &set_args, 1}, {"l", required_argument, 0, 'l'}, {"return-child-result", no_argument, &return_child_result, 1}, @@ -766,8 +839,6 @@ captured_main_1 (struct captured_main_args *context) #ifdef GDBTK case 'z': { - extern int gdbtk_test (char *); - if (!gdbtk_test (optarg)) error (_("%s: unable to load tclcommand file \"%s\""), gdb_program_name, optarg); @@ -780,8 +851,6 @@ captured_main_1 (struct captured_main_args *context) { /* Set the external editor commands when gdb is farming out files to be edited by another program. */ - extern char *external_editor_command; - external_editor_command = xstrdup (optarg); break; } @@ -845,6 +914,7 @@ captured_main_1 (struct captured_main_args *context) gdb_program_name); } } + write_files = (write_files_1 != 0); if (batch_flag) { @@ -858,7 +928,7 @@ captured_main_1 (struct captured_main_args *context) save_original_signals_state (quiet); /* Try to set up an alternate signal stack for SIGSEGV handlers. */ - setup_alternate_signal_stack (); + gdb::alternate_signal_stack signal_stack; /* Initialize all files. */ gdb_init (gdb_program_name); @@ -913,9 +983,9 @@ captured_main_1 (struct captured_main_args *context) } /* Lookup gdbinit files. Note that the gdbinit file name may be - overriden during file initialization, so get_init_files should be + overridden during file initialization, so get_init_files should be called after gdb_init. */ - std::string system_gdbinit; + std::vector system_gdbinit; std::string home_gdbinit; std::string local_gdbinit; get_init_files (&system_gdbinit, &home_gdbinit, &local_gdbinit); @@ -936,7 +1006,6 @@ captured_main_1 (struct captured_main_args *context) if (print_help) { print_gdb_help (gdb_stdout); - fputs_unfiltered ("\n", gdb_stdout); exit (0); } @@ -995,7 +1064,10 @@ captured_main_1 (struct captured_main_args *context) processed; it sets global parameters, which are independent of what file you are debugging or what directory you are in. */ if (!system_gdbinit.empty () && !inhibit_gdbinit) - ret = catch_command_errors (source_script, system_gdbinit.c_str (), 0); + { + for (const std::string &file : system_gdbinit) + ret = catch_command_errors (source_script, file.c_str (), 0); + } /* Read and execute $HOME/.gdbinit file, if it exists. This is done *before* all the command line arguments are processed; it sets @@ -1213,7 +1285,7 @@ gdb_main (struct captured_main_args *args) static void print_gdb_help (struct ui_file *stream) { - std::string system_gdbinit; + std::vector system_gdbinit; std::string home_gdbinit; std::string local_gdbinit; @@ -1294,9 +1366,18 @@ Other options:\n\n\ At startup, GDB reads the following init files and executes their commands:\n\ "), stream); if (!system_gdbinit.empty ()) - fprintf_unfiltered (stream, _("\ - * system-wide init file: %s\n\ -"), system_gdbinit.c_str ()); + { + std::string output; + for (size_t idx = 0; idx < system_gdbinit.size (); ++idx) + { + output += system_gdbinit[idx]; + if (idx < system_gdbinit.size () - 1) + output += ", "; + } + fprintf_unfiltered (stream, _("\ + * system-wide init files: %s\n\ +"), output.c_str ()); + } if (!home_gdbinit.empty ()) fprintf_unfiltered (stream, _("\ * user-specific init file: %s\n\ @@ -1310,7 +1391,11 @@ For more information, type \"help\" from within GDB, or consult the\n\ GDB manual (available as on-line info or a printed manual).\n\ "), stream); if (REPORT_BUGS_TO[0] && stream == gdb_stdout) - fprintf_unfiltered (stream, _("\ -Report bugs to \"%s\".\n\ + fprintf_unfiltered (stream, _("\n\ +Report bugs to %s.\n\ "), REPORT_BUGS_TO); + if (stream == gdb_stdout) + fprintf_unfiltered (stream, _("\n\ +You can ask GDB-related questions on the GDB users mailing list\n\ +(gdb@sourceware.org) or on GDB's IRC channel (#gdb on Freenode).\n")); }