Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Andrew Cagney <ac131313@redhat.com>
To: Michal Ludvig <mludvig@suse.cz>
Cc: GDB Patches <gdb-patches@sources.redhat.com>
Subject: Re: [patch/rfc] Add a sentinel frame
Date: Wed, 19 Feb 2003 13:27:00 -0000	[thread overview]
Message-ID: <3E538770.6070209@redhat.com> (raw)
In-Reply-To: <3E52173B.1030800@suse.cz>

(I hate jet lag, I'm never up at 7am, well ok ...)

> I got back to the mainline/"sentinel" problem and have found that it happens when a program's function is called from a gdb prompt.
> 
> To reproduce create a very simple program:
> int func(int arg) { return 2*arg; }
> int main(int argc) { return func(argc); }
> 
> Then run mainline GDB on x86-64:
> (gdb) break main
> (gdb) run
> (gdb) print func(1)
> ../../gdb-head/gdb/sentinel-frame.c:102: internal-error: Function sentinal_frame_pop called
> A problem internal to GDB has been detected.  Further
> debugging may prove unreliable.
> Quit this debugging session? (y or n)
> 
> Attached is a backtrace of this failing GDB.
> Any ideas?

Yes!


> #6  0x00000000005446d1 in sentinel_frame_pop (frame=0x82c100, cache=0x82c130, 
>     regcache=0x850610) at ../../gdb-head/gdb/sentinel-frame.c:102

At this point GDB is hosed.

As I mentioned before, popping the sentinal frame is meaningless so the 
question is, where did that frame come from.

A wild guess is that it is trying to pop the dummy frame having finished 
the inferior function call.  A confirmation is:

(gdb) break func
(gdb) print func(1)

It should manage to stop in func, the stack being something like 
(assuming bt doesn't also internal error :-):

(gdb) bt
.... func ...
.... <dummy-frame> ...
.... main ...

Returning from func(), causing the dummy-frame to be discarded should 
then trigger things:

(gdb) finish
... barf ...

Can you confirm that the PC for this frame is falling in the stack dummy?


> #7  0x00000000004e6692 in frame_pop (frame=0x82c100)
>     at ../../gdb-head/gdb/frame.c:164


> #8  0x000000000048a3c4 in normal_stop () at ../../gdb-head/gdb/infrun.c:3113

The code reads:

   if (stop_stack_dummy)
     {
       /* Pop the empty frame that contains the stack dummy.  POP_FRAME
          ends with a setting of the current frame, so we can use that
          next. */
       frame_pop (get_current_frame ());
       /* Set stop_pc to what it was before we called the function.
          Can't rely on restore_inferior_status because that only gets
          called if we don't stop in the called function.  */
       stop_pc = read_pc ();
       select_frame (get_current_frame ());
     }

Hmm, not so good.  I was expecting something involving sentinal frames. 
  Anyway ...

get_current_frame() does the sequence:

   if (current_frame == NULL)
     {

This is where the sentinel frame comes from.

       struct frame_info *sentinel_frame =
         create_sentinel_frame (current_regcache);

This is where it tries to unwind it back to the current frame (a dummy 
frame in this case). Note that unwind_to_current_frame() calls 
get_prev_frame().

       if (catch_exceptions (uiout, unwind_to_current_frame, sentinel_frame,
                             NULL, RETURN_MASK_ERROR) != 0)
         {

And if it fails, it does this:

           /* Oops! Fake a current frame?  Is this useful?  It has a PC
              of zero, for instance.  */
           current_frame = sentinel_frame;
         }
     }

So lets assume that get_prev_frame() is failing.  It can do it two ways:

- noisily via an error() call such as when a memory read fails
(I don't think it is this 'cos we'd see that error).
- silently because get_prev_frame() thinks that chaining is invalid
(more likely)

So I think it is one of these tests going awall:

   if (next_frame->level >= 0
       && !backtrace_below_main
       && inside_main_func (get_frame_pc (next_frame)))
     /* Don't unwind past main(), bug always unwind the sentinel frame.
        Note, this is done _before_ the frame has been marked as
        previously unwound.  That way if the user later decides to
        allow unwinds past main(), that just happens.  */
     return NULL;

   /* If we're inside the entry file, it isn't valid.  */
   /* NOTE: drow/2002-12-25: should there be a way to disable this
      check?  It assumes a single small entry file, and the way some
      debug readers (e.g.  dbxread) figure out which object is the
      entry file is somewhat hokey.  */
   /* NOTE: cagney/2003-01-10: If there is a way of disabling this test
      then it should probably be moved to before the ->prev_p test,
      above.  */
   if (inside_entry_file (get_frame_pc (next_frame)))
       return NULL;

The second looks worrying (the dummy frame breakpoint lives in the entry 
file ...).  Perhaphs something like:

if (dummy_frame_p (get_frame_pc (next_frame) != NULL
     && inside_entry_file (get_frame_pc (next_frame))
   return NULL;

Andrew



  reply	other threads:[~2003-02-19 13:27 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-01-23 20:54 Andrew Cagney
2003-01-27 21:42 ` Andrew Cagney
2003-02-10 23:36 ` Michal Ludvig
2003-02-11 16:48   ` Andrew Cagney
2003-02-18 11:21     ` Michal Ludvig
2003-02-19 13:27       ` Andrew Cagney [this message]
2003-02-19 14:04         ` Daniel Jacobowitz
2003-02-19 16:46           ` Andrew Cagney
2003-02-19 16:56             ` Daniel Jacobowitz
2003-02-19 17:11               ` Andrew Cagney
2003-02-19 17:17                 ` Daniel Jacobowitz
2003-02-19 17:46                   ` Andrew Cagney
2003-02-19 17:56                     ` Daniel Jacobowitz
2003-02-19 18:36                       ` Andrew Cagney
2003-02-19 18:52                         ` Daniel Jacobowitz
2003-02-19 20:22                           ` Andrew Cagney
2003-02-19 20:39                             ` Daniel Jacobowitz
2003-02-19 21:21                               ` Andrew Cagney
2003-02-20 19:32                                 ` Daniel Jacobowitz
2003-02-19 21:45                               ` Andrew Cagney
2003-02-20 19:32                                 ` Daniel Jacobowitz
2003-02-25 16:24         ` Michal Ludvig
2003-02-25 19:43           ` Andrew Cagney
2003-02-25 21:00             ` Michal Ludvig
2003-02-25 21:12               ` Andrew Cagney
2003-02-26  8:04                 ` Michal Ludvig
2003-02-27 18:27                   ` Andrew Cagney
2003-02-28 13:02                     ` Michal Ludvig
2003-02-28 15:48                       ` Andrew Cagney
2003-03-05 17:38                         ` Michal Ludvig
2003-03-05 18:25                           ` Andrew Cagney
2003-03-06 16:00                             ` Michal Ludvig
2003-03-06 20:13                               ` Andrew Cagney
2003-03-06 22:42                                 ` [RFA] Dummy frames on x86-64 Michal Ludvig
2003-03-07 14:50                                   ` Andrew Cagney
2003-02-25 22:41               ` [patch/rfc] Add a sentinel frame Andrew Cagney
2003-02-25 21:21 Michael Elizabeth Chastain

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=3E538770.6070209@redhat.com \
    --to=ac131313@redhat.com \
    --cc=gdb-patches@sources.redhat.com \
    --cc=mludvig@suse.cz \
    /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