xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1 //===-- DWARFFormValue.cpp --------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include <assert.h>
10 
11 #include "lldb/Core/Module.h"
12 #include "lldb/Core/dwarf.h"
13 #include "lldb/Symbol/ObjectFile.h"
14 #include "lldb/Utility/Stream.h"
15 
16 #include "DWARFDebugInfo.h"
17 #include "DWARFFormValue.h"
18 #include "DWARFUnit.h"
19 
20 class DWARFUnit;
21 
22 using namespace lldb_private;
23 
24 void DWARFFormValue::Clear() {
25   m_unit = nullptr;
26   m_form = 0;
27   m_value = ValueTypeTag();
28 }
29 
30 bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,
31                                   lldb::offset_t *offset_ptr) {
32   if (m_form == DW_FORM_implicit_const)
33     return true;
34 
35   bool indirect = false;
36   bool is_block = false;
37   m_value.data = nullptr;
38   uint8_t ref_addr_size;
39   // Read the value for the form into value and follow and DW_FORM_indirect
40   // instances we run into
41   do {
42     indirect = false;
43     switch (m_form) {
44     case DW_FORM_addr:
45       assert(m_unit);
46       m_value.value.uval =
47           data.GetMaxU64(offset_ptr, DWARFUnit::GetAddressByteSize(m_unit));
48       break;
49     case DW_FORM_block1:
50       m_value.value.uval = data.GetU8(offset_ptr);
51       is_block = true;
52       break;
53     case DW_FORM_block2:
54       m_value.value.uval = data.GetU16(offset_ptr);
55       is_block = true;
56       break;
57     case DW_FORM_block4:
58       m_value.value.uval = data.GetU32(offset_ptr);
59       is_block = true;
60       break;
61     case DW_FORM_data16:
62       m_value.value.uval = 16;
63       is_block = true;
64       break;
65     case DW_FORM_exprloc:
66     case DW_FORM_block:
67       m_value.value.uval = data.GetULEB128(offset_ptr);
68       is_block = true;
69       break;
70     case DW_FORM_string:
71       m_value.value.cstr = data.GetCStr(offset_ptr);
72       break;
73     case DW_FORM_sdata:
74       m_value.value.sval = data.GetSLEB128(offset_ptr);
75       break;
76     case DW_FORM_strp:
77     case DW_FORM_line_strp:
78     case DW_FORM_sec_offset:
79       m_value.value.uval = data.GetMaxU64(offset_ptr, 4);
80       break;
81     case DW_FORM_addrx1:
82     case DW_FORM_strx1:
83     case DW_FORM_ref1:
84     case DW_FORM_data1:
85     case DW_FORM_flag:
86       m_value.value.uval = data.GetU8(offset_ptr);
87       break;
88     case DW_FORM_addrx2:
89     case DW_FORM_strx2:
90     case DW_FORM_ref2:
91     case DW_FORM_data2:
92       m_value.value.uval = data.GetU16(offset_ptr);
93       break;
94     case DW_FORM_addrx3:
95     case DW_FORM_strx3:
96       m_value.value.uval = data.GetMaxU64(offset_ptr, 3);
97       break;
98     case DW_FORM_addrx4:
99     case DW_FORM_strx4:
100     case DW_FORM_ref4:
101     case DW_FORM_data4:
102       m_value.value.uval = data.GetU32(offset_ptr);
103       break;
104     case DW_FORM_data8:
105     case DW_FORM_ref8:
106     case DW_FORM_ref_sig8:
107       m_value.value.uval = data.GetU64(offset_ptr);
108       break;
109     case DW_FORM_addrx:
110     case DW_FORM_rnglistx:
111     case DW_FORM_strx:
112     case DW_FORM_udata:
113     case DW_FORM_ref_udata:
114     case DW_FORM_GNU_str_index:
115     case DW_FORM_GNU_addr_index:
116       m_value.value.uval = data.GetULEB128(offset_ptr);
117       break;
118     case DW_FORM_ref_addr:
119       assert(m_unit);
120       if (m_unit->GetVersion() <= 2)
121         ref_addr_size = m_unit->GetAddressByteSize();
122       else
123         ref_addr_size = 4;
124       m_value.value.uval = data.GetMaxU64(offset_ptr, ref_addr_size);
125       break;
126     case DW_FORM_indirect:
127       m_form = data.GetULEB128(offset_ptr);
128       indirect = true;
129       break;
130     case DW_FORM_flag_present:
131       m_value.value.uval = 1;
132       break;
133     default:
134       return false;
135     }
136   } while (indirect);
137 
138   if (is_block) {
139     m_value.data = data.PeekData(*offset_ptr, m_value.value.uval);
140     if (m_value.data != nullptr) {
141       *offset_ptr += m_value.value.uval;
142     }
143   }
144 
145   return true;
146 }
147 
148 struct FormSize {
149   uint8_t valid:1, size:7;
150 };
151 static FormSize g_form_sizes[] = {
152   {0,0}, // 0x00 unused
153   {0,0}, // 0x01 DW_FORM_addr
154   {0,0}, // 0x02 unused
155   {0,0}, // 0x03 DW_FORM_block2
156   {0,0}, // 0x04 DW_FORM_block4
157   {1,2}, // 0x05 DW_FORM_data2
158   {1,4}, // 0x06 DW_FORM_data4
159   {1,8}, // 0x07 DW_FORM_data8
160   {0,0}, // 0x08 DW_FORM_string
161   {0,0}, // 0x09 DW_FORM_block
162   {0,0}, // 0x0a DW_FORM_block1
163   {1,1}, // 0x0b DW_FORM_data1
164   {1,1}, // 0x0c DW_FORM_flag
165   {0,0}, // 0x0d DW_FORM_sdata
166   {1,4}, // 0x0e DW_FORM_strp
167   {0,0}, // 0x0f DW_FORM_udata
168   {0,0}, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes for
169          // DWARF32, 8 bytes for DWARF32 in DWARF 3 and later
170   {1,1}, // 0x11 DW_FORM_ref1
171   {1,2}, // 0x12 DW_FORM_ref2
172   {1,4}, // 0x13 DW_FORM_ref4
173   {1,8}, // 0x14 DW_FORM_ref8
174   {0,0}, // 0x15 DW_FORM_ref_udata
175   {0,0}, // 0x16 DW_FORM_indirect
176   {1,4}, // 0x17 DW_FORM_sec_offset
177   {0,0}, // 0x18 DW_FORM_exprloc
178   {1,0}, // 0x19 DW_FORM_flag_present
179   {0,0}, // 0x1a
180   {0,0}, // 0x1b
181   {0,0}, // 0x1c
182   {0,0}, // 0x1d
183   {0,0}, // 0x1e
184   {0,0}, // 0x1f
185   {1,8}, // 0x20 DW_FORM_ref_sig8
186 };
187 
188 llvm::Optional<uint8_t>
189 DWARFFormValue::GetFixedSize(dw_form_t form, const DWARFUnit *u) {
190   if (form <= DW_FORM_ref_sig8 && g_form_sizes[form].valid)
191     return g_form_sizes[form].size;
192   if (form == DW_FORM_addr && u)
193     return u->GetAddressByteSize();
194   return llvm::None;
195 }
196 
197 llvm::Optional<uint8_t> DWARFFormValue::GetFixedSize() const {
198   return GetFixedSize(m_form, m_unit);
199 }
200 
201 bool DWARFFormValue::SkipValue(const DWARFDataExtractor &debug_info_data,
202                                lldb::offset_t *offset_ptr) const {
203   return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, m_unit);
204 }
205 
206 bool DWARFFormValue::SkipValue(dw_form_t form,
207                                const DWARFDataExtractor &debug_info_data,
208                                lldb::offset_t *offset_ptr,
209                                const DWARFUnit *unit) {
210   uint8_t ref_addr_size;
211   switch (form) {
212   // Blocks if inlined data that have a length field and the data bytes inlined
213   // in the .debug_info
214   case DW_FORM_exprloc:
215   case DW_FORM_block: {
216     dw_uleb128_t size = debug_info_data.GetULEB128(offset_ptr);
217     *offset_ptr += size;
218   }
219     return true;
220   case DW_FORM_block1: {
221     dw_uleb128_t size = debug_info_data.GetU8(offset_ptr);
222     *offset_ptr += size;
223   }
224     return true;
225   case DW_FORM_block2: {
226     dw_uleb128_t size = debug_info_data.GetU16(offset_ptr);
227     *offset_ptr += size;
228   }
229     return true;
230   case DW_FORM_block4: {
231     dw_uleb128_t size = debug_info_data.GetU32(offset_ptr);
232     *offset_ptr += size;
233   }
234     return true;
235 
236   // Inlined NULL terminated C-strings
237   case DW_FORM_string:
238     debug_info_data.GetCStr(offset_ptr);
239     return true;
240 
241   // Compile unit address sized values
242   case DW_FORM_addr:
243     *offset_ptr += DWARFUnit::GetAddressByteSize(unit);
244     return true;
245 
246   case DW_FORM_ref_addr:
247     ref_addr_size = 4;
248     assert(unit); // Unit must be valid for DW_FORM_ref_addr objects or we will
249                   // get this wrong
250     if (unit->GetVersion() <= 2)
251       ref_addr_size = unit->GetAddressByteSize();
252     else
253       ref_addr_size = 4;
254     *offset_ptr += ref_addr_size;
255     return true;
256 
257   // 0 bytes values (implied from DW_FORM)
258   case DW_FORM_flag_present:
259   case DW_FORM_implicit_const:
260     return true;
261 
262     // 1 byte values
263     case DW_FORM_addrx1:
264     case DW_FORM_data1:
265     case DW_FORM_flag:
266     case DW_FORM_ref1:
267     case DW_FORM_strx1:
268       *offset_ptr += 1;
269       return true;
270 
271     // 2 byte values
272     case DW_FORM_addrx2:
273     case DW_FORM_data2:
274     case DW_FORM_ref2:
275     case DW_FORM_strx2:
276       *offset_ptr += 2;
277       return true;
278 
279     // 3 byte values
280     case DW_FORM_addrx3:
281     case DW_FORM_strx3:
282       *offset_ptr += 3;
283       return true;
284 
285     // 32 bit for DWARF 32, 64 for DWARF 64
286     case DW_FORM_sec_offset:
287     case DW_FORM_strp:
288       *offset_ptr += 4;
289       return true;
290 
291     // 4 byte values
292     case DW_FORM_addrx4:
293     case DW_FORM_data4:
294     case DW_FORM_ref4:
295     case DW_FORM_strx4:
296       *offset_ptr += 4;
297       return true;
298 
299     // 8 byte values
300     case DW_FORM_data8:
301     case DW_FORM_ref8:
302     case DW_FORM_ref_sig8:
303       *offset_ptr += 8;
304       return true;
305 
306     // signed or unsigned LEB 128 values
307     case DW_FORM_addrx:
308     case DW_FORM_rnglistx:
309     case DW_FORM_sdata:
310     case DW_FORM_udata:
311     case DW_FORM_ref_udata:
312     case DW_FORM_GNU_addr_index:
313     case DW_FORM_GNU_str_index:
314     case DW_FORM_strx:
315       debug_info_data.Skip_LEB128(offset_ptr);
316       return true;
317 
318   case DW_FORM_indirect: {
319     dw_form_t indirect_form = debug_info_data.GetULEB128(offset_ptr);
320     return DWARFFormValue::SkipValue(indirect_form, debug_info_data, offset_ptr,
321                                      unit);
322   }
323 
324   default:
325     break;
326   }
327   return false;
328 }
329 
330 void DWARFFormValue::Dump(Stream &s) const {
331   uint64_t uvalue = Unsigned();
332   bool unit_relative_offset = false;
333 
334   switch (m_form) {
335   case DW_FORM_addr:
336     s.Address(uvalue, sizeof(uint64_t));
337     break;
338   case DW_FORM_flag:
339   case DW_FORM_data1:
340     s.PutHex8(uvalue);
341     break;
342   case DW_FORM_data2:
343     s.PutHex16(uvalue);
344     break;
345   case DW_FORM_sec_offset:
346   case DW_FORM_data4:
347     s.PutHex32(uvalue);
348     break;
349   case DW_FORM_ref_sig8:
350   case DW_FORM_data8:
351     s.PutHex64(uvalue);
352     break;
353   case DW_FORM_string:
354     s.QuotedCString(AsCString());
355     break;
356   case DW_FORM_exprloc:
357   case DW_FORM_block:
358   case DW_FORM_block1:
359   case DW_FORM_block2:
360   case DW_FORM_block4:
361     if (uvalue > 0) {
362       switch (m_form) {
363       case DW_FORM_exprloc:
364       case DW_FORM_block:
365         s.Printf("<0x%" PRIx64 "> ", uvalue);
366         break;
367       case DW_FORM_block1:
368         s.Printf("<0x%2.2x> ", (uint8_t)uvalue);
369         break;
370       case DW_FORM_block2:
371         s.Printf("<0x%4.4x> ", (uint16_t)uvalue);
372         break;
373       case DW_FORM_block4:
374         s.Printf("<0x%8.8x> ", (uint32_t)uvalue);
375         break;
376       default:
377         break;
378       }
379 
380       const uint8_t *data_ptr = m_value.data;
381       if (data_ptr) {
382         const uint8_t *end_data_ptr =
383             data_ptr + uvalue; // uvalue contains size of block
384         while (data_ptr < end_data_ptr) {
385           s.Printf("%2.2x ", *data_ptr);
386           ++data_ptr;
387         }
388       } else
389         s.PutCString("NULL");
390     }
391     break;
392 
393   case DW_FORM_sdata:
394     s.PutSLEB128(uvalue);
395     break;
396   case DW_FORM_udata:
397     s.PutULEB128(uvalue);
398     break;
399   case DW_FORM_strp: {
400     const char *dbg_str = AsCString();
401     if (dbg_str) {
402       s.QuotedCString(dbg_str);
403     } else {
404       s.PutHex32(uvalue);
405     }
406   } break;
407 
408   case DW_FORM_ref_addr: {
409     assert(m_unit); // Unit must be valid for DW_FORM_ref_addr objects or we
410                     // will get this wrong
411     if (m_unit->GetVersion() <= 2)
412       s.Address(uvalue, sizeof(uint64_t) * 2);
413     else
414       s.Address(uvalue, 4 * 2); // 4 for DWARF32, 8 for DWARF64, but we don't
415                                 // support DWARF64 yet
416     break;
417   }
418   case DW_FORM_ref1:
419     unit_relative_offset = true;
420     break;
421   case DW_FORM_ref2:
422     unit_relative_offset = true;
423     break;
424   case DW_FORM_ref4:
425     unit_relative_offset = true;
426     break;
427   case DW_FORM_ref8:
428     unit_relative_offset = true;
429     break;
430   case DW_FORM_ref_udata:
431     unit_relative_offset = true;
432     break;
433 
434   // All DW_FORM_indirect attributes should be resolved prior to calling this
435   // function
436   case DW_FORM_indirect:
437     s.PutCString("DW_FORM_indirect");
438     break;
439   case DW_FORM_flag_present:
440     break;
441   default:
442     s.Printf("DW_FORM(0x%4.4x)", m_form);
443     break;
444   }
445 
446   if (unit_relative_offset) {
447     assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile
448                     // unit relative or we will get this wrong
449     s.Printf("{0x%8.8" PRIx64 "}", uvalue + m_unit->GetOffset());
450   }
451 }
452 
453 const char *DWARFFormValue::AsCString() const {
454   SymbolFileDWARF &symbol_file = m_unit->GetSymbolFileDWARF();
455 
456   if (m_form == DW_FORM_string) {
457     return m_value.value.cstr;
458   } else if (m_form == DW_FORM_strp) {
459     return symbol_file.GetDWARFContext().getOrLoadStrData().PeekCStr(
460         m_value.value.uval);
461   } else if (m_form == DW_FORM_GNU_str_index) {
462     uint32_t index_size = 4;
463     lldb::offset_t offset = m_value.value.uval * index_size;
464     dw_offset_t str_offset =
465         symbol_file.GetDWARFContext().getOrLoadStrOffsetsData().GetMaxU64(
466             &offset, index_size);
467     return symbol_file.GetDWARFContext().getOrLoadStrData().PeekCStr(
468         str_offset);
469   }
470 
471   if (m_form == DW_FORM_strx || m_form == DW_FORM_strx1 ||
472       m_form == DW_FORM_strx2 || m_form == DW_FORM_strx3 ||
473       m_form == DW_FORM_strx4) {
474 
475     // The same code as above.
476     uint32_t indexSize = 4;
477     lldb::offset_t offset =
478         m_unit->GetStrOffsetsBase() + m_value.value.uval * indexSize;
479     dw_offset_t strOffset =
480         symbol_file.GetDWARFContext().getOrLoadStrOffsetsData().GetMaxU64(
481             &offset, indexSize);
482     return symbol_file.GetDWARFContext().getOrLoadStrData().PeekCStr(strOffset);
483   }
484 
485   if (m_form == DW_FORM_line_strp)
486     return symbol_file.GetDWARFContext().getOrLoadLineStrData().PeekCStr(
487         m_value.value.uval);
488 
489   return nullptr;
490 }
491 
492 dw_addr_t DWARFFormValue::Address() const {
493   SymbolFileDWARF &symbol_file = m_unit->GetSymbolFileDWARF();
494 
495   if (m_form == DW_FORM_addr)
496     return Unsigned();
497 
498   assert(m_unit);
499   assert(m_form == DW_FORM_GNU_addr_index || m_form == DW_FORM_addrx ||
500          m_form == DW_FORM_addrx1 || m_form == DW_FORM_addrx2 ||
501          m_form == DW_FORM_addrx3 || m_form == DW_FORM_addrx4);
502 
503   uint32_t index_size = m_unit->GetAddressByteSize();
504   dw_offset_t addr_base = m_unit->GetAddrBase();
505   lldb::offset_t offset = addr_base + m_value.value.uval * index_size;
506   return symbol_file.GetDWARFContext().getOrLoadAddrData().GetMaxU64(
507       &offset, index_size);
508 }
509 
510 DWARFDIE DWARFFormValue::Reference() const {
511   uint64_t value = m_value.value.uval;
512   switch (m_form) {
513   case DW_FORM_ref1:
514   case DW_FORM_ref2:
515   case DW_FORM_ref4:
516   case DW_FORM_ref8:
517   case DW_FORM_ref_udata:
518     assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile
519                     // unit relative or we will get this wrong
520     value += m_unit->GetOffset();
521     if (!m_unit->ContainsDIEOffset(value)) {
522       m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
523           "DW_FORM_ref* DIE reference 0x%" PRIx64 " is outside of its CU",
524           value);
525       return {};
526     }
527     return const_cast<DWARFUnit *>(m_unit)->GetDIE(value);
528 
529   case DW_FORM_ref_addr: {
530     DWARFUnit *ref_cu =
531         m_unit->GetSymbolFileDWARF().DebugInfo()->GetUnitContainingDIEOffset(
532             DIERef::Section::DebugInfo, value);
533     if (!ref_cu) {
534       m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
535           "DW_FORM_ref_addr DIE reference 0x%" PRIx64 " has no matching CU",
536           value);
537       return {};
538     }
539     return ref_cu->GetDIE(value);
540   }
541 
542   case DW_FORM_ref_sig8: {
543     DWARFTypeUnit *tu =
544         m_unit->GetSymbolFileDWARF().DebugInfo()->GetTypeUnitForHash(value);
545     if (!tu)
546       return {};
547     return tu->GetDIE(tu->GetTypeOffset());
548   }
549 
550   default:
551     return {};
552   }
553 }
554 
555 uint64_t DWARFFormValue::Reference(dw_offset_t base_offset) const {
556   uint64_t value = m_value.value.uval;
557   switch (m_form) {
558   case DW_FORM_ref1:
559   case DW_FORM_ref2:
560   case DW_FORM_ref4:
561   case DW_FORM_ref8:
562   case DW_FORM_ref_udata:
563     return value + base_offset;
564 
565   case DW_FORM_ref_addr:
566   case DW_FORM_ref_sig8:
567   case DW_FORM_GNU_ref_alt:
568     return value;
569 
570   default:
571     return DW_INVALID_OFFSET;
572   }
573 }
574 
575 const uint8_t *DWARFFormValue::BlockData() const { return m_value.data; }
576 
577 bool DWARFFormValue::IsBlockForm(const dw_form_t form) {
578   switch (form) {
579   case DW_FORM_exprloc:
580   case DW_FORM_block:
581   case DW_FORM_block1:
582   case DW_FORM_block2:
583   case DW_FORM_block4:
584     return true;
585   }
586   return false;
587 }
588 
589 bool DWARFFormValue::IsDataForm(const dw_form_t form) {
590   switch (form) {
591   case DW_FORM_sdata:
592   case DW_FORM_udata:
593   case DW_FORM_data1:
594   case DW_FORM_data2:
595   case DW_FORM_data4:
596   case DW_FORM_data8:
597     return true;
598   }
599   return false;
600 }
601 
602 int DWARFFormValue::Compare(const DWARFFormValue &a_value,
603                             const DWARFFormValue &b_value) {
604   dw_form_t a_form = a_value.Form();
605   dw_form_t b_form = b_value.Form();
606   if (a_form < b_form)
607     return -1;
608   if (a_form > b_form)
609     return 1;
610   switch (a_form) {
611   case DW_FORM_addr:
612   case DW_FORM_addrx:
613   case DW_FORM_flag:
614   case DW_FORM_data1:
615   case DW_FORM_data2:
616   case DW_FORM_data4:
617   case DW_FORM_data8:
618   case DW_FORM_udata:
619   case DW_FORM_ref_addr:
620   case DW_FORM_sec_offset:
621   case DW_FORM_flag_present:
622   case DW_FORM_ref_sig8:
623   case DW_FORM_GNU_addr_index: {
624     uint64_t a = a_value.Unsigned();
625     uint64_t b = b_value.Unsigned();
626     if (a < b)
627       return -1;
628     if (a > b)
629       return 1;
630     return 0;
631   }
632 
633   case DW_FORM_sdata: {
634     int64_t a = a_value.Signed();
635     int64_t b = b_value.Signed();
636     if (a < b)
637       return -1;
638     if (a > b)
639       return 1;
640     return 0;
641   }
642 
643   case DW_FORM_string:
644   case DW_FORM_strp:
645   case DW_FORM_GNU_str_index: {
646     const char *a_string = a_value.AsCString();
647     const char *b_string = b_value.AsCString();
648     if (a_string == b_string)
649       return 0;
650     else if (a_string && b_string)
651       return strcmp(a_string, b_string);
652     else if (a_string == nullptr)
653       return -1; // A string is NULL, and B is valid
654     else
655       return 1; // A string valid, and B is NULL
656   }
657 
658   case DW_FORM_block:
659   case DW_FORM_block1:
660   case DW_FORM_block2:
661   case DW_FORM_block4:
662   case DW_FORM_exprloc: {
663     uint64_t a_len = a_value.Unsigned();
664     uint64_t b_len = b_value.Unsigned();
665     if (a_len < b_len)
666       return -1;
667     if (a_len > b_len)
668       return 1;
669     // The block lengths are the same
670     return memcmp(a_value.BlockData(), b_value.BlockData(), a_value.Unsigned());
671   } break;
672 
673   case DW_FORM_ref1:
674   case DW_FORM_ref2:
675   case DW_FORM_ref4:
676   case DW_FORM_ref8:
677   case DW_FORM_ref_udata: {
678     uint64_t a = a_value.m_value.value.uval;
679     uint64_t b = b_value.m_value.value.uval;
680     if (a < b)
681       return -1;
682     if (a > b)
683       return 1;
684     return 0;
685   }
686 
687   case DW_FORM_indirect:
688     llvm_unreachable(
689         "This shouldn't happen after the form has been extracted...");
690 
691   default:
692     llvm_unreachable("Unhandled DW_FORM");
693   }
694   return -1;
695 }
696 
697 bool DWARFFormValue::FormIsSupported(dw_form_t form) {
698   switch (form) {
699     case DW_FORM_addr:
700     case DW_FORM_addrx:
701     case DW_FORM_rnglistx:
702     case DW_FORM_block2:
703     case DW_FORM_block4:
704     case DW_FORM_data2:
705     case DW_FORM_data4:
706     case DW_FORM_data8:
707     case DW_FORM_string:
708     case DW_FORM_block:
709     case DW_FORM_block1:
710     case DW_FORM_data1:
711     case DW_FORM_flag:
712     case DW_FORM_sdata:
713     case DW_FORM_strp:
714     case DW_FORM_strx:
715     case DW_FORM_strx1:
716     case DW_FORM_strx2:
717     case DW_FORM_strx3:
718     case DW_FORM_strx4:
719     case DW_FORM_udata:
720     case DW_FORM_ref_addr:
721     case DW_FORM_ref1:
722     case DW_FORM_ref2:
723     case DW_FORM_ref4:
724     case DW_FORM_ref8:
725     case DW_FORM_ref_udata:
726     case DW_FORM_indirect:
727     case DW_FORM_sec_offset:
728     case DW_FORM_exprloc:
729     case DW_FORM_flag_present:
730     case DW_FORM_ref_sig8:
731     case DW_FORM_GNU_str_index:
732     case DW_FORM_GNU_addr_index:
733     case DW_FORM_implicit_const:
734       return true;
735     default:
736       break;
737   }
738   return false;
739 }
740