Skip to content

Commit 3966ec6

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 b98e417 commit 3966ec6

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>
@@ -866,11 +869,19 @@ DWARFASTParserClang::GetDIEClassTemplateParams(const DWARFDIE &die) {
866869
if (llvm::StringRef(die.GetName()).contains("<"))
867870
return ConstString();
868871

872+
#if 1
873+
std::string R;
874+
llvm::raw_string_ostream OS(R);
875+
llvm::DWARFTypePrinter<DWARFDIE> p(OS);
876+
p.appendAndTerminateTemplateParameters(die);
877+
return ConstString(R);
878+
#else
869879
TypeSystemClang::TemplateParameterInfos template_param_infos;
870880
if (ParseTemplateParameterInfos(die, template_param_infos)) {
871881
return ConstString(m_ast.PrintTemplateParams(template_param_infos));
872882
}
873883
return ConstString();
884+
#endif
874885
}
875886

876887
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
dw_offset_t GetOffset() const;
8996

@@ -94,6 +101,9 @@ class DWARFBaseDIE {
94101
lldb::user_id_t GetID() const;
95102

96103
const char *GetName() const;
104+
const char *getShortName() const {
105+
return GetName();
106+
}
97107

98108
lldb::ModuleSP GetModule() const;
99109

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

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

120120
DWARFDIE
121-
DWARFDIE::GetDIE(dw_offset_t die_offset) const {
121+
DWARFDIE::getAttributeValueAsReferencedDie(DWARFFormValue value) const {
122+
if (IsValid())
123+
return value.Reference();
124+
return {};
125+
}
126+
127+
DWARFDIE DWARFDIE::GetDIE(dw_offset_t die_offset) const {
122128
if (IsValid())
123129
return m_cu->GetDIE(die_offset);
124130
else
@@ -545,3 +551,16 @@ bool DWARFDIE::GetDIENamesAndRanges(
545551
llvm::iterator_range<DWARFDIE::child_iterator> DWARFDIE::children() const {
546552
return llvm::make_range(child_iterator(*this), child_iterator());
547553
}
554+
555+
DWARFDIE::child_iterator DWARFDIE::begin() const {
556+
return child_iterator(*this);
557+
}
558+
DWARFDIE::child_iterator DWARFDIE::end() const {
559+
return child_iterator();
560+
}
561+
std::optional<DWARFFormValue> DWARFDIE::find(const dw_attr_t attr) const {
562+
DWARFFormValue form_value;
563+
if (m_die->GetAttributeValue(m_cu, attr, form_value, nullptr, false))
564+
return form_value;
565+
return std::nullopt;
566+
}

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
@@ -3219,31 +3219,21 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die) {
32193219
type_dwarf_decl_ctx.GetQualifiedName());
32203220
}
32213221

3222-
Type *resolved_type = ResolveType(type_die, false);
3223-
if (!resolved_type || resolved_type == DIE_IS_BEING_PARSED)
3224-
return true;
3225-
32263222
// With -gsimple-template-names, the DIE name may not contain the template
32273223
// parameters. If the declaration has template parameters but doesn't
32283224
// contain '<', check that the child template parameters match.
32293225
if (template_params) {
3230-
llvm::StringRef test_base_name =
3231-
GetTypeForDIE(type_die)->GetBaseName().GetStringRef();
3232-
auto i = test_base_name.find('<');
3233-
3234-
// Full name from clang AST doesn't contain '<' so this type_die isn't
3235-
// a template parameter, but we're expecting template parameters, so
3236-
// bail.
3237-
if (i == llvm::StringRef::npos)
3238-
return true;
3239-
3240-
llvm::StringRef test_template_params =
3241-
test_base_name.slice(i, test_base_name.size());
3226+
ConstString test_template_params =
3227+
type_system->GetDWARFParser()->GetDIEClassTemplateParams(type_die);
32423228
// Bail if template parameters don't match.
3243-
if (test_template_params != template_params.GetStringRef())
3229+
if (test_template_params != template_params)
32443230
return true;
32453231
}
32463232

3233+
Type *resolved_type = ResolveType(type_die, false);
3234+
if (!resolved_type || resolved_type == DIE_IS_BEING_PARSED)
3235+
return true;
3236+
32473237
type_sp = resolved_type->shared_from_this();
32483238
return false;
32493239
});

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)