| /* GDB routines for supporting auto-loaded scripts. | |
| Copyright (C) 2010 Free Software Foundation, Inc. | |
| This file is part of GDB. | |
| This program is free software; you can redistribute it and/or modify | |
| it under the terms of the GNU General Public License as published by | |
| the Free Software Foundation; either version 3 of the License, or | |
| (at your option) any later version. | |
| This program is distributed in the hope that it will be useful, | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| GNU General Public License for more details. | |
| You should have received a copy of the GNU General Public License | |
| along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
| #include "defs.h" | |
| #include "gdb_string.h" | |
| #include "gdb_regex.h" | |
| #include "top.h" | |
| #include "exceptions.h" | |
| #include "command.h" | |
| #include "gdbcmd.h" | |
| #include "observer.h" | |
| #include "progspace.h" | |
| #include "objfiles.h" | |
| #include "python.h" | |
| #include "cli/cli-cmds.h" | |
| /* 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. | |
| Both gdbpy_auto_load && gdbpy_global_auto_load must be true to enable | |
| auto-loading. | |
| 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 gdbpy_global_auto_load = 1; | |
| #ifdef HAVE_PYTHON | |
| #include "python-internal.h" | |
| /* NOTE: It's trivial to also support auto-loading normal gdb scripts. | |
| There has yet to be a need so it's not implemented. */ | |
| /* The suffix of per-objfile scripts to auto-load. | |
| E.g. When the program loads libfoo.so, look for libfoo-gdb.py. */ | |
| #define GDBPY_AUTO_FILE_NAME "-gdb.py" | |
| /* The section to look for scripts (in file formats that support sections). | |
| Each entry in this section is a byte of value 1, and then the nul-terminated | |
| name of the script. The script name may include a directory. | |
| The leading byte is to allow upward compatible extensions. */ | |
| #define GDBPY_AUTO_SECTION_NAME ".debug_gdb_scripts" | |
| /* For scripts specified in .debug_gdb_scripts, multiple objfiles may load | |
| the same script. There's no point in loading the script multiple times, | |
| and there can be a lot of objfiles and scripts, so we keep track of scripts | |
| loaded this way. */ | |
| struct auto_load_pspace_info | |
| { | |
| /* For each program space we keep track of loaded scripts. */ | |
| struct htab *loaded_scripts; | |
| }; | |
| /* Objects of this type are stored in the loaded script hash table. */ | |
| struct loaded_script_entry | |
| { | |
| /* Name as provided by the objfile. */ | |
| const char *name; | |
| /* Full path name or NULL if script wasn't found (or was otherwise | |
| inaccessible). */ | |
| const char *full_path; | |
| }; | |
| /* User-settable option to enable/disable auto-loading: | |
| maint set python auto-load on|off | |
| This is true if we should auto-load python code when an objfile is opened, | |
| false otherwise. */ | |
| static int gdbpy_auto_load = 1; | |
| /* Per-program-space data key. */ | |
| 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; | |
| info = program_space_data (pspace, auto_load_pspace_data); | |
| if (info != NULL) | |
| { | |
| 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 | |
| function always returns a valid object. */ | |
| static struct auto_load_pspace_info * | |
| get_auto_load_pspace_data (struct program_space *pspace) | |
| { | |
| struct auto_load_pspace_info *info; | |
| info = program_space_data (pspace, auto_load_pspace_data); | |
| if (info == NULL) | |
| { | |
| info = XZALLOC (struct auto_load_pspace_info); | |
| set_program_space_data (pspace, auto_load_pspace_data, info); | |
| } | |
| return info; | |
| } | |
| /* Hash function for the loaded script hash. */ | |
| static hashval_t | |
| hash_loaded_script_entry (const void *data) | |
| { | |
| const struct loaded_script_entry *e = data; | |
| return htab_hash_string (e->name); | |
| } | |
| /* Equality function for the loaded script hash. */ | |
| static int | |
| eq_loaded_script_entry (const void *a, const void *b) | |
| { | |
| const struct loaded_script_entry *ea = a; | |
| const struct loaded_script_entry *eb = b; | |
| return strcmp (ea->name, eb->name) == 0; | |
| } | |
| /* Create the hash table used for loaded scripts. | |
| Each entry is hashed by the full path name. */ | |
| static void | |
| create_loaded_scripts_hash (struct auto_load_pspace_info *pspace_info) | |
| { | |
| /* Choose 31 as the starting size of the hash table, somewhat arbitrarily. | |
| 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); | |
| } | |
| /* Load scripts specified in OBJFILE. | |
| START,END delimit a buffer containing a list of nul-terminated | |
| file names. | |
| SOURCE_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 files containing | |
| python code to load. Each path is null-terminated. */ | |
| static void | |
| source_section_scripts (struct objfile *objfile, const char *source_name, | |
| const char *start, const char *end) | |
| { | |
| const char *p; | |
| struct auto_load_pspace_info *pspace_info; | |
| struct loaded_script_entry **slot, entry; | |
| pspace_info = get_auto_load_pspace_data (current_program_space); | |
| if (pspace_info->loaded_scripts == NULL) | |
| create_loaded_scripts_hash (pspace_info); | |
| for (p = start; p < end; ++p) | |
| { | |
| const char *file; | |
| FILE *stream; | |
| char *full_path; | |
| int opened, in_hash_table; | |
| if (*p != 1) | |
| { | |
| warning (_("Invalid entry in %s section"), GDBPY_AUTO_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"), | |
| source_name, buf); | |
| /* Don't load it. */ | |
| break; | |
| } | |
| if (p == file) | |
| { | |
| warning (_("Empty path in %s"), source_name); | |
| continue; | |
| } | |
| opened = find_and_open_script (file, 1 /*search_path*/, | |
| &stream, &full_path); | |
| /* If the file is not found, we still record the file in the hash table, | |
| we only want to print an error message once. | |
| IWBN if complaints.c were more general-purpose. */ | |
| entry.name = file; | |
| if (opened) | |
| entry.full_path = full_path; | |
| else | |
| entry.full_path = NULL; | |
| slot = ((struct loaded_script_entry **) | |
| htab_find_slot (pspace_info->loaded_scripts, | |
| &entry, INSERT)); | |
| in_hash_table = *slot != NULL; | |
| /* If this file is not in the hash table, add it. */ | |
| if (! in_hash_table) | |
| { | |
| char *p; | |
| *slot = xmalloc (sizeof (**slot) | |
| + strlen (file) + 1 | |
| + (opened ? (strlen (full_path) + 1) : 0)); | |
| p = ((char*) *slot) + sizeof (**slot); | |
| strcpy (p, file); | |
| (*slot)->name = p; | |
| if (opened) | |
| { | |
| p += strlen (p) + 1; | |
| strcpy (p, full_path); | |
| (*slot)->full_path = p; | |
| } | |
| else | |
| (*slot)->full_path = NULL; | |
| } | |
| if (opened) | |
| free (full_path); | |
| if (! opened) | |
| { | |
| /* We don't throw an error, the program is still debuggable. | |
| Check in_hash_table to only print the warning once. */ | |
| if (! in_hash_table) | |
| warning (_("%s (referenced in %s): %s"), | |
| file, GDBPY_AUTO_SECTION_NAME, safe_strerror (errno)); | |
| continue; | |
| } | |
| /* If this file is not currently loaded, load it. */ | |
| if (! in_hash_table) | |
| source_python_script_for_objfile (objfile, stream, file); | |
| } | |
| } | |
| /* 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_size_type size; | |
| char *p; | |
| struct cleanup *cleanups; | |
| scripts_sect = bfd_get_section_by_name (abfd, section_name); | |
| if (scripts_sect == NULL) | |
| return; | |
| size = bfd_get_section_size (scripts_sect); | |
| p = xmalloc (size); | |
| cleanups = make_cleanup (xfree, p); | |
| if (bfd_get_section_contents (abfd, scripts_sect, p, (file_ptr) 0, size)) | |
| source_section_scripts (objfile, section_name, p, p + size); | |
| else | |
| warning (_("Couldn't read %s section of %s"), | |
| section_name, bfd_get_filename (abfd)); | |
| do_cleanups (cleanups); | |
| } | |
| /* Clear the table of loaded section scripts. */ | |
| static void | |
| 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; | |
| } | |
| } | |
| /* Look for the auto-load script associated with OBJFILE and load it. */ | |
| static void | |
| auto_load_objfile_script (struct objfile *objfile, const char *suffix) | |
| { | |
| char *realname; | |
| char *filename, *debugfile; | |
| int len; | |
| FILE *input; | |
| struct cleanup *cleanups; | |
| realname = gdb_realpath (objfile->name); | |
| len = strlen (realname); | |
| filename = xmalloc (len + strlen (suffix) + 1); | |
| memcpy (filename, realname, len); | |
| strcpy (filename + len, suffix); | |
| cleanups = make_cleanup (xfree, filename); | |
| make_cleanup (xfree, realname); | |
| input = fopen (filename, "r"); | |
| debugfile = filename; | |
| if (!input && debug_file_directory) | |
| { | |
| /* Also try the same file in the separate debug info directory. */ | |
| debugfile = xmalloc (strlen (filename) | |
| + strlen (debug_file_directory) + 1); | |
| strcpy (debugfile, debug_file_directory); | |
| /* FILENAME is absolute, so we don't need a "/" here. */ | |
| strcat (debugfile, filename); | |
| make_cleanup (xfree, debugfile); | |
| input = fopen (debugfile, "r"); | |
| } | |
| if (!input && gdb_datadir) | |
| { | |
| /* Also try the same file in a subdirectory of gdb's data | |
| directory. */ | |
| debugfile = xmalloc (strlen (gdb_datadir) + strlen (filename) | |
| + strlen ("/auto-load") + 1); | |
| strcpy (debugfile, gdb_datadir); | |
| strcat (debugfile, "/auto-load"); | |
| /* FILENAME is absolute, so we don't need a "/" here. */ | |
| strcat (debugfile, filename); | |
| make_cleanup (xfree, debugfile); | |
| input = fopen (debugfile, "r"); | |
| } | |
| if (input) | |
| { | |
| source_python_script_for_objfile (objfile, input, debugfile); | |
| fclose (input); | |
| } | |
| do_cleanups (cleanups); | |
| } | |
| /* This is a new_objfile observer callback to auto-load scripts. | |
| Two flavors of auto-loaded scripts are supported. | |
| 1) based on the path to the objfile | |
| 2) from .debug_gdb_scripts section */ | |
| static void | |
| auto_load_new_objfile (struct objfile *objfile) | |
| { | |
| if (!objfile) | |
| { | |
| /* OBJFILE is NULL when loading a new "main" symbol-file. */ | |
| clear_section_scripts (); | |
| return; | |
| } | |
| if (!objfile->name) | |
| return; | |
| load_auto_scripts_for_objfile (objfile); | |
| } | |
| /* Load any auto-loaded scripts for OBJFILE. */ | |
| void | |
| load_auto_scripts_for_objfile (struct objfile *objfile) | |
| { | |
| if (gdbpy_auto_load && gdbpy_global_auto_load) | |
| { | |
| auto_load_objfile_script (objfile, GDBPY_AUTO_FILE_NAME); | |
| auto_load_section_scripts (objfile, GDBPY_AUTO_SECTION_NAME); | |
| } | |
| } | |
| /* Traversal function for htab_traverse. | |
| Print the entry if specified in the regex. */ | |
| static int | |
| maybe_print_section_script (void **slot, void *info) | |
| { | |
| struct loaded_script_entry *entry = *slot; | |
| if (re_exec (entry->name)) | |
| { | |
| printf_filtered (_("Script name: %s\n"), entry->name); | |
| printf_filtered (_(" Full name: %s\n"), | |
| entry->full_path ? entry->full_path : _("unknown")); | |
| } | |
| return 1; | |
| } | |
| /* "maint print section-scripts" command. */ | |
| static void | |
| maintenance_print_section_scripts (char *pattern, int from_tty) | |
| { | |
| struct auto_load_pspace_info *pspace_info; | |
| dont_repeat (); | |
| if (pattern && *pattern) | |
| { | |
| char *re_err = re_comp (pattern); | |
| if (re_err) | |
| error (_("Invalid regexp: %s"), re_err); | |
| printf_filtered (_("Objfile scripts matching %s:\n"), pattern); | |
| } | |
| else | |
| { | |
| re_comp (""); | |
| printf_filtered (_("Objfile scripts:\n")); | |
| } | |
| pspace_info = get_auto_load_pspace_data (current_program_space); | |
| if (pspace_info == NULL || pspace_info->loaded_scripts == NULL) | |
| return; | |
| immediate_quit++; | |
| htab_traverse_noresize (pspace_info->loaded_scripts, | |
| maybe_print_section_script, NULL); | |
| immediate_quit--; | |
| } | |
| void | |
| gdbpy_initialize_auto_load (void) | |
| { | |
| auto_load_pspace_data | |
| = register_program_space_data_with_cleanup (auto_load_pspace_data_cleanup); | |
| observer_attach_new_objfile (auto_load_new_objfile); | |
| add_setshow_boolean_cmd ("auto-load", class_maintenance, | |
| &gdbpy_auto_load, _("\ | |
| Enable or disable auto-loading of Python code when an object is opened."), _("\ | |
| Show whether Python code will be auto-loaded when an object is opened."), _("\ | |
| Enables or disables auto-loading of Python code when an object is opened."), | |
| NULL, NULL, | |
| &set_python_list, | |
| &show_python_list); | |
| add_cmd ("section-scripts", class_maintenance, maintenance_print_section_scripts, | |
| _("Print dump of auto-loaded section scripts matching REGEXP."), | |
| &maintenanceprintlist); | |
| } | |
| #else /* ! HAVE_PYTHON */ | |
| void | |
| load_auto_scripts_for_objfile (struct objfile *objfile) | |
| { | |
| } | |
| #endif /* ! HAVE_PYTHON */ |