]> Git Repo - binutils.git/blob - gdb/dwarf2/cooked-index.c
Automatic date update in version.in
[binutils.git] / gdb / dwarf2 / cooked-index.c
1 /* DIE indexing 
2
3    Copyright (C) 2022 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/cooked-index.h"
22 #include "dwarf2/read.h"
23 #include "cp-support.h"
24 #include "c-lang.h"
25 #include "ada-lang.h"
26 #include "split-name.h"
27 #include <algorithm>
28
29 /* Hash function for cooked_index_entry.  */
30
31 static hashval_t
32 hash_entry (const void *e)
33 {
34   const cooked_index_entry *entry = (const cooked_index_entry *) e;
35   return dwarf5_djb_hash (entry->canonical);
36 }
37
38 /* Equality function for cooked_index_entry.  */
39
40 static int
41 eq_entry (const void *a, const void *b)
42 {
43   const cooked_index_entry *ae = (const cooked_index_entry *) a;
44   const gdb::string_view *sv = (const gdb::string_view *) b;
45   return (strlen (ae->canonical) == sv->length ()
46           && strncasecmp (ae->canonical, sv->data (), sv->length ()) == 0);
47 }
48
49 /* See cooked-index.h.  */
50
51 const char *
52 cooked_index_entry::full_name (struct obstack *storage) const
53 {
54   if ((flags & IS_LINKAGE) != 0 || parent_entry == nullptr)
55     return canonical;
56
57   const char *sep = nullptr;
58   switch (per_cu->lang ())
59     {
60     case language_cplus:
61     case language_rust:
62       sep = "::";
63       break;
64
65     case language_go:
66     case language_d:
67     case language_ada:
68       sep = ".";
69       break;
70
71     default:
72       return canonical;
73     }
74
75   parent_entry->write_scope (storage, sep);
76   obstack_grow0 (storage, canonical, strlen (canonical));
77   return (const char *) obstack_finish (storage);
78 }
79
80 /* See cooked-index.h.  */
81
82 void
83 cooked_index_entry::write_scope (struct obstack *storage,
84                                  const char *sep) const
85 {
86   if (parent_entry != nullptr)
87     parent_entry->write_scope (storage, sep);
88   obstack_grow (storage, canonical, strlen (canonical));
89   obstack_grow (storage, sep, strlen (sep));
90 }
91
92 /* See cooked-index.h.  */
93
94 const cooked_index_entry *
95 cooked_index::add (sect_offset die_offset, enum dwarf_tag tag,
96                    cooked_index_flag flags, const char *name,
97                    const cooked_index_entry *parent_entry,
98                    dwarf2_per_cu_data *per_cu)
99 {
100   cooked_index_entry *result = create (die_offset, tag, flags, name,
101                                        parent_entry, per_cu);
102   m_entries.push_back (result);
103
104   /* An explicitly-tagged main program should always override the
105      implicit "main" discovery.  */
106   if ((flags & IS_MAIN) != 0)
107     m_main = result;
108   else if (per_cu->lang () != language_ada
109            && m_main == nullptr
110            && strcmp (name, "main") == 0)
111     m_main = result;
112
113   return result;
114 }
115
116 /* See cooked-index.h.  */
117
118 void
119 cooked_index::finalize ()
120 {
121   m_future = gdb::thread_pool::g_thread_pool->post_task ([this] ()
122     {
123       do_finalize ();
124     });
125 }
126
127 /* See cooked-index.h.  */
128
129 gdb::unique_xmalloc_ptr<char>
130 cooked_index::handle_gnat_encoded_entry (cooked_index_entry *entry,
131                                          htab_t gnat_entries)
132 {
133   std::string canonical = ada_decode (entry->name, false, false);
134   if (canonical.empty ())
135     return {};
136   std::vector<gdb::string_view> names = split_name (canonical.c_str (),
137                                                     split_style::DOT);
138   gdb::string_view tail = names.back ();
139   names.pop_back ();
140
141   const cooked_index_entry *parent = nullptr;
142   for (const auto &name : names)
143     {
144       uint32_t hashval = dwarf5_djb_hash (name);
145       void **slot = htab_find_slot_with_hash (gnat_entries, &name,
146                                               hashval, INSERT);
147       /* CUs are processed in order, so we only need to check the most
148          recent entry.  */
149       cooked_index_entry *last = (cooked_index_entry *) *slot;
150       if (last == nullptr || last->per_cu != entry->per_cu)
151         {
152           gdb::unique_xmalloc_ptr<char> new_name
153             = make_unique_xstrndup (name.data (), name.length ());
154           last = create (entry->die_offset, DW_TAG_namespace,
155                          0, new_name.get (), parent,
156                          entry->per_cu);
157           last->canonical = last->name;
158           m_names.push_back (std::move (new_name));
159           *slot = last;
160         }
161
162       parent = last;
163     }
164
165   entry->parent_entry = parent;
166   return make_unique_xstrndup (tail.data (), tail.length ());
167 }
168
169 /* See cooked-index.h.  */
170
171 void
172 cooked_index::do_finalize ()
173 {
174   auto hash_name_ptr = [] (const void *p)
175     {
176       const cooked_index_entry *entry = (const cooked_index_entry *) p;
177       return htab_hash_pointer (entry->name);
178     };
179
180   auto eq_name_ptr = [] (const void *a, const void *b) -> int
181     {
182       const cooked_index_entry *ea = (const cooked_index_entry *) a;
183       const cooked_index_entry *eb = (const cooked_index_entry *) b;
184       return ea->name == eb->name;
185     };
186
187   /* We can use pointer equality here because names come from
188      .debug_str, which will normally be unique-ified by the linker.
189      Also, duplicates are relatively harmless -- they just mean a bit
190      of extra memory is used.  */
191   htab_up seen_names (htab_create_alloc (10, hash_name_ptr, eq_name_ptr,
192                                          nullptr, xcalloc, xfree));
193
194   htab_up gnat_entries (htab_create_alloc (10, hash_entry, eq_entry,
195                                            nullptr, xcalloc, xfree));
196
197   for (cooked_index_entry *entry : m_entries)
198     {
199       gdb_assert (entry->canonical == nullptr);
200       if ((entry->flags & IS_LINKAGE) != 0)
201         entry->canonical = entry->name;
202       else if (entry->per_cu->lang () == language_ada)
203         {
204           gdb::unique_xmalloc_ptr<char> canon_name
205             = handle_gnat_encoded_entry (entry, gnat_entries.get ());
206           if (canon_name == nullptr)
207             entry->canonical = entry->name;
208           else
209             {
210               entry->canonical = canon_name.get ();
211               m_names.push_back (std::move (canon_name));
212             }
213         }
214       else if (entry->per_cu->lang () == language_cplus
215                || entry->per_cu->lang () == language_c)
216         {
217           void **slot = htab_find_slot (seen_names.get (), entry,
218                                         INSERT);
219           if (*slot == nullptr)
220             {
221               gdb::unique_xmalloc_ptr<char> canon_name
222                 = (entry->per_cu->lang () == language_cplus
223                    ? cp_canonicalize_string (entry->name)
224                    : c_canonicalize_name (entry->name));
225               if (canon_name == nullptr)
226                 entry->canonical = entry->name;
227               else
228                 {
229                   entry->canonical = canon_name.get ();
230                   m_names.push_back (std::move (canon_name));
231                 }
232             }
233           else
234             {
235               const cooked_index_entry *other
236                 = (const cooked_index_entry *) *slot;
237               entry->canonical = other->canonical;
238             }
239         }
240       else
241         entry->canonical = entry->name;
242     }
243
244   m_names.shrink_to_fit ();
245   m_entries.shrink_to_fit ();
246   std::sort (m_entries.begin (), m_entries.end (),
247              [] (const cooked_index_entry *a, const cooked_index_entry *b)
248              {
249                return *a < *b;
250              });
251 }
252
253 /* See cooked-index.h.  */
254
255 cooked_index::range
256 cooked_index::find (gdb::string_view name, bool completing)
257 {
258   wait ();
259
260   auto lower = std::lower_bound (m_entries.begin (), m_entries.end (),
261                                  name,
262                                  [=] (const cooked_index_entry *entry,
263                                       const gdb::string_view &n)
264   {
265     int cmp = strncasecmp (entry->canonical, n.data (), n.length ());
266     if (cmp != 0 || completing)
267       return cmp < 0;
268     return strlen (entry->canonical) < n.length ();
269   });
270
271   auto upper = std::upper_bound (m_entries.begin (), m_entries.end (),
272                                  name,
273                                  [=] (const gdb::string_view &n,
274                                       const cooked_index_entry *entry)
275   {
276     int cmp = strncasecmp (n.data (), entry->canonical, n.length ());
277     if (cmp != 0 || completing)
278       return cmp < 0;
279     return n.length () < strlen (entry->canonical);
280   });
281
282   return range (lower, upper);
283 }
284
285 cooked_index_vector::cooked_index_vector (vec_type &&vec)
286   : m_vector (std::move (vec))
287 {
288   for (auto &idx : m_vector)
289     idx->finalize ();
290 }
291
292 /* See cooked-index.h.  */
293
294 dwarf2_per_cu_data *
295 cooked_index_vector::lookup (CORE_ADDR addr)
296 {
297   for (const auto &index : m_vector)
298     {
299       dwarf2_per_cu_data *result = index->lookup (addr);
300       if (result != nullptr)
301         return result;
302     }
303   return nullptr;
304 }
305
306 /* See cooked-index.h.  */
307
308 std::vector<addrmap *>
309 cooked_index_vector::get_addrmaps ()
310 {
311   std::vector<addrmap *> result;
312   for (const auto &index : m_vector)
313     result.push_back (index->m_addrmap);
314   return result;
315 }
316
317 /* See cooked-index.h.  */
318
319 cooked_index_vector::range
320 cooked_index_vector::find (gdb::string_view name, bool completing)
321 {
322   std::vector<cooked_index::range> result_range;
323   result_range.reserve (m_vector.size ());
324   for (auto &entry : m_vector)
325     result_range.push_back (entry->find (name, completing));
326   return range (std::move (result_range));
327 }
328
329 /* See cooked-index.h.  */
330
331 const cooked_index_entry *
332 cooked_index_vector::get_main () const
333 {
334   const cooked_index_entry *result = nullptr;
335
336   for (const auto &index : m_vector)
337     {
338       const cooked_index_entry *entry = index->get_main ();
339       if (result == nullptr
340           || ((result->flags & IS_MAIN) == 0
341               && entry != nullptr
342               && (entry->flags & IS_MAIN) != 0))
343         result = entry;
344     }
345
346   return result;
347 }
This page took 0.044385 seconds and 4 git commands to generate.