From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9620 invoked by alias); 1 Dec 2007 01:48:18 -0000 Received: (qmail 9610 invoked by uid 22791); 1 Dec 2007 01:48:17 -0000 X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.31) with ESMTP; Sat, 01 Dec 2007 01:48:11 +0000 Received: (qmail 5358 invoked from network); 1 Dec 2007 01:48:09 -0000 Received: from unknown (HELO localhost) (jimb@127.0.0.2) by mail.codesourcery.com with ESMTPA; 1 Dec 2007 01:48:09 -0000 To: Vladimir Prus Cc: gdb-patches@sources.redhat.com Subject: Re: Support constants for DW_AT_data_member_location References: <200711291254.14423.vladimir@codesourcery.com> <200711292317.53967.vladimir@codesourcery.com> From: Jim Blandy Date: Sat, 01 Dec 2007 01:48:00 -0000 In-Reply-To: <200711292317.53967.vladimir@codesourcery.com> (Vladimir Prus's message of "Thu, 29 Nov 2007 23:17:53 +0300") Message-ID: User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-IsSubscribed: yes 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: 2007-12/txt/msg00003.txt.bz2 Vladimir Prus writes: > This is wrong, per DWARF standard: > > Some encodings are members of more than one class; in that case, > the list of classes allowed by the applicable attribute in > Figure 18 determines the class of the form. DW_FORM_data4 and > DW_FORM_data8 may be members of classes constant, lineptr, > loclistptr, macptr and rangelistptr. They are members of the > class constant if used for the value of an attribute that allows class > constant but not class lineptr, loclistptr, macptr or rangelistptr. > They are members of the class lineptr, loclistptr, macptr or > rangelistptr if used for the value of an attribute that allows > one of those classes. > > Referring to Figure 18, I see: > > Attribute name Classes > DW_AT_data_member_location block, constant, loclistptr > > So, DW_FORM_data4 used for DW_AT_data_member_location is never interepreted > as constant. Maybe we should have "is_surely_constant" function? Oh --- great catch, thanks. (We don't support location lists for DW_AT_data_member_location yet, but we certainly should warn, not randomly misinterpret the value.) How's this, then? gdb/ChangeLog: 2007-11-30 Jim Blandy * dwarf2read.c (attr_form_is_constant): New function. (dwarf2_add_field): Use it and attr_form_is_section_offset to recognize DW_AT_data_member_location attributes. Use dwarf2_get_attr_constant_value when the attribute is a constant. * dwarf2read.c (attr_form_is_section_offset): New function. (dwarf_add_member_fn, read_common_block, read_partial_die) (dwarf2_symbol_mark_computed): Use it, instead of writing it out. diff -r c4f654de59cf gdb/dwarf2read.c --- a/gdb/dwarf2read.c Thu Nov 29 11:28:59 2007 -0800 +++ b/gdb/dwarf2read.c Fri Nov 30 17:32:46 2007 -0800 @@ -1039,6 +1039,10 @@ static void dwarf_decode_macros (struct char *, bfd *, struct dwarf2_cu *); static int attr_form_is_block (struct attribute *); + +static int attr_form_is_section_offset (struct attribute *); + +static int attr_form_is_constant (struct attribute *); static void dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, @@ -3380,8 +3384,16 @@ dwarf2_add_field (struct field_info *fip attr = dwarf2_attr (die, DW_AT_data_member_location, cu); if (attr) { - FIELD_BITPOS (*fp) = - decode_locdesc (DW_BLOCK (attr), cu) * bits_per_byte; + if (attr_form_is_section_offset (attr)) + { + dwarf2_complex_location_expr_complaint (); + FIELD_BITPOS (*fp) = 0; + } + else if (attr_form_is_constant (attr)) + FIELD_BITPOS (*fp) = dwarf2_get_attr_constant_value (attr, 0); + else + FIELD_BITPOS (*fp) = + decode_locdesc (DW_BLOCK (attr), cu) * bits_per_byte; } else FIELD_BITPOS (*fp) = 0; @@ -3700,7 +3712,7 @@ dwarf2_add_member_fn (struct field_info { fnp->voffset = decode_locdesc (DW_BLOCK (attr), cu) + 2; } - else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8) + else if (attr_form_is_section_offset (attr)) { dwarf2_complex_location_expr_complaint (); } @@ -4416,7 +4428,7 @@ read_common_block (struct die_info *die, { base = decode_locdesc (DW_BLOCK (attr), cu); } - else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8) + else if (attr_form_is_section_offset (attr)) { dwarf2_complex_location_expr_complaint (); } @@ -5598,7 +5610,7 @@ read_partial_die (struct partial_die_inf { part_die->locdesc = DW_BLOCK (&attr); } - else if (attr.form == DW_FORM_data4 || attr.form == DW_FORM_data8) + else if (attr_form_is_section_offset (&attr)) { dwarf2_complex_location_expr_complaint (); } @@ -9755,6 +9767,46 @@ attr_form_is_block (struct attribute *at || attr->form == DW_FORM_block); } +/* Return non-zero if ATTR's value is a section offset (classes + lineptr, loclistptr, macptr or rangelistptr). In this case, + you may use DW_UNSND (attr) to retrieve the offset. */ +static int +attr_form_is_section_offset (struct attribute *attr) +{ + return (attr->form == DW_FORM_data4 + || attr->form == DW_FORM_data8); +} + + +/* Return non-zero if ATTR's value falls in the 'constant' class, or + zero otherwise. When this function returns true, you can apply + dwarf2_get_attr_constant_value to it. + + However, note that for some attributes you must check + attr_form_is_section_offset before using this test. DW_FORM_data4 + and DW_FORM_data8 are members of both the constant class, and of + the classes that contain offsets into other debug sections + (lineptr, loclistptr, macptr or rangelistptr). The DWARF spec says + that, if an attribute's can be either a constant or one of the + section offset classes, DW_FORM_data4 and DW_FORM_data8 should be + taken as section offsets, not constants. */ +static int +attr_form_is_constant (struct attribute *attr) +{ + switch (attr->form) + { + case DW_FORM_sdata: + case DW_FORM_udata: + case DW_FORM_data1: + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_data8: + return 1; + default: + return 0; + } +} + static void dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, struct dwarf2_cu *cu) @@ -9766,7 +9818,7 @@ dwarf2_symbol_mark_computed (struct attr if (objfile->separate_debug_objfile_backlink) objfile = objfile->separate_debug_objfile_backlink; - if ((attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8) + if (attr_form_is_section_offset (attr) /* ".debug_loc" may not exist at all, or the offset may be outside the section. If so, fall through to the complaint in the other branch. */