Skip to content

Commit 9a654b0

Browse files
committed
DO NOT SUBMIT: Really dodgy demonstration of DWARFTypePrinter reuse in lldb
The hacks necessary to make lldb's DWARFDIE APIs sufficiently compatible with LLVM's DWARFDie API aren't shippable, but maybe somewhere to start the conversation. With all these changes, an internal example that would crash expanding too many types (computing the fully qualified name for 414671 types before crashing due to running out of stack) - but with these patches applied, it comes down to 856 expansions (compared to 848 for non-simplified template names inputs)
1 parent b292649 commit 9a654b0

File tree

12 files changed

+830
-715
lines changed

12 files changed

+830
-715
lines changed

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include <cstdlib>
1010
#include <iostream>
11+
#include <algorithm>
1112

1213
#include "DWARFASTParser.h"
1314
#include "DWARFASTParserClang.h"
@@ -45,6 +46,8 @@
4546
#include "clang/AST/Type.h"
4647
#include "llvm/Demangle/Demangle.h"
4748

49+
#include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h"
50+
4851
#include <map>
4952
#include <memory>
5053
#include <optional>
@@ -798,11 +801,19 @@ DWARFASTParserClang::GetDIEClassTemplateParams(const DWARFDIE &die) {
798801
if (llvm::StringRef(die.GetName()).contains("<"))
799802
return ConstString();
800803

804+
#if 1
805+
std::string R;
806+
llvm::raw_string_ostream OS(R);
807+
llvm::DWARFTypePrinter<DWARFDIE> p(OS);
808+
p.appendAndTerminateTemplateParameters(die);
809+
return ConstString(R);
810+
#else
801811
TypeSystemClang::TemplateParameterInfos template_param_infos;
802812
if (ParseTemplateParameterInfos(die, template_param_infos)) {
803813
return ConstString(m_ast.PrintTemplateParams(template_param_infos));
804814
}
805815
return ConstString();
816+
#endif
806817
}
807818

