Issue 250506.2: Improve Support for Downcasting Objects
| Author: | Cary Coutant |
|---|---|
| Champion: | Cary Coutant |
| Date submitted: | 2025-05-06 |
| Date revised: | 2026-01-04 |
| Date closed: | 2026-01-05 |
| Type: | Enhancement |
| Status: | Accepted |
| DWARF version: | 6 |
Comparing 2025-11-20 with latest. [ 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
and whose (new) `DW_AT_vtable_for_type` attribute points to the
type DIE corresponding to the vtable.
The vtable object will be a direct child of the compilation unit DIE.
Additional attributes may provide additional details about the vtable. To provide for faster lookup of vtable addresses, we add 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 a row to Table 2.2: > | Attribute | Usage | > | --------- | ----- |
> | `DW_AT_vtable_type` | Type corresponding to a vtable |
> | `DW_AT_vtable_for_type` | Type corresponding to a vtable |
In Section 2.16, "Code Addresses, Ranges and Base Addresses," change the first paragraph as follows: > 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 4.1.1 [OLD 3.1.1], "Full and Partial Compilation Unit Entries," change paragraph 5 as follows: > A full or partial compilation unit entry must have 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 Section 4.1.2 [OLD 3.1.2], "Skeleton Compilation Unit Entries," change item 2 as follows: > 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 5 [OLD 4], "Data Object and Object List Entries," add a new section: > 5.4 Virtual Function Table (vtable) Entries > > Virtual function tables (vtables) are represented by
> debugging information entries with the tag `DW_TAG_vtable`.
> debugging information entries with the tag `DW_TAG_vtable`, > whose parent is a compilation unit entry.
> It may have the following attributes:
> A vtable entry 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
> 2. A `DW_AT_vtable_for_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 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 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_for_type` | TBD | reference |
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` |
> | `DW_TAG_vtable` | `DW_AT_artificial` <br> `DW_AT_location` <br> `DW_AT_vtable_for_type` |
## 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. [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.
2025-12-30: Reopened. [Revised][diff2] to note that vtable entries should be the children of a compilation unit DIE, and to update text in Section 4.1.1. 2026-01-04: Changed `DW_AT_vtable_type` to `DW_AT_vtable_for_type`. 2026-01-05: Accepted.