Skip to content

Commit

Permalink
Reapply [lldb][DWARF] Delay struct/class/union definition DIE searchi…
Browse files Browse the repository at this point in the history
…ng when parsing declaration DIEs. (#98361)

This is a reapply of #92328 and
#93839.

It now passes the
[test](de3f1b6),
which crashes with the original reverted changes.
  • Loading branch information
ZequanWu authored Jul 16, 2024
1 parent f2d6d74 commit b7b77b0
Show file tree
Hide file tree
Showing 11 changed files with 366 additions and 293 deletions.
331 changes: 151 additions & 180 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp

Large diffs are not rendered by default.

9 changes: 7 additions & 2 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
std::string GetDIEClassTemplateParams(
const lldb_private::plugin::dwarf::DWARFDIE &die) override;

void MapDeclDIEToDefDIE(const lldb_private::plugin::dwarf::DWARFDIE &decl_die,
const lldb_private::plugin::dwarf::DWARFDIE &def_die);

protected:
/// Protected typedefs and members.
/// @{
Expand Down Expand Up @@ -168,8 +171,10 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
lldb_private::TypeSystemClang::TemplateParameterInfos
&template_param_infos);

std::string
GetCPlusPlusQualifiedName(const lldb_private::plugin::dwarf::DWARFDIE &die);
void GetUniqueTypeNameAndDeclaration(
const lldb_private::plugin::dwarf::DWARFDIE &die,
lldb::LanguageType language, lldb_private::ConstString &unique_typename,
lldb_private::Declaration &decl_declaration);

bool ParseChildMembers(
const lldb_private::plugin::dwarf::DWARFDIE &die,
Expand Down
78 changes: 55 additions & 23 deletions lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,13 @@ static ConstString GetDWARFMachOSegmentName() {
return g_dwarf_section_name;
}

llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> &
SymbolFileDWARF::GetForwardDeclCompilerTypeToDIE() {
if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile())
return debug_map_symfile->GetForwardDeclCompilerTypeToDIE();
return m_forward_decl_compiler_type_to_die;
}

UniqueDWARFASTTypeMap &SymbolFileDWARF::GetUniqueDWARFASTTypeMap() {
SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
if (debug_map_symfile)
Expand Down Expand Up @@ -1631,27 +1638,45 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) {
return true;
}

DWARFDIE dwarf_die = GetDIE(die_it->getSecond());
if (dwarf_die) {
// Once we start resolving this type, remove it from the forward
// declaration map in case anyone child members or other types require this
// type to get resolved. The type will get resolved when all of the calls
// to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition are done.
GetForwardDeclCompilerTypeToDIE().erase(die_it);

Type *type = GetDIEToType().lookup(dwarf_die.GetDIE());
DWARFDIE decl_die = GetDIE(die_it->getSecond());
// Once we start resolving this type, remove it from the forward
// declaration map in case anyone's child members or other types require this
// type to get resolved.
GetForwardDeclCompilerTypeToDIE().erase(die_it);
DWARFDIE def_die = FindDefinitionDIE(decl_die);
if (!def_die) {
SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
if (debug_map_symfile) {
// We weren't able to find a full declaration in this DWARF, see
// if we have a declaration anywhere else...
def_die = debug_map_symfile->FindDefinitionDIE(decl_die);
}
}
if (!def_die) {
// If we don't have definition DIE, CompleteTypeFromDWARF will forcefully
// complete this type.
def_die = decl_die;
}

Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion);
if (log)
GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
log, "{0:x8}: {1} ({2}) '{3}' resolving forward declaration...",
dwarf_die.GetID(), DW_TAG_value_to_name(dwarf_die.Tag()),
dwarf_die.Tag(), type->GetName().AsCString());
assert(compiler_type);
if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU()))
return dwarf_ast->CompleteTypeFromDWARF(dwarf_die, type, compiler_type);
DWARFASTParser *dwarf_ast = GetDWARFParser(*def_die.GetCU());
if (!dwarf_ast)
return false;
Type *type = GetDIEToType().lookup(decl_die.GetDIE());
if (decl_die != def_die) {
GetDIEToType()[def_die.GetDIE()] = type;
DWARFASTParserClang *ast_parser =
static_cast<DWARFASTParserClang *>(dwarf_ast);
ast_parser->MapDeclDIEToDefDIE(decl_die, def_die);
}
return false;

Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion);
if (log)
GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
log, "{0:x8}: {1} ({2}) '{3}' resolving forward declaration...",
def_die.GetID(), DW_TAG_value_to_name(def_die.Tag()), def_die.Tag(),
type->GetName().AsCString());
assert(compiler_type);
return dwarf_ast->CompleteTypeFromDWARF(def_die, type, compiler_type);
}

