aboutsummaryrefslogtreecommitdiff
path: root/gdb/dwarf2/cooked-index.h
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/dwarf2/cooked-index.h')
-rw-r--r--gdb/dwarf2/cooked-index.h499
1 files changed, 14 insertions, 485 deletions
diff --git a/gdb/dwarf2/cooked-index.h b/gdb/dwarf2/cooked-index.h
index 56c84bd..384938e 100644
--- a/gdb/dwarf2/cooked-index.h
+++ b/gdb/dwarf2/cooked-index.h
@@ -20,490 +20,16 @@
#ifndef GDB_DWARF2_COOKED_INDEX_H
#define GDB_DWARF2_COOKED_INDEX_H
-#include "dwarf2.h"
-#include "dwarf2/types.h"
+#include "dwarf2/cooked-index-entry.h"
#include "symtab.h"
-#include "hashtab.h"
#include "quick-symbol.h"
-#include "gdbsupport/gdb_obstack.h"
#include "addrmap.h"
-#include "gdbsupport/iterator-range.h"
#include "dwarf2/mapped-index.h"
#include "dwarf2/read.h"
#include "dwarf2/parent-map.h"
#include "gdbsupport/range-chain.h"
-#include "gdbsupport/string-set.h"
-#include "complaints.h"
-
-#if CXX_STD_THREAD
-#include <mutex>
-#include <condition_variable>
-#endif /* CXX_STD_THREAD */
-
-struct dwarf2_per_cu;
-struct dwarf2_per_bfd;
-struct index_cache_store_context;
-struct cooked_index_entry;
-
-/* Flags that describe an entry in the index. */
-enum cooked_index_flag_enum : unsigned char
-{
- /* True if this entry is the program's "main". */
- IS_MAIN = 1,
- /* True if this entry represents a "static" object. */
- IS_STATIC = 2,
- /* True if this entry uses the linkage name. */
- IS_LINKAGE = 4,
- /* True if this entry is just for the declaration of a type, not the
- definition. */
- IS_TYPE_DECLARATION = 8,
- /* True is parent_entry.deferred has a value rather than parent_entry
- .resolved. */
- IS_PARENT_DEFERRED = 16,
- /* True if this entry was synthesized by gdb (as opposed to coming
- directly from the DWARF). */
- IS_SYNTHESIZED = 32,
-};
-DEF_ENUM_FLAGS_TYPE (enum cooked_index_flag_enum, cooked_index_flag);
-
-/* Flags used when requesting the full name of an entry. */
-enum cooked_index_full_name_enum : unsigned char
-{
- /* Set when requesting the name of "main". See the method for the
- full description. */
- FOR_MAIN = 1,
- /* Set when requesting the linkage name for an Ada entry. */
- FOR_ADA_LINKAGE_NAME = 2,
-};
-DEF_ENUM_FLAGS_TYPE (enum cooked_index_full_name_enum, cooked_index_full_name_flag);
-
-/* Type representing either a resolved or deferred cooked_index_entry. */
-
-union cooked_index_entry_ref
-{
- cooked_index_entry_ref (parent_map::addr_type deferred_)
- {
- deferred = deferred_;
- }
-
- cooked_index_entry_ref (const cooked_index_entry *resolved_)
- {
- resolved = resolved_;
- }
-
- const cooked_index_entry *resolved;
- parent_map::addr_type deferred;
-};
-
-/* Return a string representation of FLAGS. */
-
-std::string to_string (cooked_index_flag flags);
-
-/* Return true if LANG requires canonicalization. This is used
- primarily to work around an issue computing the name of "main".
- This function must be kept in sync with
- cooked_index_shard::finalize. */
-
-extern bool language_requires_canonicalization (enum language lang);
-
-/* A cooked_index_entry represents a single item in the index. Note
- that two entries can be created for the same DIE -- one using the
- name, and another one using the linkage name, if any.
-
- This is an "open" class and the members are all directly
- accessible. It is read-only after the index has been fully read
- and processed. */
-struct cooked_index_entry : public allocate_on_obstack<cooked_index_entry>
-{
- cooked_index_entry (sect_offset die_offset_, enum dwarf_tag tag_,
- cooked_index_flag flags_,
- enum language lang_, const char *name_,
- cooked_index_entry_ref parent_entry_,
- dwarf2_per_cu *per_cu_)
- : name (name_),
- tag (tag_),
- flags (flags_),
- lang (lang_),
- die_offset (die_offset_),
- per_cu (per_cu_),
- m_parent_entry (parent_entry_)
- {
- }
-
- /* Return true if this entry matches SEARCH_FLAGS. */
- bool matches (block_search_flags search_flags) const
- {
- /* Just reject type declarations. */
- if ((flags & IS_TYPE_DECLARATION) != 0)
- return false;
-
- if ((search_flags & SEARCH_STATIC_BLOCK) != 0
- && (flags & IS_STATIC) != 0)
- return true;
- if ((search_flags & SEARCH_GLOBAL_BLOCK) != 0
- && (flags & IS_STATIC) == 0)
- return true;
- return false;
- }
-
- /* Return true if this entry matches KIND. */
- bool matches (domain_search_flags kind) const;
-
- /* Construct the fully-qualified name of this entry and return a
- pointer to it. If allocation is needed, it will be done on
- STORAGE.
-
- FLAGS affects the result. If the FOR_MAIN flag is set, we are
- computing the name of the "main" entry -- one marked
- DW_AT_main_subprogram. This matters for avoiding name
- canonicalization and also a related race (if "main" computation
- is done during finalization).
-
- If the FOR_ADA_LINKAGE_NAME flag is set, then Ada-language
- symbols will have their "linkage-style" name computed. The
- default is source-style.
-
- If the language doesn't prescribe a separator, one can be
- specified using DEFAULT_SEP. */
- const char *full_name (struct obstack *storage,
- cooked_index_full_name_flag name_flags = 0,
- const char *default_sep = nullptr) const;
-
- /* Comparison modes for the 'compare' function. See the function
- for a description. */
- enum comparison_mode
- {
- MATCH,
- SORT,
- COMPLETE,
- };
-
- /* Compare two strings, case-insensitively. Return -1 if STRA is
- less than STRB, 0 if they are equal, and 1 if STRA is greater.
-
- When comparing, '<' is considered to be less than all other
- printable characters. This ensures that "t<x>" sorts before
- "t1", which is necessary when looking up "t". This '<' handling
- is to ensure that certain C++ lookups work correctly. It is
- inexact, and applied regardless of the search language, but this
- is ok because callers of this code do more precise filtering
- according to their needs. This is also why using a
- case-insensitive comparison works even for languages that are
- case sensitive.
-
- MODE controls how the comparison proceeds.
-
- MODE==SORT is used when sorting and the only special '<' handling
- that it does is to ensure that '<' sorts before all other
- printable characters. This ensures that the resulting ordering
- will be binary-searchable.
-
- MODE==MATCH is used when searching for a symbol. In this case,
- STRB must always be the search name, and STRA must be the name in
- the index that is under consideration. In compare mode, early
- termination of STRB may match STRA -- for example, "t<int>" and
- "t" will be considered to be equal. (However, if A=="t" and
- B=="t<int>", then this will not consider them as equal.)
-
- MODE==COMPLETE is used when searching for a symbol for
- completion. In this case, STRB must always be the search name,
- and STRA must be the name in the index that is under
- consideration. In completion mode, early termination of STRB
- always results in a match. */
- static int compare (const char *stra, const char *strb,
- comparison_mode mode);
-
- /* Compare two entries by canonical name. */
- bool operator< (const cooked_index_entry &other) const
- {
- return compare (canonical, other.canonical, SORT) < 0;
- }
-
- /* Set parent entry to PARENT. */
- void set_parent (const cooked_index_entry *parent)
- {
- gdb_assert ((flags & IS_PARENT_DEFERRED) == 0);
- m_parent_entry.resolved = parent;
- }
-
- /* Resolve deferred parent entry to PARENT. */
- void resolve_parent (const cooked_index_entry *parent)
- {
- gdb_assert ((flags & IS_PARENT_DEFERRED) != 0);
- flags = flags & ~IS_PARENT_DEFERRED;
- m_parent_entry.resolved = parent;
- }
-
- /* Return parent entry. */
- const cooked_index_entry *get_parent () const
- {
- gdb_assert ((flags & IS_PARENT_DEFERRED) == 0);
- return m_parent_entry.resolved;
- }
-
- /* Return deferred parent entry. */
- parent_map::addr_type get_deferred_parent () const
- {
- gdb_assert ((flags & IS_PARENT_DEFERRED) != 0);
- return m_parent_entry.deferred;
- }
-
- /* The name as it appears in DWARF. This always points into one of
- the mapped DWARF sections. Note that this may be the name or the
- linkage name -- two entries are created for DIEs which have both
- attributes. */
- const char *name;
- /* The canonical name. This may be equal to NAME. */
- const char *canonical = nullptr;
- /* The DWARF tag. */
- enum dwarf_tag tag;
- /* Any flags attached to this entry. */
- cooked_index_flag flags;
- /* The language of this symbol. */
- ENUM_BITFIELD (language) lang : LANGUAGE_BITS;
- /* The offset of this DIE. */
- sect_offset die_offset;
- /* The CU from which this entry originates. */
- dwarf2_per_cu *per_cu;
-
-private:
-
- /* A helper method for full_name. Emits the full scope of this
- object, followed by the separator, to STORAGE. If this entry has
- a parent, its write_scope method is called first. See full_name
- for a description of the FLAGS parameter. */
- void write_scope (struct obstack *storage, const char *sep,
- cooked_index_full_name_flag flags) const;
-
- /* The parent entry. This is NULL for top-level entries.
- Otherwise, it points to the parent entry, such as a namespace or
- class. */
- cooked_index_entry_ref m_parent_entry;
-};
-
-class cooked_index;
-
-/* 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.
-
- Operations on the index are described below. They are chosen to
- make it relatively simple to implement the symtab "quick"
- methods. */
-class cooked_index_shard
-{
-public:
- cooked_index_shard () = default;
- DISABLE_COPY_AND_ASSIGN (cooked_index_shard);
-
- /* Create a new cooked_index_entry and register it with this object.
- Entries are owned by this object. The new item is returned. */
- cooked_index_entry *add (sect_offset die_offset, enum dwarf_tag tag,
- cooked_index_flag flags, enum language lang,
- const char *name,
- cooked_index_entry_ref parent_entry,
- dwarf2_per_cu *per_cu);
-
- /* Install a new fixed addrmap from the given mutable addrmap. */
- void install_addrmap (addrmap_mutable *map)
- {
- gdb_assert (m_addrmap == nullptr);
- m_addrmap = new (&m_storage) addrmap_fixed (&m_storage, map);
- }
-
- friend class cooked_index;
-
- /* A simple range over part of m_entries. */
- typedef iterator_range<std::vector<cooked_index_entry *>::const_iterator>
- range;
-
- /* Return a range of all the entries. */
- range all_entries () const
- {
- return { m_entries.cbegin (), m_entries.cend () };
- }
-
- /* 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 (const std::string &name, bool completing) const;
-
-private:
-
- /* 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 *lookup (unrelocated_addr addr)
- {
- if (m_addrmap == nullptr)
- return nullptr;
-
- return (static_cast<dwarf2_per_cu *> (m_addrmap->find ((CORE_ADDR) addr)));
- }
-
- /* Create a new cooked_index_entry and register it with this object.
- Entries are owned by this object. The new item is returned. */
- cooked_index_entry *create (sect_offset die_offset,
- enum dwarf_tag tag,
- cooked_index_flag flags,
- enum language lang,
- const char *name,
- cooked_index_entry_ref parent_entry,
- dwarf2_per_cu *per_cu);
-
- /* When GNAT emits mangled ("encoded") names in the DWARF, and does
- not emit the module structure, we still need this structuring to
- do lookups. This function recreates that information for an
- existing entry, modifying ENTRY as appropriate. Any new entries
- are added to NEW_ENTRIES. */
- void handle_gnat_encoded_entry
- (cooked_index_entry *entry, htab_t gnat_entries,
- std::vector<cooked_index_entry *> &new_entries);
-
- /* 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 table and fixes up all missing parent links.
- This may be invoked in a worker thread. */
- void finalize (const parent_map_map *parent_maps);
-
- /* Storage for the entries. */
- auto_obstack m_storage;
- /* List of all entries. */
- std::vector<cooked_index_entry *> m_entries;
- /* If we found an entry with 'is_main' set, store it here. */
- cooked_index_entry *m_main = nullptr;
- /* The addrmap. This maps address ranges to dwarf2_per_cu objects. */
- addrmap_fixed *m_addrmap = nullptr;
- /* Storage for canonical names. */
- gdb::string_set m_names;
-};
-
-using cooked_index_shard_up = std::unique_ptr<cooked_index_shard>;
-
-/* The possible states of the index. See the explanatory comment
- before cooked_index for more details. */
-enum class cooked_state
-{
- /* The default state. This is not a valid argument to 'wait'. */
- INITIAL,
- /* The initial scan has completed. The name of "main" is now
- available (if known). The addrmaps are usable now.
- Finalization has started but is not complete. */
- MAIN_AVAILABLE,
- /* Finalization has completed. This means the index is fully
- available for queries. */
- FINALIZED,
- /* Writing to the index cache has finished. */
- CACHE_DONE,
-};
-
-/* An object of this type controls the scanning of the DWARF. It
- schedules the worker tasks and tracks the current state. Once
- scanning is done, this object is discarded.
-
- This is an abstract base class that defines the basic behavior of
- scanners. Separate concrete implementations exist for scanning
- .debug_names and .debug_info. */
-
-class cooked_index_worker
-{
-public:
-
- explicit cooked_index_worker (dwarf2_per_objfile *per_objfile)
- : m_per_objfile (per_objfile),
- m_cache_store (global_index_cache, per_objfile->per_bfd)
- { }
- virtual ~cooked_index_worker ()
- { }
- DISABLE_COPY_AND_ASSIGN (cooked_index_worker);
-
- /* Start reading. */
- void start ();
-
- /* Wait for a particular state to be achieved. If ALLOW_QUIT is
- true, then the loop will check the QUIT flag. Normally this
- method may only be called from the main thread; however, it can
- be called from a worker thread provided that the desired state
- has already been attained. (This oddity is used by the index
- cache writer.) */
- bool wait (cooked_state desired_state, bool allow_quit);
-
-protected:
-
- /* Let cooked_index call the 'set' and 'write_to_cache' methods. */
- friend class cooked_index;
-
- /* Set the current state. */
- void set (cooked_state desired_state);
-
- /* Write to the index cache. */
- void write_to_cache (const cooked_index *idx,
- deferred_warnings *warn) const;
-
- /* Helper function that does the work of reading. This must be able
- to be run in a worker thread without problems. */
- virtual void do_reading () = 0;
-
- /* A callback that can print stats, if needed. This is called when
- transitioning to the 'MAIN_AVAILABLE' state. */
- virtual void print_stats ()
- { }
-
- /* Each thread returns a tuple holding a cooked index, any collected
- complaints, a vector of errors that should be printed, and a
- parent map.
-
- The errors are retained because GDB's I/O system is not
- thread-safe. run_on_main_thread could be used, but that would
- mean the messages are printed after the prompt, which looks
- weird. */
- using result_type = std::tuple<cooked_index_shard_up,
- complaint_collection,
- std::vector<gdb_exception>,
- parent_map>;
-
- /* The per-objfile object. */
- dwarf2_per_objfile *m_per_objfile;
- /* Result of each worker task. */
- std::vector<result_type> m_results;
- /* Any warnings emitted. This is not in 'result_type' because (for
- the time being at least), it's only needed in do_reading, not in
- every worker. Note that deferred_warnings uses gdb_stderr in its
- constructor, and this should only be done from the main thread.
- This is enforced in the cooked_index_worker constructor. */
- deferred_warnings m_warnings;
-
- /* A map of all parent maps. Used during finalization to fix up
- parent relationships. */
- parent_map_map m_all_parents_map;
-
-#if CXX_STD_THREAD
- /* Current state of this object. */
- cooked_state m_state = cooked_state::INITIAL;
- /* Mutex and condition variable used to synchronize. */
- std::mutex m_mutex;
- std::condition_variable m_cond;
-#endif /* CXX_STD_THREAD */
- /* This flag indicates whether any complaints or exceptions that
- arose during scanning have been reported by 'wait'. This may
- only be modified on the main thread. */
- bool m_reported = false;
- /* If set, an exception occurred during reading; in this case the
- scanning is stopped and this exception will later be reported by
- the 'wait' method. */
- std::optional<gdb_exception> m_failed;
- /* An object used to write to the index cache. */
- index_cache_store_context m_cache_store;
-};
-
-using cooked_index_worker_up = std::unique_ptr<cooked_index_worker>;
+#include "dwarf2/cooked-index-shard.h"
+#include "dwarf2/cooked-index-worker.h"
/* The main index of DIEs.
@@ -515,6 +41,14 @@ using cooked_index_worker_up = std::unique_ptr<cooked_index_worker>;
possible. This combination should help hide the effort from the
user to the maximum possible degree.
+ There are a number of different objects involved in this process.
+ Most of them are temporary -- they are created to handle different
+ phases of scanning, then discarded when possible. The "steady
+ state" objects are index itself (cooked_index, below), which holds
+ the entries (cooked_index_entry), and the implementation of the
+ "quick" API (e.g., cooked_index_functions, though there are
+ other variants).
+
. Main Thread | Worker Threads
============================================================
. dwarf2_initialize_objfile
@@ -546,6 +80,7 @@ using cooked_index_worker_up = std::unique_ptr<cooked_index_worker>;
. v
. maybe write to index cache
. state = CACHE_DONE
+ . ~cooked_index_worker
.
.
. if main thread calls...
@@ -570,14 +105,8 @@ public:
void start_reading () override;
/* Called by cooked_index_worker to set the contents of this index
- and transition to the MAIN_AVAILABLE state. WARN is used to
- collect any warnings that may arise when writing to the cache.
- PARENT_MAPS is used when resolving pending parent links.
- PARENT_MAPS may be NULL if there are no IS_PARENT_DEFERRED
- entries in VEC. */
- void set_contents (std::vector<cooked_index_shard_up> &&vec,
- deferred_warnings *warn,
- const parent_map_map *parent_maps);
+ and transition to the MAIN_AVAILABLE state. */
+ void set_contents ();
/* A range over a vector of subranges. */
using range = range_chain<cooked_index_shard::range>;