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