Type *SymbolFileDWARF::ResolveType(const DWARFDIE &die,
Expand Down Expand Up @@ -3047,8 +3072,15 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE(

DWARFDIE
SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) {
if (!die.GetName())
const char *name = die.GetName();
if (!name)
return {};
if (!die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0))
return die;

Progress progress(llvm::formatv(
"Searching definition DIE in {0}: '{1}'",
GetObjectFile()->GetFileSpec().GetFilename().GetString(), name));

const dw_tag_t tag = die.Tag();

Expand All @@ -3058,7 +3090,7 @@ SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) {
log,
"SymbolFileDWARF::FindDefinitionDIE(tag={0} "
"({1}), name='{2}')",
DW_TAG_value_to_name(tag), tag, die.GetName());
DW_TAG_value_to_name(tag), tag, name);
}

// Get the type system that we are looking to find a type for. We will
Expand Down Expand Up @@ -3132,7 +3164,7 @@ SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) {
log,
"SymbolFileDWARF::FindDefinitionDIE(tag={0} ({1}), "
"name='{2}') ignoring die={3:x16} ({4})",
DW_TAG_value_to_name(tag), tag, die.GetName(), type_die.GetOffset(),
DW_TAG_value_to_name(tag), tag, name, type_die.GetOffset(),
type_die.GetName());
}
return true;
Expand All @@ -3144,7 +3176,7 @@ SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) {
log,
"SymbolFileDWARF::FindDefinitionTypeDIE(tag={0} ({1}), name='{2}') "
"trying die={3:x16} ({4})",
DW_TAG_value_to_name(tag), tag, die.GetName(), type_die.GetOffset(),
DW_TAG_value_to_name(tag), tag, name, type_die.GetOffset(),
type_dwarf_decl_ctx.GetQualifiedName());
}

