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/ADT/None.h"
11 #include "llvm/ADT/Optional.h"
12 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
13 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
14 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
15 #include "llvm/Support/DataExtractor.h"
16 #include "llvm/Support/Dwarf.h"
17 #include "llvm/Support/Format.h"
18 #include "llvm/Support/raw_ostream.h"
19 #include <cstddef>
20 #include <cstdint>
21 
22 using namespace llvm;
23 using namespace dwarf;
24 
25 void DWARFAbbreviationDeclaration::clear() {
26   Code = 0;
27   Tag = DW_TAG_null;
28   CodeByteSize = 0;
29   HasChildren = false;
30   AttributeSpecs.clear();
31   FixedAttributeSize.reset();
32 }
33 
34 DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() {
35   clear();
36 }
37 
38 bool
39 DWARFAbbreviationDeclaration::extract(DataExtractor Data,
40                                       uint32_t* OffsetPtr) {
41   clear();
42   const uint32_t Offset = *OffsetPtr;
43   Code = Data.getULEB128(OffsetPtr);
44   if (Code == 0) {
45     return false;
46   }
47   CodeByteSize = *OffsetPtr - Offset;
48   Tag = static_cast<llvm::dwarf::Tag>(Data.getULEB128(OffsetPtr));
49   if (Tag == DW_TAG_null) {
50     clear();
51     return false;
52   }
53   uint8_t ChildrenByte = Data.getU8(OffsetPtr);
54   HasChildren = (ChildrenByte == DW_CHILDREN_yes);
55   // Assign a value to our optional FixedAttributeSize member variable. If
56   // this member variable still has a value after the while loop below, then
57   // all attribute data in this abbreviation declaration has a fixed byte size.
58   FixedAttributeSize = FixedSizeInfo();
59 
60   // Read all of the abbreviation attributes and forms.
61   while (true) {
62     auto A = static_cast<Attribute>(Data.getULEB128(OffsetPtr));
63     auto F = static_cast<Form>(Data.getULEB128(OffsetPtr));
64     if (A && F) {
65       Optional<int64_t> V;
66       bool IsImplicitConst = (F == DW_FORM_implicit_const);
67       if (IsImplicitConst)
68         V = Data.getSLEB128(OffsetPtr);
69       else if (auto Size = DWARFFormValue::getFixedByteSize(F))
70         V = *Size;
71       AttributeSpecs.push_back(AttributeSpec(A, F, V));
72       if (IsImplicitConst)
73         continue;
74       // If this abbrevation still has a fixed byte size, then update the
75       // FixedAttributeSize as needed.
76       if (FixedAttributeSize) {
77         if (V)
78           FixedAttributeSize->NumBytes += *V;
79         else {
80           switch (F) {
81           case DW_FORM_addr:
82             ++FixedAttributeSize->NumAddrs;
83             break;
84 
85           case DW_FORM_ref_addr:
86             ++FixedAttributeSize->NumRefAddrs;
87             break;
88 
89           case DW_FORM_strp:
90           case DW_FORM_GNU_ref_alt:
91           case DW_FORM_GNU_strp_alt:
92           case DW_FORM_line_strp:
93           case DW_FORM_sec_offset:
94           case DW_FORM_strp_sup:
95           case DW_FORM_ref_sup:
96             ++FixedAttributeSize->NumDwarfOffsets;
97             break;
98 
99           default:
100             // Indicate we no longer have a fixed byte size for this
101             // abbreviation by clearing the FixedAttributeSize optional value
102             // so it doesn't have a value.
103             FixedAttributeSize.reset();
104             break;
105           }
106         }
107       }
108     } else if (A == 0 && F == 0) {
109       // We successfully reached the end of this abbreviation declaration
110       // since both attribute and form are zero.
111       break;
112     } else {
113       // Attribute and form pairs must either both be non-zero, in which case
114       // they are added to the abbreviation declaration, or both be zero to
115       // terminate the abbrevation declaration. In this case only one was
116       // zero which is an error.
117       clear();
118       return false;
119     }
120   }
121   return true;
122 }
123 
124 void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const {
125   auto tagString = TagString(getTag());
126   OS << '[' << getCode() << "] ";
127   if (!tagString.empty())
128     OS << tagString;
129   else
130     OS << format("DW_TAG_Unknown_%x", getTag());
131   OS << "\tDW_CHILDREN_" << (hasChildren() ? "yes" : "no") << '\n';
132   for (const AttributeSpec &Spec : AttributeSpecs) {
133     OS << '\t';
134     auto attrString = AttributeString(Spec.Attr);
135     if (!attrString.empty())
136       OS << attrString;
137     else
138       OS << format("DW_AT_Unknown_%x", Spec.Attr);
139     OS << '\t';
140     auto formString = FormEncodingString(Spec.Form);
141     if (!formString.empty())
142       OS << formString;
143     else
144       OS << format("DW_FORM_Unknown_%x", Spec.Form);
145     if (Spec.isImplicitConst())
146       OS << '\t' << *Spec.ByteSizeOrValue;
147     OS << '\n';
148   }
149   OS << '\n';
150 }
151 
152 Optional<uint32_t>
153 DWARFAbbreviationDeclaration::findAttributeIndex(dwarf::Attribute Attr) const {
154   for (uint32_t i = 0, e = AttributeSpecs.size(); i != e; ++i) {
155     if (AttributeSpecs[i].Attr == Attr)
156       return i;
157   }
158   return None;
159 }
160 
161 Optional<DWARFFormValue> DWARFAbbreviationDeclaration::getAttributeValue(
162     const uint32_t DIEOffset, const dwarf::Attribute Attr,
163     const DWARFUnit &U) const {
164   Optional<uint32_t> MatchAttrIndex = findAttributeIndex(Attr);
165   if (!MatchAttrIndex)
166     return None;
167 
168   auto DebugInfoData = U.getDebugInfoExtractor();
169 
170   // Add the byte size of ULEB that for the abbrev Code so we can start
171   // skipping the attribute data.
172   uint32_t Offset = DIEOffset + CodeByteSize;
173   uint32_t AttrIndex = 0;
174   for (const auto &Spec : AttributeSpecs) {
175     if (*MatchAttrIndex == AttrIndex) {
176       // We have arrived at the attribute to extract, extract if from Offset.
177       DWARFFormValue FormValue(Spec.Form);
178       if (Spec.isImplicitConst()) {
179         FormValue.setSValue(*Spec.ByteSizeOrValue);
180         return FormValue;
181       }
182       if (FormValue.extractValue(DebugInfoData, &Offset, &U))
183         return FormValue;
184     }
185     // March Offset along until we get to the attribute we want.
186     if (auto FixedSize = Spec.getByteSize(U))
187       Offset += *FixedSize;
188     else
189       DWARFFormValue::skipValue(Spec.Form, DebugInfoData, &Offset, &U);
190     ++AttrIndex;
191   }
192   return None;
193 }
194 
195 size_t DWARFAbbreviationDeclaration::FixedSizeInfo::getByteSize(
196     const DWARFUnit &U) const {
197   size_t ByteSize = NumBytes;
198   if (NumAddrs)
199     ByteSize += NumAddrs * U.getAddressByteSize();
200   if (NumRefAddrs)
201     ByteSize += NumRefAddrs * U.getRefAddrByteSize();
202   if (NumDwarfOffsets)
203     ByteSize += NumDwarfOffsets * U.getDwarfOffsetByteSize();
204   return ByteSize;
205 }
206 
207 Optional<int64_t> DWARFAbbreviationDeclaration::AttributeSpec::getByteSize(
208     const DWARFUnit &U) const {
209   if (isImplicitConst())
210     return 0;
211   if (ByteSizeOrValue)
212     return ByteSizeOrValue;
213   Optional<int64_t> S;
214   auto FixedByteSize = DWARFFormValue::getFixedByteSize(Form, &U);
215   if (FixedByteSize)
216     S = *FixedByteSize;
217   return S;
218 }
219 
220 Optional<size_t> DWARFAbbreviationDeclaration::getFixedAttributesByteSize(
221     const DWARFUnit &U) const {
222   if (FixedAttributeSize)
223     return FixedAttributeSize->getByteSize(U);
224   return None;
225 }
226