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