From patchwork Tue Sep 24 16:29:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Terekhov, Mikhail via Gdb-patches" X-Patchwork-Id: 34644 Received: (qmail 53058 invoked by alias); 24 Sep 2019 16:30: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 52642 invoked by uid 89); 24 Sep 2019 16:30:04 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-22.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=Home, scripting, roland X-HELO: mail-qk1-f202.google.com Received: from mail-qk1-f202.google.com (HELO mail-qk1-f202.google.com) (209.85.222.202) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 24 Sep 2019 16:29:59 +0000 Received: by mail-qk1-f202.google.com with SMTP id b143so2619105qkg.9 for ; Tue, 24 Sep 2019 09:29:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=87lyyWukPNQuNezIftt9szluzFVKSnkcKgbsQVlSuWE=; b=dJJFfFLkCPJx5Tm0YNLpWJQn4xRn/pl86icMl2FmrsxoJhvjdVjGOQwM2THw+S7oN9 dRIJuEACGof4A0mLEiDftsbGNdhkAZUo9UVshLEmOWACpGjCJHIKZH39AJ01xAEckeFk 7zcTr69sQ4B6mG2uNG8CuqazjDbhf+IswijwzTgVF4mCq65A5xBZ1OKpL2DKjmt1UMVj 48l8x6ijLoQ6Mh50wBo78N2M5CIm1U/2kdnbuV6O8B4qYWoZCENxl1fYOQ64v8XgBpX/ 1Ts6XE2W/8hS2dLwq79IJxUSDDaxlubw3W/X7U5LFfu/7rudy5jtWtD0Wa6Hh4q0yjF6 nBKg== Date: Tue, 24 Sep 2019 11:29:52 -0500 In-Reply-To: Message-Id: <20190924162952.145769-1-cbiesinger@google.com> Mime-Version: 1.0 References: Subject: [PATCH 3/3 v3] Load system gdbinit files from a directory X-Patchwork-Original-From: "Christian Biesinger via gdb-patches" From: "Terekhov, Mikhail via Gdb-patches" Reply-To: Christian Biesinger To: gdb-patches@sourceware.org Cc: Christian Biesinger X-IsSubscribed: yes [Looks like I never did send this updated patch :( Please take another look!] 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 * gdb.texinfo (many sections): Document new --with-system-gdbinit-dir option. --- gdb/NEWS | 6 ++++ gdb/config.in | 7 ++++ gdb/configure | 51 +++++++++++++++++++++++++++++ gdb/configure.ac | 3 ++ gdb/doc/gdb.texinfo | 67 ++++++++++++++++++++++++++++++++----- gdb/extension.c | 3 ++ gdb/main.c | 80 +++++++++++++++++++++++++++++++++++++-------- gdb/top.c | 4 +++ 8 files changed, 199 insertions(+), 22 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index 779fd91d3a..1d0f56a119 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -34,6 +34,12 @@ * GDB can now be compiled with Python 3 on Windows. +* 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 26ca02f6a3..c0745c90a3 100644 --- a/gdb/config.in +++ b/gdb/config.in @@ -684,6 +684,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 22a5f6051d..8436f06c9f 100755 --- a/gdb/configure +++ b/gdb/configure @@ -693,6 +693,7 @@ WIN32LIBS SER_HARDWIRE WERROR_CFLAGS WARN_CFLAGS +SYSTEM_GDBINIT_DIR SYSTEM_GDBINIT TARGET_SYSTEM_ROOT CONFIG_LDFLAGS @@ -884,6 +885,7 @@ with_libipt_prefix with_included_regex with_sysroot with_system_gdbinit +with_system_gdbinit_dir enable_werror enable_build_warnings enable_gdb_build_warnings @@ -1618,6 +1620,9 @@ Optional Packages: --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 @@ -15238,6 +15243,52 @@ _ACEOF +# 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 9da8818fb5..f3f5bd0635 100644 --- a/gdb/configure.ac +++ b/gdb/configure.ac @@ -1843,6 +1843,9 @@ GDB_AC_DEFINE_RELOCATABLE(TARGET_SYSTEM_ROOT, sysroot, ${ac_define_dir}) 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/gdb.texinfo b/gdb/doc/gdb.texinfo index f2713c0396..eb385ae1ee 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -1083,6 +1083,16 @@ Its location is specified with the @code{--with-system-gdbinit} 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 (@code{.py}/@code{.scm}) or be named with a @code{.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 @@ Sets up the command interpreter as specified by the command line @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 @code{.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 @@ -37034,6 +37047,14 @@ directory under the configured prefix, and @value{GDBN} is moved to 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 @@ -37059,24 +37080,28 @@ was first introduced in GCC 4.9. @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 @@ -37102,6 +37127,14 @@ initialization. If the data-directory is changed after @value{GDBN} has 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 @code{.gdb} +extension. + @menu * System-wide Configuration Scripts:: Installed System-wide Configuration Scripts @end menu @@ -45591,6 +45624,10 @@ Richard M. Stallman and Roland H. Pesch, July 1991. @value{SYSTEM_GDBINIT} @end ifset +@ifset SYSTEM_GDBINIT_DIR +@value{SYSTEM_GDBINIT_DIR}/* +@end ifset + ~/.gdbinit ./.gdbinit @@ -45632,6 +45669,20 @@ See more in 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 8637bc53f2..1fb4b48003 100644 --- a/gdb/extension.c +++ b/gdb/extension.c @@ -154,6 +154,9 @@ get_ext_lang_of_file (const char *file) 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 7fab8ff8da..ed902371cb 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" @@ -195,7 +196,8 @@ relocate_gdb_directory (const char *initial, bool relocatable) 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); @@ -219,9 +221,8 @@ relocate_gdbinit_path_maybe_in_datadir (const std::string& file) } 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; } @@ -232,11 +233,11 @@ relocate_gdbinit_path_maybe_in_datadir (const std::string& file) 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; @@ -248,10 +249,49 @@ get_init_files (std::string *system_gdbinit, 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); + DIR *dir = nullptr; + if (!relocated_gdbinit_dir.empty ()) + dir = opendir (relocated_gdbinit_dir.c_str ()); + if (dir != nullptr) + { + std::vector files; + struct dirent *ent; + for (;;) + { + ent = readdir (dir); + if (ent == nullptr) + break; + if (ent->d_name[0] == '.') + 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 + ent->d_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 (filename); + } + closedir (dir); + std::sort (files.begin (), files.end ()); + sysgdbinit.insert (sysgdbinit.end (), files.begin (), files.end ()); + } } const char *homedir = getenv ("HOME"); @@ -916,7 +956,7 @@ captured_main_1 (struct captured_main_args *context) /* Lookup gdbinit files. Note that the gdbinit file name may be overriden 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); @@ -996,7 +1036,10 @@ captured_main_1 (struct captured_main_args *context) 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 @@ -1214,7 +1257,7 @@ gdb_main (struct captured_main_args *args) 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; @@ -1295,9 +1338,18 @@ Other options:\n\n\ 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 49e6daae94..7a45f1b4aa 100644 --- a/gdb/top.c +++ b/gdb/top.c @@ -1515,6 +1515,10 @@ This GDB was configured as follows:\n\ 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\