summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2011-03-30 12:44:14 +0200
committerMark Wielaard <mjw@redhat.com>2011-03-31 12:55:20 +0200
commit71f19d6c7760055c12ae521f8e62124fc963252a (patch)
tree5647ee5d66286b683bd93222b68ea503b02fbab5
parent01b2cde6b5d1839dcc73381ecb442f5ba8346674 (diff)
downloadelfutils-71f19d6c7760055c12ae521f8e62124fc963252a.tar.gz
dwarflint: Allow DW_AT_ranges with const form, as gnu version 2 extension.
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. This case is added in the form_allowed override for dwarf_gnu, for version 2. In gnu mode form_allowed checks both variants, source and extension, in no-gnu mode, only the latest is allowed.
-rw-r--r--dwarflint/dwarf_gnu.cc26
-rw-r--r--dwarflint/dwarf_gnu.hh2
-rw-r--r--dwarflint/dwarf_version.cc22
3 files changed, 39 insertions, 11 deletions
diff --git a/dwarflint/dwarf_gnu.cc b/dwarflint/dwarf_gnu.cc
index b70a6d2d..6fa50bef 100644
--- a/dwarflint/dwarf_gnu.cc
+++ b/dwarflint/dwarf_gnu.cc
@@ -86,13 +86,27 @@ namespace
struct dwarf_gnu_ext_t
: public std_dwarf
{
- dwarf_gnu_ext_t ()
- : std_dwarf (dwarf_gnu_attributes (), form_table ())
- {}
+ unsigned _m_version;
- virtual bool
+ dwarf_gnu_ext_t (unsigned version)
+ : std_dwarf (dwarf_gnu_attributes (), form_table ()),
+ _m_version (version)
+ { }
+
+ 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 (_m_version == 2 && attr->name () == DW_AT_ranges)
+ {
+ form_width_t width = form->width (NULL);
+ return (form->classes ()[cl_constant]
+ && (width == fw_4 || width == fw_8));
+ }
+
if (attr->name () == DW_AT_GNU_odr_signature)
return form->classes ()[cl_constant] && form->width (NULL) == fw_8;
else
@@ -102,8 +116,8 @@ namespace
}
dwarf_version const *
-dwarf_gnu_ext ()
+dwarf_gnu_ext (unsigned version)
{
- static dwarf_gnu_ext_t dw;
+ static dwarf_gnu_ext_t dw (version);
return &dw;
}
diff --git a/dwarflint/dwarf_gnu.hh b/dwarflint/dwarf_gnu.hh
index dde52f4f..14ce31c0 100644
--- a/dwarflint/dwarf_gnu.hh
+++ b/dwarflint/dwarf_gnu.hh
@@ -28,6 +28,6 @@
#include "dwarf_version.ii"
-dwarf_version const *dwarf_gnu_ext ();
+dwarf_version const *dwarf_gnu_ext (unsigned version);
#endif//DWARFLINT_DWARF_GNU_HH
diff --git a/dwarflint/dwarf_version.cc b/dwarflint/dwarf_version.cc
index a74e1699..60021521 100644
--- a/dwarflint/dwarf_version.cc
+++ b/dwarflint/dwarf_version.cc
@@ -219,6 +219,18 @@ namespace
ret = _m_source->ambiguous_class (form, attribute, candidates);
return ret;
}
+
+ bool
+ form_allowed (attribute const *attr, form const *form) const
+ {
+ // In GNU mode any combination of new attribute/old form goes,
+ // in strict mode only the latest.
+ if (opt_nognu)
+ return _m_extension->form_allowed (attr, form);
+ else
+ return (_m_source->form_allowed (attr, form)
+ || _m_extension->form_allowed (attr, form));
+ }
};
}
@@ -235,7 +247,7 @@ dwarf_version::extend (dwarf_version const *source,
namespace
{
- dwarf_version const *get_ext ()
+ dwarf_version const *get_ext (unsigned version)
{
// xxx The GNU toolchain commonly uses DW_AT_MIPS_linkage_name,
// which is part of the MIPS extensions. So that's what we
@@ -247,31 +259,33 @@ namespace
if (opt_nognu)
return dwarf_mips_ext ();
else
- return dwarf_version::extend (dwarf_mips_ext (), dwarf_gnu_ext ());
+ return dwarf_version::extend (dwarf_mips_ext (),
+ dwarf_gnu_ext (version));
}
}
dwarf_version const *
dwarf_version::get (unsigned version)
{
- static dwarf_version const *ext = get_ext ();
-
switch (version)
{
case 2:
{
+ static dwarf_version const *ext = get_ext (2);
static dwarf_version const *dw = extend (dwarf_2 (), ext);
return dw;
}
case 3:
{
+ static dwarf_version const *ext = get_ext (3);
static dwarf_version const *dw = extend (dwarf_3 (), ext);
return dw;
}
case 4:
{
+ static dwarf_version const *ext = get_ext (4);
static dwarf_version const *dw = extend (dwarf_4 (), ext);
return dw;
}