>
> The first part of this is straightforward. The DWARF for Base will
> contain a member for the vtable pointer, and that plus knowledge of
> how the ABI lays out vtables allows the debugger to effectively do a
> dynamic_cast<void*> to obtain a pointer to the most derived object.
> From there the vtable address is compared against the ELF symbol table
> to find the mangled name of the vtable symbol.
>

This made me do a bit of research...

The artificial member for the vtable pointer appears to be a DWARF
extension requested as far back as 2003 and implemented in 2009:

   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=11208

But I can't find any relevant discussion on the DWARF mailing lists, until
a question arose about that very member in 2022:

   https://dwarfstd.org/pipermail/dwarf-discuss/2022-February/002127.html

It seems to me that, given the apparent need for this information in the
DWARF info, we should have addressed it in DWARF by now. I suspect the
DWARF committee's position was (or would have been) that the ABI tells you
how to find the vtable so it doesn't need to be explicitly recorded in the
DWARF info. But if both GCC and LLVM have decided it's useful enough (and
there's discussion about that point in the original PR that 11208 spun off
from), then we should discuss it. Otherwise, we risk having different
toolchains adopt different solutions. (GCC and LLVM appear to have avoided
that through careful consideration of what the other project was doing.)
The argument in PR 11208 is that it's /legal/ in DWARF to do this, so no
new DWARF feature was requested.

The request in PR 11208 was for three things:

> 1) I'd like to be able to locate the vtable pointer in the class
>    structure so that the debugger knows that the hole in the apparent
>    layout is not padding.
>
> 2) I'd like to know the type of the target of the vtable pointer, so
>    that if the user asks to see it they see something sane.
>
> 3) I'd like to be able to find a specific virtual functions entry in
>    the vtable, however I believe that this information will be best
>    expressed as a property of the function, not directly of the class
>    or vtable. DWARF3 has the DW_AT_vtable_elem_location attribute for
>    precisely this information. gcc should generate that too.
>
>    Quoting the DWARF spec again :-
>      An entry for a virtual function also has a
>      DW_AT_vtable_elem_location attribute whose value contains a
>      location description yielding the address of the slot for the
>      function within the virtual function table for the enclosing
>      class. The address of an object of the enclosing type is pushed
>      onto the expression stack before the location description is
>      evaluated.

Point #1 is satisfied with an artificial member whose data_member_location
is the offset of the vtable pointer.

I'm not clear how Point #2 was addressed.

Point #3 was addressed via the vtable_elem_location attribute.

Looking at the DWARF generated by GCC (and I'm guessing LLVM does the
same), I see vtable_elem_location attributes that look like this:

    <1b8>   DW_AT_vtable_elem_location: 2 byte block: 10 0 (DW_OP_constu: 0)

This is not correct DWARF! It's supposed to be a location description, and
this is merely a DWARF expression that evaluates to an offset relative to
the vtable pointer. The description of the attribute says that address of
an object of the enclosing type is pushed onto the expression stack, so
there really ought to be a DW_OP_deref to get the vtable pointer on the
stack, followed by the DW_OP_constu and DW_OP_add.

Now if we compare this to DW_AT_data_member_location, we see that one valid
form for that attribute is an integer constant providing the offset of the
data member. But even there, if the attribute has a location expression, it
should compute an actual address, not just deliver the offset.

It would seem an obvious and useful extension to DWARF to allow
DW_AT_vtable_elem_location to take a constant class form that provides the
offset relative to the start of the vtable, so an acceptable form of the
attribute might be:

    <1b8>   DW_AT_vtable_elem_location: 0   # (using a constant class form)

There's still the question of what do we do about the form GCC is already
emitting (and has been emitting since 2009)? Make it legal? Let it slide
and ask the compilers to fix it?

Getting back to the original request, do we need an issue to provide an
officially-blessed DWARF way to find the vtable pointer? The current
approach seems rather hacky, especially with respect to attaching a special
meaning to the DW_AT_name attribute. Perhaps a DW_AT_vtable_ptr_location
attribute on the class? And maybe a DW_OP_push_vtable_location operator?


> Then things begin to get hairy, the debugger demangles the mangled
> name that exists in the ELF symbol table, chops off the "vtable for "
> prefix on the demangled name, and searches for the type by name in the
> DWARF. If it finds the type, it adjusts the type of the value and
> prints it accordingly. But this text based matching doesn't always
> work. There are no mangled names for types so the debugger's
> demangling has to match the compiler's output character for character.
>

Yes, things are really hairy here! It seems like you'd want some
DWARF-based RTTI that could be as simple as a DW_AT_vtable_location on each
class? That should let you map a vtable pointer onto the DIE for the class
of the object you have. (Although it may be expensive, since building that
lookup table would require parsing the whole DIE tree.) The LLVM discussion
Michael pointed to does seem relevant.


> Perhaps these are merely quality of implementation issues and belong
> on the respective bug trackers, however, better representations are
> possible. Rustc, for example, does not rely on the ELF symbol table
> and demangled string matching. It emits a global variable in the DWARF
> whose location is the address of the vtable. That variable has a
> DW_AT_type pointing to a DW_TAG_class_type that describes the layout
> of the vtable, and that type has a DW_AT_containing_type that points
> to the type making use of that vtable.
>

Is this an artificial global variable? How would that help vs. just
recording the address of the vtable as an attribute of the class?

-cary
-- 
Dwarf-discuss mailing list
Dwarf-discuss@lists.dwarfstd.org
https://lists.dwarfstd.org/mailman/listinfo/dwarf-discuss

Reply via email to