Home | History | Annotate | Line # | Download | only in DWARF
      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-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 
      9 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
     10 
     11 #include "llvm/ADT/None.h"
     12 #include "llvm/ADT/Optional.h"
     13 #include "llvm/BinaryFormat/Dwarf.h"
     14 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
     15 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
     16 #include "llvm/Support/DataExtractor.h"
     17 #include "llvm/Support/Format.h"
     18 #include "llvm/Support/FormatVariadic.h"
     19 #include "llvm/Support/raw_ostream.h"
     20 #include <cstddef>
     21 #include <cstdint>
     22 
     23 using namespace llvm;
     24 using namespace dwarf;
     25 
     26 void DWARFAbbreviationDeclaration::clear() {
     27   Code = 0;
     28   Tag = DW_TAG_null;
     29   CodeByteSize = 0;
     30   HasChildren = false;
     31   AttributeSpecs.clear();
     32   FixedAttributeSize.reset();
     33 }
     34 
     35 DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() {
     36   clear();
     37 }
     38 
     39 bool
     40 DWARFAbbreviationDeclaration::extract(DataExtractor Data,
     41                                       uint64_t* OffsetPtr) {
     42   clear();
     43   const uint64_t Offset = *OffsetPtr;
     44   Code = Data.getULEB128(OffsetPtr);
     45   if (Code == 0) {
     46     return false;
     47   }
     48   CodeByteSize = *OffsetPtr - Offset;
     49   Tag = static_cast<llvm::dwarf::Tag>(Data.getULEB128(OffsetPtr));
     50   if (Tag == DW_TAG_null) {
     51     clear();
     52     return false;
     53   }
     54   uint8_t ChildrenByte = Data.getU8(OffsetPtr);
     55   HasChildren = (ChildrenByte == DW_CHILDREN_yes);
     56   // Assign a value to our optional FixedAttributeSize member variable. If
     57   // this member variable still has a value after the while loop below, then
     58   // all attribute data in this abbreviation declaration has a fixed byte size.
     59   FixedAttributeSize = FixedSizeInfo();
     60 
     61   // Read all of the abbreviation attributes and forms.
     62   while (true) {
     63     auto A = static_cast<Attribute>(Data.getULEB128(OffsetPtr));
     64     auto F = static_cast<Form>(Data.getULEB128(OffsetPtr));
     65     if (A && F) {
     66       bool IsImplicitConst = (F == DW_FORM_implicit_const);
     67       if (IsImplicitConst) {
     68         int64_t V = Data.getSLEB128(OffsetPtr);
     69         AttributeSpecs.push_back(AttributeSpec(A, F, V));
     70         continue;
     71       }
     72       Optional<uint8_t> ByteSize;
     73       // If this abbrevation still has a fixed byte size, then update the
     74       // FixedAttributeSize as needed.
     75       switch (F) {
     76       case DW_FORM_addr:
     77         if (FixedAttributeSize)
     78           ++FixedAttributeSize->NumAddrs;
     79         break;
     80 
     81       case DW_FORM_ref_addr:
     82         if (FixedAttributeSize)
     83           ++FixedAttributeSize->NumRefAddrs;
     84         break;
     85 
     86       case DW_FORM_strp:
     87       case DW_FORM_GNU_ref_alt:
     88       case DW_FORM_GNU_strp_alt:
     89       case DW_FORM_line_strp:
     90       case DW_FORM_sec_offset:
     91       case DW_FORM_strp_sup:
     92         if (FixedAttributeSize)
     93           ++FixedAttributeSize->NumDwarfOffsets;
     94         break;
     95 
     96       default:
     97         // The form has a byte size that doesn't depend on Params.
     98         // If it's a fixed size, keep track of it.
     99         if ((ByteSize = dwarf::getFixedFormByteSize(F, dwarf::FormParams()))) {
    100           if (FixedAttributeSize)
    101             FixedAttributeSize->NumBytes += *ByteSize;
    102           break;
    103         }
    104         // Indicate we no longer have a fixed byte size for this
    105         // abbreviation by clearing the FixedAttributeSize optional value
    106         // so it doesn't have a value.
    107         FixedAttributeSize.reset();
    108         break;
    109       }
    110       // Record this attribute and its fixed size if it has one.
    111       AttributeSpecs.push_back(AttributeSpec(A, F, ByteSize));
    112     } else if (A == 0 && F == 0) {
    113       // We successfully reached the end of this abbreviation declaration
    114       // since both attribute and form are zero.
    115       break;
    116     } else {
    117       // Attribute and form pairs must either both be non-zero, in which case
    118       // they are added to the abbreviation declaration, or both be zero to
    119       // terminate the abbrevation declaration. In this case only one was
    120       // zero which is an error.
    121       clear();
    122       return false;
    123     }
    124   }
    125   return true;
    126 }
    127 
    128 void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const {
    129   OS << '[' << getCode() << "] ";
    130   OS << formatv("{0}", getTag());
    131   OS << "\tDW_CHILDREN_" << (hasChildren() ? "yes" : "no") << '\n';
    132   for (const AttributeSpec &Spec : AttributeSpecs) {
    133     OS << formatv("\t{0}\t{1}", Spec.Attr, Spec.Form);
    134     if (Spec.isImplicitConst())
    135       OS << '\t' << Spec.getImplicitConstValue();
    136     OS << '\n';
    137   }
    138   OS << '\n';
    139 }
    140 
    141 Optional<uint32_t>
    142 DWARFAbbreviationDeclaration::findAttributeIndex(dwarf::Attribute Attr) const {
    143   for (uint32_t i = 0, e = AttributeSpecs.size(); i != e; ++i) {
    144     if (AttributeSpecs[i].Attr == Attr)
    145       return i;
    146   }
    147   return None;
    148 }
    149 
    150 Optional<DWARFFormValue> DWARFAbbreviationDeclaration::getAttributeValue(
    151     const uint64_t DIEOffset, const dwarf::Attribute Attr,
    152     const DWARFUnit &U) const {
    153   // Check if this abbreviation has this attribute without needing to skip
    154   // any data so we can return quickly if it doesn't.
    155   Optional<uint32_t> MatchAttrIndex = findAttributeIndex(Attr);
    156   if (!MatchAttrIndex)
    157     return None;
    158 
    159   auto DebugInfoData = U.getDebugInfoExtractor();
    160 
    161   // Add the byte size of ULEB that for the abbrev Code so we can start
    162   // skipping the attribute data.
    163   uint64_t Offset = DIEOffset + CodeByteSize;
    164   for (uint32_t CurAttrIdx = 0; CurAttrIdx != *MatchAttrIndex; ++CurAttrIdx)
    165     // Match Offset along until we get to the attribute we want.
    166     if (auto FixedSize = AttributeSpecs[CurAttrIdx].getByteSize(U))
    167       Offset += *FixedSize;
    168     else
    169       DWARFFormValue::skipValue(AttributeSpecs[CurAttrIdx].Form, DebugInfoData,
    170                                 &Offset, U.getFormParams());
    171 
    172   // We have arrived at the attribute to extract, extract if from Offset.
    173   const AttributeSpec &Spec = AttributeSpecs[*MatchAttrIndex];
    174   if (Spec.isImplicitConst())
    175     return DWARFFormValue::createFromSValue(Spec.Form,
    176                                             Spec.getImplicitConstValue());
    177 
    178   DWARFFormValue FormValue(Spec.Form);
    179   if (FormValue.extractValue(DebugInfoData, &Offset, U.getFormParams(), &U))
    180     return FormValue;
    181 
    182   return None;
    183 }
    184 
    185 size_t DWARFAbbreviationDeclaration::FixedSizeInfo::getByteSize(
    186     const DWARFUnit &U) const {
    187   size_t ByteSize = NumBytes;
    188   if (NumAddrs)
    189     ByteSize += NumAddrs * U.getAddressByteSize();
    190   if (NumRefAddrs)
    191     ByteSize += NumRefAddrs * U.getRefAddrByteSize();
    192   if (NumDwarfOffsets)
    193     ByteSize += NumDwarfOffsets * U.getDwarfOffsetByteSize();
    194   return ByteSize;
    195 }
    196 
    197 Optional<int64_t> DWARFAbbreviationDeclaration::AttributeSpec::getByteSize(
    198     const DWARFUnit &U) const {
    199   if (isImplicitConst())
    200     return 0;
    201   if (ByteSize.HasByteSize)
    202     return ByteSize.ByteSize;
    203   Optional<int64_t> S;
    204   auto FixedByteSize = dwarf::getFixedFormByteSize(Form, U.getFormParams());
    205   if (FixedByteSize)
    206     S = *FixedByteSize;
    207   return S;
    208 }
    209 
    210 Optional<size_t> DWARFAbbreviationDeclaration::getFixedAttributesByteSize(
    211     const DWARFUnit &U) const {
    212   if (FixedAttributeSize)
    213     return FixedAttributeSize->getByteSize(U);
    214   return None;
    215 }
    216