From patchwork Thu Oct 24 19:05:16 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Simon Marchi (Code Review)" X-Patchwork-Id: 35286 Received: (qmail 35930 invoked by alias); 24 Oct 2019 19:05:28 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 35666 invoked by uid 89); 24 Oct 2019 19:05:27 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-20.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3 autolearn=ham version=3.3.1 spammy= X-HELO: mx1.osci.io Received: from polly.osci.io (HELO mx1.osci.io) (8.43.85.229) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 24 Oct 2019 19:05:24 +0000 Received: by mx1.osci.io (Postfix, from userid 994) id DEC66204A7; Thu, 24 Oct 2019 15:05:22 -0400 (EDT) Received: from gnutoolchain-gerrit.osci.io (gnutoolchain-gerrit.osci.io [8.43.85.239]) by mx1.osci.io (Postfix) with ESMTP id 9187520176; Thu, 24 Oct 2019 15:05:17 -0400 (EDT) Received: from localhost (localhost [127.0.0.1]) by gnutoolchain-gerrit.osci.io (Postfix) with ESMTP id 66509204C9; Thu, 24 Oct 2019 15:05:17 -0400 (EDT) X-Gerrit-PatchSet: 5 Date: Thu, 24 Oct 2019 15:05:16 -0400 From: "Christian Biesinger (Code Review)" To: Christian Biesinger , Tom de Vries , gdb-patches@sourceware.org Cc: Tom Tromey , Simon Marchi Auto-Submitted: auto-generated X-Gerrit-MessageType: newpatchset Subject: [review v5] Load system gdbinit files from a directory X-Gerrit-Change-Id: If233859ecc21bc6421d589b37cd658a3c7d030f2 X-Gerrit-Change-Number: 26 X-Gerrit-ChangeURL: X-Gerrit-Commit: eca839c42e9fd7c5dd7fff3e5612fd85c8fc865b In-Reply-To: References: Reply-To: cbiesinger@google.com, simon.marchi@polymtl.ca, tdevries@suse.de, tromey@sourceware.org, cbiesinger@google.com, gdb-patches@sourceware.org MIME-Version: 1.0 Content-Disposition: inline User-Agent: Gerrit/3.0.3 Message-Id: <20191024190517.66509204C9@gnutoolchain-gerrit.osci.io> Change URL: https://gnutoolchain-gerrit.osci.io/r/c/binutils-gdb/+/26 ...................................................................... Load system gdbinit files from a directory Adds a configure option --with-system-gdbinit-dir to specify a directory in which to look for gdbinit files. All files in this directory are loaded on startup (subject to -n/-nx as usual) as long as the extension matches a known and enabled scripting language (.gdb/.py/.scm). This also changes get_ext_lang_of_file to support ".gdb" files, similar to get_ext_lang_defn's handling of EXT_LANG_GDB. gdb/ChangeLog: 2019-08-20 Christian Biesinger * NEWS: Mention new --with-system-gdbinit-dir option. * config.in: Regenerate. * configure: Regenerate. * configure.ac: Add new option --with-system-gdbinit-dir. * extension.c (get_ext_lang_of_file): Return extension_language_gdb for a ".gdb" suffix. * main.c (get_init_files): Change system_gdbinit argument to a vector and return the files in SYSTEM_GDBINIT_DIR in addition to SYSTEM_GDBINIT. (captured_main_1): Update. (print_gdb_help): Update. * top.c (print_gdb_configuration): Also print the value of SYSTEM_GDBINIT_DIR. gdb/doc/ChangeLog: 2019-08-25 Christian Biesinger * Makefile.in: Also set SYSTEM_GDBINIT_DIR for the info manual generation. * gdb.texinfo (many sections): Document new --with-system-gdbinit-dir option. Change-Id: If233859ecc21bc6421d589b37cd658a3c7d030f2 --- M gdb/NEWS M gdb/config.in M gdb/configure M gdb/configure.ac M gdb/doc/Makefile.in M gdb/doc/gdb.texinfo M gdb/extension.c M gdb/main.c M gdb/top.c 9 files changed, 212 insertions(+), 22 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index 25e67e4..7613598 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -46,6 +46,12 @@ The 'outer_function::' prefix is only needed if 'inner_function' is not visible in the current scope. +* In addition to the system-wide gdbinit file, if configured with + --with-system-gdbinit-dir, GDB will now also load files in that directory + as system gdbinit files, unless the -nx or -n flag is provided. Files + with extensions .gdb, .py and .scm are supported as long as GDB was + compiled with support for that language. + * Python API ** The gdb.Value type has a new method 'format_string' which returns a diff --git a/gdb/config.in b/gdb/config.in index da365a7..480eb58 100644 --- a/gdb/config.in +++ b/gdb/config.in @@ -687,6 +687,13 @@ /* automatically load a system-wide gdbinit file */ #undef SYSTEM_GDBINIT +/* automatically load system-wide gdbinit files from this directory */ +#undef SYSTEM_GDBINIT_DIR + +/* Define if the system-gdbinit-dir directory should be relocated when GDB is + moved. */ +#undef SYSTEM_GDBINIT_DIR_RELOCATABLE + /* Define if the system-gdbinit directory should be relocated when GDB is moved. */ #undef SYSTEM_GDBINIT_RELOCATABLE diff --git a/gdb/configure b/gdb/configure index ae8e451..8bb1ec7 100755 --- a/gdb/configure +++ b/gdb/configure @@ -697,6 +697,7 @@ SER_HARDWIRE WERROR_CFLAGS WARN_CFLAGS +SYSTEM_GDBINIT_DIR SYSTEM_GDBINIT TARGET_SYSTEM_ROOT CONFIG_LDFLAGS @@ -888,6 +889,7 @@ with_included_regex with_sysroot with_system_gdbinit +with_system_gdbinit_dir enable_werror enable_build_warnings enable_gdb_build_warnings @@ -1624,6 +1626,9 @@ --with-sysroot[=DIR] search for usr/lib et al within DIR --with-system-gdbinit=PATH automatically load a system-wide gdbinit file + --with-system-gdbinit-dir=PATH + automatically load system-wide gdbinit files from + this directory --with-lzma support lzma compression (auto/yes/no) --with-liblzma-prefix[=DIR] search for liblzma in DIR/include and DIR/lib --without-liblzma-prefix don't search for liblzma in includedir and libdir @@ -15247,6 +15252,52 @@ +# Check whether --with-system-gdbinit-dir was given. +if test "${with_system_gdbinit_dir+set}" = set; then : + withval=$with_system_gdbinit_dir; + SYSTEM_GDBINIT_DIR=$withval +else + SYSTEM_GDBINIT_DIR= +fi + + + test "x$prefix" = xNONE && prefix="$ac_default_prefix" + test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + ac_define_dir=`eval echo $SYSTEM_GDBINIT_DIR` + ac_define_dir=`eval echo $ac_define_dir` + +cat >>confdefs.h <<_ACEOF +#define SYSTEM_GDBINIT_DIR "$ac_define_dir" +_ACEOF + + + + + if test "x$exec_prefix" = xNONE || test "x$exec_prefix" = 'x${prefix}'; then + if test "x$prefix" = xNONE; then + test_prefix=/usr/local + else + test_prefix=$prefix + fi + else + test_prefix=$exec_prefix + fi + value=0 + case ${ac_define_dir} in + "${test_prefix}"|"${test_prefix}/"*|\ + '${exec_prefix}'|'${exec_prefix}/'*) + value=1 + ;; + esac + +cat >>confdefs.h <<_ACEOF +#define SYSTEM_GDBINIT_DIR_RELOCATABLE $value +_ACEOF + + + + + # Check whether --enable-werror was given. if test "${enable_werror+set}" = set; then : enableval=$enable_werror; case "${enableval}" in diff --git a/gdb/configure.ac b/gdb/configure.ac index 6297502..47efc54 100644 --- a/gdb/configure.ac +++ b/gdb/configure.ac @@ -1843,6 +1843,9 @@ GDB_AC_WITH_DIR(SYSTEM_GDBINIT, system-gdbinit, [automatically load a system-wide gdbinit file], []) +GDB_AC_WITH_DIR(SYSTEM_GDBINIT_DIR, system-gdbinit-dir, + [automatically load system-wide gdbinit files from this directory], + []) AM_GDB_WARNINGS AM_GDB_UBSAN diff --git a/gdb/doc/Makefile.in b/gdb/doc/Makefile.in index 2bb8a30..de4d495 100644 --- a/gdb/doc/Makefile.in +++ b/gdb/doc/Makefile.in @@ -41,6 +41,7 @@ INSTALL_DATA = @INSTALL_DATA@ SYSTEM_GDBINIT = @SYSTEM_GDBINIT@ +SYSTEM_GDBINIT_DIR = @SYSTEM_GDBINIT_DIR@ mkinstalldirs = $(SHELL) $(srcdir)/../../mkinstalldirs @@ -425,6 +426,9 @@ if [ -n "$(SYSTEM_GDBINIT)" ]; then \ echo "@set SYSTEM_GDBINIT $(SYSTEM_GDBINIT)" >> ./GDBvn.new; \ fi + if [ -n "$(SYSTEM_GDBINIT_DIR)" ]; then \ + echo "@set SYSTEM_GDBINIT_DIR $(SYSTEM_GDBINIT_DIR)" >> ./GDBvn.new; \ + fi mv GDBvn.new GDBvn.texi version.subst: $(gdbdir)/version.in $(gdbdir)/../bfd/version.h diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 1208e4f..db3d15b 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -1083,6 +1083,16 @@ configure option (@pxref{System-wide configuration}). It is loaded first when @value{GDBN} starts, before command line options have been processed. +@item @file{system.gdbinit.d} +This is the system-wide init directory. +Its location is specified with the @code{--with-system-gdbinit-dir} +configure option (@pxref{System-wide configuration}). +Files in this directory are loaded in alphabetical order immediately after +system.gdbinit (if enabled) when @value{GDBN} starts, before command line +options have been processed. Files need to have a recognized scripting +language extension (@file{.py}/@file{.scm}) or be named with a @file{.gdb} +extension to be interpreted as regular @value{GDBN} commands. @value{GDBN} +will not recurse into any subdirectories of this directory. @item @file{~/.gdbinit} This is the init file in your home directory. It is loaded next, after @file{system.gdbinit}, and before @@ -1315,8 +1325,11 @@ @cindex init file Reads the system-wide @dfn{init file} (if @option{--with-system-gdbinit} was used when building @value{GDBN}; @pxref{System-wide configuration, - ,System-wide configuration and settings}) and executes all the commands in -that file. + ,System-wide configuration and settings}) and the files in the system-wide +gdbinit directory (if @option{--with-system-gdbinit-dir} was used) and executes +all the commands in those files. The files need to be named with a @file{.gdb} +extension to be interpreted as @value{GDBN} commands, or they can be written +in a supported scripting language with an appropriate file extension. @anchor{Home Directory Init File} @item @@ -26283,6 +26296,13 @@ @end table +@ifset SYSTEM_GDBINIT_DIR +This setting is not used for files in the system-wide gdbinit directory. +Files in that directory must have an extension matching their language, +or have a @file{.gdb} extension to be interpreted as regular @value{GDBN} +commands. @xref{Startup}. +@end ifset + @node Sequences @section Canned Sequences of Commands @@ -37054,6 +37074,14 @@ another location after being built, the location of the system-wide init file will be adjusted accordingly. +@item --with-system-gdbinit-dir=@var{directory} +Configure @value{GDBN} to automatically load init files from a +system-wide directory. @var{directory} should be an absolute directory +name. If @var{directory} is in a directory under the configured +prefix, and @value{GDBN} is moved to another location after being +built, the location of the system-wide init directory will be +adjusted accordingly. + @item --enable-build-warnings When building the @value{GDBN} sources, ask the compiler to warn about any code which looks even vaguely suspicious. It passes many @@ -37079,24 +37107,28 @@ @section System-wide configuration and settings @cindex system-wide init file -@value{GDBN} can be configured to have a system-wide init file; -this file will be read and executed at startup (@pxref{Startup, , What -@value{GDBN} does during startup}). +@value{GDBN} can be configured to have a system-wide init file and a +system-wide init file directory; this file and files in that directory +(if they have a recognized file extension) will be read and executed at +startup (@pxref{Startup, , What @value{GDBN} does during startup}). -Here is the corresponding configure option: +Here are the corresponding configure options: @table @code @item --with-system-gdbinit=@var{file} Specify that the default location of the system-wide init file is @var{file}. +@item --with-system-gdbinit-dir=@var{directory} +Specify that the default location of the system-wide init file directory +is @var{directory}. @end table If @value{GDBN} has been configured with the option @option{--prefix=$prefix}, -it may be subject to relocation. Two possible cases: +they may be subject to relocation. Two possible cases: @itemize @bullet @item -If the default location of this init file contains @file{$prefix}, +If the default location of this init file/directory contains @file{$prefix}, it will be subject to relocation. Suppose that the configure options are @option{--prefix=$prefix --with-system-gdbinit=$prefix/etc/gdbinit}; if @value{GDBN} is moved from @file{$prefix} to @file{$install}, the system @@ -37122,6 +37154,14 @@ started with the @code{set data-directory} command, the file will not be reread. +This applies similarly to the system-wide directory specified in +@option{--with-system-gdbinit-dir}. + +Any supported scripting language can be used for these init files, as long +as the file extension matches the scripting language. To be interpreted +as regular @value{GDBN} commands, the files needs to have a @file{.gdb} +extension. + @menu * System-wide Configuration Scripts:: Installed System-wide Configuration Scripts @end menu @@ -45611,6 +45651,10 @@ @value{SYSTEM_GDBINIT} @end ifset +@ifset SYSTEM_GDBINIT_DIR +@value{SYSTEM_GDBINIT_DIR}/* +@end ifset + ~/.gdbinit ./.gdbinit @@ -45652,6 +45696,20 @@ the @value{GDBN} manual in node @code{System-wide configuration} -- shell command @code{info -f gdb -n 'System-wide configuration'}. @end ifset +@ifset SYSTEM_GDBINIT_DIR +@item @value{SYSTEM_GDBINIT_DIR} +@end ifset +@ifclear SYSTEM_GDBINIT_DIR +@item (not enabled with @code{--with-system-gdbinit-dir} during compilation) +@end ifclear +System-wide initialization directory. All files in this directory are +executed on startup unless user specified @value{GDBN} option @code{-nx} or +@code{-n}, as long as they have a recognized file extension. +See more in +@ifset man +the @value{GDBN} manual in node @code{System-wide configuration} +-- shell command @code{info -f gdb -n 'System-wide configuration'}. +@end ifset @ifclear man @ref{System-wide configuration}. @end ifclear diff --git a/gdb/extension.c b/gdb/extension.c index 8637bc5..1fb4b48 100644 --- a/gdb/extension.c +++ b/gdb/extension.c @@ -154,6 +154,9 @@ int i; const struct extension_language_defn *extlang; + if (has_extension (file, extension_language_gdb.suffix)) + return &extension_language_gdb; + ALL_EXTENSION_LANGUAGES (i, extlang) { if (has_extension (file, extlang->suffix)) diff --git a/gdb/main.c b/gdb/main.c index a77d6ec..a051254 100644 --- a/gdb/main.c +++ b/gdb/main.c @@ -45,6 +45,7 @@ #include "event-top.h" #include "infrun.h" #include "gdbsupport/signals-state-save-restore.h" +#include #include #include "gdbsupport/pathstuff.h" #include "cli/cli-style.h" @@ -198,7 +199,8 @@ otherwise. */ static std::string -relocate_gdbinit_path_maybe_in_datadir (const std::string& file) +relocate_gdbinit_path_maybe_in_datadir (const std::string &file, + bool relocatable) { size_t datadir_len = strlen (GDB_DATADIR); @@ -221,9 +223,8 @@ } else { - relocated_path = relocate_path (gdb_program_name, - file.c_str (), - SYSTEM_GDBINIT_RELOCATABLE); + relocated_path = relocate_path (gdb_program_name, file.c_str (), + relocatable); } return relocated_path; } @@ -234,11 +235,11 @@ to be loaded, then SYSTEM_GDBINIT (resp. HOME_GDBINIT and LOCAL_GDBINIT) is set to the empty string. */ static void -get_init_files (std::string *system_gdbinit, +get_init_files (std::vector *system_gdbinit, std::string *home_gdbinit, std::string *local_gdbinit) { - static std::string sysgdbinit; + static std::vector sysgdbinit; static std::string homeinit; static std::string localinit; static int initialized = 0; @@ -250,10 +251,51 @@ if (SYSTEM_GDBINIT[0]) { std::string relocated_sysgdbinit - = relocate_gdbinit_path_maybe_in_datadir (SYSTEM_GDBINIT); + = relocate_gdbinit_path_maybe_in_datadir + (SYSTEM_GDBINIT, SYSTEM_GDBINIT_RELOCATABLE); if (!relocated_sysgdbinit.empty () && stat (relocated_sysgdbinit.c_str (), &s) == 0) - sysgdbinit = relocated_sysgdbinit; + sysgdbinit.push_back (relocated_sysgdbinit); + } + if (SYSTEM_GDBINIT_DIR[0]) + { + std::string relocated_gdbinit_dir + = relocate_gdbinit_path_maybe_in_datadir + (SYSTEM_GDBINIT_DIR, SYSTEM_GDBINIT_DIR_RELOCATABLE); + if (!relocated_gdbinit_dir.empty ()) { + gdb_dir_up dir (opendir (relocated_gdbinit_dir.c_str ())); + if (dir != nullptr) + { + std::vector files; + for (;;) + { + struct dirent *ent = readdir (dir.get ()); + if (ent == nullptr) + break; + std::string name (ent->d_name); + if (name == "." || name == "..") + continue; + /* ent->d_type is not available on all systems (e.g. mingw, + Solaris), so we have to call stat(). */ + std::string filename + = relocated_gdbinit_dir + SLASH_STRING + name; + if (stat (filename.c_str (), &s) != 0 + || !S_ISREG (s.st_mode)) + continue; + const struct extension_language_defn *extlang + = get_ext_lang_of_file (filename.c_str ()); + /* We effectively don't support "set script-extension + off/soft", because we are loading system init files here, + so it does not really make sense to depend on a + setting. */ + if (extlang != nullptr && ext_lang_present_p (extlang)) + files.push_back (std::move (filename)); + } + std::sort (files.begin (), files.end ()); + sysgdbinit.insert (sysgdbinit.end (), + files.begin (), files.end ()); + } + } } const char *homedir = getenv ("HOME"); @@ -913,7 +955,7 @@ /* Lookup gdbinit files. Note that the gdbinit file name may be overridden during file initialization, so get_init_files should be called after gdb_init. */ - std::string system_gdbinit; + std::vector system_gdbinit; std::string home_gdbinit; std::string local_gdbinit; get_init_files (&system_gdbinit, &home_gdbinit, &local_gdbinit); @@ -993,7 +1035,10 @@ processed; it sets global parameters, which are independent of what file you are debugging or what directory you are in. */ if (!system_gdbinit.empty () && !inhibit_gdbinit) - ret = catch_command_errors (source_script, system_gdbinit.c_str (), 0); + { + for (const std::string &file : system_gdbinit) + ret = catch_command_errors (source_script, file.c_str (), 0); + } /* Read and execute $HOME/.gdbinit file, if it exists. This is done *before* all the command line arguments are processed; it sets @@ -1211,7 +1256,7 @@ static void print_gdb_help (struct ui_file *stream) { - std::string system_gdbinit; + std::vector system_gdbinit; std::string home_gdbinit; std::string local_gdbinit; @@ -1292,9 +1337,18 @@ At startup, GDB reads the following init files and executes their commands:\n\ "), stream); if (!system_gdbinit.empty ()) - fprintf_unfiltered (stream, _("\ - * system-wide init file: %s\n\ -"), system_gdbinit.c_str ()); + { + std::string output; + for (size_t idx = 0; idx < system_gdbinit.size (); ++idx) + { + output += system_gdbinit[idx]; + if (idx < system_gdbinit.size () - 1) + output += ", "; + } + fprintf_unfiltered (stream, _("\ + * system-wide init files: %s\n\ +"), output.c_str ()); + } if (!home_gdbinit.empty ()) fprintf_unfiltered (stream, _("\ * user-specific init file: %s\n\ diff --git a/gdb/top.c b/gdb/top.c index 15d4fab..a443159 100644 --- a/gdb/top.c +++ b/gdb/top.c @@ -1513,6 +1513,10 @@ fprintf_filtered (stream, _("\ --with-system-gdbinit=%s%s\n\ "), SYSTEM_GDBINIT, SYSTEM_GDBINIT_RELOCATABLE ? " (relocatable)" : ""); + if (SYSTEM_GDBINIT_DIR[0]) + fprintf_filtered (stream, _("\ + --with-system-gdbinit-dir=%s%s\n\ +"), SYSTEM_GDBINIT_DIR, SYSTEM_GDBINIT_DIR_RELOCATABLE ? " (relocatable)" : ""); /* We assume "relocatable" will be printed at least once, thus we always print this text. It's a reasonably safe assumption for now. */ fprintf_filtered (stream, _("\n\