Skip to content

Commit

Permalink
llvm-dwarfdump: Lookup type units when prettyprinting types
Browse files Browse the repository at this point in the history
This handles DWARFv4 and DWARFv5 type units, but not Split DWARF type
units. That'll come in a follow-up patch.
  • Loading branch information
dwblaikie committed Nov 10, 2021
1 parent f30a8a6 commit 58b1b64
Show file tree
Hide file tree
Showing 6 changed files with 479 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
// RUN: %clang %target_itanium_abi_host_triple %s -c -o - -g -Xclang -gsimple-template-names=mangled -Xclang -debug-forward-template-params -std=c++20 \
// RUN: %clang %target_itanium_abi_host_triple %s -c -o - -gdwarf-4 -Xclang -gsimple-template-names=mangled -Xclang -debug-forward-template-params -std=c++20 \
// RUN: | llvm-dwarfdump --verify -
// RUN: %clang %target_itanium_abi_host_triple %s -c -o - -gdwarf-4 -Xclang -gsimple-template-names=mangled -Xclang -debug-forward-template-params -std=c++20 -fdebug-types-section \
// RUN: | llvm-dwarfdump --verify -
// RUN: %clang %target_itanium_abi_host_triple %s -c -o - -gdwarf-5 -Xclang -gsimple-template-names=mangled -Xclang -debug-forward-template-params -std=c++20 -fdebug-types-section \
// RUN: | llvm-dwarfdump --verify -
#include <cstdint>
template<typename ...Ts>
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ class DWARFContext : public DIContext {
}

DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash);
DWARFTypeUnit *getTypeUnitForHash(uint16_t Version, uint64_t Hash);

