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