1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
|
#pragma once
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
//===- DWARFAbbreviationDeclaration.h ---------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_DWARF_DWARFABBREVIATIONDECLARATION_H
#define LLVM_DEBUGINFO_DWARF_DWARFABBREVIATIONDECLARATION_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
namespace llvm {
class DataExtractor;
class DWARFFormValue;
class DWARFUnit;
class raw_ostream;
class DWARFAbbreviationDeclaration {
public:
struct AttributeSpec {
AttributeSpec(dwarf::Attribute A, dwarf::Form F, int64_t Value)
: Attr(A), Form(F), Value(Value) {
assert(isImplicitConst());
}
AttributeSpec(dwarf::Attribute A, dwarf::Form F,
std::optional<uint8_t> ByteSize)
: Attr(A), Form(F) {
assert(!isImplicitConst());
this->ByteSize.HasByteSize = ByteSize.has_value();
if (this->ByteSize.HasByteSize)
this->ByteSize.ByteSize = *ByteSize;
}
dwarf::Attribute Attr;
dwarf::Form Form;
private:
/// The following field is used for ByteSize for non-implicit_const
/// attributes and as value for implicit_const ones, indicated by
/// Form == DW_FORM_implicit_const.
/// The following cases are distinguished:
/// * Form != DW_FORM_implicit_const and HasByteSize is true:
/// ByteSize contains the fixed size in bytes for the Form in this
/// object.
/// * Form != DW_FORM_implicit_const and HasByteSize is false:
/// byte size of Form either varies according to the DWARFUnit
/// that it is contained in or the value size varies and must be
/// decoded from the debug information in order to determine its size.
/// * Form == DW_FORM_implicit_const:
/// Value contains value for the implicit_const attribute.
struct ByteSizeStorage {
bool HasByteSize;
uint8_t ByteSize;
};
union {
ByteSizeStorage ByteSize;
int64_t Value;
};
public:
bool isImplicitConst() const {
return Form == dwarf::DW_FORM_implicit_const;
}
int64_t getImplicitConstValue() const {
assert(isImplicitConst());
return Value;
}
/// Get the fixed byte size of this Form if possible. This function might
/// use the DWARFUnit to calculate the size of the Form, like for
/// DW_AT_address and DW_AT_ref_addr, so this isn't just an accessor for
/// the ByteSize member.
std::optional<int64_t> getByteSize(const DWARFUnit &U) const;
};
using AttributeSpecVector = SmallVector<AttributeSpec, 8>;
DWARFAbbreviationDeclaration();
uint32_t getCode() const { return Code; }
uint8_t getCodeByteSize() const { return CodeByteSize; }
dwarf::Tag getTag() const { return Tag; }
bool hasChildren() const { return HasChildren; }
using attr_iterator_range =
iterator_range<AttributeSpecVector::const_iterator>;
attr_iterator_range attributes() const {
return attr_iterator_range(AttributeSpecs.begin(), AttributeSpecs.end());
}
dwarf::Form getFormByIndex(uint32_t idx) const {
assert(idx < AttributeSpecs.size());
return AttributeSpecs[idx].Form;
}
size_t getNumAttributes() const {
return AttributeSpecs.size();
}
dwarf::Attribute getAttrByIndex(uint32_t idx) const {
assert(idx < AttributeSpecs.size());
return AttributeSpecs[idx].Attr;
}
bool getAttrIsImplicitConstByIndex(uint32_t idx) const {
assert(idx < AttributeSpecs.size());
return AttributeSpecs[idx].isImplicitConst();
}
int64_t getAttrImplicitConstValueByIndex(uint32_t idx) const {
assert(idx < AttributeSpecs.size());
return AttributeSpecs[idx].getImplicitConstValue();
}
/// Get the index of the specified attribute.
///
/// Searches the this abbreviation declaration for the index of the specified
/// attribute.
///
/// \param attr DWARF attribute to search for.
/// \returns Optional index of the attribute if found, std::nullopt otherwise.
std::optional<uint32_t> findAttributeIndex(dwarf::Attribute attr) const;
/// Extract a DWARF form value from a DIE specified by DIE offset.
///
/// Extract an attribute value for a DWARFUnit given the DIE offset and the
/// attribute.
///
/// \param DIEOffset the DIE offset that points to the ULEB128 abbreviation
/// code in the .debug_info data.
/// \param Attr DWARF attribute to search for.
/// \param U the DWARFUnit the contains the DIE.
/// \returns Optional DWARF form value if the attribute was extracted.
std::optional<DWARFFormValue> getAttributeValue(const uint64_t DIEOffset,
const dwarf::Attribute Attr,
const DWARFUnit &U) const;
/// Compute an offset from a DIE specified by DIE offset and attribute index.
///
/// \param AttrIndex an index of DWARF attribute.
/// \param DIEOffset the DIE offset that points to the ULEB128 abbreviation
/// code in the .debug_info data.
/// \param U the DWARFUnit the contains the DIE.
/// \returns an offset of the attribute.
uint64_t getAttributeOffsetFromIndex(uint32_t AttrIndex, uint64_t DIEOffset,
const DWARFUnit &U) const;
/// Extract a DWARF form value from a DIE speccified by attribute index and
/// its offset.
///
/// \param AttrIndex an index of DWARF attribute.
/// \param Offset offset of the attribute.
/// \param U the DWARFUnit the contains the DIE.
/// \returns Optional DWARF form value if the attribute was extracted.
std::optional<DWARFFormValue>
getAttributeValueFromOffset(uint32_t AttrIndex, uint64_t Offset,
const DWARFUnit &U) const;
bool extract(DataExtractor Data, uint64_t* OffsetPtr);
void dump(raw_ostream &OS) const;
// Return an optional byte size of all attribute data in this abbreviation
// if a constant byte size can be calculated given a DWARFUnit. This allows
// DWARF parsing to be faster as many DWARF DIEs have a fixed byte size.
std::optional<size_t> getFixedAttributesByteSize(const DWARFUnit &U) const;
private:
void clear();
/// A helper structure that can quickly determine the size in bytes of an
/// abbreviation declaration.
struct FixedSizeInfo {
/// The fixed byte size for fixed size forms.
uint16_t NumBytes = 0;
/// Number of DW_FORM_address forms in this abbrevation declaration.
uint8_t NumAddrs = 0;
/// Number of DW_FORM_ref_addr forms in this abbrevation declaration.
uint8_t NumRefAddrs = 0;
/// Number of 4 byte in DWARF32 and 8 byte in DWARF64 forms.
uint8_t NumDwarfOffsets = 0;
FixedSizeInfo() = default;
/// Calculate the fixed size in bytes given a DWARFUnit.
///
/// \param U the DWARFUnit to use when determing the byte size.
/// \returns the size in bytes for all attribute data in this abbreviation.
/// The returned size does not include bytes for the ULEB128 abbreviation
/// code
size_t getByteSize(const DWARFUnit &U) const;
};
uint32_t Code;
dwarf::Tag Tag;
uint8_t CodeByteSize;
bool HasChildren;
AttributeSpecVector AttributeSpecs;
/// If this abbreviation has a fixed byte size then FixedAttributeSize member
/// variable below will have a value.
std::optional<FixedSizeInfo> FixedAttributeSize;
};
} // end namespace llvm
#endif // LLVM_DEBUGINFO_DWARF_DWARFABBREVIATIONDECLARATION_H
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
|