binutils-gdb/gdb/dwarf2/cu.h

279 lines
11 KiB
C
Raw Normal View History

/* DWARF CU data structure
Copyright (C) 2021 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_CU_H
#define GDB_DWARF2_CU_H
#include "buildsym.h"
#include "dwarf2/comp-unit-head.h"
#include "gdbsupport/gdb_optional.h"
/* Type used for delaying computation of method physnames.
See comments for compute_delayed_physnames. */
struct delayed_method_info
{
/* The type to which the method is attached, i.e., its parent class. */
struct type *type;
/* The index of the method in the type's function fieldlists. */
int fnfield_index;
/* The index of the method in the fieldlist. */
int index;
/* The name of the DIE. */
const char *name;
/* The DIE associated with this method. */
struct die_info *die;
};
/* Internal state when decoding a particular compilation unit. */
struct dwarf2_cu
{
explicit dwarf2_cu (dwarf2_per_cu_data *per_cu,
dwarf2_per_objfile *per_objfile);
DISABLE_COPY_AND_ASSIGN (dwarf2_cu);
/* TU version of handle_DW_AT_stmt_list for read_type_unit_scope.
Create the set of symtabs used by this TU, or if this TU is sharing
symtabs with another TU and the symtabs have already been created
then restore those symtabs in the line header.
We don't need the pc/line-number mapping for type units. */
void setup_type_unit_groups (struct die_info *die);
/* Start a symtab for DWARF. NAME, COMP_DIR, LOW_PC are passed to the
buildsym_compunit constructor. */
struct compunit_symtab *start_symtab (const char *name,
const char *comp_dir,
CORE_ADDR low_pc);
/* Reset the builder. */
void reset_builder () { m_builder.reset (); }
/* Return a type that is a generic pointer type, the size of which
matches the address size given in the compilation unit header for
this CU. */
struct type *addr_type () const;
/* Find an integer type the same size as the address size given in
the compilation unit header for this CU. UNSIGNED_P controls if
the integer is unsigned or not. */
struct type *addr_sized_int_type (bool unsigned_p) const;
/* Mark this CU as used. */
void mark ();
/* Clear the mark on this CU. */
void clear_mark ()
{
m_mark = false;
}
/* True if this CU has been marked. */
bool is_marked () const
{
return m_mark;
}
/* Add a dependence relationship from this cu to REF_PER_CU. */
void add_dependence (struct dwarf2_per_cu_data *ref_per_cu);
/* The header of the compilation unit. */
struct comp_unit_head header {};
/* Base address of this compilation unit. */
gdb::optional<CORE_ADDR> base_address;
/* The language we are debugging. */
const struct language_defn *language_defn = nullptr;
const char *producer = nullptr;
private:
/* The symtab builder for this CU. This is only non-NULL when full
symbols are being read. */
std::unique_ptr<buildsym_compunit> m_builder;
/* A set of pointers to dwarf2_per_cu_data objects for compilation
units referenced by this one. Only set during full symbol processing;
partial symbol tables do not have dependencies. */
htab_t m_dependencies = nullptr;
public:
/* The generic symbol table building routines have separate lists for
file scope symbols and all all other scopes (local scopes). So
we need to select the right one to pass to add_symbol_to_list().
We do it by keeping a pointer to the correct list in list_in_scope.
FIXME: The original dwarf code just treated the file scope as the
first local scope, and all other local scopes as nested local
scopes, and worked fine. Check to see if we really need to
distinguish these in buildsym.c. */
struct pending **list_in_scope = nullptr;
/* Hash table holding all the loaded partial DIEs
with partial_die->offset.SECT_OFF as hash. */
htab_t partial_dies = nullptr;
/* Storage for things with the same lifetime as this read-in compilation
unit, including partial DIEs. */
auto_obstack comp_unit_obstack;
/* Backlink to our per_cu entry. */
struct dwarf2_per_cu_data *per_cu;
/* The dwarf2_per_objfile that owns this. */
dwarf2_per_objfile *per_objfile;
/* How many compilation units ago was this CU last referenced? */
int last_used = 0;
/* A hash table of DIE cu_offset for following references with
die_info->offset.sect_off as hash. */
htab_t die_hash = nullptr;
/* Full DIEs if read in. */
struct die_info *dies = nullptr;
/* Header data from the line table, during full symbol processing. */
struct line_header *line_header = nullptr;
/* Non-NULL if LINE_HEADER is owned by this DWARF_CU. Otherwise,
it's owned by dwarf2_per_bfd::line_header_hash. If non-NULL,
this is the DW_TAG_compile_unit die for this CU. We'll hold on
to the line header as long as this DIE is being processed. See
process_die_scope. */
die_info *line_header_die_owner = nullptr;
/* A list of methods which need to have physnames computed
after all type information has been read. */
std::vector<delayed_method_info> method_list;
/* To be copied to symtab->call_site_htab. */
htab_t call_site_htab = nullptr;
/* Non-NULL if this CU came from a DWO file.
There is an invariant here that is important to remember:
Except for attributes copied from the top level DIE in the "main"
(or "stub") file in preparation for reading the DWO file
(e.g., DW_AT_addr_base), we KISS: there is only *one* CU.
Either there isn't a DWO file (in which case this is NULL and the point
is moot), or there is and either we're not going to read it (in which
case this is NULL) or there is and we are reading it (in which case this
is non-NULL). */
struct dwo_unit *dwo_unit = nullptr;
/* The DW_AT_addr_base (DW_AT_GNU_addr_base) attribute if present.
Note this value comes from the Fission stub CU/TU's DIE. */
gdb::optional<ULONGEST> addr_base;
/* The DW_AT_GNU_ranges_base attribute, if present.
This is only relevant in the context of pre-DWARF 5 split units. In this
context, there is a .debug_ranges section in the linked executable,
containing all the ranges data for all the compilation units. Each
skeleton/stub unit has (if needed) a DW_AT_GNU_ranges_base attribute that
indicates the base of its contribution to that section. The DW_AT_ranges
attributes in the split-unit are of the form DW_FORM_sec_offset and point
into the .debug_ranges section of the linked file. However, they are not
"true" DW_FORM_sec_offset, because they are relative to the base of their
compilation unit's contribution, rather than relative to the beginning of
the section. The DW_AT_GNU_ranges_base value must be added to it to make
it relative to the beginning of the section.
Note that the value is zero when we are not in a pre-DWARF 5 split-unit
case, so this value can be added without needing to know whether we are in
this case or not.
N.B. If a DW_AT_ranges attribute is found on the DW_TAG_compile_unit in the
skeleton/stub, it must not have the base added, as it already points to the
right place. And since the DW_TAG_compile_unit DIE in the split-unit can't
have a DW_AT_ranges attribute, we can use the
die->tag != DW_AT_compile_unit
to determine whether the base should be added or not. */
ULONGEST gnu_ranges_base = 0;
/* The DW_AT_rnglists_base attribute, if present.
This is used when processing attributes of form DW_FORM_rnglistx in
non-split units. Attributes of this form found in a split unit don't
use it, as split-unit files have their own non-shared .debug_rnglists.dwo
section. */
ULONGEST rnglists_base = 0;
/* The DW_AT_loclists_base attribute if present. */
ULONGEST loclist_base = 0;
/* When reading debug info generated by older versions of rustc, we
have to rewrite some union types to be struct types with a
variant part. This rewriting must be done after the CU is fully
read in, because otherwise at the point of rewriting some struct
type might not have been fully processed. So, we keep a list of
all such types here and process them after expansion. */
std::vector<struct type *> rust_unions;
/* The DW_AT_str_offsets_base attribute if present. For DWARF 4 version DWO
files, the value is implicitly zero. For DWARF 5 version DWO files, the
value is often implicit and is the size of the header of
.debug_str_offsets section (8 or 4, depending on the address size). */
gdb::optional<ULONGEST> str_offsets_base;
/* Mark used when releasing cached dies. */
bool m_mark : 1;
/* This CU references .debug_loc. See the symtab->locations_valid field.
This test is imperfect as there may exist optimized debug code not using
any location list and still facing inlining issues if handled as
unoptimized code. For a future better test see GCC PR other/32998. */
bool has_loclist : 1;
/* These cache the results for producer_is_* fields. CHECKED_PRODUCER is true
if all the producer_is_* fields are valid. This information is cached
because profiling CU expansion showed excessive time spent in
producer_is_gxx_lt_4_6. */
bool checked_producer : 1;
bool producer_is_gxx_lt_4_6 : 1;
bool producer_is_gcc_lt_4_3 : 1;
bool producer_is_icc : 1;
bool producer_is_icc_lt_14 : 1;
bool producer_is_codewarrior : 1;
/* When true, the file that we're processing is known to have
debugging info for C++ namespaces. GCC 3.3.x did not produce
this information, but later versions do. */
bool processing_has_namespace_info : 1;
[gdb/symtab] Fix Dwarf Error: cannot find DIE When loading the debug info package libLLVM.so.10-10.0.1-lp152.30.4.x86_64.debug from openSUSE Leap 15.2, we run into a dwarf error: ... $ gdb -q -batch libLLVM.so.10-10.0.1-lp152.30.4.x86_64.debug Dwarf Error: Cannot not find DIE at 0x18a936e7 \ [from module libLLVM.so.10-10.0.1-lp152.30.4.x86_64.debug] ... The DIE @ 0x18a936e7 does in fact exist, and is part of a CU @ 0x18a23e52. No error message is printed when using -readnow. What happens is the following: - a dwarf2_per_cu_data P is created for the CU. - a dwarf2_cu A is created for the same CU. - another dwarf2_cu B is created for the same CU. - the dwarf2_cu B is set in per_objfile->m_dwarf2_cus, such that per_objfile->get_cu (P) returns B. - P->load_all_dies is set to 1. - all dies are read into the A->partial_dies htab - dwarf2_cu A is destroyed. - we try to find the partial_die for the DIE @ 0x18a936e7 in B->partial_dies. We can't find it, but do not try to load all dies, because P->load_all_dies is already set to 1. - an error message is generated. The question is why we're creating dwarf2_cu A and B for the same CU. The dwarf2_cu A is created here: ... (gdb) bt #0 dwarf2_cu::dwarf2_cu (this=0x79a9660, per_cu=0x23c0b30, per_objfile=0x1ad01b0) at dwarf2/cu.c:38 #1 0x0000000000675799 in cutu_reader::cutu_reader (this=0x7fffffffd040, this_cu=0x23c0b30, per_objfile=0x1ad01b0, abbrev_table=0x0, existing_cu=0x0, skip_partial=false) at dwarf2/read.c:6487 #2 0x0000000000676eb3 in process_psymtab_comp_unit (this_cu=0x23c0b30, per_objfile=0x1ad01b0, want_partial_unit=false, pretend_language=language_minimal) at dwarf2/read.c:7028 ... And the dwarf2_cu B is created here: ... (gdb) bt #0 dwarf2_cu::dwarf2_cu (this=0x885e8c0, per_cu=0x23c0b30, per_objfile=0x1ad01b0) at dwarf2/cu.c:38 #1 0x0000000000675799 in cutu_reader::cutu_reader (this=0x7fffffffcc50, this_cu=0x23c0b30, per_objfile=0x1ad01b0, abbrev_table=0x0, existing_cu=0x0, skip_partial=false) at dwarf2/read.c:6487 #2 0x0000000000678118 in load_partial_comp_unit (this_cu=0x23c0b30, per_objfile=0x1ad01b0, existing_cu=0x0) at dwarf2/read.c:7436 #3 0x000000000069721d in find_partial_die (sect_off=(unknown: 0x18a55054), offset_in_dwz=0, cu=0x0) at dwarf2/read.c:19391 #4 0x000000000069755b in partial_die_info::fixup (this=0x9096900, cu=0xa6a85f0) at dwarf2/read.c:19512 #5 0x0000000000697586 in partial_die_info::fixup (this=0x8629bb0, cu=0xa6a85f0) at dwarf2/read.c:19516 #6 0x00000000006787b1 in scan_partial_symbols (first_die=0x8629b40, lowpc=0x7fffffffcf58, highpc=0x7fffffffcf50, set_addrmap=0, cu=0x79a9660) at dwarf2/read.c:7563 #7 0x0000000000678878 in scan_partial_symbols (first_die=0x796ebf0, lowpc=0x7fffffffcf58, highpc=0x7fffffffcf50, set_addrmap=0, cu=0x79a9660) at dwarf2/read.c:7580 #8 0x0000000000676b82 in process_psymtab_comp_unit_reader (reader=0x7fffffffd040, info_ptr=0x7fffc1b3f29b, comp_unit_die=0x6ea90f0, pretend_language=language_minimal) at dwarf2/read.c:6954 #9 0x0000000000676ffd in process_psymtab_comp_unit (this_cu=0x23c0b30, per_objfile=0x1ad01b0, want_partial_unit=false, pretend_language=language_minimal) at dwarf2/read.c:7057 ... So in frame #9, a cutu_reader is created with dwarf2_cu A. Then a fixup takes us to the following CU @ 0x18aa33d6, in frame #5. And a similar fixup in frame #4 takes us back to CU @ 0x18a23e52. At that point, there's no information available that we're already trying to read that CU, and we end up creating another cutu_reader with dwarf2_cu B. It seems that there are two related problems: - creating two dwarf2_cu's is not optimal - the unoptimal case is not handled correctly This patch addresses the last problem, by moving the load_all_dies flag from dwarf2_per_cu_data to dwarf2_cu, such that it is paired with the partial_dies field, which ensures that the two can be kept in sync. Tested on x86_64-linux. gdb/ChangeLog: 2021-05-27 Tom de Vries <tdevries@suse.de> PR symtab/27898 * dwarf2/cu.c (dwarf2_cu::dwarf2_cu): Add load_all_dies init. * dwarf2/cu.h (dwarf2_cu): Add load_all_dies field. * dwarf2/read.c (load_partial_dies, find_partial_die): Update. * dwarf2/read.h (dwarf2_per_cu_data::dwarf2_per_cu_data): Remove load_all_dies init. (dwarf2_per_cu_data): Remove load_all_dies field.
2021-05-27 21:22:38 +08:00
/* This flag will be set when reading partial DIEs if we need to load
absolutely all DIEs for this compilation unit, instead of just the ones
we think are interesting. It gets set if we look for a DIE in the
hash table and don't find it. */
bool load_all_dies : 1;
struct partial_die_info *find_partial_die (sect_offset sect_off);
/* Get the buildsym_compunit for this CU. */
[gdb/symtab] Fix infinite recursion in dwarf2_cu::get_builder(), again This is another attempt at fixing the problem described in commit 4cf88725da1 "[gdb/symtab] Fix infinite recursion in dwarf2_cu::get_builder()", which was reverted in commit 3db19b2d724. First off, some context. A DWARF CU can be viewed as a symbol table: toplevel children of a CU DIE represent symbol table entries for that CU. Furthermore, there is a hierarchy: a symbol table entry such as a function itself has a symbol table containing parameters and local variables. The dwarf reader maintains a notion of current symbol table (that is: the symbol table a new symbol needs to be entered into) in dwarf2_cu member list_in_scope. A problem then presents itself when reading inter-CU references: - a new symbol read from a CU B needs to be entered into the symbol table of another CU A. - the notion of current symbol table is tracked on a per-CU basis. This is addressed in inherit_abstract_dies by temporarily overwriting the list_in_scope for CU B with the one for CU A. The current symbol table is one aspect of the current dwarf reader context that is tracked, but there are more, f.i. ones that are tracked via the dwarf2_cu member m_builder, f.i. m_builder->m_local_using_directives. A similar problem exists in relation to inter-CU references, but a different solution was chosen: - to keep track of an ancestor field in dwarf2_cu, which is updated when traversing inter-CU references, and - to use the ancestor field in dwarf2_cu::get_builder to return the m_builder in scope. There is no actual concept of a CU having an ancestor, it just marks the most recent CU from which a CU was inter-CU-referenced. Consequently, when following inter-CU references from a CU A to another CU B and back to CU A, the ancestors form a cycle, which causes dwarf2_cu::get_builder to hang or segfault, as reported in PR26327. ISTM that the ancestor implementation is confusing and fragile, and should go. Furthermore, it seems that keeping track of the m_builder in scope can be handled simply with a per-objfile variable. Fix the hang / segfault by: - keeping track of the m_builder in scope using a new variable per_obj->sym_cu, and - using it in dwarf2_cu::get_builder. Tested on x86_64-linux (openSUSE Leap 15.2), no regressions for config: - using default gcc version 7.5.0 (with 5 unexpected FAILs) - gcc 10.3.0 and target board unix/-flto/-O0/-flto-partition=none/-ffat-lto-objects (with 1000 unexpected FAILs) gdb/ChangeLog: 2021-06-16 Tom de Vries <tdevries@suse.de> PR symtab/26327 * dwarf2/cu.h (dwarf2_cu::ancestor): Remove. (dwarf2_cu::get_builder): Declare and move ... * dwarf2/cu.c (dwarf2_cu::get_builder): ... here. Use sym_cu instead of ancestor. Assert return value is non-null. * dwarf2/read.c (read_file_scope): Set per_objfile->sym_cu. (follow_die_offset, follow_die_sig_1): Remove setting of ancestor. (dwarf2_per_objfile): Add sym_cu field.
2021-06-16 18:44:30 +08:00
buildsym_compunit *get_builder ();
};
#endif /* GDB_DWARF2_CU_H */