Issue 250506.2: Improve Support for Downcasting Objects

Author: Cary Coutant
Champion: Cary Coutant
Date submitted: 2025-05-06
Date revised: 2025-11-20
Date closed: 2026-01-05
Type: Enhancement
Status: Accepted
DWARF version: 6

Comparing original with 2025-11-20. [ View this version ] [ Return to the latest version ]

This is the second part of a three-part proposal.
The first part, [250506.1][250506.1], proposes a standard mechanism for locating
the virtual function table (vtable) given an object of a
polymorphic class.
This second part proposes a standard mechanism
for identifying the most-derived class of an object,
given its vtable location, in order to support downcasting
of pointers while debugging.
The third part, [250506.3][250506.3], proposes a fix to the
`DW_AT_vtable_elem_location` attribute,
which appears to be incorrectly implemented in compilers today.

## Background

See [250506.1][250506.1] for the full background and history.

## Problem

The second request in [PR 7081][pr7081] was for a way to
associate vtables with their class definitions, to make it
easier to downcast pointers from the base class to the
most-derived class, based on the vtable pointer. The clang
and Rust approaches are similar, but not exactly the same,
and the Concurrent approach puts a relocatable address of
the vtable in the type DIE.

Adding an attribute directly to the type DIE that points to
the vtable has the disadvantage that type de-duplication might
discard all but one of several copies of a vtable, if multiple
copies of the vtable remain after linking.

We also desire a fast lookup mechanism where a vtable address
can be translated into the corresponding type DIE without
requiring the consumer to parse all the DWARF info at once.

## Proposal

To make the association between a vtable and a type DIE,
we add a new DWARF tag for a vtable object, `DW_TAG_vtable`,
whose `DW_AT_location` provides the address of the vtable,
and whose (new) `DW_AT_vtable_type` attribute points to the
type DIE corresponding to the vtable.
Additional attributes may provide additional details about
the vtable.

To provide for faster lookup of vtable addresses, we add a
To provide for faster lookup of vtable addresses, we add
`DW_AT_vtable_ranges` attribute to the compilation unit
DIEs.
vtable ranges to the `DW_AT_ranges` attribute of the
compilation unit DIE.

In Section 2.1, "The Debugging Information Entry," add
`DW_TAG_vtable` to Table 2.1.

In Section 2.2, "Attribute Types," add two rows to Table 2.2:
In Section 2.2, "Attribute Types," add a row to Table 2.2:

> | Attribute | Usage |
> | --------- | ----- |
> | `DW_AT_vtable_type` | Type corresponding to a vtable |
> | `DW_AT_vtable_ranges` | Ranges of vtable addresses |

In Section 3.1.1, "Full and Partial Compilation Unit Entries,"
add a numbered item:
In Section 2.16, "Code Addresses, Ranges and Base Addresses,"
change the first paragraph as follows:

> 18\. A `DW_AT_vtable_ranges` attribute, whose value is of
> class rnglist, which provides a range of addresses containing
> vtables defined by this compilation unit.
> Any debugging information entry describing an entity that
> has a machine code address or range of machine code
> addresses <ins>or virtual tables (see Section 4.4)</ins>,
> which includes compilation units, module initialization,
> subroutines, lexical blocks, try/catch blocks (see Section
> 4.8 on page 108), labels and the like, may have

In Section 3.1.2, "Skeleton Compilation Unit Entries,"
In Section 4.1.2 [OLD 3.1.2], "Skeleton Compilation Unit Entries,"
add a numbered item:
change item 2 as follows:

> 9\. A `DW_AT_vtable_ranges` attribute.
> 2\. Either a `DW_AT_low_pc` and `DW_AT_high_pc` pair of
> attributes or a `DW_AT_ranges` attribute whose values encode
> the contiguous or non-contiguous address ranges,
> respectively, of the machine instructions
> <ins>and the virtual tables</ins>
> generated for the compilation unit (see Section 2.16 on page 34).

In Chapter 4, "Data Object and Object List Entries," add a new section:
In Chapter 5 [OLD 4], "Data Object and Object List Entries," add a new section:

> 4.4 Virtual Function Table (vtable) Entries
> 5.4 Virtual Function Table (vtable) Entries
> 
> Virtual function tables (vtables) are represented by
> debugging information entries with the tag `DW_TAG_vtable`.
> It may have the following attributes:
> 
> 1. A `DW_AT_location` attribute, whose value describes
> the location of the vtable.
> 
> 2. A `DW_AT_vtable_type` attribute, which is a reference
> to the debugging information entry for the associated
> type.
> 
> 3. A `DW_AT_artificial` attribute, which is a flag
> indicating that the vtable entry represents an object
> created by the compiler that does not correspond directly to
> source code.
> 
> *Virtual Function Table entries allow a debugger to
> associate vtables with the corresponding class type, in
> order to downcast a pointer whose type is
> "pointer-to-base-class" to a pointer with type
> "pointer-to-derived-class," using the vtable pointer of
> the object.*

In Section 7.5.3, "Abbreviations Tables," add a row to Table 7.3:
In Section 8.5.3 [OLD 7.5.3], "Abbreviations Tables," add a row to Table 8.3:

> | TAG name | Value |
> | -------- | ----- |
> | `DW_TAG_vtable` | TBD |

In Section 7.5.4, "Attribute Encodings," add two rows to Table 7.5:
In Section 8.5.4 [OLD 7.5.4], "Attribute Encodings," add a row to Table 8.5:

> | Attribute name | Value | Classes |
> | -------------- | ----- | ------- |
> | `DW_AT_vtable_type` | TBD | reference |
> | `DW_AT_vtable_ranges` | TBD | rnglist |

In Appendix A, "Attribute by Tag," add a row for `DW_TAG_vtable`:

> | TAG name | Applicable attributes |
> | -------- | --------------------- |
> | `DW_TAG_vtable` | `DW_AT_artificial` <br> `DW_AT_location` <br> `DW_AT_vtable_type` |

In the same table, add `DW_AT_vtable_ranges` to the row for
`DW_TAG_compile_unit`.

## Optional Variations

- If useful, we could add additional attributes to the
`DW_TAG_vtable` DIE to identify construction/destruction
vtables, and A-in-B vtables.

- Instead of `DW_AT_vtable_ranges`, we could require
including the vtable ranges in the `DW_AT_ranges` attribute
of a CU.

[230524.1]: https://dwarfstd.org/issues/230524.1.html
[250506.1]: https://dwarfstd.org/issues/250506.1.html
[250506.2]: https://dwarfstd.org/issues/250506.2.html
[250506.3]: https://dwarfstd.org/issues/250506.3.html
[huey2025]: https://lists.dwarfstd.org/pipermail/dwarf-discuss/2025-April/002671.html
[pr11208]: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=11208
[louzon2022]: https://lists.dwarfstd.org/pipermail/dwarf-discuss/2022-February/002127.html
[pr7081]: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=7081
[clang130255]: https://github.com/llvm/llvm-project/pull/130255
[rust125126]: https://github.com/rust-lang/rust/issues/125126
[allen2025]: https://lists.dwarfstd.org/pipermail/dwarf-discuss/2025-May/002690.html

---

2025-11-20: [Revised][diff1] to put vtable ranges in the
`DW_AT_ranges` attribute instead of a new attribute;
updated chapter and section numbers.

2025-12-08: Accepted.