1 /* debuginfod utilities for GDB.
2 Copyright (C) 2020-2021 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
));
75 gdb_assert (data
!= nullptr);
77 if (check_quit_flag ())
79 printf_filtered ("Cancelling download of %s %ps...\n",
81 styled_string (file_name_style
.style (), data
->fname
));
88 if (!data
->meter
.has_value ())
90 float size_in_mb
= 1.0f
* total
/ (1024 * 1024);
91 string_file
styled_filename (current_uiout
->can_emit_style_escape ());
92 fprintf_styled (&styled_filename
,
93 file_name_style
.style (),
97 = string_printf ("Downloading %.2f MB %s %s", size_in_mb
, data
->desc
,
98 styled_filename
.c_str());
99 data
->meter
.emplace (current_uiout
, message
, 1);
102 current_uiout
->progress ((double)cur
/ (double)total
);
107 static debuginfod_client
*
108 get_debuginfod_client ()
110 static debuginfod_client_up global_client
;
112 if (global_client
== nullptr)
114 global_client
.reset (debuginfod_begin ());
116 if (global_client
!= nullptr)
117 debuginfod_set_progressfn (global_client
.get (), progressfn
);
120 return global_client
.get ();
123 /* See debuginfod-support.h */
126 debuginfod_source_query (const unsigned char *build_id
,
129 gdb::unique_xmalloc_ptr
<char> *destname
)
131 const char *urls_env_var
= getenv (DEBUGINFOD_URLS_ENV_VAR
);
132 if (urls_env_var
== NULL
|| urls_env_var
[0] == '\0')
133 return scoped_fd (-ENOSYS
);
135 debuginfod_client
*c
= get_debuginfod_client ();
138 return scoped_fd (-ENOMEM
);
140 user_data
data ("source file", srcpath
);
142 debuginfod_set_user_data (c
, &data
);
143 scoped_fd
fd (debuginfod_find_source (c
,
148 debuginfod_set_user_data (c
, nullptr);
150 /* TODO: Add 'set debug debuginfod' command to control when error messages are shown. */
151 if (fd
.get () < 0 && fd
.get () != -ENOENT
)
152 printf_filtered (_("Download failed: %s. Continuing without source file %ps.\n"),
153 safe_strerror (-fd
.get ()),
154 styled_string (file_name_style
.style (), srcpath
));
157 *destname
= make_unique_xstrdup (srcpath
);
162 /* See debuginfod-support.h */
165 debuginfod_debuginfo_query (const unsigned char *build_id
,
167 const char *filename
,
168 gdb::unique_xmalloc_ptr
<char> *destname
)
170 const char *urls_env_var
= getenv (DEBUGINFOD_URLS_ENV_VAR
);
171 if (urls_env_var
== NULL
|| urls_env_var
[0] == '\0')
172 return scoped_fd (-ENOSYS
);
174 debuginfod_client
*c
= get_debuginfod_client ();
177 return scoped_fd (-ENOMEM
);
179 char *dname
= nullptr;
180 user_data
data ("separate debug info for", filename
);
182 debuginfod_set_user_data (c
, &data
);
183 scoped_fd
fd (debuginfod_find_debuginfo (c
, build_id
, build_id_len
,
185 debuginfod_set_user_data (c
, nullptr);
187 if (fd
.get () < 0 && fd
.get () != -ENOENT
)
188 printf_filtered (_("Download failed: %s. Continuing without debug info for %ps.\n"),
189 safe_strerror (-fd
.get ()),
190 styled_string (file_name_style
.style (), filename
));
193 destname
->reset (dname
);