mirror of
git://sourceware.org/git/libabigail.git
synced 2025-02-23 09:16:57 +00:00
dwarf-reader: Support indirectly referenced subrange_type DIEs
This is about supporting an Ada-induced DWARF construct related to ranged types. To reproduce the issue this patch originated from, you can type: $ fedabipkgdiff --self-compare -a --from fc37 gprbuild From that gprbuild package from fc37, consider this subrange_type DIE coming from the debuginfo file prtests/gprbuild-2020-11.fc37.aarch64: 1 [ 3c10d] subrange_type abbrev: 34 2 type (ref_addr) [ 6191e] 3 lower_bound (sdata) 2 4 upper_bound (ref_udata) [ 3c0eb] At line 4, look at how the DW_AT_upper_bound attribute is a reference to another DIE, instead of being a (signed) constant value, like the DW_AT_lower_bound attribute at line 3. The referenced DIE is at offset 0x3c0eb. How do we get the actual value of the upper_bound of that subrange type? To answer that question, let's look at the DIE, at offset 0x3c0eb that is referenced by the DW_AT_upper_bound attribute at line 4: 1 [ 3c0eb] member abbrev: 87 2 name (strp) "last" 3 decl_file (data1) a-coinve.ads (35) 4 decl_line (data2) 415 5 decl_column (data1) 24 6 type (ref_udata) [ 3c0f7] It's a data member which type is referenced at line 6. Let's look at that type, which offset is 0x3c0f7: 1 [ 3c0f7] subrange_type abbrev: 122 2 upper_bound (sdata) 99999999 3 name (strp) "gpr__names__name_vectors__T449bXn" 4 type (ref_addr) [ 6191e] 5 artificial (flag_present) yes That type is a DW_TAG_subrange_type and its DW_AT_upper_bound value is a constant. Finally. Actually, the value of DW_AT_upper_bound of this DIE at offset 0x3c0f7 is the value of the DW_AT_upper_bound of the subrange_type DIE at offset 0x3c10d that we were initially looking for. The DIE at 0x3c0f7 is said to be indirectly referenced by the DIE at 0x3c10d, through its DW_AT_upper_bound attribute. This patch supports retrieving the value of the DW_AT_upper_bound of 0x3c10d through the 0x3c0f7 DIE that it indirectly references. The package gprbuild from fc37 now passes self comparison with this patch. * src/abg-dwarf-reader.cc (subrange_die_indirect_bound_value) (subrange_die_indirectly_references_subrange_die): Define new static function. (build_subrange_type): If the value of DW_AT_upper_bound is not a constant, try to consider it as an indirect reference to a DW_TAG_subrange_type DIE, whose DW_AT_upper_bound might carry the constant value that we are looking for. Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
parent
8180e4a0e7
commit
ff8cba872e
@ -523,6 +523,16 @@ die_die_attribute(const Dwarf_Die* die,
|
||||
Dwarf_Die& result,
|
||||
bool recursively = true);
|
||||
|
||||
static bool
|
||||
subrange_die_indirect_bound_value(const Dwarf_Die *die,
|
||||
unsigned attr_name,
|
||||
array_type_def::subrange_type::bound_value& v,
|
||||
bool& is_signed);
|
||||
|
||||
static bool
|
||||
subrange_die_indirectly_references_subrange_die(const Dwarf_Die *die,
|
||||
unsigned attr_name,
|
||||
Dwarf_Die& referenced_subrange);
|
||||
static string
|
||||
get_internal_anonymous_die_prefix_name(const Dwarf_Die *die);
|
||||
|
||||
@ -6199,6 +6209,110 @@ die_die_attribute(const Dwarf_Die* die,
|
||||
return dwarf_formref_die(&attr, &result);
|
||||
}
|
||||
|
||||
/// Test if a subrange DIE indirectly references another subrange DIE
|
||||
/// through a given attribute.
|
||||
///
|
||||
/// A DW_TAG_subrange_type DIE can have its DW_AT_{lower,upper}_bound
|
||||
/// attribute be a reference to either a data member or a variable
|
||||
/// which type is itself a DW_TAG_subrange_type. This latter subrange
|
||||
/// DIE is said to be "indirectly referenced" by the former subrange
|
||||
/// DIE. In that case, the DW_AT_{lower,upper}_bound of the latter is
|
||||
/// the value we want for the DW_AT_upper_bound of the former.
|
||||
///
|
||||
/// This function tests if the former subrange DIE does indirectly
|
||||
/// reference another subrange DIE through a given attribute (not
|
||||
/// necessarily DW_AT_upper_bound).
|
||||
///
|
||||
/// @param die the DIE to consider. Note that It must be a
|
||||
/// DW_TAG_subrange_type.
|
||||
///
|
||||
/// @param attr_name the name of the attribute to look through for the
|
||||
/// indirectly referenced subrange DIE.
|
||||
///
|
||||
/// @param referenced_subrange if the function returns true, then the
|
||||
/// argument of this parameter is set to the indirectly referenced
|
||||
/// DW_TAG_subrange_type DIE.
|
||||
///
|
||||
/// @return true iff @p DIE indirectly references a subrange DIE
|
||||
/// through the attribute @p attr_name.
|
||||
static bool
|
||||
subrange_die_indirectly_references_subrange_die(const Dwarf_Die *die,
|
||||
unsigned attr_name,
|
||||
Dwarf_Die& referenced_subrange)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (dwarf_tag(const_cast<Dwarf_Die*>(die)) != DW_TAG_subrange_type)
|
||||
return result;
|
||||
|
||||
Dwarf_Die referenced_die;
|
||||
if (die_die_attribute(die, attr_name, referenced_die))
|
||||
{
|
||||
unsigned tag = dwarf_tag(&referenced_die);
|
||||
if ( tag == DW_TAG_member || tag == DW_TAG_variable)
|
||||
{
|
||||
Dwarf_Die type_die;
|
||||
if (die_die_attribute(&referenced_die, DW_AT_type, type_die))
|
||||
{
|
||||
tag = dwarf_tag(&type_die);
|
||||
if (tag == DW_TAG_subrange_type)
|
||||
{
|
||||
memcpy(&referenced_subrange, &type_die, sizeof(type_die));
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Return the bound value of subrange die by looking at an indirectly
|
||||
/// referenced subrange DIE.
|
||||
///
|
||||
/// A DW_TAG_subrange_type DIE can have its DW_AT_{lower,upper}_bound
|
||||
/// attribute be a reference to either a data member or a variable
|
||||
/// which type is itself a DW_TAG_subrange_type. This latter subrange
|
||||
/// DIE is said to be "indirectly referenced" by the former subrange
|
||||
/// DIE. In that case, the DW_AT_{lower,upper}_bound of the latter is
|
||||
/// the value we want for the DW_AT_{lower,upper}_bound of the former.
|
||||
///
|
||||
/// This function gets the DW_AT_{lower,upper}_bound value of a
|
||||
/// subrange type by looking at the DW_AT_{lower,upper}_bound value of
|
||||
/// the indirectly referenced subrange type, if it exists.
|
||||
///
|
||||
/// @param die the subrange DIE to consider.
|
||||
///
|
||||
/// @param attr_name the name of the attribute to consider, typically,
|
||||
/// DW_AT_{lower,upper}_bound.
|
||||
///
|
||||
/// @param v the found value, iff this function returned true.
|
||||
///
|
||||
/// @param is_signed, this is set to true if @p v is signed. This
|
||||
/// parameter is set at all only if the function returns true.
|
||||
///
|
||||
/// @return true iff the DW_AT_{lower,upper}_bound was found on the
|
||||
/// indirectly referenced subrange type.
|
||||
static bool
|
||||
subrange_die_indirect_bound_value(const Dwarf_Die *die,
|
||||
unsigned attr_name,
|
||||
array_type_def::subrange_type::bound_value& v,
|
||||
bool& is_signed)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (dwarf_tag(const_cast<Dwarf_Die*>(die)) != DW_TAG_subrange_type)
|
||||
return result;
|
||||
|
||||
Dwarf_Die subrange_die;
|
||||
if (subrange_die_indirectly_references_subrange_die(die, attr_name,
|
||||
subrange_die))
|
||||
{
|
||||
if (die_constant_attribute(&subrange_die, attr_name, is_signed, v))
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Read and return an addresss class attribute from a given DIE.
|
||||
///
|
||||
/// @param die the DIE to consider.
|
||||
@ -14162,8 +14276,15 @@ build_subrange_type(reader& rdr,
|
||||
// So let's look for DW_AT_lower_bound first.
|
||||
die_constant_attribute(die, DW_AT_lower_bound, is_signed, lower_bound);
|
||||
|
||||
bool found_upper_bound = die_constant_attribute(die, DW_AT_upper_bound,
|
||||
is_signed, upper_bound);
|
||||
if (!found_upper_bound)
|
||||
found_upper_bound = subrange_die_indirect_bound_value(die,
|
||||
DW_AT_upper_bound,
|
||||
upper_bound,
|
||||
is_signed);
|
||||
// Then, DW_AT_upper_bound.
|
||||
if (!die_constant_attribute(die, DW_AT_upper_bound, is_signed, upper_bound))
|
||||
if (!found_upper_bound)
|
||||
{
|
||||
// The DWARF 4 spec says, in [5.11 Subrange Type
|
||||
// Entries]:
|
||||
|
Loading…
Reference in New Issue
Block a user