From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 30965 invoked by alias); 30 Jan 2003 01:02:35 -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 30958 invoked from network); 30 Jan 2003 01:02:35 -0000 Received: from unknown (HELO mx1.redhat.com) (172.16.49.200) by 172.16.49.205 with SMTP; 30 Jan 2003 01:02:35 -0000 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.11.6/8.11.6) with ESMTP id h0U0XAf24730 for ; Wed, 29 Jan 2003 19:33:10 -0500 Received: from pobox.corp.redhat.com (pobox.corp.redhat.com [172.16.52.156]) by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id h0U12Za08382; Wed, 29 Jan 2003 20:02:35 -0500 Received: from localhost.redhat.com (romulus-int.sfbay.redhat.com [172.16.27.46]) by pobox.corp.redhat.com (8.11.6/8.11.6) with ESMTP id h0U12WC09347; Wed, 29 Jan 2003 20:02:33 -0500 Received: by localhost.redhat.com (Postfix, from userid 469) id EC60FFF79; Wed, 29 Jan 2003 20:06:46 -0500 (EST) From: Elena Zannoni MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Message-ID: <15928.31398.39881.249991@localhost.redhat.com> Date: Thu, 30 Jan 2003 01:02:00 -0000 To: Daniel Jacobowitz Cc: Elena Zannoni , Jim Blandy , Richard Henderson , gdb-patches@sources.redhat.com Subject: Re: [RFC] Partial support for dwarf3 DW_AT_ranges In-Reply-To: <20030130005208.GA28894@nevyn.them.org> References: <20011231003448.A3399@redhat.com> <15413.57239.249007.204757@localhost.localdomain> <20030129155346.GA13172@nevyn.them.org> <15928.6608.942581.500183@localhost.redhat.com> <20030130005208.GA28894@nevyn.them.org> X-SW-Source: 2003-01/txt/msg00799.txt.bz2 Daniel Jacobowitz writes: > On Wed, Jan 29, 2003 at 01:13:36PM -0500, Elena Zannoni wrote: > > If you have time, I'd appreciate it. I have adapted the patch to the > > current sources, but even with it, I wasn't able to make Jakub's > > example work. The example is in PR 833. > > I can send you the diffs I have, if it helps. > > This is pretty similar to what you sent me, cleaned up a little to > match my reading of the standard. It works to fix my testcase for PR > gdb/961, which is a simpler case of disappearing local variables. > I'll submit that for the testsuite separately but I don't know quite > how to do it yet; the problem is not going to show up if you don't have > optimization. > cool! i think there is a testcase in gdb.base somewhere that turns optimization up to -O2, so you could copy that (mips-pro.exp and break.exp), if this is what you are asking. > This doesn't solve PR gdb/833, for the reasons outlined in my previous > message. > > How does this patch look? > ok with me. thanks!! elena > -- > Daniel Jacobowitz > MontaVista Software Debian GNU/Linux Developer > > 2003-01-29 Richard Henderson > Elena Zannoni > Daniel Jacobowitz > > Fix PR gdb/961. > * dwarf2read.c (dwarf_ranges_offset, dwarf_ranges_size): New > variables. > (RANGES_SECTION): New. > (dwarf_ranges_buffer): New variable. > (struct comp_unit_head): Add member "die". > (struct dwarf2_pinfo): Add dwarf_ranges_buffer, dwarf_ranges_size. > (DWARF_RANGES_BUFFER, DWARF_RANGES_SIZE): New. > (dwarf2_has_info): Init dwarf_ranges_offset and dwarf_ranges_size. > (dwarf2_locate_sections): Likewise. > (dwarf2_build_psymtabs): Read .debug_ranges. > (dwarf2_build_psymtabs_hard): Swap dwarf_ranges out. > (psymtab_to_symtab_1): Swap dwarf_ranges in. Set cu_header.die. > (RANGES_SECTION): New. twice mentioned > (dwarf2_get_pc_bounds): New cu_header argument; adjust all callers. > Look for DW_AT_ranges and return the bounding box. > > Index: dwarf2read.c > =================================================================== > RCS file: /big/fsf/rsync/src-cvs/src/gdb/dwarf2read.c,v > retrieving revision 1.79 > diff -u -p -r1.79 dwarf2read.c > --- dwarf2read.c 18 Jan 2003 15:55:51 -0000 1.79 > +++ dwarf2read.c 30 Jan 2003 00:41:19 -0000 > @@ -133,6 +133,7 @@ static file_ptr dwarf_aranges_offset; > static file_ptr dwarf_loc_offset; > static file_ptr dwarf_macinfo_offset; > static file_ptr dwarf_str_offset; > +static file_ptr dwarf_ranges_offset; > file_ptr dwarf_frame_offset; > file_ptr dwarf_eh_frame_offset; > > @@ -144,6 +145,7 @@ static unsigned int dwarf_aranges_size; > static unsigned int dwarf_loc_size; > static unsigned int dwarf_macinfo_size; > static unsigned int dwarf_str_size; > +static unsigned int dwarf_ranges_size; > unsigned int dwarf_frame_size; > unsigned int dwarf_eh_frame_size; > > @@ -157,6 +159,7 @@ unsigned int dwarf_eh_frame_size; > #define LOC_SECTION ".debug_loc" > #define MACINFO_SECTION ".debug_macinfo" > #define STR_SECTION ".debug_str" > +#define RANGES_SECTION ".debug_ranges" > #define FRAME_SECTION ".debug_frame" > #define EH_FRAME_SECTION ".eh_frame" > > @@ -202,6 +205,10 @@ struct comp_unit_head > /* DWARF abbreviation table associated with this compilation unit */ > > struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE]; > + > + /* Pointer to the DIE associated with the compilation unit. */ > + > + struct die_info *die; > }; > > /* The line number information for a compilation unit (found in the > @@ -373,6 +380,7 @@ static char *dwarf_abbrev_buffer; > static char *dwarf_line_buffer; > static char *dwarf_str_buffer; > static char *dwarf_macinfo_buffer; > +static char *dwarf_ranges_buffer; > > /* A zeroed version of a partial die for initialization purposes. */ > static struct partial_die_info zeroed_partial_die; > @@ -481,6 +489,14 @@ struct dwarf2_pinfo > > unsigned int dwarf_macinfo_size; > > + /* Pointer to start of dwarf ranges buffer for the objfile. */ > + > + char *dwarf_ranges_buffer; > + > + /* Size of dwarf ranges buffer for the objfile. */ > + > + unsigned int dwarf_ranges_size; > + > }; > > #define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private) > @@ -494,6 +510,8 @@ struct dwarf2_pinfo > #define DWARF_STR_SIZE(p) (PST_PRIVATE(p)->dwarf_str_size) > #define DWARF_MACINFO_BUFFER(p) (PST_PRIVATE(p)->dwarf_macinfo_buffer) > #define DWARF_MACINFO_SIZE(p) (PST_PRIVATE(p)->dwarf_macinfo_size) > +#define DWARF_RANGES_BUFFER(p) (PST_PRIVATE(p)->dwarf_ranges_buffer) > +#define DWARF_RANGES_SIZE(p) (PST_PRIVATE(p)->dwarf_ranges_size) > > /* Maintain an array of referenced fundamental types for the current > compilation unit being read. For DWARF version 1, we have to construct > @@ -751,7 +769,8 @@ static void read_lexical_block_scope (st > const struct comp_unit_head *); > > static int dwarf2_get_pc_bounds (struct die_info *, > - CORE_ADDR *, CORE_ADDR *, struct objfile *); > + 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 *); > @@ -886,6 +905,8 @@ dwarf2_has_info (bfd *abfd) > dwarf_macinfo_offset = 0; > dwarf_frame_offset = 0; > dwarf_eh_frame_offset = 0; > + dwarf_ranges_offset = 0; > + > bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL); > if (dwarf_info_offset && dwarf_abbrev_offset) > { > @@ -954,6 +975,11 @@ dwarf2_locate_sections (bfd *ignore_abfd > dwarf_eh_frame_offset = sectp->filepos; > dwarf_eh_frame_size = bfd_get_section_size_before_reloc (sectp); > } > + else if (STREQ (sectp->name, RANGES_SECTION)) > + { > + dwarf_ranges_offset = sectp->filepos; > + dwarf_ranges_size = bfd_get_section_size_before_reloc (sectp); > + } > } > > /* Build a partial symbol table. */ > @@ -992,6 +1018,13 @@ dwarf2_build_psymtabs (struct objfile *o > else > dwarf_macinfo_buffer = NULL; > > + if (dwarf_ranges_offset) > + dwarf_ranges_buffer = dwarf2_read_section (objfile, > + dwarf_ranges_offset, > + dwarf_ranges_size); > + else > + dwarf_ranges_buffer = NULL; > + > if (mainline > || (objfile->global_psymbols.size == 0 > && objfile->static_psymbols.size == 0)) > @@ -1207,6 +1240,8 @@ dwarf2_build_psymtabs_hard (struct objfi > DWARF_STR_SIZE (pst) = dwarf_str_size; > DWARF_MACINFO_BUFFER (pst) = dwarf_macinfo_buffer; > DWARF_MACINFO_SIZE (pst) = dwarf_macinfo_size; > + DWARF_RANGES_BUFFER (pst) = dwarf_ranges_buffer; > + DWARF_RANGES_SIZE (pst) = dwarf_ranges_size; > baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); > > /* Store the function that reads in the rest of the symbol table */ > @@ -1543,6 +1578,8 @@ psymtab_to_symtab_1 (struct partial_symt > dwarf_str_size = DWARF_STR_SIZE (pst); > dwarf_macinfo_buffer = DWARF_MACINFO_BUFFER (pst); > dwarf_macinfo_size = DWARF_MACINFO_SIZE (pst); > + dwarf_ranges_buffer = DWARF_RANGES_BUFFER (pst); > + dwarf_ranges_size = DWARF_RANGES_SIZE (pst); > baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile)); > cu_header_offset = offset; > info_ptr = dwarf_info_buffer + offset; > @@ -1565,9 +1602,10 @@ psymtab_to_symtab_1 (struct partial_symt > make_cleanup_free_die_list (dies); > > /* Do line number decoding in read_file_scope () */ > + cu_header.die = dies; > process_die (dies, objfile, &cu_header); > > - if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile)) > + 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, > @@ -1582,7 +1620,8 @@ psymtab_to_symtab_1 (struct partial_symt > { > CORE_ADDR low, high; > > - if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile)) > + if (dwarf2_get_pc_bounds (child_die, &low, &high, > + objfile, &cu_header)) > { > highpc = max (highpc, high); > } > @@ -1711,7 +1750,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)) > + if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header)) > { > if (die->has_children) > { > @@ -1722,7 +1761,8 @@ read_file_scope (struct die_info *die, s > { > CORE_ADDR low, high; > > - if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile)) > + if (dwarf2_get_pc_bounds (child_die, &low, &high, > + objfile, cu_header)) > { > lowpc = min (lowpc, low); > highpc = max (highpc, high); > @@ -1868,7 +1908,7 @@ read_func_scope (struct die_info *die, s > > /* Ignore functions with missing or empty names and functions with > missing or invalid low and high pc attributes. */ > - if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile)) > + if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header)) > return; > > lowpc += baseaddr; > @@ -1966,7 +2006,11 @@ read_lexical_block_scope (struct die_inf > struct die_info *child_die; > > /* Ignore blocks with missing or invalid low and high pc attributes. */ > - if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile)) > + /* ??? Perhaps consider discontiguous blocks defined by DW_AT_ranges > + as multiple lexical blocks? Handling children in a sane way would > + be nasty. Might be easier to properly extend generic blocks to > + describe ranges. */ > + if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header)) > return; > lowpc += baseaddr; > highpc += baseaddr; > @@ -1991,27 +2035,159 @@ read_lexical_block_scope (struct die_inf > local_symbols = new->locals; > } > > -/* Get low and high pc attributes from a die. > - Return 1 if the attributes are present and valid, otherwise, return 0. */ > - > +/* Get low and high pc attributes from a die. Return 1 if the attributes > + are present and valid, otherwise, return 0. Return -1 if the range is > + discontinuous, i.e. derived from DW_AT_ranges information. */ > static int > -dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, CORE_ADDR *highpc, > - struct objfile *objfile) > +dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, > + CORE_ADDR *highpc, struct objfile *objfile, > + const struct comp_unit_head *cu_header) > { > struct attribute *attr; > - CORE_ADDR low; > - CORE_ADDR high; > + bfd *obfd = objfile->obfd; > + CORE_ADDR low = 0; > + CORE_ADDR high = 0; > + int ret = 0; > > - attr = dwarf_attr (die, DW_AT_low_pc); > - if (attr) > - low = DW_ADDR (attr); > - else > - return 0; > attr = dwarf_attr (die, DW_AT_high_pc); > if (attr) > - high = DW_ADDR (attr); > + { > + high = DW_ADDR (attr); > + attr = dwarf_attr (die, DW_AT_low_pc); > + if (attr) > + low = DW_ADDR (attr); > + else > + /* Found high w/o low attribute. */ > + return 0; > + > + /* Found consecutive range of addresses. */ > + ret = 1; > + } > else > - return 0; > + { > + attr = dwarf_attr (die, DW_AT_ranges); > + if (attr != NULL) > + { > + unsigned int addr_size = cu_header->addr_size; > + CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1)); > + /* Value of the DW_AT_ranges attribute is the offset in the > + .debug_renges section. */ > + unsigned int offset = DW_UNSND (attr); > + /* Base address selection entry. */ > + CORE_ADDR base = 0; > + int found_base = 0; > + int dummy; > + unsigned int i; > + char *buffer; > + CORE_ADDR marker; > + int low_set; > + > + /* The applicable base address is determined by (1) the closest > + preceding base address selection entry in the range list or > + (2) the DW_AT_low_pc of the compilation unit. */ > + > + /* ??? Was in dwarf3 draft4, and has since been removed. > + GCC still uses it though. */ > + attr = dwarf_attr (cu_header->die, DW_AT_entry_pc); > + if (attr) > + { > + base = DW_ADDR (attr); > + found_base = 1; > + } > + > + if (!found_base) > + { > + attr = dwarf_attr (cu_header->die, DW_AT_low_pc); > + if (attr) > + { > + base = DW_ADDR (attr); > + found_base = 1; > + } > + } > + > + buffer = dwarf_ranges_buffer + offset; > + > + > + /* Read in the largest possible address. */ > + marker = read_address (obfd, buffer, cu_header, &dummy); > + if ((marker & mask) == mask) > + { > + /* If we found the largest possible address, then > + read the base address. */ > + base = read_address (obfd, buffer + addr_size, > + cu_header, &dummy); > + buffer += 2 * addr_size; > + offset += 2 * addr_size; > + found_base = 1; > + } > + > + low_set = 0; > + > + while (1) > + { > + CORE_ADDR range_beginning, range_end; > + > + range_beginning = read_address (obfd, buffer, > + cu_header, &dummy); > + buffer += addr_size; > + range_end = read_address (obfd, buffer, cu_header, &dummy); > + buffer += addr_size; > + offset += 2 * addr_size; > + > + /* An end of list marker is a pair of zero addresses. */ > + if (range_beginning == 0 && range_end == 0) > + /* Found the end of list entry. */ > + break; > + > + /* Each base address selection entry is a pair of 2 values. > + The first is the largest possible address, the second is > + the base address. Check for a base address here. */ > + if ((range_beginning & mask) == mask) > + { > + /* If we found the largest possible address, then > + read the base address. */ > + base = read_address (obfd, buffer + addr_size, > + cu_header, &dummy); > + found_base = 1; > + continue; > + } > + > + if (!found_base) > + { > + /* We have no valid base address for the ranges > + data. */ > + complaint (&symfile_complaints, > + "Invalid .debug_ranges data (no base address)"); > + return 0; > + } > + > + /* FIXME: This is recording everything as a low-high > + segment of consecutive addresses. We should have a > + data structure for discontiguous block ranges > + instead. */ > + if (! low_set) > + { > + low = range_beginning; > + high = range_end; > + low_set = 1; > + } > + else > + { > + if (range_beginning < low) > + low = range_beginning; > + if (range_end > high) > + high = range_end; > + } > + } > + > + if (! low_set) > + /* If the first entry is an end-of-list marker, the range > + describes an empty scope, i.e. no instructions. */ > + return 0; > + > + ret = -1; > + } > + } > > if (high < low) > return 0; > @@ -2024,12 +2200,12 @@ dwarf2_get_pc_bounds (struct die_info *d > labels are not in the output, so the relocs get a value of 0. > If this is a discarded function, mark the pc bounds as invalid, > so that GDB will ignore it. */ > - if (low == 0 && (bfd_get_file_flags (objfile->obfd) & HAS_RELOC) == 0) > + if (low == 0 && (bfd_get_file_flags (obfd) & HAS_RELOC) == 0) > return 0; > > *lowpc = low; > *highpc = high; > - return 1; > + return ret; > } > > /* Add an aggregate field to the field list. */