123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- //===- 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;
- }
- uint64_t DWARFAbbreviationDeclaration::getAttributeOffsetFromIndex(
- uint32_t AttrIndex, uint64_t DIEOffset, const DWARFUnit &U) const {
- DWARFDataExtractor 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;
- for (uint32_t CurAttrIdx = 0; CurAttrIdx != AttrIndex; ++CurAttrIdx)
- // Match Offset along until we get to the attribute we want.
- if (auto FixedSize = AttributeSpecs[CurAttrIdx].getByteSize(U))
- Offset += *FixedSize;
- else
- DWARFFormValue::skipValue(AttributeSpecs[CurAttrIdx].Form, DebugInfoData,
- &Offset, U.getFormParams());
- return Offset;
- }
- Optional<DWARFFormValue>
- DWARFAbbreviationDeclaration::getAttributeValueFromOffset(
- uint32_t AttrIndex, uint64_t Offset, const DWARFUnit &U) const {
- assert(AttributeSpecs.size() > AttrIndex &&
- "Attribute Index is out of bounds.");
- // We have arrived at the attribute to extract, extract if from Offset.
- const AttributeSpec &Spec = AttributeSpecs[AttrIndex];
- if (Spec.isImplicitConst())
- return DWARFFormValue::createFromSValue(Spec.Form,
- Spec.getImplicitConstValue());
- DWARFFormValue FormValue(Spec.Form);
- DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor();
- if (FormValue.extractValue(DebugInfoData, &Offset, U.getFormParams(), &U))
- return FormValue;
- return None;
- }
- Optional<DWARFFormValue>
- DWARFAbbreviationDeclaration::getAttributeValue(const uint64_t DIEOffset,
- const dwarf::Attribute Attr,
- const DWARFUnit &U) const {
- // Check if this abbreviation has this attribute without needing to skip
- // any data so we can return quickly if it doesn't.
- Optional<uint32_t> MatchAttrIndex = findAttributeIndex(Attr);
- if (!MatchAttrIndex)
- return None;
- uint64_t Offset = getAttributeOffsetFromIndex(*MatchAttrIndex, DIEOffset, U);
- return getAttributeValueFromOffset(*MatchAttrIndex, Offset, U);
- }
- 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;
- }
|