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/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 uint32_t* OffsetPtr) { 42 clear(); 43 const uint32_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 Optional<int64_t> V; 67 bool IsImplicitConst = (F == DW_FORM_implicit_const); 68 if (IsImplicitConst) { 69 V = Data.getSLEB128(OffsetPtr); 70 AttributeSpecs.push_back(AttributeSpec(A, F, V)); 71 continue; 72 } 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 (auto Size = 100 DWARFFormValue::getFixedByteSize(F, DWARFFormParams())) { 101 V = *Size; 102 if (FixedAttributeSize) 103 FixedAttributeSize->NumBytes += *V; 104 break; 105 } 106 // Indicate we no longer have a fixed byte size for this 107 // abbreviation by clearing the FixedAttributeSize optional value 108 // so it doesn't have a value. 109 FixedAttributeSize.reset(); 110 break; 111 } 112 // Record this attribute and its fixed size if it has one. 113 AttributeSpecs.push_back(AttributeSpec(A, F, V)); 114 } else if (A == 0 && F == 0) { 115 // We successfully reached the end of this abbreviation declaration 116 // since both attribute and form are zero. 117 break; 118 } else { 119 // Attribute and form pairs must either both be non-zero, in which case 120 // they are added to the abbreviation declaration, or both be zero to 121 // terminate the abbrevation declaration. In this case only one was 122 // zero which is an error. 123 clear(); 124 return false; 125 } 126 } 127 return true; 128 } 129 130 void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const { 131 auto tagString = TagString(getTag()); 132 OS << '[' << getCode() << "] "; 133 if (!tagString.empty()) 134 OS << tagString; 135 else 136 OS << format("DW_TAG_Unknown_%x", getTag()); 137 OS << "\tDW_CHILDREN_" << (hasChildren() ? "yes" : "no") << '\n'; 138 for (const AttributeSpec &Spec : AttributeSpecs) { 139 OS << '\t'; 140 auto attrString = AttributeString(Spec.Attr); 141 if (!attrString.empty()) 142 OS << attrString; 143 else 144 OS << format("DW_AT_Unknown_%x", Spec.Attr); 145 OS << '\t'; 146 auto formString = FormEncodingString(Spec.Form); 147 if (!formString.empty()) 148 OS << formString; 149 else 150 OS << format("DW_FORM_Unknown_%x", Spec.Form); 151 if (Spec.isImplicitConst()) 152 OS << '\t' << *Spec.ByteSizeOrValue; 153 OS << '\n'; 154 } 155 OS << '\n'; 156 } 157 158 Optional<uint32_t> 159 DWARFAbbreviationDeclaration::findAttributeIndex(dwarf::Attribute Attr) const { 160 for (uint32_t i = 0, e = AttributeSpecs.size(); i != e; ++i) { 161 if (AttributeSpecs[i].Attr == Attr) 162 return i; 163 } 164 return None; 165 } 166 167 Optional<DWARFFormValue> DWARFAbbreviationDeclaration::getAttributeValue( 168 const uint32_t DIEOffset, const dwarf::Attribute Attr, 169 const DWARFUnit &U) const { 170 Optional<uint32_t> MatchAttrIndex = findAttributeIndex(Attr); 171 if (!MatchAttrIndex) 172 return None; 173 174 auto DebugInfoData = U.getDebugInfoExtractor(); 175 176 // Add the byte size of ULEB that for the abbrev Code so we can start 177 // skipping the attribute data. 178 uint32_t Offset = DIEOffset + CodeByteSize; 179 uint32_t AttrIndex = 0; 180 for (const auto &Spec : AttributeSpecs) { 181 if (*MatchAttrIndex == AttrIndex) { 182 // We have arrived at the attribute to extract, extract if from Offset. 183 DWARFFormValue FormValue(Spec.Form); 184 if (Spec.isImplicitConst()) { 185 FormValue.setSValue(*Spec.ByteSizeOrValue); 186 return FormValue; 187 } 188 if (FormValue.extractValue(DebugInfoData, &Offset, &U)) 189 return FormValue; 190 } 191 // March Offset along until we get to the attribute we want. 192 if (auto FixedSize = Spec.getByteSize(U)) 193 Offset += *FixedSize; 194 else 195 DWARFFormValue::skipValue(Spec.Form, DebugInfoData, &Offset, 196 U.getFormParams()); 197 ++AttrIndex; 198 } 199 return None; 200 } 201 202 size_t DWARFAbbreviationDeclaration::FixedSizeInfo::getByteSize( 203 const DWARFUnit &U) const { 204 size_t ByteSize = NumBytes; 205 if (NumAddrs) 206 ByteSize += NumAddrs * U.getAddressByteSize(); 207 if (NumRefAddrs) 208 ByteSize += NumRefAddrs * U.getRefAddrByteSize(); 209 if (NumDwarfOffsets) 210 ByteSize += NumDwarfOffsets * U.getDwarfOffsetByteSize(); 211 return ByteSize; 212 } 213 214 Optional<int64_t> DWARFAbbreviationDeclaration::AttributeSpec::getByteSize( 215 const DWARFUnit &U) const { 216 if (isImplicitConst()) 217 return 0; 218 if (ByteSizeOrValue) 219 return ByteSizeOrValue; 220 Optional<int64_t> S; 221 auto FixedByteSize = 222 DWARFFormValue::getFixedByteSize(Form, U.getFormParams()); 223 if (FixedByteSize) 224 S = *FixedByteSize; 225 return S; 226 } 227 228 Optional<size_t> DWARFAbbreviationDeclaration::getFixedAttributesByteSize( 229 const DWARFUnit &U) const { 230 if (FixedAttributeSize) 231 return FixedAttributeSize->getByteSize(U); 232 return None; 233 } 234