aboutsummaryrefslogtreecommitdiff
path: root/lib/DebugInfo/DWARF/DWARFDie.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/DebugInfo/DWARF/DWARFDie.cpp')
-rw-r--r--lib/DebugInfo/DWARF/DWARFDie.cpp196
1 files changed, 117 insertions, 79 deletions
diff --git a/lib/DebugInfo/DWARF/DWARFDie.cpp b/lib/DebugInfo/DWARF/DWARFDie.cpp
index 89b83b11ab68..4308cc2e2639 100644
--- a/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ b/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -1,4 +1,4 @@
-//===-- DWARFDie.cpp ------------------------------------------------------===//
+//===- DWARFDie.cpp -------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,25 +7,33 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "SyntaxHighlighting.h"
-#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
-#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
-#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
+#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
-#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/Debug.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cinttypes>
+#include <cstdint>
+#include <string>
+#include <utility>
using namespace llvm;
using namespace dwarf;
using namespace syntax;
-namespace {
- static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) {
+static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) {
OS << " (";
do {
uint64_t Shift = countTrailingZeros(Val);
@@ -122,8 +130,6 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
OS << ")\n";
}
-} // end anonymous namespace
-
bool DWARFDie::isSubprogramDIE() const {
return getTag() == DW_TAG_subprogram;
}
@@ -134,7 +140,7 @@ bool DWARFDie::isSubroutineDIE() const {
}
Optional<DWARFFormValue>
-DWARFDie::getAttributeValue(dwarf::Attribute Attr) const {
+DWARFDie::find(dwarf::Attribute Attr) const {
if (!isValid())
return None;
auto AbbrevDecl = getAbbreviationDeclarationPtr();
@@ -143,54 +149,41 @@ DWARFDie::getAttributeValue(dwarf::Attribute Attr) const {
return None;
}
-const char *DWARFDie::getAttributeValueAsString(dwarf::Attribute Attr,
- const char *FailValue) const {
- auto FormValue = getAttributeValue(Attr);
- if (!FormValue)
- return FailValue;
- Optional<const char *> Result = FormValue->getAsCString();
- return Result.hasValue() ? Result.getValue() : FailValue;
-}
-
-Optional<uint64_t>
-DWARFDie::getAttributeValueAsAddress(dwarf::Attribute Attr) const {
- if (auto FormValue = getAttributeValue(Attr))
- return FormValue->getAsAddress();
- return None;
-}
-
-Optional<int64_t>
-DWARFDie::getAttributeValueAsSignedConstant(dwarf::Attribute Attr) const {
- if (auto FormValue = getAttributeValue(Attr))
- return FormValue->getAsSignedConstant();
- return None;
-}
-
-Optional<uint64_t>
-DWARFDie::getAttributeValueAsUnsignedConstant(dwarf::Attribute Attr) const {
- if (auto FormValue = getAttributeValue(Attr))
- return FormValue->getAsUnsignedConstant();
- return None;
-}
-
-Optional<uint64_t>
-DWARFDie::getAttributeValueAsReference(dwarf::Attribute Attr) const {
- if (auto FormValue = getAttributeValue(Attr))
- return FormValue->getAsReference();
+Optional<DWARFFormValue>
+DWARFDie::find(ArrayRef<dwarf::Attribute> Attrs) const {
+ if (!isValid())
+ return None;
+ auto AbbrevDecl = getAbbreviationDeclarationPtr();
+ if (AbbrevDecl) {
+ for (auto Attr : Attrs) {
+ if (auto Value = AbbrevDecl->getAttributeValue(getOffset(), Attr, *U))
+ return Value;
+ }
+ }
return None;
}
-Optional<uint64_t>
-DWARFDie::getAttributeValueAsSectionOffset(dwarf::Attribute Attr) const {
- if (auto FormValue = getAttributeValue(Attr))
- return FormValue->getAsSectionOffset();
+Optional<DWARFFormValue>
+DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const {
+ if (!isValid())
+ return None;
+ auto Die = *this;
+ if (auto Value = Die.find(Attrs))
+ return Value;
+ if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
+ Die = D;
+ if (auto Value = Die.find(Attrs))
+ return Value;
+ if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_specification))
+ Die = D;
+ if (auto Value = Die.find(Attrs))
+ return Value;
return None;
}
-
DWARFDie
DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const {
- auto SpecRef = getAttributeValueAsReference(Attr);
+ auto SpecRef = toReference(find(Attr));
if (SpecRef) {
auto SpecUnit = U->getUnitSection().getUnitForOffset(*SpecRef);
if (SpecUnit)
@@ -201,14 +194,11 @@ DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const {
Optional<uint64_t>
DWARFDie::getRangesBaseAttribute() const {
- auto Result = getAttributeValueAsSectionOffset(DW_AT_rnglists_base);
- if (Result)
- return Result;
- return getAttributeValueAsSectionOffset(DW_AT_GNU_ranges_base);
+ return toSectionOffset(find({DW_AT_rnglists_base, DW_AT_GNU_ranges_base}));
}
Optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const {
- if (auto FormValue = getAttributeValue(DW_AT_high_pc)) {
+ if (auto FormValue = find(DW_AT_high_pc)) {
if (auto Address = FormValue->getAsAddress()) {
// High PC is an address.
return Address;
@@ -222,7 +212,7 @@ Optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const {
}
bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC) const {
- auto LowPcAddr = getAttributeValueAsAddress(DW_AT_low_pc);
+ auto LowPcAddr = toAddress(find(DW_AT_low_pc));
if (!LowPcAddr)
return false;
if (auto HighPcAddr = getHighPC(*LowPcAddr)) {
@@ -243,7 +233,7 @@ DWARFDie::getAddressRanges() const {
return DWARFAddressRangesVector(1, std::make_pair(LowPC, HighPC));
}
// Multiple ranges from .debug_ranges section.
- auto RangesOffset = getAttributeValueAsSectionOffset(DW_AT_ranges);
+ auto RangesOffset = toSectionOffset(find(DW_AT_ranges));
if (RangesOffset) {
DWARFDebugRangeList RangeList;
if (U->extractRangeList(*RangesOffset, RangeList))
@@ -284,33 +274,26 @@ const char *
DWARFDie::getName(DINameKind Kind) const {
if (!isValid() || Kind == DINameKind::None)
return nullptr;
- const char *name = nullptr;
// Try to get mangled name only if it was asked for.
if (Kind == DINameKind::LinkageName) {
- if ((name = getAttributeValueAsString(DW_AT_MIPS_linkage_name, nullptr)))
- return name;
- if ((name = getAttributeValueAsString(DW_AT_linkage_name, nullptr)))
- return name;
+ if (auto Name = dwarf::toString(findRecursively({DW_AT_MIPS_linkage_name,
+ DW_AT_linkage_name}), nullptr))
+ return Name;
}
- if ((name = getAttributeValueAsString(DW_AT_name, nullptr)))
- return name;
- // Try to get name from specification DIE.
- DWARFDie SpecDie = getAttributeValueAsReferencedDie(DW_AT_specification);
- if (SpecDie && (name = SpecDie.getName(Kind)))
- return name;
- // Try to get name from abstract origin DIE.
- DWARFDie AbsDie = getAttributeValueAsReferencedDie(DW_AT_abstract_origin);
- if (AbsDie && (name = AbsDie.getName(Kind)))
- return name;
+ if (auto Name = dwarf::toString(findRecursively(DW_AT_name), nullptr))
+ return Name;
return nullptr;
}
+uint64_t DWARFDie::getDeclLine() const {
+ return toUnsigned(findRecursively(DW_AT_decl_line), 0);
+}
+
void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,
uint32_t &CallColumn) const {
- CallFile = getAttributeValueAsUnsignedConstant(DW_AT_call_file).getValueOr(0);
- CallLine = getAttributeValueAsUnsignedConstant(DW_AT_call_line).getValueOr(0);
- CallColumn =
- getAttributeValueAsUnsignedConstant(DW_AT_call_column).getValueOr(0);
+ CallFile = toUnsigned(find(DW_AT_call_file), 0);
+ CallLine = toUnsigned(find(DW_AT_call_line), 0);
+ CallColumn = toUnsigned(find(DW_AT_call_column), 0);
}
void DWARFDie::dump(raw_ostream &OS, unsigned RecurseDepth,
@@ -340,6 +323,12 @@ void DWARFDie::dump(raw_ostream &OS, unsigned RecurseDepth,
// Dump all data in the DIE for the attributes.
for (const auto &AttrSpec : AbbrevDecl->attributes()) {
+ if (AttrSpec.Form == DW_FORM_implicit_const) {
+ // We are dumping .debug_info section ,
+ // implicit_const attribute values are not really stored here,
+ // but in .debug_abbrev section. So we just skip such attrs.
+ continue;
+ }
dumpAttribute(OS, *this, &offset, AttrSpec.Attr, AttrSpec.Form,
Indent);
}
@@ -361,7 +350,6 @@ void DWARFDie::dump(raw_ostream &OS, unsigned RecurseDepth,
}
}
-
void DWARFDie::getInlinedChainForAddress(
const uint64_t Address, SmallVectorImpl<DWARFDie> &InlinedChain) const {
if (isNULL())
@@ -399,3 +387,53 @@ DWARFDie DWARFDie::getSibling() const {
return U->getSibling(Die);
return DWARFDie();
}
+
+iterator_range<DWARFDie::attribute_iterator>
+DWARFDie::attributes() const {
+ return make_range(attribute_iterator(*this, false),
+ attribute_iterator(*this, true));
+}
+
+DWARFDie::attribute_iterator::attribute_iterator(DWARFDie D, bool End) :
+ Die(D), AttrValue(0), Index(0) {
+ auto AbbrDecl = Die.getAbbreviationDeclarationPtr();
+ assert(AbbrDecl && "Must have abbreviation declaration");
+ if (End) {
+ // This is the end iterator so we set the index to the attribute count.
+ Index = AbbrDecl->getNumAttributes();
+ } else {
+ // This is the begin iterator so we extract the value for this->Index.
+ AttrValue.Offset = D.getOffset() + AbbrDecl->getCodeByteSize();
+ updateForIndex(*AbbrDecl, 0);
+ }
+}
+
+void DWARFDie::attribute_iterator::updateForIndex(
+ const DWARFAbbreviationDeclaration &AbbrDecl, uint32_t I) {
+ Index = I;
+ // AbbrDecl must be valid befor calling this function.
+ auto NumAttrs = AbbrDecl.getNumAttributes();
+ if (Index < NumAttrs) {
+ AttrValue.Attr = AbbrDecl.getAttrByIndex(Index);
+ // Add the previous byte size of any previous attribute value.
+ AttrValue.Offset += AttrValue.ByteSize;
+ AttrValue.Value.setForm(AbbrDecl.getFormByIndex(Index));
+ uint32_t ParseOffset = AttrValue.Offset;
+ auto U = Die.getDwarfUnit();
+ assert(U && "Die must have valid DWARF unit");
+ bool b = AttrValue.Value.extractValue(U->getDebugInfoExtractor(),
+ &ParseOffset, U);
+ (void)b;
+ assert(b && "extractValue cannot fail on fully parsed DWARF");
+ AttrValue.ByteSize = ParseOffset - AttrValue.Offset;
+ } else {
+ assert(Index == NumAttrs && "Indexes should be [0, NumAttrs) only");
+ AttrValue.clear();
+ }
+}
+
+DWARFDie::attribute_iterator &DWARFDie::attribute_iterator::operator++() {
+ if (auto AbbrDecl = Die.getAbbreviationDeclarationPtr())
+ updateForIndex(*AbbrDecl, Index + 1);
+ return *this;
+}