[lldb-dev] [cfe-dev] clang CL breaks LLDB std::string printing

Vince Harron vharron at google.com
Fri Feb 27 12:32:09 PST 2015


> If you don't have debug info for that shared library (hence the
suggestion to install debug info for the standard library - there are
packages for it).

Not if you're using a random Android device from vendor foo.  =)

> I imagine at some point, the Googlers working on LLDB will ultimately
want/need to implement this to keep our debug info size improvements on
while being usable with LLDB, but I don't actually know their
plans/goals/tradeoffs.

It will be a long time before we get there.  Until then, I'd like to have
-fstandalone-debug default for all targets.  I also think it's unintuitive
to have different platforms silently behave differently for completely
cross platform concepts.

> also, we tend to build everything statically, as I understand it - so
shared library features aren't as valuable for our use cases

I'm working on tools for third-party (and Google) Android developers, who
have very similar priorities as independent Linux developers, e.g.
error-proof/easy-to-use is more important than smallest possible debug
symbols.

Sincerely,

Vince


On Fri, Feb 27, 2015 at 1:28 PM, David Blaikie <dblaikie at gmail.com> wrote:

>
>
> On Fri, Feb 27, 2015 at 10:04 AM, Greg Clayton <clayborg at gmail.com> wrote:
>
>>
>> > On Feb 27, 2015, at 9:40 AM, David Blaikie <dblaikie at gmail.com> wrote:
>> >
>> >
>> >
>> > On Fri, Feb 27, 2015 at 9:31 AM, Greg Clayton <clayborg at gmail.com>
>> wrote:
>> > I recommend telling the compiler to not do this using (set
>> -no-fstandalone-debug in OTHER_CFLAGS) if you want to debug with LLDB. If
>> you don't you can DWARF for the following code:
>> >
>> >
>> > class A : public B
>> > {
>> > };
>> >
>> > Where the compiler says "no one used 'B' so I am going to emit a
>> forward declaration for 'B'.
>> >
>> > That's not quite the logic used here. Certainly if you use A then
>> you've used B. B may be emitted as a declaration if we know that some other
>> CU will contain the definition (eg: using the vtable optimization - if B
>> has virtual functions, we'll only emit the definition of B where the vtable
>> goes (if B has a key function, this means the debug info definition of B
>> goes in exactly one place: where the definition of the key function
>> appears))
>>
>> Sure, then only if B has a vtable this will happen.
>>
>
> (or an explicit instantiation declaration (such as std::string) - or is
> only used in ways that don't require the complete type)
>
>
>>
>> >
>> > Then LLDB tries to make class 'A' in a clang AST context and then we
>> try to parse 'B' so we can have 'A' inherit from it and clang of course
>> would assert and kill LLDB (if we actually try to give clang a class 'B'
>> that is a forward declaration as a base class) so LLDB has to lie to keep
>> clang from asserting and just say that 'B' class that contains nothing.
>> >
>> > Shouldn't it go & find B in another file? The same way you would find
>> the definition of foo if one file contained "struct foo; foo *f;" and the
>> user executed the command "p f->bar"?
>>
>> LLDB is designed to parse each shared library individually so that we can
>> re-use shared libraries from between multiple runs. If liba.so doesn't
>> changed, we don't need to re-parse anything in liba.so or its debug info
>> file. If you recompile libb.so, we don't have any dependencies in liba.so
>> on types like 'B' from elsewhere otherwise the types passed out by each
>> shared library have dependencies and have to throw everything away when any
>> dependent shared library is loaded.
>>
>
> Ah, thanks for the architectural explanation - this is a detail I hadn't
> read about/understood before.
>
>
>> But in LLDB, when we have a process, _will_ find the real definition
>> elsewhere when displaying things to you for things that can legally be
>> forward declarations in sources (pointers and references). So we will have
>> a variable of type "A" from liba.so and we will be displaying it and if it
>> has an instance variable, whose type is "C *" and that 'C' is a forward
>> declaration, we will search and find "C" elsewhere (in libb.so) for display
>> purposed by switching over to using the type from 'libb.so'. But we can't
>> do this for things that can't be forward declarations in sources, like base
>> classes.
>>
>
> OK, so you switch contexts to find the type (knowing where it is - with
> some index, etc).
>
> It seems to me that to support this kind of optimized debug info with
> LLDB's architecture similar things could be done during AST building time -
> switching library context to find the definition elsewhere. The extra
> wrinkle being you'd want to keep track of the dependent libraries used in
> this case - and, yes, it'd come with some performance cost - if you had to
> reload the dependent library, you'd reload any libraries that depended upon
> it (or possibly only the specific types that were dependent)
>
> I mean that's up to you guys/whoever's working on the project if it's
> important - I get that Google's needs for small debug info are somewhat
> more dire than other projects, but even before I started on debug info it
> seemed like size was a continuous concern/priority - so I'm still somewhat
> surprised/confused by the apparent priorities here, but we have a flag &
> the choice is easy enough to make.
>
> I imagine at some point, the Googlers working on LLDB will ultimately
> want/need to implement this to keep our debug info size improvements on
> while being usable with LLDB, but I don't actually know their
> plans/goals/tradeoffs. (also, we tend to build everything statically, as I
> understand it - so shared library features aren't as valuable for our use
> cases)
>
> - David
>
>
>>
>> >
>> > The idea was that someone will certainly declare 'B' somewhere in your
>> current source base.
>> >
>> > It's more robust than that - the vtable optimization, assuming you
>> compile your whole program with debug info, is guaranteed by the C++
>> standard (odr use of the class means you have a definition of all the
>> virtual members /somewhere/ in your program).
>>
>> Yes, but this doesn't guarantee that this debug info is in the current
>> shared library or executable. So if the other shared library doesn't have
>> debug info, then you end up missing debug info. LLDB parses shared
>> libraries individually because it can have multiple debug sessions running
>> simultaneously, each using different combinations of shared libraries at
>> the same time. So we can't take type 'B' from libb.so and copy it into type
>> 'A' from liba.so because if libb.so changes and we restart a debug session,
>> we would have to throw away all type info (or maintain dependency lists).
>> Further we can't do it because process 123 might be still be using the old
>> version of libb.so while process 124 restarted and is using the new version.
>>
>> > GCC has been doing this optimization for a while now, Clang was doing
>> similar optimizations ("struct foo { }; foo *f;" - we'd only emit the
>> declaration of 'foo' since it was never dereferenced) for a while too - I
>> believe Eric implemented the first versions of that on a suggestion from
>> Chris Lattner, FWIW.
>>
>> Again, for places that can have forward declarations (for pointers and
>> references), this is quite OK. Our variable display logic will find the
>> right definition. It is just in the base class case where this falls down
>> for LLDB.
>> >
>> > This mostly holds true, but if you have a header file from a shared
>> library that has a C++ class that people might inherit from (like we do in
>> Darwin Kernel Extensions),
>> >
>> > If you don't have debug info for that shared library (hence the
>> suggestion to install debug info for the standard library - there are
>> packages for it). Granted I imagine it'll take some finagling to change the
>> Darwin Kernel Extensions build system to build a partial debug info package
>> (presumably you don't want to ship all the debug info for the
>> implementation of that library - for size and privacy reasons).
>>
>> We do have this issue and we won't be changing the default on MacOSX for
>> this very reason.
>>
>> The performance and memory benefits we get in LLDB from having each
>> shared library be independent are huge. Re-starting a debug session in
>> Xcode for the same program (rerunning) is instant as we have a global cache
>> of shared libraries that are all stand alone and have no dependencies. When
>> we still used GDB, every restart was a new delay as it loaded all shared
>> libraries and debug info for each run. Each debug session was a unique new
>> instance of GDB running in a separate process so that GDB could hack its
>> shared libraries up any way it chose to with no worries of dependencies
>> because there was only 1 debug session going on at a time. If a shared
>> library doesn't change in LLDB, we still have a live copy all pre-parsed
>> and ready to go in our global cache.
>>
>> >
>> > we end up with a class we use for debugging that isn't allowed to see
>> any ivars from "B", nor call any functions declared inside 'B' or any of
>> its subclasses (because we told clang 'B' has no contents when creating the
>> type in the clang AST. So we default to -no-fstandalone-debug for all of
>> Darwin to avoid this.
>> >
>> > Greg Clayton
>> >
>> > > On Feb 26, 2015, at 4:35 PM, Ed Maste <emaste at freebsd.org> wrote:
>> > >
>> > > On 26 February 2015 at 17:28, Adrian Prantl <aprantl at apple.com>
>> wrote:
>> > >>
>> > >>           The -fstandalone-debug option turns off these
>> optimizations.  This is useful when working with 3rd-party libraries that
>> don't come with
>> > >>           debug information.  This is the default on Darwin.  Note
>> that Clang will never emit type information for types that are not
>> referenced at
>> > >>           all by the program.
>> > >
>> > > Note that this is also the default on FreeBSD. This might be an
>> > > important point when comparing test results on FreeBSD and Linux since
>> > > they otherwise share a lot of attributes.
>> > >
>> > > -Ed
>> >
>> >
>>
>>
>
> _______________________________________________
> lldb-dev mailing list
> lldb-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
>
>


-- 

Vince Harron | Technical Lead Manager | vharron at google.com | 858-442-0868
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20150227/c2d83b21/attachment.html>


More information about the lldb-dev mailing list