1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "dwarf_abbrev.h"
18
19 #include <map>
20 #include <memory>
21 #include <vector>
22
23 #include "berberis/base/stringprintf.h"
24
25 #include "dwarf_constants.h"
26
27 namespace nogrod {
28
29 namespace {
30
31 using berberis::StringPrintf;
32
33 class DwarfClasses {
34 public:
DwarfClasses()35 DwarfClasses() { classes_[0] = {}; }
36
DwarfClasses(std::initializer_list<const DwarfClass * > classes)37 DwarfClasses(std::initializer_list<const DwarfClass*> classes) {
38 classes_[0] = std::vector(classes);
39 }
40
DwarfClasses(std::initializer_list<std::map<uint16_t,std::vector<const DwarfClass * >>::value_type> classes)41 DwarfClasses(
42 std::initializer_list<std::map<uint16_t, std::vector<const DwarfClass*>>::value_type> classes)
43 : classes_(classes) {}
44
get(uint16_t version) const45 [[nodiscard]] const std::vector<const DwarfClass*>* get(uint16_t version) const {
46 auto candidate = classes_.find(version);
47 if (candidate != classes_.end()) {
48 return &candidate->second;
49 }
50
51 for (auto it = classes_.begin(), end = classes_.end(); it != end; ++it) {
52 if (it->first <= version) {
53 candidate = it;
54 } else {
55 break;
56 }
57 }
58
59 return candidate != classes_.end() ? &candidate->second : nullptr;
60 }
61
62 private:
63 // classes for every version
64 std::map<uint16_t, std::vector<const DwarfClass*>> classes_;
65 };
66
67 struct AbbrevDescriptor {
68 uint32_t code;
69 DwarfClasses classes;
70 const char* name;
71 };
72
73 // clang-format makes this part unreadable so we disable it.
74 // clang-format off
75 const AbbrevDescriptor kFormDescriptors[] = {
76 { 0x00, { }, "null"},
77 { 0x01, { DwarfClass::kAddress }, "DW_FORM_addr" },
78 { 0x02, { }, "Reserved 0x02" },
79 { 0x03, { DwarfClass::kBlock }, "DW_FORM_block2" },
80 { 0x04, { DwarfClass::kBlock }, "DW_FORM_block4" },
81 { 0x05, { DwarfClass::kConstant }, "DW_FORM_data2" },
82 { 0x06, { DwarfClass::kConstant }, "DW_FORM_data4" },
83 { 0x07, { DwarfClass::kConstant }, "DW_FORM_data8" },
84 { 0x08, { DwarfClass::kString }, "DW_FORM_string" },
85 { 0x09, { DwarfClass::kBlock }, "DW_FORM_block" },
86 { 0x0a, { DwarfClass::kBlock }, "DW_FORM_block4" },
87 { 0x0b, { DwarfClass::kConstant }, "DW_FORM_data1" },
88 { 0x0c, { DwarfClass::kFlag }, "DW_FORM_flag" },
89 { 0x0d, { DwarfClass::kConstant }, "DW_FORM_sdata" },
90 { 0x0e, { DwarfClass::kString }, "DW_FORM_strp" },
91 { 0x0f, { DwarfClass::kConstant }, "DW_FORM_udata" },
92 { 0x10, { DwarfClass::kReference }, "DW_FORM_ref_addr" },
93 { 0x11, { DwarfClass::kReference }, "DW_FORM_ref1" },
94 { 0x12, { DwarfClass::kReference }, "DW_FORM_ref2" },
95 { 0x13, { DwarfClass::kReference }, "DW_FORM_ref4" },
96 { 0x14, { DwarfClass::kReference }, "DW_FORM_ref8" },
97 { 0x15, { DwarfClass::kReference }, "DW_FORM_ref_udata" },
98 { 0x16, {}, "DW_FORM_indirect" }, // TODO(dimitry): DwarfClass::kIndirect?
99 { 0x17, { DwarfClass::kAddrptr,
100 DwarfClass::kLineptr,
101 //DwarfClass::kLoclist,
102 DwarfClass::kLoclistsptr,
103 DwarfClass::kMacptr,
104 //DwarfClass::kRnglist,
105 DwarfClass::kRnglistsptr,
106 DwarfClass::kStroffsetsptr,
107 }, "DW_FORM_sec_offset"},
108 { 0x18, { DwarfClass::kExprloc }, "DW_FORM_exprloc" },
109 { 0x19, { DwarfClass::kFlag }, "DW_FORM_flag_present" },
110 { 0x1a, { DwarfClass::kString }, "DW_FORM_strx" },
111 { 0x1b, { DwarfClass::kAddress }, "DW_FORM_addrx" },
112 { 0x1c, { DwarfClass::kReference }, "DW_FORM_ref_sup4" },
113 { 0x1d, { DwarfClass::kString }, "DW_FORM_strp_sup" },
114 { 0x1e, { DwarfClass::kConstant }, "DW_FORM_data16" },
115 { 0x1f, { DwarfClass::kString }, "DW_FORM_line_strp" },
116 { 0x20, { DwarfClass::kReference }, "DW_FORM_ref_sig8" },
117 { 0x21, { DwarfClass::kConstant }, "DW_FORM_implicit_const" },
118 { 0x22, { DwarfClass::kLoclist }, "DW_FORM_loclistx" },
119 { 0x23, { DwarfClass::kRnglist }, "DW_FORM_rnglistx" },
120 { 0x24, { DwarfClass::kReference }, "DW_FORM_ref_sup8" },
121 { 0x25, { DwarfClass::kString }, "DW_FORM_strx1" },
122 { 0x26, { DwarfClass::kString }, "DW_FORM_strx2" },
123 { 0x27, { DwarfClass::kString }, "DW_FORM_strx3" },
124 { 0x28, { DwarfClass::kString }, "DW_FORM_strx4" },
125 { 0x29, { DwarfClass::kAddress }, "DW_FORM_addrx1" },
126 { 0x2a, { DwarfClass::kAddress }, "DW_FORM_addrx2" },
127 { 0x2b, { DwarfClass::kAddress }, "DW_FORM_addrx3" },
128 { 0x2c, { DwarfClass::kAddress }, "DW_FORM_addrx4" },
129 };
130
131 const AbbrevDescriptor kNameDescriptors[] = {
132 { 0x00, { }, "null" },
133 { 0x01, { { 2, { DwarfClass::kReference } } }, "DW_AT_sibling" },
134 { 0x02, {
135 { 2, { DwarfClass::kBlock, DwarfClass::kConstant } },
136 { 3, { DwarfClass::kBlock, DwarfClass::kLoclistsptr } },
137 { 4, { DwarfClass::kExprloc, DwarfClass::kLoclistsptr } },
138 { 5, { DwarfClass::kExprloc, DwarfClass::kLoclist } },
139 }, "DW_AT_location" },
140 { 0x03, { { 2, { DwarfClass::kString } } }, "DW_AT_name" },
141 { 0x04, { }, "Reserved 0x04" },
142 { 0x05, { }, "Reserved 0x05" },
143 { 0x06, { }, "Reserved 0x06" },
144 { 0x07, { }, "Reserved 0x07" },
145 { 0x08, { }, "Reserved 0x08" },
146 { 0x09, { { 2, { DwarfClass::kConstant } } }, "DW_AT_ordering" },
147 { 0x0a, { }, "Reserved 0x0a" },
148 { 0x0b, {
149 { 2, { DwarfClass::kConstant } },
150 { 3, { DwarfClass::kBlock,
151 DwarfClass::kConstant,
152 DwarfClass::kReference } },
153 { 4, { DwarfClass::kConstant,
154 DwarfClass::kExprloc,
155 DwarfClass::kReference } },
156 }, "DW_AT_byte_size" },
157 { 0x0c, {
158 { 2, { DwarfClass::kConstant } },
159 { 3, { DwarfClass::kConstant,
160 DwarfClass::kBlock,
161 DwarfClass::kReference } },
162 { 4, { DwarfClass::kConstant,
163 DwarfClass::kExprloc,
164 DwarfClass::kReference } },
165 }, "DW_AT_bit_offset" }, // Removed in dwarf5??
166 { 0x0d, {
167 { 2, { DwarfClass::kConstant } },
168 { 3, { DwarfClass::kConstant,
169 DwarfClass::kBlock,
170 DwarfClass::kReference } },
171 { 4, { DwarfClass::kConstant,
172 DwarfClass::kExprloc,
173 DwarfClass::kReference } },
174 }, "DW_AT_bit_size" },
175 { 0x0e, { }, "Reserved 0x0e" },
176 { 0x0f, { }, "Reserved 0x0f" },
177 { 0x10, {
178 { 2, { DwarfClass::kConstant } },
179 { 3, { DwarfClass::kLineptr } },
180 }, "DW_AT_stmt_list" },
181 { 0x11, { { 2, { DwarfClass::kAddress } } }, "DW_AT_low_pc" },
182 { 0x12, {
183 { 2, { DwarfClass::kAddress } },
184 { 4, { DwarfClass::kAddress, DwarfClass::kConstant } },
185 }, "DW_AT_high_pc" },
186 { 0x13, { { 2, { DwarfClass::kConstant } } }, "DW_AT_language" },
187 { 0x14, { }, "Reserved 0x14" },
188 { 0x15, { { 2, { DwarfClass::kReference } } }, "DW_AT_discr" },
189 { 0x16, { { 2, { DwarfClass::kConstant } } }, "DW_AT_discr_value" },
190 { 0x17, { { 2, { DwarfClass::kConstant } } }, "DW_AT_visibility" },
191 { 0x18, { { 2, { DwarfClass::kReference } } }, "DW_AT_import" },
192 { 0x19, {
193 { 2, { DwarfClass::kBlock, DwarfClass::kConstant } },
194 { 3, { DwarfClass::kBlock, DwarfClass::kLoclistsptr } },
195 { 4, { DwarfClass::kExprloc, DwarfClass::kLoclistsptr } },
196 { 5, { DwarfClass::kExprloc/*, DwarfClass::kLoclist */, DwarfClass::kReference } },
197 }, "DW_AT_string_length" },
198 { 0x1a, { { 2, { DwarfClass::kReference } } }, "DW_AT_common_reference" },
199 { 0x1b, { { 2, { DwarfClass::kString } } }, "DW_AT_comp_dir" },
200 { 0x1c, {
201 { 2, { DwarfClass::kBlock, DwarfClass::kConstant, DwarfClass::kString } }
202 }, "DW_AT_const_value" },
203 { 0x1d, { { 2, { DwarfClass::kReference } } }, "DW_AT_containing_type" },
204 { 0x1e, {
205 { 2, { DwarfClass::kReference } },
206 { 5, { DwarfClass::kConstant,
207 DwarfClass::kReference,
208 DwarfClass::kFlag } }
209 }, "DW_AT_default_value" },
210 { 0x1f, { }, "Reserved 0x1f" },
211 { 0x20, { { 2, { DwarfClass::kConstant } } }, "DW_AT_inline" },
212 { 0x21, { { 2, { DwarfClass::kFlag } } }, "DW_AT_is_optional" },
213 { 0x22, {
214 { 2, { DwarfClass::kConstant, DwarfClass::kReference } },
215 { 3, { DwarfClass::kBlock, DwarfClass::kConstant, DwarfClass::kReference } },
216 { 4, { DwarfClass::kConstant, DwarfClass::kExprloc, DwarfClass::kReference } },
217 }, "DW_AT_lower_bound" },
218 { 0x23, { }, "Reserved 0x23" },
219 { 0x24, { }, "Reserved 0x24" },
220 { 0x25, { { 2, { DwarfClass::kString } } }, "DW_AT_producer" },
221 { 0x26, { }, "Reserved 0x26" },
222 { 0x27, { { 2, { DwarfClass::kFlag } } }, "DW_AT_prototyped" },
223 { 0x28, { }, "Reserved 0x28" },
224 { 0x29, { }, "Reserved 0x29" },
225 { 0x2a, {
226 { 2, { DwarfClass::kBlock, DwarfClass::kConstant } },
227 { 3, { DwarfClass::kBlock, DwarfClass::kLoclistsptr } },
228 { 4, { DwarfClass::kExprloc, DwarfClass::kLoclistsptr } },
229 { 5, { DwarfClass::kExprloc, /* DwarfClass::kLoclist */ } }
230 }, "DW_AT_return_addr" },
231 { 0x2b, { }, "Reserved 0x2b" },
232 { 0x2c, {
233 { 2, { DwarfClass::kConstant } },
234 { 4, { DwarfClass::kConstant, DwarfClass::kRnglistsptr } },
235 { 5, { DwarfClass::kConstant, /* DwarfClass::kRnglist */ } }
236 }, "DW_AT_start_scope" },
237 { 0x2d, { }, "Reserved 0x2d" },
238 { 0x2e, {
239 { 2, { DwarfClass::kConstant } },
240 { 4, { DwarfClass::kConstant, DwarfClass::kExprloc, DwarfClass::kReference } },
241 }, "DW_AT_bit_stride" }, // called "DW_AT_stride_size" in dwarf2
242 { 0x2f, {
243 { 2, { DwarfClass::kConstant, DwarfClass::kReference } },
244 { 3, { DwarfClass::kBlock, DwarfClass::kConstant, DwarfClass::kReference } },
245 { 4, { DwarfClass::kConstant, DwarfClass::kExprloc, DwarfClass::kReference } },
246 }, "DW_AT_upper_bound" },
247 { 0x30, { }, "Reserved 0x30" },
248 { 0x31, { { 2, { DwarfClass::kReference } } }, "DW_AT_abstract_origin" },
249 { 0x32, { { 2, { DwarfClass::kConstant } } }, "DW_AT_accessibility" },
250 { 0x33, { { 2, { DwarfClass::kConstant } } }, "DW_AT_address_class" },
251 { 0x34, { { 2, { DwarfClass::kFlag } } }, "DW_AT_artificial" },
252 { 0x35, { { 2, { DwarfClass::kReference } } }, "DW_AT_base_types" },
253 { 0x36, { { 2, { DwarfClass::kConstant } } }, "DW_AT_calling_convention" },
254 { 0x37, {
255 { 2, { DwarfClass::kConstant, DwarfClass::kReference } },
256 { 3, { DwarfClass::kBlock, DwarfClass::kConstant, DwarfClass::kReference } },
257 { 4, { DwarfClass::kConstant, DwarfClass::kExprloc, DwarfClass::kReference } },
258 }, "DW_AT_count" },
259 { 0x38, {
260 { 2, { DwarfClass::kBlock, DwarfClass::kReference } },
261 { 3, { DwarfClass::kBlock, DwarfClass::kConstant, DwarfClass::kLoclistsptr } },
262 { 4, { DwarfClass::kConstant, DwarfClass::kExprloc, DwarfClass::kLoclistsptr } },
263 { 5, { DwarfClass::kConstant, DwarfClass::kExprloc /*, DwarfClass::kLoclist */ } },
264 }, "DW_AT_data_member_location" },
265 { 0x39, { { 2, { DwarfClass::kConstant } } }, "DW_AT_decl_column" },
266 { 0x3a, { { 2, { DwarfClass::kConstant } } }, "DW_AT_decl_file" },
267 { 0x3b, { { 2, { DwarfClass::kConstant } } }, "DW_AT_decl_line" },
268 { 0x3c, { { 2, { DwarfClass::kFlag } } }, "DW_AT_declaration" },
269 { 0x3d, { { 2, { DwarfClass::kBlock } } }, "DW_AT_discr_list" },
270 { 0x3e, { { 2, { DwarfClass::kConstant } } }, "DW_AT_encoding" },
271 { 0x3f, { { 2, { DwarfClass::kFlag } } }, "DW_AT_external" },
272 { 0x40, {
273 { 2, { DwarfClass::kBlock, DwarfClass::kConstant } },
274 { 3, { DwarfClass::kBlock, DwarfClass::kLoclistsptr } },
275 { 4, { DwarfClass::kExprloc, DwarfClass::kLoclistsptr } },
276 { 5, { DwarfClass::kExprloc, /* DwarfClass::kLoclist */ } },
277 }, "DW_AT_frame_base" },
278 { 0x41, { { 2, { DwarfClass::kReference } } }, "DW_AT_friend" },
279 { 0x42, { { 2, { DwarfClass::kConstant } } }, "DW_AT_identifier_case" },
280 { 0x43, {
281 { 2, { DwarfClass::kConstant } },
282 { 3, { DwarfClass::kMacptr } },
283 }, "DW_AT_macro_info" }, // Removed in dwarf5??
284 { 0x44, {
285 { 2, { DwarfClass::kBlock } },
286 { 4, { DwarfClass::kReference } },
287 }, "DW_AT_namelist_item" },
288 { 0x45, { { 2, { DwarfClass::kReference } } }, "DW_AT_priority" },
289 { 0x46, {
290 { 2, { DwarfClass::kBlock, DwarfClass::kConstant } },
291 { 3, { DwarfClass::kBlock, DwarfClass::kLoclistsptr } },
292 { 4, { DwarfClass::kExprloc, DwarfClass::kLoclistsptr } },
293 { 5, { DwarfClass::kExprloc, /* DwarfClass::kLoclist */ } },
294 }, "DW_AT_segment" },
295 { 0x47, { { 2, { DwarfClass::kReference } } }, "DW_AT_specification" },
296 { 0x48, {
297 { 2, { DwarfClass::kBlock, DwarfClass::kConstant } },
298 { 3, { DwarfClass::kBlock, DwarfClass::kLoclistsptr } },
299 { 4, { DwarfClass::kExprloc, DwarfClass::kLoclistsptr } },
300 { 5, { DwarfClass::kExprloc, /* DwarfClass::kLoclist */ } },
301 }, "DW_AT_static_link" },
302 { 0x49, { { 2, { DwarfClass::kReference } } }, "DW_AT_type" },
303 { 0x4a, {
304 { 2, { DwarfClass::kBlock, DwarfClass::kConstant } },
305 { 3, { DwarfClass::kBlock, DwarfClass::kLoclistsptr } },
306 { 4, { DwarfClass::kExprloc, DwarfClass::kLoclistsptr } },
307 { 5, { DwarfClass::kExprloc, /* DwarfClass::kLoclist */ } },
308 }, "DW_AT_use_location" },
309 { 0x4b, { { 2, { DwarfClass::kFlag } } }, "DW_AT_variable_parameter" },
310 { 0x4c, { { 2, { DwarfClass::kConstant } } }, "DW_AT_virtuality" },
311 { 0x4d, {
312 { 2, { DwarfClass::kBlock, DwarfClass::kReference } },
313 { 3, { DwarfClass::kBlock, DwarfClass::kLoclistsptr } },
314 { 4, { DwarfClass::kExprloc, DwarfClass::kLoclistsptr } },
315 { 5, { DwarfClass::kExprloc, /* DwarfClass::kLoclist */ } },
316 }, "DW_AT_vtable_elem_location" },
317 // Dwarf 3
318 { 0x4e, {
319 { 3, { DwarfClass::kBlock, DwarfClass::kConstant, DwarfClass::kReference } },
320 { 4, { DwarfClass::kConstant, DwarfClass::kExprloc, DwarfClass::kReference } },
321 }, "DW_AT_allocated" },
322 { 0x4f, {
323 { 3, { DwarfClass::kBlock, DwarfClass::kConstant, DwarfClass::kReference } },
324 { 4, { DwarfClass::kConstant, DwarfClass::kExprloc, DwarfClass::kReference } },
325 }, "DW_AT_associated" },
326 { 0x50, {
327 { 3, { DwarfClass::kBlock } },
328 { 4, { DwarfClass::kExprloc } },
329 }, "DW_AT_data_location" },
330 { 0x51, {
331 { 3, { DwarfClass::kBlock, DwarfClass::kConstant, DwarfClass::kReference } },
332 { 4, { DwarfClass::kConstant, DwarfClass::kExprloc, DwarfClass::kReference } },
333 }, "DW_AT_byte_stride" },
334 { 0x52, {
335 { 3, { DwarfClass::kAddress } },
336 { 5, { DwarfClass::kAddress, DwarfClass::kConstant } },
337 }, "DW_AT_entry_pc" },
338 { 0x53, { { 3, { DwarfClass::kFlag } } }, "DW_AT_use_UTF8" },
339 { 0x54, { { 3, { DwarfClass::kReference } } }, "DW_AT_extension" },
340 { 0x55, {
341 { 2, { DwarfClass::kConstant } }, // not in spec, but clang uses this in dwarf2??
342 { 3, { DwarfClass::kRnglistsptr } },
343 { 5, { DwarfClass::kRnglist } },
344 }, "DW_AT_ranges" },
345 { 0x56, {
346 { 3, { DwarfClass::kAddress,
347 DwarfClass::kFlag,
348 DwarfClass::kReference,
349 DwarfClass::kString } },
350 }, "DW_AT_trampoline" },
351 { 0x57, { { 3, { DwarfClass::kConstant } } }, "DW_AT_call_column" },
352 { 0x58, { { 3, { DwarfClass::kConstant } } }, "DW_AT_call_file" },
353 { 0x59, { { 3, { DwarfClass::kConstant } } }, "DW_AT_call_line" },
354 { 0x5a, { { 3, { DwarfClass::kString } } }, "DW_AT_description" },
355 { 0x5b, { { 3, { DwarfClass::kConstant } } }, "DW_AT_binary_scale" },
356 { 0x5c, { { 3, { DwarfClass::kConstant } } }, "DW_AT_decimal_scale" },
357 { 0x5d, { { 3, { DwarfClass::kReference } } }, "DW_AT_small" },
358 { 0x5e, { { 3, { DwarfClass::kConstant } } }, "DW_AT_decimal_sign" },
359 { 0x5f, { { 3, { DwarfClass::kConstant } } }, "DW_AT_digit_count" },
360 { 0x60, { { 3, { DwarfClass::kString } } }, "DW_AT_picture_string" },
361 { 0x61, { { 3, { DwarfClass::kFlag } } }, "DW_AT_mutable" },
362 { 0x62, { { 3, { DwarfClass::kFlag } } }, "DW_AT_thread_scaled" },
363 { 0x63, { { 3, { DwarfClass::kFlag } } }, "DW_AT_explicit" },
364 { 0x64, { { 3, { DwarfClass::kReference } } }, "DW_AT_object_pointer" },
365 { 0x65, { { 3, { DwarfClass::kConstant } } }, "DW_AT_endianity" },
366 { 0x66, { { 3, { DwarfClass::kFlag } } }, "DW_AT_elemental" },
367 { 0x67, { { 3, { DwarfClass::kFlag } } }, "DW_AT_pure" },
368 { 0x68, { { 3, { DwarfClass::kFlag } } }, "DW_AT_recursive" },
369 // Dwarf 4
370 { 0x69, { { 4, { DwarfClass::kReference } } }, "DW_AT_signature" },
371 { 0x6a, { { 4, { DwarfClass::kFlag } } }, "DW_AT_main_subprogram" },
372 { 0x6b, { { 4, { DwarfClass::kConstant } } }, "DW_AT_data_bit_offset" },
373 { 0x6c, { { 4, { DwarfClass::kFlag } } }, "DW_AT_const_expr" },
374 { 0x6d, { { 4, { DwarfClass::kFlag } } }, "DW_AT_enum_class" },
375 { 0x6e, { { 4, { DwarfClass::kString } } }, "DW_AT_linkage_name" },
376 // Dwarf 5
377 { 0x6f, { { 5, { DwarfClass::kConstant } } }, "DW_AT_string_length_bit_size" },
378 { 0x70, { { 5, { DwarfClass::kConstant } } }, "DW_AT_string_length_byte_size" },
379 { 0x71, { { 5, { DwarfClass::kConstant, DwarfClass::kExprloc } } }, "DW_AT_rank" },
380 { 0x72, { { 5, { DwarfClass::kStroffsetsptr } } }, "DW_AT_str_offset_base" },
381 { 0x73, { { 5, { DwarfClass::kAddrptr } } }, "DW_AT_addr_base" },
382 { 0x74, { { 5, { DwarfClass::kRnglistsptr } } }, "DW_AT_rnglists_base" },
383 { 0x75, { }, "Unused 0x75" },
384 { 0x76, { { 5, { DwarfClass::kString } } }, "DW_AT_dwo_name" },
385 // The following are dwarf 5 by spec but clang still injects it to dwarf4
386 { 0x77, { { 4, { DwarfClass::kFlag } } }, "DW_AT_reference" },
387 { 0x78, { { 4, { DwarfClass::kFlag } } }, "DW_AT_rvalue_reference" },
388 { 0x79, { { 5, { DwarfClass::kMacptr } } }, "DW_AT_macros" },
389 { 0x7a, { { 5, { DwarfClass::kFlag } } }, "DW_AT_call_all_calls" },
390 { 0x7b, { { 5, { DwarfClass::kFlag } } }, "DW_AT_call_all_source_calls" },
391 { 0x7c, { { 5, { DwarfClass::kFlag } } }, "DW_AT_call_all_tail_calls" },
392 { 0x7d, { { 5, { DwarfClass::kAddress } } }, "DW_AT_call_return_pc" },
393 { 0x7e, { { 5, { DwarfClass::kExprloc } } }, "DW_AT_call_value" },
394 // kReference is not allowed for DW_AT_call_origin by DWARF5 standard, but it is used by clang
395 { 0x7f, { { 5, { DwarfClass::kExprloc, DwarfClass::kReference } } }, "DW_AT_call_origin" },
396 { 0x80, { { 5, { DwarfClass::kReference } } }, "DW_AT_call_parameter" },
397 { 0x81, { { 5, { DwarfClass::kAddress } } }, "DW_AT_call_pc" },
398 { 0x82, { { 5, { DwarfClass::kFlag } } }, "DW_AT_call_tail_call" },
399 { 0x83, { { 5, { DwarfClass::kExprloc } } }, "DW_AT_call_target" },
400 { 0x84, { { 5, { DwarfClass::kExprloc } } }, "DW_AT_call_target_clobbered" },
401 { 0x85, { { 5, { DwarfClass::kExprloc } } }, "DW_AT_call_data_location" },
402 { 0x86, { { 5, { DwarfClass::kExprloc } } }, "DW_AT_call_data_value" },
403 // Apparently clang uses these in dwarf4 CUs
404 { 0x87, { { 4, { DwarfClass::kFlag } } }, "DW_AT_noreturn" },
405 { 0x88, { { 4, { DwarfClass::kConstant } } }, "DW_AT_alignment" },
406 { 0x89, { { 4, { DwarfClass::kFlag } } }, "DW_AT_export_symbols" },
407 { 0x8a, { { 5, { DwarfClass::kFlag } } }, "DW_AT_deleted" },
408 { 0x8b, { { 5, { DwarfClass::kConstant } } }, "DW_AT_defaulted" },
409 { 0x8c, { { 5, { DwarfClass::kLoclistsptr } } }, "DW_AT_loclists_base" },
410 };
411 // clang-format on
412
413 static_assert(sizeof(kFormDescriptors) / sizeof(AbbrevDescriptor) == (DW_FORM_MAX_VALUE + 1), "");
414 static_assert(sizeof(kNameDescriptors) / sizeof(AbbrevDescriptor) == (DW_AT_MAX_VALUE + 1), "");
415
416 const AbbrevDescriptor kAtGnuVector = {0x2107, {DwarfClass::kFlag}, "DW_AT_GNU_vector"};
417
418 const AbbrevDescriptor kAtGnuTemplateName = {0x2110,
419 {DwarfClass::kString},
420 "DW_AT_GNU_template_name"};
421
422 const AbbrevDescriptor kAtGnuCallSiteValue = {0x2111,
423 {DwarfClass::kExprloc},
424 "DW_AT_GNU_call_site_value"};
425
426 const AbbrevDescriptor kAtGnuCallSiteTarget = {0x2113,
427 {DwarfClass::kExprloc},
428 "DW_AT_GNU_call_site_target"};
429
430 const AbbrevDescriptor kAtGnuTailCall = {0x2115, {DwarfClass::kFlag}, "DW_AT_GNU_tail_call"};
431
432 const AbbrevDescriptor kAtGnuAllTailCallSites = {0x2116,
433 {DwarfClass::kFlag},
434 "DW_AT_GNU_all_tail_call_sites"};
435
436 const AbbrevDescriptor kAtGnuAllCallSites = {0x2117,
437 {DwarfClass::kFlag},
438 "DW_AT_GNU_all_call_sites"};
439
440 const AbbrevDescriptor kAtGnuPubnamesDescriptor = {0x2134,
441 {DwarfClass::kFlag},
442 "DW_AT_GNU_pubnames"};
443
444 const AbbrevDescriptor kAtGnuDiscriminator = {0x2136,
445 {DwarfClass::kConstant},
446 "DW_AT_GNU_discriminator"};
447
448 const AbbrevDescriptor kAtGnuLocviews = {0x2137, {DwarfClass::kLoclistsptr}, "DW_AT_GNU_locviews"};
449
450 const AbbrevDescriptor kAtGnuEntryView = {0x2138, {DwarfClass::kConstant}, "DW_AT_GNU_entry_view"};
451
GetNameDescriptor(uint32_t name)452 const AbbrevDescriptor* GetNameDescriptor(uint32_t name) {
453 switch (name) {
454 case DW_AT_GNU_vector:
455 return &kAtGnuVector;
456 case DW_AT_GNU_template_name:
457 return &kAtGnuTemplateName;
458 case DW_AT_GNU_call_site_value:
459 return &kAtGnuCallSiteValue;
460 case DW_AT_GNU_call_site_target:
461 return &kAtGnuCallSiteTarget;
462 case DW_AT_GNU_tail_call:
463 return &kAtGnuTailCall;
464 case DW_AT_GNU_all_tail_call_sites:
465 return &kAtGnuAllTailCallSites;
466 case DW_AT_GNU_all_call_sites:
467 return &kAtGnuAllCallSites;
468 case DW_AT_GNU_pubnames:
469 return &kAtGnuPubnamesDescriptor;
470 case DW_AT_GNU_discriminator:
471 return &kAtGnuDiscriminator;
472 case DW_AT_GNU_locviews:
473 return &kAtGnuLocviews;
474 case DW_AT_GNU_entry_view:
475 return &kAtGnuEntryView;
476 }
477
478 if (name > DW_AT_MAX_VALUE) {
479 return nullptr;
480 }
481
482 return kNameDescriptors + name;
483 }
484
NameToString(uint32_t name)485 std::string NameToString(uint32_t name) {
486 auto descriptor = GetNameDescriptor(name);
487 if (descriptor == nullptr) {
488 return StringPrintf("unknown-0x%x", name);
489 }
490
491 return descriptor->name;
492 }
493
FormToString(uint32_t form)494 std::string FormToString(uint32_t form) {
495 if (form >= DW_FORM_MAX_VALUE) {
496 return StringPrintf("unknown-0x%x", form);
497 }
498
499 return kFormDescriptors[form].name;
500 }
501
502 class DwarfClassAddress : public DwarfClass {
503 public:
DwarfClassAddress()504 DwarfClassAddress() : DwarfClass("address") {}
ReadAttribute(const DwarfCompilationUnitHeader * cu,const DwarfAbbrevAttribute * abbrev_attr,DwarfContext * context,std::string * error_msg) const505 virtual std::unique_ptr<DwarfAttribute> ReadAttribute(const DwarfCompilationUnitHeader* cu,
506 const DwarfAbbrevAttribute* abbrev_attr,
507 DwarfContext* context,
508 std::string* error_msg) const override {
509 ByteInputStream* bs = context->info_stream();
510
511 uint64_t address;
512 uint32_t form = abbrev_attr->form();
513 uint32_t name = abbrev_attr->name();
514 if (form == DW_FORM_addr) {
515 uint8_t address_size = cu->address_size();
516 if (address_size != 4 && address_size != 8) {
517 *error_msg = StringPrintf("Invalid address size %d (expected 4 or 8)", address_size);
518 return nullptr;
519 }
520 address = address_size == 4 ? bs->ReadUint32() : bs->ReadUint64();
521 } else if (form == DW_FORM_addrx || form == DW_FORM_addrx1 || form == DW_FORM_addrx2 ||
522 form == DW_FORM_addrx3 || form == DW_FORM_addrx4) {
523 address = bs->ReadLeb128();
524 } else {
525 *error_msg = StringPrintf("%s:%d:%s: Unsupported form %s for class: %s",
526 __FILE__,
527 __LINE__,
528 __FUNCTION__,
529 FormToString(form).c_str(),
530 NameToString(name).c_str());
531 return nullptr;
532 }
533
534 return std::unique_ptr<DwarfAttribute>(new DwarfAttributeValue<uint64_t>(name, address));
535 }
536 };
537
538 class DwarfClassBlock : public DwarfClass {
539 public:
DwarfClassBlock()540 DwarfClassBlock() : DwarfClass("block") {}
ReadAttribute(const DwarfCompilationUnitHeader *,const DwarfAbbrevAttribute * abbrev_attr,DwarfContext * context,std::string * error_msg) const541 virtual std::unique_ptr<DwarfAttribute> ReadAttribute(const DwarfCompilationUnitHeader*,
542 const DwarfAbbrevAttribute* abbrev_attr,
543 DwarfContext* context,
544 std::string* error_msg) const override {
545 ByteInputStream* bs = context->info_stream();
546
547 uint64_t size = 0;
548 uint32_t form = abbrev_attr->form();
549 uint32_t name = abbrev_attr->name();
550
551 switch (form) {
552 case DW_FORM_block1:
553 size = bs->ReadUint8();
554 break;
555 case DW_FORM_block2:
556 size = bs->ReadUint16();
557 break;
558 case DW_FORM_block4:
559 size = bs->ReadUint32();
560 break;
561 case DW_FORM_block:
562 size = bs->ReadLeb128();
563 break;
564 default:
565 *error_msg = StringPrintf("%s:%d:%s: Unsupported form %s for class: %s",
566 __FILE__,
567 __LINE__,
568 __FUNCTION__,
569 FormToString(form).c_str(),
570 NameToString(name).c_str());
571 return nullptr;
572 }
573
574 std::vector<uint8_t> data = bs->ReadBytes(size);
575
576 return std::unique_ptr<DwarfAttribute>(
577 new DwarfAttributeValue<std::vector<uint8_t>>(name, std::move(data)));
578 }
579 };
580
581 class DwarfClassConstant : public DwarfClass {
582 public:
DwarfClassConstant()583 DwarfClassConstant() : DwarfClass("constant") {}
ReadAttribute(const DwarfCompilationUnitHeader *,const DwarfAbbrevAttribute * abbrev_attr,DwarfContext * context,std::string * error_msg) const584 virtual std::unique_ptr<DwarfAttribute> ReadAttribute(const DwarfCompilationUnitHeader*,
585 const DwarfAbbrevAttribute* abbrev_attr,
586 DwarfContext* context,
587 std::string* error_msg) const override {
588 ByteInputStream* bs = context->info_stream();
589
590 uint64_t size = 0;
591 uint32_t form = abbrev_attr->form();
592 uint32_t name = abbrev_attr->name();
593
594 if (form == DW_FORM_implicit_const) {
595 return std::unique_ptr<DwarfAttribute>(
596 new DwarfAttributeValue<int64_t>(name, abbrev_attr->value()));
597 }
598
599 if (form == DW_FORM_sdata) {
600 return std::unique_ptr<DwarfAttribute>(
601 new DwarfAttributeValue<int64_t>(name, bs->ReadSleb128()));
602 }
603
604 if (form == DW_FORM_udata) {
605 return std::unique_ptr<DwarfAttribute>(
606 new DwarfAttributeValue<uint64_t>(name, bs->ReadLeb128()));
607 }
608
609 switch (form) {
610 case DW_FORM_data1:
611 size = 1;
612 break;
613 case DW_FORM_data2:
614 size = 2;
615 break;
616 case DW_FORM_data4:
617 size = 4;
618 break;
619 case DW_FORM_data8:
620 size = 8;
621 break;
622 case DW_FORM_data16:
623 size = 16;
624 break;
625 default:
626 *error_msg = StringPrintf("%s:%d:%s: Unsupported form %s for class: %s",
627 __FILE__,
628 __LINE__,
629 __FUNCTION__,
630 FormToString(form).c_str(),
631 NameToString(name).c_str());
632 return nullptr;
633 }
634
635 std::vector<uint8_t> data = bs->ReadBytes(size);
636
637 return std::unique_ptr<DwarfAttribute>(
638 new DwarfAttributeValue<std::vector<uint8_t>>(name, std::move(data)));
639 }
640 };
641
642 class DwarfClassExprloc : public DwarfClass {
643 public:
DwarfClassExprloc()644 DwarfClassExprloc() : DwarfClass("exprloc") {}
ReadAttribute(const DwarfCompilationUnitHeader *,const DwarfAbbrevAttribute * abbrev_attr,DwarfContext * context,std::string * error_msg) const645 virtual std::unique_ptr<DwarfAttribute> ReadAttribute(const DwarfCompilationUnitHeader*,
646 const DwarfAbbrevAttribute* abbrev_attr,
647 DwarfContext* context,
648 std::string* error_msg) const override {
649 ByteInputStream* bs = context->info_stream();
650
651 uint32_t form = abbrev_attr->form();
652 uint32_t name = abbrev_attr->name();
653
654 if (form != DW_FORM_exprloc) {
655 *error_msg = StringPrintf("%s:%d:%s: Unsupported form %s for class: %s",
656 __FILE__,
657 __LINE__,
658 __FUNCTION__,
659 FormToString(form).c_str(),
660 NameToString(name).c_str());
661 return nullptr;
662 }
663
664 uint64_t length = bs->ReadLeb128();
665
666 return std::unique_ptr<DwarfAttribute>(
667 new DwarfAttributeValue<std::vector<uint8_t>>(name, bs->ReadBytes(length)));
668 }
669 };
670
671 class DwarfClassFlag : public DwarfClass {
672 public:
DwarfClassFlag()673 DwarfClassFlag() : DwarfClass("flag") {}
ReadAttribute(const DwarfCompilationUnitHeader *,const DwarfAbbrevAttribute * abbrev_attr,DwarfContext * context,std::string * error_msg) const674 virtual std::unique_ptr<DwarfAttribute> ReadAttribute(const DwarfCompilationUnitHeader*,
675 const DwarfAbbrevAttribute* abbrev_attr,
676 DwarfContext* context,
677 std::string* error_msg) const override {
678 ByteInputStream* bs = context->info_stream();
679
680 uint32_t form = abbrev_attr->form();
681 uint32_t name = abbrev_attr->name();
682
683 bool value;
684
685 if (form == DW_FORM_flag_present) {
686 value = true;
687 } else if (form == DW_FORM_flag) {
688 value = bs->ReadUint8();
689 } else {
690 *error_msg = StringPrintf("%s:%d:%s: Unsupported form %s for class: %s",
691 __FILE__,
692 __LINE__,
693 __FUNCTION__,
694 FormToString(form).c_str(),
695 NameToString(name).c_str());
696 return nullptr;
697 }
698
699 return std::unique_ptr<DwarfAttribute>(new DwarfAttributeValue<bool>(name, value));
700 }
701 };
702
703 // Use this implementation for classes where we are not interested in the value
704 // This one reads offset and puts it into attribute list. It does not read the
705 // actual value from the corresponding target segment.
706 class DwarfClassBaseptr : public DwarfClass {
707 public:
DwarfClassBaseptr(const char * name)708 explicit DwarfClassBaseptr(const char* name) : DwarfClass(name) {}
ReadAttribute(const DwarfCompilationUnitHeader * cu,const DwarfAbbrevAttribute * abbrev_attr,DwarfContext * context,std::string * error_msg) const709 virtual std::unique_ptr<DwarfAttribute> ReadAttribute(const DwarfCompilationUnitHeader* cu,
710 const DwarfAbbrevAttribute* abbrev_attr,
711 DwarfContext* context,
712 std::string* error_msg) const override {
713 ByteInputStream* bs = context->info_stream();
714
715 uint32_t form = abbrev_attr->form();
716 uint32_t name = abbrev_attr->name();
717
718 if (form == DW_FORM_sec_offset) {
719 uint64_t offset = cu->is_dwarf64() ? bs->ReadUint64() : bs->ReadUint32();
720 return std::make_unique<DwarfAttributeValue<uint64_t>>(name, offset);
721 }
722
723 if (form == DW_FORM_rnglistx || form == DW_FORM_loclistx) {
724 return std::make_unique<DwarfAttributeValue<uint64_t>>(name, bs->ReadLeb128());
725 }
726
727 *error_msg = StringPrintf("%s:%d:%s: Unsupported form %s for class: %s",
728 __FILE__,
729 __LINE__,
730 __FUNCTION__,
731 FormToString(form).c_str(),
732 NameToString(name).c_str());
733 return nullptr;
734 }
735 };
736
737 class DwarfClassReference : public DwarfClass {
738 public:
DwarfClassReference()739 DwarfClassReference() : DwarfClass("reference") {}
ReadAttribute(const DwarfCompilationUnitHeader * cu,const DwarfAbbrevAttribute * abbrev_attr,DwarfContext * context,std::string * error_msg) const740 [[nodiscard]] std::unique_ptr<DwarfAttribute> ReadAttribute(
741 const DwarfCompilationUnitHeader* cu,
742 const DwarfAbbrevAttribute* abbrev_attr,
743 DwarfContext* context,
744 std::string* error_msg) const override {
745 ByteInputStream* bs = context->info_stream();
746
747 uint32_t form = abbrev_attr->form();
748 uint32_t name = abbrev_attr->name();
749
750 uint64_t offset = 0;
751 switch (form) {
752 case DW_FORM_ref1:
753 offset = cu->unit_offset() + bs->ReadUint8();
754 break;
755 case DW_FORM_ref2:
756 offset = cu->unit_offset() + bs->ReadUint16();
757 break;
758 case DW_FORM_ref4:
759 offset = cu->unit_offset() + bs->ReadUint32();
760 break;
761 case DW_FORM_ref8:
762 offset = cu->unit_offset() + bs->ReadUint64();
763 break;
764 case DW_FORM_ref_udata:
765 offset = cu->unit_offset() + bs->ReadLeb128();
766 break;
767 case DW_FORM_ref_addr:
768 offset = cu->is_dwarf64() ? bs->ReadUint64() : bs->ReadUint32();
769 break;
770 // TODO(dimitry): DW_FORM_ref_sig8?
771 default:
772 *error_msg = StringPrintf("%s:%d:%s: Unsupported form %s for class: %s",
773 __FILE__,
774 __LINE__,
775 __FUNCTION__,
776 FormToString(form).c_str(),
777 NameToString(name).c_str());
778 return nullptr;
779 }
780
781 return std::unique_ptr<DwarfAttribute>(new DwarfAttributeValue<uint64_t>(name, offset));
782 }
783 };
784
785 class DwarfClassString : public DwarfClass {
786 public:
DwarfClassString()787 DwarfClassString() : DwarfClass("string") {}
788
ReadAttribute(const DwarfCompilationUnitHeader * cu,const DwarfAbbrevAttribute * abbrev_attr,DwarfContext * context,std::string * error_msg) const789 [[nodiscard]] std::unique_ptr<DwarfAttribute> ReadAttribute(
790 const DwarfCompilationUnitHeader* cu,
791 const DwarfAbbrevAttribute* abbrev_attr,
792 DwarfContext* context,
793 std::string* error_msg) const override {
794 ByteInputStream* bs = context->info_stream();
795
796 uint32_t form = abbrev_attr->form();
797 uint32_t name = abbrev_attr->name();
798
799 switch (form) {
800 case DW_FORM_string:
801 // This form should be deprecated...
802 return std::make_unique<DwarfAttributeValue<std::string>>(name, bs->ReadString());
803 case DW_FORM_strp: {
804 uint64_t offset = cu->is_dwarf64() ? bs->ReadUint64() : bs->ReadUint32();
805 std::string value = context->debug_str_table()->GetString(offset);
806 return std::make_unique<DwarfAttributeValue<std::string>>(name, value);
807 }
808 case DW_FORM_strx:
809 return std::make_unique<DwarfStrXAttribute>(name, bs->ReadLeb128());
810 case DW_FORM_strx1:
811 return std::make_unique<DwarfStrXAttribute>(name, bs->ReadUint8());
812 case DW_FORM_strx2:
813 return std::make_unique<DwarfStrXAttribute>(name, bs->ReadUint16());
814 case DW_FORM_strx3:
815 return std::make_unique<DwarfStrXAttribute>(name, bs->ReadUint24());
816 case DW_FORM_strx4:
817 return std::make_unique<DwarfStrXAttribute>(name, bs->ReadUint32());
818 default:
819 // We do not support supplemental object files and debug_line_str (DW_FORM_line_strp) atm.
820 *error_msg = StringPrintf("%s:%d:%s: Unsupported form %s for class: %s",
821 __FILE__,
822 __LINE__,
823 __FUNCTION__,
824 FormToString(form).c_str(),
825 NameToString(name).c_str());
826 return nullptr;
827 }
828 }
829 };
830
FindDwarfClass(uint16_t version,uint32_t name,uint32_t form,std::string * error_msg)831 const DwarfClass* FindDwarfClass(uint16_t version,
832 uint32_t name,
833 uint32_t form,
834 std::string* error_msg) {
835 if (form > DW_FORM_MAX_VALUE) {
836 *error_msg = StringPrintf("Invalid abbrev attribute form: 0x%x", form);
837 return nullptr;
838 }
839
840 auto name_descriptor = GetNameDescriptor(name);
841 if (name_descriptor == nullptr) {
842 *error_msg = StringPrintf("Invalid abbrev attribute name: 0x%x", name);
843 return nullptr;
844 }
845
846 auto name_classes = name_descriptor->classes.get(version);
847 if (name_classes == nullptr) {
848 *error_msg = StringPrintf(
849 "failed to lookup classes for %s (0x%x) version=%d", name_descriptor->name, name, version);
850 return nullptr;
851 }
852
853 auto& form_descriptor = kFormDescriptors[form];
854 auto form_classes = form_descriptor.classes.get(version);
855
856 if (form_classes == nullptr) {
857 *error_msg = StringPrintf(
858 "failed to lookup classes for %s (0x%x) version=%d", form_descriptor.name, form, version);
859 return nullptr;
860 }
861
862 // Check if the class identified by form actually in the list of classes
863 // supported by name
864 const DwarfClass* result = nullptr;
865 for (auto form_class : *form_classes) {
866 for (auto name_class : *name_classes) {
867 if (name_class == form_class) { // found valid combination
868 if (result != nullptr) {
869 *error_msg = StringPrintf(
870 "Incompatible combination of form %s(%x) and name %s(%x): "
871 "Found more than one intersection of classes (%s and %s)",
872 form_descriptor.name,
873 form,
874 name_descriptor->name,
875 name,
876 result->name(),
877 name_class->name());
878 return nullptr;
879 }
880
881 result = name_class;
882 }
883 }
884 }
885
886 if (result == nullptr) {
887 *error_msg = StringPrintf("form %s (0x%x) is not applicable to the name %s (0x%x) version=%d.",
888 form_descriptor.name,
889 form,
890 name_descriptor->name,
891 name,
892 version);
893 }
894
895 return result;
896 }
897
898 DwarfClassAddress g_class_address;
899 DwarfClassBaseptr g_class_addrptr("addrptr");
900 DwarfClassBlock g_class_block;
901 DwarfClassConstant g_class_constant;
902 DwarfClassExprloc g_class_exprloc;
903 DwarfClassFlag g_class_flag;
904 DwarfClassBaseptr g_class_lineptr("lineptr");
905 DwarfClassBaseptr g_class_loclist("loclist");
906 DwarfClassBaseptr g_class_loclistptr("loclistptr");
907 DwarfClassBaseptr g_class_macptr("macptr");
908 DwarfClassReference g_class_reference;
909 DwarfClassBaseptr g_class_rnglist("rnglist");
910 DwarfClassBaseptr g_class_rnglistptr("rnglistptr");
911 DwarfClassString g_class_string;
912 DwarfClassBaseptr g_class_stroffsetsptr("rnglistptr");
913
914 } // namespace
915
916 const DwarfClass* DwarfClass::kAddress = &g_class_address;
917 const DwarfClass* DwarfClass::kAddrptr = &g_class_addrptr;
918 const DwarfClass* DwarfClass::kBlock = &g_class_block;
919 const DwarfClass* DwarfClass::kConstant = &g_class_constant;
920 const DwarfClass* DwarfClass::kFlag = &g_class_flag;
921 const DwarfClass* DwarfClass::kExprloc = &g_class_exprloc;
922 const DwarfClass* DwarfClass::kLineptr = &g_class_lineptr;
923 const DwarfClass* DwarfClass::kLoclist = &g_class_loclist;
924 const DwarfClass* DwarfClass::kLoclistsptr = &g_class_loclistptr;
925 const DwarfClass* DwarfClass::kMacptr = &g_class_macptr;
926 const DwarfClass* DwarfClass::kReference = &g_class_reference;
927 const DwarfClass* DwarfClass::kRnglist = &g_class_rnglist;
928 const DwarfClass* DwarfClass::kRnglistsptr = &g_class_rnglistptr;
929 const DwarfClass* DwarfClass::kString = &g_class_string;
930 const DwarfClass* DwarfClass::kStroffsetsptr = &g_class_stroffsetsptr;
931
DwarfClass(const char * name)932 DwarfClass::DwarfClass(const char* name) : name_{name} {}
933
name() const934 const char* DwarfClass::name() const {
935 return name_;
936 }
937
DwarfAttribute(uint32_t name)938 DwarfAttribute::DwarfAttribute(uint32_t name) : name_(name) {}
939
940 template <typename T>
StringValue() const941 std::optional<std::string> DwarfAttributeValue<T>::StringValue() const {
942 return {};
943 }
944
945 template <typename T>
Uint64Value() const946 std::optional<uint64_t> DwarfAttributeValue<T>::Uint64Value() const {
947 return {};
948 }
949
950 template <typename T>
BoolValue() const951 std::optional<bool> DwarfAttributeValue<T>::BoolValue() const {
952 return {};
953 }
954 template <typename T>
Resolve(DwarfContext *)955 void DwarfAttributeValue<T>::Resolve(DwarfContext* /*context*/) {}
956
957 template <>
StringValue() const958 std::optional<std::string> DwarfAttributeValue<std::string>::StringValue() const {
959 return value_;
960 }
961
962 template <>
Uint64Value() const963 std::optional<uint64_t> DwarfAttributeValue<uint64_t>::Uint64Value() const {
964 return value_;
965 }
966
967 template <>
Uint64Value() const968 std::optional<uint64_t> DwarfAttributeValue<std::vector<uint8_t>>::Uint64Value() const {
969 CHECK(value_.size() <= sizeof(uint64_t));
970 uint64_t result = 0;
971 memcpy(&result, value_.data(), value_.size());
972 return result;
973 }
974
975 template <>
BoolValue() const976 std::optional<bool> DwarfAttributeValue<bool>::BoolValue() const {
977 return value_;
978 }
979
StringValue() const980 std::optional<std::string> DwarfStrXAttribute::StringValue() const {
981 // At this point we expect the string to exist.
982 CHECK(string_.has_value());
983 return string_.value();
984 }
985
Resolve(DwarfContext * context)986 void DwarfStrXAttribute::Resolve(DwarfContext* context) {
987 CHECK(context->str_offsets_base().has_value());
988 CHECK(context->string_offset_table().has_value());
989 uint64_t string_offset =
990 context->string_offset_table()->GetStringOffset(context->str_offsets_base().value(), index_);
991 string_.emplace(context->debug_str_table()->GetString(string_offset));
992 }
993
CreateAbbrevAttribute(uint16_t version,uint32_t name,uint32_t form,int64_t value,std::string * error_msg)994 std::unique_ptr<const DwarfAbbrevAttribute> DwarfAbbrevAttribute::CreateAbbrevAttribute(
995 uint16_t version,
996 uint32_t name,
997 uint32_t form,
998 int64_t value,
999 std::string* error_msg) {
1000 // TODO(dimitry): support DW_FORM_indirect, might require some refactoring of DwarfClass
1001 if (form == DW_FORM_indirect) {
1002 *error_msg = "DW_FORM_indirect is not yet supported.";
1003 return nullptr;
1004 }
1005
1006 const DwarfClass* dwarf_class = FindDwarfClass(version, name, form, error_msg);
1007
1008 if (dwarf_class == nullptr) {
1009 return nullptr;
1010 }
1011
1012 return std::make_unique<DwarfAbbrevAttribute>(name, form, value, dwarf_class);
1013 }
1014
DwarfCompilationUnitHeader(uint64_t unit_offset,uint64_t unit_length,uint16_t version,uint64_t abbrev_offset,uint8_t address_size,bool is_dwarf64)1015 DwarfCompilationUnitHeader::DwarfCompilationUnitHeader(uint64_t unit_offset,
1016 uint64_t unit_length,
1017 uint16_t version,
1018 uint64_t abbrev_offset,
1019 uint8_t address_size,
1020 bool is_dwarf64)
1021 : unit_offset_(unit_offset),
1022 unit_length_(unit_length),
1023 version_(version),
1024 abbrev_offset_(abbrev_offset),
1025 address_size_(address_size),
1026 is_dwarf64_(is_dwarf64) {}
1027
DwarfAbbrev()1028 DwarfAbbrev::DwarfAbbrev() : code_(0), tag_(0), has_children_(false) {}
1029
DwarfAbbrev(uint64_t code,uint64_t tag,bool has_children)1030 DwarfAbbrev::DwarfAbbrev(uint64_t code, uint64_t tag, bool has_children)
1031 : code_(code), tag_(tag), has_children_(has_children) {}
1032
AddAttribute(std::unique_ptr<const DwarfAbbrevAttribute> && abbrev_attribute)1033 void DwarfAbbrev::AddAttribute(std::unique_ptr<const DwarfAbbrevAttribute>&& abbrev_attribute) {
1034 attributes_.push_back(std::move(abbrev_attribute));
1035 }
1036
DwarfAbbrevAttribute()1037 DwarfAbbrevAttribute::DwarfAbbrevAttribute()
1038 : name_{0}, form_{0}, value_{0}, dwarf_class_{nullptr} {}
1039
DwarfAbbrevAttribute(uint32_t name,uint32_t form,int64_t value,const DwarfClass * dwarf_class)1040 DwarfAbbrevAttribute::DwarfAbbrevAttribute(uint32_t name,
1041 uint32_t form,
1042 int64_t value,
1043 const DwarfClass* dwarf_class)
1044 : name_(name), form_(form), value_(value), dwarf_class_(dwarf_class) {}
1045
1046 } // namespace nogrod
1047