123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671 |
- /* GDB routines for supporting auto-loaded scripts.
- Copyright (C) 2012-2022 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 <ctype.h>
- #include "auto-load.h"
- #include "progspace.h"
- #include "gdbsupport/gdb_regex.h"
- #include "ui-out.h"
- #include "filenames.h"
- #include "command.h"
- #include "observable.h"
- #include "objfiles.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 "readline/tilde.h"
- #include "completer.h"
- #include "fnmatch.h"
- #include "top.h"
- #include "gdbsupport/filestuff.h"
- #include "extension.h"
- #include "gdb/section-scripts.h"
- #include <algorithm>
- #include "gdbsupport/pathstuff.h"
- #include "cli/cli-style.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 section to look in for the name of a separate debug file. */
- #define DEBUGLINK_SECTION_NAME ".gnu_debuglink"
- static void maybe_print_unsupported_script_warning
- (struct auto_load_pspace_info *, struct objfile *objfile,
- const struct extension_language_defn *language,
- const char *section_name, unsigned offset);
- static void maybe_print_script_not_found_warning
- (struct auto_load_pspace_info *, struct objfile *objfile,
- const struct extension_language_defn *language,
- const char *section_name, unsigned offset);
- /* See auto-load.h. */
- bool debug_auto_load = false;
- /* "show" command for the debug_auto_load configuration variable. */
- static void
- show_debug_auto_load (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
- {
- gdb_printf (file, _("Debugging output for files "
- "of 'set auto-load ...' is %s.\n"),
- value);
- }
- /* User-settable option to enable/disable auto-loading of GDB_AUTO_FILE_NAME
- scripts:
- set auto-load gdb-scripts on|off
- This is true if we should auto-load associated scripts when an objfile
- is opened, false otherwise. */
- static bool auto_load_gdb_scripts = true;
- /* "show" command for the auto_load_gdb_scripts configuration variable. */
- static void
- show_auto_load_gdb_scripts (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
- {
- gdb_printf (file, _("Auto-loading of canned sequences of commands "
- "scripts is %s.\n"),
- value);
- }
- /* See auto-load.h. */
- bool
- auto_load_gdb_scripts_enabled (const struct extension_language_defn *extlang)
- {
- 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.
- Both auto_load_scripts && 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. */
- bool global_auto_load = true;
- /* Auto-load .gdbinit file from the current directory? */
- bool auto_load_local_gdbinit = true;
- /* Absolute pathname to the current directory .gdbinit, if it exists. */
- char *auto_load_local_gdbinit_pathname = NULL;
- /* if AUTO_LOAD_LOCAL_GDBINIT_PATHNAME has been loaded. */
- bool auto_load_local_gdbinit_loaded = false;
- /* "show" command for the auto_load_local_gdbinit configuration variable. */
- static void
- show_auto_load_local_gdbinit (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
- {
- gdb_printf (file, _("Auto-loading of .gdbinit script from current "
- "directory is %s.\n"),
- value);
- }
- /* Directory list from which to load auto-loaded scripts. It is not checked
- for absolute paths but they are strongly recommended. It is initialized by
- _initialize_auto_load. */
- static std::string auto_load_dir = AUTO_LOAD_DIR;
- /* "set" command for the auto_load_dir configuration variable. */
- static void
- set_auto_load_dir (const char *args, int from_tty, struct cmd_list_element *c)
- {
- /* Setting the variable to "" resets it to the compile time defaults. */
- if (auto_load_dir.empty ())
- auto_load_dir = AUTO_LOAD_DIR;
- }
- /* "show" command for the auto_load_dir configuration variable. */
- static void
- show_auto_load_dir (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
- {
- gdb_printf (file, _("List of directories from which to load "
- "auto-loaded scripts is %s.\n"),
- value);
- }
- /* Directory list safe to hold auto-loaded files. It is not checked for
- absolute paths but they are strongly recommended. It is initialized by
- _initialize_auto_load. */
- static std::string auto_load_safe_path = AUTO_LOAD_SAFE_PATH;
- /* Vector of directory elements of AUTO_LOAD_SAFE_PATH with each one normalized
- by tilde_expand and possibly each entries has added its gdb_realpath
- counterpart. */
- static std::vector<gdb::unique_xmalloc_ptr<char>> auto_load_safe_path_vec;
- /* Expand $datadir and $debugdir in STRING according to the rules of
- substitute_path_component. */
- static std::vector<gdb::unique_xmalloc_ptr<char>>
- auto_load_expand_dir_vars (const char *string)
- {
- char *s = xstrdup (string);
- substitute_path_component (&s, "$datadir", gdb_datadir.c_str ());
- substitute_path_component (&s, "$debugdir", debug_file_directory.c_str ());
- if (debug_auto_load && strcmp (s, string) != 0)
- auto_load_debug_printf ("Expanded $-variables to \"%s\".", s);
- std::vector<gdb::unique_xmalloc_ptr<char>> dir_vec
- = dirnames_to_char_ptr_vec (s);
- xfree(s);
- return dir_vec;
- }
- /* Update auto_load_safe_path_vec from current AUTO_LOAD_SAFE_PATH. */
- static void
- auto_load_safe_path_vec_update (void)
- {
- auto_load_debug_printf ("Updating directories of \"%s\".",
- auto_load_safe_path.c_str ());
- auto_load_safe_path_vec
- = auto_load_expand_dir_vars (auto_load_safe_path.c_str ());
- size_t len = auto_load_safe_path_vec.size ();
- /* Apply tilde_expand and gdb_realpath to each AUTO_LOAD_SAFE_PATH_VEC
- element. */
- for (size_t i = 0; i < len; i++)
- {
- gdb::unique_xmalloc_ptr<char> &in_vec = auto_load_safe_path_vec[i];
- gdb::unique_xmalloc_ptr<char> expanded (tilde_expand (in_vec.get ()));
- gdb::unique_xmalloc_ptr<char> real_path = gdb_realpath (expanded.get ());
- /* Ensure the current entry is at least tilde_expand-ed. ORIGINAL makes
- sure we free the original string. */
- gdb::unique_xmalloc_ptr<char> original = std::move (in_vec);
- in_vec = std::move (expanded);
- if (debug_auto_load)
- {
- if (strcmp (in_vec.get (), original.get ()) == 0)
- auto_load_debug_printf ("Using directory \"%s\".",
- in_vec.get ());
- else
- auto_load_debug_printf ("Resolved directory \"%s\" as \"%s\".",
- original.get (), in_vec.get ());
- }
- /* If gdb_realpath returns a different content, append it. */
- if (strcmp (real_path.get (), in_vec.get ()) != 0)
- {
- auto_load_debug_printf ("And canonicalized as \"%s\".",
- real_path.get ());
- auto_load_safe_path_vec.push_back (std::move (real_path));
- }
- }
- }
- /* Variable gdb_datadir has been set. Update content depending on $datadir. */
- static void
- auto_load_gdb_datadir_changed (void)
- {
- auto_load_safe_path_vec_update ();
- }
- /* "set" command for the auto_load_safe_path configuration variable. */
- static void
- set_auto_load_safe_path (const char *args,
- int from_tty, struct cmd_list_element *c)
- {
- /* Setting the variable to "" resets it to the compile time defaults. */
- if (auto_load_safe_path.empty ())
- auto_load_safe_path = AUTO_LOAD_SAFE_PATH;
- auto_load_safe_path_vec_update ();
- }
- /* "show" command for the auto_load_safe_path configuration variable. */
- static void
- show_auto_load_safe_path (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
- {
- const char *cs;
- /* Check if user has entered either "/" or for example ":".
- But while more complicate content like ":/foo" would still also
- permit any location do not hide those. */
- for (cs = value; *cs && (*cs == DIRNAME_SEPARATOR || IS_DIR_SEPARATOR (*cs));
- cs++);
- if (*cs == 0)
- gdb_printf (file, _("Auto-load files are safe to load from any "
- "directory.\n"));
- else
- gdb_printf (file, _("List of directories from which it is safe to "
- "auto-load files is %s.\n"),
- value);
- }
- /* "add-auto-load-safe-path" command for the auto_load_safe_path configuration
- variable. */
- static void
- add_auto_load_safe_path (const char *args, int from_tty)
- {
- if (args == NULL || *args == 0)
- error (_("\
- Directory argument required.\n\
- Use 'set auto-load safe-path /' for disabling the auto-load safe-path security.\
- "));
- auto_load_safe_path = string_printf ("%s%c%s", auto_load_safe_path.c_str (),
- DIRNAME_SEPARATOR, args);
- auto_load_safe_path_vec_update ();
- }
- /* "add-auto-load-scripts-directory" command for the auto_load_dir configuration
- variable. */
- static void
- add_auto_load_dir (const char *args, int from_tty)
- {
- if (args == NULL || *args == 0)
- error (_("Directory argument required."));
- auto_load_dir = string_printf ("%s%c%s", auto_load_dir.c_str (),
- DIRNAME_SEPARATOR, args);
- }
- /* Implementation for filename_is_in_pattern overwriting the caller's FILENAME
- and PATTERN. */
- static int
- filename_is_in_pattern_1 (char *filename, char *pattern)
- {
- size_t pattern_len = strlen (pattern);
- size_t filename_len = strlen (filename);
- auto_load_debug_printf ("Matching file \"%s\" to pattern \"%s\"",
- filename, pattern);
- /* 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 (pattern_len == 0)
- {
- auto_load_debug_printf ("Matched - empty pattern");
- return 1;
- }
- 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)
- {
- auto_load_debug_printf ("Not matched - pattern \"%s\".", pattern);
- return 0;
- }
- if (gdb_filename_fnmatch (pattern, filename, FNM_FILE_NAME | FNM_NOESCAPE)
- == 0)
- {
- auto_load_debug_printf ("Matched - file \"%s\" to pattern \"%s\".",
- 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 = (char *) alloca (strlen (filename) + 1);
- strcpy (filename_copy, filename);
- pattern_copy = (char *) 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
- AUTO_LOAD_SAFE_PATH_VEC. Return 0 otherwise.
- auto_load_safe_path_vec_update is never called.
- *FILENAME_REALP may be updated by gdb_realpath of FILENAME. */
- static int
- filename_is_in_auto_load_safe_path_vec (const char *filename,
- gdb::unique_xmalloc_ptr<char> *filename_realp)
- {
- const char *pattern = NULL;
- for (const gdb::unique_xmalloc_ptr<char> &p : auto_load_safe_path_vec)
- if (*filename_realp == NULL && filename_is_in_pattern (filename, p.get ()))
- {
- pattern = p.get ();
- break;
- }
-
- if (pattern == NULL)
- {
- if (*filename_realp == NULL)
- {
- *filename_realp = gdb_realpath (filename);
- if (debug_auto_load && strcmp (filename_realp->get (), filename) != 0)
- auto_load_debug_printf ("Resolved file \"%s\" as \"%s\".",
- filename, filename_realp->get ());
- }
- if (strcmp (filename_realp->get (), filename) != 0)
- for (const gdb::unique_xmalloc_ptr<char> &p : auto_load_safe_path_vec)
- if (filename_is_in_pattern (filename_realp->get (), p.get ()))
- {
- pattern = p.get ();
- break;
- }
- }
- if (pattern != NULL)
- {
- auto_load_debug_printf ("File \"%s\" matches directory \"%s\".",
- filename, pattern);
- return 1;
- }
- return 0;
- }
- /* See auto-load.h. */
- bool
- file_is_auto_load_safe (const char *filename)
- {
- gdb::unique_xmalloc_ptr<char> filename_real;
- static bool advice_printed = false;
- if (filename_is_in_auto_load_safe_path_vec (filename, &filename_real))
- return true;
- auto_load_safe_path_vec_update ();
- if (filename_is_in_auto_load_safe_path_vec (filename, &filename_real))
- return true;
- warning (_("File \"%ps\" auto-loading has been declined by your "
- "`auto-load safe-path' set to \"%s\"."),
- styled_string (file_name_style.style (), filename_real.get ()),
- auto_load_safe_path.c_str ());
- if (!advice_printed)
- {
- /* Find the existing home directory config file. */
- struct stat buf;
- std::string home_config = find_gdb_home_config_file (GDBINIT, &buf);
- if (home_config.empty ())
- {
- /* The user doesn't have an existing home directory config file,
- so we should suggest a suitable path for them to use. */
- std::string config_dir_file
- = get_standard_config_filename (GDBINIT);
- if (!config_dir_file.empty ())
- home_config = config_dir_file;
- else
- {
- const char *homedir = getenv ("HOME");
- if (homedir == nullptr)
- homedir = "$HOME";
- home_config = (std::string (homedir) + SLASH_STRING
- + std::string (GDBINIT));
- }
- }
- gdb_printf (_("\
- To enable execution of this file add\n\
- \tadd-auto-load-safe-path %s\n\
- line to your configuration file \"%ps\".\n\
- To completely disable this security protection add\n\
- \tset auto-load safe-path /\n\
- line to your configuration file \"%ps\".\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.get (),
- styled_string (file_name_style.style (),
- home_config.c_str ()),
- styled_string (file_name_style.style (),
- home_config.c_str ()));
- advice_printed = true;
- }
- return false;
- }
- /* 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, both when
- specified as file names and as scripts to be executed directly. */
- htab_up loaded_script_files;
- htab_up loaded_script_texts;
- /* Non-zero if we've issued the warning about an auto-load script not being
- supported. We only want to issue this warning once. */
- bool unsupported_script_warning_printed = false;
- /* Non-zero if we've issued the warning about an auto-load script not being
- found. We only want to issue this warning once. */
- bool script_not_found_warning_printed = false;
- };
- /* Objects of this type are stored in the loaded_script hash table. */
- struct loaded_script
- {
- /* Name as provided by the objfile. */
- const char *name;
- /* Full path name or NULL if script wasn't found (or was otherwise
- inaccessible), or NULL for loaded_script_texts. */
- const char *full_path;
- /* True if this script has been loaded. */
- bool loaded;
- const struct extension_language_defn *language;
- };
- /* Per-program-space data key. */
- static const struct program_space_key<struct auto_load_pspace_info>
- auto_load_pspace_data;
- /* 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 = auto_load_pspace_data.get (pspace);
- if (info == NULL)
- info = auto_load_pspace_data.emplace (pspace);
- return info;
- }
- /* Hash function for the loaded script hash. */
- static hashval_t
- hash_loaded_script_entry (const void *data)
- {
- const struct loaded_script *e = (const struct loaded_script *) data;
- return htab_hash_string (e->name) ^ htab_hash_pointer (e->language);
- }
- /* Equality function for the loaded script hash. */
- static int
- eq_loaded_script_entry (const void *a, const void *b)
- {
- const struct loaded_script *ea = (const struct loaded_script *) a;
- const struct loaded_script *eb = (const struct loaded_script *) b;
- return strcmp (ea->name, eb->name) == 0 && ea->language == eb->language;
- }
- /* Initialize the table to track loaded scripts.
- Each entry is hashed by the full path name. */
- static void
- init_loaded_scripts_info (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_script_files.reset
- (htab_create (31,
- hash_loaded_script_entry,
- eq_loaded_script_entry,
- xfree));
- pspace_info->loaded_script_texts.reset
- (htab_create (31,
- hash_loaded_script_entry,
- eq_loaded_script_entry,
- xfree));
- pspace_info->unsupported_script_warning_printed = false;
- pspace_info->script_not_found_warning_printed = false;
- }
- /* Wrapper on get_auto_load_pspace_data to also allocate the hash table
- for loading scripts. */
- struct auto_load_pspace_info *
- get_auto_load_pspace_data_for_loading (struct program_space *pspace)
- {
- struct auto_load_pspace_info *info;
- info = get_auto_load_pspace_data (pspace);
- if (info->loaded_script_files == NULL)
- init_loaded_scripts_info (info);
- return info;
- }
- /* Add script file NAME in LANGUAGE to hash table of PSPACE_INFO.
- LOADED is true if the script has been (is going to) be loaded, false
- otherwise (such as if it has not been found).
- FULL_PATH is NULL if the script wasn't found.
- The result is true if the script was already in the hash table. */
- static bool
- maybe_add_script_file (struct auto_load_pspace_info *pspace_info, bool loaded,
- const char *name, const char *full_path,
- const struct extension_language_defn *language)
- {
- struct htab *htab = pspace_info->loaded_script_files.get ();
- struct loaded_script **slot, entry;
- entry.name = name;
- entry.language = language;
- slot = (struct loaded_script **) htab_find_slot (htab, &entry, INSERT);
- bool in_hash_table = *slot != NULL;
- /* If this script is not in the hash table, add it. */
- if (!in_hash_table)
- {
- char *p;
- /* Allocate all space in one chunk so it's easier to free. */
- *slot = ((struct loaded_script *)
- xmalloc (sizeof (**slot)
- + strlen (name) + 1
- + (full_path != NULL ? (strlen (full_path) + 1) : 0)));
- p = ((char*) *slot) + sizeof (**slot);
- strcpy (p, name);
- (*slot)->name = p;
- if (full_path != NULL)
- {
- p += strlen (p) + 1;
- strcpy (p, full_path);
- (*slot)->full_path = p;
- }
- else
- (*slot)->full_path = NULL;
- (*slot)->loaded = loaded;
- (*slot)->language = language;
- }
- return in_hash_table;
- }
- /* Add script contents NAME in LANGUAGE to hash table of PSPACE_INFO.
- LOADED is true if the script has been (is going to) be loaded, false
- otherwise (such as if it has not been found).
- The result is true if the script was already in the hash table. */
- static bool
- maybe_add_script_text (struct auto_load_pspace_info *pspace_info,
- bool loaded, const char *name,
- const struct extension_language_defn *language)
- {
- struct htab *htab = pspace_info->loaded_script_texts.get ();
- struct loaded_script **slot, entry;
- entry.name = name;
- entry.language = language;
- slot = (struct loaded_script **) htab_find_slot (htab, &entry, INSERT);
- bool in_hash_table = *slot != NULL;
- /* If this script is not in the hash table, add it. */
- if (!in_hash_table)
- {
- char *p;
- /* Allocate all space in one chunk so it's easier to free. */
- *slot = ((struct loaded_script *)
- xmalloc (sizeof (**slot) + strlen (name) + 1));
- p = ((char*) *slot) + sizeof (**slot);
- strcpy (p, name);
- (*slot)->name = p;
- (*slot)->full_path = NULL;
- (*slot)->loaded = loaded;
- (*slot)->language = language;
- }
- return in_hash_table;
- }
- /* 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 = auto_load_pspace_data.get (pspace);
- if (info != NULL && info->loaded_script_files != NULL)
- auto_load_pspace_data.clear (pspace);
- }
- /* 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. */
- static int
- auto_load_objfile_script_1 (struct objfile *objfile, const char *realname,
- const struct extension_language_defn *language)
- {
- const char *debugfile;
- int retval;
- const char *suffix = ext_lang_auto_load_suffix (language);
- std::string filename = std::string (realname) + suffix;
- gdb_file_up input = gdb_fopen_cloexec (filename.c_str (), "r");
- debugfile = filename.c_str ();
- auto_load_debug_printf ("Attempted file \"%ps\" %s.",
- styled_string (file_name_style.style (), debugfile),
- input != nullptr ? "exists" : "does not exist");
- std::string debugfile_holder;
- if (!input)
- {
- /* Also try the same file in a subdirectory of gdb's data
- directory. */
- std::vector<gdb::unique_xmalloc_ptr<char>> vec
- = auto_load_expand_dir_vars (auto_load_dir.c_str ());
- auto_load_debug_printf
- ("Searching 'set auto-load scripts-directory' path \"%s\".",
- auto_load_dir.c_str ());
- /* Convert Windows file name from c:/dir/file to /c/dir/file. */
- if (HAS_DRIVE_SPEC (debugfile))
- filename = (std::string("\\") + debugfile[0]
- + STRIP_DRIVE_SPEC (debugfile));
- for (const gdb::unique_xmalloc_ptr<char> &dir : vec)
- {
- /* FILENAME is absolute, so we don't need a "/" here. */
- debugfile_holder = dir.get () + filename;
- debugfile = debugfile_holder.c_str ();
- input = gdb_fopen_cloexec (debugfile, "r");
- auto_load_debug_printf ("Attempted file \"%ps\" %s.",
- styled_string (file_name_style.style (),
- debugfile),
- (input != nullptr
- ? "exists"
- : "does not exist"));
- if (input != NULL)
- break;
- }
- }
- if (input)
- {
- struct auto_load_pspace_info *pspace_info;
- auto_load_debug_printf
- ("Loading %s script \"%s\" by extension for objfile \"%s\".",
- ext_lang_name (language), debugfile, objfile_name (objfile));
- bool is_safe = file_is_auto_load_safe (debugfile);
- /* 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_file (pspace_info, is_safe, debugfile, debugfile,
- 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. */
- if (is_safe)
- {
- objfile_script_sourcer_func *sourcer
- = ext_lang_objfile_script_sourcer (language);
- /* We shouldn't get here if support for the language isn't
- compiled in. And the extension language is required to implement
- this function. */
- gdb_assert (sourcer != NULL);
- sourcer (language, objfile, input.get (), debugfile);
- }
- retval = 1;
- }
- else
- retval = 0;
- 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 extension_language_defn *language)
- {
- gdb::unique_xmalloc_ptr<char> realname
- = gdb_realpath (objfile_name (objfile));
- if (auto_load_objfile_script_1 (objfile, realname.get (), language))
- return;
- /* 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.get ());
- const size_t lexe = sizeof (".exe") - 1;
- if (len > lexe && strcasecmp (realname.get () + len - lexe, ".exe") == 0)
- {
- len -= lexe;
- realname.get ()[len] = '\0';
- auto_load_debug_printf
- ("Stripped .exe suffix, retrying with \"%s\".", realname.get ());
- auto_load_objfile_script_1 (objfile, realname.get (), language);
- return;
- }
- /* If OBJFILE is a separate debug file and its name does not match
- the name given in the parent's .gnu_debuglink section, try to
- find the auto-load script using the parent's path and the
- debuglink name. */
- struct objfile *parent = objfile->separate_debug_objfile_backlink;
- if (parent != nullptr)
- {
- unsigned long crc32;
- gdb::unique_xmalloc_ptr<char> debuglink
- (bfd_get_debug_link_info (parent->obfd, &crc32));
- if (debuglink.get () != nullptr
- && strcmp (debuglink.get (), lbasename (realname.get ())) != 0)
- {
- /* Replace the last component of the parent's path with the
- debuglink name. */
- std::string p_realname = gdb_realpath (objfile_name (parent)).get ();
- size_t last = p_realname.find_last_of ('/');
- if (last != std::string::npos)
- {
- p_realname.replace (last + 1, std::string::npos,
- debuglink.get ());
- auto_load_debug_printf
- ("Debug filename mismatch, retrying with \"%s\".",
- p_realname.c_str ());
- auto_load_objfile_script_1 (objfile,
- p_realname.c_str (), language);
- }
- }
- }
- }
- /* Subroutine of source_section_scripts to simplify it.
- Load FILE as a script in extension language LANGUAGE.
- The script is from section SECTION_NAME in OBJFILE at offset OFFSET. */
- static void
- source_script_file (struct auto_load_pspace_info *pspace_info,
- struct objfile *objfile,
- const struct extension_language_defn *language,
- const char *section_name, unsigned int offset,
- const char *file)
- {
- objfile_script_sourcer_func *sourcer;
- /* Skip this script if support is not compiled in. */
- sourcer = ext_lang_objfile_script_sourcer (language);
- if (sourcer == NULL)
- {
- /* We don't throw an error, the program is still debuggable. */
- maybe_print_unsupported_script_warning (pspace_info, objfile, language,
- section_name, offset);
- /* We *could* still try to open it, but there's no point. */
- maybe_add_script_file (pspace_info, 0, file, NULL, language);
- return;
- }
- /* Skip this script if auto-loading it has been disabled. */
- if (!ext_lang_auto_load_enabled (language))
- {
- /* No message is printed, just skip it. */
- return;
- }
- gdb::optional<open_script> opened = find_and_open_script (file,
- 1 /*search_path*/);
- if (opened)
- {
- auto_load_debug_printf
- ("Loading %s script \"%s\" from section \"%s\" of objfile \"%s\".",
- ext_lang_name (language), opened->full_path.get (),
- section_name, objfile_name (objfile));
- if (!file_is_auto_load_safe (opened->full_path.get ()))
- opened.reset ();
- }
- else
- {
- /* 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. */
- maybe_print_script_not_found_warning (pspace_info, objfile, language,
- section_name, offset);
- }
- bool in_hash_table
- = maybe_add_script_file (pspace_info, bool (opened), file,
- (opened ? opened->full_path.get (): NULL),
- language);
- /* If this file is not currently loaded, load it. */
- if (opened && !in_hash_table)
- sourcer (language, objfile, opened->stream.get (),
- opened->full_path.get ());
- }
- /* Subroutine of source_section_scripts to simplify it.
- Execute SCRIPT as a script in extension language LANG.
- The script is from section SECTION_NAME in OBJFILE at offset OFFSET. */
- static void
- execute_script_contents (struct auto_load_pspace_info *pspace_info,
- struct objfile *objfile,
- const struct extension_language_defn *language,
- const char *section_name, unsigned int offset,
- const char *script)
- {
- objfile_script_executor_func *executor;
- const char *newline, *script_text;
- const char *name;
- /* The first line of the script is the name of the script.
- It must not contain any kind of space character. */
- name = NULL;
- newline = strchr (script, '\n');
- std::string name_holder;
- if (newline != NULL)
- {
- const char *buf, *p;
- /* Put the name in a buffer and validate it. */
- name_holder = std::string (script, newline - script);
- buf = name_holder.c_str ();
- for (p = buf; *p != '\0'; ++p)
- {
- if (isspace (*p))
- break;
- }
- /* We don't allow nameless scripts, they're not helpful to the user. */
- if (p != buf && *p == '\0')
- name = buf;
- }
- if (name == NULL)
- {
- /* We don't throw an error, the program is still debuggable. */
- warning (_("\
- Missing/bad script name in entry at offset %u in section %s\n\
- of file %ps."),
- offset, section_name,
- styled_string (file_name_style.style (),
- objfile_name (objfile)));
- return;
- }
- script_text = newline + 1;
- /* Skip this script if support is not compiled in. */
- executor = ext_lang_objfile_script_executor (language);
- if (executor == NULL)
- {
- /* We don't throw an error, the program is still debuggable. */
- maybe_print_unsupported_script_warning (pspace_info, objfile, language,
- section_name, offset);
- maybe_add_script_text (pspace_info, 0, name, language);
- return;
- }
- /* Skip this script if auto-loading it has been disabled. */
- if (!ext_lang_auto_load_enabled (language))
- {
- /* No message is printed, just skip it. */
- return;
- }
- auto_load_debug_printf
- ("Loading %s script \"%s\" from section \"%s\" of objfile \"%s\".",
- ext_lang_name (language), name, section_name, objfile_name (objfile));
- bool is_safe = file_is_auto_load_safe (objfile_name (objfile));
- bool in_hash_table
- = maybe_add_script_text (pspace_info, is_safe, name, language);
- /* If this file is not currently loaded, load it. */
- if (is_safe && !in_hash_table)
- executor (language, objfile, name, script_text);
- }
- /* 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 specified as file names 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 or
- actual script contents. Each entry is nul-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 *entry;
- const struct extension_language_defn *language;
- unsigned int offset = p - start;
- int code = *p;
- switch (code)
- {
- case SECTION_SCRIPT_ID_PYTHON_FILE:
- case SECTION_SCRIPT_ID_PYTHON_TEXT:
- language = get_ext_lang_defn (EXT_LANG_PYTHON);
- break;
- case SECTION_SCRIPT_ID_SCHEME_FILE:
- case SECTION_SCRIPT_ID_SCHEME_TEXT:
- language = get_ext_lang_defn (EXT_LANG_GUILE);
- break;
- default:
- 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. */
- return;
- }
- entry = ++p;
- while (p < end && *p != '\0')
- ++p;
- if (p == end)
- {
- warning (_("Non-nul-terminated entry in %s at offset %u"),
- section_name, offset);
- /* Don't load/execute it. */
- break;
- }
- switch (code)
- {
- case SECTION_SCRIPT_ID_PYTHON_FILE:
- case SECTION_SCRIPT_ID_SCHEME_FILE:
- if (p == entry)
- {
- warning (_("Empty entry in %s at offset %u"),
- section_name, offset);
- continue;
- }
- source_script_file (pspace_info, objfile, language,
- section_name, offset, entry);
- break;
- case SECTION_SCRIPT_ID_PYTHON_TEXT:
- case SECTION_SCRIPT_ID_SCHEME_TEXT:
- execute_script_contents (pspace_info, objfile, language,
- section_name, offset, entry);
- break;
- }
- }
- }
- /* 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
- || (bfd_section_flags (scripts_sect) & SEC_HAS_CONTENTS) == 0)
- return;
- if (!bfd_get_full_section_contents (abfd, scripts_sect, &data))
- warning (_("Couldn't read %s section of %ps"),
- section_name,
- styled_string (file_name_style.style (),
- bfd_get_filename (abfd)));
- else
- {
- gdb::unique_xmalloc_ptr<bfd_byte> data_holder (data);
- char *p = (char *) data;
- source_section_scripts (objfile, section_name, p,
- p + bfd_section_size (scripts_sect));
- }
- }
- /* Load any auto-loaded scripts for OBJFILE. */
- void
- load_auto_scripts_for_objfile (struct objfile *objfile)
- {
- /* Return immediately if auto-loading has been globally disabled.
- This is to handle sequencing of operations during gdb startup.
- Also return immediately if OBJFILE was not created from a file
- on the local filesystem. */
- if (!global_auto_load
- || (objfile->flags & OBJF_NOT_FILENAME) != 0
- || is_target_filename (objfile->original_name))
- return;
- /* Load any extension language scripts for this objfile.
- E.g., foo-gdb.gdb, foo-gdb.py. */
- auto_load_ext_lang_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.
- 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;
- }
- load_auto_scripts_for_objfile (objfile);
- }
- /* Collect scripts to be printed in a vec. */
- struct collect_matching_scripts_data
- {
- collect_matching_scripts_data (std::vector<loaded_script *> *scripts_p_,
- const extension_language_defn *language_)
- : scripts_p (scripts_p_), language (language_)
- {}
- std::vector<loaded_script *> *scripts_p;
- const struct extension_language_defn *language;
- };
- /* Traversal function for htab_traverse.
- Collect the entry if it matches the regexp. */
- static int
- collect_matching_scripts (void **slot, void *info)
- {
- struct loaded_script *script = (struct loaded_script *) *slot;
- struct collect_matching_scripts_data *data
- = (struct collect_matching_scripts_data *) info;
- if (script->language == data->language && re_exec (script->name))
- data->scripts_p->push_back (script);
- return 1;
- }
- /* Print SCRIPT. */
- static void
- print_script (struct loaded_script *script)
- {
- struct ui_out *uiout = current_uiout;
- ui_out_emit_tuple tuple_emitter (uiout, NULL);
- uiout->field_string ("loaded", script->loaded ? "Yes" : "No");
- uiout->field_string ("script", script->name);
- uiout->text ("\n");
- /* If the name isn't the full path, print it too. */
- if (script->full_path != NULL
- && strcmp (script->name, script->full_path) != 0)
- {
- uiout->text ("\tfull name: ");
- uiout->field_string ("full_path", script->full_path);
- uiout->text ("\n");
- }
- }
- /* Helper for info_auto_load_scripts to sort the scripts by name. */
- static bool
- sort_scripts_by_name (loaded_script *a, loaded_script *b)
- {
- return FILENAME_CMP (a->name, b->name) < 0;
- }
- /* Special internal GDB value of auto_load_info_scripts's PATTERN identify
- the "info auto-load XXX" command has been executed through the general
- "info auto-load" invocation. Extra newline will be printed if needed. */
- char auto_load_info_scripts_pattern_nl[] = "";
- /* Subroutine of auto_load_info_scripts to simplify it.
- Print SCRIPTS. */
- static void
- print_scripts (const std::vector<loaded_script *> &scripts)
- {
- for (loaded_script *script : scripts)
- print_script (script);
- }
- /* Implementation for "info auto-load gdb-scripts"
- (and "info auto-load python-scripts"). List scripts in LANGUAGE matching
- PATTERN. FROM_TTY is the usual GDB boolean for user interactivity. */
- void
- auto_load_info_scripts (const char *pattern, int from_tty,
- const struct extension_language_defn *language)
- {
- struct ui_out *uiout = current_uiout;
- struct auto_load_pspace_info *pspace_info;
- dont_repeat ();
- pspace_info = get_auto_load_pspace_data (current_program_space);
- if (pattern && *pattern)
- {
- char *re_err = re_comp (pattern);
- if (re_err)
- error (_("Invalid regexp: %s"), re_err);
- }
- else
- {
- re_comp ("");
- }
- /* We need to know the number of rows before we build the table.
- Plus we want to sort the scripts by name.
- So first traverse the hash table collecting the matching scripts. */
- std::vector<loaded_script *> script_files, script_texts;
- if (pspace_info != NULL && pspace_info->loaded_script_files != NULL)
- {
- collect_matching_scripts_data data (&script_files, language);
- /* Pass a pointer to scripts as VEC_safe_push can realloc space. */
- htab_traverse_noresize (pspace_info->loaded_script_files.get (),
- collect_matching_scripts, &data);
- std::sort (script_files.begin (), script_files.end (),
- sort_scripts_by_name);
- }
- if (pspace_info != NULL && pspace_info->loaded_script_texts != NULL)
- {
- collect_matching_scripts_data data (&script_texts, language);
- /* Pass a pointer to scripts as VEC_safe_push can realloc space. */
- htab_traverse_noresize (pspace_info->loaded_script_texts.get (),
- collect_matching_scripts, &data);
- std::sort (script_texts.begin (), script_texts.end (),
- sort_scripts_by_name);
- }
- int nr_scripts = script_files.size () + script_texts.size ();
- /* Table header shifted right by preceding "gdb-scripts: " would not match
- its columns. */
- if (nr_scripts > 0 && pattern == auto_load_info_scripts_pattern_nl)
- uiout->text ("\n");
- {
- ui_out_emit_table table_emitter (uiout, 2, nr_scripts,
- "AutoLoadedScriptsTable");
- uiout->table_header (7, ui_left, "loaded", "Loaded");
- uiout->table_header (70, ui_left, "script", "Script");
- uiout->table_body ();
- print_scripts (script_files);
- print_scripts (script_texts);
- }
- if (nr_scripts == 0)
- {
- if (pattern && *pattern)
- uiout->message ("No auto-load scripts matching %s.\n", pattern);
- else
- uiout->message ("No auto-load scripts.\n");
- }
- }
- /* Wrapper for "info auto-load gdb-scripts". */
- static void
- info_auto_load_gdb_scripts (const char *pattern, int from_tty)
- {
- auto_load_info_scripts (pattern, from_tty, &extension_language_gdb);
- }
- /* Implement 'info auto-load local-gdbinit'. */
- static void
- info_auto_load_local_gdbinit (const char *args, int from_tty)
- {
- if (auto_load_local_gdbinit_pathname == NULL)
- gdb_printf (_("Local .gdbinit file was not found.\n"));
- else if (auto_load_local_gdbinit_loaded)
- gdb_printf (_("Local .gdbinit file \"%ps\" has been loaded.\n"),
- styled_string (file_name_style.style (),
- auto_load_local_gdbinit_pathname));
- else
- gdb_printf (_("Local .gdbinit file \"%ps\" has not been loaded.\n"),
- styled_string (file_name_style.style (),
- auto_load_local_gdbinit_pathname));
- }
- /* Print an "unsupported script" warning if it has not already been printed.
- The script is in language LANGUAGE at offset OFFSET in section SECTION_NAME
- of OBJFILE. */
- static void
- maybe_print_unsupported_script_warning
- (struct auto_load_pspace_info *pspace_info,
- struct objfile *objfile, const struct extension_language_defn *language,
- const char *section_name, unsigned offset)
- {
- if (!pspace_info->unsupported_script_warning_printed)
- {
- warning (_("\
- Unsupported auto-load script at offset %u in section %s\n\
- of file %ps.\n\
- Use `info auto-load %s-scripts [REGEXP]' to list them."),
- offset, section_name,
- styled_string (file_name_style.style (),
- objfile_name (objfile)),
- ext_lang_name (language));
- pspace_info->unsupported_script_warning_printed = true;
- }
- }
- /* Return non-zero if SCRIPT_NOT_FOUND_WARNING_PRINTED of PSPACE_INFO was unset
- before calling this function. Always set SCRIPT_NOT_FOUND_WARNING_PRINTED
- of PSPACE_INFO. */
- static void
- maybe_print_script_not_found_warning
- (struct auto_load_pspace_info *pspace_info,
- struct objfile *objfile, const struct extension_language_defn *language,
- const char *section_name, unsigned offset)
- {
- if (!pspace_info->script_not_found_warning_printed)
- {
- warning (_("\
- Missing auto-load script at offset %u in section %s\n\
- of file %ps.\n\
- Use `info auto-load %s-scripts [REGEXP]' to list them."),
- offset, section_name,
- styled_string (file_name_style.style (),
- objfile_name (objfile)),
- ext_lang_name (language));
- pspace_info->script_not_found_warning_printed = true;
- }
- }
- /* The only valid "set auto-load" argument is off|0|no|disable. */
- static void
- set_auto_load_cmd (const char *args, int from_tty)
- {
- struct cmd_list_element *list;
- size_t length;
- /* See parse_binary_operation in use by the sub-commands. */
- length = args ? strlen (args) : 0;
- while (length > 0 && (args[length - 1] == ' ' || args[length - 1] == '\t'))
- length--;
- if (length == 0 || (strncmp (args, "off", length) != 0
- && strncmp (args, "0", length) != 0
- && strncmp (args, "no", length) != 0
- && strncmp (args, "disable", length) != 0))
- error (_("Valid is only global 'set auto-load no'; "
- "otherwise check the auto-load sub-commands."));
- for (list = *auto_load_set_cmdlist_get (); list != NULL; list = list->next)
- if (list->var->type () == var_boolean)
- {
- gdb_assert (list->type == set_cmd);
- do_set_command (args, from_tty, list);
- }
- }
- /* Initialize "set auto-load " commands prefix and return it. */
- struct cmd_list_element **
- auto_load_set_cmdlist_get (void)
- {
- static struct cmd_list_element *retval;
- if (retval == NULL)
- add_prefix_cmd ("auto-load", class_maintenance, set_auto_load_cmd, _("\
- Auto-loading specific settings.\n\
- Configure various auto-load-specific variables such as\n\
- automatic loading of Python scripts."),
- &retval, 1/*allow-unknown*/, &setlist);
- return &retval;
- }
- /* Initialize "show auto-load " commands prefix and return it. */
- struct cmd_list_element **
- auto_load_show_cmdlist_get (void)
- {
- static struct cmd_list_element *retval;
- if (retval == NULL)
- add_show_prefix_cmd ("auto-load", class_maintenance, _("\
- Show auto-loading specific settings.\n\
- Show configuration of various auto-load-specific variables such as\n\
- automatic loading of Python scripts."),
- &retval, 0/*allow-unknown*/, &showlist);
- return &retval;
- }
- /* Command "info auto-load" displays whether the various auto-load files have
- been loaded. This is reimplementation of cmd_show_list which inserts
- newlines at proper places. */
- static void
- info_auto_load_cmd (const char *args, int from_tty)
- {
- struct cmd_list_element *list;
- struct ui_out *uiout = current_uiout;
- ui_out_emit_tuple tuple_emitter (uiout, "infolist");
- for (list = *auto_load_info_cmdlist_get (); list != NULL; list = list->next)
- {
- ui_out_emit_tuple option_emitter (uiout, "option");
- gdb_assert (!list->is_prefix ());
- gdb_assert (list->type == not_set_cmd);
- uiout->field_string ("name", list->name);
- uiout->text (": ");
- cmd_func (list, auto_load_info_scripts_pattern_nl, from_tty);
- }
- }
- /* Initialize "info auto-load " commands prefix and return it. */
- struct cmd_list_element **
- auto_load_info_cmdlist_get (void)
- {
- static struct cmd_list_element *retval;
- if (retval == NULL)
- add_prefix_cmd ("auto-load", class_info, info_auto_load_cmd, _("\
- Print current status of auto-loaded files.\n\
- Print whether various files like Python scripts or .gdbinit files have been\n\
- found and/or loaded."),
- &retval, 0/*allow-unknown*/, &infolist);
- return &retval;
- }
- /* See auto-load.h. */
- gdb::observers::token auto_load_new_objfile_observer_token;
- void _initialize_auto_load ();
- void
- _initialize_auto_load ()
- {
- struct cmd_list_element *cmd;
- gdb::unique_xmalloc_ptr<char> scripts_directory_help, gdb_name_help,
- python_name_help, guile_name_help;
- const char *suffix;
- gdb::observers::new_objfile.attach (auto_load_new_objfile,
- auto_load_new_objfile_observer_token,
- "auto-load");
- add_setshow_boolean_cmd ("gdb-scripts", class_support,
- &auto_load_gdb_scripts, _("\
- Enable or disable auto-loading of canned sequences of commands scripts."), _("\
- Show whether auto-loading of canned sequences of commands scripts is enabled."),
- _("\
- If enabled, canned sequences of commands are loaded when the debugger reads\n\
- an executable or shared library.\n\
- This option has security implications for untrusted inferiors."),
- NULL, show_auto_load_gdb_scripts,
- auto_load_set_cmdlist_get (),
- auto_load_show_cmdlist_get ());
- add_cmd ("gdb-scripts", class_info, info_auto_load_gdb_scripts,
- _("Print the list of automatically loaded sequences of commands.\n\
- Usage: info auto-load gdb-scripts [REGEXP]"),
- auto_load_info_cmdlist_get ());
- add_setshow_boolean_cmd ("local-gdbinit", class_support,
- &auto_load_local_gdbinit, _("\
- Enable or disable auto-loading of .gdbinit script in current directory."), _("\
- Show whether auto-loading .gdbinit script in current directory is enabled."),
- _("\
- If enabled, canned sequences of commands are loaded when debugger starts\n\
- from .gdbinit file in current directory. Such files are deprecated,\n\
- use a script associated with inferior executable file instead.\n\
- This option has security implications for untrusted inferiors."),
- NULL, show_auto_load_local_gdbinit,
- auto_load_set_cmdlist_get (),
- auto_load_show_cmdlist_get ());
- add_cmd ("local-gdbinit", class_info, info_auto_load_local_gdbinit,
- _("Print whether current directory .gdbinit file has been loaded.\n\
- Usage: info auto-load local-gdbinit"),
- auto_load_info_cmdlist_get ());
- suffix = ext_lang_auto_load_suffix (get_ext_lang_defn (EXT_LANG_GDB));
- gdb_name_help
- = xstrprintf (_("\
- GDB scripts: OBJFILE%s\n"),
- suffix);
- python_name_help = NULL;
- #ifdef HAVE_PYTHON
- suffix = ext_lang_auto_load_suffix (get_ext_lang_defn (EXT_LANG_PYTHON));
- python_name_help
- = xstrprintf (_("\
- Python scripts: OBJFILE%s\n"),
- suffix);
- #endif
- guile_name_help = NULL;
- #ifdef HAVE_GUILE
- suffix = ext_lang_auto_load_suffix (get_ext_lang_defn (EXT_LANG_GUILE));
- guile_name_help
- = xstrprintf (_("\
- Guile scripts: OBJFILE%s\n"),
- suffix);
- #endif
- scripts_directory_help
- = xstrprintf (_("\
- Automatically loaded scripts are located in one of the directories listed\n\
- by this option.\n\
- \n\
- Script names:\n\
- %s%s%s\
- \n\
- 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."),
- gdb_name_help.get (),
- python_name_help.get () ? python_name_help.get () : "",
- guile_name_help.get () ? guile_name_help.get () : "");
- 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."),
- scripts_directory_help.get (),
- set_auto_load_dir, show_auto_load_dir,
- auto_load_set_cmdlist_get (),
- auto_load_show_cmdlist_get ());
- auto_load_safe_path_vec_update ();
- add_setshow_optional_filename_cmd ("safe-path", class_support,
- &auto_load_safe_path, _("\
- 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. 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 option has security implications for untrusted inferiors."),
- set_auto_load_safe_path,
- show_auto_load_safe_path,
- auto_load_set_cmdlist_get (),
- auto_load_show_cmdlist_get ());
- gdb::observers::gdb_datadir_changed.attach (auto_load_gdb_datadir_changed,
- "auto-load");
- cmd = add_cmd ("add-auto-load-safe-path", class_support,
- add_auto_load_safe_path,
- _("Add entries to the list of directories from which it is safe "
- "to auto-load files.\n\
- See the commands 'set auto-load safe-path' and 'show auto-load safe-path' to\n\
- access the current full list setting."),
- &cmdlist);
- set_cmd_completer (cmd, filename_completer);
- cmd = add_cmd ("add-auto-load-scripts-directory", class_support,
- add_auto_load_dir,
- _("Add entries to the list of directories from which to load "
- "auto-loaded scripts.\n\
- See the commands 'set auto-load scripts-directory' and\n\
- 'show auto-load scripts-directory' to access the current full list setting."),
- &cmdlist);
- set_cmd_completer (cmd, filename_completer);
- add_setshow_boolean_cmd ("auto-load", class_maintenance,
- &debug_auto_load, _("\
- Set auto-load verifications debugging."), _("\
- Show auto-load verifications debugging."), _("\
- When non-zero, debugging output for files of 'set auto-load ...'\n\
- is displayed."),
- NULL, show_debug_auto_load,
- &setdebuglist, &showdebuglist);
- }
|