1 //===- DWARFAbbreviationDeclaration.cpp -----------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
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"
25 using namespace dwarf
;
27 void DWARFAbbreviationDeclaration::clear() {
32 AttributeSpecs
.clear();
33 FixedAttributeSize
.reset();
36 DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() {
41 DWARFAbbreviationDeclaration::extract(DataExtractor Data
,
42 uint32_t* OffsetPtr
) {
44 const uint32_t Offset
= *OffsetPtr
;
45 Code
= Data
.getULEB128(OffsetPtr
);
49 CodeByteSize
= *OffsetPtr
- Offset
;
50 Tag
= static_cast<llvm::dwarf::Tag
>(Data
.getULEB128(OffsetPtr
));
51 if (Tag
== DW_TAG_null
) {
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();
62 // Read all of the abbreviation attributes and forms.
64 auto A
= static_cast<Attribute
>(Data
.getULEB128(OffsetPtr
));
65 auto F
= static_cast<Form
>(Data
.getULEB128(OffsetPtr
));
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
));
73 Optional
<uint8_t> ByteSize
;
74 // If this abbrevation still has a fixed byte size, then update the
75 // FixedAttributeSize as needed.
78 if (FixedAttributeSize
)
79 ++FixedAttributeSize
->NumAddrs
;
82 case DW_FORM_ref_addr
:
83 if (FixedAttributeSize
)
84 ++FixedAttributeSize
->NumRefAddrs
;
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
;
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
;
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();
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.
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.
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();
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
)
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
);
158 auto DebugInfoData
= U
.getDebugInfoExtractor();
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());
172 if (FormValue
.extractValue(DebugInfoData
, &Offset
, U
.getFormParams(), &U
))
175 // March Offset along until we get to the attribute we want.
176 if (auto FixedSize
= Spec
.getByteSize(U
))
177 Offset
+= *FixedSize
;
179 DWARFFormValue::skipValue(Spec
.Form
, DebugInfoData
, &Offset
,
186 size_t DWARFAbbreviationDeclaration::FixedSizeInfo::getByteSize(
187 const DWARFUnit
&U
) const {
188 size_t ByteSize
= NumBytes
;
190 ByteSize
+= NumAddrs
* U
.getAddressByteSize();
192 ByteSize
+= NumRefAddrs
* U
.getRefAddrByteSize();
194 ByteSize
+= NumDwarfOffsets
* U
.getDwarfOffsetByteSize();
198 Optional
<int64_t> DWARFAbbreviationDeclaration::AttributeSpec::getByteSize(
199 const DWARFUnit
&U
) const {
200 if (isImplicitConst())
202 if (ByteSize
.HasByteSize
)
203 return ByteSize
.ByteSize
;
205 auto FixedByteSize
= dwarf::getFixedFormByteSize(Form
, U
.getFormParams());
211 Optional
<size_t> DWARFAbbreviationDeclaration::getFixedAttributesByteSize(
212 const DWARFUnit
&U
) const {
213 if (FixedAttributeSize
)
214 return FixedAttributeSize
->getByteSize(U
);