Expand Down
15 changes: 8 additions & 7 deletions lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,12 +342,8 @@ class SymbolFileDWARF : public SymbolFileCommon {

virtual DIEToTypePtr &GetDIEToType() { return m_die_to_type; }

typedef llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef>
CompilerTypeToDIE;

virtual CompilerTypeToDIE &GetForwardDeclCompilerTypeToDIE() {
return m_forward_decl_compiler_type_to_die;
}
virtual llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> &
GetForwardDeclCompilerTypeToDIE();

typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP>
DIEToVariableSP;
Expand Down Expand Up @@ -537,9 +533,14 @@ class SymbolFileDWARF : public SymbolFileCommon {
NameToOffsetMap m_function_scope_qualified_name_map;
std::unique_ptr<DWARFDebugRanges> m_ranges;
UniqueDWARFASTTypeMap m_unique_ast_type_map;
// A map from DIE to lldb_private::Type. For record type, the key might be
// either declaration DIE or definition DIE.
DIEToTypePtr m_die_to_type;
DIEToVariableSP m_die_to_variable_sp;
CompilerTypeToDIE m_forward_decl_compiler_type_to_die;
// A map from CompilerType to the struct/class/union/enum DIE (might be a
// declaration or a definition) that is used to construct it.
llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef>
m_forward_decl_compiler_type_to_die;
llvm::DenseMap<dw_offset_t, std::unique_ptr<SupportFileList>>
m_type_unit_support_files;
std::vector<uint32_t> m_lldb_cu_to_dwarf_unit;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,11 @@ class SymbolFileDWARFDebugMap : public SymbolFileCommon {
lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE(
const DWARFDIE &die, ConstString type_name, bool must_be_implementation);

llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> &
GetForwardDeclCompilerTypeToDIE() {
return m_forward_decl_compiler_type_to_die;
}

UniqueDWARFASTTypeMap &GetUniqueDWARFASTTypeMap() {
return m_unique_ast_type_map;
}
Expand Down Expand Up @@ -321,6 +326,10 @@ class SymbolFileDWARFDebugMap : public SymbolFileCommon {
std::vector<uint32_t> m_func_indexes; // Sorted by address
std::vector<uint32_t> m_glob_indexes;
std::map<std::pair<ConstString, llvm::sys::TimePoint<>>, OSOInfoSP> m_oso_map;
// A map from CompilerType to the struct/class/union/enum DIE (might be a
// declaration or a definition) that is used to construct it.
llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef>
m_forward_decl_compiler_type_to_die;
UniqueDWARFASTTypeMap m_unique_ast_type_map;
LazyBool m_supports_DW_AT_APPLE_objc_complete_type;
DebugMap m_debug_map;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ SymbolFileDWARF::DIEToVariableSP &SymbolFileDWARFDwo::GetDIEToVariable() {
return GetBaseSymbolFile().GetDIEToVariable();
}

SymbolFileDWARF::CompilerTypeToDIE &
llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> &
SymbolFileDWARFDwo::GetForwardDeclCompilerTypeToDIE() {
return GetBaseSymbolFile().GetForwardDeclCompilerTypeToDIE();
}
Expand Down
3 changes: 2 additions & 1 deletion lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ class SymbolFileDWARFDwo : public SymbolFileDWARF {

DIEToVariableSP &GetDIEToVariable() override;

CompilerTypeToDIE &GetForwardDeclCompilerTypeToDIE() override;
llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> &
GetForwardDeclCompilerTypeToDIE() override;

UniqueDWARFASTTypeMap &GetUniqueDWARFASTTypeMap() override;

Expand Down
117 changes: 63 additions & 54 deletions lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,66 +13,75 @@
using namespace lldb_private::dwarf;
using namespace lldb_private::plugin::dwarf;

bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die,
const lldb_private::Declaration &decl,
const int32_t byte_size,
UniqueDWARFASTType &entry) const {
for (const UniqueDWARFASTType &udt : m_collection) {
// Make sure the tags match
if (udt.m_die.Tag() == die.Tag()) {
// Validate byte sizes of both types only if both are valid.
if (udt.m_byte_size < 0 || byte_size < 0 ||
udt.m_byte_size == byte_size) {
// Make sure the file and line match
if (udt.m_declaration == decl) {
// The type has the same name, and was defined on the same file and
// line. Now verify all of the parent DIEs match.
DWARFDIE parent_arg_die = die.GetParent();
DWARFDIE parent_pos_die = udt.m_die.GetParent();
bool match = true;
bool done = false;
while (!done && match && parent_arg_die && parent_pos_die) {
const dw_tag_t parent_arg_tag = parent_arg_die.Tag();
const dw_tag_t parent_pos_tag = parent_pos_die.Tag();
if (parent_arg_tag == parent_pos_tag) {
switch (parent_arg_tag) {
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
case DW_TAG_namespace: {
const char *parent_arg_die_name = parent_arg_die.GetName();
if (parent_arg_die_name ==
nullptr) // Anonymous (i.e. no-name) struct
{
match = false;
} else {
const char *parent_pos_die_name = parent_pos_die.GetName();
if (parent_pos_die_name == nullptr ||
((parent_arg_die_name != parent_pos_die_name) &&
strcmp(parent_arg_die_name, parent_pos_die_name)))
match = false;
}
} break;
static bool IsStructOrClassTag(llvm::dwarf::Tag Tag) {
return Tag == llvm::dwarf::Tag::DW_TAG_class_type ||
Tag == llvm::dwarf::Tag::DW_TAG_structure_type;
}

case DW_TAG_compile_unit:
case DW_TAG_partial_unit:
done = true;
break;
default:
break;
}
UniqueDWARFASTType *UniqueDWARFASTTypeList::Find(
const DWARFDIE &die, const lldb_private::Declaration &decl,
const int32_t byte_size, bool is_forward_declaration) {
for (UniqueDWARFASTType &udt : m_collection) {
// Make sure the tags match
if (udt.m_die.Tag() == die.Tag() || (IsStructOrClassTag(udt.m_die.Tag()) &&
IsStructOrClassTag(die.Tag()))) {
// If they are not both definition DIEs or both declaration DIEs, then
// don't check for byte size and declaration location, because declaration
// DIEs usually don't have those info.
bool matching_size_declaration =
udt.m_is_forward_declaration != is_forward_declaration
? true
: (udt.m_byte_size < 0 || byte_size < 0 ||
udt.m_byte_size == byte_size) &&
udt.m_declaration == decl;
if (!matching_size_declaration)
continue;
// The type has the same name, and was defined on the same file and
// line. Now verify all of the parent DIEs match.
DWARFDIE parent_arg_die = die.GetParent();
DWARFDIE parent_pos_die = udt.m_die.GetParent();
bool match = true;
bool done = false;
while (!done && match && parent_arg_die && parent_pos_die) {
const dw_tag_t parent_arg_tag = parent_arg_die.Tag();
const dw_tag_t parent_pos_tag = parent_pos_die.Tag();
if (parent_arg_tag == parent_pos_tag ||
(IsStructOrClassTag(parent_arg_tag) &&
IsStructOrClassTag(parent_pos_tag))) {
switch (parent_arg_tag) {
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
case DW_TAG_namespace: {
const char *parent_arg_die_name = parent_arg_die.GetName();
if (parent_arg_die_name == nullptr) {
// Anonymous (i.e. no-name) struct
match = false;
} else {
const char *parent_pos_die_name = parent_pos_die.GetName();
if (parent_pos_die_name == nullptr ||
((parent_arg_die_name != parent_pos_die_name) &&
strcmp(parent_arg_die_name, parent_pos_die_name)))
match = false;
}
parent_arg_die = parent_arg_die.GetParent();
parent_pos_die = parent_pos_die.GetParent();
}
} break;

if (match) {
entry = udt;
return true;
case DW_TAG_compile_unit:
case DW_TAG_partial_unit:
done = true;
break;
default:
break;
}
}
parent_arg_die = parent_arg_die.GetParent();
parent_pos_die = parent_pos_die.GetParent();
}

if (match) {
return &udt;
}
}
}
return false;
return nullptr;
}
Loading

0 comments on commit b7b77b0

Please sign in to comment.