[Lldb-commits] [PATCH] D13066: DWARFASTParserClang::CompleteTypeFromDWARF: Handle incomplete baseclass or child

Greg Clayton via lldb-commits lldb-commits at lists.llvm.org
Thu Sep 24 11:42:40 PDT 2015

clayborg added a comment.

Each shared library is an object that can be shared between multiple targets. We do not want to injecting types from another shared library into the static notion of what a type is within a shared library. Why? What if one target in lldb loads liba.so which has a forward declaration to "class Bar;", and this same target loads libb.so which contains a full definition for "Bar". Another target also loads liba.so, but it loads a different version of "libb.so" which has a newer more up to date version of "Bar" because you are doing a edit/compile/debug cycle. We can't take a full definition of "Bar" and place it into the debug info for liba.so because it can be wrong. So each shared library always just parses the types _as_they_see_them_ in their debug info.

We do allow variable introspection to always grab the complete type from another shared library when displaying the type, we just don't allow the static notion of a type that comes from a specific shared library to be augmented within that shared library.

So lets say you have liba.so that contains Foo class which has a "Bar *m_bar;" member variable. liba.so doesn't have a full definition for "Bar" which is OK. "Bar", in liba.so, is known to be "class Bar;", nothing else. When we are debugging a a.out binary later that loads both liba.so and libb.so (which contains the full definition for "Bar"), in the variable display code we see that we want to expand "Bar" in the variables view and we note that we have  a full definition of "Bar" in libb.so, so we end up using the full definition from libb.so in place of the forward declaration. Again, we just switch the types. We can do this because have have a type that comes from a specific target, and within that target (a collection of shared libraries) we can come up with the right definition for "Bar" without modifying the type itself from the debug info within liba.so.

So there should be not problems when viewing variables because we have that covered.

If we have any problems in the expression parser, we will need to solve them in the say kind of way: given a target context, determine the right version of the type to use and copy into the ASTContext for the expression. We currently import types from multiple different ASTContexts into an expression ASTContext for each expression that we run, so it would be possible to identify any classes that were forward declarations and try to complete them during the ASTContext -> ASTContext copy cycle. We would need to somehow mark these incomplete types to allow them to be completed later. Like for example the forward declaration to a base class. We used to just complete the definition for the base class and say it had no member and no methods. We have hooks in to allow the DWARF to assist in laying out a class so that we can correct any alignment issues we run into (since DWARF doesn't always capture any #pragma pack and other compiler directives that can affect how a class is laid out), but we could allow these base classes to be created and mark them somehow in the ClangASTContext so we can identify them later during any expression use. We could also use this for the Variable display code and find the full definition of the forward declaration base class...

So, any changes you make in future fixes must adhere to:

- a type is parsed exactly as it is represented within the object file itself, no outside definitions from other shared libraries can be merged into these types
- it is fine to switch over to using a different version of a type (the full definition of "Bar" from libb.so when you have a forward declaration for "Bar" in liba.so) when displaying variables or evaluating expressions that have a Target in their execution context since the target has a list of all the shared libraries that are currently loaded. This allows process a.out to load one version of "Bar" from libb.so, and process b.out to load another version of "Bar" from libc.so
- We can modify the ClangASTContext ASTImporter to do the same kind of type switching when copying types into the expression ASTContext


More information about the lldb-commits mailing list