DWARFFormValue.cpp revision 296417
1236769Sobrien//===-- DWARFFormValue.cpp --------------------------------------*- C++ -*-===//
2236769Sobrien//
3236769Sobrien//                     The LLVM Compiler Infrastructure
4236769Sobrien//
5236769Sobrien// This file is distributed under the University of Illinois Open Source
6236769Sobrien// License. See LICENSE.TXT for details.
7236769Sobrien//
8236769Sobrien//===----------------------------------------------------------------------===//
9236769Sobrien
10236769Sobrien#include <assert.h>
11236769Sobrien
12236769Sobrien#include "lldb/Core/dwarf.h"
13236769Sobrien#include "lldb/Core/Stream.h"
14236769Sobrien
15236769Sobrien#include "DWARFFormValue.h"
16236769Sobrien#include "DWARFCompileUnit.h"
17236769Sobrien
18236769Sobrienclass DWARFCompileUnit;
19236769Sobrien
20236769Sobrienusing namespace lldb_private;
21236769Sobrien
22236769Sobrien
23236769Sobrienstatic uint8_t g_form_sizes_addr4[] =
24236769Sobrien{
25236769Sobrien    0, // 0x00 unused
26236769Sobrien    4, // 0x01 DW_FORM_addr
27236769Sobrien    0, // 0x02 unused
28236769Sobrien    0, // 0x03 DW_FORM_block2
29236769Sobrien    0, // 0x04 DW_FORM_block4
30236769Sobrien    2, // 0x05 DW_FORM_data2
31236769Sobrien    4, // 0x06 DW_FORM_data4
32236769Sobrien    8, // 0x07 DW_FORM_data8
33236769Sobrien    0, // 0x08 DW_FORM_string
34236769Sobrien    0, // 0x09 DW_FORM_block
35236769Sobrien    0, // 0x0a DW_FORM_block1
36236769Sobrien    1, // 0x0b DW_FORM_data1
37236769Sobrien    1, // 0x0c DW_FORM_flag
38236769Sobrien    0, // 0x0d DW_FORM_sdata
39236769Sobrien    4, // 0x0e DW_FORM_strp
40236769Sobrien    0, // 0x0f DW_FORM_udata
41236769Sobrien    0, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes for DWARF32, 8 bytes for DWARF32 in DWARF 3 and later
42236769Sobrien    1, // 0x11 DW_FORM_ref1
43236769Sobrien    2, // 0x12 DW_FORM_ref2
44236769Sobrien    4, // 0x13 DW_FORM_ref4
45236769Sobrien    8, // 0x14 DW_FORM_ref8
46236769Sobrien    0, // 0x15 DW_FORM_ref_udata
47236769Sobrien    0, // 0x16 DW_FORM_indirect
48236769Sobrien    4, // 0x17 DW_FORM_sec_offset
49236769Sobrien    0, // 0x18 DW_FORM_exprloc
50236769Sobrien    0, // 0x19 DW_FORM_flag_present
51236769Sobrien    0, // 0x1a
52236769Sobrien    0, // 0x1b
53236769Sobrien    0, // 0x1c
54236769Sobrien    0, // 0x1d
55236769Sobrien    0, // 0x1e
56236769Sobrien    0, // 0x1f
57236769Sobrien    8, // 0x20 DW_FORM_ref_sig8
58236769Sobrien
59236769Sobrien};
60236769Sobrien
61236769Sobrienstatic uint8_t
62236769Sobrieng_form_sizes_addr8[] =
63236769Sobrien{
64236769Sobrien    0, // 0x00 unused
65236769Sobrien    8, // 0x01 DW_FORM_addr
66236769Sobrien    0, // 0x02 unused
67236769Sobrien    0, // 0x03 DW_FORM_block2
68236769Sobrien    0, // 0x04 DW_FORM_block4
69236769Sobrien    2, // 0x05 DW_FORM_data2
70236769Sobrien    4, // 0x06 DW_FORM_data4
71236769Sobrien    8, // 0x07 DW_FORM_data8
72236769Sobrien    0, // 0x08 DW_FORM_string
73236769Sobrien    0, // 0x09 DW_FORM_block
74236769Sobrien    0, // 0x0a DW_FORM_block1
75236769Sobrien    1, // 0x0b DW_FORM_data1
76236769Sobrien    1, // 0x0c DW_FORM_flag
77236769Sobrien    0, // 0x0d DW_FORM_sdata
78236769Sobrien    4, // 0x0e DW_FORM_strp
79236769Sobrien    0, // 0x0f DW_FORM_udata
80236769Sobrien    0, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes for DWARF32, 8 bytes for DWARF32 in DWARF 3 and later
81236769Sobrien    1, // 0x11 DW_FORM_ref1
82236769Sobrien    2, // 0x12 DW_FORM_ref2
83236769Sobrien    4, // 0x13 DW_FORM_ref4
84236769Sobrien    8, // 0x14 DW_FORM_ref8
85236769Sobrien    0, // 0x15 DW_FORM_ref_udata
86236769Sobrien    0, // 0x16 DW_FORM_indirect
87236769Sobrien    4, // 0x17 DW_FORM_sec_offset
88    0, // 0x18 DW_FORM_exprloc
89    0, // 0x19 DW_FORM_flag_present
90    0, // 0x1a
91    0, // 0x1b
92    0, // 0x1c
93    0, // 0x1d
94    0, // 0x1e
95    0, // 0x1f
96    8, // 0x20 DW_FORM_ref_sig8
97};
98
99// Difference with g_form_sizes_addr8:
100// DW_FORM_strp and DW_FORM_sec_offset are 8 instead of 4
101static uint8_t
102g_form_sizes_addr8_dwarf64[] =
103{
104    0, // 0x00 unused
105    8, // 0x01 DW_FORM_addr
106    0, // 0x02 unused
107    0, // 0x03 DW_FORM_block2
108    0, // 0x04 DW_FORM_block4
109    2, // 0x05 DW_FORM_data2
110    4, // 0x06 DW_FORM_data4
111    8, // 0x07 DW_FORM_data8
112    0, // 0x08 DW_FORM_string
113    0, // 0x09 DW_FORM_block
114    0, // 0x0a DW_FORM_block1
115    1, // 0x0b DW_FORM_data1
116    1, // 0x0c DW_FORM_flag
117    0, // 0x0d DW_FORM_sdata
118    8, // 0x0e DW_FORM_strp
119    0, // 0x0f DW_FORM_udata
120    0, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes for DWARF32, 8 bytes for DWARF32 in DWARF 3 and later
121    1, // 0x11 DW_FORM_ref1
122    2, // 0x12 DW_FORM_ref2
123    4, // 0x13 DW_FORM_ref4
124    8, // 0x14 DW_FORM_ref8
125    0, // 0x15 DW_FORM_ref_udata
126    0, // 0x16 DW_FORM_indirect
127    8, // 0x17 DW_FORM_sec_offset
128    0, // 0x18 DW_FORM_exprloc
129    0, // 0x19 DW_FORM_flag_present
130    0, // 0x1a
131    0, // 0x1b
132    0, // 0x1c
133    0, // 0x1d
134    0, // 0x1e
135    0, // 0x1f
136    8, // 0x20 DW_FORM_ref_sig8
137};
138
139DWARFFormValue::FixedFormSizes
140DWARFFormValue::GetFixedFormSizesForAddressSize (uint8_t addr_size, bool is_dwarf64)
141{
142    if (!is_dwarf64) {
143        switch (addr_size)
144        {
145        case 4: return FixedFormSizes(g_form_sizes_addr4, sizeof(g_form_sizes_addr4));
146        case 8: return FixedFormSizes(g_form_sizes_addr8, sizeof(g_form_sizes_addr8));
147        }
148    } else {
149        if (addr_size == 8)
150            return FixedFormSizes(g_form_sizes_addr8_dwarf64, sizeof(g_form_sizes_addr8_dwarf64));
151        // is_dwarf64 && addr_size == 4 : no provider does this.
152    }
153    return FixedFormSizes();
154}
155
156DWARFFormValue::DWARFFormValue() :
157    m_cu (NULL),
158    m_form(0),
159    m_value()
160{
161}
162
163DWARFFormValue::DWARFFormValue(const DWARFCompileUnit* cu, dw_form_t form) :
164    m_cu (cu),
165    m_form(form),
166    m_value()
167{
168}
169
170bool
171DWARFFormValue::ExtractValue(const DWARFDataExtractor& data, lldb::offset_t* offset_ptr)
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 instances we run into
178    do
179    {
180        indirect = false;
181        switch (m_form)
182        {
183        case DW_FORM_addr:      assert(m_cu);
184                                m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::GetAddressByteSize(m_cu));  break;
185        case DW_FORM_block2:    m_value.value.uval = data.GetU16(offset_ptr); is_block = true;          break;
186        case DW_FORM_block4:    m_value.value.uval = data.GetU32(offset_ptr); is_block = true;          break;
187        case DW_FORM_data2:     m_value.value.uval = data.GetU16(offset_ptr);                           break;
188        case DW_FORM_data4:     m_value.value.uval = data.GetU32(offset_ptr);                           break;
189        case DW_FORM_data8:     m_value.value.uval = data.GetU64(offset_ptr);                           break;
190        case DW_FORM_string:    m_value.value.cstr = data.GetCStr(offset_ptr);                          break;
191        case DW_FORM_exprloc:
192        case DW_FORM_block:     m_value.value.uval = data.GetULEB128(offset_ptr); is_block = true;      break;
193        case DW_FORM_block1:    m_value.value.uval = data.GetU8(offset_ptr); is_block = true;           break;
194        case DW_FORM_data1:     m_value.value.uval = data.GetU8(offset_ptr);                            break;
195        case DW_FORM_flag:      m_value.value.uval = data.GetU8(offset_ptr);                            break;
196        case DW_FORM_sdata:     m_value.value.sval = data.GetSLEB128(offset_ptr);                       break;
197        case DW_FORM_strp:      assert(m_cu);
198                                m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::IsDWARF64(m_cu) ? 8 : 4);  break;
199    //  case DW_FORM_APPLE_db_str:
200        case DW_FORM_udata:     m_value.value.uval = data.GetULEB128(offset_ptr);                       break;
201        case DW_FORM_ref_addr:  assert(m_cu);
202                                ref_addr_size = 4;
203                                if (m_cu->GetVersion() <= 2)
204                                    ref_addr_size = m_cu->GetAddressByteSize();
205                                else
206                                    ref_addr_size = m_cu->IsDWARF64() ? 8 : 4;
207                                m_value.value.uval = data.GetMaxU64(offset_ptr, ref_addr_size);         break;
208        case DW_FORM_ref1:      m_value.value.uval = data.GetU8(offset_ptr);                            break;
209        case DW_FORM_ref2:      m_value.value.uval = data.GetU16(offset_ptr);                           break;
210        case DW_FORM_ref4:      m_value.value.uval = data.GetU32(offset_ptr);                           break;
211        case DW_FORM_ref8:      m_value.value.uval = data.GetU64(offset_ptr);                           break;
212        case DW_FORM_ref_udata: m_value.value.uval = data.GetULEB128(offset_ptr);                       break;
213        case DW_FORM_indirect:
214            m_form = data.GetULEB128(offset_ptr);
215            indirect = true;
216            break;
217
218        case DW_FORM_sec_offset:     assert(m_cu);
219                                     m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::IsDWARF64(m_cu) ? 8 : 4); break;
220        case DW_FORM_flag_present:   m_value.value.uval = 1;                                            break;
221        case DW_FORM_ref_sig8:       m_value.value.uval = data.GetU64(offset_ptr);                      break;
222        case DW_FORM_GNU_str_index:  m_value.value.uval = data.GetULEB128(offset_ptr);                  break;
223        case DW_FORM_GNU_addr_index: m_value.value.uval = data.GetULEB128(offset_ptr);                  break;
224        default:
225            return false;
226            break;
227        }
228    } while (indirect);
229
230    if (is_block)
231    {
232        m_value.data = data.PeekData(*offset_ptr, m_value.value.uval);
233        if (m_value.data != NULL)
234        {
235            *offset_ptr += m_value.value.uval;
236        }
237    }
238
239    return true;
240}
241
242bool
243DWARFFormValue::SkipValue(const DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr) const
244{
245    return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, m_cu);
246}
247
248bool
249DWARFFormValue::SkipValue(dw_form_t form, const DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu)
250{
251    uint8_t ref_addr_size;
252    switch (form)
253    {
254    // Blocks if inlined data that have a length field and the data bytes
255    // inlined in the .debug_info
256    case DW_FORM_exprloc:
257    case DW_FORM_block:  { dw_uleb128_t size = debug_info_data.GetULEB128(offset_ptr); *offset_ptr += size; } return true;
258    case DW_FORM_block1: { dw_uleb128_t size = debug_info_data.GetU8(offset_ptr);      *offset_ptr += size; } return true;
259    case DW_FORM_block2: { dw_uleb128_t size = debug_info_data.GetU16(offset_ptr);     *offset_ptr += size; } return true;
260    case DW_FORM_block4: { dw_uleb128_t size = debug_info_data.GetU32(offset_ptr);     *offset_ptr += size; } return true;
261
262    // Inlined NULL terminated C-strings
263    case DW_FORM_string:
264        debug_info_data.GetCStr(offset_ptr);
265        return true;
266
267    // Compile unit address sized values
268    case DW_FORM_addr:
269        *offset_ptr += DWARFCompileUnit::GetAddressByteSize(cu);
270        return true;
271
272    case DW_FORM_ref_addr:
273        ref_addr_size = 4;
274        assert (cu); // CU must be valid for DW_FORM_ref_addr objects or we will get this wrong
275        if (cu->GetVersion() <= 2)
276            ref_addr_size = cu->GetAddressByteSize();
277        else
278            ref_addr_size = cu->IsDWARF64() ? 8 : 4;
279        *offset_ptr += ref_addr_size;
280        return true;
281
282    // 0 bytes values (implied from DW_FORM)
283    case DW_FORM_flag_present:
284        return true;
285
286    // 1 byte values
287    case DW_FORM_data1:
288    case DW_FORM_flag:
289    case DW_FORM_ref1:
290        *offset_ptr += 1;
291        return true;
292
293    // 2 byte values
294    case DW_FORM_data2:
295    case DW_FORM_ref2:
296        *offset_ptr += 2;
297        return true;
298
299    // 32 bit for DWARF 32, 64 for DWARF 64
300    case DW_FORM_sec_offset:
301    case DW_FORM_strp:
302        assert(cu);
303        *offset_ptr += (cu->IsDWARF64() ? 8 : 4);
304        return true;
305
306    // 4 byte values
307    case DW_FORM_data4:
308    case DW_FORM_ref4:
309        *offset_ptr += 4;
310        return true;
311
312    // 8 byte values
313    case DW_FORM_data8:
314    case DW_FORM_ref8:
315    case DW_FORM_ref_sig8:
316        *offset_ptr += 8;
317        return true;
318
319    // signed or unsigned LEB 128 values
320    case DW_FORM_sdata:
321    case DW_FORM_udata:
322    case DW_FORM_ref_udata:
323    case DW_FORM_GNU_addr_index:
324    case DW_FORM_GNU_str_index:
325        debug_info_data.Skip_LEB128(offset_ptr);
326        return true;
327
328    case DW_FORM_indirect:
329        {
330            dw_form_t indirect_form = debug_info_data.GetULEB128(offset_ptr);
331            return DWARFFormValue::SkipValue (indirect_form,
332                                              debug_info_data,
333                                              offset_ptr,
334                                              cu);
335        }
336
337    default:
338        break;
339    }
340    return false;
341}
342
343
344void
345DWARFFormValue::Dump(Stream &s) const
346{
347    uint64_t uvalue = Unsigned();
348    bool cu_relative_offset = false;
349
350    bool verbose = s.GetVerbose();
351
352    switch (m_form)
353    {
354    case DW_FORM_addr:      s.Address(uvalue, sizeof (uint64_t)); break;
355    case DW_FORM_flag:
356    case DW_FORM_data1:     s.PutHex8(uvalue);         break;
357    case DW_FORM_data2:     s.PutHex16(uvalue);        break;
358    case DW_FORM_sec_offset:
359    case DW_FORM_data4:     s.PutHex32(uvalue);        break;
360    case DW_FORM_ref_sig8:
361    case DW_FORM_data8:     s.PutHex64(uvalue);        break;
362    case DW_FORM_string:    s.QuotedCString(AsCString()); break;
363    case DW_FORM_exprloc:
364    case DW_FORM_block:
365    case DW_FORM_block1:
366    case DW_FORM_block2:
367    case DW_FORM_block4:
368        if (uvalue > 0)
369        {
370            switch (m_form)
371            {
372            case DW_FORM_exprloc:
373            case DW_FORM_block:  s.Printf("<0x%" PRIx64 "> ", uvalue);                break;
374            case DW_FORM_block1: s.Printf("<0x%2.2x> ", (uint8_t)uvalue);      break;
375            case DW_FORM_block2: s.Printf("<0x%4.4x> ", (uint16_t)uvalue);     break;
376            case DW_FORM_block4: s.Printf("<0x%8.8x> ", (uint32_t)uvalue);     break;
377            default:                                                            break;
378            }
379
380            const uint8_t* data_ptr = m_value.data;
381            if (data_ptr)
382            {
383                const uint8_t* end_data_ptr = data_ptr + uvalue;    // uvalue contains size of block
384                while (data_ptr < end_data_ptr)
385                {
386                    s.Printf("%2.2x ", *data_ptr);
387                    ++data_ptr;
388                }
389            }
390            else
391                s.PutCString("NULL");
392        }
393        break;
394
395    case DW_FORM_sdata:     s.PutSLEB128(uvalue); break;
396    case DW_FORM_udata:     s.PutULEB128(uvalue); break;
397    case DW_FORM_strp:
398        {
399            const char* dbg_str = AsCString();
400            if (dbg_str)
401            {
402                if (verbose)
403                    s.Printf(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
404                s.QuotedCString(dbg_str);
405            }
406            else
407            {
408                s.PutHex32(uvalue);
409            }
410        }
411        break;
412
413    case DW_FORM_ref_addr:
414    {
415        assert (m_cu); // CU must be valid for DW_FORM_ref_addr objects or we will get this wrong
416        if (m_cu->GetVersion() <= 2)
417            s.Address(uvalue, sizeof (uint64_t) * 2);
418        else
419            s.Address(uvalue, 4 * 2);// 4 for DWARF32, 8 for DWARF64, but we don't support DWARF64 yet
420        break;
421    }
422    case DW_FORM_ref1:      cu_relative_offset = true;  if (verbose) s.Printf("cu + 0x%2.2x", (uint8_t)uvalue); break;
423    case DW_FORM_ref2:      cu_relative_offset = true;  if (verbose) s.Printf("cu + 0x%4.4x", (uint16_t)uvalue); break;
424    case DW_FORM_ref4:      cu_relative_offset = true;  if (verbose) s.Printf("cu + 0x%4.4x", (uint32_t)uvalue); break;
425    case DW_FORM_ref8:      cu_relative_offset = true;  if (verbose) s.Printf("cu + 0x%8.8" PRIx64, uvalue); break;
426    case DW_FORM_ref_udata: cu_relative_offset = true;  if (verbose) s.Printf("cu + 0x%" PRIx64, uvalue); break;
427
428    // All DW_FORM_indirect attributes should be resolved prior to calling this function
429    case DW_FORM_indirect:  s.PutCString("DW_FORM_indirect"); break;
430    case DW_FORM_flag_present: break;
431    default:
432        s.Printf("DW_FORM(0x%4.4x)", m_form);
433        break;
434    }
435
436    if (cu_relative_offset)
437    {
438        assert (m_cu); // CU must be valid for DW_FORM_ref forms that are compile unit relative or we will get this wrong
439        if (verbose)
440            s.PutCString(" => ");
441
442        s.Printf("{0x%8.8" PRIx64 "}", uvalue + m_cu->GetOffset());
443    }
444}
445
446const char*
447DWARFFormValue::AsCString() const
448{
449    SymbolFileDWARF* symbol_file = m_cu->GetSymbolFileDWARF();
450
451    if (m_form == DW_FORM_string)
452    {
453        return m_value.value.cstr;
454    }
455    else if (m_form == DW_FORM_strp)
456    {
457        if (!symbol_file)
458            return nullptr;
459
460        return symbol_file->get_debug_str_data().PeekCStr(m_value.value.uval);
461    }
462    else if (m_form == DW_FORM_GNU_str_index)
463    {
464        if (!symbol_file)
465            return nullptr;
466
467        uint32_t index_size = m_cu->IsDWARF64() ? 8 : 4;
468        lldb::offset_t offset = m_value.value.uval * index_size;
469        dw_offset_t str_offset = symbol_file->get_debug_str_offsets_data().GetMaxU64(&offset, index_size);
470        return symbol_file->get_debug_str_data().PeekCStr(str_offset);
471    }
472    return nullptr;
473}
474
475dw_addr_t
476DWARFFormValue::Address() const
477{
478    SymbolFileDWARF* symbol_file = m_cu->GetSymbolFileDWARF();
479
480    if (m_form == DW_FORM_addr)
481        return Unsigned();
482
483    assert(m_cu);
484    assert(m_form == DW_FORM_GNU_addr_index);
485
486    if (!symbol_file)
487        return 0;
488
489    uint32_t index_size = m_cu->GetAddressByteSize();
490    dw_offset_t addr_base = m_cu->GetAddrBase();
491    lldb::offset_t offset = addr_base + m_value.value.uval * index_size;
492    return symbol_file->get_debug_addr_data().GetMaxU64(&offset, index_size);
493}
494
495uint64_t
496DWARFFormValue::Reference() const
497{
498    uint64_t die_offset = m_value.value.uval;
499    switch (m_form)
500    {
501    case DW_FORM_ref1:
502    case DW_FORM_ref2:
503    case DW_FORM_ref4:
504    case DW_FORM_ref8:
505    case DW_FORM_ref_udata:
506        assert (m_cu); // CU must be valid for DW_FORM_ref forms that are compile unit relative or we will get this wrong
507        die_offset += m_cu->GetOffset();
508        break;
509
510    default:
511        break;
512    }
513
514    return die_offset;
515}
516
517uint64_t
518DWARFFormValue::Reference (dw_offset_t base_offset) const
519{
520    uint64_t die_offset = m_value.value.uval;
521    switch (m_form)
522    {
523        case DW_FORM_ref1:
524        case DW_FORM_ref2:
525        case DW_FORM_ref4:
526        case DW_FORM_ref8:
527        case DW_FORM_ref_udata:
528            die_offset += base_offset;
529            break;
530
531        default:
532            break;
533    }
534
535    return die_offset;
536}
537
538
539const uint8_t*
540DWARFFormValue::BlockData() const
541{
542    return m_value.data;
543}
544
545
546bool
547DWARFFormValue::IsBlockForm(const dw_form_t form)
548{
549    switch (form)
550    {
551    case DW_FORM_block:
552    case DW_FORM_block1:
553    case DW_FORM_block2:
554    case DW_FORM_block4:
555        return true;
556    }
557    return false;
558}
559
560bool
561DWARFFormValue::IsDataForm(const dw_form_t form)
562{
563    switch (form)
564    {
565    case DW_FORM_sdata:
566    case DW_FORM_udata:
567    case DW_FORM_data1:
568    case DW_FORM_data2:
569    case DW_FORM_data4:
570    case DW_FORM_data8:
571        return true;
572    }
573    return false;
574}
575
576int
577DWARFFormValue::Compare (const DWARFFormValue& a_value,
578                         const DWARFFormValue& b_value)
579{
580    dw_form_t a_form = a_value.Form();
581    dw_form_t b_form = b_value.Form();
582    if (a_form < b_form)
583        return -1;
584    if (a_form > b_form)
585        return 1;
586    switch (a_form)
587    {
588    case DW_FORM_addr:
589    case DW_FORM_flag:
590    case DW_FORM_data1:
591    case DW_FORM_data2:
592    case DW_FORM_data4:
593    case DW_FORM_data8:
594    case DW_FORM_udata:
595    case DW_FORM_ref_addr:
596    case DW_FORM_sec_offset:
597    case DW_FORM_flag_present:
598    case DW_FORM_ref_sig8:
599    case DW_FORM_GNU_addr_index:
600        {
601            uint64_t a = a_value.Unsigned();
602            uint64_t b = b_value.Unsigned();
603            if (a < b)
604                return -1;
605            if (a > b)
606                return 1;
607            return 0;
608        }
609
610    case DW_FORM_sdata:
611        {
612            int64_t a = a_value.Signed();
613            int64_t b = b_value.Signed();
614            if (a < b)
615                return -1;
616            if (a > b)
617                return 1;
618            return 0;
619        }
620
621    case DW_FORM_string:
622    case DW_FORM_strp:
623    case DW_FORM_GNU_str_index:
624        {
625            const char *a_string = a_value.AsCString();
626            const char *b_string = b_value.AsCString();
627            if (a_string == b_string)
628                return 0;
629            else if (a_string && b_string)
630                return strcmp(a_string, b_string);
631            else if (a_string == NULL)
632                return -1;  // A string is NULL, and B is valid
633            else
634                return 1;   // A string valid, and B is NULL
635        }
636
637
638    case DW_FORM_block:
639    case DW_FORM_block1:
640    case DW_FORM_block2:
641    case DW_FORM_block4:
642    case DW_FORM_exprloc:
643        {
644            uint64_t a_len = a_value.Unsigned();
645            uint64_t b_len = b_value.Unsigned();
646            if (a_len < b_len)
647                return -1;
648            if (a_len > b_len)
649                return 1;
650            // The block lengths are the same
651            return memcmp(a_value.BlockData(), b_value.BlockData(), a_value.Unsigned());
652        }
653        break;
654
655    case DW_FORM_ref1:
656    case DW_FORM_ref2:
657    case DW_FORM_ref4:
658    case DW_FORM_ref8:
659    case DW_FORM_ref_udata:
660        {
661            uint64_t a = a_value.Reference();
662            uint64_t b = b_value.Reference();
663            if (a < b)
664                return -1;
665            if (a > b)
666                return 1;
667            return 0;
668        }
669
670    case DW_FORM_indirect:
671        assert(!"This shouldn't happen after the form has been extracted...");
672        break;
673
674    default:
675        assert(!"Unhandled DW_FORM");
676        break;
677    }
678    return -1;
679}
680
681