AArch64: Add SVE constraints verifier.
[external/binutils.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 }