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