With recent versions of gdb (somewhere around 8.x to 10.0.50.20200731-git), I've noticed that GDB sometimes hangs when debugging C++ programs compiled with Clang/LLVM 10.0.1. This can occur either initially when reading symbols, or during debugging after a breakpoint fires. I noticed a workaround was sent previously: "Fixing get_builder() function in dwarf2/read.c", which appears to be for the same problem. I don't know what the correct solution is wrt parsing DWARF symbols, but I'm experiencing similar symptoms, and my stacktrace looks similar to the second one sent out by Slava. I can provide the binary (~9MB), but not the direct source (it's 447.dealII from SPEC CPU2006).
(In reply to d.c.ddcc from comment #0) > I noticed a workaround was sent previously: "Fixing get_builder() function > in dwarf2/read.c" https://sourceware.org/pipermail/gdb-patches/2020-June/169471.html
Like I said in the original report, a reproducer program or at least binary would be useful so we can analyze the problem and make sure we fix the problem the right way, and not only cover up the problem.
Created attachment 12737 [details] 447.dealII, hangs on reading symbols in GDB #0 0x0000560a5ab7e27c in dwarf2_cu::get_builder (this=0x560a5eb32060) at ../../gdb/dwarf2/read.c:606 dwarf2_name(die, cu) = 0x7f9fe022b8d3 "arg_list" #1 new_symbol (die=0x560a5f391500, type=0x0, cu=0x560a5eb32060, space=<optimized out>) at ../../gdb/dwarf2/read.c:21225 dwarf2_name(die, cu) = 0x7f9fe022b8d3 "arg_list" #2 0x0000560a5ab881a1 in process_die (die=0x560a5f391500, cu=0x560a5eb32060) at ../../gdb/dwarf2/read.c:10214 dwarf2_name(die, cu) = 0x560a5f3b7200 "do_call<void (*)(std::vector<DataOutBase::Patch<3, 3>, std::allocator<DataOutBase::Patch<3, 3> > > const&, Table<2, double>&), boost::tuples::tuple<std::vector<DataOutBase::Patch<3, 3>, std::allocator<DataOutBase::Patch<3, 3> > > const&, Table<2, double>&, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type> >" #3 0x0000560a5ab86930 in inherit_abstract_dies (die=0x560a5d66ab00, cu=0x560a5d479a30) at ../../gdb/dwarf2/read.c:13132 #4 0x0000560a5ab86d83 in read_func_scope (die=0x560a5d66ab00, cu=0x560a5d479a30) at ../../gdb/dwarf2/read.c:13260 #5 0x0000560a5ab88239 in process_die (die=0x560a5d66ab00, cu=0x560a5d479a30) at ../../gdb/dwarf2/read.c:10136 #6 0x0000560a5ab86d1b in read_func_scope (die=0x560a5d66aa30, cu=0x560a5d479a30) at ../../gdb/dwarf2/read.c:13255 #7 0x0000560a5ab88239 in process_die (die=0x560a5d66aa30, cu=0x560a5d479a30) at ../../gdb/dwarf2/read.c:10136 #8 0x0000560a5ab86d1b in read_func_scope (die=0x560a5d66a950, cu=0x560a5d479a30) at ../../gdb/dwarf2/read.c:13255 #9 0x0000560a5ab88239 in process_die (die=0x560a5d66a950, cu=0x560a5d479a30) at ../../gdb/dwarf2/read.c:10136 #10 0x0000560a5ab86d1b in read_func_scope (die=0x560a5d66a7e0, cu=0x560a5d479a30) at ../../gdb/dwarf2/read.c:13255 #11 0x0000560a5ab88239 in process_die (die=0x560a5d66a7e0, cu=0x560a5d479a30) at ../../gdb/dwarf2/read.c:10136 #12 0x0000560a5ab86d1b in read_func_scope (die=0x560a5d6683e0, cu=0x560a5d479a30) at ../../gdb/dwarf2/read.c:13255 #13 0x0000560a5ab88239 in process_die (die=0x560a5d6683e0, cu=0x560a5d479a30) at ../../gdb/dwarf2/read.c:10136 #14 0x0000560a5ab86d1b in read_func_scope (die=0x560a5d6682c0, cu=0x560a5d479a30) at ../../gdb/dwarf2/read.c:13255 #15 0x0000560a5ab88239 in process_die (die=0x560a5d6682c0, cu=0x560a5d479a30) at ../../gdb/dwarf2/read.c:10136 #16 0x0000560a5ab86d1b in read_func_scope (die=0x560a5d668100, cu=0x560a5d479a30) at ../../gdb/dwarf2/read.c:13255 #17 0x0000560a5ab88239 in process_die (die=0x560a5d668100, cu=0x560a5d479a30) at ../../gdb/dwarf2/read.c:10136 #18 0x0000560a5ab8b8cb in read_lexical_block_scope (die=0x560a5d65d420, cu=0x560a5d479a30) at ../../gdb/dwarf2/read.c:13391 #19 0x0000560a5ab89222 in process_die (die=0x560a5d65d420, cu=0x560a5d479a30) at ../../gdb/dwarf2/read.c:10141 #20 0x0000560a5ab86d1b in read_func_scope (die=0x560a5d60a830, cu=0x560a5d479a30) at ../../gdb/dwarf2/read.c:13255 #21 0x0000560a5ab88239 in process_die (die=0x560a5d60a830, cu=0x560a5d479a30) at ../../gdb/dwarf2/read.c:10136 #22 0x0000560a5ab8b4a9 in read_file_scope (die=0x560a5d457e90, cu=0x560a5d479a30) at ../../gdb/dwarf2/read.c:11112 #23 0x0000560a5ab89190 in process_die (die=0x560a5d457e90, cu=0x560a5d479a30) at ../../gdb/dwarf2/read.c:10123 #24 0x0000560a5ab8bf03 in process_full_comp_unit (pretend_language=<optimized out>, cu=0x560a5d479a30) at ../../gdb/dwarf2/read.c:9893 #25 process_queue (per_objfile=0x560a5d231940) at ../../gdb/dwarf2/read.c:9134 #26 dw2_do_instantiate_symtab (per_cu=per_cu@entry=0x560a5d470180, per_objfile=per_objfile@entry=0x560a5d231940, skip_partial=skip_partial@entry=false) at ../../gdb/dwarf2/read.c:2411 #27 0x0000560a5ab8c457 in dw2_instantiate_symtab (per_cu=0x560a5d470180, per_objfile=0x560a5d231940, skip_partial=<optimized out>) at ../../gdb/dwarf2/read.c:2434 #28 0x0000560a5ab8d10c in dw2_lookup_symbol (objfile=<optimized out>, block_index=GLOBAL_BLOCK, name=0x560a5d3feaa0 "main", domain=VAR_DOMAIN) at ../../gdb/dwarf2/read.c:3623 #29 0x0000560a5ad420fb in lookup_symbol_via_quick_fns (domain=VAR_DOMAIN, name=0x560a5d3feaa0 "main", block_index=GLOBAL_BLOCK, objfile=0x560a5d3fe3e0) at ../../gdb/symtab.c:2373 #30 lookup_symbol_in_objfile (objfile=0x560a5d3fe3e0, block_index=GLOBAL_BLOCK, name=0x560a5d3feaa0 "main", domain=VAR_DOMAIN) at ../../gdb/symtab.c:2522 #31 0x0000560a5ad42344 in lookup_symbol_global_or_static_iterator_cb (objfile=<optimized out>, cb_data=0x7ffea086f6f0) at ../../gdb/symtab.c:2596 #32 0x0000560a5ad0b744 in svr4_iterate_over_objfiles_in_search_order (gdbarch=<optimized out>, cb=0x560a5ad42320 <lookup_symbol_global_or_static_iterator_cb(objfile*, void*)>, cb_data=0x7ffea086f6f0, current_objfile=0x0) at ../../gdb/solib-svr4.c:3248 #33 0x0000560a5ad3c4be in lookup_global_or_static_symbol (name=0x560a5d3feaa0 "main", block_index=GLOBAL_BLOCK, objfile=0x0, domain=VAR_DOMAIN) at ../../gdb/symtab.c:2641 #34 0x0000560a5ad41b6d in lookup_global_symbol (name=0x560a5d3feaa0 "main", block=<optimized out>, domain=VAR_DOMAIN) at ../../gdb/symtab.c:2691 #35 0x0000560a5ad417d4 in lookup_symbol_aux (name=0x560a5d3feaa0 "main", match_type=match_type@entry=symbol_name_match_type::FULL, block=block@entry=0x0, domain=domain@entry=VAR_DOMAIN, language=language@entry=language_c, is_a_field_of_this=is_a_field_of_this@entry=0x0) at ../../gdb/symtab.c:2089 #36 0x0000560a5ad41934 in lookup_symbol_in_language (name=<optimized out>, block=block@entry=0x0, domain=domain@entry=VAR_DOMAIN, lang=lang@entry=language_c, is_a_field_of_this=is_a_field_of_this@entry=0x0) at ../../gdb/symtab.c:1881 #37 0x0000560a5ad2cf9c in set_initial_language () at ../../gdb/symfile.c:1683 #38 0x0000560a5ac41840 in catch_command_errors (command=<optimized out>, arg=<optimized out>, from_tty=<optimized out>) at ../../gdb/main.c:457 #39 0x0000560a5ac435cd in captured_main_1 (context=<optimized out>) at ../../gdb/main.c:1123 #40 0x0000560a5ac4381f in captured_main (data=0x7ffea086fba0) at ../../gdb/main.c:1243 #41 gdb_main (args=args@entry=0x7ffea086fbc0) at ../../gdb/main.c:1268 #42 0x0000560a5aa57640 in main (argc=<optimized out>, argv=<optimized out>) at ../../gdb/gdb.c:32
I've added a problematic binary as an attachment, plus a stack trace, and the result of manually calling `dwarf2_die(die, cu)` on a couple of the top stack frames. Let me know if you need anything else; I could also supply a packed rr trace of GDB loading the file, if that's useful. Note that this binary is using musl libc with a custom loader path, so it may not be directly executable.
Thanks! The infinite can be triggered without running the binary, with: ./gdb -nx -readnow 447.dealII Note that I made GDB crash in other fun ways with this binary 1. Create breakpoint on main $./gdb -nx ~/Downloads/447.dealII (gdb) b main [1] 1054570 abort (core dumped) ./gdb -nx ~/Downloads/447.dealII 2. With the index-cache Populate the index-cache for this binary: $ ./gdb -nx -iex "set index-cache on" ~/Downloads/447.dealII -batch It should create this file: ~/.cache/gdb/ad3eca2473ddcca165529cecf211308a2e8f5291.gdb-index Then, starting GDB again crashes: $./gdb -nx -iex "set index-cache on" ~/Downloads/447.dealII -batch [1] 1054856 abort (core dumped) ./gdb -nx -iex "set index-cache on" ~/Downloads/447.dealII -batch
Tentative patch, prevents introducing cycles in ancestor chain: ... diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 37409c5c3f..72e5446b8b 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -22947,7 +22947,19 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz, temp_die.sect_off = sect_off; if (target_cu != cu) - target_cu->ancestor = cu; + { + bool cycle_p = false; + for (struct dwarf2_cu *tmp = cu->ancestor; tmp; tmp = tmp->ancestor) + { + if (tmp != target_cu) + continue; + + cycle_p = true; + break; + } + if (!cycle_p) + target_cu->ancestor = cu; + } return (struct die_info *) htab_find_with_hash (target_cu->die_hash, &temp_die, @@ -24256,7 +24268,8 @@ dwarf2_cu::dwarf2_cu (dwarf2_per_cu_data *per_cu, producer_is_icc (false), producer_is_icc_lt_14 (false), producer_is_codewarrior (false), - processing_has_namespace_info (false) + processing_has_namespace_info (false), + ancestor (nullptr) { } ...
(In reply to Tom de Vries from comment #6) > Tentative patch, prevents introducing cycles in ancestor chain: Which fixes the hang. But not the "./gdb -nx -readnow 447.dealII" crash. This fixes the crash: ... diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index e1c528f44d..64f2ba0ee0 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -21632,15 +21632,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2 _cu *cu, break; case DW_TAG_formal_parameter: { - /* If we are inside a function, mark this as an argument. If - not, we might be looking at an argument to an inlined function - when we do not have enough information to show inlined frames; - pretend it's a local variable in that case so that the user can - still see it. */ - struct context_stack *curr - = cu->get_builder ()->get_current_context_stack (); - if (curr != nullptr && curr->name != nullptr) - SYMBOL_IS_ARGUMENT (sym) = 1; + SYMBOL_IS_ARGUMENT (sym) = 1; attr = dwarf2_attr (die, DW_AT_location, cu); if (attr != nullptr) { ...
Is this the to-be-committed fix, or a workaround? I'm not familiar with DWARF internals, and whether this handling of inlined function arguments is necessary?
I ran into this debugging a core dump from a GCC-9.3-compiled application linked to a Clang-10.0.1-compiled shared library with gdb 9.1. The thread I was attempting to backtrace was in the Clang-compiled shared library. Applying the patches from comment 6 and comment 7 appeared to resolve the problem and I was able to see what looked like a correct backtrace.
(In reply to Tom de Vries from comment #6) > Tentative patch, prevents introducing cycles in ancestor chain: > ... > diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c > index 37409c5c3f..72e5446b8b 100644 > --- a/gdb/dwarf2/read.c > +++ b/gdb/dwarf2/read.c > @@ -22947,7 +22947,19 @@ follow_die_offset (sect_offset sect_off, int > offset_in_dwz, > temp_die.sect_off = sect_off; > > if (target_cu != cu) > - target_cu->ancestor = cu; > + { > + bool cycle_p = false; > + for (struct dwarf2_cu *tmp = cu->ancestor; tmp; tmp = tmp->ancestor) of course that loop looks quite expensive - what prevents target_cu from having multiple ancestors? The above just overwrites the old. For example with GCC LTO a LTRANS CU can refer to multiple compile CUs via abstract origins. And indeed I don't think DWARF forbids cycles here (but at least I think GCC shouldn't create those). Will the CU with m_builder ever have an ancestor? Thus, how about recording the ultimate ancestor only (which then should have the builder): if (target_cu != cu) { gcc_assert (!target_cu->m_builder); target_cu->ancestor = cu->ancestor; gcc_assert (target_cu->ancestor->m_builder); } and removing the recursion in get_builder? > + { > + if (tmp != target_cu) > + continue; > + > + cycle_p = true; > + break; > + } > + if (!cycle_p) > + target_cu->ancestor = cu; > + } > > return (struct die_info *) htab_find_with_hash (target_cu->die_hash, > &temp_die, > @@ -24256,7 +24268,8 @@ dwarf2_cu::dwarf2_cu (dwarf2_per_cu_data *per_cu, > producer_is_icc (false), > producer_is_icc_lt_14 (false), > producer_is_codewarrior (false), > - processing_has_namespace_info (false) > + processing_has_namespace_info (false), > + ancestor (nullptr) > { > } > > ...
(In reply to Richard Biener from comment #10) > (In reply to Tom de Vries from comment #6) > > Tentative patch, prevents introducing cycles in ancestor chain: > > ... > > diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c > > index 37409c5c3f..72e5446b8b 100644 > > --- a/gdb/dwarf2/read.c > > +++ b/gdb/dwarf2/read.c > > @@ -22947,7 +22947,19 @@ follow_die_offset (sect_offset sect_off, int > > offset_in_dwz, > > temp_die.sect_off = sect_off; > > > > if (target_cu != cu) > > - target_cu->ancestor = cu; > > + { > > + bool cycle_p = false; > > + for (struct dwarf2_cu *tmp = cu->ancestor; tmp; tmp = tmp->ancestor) > > of course that loop looks quite expensive - what prevents target_cu > from having multiple ancestors? The above just overwrites the old. > For example with GCC LTO a LTRANS CU can refer to multiple compile CUs > via abstract origins. And indeed I don't think DWARF forbids cycles here > (but at least I think GCC shouldn't create those). > > Will the CU with m_builder ever have an ancestor? Thus, how about recording > the ultimate ancestor only (which then should have the builder): > > if (target_cu != cu) > { > gcc_assert (!target_cu->m_builder); > target_cu->ancestor = cu->ancestor; > gcc_assert (target_cu->ancestor->m_builder); > } > > and removing the recursion in get_builder? And since all this is only relevant in the "full symbols are being read" case not set ->ancestor at all when cu->ancestor->m_builder is NULL. > > + { > > + if (tmp != target_cu) > > + continue; > > + > > + cycle_p = true; > > + break; > > + } > > + if (!cycle_p) > > + target_cu->ancestor = cu; > > + } > > > > return (struct die_info *) htab_find_with_hash (target_cu->die_hash, > > &temp_die, > > @@ -24256,7 +24268,8 @@ dwarf2_cu::dwarf2_cu (dwarf2_per_cu_data *per_cu, > > producer_is_icc (false), > > producer_is_icc_lt_14 (false), > > producer_is_codewarrior (false), > > - processing_has_namespace_info (false) > > + processing_has_namespace_info (false), > > + ancestor (nullptr) > > { > > } > > > > ...
Hmm, this survives a build & regression test on Leap 15.2: ... $ git diff diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 5796cf1730b..c889c1c15af 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -695,9 +695,11 @@ struct dwarf2_cu if (m_builder != nullptr) return m_builder.get (); +#if 0 /* Otherwise, search ancestors for a valid builder. */ if (ancestor != nullptr) return ancestor->get_builder (); +#endif return nullptr; } @@ -22045,15 +22047,7 @@ new_symbol (struct die_info *die, struct type *type, struct d warf2_cu *cu, break; case DW_TAG_formal_parameter: { - /* If we are inside a function, mark this as an argument. If - not, we might be looking at an argument to an inlined function - when we do not have enough information to show inlined frames; - pretend it's a local variable in that case so that the user can - still see it. */ - struct context_stack *curr - = cu->get_builder ()->get_current_context_stack (); - if (curr != nullptr && curr->name != nullptr) - SYMBOL_IS_ARGUMENT (sym) = 1; + SYMBOL_IS_ARGUMENT (sym) = 1; attr = dwarf2_attr (die, DW_AT_location, cu); if (attr != nullptr) { ...
(In reply to Tom de Vries from comment #12) > Hmm, this survives a build & regression test on Leap 15.2: Same on Tumbleweed.
So what I meant is record the builder by means of recording its CU rather than trying to be too clever walking the "ancestor chain" (which we don't do properly anyway).
(In reply to Tom de Vries from comment #13) > (In reply to Tom de Vries from comment #12) > > Hmm, this survives a build & regression test on Leap 15.2: > > Same on Tumbleweed. Patch submitted: https://sourceware.org/pipermail/gdb-patches/2021-May/178547.html
The master branch has been updated by Tom de Vries <vries@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=4cf88725da1cb503be04d3237354105ec170bc86 commit 4cf88725da1cb503be04d3237354105ec170bc86 Author: Tom de Vries <tdevries@suse.de> Date: Fri May 7 12:13:05 2021 +0200 [gdb/symtab] Fix infinite recursion in dwarf2_cu::get_builder() With the test-case attached in PR26327, gdb aborts: ... $ gdb -q -batch 447.dealII -ex "b main" Aborted (core dumped) ... when running out of stack due to infinite recursion: ... #8 0x00000000006aaba6 in dwarf2_cu::get_builder (this=0x35e4b40) at src/gdb/dwarf2/read.c:700 #9 0x00000000006aaba6 in dwarf2_cu::get_builder (this=0x22ee2c0) at src/gdb/dwarf2/read.c:700 #10 0x00000000006aaba6 in dwarf2_cu::get_builder (this=0x35e4b40) at src/gdb/dwarf2/read.c:700 #11 0x00000000006aaba6 in dwarf2_cu::get_builder (this=0x22ee2c0) at src/gdb/dwarf2/read.c:700 ... We're recursing in this code in dwarf2_cu::get_builder(): ... /* Otherwise, search ancestors for a valid builder. */ if (ancestor != nullptr) return ancestor->get_builder (); ... due to the fact that the ancestor chain is a cycle. Higher up in the call stack, we find some code that is responsible for triggering this, in new_symbol: ... case DW_TAG_formal_parameter: { /* If we are inside a function, mark this as an argument. If not, we might be looking at an argument to an inlined function when we do not have enough information to show inlined frames; pretend it's a local variable in that case so that the user can still see it. */ struct context_stack *curr = cu->get_builder ()->get_current_context_stack (); if (curr != nullptr && curr->name != nullptr) SYMBOL_IS_ARGUMENT (sym) = 1; ... This is code that was added to support pre-4.1 gcc, to be able to show arguments of inlined functions as locals, in the absense of sufficiently correct debug information. Removing this code (that is, doing SYMBOL_IS_ARGUMENT (sym) = 1 unconditially), fixes the crash. The ancestor variable also seems to have been added specifically to deal with fallout from this code, so remove that as well. Tested on x86_64-linux: - openSUSE Leap 15.2 with gcc 7.5.0, and - openSUSE Tumbleweed with gcc 10.3.0. gdb/ChangeLog: 2021-05-07 Tom de Vries <tdevries@suse.de> PR symtab/26327 * dwarf2/read.c (struct dwarf2_cu): Remove ancestor. (dwarf2_cu::get_builder): Remove ancestor-related code. (new_symbol): Remove code supporting pre-4.1 gcc that show arguments of inlined functions as locals. (follow_die_offset, follow_die_sig_1): Remove setting of ancestor. gdb/doc/ChangeLog: 2021-05-07 Tom de Vries <tdevries@suse.de> PR symtab/26327 * gdb.texinfo (Inline Functions): Update.
Patch committed, marking resolved-fixed.
Patch reverted due to regression, reopening.
(In reply to Tom de Vries from comment #12) > +#if 0 > /* Otherwise, search ancestors for a valid builder. */ > if (ancestor != nullptr) > return ancestor->get_builder (); > +#endif The problem is not that we search ancestors, the problem is that we allow ancestors to form a loop. See detailed investigation at <URL: https://bugzilla.opensuse.org/show_bug.cgi?id=1185800 >. Your fix looks more like a band-aid to me. As a side note, I have captured a situation when the ancestor is a random non-pointer because cu constructor does not bother to clear it. Not nice.
https://sourceware.org/pipermail/gdb-patches/2021-June/179750.html
The master branch has been updated by Tom de Vries <vries@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=8457e5ecc45295bc9550c4f705a276d5ca90d908 commit 8457e5ecc45295bc9550c4f705a276d5ca90d908 Author: Tom de Vries <tdevries@suse.de> Date: Wed Jun 16 12:44:30 2021 +0200 [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.
Patch committed, marking resolved-fixed, again.