GDB (xrefs)
Loading...
Searching...
No Matches
index-cache.c
Go to the documentation of this file.
1/* Caching of GDB/DWARF index files.
2
3 Copyright (C) 1994-2023 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20#include "defs.h"
21#include "dwarf2/index-cache.h"
22
23#include "build-id.h"
24#include "cli/cli-cmds.h"
25#include "cli/cli-decode.h"
26#include "command.h"
27#include "gdbsupport/scoped_mmap.h"
28#include "gdbsupport/pathstuff.h"
29#include "dwarf2/index-write.h"
30#include "dwarf2/read.h"
31#include "dwarf2/dwz.h"
32#include "objfiles.h"
33#include "gdbsupport/selftest.h"
34#include <string>
35#include <stdlib.h>
36
37/* When set to true, show debug messages about the index cache. */
38static bool debug_index_cache = false;
39
40#define index_cache_debug(FMT, ...) \
41 debug_prefixed_printf_cond_nofunc (debug_index_cache, "index-cache", \
42 FMT, ## __VA_ARGS__)
43
44/* The index cache directory, used for "set/show index-cache directory". */
45static std::string index_cache_directory;
46
47/* See dwarf-index.cache.h. */
49
50/* set/show index-cache commands. */
53
54/* Default destructor of index_cache_resource. */
56
57/* See dwarf-index-cache.h. */
58
59void
61{
62 gdb_assert (!dir.empty ());
63
64 m_dir = std::move (dir);
65
66 index_cache_debug ("now using directory %s", m_dir.c_str ());
67}
68
69/* See dwarf-index-cache.h. */
70
71void
73{
74 index_cache_debug ("enabling (%s)", m_dir.c_str ());
75
76 m_enabled = true;
77}
78
79/* See dwarf-index-cache.h. */
80
81void
83{
84 index_cache_debug ("disabling");
85
86 m_enabled = false;
87}
88
89 /* See index-cache.h. */
90
92 dwarf2_per_bfd *per_bfd)
93 : m_enabled (ic.enabled ())
94{
95 if (!m_enabled)
96 return;
97
98 /* Get build id of objfile. */
99 const bfd_build_id *build_id = build_id_bfd_get (per_bfd->obfd);
100 if (build_id == nullptr)
101 {
102 index_cache_debug ("objfile %s has no build id",
103 bfd_get_filename (per_bfd->obfd));
104 m_enabled = false;
105 return;
106 }
107 build_id_str = build_id_to_string (build_id);
108
109 /* Get build id of dwz file, if present. */
110 const dwz_file *dwz = dwarf2_get_dwz_file (per_bfd);
111
112 if (dwz != nullptr)
113 {
114 const bfd_build_id *dwz_build_id = build_id_bfd_get (dwz->dwz_bfd.get ());
115
116 if (dwz_build_id == nullptr)
117 {
118 index_cache_debug ("dwz objfile %s has no build id",
119 dwz->filename ());
120 m_enabled = false;
121 return;
122 }
123
124 dwz_build_id_str = build_id_to_string (dwz_build_id);
125 }
126
127 if (ic.m_dir.empty ())
128 {
129 warning (_("The index cache directory name is empty, skipping store."));
130 m_enabled = false;
131 return;
132 }
133
134 try
135 {
136 /* Try to create the containing directory. */
137 if (!mkdir_recursive (ic.m_dir.c_str ()))
138 {
139 warning (_("index cache: could not make cache directory: %s"),
140 safe_strerror (errno));
141 m_enabled = false;
142 return;
143 }
144 }
145 catch (const gdb_exception_error &except)
146 {
147 index_cache_debug ("couldn't store index cache for objfile %s: %s",
148 bfd_get_filename (per_bfd->obfd), except.what ());
149 m_enabled = false;
150 }
151}
152
153/* See dwarf-index-cache.h. */
154
155void
157 const index_cache_store_context &ctx)
158{
159 if (!ctx.m_enabled)
160 return;
161
162 const char *dwz_build_id_ptr = (ctx.dwz_build_id_str.has_value ()
163 ? ctx.dwz_build_id_str->c_str ()
164 : nullptr);
165
166 try
167 {
168 index_cache_debug ("writing index cache for objfile %s",
169 bfd_get_filename (per_bfd->obfd));
170
171 /* Write the index itself to the directory, using the build id as the
172 filename. */
173 write_dwarf_index (per_bfd, m_dir.c_str (),
174 ctx.build_id_str.c_str (), dwz_build_id_ptr,
176 }
177 catch (const gdb_exception_error &except)
178 {
179 index_cache_debug ("couldn't store index cache for objfile %s: %s",
180 bfd_get_filename (per_bfd->obfd), except.what ());
181 }
182}
183
184#if HAVE_SYS_MMAN_H
185
186/* Hold the resources for an mmapped index file. */
187
188struct index_cache_resource_mmap final : public index_cache_resource
189{
190 /* Try to mmap FILENAME. Throw an exception on failure, including if the
191 file doesn't exist. */
192 index_cache_resource_mmap (const char *filename)
193 : mapping (mmap_file (filename))
194 {}
195
196 scoped_mmap mapping;
197};
198
199/* See dwarf-index-cache.h. */
200
201gdb::array_view<const gdb_byte>
202index_cache::lookup_gdb_index (const bfd_build_id *build_id,
203 std::unique_ptr<index_cache_resource> *resource)
204{
205 if (!enabled ())
206 return {};
207
208 if (m_dir.empty ())
209 {
210 warning (_("The index cache directory name is empty, skipping cache "
211 "lookup."));
212 return {};
213 }
214
215 /* Compute where we would expect a gdb index file for this build id to be. */
216 std::string filename = make_index_filename (build_id, INDEX4_SUFFIX);
217
218 try
219 {
220 index_cache_debug ("trying to read %s",
221 filename.c_str ());
222
223 /* Try to map that file. */
224 index_cache_resource_mmap *mmap_resource
225 = new index_cache_resource_mmap (filename.c_str ());
226
227 /* Yay, it worked! Hand the resource to the caller. */
228 resource->reset (mmap_resource);
229
230 return gdb::array_view<const gdb_byte>
231 ((const gdb_byte *) mmap_resource->mapping.get (),
232 mmap_resource->mapping.size ());
233 }
234 catch (const gdb_exception_error &except)
235 {
236 index_cache_debug ("couldn't read %s: %s",
237 filename.c_str (), except.what ());
238 }
239
240 return {};
241}
242
243#else /* !HAVE_SYS_MMAN_H */
244
245/* See dwarf-index-cache.h. This is a no-op on unsupported systems. */
246
247gdb::array_view<const gdb_byte>
248index_cache::lookup_gdb_index (const bfd_build_id *build_id,
249 std::unique_ptr<index_cache_resource> *resource)
250{
251 return {};
252}
253
254#endif
255
256/* See dwarf-index-cache.h. */
257
258std::string
259index_cache::make_index_filename (const bfd_build_id *build_id,
260 const char *suffix) const
261{
262 std::string build_id_str = build_id_to_string (build_id);
263
264 return m_dir + SLASH_STRING + build_id_str + suffix;
265}
266
267/* True when we are executing "show index-cache". This is used to improve the
268 printout a little bit. */
269static bool in_show_index_cache_command = false;
270
271/* "show index-cache" handler. */
272
273static void
274show_index_cache_command (const char *arg, int from_tty)
275{
276 /* Note that we are executing "show index-cache". */
277 auto restore_flag = make_scoped_restore (&in_show_index_cache_command, true);
278
279 /* Call all "show index-cache" subcommands. */
281
282 gdb_printf ("\n");
284 (_("The index cache is currently %s.\n"),
285 global_index_cache.enabled () ? _("enabled") : _("disabled"));
286}
287
288/* "set/show index-cache enabled" set callback. */
289
290static void
298
299/* "set/show index-cache enabled" get callback. */
300
301static bool
306
307/* "set/show index-cache enabled" show callback. */
308
309static void
311 cmd_list_element *cmd, const char *value)
312{
313 gdb_printf (stream, _("The index cache is %s.\n"), value);
314}
315
316/* "set index-cache directory" handler. */
317
318static void
319set_index_cache_directory_command (const char *arg, int from_tty,
320 cmd_list_element *element)
321{
322 /* Make sure the index cache directory is absolute and tilde-expanded. */
323 index_cache_directory = gdb_abspath (index_cache_directory.c_str ());
325}
326
327/* "show index-cache stats" handler. */
328
329static void
330show_index_cache_stats_command (const char *arg, int from_tty)
331{
332 const char *indent = "";
333
334 /* If this command is invoked through "show index-cache", make the display a
335 bit nicer. */
337 {
338 indent = " ";
339 gdb_printf ("\n");
340 }
341
342 gdb_printf (_("%s Cache hits (this session): %u\n"),
343 indent, global_index_cache.n_hits ());
344 gdb_printf (_("%sCache misses (this session): %u\n"),
345 indent, global_index_cache.n_misses ());
346}
347
349void
351{
352 /* Set the default index cache directory. */
353 std::string cache_dir = get_standard_cache_dir ();
354 if (!cache_dir.empty ())
355 {
356 index_cache_directory = cache_dir;
357 global_index_cache.set_directory (std::move (cache_dir));
358 }
359 else
360 warning (_("Couldn't determine a path for the index cache directory."));
361
362 /* set index-cache */
363 add_basic_prefix_cmd ("index-cache", class_files,
364 _("Set index-cache options."),
366 false, &setlist);
367
368 /* show index-cache */
370 _("Show index-cache options."), &show_index_cache_prefix_list,
371 false, &showlist);
372
373 /* set/show index-cache enabled */
374 set_show_commands setshow_index_cache_enabled_cmds
376 _("Enable the index cache."),
377 _("Show whether the index cache is enabled."),
378 _("When on, enable the use of the index cache."),
384
385 /* set index-cache on */
386 cmd_list_element *set_index_cache_on_cmd
387 = add_alias_cmd ("on", setshow_index_cache_enabled_cmds.set, class_files,
389 deprecate_cmd (set_index_cache_on_cmd, "set index-cache enabled on");
390 set_index_cache_on_cmd->default_args = "on";
391
392 /* set index-cache off */
393 cmd_list_element *set_index_cache_off_cmd
394 = add_alias_cmd ("off", setshow_index_cache_enabled_cmds.set, class_files,
396 deprecate_cmd (set_index_cache_off_cmd, "set index-cache enabled off");
397 set_index_cache_off_cmd->default_args = "off";
398
399 /* set index-cache directory */
401 _("Set the directory of the index cache."),
402 _("Show the directory of the index cache."),
403 NULL,
407
408 /* show index-cache stats */
410 _("Show some stats about the index cache."),
412
413 /* set debug index-cache */
416 _("Set display of index-cache debug messages."),
417 _("Show display of index-cache debug messages."),
418 _("\
419When non-zero, debugging output for the index cache is displayed."),
420 NULL, NULL,
422}
const struct bfd_build_id * build_id_bfd_get(bfd *abfd)
Definition build-id.c:34
static std::string build_id_to_string(const bfd_build_id *build_id)
Definition build-id.h:66
unsigned int n_hits() const
Definition index-cache.h:94
unsigned int n_misses() const
gdb::array_view< const gdb_byte > lookup_gdb_index(const bfd_build_id *build_id, std::unique_ptr< index_cache_resource > *resource)
void disable()
Definition index-cache.c:82
void store(dwarf2_per_bfd *per_bfd, const index_cache_store_context &)
std::string make_index_filename(const bfd_build_id *build_id, const char *suffix) const
std::string m_dir
bool enabled() const
Definition index-cache.h:68
void enable()
Definition index-cache.c:72
void set_directory(std::string dir)
Definition index-cache.c:60
struct cmd_list_element * showlist
Definition cli-cmds.c:127
struct cmd_list_element * setlist
Definition cli-cmds.c:119
struct cmd_list_element * showdebuglist
Definition cli-cmds.c:167
struct cmd_list_element * setdebuglist
Definition cli-cmds.c:165
set_show_commands add_setshow_filename_cmd(const char *name, enum command_class theclass, std::string *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, show_value_ftype *show_func, struct cmd_list_element **set_list, struct cmd_list_element **show_list)
Definition cli-decode.c:855
struct cmd_list_element * add_alias_cmd(const char *name, cmd_list_element *target, enum command_class theclass, int abbrev_flag, struct cmd_list_element **list)
Definition cli-decode.c:294
struct cmd_list_element * add_cmd(const char *name, enum command_class theclass, const char *doc, struct cmd_list_element **list)
Definition cli-decode.c:233
struct cmd_list_element * deprecate_cmd(struct cmd_list_element *cmd, const char *replacement)
Definition cli-decode.c:280
struct cmd_list_element * add_prefix_cmd(const char *name, enum command_class theclass, cmd_simple_func_ftype *fun, const char *doc, struct cmd_list_element **subcommands, int allow_unknown, struct cmd_list_element **list)
Definition cli-decode.c:357
set_show_commands add_setshow_boolean_cmd(const char *name, enum command_class theclass, bool *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, show_value_ftype *show_func, struct cmd_list_element **set_list, struct cmd_list_element **show_list)
Definition cli-decode.c:809
struct cmd_list_element * add_basic_prefix_cmd(const char *name, enum command_class theclass, const char *doc, struct cmd_list_element **subcommands, int allow_unknown, struct cmd_list_element **list)
Definition cli-decode.c:391
void cmd_show_list(struct cmd_list_element *list, int from_tty)
@ class_maintenance
Definition command.h:65
@ class_files
Definition command.h:57
struct dwz_file * dwarf2_get_dwz_file(dwarf2_per_bfd *per_bfd, bool require)
Definition dwz.c:193
static cmd_list_element * show_index_cache_prefix_list
Definition index-cache.c:52
static void show_index_cache_command(const char *arg, int from_tty)
static bool debug_index_cache
Definition index-cache.c:38
#define index_cache_debug(FMT,...)
Definition index-cache.c:40
static cmd_list_element * set_index_cache_prefix_list
Definition index-cache.c:51
static void set_index_cache_directory_command(const char *arg, int from_tty, cmd_list_element *element)
static void show_index_cache_stats_command(const char *arg, int from_tty)
static std::string index_cache_directory
Definition index-cache.c:45
static bool in_show_index_cache_command
static void set_index_cache_enabled_command(bool value)
void _initialize_index_cache()
static void show_index_cache_enabled_command(ui_file *stream, int from_tty, cmd_list_element *cmd, const char *value)
static bool get_index_cache_enabled_command()
index_cache global_index_cache
Definition index-cache.c:48
#define INDEX4_SUFFIX
void write_dwarf_index(dwarf2_per_bfd *per_bfd, const char *dir, const char *basename, const char *dwz_basename, dw_index_kind index_kind)
std::string default_args
Definition cli-decode.h:210
bfd * obfd
Definition read.h:462
Definition dwz.h:32
const char * filename() const
Definition dwz.h:38
gdb_bfd_ref_ptr dwz_bfd
Definition dwz.h:54
virtual ~index_cache_resource()=0
index_cache_store_context(const index_cache &ic, dwarf2_per_bfd *per_bfd)
Definition index-cache.c:91
gdb::optional< std::string > dwz_build_id_str
Definition index-cache.h:55
cmd_list_element * set
Definition command.h:422
Definition value.h:130
void gdb_printf(struct ui_file *stream, const char *format,...)
Definition utils.c:1886