]>
Commit | Line | Data |
---|---|---|
51f5a4b8 TT |
1 | /* DIE indexing |
2 | ||
1d506c26 | 3 | Copyright (C) 2022-2024 Free Software Foundation, Inc. |
51f5a4b8 TT |
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 | ||
51f5a4b8 TT |
20 | #include "dwarf2/cooked-index.h" |
21 | #include "dwarf2/read.h" | |
7d82b08e | 22 | #include "dwarf2/stringify.h" |
52e5e48e | 23 | #include "dwarf2/index-cache.h" |
51f5a4b8 | 24 | #include "cp-support.h" |
55fc1623 | 25 | #include "c-lang.h" |
51f5a4b8 | 26 | #include "ada-lang.h" |
e5dc0d5d | 27 | #include "event-top.h" |
51f5a4b8 | 28 | #include "split-name.h" |
52e5e48e TT |
29 | #include "observable.h" |
30 | #include "run-on-main-thread.h" | |
51f5a4b8 | 31 | #include <algorithm> |
e0f4b3ec | 32 | #include "gdbsupport/gdb-safe-ctype.h" |
ac37b79c | 33 | #include "gdbsupport/selftest.h" |
307733cc | 34 | #include <chrono> |
52e5e48e | 35 | #include <unordered_set> |
f0c3dcc1 | 36 | #include "cli/cli-cmds.h" |
52e5e48e TT |
37 | |
38 | /* We don't want gdb to exit while it is in the process of writing to | |
39 | the index cache. So, all live cooked index vectors are stored | |
40 | here, and then these are all waited for before exit proceeds. */ | |
41 | static std::unordered_set<cooked_index *> active_vectors; | |
ac37b79c TT |
42 | |
43 | /* See cooked-index.h. */ | |
44 | ||
7d82b08e SM |
45 | std::string |
46 | to_string (cooked_index_flag flags) | |
47 | { | |
48 | static constexpr cooked_index_flag::string_mapping mapping[] = { | |
49 | MAP_ENUM_FLAG (IS_MAIN), | |
50 | MAP_ENUM_FLAG (IS_STATIC), | |
7d82b08e SM |
51 | MAP_ENUM_FLAG (IS_LINKAGE), |
52 | MAP_ENUM_FLAG (IS_TYPE_DECLARATION), | |
42bd6b5f | 53 | MAP_ENUM_FLAG (IS_PARENT_DEFERRED), |
7d82b08e SM |
54 | }; |
55 | ||
56 | return flags.to_string (mapping); | |
57 | } | |
58 | ||
59 | /* See cooked-index.h. */ | |
60 | ||
47fe57c9 TT |
61 | bool |
62 | language_requires_canonicalization (enum language lang) | |
63 | { | |
64 | return (lang == language_ada | |
65 | || lang == language_c | |
66 | || lang == language_cplus); | |
67 | } | |
68 | ||
33c6eaae TT |
69 | /* Return true if a plain "main" could be the main program for this |
70 | language. Languages that are known to use some other mechanism are | |
71 | excluded here. */ | |
72 | ||
73 | static bool | |
74 | language_may_use_plain_main (enum language lang) | |
75 | { | |
76 | /* No need to handle "unknown" here. */ | |
77 | return (lang == language_c | |
78 | || lang == language_objc | |
79 | || lang == language_cplus | |
80 | || lang == language_m2 | |
81 | || lang == language_asm | |
82 | || lang == language_opencl | |
83 | || lang == language_minimal); | |
84 | } | |
85 | ||
47fe57c9 TT |
86 | /* See cooked-index.h. */ |
87 | ||
c121e82c | 88 | int |
ac37b79c | 89 | cooked_index_entry::compare (const char *stra, const char *strb, |
c121e82c | 90 | comparison_mode mode) |
ac37b79c | 91 | { |
c121e82c TT |
92 | auto munge = [] (char c) -> unsigned char |
93 | { | |
94 | /* We want to sort '<' before any other printable character. | |
95 | So, rewrite '<' to something just before ' '. */ | |
96 | if (c == '<') | |
97 | return '\x1f'; | |
98 | return TOLOWER ((unsigned char) c); | |
99 | }; | |
ac37b79c TT |
100 | |
101 | while (*stra != '\0' | |
102 | && *strb != '\0' | |
c121e82c | 103 | && (munge (*stra) == munge (*strb))) |
ac37b79c | 104 | { |
ac37b79c TT |
105 | ++stra; |
106 | ++strb; | |
107 | } | |
108 | ||
c121e82c TT |
109 | unsigned char c1 = munge (*stra); |
110 | unsigned char c2 = munge (*strb); | |
ac37b79c | 111 | |
c121e82c TT |
112 | if (c1 == c2) |
113 | return 0; | |
114 | ||
115 | /* When completing, if STRB ends earlier than STRA, consider them as | |
116 | equal. When comparing, if STRB ends earlier and STRA ends with | |
117 | '<', consider them as equal. */ | |
118 | if (mode == COMPLETE || (mode == MATCH && c1 == munge ('<'))) | |
ac37b79c | 119 | { |
c121e82c TT |
120 | if (c2 == '\0') |
121 | return 0; | |
ac37b79c TT |
122 | } |
123 | ||
c121e82c | 124 | return c1 < c2 ? -1 : 1; |
ac37b79c TT |
125 | } |
126 | ||
127 | #if GDB_SELF_TEST | |
128 | ||
129 | namespace { | |
130 | ||
131 | void | |
132 | test_compare () | |
133 | { | |
c121e82c TT |
134 | /* Convenience aliases. */ |
135 | const auto mode_compare = cooked_index_entry::MATCH; | |
136 | const auto mode_sort = cooked_index_entry::SORT; | |
137 | const auto mode_complete = cooked_index_entry::COMPLETE; | |
138 | ||
139 | SELF_CHECK (cooked_index_entry::compare ("abcd", "abcd", | |
140 | mode_compare) == 0); | |
141 | SELF_CHECK (cooked_index_entry::compare ("abcd", "abcd", | |
142 | mode_complete) == 0); | |
143 | ||
144 | SELF_CHECK (cooked_index_entry::compare ("abcd", "ABCDE", | |
145 | mode_compare) < 0); | |
146 | SELF_CHECK (cooked_index_entry::compare ("ABCDE", "abcd", | |
147 | mode_compare) > 0); | |
148 | SELF_CHECK (cooked_index_entry::compare ("abcd", "ABCDE", | |
149 | mode_complete) < 0); | |
150 | SELF_CHECK (cooked_index_entry::compare ("ABCDE", "abcd", | |
151 | mode_complete) == 0); | |
152 | ||
153 | SELF_CHECK (cooked_index_entry::compare ("name", "name<>", | |
154 | mode_compare) < 0); | |
155 | SELF_CHECK (cooked_index_entry::compare ("name<>", "name", | |
156 | mode_compare) == 0); | |
157 | SELF_CHECK (cooked_index_entry::compare ("name", "name<>", | |
158 | mode_complete) < 0); | |
159 | SELF_CHECK (cooked_index_entry::compare ("name<>", "name", | |
160 | mode_complete) == 0); | |
161 | ||
162 | SELF_CHECK (cooked_index_entry::compare ("name<arg>", "name<arg>", | |
163 | mode_compare) == 0); | |
164 | SELF_CHECK (cooked_index_entry::compare ("name<arg>", "name<ag>", | |
165 | mode_compare) > 0); | |
166 | SELF_CHECK (cooked_index_entry::compare ("name<arg>", "name<arg>", | |
167 | mode_complete) == 0); | |
168 | SELF_CHECK (cooked_index_entry::compare ("name<arg>", "name<ag>", | |
169 | mode_complete) > 0); | |
170 | ||
171 | SELF_CHECK (cooked_index_entry::compare ("name<arg<more>>", | |
172 | "name<arg<more>>", | |
173 | mode_compare) == 0); | |
174 | ||
175 | SELF_CHECK (cooked_index_entry::compare ("name", "name<arg<more>>", | |
176 | mode_compare) < 0); | |
177 | SELF_CHECK (cooked_index_entry::compare ("name<arg<more>>", "name", | |
178 | mode_compare) == 0); | |
179 | SELF_CHECK (cooked_index_entry::compare ("name<arg<more>>", "name<arg<", | |
180 | mode_compare) > 0); | |
181 | SELF_CHECK (cooked_index_entry::compare ("name<arg<more>>", "name<arg<", | |
182 | mode_complete) == 0); | |
183 | ||
184 | SELF_CHECK (cooked_index_entry::compare ("", "abcd", mode_compare) < 0); | |
185 | SELF_CHECK (cooked_index_entry::compare ("", "abcd", mode_complete) < 0); | |
186 | SELF_CHECK (cooked_index_entry::compare ("abcd", "", mode_compare) > 0); | |
187 | SELF_CHECK (cooked_index_entry::compare ("abcd", "", mode_complete) == 0); | |
188 | ||
189 | SELF_CHECK (cooked_index_entry::compare ("func", "func<type>", | |
190 | mode_sort) < 0); | |
191 | SELF_CHECK (cooked_index_entry::compare ("func<type>", "func1", | |
192 | mode_sort) < 0); | |
ac37b79c TT |
193 | } |
194 | ||
195 | } /* anonymous namespace */ | |
196 | ||
197 | #endif /* GDB_SELF_TEST */ | |
51f5a4b8 | 198 | |
51f5a4b8 TT |
199 | /* See cooked-index.h. */ |
200 | ||
c92d4de1 TT |
201 | bool |
202 | cooked_index_entry::matches (domain_search_flags kind) const | |
203 | { | |
204 | /* Just reject type declarations. */ | |
205 | if ((flags & IS_TYPE_DECLARATION) != 0) | |
206 | return false; | |
207 | ||
974b36c2 | 208 | return tag_matches_domain (tag, kind, lang); |
c92d4de1 TT |
209 | } |
210 | ||
211 | /* See cooked-index.h. */ | |
212 | ||
51f5a4b8 | 213 | const char * |
47fe57c9 | 214 | cooked_index_entry::full_name (struct obstack *storage, bool for_main) const |
51f5a4b8 | 215 | { |
47fe57c9 TT |
216 | const char *local_name = for_main ? name : canonical; |
217 | ||
850fce8b | 218 | if ((flags & IS_LINKAGE) != 0 || get_parent () == nullptr) |
47fe57c9 | 219 | return local_name; |
51f5a4b8 TT |
220 | |
221 | const char *sep = nullptr; | |
5902fa8a | 222 | switch (lang) |
51f5a4b8 TT |
223 | { |
224 | case language_cplus: | |
225 | case language_rust: | |
226 | sep = "::"; | |
227 | break; | |
228 | ||
229 | case language_go: | |
230 | case language_d: | |
231 | case language_ada: | |
232 | sep = "."; | |
233 | break; | |
51f5a4b8 | 234 | |
72b580b8 | 235 | default: |
47fe57c9 | 236 | return local_name; |
72b580b8 | 237 | } |
51f5a4b8 | 238 | |
850fce8b | 239 | get_parent ()->write_scope (storage, sep, for_main); |
47fe57c9 | 240 | obstack_grow0 (storage, local_name, strlen (local_name)); |
51f5a4b8 TT |
241 | return (const char *) obstack_finish (storage); |
242 | } | |
243 | ||
244 | /* See cooked-index.h. */ | |
245 | ||
246 | void | |
247 | cooked_index_entry::write_scope (struct obstack *storage, | |
47fe57c9 TT |
248 | const char *sep, |
249 | bool for_main) const | |
51f5a4b8 | 250 | { |
850fce8b TV |
251 | if (get_parent () != nullptr) |
252 | get_parent ()->write_scope (storage, sep, for_main); | |
47fe57c9 TT |
253 | const char *local_name = for_main ? name : canonical; |
254 | obstack_grow (storage, local_name, strlen (local_name)); | |
51f5a4b8 TT |
255 | obstack_grow (storage, sep, strlen (sep)); |
256 | } | |
257 | ||
258 | /* See cooked-index.h. */ | |
259 | ||
920bcec0 | 260 | cooked_index_entry * |
a8dc6718 | 261 | cooked_index_shard::add (sect_offset die_offset, enum dwarf_tag tag, |
5902fa8a TT |
262 | cooked_index_flag flags, enum language lang, |
263 | const char *name, | |
42bd6b5f | 264 | cooked_index_entry_ref parent_entry, |
a8dc6718 | 265 | dwarf2_per_cu_data *per_cu) |
51f5a4b8 | 266 | { |
5902fa8a | 267 | cooked_index_entry *result = create (die_offset, tag, flags, lang, name, |
51f5a4b8 TT |
268 | parent_entry, per_cu); |
269 | m_entries.push_back (result); | |
270 | ||
271 | /* An explicitly-tagged main program should always override the | |
272 | implicit "main" discovery. */ | |
273 | if ((flags & IS_MAIN) != 0) | |
274 | m_main = result; | |
42bd6b5f TV |
275 | else if ((flags & IS_PARENT_DEFERRED) == 0 |
276 | && parent_entry.resolved == nullptr | |
33c6eaae | 277 | && m_main == nullptr |
5902fa8a | 278 | && language_may_use_plain_main (lang) |
33c6eaae TT |
279 | && strcmp (name, "main") == 0) |
280 | m_main = result; | |
51f5a4b8 TT |
281 | |
282 | return result; | |
283 | } | |
284 | ||
46114cb7 TT |
285 | /* See cooked-index.h. */ |
286 | ||
51f5a4b8 | 287 | gdb::unique_xmalloc_ptr<char> |
a8dc6718 SM |
288 | cooked_index_shard::handle_gnat_encoded_entry (cooked_index_entry *entry, |
289 | htab_t gnat_entries) | |
51f5a4b8 | 290 | { |
957ce537 TT |
291 | /* We decode Ada names in a particular way: operators and wide |
292 | characters are left as-is. This is done to make name matching a | |
293 | bit simpler; and for wide characters, it means the choice of Ada | |
294 | source charset does not affect the indexer directly. */ | |
295 | std::string canonical = ada_decode (entry->name, false, false, false); | |
51f5a4b8 TT |
296 | if (canonical.empty ()) |
297 | return {}; | |
8082468f | 298 | std::vector<std::string_view> names = split_name (canonical.c_str (), |
fe26aa95 | 299 | split_style::DOT_STYLE); |
8082468f | 300 | std::string_view tail = names.back (); |
51f5a4b8 TT |
301 | names.pop_back (); |
302 | ||
303 | const cooked_index_entry *parent = nullptr; | |
304 | for (const auto &name : names) | |
305 | { | |
306 | uint32_t hashval = dwarf5_djb_hash (name); | |
307 | void **slot = htab_find_slot_with_hash (gnat_entries, &name, | |
308 | hashval, INSERT); | |
309 | /* CUs are processed in order, so we only need to check the most | |
310 | recent entry. */ | |
311 | cooked_index_entry *last = (cooked_index_entry *) *slot; | |
312 | if (last == nullptr || last->per_cu != entry->per_cu) | |
313 | { | |
314 | gdb::unique_xmalloc_ptr<char> new_name | |
315 | = make_unique_xstrndup (name.data (), name.length ()); | |
20a26f4e | 316 | last = create (entry->die_offset, DW_TAG_namespace, |
5902fa8a | 317 | 0, language_ada, new_name.get (), parent, |
20a26f4e | 318 | entry->per_cu); |
51f5a4b8 TT |
319 | last->canonical = last->name; |
320 | m_names.push_back (std::move (new_name)); | |
321 | *slot = last; | |
322 | } | |
323 | ||
324 | parent = last; | |
325 | } | |
326 | ||
850fce8b | 327 | entry->set_parent (parent); |
51f5a4b8 TT |
328 | return make_unique_xstrndup (tail.data (), tail.length ()); |
329 | } | |
330 | ||
331 | /* See cooked-index.h. */ | |
332 | ||
333 | void | |
4320a9c9 | 334 | cooked_index_shard::finalize (const parent_map_map *parent_maps) |
51f5a4b8 TT |
335 | { |
336 | auto hash_name_ptr = [] (const void *p) | |
337 | { | |
338 | const cooked_index_entry *entry = (const cooked_index_entry *) p; | |
339 | return htab_hash_pointer (entry->name); | |
340 | }; | |
341 | ||
342 | auto eq_name_ptr = [] (const void *a, const void *b) -> int | |
343 | { | |
344 | const cooked_index_entry *ea = (const cooked_index_entry *) a; | |
345 | const cooked_index_entry *eb = (const cooked_index_entry *) b; | |
346 | return ea->name == eb->name; | |
347 | }; | |
348 | ||
349 | /* We can use pointer equality here because names come from | |
350 | .debug_str, which will normally be unique-ified by the linker. | |
351 | Also, duplicates are relatively harmless -- they just mean a bit | |
352 | of extra memory is used. */ | |
353 | htab_up seen_names (htab_create_alloc (10, hash_name_ptr, eq_name_ptr, | |
354 | nullptr, xcalloc, xfree)); | |
355 | ||
5a89072f TT |
356 | auto hash_entry = [] (const void *e) |
357 | { | |
358 | const cooked_index_entry *entry = (const cooked_index_entry *) e; | |
359 | return dwarf5_djb_hash (entry->canonical); | |
360 | }; | |
361 | ||
362 | auto eq_entry = [] (const void *a, const void *b) -> int | |
363 | { | |
364 | const cooked_index_entry *ae = (const cooked_index_entry *) a; | |
8082468f | 365 | const std::string_view *sv = (const std::string_view *) b; |
5a89072f TT |
366 | return (strlen (ae->canonical) == sv->length () |
367 | && strncasecmp (ae->canonical, sv->data (), sv->length ()) == 0); | |
368 | }; | |
369 | ||
20a26f4e TT |
370 | htab_up gnat_entries (htab_create_alloc (10, hash_entry, eq_entry, |
371 | nullptr, xcalloc, xfree)); | |
46114cb7 | 372 | |
20a26f4e TT |
373 | for (cooked_index_entry *entry : m_entries) |
374 | { | |
4320a9c9 TT |
375 | if ((entry->flags & IS_PARENT_DEFERRED) != 0) |
376 | { | |
377 | const cooked_index_entry *new_parent | |
378 | = parent_maps->find (entry->get_deferred_parent ()); | |
379 | entry->resolve_parent (new_parent); | |
380 | } | |
381 | ||
47fe57c9 TT |
382 | /* Note that this code must be kept in sync with |
383 | language_requires_canonicalization. */ | |
20a26f4e | 384 | gdb_assert (entry->canonical == nullptr); |
bed34ce7 | 385 | if ((entry->flags & IS_LINKAGE) != 0) |
20a26f4e | 386 | entry->canonical = entry->name; |
5902fa8a | 387 | else if (entry->lang == language_ada) |
51f5a4b8 | 388 | { |
bed34ce7 TT |
389 | gdb::unique_xmalloc_ptr<char> canon_name |
390 | = handle_gnat_encoded_entry (entry, gnat_entries.get ()); | |
391 | if (canon_name == nullptr) | |
392 | entry->canonical = entry->name; | |
393 | else | |
394 | { | |
395 | entry->canonical = canon_name.get (); | |
396 | m_names.push_back (std::move (canon_name)); | |
397 | } | |
398 | } | |
5902fa8a | 399 | else if (entry->lang == language_cplus || entry->lang == language_c) |
bed34ce7 TT |
400 | { |
401 | void **slot = htab_find_slot (seen_names.get (), entry, | |
402 | INSERT); | |
403 | if (*slot == nullptr) | |
20a26f4e TT |
404 | { |
405 | gdb::unique_xmalloc_ptr<char> canon_name | |
5902fa8a | 406 | = (entry->lang == language_cplus |
55fc1623 TT |
407 | ? cp_canonicalize_string (entry->name) |
408 | : c_canonicalize_name (entry->name)); | |
20a26f4e TT |
409 | if (canon_name == nullptr) |
410 | entry->canonical = entry->name; | |
411 | else | |
412 | { | |
413 | entry->canonical = canon_name.get (); | |
414 | m_names.push_back (std::move (canon_name)); | |
415 | } | |
b6c55de7 | 416 | *slot = entry; |
20a26f4e | 417 | } |
51f5a4b8 TT |
418 | else |
419 | { | |
bed34ce7 TT |
420 | const cooked_index_entry *other |
421 | = (const cooked_index_entry *) *slot; | |
422 | entry->canonical = other->canonical; | |
51f5a4b8 TT |
423 | } |
424 | } | |
bed34ce7 TT |
425 | else |
426 | entry->canonical = entry->name; | |
51f5a4b8 TT |
427 | } |
428 | ||
429 | m_names.shrink_to_fit (); | |
430 | m_entries.shrink_to_fit (); | |
431 | std::sort (m_entries.begin (), m_entries.end (), | |
432 | [] (const cooked_index_entry *a, const cooked_index_entry *b) | |
433 | { | |
434 | return *a < *b; | |
435 | }); | |
436 | } | |
20a26f4e TT |
437 | |
438 | /* See cooked-index.h. */ | |
439 | ||
a8dc6718 SM |
440 | cooked_index_shard::range |
441 | cooked_index_shard::find (const std::string &name, bool completing) const | |
20a26f4e | 442 | { |
c121e82c TT |
443 | cooked_index_entry::comparison_mode mode = (completing |
444 | ? cooked_index_entry::COMPLETE | |
445 | : cooked_index_entry::MATCH); | |
446 | ||
35e17631 | 447 | auto lower = std::lower_bound (m_entries.cbegin (), m_entries.cend (), name, |
20a26f4e | 448 | [=] (const cooked_index_entry *entry, |
ac37b79c | 449 | const std::string &n) |
20a26f4e | 450 | { |
c121e82c | 451 | return cooked_index_entry::compare (entry->canonical, n.c_str (), mode) < 0; |
20a26f4e TT |
452 | }); |
453 | ||
35e17631 | 454 | auto upper = std::upper_bound (m_entries.cbegin (), m_entries.cend (), name, |
ac37b79c | 455 | [=] (const std::string &n, |
20a26f4e TT |
456 | const cooked_index_entry *entry) |
457 | { | |
c121e82c | 458 | return cooked_index_entry::compare (entry->canonical, n.c_str (), mode) > 0; |
20a26f4e TT |
459 | }); |
460 | ||
461 | return range (lower, upper); | |
462 | } | |
463 | ||
47efef8f TT |
464 | /* See cooked-index.h. */ |
465 | ||
466 | void | |
467 | cooked_index_worker::start () | |
468 | { | |
469 | gdb::thread_pool::g_thread_pool->post_task ([=] () | |
470 | { | |
36cde74b TT |
471 | try |
472 | { | |
473 | do_reading (); | |
474 | } | |
475 | catch (const gdb_exception &exc) | |
476 | { | |
477 | m_failed = exc; | |
478 | set (cooked_state::CACHE_DONE); | |
479 | } | |
47efef8f | 480 | |
36cde74b TT |
481 | bfd_thread_cleanup (); |
482 | }); | |
47efef8f TT |
483 | } |
484 | ||
485 | /* See cooked-index.h. */ | |
486 | ||
487 | bool | |
488 | cooked_index_worker::wait (cooked_state desired_state, bool allow_quit) | |
489 | { | |
490 | bool done; | |
491 | #if CXX_STD_THREAD | |
492 | { | |
493 | std::unique_lock<std::mutex> lock (m_mutex); | |
494 | ||
495 | /* This may be called from a non-main thread -- this functionality | |
496 | is needed for the index cache -- but in this case we require | |
497 | that the desired state already have been attained. */ | |
498 | gdb_assert (is_main_thread () || desired_state <= m_state); | |
499 | ||
500 | while (desired_state > m_state) | |
501 | { | |
502 | if (allow_quit) | |
503 | { | |
504 | std::chrono::milliseconds duration { 15 }; | |
505 | if (m_cond.wait_for (lock, duration) == std::cv_status::timeout) | |
506 | QUIT; | |
507 | } | |
508 | else | |
509 | m_cond.wait (lock); | |
510 | } | |
511 | done = m_state == cooked_state::CACHE_DONE; | |
512 | } | |
513 | #else | |
514 | /* Without threads, all the work is done immediately on the main | |
515 | thread, and there is never anything to wait for. */ | |
516 | done = true; | |
517 | #endif /* CXX_STD_THREAD */ | |
518 | ||
519 | /* Only the main thread is allowed to report complaints and the | |
520 | like. */ | |
521 | if (!is_main_thread ()) | |
522 | return false; | |
523 | ||
524 | if (m_reported) | |
525 | return done; | |
526 | m_reported = true; | |
527 | ||
528 | /* Emit warnings first, maybe they were emitted before an exception | |
529 | (if any) was thrown. */ | |
530 | m_warnings.emit (); | |
531 | ||
532 | if (m_failed.has_value ()) | |
533 | { | |
36cde74b | 534 | /* do_reading failed -- report it. */ |
47efef8f TT |
535 | exception_print (gdb_stderr, *m_failed); |
536 | m_failed.reset (); | |
537 | return done; | |
538 | } | |
539 | ||
540 | /* Only show a given exception a single time. */ | |
541 | std::unordered_set<gdb_exception> seen_exceptions; | |
542 | for (auto &one_result : m_results) | |
543 | { | |
544 | re_emit_complaints (std::get<1> (one_result)); | |
545 | for (auto &one_exc : std::get<2> (one_result)) | |
546 | if (seen_exceptions.insert (one_exc).second) | |
547 | exception_print (gdb_stderr, one_exc); | |
548 | } | |
549 | ||
550 | print_stats (); | |
551 | ||
552 | struct objfile *objfile = m_per_objfile->objfile; | |
553 | dwarf2_per_bfd *per_bfd = m_per_objfile->per_bfd; | |
554 | cooked_index *table | |
555 | = (gdb::checked_static_cast<cooked_index *> | |
556 | (per_bfd->index_table.get ())); | |
557 | ||
558 | auto_obstack temp_storage; | |
559 | enum language lang = language_unknown; | |
560 | const char *main_name = table->get_main_name (&temp_storage, &lang); | |
561 | if (main_name != nullptr) | |
562 | set_objfile_main_name (objfile, main_name, lang); | |
563 | ||
564 | /* dwarf_read_debug_printf ("Done building psymtabs of %s", */ | |
565 | /* objfile_name (objfile)); */ | |
566 | ||
567 | return done; | |
568 | } | |
569 | ||
570 | /* See cooked-index.h. */ | |
571 | ||
572 | void | |
573 | cooked_index_worker::set (cooked_state desired_state) | |
574 | { | |
575 | gdb_assert (desired_state != cooked_state::INITIAL); | |
576 | ||
577 | #if CXX_STD_THREAD | |
578 | std::lock_guard<std::mutex> guard (m_mutex); | |
579 | gdb_assert (desired_state > m_state); | |
580 | m_state = desired_state; | |
581 | m_cond.notify_one (); | |
582 | #else | |
583 | /* Without threads, all the work is done immediately on the main | |
584 | thread, and there is never anything to do. */ | |
585 | #endif /* CXX_STD_THREAD */ | |
586 | } | |
307733cc | 587 | |
ed29a346 TT |
588 | /* See cooked-index.h. */ |
589 | ||
590 | void | |
818ef5f4 TT |
591 | cooked_index_worker::write_to_cache (const cooked_index *idx, |
592 | deferred_warnings *warn) const | |
ed29a346 TT |
593 | { |
594 | if (idx != nullptr) | |
818ef5f4 TT |
595 | { |
596 | /* Writing to the index cache may cause a warning to be emitted. | |
597 | See PR symtab/30837. This arranges to capture all such | |
598 | warnings. This is safe because we know the deferred_warnings | |
599 | object isn't in use by any other thread at this point. */ | |
75670e00 | 600 | scoped_restore_warning_hook defer (warn); |
818ef5f4 TT |
601 | m_cache_store.store (); |
602 | } | |
ed29a346 TT |
603 | } |
604 | ||
47efef8f TT |
605 | cooked_index::cooked_index (dwarf2_per_objfile *per_objfile, |
606 | std::unique_ptr<cooked_index_worker> &&worker) | |
607 | : m_state (std::move (worker)), | |
33c6eaae | 608 | m_per_bfd (per_objfile->per_bfd) |
20a26f4e | 609 | { |
52e5e48e TT |
610 | /* ACTIVE_VECTORS is not locked, and this assert ensures that this |
611 | will be caught if ever moved to the background. */ | |
612 | gdb_assert (is_main_thread ()); | |
613 | active_vectors.insert (this); | |
614 | } | |
615 | ||
33c6eaae TT |
616 | void |
617 | cooked_index::start_reading () | |
618 | { | |
619 | m_state->start (); | |
620 | } | |
6f214d0f TT |
621 | |
622 | void | |
33c6eaae | 623 | cooked_index::wait (cooked_state desired_state, bool allow_quit) |
6f214d0f | 624 | { |
33c6eaae | 625 | gdb_assert (desired_state != cooked_state::INITIAL); |
8adc5522 | 626 | |
33c6eaae TT |
627 | /* If the state object has been deleted, then that means waiting is |
628 | completely done. */ | |
629 | if (m_state == nullptr) | |
630 | return; | |
631 | ||
632 | if (m_state->wait (desired_state, allow_quit)) | |
633 | { | |
634 | /* Only the main thread can modify this. */ | |
635 | gdb_assert (is_main_thread ()); | |
636 | m_state.reset (nullptr); | |
637 | } | |
638 | } | |
639 | ||
640 | void | |
4320a9c9 TT |
641 | cooked_index::set_contents (vec_type &&vec, deferred_warnings *warn, |
642 | const parent_map_map *parent_maps) | |
33c6eaae TT |
643 | { |
644 | gdb_assert (m_vector.empty ()); | |
645 | m_vector = std::move (vec); | |
646 | ||
647 | m_state->set (cooked_state::MAIN_AVAILABLE); | |
648 | ||
33c6eaae TT |
649 | /* This is run after finalization is done -- but not before. If |
650 | this task were submitted earlier, it would have to wait for | |
651 | finalization. However, that would take a slot in the global | |
652 | thread pool, and if enough such tasks were submitted at once, it | |
653 | would cause a livelock. */ | |
818ef5f4 | 654 | gdb::task_group finalizers ([=] () |
33c6eaae TT |
655 | { |
656 | m_state->set (cooked_state::FINALIZED); | |
818ef5f4 | 657 | m_state->write_to_cache (index_for_writing (), warn); |
ed29a346 | 658 | m_state->set (cooked_state::CACHE_DONE); |
33c6eaae TT |
659 | }); |
660 | ||
661 | for (auto &idx : m_vector) | |
662 | { | |
663 | auto this_index = idx.get (); | |
4320a9c9 | 664 | finalizers.add_task ([=] () { this_index->finalize (parent_maps); }); |
33c6eaae TT |
665 | } |
666 | ||
667 | finalizers.start (); | |
6f214d0f TT |
668 | } |
669 | ||
52e5e48e TT |
670 | cooked_index::~cooked_index () |
671 | { | |
33c6eaae | 672 | /* Wait for index-creation to be done, though this one must also |
52e5e48e TT |
673 | waited for by the per-BFD object to ensure the required data |
674 | remains live. */ | |
33c6eaae | 675 | wait (cooked_state::CACHE_DONE); |
52e5e48e TT |
676 | |
677 | /* Remove our entry from the global list. See the assert in the | |
678 | constructor to understand this. */ | |
679 | gdb_assert (is_main_thread ()); | |
680 | active_vectors.erase (this); | |
20a26f4e TT |
681 | } |
682 | ||
683 | /* See cooked-index.h. */ | |
684 | ||
685 | dwarf2_per_cu_data * | |
bdb4b803 | 686 | cooked_index::lookup (unrelocated_addr addr) |
20a26f4e | 687 | { |
33c6eaae TT |
688 | /* Ensure that the address maps are ready. */ |
689 | wait (cooked_state::MAIN_AVAILABLE, true); | |
20a26f4e TT |
690 | for (const auto &index : m_vector) |
691 | { | |
692 | dwarf2_per_cu_data *result = index->lookup (addr); | |
693 | if (result != nullptr) | |
694 | return result; | |
695 | } | |
696 | return nullptr; | |
697 | } | |
698 | ||
699 | /* See cooked-index.h. */ | |
700 | ||
70ca3a6b | 701 | std::vector<const addrmap *> |
33c6eaae | 702 | cooked_index::get_addrmaps () |
20a26f4e | 703 | { |
33c6eaae TT |
704 | /* Ensure that the address maps are ready. */ |
705 | wait (cooked_state::MAIN_AVAILABLE, true); | |
70ca3a6b | 706 | std::vector<const addrmap *> result; |
20a26f4e TT |
707 | for (const auto &index : m_vector) |
708 | result.push_back (index->m_addrmap); | |
709 | return result; | |
710 | } | |
711 | ||
712 | /* See cooked-index.h. */ | |
713 | ||
19455ee1 | 714 | cooked_index::range |
33c6eaae | 715 | cooked_index::find (const std::string &name, bool completing) |
20a26f4e | 716 | { |
33c6eaae | 717 | wait (cooked_state::FINALIZED, true); |
a8dc6718 | 718 | std::vector<cooked_index_shard::range> result_range; |
20a26f4e TT |
719 | result_range.reserve (m_vector.size ()); |
720 | for (auto &entry : m_vector) | |
721 | result_range.push_back (entry->find (name, completing)); | |
722 | return range (std::move (result_range)); | |
723 | } | |
724 | ||
725 | /* See cooked-index.h. */ | |
726 | ||
33c6eaae TT |
727 | const char * |
728 | cooked_index::get_main_name (struct obstack *obstack, enum language *lang) | |
729 | const | |
730 | { | |
731 | const cooked_index_entry *entry = get_main (); | |
732 | if (entry == nullptr) | |
733 | return nullptr; | |
734 | ||
5902fa8a | 735 | *lang = entry->lang; |
33c6eaae TT |
736 | return entry->full_name (obstack, true); |
737 | } | |
738 | ||
739 | /* See cooked_index.h. */ | |
740 | ||
20a26f4e | 741 | const cooked_index_entry * |
19455ee1 | 742 | cooked_index::get_main () const |
20a26f4e | 743 | { |
33c6eaae | 744 | const cooked_index_entry *best_entry = nullptr; |
20a26f4e TT |
745 | for (const auto &index : m_vector) |
746 | { | |
747 | const cooked_index_entry *entry = index->get_main (); | |
33c6eaae TT |
748 | /* Choose the first "main" we see. We only do this for names |
749 | not requiring canonicalization. At this point in the process | |
750 | names might not have been canonicalized. However, currently, | |
751 | languages that require this step also do not use | |
752 | DW_AT_main_subprogram. An assert is appropriate here because | |
753 | this filtering is done in get_main. */ | |
754 | if (entry != nullptr) | |
47fe57c9 | 755 | { |
33c6eaae TT |
756 | if ((entry->flags & IS_MAIN) != 0) |
757 | { | |
5902fa8a | 758 | if (!language_requires_canonicalization (entry->lang)) |
33c6eaae TT |
759 | { |
760 | /* There won't be one better than this. */ | |
761 | return entry; | |
762 | } | |
763 | } | |
764 | else | |
765 | { | |
766 | /* This is one that is named "main". Here we don't care | |
767 | if the language requires canonicalization, due to how | |
768 | the entry is detected. Entries like this have worse | |
769 | priority than IS_MAIN entries. */ | |
770 | if (best_entry == nullptr) | |
771 | best_entry = entry; | |
772 | } | |
47fe57c9 | 773 | } |
20a26f4e TT |
774 | } |
775 | ||
33c6eaae | 776 | return best_entry; |
20a26f4e | 777 | } |
ac37b79c | 778 | |
9fac3e79 TT |
779 | quick_symbol_functions_up |
780 | cooked_index::make_quick_functions () const | |
781 | { | |
782 | return quick_symbol_functions_up (new cooked_index_functions); | |
783 | } | |
784 | ||
7d82b08e SM |
785 | /* See cooked-index.h. */ |
786 | ||
787 | void | |
33c6eaae | 788 | cooked_index::dump (gdbarch *arch) |
7d82b08e | 789 | { |
8f258a6c TV |
790 | auto_obstack temp_storage; |
791 | ||
7d82b08e SM |
792 | gdb_printf (" entries:\n"); |
793 | gdb_printf ("\n"); | |
794 | ||
795 | size_t i = 0; | |
796 | for (const cooked_index_entry *entry : this->all_entries ()) | |
797 | { | |
798 | QUIT; | |
799 | ||
800 | gdb_printf (" [%zu] ((cooked_index_entry *) %p)\n", i++, entry); | |
801 | gdb_printf (" name: %s\n", entry->name); | |
802 | gdb_printf (" canonical: %s\n", entry->canonical); | |
8f258a6c | 803 | gdb_printf (" qualified: %s\n", entry->full_name (&temp_storage, false)); |
7d82b08e SM |
804 | gdb_printf (" DWARF tag: %s\n", dwarf_tag_name (entry->tag)); |
805 | gdb_printf (" flags: %s\n", to_string (entry->flags).c_str ()); | |
b8a175b4 | 806 | gdb_printf (" DIE offset: %s\n", sect_offset_str (entry->die_offset)); |
7d82b08e | 807 | |
42bd6b5f TV |
808 | if ((entry->flags & IS_PARENT_DEFERRED) != 0) |
809 | gdb_printf (" parent: deferred (%" PRIx64 ")\n", | |
810 | entry->get_deferred_parent ()); | |
811 | else if (entry->get_parent () != nullptr) | |
7d82b08e | 812 | gdb_printf (" parent: ((cooked_index_entry *) %p) [%s]\n", |
850fce8b | 813 | entry->get_parent (), entry->get_parent ()->name); |
7d82b08e SM |
814 | else |
815 | gdb_printf (" parent: ((cooked_index_entry *) 0)\n"); | |
816 | ||
817 | gdb_printf ("\n"); | |
818 | } | |
819 | ||
820 | const cooked_index_entry *main_entry = this->get_main (); | |
821 | if (main_entry != nullptr) | |
822 | gdb_printf (" main: ((cooked_index_entry *) %p) [%s]\n", main_entry, | |
823 | main_entry->name); | |
824 | else | |
825 | gdb_printf (" main: ((cooked_index_entry *) 0)\n"); | |
826 | ||
827 | gdb_printf ("\n"); | |
828 | gdb_printf (" address maps:\n"); | |
829 | gdb_printf ("\n"); | |
830 | ||
831 | std::vector<const addrmap *> addrmaps = this->get_addrmaps (); | |
832 | for (i = 0; i < addrmaps.size (); ++i) | |
833 | { | |
834 | const addrmap &addrmap = *addrmaps[i]; | |
835 | ||
836 | gdb_printf (" [%zu] ((addrmap *) %p)\n", i, &addrmap); | |
837 | gdb_printf ("\n"); | |
838 | ||
839 | addrmap.foreach ([arch] (CORE_ADDR start_addr, const void *obj) | |
840 | { | |
841 | QUIT; | |
842 | ||
843 | const char *start_addr_str = paddress (arch, start_addr); | |
844 | ||
845 | if (obj != nullptr) | |
846 | { | |
847 | const dwarf2_per_cu_data *per_cu | |
848 | = static_cast<const dwarf2_per_cu_data *> (obj); | |
849 | gdb_printf (" [%s] ((dwarf2_per_cu_data *) %p)\n", | |
850 | start_addr_str, per_cu); | |
851 | } | |
852 | else | |
853 | gdb_printf (" [%s] ((dwarf2_per_cu_data *) 0)\n", | |
854 | start_addr_str); | |
855 | ||
856 | return 0; | |
857 | }); | |
858 | ||
859 | gdb_printf ("\n"); | |
860 | } | |
861 | } | |
862 | ||
52e5e48e TT |
863 | /* Wait for all the index cache entries to be written before gdb |
864 | exits. */ | |
865 | static void | |
866 | wait_for_index_cache (int) | |
867 | { | |
868 | gdb_assert (is_main_thread ()); | |
869 | for (cooked_index *item : active_vectors) | |
870 | item->wait_completely (); | |
871 | } | |
872 | ||
f0c3dcc1 TT |
873 | /* A maint command to wait for the cache. */ |
874 | ||
875 | static void | |
876 | maintenance_wait_for_index_cache (const char *args, int from_tty) | |
877 | { | |
878 | wait_for_index_cache (0); | |
879 | } | |
880 | ||
ac37b79c TT |
881 | void _initialize_cooked_index (); |
882 | void | |
883 | _initialize_cooked_index () | |
884 | { | |
885 | #if GDB_SELF_TEST | |
886 | selftests::register_test ("cooked_index_entry::compare", test_compare); | |
887 | #endif | |
52e5e48e | 888 | |
f0c3dcc1 TT |
889 | add_cmd ("wait-for-index-cache", class_maintenance, |
890 | maintenance_wait_for_index_cache, _("\ | |
4779ed97 TT |
891 | Wait until all pending writes to the index cache have completed.\n\ |
892 | Usage: maintenance wait-for-index-cache"), | |
f0c3dcc1 TT |
893 | &maintenancelist); |
894 | ||
52e5e48e | 895 | gdb::observers::gdb_exiting.attach (wait_for_index_cache, "cooked-index"); |
ac37b79c | 896 | } |