X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fauto-load.c;h=850c704ebf258e69eea973f791bf87fd404aaa60;hb=45a466b578083a05f1138eff9232254b1a30f683;hp=cfcab7b09ccb732ef50ec1206dc78c445e2a9c02;hpb=1564a2618d1766c3ea3a27dfa2ae77fe4ef51ef3;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/auto-load.c b/gdb/auto-load.c index cfcab7b09c..850c704ebf 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. @@ -36,6 +36,8 @@ #include "readline/tilde.h" #include "completer.h" #include "observer.h" +#include "fnmatch.h" +#include "top.h" /* 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. */ @@ -297,27 +299,85 @@ Use 'set auto-load safe-path /' for disabling the auto-load safe-path security.\ auto_load_safe_path_vec_update (); } -/* Return 1 if FILENAME is equal to DIR or if FILENAME belongs to the - subdirectory DIR. Return 0 otherwise. gdb_realpath normalization is never - done here. */ +/* Implementation for filename_is_in_pattern overwriting the caller's FILENAME + and PATTERN. */ -static ATTRIBUTE_PURE int -filename_is_in_dir (const char *filename, const char *dir) +static int +filename_is_in_pattern_1 (char *filename, char *pattern) { - size_t dir_len = strlen (dir); + size_t pattern_len = strlen (pattern); + size_t filename_len = strlen (filename); + + if (debug_auto_load) + fprintf_unfiltered (gdb_stdlog, _("auto-load: Matching file \"%s\" " + "to pattern \"%s\"\n"), + filename, pattern); - while (dir_len && IS_DIR_SEPARATOR (dir[dir_len - 1])) - dir_len--; + /* Trim trailing slashes ("/") from PATTERN. Even for "d:\" paths as + trailing slashes are trimmed also from FILENAME it still matches + correctly. */ + while (pattern_len && IS_DIR_SEPARATOR (pattern[pattern_len - 1])) + pattern_len--; + pattern[pattern_len] = '\0'; /* Ensure auto_load_safe_path "/" matches any FILENAME. On MS-Windows platform FILENAME even after gdb_realpath does not have to start with IS_DIR_SEPARATOR character, such as the 'C:\x.exe' filename. */ - if (dir_len == 0) - return 1; + if (pattern_len == 0) + { + if (debug_auto_load) + fprintf_unfiltered (gdb_stdlog, + _("auto-load: Matched - empty pattern\n")); + return 1; + } - return (filename_ncmp (dir, filename, dir_len) == 0 - && (IS_DIR_SEPARATOR (filename[dir_len]) - || filename[dir_len] == '\0')); + for (;;) + { + /* Trim trailing slashes ("/"). PATTERN also has slashes trimmed the + same way so they will match. */ + while (filename_len && IS_DIR_SEPARATOR (filename[filename_len - 1])) + filename_len--; + filename[filename_len] = '\0'; + if (filename_len == 0) + { + if (debug_auto_load) + fprintf_unfiltered (gdb_stdlog, + _("auto-load: Not matched - pattern \"%s\".\n"), + pattern); + return 0; + } + + if (gdb_filename_fnmatch (pattern, filename, FNM_FILE_NAME | FNM_NOESCAPE) + == 0) + { + if (debug_auto_load) + fprintf_unfiltered (gdb_stdlog, _("auto-load: Matched - file " + "\"%s\" to pattern \"%s\".\n"), + filename, pattern); + return 1; + } + + /* Trim trailing FILENAME component. */ + while (filename_len > 0 && !IS_DIR_SEPARATOR (filename[filename_len - 1])) + filename_len--; + } +} + +/* Return 1 if FILENAME matches PATTERN or if FILENAME resides in + a subdirectory of a directory that matches PATTERN. Return 0 otherwise. + gdb_realpath normalization is never done here. */ + +static ATTRIBUTE_PURE int +filename_is_in_pattern (const char *filename, const char *pattern) +{ + char *filename_copy, *pattern_copy; + + filename_copy = alloca (strlen (filename) + 1); + strcpy (filename_copy, filename); + pattern_copy = alloca (strlen (pattern) + 1); + strcpy (pattern_copy, pattern); + + return filename_is_in_pattern_1 (filename_copy, pattern_copy); } /* Return 1 if FILENAME belongs to one of directory components of @@ -330,14 +390,15 @@ static int filename_is_in_auto_load_safe_path_vec (const char *filename, char **filename_realp) { - char *dir; + char *pattern; int ix; - for (ix = 0; VEC_iterate (char_ptr, auto_load_safe_path_vec, ix, dir); ++ix) - if (*filename_realp == NULL && filename_is_in_dir (filename, dir)) + 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; - if (dir == NULL) + if (pattern == NULL) { if (*filename_realp == NULL) { @@ -350,18 +411,18 @@ filename_is_in_auto_load_safe_path_vec (const char *filename, } if (strcmp (*filename_realp, filename) != 0) - for (ix = 0; VEC_iterate (char_ptr, auto_load_safe_path_vec, ix, dir); - ++ix) - if (filename_is_in_dir (*filename_realp, dir)) + 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 (dir != NULL) + if (pattern != NULL) { if (debug_auto_load) fprintf_unfiltered (gdb_stdlog, _("auto-load: File \"%s\" matches " "directory \"%s\".\n"), - filename, dir); + filename, pattern); return 1; } @@ -381,6 +442,7 @@ file_is_auto_load_safe (const char *filename, const char *debug_fmt, ...) { char *filename_real = NULL; struct cleanup *back_to; + static int advice_printed = 0; if (debug_auto_load) { @@ -410,6 +472,30 @@ file_is_auto_load_safe (const char *filename, const char *debug_fmt, ...) "`auto-load safe-path' set to \"%s\"."), filename_real, 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); + + printf_filtered (_("\ +To enable execution of this file add\n\ +\tadd-auto-load-safe-path %s\n\ +line to your configuration file \"%s\".\n\ +To completely disable this security protection add\n\ +\tset auto-load safe-path /\n\ +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); + advice_printed = 1; + } + do_cleanups (back_to); return 0; } @@ -633,27 +719,25 @@ clear_section_scripts (void) } } -/* Look for the auto-load script in LANGUAGE associated with OBJFILE and load - it. */ +/* Look for the auto-load script in LANGUAGE associated with OBJFILE where + OBJFILE's gdb_realpath is REALNAME and load it. Return 1 if we found any + matching script, return 0 otherwise. */ -void -auto_load_objfile_script (struct objfile *objfile, - const struct script_language *language) +static int +auto_load_objfile_script_1 (struct objfile *objfile, const char *realname, + const struct script_language *language) { - char *realname; char *filename, *debugfile; - int len; + int len, retval; FILE *input; struct cleanup *cleanups; - realname = gdb_realpath (objfile->name); len = strlen (realname); filename = xmalloc (len + strlen (language->suffix) + 1); memcpy (filename, realname, len); strcpy (filename + len, language->suffix); cleanups = make_cleanup (xfree, filename); - make_cleanup (xfree, realname); input = fopen (filename, "r"); debugfile = filename; @@ -708,6 +792,44 @@ auto_load_objfile_script (struct objfile *objfile, and these scripts are required to be idempotent under multiple loads anyway. */ language->source_script_for_objfile (objfile, input, debugfile); + + retval = 1; + } + else + retval = 0; + + do_cleanups (cleanups); + return retval; +} + +/* Look for the auto-load script in LANGUAGE associated with OBJFILE and load + it. */ + +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); + + if (!auto_load_objfile_script_1 (objfile, realname, 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); + const size_t lexe = sizeof (".exe") - 1; + + if (len > lexe && strcasecmp (realname + len - lexe, ".exe") == 0) + { + len -= lexe; + realname[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); + } } do_cleanups (cleanups); @@ -856,11 +978,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); @@ -964,7 +1084,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); } } @@ -1070,9 +1190,11 @@ void _initialize_auto_load (void) { struct cmd_list_element *cmd; + 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); @@ -1112,30 +1234,51 @@ Usage: info auto-load local-gdbinit"), auto_load_info_cmdlist_get ()); auto_load_dir = xstrdup (AUTO_LOAD_DIR); + scripts_directory_help = xstrprintf ( +#ifdef HAVE_PYTHON + _("\ +Automatically loaded Python scripts (named OBJFILE%s) and GDB scripts\n\ +(named OBJFILE%s) are located in one of the directories listed by this\n\ +option.\n\ +%s"), + GDBPY_AUTO_FILE_NAME, +#else + _("\ +Automatically loaded GDB scripts (named OBJFILE%s) are located in one\n\ +of the directories listed by this option.\n\ +%s"), +#endif + GDB_AUTO_FILE_NAME, + _("\ +This option is ignored for the kinds of scripts \ +having 'set auto-load ... off'.\n\ +Directories listed here need to be present also \ +in the 'set auto-load safe-path'\n\ +option.")); add_setshow_optional_filename_cmd ("scripts-directory", class_support, &auto_load_dir, _("\ Set the list of directories from which to load auto-loaded scripts."), _("\ -Show the list of directories from which to load auto-loaded scripts."), _("\ -Automatically loaded Python scripts and GDB scripts are located in one of the\n\ -directories listed by this option. This option is ignored for the kinds of\n\ -scripts having 'set auto-load ... off'. Directories listed here need to be\n\ -present also in the 'set auto-load safe-path' option."), +Show the list of directories from which to load auto-loaded scripts."), + scripts_directory_help, set_auto_load_dir, show_auto_load_dir, auto_load_set_cmdlist_get (), auto_load_show_cmdlist_get ()); + xfree (scripts_directory_help); auto_load_safe_path = xstrdup (AUTO_LOAD_SAFE_PATH); auto_load_safe_path_vec_update (); add_setshow_optional_filename_cmd ("safe-path", class_support, &auto_load_safe_path, _("\ -Set the list of directories from which it is safe to auto-load files."), _("\ -Show the list of directories from which it is safe to auto-load files."), _("\ +Set the list of files and directories that are safe for auto-loading."), _("\ +Show the list of files and directories that are safe for auto-loading."), _("\ Various files loaded automatically for the 'set auto-load ...' options must\n\ be located in one of the directories listed by this option. Warning will be\n\ printed and file will not be used otherwise.\n\ +You can mix both directory and filename entries.\n\ Setting this parameter to an empty list resets it to its default value.\n\ Setting this parameter to '/' (without the quotes) allows any file\n\ -for the 'set auto-load ...' options.\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."), set_auto_load_safe_path,