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