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/FormatVariadic.h" 20 #include "llvm/Support/raw_ostream.h" 21 #include <cstddef> 22 #include <cstdint> 23 24 using namespace llvm; 25 using namespace dwarf; 26 27 void DWARFAbbreviationDeclaration::clear() { 28 Code = 0; 29 Tag = DW_TAG_null; 30 CodeByteSize = 0; 31 HasChildren = false; 32 AttributeSpecs.clear(); 33 FixedAttributeSize.reset(); 34 } 35 36 DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() { 37 clear(); 38 } 39 40 bool 41 DWARFAbbreviationDeclaration::extract(DataExtractor Data, 42 uint32_t* OffsetPtr) { 43 clear(); 44 const uint32_t Offset = *OffsetPtr; 45 Code = Data.getULEB128(OffsetPtr); 46 if (Code == 0) { 47 return false; 48 } 49 CodeByteSize = *OffsetPtr - Offset; 50 Tag = static_cast<llvm::dwarf::Tag>(Data.getULEB128(OffsetPtr)); 51 if (Tag == DW_TAG_null) { 52 clear(); 53 return false; 54 } 55 uint8_t ChildrenByte = Data.getU8(OffsetPtr); 56 HasChildren = (ChildrenByte == DW_CHILDREN_yes); 57 // Assign a value to our optional FixedAttributeSize member variable. If 58 // this member variable still has a value after the while loop below, then 59 // all attribute data in this abbreviation declaration has a fixed byte size. 60 FixedAttributeSize = FixedSizeInfo(); 61 62 // Read all of the abbreviation attributes and forms. 63 while (true) { 64 auto A = static_cast<Attribute>(Data.getULEB128(OffsetPtr)); 65 auto F = static_cast<Form>(Data.getULEB128(OffsetPtr)); 66 if (A && F) { 67 bool IsImplicitConst = (F == DW_FORM_implicit_const); 68 if (IsImplicitConst) { 69 int64_t V = Data.getSLEB128(OffsetPtr); 70 AttributeSpecs.push_back(AttributeSpec(A, F, V)); 71 continue; 72 } 73 Optional<uint8_t> ByteSize; 74 // If this abbrevation still has a fixed byte size, then update the 75 // FixedAttributeSize as needed. 76 switch (F) { 77 case DW_FORM_addr: 78 if (FixedAttributeSize) 79 ++FixedAttributeSize->NumAddrs; 80 break; 81 82 case DW_FORM_ref_addr: 83 if (FixedAttributeSize) 84 ++FixedAttributeSize->NumRefAddrs; 85 break; 86 87 case DW_FORM_strp: 88 case DW_FORM_GNU_ref_alt: 89 case DW_FORM_GNU_strp_alt: 90 case DW_FORM_line_strp: 91 case DW_FORM_sec_offset: 92 case DW_FORM_strp_sup: 93 if (FixedAttributeSize) 94 ++FixedAttributeSize->NumDwarfOffsets; 95 break; 96 97 default: 98 // The form has a byte size that doesn't depend on Params. 99 // If it's a fixed size, keep track of it. 100 if ((ByteSize = dwarf::getFixedFormByteSize(F, dwarf::FormParams()))) { 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 OS << '[' << getCode() << "] "; 131 OS << formatv("{0}", getTag()); 132 OS << "\tDW_CHILDREN_" << (hasChildren() ? "yes" : "no") << '\n'; 133 for (const AttributeSpec &Spec : AttributeSpecs) { 134 OS << formatv("\t{0}\t{1}", Spec.Attr, Spec.Form); 135 if (Spec.isImplicitConst()) 136 OS << '\t' << Spec.getImplicitConstValue(); 137 OS << '\n'; 138 } 139 OS << '\n'; 140 } 141 142 Optional<uint32_t> 143 DWARFAbbreviationDeclaration::findAttributeIndex(dwarf::Attribute Attr) const { 144 for (uint32_t i = 0, e = AttributeSpecs.size(); i != e; ++i) { 145 if (AttributeSpecs[i].Attr == Attr) 146 return i; 147 } 148 return None; 149 } 150 151 Optional<DWARFFormValue> DWARFAbbreviationDeclaration::getAttributeValue( 152 const uint32_t DIEOffset, const dwarf::Attribute Attr, 153 const DWARFUnit &U) const { 154 Optional<uint32_t> MatchAttrIndex = findAttributeIndex(Attr); 155 if (!MatchAttrIndex) 156 return None; 157 158 auto DebugInfoData = U.getDebugInfoExtractor(); 159 160 // Add the byte size of ULEB that for the abbrev Code so we can start 161 // skipping the attribute data. 162 uint32_t Offset = DIEOffset + CodeByteSize; 163 uint32_t AttrIndex = 0; 164 for (const auto &Spec : AttributeSpecs) { 165 if (*MatchAttrIndex == AttrIndex) { 166 // We have arrived at the attribute to extract, extract if from Offset. 167 DWARFFormValue FormValue(Spec.Form); 168 if (Spec.isImplicitConst()) { 169 FormValue.setSValue(Spec.getImplicitConstValue()); 170 return FormValue; 171 } 172 if (FormValue.extractValue(DebugInfoData, &Offset, U.getFormParams(), &U)) 173 return FormValue; 174 } 175 // March Offset along until we get to the attribute we want. 176 if (auto FixedSize = Spec.getByteSize(U)) 177 Offset += *FixedSize; 178 else 179 DWARFFormValue::skipValue(Spec.Form, DebugInfoData, &Offset, 180 U.getFormParams()); 181 ++AttrIndex; 182 } 183 return None; 184 } 185 186 size_t DWARFAbbreviationDeclaration::FixedSizeInfo::getByteSize( 187 const DWARFUnit &U) const { 188 size_t ByteSize = NumBytes; 189 if (NumAddrs) 190 ByteSize += NumAddrs * U.getAddressByteSize(); 191 if (NumRefAddrs) 192 ByteSize += NumRefAddrs * U.getRefAddrByteSize(); 193 if (NumDwarfOffsets) 194 ByteSize += NumDwarfOffsets * U.getDwarfOffsetByteSize(); 195 return ByteSize; 196 } 197 198 Optional<int64_t> DWARFAbbreviationDeclaration::AttributeSpec::getByteSize( 199 const DWARFUnit &U) const { 200 if (isImplicitConst()) 201 return 0; 202 if (ByteSize.HasByteSize) 203 return ByteSize.ByteSize; 204 Optional<int64_t> S; 205 auto FixedByteSize = dwarf::getFixedFormByteSize(Form, U.getFormParams()); 206 if (FixedByteSize) 207 S = *FixedByteSize; 208 return S; 209 } 210 211 Optional<size_t> DWARFAbbreviationDeclaration::getFixedAttributesByteSize( 212 const DWARFUnit &U) const { 213 if (FixedAttributeSize) 214 return FixedAttributeSize->getByteSize(U); 215 return None; 216 } 217