DWARFFormValue.cpp revision 288943
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/Core/Stream.h"
14
15#include "DWARFFormValue.h"
16#include "DWARFCompileUnit.h"
17
18class DWARFCompileUnit;
19
20using namespace lldb_private;
21
22
23static uint8_t g_form_sizes_addr4[] =
24{
25    0, // 0x00 unused
26    4, // 0x01 DW_FORM_addr
27    0, // 0x02 unused
28    0, // 0x03 DW_FORM_block2
29    0, // 0x04 DW_FORM_block4
30    2, // 0x05 DW_FORM_data2
31    4, // 0x06 DW_FORM_data4
32    8, // 0x07 DW_FORM_data8
33    0, // 0x08 DW_FORM_string
34    0, // 0x09 DW_FORM_block
35    0, // 0x0a DW_FORM_block1
36    1, // 0x0b DW_FORM_data1
37    1, // 0x0c DW_FORM_flag
38    0, // 0x0d DW_FORM_sdata
39    4, // 0x0e DW_FORM_strp
40    0, // 0x0f DW_FORM_udata
41    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
42    1, // 0x11 DW_FORM_ref1
43    2, // 0x12 DW_FORM_ref2
44    4, // 0x13 DW_FORM_ref4
45    8, // 0x14 DW_FORM_ref8
46    0, // 0x15 DW_FORM_ref_udata
47    0, // 0x16 DW_FORM_indirect
48    4, // 0x17 DW_FORM_sec_offset
49    0, // 0x18 DW_FORM_exprloc
50    0, // 0x19 DW_FORM_flag_present
51    0, // 0x1a
52    0, // 0x1b
53    0, // 0x1c
54    0, // 0x1d
55    0, // 0x1e
56    0, // 0x1f
57    8, // 0x20 DW_FORM_ref_sig8
58
59};
60
61static uint8_t
62g_form_sizes_addr8[] =
63{
64    0, // 0x00 unused
65    8, // 0x01 DW_FORM_addr
66    0, // 0x02 unused
67    0, // 0x03 DW_FORM_block2
68    0, // 0x04 DW_FORM_block4
69    2, // 0x05 DW_FORM_data2
70    4, // 0x06 DW_FORM_data4
71    8, // 0x07 DW_FORM_data8
72    0, // 0x08 DW_FORM_string
73    0, // 0x09 DW_FORM_block
74    0, // 0x0a DW_FORM_block1
75    1, // 0x0b DW_FORM_data1
76    1, // 0x0c DW_FORM_flag
77    0, // 0x0d DW_FORM_sdata
78    4, // 0x0e DW_FORM_strp
79    0, // 0x0f DW_FORM_udata
80    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
81    1, // 0x11 DW_FORM_ref1
82    2, // 0x12 DW_FORM_ref2
83    4, // 0x13 DW_FORM_ref4
84    8, // 0x14 DW_FORM_ref8
85    0, // 0x15 DW_FORM_ref_udata
86    0, // 0x16 DW_FORM_indirect
87    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
139const uint8_t *
140DWARFFormValue::GetFixedFormSizesForAddressSize (uint8_t addr_size, bool is_dwarf64)
141{
142    if (!is_dwarf64) {
143        switch (addr_size)
144        {
145        case 4: return g_form_sizes_addr4;
146        case 8: return g_form_sizes_addr8;
147        }
148    } else {
149        if (addr_size == 8)
150            return g_form_sizes_addr8_dwarf64;
151        // is_dwarf64 && addr_size == 4 : no provider does this.
152    }
153    return NULL;
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);
191                                // Set the string value to also be the data for inlined cstr form values only
192                                // so we can tell the difference between DW_FORM_string and DW_FORM_strp form
193                                // values;
194                                m_value.data = (const uint8_t*)m_value.value.cstr;                      break;
195        case DW_FORM_exprloc:
196        case DW_FORM_block:     m_value.value.uval = data.GetULEB128(offset_ptr); is_block = true;      break;
197        case DW_FORM_block1:    m_value.value.uval = data.GetU8(offset_ptr); is_block = true;           break;
198        case DW_FORM_data1:     m_value.value.uval = data.GetU8(offset_ptr);                            break;
199        case DW_FORM_flag:      m_value.value.uval = data.GetU8(offset_ptr);                            break;
200        case DW_FORM_sdata:     m_value.value.sval = data.GetSLEB128(offset_ptr);                       break;
201        case DW_FORM_strp:      assert(m_cu);
202                                m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::IsDWARF64(m_cu) ? 8 : 4);  break;
203    //  case DW_FORM_APPLE_db_str:
204        case DW_FORM_udata:     m_value.value.uval = data.GetULEB128(offset_ptr);                       break;
205        case DW_FORM_ref_addr:  assert(m_cu);
206                                ref_addr_size = 4;
207                                if (m_cu->GetVersion() <= 2)
208                                    ref_addr_size = m_cu->GetAddressByteSize();
209                                else
210                                    ref_addr_size = m_cu->IsDWARF64() ? 8 : 4;
211                                m_value.value.uval = data.GetMaxU64(offset_ptr, ref_addr_size);         break;
212        case DW_FORM_ref1:      m_value.value.uval = data.GetU8(offset_ptr);                            break;
213        case DW_FORM_ref2:      m_value.value.uval = data.GetU16(offset_ptr);                           break;
214        case DW_FORM_ref4:      m_value.value.uval = data.GetU32(offset_ptr);                           break;
215        case DW_FORM_ref8:      m_value.value.uval = data.GetU64(offset_ptr);                           break;
216        case DW_FORM_ref_udata: m_value.value.uval = data.GetULEB128(offset_ptr);                       break;
217        case DW_FORM_indirect:
218            m_form = data.GetULEB128(offset_ptr);
219            indirect = true;
220            break;
221
222        case DW_FORM_sec_offset:    assert(m_cu);
223                                    m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::IsDWARF64(m_cu) ? 8 : 4);  break;
224        case DW_FORM_flag_present:  m_value.value.uval = 1;                                             break;
225        case DW_FORM_ref_sig8:      m_value.value.uval = data.GetU64(offset_ptr);                       break;
226        default:
227            return false;
228            break;
229        }
230    } while (indirect);
231
232    if (is_block)
233    {
234        m_value.data = data.PeekData(*offset_ptr, m_value.value.uval);
235        if (m_value.data != NULL)
236        {
237            *offset_ptr += m_value.value.uval;
238        }
239    }
240
241    return true;
242}
243
244bool
245DWARFFormValue::SkipValue(const DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr) const
246{
247    return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, m_cu);
248}
249
250bool
251DWARFFormValue::SkipValue(dw_form_t form, const DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu)
252{
253    uint8_t ref_addr_size;
254    switch (form)
255    {
256    // Blocks if inlined data that have a length field and the data bytes
257    // inlined in the .debug_info
258    case DW_FORM_exprloc:
259    case DW_FORM_block:  { dw_uleb128_t size = debug_info_data.GetULEB128(offset_ptr); *offset_ptr += size; } return true;
260    case DW_FORM_block1: { dw_uleb128_t size = debug_info_data.GetU8(offset_ptr);      *offset_ptr += size; } return true;
261    case DW_FORM_block2: { dw_uleb128_t size = debug_info_data.GetU16(offset_ptr);     *offset_ptr += size; } return true;
262    case DW_FORM_block4: { dw_uleb128_t size = debug_info_data.GetU32(offset_ptr);     *offset_ptr += size; } return true;
263
264    // Inlined NULL terminated C-strings
265    case DW_FORM_string:
266        debug_info_data.GetCStr(offset_ptr);
267        return true;
268
269    // Compile unit address sized values
270    case DW_FORM_addr:
271        *offset_ptr += DWARFCompileUnit::GetAddressByteSize(cu);
272        return true;
273
274    case DW_FORM_ref_addr:
275        ref_addr_size = 4;
276        assert (cu); // CU must be valid for DW_FORM_ref_addr objects or we will get this wrong
277        if (cu->GetVersion() <= 2)
278            ref_addr_size = cu->GetAddressByteSize();
279        else
280            ref_addr_size = cu->IsDWARF64() ? 8 : 4;
281        *offset_ptr += ref_addr_size;
282        return true;
283
284    // 0 bytes values (implied from DW_FORM)
285    case DW_FORM_flag_present:
286        return true;
287
288    // 1 byte values
289    case DW_FORM_data1:
290    case DW_FORM_flag:
291    case DW_FORM_ref1:
292        *offset_ptr += 1;
293        return true;
294
295    // 2 byte values
296    case DW_FORM_data2:
297    case DW_FORM_ref2:
298        *offset_ptr += 2;
299        return true;
300
301    // 32 bit for DWARF 32, 64 for DWARF 64
302    case DW_FORM_sec_offset:
303    case DW_FORM_strp:
304        assert(cu);
305        *offset_ptr += (cu->IsDWARF64() ? 8 : 4);
306        return true;
307
308    // 4 byte values
309    case DW_FORM_data4:
310    case DW_FORM_ref4:
311        *offset_ptr += 4;
312        return true;
313
314    // 8 byte values
315    case DW_FORM_data8:
316    case DW_FORM_ref8:
317    case DW_FORM_ref_sig8:
318        *offset_ptr += 8;
319        return true;
320
321    // signed or unsigned LEB 128 values
322    case DW_FORM_sdata:
323    case DW_FORM_udata:
324    case DW_FORM_ref_udata:
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 DWARFDataExtractor* debug_str_data) 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(NULL));          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        if (debug_str_data)
399        {
400            if (verbose)
401                s.Printf(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
402
403            const char* dbg_str = AsCString(debug_str_data);
404            if (dbg_str)
405                s.QuotedCString(dbg_str);
406        }
407        else
408        {
409            s.PutHex32(uvalue);
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 DWARFDataExtractor* debug_str_data_ptr) const
448{
449    if (IsInlinedCStr())
450        return m_value.value.cstr;
451    else if (debug_str_data_ptr)
452        return debug_str_data_ptr->PeekCStr(m_value.value.uval);
453    return NULL;
454}
455
456uint64_t
457DWARFFormValue::Reference() const
458{
459    uint64_t die_offset = m_value.value.uval;
460    switch (m_form)
461    {
462    case DW_FORM_ref1:
463    case DW_FORM_ref2:
464    case DW_FORM_ref4:
465    case DW_FORM_ref8:
466    case DW_FORM_ref_udata:
467        assert (m_cu); // CU must be valid for DW_FORM_ref forms that are compile unit relative or we will get this wrong
468        die_offset += m_cu->GetOffset();
469        break;
470
471    default:
472        break;
473    }
474
475    return die_offset;
476}
477
478uint64_t
479DWARFFormValue::Reference (dw_offset_t base_offset) const
480{
481    uint64_t die_offset = m_value.value.uval;
482    switch (m_form)
483    {
484        case DW_FORM_ref1:
485        case DW_FORM_ref2:
486        case DW_FORM_ref4:
487        case DW_FORM_ref8:
488        case DW_FORM_ref_udata:
489            die_offset += base_offset;
490            break;
491
492        default:
493            break;
494    }
495
496    return die_offset;
497}
498
499
500const uint8_t*
501DWARFFormValue::BlockData() const
502{
503    if (!IsInlinedCStr())
504        return m_value.data;
505    return NULL;
506}
507
508
509bool
510DWARFFormValue::IsBlockForm(const dw_form_t form)
511{
512    switch (form)
513    {
514    case DW_FORM_block:
515    case DW_FORM_block1:
516    case DW_FORM_block2:
517    case DW_FORM_block4:
518        return true;
519    }
520    return false;
521}
522
523bool
524DWARFFormValue::IsDataForm(const dw_form_t form)
525{
526    switch (form)
527    {
528    case DW_FORM_sdata:
529    case DW_FORM_udata:
530    case DW_FORM_data1:
531    case DW_FORM_data2:
532    case DW_FORM_data4:
533    case DW_FORM_data8:
534        return true;
535    }
536    return false;
537}
538
539int
540DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_value, const DWARFDataExtractor* debug_str_data_ptr)
541{
542    dw_form_t a_form = a_value.Form();
543    dw_form_t b_form = b_value.Form();
544    if (a_form < b_form)
545        return -1;
546    if (a_form > b_form)
547        return 1;
548    switch (a_form)
549    {
550    case DW_FORM_addr:
551    case DW_FORM_flag:
552    case DW_FORM_data1:
553    case DW_FORM_data2:
554    case DW_FORM_data4:
555    case DW_FORM_data8:
556    case DW_FORM_udata:
557    case DW_FORM_ref_addr:
558    case DW_FORM_sec_offset:
559    case DW_FORM_flag_present:
560    case DW_FORM_ref_sig8:
561        {
562            uint64_t a = a_value.Unsigned();
563            uint64_t b = b_value.Unsigned();
564            if (a < b)
565                return -1;
566            if (a > b)
567                return 1;
568            return 0;
569        }
570
571    case DW_FORM_sdata:
572        {
573            int64_t a = a_value.Signed();
574            int64_t b = b_value.Signed();
575            if (a < b)
576                return -1;
577            if (a > b)
578                return 1;
579            return 0;
580        }
581
582    case DW_FORM_string:
583    case DW_FORM_strp:
584        {
585            const char *a_string = a_value.AsCString(debug_str_data_ptr);
586            const char *b_string = b_value.AsCString(debug_str_data_ptr);
587            if (a_string == b_string)
588                return 0;
589            else if (a_string && b_string)
590                return strcmp(a_string, b_string);
591            else if (a_string == NULL)
592                return -1;  // A string is NULL, and B is valid
593            else
594                return 1;   // A string valid, and B is NULL
595        }
596
597
598    case DW_FORM_block:
599    case DW_FORM_block1:
600    case DW_FORM_block2:
601    case DW_FORM_block4:
602    case DW_FORM_exprloc:
603        {
604            uint64_t a_len = a_value.Unsigned();
605            uint64_t b_len = b_value.Unsigned();
606            if (a_len < b_len)
607                return -1;
608            if (a_len > b_len)
609                return 1;
610            // The block lengths are the same
611            return memcmp(a_value.BlockData(), b_value.BlockData(), a_value.Unsigned());
612        }
613        break;
614
615    case DW_FORM_ref1:
616    case DW_FORM_ref2:
617    case DW_FORM_ref4:
618    case DW_FORM_ref8:
619    case DW_FORM_ref_udata:
620        {
621            uint64_t a = a_value.Reference();
622            uint64_t b = b_value.Reference();
623            if (a < b)
624                return -1;
625            if (a > b)
626                return 1;
627            return 0;
628        }
629
630    case DW_FORM_indirect:
631        assert(!"This shouldn't happen after the form has been extracted...");
632        break;
633
634    default:
635        assert(!"Unhandled DW_FORM");
636        break;
637    }
638    return -1;
639}
640
641