| Index: gdb/auto-load.c
|
| diff --git a/gdb/auto-load.c b/gdb/auto-load.c
|
| index 5ace0de8d27bcc581c90705ad290d00a3faeb7e2..e516c6a4252b9d85519105aed20687eacf49948d 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 Free Software Foundation, Inc.
|
| + Copyright (C) 2012-2013 Free Software Foundation, Inc.
|
|
|
| This file is part of GDB.
|
|
|
| @@ -30,6 +30,7 @@
|
| #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"
|
| @@ -38,6 +39,15 @@
|
| #include "observer.h"
|
| #include "fnmatch.h"
|
| #include "top.h"
|
| +#include "filestuff.h"
|
| +
|
| +/* The section to look in for auto-loaded scripts (in file formats that
|
| + support sections).
|
| + Each entry in this section is a record that begins with a leading byte
|
| + identifying the record type.
|
| + At the moment we only support one record type: A leading byte of 1,
|
| + followed by the path of a python script to load. */
|
| +#define AUTO_SECTION_NAME ".debug_gdb_scripts"
|
|
|
| /* The suffix of per-objfile scripts to auto-load as non-Python command files.
|
| E.g. When the program loads libfoo.so, look for libfoo-gdb.gdb. */
|
| @@ -78,6 +88,14 @@ show_auto_load_gdb_scripts (struct ui_file *file, int from_tty,
|
| value);
|
| }
|
|
|
| +/* Return non-zero if auto-loading gdb scripts is enabled. */
|
| +
|
| +static int
|
| +auto_load_gdb_scripts_enabled (void)
|
| +{
|
| + return auto_load_gdb_scripts;
|
| +}
|
| +
|
| /* Internal-use flag to enable/disable auto-loading.
|
| This is true if we should auto-load python code when an objfile is opened,
|
| false otherwise.
|
| @@ -178,7 +196,6 @@ auto_load_expand_dir_vars (const char *string)
|
| static void
|
| auto_load_safe_path_vec_update (void)
|
| {
|
| - VEC (char_ptr) *dir_vec = NULL;
|
| unsigned len;
|
| int ix;
|
|
|
| @@ -502,31 +519,20 @@ For more information about this security protection see the\n\
|
|
|
| /* Definition of script language for GDB canned sequences of commands. */
|
|
|
| -static const struct script_language script_language_gdb
|
| - = { GDB_AUTO_FILE_NAME, source_gdb_script_for_objfile };
|
| +static const struct script_language script_language_gdb =
|
| +{
|
| + "gdb",
|
| + GDB_AUTO_FILE_NAME,
|
| + auto_load_gdb_scripts_enabled,
|
| + source_gdb_script_for_objfile
|
| +};
|
|
|
| static void
|
| source_gdb_script_for_objfile (struct objfile *objfile, FILE *file,
|
| const char *filename)
|
| {
|
| - int is_safe;
|
| - struct auto_load_pspace_info *pspace_info;
|
| volatile struct gdb_exception e;
|
|
|
| - is_safe = file_is_auto_load_safe (filename, _("auto-load: Loading canned "
|
| - "sequences of commands script "
|
| - "\"%s\" for objfile \"%s\".\n"),
|
| - filename, objfile->name);
|
| -
|
| - /* Add this script to the hash table too so "info auto-load gdb-scripts"
|
| - can print it. */
|
| - pspace_info = get_auto_load_pspace_data_for_loading (current_program_space);
|
| - maybe_add_script (pspace_info, is_safe, filename, filename,
|
| - &script_language_gdb);
|
| -
|
| - if (!is_safe)
|
| - return;
|
| -
|
| TRY_CATCH (e, RETURN_MASK_ALL)
|
| {
|
| script_from_file (file, filename);
|
| @@ -572,15 +578,11 @@ static const struct program_space_data *auto_load_pspace_data;
|
| static void
|
| auto_load_pspace_data_cleanup (struct program_space *pspace, void *arg)
|
| {
|
| - struct auto_load_pspace_info *info;
|
| + struct auto_load_pspace_info *info = arg;
|
|
|
| - info = program_space_data (pspace, auto_load_pspace_data);
|
| - if (info != NULL)
|
| - {
|
| - if (info->loaded_scripts)
|
| - htab_delete (info->loaded_scripts);
|
| - xfree (info);
|
| - }
|
| + if (info->loaded_scripts)
|
| + htab_delete (info->loaded_scripts);
|
| + xfree (info);
|
| }
|
|
|
| /* Get the current autoload data. If none is found yet, add it now. This
|
| @@ -739,7 +741,7 @@ auto_load_objfile_script_1 (struct objfile *objfile, const char *realname,
|
|
|
| cleanups = make_cleanup (xfree, filename);
|
|
|
| - input = fopen (filename, "r");
|
| + input = gdb_fopen_cloexec (filename, "r");
|
| debugfile = filename;
|
| if (debug_auto_load)
|
| fprintf_unfiltered (gdb_stdlog, _("auto-load: Attempted file \"%s\" %s.\n"),
|
| @@ -771,7 +773,7 @@ auto_load_objfile_script_1 (struct objfile *objfile, const char *realname,
|
| strcat (debugfile, filename);
|
|
|
| make_cleanup (xfree, debugfile);
|
| - input = fopen (debugfile, "r");
|
| + input = gdb_fopen_cloexec (debugfile, "r");
|
| if (debug_auto_load)
|
| fprintf_unfiltered (gdb_stdlog, _("auto-load: Attempted file "
|
| "\"%s\" %s.\n"),
|
| @@ -784,14 +786,31 @@ auto_load_objfile_script_1 (struct objfile *objfile, const char *realname,
|
|
|
| if (input)
|
| {
|
| + int is_safe;
|
| + struct auto_load_pspace_info *pspace_info;
|
| +
|
| make_cleanup_fclose (input);
|
|
|
| + is_safe
|
| + = file_is_auto_load_safe (filename,
|
| + _("auto-load: Loading %s script \"%s\""
|
| + " by extension for objfile \"%s\".\n"),
|
| + language->name, filename,
|
| + objfile_name (objfile));
|
| +
|
| + /* Add this script to the hash table too so
|
| + "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, filename, filename, language);
|
| +
|
| /* To preserve existing behaviour we don't check for whether the
|
| script was already in the table, and always load it.
|
| It's highly unlikely that we'd ever load it twice,
|
| and these scripts are required to be idempotent under multiple
|
| loads anyway. */
|
| - language->source_script_for_objfile (objfile, input, debugfile);
|
| + if (is_safe)
|
| + language->source_script_for_objfile (objfile, input, debugfile);
|
|
|
| retval = 1;
|
| }
|
| @@ -805,12 +824,21 @@ auto_load_objfile_script_1 (struct objfile *objfile, const char *realname,
|
| /* Look for the auto-load script in LANGUAGE associated with OBJFILE and load
|
| it. */
|
|
|
| -void
|
| +static void
|
| auto_load_objfile_script (struct objfile *objfile,
|
| const struct script_language *language)
|
| {
|
| - char *realname = gdb_realpath (objfile->name);
|
| - struct cleanup *cleanups = make_cleanup (xfree, realname);
|
| + char *realname;
|
| + struct cleanup *cleanups;
|
| +
|
| + /* Skip this script if support has not been compiled in or
|
| + auto-loading it has been disabled. */
|
| + if (language == NULL
|
| + || !language->auto_load_enabled ())
|
| + return;
|
| +
|
| + realname = gdb_realpath (objfile_name (objfile));
|
| + cleanups = make_cleanup (xfree, realname);
|
|
|
| if (!auto_load_objfile_script_1 (objfile, realname, language))
|
| {
|
| @@ -835,18 +863,170 @@ auto_load_objfile_script (struct objfile *objfile,
|
| do_cleanups (cleanups);
|
| }
|
|
|
| +/* Load scripts specified in OBJFILE.
|
| + START,END delimit a buffer containing a list of nul-terminated
|
| + 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.
|
| +
|
| + The section contains a list of path names of script files to load.
|
| + Each path is null-terminated. */
|
| +
|
| +static void
|
| +source_section_scripts (struct objfile *objfile, const char *section_name,
|
| + const char *start, const char *end)
|
| +{
|
| + const char *p;
|
| + struct auto_load_pspace_info *pspace_info;
|
| +
|
| + pspace_info = get_auto_load_pspace_data_for_loading (current_program_space);
|
| +
|
| + for (p = start; p < end; ++p)
|
| + {
|
| + const char *file;
|
| + FILE *stream;
|
| + char *full_path;
|
| + int opened, in_hash_table;
|
| + struct cleanup *back_to;
|
| + /* At the moment we only support python scripts in .debug_gdb_scripts,
|
| + but that can change. */
|
| + const struct script_language *language = gdbpy_script_language_defn ();
|
| +
|
| + if (*p != 1)
|
| + {
|
| + warning (_("Invalid entry in %s section"), section_name);
|
| + /* We could try various heuristics to find the next valid entry,
|
| + but it's safer to just punt. */
|
| + break;
|
| + }
|
| + file = ++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. */
|
| + break;
|
| + }
|
| + if (p == file)
|
| + {
|
| + warning (_("Empty path in %s"), section_name);
|
| + continue;
|
| + }
|
| +
|
| + /* Skip this script if support has not been compiled in or
|
| + auto-loading it has been disabled. */
|
| + if (language == NULL
|
| + || !language->auto_load_enabled ())
|
| + {
|
| + /* 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"),
|
| + language->name, 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), language->name);
|
| + }
|
| +
|
| + 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)
|
| + {
|
| + gdb_assert (language->source_script_for_objfile != NULL);
|
| + language->source_script_for_objfile (objfile, stream, full_path);
|
| + }
|
| +
|
| + do_cleanups (back_to);
|
| + }
|
| +}
|
| +
|
| +/* Load scripts specified in section SECTION_NAME of OBJFILE. */
|
| +
|
| +static void
|
| +auto_load_section_scripts (struct objfile *objfile, const char *section_name)
|
| +{
|
| + bfd *abfd = objfile->obfd;
|
| + asection *scripts_sect;
|
| + bfd_byte *data = NULL;
|
| +
|
| + scripts_sect = bfd_get_section_by_name (abfd, section_name);
|
| + if (scripts_sect == NULL)
|
| + 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));
|
| + else
|
| + {
|
| + struct cleanup *cleanups;
|
| + char *p = (char *) data;
|
| +
|
| + cleanups = make_cleanup (xfree, p);
|
| + source_section_scripts (objfile, section_name, p,
|
| + p + bfd_get_section_size (scripts_sect));
|
| + do_cleanups (cleanups);
|
| + }
|
| +}
|
| +
|
| /* Load any auto-loaded scripts for OBJFILE. */
|
|
|
| void
|
| load_auto_scripts_for_objfile (struct objfile *objfile)
|
| {
|
| - if (!global_auto_load)
|
| + /* 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)
|
| return;
|
|
|
| - if (auto_load_gdb_scripts)
|
| - auto_load_objfile_script (objfile, &script_language_gdb);
|
| + /* Load any scripts for this objfile. e.g. foo-gdb.gdb, foo-gdb.py. */
|
| + auto_load_objfile_script (objfile, &script_language_gdb);
|
| + auto_load_objfile_script (objfile, gdbpy_script_language_defn ());
|
|
|
| - gdbpy_load_auto_scripts_for_objfile (objfile);
|
| + /* Load any scripts mentioned in AUTO_SECTION_NAME (.debug_gdb_scripts). */
|
| + auto_load_section_scripts (objfile, AUTO_SECTION_NAME);
|
| }
|
|
|
| /* This is a new_objfile observer callback to auto-load scripts.
|
| @@ -978,11 +1158,9 @@ auto_load_info_scripts (char *pattern, int from_tty,
|
| {
|
| struct collect_matching_scripts_data data = { &scripts, language };
|
|
|
| - immediate_quit++;
|
| /* Pass a pointer to scripts as VEC_safe_push can realloc space. */
|
| htab_traverse_noresize (pspace_info->loaded_scripts,
|
| collect_matching_scripts, &data);
|
| - immediate_quit--;
|
| }
|
|
|
| nr_scripts = VEC_length (loaded_script_ptr, scripts);
|
| @@ -1086,7 +1264,7 @@ set_auto_load_cmd (char *args, int from_tty)
|
| if (list->var_type == var_boolean)
|
| {
|
| gdb_assert (list->type == set_cmd);
|
| - do_setshow_command (args, from_tty, list);
|
| + do_set_command (args, from_tty, list);
|
| }
|
| }
|
|
|
| @@ -1195,7 +1373,8 @@ _initialize_auto_load (void)
|
| char *scripts_directory_help;
|
|
|
| auto_load_pspace_data
|
| - = register_program_space_data_with_cleanup (auto_load_pspace_data_cleanup);
|
| + = register_program_space_data_with_cleanup (NULL,
|
| + auto_load_pspace_data_cleanup);
|
|
|
| observer_attach_new_objfile (auto_load_new_objfile);
|
|
|
|
|