/* Pedantic checking of DWARF files Copyright (C) 2010, 2011 Red Hat, Inc. This file is part of elfutils. This file is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "dwarf_version-imp.hh" #include "../libdw/dwarf.h" namespace { struct dwarf_gnu_attributes : public attribute_table { void unused (__attribute__ ((unused)) attribute const &attrib) const {} dwarf_gnu_attributes () { // It's rather hard to find any reference on some of the GNU // extensions. So we simply mark these with unused. // The MIPS documentation claims that these are "apparently only // output in DWARF1, not DWARF2". I found nothing particular // about how these are used. unused (const_attribute (DW_AT_sf_names)); unused (const_attribute (DW_AT_src_info)); unused (const_attribute (DW_AT_mac_info)); unused (const_attribute (DW_AT_src_coords)); unused (const_attribute (DW_AT_body_begin)); unused (const_attribute (DW_AT_body_end)); add (flag_attribute (DW_AT_GNU_vector)); // xxx these are glass cl_GNU_mutexlistptr. data4 and data8 are // supposed to have this class. So how do we smuggle this class // to whatever DW_FORM_data4 and DW_FORM_data8 have in current // version? For now, just claim it's plain old constant. // http://gcc.gnu.org/wiki/ThreadSafetyAnnotationsInDWARF add (const_attribute (DW_AT_GNU_guarded_by)); add (const_attribute (DW_AT_GNU_pt_guarded_by)); add (const_attribute (DW_AT_GNU_guarded)); add (const_attribute (DW_AT_GNU_pt_guarded)); add (const_attribute (DW_AT_GNU_locks_excluded)); add (const_attribute (DW_AT_GNU_exclusive_locks_required)); add (const_attribute (DW_AT_GNU_shared_locks_required)); // Contains a shallower 8-byte signature of the type described // in the type unit. This is nominally a const_attribute, but // we do the checking ourselves in form_allowed. // http://gcc.gnu.org/wiki/DwarfSeparateTypeInfo add (const_attribute (DW_AT_GNU_odr_signature)); // http://gcc.gnu.org/wiki/TemplateParmsDwarf add (string_attribute (DW_AT_GNU_template_name)); // GNU extensions for representation of call sites // http://www.dwarfstd.org/ShowIssue.php?issue=100909.2 add (attribute (DW_AT_GNU_call_site_value, cl_exprloc)); add (attribute (DW_AT_GNU_call_site_data_value, cl_exprloc)); add (attribute (DW_AT_GNU_call_site_target, cl_exprloc)); add (attribute (DW_AT_GNU_call_site_target_clobbered, cl_exprloc)); add (flag_attribute (DW_AT_GNU_tail_call)); add (flag_attribute (DW_AT_GNU_all_tail_call_sites)); add (flag_attribute (DW_AT_GNU_all_call_sites)); add (flag_attribute (DW_AT_GNU_all_source_call_sites)); } }; struct dwarf_gnu_ext_t : public std_dwarf { dwarf_gnu_ext_t () : std_dwarf (dwarf_gnu_attributes (), form_table ()) {} virtual bool form_allowed (attribute const *attr, form const *form) const { // Without -gstrict-dwarf gcc allows usage of attributes from // later versions. One strange case is DW_AT_ranges in version 2 // since that version doesn't actually define a rangelistptr // class. So we just allow data4 or data8 here. if (attr->name () == DW_AT_ranges) { form_width_t width = form->width (NULL); return (form->classes ()[cl_constant] && (width == fw_4 || width == fw_8)); } // upper_bound is allowed to also be a block (dwarf3 in dwarf2). if (attr->name () == DW_AT_upper_bound) return form->classes ()[cl_block]; if (attr->name () == DW_AT_GNU_odr_signature) return form->classes ()[cl_constant] && form->width (NULL) == fw_8; else return std_dwarf::form_allowed (attr, form); } }; } dwarf_version const * dwarf_gnu_ext () { static dwarf_gnu_ext_t dw; return &dw; }