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