• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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