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