blob: 97f28d050138737ae128f4b6d0a2aab1a75aab23 [file] [log] [blame]
/* 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 <http://www.gnu.org/licenses/>. */
#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;
}