1 /* Caching of GDB/DWARF index files. 2 3 Copyright (C) 1994-2020 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 "command.h" 26 #include "gdbsupport/scoped_mmap.h" 27 #include "gdbsupport/pathstuff.h" 28 #include "dwarf2/index-write.h" 29 #include "dwarf2/read.h" 30 #include "dwarf2/dwz.h" 31 #include "objfiles.h" 32 #include "gdbsupport/selftest.h" 33 #include <string> 34 #include <stdlib.h> 35 36 /* When set to true, show debug messages about the index cache. */ 37 static bool debug_index_cache = false; 38 39 /* The index cache directory, used for "set/show index-cache directory". */ 40 static char *index_cache_directory = NULL; 41 42 /* See dwarf-index.cache.h. */ 43 index_cache global_index_cache; 44 45 /* set/show index-cache commands. */ 46 static cmd_list_element *set_index_cache_prefix_list; 47 static cmd_list_element *show_index_cache_prefix_list; 48 49 /* Default destructor of index_cache_resource. */ 50 index_cache_resource::~index_cache_resource () = default; 51 52 /* See dwarf-index-cache.h. */ 53 54 void 55 index_cache::set_directory (std::string dir) 56 { 57 gdb_assert (!dir.empty ()); 58 59 m_dir = std::move (dir); 60 61 if (debug_index_cache) 62 printf_unfiltered ("index cache: now using directory %s\n", m_dir.c_str ()); 63 } 64 65 /* See dwarf-index-cache.h. */ 66 67 void 68 index_cache::enable () 69 { 70 if (debug_index_cache) 71 printf_unfiltered ("index cache: enabling (%s)\n", m_dir.c_str ()); 72 73 m_enabled = true; 74 } 75 76 /* See dwarf-index-cache.h. */ 77 78 void 79 index_cache::disable () 80 { 81 if (debug_index_cache) 82 printf_unfiltered ("index cache: disabling\n"); 83 84 m_enabled = false; 85 } 86 87 /* See dwarf-index-cache.h. */ 88 89 void 90 index_cache::store (dwarf2_per_objfile *per_objfile) 91 { 92 objfile *obj = per_objfile->objfile; 93 94 if (!enabled ()) 95 return; 96 97 /* Get build id of objfile. */ 98 const bfd_build_id *build_id = build_id_bfd_get (obj->obfd); 99 if (build_id == nullptr) 100 { 101 if (debug_index_cache) 102 printf_unfiltered ("index cache: objfile %s has no build id\n", 103 objfile_name (obj)); 104 return; 105 } 106 107 std::string build_id_str = build_id_to_string (build_id); 108 109 /* Get build id of dwz file, if present. */ 110 gdb::optional<std::string> dwz_build_id_str; 111 const dwz_file *dwz = dwarf2_get_dwz_file (per_objfile->per_bfd); 112 const char *dwz_build_id_ptr = NULL; 113 114 if (dwz != nullptr) 115 { 116 const bfd_build_id *dwz_build_id = build_id_bfd_get (dwz->dwz_bfd.get ()); 117 118 if (dwz_build_id == nullptr) 119 { 120 if (debug_index_cache) 121 printf_unfiltered ("index cache: dwz objfile %s has no build id\n", 122 dwz->filename ()); 123 return; 124 } 125 126 dwz_build_id_str = build_id_to_string (dwz_build_id); 127 dwz_build_id_ptr = dwz_build_id_str->c_str (); 128 } 129 130 if (m_dir.empty ()) 131 { 132 warning (_("The index cache directory name is empty, skipping store.")); 133 return; 134 } 135 136 try 137 { 138 /* Try to create the containing directory. */ 139 if (!mkdir_recursive (m_dir.c_str ())) 140 { 141 warning (_("index cache: could not make cache directory: %s"), 142 safe_strerror (errno)); 143 return; 144 } 145 146 if (debug_index_cache) 147 printf_unfiltered ("index cache: writing index cache for objfile %s\n", 148 objfile_name (obj)); 149 150 /* Write the index itself to the directory, using the build id as the 151 filename. */ 152 write_psymtabs_to_index (per_objfile, m_dir.c_str (), 153 build_id_str.c_str (), dwz_build_id_ptr, 154 dw_index_kind::GDB_INDEX); 155 } 156 catch (const gdb_exception_error &except) 157 { 158 if (debug_index_cache) 159 printf_unfiltered ("index cache: couldn't store index cache for objfile " 160 "%s: %s", objfile_name (obj), except.what ()); 161 } 162 } 163 164 #if HAVE_SYS_MMAN_H 165 166 /* Hold the resources for an mmapped index file. */ 167 168 struct index_cache_resource_mmap final : public index_cache_resource 169 { 170 /* Try to mmap FILENAME. Throw an exception on failure, including if the 171 file doesn't exist. */ 172 index_cache_resource_mmap (const char *filename) 173 : mapping (mmap_file (filename)) 174 {} 175 176 scoped_mmap mapping; 177 }; 178 179 /* See dwarf-index-cache.h. */ 180 181 gdb::array_view<const gdb_byte> 182 index_cache::lookup_gdb_index (const bfd_build_id *build_id, 183 std::unique_ptr<index_cache_resource> *resource) 184 { 185 if (!enabled ()) 186 return {}; 187 188 if (m_dir.empty ()) 189 { 190 warning (_("The index cache directory name is empty, skipping cache " 191 "lookup.")); 192 return {}; 193 } 194 195 /* Compute where we would expect a gdb index file for this build id to be. */ 196 std::string filename = make_index_filename (build_id, INDEX4_SUFFIX); 197 198 try 199 { 200 if (debug_index_cache) 201 printf_unfiltered ("index cache: trying to read %s\n", 202 filename.c_str ()); 203 204 /* Try to map that file. */ 205 index_cache_resource_mmap *mmap_resource 206 = new index_cache_resource_mmap (filename.c_str ()); 207 208 /* Yay, it worked! Hand the resource to the caller. */ 209 resource->reset (mmap_resource); 210 211 return gdb::array_view<const gdb_byte> 212 ((const gdb_byte *) mmap_resource->mapping.get (), 213 mmap_resource->mapping.size ()); 214 } 215 catch (const gdb_exception_error &except) 216 { 217 if (debug_index_cache) 218 printf_unfiltered ("index cache: couldn't read %s: %s\n", 219 filename.c_str (), except.what ()); 220 } 221 222 return {}; 223 } 224 225 #else /* !HAVE_SYS_MMAN_H */ 226 227 /* See dwarf-index-cache.h. This is a no-op on unsupported systems. */ 228 229 gdb::array_view<const gdb_byte> 230 index_cache::lookup_gdb_index (const bfd_build_id *build_id, 231 std::unique_ptr<index_cache_resource> *resource) 232 { 233 return {}; 234 } 235 236 #endif 237 238 /* See dwarf-index-cache.h. */ 239 240 std::string 241 index_cache::make_index_filename (const bfd_build_id *build_id, 242 const char *suffix) const 243 { 244 std::string build_id_str = build_id_to_string (build_id); 245 246 return m_dir + SLASH_STRING + build_id_str + suffix; 247 } 248 249 /* True when we are executing "show index-cache". This is used to improve the 250 printout a little bit. */ 251 static bool in_show_index_cache_command = false; 252 253 /* "show index-cache" handler. */ 254 255 static void 256 show_index_cache_command (const char *arg, int from_tty) 257 { 258 /* Note that we are executing "show index-cache". */ 259 auto restore_flag = make_scoped_restore (&in_show_index_cache_command, true); 260 261 /* Call all "show index-cache" subcommands. */ 262 cmd_show_list (show_index_cache_prefix_list, from_tty); 263 264 printf_unfiltered ("\n"); 265 printf_unfiltered 266 (_("The index cache is currently %s.\n"), 267 global_index_cache.enabled () ? _("enabled") : _("disabled")); 268 } 269 270 /* "set index-cache on" handler. */ 271 272 static void 273 set_index_cache_on_command (const char *arg, int from_tty) 274 { 275 global_index_cache.enable (); 276 } 277 278 /* "set index-cache off" handler. */ 279 280 static void 281 set_index_cache_off_command (const char *arg, int from_tty) 282 { 283 global_index_cache.disable (); 284 } 285 286 /* "set index-cache directory" handler. */ 287 288 static void 289 set_index_cache_directory_command (const char *arg, int from_tty, 290 cmd_list_element *element) 291 { 292 /* Make sure the index cache directory is absolute and tilde-expanded. */ 293 gdb::unique_xmalloc_ptr<char> abs (gdb_abspath (index_cache_directory)); 294 xfree (index_cache_directory); 295 index_cache_directory = abs.release (); 296 global_index_cache.set_directory (index_cache_directory); 297 } 298 299 /* "show index-cache stats" handler. */ 300 301 static void 302 show_index_cache_stats_command (const char *arg, int from_tty) 303 { 304 const char *indent = ""; 305 306 /* If this command is invoked through "show index-cache", make the display a 307 bit nicer. */ 308 if (in_show_index_cache_command) 309 { 310 indent = " "; 311 printf_unfiltered ("\n"); 312 } 313 314 printf_unfiltered (_("%s Cache hits (this session): %u\n"), 315 indent, global_index_cache.n_hits ()); 316 printf_unfiltered (_("%sCache misses (this session): %u\n"), 317 indent, global_index_cache.n_misses ()); 318 } 319 320 void _initialize_index_cache (); 321 void 322 _initialize_index_cache () 323 { 324 /* Set the default index cache directory. */ 325 std::string cache_dir = get_standard_cache_dir (); 326 if (!cache_dir.empty ()) 327 { 328 index_cache_directory = xstrdup (cache_dir.c_str ()); 329 global_index_cache.set_directory (std::move (cache_dir)); 330 } 331 else 332 warning (_("Couldn't determine a path for the index cache directory.")); 333 334 /* set index-cache */ 335 add_basic_prefix_cmd ("index-cache", class_files, 336 _("Set index-cache options."), 337 &set_index_cache_prefix_list, 338 "set index-cache ", false, &setlist); 339 340 /* show index-cache */ 341 add_prefix_cmd ("index-cache", class_files, show_index_cache_command, 342 _("Show index-cache options."), &show_index_cache_prefix_list, 343 "show index-cache ", false, &showlist); 344 345 /* set index-cache on */ 346 add_cmd ("on", class_files, set_index_cache_on_command, 347 _("Enable the index cache."), &set_index_cache_prefix_list); 348 349 /* set index-cache off */ 350 add_cmd ("off", class_files, set_index_cache_off_command, 351 _("Disable the index cache."), &set_index_cache_prefix_list); 352 353 /* set index-cache directory */ 354 add_setshow_filename_cmd ("directory", class_files, &index_cache_directory, 355 _("Set the directory of the index cache."), 356 _("Show the directory of the index cache."), 357 NULL, 358 set_index_cache_directory_command, NULL, 359 &set_index_cache_prefix_list, 360 &show_index_cache_prefix_list); 361 362 /* show index-cache stats */ 363 add_cmd ("stats", class_files, show_index_cache_stats_command, 364 _("Show some stats about the index cache."), 365 &show_index_cache_prefix_list); 366 367 /* set debug index-cache */ 368 add_setshow_boolean_cmd ("index-cache", class_maintenance, 369 &debug_index_cache, 370 _("Set display of index-cache debug messages."), 371 _("Show display of index-cache debug messages."), 372 _("\ 373 When non-zero, debugging output for the index cache is displayed."), 374 NULL, NULL, 375 &setdebuglist, &showdebuglist); 376 } 377