From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 12437 invoked by alias); 15 Dec 2003 21:24:54 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 12428 invoked from network); 15 Dec 2003 21:24:53 -0000 Received: from unknown (HELO coconut.kealia.com) (209.3.10.89) by sources.redhat.com with SMTP; 15 Dec 2003 21:24:53 -0000 Received: from coconut.kealia.com (localhost.localdomain [127.0.0.1]) by coconut.kealia.com (8.12.8/8.12.8) with ESMTP id hBFLOq0t007596; Mon, 15 Dec 2003 13:24:52 -0800 Received: (from carlton@localhost) by coconut.kealia.com (8.12.8/8.12.8/Submit) id hBFLOp1g007594; Mon, 15 Dec 2003 13:24:51 -0800 X-Authentication-Warning: coconut.kealia.com: carlton set sender to carlton@kealia.com using -f To: gdb-patches@sources.redhat.com Subject: [dictionary] set bounds info correctly in symtabs From: David Carlton Date: Mon, 15 Dec 2003 21:24:00 -0000 Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-SW-Source: 2003-12/txt/msg00382.txt.bz2 For a while, local users have been complaining that GDB generates tons of "pc in read in psymtab, but not in symtab" messages. Which is annoying (and the gratuitous extra "in" doesn't help). :-) I finally got around to tracking this down; it turns out that the psymtabs are correct and the symtabs are wrong in this case. Specifically, in dwarf2read.c, psymtab_to_symtab_1 and read_file_scope, when determining the PC bounds of the file, assume that all functions are children of the DW_TAG_compile_unit die, which isn't the case once DW_TAG_namesepace appears. (Actually, it seems to me that DW_TAG_class_type could already cause problems; it's just that GCC doesn't generate debug info in a form that could trigger this issue.) I've applied the attached patch to my branch. This problem is on mainline, too, though (and has been there since 5.3, alas); I'll submit a mainline patch in a bit. It shouldn't affect people using any released version of GCC, since they don't use DW_TAG_namespace. (Whoops, there's a typo in a comment. I'll fix that in a sec.) David Carlton carlton@kealia.com 2003-12-15 David Carlton * dwarf2read.c (get_scope_pc_bounds): New. (psymtab_to_symtab_1): Use get_scope_pc_bounds. (read_file_scope): Ditto. Index: dwarf2read.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2read.c,v retrieving revision 1.66.4.38 diff -u -p -r1.66.4.38 dwarf2read.c --- dwarf2read.c 12 Nov 2003 00:20:58 -0000 1.66.4.38 +++ dwarf2read.c 15 Dec 2003 21:14:43 -0000 @@ -840,6 +840,10 @@ static int dwarf2_get_pc_bounds (struct CORE_ADDR *, CORE_ADDR *, struct objfile *, const struct comp_unit_head *); +static void get_scope_pc_bounds (struct die_info *, + CORE_ADDR *, CORE_ADDR *, struct objfile *, + const struct comp_unit_head *); + static void dwarf2_add_field (struct field_info *, struct die_info *, struct objfile *, const struct comp_unit_head *); @@ -1977,31 +1981,7 @@ psymtab_to_symtab_1 (struct partial_symt /* Do line number decoding in read_file_scope () */ process_die (dies, objfile, &cu_header); - if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile, &cu_header)) - { - /* Some compilers don't define a DW_AT_high_pc attribute for - the compilation unit. If the DW_AT_high_pc is missing, - synthesize it, by scanning the DIE's below the compilation unit. */ - highpc = 0; - if (dies->child != NULL) - { - child_die = dies->child; - while (child_die && child_die->tag) - { - if (child_die->tag == DW_TAG_subprogram) - { - CORE_ADDR low, high; - - if (dwarf2_get_pc_bounds (child_die, &low, &high, - objfile, &cu_header)) - { - highpc = max (highpc, high); - } - } - child_die = sibling_die (child_die); - } - } - } + get_scope_pc_bounds (dies, &lowpc, &highpc, objfile, &cu_header); symtab = end_symtab (highpc + baseaddr, objfile, SECT_OFF_TEXT (objfile)); /* Set symtab language to language from DW_AT_language. @@ -2125,28 +2105,7 @@ read_file_scope (struct die_info *die, s bfd *abfd = objfile->obfd; struct line_header *line_header = 0; - if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header)) - { - if (die->child != NULL) - { - child_die = die->child; - while (child_die && child_die->tag) - { - if (child_die->tag == DW_TAG_subprogram) - { - CORE_ADDR low, high; - - if (dwarf2_get_pc_bounds (child_die, &low, &high, - objfile, cu_header)) - { - lowpc = min (lowpc, low); - highpc = max (highpc, high); - } - } - child_die = sibling_die (child_die); - } - } - } + get_scope_pc_bounds (die, &lowpc, &highpc, objfile, cu_header); /* If we didn't find a lowpc, set it to highpc to avoid complaints from finish_block. */ @@ -2575,6 +2534,69 @@ dwarf2_get_pc_bounds (struct die_info *d *lowpc = low; *highpc = high; return ret; +} + +/* 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. */ +static void +get_scope_pc_bounds (struct die_info *die, + CORE_ADDR *lowpc, CORE_ADDR *highpc, + struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + CORE_ADDR best_low = (CORE_ADDR) -1; + CORE_ADDR best_high = (CORE_ADDR) 0; + CORE_ADDR current_low, current_high; + + if (dwarf2_get_pc_bounds (die, ¤t_low, ¤t_high, + objfile, cu_header)) + { + best_low = current_low; + best_high = current_high; + } + else + { + struct die_info *child = die->child; + + while (child && child->tag) + { + switch (child->tag) { + case DW_TAG_subprogram: + if (dwarf2_get_pc_bounds (child, ¤t_low, ¤t_high, + objfile, cu_header)); + { + best_low = min (best_low, current_low); + best_high = max (best_high, current_high); + } + break; + case DW_TAG_namespace: + /* FIXME: carlton/2003-12-15: Should we do this for + DW_TAG_class_type/DW_TAG_structure_type, too? I think + that current GCC's always generate the DIEs + corresponding to definitions methods of classes at + namespace scope, but I don't see any reason why they + have to. */ + get_scope_pc_bounds (child, ¤t_low, ¤t_high, + objfile, cu_header); + + if (current_low != ((CORE_ADDR) -1)) + { + best_low = min (best_low, current_low); + best_high = max (best_high, current_high); + } + break; + default: + /* Ignore. */ + break; + } + + child = sibling_die (child); + } + } + + *lowpc = best_low; + *highpc = best_high; } /* Add an aggregate field to the field list. */