Skip to content

Commit

Permalink
DO NOT SUBMIT: Really dodgy demonstration of DWARFTypePrinter reuse i…
Browse files Browse the repository at this point in the history
…n 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)
  • Loading branch information
dwblaikie committed Apr 25, 2024
1 parent b292649 commit 9a654b0
Show file tree
Hide file tree
Showing 12 changed files with 830 additions and 715 deletions.
11 changes: 11 additions & 0 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <cstdlib>
#include <iostream>
#include <algorithm>

#include "DWARFASTParser.h"
#include "DWARFASTParserClang.h"
Expand Down Expand Up @@ -45,6 +46,8 @@
#include "clang/AST/Type.h"
#include "llvm/Demangle/Demangle.h"

#include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h"

#include <map>
#include <memory>
#include <optional>
Expand Down Expand Up @@ -798,11 +801,19 @@ DWARFASTParserClang::GetDIEClassTemplateParams(const DWARFDIE &die) {
if (llvm::StringRef(die.GetName()).contains("<"))
return ConstString();

#if 1
std::string R;
llvm::raw_string_ostream OS(R);
llvm::DWARFTypePrinter<DWARFDIE> p(OS);
p.appendAndTerminateTemplateParameters(die);
return ConstString(R);
#else
TypeSystemClang::TemplateParameterInfos template_param_infos;
if (ParseTemplateParameterInfos(die, template_param_infos)) {
return ConstString(m_ast.PrintTemplateParams(template_param_infos));
}
return ConstString();
#endif
}

