]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/dwarf2/cooked-index.c
Add language to cooked_index_entry
[thirdparty/binutils-gdb.git] / gdb / dwarf2 / cooked-index.c
CommitLineData
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
20#include "defs.h"
21#include "dwarf2/cooked-index.h"
22#include "dwarf2/read.h"
7d82b08e 23#include "dwarf2/stringify.h"
52e5e48e 24#include "dwarf2/index-cache.h"
51f5a4b8 25#include "cp-support.h"
55fc1623 26#include "c-lang.h"
51f5a4b8
TT
27#include "ada-lang.h"
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. */
41static std::unordered_set<cooked_index *> active_vectors;
ac37b79c
TT
42
43/* See cooked-index.h. */
44
7d82b08e
SM
45std::string
46to_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
61bool
62language_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
73static bool
74language_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 88int
ac37b79c 89cooked_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
129namespace {
130
131void
132test_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
201const char *
47fe57c9 202cooked_index_entry::full_name (struct obstack *storage, bool for_main) const
51f5a4b8 203{
47fe57c9
TT
204 const char *local_name = for_main ? name : canonical;
205
850fce8b 206 if ((flags & IS_LINKAGE) != 0 || get_parent () == nullptr)
47fe57c9 207 return local_name;
51f5a4b8
TT
208
209 const char *sep = nullptr;
5902fa8a 210 switch (lang)
51f5a4b8
TT
211 {
212 case language_cplus:
213 case language_rust:
214 sep = "::";
215 break;
216
217 case language_go:
218 case language_d:
219 case language_ada:
220 sep = ".";
221 break;
51f5a4b8 222
72b580b8 223 default:
47fe57c9 224 return local_name;
72b580b8 225 }
51f5a4b8 226
850fce8b 227 get_parent ()->write_scope (storage, sep, for_main);
47fe57c9 228 obstack_grow0 (storage, local_name, strlen (local_name));
51f5a4b8
TT
229 return (const char *) obstack_finish (storage);
230}
231
232/* See cooked-index.h. */
233
234void
235cooked_index_entry::write_scope (struct obstack *storage,
47fe57c9
TT
236 const char *sep,
237 bool for_main) const
51f5a4b8 238{
850fce8b
TV
239 if (get_parent () != nullptr)
240 get_parent ()->write_scope (storage, sep, for_main);
47fe57c9
TT
241 const char *local_name = for_main ? name : canonical;
242 obstack_grow (storage, local_name, strlen (local_name));
51f5a4b8
TT
243 obstack_grow (storage, sep, strlen (sep));
244}
245
246/* See cooked-index.h. */
247
920bcec0 248cooked_index_entry *
a8dc6718 249cooked_index_shard::add (sect_offset die_offset, enum dwarf_tag tag,
5902fa8a
TT
250 cooked_index_flag flags, enum language lang,
251 const char *name,
42bd6b5f 252 cooked_index_entry_ref parent_entry,
a8dc6718 253 dwarf2_per_cu_data *per_cu)
51f5a4b8 254{
5902fa8a 255 cooked_index_entry *result = create (die_offset, tag, flags, lang, name,
51f5a4b8
TT
256 parent_entry, per_cu);
257 m_entries.push_back (result);
258
259 /* An explicitly-tagged main program should always override the
260 implicit "main" discovery. */
261 if ((flags & IS_MAIN) != 0)
262 m_main = result;
42bd6b5f
TV
263 else if ((flags & IS_PARENT_DEFERRED) == 0
264 && parent_entry.resolved == nullptr
33c6eaae 265 && m_main == nullptr
5902fa8a 266 && language_may_use_plain_main (lang)
33c6eaae
TT
267 && strcmp (name, "main") == 0)
268 m_main = result;
51f5a4b8
TT
269
270 return result;
271}
272
46114cb7
TT
273/* See cooked-index.h. */
274
51f5a4b8 275gdb::unique_xmalloc_ptr<char>
a8dc6718
SM
276cooked_index_shard::handle_gnat_encoded_entry (cooked_index_entry *entry,
277 htab_t gnat_entries)
51f5a4b8 278{
957ce537
TT
279 /* We decode Ada names in a particular way: operators and wide
280 characters are left as-is. This is done to make name matching a
281 bit simpler; and for wide characters, it means the choice of Ada
282 source charset does not affect the indexer directly. */
283 std::string canonical = ada_decode (entry->name, false, false, false);
51f5a4b8
TT
284 if (canonical.empty ())
285 return {};
8082468f 286 std::vector<std::string_view> names = split_name (canonical.c_str (),
fe26aa95 287 split_style::DOT_STYLE);
8082468f 288 std::string_view tail = names.back ();
51f5a4b8
TT
289 names.pop_back ();
290
291 const cooked_index_entry *parent = nullptr;
292 for (const auto &name : names)
293 {
294 uint32_t hashval = dwarf5_djb_hash (name);
295 void **slot = htab_find_slot_with_hash (gnat_entries, &name,
296 hashval, INSERT);
297 /* CUs are processed in order, so we only need to check the most
298 recent entry. */
299 cooked_index_entry *last = (cooked_index_entry *) *slot;
300 if (last == nullptr || last->per_cu != entry->per_cu)
301 {
302 gdb::unique_xmalloc_ptr<char> new_name
303 = make_unique_xstrndup (name.data (), name.length ());
20a26f4e 304 last = create (entry->die_offset, DW_TAG_namespace,
5902fa8a 305 0, language_ada, new_name.get (), parent,
20a26f4e 306 entry->per_cu);
51f5a4b8
TT
307 last->canonical = last->name;
308 m_names.push_back (std::move (new_name));
309 *slot = last;
310 }
311
312 parent = last;
313 }
314
850fce8b 315 entry->set_parent (parent);
51f5a4b8
TT
316 return make_unique_xstrndup (tail.data (), tail.length ());
317}
318
319/* See cooked-index.h. */
320
321void
33c6eaae 322cooked_index_shard::finalize ()
51f5a4b8
TT
323{
324 auto hash_name_ptr = [] (const void *p)
325 {
326 const cooked_index_entry *entry = (const cooked_index_entry *) p;
327 return htab_hash_pointer (entry->name);
328 };
329
330 auto eq_name_ptr = [] (const void *a, const void *b) -> int
331 {
332 const cooked_index_entry *ea = (const cooked_index_entry *) a;
333 const cooked_index_entry *eb = (const cooked_index_entry *) b;
334 return ea->name == eb->name;
335 };
336
337 /* We can use pointer equality here because names come from
338 .debug_str, which will normally be unique-ified by the linker.
339 Also, duplicates are relatively harmless -- they just mean a bit
340 of extra memory is used. */
341 htab_up seen_names (htab_create_alloc (10, hash_name_ptr, eq_name_ptr,
342 nullptr, xcalloc, xfree));
343
5a89072f
TT
344 auto hash_entry = [] (const void *e)
345 {
346 const cooked_index_entry *entry = (const cooked_index_entry *) e;
347 return dwarf5_djb_hash (entry->canonical);
348 };
349
350 auto eq_entry = [] (const void *a, const void *b) -> int
351 {
352 const cooked_index_entry *ae = (const cooked_index_entry *) a;
8082468f 353 const std::string_view *sv = (const std::string_view *) b;
5a89072f
TT
354 return (strlen (ae->canonical) == sv->length ()
355 && strncasecmp (ae->canonical, sv->data (), sv->length ()) == 0);
356 };
357
20a26f4e
TT
358 htab_up gnat_entries (htab_create_alloc (10, hash_entry, eq_entry,
359 nullptr, xcalloc, xfree));
46114cb7 360
20a26f4e
TT
361 for (cooked_index_entry *entry : m_entries)
362 {
47fe57c9
TT
363 /* Note that this code must be kept in sync with
364 language_requires_canonicalization. */
20a26f4e 365 gdb_assert (entry->canonical == nullptr);
bed34ce7 366 if ((entry->flags & IS_LINKAGE) != 0)
20a26f4e 367 entry->canonical = entry->name;
5902fa8a 368 else if (entry->lang == language_ada)
51f5a4b8 369 {
bed34ce7
TT
370 gdb::unique_xmalloc_ptr<char> canon_name
371 = handle_gnat_encoded_entry (entry, gnat_entries.get ());
372 if (canon_name == nullptr)
373 entry->canonical = entry->name;
374 else
375 {
376 entry->canonical = canon_name.get ();
377 m_names.push_back (std::move (canon_name));
378 }
379 }
5902fa8a 380 else if (entry->lang == language_cplus || entry->lang == language_c)
bed34ce7
TT
381 {
382 void **slot = htab_find_slot (seen_names.get (), entry,
383 INSERT);
384 if (*slot == nullptr)
20a26f4e
TT
385 {
386 gdb::unique_xmalloc_ptr<char> canon_name
5902fa8a 387 = (entry->lang == language_cplus
55fc1623
TT
388 ? cp_canonicalize_string (entry->name)
389 : c_canonicalize_name (entry->name));
20a26f4e
TT
390 if (canon_name == nullptr)
391 entry->canonical = entry->name;
392 else
393 {
394 entry->canonical = canon_name.get ();
395 m_names.push_back (std::move (canon_name));
396 }
b6c55de7 397 *slot = entry;
20a26f4e 398 }
51f5a4b8
TT
399 else
400 {
bed34ce7
TT
401 const cooked_index_entry *other
402 = (const cooked_index_entry *) *slot;
403 entry->canonical = other->canonical;
51f5a4b8
TT
404 }
405 }
bed34ce7
TT
406 else
407 entry->canonical = entry->name;
51f5a4b8
TT
408 }
409
410 m_names.shrink_to_fit ();
411 m_entries.shrink_to_fit ();
412 std::sort (m_entries.begin (), m_entries.end (),
413 [] (const cooked_index_entry *a, const cooked_index_entry *b)
414 {
415 return *a < *b;
416 });
417}
20a26f4e
TT
418
419/* See cooked-index.h. */
420
a8dc6718
SM
421cooked_index_shard::range
422cooked_index_shard::find (const std::string &name, bool completing) const
20a26f4e 423{
c121e82c
TT
424 cooked_index_entry::comparison_mode mode = (completing
425 ? cooked_index_entry::COMPLETE
426 : cooked_index_entry::MATCH);
427
35e17631 428 auto lower = std::lower_bound (m_entries.cbegin (), m_entries.cend (), name,
20a26f4e 429 [=] (const cooked_index_entry *entry,
ac37b79c 430 const std::string &n)
20a26f4e 431 {
c121e82c 432 return cooked_index_entry::compare (entry->canonical, n.c_str (), mode) < 0;
20a26f4e
TT
433 });
434
35e17631 435 auto upper = std::upper_bound (m_entries.cbegin (), m_entries.cend (), name,
ac37b79c 436 [=] (const std::string &n,
20a26f4e
TT
437 const cooked_index_entry *entry)
438 {
c121e82c 439 return cooked_index_entry::compare (entry->canonical, n.c_str (), mode) > 0;
20a26f4e
TT
440 });
441
442 return range (lower, upper);
443}
444
307733cc 445
33c6eaae
TT
446cooked_index::cooked_index (dwarf2_per_objfile *per_objfile)
447 : m_state (std::make_unique<cooked_index_worker> (per_objfile)),
448 m_per_bfd (per_objfile->per_bfd)
20a26f4e 449{
52e5e48e
TT
450 /* ACTIVE_VECTORS is not locked, and this assert ensures that this
451 will be caught if ever moved to the background. */
452 gdb_assert (is_main_thread ());
453 active_vectors.insert (this);
454}
455
33c6eaae
TT
456void
457cooked_index::start_reading ()
458{
459 m_state->start ();
460}
6f214d0f
TT
461
462void
33c6eaae 463cooked_index::wait (cooked_state desired_state, bool allow_quit)
6f214d0f 464{
33c6eaae 465 gdb_assert (desired_state != cooked_state::INITIAL);
8adc5522 466
33c6eaae
TT
467 /* If the state object has been deleted, then that means waiting is
468 completely done. */
469 if (m_state == nullptr)
470 return;
471
472 if (m_state->wait (desired_state, allow_quit))
473 {
474 /* Only the main thread can modify this. */
475 gdb_assert (is_main_thread ());
476 m_state.reset (nullptr);
477 }
478}
479
480void
481cooked_index::set_contents (vec_type &&vec)
482{
483 gdb_assert (m_vector.empty ());
484 m_vector = std::move (vec);
485
486 m_state->set (cooked_state::MAIN_AVAILABLE);
487
488 index_cache_store_context ctx (global_index_cache, m_per_bfd);
489
490 /* This is run after finalization is done -- but not before. If
491 this task were submitted earlier, it would have to wait for
492 finalization. However, that would take a slot in the global
493 thread pool, and if enough such tasks were submitted at once, it
494 would cause a livelock. */
495 gdb::task_group finalizers ([this, ctx = std::move (ctx)] ()
496 {
497 m_state->set (cooked_state::FINALIZED);
498 maybe_write_index (m_per_bfd, ctx);
499 });
500
501 for (auto &idx : m_vector)
502 {
503 auto this_index = idx.get ();
504 finalizers.add_task ([=] () { this_index->finalize (); });
505 }
506
507 finalizers.start ();
6f214d0f
TT
508}
509
52e5e48e
TT
510cooked_index::~cooked_index ()
511{
33c6eaae 512 /* Wait for index-creation to be done, though this one must also
52e5e48e
TT
513 waited for by the per-BFD object to ensure the required data
514 remains live. */
33c6eaae 515 wait (cooked_state::CACHE_DONE);
52e5e48e
TT
516
517 /* Remove our entry from the global list. See the assert in the
518 constructor to understand this. */
519 gdb_assert (is_main_thread ());
520 active_vectors.erase (this);
20a26f4e
TT
521}
522
523/* See cooked-index.h. */
524
525dwarf2_per_cu_data *
bdb4b803 526cooked_index::lookup (unrelocated_addr addr)
20a26f4e 527{
33c6eaae
TT
528 /* Ensure that the address maps are ready. */
529 wait (cooked_state::MAIN_AVAILABLE, true);
20a26f4e
TT
530 for (const auto &index : m_vector)
531 {
532 dwarf2_per_cu_data *result = index->lookup (addr);
533 if (result != nullptr)
534 return result;
535 }
536 return nullptr;
537}
538
539/* See cooked-index.h. */
540
70ca3a6b 541std::vector<const addrmap *>
33c6eaae 542cooked_index::get_addrmaps ()
20a26f4e 543{
33c6eaae
TT
544 /* Ensure that the address maps are ready. */
545 wait (cooked_state::MAIN_AVAILABLE, true);
70ca3a6b 546 std::vector<const addrmap *> result;
20a26f4e
TT
547 for (const auto &index : m_vector)
548 result.push_back (index->m_addrmap);
549 return result;
550}
551
552/* See cooked-index.h. */
553
19455ee1 554cooked_index::range
33c6eaae 555cooked_index::find (const std::string &name, bool completing)
20a26f4e 556{
33c6eaae 557 wait (cooked_state::FINALIZED, true);
a8dc6718 558 std::vector<cooked_index_shard::range> result_range;
20a26f4e
TT
559 result_range.reserve (m_vector.size ());
560 for (auto &entry : m_vector)
561 result_range.push_back (entry->find (name, completing));
562 return range (std::move (result_range));
563}
564
565/* See cooked-index.h. */
566
33c6eaae
TT
567const char *
568cooked_index::get_main_name (struct obstack *obstack, enum language *lang)
569 const
570{
571 const cooked_index_entry *entry = get_main ();
572 if (entry == nullptr)
573 return nullptr;
574
5902fa8a 575 *lang = entry->lang;
33c6eaae
TT
576 return entry->full_name (obstack, true);
577}
578
579/* See cooked_index.h. */
580
20a26f4e 581const cooked_index_entry *
19455ee1 582cooked_index::get_main () const
20a26f4e 583{
33c6eaae 584 const cooked_index_entry *best_entry = nullptr;
20a26f4e
TT
585 for (const auto &index : m_vector)
586 {
587 const cooked_index_entry *entry = index->get_main ();
33c6eaae
TT
588 /* Choose the first "main" we see. We only do this for names
589 not requiring canonicalization. At this point in the process
590 names might not have been canonicalized. However, currently,
591 languages that require this step also do not use
592 DW_AT_main_subprogram. An assert is appropriate here because
593 this filtering is done in get_main. */
594 if (entry != nullptr)
47fe57c9 595 {
33c6eaae
TT
596 if ((entry->flags & IS_MAIN) != 0)
597 {
5902fa8a 598 if (!language_requires_canonicalization (entry->lang))
33c6eaae
TT
599 {
600 /* There won't be one better than this. */
601 return entry;
602 }
603 }
604 else
605 {
606 /* This is one that is named "main". Here we don't care
607 if the language requires canonicalization, due to how
608 the entry is detected. Entries like this have worse
609 priority than IS_MAIN entries. */
610 if (best_entry == nullptr)
611 best_entry = entry;
612 }
47fe57c9 613 }
20a26f4e
TT
614 }
615
33c6eaae 616 return best_entry;
20a26f4e 617}
ac37b79c 618
7d82b08e
SM
619/* See cooked-index.h. */
620
621void
33c6eaae 622cooked_index::dump (gdbarch *arch)
7d82b08e 623{
8f258a6c
TV
624 auto_obstack temp_storage;
625
7d82b08e
SM
626 gdb_printf (" entries:\n");
627 gdb_printf ("\n");
628
629 size_t i = 0;
630 for (const cooked_index_entry *entry : this->all_entries ())
631 {
632 QUIT;
633
634 gdb_printf (" [%zu] ((cooked_index_entry *) %p)\n", i++, entry);
635 gdb_printf (" name: %s\n", entry->name);
636 gdb_printf (" canonical: %s\n", entry->canonical);
8f258a6c 637 gdb_printf (" qualified: %s\n", entry->full_name (&temp_storage, false));
7d82b08e
SM
638 gdb_printf (" DWARF tag: %s\n", dwarf_tag_name (entry->tag));
639 gdb_printf (" flags: %s\n", to_string (entry->flags).c_str ());
b8a175b4 640 gdb_printf (" DIE offset: %s\n", sect_offset_str (entry->die_offset));
7d82b08e 641
42bd6b5f
TV
642 if ((entry->flags & IS_PARENT_DEFERRED) != 0)
643 gdb_printf (" parent: deferred (%" PRIx64 ")\n",
644 entry->get_deferred_parent ());
645 else if (entry->get_parent () != nullptr)
7d82b08e 646 gdb_printf (" parent: ((cooked_index_entry *) %p) [%s]\n",
850fce8b 647 entry->get_parent (), entry->get_parent ()->name);
7d82b08e
SM
648 else
649 gdb_printf (" parent: ((cooked_index_entry *) 0)\n");
650
651 gdb_printf ("\n");
652 }
653
654 const cooked_index_entry *main_entry = this->get_main ();
655 if (main_entry != nullptr)
656 gdb_printf (" main: ((cooked_index_entry *) %p) [%s]\n", main_entry,
657 main_entry->name);
658 else
659 gdb_printf (" main: ((cooked_index_entry *) 0)\n");
660
661 gdb_printf ("\n");
662 gdb_printf (" address maps:\n");
663 gdb_printf ("\n");
664
665 std::vector<const addrmap *> addrmaps = this->get_addrmaps ();
666 for (i = 0; i < addrmaps.size (); ++i)
667 {
668 const addrmap &addrmap = *addrmaps[i];
669
670 gdb_printf (" [%zu] ((addrmap *) %p)\n", i, &addrmap);
671 gdb_printf ("\n");
672
673 addrmap.foreach ([arch] (CORE_ADDR start_addr, const void *obj)
674 {
675 QUIT;
676
677 const char *start_addr_str = paddress (arch, start_addr);
678
679 if (obj != nullptr)
680 {
681 const dwarf2_per_cu_data *per_cu
682 = static_cast<const dwarf2_per_cu_data *> (obj);
683 gdb_printf (" [%s] ((dwarf2_per_cu_data *) %p)\n",
684 start_addr_str, per_cu);
685 }
686 else
687 gdb_printf (" [%s] ((dwarf2_per_cu_data *) 0)\n",
688 start_addr_str);
689
690 return 0;
691 });
692
693 gdb_printf ("\n");
694 }
695}
696
52e5e48e 697void
8adc5522
TV
698cooked_index::maybe_write_index (dwarf2_per_bfd *per_bfd,
699 const index_cache_store_context &ctx)
52e5e48e 700{
52e5e48e 701 /* (maybe) store an index in the cache. */
33c6eaae
TT
702 global_index_cache.store (m_per_bfd, ctx);
703 m_state->set (cooked_state::CACHE_DONE);
52e5e48e
TT
704}
705
706/* Wait for all the index cache entries to be written before gdb
707 exits. */
708static void
709wait_for_index_cache (int)
710{
711 gdb_assert (is_main_thread ());
712 for (cooked_index *item : active_vectors)
713 item->wait_completely ();
714}
715
f0c3dcc1
TT
716/* A maint command to wait for the cache. */
717
718static void
719maintenance_wait_for_index_cache (const char *args, int from_tty)
720{
721 wait_for_index_cache (0);
722}
723
ac37b79c
TT
724void _initialize_cooked_index ();
725void
726_initialize_cooked_index ()
727{
728#if GDB_SELF_TEST
729 selftests::register_test ("cooked_index_entry::compare", test_compare);
730#endif
52e5e48e 731
f0c3dcc1
TT
732 add_cmd ("wait-for-index-cache", class_maintenance,
733 maintenance_wait_for_index_cache, _("\
4779ed97
TT
734Wait until all pending writes to the index cache have completed.\n\
735Usage: maintenance wait-for-index-cache"),
f0c3dcc1
TT
736 &maintenancelist);
737
52e5e48e 738 gdb::observers::gdb_exiting.attach (wait_for_index_cache, "cooked-index");
ac37b79c 739}