[libunwind-frame] handle functions with no minimal symbol/debug info.

This is something that I am seeing on ia64-hpux while trying to
backtrace from a thread that's doing a wait:

    (gdb) task 2
    [Switching to task 2]
    0x9fffffffef52f590 in __ksleep () from /[...]/libc.so.1
    (gdb) bt
    #0  0x9fffffffef52f590 in __ksleep () from /[...]/libc.so.1
    #1  0x9fffffffef73c870 in __sleep_1x1 () from /[...]/libpthread.so.1
    #2  0x9fffffffef738fe0 in __mxn_sleep () from /[...]/libpthread.so.1
    #3  0x9fffffffef675e90 in ?? () from /[...]/libpthread.so.1

The backtrace is incomplete and stops at frame #3, but there are in fact
a few more frames.

The reason why we stopped the backtrace is related to the fact that
we were not able to determine the start address of the function
corresponding to the frame PC.  This is visible at the user level
thanks to the "??" that GDB displayed for frame 3.

We have the following code in libunwind-frame.c:libunwind_frame_cache
which explicitly returns a NULL cache when we couldn't determine the
frame's function address, immediately triggering an end-of-stack
frame_id, thus terminating the backtrace:

   /* We can assume we are unwinding a normal frame.  Even if this is
      for a signal trampoline, ia64 signal "trampolines" use a normal
      subroutine call to start the signal handler.  */
   cache->func_addr = get_frame_func (this_frame);
   if (cache->func_addr == 0
       && get_next_frame (this_frame)
       && get_frame_type (get_next_frame (this_frame)) == NORMAL_FRAME)
     return NULL;

As explained in the comment, I think we can still go on, and use
the unwind record to do the debugging.  This change imlements this
change, and allows us to get the full backtrace.

gdb/ChangeLog:

        * libunwind-frame.c (libunwind_frame_cache): Do not return NULL
        if we could not determine the frame's function address.  Instead,
        use the frame's PC, and then continue.
This commit is contained in:
Joel Brobecker 2011-01-13 16:23:22 +00:00
parent 3e5e6e2ab5
commit 1b89e62fe3
2 changed files with 19 additions and 7 deletions

View File

@ -1,3 +1,9 @@
2011-01-13 Joel Brobecker <brobecker@adacore.com>
* libunwind-frame.c (libunwind_frame_cache): Do not return NULL
if we could not determine the frame's function address. Instead,
use the frame's PC, and then continue.
2011-01-13 Joel Brobecker <brobecker@adacore.com>
* libunwind-frame.c (__LITTLE_ENDIAN, __BIG_ENDIAN): Define if

View File

@ -162,14 +162,20 @@ libunwind_frame_cache (struct frame_info *this_frame, void **this_cache)
/* Allocate a new cache. */
cache = FRAME_OBSTACK_ZALLOC (struct libunwind_frame_cache);
/* We can assume we are unwinding a normal frame. Even if this is
for a signal trampoline, ia64 signal "trampolines" use a normal
subroutine call to start the signal handler. */
cache->func_addr = get_frame_func (this_frame);
if (cache->func_addr == 0
&& get_next_frame (this_frame)
&& get_frame_type (get_next_frame (this_frame)) == NORMAL_FRAME)
return NULL;
if (cache->func_addr == 0)
/* This can happen when the frame corresponds to a function for which
there is no debugging information nor any entry in the symbol table.
This is probably a static function for which an entry in the symbol
table was not created when the objfile got linked (observed in
libpthread.so on ia64-hpux).
The best we can do, in that case, is use the frame PC as the function
address. We don't need to give up since we still have the unwind
record to help us perform the unwinding. There is also another
compelling to continue, because abandonning now means stopping
the backtrace, which can never be helpful for the user. */
cache->func_addr = get_frame_pc (this_frame);
/* Get a libunwind cursor to the previous frame.