DWARFFormValue.cpp revision 344779
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
18class DWARFUnit;
19
20using namespace lldb_private;
21
22static 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
60static 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
99static 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
136DWARFFormValue::FixedFormSizes
137DWARFFormValue::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
155DWARFFormValue::DWARFFormValue() : m_cu(NULL), m_form(0), m_value() {}
156
157DWARFFormValue::DWARFFormValue(const DWARFUnit *cu)
158    : m_cu(cu), m_form(0), m_value() {}
159
160DWARFFormValue::DWARFFormValue(const DWARFUnit *cu, dw_form_t form)
161    : m_cu(cu), m_form(form), m_value() {}
162
163void DWARFFormValue::Clear() {
164  m_cu = nullptr;
165  m_form = 0;
166  memset(&m_value, 0, sizeof(m_value));
167}
168
169bool 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
289bool 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
294bool 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
419void 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
542const 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    uint32_t indexSize = m_cu->IsDWARF64() ? 8 : 4;
573    lldb::offset_t offset =
574        m_cu->GetStrOffsetsBase() + m_value.value.uval * indexSize;
575    dw_offset_t strOffset =
576        symbol_file->get_debug_str_offsets_data().GetMaxU64(&offset, indexSize);
577    return symbol_file->get_debug_str_data().PeekCStr(strOffset);
578  }
579
580  if (m_form == DW_FORM_line_strp)
581    return symbol_file->get_debug_line_str_data().PeekCStr(m_value.value.uval);
582
583  return nullptr;
584}
585
586dw_addr_t DWARFFormValue::Address() const {
587  SymbolFileDWARF *symbol_file = m_cu->GetSymbolFileDWARF();
588
589  if (m_form == DW_FORM_addr)
590    return Unsigned();
591
592  assert(m_cu);
593  assert(m_form == DW_FORM_GNU_addr_index || m_form == DW_FORM_addrx ||
594         m_form == DW_FORM_addrx1 || m_form == DW_FORM_addrx2 ||
595         m_form == DW_FORM_addrx3 || m_form == DW_FORM_addrx4);
596
597  if (!symbol_file)
598    return 0;
599
600  uint32_t index_size = m_cu->GetAddressByteSize();
601  dw_offset_t addr_base = m_cu->GetAddrBase();
602  lldb::offset_t offset = addr_base + m_value.value.uval * index_size;
603  return symbol_file->get_debug_addr_data().GetMaxU64(&offset, index_size);
604}
605
606uint64_t DWARFFormValue::Reference() const {
607  uint64_t value = m_value.value.uval;
608  switch (m_form) {
609  case DW_FORM_ref1:
610  case DW_FORM_ref2:
611  case DW_FORM_ref4:
612  case DW_FORM_ref8:
613  case DW_FORM_ref_udata:
614    assert(m_cu); // CU must be valid for DW_FORM_ref forms that are compile
615                  // unit relative or we will get this wrong
616    return value + m_cu->GetOffset();
617
618  case DW_FORM_ref_addr:
619  case DW_FORM_ref_sig8:
620  case DW_FORM_GNU_ref_alt:
621    return value;
622
623  default:
624    return DW_INVALID_OFFSET;
625  }
626}
627
628uint64_t DWARFFormValue::Reference(dw_offset_t base_offset) const {
629  uint64_t value = m_value.value.uval;
630  switch (m_form) {
631  case DW_FORM_ref1:
632  case DW_FORM_ref2:
633  case DW_FORM_ref4:
634  case DW_FORM_ref8:
635  case DW_FORM_ref_udata:
636    return value + base_offset;
637
638  case DW_FORM_ref_addr:
639  case DW_FORM_ref_sig8:
640  case DW_FORM_GNU_ref_alt:
641    return value;
642
643  default:
644    return DW_INVALID_OFFSET;
645  }
646}
647
648const uint8_t *DWARFFormValue::BlockData() const { return m_value.data; }
649
650bool DWARFFormValue::IsBlockForm(const dw_form_t form) {
651  switch (form) {
652  case DW_FORM_exprloc:
653  case DW_FORM_block:
654  case DW_FORM_block1:
655  case DW_FORM_block2:
656  case DW_FORM_block4:
657    return true;
658  }
659  return false;
660}
661
662bool DWARFFormValue::IsDataForm(const dw_form_t form) {
663  switch (form) {
664  case DW_FORM_sdata:
665  case DW_FORM_udata:
666  case DW_FORM_data1:
667  case DW_FORM_data2:
668  case DW_FORM_data4:
669  case DW_FORM_data8:
670    return true;
671  }
672  return false;
673}
674
675int DWARFFormValue::Compare(const DWARFFormValue &a_value,
676                            const DWARFFormValue &b_value) {
677  dw_form_t a_form = a_value.Form();
678  dw_form_t b_form = b_value.Form();
679  if (a_form < b_form)
680    return -1;
681  if (a_form > b_form)
682    return 1;
683  switch (a_form) {
684  case DW_FORM_addr:
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
769bool 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