diff options
author | Tom Tromey <tromey@adacore.com> | 2020-05-08 14:26:11 -0600 |
---|---|---|
committer | Tom Tromey <tromey@adacore.com> | 2020-05-08 14:26:11 -0600 |
commit | 4f7bc5edbd3ffaad52022849d6263d982c23ff3c (patch) | |
tree | d1a4c5ee8cd682341f6488f2600ed6c652924737 /gdb/dwarf2/read.c | |
parent | 8be4b118a9343197291d23c666f6a8ad24bce76a (diff) | |
download | gdb-4f7bc5edbd3ffaad52022849d6263d982c23ff3c.zip gdb-4f7bc5edbd3ffaad52022849d6263d982c23ff3c.tar.gz gdb-4f7bc5edbd3ffaad52022849d6263d982c23ff3c.tar.bz2 |
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 <tromey@adacore.com>
* dwarf2/read.c (read_lexical_block_scope): Don't process a DIE
already being processed.
Diffstat (limited to 'gdb/dwarf2/read.c')
-rw-r--r-- | gdb/dwarf2/read.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 60b56b8..439b889 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; |