Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Pedro Alves <palves@redhat.com>
To: Tom Tromey <tromey@redhat.com>
Cc: gdb-patches@sourceware.org
Subject: Re: [PATCH 1/2] avoid infinite loop with bad debuginfo
Date: Tue, 19 Nov 2013 16:33:00 -0000	[thread overview]
Message-ID: <528B8FF6.7000406@redhat.com> (raw)
In-Reply-To: <87vbzomm78.fsf@fleche.redhat.com>

On 11/19/2013 03:43 PM, Tom Tromey wrote:

> That said, even once your change is in, I think both of these patches
> should go in.  Patch #1 still prevents an infinite loop -- 

...

> I can probably find another test case

Yes, probably by manually creating a corrupted stack.

      while (VALUE_LVAL (new_val) == lval_register && value_lazy (new_val))
	{
	  frame = frame_find_by_id (VALUE_FRAME_ID (new_val));
...
	  new_val = get_frame_register_value (frame, regnum);
	}

get_frame_register_value can return a lazy register value pointing
to the next frame (in the dwarf unwinder, that's
DWARF2_FRAME_REG_SAME_VALUE).  That's perfectly normal.

But say we have a corrupted stack like this:

 #0 - frame_id_1
 #1 - frame_id_2
 #2 - frame_id_3
 #3 - frame_id_4
 #4 - frame_id_4  <<<< outermost (UNWIND_SAME_ID).

So, get_frame_register_value in frame #4, can return
a lazy value pointing to frame #3.  What's not normal is having two
frames with the same id.  So the next iteration, frame_find_by_id
tries to look for frame #3.  But, since it has the
same id as frame #4, frame #4 is returned, rinse, repeat.

I think this is an old latent problem.  We shouldn't ever have
two frames with the same id in the frame chain, lots of things
break otherwise.  But somehow, we managed to get this far
in this particular case.

If we can indeed trigger this with a real corruption test
case, I believe the reason is that the recent-ish addition
of the frame stash exposes the latent bug:

struct frame_info *
frame_find_by_id (struct frame_id id)
{
  struct frame_info *frame, *prev_frame;

  /* ZERO denotes the null frame, let the caller decide what to do
     about it.  Should it instead return get_current_frame()?  */
  if (!frame_id_p (id))
    return NULL;

  /* Try using the frame stash first.  Finding it there removes the need
     to perform the search by looping over all frames, which can be very
     CPU-intensive if the number of frames is very high (the loop is O(n)
     and get_prev_frame performs a series of checks that are relatively
     expensive).  This optimization is particularly useful when this function
     is called from another function (such as value_fetch_lazy, case
     VALUE_LVAL (val) == lval_register) which already loops over all frames,
     making the overall behavior O(n^2).  */
  frame = frame_stash_find (id);
  if (frame)
    return frame;

  for (frame = get_current_frame (); ; frame = prev_frame)
    {


Before we had a stash, frame_find_by_id(frame_id_4) would
always find #3 first.  But now, it's possible that
the stash returns #4 instead.

I still think that such a loop should be broken by never
having two frames with the same id in the frame chain in the
first place.  This potential infinite loop in value_fetch_lazy
is really an internal error, IMO.

-- 
Pedro Alves


  reply	other threads:[~2013-11-19 16:22 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-11-13 20:51 [PATCH 0/2] fix multi-threaded unwinding on AArch64 Tom Tromey
2013-11-13 20:51 ` [PATCH 2/2] handle an unspecified return address column Tom Tromey
2013-11-22 18:22   ` Tom Tromey
2013-11-26 13:55   ` Joel Brobecker
2013-11-26 14:30     ` Mark Kettenis
2013-11-26 14:37       ` Joel Brobecker
2013-11-26 14:41         ` Mark Kettenis
2013-11-26 14:42           ` Joel Brobecker
2013-11-26 14:50           ` Tom Tromey
2013-11-26 15:05           ` Tom Tromey
2013-11-26 15:16       ` Tom Tromey
2013-11-26 16:11         ` Joel Brobecker
2013-11-13 22:03 ` [PATCH 1/2] avoid infinite loop with bad debuginfo Tom Tromey
2013-11-14 17:34   ` Pedro Alves
2013-11-18 18:25     ` Tom Tromey
2013-11-19 15:10       ` Pedro Alves
2013-11-19 15:47         ` Tom Tromey
2013-11-19 16:33           ` Pedro Alves [this message]
2013-11-19 19:07             ` Tom Tromey
2013-11-19 20:24               ` Pedro Alves
2013-11-19 20:56                 ` Tom Tromey
2013-11-20 18:27                   ` [PATCH] Don't let two frames with the same id end up in the frame chain. (Re: [PATCH 1/2] avoid infinite loop with bad debuginfo) Pedro Alves
2013-11-21  0:33                     ` Tom Tromey
2013-11-21 16:40                       ` Pedro Alves
2013-11-21 19:25                         ` Tom Tromey
2013-11-22 14:13                           ` [COMMITTED] Make use of the frame stash to detect wider stack cycles. (was: Re: [PATCH] Don't let two frames with the same id end up in the frame chain. (Re: [PATCH 1/2] avoid infinite loop with bad debuginfo)) Pedro Alves
2013-11-22 14:29                         ` [PATCH] Don't let two frames with the same id end up in the frame chain. (Re: [PATCH 1/2] avoid infinite loop with bad debuginfo) Pedro Alves
2013-11-22 14:52       ` [PATCH 1/2] avoid infinite loop with bad debuginfo Pedro Alves
2013-11-22 17:16         ` Tom Tromey
2013-11-22 17:56           ` Pedro Alves
2013-11-19 15:52     ` Tom Tromey

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=528B8FF6.7000406@redhat.com \
    --to=palves@redhat.com \
    --cc=gdb-patches@sourceware.org \
    --cc=tromey@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox