X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fauto-load.c;h=0864ad38a762ffda672ce2a4b533bd23504fb414;hb=7cac64af7bc6a7f7a86f90a1465f7c3d2b6f07e8;hp=1112ef242f395575eed837a9c388b314078f97df;hpb=849c862eb2637990692ffe31d16dc779f9bf30c5;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/auto-load.c b/gdb/auto-load.c index 1112ef242f..0864ad38a7 100644 --- a/gdb/auto-load.c +++ b/gdb/auto-load.c @@ -1,6 +1,6 @@ /* GDB routines for supporting auto-loaded scripts. - Copyright (C) 2012-2014 Free Software Foundation, Inc. + Copyright (C) 2012-2019 Free Software Foundation, Inc. This file is part of GDB. @@ -18,28 +18,30 @@ along with this program. If not, see . */ #include "defs.h" +#include #include "auto-load.h" #include "progspace.h" #include "gdb_regex.h" #include "ui-out.h" #include "filenames.h" #include "command.h" -#include "observer.h" +#include "observable.h" #include "objfiles.h" -#include "exceptions.h" #include "cli/cli-script.h" #include "gdbcmd.h" #include "cli/cli-cmds.h" #include "cli/cli-decode.h" #include "cli/cli-setshow.h" -#include "gdb_vecs.h" #include "readline/tilde.h" #include "completer.h" #include "fnmatch.h" #include "top.h" -#include "filestuff.h" +#include "gdbsupport/filestuff.h" #include "extension.h" #include "gdb/section-scripts.h" +#include +#include "gdbsupport/pathstuff.h" +#include "cli/cli-style.h" /* The section to look in for auto-loaded scripts (in file formats that support sections). @@ -49,17 +51,18 @@ followed by the path of a python script to load. */ #define AUTO_SECTION_NAME ".debug_gdb_scripts" -static int maybe_add_script (struct auto_load_pspace_info *pspace_info, - int loaded, const char *name, - const char *full_path, - const struct extension_language_defn *language); +static void maybe_print_unsupported_script_warning + (struct auto_load_pspace_info *, struct objfile *objfile, + const struct extension_language_defn *language, + const char *section_name, unsigned offset); -static int unsupported_script_warning_print (struct auto_load_pspace_info *); - -static int script_not_found_warning_print (struct auto_load_pspace_info *); +static void maybe_print_script_not_found_warning + (struct auto_load_pspace_info *, struct objfile *objfile, + const struct extension_language_defn *language, + const char *section_name, unsigned offset); /* Value of the 'set debug auto-load' configuration variable. */ -static int debug_auto_load = 0; +static bool debug_auto_load = false; /* "show" command for the debug_auto_load configuration variable. */ @@ -77,7 +80,7 @@ show_debug_auto_load (struct ui_file *file, int from_tty, set auto-load gdb-scripts on|off This is true if we should auto-load associated scripts when an objfile is opened, false otherwise. */ -static int auto_load_gdb_scripts = 1; +static bool auto_load_gdb_scripts = true; /* "show" command for the auto_load_gdb_scripts configuration variable. */ @@ -108,16 +111,16 @@ auto_load_gdb_scripts_enabled (const struct extension_language_defn *extlang) This flag exists to facilitate deferring auto-loading during start-up until after ./.gdbinit has been read; it may augment the search directories used to find the scripts. */ -int global_auto_load = 1; +bool global_auto_load = true; /* Auto-load .gdbinit file from the current directory? */ -int auto_load_local_gdbinit = 1; +bool auto_load_local_gdbinit = true; /* Absolute pathname to the current directory .gdbinit, if it exists. */ char *auto_load_local_gdbinit_pathname = NULL; -/* Boolean value if AUTO_LOAD_LOCAL_GDBINIT_PATHNAME has been loaded. */ -int auto_load_local_gdbinit_loaded = 0; +/* if AUTO_LOAD_LOCAL_GDBINIT_PATHNAME has been loaded. */ +bool auto_load_local_gdbinit_loaded = false; /* "show" command for the auto_load_local_gdbinit configuration variable. */ @@ -138,7 +141,7 @@ static char *auto_load_dir; /* "set" command for the auto_load_dir configuration variable. */ static void -set_auto_load_dir (char *args, int from_tty, struct cmd_list_element *c) +set_auto_load_dir (const char *args, int from_tty, struct cmd_list_element *c) { /* Setting the variable to "" resets it to the compile time defaults. */ if (auto_load_dir[0] == '\0') @@ -167,27 +170,24 @@ static char *auto_load_safe_path; /* Vector of directory elements of AUTO_LOAD_SAFE_PATH with each one normalized by tilde_expand and possibly each entries has added its gdb_realpath counterpart. */ -static VEC (char_ptr) *auto_load_safe_path_vec; +std::vector> auto_load_safe_path_vec; /* Expand $datadir and $debugdir in STRING according to the rules of - substitute_path_component. Return vector from dirnames_to_char_ptr_vec, - this vector must be freed by free_char_ptr_vec by the caller. */ + substitute_path_component. */ -static VEC (char_ptr) * +static std::vector> auto_load_expand_dir_vars (const char *string) { - VEC (char_ptr) *dir_vec; - char *s; - - s = xstrdup (string); - substitute_path_component (&s, "$datadir", gdb_datadir); + char *s = xstrdup (string); + substitute_path_component (&s, "$datadir", gdb_datadir.c_str ()); substitute_path_component (&s, "$debugdir", debug_file_directory); if (debug_auto_load && strcmp (s, string) != 0) fprintf_unfiltered (gdb_stdlog, _("auto-load: Expanded $-variables to \"%s\".\n"), s); - dir_vec = dirnames_to_char_ptr_vec (s); + std::vector> dir_vec + = dirnames_to_char_ptr_vec (s); xfree(s); return dir_vec; @@ -198,55 +198,49 @@ auto_load_expand_dir_vars (const char *string) static void auto_load_safe_path_vec_update (void) { - unsigned len; - int ix; - if (debug_auto_load) fprintf_unfiltered (gdb_stdlog, _("auto-load: Updating directories of \"%s\".\n"), auto_load_safe_path); - free_char_ptr_vec (auto_load_safe_path_vec); - auto_load_safe_path_vec = auto_load_expand_dir_vars (auto_load_safe_path); - len = VEC_length (char_ptr, auto_load_safe_path_vec); + size_t len = auto_load_safe_path_vec.size (); /* Apply tilde_expand and gdb_realpath to each AUTO_LOAD_SAFE_PATH_VEC element. */ - for (ix = 0; ix < len; ix++) + for (size_t i = 0; i < len; i++) { - char *dir = VEC_index (char_ptr, auto_load_safe_path_vec, ix); - char *expanded = tilde_expand (dir); - char *real_path = gdb_realpath (expanded); + gdb::unique_xmalloc_ptr &in_vec = auto_load_safe_path_vec[i]; + gdb::unique_xmalloc_ptr expanded (tilde_expand (in_vec.get ())); + gdb::unique_xmalloc_ptr real_path = gdb_realpath (expanded.get ()); - /* Ensure the current entry is at least tilde_expand-ed. */ - VEC_replace (char_ptr, auto_load_safe_path_vec, ix, expanded); + /* Ensure the current entry is at least tilde_expand-ed. ORIGINAL makes + sure we free the original string. */ + gdb::unique_xmalloc_ptr original = std::move (in_vec); + in_vec = std::move (expanded); if (debug_auto_load) { - if (strcmp (expanded, dir) == 0) + if (strcmp (in_vec.get (), original.get ()) == 0) fprintf_unfiltered (gdb_stdlog, _("auto-load: Using directory \"%s\".\n"), - expanded); + in_vec.get ()); else fprintf_unfiltered (gdb_stdlog, _("auto-load: Resolved directory \"%s\" " "as \"%s\".\n"), - dir, expanded); + original.get (), in_vec.get ()); } - xfree (dir); /* If gdb_realpath returns a different content, append it. */ - if (strcmp (real_path, expanded) == 0) - xfree (real_path); - else + if (strcmp (real_path.get (), in_vec.get ()) != 0) { - VEC_safe_push (char_ptr, auto_load_safe_path_vec, real_path); - if (debug_auto_load) fprintf_unfiltered (gdb_stdlog, _("auto-load: And canonicalized as \"%s\".\n"), - real_path); + real_path.get ()); + + auto_load_safe_path_vec.push_back (std::move (real_path)); } } } @@ -262,7 +256,8 @@ auto_load_gdb_datadir_changed (void) /* "set" command for the auto_load_safe_path configuration variable. */ static void -set_auto_load_safe_path (char *args, int from_tty, struct cmd_list_element *c) +set_auto_load_safe_path (const char *args, + int from_tty, struct cmd_list_element *c) { /* Setting the variable to "" resets it to the compile time defaults. */ if (auto_load_safe_path[0] == '\0') @@ -301,7 +296,7 @@ show_auto_load_safe_path (struct ui_file *file, int from_tty, variable. */ static void -add_auto_load_safe_path (char *args, int from_tty) +add_auto_load_safe_path (const char *args, int from_tty) { char *s; @@ -318,6 +313,22 @@ Use 'set auto-load safe-path /' for disabling the auto-load safe-path security.\ auto_load_safe_path_vec_update (); } +/* "add-auto-load-scripts-directory" command for the auto_load_dir configuration + variable. */ + +static void +add_auto_load_dir (const char *args, int from_tty) +{ + char *s; + + if (args == NULL || *args == 0) + error (_("Directory argument required.")); + + s = xstrprintf ("%s%c%s", auto_load_dir, DIRNAME_SEPARATOR, args); + xfree (auto_load_dir); + auto_load_dir = s; +} + /* Implementation for filename_is_in_pattern overwriting the caller's FILENAME and PATTERN. */ @@ -391,9 +402,9 @@ filename_is_in_pattern (const char *filename, const char *pattern) { char *filename_copy, *pattern_copy; - filename_copy = alloca (strlen (filename) + 1); + filename_copy = (char *) alloca (strlen (filename) + 1); strcpy (filename_copy, filename); - pattern_copy = alloca (strlen (pattern) + 1); + pattern_copy = (char *) alloca (strlen (pattern) + 1); strcpy (pattern_copy, pattern); return filename_is_in_pattern_1 (filename_copy, pattern_copy); @@ -402,38 +413,40 @@ filename_is_in_pattern (const char *filename, const char *pattern) /* Return 1 if FILENAME belongs to one of directory components of AUTO_LOAD_SAFE_PATH_VEC. Return 0 otherwise. auto_load_safe_path_vec_update is never called. - *FILENAME_REALP may be updated by gdb_realpath of FILENAME - it has to be - freed by the caller. */ + *FILENAME_REALP may be updated by gdb_realpath of FILENAME. */ static int filename_is_in_auto_load_safe_path_vec (const char *filename, - char **filename_realp) + gdb::unique_xmalloc_ptr *filename_realp) { - char *pattern; - int ix; + const char *pattern = NULL; - for (ix = 0; VEC_iterate (char_ptr, auto_load_safe_path_vec, ix, pattern); - ++ix) - if (*filename_realp == NULL && filename_is_in_pattern (filename, pattern)) - break; + for (const gdb::unique_xmalloc_ptr &p : auto_load_safe_path_vec) + if (*filename_realp == NULL && filename_is_in_pattern (filename, p.get ())) + { + pattern = p.get (); + break; + } if (pattern == NULL) { if (*filename_realp == NULL) { *filename_realp = gdb_realpath (filename); - if (debug_auto_load && strcmp (*filename_realp, filename) != 0) + if (debug_auto_load && strcmp (filename_realp->get (), filename) != 0) fprintf_unfiltered (gdb_stdlog, _("auto-load: Resolved " "file \"%s\" as \"%s\".\n"), - filename, *filename_realp); + filename, filename_realp->get ()); } - if (strcmp (*filename_realp, filename) != 0) - for (ix = 0; - VEC_iterate (char_ptr, auto_load_safe_path_vec, ix, pattern); ++ix) - if (filename_is_in_pattern (*filename_realp, pattern)) - break; + if (strcmp (filename_realp->get (), filename) != 0) + for (const gdb::unique_xmalloc_ptr &p : auto_load_safe_path_vec) + if (filename_is_in_pattern (filename_realp->get (), p.get ())) + { + pattern = p.get (); + break; + } } if (pattern != NULL) @@ -459,8 +472,7 @@ filename_is_in_auto_load_safe_path_vec (const char *filename, int file_is_auto_load_safe (const char *filename, const char *debug_fmt, ...) { - char *filename_real = NULL; - struct cleanup *back_to; + gdb::unique_xmalloc_ptr filename_real; static int advice_printed = 0; if (debug_auto_load) @@ -472,34 +484,25 @@ file_is_auto_load_safe (const char *filename, const char *debug_fmt, ...) va_end (debug_args); } - back_to = make_cleanup (free_current_contents, &filename_real); - if (filename_is_in_auto_load_safe_path_vec (filename, &filename_real)) - { - do_cleanups (back_to); - return 1; - } + return 1; auto_load_safe_path_vec_update (); if (filename_is_in_auto_load_safe_path_vec (filename, &filename_real)) - { - do_cleanups (back_to); - return 1; - } + return 1; - warning (_("File \"%s\" auto-loading has been declined by your " + warning (_("File \"%ps\" auto-loading has been declined by your " "`auto-load safe-path' set to \"%s\"."), - filename_real, auto_load_safe_path); + styled_string (file_name_style.style (), filename_real.get ()), + auto_load_safe_path); if (!advice_printed) { const char *homedir = getenv ("HOME"); - char *homeinit; if (homedir == NULL) homedir = "$HOME"; - homeinit = xstrprintf ("%s/%s", homedir, gdbinit); - make_cleanup (xfree, homeinit); + std::string homeinit = string_printf ("%s/%s", homedir, GDBINIT); printf_filtered (_("\ To enable execution of this file add\n\ @@ -511,11 +514,11 @@ line to your configuration file \"%s\".\n\ For more information about this security protection see the\n\ \"Auto-loading safe path\" section in the GDB manual. E.g., run from the shell:\n\ \tinfo \"(gdb)Auto-loading safe path\"\n"), - filename_real, homeinit, homeinit); + filename_real.get (), + homeinit.c_str (), homeinit.c_str ()); advice_printed = 1; } - do_cleanups (back_to); return 0; } @@ -526,19 +529,24 @@ For more information about this security protection see the\n\ struct auto_load_pspace_info { - /* For each program space we keep track of loaded scripts. */ - struct htab *loaded_scripts; + auto_load_pspace_info () = default; + ~auto_load_pspace_info (); + + /* For each program space we keep track of loaded scripts, both when + specified as file names and as scripts to be executed directly. */ + struct htab *loaded_script_files = nullptr; + struct htab *loaded_script_texts = nullptr; /* Non-zero if we've issued the warning about an auto-load script not being supported. We only want to issue this warning once. */ - int unsupported_script_warning_printed; + bool unsupported_script_warning_printed = false; /* Non-zero if we've issued the warning about an auto-load script not being found. We only want to issue this warning once. */ - int script_not_found_warning_printed; + bool script_not_found_warning_printed = false; }; -/* Objects of this type are stored in the loaded script hash table. */ +/* Objects of this type are stored in the loaded_script hash table. */ struct loaded_script { @@ -546,7 +554,7 @@ struct loaded_script const char *name; /* Full path name or NULL if script wasn't found (or was otherwise - inaccessible). */ + inaccessible), or NULL for loaded_script_texts. */ const char *full_path; /* Non-zero if this script has been loaded. */ @@ -556,16 +564,15 @@ struct loaded_script }; /* Per-program-space data key. */ -static const struct program_space_data *auto_load_pspace_data; +static const struct program_space_key + auto_load_pspace_data; -static void -auto_load_pspace_data_cleanup (struct program_space *pspace, void *arg) +auto_load_pspace_info::~auto_load_pspace_info () { - struct auto_load_pspace_info *info = arg; - - if (info->loaded_scripts) - htab_delete (info->loaded_scripts); - xfree (info); + if (loaded_script_files) + htab_delete (loaded_script_files); + if (loaded_script_texts) + htab_delete (loaded_script_texts); } /* Get the current autoload data. If none is found yet, add it now. This @@ -576,12 +583,9 @@ get_auto_load_pspace_data (struct program_space *pspace) { struct auto_load_pspace_info *info; - info = program_space_data (pspace, auto_load_pspace_data); + info = auto_load_pspace_data.get (pspace); if (info == NULL) - { - info = XCNEW (struct auto_load_pspace_info); - set_program_space_data (pspace, auto_load_pspace_data, info); - } + info = auto_load_pspace_data.emplace (pspace); return info; } @@ -591,7 +595,7 @@ get_auto_load_pspace_data (struct program_space *pspace) static hashval_t hash_loaded_script_entry (const void *data) { - const struct loaded_script *e = data; + const struct loaded_script *e = (const struct loaded_script *) data; return htab_hash_string (e->name) ^ htab_hash_pointer (e->language); } @@ -601,8 +605,8 @@ hash_loaded_script_entry (const void *data) static int eq_loaded_script_entry (const void *a, const void *b) { - const struct loaded_script *ea = a; - const struct loaded_script *eb = b; + const struct loaded_script *ea = (const struct loaded_script *) a; + const struct loaded_script *eb = (const struct loaded_script *) b; return strcmp (ea->name, eb->name) == 0 && ea->language == eb->language; } @@ -617,13 +621,17 @@ init_loaded_scripts_info (struct auto_load_pspace_info *pspace_info) Space for each entry is obtained with one malloc so we can free them easily. */ - pspace_info->loaded_scripts = htab_create (31, - hash_loaded_script_entry, - eq_loaded_script_entry, - xfree); - - pspace_info->unsupported_script_warning_printed = FALSE; - pspace_info->script_not_found_warning_printed = FALSE; + pspace_info->loaded_script_files = htab_create (31, + hash_loaded_script_entry, + eq_loaded_script_entry, + xfree); + pspace_info->loaded_script_texts = htab_create (31, + hash_loaded_script_entry, + eq_loaded_script_entry, + xfree); + + pspace_info->unsupported_script_warning_printed = false; + pspace_info->script_not_found_warning_printed = false; } /* Wrapper on get_auto_load_pspace_data to also allocate the hash table @@ -635,23 +643,24 @@ get_auto_load_pspace_data_for_loading (struct program_space *pspace) struct auto_load_pspace_info *info; info = get_auto_load_pspace_data (pspace); - if (info->loaded_scripts == NULL) + if (info->loaded_script_files == NULL) init_loaded_scripts_info (info); return info; } -/* Add script NAME in LANGUAGE to hash table of PSPACE_INFO. LOADED 1 if the - script has been (is going to) be loaded, 0 otherwise (such as if it has not - been found). FULL_PATH is NULL if the script wasn't found. The result is - true if the script was already in the hash table. */ +/* Add script file NAME in LANGUAGE to hash table of PSPACE_INFO. + LOADED 1 if the script has been (is going to) be loaded, 0 otherwise + (such as if it has not been found). + FULL_PATH is NULL if the script wasn't found. + The result is true if the script was already in the hash table. */ static int -maybe_add_script (struct auto_load_pspace_info *pspace_info, int loaded, - const char *name, const char *full_path, - const struct extension_language_defn *language) +maybe_add_script_file (struct auto_load_pspace_info *pspace_info, int loaded, + const char *name, const char *full_path, + const struct extension_language_defn *language) { - struct htab *htab = pspace_info->loaded_scripts; + struct htab *htab = pspace_info->loaded_script_files; struct loaded_script **slot, entry; int in_hash_table; @@ -662,14 +671,15 @@ maybe_add_script (struct auto_load_pspace_info *pspace_info, int loaded, /* If this script is not in the hash table, add it. */ - if (! in_hash_table) + if (!in_hash_table) { char *p; /* Allocate all space in one chunk so it's easier to free. */ - *slot = xmalloc (sizeof (**slot) - + strlen (name) + 1 - + (full_path != NULL ? (strlen (full_path) + 1) : 0)); + *slot = ((struct loaded_script *) + xmalloc (sizeof (**slot) + + strlen (name) + 1 + + (full_path != NULL ? (strlen (full_path) + 1) : 0))); p = ((char*) *slot) + sizeof (**slot); strcpy (p, name); (*slot)->name = p; @@ -688,6 +698,45 @@ maybe_add_script (struct auto_load_pspace_info *pspace_info, int loaded, return in_hash_table; } +/* Add script contents NAME in LANGUAGE to hash table of PSPACE_INFO. + LOADED 1 if the script has been (is going to) be loaded, 0 otherwise + (such as if it has not been found). + The result is true if the script was already in the hash table. */ + +static int +maybe_add_script_text (struct auto_load_pspace_info *pspace_info, + int loaded, const char *name, + const struct extension_language_defn *language) +{ + struct htab *htab = pspace_info->loaded_script_texts; + struct loaded_script **slot, entry; + int in_hash_table; + + entry.name = name; + entry.language = language; + slot = (struct loaded_script **) htab_find_slot (htab, &entry, INSERT); + in_hash_table = *slot != NULL; + + /* If this script is not in the hash table, add it. */ + + if (!in_hash_table) + { + char *p; + + /* Allocate all space in one chunk so it's easier to free. */ + *slot = ((struct loaded_script *) + xmalloc (sizeof (**slot) + strlen (name) + 1)); + p = ((char*) *slot) + sizeof (**slot); + strcpy (p, name); + (*slot)->name = p; + (*slot)->full_path = NULL; + (*slot)->loaded = loaded; + (*slot)->language = language; + } + + return in_hash_table; +} + /* Clear the table of loaded section scripts. */ static void @@ -696,14 +745,9 @@ clear_section_scripts (void) struct program_space *pspace = current_program_space; struct auto_load_pspace_info *info; - info = program_space_data (pspace, auto_load_pspace_data); - if (info != NULL && info->loaded_scripts != NULL) - { - htab_delete (info->loaded_scripts); - info->loaded_scripts = NULL; - info->unsupported_script_warning_printed = FALSE; - info->script_not_found_warning_printed = FALSE; - } + info = auto_load_pspace_data.get (pspace); + if (info != NULL && info->loaded_script_files != NULL) + auto_load_pspace_data.clear (pspace); } /* Look for the auto-load script in LANGUAGE associated with OBJFILE where @@ -714,51 +758,38 @@ static int auto_load_objfile_script_1 (struct objfile *objfile, const char *realname, const struct extension_language_defn *language) { - char *filename, *debugfile; - int len, retval; - FILE *input; - struct cleanup *cleanups; + const char *debugfile; + int retval; const char *suffix = ext_lang_auto_load_suffix (language); - len = strlen (realname); - filename = xmalloc (len + strlen (suffix) + 1); - memcpy (filename, realname, len); - strcpy (filename + len, suffix); - - cleanups = make_cleanup (xfree, filename); + std::string filename = std::string (realname) + suffix; - input = gdb_fopen_cloexec (filename, "r"); - debugfile = filename; + gdb_file_up input = gdb_fopen_cloexec (filename.c_str (), "r"); + debugfile = filename.c_str (); if (debug_auto_load) fprintf_unfiltered (gdb_stdlog, _("auto-load: Attempted file \"%s\" %s.\n"), debugfile, input ? _("exists") : _("does not exist")); + std::string debugfile_holder; if (!input) { - VEC (char_ptr) *vec; - int ix; - char *dir; - /* Also try the same file in a subdirectory of gdb's data directory. */ - vec = auto_load_expand_dir_vars (auto_load_dir); - make_cleanup_free_char_ptr_vec (vec); + std::vector> vec + = auto_load_expand_dir_vars (auto_load_dir); if (debug_auto_load) fprintf_unfiltered (gdb_stdlog, _("auto-load: Searching 'set auto-load " "scripts-directory' path \"%s\".\n"), auto_load_dir); - for (ix = 0; VEC_iterate (char_ptr, vec, ix, dir); ++ix) + for (const gdb::unique_xmalloc_ptr &dir : vec) { - debugfile = xmalloc (strlen (dir) + strlen (filename) + 1); - strcpy (debugfile, dir); - /* FILENAME is absolute, so we don't need a "/" here. */ - strcat (debugfile, filename); + debugfile_holder = dir.get () + filename; + debugfile = debugfile_holder.c_str (); - make_cleanup (xfree, debugfile); input = gdb_fopen_cloexec (debugfile, "r"); if (debug_auto_load) fprintf_unfiltered (gdb_stdlog, _("auto-load: Attempted file " @@ -775,8 +806,6 @@ auto_load_objfile_script_1 (struct objfile *objfile, const char *realname, int is_safe; struct auto_load_pspace_info *pspace_info; - make_cleanup_fclose (input); - is_safe = file_is_auto_load_safe (debugfile, _("auto-load: Loading %s script \"%s\"" @@ -788,7 +817,8 @@ auto_load_objfile_script_1 (struct objfile *objfile, const char *realname, "info auto-load ${lang}-scripts" can print it. */ pspace_info = get_auto_load_pspace_data_for_loading (current_program_space); - maybe_add_script (pspace_info, is_safe, debugfile, debugfile, language); + maybe_add_script_file (pspace_info, is_safe, debugfile, debugfile, + language); /* To preserve existing behaviour we don't check for whether the script was already in the table, and always load it. @@ -804,7 +834,7 @@ auto_load_objfile_script_1 (struct objfile *objfile, const char *realname, compiled in. And the extension language is required to implement this function. */ gdb_assert (sourcer != NULL); - sourcer (language, objfile, input, debugfile); + sourcer (language, objfile, input.get (), debugfile); } retval = 1; @@ -812,7 +842,6 @@ auto_load_objfile_script_1 (struct objfile *objfile, const char *realname, else retval = 0; - do_cleanups (cleanups); return retval; } @@ -823,30 +852,183 @@ void auto_load_objfile_script (struct objfile *objfile, const struct extension_language_defn *language) { - char *realname = gdb_realpath (objfile_name (objfile)); - struct cleanup *cleanups = make_cleanup (xfree, realname); + gdb::unique_xmalloc_ptr realname + = gdb_realpath (objfile_name (objfile)); - if (!auto_load_objfile_script_1 (objfile, realname, language)) + if (!auto_load_objfile_script_1 (objfile, realname.get (), language)) { /* For Windows/DOS .exe executables, strip the .exe suffix, so that FOO-gdb.gdb could be used for FOO.exe, and try again. */ - size_t len = strlen (realname); + size_t len = strlen (realname.get ()); const size_t lexe = sizeof (".exe") - 1; - if (len > lexe && strcasecmp (realname + len - lexe, ".exe") == 0) + if (len > lexe && strcasecmp (realname.get () + len - lexe, ".exe") == 0) { len -= lexe; - realname[len] = '\0'; + realname.get ()[len] = '\0'; if (debug_auto_load) fprintf_unfiltered (gdb_stdlog, _("auto-load: Stripped .exe suffix, " "retrying with \"%s\".\n"), - realname); - auto_load_objfile_script_1 (objfile, realname, language); + realname.get ()); + auto_load_objfile_script_1 (objfile, realname.get (), language); } } +} + +/* Subroutine of source_section_scripts to simplify it. + Load FILE as a script in extension language LANGUAGE. + The script is from section SECTION_NAME in OBJFILE at offset OFFSET. */ - do_cleanups (cleanups); +static void +source_script_file (struct auto_load_pspace_info *pspace_info, + struct objfile *objfile, + const struct extension_language_defn *language, + const char *section_name, unsigned int offset, + const char *file) +{ + int in_hash_table; + objfile_script_sourcer_func *sourcer; + + /* Skip this script if support is not compiled in. */ + sourcer = ext_lang_objfile_script_sourcer (language); + if (sourcer == NULL) + { + /* We don't throw an error, the program is still debuggable. */ + maybe_print_unsupported_script_warning (pspace_info, objfile, language, + section_name, offset); + /* We *could* still try to open it, but there's no point. */ + maybe_add_script_file (pspace_info, 0, file, NULL, language); + return; + } + + /* Skip this script if auto-loading it has been disabled. */ + if (!ext_lang_auto_load_enabled (language)) + { + /* No message is printed, just skip it. */ + return; + } + + gdb::optional opened = find_and_open_script (file, + 1 /*search_path*/); + + if (opened) + { + if (!file_is_auto_load_safe (opened->full_path.get (), + _("auto-load: Loading %s script " + "\"%s\" from section \"%s\" of " + "objfile \"%s\".\n"), + ext_lang_name (language), + opened->full_path.get (), + section_name, objfile_name (objfile))) + opened.reset (); + } + else + { + /* If one script isn't found it's not uncommon for more to not be + found either. We don't want to print a message for each script, + too much noise. Instead, we print the warning once and tell the + user how to find the list of scripts that weren't loaded. + We don't throw an error, the program is still debuggable. + + IWBN if complaints.c were more general-purpose. */ + + maybe_print_script_not_found_warning (pspace_info, objfile, language, + section_name, offset); + } + + in_hash_table = maybe_add_script_file (pspace_info, bool (opened), file, + (opened + ? opened->full_path.get () + : NULL), + language); + + /* If this file is not currently loaded, load it. */ + if (opened && !in_hash_table) + sourcer (language, objfile, opened->stream.get (), + opened->full_path.get ()); +} + +/* Subroutine of source_section_scripts to simplify it. + Execute SCRIPT as a script in extension language LANG. + The script is from section SECTION_NAME in OBJFILE at offset OFFSET. */ + +static void +execute_script_contents (struct auto_load_pspace_info *pspace_info, + struct objfile *objfile, + const struct extension_language_defn *language, + const char *section_name, unsigned int offset, + const char *script) +{ + objfile_script_executor_func *executor; + const char *newline, *script_text; + const char *name; + int is_safe, in_hash_table; + + /* The first line of the script is the name of the script. + It must not contain any kind of space character. */ + name = NULL; + newline = strchr (script, '\n'); + std::string name_holder; + if (newline != NULL) + { + const char *buf, *p; + + /* Put the name in a buffer and validate it. */ + name_holder = std::string (script, newline - script); + buf = name_holder.c_str (); + for (p = buf; *p != '\0'; ++p) + { + if (isspace (*p)) + break; + } + /* We don't allow nameless scripts, they're not helpful to the user. */ + if (p != buf && *p == '\0') + name = buf; + } + if (name == NULL) + { + /* We don't throw an error, the program is still debuggable. */ + warning (_("\ +Missing/bad script name in entry at offset %u in section %s\n\ +of file %ps."), + offset, section_name, + styled_string (file_name_style.style (), + objfile_name (objfile))); + return; + } + script_text = newline + 1; + + /* Skip this script if support is not compiled in. */ + executor = ext_lang_objfile_script_executor (language); + if (executor == NULL) + { + /* We don't throw an error, the program is still debuggable. */ + maybe_print_unsupported_script_warning (pspace_info, objfile, language, + section_name, offset); + maybe_add_script_text (pspace_info, 0, name, language); + return; + } + + /* Skip this script if auto-loading it has been disabled. */ + if (!ext_lang_auto_load_enabled (language)) + { + /* No message is printed, just skip it. */ + return; + } + + is_safe = file_is_auto_load_safe (objfile_name (objfile), + _("auto-load: Loading %s script " + "\"%s\" from section \"%s\" of " + "objfile \"%s\".\n"), + ext_lang_name (language), name, + section_name, objfile_name (objfile)); + + in_hash_table = maybe_add_script_text (pspace_info, is_safe, name, language); + + /* If this file is not currently loaded, load it. */ + if (is_safe && !in_hash_table) + executor (language, objfile, name, script_text); } /* Load scripts specified in OBJFILE. @@ -854,12 +1036,12 @@ auto_load_objfile_script (struct objfile *objfile, file names. SECTION_NAME is used in error messages. - Scripts are found per normal "source -s" command processing. - First the script is looked for in $cwd. If not found there the - source search path is used. + Scripts specified as file names are found per normal "source -s" command + processing. First the script is looked for in $cwd. If not found there + the source search path is used. - The section contains a list of path names of script files to load. - Each path is null-terminated. */ + The section contains a list of path names of script files to load or + actual script contents. Each entry is nul-terminated. */ static void source_section_scripts (struct objfile *objfile, const char *section_name, @@ -872,20 +1054,19 @@ source_section_scripts (struct objfile *objfile, const char *section_name, for (p = start; p < end; ++p) { - const char *file; - FILE *stream; - char *full_path; - int opened, in_hash_table; - struct cleanup *back_to; + const char *entry; const struct extension_language_defn *language; - objfile_script_sourcer_func *sourcer; + unsigned int offset = p - start; + int code = *p; - switch (*p) + switch (code) { case SECTION_SCRIPT_ID_PYTHON_FILE: + case SECTION_SCRIPT_ID_PYTHON_TEXT: language = get_ext_lang_defn (EXT_LANG_PYTHON); break; case SECTION_SCRIPT_ID_SCHEME_FILE: + case SECTION_SCRIPT_ID_SCHEME_TEXT: language = get_ext_lang_defn (EXT_LANG_GUILE); break; default: @@ -894,105 +1075,37 @@ source_section_scripts (struct objfile *objfile, const char *section_name, but it's safer to just punt. */ return; } - file = ++p; + entry = ++p; while (p < end && *p != '\0') ++p; if (p == end) { - char *buf = alloca (p - file + 1); - - memcpy (buf, file, p - file); - buf[p - file] = '\0'; - warning (_("Non-null-terminated path in %s: %s"), - section_name, buf); - /* Don't load it. */ + warning (_("Non-nul-terminated entry in %s at offset %u"), + section_name, offset); + /* Don't load/execute it. */ break; } - if (p == file) - { - warning (_("Empty path in %s"), section_name); - continue; - } - /* Until we support more types of records in .debug_gdb_scripts we do - all the processing here. The expectation is to add a new - extension_language_script_ops "method" that handles all the records - for the language. For now we can just use - extension_language_script_ops.objfile_script_sourcer. */ - - /* Skip this script if support is not compiled in. */ - sourcer = ext_lang_objfile_script_sourcer (language); - if (sourcer == NULL) + switch (code) { - /* We don't throw an error, the program is still debuggable. */ - if (!unsupported_script_warning_print (pspace_info)) + case SECTION_SCRIPT_ID_PYTHON_FILE: + case SECTION_SCRIPT_ID_SCHEME_FILE: + if (p == entry) { - warning (_("Unsupported auto-load scripts referenced in" - " %s section\n" - "of file %s.\n" - "Use `info auto-load %s-scripts [REGEXP]'" - " to list them."), - section_name, objfile_name (objfile), - ext_lang_name (language)); + warning (_("Empty entry in %s at offset %u"), + section_name, offset); + continue; } - /* We *could* still try to open it, but there's no point. */ - maybe_add_script (pspace_info, 0, file, NULL, language); - continue; - } - - /* Skip this script if auto-loading it has been disabled. */ - if (!ext_lang_auto_load_enabled (language)) - { - /* No message is printed, just skip it. */ - continue; - } - - opened = find_and_open_script (file, 1 /*search_path*/, - &stream, &full_path); - - back_to = make_cleanup (null_cleanup, NULL); - if (opened) - { - make_cleanup_fclose (stream); - make_cleanup (xfree, full_path); - - if (!file_is_auto_load_safe (full_path, - _("auto-load: Loading %s script " - "\"%s\" from section \"%s\" of " - "objfile \"%s\".\n"), - ext_lang_name (language), full_path, - section_name, objfile_name (objfile))) - opened = 0; - } - else - { - full_path = NULL; - - /* If one script isn't found it's not uncommon for more to not be - found either. We don't want to print a message for each script, - too much noise. Instead, we print the warning once and tell the - user how to find the list of scripts that weren't loaded. - We don't throw an error, the program is still debuggable. - - IWBN if complaints.c were more general-purpose. */ - - if (script_not_found_warning_print (pspace_info)) - warning (_("Missing auto-load scripts referenced in section %s\n\ -of file %s\n\ -Use `info auto-load %s-scripts [REGEXP]' to list them."), - section_name, objfile_name (objfile), - ext_lang_name (language)); + source_script_file (pspace_info, objfile, language, + section_name, offset, entry); + break; + case SECTION_SCRIPT_ID_PYTHON_TEXT: + case SECTION_SCRIPT_ID_SCHEME_TEXT: + execute_script_contents (pspace_info, objfile, language, + section_name, offset, entry); + break; } - - in_hash_table = maybe_add_script (pspace_info, opened, file, full_path, - language); - - /* If this file is not currently loaded, load it. */ - if (opened && !in_hash_table) - sourcer (language, objfile, stream, full_path); - - do_cleanups (back_to); } } @@ -1006,21 +1119,22 @@ auto_load_section_scripts (struct objfile *objfile, const char *section_name) bfd_byte *data = NULL; scripts_sect = bfd_get_section_by_name (abfd, section_name); - if (scripts_sect == NULL) + if (scripts_sect == NULL + || (bfd_section_flags (scripts_sect) & SEC_HAS_CONTENTS) == 0) return; if (!bfd_get_full_section_contents (abfd, scripts_sect, &data)) - warning (_("Couldn't read %s section of %s"), - section_name, bfd_get_filename (abfd)); + warning (_("Couldn't read %s section of %ps"), + section_name, + styled_string (file_name_style.style (), + bfd_get_filename (abfd))); else { - struct cleanup *cleanups; - char *p = (char *) data; + gdb::unique_xmalloc_ptr data_holder (data); - cleanups = make_cleanup (xfree, p); + char *p = (char *) data; source_section_scripts (objfile, section_name, p, - p + bfd_get_section_size (scripts_sect)); - do_cleanups (cleanups); + p + bfd_section_size (scripts_sect)); } } @@ -1031,8 +1145,11 @@ load_auto_scripts_for_objfile (struct objfile *objfile) { /* Return immediately if auto-loading has been globally disabled. This is to handle sequencing of operations during gdb startup. - Also return immediately if OBJFILE is not actually a file. */ - if (!global_auto_load || (objfile->flags & OBJF_NOT_FILENAME) != 0) + Also return immediately if OBJFILE was not created from a file + on the local filesystem. */ + if (!global_auto_load + || (objfile->flags & OBJF_NOT_FILENAME) != 0 + || is_target_filename (objfile->original_name)) return; /* Load any extension language scripts for this objfile. @@ -1064,13 +1181,14 @@ auto_load_new_objfile (struct objfile *objfile) /* Collect scripts to be printed in a vec. */ -typedef struct loaded_script *loaded_script_ptr; -DEF_VEC_P (loaded_script_ptr); - struct collect_matching_scripts_data { - VEC (loaded_script_ptr) **scripts_p; + collect_matching_scripts_data (std::vector *scripts_p_, + const extension_language_defn *language_) + : scripts_p (scripts_p_), language (language_) + {} + std::vector *scripts_p; const struct extension_language_defn *language; }; @@ -1080,11 +1198,12 @@ struct collect_matching_scripts_data static int collect_matching_scripts (void **slot, void *info) { - struct loaded_script *script = *slot; - struct collect_matching_scripts_data *data = info; + struct loaded_script *script = (struct loaded_script *) *slot; + struct collect_matching_scripts_data *data + = (struct collect_matching_scripts_data *) info; if (script->language == data->language && re_exec (script->name)) - VEC_safe_push (loaded_script_ptr, *data->scripts_p, script); + data->scripts_p->push_back (script); return 1; } @@ -1095,35 +1214,29 @@ static void print_script (struct loaded_script *script) { struct ui_out *uiout = current_uiout; - struct cleanup *chain; - chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + ui_out_emit_tuple tuple_emitter (uiout, NULL); - ui_out_field_string (uiout, "loaded", script->loaded ? "Yes" : "No"); - ui_out_field_string (uiout, "script", script->name); - ui_out_text (uiout, "\n"); + uiout->field_string ("loaded", script->loaded ? "Yes" : "No"); + uiout->field_string ("script", script->name); + uiout->text ("\n"); /* If the name isn't the full path, print it too. */ if (script->full_path != NULL && strcmp (script->name, script->full_path) != 0) { - ui_out_text (uiout, "\tfull name: "); - ui_out_field_string (uiout, "full_path", script->full_path); - ui_out_text (uiout, "\n"); + uiout->text ("\tfull name: "); + uiout->field_string ("full_path", script->full_path); + uiout->text ("\n"); } - - do_cleanups (chain); } /* Helper for info_auto_load_scripts to sort the scripts by name. */ -static int -sort_scripts_by_name (const void *ap, const void *bp) +static bool +sort_scripts_by_name (loaded_script *a, loaded_script *b) { - const struct loaded_script *a = *(const struct loaded_script **) ap; - const struct loaded_script *b = *(const struct loaded_script **) bp; - - return FILENAME_CMP (a->name, b->name); + return FILENAME_CMP (a->name, b->name) < 0; } /* Special internal GDB value of auto_load_info_scripts's PATTERN identify @@ -1131,19 +1244,26 @@ sort_scripts_by_name (const void *ap, const void *bp) "info auto-load" invocation. Extra newline will be printed if needed. */ char auto_load_info_scripts_pattern_nl[] = ""; +/* Subroutine of auto_load_info_scripts to simplify it. + Print SCRIPTS. */ + +static void +print_scripts (const std::vector &scripts) +{ + for (loaded_script *script : scripts) + print_script (script); +} + /* Implementation for "info auto-load gdb-scripts" (and "info auto-load python-scripts"). List scripts in LANGUAGE matching PATTERN. FROM_TTY is the usual GDB boolean for user interactivity. */ void -auto_load_info_scripts (char *pattern, int from_tty, +auto_load_info_scripts (const char *pattern, int from_tty, const struct extension_language_defn *language) { struct ui_out *uiout = current_uiout; struct auto_load_pspace_info *pspace_info; - struct cleanup *script_chain; - VEC (loaded_script_ptr) *scripts; - int nr_scripts; dont_repeat (); @@ -1165,60 +1285,64 @@ auto_load_info_scripts (char *pattern, int from_tty, Plus we want to sort the scripts by name. So first traverse the hash table collecting the matching scripts. */ - scripts = VEC_alloc (loaded_script_ptr, 10); - script_chain = make_cleanup (VEC_cleanup (loaded_script_ptr), &scripts); + std::vector script_files, script_texts; + + if (pspace_info != NULL && pspace_info->loaded_script_files != NULL) + { + collect_matching_scripts_data data (&script_files, language); + + /* Pass a pointer to scripts as VEC_safe_push can realloc space. */ + htab_traverse_noresize (pspace_info->loaded_script_files, + collect_matching_scripts, &data); + + std::sort (script_files.begin (), script_files.end (), + sort_scripts_by_name); + } - if (pspace_info != NULL && pspace_info->loaded_scripts != NULL) + if (pspace_info != NULL && pspace_info->loaded_script_texts != NULL) { - struct collect_matching_scripts_data data = { &scripts, language }; + collect_matching_scripts_data data (&script_texts, language); /* Pass a pointer to scripts as VEC_safe_push can realloc space. */ - htab_traverse_noresize (pspace_info->loaded_scripts, + htab_traverse_noresize (pspace_info->loaded_script_texts, collect_matching_scripts, &data); + + std::sort (script_texts.begin (), script_texts.end (), + sort_scripts_by_name); } - nr_scripts = VEC_length (loaded_script_ptr, scripts); + int nr_scripts = script_files.size () + script_texts.size (); /* Table header shifted right by preceding "gdb-scripts: " would not match its columns. */ if (nr_scripts > 0 && pattern == auto_load_info_scripts_pattern_nl) - ui_out_text (uiout, "\n"); + uiout->text ("\n"); - make_cleanup_ui_out_table_begin_end (uiout, 2, nr_scripts, - "AutoLoadedScriptsTable"); + { + ui_out_emit_table table_emitter (uiout, 2, nr_scripts, + "AutoLoadedScriptsTable"); - ui_out_table_header (uiout, 7, ui_left, "loaded", "Loaded"); - ui_out_table_header (uiout, 70, ui_left, "script", "Script"); - ui_out_table_body (uiout); - - if (nr_scripts > 0) - { - int i; - loaded_script_ptr script; - - qsort (VEC_address (loaded_script_ptr, scripts), - VEC_length (loaded_script_ptr, scripts), - sizeof (loaded_script_ptr), sort_scripts_by_name); - for (i = 0; VEC_iterate (loaded_script_ptr, scripts, i, script); ++i) - print_script (script); - } + uiout->table_header (7, ui_left, "loaded", "Loaded"); + uiout->table_header (70, ui_left, "script", "Script"); + uiout->table_body (); - do_cleanups (script_chain); + print_scripts (script_files); + print_scripts (script_texts); + } if (nr_scripts == 0) { if (pattern && *pattern) - ui_out_message (uiout, 0, "No auto-load scripts matching %s.\n", - pattern); + uiout->message ("No auto-load scripts matching %s.\n", pattern); else - ui_out_message (uiout, 0, "No auto-load scripts.\n"); + uiout->message ("No auto-load scripts.\n"); } } /* Wrapper for "info auto-load gdb-scripts". */ static void -info_auto_load_gdb_scripts (char *pattern, int from_tty) +info_auto_load_gdb_scripts (const char *pattern, int from_tty) { auto_load_info_scripts (pattern, from_tty, &extension_language_gdb); } @@ -1226,50 +1350,72 @@ info_auto_load_gdb_scripts (char *pattern, int from_tty) /* Implement 'info auto-load local-gdbinit'. */ static void -info_auto_load_local_gdbinit (char *args, int from_tty) +info_auto_load_local_gdbinit (const char *args, int from_tty) { if (auto_load_local_gdbinit_pathname == NULL) printf_filtered (_("Local .gdbinit file was not found.\n")); else if (auto_load_local_gdbinit_loaded) - printf_filtered (_("Local .gdbinit file \"%s\" has been loaded.\n"), - auto_load_local_gdbinit_pathname); + printf_filtered (_("Local .gdbinit file \"%ps\" has been loaded.\n"), + styled_string (file_name_style.style (), + auto_load_local_gdbinit_pathname)); else - printf_filtered (_("Local .gdbinit file \"%s\" has not been loaded.\n"), - auto_load_local_gdbinit_pathname); + printf_filtered (_("Local .gdbinit file \"%ps\" has not been loaded.\n"), + styled_string (file_name_style.style (), + auto_load_local_gdbinit_pathname)); } -/* Return non-zero if UNSUPPORTED_SCRIPT_WARNING_PRINTED of PSPACE_INFO was - unset before calling this function. Always set - UNSUPPORTED_SCRIPT_WARNING_PRINTED of PSPACE_INFO. */ +/* Print an "unsupported script" warning if it has not already been printed. + The script is in language LANGUAGE at offset OFFSET in section SECTION_NAME + of OBJFILE. */ -static int -unsupported_script_warning_print (struct auto_load_pspace_info *pspace_info) +static void +maybe_print_unsupported_script_warning + (struct auto_load_pspace_info *pspace_info, + struct objfile *objfile, const struct extension_language_defn *language, + const char *section_name, unsigned offset) { - int retval = !pspace_info->unsupported_script_warning_printed; - - pspace_info->unsupported_script_warning_printed = 1; - - return retval; + if (!pspace_info->unsupported_script_warning_printed) + { + warning (_("\ +Unsupported auto-load script at offset %u in section %s\n\ +of file %ps.\n\ +Use `info auto-load %s-scripts [REGEXP]' to list them."), + offset, section_name, + styled_string (file_name_style.style (), + objfile_name (objfile)), + ext_lang_name (language)); + pspace_info->unsupported_script_warning_printed = true; + } } /* Return non-zero if SCRIPT_NOT_FOUND_WARNING_PRINTED of PSPACE_INFO was unset before calling this function. Always set SCRIPT_NOT_FOUND_WARNING_PRINTED of PSPACE_INFO. */ -static int -script_not_found_warning_print (struct auto_load_pspace_info *pspace_info) +static void +maybe_print_script_not_found_warning + (struct auto_load_pspace_info *pspace_info, + struct objfile *objfile, const struct extension_language_defn *language, + const char *section_name, unsigned offset) { - int retval = !pspace_info->script_not_found_warning_printed; - - pspace_info->script_not_found_warning_printed = 1; - - return retval; + if (!pspace_info->script_not_found_warning_printed) + { + warning (_("\ +Missing auto-load script at offset %u in section %s\n\ +of file %ps.\n\ +Use `info auto-load %s-scripts [REGEXP]' to list them."), + offset, section_name, + styled_string (file_name_style.style (), + objfile_name (objfile)), + ext_lang_name (language)); + pspace_info->script_not_found_warning_printed = true; + } } /* The only valid "set auto-load" argument is off|0|no|disable. */ static void -set_auto_load_cmd (char *args, int from_tty) +set_auto_load_cmd (const char *args, int from_tty) { struct cmd_list_element *list; size_t length; @@ -1318,7 +1464,7 @@ automatic loading of Python scripts."), "show auto-load " settings. */ static void -show_auto_load_cmd (char *args, int from_tty) +show_auto_load_cmd (const char *args, int from_tty) { cmd_show_list (*auto_load_show_cmdlist_get (), from_tty, ""); } @@ -1346,32 +1492,24 @@ automatic loading of Python scripts."), newlines at proper places. */ static void -info_auto_load_cmd (char *args, int from_tty) +info_auto_load_cmd (const char *args, int from_tty) { struct cmd_list_element *list; - struct cleanup *infolist_chain; struct ui_out *uiout = current_uiout; - infolist_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "infolist"); + ui_out_emit_tuple tuple_emitter (uiout, "infolist"); for (list = *auto_load_info_cmdlist_get (); list != NULL; list = list->next) { - struct cleanup *option_chain - = make_cleanup_ui_out_tuple_begin_end (uiout, "option"); + ui_out_emit_tuple option_emitter (uiout, "option"); gdb_assert (!list->prefixlist); gdb_assert (list->type == not_set_cmd); - ui_out_field_string (uiout, "name", list->name); - ui_out_text (uiout, ": "); + uiout->field_string ("name", list->name); + uiout->text (": "); cmd_func (list, auto_load_info_scripts_pattern_nl, from_tty); - - /* Close the tuple. */ - do_cleanups (option_chain); } - - /* Close the tuple. */ - do_cleanups (infolist_chain); } /* Initialize "info auto-load " commands prefix and return it. */ @@ -1392,8 +1530,6 @@ found and/or loaded."), return &retval; } -void _initialize_auto_load (void); - void _initialize_auto_load (void) { @@ -1402,11 +1538,7 @@ _initialize_auto_load (void) char *guile_name_help; const char *suffix; - auto_load_pspace_data - = register_program_space_data_with_cleanup (NULL, - auto_load_pspace_data_cleanup); - - observer_attach_new_objfile (auto_load_new_objfile); + gdb::observers::new_objfile.attach (auto_load_new_objfile); add_setshow_boolean_cmd ("gdb-scripts", class_support, &auto_load_gdb_scripts, _("\ @@ -1415,7 +1547,7 @@ Show whether auto-loading of canned sequences of commands scripts is enabled."), _("\ If enabled, canned sequences of commands are loaded when the debugger reads\n\ an executable or shared library.\n\ -This options has security implications for untrusted inferiors."), +This option has security implications for untrusted inferiors."), NULL, show_auto_load_gdb_scripts, auto_load_set_cmdlist_get (), auto_load_show_cmdlist_get ()); @@ -1433,7 +1565,7 @@ Show whether auto-loading .gdbinit script in current directory is enabled."), If enabled, canned sequences of commands are loaded when debugger starts\n\ from .gdbinit file in current directory. Such files are deprecated,\n\ use a script associated with inferior executable file instead.\n\ -This options has security implications for untrusted inferiors."), +This option has security implications for untrusted inferiors."), NULL, show_auto_load_local_gdbinit, auto_load_set_cmdlist_get (), auto_load_show_cmdlist_get ()); @@ -1511,12 +1643,12 @@ Setting this parameter to '/' (without the quotes) allows any file\n\ for the 'set auto-load ...' options. Each path entry can be also shell\n\ wildcard pattern; '*' does not match directory separator.\n\ This option is ignored for the kinds of files having 'set auto-load ... off'.\n\ -This options has security implications for untrusted inferiors."), +This option has security implications for untrusted inferiors."), set_auto_load_safe_path, show_auto_load_safe_path, auto_load_set_cmdlist_get (), auto_load_show_cmdlist_get ()); - observer_attach_gdb_datadir_changed (auto_load_gdb_datadir_changed); + gdb::observers::gdb_datadir_changed.attach (auto_load_gdb_datadir_changed); cmd = add_cmd ("add-auto-load-safe-path", class_support, add_auto_load_safe_path, @@ -1527,6 +1659,15 @@ access the current full list setting."), &cmdlist); set_cmd_completer (cmd, filename_completer); + cmd = add_cmd ("add-auto-load-scripts-directory", class_support, + add_auto_load_dir, + _("Add entries to the list of directories from which to load " + "auto-loaded scripts.\n\ +See the commands 'set auto-load scripts-directory' and\n\ +'show auto-load scripts-directory' to access the current full list setting."), + &cmdlist); + set_cmd_completer (cmd, filename_completer); + add_setshow_boolean_cmd ("auto-load", class_maintenance, &debug_auto_load, _("\ Set auto-load verifications debugging."), _("\