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