/// Return the compile unit that includes an offset (relative to .debug_info).
DWARFCompileUnit *getCompileUnitForOffset(uint64_t Offset);
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 @@ -182,6 +182,8 @@ class DWARFDie {
DWARFDie getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const;
DWARFDie getAttributeValueAsReferencedDie(const DWARFFormValue &V) const;

DWARFDie resolveTypeUnitReference() const;

/// Extract the range base attribute from this DIE as absolute section offset.
///
/// This is a utility function that checks for either the DW_AT_rnglists_base
Expand Down
21 changes: 21 additions & 0 deletions llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,27 @@ void DWARFContext::dump(
getDebugNames().dump(OS);
}

DWARFTypeUnit *DWARFContext::getTypeUnitForHash(uint16_t Version,
uint64_t Hash) {
// FIXME: Include support for Split DWARF here
parseNormalUnits();

auto IsTypeWithHash = [&](const std::unique_ptr<DWARFUnit> &Unit) {
DWARFTypeUnit *TU = dyn_cast<DWARFTypeUnit>(Unit.get());
if (!TU)
return false;
return TU->getTypeHash() == Hash;
};
auto I = llvm::find_if(types_section_units(), IsTypeWithHash);
if (I != types_section_units().end())
return cast<DWARFTypeUnit>(I->get());
// Search normal .debug_info units in case it's a DWARFv5 type unit.
I = llvm::find_if(normal_units(), IsTypeWithHash);
if (I != types_section_units().end())
return cast<DWARFTypeUnit>(I->get());
return nullptr;
}

DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) {
parseDWOUnits(LazyParse);

Expand Down
77 changes: 47 additions & 30 deletions llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,14 @@ static void dumpLocationExpr(raw_ostream &OS, const DWARFFormValue &FormValue,
return;
}

static DWARFDie resolveReferencedType(DWARFDie D,
dwarf::Attribute Attr = DW_AT_type) {
return D.getAttributeValueAsReferencedDie(Attr).resolveTypeUnitReference();
}
static DWARFDie resolveReferencedType(DWARFDie D, DWARFFormValue F) {
return D.getAttributeValueAsReferencedDie(F).resolveTypeUnitReference();
}

namespace {

// FIXME: We should have pretty printers per language. Currently we print
Expand Down Expand Up @@ -181,7 +189,7 @@ struct DWARFTypePrinter {
DWARFDie skipQualifiers(DWARFDie D) {
while (D && (D.getTag() == DW_TAG_const_type ||
D.getTag() == DW_TAG_volatile_type))
D = D.getAttributeValueAsReferencedDie(DW_AT_type);
D = resolveReferencedType(D);
return D;
}

Expand Down Expand Up @@ -209,7 +217,7 @@ struct DWARFTypePrinter {
OS << "void";
return DWARFDie();
}
DWARFDie Inner = D.getAttributeValueAsReferencedDie(DW_AT_type);
DWARFDie Inner = resolveReferencedType(D);
const dwarf::Tag T = D.getTag();
switch (T) {
case DW_TAG_pointer_type: {
Expand Down Expand Up @@ -240,8 +248,7 @@ struct DWARFTypePrinter {
OS << '(';
else if (Word)
OS << ' ';
if (DWARFDie Cont =
D.getAttributeValueAsReferencedDie(DW_AT_containing_type)) {
if (DWARFDie Cont = resolveReferencedType(D, DW_AT_containing_type)) {
appendQualifiedName(Cont);
OS << "::";
}
Expand Down Expand Up @@ -339,10 +346,9 @@ struct DWARFTypePrinter {
case DW_TAG_pointer_type: {
if (needsParens(Inner))
OS << ')';
appendUnqualifiedNameAfter(
Inner, Inner.getAttributeValueAsReferencedDie(DW_AT_type),
/*SkipFirstParamIfArtificial=*/D.getTag() ==
DW_TAG_ptr_to_member_type);
appendUnqualifiedNameAfter(Inner, resolveReferencedType(Inner),
/*SkipFirstParamIfArtificial=*/D.getTag() ==
DW_TAG_ptr_to_member_type);
break;
}
/*
Expand Down Expand Up @@ -387,7 +393,7 @@ struct DWARFTypePrinter {
appendTemplateParameters(C, FirstParameter);
}
if (C.getTag() == dwarf::DW_TAG_template_value_parameter) {
DWARFDie T = C.getAttributeValueAsReferencedDie(DW_AT_type);
DWARFDie T = resolveReferencedType(C);
Sep();
if (T.getTag() == DW_TAG_enumeration_type) {
auto V = C.find(DW_AT_const_value);
Expand Down Expand Up @@ -523,9 +529,8 @@ struct DWARFTypePrinter {
continue;
auto TypeAttr = C.find(DW_AT_type);
Sep();
appendQualifiedName(TypeAttr
? C.getAttributeValueAsReferencedDie(*TypeAttr)
: DWARFDie());
appendQualifiedName(TypeAttr ? resolveReferencedType(C, *TypeAttr)
: DWARFDie());
}
if (IsTemplate && *FirstParameter && FirstParameter == &FirstParameterValue)
OS << '<';
Expand All @@ -534,15 +539,15 @@ struct DWARFTypePrinter {
void decomposeConstVolatile(DWARFDie &N, DWARFDie &T, DWARFDie &C,
DWARFDie &V) {
(N.getTag() == DW_TAG_const_type ? C : V) = N;
T = N.getAttributeValueAsReferencedDie(DW_AT_type);
T = resolveReferencedType(N);
if (T) {
auto Tag = T.getTag();
if (Tag == DW_TAG_const_type) {
C = T;
T = T.getAttributeValueAsReferencedDie(DW_AT_type);
T = resolveReferencedType(T);
} else if (Tag == DW_TAG_volatile_type) {
V = T;
T = T.getAttributeValueAsReferencedDie(DW_AT_type);
T = resolveReferencedType(T);
}
}
}
Expand All @@ -552,12 +557,10 @@ struct DWARFTypePrinter {
DWARFDie T;
decomposeConstVolatile(N, T, C, V);
if (T && T.getTag() == DW_TAG_subroutine_type)
appendSubroutineNameAfter(T,
T.getAttributeValueAsReferencedDie(DW_AT_type),
false, C.isValid(), V.isValid());
appendSubroutineNameAfter(T, resolveReferencedType(T), false, C.isValid(),
V.isValid());
else
appendUnqualifiedNameAfter(
T, T.getAttributeValueAsReferencedDie(DW_AT_type));
appendUnqualifiedNameAfter(T, resolveReferencedType(T));
}
void appendConstVolatileQualifierBefore(DWARFDie N) {
DWARFDie C;
Expand All @@ -567,7 +570,7 @@ struct DWARFTypePrinter {
bool Subroutine = T && T.getTag() == DW_TAG_subroutine_type;
DWARFDie A = T;
while (A && A.getTag() == DW_TAG_array_type)
A = A.getAttributeValueAsReferencedDie(DW_AT_type);
A = resolveReferencedType(A);
bool Leading =
(!A || (A.getTag() != DW_TAG_pointer_type &&
A.getTag() != llvm::dwarf::DW_TAG_ptr_to_member_type)) &&
Expand Down Expand Up @@ -611,7 +614,7 @@ struct DWARFTypePrinter {
for (DWARFDie P : D) {
if (P.getTag() != DW_TAG_formal_parameter)
return;
DWARFDie T = P.getAttributeValueAsReferencedDie(DW_AT_type);
DWARFDie T = resolveReferencedType(P);
if (SkipFirstParamIfArtificial && RealFirst && P.find(DW_AT_artificial)) {
FirstParamIfArtificial = T;
RealFirst = false;
Expand All @@ -631,7 +634,7 @@ struct DWARFTypePrinter {
DWARFDie C;
DWARFDie V;
auto CVStep = [&](DWARFDie CV) {
if (DWARFDie U = CV.getAttributeValueAsReferencedDie(DW_AT_type)) {
if (DWARFDie U = resolveReferencedType(CV)) {
if (U.getTag() == DW_TAG_const_type)
return C = U;
if (U.getTag() == DW_TAG_volatile_type)
Expand All @@ -658,8 +661,7 @@ struct DWARFTypePrinter {
OS << " &";
if (D.find(DW_AT_rvalue_reference))
OS << " &&";
appendUnqualifiedNameAfter(
Inner, Inner.getAttributeValueAsReferencedDie(DW_AT_type));
appendUnqualifiedNameAfter(Inner, resolveReferencedType(Inner));
}
void appendScopes(DWARFDie D) {
if (D.getTag() == DW_TAG_compile_unit)
Expand All @@ -670,6 +672,7 @@ struct DWARFTypePrinter {
return;
if (D.getTag() == DW_TAG_subprogram)
return;
D = D.resolveTypeUnitReference();
if (DWARFDie P = D.getParent())
appendScopes(P);
appendUnqualifiedName(D);
Expand Down Expand Up @@ -761,7 +764,7 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
DINameKind::LinkageName))
OS << Space << "\"" << Name << '\"';
} else if (Attr == DW_AT_type) {
DWARFDie D = Die.getAttributeValueAsReferencedDie(FormValue);
DWARFDie D = resolveReferencedType(Die, FormValue);
if (D && !D.isNULL()) {
OS << Space << "\"";
DWARFTypePrinter(OS).appendQualifiedName(D);
Expand Down Expand Up @@ -873,13 +876,27 @@ DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const {

DWARFDie
DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue &V) const {
DWARFDie Result;
if (auto SpecRef = V.getAsRelativeReference()) {
if (SpecRef->Unit)
return SpecRef->Unit->getDIEForOffset(SpecRef->Unit->getOffset() + SpecRef->Offset);
if (auto SpecUnit = U->getUnitVector().getUnitForOffset(SpecRef->Offset))
return SpecUnit->getDIEForOffset(SpecRef->Offset);
Result = SpecRef->Unit->getDIEForOffset(SpecRef->Unit->getOffset() +
SpecRef->Offset);
else if (auto SpecUnit =
U->getUnitVector().getUnitForOffset(SpecRef->Offset))
Result = SpecUnit->getDIEForOffset(SpecRef->Offset);
}
return DWARFDie();
return Result;
}

DWARFDie DWARFDie::resolveTypeUnitReference() const {
if (auto Attr = find(DW_AT_signature)) {
if (Optional<uint64_t> Sig = Attr->getAsReferenceUVal()) {
if (DWARFTypeUnit *TU =
U->getContext().getTypeUnitForHash(U->getVersion(), *Sig))
return TU->getDIEForOffset(TU->getTypeOffset() + TU->getOffset());
}
}
return *this;
}

Optional<uint64_t> DWARFDie::getRangesBaseAttribute() const {
Expand Down
Loading

0 comments on commit 58b1b64

Please sign in to comment.