#include "gdbsupport/gdb_obstack.h"
#include "addrmap.h"
#include "gdbsupport/iterator-range.h"
+#include "gdbsupport/thread-pool.h"
+#include "dwarf2/mapped-index.h"
+#include "dwarf2/tag.h"
+#include "gdbsupport/range-chain.h"
struct dwarf2_per_cu_data;
switch (kind)
{
case VARIABLES_DOMAIN:
- return tag == DW_TAG_variable;
+ return (tag == DW_TAG_variable
+ || tag == DW_TAG_constant
+ || tag == DW_TAG_enumerator);
case FUNCTIONS_DOMAIN:
return tag == DW_TAG_subprogram;
case TYPES_DOMAIN:
- return tag == DW_TAG_typedef || tag == DW_TAG_structure_type;
+ return tag_is_type (tag);
case MODULES_DOMAIN:
return tag == DW_TAG_module;
}
void write_scope (struct obstack *storage, const char *sep) const;
};
+class cooked_index_vector;
+
/* An index of interesting DIEs. This is "cooked", in contrast to a
mapped .debug_names or .gdb_index, which are "raw". An entry in
the index is of type cooked_index_entry.
{
public:
cooked_index () = default;
- explicit cooked_index (cooked_index &&other) = default;
DISABLE_COPY_AND_ASSIGN (cooked_index);
- cooked_index &operator= (cooked_index &&other) = default;
/* Create a new cooked_index_entry and register it with this object.
Entries are owned by this object. The new item is returned. */
const cooked_index_entry *parent_entry,
dwarf2_per_cu_data *per_cu);
- /* Return the entry that is believed to represent the program's
- "main". This will return NULL if no such entry is available. */
- const cooked_index_entry *get_main () const
- {
- return m_main;
- }
-
/* Install a new fixed addrmap from the given mutable addrmap. */
- void install_addrmap (addrmap *map)
+ void install_addrmap (addrmap_mutable *map)
{
gdb_assert (m_addrmap == nullptr);
- m_addrmap = addrmap_create_fixed (map, &m_storage);
- }
-
- /* Look up ADDR in the address map, and return either the
- corresponding CU, or nullptr if the address could not be
- found. */
- dwarf2_per_cu_data *lookup (CORE_ADDR addr)
- {
- return (dwarf2_per_cu_data *) addrmap_find (m_addrmap, addr);
+ m_addrmap = new (&m_storage) addrmap_fixed (&m_storage, map);
}
/* Finalize the index. This should be called a single time, when
the index has been fully populated. It enters all the entries
- into the internal hash table. */
+ into the internal table. */
void finalize ();
+ /* Wait for this index's finalization to be complete. */
+ void wait ()
+ {
+ m_future.wait ();
+ }
+
+ friend class cooked_index_vector;
+
/* A simple range over part of m_entries. */
typedef iterator_range<std::vector<cooked_index_entry *>::iterator> range;
- /* Look up an entry by name. Returns a range of all matching
- results. If COMPLETING is true, then a larger range, suitable
- for completion, will be returned. */
- range find (gdb::string_view name, bool completing);
-
/* Return a range of all the entries. */
range all_entries ()
{
+ wait ();
return { m_entries.begin (), m_entries.end () };
}
+ /* Look up an entry by name. Returns a range of all matching
+ results. If COMPLETING is true, then a larger range, suitable
+ for completion, will be returned. */
+ range find (gdb::string_view name, bool completing);
+
private:
- /* GNAT only emits mangled ("encoded") names in the DWARF, and does
- not emit the module structure. However, we need this structure
- to do lookups. This function recreates that structure for an
- existing entry. It returns the base name (last element) of the
- full decoded name. */
- gdb::unique_xmalloc_ptr<char> handle_gnat_encoded_entry
- (cooked_index_entry *entry, htab_t gnat_entries);
+ /* Return the entry that is believed to represent the program's
+ "main". This will return NULL if no such entry is available. */
+ const cooked_index_entry *get_main () const
+ {
+ return m_main;
+ }
+
+ /* Look up ADDR in the address map, and return either the
+ corresponding CU, or nullptr if the address could not be
+ found. */
+ dwarf2_per_cu_data *lookup (CORE_ADDR addr)
+ {
+ return (dwarf2_per_cu_data *) m_addrmap->find (addr);
+ }
/* Create a new cooked_index_entry and register it with this object.
Entries are owned by this object. The new item is returned. */
per_cu);
}
+ /* GNAT only emits mangled ("encoded") names in the DWARF, and does
+ not emit the module structure. However, we need this structure
+ to do lookups. This function recreates that structure for an
+ existing entry. It returns the base name (last element) of the
+ full decoded name. */
+ gdb::unique_xmalloc_ptr<char> handle_gnat_encoded_entry
+ (cooked_index_entry *entry, htab_t gnat_entries);
+
+ /* A helper method that does the work of 'finalize'. */
+ void do_finalize ();
+
/* Storage for the entries. */
auto_obstack m_storage;
/* List of all entries. */
/* If we found "main" or an entry with 'is_main' set, store it
here. */
cooked_index_entry *m_main = nullptr;
- /* Storage for canonical names. */
- std::vector<gdb::unique_xmalloc_ptr<char>> m_names;
/* The addrmap. This maps address ranges to dwarf2_per_cu_data
objects. */
addrmap *m_addrmap = nullptr;
+ /* Storage for canonical names. */
+ std::vector<gdb::unique_xmalloc_ptr<char>> m_names;
+ /* A future that tracks when the 'finalize' method is done. Note
+ that the 'get' method is never called on this future, only
+ 'wait'. */
+ gdb::future<void> m_future;
+};
+
+/* The main index of DIEs. The parallel DIE indexers create
+ cooked_index objects. Then, these are all handled to a
+ cooked_index_vector for storage and final indexing. The index is
+ made by iterating over the entries previously created. */
+
+class cooked_index_vector : public dwarf_scanner_base
+{
+public:
+
+ /* A convenience typedef for the vector that is contained in this
+ object. */
+ typedef std::vector<std::unique_ptr<cooked_index>> vec_type;
+
+ explicit cooked_index_vector (vec_type &&vec);
+ DISABLE_COPY_AND_ASSIGN (cooked_index_vector);
+
+ /* Wait until the finalization of the entire cooked_index_vector is
+ done. */
+ void wait ()
+ {
+ for (auto &item : m_vector)
+ item->wait ();
+ }
+
+ ~cooked_index_vector ()
+ {
+ /* The 'finalize' methods may be run in a different thread. If
+ this object is destroyed before these complete, then one will
+ end up writing to freed memory. Waiting for finalization to
+ complete avoids this problem; and the cost seems ignorable
+ because creating and immediately destroying the debug info is a
+ relatively rare thing to do. */
+ wait ();
+ }
+
+ /* A range over a vector of subranges. */
+ typedef range_chain<cooked_index::range> range;
+
+ /* Look up an entry by name. Returns a range of all matching
+ results. If COMPLETING is true, then a larger range, suitable
+ for completion, will be returned. */
+ range find (gdb::string_view name, bool completing);
+
+ /* Return a range of all the entries. */
+ range all_entries ()
+ {
+ std::vector<cooked_index::range> result_range;
+ result_range.reserve (m_vector.size ());
+ for (auto &entry : m_vector)
+ result_range.push_back (entry->all_entries ());
+ return range (std::move (result_range));
+ }
+
+ /* Look up ADDR in the address map, and return either the
+ corresponding CU, or nullptr if the address could not be
+ found. */
+ dwarf2_per_cu_data *lookup (CORE_ADDR addr);
+
+ /* Return a new vector of all the addrmaps used by all the indexes
+ held by this object. */
+ std::vector<addrmap *> get_addrmaps ();
+
+ /* Return the entry that is believed to represent the program's
+ "main". This will return NULL if no such entry is available. */
+ const cooked_index_entry *get_main () const;
+
+ cooked_index_vector *index_for_writing () override
+ {
+ return this;
+ }
+
+ quick_symbol_functions_up make_quick_functions () const override;
+
+private:
+
+ /* The vector of cooked_index objects. This is stored because the
+ entries are stored on the obstacks in those objects. */
+ vec_type m_vector;
};
#endif /* GDB_DWARF2_COOKED_INDEX_H */