TypeSP DWARFASTParserClang::ParseEnum(const SymbolContext &sc,
Expand Down
10 changes: 10 additions & 0 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class DWARFUnit;
class DWARFDebugInfoEntry;
class DWARFDeclContext;
class SymbolFileDWARF;
class DWARFFormValue;

class DWARFBaseDIE {
public:
Expand All @@ -47,6 +48,8 @@ class DWARFBaseDIE {

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

bool isValid() const { return IsValid(); }

bool HasChildren() const;

bool Supports_DW_AT_APPLE_objc_complete_type() const;
Expand Down Expand Up @@ -84,6 +87,10 @@ class DWARFBaseDIE {

// Accessing information about a DIE
dw_tag_t Tag() const;
dw_tag_t getTag() const {
return Tag();
}
using DWARFFormValue = dwarf::DWARFFormValue;

const char *GetTagAsCString() const;

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

const char *GetName() const;
const char *getShortName() const {
return GetName();
}

lldb::ModuleSP GetModule() const;

Expand Down
21 changes: 20 additions & 1 deletion lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,13 @@ DWARFDIE::GetReferencedDIE(const dw_attr_t attr) const {
}

DWARFDIE
DWARFDIE::GetDIE(dw_offset_t die_offset) const {
DWARFDIE::getAttributeValueAsReferencedDie(DWARFFormValue value) const {
if (IsValid())
return value.Reference();
return {};
}

DWARFDIE DWARFDIE::GetDIE(dw_offset_t die_offset) const {
if (IsValid())
return m_cu->GetDIE(die_offset);
else
Expand Down Expand Up @@ -522,3 +528,16 @@ bool DWARFDIE::GetDIENamesAndRanges(
llvm::iterator_range<DWARFDIE::child_iterator> DWARFDIE::children() const {
return llvm::make_range(child_iterator(*this), child_iterator());
}

DWARFDIE::child_iterator DWARFDIE::begin() const {
return child_iterator(*this);
}
DWARFDIE::child_iterator DWARFDIE::end() const {
return child_iterator();
}
std::optional<DWARFFormValue> DWARFDIE::find(const dw_attr_t attr) const {
DWARFFormValue form_value;
if (m_die->GetAttributeValue(m_cu, attr, form_value, nullptr, false))
return form_value;
return std::nullopt;
}
13 changes: 13 additions & 0 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ class DWARFDIE : public DWARFBaseDIE {
DWARFDIE
GetParent() const;

DWARFDIE getParent() const { return GetParent(); }

DWARFDIE
GetFirstChild() const;

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

DWARFDIE getAttributeValueAsReferencedDie(const dw_attr_t attr) const {
return GetReferencedDIE(attr);
}

DWARFDIE getAttributeValueAsReferencedDie(DWARFFormValue) const;

// Get a another DIE from the same DWARF file as this DIE. This will
// check the current DIE's compile unit first to see if "die_offset" is
// in the same compile unit, and fall back to checking the DWARF file.
Expand Down Expand Up @@ -97,6 +105,8 @@ class DWARFDIE : public DWARFBaseDIE {
DWARFDIE
GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const;

std::optional<DWARFFormValue> find(const dw_attr_t attr) const;

bool GetDIENamesAndRanges(
const char *&name, const char *&mangled, DWARFRangeList &ranges,
std::optional<int> &decl_file, std::optional<int> &decl_line,
Expand All @@ -106,6 +116,9 @@ class DWARFDIE : public DWARFBaseDIE {

/// The range of all the children of this DIE.
llvm::iterator_range<child_iterator> children() const;

child_iterator begin() const;
child_iterator end() const;
};

class DWARFDIE::child_iterator
Expand Down
37 changes: 37 additions & 0 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,30 @@ class DWARFFormValue {
uint64_t Reference(dw_offset_t offset) const;
bool Boolean() const { return m_value.value.uval != 0; }
uint64_t Unsigned() const { return m_value.value.uval; }
std::optional<uint64_t> getAsUnsignedConstant() const {
if ((!IsDataForm(m_form)) || m_form == lldb_private::dwarf::DW_FORM_sdata)
return std::nullopt;
return m_value.value.uval;
}
std::optional<int64_t> getAsSignedConstant() const {
if ((!IsDataForm(m_form)) ||
(m_form == lldb_private::dwarf::DW_FORM_udata &&
uint64_t(std::numeric_limits<int64_t>::max()) < m_value.value.uval))
return std::nullopt;
switch (m_form) {
case lldb_private::dwarf::DW_FORM_data4:
return int32_t(m_value.value.uval);
case lldb_private::dwarf::DW_FORM_data2:
return int16_t(m_value.value.uval);
case lldb_private::dwarf::DW_FORM_data1:
return int8_t(m_value.value.uval);
case lldb_private::dwarf::DW_FORM_sdata:
case lldb_private::dwarf::DW_FORM_data8:
default:
return m_value.value.sval;
}
}

void SetUnsigned(uint64_t uval) { m_value.value.uval = uval; }
int64_t Signed() const { return m_value.value.sval; }
void SetSigned(int64_t sval) { m_value.value.sval = sval; }
Expand All @@ -93,6 +117,19 @@ class DWARFFormValue {
dw_form_t m_form = dw_form_t(0); // Form for this value
ValueType m_value; // Contains all data for the form
};

inline const char* toString(DWARFFormValue Value, const char* Default) {
if (const char* R = Value.AsCString())
return R;
return Default;
}
inline const char* toString(std::optional<DWARFFormValue> Value, const char* Default) {
if (!Value)
return Default;
if (const char* R = Value->AsCString())
return R;
return Default;
}
} // namespace dwarf
} // namespace lldb_private::plugin

Expand Down
24 changes: 7 additions & 17 deletions lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3203,31 +3203,21 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die) {
type_dwarf_decl_ctx.GetQualifiedName());
}

Type *resolved_type = ResolveType(type_die, false);
if (!resolved_type || resolved_type == DIE_IS_BEING_PARSED)
return true;

// With -gsimple-template-names, the DIE name may not contain the template
// parameters. If the declaration has template parameters but doesn't
// contain '<', check that the child template parameters match.
if (template_params) {
llvm::StringRef test_base_name =
GetTypeForDIE(type_die)->GetBaseName().GetStringRef();
auto i = test_base_name.find('<');

// Full name from clang AST doesn't contain '<' so this type_die isn't
// a template parameter, but we're expecting template parameters, so
// bail.
if (i == llvm::StringRef::npos)
return true;

llvm::StringRef test_template_params =
test_base_name.slice(i, test_base_name.size());
ConstString test_template_params =
type_system->GetDWARFParser()->GetDIEClassTemplateParams(type_die);
// Bail if template parameters don't match.
if (test_template_params != template_params.GetStringRef())
if (test_template_params != template_params)
return true;
}

Type *resolved_type = ResolveType(type_die, false);
if (!resolved_type || resolved_type == DIE_IS_BEING_PARSED)
return true;

type_sp = resolved_type->shared_from_this();
return false;
});
Expand Down
8 changes: 8 additions & 0 deletions llvm/include/llvm-c/Error.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ LLVMErrorTypeId LLVMGetErrorTypeId(LLVMErrorRef Err);
*/
void LLVMConsumeError(LLVMErrorRef Err);

/**
* Report a fatal error if Err is a failure value.
*
* This function can be used to wrap calls to fallible functions ONLY when it
* is known that the Error will always be a success value.
*/
void LLVMCantFail(LLVMErrorRef Err);

/**
* Returns the given string's error message. This operation consumes the error,
* and the given LLVMErrorRef value is not usable once this call returns.
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
#include "llvm/DebugInfo/DWARF/DWARFAttribute.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
#include <cassert>
#include <cstdint>
Expand Down Expand Up @@ -44,6 +45,7 @@ class DWARFDie {
const DWARFDebugInfoEntry *Die = nullptr;

public:
using DWARFFormValue = llvm::DWARFFormValue;
DWARFDie() = default;
DWARFDie(DWARFUnit *Unit, const DWARFDebugInfoEntry *D) : U(Unit), Die(D) {}

Expand Down
7 changes: 5 additions & 2 deletions llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,6 @@ class DWARFFormValue {
void dumpString(raw_ostream &OS) const;
};

namespace dwarf {

/// Take an optional DWARFFormValue and try to extract a string value from it.
///
/// \param V and optional DWARFFormValue to attempt to extract the value from.
Expand Down Expand Up @@ -219,6 +217,11 @@ inline const char *toString(const std::optional<DWARFFormValue> &V,
return Default;
}

namespace dwarf {

using llvm::toString;
using llvm::toStringRef;

/// Take an optional DWARFFormValue and try to extract an unsigned constant.
///
/// \param V and optional DWARFFormValue to attempt to extract the value from.
Expand Down
Loading

0 comments on commit 9a654b0

Please sign in to comment.