]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp
Merge llvm trunk r338150 (just before the 7.0.0 branch point), and
[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/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 }