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