Sounds like this is what
https://github.com/llvm/llvm-project/pull/130255 is trying to achieve?
If we could simplify that part of LLDB that'd be great!

On Wed, 23 Apr 2025 at 16:32, Kyle Huey via Dwarf-discuss
<dwarf-discuss@lists.dwarfstd.org> wrote:
>
> Consider the following C++ program
>
> #include <stdio.h>
>
> class Base {
> public:
>   virtual const char* method1() = 0;
>   void method2() {
>     printf("%s\n", method1());
>   }
> };
>
> class DerivedOne : public Base {
>   virtual const char* method1() override {
>     return "DerivedOne";
>   }
> };
>
> template<typename T>
> class DerivedTwo : public Base {
> public:
>   DerivedTwo(T t) : t(t) {}
> private:
>   virtual const char* method1() override {
>     return t;
>   }
>   T t;
> };
>
> template<typename T>
> class DerivedThree : public Base {
> public:
>   DerivedThree(T t) : t(t) {}
> private:
>   virtual const char* method1() override {
>     return t();
>   }
>   T t;
> };
>
> int main() {
>   DerivedOne d1;
>   DerivedTwo d2("DerivedTwo");
>   DerivedThree d3([]() {
>     return "DerivedThree";
>   });
>   d1.method2();
>   d2.method2();
>   d3.method2();
>   return 0;
> }
>
> If a debugger stops at method1, the DW_TAG_formal_parameter will tell
> the debugger the type of `this` is Base. Downcasting to the derived
> type is very useful for the programmer though, so both gdb and lldb
> contain a feature to downcast based on the vtable pointer (the "print
> object" and the "target.prefer-dynamic" settings in the respective
> debuggers).
>
> 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.
>
> 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.
>
> In the example program I've provided, when using the respective
> compilers, gdb can successfully downcast DerivedOne and DerivedThree
> but not DerivedTwo. gdb fails because gcc emits the DW_TAG_class_type
> with a DW_AT_name "DerivedTwo<main()::<lambda()> >" but libiberty
> demangles the vtable symbol to "vtable for
> DerivedTwo<main::{lambda()#1}>" and those do not match. lldb can only
> successfully downcast DerivedOne. lldb appears to not handle classes
> with template parameters correctly at all. And even if all of that
> were fixed, libiberty and llvm disagree about how to demangle the
> symbol for DerivedTwo's vtable, so the two ecosystems would not be
> interoperable.
>
> 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.
>
> Any thoughts?
>
> - Kyle
> --
> Dwarf-discuss mailing list
> Dwarf-discuss@lists.dwarfstd.org
> https://lists.dwarfstd.org/mailman/listinfo/dwarf-discuss
-- 
Dwarf-discuss mailing list
Dwarf-discuss@lists.dwarfstd.org
https://lists.dwarfstd.org/mailman/listinfo/dwarf-discuss

Reply via email to