]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
dwarflint: Add dwarf_version::form_class, ~::ambiguous_class, drop form::cls
authorPetr Machata <pmachata@redhat.com>
Thu, 7 Oct 2010 15:46:58 +0000 (17:46 +0200)
committerPetr Machata <pmachata@redhat.com>
Thu, 7 Oct 2010 15:46:58 +0000 (17:46 +0200)
- And use that in dwarf_3 to properly support DW_AT_data_member_location

dwarflint/dwarf_3.cc
dwarflint/dwarf_version.cc
dwarflint/dwarf_version.hh

index 3afb3ca58a1909cda356e28a37ab935694d97529..64713c5b84ef53c7f93d8e8153d3981c1ba2be76 100644 (file)
@@ -27,6 +27,7 @@
 #include "dwarf_2.hh"
 #include "dwarf_3.hh"
 #include "../libdw/dwarf.h"
+#include <cassert>
 
 namespace
 {
@@ -112,6 +113,16 @@ namespace
     dwarf_3_ext_t ()
       : std_dwarf (dwarf_3_attributes (), dwarf_3_forms ())
     {}
+
+    dw_class
+    ambiguous_class (__attribute__ ((unused)) form const *form,
+                    attribute const *attribute,
+                    dw_class_set const &candidates) const
+    {
+      assert (attribute->name () == DW_AT_data_member_location);
+      assert (candidates == dw_class_set (cl_constant, cl_loclistptr));
+      return cl_loclistptr;
+    }
   };
 }
 
index bab5a70983eb9a26bbf313a4b5098f21f7246f48..a5f3371f912aefa30443b605c3d6f0217e87c26c 100644 (file)
@@ -59,7 +59,7 @@ form::form (int a_name, dw_class_set a_classes,
 {}
 
 form::form (int a_name, dw_class_set a_classes,
-      form_width_special_t a_width, storage_class_t a_storclass)
+           form_width_special_t a_width, storage_class_t a_storclass)
   : _m_name (a_name)
   , _m_classes (a_classes)
   , _m_width (a_width)
@@ -67,13 +67,22 @@ form::form (int a_name, dw_class_set a_classes,
 {}
 
 dw_class
-form::cls (attribute const *attribute) const
+dwarf_version::form_class (form const *form, attribute const *attribute) const
 {
+  assert (form != NULL);
   assert (attribute != NULL);
-  dw_class_set result = classes ();
+  dw_class_set result = form->classes ();
   result &= attribute->classes ();
-  assert (result.count () == 1);
-  return static_cast<dw_class> (ffsl (result.to_ulong ()));
+  assert (result.any ());
+  if (result.count () > 1)
+    {
+      dw_class ret = this->ambiguous_class (form, attribute, result);
+      assert (ret < max_dw_class);
+      assert (result[ret]);
+      return ret;
+    }
+  else
+    return static_cast<dw_class> (ffsl (result.to_ulong ()));
 }
 
 form_width_t
@@ -161,6 +170,17 @@ namespace
     {
       return lookfor (attribute_name, &dwarf_version::get_attribute);
     }
+
+    dw_class
+    ambiguous_class (form const *form,
+                    attribute const *attribute,
+                    dw_class_set const &candidates) const
+    {
+      dw_class ret = _m_extension->ambiguous_class (form, attribute, candidates);
+      if (ret == max_dw_class)
+       ret = _m_source->ambiguous_class (form, attribute, candidates);
+      return ret;
+    }
   };
 }
 
index 520fa80ff52792be69bab342d457c1d3f6580fea..3868df82e67dbf4b7f1999712fc82412fdcf269d 100644 (file)
@@ -110,12 +110,6 @@ public:
     return _m_classes;
   }
 
-  /// Answer a class of form given attribute as a context.  This
-  /// assumes that the result is exactly one class.  You must validate
-  /// the form via form_allowed before calling this.  If more than two
-  /// classes match, the form and attribute tables are ill-designed.
-  dw_class cls (attribute const *attribute) const;
-
   /// Return width of data stored with given form.  CU may be NULL if
   /// you are sure that the form size doesn't depend on bitness of
   /// address_size or offset_size.
@@ -170,6 +164,17 @@ public:
   /// for unknown attributes;
   virtual attribute const *get_attribute (int attribute_name) const = 0;
 
+  /// If more than one class ends up as a candidate after the request
+  /// to form_class, this function is called to resolve the ambiguity.
+  virtual dw_class
+  ambiguous_class (__attribute__ ((unused)) form const *form,
+                  __attribute__ ((unused)) attribute const *attribute,
+                  __attribute__ ((unused)) dw_class_set const &candidates)
+    const
+  {
+    return max_dw_class; // = we don't know.  This will assert back in caller.
+  }
+
   /// Shortcut for get_form (form_name) != NULL.
   bool form_allowed (int form_name) const;
 
@@ -177,6 +182,15 @@ public:
   /// allowed to have given form.
   bool form_allowed (int attribute_name, int form_name) const;
 
+  /// Answer a class of FORM given ATTRIBUTE as a context.  If there's
+  /// exactly one candidate class, that's the one answered.  If
+  /// there's more, ambiguous_class is called to resolve the
+  /// ambiguity.  If there's no candidate, then the request is
+  /// invalid, you must validate the form via form_allowed before
+  /// calling this.
+  dw_class form_class (form const *form, attribute const *attribute) const;
+
+
   /// Return dwarf_version object for given DWARF version.
   static dwarf_version const *get (unsigned version)
     __attribute__ ((pure));