X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fmain.c;h=59cb14161be31e4764f02a846c86dbd7e4a2e9d4;hb=refs%2Fheads%2Fconcurrent-displaced-stepping-2020-04-01;hp=6b75fced23626e3c2b0c0361d78b183d88f086be;hpb=f2aec7f6d149c8a534e8246b0d3a50038864fa2d;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/main.c b/gdb/main.c index 6b75fced23..59cb14161b 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 @@ -119,7 +125,8 @@ 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)); gdb_datadir = gdb_realpath (new_datadir).get (); @@ -195,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); @@ -214,14 +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 { - relocated_path = relocate_path (gdb_program_name, - file.c_str (), - SYSTEM_GDBINIT_RELOCATABLE); + relocated_path = relocate_path (gdb_program_name, file.c_str (), + relocatable); } return relocated_path; } @@ -232,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; @@ -248,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"); @@ -290,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; - /* 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; + try + { + result = gdb_do_one_event (); + } + catch (const gdb_exception &ex) + { + exception_print (gdb_stderr, ex); - sigaltstack(&ss, NULL); -#endif + /* 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. */ + } + + if (result < 0) + break; + } + + /* We are done with the event loop. There are no more event sources + to listen to. So we exit GDB. */ + return; } /* Call command_loop. */ @@ -549,18 +628,12 @@ captured_main_1 (struct captured_main_args *context) = xstrdup (relocate_gdb_directory (DEBUGDIR, DEBUGDIR_RELOCATABLE).c_str ()); - gdb_datadir - = xstrdup (relocate_gdb_directory (GDB_DATADIR, - GDB_DATADIR_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 @@ -594,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}, @@ -658,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}, @@ -763,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); @@ -777,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; } @@ -842,6 +914,7 @@ captured_main_1 (struct captured_main_args *context) gdb_program_name); } } + write_files = (write_files_1 != 0); if (batch_flag) { @@ -855,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); @@ -910,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); @@ -992,7 +1065,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 @@ -1210,7 +1286,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; @@ -1291,9 +1367,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\