1 //===- DWARFAbbreviationDeclaration.cpp -----------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
11 #include "llvm/ADT/None.h"
12 #include "llvm/ADT/Optional.h"
13 #include "llvm/BinaryFormat/Dwarf.h"
14 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
15 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
16 #include "llvm/Support/DataExtractor.h"
17 #include "llvm/Support/Format.h"
18 #include "llvm/Support/FormatVariadic.h"
19 #include "llvm/Support/raw_ostream.h"
24 using namespace dwarf
;
26 void DWARFAbbreviationDeclaration::clear() {
31 AttributeSpecs
.clear();
32 FixedAttributeSize
.reset();
35 DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() {
40 DWARFAbbreviationDeclaration::extract(DataExtractor Data
,
41 uint64_t* OffsetPtr
) {
43 const uint64_t Offset
= *OffsetPtr
;
44 Code
= Data
.getULEB128(OffsetPtr
);
48 CodeByteSize
= *OffsetPtr
- Offset
;
49 Tag
= static_cast<llvm::dwarf::Tag
>(Data
.getULEB128(OffsetPtr
));
50 if (Tag
== DW_TAG_null
) {
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();
61 // Read all of the abbreviation attributes and forms.
63 auto A
= static_cast<Attribute
>(Data
.getULEB128(OffsetPtr
));
64 auto F
= static_cast<Form
>(Data
.getULEB128(OffsetPtr
));
66 bool IsImplicitConst
= (F
== DW_FORM_implicit_const
);
67 if (IsImplicitConst
) {
68 int64_t V
= Data
.getSLEB128(OffsetPtr
);
69 AttributeSpecs
.push_back(AttributeSpec(A
, F
, V
));
72 Optional
<uint8_t> ByteSize
;
73 // If this abbrevation still has a fixed byte size, then update the
74 // FixedAttributeSize as needed.
77 if (FixedAttributeSize
)
78 ++FixedAttributeSize
->NumAddrs
;
81 case DW_FORM_ref_addr
:
82 if (FixedAttributeSize
)
83 ++FixedAttributeSize
->NumRefAddrs
;
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
;
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 ((ByteSize
= dwarf::getFixedFormByteSize(F
, dwarf::FormParams()))) {
100 if (FixedAttributeSize
)
101 FixedAttributeSize
->NumBytes
+= *ByteSize
;
104 // Indicate we no longer have a fixed byte size for this
105 // abbreviation by clearing the FixedAttributeSize optional value
106 // so it doesn't have a value.
107 FixedAttributeSize
.reset();
110 // Record this attribute and its fixed size if it has one.
111 AttributeSpecs
.push_back(AttributeSpec(A
, F
, ByteSize
));
112 } else if (A
== 0 && F
== 0) {
113 // We successfully reached the end of this abbreviation declaration
114 // since both attribute and form are zero.
117 // Attribute and form pairs must either both be non-zero, in which case
118 // they are added to the abbreviation declaration, or both be zero to
119 // terminate the abbrevation declaration. In this case only one was
120 // zero which is an error.
128 void DWARFAbbreviationDeclaration::dump(raw_ostream
&OS
) const {
129 OS
<< '[' << getCode() << "] ";
130 OS
<< formatv("{0}", getTag());
131 OS
<< "\tDW_CHILDREN_" << (hasChildren() ? "yes" : "no") << '\n';
132 for (const AttributeSpec
&Spec
: AttributeSpecs
) {
133 OS
<< formatv("\t{0}\t{1}", Spec
.Attr
, Spec
.Form
);
134 if (Spec
.isImplicitConst())
135 OS
<< '\t' << Spec
.getImplicitConstValue();
142 DWARFAbbreviationDeclaration::findAttributeIndex(dwarf::Attribute Attr
) const {
143 for (uint32_t i
= 0, e
= AttributeSpecs
.size(); i
!= e
; ++i
) {
144 if (AttributeSpecs
[i
].Attr
== Attr
)
150 Optional
<DWARFFormValue
> DWARFAbbreviationDeclaration::getAttributeValue(
151 const uint64_t DIEOffset
, const dwarf::Attribute Attr
,
152 const DWARFUnit
&U
) const {
153 Optional
<uint32_t> MatchAttrIndex
= findAttributeIndex(Attr
);
157 auto DebugInfoData
= U
.getDebugInfoExtractor();
159 // Add the byte size of ULEB that for the abbrev Code so we can start
160 // skipping the attribute data.
161 uint64_t Offset
= DIEOffset
+ CodeByteSize
;
162 uint32_t AttrIndex
= 0;
163 for (const auto &Spec
: AttributeSpecs
) {
164 if (*MatchAttrIndex
== AttrIndex
) {
165 // We have arrived at the attribute to extract, extract if from Offset.
166 if (Spec
.isImplicitConst())
167 return DWARFFormValue::createFromSValue(Spec
.Form
,
168 Spec
.getImplicitConstValue());
170 DWARFFormValue
FormValue(Spec
.Form
);
171 if (FormValue
.extractValue(DebugInfoData
, &Offset
, U
.getFormParams(), &U
))
174 // March Offset along until we get to the attribute we want.
175 if (auto FixedSize
= Spec
.getByteSize(U
))
176 Offset
+= *FixedSize
;
178 DWARFFormValue::skipValue(Spec
.Form
, DebugInfoData
, &Offset
,
185 size_t DWARFAbbreviationDeclaration::FixedSizeInfo::getByteSize(
186 const DWARFUnit
&U
) const {
187 size_t ByteSize
= NumBytes
;
189 ByteSize
+= NumAddrs
* U
.getAddressByteSize();
191 ByteSize
+= NumRefAddrs
* U
.getRefAddrByteSize();
193 ByteSize
+= NumDwarfOffsets
* U
.getDwarfOffsetByteSize();
197 Optional
<int64_t> DWARFAbbreviationDeclaration::AttributeSpec::getByteSize(
198 const DWARFUnit
&U
) const {
199 if (isImplicitConst())
201 if (ByteSize
.HasByteSize
)
202 return ByteSize
.ByteSize
;
204 auto FixedByteSize
= dwarf::getFixedFormByteSize(Form
, U
.getFormParams());
210 Optional
<size_t> DWARFAbbreviationDeclaration::getFixedAttributesByteSize(
211 const DWARFUnit
&U
) const {
212 if (FixedAttributeSize
)
213 return FixedAttributeSize
->getByteSize(U
);