808819
TypeSP DWARFASTParserClang::ParseEnum(const SymbolContext &sc,

lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class DWARFUnit;
2424
class DWARFDebugInfoEntry;
2525
class DWARFDeclContext;
2626
class SymbolFileDWARF;
27+
class DWARFFormValue;
2728

2829
class DWARFBaseDIE {
2930
public:
@@ -47,6 +48,8 @@ class DWARFBaseDIE {
4748

4849
bool IsValid() const { return m_cu && m_die; }
4950

51+
bool isValid() const { return IsValid(); }
52+
5053
bool HasChildren() const;
5154

5255
bool Supports_DW_AT_APPLE_objc_complete_type() const;
@@ -84,6 +87,10 @@ class DWARFBaseDIE {
8487

8588
// Accessing information about a DIE
8689
dw_tag_t Tag() const;
90+
dw_tag_t getTag() const {
91+
return Tag();
92+
}
93+
using DWARFFormValue = dwarf::DWARFFormValue;
8794

8895
const char *GetTagAsCString() const;
8996

@@ -96,6 +103,9 @@ class DWARFBaseDIE {
96103
lldb::user_id_t GetID() const;
97104

98105
const char *GetName() const;
106+
const char *getShortName() const {
107+
return GetName();
108+
}
99109

100110
lldb::ModuleSP GetModule() const;
101111

lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,13 @@ DWARFDIE::GetReferencedDIE(const dw_attr_t attr) const {
116116
}
117117

118118
DWARFDIE
119-
DWARFDIE::GetDIE(dw_offset_t die_offset) const {
119+
DWARFDIE::getAttributeValueAsReferencedDie(DWARFFormValue value) const {
120+
if (IsValid())
121+
return value.Reference();
122+
return {};
123+
}
124+
125+
DWARFDIE DWARFDIE::GetDIE(dw_offset_t die_offset) const {
120126
if (IsValid())
121127
return m_cu->GetDIE(die_offset);
122128
else
@@ -522,3 +528,16 @@ bool DWARFDIE::GetDIENamesAndRanges(
522528
llvm::iterator_range<DWARFDIE::child_iterator> DWARFDIE::children() const {
523529
return llvm::make_range(child_iterator(*this), child_iterator());
524530
}
531+
532+
DWARFDIE::child_iterator DWARFDIE::begin() const {
533+
return child_iterator(*this);
534+
}
535+
DWARFDIE::child_iterator DWARFDIE::end() const {
536+
return child_iterator();
537+
}
538+
std::optional<DWARFFormValue> DWARFDIE::find(const dw_attr_t attr) const {
539+
DWARFFormValue form_value;
540+
if (m_die->GetAttributeValue(m_cu, attr, form_value, nullptr, false))
541+
return form_value;
542+
return std::nullopt;
543+
}

lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ class DWARFDIE : public DWARFBaseDIE {
4747
DWARFDIE
4848
GetParent() const;
4949

50+
DWARFDIE getParent() const { return GetParent(); }
51+
5052
DWARFDIE
5153
GetFirstChild() const;
5254

@@ -56,6 +58,12 @@ class DWARFDIE : public DWARFBaseDIE {
5658
DWARFDIE
5759
GetReferencedDIE(const dw_attr_t attr) const;
5860

61+
DWARFDIE getAttributeValueAsReferencedDie(const dw_attr_t attr) const {
62+
return GetReferencedDIE(attr);
63+
}
64+
65+
DWARFDIE getAttributeValueAsReferencedDie(DWARFFormValue) const;
66+
5967
// Get a another DIE from the same DWARF file as this DIE. This will
6068
// check the current DIE's compile unit first to see if "die_offset" is
6169
// in the same compile unit, and fall back to checking the DWARF file.
@@ -97,6 +105,8 @@ class DWARFDIE : public DWARFBaseDIE {
97105
DWARFDIE
98106
GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const;
99107

108+
std::optional<DWARFFormValue> find(const dw_attr_t attr) const;
109+
100110
bool GetDIENamesAndRanges(
101111
const char *&name, const char *&mangled, DWARFRangeList &ranges,
102112
std::optional<int> &decl_file, std::optional<int> &decl_line,
@@ -106,6 +116,9 @@ class DWARFDIE : public DWARFBaseDIE {
106116

107117
/// The range of all the children of this DIE.
108118
llvm::iterator_range<child_iterator> children() const;
119+
120+
child_iterator begin() const;
121+
child_iterator end() const;
109122
};
110123

111124
class DWARFDIE::child_iterator

lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,30 @@ class DWARFFormValue {
6969
uint64_t Reference(dw_offset_t offset) const;
7070
bool Boolean() const { return m_value.value.uval != 0; }
7171
uint64_t Unsigned() const { return m_value.value.uval; }
72+
std::optional<uint64_t> getAsUnsignedConstant() const {
73+
if ((!IsDataForm(m_form)) || m_form == lldb_private::dwarf::DW_FORM_sdata)
74+
return std::nullopt;
75+
return m_value.value.uval;
76+
}
77+
std::optional<int64_t> getAsSignedConstant() const {
78+
if ((!IsDataForm(m_form)) ||
79+
(m_form == lldb_private::dwarf::DW_FORM_udata &&
80+
uint64_t(std::numeric_limits<int64_t>::max()) < m_value.value.uval))
81+
return std::nullopt;
82+
switch (m_form) {
83+
case lldb_private::dwarf::DW_FORM_data4:
84+
return int32_t(m_value.value.uval);
85+
case lldb_private::dwarf::DW_FORM_data2:
86+
return int16_t(m_value.value.uval);
87+
case lldb_private::dwarf::DW_FORM_data1:
88+
return int8_t(m_value.value.uval);
89+
case lldb_private::dwarf::DW_FORM_sdata:
90+
case lldb_private::dwarf::DW_FORM_data8:
91+
default:
92+
return m_value.value.sval;
93+
}
94+
}
95+
7296
void SetUnsigned(uint64_t uval) { m_value.value.uval = uval; }
7397
int64_t Signed() const { return m_value.value.sval; }
7498
void SetSigned(int64_t sval) { m_value.value.sval = sval; }
@@ -93,6 +117,19 @@ class DWARFFormValue {
93117
dw_form_t m_form = dw_form_t(0); // Form for this value
94118
ValueType m_value; // Contains all data for the form
95119
};
120+
121+
inline const char* toString(DWARFFormValue Value, const char* Default) {
122+
if (const char* R = Value.AsCString())
123+
return R;
124+
return Default;
125+
}
126+
inline const char* toString(std::optional<DWARFFormValue> Value, const char* Default) {
127+
if (!Value)
128+
return Default;
129+
if (const char* R = Value->AsCString())
130+
return R;
131+
return Default;
132+
}
96133
} // namespace dwarf
97134
} // namespace lldb_private::plugin
98135

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3203,31 +3203,21 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die) {
32033203
type_dwarf_decl_ctx.GetQualifiedName());
32043204
}
32053205

3206-
Type *resolved_type = ResolveType(type_die, false);
3207-
if (!resolved_type || resolved_type == DIE_IS_BEING_PARSED)
3208-
return true;
3209-
32103206
// With -gsimple-template-names, the DIE name may not contain the template
32113207
// parameters. If the declaration has template parameters but doesn't
32123208
// contain '<', check that the child template parameters match.
32133209
if (template_params) {
3214-
llvm::StringRef test_base_name =
3215-
GetTypeForDIE(type_die)->GetBaseName().GetStringRef();
3216-
auto i = test_base_name.find('<');
3217-
3218-
// Full name from clang AST doesn't contain '<' so this type_die isn't
3219-
// a template parameter, but we're expecting template parameters, so
3220-
// bail.
3221-
if (i == llvm::StringRef::npos)
3222-
return true;
3223-
3224-
llvm::StringRef test_template_params =
3225-
test_base_name.slice(i, test_base_name.size());
3210+
ConstString test_template_params =
3211+
type_system->GetDWARFParser()->GetDIEClassTemplateParams(type_die);
32263212
// Bail if template parameters don't match.
3227-
if (test_template_params != template_params.GetStringRef())
3213+
if (test_template_params != template_params)
32283214
return true;
32293215
}
32303216

3217+
Type *resolved_type = ResolveType(type_die, false);
3218+
if (!resolved_type || resolved_type == DIE_IS_BEING_PARSED)
3219+
return true;
3220+
32313221
type_sp = resolved_type->shared_from_this();
32323222
return false;
32333223
});

llvm/include/llvm-c/Error.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ LLVMErrorTypeId LLVMGetErrorTypeId(LLVMErrorRef Err);
5151
*/
5252
void LLVMConsumeError(LLVMErrorRef Err);
5353

54+
/**
55+
* Report a fatal error if Err is a failure value.
56+
*
57+
* This function can be used to wrap calls to fallible functions ONLY when it
58+
* is known that the Error will always be a success value.
59+
*/
60+
void LLVMCantFail(LLVMErrorRef Err);
61+
5462
/**
5563
* Returns the given string's error message. This operation consumes the error,
5664
* and the given LLVMErrorRef value is not usable once this call returns.

llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
1818
#include "llvm/DebugInfo/DWARF/DWARFAttribute.h"
1919
#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
20+
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
2021
#include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
2122
#include <cassert>
2223
#include <cstdint>
@@ -44,6 +45,7 @@ class DWARFDie {
4445
const DWARFDebugInfoEntry *Die = nullptr;
4546

4647
public:
48+
using DWARFFormValue = llvm::DWARFFormValue;
4749
DWARFDie() = default;
4850
DWARFDie(DWARFUnit *Unit, const DWARFDebugInfoEntry *D) : U(Unit), Die(D) {}
4951

llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,6 @@ class DWARFFormValue {
168168
void dumpString(raw_ostream &OS) const;
169169
};
170170

171-
namespace dwarf {
172-
173171
/// Take an optional DWARFFormValue and try to extract a string value from it.
174172
///
175173
/// \param V and optional DWARFFormValue to attempt to extract the value from.
@@ -219,6 +217,11 @@ inline const char *toString(const std::optional<DWARFFormValue> &V,
219217
return Default;
220218
}
221219

220+
namespace dwarf {
221+
222+
using llvm::toString;
223+
using llvm::toStringRef;
224+
222225
/// Take an optional DWARFFormValue and try to extract an unsigned constant.
223226
///
224227
/// \param V and optional DWARFFormValue to attempt to extract the value from.

0 commit comments

Comments
 (0)