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