2021-05-18 04:16:06 +08:00
|
|
|
/* 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/>. */
|
|
|
|
|
|
|
|
#include "defs.h"
|
|
|
|
#include "dwarf2/cu.h"
|
|
|
|
#include "dwarf2/read.h"
|
|
|
|
|
|
|
|
/* Initialize dwarf2_cu to read PER_CU, in the context of PER_OBJFILE. */
|
|
|
|
|
|
|
|
dwarf2_cu::dwarf2_cu (dwarf2_per_cu_data *per_cu,
|
|
|
|
dwarf2_per_objfile *per_objfile)
|
|
|
|
: per_cu (per_cu),
|
|
|
|
per_objfile (per_objfile),
|
2021-05-18 04:16:06 +08:00
|
|
|
m_mark (false),
|
2021-05-18 04:16:06 +08:00
|
|
|
has_loclist (false),
|
|
|
|
checked_producer (false),
|
|
|
|
producer_is_gxx_lt_4_6 (false),
|
|
|
|
producer_is_gcc_lt_4_3 (false),
|
|
|
|
producer_is_icc (false),
|
|
|
|
producer_is_icc_lt_14 (false),
|
|
|
|
producer_is_codewarrior (false),
|
[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
|
|
|
processing_has_namespace_info (false),
|
|
|
|
load_all_dies (false)
|
2021-05-18 04:16:06 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/* See cu.h. */
|
|
|
|
|
|
|
|
struct type *
|
|
|
|
dwarf2_cu::addr_sized_int_type (bool unsigned_p) const
|
|
|
|
{
|
|
|
|
int addr_size = this->per_cu->addr_size ();
|
2021-10-19 02:15:21 +08:00
|
|
|
return objfile_int_type (this->per_objfile->objfile, addr_size, unsigned_p);
|
2021-05-18 04:16:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Start a symtab for DWARF. NAME, COMP_DIR, LOW_PC are passed to the
|
|
|
|
buildsym_compunit constructor. */
|
|
|
|
|
|
|
|
struct compunit_symtab *
|
|
|
|
dwarf2_cu::start_symtab (const char *name, const char *comp_dir,
|
|
|
|
CORE_ADDR low_pc)
|
|
|
|
{
|
|
|
|
gdb_assert (m_builder == nullptr);
|
|
|
|
|
|
|
|
m_builder.reset (new struct buildsym_compunit
|
|
|
|
(this->per_objfile->objfile,
|
Remove dwarf2_cu::language
dwarf2_cu has a 'language' value, but dwarf2_per_cu_data also holds a
value of this same type. There doesn't seem to be any reason to keep
two copies of this value. This patch removes the field from
dwarf2_cu, and arranges to set the value in the per-CU object instead.
Note that the value must still be set when expanding the full CU.
This is needed because the CUs will not be scanned when a DWARF index
is in use.
gdb/ChangeLog
2021-06-25 Tom Tromey <tom@tromey.com>
* dwarf2/read.c (process_psymtab_comp_unit): Don't set 'lang'.
(scan_partial_symbols, partial_die_parent_scope)
(add_partial_symbol, add_partial_subprogram)
(compute_delayed_physnames, rust_union_quirks)
(process_full_comp_unit, process_full_type_unit)
(process_imported_unit_die, process_die, dw2_linkage_name)
(dwarf2_compute_name, dwarf2_physname, read_import_statement)
(read_file_scope, queue_and_load_dwo_tu, read_func_scope)
(read_variable, dwarf2_get_subprogram_pc_bounds)
(dwarf2_attach_fields_to_type, dwarf2_add_member_fn)
(dwarf2_attach_fn_fields_to_type)
(quirk_ada_thick_pointer_struct, read_structure_type)
(handle_struct_member_die, process_structure_scope)
(read_array_type, read_array_order, prototyped_function_p)
(read_subroutine_type, dwarf2_init_complex_target_type)
(read_base_type, read_subrange_type, read_unspecified_type)
(load_partial_dies, partial_die_info::fixup, set_cu_language)
(new_symbol, need_gnat_info, determine_prefix, typename_concat)
(dwarf2_canonicalize_name, follow_die_offset)
(prepare_one_comp_unit): Update.
* dwarf2/cu.c (dwarf2_cu::start_symtab): Update.
2021-06-26 02:23:04 +08:00
|
|
|
name, comp_dir, per_cu->lang, low_pc));
|
2021-05-18 04:16:06 +08:00
|
|
|
|
|
|
|
list_in_scope = get_builder ()->get_file_symbols ();
|
|
|
|
|
|
|
|
get_builder ()->record_debugformat ("DWARF 2");
|
|
|
|
get_builder ()->record_producer (producer);
|
|
|
|
|
|
|
|
processing_has_namespace_info = false;
|
|
|
|
|
|
|
|
return get_builder ()->get_compunit_symtab ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* See read.h. */
|
|
|
|
|
|
|
|
struct type *
|
|
|
|
dwarf2_cu::addr_type () const
|
|
|
|
{
|
|
|
|
struct objfile *objfile = this->per_objfile->objfile;
|
|
|
|
struct type *void_type = objfile_type (objfile)->builtin_void;
|
|
|
|
struct type *addr_type = lookup_pointer_type (void_type);
|
|
|
|
int addr_size = this->per_cu->addr_size ();
|
|
|
|
|
|
|
|
if (TYPE_LENGTH (addr_type) == addr_size)
|
|
|
|
return addr_type;
|
|
|
|
|
|
|
|
addr_type = addr_sized_int_type (addr_type->is_unsigned ());
|
|
|
|
return addr_type;
|
|
|
|
}
|
2021-05-18 04:16:06 +08:00
|
|
|
|
|
|
|
/* A hashtab traversal function that marks the dependent CUs. */
|
|
|
|
|
|
|
|
static int
|
|
|
|
dwarf2_mark_helper (void **slot, void *data)
|
|
|
|
{
|
|
|
|
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->m_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 (cu != nullptr)
|
|
|
|
cu->mark ();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* See dwarf2/cu.h. */
|
|
|
|
|
|
|
|
void
|
|
|
|
dwarf2_cu::mark ()
|
|
|
|
{
|
|
|
|
if (!m_mark)
|
|
|
|
{
|
|
|
|
m_mark = true;
|
|
|
|
if (m_dependencies != nullptr)
|
|
|
|
htab_traverse (m_dependencies, dwarf2_mark_helper, per_objfile);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* See dwarf2/cu.h. */
|
|
|
|
|
|
|
|
void
|
|
|
|
dwarf2_cu::add_dependence (struct dwarf2_per_cu_data *ref_per_cu)
|
|
|
|
{
|
|
|
|
void **slot;
|
|
|
|
|
|
|
|
if (m_dependencies == nullptr)
|
|
|
|
m_dependencies
|
|
|
|
= htab_create_alloc_ex (5, htab_hash_pointer, htab_eq_pointer,
|
|
|
|
NULL, &comp_unit_obstack,
|
|
|
|
hashtab_obstack_allocate,
|
|
|
|
dummy_obstack_deallocate);
|
|
|
|
|
|
|
|
slot = htab_find_slot (m_dependencies, ref_per_cu, INSERT);
|
|
|
|
if (*slot == nullptr)
|
|
|
|
*slot = ref_per_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
|
|
|
|
|
|
|
/* See dwarf2/cu.h. */
|
|
|
|
|
|
|
|
buildsym_compunit *
|
|
|
|
dwarf2_cu::get_builder ()
|
|
|
|
{
|
|
|
|
/* If this CU has a builder associated with it, use that. */
|
|
|
|
if (m_builder != nullptr)
|
|
|
|
return m_builder.get ();
|
|
|
|
|
|
|
|
if (per_objfile->sym_cu != nullptr)
|
|
|
|
return per_objfile->sym_cu->m_builder.get ();
|
|
|
|
|
|
|
|
gdb_assert_not_reached ("");
|
|
|
|
}
|