]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/dwarf2/cooked-index.c
gdb: move a bunch of quit-related things to event-top.{c,h}
[thirdparty/binutils-gdb.git] / gdb / dwarf2 / cooked-index.c
1 /* DIE indexing
2
3 Copyright (C) 2022-2024 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 "dwarf2/cooked-index.h"
21 #include "dwarf2/read.h"
22 #include "dwarf2/stringify.h"
23 #include "dwarf2/index-cache.h"
24 #include "cp-support.h"
25 #include "c-lang.h"
26 #include "ada-lang.h"
27 #include "event-top.h"
28 #include "split-name.h"
29 #include "observable.h"
30 #include "run-on-main-thread.h"
31 #include <algorithm>
32 #include "gdbsupport/gdb-safe-ctype.h"
33 #include "gdbsupport/selftest.h"
34 #include <chrono>
35 #include <unordered_set>
36 #include "cli/cli-cmds.h"
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;
42
43 /* See cooked-index.h. */
44
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),
51 MAP_ENUM_FLAG (IS_LINKAGE),
52 MAP_ENUM_FLAG (IS_TYPE_DECLARATION),
53 MAP_ENUM_FLAG (IS_PARENT_DEFERRED),
54 };
55
56 return flags.to_string (mapping);
57 }
58
59 /* See cooked-index.h. */
60
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
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
86 /* See cooked-index.h. */
87
88 int
89 cooked_index_entry::compare (const char *stra, const char *strb,
90 comparison_mode mode)
91 {
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 };
100
101 while (*stra != '\0'
102 && *strb != '\0'
103 && (munge (*stra) == munge (*strb)))
104 {
105 ++stra;
106 ++strb;
107 }
108
109 unsigned char c1 = munge (*stra);
110 unsigned char c2 = munge (*strb);
111
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 ('<')))
119 {
120 if (c2 == '\0')
121 return 0;
122 }
123
124 return c1 < c2 ? -1 : 1;
125 }
126
127 #if GDB_SELF_TEST
128
129 namespace {
130
131 void
132 test_compare ()
133 {
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);
193 }
194
195 } /* anonymous namespace */
196
197 #endif /* GDB_SELF_TEST */
198
199 /* See cooked-index.h. */
200
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
208 return tag_matches_domain (tag, kind, lang);
209 }
210
211 /* See cooked-index.h. */
212
213 const char *
214 cooked_index_entry::full_name (struct obstack *storage, bool for_main) const
215 {
216 const char *local_name = for_main ? name : canonical;
217
218 if ((flags & IS_LINKAGE) != 0 || get_parent () == nullptr)
219 return local_name;
220
221 const char *sep = nullptr;
222 switch (lang)
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;
234
235 default:
236 return local_name;
237 }
238
239 get_parent ()->write_scope (storage, sep, for_main);
240 obstack_grow0 (storage, local_name, strlen (local_name));
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,
248 const char *sep,
249 bool for_main) const
250 {
251 if (get_parent () != nullptr)
252 get_parent ()->write_scope (storage, sep, for_main);
253 const char *local_name = for_main ? name : canonical;
254 obstack_grow (storage, local_name, strlen (local_name));
255 obstack_grow (storage, sep, strlen (sep));
256 }
257
258 /* See cooked-index.h. */
259
260 cooked_index_entry *
261 cooked_index_shard::add (sect_offset die_offset, enum dwarf_tag tag,
262 cooked_index_flag flags, enum language lang,
263 const char *name,
264 cooked_index_entry_ref parent_entry,
265 dwarf2_per_cu_data *per_cu)
266 {
267 cooked_index_entry *result = create (die_offset, tag, flags, lang, name,
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;
275 else if ((flags & IS_PARENT_DEFERRED) == 0
276 && parent_entry.resolved == nullptr
277 && m_main == nullptr
278 && language_may_use_plain_main (lang)
279 && strcmp (name, "main") == 0)
280 m_main = result;
281
282 return result;
283 }
284
285 /* See cooked-index.h. */
286
287 gdb::unique_xmalloc_ptr<char>
288 cooked_index_shard::handle_gnat_encoded_entry (cooked_index_entry *entry,
289 htab_t gnat_entries)
290 {
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);
296 if (canonical.empty ())
297 return {};
298 std::vector<std::string_view> names = split_name (canonical.c_str (),
299 split_style::DOT_STYLE);
300 std::string_view tail = names.back ();
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 ());
316 last = create (entry->die_offset, DW_TAG_namespace,
317 0, language_ada, new_name.get (), parent,
318 entry->per_cu);
319 last->canonical = last->name;
320 m_names.push_back (std::move (new_name));
321 *slot = last;
322 }
323
324 parent = last;
325 }
326
327 entry->set_parent (parent);
328 return make_unique_xstrndup (tail.data (), tail.length ());
329 }
330
331 /* See cooked-index.h. */
332
333 void
334 cooked_index_shard::finalize (const parent_map_map *parent_maps)
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
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;
365 const std::string_view *sv = (const std::string_view *) b;
366 return (strlen (ae->canonical) == sv->length ()
367 && strncasecmp (ae->canonical, sv->data (), sv->length ()) == 0);
368 };
369
370 htab_up gnat_entries (htab_create_alloc (10, hash_entry, eq_entry,
371 nullptr, xcalloc, xfree));
372
373 for (cooked_index_entry *entry : m_entries)
374 {
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
382 /* Note that this code must be kept in sync with
383 language_requires_canonicalization. */
384 gdb_assert (entry->canonical == nullptr);
385 if ((entry->flags & IS_LINKAGE) != 0)
386 entry->canonical = entry->name;
387 else if (entry->lang == language_ada)
388 {
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 }
399 else if (entry->lang == language_cplus || entry->lang == language_c)
400 {
401 void **slot = htab_find_slot (seen_names.get (), entry,
402 INSERT);
403 if (*slot == nullptr)
404 {
405 gdb::unique_xmalloc_ptr<char> canon_name
406 = (entry->lang == language_cplus
407 ? cp_canonicalize_string (entry->name)
408 : c_canonicalize_name (entry->name));
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 }
416 *slot = entry;
417 }
418 else
419 {
420 const cooked_index_entry *other
421 = (const cooked_index_entry *) *slot;
422 entry->canonical = other->canonical;
423 }
424 }
425 else
426 entry->canonical = entry->name;
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 }
437
438 /* See cooked-index.h. */
439
440 cooked_index_shard::range
441 cooked_index_shard::find (const std::string &name, bool completing) const
442 {
443 cooked_index_entry::comparison_mode mode = (completing
444 ? cooked_index_entry::COMPLETE
445 : cooked_index_entry::MATCH);
446
447 auto lower = std::lower_bound (m_entries.cbegin (), m_entries.cend (), name,
448 [=] (const cooked_index_entry *entry,
449 const std::string &n)
450 {
451 return cooked_index_entry::compare (entry->canonical, n.c_str (), mode) < 0;
452 });
453
454 auto upper = std::upper_bound (m_entries.cbegin (), m_entries.cend (), name,
455 [=] (const std::string &n,
456 const cooked_index_entry *entry)
457 {
458 return cooked_index_entry::compare (entry->canonical, n.c_str (), mode) > 0;
459 });
460
461 return range (lower, upper);
462 }
463
464 /* See cooked-index.h. */
465
466 void
467 cooked_index_worker::start ()
468 {
469 gdb::thread_pool::g_thread_pool->post_task ([=] ()
470 {
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 }
480
481 bfd_thread_cleanup ();
482 });
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 {
534 /* do_reading failed -- report it. */
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 }
587
588 /* See cooked-index.h. */
589
590 void
591 cooked_index_worker::write_to_cache (const cooked_index *idx,
592 deferred_warnings *warn) const
593 {
594 if (idx != nullptr)
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. */
600 scoped_restore_warning_hook defer (warn);
601 m_cache_store.store ();
602 }
603 }
604
605 cooked_index::cooked_index (dwarf2_per_objfile *per_objfile,
606 std::unique_ptr<cooked_index_worker> &&worker)
607 : m_state (std::move (worker)),
608 m_per_bfd (per_objfile->per_bfd)
609 {
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
616 void
617 cooked_index::start_reading ()
618 {
619 m_state->start ();
620 }
621
622 void
623 cooked_index::wait (cooked_state desired_state, bool allow_quit)
624 {
625 gdb_assert (desired_state != cooked_state::INITIAL);
626
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
641 cooked_index::set_contents (vec_type &&vec, deferred_warnings *warn,
642 const parent_map_map *parent_maps)
643 {
644 gdb_assert (m_vector.empty ());
645 m_vector = std::move (vec);
646
647 m_state->set (cooked_state::MAIN_AVAILABLE);
648
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. */
654 gdb::task_group finalizers ([=] ()
655 {
656 m_state->set (cooked_state::FINALIZED);
657 m_state->write_to_cache (index_for_writing (), warn);
658 m_state->set (cooked_state::CACHE_DONE);
659 });
660
661 for (auto &idx : m_vector)
662 {
663 auto this_index = idx.get ();
664 finalizers.add_task ([=] () { this_index->finalize (parent_maps); });
665 }
666
667 finalizers.start ();
668 }
669
670 cooked_index::~cooked_index ()
671 {
672 /* Wait for index-creation to be done, though this one must also
673 waited for by the per-BFD object to ensure the required data
674 remains live. */
675 wait (cooked_state::CACHE_DONE);
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);
681 }
682
683 /* See cooked-index.h. */
684
685 dwarf2_per_cu_data *
686 cooked_index::lookup (unrelocated_addr addr)
687 {
688 /* Ensure that the address maps are ready. */
689 wait (cooked_state::MAIN_AVAILABLE, true);
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
701 std::vector<const addrmap *>
702 cooked_index::get_addrmaps ()
703 {
704 /* Ensure that the address maps are ready. */
705 wait (cooked_state::MAIN_AVAILABLE, true);
706 std::vector<const addrmap *> result;
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
714 cooked_index::range
715 cooked_index::find (const std::string &name, bool completing)
716 {
717 wait (cooked_state::FINALIZED, true);
718 std::vector<cooked_index_shard::range> result_range;
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
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
735 *lang = entry->lang;
736 return entry->full_name (obstack, true);
737 }
738
739 /* See cooked_index.h. */
740
741 const cooked_index_entry *
742 cooked_index::get_main () const
743 {
744 const cooked_index_entry *best_entry = nullptr;
745 for (const auto &index : m_vector)
746 {
747 const cooked_index_entry *entry = index->get_main ();
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)
755 {
756 if ((entry->flags & IS_MAIN) != 0)
757 {
758 if (!language_requires_canonicalization (entry->lang))
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 }
773 }
774 }
775
776 return best_entry;
777 }
778
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
785 /* See cooked-index.h. */
786
787 void
788 cooked_index::dump (gdbarch *arch)
789 {
790 auto_obstack temp_storage;
791
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);
803 gdb_printf (" qualified: %s\n", entry->full_name (&temp_storage, false));
804 gdb_printf (" DWARF tag: %s\n", dwarf_tag_name (entry->tag));
805 gdb_printf (" flags: %s\n", to_string (entry->flags).c_str ());
806 gdb_printf (" DIE offset: %s\n", sect_offset_str (entry->die_offset));
807
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)
812 gdb_printf (" parent: ((cooked_index_entry *) %p) [%s]\n",
813 entry->get_parent (), entry->get_parent ()->name);
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
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
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
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
888
889 add_cmd ("wait-for-index-cache", class_maintenance,
890 maintenance_wait_for_index_cache, _("\
891 Wait until all pending writes to the index cache have completed.\n\
892 Usage: maintenance wait-for-index-cache"),
893 &maintenancelist);
894
895 gdb::observers::gdb_exiting.attach (wait_for_index_cache, "cooked-index");
896 }