Replace dwarf2_per_cu_data::cu backlink with per-objfile map
The dwarf2_per_cu_data type is going to become objfile-independent, while the dwarf2_cu type will stay object-dependent. This patch removes the backlink from dwarf2_per_cu_data to dwarf2_cu, in favor of the dwarf2_per_objfile::m_dwarf2_cus map. It maps dwarf2_per_cu_data objects to the corresponding dwarf2_cu objects for this objfile. If a CU has been read in in the context of this objfile, then an entry will be present in the map. The dwarf2_cu objects that are read in are currently kept in a linked list rooted in the dwarf2_per_bfd. Except that the dwarf2_cu objects are not simply linked together, they are interleaved with their corresponding dwarf2_per_cu_data objects. So if we have CUs A and B read in, the dwarf2_per_bfd::read_in_chain will point to a chain like this (DPCD == dwarf2_per_cu_data, DC == dwarf2_cu): DPCD A -> DC A -> DPCD B -> DC B Obviously, this can't stay as is, since a same CU can be read in for an objfile but not read in for another objfile sharing the same BFD, and the dwarf2_per_cu_data::cu link is removed. This is all replaced by the dwarf2_per_objfile::m_dwarf2_cus map. gdb/ChangeLog: * dwarf2/read.h (struct dwarf2_cu): Forward-declare. (struct dwarf2_per_bfd) <free_cached_comp_units>: Remove, move to dwarf2_per_objfile. <read_in_chain>: Remove. (struct dwarf2_per_objfile) <get_cu, set_cu, remove_cu, remove_all_cus, age_comp_units>: New methods. <m_dwarf2_cus>: New member. (struct dwarf2_per_cu_data) <cu>: Remove. * dwarf2/read.c (struct dwarf2_cu) <read_in_chain>: Remove. (age_cached_comp_units, free_one_cached_comp_unit): Remove, moved to methods of dwarf2_per_objfile. (dwarf2_clear_marks): Remove. (dwarf2_queue_item::~dwarf2_queue_item): Update. (dwarf2_per_bfd::~dwarf2_per_bfd): Don't free dwarf2_cus. (dwarf2_per_bfd::free_cached_comp_units): Remove. (dwarf2_per_objfile::remove_all_cus): New. (class free_cached_comp_units) <~free_cached_comp_units>: Update. (load_cu): Update. (dw2_do_instantiate_symtab): Adjust. (fill_in_sig_entry_from_dwo_entry): Adjust. (cutu_reader::init_tu_and_read_dwo_dies): Update. (cutu_reader::cutu_reader): Likewise. (cutu_reader::keep): Use dwarf2_per_objfile::set_cu. (cutu_reader::cutu_reader): Use dwarf2_per_objfile::get_cu. (process_psymtab_comp_unit): Use dwarf2_per_objfile::remove_cu and dwarf2_per_objfile::age_comp_units. (load_partial_comp_unit): Update. (maybe_queue_comp_unit): Use dwarf2_per_objfile::get_cu. (process_queue): Likewise. (find_partial_die): Use dwarf2_per_objfile::get_cu instead of cu backlink. (dwarf2_read_addr_index): Likewise. (follow_die_offset): Likewise. (dwarf2_fetch_die_loc_sect_off): Likewise. (dwarf2_fetch_constant_bytes): Likewise. (dwarf2_fetch_die_type_sect_off): Likewise. (follow_die_sig_1): Likewise. (load_full_type_unit): Likewise. (read_signatured_type): Likewise. (dwarf2_cu::dwarf2_cu): Don't set cu field. (dwarf2_cu::~dwarf2_cu): Remove. (dwarf2_per_objfile::get_cu): New. (dwarf2_per_objfile::set_cu): New. (age_cached_comp_units): Rename to... (dwarf2_per_objfile::age_comp_units): ... this. Adjust to std::unordered_map. (free_one_cached_comp_unit): Rename to... (dwarf2_per_objfile::remove_cu): ... this. Adjust to std::unordered_map. (dwarf2_per_objfile::~dwarf2_per_objfile): New. (dwarf2_mark_helper): Use dwarf2_per_objfile::get_cu, expect a dwarf2_per_objfile in data. (dwarf2_mark): Pass dwarf2_per_objfile in data to htab_traverse. (dwarf2_clear_marks): Remove. Change-Id: Ia33ac71c79b2de4710569008e22a6563a1505cde
This commit is contained in:
parent
2e6711003b
commit
7188ed02d2
3 changed files with 249 additions and 203 deletions
|
@ -1,3 +1,61 @@
|
|||
2020-05-27 Simon Marchi <simon.marchi@efficios.com>
|
||||
|
||||
* dwarf2/read.h (struct dwarf2_cu): Forward-declare.
|
||||
(struct dwarf2_per_bfd) <free_cached_comp_units>: Remove,
|
||||
move to dwarf2_per_objfile.
|
||||
<read_in_chain>: Remove.
|
||||
(struct dwarf2_per_objfile) <get_cu, set_cu, remove_cu,
|
||||
remove_all_cus, age_comp_units>: New methods.
|
||||
<m_dwarf2_cus>: New member.
|
||||
(struct dwarf2_per_cu_data) <cu>: Remove.
|
||||
* dwarf2/read.c (struct dwarf2_cu) <read_in_chain>: Remove.
|
||||
(age_cached_comp_units, free_one_cached_comp_unit): Remove,
|
||||
moved to methods of dwarf2_per_objfile.
|
||||
(dwarf2_clear_marks): Remove.
|
||||
(dwarf2_queue_item::~dwarf2_queue_item): Update.
|
||||
(dwarf2_per_bfd::~dwarf2_per_bfd): Don't free dwarf2_cus.
|
||||
(dwarf2_per_bfd::free_cached_comp_units): Remove.
|
||||
(dwarf2_per_objfile::remove_all_cus): New.
|
||||
(class free_cached_comp_units) <~free_cached_comp_units>:
|
||||
Update.
|
||||
(load_cu): Update.
|
||||
(dw2_do_instantiate_symtab): Adjust.
|
||||
(fill_in_sig_entry_from_dwo_entry): Adjust.
|
||||
(cutu_reader::init_tu_and_read_dwo_dies): Update.
|
||||
(cutu_reader::cutu_reader): Likewise.
|
||||
(cutu_reader::keep): Use dwarf2_per_objfile::set_cu.
|
||||
(cutu_reader::cutu_reader): Use dwarf2_per_objfile::get_cu.
|
||||
(process_psymtab_comp_unit): Use dwarf2_per_objfile::remove_cu
|
||||
and dwarf2_per_objfile::age_comp_units.
|
||||
(load_partial_comp_unit): Update.
|
||||
(maybe_queue_comp_unit): Use dwarf2_per_objfile::get_cu.
|
||||
(process_queue): Likewise.
|
||||
(find_partial_die): Use dwarf2_per_objfile::get_cu instead of cu
|
||||
backlink.
|
||||
(dwarf2_read_addr_index): Likewise.
|
||||
(follow_die_offset): Likewise.
|
||||
(dwarf2_fetch_die_loc_sect_off): Likewise.
|
||||
(dwarf2_fetch_constant_bytes): Likewise.
|
||||
(dwarf2_fetch_die_type_sect_off): Likewise.
|
||||
(follow_die_sig_1): Likewise.
|
||||
(load_full_type_unit): Likewise.
|
||||
(read_signatured_type): Likewise.
|
||||
(dwarf2_cu::dwarf2_cu): Don't set cu field.
|
||||
(dwarf2_cu::~dwarf2_cu): Remove.
|
||||
(dwarf2_per_objfile::get_cu): New.
|
||||
(dwarf2_per_objfile::set_cu): New.
|
||||
(age_cached_comp_units): Rename to...
|
||||
(dwarf2_per_objfile::age_comp_units): ... this. Adjust
|
||||
to std::unordered_map.
|
||||
(free_one_cached_comp_unit): Rename to...
|
||||
(dwarf2_per_objfile::remove_cu): ... this. Adjust
|
||||
to std::unordered_map.
|
||||
(dwarf2_per_objfile::~dwarf2_per_objfile): New.
|
||||
(dwarf2_mark_helper): Use dwarf2_per_objfile::get_cu, expect
|
||||
a dwarf2_per_objfile in data.
|
||||
(dwarf2_mark): Pass dwarf2_per_objfile in data to htab_traverse.
|
||||
(dwarf2_clear_marks): Remove.
|
||||
|
||||
2020-05-27 Simon Marchi <simon.marchi@efficios.com>
|
||||
|
||||
* dwarf2/read.c (class cutu_reader) <cutu_reader>: Replace
|
||||
|
|
|
@ -401,7 +401,6 @@ struct dwarf2_cu
|
|||
{
|
||||
explicit dwarf2_cu (dwarf2_per_cu_data *per_cu,
|
||||
dwarf2_per_objfile *per_objfile);
|
||||
~dwarf2_cu ();
|
||||
|
||||
DISABLE_COPY_AND_ASSIGN (dwarf2_cu);
|
||||
|
||||
|
@ -468,12 +467,6 @@ public:
|
|||
unit, including partial DIEs. */
|
||||
auto_obstack comp_unit_obstack;
|
||||
|
||||
/* When multiple dwarf2_cu structures are living in memory, this field
|
||||
chains them all together, so that they can be released efficiently.
|
||||
We will probably also want a generation counter so that most-recently-used
|
||||
compilation units are cached... */
|
||||
struct dwarf2_per_cu_data *read_in_chain = nullptr;
|
||||
|
||||
/* Backlink to our per_cu entry. */
|
||||
struct dwarf2_per_cu_data *per_cu;
|
||||
|
||||
|
@ -1553,11 +1546,6 @@ static void prepare_one_comp_unit (struct dwarf2_cu *cu,
|
|||
struct die_info *comp_unit_die,
|
||||
enum language pretend_language);
|
||||
|
||||
static void age_cached_comp_units (struct dwarf2_per_objfile *dwarf2_per_objfile);
|
||||
|
||||
static void free_one_cached_comp_unit (dwarf2_per_cu_data *target_per_cu,
|
||||
dwarf2_per_objfile *per_objfile);
|
||||
|
||||
static struct type *set_die_type (struct die_info *, struct type *,
|
||||
struct dwarf2_cu *);
|
||||
|
||||
|
@ -1581,8 +1569,6 @@ static void dwarf2_add_dependence (struct dwarf2_cu *,
|
|||
|
||||
static void dwarf2_mark (struct dwarf2_cu *);
|
||||
|
||||
static void dwarf2_clear_marks (struct dwarf2_per_cu_data *);
|
||||
|
||||
static struct type *get_die_type_at_offset (sect_offset,
|
||||
dwarf2_per_cu_data *per_cu,
|
||||
dwarf2_per_objfile *per_objfile);
|
||||
|
@ -1629,8 +1615,7 @@ dwarf2_queue_item::~dwarf2_queue_item ()
|
|||
inconsistent state, so discard it. */
|
||||
if (per_cu->queued)
|
||||
{
|
||||
if (per_cu->cu != NULL)
|
||||
free_one_cached_comp_unit (per_cu, per_objfile);
|
||||
per_objfile->remove_cu (per_cu);
|
||||
per_cu->queued = 0;
|
||||
}
|
||||
}
|
||||
|
@ -1772,9 +1757,6 @@ dwarf2_per_bfd::dwarf2_per_bfd (bfd *obfd, const dwarf2_debug_sections *names,
|
|||
|
||||
dwarf2_per_bfd::~dwarf2_per_bfd ()
|
||||
{
|
||||
/* Cached DIE trees use xmalloc and the comp_unit_obstack. */
|
||||
free_cached_comp_units ();
|
||||
|
||||
for (dwarf2_per_cu_data *per_cu : all_comp_units)
|
||||
per_cu->imported_symtabs_free ();
|
||||
|
||||
|
@ -1784,21 +1766,15 @@ dwarf2_per_bfd::~dwarf2_per_bfd ()
|
|||
/* Everything else should be on this->obstack. */
|
||||
}
|
||||
|
||||
/* See declaration. */
|
||||
/* See read.h. */
|
||||
|
||||
void
|
||||
dwarf2_per_bfd::free_cached_comp_units ()
|
||||
dwarf2_per_objfile::remove_all_cus ()
|
||||
{
|
||||
dwarf2_per_cu_data *per_cu = read_in_chain;
|
||||
dwarf2_per_cu_data **last_chain = &read_in_chain;
|
||||
while (per_cu != NULL)
|
||||
{
|
||||
dwarf2_per_cu_data *next_cu = per_cu->cu->read_in_chain;
|
||||
for (auto pair : m_dwarf2_cus)
|
||||
delete pair.second;
|
||||
|
||||
delete per_cu->cu;
|
||||
*last_chain = next_cu;
|
||||
per_cu = next_cu;
|
||||
}
|
||||
m_dwarf2_cus.clear ();
|
||||
}
|
||||
|
||||
/* A helper class that calls free_cached_comp_units on
|
||||
|
@ -1815,7 +1791,7 @@ public:
|
|||
|
||||
~free_cached_comp_units ()
|
||||
{
|
||||
m_per_objfile->per_bfd->free_cached_comp_units ();
|
||||
m_per_objfile->remove_all_cus ();
|
||||
}
|
||||
|
||||
DISABLE_COPY_AND_ASSIGN (free_cached_comp_units);
|
||||
|
@ -2344,12 +2320,13 @@ load_cu (dwarf2_per_cu_data *per_cu, dwarf2_per_objfile *per_objfile,
|
|||
else
|
||||
load_full_comp_unit (per_cu, per_objfile, skip_partial, language_minimal);
|
||||
|
||||
if (per_cu->cu == nullptr)
|
||||
dwarf2_cu *cu = per_objfile->get_cu (per_cu);
|
||||
if (cu == nullptr)
|
||||
return nullptr; /* Dummy CU. */
|
||||
|
||||
dwarf2_find_base_address (per_cu->cu->dies, per_cu->cu);
|
||||
dwarf2_find_base_address (cu->dies, cu);
|
||||
|
||||
return per_cu->cu;
|
||||
return cu;
|
||||
}
|
||||
|
||||
/* Read in the symbols for PER_CU in the context of DWARF"_PER_OBJFILE. */
|
||||
|
@ -2391,7 +2368,7 @@ dw2_do_instantiate_symtab (dwarf2_per_cu_data *per_cu,
|
|||
|
||||
/* Age the cache, releasing compilation units that have not
|
||||
been used recently. */
|
||||
age_cached_comp_units (dwarf2_per_objfile);
|
||||
dwarf2_per_objfile->age_comp_units ();
|
||||
}
|
||||
|
||||
/* Ensure that the symbols for PER_CU have been read in. DWARF2_PER_OBJFILE is
|
||||
|
@ -6465,7 +6442,7 @@ fill_in_sig_entry_from_dwo_entry (struct dwarf2_per_objfile *dwarf2_per_objfile,
|
|||
|
||||
/* Make sure we're not clobbering something we don't expect to. */
|
||||
gdb_assert (! sig_entry->per_cu.queued);
|
||||
gdb_assert (sig_entry->per_cu.cu == NULL);
|
||||
gdb_assert (dwarf2_per_objfile->get_cu (&sig_entry->per_cu) == NULL);
|
||||
if (per_bfd->using_index)
|
||||
{
|
||||
gdb_assert (sig_entry->per_cu.v.quick != NULL);
|
||||
|
@ -6923,8 +6900,9 @@ cutu_reader::init_tu_and_read_dwo_dies (dwarf2_per_cu_data *this_cu,
|
|||
}
|
||||
else
|
||||
{
|
||||
/* If an existing_cu is provided, this_cu->cu must be NULL. */
|
||||
gdb_assert (this_cu->cu == NULL);
|
||||
/* If an existing_cu is provided, a dwarf2_cu must not exist for this_cu
|
||||
in per_objfile yet. */
|
||||
gdb_assert (per_objfile->get_cu (this_cu) == nullptr);
|
||||
m_new_cu.reset (new dwarf2_cu (this_cu, per_objfile));
|
||||
cu = m_new_cu.get ();
|
||||
}
|
||||
|
@ -7013,8 +6991,9 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu,
|
|||
}
|
||||
else
|
||||
{
|
||||
/* If an existing_cu is provided, this_cu->cu must be NULL. */
|
||||
gdb_assert (this_cu->cu == NULL);
|
||||
/* If an existing_cu is provided, a dwarf2_cu must not exist for this_cu
|
||||
in per_objfile yet. */
|
||||
gdb_assert (dwarf2_per_objfile->get_cu (this_cu) == nullptr);
|
||||
m_new_cu.reset (new dwarf2_cu (this_cu, dwarf2_per_objfile));
|
||||
cu = m_new_cu.get ();
|
||||
}
|
||||
|
@ -7154,16 +7133,10 @@ cutu_reader::keep ()
|
|||
gdb_assert (!dummy_p);
|
||||
if (m_new_cu != NULL)
|
||||
{
|
||||
/* We know that m_this_cu->cu is set, since we are in the process of
|
||||
parsing the CU. */
|
||||
gdb_assert (m_this_cu->cu != nullptr);
|
||||
dwarf2_per_objfile *dwarf2_per_objfile = m_this_cu->cu->per_objfile;
|
||||
|
||||
/* Link this CU into read_in_chain. */
|
||||
m_this_cu->cu->read_in_chain = dwarf2_per_objfile->per_bfd->read_in_chain;
|
||||
dwarf2_per_objfile->per_bfd->read_in_chain = m_this_cu;
|
||||
/* The chain owns it now. */
|
||||
m_new_cu.release ();
|
||||
/* Save this dwarf2_cu in the per_objfile. The per_objfile owns it
|
||||
now. */
|
||||
dwarf2_per_objfile *per_objfile = m_new_cu->per_objfile;
|
||||
per_objfile->set_cu (m_this_cu, m_new_cu.release ());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7201,7 +7174,7 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu,
|
|||
this_cu->is_debug_types ? "type" : "comp",
|
||||
sect_offset_str (this_cu->sect_off));
|
||||
|
||||
gdb_assert (this_cu->cu == NULL);
|
||||
gdb_assert (dwarf2_per_objfile->get_cu (this_cu) == nullptr);
|
||||
|
||||
abbrev_section = (dwo_file != NULL
|
||||
? &dwo_file->sections.abbrev
|
||||
|
@ -7563,8 +7536,7 @@ process_psymtab_comp_unit (dwarf2_per_cu_data *this_cu,
|
|||
necessary because we skipped some symbols when we first
|
||||
read in the compilation unit (see load_partial_dies).
|
||||
This problem could be avoided, but the benefit is unclear. */
|
||||
if (this_cu->cu != NULL)
|
||||
free_one_cached_comp_unit (this_cu, per_objfile);
|
||||
per_objfile->remove_cu (this_cu);
|
||||
|
||||
cutu_reader reader (this_cu, per_objfile, nullptr, nullptr, false);
|
||||
|
||||
|
@ -7593,10 +7565,10 @@ process_psymtab_comp_unit (dwarf2_per_cu_data *this_cu,
|
|||
reader.comp_unit_die,
|
||||
pretend_language);
|
||||
|
||||
this_cu->lang = this_cu->cu->language;
|
||||
this_cu->lang = reader.cu->language;
|
||||
|
||||
/* Age out any secondary CUs. */
|
||||
age_cached_comp_units (per_objfile);
|
||||
per_objfile->age_comp_units ();
|
||||
}
|
||||
|
||||
/* Reader function for build_type_psymtabs. */
|
||||
|
@ -8951,7 +8923,9 @@ maybe_queue_comp_unit (struct dwarf2_cu *dependent_cu,
|
|||
not queue PER_CU, just tell our caller to load its DIEs. */
|
||||
if (per_cu->per_bfd->reading_partial_symbols)
|
||||
{
|
||||
if (per_cu->cu == NULL || per_cu->cu->dies == NULL)
|
||||
dwarf2_cu *cu = per_objfile->get_cu (per_cu);
|
||||
|
||||
if (cu == NULL || cu->dies == NULL)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -8967,9 +8941,10 @@ maybe_queue_comp_unit (struct dwarf2_cu *dependent_cu,
|
|||
|
||||
/* If the compilation unit is already loaded, just mark it as
|
||||
used. */
|
||||
if (per_cu->cu != NULL)
|
||||
dwarf2_cu *cu = per_objfile->get_cu (per_cu);
|
||||
if (cu != nullptr)
|
||||
{
|
||||
per_cu->cu->last_used = 0;
|
||||
cu->last_used = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -8996,47 +8971,51 @@ process_queue (struct dwarf2_per_objfile *dwarf2_per_objfile)
|
|||
while (!dwarf2_per_objfile->per_bfd->queue.empty ())
|
||||
{
|
||||
dwarf2_queue_item &item = dwarf2_per_objfile->per_bfd->queue.front ();
|
||||
dwarf2_per_cu_data *per_cu = item.per_cu;
|
||||
|
||||
if (!dwarf2_per_objfile->symtab_set_p (item.per_cu)
|
||||
/* Skip dummy CUs. */
|
||||
&& item.per_cu->cu != NULL)
|
||||
if (!dwarf2_per_objfile->symtab_set_p (per_cu))
|
||||
{
|
||||
struct dwarf2_per_cu_data *per_cu = item.per_cu;
|
||||
unsigned int debug_print_threshold;
|
||||
char buf[100];
|
||||
dwarf2_cu *cu = dwarf2_per_objfile->get_cu (per_cu);
|
||||
|
||||
if (per_cu->is_debug_types)
|
||||
/* Skip dummy CUs. */
|
||||
if (cu != nullptr)
|
||||
{
|
||||
struct signatured_type *sig_type =
|
||||
(struct signatured_type *) per_cu;
|
||||
unsigned int debug_print_threshold;
|
||||
char buf[100];
|
||||
|
||||
sprintf (buf, "TU %s at offset %s",
|
||||
hex_string (sig_type->signature),
|
||||
sect_offset_str (per_cu->sect_off));
|
||||
/* There can be 100s of TUs.
|
||||
Only print them in verbose mode. */
|
||||
debug_print_threshold = 2;
|
||||
if (per_cu->is_debug_types)
|
||||
{
|
||||
struct signatured_type *sig_type =
|
||||
(struct signatured_type *) per_cu;
|
||||
|
||||
sprintf (buf, "TU %s at offset %s",
|
||||
hex_string (sig_type->signature),
|
||||
sect_offset_str (per_cu->sect_off));
|
||||
/* There can be 100s of TUs.
|
||||
Only print them in verbose mode. */
|
||||
debug_print_threshold = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf (buf, "CU at offset %s",
|
||||
sect_offset_str (per_cu->sect_off));
|
||||
debug_print_threshold = 1;
|
||||
}
|
||||
|
||||
if (dwarf_read_debug >= debug_print_threshold)
|
||||
fprintf_unfiltered (gdb_stdlog, "Expanding symtab of %s\n", buf);
|
||||
|
||||
if (per_cu->is_debug_types)
|
||||
process_full_type_unit (cu, item.pretend_language);
|
||||
else
|
||||
process_full_comp_unit (cu, item.pretend_language);
|
||||
|
||||
if (dwarf_read_debug >= debug_print_threshold)
|
||||
fprintf_unfiltered (gdb_stdlog, "Done expanding %s\n", buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf (buf, "CU at offset %s",
|
||||
sect_offset_str (per_cu->sect_off));
|
||||
debug_print_threshold = 1;
|
||||
}
|
||||
|
||||
if (dwarf_read_debug >= debug_print_threshold)
|
||||
fprintf_unfiltered (gdb_stdlog, "Expanding symtab of %s\n", buf);
|
||||
|
||||
if (per_cu->is_debug_types)
|
||||
process_full_type_unit (per_cu->cu, item.pretend_language);
|
||||
else
|
||||
process_full_comp_unit (per_cu->cu, item.pretend_language);
|
||||
|
||||
if (dwarf_read_debug >= debug_print_threshold)
|
||||
fprintf_unfiltered (gdb_stdlog, "Done expanding %s\n", buf);
|
||||
}
|
||||
|
||||
item.per_cu->queued = 0;
|
||||
per_cu->queued = 0;
|
||||
dwarf2_per_objfile->per_bfd->queue.pop ();
|
||||
}
|
||||
|
||||
|
@ -9112,7 +9091,8 @@ load_full_comp_unit (dwarf2_per_cu_data *this_cu,
|
|||
{
|
||||
gdb_assert (! this_cu->is_debug_types);
|
||||
|
||||
cutu_reader reader (this_cu, per_objfile, NULL, this_cu->cu, skip_partial);
|
||||
dwarf2_cu *existing_cu = per_objfile->get_cu (this_cu);
|
||||
cutu_reader reader (this_cu, per_objfile, NULL, existing_cu, skip_partial);
|
||||
if (reader.dummy_p)
|
||||
return;
|
||||
|
||||
|
@ -18693,7 +18673,6 @@ find_partial_die (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu *cu)
|
|||
{
|
||||
struct dwarf2_per_objfile *dwarf2_per_objfile = cu->per_objfile;
|
||||
struct objfile *objfile = dwarf2_per_objfile->objfile;
|
||||
struct dwarf2_per_cu_data *per_cu = NULL;
|
||||
struct partial_die_info *pd = NULL;
|
||||
|
||||
if (offset_in_dwz == cu->per_cu->is_dwz
|
||||
|
@ -18704,7 +18683,6 @@ find_partial_die (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu *cu)
|
|||
return { cu, pd };
|
||||
/* We missed recording what we needed.
|
||||
Load all dies and try again. */
|
||||
per_cu = cu->per_cu;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -18716,22 +18694,26 @@ find_partial_die (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu *cu)
|
|||
sect_offset_str (cu->header.sect_off), sect_offset_str (sect_off),
|
||||
bfd_get_filename (objfile->obfd));
|
||||
}
|
||||
per_cu = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz,
|
||||
dwarf2_per_objfile);
|
||||
dwarf2_per_cu_data *per_cu
|
||||
= dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz,
|
||||
dwarf2_per_objfile);
|
||||
|
||||
if (per_cu->cu == NULL || per_cu->cu->partial_dies == NULL)
|
||||
load_partial_comp_unit (per_cu, cu->per_objfile, nullptr);
|
||||
cu = dwarf2_per_objfile->get_cu (per_cu);
|
||||
if (cu == NULL || cu->partial_dies == NULL)
|
||||
load_partial_comp_unit (per_cu, dwarf2_per_objfile, nullptr);
|
||||
|
||||
per_cu->cu->last_used = 0;
|
||||
pd = per_cu->cu->find_partial_die (sect_off);
|
||||
cu = dwarf2_per_objfile->get_cu (per_cu);
|
||||
|
||||
cu->last_used = 0;
|
||||
pd = cu->find_partial_die (sect_off);
|
||||
}
|
||||
|
||||
/* If we didn't find it, and not all dies have been loaded,
|
||||
load them all and try again. */
|
||||
|
||||
if (pd == NULL && per_cu->load_all_dies == 0)
|
||||
if (pd == NULL && cu->per_cu->load_all_dies == 0)
|
||||
{
|
||||
per_cu->load_all_dies = 1;
|
||||
cu->per_cu->load_all_dies = 1;
|
||||
|
||||
/* This is nasty. When we reread the DIEs, somewhere up the call chain
|
||||
THIS_CU->cu may already be in use. So we can't just free it and
|
||||
|
@ -18739,9 +18721,9 @@ find_partial_die (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu *cu)
|
|||
DIEs alone (which can still be in use, e.g. in scan_partial_symbols),
|
||||
and clobber THIS_CU->cu->partial_dies with the hash table for the new
|
||||
set. */
|
||||
load_partial_comp_unit (per_cu, cu->per_objfile, cu);
|
||||
load_partial_comp_unit (cu->per_cu, dwarf2_per_objfile, cu);
|
||||
|
||||
pd = per_cu->cu->find_partial_die (sect_off);
|
||||
pd = cu->find_partial_die (sect_off);
|
||||
}
|
||||
|
||||
if (pd == NULL)
|
||||
|
@ -18749,7 +18731,7 @@ find_partial_die (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu *cu)
|
|||
_("could not find partial DIE %s "
|
||||
"in cache [from module %s]\n"),
|
||||
sect_offset_str (sect_off), bfd_get_filename (objfile->obfd));
|
||||
return { per_cu->cu, pd };
|
||||
return { cu, pd };
|
||||
}
|
||||
|
||||
/* See if we can figure out if the class lives in a namespace. We do
|
||||
|
@ -19429,7 +19411,7 @@ dwarf2_read_addr_index (dwarf2_per_cu_data *per_cu,
|
|||
dwarf2_per_objfile *dwarf2_per_objfile,
|
||||
unsigned int addr_index)
|
||||
{
|
||||
struct dwarf2_cu *cu = per_cu->cu;
|
||||
struct dwarf2_cu *cu = dwarf2_per_objfile->get_cu (per_cu);
|
||||
gdb::optional<ULONGEST> addr_base;
|
||||
int addr_size;
|
||||
|
||||
|
@ -22270,7 +22252,7 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz,
|
|||
if (maybe_queue_comp_unit (cu, per_cu, dwarf2_per_objfile, cu->language))
|
||||
load_full_comp_unit (per_cu, dwarf2_per_objfile, false, cu->language);
|
||||
|
||||
target_cu = per_cu->cu;
|
||||
target_cu = dwarf2_per_objfile->get_cu (per_cu);
|
||||
}
|
||||
else if (cu->dies == NULL)
|
||||
{
|
||||
|
@ -22330,7 +22312,7 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off,
|
|||
struct dwarf2_locexpr_baton retval;
|
||||
struct objfile *objfile = dwarf2_per_objfile->objfile;
|
||||
|
||||
dwarf2_cu *cu = per_cu->cu;
|
||||
dwarf2_cu *cu = dwarf2_per_objfile->get_cu (per_cu);
|
||||
if (cu == nullptr)
|
||||
cu = load_cu (per_cu, dwarf2_per_objfile, false);
|
||||
|
||||
|
@ -22415,7 +22397,7 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off,
|
|||
retval.per_objfile = dwarf2_per_objfile;
|
||||
retval.per_cu = cu->per_cu;
|
||||
|
||||
age_cached_comp_units (dwarf2_per_objfile);
|
||||
dwarf2_per_objfile->age_comp_units ();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -22471,7 +22453,7 @@ dwarf2_fetch_constant_bytes (sect_offset sect_off,
|
|||
enum bfd_endian byte_order;
|
||||
struct objfile *objfile = per_objfile->objfile;
|
||||
|
||||
dwarf2_cu *cu = per_cu->cu;
|
||||
dwarf2_cu *cu = per_objfile->get_cu (per_cu);
|
||||
if (cu == nullptr)
|
||||
cu = load_cu (per_cu, per_objfile, false);
|
||||
|
||||
|
@ -22594,7 +22576,7 @@ dwarf2_fetch_die_type_sect_off (sect_offset sect_off,
|
|||
{
|
||||
struct die_info *die;
|
||||
|
||||
dwarf2_cu *cu = per_cu->cu;
|
||||
dwarf2_cu *cu = per_objfile->get_cu (per_cu);
|
||||
if (cu == nullptr)
|
||||
cu = load_cu (per_cu, per_objfile, false);
|
||||
|
||||
|
@ -22644,7 +22626,7 @@ follow_die_sig_1 (struct die_info *src_die, struct signatured_type *sig_type,
|
|||
language_minimal))
|
||||
read_signatured_type (sig_type, dwarf2_per_objfile);
|
||||
|
||||
sig_cu = sig_type->per_cu.cu;
|
||||
sig_cu = dwarf2_per_objfile->get_cu (&sig_type->per_cu);
|
||||
gdb_assert (sig_cu != NULL);
|
||||
gdb_assert (to_underlying (sig_type->type_offset_in_section) != 0);
|
||||
temp_die.sect_off = sig_type->type_offset_in_section;
|
||||
|
@ -22818,11 +22800,11 @@ load_full_type_unit (dwarf2_per_cu_data *per_cu,
|
|||
gdb_assert (per_cu->is_debug_types);
|
||||
sig_type = (struct signatured_type *) per_cu;
|
||||
|
||||
gdb_assert (per_cu->cu == NULL);
|
||||
gdb_assert (per_objfile->get_cu (per_cu) == nullptr);
|
||||
|
||||
read_signatured_type (sig_type, per_objfile);
|
||||
|
||||
gdb_assert (per_cu->cu != NULL);
|
||||
gdb_assert (per_objfile->get_cu (per_cu) != nullptr);
|
||||
}
|
||||
|
||||
/* Read in a signatured type and build its CU and DIEs.
|
||||
|
@ -22836,7 +22818,7 @@ read_signatured_type (signatured_type *sig_type,
|
|||
struct dwarf2_per_cu_data *per_cu = &sig_type->per_cu;
|
||||
|
||||
gdb_assert (per_cu->is_debug_types);
|
||||
gdb_assert (per_cu->cu == NULL);
|
||||
gdb_assert (per_objfile->get_cu (per_cu) == nullptr);
|
||||
|
||||
cutu_reader reader (per_cu, per_objfile, nullptr, nullptr, false);
|
||||
|
||||
|
@ -23543,14 +23525,6 @@ dwarf2_cu::dwarf2_cu (dwarf2_per_cu_data *per_cu,
|
|||
producer_is_codewarrior (false),
|
||||
processing_has_namespace_info (false)
|
||||
{
|
||||
per_cu->cu = this;
|
||||
}
|
||||
|
||||
/* Destroy a dwarf2_cu. */
|
||||
|
||||
dwarf2_cu::~dwarf2_cu ()
|
||||
{
|
||||
per_cu->cu = NULL;
|
||||
}
|
||||
|
||||
/* Initialize basic fields of dwarf_cu CU according to DIE COMP_UNIT_DIE. */
|
||||
|
@ -23574,72 +23548,80 @@ prepare_one_comp_unit (struct dwarf2_cu *cu, struct die_info *comp_unit_die,
|
|||
cu->producer = dwarf2_string_attr (comp_unit_die, DW_AT_producer, cu);
|
||||
}
|
||||
|
||||
/* Increase the age counter on each cached compilation unit, and free
|
||||
any that are too old. */
|
||||
/* See read.h. */
|
||||
|
||||
static void
|
||||
age_cached_comp_units (struct dwarf2_per_objfile *dwarf2_per_objfile)
|
||||
dwarf2_cu *
|
||||
dwarf2_per_objfile::get_cu (dwarf2_per_cu_data *per_cu)
|
||||
{
|
||||
struct dwarf2_per_cu_data *per_cu, **last_chain;
|
||||
auto it = m_dwarf2_cus.find (per_cu);
|
||||
if (it == m_dwarf2_cus.end ())
|
||||
return nullptr;
|
||||
|
||||
dwarf2_clear_marks (dwarf2_per_objfile->per_bfd->read_in_chain);
|
||||
per_cu = dwarf2_per_objfile->per_bfd->read_in_chain;
|
||||
while (per_cu != NULL)
|
||||
return it->second;
|
||||
}
|
||||
|
||||
/* See read.h. */
|
||||
|
||||
void
|
||||
dwarf2_per_objfile::set_cu (dwarf2_per_cu_data *per_cu, dwarf2_cu *cu)
|
||||
{
|
||||
gdb_assert (this->get_cu (per_cu) == nullptr);
|
||||
|
||||
m_dwarf2_cus[per_cu] = cu;
|
||||
}
|
||||
|
||||
/* See read.h. */
|
||||
|
||||
void
|
||||
dwarf2_per_objfile::age_comp_units ()
|
||||
{
|
||||
/* Start by clearing all marks. */
|
||||
for (auto pair : m_dwarf2_cus)
|
||||
pair.second->mark = false;
|
||||
|
||||
/* Traverse all CUs, mark them and their dependencies if used recently
|
||||
enough. */
|
||||
for (auto pair : m_dwarf2_cus)
|
||||
{
|
||||
per_cu->cu->last_used ++;
|
||||
if (per_cu->cu->last_used <= dwarf_max_cache_age)
|
||||
dwarf2_mark (per_cu->cu);
|
||||
per_cu = per_cu->cu->read_in_chain;
|
||||
dwarf2_cu *cu = pair.second;
|
||||
|
||||
cu->last_used++;
|
||||
if (cu->last_used <= dwarf_max_cache_age)
|
||||
dwarf2_mark (cu);
|
||||
}
|
||||
|
||||
per_cu = dwarf2_per_objfile->per_bfd->read_in_chain;
|
||||
last_chain = &dwarf2_per_objfile->per_bfd->read_in_chain;
|
||||
while (per_cu != NULL)
|
||||
/* Delete all CUs still not marked. */
|
||||
for (auto it = m_dwarf2_cus.begin (); it != m_dwarf2_cus.end ();)
|
||||
{
|
||||
struct dwarf2_per_cu_data *next_cu;
|
||||
dwarf2_cu *cu = it->second;
|
||||
|
||||
next_cu = per_cu->cu->read_in_chain;
|
||||
|
||||
if (!per_cu->cu->mark)
|
||||
if (!cu->mark)
|
||||
{
|
||||
delete per_cu->cu;
|
||||
*last_chain = next_cu;
|
||||
delete cu;
|
||||
it = m_dwarf2_cus.erase (it);
|
||||
}
|
||||
else
|
||||
last_chain = &per_cu->cu->read_in_chain;
|
||||
|
||||
per_cu = next_cu;
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove a single compilation unit from the cache. */
|
||||
/* See read.h. */
|
||||
|
||||
static void
|
||||
free_one_cached_comp_unit (dwarf2_per_cu_data *target_per_cu,
|
||||
dwarf2_per_objfile *dwarf2_per_objfile)
|
||||
void
|
||||
dwarf2_per_objfile::remove_cu (dwarf2_per_cu_data *per_cu)
|
||||
{
|
||||
struct dwarf2_per_cu_data *per_cu, **last_chain;
|
||||
auto it = m_dwarf2_cus.find (per_cu);
|
||||
if (it == m_dwarf2_cus.end ())
|
||||
return;
|
||||
|
||||
per_cu = dwarf2_per_objfile->per_bfd->read_in_chain;
|
||||
last_chain = &dwarf2_per_objfile->per_bfd->read_in_chain;
|
||||
while (per_cu != NULL)
|
||||
{
|
||||
struct dwarf2_per_cu_data *next_cu;
|
||||
delete it->second;
|
||||
|
||||
next_cu = per_cu->cu->read_in_chain;
|
||||
m_dwarf2_cus.erase (it);
|
||||
}
|
||||
|
||||
if (per_cu == target_per_cu)
|
||||
{
|
||||
delete per_cu->cu;
|
||||
per_cu->cu = NULL;
|
||||
*last_chain = next_cu;
|
||||
break;
|
||||
}
|
||||
else
|
||||
last_chain = &per_cu->cu->read_in_chain;
|
||||
|
||||
per_cu = next_cu;
|
||||
}
|
||||
dwarf2_per_objfile::~dwarf2_per_objfile ()
|
||||
{
|
||||
remove_all_cus ();
|
||||
}
|
||||
|
||||
/* A set of CU "per_cu" pointer, DIE offset, and GDB type pointer.
|
||||
|
@ -23841,27 +23823,30 @@ dwarf2_add_dependence (struct dwarf2_cu *cu,
|
|||
|
||||
/* Subroutine of dwarf2_mark to pass to htab_traverse.
|
||||
Set the mark field in every compilation unit in the
|
||||
cache that we must keep because we are keeping CU. */
|
||||
cache that we must keep because we are keeping CU.
|
||||
|
||||
DATA is the dwarf2_per_objfile object in which to look up CUs. */
|
||||
|
||||
static int
|
||||
dwarf2_mark_helper (void **slot, void *data)
|
||||
{
|
||||
struct dwarf2_per_cu_data *per_cu;
|
||||
|
||||
per_cu = (struct dwarf2_per_cu_data *) *slot;
|
||||
dwarf2_per_cu_data *per_cu = (dwarf2_per_cu_data *) *slot;
|
||||
dwarf2_per_objfile *per_objfile = (dwarf2_per_objfile *) data;
|
||||
dwarf2_cu *cu = per_objfile->get_cu (per_cu);
|
||||
|
||||
/* cu->dependencies references may not yet have been ever read if QUIT aborts
|
||||
reading of the chain. As such dependencies remain valid it is not much
|
||||
useful to track and undo them during QUIT cleanups. */
|
||||
if (per_cu->cu == NULL)
|
||||
if (cu == nullptr)
|
||||
return 1;
|
||||
|
||||
if (per_cu->cu->mark)
|
||||
if (cu->mark)
|
||||
return 1;
|
||||
per_cu->cu->mark = true;
|
||||
|
||||
if (per_cu->cu->dependencies != NULL)
|
||||
htab_traverse (per_cu->cu->dependencies, dwarf2_mark_helper, NULL);
|
||||
cu->mark = true;
|
||||
|
||||
if (cu->dependencies != nullptr)
|
||||
htab_traverse (cu->dependencies, dwarf2_mark_helper, per_objfile);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -23874,19 +23859,11 @@ dwarf2_mark (struct dwarf2_cu *cu)
|
|||
{
|
||||
if (cu->mark)
|
||||
return;
|
||||
cu->mark = true;
|
||||
if (cu->dependencies != NULL)
|
||||
htab_traverse (cu->dependencies, dwarf2_mark_helper, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
dwarf2_clear_marks (struct dwarf2_per_cu_data *per_cu)
|
||||
{
|
||||
while (per_cu)
|
||||
{
|
||||
per_cu->cu->mark = false;
|
||||
per_cu = per_cu->cu->read_in_chain;
|
||||
}
|
||||
cu->mark = true;
|
||||
|
||||
if (cu->dependencies != nullptr)
|
||||
htab_traverse (cu->dependencies, dwarf2_mark_helper, cu->per_objfile);
|
||||
}
|
||||
|
||||
/* Trivial hash function for partial_die_info: the hash value of a DIE
|
||||
|
|
|
@ -43,6 +43,7 @@ struct tu_stats
|
|||
int nr_all_type_units_reallocs;
|
||||
};
|
||||
|
||||
struct dwarf2_cu;
|
||||
struct dwarf2_debug_sections;
|
||||
struct dwarf2_per_cu_data;
|
||||
struct mapped_index;
|
||||
|
@ -115,9 +116,6 @@ struct dwarf2_per_bfd
|
|||
TU. */
|
||||
signatured_type *get_tu (int index);
|
||||
|
||||
/* Free all cached compilation units. */
|
||||
void free_cached_comp_units ();
|
||||
|
||||
/* A convenience function to allocate a dwarf2_per_cu_data. The
|
||||
returned object has its "index" field set properly. The object
|
||||
is allocated on the dwarf2_per_bfd obstack. */
|
||||
|
@ -189,10 +187,6 @@ public:
|
|||
are doing. */
|
||||
struct tu_stats tu_stats {};
|
||||
|
||||
/* A chain of compilation units that are currently read in, so that
|
||||
they can be freed later. */
|
||||
dwarf2_per_cu_data *read_in_chain = NULL;
|
||||
|
||||
/* A table mapping DW_AT_dwo_name values to struct dwo_file objects.
|
||||
This is NULL if the table hasn't been allocated yet. */
|
||||
htab_up dwo_files;
|
||||
|
@ -303,6 +297,8 @@ struct dwarf2_per_objfile
|
|||
: objfile (objfile), per_bfd (per_bfd)
|
||||
{}
|
||||
|
||||
~dwarf2_per_objfile ();
|
||||
|
||||
/* Return pointer to string at .debug_line_str offset as read from BUF.
|
||||
BUF is assumed to be in a compilation unit described by CU_HEADER.
|
||||
Return *BYTES_READ_PTR count of bytes read from BUF. */
|
||||
|
@ -344,6 +340,22 @@ struct dwarf2_per_objfile
|
|||
UNSIGNED_P controls if the integer is unsigned or not. */
|
||||
struct type *int_type (int size_in_bytes, bool unsigned_p) const;
|
||||
|
||||
/* Get the dwarf2_cu matching PER_CU for this objfile. */
|
||||
dwarf2_cu *get_cu (dwarf2_per_cu_data *per_cu);
|
||||
|
||||
/* Set the dwarf2_cu matching PER_CU for this objfile. */
|
||||
void set_cu (dwarf2_per_cu_data *per_cu, dwarf2_cu *cu);
|
||||
|
||||
/* Remove/free the dwarf2_cu matching PER_CU for this objfile. */
|
||||
void remove_cu (dwarf2_per_cu_data *per_cu);
|
||||
|
||||
/* Free all cached compilation units. */
|
||||
void remove_all_cus ();
|
||||
|
||||
/* Increase the age counter on each CU compilation unit and free
|
||||
any that are too old. */
|
||||
void age_comp_units ();
|
||||
|
||||
/* Back link. */
|
||||
struct objfile *objfile;
|
||||
|
||||
|
@ -372,6 +384,10 @@ private:
|
|||
|
||||
/* Map from signatured types to the corresponding struct type. */
|
||||
std::unordered_map<signatured_type *, struct type *> m_type_map;
|
||||
|
||||
/* Map from the objfile-independent dwarf2_per_cu_data instances to the
|
||||
corresponding objfile-dependent dwarf2_cu instances. */
|
||||
std::unordered_map<dwarf2_per_cu_data *, dwarf2_cu *> m_dwarf2_cus;
|
||||
};
|
||||
|
||||
/* Get the dwarf2_per_objfile associated to OBJFILE. */
|
||||
|
@ -455,11 +471,6 @@ struct dwarf2_per_cu_data
|
|||
not the DWO file. */
|
||||
struct dwarf2_section_info *section;
|
||||
|
||||
/* Set to non-NULL iff this CU is currently loaded. When it gets freed out
|
||||
of the CU cache it gets reset to NULL again. This is left as NULL for
|
||||
dummy CUs (a CU header, but nothing else). */
|
||||
struct dwarf2_cu *cu;
|
||||
|
||||
/* The unit type of this CU. */
|
||||
enum dwarf_unit_type unit_type;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue