forked from Imagelibrary/binutils-gdb
This updates the copyright headers to include 2025. I did this by running gdb/copyright.py and then manually modifying a few files as noted by the script. Approved-By: Eli Zaretskii <eliz@gnu.org>
274 lines
9.4 KiB
C++
274 lines
9.4 KiB
C++
/* DIE indexing
|
|
|
|
Copyright (C) 2022-2025 Free Software Foundation, Inc.
|
|
|
|
This file is part of GDB.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
#ifndef GDB_DWARF2_COOKED_INDEX_H
|
|
#define GDB_DWARF2_COOKED_INDEX_H
|
|
|
|
#include "dwarf2/cooked-index-entry.h"
|
|
#include "symtab.h"
|
|
#include "quick-symbol.h"
|
|
#include "addrmap.h"
|
|
#include "dwarf2/mapped-index.h"
|
|
#include "dwarf2/read.h"
|
|
#include "dwarf2/parent-map.h"
|
|
#include "gdbsupport/range-chain.h"
|
|
#include "dwarf2/cooked-index-shard.h"
|
|
#include "dwarf2/cooked-index-worker.h"
|
|
|
|
/* The main index of DIEs.
|
|
|
|
The index is created by multiple threads. The overall process is
|
|
somewhat complicated, so here's a diagram to help sort it out.
|
|
|
|
The basic idea behind this design is (1) to do as much work as
|
|
possible in worker threads, and (2) to start the work as early as
|
|
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
|
|
. |
|
|
. v
|
|
. cooked index ------------> cooked_index_worker::start
|
|
. | / | \
|
|
. v / | \
|
|
. install / | \
|
|
. cooked_index_functions scan CUs in workers
|
|
. | create cooked_index_shard objects
|
|
. | \ | /
|
|
. v \|/
|
|
. return to caller v
|
|
. initial scan is done
|
|
. state = MAIN_AVAILABLE
|
|
. "main" name now available
|
|
. |
|
|
. |
|
|
. if main thread calls... v
|
|
. compute_main_name cooked_index::set_contents
|
|
. | / | \
|
|
. v / | \
|
|
. wait (MAIN_AVAILABLE) finalization
|
|
. | \ | /
|
|
. v \ | /
|
|
. done state = FINALIZED
|
|
. |
|
|
. v
|
|
. maybe write to index cache
|
|
. state = CACHE_DONE
|
|
. ~cooked_index_worker
|
|
.
|
|
.
|
|
. if main thread calls...
|
|
. any other "quick" API
|
|
. |
|
|
. v
|
|
. wait (FINALIZED)
|
|
. |
|
|
. v
|
|
. use the index
|
|
*/
|
|
|
|
class cooked_index : public dwarf_scanner_base
|
|
{
|
|
public:
|
|
cooked_index (cooked_index_worker_up &&worker);
|
|
~cooked_index () override;
|
|
|
|
DISABLE_COPY_AND_ASSIGN (cooked_index);
|
|
|
|
/* Start reading the DWARF. */
|
|
void start_reading () override;
|
|
|
|
/* Called by cooked_index_worker to set the contents of this index
|
|
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>;
|
|
|
|
/* 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);
|
|
|
|
/* Return a range of all the entries. */
|
|
range all_entries ()
|
|
{
|
|
wait (cooked_state::FINALIZED, true);
|
|
std::vector<cooked_index_shard::range> result_range;
|
|
result_range.reserve (m_shards.size ());
|
|
for (auto &shard : m_shards)
|
|
result_range.push_back (shard->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 *lookup (unrelocated_addr addr) override;
|
|
|
|
/* Return a new vector of all the addrmaps used by all the indexes
|
|
held by this object.
|
|
|
|
Elements of the vector may be nullptr. */
|
|
std::vector<const 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;
|
|
|
|
const char *get_main_name (struct obstack *obstack, enum language *lang)
|
|
const;
|
|
|
|
cooked_index *index_for_writing () override
|
|
{
|
|
wait (cooked_state::FINALIZED, true);
|
|
return this;
|
|
}
|
|
|
|
quick_symbol_functions_up make_quick_functions () const override;
|
|
|
|
/* Dump a human-readable form of the contents of the index. */
|
|
void dump (gdbarch *arch);
|
|
|
|
/* Wait until this object reaches the desired state. Note that
|
|
DESIRED_STATE may not be INITIAL -- it does not make sense to
|
|
wait for this. If ALLOW_QUIT is true, timed waits will be done
|
|
and the quit flag will be checked in a loop. This may normally
|
|
only be called from the main thread; however, it is ok to call
|
|
from a worker as long as the desired state has already been
|
|
attained. (This property is needed by the index cache
|
|
writer.) */
|
|
void wait (cooked_state desired_state, bool allow_quit = false);
|
|
|
|
void wait_completely () override
|
|
{ wait (cooked_state::CACHE_DONE); }
|
|
|
|
private:
|
|
|
|
/* The vector of cooked_index objects. This is stored because the
|
|
entries are stored on the obstacks in those objects. */
|
|
std::vector<cooked_index_shard_up> m_shards;
|
|
|
|
/* This tracks the current state. When this is nullptr, it means
|
|
that the state is CACHE_DONE -- it's important to note that only
|
|
the main thread may change the value of this pointer. */
|
|
cooked_index_worker_up m_state;
|
|
};
|
|
|
|
/* An implementation of quick_symbol_functions for the cooked DWARF
|
|
index. */
|
|
|
|
struct cooked_index_functions : public dwarf2_base_index_functions
|
|
{
|
|
cooked_index *wait (struct objfile *objfile, bool allow_quit)
|
|
{
|
|
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
|
|
cooked_index *table
|
|
= (gdb::checked_static_cast<cooked_index *>
|
|
(per_objfile->per_bfd->index_table.get ()));
|
|
table->wait (cooked_state::MAIN_AVAILABLE, allow_quit);
|
|
return table;
|
|
}
|
|
|
|
struct compunit_symtab *find_compunit_symtab_by_address
|
|
(struct objfile *objfile, CORE_ADDR address) override;
|
|
|
|
bool has_unexpanded_symtabs (struct objfile *objfile) override
|
|
{
|
|
wait (objfile, true);
|
|
return dwarf2_base_index_functions::has_unexpanded_symtabs (objfile);
|
|
}
|
|
|
|
struct symtab *find_last_source_symtab (struct objfile *objfile) override
|
|
{
|
|
wait (objfile, true);
|
|
return dwarf2_base_index_functions::find_last_source_symtab (objfile);
|
|
}
|
|
|
|
void forget_cached_source_info (struct objfile *objfile) override
|
|
{
|
|
wait (objfile, true);
|
|
dwarf2_base_index_functions::forget_cached_source_info (objfile);
|
|
}
|
|
|
|
void print_stats (struct objfile *objfile, bool print_bcache) override
|
|
{
|
|
wait (objfile, true);
|
|
dwarf2_base_index_functions::print_stats (objfile, print_bcache);
|
|
}
|
|
|
|
void dump (struct objfile *objfile) override
|
|
{
|
|
cooked_index *index = wait (objfile, true);
|
|
gdb_printf ("Cooked index in use:\n");
|
|
gdb_printf ("\n");
|
|
index->dump (objfile->arch ());
|
|
}
|
|
|
|
void expand_all_symtabs (struct objfile *objfile) override
|
|
{
|
|
wait (objfile, true);
|
|
dwarf2_base_index_functions::expand_all_symtabs (objfile);
|
|
}
|
|
|
|
bool expand_symtabs_matching
|
|
(struct objfile *objfile,
|
|
expand_symtabs_file_matcher file_matcher,
|
|
const lookup_name_info *lookup_name,
|
|
expand_symtabs_symbol_matcher symbol_matcher,
|
|
expand_symtabs_expansion_listener expansion_notify,
|
|
block_search_flags search_flags,
|
|
domain_search_flags domain,
|
|
expand_symtabs_lang_matcher lang_matcher) override;
|
|
|
|
struct compunit_symtab *find_pc_sect_compunit_symtab
|
|
(struct objfile *objfile, bound_minimal_symbol msymbol,
|
|
CORE_ADDR pc, struct obj_section *section, int warn_if_readin) override
|
|
{
|
|
wait (objfile, true);
|
|
return (dwarf2_base_index_functions::find_pc_sect_compunit_symtab
|
|
(objfile, msymbol, pc, section, warn_if_readin));
|
|
}
|
|
|
|
void map_symbol_filenames (objfile *objfile, symbol_filename_listener fun,
|
|
bool need_fullname) override
|
|
{
|
|
wait (objfile, true);
|
|
return (dwarf2_base_index_functions::map_symbol_filenames
|
|
(objfile, fun, need_fullname));
|
|
}
|
|
|
|
void compute_main_name (struct objfile *objfile) override
|
|
{
|
|
wait (objfile, false);
|
|
}
|
|
};
|
|
|
|
#endif /* GDB_DWARF2_COOKED_INDEX_H */
|