#include "dwarf_2.hh"
#include "dwarf_3.hh"
#include "../libdw/dwarf.h"
+#include <cassert>
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;
+ }
};
}
{}
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)
{}
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
{
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;
+ }
};
}
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.
/// 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;
/// 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));