From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 12677 invoked by alias); 28 Dec 2010 04:43:40 -0000 Received: (qmail 12667 invoked by uid 22791); 28 Dec 2010 04:43:39 -0000 X-SWARE-Spam-Status: No, hits=-2.0 required=5.0 tests=AWL,BAYES_00,TW_BJ,TW_MX,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from rock.gnat.com (HELO rock.gnat.com) (205.232.38.15) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 28 Dec 2010 04:43:34 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id 08B7F2BABC4; Mon, 27 Dec 2010 23:43:33 -0500 (EST) Received: from rock.gnat.com ([127.0.0.1]) by localhost (rock.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id YnT4m85ht2g8; Mon, 27 Dec 2010 23:43:32 -0500 (EST) Received: from joel.gnat.com (localhost.localdomain [127.0.0.1]) by rock.gnat.com (Postfix) with ESMTP id 7D7EF2BAB2A; Mon, 27 Dec 2010 23:43:32 -0500 (EST) Received: by joel.gnat.com (Postfix, from userid 1000) id E69191457BB; Tue, 28 Dec 2010 05:43:23 +0100 (CET) From: Joel Brobecker To: gdb-patches@sourceware.org Cc: Joel Brobecker Subject: [PATCH 4/8] libunwind-frame.c: handle functions with no minimal symbol/debug info. Date: Tue, 28 Dec 2010 04:43:00 -0000 Message-Id: <1293511386-7384-5-git-send-email-brobecker@adacore.com> In-Reply-To: <1293511386-7384-1-git-send-email-brobecker@adacore.com> References: <1293511386-7384-1-git-send-email-brobecker@adacore.com> Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2010-12/txt/msg00482.txt.bz2 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. --- gdb/libunwind-frame.c | 20 +++++++++++++------- 1 files changed, 13 insertions(+), 7 deletions(-) diff --git a/gdb/libunwind-frame.c b/gdb/libunwind-frame.c index dc28064..8b712b9 100644 --- a/gdb/libunwind-frame.c +++ b/gdb/libunwind-frame.c @@ -157,14 +157,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. -- 1.7.1