From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3172 invoked by alias); 30 Sep 2008 15:28:39 -0000 Received: (qmail 3161 invoked by uid 22791); 30 Sep 2008 15:28:37 -0000 X-Spam-Check-By: sourceware.org Received: from rock.gnat.com (HELO rock.gnat.com) (205.232.38.15) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 30 Sep 2008 15:28:02 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id 5C6682A968C for ; Tue, 30 Sep 2008 11:28:00 -0400 (EDT) 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 5p7lQVR+eziy for ; Tue, 30 Sep 2008 11:28:00 -0400 (EDT) Received: from joel.gnat.com (localhost.localdomain [127.0.0.1]) by rock.gnat.com (Postfix) with ESMTP id E19412A9694 for ; Tue, 30 Sep 2008 11:27:59 -0400 (EDT) Received: by joel.gnat.com (Postfix, from userid 1000) id 685ACE7ACD; Tue, 30 Sep 2008 08:27:57 -0700 (PDT) Date: Tue, 30 Sep 2008 15:28:00 -0000 From: Joel Brobecker To: gdb-patches@sourceware.org Subject: [RFA/DWARF2] Handle nested subprograms in CU pc bound calculation Message-ID: <20080930152757.GC23135@adacore.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="DocE+STaALJfprDB" Content-Disposition: inline User-Agent: Mutt/1.4.2.2i 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: 2008-09/txt/msg00570.txt.bz2 --DocE+STaALJfprDB Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 2575 Hello, We just recently encountered a situation where GDB was emitting the following warning: | (gdb) b f1 | warning: (Internal error: pc 0x80495ce in read in psymtab, but not in symtab.) | warning: (Internal error: pc 0x80495d1 in read in psymtab, but not in symtab.) | warning: (Internal error: pc 0x80495d1 in read in psymtab, but not in symtab.) | warning: (Internal error: pc 0x80495d1 in read in psymtab, but not in symtab.) | Breakpoint 1 at 0x80495d1: file gen1.adb, line 3. This happened after compiling the CU with -ffunction-sections, and is related to the fact that f1 is a nested subprogram. The code looks like this: procedure Foo is procedure F1 is new Gen; begin ... Here is what happens: 1. When compiling with -ffunction-sections, the compiler is not providing the CU PC bounds (DW_AT_low_pc and DW_AT_high_pc). I would imagine that this is because functions might be removed later during the link, and thus bounds might be affected. 2. As a result, GDB ends up having to compute the PC bounds itself by inspecting the children of the CU. This is done inside get_scope_pc_bounds. However, this function only handles non-nested functions. As a result, after having determined the bounds of the main procedure Foo, it goes directly to the next sibling of that function, past the two nested subprograms. The net effect is that the low/high PC range is too short, missing the range for our nested subprogram. 3. Later, when the user inserts a breakpoint on the nested subprogram, GDB finds symbol f1, converts the associated psymtab into a symtab, and then tries to find the first "real" line of code, and so ends up searching the symtab associated to a PC inside our subprogram. The search among known symtabs fails because of the incorrect PC bounds. So the next step is searching through the psymtabs, where we find the correct one, and realize that it has already been read in, meaning that the previous search should have found it -> warning. The attached patch fixes this problem by handling nested subprograms. Similarly to what was done earlier, I am limiting this to languages that allow nested subprogram, which means only Ada for now. Other languages should be unaffected. 2008-09-30 Joel Brobecker * dwarf2read.c (dwarf2_get_subprogram_pc_bounds): New function. (get_scope_pc_bounds): Use it. Tested on x86-linux. No regression. Any objection? Thanks, -- Joel --DocE+STaALJfprDB Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="dwarf2read.c.diff" Content-length: 2401 Index: dwarf2read.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2read.c,v retrieving revision 1.284 diff -u -p -r1.284 dwarf2read.c --- dwarf2read.c 23 Sep 2008 17:36:51 -0000 1.284 +++ dwarf2read.c 30 Sep 2008 14:54:29 -0000 @@ -3324,6 +3324,43 @@ dwarf2_get_pc_bounds (struct die_info *d return ret; } +/* Assuming that DIE represents a subprogram DIE or a lexical block, get + its low and high PC addresses. Do nothing if these addresses could not + be determined. Otherwise, set LOWPC to the low address if it is smaller, + and HIGHPC to the high address if greater than HIGHPC. */ + +static void +dwarf2_get_subprogram_pc_bounds (struct die_info *die, + CORE_ADDR *lowpc, CORE_ADDR *highpc, + struct dwarf2_cu *cu) +{ + CORE_ADDR low, high; + struct die_info *child = die->child; + + if (dwarf2_get_pc_bounds (die, &low, &high, cu)) + { + *lowpc = min (*lowpc, low); + *highpc = max (*highpc, high); + } + + /* If the language does not allow nested subprograms (either inside + subprograms or lexical blocks), we're done. */ + if (cu->language != language_ada) + return; + + /* Check all the children of the given DIE. If it contains nested + subprograms, then check their pc bounds. Likewise, we need to + check lexical blocks as well, as they may also contain subprogram + definitions. */ + while (child && child->tag) + { + if (child->tag == DW_TAG_subprogram + || child->tag == DW_TAG_lexical_block) + dwarf2_get_subprogram_pc_bounds (child, lowpc, highpc, cu); + child = sibling_die (child); + } +} + /* Get the low and high pc's represented by the scope DIE, and store them in *LOWPC and *HIGHPC. If the correct values can't be determined, set *LOWPC to -1 and *HIGHPC to 0. */ @@ -3350,11 +3387,7 @@ get_scope_pc_bounds (struct die_info *di { switch (child->tag) { case DW_TAG_subprogram: - if (dwarf2_get_pc_bounds (child, ¤t_low, ¤t_high, cu)) - { - best_low = min (best_low, current_low); - best_high = max (best_high, current_high); - } + dwarf2_get_subprogram_pc_bounds (child, &best_low, &best_high, cu); break; case DW_TAG_namespace: /* FIXME: carlton/2004-01-16: Should we do this for --DocE+STaALJfprDB--