]>
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 | ||
20 | #ifndef GDB_DWARF2_COOKED_INDEX_H | |
21 | #define GDB_DWARF2_COOKED_INDEX_H | |
22 | ||
23 | #include "dwarf2.h" | |
1298c32f | 24 | #include "dwarf2/types.h" |
51f5a4b8 TT |
25 | #include "symtab.h" |
26 | #include "hashtab.h" | |
27 | #include "dwarf2/index-common.h" | |
8082468f | 28 | #include <string_view> |
51f5a4b8 TT |
29 | #include "quick-symbol.h" |
30 | #include "gdbsupport/gdb_obstack.h" | |
31 | #include "addrmap.h" | |
32 | #include "gdbsupport/iterator-range.h" | |
46114cb7 | 33 | #include "gdbsupport/thread-pool.h" |
6606799f | 34 | #include "dwarf2/mapped-index.h" |
33c6eaae | 35 | #include "dwarf2/read.h" |
446fcb44 | 36 | #include "dwarf2/tag.h" |
a274da12 | 37 | #include "dwarf2/abbrev-cache.h" |
20a26f4e | 38 | #include "gdbsupport/range-chain.h" |
33c6eaae TT |
39 | #include "gdbsupport/task-group.h" |
40 | #include "complaints.h" | |
41 | #include "run-on-main-thread.h" | |
42 | ||
43 | #if CXX_STD_THREAD | |
44 | #include <mutex> | |
45 | #include <condition_variable> | |
46 | #endif /* CXX_STD_THREAD */ | |
51f5a4b8 TT |
47 | |
48 | struct dwarf2_per_cu_data; | |
52e5e48e | 49 | struct dwarf2_per_bfd; |
8adc5522 | 50 | struct index_cache_store_context; |
42bd6b5f | 51 | struct cooked_index_entry; |
51f5a4b8 TT |
52 | |
53 | /* Flags that describe an entry in the index. */ | |
54 | enum cooked_index_flag_enum : unsigned char | |
55 | { | |
56 | /* True if this entry is the program's "main". */ | |
57 | IS_MAIN = 1, | |
58 | /* True if this entry represents a "static" object. */ | |
59 | IS_STATIC = 2, | |
60 | /* True if this entry is an "enum class". */ | |
61 | IS_ENUM_CLASS = 4, | |
62 | /* True if this entry uses the linkage name. */ | |
63 | IS_LINKAGE = 8, | |
2afd002a TT |
64 | /* True if this entry is just for the declaration of a type, not the |
65 | definition. */ | |
66 | IS_TYPE_DECLARATION = 16, | |
42bd6b5f TV |
67 | /* True is parent_entry.deferred has a value rather than parent_entry |
68 | .resolved. */ | |
69 | IS_PARENT_DEFERRED = 32, | |
51f5a4b8 TT |
70 | }; |
71 | DEF_ENUM_FLAGS_TYPE (enum cooked_index_flag_enum, cooked_index_flag); | |
72 | ||
42bd6b5f TV |
73 | /* Type representing either a resolved or deferred cooked_index_entry. */ |
74 | ||
75 | union cooked_index_entry_ref | |
76 | { | |
77 | cooked_index_entry_ref (CORE_ADDR deferred_) | |
78 | { | |
79 | deferred = deferred_; | |
80 | } | |
81 | ||
82 | cooked_index_entry_ref (const cooked_index_entry *resolved_) | |
83 | { | |
84 | resolved = resolved_; | |
85 | } | |
86 | ||
87 | const cooked_index_entry *resolved; | |
88 | CORE_ADDR deferred; | |
89 | }; | |
90 | ||
7d82b08e SM |
91 | /* Return a string representation of FLAGS. */ |
92 | ||
93 | std::string to_string (cooked_index_flag flags); | |
94 | ||
47fe57c9 TT |
95 | /* Return true if LANG requires canonicalization. This is used |
96 | primarily to work around an issue computing the name of "main". | |
97 | This function must be kept in sync with | |
33c6eaae | 98 | cooked_index_shard::finalize. */ |
47fe57c9 TT |
99 | |
100 | extern bool language_requires_canonicalization (enum language lang); | |
101 | ||
51f5a4b8 TT |
102 | /* A cooked_index_entry represents a single item in the index. Note |
103 | that two entries can be created for the same DIE -- one using the | |
104 | name, and another one using the linkage name, if any. | |
105 | ||
106 | This is an "open" class and the members are all directly | |
107 | accessible. It is read-only after the index has been fully read | |
108 | and processed. */ | |
109 | struct cooked_index_entry : public allocate_on_obstack | |
110 | { | |
111 | cooked_index_entry (sect_offset die_offset_, enum dwarf_tag tag_, | |
112 | cooked_index_flag flags_, const char *name_, | |
42bd6b5f | 113 | cooked_index_entry_ref parent_entry_, |
51f5a4b8 TT |
114 | dwarf2_per_cu_data *per_cu_) |
115 | : name (name_), | |
116 | tag (tag_), | |
117 | flags (flags_), | |
118 | die_offset (die_offset_), | |
850fce8b TV |
119 | per_cu (per_cu_), |
120 | m_parent_entry (parent_entry_) | |
51f5a4b8 TT |
121 | { |
122 | } | |
123 | ||
124 | /* Return true if this entry matches SEARCH_FLAGS. */ | |
125 | bool matches (block_search_flags search_flags) const | |
126 | { | |
2afd002a TT |
127 | /* Just reject type declarations. */ |
128 | if ((flags & IS_TYPE_DECLARATION) != 0) | |
129 | return false; | |
130 | ||
51f5a4b8 TT |
131 | if ((search_flags & SEARCH_STATIC_BLOCK) != 0 |
132 | && (flags & IS_STATIC) != 0) | |
133 | return true; | |
134 | if ((search_flags & SEARCH_GLOBAL_BLOCK) != 0 | |
135 | && (flags & IS_STATIC) == 0) | |
136 | return true; | |
137 | return false; | |
138 | } | |
139 | ||
140 | /* Return true if this entry matches DOMAIN. */ | |
141 | bool matches (domain_enum domain) const | |
142 | { | |
2afd002a TT |
143 | /* Just reject type declarations. */ |
144 | if ((flags & IS_TYPE_DECLARATION) != 0) | |
145 | return false; | |
146 | ||
51f5a4b8 TT |
147 | switch (domain) |
148 | { | |
149 | case LABEL_DOMAIN: | |
150 | return false; | |
151 | ||
152 | case MODULE_DOMAIN: | |
153 | return tag == DW_TAG_module; | |
154 | ||
155 | case COMMON_BLOCK_DOMAIN: | |
156 | return tag == DW_TAG_common_block; | |
157 | } | |
158 | ||
159 | return true; | |
160 | } | |
161 | ||
162 | /* Return true if this entry matches KIND. */ | |
163 | bool matches (enum search_domain kind) const | |
164 | { | |
2afd002a TT |
165 | /* Just reject type declarations. */ |
166 | if ((flags & IS_TYPE_DECLARATION) != 0) | |
167 | return false; | |
168 | ||
51f5a4b8 TT |
169 | switch (kind) |
170 | { | |
171 | case VARIABLES_DOMAIN: | |
446fcb44 TT |
172 | return (tag == DW_TAG_variable |
173 | || tag == DW_TAG_constant | |
174 | || tag == DW_TAG_enumerator); | |
51f5a4b8 | 175 | case FUNCTIONS_DOMAIN: |
3396471b NCK |
176 | return (tag == DW_TAG_subprogram |
177 | || tag == DW_TAG_entry_point); | |
51f5a4b8 | 178 | case TYPES_DOMAIN: |
446fcb44 | 179 | return tag_is_type (tag); |
51f5a4b8 TT |
180 | case MODULES_DOMAIN: |
181 | return tag == DW_TAG_module; | |
182 | } | |
183 | ||
184 | return true; | |
185 | } | |
186 | ||
187 | /* Construct the fully-qualified name of this entry and return a | |
188 | pointer to it. If allocation is needed, it will be done on | |
47fe57c9 TT |
189 | STORAGE. FOR_MAIN is true if we are computing the name of the |
190 | "main" entry -- one marked DW_AT_main_subprogram. This matters | |
191 | for avoiding name canonicalization and also a related race (if | |
192 | "main" computation is done during finalization). */ | |
193 | const char *full_name (struct obstack *storage, bool for_main = false) const; | |
51f5a4b8 | 194 | |
c121e82c TT |
195 | /* Comparison modes for the 'compare' function. See the function |
196 | for a description. */ | |
197 | enum comparison_mode | |
198 | { | |
199 | MATCH, | |
200 | SORT, | |
201 | COMPLETE, | |
202 | }; | |
203 | ||
204 | /* Compare two strings, case-insensitively. Return -1 if STRA is | |
205 | less than STRB, 0 if they are equal, and 1 if STRA is greater. | |
206 | ||
207 | When comparing, '<' is considered to be less than all other | |
208 | printable characters. This ensures that "t<x>" sorts before | |
209 | "t1", which is necessary when looking up "t". This '<' handling | |
210 | is to ensure that certain C++ lookups work correctly. It is | |
211 | inexact, and applied regardless of the search language, but this | |
212 | is ok because callers of this code do more precise filtering | |
213 | according to their needs. This is also why using a | |
214 | case-insensitive comparison works even for languages that are | |
215 | case sensitive. | |
216 | ||
217 | MODE controls how the comparison proceeds. | |
218 | ||
219 | MODE==SORT is used when sorting and the only special '<' handling | |
220 | that it does is to ensure that '<' sorts before all other | |
221 | printable characters. This ensures that the resulting ordering | |
222 | will be binary-searchable. | |
223 | ||
224 | MODE==MATCH is used when searching for a symbol. In this case, | |
225 | STRB must always be the search name, and STRA must be the name in | |
226 | the index that is under consideration. In compare mode, early | |
227 | termination of STRB may match STRA -- for example, "t<int>" and | |
228 | "t" will be considered to be equal. (However, if A=="t" and | |
229 | B=="t<int>", then this will not consider them as equal.) | |
230 | ||
231 | MODE==COMPLETE is used when searching for a symbol for | |
232 | completion. In this case, STRB must always be the search name, | |
233 | and STRA must be the name in the index that is under | |
234 | consideration. In completion mode, early termination of STRB | |
235 | always results in a match. */ | |
236 | static int compare (const char *stra, const char *strb, | |
237 | comparison_mode mode); | |
ac37b79c TT |
238 | |
239 | /* Compare two entries by canonical name. */ | |
51f5a4b8 TT |
240 | bool operator< (const cooked_index_entry &other) const |
241 | { | |
c121e82c | 242 | return compare (canonical, other.canonical, SORT) < 0; |
51f5a4b8 TT |
243 | } |
244 | ||
850fce8b TV |
245 | /* Set parent entry to PARENT. */ |
246 | void set_parent (const cooked_index_entry *parent) | |
247 | { | |
42bd6b5f TV |
248 | gdb_assert ((flags & IS_PARENT_DEFERRED) == 0); |
249 | m_parent_entry.resolved = parent; | |
250 | } | |
251 | ||
252 | /* Resolve deferred parent entry to PARENT. */ | |
253 | void resolve_parent (const cooked_index_entry *parent) | |
254 | { | |
255 | gdb_assert ((flags & IS_PARENT_DEFERRED) != 0); | |
256 | flags = flags & ~IS_PARENT_DEFERRED; | |
257 | m_parent_entry.resolved = parent; | |
850fce8b TV |
258 | } |
259 | ||
260 | /* Return parent entry. */ | |
261 | const cooked_index_entry *get_parent () const | |
262 | { | |
42bd6b5f TV |
263 | gdb_assert ((flags & IS_PARENT_DEFERRED) == 0); |
264 | return m_parent_entry.resolved; | |
265 | } | |
266 | ||
267 | /* Return deferred parent entry. */ | |
268 | CORE_ADDR get_deferred_parent () const | |
269 | { | |
270 | gdb_assert ((flags & IS_PARENT_DEFERRED) != 0); | |
271 | return m_parent_entry.deferred; | |
850fce8b TV |
272 | } |
273 | ||
51f5a4b8 TT |
274 | /* The name as it appears in DWARF. This always points into one of |
275 | the mapped DWARF sections. Note that this may be the name or the | |
276 | linkage name -- two entries are created for DIEs which have both | |
277 | attributes. */ | |
278 | const char *name; | |
279 | /* The canonical name. For C++ names, this may differ from NAME. | |
280 | In all other cases, this is equal to NAME. */ | |
281 | const char *canonical = nullptr; | |
282 | /* The DWARF tag. */ | |
283 | enum dwarf_tag tag; | |
284 | /* Any flags attached to this entry. */ | |
285 | cooked_index_flag flags; | |
286 | /* The offset of this DIE. */ | |
287 | sect_offset die_offset; | |
51f5a4b8 TT |
288 | /* The CU from which this entry originates. */ |
289 | dwarf2_per_cu_data *per_cu; | |
290 | ||
291 | private: | |
292 | ||
47fe57c9 TT |
293 | /* A helper method for full_name. Emits the full scope of this |
294 | object, followed by the separator, to STORAGE. If this entry has | |
295 | a parent, its write_scope method is called first. */ | |
296 | void write_scope (struct obstack *storage, const char *sep, | |
297 | bool for_name) const; | |
850fce8b TV |
298 | |
299 | /* The parent entry. This is NULL for top-level entries. | |
300 | Otherwise, it points to the parent entry, such as a namespace or | |
301 | class. */ | |
42bd6b5f | 302 | cooked_index_entry_ref m_parent_entry; |
51f5a4b8 TT |
303 | }; |
304 | ||
19455ee1 | 305 | class cooked_index; |
46114cb7 | 306 | |
51f5a4b8 TT |
307 | /* An index of interesting DIEs. This is "cooked", in contrast to a |
308 | mapped .debug_names or .gdb_index, which are "raw". An entry in | |
309 | the index is of type cooked_index_entry. | |
310 | ||
311 | Operations on the index are described below. They are chosen to | |
312 | make it relatively simple to implement the symtab "quick" | |
313 | methods. */ | |
a8dc6718 | 314 | class cooked_index_shard |
51f5a4b8 TT |
315 | { |
316 | public: | |
a8dc6718 SM |
317 | cooked_index_shard () = default; |
318 | DISABLE_COPY_AND_ASSIGN (cooked_index_shard); | |
51f5a4b8 TT |
319 | |
320 | /* Create a new cooked_index_entry and register it with this object. | |
321 | Entries are owned by this object. The new item is returned. */ | |
920bcec0 TV |
322 | cooked_index_entry *add (sect_offset die_offset, enum dwarf_tag tag, |
323 | cooked_index_flag flags, | |
324 | const char *name, | |
42bd6b5f | 325 | cooked_index_entry_ref parent_entry, |
920bcec0 | 326 | dwarf2_per_cu_data *per_cu); |
51f5a4b8 | 327 | |
51f5a4b8 | 328 | /* Install a new fixed addrmap from the given mutable addrmap. */ |
d89120e9 | 329 | void install_addrmap (addrmap_mutable *map) |
51f5a4b8 TT |
330 | { |
331 | gdb_assert (m_addrmap == nullptr); | |
d89120e9 | 332 | m_addrmap = new (&m_storage) addrmap_fixed (&m_storage, map); |
51f5a4b8 TT |
333 | } |
334 | ||
19455ee1 | 335 | friend class cooked_index; |
46114cb7 | 336 | |
20a26f4e | 337 | /* A simple range over part of m_entries. */ |
35e17631 TT |
338 | typedef iterator_range<std::vector<cooked_index_entry *>::const_iterator> |
339 | range; | |
20a26f4e TT |
340 | |
341 | /* Return a range of all the entries. */ | |
35e17631 | 342 | range all_entries () const |
20a26f4e | 343 | { |
35e17631 | 344 | return { m_entries.cbegin (), m_entries.cend () }; |
20a26f4e TT |
345 | } |
346 | ||
347 | /* Look up an entry by name. Returns a range of all matching | |
348 | results. If COMPLETING is true, then a larger range, suitable | |
349 | for completion, will be returned. */ | |
35e17631 | 350 | range find (const std::string &name, bool completing) const; |
20a26f4e | 351 | |
46114cb7 TT |
352 | private: |
353 | ||
354 | /* Return the entry that is believed to represent the program's | |
355 | "main". This will return NULL if no such entry is available. */ | |
356 | const cooked_index_entry *get_main () const | |
357 | { | |
358 | return m_main; | |
359 | } | |
360 | ||
51f5a4b8 TT |
361 | /* Look up ADDR in the address map, and return either the |
362 | corresponding CU, or nullptr if the address could not be | |
363 | found. */ | |
bdb4b803 | 364 | dwarf2_per_cu_data *lookup (unrelocated_addr addr) |
51f5a4b8 | 365 | { |
bdb4b803 TT |
366 | return (static_cast<dwarf2_per_cu_data *> |
367 | (m_addrmap->find ((CORE_ADDR) addr))); | |
51f5a4b8 TT |
368 | } |
369 | ||
46114cb7 TT |
370 | /* Create a new cooked_index_entry and register it with this object. |
371 | Entries are owned by this object. The new item is returned. */ | |
372 | cooked_index_entry *create (sect_offset die_offset, | |
373 | enum dwarf_tag tag, | |
374 | cooked_index_flag flags, | |
375 | const char *name, | |
42bd6b5f | 376 | cooked_index_entry_ref parent_entry, |
46114cb7 TT |
377 | dwarf2_per_cu_data *per_cu) |
378 | { | |
379 | return new (&m_storage) cooked_index_entry (die_offset, tag, flags, | |
380 | name, parent_entry, | |
381 | per_cu); | |
382 | } | |
383 | ||
20a26f4e TT |
384 | /* GNAT only emits mangled ("encoded") names in the DWARF, and does |
385 | not emit the module structure. However, we need this structure | |
386 | to do lookups. This function recreates that structure for an | |
387 | existing entry. It returns the base name (last element) of the | |
388 | full decoded name. */ | |
389 | gdb::unique_xmalloc_ptr<char> handle_gnat_encoded_entry | |
390 | (cooked_index_entry *entry, htab_t gnat_entries); | |
391 | ||
33c6eaae TT |
392 | /* Finalize the index. This should be called a single time, when |
393 | the index has been fully populated. It enters all the entries | |
394 | into the internal table. This may be invoked in a worker | |
395 | thread. */ | |
396 | void finalize (); | |
20a26f4e | 397 | |
46114cb7 TT |
398 | /* Storage for the entries. */ |
399 | auto_obstack m_storage; | |
400 | /* List of all entries. */ | |
401 | std::vector<cooked_index_entry *> m_entries; | |
47fe57c9 | 402 | /* If we found an entry with 'is_main' set, store it here. */ |
46114cb7 | 403 | cooked_index_entry *m_main = nullptr; |
46114cb7 TT |
404 | /* The addrmap. This maps address ranges to dwarf2_per_cu_data |
405 | objects. */ | |
406 | addrmap *m_addrmap = nullptr; | |
20a26f4e TT |
407 | /* Storage for canonical names. */ |
408 | std::vector<gdb::unique_xmalloc_ptr<char>> m_names; | |
46114cb7 TT |
409 | }; |
410 | ||
a274da12 TT |
411 | class cutu_reader; |
412 | ||
413 | /* An instance of this is created when scanning DWARF to create a | |
414 | cooked index. */ | |
415 | ||
416 | class cooked_index_storage | |
417 | { | |
418 | public: | |
419 | ||
420 | cooked_index_storage (); | |
421 | DISABLE_COPY_AND_ASSIGN (cooked_index_storage); | |
422 | ||
423 | /* Return the current abbrev cache. */ | |
424 | abbrev_cache *get_abbrev_cache () | |
425 | { | |
426 | return &m_abbrev_cache; | |
427 | } | |
428 | ||
429 | /* Return the DIE reader corresponding to PER_CU. If no such reader | |
430 | has been registered, return NULL. */ | |
431 | cutu_reader *get_reader (dwarf2_per_cu_data *per_cu); | |
432 | ||
433 | /* Preserve READER by storing it in the local hash table. */ | |
434 | cutu_reader *preserve (std::unique_ptr<cutu_reader> reader); | |
435 | ||
436 | /* Add an entry to the index. The arguments describe the entry; see | |
437 | cooked-index.h. The new entry is returned. */ | |
920bcec0 TV |
438 | cooked_index_entry *add (sect_offset die_offset, enum dwarf_tag tag, |
439 | cooked_index_flag flags, | |
440 | const char *name, | |
42bd6b5f | 441 | cooked_index_entry_ref parent_entry, |
920bcec0 | 442 | dwarf2_per_cu_data *per_cu) |
a274da12 TT |
443 | { |
444 | return m_index->add (die_offset, tag, flags, name, parent_entry, per_cu); | |
445 | } | |
446 | ||
447 | /* Install the current addrmap into the shard being constructed, | |
448 | then transfer ownership of the index to the caller. */ | |
449 | std::unique_ptr<cooked_index_shard> release () | |
450 | { | |
451 | m_index->install_addrmap (&m_addrmap); | |
452 | return std::move (m_index); | |
453 | } | |
454 | ||
455 | /* Return the mutable addrmap that is currently being created. */ | |
456 | addrmap_mutable *get_addrmap () | |
457 | { | |
458 | return &m_addrmap; | |
459 | } | |
460 | ||
461 | private: | |
462 | ||
463 | /* Hash function for a cutu_reader. */ | |
464 | static hashval_t hash_cutu_reader (const void *a); | |
465 | ||
466 | /* Equality function for cutu_reader. */ | |
467 | static int eq_cutu_reader (const void *a, const void *b); | |
468 | ||
469 | /* The abbrev cache used by this indexer. */ | |
470 | abbrev_cache m_abbrev_cache; | |
471 | /* A hash table of cutu_reader objects. */ | |
472 | htab_up m_reader_hash; | |
473 | /* The index shard that is being constructed. */ | |
474 | std::unique_ptr<cooked_index_shard> m_index; | |
475 | ||
476 | /* A writeable addrmap being constructed by this scanner. */ | |
477 | addrmap_mutable m_addrmap; | |
478 | }; | |
479 | ||
33c6eaae TT |
480 | /* The possible states of the index. See the explanatory comment |
481 | before cooked_index for more details. */ | |
482 | enum class cooked_state | |
483 | { | |
484 | /* The default state. This is not a valid argument to 'wait'. */ | |
485 | INITIAL, | |
486 | /* The initial scan has completed. The name of "main" is now | |
487 | available (if known). The addrmaps are usable now. | |
488 | Finalization has started but is not complete. */ | |
489 | MAIN_AVAILABLE, | |
490 | /* Finalization has completed. This means the index is fully | |
491 | available for queries. */ | |
492 | FINALIZED, | |
493 | /* Writing to the index cache has finished. */ | |
494 | CACHE_DONE, | |
495 | }; | |
496 | ||
497 | /* An object of this type controls the scanning of the DWARF. It | |
498 | schedules the worker tasks and tracks the current state. Once | |
499 | scanning is done, this object is discarded. */ | |
500 | ||
501 | class cooked_index_worker | |
502 | { | |
503 | public: | |
504 | ||
505 | explicit cooked_index_worker (dwarf2_per_objfile *per_objfile); | |
506 | DISABLE_COPY_AND_ASSIGN (cooked_index_worker); | |
507 | ||
508 | /* Start reading. */ | |
509 | void start (); | |
510 | ||
511 | /* Wait for a particular state to be achieved. If ALLOW_QUIT is | |
512 | true, then the loop will check the QUIT flag. Normally this | |
513 | method may only be called from the main thread; however, it can | |
514 | be called from a worker thread provided that the desired state | |
515 | has already been attained. (This oddity is used by the index | |
516 | cache writer.) */ | |
517 | bool wait (cooked_state desired_state, bool allow_quit); | |
518 | ||
519 | private: | |
520 | ||
521 | /* Let cooked_index call the 'set' method. */ | |
522 | friend class cooked_index; | |
523 | void set (cooked_state desired_state); | |
524 | ||
525 | /* Start reading DWARF. This can be run in a worker thread without | |
526 | problems. */ | |
527 | void start_reading (); | |
528 | ||
529 | /* Helper function that does most of the work for start_reading. */ | |
530 | void do_reading (); | |
531 | ||
532 | /* After the last DWARF-reading task has finished, this function | |
533 | does the remaining work to finish the scan. */ | |
534 | void done_reading (); | |
535 | ||
536 | /* An iterator for the comp units. */ | |
537 | typedef std::vector<dwarf2_per_cu_data_up>::iterator unit_iterator; | |
538 | ||
539 | /* Process a batch of CUs. This may be called multiple times in | |
540 | separate threads. TASK_NUMBER indicates which task this is -- | |
541 | the result is stored in that slot of M_RESULTS. */ | |
542 | void process_cus (size_t task_number, unit_iterator first, | |
543 | unit_iterator end); | |
544 | ||
545 | /* Each thread returns a tuple holding a cooked index, any collected | |
546 | complaints, and a vector of errors that should be printed. The | |
547 | latter is done because GDB's I/O system is not thread-safe. | |
548 | run_on_main_thread could be used, but that would mean the | |
549 | messages are printed after the prompt, which looks weird. */ | |
550 | using result_type = std::tuple<std::unique_ptr<cooked_index_shard>, | |
551 | complaint_collection, | |
552 | std::vector<gdb_exception>>; | |
553 | ||
554 | /* The per-objfile object. */ | |
555 | dwarf2_per_objfile *m_per_objfile; | |
556 | /* A storage object for "leftovers" -- see the 'start' method, but | |
557 | essentially things not parsed during the normal CU parsing | |
558 | passes. */ | |
559 | cooked_index_storage m_index_storage; | |
560 | /* Result of each worker task. */ | |
561 | std::vector<result_type> m_results; | |
562 | /* Any warnings emitted. This is not in 'result_type' because (for | |
563 | the time being at least), it's only needed in do_reading, not in | |
564 | every worker. Note that deferred_warnings uses gdb_stderr in its | |
565 | constructor, and this should only be done from the main thread. | |
566 | This is enforced in the cooked_index_worker constructor. */ | |
567 | deferred_warnings m_warnings; | |
568 | ||
569 | #if CXX_STD_THREAD | |
570 | /* Current state of this object. */ | |
571 | cooked_state m_state = cooked_state::INITIAL; | |
8baaed84 TT |
572 | /* Mutex and condition variable used to synchronize. */ |
573 | std::mutex m_mutex; | |
574 | std::condition_variable m_cond; | |
575 | #endif /* CXX_STD_THREAD */ | |
33c6eaae TT |
576 | /* This flag indicates whether any complaints or exceptions that |
577 | arose during scanning have been reported by 'wait'. This may | |
578 | only be modified on the main thread. */ | |
579 | bool m_reported = false; | |
33c6eaae TT |
580 | /* If set, an exception occurred during start_reading; in this case |
581 | the scanning is stopped and this exception will later be reported | |
582 | by the 'wait' method. */ | |
583 | std::optional<gdb_exception> m_failed; | |
33c6eaae TT |
584 | }; |
585 | ||
586 | /* The main index of DIEs. | |
587 | ||
588 | The index is created by multiple threads. The overall process is | |
589 | somewhat complicated, so here's a diagram to help sort it out. | |
590 | ||
591 | The basic idea behind this design is (1) to do as much work as | |
592 | possible in worker threads, and (2) to start the work as early as | |
593 | possible. This combination should help hide the effort from the | |
594 | user to the maximum possible degree. | |
595 | ||
596 | . Main Thread | Worker Threads | |
597 | ============================================================ | |
598 | . dwarf2_initialize_objfile | |
599 | . | | |
600 | . v | |
601 | . cooked index ------------> cooked_index_worker::start | |
602 | . | / | \ | |
603 | . v / | \ | |
604 | . install / | \ | |
605 | . cooked_index_functions scan CUs in workers | |
606 | . | create cooked_index_shard objects | |
607 | . | \ | / | |
608 | . v \|/ | |
609 | . return to caller v | |
610 | . initial scan is done | |
611 | . state = MAIN_AVAILABLE | |
612 | . "main" name now available | |
613 | . | | |
614 | . | | |
615 | . if main thread calls... v | |
616 | . compute_main_name cooked_index::set_contents | |
617 | . | / | \ | |
618 | . v / | \ | |
619 | . wait (MAIN_AVAILABLE) finalization | |
620 | . | \ | / | |
621 | . v \ | / | |
622 | . done state = FINALIZED | |
623 | . | | |
624 | . v | |
625 | . maybe write to index cache | |
626 | . state = CACHE_DONE | |
627 | . | |
628 | . | |
629 | . if main thread calls... | |
630 | . any other "quick" API | |
631 | . | | |
632 | . v | |
633 | . wait (FINALIZED) | |
634 | . | | |
635 | . v | |
636 | . use the index | |
637 | */ | |
46114cb7 | 638 | |
19455ee1 | 639 | class cooked_index : public dwarf_scanner_base |
46114cb7 TT |
640 | { |
641 | public: | |
642 | ||
643 | /* A convenience typedef for the vector that is contained in this | |
644 | object. */ | |
a8dc6718 | 645 | using vec_type = std::vector<std::unique_ptr<cooked_index_shard>>; |
46114cb7 | 646 | |
33c6eaae | 647 | explicit cooked_index (dwarf2_per_objfile *per_objfile); |
52e5e48e | 648 | ~cooked_index () override; |
33c6eaae | 649 | |
19455ee1 | 650 | DISABLE_COPY_AND_ASSIGN (cooked_index); |
51f5a4b8 | 651 | |
33c6eaae TT |
652 | /* Start reading the DWARF. */ |
653 | void start_reading (); | |
654 | ||
655 | /* Called by cooked_index_worker to set the contents of this index | |
656 | and transition to the MAIN_AVAILABLE state. */ | |
657 | void set_contents (vec_type &&vec); | |
7d1a572d | 658 | |
20a26f4e | 659 | /* A range over a vector of subranges. */ |
a8dc6718 | 660 | using range = range_chain<cooked_index_shard::range>; |
51f5a4b8 TT |
661 | |
662 | /* Look up an entry by name. Returns a range of all matching | |
663 | results. If COMPLETING is true, then a larger range, suitable | |
664 | for completion, will be returned. */ | |
33c6eaae | 665 | range find (const std::string &name, bool completing); |
51f5a4b8 TT |
666 | |
667 | /* Return a range of all the entries. */ | |
33c6eaae | 668 | range all_entries () |
51f5a4b8 | 669 | { |
33c6eaae | 670 | wait (cooked_state::FINALIZED, true); |
a8dc6718 | 671 | std::vector<cooked_index_shard::range> result_range; |
20a26f4e TT |
672 | result_range.reserve (m_vector.size ()); |
673 | for (auto &entry : m_vector) | |
674 | result_range.push_back (entry->all_entries ()); | |
675 | return range (std::move (result_range)); | |
51f5a4b8 TT |
676 | } |
677 | ||
46114cb7 TT |
678 | /* Look up ADDR in the address map, and return either the |
679 | corresponding CU, or nullptr if the address could not be | |
680 | found. */ | |
bdb4b803 | 681 | dwarf2_per_cu_data *lookup (unrelocated_addr addr); |
46114cb7 TT |
682 | |
683 | /* Return a new vector of all the addrmaps used by all the indexes | |
684 | held by this object. */ | |
33c6eaae | 685 | std::vector<const addrmap *> get_addrmaps (); |
46114cb7 TT |
686 | |
687 | /* Return the entry that is believed to represent the program's | |
688 | "main". This will return NULL if no such entry is available. */ | |
689 | const cooked_index_entry *get_main () const; | |
690 | ||
33c6eaae TT |
691 | const char *get_main_name (struct obstack *obstack, enum language *lang) |
692 | const; | |
693 | ||
19455ee1 | 694 | cooked_index *index_for_writing () override |
758ffab4 | 695 | { |
33c6eaae | 696 | wait (cooked_state::FINALIZED, true); |
758ffab4 TT |
697 | return this; |
698 | } | |
699 | ||
6606799f TT |
700 | quick_symbol_functions_up make_quick_functions () const override; |
701 | ||
7d82b08e | 702 | /* Dump a human-readable form of the contents of the index. */ |
33c6eaae TT |
703 | void dump (gdbarch *arch); |
704 | ||
705 | /* Wait until this object reaches the desired state. Note that | |
706 | DESIRED_STATE may not be INITIAL -- it does not make sense to | |
707 | wait for this. If ALLOW_QUIT is true, timed waits will be done | |
708 | and the quit flag will be checked in a loop. This may normally | |
709 | only be called from the main thread; however, it is ok to call | |
710 | from a worker as long as the desired state has already been | |
711 | attained. (This property is needed by the index cache | |
712 | writer.) */ | |
713 | void wait (cooked_state desired_state, bool allow_quit = false); | |
7d82b08e | 714 | |
52e5e48e | 715 | void wait_completely () override |
33c6eaae | 716 | { wait (cooked_state::CACHE_DONE); } |
6f214d0f | 717 | |
51f5a4b8 TT |
718 | private: |
719 | ||
52e5e48e | 720 | /* Maybe write the index to the index cache. */ |
8adc5522 TV |
721 | void maybe_write_index (dwarf2_per_bfd *per_bfd, |
722 | const index_cache_store_context &); | |
52e5e48e | 723 | |
46114cb7 TT |
724 | /* The vector of cooked_index objects. This is stored because the |
725 | entries are stored on the obstacks in those objects. */ | |
726 | vec_type m_vector; | |
52e5e48e | 727 | |
33c6eaae TT |
728 | /* This tracks the current state. When this is nullptr, it means |
729 | that the state is CACHE_DONE -- it's important to note that only | |
730 | the main thread may change the value of this pointer. */ | |
731 | std::unique_ptr<cooked_index_worker> m_state; | |
732 | ||
733 | dwarf2_per_bfd *m_per_bfd; | |
51f5a4b8 TT |
734 | }; |
735 | ||
736 | #endif /* GDB_DWARF2_COOKED_INDEX_H */ |