Automatic date update in version.in
[binutils-gdb.git] / gdb / debuginfod-support.c
blob9dbe6b5d8b2b9904eac1e3207439b76729c3d0e5
1 /* debuginfod utilities for GDB.
2 Copyright (C) 2020-2022 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 "defs.h"
20 #include "diagnostics.h"
21 #include <errno.h>
22 #include "gdbsupport/scoped_fd.h"
23 #include "debuginfod-support.h"
24 #include "gdbsupport/gdb_optional.h"
25 #include "cli/cli-cmds.h"
26 #include "cli/cli-style.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 static const char debuginfod_on[] = "on";
34 static const char debuginfod_off[] = "off";
35 static const char debuginfod_ask[] = "ask";
37 static const char *debuginfod_enabled_enum[] =
39 debuginfod_on,
40 debuginfod_off,
41 debuginfod_ask,
42 nullptr
45 static const char *debuginfod_enabled =
46 #if defined(HAVE_LIBDEBUGINFOD)
47 debuginfod_ask;
48 #else
49 debuginfod_off;
50 #endif
52 static unsigned int debuginfod_verbose = 1;
54 #ifndef HAVE_LIBDEBUGINFOD
55 scoped_fd
56 debuginfod_source_query (const unsigned char *build_id,
57 int build_id_len,
58 const char *srcpath,
59 gdb::unique_xmalloc_ptr<char> *destname)
61 return scoped_fd (-ENOSYS);
64 scoped_fd
65 debuginfod_debuginfo_query (const unsigned char *build_id,
66 int build_id_len,
67 const char *filename,
68 gdb::unique_xmalloc_ptr<char> *destname)
70 return scoped_fd (-ENOSYS);
73 scoped_fd
74 debuginfod_exec_query (const unsigned char *build_id,
75 int build_id_len,
76 const char *filename,
77 gdb::unique_xmalloc_ptr<char> *destname)
79 return scoped_fd (-ENOSYS);
82 #define NO_IMPL _("Support for debuginfod is not compiled into GDB.")
84 #else
85 #include <elfutils/debuginfod.h>
87 struct user_data
89 user_data (const char *desc, const char *fname)
90 : desc (desc), fname (fname), has_printed (false)
91 { }
93 const char * const desc;
94 const char * const fname;
95 bool has_printed;
98 /* Deleter for a debuginfod_client. */
100 struct debuginfod_client_deleter
102 void operator() (debuginfod_client *c)
104 debuginfod_end (c);
108 using debuginfod_client_up
109 = std::unique_ptr<debuginfod_client, debuginfod_client_deleter>;
111 static int
112 progressfn (debuginfod_client *c, long cur, long total)
114 user_data *data = static_cast<user_data *> (debuginfod_get_user_data (c));
115 gdb_assert (data != nullptr);
117 if (check_quit_flag ())
119 gdb_printf ("Cancelling download of %s %ps...\n",
120 data->desc,
121 styled_string (file_name_style.style (), data->fname));
122 return 1;
125 if (!data->has_printed)
127 /* Include the transfer size, if available. */
128 if (total > 0)
130 float size = 1.0f * total / 1024;
131 const char *unit = "KB";
133 /* If size is greater than 0.01 MB, set unit to MB. */
134 if (size > 10.24)
136 size /= 1024;
137 unit = "MB";
140 gdb_printf ("Downloading %.2f %s %s %ps...\n",
141 size, unit, data->desc,
142 styled_string (file_name_style.style (),
143 data->fname));
145 else
146 gdb_printf ("Downloading %s %ps...\n", data->desc,
147 styled_string (file_name_style.style (), data->fname));
149 data->has_printed = true;
152 return 0;
155 static debuginfod_client *
156 get_debuginfod_client ()
158 static debuginfod_client_up global_client;
160 if (global_client == nullptr)
162 global_client.reset (debuginfod_begin ());
164 if (global_client != nullptr)
165 debuginfod_set_progressfn (global_client.get (), progressfn);
168 return global_client.get ();
171 /* Check if debuginfod is enabled. If configured to do so, ask the user
172 whether to enable debuginfod. */
174 static bool
175 debuginfod_is_enabled ()
177 const char *urls = skip_spaces (getenv (DEBUGINFOD_URLS_ENV_VAR));
179 if (debuginfod_enabled == debuginfod_off
180 || urls == nullptr
181 || *urls == '\0')
182 return false;
184 if (debuginfod_enabled == debuginfod_ask)
186 gdb_printf (_("\nThis GDB supports auto-downloading debuginfo " \
187 "from the following URLs:\n"));
189 gdb::string_view url_view (urls);
190 while (true)
192 size_t off = url_view.find_first_not_of (' ');
193 if (off == gdb::string_view::npos)
194 break;
195 url_view = url_view.substr (off);
196 /* g++ 11.2.1 on s390x, g++ 11.3.1 on ppc64le and g++ 11 on
197 hppa seem convinced url_view might be of SIZE_MAX length.
198 And so complains because the length of an array can only
199 be PTRDIFF_MAX. */
200 DIAGNOSTIC_PUSH
201 DIAGNOSTIC_IGNORE_STRINGOP_OVERREAD
202 off = url_view.find_first_of (' ');
203 DIAGNOSTIC_POP
204 gdb_printf
205 (_(" <%ps>\n"),
206 styled_string (file_name_style.style (),
207 gdb::to_string (url_view.substr (0,
208 off)).c_str ()));
209 if (off == gdb::string_view::npos)
210 break;
211 url_view = url_view.substr (off);
214 int resp = nquery (_("Enable debuginfod for this session? "));
215 if (!resp)
217 gdb_printf (_("Debuginfod has been disabled.\nTo make this " \
218 "setting permanent, add \'set debuginfod " \
219 "enabled off\' to .gdbinit.\n"));
220 debuginfod_enabled = debuginfod_off;
221 return false;
224 gdb_printf (_("Debuginfod has been enabled.\nTo make this " \
225 "setting permanent, add \'set debuginfod enabled " \
226 "on\' to .gdbinit.\n"));
227 debuginfod_enabled = debuginfod_on;
230 return true;
233 /* See debuginfod-support.h */
235 scoped_fd
236 debuginfod_source_query (const unsigned char *build_id,
237 int build_id_len,
238 const char *srcpath,
239 gdb::unique_xmalloc_ptr<char> *destname)
241 if (!debuginfod_is_enabled ())
242 return scoped_fd (-ENOSYS);
244 debuginfod_client *c = get_debuginfod_client ();
246 if (c == nullptr)
247 return scoped_fd (-ENOMEM);
249 char *dname = nullptr;
250 user_data data ("source file", srcpath);
252 debuginfod_set_user_data (c, &data);
253 gdb::optional<target_terminal::scoped_restore_terminal_state> term_state;
254 if (target_supports_terminal_ours ())
256 term_state.emplace ();
257 target_terminal::ours ();
260 scoped_fd fd (debuginfod_find_source (c,
261 build_id,
262 build_id_len,
263 srcpath,
264 &dname));
265 debuginfod_set_user_data (c, nullptr);
267 if (fd.get () < 0 && fd.get () != -ENOENT)
268 gdb_printf (_("Download failed: %s. Continuing without source file %ps.\n"),
269 safe_strerror (-fd.get ()),
270 styled_string (file_name_style.style (), srcpath));
272 if (fd.get () >= 0)
273 destname->reset (dname);
275 return fd;
278 /* See debuginfod-support.h */
280 scoped_fd
281 debuginfod_debuginfo_query (const unsigned char *build_id,
282 int build_id_len,
283 const char *filename,
284 gdb::unique_xmalloc_ptr<char> *destname)
286 if (!debuginfod_is_enabled ())
287 return scoped_fd (-ENOSYS);
289 debuginfod_client *c = get_debuginfod_client ();
291 if (c == nullptr)
292 return scoped_fd (-ENOMEM);
294 char *dname = nullptr;
295 user_data data ("separate debug info for", filename);
297 debuginfod_set_user_data (c, &data);
298 gdb::optional<target_terminal::scoped_restore_terminal_state> term_state;
299 if (target_supports_terminal_ours ())
301 term_state.emplace ();
302 target_terminal::ours ();
305 scoped_fd fd (debuginfod_find_debuginfo (c, build_id, build_id_len,
306 &dname));
307 debuginfod_set_user_data (c, nullptr);
309 if (fd.get () < 0 && fd.get () != -ENOENT)
310 gdb_printf (_("Download failed: %s. Continuing without debug info for %ps.\n"),
311 safe_strerror (-fd.get ()),
312 styled_string (file_name_style.style (), filename));
314 if (fd.get () >= 0)
315 destname->reset (dname);
317 return fd;
320 /* See debuginfod-support.h */
322 scoped_fd
323 debuginfod_exec_query (const unsigned char *build_id,
324 int build_id_len,
325 const char *filename,
326 gdb::unique_xmalloc_ptr<char> *destname)
328 if (!debuginfod_is_enabled ())
329 return scoped_fd (-ENOSYS);
331 debuginfod_client *c = get_debuginfod_client ();
333 if (c == nullptr)
334 return scoped_fd (-ENOMEM);
336 char *dname = nullptr;
337 user_data data ("executable for", filename);
339 debuginfod_set_user_data (c, &data);
340 gdb::optional<target_terminal::scoped_restore_terminal_state> term_state;
341 if (target_supports_terminal_ours ())
343 term_state.emplace ();
344 target_terminal::ours ();
347 scoped_fd fd (debuginfod_find_executable (c, build_id, build_id_len, &dname));
348 debuginfod_set_user_data (c, nullptr);
350 if (fd.get () < 0 && fd.get () != -ENOENT)
351 gdb_printf (_("Download failed: %s. " \
352 "Continuing without executable for %ps.\n"),
353 safe_strerror (-fd.get ()),
354 styled_string (file_name_style.style (), filename));
356 if (fd.get () >= 0)
357 destname->reset (dname);
359 return fd;
361 #endif
363 /* Set callback for "set debuginfod enabled". */
365 static void
366 set_debuginfod_enabled (const char *value)
368 #if defined(HAVE_LIBDEBUGINFOD)
369 debuginfod_enabled = value;
370 #else
371 error (NO_IMPL);
372 #endif
375 /* Get callback for "set debuginfod enabled". */
377 static const char *
378 get_debuginfod_enabled ()
380 return debuginfod_enabled;
383 /* Show callback for "set debuginfod enabled". */
385 static void
386 show_debuginfod_enabled (ui_file *file, int from_tty, cmd_list_element *cmd,
387 const char *value)
389 gdb_printf (file,
390 _("Debuginfod functionality is currently set to "
391 "\"%s\".\n"), debuginfod_enabled);
394 /* Set callback for "set debuginfod urls". */
396 static void
397 set_debuginfod_urls (const std::string &urls)
399 #if defined(HAVE_LIBDEBUGINFOD)
400 if (setenv (DEBUGINFOD_URLS_ENV_VAR, urls.c_str (), 1) != 0)
401 warning (_("Unable to set debuginfod URLs: %s"), safe_strerror (errno));
402 #else
403 error (NO_IMPL);
404 #endif
407 /* Get callback for "set debuginfod urls". */
409 static const std::string&
410 get_debuginfod_urls ()
412 static std::string urls;
413 #if defined(HAVE_LIBDEBUGINFOD)
414 const char *envvar = getenv (DEBUGINFOD_URLS_ENV_VAR);
416 if (envvar != nullptr)
417 urls = envvar;
418 else
419 urls.clear ();
420 #endif
422 return urls;
425 /* Show callback for "set debuginfod urls". */
427 static void
428 show_debuginfod_urls (ui_file *file, int from_tty, cmd_list_element *cmd,
429 const char *value)
431 if (value[0] == '\0')
432 gdb_printf (file, _("Debuginfod URLs have not been set.\n"));
433 else
434 gdb_printf (file, _("Debuginfod URLs are currently set to:\n%s\n"),
435 value);
438 /* Show callback for "set debuginfod verbose". */
440 static void
441 show_debuginfod_verbose_command (ui_file *file, int from_tty,
442 cmd_list_element *cmd, const char *value)
444 gdb_printf (file, _("Debuginfod verbose output is set to %s.\n"),
445 value);
448 /* Register debuginfod commands. */
450 void _initialize_debuginfod ();
451 void
452 _initialize_debuginfod ()
454 /* set/show debuginfod */
455 add_setshow_prefix_cmd ("debuginfod", class_run,
456 _("Set debuginfod options."),
457 _("Show debuginfod options."),
458 &set_debuginfod_prefix_list,
459 &show_debuginfod_prefix_list,
460 &setlist, &showlist);
462 add_setshow_enum_cmd ("enabled", class_run, debuginfod_enabled_enum,
463 _("Set whether to use debuginfod."),
464 _("Show whether to use debuginfod."),
465 _("\
466 When on, enable the use of debuginfod to download missing debug info and\n\
467 source files."),
468 set_debuginfod_enabled,
469 get_debuginfod_enabled,
470 show_debuginfod_enabled,
471 &set_debuginfod_prefix_list,
472 &show_debuginfod_prefix_list);
474 /* set/show debuginfod urls */
475 add_setshow_string_noescape_cmd ("urls", class_run, _("\
476 Set the list of debuginfod server URLs."), _("\
477 Show the list of debuginfod server URLs."), _("\
478 Manage the space-separated list of debuginfod server URLs that GDB will query \
479 when missing debuginfo, executables or source files.\nThe default value is \
480 copied from the DEBUGINFOD_URLS environment variable."),
481 set_debuginfod_urls,
482 get_debuginfod_urls,
483 show_debuginfod_urls,
484 &set_debuginfod_prefix_list,
485 &show_debuginfod_prefix_list);
487 /* set/show debuginfod verbose */
488 add_setshow_zuinteger_cmd ("verbose", class_support,
489 &debuginfod_verbose, _("\
490 Set verbosity of debuginfod output."), _("\
491 Show debuginfod debugging."), _("\
492 When set to a non-zero value, display verbose output for each debuginfod \
493 query.\nTo disable, set to zero. Verbose output is displayed by default."),
494 nullptr,
495 show_debuginfod_verbose_command,
496 &set_debuginfod_prefix_list,
497 &show_debuginfod_prefix_list);