From: Tom Tromey Date: Fri, 8 May 2020 20:26:11 +0000 (-0600) Subject: Don't re-process a DIE in read_lexical_block_scope X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4f7bc5edbd3ffaad52022849d6263d982c23ff3c;p=binutils-gdb.git Don't re-process a DIE in read_lexical_block_scope A customer reported a crash in the DWARF reader. Investigation showed that the crash occurred in an unusual scenario: a function was lexically scoped within some other function -- but the inner function inlined the outer function and referred to its DIE via DW_AT_abstract_origin. With the executable in question, inherit_abstract_dies could eventually call read_lexical_block_scope, which in turn could recurse into process_die, to process a DIE that was already being read, triggering an assert. This came up once before; see: https://www.sourceware.org/ml/gdb-patches/2014-02/msg00652.html However, in this case, I don't have an easy way to reproduce. So, there is no test case. I did experiment with the failing executable. This patch fixes the bug and doesn't seem to cause other issues. For example, I can still set breakpoints on the relevant functions. gdb/ChangeLog 2020-05-08 Tom Tromey * dwarf2/read.c (read_lexical_block_scope): Don't process a DIE already being processed. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 59125fd6ded..07bc9505020 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,8 @@ +2020-05-08 Tom Tromey + + * dwarf2/read.c (read_lexical_block_scope): Don't process a DIE + already being processed. + 2020-05-08 Tom Tromey * printcmd.c (struct display) : Remove. diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 60b56b8ea81..439b889144b 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -13102,7 +13102,16 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu) for (child_die = die->child; child_die != NULL && child_die->tag; child_die = child_die->sibling) - process_die (child_die, cu); + { + /* We might already be processing this DIE. This can happen + in an unusual circumstance -- where a subroutine A + appears lexically in another subroutine B, but A actually + inlines B. The recursion is broken here, rather than in + inherit_abstract_dies, because it seems better to simply + drop concrete children here. */ + if (!child_die->in_process) + process_die (child_die, cu); + } return; case PC_BOUNDS_INVALID: return;