Pavel Labath a03dc8c9fa [lldb] Add basic -flimit-debug-info support to expression evaluator
Summary:
This patch adds support for evaluation of expressions referring to types
which were compiled in -flimit-debug-info (a.k.a -fno-standalone-debug)
in clang. In this mode it's possible that the debug information needed
to fully describe a c++ type is not present in a single shared library
-- for example debug info for a base class or a member of a type can
only be found in another shared library.  This situation is not
currently handled well within lldb as we are limited to searching within
a single shared library (lldb_private::Module) when searching for the
definition of these types.

The way that this patch gets around this limitation is by doing the
search at a later stage -- during the construction of the expression ast
context. This works by having the parser (currently SymbolFileDWARF, but
a similar approach is probably needed for PDBs too) mark a type as
"forcefully completed". What this means is that the parser has marked
the type as "complete" in the module ast context (as this is necessary
to e.g. derive classes from it), but its definition is not really there.
This is done via a new field on the ClangASTMetadata struct.

Later, when we are importing such a type into the expression ast, we
check this flag. If the flag is set, we try to find a better definition
for the type in other shared libraries. We do this by initiating a
new lookup for the "forcefully completed" classes, which then imports the
type from a module with a full definition.

This patch only implements this handling for base classes, but other
cases (members, array element types, etc.). The changes for that should
be fairly simple and mostly revolve around marking these types as
"forcefully completed" at an approriate time -- the importing logic is
generic already.

Another aspect, which is also not handled by this patch is viewing these
types via the "frame variable" command. This does not use the AST
importer and so it will need to handle these types on its own -- that
will be the subject of another patch.

Differential Revision: https://reviews.llvm.org/D81561
2020-07-01 14:50:14 +02:00

111 lines
2.9 KiB
C++

//===-- ClangASTMetadata.h --------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGASTMETADATA_H
#define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGASTMETADATA_H
#include "lldb/Core/dwarf.h"
#include "lldb/lldb-defines.h"
#include "lldb/lldb-enumerations.h"
namespace lldb_private {
class ClangASTMetadata {
public:
ClangASTMetadata()
: m_user_id(0), m_union_is_user_id(false), m_union_is_isa_ptr(false),
m_has_object_ptr(false), m_is_self(false), m_is_dynamic_cxx(true),
m_is_forcefully_completed(false) {}
bool GetIsDynamicCXXType() const { return m_is_dynamic_cxx; }
void SetIsDynamicCXXType(bool b) { m_is_dynamic_cxx = b; }
void SetUserID(lldb::user_id_t user_id) {
m_user_id = user_id;
m_union_is_user_id = true;
m_union_is_isa_ptr = false;
}
lldb::user_id_t GetUserID() const {
if (m_union_is_user_id)
return m_user_id;
else
return LLDB_INVALID_UID;
}
void SetISAPtr(uint64_t isa_ptr) {
m_isa_ptr = isa_ptr;
m_union_is_user_id = false;
m_union_is_isa_ptr = true;
}
uint64_t GetISAPtr() const {
if (m_union_is_isa_ptr)
return m_isa_ptr;
else
return 0;
}
void SetObjectPtrName(const char *name) {
m_has_object_ptr = true;
if (strcmp(name, "self") == 0)
m_is_self = true;
else if (strcmp(name, "this") == 0)
m_is_self = false;
else
m_has_object_ptr = false;
}
lldb::LanguageType GetObjectPtrLanguage() const {
if (m_has_object_ptr) {
if (m_is_self)
return lldb::eLanguageTypeObjC;
else
return lldb::eLanguageTypeC_plus_plus;
}
return lldb::eLanguageTypeUnknown;
}
const char *GetObjectPtrName() const {
if (m_has_object_ptr) {
if (m_is_self)
return "self";
else
return "this";
} else
return nullptr;
}
bool HasObjectPtr() const { return m_has_object_ptr; }
/// A type is "forcefully completed" if it was declared complete to satisfy an
/// AST invariant (e.g. base classes must be complete types), but in fact we
/// were not able to find a actual definition for it.
bool IsForcefullyCompleted() const { return m_is_forcefully_completed; }
void SetIsForcefullyCompleted(bool value = true) {
m_is_forcefully_completed = true;
}
void Dump(Stream *s);
private:
union {
lldb::user_id_t m_user_id;
uint64_t m_isa_ptr;
};
bool m_union_is_user_id : 1, m_union_is_isa_ptr : 1, m_has_object_ptr : 1,
m_is_self : 1, m_is_dynamic_cxx : 1, m_is_forcefully_completed : 1;
};
} // namespace lldb_private
#endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGASTMETADATA_H