[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.
This commit is contained in:
Tom de Vries
2021-05-07 12:13:05 +02:00
parent 17c6c3b991
commit 4cf88725da
4 changed files with 18 additions and 25 deletions

View File

@@ -1,3 +1,12 @@
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.
2021-05-07 Andrew Burgess <andrew.burgess@embecosm.com>
* guile/guile-internal.h (gdbscm_safe_source_script): Change

View File

@@ -1,3 +1,8 @@
2021-05-07 Tom de Vries <tdevries@suse.de>
PR symtab/26327
* gdb.texinfo (Inline Functions): Update.
2021-05-06 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* gdb.texinfo (GDB/MI Breakpoint Commands): Mention the

View File

@@ -13842,8 +13842,8 @@ when using @sc{dwarf 2}. Versions of @value{NGCC} before 4.1
do not emit two required attributes (@samp{DW_AT_call_file} and
@samp{DW_AT_call_line}); @value{GDBN} does not display inlined
function calls with earlier versions of @value{NGCC}. It instead
displays the arguments and local variables of inlined functions as
local variables in the caller.
displays local variables of inlined functions as local variables in
the caller.
The body of an inlined function is directly included at its call site;
unlike a non-inlined function, there are no instructions devoted to

View File

@@ -684,10 +684,6 @@ public:
struct partial_die_info *find_partial_die (sect_offset sect_off);
/* If this CU was inherited by another CU (via specification,
abstract_origin, etc), this is the ancestor CU. */
dwarf2_cu *ancestor;
/* Get the buildsym_compunit for this CU. */
buildsym_compunit *get_builder ()
{
@@ -695,10 +691,6 @@ public:
if (m_builder != nullptr)
return m_builder.get ();
/* Otherwise, search ancestors for a valid builder. */
if (ancestor != nullptr)
return ancestor->get_builder ();
return nullptr;
}
};
@@ -22045,15 +22037,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)
{
@@ -23389,9 +23373,6 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz,
*ref_cu = target_cu;
temp_die.sect_off = sect_off;
if (target_cu != cu)
target_cu->ancestor = cu;
return (struct die_info *) htab_find_with_hash (target_cu->die_hash,
&temp_die,
to_underlying (sect_off));
@@ -23741,7 +23722,7 @@ follow_die_sig_1 (struct die_info *src_die, struct signatured_type *sig_type,
struct dwarf2_cu **ref_cu)
{
struct die_info temp_die;
struct dwarf2_cu *sig_cu, *cu = *ref_cu;
struct dwarf2_cu *sig_cu;
struct die_info *die;
dwarf2_per_objfile *per_objfile = (*ref_cu)->per_objfile;
@@ -23777,8 +23758,6 @@ follow_die_sig_1 (struct die_info *src_die, struct signatured_type *sig_type,
}
*ref_cu = sig_cu;
if (sig_cu != cu)
sig_cu->ancestor = cu;
return die;
}