/* 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 . */ #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 */