Home | History | Annotate | Line # | Download | only in gdb
      1      1.1  christos /* debuginfod utilities for GDB.
      2  1.1.1.3  christos    Copyright (C) 2020-2024 Free Software Foundation, Inc.
      3      1.1  christos 
      4      1.1  christos    This file is part of GDB.
      5      1.1  christos 
      6      1.1  christos    This program is free software; you can redistribute it and/or modify
      7      1.1  christos    it under the terms of the GNU General Public License as published by
      8      1.1  christos    the Free Software Foundation; either version 3 of the License, or
      9      1.1  christos    (at your option) any later version.
     10      1.1  christos 
     11      1.1  christos    This program is distributed in the hope that it will be useful,
     12      1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14      1.1  christos    GNU General Public License for more details.
     15      1.1  christos 
     16      1.1  christos    You should have received a copy of the GNU General Public License
     17      1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     18      1.1  christos 
     19  1.1.1.2  christos #include "diagnostics.h"
     20      1.1  christos #include <errno.h>
     21      1.1  christos #include "gdbsupport/scoped_fd.h"
     22      1.1  christos #include "debuginfod-support.h"
     23  1.1.1.3  christos #include <optional>
     24  1.1.1.2  christos #include "cli/cli-cmds.h"
     25  1.1.1.2  christos #include "cli/cli-style.h"
     26  1.1.1.2  christos #include "cli-out.h"
     27  1.1.1.2  christos #include "target.h"
     28  1.1.1.2  christos 
     29  1.1.1.2  christos /* Set/show debuginfod commands.  */
     30  1.1.1.2  christos static cmd_list_element *set_debuginfod_prefix_list;
     31  1.1.1.2  christos static cmd_list_element *show_debuginfod_prefix_list;
     32  1.1.1.2  christos 
     33  1.1.1.3  christos /* maint set/show debuginfod commands.  */
     34  1.1.1.3  christos static cmd_list_element *maint_set_debuginfod_cmdlist;
     35  1.1.1.3  christos static cmd_list_element *maint_show_debuginfod_cmdlist;
     36  1.1.1.3  christos 
     37  1.1.1.2  christos static const char debuginfod_on[] = "on";
     38  1.1.1.2  christos static const char debuginfod_off[] = "off";
     39  1.1.1.2  christos static const char debuginfod_ask[] = "ask";
     40  1.1.1.2  christos 
     41  1.1.1.2  christos static const char *debuginfod_enabled_enum[] =
     42  1.1.1.2  christos {
     43  1.1.1.2  christos   debuginfod_on,
     44  1.1.1.2  christos   debuginfod_off,
     45  1.1.1.2  christos   debuginfod_ask,
     46  1.1.1.2  christos   nullptr
     47  1.1.1.2  christos };
     48  1.1.1.2  christos 
     49  1.1.1.2  christos static const char *debuginfod_enabled =
     50  1.1.1.2  christos #if defined(HAVE_LIBDEBUGINFOD)
     51  1.1.1.2  christos   debuginfod_ask;
     52  1.1.1.2  christos #else
     53  1.1.1.2  christos   debuginfod_off;
     54  1.1.1.2  christos #endif
     55  1.1.1.2  christos 
     56  1.1.1.3  christos /* Controls whether ELF/DWARF section downloading is enabled.  */
     57  1.1.1.3  christos static bool debuginfod_download_sections =
     58  1.1.1.3  christos #if defined(HAVE_LIBDEBUGINFOD_FIND_SECTION)
     59  1.1.1.3  christos   true;
     60  1.1.1.3  christos #else
     61  1.1.1.3  christos   false;
     62  1.1.1.3  christos #endif
     63  1.1.1.3  christos 
     64  1.1.1.2  christos static unsigned int debuginfod_verbose = 1;
     65      1.1  christos 
     66      1.1  christos #ifndef HAVE_LIBDEBUGINFOD
     67      1.1  christos scoped_fd
     68      1.1  christos debuginfod_source_query (const unsigned char *build_id,
     69      1.1  christos 			 int build_id_len,
     70      1.1  christos 			 const char *srcpath,
     71      1.1  christos 			 gdb::unique_xmalloc_ptr<char> *destname)
     72      1.1  christos {
     73      1.1  christos   return scoped_fd (-ENOSYS);
     74      1.1  christos }
     75      1.1  christos 
     76      1.1  christos scoped_fd
     77      1.1  christos debuginfod_debuginfo_query (const unsigned char *build_id,
     78      1.1  christos 			    int build_id_len,
     79      1.1  christos 			    const char *filename,
     80      1.1  christos 			    gdb::unique_xmalloc_ptr<char> *destname)
     81      1.1  christos {
     82      1.1  christos   return scoped_fd (-ENOSYS);
     83      1.1  christos }
     84  1.1.1.2  christos 
     85  1.1.1.2  christos scoped_fd
     86  1.1.1.2  christos debuginfod_exec_query (const unsigned char *build_id,
     87  1.1.1.2  christos 		       int build_id_len,
     88  1.1.1.2  christos 		       const char *filename,
     89  1.1.1.2  christos 		       gdb::unique_xmalloc_ptr<char> *destname)
     90  1.1.1.2  christos {
     91  1.1.1.2  christos   return scoped_fd (-ENOSYS);
     92  1.1.1.2  christos }
     93  1.1.1.2  christos 
     94  1.1.1.3  christos scoped_fd
     95  1.1.1.3  christos debuginfod_section_query (const unsigned char *build_id,
     96  1.1.1.3  christos 			  int build_id_len,
     97  1.1.1.3  christos 			  const char *filename,
     98  1.1.1.3  christos 			  const char *section_name,
     99  1.1.1.3  christos 			  gdb::unique_xmalloc_ptr<char> *destname)
    100  1.1.1.3  christos {
    101  1.1.1.3  christos   return scoped_fd (-ENOSYS);
    102  1.1.1.3  christos }
    103  1.1.1.2  christos #define NO_IMPL _("Support for debuginfod is not compiled into GDB.")
    104  1.1.1.2  christos 
    105      1.1  christos #else
    106      1.1  christos #include <elfutils/debuginfod.h>
    107      1.1  christos 
    108      1.1  christos struct user_data
    109      1.1  christos {
    110      1.1  christos   user_data (const char *desc, const char *fname)
    111  1.1.1.2  christos     : desc (desc), fname (fname)
    112      1.1  christos   { }
    113      1.1  christos 
    114      1.1  christos   const char * const desc;
    115      1.1  christos   const char * const fname;
    116  1.1.1.2  christos   ui_out::progress_update progress;
    117  1.1.1.2  christos };
    118  1.1.1.2  christos 
    119  1.1.1.2  christos /* Convert SIZE into a unit suitable for use with progress updates.
    120  1.1.1.2  christos    SIZE should in given in bytes and will be converted into KB, MB, GB
    121  1.1.1.2  christos    or remain unchanged. UNIT will be set to "B", "KB", "MB" or "GB"
    122  1.1.1.2  christos    accordingly.  */
    123  1.1.1.2  christos 
    124  1.1.1.2  christos static const char *
    125  1.1.1.2  christos get_size_and_unit (double &size)
    126  1.1.1.2  christos {
    127  1.1.1.2  christos   if (size < 1024)
    128  1.1.1.2  christos     /* If size is less than 1 KB then set unit to B.  */
    129  1.1.1.2  christos     return "B";
    130  1.1.1.2  christos 
    131  1.1.1.2  christos   size /= 1024;
    132  1.1.1.2  christos   if (size < 1024)
    133  1.1.1.2  christos     /* If size is less than 1 MB then set unit to KB.  */
    134  1.1.1.2  christos     return "K";
    135  1.1.1.2  christos 
    136  1.1.1.2  christos   size /= 1024;
    137  1.1.1.2  christos   if (size < 1024)
    138  1.1.1.2  christos     /* If size is less than 1 GB then set unit to MB.  */
    139  1.1.1.2  christos     return "M";
    140  1.1.1.2  christos 
    141  1.1.1.2  christos   size /= 1024;
    142  1.1.1.2  christos   return "G";
    143  1.1.1.2  christos }
    144  1.1.1.2  christos 
    145      1.1  christos static int
    146      1.1  christos progressfn (debuginfod_client *c, long cur, long total)
    147      1.1  christos {
    148      1.1  christos   user_data *data = static_cast<user_data *> (debuginfod_get_user_data (c));
    149  1.1.1.2  christos   gdb_assert (data != nullptr);
    150  1.1.1.2  christos 
    151  1.1.1.2  christos   string_file styled_fname (current_uiout->can_emit_style_escape ());
    152  1.1.1.2  christos   fprintf_styled (&styled_fname, file_name_style.style (), "%s",
    153  1.1.1.2  christos 		  data->fname);
    154      1.1  christos 
    155      1.1  christos   if (check_quit_flag ())
    156      1.1  christos     {
    157  1.1.1.3  christos       ui_file *outstream = get_unbuffered (gdb_stdout);
    158  1.1.1.3  christos       gdb_printf (outstream, _("Cancelling download of %s %s...\n"),
    159  1.1.1.2  christos 		  data->desc, styled_fname.c_str ());
    160      1.1  christos       return 1;
    161      1.1  christos     }
    162      1.1  christos 
    163  1.1.1.2  christos   if (debuginfod_verbose == 0)
    164  1.1.1.2  christos     return 0;
    165  1.1.1.2  christos 
    166  1.1.1.2  christos   /* Print progress update.  Include the transfer size if available.  */
    167  1.1.1.2  christos   if (total > 0)
    168      1.1  christos     {
    169  1.1.1.2  christos       /* Transfer size is known.  */
    170  1.1.1.2  christos       double howmuch = (double) cur / (double) total;
    171  1.1.1.2  christos 
    172  1.1.1.2  christos       if (howmuch >= 0.0 && howmuch <= 1.0)
    173  1.1.1.2  christos 	{
    174  1.1.1.2  christos 	  double d_total = (double) total;
    175  1.1.1.2  christos 	  const char *unit =  get_size_and_unit (d_total);
    176  1.1.1.2  christos 	  std::string msg = string_printf ("Downloading %0.2f %s %s %s",
    177  1.1.1.2  christos 					   d_total, unit, data->desc,
    178  1.1.1.2  christos 					   styled_fname.c_str ());
    179  1.1.1.2  christos 	  data->progress.update_progress (msg, unit, howmuch, d_total);
    180  1.1.1.2  christos 	  return 0;
    181  1.1.1.2  christos 	}
    182      1.1  christos     }
    183      1.1  christos 
    184  1.1.1.2  christos   std::string msg = string_printf ("Downloading %s %s",
    185  1.1.1.2  christos 				   data->desc, styled_fname.c_str ());
    186  1.1.1.2  christos   data->progress.update_progress (msg);
    187      1.1  christos   return 0;
    188      1.1  christos }
    189      1.1  christos 
    190  1.1.1.3  christos /* Return a pointer to the single global debuginfod_client, initialising it
    191  1.1.1.3  christos    first if needed.  */
    192  1.1.1.3  christos 
    193      1.1  christos static debuginfod_client *
    194  1.1.1.2  christos get_debuginfod_client ()
    195      1.1  christos {
    196  1.1.1.3  christos   static debuginfod_client *global_client = nullptr;
    197  1.1.1.2  christos 
    198  1.1.1.2  christos   if (global_client == nullptr)
    199  1.1.1.2  christos     {
    200  1.1.1.3  christos       global_client = debuginfod_begin ();
    201  1.1.1.2  christos 
    202  1.1.1.2  christos       if (global_client != nullptr)
    203  1.1.1.3  christos 	{
    204  1.1.1.3  christos 	  /* It is important that we cleanup the debuginfod_client object
    205  1.1.1.3  christos 	     before calling exit.  Some of the libraries used by debuginfod
    206  1.1.1.3  christos 	     make use of at_exit handlers to perform cleanup.
    207  1.1.1.3  christos 
    208  1.1.1.3  christos 	     If we wrapped the debuginfod_client in a unique_ptr and relied
    209  1.1.1.3  christos 	     on its destructor to cleanup then this would be run as part of
    210  1.1.1.3  christos 	     the global C++ object destructors, which is after the at_exit
    211  1.1.1.3  christos 	     handlers, which is too late.
    212  1.1.1.3  christos 
    213  1.1.1.3  christos 	     So instead, we make use of GDB's final cleanup mechanism.  */
    214  1.1.1.3  christos 	  add_final_cleanup ([] ()
    215  1.1.1.3  christos 	    {
    216  1.1.1.3  christos 	      debuginfod_end (global_client);
    217  1.1.1.3  christos 	    });
    218  1.1.1.3  christos 	  debuginfod_set_progressfn (global_client, progressfn);
    219  1.1.1.3  christos 	}
    220  1.1.1.2  christos     }
    221  1.1.1.2  christos 
    222  1.1.1.3  christos   return global_client;
    223  1.1.1.2  christos }
    224  1.1.1.2  christos 
    225  1.1.1.2  christos /* Check if debuginfod is enabled.  If configured to do so, ask the user
    226  1.1.1.2  christos    whether to enable debuginfod.  */
    227  1.1.1.2  christos 
    228  1.1.1.2  christos static bool
    229  1.1.1.2  christos debuginfod_is_enabled ()
    230  1.1.1.2  christos {
    231  1.1.1.2  christos   const char *urls = skip_spaces (getenv (DEBUGINFOD_URLS_ENV_VAR));
    232  1.1.1.2  christos 
    233  1.1.1.2  christos   if (debuginfod_enabled == debuginfod_off
    234  1.1.1.2  christos       || urls == nullptr
    235  1.1.1.2  christos       || *urls == '\0')
    236  1.1.1.2  christos     return false;
    237  1.1.1.2  christos 
    238  1.1.1.2  christos   if (debuginfod_enabled == debuginfod_ask)
    239  1.1.1.2  christos     {
    240  1.1.1.2  christos       gdb_printf (_("\nThis GDB supports auto-downloading debuginfo " \
    241  1.1.1.2  christos 		    "from the following URLs:\n"));
    242  1.1.1.2  christos 
    243  1.1.1.3  christos       std::string_view url_view (urls);
    244  1.1.1.2  christos       while (true)
    245  1.1.1.2  christos 	{
    246  1.1.1.2  christos 	  size_t off = url_view.find_first_not_of (' ');
    247  1.1.1.3  christos 	  if (off == std::string_view::npos)
    248  1.1.1.2  christos 	    break;
    249  1.1.1.2  christos 	  url_view = url_view.substr (off);
    250  1.1.1.2  christos 	  /* g++ 11.2.1 on s390x, g++ 11.3.1 on ppc64le and g++ 11 on
    251  1.1.1.2  christos 	     hppa seem convinced url_view might be of SIZE_MAX length.
    252  1.1.1.2  christos 	     And so complains because the length of an array can only
    253  1.1.1.2  christos 	     be PTRDIFF_MAX.  */
    254  1.1.1.2  christos 	  DIAGNOSTIC_PUSH
    255  1.1.1.2  christos 	  DIAGNOSTIC_IGNORE_STRINGOP_OVERREAD
    256  1.1.1.2  christos 	  off = url_view.find_first_of (' ');
    257  1.1.1.2  christos 	  DIAGNOSTIC_POP
    258  1.1.1.2  christos 	  gdb_printf
    259  1.1.1.2  christos 	    (_("  <%ps>\n"),
    260  1.1.1.2  christos 	     styled_string (file_name_style.style (),
    261  1.1.1.3  christos 			    std::string (url_view.substr (0, off)).c_str ()));
    262  1.1.1.3  christos 	  if (off == std::string_view::npos)
    263  1.1.1.2  christos 	    break;
    264  1.1.1.2  christos 	  url_view = url_view.substr (off);
    265  1.1.1.2  christos 	}
    266  1.1.1.2  christos 
    267  1.1.1.2  christos       int resp = nquery (_("Enable debuginfod for this session? "));
    268  1.1.1.2  christos       if (!resp)
    269  1.1.1.2  christos 	{
    270  1.1.1.2  christos 	  gdb_printf (_("Debuginfod has been disabled.\nTo make this " \
    271  1.1.1.2  christos 			"setting permanent, add \'set debuginfod " \
    272  1.1.1.2  christos 			"enabled off\' to .gdbinit.\n"));
    273  1.1.1.2  christos 	  debuginfod_enabled = debuginfod_off;
    274  1.1.1.2  christos 	  return false;
    275  1.1.1.2  christos 	}
    276  1.1.1.2  christos 
    277  1.1.1.2  christos       gdb_printf (_("Debuginfod has been enabled.\nTo make this " \
    278  1.1.1.2  christos 		    "setting permanent, add \'set debuginfod enabled " \
    279  1.1.1.2  christos 		    "on\' to .gdbinit.\n"));
    280  1.1.1.2  christos       debuginfod_enabled = debuginfod_on;
    281  1.1.1.2  christos     }
    282      1.1  christos 
    283  1.1.1.2  christos   return true;
    284  1.1.1.2  christos }
    285  1.1.1.2  christos 
    286  1.1.1.2  christos /* Print the result of the most recent attempted download.  */
    287  1.1.1.2  christos 
    288  1.1.1.2  christos static void
    289  1.1.1.3  christos print_outcome (int fd, const char *desc, const char *fname)
    290  1.1.1.2  christos {
    291  1.1.1.2  christos   if (fd < 0 && fd != -ENOENT)
    292  1.1.1.3  christos     {
    293  1.1.1.3  christos       ui_file *outstream = get_unbuffered (gdb_stdout);
    294  1.1.1.3  christos       gdb_printf (outstream,
    295  1.1.1.3  christos 		  _("Download failed: %s.  Continuing without %s %ps.\n"),
    296  1.1.1.3  christos 		  safe_strerror (-fd),
    297  1.1.1.3  christos 		  desc,
    298  1.1.1.3  christos 		  styled_string (file_name_style.style (), fname));
    299  1.1.1.3  christos     }
    300      1.1  christos }
    301      1.1  christos 
    302      1.1  christos /* See debuginfod-support.h  */
    303      1.1  christos 
    304      1.1  christos scoped_fd
    305      1.1  christos debuginfod_source_query (const unsigned char *build_id,
    306      1.1  christos 			 int build_id_len,
    307      1.1  christos 			 const char *srcpath,
    308      1.1  christos 			 gdb::unique_xmalloc_ptr<char> *destname)
    309      1.1  christos {
    310  1.1.1.2  christos   if (!debuginfod_is_enabled ())
    311      1.1  christos     return scoped_fd (-ENOSYS);
    312      1.1  christos 
    313  1.1.1.2  christos   debuginfod_client *c = get_debuginfod_client ();
    314      1.1  christos 
    315      1.1  christos   if (c == nullptr)
    316      1.1  christos     return scoped_fd (-ENOMEM);
    317      1.1  christos 
    318  1.1.1.2  christos   char *dname = nullptr;
    319  1.1.1.3  christos   scoped_fd fd;
    320  1.1.1.3  christos   std::optional<target_terminal::scoped_restore_terminal_state> term_state;
    321      1.1  christos 
    322  1.1.1.3  christos   {
    323  1.1.1.3  christos     user_data data ("source file", srcpath);
    324  1.1.1.2  christos 
    325  1.1.1.3  christos     debuginfod_set_user_data (c, &data);
    326  1.1.1.3  christos     if (target_supports_terminal_ours ())
    327  1.1.1.3  christos       {
    328  1.1.1.3  christos 	term_state.emplace ();
    329  1.1.1.3  christos 	target_terminal::ours ();
    330  1.1.1.3  christos       }
    331  1.1.1.3  christos 
    332  1.1.1.3  christos     fd = scoped_fd (debuginfod_find_source (c,
    333  1.1.1.3  christos 					    build_id,
    334  1.1.1.3  christos 					    build_id_len,
    335  1.1.1.3  christos 					    srcpath,
    336  1.1.1.3  christos 					    &dname));
    337  1.1.1.3  christos     debuginfod_set_user_data (c, nullptr);
    338  1.1.1.3  christos   }
    339  1.1.1.3  christos 
    340  1.1.1.3  christos   print_outcome (fd.get (), "source file", srcpath);
    341      1.1  christos 
    342  1.1.1.2  christos   if (fd.get () >= 0)
    343  1.1.1.2  christos     destname->reset (dname);
    344      1.1  christos 
    345      1.1  christos   return fd;
    346      1.1  christos }
    347      1.1  christos 
    348      1.1  christos /* See debuginfod-support.h  */
    349      1.1  christos 
    350      1.1  christos scoped_fd
    351      1.1  christos debuginfod_debuginfo_query (const unsigned char *build_id,
    352      1.1  christos 			    int build_id_len,
    353      1.1  christos 			    const char *filename,
    354      1.1  christos 			    gdb::unique_xmalloc_ptr<char> *destname)
    355      1.1  christos {
    356  1.1.1.2  christos   if (!debuginfod_is_enabled ())
    357      1.1  christos     return scoped_fd (-ENOSYS);
    358      1.1  christos 
    359  1.1.1.2  christos   debuginfod_client *c = get_debuginfod_client ();
    360      1.1  christos 
    361      1.1  christos   if (c == nullptr)
    362      1.1  christos     return scoped_fd (-ENOMEM);
    363      1.1  christos 
    364      1.1  christos   char *dname = nullptr;
    365  1.1.1.3  christos   scoped_fd fd;
    366  1.1.1.3  christos   std::optional<target_terminal::scoped_restore_terminal_state> term_state;
    367      1.1  christos 
    368  1.1.1.3  christos   {
    369  1.1.1.3  christos     user_data data ("separate debug info for", filename);
    370  1.1.1.2  christos 
    371  1.1.1.3  christos     debuginfod_set_user_data (c, &data);
    372  1.1.1.3  christos     if (target_supports_terminal_ours ())
    373  1.1.1.3  christos       {
    374  1.1.1.3  christos 	term_state.emplace ();
    375  1.1.1.3  christos 	target_terminal::ours ();
    376  1.1.1.3  christos       }
    377  1.1.1.3  christos 
    378  1.1.1.3  christos     fd = scoped_fd (debuginfod_find_debuginfo (c, build_id, build_id_len,
    379  1.1.1.3  christos 					       &dname));
    380  1.1.1.3  christos     debuginfod_set_user_data (c, nullptr);
    381  1.1.1.3  christos   }
    382  1.1.1.3  christos 
    383  1.1.1.3  christos   print_outcome (fd.get (), "separate debug info for", filename);
    384      1.1  christos 
    385  1.1.1.2  christos   if (fd.get () >= 0)
    386  1.1.1.2  christos     destname->reset (dname);
    387      1.1  christos 
    388      1.1  christos   return fd;
    389      1.1  christos }
    390  1.1.1.2  christos 
    391  1.1.1.2  christos /* See debuginfod-support.h  */
    392  1.1.1.2  christos 
    393  1.1.1.2  christos scoped_fd
    394  1.1.1.2  christos debuginfod_exec_query (const unsigned char *build_id,
    395  1.1.1.2  christos 		       int build_id_len,
    396  1.1.1.2  christos 		       const char *filename,
    397  1.1.1.2  christos 		       gdb::unique_xmalloc_ptr<char> *destname)
    398  1.1.1.2  christos {
    399  1.1.1.2  christos   if (!debuginfod_is_enabled ())
    400  1.1.1.2  christos     return scoped_fd (-ENOSYS);
    401  1.1.1.2  christos 
    402  1.1.1.2  christos   debuginfod_client *c = get_debuginfod_client ();
    403  1.1.1.2  christos 
    404  1.1.1.2  christos   if (c == nullptr)
    405  1.1.1.2  christos     return scoped_fd (-ENOMEM);
    406  1.1.1.2  christos 
    407  1.1.1.2  christos   char *dname = nullptr;
    408  1.1.1.3  christos   scoped_fd fd;
    409  1.1.1.3  christos   std::optional<target_terminal::scoped_restore_terminal_state> term_state;
    410  1.1.1.2  christos 
    411  1.1.1.3  christos   {
    412  1.1.1.3  christos     user_data data ("executable for", filename);
    413  1.1.1.2  christos 
    414  1.1.1.3  christos     debuginfod_set_user_data (c, &data);
    415  1.1.1.3  christos     if (target_supports_terminal_ours ())
    416  1.1.1.3  christos       {
    417  1.1.1.3  christos 	term_state.emplace ();
    418  1.1.1.3  christos 	target_terminal::ours ();
    419  1.1.1.3  christos       }
    420  1.1.1.3  christos 
    421  1.1.1.3  christos     fd = scoped_fd (debuginfod_find_executable (c, build_id, build_id_len,
    422  1.1.1.3  christos 						&dname));
    423  1.1.1.3  christos     debuginfod_set_user_data (c, nullptr);
    424  1.1.1.3  christos   }
    425  1.1.1.3  christos 
    426  1.1.1.3  christos   print_outcome (fd.get (), "executable for", filename);
    427  1.1.1.2  christos 
    428  1.1.1.2  christos   if (fd.get () >= 0)
    429  1.1.1.2  christos     destname->reset (dname);
    430  1.1.1.2  christos 
    431  1.1.1.2  christos   return fd;
    432  1.1.1.2  christos }
    433  1.1.1.3  christos 
    434  1.1.1.3  christos /* See debuginfod-support.h  */
    435  1.1.1.3  christos 
    436  1.1.1.3  christos scoped_fd
    437  1.1.1.3  christos debuginfod_section_query (const unsigned char *build_id,
    438  1.1.1.3  christos 			  int build_id_len,
    439  1.1.1.3  christos 			  const char *filename,
    440  1.1.1.3  christos 			  const char *section_name,
    441  1.1.1.3  christos 			  gdb::unique_xmalloc_ptr<char> *destname)
    442  1.1.1.3  christos {
    443  1.1.1.3  christos #if !defined (HAVE_LIBDEBUGINFOD_FIND_SECTION)
    444  1.1.1.3  christos   return scoped_fd (-ENOSYS);
    445  1.1.1.3  christos #else
    446  1.1.1.3  christos 
    447  1.1.1.3  christos   if (!debuginfod_download_sections || !debuginfod_is_enabled ())
    448  1.1.1.3  christos     return scoped_fd (-ENOSYS);
    449  1.1.1.3  christos 
    450  1.1.1.3  christos   debuginfod_client *c = get_debuginfod_client ();
    451  1.1.1.3  christos 
    452  1.1.1.3  christos   if (c == nullptr)
    453  1.1.1.3  christos     return scoped_fd (-ENOMEM);
    454  1.1.1.3  christos 
    455  1.1.1.3  christos   char *dname = nullptr;
    456  1.1.1.3  christos   std::string desc = std::string ("section ") + section_name + " for";
    457  1.1.1.3  christos   scoped_fd fd;
    458  1.1.1.3  christos   std::optional<target_terminal::scoped_restore_terminal_state> term_state;
    459  1.1.1.3  christos 
    460  1.1.1.3  christos   {
    461  1.1.1.3  christos     user_data data (desc.c_str (), filename);
    462  1.1.1.3  christos     debuginfod_set_user_data (c, &data);
    463  1.1.1.3  christos     if (target_supports_terminal_ours ())
    464  1.1.1.3  christos       {
    465  1.1.1.3  christos 	term_state.emplace ();
    466  1.1.1.3  christos 	target_terminal::ours ();
    467  1.1.1.3  christos       }
    468  1.1.1.3  christos 
    469  1.1.1.3  christos     fd = scoped_fd (debuginfod_find_section (c, build_id, build_id_len,
    470  1.1.1.3  christos 					     section_name, &dname));
    471  1.1.1.3  christos     debuginfod_set_user_data (c, nullptr);
    472  1.1.1.3  christos   }
    473  1.1.1.3  christos 
    474  1.1.1.3  christos   print_outcome (fd.get (), desc.c_str (), filename);
    475  1.1.1.3  christos   gdb_assert (destname != nullptr);
    476  1.1.1.3  christos 
    477  1.1.1.3  christos   if (fd.get () >= 0)
    478  1.1.1.3  christos     destname->reset (dname);
    479  1.1.1.3  christos 
    480  1.1.1.3  christos   return fd;
    481  1.1.1.3  christos #endif /* HAVE_LIBDEBUGINFOD_FIND_SECTION */
    482  1.1.1.3  christos }
    483  1.1.1.3  christos 
    484  1.1.1.2  christos #endif
    485  1.1.1.2  christos 
    486  1.1.1.2  christos /* Set callback for "set debuginfod enabled".  */
    487  1.1.1.2  christos 
    488  1.1.1.2  christos static void
    489  1.1.1.2  christos set_debuginfod_enabled (const char *value)
    490  1.1.1.2  christos {
    491  1.1.1.2  christos #if defined(HAVE_LIBDEBUGINFOD)
    492  1.1.1.2  christos   debuginfod_enabled = value;
    493  1.1.1.2  christos #else
    494  1.1.1.2  christos   /* Disabling debuginfod when gdb is not built with it is a no-op.  */
    495  1.1.1.2  christos   if (value != debuginfod_off)
    496  1.1.1.2  christos     error (NO_IMPL);
    497      1.1  christos #endif
    498  1.1.1.2  christos }
    499  1.1.1.2  christos 
    500  1.1.1.2  christos /* Get callback for "set debuginfod enabled".  */
    501  1.1.1.2  christos 
    502  1.1.1.2  christos static const char *
    503  1.1.1.2  christos get_debuginfod_enabled ()
    504  1.1.1.2  christos {
    505  1.1.1.2  christos   return debuginfod_enabled;
    506  1.1.1.2  christos }
    507  1.1.1.2  christos 
    508  1.1.1.2  christos /* Show callback for "set debuginfod enabled".  */
    509  1.1.1.2  christos 
    510  1.1.1.2  christos static void
    511  1.1.1.2  christos show_debuginfod_enabled (ui_file *file, int from_tty, cmd_list_element *cmd,
    512  1.1.1.2  christos 			 const char *value)
    513  1.1.1.2  christos {
    514  1.1.1.2  christos   gdb_printf (file,
    515  1.1.1.2  christos 	      _("Debuginfod functionality is currently set to "
    516  1.1.1.2  christos 		"\"%s\".\n"), debuginfod_enabled);
    517  1.1.1.2  christos }
    518  1.1.1.2  christos 
    519  1.1.1.2  christos /* Set callback for "set debuginfod urls".  */
    520  1.1.1.2  christos 
    521  1.1.1.2  christos static void
    522  1.1.1.2  christos set_debuginfod_urls (const std::string &urls)
    523  1.1.1.2  christos {
    524  1.1.1.2  christos #if defined(HAVE_LIBDEBUGINFOD)
    525  1.1.1.2  christos   if (setenv (DEBUGINFOD_URLS_ENV_VAR, urls.c_str (), 1) != 0)
    526  1.1.1.2  christos     warning (_("Unable to set debuginfod URLs: %s"), safe_strerror (errno));
    527  1.1.1.2  christos #else
    528  1.1.1.2  christos   error (NO_IMPL);
    529  1.1.1.2  christos #endif
    530  1.1.1.2  christos }
    531  1.1.1.2  christos 
    532  1.1.1.2  christos /* Get callback for "set debuginfod urls".  */
    533  1.1.1.2  christos 
    534  1.1.1.2  christos static const std::string&
    535  1.1.1.2  christos get_debuginfod_urls ()
    536  1.1.1.2  christos {
    537  1.1.1.2  christos   static std::string urls;
    538  1.1.1.2  christos #if defined(HAVE_LIBDEBUGINFOD)
    539  1.1.1.2  christos   const char *envvar = getenv (DEBUGINFOD_URLS_ENV_VAR);
    540  1.1.1.2  christos 
    541  1.1.1.2  christos   if (envvar != nullptr)
    542  1.1.1.2  christos     urls = envvar;
    543  1.1.1.2  christos   else
    544  1.1.1.2  christos     urls.clear ();
    545  1.1.1.2  christos #endif
    546  1.1.1.2  christos 
    547  1.1.1.2  christos   return urls;
    548  1.1.1.2  christos }
    549  1.1.1.2  christos 
    550  1.1.1.2  christos /* Show callback for "set debuginfod urls".  */
    551  1.1.1.2  christos 
    552  1.1.1.2  christos static void
    553  1.1.1.2  christos show_debuginfod_urls (ui_file *file, int from_tty, cmd_list_element *cmd,
    554  1.1.1.2  christos 		      const char *value)
    555  1.1.1.2  christos {
    556  1.1.1.2  christos   if (value[0] == '\0')
    557  1.1.1.2  christos     gdb_printf (file, _("Debuginfod URLs have not been set.\n"));
    558  1.1.1.2  christos   else
    559  1.1.1.2  christos     gdb_printf (file, _("Debuginfod URLs are currently set to:\n%s\n"),
    560  1.1.1.2  christos 		value);
    561  1.1.1.2  christos }
    562  1.1.1.2  christos 
    563  1.1.1.2  christos /* Show callback for "set debuginfod verbose".  */
    564  1.1.1.2  christos 
    565  1.1.1.2  christos static void
    566  1.1.1.2  christos show_debuginfod_verbose_command (ui_file *file, int from_tty,
    567  1.1.1.2  christos 				 cmd_list_element *cmd, const char *value)
    568  1.1.1.2  christos {
    569  1.1.1.2  christos   gdb_printf (file, _("Debuginfod verbose output is set to %s.\n"),
    570  1.1.1.2  christos 	      value);
    571  1.1.1.2  christos }
    572  1.1.1.2  christos 
    573  1.1.1.3  christos /* Set callback for "maint set debuginfod download-sections".  */
    574  1.1.1.3  christos 
    575  1.1.1.3  christos static void
    576  1.1.1.3  christos maint_set_debuginfod_download_sections (bool value)
    577  1.1.1.3  christos {
    578  1.1.1.3  christos #if !defined(HAVE_LIBDEBUGINFOD_FIND_SECTION)
    579  1.1.1.3  christos   if (value)
    580  1.1.1.3  christos     error (_("Support for section downloading is not compiled into GDB. " \
    581  1.1.1.3  christos "Defaulting to \"off\"."));
    582  1.1.1.3  christos #endif
    583  1.1.1.3  christos 
    584  1.1.1.3  christos   debuginfod_download_sections = value;
    585  1.1.1.3  christos }
    586  1.1.1.3  christos 
    587  1.1.1.3  christos /* Get callback for "maint set debuginfod download-sections".  */
    588  1.1.1.3  christos 
    589  1.1.1.3  christos static bool
    590  1.1.1.3  christos maint_get_debuginfod_download_sections ()
    591  1.1.1.3  christos {
    592  1.1.1.3  christos   return debuginfod_download_sections;
    593  1.1.1.3  christos }
    594  1.1.1.3  christos 
    595  1.1.1.2  christos /* Register debuginfod commands.  */
    596  1.1.1.2  christos 
    597  1.1.1.2  christos void _initialize_debuginfod ();
    598  1.1.1.2  christos void
    599  1.1.1.2  christos _initialize_debuginfod ()
    600  1.1.1.2  christos {
    601  1.1.1.2  christos   /* set/show debuginfod */
    602  1.1.1.2  christos   add_setshow_prefix_cmd ("debuginfod", class_run,
    603  1.1.1.2  christos 			  _("Set debuginfod options."),
    604  1.1.1.2  christos 			  _("Show debuginfod options."),
    605  1.1.1.2  christos 			  &set_debuginfod_prefix_list,
    606  1.1.1.2  christos 			  &show_debuginfod_prefix_list,
    607  1.1.1.2  christos 			  &setlist, &showlist);
    608  1.1.1.2  christos 
    609  1.1.1.2  christos   add_setshow_enum_cmd ("enabled", class_run, debuginfod_enabled_enum,
    610  1.1.1.2  christos 			_("Set whether to use debuginfod."),
    611  1.1.1.2  christos 			_("Show whether to use debuginfod."),
    612  1.1.1.2  christos 			_("\
    613  1.1.1.3  christos When set to \"on\", enable the use of debuginfod to download missing\n\
    614  1.1.1.3  christos debug info and source files.  GDB may also download components of debug\n\
    615  1.1.1.3  christos info instead of entire files.  \"off\" disables the use of debuginfod.\n\
    616  1.1.1.3  christos When set to \"ask\", prompt whether to enable or disable debuginfod." ),
    617  1.1.1.2  christos 			set_debuginfod_enabled,
    618  1.1.1.2  christos 			get_debuginfod_enabled,
    619  1.1.1.2  christos 			show_debuginfod_enabled,
    620  1.1.1.2  christos 			&set_debuginfod_prefix_list,
    621  1.1.1.2  christos 			&show_debuginfod_prefix_list);
    622  1.1.1.2  christos 
    623  1.1.1.2  christos   /* set/show debuginfod urls */
    624  1.1.1.2  christos   add_setshow_string_noescape_cmd ("urls", class_run, _("\
    625  1.1.1.2  christos Set the list of debuginfod server URLs."), _("\
    626  1.1.1.2  christos Show the list of debuginfod server URLs."), _("\
    627  1.1.1.2  christos Manage the space-separated list of debuginfod server URLs that GDB will query \
    628  1.1.1.2  christos when missing debuginfo, executables or source files.\nThe default value is \
    629  1.1.1.2  christos copied from the DEBUGINFOD_URLS environment variable."),
    630  1.1.1.2  christos 				   set_debuginfod_urls,
    631  1.1.1.2  christos 				   get_debuginfod_urls,
    632  1.1.1.2  christos 				   show_debuginfod_urls,
    633  1.1.1.2  christos 				   &set_debuginfod_prefix_list,
    634  1.1.1.2  christos 				   &show_debuginfod_prefix_list);
    635  1.1.1.2  christos 
    636  1.1.1.2  christos   /* set/show debuginfod verbose */
    637  1.1.1.2  christos   add_setshow_zuinteger_cmd ("verbose", class_support,
    638  1.1.1.2  christos 			     &debuginfod_verbose, _("\
    639  1.1.1.2  christos Set verbosity of debuginfod output."), _("\
    640  1.1.1.2  christos Show debuginfod debugging."), _("\
    641  1.1.1.2  christos When set to a non-zero value, display verbose output for each debuginfod \
    642  1.1.1.2  christos query.\nTo disable, set to zero.  Verbose output is displayed by default."),
    643  1.1.1.2  christos 			     nullptr,
    644  1.1.1.2  christos 			     show_debuginfod_verbose_command,
    645  1.1.1.2  christos 			     &set_debuginfod_prefix_list,
    646  1.1.1.2  christos 			     &show_debuginfod_prefix_list);
    647  1.1.1.3  christos 
    648  1.1.1.3  christos   /* maint set/show debuginfod.  */
    649  1.1.1.3  christos   add_setshow_prefix_cmd ("debuginfod", class_maintenance,
    650  1.1.1.3  christos 			  _("Set debuginfod specific variables."),
    651  1.1.1.3  christos 			  _("Show debuginfod specific variables."),
    652  1.1.1.3  christos 			  &maint_set_debuginfod_cmdlist,
    653  1.1.1.3  christos 			  &maint_show_debuginfod_cmdlist,
    654  1.1.1.3  christos 			  &maintenance_set_cmdlist, &maintenance_show_cmdlist);
    655  1.1.1.3  christos 
    656  1.1.1.3  christos   /* maint set/show debuginfod download-sections.  */
    657  1.1.1.3  christos   add_setshow_boolean_cmd ("download-sections", class_maintenance, _("\
    658  1.1.1.3  christos Set whether debuginfod may download individual ELF/DWARF sections."), _("\
    659  1.1.1.3  christos Show whether debuginfod may download individual ELF/DWARF sections."), _("\
    660  1.1.1.3  christos When enabled, debuginfod may attempt to download individual ELF/DWARF \
    661  1.1.1.3  christos sections from debug info files.\nIf disabled, only whole debug info files \
    662  1.1.1.3  christos may be downloaded."),
    663  1.1.1.3  christos 			   maint_set_debuginfod_download_sections,
    664  1.1.1.3  christos 			   maint_get_debuginfod_download_sections,
    665  1.1.1.3  christos 			   nullptr,
    666  1.1.1.3  christos 			   &maint_set_debuginfod_cmdlist,
    667  1.1.1.3  christos 			   &maint_show_debuginfod_cmdlist);
    668  1.1.1.2  christos }
    669