brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.5 KiB · ecdbd00 Raw
252 lines · cpp
1//===- DWARFAbbreviationDeclaration.cpp -----------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"10 11#include "llvm/BinaryFormat/Dwarf.h"12#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"13#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"14#include "llvm/DebugInfo/DWARF/DWARFUnit.h"15#include "llvm/Support/DataExtractor.h"16#include "llvm/Support/FormatVariadic.h"17#include "llvm/Support/raw_ostream.h"18#include <cstddef>19#include <cstdint>20 21using namespace llvm;22using namespace dwarf;23 24void DWARFAbbreviationDeclaration::clear() {25  Code = 0;26  Tag = DW_TAG_null;27  CodeByteSize = 0;28  HasChildren = false;29  AttributeSpecs.clear();30  FixedAttributeSize.reset();31}32 33DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() {34  clear();35}36 37llvm::Expected<DWARFAbbreviationDeclaration::ExtractState>38DWARFAbbreviationDeclaration::extract(DataExtractor Data, uint64_t *OffsetPtr) {39  clear();40  const uint64_t Offset = *OffsetPtr;41  Error Err = Error::success();42  Code = Data.getULEB128(OffsetPtr, &Err);43  if (Err)44    return std::move(Err);45 46  if (Code == 0)47    return ExtractState::Complete;48 49  CodeByteSize = *OffsetPtr - Offset;50  Tag = static_cast<llvm::dwarf::Tag>(Data.getULEB128(OffsetPtr, &Err));51  if (Err)52    return std::move(Err);53 54  if (Tag == DW_TAG_null) {55    clear();56    return make_error<llvm::object::GenericBinaryError>(57        "abbreviation declaration requires a non-null tag");58  }59  uint8_t ChildrenByte = Data.getU8(OffsetPtr, &Err);60  if (Err)61    return std::move(Err);62 63  HasChildren = (ChildrenByte == DW_CHILDREN_yes);64  // Assign a value to our optional FixedAttributeSize member variable. If65  // this member variable still has a value after the while loop below, then66  // all attribute data in this abbreviation declaration has a fixed byte size.67  FixedAttributeSize = FixedSizeInfo();68 69  // Read all of the abbreviation attributes and forms.70  while (Data.isValidOffset(*OffsetPtr)) {71    auto A = static_cast<Attribute>(Data.getULEB128(OffsetPtr, &Err));72    if (Err)73      return std::move(Err);74 75    auto F = static_cast<Form>(Data.getULEB128(OffsetPtr, &Err));76    if (Err)77      return std::move(Err);78 79    // We successfully reached the end of this abbreviation declaration80    // since both attribute and form are zero. There may be more abbreviation81    // declarations afterwards.82    if (!A && !F)83      return ExtractState::MoreItems;84 85    if (!A || !F) {86      // Attribute and form pairs must either both be non-zero, in which case87      // they are added to the abbreviation declaration, or both be zero to88      // terminate the abbrevation declaration. In this case only one was89      // zero which is an error.90      clear();91      return make_error<llvm::object::GenericBinaryError>(92          "malformed abbreviation declaration attribute. Either the attribute "93          "or the form is zero while the other is not");94    }95 96    bool IsImplicitConst = (F == DW_FORM_implicit_const);97    if (IsImplicitConst) {98      int64_t V = Data.getSLEB128(OffsetPtr);99      AttributeSpecs.push_back(AttributeSpec(A, F, V));100      continue;101    }102    std::optional<uint8_t> ByteSize;103    // If this abbrevation still has a fixed byte size, then update the104    // FixedAttributeSize as needed.105    switch (F) {106    case DW_FORM_addr:107      if (FixedAttributeSize)108        ++FixedAttributeSize->NumAddrs;109      break;110 111    case DW_FORM_ref_addr:112      if (FixedAttributeSize)113        ++FixedAttributeSize->NumRefAddrs;114      break;115 116    case DW_FORM_strp:117    case DW_FORM_GNU_ref_alt:118    case DW_FORM_GNU_strp_alt:119    case DW_FORM_line_strp:120    case DW_FORM_sec_offset:121    case DW_FORM_strp_sup:122      if (FixedAttributeSize)123        ++FixedAttributeSize->NumDwarfOffsets;124      break;125 126    default:127      // The form has a byte size that doesn't depend on Params.128      // If it's a fixed size, keep track of it.129      if ((ByteSize = dwarf::getFixedFormByteSize(F, dwarf::FormParams()))) {130        if (FixedAttributeSize)131          FixedAttributeSize->NumBytes += *ByteSize;132        break;133      }134      // Indicate we no longer have a fixed byte size for this135      // abbreviation by clearing the FixedAttributeSize optional value136      // so it doesn't have a value.137      FixedAttributeSize.reset();138      break;139    }140    // Record this attribute and its fixed size if it has one.141    AttributeSpecs.push_back(AttributeSpec(A, F, ByteSize));142  }143  return make_error<llvm::object::GenericBinaryError>(144      "abbreviation declaration attribute list was not terminated with a null "145      "entry");146}147 148void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const {149  OS << '[' << getCode() << "] ";150  OS << formatv("{0}", getTag());151  OS << "\tDW_CHILDREN_" << (hasChildren() ? "yes" : "no") << '\n';152  for (const AttributeSpec &Spec : AttributeSpecs) {153    OS << formatv("\t{0}\t{1}", Spec.Attr, Spec.Form);154    if (Spec.isImplicitConst())155      OS << '\t' << Spec.getImplicitConstValue();156    OS << '\n';157  }158  OS << '\n';159}160 161std::optional<uint32_t>162DWARFAbbreviationDeclaration::findAttributeIndex(dwarf::Attribute Attr) const {163  for (uint32_t i = 0, e = AttributeSpecs.size(); i != e; ++i) {164    if (AttributeSpecs[i].Attr == Attr)165      return i;166  }167  return std::nullopt;168}169 170uint64_t DWARFAbbreviationDeclaration::getAttributeOffsetFromIndex(171    uint32_t AttrIndex, uint64_t DIEOffset, const DWARFUnit &U) const {172  DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor();173 174  // Add the byte size of ULEB that for the abbrev Code so we can start175  // skipping the attribute data.176  uint64_t Offset = DIEOffset + CodeByteSize;177  for (uint32_t CurAttrIdx = 0; CurAttrIdx != AttrIndex; ++CurAttrIdx)178    // Match Offset along until we get to the attribute we want.179    if (auto FixedSize = AttributeSpecs[CurAttrIdx].getByteSize(U))180      Offset += *FixedSize;181    else182      DWARFFormValue::skipValue(AttributeSpecs[CurAttrIdx].Form, DebugInfoData,183                                &Offset, U.getFormParams());184  return Offset;185}186 187std::optional<DWARFFormValue>188DWARFAbbreviationDeclaration::getAttributeValueFromOffset(189    uint32_t AttrIndex, uint64_t Offset, const DWARFUnit &U) const {190  assert(AttributeSpecs.size() > AttrIndex &&191         "Attribute Index is out of bounds.");192 193  // We have arrived at the attribute to extract, extract if from Offset.194  const AttributeSpec &Spec = AttributeSpecs[AttrIndex];195  if (Spec.isImplicitConst())196    return DWARFFormValue::createFromSValue(Spec.Form,197                                            Spec.getImplicitConstValue());198 199  DWARFFormValue FormValue(Spec.Form);200  DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor();201  if (FormValue.extractValue(DebugInfoData, &Offset, U.getFormParams(), &U))202    return FormValue;203  return std::nullopt;204}205 206std::optional<DWARFFormValue>207DWARFAbbreviationDeclaration::getAttributeValue(const uint64_t DIEOffset,208                                                const dwarf::Attribute Attr,209                                                const DWARFUnit &U) const {210  // Check if this abbreviation has this attribute without needing to skip211  // any data so we can return quickly if it doesn't.212  std::optional<uint32_t> MatchAttrIndex = findAttributeIndex(Attr);213  if (!MatchAttrIndex)214    return std::nullopt;215 216  uint64_t Offset = getAttributeOffsetFromIndex(*MatchAttrIndex, DIEOffset, U);217 218  return getAttributeValueFromOffset(*MatchAttrIndex, Offset, U);219}220 221size_t DWARFAbbreviationDeclaration::FixedSizeInfo::getByteSize(222    const DWARFUnit &U) const {223  size_t ByteSize = NumBytes;224  if (NumAddrs)225    ByteSize += NumAddrs * U.getAddressByteSize();226  if (NumRefAddrs)227    ByteSize += NumRefAddrs * U.getRefAddrByteSize();228  if (NumDwarfOffsets)229    ByteSize += NumDwarfOffsets * U.getDwarfOffsetByteSize();230  return ByteSize;231}232 233std::optional<int64_t> DWARFAbbreviationDeclaration::AttributeSpec::getByteSize(234    const DWARFUnit &U) const {235  if (isImplicitConst())236    return 0;237  if (ByteSize.HasByteSize)238    return ByteSize.ByteSize;239  std::optional<int64_t> S;240  auto FixedByteSize = dwarf::getFixedFormByteSize(Form, U.getFormParams());241  if (FixedByteSize)242    S = *FixedByteSize;243  return S;244}245 246std::optional<size_t> DWARFAbbreviationDeclaration::getFixedAttributesByteSize(247    const DWARFUnit &U) const {248  if (FixedAttributeSize)249    return FixedAttributeSize->getByteSize(U);250  return std::nullopt;251}252