Blame SOURCES/gdb-rhbz2024875-set_show-for-managing-debuginfod.patch

ab2726
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
ab2726
From: =?UTF-8?q?Alexandra=20H=C3=A1jkov=C3=A1?= <ahajkova@redhat.com>
ab2726
Date: Mon, 10 Jan 2022 13:35:45 +0100
ab2726
Subject: gdb-rhbz2024875-set_show-for-managing-debuginfod.patch
ab2726
ab2726
;;Backport upstream commit from Aaron Merey
ab2726
;;7811fa5995f gdb: add set/show commands for managing debuginfo
ab2726
ab2726
gdb: add set/show commands for managing debuginfod
ab2726
ab2726
Add 'set debuginfod' command.  Accepts 'on', 'off' or 'ask' as an
ab2726
argument.  'on' enables debuginfod for the current session.  'off'
ab2726
disables debuginfod for the current session.  'ask' will prompt
ab2726
the user to either enable or disable debuginfod when the next query
ab2726
is about to be performed:
ab2726
ab2726
    This GDB supports auto-downloading debuginfo from the following URLs:
ab2726
    <URL1> <URL2> ...
ab2726
    Enable debuginfod for this session? (y or [n]) y
ab2726
    Debuginfod has been enabled.
ab2726
    To make this setting permanent, add 'set debuginfod on' to .gdbinit.
ab2726
ab2726
For interactive sessions, 'ask' is the default.  For non-interactive
ab2726
sessions, 'off' is the default.
ab2726
ab2726
Add 'show debuginfod status' command.  Displays whether debuginfod
ab2726
is set to 'on', 'off' or 'ask'.
ab2726
ab2726
Add 'set/show debuginfod urls' commands. Accepts a string of
ab2726
space-separated debuginfod server URLs to be queried.  The default
ab2726
value is copied from the DEBUGINFOD_URLS environment variable.
ab2726
ab2726
Finally add 'set/show debuginfod verbose' commands to control whether
ab2726
debuginfod-related output is displayed.  Verbose output is enabled
ab2726
by default.
ab2726
ab2726
    (gdb) run
ab2726
    Starting program: /bin/sleep 5
ab2726
    Download failed: No route to host.  Continuing without debug info for /lib64/libc.so.6.
ab2726
ab2726
If GDB is not built with debuginfod then these commands will just display
ab2726
ab2726
    Support for debuginfod is not compiled into GDB.
ab2726
ab2726
diff --git a/gdb/debuginfod-support.c b/gdb/debuginfod-support.c
ab2726
--- a/gdb/debuginfod-support.c
ab2726
+++ b/gdb/debuginfod-support.c
ab2726
@@ -18,10 +18,26 @@
ab2726
 
ab2726
 #include "defs.h"
ab2726
 #include <errno.h>
ab2726
-#include "cli/cli-style.h"
ab2726
 #include "gdbsupport/scoped_fd.h"
ab2726
 #include "debuginfod-support.h"
ab2726
 #include "gdbsupport/gdb_optional.h"
ab2726
+#include "cli/cli-cmds.h"
ab2726
+#include "cli/cli-style.h"
ab2726
+
ab2726
+/* Set/show debuginfod commands.  */
ab2726
+static cmd_list_element *set_debuginfod_prefix_list;
ab2726
+static cmd_list_element *show_debuginfod_prefix_list;
ab2726
+
ab2726
+static const char debuginfod_on[] = "on";
ab2726
+static const char debuginfod_off[] = "off";
ab2726
+static const char debuginfod_ask[] = "ask";
ab2726
+
ab2726
+static const char *debuginfod_enable = debuginfod_ask;
ab2726
+static unsigned debuginfod_verbose = 1;
ab2726
+
ab2726
+/* This is never actually used.  URLs are always pulled from the
ab2726
+   environment.  */
ab2726
+static char *debuginfod_urls;
ab2726
 
ab2726
 #ifndef HAVE_LIBDEBUGINFOD
ab2726
 scoped_fd
