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 else if (auto Size = DWARFFormValue::getFixedByteSize(F)) 71 V = *Size; 72 AttributeSpecs.push_back(AttributeSpec(A, F, V)); 73 if (IsImplicitConst) 74 continue; 75 // If this abbrevation still has a fixed byte size, then update the 76 // FixedAttributeSize as needed. 77 if (FixedAttributeSize) { 78 if (V) 79 FixedAttributeSize->NumBytes += *V; 80 else { 81 switch (F) { 82 case DW_FORM_addr: 83 ++FixedAttributeSize->NumAddrs; 84 break; 85 86 case DW_FORM_ref_addr: 87 ++FixedAttributeSize->NumRefAddrs; 88 break; 89 90 case DW_FORM_strp: 91 case DW_FORM_GNU_ref_alt: 92 case DW_FORM_GNU_strp_alt: 93 case DW_FORM_line_strp: 94 case DW_FORM_sec_offset: 95 case DW_FORM_strp_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