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