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
99const uint8_t *
100DWARFFormValue::GetFixedFormSizesForAddressSize (uint8_t addr_size)
101{
102    switch (addr_size)
103    {
104    case 4: return g_form_sizes_addr4;
105    case 8: return g_form_sizes_addr8;
106    }
107    return NULL;
108}
109
110DWARFFormValue::DWARFFormValue(dw_form_t form) :
111    m_form(form),
112    m_value()
113{
114}
115
116bool
117DWARFFormValue::ExtractValue(const DataExtractor& data, lldb::offset_t* offset_ptr, const DWARFCompileUnit* cu)
118{
119    bool indirect = false;
120    bool is_block = false;
121    m_value.data = NULL;
122    // Read the value for the form into value and follow and DW_FORM_indirect instances we run into
123    do
124    {
125        indirect = false;
126        switch (m_form)
127        {
128        case DW_FORM_addr:      m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::GetAddressByteSize(cu));  break;
129        case DW_FORM_block2:    m_value.value.uval = data.GetU16(offset_ptr); is_block = true;          break;
130        case DW_FORM_block4:    m_value.value.uval = data.GetU32(offset_ptr); is_block = true;          break;
131        case DW_FORM_data2:     m_value.value.uval = data.GetU16(offset_ptr);                           break;
132        case DW_FORM_data4:     m_value.value.uval = data.GetU32(offset_ptr);                           break;
133        case DW_FORM_data8:     m_value.value.uval = data.GetU64(offset_ptr);                           break;
134        case DW_FORM_string:    m_value.value.cstr = data.GetCStr(offset_ptr);
135                                // Set the string value to also be the data for inlined cstr form values only
136                                // so we can tell the differnence between DW_FORM_string and DW_FORM_strp form
137                                // values;
138                                m_value.data = (uint8_t*)m_value.value.cstr;                            break;
139        case DW_FORM_exprloc:
140        case DW_FORM_block:     m_value.value.uval = data.GetULEB128(offset_ptr); is_block = true;      break;
141        case DW_FORM_block1:    m_value.value.uval = data.GetU8(offset_ptr); is_block = true;           break;
142        case DW_FORM_data1:     m_value.value.uval = data.GetU8(offset_ptr);                            break;
143        case DW_FORM_flag:      m_value.value.uval = data.GetU8(offset_ptr);                            break;
144        case DW_FORM_sdata:     m_value.value.sval = data.GetSLEB128(offset_ptr);                       break;
145        case DW_FORM_strp:      m_value.value.uval = data.GetU32(offset_ptr);                           break;
146    //  case DW_FORM_APPLE_db_str:
147        case DW_FORM_udata:     m_value.value.uval = data.GetULEB128(offset_ptr);                       break;
148        case DW_FORM_ref_addr:
149            if (cu->GetVersion() <= 2)
150                m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::GetAddressByteSize(cu));
151            else
152                m_value.value.uval = data.GetU32(offset_ptr); // 4 for DWARF32, 8 for DWARF64, but we don't support DWARF64 yet
153            break;
154        case DW_FORM_ref1:      m_value.value.uval = data.GetU8(offset_ptr);                            break;
155        case DW_FORM_ref2:      m_value.value.uval = data.GetU16(offset_ptr);                           break;
156        case DW_FORM_ref4:      m_value.value.uval = data.GetU32(offset_ptr);                           break;
157        case DW_FORM_ref8:      m_value.value.uval = data.GetU64(offset_ptr);                           break;
158        case DW_FORM_ref_udata: m_value.value.uval = data.GetULEB128(offset_ptr);                       break;
159        case DW_FORM_indirect:
160            m_form = data.GetULEB128(offset_ptr);
161            indirect = true;
162            break;
163
164        case DW_FORM_sec_offset:    m_value.value.uval = data.GetU32(offset_ptr);                       break;
165        case DW_FORM_flag_present:  m_value.value.uval = 1;                                             break;
166        case DW_FORM_ref_sig8:      m_value.value.uval = data.GetU64(offset_ptr);                       break;
167        default:
168            return false;
169            break;
170        }
171    } while (indirect);
172
173    if (is_block)
174    {
175        m_value.data = data.PeekData(*offset_ptr, m_value.value.uval);
176        if (m_value.data != NULL)
177        {
178            *offset_ptr += m_value.value.uval;
179        }
180    }
181
182    return true;
183}
184
185bool
186DWARFFormValue::SkipValue(const DataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu) const
187{
188    return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, cu);
189}
190
191bool
192DWARFFormValue::SkipValue(dw_form_t form, const DataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu)
193{
194    switch (form)
195    {
196    // Blocks if inlined data that have a length field and the data bytes
197    // inlined in the .debug_info
198    case DW_FORM_exprloc:
199    case DW_FORM_block:  { dw_uleb128_t size = debug_info_data.GetULEB128(offset_ptr); *offset_ptr += size; } return true;
200    case DW_FORM_block1: { dw_uleb128_t size = debug_info_data.GetU8(offset_ptr);      *offset_ptr += size; } return true;
201    case DW_FORM_block2: { dw_uleb128_t size = debug_info_data.GetU16(offset_ptr);     *offset_ptr += size; } return true;
202    case DW_FORM_block4: { dw_uleb128_t size = debug_info_data.GetU32(offset_ptr);     *offset_ptr += size; } return true;
203
204    // Inlined NULL terminated C-strings
205    case DW_FORM_string:
206        debug_info_data.GetCStr(offset_ptr);
207        return true;
208
209    // Compile unit address sized values
210    case DW_FORM_addr:
211        *offset_ptr += DWARFCompileUnit::GetAddressByteSize(cu);
212        return true;
213
214    case DW_FORM_ref_addr:
215        if (cu->GetVersion() <= 2)
216            *offset_ptr += DWARFCompileUnit::GetAddressByteSize(cu);
217        else
218            *offset_ptr += 4;// 4 for DWARF32, 8 for DWARF64, but we don't support DWARF64 yet
219        return true;
220
221    // 0 bytes values (implied from DW_FORM)
222    case DW_FORM_flag_present:
223        return true;
224
225    // 1 byte values
226    case DW_FORM_data1:
227    case DW_FORM_flag:
228    case DW_FORM_ref1:
229        *offset_ptr += 1;
230        return true;
231
232    // 2 byte values
233    case DW_FORM_data2:
234    case DW_FORM_ref2:
235        *offset_ptr += 2;
236        return true;
237
238    // 32 bit for DWARF 32, 64 for DWARF 64
239    case DW_FORM_sec_offset:
240        *offset_ptr += 4;
241        return true;
242
243    // 4 byte values
244    case DW_FORM_strp:
245    case DW_FORM_data4:
246    case DW_FORM_ref4:
247        *offset_ptr += 4;
248        return true;
249
250    // 8 byte values
251    case DW_FORM_data8:
252    case DW_FORM_ref8:
253    case DW_FORM_ref_sig8:
254        *offset_ptr += 8;
255        return true;
256
257    // signed or unsigned LEB 128 values
258    case DW_FORM_sdata:
259    case DW_FORM_udata:
260    case DW_FORM_ref_udata:
261        debug_info_data.Skip_LEB128(offset_ptr);
262        return true;
263
264    case DW_FORM_indirect:
265        {
266            dw_form_t indirect_form = debug_info_data.GetULEB128(offset_ptr);
267            return DWARFFormValue::SkipValue (indirect_form,
268                                              debug_info_data,
269                                              offset_ptr,
270                                              cu);
271        }
272
273    default:
274        break;
275    }
276    return false;
277}
278
279
280void
281DWARFFormValue::Dump(Stream &s, const DataExtractor* debug_str_data, const DWARFCompileUnit* cu) const
282{
283    uint64_t uvalue = Unsigned();
284    bool cu_relative_offset = false;
285
286    bool verbose = s.GetVerbose();
287
288    switch (m_form)
289    {
290    case DW_FORM_addr:      s.Address(uvalue, sizeof (uint64_t)); break;
291    case DW_FORM_flag:
292    case DW_FORM_data1:     s.PutHex8(uvalue);     break;
293    case DW_FORM_data2:     s.PutHex16(uvalue);        break;
294    case DW_FORM_sec_offset:
295    case DW_FORM_data4:     s.PutHex32(uvalue);        break;
296    case DW_FORM_ref_sig8:
297    case DW_FORM_data8:     s.PutHex64(uvalue);        break;
298    case DW_FORM_string:    s.QuotedCString(AsCString(NULL));          break;
299    case DW_FORM_exprloc:
300    case DW_FORM_block:
301    case DW_FORM_block1:
302    case DW_FORM_block2:
303    case DW_FORM_block4:
304        if (uvalue > 0)
305        {
306            switch (m_form)
307            {
308            case DW_FORM_exprloc:
309            case DW_FORM_block:  s.Printf("<0x%" PRIx64 "> ", uvalue);                break;
310            case DW_FORM_block1: s.Printf("<0x%2.2x> ", (uint8_t)uvalue);      break;
311            case DW_FORM_block2: s.Printf("<0x%4.4x> ", (uint16_t)uvalue);     break;
312            case DW_FORM_block4: s.Printf("<0x%8.8x> ", (uint32_t)uvalue);     break;
313            default:                                                            break;
314            }
315
316            const uint8_t* data_ptr = m_value.data;
317            if (data_ptr)
318            {
319                const uint8_t* end_data_ptr = data_ptr + uvalue;    // uvalue contains size of block
320                while (data_ptr < end_data_ptr)
321                {
322                    s.Printf("%2.2x ", *data_ptr);
323                    ++data_ptr;
324                }
325            }
326            else
327                s.PutCString("NULL");
328        }
329        break;
330
331    case DW_FORM_sdata:     s.PutSLEB128(uvalue); break;
332    case DW_FORM_udata:     s.PutULEB128(uvalue); break;
333    case DW_FORM_strp:
334        if (debug_str_data)
335        {
336            if (verbose)
337                s.Printf(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
338
339            const char* dbg_str = AsCString(debug_str_data);
340            if (dbg_str)
341                s.QuotedCString(dbg_str);
342        }
343        else
344        {
345            s.PutHex32(uvalue);
346        }
347        break;
348
349    case DW_FORM_ref_addr:
350    {
351        if (cu->GetVersion() <= 2)
352            s.Address(uvalue, sizeof (uint64_t) * 2);
353        else
354            s.Address(uvalue, 4 * 2);// 4 for DWARF32, 8 for DWARF64, but we don't support DWARF64 yet
355        break;
356    }
357    case DW_FORM_ref1:      cu_relative_offset = true;  if (verbose) s.Printf("cu + 0x%2.2x", (uint8_t)uvalue); break;
358    case DW_FORM_ref2:      cu_relative_offset = true;  if (verbose) s.Printf("cu + 0x%4.4x", (uint16_t)uvalue); break;
359    case DW_FORM_ref4:      cu_relative_offset = true;  if (verbose) s.Printf("cu + 0x%4.4x", (uint32_t)uvalue); break;
360    case DW_FORM_ref8:      cu_relative_offset = true;  if (verbose) s.Printf("cu + 0x%8.8" PRIx64, uvalue); break;
361    case DW_FORM_ref_udata: cu_relative_offset = true;  if (verbose) s.Printf("cu + 0x%" PRIx64, uvalue); break;
362
363    // All DW_FORM_indirect attributes should be resolved prior to calling this function
364    case DW_FORM_indirect:  s.PutCString("DW_FORM_indirect"); break;
365    case DW_FORM_flag_present: break;
366    default:
367        s.Printf("DW_FORM(0x%4.4x)", m_form);
368        break;
369    }
370
371    if (cu_relative_offset)
372    {
373        if (verbose)
374            s.PutCString(" => ");
375
376        s.Printf("{0x%8.8" PRIx64 "}", (uvalue + (cu ? cu->GetOffset() : 0)));
377    }
378}
379
380const char*
381DWARFFormValue::AsCString(const DataExtractor* debug_str_data_ptr) const
382{
383    if (IsInlinedCStr())
384        return m_value.value.cstr;
385    else if (debug_str_data_ptr)
386        return debug_str_data_ptr->PeekCStr(m_value.value.uval);
387    return NULL;
388}
389
390uint64_t
391DWARFFormValue::Reference(const DWARFCompileUnit* cu) const
392{
393    uint64_t die_offset = m_value.value.uval;
394    switch (m_form)
395    {
396    case DW_FORM_ref1:
397    case DW_FORM_ref2:
398    case DW_FORM_ref4:
399    case DW_FORM_ref8:
400    case DW_FORM_ref_udata:
401        die_offset += (cu ? cu->GetOffset() : 0);
402        break;
403
404    default:
405        break;
406    }
407
408    return die_offset;
409}
410
411uint64_t
412DWARFFormValue::Reference (dw_offset_t base_offset) const
413{
414    uint64_t die_offset = m_value.value.uval;
415    switch (m_form)
416    {
417        case DW_FORM_ref1:
418        case DW_FORM_ref2:
419        case DW_FORM_ref4:
420        case DW_FORM_ref8:
421        case DW_FORM_ref_udata:
422            die_offset += base_offset;
423            break;
424
425        default:
426            break;
427    }
428
429    return die_offset;
430}
431
432//----------------------------------------------------------------------
433// Resolve any compile unit specific references so that we don't need
434// the compile unit at a later time in order to work with the form
435// value.
436//----------------------------------------------------------------------
437bool
438DWARFFormValue::ResolveCompileUnitReferences(const DWARFCompileUnit* cu)
439{
440    switch (m_form)
441    {
442    case DW_FORM_ref1:
443    case DW_FORM_ref2:
444    case DW_FORM_ref4:
445    case DW_FORM_ref8:
446    case DW_FORM_ref_udata:
447        m_value.value.uval += cu->GetOffset();
448        m_form = DW_FORM_ref_addr;
449        return true;
450        break;
451
452    default:
453        break;
454    }
455
456    return false;
457}
458
459const uint8_t*
460DWARFFormValue::BlockData() const
461{
462    if (!IsInlinedCStr())
463        return m_value.data;
464    return NULL;
465}
466
467
468bool
469DWARFFormValue::IsBlockForm(const dw_form_t form)
470{
471    switch (form)
472    {
473    case DW_FORM_block:
474    case DW_FORM_block1:
475    case DW_FORM_block2:
476    case DW_FORM_block4:
477        return true;
478    }
479    return false;
480}
481
482bool
483DWARFFormValue::IsDataForm(const dw_form_t form)
484{
485    switch (form)
486    {
487    case DW_FORM_sdata:
488    case DW_FORM_udata:
489    case DW_FORM_data1:
490    case DW_FORM_data2:
491    case DW_FORM_data4:
492    case DW_FORM_data8:
493        return true;
494    }
495    return false;
496}
497
498int
499DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_value, const DWARFCompileUnit* a_cu, const DWARFCompileUnit* b_cu, const DataExtractor* debug_str_data_ptr)
500{
501    dw_form_t a_form = a_value.Form();
502    dw_form_t b_form = b_value.Form();
503    if (a_form < b_form)
504        return -1;
505    if (a_form > b_form)
506        return 1;
507    switch (a_form)
508    {
509    case DW_FORM_addr:
510    case DW_FORM_flag:
511    case DW_FORM_data1:
512    case DW_FORM_data2:
513    case DW_FORM_data4:
514    case DW_FORM_data8:
515    case DW_FORM_udata:
516    case DW_FORM_ref_addr:
517    case DW_FORM_sec_offset:
518    case DW_FORM_flag_present:
519    case DW_FORM_ref_sig8:
520        {
521            uint64_t a = a_value.Unsigned();
522            uint64_t b = b_value.Unsigned();
523            if (a < b)
524                return -1;
525            if (a > b)
526                return 1;
527            return 0;
528        }
529
530    case DW_FORM_sdata:
531        {
532            int64_t a = a_value.Signed();
533            int64_t b = b_value.Signed();
534            if (a < b)
535                return -1;
536            if (a > b)
537                return 1;
538            return 0;
539        }
540
541    case DW_FORM_string:
542    case DW_FORM_strp:
543        {
544            const char *a_string = a_value.AsCString(debug_str_data_ptr);
545            const char *b_string = b_value.AsCString(debug_str_data_ptr);
546            if (a_string == b_string)
547                return 0;
548            else if (a_string && b_string)
549                return strcmp(a_string, b_string);
550            else if (a_string == NULL)
551                return -1;  // A string is NULL, and B is valid
552            else
553                return 1;   // A string valid, and B is NULL
554        }
555
556
557    case DW_FORM_block:
558    case DW_FORM_block1:
559    case DW_FORM_block2:
560    case DW_FORM_block4:
561    case DW_FORM_exprloc:
562        {
563            uint64_t a_len = a_value.Unsigned();
564            uint64_t b_len = b_value.Unsigned();
565            if (a_len < b_len)
566                return -1;
567            if (a_len > b_len)
568                return 1;
569            // The block lengths are the same
570            return memcmp(a_value.BlockData(), b_value.BlockData(), a_value.Unsigned());
571        }
572        break;
573
574    case DW_FORM_ref1:
575    case DW_FORM_ref2:
576    case DW_FORM_ref4:
577    case DW_FORM_ref8:
578    case DW_FORM_ref_udata:
579        {
580            uint64_t a = a_value.Reference(a_cu);
581            uint64_t b = b_value.Reference(b_cu);
582            if (a < b)
583                return -1;
584            if (a > b)
585                return 1;
586            return 0;
587        }
588
589    case DW_FORM_indirect:
590        assert(!"This shouldn't happen after the form has been extracted...");
591        break;
592
593    default:
594        assert(!"Unhandled DW_FORM");
595        break;
596    }
597    return -1;
598}
599
600