From: Petr Machata Date: Thu, 7 Oct 2010 15:46:58 +0000 (+0200) Subject: dwarflint: Add dwarf_version::form_class, ~::ambiguous_class, drop form::cls X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=df9af030bf557bec7da5ebba017ba7e10f9b68c0;p=thirdparty%2Felfutils.git dwarflint: Add dwarf_version::form_class, ~::ambiguous_class, drop form::cls - And use that in dwarf_3 to properly support DW_AT_data_member_location --- diff --git a/dwarflint/dwarf_3.cc b/dwarflint/dwarf_3.cc index 3afb3ca58..64713c5b8 100644 --- a/dwarflint/dwarf_3.cc +++ b/dwarflint/dwarf_3.cc @@ -27,6 +27,7 @@ #include "dwarf_2.hh" #include "dwarf_3.hh" #include "../libdw/dwarf.h" +#include 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; + } }; } diff --git a/dwarflint/dwarf_version.cc b/dwarflint/dwarf_version.cc index bab5a7098..a5f3371f9 100644 --- a/dwarflint/dwarf_version.cc +++ b/dwarflint/dwarf_version.cc @@ -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 (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 (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; + } }; } diff --git a/dwarflint/dwarf_version.hh b/dwarflint/dwarf_version.hh index 520fa80ff..3868df82e 100644 --- a/dwarflint/dwarf_version.hh +++ b/dwarflint/dwarf_version.hh @@ -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));