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); |