1 /* debuginfod utilities for GDB.
2 Copyright (C) 2020 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/>. */
21 #include "cli/cli-style.h"
22 #include "gdbsupport/scoped_fd.h"
23 #include "debuginfod-support.h"
24 #include "gdbsupport/gdb_optional.h"
26 #ifndef HAVE_LIBDEBUGINFOD
28 debuginfod_source_query (const unsigned char *build_id
,
31 gdb::unique_xmalloc_ptr
<char> *destname
)
33 return scoped_fd (-ENOSYS
);
37 debuginfod_debuginfo_query (const unsigned char *build_id
,
40 gdb::unique_xmalloc_ptr
<char> *destname
)
42 return scoped_fd (-ENOSYS
);
45 #include <elfutils/debuginfod.h>
49 user_data (const char *desc
, const char *fname
)
50 : desc (desc
), fname (fname
)
53 const char * const desc
;
54 const char * const fname
;
55 gdb::optional
<ui_out::progress_meter
> meter
;
58 /* Deleter for a debuginfod_client. */
60 struct debuginfod_client_deleter
62 void operator() (debuginfod_client
*c
)
68 using debuginfod_client_up
69 = std::unique_ptr
<debuginfod_client
, debuginfod_client_deleter
>;
72 progressfn (debuginfod_client
*c
, long cur
, long total
)
74 user_data
*data
= static_cast<user_data
*> (debuginfod_get_user_data (c
));
76 if (check_quit_flag ())
78 printf_filtered ("Cancelling download of %s %ps...\n",
80 styled_string (file_name_style
.style (), data
->fname
));
87 if (!data
->meter
.has_value ())
89 float size_in_mb
= 1.0f
* total
/ (1024 * 1024);
90 string_file
styled_filename (current_uiout
->can_emit_style_escape ());
91 fprintf_styled (&styled_filename
,
92 file_name_style
.style (),
96 = string_printf ("Downloading %.2f MB %s %s", size_in_mb
, data
->desc
,
97 styled_filename
.c_str());
98 data
->meter
.emplace (current_uiout
, message
, 1);
101 current_uiout
->progress ((double)cur
/ (double)total
);
106 static debuginfod_client_up
109 debuginfod_client_up
c (debuginfod_begin ());
112 debuginfod_set_progressfn (c
.get (), progressfn
);
117 /* See debuginfod-support.h */
120 debuginfod_source_query (const unsigned char *build_id
,
123 gdb::unique_xmalloc_ptr
<char> *destname
)
125 const char *urls_env_var
= getenv (DEBUGINFOD_URLS_ENV_VAR
);
126 if (urls_env_var
== NULL
|| urls_env_var
[0] == '\0')
127 return scoped_fd (-ENOSYS
);
129 debuginfod_client_up c
= debuginfod_init ();
132 return scoped_fd (-ENOMEM
);
134 user_data
data ("source file", srcpath
);
136 debuginfod_set_user_data (c
.get (), &data
);
137 scoped_fd
fd (debuginfod_find_source (c
.get (),
143 /* TODO: Add 'set debug debuginfod' command to control when error messages are shown. */
144 if (fd
.get () < 0 && fd
.get () != -ENOENT
)
145 printf_filtered (_("Download failed: %s. Continuing without source file %ps.\n"),
146 safe_strerror (-fd
.get ()),
147 styled_string (file_name_style
.style (), srcpath
));
150 *destname
= make_unique_xstrdup (srcpath
);
155 /* See debuginfod-support.h */
158 debuginfod_debuginfo_query (const unsigned char *build_id
,
160 const char *filename
,
161 gdb::unique_xmalloc_ptr
<char> *destname
)
163 const char *urls_env_var
= getenv (DEBUGINFOD_URLS_ENV_VAR
);
164 if (urls_env_var
== NULL
|| urls_env_var
[0] == '\0')
165 return scoped_fd (-ENOSYS
);
167 debuginfod_client_up c
= debuginfod_init ();
170 return scoped_fd (-ENOMEM
);
172 char *dname
= nullptr;
173 user_data
data ("separate debug info for", filename
);
175 debuginfod_set_user_data (c
.get (), &data
);
176 scoped_fd
fd (debuginfod_find_debuginfo (c
.get (), build_id
, build_id_len
,
179 if (fd
.get () < 0 && fd
.get () != -ENOENT
)
180 printf_filtered (_("Download failed: %s. Continuing without debug info for %ps.\n"),
181 safe_strerror (-fd
.get ()),
182 styled_string (file_name_style
.style (), filename
));
185 destname
->reset (dname
);