AArch64: Add MOVPRFX tests and update testsuite
[deliverable/binutils-gdb.git] / gdb / dwarf-index-cache.c
1 /* Caching of GDB/DWARF index files.
2
3 Copyright (C) 1994-2018 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 "dwarf-index-cache.h"
22
23 #include "build-id.h"
24 #include "cli/cli-cmds.h"
25 #include "command.h"
26 #include "common/scoped_mmap.h"
27 #include "common/pathstuff.h"
28 #include "dwarf-index-write.h"
29 #include "dwarf2read.h"
30 #include "objfiles.h"
31 #include "selftest.h"
32 #include <string>
33 #include <stdlib.h>
34
35 /* When set to 1, show debug messages about the index cache. */
36 static int debug_index_cache = 0;
37
38 /* The index cache directory, used for "set/show index-cache directory". */
39 static char *index_cache_directory = NULL;
40
41 /* See dwarf-index.cache.h. */
42 index_cache global_index_cache;
43
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;
47
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. */
51
52 static void
53 mkdir_recursive (const char *dir)
54 {
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;
59
60 while (1)
61 {
62 /* Find the beginning of the next component. */
63 while (*component_start == '/')
64 component_start++;
65
66 /* Are we done? */
67 if (*component_start == '\0')
68 return;
69
70 /* Find the slash or null-terminator after this component. */
71 component_end = component_start;
72 while (*component_end != '/' && *component_end != '\0')
73 component_end++;
74
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';
79
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)
86 if (errno != EEXIST)
87 return;
88
89 /* Restore the overwritten char. */
90 *component_end = saved_char;
91 component_start = component_end;
92 }
93 }
94
95 /* Default destructor of index_cache_resource. */
96 index_cache_resource::~index_cache_resource () = default;
97
98 /* See dwarf-index-cache.h. */
99
100 void
101 index_cache::set_directory (std::string dir)
102 {
103 gdb_assert (!dir.empty ());
104
105 m_dir = std::move (dir);
106
107 if (debug_index_cache)
108 printf_unfiltered ("index cache: now using directory %s\n", m_dir.c_str ());
109 }
110
111 /* See dwarf-index-cache.h. */
112
113 void
114 index_cache::enable ()
115 {
116 if (debug_index_cache)
117 printf_unfiltered ("index cache: enabling (%s)\n", m_dir.c_str ());
118
119 m_enabled = true;
120 }
121
122 /* See dwarf-index-cache.h. */
123
124 void
125 index_cache::disable ()
126 {
127 if (debug_index_cache)
128 printf_unfiltered ("index cache: disabling\n");
129
130 m_enabled = false;
131 }
132
133 /* See dwarf-index-cache.h. */
134
135 void
136 index_cache::store (struct dwarf2_per_objfile *dwarf2_per_objfile)
137 {
138 objfile *obj = dwarf2_per_objfile->objfile;
139
140 if (!enabled ())
141 return;
142
143 const bfd_build_id *build_id = build_id_bfd_get (obj->obfd);
144 if (build_id == nullptr)
145 {
146 if (debug_index_cache)
147 printf_unfiltered ("index cache: objfile %s has no build id\n",
148 objfile_name (obj));
149 return;
150 }
151
152 if (m_dir.empty ())
153 {
154 warning (_("The index cache directory name is empty, skipping store."));
155 return;
156 }
157
158 std::string build_id_str = build_id_to_string (build_id);
159
160 TRY
161 {
162 /* Try to create the containing directory. */
163 mkdir_recursive (m_dir.c_str ());
164
165 if (debug_index_cache)
166 printf_unfiltered ("index cache: writing index cache for objfile %s\n",
167 objfile_name (obj));
168
169 /* Write the index itself to the directory, using the build id as the
170 filename. */
171 write_psymtabs_to_index (dwarf2_per_objfile, m_dir.c_str (),
172 build_id_str.c_str (), dw_index_kind::GDB_INDEX);
173 }
174 CATCH (except, RETURN_MASK_ERROR)
175 {
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);
179 }
180 END_CATCH
181 }
182
183 #if HAVE_SYS_MMAN_H
184
185 /* Hold the resources for an mmapped index file. */
186
187 struct index_cache_resource_mmap final : public index_cache_resource
188 {
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))
193 {}
194
195 scoped_mmap mapping;
196 };
197
198 /* See dwarf-index-cache.h. */
199
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)
203 {
204 if (!enabled ())
205 return {};
206
207 if (m_dir.empty ())
208 {
209 warning (_("The index cache directory name is empty, skipping cache "
210 "lookup."));
211 return {};
212 }
213
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);
216
217 TRY
218 {
219 if (debug_index_cache)
220 printf_unfiltered ("index cache: trying to read %s\n",
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 (except, RETURN_MASK_ERROR)
235 {
236 if (debug_index_cache)
237 printf_unfiltered ("index cache: couldn't read %s: %s\n",
238 filename.c_str (), except.message);
239 }
240 END_CATCH
241
242 return {};
243 }
244
245 #else /* !HAVE_SYS_MMAN_H */
246
247 /* See dwarf-index-cache.h. This is a no-op on unsupported systems. */
248
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)
252 {
253 return {};
254 }
255
256 #endif
257
258 /* See dwarf-index-cache.h. */
259
260 std::string
261 index_cache::make_index_filename (const bfd_build_id *build_id,
262 const char *suffix) const
263 {
264 std::string build_id_str = build_id_to_string (build_id);
265
266 return m_dir + SLASH_STRING + build_id_str + suffix;
267 }
268
269 /* "set index-cache" handler. */
270
271 static void
272 set_index_cache_command (const char *arg, int from_tty)
273 {
274 printf_unfiltered (_("\
275 Missing arguments. See \"help set index-cache\" for help.\n"));
276 }
277
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;
281
282 /* "show index-cache" handler. */
283
284 static void
285 show_index_cache_command (const char *arg, int from_tty)
286 {
287 /* Note that we are executing "show index-cache". */
288 auto restore_flag = make_scoped_restore (&in_show_index_cache_command, true);
289
290 /* Call all "show index-cache" subcommands. */
291 cmd_show_list (show_index_cache_prefix_list, from_tty, "");
292
293 printf_unfiltered ("\n");
294 printf_unfiltered
295 (_("The index cache is currently %s.\n"),
296 global_index_cache.enabled () ? _("enabled") : _("disabled"));
297 }
298
299 /* "set index-cache on" handler. */
300
301 static void
302 set_index_cache_on_command (const char *arg, int from_tty)
303 {
304 global_index_cache.enable ();
305 }
306
307 /* "set index-cache off" handler. */
308
309 static void
310 set_index_cache_off_command (const char *arg, int from_tty)
311 {
312 global_index_cache.disable ();
313 }
314
315 /* "set index-cache directory" handler. */
316
317 static void
318 set_index_cache_directory_command (const char *arg, int from_tty,
319 cmd_list_element *element)
320 {
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);
326 }
327
328 /* "show index-cache stats" handler. */
329
330 static void
331 show_index_cache_stats_command (const char *arg, int from_tty)
332 {
333 const char *indent = "";
334
335 /* If this command is invoked through "show index-cache", make the display a
336 bit nicer. */
337 if (in_show_index_cache_command)
338 {
339 indent = " ";
340 printf_unfiltered ("\n");
341 }
342
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 ());
347 }
348
349 #if GDB_SELF_TEST && defined (HAVE_MKDTEMP)
350 namespace selftests
351 {
352
353 /* Try to create DIR using mkdir_recursive and make sure it exists. */
354
355 static bool
356 create_dir_and_check (const char *dir)
357 {
358 mkdir_recursive (dir);
359
360 struct stat st;
361 if (stat (dir, &st) != 0)
362 perror_with_name (("stat"));
363
364 return (st.st_mode & S_IFDIR) != 0;
365 }
366
367 /* Test mkdir_recursive. */
368
369 static void
370 test_mkdir_recursive ()
371 {
372 char base[] = "/tmp/gdb-selftests-XXXXXX";
373
374 if (mkdtemp (base) == NULL)
375 perror_with_name (("mkdtemp"));
376
377 /* Try not to leave leftover directories. */
378 struct cleanup_dirs {
379 cleanup_dirs (const char *base)
380 : m_base (base)
381 {}
382
383 ~cleanup_dirs () {
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 ());
389 rmdir (m_base);
390 }
391
392 private:
393 const char *m_base;
394 } cleanup_dirs (base);
395
396 std::string dir = string_printf ("%s/a/b", base);
397 SELF_CHECK (create_dir_and_check (dir.c_str ()));
398
399 dir = string_printf ("%s/a/b/c//d/e/", base);
400 SELF_CHECK (create_dir_and_check (dir.c_str ()));
401 }
402 }
403 #endif /* GDB_SELF_TEST && defined (HAVE_MKDTEMP) */
404
405 void
406 _initialize_index_cache ()
407 {
408 /* Set the default index cache directory. */
409 std::string cache_dir = get_standard_cache_dir ();
410 if (!cache_dir.empty ())
411 {
412 index_cache_directory = xstrdup (cache_dir.c_str ());
413 global_index_cache.set_directory (std::move (cache_dir));
414 }
415 else
416 warning (_("Couldn't determine a path for the index cache directory."));
417
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);
422
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);
427
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);
431
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);
435
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."),
440 NULL,
441 set_index_cache_directory_command, NULL,
442 &set_index_cache_prefix_list,
443 &show_index_cache_prefix_list);
444
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);
449
450 /* set debug index-cache */
451 add_setshow_boolean_cmd ("index-cache", class_maintenance,
452 &debug_index_cache,
453 _("Set display of index-cache debug messages."),
454 _("Show display of index-cache debug messages."),
455 _("\
456 When non-zero, debugging output for the index cache is displayed."),
457 NULL, NULL,
458 &setdebuglist, &showdebuglist);
459
460 #if GDB_SELF_TEST && defined (HAVE_MKDTEMP)
461 selftests::register_test ("mkdir_recursive", selftests::test_mkdir_recursive);
462 #endif
463 }
This page took 0.068083 seconds and 4 git commands to generate.