Re: gdb 8.x - g++ 7.x compatibility

Daniel Berlin
2018-02-07T17:04:09Z

On Wed, Feb 7, 2018 at 5:44 AM, Simon Marchi <simon.marchi@polymtl.ca>
wrote:

> On 2018-02-07 02:21, Daniel Berlin wrote:
>
>> As the person who, eons ago, wrote a bunch of the the GDB code for this
>> C++
>> ABI support, and as someone who helped with DWARF support in both GDB and
>> GCC, let me try to propose a useful path forward (in the hopes that
>> someone
>> will say "that's horrible, do it this <clearly better way> instead")
>>
>> Here are the constraints i believe we are working with.
>>
>> 1. GDB should work with multiple DWARF producers and multiple C++
>> compilers
>> implementing the C++ ABI
>> 2. There is no canonical demangled format for the C++ ABI
>> 3. There is no canoncial target demangler you can say everyone should use
>> (and even if there was, you don't want to avoid debugging working because
>> someone chose not to)
>> 4. You don't want to slow down GDB if you can avoid it
>> 5. Despite them all implementation the same ABI, it's still possible to
>> distinguish the producers by the producer/compiler in the dwarf info.
>>
>> Given all that:
>>
>> GDB has ABI hooks that tell it what to do for various C++ ABIs. This is
>> how
>> it knows to call the right demangler for gcc v3's abi vs gcc v2's abi. and
>> handle various differences between them.
>>
>> See gdb/cp-abi.h
>>
>> The IMHO, obvious thing to do here is: Handle the resulting demangler
>> differences with 1 or more new C++ ABI hooks.
>> Or, introduce C++ debuginfo producer hooks that the C++ ABI hooks use if
>> folks want it to be separate.
>>
>> Once the producer is detected, fill in the hooks with a set of functions
>> that does the right thing.
>>
>> I imagine this would also clean up a bundle of hacks in various parts of
>> gdb trying to handle these differences anyway (which is where a lot of the
>> multiple symbol lookups/etc that are often slow come from.
>> If we just detected and said "this is gcc 6, it behaves like this", we
>> wouldn't need to do that)
>>
>> In case you are worried, you will discover this is how a bunch of stuff is
>> done and already contains a ball of hacks.
>>
>> Using hooks would be, IMHO, a significant improvement.
>>
>
> Hi Daniel,
>
> Thanks for chiming in.
>
> This addresses the issue of how to do good software design in GDB to
> support different producers cleanly, but I think we have some issues even
> before that, like how to support g++ 7.3 and up.

They are, IMHO, the same.

> I'll try to summarize the issue quickly. It's now possible to end up with
> two templated classes with the same name that differ only by the signedness
> of their non-type template parameter.

Yup.

> One is Foo<int N> and the other is Foo<unsigned int N> (the 10 is
> unsigned). Until 7.3, g++ would generate names like Foo<10> for the former
> and names like Foo<10u> for the later (in the DW_AT_name attribute of the
> classes' DIEs). Since 7.3, it produces Foo<10> for both.
>
> When GDB wants to know the run time type of an object, it fetches the
> pointer to its vtable, does a symbol lookup to get the linkage name and
> demangles it,

Yes, this is code i wrote :)

> which gives a string like "vtable for Foo<10>" or "vtable for Foo<10u>".
> It strips the "vtable for " and uses the remainder to do a type lookup.
> Since g++ 7.3, you can see that doing a type lookup for Foo<10> may find
> the wrong type,

Certainly if you can't distinguish the types you are screwed, but this is
not the only way to find this type. This was in fact, the first hack i
thought up to make it work because the ABI was not entirely fully formed at
the time, and the debug info did not have fully qualified names.

Here is a different way that should produce more consistent results.

Find the linker symbol
look up the symbol in the dwarf info by address.
This will give you the vtable type debug info.
Look at the name attribute of the debug info, which should already be
demangled.

Strip the "vtable for" from that.
Look that up.

This avoids the problem of the demangler gdb is using getting a different
name than the producer used. It also should always give you the right one.
If the producer calls the type "vtable fo Foo<2u>" here and "Foo<2>"
elsewhere, yes, that's a bug. It should be consistent.

If there are multiple types named Foo<2u>, DWARF needs to be extended to
allow a pointer from the vtable debug info to the class type debug info
(unless they already added one).
Then you would do *no* symbol lookups, you'd follow that pointer (gdb would
add it to the symbol_info structure)

> and doing a lookup for Foo<10u> won't find anything.
>

Correct. This stripping is a hook that does the stripping and lookup in
gnuv3_rtti_type.

That is not the only way yo to it.

>
> So the problem here is how to uniquely identify those two classes when we
> are doing this run-time type finding operation (and probably in other cases
> too).

>
>
> Simon
>