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       else if (auto Size = DWARFFormValue::getFixedByteSize(F))
71         V = *Size;
72       AttributeSpecs.push_back(AttributeSpec(A, F, V));
73       if (IsImplicitConst)
74         continue;
75       // If this abbrevation still has a fixed byte size, then update the
76       // FixedAttributeSize as needed.
77       if (FixedAttributeSize) {
78         if (V)
79           FixedAttributeSize->NumBytes += *V;
80         else {
81           switch (F) {
82           case DW_FORM_addr:
83             ++FixedAttributeSize->NumAddrs;
84             break;
85 
86           case DW_FORM_ref_addr:
87             ++FixedAttributeSize->NumRefAddrs;
88             break;
89 
90           case DW_FORM_strp:
91           case DW_FORM_GNU_ref_alt:
92           case DW_FORM_GNU_strp_alt:
93           case DW_FORM_line_strp:
94           case DW_FORM_sec_offset:
95           case DW_FORM_strp_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