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 =
186           data.GetMaxU64(offset_ptr, DWARFUnit::GetAddressByteSize(m_cu));
187       break;
188     case DW_FORM_block1:
189       m_value.value.uval = data.GetU8(offset_ptr);
190       is_block = true;
191       break;
192     case DW_FORM_block2:
193       m_value.value.uval = data.GetU16(offset_ptr);
194       is_block = true;
195       break;
196     case DW_FORM_block4:
197       m_value.value.uval = data.GetU32(offset_ptr);
198       is_block = true;
199       break;
200     case DW_FORM_data16:
201       m_value.value.uval = 16;
202       is_block = true;
203       break;
204     case DW_FORM_exprloc:
205     case DW_FORM_block:
206       m_value.value.uval = data.GetULEB128(offset_ptr);
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_sdata:
213       m_value.value.sval = data.GetSLEB128(offset_ptr);
214       break;
215     case DW_FORM_strp:
216     case DW_FORM_line_strp:
217     case DW_FORM_sec_offset:
218       assert(m_cu);
219       m_value.value.uval =
220           data.GetMaxU64(offset_ptr, DWARFUnit::IsDWARF64(m_cu) ? 8 : 4);
221       break;
222     case DW_FORM_addrx1:
223     case DW_FORM_strx1:
224     case DW_FORM_ref1:
225     case DW_FORM_data1:
226     case DW_FORM_flag:
227       m_value.value.uval = data.GetU8(offset_ptr);
228       break;
229     case DW_FORM_addrx2:
230     case DW_FORM_strx2:
231     case DW_FORM_ref2:
232     case DW_FORM_data2:
233       m_value.value.uval = data.GetU16(offset_ptr);
234       break;
235     case DW_FORM_addrx3:
236     case DW_FORM_strx3:
237       m_value.value.uval = data.GetMaxU64(offset_ptr, 3);
238       break;
239     case DW_FORM_addrx4:
240     case DW_FORM_strx4:
241     case DW_FORM_ref4:
242     case DW_FORM_data4:
243       m_value.value.uval = data.GetU32(offset_ptr);
244       break;
245     case DW_FORM_data8:
246     case DW_FORM_ref8:
247     case DW_FORM_ref_sig8:
248       m_value.value.uval = data.GetU64(offset_ptr);
249       break;
250     case DW_FORM_addrx:
251     case DW_FORM_rnglistx:
252     case DW_FORM_strx:
253     case DW_FORM_udata:
254     case DW_FORM_ref_udata:
255     case DW_FORM_GNU_str_index:
256     case DW_FORM_GNU_addr_index:
257       m_value.value.uval = data.GetULEB128(offset_ptr);
258       break;
259     case DW_FORM_ref_addr:
260       assert(m_cu);
261       if (m_cu->GetVersion() <= 2)
262         ref_addr_size = m_cu->GetAddressByteSize();
263       else
264         ref_addr_size = m_cu->IsDWARF64() ? 8 : 4;
265       m_value.value.uval = data.GetMaxU64(offset_ptr, ref_addr_size);
266       break;
267     case DW_FORM_indirect:
268       m_form = data.GetULEB128(offset_ptr);
269       indirect = true;
270       break;
271     case DW_FORM_flag_present:
272       m_value.value.uval = 1;
273       break;
274     default:
275       return false;
276     }
277   } while (indirect);
278 
279   if (is_block) {
280     m_value.data = data.PeekData(*offset_ptr, m_value.value.uval);
281     if (m_value.data != NULL) {
282       *offset_ptr += m_value.value.uval;
283     }
284   }
285 
286   return true;
287 }
288 
289 bool DWARFFormValue::SkipValue(const DWARFDataExtractor &debug_info_data,
290                                lldb::offset_t *offset_ptr) const {
291   return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, m_cu);
292 }
293 
294 bool DWARFFormValue::SkipValue(dw_form_t form,
295                                const DWARFDataExtractor &debug_info_data,
296                                lldb::offset_t *offset_ptr,
297                                const DWARFUnit *cu) {
298   uint8_t ref_addr_size;
299   switch (form) {
300   // Blocks if inlined data that have a length field and the data bytes inlined
301   // in the .debug_info
302   case DW_FORM_exprloc:
303   case DW_FORM_block: {
304     dw_uleb128_t size = debug_info_data.GetULEB128(offset_ptr);
305     *offset_ptr += size;
306   }
307     return true;
308   case DW_FORM_block1: {
309     dw_uleb128_t size = debug_info_data.GetU8(offset_ptr);
310     *offset_ptr += size;
311   }
312     return true;
313   case DW_FORM_block2: {
314     dw_uleb128_t size = debug_info_data.GetU16(offset_ptr);
315     *offset_ptr += size;
316   }
317     return true;
318   case DW_FORM_block4: {
319     dw_uleb128_t size = debug_info_data.GetU32(offset_ptr);
320     *offset_ptr += size;
321   }
322     return true;
323 
324   // Inlined NULL terminated C-strings
325   case DW_FORM_string:
326     debug_info_data.GetCStr(offset_ptr);
327     return true;
328 
329   // Compile unit address sized values
330   case DW_FORM_addr:
331     *offset_ptr += DWARFUnit::GetAddressByteSize(cu);
332     return true;
333 
334   case DW_FORM_ref_addr:
335     ref_addr_size = 4;
336     assert(cu); // CU must be valid for DW_FORM_ref_addr objects or we will get
337                 // this wrong
338     if (cu->GetVersion() <= 2)
339       ref_addr_size = cu->GetAddressByteSize();
340     else
341       ref_addr_size = cu->IsDWARF64() ? 8 : 4;
342     *offset_ptr += ref_addr_size;
343     return true;
344 
345   // 0 bytes values (implied from DW_FORM)
346   case DW_FORM_flag_present:
347   case DW_FORM_implicit_const:
348     return true;
349 
350     // 1 byte values
351     case DW_FORM_addrx1:
352     case DW_FORM_data1:
353     case DW_FORM_flag:
354     case DW_FORM_ref1:
355     case DW_FORM_strx1:
356       *offset_ptr += 1;
357       return true;
358 
359     // 2 byte values
360     case DW_FORM_addrx2:
361     case DW_FORM_data2:
362     case DW_FORM_ref2:
363     case DW_FORM_strx2:
364       *offset_ptr += 2;
365       return true;
366 
367     // 3 byte values
368     case DW_FORM_addrx3:
369     case DW_FORM_strx3:
370       *offset_ptr += 3;
371       return true;
372 
373     // 32 bit for DWARF 32, 64 for DWARF 64
374     case DW_FORM_sec_offset:
375     case DW_FORM_strp:
376       assert(cu);
377       *offset_ptr += (cu->IsDWARF64() ? 8 : 4);
378       return true;
379 
380     // 4 byte values
381     case DW_FORM_addrx4:
382     case DW_FORM_data4:
383     case DW_FORM_ref4:
384     case DW_FORM_strx4:
385       *offset_ptr += 4;
386       return true;
387 
388     // 8 byte values
389     case DW_FORM_data8:
390     case DW_FORM_ref8:
391     case DW_FORM_ref_sig8:
392       *offset_ptr += 8;
393       return true;
394 
395     // signed or unsigned LEB 128 values
396     case DW_FORM_addrx:
397     case DW_FORM_rnglistx:
398     case DW_FORM_sdata:
399     case DW_FORM_udata:
400     case DW_FORM_ref_udata:
401     case DW_FORM_GNU_addr_index:
402     case DW_FORM_GNU_str_index:
403     case DW_FORM_strx:
404       debug_info_data.Skip_LEB128(offset_ptr);
405       return true;
406 
407   case DW_FORM_indirect: {
408     dw_form_t indirect_form = debug_info_data.GetULEB128(offset_ptr);
409     return DWARFFormValue::SkipValue(indirect_form, debug_info_data, offset_ptr,
410                                      cu);
411   }
412 
413   default:
414     break;
415   }
416   return false;
417 }
418 
419 void DWARFFormValue::Dump(Stream &s) const {
420   uint64_t uvalue = Unsigned();
421   bool cu_relative_offset = false;
422 
423   switch (m_form) {
424   case DW_FORM_addr:
425     s.Address(uvalue, sizeof(uint64_t));
426     break;
427   case DW_FORM_flag:
428   case DW_FORM_data1:
429     s.PutHex8(uvalue);
430     break;
431   case DW_FORM_data2:
432     s.PutHex16(uvalue);
433     break;
434   case DW_FORM_sec_offset:
435   case DW_FORM_data4:
436     s.PutHex32(uvalue);
437     break;
438   case DW_FORM_ref_sig8:
439   case DW_FORM_data8:
440     s.PutHex64(uvalue);
441     break;
442   case DW_FORM_string:
443     s.QuotedCString(AsCString());
444     break;
445   case DW_FORM_exprloc:
446   case DW_FORM_block:
447   case DW_FORM_block1:
448   case DW_FORM_block2:
449   case DW_FORM_block4:
450     if (uvalue > 0) {
451       switch (m_form) {
452       case DW_FORM_exprloc:
453       case DW_FORM_block:
454         s.Printf("<0x%" PRIx64 "> ", uvalue);
455         break;
456       case DW_FORM_block1:
457         s.Printf("<0x%2.2x> ", (uint8_t)uvalue);
458         break;
459       case DW_FORM_block2:
460         s.Printf("<0x%4.4x> ", (uint16_t)uvalue);
461         break;
462       case DW_FORM_block4:
463         s.Printf("<0x%8.8x> ", (uint32_t)uvalue);
464         break;
465       default:
466         break;
467       }
468 
469       const uint8_t *data_ptr = m_value.data;
470       if (data_ptr) {
471         const uint8_t *end_data_ptr =
472             data_ptr + uvalue; // uvalue contains size of block
473         while (data_ptr < end_data_ptr) {
474           s.Printf("%2.2x ", *data_ptr);
475           ++data_ptr;
476         }
477       } else
478         s.PutCString("NULL");
479     }
480     break;
481 
482   case DW_FORM_sdata:
483     s.PutSLEB128(uvalue);
484     break;
485   case DW_FORM_udata:
486     s.PutULEB128(uvalue);
487     break;
488   case DW_FORM_strp: {
489     const char *dbg_str = AsCString();
490     if (dbg_str) {
491       s.QuotedCString(dbg_str);
492     } else {
493       s.PutHex32(uvalue);
494     }
495   } break;
496 
497   case DW_FORM_ref_addr: {
498     assert(m_cu); // CU must be valid for DW_FORM_ref_addr objects or we will
499                   // get this wrong
500     if (m_cu->GetVersion() <= 2)
501       s.Address(uvalue, sizeof(uint64_t) * 2);
502     else
503       s.Address(uvalue, 4 * 2); // 4 for DWARF32, 8 for DWARF64, but we don't
504                                 // support DWARF64 yet
505     break;
506   }
507   case DW_FORM_ref1:
508     cu_relative_offset = true;
509     break;
510   case DW_FORM_ref2:
511     cu_relative_offset = true;
512     break;
513   case DW_FORM_ref4:
514     cu_relative_offset = true;
515     break;
516   case DW_FORM_ref8:
517     cu_relative_offset = true;
518     break;
519   case DW_FORM_ref_udata:
520     cu_relative_offset = true;
521     break;
522 
523   // All DW_FORM_indirect attributes should be resolved prior to calling this
524   // function
525   case DW_FORM_indirect:
526     s.PutCString("DW_FORM_indirect");
527     break;
528   case DW_FORM_flag_present:
529     break;
530   default:
531     s.Printf("DW_FORM(0x%4.4x)", m_form);
532     break;
533   }
534 
535   if (cu_relative_offset) {
536     assert(m_cu); // CU must be valid for DW_FORM_ref forms that are compile
537                   // unit relative or we will get this wrong
538     s.Printf("{0x%8.8" PRIx64 "}", uvalue + m_cu->GetOffset());
539   }
540 }
541 
542 const char *DWARFFormValue::AsCString() const {
543   SymbolFileDWARF *symbol_file = m_cu->GetSymbolFileDWARF();
544 
545   if (m_form == DW_FORM_string) {
546     return m_value.value.cstr;
547   } else if (m_form == DW_FORM_strp) {
548     if (!symbol_file)
549       return nullptr;
550 
551     return symbol_file->get_debug_str_data().PeekCStr(m_value.value.uval);
552   } else if (m_form == DW_FORM_GNU_str_index) {
553     if (!symbol_file)
554       return nullptr;
555 
556     uint32_t index_size = m_cu->IsDWARF64() ? 8 : 4;
557     lldb::offset_t offset = m_value.value.uval * index_size;
558     dw_offset_t str_offset =
559         symbol_file->get_debug_str_offsets_data().GetMaxU64(&offset,
560                                                             index_size);
561     return symbol_file->get_debug_str_data().PeekCStr(str_offset);
562   }
563 
564   if (m_form == DW_FORM_strx || m_form == DW_FORM_strx1 ||
565       m_form == DW_FORM_strx2 || m_form == DW_FORM_strx3 ||
566       m_form == DW_FORM_strx4) {
567 
568     // The same code as above.
569     if (!symbol_file)
570       return nullptr;
571 
572     lldb::offset_t baseOffset = 0;
573     const DWARFDataExtractor &strOffsets =
574         symbol_file->get_debug_str_offsets_data();
575     uint64_t length = strOffsets.GetU32(&baseOffset);
576     if (length == 0xffffffff)
577       length = strOffsets.GetU64(&baseOffset);
578 
579     // Check version.
580     if (strOffsets.GetU16(&baseOffset) < 5)
581       return nullptr;
582 
583     // Skip padding.
584     baseOffset += 2;
585 
586     uint32_t indexSize = m_cu->IsDWARF64() ? 8 : 4;
587     lldb::offset_t offset = baseOffset + m_value.value.uval * indexSize;
588     dw_offset_t strOffset =
589         symbol_file->get_debug_str_offsets_data().GetMaxU64(&offset, indexSize);
590     return symbol_file->get_debug_str_data().PeekCStr(strOffset);
591   }
592 
593   if (m_form == DW_FORM_line_strp)
594     return symbol_file->get_debug_line_str_data().PeekCStr(m_value.value.uval);
595 
596   return nullptr;
597 }
598 
599 dw_addr_t DWARFFormValue::Address() const {
600   SymbolFileDWARF *symbol_file = m_cu->GetSymbolFileDWARF();
601 
602   if (m_form == DW_FORM_addr)
603     return Unsigned();
604 
605   assert(m_cu);
606   assert(m_form == DW_FORM_GNU_addr_index || m_form == DW_FORM_addrx ||
607          m_form == DW_FORM_addrx1 || m_form == DW_FORM_addrx2 ||
608          m_form == DW_FORM_addrx3 || m_form == DW_FORM_addrx4);
609 
610   if (!symbol_file)
611     return 0;
612 
613   uint32_t index_size = m_cu->GetAddressByteSize();
614   dw_offset_t addr_base = m_cu->GetAddrBase();
615   lldb::offset_t offset = addr_base + m_value.value.uval * index_size;
616   return symbol_file->get_debug_addr_data().GetMaxU64(&offset, index_size);
617 }
618 
619 uint64_t DWARFFormValue::Reference() const {
620   uint64_t die_offset = m_value.value.uval;
621   switch (m_form) {
622   case DW_FORM_ref1:
623   case DW_FORM_ref2:
624   case DW_FORM_ref4:
625   case DW_FORM_ref8:
626   case DW_FORM_ref_udata:
627     assert(m_cu); // CU must be valid for DW_FORM_ref forms that are compile
628                   // unit relative or we will get this wrong
629     die_offset += m_cu->GetOffset();
630     break;
631 
632   default:
633     break;
634   }
635 
636   return die_offset;
637 }
638 
639 uint64_t DWARFFormValue::Reference(dw_offset_t base_offset) 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     die_offset += base_offset;
648     break;
649 
650   default:
651     break;
652   }
653 
654   return die_offset;
655 }
656 
657 const uint8_t *DWARFFormValue::BlockData() const { return m_value.data; }
658 
659 bool DWARFFormValue::IsBlockForm(const dw_form_t form) {
660   switch (form) {
661   case DW_FORM_exprloc:
662   case DW_FORM_block:
663   case DW_FORM_block1:
664   case DW_FORM_block2:
665   case DW_FORM_block4:
666     return true;
667   }
668   return false;
669 }
670 
671 bool DWARFFormValue::IsDataForm(const dw_form_t form) {
672   switch (form) {
673   case DW_FORM_sdata:
674   case DW_FORM_udata:
675   case DW_FORM_data1:
676   case DW_FORM_data2:
677   case DW_FORM_data4:
678   case DW_FORM_data8:
679     return true;
680   }
681   return false;
682 }
683 
684 int DWARFFormValue::Compare(const DWARFFormValue &a_value,
685                             const DWARFFormValue &b_value) {
686   dw_form_t a_form = a_value.Form();
687   dw_form_t b_form = b_value.Form();
688   if (a_form < b_form)
689     return -1;
690   if (a_form > b_form)
691     return 1;
692   switch (a_form) {
693   case DW_FORM_addr:
694   case DW_FORM_flag:
695   case DW_FORM_data1:
696   case DW_FORM_data2:
697   case DW_FORM_data4:
698   case DW_FORM_data8:
699   case DW_FORM_udata:
700   case DW_FORM_ref_addr:
701   case DW_FORM_sec_offset:
702   case DW_FORM_flag_present:
703   case DW_FORM_ref_sig8:
704   case DW_FORM_GNU_addr_index: {
705     uint64_t a = a_value.Unsigned();
706     uint64_t b = b_value.Unsigned();
707     if (a < b)
708       return -1;
709     if (a > b)
710       return 1;
711     return 0;
712   }
713 
714   case DW_FORM_sdata: {
715     int64_t a = a_value.Signed();
716     int64_t b = b_value.Signed();
717     if (a < b)
718       return -1;
719     if (a > b)
720       return 1;
721     return 0;
722   }
723 
724   case DW_FORM_string:
725   case DW_FORM_strp:
726   case DW_FORM_GNU_str_index: {
727     const char *a_string = a_value.AsCString();
728     const char *b_string = b_value.AsCString();
729     if (a_string == b_string)
730       return 0;
731     else if (a_string && b_string)
732       return strcmp(a_string, b_string);
733     else if (a_string == NULL)
734       return -1; // A string is NULL, and B is valid
735     else
736       return 1; // A string valid, and B is NULL
737   }
738 
739   case DW_FORM_block:
740   case DW_FORM_block1:
741   case DW_FORM_block2:
742   case DW_FORM_block4:
743   case DW_FORM_exprloc: {
744     uint64_t a_len = a_value.Unsigned();
745     uint64_t b_len = b_value.Unsigned();
746     if (a_len < b_len)
747       return -1;
748     if (a_len > b_len)
749       return 1;
750     // The block lengths are the same
751     return memcmp(a_value.BlockData(), b_value.BlockData(), a_value.Unsigned());
752   } break;
753 
754   case DW_FORM_ref1:
755   case DW_FORM_ref2:
756   case DW_FORM_ref4:
757   case DW_FORM_ref8:
758   case DW_FORM_ref_udata: {
759     uint64_t a = a_value.Reference();
760     uint64_t b = b_value.Reference();
761     if (a < b)
762       return -1;
763     if (a > b)
764       return 1;
765     return 0;
766   }
767 
768   case DW_FORM_indirect:
769     llvm_unreachable(
770         "This shouldn't happen after the form has been extracted...");
771 
772   default:
773     llvm_unreachable("Unhandled DW_FORM");
774   }
775   return -1;
776 }
777 
778 bool DWARFFormValue::FormIsSupported(dw_form_t form) {
779   switch (form) {
780     case DW_FORM_addr:
781     case DW_FORM_addrx:
782     case DW_FORM_rnglistx:
783     case DW_FORM_block2:
784     case DW_FORM_block4:
785     case DW_FORM_data2:
786     case DW_FORM_data4:
787     case DW_FORM_data8:
788     case DW_FORM_string:
789     case DW_FORM_block:
790     case DW_FORM_block1:
791     case DW_FORM_data1:
792     case DW_FORM_flag:
793     case DW_FORM_sdata:
794     case DW_FORM_strp:
795     case DW_FORM_strx:
796     case DW_FORM_strx1:
797     case DW_FORM_strx2:
798     case DW_FORM_strx3:
799     case DW_FORM_strx4:
800     case DW_FORM_udata:
801     case DW_FORM_ref_addr:
802     case DW_FORM_ref1:
803     case DW_FORM_ref2:
804     case DW_FORM_ref4:
805     case DW_FORM_ref8:
806     case DW_FORM_ref_udata:
807     case DW_FORM_indirect:
808     case DW_FORM_sec_offset:
809     case DW_FORM_exprloc:
810     case DW_FORM_flag_present:
811     case DW_FORM_ref_sig8:
812     case DW_FORM_GNU_str_index:
813     case DW_FORM_GNU_addr_index:
814     case DW_FORM_implicit_const:
815       return true;
816     default:
817       break;
818   }
819   return false;
820 }
821