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