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 uint64_t DWARFAbbreviationDeclaration::getAttributeOffsetFromIndex( 151 uint32_t AttrIndex, uint64_t DIEOffset, const DWARFUnit &U) const { 152 DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor(); 153 154 // Add the byte size of ULEB that for the abbrev Code so we can start 155 // skipping the attribute data. 156 uint64_t Offset = DIEOffset + CodeByteSize; 157 for (uint32_t CurAttrIdx = 0; CurAttrIdx != AttrIndex; ++CurAttrIdx) 158 // Match Offset along until we get to the attribute we want. 159 if (auto FixedSize = AttributeSpecs[CurAttrIdx].getByteSize(U)) 160 Offset += *FixedSize; 161 else 162 DWARFFormValue::skipValue(AttributeSpecs[CurAttrIdx].Form, DebugInfoData, 163 &Offset, U.getFormParams()); 164 return Offset; 165 } 166 167 Optional<DWARFFormValue> 168 DWARFAbbreviationDeclaration::getAttributeValueFromOffset( 169 uint32_t AttrIndex, uint64_t Offset, const DWARFUnit &U) const { 170 assert(AttributeSpecs.size() > AttrIndex && 171 "Attribute Index is out of bounds."); 172 173 // We have arrived at the attribute to extract, extract if from Offset. 174 const AttributeSpec &Spec = AttributeSpecs[AttrIndex]; 175 if (Spec.isImplicitConst()) 176 return DWARFFormValue::createFromSValue(Spec.Form, 177 Spec.getImplicitConstValue()); 178 179 DWARFFormValue FormValue(Spec.Form); 180 DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor(); 181 if (FormValue.extractValue(DebugInfoData, &Offset, U.getFormParams(), &U)) 182 return FormValue; 183 return None; 184 } 185 186 Optional<DWARFFormValue> 187 DWARFAbbreviationDeclaration::getAttributeValue(const uint64_t DIEOffset, 188 const dwarf::Attribute Attr, 189 const DWARFUnit &U) const { 190 // Check if this abbreviation has this attribute without needing to skip 191 // any data so we can return quickly if it doesn't. 192 Optional<uint32_t> MatchAttrIndex = findAttributeIndex(Attr); 193 if (!MatchAttrIndex) 194 return None; 195 196 uint64_t Offset = getAttributeOffsetFromIndex(*MatchAttrIndex, DIEOffset, U); 197 198 return getAttributeValueFromOffset(*MatchAttrIndex, Offset, U); 199 } 200 201 size_t DWARFAbbreviationDeclaration::FixedSizeInfo::getByteSize( 202 const DWARFUnit &U) const { 203 size_t ByteSize = NumBytes; 204 if (NumAddrs) 205 ByteSize += NumAddrs * U.getAddressByteSize(); 206 if (NumRefAddrs) 207 ByteSize += NumRefAddrs * U.getRefAddrByteSize(); 208 if (NumDwarfOffsets) 209 ByteSize += NumDwarfOffsets * U.getDwarfOffsetByteSize(); 210 return ByteSize; 211 } 212 213 Optional<int64_t> DWARFAbbreviationDeclaration::AttributeSpec::getByteSize( 214 const DWARFUnit &U) const { 215 if (isImplicitConst()) 216 return 0; 217 if (ByteSize.HasByteSize) 218 return ByteSize.ByteSize; 219 Optional<int64_t> S; 220 auto FixedByteSize = dwarf::getFixedFormByteSize(Form, U.getFormParams()); 221 if (FixedByteSize) 222 S = *FixedByteSize; 223 return S; 224 } 225 226 Optional<size_t> DWARFAbbreviationDeclaration::getFixedAttributesByteSize( 227 const DWARFUnit &U) const { 228 if (FixedAttributeSize) 229 return FixedAttributeSize->getByteSize(U); 230 return None; 231 } 232