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