ab2726
@@ -41,6 +57,67 @@ debuginfod_debuginfo_query (const unsigned char *build_id,
ab2726
 {
ab2726
   return scoped_fd (-ENOSYS);
ab2726
 }
ab2726
+
ab2726
+#define NO_IMPL _("Support for debuginfod is not compiled into GDB.")
ab2726
+
ab2726
+/* Stub set/show commands that indicate debuginfod is not supported.  */
ab2726
+
ab2726
+static void
ab2726
+set_debuginfod_on_command (const char *args, int from_tty)
ab2726
+{
ab2726
+  error (NO_IMPL);
ab2726
+  debuginfod_enable = debuginfod_off;
ab2726
+}
ab2726
+
ab2726
+static void
ab2726
+set_debuginfod_off_command (const char *args, int from_tty)
ab2726
+{
ab2726
+  error (NO_IMPL);
ab2726
+  debuginfod_enable = debuginfod_off;
ab2726
+}
ab2726
+
ab2726
+static void
ab2726
+set_debuginfod_ask_command (const char *args, int from_tty)
ab2726
+{
ab2726
+  error (NO_IMPL);
ab2726
+  debuginfod_enable = debuginfod_off;
ab2726
+}
ab2726
+
ab2726
+static void
ab2726
+show_debuginfod_status_command (const char *args, int from_tty)
ab2726
+{
ab2726
+  error (NO_IMPL);
ab2726
+}
ab2726
+
ab2726
+static void
ab2726
+set_debuginfod_urls_command (const char *ignore, int from_tty,
ab2726
+                             struct cmd_list_element *c)
ab2726
+{
ab2726
+  error (NO_IMPL);
ab2726
+}
ab2726
+
ab2726
+static void
ab2726
+show_debuginfod_urls_command (struct ui_file *file, int from_tty,
ab2726
+			      struct cmd_list_element *cmd, const char *value)
ab2726
+{
ab2726
+  error (NO_IMPL);
ab2726
+}
ab2726
+
ab2726
+static void
ab2726
+set_debuginfod_verbose_command (const char *args, int from_tty,
ab2726
+				struct cmd_list_element *c)
ab2726
+{
ab2726
+  error (NO_IMPL);
ab2726
+  debuginfod_verbose = 0;
ab2726
+}
ab2726
+
ab2726
+static void
ab2726
+show_debuginfod_verbose_command (struct ui_file *file, int from_tty,
ab2726
+				 struct cmd_list_element *cmd,
ab2726
+				 const char *value)
ab2726
+{
ab2726
+  error (NO_IMPL);
ab2726
+}
ab2726
 #else
ab2726
 #include <elfutils/debuginfod.h>
ab2726
 
ab2726
@@ -68,6 +145,82 @@ struct debuginfod_client_deleter
ab2726
 using debuginfod_client_up
ab2726
   = std::unique_ptr<debuginfod_client, debuginfod_client_deleter>;
ab2726
 
ab2726
+/* Enable debuginfod.  */
ab2726
+
ab2726
+static void
ab2726
+set_debuginfod_on_command (const char *args, int from_tty)
ab2726
+{
ab2726
+  debuginfod_enable = debuginfod_on;
ab2726
+}
ab2726
+
ab2726
+/* Disable debuginfod.  */
ab2726
+
ab2726
+static void
ab2726
+set_debuginfod_off_command (const char *args, int from_tty)
ab2726
+{
ab2726
+  debuginfod_enable = debuginfod_off;
ab2726
+}
ab2726
+
ab2726
+/* Before next query, ask user whether to enable debuginfod.  */
ab2726
+
ab2726
+static void
ab2726
+set_debuginfod_ask_command (const char *args, int from_tty)
ab2726
+{
ab2726
+  debuginfod_enable = debuginfod_ask;
ab2726
+}
ab2726
+
ab2726
+/* Show whether debuginfod is enabled.  */
ab2726
+
ab2726
+static void
ab2726
+show_debuginfod_status_command (const char *args, int from_tty)
ab2726
+{
ab2726
+  printf_unfiltered (_("Debuginfod functionality is currently set to " \
ab2726
+		     "\"%s\".\n"), debuginfod_enable);
ab2726
+}
ab2726
+
ab2726
+/* Set the URLs that debuginfod will query.  */
ab2726
+
ab2726
+static void
ab2726
+set_debuginfod_urls_command (const char *ignore, int from_tty,
ab2726
+                             struct cmd_list_element *c)
ab2726
+{
ab2726
+  gdb_assert (debuginfod_urls != nullptr);
ab2726
+  if (setenv ("DEBUGINFOD_URLS", debuginfod_urls, 1) != 0)
ab2726
+    warning (_("Unable to set debuginfod URLs: %s"), safe_strerror (errno));
ab2726
+}
ab2726
+
ab2726
+/* Show the URLs that debuginfod will query.  */
ab2726
+
ab2726
+static void
ab2726
+show_debuginfod_urls_command (struct ui_file *file, int from_tty,
ab2726
+			      struct cmd_list_element *cmd, const char *value)
ab2726
+{
ab2726
+  if (value == nullptr || value[0] == '\0')
ab2726
+    fprintf_unfiltered (file, _("Debuginfod URLs have not been set.\n"));
ab2726
+  else
ab2726
+    fprintf_filtered (file, _("Debuginfod URLs are currently set to:\n%s\n"),
ab2726
+		      value);
ab2726
+}
ab2726
+
ab2726
+/* No-op setter used for compatibility when gdb is built without debuginfod.  */
ab2726
+
ab2726
+static void
ab2726
+set_debuginfod_verbose_command (const char *args, int from_tty,
ab2726
+				struct cmd_list_element *c)
ab2726
+{
ab2726
+  return;
ab2726
+}
ab2726
+
ab2726
+/* Show verbosity.  */
ab2726
+
ab2726
+static void
ab2726
+show_debuginfod_verbose_command (struct ui_file *file, int from_tty,
ab2726
+				 struct cmd_list_element *cmd, const char *value)
ab2726
+{
ab2726
+  fprintf_filtered (file, _("Debuginfod verbose output is set to %s.\n"),
ab2726
+		    value);
ab2726
+}
ab2726
+
ab2726
 static int
ab2726
 progressfn (debuginfod_client *c, long cur, long total)
ab2726
 {
ab2726
@@ -120,6 +273,42 @@ get_debuginfod_client ()
ab2726
   return global_client.get ();
ab2726
 }
ab2726
 
ab2726
+/* Check if debuginfod is enabled.  If configured to do so, ask the user
ab2726
+   whether to enable debuginfod.  */
ab2726
+
ab2726
+static bool
ab2726
+debuginfod_enabled ()
ab2726
+{
ab2726
+  const char *urls = getenv (DEBUGINFOD_URLS_ENV_VAR);
ab2726
+
ab2726
+  if (urls == nullptr || urls[0] == '\0'
ab2726
+      || debuginfod_enable == debuginfod_off)
ab2726
+    return false;
ab2726
+
ab2726
+  if (debuginfod_enable == debuginfod_ask)
ab2726
+    {
ab2726
+      int resp = nquery (_("\nThis GDB supports auto-downloading debuginfo " \
ab2726
+			   "from the following URLs:\n%s\nEnable debuginfod " \
ab2726
+			   "for this session? "),
ab2726
+			 urls);
ab2726
+      if (!resp)
ab2726
+	{
ab2726
+	  printf_filtered (_("Debuginfod has been disabled.\nTo make this " \
ab2726
+			     "setting permanent, add \'set debuginfod off\' " \
ab2726
+			     "to .gdbinit.\n"));
ab2726
+	  debuginfod_enable = debuginfod_off;
ab2726
+	  return false;
ab2726
+	}
ab2726
+
ab2726
+      printf_filtered (_("Debuginfod has been enabled.\nTo make this " \
ab2726
+			 "setting permanent, add \'set debuginfod on\' " \
ab2726
+			 "to .gdbinit.\n"));
ab2726
+      debuginfod_enable = debuginfod_on;
ab2726
+    }
ab2726
+
ab2726
+  return true;
ab2726
+}
ab2726
+
ab2726
 /* See debuginfod-support.h  */
ab2726
 
ab2726
 scoped_fd
ab2726
@@ -128,8 +317,7 @@ debuginfod_source_query (const unsigned char *build_id,
ab2726
 			 const char *srcpath,
ab2726
 			 gdb::unique_xmalloc_ptr<char> *destname)
ab2726
 {
ab2726
-  const char *urls_env_var = getenv (DEBUGINFOD_URLS_ENV_VAR);
ab2726
-  if (urls_env_var == NULL || urls_env_var[0] == '\0')
ab2726
+  if (!debuginfod_enabled ())
ab2726
     return scoped_fd (-ENOSYS);
ab2726
 
ab2726
   debuginfod_client *c = get_debuginfod_client ();
ab2726
@@ -147,8 +335,7 @@ debuginfod_source_query (const unsigned char *build_id,
ab2726
 					nullptr));
ab2726
   debuginfod_set_user_data (c, nullptr);
ab2726
 
ab2726
-  /* TODO: Add 'set debug debuginfod' command to control when error messages are shown.  */
ab2726
-  if (fd.get () < 0 && fd.get () != -ENOENT)
ab2726
+  if (debuginfod_verbose > 0 && fd.get () < 0 && fd.get () != -ENOENT)
ab2726
     printf_filtered (_("Download failed: %s.  Continuing without source file %ps.\n"),
ab2726
 		     safe_strerror (-fd.get ()),
ab2726
 		     styled_string (file_name_style.style (),  srcpath));
ab2726
@@ -167,8 +354,7 @@ debuginfod_debuginfo_query (const unsigned char *build_id,
ab2726
 			    const char *filename,
ab2726
 			    gdb::unique_xmalloc_ptr<char> *destname)
ab2726
 {
ab2726
-  const char *urls_env_var = getenv (DEBUGINFOD_URLS_ENV_VAR);
ab2726
-  if (urls_env_var == NULL || urls_env_var[0] == '\0')
ab2726
+  if (!debuginfod_enabled ())
ab2726
     return scoped_fd (-ENOSYS);
ab2726
 
ab2726
   debuginfod_client *c = get_debuginfod_client ();
ab2726
@@ -184,7 +370,7 @@ debuginfod_debuginfo_query (const unsigned char *build_id,
ab2726
 					   &dname));
ab2726
   debuginfod_set_user_data (c, nullptr);
ab2726
 
ab2726
-  if (fd.get () < 0 && fd.get () != -ENOENT)
ab2726
+  if (debuginfod_verbose > 0 && fd.get () < 0 && fd.get () != -ENOENT)
ab2726
     printf_filtered (_("Download failed: %s.  Continuing without debug info for %ps.\n"),
ab2726
 		     safe_strerror (-fd.get ()),
ab2726
 		     styled_string (file_name_style.style (),  filename));
ab2726
@@ -195,3 +381,63 @@ debuginfod_debuginfo_query (const unsigned char *build_id,
ab2726
   return fd;
ab2726
 }
ab2726
 #endif
ab2726
+
ab2726
+/* Register debuginfod commands.  */
ab2726
+
ab2726
+void _initialize_debuginfod ();
ab2726
+void
ab2726
+_initialize_debuginfod ()
ab2726
+{
ab2726
+  /* set/show debuginfod */
ab2726
+  add_basic_prefix_cmd ("debuginfod", class_run,
ab2726
+                        _("Set debuginfod options"),
ab2726
+                        &set_debuginfod_prefix_list, 0, &setlist);
ab2726
+
ab2726
+  add_show_prefix_cmd ("debuginfod", class_run,
ab2726
+                       _("Show debuginfod options"),
ab2726
+                       &show_debuginfod_prefix_list, 0, &showlist);
ab2726
+
ab2726
+  /* set debuginfod on */
ab2726
+  add_cmd ("on", class_run, set_debuginfod_on_command,
ab2726
+	   _("Enable debuginfod."), &set_debuginfod_prefix_list);
ab2726
+
ab2726
+  /* set debuginfod off */
ab2726
+  add_cmd ("off", class_run, set_debuginfod_off_command,
ab2726
+	   _("Disable debuginfod."), &set_debuginfod_prefix_list);
ab2726
+
ab2726
+  /* set debuginfod ask */
ab2726
+  add_cmd ("ask", class_run, set_debuginfod_ask_command, _("\
ab2726
+Ask the user whether to enable debuginfod before performing the next query."),
ab2726
+	   &set_debuginfod_prefix_list);
ab2726
+
ab2726
+  /* show debuginfod status */
ab2726
+  add_cmd ("status", class_run, show_debuginfod_status_command,
ab2726
+	   _("Show whether debuginfod is set to \"on\", \"off\" or \"ask\"."),
ab2726
+	   &show_debuginfod_prefix_list);
ab2726
+
ab2726
+  /* set/show debuginfod urls */
ab2726
+  add_setshow_string_noescape_cmd ("urls", class_run, &debuginfod_urls, _("\
ab2726
+Set the list of debuginfod server URLs."), _("\
ab2726
+Show the list of debuginfod server URLs."), _("\
ab2726
+Manage the space-separated list of debuginfod server URLs that GDB will query \
ab2726
+when missing debuginfo, executables or source files.\nThe default value is \
ab2726
+copied from the DEBUGINFOD_URLS environment variable."),
ab2726
+				   set_debuginfod_urls_command,
ab2726
+				   show_debuginfod_urls_command,
ab2726
+				   &set_debuginfod_prefix_list,
ab2726
+				   &show_debuginfod_prefix_list);
ab2726
+  if (getenv ("DEBUGINFOD_URLS") != nullptr)
ab2726
+    debuginfod_urls = xstrdup (getenv ("DEBUGINFOD_URLS"));
ab2726
+
ab2726
+  /* set/show debuginfod verbose */
ab2726
+  add_setshow_zuinteger_cmd ("verbose", class_support,
ab2726
+			     &debuginfod_verbose, _("\
ab2726
+Set verbosity of debuginfod output."), _("\
ab2726
+Show debuginfod debugging."), _("\
ab2726
+When set to a non-zero value, display verbose output for each debuginfod \
ab2726
+query.\nTo disable, set to zero.  Verbose output is displayed by default."),
ab2726
+			     set_debuginfod_verbose_command,
ab2726
+			     show_debuginfod_verbose_command,
ab2726
+			     &set_debuginfod_prefix_list,
ab2726
+			     &show_debuginfod_prefix_list);
ab2726
+}
ab2726
diff --git a/gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp b/gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp
ab2726
--- a/gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp
ab2726
+++ b/gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp
ab2726
@@ -217,7 +217,8 @@ proc local_url { } {
ab2726
     setenv DEBUGINFOD_URLS http://127.0.0.1:$port
ab2726
 
ab2726
     # gdb should now find the symbol and source files
ab2726
-    clean_restart $binfile
ab2726
+    clean_restart
ab2726
+    gdb_test "file $binfile" "" "file [file tail $binfile]" "Enable debuginfod?.*" "y"
ab2726
     gdb_test_no_output "set substitute-path $outputdir /dev/null" \
ab2726
 	"set substitute-path"
ab2726
     gdb_test "br main" "Breakpoint 1 at.*file.*"
ab2726
@@ -226,8 +227,26 @@ proc local_url { } {
ab2726
     # gdb should now find the debugaltlink file
ab2726
     clean_restart
ab2726
     gdb_test "file ${binfile}_alt.o" \
ab2726
-	".*Reading symbols from ${binfile}_alt.o\.\.\.*" \
ab2726
-	"file [file tail ${binfile}_alt.o]"
ab2726
+	".*Downloading.*separate debug info.*" \
ab2726
+	"file [file tail ${binfile}_alt.o]" \
ab2726
+	".*Enable debuginfod?.*" "y"
ab2726
+
ab2726
+    # Configure debuginfod with commands
ab2726
+    unsetenv DEBUGINFOD_URLS
ab2726
+    clean_restart
ab2726
+    gdb_test "file $binfile" ".*No debugging symbols.*" \
ab2726
+	"file [file tail $binfile] cmd"
ab2726
+    gdb_test_no_output "set debuginfod off"
ab2726
+    gdb_test_no_output "set debuginfod urls http://127.0.0.1:$port"
ab2726
+
ab2726
+    # gdb shouldn't find the debuginfo since debuginfod has been disabled
ab2726
+    gdb_test "file $binfile" ".*No debugging symbols.*" \
ab2726
+	"file [file tail $binfile] cmd off"
ab2726
+
ab2726
+    # Enable debuginfod and fetch the debuginfo
ab2726
+    gdb_test_no_output "set debuginfod on"
ab2726
+    gdb_test "file $binfile" ".*Reading symbols from.*debuginfo.*" \
ab2726
+	"file [file tail $binfile] cmd on"
ab2726
 }
ab2726
 
ab2726
 set envlist \