1 /* Caching of GDB/DWARF index files.
3 Copyright (C) 1994-2018 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
21 #include "dwarf-index-cache.h"
24 #include "cli/cli-cmds.h"
26 #include "common/scoped_mmap.h"
27 #include "common/pathstuff.h"
28 #include "dwarf-index-write.h"
29 #include "dwarf2read.h"
35 /* When set to 1, show debug messages about the index cache. */
36 static int debug_index_cache = 0;
38 /* The index cache directory, used for "set/show index-cache directory". */
39 static char *index_cache_directory = NULL;
41 /* See dwarf-index.cache.h. */
42 index_cache global_index_cache;
44 /* set/show index-cache commands. */
45 static cmd_list_element *set_index_cache_prefix_list;
46 static cmd_list_element *show_index_cache_prefix_list;
48 /* A cheap (as in low-quality) recursive mkdir. Try to create all the parents
49 directories up to DIR and DIR itself. Stop if we hit an error along the way.
50 There is no attempt to remove created directories in case of failure. */
53 mkdir_recursive (const char *dir)
55 gdb::unique_xmalloc_ptr<char> holder (xstrdup (dir));
56 char * const start = holder.get ();
57 char *component_start = start;
58 char *component_end = start;
62 /* Find the beginning of the next component. */
63 while (*component_start == '/')
67 if (*component_start == '\0')
70 /* Find the slash or null-terminator after this component. */
71 component_end = component_start;
72 while (*component_end != '/' && *component_end != '\0')
75 /* Temporarily replace the slash with a null terminator, so we can create
76 the directory up to this component. */
77 char saved_char = *component_end;
78 *component_end = '\0';
80 /* If we get EEXIST and the existing path is a directory, then we're
81 happy. If it exists, but it's a regular file and this is not the last
82 component, we'll fail at the next component. If this is the last
83 component, the caller will fail with ENOTDIR when trying to
84 open/create a file under that path. */
85 if (mkdir (start, 0700) != 0)
89 /* Restore the overwritten char. */
90 *component_end = saved_char;
91 component_start = component_end;
95 /* Default destructor of index_cache_resource. */
96 index_cache_resource::~index_cache_resource () = default;
98 /* See dwarf-index-cache.h. */
101 index_cache::set_directory (std::string dir)
103 gdb_assert (!dir.empty ());
105 m_dir = std::move (dir);
107 if (debug_index_cache)
108 printf_unfiltered ("index cache: now using directory %s\n", m_dir.c_str ());
111 /* See dwarf-index-cache.h. */
114 index_cache::enable ()
116 if (debug_index_cache)
117 printf_unfiltered ("index cache: enabling (%s)\n", m_dir.c_str ());
122 /* See dwarf-index-cache.h. */
125 index_cache::disable ()
127 if (debug_index_cache)
128 printf_unfiltered ("index cache: disabling\n");
133 /* See dwarf-index-cache.h. */
136 index_cache::store (struct dwarf2_per_objfile *dwarf2_per_objfile)
138 objfile *obj = dwarf2_per_objfile->objfile;
143 const bfd_build_id *build_id = build_id_bfd_get (obj->obfd);
144 if (build_id == nullptr)
146 if (debug_index_cache)
147 printf_unfiltered ("index cache: objfile %s has no build id\n",
154 warning (_("The index cache directory name is empty, skipping store."));
158 std::string build_id_str = build_id_to_string (build_id);
162 /* Try to create the containing directory. */
163 mkdir_recursive (m_dir.c_str ());
165 if (debug_index_cache)
166 printf_unfiltered ("index cache: writing index cache for objfile %s\n",
169 /* Write the index itself to the directory, using the build id as the
171 write_psymtabs_to_index (dwarf2_per_objfile, m_dir.c_str (),
172 build_id_str.c_str (), dw_index_kind::GDB_INDEX);
174 CATCH (except, RETURN_MASK_ERROR)
176 if (debug_index_cache)
177 printf_unfiltered ("index cache: couldn't store index cache for objfile "
178 "%s: %s", objfile_name (obj), except.message);
185 /* Hold the resources for an mmapped index file. */
187 struct index_cache_resource_mmap final : public index_cache_resource
189 /* Try to mmap FILENAME. Throw an exception on failure, including if the
190 file doesn't exist. */
191 index_cache_resource_mmap (const char *filename)
192 : mapping (mmap_file (filename))
198 /* See dwarf-index-cache.h. */
200 gdb::array_view<const gdb_byte>
201 index_cache::lookup_gdb_index (const bfd_build_id *build_id,
202 std::unique_ptr<index_cache_resource> *resource)
209 warning (_("The index cache directory name is empty, skipping cache "
214 /* Compute where we would expect a gdb index file for this build id to be. */
215 std::string filename = make_index_filename (build_id, INDEX4_SUFFIX);
219 if (debug_index_cache)
220 printf_unfiltered ("index cache: trying to read %s\n",
223 /* Try to map that file. */
224 index_cache_resource_mmap *mmap_resource
225 = new index_cache_resource_mmap (filename.c_str ());
227 /* Yay, it worked! Hand the resource to the caller. */
228 resource->reset (mmap_resource);
230 return gdb::array_view<const gdb_byte>
231 ((const gdb_byte *) mmap_resource->mapping.get (),
232 mmap_resource->mapping.size ());
234 CATCH (except, RETURN_MASK_ERROR)
236 if (debug_index_cache)
237 printf_unfiltered ("index cache: couldn't read %s: %s\n",
238 filename.c_str (), except.message);
245 #else /* !HAVE_SYS_MMAN_H */
247 /* See dwarf-index-cache.h. This is a no-op on unsupported systems. */
249 gdb::array_view<const gdb_byte>
250 index_cache::lookup_gdb_index (const bfd_build_id *build_id,
251 std::unique_ptr<index_cache_resource> *resource)
258 /* See dwarf-index-cache.h. */
261 index_cache::make_index_filename (const bfd_build_id *build_id,
262 const char *suffix) const
264 std::string build_id_str = build_id_to_string (build_id);
266 return m_dir + SLASH_STRING + build_id_str + suffix;
269 /* "set index-cache" handler. */
272 set_index_cache_command (const char *arg, int from_tty)
274 printf_unfiltered (_("\
275 Missing arguments. See \"help set index-cache\" for help.\n"));
278 /* True when we are executing "show index-cache". This is used to improve the
279 printout a little bit. */
280 static bool in_show_index_cache_command = false;
282 /* "show index-cache" handler. */
285 show_index_cache_command (const char *arg, int from_tty)
287 /* Note that we are executing "show index-cache". */
288 auto restore_flag = make_scoped_restore (&in_show_index_cache_command, true);
290 /* Call all "show index-cache" subcommands. */
291 cmd_show_list (show_index_cache_prefix_list, from_tty, "");
293 printf_unfiltered ("\n");
295 (_("The index cache is currently %s.\n"),
296 global_index_cache.enabled () ? _("enabled") : _("disabled"));
299 /* "set index-cache on" handler. */
302 set_index_cache_on_command (const char *arg, int from_tty)
304 global_index_cache.enable ();
307 /* "set index-cache off" handler. */
310 set_index_cache_off_command (const char *arg, int from_tty)
312 global_index_cache.disable ();
315 /* "set index-cache directory" handler. */
318 set_index_cache_directory_command (const char *arg, int from_tty,
319 cmd_list_element *element)
321 /* Make sure the index cache directory is absolute and tilde-expanded. */
322 gdb::unique_xmalloc_ptr<char> abs (gdb_abspath (index_cache_directory));
323 xfree (index_cache_directory);
324 index_cache_directory = abs.release ();
325 global_index_cache.set_directory (index_cache_directory);
328 /* "show index-cache stats" handler. */
331 show_index_cache_stats_command (const char *arg, int from_tty)
333 const char *indent = "";
335 /* If this command is invoked through "show index-cache", make the display a
337 if (in_show_index_cache_command)
340 printf_unfiltered ("\n");
343 printf_unfiltered (_("%s Cache hits (this session): %u\n"),
344 indent, global_index_cache.n_hits ());
345 printf_unfiltered (_("%sCache misses (this session): %u\n"),
346 indent, global_index_cache.n_misses ());
349 #if GDB_SELF_TEST && defined (HAVE_MKDTEMP)
353 /* Try to create DIR using mkdir_recursive and make sure it exists. */
356 create_dir_and_check (const char *dir)
358 mkdir_recursive (dir);
361 if (stat (dir, &st) != 0)
362 perror_with_name (("stat"));
364 return (st.st_mode & S_IFDIR) != 0;
367 /* Test mkdir_recursive. */
370 test_mkdir_recursive ()
372 char base[] = "/tmp/gdb-selftests-XXXXXX";
374 if (mkdtemp (base) == NULL)
375 perror_with_name (("mkdtemp"));
377 /* Try not to leave leftover directories. */
378 struct cleanup_dirs {
379 cleanup_dirs (const char *base)
384 rmdir (string_printf ("%s/a/b/c/d/e", m_base).c_str ());
385 rmdir (string_printf ("%s/a/b/c/d", m_base).c_str ());
386 rmdir (string_printf ("%s/a/b/c", m_base).c_str ());
387 rmdir (string_printf ("%s/a/b", m_base).c_str ());
388 rmdir (string_printf ("%s/a", m_base).c_str ());
394 } cleanup_dirs (base);
396 std::string dir = string_printf ("%s/a/b", base);
397 SELF_CHECK (create_dir_and_check (dir.c_str ()));
399 dir = string_printf ("%s/a/b/c//d/e/", base);
400 SELF_CHECK (create_dir_and_check (dir.c_str ()));
403 #endif /* GDB_SELF_TEST && defined (HAVE_MKDTEMP) */
406 _initialize_index_cache ()
408 /* Set the default index cache directory. */
409 std::string cache_dir = get_standard_cache_dir ();
410 if (!cache_dir.empty ())
412 index_cache_directory = xstrdup (cache_dir.c_str ());
413 global_index_cache.set_directory (std::move (cache_dir));
416 warning (_("Couldn't determine a path for the index cache directory."));
418 /* set index-cache */
419 add_prefix_cmd ("index-cache", class_files, set_index_cache_command,
420 _("Set index-cache options"), &set_index_cache_prefix_list,
421 "set index-cache ", false, &setlist);
423 /* show index-cache */
424 add_prefix_cmd ("index-cache", class_files, show_index_cache_command,
425 _("Show index-cache options"), &show_index_cache_prefix_list,
426 "show index-cache ", false, &showlist);
428 /* set index-cache on */
429 add_cmd ("on", class_files, set_index_cache_on_command,
430 _("Enable the index cache."), &set_index_cache_prefix_list);
432 /* set index-cache off */
433 add_cmd ("off", class_files, set_index_cache_off_command,
434 _("Disable the index cache."), &set_index_cache_prefix_list);
436 /* set index-cache directory */
437 add_setshow_filename_cmd ("directory", class_files, &index_cache_directory,
438 _("Set the directory of the index cache."),
439 _("Show the directory of the index cache."),
441 set_index_cache_directory_command, NULL,
442 &set_index_cache_prefix_list,
443 &show_index_cache_prefix_list);
445 /* show index-cache stats */
446 add_cmd ("stats", class_files, show_index_cache_stats_command,
447 _("Show some stats about the index cache."),
448 &show_index_cache_prefix_list);
450 /* set debug index-cache */
451 add_setshow_boolean_cmd ("index-cache", class_maintenance,
453 _("Set display of index-cache debug messages."),
454 _("Show display of index-cache debug messages."),
456 When non-zero, debugging output for the index cache is displayed."),
458 &setdebuglist, &showdebuglist);
460 #if GDB_SELF_TEST && defined (HAVE_MKDTEMP)
461 selftests::register_test ("mkdir_recursive", selftests::test_mkdir_recursive);