On Fri, Feb 27, 2015 at 10:04 AM, Greg Clayton <clayb...@gmail.com> wrote:
> > > On Feb 27, 2015, at 9:40 AM, David Blaikie <dblai...@gmail.com> wrote: > > > > > > > > On Fri, Feb 27, 2015 at 9:31 AM, Greg Clayton <clayb...@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 <ema...@freebsd.org> wrote: > > > > > > On 26 February 2015 at 17:28, Adrian Prantl <apra...@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@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev