Handle dynamic DW_AT_data_bit_offset

In Ada, a field can have a dynamic bit offset in its enclosing record.

In DWARF 3, this was handled using a dynamic
DW_AT_data_member_location, combined with a DW_AT_bit_offset -- this
combination worked out ok because in practice GNAT only needs a
dynamic byte offset with a fixed offset within the byte.

However, this approach was deprecated in DWARF 4 and then removed in
DWARF 5.  No replacement approach was given, meaning that in strict
mode there is no way to express this.

This is a DWARF bug, see

    https://dwarfstd.org/issues/250501.1.html

In a discussion on the DWARF mailing list, a couple people mentioned
that compilers could use the obvious extension of a dynamic
DW_AT_data_bit_offset.  I've implemented this for LLVM:

    https://github.com/llvm/llvm-project/pull/141106

In preparation for that landing, this patch implements support for
this construct in gdb.

New in v2: renamed some constants and added a helper method, per
Simon's review.

New in v3: more renamings.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
This commit is contained in:
Tom Tromey
2025-05-20 10:45:07 -06:00
parent fcfd8a4f23
commit 692252c4b0
7 changed files with 162 additions and 18 deletions

View File

@@ -480,7 +480,10 @@ enum field_loc_kind
FIELD_LOC_KIND_ENUMVAL, /**< enumval */
FIELD_LOC_KIND_PHYSADDR, /**< physaddr */
FIELD_LOC_KIND_PHYSNAME, /**< physname */
FIELD_LOC_KIND_DWARF_BLOCK /**< dwarf_block */
/* A DWARF block that computes the address of the field. */
FIELD_LOC_KIND_DWARF_BLOCK_ADDR, /**< dwarf_block */
/* A DWARF block that computes the bit offset of the field. */
FIELD_LOC_KIND_DWARF_BLOCK_BITPOS,
};
/* * A discriminant to determine which field in the
@@ -616,6 +619,13 @@ struct field
return m_loc_kind;
}
/* Return true if this location has either "DWARF block" kind. */
bool loc_is_dwarf_block () const
{
return (m_loc_kind == FIELD_LOC_KIND_DWARF_BLOCK_ADDR
|| m_loc_kind == FIELD_LOC_KIND_DWARF_BLOCK_BITPOS);
}
LONGEST loc_bitpos () const
{
gdb_assert (m_loc_kind == FIELD_LOC_KIND_BITPOS);
@@ -666,13 +676,19 @@ struct field
dwarf2_locexpr_baton *loc_dwarf_block () const
{
gdb_assert (m_loc_kind == FIELD_LOC_KIND_DWARF_BLOCK);
gdb_assert (loc_is_dwarf_block ());
return m_loc.dwarf_block;
}
void set_loc_dwarf_block (dwarf2_locexpr_baton *dwarf_block)
void set_loc_dwarf_block_addr (dwarf2_locexpr_baton *dwarf_block)
{
m_loc_kind = FIELD_LOC_KIND_DWARF_BLOCK;
m_loc_kind = FIELD_LOC_KIND_DWARF_BLOCK_ADDR;
m_loc.dwarf_block = dwarf_block;
}
void set_loc_dwarf_block_bitpos (dwarf2_locexpr_baton *dwarf_block)
{
m_loc_kind = FIELD_LOC_KIND_DWARF_BLOCK_BITPOS;
m_loc.dwarf_block = dwarf_block;
}