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
clear()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
DWARFAbbreviationDeclaration()36 DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() {
37 clear();
38 }
39
40 bool
extract(DataExtractor Data,uint32_t * OffsetPtr)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
dump(raw_ostream & OS) const129 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>
findAttributeIndex(dwarf::Attribute Attr) const143 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
getAttributeValue(const uint32_t DIEOffset,const dwarf::Attribute Attr,const DWARFUnit & U) const151 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
getByteSize(const DWARFUnit & U) const186 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
getByteSize(const DWARFUnit & U) const198 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
getFixedAttributesByteSize(const DWARFUnit & U) const211 Optional<size_t> DWARFAbbreviationDeclaration::getFixedAttributesByteSize(
212 const DWARFUnit &U) const {
213 if (FixedAttributeSize)
214 return FixedAttributeSize->getByteSize(U);
215 return None;
216 }
217