summaryrefslogtreecommitdiff
path: root/third_party/llvm-project/DWARFAbbreviationDeclaration.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/llvm-project/DWARFAbbreviationDeclaration.cpp')
-rw-r--r--third_party/llvm-project/DWARFAbbreviationDeclaration.cpp215
1 files changed, 215 insertions, 0 deletions
diff --git a/third_party/llvm-project/DWARFAbbreviationDeclaration.cpp b/third_party/llvm-project/DWARFAbbreviationDeclaration.cpp
new file mode 100644
index 000000000..abbea3a86
--- /dev/null
+++ b/third_party/llvm-project/DWARFAbbreviationDeclaration.cpp
@@ -0,0 +1,215 @@
+//===- DWARFAbbreviationDeclaration.cpp -----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
+
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstddef>
+#include <cstdint>
+
+using namespace llvm;
+using namespace dwarf;
+
+void DWARFAbbreviationDeclaration::clear() {
+ Code = 0;
+ Tag = DW_TAG_null;
+ CodeByteSize = 0;
+ HasChildren = false;
+ AttributeSpecs.clear();
+ FixedAttributeSize.reset();
+}
+
+DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() {
+ clear();
+}
+
+bool
+DWARFAbbreviationDeclaration::extract(DataExtractor Data,
+ uint64_t* OffsetPtr) {
+ clear();
+ const uint64_t Offset = *OffsetPtr;
+ Code = Data.getULEB128(OffsetPtr);
+ if (Code == 0) {
+ return false;
+ }
+ CodeByteSize = *OffsetPtr - Offset;
+ Tag = static_cast<llvm::dwarf::Tag>(Data.getULEB128(OffsetPtr));
+ if (Tag == DW_TAG_null) {
+ clear();
+ return false;
+ }
+ uint8_t ChildrenByte = Data.getU8(OffsetPtr);
+ HasChildren = (ChildrenByte == DW_CHILDREN_yes);
+ // Assign a value to our optional FixedAttributeSize member variable. If
+ // this member variable still has a value after the while loop below, then
+ // all attribute data in this abbreviation declaration has a fixed byte size.
+ FixedAttributeSize = FixedSizeInfo();
+
+ // Read all of the abbreviation attributes and forms.
+ while (true) {
+ auto A = static_cast<Attribute>(Data.getULEB128(OffsetPtr));
+ auto F = static_cast<Form>(Data.getULEB128(OffsetPtr));
+ if (A && F) {
+ bool IsImplicitConst = (F == DW_FORM_implicit_const);
+ if (IsImplicitConst) {
+ int64_t V = Data.getSLEB128(OffsetPtr);
+ AttributeSpecs.push_back(AttributeSpec(A, F, V));
+ continue;
+ }
+ Optional<uint8_t> ByteSize;
+ // If this abbrevation still has a fixed byte size, then update the
+ // FixedAttributeSize as needed.
+ switch (F) {
+ case DW_FORM_addr:
+ if (FixedAttributeSize)
+ ++FixedAttributeSize->NumAddrs;
+ break;
+
+ case DW_FORM_ref_addr:
+ if (FixedAttributeSize)
+ ++FixedAttributeSize->NumRefAddrs;
+ break;
+
+ case DW_FORM_strp:
+ case DW_FORM_GNU_ref_alt:
+ case DW_FORM_GNU_strp_alt:
+ case DW_FORM_line_strp:
+ case DW_FORM_sec_offset:
+ case DW_FORM_strp_sup:
+ if (FixedAttributeSize)
+ ++FixedAttributeSize->NumDwarfOffsets;
+ break;
+
+ default:
+ // The form has a byte size that doesn't depend on Params.
+ // If it's a fixed size, keep track of it.
+ if ((ByteSize = dwarf::getFixedFormByteSize(F, dwarf::FormParams()))) {
+ if (FixedAttributeSize)
+ FixedAttributeSize->NumBytes += *ByteSize;
+ break;
+ }
+ // Indicate we no longer have a fixed byte size for this
+ // abbreviation by clearing the FixedAttributeSize optional value
+ // so it doesn't have a value.
+ FixedAttributeSize.reset();
+ break;
+ }
+ // Record this attribute and its fixed size if it has one.
+ AttributeSpecs.push_back(AttributeSpec(A, F, ByteSize));
+ } else if (A == 0 && F == 0) {
+ // We successfully reached the end of this abbreviation declaration
+ // since both attribute and form are zero.
+ break;
+ } else {
+ // Attribute and form pairs must either both be non-zero, in which case
+ // they are added to the abbreviation declaration, or both be zero to
+ // terminate the abbrevation declaration. In this case only one was
+ // zero which is an error.
+ clear();
+ return false;
+ }
+ }
+ return true;
+}
+
+void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const {
+ OS << '[' << getCode() << "] ";
+ OS << formatv("{0}", getTag());
+ OS << "\tDW_CHILDREN_" << (hasChildren() ? "yes" : "no") << '\n';
+ for (const AttributeSpec &Spec : AttributeSpecs) {
+ OS << formatv("\t{0}\t{1}", Spec.Attr, Spec.Form);
+ if (Spec.isImplicitConst())
+ OS << '\t' << Spec.getImplicitConstValue();
+ OS << '\n';
+ }
+ OS << '\n';
+}
+
+Optional<uint32_t>
+DWARFAbbreviationDeclaration::findAttributeIndex(dwarf::Attribute Attr) const {
+ for (uint32_t i = 0, e = AttributeSpecs.size(); i != e; ++i) {
+ if (AttributeSpecs[i].Attr == Attr)
+ return i;
+ }
+ return None;
+}
+
+Optional<DWARFFormValue> DWARFAbbreviationDeclaration::getAttributeValue(
+ const uint64_t DIEOffset, const dwarf::Attribute Attr,
+ const DWARFUnit &U) const {
+ Optional<uint32_t> MatchAttrIndex = findAttributeIndex(Attr);
+ if (!MatchAttrIndex)
+ return None;
+
+ auto DebugInfoData = U.getDebugInfoExtractor();
+
+ // Add the byte size of ULEB that for the abbrev Code so we can start
+ // skipping the attribute data.
+ uint64_t Offset = DIEOffset + CodeByteSize;
+ uint32_t AttrIndex = 0;
+ for (const auto &Spec : AttributeSpecs) {
+ if (*MatchAttrIndex == AttrIndex) {
+ // We have arrived at the attribute to extract, extract if from Offset.
+ if (Spec.isImplicitConst())
+ return DWARFFormValue::createFromSValue(Spec.Form,
+ Spec.getImplicitConstValue());
+
+ DWARFFormValue FormValue(Spec.Form);
+ if (FormValue.extractValue(DebugInfoData, &Offset, U.getFormParams(), &U))
+ return FormValue;
+ }
+ // March Offset along until we get to the attribute we want.
+ if (auto FixedSize = Spec.getByteSize(U))
+ Offset += *FixedSize;
+ else
+ DWARFFormValue::skipValue(Spec.Form, DebugInfoData, &Offset,
+ U.getFormParams());
+ ++AttrIndex;
+ }
+ return None;
+}
+
+size_t DWARFAbbreviationDeclaration::FixedSizeInfo::getByteSize(
+ const DWARFUnit &U) const {
+ size_t ByteSize = NumBytes;
+ if (NumAddrs)
+ ByteSize += NumAddrs * U.getAddressByteSize();
+ if (NumRefAddrs)
+ ByteSize += NumRefAddrs * U.getRefAddrByteSize();
+ if (NumDwarfOffsets)
+ ByteSize += NumDwarfOffsets * U.getDwarfOffsetByteSize();
+ return ByteSize;
+}
+
+Optional<int64_t> DWARFAbbreviationDeclaration::AttributeSpec::getByteSize(
+ const DWARFUnit &U) const {
+ if (isImplicitConst())
+ return 0;
+ if (ByteSize.HasByteSize)
+ return ByteSize.ByteSize;
+ Optional<int64_t> S;
+ auto FixedByteSize = dwarf::getFixedFormByteSize(Form, U.getFormParams());
+ if (FixedByteSize)
+ S = *FixedByteSize;
+ return S;
+}
+
+Optional<size_t> DWARFAbbreviationDeclaration::getFixedAttributesByteSize(
+ const DWARFUnit &U) const {
+ if (FixedAttributeSize)
+ return FixedAttributeSize->getByteSize(U);
+ return None;
+}