DWARFFormValue.cpp revision 353358
1135549Sdes//===-- DWARFFormValue.cpp --------------------------------------*- C++ -*-===//
2135549Sdes//
3135549Sdes// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4166335Sdougb// See https://llvm.org/LICENSE.txt for license information.
5135549Sdes// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6135549Sdes//
7135549Sdes//===----------------------------------------------------------------------===//
8135549Sdes
9135549Sdes#include <assert.h>
10135549Sdes
11135549Sdes#include "lldb/Core/Module.h"
12135549Sdes#include "lldb/Core/dwarf.h"
13135549Sdes#include "lldb/Symbol/ObjectFile.h"
14135549Sdes#include "lldb/Utility/Stream.h"
15135549Sdes
16135549Sdes#include "DWARFDebugInfo.h"
17135549Sdes#include "DWARFFormValue.h"
18135549Sdes#include "DWARFUnit.h"
19135549Sdes
20135549Sdesclass DWARFUnit;
21135549Sdes
22135549Sdesusing namespace lldb_private;
23135549Sdes
24135549Sdesvoid DWARFFormValue::Clear() {
25135549Sdes  m_unit = nullptr;
26135549Sdes  m_form = 0;
27170224Sdougb  m_value = ValueTypeTag();
28170224Sdougb}
29135549Sdes
30135549Sdesbool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,
31135549Sdes                                  lldb::offset_t *offset_ptr) {
32135549Sdes  if (m_form == DW_FORM_implicit_const)
33135549Sdes    return true;
34135549Sdes
35135549Sdes  bool indirect = false;
36135549Sdes  bool is_block = false;
37135549Sdes  m_value.data = nullptr;
38135549Sdes  uint8_t ref_addr_size;
39135549Sdes  // Read the value for the form into value and follow and DW_FORM_indirect
40135549Sdes  // instances we run into
41135549Sdes  do {
42135549Sdes    indirect = false;
43135549Sdes    switch (m_form) {
44135549Sdes    case DW_FORM_addr:
45135549Sdes      assert(m_unit);
46135549Sdes      m_value.value.uval =
47135549Sdes          data.GetMaxU64(offset_ptr, DWARFUnit::GetAddressByteSize(m_unit));
48135549Sdes      break;
49135549Sdes    case DW_FORM_block1:
50135549Sdes      m_value.value.uval = data.GetU8(offset_ptr);
51135549Sdes      is_block = true;
52135549Sdes      break;
53135549Sdes    case DW_FORM_block2:
54135549Sdes      m_value.value.uval = data.GetU16(offset_ptr);
55135549Sdes      is_block = true;
56135549Sdes      break;
57135549Sdes    case DW_FORM_block4:
58135549Sdes      m_value.value.uval = data.GetU32(offset_ptr);
59135549Sdes      is_block = true;
60135549Sdes      break;
61135549Sdes    case DW_FORM_data16:
62135549Sdes      m_value.value.uval = 16;
63135549Sdes      is_block = true;
64135549Sdes      break;
65135549Sdes    case DW_FORM_exprloc:
66135549Sdes    case DW_FORM_block:
67135549Sdes      m_value.value.uval = data.GetULEB128(offset_ptr);
68135549Sdes      is_block = true;
69135549Sdes      break;
70135549Sdes    case DW_FORM_string:
71135549Sdes      m_value.value.cstr = data.GetCStr(offset_ptr);
72135549Sdes      break;
73135549Sdes    case DW_FORM_sdata:
74170224Sdougb      m_value.value.sval = data.GetSLEB128(offset_ptr);
75135549Sdes      break;
76135549Sdes    case DW_FORM_strp:
77135549Sdes    case DW_FORM_line_strp:
78170224Sdougb    case DW_FORM_sec_offset:
79135549Sdes      m_value.value.uval = data.GetMaxU64(offset_ptr, 4);
80135549Sdes      break;
81135549Sdes    case DW_FORM_addrx1:
82165077Sdougb    case DW_FORM_strx1:
83135549Sdes    case DW_FORM_ref1:
84135549Sdes    case DW_FORM_data1:
85135549Sdes    case DW_FORM_flag:
86135549Sdes      m_value.value.uval = data.GetU8(offset_ptr);
87135549Sdes      break;
88135549Sdes    case DW_FORM_addrx2:
89135549Sdes    case DW_FORM_strx2:
90135549Sdes    case DW_FORM_ref2:
91135549Sdes    case DW_FORM_data2:
92135549Sdes      m_value.value.uval = data.GetU16(offset_ptr);
93135549Sdes      break;
94135549Sdes    case DW_FORM_addrx3:
95135549Sdes    case DW_FORM_strx3:
96135549Sdes      m_value.value.uval = data.GetMaxU64(offset_ptr, 3);
97135549Sdes      break;
98135549Sdes    case DW_FORM_addrx4:
99135549Sdes    case DW_FORM_strx4:
100135549Sdes    case DW_FORM_ref4:
101135549Sdes    case DW_FORM_data4:
102135549Sdes      m_value.value.uval = data.GetU32(offset_ptr);
103135549Sdes      break;
104135549Sdes    case DW_FORM_data8:
105135549Sdes    case DW_FORM_ref8:
106135549Sdes    case DW_FORM_ref_sig8:
107135549Sdes      m_value.value.uval = data.GetU64(offset_ptr);
108135549Sdes      break;
109135549Sdes    case DW_FORM_addrx:
110135549Sdes    case DW_FORM_rnglistx:
111135549Sdes    case DW_FORM_strx:
112135549Sdes    case DW_FORM_udata:
113135549Sdes    case DW_FORM_ref_udata:
114135549Sdes    case DW_FORM_GNU_str_index:
115135549Sdes    case DW_FORM_GNU_addr_index:
116135549Sdes      m_value.value.uval = data.GetULEB128(offset_ptr);
117135549Sdes      break;
118135549Sdes    case DW_FORM_ref_addr:
119135549Sdes      assert(m_unit);
120135549Sdes      if (m_unit->GetVersion() <= 2)
121135549Sdes        ref_addr_size = m_unit->GetAddressByteSize();
122135549Sdes      else
123135549Sdes        ref_addr_size = 4;
124135549Sdes      m_value.value.uval = data.GetMaxU64(offset_ptr, ref_addr_size);
125135549Sdes      break;
126135549Sdes    case DW_FORM_indirect:
127135549Sdes      m_form = data.GetULEB128(offset_ptr);
128135549Sdes      indirect = true;
129135549Sdes      break;
130135549Sdes    case DW_FORM_flag_present:
131170224Sdougb      m_value.value.uval = 1;
132135549Sdes      break;
133135549Sdes    default:
134135549Sdes      return false;
135170224Sdougb    }
136135549Sdes  } while (indirect);
137135549Sdes
138135549Sdes  if (is_block) {
139135549Sdes    m_value.data = data.PeekData(*offset_ptr, m_value.value.uval);
140135549Sdes    if (m_value.data != nullptr) {
141135549Sdes      *offset_ptr += m_value.value.uval;
142135549Sdes    }
143135549Sdes  }
144135549Sdes
145135549Sdes  return true;
146135549Sdes}
147
148struct FormSize {
149  uint8_t valid:1, size:7;
150};
151static FormSize g_form_sizes[] = {
152  {0,0}, // 0x00 unused
153  {0,0}, // 0x01 DW_FORM_addr
154  {0,0}, // 0x02 unused
155  {0,0}, // 0x03 DW_FORM_block2
156  {0,0}, // 0x04 DW_FORM_block4
157  {1,2}, // 0x05 DW_FORM_data2
158  {1,4}, // 0x06 DW_FORM_data4
159  {1,8}, // 0x07 DW_FORM_data8
160  {0,0}, // 0x08 DW_FORM_string
161  {0,0}, // 0x09 DW_FORM_block
162  {0,0}, // 0x0a DW_FORM_block1
163  {1,1}, // 0x0b DW_FORM_data1
164  {1,1}, // 0x0c DW_FORM_flag
165  {0,0}, // 0x0d DW_FORM_sdata
166  {1,4}, // 0x0e DW_FORM_strp
167  {0,0}, // 0x0f DW_FORM_udata
168  {0,0}, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes for
169         // DWARF32, 8 bytes for DWARF32 in DWARF 3 and later
170  {1,1}, // 0x11 DW_FORM_ref1
171  {1,2}, // 0x12 DW_FORM_ref2
172  {1,4}, // 0x13 DW_FORM_ref4
173  {1,8}, // 0x14 DW_FORM_ref8
174  {0,0}, // 0x15 DW_FORM_ref_udata
175  {0,0}, // 0x16 DW_FORM_indirect
176  {1,4}, // 0x17 DW_FORM_sec_offset
177  {0,0}, // 0x18 DW_FORM_exprloc
178  {1,0}, // 0x19 DW_FORM_flag_present
179  {0,0}, // 0x1a
180  {0,0}, // 0x1b
181  {0,0}, // 0x1c
182  {0,0}, // 0x1d
183  {0,0}, // 0x1e
184  {0,0}, // 0x1f
185  {1,8}, // 0x20 DW_FORM_ref_sig8
186};
187
188llvm::Optional<uint8_t>
189DWARFFormValue::GetFixedSize(dw_form_t form, const DWARFUnit *u) {
190  if (form <= DW_FORM_ref_sig8 && g_form_sizes[form].valid)
191    return g_form_sizes[form].size;
192  if (form == DW_FORM_addr && u)
193    return u->GetAddressByteSize();
194  return llvm::None;
195}
196
197llvm::Optional<uint8_t> DWARFFormValue::GetFixedSize() const {
198  return GetFixedSize(m_form, m_unit);
199}
200
201bool DWARFFormValue::SkipValue(const DWARFDataExtractor &debug_info_data,
202                               lldb::offset_t *offset_ptr) const {
203  return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, m_unit);
204}
205
206bool DWARFFormValue::SkipValue(dw_form_t form,
207                               const DWARFDataExtractor &debug_info_data,
208                               lldb::offset_t *offset_ptr,
209                               const DWARFUnit *unit) {
210  uint8_t ref_addr_size;
211  switch (form) {
212  // Blocks if inlined data that have a length field and the data bytes inlined
213  // in the .debug_info
214  case DW_FORM_exprloc:
215  case DW_FORM_block: {
216    dw_uleb128_t size = debug_info_data.GetULEB128(offset_ptr);
217    *offset_ptr += size;
218  }
219    return true;
220  case DW_FORM_block1: {
221    dw_uleb128_t size = debug_info_data.GetU8(offset_ptr);
222    *offset_ptr += size;
223  }
224    return true;
225  case DW_FORM_block2: {
226    dw_uleb128_t size = debug_info_data.GetU16(offset_ptr);
227    *offset_ptr += size;
228  }
229    return true;
230  case DW_FORM_block4: {
231    dw_uleb128_t size = debug_info_data.GetU32(offset_ptr);
232    *offset_ptr += size;
233  }
234    return true;
235
236  // Inlined NULL terminated C-strings
237  case DW_FORM_string:
238    debug_info_data.GetCStr(offset_ptr);
239    return true;
240
241  // Compile unit address sized values
242  case DW_FORM_addr:
243    *offset_ptr += DWARFUnit::GetAddressByteSize(unit);
244    return true;
245
246  case DW_FORM_ref_addr:
247    ref_addr_size = 4;
248    assert(unit); // Unit must be valid for DW_FORM_ref_addr objects or we will
249                  // get this wrong
250    if (unit->GetVersion() <= 2)
251      ref_addr_size = unit->GetAddressByteSize();
252    else
253      ref_addr_size = 4;
254    *offset_ptr += ref_addr_size;
255    return true;
256
257  // 0 bytes values (implied from DW_FORM)
258  case DW_FORM_flag_present:
259  case DW_FORM_implicit_const:
260    return true;
261
262    // 1 byte values
263    case DW_FORM_addrx1:
264    case DW_FORM_data1:
265    case DW_FORM_flag:
266    case DW_FORM_ref1:
267    case DW_FORM_strx1:
268      *offset_ptr += 1;
269      return true;
270
271    // 2 byte values
272    case DW_FORM_addrx2:
273    case DW_FORM_data2:
274    case DW_FORM_ref2:
275    case DW_FORM_strx2:
276      *offset_ptr += 2;
277      return true;
278
279    // 3 byte values
280    case DW_FORM_addrx3:
281    case DW_FORM_strx3:
282      *offset_ptr += 3;
283      return true;
284
285    // 32 bit for DWARF 32, 64 for DWARF 64
286    case DW_FORM_sec_offset:
287    case DW_FORM_strp:
288      *offset_ptr += 4;
289      return true;
290
291    // 4 byte values
292    case DW_FORM_addrx4:
293    case DW_FORM_data4:
294    case DW_FORM_ref4:
295    case DW_FORM_strx4:
296      *offset_ptr += 4;
297      return true;
298
299    // 8 byte values
300    case DW_FORM_data8:
301    case DW_FORM_ref8:
302    case DW_FORM_ref_sig8:
303      *offset_ptr += 8;
304      return true;
305
306    // signed or unsigned LEB 128 values
307    case DW_FORM_addrx:
308    case DW_FORM_rnglistx:
309    case DW_FORM_sdata:
310    case DW_FORM_udata:
311    case DW_FORM_ref_udata:
312    case DW_FORM_GNU_addr_index:
313    case DW_FORM_GNU_str_index:
314    case DW_FORM_strx:
315      debug_info_data.Skip_LEB128(offset_ptr);
316      return true;
317
318  case DW_FORM_indirect: {
319    dw_form_t indirect_form = debug_info_data.GetULEB128(offset_ptr);
320    return DWARFFormValue::SkipValue(indirect_form, debug_info_data, offset_ptr,
321                                     unit);
322  }
323
324  default:
325    break;
326  }
327  return false;
328}
329
330void DWARFFormValue::Dump(Stream &s) const {
331  uint64_t uvalue = Unsigned();
332  bool unit_relative_offset = false;
333
334  switch (m_form) {
335  case DW_FORM_addr:
336    s.Address(uvalue, sizeof(uint64_t));
337    break;
338  case DW_FORM_flag:
339  case DW_FORM_data1:
340    s.PutHex8(uvalue);
341    break;
342  case DW_FORM_data2:
343    s.PutHex16(uvalue);
344    break;
345  case DW_FORM_sec_offset:
346  case DW_FORM_data4:
347    s.PutHex32(uvalue);
348    break;
349  case DW_FORM_ref_sig8:
350  case DW_FORM_data8:
351    s.PutHex64(uvalue);
352    break;
353  case DW_FORM_string:
354    s.QuotedCString(AsCString());
355    break;
356  case DW_FORM_exprloc:
357  case DW_FORM_block:
358  case DW_FORM_block1:
359  case DW_FORM_block2:
360  case DW_FORM_block4:
361    if (uvalue > 0) {
362      switch (m_form) {
363      case DW_FORM_exprloc:
364      case DW_FORM_block:
365        s.Printf("<0x%" PRIx64 "> ", uvalue);
366        break;
367      case DW_FORM_block1:
368        s.Printf("<0x%2.2x> ", (uint8_t)uvalue);
369        break;
370      case DW_FORM_block2:
371        s.Printf("<0x%4.4x> ", (uint16_t)uvalue);
372        break;
373      case DW_FORM_block4:
374        s.Printf("<0x%8.8x> ", (uint32_t)uvalue);
375        break;
376      default:
377        break;
378      }
379
380      const uint8_t *data_ptr = m_value.data;
381      if (data_ptr) {
382        const uint8_t *end_data_ptr =
383            data_ptr + uvalue; // uvalue contains size of block
384        while (data_ptr < end_data_ptr) {
385          s.Printf("%2.2x ", *data_ptr);
386          ++data_ptr;
387        }
388      } else
389        s.PutCString("NULL");
390    }
391    break;
392
393  case DW_FORM_sdata:
394    s.PutSLEB128(uvalue);
395    break;
396  case DW_FORM_udata:
397    s.PutULEB128(uvalue);
398    break;
399  case DW_FORM_strp: {
400    const char *dbg_str = AsCString();
401    if (dbg_str) {
402      s.QuotedCString(dbg_str);
403    } else {
404      s.PutHex32(uvalue);
405    }
406  } break;
407
408  case DW_FORM_ref_addr: {
409    assert(m_unit); // Unit must be valid for DW_FORM_ref_addr objects or we
410                    // will get this wrong
411    if (m_unit->GetVersion() <= 2)
412      s.Address(uvalue, sizeof(uint64_t) * 2);
413    else
414      s.Address(uvalue, 4 * 2); // 4 for DWARF32, 8 for DWARF64, but we don't
415                                // support DWARF64 yet
416    break;
417  }
418  case DW_FORM_ref1:
419    unit_relative_offset = true;
420    break;
421  case DW_FORM_ref2:
422    unit_relative_offset = true;
423    break;
424  case DW_FORM_ref4:
425    unit_relative_offset = true;
426    break;
427  case DW_FORM_ref8:
428    unit_relative_offset = true;
429    break;
430  case DW_FORM_ref_udata:
431    unit_relative_offset = true;
432    break;
433
434  // All DW_FORM_indirect attributes should be resolved prior to calling this
435  // function
436  case DW_FORM_indirect:
437    s.PutCString("DW_FORM_indirect");
438    break;
439  case DW_FORM_flag_present:
440    break;
441  default:
442    s.Printf("DW_FORM(0x%4.4x)", m_form);
443    break;
444  }
445
446  if (unit_relative_offset) {
447    assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile
448                    // unit relative or we will get this wrong
449    s.Printf("{0x%8.8" PRIx64 "}", uvalue + m_unit->GetOffset());
450  }
451}
452
453const char *DWARFFormValue::AsCString() const {
454  SymbolFileDWARF &symbol_file = m_unit->GetSymbolFileDWARF();
455
456  if (m_form == DW_FORM_string) {
457    return m_value.value.cstr;
458  } else if (m_form == DW_FORM_strp) {
459    return symbol_file.GetDWARFContext().getOrLoadStrData().PeekCStr(
460        m_value.value.uval);
461  } else if (m_form == DW_FORM_GNU_str_index) {
462    uint32_t index_size = 4;
463    lldb::offset_t offset = m_value.value.uval * index_size;
464    dw_offset_t str_offset =
465        symbol_file.GetDWARFContext().getOrLoadStrOffsetsData().GetMaxU64(
466            &offset, index_size);
467    return symbol_file.GetDWARFContext().getOrLoadStrData().PeekCStr(
468        str_offset);
469  }
470
471  if (m_form == DW_FORM_strx || m_form == DW_FORM_strx1 ||
472      m_form == DW_FORM_strx2 || m_form == DW_FORM_strx3 ||
473      m_form == DW_FORM_strx4) {
474
475    // The same code as above.
476    uint32_t indexSize = 4;
477    lldb::offset_t offset =
478        m_unit->GetStrOffsetsBase() + m_value.value.uval * indexSize;
479    dw_offset_t strOffset =
480        symbol_file.GetDWARFContext().getOrLoadStrOffsetsData().GetMaxU64(
481            &offset, indexSize);
482    return symbol_file.GetDWARFContext().getOrLoadStrData().PeekCStr(strOffset);
483  }
484
485  if (m_form == DW_FORM_line_strp)
486    return symbol_file.GetDWARFContext().getOrLoadLineStrData().PeekCStr(
487        m_value.value.uval);
488
489  return nullptr;
490}
491
492dw_addr_t DWARFFormValue::Address() const {
493  SymbolFileDWARF &symbol_file = m_unit->GetSymbolFileDWARF();
494
495  if (m_form == DW_FORM_addr)
496    return Unsigned();
497
498  assert(m_unit);
499  assert(m_form == DW_FORM_GNU_addr_index || m_form == DW_FORM_addrx ||
500         m_form == DW_FORM_addrx1 || m_form == DW_FORM_addrx2 ||
501         m_form == DW_FORM_addrx3 || m_form == DW_FORM_addrx4);
502
503  uint32_t index_size = m_unit->GetAddressByteSize();
504  dw_offset_t addr_base = m_unit->GetAddrBase();
505  lldb::offset_t offset = addr_base + m_value.value.uval * index_size;
506  return symbol_file.GetDWARFContext().getOrLoadAddrData().GetMaxU64(
507      &offset, index_size);
508}
509
510DWARFDIE DWARFFormValue::Reference() const {
511  uint64_t value = m_value.value.uval;
512  switch (m_form) {
513  case DW_FORM_ref1:
514  case DW_FORM_ref2:
515  case DW_FORM_ref4:
516  case DW_FORM_ref8:
517  case DW_FORM_ref_udata:
518    assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile
519                    // unit relative or we will get this wrong
520    value += m_unit->GetOffset();
521    if (!m_unit->ContainsDIEOffset(value)) {
522      m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
523          "DW_FORM_ref* DIE reference 0x%" PRIx64 " is outside of its CU",
524          value);
525      return {};
526    }
527    return const_cast<DWARFUnit *>(m_unit)->GetDIE(value);
528
529  case DW_FORM_ref_addr: {
530    DWARFUnit *ref_cu =
531        m_unit->GetSymbolFileDWARF().DebugInfo()->GetUnitContainingDIEOffset(
532            DIERef::Section::DebugInfo, value);
533    if (!ref_cu) {
534      m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
535          "DW_FORM_ref_addr DIE reference 0x%" PRIx64 " has no matching CU",
536          value);
537      return {};
538    }
539    return ref_cu->GetDIE(value);
540  }
541
542  case DW_FORM_ref_sig8: {
543    DWARFTypeUnit *tu =
544        m_unit->GetSymbolFileDWARF().DebugInfo()->GetTypeUnitForHash(value);
545    if (!tu)
546      return {};
547    return tu->GetDIE(tu->GetTypeOffset());
548  }
549
550  default:
551    return {};
552  }
553}
554
555uint64_t DWARFFormValue::Reference(dw_offset_t base_offset) const {
556  uint64_t value = m_value.value.uval;
557  switch (m_form) {
558  case DW_FORM_ref1:
559  case DW_FORM_ref2:
560  case DW_FORM_ref4:
561  case DW_FORM_ref8:
562  case DW_FORM_ref_udata:
563    return value + base_offset;
564
565  case DW_FORM_ref_addr:
566  case DW_FORM_ref_sig8:
567  case DW_FORM_GNU_ref_alt:
568    return value;
569
570  default:
571    return DW_INVALID_OFFSET;
572  }
573}
574
575const uint8_t *DWARFFormValue::BlockData() const { return m_value.data; }
576
577bool DWARFFormValue::IsBlockForm(const dw_form_t form) {
578  switch (form) {
579  case DW_FORM_exprloc:
580  case DW_FORM_block:
581  case DW_FORM_block1:
582  case DW_FORM_block2:
583  case DW_FORM_block4:
584    return true;
585  }
586  return false;
587}
588
589bool DWARFFormValue::IsDataForm(const dw_form_t form) {
590  switch (form) {
591  case DW_FORM_sdata:
592  case DW_FORM_udata:
593  case DW_FORM_data1:
594  case DW_FORM_data2:
595  case DW_FORM_data4:
596  case DW_FORM_data8:
597    return true;
598  }
599  return false;
600}
601
602int DWARFFormValue::Compare(const DWARFFormValue &a_value,
603                            const DWARFFormValue &b_value) {
604  dw_form_t a_form = a_value.Form();
605  dw_form_t b_form = b_value.Form();
606  if (a_form < b_form)
607    return -1;
608  if (a_form > b_form)
609    return 1;
610  switch (a_form) {
611  case DW_FORM_addr:
612  case DW_FORM_addrx:
613  case DW_FORM_flag:
614  case DW_FORM_data1:
615  case DW_FORM_data2:
616  case DW_FORM_data4:
617  case DW_FORM_data8:
618  case DW_FORM_udata:
619  case DW_FORM_ref_addr:
620  case DW_FORM_sec_offset:
621  case DW_FORM_flag_present:
622  case DW_FORM_ref_sig8:
623  case DW_FORM_GNU_addr_index: {
624    uint64_t a = a_value.Unsigned();
625    uint64_t b = b_value.Unsigned();
626    if (a < b)
627      return -1;
628    if (a > b)
629      return 1;
630    return 0;
631  }
632
633  case DW_FORM_sdata: {
634    int64_t a = a_value.Signed();
635    int64_t b = b_value.Signed();
636    if (a < b)
637      return -1;
638    if (a > b)
639      return 1;
640    return 0;
641  }
642
643  case DW_FORM_string:
644  case DW_FORM_strp:
645  case DW_FORM_GNU_str_index: {
646    const char *a_string = a_value.AsCString();
647    const char *b_string = b_value.AsCString();
648    if (a_string == b_string)
649      return 0;
650    else if (a_string && b_string)
651      return strcmp(a_string, b_string);
652    else if (a_string == nullptr)
653      return -1; // A string is NULL, and B is valid
654    else
655      return 1; // A string valid, and B is NULL
656  }
657
658  case DW_FORM_block:
659  case DW_FORM_block1:
660  case DW_FORM_block2:
661  case DW_FORM_block4:
662  case DW_FORM_exprloc: {
663    uint64_t a_len = a_value.Unsigned();
664    uint64_t b_len = b_value.Unsigned();
665    if (a_len < b_len)
666      return -1;
667    if (a_len > b_len)
668      return 1;
669    // The block lengths are the same
670    return memcmp(a_value.BlockData(), b_value.BlockData(), a_value.Unsigned());
671  } break;
672
673  case DW_FORM_ref1:
674  case DW_FORM_ref2:
675  case DW_FORM_ref4:
676  case DW_FORM_ref8:
677  case DW_FORM_ref_udata: {
678    uint64_t a = a_value.m_value.value.uval;
679    uint64_t b = b_value.m_value.value.uval;
680    if (a < b)
681      return -1;
682    if (a > b)
683      return 1;
684    return 0;
685  }
686
687  case DW_FORM_indirect:
688    llvm_unreachable(
689        "This shouldn't happen after the form has been extracted...");
690
691  default:
692    llvm_unreachable("Unhandled DW_FORM");
693  }
694  return -1;
695}
696
697bool DWARFFormValue::FormIsSupported(dw_form_t form) {
698  switch (form) {
699    case DW_FORM_addr:
700    case DW_FORM_addrx:
701    case DW_FORM_rnglistx:
702    case DW_FORM_block2:
703    case DW_FORM_block4:
704    case DW_FORM_data2:
705    case DW_FORM_data4:
706    case DW_FORM_data8:
707    case DW_FORM_string:
708    case DW_FORM_block:
709    case DW_FORM_block1:
710    case DW_FORM_data1:
711    case DW_FORM_flag:
712    case DW_FORM_sdata:
713    case DW_FORM_strp:
714    case DW_FORM_strx:
715    case DW_FORM_strx1:
716    case DW_FORM_strx2:
717    case DW_FORM_strx3:
718    case DW_FORM_strx4:
719    case DW_FORM_udata:
720    case DW_FORM_ref_addr:
721    case DW_FORM_ref1:
722    case DW_FORM_ref2:
723    case DW_FORM_ref4:
724    case DW_FORM_ref8:
725    case DW_FORM_ref_udata:
726    case DW_FORM_indirect:
727    case DW_FORM_sec_offset:
728    case DW_FORM_exprloc:
729    case DW_FORM_flag_present:
730    case DW_FORM_ref_sig8:
731    case DW_FORM_GNU_str_index:
732    case DW_FORM_GNU_addr_index:
733    case DW_FORM_implicit_const:
734      return true;
735    default:
736      break;
737  }
738  return false;
739}
740