This is the mail archive of the gdb@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Infinite backtrace on arm


On Sun, Oct 26, 2003 at 12:28:13AM -0400, Jon Ringle wrote:
> Hi,
> 
> I backported arm kgdb to run in an embedded arm target running 2.2.16 kernel. 
> I can debug the the target for the most part with gdb-5.3 over a serial 
> connection. However, sometimes when I ask for a backtrace, the bt gets stuck 
> recursing at the bottom of the bt. Here is an example:
> 
> Breakpoint 9, dimp_proc_bring_dsp_down (p_dsp=0x1022dc00, reason=7) at 
> common/micro/dim/dimutl.c:247
> (gdb) bt
> #0  dimp_proc_bring_dsp_down (p_dsp=0x1022dc00, reason=7) at 
> common/micro/dim/dimutl.c:247
> #1  0x1005dff4 in dimp_bring_dsp_down (p_dsp=0x1022dc00, 
> reason=DIM_DSP_ERR_OK) at common/micro/dim/dimutl.c:74
> #2  0x1005ae20 in dimp_check_dsp_msgs () at common/micro/dim/dimdsp.c:1831
> #3  0x100557a8 in dim_process_poll () at common/micro/dim/dimcomm.c:107
> #4  0x10067d78 in dsp_timer1intHandler (irq=0, dev_id=0x0, regs=0x1018a820) at 
> dspdriver.c:169
> #5  0x1000c004 in do_IRQ (irq=1, regs=0x10ffdfa8) at irq.c:247
> #6  0x1000b200 in linux_VECTOR_IRQ ()
> #7  0x1000b200 in linux_VECTOR_IRQ ()
> #8  0x1000b200 in linux_VECTOR_IRQ ()
> [repeated ad infinitum...]
> 
> I found the following code check at blockframe.c:496 that is supposed to trap 
> this situation:
> 
>   /* If ->frame and ->pc are unchanged, we are in the process of getting
>      ourselves into an infinite backtrace.  Some architectures check this
>      in FRAME_CHAIN or thereabouts, but it seems like there is no reason
>      this can't be an architecture-independent check.  */
>   if (next_frame != NULL)
>     {
>       if (prev->frame == next_frame->frame
>         && prev->pc == next_frame->pc)
>         {
>           next_frame->prev = NULL;
>           obstack_free (&frame_cache_obstack, prev);
>           return NULL;
>         }
>     }
> 
> However, I found by debugging gdb that frame was changing by framesize. I 
> think (but not confirmed) that this is happening because this is not caught 
> by arm_frame_chain() and it is returning with:
>     return fi->frame + fi->extra_info->framesize;
> 
> I fixed my problem with the following:
> --- gdb/blockframe.c~   2003-10-26 00:17:13.000000000 -0400
> +++ gdb/blockframe.c    2003-10-26 00:17:53.000000000 -0400
> @@ -499,8 +499,7 @@
>       this can't be an architecture-independent check.  */
>    if (next_frame != NULL)
>      {
> -      if (prev->frame == next_frame->frame
> -         && prev->pc == next_frame->pc)
> +      if (prev->pc == next_frame->pc)
>         {
>           next_frame->prev = NULL;
>           obstack_free (&frame_cache_obstack, prev);
> 
> I don't think this is the right thing to do, and that a fix is really needed 
> in arm_frame_chain(). But I'm not sure what that might be. Does anyone have a 
> suggestion?

Well, for starters, I can tell you what the long-term "correct" thing
to do is:

  - Use a CVS version of GDB
  - Enable DWARF2-based unwinding for ARM; it's disabled in GDB because
    of some problems with Thumb unwind info.  I'll be working on this
    sometime soon.
  - Use a version of binutils which supports .cfi_* directives
    on ARM - I have patches for this but haven't posted them yet, I'll
    try again to do it this week.
  - Find a convention for unwind info that should tell GDB to terminate
    the backtrace.  I don't think there is one right now.
  - Annotate your copy of linux_VECTOR_IRQ, which is presumably an
    assembly stub, with information to make the backtrace stop.  Or to
    continue to its caller if it has one and isn't just called through
    an interrupt handler.

The problem is that there's not much GDB can do with hand-coded
assembly functions.

However, GDB ought to be able to detect and stop that loop without any
of this.  It seems to me that the problem is not two frames with the
same PC, but two frames with their PC "saved" in the same place - i.e.
GDB failing to figure out where the PC is saved.  This is made a little
tricky in current versions of GDB, because the PC is normally unwound
using frame_pc_unwind (which doesn't tell us where it was saved, since
the interface doesn't assume it's a single normal register), and the
core code doesn't have a concept of a "PC register" any more.

Andrew, any idea on how to do this?

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]